Mercurial > ~dholland > hg > tradcpp > index.cgi
comparison directive.c @ 160:d6e6b3940780
Fully implement #line.
author | Joerg Sonnenberger <joerg@bec.de> |
---|---|
date | Fri, 27 Feb 2015 02:06:49 +0100 |
parents | 1cda505ddc78 |
children | f14f5352956c |
comparison
equal
deleted
inserted
replaced
159:8cef6d7227a8 | 160:d6e6b3940780 |
---|---|
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, char *line) | 178 d_if(struct place *p, struct place *p2, struct place *np, 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; |
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, char *line) | 203 d_ifdef(struct place *p, struct place *p2, struct place *np, 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(p, macro_isdefined(line)); |
208 } | 208 } |
209 | 209 |
210 static | 210 static |
211 void | 211 void |
212 d_ifndef(struct place *p, struct place *p2, char *line) | 212 d_ifndef(struct place *p, struct place *p2, struct place *np, 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(p, !macro_isdefined(line)); |
217 } | 217 } |
218 | 218 |
219 static | 219 static |
220 void | 220 void |
221 d_elif(struct place *p, struct place *p2, char *line) | 221 d_elif(struct place *p, struct place *p2, struct place *np, 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 |
245 } | 245 } |
246 } | 246 } |
247 | 247 |
248 static | 248 static |
249 void | 249 void |
250 d_else(struct place *p, struct place *p2, char *line) | 250 d_else(struct place *p, struct place *p2, struct place *np, 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) { |
262 ifstate->seenelse = true; | 262 ifstate->seenelse = true; |
263 } | 263 } |
264 | 264 |
265 static | 265 static |
266 void | 266 void |
267 d_endif(struct place *p, struct place *p2, char *line) | 267 d_endif(struct place *p, struct place *p2, struct place *np, char *line) |
268 { | 268 { |
269 (void)p2; | 269 (void)p2; |
270 (void)line; | 270 (void)line; |
271 | 271 |
272 if (ifstate->prev == NULL) { | 272 if (ifstate->prev == NULL) { |
280 //////////////////////////////////////////////////////////// | 280 //////////////////////////////////////////////////////////// |
281 // macros | 281 // macros |
282 | 282 |
283 static | 283 static |
284 void | 284 void |
285 d_define(struct place *p, struct place *p2, char *line) | 285 d_define(struct place *p, struct place *p2, struct place *np, char *line) |
286 { | 286 { |
287 size_t pos, argpos; | 287 size_t pos, argpos; |
288 struct place p3, p4; | 288 struct place p3, p4; |
289 | 289 |
290 (void)p; | 290 (void)p; |
345 } | 345 } |
346 } | 346 } |
347 | 347 |
348 static | 348 static |
349 void | 349 void |
350 d_undef(struct place *p, struct place *p2, char *line) | 350 d_undef(struct place *p, struct place *p2, struct place *np, char *line) |
351 { | 351 { |
352 (void)p; | 352 (void)p; |
353 | 353 |
354 uncomment(line); | 354 uncomment(line); |
355 oneword("#undef", p2, line); | 355 oneword("#undef", p2, line); |
381 return false; | 381 return false; |
382 } | 382 } |
383 | 383 |
384 static | 384 static |
385 void | 385 void |
386 d_include(struct place *p, struct place *p2, char *line) | 386 d_include(struct place *p, struct place *p2, struct place *np, char *line) |
387 { | 387 { |
388 char *text; | 388 char *text; |
389 size_t oldlen; | 389 size_t oldlen; |
390 | 390 |
391 uncomment(line); | 391 uncomment(line); |
410 complain_fail(); | 410 complain_fail(); |
411 } | 411 } |
412 | 412 |
413 static | 413 static |
414 void | 414 void |
415 d_line(struct place *p, struct place *p2, char *line) | 415 d_line(struct place *p, struct place *p2, struct place *np, char *line) |
416 { | 416 { |
417 (void)p2; | 417 char *text; |
418 (void)line; | 418 size_t oldlen; |
419 | 419 const char *token, *start_lineno, *start_filename; |
420 /* XXX */ | 420 size_t len_lineno, len_filename; |
421 complain(p, "Sorry, no #line yet"); | 421 |
422 text = macroexpand(p2, line, strlen(line), true); | |
423 | |
424 oldlen = strlen(text); | |
425 uncomment(text); | |
426 /* trim to fit, so the malloc debugging won't complain */ | |
427 text = dorealloc(text, oldlen + 1, strlen(text) + 1); | |
428 | |
429 token = text; | |
430 token += strspn(token, ws); | |
431 start_lineno = token; | |
432 len_lineno = strspn(token, digits); | |
433 if (len_lineno == 0) { | |
434 goto illegal_line; | |
435 } | |
436 token += len_lineno; | |
437 token += strspn(ws, token); | |
438 if (*token == '"') { | |
439 ++token; | |
440 start_filename = token; | |
441 len_filename = strcspn(token, "\""); | |
442 token += len_filename; | |
443 if (*token != '"' || len_filename == 0) { | |
444 goto illegal_line; | |
445 } | |
446 ++token; | |
447 token += strspn(token, ws); | |
448 if (*token != '\0') { | |
449 goto illegal_line; | |
450 } | |
451 } else { | |
452 len_filename = 0; | |
453 token += strspn(token, ws); | |
454 if (*token != '\0') { | |
455 goto illegal_line; | |
456 } | |
457 } | |
458 np->line = atoi(start_lineno); | |
459 if (len_filename) { | |
460 char *filename = dostrndup(start_filename, len_filename); | |
461 place_setfile(np, filename); | |
462 dostrfree(filename); | |
463 } | |
464 dostrfree(text); | |
465 return; | |
466 | |
467 illegal_line: | |
468 complain(p, "Illegal #line directive"); | |
469 complain(p, "Before macro expansion: #include %s", line); | |
470 complain(p, "After macro expansion: #include %s", text); | |
471 dostrfree(text); | |
422 } | 472 } |
423 | 473 |
424 //////////////////////////////////////////////////////////// | 474 //////////////////////////////////////////////////////////// |
425 // messages | 475 // messages |
426 | 476 |
427 static | 477 static |
428 void | 478 void |
429 d_warning(struct place *p, struct place *p2, char *line) | 479 d_warning(struct place *p, struct place *p2, struct place *np, char *line) |
430 { | 480 { |
431 char *msg; | 481 char *msg; |
432 | 482 |
433 msg = macroexpand(p2, line, strlen(line), false); | 483 msg = macroexpand(p2, line, strlen(line), false); |
434 complain(p, "#warning: %s", msg); | 484 complain(p, "#warning: %s", msg); |
438 dostrfree(msg); | 488 dostrfree(msg); |
439 } | 489 } |
440 | 490 |
441 static | 491 static |
442 void | 492 void |
443 d_error(struct place *p, struct place *p2, char *line) | 493 d_error(struct place *p, struct place *p2, struct place *np, char *line) |
444 { | 494 { |
445 char *msg; | 495 char *msg; |
446 | 496 |
447 msg = macroexpand(p2, line, strlen(line), false); | 497 msg = macroexpand(p2, line, strlen(line), false); |
448 complain(p, "#error: %s", msg); | 498 complain(p, "#error: %s", msg); |
453 //////////////////////////////////////////////////////////// | 503 //////////////////////////////////////////////////////////// |
454 // other | 504 // other |
455 | 505 |
456 static | 506 static |
457 void | 507 void |
458 d_pragma(struct place *p, struct place *p2, char *line) | 508 d_pragma(struct place *p, struct place *p2, struct place *np, char *line) |
459 { | 509 { |
460 (void)p2; | 510 (void)p2; |
461 | 511 |
462 complain(p, "#pragma %s", line); | 512 complain(p, "#pragma %s", line); |
463 complain_fail(); | 513 complain_fail(); |
467 // directive table | 517 // directive table |
468 | 518 |
469 static const struct { | 519 static const struct { |
470 const char *name; | 520 const char *name; |
471 bool ifskip; | 521 bool ifskip; |
472 void (*func)(struct place *, struct place *, char *line); | 522 void (*func)(struct place *, struct place *, struct place *, |
523 char *line); | |
473 } directives[] = { | 524 } directives[] = { |
474 { "define", true, d_define }, | 525 { "define", true, d_define }, |
475 { "elif", false, d_elif }, | 526 { "elif", false, d_elif }, |
476 { "else", false, d_else }, | 527 { "else", false, d_else }, |
477 { "endif", false, d_endif }, | 528 { "endif", false, d_endif }, |
487 }; | 538 }; |
488 static const unsigned numdirectives = HOWMANY(directives); | 539 static const unsigned numdirectives = HOWMANY(directives); |
489 | 540 |
490 static | 541 static |
491 void | 542 void |
492 directive_gotdirective(struct place *p, char *line) | 543 directive_gotdirective(struct place *p, struct place *np, char *line) |
493 { | 544 { |
494 struct place p2; | 545 struct place p2; |
495 size_t len, skip; | 546 size_t len, skip; |
496 unsigned i; | 547 unsigned i; |
497 | 548 |
510 len = strlen(line); | 561 len = strlen(line); |
511 len = notrailingws(line, len); | 562 len = notrailingws(line, len); |
512 if (len < strlen(line)) { | 563 if (len < strlen(line)) { |
513 line[len] = '\0'; | 564 line[len] = '\0'; |
514 } | 565 } |
515 directives[i].func(p, &p2, line); | 566 directives[i].func(p, &p2, np, line); |
516 return; | 567 return; |
517 } | 568 } |
518 } | 569 } |
519 /* ugh. allow # by itself, including with a comment after it */ | 570 /* ugh. allow # by itself, including with a comment after it */ |
520 uncomment(line); | 571 uncomment(line); |
572 assert(!incomment); | 623 assert(!incomment); |
573 return len; | 624 return len; |
574 } | 625 } |
575 | 626 |
576 void | 627 void |
577 directive_gotline(struct place *p, char *line, size_t len) | 628 directive_gotline(struct place *p, struct place *np, char *line, size_t len) |
578 { | 629 { |
579 size_t skip; | 630 size_t skip; |
580 | 631 |
581 if (warns.nestcomment) { | 632 if (warns.nestcomment) { |
582 directive_scancomments(p, line, len); | 633 directive_scancomments(p, line, len); |
586 if (line[0] == '#') { | 637 if (line[0] == '#') { |
587 skip = 1 + strspn(line + 1, ws); | 638 skip = 1 + strspn(line + 1, ws); |
588 assert(skip <= len); | 639 assert(skip <= len); |
589 p->column += skip; | 640 p->column += skip; |
590 assert(line[len] == '\0'); | 641 assert(line[len] == '\0'); |
591 directive_gotdirective(p, line+skip /*, length = len-skip */); | 642 directive_gotdirective(p, np, line+skip); |
592 p->column += len-skip; | 643 p->column += len-skip; |
593 } else if (ifstate->curtrue) { | 644 } else if (ifstate->curtrue) { |
594 macro_sendline(p, line, len); | 645 macro_sendline(p, line, len); |
595 p->column += len; | 646 p->column += len; |
596 } | 647 } |