X-Git-Url: https://jxself.org/git/?p=carl9170fw.git;a=blobdiff_plain;f=config%2Fpreprocess.c;h=b028a48b0e761f491f90e29df43b6975f5a0a757;hp=d103683b386edc551ffc526d28bf74434856d7b1;hb=342b243d70ea8bd00733d288f08fa89cf44a2773;hpb=dd88a7e5b482637a26c67ffa1cdf7ebed204161d diff --git a/config/preprocess.c b/config/preprocess.c index d103683..b028a48 100644 --- a/config/preprocess.c +++ b/config/preprocess.c @@ -106,6 +106,35 @@ struct function { char *(*func)(int argc, char *argv[]); }; +static char *do_error_if(int argc, char *argv[]) +{ + if (!strcmp(argv[0], "y")) + pperror("%s", argv[1]); + + return NULL; +} + +static char *do_filename(int argc, char *argv[]) +{ + return xstrdup(current_file->name); +} + +static char *do_info(int argc, char *argv[]) +{ + printf("%s\n", argv[0]); + + return xstrdup(""); +} + +static char *do_lineno(int argc, char *argv[]) +{ + char buf[16]; + + sprintf(buf, "%d", yylineno); + + return xstrdup(buf); +} + static char *do_shell(int argc, char *argv[]) { FILE *p; @@ -127,7 +156,7 @@ static char *do_shell(int argc, char *argv[]) nread--; /* remove trailing new lines */ - while (buf[nread - 1] == '\n') + while (nread > 0 && buf[nread - 1] == '\n') nread--; buf[nread] = 0; @@ -146,9 +175,23 @@ static char *do_shell(int argc, char *argv[]) return xstrdup(buf); } +static char *do_warning_if(int argc, char *argv[]) +{ + if (!strcmp(argv[0], "y")) + fprintf(stderr, "%s:%d: %s\n", + current_file->name, yylineno, argv[1]); + + return xstrdup(""); +} + static const struct function function_table[] = { /* Name MIN MAX Function */ + { "error-if", 2, 2, do_error_if }, + { "filename", 0, 0, do_filename }, + { "info", 1, 1, do_info }, + { "lineno", 0, 0, do_lineno }, { "shell", 1, 1, do_shell }, + { "warning-if", 2, 2, do_warning_if }, }; #define FUNCTION_MAX_ARGS 16 @@ -186,6 +229,7 @@ struct variable { char *name; char *value; enum variable_flavor flavor; + int exp_count; struct list_head node; }; @@ -210,11 +254,22 @@ static char *variable_expand(const char *name, int argc, char *argv[]) if (!v) return NULL; + if (argc == 0 && v->exp_count) + pperror("Recursive variable '%s' references itself (eventually)", + name); + + if (v->exp_count > 1000) + pperror("Too deep recursive expansion"); + + v->exp_count++; + if (v->flavor == VAR_RECURSIVE) res = expand_string_with_args(v->value, argc, argv); else res = xstrdup(v->value); + v->exp_count--; + return res; } @@ -222,22 +277,45 @@ void variable_add(const char *name, const char *value, enum variable_flavor flavor) { struct variable *v; + char *new_value; + bool append = false; v = variable_lookup(name); if (v) { - free(v->value); + /* For defined variables, += inherits the existing flavor */ + if (flavor == VAR_APPEND) { + flavor = v->flavor; + append = true; + } else { + free(v->value); + } } else { + /* For undefined variables, += assumes the recursive flavor */ + if (flavor == VAR_APPEND) + flavor = VAR_RECURSIVE; + v = xmalloc(sizeof(*v)); v->name = xstrdup(name); + v->exp_count = 0; list_add_tail(&v->node, &variable_list); } v->flavor = flavor; if (flavor == VAR_SIMPLE) - v->value = expand_string(value); + new_value = expand_string(value); else - v->value = xstrdup(value); + new_value = xstrdup(value); + + if (append) { + v->value = xrealloc(v->value, + strlen(v->value) + strlen(new_value) + 2); + strcat(v->value, " "); + strcat(v->value, new_value); + free(new_value); + } else { + v->value = new_value; + } } static void variable_del(struct variable *v) @@ -477,8 +555,7 @@ char *expand_string(const char *in) static bool is_end_of_token(char c) { - /* Why are '.' and '/' valid characters for symbols? */ - return !(isalnum(c) || c == '_' || c == '-' || c == '.' || c == '/'); + return !(isalnum(c) || c == '_' || c == '-'); } /*