BUG: did not handle properly pragmas $endinput/$debug inside a $if.

This commit is contained in:
Roberto Ierusalimschy 1997-06-11 15:56:02 -03:00
parent e77534c08f
commit 33f4fef410
1 changed files with 44 additions and 36 deletions

80
lex.c
View File

@ -1,4 +1,4 @@
char *rcs_lex = "$Id: lex.c,v 3.2 1997/04/14 15:30:29 roberto Exp roberto $"; char *rcs_lex = "$Id: lex.c,v 3.4 1997/06/11 14:20:51 roberto Exp $";
#include <ctype.h> #include <ctype.h>
@ -23,17 +23,17 @@ char *rcs_lex = "$Id: lex.c,v 3.2 1997/04/14 15:30:29 roberto Exp roberto $";
static int current; /* look ahead character */ static int current; /* look ahead character */
static Input input; /* input function */ static Input input; /* input function */
#define MAX_IFS 10
/* "ifstate" keeps the state of each nested $if the lexical is #define MAX_IFS 5
** dealing with. The first bit indicates whether the $if condition
** is false or true. The second bit indicates whether the lexical is /* "ifstate" keeps the state of each nested $if the lexical is dealing with. */
** inside the "then" part (0) or the "else" part (2)
*/ static struct {
static int ifstate[MAX_IFS]; /* 0 => then part - condition false */ int elsepart; /* true if its in the $else part */
/* 1 => then part - condition true */ int condition; /* true if $if condition is true */
/* 2 => else part - condition false */ int skip; /* true if part must be skiped */
/* 3 => else part - condition true */ } ifstate[MAX_IFS];
static int iflevel; /* level of nested $if's */ static int iflevel; /* level of nested $if's */
@ -42,6 +42,8 @@ void lua_setinput (Input fn)
current = '\n'; current = '\n';
lua_linenumber = 0; lua_linenumber = 0;
iflevel = 0; iflevel = 0;
ifstate[0].skip = 0;
ifstate[0].elsepart = 1; /* to avoid a free $else */
input = fn; input = fn;
} }
@ -117,10 +119,9 @@ static void skipspace (void)
static int checkcond (char *buff) static int checkcond (char *buff)
{ {
if (strcmp(buff, "nil") == 0) static char *opts[] = {"nil", "1"};
return 0; int i = luaI_findstring(buff, opts);
else if (strcmp(buff, "1") == 0) if (i >= 0) return i;
return 1;
else if (isalpha((unsigned char)buff[0]) || buff[0] == '_') else if (isalpha((unsigned char)buff[0]) || buff[0] == '_')
return luaI_globaldefined(buff); return luaI_globaldefined(buff);
else { else {
@ -149,11 +150,9 @@ static void readname (char *buff)
static void inclinenumber (void); static void inclinenumber (void);
static void ifskip (int thisiflevel) static void ifskip (void)
{ {
if (thisiflevel < 0) return; while (ifstate[iflevel].skip) {
while (iflevel > thisiflevel &&
(ifstate[thisiflevel] == 0 || ifstate[thisiflevel] == 3)) {
if (current == '\n') if (current == '\n')
inclinenumber(); inclinenumber();
else if (current == 0) else if (current == 0)
@ -166,51 +165,60 @@ static void ifskip (int thisiflevel)
static void inclinenumber (void) static void inclinenumber (void)
{ {
static char *pragmas [] = static char *pragmas [] =
{"debug", "nodebug", "end", "ifnot", "if", "else", "endinput", NULL}; {"debug", "nodebug", "endinput", "end", "ifnot", "if", "else", NULL};
next(); /* skip '\n' */ next(); /* skip '\n' */
++lua_linenumber; ++lua_linenumber;
if (current == '$') { /* is a pragma? */ if (current == '$') { /* is a pragma? */
char buff[PRAGMASIZE+1]; char buff[PRAGMASIZE+1];
int ifnot = 0; int ifnot = 0;
int skip = ifstate[iflevel].skip;
next(); /* skip $ */ next(); /* skip $ */
readname(buff); readname(buff);
switch (luaI_findstring(buff, pragmas)) { switch (luaI_findstring(buff, pragmas)) {
case 0: /* debug */ case 0: /* debug */
lua_debug = 1; if (!skip) lua_debug = 1;
break; break;
case 1: /* nodebug */ case 1: /* nodebug */
lua_debug = 0; if (!skip) lua_debug = 0;
break; break;
case 2: /* end */ case 2: /* endinput */
if (--iflevel < 0) if (!skip) {
current = 0;
iflevel = 0; /* to allow $endinput inside a $if */
}
break;
case 3: /* end */
if (iflevel-- == 0)
luaI_auxsyntaxerror("unmatched $endif"); luaI_auxsyntaxerror("unmatched $endif");
break; break;
case 3: /* ifnot */ case 4: /* ifnot */
ifnot = 1; ifnot = 1;
/* go through */ /* go through */
case 4: /* if */ case 5: /* if */
if (iflevel == MAX_IFS) if (iflevel == MAX_IFS-1)
luaI_auxsyntaxerror("too many nested `$ifs'"); luaI_auxsyntaxerror("too many nested `$ifs'");
readname(buff); readname(buff);
ifstate[iflevel++] = checkcond(buff) ? !ifnot : ifnot; iflevel++;
ifstate[iflevel].elsepart = 0;
ifstate[iflevel].condition = checkcond(buff) ? !ifnot : ifnot;
ifstate[iflevel].skip = skip || !ifstate[iflevel].condition;
break; break;
case 5: /* else */ case 6: /* else */
if (iflevel <= 0 || (ifstate[iflevel-1] & 2)) if (ifstate[iflevel].elsepart)
luaI_auxsyntaxerror("unmatched $else"); luaI_auxsyntaxerror("unmatched $else");
ifstate[iflevel-1] = ifstate[iflevel-1] | 2; ifstate[iflevel].elsepart = 1;
break; ifstate[iflevel].skip =
case 6: /* endinput */ ifstate[iflevel-1].skip || ifstate[iflevel].condition;
current = 0;
break; break;
default: default:
luaI_auxsynterrbf("invalid pragma", buff); luaI_auxsynterrbf("invalid pragma", buff);
} }
skipspace(); skipspace();
if (current == '\n') /* pragma must end with a '\n' */ if (current == '\n') /* pragma must end with a '\n' ... */
inclinenumber(); inclinenumber();
else if (current != 0) /* or eof */ else if (current != 0) /* or eof */
luaI_auxsyntaxerror("invalid pragma format"); luaI_auxsyntaxerror("invalid pragma format");
ifskip(iflevel-1); ifskip();
} }
} }