diff --git a/topology/pre-processor.c b/topology/pre-processor.c index e6f9af6..b0353bb 100644 --- a/topology/pre-processor.c +++ b/topology/pre-processor.c @@ -222,7 +222,93 @@ err: return ret; } -int pre_process(struct tplg_pre_processor *tplg_pp, char *config, size_t config_size) +static int pre_process_defines(struct tplg_pre_processor *tplg_pp, const char *pre_processor_defs, + snd_config_t *top) +{ + snd_config_t *conf_defines, *defines; + int ret; + + ret = snd_config_search(tplg_pp->input_cfg, "Define", &conf_defines); + if (ret < 0) + return 0; + + if (snd_config_get_type(conf_defines) != SND_CONFIG_TYPE_COMPOUND) + return 0; + + /* + * load and merge the command line defines with the variables in the conf file to override + * default values + */ + if (pre_processor_defs != NULL) { + ret = snd_config_load_string(&defines, pre_processor_defs, strlen(pre_processor_defs)); + if (ret < 0) { + fprintf(stderr, "Failed to load pre-processor command line definitions\n"); + return ret; + } + + ret = snd_config_merge(conf_defines, defines, true); + if (ret < 0) { + fprintf(stderr, "Failed to override variable definitions\n"); + return ret; + } + } + + return 0; +} + +static int pre_process_variables_expand_fcn(snd_config_t **dst, const char *str, + void *private_data) +{ + struct tplg_pre_processor *tplg_pp = private_data; + snd_config_iterator_t i, next; + snd_config_t *conf_defines; + int ret; + + ret = snd_config_search(tplg_pp->input_cfg, "Define", &conf_defines); + if (ret < 0) + return 0; + + /* find variable definition */ + snd_config_for_each(i, next, conf_defines) { + snd_config_t *n; + const char *id; + + n = snd_config_iterator_entry(i); + if (snd_config_get_id(n, &id) < 0) + continue; + + if (strcmp(id, str)) + continue; + + /* found definition. Match type and return appropriate config */ + if (snd_config_get_type(n) == SND_CONFIG_TYPE_STRING) { + const char *s; + + if (snd_config_get_string(n, &s) < 0) + continue; + + return snd_config_imake_string(dst, NULL, s); + } + + if (snd_config_get_type(n) == SND_CONFIG_TYPE_INTEGER) { + long v; + + if (snd_config_get_integer(n, &v) < 0) + continue; + + ret = snd_config_imake_integer(dst, NULL, v); + return ret; + } + + } + + fprintf(stderr, "No definition for variable %s\n", str); + + return -EINVAL; +} + +int pre_process(struct tplg_pre_processor *tplg_pp, char *config, size_t config_size, + const char *pre_processor_defs) { snd_input_t *in; snd_config_t *top; @@ -249,7 +335,22 @@ int pre_process(struct tplg_pre_processor *tplg_pp, char *config, size_t config_ tplg_pp->input_cfg = top; - err = pre_process_config(tplg_pp, top); + /* parse command line definitions */ + err = pre_process_defines(tplg_pp, pre_processor_defs, tplg_pp->input_cfg); + if (err < 0) { + fprintf(stderr, "Failed to parse arguments in input config\n"); + goto err; + } + + /* expand pre-processor variables */ + err = snd_config_expand_custom(tplg_pp->input_cfg, tplg_pp->input_cfg, pre_process_variables_expand_fcn, + tplg_pp, &tplg_pp->input_cfg); + if (err < 0) { + fprintf(stderr, "Failed to expand pre-processor definitions in input config\n"); + goto err; + } + + err = pre_process_config(tplg_pp, tplg_pp->input_cfg); if (err < 0) { fprintf(stderr, "Unable to pre-process configuration\n"); goto err; diff --git a/topology/topology.c b/topology/topology.c index e0c7e7c..4a0750f 100644 --- a/topology/topology.c +++ b/topology/topology.c @@ -234,7 +234,8 @@ static int dump(const char *source_file, const char *output_file, int cflags, in } /* Convert Topology2.0 conf to the existing conf syntax */ -static int pre_process_conf(const char *source_file, const char *output_file) +static int pre_process_conf(const char *source_file, const char *output_file, + const char *pre_processor_defs) { struct tplg_pre_processor *tplg_pp; size_t config_size; @@ -254,7 +255,7 @@ static int pre_process_conf(const char *source_file, const char *output_file) } /* pre-process conf file */ - err = pre_process(tplg_pp, config, config_size); + err = pre_process(tplg_pp, config, config_size, pre_processor_defs); /* free pre-processor */ free_pre_preprocessor(tplg_pp); @@ -262,7 +263,8 @@ static int pre_process_conf(const char *source_file, const char *output_file) return err; } -static int compile(const char *source_file, const char *output_file, int cflags) +static int compile(const char *source_file, const char *output_file, int cflags, + const char *pre_processor_defs) { struct tplg_pre_processor *tplg_pp = NULL; snd_tplg_t *tplg; @@ -284,7 +286,7 @@ static int compile(const char *source_file, const char *output_file, int cflags) init_pre_precessor(&tplg_pp, SND_OUTPUT_BUFFER, NULL); /* pre-process conf file */ - err = pre_process(tplg_pp, config, config_size); + err = pre_process(tplg_pp, config, config_size, pre_processor_defs); if (err) { free_pre_preprocessor(tplg_pp); free(config); @@ -353,7 +355,7 @@ static int decode(const char *source_file, const char *output_file, int main(int argc, char *argv[]) { - static const char short_options[] = "hc:d:n:u:v:o:pP:sgxzV"; + static const char short_options[] = "hc:d:n:u:v:o:pP:sgxzVD:"; static const struct option long_options[] = { {"help", 0, NULL, 'h'}, {"verbose", 1, NULL, 'v'}, @@ -372,6 +374,7 @@ int main(int argc, char *argv[]) }; char *source_file = NULL; char *output_file = NULL; + const char *pre_processor_defs = NULL; int c, err, op = 'c', cflags = 0, dflags = 0, sflags = 0, option_index; #ifdef ENABLE_NLS @@ -423,6 +426,9 @@ int main(int argc, char *argv[]) case 'x': sflags |= SND_TPLG_SAVE_NOCHECK; break; + case 'D': + pre_processor_defs = optarg; + break; case 'V': version(argv[0]); return 0; @@ -448,13 +454,13 @@ int main(int argc, char *argv[]) switch (op) { case 'c': - err = compile(source_file, output_file, cflags); + err = compile(source_file, output_file, cflags, pre_processor_defs); break; case 'd': err = decode(source_file, output_file, cflags, dflags, sflags); break; case 'P': - err = pre_process_conf(source_file, output_file); + err = pre_process_conf(source_file, output_file, pre_processor_defs); break; default: err = dump(source_file, output_file, cflags, sflags); diff --git a/topology/topology.h b/topology/topology.h index 494612b..5dd9b1f 100644 --- a/topology/topology.h +++ b/topology/topology.h @@ -27,7 +27,8 @@ struct tplg_pre_processor { snd_output_t *dbg_output; }; -int pre_process(struct tplg_pre_processor *tplg_pp, char *config, size_t config_size); +int pre_process(struct tplg_pre_processor *tplg_pp, char *config, size_t config_size, + const char *pre_processor_defs); int init_pre_precessor(struct tplg_pre_processor **tplg_pp, snd_output_type_t type, const char *output_file); void free_pre_preprocessor(struct tplg_pre_processor *tplg_pp);