1 /* 2 3 * Copyright (c) 1984, 1985, 1986 AT&T 4 * All Rights Reserved 5 6 * THIS IS UNPUBLISHED PROPRIETARY SOURCE 7 * CODE OF AT&T. 8 * The copyright notice above does not 9 * evidence any actual or intended 10 * publication of such source code. 11 12 */ 13 /* @(#)arith.c 1.1 */ 14 15 /* 16 * ARITH.C 17 * 18 * Programmer: D. G. Korn 19 * 20 * Owner: D. A. Lambeth 21 * 22 * Date: April 17, 1980 23 * 24 * 25 * 26 * AEVAL (STRING) 27 * 28 * Evaluate STRING as an arithmetic expression (possibly 29 * containing variables from trees in NAMEP) and return its value. 30 * 31 * LOOKUP (NAME) 32 * 33 * Return a pointer to the shell-owned Namnod in TREE 34 * whose namid is NAME. If TYPE is non-zero, a new Namnod 35 * with the given namid will be inserted, when none is found. 36 * 37 * These functions are indirectly mutually recursive. 38 * 39 * 40 * 41 * See Also: LET(I), findnod(III) 42 */ 43 44 #ifdef KSHELL 45 #include "shtype.h" 46 #else 47 #include <ctype.h> 48 #endif /* KSHELL */ 49 #include <stdio.h> 50 #include "name.h" 51 #include "flags.h" 52 53 #define getchr() (*(unsigned char*)strg++) 54 #define seekto(loc) (strg=(loc)) 55 #define ungetc() (--strg) 56 #define peekc() (*strg) 57 #define MAXLOOP 10 58 59 extern union Namval *aget_up(); 60 extern char *bracket_match(); 61 extern char *valup(); 62 extern void failed(); 63 extern struct Namnod *findnod(); 64 #ifdef NAME_SCOPE 65 extern struct Namnod *copy_nod(); 66 #endif 67 struct Namnod *lookup(); 68 69 static long arith(); 70 static void aerror(); 71 72 static char *strg = 0; 73 static int level = 0; 74 75 /* 76 * AEVAL (STRING) 77 * 78 * char *STRING; 79 * 80 * 81 * Evaluate string as an arithmetic expression (possibly 82 * containing variables from trees in NAMEP) and return its 83 * value as a long int. STRING can be anything acceptable to 84 * the LET(I) builtin of the shell. 85 * 86 */ 87 88 long aeval(string) 89 char *string; 90 { 91 long r; 92 long arith(); 93 char *ostr; 94 ostr = strg; 95 if(level++ > MAXLOOP) 96 aerror(string,badnum); 97 strg = string; 98 r = arith(0); 99 strg = ostr; 100 level--; 101 return(r); 102 } 103 104 /* 105 * ARITH (PREC) 106 * 107 * int PREC; 108 * 109 * Evaluate the expression given in the global pointer strg 110 * as an arithmetic expression, to PREC digits. The form 111 * of strg is as is given for the LET builtin. 112 */ 113 114 static long int arith(prec) 115 { 116 register int c; 117 #ifdef pdp11 118 long r; 119 long rr; 120 #else 121 register long r; 122 register long rr; 123 #endif 124 int base; 125 char *ostr; 126 char dot = 0; 127 128 /* ignore whitespace */ 129 while((c=getchr()),isspace(c)); 130 if(c==0) 131 goto done; 132 ostr = (strg-1); 133 r = 0; 134 if(c == '-') 135 r = -arith(8); 136 else if(c == '!') 137 r = !arith(7); 138 else if(isalpha(c)) 139 { 140 int oldc; 141 char *varname,*sp; 142 varname = ostr; 143 for(;isalnum(c);c=getchr()); 144 if(c == '[') 145 { 146 seekto(bracket_match(ungetc())); 147 c = getchr(); 148 if(c == 0) 149 aerror(varname,subscript); 150 c = getchr(); 151 } 152 /* null terminate variable name */ 153 sp = (strg-1); 154 *sp = 0; 155 /* skip over whitespace */ 156 for(oldc = c;isspace(c);c = getchr()); 157 if(c == '='&& peekc() != '=') 158 asslong(lookup(varname),r=arith(2)); 159 else 160 { 161 char *str; 162 register struct Namnod *np = lookup(varname); 163 register union Namval *up; 164 ungetc(); 165 if (attest (np, INT_GER)) 166 { 167 #ifdef NAME_SCOPE 168 if (attest (np,C_WRITE)) 169 np = copy_nod(np,1); 170 #endif 171 up= &np->value.namval; 172 if(attest(np,IN_DIR)) 173 up = up->up; 174 if(attest (np, (BLT_NOD))) 175 r = (long)((*up->fp->f_vp)()); 176 else if(up->lp==NULL) 177 r = 0; 178 else 179 r = *up->lp; 180 } 181 else 182 { 183 if((str=valup(np))==0 || *str==0) 184 aerror(varname,badnum); 185 r = aeval(str); 186 } 187 } 188 *sp = oldc; 189 } 190 else 191 { 192 base = 10; 193 ungetc(); 194 lastbase = base; 195 } 196 197 while((c=getchr()) && c != ']') 198 { 199 switch(c) 200 { 201 case ')': 202 if(prec) 203 goto done; 204 else 205 aerror(ostr,synmsg); 206 207 case '(': 208 r = arith(1); 209 if((c=getchr()) != ')') 210 aerror(ostr,synmsg); 211 break; 212 213 case '=': case '!': 214 if(prec > 3) 215 goto done; 216 if(getchr() != '=') 217 aerror(ostr,synmsg); 218 rr = arith(4); 219 if(c == '=') 220 r = r == rr; 221 else 222 r = r != rr; 223 break; 224 225 case '<': case '>': 226 if(prec > 4) 227 goto done; 228 if(peekc() == '=') 229 { 230 getchr(); 231 rr = arith(5); 232 if(c == '<') 233 r = r <= rr; 234 else 235 r = r >= rr; 236 break; 237 } 238 rr = arith(5); 239 if(c == '<') 240 r = r < rr; 241 else 242 r = r > rr; 243 break; 244 245 case '+': case '-': 246 if(prec > 5) 247 goto done; 248 rr = arith(6); 249 if(c == '+') 250 r += rr; 251 else 252 r -= rr; 253 break; 254 255 case '*': case '/': case '%': 256 if(prec > 6) 257 goto done; 258 rr = arith(7); 259 if (c == '*') 260 r *= rr; 261 else if(rr == 0) 262 aerror(ostr,divzero); 263 else if (c == '/') 264 r /= rr; 265 else 266 r %= rr; 267 break; 268 269 case ' ': case '\n': case '\t': 270 break; 271 272 case '#': 273 lastbase = base = r; 274 r = 0; 275 break; 276 277 case '.': 278 if(dot++==0) 279 continue; 280 281 default: 282 { 283 register int d; 284 for(d=0; hdigits[d] && c != hdigits[d];d++); 285 d >>= 1; 286 if( d < base ) 287 { 288 if(dot==0) 289 r = base*r + d; 290 } 291 else 292 aerror(ostr,badnum); 293 } 294 } 295 } 296 done: 297 ungetc(); 298 return(r); 299 } 300 301 static void aerror(name,msg) 302 char *name,*msg; 303 { 304 level = 0; 305 failed(name,msg); 306 } 307 308 /* 309 * lookup name and return Namnod pointer with this name. 310 * If none exists, it will be created. 311 */ 312 313 struct Namnod *lookup(name) 314 char *name; 315 { 316 register struct Namnod *np = NULL; 317 register struct Amemory *ap; 318 register struct Amemory *app = namep; 319 int type = 0; 320 while((ap=app) && np==NULL) 321 { 322 app = app->nexttree; 323 np =findnod(name,ap,type|(app==NULL)); 324 type = RE_USE; 325 } 326 return(np); 327 } 328 329