19 #include <libtu/misc.h> |
19 #include <libtu/misc.h> |
20 #include <libtu/output.h> |
20 #include <libtu/output.h> |
21 |
21 |
22 |
22 |
23 static const char *errors[]={ |
23 static const char *errors[]={ |
24 DUMMY_TR("(no error)"), |
24 DUMMY_TR("(no error)"), |
25 DUMMY_TR("Unexpected end of file"), /* E_TOKZ_UNEXPECTED_EOF */ |
25 DUMMY_TR("Unexpected end of file"), /* E_TOKZ_UNEXPECTED_EOF */ |
26 DUMMY_TR("Unexpected end of line"), /* E_TOKZ_UNEXPECTED_EOL */ |
26 DUMMY_TR("Unexpected end of line"), /* E_TOKZ_UNEXPECTED_EOL */ |
27 DUMMY_TR("End of line expected"), /* E_TOKZ_EOL_EXPECTED */ |
27 DUMMY_TR("End of line expected"), /* E_TOKZ_EOL_EXPECTED */ |
28 DUMMY_TR("Invalid character"), /* E_TOKZ_INVALID_CHAR*/ |
28 DUMMY_TR("Invalid character"), /* E_TOKZ_INVALID_CHAR*/ |
29 DUMMY_TR("Numeric constant too big"), /* E_TOKZ_TOOBIG */ |
29 DUMMY_TR("Numeric constant too big"), /* E_TOKZ_TOOBIG */ |
30 DUMMY_TR("Invalid numberic format"), /* E_TOKZ_NUMFMT */ |
30 DUMMY_TR("Invalid numberic format"), /* E_TOKZ_NUMFMT */ |
31 DUMMY_TR("Junk after numeric constant"), /* E_TOKZ_NUM_JUNK */ |
31 DUMMY_TR("Junk after numeric constant"), /* E_TOKZ_NUM_JUNK */ |
32 DUMMY_TR("Not an integer"), /* E_TOKZ_NOTINT */ |
32 DUMMY_TR("Not an integer"), /* E_TOKZ_NOTINT */ |
33 DUMMY_TR("Numeric constant out of range"), /* E_TOKZ_RANGE */ |
33 DUMMY_TR("Numeric constant out of range"), /* E_TOKZ_RANGE */ |
34 DUMMY_TR("Multi-character character constant"), /* E_TOKZ_MULTICHAR */ |
34 DUMMY_TR("Multi-character character constant"), /* E_TOKZ_MULTICHAR */ |
35 DUMMY_TR("Token/statement limit reached"), /* E_TOKZ_TOKEN_LIMIT */ |
35 DUMMY_TR("Token/statement limit reached"), /* E_TOKZ_TOKEN_LIMIT */ |
36 DUMMY_TR("Unknown option"), /* E_TOKZ_UNKONWN_OPTION */ |
36 DUMMY_TR("Unknown option"), /* E_TOKZ_UNKONWN_OPTION */ |
37 DUMMY_TR("Syntax error"), /* E_TOKZ_SYNTAX */ |
37 DUMMY_TR("Syntax error"), /* E_TOKZ_SYNTAX */ |
38 DUMMY_TR("Invalid argument"), /* E_TOKZ_INVALID_ARGUMENT */ |
38 DUMMY_TR("Invalid argument"), /* E_TOKZ_INVALID_ARGUMENT */ |
39 DUMMY_TR("End of statement expected"), /* E_TOKZ_EOS_EXPECTED */ |
39 DUMMY_TR("End of statement expected"), /* E_TOKZ_EOS_EXPECTED */ |
40 DUMMY_TR("Too few arguments"), /* E_TOKZ_TOO_FEW_ARGS */ |
40 DUMMY_TR("Too few arguments"), /* E_TOKZ_TOO_FEW_ARGS */ |
41 DUMMY_TR("Too many arguments"), /* E_TOKZ_TOO_MANY_ARGS */ |
41 DUMMY_TR("Too many arguments"), /* E_TOKZ_TOO_MANY_ARGS */ |
42 DUMMY_TR("Maximum section nestin level exceeded"), /* E_TOK_Z_MAX_NEST */ |
42 DUMMY_TR("Maximum section nestin level exceeded"), /* E_TOK_Z_MAX_NEST */ |
43 DUMMY_TR("Identifier expected"), /* E_TOKZ_IDENTIFIER_EXPECTED */ |
43 DUMMY_TR("Identifier expected"), /* E_TOKZ_IDENTIFIER_EXPECTED */ |
44 DUMMY_TR("Starting brace ('{') expected"), /* E_TOKZ_LBRACE_EXPECTED */ |
44 DUMMY_TR("Starting brace ('{') expected"), /* E_TOKZ_LBRACE_EXPECTED */ |
45 }; |
45 }; |
46 |
46 |
47 |
47 |
48 /* */ |
48 /* */ |
49 |
49 |
107 #define GETCH() _getch(tokz) |
107 #define GETCH() _getch(tokz) |
108 #define UNGETCH(C) _ungetch(tokz, C) |
108 #define UNGETCH(C) _ungetch(tokz, C) |
109 |
109 |
110 static int _getch(Tokenizer *tokz) |
110 static int _getch(Tokenizer *tokz) |
111 { |
111 { |
112 int c; |
112 int c; |
113 |
113 |
114 if(tokz->ungetc!=-1){ |
114 if(tokz->ungetc!=-1){ |
115 c=tokz->ungetc; |
115 c=tokz->ungetc; |
116 tokz->ungetc=-1; |
116 tokz->ungetc=-1; |
117 }else if (tokz->flags&TOKZ_READ_FROM_BUFFER) { |
117 }else if (tokz->flags&TOKZ_READ_FROM_BUFFER) { |
118 assert(tokz->buffer.data!=NULL); |
118 assert(tokz->buffer.data!=NULL); |
119 if (tokz->buffer.pos==tokz->buffer.len) |
119 if (tokz->buffer.pos==tokz->buffer.len) |
120 c=EOF; |
120 c=EOF; |
121 else |
121 else |
122 c=tokz->buffer.data[tokz->buffer.pos++]; |
122 c=tokz->buffer.data[tokz->buffer.pos++]; |
123 }else{ |
123 }else{ |
124 c=getc(tokz->file); |
124 c=getc(tokz->file); |
125 } |
125 } |
126 |
126 |
127 return c; |
127 return c; |
128 } |
128 } |
129 |
129 |
130 |
130 |
131 static void _ungetch(Tokenizer *tokz, int c) |
131 static void _ungetch(Tokenizer *tokz, int c) |
132 { |
132 { |
133 tokz->ungetc=c; |
133 tokz->ungetc=c; |
134 } |
134 } |
135 |
135 |
136 |
136 |
137 /* */ |
137 /* */ |
138 |
138 |
139 |
139 |
140 static int scan_line_comment(Token *tok, Tokenizer *tokz) |
140 static int scan_line_comment(Token *tok, Tokenizer *tokz) |
141 { |
141 { |
142 STRING_DECL_P(s, "#"); |
142 STRING_DECL_P(s, "#"); |
143 int c; |
143 int c; |
144 |
144 |
145 c=GETCH(); |
145 c=GETCH(); |
146 |
146 |
147 while(c!='\n' && c!=EOF){ |
147 while(c!='\n' && c!=EOF){ |
148 STRING_APPEND(s, c); |
148 STRING_APPEND(s, c); |
149 c=GETCH(); |
149 c=GETCH(); |
150 } |
150 } |
151 |
151 |
152 UNGETCH(c); |
152 UNGETCH(c); |
153 |
153 |
154 STRING_FINISH(s); |
154 STRING_FINISH(s); |
155 |
155 |
156 TOK_SET_COMMENT(tok, s); |
156 TOK_SET_COMMENT(tok, s); |
157 |
157 |
158 return 0; |
158 return 0; |
159 } |
159 } |
160 |
160 |
161 |
161 |
162 static int skip_line_comment(Tokenizer *tokz) |
162 static int skip_line_comment(Tokenizer *tokz) |
163 { |
163 { |
164 int c; |
164 int c; |
165 |
165 |
166 do{ |
166 do{ |
167 c=GETCH(); |
167 c=GETCH(); |
168 }while(c!='\n' && c!=EOF); |
168 }while(c!='\n' && c!=EOF); |
169 |
169 |
170 UNGETCH(c); |
170 UNGETCH(c); |
171 |
171 |
172 return 0; |
172 return 0; |
173 } |
173 } |
174 |
174 |
175 |
175 |
176 /* */ |
176 /* */ |
177 |
177 |
178 |
178 |
179 static int scan_c_comment(Token *tok, Tokenizer *tokz) |
179 static int scan_c_comment(Token *tok, Tokenizer *tokz) |
180 { |
180 { |
181 STRING_DECL_P(s, "/*"); |
181 STRING_DECL_P(s, "/*"); |
182 int c; |
182 int c; |
183 int st=0; |
183 int st=0; |
184 |
184 |
185 while(1){ |
185 while(1){ |
186 c=GETCH(); |
186 c=GETCH(); |
187 |
187 |
188 if(c==EOF){ |
188 if(c==EOF){ |
189 STRING_FREE(s); |
189 STRING_FREE(s); |
190 return E_TOKZ_UNEXPECTED_EOF; |
190 return E_TOKZ_UNEXPECTED_EOF; |
191 } |
191 } |
192 |
192 |
193 STRING_APPEND(s, c); |
193 STRING_APPEND(s, c); |
194 |
194 |
195 if(c=='\n'){ |
195 if(c=='\n'){ |
196 INC_LINE(); |
196 INC_LINE(); |
197 }else if(st==0 && c=='*'){ |
197 }else if(st==0 && c=='*'){ |
198 st=1; |
198 st=1; |
199 }else if(st==1){ |
199 }else if(st==1){ |
200 if(c=='/') |
200 if(c=='/') |
201 break; |
201 break; |
202 st=0; |
202 st=0; |
203 } |
203 } |
204 } |
204 } |
205 |
205 |
206 STRING_FINISH(s); |
206 STRING_FINISH(s); |
207 |
207 |
208 TOK_SET_COMMENT(tok, s); |
208 TOK_SET_COMMENT(tok, s); |
209 |
209 |
210 return 0; |
210 return 0; |
211 } |
211 } |
212 |
212 |
213 |
213 |
214 static int skip_c_comment(Tokenizer *tokz) |
214 static int skip_c_comment(Tokenizer *tokz) |
215 { |
215 { |
216 int c; |
216 int c; |
217 int st=0; |
217 int st=0; |
218 |
218 |
219 while(1){ |
219 while(1){ |
220 c=GETCH(); |
220 c=GETCH(); |
221 |
221 |
222 if(c==EOF) |
222 if(c==EOF) |
223 return E_TOKZ_UNEXPECTED_EOF; |
223 return E_TOKZ_UNEXPECTED_EOF; |
224 |
224 |
225 if(c=='\n') |
225 if(c=='\n') |
226 INC_LINE(); |
226 INC_LINE(); |
227 else if(st==0 && c=='*') |
227 else if(st==0 && c=='*') |
228 st=1; |
228 st=1; |
229 else if(st==1){ |
229 else if(st==1){ |
230 if(c=='/') |
230 if(c=='/') |
231 break; |
231 break; |
232 st=0; |
232 st=0; |
233 } |
233 } |
234 } |
234 } |
235 |
235 |
236 return 0; |
236 return 0; |
237 } |
237 } |
238 |
238 |
239 |
239 |
240 /* */ |
240 /* */ |
241 |
241 |
242 |
242 |
243 static int scan_char_escape(Tokenizer *tokz) |
243 static int scan_char_escape(Tokenizer *tokz) |
244 { |
244 { |
245 static char* special_chars="nrtbae"; |
245 static char* special_chars="nrtbae"; |
246 static char* specials="\n\r\t\b\a\033"; |
246 static char* specials="\n\r\t\b\a\033"; |
247 int base, max; |
247 int base, max; |
248 int i ,c; |
248 int i ,c; |
249 |
249 |
250 c=GETCH(); |
250 c=GETCH(); |
251 |
251 |
252 for(i=0;special_chars[i];i++){ |
252 for(i=0;special_chars[i];i++){ |
253 if(special_chars[i]==c) |
253 if(special_chars[i]==c) |
254 return specials[c]; |
254 return specials[c]; |
255 } |
255 } |
256 |
256 |
257 if(c=='x' || c=='X'){ |
257 if(c=='x' || c=='X'){ |
258 base=16;max=2;i=0; |
258 base=16;max=2;i=0; |
259 }else if(c=='d' || c=='D'){ |
259 }else if(c=='d' || c=='D'){ |
260 base=10;max=3;i=0; |
260 base=10;max=3;i=0; |
261 }else if(c=='8' || c=='9'){ |
261 }else if(c=='8' || c=='9'){ |
262 base=10;max=2;i=c-'0'; |
262 base=10;max=2;i=c-'0'; |
263 }else if('0'<=c && c<='7'){ |
263 }else if('0'<=c && c<='7'){ |
264 base=8;max=2;i=c-'0'; |
264 base=8;max=2;i=c-'0'; |
265 }else if(c=='\n'){ |
265 }else if(c=='\n'){ |
266 UNGETCH(c); |
266 UNGETCH(c); |
267 return -2; |
267 return -2; |
268 }else{ |
268 }else{ |
269 return c; |
269 return c; |
270 } |
270 } |
271 |
271 |
272 |
272 |
273 while(--max>=0){ |
273 while(--max>=0){ |
274 c=GETCH(); |
274 c=GETCH(); |
275 |
275 |
276 if(c==EOF) |
276 if(c==EOF) |
277 return EOF; |
277 return EOF; |
278 |
278 |
279 if(c=='\n'){ |
279 if(c=='\n'){ |
280 UNGETCH(c); |
280 UNGETCH(c); |
281 return -2; |
281 return -2; |
282 } |
282 } |
283 |
283 |
284 if(base==16){ |
284 if(base==16){ |
285 if(!isxdigit(c)) |
285 if(!isxdigit(c)) |
286 break; |
286 break; |
287 |
287 |
288 i<<=4; |
288 i<<=4; |
289 |
289 |
290 if(isdigit(c)) |
290 if(isdigit(c)) |
291 i+=c-'0'; |
291 i+=c-'0'; |
292 else if(i>='a') |
292 else if(i>='a') |
293 i+=0xa+c-'a'; |
293 i+=0xa+c-'a'; |
294 else |
294 else |
295 i+=0xa+c-'a'; |
295 i+=0xa+c-'a'; |
296 |
296 |
297 }else if(base==10){ |
297 }else if(base==10){ |
298 if(!isdigit(c)) |
298 if(!isdigit(c)) |
299 break; |
299 break; |
300 i*=10; |
300 i*=10; |
301 i+=c-'0'; |
301 i+=c-'0'; |
302 }else{ |
302 }else{ |
303 if(c<'0' || c>'7') |
303 if(c<'0' || c>'7') |
304 break; |
304 break; |
305 i<<=3; |
305 i<<=3; |
306 i+=c-'0'; |
306 i+=c-'0'; |
307 } |
307 } |
308 } |
308 } |
309 |
309 |
310 if(max>=0) |
310 if(max>=0) |
311 UNGETCH(c); |
311 UNGETCH(c); |
312 |
312 |
313 return i; |
313 return i; |
314 } |
314 } |
315 |
315 |
316 |
316 |
317 /* */ |
317 /* */ |
318 |
318 |
319 |
319 |
320 static int scan_string(Token *tok, Tokenizer *tokz, bool escapes) |
320 static int scan_string(Token *tok, Tokenizer *tokz, bool escapes) |
321 { |
321 { |
322 STRING_DECL(s); |
322 STRING_DECL(s); |
323 int c; |
323 int c; |
324 |
324 |
325 while(1){ |
325 while(1){ |
326 c=GETCH(); |
326 c=GETCH(); |
327 |
327 |
328 if(c=='"') |
328 if(c=='"') |
329 break; |
329 break; |
330 |
330 |
331 if(c=='\n'){ |
331 if(c=='\n'){ |
332 UNGETCH(c); |
332 UNGETCH(c); |
333 STRING_FREE(s); |
333 STRING_FREE(s); |
334 return E_TOKZ_UNEXPECTED_EOL; |
334 return E_TOKZ_UNEXPECTED_EOL; |
335 } |
335 } |
336 |
336 |
337 if(c=='\\' && escapes){ |
337 if(c=='\\' && escapes){ |
338 c=scan_char_escape(tokz); |
338 c=scan_char_escape(tokz); |
339 if(c==-2){ |
339 if(c==-2){ |
340 STRING_FREE(s); |
340 STRING_FREE(s); |
341 return E_TOKZ_UNEXPECTED_EOL; |
341 return E_TOKZ_UNEXPECTED_EOL; |
342 } |
342 } |
343 } |
343 } |
344 |
344 |
345 if(c==EOF){ |
345 if(c==EOF){ |
346 STRING_FREE(s); |
346 STRING_FREE(s); |
347 return E_TOKZ_UNEXPECTED_EOF; |
347 return E_TOKZ_UNEXPECTED_EOF; |
348 } |
348 } |
349 |
349 |
350 STRING_APPEND(s, c); |
350 STRING_APPEND(s, c); |
351 } |
351 } |
352 |
352 |
353 STRING_FINISH(s); |
353 STRING_FINISH(s); |
354 |
354 |
355 TOK_SET_STRING(tok, s); |
355 TOK_SET_STRING(tok, s); |
356 |
356 |
357 return 0; |
357 return 0; |
358 } |
358 } |
359 |
359 |
360 |
360 |
361 /* */ |
361 /* */ |
362 |
362 |
363 |
363 |
364 static int scan_char(Token *tok, Tokenizer *tokz) |
364 static int scan_char(Token *tok, Tokenizer *tokz) |
365 { |
365 { |
366 int c, c2; |
366 int c, c2; |
367 |
367 |
368 c=GETCH(); |
368 c=GETCH(); |
369 |
369 |
370 if(c==EOF) |
370 if(c==EOF) |
371 return E_TOKZ_UNEXPECTED_EOF; |
371 return E_TOKZ_UNEXPECTED_EOF; |
372 |
372 |
373 if(c=='\n') |
373 if(c=='\n') |
374 return E_TOKZ_UNEXPECTED_EOL; |
374 return E_TOKZ_UNEXPECTED_EOL; |
375 |
375 |
376 if(c=='\\'){ |
376 if(c=='\\'){ |
377 c=scan_char_escape(tokz); |
377 c=scan_char_escape(tokz); |
378 |
378 |
379 if(c==EOF) |
379 if(c==EOF) |
380 return E_TOKZ_UNEXPECTED_EOF; |
380 return E_TOKZ_UNEXPECTED_EOF; |
381 |
381 |
382 if(c==-2) |
382 if(c==-2) |
383 return E_TOKZ_UNEXPECTED_EOL; |
383 return E_TOKZ_UNEXPECTED_EOL; |
384 } |
384 } |
385 |
385 |
386 c2=GETCH(); |
386 c2=GETCH(); |
387 |
387 |
388 if(c2!='\'') |
388 if(c2!='\'') |
389 return E_TOKZ_MULTICHAR; |
389 return E_TOKZ_MULTICHAR; |
390 |
390 |
391 TOK_SET_CHAR(tok, c); |
391 TOK_SET_CHAR(tok, c); |
392 |
392 |
393 return 0; |
393 return 0; |
394 } |
394 } |
395 |
395 |
396 |
396 |
397 /* */ |
397 /* */ |
398 |
398 |
400 #define START_IDENT(X) (isalpha(X) || X=='_' || X=='$') |
400 #define START_IDENT(X) (isalpha(X) || X=='_' || X=='$') |
401 |
401 |
402 |
402 |
403 static int scan_identifier(Token *tok, Tokenizer *tokz, int c) |
403 static int scan_identifier(Token *tok, Tokenizer *tokz, int c) |
404 { |
404 { |
405 STRING_DECL(s); |
405 STRING_DECL(s); |
406 |
406 |
407 do{ |
407 do{ |
408 STRING_APPEND(s, c); |
408 STRING_APPEND(s, c); |
409 c=GETCH(); |
409 c=GETCH(); |
410 }while(isalnum(c) || c=='_' || c=='$'); |
410 }while(isalnum(c) || c=='_' || c=='$'); |
411 |
411 |
412 UNGETCH(c); |
412 UNGETCH(c); |
413 |
413 |
414 STRING_FINISH(s); |
414 STRING_FINISH(s); |
415 |
415 |
416 TOK_SET_IDENT(tok, s); |
416 TOK_SET_IDENT(tok, s); |
417 |
417 |
418 return 0; |
418 return 0; |
419 } |
419 } |
420 |
420 |
421 #define NP_SIMPLE_IMPL |
421 #define NP_SIMPLE_IMPL |
422 #include "np/numparser2.h" |
422 #include "np/numparser2.h" |
423 #include "np/np-conv.h" |
423 #include "np/np-conv.h" |
424 |
424 |
425 |
425 |
426 static int scan_number(Token *tok, Tokenizer *tokz, int c) |
426 static int scan_number(Token *tok, Tokenizer *tokz, int c) |
427 { |
427 { |
428 NPNum num=NUM_INIT; |
428 NPNum num=NUM_INIT; |
429 int e; |
429 int e; |
430 |
430 |
431 if((e=parse_number(&num, tokz, c))) |
431 if((e=parse_number(&num, tokz, c))) |
432 return e; |
432 return e; |
433 |
433 |
434 if(num.type==NPNUM_INT){ |
434 if(num.type==NPNUM_INT){ |
435 long l; |
435 long l; |
436 if((e=num_to_long(&l, &num, TRUE))) |
436 if((e=num_to_long(&l, &num, TRUE))) |
437 return e; |
437 return e; |
438 |
438 |
439 TOK_SET_LONG(tok, l); |
439 TOK_SET_LONG(tok, l); |
440 }else if(num.type==NPNUM_FLOAT){ |
440 }else if(num.type==NPNUM_FLOAT){ |
441 double d; |
441 double d; |
442 if((e=num_to_double(&d, &num))) |
442 if((e=num_to_double(&d, &num))) |
443 return e; |
443 return e; |
444 |
444 |
445 TOK_SET_DOUBLE(tok, d); |
445 TOK_SET_DOUBLE(tok, d); |
446 }else{ |
446 }else{ |
447 return E_TOKZ_NUMFMT; |
447 return E_TOKZ_NUMFMT; |
448 } |
448 } |
449 |
449 |
450 return 0; |
450 return 0; |
451 } |
451 } |
452 |
452 |
453 |
453 |
454 /* */ |
454 /* */ |
455 |
455 |
456 |
456 |
457 static uchar op_map[]={ |
457 static uchar op_map[]={ |
458 0x00, /* ________ 0-7 */ |
458 0x00, /* ________ 0-7 */ |
459 0x00, /* ________ 8-15 */ |
459 0x00, /* ________ 8-15 */ |
460 0x00, /* ________ 16-23 */ |
460 0x00, /* ________ 16-23 */ |
461 0x00, /* ________ 24-31 */ |
461 0x00, /* ________ 24-31 */ |
462 0x62, /* _!___%&_ 32-39 */ |
462 0x62, /* _!___%&_ 32-39 */ |
463 0xff, /* ()*+,-./ 40-47 */ |
463 0xff, /* ()*+,-./ 40-47 */ |
464 0x00, /* ________ 48-55 */ |
464 0x00, /* ________ 48-55 */ |
465 0xfc, /* __:;<=>? 56-63 */ |
465 0xfc, /* __:;<=>? 56-63 */ |
466 0x01, /* @_______ 64-71 */ |
466 0x01, /* @_______ 64-71 */ |
467 0x00, /* ________ 72-79 */ |
467 0x00, /* ________ 72-79 */ |
468 0x00, /* ________ 80-87 */ |
468 0x00, /* ________ 80-87 */ |
469 0x78, /* ___[_]^_ 88-95 */ |
469 0x78, /* ___[_]^_ 88-95 */ |
470 0x00, /* ________ 96-103 */ |
470 0x00, /* ________ 96-103 */ |
471 0x00, /* ________ 104-111 */ |
471 0x00, /* ________ 104-111 */ |
472 0x00, /* ________ 112-119 */ |
472 0x00, /* ________ 112-119 */ |
473 0x38 /* ___{|}__ 120-127 */ |
473 0x38 /* ___{|}__ 120-127 */ |
474 }; |
474 }; |
475 |
475 |
476 |
476 |
477 static bool map_isset(uchar *map, uint ch) |
477 static bool map_isset(uchar *map, uint ch) |
478 { |
478 { |
479 if(ch>127) |
479 if(ch>127) |
480 return FALSE; |
480 return FALSE; |
481 |
481 |
482 return map[ch>>3]&(1<<(ch&7)); |
482 return map[ch>>3]&(1<<(ch&7)); |
483 } |
483 } |
484 |
484 |
485 |
485 |
486 static bool is_opch(uint ch) |
486 static bool is_opch(uint ch) |
487 { |
487 { |
488 return map_isset(op_map, ch); |
488 return map_isset(op_map, ch); |
489 } |
489 } |
490 |
490 |
491 |
491 |
492 static int scan_op(Token *tok, Tokenizer *tokz, int c) |
492 static int scan_op(Token *tok, Tokenizer *tokz, int c) |
493 { |
493 { |
494 int c2; |
494 int c2; |
495 int op=-1; |
495 int op=-1; |
496 |
496 |
497 /* Quickly check it is an operator character */ |
497 /* Quickly check it is an operator character */ |
498 if(!is_opch(c)) |
498 if(!is_opch(c)) |
499 return E_TOKZ_INVALID_CHAR; |
499 return E_TOKZ_INVALID_CHAR; |
500 |
500 |
501 switch(c){ |
501 switch(c){ |
502 case '+': |
502 case '+': |
503 case '-': |
503 case '-': |
504 case '*': |
504 case '*': |
505 /* case '/': Checked elsewhere */ |
505 /* case '/': Checked elsewhere */ |
506 case '%': |
506 case '%': |
507 case '^': |
507 case '^': |
508 case '!': |
508 case '!': |
509 case '=': |
509 case '=': |
510 case '<': |
510 case '<': |
511 case '>': |
511 case '>': |
512 c2=GETCH(); |
512 c2=GETCH(); |
513 if(c2=='='){ |
513 if(c2=='='){ |
514 op=c|(c2<<8); |
514 op=c|(c2<<8); |
515 }else if(c2==c && (c2!='%' && c2!='!' && c2!='*')){ |
515 }else if(c2==c && (c2!='%' && c2!='!' && c2!='*')){ |
516 if(c=='<' || c=='>'){ |
516 if(c=='<' || c=='>'){ |
517 int c3=GETCH(); |
517 int c3=GETCH(); |
518 if(c3=='='){ |
518 if(c3=='='){ |
519 op=c|(c2<<8)|(c3<<16); |
519 op=c|(c2<<8)|(c3<<16); |
520 }else{ |
520 }else{ |
521 UNGETCH(c3); |
521 UNGETCH(c3); |
522 op=c|(c2<<8); |
522 op=c|(c2<<8); |
523 } |
523 } |
524 }else{ |
524 }else{ |
525 op=c|(c2<<8); |
525 op=c|(c2<<8); |
526 } |
526 } |
527 }else{ |
527 }else{ |
528 UNGETCH(c2); |
528 UNGETCH(c2); |
529 op=c; |
529 op=c; |
530 } |
530 } |
531 break; |
531 break; |
532 |
532 |
533 /* It is already known that it is a operator so these are not needed |
533 /* It is already known that it is a operator so these are not needed |
534 case ':': |
534 case ':': |
535 case '~': |
535 case '~': |
536 case '?': |
536 case '?': |
537 case '.': |
537 case '.': |
538 case ';'; |
538 case ';'; |
539 case '{': |
539 case '{': |
540 case '}': |
540 case '}': |
541 case '@': |
541 case '@': |
542 case '|': |
542 case '|': |
543 case '&': |
543 case '&': |
544 */ |
544 */ |
545 default: |
545 default: |
546 op=c; |
546 op=c; |
547 } |
547 } |
548 |
548 |
549 TOK_SET_OP(tok, op); |
549 TOK_SET_OP(tok, op); |
550 |
550 |
551 return 0; |
551 return 0; |
552 } |
552 } |
553 |
553 |
554 |
554 |
555 /* */ |
555 /* */ |
556 |
556 |
557 |
557 |
558 void tokz_warn(const Tokenizer *tokz, int line, const char *fmt, ...) |
558 void tokz_warn(const Tokenizer *tokz, int line, const char *fmt, ...) |
559 { |
559 { |
560 va_list args; |
560 va_list args; |
561 |
561 |
562 va_start(args, fmt); |
562 va_start(args, fmt); |
563 |
563 |
564 if(tokz!=NULL) |
564 if(tokz!=NULL) |
565 warn_obj_line_v(tokz->name, line, fmt, args); |
565 warn_obj_line_v(tokz->name, line, fmt, args); |
566 else |
566 else |
567 warn(fmt, args); |
567 warn(fmt, args); |
568 |
568 |
569 va_end(args); |
569 va_end(args); |
570 } |
570 } |
571 |
571 |
572 |
572 |
573 void tokz_warn_error(const Tokenizer *tokz, int line, int e) |
573 void tokz_warn_error(const Tokenizer *tokz, int line, int e) |
574 { |
574 { |
575 if(e==E_TOKZ_UNEXPECTED_EOF) |
575 if(e==E_TOKZ_UNEXPECTED_EOF) |
576 line=0; |
576 line=0; |
577 |
577 |
578 if(e<0) |
578 if(e<0) |
579 tokz_warn(tokz, line, "%s", strerror(-e)); |
579 tokz_warn(tokz, line, "%s", strerror(-e)); |
580 else |
580 else |
581 tokz_warn(tokz, line, "%s", TR(errors[e])); |
581 tokz_warn(tokz, line, "%s", TR(errors[e])); |
582 } |
582 } |
583 |
583 |
584 |
584 |
585 bool tokz_get_token(Tokenizer *tokz, Token *tok) |
585 bool tokz_get_token(Tokenizer *tokz, Token *tok) |
586 { |
586 { |
587 int c, c2, e; |
587 int c, c2, e; |
588 |
588 |
589 if (!(tokz->flags&TOKZ_READ_FROM_BUFFER)) |
589 if (!(tokz->flags&TOKZ_READ_FROM_BUFFER)) |
590 assert(tokz->file!=NULL); |
590 assert(tokz->file!=NULL); |
591 |
591 |
592 tok_free(tok); |
592 tok_free(tok); |
593 |
593 |
594 if(!TOK_IS_INVALID(&(tokz->ungettok))){ |
594 if(!TOK_IS_INVALID(&(tokz->ungettok))){ |
595 *tok=tokz->ungettok; |
595 *tok=tokz->ungettok; |
596 tokz->ungettok.type=TOK_INVALID; |
596 tokz->ungettok.type=TOK_INVALID; |
597 return TRUE; |
597 return TRUE; |
598 } |
598 } |
599 |
599 |
600 while(1){ |
600 while(1){ |
601 |
601 |
602 e=0; |
602 e=0; |
603 |
603 |
604 do{ |
604 do{ |
605 c=GETCH(); |
605 c=GETCH(); |
606 }while(c!='\n' && c!=EOF && isspace(c)); |
606 }while(c!='\n' && c!=EOF && isspace(c)); |
607 |
607 |
608 tok->line=tokz->line; |
608 tok->line=tokz->line; |
609 |
609 |
610 switch(c){ |
610 switch(c){ |
611 case EOF: |
611 case EOF: |
612 TOK_SET_OP(tok, OP_EOF); |
612 TOK_SET_OP(tok, OP_EOF); |
613 return TRUE; |
613 return TRUE; |
614 |
614 |
615 case '\n': |
615 case '\n': |
616 INC_LINE(); |
616 INC_LINE(); |
617 |
617 |
618 if(tokz->flags&TOKZ_IGNORE_NEXTLINE) |
618 if(tokz->flags&TOKZ_IGNORE_NEXTLINE) |
619 continue; |
619 continue; |
620 |
620 |
621 TOK_SET_OP(tok, OP_NEXTLINE); |
621 TOK_SET_OP(tok, OP_NEXTLINE); |
622 |
622 |
623 return TRUE; |
623 return TRUE; |
624 |
624 |
625 case '\\': |
625 case '\\': |
626 do{ |
626 do{ |
627 c=GETCH(); |
627 c=GETCH(); |
628 if(c==EOF){ |
628 if(c==EOF){ |
629 TOK_SET_OP(tok, OP_EOF); |
629 TOK_SET_OP(tok, OP_EOF); |
630 return FALSE; |
630 return FALSE; |
631 } |
631 } |
632 if(!isspace(c) && e==0){ |
632 if(!isspace(c) && e==0){ |
633 e=E_TOKZ_EOL_EXPECTED; |
633 e=E_TOKZ_EOL_EXPECTED; |
634 tokz_warn_error(tokz, tokz->line, e); |
634 tokz_warn_error(tokz, tokz->line, e); |
635 if(!(tokz->flags&TOKZ_ERROR_TOLERANT)) |
635 if(!(tokz->flags&TOKZ_ERROR_TOLERANT)) |
636 return FALSE; |
636 return FALSE; |
637 } |
637 } |
638 }while(c!='\n'); |
638 }while(c!='\n'); |
639 |
639 |
640 INC_LINE(); |
640 INC_LINE(); |
641 continue; |
641 continue; |
642 |
642 |
643 case '#': |
643 case '#': |
644 if(tokz->flags&TOKZ_READ_COMMENTS){ |
644 if(tokz->flags&TOKZ_READ_COMMENTS){ |
645 e=scan_line_comment(tok, tokz); |
645 e=scan_line_comment(tok, tokz); |
646 break; |
646 break; |
647 }else if((e=skip_line_comment(tokz))){ |
647 }else if((e=skip_line_comment(tokz))){ |
648 break; |
648 break; |
649 } |
649 } |
650 |
650 |
651 continue; |
651 continue; |
652 |
652 |
653 case '/': |
653 case '/': |
654 c2=GETCH(); |
654 c2=GETCH(); |
655 |
655 |
656 if(c2=='='){ |
656 if(c2=='='){ |
657 TOK_SET_OP(tok, OP_AS_DIV); |
657 TOK_SET_OP(tok, OP_AS_DIV); |
658 return TRUE; |
658 return TRUE; |
659 } |
659 } |
660 |
660 |
661 if(c2!='*'){ |
661 if(c2!='*'){ |
662 UNGETCH(c2); |
662 UNGETCH(c2); |
663 TOK_SET_OP(tok, OP_DIV); |
663 TOK_SET_OP(tok, OP_DIV); |
664 return TRUE; |
664 return TRUE; |
665 } |
665 } |
666 |
666 |
667 if(tokz->flags&TOKZ_READ_COMMENTS){ |
667 if(tokz->flags&TOKZ_READ_COMMENTS){ |
668 e=scan_c_comment(tok, tokz); |
668 e=scan_c_comment(tok, tokz); |
669 break; |
669 break; |
670 }else if((e=skip_c_comment(tokz))){ |
670 }else if((e=skip_c_comment(tokz))){ |
671 break; |
671 break; |
672 } |
672 } |
673 |
673 |
674 continue; |
674 continue; |
675 |
675 |
676 case '\"': |
676 case '\"': |
677 e=scan_string(tok, tokz, TRUE); |
677 e=scan_string(tok, tokz, TRUE); |
678 break; |
678 break; |
679 |
679 |
680 case '\'': |
680 case '\'': |
681 e=scan_char(tok, tokz); |
681 e=scan_char(tok, tokz); |
682 break; |
682 break; |
683 |
683 |
684 default: |
684 default: |
685 if(('0'<=c && c<='9') || c=='-' || c=='+'){ |
685 if(('0'<=c && c<='9') || c=='-' || c=='+'){ |
686 e=scan_number(tok, tokz, c); |
686 e=scan_number(tok, tokz, c); |
687 break; |
687 break; |
688 } |
688 } |
689 |
689 |
690 if(START_IDENT(c)) |
690 if(START_IDENT(c)) |
691 e=scan_identifier(tok, tokz, c); |
691 e=scan_identifier(tok, tokz, c); |
692 else |
692 else |
693 e=scan_op(tok, tokz, c); |
693 e=scan_op(tok, tokz, c); |
694 } |
694 } |
695 |
695 |
696 if(!e) |
696 if(!e) |
697 return TRUE; |
697 return TRUE; |
698 |
698 |
699 tokz_warn_error(tokz, tokz->line, e); |
699 tokz_warn_error(tokz, tokz->line, e); |
700 return FALSE; |
700 return FALSE; |
701 } |
701 } |
702 } |
702 } |
703 |
703 |
704 |
704 |
705 void tokz_unget_token(Tokenizer *tokz, Token *tok) |
705 void tokz_unget_token(Tokenizer *tokz, Token *tok) |
706 { |
706 { |
707 tok_free(&(tokz->ungettok)); |
707 tok_free(&(tokz->ungettok)); |
708 tokz->ungettok=*tok; |
708 tokz->ungettok=*tok; |
709 tok->type=TOK_INVALID; |
709 tok->type=TOK_INVALID; |
710 } |
710 } |
711 |
711 |
712 |
712 |
713 /* |
713 /* |
714 * File open |
714 * File open |
715 */ |
715 */ |
716 |
716 |
717 static bool do_tokz_pushf(Tokenizer *tokz) |
717 static bool do_tokz_pushf(Tokenizer *tokz) |
718 { |
718 { |
719 Tokenizer_FInfo *finfo; |
719 Tokenizer_FInfo *finfo; |
720 |
720 |
721 finfo=REALLOC_N(tokz->filestack, Tokenizer_FInfo, |
721 finfo=REALLOC_N(tokz->filestack, Tokenizer_FInfo, |
722 tokz->filestack_n, tokz->filestack_n+1); |
722 tokz->filestack_n, tokz->filestack_n+1); |
723 |
723 |
724 if(finfo==NULL) |
724 if(finfo==NULL) |
725 return FALSE; |
725 return FALSE; |
726 |
726 |
727 tokz->filestack=finfo; |
727 tokz->filestack=finfo; |
728 finfo=&(finfo[tokz->filestack_n++]); |
728 finfo=&(finfo[tokz->filestack_n++]); |
729 |
729 |
730 finfo->file=tokz->file; |
730 finfo->file=tokz->file; |
731 finfo->name=tokz->name; |
731 finfo->name=tokz->name; |
732 finfo->line=tokz->line; |
732 finfo->line=tokz->line; |
733 finfo->ungetc=tokz->ungetc; |
733 finfo->ungetc=tokz->ungetc; |
734 finfo->ungettok=tokz->ungettok; |
734 finfo->ungettok=tokz->ungettok; |
735 |
735 |
736 return TRUE; |
736 return TRUE; |
737 } |
737 } |
738 |
738 |
739 |
739 |
740 bool tokz_pushf_file(Tokenizer *tokz, FILE *file, const char *fname) |
740 bool tokz_pushf_file(Tokenizer *tokz, FILE *file, const char *fname) |
741 { |
741 { |
742 char *fname_copy=NULL; |
742 char *fname_copy=NULL; |
743 |
743 |
744 if(file==NULL) |
744 if(file==NULL) |
745 return FALSE; |
745 return FALSE; |
746 |
746 |
747 if(fname!=NULL){ |
747 if(fname!=NULL){ |
748 fname_copy=scopy(fname); |
748 fname_copy=scopy(fname); |
749 if(fname_copy==NULL){ |
749 if(fname_copy==NULL){ |
750 warn_err(); |
750 warn_err(); |
751 return FALSE; |
751 return FALSE; |
752 } |
752 } |
753 } |
753 } |
754 |
754 |
755 if(tokz->file!=NULL){ |
755 if(tokz->file!=NULL){ |
756 if(!do_tokz_pushf(tokz)){ |
756 if(!do_tokz_pushf(tokz)){ |
757 warn_err(); |
757 warn_err(); |
758 if(fname_copy!=NULL) |
758 if(fname_copy!=NULL) |
759 free(fname_copy); |
759 free(fname_copy); |
760 return FALSE; |
760 return FALSE; |
761 } |
761 } |
762 } |
762 } |
763 |
763 |
764 tokz->file=file; |
764 tokz->file=file; |
765 tokz->name=fname_copy; |
765 tokz->name=fname_copy; |
766 tokz->line=1; |
766 tokz->line=1; |
767 tokz->ungetc=-1; |
767 tokz->ungetc=-1; |
768 tokz->ungettok.type=TOK_INVALID; |
768 tokz->ungettok.type=TOK_INVALID; |
769 |
769 |
770 return TRUE; |
770 return TRUE; |
771 } |
771 } |
772 |
772 |
773 |
773 |
774 bool tokz_pushf(Tokenizer *tokz, const char *fname) |
774 bool tokz_pushf(Tokenizer *tokz, const char *fname) |
775 { |
775 { |
776 FILE *file; |
776 FILE *file; |
777 |
777 |
778 file=fopen(fname, "r"); |
778 file=fopen(fname, "r"); |
779 |
779 |
780 if(file==NULL){ |
780 if(file==NULL){ |
781 warn_err_obj(fname); |
781 warn_err_obj(fname); |
782 return FALSE; |
782 return FALSE; |
783 } |
783 } |
784 |
784 |
785 if(!tokz_pushf_file(tokz, file, fname)){ |
785 if(!tokz_pushf_file(tokz, file, fname)){ |
786 fclose(file); |
786 fclose(file); |
787 return FALSE; |
787 return FALSE; |
788 } |
788 } |
789 |
789 |
790 return TRUE; |
790 return TRUE; |
791 } |
791 } |
792 |
792 |
793 |
793 |
794 |
794 |
795 static Tokenizer *tokz_create() |
795 static Tokenizer *tokz_create() |
796 { |
796 { |
797 Tokenizer*tokz; |
797 Tokenizer*tokz; |
798 |
798 |
799 tokz=ALLOC(Tokenizer); |
799 tokz=ALLOC(Tokenizer); |
800 |
800 |
801 if(tokz==NULL){ |
801 if(tokz==NULL){ |
802 warn_err(); |
802 warn_err(); |
803 return NULL; |
803 return NULL; |
804 } |
804 } |
805 |
805 |
806 tokz->file=NULL; |
806 tokz->file=NULL; |
807 tokz->name=NULL; |
807 tokz->name=NULL; |
808 tokz->line=1; |
808 tokz->line=1; |
809 tokz->ungetc=-1; |
809 tokz->ungetc=-1; |
810 tokz->ungettok.type=TOK_INVALID; |
810 tokz->ungettok.type=TOK_INVALID; |
811 tokz->flags=0; |
811 tokz->flags=0; |
812 tokz->optstack=NULL; |
812 tokz->optstack=NULL; |
813 tokz->nest_lvl=0; |
813 tokz->nest_lvl=0; |
814 tokz->filestack_n=0; |
814 tokz->filestack_n=0; |
815 tokz->filestack=NULL; |
815 tokz->filestack=NULL; |
816 tokz->buffer.data=0; |
816 tokz->buffer.data=0; |
817 tokz->buffer.len=0; |
817 tokz->buffer.len=0; |
818 tokz->buffer.pos=0; |
818 tokz->buffer.pos=0; |
819 |
819 |
820 return tokz; |
820 return tokz; |
821 } |
821 } |
822 |
822 |
823 |
823 |
824 Tokenizer *tokz_open(const char *fname) |
824 Tokenizer *tokz_open(const char *fname) |
825 { |
825 { |
826 Tokenizer *tokz; |
826 Tokenizer *tokz; |
827 |
827 |
828 tokz=tokz_create(); |
828 tokz=tokz_create(); |
829 |
829 |
830 if(!tokz_pushf(tokz, fname)){ |
830 if(!tokz_pushf(tokz, fname)){ |
831 free(tokz); |
831 free(tokz); |
832 return NULL; |
832 return NULL; |
833 } |
833 } |
834 |
834 |
835 return tokz; |
835 return tokz; |
836 } |
836 } |
837 |
837 |
838 |
838 |
839 Tokenizer *tokz_open_file(FILE *file, const char *fname) |
839 Tokenizer *tokz_open_file(FILE *file, const char *fname) |
840 { |
840 { |
841 Tokenizer *tokz; |
841 Tokenizer *tokz; |
842 |
842 |
843 tokz=tokz_create(); |
843 tokz=tokz_create(); |
844 |
844 |
845 if(!tokz_pushf_file(tokz, file, fname)){ |
845 if(!tokz_pushf_file(tokz, file, fname)){ |
846 free(tokz); |
846 free(tokz); |
847 return NULL; |
847 return NULL; |
848 } |
848 } |
849 |
849 |
850 return tokz; |
850 return tokz; |
851 } |
851 } |
852 |
852 |
853 Tokenizer *tokz_prepare_buffer(char *buffer, int len) |
853 Tokenizer *tokz_prepare_buffer(char *buffer, int len) |
854 { |
854 { |
855 Tokenizer *tokz; |
855 Tokenizer *tokz; |
856 char old=0; |
856 char old=0; |
857 |
857 |
858 tokz=tokz_create(); |
858 tokz=tokz_create(); |
859 if(len>0){ |
859 if(len>0){ |
860 old=buffer[len-1]; |
860 old=buffer[len-1]; |
861 buffer[len-1]='\0'; |
861 buffer[len-1]='\0'; |
862 } |
862 } |
863 |
863 |
864 tokz->flags|=TOKZ_READ_FROM_BUFFER; |
864 tokz->flags|=TOKZ_READ_FROM_BUFFER; |
865 tokz->buffer.data=scopy(buffer); |
865 tokz->buffer.data=scopy(buffer); |
866 tokz->buffer.len=(len>0 ? (uint)len : strlen(tokz->buffer.data)); |
866 tokz->buffer.len=(len>0 ? (uint)len : strlen(tokz->buffer.data)); |
867 tokz->buffer.pos=0; |
867 tokz->buffer.pos=0; |
868 |
868 |
869 if(old>0) |
869 if(old>0) |
870 buffer[len-1]=old; |
870 buffer[len-1]=old; |
871 |
871 |
872 return tokz; |
872 return tokz; |
873 } |
873 } |
874 |
874 |
875 /* |
875 /* |
876 * File close |
876 * File close |
877 */ |
877 */ |
878 |
878 |
879 static bool do_tokz_popf(Tokenizer *tokz, bool shrink) |
879 static bool do_tokz_popf(Tokenizer *tokz, bool shrink) |
880 { |
880 { |
881 Tokenizer_FInfo *finfo; |
881 Tokenizer_FInfo *finfo; |
882 |
882 |
883 if(tokz->filestack_n<=0) |
883 if(tokz->filestack_n<=0) |
884 return FALSE; |
884 return FALSE; |
885 |
885 |
886 if(tokz->file!=NULL) |
886 if(tokz->file!=NULL) |
887 fclose(tokz->file); |
887 fclose(tokz->file); |
888 if(tokz->name!=NULL) |
888 if(tokz->name!=NULL) |
889 free(tokz->name); |
889 free(tokz->name); |
890 |
890 |
891 finfo=&(tokz->filestack[--tokz->filestack_n]); |
891 finfo=&(tokz->filestack[--tokz->filestack_n]); |
892 |
892 |
893 tokz->file=finfo->file; |
893 tokz->file=finfo->file; |
894 tokz->name=finfo->name; |
894 tokz->name=finfo->name; |
895 tokz->line=finfo->line; |
895 tokz->line=finfo->line; |
896 tokz->ungetc=finfo->ungetc; |
896 tokz->ungetc=finfo->ungetc; |
897 tokz->ungettok=finfo->ungettok; |
897 tokz->ungettok=finfo->ungettok; |
898 |
898 |
899 if(tokz->filestack_n==0){ |
899 if(tokz->filestack_n==0){ |
900 free(tokz->filestack); |
900 free(tokz->filestack); |
901 tokz->filestack=NULL; |
901 tokz->filestack=NULL; |
902 }else if(shrink){ |
902 }else if(shrink){ |
903 finfo=REALLOC_N(tokz->filestack, Tokenizer_FInfo, |
903 finfo=REALLOC_N(tokz->filestack, Tokenizer_FInfo, |
904 tokz->filestack_n+1, tokz->filestack_n); |
904 tokz->filestack_n+1, tokz->filestack_n); |
905 if(finfo==NULL) |
905 if(finfo==NULL) |
906 warn_err(); |
906 warn_err(); |
907 else |
907 else |
908 tokz->filestack=finfo; |
908 tokz->filestack=finfo; |
909 } |
909 } |
910 |
910 |
911 return TRUE; |
911 return TRUE; |
912 } |
912 } |
913 |
913 |
914 |
914 |
915 bool tokz_popf(Tokenizer *tokz) |
915 bool tokz_popf(Tokenizer *tokz) |
916 { |
916 { |
917 return do_tokz_popf(tokz, TRUE); |
917 return do_tokz_popf(tokz, TRUE); |
918 } |
918 } |
919 |
919 |
920 |
920 |
921 void tokz_close(Tokenizer *tokz) |
921 void tokz_close(Tokenizer *tokz) |
922 { |
922 { |
923 while(tokz->filestack_n>0) |
923 while(tokz->filestack_n>0) |
924 do_tokz_popf(tokz, FALSE); |
924 do_tokz_popf(tokz, FALSE); |
925 |
925 |
926 if(tokz->file!=NULL) |
926 if(tokz->file!=NULL) |
927 fclose(tokz->file); |
927 fclose(tokz->file); |
928 if(tokz->name!=NULL) |
928 if(tokz->name!=NULL) |
929 free(tokz->name); |
929 free(tokz->name); |
930 tok_free(&(tokz->ungettok)); |
930 tok_free(&(tokz->ungettok)); |
931 |
931 |
932 free(tokz); |
932 free(tokz); |
933 } |
933 } |
934 |
934 |
935 |
935 |
936 |
936 |
937 /* */ |
937 /* */ |
938 |
938 |
939 |
939 |
940 void tok_free(Token *tok) |
940 void tok_free(Token *tok) |
941 { |
941 { |
942 if(TOK_IS_STRING(tok) || TOK_IS_IDENT(tok) || TOK_IS_COMMENT(tok)){ |
942 if(TOK_IS_STRING(tok) || TOK_IS_IDENT(tok) || TOK_IS_COMMENT(tok)){ |
943 if(TOK_STRING_VAL(tok)!=NULL) |
943 if(TOK_STRING_VAL(tok)!=NULL) |
944 free(TOK_STRING_VAL(tok)); |
944 free(TOK_STRING_VAL(tok)); |
945 } |
945 } |
946 |
946 |
947 tok->type=TOK_INVALID; |
947 tok->type=TOK_INVALID; |
948 } |
948 } |
949 |
949 |
950 |
950 |
951 void tok_init(Token *tok) |
951 void tok_init(Token *tok) |
952 { |
952 { |
953 static Token dummy=TOK_INIT; |
953 static Token dummy=TOK_INIT; |
954 |
954 |
955 memcpy(tok, &dummy, sizeof(*tok)); |
955 memcpy(tok, &dummy, sizeof(*tok)); |
956 } |
956 } |
957 |
957 |