parser: fix order of declarations
[project/jsonpath.git] / main.c
1 /*
2 * Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #include <stdio.h>
18 #include <stdbool.h>
19 #include <unistd.h>
20 #include <errno.h>
21
22 #ifdef JSONC
23 #include <json.h>
24 #else
25 #include <json-c/json.h>
26 #endif
27
28 #include "lexer.h"
29 #include "parser.h"
30 #include "matcher.h"
31
32 static struct json_object *
33 parse_json(FILE *fd, const char *source, const char **error)
34 {
35 int len;
36 char buf[256];
37 struct json_object *obj = NULL;
38 struct json_tokener *tok = json_tokener_new();
39 enum json_tokener_error err = json_tokener_continue;
40
41 if (!tok)
42 return NULL;
43
44 if (source)
45 {
46 obj = json_tokener_parse_ex(tok, source, strlen(source));
47 err = json_tokener_get_error(tok);
48 }
49 else
50 {
51 while ((len = fread(buf, 1, sizeof(buf), fd)) > 0)
52 {
53 obj = json_tokener_parse_ex(tok, buf, len);
54 err = json_tokener_get_error(tok);
55
56 if (!err || err != json_tokener_continue)
57 break;
58 }
59 }
60
61 json_tokener_free(tok);
62
63 if (err)
64 {
65 if (err == json_tokener_continue)
66 err = json_tokener_error_parse_eof;
67
68 *error = json_tokener_error_desc(err);
69 return NULL;
70 }
71
72 return obj;
73 }
74
75 static void
76 print_string(const char *s)
77 {
78 const char *p;
79
80 printf("'");
81
82 for (p = s; *p; p++)
83 {
84 if (*p == '\'')
85 printf("'\"'\"'");
86 else
87 printf("%c", *p);
88 }
89
90 printf("'");
91 }
92
93 static void
94 export_value(struct json_object *jsobj, const char *prefix)
95 {
96 int n, len;
97 bool first = true;
98
99 if (prefix)
100 {
101 switch (json_object_get_type(jsobj))
102 {
103 case json_type_object:
104 printf("export %s=", prefix);
105 json_object_object_foreach(jsobj, key, val)
106 {
107 if (!val)
108 continue;
109
110 if (!first)
111 printf("\\ ");
112
113 print_string(key);
114 first = false;
115 }
116 printf("; ");
117 break;
118
119 case json_type_array:
120 printf("export %s=", prefix);
121 for (n = 0, len = json_object_array_length(jsobj); n < len; n++)
122 {
123 if (!first)
124 printf("\\ ");
125
126 printf("%d", n);
127 first = false;
128 }
129 printf("; ");
130 break;
131
132 case json_type_boolean:
133 printf("export %s=%d; ", prefix, json_object_get_boolean(jsobj));
134 break;
135
136 case json_type_int:
137 printf("export %s=%d; ", prefix, json_object_get_int(jsobj));
138 break;
139
140 case json_type_double:
141 printf("export %s=%f; ", prefix, json_object_get_double(jsobj));
142 break;
143
144 case json_type_string:
145 printf("export %s=", prefix);
146 print_string(json_object_get_string(jsobj));
147 printf("; ");
148 break;
149
150 case json_type_null:
151 break;
152 }
153 }
154 else
155 {
156 printf("%s\n", json_object_to_json_string(jsobj));
157 }
158 }
159
160 static void
161 export_type(struct json_object *jsobj, const char *prefix)
162 {
163 const char *types[] = {
164 "null",
165 "boolean",
166 "double",
167 "int",
168 "object",
169 "array",
170 "string"
171 };
172
173 if (prefix)
174 printf("export %s=%s; ", prefix, types[json_object_get_type(jsobj)]);
175 else
176 printf("%s\n", types[json_object_get_type(jsobj)]);
177 }
178
179 static bool
180 filter_json(int opt, struct json_object *jsobj, char *expr)
181 {
182 struct jp_state *state;
183 struct json_object *res = NULL;
184 const char *prefix = NULL;
185
186 state = jp_parse(expr);
187
188 if (!state || state->error)
189 {
190 fprintf(stderr, "In expression '%s': %s\n",
191 expr, state ? state->error : "Out of memory");
192
193 goto out;
194 }
195
196 res = jp_match(state->path, jsobj);
197
198 if (res)
199 {
200 prefix = (state->path->type == T_LABEL) ? state->path->str : NULL;
201
202 switch (opt)
203 {
204 case 't':
205 export_type(res, prefix);
206 break;
207
208 default:
209 export_value(res, prefix);
210 break;
211 }
212 }
213
214 out:
215 if (state)
216 jp_free(state);
217
218 return !!res;
219 }
220
221 int main(int argc, char **argv)
222 {
223 int opt, rv = 0;
224 FILE *input = stdin;
225 struct json_object *jsobj = NULL;
226 const char *jserr = NULL, *source = NULL;
227
228 while ((opt = getopt(argc, argv, "i:s:e:t:q")) != -1)
229 {
230 switch (opt)
231 {
232 case 'i':
233 input = fopen(optarg, "r");
234
235 if (!input)
236 {
237 fprintf(stderr, "Failed to open %s: %s\n",
238 optarg, strerror(errno));
239
240 rv = 125;
241 goto out;
242 }
243
244 break;
245
246 case 's':
247 source = optarg;
248 break;
249
250 case 't':
251 case 'e':
252 if (!jsobj)
253 {
254 jsobj = parse_json(input, source, &jserr);
255
256 if (!jsobj)
257 {
258 fprintf(stderr, "Failed to parse json data: %s\n",
259 jserr);
260
261 rv = 126;
262 goto out;
263 }
264 }
265
266 if (!filter_json(opt, jsobj, optarg))
267 rv = 1;
268
269 break;
270
271 case 'q':
272 fclose(stderr);
273 break;
274 }
275 }
276
277 out:
278 if (jsobj)
279 json_object_put(jsobj);
280
281 if (input != stdin)
282 fclose(input);
283
284 return rv;
285 }