From 3dddcfa45efd85c5f74f49b2aa1484b0e7751e5f Mon Sep 17 00:00:00 2001 From: Richard Kettlewell Date: Sun, 27 Apr 2008 21:35:19 +0100 Subject: [PATCH] First cut at macro definition. Does not expand args yet. --- server/cgi.c | 84 ++++++++++++++++++++++++++++++++++++++++++++--------------- server/cgi.h | 5 ++++ server/dcgi.c | 12 +++++++++ 3 files changed, 80 insertions(+), 21 deletions(-) diff --git a/server/cgi.c b/server/cgi.c index 23d1020..f703c32 100644 --- a/server/cgi.c +++ b/server/cgi.c @@ -53,6 +53,7 @@ #include "printf.h" #include "mime.h" #include "unicode.h" +#include "hash.h" struct kvp *cgi_args; @@ -64,6 +65,15 @@ struct column { char **columns; }; +/* macros */ +struct cgi_macro { + int nargs; + char **args; + const char *value; +}; + +static hash *cgi_macros; + #define RELIST(x) struct re *x, **x##_tail = &x static int have_read_options; @@ -372,6 +382,7 @@ void cgi_expand_string(const char *name, struct vector v; struct dynstr d; cgi_sink parameter_output; + const struct cgi_macro *macro; while(*template) { if(*template != '@') { @@ -443,29 +454,46 @@ finished_expansion: offsetof(struct cgi_expansion, name), sizeof (struct cgi_expansion), nexpansions, - v.vec[0])) < 0) - fatal(0, "%s:%d: unknown expansion '%s'", name, line, v.vec[0]); - 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; + 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; + } } + expansions[n].handler(v.nvec - 1, v.vec + 1, output, u); + } else if(cgi_macros && (macro = hash_find(cgi_macros, v.vec[0]))) { + /* We found a macro */ + if(v.nvec - 1 != macro->nargs) + fatal(0, "%s:%d: wrong number of arguments to @%s@ (need %d, got %d)", + name, line, v.vec[0], macro->nargs, v.nvec - 1); + /* We must substitute in argument values */ + /* TODO */ + cgi_expand_string(v.vec[0], + macro->value, + expansions, + nexpansions, + output, + u); + } else { + /* Totally undefined */ + fatal(0, "%s:%d: unknown expansion '%s'", name, line, v.vec[0]); } - expansions[n].handler(v.nvec - 1, v.vec + 1, output, u); } } @@ -633,6 +661,20 @@ char **cgi_columns(const char *name, int *ncolumns) { } } +void cgi_define(const char *name, + int nargs, + char **args, + const char *value) { + struct cgi_macro m; + + if(!cgi_macros) + cgi_macros = hash_new(sizeof(struct cgi_macro)); + m.nargs = nargs; + m.args = args; + m.value = value; + hash_add(cgi_macros, name, &m, HASH_INSERT_OR_REPLACE); +} + /* Local Variables: c-basic-offset:2 diff --git a/server/cgi.h b/server/cgi.h index 2381c03..8a76d31 100644 --- a/server/cgi.h +++ b/server/cgi.h @@ -65,6 +65,11 @@ struct cgi_expansion { void (*handler)(int nargs, char **args, cgi_sink *output, void *u); }; +void cgi_define(const char *name, + int nargs, + char **args, + const char *value); + void cgi_expand(const char *name, const struct cgi_expansion *expansions, size_t nexpansions, diff --git a/server/dcgi.c b/server/dcgi.c index 33630fa..16a5a6c 100644 --- a/server/dcgi.c +++ b/server/dcgi.c @@ -1760,6 +1760,17 @@ static void exp_image(int attribute((unused)) nargs, cgi_output(output, "/disorder/%s", imagestem); } +static void exp_define(int attribute((unused)) nargs, + char **args, + cgi_sink attribute((unused)) *output, + void attribute((unused)) *u) { + const char *n = args[0], *a = args[1], *v = args[2]; + int nas; + char **as = split(a, &nas, 0, 0, 0); + + cgi_define(n, nas, as, v); +} + static const struct cgi_expansion expansions[] = { { "#", 0, INT_MAX, EXP_MAGIC, exp_comment }, { "action", 0, 0, 0, exp_action }, @@ -1767,6 +1778,7 @@ static const struct cgi_expansion expansions[] = { { "arg", 1, 1, 0, exp_arg }, { "basename", 0, 1, 0, exp_basename }, { "choose", 2, 2, EXP_MAGIC, exp_choose }, + { "define", 3, 3, EXP_MAGIC, exp_define }, { "dirname", 0, 1, 0, exp_dirname }, { "enabled", 0, 0, 0, exp_enabled }, { "eq", 2, 2, 0, exp_eq }, -- 2.11.0