+vat2_register_function (char *name, cJSON (*f) (cJSON *),
+ cJSON (*tojson) (void *))
+{
+ struct apifuncs_s funcs = { .f = f, .tojson = tojson };
+ vec_add1 (apifuncs, funcs);
+ hash_set_mem (function_by_name, name, vec_len (apifuncs) - 1);
+}
+
+static int
+vat2_exec_command_by_name (char *msgname, cJSON *o)
+{
+ uword *p = hash_get_mem (function_by_name, msgname);
+ if (!p)
+ {
+ fprintf (stderr, "No such command %s", msgname);
+ return -1;
+ }
+
+ cJSON *(*fp) (cJSON *);
+ fp = (void *) apifuncs[p[0]].f;
+ cJSON *r = (*fp) (o);
+
+ if (r)
+ {
+ char *output = cJSON_Print (r);
+ cJSON_Delete (r);
+ printf ("%s\n", output);
+ free (output);
+ }
+ else
+ {
+ fprintf (stderr, "Call failed: %s\n", msgname);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+vat2_exec_command (cJSON *o)
+{
+
+ cJSON *msg_id_obj = cJSON_GetObjectItem (o, "_msgname");
+ if (!msg_id_obj)
+ {
+ fprintf (stderr, "Missing '_msgname' element!\n");
+ return -1;
+ }
+
+ char *name = cJSON_GetStringValue (msg_id_obj);
+ assert (name);
+ return vat2_exec_command_by_name (name, o);
+}
+static void
+print_template (char *msgname)
+{
+ uword *p = hash_get_mem (function_by_name, msgname);
+ if (!p)
+ {
+ fprintf (stderr, "no such message: %s", msgname);
+ }
+ cJSON *(*fp) (void *);
+ fp = (void *) apifuncs[p[0]].tojson;
+ assert (fp);
+ void *scratch = malloc (2048);
+ memset (scratch, 0, 2048);
+ cJSON *t = fp (scratch);
+ free (scratch);
+ char *output = cJSON_Print (t);
+ cJSON_Delete (t);
+ printf ("%s\n", output);
+ free (output);
+}
+static void
+dump_apis (void)
+{
+ char *name;
+ u32 *i;
+ hash_foreach_mem (name, i, function_by_name, ({ printf ("%s\n", name); }));
+}
+
+static void
+print_help (void)