comparison lwcc/preproc.c @ 308:670ea8f90212 ccdev

Converted preproc logic to library and moved some utility stuff to lwlib The strbuf and strpool stuff is generally useful so move it to lwlib where other such things live. Also, package the preprocessor logic into a library for easy use in multiple places.
author William Astle <lost@l-w.ca>
date Sat, 21 Sep 2013 13:33:54 -0600
parents 9e342c4e4b66
children 73b2bfa17ab0
comparison
equal deleted inserted replaced
307:9e342c4e4b66 308:670ea8f90212
25 #include <time.h> 25 #include <time.h>
26 #include <unistd.h> 26 #include <unistd.h>
27 27
28 #include <lw_alloc.h> 28 #include <lw_alloc.h>
29 #include <lw_string.h> 29 #include <lw_string.h>
30 #include <lw_strbuf.h>
31 #include <lw_strpool.h>
30 32
31 #include "cpp.h" 33 #include "cpp.h"
32 #include "strbuf.h"
33 #include "strpool.h"
34 #include "symbol.h" 34 #include "symbol.h"
35 #include "token.h" 35 #include "token.h"
36 36
37 static int expand_macro(struct preproc_info *, char *); 37 static int expand_macro(struct preproc_info *, char *);
38 static void process_directive(struct preproc_info *); 38 static void process_directive(struct preproc_info *);
39 static long eval_expr(struct preproc_info *); 39 static long eval_expr(struct preproc_info *);
40 extern struct token *preproc_lex_next_token(struct preproc_info *); 40 extern struct token *preproc_lex_next_token(struct preproc_info *);
41 static long preproc_numval(struct preproc_info *, struct token *);
42 static int eval_escape(char **);
41 43
42 44
43 struct token *preproc_next_processed_token(struct preproc_info *pp) 45 struct token *preproc_next_processed_token(struct preproc_info *pp)
44 { 46 {
45 struct token *ct; 47 struct token *ct;
422 check_eol(pp); 424 check_eol(pp);
423 } 425 }
424 426
425 char *streol(struct preproc_info *pp) 427 char *streol(struct preproc_info *pp)
426 { 428 {
427 struct strbuf *s; 429 struct lw_strbuf *s;
428 struct token *ct; 430 struct token *ct;
429 int i; 431 int i;
430 432
431 s = strbuf_new(); 433 s = lw_strbuf_new();
432 do 434 do
433 { 435 {
434 ct = preproc_next_token(pp); 436 ct = preproc_next_token(pp);
435 } while (ct -> ttype == TOK_WSPACE); 437 } while (ct -> ttype == TOK_WSPACE);
436 438
437 while (ct -> ttype != TOK_EOL) 439 while (ct -> ttype != TOK_EOL)
438 { 440 {
439 for (i = 0; ct -> strval[i]; i++) 441 for (i = 0; ct -> strval[i]; i++)
440 strbuf_add(s, ct -> strval[i]); 442 lw_strbuf_add(s, ct -> strval[i]);
441 ct = preproc_next_token(pp); 443 ct = preproc_next_token(pp);
442 } 444 }
443 return strbuf_end(s); 445 return lw_strbuf_end(s);
444 } 446 }
445 447
446 static void dir_error(struct preproc_info *pp) 448 static void dir_error(struct preproc_info *pp)
447 { 449 {
448 char *s; 450 char *s;
542 { 544 {
543 FILE *fp; 545 FILE *fp;
544 struct token *ct; 546 struct token *ct;
545 int sys = 0; 547 int sys = 0;
546 char *fn; 548 char *fn;
547 struct strbuf *strbuf; 549 struct lw_strbuf *strbuf;
548 int i; 550 int i;
549 struct preproc_info *fs; 551 struct preproc_info *fs;
550 552
551 ct = preproc_next_token_nws(pp); 553 ct = preproc_next_token_nws(pp);
552 if (ct -> ttype == TOK_STR_LIT) 554 if (ct -> ttype == TOK_STR_LIT)
559 sys = 0; 561 sys = 0;
560 goto doinc; 562 goto doinc;
561 } 563 }
562 else if (ct -> ttype == TOK_LT) 564 else if (ct -> ttype == TOK_LT)
563 { 565 {
564 strbuf = strbuf_new(); 566 strbuf = lw_strbuf_new();
565 for (;;) 567 for (;;)
566 { 568 {
567 int c; 569 int c;
568 c = preproc_lex_fetch_byte(pp); 570 c = preproc_lex_fetch_byte(pp);
569 if (c == CPP_EOL) 571 if (c == CPP_EOL)
570 { 572 {
571 preproc_lex_unfetch_byte(pp, c); 573 preproc_lex_unfetch_byte(pp, c);
572 preproc_throw_error(pp, "Bad #include"); 574 preproc_throw_error(pp, "Bad #include");
573 lw_free(strbuf_end(strbuf)); 575 lw_free(lw_strbuf_end(strbuf));
574 break; 576 break;
575 } 577 }
576 if (c == '>') 578 if (c == '>')
577 break; 579 break;
578 strbuf_add(strbuf, c); 580 lw_strbuf_add(strbuf, c);
579 } 581 }
580 ct = preproc_next_token_nws(pp); 582 ct = preproc_next_token_nws(pp);
581 if (ct -> ttype != TOK_EOL) 583 if (ct -> ttype != TOK_EOL)
582 { 584 {
583 preproc_throw_error(pp, "Bad #include"); 585 preproc_throw_error(pp, "Bad #include");
584 skip_eol(pp); 586 skip_eol(pp);
585 lw_free(strbuf_end(strbuf)); 587 lw_free(lw_strbuf_end(strbuf));
586 return; 588 return;
587 } 589 }
588 sys = 1; 590 sys = 1;
589 fn = strbuf_end(strbuf); 591 fn = lw_strbuf_end(strbuf);
590 goto doinc; 592 goto doinc;
591 } 593 }
592 else 594 else
593 { 595 {
594 preproc_unget_token(pp, ct); 596 preproc_unget_token(pp, ct);
596 ct = preproc_next_processed_token_nws(pp); 598 ct = preproc_next_processed_token_nws(pp);
597 if (ct -> ttype == TOK_STR_LIT) 599 if (ct -> ttype == TOK_STR_LIT)
598 goto usrinc; 600 goto usrinc;
599 else if (ct -> ttype == TOK_LT) 601 else if (ct -> ttype == TOK_LT)
600 { 602 {
601 strbuf = strbuf_new(); 603 strbuf = lw_strbuf_new();
602 for (;;) 604 for (;;)
603 { 605 {
604 ct = preproc_next_processed_token(pp); 606 ct = preproc_next_processed_token(pp);
605 if (ct -> ttype == TOK_GT) 607 if (ct -> ttype == TOK_GT)
606 break; 608 break;
607 if (ct -> ttype == TOK_EOL) 609 if (ct -> ttype == TOK_EOL)
608 { 610 {
609 preproc_throw_error(pp, "Bad #include"); 611 preproc_throw_error(pp, "Bad #include");
610 lw_free(strbuf_end(strbuf)); 612 lw_free(lw_strbuf_end(strbuf));
611 return; 613 return;
612 } 614 }
613 for (i = 0; ct -> strval[i]; ct++) 615 for (i = 0; ct -> strval[i]; ct++)
614 { 616 {
615 strbuf_add(strbuf, ct -> strval[i]); 617 lw_strbuf_add(strbuf, ct -> strval[i]);
616 } 618 }
617 } 619 }
618 ct = preproc_next_processed_token_nws(pp); 620 ct = preproc_next_processed_token_nws(pp);
619 if (ct -> ttype != TOK_EOL) 621 if (ct -> ttype != TOK_EOL)
620 { 622 {
621 preproc_throw_error(pp, "Bad #include"); 623 preproc_throw_error(pp, "Bad #include");
622 skip_eol(pp); 624 skip_eol(pp);
623 lw_free(strbuf_end(strbuf)); 625 lw_free(lw_strbuf_end(strbuf));
624 return; 626 return;
625 } 627 }
626 sys = 1; 628 sys = 1;
627 fn = strbuf_end(strbuf); 629 fn = lw_strbuf_end(strbuf);
628 goto doinc; 630 goto doinc;
629 } 631 }
630 else 632 else
631 { 633 {
632 skip_eol(pp); 634 skip_eol(pp);
651 fs = lw_alloc(sizeof(struct preproc_info)); 653 fs = lw_alloc(sizeof(struct preproc_info));
652 *fs = *pp; 654 *fs = *pp;
653 fs -> n = pp -> filestack; 655 fs -> n = pp -> filestack;
654 pp -> curtok = NULL; 656 pp -> curtok = NULL;
655 pp -> filestack = fs; 657 pp -> filestack = fs;
656 pp -> fn = strpool_strdup(pp -> strpool, fn); 658 pp -> fn = lw_strpool_strdup(pp -> strpool, fn);
657 lw_free(fn); 659 lw_free(fn);
658 pp -> fp = fp; 660 pp -> fp = fp;
659 pp -> ra = CPP_NOUNG; 661 pp -> ra = CPP_NOUNG;
660 pp -> ppeolseen = 1; 662 pp -> ppeolseen = 1;
661 pp -> eolstate = 0; 663 pp -> eolstate = 0;
768 770
769 // NULL directive 771 // NULL directive
770 if (ct -> ttype == TOK_EOL) 772 if (ct -> ttype == TOK_EOL)
771 return; 773 return;
772 774
775 if (ct -> ttype == TOK_NUMBER)
776 {
777 // this is probably a file marker from a previous run of the preprocessor
778 char *fn;
779 struct lw_strbuf *sb;
780
781 i = preproc_numval(pp, ct);
782 ct = preproc_next_token_nws(pp);
783 if (ct -> ttype != TOK_STR_LIT)
784 goto baddir;
785 pp -> lineno = i;
786 sb = lw_strbuf_new();
787 for (fn = ct -> strval; *fn && *fn != '"'; )
788 {
789 if (*fn == '\\')
790 {
791 lw_strbuf_add(sb, eval_escape(&fn));
792 }
793 else
794 {
795 lw_strbuf_add(sb, *fn++);
796 }
797 }
798 fn = lw_strbuf_end(sb);
799 pp -> fn = lw_strpool_strdup(pp -> strpool, fn);
800 lw_free(fn);
801 skip_eol(pp);
802 return;
803 }
804
773 if (ct -> ttype != TOK_IDENT) 805 if (ct -> ttype != TOK_IDENT)
774 goto baddir; 806 goto baddir;
775 807
776 for (i = 0; dirlist[i].name; i++) 808 for (i = 0; dirlist[i].name; i++)
777 { 809 {
798 skip_eol(pp); 830 skip_eol(pp);
799 preproc_unget_token(pp, pp -> curtok); 831 preproc_unget_token(pp, pp -> curtok);
800 } 832 }
801 833
802 static long eval_expr_real(struct preproc_info *, int); 834 static long eval_expr_real(struct preproc_info *, int);
803 static long preproc_numval(struct preproc_info *, struct token *);
804 835
805 static long eval_term_real(struct preproc_info *pp) 836 static long eval_term_real(struct preproc_info *pp)
806 { 837 {
807 long tval = 0; 838 long tval = 0;
808 struct token *ct; 839 struct token *ct;
1163 /* 1194 /*
1164 Below here is the logic for expanding a macro 1195 Below here is the logic for expanding a macro
1165 */ 1196 */
1166 static char *stringify(struct token_list *tli) 1197 static char *stringify(struct token_list *tli)
1167 { 1198 {
1168 struct strbuf *s; 1199 struct lw_strbuf *s;
1169 int ws = 0; 1200 int ws = 0;
1170 struct token *tl = tli -> head; 1201 struct token *tl = tli -> head;
1171 1202
1172 s = strbuf_new(); 1203 s = lw_strbuf_new();
1173 strbuf_add(s, '"'); 1204 lw_strbuf_add(s, '"');
1174 1205
1175 while (tl && tl -> ttype == TOK_WSPACE) 1206 while (tl && tl -> ttype == TOK_WSPACE)
1176 tl = tl -> next; 1207 tl = tl -> next;
1177 1208
1178 for (; tl; tl = tl -> next) 1209 for (; tl; tl = tl -> next)
1182 ws = 1; 1213 ws = 1;
1183 continue; 1214 continue;
1184 } 1215 }
1185 if (ws) 1216 if (ws)
1186 { 1217 {
1187 strbuf_add(s, ' '); 1218 lw_strbuf_add(s, ' ');
1188 } 1219 }
1189 for (ws = 0; tl -> strval[ws]; ws++) 1220 for (ws = 0; tl -> strval[ws]; ws++)
1190 { 1221 {
1191 if (tl -> ttype == TOK_STR_LIT || tl -> ttype == TOK_CHR_LIT) 1222 if (tl -> ttype == TOK_STR_LIT || tl -> ttype == TOK_CHR_LIT)
1192 { 1223 {
1193 if (tl -> strval[ws] == '"' || tl -> strval[ws] == '\\') 1224 if (tl -> strval[ws] == '"' || tl -> strval[ws] == '\\')
1194 strbuf_add(s, '\\'); 1225 lw_strbuf_add(s, '\\');
1195 } 1226 }
1196 } 1227 }
1197 ws = 0; 1228 ws = 0;
1198 } 1229 }
1199 1230
1200 strbuf_add(s, '"'); 1231 lw_strbuf_add(s, '"');
1201 return strbuf_end(s); 1232 return lw_strbuf_end(s);
1202 } 1233 }
1203 1234
1204 static int macro_arg(struct symtab_e *s, char *str) 1235 static int macro_arg(struct symtab_e *s, char *str)
1205 { 1236 {
1206 int i; 1237 int i;
1337 struct token_list *rtl; 1368 struct token_list *rtl;
1338 1369
1339 // check for built in macros 1370 // check for built in macros
1340 if (strcmp(mname, "__FILE__") == 0) 1371 if (strcmp(mname, "__FILE__") == 0)
1341 { 1372 {
1342 struct strbuf *sb; 1373 struct lw_strbuf *sb;
1343 1374
1344 sb = strbuf_new(); 1375 sb = lw_strbuf_new();
1345 strbuf_add(sb, '"'); 1376 lw_strbuf_add(sb, '"');
1346 for (tstr = (char *)(pp -> fn); *tstr; tstr++) 1377 for (tstr = (char *)(pp -> fn); *tstr; tstr++)
1347 { 1378 {
1348 if (*tstr == 32 || (*tstr > 34 && *tstr < 127)) 1379 if (*tstr == 32 || (*tstr > 34 && *tstr < 127))
1349 { 1380 {
1350 strbuf_add(sb, *tstr); 1381 lw_strbuf_add(sb, *tstr);
1351 } 1382 }
1352 else 1383 else
1353 { 1384 {
1354 strbuf_add(sb, '\\'); 1385 lw_strbuf_add(sb, '\\');
1355 strbuf_add(sb, (*tstr >> 6) + '0'); 1386 lw_strbuf_add(sb, (*tstr >> 6) + '0');
1356 strbuf_add(sb, ((*tstr >> 3) & 7) + '0'); 1387 lw_strbuf_add(sb, ((*tstr >> 3) & 7) + '0');
1357 strbuf_add(sb, (*tstr & 7) + '0'); 1388 lw_strbuf_add(sb, (*tstr & 7) + '0');
1358 } 1389 }
1359 } 1390 }
1360 strbuf_add(sb, '"'); 1391 lw_strbuf_add(sb, '"');
1361 tstr = strbuf_end(sb); 1392 tstr = lw_strbuf_end(sb);
1362 preproc_unget_token(pp, token_create(TOK_STR_LIT, tstr, pp -> lineno, pp -> column, pp -> fn)); 1393 preproc_unget_token(pp, token_create(TOK_STR_LIT, tstr, pp -> lineno, pp -> column, pp -> fn));
1363 lw_free(tstr); 1394 lw_free(tstr);
1364 return 1; 1395 return 1;
1365 } 1396 }
1366 else if (strcmp(mname, "__LINE__") == 0) 1397 else if (strcmp(mname, "__LINE__") == 0)