# HG changeset patch # User David A. Holland # Date 1434085238 14400 # Node ID f14f5352956cfa5166946494320e56186cc4ed42 # Parent e1dfa3f90b6ceeb796f8de95cd50f420bfdad99a# Parent a2c2fe8dbea3fd892ed9fb4c1a1f9135e442d399 Merge upstream into Joerg's changes. diff -r a2c2fe8dbea3 -r f14f5352956c directive.c --- a/directive.c Fri Jun 12 00:56:12 2015 -0400 +++ b/directive.c Fri Jun 12 01:00:38 2015 -0400 @@ -415,11 +415,61 @@ void d_line(struct lineplace *lp, struct place *p2, 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(&lp->current, "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; + } + } + lp->nextline.line = atoi(start_lineno); + if (len_filename) { + char *filename = dostrndup(start_filename, len_filename); + place_setfile(&lp->nextline, filename); + dostrfree(filename); + } + 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); + dostrfree(text); } //////////////////////////////////////////////////////////// diff -r a2c2fe8dbea3 -r f14f5352956c directive.h diff -r a2c2fe8dbea3 -r f14f5352956c files.c diff -r a2c2fe8dbea3 -r f14f5352956c macro.c --- a/macro.c Fri Jun 12 00:56:12 2015 -0400 +++ b/macro.c Fri Jun 12 01:00:38 2015 -0400 @@ -28,6 +28,7 @@ */ #include +#include #include #include @@ -38,7 +39,7 @@ #include "output.h" struct expansionitem { - bool isstring; + enum { EI_PARAM, EI_STRING, EI_FILE, EI_LINE } itemtype; union { char *string; unsigned param; @@ -50,11 +51,12 @@ struct macro { struct place defplace; struct place expansionplace; - unsigned hash; - char *name; - bool hasparams; struct stringarray params; struct expansionitemarray expansion; + char *name; + unsigned hash; + bool hasparams; + bool isspecial; bool inuse; }; DECLARRAY(macro, static UNUSED); @@ -76,7 +78,7 @@ struct expansionitem *ei; ei = domalloc(sizeof(*ei)); - ei->isstring = true; + ei->itemtype = EI_STRING; ei->string = dostrdup(string); return ei; } @@ -88,7 +90,7 @@ struct expansionitem *ei; ei = domalloc(sizeof(*ei)); - ei->isstring = true; + ei->itemtype = EI_STRING; ei->string = dostrndup(string, len); return ei; } @@ -100,16 +102,38 @@ struct expansionitem *ei; ei = domalloc(sizeof(*ei)); - ei->isstring = false; + ei->itemtype = EI_PARAM; ei->param = param; return ei; } static +struct expansionitem * +expansionitem_create_file(void) +{ + struct expansionitem *ei; + + ei = domalloc(sizeof(*ei)); + ei->itemtype = EI_FILE; + return ei; +} + +static +struct expansionitem * +expansionitem_create_line(void) +{ + struct expansionitem *ei; + + ei = domalloc(sizeof(*ei)); + ei->itemtype = EI_LINE; + return ei; +} + +static void expansionitem_destroy(struct expansionitem *ei) { - if (ei->isstring) { + if (ei->itemtype == EI_STRING) { dostrfree(ei->string); } dofree(ei, sizeof(*ei)); @@ -120,10 +144,10 @@ expansionitem_eq(const struct expansionitem *ei1, const struct expansionitem *ei2) { - if (ei1->isstring != ei2->isstring) { + if ((ei1->itemtype == EI_STRING) != (ei2->itemtype == EI_STRING)) { return false; } - if (ei1->isstring) { + if (ei1->itemtype == EI_STRING) { if (strcmp(ei1->string, ei2->string) != 0) { return false; } @@ -148,6 +172,7 @@ m->hash = hash; m->name = dostrdup(name); m->hasparams = false; + m->isspecial = false; stringarray_init(&m->params); expansionitemarray_init(&m->expansion); m->inuse = false; @@ -174,6 +199,10 @@ struct expansionitem *ei1, *ei2; const char *p1, *p2; + if (m2->isspecial) { + return false; + } + if (strcmp(m1->name, m2->name) != 0) { return false; } @@ -573,6 +602,32 @@ } void +macro_define_file(struct place *p) +{ + struct macro *m; + struct expansionitem *ei; + + m = macro_define_common_start(p, "__FILE__", p); + m->isspecial = true; + ei = expansionitem_create_file(); + expansionitemarray_add(&m->expansion, ei, NULL); + macro_define_common_end(m); +} + +void +macro_define_line(struct place *p) +{ + struct macro *m; + struct expansionitem *ei; + + m = macro_define_common_start(p, "__LINE__", p); + m->isspecial = true; + ei = expansionitem_create_line(); + expansionitemarray_add(&m->expansion, ei, NULL); + macro_define_common_end(m); +} + +void macro_define_params(struct place *p1, const char *macro, struct place *p2, const char *params, struct place *p3, const char *expansion) @@ -705,7 +760,7 @@ static void -expand_newarg(struct expstate *es, char *buf, size_t len) +expand_newarg(struct expstate *es, const char *buf, size_t len) { char *text; @@ -715,7 +770,7 @@ static void -expand_appendarg(struct expstate *es, char *buf, size_t len) +expand_appendarg(struct expstate *es, const char *buf, size_t len) { unsigned num; char *text; @@ -742,6 +797,7 @@ char *arg; char *ret; unsigned numargs, numparams; + char numbuf[64]; numargs = stringarray_num(&es->args); numparams = stringarray_num(&es->curmacro->params); @@ -766,11 +822,20 @@ num = expansionitemarray_num(&es->curmacro->expansion); for (i=0; icurmacro->expansion, i); - if (ei->isstring) { + switch (ei->itemtype) { + case EI_STRING: len += strlen(ei->string); - } else { + break; + case EI_PARAM: arg = stringarray_get(&es->args, ei->param); len += strlen(arg); + break; + case EI_FILE: + len += strlen(place_getname(p)) + 2; + break; + case EI_LINE: + len += snprintf(numbuf, sizeof(numbuf), "%u", p->line); + break; } } @@ -778,11 +843,23 @@ *ret = '\0'; for (i=0; icurmacro->expansion, i); - if (ei->isstring) { + switch (ei->itemtype) { + case EI_STRING: strcat(ret, ei->string); - } else { + break; + case EI_PARAM: arg = stringarray_get(&es->args, ei->param); strcat(ret, arg); + break; + case EI_FILE: + strcat(ret, "\""); + strcat(ret, place_getname(p)); + strcat(ret, "\""); + break; + case EI_LINE: + snprintf(numbuf, sizeof(numbuf), "%u", p->line); + strcat(ret, numbuf); + break; } } @@ -846,7 +923,7 @@ static void -expand_got_ws(struct expstate *es, struct place *p, char *buf, size_t len) +expand_got_ws(struct expstate *es, struct place *p, const char *buf, size_t len) { switch (es->state) { case ES_NORMAL: @@ -885,11 +962,18 @@ m = macrotable_findlen(buf, len, false); if (m == NULL || m->inuse) { expand_send(es, p, buf, len); + } else if (m->isspecial) { + es->curmacro = m; + newbuf = expand_substitute(p, es); + expand_send(es, p, newbuf, strlen(newbuf)); + dostrfree(newbuf); + es->curmacro = NULL; + m->inuse = false; } else if (!m->hasparams) { m->inuse = true; assert(expansionitemarray_num(&m->expansion) == 1); ei = expansionitemarray_get(&m->expansion, 0); - assert(ei->isstring); + assert(ei->itemtype == EI_STRING); newbuf = macroexpand(p, ei->string, strlen(ei->string), false); doexpand(es, p, newbuf, strlen(newbuf)); @@ -1177,7 +1261,16 @@ macro_sendline(struct place *p, char *buf, size_t len) { doexpand(&mainstate, p, buf, len); - output(p, "\n", 1); + switch (mainstate.state) { + case ES_NORMAL: + output(p, "\n", 1); + break; + case ES_WANTLPAREN: + case ES_NOARG: + case ES_HAVEARG: + expand_got_ws(&mainstate, p, " ", 1); + break; + } } void diff -r a2c2fe8dbea3 -r f14f5352956c macro.h --- a/macro.h Fri Jun 12 00:56:12 2015 -0400 +++ b/macro.h Fri Jun 12 01:00:38 2015 -0400 @@ -35,6 +35,8 @@ void macros_init(void); void macros_cleanup(void); +void macro_define_file(struct place *); +void macro_define_line(struct place *); void macro_define_plain(struct place *, const char *macro, struct place *, const char *expansion); void macro_define_params(struct place *, const char *macro, diff -r a2c2fe8dbea3 -r f14f5352956c main.c --- a/main.c Fri Jun 12 00:56:12 2015 -0400 +++ b/main.c Fri Jun 12 01:00:38 2015 -0400 @@ -195,6 +195,18 @@ static void +apply_special_macros(unsigned *builtin_counter) +{ + struct place p; + + place_setbuiltin(&p, ++(*builtin_counter)); + macro_define_file(&p); + place_setbuiltin(&p, ++(*builtin_counter)); + macro_define_line(&p); +} + +static +void apply_builtin_macro(unsigned num, const char *name, const char *val) { struct place p; @@ -205,35 +217,35 @@ static void -apply_builtin_macros(void) +apply_builtin_macros(unsigned *builtin_counter) { - unsigned n = 1; - #ifdef CONFIG_OS - apply_builtin_macro(n++, CONFIG_OS, "1"); + apply_builtin_macro(++(*builtin_counter), CONFIG_OS, "1"); #endif #ifdef CONFIG_OS_2 - apply_builtin_macro(n++, CONFIG_OS_2, "1"); + apply_builtin_macro(++(*builtin_counter), CONFIG_OS_2, "1"); #endif #ifdef CONFIG_CPU - apply_builtin_macro(n++, CONFIG_CPU, "1"); + apply_builtin_macro(++(*builtin_counter), CONFIG_CPU, "1"); #endif #ifdef CONFIG_CPU_2 - apply_builtin_macro(n++, CONFIG_CPU_2, "1"); + apply_builtin_macro(++(*builtin_counter), CONFIG_CPU_2, "1"); #endif #ifdef CONFIG_SIZE - apply_builtin_macro(n++, CONFIG_SIZE, "1"); + apply_builtin_macro(++(*builtin_counter), CONFIG_SIZE, "1"); #endif #ifdef CONFIG_BINFMT - apply_builtin_macro(n++, CONFIG_BINFMT, "1"); + apply_builtin_macro(++(*builtin_counter), CONFIG_BINFMT, "1"); #endif #ifdef CONFIG_COMPILER - apply_builtin_macro(n++, CONFIG_COMPILER, VERSION_MAJOR); - apply_builtin_macro(n++, CONFIG_COMPILER_MINOR, VERSION_MINOR); - apply_builtin_macro(n++, "__VERSION__", VERSION_LONG); + apply_builtin_macro(++(*builtin_counter), CONFIG_COMPILER, + VERSION_MAJOR); + apply_builtin_macro(++(*builtin_counter), CONFIG_COMPILER_MINOR, + VERSION_MINOR); + apply_builtin_macro(++(*builtin_counter), "__VERSION__", VERSION_LONG); #endif } @@ -1031,6 +1043,7 @@ const char *inputfile = NULL; const char *outputfile = NULL; struct place cmdplace; + unsigned builtin_counter; int i; progname = strrchr(argv[0], '/'); @@ -1076,7 +1089,11 @@ mode.output_file = outputfile; loadincludepath(); - apply_builtin_macros(); + + builtin_counter = 0; + apply_special_macros(&builtin_counter); + apply_builtin_macros(&builtin_counter); + apply_commandline_macros(); read_commandline_files(); place_setnowhere(&cmdplace); diff -r a2c2fe8dbea3 -r f14f5352956c place.c --- a/place.c Fri Jun 12 00:56:12 2015 -0400 +++ b/place.c Fri Jun 12 01:00:38 2015 -0400 @@ -154,7 +154,17 @@ p->column = 1; } -static +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 a2c2fe8dbea3 -r f14f5352956c place.h --- a/place.h Fri Jun 12 00:56:12 2015 -0400 +++ b/place.h Fri Jun 12 01:00:38 2015 -0400 @@ -47,11 +47,13 @@ void place_init(void); void place_cleanup(void); +const char *place_getname(const struct place *); void place_setnowhere(struct place *p); 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 a2c2fe8dbea3 -r f14f5352956c tests/Makefile --- a/tests/Makefile Fri Jun 12 00:56:12 2015 -0400 +++ b/tests/Makefile Fri Jun 12 01:00:38 2015 -0400 @@ -4,7 +4,7 @@ TESTS=\ t01 t02 t03 t04 t05 t06 t07 t08 t09 t10 t11 t12 t13 t14 t15 t16 \ t17 t18 t19 t20 t21 t22 t23 t24 t25 t26 t27 t28 t29 t30 t31 t32 \ - t33 t34 t35 t36 t37 + t33 t34 t35 t36 t37 t38 t39 all: run-tests .WAIT show-diffs diff -r a2c2fe8dbea3 -r f14f5352956c tests/t38.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/t38.c Fri Jun 12 01:00:38 2015 -0400 @@ -0,0 +1,9 @@ +#define m() __FILE__:__LINE__ +__LINE__ +__FILE__ +__LINE__ +m() +#line 500 +m() +#line 600 "foo.c" +m() diff -r a2c2fe8dbea3 -r f14f5352956c tests/t38.good --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/t38.good Fri Jun 12 01:00:38 2015 -0400 @@ -0,0 +1,6 @@ +2 +"t38.c" +4 +"t38.c":5 +"t38.c":500 +"foo.c":600 diff -r a2c2fe8dbea3 -r f14f5352956c tests/t39.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/t39.c Fri Jun 12 01:00:38 2015 -0400 @@ -0,0 +1,3 @@ +#define m(a,b) a::b +=m(123, +456) diff -r a2c2fe8dbea3 -r f14f5352956c tests/t39.good --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/t39.good Fri Jun 12 01:00:38 2015 -0400 @@ -0,0 +1,1 @@ +=123:: 456 diff -r a2c2fe8dbea3 -r f14f5352956c utils.c --- a/utils.c Fri Jun 12 00:56:12 2015 -0400 +++ b/utils.c Fri Jun 12 01:00:38 2015 -0400 @@ -44,6 +44,9 @@ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "_" ; +const char digits[] = + "0123456789" +; //////////////////////////////////////////////////////////// // malloc diff -r a2c2fe8dbea3 -r f14f5352956c utils.h --- a/utils.h Fri Jun 12 00:56:12 2015 -0400 +++ b/utils.h Fri Jun 12 01:00:38 2015 -0400 @@ -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);