comparison directive.c @ 165:cc6d6f27d6ee

Fix Joerg's #line code. (avoid redundant whitespace grinding, don't use atoi, be simpler and tidier, etc.)
author David A. Holland
date Fri, 12 Jun 2015 01:30:13 -0400
parents f14f5352956c
children 6ff17ab68b16
comparison
equal deleted inserted replaced
164:f14f5352956c 165:cc6d6f27d6ee
29 29
30 #include <assert.h> 30 #include <assert.h>
31 #include <stdbool.h> 31 #include <stdbool.h>
32 #include <stdlib.h> 32 #include <stdlib.h>
33 #include <string.h> 33 #include <string.h>
34 #include <errno.h>
34 35
35 #include "utils.h" 36 #include "utils.h"
36 #include "mode.h" 37 #include "mode.h"
37 #include "place.h" 38 #include "place.h"
38 #include "files.h" 39 #include "files.h"
415 void 416 void
416 d_line(struct lineplace *lp, struct place *p2, char *line) 417 d_line(struct lineplace *lp, struct place *p2, char *line)
417 { 418 {
418 char *text; 419 char *text;
419 size_t oldlen; 420 size_t oldlen;
420 const char *token, *start_lineno, *start_filename; 421 unsigned long val;
421 size_t len_lineno, len_filename; 422 char *moretext;
423 size_t moretextlen;
424 char *filename;
422 425
423 text = macroexpand(p2, line, strlen(line), true); 426 text = macroexpand(p2, line, strlen(line), true);
424 427
425 oldlen = strlen(text); 428 oldlen = strlen(text);
426 uncomment(text); 429 uncomment(text);
427 /* trim to fit, so the malloc debugging won't complain */ 430 /* trim to fit, so the malloc debugging won't complain */
428 text = dorealloc(text, oldlen + 1, strlen(text) + 1); 431 text = dorealloc(text, oldlen + 1, strlen(text) + 1);
429 432
430 token = text; 433 /*
431 token += strspn(token, ws); 434 * What we should have here: either 1234 "file.c",
432 start_lineno = token; 435 * or just 1234.
433 len_lineno = strspn(token, digits); 436 */
434 if (len_lineno == 0) { 437
435 goto illegal_line; 438 errno = 0;
436 } 439 val = strtoul(text, &moretext, 10);
437 token += len_lineno; 440 if (errno) {
438 token += strspn(ws, token); 441 complain(&lp->current, "No line number in #line directive");
439 if (*token == '"') { 442 goto fail;
440 ++token; 443 }
441 start_filename = token; 444 #if UINT_MAX < ULONG_MAX
442 len_filename = strcspn(token, "\""); 445 if (val > UINT_MAX) {
443 token += len_filename; 446 complain(&lp->current,
444 if (*token != '"' || len_filename == 0) { 447 "Line number in #line directive too large");
445 goto illegal_line; 448 goto fail;
446 } 449 }
447 ++token; 450 #endif
448 token += strspn(token, ws); 451 moretext += strspn(moretext, ws);
449 if (*token != '\0') { 452 moretextlen = strlen(moretext);
450 goto illegal_line; 453 lp->current.column += (moretext - text);
451 } 454
452 } else { 455 if (moretextlen > 2 &&
453 len_filename = 0; 456 moretext[0] == '"' && moretext[moretextlen-1] == '"') {
454 token += strspn(token, ws); 457 filename = dostrndup(moretext+1, moretextlen-2);
455 if (*token != '\0') {
456 goto illegal_line;
457 }
458 }
459 lp->nextline.line = atoi(start_lineno);
460 if (len_filename) {
461 char *filename = dostrndup(start_filename, len_filename);
462 place_setfile(&lp->nextline, filename); 458 place_setfile(&lp->nextline, filename);
463 dostrfree(filename); 459 dostrfree(filename);
464 } 460 }
461 else if (moretextlen > 0) {
462 complain(&lp->current,
463 "Invalid file name in #line directive");
464 goto fail;
465 }
466
467 lp->nextline.line = val;
465 dostrfree(text); 468 dostrfree(text);
466 return; 469 return;
467 470
468 illegal_line: 471 fail:
469 complain(&lp->current, "Illegal #line directive"); 472 complain(&lp->current, "Before macro expansion: #line %s", line);
470 complain(&lp->current, "Before macro expansion: #include %s", line); 473 complain(&lp->current, "After macro expansion: #line %s", text);
471 complain(&lp->current, "After macro expansion: #include %s", text); 474 complain_fail();
472 dostrfree(text); 475 dostrfree(text);
473 } 476 }
474 477
475 //////////////////////////////////////////////////////////// 478 ////////////////////////////////////////////////////////////
476 // messages 479 // messages