diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1997-06-11 15:56:02 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1997-06-11 15:56:02 -0300 |
commit | 33f4fef4101f4c834516ad3be9869d90182559c4 (patch) | |
tree | 7641515cb8309276bd494f2b1ccc3bddcb6c7c8b | |
parent | e77534c08f6470c01ee8be2b609422ef0834463b (diff) | |
download | lua-33f4fef4101f4c834516ad3be9869d90182559c4.tar.gz lua-33f4fef4101f4c834516ad3be9869d90182559c4.tar.bz2 lua-33f4fef4101f4c834516ad3be9869d90182559c4.zip |
BUG: did not handle properly pragmas $endinput/$debug inside a $if.
-rw-r--r-- | lex.c | 80 |
1 files changed, 44 insertions, 36 deletions
@@ -1,4 +1,4 @@ | |||
1 | char *rcs_lex = "$Id: lex.c,v 3.2 1997/04/14 15:30:29 roberto Exp roberto $"; | 1 | char *rcs_lex = "$Id: lex.c,v 3.4 1997/06/11 14:20:51 roberto Exp $"; |
2 | 2 | ||
3 | 3 | ||
4 | #include <ctype.h> | 4 | #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 $"; | |||
23 | static int current; /* look ahead character */ | 23 | static int current; /* look ahead character */ |
24 | static Input input; /* input function */ | 24 | static Input input; /* input function */ |
25 | 25 | ||
26 | #define MAX_IFS 10 | ||
27 | 26 | ||
28 | /* "ifstate" keeps the state of each nested $if the lexical is | 27 | #define MAX_IFS 5 |
29 | ** dealing with. The first bit indicates whether the $if condition | 28 | |
30 | ** is false or true. The second bit indicates whether the lexical is | 29 | /* "ifstate" keeps the state of each nested $if the lexical is dealing with. */ |
31 | ** inside the "then" part (0) or the "else" part (2) | 30 | |
32 | */ | 31 | static struct { |
33 | static int ifstate[MAX_IFS]; /* 0 => then part - condition false */ | 32 | int elsepart; /* true if its in the $else part */ |
34 | /* 1 => then part - condition true */ | 33 | int condition; /* true if $if condition is true */ |
35 | /* 2 => else part - condition false */ | 34 | int skip; /* true if part must be skiped */ |
36 | /* 3 => else part - condition true */ | 35 | } ifstate[MAX_IFS]; |
36 | |||
37 | static int iflevel; /* level of nested $if's */ | 37 | static int iflevel; /* level of nested $if's */ |
38 | 38 | ||
39 | 39 | ||
@@ -42,6 +42,8 @@ void lua_setinput (Input fn) | |||
42 | current = '\n'; | 42 | current = '\n'; |
43 | lua_linenumber = 0; | 43 | lua_linenumber = 0; |
44 | iflevel = 0; | 44 | iflevel = 0; |
45 | ifstate[0].skip = 0; | ||
46 | ifstate[0].elsepart = 1; /* to avoid a free $else */ | ||
45 | input = fn; | 47 | input = fn; |
46 | } | 48 | } |
47 | 49 | ||
@@ -117,10 +119,9 @@ static void skipspace (void) | |||
117 | 119 | ||
118 | static int checkcond (char *buff) | 120 | static int checkcond (char *buff) |
119 | { | 121 | { |
120 | if (strcmp(buff, "nil") == 0) | 122 | static char *opts[] = {"nil", "1"}; |
121 | return 0; | 123 | int i = luaI_findstring(buff, opts); |
122 | else if (strcmp(buff, "1") == 0) | 124 | if (i >= 0) return i; |
123 | return 1; | ||
124 | else if (isalpha((unsigned char)buff[0]) || buff[0] == '_') | 125 | else if (isalpha((unsigned char)buff[0]) || buff[0] == '_') |
125 | return luaI_globaldefined(buff); | 126 | return luaI_globaldefined(buff); |
126 | else { | 127 | else { |
@@ -149,11 +150,9 @@ static void readname (char *buff) | |||
149 | static void inclinenumber (void); | 150 | static void inclinenumber (void); |
150 | 151 | ||
151 | 152 | ||
152 | static void ifskip (int thisiflevel) | 153 | static void ifskip (void) |
153 | { | 154 | { |
154 | if (thisiflevel < 0) return; | 155 | while (ifstate[iflevel].skip) { |
155 | while (iflevel > thisiflevel && | ||
156 | (ifstate[thisiflevel] == 0 || ifstate[thisiflevel] == 3)) { | ||
157 | if (current == '\n') | 156 | if (current == '\n') |
158 | inclinenumber(); | 157 | inclinenumber(); |
159 | else if (current == 0) | 158 | else if (current == 0) |
@@ -166,51 +165,60 @@ static void ifskip (int thisiflevel) | |||
166 | static void inclinenumber (void) | 165 | static void inclinenumber (void) |
167 | { | 166 | { |
168 | static char *pragmas [] = | 167 | static char *pragmas [] = |
169 | {"debug", "nodebug", "end", "ifnot", "if", "else", "endinput", NULL}; | 168 | {"debug", "nodebug", "endinput", "end", "ifnot", "if", "else", NULL}; |
170 | next(); /* skip '\n' */ | 169 | next(); /* skip '\n' */ |
171 | ++lua_linenumber; | 170 | ++lua_linenumber; |
172 | if (current == '$') { /* is a pragma? */ | 171 | if (current == '$') { /* is a pragma? */ |
173 | char buff[PRAGMASIZE+1]; | 172 | char buff[PRAGMASIZE+1]; |
174 | int ifnot = 0; | 173 | int ifnot = 0; |
174 | int skip = ifstate[iflevel].skip; | ||
175 | next(); /* skip $ */ | 175 | next(); /* skip $ */ |
176 | readname(buff); | 176 | readname(buff); |
177 | switch (luaI_findstring(buff, pragmas)) { | 177 | switch (luaI_findstring(buff, pragmas)) { |
178 | case 0: /* debug */ | 178 | case 0: /* debug */ |
179 | lua_debug = 1; | 179 | if (!skip) lua_debug = 1; |
180 | break; | 180 | break; |
181 | case 1: /* nodebug */ | 181 | case 1: /* nodebug */ |
182 | lua_debug = 0; | 182 | if (!skip) lua_debug = 0; |
183 | break; | 183 | break; |
184 | case 2: /* end */ | 184 | case 2: /* endinput */ |
185 | if (--iflevel < 0) | 185 | if (!skip) { |
186 | current = 0; | ||
187 | iflevel = 0; /* to allow $endinput inside a $if */ | ||
188 | } | ||
189 | break; | ||
190 | case 3: /* end */ | ||
191 | if (iflevel-- == 0) | ||
186 | luaI_auxsyntaxerror("unmatched $endif"); | 192 | luaI_auxsyntaxerror("unmatched $endif"); |
187 | break; | 193 | break; |
188 | case 3: /* ifnot */ | 194 | case 4: /* ifnot */ |
189 | ifnot = 1; | 195 | ifnot = 1; |
190 | /* go through */ | 196 | /* go through */ |
191 | case 4: /* if */ | 197 | case 5: /* if */ |
192 | if (iflevel == MAX_IFS) | 198 | if (iflevel == MAX_IFS-1) |
193 | luaI_auxsyntaxerror("too many nested `$ifs'"); | 199 | luaI_auxsyntaxerror("too many nested `$ifs'"); |
194 | readname(buff); | 200 | readname(buff); |
195 | ifstate[iflevel++] = checkcond(buff) ? !ifnot : ifnot; | 201 | iflevel++; |
202 | ifstate[iflevel].elsepart = 0; | ||
203 | ifstate[iflevel].condition = checkcond(buff) ? !ifnot : ifnot; | ||
204 | ifstate[iflevel].skip = skip || !ifstate[iflevel].condition; | ||
196 | break; | 205 | break; |
197 | case 5: /* else */ | 206 | case 6: /* else */ |
198 | if (iflevel <= 0 || (ifstate[iflevel-1] & 2)) | 207 | if (ifstate[iflevel].elsepart) |
199 | luaI_auxsyntaxerror("unmatched $else"); | 208 | luaI_auxsyntaxerror("unmatched $else"); |
200 | ifstate[iflevel-1] = ifstate[iflevel-1] | 2; | 209 | ifstate[iflevel].elsepart = 1; |
201 | break; | 210 | ifstate[iflevel].skip = |
202 | case 6: /* endinput */ | 211 | ifstate[iflevel-1].skip || ifstate[iflevel].condition; |
203 | current = 0; | ||
204 | break; | 212 | break; |
205 | default: | 213 | default: |
206 | luaI_auxsynterrbf("invalid pragma", buff); | 214 | luaI_auxsynterrbf("invalid pragma", buff); |
207 | } | 215 | } |
208 | skipspace(); | 216 | skipspace(); |
209 | if (current == '\n') /* pragma must end with a '\n' */ | 217 | if (current == '\n') /* pragma must end with a '\n' ... */ |
210 | inclinenumber(); | 218 | inclinenumber(); |
211 | else if (current != 0) /* or eof */ | 219 | else if (current != 0) /* or eof */ |
212 | luaI_auxsyntaxerror("invalid pragma format"); | 220 | luaI_auxsyntaxerror("invalid pragma format"); |
213 | ifskip(iflevel-1); | 221 | ifskip(); |
214 | } | 222 | } |
215 | } | 223 | } |
216 | 224 | ||