# HG changeset patch # User David A. Holland # Date 1292827907 18000 # Node ID c08a947d8f30c9350e505581eaba17d8c43b16c2 # Parent 76da41da923f04d277c50208301f5d1e397ba975 deal with macro parameters diff -r 76da41da923f -r c08a947d8f30 directive.c --- a/directive.c Mon Dec 20 01:15:43 2010 -0500 +++ b/directive.c Mon Dec 20 01:51:47 2010 -0500 @@ -171,8 +171,8 @@ void d_define(struct place *p, struct place *p2, char *line, size_t len) { - size_t pos; - struct place p3; + size_t pos, argpos; + struct place p3, p4; /* * line may be: @@ -182,7 +182,8 @@ pos = strcspn(line, " \t\f\v("); if (line[pos] == '(') { - pos++; + line[pos++] = '\0'; + argpos = pos; pos = pos + strcspn(line+pos, "()"); if (line[pos] == '(') { p2->column += pos; @@ -196,25 +197,35 @@ complain_fail(); return; } - pos++; + line[pos++] = '\0'; if (!strchr(ws, line[pos])) { p2->column += pos; complain(p2, "Trash after macro parameter list"); complain_fail(); return; } - line[pos++] = '\0'; } else if (line[pos] == '\0') { - /* nothing */ + argpos = 0; } else { line[pos++] = '\0'; + argpos = 0; } pos += strspn(line+pos, ws); p3 = *p2; - p3.column += pos; - macro_define(p2, line, &p3, line + pos); + p3.column += argpos; + + p4 = *p2; + p4.column += pos; + + if (argpos) { + macro_define_params(p2, line, &p3, + line + argpos, &p4, + line + pos); + } else { + macro_define_plain(p2, line, &p4, line + pos); + } } static @@ -337,16 +348,6 @@ static const unsigned numdirectives = HOWMANY(directives); static -size_t -notrailingws(char *buf, size_t len) -{ - while (len > 0 && strchr(ws, buf[len-1])) { - buf[--len] = '\0'; - } - return len; -} - -static void directive_gotdirective(struct place *p, char *line, size_t linelen) { diff -r 76da41da923f -r c08a947d8f30 macro.c --- a/macro.c Mon Dec 20 01:15:43 2010 -0500 +++ b/macro.c Mon Dec 20 01:51:47 2010 -0500 @@ -11,6 +11,8 @@ struct place expansionplace; unsigned hash; char *name; + bool hasparams; + struct stringarray params; char *expansion; }; DECLARRAY(macro); @@ -27,8 +29,8 @@ static struct macro * -macro_create(struct place *p1, struct place *p2, unsigned hash, - const char *name, const char *expansion) +macro_create(struct place *p1, const char *name, unsigned hash, + struct place *p2, const char *expansion) { struct macro *m; @@ -37,6 +39,8 @@ m->expansionplace = *p2; m->hash = hash; m->name = dostrdup(name); + m->hasparams = false; + stringarray_init(&m->params); m->expansion = dostrdup(expansion); return m; } @@ -50,6 +54,41 @@ free(m); } +static +bool +macro_eq(const struct macro *m1, const struct macro *m2) +{ + unsigned num1, num2, i; + const char *p1, *p2; + + if (strcmp(m1->name, m2->name) != 0) { + return false; + } + + if (m1->hasparams != m2->hasparams) { + return false; + } + + if (strcmp(m1->expansion, m2->expansion) != 0) { + return false; + } + + num1 = stringarray_num(&m1->params); + num2 = stringarray_num(&m2->params); + if (num1 != num2) { + return false; + } + + for (i=0; iparams, i); + p2 = stringarray_get(&m2->params, i); + if (strcmp(p1, p2) != 0) { + return false; + } + } + return true; +} + //////////////////////////////////////////////////////////// // macro table @@ -238,28 +277,104 @@ //////////////////////////////////////////////////////////// // external macro definition interface -void -macro_define(struct place *p1, const char *macro, - struct place *p2, const char *expansion) +static +struct macro * +macro_define_common_start(struct place *p1, const char *macro, + struct place *p2, const char *expansion) { struct macro *m; - m = macrotable_find(macro, false); - if (m != NULL) { - if (!strcmp(expansion, m->expansion)) { - complain(p1, "Warning: redefinition of %s", macro); + if (!is_identifier(macro)) { + complain(p1, "Invalid macro name %s", macro); + complain_fail(); + } + + m = macro_create(p1, macro, hashfunc(macro), p2, expansion); + return m; +} + +static +void +macro_define_common_end(struct macro *m) +{ + struct macro *oldm; + bool ok; + + oldm = macrotable_find(m->name, false); + if (oldm != NULL) { + ok = macro_eq(m, oldm); + if (ok) { + complain(&m->defplace, + "Warning: redefinition of %s", m->name); if (mode.werror) { complain_fail(); } - return; + } else { + complain(&m->defplace, + "Redefinition of %s is not identical", + m->name); + complain_fail(); } - complain(p1, "Redefinition of %s is not identical", macro); - complain_fail(); + complain(&oldm->defplace, "Previous definition was here"); + macro_destroy(m); return; } + macrotable_add(m); +} - m = macro_create(p1, p2, hashfunc(macro), macro, expansion); - macrotable_add(m); +static +void +macro_parse_parameters(struct macro *m, struct place *p, const char *params) +{ + size_t len; + const char *s; + char *param; + + while (params != NULL) { + len = strspn(params, ws); + params += len; + p->column += len; + s = strchr(params, ','); + if (s) { + len = s-params; + param = dostrndup(params, len); + s++; + } else { + len = strlen(params); + param = dostrndup(params, len); + } + notrailingws(param, strlen(param)); + if (!is_identifier(param)) { + complain(p, "Invalid macro parameter name %s", param); + complain_fail(); + } else { + stringarray_add(&m->params, param, NULL); + } + params = s; + p->column += len; + } +} + +void +macro_define_plain(struct place *p1, const char *macro, + struct place *p2, const char *expansion) +{ + struct macro *m; + + m = macro_define_common_start(p1, macro, p2, expansion); + 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) +{ + struct macro *m; + + m = macro_define_common_start(p1, macro, p3, expansion); + macro_parse_parameters(m, p2, params); + macro_define_common_end(m); } void diff -r 76da41da923f -r c08a947d8f30 macro.h --- a/macro.h Mon Dec 20 01:15:43 2010 -0500 +++ b/macro.h Mon Dec 20 01:51:47 2010 -0500 @@ -6,8 +6,11 @@ void macros_init(void); void macros_cleanup(void); -void macro_define(struct place *, const char *macro, - struct place *, const char *expansion); +void macro_define_plain(struct place *, const char *macro, + struct place *, const char *expansion); +void macro_define_params(struct place *, const char *macro, + struct place *, const char *params, + struct place *, const char *expansion); void macro_undef(const char *macro); bool macro_isdefined(const char *macro); diff -r 76da41da923f -r c08a947d8f30 main.c --- a/main.c Mon Dec 20 01:15:43 2010 -0500 +++ b/main.c Mon Dec 20 01:51:47 2010 -0500 @@ -133,8 +133,8 @@ for (i=0; iexpansion != NULL) { - macro_define(&cm->where, cm->macro, - &cm->where2, cm->expansion); + macro_define_plain(&cm->where, cm->macro, + &cm->where2, cm->expansion); } else { macro_undef(cm->macro); } @@ -150,7 +150,7 @@ struct place p; place_setbuiltin(&p, num); - macro_define(&p, name, &p, val); + macro_define_plain(&p, name, &p, val); } static diff -r 76da41da923f -r c08a947d8f30 utils.c --- a/utils.c Mon Dec 20 01:15:43 2010 -0500 +++ b/utils.c Mon Dec 20 01:51:47 2010 -0500 @@ -108,3 +108,26 @@ return ret; } +size_t +notrailingws(char *buf, size_t len) +{ + while (len > 0 && strchr(ws, buf[len-1])) { + buf[--len] = '\0'; + } + return len; +} + +bool +is_identifier(const char *str) +{ + size_t len; + + len = strlen(str); + if (len != strspn(str, alnum)) { + return false; + } + if (str[0] >= '0' && str[0] <= '9') { + return false; + } + return true; +} diff -r 76da41da923f -r c08a947d8f30 utils.h --- a/utils.h Mon Dec 20 01:15:43 2010 -0500 +++ b/utils.h Mon Dec 20 01:51:47 2010 -0500 @@ -16,6 +16,10 @@ char *dostrdup(const char *s); char *dostrdup2(const char *s, const char *t); char *dostrdup3(const char *s, const char *t, const char *u); +char *dostrndup(const char *s, size_t len); + +size_t notrailingws(char *buf, size_t len); +bool is_identifier(const char *str); /* in place.c */ void complain(const struct place *, const char *fmt, ...);