# HG changeset patch # User Joerg Sonnenberger # Date 1424999209 -3600 # Node ID d6e6b3940780ea6f1f053eab17664fe7f4942d53 # Parent 8cef6d7227a854fefadb2ac6ca9ea6f57fc820f3 Fully implement #line. diff -r 8cef6d7227a8 -r d6e6b3940780 directive.c --- a/directive.c Fri Feb 27 00:41:46 2015 +0100 +++ b/directive.c Fri Feb 27 02:06:49 2015 +0100 @@ -175,7 +175,7 @@ static void -d_if(struct place *p, struct place *p2, char *line) +d_if(struct place *p, struct place *p2, struct place *np, char *line) { char *expr; bool val; @@ -200,7 +200,7 @@ static void -d_ifdef(struct place *p, struct place *p2, char *line) +d_ifdef(struct place *p, struct place *p2, struct place *np, char *line) { uncomment(line); oneword("#ifdef", p2, line); @@ -209,7 +209,7 @@ static void -d_ifndef(struct place *p, struct place *p2, char *line) +d_ifndef(struct place *p, struct place *p2, struct place *np, char *line) { uncomment(line); oneword("#ifndef", p2, line); @@ -218,7 +218,7 @@ static void -d_elif(struct place *p, struct place *p2, char *line) +d_elif(struct place *p, struct place *p2, struct place *np, char *line) { char *expr; struct place p3 = *p2; @@ -247,7 +247,7 @@ static void -d_else(struct place *p, struct place *p2, char *line) +d_else(struct place *p, struct place *p2, struct place *np, char *line) { (void)p2; (void)line; @@ -264,7 +264,7 @@ static void -d_endif(struct place *p, struct place *p2, char *line) +d_endif(struct place *p, struct place *p2, struct place *np, char *line) { (void)p2; (void)line; @@ -282,7 +282,7 @@ static void -d_define(struct place *p, struct place *p2, char *line) +d_define(struct place *p, struct place *p2, struct place *np, char *line) { size_t pos, argpos; struct place p3, p4; @@ -347,7 +347,7 @@ static void -d_undef(struct place *p, struct place *p2, char *line) +d_undef(struct place *p, struct place *p2, struct place *np, char *line) { (void)p; @@ -383,7 +383,7 @@ static void -d_include(struct place *p, struct place *p2, char *line) +d_include(struct place *p, struct place *p2, struct place *np, char *line) { char *text; size_t oldlen; @@ -412,13 +412,63 @@ static void -d_line(struct place *p, struct place *p2, char *line) +d_line(struct place *p, struct place *p2, struct place *np, char *line) { - (void)p2; - (void)line; + char *text; + size_t oldlen; + const char *token, *start_lineno, *start_filename; + size_t len_lineno, len_filename; + + text = macroexpand(p2, line, strlen(line), true); + + oldlen = strlen(text); + uncomment(text); + /* trim to fit, so the malloc debugging won't complain */ + text = dorealloc(text, oldlen + 1, strlen(text) + 1); - /* XXX */ - complain(p, "Sorry, no #line yet"); + token = text; + token += strspn(token, ws); + start_lineno = token; + len_lineno = strspn(token, digits); + if (len_lineno == 0) { + goto illegal_line; + } + token += len_lineno; + token += strspn(ws, token); + if (*token == '"') { + ++token; + start_filename = token; + len_filename = strcspn(token, "\""); + token += len_filename; + if (*token != '"' || len_filename == 0) { + goto illegal_line; + } + ++token; + token += strspn(token, ws); + if (*token != '\0') { + goto illegal_line; + } + } else { + len_filename = 0; + token += strspn(token, ws); + if (*token != '\0') { + goto illegal_line; + } + } + np->line = atoi(start_lineno); + if (len_filename) { + char *filename = dostrndup(start_filename, len_filename); + place_setfile(np, filename); + dostrfree(filename); + } + dostrfree(text); + return; + +illegal_line: + complain(p, "Illegal #line directive"); + complain(p, "Before macro expansion: #include %s", line); + complain(p, "After macro expansion: #include %s", text); + dostrfree(text); } //////////////////////////////////////////////////////////// @@ -426,7 +476,7 @@ static void -d_warning(struct place *p, struct place *p2, char *line) +d_warning(struct place *p, struct place *p2, struct place *np, char *line) { char *msg; @@ -440,7 +490,7 @@ static void -d_error(struct place *p, struct place *p2, char *line) +d_error(struct place *p, struct place *p2, struct place *np, char *line) { char *msg; @@ -455,7 +505,7 @@ static void -d_pragma(struct place *p, struct place *p2, char *line) +d_pragma(struct place *p, struct place *p2, struct place *np, char *line) { (void)p2; @@ -469,7 +519,8 @@ static const struct { const char *name; bool ifskip; - void (*func)(struct place *, struct place *, char *line); + void (*func)(struct place *, struct place *, struct place *, + char *line); } directives[] = { { "define", true, d_define }, { "elif", false, d_elif }, @@ -489,7 +540,7 @@ static void -directive_gotdirective(struct place *p, char *line) +directive_gotdirective(struct place *p, struct place *np, char *line) { struct place p2; size_t len, skip; @@ -512,7 +563,7 @@ if (len < strlen(line)) { line[len] = '\0'; } - directives[i].func(p, &p2, line); + directives[i].func(p, &p2, np, line); return; } } @@ -574,7 +625,7 @@ } void -directive_gotline(struct place *p, char *line, size_t len) +directive_gotline(struct place *p, struct place *np, char *line, size_t len) { size_t skip; @@ -588,7 +639,7 @@ assert(skip <= len); p->column += skip; assert(line[len] == '\0'); - directive_gotdirective(p, line+skip /*, length = len-skip */); + directive_gotdirective(p, np, line+skip); p->column += len-skip; } else if (ifstate->curtrue) { macro_sendline(p, line, len); diff -r 8cef6d7227a8 -r d6e6b3940780 directive.h --- a/directive.h Fri Feb 27 00:41:46 2015 +0100 +++ b/directive.h Fri Feb 27 02:06:49 2015 +0100 @@ -34,6 +34,6 @@ void directive_init(void); void directive_cleanup(void); -void directive_gotline(struct place *p, char *line, size_t len); +void directive_gotline(struct place *p, struct place *np, char *line, size_t len); void directive_goteof(struct place *p); diff -r 8cef6d7227a8 -r d6e6b3940780 files.c --- a/files.c Fri Feb 27 00:41:46 2015 +0100 +++ b/files.c Fri Feb 27 02:06:49 2015 +0100 @@ -275,7 +275,7 @@ /* if the line isn't empty, process it */ if (lineend > linestart) { - directive_gotline(&linestartplace, + directive_gotline(&linestartplace, &nextlinestartplace, buf+linestart, lineend-linestart); } diff -r 8cef6d7227a8 -r d6e6b3940780 place.c --- a/place.c Fri Feb 27 00:41:46 2015 +0100 +++ b/place.c Fri Feb 27 02:06:49 2015 +0100 @@ -154,6 +154,17 @@ p->column = 1; } +void +place_setfile(struct place *p, const char *name) +{ + assert(p->type == P_FILE); + if (strcmp(name, p->file->name) == 0) { + return; + } + p->file = placefile_create(&p->file->includedfrom, name, + p->file->fromsystemdir); +} + const char * place_getname(const struct place *p) { diff -r 8cef6d7227a8 -r d6e6b3940780 place.h --- a/place.h Fri Feb 27 00:41:46 2015 +0100 +++ b/place.h Fri Feb 27 02:06:49 2015 +0100 @@ -50,6 +50,7 @@ void place_setbuiltin(struct place *p, unsigned num); void place_setcommandline(struct place *p, unsigned word, unsigned column); void place_setfilestart(struct place *p, const struct placefile *pf); +void place_setfile(struct place *p, const char *name); const char *place_getparsedir(const struct place *incplace); diff -r 8cef6d7227a8 -r d6e6b3940780 tests/t38.c --- a/tests/t38.c Fri Feb 27 00:41:46 2015 +0100 +++ b/tests/t38.c Fri Feb 27 02:06:49 2015 +0100 @@ -3,3 +3,7 @@ __FILE__ __LINE__ m() +#line 500 +m() +#line 600 "foo.c" +m() diff -r 8cef6d7227a8 -r d6e6b3940780 tests/t38.good --- a/tests/t38.good Fri Feb 27 00:41:46 2015 +0100 +++ b/tests/t38.good Fri Feb 27 02:06:49 2015 +0100 @@ -2,3 +2,5 @@ "t38.c" 4 "t38.c":5 +"t38.c":500 +"foo.c":600 diff -r 8cef6d7227a8 -r d6e6b3940780 utils.c --- a/utils.c Fri Feb 27 00:41:46 2015 +0100 +++ b/utils.c Fri Feb 27 02:06:49 2015 +0100 @@ -44,6 +44,9 @@ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "_" ; +const char digits[] = + "0123456789" +; //////////////////////////////////////////////////////////// // malloc diff -r 8cef6d7227a8 -r d6e6b3940780 utils.h --- a/utils.h Fri Feb 27 00:41:46 2015 +0100 +++ b/utils.h Fri Feb 27 02:06:49 2015 +0100 @@ -46,7 +46,7 @@ extern const char ws[]; extern const char alnum[]; - +extern const char digits[]; void *domalloc(size_t len); void *dorealloc(void *ptr, size_t oldlen, size_t newlen);