]>
Commit | Line | Data |
---|---|---|
0516711e | 1 | /**************************************************************************** |
b5dcae6d | 2 | * RRDtool 1.2rc6 Copyright by Tobi Oetiker, 1997-2005 |
0516711e TO |
3 | **************************************************************************** |
4 | * rrd_graph_helper.c commandline parser functions | |
5 | * this code was probably writtenn by Alex van den Bogaerdt | |
6 | ****************************************************************************/ | |
7 | ||
adb27eb6 | 8 | #include "rrd_graph.h" |
6465207c AB |
9 | |
10 | #define dprintf if (gdp->debug) printf | |
11 | ||
b8d04741 TO |
12 | /* Define prototypes for the parsing methods. |
13 | Inputs: | |
14 | char *line - pointer to base of input source | |
15 | unsigned int eaten - index to next input character (INPUT/OUTPUT) | |
16 | graph_desc_t *gdp - pointer to a graph description | |
17 | image_desc_t *im - pointer to an image description | |
18 | */ | |
19 | ||
20 | int rrd_parse_find_gf (char *, unsigned int *, graph_desc_t *); | |
21 | int rrd_parse_legend (char *, unsigned int *, graph_desc_t *); | |
22 | int rrd_parse_color (char *, graph_desc_t *); | |
8db0db54 | 23 | int rrd_parse_CF (char *, unsigned int *, graph_desc_t *, enum cf_en *); |
b8d04741 | 24 | int rrd_parse_print (char *, unsigned int *, graph_desc_t *, image_desc_t *); |
c4e7b680 TO |
25 | int rrd_parse_shift (char *, unsigned int *, graph_desc_t *, image_desc_t *); |
26 | int rrd_parse_xport (char *, unsigned int *, graph_desc_t *, image_desc_t *); | |
b8d04741 TO |
27 | int rrd_parse_PVHLAST (char *, unsigned int *, graph_desc_t *, image_desc_t *); |
28 | int rrd_parse_vname (char *, unsigned int *, graph_desc_t *, image_desc_t *); | |
29 | int rrd_parse_def (char *, unsigned int *, graph_desc_t *, image_desc_t *); | |
30 | int rrd_parse_vdef (char *, unsigned int *, graph_desc_t *, image_desc_t *); | |
31 | int rrd_parse_cdef (char *, unsigned int *, graph_desc_t *, image_desc_t *); | |
32 | ||
33 | ||
34 | ||
adb27eb6 | 35 | int |
6465207c AB |
36 | rrd_parse_find_gf(char *line, unsigned int *eaten, graph_desc_t *gdp) { |
37 | char funcname[11],c1=0,c2=0; | |
38 | int i=0; | |
39 | ||
40 | sscanf(&line[*eaten], "DEBUG%n", &i); | |
41 | if (i) { | |
42 | gdp->debug=1; | |
43 | (*eaten)+=i; | |
44 | i=0; | |
45 | dprintf("Scanning line '%s'\n",&line[*eaten]); | |
46 | } | |
47 | sscanf(&line[*eaten], "%10[A-Z]%n%c%c", funcname, &i, &c1, &c2); | |
48 | if (!i) { | |
49 | rrd_set_error("Could not make sense out of '%s'",line); | |
50 | return 1; | |
51 | } | |
52 | if ((int)(gdp->gf=gf_conv(funcname)) == -1) { | |
53 | rrd_set_error("'%s' is not a valid function name", funcname); | |
54 | return 1; | |
adb27eb6 | 55 | } |
6465207c AB |
56 | if (gdp->gf == GF_LINE) { |
57 | if (c1 < '1' || c1 > '3' || c2 != ':') { | |
58 | rrd_set_error("Malformed LINE command: %s",line); | |
59 | return 1; | |
60 | } | |
61 | gdp->linewidth=c1-'0'; | |
62 | i++; | |
63 | } else { | |
64 | if (c1 != ':') { | |
65 | rrd_set_error("Malformed %s command: %s",funcname,line); | |
66 | return 1; | |
67 | } | |
68 | } | |
69 | *eaten+=++i; | |
70 | return 0; | |
71 | } | |
adb27eb6 | 72 | |
6465207c AB |
73 | int |
74 | rrd_parse_legend(char *line, unsigned int *eaten, graph_desc_t *gdp) { | |
75 | int i; | |
76 | ||
77 | dprintf("- examining '%s'\n",&line[*eaten]); | |
78 | ||
79 | i=scan_for_col(&line[*eaten],FMT_LEG_LEN,gdp->legend); | |
80 | ||
81 | *eaten += i; | |
82 | if (line[*eaten]!='\0' && line[*eaten]!=':') { | |
83 | rrd_set_error("Legend too long"); | |
84 | return 1; | |
85 | } else { | |
86 | dprintf("- found legend '%s'\n", gdp->legend); | |
adb27eb6 AB |
87 | return 0; |
88 | } | |
6465207c AB |
89 | } |
90 | ||
91 | int | |
92 | rrd_parse_color(char *string, graph_desc_t *gdp) { | |
93 | unsigned int r=0,g=0,b=0,a=0; | |
94 | int i1=0,i2=0,i3=0; | |
95 | ||
96 | if (string[0] != '#') return 1; | |
97 | sscanf(string, "#%02x%02x%02x%n%02x%n%*s%n", | |
98 | &r,&g,&b,&i1,&a,&i2,&i3); | |
99 | ||
100 | if (i3) return 1; /* garbage after color */ | |
101 | if (!i2) a=0xFF; | |
102 | if (!i1) return 1; /* no color after '#' */ | |
103 | gdp->col = r<<24|g<<16|b<<8|a; | |
104 | return 0; | |
105 | } | |
106 | ||
107 | int | |
8db0db54 | 108 | rrd_parse_CF(char *line, unsigned int *eaten, graph_desc_t *gdp, enum cf_en *cf) { |
6465207c AB |
109 | char symname[CF_NAM_SIZE]; |
110 | int i=0; | |
111 | ||
112 | sscanf(&line[*eaten], CF_NAM_FMT "%n", symname,&i); | |
113 | if ((!i)||((line[*eaten+i]!='\0')&&(line[*eaten+i]!=':'))) { | |
114 | rrd_set_error("Cannot parse CF in '%s'",line); | |
115 | return 1; | |
116 | } | |
117 | (*eaten)+=i; | |
118 | dprintf("- using CF '%s'\n",symname); | |
adb27eb6 | 119 | |
8db0db54 | 120 | if ((int)(*cf = cf_conv(symname))==-1) { |
6465207c AB |
121 | rrd_set_error("Unknown CF '%s' in '%s'",symname,line); |
122 | return 1; | |
123 | } | |
124 | ||
125 | if (line[*eaten]!='\0') (*eaten)++; | |
126 | return 0; | |
127 | } | |
128 | ||
129 | /* Parsing old-style xPRINT and new-style xPRINT */ | |
130 | int | |
131 | rrd_parse_print(char *line, unsigned int *eaten, graph_desc_t *gdp, image_desc_t *im) { | |
132 | /* vname:CF:format in case of DEF-based vname | |
133 | ** vname:CF:format in case of CDEF-based vname | |
134 | ** vname:format in case of VDEF-based vname | |
135 | */ | |
136 | char tmpstr[MAX_VNAME_LEN+1]; | |
137 | int i=0; | |
138 | ||
139 | sscanf(&line[*eaten], DEF_NAM_FMT ":%n", tmpstr,&i); | |
140 | if (!i) { | |
141 | rrd_set_error("Could not parse line '%s'",line); | |
142 | return 1; | |
143 | } | |
144 | (*eaten)+=i; | |
145 | dprintf("- Found candidate vname '%s'\n",tmpstr); | |
146 | ||
147 | if ((gdp->vidx=find_var(im,tmpstr))<0) { | |
148 | rrd_set_error("Not a valid vname: %s in line %s",tmpstr,line); | |
149 | return 1; | |
150 | } | |
151 | switch (im->gdes[gdp->vidx].gf) { | |
152 | case GF_DEF: | |
153 | case GF_CDEF: | |
154 | dprintf("- vname is of type DEF or CDEF, looking for CF\n"); | |
8db0db54 | 155 | if (rrd_parse_CF(line,eaten,gdp,&gdp->cf)) return 1; |
6465207c AB |
156 | break; |
157 | case GF_VDEF: | |
158 | dprintf("- vname is of type VDEF\n"); | |
159 | break; | |
160 | default: | |
161 | rrd_set_error("Encountered unknown type variable '%s'",tmpstr); | |
162 | return 1; | |
163 | } | |
164 | ||
165 | if (rrd_parse_legend(line,eaten,gdp)) return 1; | |
6d54723b TO |
166 | /* for *PRINT the legend itself gets renderd later. We only |
167 | get the format at this juncture */ | |
6465207c | 168 | strcpy(gdp->format,gdp->legend); |
6d54723b | 169 | gdp->legend[0]='\0'; |
6465207c AB |
170 | return 0; |
171 | } | |
172 | ||
c4e7b680 TO |
173 | int |
174 | rrd_parse_shift(char *line, unsigned int *eaten, graph_desc_t *gdp, image_desc_t *im) { | |
175 | char *l = strdup(line + *eaten), *p; | |
176 | int rc = 1; | |
177 | ||
4d4c7522 | 178 | p = strchr(l, ':'); |
c4e7b680 TO |
179 | if (p == NULL) { |
180 | rrd_set_error("Invalid SHIFT syntax"); | |
181 | goto out; | |
182 | } | |
183 | *p++ = '\0'; | |
184 | ||
185 | if ((gdp->vidx=find_var(im,l))<0) { | |
186 | rrd_set_error("Not a valid vname: %s in line %s",l,line); | |
187 | goto out; | |
188 | } | |
189 | ||
190 | /* constant will parse; otherwise, must be VDEF reference */ | |
191 | if (sscanf(p, "%ld", &gdp->shval) != 1) { | |
192 | graph_desc_t *vdp; | |
193 | ||
194 | if ((gdp->shidx=find_var(im, p))<0) { | |
195 | rrd_set_error("invalid offset vname: %s", p); | |
196 | goto out; | |
197 | } | |
198 | ||
199 | vdp = &im->gdes[gdp->shidx]; | |
200 | if (vdp->gf != GF_VDEF) { | |
201 | rrd_set_error("offset must specify value or VDEF"); | |
202 | goto out; | |
203 | } | |
204 | } else { | |
205 | gdp->shidx = -1; | |
206 | } | |
207 | ||
208 | *eaten = strlen(line); | |
209 | rc = 0; | |
210 | ||
211 | out: | |
212 | free(l); | |
213 | return rc; | |
214 | } | |
215 | ||
216 | int | |
217 | rrd_parse_xport(char *line, unsigned int *eaten, graph_desc_t *gdp, image_desc_t *im) { | |
218 | char *l = strdup(line + *eaten), *p; | |
219 | int rc = 1; | |
220 | ||
221 | p = strchr(l, ':'); | |
222 | if (p != NULL) | |
223 | *p++ = '\0'; | |
224 | else | |
225 | p = ""; | |
226 | ||
227 | if ((gdp->vidx=find_var(im, l))==-1){ | |
228 | rrd_set_error("unknown variable '%s'",l); | |
229 | goto out; | |
230 | } | |
231 | ||
232 | if (strlen(p) >= FMT_LEG_LEN) | |
233 | *(p + FMT_LEG_LEN) = '\0'; | |
234 | ||
235 | strcpy(gdp->legend, p); | |
236 | *eaten = strlen(line); | |
237 | rc = 0; | |
238 | ||
239 | out: | |
240 | free(l); | |
241 | return rc; | |
242 | } | |
243 | ||
6465207c AB |
244 | /* Parsing of PART, VRULE, HRULE, LINE, AREA, STACK and TICK |
245 | ** is done in one function. Stacking STACK is silently ignored | |
246 | ** as it is redundant. Stacking PART, VRULE, HRULE or TICK is | |
247 | ** not allowed. The check for color doesn't need to be so strict | |
248 | ** anymore, the user can specify the color '#00000000' and | |
249 | ** effectively circumvent this check, so why bother. | |
250 | ** | |
251 | ** If a number (which is valid to enter) is more than a | |
252 | ** certain amount of characters, it is caught as an error. | |
253 | ** While this is arguable, so is entering fixed numbers | |
254 | ** with more than MAX_VNAME_LEN significant digits. | |
255 | */ | |
256 | int | |
257 | rrd_parse_PVHLAST(char *line, unsigned int *eaten, graph_desc_t *gdp, image_desc_t *im) { | |
258 | int i,j; | |
259 | int colorfound=0; | |
260 | char tmpstr[MAX_VNAME_LEN + 10]; /* vname#RRGGBBAA\0 */ | |
261 | ||
262 | dprintf("- parsing '%s'\n",&line[*eaten]); | |
263 | dprintf("- from line '%s'\n",line); | |
264 | ||
265 | i=scan_for_col(&line[*eaten],MAX_VNAME_LEN+9,tmpstr); | |
266 | if (line[*eaten+i]!='\0' && line[*eaten+i]!=':') { | |
267 | rrd_set_error("Cannot parse line '%s'",line); | |
268 | return 1; | |
269 | } | |
270 | ||
271 | j=i; while (j>0 && tmpstr[j]!='#') j--; | |
272 | ||
273 | if (tmpstr[j]=='#') { | |
274 | if (rrd_parse_color(&tmpstr[j],gdp)) { | |
275 | rrd_set_error("Could not parse color in '%s'",tmpstr[j]); | |
276 | return 1; | |
277 | } | |
278 | tmpstr[j]='\0'; | |
279 | dprintf("- parsed color 0x%08x\n",(unsigned int)gdp->col); | |
280 | colorfound=1; | |
281 | } | |
282 | ||
283 | dprintf("- examining '%s'\n",tmpstr); | |
284 | j=0; | |
285 | if (gdp->gf == GF_VRULE) { | |
286 | sscanf(tmpstr,"%li%n",&gdp->xrule,&j); | |
287 | if (j) dprintf("- found time: %li\n",gdp->xrule); | |
288 | } else { | |
289 | sscanf(tmpstr,"%lf%n",&gdp->yrule,&j); | |
290 | if (j) dprintf("- found number: %f\n",gdp->yrule); | |
291 | } | |
292 | if (!j) { | |
293 | if ((gdp->vidx=find_var(im,tmpstr))<0) { | |
294 | rrd_set_error("Not a valid vname: %s in line %s",tmpstr,line); | |
295 | return 1; | |
296 | } | |
297 | dprintf("- found vname: '%s' vidx %li\n",tmpstr,gdp->vidx); | |
298 | } | |
299 | /* "*eaten" is still pointing to the original location, | |
300 | ** "*eaten +i" is pointing to the character after the color | |
301 | ** or to the terminating '\0' in which case we're finished. | |
302 | */ | |
303 | if (line[*eaten+i]=='\0') { | |
304 | *eaten+=i; | |
adb27eb6 | 305 | return 0; |
6465207c AB |
306 | } |
307 | *eaten+=++i; | |
308 | ||
309 | /* If a color is specified and the only remaining part is | |
310 | ** ":STACK" then it is assumed to be the legend. An empty | |
311 | ** legend can be specified as expected. This means the | |
312 | ** following can be done: LINE1:x#FF0000FF::STACK | |
313 | */ | |
314 | if (colorfound) { /* no legend if no color */ | |
315 | if (gdp->gf == GF_TICK) { | |
316 | dprintf("- looking for optional number\n"); | |
8db0db54 | 317 | sscanf(&line[*eaten],"%lf%n",&gdp->yrule,&j); |
6465207c AB |
318 | if (j) { |
319 | dprintf("- found number %f\n",gdp->yrule); | |
320 | (*eaten)+=j; | |
321 | if (gdp->yrule > 1.0 || gdp->yrule < -1.0) { | |
322 | rrd_set_error("Tick factor should be <= 1.0"); | |
323 | return 1; | |
324 | } | |
8db0db54 TO |
325 | if (line[*eaten] == ':') |
326 | (*eaten)++; | |
6465207c AB |
327 | } else { |
328 | dprintf("- not found, defaulting to 0.1\n"); | |
329 | gdp->yrule=0.1; | |
330 | return 0; | |
331 | } | |
332 | } | |
333 | dprintf("- looking for optional legend\n"); | |
334 | dprintf("- in '%s'\n",&line[*eaten]); | |
0516711e TO |
335 | /* the legend for a graph item must start with "m " the first |
336 | m will then be over drawn with a color box. Since there | |
337 | is ample space I overwrite the first few characters of the line | |
338 | with the material that I want to see in the legend */ | |
339 | if (line[*eaten] != '\0' && line[*eaten] != ':'){ | |
340 | *eaten = *eaten - 2; | |
341 | line[*eaten] = 'm'; | |
342 | line[*eaten+1] = ' '; | |
343 | } | |
6465207c AB |
344 | if (rrd_parse_legend(line, eaten, gdp)) return 1; |
345 | } | |
346 | ||
347 | /* PART, HRULE, VRULE and TICK cannot be stacked. We're finished */ | |
348 | if ( (gdp->gf == GF_HRULE) | |
349 | || (gdp->gf == GF_VRULE) | |
7d3f6363 | 350 | #ifdef WITH_PIECHART |
6465207c | 351 | || (gdp->gf == GF_PART) |
7d3f6363 | 352 | #endif |
6465207c AB |
353 | || (gdp->gf == GF_TICK) |
354 | ) return 0; | |
355 | ||
356 | if (line[*eaten]!='\0') { | |
357 | dprintf("- still more, should be STACK\n"); | |
358 | (*eaten)++; | |
359 | j=scan_for_col(&line[*eaten],5,tmpstr); | |
360 | if (line[*eaten+j]!='\0') { | |
361 | rrd_set_error("Garbage found where STACK expected"); | |
362 | return 1; | |
363 | } | |
364 | if (!strcmp("STACK",tmpstr)) { | |
365 | dprintf("- found STACK\n"); | |
366 | gdp->stack=1; | |
367 | (*eaten)+=5; | |
368 | } else { | |
369 | rrd_set_error("Garbage found where STACK expected"); | |
370 | return 1; | |
371 | } | |
372 | } | |
a5cda330 TO |
373 | /* have simpler code in the drawing section */ |
374 | if ( gdp->gf == GF_STACK ){ | |
375 | gdp->stack=1; | |
376 | } | |
6465207c AB |
377 | return 0; |
378 | } | |
379 | ||
380 | int | |
381 | rrd_parse_vname(char *line, unsigned int *eaten, graph_desc_t *gdp, image_desc_t *im) { | |
382 | char tmpstr[MAX_VNAME_LEN + 10]; | |
383 | int i=0; | |
adb27eb6 | 384 | |
6465207c AB |
385 | sscanf(&line[*eaten], DEF_NAM_FMT "=%n", tmpstr,&i); |
386 | if (!i) { | |
387 | rrd_set_error("Cannot parse vname from '%s'",line); | |
388 | return 1; | |
389 | } | |
390 | dprintf("- found candidate '%s'\n",tmpstr); | |
adb27eb6 | 391 | |
6465207c AB |
392 | if ((gdp->vidx=find_var(im,tmpstr))>=0) { |
393 | rrd_set_error("Attempting to reuse '%s'",im->gdes[gdp->vidx].vname); | |
394 | return 1; | |
395 | } | |
396 | strcpy(gdp->vname,tmpstr); | |
397 | dprintf("- created vname '%s' vidx %lu\n", gdp->vname,im->gdes_c-1); | |
398 | (*eaten)+=i; | |
399 | return 0; | |
adb27eb6 AB |
400 | } |
401 | ||
6465207c AB |
402 | int |
403 | rrd_parse_def(char *line, unsigned int *eaten, graph_desc_t *gdp, image_desc_t *im) { | |
404 | int i=0; | |
8db0db54 | 405 | char command[7]; /* step, start, end, reduce */ |
6465207c | 406 | char tmpstr[256]; |
051cc27e | 407 | struct rrd_time_value start_tv,end_tv; |
6465207c AB |
408 | time_t start_tmp=0,end_tmp=0; |
409 | char *parsetime_error=NULL; | |
410 | ||
411 | start_tv.type = end_tv.type=ABSOLUTE_TIME; | |
412 | start_tv.offset = end_tv.offset=0; | |
7ee93d7b TO |
413 | localtime_r(&gdp->start, &start_tv.tm); |
414 | localtime_r(&gdp->end, &end_tv.tm); | |
6465207c AB |
415 | |
416 | dprintf("- parsing '%s'\n",&line[*eaten]); | |
417 | dprintf("- from line '%s'\n",line); | |
418 | ||
419 | if (rrd_parse_vname(line,eaten,gdp,im)) return 1; | |
420 | i=scan_for_col(&line[*eaten],254,gdp->rrd); | |
421 | if (line[*eaten+i]!=':') { | |
422 | rrd_set_error("Problems reading database name"); | |
423 | return 1; | |
424 | } | |
425 | (*eaten)+=++i; | |
426 | dprintf("- using file '%s'\n",gdp->rrd); | |
427 | ||
428 | i=0; | |
429 | sscanf(&line[*eaten], DS_NAM_FMT ":%n", gdp->ds_nam,&i); | |
430 | if (!i) { | |
431 | rrd_set_error("Cannot parse DS in '%s'",line); | |
432 | return 1; | |
433 | } | |
434 | (*eaten)+=i; | |
435 | dprintf("- using DS '%s'\n",gdp->ds_nam); | |
436 | ||
8db0db54 TO |
437 | if (rrd_parse_CF(line,eaten,gdp,&gdp->cf)) return 1; |
438 | gdp->cf_reduce = gdp->cf; | |
439 | ||
6465207c AB |
440 | if (line[*eaten]=='\0') return 0; |
441 | ||
442 | while (1) { | |
443 | dprintf("- optional parameter follows: %s\n", &line[*eaten]); | |
444 | i=0; | |
8db0db54 | 445 | sscanf(&line[*eaten], "%6[a-z]=%n", command, &i); |
6465207c AB |
446 | if (!i) { |
447 | rrd_set_error("Parse error in '%s'",line); | |
448 | return 1; | |
449 | } | |
450 | (*eaten)+=i; | |
451 | dprintf("- processing '%s'\n",command); | |
8db0db54 TO |
452 | if (!strcmp("reduce",command)) { |
453 | if (rrd_parse_CF(line,eaten,gdp,&gdp->cf_reduce)) return 1; | |
454 | if (line[*eaten] != '\0') | |
455 | (*eaten)--; | |
456 | } else if (!strcmp("step",command)) { | |
6465207c AB |
457 | i=0; |
458 | sscanf(&line[*eaten],"%lu%n",&gdp->step,&i); | |
459 | (*eaten)+=i; | |
460 | dprintf("- using step %lu\n",gdp->step); | |
461 | } else if (!strcmp("start",command)) { | |
462 | i=scan_for_col(&line[*eaten],255,tmpstr); | |
463 | (*eaten)+=i; | |
464 | if ((parsetime_error = parsetime(tmpstr, &start_tv))) { | |
465 | rrd_set_error( "start time: %s", parsetime_error ); | |
466 | return 1; | |
467 | } | |
468 | dprintf("- done parsing: '%s'\n",&line[*eaten]); | |
469 | } else if (!strcmp("end",command)) { | |
470 | i=scan_for_col(&line[*eaten],255,tmpstr); | |
471 | (*eaten)+=i; | |
472 | if ((parsetime_error = parsetime(tmpstr, &end_tv))) { | |
473 | rrd_set_error( "end time: %s", parsetime_error ); | |
474 | return 1; | |
475 | } | |
476 | dprintf("- done parsing: '%s'\n",&line[*eaten]); | |
477 | } else { | |
478 | rrd_set_error("Parse error in '%s'",line); | |
479 | return 1; | |
480 | } | |
481 | if (line[*eaten]=='\0') break; | |
482 | if (line[*eaten]!=':') { | |
483 | dprintf("- Expected to see end of string but got '%s'\n",\ | |
484 | &line[*eaten]); | |
485 | rrd_set_error("Parse error in '%s'",line); | |
486 | return 1; | |
487 | } | |
488 | (*eaten)++; | |
489 | } | |
490 | if (proc_start_end(&start_tv,&end_tv,&start_tmp,&end_tmp) == -1){ | |
491 | /* error string is set in parsetime.c */ | |
492 | return 1; | |
493 | } | |
494 | if (start_tmp < 3600*24*365*10) { | |
495 | rrd_set_error("the first entry to fetch should be " | |
496 | "after 1980 (%ld)",start_tmp); | |
497 | return 1; | |
498 | } | |
499 | ||
500 | if (end_tmp < start_tmp) { | |
501 | rrd_set_error("start (%ld) should be less than end (%ld)", | |
502 | start_tmp, end_tmp); | |
503 | return 1; | |
504 | } | |
505 | ||
506 | gdp->start = start_tmp; | |
507 | gdp->end = end_tmp; | |
508 | ||
509 | dprintf("- start time %lu\n",gdp->start); | |
510 | dprintf("- end time %lu\n",gdp->end); | |
511 | ||
512 | return 0; | |
513 | } | |
adb27eb6 | 514 | |
6465207c AB |
515 | int |
516 | rrd_parse_vdef(char *line, unsigned int *eaten, graph_desc_t *gdp, image_desc_t *im) { | |
517 | char tmpstr[MAX_VNAME_LEN+1]; /* vname\0 */ | |
518 | int i=0; | |
519 | ||
520 | dprintf("- parsing '%s'\n",&line[*eaten]); | |
521 | if (rrd_parse_vname(line,eaten,gdp,im)) return 1; | |
522 | ||
523 | sscanf(&line[*eaten], DEF_NAM_FMT ",%n", tmpstr,&i); | |
524 | if (!i) { | |
525 | rrd_set_error("Cannot parse line '%s'",line); | |
526 | return 1; | |
527 | } | |
528 | if ((gdp->vidx=find_var(im,tmpstr))<0) { | |
529 | rrd_set_error("Not a valid vname: %s in line %s",tmpstr,line); | |
530 | return 1; | |
531 | } | |
532 | if ( im->gdes[gdp->vidx].gf != GF_DEF | |
533 | && im->gdes[gdp->vidx].gf != GF_CDEF) { | |
534 | rrd_set_error("variable '%s' not DEF nor " | |
535 | "CDEF in VDEF '%s'", tmpstr,gdp->vname); | |
536 | return 1; | |
537 | } | |
538 | dprintf("- found vname: '%s' vidx %li\n",tmpstr,gdp->vidx); | |
539 | (*eaten)+=i; | |
540 | ||
541 | dprintf("- calling vdef_parse with param '%s'\n",&line[*eaten]); | |
542 | vdef_parse(gdp,&line[*eaten]); | |
543 | while (line[*eaten]!='\0'&&line[*eaten]!=':') | |
544 | (*eaten)++; | |
545 | ||
546 | return 0; | |
547 | } | |
548 | ||
549 | int | |
550 | rrd_parse_cdef(char *line, unsigned int *eaten, graph_desc_t *gdp, image_desc_t *im) { | |
551 | dprintf("- parsing '%s'\n",&line[*eaten]); | |
552 | if (rrd_parse_vname(line,eaten,gdp,im)) return 1; | |
553 | if ((gdp->rpnp = rpn_parse( | |
554 | (void *)im, | |
555 | &line[*eaten], | |
556 | &find_var_wrapper) | |
557 | )==NULL) { | |
558 | rrd_set_error("invalid rpn expression in: %s",&line[*eaten]); | |
559 | return 1; | |
560 | }; | |
561 | while (line[*eaten]!='\0'&&line[*eaten]!=':') | |
562 | (*eaten)++; | |
563 | return 0; | |
564 | } | |
565 | ||
566 | void | |
c4e7b680 | 567 | rrd_graph_script(int argc, char *argv[], image_desc_t *im, int optno) { |
6465207c AB |
568 | int i; |
569 | ||
c4e7b680 | 570 | for (i=optind+optno;i<argc;i++) { |
6465207c AB |
571 | graph_desc_t *gdp; |
572 | unsigned int eaten=0; | |
573 | ||
574 | if (gdes_alloc(im)) return; /* the error string is already set */ | |
575 | gdp = &im->gdes[im->gdes_c-1]; | |
576 | #ifdef DEBUG | |
577 | gdp->debug = 1; | |
578 | #endif | |
579 | ||
580 | if (rrd_parse_find_gf(argv[i],&eaten,gdp)) return; | |
581 | ||
582 | switch (gdp->gf) { | |
c4e7b680 TO |
583 | case GF_SHIFT: /* vname:value */ |
584 | if (rrd_parse_shift(argv[i],&eaten,gdp,im)) return; | |
585 | break; | |
6465207c | 586 | case GF_XPORT: |
c4e7b680 | 587 | if (rrd_parse_xport(argv[i],&eaten,gdp,im)) return; |
6465207c AB |
588 | break; |
589 | case GF_PRINT: /* vname:CF:format -or- vname:format */ | |
590 | case GF_GPRINT: /* vname:CF:format -or- vname:format */ | |
591 | if (rrd_parse_print(argv[i],&eaten,gdp,im)) return; | |
592 | break; | |
593 | case GF_COMMENT: /* text */ | |
594 | if (rrd_parse_legend(argv[i],&eaten,gdp)) return; | |
595 | break; | |
a5cda330 | 596 | case GF_STACK: /* vname-or-value[#color[:legend]] */ |
7d3f6363 | 597 | #ifdef WITH_PIECHART |
6465207c | 598 | case GF_PART: /* value[#color[:legend]] */ |
7d3f6363 | 599 | #endif |
6465207c AB |
600 | case GF_VRULE: /* value#color[:legend] */ |
601 | case GF_HRULE: /* value#color[:legend] */ | |
602 | case GF_LINE: /* vname-or-value[#color[:legend]][:STACK] */ | |
603 | case GF_AREA: /* vname-or-value[#color[:legend]][:STACK] */ | |
6465207c AB |
604 | case GF_TICK: /* vname#color[:num[:legend]] */ |
605 | if (rrd_parse_PVHLAST(argv[i],&eaten,gdp,im)) return; | |
606 | break; | |
607 | /* data acquisition */ | |
608 | case GF_DEF: /* vname=x:DS:CF:[:step=#][:start=#][:end=#] */ | |
609 | if (rrd_parse_def(argv[i],&eaten,gdp,im)) return; | |
610 | break; | |
611 | case GF_CDEF: /* vname=rpn-expression */ | |
612 | if (rrd_parse_cdef(argv[i],&eaten,gdp,im)) return; | |
613 | break; | |
614 | case GF_VDEF: /* vname=rpn-expression */ | |
615 | if (rrd_parse_vdef(argv[i],&eaten,gdp,im)) return; | |
616 | break; | |
617 | } | |
618 | if (gdp->debug) { | |
619 | dprintf("used %i out of %i chars\n",eaten,strlen(argv[i])); | |
620 | dprintf("parsed line: '%s'\n",argv[i]); | |
621 | dprintf("remaining: '%s'\n",&argv[i][eaten]); | |
622 | if (eaten >= strlen(argv[i])) | |
623 | dprintf("Command finished successfully\n"); | |
624 | } | |
625 | if (eaten < strlen(argv[i])) { | |
626 | rrd_set_error("Garbage '%s' after command:\n%s", | |
627 | &argv[i][eaten],argv[i]); | |
628 | return; | |
629 | } | |
630 | } | |
631 | } |