(file) Return to thTestParse.c CVS log (file) (dir) Up to [HallC] / Analyzer / CTP

   1 saw   1.1 /*-----------------------------------------------------------------------------
   2            * Copyright (c) 1993 Southeastern Universities Research Association,
   3            *                    Continuous Electron Beam Accelerator Facility
   4            *
   5            * This software was developed under a United States Government license
   6            * described in the NOTICE file included as part of this distribution.
   7            *
   8            * Stephen A. Wood, 12000 Jefferson Ave., Newport News, VA 23606
   9            * Email: saw@cebaf.gov  Tel: (804) 249-7367  Fax: (804) 249-5800
  10            *-----------------------------------------------------------------------------
  11            * 
  12            * Description:
  13            *  The expression parser and stack executor for the Test Package
  14            *	
  15            * Author:  Stephen Wood, CEBAF Hall C
  16            *
  17            * Revision History:
  18            *   $Log: thTestParse.c,v $
  19 saw   1.3  *   Revision 1.19  1999/08/25 13:16:07  saw
  20            *   *** empty log message ***
  21            *
  22            *   Revision 1.18  1999/07/07 13:43:51  saw
  23            *   Don't make numbers starting with "0" be octal.  Accept 0x as hex.
  24            *
  25            *   Move thTestRHandler() into thTestParse.c
  26 saw   1.2  *
  27            *   Revision 1.17  1999/03/01 20:00:50  saw
  28            *   Fix bug where a series of numbers added or subtracted in a parameter line
  29            *   got evaluated to be just the first number.  Improve the scientific
  30            *   number detection to do this.
  31            *
  32 saw   1.1  *   Revision 1.16  1996/07/31 20:36:56  saw
  33            *   Support floating point for mod command.  Add trig functions.
  34            *
  35            * Revision 1.15  1995/08/03  13:56:36  saw
  36            * Add single argument functions
  37            *
  38            * Revision 1.14  1995/04/10  15:51:21  saw
  39            * thEvalImed returns INTOVF if double result is to large to convert to int.
  40            *
  41            * Revision 1.13  1995/02/14  16:53:52  saw
  42            * Make compatible with OSF/Alpha (64 bit pointers)
  43            *
  44            * Revision 1.12  1995/01/09  16:06:11  saw
  45            * Fix a short malloc for a string
  46            *
  47            * Revision 1.11  1994/11/17  18:14:21  saw
  48            * Strip out unary + operators when parsing expressions
  49            *
  50            * Revision 1.10  1994/11/07  14:28:34  saw
  51            * Add thevalchk fortran call to check for expressions.
  52            * Try to avoid bomb outs for bad expressions
  53 saw   1.1  *
  54            * Revision 1.9  1994/10/03  12:41:22  saw
  55            * All "/" (division) has real result.  New op "//" has integerized
  56            * result.  thEvalImed actually gets a double from thTestExecute.
  57            * Added fortran interfaces to thEvalImed (itheval, ftheval, dtheval).
  58            *
  59            * Revision 1.8  1994/09/12  15:12:31  saw
  60            * thGetTok was missing reset of lastop on EOL
  61            *
  62            * Revision 1.7  1994/08/29  20:08:10  saw
  63            * Fix calculation of testscalervarname length
  64            *
  65            * Revision 1.6  1994/08/26  17:46:18  saw
  66            * Register test scaler results
  67            *
  68            * Revision 1.5  1994/08/26  13:36:46  saw
  69            * Add DAVAR_REPOINTOK to some flags
  70            *
  71            * Revision 1.4  1994/06/03  18:54:29  saw
  72            * Replace stderr with STDERR
  73            *
  74 saw   1.1  * Revision 1.3  1993/12/02  21:33:36  saw
  75            * Fully allow use of doubles in test expressions
  76            *
  77            * Revision 1.2  1993/11/24  21:24:54  saw
  78            * thEvalImed now returns double instead of floating result.
  79            *
  80            *	  Revision 1.3  1993/09/22  17:51:06  saw
  81            *	  Allow integer constants to be octal or hex.
  82            *
  83            *	  Revision 1.2  1993/05/11  18:00:10  saw
  84            *	  Update header
  85            *
  86            */
  87           
  88           /* thTestParse.c
  89              
  90              Make test result variable that are created take the type of the rhs???
  91              Add variable names to stack so that expressions can be recreated.
  92              Allow constants to be hex or octal.
  93              Agree on a new comment character or syntax since ! is not part
  94              of expressions.
  95 saw   1.1    Add unary operators to executor.  Allow + to be a unary operator too.
  96           
  97              Need to build up a linked list of test results used in a block.  Don't
  98              duplicate any variables.  Print warning when a scaler test result is
  99              reused.
 100           
 101           */
 102           /*An argument is a variable name, an array, or a number.  Numbers are not
 103           allowed for test result.  Arrays start at 0 if []'s are used and start
 104           at 1 if ()'s are used.  Arrays may only be used for test results if they
 105           are already registered by the analyzer.  (May add option to declare them
 106           in the test package.)*/
 107           
 108           #include <stdio.h>
 109           #include <string.h>
 110           #include <math.h>
 111           #include <values.h>
 112 saw   1.3 #include <rpc/rpc.h>
 113 saw   1.1 #include "daVar.h"
 114 saw   1.3 #include "daVarRpc.h"
 115           #include "daVarHandlers.h"
 116 saw   1.1 #include "th.h"
 117           #include "thUtils.h"
 118           #include "thTestParse.h"
 119           #include "thInternal.h"
 120           #include "cfortran.h"
 121           
 122 saw   1.3 void thTestRHandler(char *name, daVarStruct *varclass, any *retval);
 123 saw   1.1 
 124           CODE opstack[100];		/* Operator stack */
 125           CODE typstack[100];		/* Result type stack */
 126           
 127           typedef struct
 128           {
 129             char *ops;
 130             int  toks[3];
 131           } OPTABLE;
 132           
 133           OPTABLE optable[] =
 134           {
 135             {"(",{OPLP}},
 136             {")",{OPRP}},
 137             {"[",{OPLINDEXB}},
 138             {"]",{OPRP}},
 139             {"-",{OPSUB}},
 140             {"+",{OPADD}},
 141             {"<<=",{OPISLT,OPSHL,OPISLE}},
 142             {">>=",{OPISGT,OPSHR,OPISGE}},
 143             {"==",{OPEQUAL,OPISEQUAL}},
 144 saw   1.1   {"!=",{OPNOT,OPISNOTEQUAL}},
 145             {"&&",{OPBITAND,OPLOGAND}},
 146             {"||",{OPBITOR,OPLOGOR}},
 147             {"^^",{OPBITXOR,OPLOGXOR}},
 148             {"*",{OPTIMES}},
 149             {"//",{OPDIV,OPIDIV}},
 150             {"%",{OPMOD}},
 151             {"~",{OPCOMP}},
 152             {",",{OPCOMMA}},
 153             {0,{0,0,0}}};
 154           static char *opchars=0;
 155           
 156           /* For Q like test package format, must be in same order as type
 157              types listed in typedef for thTestType. */
 158           char *testCodes[tBAD] 
 159             = {"GA","PA","EQ","BI","AN","IO","EO","MA","US"};
 160           
 161           typedef struct
 162           {
 163             CODE op;
 164             CODE result[9];
 165 saw   1.1 } TYPETABLE;
 166           
 167           TYPETABLE typetable[] =
 168           {
 169             {OPLINDEX,{0,0,0,1,1,1,2,2,2}}, /* Result is same as variable */
 170             {OPLINDEXB,{0,0,0,1,1,1,2,2,2}}, /* being indexed */
 171             {OPLINDEXP,{0,0,0,1,1,1,2,2,2}}, /* Result is same as variable */
 172             {OPLINDEXPB,{0,0,0,1,1,1,2,2,2}}, /* being indexed */
 173             {OPEQUAL,{0,0,0,1,1,1,2,2,2}}, /* Set result type to LHS type */
 174             {OPLOGOR,{0,0,0,0,0,0,0,0,0}}, /* Result is always integer */
 175             {OPLOGXOR,{0,0,0,0,0,0,0,0,0}},
 176             {OPLOGAND,{0,0,0,0,0,0,0,0,0}},
 177             {OPBITOR,{0,0,0,0,0,0,0,0,0}},
 178             {OPBITXOR,{0,0,0,0,0,0,0,0,0}},
 179             {OPBITAND,{0,0,0,0,0,0,0,0,0}},
 180             {OPISEQUAL,{0,0,0,0,0,0,0,0,0}},
 181             {OPISNOTEQUAL,{0,0,0,0,0,0,0,0,0}},
 182             {OPISLT,{0,0,0,0,0,0,0,0,0}},
 183             {OPISLE,{0,0,0,0,0,0,0,0,0}},
 184             {OPISGT,{0,0,0,0,0,0,0,0,0}},
 185             {OPISGE,{0,0,0,0,0,0,0,0,0}},
 186 saw   1.1   {OPSHL,{0,0,0,0,0,0,0,0,0}},
 187             {OPSHR,{0,0,0,0,0,0,0,0,0}},
 188             {OPADD,{0,2,2,2,2,2,2,2,2}},	/* Result is double unless both ops int */
 189             {OPSUB,{0,2,2,2,2,2,2,2,2}},
 190             {OPTIMES,{0,2,2,2,2,2,2,2,2}},
 191             {OPDIV,{2,2,2,2,2,2,2,2,2}},	/* Result always double */
 192             {OPIDIV,{0,0,0,0,0,0,0,0,0}},	/* Result always integer */
 193             {OPMOD,{0,2,2,2,2,2,2,2,2}},
 194             {OPNEG,{0,1,2,0,1,2,0,1,2}},	/* No lh operand, type = rh type */
 195             {OPNOT,{0,0,0,0,0,0,0,0,0}},	/* No lh operand, type always int */
 196             {OPCOMP,{0,0,0,0,0,0,0,0,0}},	/* No lh operand, type always int */
 197             {0,{0,0,0,0,0,0,0,0,0}}};
 198           
 199           INTRINSIC_FUNCTIONS intrinsic_functions[] =
 200           {
 201             {"abs",{0,1,2}},
 202             {"sqrt",{2,2,2}},
 203             {"exp",{2,2,2}},
 204             {"sin",{2,2,2}},
 205             {"cos",{2,2,2}},
 206             {"tan",{2,2,2}},
 207 saw   1.1   {0,{0,0,0}}
 208           };
 209           char *thGetTok(char *linep, int *tokenid, char **tokstr,
 210           	       CODE *tokval, void **tokptr, int expflag, daVarStructList **vlisthead)
 211           /* Pass a pointer to the unscanned portion of the line.
 212              Returns An ID code for operators, and an operand type for operands in
 213              tokenid.
 214              Returns the string for the operand in tokstr.  (Null otherwise)
 215              Returns the operand value in tokval, or in tokptr if the operand is
 216              a pointer.
 217              If the operand is a function, then tokenid will be pushfunction, and
 218              tokval will be a the fuction id.
 219           
 220              Function returns pointer to remainder of the line.
 221           
 222           
 223              */
 224           {
 225             static char string[100];
 226             static int lasttoktype=0;	/* Last tok was an operator */
 227             static CODE lastop=0;
 228 saw   1.1 
 229             char *savelinep;
 230             char *stringp;
 231             char *ptr,c;
 232             int tindex,sindex;
 233             daVarStruct *varp;
 234             DAFLOAT f;
 235           
 236             /* Build up a list of characters that can start operators */
 237             if(opchars == 0){
 238               int count=0;
 239               int i;
 240           
 241               while(optable[count++].ops != 0) ;
 242               opchars = (char *) malloc(count);
 243               for(i=0;i<(count-1); i++)
 244                 opchars[i] = optable[i].ops[0];
 245               opchars[count-1] = 0;
 246             }
 247           
 248             *tokstr = 0;
 249 saw   1.1   *tokval = 0;
 250             *tokptr = 0;
 251             *tokenid = 0;			/* Will signify an undeclared operand */
 252           
 253             if(!(*linep)) {
 254               *tokenid = OPEOL;
 255               lasttoktype = 0;
 256               lastop = 0;
 257               return(0);
 258             }
 259             savelinep = linep;
 260             while(*linep == ' ' || *linep == '\t') linep++;
 261             if((ptr = strchr(opchars,*linep))) { /* Operator */
 262               tindex = ptr -  opchars;
 263               if(lasttoktype == 0 && *linep == '-') { /*  Last thing was an operator */
 264                 *tokenid = OPNEG;		/* So the '-' must be a negative sign */
 265                 linep++;
 266               } else if(lasttoktype == 0 && *linep == '+') { /* Unary plus */
 267                 linep++;
 268                 goto operand;
 269               } else if(lasttoktype == 1 && *linep == '(') {
 270 saw   1.1       *tokenid = OPLINDEX;
 271                 linep++;
 272               } else if(lasttoktype == 3 && *linep == '(') {
 273           	/* How will we know when the right hand operator is the closing
 274           	   paren of the function?  We don't need to know.  The RHP only
 275           	   acts to determine precedence.  */
 276                 *tokenid = OPLFARG;
 277                 linep++;
 278               } else {
 279                 linep++;
 280                 *tokenid = optable[tindex].toks[0];
 281                 sindex = 1;
 282                 if(*linep) {		/* Don't search past end of line */
 283           	while((c = optable[tindex].ops[sindex])) {
 284           	  if(*linep == c) {
 285           	    *tokenid = optable[tindex].toks[sindex];
 286           	    linep++;
 287           	    break;
 288           	  }
 289           	  sindex++;
 290           	}
 291 saw   1.1       }
 292               }
 293               /*  Following two lines were before last }. */
 294               if(*tokenid == OPRP) lasttoktype = 2; /* Minus is minus after ) or ] */
 295               else lasttoktype = 0;
 296               /* For OPLINDEX and OPLINDEXB, need to search ahead for matching ) or ]
 297                  and check if the next operator is an = not ==).  If so, then we
 298                  need to return OPLINDEXP or OPLINDEXPB.  */
 299               if(*tokenid == OPLINDEX || *tokenid == OPLINDEXB){
 300                 char *p; char rc; int ccount=0; int bcount=0;
 301                 if(*tokenid == OPLINDEXB) rc = ']';
 302                 else rc = ')';
 303                 p = linep;
 304                 while(*p && (*p != rc || bcount || ccount)) {
 305           	switch(*p++)
 306           	  {
 307           	  case '(': ccount++; break;
 308           	  case ')': ccount--; break;
 309           	  case '[': bcount++; break;
 310           	  case ']': bcount--; break;
 311           	  default: break;
 312 saw   1.1 	  }
 313                 }				/* Only NULL or balanced rc terminates */
 314                 if(*p++){			/* Search for = */
 315           	while(*p == ' ' || *p=='\t') p++;
 316           	if(*p == '=' && *(p+1) != '=') {
 317           	  *tokenid += (OPLINDEXP - OPLINDEX); 
 318           	  /* Assumes OPLINDEXBP-OPLINDEXB is the same*/
 319           	}
 320                 } else
 321           	fprintf(STDERR,"thTest: Parenthesis balance problem\n");
 322               }
 323               lastop = *tokenid;
 324             } else {			/* Operand */
 325               int optype;
 326               int isnum;
 327               int efound;
 328           
 329             operand:
 330               lasttoktype = 1;
 331               stringp = string;
 332               /* Scan until operator or whitespace is reached */
 333 saw   1.1     isnum = 1; efound = 0;
 334           /* What a hack to check for scientific notation */
 335               while(*linep && *linep!=' ' && *linep!='\t' && !strchr(opchars,*linep)){
 336                 if(*linep == 'e' || *linep == 'E') {
 337           	if(efound) {
 338           	  isnum = 0;
 339           	} else {
 340           	  if(stringp > string) {
 341           	    efound=1;
 342           	  } else {
 343           	    isnum = 0;
 344           	  }
 345           	}
 346                 } else if(!isdigit(*linep) && *linep != '.') isnum = 0;
 347                 *stringp++ = *linep++;
 348               }
 349               if(isnum && efound) {	/* Exponential, scan past last digit */
 350                 if(*linep == '-' || *linep == '+') *stringp++ = *linep++;
 351                 while(isdigit(*linep)) {
 352           	*stringp++ = *linep++;
 353                 }
 354 saw   1.1     }
 355               while(*linep == ' ' || *linep == '\t') linep++; /* Skip past whitespace */
 356               *stringp = 0;
 357               *tokstr = string;
 358           /*    printf("token=%s\n",string);*/
 359               switch(thIDToken(string))
 360                 {
 361                 case TOKINT:
 362 saw   1.2 	if(string[0] == '0' && (string[1] == 'x' || string[1] == 'X')) {
 363           	  sscanf(string,"%li",tokval); /* Treat as Hex */
 364           	} else {
 365           	  sscanf(string,"%ld",tokval); /* Treat as decimal */
 366           	}
 367 saw   1.1 	*tokenid = OPPUSHINT;
 368           	break;
 369                 case TOKFLOAT:
 370           	f = atof(string);
 371           	*tokval = *(DAINT *)&f;	/* Copy floating value */
 372           	*tokenid = OPPUSHFLOAT;
 373           	break;
 374                 case TOKVAR:
 375           	{
 376           	  char **classlist;
 377           	  thOperandType optype;
 378           
 379           	  optype = thGetOperandType(string,linep,lastop,0);
 380           	  classlist = thGetClassList(optype);
 381 saw   1.3 	  /* Probably should consistently use the same class list of
 382           	     TEST,EVENT,PARM here */
 383 saw   1.1 /* If token is a result variable (and we are in non-immediate mode), and the
 384              variable is an integer type, then we need to add this variable to a list
 385              of variables for the current block.   (Probably add real  variable to
 386              the list anyway. ) This will allow us to acumulate scalers.  The opaque
 387              pointer of each variable in the list will point to the scaler array. */
 388           
 389           	  /* First check if variable is really an intrinsic function */
 390           	  {
 391           	    int ifunc;
 392           	    ifunc = 0;
 393           	    while(intrinsic_functions[ifunc].name) {
 394           	      if(strcasecmp(string,intrinsic_functions[ifunc].name)==0) {
 395           		*tokenid = OPPUSHFUNCTION;
 396           		*tokval = ifunc;
 397           		lasttoktype = 3;
 398           		break;
 399           	      }
 400           	      ifunc++;
 401           	    }
 402           	    if(*tokenid) break;	/* Hopefully this breaks out of case */
 403           	  }
 404 saw   1.1 	  if(daVarLookupPWithClass(string,classlist,&varp) == S_SUCCESS) {
 405           /*	    printf("Found variable %s[%s]\n",string,varp->name);*/
 406           	    if(varp->type == DAVARFLOAT) {/* If next operator is a ( or [ */
 407           /*	      printf("FLOAT ");*/
 408           	      /* then push pointer instead of */
 409           #define ISARRAYORLHS(x) (*x=='(' || *x=='[' || (*x=='=' && *(x+1)!='='))
 410           	      *tokenid = ISARRAYORLHS(linep) ? OPPUSHPFLOAT : OPPUSHFLOATP; 
 411           	    } else if(varp->type == DAVARDOUBLE){	/* value onto rpn stack */
 412           /*	      printf("DOUBL ");*/
 413           	      *tokenid = ISARRAYORLHS(linep) ? OPPUSHPDOUBLE : OPPUSHDOUBLEP;
 414           	    } else if(varp->type == DAVARINT){	/* value onto rpn stack */
 415           /*	      printf("INT   ");*/
 416           	      *tokenid = ISARRAYORLHS(linep) ? OPPUSHPINT : OPPUSHINTP;
 417           	    }
 418           	    else {
 419           	      fprintf(STDERR
 420           		      ,"thTest: Variable %s[%s] must be integer, float or double\n"
 421           		      ,string,varp->name);
 422           	    }
 423           /*	    *tokval = *(DAINT *)&varp->varptr;*/ /* Get the pointer */
 424           	    *tokptr = varp->varptr;
 425 saw   1.1 	  } else if(*linep=='=' && (*(linep+1)!='=')){
 426           	    /* Undefined variable is an unindexed result */
 427           	    /* For now, create an integer variable.  Later figure out how
 428           	       to make the variable the same type as the rhs */
 429           	    daVarStruct var;
 430           	    var.name = (char *) malloc(strlen(classlist[0])
 431           				       +strlen(string)+2);
 432           	    strcpy(var.name,classlist[0]);
 433           	    strcat(var.name,".");
 434           	    strcat(var.name,string);
 435           	    var.varptr = (void *) malloc(sizeof(DAINT));
 436           	    var.size = 1;
 437           	    var.opaque = 0;
 438           	    var.rhook = var.whook = 0;
 439           	    var.type = DAVARINT;
 440           	    var.flag = DAVAR_READONLY | DAVAR_REPOINTOK;
 441           	    var.title = savelinep;
 442           	    daVarRegister((int) 0,&var); /* Create test result */
 443           	    daVarLookupP(var.name,&varp);
 444           	    free(var.name);
 445           printf("Created test result %s\n",varp->name);
 446 saw   1.1 	    *tokenid = OPPUSHPINT;
 447           /*	    *tokval = *(DAINT *)&varp->varptr;*/
 448           	    *tokptr = varp->varptr;
 449           	  } /* else 
 450           	       printf("%s not found\n",string);
 451           	       }*/
 452           	  /* If variable does not exist, caller will note that toktype and
 453           	     tokval have not been set. */
 454           	  if(optype == otRESULT && vlisthead){ /* Don't make scalers for */
 455           	    thAddVarToList(vlisthead,varp); /* Variables created in */
 456           	    if(varp->type == DAVARINT) { /* thEvalImed */
 457           	      DAINT *sarray; int i;
 458           	      if(varp->opaque == 0) { /* No scaler array yet */
 459           		char *testscalervarname;
 460           		daVarStruct *svarp; /* Pointer to scaler var struct */
 461           		testscalervarname = /* Add the "scaler" attribute */
 462           		  (char *) malloc(strlen(varp->name)+strlen(SCALERSTR)+2);
 463           		strcpy(testscalervarname,varp->name);
 464           		strcat(testscalervarname,".");
 465           		strcat(testscalervarname,SCALERSTR);
 466           		if(daVarLookupP(testscalervarname,&svarp) != S_SUCCESS) {
 467 saw   1.1 		  daVarStruct svar;
 468           		  svar.name = testscalervarname;
 469           		  svar.opaque = 0;
 470           		  svar.rhook = svar.whook = 0;
 471           		  svar.type = DAVARINT;
 472           		  svar.flag = DAVAR_READONLY | DAVAR_REPOINTOK;
 473           		  svar.varptr = (void *) malloc(varp->size*sizeof(DAINT));
 474           		  svar.size = varp->size;
 475           		  /* Actually not OK to repoint, but this says CTP made it */
 476           		  svar.title = varp->name;
 477           		  daVarRegister((int) 0, &svar);
 478           		  daVarLookupP(svar.name,&svarp);
 479           		}
 480           		varp->opaque = (DAINT *) svarp->varptr;
 481           		varp->rhook = thTestRHandler;
 482           		free(testscalervarname);
 483           	      }
 484           	      sarray = varp->opaque;
 485           	      for(i=0;i<varp->size;i++)
 486           		sarray[i] = 0;
 487           	    }
 488 saw   1.1 	  }
 489           	}
 490           	break;
 491                 default:
 492           	fprintf(STDERR,"thTest: Error understanding %s\n",string);
 493           	break;
 494                 }
 495           /*    printf("token = %x\n",*tokenid);*/
 496               lastop = 0;
 497             }
 498             while(*linep == ' ' || *linep == '\t') linep++; /* Skip whitespace */
 499             return(linep);
 500           }
 501             
 502           
 503           char **thGetClassList(thOperandType optype)
 504           {
 505             static char *explist[]={PARMSTR,EVENTSTR,TESTSTR,0}; /* Immediate expressions */
 506             static char *loglist[]={TESTSTR,PARMSTR,EVENTSTR,0}; /* Logical operand */
 507             static char *numlist[]={EVENTSTR,PARMSTR,TESTSTR,0}; /* Operand is a value */
 508             static char *resultlistp[]={TESTSTR,EVENTSTR,PARMSTR,0}; /* Operand is a result */
 509 saw   1.1 
 510 saw   1.3 #define ALWAYSTESTFIRST
 511           #ifdef ALWAYSTESTFIRST
 512             return(resultlistp);
 513           #else
 514 saw   1.1   switch(optype)
 515               {
 516               case otIMMED:
 517                 return(explist);
 518               case otLOGIC:
 519                 return(loglist);
 520               case otVALUE:
 521                 return(numlist);
 522               case otRESULT:
 523                 return(resultlistp);
 524               }
 525 saw   1.3 #endif
 526 saw   1.1 }
 527           
 528           thOperandType thGetOperandType(char *soperand, char *rest, CODE lastop,
 529           			       int expflag)
 530           {
 531             if(expflag)
 532               return(otIMMED);
 533             else if(lastop == OPNOT)
 534               return(otLOGIC);
 535             else if(lastop != 0 && (lastop != OPLOGOR)
 536           		  && (lastop != OPLOGAND) && (lastop != OPLOGXOR)
 537           		  && (lastop != OPEQUAL) && (lastop != OPCOMMA)
 538           		  && (lastop != OPLP))
 539               return(otVALUE);
 540             else {
 541               /* This is really ugly code to determine if the operand
 542                  is a result, logical operand, or numerical operand from the
 543                  surrounding operators.  The last operator is known, but it must
 544                  search ahead for the next operator.  This code should be  burried
 545                  in a subroutine. */
 546               
 547 saw   1.1     char *p;
 548               p = rest;
 549               if(*p == '(' || *p == '[') {
 550                 int ccount=0; int bcount=0;
 551                 if(*p++ == '(') ccount++; else bcount++;
 552                 while(*p && (bcount || ccount)){
 553           	/*	      printf("%c(%d,%d)\n",*p,ccount,bcount);*/
 554           	switch(*p++) {
 555           	case '(': ccount++; break; case ')': ccount--; break;
 556           	case '[': bcount++; break; case ']': bcount--; break;
 557           	default: break;
 558           	}
 559                 }
 560                 /*	    printf("pos=%c, %d %d ",*p,ccount,bcount);*/
 561               }
 562               while(*p == ' ' || *p =='\t') p++;
 563           #define ISLOG(x,y) (*x==y && *(x+1)==y)
 564               /*	  printf(", Nextchar=%c:  ",*p);*/
 565               if(*p=='=' && *(p+1)!='=') {
 566                 return(otRESULT);
 567               } else if((ISLOG(p,'|') || ISLOG(p,'&') || ISLOG(p,'^')
 568 saw   1.1 	       || *p=='\0' || *p==',' || *p == ')'))
 569                 return(otLOGIC);
 570             }
 571             return(otVALUE);
 572           }
 573           
 574           CODE thGetResultType(CODE operator, CODE leftoptype, CODE rightoptype)
 575           {
 576             /* For a given operator, determine the data type of the result a given
 577                combination of the types of the lh and rh operands.
 578                Assumes that only types 0, 1, or 2 are allowed. */
 579             
 580             int lrindex;
 581             int i;
 582           
 583             if(leftoptype < 0 || leftoptype > 2 || rightoptype < 0 || rightoptype > 2) {
 584               fprintf(STDERR,"thTest: Illegal operand type %x %x\n",leftoptype,rightoptype);
 585               return(0);
 586             }
 587             lrindex = (leftoptype * 3) + rightoptype;
 588             for(i=0; typetable[i].op; i++) { /* Do Linear search for the operator */
 589 saw   1.1     if(operator == typetable[i].op) {
 590                 return(typetable[i].result[lrindex]);
 591               }
 592             }
 593             fprintf(STDERR,"Operator %x not found in result type table\n",operator);
 594             return(0);
 595           }
 596           
 597 saw   1.3 thStatus thEvalImed(char *line, DADOUBLE *d, DAINT *i)
 598 saw   1.1 /* ImmedOBiately evaluate the expression in line.  Will internally evaluate to
 599              a float, and then pass back both the float and interized values. */
 600           {
 601             CODEPTR codehead, codenext, codelimit, codelastop;
 602             int codesize;
 603           #define RDOUBLE
 604           #ifdef RDOUBLE
 605             double result;
 606           #else
 607             float result;			/* Should    change to double */
 608           #endif
 609             thStatus retcode;
 610           
 611           /*  printf("%s=",line);*/
 612             codesize = 10+2*strlen(line);
 613             codehead = codenext = (CODEPTR) malloc(sizeof(CODE)*codesize);
 614             codelimit = codehead + codesize;
 615           #ifdef RDOUBLE
 616             *codenext++ = OPPUSHPDOUBLE;
 617           #ifdef USEMEMCPY
 618             {
 619 saw   1.1     void *resultp;
 620               resultp = &result;
 621             memcpy(((void **)codenext)++, (void *) &resultp, sizeof(void *));
 622             }
 623           #else
 624             *((void **) codenext)++ = (void *) &result;
 625           #endif
 626           /*  printf("%x\n",codenext);*/
 627           #else
 628             *codenext++ = OPPUSHPFLOAT;	/* Should change to double */
 629             *((void **) codenext)++ = (void *) &result;
 630           #endif
 631             retcode = S_SUCCESS;
 632             if(thBookaTest(line,&codehead,&codenext,&codelimit,&codelastop,0)!=S_SUCCESS) {
 633               fprintf(STDERR,"Failure interpreting expression |%s|\n",line);
 634               result = 0.0;
 635               retcode = S_FAILURE;
 636             } else {
 637               int exptype;
 638               CODE lastop;
 639           #if 0
 640 saw   1.1     printf("%x-%x=%d\n",codenext,codehead,codenext-codehead);
 641               {
 642                 CODEPTR code;
 643                 for(code=codehead;code < codenext; code++)
 644           	if(code==codelastop) printf("* %x\n",*code);
 645           	else printf("  %x\n",*code);
 646               }
 647           #endif
 648               codenext = codelastop;
 649               exptype = *codenext++ & OPRESTYPEMASK;
 650               lastop = *codelastop & OPCODEMASK;
 651               if(lastop == OPPUSHPINT || lastop == OPPUSHINTP) {
 652                 *((DAINT **)codenext)++;
 653               } else if(lastop == OPPUSHINT) {
 654                 if(exptype == OPRDOUBLE) {
 655           	*((DADOUBLE *)codenext)++;
 656                 } else {			/* Assume ints, floats have size */
 657           	*((DAINT *)codenext)++;
 658                 }
 659               }
 660           #ifdef RDOUBLE
 661 saw   1.1     *codenext++ = OPEQUAL | 0x202 | (exptype<<4);
 662           #else
 663               *codenext++ = OPEQUAL | 0x101 | (exptype<<4);
 664           #endif
 665           #ifdef RDOUBLE
 666               *codenext++ = OPEOL | (OPRDOUBLE<<4);
 667           #else
 668               *codenext++ = OPEOL;
 669           #endif
 670               if(thExecuteCode("IMMED",codehead,codenext)!=S_SUCCESS){
 671                 fprintf(STDERR,"Failure evaluating expression |%s|\n",line);
 672                 result = 0.0;
 673                 retcode = S_FAILURE;
 674               }
 675             }
 676           /*  printf("%f\n",result);*/
 677             free(codehead);
 678             if(d) *d = result;
 679             if(i) {
 680               if(result>=MAXINT || result <=-MAXINT) {
 681                 if(retcode==S_SUCCESS)
 682 saw   1.1 	retcode=S_INTOVF;
 683               } else {
 684                 *i = floatToLong(result);
 685               }
 686             }
 687             return(retcode);
 688           }
 689             
 690           thStatus thBookaTest(char *line, CODEPTR *codeheadp, CODEPTR *codenextp,
 691           		     CODEPTR *codelimitp, CODEPTR *codelastop, daVarStructList **vlisthead)
 692           /* if expflag != 0, still treat as an expression even if there is no
 693              equal sign in the line.
 694              Return codes:
 695                S_SUCCESS = Line OK
 696                S_FAILURE = Line not executable
 697           */
 698           {
 699             /*  int type;*/
 700             char *args[20];
 701             int nargs;
 702             thTokenType toktyp;
 703 saw   1.1   daVarStruct var, *varp;
 704             thTestType test_type;
 705             int forcefloat;
 706             int iarg;
 707             char *token;
 708             CODEPTR codenext;
 709             int index;			/* Used for index into arrays */
 710             thStatus status;
 711             int expflag;
 712           
 713             if(codelastop) expflag = 1; else expflag = 0;
 714             status = S_SUCCESS;
 715             if(*codenextp + 2*strlen(line) > *codelimitp) {
 716               CODEPTR src,dst,newhead;
 717               int newsize;
 718           /*    printf("Increasing the size of the code stack from %d ",
 719           	   *codelimitp-*codeheadp);*/
 720               src = *codeheadp;
 721               newsize = max((*codelimitp-*codeheadp)+CODEGROWSIZE
 722           		  ,(*codenextp-*codeheadp)+2*strlen(line));
 723               newhead = dst = (CODEPTR) malloc(sizeof(CODE)*newsize);
 724 saw   1.1     while(src < *codenextp) *dst++ = *src++;
 725               if(*codeheadp) free(*codeheadp);
 726               *codelimitp = newhead + newsize;
 727               *codeheadp = newhead;
 728               *codenextp = *codenextp + (dst - src);
 729               
 730               /*printf("to %d, using %d\n",*codelimitp-*codeheadp,*codenextp - *codeheadp);*/
 731             }
 732             codenext = *codenextp;
 733           
 734           /*  printf("Booking \"%s\"\n",line);*/
 735             if(strchr(line,'=')||expflag) {
 736               char *linep;
 737               int TOKEN,TOKCOMP;
 738               char *tokstr; CODE tokval;
 739               void *tokptr;
 740               CODE *osp, *tsp, opcode;
 741               CODE rightoptype,leftoptype,resultoptype;
 742           
 743               osp = opstack;		/* Stack of pending operators */
 744               *osp = '\0';
 745 saw   1.1 
 746               tsp = typstack;		/* Stack of Current result type */
 747           				/* Like the stack in the executor but only */
 748           				/* contains the data types */
 749               linep = line;
 750               do {
 751                 /* Get tokens until there are no more (last token will be OPEOL) */
 752                 linep = thGetTok(linep,&TOKEN, &tokstr, &tokval, &tokptr, expflag, vlisthead);
 753                 if(tokstr) {		/* Operand */
 754           /*	printf("Operand %s |",tokstr);*/
 755           	if(codelastop) *codelastop = codenext; /* HACK for thImmed: Save ptr to last operator */
 756           	if(TOKEN) {
 757           	  if(tokptr == 0) {	/* Value operand - 4 bytes */
 758           	    *codenext++ = TOKEN;	/* String not put on stack at moment */
 759           	    *codenext++ = tokval;
 760           	  } else {		/* Pointer operand - maybe 8 bytes */
 761           	    *codenext++ = TOKEN;
 762           #ifdef USEMEMCPY
 763           	    memcpy(((void **)codenext)++,&tokptr,sizeof(void *));
 764           #else
 765           	    *((void **)codenext)++ = tokptr;
 766 saw   1.1 #endif
 767           	  }
 768           	  /* If TOKEN is push function, then tokval is an index into a list of
 769           	     functions.  We put this index on tsp instead of the result type. */
 770           	  if(TOKEN==OPPUSHFUNCTION) {
 771           	    *tsp++ = tokval;
 772           	  } else {
 773           	    *tsp++ = TOKEN & OPRESTYPEMASK;
 774           	  }
 775           	} else {
 776           	  fprintf(STDERR,"thTest: Unregistered variable %s\n",tokstr);
 777                     status = S_TH_UNREG;
 778           	  *codenext++ = OPPUSHINT;
 779           	  *codenext++ = 0;
 780           	  *tsp++ = OPPUSHINT & OPRESTYPEMASK;
 781           	}
 782                 } else {			/* Operator */
 783           	switch(TOKEN)
 784           	  {
 785           	  case 0:
 786           	    fprintf(STDERR,"thTest: Bad token\n");
 787 saw   1.1 	    return(S_FAILURE);
 788           	    break;
 789           	  case OPLP:
 790           	    *++osp = TOKEN;
 791           	    break;
 792           	  default:
 793           /*	    printf("OSP:");
 794           	    {CODE *sp; for(sp=opstack;sp<=osp;sp++)
 795           	       printf("%x:",*sp);}
 796           	    printf("\n");
 797           */
 798           	    /* Generate code for all operators of equal or higher precedence
 799           	       that are pending on the operator stack. */
 800           	    if((TOKEN & OPGROUPMASK) == OPLINDEXGROUP)
 801           	      TOKCOMP = 0xFFFFFFF; /* Nothing higher in precedence */
 802           	    else
 803           	      TOKCOMP = TOKEN & OPPRECMASK;
 804           	    while((*osp & OPPRECMASK) >= TOKCOMP){
 805           /*	      if((*osp & OPPRECMASK) == OPLINDEX){*/
 806           	      if((*osp & OPGROUPMASK) == OPLINDEXGROUP){
 807           		if(TOKEN == OPRP) {
 808 saw   1.1 		  if(*osp == OPLFARG) TOKEN = OPRFARG;
 809           		  else TOKEN = OPRINDEX; /* Break from case */
 810           		}
 811           		TOKCOMP = 0xFFFFFFF; /* Terminate osp rundown */
 812           	      }
 813           	      rightoptype = *--tsp;
 814           	      leftoptype = ((*osp & OPPRECMASK) == OPUNARY) ? 0 : (*--tsp);
 815           	      /* If the Operator is "evaluate function", we need to find out
 816           		 what the function is so that we can get the correct
 817           		 result type.  leftoptype should be an index into
 818           		 "intrinsic_functions".  We can use that and rightoptype
 819           		 to look up the resulttype. */
 820           	      if(*osp==OPLFARG) {
 821           		resultoptype = 
 822           		  intrinsic_functions[leftoptype].result[rightoptype];
 823           	      } else {
 824           		resultoptype = thGetResultType(*osp,leftoptype,rightoptype);
 825           	      }
 826           	      opcode = *osp--;
 827           	      opcode |= (leftoptype << 8) | (rightoptype << 4)
 828           		| resultoptype;
 829 saw   1.1 	      if(codelastop) if((opcode&&OPCODEMASK) !=OPEOL) *codelastop = codenext; /* HACK for thImmed: Save ptr to last operator */
 830           	      *codenext++ = opcode;
 831           	      *tsp++ = resultoptype; /* Keep a rpn stack of the data type */
 832           	    }
 833           	    if(TOKEN == OPRINDEX || TOKEN == OPRFARG) break; /* No clean up needed */
 834           
 835           	    if(TOKEN == OPRP) {
 836           	      if(*osp == OPLP) osp--; /* ) removes matching ( */
 837           	      else {
 838           		fprintf(STDERR,"Right paren not matched by left\n");
 839           		return(S_FAILURE);
 840           	      }
 841           	    } else if(TOKEN == OPEOL || TOKEN == OPCOMMA) {
 842           	      if(codelastop) if(TOKEN==OPCOMMA) *codelastop = codenext; /* HACK for thImmed: Save ptr to last operator */
 843           	      *codenext++ = TOKEN | (*--tsp) << 4; /* Leave type in Right type field */
 844           	    } else {
 845           	      *++osp = TOKEN;
 846           	    }
 847           	    break;
 848           	  }
 849                 }
 850 saw   1.1       /* Token processed */
 851               } while (linep);
 852           /* Check that stacks are OK.  Need to add some clean up of allocated memory. */
 853               if(tsp != typstack) {
 854                 fprintf(STDERR,"%d items left on type stack\n",tsp-typstack);
 855                 return(S_FAILURE);
 856               }
 857               if(osp != opstack) {
 858                 fprintf(STDERR,"%d items left on operand stack\n",osp-opstack);
 859                 return(S_FAILURE);
 860               }
 861             } else {			/* Old style test lines */
 862               int i;
 863               nargs = thCommas(line,args);
 864               for(i=0;i<nargs;i++){
 865                 args[i] = thSpaceStrip(args[i]); /* Remove all space from the argument */
 866               }
 867               
 868               if(nargs <= 1) return(S_FAILURE);
 869               
 870               {				/* Interpret the test type. */
 871 saw   1.1       
 872                 for(test_type=0;test_type<tBAD;test_type++){
 873           	if(testCodes[test_type][0] == toupper(args[1][0]) &&
 874           	   testCodes[test_type][1] == toupper(args[1][1])) break;
 875                 }
 876                 if(test_type == tBAD) return(S_FAILURE);
 877                 /*    printf("%s\n",testCodes[test_type]);*/
 878               }
 879               if(test_type == tGATE || test_type == tEQ) {
 880                 forcefloat = 1;
 881               } else forcefloat = 0;
 882               for(iarg=2;iarg<nargs;iarg++){
 883                 DAFLOAT f;		/* Should do double  here */
 884                 token = args[iarg];
 885                 toktyp = thIDToken(token);
 886                 switch((toktyp = thIDToken(token)))
 887           	{
 888           	case TOKINT:
 889           	  *codenext++ = PUSHI;
 890           	  if(forcefloat) {
 891           	    f = atof(token);
 892 saw   1.1 	    *codenext++ = *(DAINT *)&f;
 893           	  } else {
 894           	    DAINT i;
 895 saw   1.2 	    if(token[0] == '0' && (token[1] == 'x' || token[1] == 'X')) {
 896           	      sscanf(token,"%li",&i); /* Treat as Hex */
 897           	    } else {
 898           	      sscanf(token,"%ld",&i); /* Treat as decimal */
 899           	    }
 900 saw   1.1 	    *codenext++ = i;
 901           	  }
 902           	  break;
 903           	case TOKFLOAT:		/* Should Do all floats as doubles */
 904           	  *codenext++ = PUSHI;
 905           	  if(forcefloat) {
 906           	    f = atof(token);
 907           	    *codenext++ = *(DAINT *)&f;
 908           	  } else {
 909           	    *codenext++ = (DAINT) floatToLong(atof(token));
 910           	  }
 911           	  break;
 912           	case TOKARRAY:
 913           	case TOKVAR:
 914           	  {
 915           	    char *p; int index; char leftp;
 916           	    if(toktyp == TOKARRAY) {
 917           	      p = thTokenArray(token,&index);
 918           	      leftp = *p; *p = 0;	/* Save ( or [ then null terminate */
 919           	    } else
 920           	      index = 0;
 921 saw   1.1 	    if(daVarLookup(token,&var)!=S_SUCCESS) {
 922           	      fprintf(STDERR,"(thTest) %s not registered\n",token);
 923           	      *codenext++ = PUSHI;
 924           	      if(forcefloat) {
 925           		f = 0.0;
 926           		*codenext++ = *(DAINT *)&f;
 927           	      } else
 928           		*codenext++ = 0;
 929           	    } else {
 930           	      if(forcefloat)
 931           		if(var.type == DAVARINT)
 932           		  *codenext++ = PUSHITOFS; /* Push converting to float and skip */
 933           		else if(var.type == DAVARFLOAT)
 934           		  *codenext++ = PUSHS;
 935           		else
 936           		  *codenext++ = PUSHI; /* Push immediate */
 937           	      else
 938           		if(var.type == DAVARINT)
 939           		  *codenext++ = PUSHS; /* Push and skip */
 940           		else if(var.type == DAVARFLOAT)
 941           		  *codenext++ = PUSHFTOIS;
 942 saw   1.1 		else
 943           		  *codenext++ = PUSHI; /* Push immediate */
 944           	      if(toktyp == TOKARRAY)
 945           		*p = leftp;
 946           	      if(var.type == DAVARINT || var.type == DAVARFLOAT) {
 947           		*((void **)codenext)++ = ((DAINT *) var.varptr+index);
 948           		*((void **)codenext) = (void *) malloc(sizeof(token)+1);
 949           		strcpy((char *) *((void **)codenext)++,token);
 950           	      } else {
 951           		if(forcefloat) {
 952           		  f = 0.0;
 953           		  *codenext++ = *(DAINT *)&f;
 954           		} else
 955           		  *codenext++ = 0;
 956           	      }
 957           	    }
 958           	  }
 959           	  break;
 960           	}
 961               }
 962               *codenext++ = test_type;	/* Operation to do on pushed args */
 963 saw   1.1     *codenext++ = nargs-2;	/* # of args pushed on stack for this op */
 964               
 965               /* Now push test result on stack */
 966               *codenext++ = POPS;
 967               
 968               token = args[0];
 969               toktyp = thIDToken(token);
 970               index = 0;
 971               switch((toktyp = thIDToken(token)))
 972                 {
 973                 case TOKINT:
 974                 case TOKFLOAT:
 975           	fprintf(STDERR,"(thTest) Test result must be a variable name\n");
 976           	return(S_FAILURE);	/* No test is added to program */
 977                 case TOKARRAY:
 978           	/* First check if variable with index has been already registered
 979           	   perhaps from a previous booking of histograms */
 980           	if(daVarLookup(token,&var) != S_SUCCESS){
 981           	  char *p; char leftp;
 982           	  p = thTokenArray(token,&index);
 983           	  leftp = *p; *p = 0;	/* Save ( or [ then null terminate */
 984 saw   1.1 	  if(daVarLookup(token,&var) != S_SUCCESS){
 985           	    fprintf(STDERR,
 986           		    "(thTest) Arrays %s must be registered\n",token);
 987           	    return(S_FAILURE);
 988           	  }
 989           	  *p = leftp;		/* Restore the left ( or [ */
 990           	  if(index >= var.size) {
 991           	    fprintf(STDERR,
 992           		    "(thTest) Array size for %s exceeded\n",token);
 993           	    return(S_FAILURE);
 994           	  }
 995           	  if(var.type != DAVARINT) {
 996           	    fprintf(STDERR,
 997           		    "(thTest) Array %s must be of integer*4\n",token);
 998           	    return(S_FAILURE);
 999           	  }
1000           	  var.varptr = (DAINT *) var.varptr + index;
1001           	  var.name = token;
1002           	  var.opaque = 0;
1003           	}
1004           	var.title = token;	/* Eventually be the input line */
1005 saw   1.1 	break;
1006                 case TOKVAR:
1007           	if(daVarLookup(token,&var)!=S_SUCCESS) {
1008           	  var.name = token;
1009           	  var.varptr = (void *) malloc(sizeof(DAINT));
1010           	  var.opaque = 0;
1011           	  var.rhook = var.whook = 0;
1012           	  var.type = DAVARINT;
1013           	  var.flag = DAVAR_READONLY | DAVAR_REPOINTOK;
1014           /* Do I need to set the size to 1 here??? */
1015           	}
1016           	var.title = token;
1017           	break;
1018                 }
1019               daVarRegister((int) 0, &var);	/* Create or replace variable */
1020               *((void **)codenext)++ = ((DAINT *) var.varptr);
1021               /* Save the token string for future reference */
1022 saw   1.2     *((void **)codenext) = ((void *) malloc(strlen(token)+1));
1023 saw   1.1     strcpy((char *) *((void **)codenext)++,token);
1024             }
1025             *codenextp = codenext;
1026             return(status);
1027             
1028           }
1029 saw   1.3 int thevalchk_(char *A1,unsigned C1)
1030 saw   1.1 /* Check if an expression is valid.  Return's zero if valid */
1031           {
1032 saw   1.3   int A0;
1033 saw   1.1   char *B1;
1034             thStatus status;
1035           
1036             status = thEvalImed((!*(int *)A1)?0:memchr(A1,'\0',C1)?A1:
1037           		      (memcpy(B1=malloc(C1+1),A1,C1),B1[C1]='\0'
1038           		       ,kill_trailing(B1,' ')),0,0);
1039             if(B1) free(B1);
1040             return(status);
1041           }
1042           
1043 saw   1.3 int itheval_(char *A1,unsigned C1)
1044 saw   1.1 {
1045 saw   1.3   int A0;
1046 saw   1.1   char *B1;
1047             DAINT i;
1048             double d;
1049             thStatus status;
1050           
1051             status = thEvalImed((!*(int *)A1)?0:memchr(A1,'\0',C1)?A1:
1052           		      (memcpy(B1=malloc(C1+1),A1,C1),B1[C1]='\0'
1053           		       ,kill_trailing(B1,' ')),0,&i);
1054             if(B1) free(B1);
1055             return i;
1056           }
1057           double dtheval_(char *A1,unsigned C1)
1058           {
1059             char *B1;
1060             double d;
1061             thStatus status;
1062           
1063             status = thEvalImed((!*(int *)A1)?0:memchr(A1,'\0',C1)?A1:
1064           		      (memcpy(B1=malloc(C1+1),A1,C1),B1[C1]='\0'
1065           		       ,kill_trailing(B1,' ')),&d,0);
1066             if(B1) free(B1);
1067 saw   1.1   return d;
1068           }
1069           float ftheval_(char *A1,unsigned C1)
1070           {
1071             char *B1;
1072             DAINT i;
1073             double d;
1074             float f;
1075             thStatus status;
1076           
1077             status = thEvalImed((!*(int *)A1)?0:memchr(A1,'\0',C1)?A1:
1078           		      (memcpy(B1=malloc(C1+1),A1,C1),B1[C1]='\0'
1079           		       ,kill_trailing(B1,' ')),&d,0);
1080             if(B1) free(B1);
1081             f = d;
1082             return f;
1083 saw   1.3 }
1084           
1085           void thTestRHandler(char *name, daVarStruct *varclass, any *retval)
1086           /* The default Read handler */
1087           {
1088             daVarStruct *varp;
1089             char *attribute;
1090             daVarStatus status;
1091             int index;
1092           
1093             status = daVarAttributeFind(name, varclass, &varp, &attribute, &index);
1094             status = daVarRegRatr(varp, attribute, index, retval);
1095             if(status == S_SUCCESS) {
1096               if(strcasecmp(attribute,DAVAR_RATR) == 0){
1097                 retval->any_u.s = realloc(retval->any_u.s,strlen(retval->any_u.s)
1098           				+strlen(TH_SCALER) + 2);
1099                 strcat(retval->any_u.s,TH_SCALER);
1100                 strcat(retval->any_u.s,"\n");
1101               }
1102             } else {
1103               if(strcasecmp(attribute,TH_SCALER) == 0){
1104 saw   1.3       int i;
1105                 if(varp->opaque){
1106           	retval->valtype = DAVARINT_RPC;
1107           	if(index == DAVAR_NOINDEX) {
1108           	  retval->any_u.i.i_len = varp->size;
1109           	  retval->any_u.i.i_val = (int *) malloc(varp->size*sizeof(int));
1110           	  for(i=0;i<varp->size;i++) {
1111           	    retval->any_u.i.i_val[i] = ((DAINT *)varp->opaque)[i];
1112           	  }
1113           	} else {
1114           	  retval->any_u.i.i_len = 1;
1115           	  retval->any_u.i.i_val = (int *) malloc(sizeof(int));
1116           	  retval->any_u.i.i_val[0] = ((DAINT *)varp->opaque)[index];
1117           	}
1118                 } else {
1119           	retval->valtype = DAVARERROR_RPC;
1120           	retval->any_u.error = S_SUCCESS;
1121                 }
1122               }
1123             }
1124             /* A special handler would check more attributes if status != SUCCESS */
1125 saw   1.3   return;
1126 saw   1.1 }

Analyzer/Replay: Mark Jones, Documents: Stephen Wood
Powered by
ViewCVS 0.9.2-cvsgraph-1.4.0