int parse_textalign(enum gf_en gf,parsedargs_t* pa,image_desc_t *const im) { /* get new graph that we fill */ graph_desc_t *gdp=newGraphDescription(im,gf,pa,0); if (!gdp) { return 1;} /* get align */ char* align=getKeyValueArgument("align",1,pa); if (!align) align=getFirstUnusedArgument(1,pa)->value; if (!align) { rrd_set_error("No alignment given"); return 1; } /* parse align */ if (strcmp(align, "left") == 0) { gdp->txtalign = TXA_LEFT; } else if (strcmp(align, "right") == 0) { gdp->txtalign = TXA_RIGHT; } else if (strcmp(align, "justified") == 0) { gdp->txtalign = TXA_JUSTIFIED; } else if (strcmp(align, "center") == 0) { gdp->txtalign = TXA_CENTER; } else { rrd_set_error("Unknown alignement type '%s'", align); return 1; } /* debug output */ dprintf("=================================\n"); dprintf("TEXTALIGN : %s\n",pa->arg_orig); dprintf("ALIGNMENT : %s (%u)\n",align,gdp->txtalign); dprintf("=================================\n"); /* and return */ return 0; }
/* implementations */ static int parse_axis(enum gf_en gf,parsedargs_t*pa,image_desc_t *const im){ #if 0 /* define X or y axis */ axis_t *a=im->xaxis; if (gf == GF_YAXIS) { a=im->yaxis; } /* try to parse the number */ char* cmd=getKeyValueArgument("cmd",1,pa); if (cmd[5]) { int num=atoi(cmd+5); if ((num<1)||(num>MAX_AXIS)) { rrd_set_error("invalid axis ID %i in %s - should be in range [1:%i]",num,cmd,MAX_AXIS); return 1; } /* and forward by that much */ a=a+(num-1); } /* and set type */ char* t=getKeyValueArgument("type",1,pa); if (t) { set_match(t,"TIME",a->type=AXIS_TYPE_TIME) else set_match(t,"LINEAR",a->type=AXIS_TYPE_LINEAR) else set_match(t,"LOGARITHMIC",a->type=AXIS_TYPE_LOGARITHMIC) else { rrd_set_error("unsupported axis type %s",t); return 1; } } /* and other stuff */ a->bounds.lowertxt=getKeyValueArgument("min",1,pa); a->bounds.uppertxt=getKeyValueArgument("max",1,pa); #else /* prevent unused warnings */ (void)gf; (void)pa; (void)im; #endif /* and return */ return 0; }
int getMappedKeyValueArgument(const char* key,int flag, parsedargs_t* pa, int* val,keyint_t** transpose) { /* get the value itself as string */ char* v=getKeyValueArgument(key,flag,pa); /* now try to parse the value */ if (v) { for(;(*transpose)->key;transpose++) { if (strcmp((*transpose)->key,v)==0) { *val=(*transpose)->value; return 0; } } } /* not found, so return error */ return 1; }
static graph_desc_t* newGraphDescription(image_desc_t *const im,enum gf_en gf,parsedargs_t* pa,uint64_t bits) { /* check that none of the other bitfield marker is set */ if ((bits&PARSE_FIELD1)&&((bits&(PARSE_FIELD2|PARSE_FIELD3|PARSE_FIELD4)))) { rrd_set_error("newGraphDescription: bad bitfield1 value %08llx",bits);return NULL; } /* the normal handler that adds to img */ if ((!(bits & PARSE_RETRY)) && (gdes_alloc(im))) { return NULL; } /* set gdp */ graph_desc_t *gdp= &im->gdes[im->gdes_c - 1]; /* set some generic things */ gdp->gf=gf; { char *t,*x; long debug=0; if ((t=getKeyValueArgument("debug",1,pa)) && ((getLong(t,&debug,&x,10)))) { rrd_set_error("Bad debug value: %s",t); return NULL; } gdp->debug=debug; } /* and the "flagged" parser implementation * * first the fields with legacy positional args */ #define bitscmp(v) ((bits&v)==v) char* vname=NULL; if (bitscmp(PARSE_VNAME)) { vname=getKeyValueArgument("vname",1,pa); dprintfparsed("got vname: %s\n",vname);} char *rrd=NULL; if (bitscmp(PARSE_RRD)) { rrd=getKeyValueArgument("rrd",1,pa); dprintfparsed("got rrd: %s\n",rrd);} char *ds=NULL; if (bitscmp(PARSE_DS)) { ds=getKeyValueArgument("ds",1,pa); dprintfparsed("got ds: %s\n",ds);} char *cf=NULL; if (bitscmp(PARSE_CF)) { cf=getKeyValueArgument("cf",1,pa); dprintfparsed("got cf: %s\n",cf);} char *color=NULL; if (bitscmp(PARSE_COLOR)) { color=getKeyValueArgument("color",1,pa); dprintfparsed("got color: %s\n",color);} char *color2=NULL; if (bitscmp(PARSE_COLOR2)) { color2=getKeyValueArgument("color2",1,pa); dprintfparsed("got color2: %s\n",color2);} char *rpn=NULL; if (bitscmp(PARSE_RPN)) { rpn=getKeyValueArgument("rpn",1,pa); dprintfparsed("got rpn: %s\n",rpn);} char *legend=NULL; if (bitscmp(PARSE_LEGEND)) { legend=getKeyValueArgument("legend",1,pa); dprintfparsed("got legend: \"%s\"\n",legend);} char *fraction=NULL; if (bitscmp(PARSE_FRACTION)) { fraction=getKeyValueArgument("fraction",1,pa); dprintfparsed("got fraction: %s\n",fraction);} /* * here the ones without delayed assigns (which are for positional parsers) */ if (bitscmp(PARSE_FORMAT)) { char *format=getKeyValueArgument("format",1,pa); if(format) { strncpy(gdp->format,format,FMT_LEG_LEN); dprintfparsed("got format: %s\n",format); } } if (bitscmp(PARSE_STRFTIMEVFMT)) { char *strft=getKeyValueArgument("strftime",1,pa); char *frmtr=getKeyValueArgument("vformatter",1,pa); gdp->strftm=(strft)?1:0; if (frmtr != NULL) { if (strcmp(frmtr,"timestamp") == 0) { gdp->vformatter = VALUE_FORMATTER_TIMESTAMP; } else if (strcmp(frmtr,"duration") == 0) { gdp->vformatter = VALUE_FORMATTER_DURATION; } else { rrd_set_error("Unsupported vformatter: %s", frmtr); return NULL; } } dprintfparsed("got strftime: %s\n",strft); } if (bitscmp(PARSE_STACK)) { char *stack=getKeyValueArgument("stack",1,pa); gdp->stack=(stack)?1:0; dprintfparsed("got stack: %s\n",stack); } if (bitscmp(PARSE_SKIPSCALE)) { char *skipscale=getKeyValueArgument("skipscale",1,pa); gdp->skipscale =(skipscale)?1:0; dprintfparsed("got skipscale: %s\n",skipscale); } if (bitscmp(PARSE_REDUCE)) { char *reduce=getKeyValueArgument("reduce",1,pa); if (reduce) { gdp->cf_reduce=cf_conv(reduce); gdp->cf_reduce_set=1; dprintfparsed("got reduce: %s (%i)\n",reduce,gdp->cf_reduce); if (((int)gdp->cf_reduce)==-1) { rrd_set_error("bad reduce CF: %s",reduce); return NULL; } } } if (bitscmp(PARSE_DAEMON)) { char *daemon=getKeyValueArgument("daemon",1,pa); if (daemon) { strncpy(gdp->daemon,daemon,strlen(daemon)); dprintfparsed("got daemon: %s\n", gdp->daemon); } } if (bitscmp(PARSE_XAXIS)) { long xaxis=0; char *t,*x; if ((t=getKeyValueArgument("xaxis",1,pa)) && ((getLong(t,&xaxis,&x,10))||(xaxis<1)||(xaxis>MAX_AXIS))) { rrd_set_error("Bad xaxis value: %s",t); return NULL; } dprintfparsed("got xaxis: %s (%li)\n",t,xaxis); gdp->xaxisidx=xaxis; } if (bitscmp(PARSE_YAXIS)) { long yaxis=0; char *t,*x; if ((t=getKeyValueArgument("yaxis",1,pa)) && ((getLong(t,&yaxis,&x,10))||(yaxis<1)||(yaxis>MAX_AXIS))) { rrd_set_error("Bad yaxis value: %s",t); return NULL; } dprintfparsed("got yaxis: %s (%li)\n",t,yaxis); gdp->yaxisidx=yaxis; } if (bitscmp(PARSE_LINEWIDTH)) { double linewidth = 1; char *t,*x; if ((t=getKeyValueArgument("linewidth",1,pa))&&(*t!=0)) { if ((getDouble(t,&linewidth,&x))||(linewidth<=0)) { rrd_set_error("Bad line width: %s",t); return NULL; } } dprintfparsed("got linewidth: %s (%g)\n",t,linewidth); gdp->linewidth=linewidth; } if (bitscmp(PARSE_GRADHEIGHT)) { double gradheight=0; char *t,*x; if ((t=getKeyValueArgument("gradheight",1,pa))&&(*t!=0)) { if (getDouble(t,&gradheight,&x)) { rrd_set_error("Bad gradheight: %s",t); return NULL; } dprintfparsed("got gradheight: %s (%g)\n",t,gradheight); gdp->gradheight=gradheight; } } if (bitscmp(PARSE_STEP)) { long step=0; char *t,*x; if ((t=getKeyValueArgument("step",1,pa)) && ((getLong(t,&step,&x,10))||(step<1))) { rrd_set_error("Bad step value: %s",t); return NULL; } dprintfparsed("got step: %s (%li)\n",t,step); gdp->step=step; } if ((bitscmp(PARSE_START)||bitscmp(PARSE_END))) { /* these should get done together to use the start/end code correctly*/ char* parsetime_error; /* first start */ char* start; rrd_time_value_t start_tv; start_tv.type = ABSOLUTE_TIME; start_tv.offset = 0; localtime_r(&gdp->start, &start_tv.tm); if (bitscmp(PARSE_START)) { start=getKeyValueArgument("start",1,pa); if ((start)&&(parsetime_error = rrd_parsetime(start, &start_tv))) { rrd_set_error("start time: %s", parsetime_error);return NULL; } dprintfparsed("got start: %s\n",start); } else { start = NULL; } /* now end */ char* end; rrd_time_value_t end_tv; end_tv.type = ABSOLUTE_TIME; end_tv.offset = 0; localtime_r(&gdp->end, &end_tv.tm); if (bitscmp(PARSE_END)) { end=getKeyValueArgument("end",1,pa); if ((end)&&(parsetime_error = rrd_parsetime(end, &end_tv))) { rrd_set_error("end time: %s", parsetime_error); return NULL; } dprintfparsed("got end: %s\n",end); } else { end = NULL; } /* and now put the pieces together (relative times like start=end-2days) */ time_t start_tmp = 0, end_tmp = 0; if (rrd_proc_start_end(&start_tv, &end_tv, &start_tmp, &end_tmp) == -1) { return NULL; } dprintfparsed("got start %s translated to: %lld\n",start,(long long int)start_tmp); dprintfparsed("got end %s translated to: %lld\n",end,(long long int)end_tmp); /* check some ranges */ if (start_tmp < 3600 * 24 * 365 * 10) { rrd_set_error("the first entry to fetch should be " "after 1980 (%ld)", start_tmp); return NULL; } if (end_tmp < start_tmp) { rrd_set_error("start (%ld) should be less than end (%ld)", start_tmp, end_tmp); return NULL; } /* and finally set it irrespectively of if it has been set or not * it may have been a relative time and if you just set it partially * then that is wrong... */ gdp->start = start_tmp; gdp->start_orig = start_tmp; gdp->end = end_tmp; gdp->end_orig = end_tmp; } if (bitscmp(PARSE_DASHES)) { char* dashes=getKeyValueArgument("dashes",1,pa); /* if we got dashes */ if (dashes) { gdp->dash = 1; gdp->offset = 0; /* count the , in dashes */ int cnt=0;for(char*t=dashes;(*t)&&(t=strchr(t,','));t++,cnt++) {;} dprintfparsed("Got dashes argument: %s with %i comma\n",dashes,cnt); /* now handle */ gdp->ndash = cnt+1; gdp->p_dashes = (double *) malloc(sizeof(double)*(gdp->ndash+1)); /* now loop dashes */ for(int i=0;i<gdp->ndash;i++) { char *x; int f=getDouble(dashes,&gdp->p_dashes[i],&x); if(f<0) { rrd_set_error("Could not parse number: %s",dashes); return NULL; } /* we should have this most of the time */ dprintfparsed("Processed %s to %g at index %i\n",dashes,gdp->p_dashes[i],i); if (f>0) { if (*x!=',') { rrd_set_error("expected a ',' at : %s",x); return NULL;} dashes=x+1; } if ((f==0)&&(i!=gdp->ndash-1)) { rrd_set_error("unexpected end at : %s",dashes); return NULL;} } } char* dashoffset=getKeyValueArgument("dash-offset",1,pa); if (dashoffset) { char* x; if (getDouble(dashoffset,&gdp->offset,&x)) { rrd_set_error("Could not parse dash-offset: %s",dashoffset); return NULL; } } } /* here now the positional(=legacy) parsers which are EXCLUSIVE - SO ELSE IF !!! * we also only parse the extra here and assign just further down * TODO maybe we can generalize this a bit more... */ if (bitscmp(PARSE_VNAMERRDDSCF)) { if ((!vname)||(!rrd)) { /* get the first unused argument */ keyvalue_t* first=getFirstUnusedArgument(1,pa); if (!first) { rrd_set_error("No argument for definition of vdef/rrd in %s",pa->arg_orig); return NULL; } dprintfparsed("got positional vname and rrd: %s - %s\n",first->key,first->value); if (!vname) {vname=first->key;} if (!rrd) {rrd=first->value; } } /* and now look for datasource */ if (!ds) { /* get the first unused argument */ keyvalue_t* first=getFirstUnusedArgument(1,pa); if (!first) { rrd_set_error("No argument for definition of DS in %s",pa->arg_orig); return NULL; } dprintfparsed("got positional ds: %s - \n",first->value); ds=first->value; } /* and for CF */ if (!cf) { /* get the first unused argument */ keyvalue_t* first=getFirstUnusedArgument(1,pa); if (!first) { rrd_set_error("No argument for definition of CF in %s",pa->arg_orig); return NULL; } dprintfparsed("got positional cf: %s - \n",first->value); cf=first->value; } } else if (bitscmp(PARSE_VNAMECOLORLEGEND)) { /* vname */ if (!vname) { keyvalue_t* first=getFirstUnusedArgument(1,pa); if (first) { vname=first->value; } else { rrd_set_error("No positional VNAME"); return NULL; } } /* fraction added into the parsing mix for TICK */ if ((bitscmp(PARSE_VNAMECOLORFRACTIONLEGEND))&&(!fraction)) { keyvalue_t* first=getFirstUnusedArgument(1,pa); if (first) { fraction=first->value; } else { rrd_set_error("No positional FRACTION"); return NULL; } } /* legend (it's optional if no other arguments follow)*/ if (!legend) { keyvalue_t* first=getFirstUnusedArgument(1,pa); if (first) { legend=first->keyvalue; dprintfparsed("got positional legend: %s - \n",legend); } } } else if (bitscmp(PARSE_VNAMERPN)) { if ((!vname)||(!rpn)) { /* get the first unused argument */ keyvalue_t* first=getFirstUnusedArgument(1,pa); if (!first) { rrd_set_error("No argument for definition of vdef/rrd in %s",pa->arg_orig); return NULL; } dprintfparsed("got positional vname and rpn: %s - %s\n",first->key,first->value); if (!vname) {vname=first->key;} if (!rpn) {rpn=first->value; } } } else if (bitscmp(PARSE_VNAMEREFPOS)) { if ((!vname)) { /* get the first unused argument */ keyvalue_t* first=getFirstUnusedArgument(1,pa); if (!first) { rrd_set_error("No argument for definition of vdef/rrd in %s",pa->arg_orig); return NULL; } dprintfparsed("got positional vname and rrd: %s - %s\n",first->key,first->value); if (!vname) {vname=first->value;} } } /* and set some of those late assignments to accommodate the legacy parser*/ /* first split vname into color */ if (vname) { /* check for color */ char *h1=strchr(vname,'#'); char* h2=NULL; if (h1) { *h1=0;h1++; dprintfparsed("got positional color: %s - \n",h1); h2=strchr(h1,'#'); if (h2) { *h2=0;h2++; dprintfparsed("got positional color2: %s - \n",h2); } } if (bitscmp(PARSE_COLOR) && (! color) && (h1)) { color=h1;} if (bitscmp(PARSE_COLOR2) && (! color2) && (h2)) { color2=h2;} } /* check if we are reusing the vname */ if (vname) { int idx=find_var(im, vname); dprintfparsed("got positional index %i for %s - \n",idx,vname); /* some handling */ if (bitscmp(PARSE_VNAMEDEF)) { if (idx>=0) { rrd_set_error("trying to reuse vname %s",vname); return NULL; } } else if (bitscmp(PARSE_VNAMEREF)) { gdp->vidx=idx; if (idx < 0){ if (bitscmp(PARSE_VNAMEREFNUM)) { double val; char *x; int f=getDouble(vname,&val,&x); if (f) { rrd_set_error("%s is not a vname nor a number",vname); return NULL; } if (gf==GF_VRULE){ gdp->xrule=val; } else { gdp->yrule=val; } } else { rrd_set_error("vname %s not found",vname); return NULL; } } } } /* and assign it */ if (vname) { strncpy(gdp->vname,vname,MAX_VNAME_LEN); gdp->vname[MAX_VNAME_LEN] = '\0'; } if (rrd) { strncpy(gdp->rrd,rrd, 1023); gdp->rrd[1023] = '\0'; } if (ds) { strncpy(gdp->ds_nam,ds,DS_NAM_SIZE - 1); gdp->ds_nam[DS_NAM_SIZE - 1] = '\0'; } if (cf) { gdp->cf=cf_conv(cf); if (((int)gdp->cf)==-1) { rrd_set_error("bad CF: %s",cf); return NULL; } } else { if (bitscmp(PARSE_CF)) { gdp->cf = (enum cf_en) -1; }} if ((color)&&(parse_color(color,&(gdp->col)))) { return NULL; } if ((color2)&&(parse_color(color2,&(gdp->col2)))) { return NULL; } if (rpn) {gdp->rpn=rpn;} if ((legend)&&(*legend!=0)) { /* and copy it into place */ strncpy(gdp->legend,legend,FMT_LEG_LEN); } if (fraction) { if (strcmp(fraction,"vname")==0) { /* check that vname is really a DEF|CDEF */ if (im->gdes[gdp->vidx].gf != GF_DEF && im->gdes[gdp->vidx].gf != GF_CDEF) { rrd_set_error("variable '%s' not DEF nor CDEF when using dynamic fractions", gdp->vname); return NULL; } /* add as flag to use (c)?def */ gdp->cf=CF_LAST; gdp->yrule=0.5; } else { /* parse number */ double val; char *x; int f=getDouble(fraction,&val,&x); if (f) { rrd_set_error("error parsing number %s",vname); return NULL; } gdp->yrule=val; } } /* remember the index for faster varfind */ char *key = gdes_fetch_key((*gdp)); if (gdp->gf == GF_DEF && !g_hash_table_lookup_extended(im->rrd_map,key,NULL,NULL)){ dprintfhash("ins key %s - %ld\n",key,im->gdes_c-1); g_hash_table_insert(im->gdef_map,g_strdup(key),GINT_TO_POINTER(im->gdes_c-1)); } free(key); if (gdp->gf == GF_DEF || gdp->gf == GF_VDEF || gdp->gf == GF_CDEF){ dprintfhash("ins vname %s - %ld\n",gdp->vname,im->gdes_c-1); g_hash_table_insert(im->gdef_map,g_strdup(gdp->vname),GINT_TO_POINTER(im->gdes_c-1)); } return gdp; }
void rrd_graph_script( int argc, char *argv[], image_desc_t *const im, int optno) { int i; /* and now handle the things*/ parsedargs_t pa; initParsedArguments(&pa); /* loop arguments */ for (i = optno; i < argc; i++) { /* release parsed args - avoiding late cleanups*/ freeParsedArguments(&pa); /* processed parsed args */ if (parseArguments(argv[i],&pa)) { return; } /* dumpArguments(&pa); */ /* now let us handle the field based on the first command or cmd=...*/ char*cmd=NULL; /* and try to get via cmd */ char* t=getKeyValueArgument("cmd",255,&pa); if (t) { cmd=t; } else if ((t=getKeyValueArgument("pos0",255,&pa))) { cmd=t; } else { rrd_set_error("no command set in argument %s",pa.arg_orig); freeParsedArguments(&pa); return; } /* convert to enum but handling LINE special*/ enum gf_en gf = (enum gf_en) -1; gf=gf_conv(cmd); if ((int)gf == -1) { if (strncmp("LINE",cmd,4)==0) { gf=GF_LINE; addToArguments(&pa,NULL,"linewidth",cmd+4,0); } else { rrd_set_error("'%s' is not a valid function name in %s", cmd,pa.arg_orig ); return; } } /* now we can handle the commands */ int r=0; switch (gf) { case GF_XAXIS: r=parse_axis(gf,&pa,im); break; case GF_YAXIS: r=parse_axis(gf,&pa,im); break; case GF_DEF: r=parse_def(gf,&pa,im); break; case GF_CDEF: r=parse_cvdef(gf,&pa,im); break; case GF_VDEF: r=parse_cvdef(gf,&pa,im); break; case GF_LINE: r=parse_line(gf,&pa,im); break; case GF_AREA: r=parse_area(gf,&pa,im); break; case GF_PRINT: r=parse_gprint(gf,&pa,im); break; case GF_GPRINT: r=parse_gprint(gf,&pa,im); break; case GF_COMMENT: r=parse_comment(gf,&pa,im); break; case GF_HRULE: r=parse_hvrule(gf,&pa,im); break; case GF_VRULE: r=parse_hvrule(gf,&pa,im); break; case GF_STACK: r=parse_stack(gf,&pa,im); break; case GF_TICK: r=parse_tick(gf,&pa,im); break; case GF_TEXTALIGN: r=parse_textalign(gf,&pa,im); break; case GF_SHIFT: r=parse_shift(gf,&pa,im); break; case GF_XPORT: r=parse_xport(gf,&pa,im); break; /* unsupported types right now */ } /* handle the return error case */ if (r) { freeParsedArguments(&pa); return;} /* check for unprocessed keyvalue args */ char *s; if ((s=checkUnusedValues(&pa))) { /* set error message */ rrd_set_error("Unused Arguments \"%s\" in command : %s",s,pa.arg_orig); free(s); /* exit early */ freeParsedArguments(&pa); return; } } /* finally free arguments */ freeParsedArguments(&pa); }
static int parse_shift(enum gf_en gf,parsedargs_t* pa,image_desc_t *const im) { keyvalue_t *kv; /* get new graph that we fill */ graph_desc_t *gdp=newGraphDescription(im,gf,pa,PARSE_VNAMEREFPOS); if (!gdp) { return 1;} /* and check that it is a CDEF */ switch (im->gdes[gdp->vidx].gf) { case GF_DEF: case GF_CDEF: dprintf("- vname is of type DEF or CDEF, OK\n"); break; case GF_VDEF: rrd_set_error("Cannot shift a VDEF: '%s' in line '%s'\n", im->gdes[gdp->vidx].vname, pa->arg_orig); return 1; default: rrd_set_error("Encountered unknown type variable '%s' in line '%s'", im->gdes[gdp->vidx].vname, pa->arg_orig); return 1; } /* now parse the "shift" */ char* shift=getKeyValueArgument("shift",1,pa); if (!shift) { kv=getFirstUnusedArgument(1,pa); if (kv) shift=kv->value; } if (!shift) { rrd_set_error("No shift given"); return 1; } /* identify shift */ gdp->shidx=find_var(im, shift); if (gdp->shidx>=0) { /* it is a def, so let us check its type*/ switch (im->gdes[gdp->shidx].gf) { case GF_DEF: case GF_CDEF: rrd_set_error("Offset cannot be a (C)DEF: '%s' in line '%s'\n", im->gdes[gdp->shidx].vname, pa->arg_orig); return 1; case GF_VDEF: dprintf("- vname is of type VDEF, OK\n"); break; default: rrd_set_error ("Encountered unknown type variable '%s' in line '%s'", im->gdes[gdp->vidx].vname, pa->arg_orig); return 1; } } else { /* it is no def, so parse as number */ long val; char *x; int f=getLong(shift,&val,&x,10); if (f) { rrd_set_error("error parsing number %s",shift); return 1; } gdp->shval = val; gdp->shidx = -1; } /* debug output */ dprintf("=================================\n"); dprintf("SHIFT : %s\n",pa->arg_orig); dprintf("VNAME : %s (%li)\n",im->gdes[gdp->vidx].vname,gdp->vidx); if (gdp->shidx>=0) { dprintf("SHIFTBY : %s (%i)\n",im->gdes[gdp->shidx].vname,gdp->shidx); } else { dprintf("SHIFTBY : %li\n",gdp->shval); } dprintf("=================================\n"); /* and return */ return 0; }