Fossil SCM

Consolidated more of the CLI/HTTP/CLI-with-POST arg handling disparities into the json_find_option() family of functions.

stephan 2011-10-05 02:26 UTC json-multitag-test
Commit 5b4a3f12dc47424fbce0a77a046e03663cfdaa56
+111 -36
--- src/json.c
+++ src/json.c
@@ -183,10 +183,30 @@
183183
#define BEGIN_TIMER
184184
#define END_TIMER 0.0
185185
#define HAS_TIMER 0
186186
#endif
187187
188
+
189
+/*
190
+** Returns true if fossil is running in JSON mode and we are either
191
+** running in HTTP mode OR g.json.post.o is not NULL (meaning POST
192
+** data was fed in from CLI mode).
193
+**
194
+** Specifically, it will return false when any of these apply:
195
+**
196
+** a) Not running in JSON mode (via json command or /json path).
197
+**
198
+** b) We are running in JSON CLI mode, but no POST data has been fed
199
+** in.
200
+**
201
+** Whether or not we need to take args from CLI or POST data makes a
202
+** difference in argument/parameter handling in many JSON rountines.
203
+*/
204
+char fossil_is_json(){
205
+ return g.json.isJsonMode && (g.isHTTP || g.json.post.o);
206
+}
207
+
188208
/*
189209
** Placeholder /json/XXX page impl for NYI (Not Yet Implemented)
190210
** (but planned) pages/commands.
191211
*/
192212
cson_value * json_page_nyi(){
@@ -466,10 +486,16 @@
466486
** json_getenv_int(), with the addition that string values which
467487
** either start with a digit 1..9 or the letters [tT] are considered
468488
** to be true. If this function cannot find a matching key/value then
469489
** dflt is returned. e.g. if it finds the key but the value is-a
470490
** Object then dftl is returned.
491
+**
492
+** If an entry is found, this function guarantees that it will return
493
+** either 0 or 1, as opposed to "0 or non-zero", so that clients can
494
+** pass a different value as dflt. Thus they can use, e.g. -1 to know
495
+** whether or not this function found a match (it will return -1 in
496
+** that case).
471497
*/
472498
char json_getenv_bool(char const * pKey, char dflt ){
473499
cson_value const * v = json_getenv(pKey);
474500
if(!v){
475501
return dflt;
@@ -501,10 +527,82 @@
501527
** internals via cgi_replace_parameter() and friends or json_setenv().
502528
*/
503529
char const * json_getenv_cstr( char const * zKey ){
504530
return cson_value_get_cstr( json_getenv(zKey) );
505531
}
532
+
533
+/*
534
+** An extended form of find_option() which tries to look up a combo
535
+** GET/POST/CLI argument.
536
+**
537
+** zKey must be the GET/POST parameter key. zCLILong must be the "long
538
+** form" CLI flag (NULL means to use zKey). zCLIShort may be NUL or
539
+** the "short form" CLI flag.
540
+**
541
+** On error (no match found) NULL is returned.
542
+**
543
+** This ONLY works for String JSON/GET/CLI values, not JSON
544
+** booleans and whatnot.
545
+*/
546
+char const * json_find_option_cstr(char const * zKey,
547
+ char const * zCLILong,
548
+ char const * zCLIShort){
549
+ char const * rc = NULL;
550
+ assert(NULL != zKey);
551
+ if(!g.isHTTP){
552
+ rc = find_option(zCLILong ? zCLILong : zKey,
553
+ zCLIShort, 1);
554
+ }
555
+ if(!rc && fossil_is_json()){
556
+ rc = json_getenv_cstr(zKey);
557
+ }
558
+ return rc;
559
+}
560
+
561
+/*
562
+** The boolean equivalent of json_find_option_cstr().
563
+** If the option is not found, dftl is returned.
564
+*/
565
+char json_find_option_bool(char const * zKey,
566
+ char const * zCLILong,
567
+ char const * zCLIShort,
568
+ char dflt ){
569
+ char rc = -1;
570
+ if(!g.isHTTP){
571
+ if(NULL != find_option(zCLILong ? zCLILong : zKey,
572
+ zCLIShort, 0)){
573
+ rc = 1;
574
+ }
575
+ }
576
+ if((-1==rc) && fossil_is_json()){
577
+ rc = json_getenv_bool(zKey,-1);
578
+ }
579
+ return (-1==rc) ? dflt : rc;
580
+}
581
+
582
+/*
583
+** The integer equivalent of json_find_option_cstr().
584
+** If the option is not found, dftl is returned.
585
+*/
586
+int json_find_option_int(char const * zKey,
587
+ char const * zCLILong,
588
+ char const * zCLIShort,
589
+ int dflt ){
590
+ enum { Magic = -947 };
591
+ int rc = Magic;
592
+ if(!g.isHTTP){
593
+ char const * opt = find_option(zCLILong ? zCLILong : zKey,
594
+ zCLIShort, 1);
595
+ if(NULL!=opt){
596
+ rc = atoi(opt);
597
+ }
598
+ }
599
+ if(Magic==rc){
600
+ rc = json_getenv_int(zKey,Magic);
601
+ }
602
+ return (Magic==rc) ? dflt : rc;
603
+}
506604
507605
508606
/*
509607
** Adds v to g.json.param.o using the given key. May cause any prior
510608
** item with that key to be destroyed (depends on current reference
@@ -1006,45 +1104,26 @@
10061104
if(cmd){
10071105
json_string_split(cmd, '/', 0, g.json.cmd.a);
10081106
g.json.cmd.commandStr = cmd;
10091107
}
10101108
}
1011
-
1012
- if(!g.json.jsonp && g.json.post.o){
1013
- g.json.jsonp =
1014
- json_getenv_cstr("jsonp")
1015
- /*cson_string_cstr(cson_value_get_string(cson_object_get(g.json.post.o,"jsonp")))*/
1016
- ;
1017
- }
1018
- if( !g.isHTTP ){
1019
- g.json.errorDetailParanoia = 0 /*disable error code dumb-down for CLI mode*/;
1020
- if(!g.json.jsonp){
1021
- g.json.jsonp = find_option("jsonp",NULL,1);
1022
- }
1109
+
1110
+
1111
+ if(!g.json.jsonp){
1112
+ g.json.jsonp = json_find_option_cstr("jsonp",NULL,NULL);
1113
+ }
1114
+ if(!g.isHTTP){
1115
+ g.json.errorDetailParanoia = 0 /*disable error code dumb-down for CLI mode*/;
10231116
}
10241117
10251118
{/* set up JSON output formatting options. */
1026
- unsigned char indent = g.isHTTP ? 0 : 1;
1119
+ int indent = -1;
10271120
char const * indentStr = NULL;
1028
- char checkAgain = 1;
1029
- if( g.json.post.v ){
1030
- cson_value const * check = json_getenv("indent");
1031
- if(check){
1032
- checkAgain = 0;
1033
- indent = (unsigned char)json_getenv_int("indent",(int)indent);
1034
- }
1035
- }
1036
- if(!g.isHTTP && checkAgain){/*CLI mode*/
1037
- indentStr = find_option("indent","I",1);
1038
- if(indentStr){
1039
- int const n = atoi(indentStr);
1040
- indent = (n>0)
1041
- ? (unsigned char)n
1042
- : 0;
1043
- }
1044
- }
1045
- g.json.outOpt.indentation = indent;
1121
+ indent = json_find_option_int("indent",NULL,"I",-1);
1122
+ g.json.outOpt.indentation = (0>indent)
1123
+ ? (g.isHTTP ? 0 : 1)
1124
+ : (unsigned char)indent;
10461125
g.json.outOpt.addNewline = g.isHTTP
10471126
? 0
10481127
: (g.json.jsonp ? 0 : 1);
10491128
}
10501129
@@ -1565,15 +1644,11 @@
15651644
if( !g.perm.Read ){
15661645
json_set_err(FSL_JSON_E_DENIED,
15671646
"Requires 'o' permissions.");
15681647
return NULL;
15691648
}
1570
- if( g.isHTTP ){
1571
- full = json_getenv_bool("full",0);
1572
- }else{
1573
- full = (0!=find_option("full","f",0));
1574
- }
1649
+ full = json_find_option_bool("full",NULL,"f",0);
15751650
#define SETBUF(O,K) cson_object_set(O, K, cson_value_new_string(zBuf, strlen(zBuf)));
15761651
15771652
jv = cson_value_new_object();
15781653
jo = cson_value_get_object(jv);
15791654
15801655
--- src/json.c
+++ src/json.c
@@ -183,10 +183,30 @@
183 #define BEGIN_TIMER
184 #define END_TIMER 0.0
185 #define HAS_TIMER 0
186 #endif
187
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
188 /*
189 ** Placeholder /json/XXX page impl for NYI (Not Yet Implemented)
190 ** (but planned) pages/commands.
191 */
192 cson_value * json_page_nyi(){
@@ -466,10 +486,16 @@
466 ** json_getenv_int(), with the addition that string values which
467 ** either start with a digit 1..9 or the letters [tT] are considered
468 ** to be true. If this function cannot find a matching key/value then
469 ** dflt is returned. e.g. if it finds the key but the value is-a
470 ** Object then dftl is returned.
 
 
 
 
 
 
471 */
472 char json_getenv_bool(char const * pKey, char dflt ){
473 cson_value const * v = json_getenv(pKey);
474 if(!v){
475 return dflt;
@@ -501,10 +527,82 @@
501 ** internals via cgi_replace_parameter() and friends or json_setenv().
502 */
503 char const * json_getenv_cstr( char const * zKey ){
504 return cson_value_get_cstr( json_getenv(zKey) );
505 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
506
507
508 /*
509 ** Adds v to g.json.param.o using the given key. May cause any prior
510 ** item with that key to be destroyed (depends on current reference
@@ -1006,45 +1104,26 @@
1006 if(cmd){
1007 json_string_split(cmd, '/', 0, g.json.cmd.a);
1008 g.json.cmd.commandStr = cmd;
1009 }
1010 }
1011
1012 if(!g.json.jsonp && g.json.post.o){
1013 g.json.jsonp =
1014 json_getenv_cstr("jsonp")
1015 /*cson_string_cstr(cson_value_get_string(cson_object_get(g.json.post.o,"jsonp")))*/
1016 ;
1017 }
1018 if( !g.isHTTP ){
1019 g.json.errorDetailParanoia = 0 /*disable error code dumb-down for CLI mode*/;
1020 if(!g.json.jsonp){
1021 g.json.jsonp = find_option("jsonp",NULL,1);
1022 }
1023 }
1024
1025 {/* set up JSON output formatting options. */
1026 unsigned char indent = g.isHTTP ? 0 : 1;
1027 char const * indentStr = NULL;
1028 char checkAgain = 1;
1029 if( g.json.post.v ){
1030 cson_value const * check = json_getenv("indent");
1031 if(check){
1032 checkAgain = 0;
1033 indent = (unsigned char)json_getenv_int("indent",(int)indent);
1034 }
1035 }
1036 if(!g.isHTTP && checkAgain){/*CLI mode*/
1037 indentStr = find_option("indent","I",1);
1038 if(indentStr){
1039 int const n = atoi(indentStr);
1040 indent = (n>0)
1041 ? (unsigned char)n
1042 : 0;
1043 }
1044 }
1045 g.json.outOpt.indentation = indent;
1046 g.json.outOpt.addNewline = g.isHTTP
1047 ? 0
1048 : (g.json.jsonp ? 0 : 1);
1049 }
1050
@@ -1565,15 +1644,11 @@
1565 if( !g.perm.Read ){
1566 json_set_err(FSL_JSON_E_DENIED,
1567 "Requires 'o' permissions.");
1568 return NULL;
1569 }
1570 if( g.isHTTP ){
1571 full = json_getenv_bool("full",0);
1572 }else{
1573 full = (0!=find_option("full","f",0));
1574 }
1575 #define SETBUF(O,K) cson_object_set(O, K, cson_value_new_string(zBuf, strlen(zBuf)));
1576
1577 jv = cson_value_new_object();
1578 jo = cson_value_get_object(jv);
1579
1580
--- src/json.c
+++ src/json.c
@@ -183,10 +183,30 @@
183 #define BEGIN_TIMER
184 #define END_TIMER 0.0
185 #define HAS_TIMER 0
186 #endif
187
188
189 /*
190 ** Returns true if fossil is running in JSON mode and we are either
191 ** running in HTTP mode OR g.json.post.o is not NULL (meaning POST
192 ** data was fed in from CLI mode).
193 **
194 ** Specifically, it will return false when any of these apply:
195 **
196 ** a) Not running in JSON mode (via json command or /json path).
197 **
198 ** b) We are running in JSON CLI mode, but no POST data has been fed
199 ** in.
200 **
201 ** Whether or not we need to take args from CLI or POST data makes a
202 ** difference in argument/parameter handling in many JSON rountines.
203 */
204 char fossil_is_json(){
205 return g.json.isJsonMode && (g.isHTTP || g.json.post.o);
206 }
207
208 /*
209 ** Placeholder /json/XXX page impl for NYI (Not Yet Implemented)
210 ** (but planned) pages/commands.
211 */
212 cson_value * json_page_nyi(){
@@ -466,10 +486,16 @@
486 ** json_getenv_int(), with the addition that string values which
487 ** either start with a digit 1..9 or the letters [tT] are considered
488 ** to be true. If this function cannot find a matching key/value then
489 ** dflt is returned. e.g. if it finds the key but the value is-a
490 ** Object then dftl is returned.
491 **
492 ** If an entry is found, this function guarantees that it will return
493 ** either 0 or 1, as opposed to "0 or non-zero", so that clients can
494 ** pass a different value as dflt. Thus they can use, e.g. -1 to know
495 ** whether or not this function found a match (it will return -1 in
496 ** that case).
497 */
498 char json_getenv_bool(char const * pKey, char dflt ){
499 cson_value const * v = json_getenv(pKey);
500 if(!v){
501 return dflt;
@@ -501,10 +527,82 @@
527 ** internals via cgi_replace_parameter() and friends or json_setenv().
528 */
529 char const * json_getenv_cstr( char const * zKey ){
530 return cson_value_get_cstr( json_getenv(zKey) );
531 }
532
533 /*
534 ** An extended form of find_option() which tries to look up a combo
535 ** GET/POST/CLI argument.
536 **
537 ** zKey must be the GET/POST parameter key. zCLILong must be the "long
538 ** form" CLI flag (NULL means to use zKey). zCLIShort may be NUL or
539 ** the "short form" CLI flag.
540 **
541 ** On error (no match found) NULL is returned.
542 **
543 ** This ONLY works for String JSON/GET/CLI values, not JSON
544 ** booleans and whatnot.
545 */
546 char const * json_find_option_cstr(char const * zKey,
547 char const * zCLILong,
548 char const * zCLIShort){
549 char const * rc = NULL;
550 assert(NULL != zKey);
551 if(!g.isHTTP){
552 rc = find_option(zCLILong ? zCLILong : zKey,
553 zCLIShort, 1);
554 }
555 if(!rc && fossil_is_json()){
556 rc = json_getenv_cstr(zKey);
557 }
558 return rc;
559 }
560
561 /*
562 ** The boolean equivalent of json_find_option_cstr().
563 ** If the option is not found, dftl is returned.
564 */
565 char json_find_option_bool(char const * zKey,
566 char const * zCLILong,
567 char const * zCLIShort,
568 char dflt ){
569 char rc = -1;
570 if(!g.isHTTP){
571 if(NULL != find_option(zCLILong ? zCLILong : zKey,
572 zCLIShort, 0)){
573 rc = 1;
574 }
575 }
576 if((-1==rc) && fossil_is_json()){
577 rc = json_getenv_bool(zKey,-1);
578 }
579 return (-1==rc) ? dflt : rc;
580 }
581
582 /*
583 ** The integer equivalent of json_find_option_cstr().
584 ** If the option is not found, dftl is returned.
585 */
586 int json_find_option_int(char const * zKey,
587 char const * zCLILong,
588 char const * zCLIShort,
589 int dflt ){
590 enum { Magic = -947 };
591 int rc = Magic;
592 if(!g.isHTTP){
593 char const * opt = find_option(zCLILong ? zCLILong : zKey,
594 zCLIShort, 1);
595 if(NULL!=opt){
596 rc = atoi(opt);
597 }
598 }
599 if(Magic==rc){
600 rc = json_getenv_int(zKey,Magic);
601 }
602 return (Magic==rc) ? dflt : rc;
603 }
604
605
606 /*
607 ** Adds v to g.json.param.o using the given key. May cause any prior
608 ** item with that key to be destroyed (depends on current reference
@@ -1006,45 +1104,26 @@
1104 if(cmd){
1105 json_string_split(cmd, '/', 0, g.json.cmd.a);
1106 g.json.cmd.commandStr = cmd;
1107 }
1108 }
1109
1110
1111 if(!g.json.jsonp){
1112 g.json.jsonp = json_find_option_cstr("jsonp",NULL,NULL);
1113 }
1114 if(!g.isHTTP){
1115 g.json.errorDetailParanoia = 0 /*disable error code dumb-down for CLI mode*/;
 
 
 
 
 
1116 }
1117
1118 {/* set up JSON output formatting options. */
1119 int indent = -1;
1120 char const * indentStr = NULL;
1121 indent = json_find_option_int("indent",NULL,"I",-1);
1122 g.json.outOpt.indentation = (0>indent)
1123 ? (g.isHTTP ? 0 : 1)
1124 : (unsigned char)indent;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1125 g.json.outOpt.addNewline = g.isHTTP
1126 ? 0
1127 : (g.json.jsonp ? 0 : 1);
1128 }
1129
@@ -1565,15 +1644,11 @@
1644 if( !g.perm.Read ){
1645 json_set_err(FSL_JSON_E_DENIED,
1646 "Requires 'o' permissions.");
1647 return NULL;
1648 }
1649 full = json_find_option_bool("full",NULL,"f",0);
 
 
 
 
1650 #define SETBUF(O,K) cson_object_set(O, K, cson_value_new_string(zBuf, strlen(zBuf)));
1651
1652 jv = cson_value_new_object();
1653 jo = cson_value_get_object(jv);
1654
1655
--- src/json_artifact.c
+++ src/json_artifact.c
@@ -225,17 +225,16 @@
225225
cson_value * entry = NULL;
226226
Blob uuid = empty_blob;
227227
int rc;
228228
int rid = 0;
229229
ArtifactDispatchEntry const * dispatcher = &ArtifactDispatchList[0];
230
- zName = g.isHTTP
231
- ? json_getenv_cstr("uuid")
232
- : find_option("uuid","u",1);
230
+ zName = json_find_option_cstr("uuid",NULL,"u");
233231
if(!zName||!*zName){
234232
zName = json_command_arg(g.json.dispatchDepth+1);
235233
if(!zName || !*zName) {
236
- g.json.resultCode = FSL_JSON_E_MISSING_ARGS;
234
+ json_set_err(FSL_JSON_E_MISSING_ARGS,
235
+ "Missing 'uuid' argument.");
237236
return NULL;
238237
}
239238
}
240239
241240
if( validate16(zName, strlen(zName)) ){
242241
--- src/json_artifact.c
+++ src/json_artifact.c
@@ -225,17 +225,16 @@
225 cson_value * entry = NULL;
226 Blob uuid = empty_blob;
227 int rc;
228 int rid = 0;
229 ArtifactDispatchEntry const * dispatcher = &ArtifactDispatchList[0];
230 zName = g.isHTTP
231 ? json_getenv_cstr("uuid")
232 : find_option("uuid","u",1);
233 if(!zName||!*zName){
234 zName = json_command_arg(g.json.dispatchDepth+1);
235 if(!zName || !*zName) {
236 g.json.resultCode = FSL_JSON_E_MISSING_ARGS;
 
237 return NULL;
238 }
239 }
240
241 if( validate16(zName, strlen(zName)) ){
242
--- src/json_artifact.c
+++ src/json_artifact.c
@@ -225,17 +225,16 @@
225 cson_value * entry = NULL;
226 Blob uuid = empty_blob;
227 int rc;
228 int rid = 0;
229 ArtifactDispatchEntry const * dispatcher = &ArtifactDispatchList[0];
230 zName = json_find_option_cstr("uuid",NULL,"u");
 
 
231 if(!zName||!*zName){
232 zName = json_command_arg(g.json.dispatchDepth+1);
233 if(!zName || !*zName) {
234 json_set_err(FSL_JSON_E_MISSING_ARGS,
235 "Missing 'uuid' argument.");
236 return NULL;
237 }
238 }
239
240 if( validate16(zName, strlen(zName)) ){
241
+42 -40
--- src/json_branch.c
+++ src/json_branch.c
@@ -77,30 +77,31 @@
7777
}
7878
payV = cson_value_new_object();
7979
pay = cson_value_get_object(payV);
8080
listV = cson_value_new_array();
8181
list = cson_value_get_array(listV);
82
- if(!g.isHTTP){
83
- range = find_option("range","r",1);
84
- if(!range||!*range){
85
- range = find_option("all","a",0);
86
- if(range && *range){
87
- range = "a";
88
- }else{
89
- range = find_option("closed","c",0);
90
- if(range&&*range){
91
- range = "c";
92
- }
93
- }
94
- }
95
- }else{
96
- range = json_getenv_cstr("range");
97
- }
82
+ if(fossil_is_json()){
83
+ range = json_getenv_cstr("range");
84
+ }
85
+
86
+ range = json_find_option_cstr("range",NULL,"r");
87
+ if((!range||!*range) && !g.isHTTP){
88
+ range = find_option("all","a",0);
89
+ if(range && *range){
90
+ range = "a";
91
+ }else{
92
+ range = find_option("closed","c",0);
93
+ if(range&&*range){
94
+ range = "c";
95
+ }
96
+ }
97
+ }
98
+
9899
if(!range || !*range){
99100
range = "o";
100101
}
101
- assert( (NULL != range) && *range );
102
+ /* Normalize range values... */
102103
switch(*range){
103104
case 'c':
104105
range = "closed";
105106
which = -1;
106107
break;
@@ -111,11 +112,11 @@
111112
default:
112113
range = "open";
113114
which = 0;
114115
break;
115116
};
116
- cson_object_set(pay,"range",cson_value_new_string(range,strlen(range)));
117
+ cson_object_set(pay,"range",json_new_string(range));
117118
118119
if( g.localOpen ){ /* add "current" property (branch name). */
119120
int vid = db_lget_int("checkout", 0);
120121
char const * zCurrent = vid
121122
? db_text(0, "SELECT value FROM tagxref"
@@ -324,46 +325,47 @@
324325
if( !g.perm.Write ){
325326
json_set_err(FSL_JSON_E_DENIED,
326327
"Requires 'i' permissions.");
327328
return NULL;
328329
}
329
- if(0){
330
- char const * x = json_command_arg(g.json.dispatchDepth+1);
331
- fprintf(stderr,"command arg=%s\n",x);
332
- assert(0);
333
- }
334330
memset(&opt,0,sizeof(BranchCreateOptions));
335
- opt.zName = g.json.post.v
336
- ? json_getenv_cstr("name")
337
- : json_command_arg(g.json.dispatchDepth+1);
331
+ if(fossil_is_json()){
332
+ opt.zName = json_getenv_cstr("name");
333
+ }
334
+
335
+ if(!opt.zName){
336
+ opt.zName = json_command_arg(g.json.dispatchDepth+1);
337
+ }
338338
339339
if(!opt.zName){
340340
json_set_err(FSL_JSON_E_MISSING_ARGS, "'name' parameter was not specified." );
341341
return NULL;
342342
}
343343
344
- opt.zBasis = g.json.post.v
345
- ? json_getenv_cstr("basis")
346
- : json_command_arg(g.json.dispatchDepth+2);
347
- if(!opt.zBasis || ('-'==*opt.zBasis/*assume CLI flag*/)){
344
+ opt.zColor = json_find_option_cstr("bgColor","bgcolor",NULL);
345
+ opt.zBasis = json_find_option_cstr("basis",NULL,NULL);
346
+ if(!opt.zBasis && !g.isHTTP){
347
+ opt.zBasis = json_command_arg(g.json.dispatchDepth+2);
348
+ }
349
+ if(!opt.zBasis){
348350
opt.zBasis = "trunk";
349351
}
350
-
351
- opt.zColor = g.json.post.v
352
- ? json_getenv_cstr("bgColor")
353
- : find_option("bgcolor","",1);
354
-
355
- opt.isPrivate = g.json.post.v
356
- ? json_getenv_bool("private",0)
357
- : (NULL != find_option("private","",0))
358
- ;
352
+ opt.isPrivate = json_find_option_bool("private",NULL,NULL,-1);
353
+ if(-1==opt.isPrivate){
354
+ if(!g.isHTTP){
355
+ opt.isPrivate = (NULL != find_option("private","",0));
356
+ }else{
357
+ opt.isPrivate = 0;
358
+ }
359
+ }
359360
360361
rc = json_branch_new( &opt, &rid );
361362
if(rc){
362
- json_set_err(rc, opt.rcErrMsg );
363
+ json_set_err(rc, opt.rcErrMsg);
363364
goto error;
364365
}
366
+ assert(0 != rid);
365367
payV = cson_value_new_object();
366368
pay = cson_value_get_object(payV);
367369
368370
cson_object_set(pay,"name",json_new_string(opt.zName));
369371
cson_object_set(pay,"basis",json_new_string(opt.zBasis));
370372
--- src/json_branch.c
+++ src/json_branch.c
@@ -77,30 +77,31 @@
77 }
78 payV = cson_value_new_object();
79 pay = cson_value_get_object(payV);
80 listV = cson_value_new_array();
81 list = cson_value_get_array(listV);
82 if(!g.isHTTP){
83 range = find_option("range","r",1);
84 if(!range||!*range){
85 range = find_option("all","a",0);
86 if(range && *range){
87 range = "a";
88 }else{
89 range = find_option("closed","c",0);
90 if(range&&*range){
91 range = "c";
92 }
93 }
94 }
95 }else{
96 range = json_getenv_cstr("range");
97 }
 
98 if(!range || !*range){
99 range = "o";
100 }
101 assert( (NULL != range) && *range );
102 switch(*range){
103 case 'c':
104 range = "closed";
105 which = -1;
106 break;
@@ -111,11 +112,11 @@
111 default:
112 range = "open";
113 which = 0;
114 break;
115 };
116 cson_object_set(pay,"range",cson_value_new_string(range,strlen(range)));
117
118 if( g.localOpen ){ /* add "current" property (branch name). */
119 int vid = db_lget_int("checkout", 0);
120 char const * zCurrent = vid
121 ? db_text(0, "SELECT value FROM tagxref"
@@ -324,46 +325,47 @@
324 if( !g.perm.Write ){
325 json_set_err(FSL_JSON_E_DENIED,
326 "Requires 'i' permissions.");
327 return NULL;
328 }
329 if(0){
330 char const * x = json_command_arg(g.json.dispatchDepth+1);
331 fprintf(stderr,"command arg=%s\n",x);
332 assert(0);
333 }
334 memset(&opt,0,sizeof(BranchCreateOptions));
335 opt.zName = g.json.post.v
336 ? json_getenv_cstr("name")
337 : json_command_arg(g.json.dispatchDepth+1);
 
 
 
 
338
339 if(!opt.zName){
340 json_set_err(FSL_JSON_E_MISSING_ARGS, "'name' parameter was not specified." );
341 return NULL;
342 }
343
344 opt.zBasis = g.json.post.v
345 ? json_getenv_cstr("basis")
346 : json_command_arg(g.json.dispatchDepth+2);
347 if(!opt.zBasis || ('-'==*opt.zBasis/*assume CLI flag*/)){
 
 
348 opt.zBasis = "trunk";
349 }
350
351 opt.zColor = g.json.post.v
352 ? json_getenv_cstr("bgColor")
353 : find_option("bgcolor","",1);
354
355 opt.isPrivate = g.json.post.v
356 ? json_getenv_bool("private",0)
357 : (NULL != find_option("private","",0))
358 ;
359
360 rc = json_branch_new( &opt, &rid );
361 if(rc){
362 json_set_err(rc, opt.rcErrMsg );
363 goto error;
364 }
 
365 payV = cson_value_new_object();
366 pay = cson_value_get_object(payV);
367
368 cson_object_set(pay,"name",json_new_string(opt.zName));
369 cson_object_set(pay,"basis",json_new_string(opt.zBasis));
370
--- src/json_branch.c
+++ src/json_branch.c
@@ -77,30 +77,31 @@
77 }
78 payV = cson_value_new_object();
79 pay = cson_value_get_object(payV);
80 listV = cson_value_new_array();
81 list = cson_value_get_array(listV);
82 if(fossil_is_json()){
83 range = json_getenv_cstr("range");
84 }
85
86 range = json_find_option_cstr("range",NULL,"r");
87 if((!range||!*range) && !g.isHTTP){
88 range = find_option("all","a",0);
89 if(range && *range){
90 range = "a";
91 }else{
92 range = find_option("closed","c",0);
93 if(range&&*range){
94 range = "c";
95 }
96 }
97 }
98
99 if(!range || !*range){
100 range = "o";
101 }
102 /* Normalize range values... */
103 switch(*range){
104 case 'c':
105 range = "closed";
106 which = -1;
107 break;
@@ -111,11 +112,11 @@
112 default:
113 range = "open";
114 which = 0;
115 break;
116 };
117 cson_object_set(pay,"range",json_new_string(range));
118
119 if( g.localOpen ){ /* add "current" property (branch name). */
120 int vid = db_lget_int("checkout", 0);
121 char const * zCurrent = vid
122 ? db_text(0, "SELECT value FROM tagxref"
@@ -324,46 +325,47 @@
325 if( !g.perm.Write ){
326 json_set_err(FSL_JSON_E_DENIED,
327 "Requires 'i' permissions.");
328 return NULL;
329 }
 
 
 
 
 
330 memset(&opt,0,sizeof(BranchCreateOptions));
331 if(fossil_is_json()){
332 opt.zName = json_getenv_cstr("name");
333 }
334
335 if(!opt.zName){
336 opt.zName = json_command_arg(g.json.dispatchDepth+1);
337 }
338
339 if(!opt.zName){
340 json_set_err(FSL_JSON_E_MISSING_ARGS, "'name' parameter was not specified." );
341 return NULL;
342 }
343
344 opt.zColor = json_find_option_cstr("bgColor","bgcolor",NULL);
345 opt.zBasis = json_find_option_cstr("basis",NULL,NULL);
346 if(!opt.zBasis && !g.isHTTP){
347 opt.zBasis = json_command_arg(g.json.dispatchDepth+2);
348 }
349 if(!opt.zBasis){
350 opt.zBasis = "trunk";
351 }
352 opt.isPrivate = json_find_option_bool("private",NULL,NULL,-1);
353 if(-1==opt.isPrivate){
354 if(!g.isHTTP){
355 opt.isPrivate = (NULL != find_option("private","",0));
356 }else{
357 opt.isPrivate = 0;
358 }
359 }
 
360
361 rc = json_branch_new( &opt, &rid );
362 if(rc){
363 json_set_err(rc, opt.rcErrMsg);
364 goto error;
365 }
366 assert(0 != rid);
367 payV = cson_value_new_object();
368 pay = cson_value_get_object(payV);
369
370 cson_object_set(pay,"name",json_new_string(opt.zName));
371 cson_object_set(pay,"basis",json_new_string(opt.zBasis));
372
--- src/json_timeline.c
+++ src/json_timeline.c
@@ -153,21 +153,13 @@
153153
char const * zBranch = NULL;
154154
int tagid = 0;
155155
if(! g.perm.Read ){
156156
return 0;
157157
}
158
- else if(g.isHTTP){
159
- zTag = json_getenv_cstr("tag");
160
- }else{
161
- zTag = find_option("tag",NULL,1);
162
- }
158
+ zTag = json_find_option_cstr("tag",NULL,NULL);
163159
if(!zTag || !*zTag){
164
- if(g.isHTTP){
165
- zBranch = json_getenv_cstr("branch");
166
- }else{
167
- zBranch = find_option("branch",NULL,1);
168
- }
160
+ zBranch = json_find_option_cstr("branch",NULL,NULL);
169161
if(!zBranch || !*zBranch){
170162
return 0;
171163
}
172164
zTag = zBranch;
173165
}
@@ -211,47 +203,30 @@
211203
** an "after" clause, and 0 if adds only an order-by clause.
212204
*/
213205
static char json_timeline_add_time_clause(Blob *pSql){
214206
char const * zAfter = NULL;
215207
char const * zBefore = NULL;
216
- if( g.isHTTP ){
217
- /**
218
- FIXME: we are only honoring STRING values here, not int (for
219
- passing Unix Epoch times).
220
- */
221
- zAfter = json_getenv_cstr("after");
222
- if(!zAfter || !*zAfter){
223
- zAfter = json_getenv_cstr("a");
224
- }
225
- if(!zAfter){
226
- zBefore = json_getenv_cstr("before");
227
- if(!zBefore||!*zBefore){
228
- zBefore = json_getenv_cstr("b");
229
- }
230
- }
231
- }else{
232
- zAfter = find_option("after","a",1);
233
- zBefore = zAfter ? NULL : find_option("before","b",1);
234
- }
208
+ int rc = 0;
209
+ zAfter = json_find_option_cstr("after",NULL,"a");
210
+ zBefore = zAfter ? NULL : json_find_option_cstr("before",NULL,"b");
211
+
235212
if(zAfter&&*zAfter){
236213
while( fossil_isspace(*zAfter) ) ++zAfter;
237214
blob_appendf(pSql,
238215
" AND event.mtime>=(SELECT julianday(%Q,'utc')) "
239216
" ORDER BY event.mtime ASC ",
240217
zAfter);
241
- return 1;
218
+ rc = 1;
242219
}else if(zBefore && *zBefore){
243220
while( fossil_isspace(*zBefore) ) ++zBefore;
244221
blob_appendf(pSql,
245222
" AND event.mtime<=(SELECT julianday(%Q,'utc')) "
246223
" ORDER BY event.mtime DESC ",
247224
zBefore);
248
- return -1;
249
- }else{
250
- blob_append(pSql," ORDER BY event.mtime DESC ", -1);
251
- return 0;
225
+ rc = -1;
252226
}
227
+ return rc;
253228
}
254229
255230
/*
256231
** Tries to figure out a timeline query length limit base on
257232
** environment parameters. If it can it returns that value,
@@ -260,21 +235,19 @@
260235
** Never returns a negative value. 0 means no limit.
261236
*/
262237
static int json_timeline_limit(){
263238
static const int defaultLimit = 20;
264239
int limit = -1;
265
- if( g.json.post.v ){
266
- limit = json_getenv_int("limit",-1);
267
- if(limit<0){
268
- limit = json_getenv_int("n",-1);
269
- }
270
- }else if(!g.isHTTP){/* CLI mode */
240
+ if(!g.isHTTP){/* CLI mode */
271241
char const * arg = find_option("limit","n",1);
272242
if(arg && *arg){
273243
limit = atoi(arg);
274244
}
275245
}
246
+ if( (limit<0) && fossil_is_json() ){
247
+ limit = json_getenv_int("limit",-1);
248
+ }
276249
return (limit<0) ? defaultLimit : limit;
277250
}
278251
279252
/*
280253
** Internal helper for the json_timeline_EVENTTYPE() family of
@@ -380,11 +353,11 @@
380353
cson_object * pay = NULL;
381354
cson_value * tmp = NULL;
382355
cson_value * listV = NULL;
383356
cson_array * list = NULL;
384357
int check = 0;
385
- int showFiles = 0;
358
+ char showFiles = -1/*magic number*/;
386359
Stmt q = empty_Stmt;
387360
char warnRowToJsonFailed = 0;
388361
char warnStringToArrayFailed = 0;
389362
Blob sql = empty_blob;
390363
if( !g.perm.Read ){
@@ -392,15 +365,11 @@
392365
i'm following the original timeline impl here.
393366
*/
394367
json_set_err( FSL_JSON_E_DENIED, "Checkin timeline requires 'o' access." );
395368
return NULL;
396369
}
397
- if( g.isHTTP ){
398
- showFiles = json_getenv_bool("files",0);
399
- }else{
400
- showFiles = 0!=find_option("files", "f",0);
401
- }
370
+ showFiles = json_find_option_bool("files",NULL,"f",0);
402371
payV = cson_value_new_object();
403372
pay = cson_value_get_object(payV);
404373
check = json_timeline_setup_sql( "ci", &sql, pay );
405374
if(check){
406375
json_set_err(check, "Query initialization failed.");
407376
--- src/json_timeline.c
+++ src/json_timeline.c
@@ -153,21 +153,13 @@
153 char const * zBranch = NULL;
154 int tagid = 0;
155 if(! g.perm.Read ){
156 return 0;
157 }
158 else if(g.isHTTP){
159 zTag = json_getenv_cstr("tag");
160 }else{
161 zTag = find_option("tag",NULL,1);
162 }
163 if(!zTag || !*zTag){
164 if(g.isHTTP){
165 zBranch = json_getenv_cstr("branch");
166 }else{
167 zBranch = find_option("branch",NULL,1);
168 }
169 if(!zBranch || !*zBranch){
170 return 0;
171 }
172 zTag = zBranch;
173 }
@@ -211,47 +203,30 @@
211 ** an "after" clause, and 0 if adds only an order-by clause.
212 */
213 static char json_timeline_add_time_clause(Blob *pSql){
214 char const * zAfter = NULL;
215 char const * zBefore = NULL;
216 if( g.isHTTP ){
217 /**
218 FIXME: we are only honoring STRING values here, not int (for
219 passing Unix Epoch times).
220 */
221 zAfter = json_getenv_cstr("after");
222 if(!zAfter || !*zAfter){
223 zAfter = json_getenv_cstr("a");
224 }
225 if(!zAfter){
226 zBefore = json_getenv_cstr("before");
227 if(!zBefore||!*zBefore){
228 zBefore = json_getenv_cstr("b");
229 }
230 }
231 }else{
232 zAfter = find_option("after","a",1);
233 zBefore = zAfter ? NULL : find_option("before","b",1);
234 }
235 if(zAfter&&*zAfter){
236 while( fossil_isspace(*zAfter) ) ++zAfter;
237 blob_appendf(pSql,
238 " AND event.mtime>=(SELECT julianday(%Q,'utc')) "
239 " ORDER BY event.mtime ASC ",
240 zAfter);
241 return 1;
242 }else if(zBefore && *zBefore){
243 while( fossil_isspace(*zBefore) ) ++zBefore;
244 blob_appendf(pSql,
245 " AND event.mtime<=(SELECT julianday(%Q,'utc')) "
246 " ORDER BY event.mtime DESC ",
247 zBefore);
248 return -1;
249 }else{
250 blob_append(pSql," ORDER BY event.mtime DESC ", -1);
251 return 0;
252 }
 
253 }
254
255 /*
256 ** Tries to figure out a timeline query length limit base on
257 ** environment parameters. If it can it returns that value,
@@ -260,21 +235,19 @@
260 ** Never returns a negative value. 0 means no limit.
261 */
262 static int json_timeline_limit(){
263 static const int defaultLimit = 20;
264 int limit = -1;
265 if( g.json.post.v ){
266 limit = json_getenv_int("limit",-1);
267 if(limit<0){
268 limit = json_getenv_int("n",-1);
269 }
270 }else if(!g.isHTTP){/* CLI mode */
271 char const * arg = find_option("limit","n",1);
272 if(arg && *arg){
273 limit = atoi(arg);
274 }
275 }
 
 
 
276 return (limit<0) ? defaultLimit : limit;
277 }
278
279 /*
280 ** Internal helper for the json_timeline_EVENTTYPE() family of
@@ -380,11 +353,11 @@
380 cson_object * pay = NULL;
381 cson_value * tmp = NULL;
382 cson_value * listV = NULL;
383 cson_array * list = NULL;
384 int check = 0;
385 int showFiles = 0;
386 Stmt q = empty_Stmt;
387 char warnRowToJsonFailed = 0;
388 char warnStringToArrayFailed = 0;
389 Blob sql = empty_blob;
390 if( !g.perm.Read ){
@@ -392,15 +365,11 @@
392 i'm following the original timeline impl here.
393 */
394 json_set_err( FSL_JSON_E_DENIED, "Checkin timeline requires 'o' access." );
395 return NULL;
396 }
397 if( g.isHTTP ){
398 showFiles = json_getenv_bool("files",0);
399 }else{
400 showFiles = 0!=find_option("files", "f",0);
401 }
402 payV = cson_value_new_object();
403 pay = cson_value_get_object(payV);
404 check = json_timeline_setup_sql( "ci", &sql, pay );
405 if(check){
406 json_set_err(check, "Query initialization failed.");
407
--- src/json_timeline.c
+++ src/json_timeline.c
@@ -153,21 +153,13 @@
153 char const * zBranch = NULL;
154 int tagid = 0;
155 if(! g.perm.Read ){
156 return 0;
157 }
158 zTag = json_find_option_cstr("tag",NULL,NULL);
 
 
 
 
159 if(!zTag || !*zTag){
160 zBranch = json_find_option_cstr("branch",NULL,NULL);
 
 
 
 
161 if(!zBranch || !*zBranch){
162 return 0;
163 }
164 zTag = zBranch;
165 }
@@ -211,47 +203,30 @@
203 ** an "after" clause, and 0 if adds only an order-by clause.
204 */
205 static char json_timeline_add_time_clause(Blob *pSql){
206 char const * zAfter = NULL;
207 char const * zBefore = NULL;
208 int rc = 0;
209 zAfter = json_find_option_cstr("after",NULL,"a");
210 zBefore = zAfter ? NULL : json_find_option_cstr("before",NULL,"b");
211
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212 if(zAfter&&*zAfter){
213 while( fossil_isspace(*zAfter) ) ++zAfter;
214 blob_appendf(pSql,
215 " AND event.mtime>=(SELECT julianday(%Q,'utc')) "
216 " ORDER BY event.mtime ASC ",
217 zAfter);
218 rc = 1;
219 }else if(zBefore && *zBefore){
220 while( fossil_isspace(*zBefore) ) ++zBefore;
221 blob_appendf(pSql,
222 " AND event.mtime<=(SELECT julianday(%Q,'utc')) "
223 " ORDER BY event.mtime DESC ",
224 zBefore);
225 rc = -1;
 
 
 
226 }
227 return rc;
228 }
229
230 /*
231 ** Tries to figure out a timeline query length limit base on
232 ** environment parameters. If it can it returns that value,
@@ -260,21 +235,19 @@
235 ** Never returns a negative value. 0 means no limit.
236 */
237 static int json_timeline_limit(){
238 static const int defaultLimit = 20;
239 int limit = -1;
240 if(!g.isHTTP){/* CLI mode */
 
 
 
 
 
241 char const * arg = find_option("limit","n",1);
242 if(arg && *arg){
243 limit = atoi(arg);
244 }
245 }
246 if( (limit<0) && fossil_is_json() ){
247 limit = json_getenv_int("limit",-1);
248 }
249 return (limit<0) ? defaultLimit : limit;
250 }
251
252 /*
253 ** Internal helper for the json_timeline_EVENTTYPE() family of
@@ -380,11 +353,11 @@
353 cson_object * pay = NULL;
354 cson_value * tmp = NULL;
355 cson_value * listV = NULL;
356 cson_array * list = NULL;
357 int check = 0;
358 char showFiles = -1/*magic number*/;
359 Stmt q = empty_Stmt;
360 char warnRowToJsonFailed = 0;
361 char warnStringToArrayFailed = 0;
362 Blob sql = empty_blob;
363 if( !g.perm.Read ){
@@ -392,15 +365,11 @@
365 i'm following the original timeline impl here.
366 */
367 json_set_err( FSL_JSON_E_DENIED, "Checkin timeline requires 'o' access." );
368 return NULL;
369 }
370 showFiles = json_find_option_bool("files",NULL,"f",0);
 
 
 
 
371 payV = cson_value_new_object();
372 pay = cson_value_get_object(payV);
373 check = json_timeline_setup_sql( "ci", &sql, pay );
374 if(check){
375 json_set_err(check, "Query initialization failed.");
376
+5 -6
--- src/json_wiki.c
+++ src/json_wiki.c
@@ -134,13 +134,14 @@
134134
if( !g.perm.RdWiki && !g.perm.Read ){
135135
json_set_err(FSL_JSON_E_DENIED,
136136
"Requires 'o' or 'j' access.");
137137
return NULL;
138138
}
139
- zPageName = (g.isHTTP || g.json.post.o)
140
- ? json_getenv_cstr("page")
141
- : find_option("page","p",1);
139
+ if(fossil_is_json()){
140
+ zPageName = json_getenv_cstr("page");
141
+ }
142
+ zPageName = json_find_option_cstr("page",NULL,"p");
142143
if( !zPageName && cson_value_is_string(g.json.reqPayload.v) ){
143144
zPageName = cson_string_cstr(cson_value_get_string(g.json.reqPayload.v));
144145
}
145146
if(!zPageName){
146147
zPageName = json_command_arg(g.json.dispatchDepth+1);
@@ -149,13 +150,11 @@
149150
json_set_err(FSL_JSON_E_MISSING_ARGS,
150151
"'page' argument is missing.");
151152
return NULL;
152153
}
153154
154
- zFormat = g.isHTTP
155
- ? json_getenv_cstr("format")
156
- : find_option("format","f",1);
155
+ zFormat = json_find_option_cstr("format",NULL,"f");
157156
if(!zFormat || !*zFormat){
158157
zFormat = "raw";
159158
}
160159
if( 'r' != *zFormat ){
161160
zFormat = "html";
162161
--- src/json_wiki.c
+++ src/json_wiki.c
@@ -134,13 +134,14 @@
134 if( !g.perm.RdWiki && !g.perm.Read ){
135 json_set_err(FSL_JSON_E_DENIED,
136 "Requires 'o' or 'j' access.");
137 return NULL;
138 }
139 zPageName = (g.isHTTP || g.json.post.o)
140 ? json_getenv_cstr("page")
141 : find_option("page","p",1);
 
142 if( !zPageName && cson_value_is_string(g.json.reqPayload.v) ){
143 zPageName = cson_string_cstr(cson_value_get_string(g.json.reqPayload.v));
144 }
145 if(!zPageName){
146 zPageName = json_command_arg(g.json.dispatchDepth+1);
@@ -149,13 +150,11 @@
149 json_set_err(FSL_JSON_E_MISSING_ARGS,
150 "'page' argument is missing.");
151 return NULL;
152 }
153
154 zFormat = g.isHTTP
155 ? json_getenv_cstr("format")
156 : find_option("format","f",1);
157 if(!zFormat || !*zFormat){
158 zFormat = "raw";
159 }
160 if( 'r' != *zFormat ){
161 zFormat = "html";
162
--- src/json_wiki.c
+++ src/json_wiki.c
@@ -134,13 +134,14 @@
134 if( !g.perm.RdWiki && !g.perm.Read ){
135 json_set_err(FSL_JSON_E_DENIED,
136 "Requires 'o' or 'j' access.");
137 return NULL;
138 }
139 if(fossil_is_json()){
140 zPageName = json_getenv_cstr("page");
141 }
142 zPageName = json_find_option_cstr("page",NULL,"p");
143 if( !zPageName && cson_value_is_string(g.json.reqPayload.v) ){
144 zPageName = cson_string_cstr(cson_value_get_string(g.json.reqPayload.v));
145 }
146 if(!zPageName){
147 zPageName = json_command_arg(g.json.dispatchDepth+1);
@@ -149,13 +150,11 @@
150 json_set_err(FSL_JSON_E_MISSING_ARGS,
151 "'page' argument is missing.");
152 return NULL;
153 }
154
155 zFormat = json_find_option_cstr("format",NULL,"f");
 
 
156 if(!zFormat || !*zFormat){
157 zFormat = "raw";
158 }
159 if( 'r' != *zFormat ){
160 zFormat = "html";
161
+4 -1
--- src/main.c
+++ src/main.c
@@ -207,11 +207,14 @@
207207
} cmd;
208208
struct { /* JSON POST data. */
209209
cson_value * v;
210210
cson_object * o;
211211
} post;
212
- struct { /* GET/COOKIE params in JSON mode. */
212
+ struct { /* GET/COOKIE params in JSON mode.
213
+ FIXME (stephan): verify that this is
214
+ still used and remove if it is not.
215
+ */
213216
cson_value * v;
214217
cson_object * o;
215218
} param;
216219
struct {
217220
cson_value * v;
218221
--- src/main.c
+++ src/main.c
@@ -207,11 +207,14 @@
207 } cmd;
208 struct { /* JSON POST data. */
209 cson_value * v;
210 cson_object * o;
211 } post;
212 struct { /* GET/COOKIE params in JSON mode. */
 
 
 
213 cson_value * v;
214 cson_object * o;
215 } param;
216 struct {
217 cson_value * v;
218
--- src/main.c
+++ src/main.c
@@ -207,11 +207,14 @@
207 } cmd;
208 struct { /* JSON POST data. */
209 cson_value * v;
210 cson_object * o;
211 } post;
212 struct { /* GET/COOKIE params in JSON mode.
213 FIXME (stephan): verify that this is
214 still used and remove if it is not.
215 */
216 cson_value * v;
217 cson_object * o;
218 } param;
219 struct {
220 cson_value * v;
221

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button