- if((n = table_find(expansions,
- offsetof(struct cgi_expansion, name),
- sizeof (struct cgi_expansion),
- nexpansions,
- v.vec[0])) >= 0) {
- /* We found a built-in */
- if(v.nvec - 1 < expansions[n].minargs)
- fatal(0, "%s:%d: insufficient arguments to @%s@ (min %d, got %d)",
- name, line, v.vec[0], expansions[n].minargs, v.nvec - 1);
- if(v.nvec - 1 > expansions[n].maxargs)
- fatal(0, "%s:%d: too many arguments to @%s@ (max %d, got %d)",
- name, line, v.vec[0], expansions[n].maxargs, v.nvec - 1);
- /* for ordinary expansions, recursively expand the arguments */
- if(!(expansions[n].flags & EXP_MAGIC)) {
- for(m = 1; m < v.nvec; ++m) {
- dynstr_init(&d);
- byte_xasprintf(&argname, "<%s:%d arg #%d>", name, sline, m);
- parameter_output.quote = 0;
- parameter_output.sink = sink_dynstr(&d);
- cgi_expand_string(argname, v.vec[m],
- expansions, nexpansions,
- ¶meter_output, u);
- dynstr_terminate(&d);
- v.vec[m] = d.vec;
+ e = xmalloc(sizeof *e);
+ e->next = 0;
+ e->line = sline;
+ e->type = ELEMENT_EXPANSION;
+ e->name = v.vec[0];
+ e->nargs = v.nvec - 1;
+ e->args = &v.vec[1];
+ *tailp = e;
+ tailp = &e->next;
+ }
+ return head;
+}
+
+void cgi_expand_string(const char *name,
+ const char *template,
+ const struct cgi_expansion *expansions,
+ size_t nexpansions,
+ cgi_sink *output,
+ void *u) {
+ int n, m;
+ char *argname;
+ struct dynstr d;
+ cgi_sink parameter_output;
+ const struct cgi_macro *macro;
+
+ struct cgi_element *e;
+
+ for(e = cgi_parse_string(name, template); e; e = e->next) {
+ switch(e->type) {
+ case ELEMENT_TEXT:
+ output->sink->write(output->sink, e->text, strlen(e->text));
+ break;
+ case ELEMENT_EXPANSION:
+ if((n = table_find(expansions,
+ offsetof(struct cgi_expansion, name),
+ sizeof (struct cgi_expansion),
+ nexpansions,
+ e->name)) >= 0) {
+ /* We found a built-in */
+ if(e->nargs < expansions[n].minargs)
+ fatal(0, "%s:%d: insufficient arguments to @%s@ (min %d, got %d)",
+ name, e->line, e->name, expansions[n].minargs, e->nargs);
+ if(e->nargs > expansions[n].maxargs)
+ fatal(0, "%s:%d: too many arguments to @%s@ (max %d, got %d)",
+ name, e->line, e->name, expansions[n].maxargs, e->nargs);
+ /* for ordinary expansions, recursively expand the arguments */
+ if(!(expansions[n].flags & EXP_MAGIC)) {
+ for(m = 0; m < e->nargs; ++m) {
+ dynstr_init(&d);
+ byte_xasprintf(&argname, "<%s:%d arg #%d>", name, e->line, m);
+ parameter_output.quote = 0;
+ parameter_output.sink = sink_dynstr(&d);
+ cgi_expand_string(argname, e->args[m],
+ expansions, nexpansions,
+ ¶meter_output, u);
+ dynstr_terminate(&d);
+ e->args[m] = d.vec;
+ }