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

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