Mercurial > ~dholland > hg > tradcpp > index.cgi
comparison directive.c @ 164:f14f5352956c
Merge upstream into Joerg's changes.
author | David A. Holland |
---|---|
date | Fri, 12 Jun 2015 01:00:38 -0400 |
parents | d6e6b3940780 a2c2fe8dbea3 |
children | cc6d6f27d6ee |
comparison
equal
deleted
inserted
replaced
163:e1dfa3f90b6c | 164:f14f5352956c |
---|---|
173 ifstate_destroy(is); | 173 ifstate_destroy(is); |
174 } | 174 } |
175 | 175 |
176 static | 176 static |
177 void | 177 void |
178 d_if(struct place *p, struct place *p2, struct place *np, char *line) | 178 d_if(struct lineplace *lp, struct place *p2, char *line) |
179 { | 179 { |
180 char *expr; | 180 char *expr; |
181 bool val; | 181 bool val; |
182 struct place p3 = *p2; | 182 struct place p3 = *p2; |
183 size_t oldlen; | 183 size_t oldlen; |
192 if (ifstate->curtrue) { | 192 if (ifstate->curtrue) { |
193 val = eval(&p3, expr); | 193 val = eval(&p3, expr); |
194 } else { | 194 } else { |
195 val = 0; | 195 val = 0; |
196 } | 196 } |
197 ifstate_push(p, val); | 197 ifstate_push(&lp->current, val); |
198 dostrfree(expr); | 198 dostrfree(expr); |
199 } | 199 } |
200 | 200 |
201 static | 201 static |
202 void | 202 void |
203 d_ifdef(struct place *p, struct place *p2, struct place *np, char *line) | 203 d_ifdef(struct lineplace *lp, struct place *p2, char *line) |
204 { | 204 { |
205 uncomment(line); | 205 uncomment(line); |
206 oneword("#ifdef", p2, line); | 206 oneword("#ifdef", p2, line); |
207 ifstate_push(p, macro_isdefined(line)); | 207 ifstate_push(&lp->current, macro_isdefined(line)); |
208 } | 208 } |
209 | 209 |
210 static | 210 static |
211 void | 211 void |
212 d_ifndef(struct place *p, struct place *p2, struct place *np, char *line) | 212 d_ifndef(struct lineplace *lp, struct place *p2, char *line) |
213 { | 213 { |
214 uncomment(line); | 214 uncomment(line); |
215 oneword("#ifndef", p2, line); | 215 oneword("#ifndef", p2, line); |
216 ifstate_push(p, !macro_isdefined(line)); | 216 ifstate_push(&lp->current, !macro_isdefined(line)); |
217 } | 217 } |
218 | 218 |
219 static | 219 static |
220 void | 220 void |
221 d_elif(struct place *p, struct place *p2, struct place *np, char *line) | 221 d_elif(struct lineplace *lp, struct place *p2, char *line) |
222 { | 222 { |
223 char *expr; | 223 char *expr; |
224 struct place p3 = *p2; | 224 struct place p3 = *p2; |
225 size_t oldlen; | 225 size_t oldlen; |
226 | 226 |
227 if (ifstate->seenelse) { | 227 if (ifstate->seenelse) { |
228 complain(p, "#elif after #else"); | 228 complain(&lp->current, "#elif after #else"); |
229 complain_fail(); | 229 complain_fail(); |
230 } | 230 } |
231 | 231 |
232 if (ifstate->evertrue) { | 232 if (ifstate->evertrue) { |
233 ifstate->curtrue = false; | 233 ifstate->curtrue = false; |
245 } | 245 } |
246 } | 246 } |
247 | 247 |
248 static | 248 static |
249 void | 249 void |
250 d_else(struct place *p, struct place *p2, struct place *np, char *line) | 250 d_else(struct lineplace *lp, struct place *p2, char *line) |
251 { | 251 { |
252 (void)p2; | 252 (void)p2; |
253 (void)line; | 253 (void)line; |
254 | 254 |
255 if (ifstate->seenelse) { | 255 if (ifstate->seenelse) { |
256 complain(p, "Multiple #else directives in one conditional"); | 256 complain(&lp->current, |
257 "Multiple #else directives in one conditional"); | |
257 complain_fail(); | 258 complain_fail(); |
258 } | 259 } |
259 | 260 |
260 ifstate->curtrue = !ifstate->evertrue; | 261 ifstate->curtrue = !ifstate->evertrue; |
261 ifstate->evertrue = true; | 262 ifstate->evertrue = true; |
262 ifstate->seenelse = true; | 263 ifstate->seenelse = true; |
263 } | 264 } |
264 | 265 |
265 static | 266 static |
266 void | 267 void |
267 d_endif(struct place *p, struct place *p2, struct place *np, char *line) | 268 d_endif(struct lineplace *lp, struct place *p2, char *line) |
268 { | 269 { |
269 (void)p2; | 270 (void)p2; |
270 (void)line; | 271 (void)line; |
271 | 272 |
272 if (ifstate->prev == NULL) { | 273 if (ifstate->prev == NULL) { |
273 complain(p, "Unmatched #endif"); | 274 complain(&lp->current, "Unmatched #endif"); |
274 complain_fail(); | 275 complain_fail(); |
275 } else { | 276 } else { |
276 ifstate_pop(); | 277 ifstate_pop(); |
277 } | 278 } |
278 } | 279 } |
280 //////////////////////////////////////////////////////////// | 281 //////////////////////////////////////////////////////////// |
281 // macros | 282 // macros |
282 | 283 |
283 static | 284 static |
284 void | 285 void |
285 d_define(struct place *p, struct place *p2, struct place *np, char *line) | 286 d_define(struct lineplace *lp, struct place *p2, char *line) |
286 { | 287 { |
287 size_t pos, argpos; | 288 size_t pos, argpos; |
288 struct place p3, p4; | 289 struct place p3, p4; |
289 | 290 |
290 (void)p; | 291 (void)lp; |
291 | 292 |
292 /* | 293 /* |
293 * line may be: | 294 * line may be: |
294 * macro expansion | 295 * macro expansion |
295 * macro(arg, arg, ...) expansion | 296 * macro(arg, arg, ...) expansion |
345 } | 346 } |
346 } | 347 } |
347 | 348 |
348 static | 349 static |
349 void | 350 void |
350 d_undef(struct place *p, struct place *p2, struct place *np, char *line) | 351 d_undef(struct lineplace *lp, struct place *p2, char *line) |
351 { | 352 { |
352 (void)p; | 353 (void)lp; |
353 | 354 |
354 uncomment(line); | 355 uncomment(line); |
355 oneword("#undef", p2, line); | 356 oneword("#undef", p2, line); |
356 macro_undef(line); | 357 macro_undef(line); |
357 } | 358 } |
381 return false; | 382 return false; |
382 } | 383 } |
383 | 384 |
384 static | 385 static |
385 void | 386 void |
386 d_include(struct place *p, struct place *p2, struct place *np, char *line) | 387 d_include(struct lineplace *lp, struct place *p2, char *line) |
387 { | 388 { |
388 char *text; | 389 char *text; |
389 size_t oldlen; | 390 size_t oldlen; |
390 | 391 |
391 uncomment(line); | 392 uncomment(line); |
392 if (tryinclude(p, line)) { | 393 if (tryinclude(&lp->current, line)) { |
393 return; | 394 return; |
394 } | 395 } |
395 text = macroexpand(p2, line, strlen(line), false); | 396 text = macroexpand(p2, line, strlen(line), false); |
396 | 397 |
397 oldlen = strlen(text); | 398 oldlen = strlen(text); |
398 uncomment(text); | 399 uncomment(text); |
399 /* trim to fit, so the malloc debugging won't complain */ | 400 /* trim to fit, so the malloc debugging won't complain */ |
400 text = dorealloc(text, oldlen + 1, strlen(text) + 1); | 401 text = dorealloc(text, oldlen + 1, strlen(text) + 1); |
401 | 402 |
402 if (tryinclude(p, text)) { | 403 if (tryinclude(&lp->current, text)) { |
403 dostrfree(text); | 404 dostrfree(text); |
404 return; | 405 return; |
405 } | 406 } |
406 complain(p, "Illegal #include directive"); | 407 complain(&lp->current, "Illegal #include directive"); |
407 complain(p, "Before macro expansion: #include %s", line); | 408 complain(&lp->current, "Before macro expansion: #include %s", line); |
408 complain(p, "After macro expansion: #include %s", text); | 409 complain(&lp->current, "After macro expansion: #include %s", text); |
409 dostrfree(text); | 410 dostrfree(text); |
410 complain_fail(); | 411 complain_fail(); |
411 } | 412 } |
412 | 413 |
413 static | 414 static |
414 void | 415 void |
415 d_line(struct place *p, struct place *p2, struct place *np, char *line) | 416 d_line(struct lineplace *lp, struct place *p2, char *line) |
416 { | 417 { |
417 char *text; | 418 char *text; |
418 size_t oldlen; | 419 size_t oldlen; |
419 const char *token, *start_lineno, *start_filename; | 420 const char *token, *start_lineno, *start_filename; |
420 size_t len_lineno, len_filename; | 421 size_t len_lineno, len_filename; |
453 token += strspn(token, ws); | 454 token += strspn(token, ws); |
454 if (*token != '\0') { | 455 if (*token != '\0') { |
455 goto illegal_line; | 456 goto illegal_line; |
456 } | 457 } |
457 } | 458 } |
458 np->line = atoi(start_lineno); | 459 lp->nextline.line = atoi(start_lineno); |
459 if (len_filename) { | 460 if (len_filename) { |
460 char *filename = dostrndup(start_filename, len_filename); | 461 char *filename = dostrndup(start_filename, len_filename); |
461 place_setfile(np, filename); | 462 place_setfile(&lp->nextline, filename); |
462 dostrfree(filename); | 463 dostrfree(filename); |
463 } | 464 } |
464 dostrfree(text); | 465 dostrfree(text); |
465 return; | 466 return; |
466 | 467 |
467 illegal_line: | 468 illegal_line: |
468 complain(p, "Illegal #line directive"); | 469 complain(&lp->current, "Illegal #line directive"); |
469 complain(p, "Before macro expansion: #include %s", line); | 470 complain(&lp->current, "Before macro expansion: #include %s", line); |
470 complain(p, "After macro expansion: #include %s", text); | 471 complain(&lp->current, "After macro expansion: #include %s", text); |
471 dostrfree(text); | 472 dostrfree(text); |
472 } | 473 } |
473 | 474 |
474 //////////////////////////////////////////////////////////// | 475 //////////////////////////////////////////////////////////// |
475 // messages | 476 // messages |
476 | 477 |
477 static | 478 static |
478 void | 479 void |
479 d_warning(struct place *p, struct place *p2, struct place *np, char *line) | 480 d_warning(struct lineplace *lp, struct place *p2, char *line) |
480 { | 481 { |
481 char *msg; | 482 char *msg; |
482 | 483 |
483 msg = macroexpand(p2, line, strlen(line), false); | 484 msg = macroexpand(p2, line, strlen(line), false); |
484 complain(p, "#warning: %s", msg); | 485 complain(&lp->current, "#warning: %s", msg); |
485 if (mode.werror) { | 486 if (mode.werror) { |
486 complain_fail(); | 487 complain_fail(); |
487 } | 488 } |
488 dostrfree(msg); | 489 dostrfree(msg); |
489 } | 490 } |
490 | 491 |
491 static | 492 static |
492 void | 493 void |
493 d_error(struct place *p, struct place *p2, struct place *np, char *line) | 494 d_error(struct lineplace *lp, struct place *p2, char *line) |
494 { | 495 { |
495 char *msg; | 496 char *msg; |
496 | 497 |
497 msg = macroexpand(p2, line, strlen(line), false); | 498 msg = macroexpand(p2, line, strlen(line), false); |
498 complain(p, "#error: %s", msg); | 499 complain(&lp->current, "#error: %s", msg); |
499 complain_fail(); | 500 complain_fail(); |
500 dostrfree(msg); | 501 dostrfree(msg); |
501 } | 502 } |
502 | 503 |
503 //////////////////////////////////////////////////////////// | 504 //////////////////////////////////////////////////////////// |
504 // other | 505 // other |
505 | 506 |
506 static | 507 static |
507 void | 508 void |
508 d_pragma(struct place *p, struct place *p2, struct place *np, char *line) | 509 d_pragma(struct lineplace *lp, struct place *p2, char *line) |
509 { | 510 { |
510 (void)p2; | 511 (void)p2; |
511 | 512 |
512 complain(p, "#pragma %s", line); | 513 complain(&lp->current, "#pragma %s", line); |
513 complain_fail(); | 514 complain_fail(); |
514 } | 515 } |
515 | 516 |
516 //////////////////////////////////////////////////////////// | 517 //////////////////////////////////////////////////////////// |
517 // directive table | 518 // directive table |
518 | 519 |
519 static const struct { | 520 static const struct { |
520 const char *name; | 521 const char *name; |
521 bool ifskip; | 522 bool ifskip; |
522 void (*func)(struct place *, struct place *, struct place *, | 523 void (*func)(struct lineplace *, struct place *, char *line); |
523 char *line); | |
524 } directives[] = { | 524 } directives[] = { |
525 { "define", true, d_define }, | 525 { "define", true, d_define }, |
526 { "elif", false, d_elif }, | 526 { "elif", false, d_elif }, |
527 { "else", false, d_else }, | 527 { "else", false, d_else }, |
528 { "endif", false, d_endif }, | 528 { "endif", false, d_endif }, |
538 }; | 538 }; |
539 static const unsigned numdirectives = HOWMANY(directives); | 539 static const unsigned numdirectives = HOWMANY(directives); |
540 | 540 |
541 static | 541 static |
542 void | 542 void |
543 directive_gotdirective(struct place *p, struct place *np, char *line) | 543 directive_gotdirective(struct lineplace *lp, char *line) |
544 { | 544 { |
545 struct place p2; | 545 struct place p2; |
546 size_t len, skip; | 546 size_t len, skip; |
547 unsigned i; | 547 unsigned i; |
548 | 548 |
549 p2 = *p; | 549 p2 = lp->current; |
550 for (i=0; i<numdirectives; i++) { | 550 for (i=0; i<numdirectives; i++) { |
551 len = strlen(directives[i].name); | 551 len = strlen(directives[i].name); |
552 if (!strncmp(line, directives[i].name, len) && | 552 if (!strncmp(line, directives[i].name, len) && |
553 strchr(ws, line[len])) { | 553 strchr(ws, line[len])) { |
554 if (directives[i].ifskip && !ifstate->curtrue) { | 554 if (directives[i].ifskip && !ifstate->curtrue) { |
561 len = strlen(line); | 561 len = strlen(line); |
562 len = notrailingws(line, len); | 562 len = notrailingws(line, len); |
563 if (len < strlen(line)) { | 563 if (len < strlen(line)) { |
564 line[len] = '\0'; | 564 line[len] = '\0'; |
565 } | 565 } |
566 directives[i].func(p, &p2, np, line); | 566 directives[i].func(lp, &p2, line); |
567 return; | 567 return; |
568 } | 568 } |
569 } | 569 } |
570 /* ugh. allow # by itself, including with a comment after it */ | 570 /* ugh. allow # by itself, including with a comment after it */ |
571 uncomment(line); | 571 uncomment(line); |
572 if (line[0] == '\0') { | 572 if (line[0] == '\0') { |
573 return; | 573 return; |
574 } | 574 } |
575 | 575 |
576 skip = strcspn(line, ws); | 576 skip = strcspn(line, ws); |
577 complain(p, "Unknown directive #%.*s", (int)skip, line); | 577 complain(&lp->current, "Unknown directive #%.*s", (int)skip, line); |
578 complain_fail(); | 578 complain_fail(); |
579 } | 579 } |
580 | 580 |
581 /* | 581 /* |
582 * Check for nested comment delimiters in LINE. | 582 * Check for nested comment delimiters in LINE. |
583 */ | 583 */ |
584 static | 584 static |
585 size_t | 585 size_t |
586 directive_scancomments(const struct place *p, char *line, size_t len) | 586 directive_scancomments(const struct lineplace *lp, char *line, size_t len) |
587 { | 587 { |
588 size_t pos; | 588 size_t pos; |
589 bool incomment; | 589 bool incomment; |
590 struct place p2; | 590 struct place p2; |
591 | 591 |
592 p2 = *p; | 592 p2 = lp->current; |
593 incomment = 0; | 593 incomment = 0; |
594 for (pos = 0; pos+1 < len; pos++) { | 594 for (pos = 0; pos+1 < len; pos++) { |
595 if (line[pos] == '/' && line[pos+1] == '*') { | 595 if (line[pos] == '/' && line[pos+1] == '*') { |
596 if (incomment) { | 596 if (incomment) { |
597 complain(&p2, "Warning: %c%c within comment", | 597 complain(&p2, "Warning: %c%c within comment", |
623 assert(!incomment); | 623 assert(!incomment); |
624 return len; | 624 return len; |
625 } | 625 } |
626 | 626 |
627 void | 627 void |
628 directive_gotline(struct place *p, struct place *np, char *line, size_t len) | 628 directive_gotline(struct lineplace *lp, char *line, size_t len) |
629 { | 629 { |
630 size_t skip; | 630 size_t skip; |
631 | 631 |
632 if (warns.nestcomment) { | 632 if (warns.nestcomment) { |
633 directive_scancomments(p, line, len); | 633 directive_scancomments(lp, line, len); |
634 } | 634 } |
635 | 635 |
636 /* check if we have a directive line (# exactly in column 0) */ | 636 /* check if we have a directive line (# exactly in column 0) */ |
637 if (line[0] == '#') { | 637 if (line[0] == '#') { |
638 skip = 1 + strspn(line + 1, ws); | 638 skip = 1 + strspn(line + 1, ws); |
639 assert(skip <= len); | 639 assert(skip <= len); |
640 p->column += skip; | 640 lp->current.column += skip; |
641 assert(line[len] == '\0'); | 641 assert(line[len] == '\0'); |
642 directive_gotdirective(p, np, line+skip); | 642 directive_gotdirective(lp, line+skip /*, length = len-skip */); |
643 p->column += len-skip; | 643 lp->current.column += len-skip; |
644 } else if (ifstate->curtrue) { | 644 } else if (ifstate->curtrue) { |
645 macro_sendline(p, line, len); | 645 macro_sendline(&lp->current, line, len); |
646 p->column += len; | 646 lp->current.column += len; |
647 } | 647 } |
648 } | 648 } |
649 | 649 |
650 void | 650 void |
651 directive_goteof(struct place *p) | 651 directive_goteof(struct place *p) |