]>
Commit | Line | Data |
---|---|---|
0516711e | 1 | /**************************************************************************** |
36400d5b | 2 | * RRDtool 1.4.3 Copyright by Tobi Oetiker, 1997-2010 |
0516711e TO |
3 | **************************************************************************** |
4 | * rrd_graph_helper.c commandline parser functions | |
054f4ff3 | 5 | * this code initially written by Alex van den Bogaerdt |
0516711e TO |
6 | ****************************************************************************/ |
7 | ||
e111de44 TO |
8 | #include <locale.h> |
9 | ||
adb27eb6 | 10 | #include "rrd_graph.h" |
e111de44 | 11 | |
1ace8365 TO |
12 | #define dprintf(...) if (gdp->debug&1) fprintf(stderr,__VA_ARGS__); |
13 | #define dprintfparsed(...) if (gdp->debug&2) fprintf(stderr,__VA_ARGS__); | |
8b1d02ad | 14 | #define dprintfhash(...) if (gdp->debug&4) fprintf(stderr,__VA_ARGS__); |
1ace8365 TO |
15 | |
16 | void initParsedArguments(parsedargs_t* pa) { | |
17 | /* initialize */ | |
18 | pa->arg=NULL; | |
19 | pa->arg_orig=NULL; | |
20 | pa->kv_args=NULL; | |
21 | pa->kv_cnt=0; | |
6465207c | 22 | } |
adb27eb6 | 23 | |
1ace8365 TO |
24 | void freeParsedArguments(parsedargs_t* pa) { |
25 | if (pa->arg) {free(pa->arg);} | |
26 | if (pa->kv_args) {free(pa->kv_args);} | |
27 | initParsedArguments(pa); | |
28 | } | |
6465207c | 29 | |
1ace8365 TO |
30 | void dumpKeyValue(char* pre,keyvalue_t* t) { |
31 | if (t) { | |
32 | fprintf(stderr,"%s%i: '%s' = '%s' %i\n", | |
33 | pre, | |
34 | t->pos, | |
35 | t->key, | |
36 | t->value, | |
37 | t->flag | |
38 | ); | |
39 | } else { | |
40 | fprintf(stderr,"%sNULL\n",pre); | |
41 | } | |
42 | } | |
6465207c | 43 | |
1ace8365 TO |
44 | void dumpArguments(parsedargs_t* pa) { |
45 | fprintf(stderr,"====================\nParsed Arguments of: %s\n",pa->arg_orig); | |
46 | for(int i=0;i<pa->kv_cnt;i++) { | |
47 | dumpKeyValue(" ",&(pa->kv_args[i])); | |
48 | } | |
49 | fprintf(stderr,"---------------\n"); | |
50 | } | |
3da125e9 | 51 | |
1ace8365 TO |
52 | char* getKeyValueArgument(const char* key,int flag, parsedargs_t* pa) { |
53 | /* we count backwords for "overwrites" */ | |
54 | for(int i=pa->kv_cnt-1;i>=0;i--) { | |
55 | char* akey=(pa->kv_args[i]).key; | |
56 | if (strcmp(akey,key)==0) { | |
57 | /* set flag */ | |
58 | if (flag) {pa->kv_args[i].flag=flag;} | |
59 | /* return value */ | |
60 | return pa->kv_args[i].value; | |
adb27eb6 | 61 | } |
1ace8365 TO |
62 | } |
63 | return NULL; | |
6465207c AB |
64 | } |
65 | ||
1ace8365 TO |
66 | keyvalue_t* getFirstUnusedArgument(int flag, parsedargs_t* pa) { |
67 | for(int i=0;i<pa->kv_cnt;i++) { | |
68 | if (! pa->kv_args[i].flag) { | |
69 | pa->kv_args[i].flag=flag; | |
70 | return &(pa->kv_args[i]); | |
18cadd88 | 71 | } |
1ace8365 TO |
72 | } |
73 | return NULL; | |
6465207c AB |
74 | } |
75 | ||
1ace8365 TO |
76 | char* checkUnusedValues(parsedargs_t* pa){ |
77 | char *res=NULL; | |
78 | for(int i=0;i<pa->kv_cnt;i++) { | |
79 | if (!pa->kv_args[i].flag) { | |
ef7231f1 TO |
80 | const size_t klen = strlen(pa->kv_args[i].key); |
81 | const size_t vlen = strlen(pa->kv_args[i].value); | |
82 | const size_t len = res ? strlen(res) : 0; | |
83 | ||
0dff959d | 84 | char *t = (char *) realloc(res,len + 3 + klen + vlen); |
1ace8365 TO |
85 | if (! t) { return res; } |
86 | res=t; | |
ef7231f1 | 87 | strncat(res,pa->kv_args[i].key, klen); |
1ace8365 | 88 | strcat(res,"="); |
ef7231f1 | 89 | strncat(res,pa->kv_args[i].value, vlen); |
1ace8365 | 90 | strcat(res,":"); |
6465207c | 91 | } |
1ace8365 TO |
92 | } |
93 | /* if we got one, then strip the final : */ | |
94 | if (res) { res[strlen(res)-1]=0; } | |
95 | /* and return res */ | |
96 | return res; | |
97 | } | |
adb27eb6 | 98 | |
1ace8365 TO |
99 | int getMappedKeyValueArgument(const char* key,int flag, parsedargs_t* pa, |
100 | int* val,keyint_t** transpose) { | |
101 | /* get the value itself as string */ | |
102 | char* v=getKeyValueArgument(key,flag,pa); | |
103 | /* now try to parse the value */ | |
104 | if (v) { | |
105 | for(;(*transpose)->key;transpose++) { | |
106 | if (strcmp((*transpose)->key,v)==0) { | |
107 | *val=(*transpose)->value; | |
108 | return 0; | |
109 | } | |
6465207c | 110 | } |
1ace8365 TO |
111 | } |
112 | /* not found, so return error */ | |
113 | return 1; | |
6465207c AB |
114 | } |
115 | ||
1ace8365 TO |
116 | int getLong(const char* v,long *val,char**extra,int base) { |
117 | /* try to execute the parser */ | |
118 | /* NOTE that this may be a bit different from the original parser */ | |
119 | *extra=NULL; | |
120 | *val=strtol(v,extra,base); | |
121 | /* and error handling */ | |
122 | if (extra==NULL) { | |
123 | return 0; | |
124 | } else { | |
125 | if (*extra==v) { | |
126 | return -1; /* failed miserably */ | |
127 | } else { | |
128 | if ((*extra)[0]==0) { return 0; } | |
129 | return 1; /* got extra bytes */ | |
7d0bd260 | 130 | } |
1ace8365 TO |
131 | } |
132 | /* not found, so return error */ | |
133 | return -2; | |
134 | } | |
135 | ||
136 | int getDouble(const char* v, double *val,char**extra) { | |
137 | /* try to execute the parser */ | |
138 | /* NOTE that this may be a bit different from the original parser */ | |
e111de44 | 139 | char *old_locale; |
1ace8365 | 140 | *extra=NULL; |
e111de44 TO |
141 | old_locale = setlocale(LC_NUMERIC, NULL); |
142 | setlocale(LC_NUMERIC, "C"); | |
143 | errno = 0; | |
144 | *val = strtod(v,extra); | |
145 | if (errno > 0) { | |
146 | rrd_set_error("converting '%s' to float: %s", v, rrd_strerror(errno)); | |
147 | return -1; | |
148 | }; | |
149 | setlocale(LC_NUMERIC, old_locale); | |
150 | ||
1ace8365 TO |
151 | *val=strtod(v,extra); |
152 | /* and error handling */ | |
153 | if (extra==NULL) { | |
154 | return 0; | |
155 | } else { | |
156 | if (*extra==v) { | |
157 | return -1; /* failed miserably */ | |
158 | } else { | |
159 | if ((*extra)[0]==0) { return 0; } | |
160 | return 1; /* got extra bytes */ | |
6465207c | 161 | } |
1ace8365 TO |
162 | } |
163 | /* not found, so return error */ | |
164 | return -2; | |
7d0bd260 TO |
165 | } |
166 | ||
1ace8365 TO |
167 | int addToArguments(parsedargs_t* pa, char*key, char*value, int cnt) { |
168 | /* resize the field */ | |
0dff959d | 169 | keyvalue_t * t = (keyvalue_t *) realloc(pa->kv_args, (pa->kv_cnt + 1) * sizeof(keyvalue_t)); |
1ace8365 TO |
170 | if (!t) { |
171 | rrd_set_error("could not realloc memory"); | |
172 | return -1; | |
173 | } else { | |
174 | /* assign pointer */ | |
175 | pa->kv_args=t; | |
176 | } | |
177 | /* fill in data */ | |
178 | pa->kv_args[pa->kv_cnt].key=key; | |
179 | pa->kv_args[pa->kv_cnt].value=value; | |
180 | pa->kv_args[pa->kv_cnt].pos=cnt; | |
181 | pa->kv_args[pa->kv_cnt].flag=0; | |
182 | pa->kv_cnt++; | |
183 | /* and return ok */ | |
184 | return 0; | |
185 | } | |
18cadd88 | 186 | |
1ace8365 TO |
187 | char *poskeys[]={"pos0","pos1","pos2","pos3","pos4","pos5","pos6","pos7","pos8","pos9"}; |
188 | int parseArguments(const char* origarg, parsedargs_t* pa) { | |
189 | initParsedArguments(pa); | |
190 | /* now assign a copy */ | |
191 | pa->arg=strdup(origarg); | |
192 | if (!pa->arg) { rrd_set_error("Could not allocate memory");return -1; } | |
193 | pa->arg_orig=origarg; | |
194 | ||
195 | /* first split arg into : */ | |
196 | char last=1; | |
197 | char c; | |
198 | int cnt=0; | |
199 | int poscnt=0; | |
200 | char* pos=pa->arg; | |
201 | char* field=pos; | |
202 | do { | |
203 | c=*pos; | |
204 | if (! field) { field=pos;cnt++;} | |
205 | switch (c) { | |
206 | /* if the char is a backslash, then this escapes the next one */ | |
207 | case '\\': | |
21542540 | 208 | if (pos[1] == ':') { |
f149e0ea TO |
209 | /* move up the rest of the string to eat the backslash */ |
210 | memmove(pos,pos+1,strlen(pos+1)+1); | |
211 | } | |
1ace8365 TO |
212 | break; |
213 | case 0: | |
0dff959d | 214 | case ':': { |
1ace8365 TO |
215 | /* null and : separate the string */ |
216 | *pos=0; | |
217 | /* handle the case where we have got an = */ | |
218 | /* find equal sign */ | |
219 | char* equal=field; | |
220 | for (equal=field;(*equal)&&(*equal!='=');equal++) { ; } | |
221 | /* if we are on position 1 then check for position 0 to be [CV]?DEV */ | |
222 | int checkforkeyvalue=1; | |
223 | /* nw define key to use */ | |
224 | char *key,*value; | |
225 | if ((*equal=='=') && (checkforkeyvalue)) { | |
226 | *equal=0; | |
227 | key=field; | |
228 | value=equal+1; | |
229 | } else { | |
230 | if ((poscnt>0)&&(strcmp(field,"STACK")==0)) { | |
231 | key="stack"; | |
232 | value="1"; | |
233 | } else if ((poscnt>0)&&(strcmp(field,"strftime")==0)) { | |
234 | key="strftime"; | |
235 | value="1"; | |
e111de44 TO |
236 | } else if ((poscnt>0)&&(strcmp(field,"skipscale")==0)) { |
237 | key="skipscale"; | |
238 | value="1"; | |
1ace8365 TO |
239 | } else { |
240 | if (poscnt>9) { | |
241 | rrd_set_error("too many positional arguments"); | |
242 | freeParsedArguments(pa); | |
243 | return -1; | |
244 | } | |
245 | key=poskeys[poscnt]; | |
246 | poscnt++; | |
247 | value=field; | |
248 | } | |
249 | } | |
250 | /* do some synonym translations */ | |
251 | if (strcmp(key,"label")==0) { key="legend"; } | |
252 | if (strcmp(key,"colour")==0) { key="color"; } | |
253 | if (strcmp(key,"colour2")==0) { key="color2"; } | |
254 | ||
255 | /* add to fields */ | |
256 | if (addToArguments(pa,key,value,cnt)) { | |
257 | freeParsedArguments(pa); | |
258 | return -1; | |
259 | } | |
260 | ||
261 | /* and reset field */ | |
0dff959d | 262 | field=NULL; } |
1ace8365 | 263 | break; |
18cadd88 | 264 | default: |
1ace8365 | 265 | break; |
5e01c4f7 | 266 | } |
1ace8365 TO |
267 | /* assign last */ |
268 | last=c; | |
269 | /* and step to next one byte */ | |
270 | pos++; | |
271 | } while (c); | |
272 | /* and return OK */ | |
273 | return 0; | |
6465207c AB |
274 | } |
275 | ||
1ace8365 TO |
276 | int parse_color( const char *const, struct gfx_color_t *); |
277 | int parse_color( const char *const string, struct gfx_color_t *c) | |
18cadd88 | 278 | { |
1ace8365 TO |
279 | unsigned int r = 0, g = 0, b = 0, a = 0, i; |
280 | ||
281 | /* matches the following formats: | |
282 | ** RGB | |
283 | ** RGBA | |
284 | ** RRGGBB | |
285 | ** RRGGBBAA | |
286 | */ | |
287 | ||
288 | i = 0; | |
289 | while (string[i] && isxdigit((unsigned int) string[i])) | |
290 | i++; | |
291 | if (string[i] != '\0') | |
292 | return 1; /* garbage follows hexdigits */ | |
293 | switch (i) { | |
294 | case 3: | |
295 | case 4: | |
296 | sscanf(string, "%1x%1x%1x%1x", &r, &g, &b, &a); | |
297 | r *= 0x11; | |
298 | g *= 0x11; | |
299 | b *= 0x11; | |
300 | a *= 0x11; | |
301 | if (i == 3) | |
302 | a = 0xFF; | |
303 | break; | |
304 | case 6: | |
305 | case 8: | |
306 | sscanf(string, "%02x%02x%02x%02x", &r, &g, &b, &a); | |
307 | if (i == 6) | |
308 | a = 0xFF; | |
309 | break; | |
310 | default: | |
311 | return 1; /* wrong number of digits */ | |
312 | } | |
313 | /* I wonder how/why this works... */ | |
314 | *c=gfx_hex_to_col(r << 24 | g << 16 | b << 8 | a); | |
315 | return 0; | |
316 | } | |
7d0bd260 | 317 | |
1ace8365 TO |
318 | /* this would allow for 240 different values */ |
319 | #define PARSE_FIELD1 (1L<<60) | |
320 | #define PARSE_FIELD2 (1L<<61) | |
321 | #define PARSE_FIELD3 (1L<<62) | |
322 | #define PARSE_FIELD4 (1L<<63) | |
323 | #define PARSE_POSITIONAL (1L<<59) | |
324 | #define PARSE_ONYAXIS (1L<<58) | |
325 | #define PARSE_VNAME (PARSE_FIELD1|(1L<< 0)) | |
326 | #define PARSE_RRD (PARSE_FIELD1|(1L<< 1)) | |
327 | #define PARSE_DS (PARSE_FIELD1|(1L<< 2)) | |
328 | #define PARSE_CF (PARSE_FIELD1|(1L<< 3)) | |
329 | #define PARSE_COLOR (PARSE_FIELD1|(1L<< 4)) | |
330 | #define PARSE_COLOR2 (PARSE_FIELD1|(1L<< 5)) | |
331 | #define PARSE_LEGEND (PARSE_FIELD1|(1L<< 6)) | |
332 | #define PARSE_RPN (PARSE_FIELD1|(1L<< 7)) | |
333 | #define PARSE_START (PARSE_FIELD1|(1L<< 8)) | |
334 | #define PARSE_STEP (PARSE_FIELD1|(1L<< 9)) | |
335 | #define PARSE_END (PARSE_FIELD1|(1L<<10)) | |
336 | #define PARSE_STACK (PARSE_FIELD1|(1L<<11)) | |
337 | #define PARSE_LINEWIDTH (PARSE_FIELD1|(1L<<12)) | |
338 | #define PARSE_XAXIS (PARSE_FIELD1|(1L<<13)) | |
339 | #define PARSE_YAXIS (PARSE_FIELD1|(1L<<14)) | |
340 | #define PARSE_REDUCE (PARSE_FIELD1|(1L<<15)) | |
e111de44 TO |
341 | #define PARSE_SKIPSCALE (PARSE_FIELD1|(1L<<16)) |
342 | ||
1ace8365 TO |
343 | #define PARSE_DASHES (PARSE_FIELD1|(1L<<20)) |
344 | #define PARSE_HEIGHT (PARSE_FIELD1|(1L<<21)) | |
345 | #define PARSE_FORMAT (PARSE_FIELD1|(1L<<22)) | |
346 | #define PARSE_STRFTIME (PARSE_FIELD1|(1L<<23)) | |
347 | #define PARSE_FRACTION (PARSE_FIELD1|(1L<<24)) | |
348 | /* VNAME Special cases for generic parsing */ | |
349 | #define PARSE_VNAMEDEF (PARSE_VNAME|(1L<<57)) | |
350 | #define PARSE_VNAMEREF (PARSE_VNAME|(1L<<56)) | |
351 | #define PARSE_VNAMEREFNUM (PARSE_VNAMEREF|(1L<<55)) | |
1ace8365 TO |
352 | /* special positional cases */ |
353 | #define PARSE_VNAMERRDDSCF (PARSE_POSITIONAL|PARSE_VNAMEDEF|PARSE_RRD|PARSE_DS|PARSE_CF) | |
354 | #define PARSE_VNAMECOLORLEGEND (PARSE_POSITIONAL|PARSE_VNAMEREFNUM|PARSE_COLOR|PARSE_COLOR2|PARSE_LEGEND) | |
355 | #define PARSE_VNAMECOLORFRACTIONLEGEND (PARSE_VNAMECOLORLEGEND|PARSE_FRACTION) | |
356 | #define PARSE_VNAMERPN (PARSE_POSITIONAL|PARSE_VNAMEDEF|PARSE_RPN) | |
357 | #define PARSE_VNAMEREFPOS (PARSE_POSITIONAL|PARSE_VNAMEREF) | |
358 | ||
37092fc2 TO |
359 | GHashTable* gdef_map; |
360 | ||
361 | /* find gdes containing var*/ | |
362 | static long find_var( | |
363 | image_desc_t *im, | |
364 | char *key) | |
365 | { | |
366 | /* this makes only sense for a sufficient number of items */ | |
367 | long match = -1; | |
8b1d02ad TO |
368 | gpointer value; |
369 | gboolean ok = g_hash_table_lookup_extended(im->gdef_map,key,NULL,&value); | |
370 | if (ok){ | |
371 | match = GPOINTER_TO_INT(value); | |
37092fc2 | 372 | } |
d093a1d3 TO |
373 | |
374 | /* printf("%s -> %ld\n",key,match); */ | |
375 | ||
37092fc2 TO |
376 | return match; |
377 | ||
378 | } | |
379 | ||
380 | static long find_var_wrapper( | |
381 | void *arg1, | |
382 | char *key) | |
383 | { | |
384 | return find_var((image_desc_t *) arg1, key); | |
385 | } | |
386 | ||
387 | ||
1ace8365 TO |
388 | graph_desc_t* newGraphDescription(image_desc_t *const,enum gf_en,parsedargs_t*,unsigned long); |
389 | graph_desc_t* newGraphDescription(image_desc_t *const im,enum gf_en gf,parsedargs_t* pa,unsigned long bits) { | |
390 | /* check that none of the othe bitfield marker is set */ | |
391 | if ((bits&PARSE_FIELD1)&&((bits&(PARSE_FIELD2|PARSE_FIELD3|PARSE_FIELD4)))) { | |
392 | rrd_set_error("newGraphDescription: bad bitfield1 value %08x",bits);return NULL; } | |
393 | /* the normal handler that adds to img */ | |
394 | if (gdes_alloc(im)) { return NULL; } | |
395 | /* set gdp */ | |
396 | graph_desc_t *gdp= &im->gdes[im->gdes_c - 1]; | |
397 | ||
398 | /* set some generic things */ | |
399 | gdp->gf=gf; | |
400 | if (1) { | |
401 | char *t,*x; | |
402 | long debug=0; | |
403 | if ((t=getKeyValueArgument("debug",1,pa)) && ((getLong(t,&debug,&x,10)))) { | |
404 | rrd_set_error("Bad debug value: %s",t); return NULL; } | |
405 | gdp->debug=debug; | |
406 | } | |
407 | ||
408 | /* and the "flagged" parser implementation | |
409 | * | |
410 | * first the fields with legacy positional args | |
411 | */ | |
412 | #define bitscmp(v) ((bits&v)==v) | |
413 | char* vname=NULL; | |
414 | if (bitscmp(PARSE_VNAME)) { vname=getKeyValueArgument("vname",1,pa); | |
415 | dprintfparsed("got vname: %s\n",vname);} | |
416 | char *rrd=NULL; | |
417 | if (bitscmp(PARSE_RRD)) { rrd=getKeyValueArgument("rrd",1,pa); | |
418 | dprintfparsed("got rrd: %s\n",rrd);} | |
419 | char *ds=NULL; | |
420 | if (bitscmp(PARSE_DS)) { ds=getKeyValueArgument("ds",1,pa); | |
421 | dprintfparsed("got ds: %s\n",ds);} | |
422 | char *cf=NULL; | |
423 | if (bitscmp(PARSE_CF)) { cf=getKeyValueArgument("cf",1,pa); | |
424 | dprintfparsed("got cf: %s\n",cf);} | |
425 | char *color=NULL; | |
426 | if (bitscmp(PARSE_COLOR)) { color=getKeyValueArgument("color",1,pa); | |
427 | dprintfparsed("got color: %s\n",color);} | |
428 | char *color2=NULL; | |
429 | if (bitscmp(PARSE_COLOR2)) { color2=getKeyValueArgument("color2",1,pa); | |
430 | dprintfparsed("got color2: %s\n",color2);} | |
431 | char *rpn=NULL; | |
432 | if (bitscmp(PARSE_RPN)) { rpn=getKeyValueArgument("rpn",1,pa); | |
433 | dprintfparsed("got rpn: %s\n",rpn);} | |
434 | char *legend=NULL; | |
435 | if (bitscmp(PARSE_LEGEND)) { legend=getKeyValueArgument("legend",1,pa); | |
436 | dprintfparsed("got legend: %s\n",legend);} | |
437 | char *fraction=NULL; | |
438 | if (bitscmp(PARSE_FRACTION)) { fraction=getKeyValueArgument("fraction",1,pa); | |
439 | dprintfparsed("got fraction: %s\n",fraction);} | |
440 | /* | |
441 | * here the ones without delayed assigns (which are for positional parsers) | |
442 | */ | |
443 | if (bitscmp(PARSE_FORMAT)) { | |
444 | char *format=getKeyValueArgument("format",1,pa); | |
445 | if(format) { | |
446 | strncpy(gdp->format,format,FMT_LEG_LEN); | |
447 | dprintfparsed("got format: %s\n",format); | |
18cadd88 | 448 | } |
1ace8365 TO |
449 | } |
450 | if (bitscmp(PARSE_STRFTIME)) { | |
451 | char *strft=getKeyValueArgument("strftime",1,pa); | |
452 | gdp->strftm=(strft)?1:0; | |
453 | dprintfparsed("got strftime: %s\n",strft); | |
454 | } | |
455 | if (bitscmp(PARSE_STACK)) { | |
456 | char *stack=getKeyValueArgument("stack",1,pa); | |
457 | gdp->stack=(stack)?1:0; | |
458 | dprintfparsed("got stack: %s\n",stack); | |
459 | } | |
e111de44 TO |
460 | if (bitscmp(PARSE_SKIPSCALE)) { |
461 | char *skipscale=getKeyValueArgument("skipscale",1,pa); | |
462 | gdp->skipscale =(skipscale)?1:0; | |
463 | dprintfparsed("got skipscale: %s\n",skipscale); | |
464 | } | |
1ace8365 TO |
465 | if (bitscmp(PARSE_REDUCE)) { |
466 | char *reduce=getKeyValueArgument("reduce",1,pa); | |
467 | if (reduce) { | |
468 | gdp->cf_reduce=cf_conv(reduce); | |
469 | dprintfparsed("got reduce: %s (%i)\n",reduce,gdp->cf_reduce); | |
470 | if (((int)gdp->cf_reduce)==-1) { rrd_set_error("bad reduce CF: %s",reduce); return NULL; } | |
7d0bd260 | 471 | } |
1ace8365 TO |
472 | } |
473 | if (bitscmp(PARSE_XAXIS)) { | |
474 | long xaxis=0; | |
475 | char *t,*x; | |
476 | if ((t=getKeyValueArgument("xaxis",1,pa)) && ((getLong(t,&xaxis,&x,10))||(xaxis<1)||(xaxis>MAX_AXIS))) { | |
477 | rrd_set_error("Bad xaxis value: %s",t); return NULL; } | |
478 | dprintfparsed("got xaxis: %s (%li)\n",t,xaxis); | |
479 | gdp->xaxisidx=xaxis; | |
480 | } | |
481 | if (bitscmp(PARSE_YAXIS)) { | |
482 | long yaxis=0; | |
483 | char *t,*x; | |
484 | if ((t=getKeyValueArgument("yaxis",1,pa)) && ((getLong(t,&yaxis,&x,10))||(yaxis<1)||(yaxis>MAX_AXIS))) { | |
485 | rrd_set_error("Bad yaxis value: %s",t); return NULL; } | |
486 | dprintfparsed("got yaxis: %s (%li)\n",t,yaxis); | |
487 | gdp->yaxisidx=yaxis; | |
488 | } | |
489 | if (bitscmp(PARSE_LINEWIDTH)) { | |
bf7625c6 | 490 | double linewidth = 1; |
1ace8365 TO |
491 | char *t,*x; |
492 | if ((t=getKeyValueArgument("linewidth",1,pa))&&(*t!=0)) { | |
493 | if ((getDouble(t,&linewidth,&x))||(linewidth<=0)) { | |
494 | rrd_set_error("Bad line width: %s",t); return NULL; | |
495 | } | |
18cadd88 | 496 | } |
bf7625c6 TO |
497 | dprintfparsed("got linewidth: %s (%g)\n",t,linewidth); |
498 | gdp->linewidth=linewidth; | |
1ace8365 TO |
499 | } |
500 | if (bitscmp(PARSE_HEIGHT)) { | |
501 | double height=0; | |
502 | char *t,*x; | |
503 | if ((t=getKeyValueArgument("height",1,pa))&&(*t!=0)) { | |
504 | if (getDouble(t,&height,&x)) { | |
505 | rrd_set_error("Bad height: %s",t); return NULL; | |
506 | } | |
507 | dprintfparsed("got height: %s (%g)\n",t,height); | |
508 | gdp->gradheight=height; | |
01496ecb | 509 | } |
1ace8365 TO |
510 | } |
511 | if (bitscmp(PARSE_STEP)) { | |
512 | long step=0; | |
513 | char *t,*x; | |
514 | if ((t=getKeyValueArgument("step",1,pa)) && ((getLong(t,&step,&x,10))||(step<1))) { | |
515 | rrd_set_error("Bad step value: %s",t); return NULL; } | |
516 | dprintfparsed("got step: %s (%li)\n",t,step); | |
517 | gdp->step=step; | |
518 | } | |
519 | if ((bitscmp(PARSE_START)||bitscmp(PARSE_END))) { | |
520 | /* these should get done together to use the start/end code correctly*/ | |
521 | char* parsetime_error; | |
522 | /* first start */ | |
523 | char* start; | |
524 | rrd_time_value_t start_tv; | |
525 | start_tv.type = ABSOLUTE_TIME; | |
526 | start_tv.offset = 0; | |
527 | localtime_r(&gdp->start, &start_tv.tm); | |
528 | if (bitscmp(PARSE_START)) { | |
529 | start=getKeyValueArgument("start",1,pa); | |
530 | if ((start)&&(parsetime_error = rrd_parsetime(start, &start_tv))) { | |
531 | rrd_set_error("start time: %s", parsetime_error);return NULL; } | |
532 | dprintfparsed("got start: %s\n",start); | |
15dbcb6e | 533 | } |
1ace8365 TO |
534 | /* now end */ |
535 | char* end; | |
536 | rrd_time_value_t end_tv; | |
537 | end_tv.type = ABSOLUTE_TIME; | |
538 | end_tv.offset = 0; | |
539 | localtime_r(&gdp->end, &end_tv.tm); | |
540 | if (bitscmp(PARSE_END)) { | |
541 | end=getKeyValueArgument("end",1,pa); | |
542 | if ((end)&&(parsetime_error = rrd_parsetime(end, &end_tv))) { | |
543 | rrd_set_error("end time: %s", parsetime_error); return NULL; } | |
544 | dprintfparsed("got end: %s\n",end); | |
2cbe4e85 | 545 | } |
1ace8365 TO |
546 | /* and now put the pieces together (relative times like start=end-2days) */ |
547 | time_t start_tmp = 0, end_tmp = 0; | |
548 | if (rrd_proc_start_end(&start_tv, &end_tv, &start_tmp, &end_tmp) == -1) { | |
549 | return NULL; | |
6465207c | 550 | } |
1ace8365 TO |
551 | dprintfparsed("got start %s translated to: %lld\n",start,(long long int)start_tmp); |
552 | dprintfparsed("got end %s translated to: %lld\n",end,(long long int)end_tmp); | |
553 | ||
554 | /* check some ranges */ | |
555 | if (start_tmp < 3600 * 24 * 365 * 10) { | |
556 | rrd_set_error("the first entry to fetch should be " | |
557 | "after 1980 (%ld)", start_tmp); | |
558 | return NULL; } | |
559 | if (end_tmp < start_tmp) { | |
560 | rrd_set_error("start (%ld) should be less than end (%ld)", | |
561 | start_tmp, end_tmp); | |
562 | return NULL; } | |
58e13ed8 | 563 | |
1ace8365 TO |
564 | /* and finally set it irrespectively of if it has been set or not |
565 | * it may have been a relative time and if you just set it partially | |
566 | * then that is wrong... | |
567 | */ | |
568 | gdp->start = start_tmp; | |
569 | gdp->start_orig = start_tmp; | |
570 | gdp->end = end_tmp; | |
571 | gdp->end_orig = end_tmp; | |
572 | } | |
573 | if (bitscmp(PARSE_DASHES)) { | |
574 | char* dashes=getKeyValueArgument("dashes",1,pa); | |
575 | /* if we got dashes */ | |
576 | if (dashes) { | |
577 | gdp->offset = 0; | |
578 | /* count the , in dashes */ | |
579 | int cnt=0;for(char*t=dashes;(*t)&&(t=strchr(t,','));t++,cnt++) {;} | |
580 | dprintfparsed("Got dashes argument: %s with %i comma\n",dashes,cnt); | |
581 | /* now handle */ | |
582 | gdp->ndash = cnt+1; | |
583 | gdp->p_dashes = (double *) malloc(sizeof(double)*(gdp->ndash+1)); | |
584 | /* now loop dashes */ | |
585 | for(int i=0;i<gdp->ndash;i++) { | |
586 | char *x; | |
587 | int f=getDouble(dashes,&gdp->p_dashes[i],&x); | |
588 | if(f<0) { | |
589 | rrd_set_error("Could not parse number: %s",dashes); return NULL; | |
58e13ed8 | 590 | } |
1ace8365 TO |
591 | /* we should have this most of the time */ |
592 | dprintfparsed("Processed %s to %g at index %i\n",dashes,gdp->p_dashes[i],i); | |
593 | if (f>0) { | |
594 | if (*x!=',') { | |
595 | rrd_set_error("expected a ',' at : %s",x); return NULL;} | |
596 | dashes=x+1; | |
597 | } | |
598 | if ((f==0)&&(i!=gdp->ndash-1)) { | |
599 | rrd_set_error("unexpected end at : %s",dashes); return NULL;} | |
600 | } | |
6465207c | 601 | } |
1ace8365 TO |
602 | char* dashoffset=getKeyValueArgument("dash-offset",1,pa); |
603 | if (dashoffset) { | |
604 | char* x; | |
605 | if (getDouble(dashes,&gdp->offset,&x)) { | |
606 | rrd_set_error("Could not parse dash-offset: %s",dashoffset); return NULL; } | |
6465207c | 607 | } |
1ace8365 TO |
608 | } |
609 | ||
610 | /* here now the positional(=legacy) parsers which are EXCLUSIVE - SO ELSE IF !!! | |
611 | * we also only parse the extra here and assign just further down | |
612 | * TODO maybe we can generalize this a bit more... | |
613 | */ | |
614 | if (bitscmp(PARSE_VNAMERRDDSCF)) { | |
615 | if ((!vname)||(!rrd)) { | |
616 | /* get the first unused argument */ | |
617 | keyvalue_t* first=getFirstUnusedArgument(1,pa); | |
618 | if (!first) { rrd_set_error("No argument for definition of vdef/rrd in %s",pa->arg_orig); return NULL; } | |
619 | dprintfparsed("got positional vname and rrd: %s - %s\n",first->key,first->value); | |
620 | if (!vname) {vname=first->key;} | |
621 | if (!rrd) {rrd=first->value; } | |
6465207c | 622 | } |
1ace8365 TO |
623 | /* and now look for datasource */ |
624 | if (!ds) { | |
625 | /* get the first unused argument */ | |
626 | keyvalue_t* first=getFirstUnusedArgument(1,pa); | |
627 | if (!first) { rrd_set_error("No argument for definition of DS in %s",pa->arg_orig); return NULL; } | |
628 | dprintfparsed("got positional ds: %s - \n",first->value); | |
629 | ds=first->value; | |
3da125e9 | 630 | } |
1ace8365 TO |
631 | /* and for CF */ |
632 | if (!cf) { | |
633 | /* get the first unused argument */ | |
634 | keyvalue_t* first=getFirstUnusedArgument(1,pa); | |
635 | if (!first) { rrd_set_error("No argument for definition of CF in %s",pa->arg_orig); return NULL; } | |
636 | dprintfparsed("got positional cf: %s - \n",first->value); | |
637 | cf=first->value; | |
638 | } | |
639 | } else if (bitscmp(PARSE_VNAMECOLORLEGEND)) { | |
640 | /* vname */ | |
641 | if (!vname) { | |
642 | keyvalue_t* first=getFirstUnusedArgument(1,pa); | |
643 | if (first) { vname=first->value; | |
644 | } else { rrd_set_error("No positional VNAME"); return NULL; } | |
3da125e9 | 645 | } |
1ace8365 TO |
646 | /* fraction added into the parsing mix for TICK */ |
647 | if ((bitscmp(PARSE_VNAMECOLORFRACTIONLEGEND))&&(!fraction)) { | |
648 | keyvalue_t* first=getFirstUnusedArgument(1,pa); | |
649 | if (first) { fraction=first->value; | |
650 | } else { rrd_set_error("No positional FRACTION"); return NULL; } | |
651 | } | |
468cdea6 | 652 | /* legend (it's optional if no other arguments follow)*/ |
1ace8365 TO |
653 | if (!legend) { |
654 | keyvalue_t* first=getFirstUnusedArgument(1,pa); | |
655 | if (first) { legend=first->value; | |
656 | dprintfparsed("got positional legend: %s - \n",first->value); | |
468cdea6 | 657 | } |
6465207c | 658 | } |
1ace8365 TO |
659 | } else if (bitscmp(PARSE_VNAMERPN)) { |
660 | if ((!vname)||(!rpn)) { | |
661 | /* get the first unused argument */ | |
662 | keyvalue_t* first=getFirstUnusedArgument(1,pa); | |
663 | if (!first) { rrd_set_error("No argument for definition of vdef/rrd in %s",pa->arg_orig); return NULL; } | |
664 | dprintfparsed("got positional vname and rpn: %s - %s\n",first->key,first->value); | |
665 | if (!vname) {vname=first->key;} | |
666 | if (!rpn) {rpn=first->value; } | |
3da125e9 | 667 | } |
1ace8365 TO |
668 | } else if (bitscmp(PARSE_VNAMEREFPOS)) { |
669 | if ((!vname)) { | |
670 | /* get the first unused argument */ | |
671 | keyvalue_t* first=getFirstUnusedArgument(1,pa); | |
672 | if (!first) { rrd_set_error("No argument for definition of vdef/rrd in %s",pa->arg_orig); return NULL; } | |
673 | dprintfparsed("got positional vname and rrd: %s - %s\n",first->key,first->value); | |
674 | if (!vname) {vname=first->value;} | |
c79bd073 | 675 | } |
1ace8365 TO |
676 | } |
677 | ||
678 | /* and set some of those late assignments to accomodate the legacy parser*/ | |
679 | /* first split vname into color */ | |
680 | if (vname) { | |
681 | /* check for color */ | |
682 | char *h1=strchr(vname,'#'); | |
683 | char* h2=NULL; | |
684 | if (h1) { | |
685 | *h1=0;h1++; | |
686 | dprintfparsed("got positional color: %s - \n",h1); | |
687 | h2=strchr(h1,'#'); | |
688 | if (h2) { | |
689 | *h2=0;h2++; | |
690 | dprintfparsed("got positional color2: %s - \n",h2); | |
691 | } | |
692 | } | |
693 | if (bitscmp(PARSE_COLOR) && (! color) && (h1)) { color=h1;} | |
694 | if (bitscmp(PARSE_COLOR2) && (! color2) && (h2)) { color2=h2;} | |
695 | } | |
696 | ||
697 | /* check if we are reusing the vname */ | |
698 | if (vname) { | |
699 | int idx=find_var(im, vname); | |
700 | dprintfparsed("got positional index %i for %s - \n",idx,vname); | |
701 | ||
702 | /* some handling */ | |
703 | if (bitscmp(PARSE_VNAMEDEF)) { | |
704 | if (idx>=0) { | |
705 | rrd_set_error("trying to reuse vname %s",vname); return NULL; } | |
706 | } else if (bitscmp(PARSE_VNAMEREF)) { | |
1fe48b55 TO |
707 | gdp->vidx=idx; |
708 | if (idx < 0){ | |
709 | if (bitscmp(PARSE_VNAMEREFNUM)) { | |
710 | double val; | |
711 | char *x; | |
712 | int f=getDouble(vname,&val,&x); | |
713 | if (f) { | |
714 | rrd_set_error("%s is not a vname nor a number",vname); return NULL; | |
715 | } | |
716 | if (gf==GF_VRULE){ | |
717 | gdp->xrule=val; | |
718 | } | |
719 | else { | |
720 | gdp->yrule=val; | |
721 | } | |
722 | } | |
723 | else { | |
724 | rrd_set_error("vname %s not found",vname); return NULL; | |
725 | } | |
726 | } | |
18cadd88 | 727 | } |
1ace8365 TO |
728 | } |
729 | ||
730 | /* and assign it */ | |
37092fc2 | 731 | if (vname) { strncpy(gdp->vname,vname,MAX_VNAME_LEN + 1);} |
1ace8365 TO |
732 | if (rrd) { strncpy(gdp->rrd,rrd,1024); } |
733 | if (ds) { strncpy(gdp->ds_nam,ds,DS_NAM_SIZE); } | |
734 | if (cf) { | |
735 | gdp->cf=cf_conv(cf); | |
736 | if (((int)gdp->cf)==-1) { | |
737 | rrd_set_error("bad CF: %s",cf); return NULL; } | |
c238ca48 | 738 | } else { if (bitscmp(PARSE_CF)) { gdp->cf = (enum cf_en) -1; }} |
1ace8365 TO |
739 | if ((color)&&(parse_color(color,&(gdp->col)))) { return NULL; } |
740 | if ((color2)&&(parse_color(color2,&(gdp->col2)))) { return NULL; } | |
741 | if (rpn) {gdp->rpn=rpn;} | |
742 | if ((legend)&&(*legend!=0)) { | |
743 | /* some spacing before we really start with the legend - needed for some reason */ | |
744 | char* t=gdp->legend; | |
745 | *t=' ';t++; | |
746 | *t=' ';t++; | |
747 | /* and copy it into place */ | |
748 | strncpy(t,legend,FMT_LEG_LEN); | |
749 | } | |
750 | if (fraction) { | |
751 | if (strcmp(fraction,"vname")==0) { | |
752 | /* check that vname is really a DEF|CDEF */ | |
753 | if (im->gdes[gdp->vidx].gf != GF_DEF && im->gdes[gdp->vidx].gf != GF_CDEF) { | |
754 | rrd_set_error("variable '%s' not DEF nor CDEF when using dynamic fractions", gdp->vname); | |
755 | return NULL; | |
756 | } | |
757 | /* add as flag to use (c)?def */ | |
758 | gdp->cf=CF_LAST; | |
759 | gdp->yrule=0.5; | |
760 | } else { | |
761 | /* parse number */ | |
762 | double val; | |
763 | char *x; | |
764 | int f=getDouble(fraction,&val,&x); | |
765 | if (f) { | |
766 | rrd_set_error("error parsing number %s",vname); return NULL; | |
767 | } | |
768 | gdp->yrule=val; | |
3da125e9 | 769 | } |
1ace8365 | 770 | } |
37092fc2 TO |
771 | /* remember the index for faster varfind */ |
772 | char *key = gdes_fetch_key((*gdp)); | |
773 | if (gdp->gf == GF_DEF && !g_hash_table_lookup_extended(im->rrd_map,key,NULL,NULL)){ | |
8b1d02ad | 774 | dprintfhash("ins key %s - %ld\n",key,im->gdes_c-1); |
37092fc2 TO |
775 | g_hash_table_insert(im->gdef_map,g_strdup(key),GINT_TO_POINTER(im->gdes_c-1)); |
776 | } | |
777 | free(key); | |
8b1d02ad TO |
778 | if (gdp->gf == GF_DEF || gdp->gf == GF_VDEF || gdp->gf == GF_CDEF){ |
779 | dprintfhash("ins vname %s - %ld\n",gdp->vname,im->gdes_c-1); | |
780 | g_hash_table_insert(im->gdef_map,g_strdup(gdp->vname),GINT_TO_POINTER(im->gdes_c-1)); | |
781 | } | |
1ace8365 | 782 | return gdp; |
6465207c AB |
783 | } |
784 | ||
1ace8365 TO |
785 | /* and some defines */ |
786 | #define set_match(str,pat,cmd) if (strcmp(pat, str) == 0) { cmd ;} | |
787 | ||
788 | /* prototypes */ | |
789 | int parse_axis(enum gf_en,parsedargs_t*,image_desc_t *const); | |
790 | int parse_def(enum gf_en,parsedargs_t*,image_desc_t *const); | |
791 | int parse_cvdef(enum gf_en,parsedargs_t*,image_desc_t *const); | |
792 | int parse_line(enum gf_en,parsedargs_t*,image_desc_t *const); | |
793 | int parse_area(enum gf_en,parsedargs_t*,image_desc_t *const); | |
794 | int parse_stack(enum gf_en,parsedargs_t*,image_desc_t *const); | |
795 | int parse_print(enum gf_en,parsedargs_t*,image_desc_t *const); | |
796 | int parse_gprint(enum gf_en,parsedargs_t*,image_desc_t *const); | |
797 | int parse_comment(enum gf_en,parsedargs_t*,image_desc_t *const); | |
798 | int parse_hvrule(enum gf_en,parsedargs_t*,image_desc_t *const); | |
799 | int parse_grad(enum gf_en,parsedargs_t*,image_desc_t *const); | |
800 | int parse_tick(enum gf_en,parsedargs_t*,image_desc_t *const); | |
801 | int parse_textalign(enum gf_en,parsedargs_t*,image_desc_t *const); | |
802 | int parse_shift(enum gf_en,parsedargs_t*,image_desc_t *const); | |
803 | int parse_xport(enum gf_en,parsedargs_t*,image_desc_t *const); | |
804 | ||
805 | /* implementations */ | |
806 | int parse_axis(enum gf_en gf,parsedargs_t*pa,image_desc_t *const im){ | |
d093a1d3 | 807 | |
1ace8365 TO |
808 | #if 0 |
809 | /* define X or y axis */ | |
810 | axis_t *a=im->xaxis; | |
811 | if (gf == GF_YAXIS) { a=im->yaxis; } | |
812 | /* try to parse the number */ | |
813 | char* cmd=getKeyValueArgument("cmd",1,pa); | |
814 | if (cmd[5]) { | |
815 | int num=atoi(cmd+5); | |
816 | if ((num<1)||(num>MAX_AXIS)) { | |
817 | rrd_set_error("invalid axis ID %i in %s - should be in range [1:%i]",num,cmd,MAX_AXIS); | |
818 | return 1; | |
d2dadad0 | 819 | } |
1ace8365 TO |
820 | /* and forward by that much */ |
821 | a=a+(num-1); | |
822 | } | |
823 | ||
824 | /* and set type */ | |
825 | char* t=getKeyValueArgument("type",1,pa); | |
826 | if (t) { | |
827 | set_match(t,"TIME",a->type=AXIS_TYPE_TIME) | |
828 | else | |
829 | set_match(t,"LINEAR",a->type=AXIS_TYPE_LINEAR) | |
830 | else | |
831 | set_match(t,"LOGARITHMIC",a->type=AXIS_TYPE_LOGARITHMIC) | |
832 | else { | |
833 | rrd_set_error("unsupported axis type %s",t); | |
834 | return 1; | |
835 | } | |
836 | } | |
837 | /* and other stuff */ | |
838 | a->bounds.lowertxt=getKeyValueArgument("min",1,pa); | |
839 | a->bounds.uppertxt=getKeyValueArgument("max",1,pa); | |
840 | #endif | |
d093a1d3 | 841 | |
1ace8365 TO |
842 | /* and return */ |
843 | return 0; | |
844 | } | |
adb27eb6 | 845 | |
1ace8365 TO |
846 | int parse_def(enum gf_en gf,parsedargs_t*pa,image_desc_t *const im){ |
847 | /* get new graph that we fill */ | |
848 | graph_desc_t *gdp=newGraphDescription(im,gf,pa, | |
849 | PARSE_VNAMERRDDSCF | |
850 | |PARSE_START | |
851 | |PARSE_STEP | |
852 | |PARSE_END | |
853 | |PARSE_REDUCE | |
854 | ); | |
d093a1d3 | 855 | if (!gdp) { return 1;} |
1ace8365 TO |
856 | |
857 | /* debugging output */ | |
858 | dprintf("=================================\n"); | |
859 | dprintf("DEF : %s\n",pa->arg_orig); | |
860 | dprintf("VNAME : %s\n",gdp->vname); | |
861 | dprintf("RRD : %s\n",gdp->rrd); | |
862 | dprintf("DS : %s\n",gdp->ds_nam); | |
863 | dprintf("CF : %i\n",gdp->cf); | |
864 | dprintf("START : (%lld)\n",(long long int)gdp->start); | |
865 | dprintf("STEP : (%lld)\n",(long long int)gdp->step); | |
866 | dprintf("END : (%lld)\n",(long long int)gdp->end); | |
867 | dprintf("REDUCE: (%i)\n",gdp->cf_reduce); | |
868 | dprintf("=================================\n"); | |
869 | ||
870 | /* and return fine */ | |
871 | return 0; | |
872 | } | |
873 | ||
874 | int parse_cvdef(enum gf_en gf,parsedargs_t*pa,image_desc_t *const im){ | |
875 | /* get new graph that we fill */ | |
876 | graph_desc_t *gdp=newGraphDescription(im,gf,pa, | |
877 | PARSE_VNAMERPN | |
878 | ); | |
d093a1d3 | 879 | if (!gdp) { return 1;} |
1ace8365 TO |
880 | |
881 | /* handle RPN parsing */ | |
882 | if (gf==GF_CDEF) { | |
883 | /* parse rpn */ | |
884 | if ((gdp->rpnp= rpn_parse((void *) im, gdp->rpn, &find_var_wrapper)) == NULL) { | |
d093a1d3 | 885 | return 1; } |
1ace8365 TO |
886 | } else { |
887 | /* parse vdef, as vdef_parse is a bit "stupid" right now we have to touch things here */ | |
888 | /* so find first , */ | |
889 | char*c=strchr(gdp->rpn,','); | |
d093a1d3 | 890 | if (! c) { rrd_set_error("Comma expected in VDEF definition %s",gdp->rpn); return 1;} |
1ace8365 TO |
891 | /* found a comma, so copy the first part to ds_name (re/abusing it) */ |
892 | *c=0; | |
893 | strncpy(gdp->ds_nam,gdp->rpn,DS_NAM_SIZE); | |
894 | *c=','; | |
895 | /* trying to find the vidx for that name */ | |
896 | gdp->vidx = find_var(im, gdp->ds_nam); | |
897 | if (gdp->vidx<0) { *c=','; | |
898 | rrd_set_error("Not a valid vname: %s in line %s", gdp->ds_nam, gdp->rpn); | |
d093a1d3 | 899 | return 1;} |
1ace8365 TO |
900 | if (im->gdes[gdp->vidx].gf != GF_DEF && im->gdes[gdp->vidx].gf != GF_CDEF) { |
901 | rrd_set_error("variable '%s' not DEF nor " | |
902 | "CDEF in VDEF '%s'", gdp->ds_nam, gdp->rpn); | |
903 | return 1; | |
6465207c | 904 | } |
1ace8365 TO |
905 | /* and parsing the rpn */ |
906 | int r=vdef_parse(gdp, c+1); | |
907 | /* original code does not check here for some reason */ | |
d093a1d3 | 908 | if (r) { return 1; } |
1ace8365 TO |
909 | } |
910 | ||
911 | /* debugging output */ | |
912 | dprintf("=================================\n"); | |
913 | if (gf==GF_CDEF) { | |
914 | dprintf("CDEF : %s\n",pa->arg_orig); | |
915 | } else { | |
916 | dprintf("VDEF : %s\n",pa->arg_orig); | |
917 | } | |
918 | dprintf("VNAME : %s\n",gdp->vname); | |
919 | dprintf("RPN : %s\n",gdp->rpn); | |
920 | dprintf("=================================\n"); | |
921 | ||
922 | /* and return fine */ | |
923 | return 0; | |
924 | } | |
925 | ||
926 | ||
927 | int parse_line(enum gf_en gf,parsedargs_t*pa,image_desc_t *const im){ | |
928 | /* get new graph that we fill */ | |
929 | graph_desc_t *gdp=newGraphDescription(im,gf,pa, | |
930 | PARSE_VNAMECOLORLEGEND | |
931 | |PARSE_STACK | |
e111de44 | 932 | |PARSE_SKIPSCALE |
1ace8365 TO |
933 | |PARSE_LINEWIDTH |
934 | |PARSE_DASHES | |
935 | |PARSE_XAXIS | |
936 | |PARSE_YAXIS | |
937 | ); | |
d093a1d3 | 938 | if (!gdp) { return 1;} |
1ace8365 TO |
939 | |
940 | /* debug output */ | |
941 | dprintf("=================================\n"); | |
942 | dprintf("LINE : %s\n",pa->arg_orig); | |
943 | if (gdp->vidx<0) { | |
944 | dprintf("VAL : %g\n",gdp->yrule); | |
945 | } else { | |
946 | dprintf("VNAME : %s (%li)\n",gdp->vname,gdp->vidx); | |
947 | } | |
948 | dprintf("COLOR : r=%g g=%g b=%g a=%g\n", | |
949 | gdp->col.red,gdp->col.green,gdp->col.blue,gdp->col.alpha); | |
950 | dprintf("COLOR2: r=%g g=%g b=%g a=%g\n", | |
951 | gdp->col2.red,gdp->col2.green,gdp->col2.blue,gdp->col2.alpha); | |
952 | dprintf("LEGEND: %s\n",gdp->legend); | |
953 | dprintf("STACK : %i\n",gdp->stack); | |
e111de44 | 954 | dprintf("SKIPSCALE : %i\n",gdp->skipscale); |
1ace8365 TO |
955 | dprintf("WIDTH : %g\n",gdp->linewidth); |
956 | dprintf("XAXIS : %i\n",gdp->xaxisidx); | |
957 | dprintf("YAXIS : %i\n",gdp->yaxisidx); | |
958 | if (gdp->ndash) { | |
959 | dprintf("DASHES: %i - %g",gdp->ndash,gdp->p_dashes[0]); | |
960 | for(int i=1;i<gdp->ndash;i++){dprintf(", %g",gdp->p_dashes[i]);} | |
961 | dprintf("\n"); | |
962 | } | |
963 | dprintf("=================================\n"); | |
964 | ||
965 | /* and return fine */ | |
966 | return 0; | |
adb27eb6 AB |
967 | } |
968 | ||
1ace8365 TO |
969 | int parse_area(enum gf_en gf,parsedargs_t*pa,image_desc_t *const im){ |
970 | /* get new graph that we fill */ | |
971 | graph_desc_t *gdp=newGraphDescription(im,gf,pa, | |
972 | PARSE_VNAMECOLORLEGEND | |
973 | |PARSE_STACK | |
e111de44 | 974 | |PARSE_SKIPSCALE |
1ace8365 TO |
975 | |PARSE_XAXIS |
976 | |PARSE_YAXIS | |
977 | |PARSE_HEIGHT | |
978 | ); | |
d093a1d3 | 979 | if (!gdp) { return 1;} |
1ace8365 TO |
980 | |
981 | /* debug output */ | |
982 | dprintf("=================================\n"); | |
983 | dprintf("AREA : %s\n",pa->arg_orig); | |
984 | if (gdp->vidx<0) { | |
985 | dprintf("VAL : %g\n",gdp->yrule); | |
986 | } else { | |
987 | dprintf("VNAME : %s (%li)\n",gdp->vname,gdp->vidx); | |
988 | } | |
989 | dprintf("COLOR : r=%g g=%g b=%g a=%g\n", | |
990 | gdp->col.red,gdp->col.green,gdp->col.blue,gdp->col.alpha); | |
991 | dprintf("COLOR2: r=%g g=%g b=%g a=%g\n", | |
992 | gdp->col2.red,gdp->col2.green,gdp->col2.blue,gdp->col2.alpha); | |
993 | dprintf("LEGEND: %s\n",gdp->legend); | |
994 | dprintf("STACK : %i\n",gdp->stack); | |
e111de44 | 995 | dprintf("SKIPSCALE : %i\n",gdp->skipscale); |
1ace8365 TO |
996 | dprintf("XAXIS : %i\n",gdp->xaxisidx); |
997 | dprintf("YAXIS : %i\n",gdp->yaxisidx); | |
998 | dprintf("=================================\n"); | |
999 | ||
1000 | /* and return fine */ | |
1001 | return 0; | |
1002 | } | |
6465207c | 1003 | |
1ace8365 TO |
1004 | int parse_stack(enum gf_en gf,parsedargs_t*pa,image_desc_t *const im){ |
1005 | /* get new graph that we fill */ | |
1006 | graph_desc_t *gdp=newGraphDescription(im,gf,pa, | |
1007 | PARSE_VNAMECOLORLEGEND | |
1008 | |PARSE_XAXIS | |
1009 | |PARSE_YAXIS | |
1010 | ); | |
d093a1d3 | 1011 | if (!gdp) { return 1;} |
1ace8365 TO |
1012 | gdp->stack=1; |
1013 | /* and try to get the one index before ourselves */ | |
1014 | long i; | |
1015 | for (i=im->gdes_c;(gdp->gf==gf)&&(i>=0);i--) { | |
1016 | dprintfparsed("trying to process entry %li with type %u\n",i,im->gdes[i].gf); | |
1017 | switch (im->gdes[i].gf) { | |
1018 | case GF_LINE: | |
1019 | case GF_AREA: | |
1020 | gdp->gf=im->gdes[i].gf; | |
1021 | gdp->linewidth=im->gdes[i].linewidth; | |
1022 | dprintfparsed("found matching LINE/AREA at %li with type %u\n",i,im->gdes[i].gf); | |
1023 | break; | |
1024 | default: break; | |
6465207c | 1025 | } |
1ace8365 TO |
1026 | } |
1027 | /* error the unhandled */ | |
1028 | if (gdp->gf==gf) { | |
d093a1d3 | 1029 | rrd_set_error("No previous LINE or AREA found for %s",pa->arg_orig); return 1;} |
1ace8365 TO |
1030 | |
1031 | /* debug output */ | |
1032 | dprintf("=================================\n"); | |
1033 | dprintf("STACK : %s\n",pa->arg_orig); | |
1034 | if (gdp->vidx<0) { | |
1035 | dprintf("VAL : %g\n",gdp->yrule); | |
1036 | } else { | |
1037 | dprintf("VNAME : %s (%li)\n",gdp->vname,gdp->vidx); | |
1038 | } | |
1039 | dprintf("COLOR : r=%g g=%g b=%g a=%g\n", | |
1040 | gdp->col.red,gdp->col.green,gdp->col.blue,gdp->col.alpha); | |
1041 | dprintf("COLOR2: r=%g g=%g b=%g a=%g\n", | |
1042 | gdp->col2.red,gdp->col2.green,gdp->col2.blue,gdp->col2.alpha); | |
1043 | dprintf("LEGEND: %s\n",gdp->legend); | |
1044 | dprintf("STACK : %i\n",gdp->stack); | |
1045 | dprintf("WIDTH : %g\n",gdp->linewidth); | |
1046 | dprintf("XAXIS : %i\n",gdp->xaxisidx); | |
1047 | dprintf("YAXIS : %i\n",gdp->yaxisidx); | |
1048 | dprintf("DASHES: TODI\n"); | |
1049 | dprintf("=================================\n"); | |
1050 | ||
1051 | /* and return fine */ | |
1052 | return 0; | |
1053 | } | |
6465207c | 1054 | |
1ace8365 TO |
1055 | int parse_hvrule(enum gf_en gf,parsedargs_t*pa,image_desc_t *const im){ |
1056 | /* get new graph that we fill */ | |
1057 | graph_desc_t *gdp=newGraphDescription(im,gf,pa, | |
1058 | PARSE_VNAMECOLORLEGEND | |
1fe48b55 | 1059 | |PARSE_VNAMEREFNUM |
1ace8365 TO |
1060 | |PARSE_XAXIS |
1061 | |PARSE_YAXIS | |
1062 | |PARSE_DASHES | |
1063 | ); | |
d093a1d3 | 1064 | if (!gdp) { return 1;} |
1ace8365 | 1065 | |
1ace8365 TO |
1066 | /* debug output */ |
1067 | dprintf("=================================\n"); | |
1068 | if (gf==GF_VRULE) { | |
1069 | dprintf("VRULE : %s\n",pa->arg_orig); | |
1070 | } else { | |
1071 | dprintf("HRULE : %s\n",pa->arg_orig); | |
1072 | } | |
1073 | if (gdp->vidx<0) { | |
1074 | if (gf==GF_VRULE) { | |
1fe48b55 | 1075 | dprintf("VAL : %lld\n",(long long)gdp->xrule); |
1ace8365 TO |
1076 | } else { |
1077 | dprintf("VAL : %g\n",gdp->yrule); | |
1078 | } | |
1079 | } else { | |
1080 | dprintf("VNAME : %s (%li)\n",gdp->vname,gdp->vidx); | |
1081 | } | |
1082 | dprintf("COLOR : r=%g g=%g b=%g a=%g\n", | |
1083 | gdp->col.red,gdp->col.green,gdp->col.blue,gdp->col.alpha); | |
1084 | dprintf("COLOR2: r=%g g=%g b=%g a=%g\n", | |
1085 | gdp->col2.red,gdp->col2.green,gdp->col2.blue,gdp->col2.alpha); | |
1086 | dprintf("LEGEND: %s\n",gdp->legend); | |
1087 | dprintf("DASHES: TODO\n"); | |
1088 | dprintf("XAXIS : %i\n",gdp->xaxisidx); | |
1089 | dprintf("YAXIS : %i\n",gdp->yaxisidx); | |
1090 | dprintf("=================================\n"); | |
1091 | ||
1fe48b55 TO |
1092 | /* check that vidx is of type VDEF */ |
1093 | if (gdp->vidx != -1 && im->gdes[gdp->vidx].gf != GF_VDEF) { | |
1094 | rrd_set_error("Using vname %s of wrong type in line %s\n", | |
1095 | gdp->vname,pa->arg_orig); | |
d093a1d3 | 1096 | return 1; |
1fe48b55 TO |
1097 | } |
1098 | ||
1099 | ||
1ace8365 TO |
1100 | /* and return fine */ |
1101 | return 0; | |
1102 | } | |
6465207c | 1103 | |
1ace8365 TO |
1104 | int parse_gprint(enum gf_en gf,parsedargs_t*pa,image_desc_t *const im) { |
1105 | /* get new graph that we fill */ | |
1106 | graph_desc_t *gdp=newGraphDescription(im,gf,pa, | |
1107 | PARSE_VNAMEREF | |
1108 | |PARSE_CF | |
1109 | |PARSE_FORMAT | |
1110 | |PARSE_STRFTIME | |
1111 | ); | |
d093a1d3 | 1112 | if (!gdp) { return 1;} |
1ace8365 TO |
1113 | /* here we parse pos arguments locally */ |
1114 | /* vname */ | |
1115 | if (gdp->vname[0]==0) { | |
1116 | dprintfparsed("Processing postitional vname\n"); | |
1117 | keyvalue_t* first=getFirstUnusedArgument(1,pa); | |
1118 | if (first) { | |
1119 | strncpy(gdp->vname,first->value,MAX_VNAME_LEN + 1); | |
1120 | /* get type of reference */ | |
1121 | gdp->vidx=find_var(im, gdp->vname); | |
1122 | if (gdp->vidx<0) { | |
d093a1d3 TO |
1123 | rrd_set_error("undefined vname %s",gdp->vname); return 1; } |
1124 | } else { rrd_set_error("No positional VNAME"); return 1; } | |
1ace8365 TO |
1125 | } |
1126 | /* check type of ref in general */ | |
1127 | enum gf_en vnamegf=im->gdes[gdp->vidx].gf; | |
1128 | dprintfparsed("Processing referenced type %i\n",vnamegf); | |
1129 | switch (vnamegf) { | |
1130 | /* depreciated */ | |
1131 | case GF_DEF: | |
1132 | case GF_CDEF: | |
1133 | dprintfparsed("Processing postitional CF\n"); | |
1134 | /* look for CF if not given */ | |
1135 | if (((int)gdp->cf)==-1) { | |
1136 | keyvalue_t* first=getFirstUnusedArgument(1,pa); | |
1137 | if (first) { | |
1138 | gdp->cf=cf_conv(first->value); | |
1139 | if (((int)gdp->cf)==-1) { | |
d093a1d3 TO |
1140 | rrd_set_error("bad CF: %s",first->value); return 1; } |
1141 | } else { rrd_set_error("No positional CDEF"); return 1; } | |
1ace8365 TO |
1142 | } |
1143 | break; | |
1144 | case GF_VDEF: | |
1145 | break; | |
1146 | default: | |
1147 | rrd_set_error("Encountered unknown type variable '%s'", | |
1148 | im->gdes[gdp->vidx].vname); | |
d093a1d3 | 1149 | return 1; |
1ace8365 TO |
1150 | } |
1151 | /* and get positional format */ | |
1152 | if (gdp->format[0]==0) { | |
1153 | dprintfparsed("Processing postitional format\n"); | |
1154 | keyvalue_t* first=getFirstUnusedArgument(1,pa); | |
1155 | if (first) { | |
1156 | strncpy(gdp->format,first->value,FMT_LEG_LEN); | |
1157 | dprintfparsed("got positional format: %s\n",gdp->format); | |
d093a1d3 | 1158 | } else { rrd_set_error("No positional CF/FORMAT"); return 1; } |
1ace8365 TO |
1159 | } |
1160 | /* debug output */ | |
1161 | dprintf("=================================\n"); | |
1162 | if (gf==GF_GPRINT) { | |
1163 | dprintf("GPRINT : %s\n",pa->arg_orig); | |
1164 | } else { | |
1165 | dprintf("PRINT : %s\n",pa->arg_orig); | |
1166 | } | |
1167 | dprintf("VNAME : %s (%li)\n",gdp->vname,gdp->vidx); | |
1168 | if ((int)gdp->cf>-1) { | |
1169 | dprintf("CF : (%u)\n",gdp->cf); | |
1170 | } | |
1171 | dprintf("FORMAT: %s\n",gdp->legend); | |
1172 | dprintf("=================================\n"); | |
1173 | ||
1174 | /* and return */ | |
1175 | return 0; | |
1176 | } | |
6465207c | 1177 | |
1ace8365 TO |
1178 | int parse_comment(enum gf_en gf,parsedargs_t*pa,image_desc_t *const im){ |
1179 | /* get new graph that we fill */ | |
1180 | graph_desc_t *gdp=newGraphDescription(im,gf,pa, | |
1181 | PARSE_LEGEND | |
1182 | ); | |
d093a1d3 | 1183 | if (!gdp) { return 1;} |
1ace8365 TO |
1184 | |
1185 | /* and if we have no legend, then use the first positional one */ | |
1186 | if (gdp->legend[0]==0) { | |
1187 | keyvalue_t* first=getFirstUnusedArgument(1,pa); | |
1188 | if (first) { | |
1189 | strncpy(gdp->legend,first->value,FMT_LEG_LEN); | |
d093a1d3 | 1190 | } else { rrd_set_error("No positional CF/FORMAT"); return 1; } |
1ace8365 TO |
1191 | } |
1192 | /* debug output */ | |
1193 | dprintf("=================================\n"); | |
1194 | dprintf("COMMENT : %s\n",pa->arg_orig); | |
1195 | dprintf("LEGEND : %s\n",gdp->legend); | |
1196 | /* and return */ | |
1197 | return 0; | |
6465207c | 1198 | } |
adb27eb6 | 1199 | |
1ace8365 TO |
1200 | int parse_tick(enum gf_en gf,parsedargs_t* pa,image_desc_t *const im) { |
1201 | /* get new graph that we fill */ | |
1202 | graph_desc_t *gdp=newGraphDescription(im,gf,pa, | |
1203 | PARSE_VNAMECOLORFRACTIONLEGEND | |
1204 | ); | |
d093a1d3 | 1205 | if (!gdp) { return 1;} |
1ace8365 TO |
1206 | /* debug output */ |
1207 | dprintf("=================================\n"); | |
1208 | dprintf("TICK : %s\n",pa->arg_orig); | |
1209 | dprintf("VNAME : %s (%li)\n",gdp->vname,gdp->vidx); | |
1210 | dprintf("COLOR : r=%g g=%g b=%g a=%g\n", | |
1211 | gdp->col.red,gdp->col.green,gdp->col.blue,gdp->col.alpha); | |
1212 | if (gdp->cf==CF_LAST) { | |
1213 | dprintf("FRAC : %s\n",gdp->vname); | |
1214 | } else { | |
1215 | dprintf("FRAC : %g\n",gdp->yrule); | |
1216 | } | |
1217 | dprintf("LEGEND: %s\n",gdp->legend); | |
1218 | dprintf("XAXIS : %i\n",gdp->xaxisidx); | |
1219 | dprintf("YAXIS : %i\n",gdp->yaxisidx); | |
1220 | dprintf("=================================\n"); | |
1221 | /* and return */ | |
1222 | return 0; | |
1223 | } | |
6465207c | 1224 | |
1ace8365 TO |
1225 | int parse_textalign(enum gf_en gf,parsedargs_t* pa,image_desc_t *const im) { |
1226 | /* get new graph that we fill */ | |
1227 | graph_desc_t *gdp=newGraphDescription(im,gf,pa,0); | |
d093a1d3 | 1228 | if (!gdp) { return 1;} |
1ace8365 TO |
1229 | |
1230 | /* get align */ | |
1231 | char* align=getKeyValueArgument("align",1,pa); | |
1232 | if (!align) align=getFirstUnusedArgument(1,pa)->value; | |
d093a1d3 | 1233 | if (!align) { rrd_set_error("No alignment given"); return 1; } |
1ace8365 TO |
1234 | |
1235 | /* parse align */ | |
1236 | if (strcmp(align, "left") == 0) { | |
1237 | gdp->txtalign = TXA_LEFT; | |
1238 | } else if (strcmp(align, "right") == 0) { | |
1239 | gdp->txtalign = TXA_RIGHT; | |
1240 | } else if (strcmp(align, "justified") == 0) { | |
1241 | gdp->txtalign = TXA_JUSTIFIED; | |
1242 | } else if (strcmp(align, "center") == 0) { | |
1243 | gdp->txtalign = TXA_CENTER; | |
1244 | } else { | |
1245 | rrd_set_error("Unknown alignement type '%s'", align); | |
1246 | return 1; | |
1247 | } | |
1248 | ||
1249 | /* debug output */ | |
1250 | dprintf("=================================\n"); | |
1251 | dprintf("TEXTALIGN : %s\n",pa->arg_orig); | |
1252 | dprintf("ALIGNMENT : %s (%u)\n",align,gdp->txtalign); | |
1253 | dprintf("=================================\n"); | |
1254 | /* and return */ | |
1255 | return 0; | |
1256 | } | |
6465207c | 1257 | |
1ace8365 TO |
1258 | int parse_shift(enum gf_en gf,parsedargs_t* pa,image_desc_t *const im) { |
1259 | /* get new graph that we fill */ | |
1260 | graph_desc_t *gdp=newGraphDescription(im,gf,pa,PARSE_VNAMEREFPOS); | |
d093a1d3 | 1261 | if (!gdp) { return 1;} |
1ace8365 TO |
1262 | /* and check that it is a CDEF */ |
1263 | switch (im->gdes[gdp->vidx].gf) { | |
1264 | case GF_DEF: | |
1265 | case GF_CDEF: | |
1266 | dprintf("- vname is of type DEF or CDEF, OK\n"); | |
1267 | break; | |
1268 | case GF_VDEF: | |
1269 | rrd_set_error("Cannot shift a VDEF: '%s' in line '%s'\n", | |
1270 | im->gdes[gdp->vidx].vname, pa->arg_orig); | |
1271 | return 1; | |
1272 | default: | |
1273 | rrd_set_error("Encountered unknown type variable '%s' in line '%s'", | |
1274 | im->gdes[gdp->vidx].vname, pa->arg_orig); | |
1275 | return 1; | |
1276 | } | |
1277 | ||
1278 | /* now parse the "shift" */ | |
1279 | char* shift=getKeyValueArgument("shift",1,pa); | |
1280 | if (!shift) {shift=getFirstUnusedArgument(1,pa)->value;} | |
d093a1d3 | 1281 | if (!shift) { rrd_set_error("No shift given"); return 1; } |
1ace8365 TO |
1282 | /* identify shift */ |
1283 | gdp->shidx=find_var(im, shift); | |
1284 | if (gdp->shidx>=0) { | |
1285 | /* it is a def, so let us check its type*/ | |
1286 | switch (im->gdes[gdp->shidx].gf) { | |
1287 | case GF_DEF: | |
1288 | case GF_CDEF: | |
1289 | rrd_set_error("Offset cannot be a (C)DEF: '%s' in line '%s'\n", | |
1290 | im->gdes[gdp->shidx].vname, pa->arg_orig); | |
1291 | return 1; | |
1292 | case GF_VDEF: | |
1293 | dprintf("- vname is of type VDEF, OK\n"); | |
1294 | break; | |
1295 | default: | |
1296 | rrd_set_error | |
1297 | ("Encountered unknown type variable '%s' in line '%s'", | |
1298 | im->gdes[gdp->vidx].vname, pa->arg_orig); | |
1299 | return 1; | |
6465207c | 1300 | } |
1ace8365 TO |
1301 | } else { |
1302 | /* it is no def, so parse as number */ | |
1303 | long val; | |
1304 | char *x; | |
1305 | int f=getLong(shift,&val,&x,10); | |
d093a1d3 | 1306 | if (f) { rrd_set_error("error parsing number %s",shift); return 1; } |
1ace8365 TO |
1307 | gdp->shval = val; |
1308 | gdp->shidx = -1; | |
1309 | } | |
1310 | ||
1311 | /* debug output */ | |
1312 | dprintf("=================================\n"); | |
1313 | dprintf("SHIFT : %s\n",pa->arg_orig); | |
1314 | dprintf("VNAME : %s (%li)\n",im->gdes[gdp->vidx].vname,gdp->vidx); | |
1315 | if (gdp->shidx>=0) { | |
1316 | dprintf("SHIFTBY : %s (%i)\n",im->gdes[gdp->shidx].vname,gdp->shidx); | |
1317 | } else { | |
1318 | dprintf("SHIFTBY : %li\n",gdp->shval); | |
1319 | } | |
1320 | dprintf("=================================\n"); | |
1321 | /* and return */ | |
1322 | return 0; | |
6465207c | 1323 | } |
1ace8365 TO |
1324 | int parse_xport(enum gf_en gf,parsedargs_t* pa,image_desc_t *const im) { |
1325 | /* get new graph that we fill */ | |
1326 | graph_desc_t *gdp=newGraphDescription(im,gf,pa,PARSE_VNAMECOLORLEGEND); | |
d093a1d3 | 1327 | if (!gdp) { return 1;} |
1ace8365 TO |
1328 | /* check for cdef */ |
1329 | /* and check that it is a CDEF */ | |
1330 | switch (im->gdes[gdp->vidx].gf) { | |
1331 | case GF_DEF: | |
1332 | case GF_CDEF: | |
1333 | dprintf("- vname is of type DEF or CDEF, OK\n"); | |
1334 | break; | |
1335 | case GF_VDEF: | |
1336 | rrd_set_error("Cannot shift a VDEF: '%s' in line '%s'\n", | |
1337 | im->gdes[gdp->vidx].vname, pa->arg_orig); | |
1338 | return 1; | |
1339 | default: | |
1340 | rrd_set_error("Encountered unknown type variable '%s' in line '%s'", | |
1341 | im->gdes[gdp->vidx].vname, pa->arg_orig); | |
1342 | return 1; | |
1343 | } | |
1344 | ||
1345 | /* debug output */ | |
1346 | dprintf("=================================\n"); | |
1347 | dprintf("LINE : %s\n",pa->arg_orig); | |
1348 | dprintf("VNAME : %s (%li)\n",gdp->vname,gdp->vidx); | |
1349 | dprintf("LEGEND: %s\n",gdp->legend); | |
1350 | dprintf("=================================\n"); | |
1351 | ||
1352 | return 0; | |
6465207c AB |
1353 | } |
1354 | ||
18cadd88 TO |
1355 | void rrd_graph_script( |
1356 | int argc, | |
1357 | char *argv[], | |
c4e8c1ea | 1358 | image_desc_t *const im, |
18cadd88 TO |
1359 | int optno) |
1360 | { | |
1361 | int i; | |
1362 | ||
1ace8365 TO |
1363 | /* and now handle the things*/ |
1364 | parsedargs_t pa; | |
1365 | initParsedArguments(&pa); | |
6465207c | 1366 | |
1ace8365 | 1367 | /* loop arguments */ |
18cadd88 | 1368 | for (i = optind + optno; i < argc; i++) { |
1ace8365 TO |
1369 | /* release parsed args - avoiding late cleanups*/ |
1370 | freeParsedArguments(&pa); | |
1371 | /* processed parsed args */ | |
1372 | if (parseArguments(argv[i],&pa)) { | |
1373 | return; } | |
1374 | ||
e111de44 | 1375 | /* dumpArguments(&pa); */ |
1ace8365 TO |
1376 | /* now let us handle the field based on the first command or cmd=...*/ |
1377 | char*cmd=NULL; | |
1378 | /* and try to get via cmd */ | |
1379 | char* t=getKeyValueArgument("cmd",1,&pa); | |
1380 | if (t) { | |
1381 | cmd=t; | |
1382 | } else if ((t=getKeyValueArgument("pos0",1,&pa))) { | |
1383 | cmd=t; | |
1384 | } else { | |
1385 | rrd_set_error("no command set in argument %s",pa.arg_orig); | |
1386 | freeParsedArguments(&pa); | |
1387 | return; | |
1388 | } | |
6465207c | 1389 | |
1ace8365 | 1390 | /* convert to enum but handling LINE special*/ |
c238ca48 | 1391 | enum gf_en gf = (enum gf_en) -1; |
1ace8365 TO |
1392 | gf=gf_conv(cmd); |
1393 | if ((int)gf == -1) { | |
1394 | if (strncmp("LINE",cmd,4)==0) { | |
1395 | gf=GF_LINE; | |
1396 | addToArguments(&pa,"linewidth",cmd+4,0); | |
1397 | } else { | |
1398 | rrd_set_error("'%s' is not a valid function name in %s", cmd,pa.arg_orig ); | |
1399 | return; | |
1400 | } | |
1401 | } | |
1402 | /* now we can handle the commands */ | |
1403 | int r=0; | |
1404 | switch (gf) { | |
1405 | case GF_XAXIS: r=parse_axis(gf,&pa,im); break; | |
1406 | case GF_YAXIS: r=parse_axis(gf,&pa,im); break; | |
1407 | case GF_DEF: r=parse_def(gf,&pa,im); break; | |
1408 | case GF_CDEF: r=parse_cvdef(gf,&pa,im); break; | |
1409 | case GF_VDEF: r=parse_cvdef(gf,&pa,im); break; | |
1410 | case GF_LINE: r=parse_line(gf,&pa,im); break; | |
1411 | case GF_AREA: r=parse_area(gf,&pa,im); break; | |
1412 | case GF_PRINT: r=parse_gprint(gf,&pa,im); break; | |
1413 | case GF_GPRINT: r=parse_gprint(gf,&pa,im); break; | |
1414 | case GF_COMMENT: r=parse_comment(gf,&pa,im); break; | |
1415 | case GF_HRULE: r=parse_hvrule(gf,&pa,im); break; | |
1416 | case GF_VRULE: r=parse_hvrule(gf,&pa,im); break; | |
1417 | case GF_STACK: r=parse_stack(gf,&pa,im); break; | |
1418 | case GF_TICK: r=parse_tick(gf,&pa,im); break; | |
1419 | case GF_TEXTALIGN: r=parse_textalign(gf,&pa,im); break; | |
1420 | case GF_SHIFT: r=parse_shift(gf,&pa,im); break; | |
1421 | case GF_XPORT: r=parse_xport(gf,&pa,im); break; | |
1422 | /* unsupported types right now */ | |
1423 | case GF_GRAD: | |
1424 | rrd_set_error("GRAD unsupported - use AREA instead"); | |
1425 | break; | |
1426 | } | |
1427 | /* handle the return error case */ | |
1428 | if (r) { freeParsedArguments(&pa); return;} | |
1429 | /* check for unprocessed keyvalue args */ | |
1430 | char *s; | |
1431 | if ((s=checkUnusedValues(&pa))) { | |
1432 | rrd_set_error("Unused Arguments in %s: %s",pa.arg_orig,s); | |
1433 | freeParsedArguments(&pa); | |
1434 | free(s); | |
1435 | return; | |
1436 | } | |
6465207c | 1437 | } |
1ace8365 TO |
1438 | /* finally free arguments */ |
1439 | freeParsedArguments(&pa); | |
6465207c | 1440 | } |