cli: gather all found items through a callback function
authorJo-Philipp Wich <jow@openwrt.org>
Wed, 1 Jan 2014 15:44:00 +0000 (15:44 +0000)
committerJo-Philipp Wich <jow@openwrt.org>
Wed, 1 Jan 2014 15:44:00 +0000 (15:44 +0000)
main.c

diff --git a/main.c b/main.c
index 78fa0e4..2bdb110 100644 (file)
--- a/main.c
+++ b/main.c
        #include <json-c/json.h>
 #endif
 
+#include <libubox/list.h>
+
 #include "lexer.h"
 #include "parser.h"
 #include "matcher.h"
 
+
+struct match_item {
+       struct json_object *jsobj;
+       struct list_head list;
+};
+
 static struct json_object *
 parse_json(FILE *fd, const char *source, const char **error)
 {
@@ -91,75 +99,95 @@ print_string(const char *s)
 }
 
 static void
-export_value(struct json_object *jsobj, const char *prefix)
+export_value(struct list_head *matches, const char *prefix)
 {
        int n, len;
        bool first = true;
+       struct match_item *item;
+
+       if (list_empty(matches))
+               return;
 
        if (prefix)
        {
-               switch (json_object_get_type(jsobj))
+               printf("export %s=", prefix);
+
+               list_for_each_entry(item, matches, list)
                {
-               case json_type_object:
-                       printf("export %s=", prefix);
-                       json_object_object_foreach(jsobj, key, val)
+                       switch (json_object_get_type(item->jsobj))
                        {
-                               if (!val)
-                                       continue;
+                       case json_type_object:
+                               ; /* a label can only be part of a statement */
+                               json_object_object_foreach(item->jsobj, key, val)
+                               {
+                                       if (!val)
+                                               continue;
 
-                               if (!first)
-                                       printf("\\ ");
+                                       if (!first)
+                                               printf("\\ ");
 
-                               print_string(key);
-                               first = false;
-                       }
-                       printf("; ");
-                       break;
+                                       print_string(key);
+                                       first = false;
+                               }
+                               break;
 
-               case json_type_array:
-                       printf("export %s=", prefix);
-                       for (n = 0, len = json_object_array_length(jsobj); n < len; n++)
-                       {
+                       case json_type_array:
+                               for (n = 0, len = json_object_array_length(item->jsobj);
+                                    n < len; n++)
+                               {
+                                       if (!first)
+                                               printf("\\ ");
+
+                                       printf("%d", n);
+                                       first = false;
+                               }
+                               break;
+
+                       case json_type_boolean:
                                if (!first)
                                        printf("\\ ");
+                               printf("%d", json_object_get_boolean(item->jsobj));
+                               break;
 
-                               printf("%d", n);
-                               first = false;
-                       }
-                       printf("; ");
-                       break;
-
-               case json_type_boolean:
-                       printf("export %s=%d; ", prefix, json_object_get_boolean(jsobj));
-                       break;
+                       case json_type_int:
+                               if (!first)
+                                       printf("\\ ");
+                               printf("%d", json_object_get_int(item->jsobj));
+                               break;
 
-               case json_type_int:
-                       printf("export %s=%d; ", prefix, json_object_get_int(jsobj));
-                       break;
+                       case json_type_double:
+                               if (!first)
+                                       printf("\\ ");
+                               printf("%f", json_object_get_double(item->jsobj));
+                               break;
 
-               case json_type_double:
-                       printf("export %s=%f; ", prefix, json_object_get_double(jsobj));
-                       break;
+                       case json_type_string:
+                               if (!first)
+                                       printf("\\ ");
+                               print_string(json_object_get_string(item->jsobj));
+                               break;
 
-               case json_type_string:
-                       printf("export %s=", prefix);
-                       print_string(json_object_get_string(jsobj));
-                       printf("; ");
-                       break;
+                       case json_type_null:
+                               break;
+                       }
 
-               case json_type_null:
-                       break;
+                       first = false;
                }
+
+               printf("; ");
        }
        else
        {
-               printf("%s\n", json_object_to_json_string(jsobj));
+               list_for_each_entry(item, matches, list)
+                       printf("%s\n", json_object_to_json_string(item->jsobj));
        }
 }
 
 static void
-export_type(struct json_object *jsobj, const char *prefix)
+export_type(struct list_head *matches, const char *prefix)
 {
+       bool first = true;
+       struct match_item *item;
        const char *types[] = {
                "null",
                "boolean",
@@ -170,18 +198,48 @@ export_type(struct json_object *jsobj, const char *prefix)
                "string"
        };
 
+       if (list_empty(matches))
+               return;
+
        if (prefix)
-               printf("export %s=%s; ", prefix, types[json_object_get_type(jsobj)]);
+               printf("export %s=", prefix);
+
+       list_for_each_entry(item, matches, list)
+       {
+               if (!first)
+                       printf("\\ ");
+
+               printf("%s", types[json_object_get_type(item->jsobj)]);
+               first = false;
+       }
+
+       if (prefix)
+               printf("; ");
        else
-               printf("%s\n", types[json_object_get_type(jsobj)]);
+               printf("\n");
+}
+
+static void
+match_cb(struct json_object *res, void *priv)
+{
+       struct list_head *h = priv;
+       struct match_item *i = calloc(1, sizeof(*i));
+
+       if (i)
+       {
+               i->jsobj = res;
+               list_add_tail(&i->list, h);
+       }
 }
 
 static bool
 filter_json(int opt, struct json_object *jsobj, char *expr)
 {
        struct jp_state *state;
-       struct json_object *res = NULL;
        const char *prefix = NULL;
+       struct list_head matches;
+       struct match_item *item, *tmp;
+       struct json_object *res = NULL;
 
        state = jp_parse(expr);
 
@@ -193,24 +251,25 @@ filter_json(int opt, struct json_object *jsobj, char *expr)
                goto out;
        }
 
-       res = jp_match(state->path, jsobj);
+       INIT_LIST_HEAD(&matches);
 
-       if (res)
-       {
-               prefix = (state->path->type == T_LABEL) ? state->path->str : NULL;
+       res = jp_match(state->path, jsobj, match_cb, &matches);
+       prefix = (state->path->type == T_LABEL) ? state->path->str : NULL;
 
-               switch (opt)
-               {
-               case 't':
-                       export_type(res, prefix);
-                       break;
+       switch (opt)
+       {
+       case 't':
+               export_type(&matches, prefix);
+               break;
 
-               default:
-                       export_value(res, prefix);
-                       break;
-               }
+       default:
+               export_value(&matches, prefix);
+               break;
        }
 
+       list_for_each_entry_safe(item, tmp, &matches, list)
+               free(item);
+
 out:
        if (state)
                jp_free(state);