kconfig: add 'filename' and 'lineno' built-in variables
[carl9170fw.git] / config / preprocess.c
index 46487fe6b36cd99e9ea04cc0bc2cbe7708b98121..0574039238c65cf1df6bb1dba86b9fff8c989375 100644 (file)
@@ -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;
@@ -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
@@ -185,6 +228,7 @@ static LIST_HEAD(variable_list);
 struct variable {
        char *name;
        char *value;
+       enum variable_flavor flavor;
        struct list_head node;
 };
 
@@ -203,28 +247,62 @@ static struct variable *variable_lookup(const char *name)
 static char *variable_expand(const char *name, int argc, char *argv[])
 {
        struct variable *v;
+       char *res;
 
        v = variable_lookup(name);
        if (!v)
                return NULL;
 
-       return expand_string_with_args(v->value, argc, argv);
+       if (v->flavor == VAR_RECURSIVE)
+               res = expand_string_with_args(v->value, argc, argv);
+       else
+               res = xstrdup(v->value);
+
+       return res;
 }
 
-void variable_add(const char *name, const char *value)
+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);
                list_add_tail(&v->node, &variable_list);
        }
 
-       v->value = xstrdup(value);
+       v->flavor = flavor;
+
+       if (flavor == VAR_SIMPLE)
+               new_value = expand_string(value);
+       else
+               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)