chiark / gitweb /
First cut at macro definition. Does not expand args yet.
authorRichard Kettlewell <rjk@greenend.org.uk>
Sun, 27 Apr 2008 20:35:19 +0000 (21:35 +0100)
committerRichard Kettlewell <rjk@greenend.org.uk>
Sun, 27 Apr 2008 20:35:19 +0000 (21:35 +0100)
server/cgi.c
server/cgi.h
server/dcgi.c

index 23d102055a7ec0c75fca6c3a1fd5aebbaf2e9d20..f703c3291291427c5de9c4ba966bc9b1843a24c2 100644 (file)
@@ -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,
-                         &parameter_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,
+                           &parameter_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
index 2381c033bf609b12962b135b93d99d94f2434211..8a76d313221686eb6f63a9c58554e5e22a958606 100644 (file)
@@ -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,
index 33630faa85ea2e037bc3fb73ae9d29c835c2aa8b..16a5a6cb6c9698994f6a5d97995b9e679fb1fadd 100644 (file)
@@ -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 },