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

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