+/** @brief Expand a list of arguments in place */
+static void cgi_expand_all_args(const char *name,
+ int line,
+ const struct cgi_expansion *expansions,
+ size_t nexpansions,
+ void *u,
+ char **args,
+ int nargs) {
+ int n;
+ struct dynstr d;
+ char *argname;
+ cgi_sink parameter_output;
+
+ for(n = 0; n < nargs; ++n) {
+ dynstr_init(&d);
+ byte_xasprintf(&argname, "<%s:%d arg #%d>", name, line,n);
+ parameter_output.quote = 0;
+ parameter_output.sink = sink_dynstr(&d);
+ cgi_expand_string(argname, args[n],
+ expansions, nexpansions,
+ ¶meter_output, u);
+ dynstr_terminate(&d);
+ args[n] = d.vec;
+ }
+}
+
+
+/** @brief Substitute macro arguments in place */
+static void cgi_substitute_args(const char *name,
+ struct cgi_element *head,
+ const struct cgi_macro *macro,
+ char **values) {
+ struct cgi_element *e;
+ int n;
+
+ for(e = head; e; e = e->next) {
+ if(e->type != ELEMENT_EXPANSION)
+ continue;
+ /* See if this is an argument name */
+ for(n = 0; n < macro->nargs; ++n)
+ if(!strcmp(e->name, macro->args[n]))
+ break;
+ if(n < macro->nargs) {
+ /* It is! */
+ if(e->nargs != 0)
+ fatal(0, "%s:%d: macro argument (%s) cannot take parameters",
+ name, e->line, e->name);
+ /* Replace it with the argument text */
+ e->type = ELEMENT_TEXT;
+ e->text = values[n];
+ continue;
+ }
+ /* It's not a macro argument. We must recurse into its arguments to
+ * substitute the macro arguments. */
+ /* TODO */
+ /* In order to do this we must parse it and our callers must expect the
+ * parsed form. We're not ready for this yet... */
+ }
+}
+