# HG changeset patch # User David A. Holland # Date 1434087013 14400 # Node ID cc6d6f27d6eeb8e9c3a19d771393a190f622b9ad # Parent f14f5352956cfa5166946494320e56186cc4ed42 Fix Joerg's #line code. (avoid redundant whitespace grinding, don't use atoi, be simpler and tidier, etc.) diff -r f14f5352956c -r cc6d6f27d6ee directive.c --- a/directive.c Fri Jun 12 01:00:38 2015 -0400 +++ b/directive.c Fri Jun 12 01:30:13 2015 -0400 @@ -31,6 +31,7 @@ #include #include #include +#include #include "utils.h" #include "mode.h" @@ -417,8 +418,10 @@ { char *text; size_t oldlen; - const char *token, *start_lineno, *start_filename; - size_t len_lineno, len_filename; + unsigned long val; + char *moretext; + size_t moretextlen; + char *filename; text = macroexpand(p2, line, strlen(line), true); @@ -427,48 +430,48 @@ /* trim to fit, so the malloc debugging won't complain */ text = dorealloc(text, oldlen + 1, strlen(text) + 1); - token = text; - token += strspn(token, ws); - start_lineno = token; - len_lineno = strspn(token, digits); - if (len_lineno == 0) { - goto illegal_line; + /* + * What we should have here: either 1234 "file.c", + * or just 1234. + */ + + errno = 0; + val = strtoul(text, &moretext, 10); + if (errno) { + complain(&lp->current, "No line number in #line directive"); + goto fail; } - 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; - } +#if UINT_MAX < ULONG_MAX + if (val > UINT_MAX) { + complain(&lp->current, + "Line number in #line directive too large"); + goto fail; } - lp->nextline.line = atoi(start_lineno); - if (len_filename) { - char *filename = dostrndup(start_filename, len_filename); +#endif + moretext += strspn(moretext, ws); + moretextlen = strlen(moretext); + lp->current.column += (moretext - text); + + if (moretextlen > 2 && + moretext[0] == '"' && moretext[moretextlen-1] == '"') { + filename = dostrndup(moretext+1, moretextlen-2); place_setfile(&lp->nextline, filename); dostrfree(filename); } + else if (moretextlen > 0) { + complain(&lp->current, + "Invalid file name in #line directive"); + goto fail; + } + + lp->nextline.line = val; dostrfree(text); return; -illegal_line: - complain(&lp->current, "Illegal #line directive"); - complain(&lp->current, "Before macro expansion: #include %s", line); - complain(&lp->current, "After macro expansion: #include %s", text); +fail: + complain(&lp->current, "Before macro expansion: #line %s", line); + complain(&lp->current, "After macro expansion: #line %s", text); + complain_fail(); dostrfree(text); }