1 #define _GNU_SOURCE
2 #include <ctype.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <stdlib.h>
6 #include <sys/param.h>
7 #include <sys/stat.h>
8 #include <unistd.h>
9 #include <jansson.h>
10 #include <errno.h>
11 #include <sys/types.h>
12 
13 // MIT licensed, (c) 2011 Kyle Keen <keenerd@gmail.com>
14 
15 /*
16     build with gcc -o jshon jshon.c -ljansson
17 
18     stdin is always json
19     stdout is always json (except for -u, -t, -l, -k)
20 
21     -P -> detect and ignore JSONP wrapper, if present
22     -S -> sort keys when writing objects
23     -Q -> quiet, suppress stderr
24     -V -> enable slower/safer pass-by-value
25     -C -> continue through errors
26     -F path -> read from file instead of stdin
27     -I -> change file in place, requires -F
28     -0 -> null delimiters
29 
30     -t(ype) -> str, object, list, number, bool, null
31     -l(ength) -> only works on str, dict, list
32     -k(eys) -> only works on dict
33     -e(xtract) index -> only works on dict, list
34     -s(tring) value -> adds json escapes
35     -n(onstring) value -> creates true/false/null/array/object/int/float
36     -u(nstring) -> removes json escapes, display value
37     -j(son literal) -> preserves json escapes, display value
38     -p(op) -> pop/undo the last manipulation
39     -d(elete) index -> remove an element from an object or array
40     -i(nsert) index -> opposite of extract, merges json up the stack
41                        objects will overwrite, arrays will insert
42                        arrays can take negative numbers or 'append'
43     -a(cross) -> iterate across the current dict or list
44 
45     --version -> returns an arbitrary number, exits
46 
47     Multiple commands can be chained.
48     Entire json is loaded into memory.
49     -e/-a copies and stores on a stack with -V.
50     Could use up a lot of memory, usually does not.
51     (For now we don't have to worry about circular refs,
52     but adding 'swap' breaks that proof.)
53 
54     Consider a golf mode with shortcuts for -e -a -u -p -l
55     -g 'results.*.Name.!.^.Version.!.^.Description.!'
56     -g 'data.children.*.data.url.!'
57     -g 'c.d.!.^.e.!'
58     (! on object/array does -l)
59     If you have keys with .!^* in them, use the normal options.
60     Implementing this is going to be a pain.
61     Maybe overwrite the original argv data?
62     Maybe two nested parse loops?
63 
64     -L(abel)
65     add jsonpipe/style/prefix/labels\t to pretty-printed json
66 
67     color?
68     loadf for stdin?
69 */
70 
71 #define JSHONVER 20131105
72 
73 // deal with API incompatibility between jansson 1.x and 2.x
74 #ifndef JANSSON_MAJOR_VERSION
75 #  define JANSSON_MAJOR_VERSION (1)
76 #endif
77 
78 #if JANSSON_MAJOR_VERSION < 2
79 #  define compat_json_loads json_loads
80 #else
compat_json_loads(const char * input,json_error_t * error)81 static json_t *compat_json_loads(const char *input, json_error_t *error)
82 {
83     return json_loads(input, 0, error);
84 }
85 #endif
86 
87 #if JANSSON_VERSION_HEX < 0x020400
88 #  define JSON_ESCAPE_SLASH 0
89 #endif
90 
91 #if (defined (__SVR4) && defined (__sun)) || defined (_WIN32)
92 #include <stdarg.h>
93 
94 #ifdef _WIN32
95 typedef unsigned int uint;
96 // Avoid no-declared error for mingw/gcc with -std=c99.
97 extern int fileno(FILE*);
98 extern char* strdup(const char*);
99 #endif
100 
asprintf(char ** ret,const char * format,...)101 int asprintf(char **ret, const char *format, ...)
102 {
103     va_list ap;
104     fprintf(stderr, "%s\n", "in the asprintf");
105 
106     *ret = NULL;  /* Ensure value can be passed to free() */
107 
108     va_start(ap, format);
109     int count = vsnprintf(NULL, 0, format, ap);
110     va_end(ap);
111 
112     if (count >= 0)
113     {
114         char* buffer = malloc(count + 1);
115         if (buffer == NULL)
116             {return -1;}
117 
118         va_start(ap, format);
119         count = vsnprintf(buffer, count + 1, format, ap);
120         va_end(ap);
121 
122         if (count < 0)
123         {
124             free(buffer);
125             return count;
126         }
127         *ret = buffer;
128     }
129 
130     return count;
131 }
132 #endif
133 
134 int dumps_flags = JSON_INDENT(1) | JSON_PRESERVE_ORDER | JSON_ESCAPE_SLASH;
135 int dumps_compact = JSON_INDENT(0) | JSON_COMPACT | JSON_PRESERVE_ORDER | JSON_ESCAPE_SLASH;
136 int by_value = 0;
137 int in_place = 0;
138 char delim = '\n';
139 char* file_path = "";
140 
141 // for error reporting
142 int quiet = 0;
143 int crash = 1;
144 char** g_argv;
145 
146 // stack depth is limited by maxargs
147 // if you need more depth, use a SAX parser
148 #define STACKDEPTH 128
149 
150 json_t* stack[STACKDEPTH];
151 json_t** stackpointer = stack;
152 
err(char * message)153 void err(char* message)
154 // also see arg_err() and json_err() below
155 {
156     if (!quiet)
157         {fprintf(stderr, "%s\n", message);}
158     if (crash)
159         {exit(1);}
160 }
161 
hard_err(char * message)162 void hard_err(char* message)
163 {
164     err(message);
165     exit(1);
166 }
167 
arg_err(char * message)168 void arg_err(char* message)
169 {
170     char* temp;
171     int i;
172     i = asprintf(&temp, message, optind-1, g_argv[optind-1]);
173     if (i == -1)
174         {hard_err("internal error: out of memory");}
175     err(temp);
176 }
177 
PUSH(json_t * json)178 void PUSH(json_t* json)
179 {
180     if (stackpointer >= &stack[STACKDEPTH])
181         {hard_err("internal error: stack overflow");}
182     if (json == NULL)
183     {
184         arg_err("parse error: bad json on arg %i, \"%s\"");
185         json = json_null();
186     }
187     *stackpointer++ = json;
188 }
189 
stack_safe_peek()190 json_t** stack_safe_peek()
191 {
192     if (stackpointer < &stack[1])
193     {
194         err("internal error: stack underflow");
195         PUSH(json_null());
196     }
197     return stackpointer - 1;
198 }
199 
200 // can not use two macros on the same line
201 #define POP        *((stackpointer = stack_safe_peek()))
202 #define PEEK       *(stack_safe_peek())
203 
maybe_deep(json_t * json)204 json_t* maybe_deep(json_t* json)
205 {
206     if (by_value)
207         {return json_deep_copy(json);}
208     return json;
209 }
210 
211 typedef struct
212 {
213     void*    itr;  // object iterator
214     json_t** stk;  // stack reentry
215     uint     lin;  // array iterator
216     int      opt;  // optind reentry
217     int      fin;  // finished iteration
218 } mapping;
219 
220 mapping mapstack[STACKDEPTH];
221 mapping* mapstackpointer = mapstack;
222 
map_safe_peek()223 mapping* map_safe_peek()
224 {
225     if (mapstackpointer < &mapstack[1])
226         {hard_err("internal error: mapstack underflow");}
227     return mapstackpointer - 1;
228 }
229 
MAPPUSH()230 void MAPPUSH()
231 {
232     if (mapstackpointer >= &mapstack[STACKDEPTH])
233         {hard_err("internal error: mapstack overflow");}
234     mapstackpointer++;
235     map_safe_peek()->stk = stack_safe_peek();
236     map_safe_peek()->opt = optind;
237     switch (json_typeof(PEEK))
238     {
239         case JSON_OBJECT:
240             map_safe_peek()->itr = json_object_iter(PEEK);
241             map_safe_peek()->fin = !map_safe_peek()->itr;
242             break;
243         case JSON_ARRAY:
244             map_safe_peek()->lin = 0;
245             map_safe_peek()->fin = json_array_size(*(map_safe_peek()->stk)) == 0;
246             break;
247         default:
248             err("parse error: type not mappable");
249     }
250 }
251 
MAPNEXT()252 void MAPNEXT()
253 {
254     stackpointer = map_safe_peek()->stk + 1;
255     optind = map_safe_peek()->opt;
256     switch (json_typeof(*(map_safe_peek()->stk)))
257     {
258         case JSON_OBJECT:
259             json_object_iter_key(map_safe_peek()->itr);
260             PUSH(maybe_deep(json_object_iter_value(map_safe_peek()->itr)));
261             map_safe_peek()->itr = json_object_iter_next(*(map_safe_peek()->stk), map_safe_peek()->itr);
262             if (!map_safe_peek()->itr)
263                 {map_safe_peek()->fin = 1;}
264             break;
265         case JSON_ARRAY:
266             PUSH(maybe_deep(json_array_get(*(map_safe_peek()->stk), map_safe_peek()->lin)));
267             map_safe_peek()->lin++;
268             if (map_safe_peek()->lin >= json_array_size(*(map_safe_peek()->stk)))
269                 {map_safe_peek()->fin = 1;}
270             break;
271         default:
272             err("parse error: type not mappable");
273             map_safe_peek()->fin = 1;
274     }
275 }
276 
MAPPOP()277 void MAPPOP()
278 {
279     stackpointer = map_safe_peek()->stk;
280     optind = map_safe_peek()->opt;
281     mapstackpointer = map_safe_peek();
282 }
283 
284 // can not use two macros on the same line
285 #define MAPPEEK       *(map_safe_peek())
286 #define MAPEMPTY      (mapstackpointer == mapstack)
287 
loop_read_fd(int fd)288 char* loop_read_fd(int fd)
289 {
290     char buffer[BUFSIZ];
291     char *content = NULL;
292     size_t content_size = 0;
293     size_t content_capacity = BUFSIZ * 2.5;
294 
295     content = malloc(content_capacity);
296     if (content == NULL)
297     {
298         fprintf(stderr, "error: failed to allocate %zd bytes\n", content_capacity);
299         return NULL;
300     }
301 
302     for (;;)
303     {
304         ssize_t bytes_r = read(fd, buffer, sizeof(buffer));
305         if (bytes_r < 0)
306         {
307             fprintf(stderr, "error: failed to read from fd: %s\n", strerror(errno));
308             goto fail;
309         }
310 
311         if (bytes_r == 0)
312         {
313             return content;
314         }
315 
316         if (content_size + bytes_r >= content_capacity)
317         {
318             content_capacity *= 2.5;
319             void *newalloc = realloc(content, content_capacity);
320             if (newalloc == NULL)
321             {
322                 fprintf(stderr, "error: failed to reallocate buffer to %zd bytes\n",
323                         content_capacity);
324                 goto fail;
325             }
326             content = newalloc;
327         }
328 
329         memcpy(&content[content_size], buffer, bytes_r);
330         content_size += bytes_r;
331         content[content_size] = '\0';
332     }
333 
334     return content;
335 
336 fail:
337     free(content);
338     return NULL;
339 }
340 
read_stream(FILE * fp)341 char* read_stream(FILE* fp)
342 {
343     struct stat st;
344     char *buffer;
345 
346     if (fstat(fileno(fp), &st) < 0)
347     {
348         fprintf(stderr, "failed to stat file: %s\n", strerror(errno));
349         return NULL;
350     }
351 
352     if (st.st_size == 0 && lseek(fileno(fp), 0, SEEK_CUR) < 0)
353     {
354         return loop_read_fd(fileno(fp));
355     }
356 
357     buffer = malloc(st.st_size + 1);
358     if (buffer == NULL)
359     {
360         fprintf(stderr, "error: failed to allocate %zd bytes\n", (ssize_t)(st.st_size + 1));
361         return NULL;
362     }
363 
364     size_t bytes_r = fread(buffer, 1, st.st_size, fp);
365     if ((ssize_t)bytes_r != st.st_size)
366     {
367         fprintf(stderr, "short read: expected to read %zd bytes, only got %zd\n",
368                 (ssize_t)st.st_size, (ssize_t)bytes_r);
369     }
370 
371     buffer[bytes_r] = 0;
372 
373     return buffer;
374 }
375 
read_stdin(void)376 char* read_stdin(void)
377 {
378     if (isatty(fileno(stdin)))
379         {return "";}
380     return read_stream(stdin);
381 }
382 
read_file(char * path)383 char* read_file(char* path)
384 {
385     FILE* fp;
386     char* content;
387     fp = fopen(path, "r");
388     if ( !fp ) {
389       fprintf(stderr, "unable to read file %s: %s\n", path, strerror(errno));
390       return NULL;
391     }
392     content = read_stream(fp);
393     fclose(fp);
394     return content;
395 }
396 
remove_jsonp_callback(char * in,int * rows_skipped,int * cols_skipped)397 char* remove_jsonp_callback(char* in, int* rows_skipped, int* cols_skipped)
398 // this 'removes' jsonp callback code which can surround json, by returning
399 // a pointer to first byte of real JSON, and overwriting the jsonp stuff at
400 // the end of the input with a null byte. it also writes out the number of
401 // lines, and then columns, which were skipped over.
402 //
403 // if a legitimate jsonp callback surround is not detected, the original
404 // input is returned and no other action is taken. this means that JSONP
405 // syntax errors will be effectively ignored, and will then fail json parsing
406 //
407 // this doesn't detect all conceivable JSONP wrappings. a simple function call
408 // with a reasonable ASCII identifier will work, and that covers 99% of the
409 // real world
410 {
411     #define JSON_WHITE(x) ((x) == 0x20 || (x) == 0x9 || (x) == 0xA || (x) == 0xD)
412     #define JSON_IDENTIFIER(x) (isalnum(x) || (x) == '$' || (x) == '_' || (x) == '.')
413 
414     char* first = in;
415     char* last = in + strlen(in) - 1;
416 
417     // skip over whitespace and semicolons at the end
418     while (first < last && (JSON_WHITE(*last) || *last == ';'))
419         {--last;}
420 
421     // count closing brackets at the end, still skipping whitespace
422     int brackets = 0;
423     while (first < last && (JSON_WHITE(*last) || *last == ')'))
424     {
425         if (*last == ')')
426             {++brackets;}
427         --last;
428     }
429 
430     // no closing brackets? it's not jsonp
431     if (brackets == 0)
432         {return in;}
433 
434     // skip leading whitespace
435     while (first < last && JSON_WHITE(*first))
436         {++first;}
437 
438     // skip leading identifier if present
439     while (first < last && JSON_IDENTIFIER(*first))
440         {++first;}
441 
442     // skip over forward brackets and whitespace, counting down the opening brackets
443     // against the closing brackets we've already done
444     while (first < last && (JSON_WHITE(*first) || *first == '('))
445     {
446         if (*first == '(')
447             {--brackets;}
448         ++first;
449     }
450 
451     // at this point we have a valid jsonp wrapper, provided that the number of opening
452     // and closing brackets matched, and provided the two pointers didn't meet in
453     // the middle (leaving no room for any actual JSON)
454     if (brackets != 0 || !(first < last))
455         {return in;}
456 
457     // count lines and columns skipped over
458     *rows_skipped = *cols_skipped = 0;
459     while (in < first)
460     {
461         ++*cols_skipped;
462         if (*in++ == '\n')
463         {
464             *cols_skipped = 0;
465             ++*rows_skipped;
466         }
467     }
468 
469     // strip off beginning and end
470     *(last+1) = '\0';
471     return first;
472 }
473 
474 #if JANSSON_VERSION_HEX < 0x020100
smart_dumps(json_t * json,int flags)475 char* smart_dumps(json_t* json, int flags)
476 // json_dumps is broken on simple types
477 {
478     char* temp;
479     char* temp2;
480     json_t* j2;
481     int i;
482     if (!flags)
483 	{flags = dumps_flags;}
484     switch (json_typeof(json))
485     {
486         case JSON_OBJECT:
487             return json_dumps(json, flags);
488         case JSON_ARRAY:
489             return json_dumps(json, flags);
490         case JSON_STRING:
491             // hack to print escaped string
492             j2 = json_array();
493             json_array_append(j2, json);
494             temp = json_dumps(j2, JSON_ESCAPE_SLASH);
495             i = asprintf(&temp2, "%.*s", (signed)strlen(temp)-2, &temp[1]);
496             if (i == -1)
497                 {hard_err("internal error: out of memory");}
498             return temp2;
499         case JSON_INTEGER:
500             i = asprintf(&temp, "%" JSON_INTEGER_FORMAT, json_integer_value(json));
501             if (i == -1)
502                 {hard_err("internal error: out of memory");}
503             return temp;
504         case JSON_REAL:
505             i = asprintf(&temp, "%f", json_real_value(json));
506             if (i == -1)
507                 {hard_err("internal error: out of memory");}
508             return temp;
509         case JSON_TRUE:
510             return "true";
511         case JSON_FALSE:
512             return "false";
513         case JSON_NULL:
514             return "null";
515         default:
516             err("internal error: unknown type");
517             return "null";
518     }
519 }
520 #else
smart_dumps(json_t * json,int flags)521 char* smart_dumps(json_t* json, int flags)
522 {
523     if (!flags)
524 	{flags = dumps_flags;}
525     switch (json_typeof(json))
526     {
527         case JSON_OBJECT:
528         case JSON_ARRAY:
529         case JSON_STRING:
530         case JSON_INTEGER:
531         case JSON_REAL:
532         case JSON_TRUE:
533         case JSON_FALSE:
534         case JSON_NULL:
535             return json_dumps(json, flags | JSON_ENCODE_ANY);
536         default:
537             err("internal error: unknown type");
538             return "null";
539     }
540 }
541 #endif
542 
543 /*char* pretty_dumps(json_t* json)
544 // underscore-style colorizing
545 // needs a more or less rewrite of dumps()
546 {
547     int depth = 0;
548     // loop over everything
549     // needs a stack
550     // number, orange
551     // string, green
552     // null, bold white
553     // string, purple?
554 }*/
555 
556 #if JANSSON_VERSION_HEX < 0x020300
smart_loads(char * j_string)557 json_t* smart_loads(char* j_string)
558 // json_loads is broken on simple types
559 {
560     json_t* json;
561     json_error_t error;
562     char *temp;
563     int i;
564     i = asprintf(&temp, "[%s]", j_string);
565     if (i == -1)
566         {hard_err("internal error: out of memory");}
567     json = compat_json_loads(temp, &error);
568     if (!json)
569         {return json_string(j_string);}
570     return json_array_get(json, 0);
571 }
572 #else
smart_loads(char * j_string)573 json_t* smart_loads(char* j_string)
574 {
575     json_error_t error;
576     return json_loads(j_string, JSON_DECODE_ANY, &error);
577 }
578 #endif
579 
pretty_type(json_t * json)580 char* pretty_type(json_t* json)
581 {
582     if (json == NULL)
583         {err("internal error: null pointer"); return "NULL";}
584     switch (json_typeof(json))
585     {
586         case JSON_OBJECT:
587             return "object";
588         case JSON_ARRAY:
589             return "array";
590         case JSON_STRING:
591             return "string";
592         case JSON_INTEGER:
593         case JSON_REAL:
594             return "number";
595         case JSON_TRUE:
596         case JSON_FALSE:
597             return "bool";
598         case JSON_NULL:
599             return "null";
600         default:
601             err("internal error: unknown type");
602             return "NULL";
603     }
604 }
605 
json_err(char * message,json_t * json)606 void json_err(char* message, json_t* json)
607 {
608     char* temp;
609     int i;
610     i = asprintf(&temp, "parse error: type '%s' %s (arg %i)", pretty_type(json), message, optind-1);
611     if (i == -1)
612         {hard_err("internal error: out of memory");}
613     err(temp);
614 }
615 
length(json_t * json)616 int length(json_t* json)
617 {
618     switch (json_typeof(json))
619     {
620         case JSON_OBJECT:
621             return json_object_size(json);
622         case JSON_ARRAY:
623             return json_array_size(json);
624         case JSON_STRING:
625             return strlen(json_string_value(json));
626         case JSON_INTEGER:
627         case JSON_REAL:
628         case JSON_TRUE:
629         case JSON_FALSE:
630         case JSON_NULL:
631         default:
632             json_err("has no length", json);
633             return 0;
634     }
635 }
636 
compare_strcmp(const void * a,const void * b)637 int compare_strcmp(const void *a, const void *b)
638 {
639     const char *sa = ((const char**)a)[0];
640     const char *sb = ((const char**)b)[0];
641     return strcmp(sa, sb);
642 }
643 
keys(json_t * json)644 void keys(json_t* json)
645 // shoddy, prints directly
646 {
647     void* iter;
648     const char** keys;
649     size_t i, n;
650 
651     if (!json_is_object(json))
652         {json_err("has no keys", json); return;}
653     if (!((keys = malloc(sizeof(char*) * json_object_size(json)))))
654         {hard_err("internal error: out of memory");}
655 
656     iter = json_object_iter(json);
657     n = 0;
658     while (iter)
659     {
660         keys[n++] = json_object_iter_key(iter);
661         iter = json_object_iter_next(json, iter);
662     }
663 
664     if (dumps_flags & JSON_SORT_KEYS)
665         {qsort(keys, n, sizeof(char*), compare_strcmp);}
666 
667     for (i = 0; i < n; ++i)
668         {printf("%s\n", keys[i]);}
669 
670     free(keys);
671 }
672 
nonstring(char * arg)673 json_t* nonstring(char* arg)
674 {
675     json_t* temp;
676     char* endptr;
677     if (!strcmp(arg, "null") || !strcmp(arg, "n"))
678         {return json_null();}
679     if (!strcmp(arg, "true") || !strcmp(arg, "t"))
680         {return json_true();}
681     if (!strcmp(arg, "false") || !strcmp(arg, "f"))
682         {return json_false();}
683     if (!strcmp(arg, "array") || !strcmp(arg, "[]"))
684         {return json_array();}
685     if (!strcmp(arg, "object") || !strcmp(arg, "{}"))
686         {return json_object();}
687     errno = 0;
688     temp = json_integer(strtol(arg, &endptr, 10));
689     if (!errno && *endptr=='\0')
690         {return temp;}
691     errno = 0;
692     temp = json_real(strtod(arg, &endptr));
693     if (!errno && *endptr=='\0')
694         {return temp;}
695     arg_err("parse error: illegal nonstring on arg %i, \"%s\"");
696     return json_null();
697 }
698 
unstring(json_t * json)699 const char* unstring(json_t* json)
700 {
701     switch (json_typeof(json))
702     {
703         case JSON_STRING:
704             return json_string_value(json);
705         case JSON_INTEGER:
706         case JSON_REAL:
707         case JSON_TRUE:
708         case JSON_FALSE:
709         case JSON_NULL:
710             return smart_dumps(json, 0);
711         case JSON_OBJECT:
712         case JSON_ARRAY:
713         default:
714             json_err("is not simple/printable", json);
715             return "";
716     }
717 }
718 
estrtol(char * key)719 int estrtol(char* key)
720 // strtol with more error handling
721 {
722     int i;
723     char* endptr;
724     errno = 0;
725     i = strtol(key, &endptr, 10);
726     if (errno || *endptr!='\0')
727     {
728         arg_err("parse error: illegal index on arg %i, \"%s\"");
729         //return json_null();
730         i = 0;
731     }
732     return i;
733 }
734 
extract(json_t * json,char * key)735 json_t* extract(json_t* json, char* key)
736 {
737     int i, s;
738     json_t* temp;
739     switch (json_typeof(json))
740     {
741         case JSON_OBJECT:
742             temp = json_object_get(json, key);
743             if (temp == NULL)
744                 {break;}
745             return temp;
746         case JSON_ARRAY:
747             s = json_array_size(json);
748             if (s == 0)
749                 {json_err("index out of bounds", json); break;}
750             i = estrtol(key);
751             if ((i < -s) || (i >= s))
752                 {json_err("index out of bounds", json);}
753             // stupid fix for a stupid modulus operation
754             while (i<0)
755                 {i+=s;}
756             return json_array_get(json, i % s);
757         case JSON_STRING:
758         case JSON_INTEGER:
759         case JSON_REAL:
760         case JSON_TRUE:
761         case JSON_FALSE:
762         case JSON_NULL:
763         default:
764             break;
765     }
766     json_err("has no elements to extract", json);
767     return json_null();
768 }
769 
delete(json_t * json,char * key)770 json_t* delete(json_t* json, char* key)
771 // no error checking
772 {
773     int i, s;
774     switch (json_typeof(json))
775     {
776         case JSON_OBJECT:
777             json_object_del(json, key);
778             return json;
779         case JSON_ARRAY:
780             s = json_array_size(json);
781             if (s == 0)
782                 {return json;}
783             i = estrtol(key);
784             json_array_remove(json, i % s);
785             return json;
786         case JSON_STRING:
787         case JSON_INTEGER:
788         case JSON_REAL:
789         case JSON_TRUE:
790         case JSON_FALSE:
791         case JSON_NULL:
792         default:
793             json_err("cannot lose elements", json);
794             return json;
795     }
796 }
797 
update_native(json_t * json,char * key,json_t * j_value)798 json_t* update_native(json_t* json, char* key, json_t* j_value)
799 // no error checking
800 {
801     int i, s;
802     switch (json_typeof(json))
803     {
804         case JSON_OBJECT:
805             json_object_set(json, key, j_value);
806             return json;
807         case JSON_ARRAY:
808             if (!strcmp(key, "append"))
809             {
810                 json_array_append(json, j_value);
811                 return json;
812             }
813             // otherwise, insert
814             i = estrtol(key);
815             s = json_array_size(json);
816             if (s == 0)
817                 {i = 0;}
818             else
819                 {i = i % s;}
820             json_array_insert(json, i, j_value);
821             return json;
822         case JSON_STRING:
823         case JSON_INTEGER:
824         case JSON_REAL:
825         case JSON_TRUE:
826         case JSON_FALSE:
827         case JSON_NULL:
828         default:
829             json_err("cannot gain elements", json);
830             return json;
831     }
832 }
833 
update(json_t * json,char * key,char * j_string)834 json_t* update(json_t* json, char* key, char* j_string)
835 {
836     return update_native(json, key, smart_loads(j_string));
837 }
838 
debug_stack(int optchar)839 void debug_stack(int optchar)
840 {
841     json_t** j;
842     printf("BEGIN STACK DUMP %c\n", optchar);
843     for (j=stack; j<stackpointer; j++)
844         {printf("%s\n", smart_dumps(*j, 0));}
845 }
846 
debug_map()847 void debug_map()
848 {
849     mapping* m;
850     printf("BEGIN MAP DUMP\n");
851     for (m=mapstack; m<mapstackpointer; m++)
852         {printf("%s\n", smart_dumps(*(m->stk), 0));}
853 }
854 
main(int argc,char * argv[])855 int main (int argc, char *argv[])
856 #define ALL_OPTIONS "PSQVCI0tlkupajF:e:s:n:d:i:"
857 {
858     char* content = "";
859     char* arg1 = "";
860     FILE* fp;
861     json_t* json = NULL;
862     json_t* jval = NULL;
863     json_error_t error;
864     int output = 1;  // flag if json should be printed
865     int optchar;
866     int jsonp = 0;   // flag if we should tolerate JSONP wrapping
867     int jsonp_rows = 0, jsonp_cols = 0;   // rows+cols skipped over by JSONP prologue
868     int empty;
869     g_argv = argv;
870 
871     // todo: get more jsonp stuff out of main
872 
873     // avoiding getopt_long for now because the BSD version is a pain
874     if (argc == 2 && strncmp(argv[1], "--version", 9) == 0)
875         {printf("%i\n", JSHONVER); exit(0);}
876 
877     // non-manipulation options
878     while ((optchar = getopt(argc, argv, ALL_OPTIONS)) != -1)
879     {
880         switch (optchar)
881         {
882             case 'P':
883                 jsonp = 1;
884                 break;
885             case 'S':
886                 dumps_flags &= ~JSON_PRESERVE_ORDER;
887                 dumps_flags |= JSON_SORT_KEYS;
888                 dumps_compact &= ~JSON_PRESERVE_ORDER;
889                 dumps_compact |= JSON_SORT_KEYS;
890                 break;
891             case 'Q':
892                 quiet = 1;
893                 break;
894             case 'V':
895                 by_value = 1;
896                 break;
897             case 'C':
898                 crash = 0;
899                 break;
900             case 'I':
901                 in_place = 1;
902                 break;
903             case 'F':
904                 file_path = (char*) strdup(optarg);
905                 break;
906             case '0':
907                 delim = '\0';
908                 break;
909             case 't':
910             case 'l':
911             case 'k':
912             case 'u':
913             case 'p':
914             case 'e':
915             case 'j':
916             case 's':
917             case 'n':
918             case 'd':
919             case 'i':
920             case 'a':
921                 break;
922             default:
923                 if (!quiet)
924                     {fprintf(stderr, "Valid: -[P|S|Q|V|C|I|0] [-F path] -[t|l|k|u|p|a|j] -[s|n] value -[e|i|d] index\n");}
925                 if (crash)
926                     {exit(2);}
927                 break;
928         }
929     }
930     optind = 1;
931 #ifdef BSD
932     optreset = 1;
933 #endif
934 
935     if (in_place && strlen(file_path)==0)
936         {err("warning: in-place editing (-I) requires -F");}
937 
938     if (!strcmp(file_path, "-"))
939         {content = read_stdin();}
940     else if (strlen(file_path) > 0)
941         {content = read_file(file_path);}
942     else
943         {content = read_stdin();}
944     if (!content) {
945       fprintf(stderr, "error: failed to read input\n");
946       exit(1);
947     }
948 
949     if (jsonp)
950         {content = remove_jsonp_callback(content, &jsonp_rows, &jsonp_cols);}
951 
952     if (content[0])
953         {json = compat_json_loads(content, &error);}
954 
955     if (!json && content[0])
956     {
957         const char *jsonp_status = "";
958         if (jsonp)
959             {jsonp_status = (jsonp_rows||jsonp_cols) ? "(jsonp detected) " : "(jsonp not detected) ";}
960 
961 #if JANSSON_MAJOR_VERSION < 2
962         if (!quiet)
963             {fprintf(stderr, "json %sread error: line %0d: %s\n",
964                  jsonp_status, error.line + jsonp_rows, error.text);}
965 #else
966         if (!quiet)
967             {fprintf(stderr, "json %sread error: line %0d column %0d: %s\n",
968                 jsonp_status, error.line + jsonp_rows, error.column + jsonp_cols, error.text);}
969 #endif
970         exit(1);
971     }
972 
973     if (json)
974         {PUSH(json);}
975 
976     do
977     {
978         if (! MAPEMPTY)
979         {
980             while (map_safe_peek()->fin)
981             {
982                 MAPPOP();
983                 if (MAPEMPTY)
984                     {exit(0);}
985             }
986             MAPNEXT();
987         }
988         while ((optchar = getopt(argc, argv, ALL_OPTIONS)) != -1)
989         {
990             empty = 0;
991             switch (optchar)
992             {
993                 case 't':  // id type
994                     printf("%s\n", pretty_type(PEEK));
995                     output = 0;
996                     break;
997                 case 'l':  // length
998                     printf("%i\n", length(PEEK));
999                     output = 0;
1000                     break;
1001                 case 'k':  // keys
1002                     keys(PEEK);
1003                     output = 0;
1004                     break;
1005                 case 'u':  // unescape string
1006                     printf("%s%c", unstring(PEEK), delim);
1007                     output = 0;
1008                     break;
1009                 case 'p':  // pop stack
1010                     json = POP;
1011                     if (by_value)
1012                         {json_decref(json);}
1013                     output = 1;
1014                     break;
1015                 case 's':  // load string
1016                     arg1 = (char*) strdup(optarg);
1017                     PUSH(json_string(arg1));
1018                     output = 1;
1019                     break;
1020                 case 'n':  // load nonstring
1021                     arg1 = (char*) strdup(optarg);
1022                     PUSH(nonstring(arg1));
1023                     output = 1;
1024                     break;
1025                 case 'e':  // extract
1026                     arg1 = (char*) strdup(optarg);
1027                     json = PEEK;
1028                     PUSH(extract(maybe_deep(json), arg1));
1029                     output = 1;
1030                     break;
1031                 case 'j':  // json literal
1032                     printf("%s%c", smart_dumps(PEEK, dumps_compact), delim);
1033                     output = 0;
1034                     break;
1035                 case 'd':  // delete
1036                     arg1 = (char*) strdup(optarg);
1037                     json = POP;
1038                     PUSH(delete(json, arg1));
1039                     output = 1;
1040                     break;
1041                 case 'i':  // insert
1042                     arg1 = (char*) strdup(optarg);
1043                     jval = POP;
1044                     json = POP;
1045                     PUSH(update_native(json, arg1, jval));
1046                     output = 1;
1047                     break;
1048                 case 'a':  // across
1049                     // something about -a is not mappable?
1050                     MAPPUSH();
1051                     empty = map_safe_peek()->fin;
1052                     if (!empty)
1053                         {MAPNEXT();}
1054                     output = 0;
1055                     break;
1056                 case 'P':  // not manipulations
1057                 case 'S':
1058                 case 'Q':
1059                 case 'V':
1060                 case 'C':
1061                 case 'I':
1062                 case 'F':
1063                 case '0':
1064                     break;
1065                 default:
1066                     if (crash)
1067                         {exit(2);}
1068                     break;
1069             }
1070             if (empty)
1071                 {break;}
1072         }
1073         if (!in_place && output && stackpointer != stack)
1074             {printf("%s\n", smart_dumps(PEEK, 0));}
1075     } while (! MAPEMPTY);
1076 
1077     if (in_place && strlen(file_path) > 0)
1078     {
1079         fp = fopen(file_path, "w");
1080         fprintf(fp, "%s\n", smart_dumps(stack[0], 0));
1081         fclose(fp);
1082     }
1083     return 0;
1084 }
1085 
1086 
1087