Skip to content

Commit 06258fb

Browse files
authored
macro functions
1 parent 5492571 commit 06258fb

File tree

1 file changed

+134
-2
lines changed

1 file changed

+134
-2
lines changed

lua514u/src/llex.c

Lines changed: 134 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "lstring.h"
2323
#include "ltable.h"
2424
#include "lzio.h"
25+
#include "lauxlib.h"
2526

2627

2728
#define next(ls) (ls->current = ls->mpos < ls->mlen ? char2int(ls->mstr[ls->mpos++]) : zgetc(ls->z))
@@ -483,6 +484,31 @@ static int llex (LexState *ls, SemInfo *seminfo) {
483484
char q = ls->current;
484485
switch (q)
485486
{
487+
case '(':
488+
{
489+
next(ls);
490+
q = ls->current;
491+
next(ls);
492+
for(;;) {
493+
if (ls->current == q) {
494+
next(ls);
495+
if (ls->current == ')') {
496+
next(ls); break;
497+
} else {
498+
save(ls, q);
499+
save_and_next(ls);
500+
}
501+
} else if (ls->current == EOZ)
502+
luaX_lexerror(ls, "unfinished macro function definition", 0);
503+
else if (ls->current == '\n') {
504+
++ls->linenumber;
505+
save_and_next(ls);
506+
}
507+
else save_and_next(ls);
508+
}
509+
q = '(';
510+
break;
511+
}
486512
case '\'':
487513
case '"':
488514
{
@@ -491,8 +517,13 @@ static int llex (LexState *ls, SemInfo *seminfo) {
491517
{
492518
if (ls->current == EOZ)
493519
luaX_lexerror(ls, "unfinished string at macro definition", 0);
494-
if (ls->current == '\n')
520+
else if (ls->current == '\n')
495521
luaX_lexerror(ls, "unfinished string at macro definition", TK_STRING);
522+
else if (ls->current == '\\') {
523+
save_and_next(ls);
524+
if (ls->current == EOZ)
525+
luaX_lexerror(ls, "unfinished string at macro definition", TK_STRING);
526+
}
496527
save_and_next(ls);
497528
}
498529
save_and_next(ls);
@@ -538,7 +569,12 @@ static int llex (LexState *ls, SemInfo *seminfo) {
538569
case '-': case '0': case '1': case '2': case '3': case '4':
539570
case '.': case '5': case '6': case '7': case '8': case '9':
540571
{
541-
while (!isspace(ls->current) && ls->current != EOZ) save_and_next(ls);
572+
if (q == '-') {
573+
save_and_next(ls);
574+
if (!isdigit(ls->current) && ls->current != '.')
575+
luaX_lexerror(ls, "invalid number at macro definition", 0);
576+
}
577+
while (isalnum(ls->current) || ls->current == '.') save_and_next(ls);
542578
break;
543579
}
544580
case '`': case '~': case '!': case '#': case '$': case '%': case '^':
@@ -570,6 +606,12 @@ static int llex (LexState *ls, SemInfo *seminfo) {
570606
if(val) strcpy(val, ls->buff->buffer);
571607
lua_pushstring(L, val);
572608
luaZ_resetbuffer(ls->buff);
609+
if (q == '(') {
610+
if (luaL_loadstring(L, val))
611+
luaX_lexerror(ls, lua_tostring(L, -1), 0);
612+
else
613+
lua_remove(L, -2);
614+
}
573615
lua_rawset(L, -3);
574616
lua_setglobal(L, MACRO);
575617
free(key);
@@ -584,6 +626,96 @@ static int llex (LexState *ls, SemInfo *seminfo) {
584626
save(ls, '\0');
585627
char *k = ls->buff->buffer;
586628
lua_getfield(L, -1, k);
629+
630+
if (lua_isfunction(L, -1)) {
631+
lua_newtable(L);
632+
lua_pushstring(L,getstr(ls->source));
633+
lua_rawseti(L,-2,0);
634+
if (ls->current != '(')
635+
luaX_lexerror(ls, "invalid macro function call", 0);
636+
int parens = 1;
637+
next(ls);
638+
int t, i;
639+
for (i = 1; ;i++) {
640+
t = llex(ls, seminfo);
641+
if (t == ')' && --parens == 0) break;
642+
else if (t == '(') ++parens;
643+
switch (t)
644+
{
645+
case TK_EOS: case EOZ:
646+
luaX_lexerror(ls, "unfinished macro function call", 0);
647+
case TK_STRING:
648+
{
649+
const char *str = getstr(seminfo->ts);
650+
TString *ts = seminfo->ts;
651+
size_t len = ts->tsv.len;
652+
char *res = (char *) malloc(4 * len + 2);
653+
res[0] = '"';
654+
size_t j = 0;
655+
size_t i;
656+
for (i = 0; i < len; i++) {
657+
switch (str[i])
658+
{
659+
case '\a': res[++j] = '\\'; res[++j] = 'a'; break;
660+
case '\b': res[++j] = '\\'; res[++j] = 'b'; break;
661+
case '\f': res[++j] = '\\'; res[++j] = 'f'; break;
662+
case '\t': res[++j] = '\\'; res[++j] = 't'; break;
663+
case '\v': res[++j] = '\\'; res[++j] = 'v'; break;
664+
case '\n': res[++j] = '\\'; res[++j] = 'n'; break;
665+
case '\r': res[++j] = '\\'; res[++j] = 'r'; break;
666+
case '"': res[++j] = '\\'; res[++j] = '"'; break;
667+
case '\0':
668+
res[++j] = '\\';
669+
res[++j] = '0';
670+
res[++j] = '0';
671+
res[++j] = '0';
672+
break;
673+
default:
674+
res[++j] = str[i];
675+
break;
676+
}
677+
}
678+
res[++j] = '"';
679+
res[++j] = '\0';
680+
lua_pushstring(L, res);
681+
free(res);
682+
break;
683+
}
684+
case TK_NAME:
685+
lua_pushstring(L,getstr(seminfo->ts));
686+
break;
687+
case TK_NUMBER:
688+
{
689+
const char *str = ls->buff->buffer;
690+
if (str[0] == '0') lua_pushstring(L,str);
691+
else {
692+
char *res = (char *) malloc(strlen(str) + 1);
693+
res[0] = '\0';
694+
strcat(res, "0");
695+
strcat(res, str);
696+
lua_pushstring(L,res);
697+
}
698+
break;
699+
}
700+
default:
701+
if (t<FIRST_RESERVED)
702+
{
703+
char s[2]= {t,0};
704+
lua_pushstring(L,s);
705+
}
706+
else
707+
lua_pushstring(L,luaX_tokens[t-FIRST_RESERVED]);
708+
break;
709+
}
710+
lua_rawseti(L,-2,i);
711+
}
712+
lua_call(L,1,1);
713+
if (!lua_isstring(L, -1))
714+
luaX_lexerror(ls, "macro function call should return string", 0);
715+
lua_pushstring(L, " ");
716+
lua_concat(L, 2);
717+
}
718+
587719
if (lua_isstring(L, -1)) {
588720
luaZ_resetbuffer(ls->buff);
589721
const char *s = lua_tostring(L, -1);

0 commit comments

Comments
 (0)