|
|
1.1 root 1: static char sccsid[] = "@(#)expr.c 2.12";
2:
3: #include "cdb.h"
4: #include "macdefs.h"
5:
6: extern long atol();
7: extern double atof();
8: extern int vrgOffset[]; /* defined in access.c */
9:
10: /* the following define the stack mechanism used by the expression parser */
11:
12: export int viopMac; /* operator stack pointer */
13: export int vivarMac; /* variable stack pointer */
14:
15: #define istkMax 15
16: TYR vrgTy[cTyMax*istkMax]; /* variable stack */
17: ADRT vrgAdr[cTyMax*istkMax]; /* addresses of the variables in vrgTy */
18: TKE vrgTk[istkMax]; /* operator stack */
19:
20: #define TOPOP (vrgTk[viopMac-1])
21: #define TOPVAR (vrgTy[vivarMac-1])
22: #define EmptyStack (vivarMac==0)
23: #define precParen 99
24:
25: /* parser state */
26: #define psFail 0 /* parser tripped */
27: #define psOp 1 /* expression parser last saw an OPERATOR */
28: #define psVar 2 /* expression parser last saw an VARIABLE */
29: typedef int PSE, *pPSE; /* parser state */
30:
31: ADRT vadrSb, vadrSbMax; /* where we can stick strings in child */
32:
33: /* P U S H O P */
34:
35: local void PushOp(tk)
36: TKE tk;
37: {
38: if (viopMac >= istkMax)
39: UError("Expression stack overflow");
40: vrgTk[viopMac++] = tk;
41: } /* PushOp */
42:
43:
44: /* P O P O P */
45:
46: local TKE PopOp()
47: {
48: if (viopMac <= 0)
49: UError("Operator stack underflow");
50: return(vrgTk[--viopMac]);
51: } /* PopOp */
52:
53:
54: /* P U S H V A R */
55:
56: local void PushVar(adrLong, ty)
57: long adrLong;
58: pTYR ty;
59: {
60: if (vivarMac >= istkMax)
61: UError("Expression stack overflow");
62: CopyTy(vrgTy+vivarMac, ty);
63: vrgAdr[vivarMac] = adrLong;
64: vivarMac += 2;
65: } /* PushVar */
66:
67:
68: /* F P O P V A R */
69:
70: local FLAGT FPopVar(pret, ty)
71: long *pret;
72: pTYR ty;
73: {
74: if (vivarMac <= 0)
75: return(false);
76: vivarMac -= 2; /* point to first one */
77: CopyTy(ty, vrgTy+vivarMac);
78: *pret = vrgAdr[vivarMac];
79: return(true);
80: } /* FPopVar */
81:
82:
83: /* A D R F S T O R E */
84:
85: export ADRT AdrFStore(sb, cb)
86: char *sb;
87: int cb;
88: {
89: ADRT adr;
90: TYR ty[cTyMax];
91:
92: /* this routine stores data in the CHILD's address space.
93: * this is mostly useful for passing strings as arguements to
94: * procedure calls from the command line.
95: */
96: if (FOdd(cb))
97: cb++; /* force to word boundary */
98: /* will it fit? */
99: if ((vadrSb == 0) OR (vadrSb+cb >= vadrSbMax)) {
100: /* no, we will go back and use the buffer over again */
101: vadrSb = AdrFGlobal("__buffer", ty);
102: vadrSbMax = AdrFGlobal("_bufMax", ty);
103: if (vadrSb+cb >= vadrSbMax)
104: UError("I can't put something that big in the child. See 'end.c'");
105: }
106: adr = vadrSb;
107: vadrSb += cb; /* advance to next free byte */
108: PutBlock(adr, spaceData, sb, cb);
109: return(adr);
110: } /* AdrFStore */
111:
112:
113: /* P R E C F T K */
114:
115: export int PrecFTk(tk)
116: TKE tk;
117: {
118: /* determine precedence */
119: /* these values are meaningful only in their relationship to one another */
120: switch (tk) {
121: default:
122: return(0);
123: case tkBOE:
124: case tkLP:
125: return(precParen);
126: case tkInside:
127: case tkSizeof:
128: case tkLSB:
129: case tkPtr:
130: case tkDot:
131: return(96);
132: case tkRef:
133: case tkUMinus:
134: case tkBang:
135: case tkTilda:
136: case tkDeref:
137: return(95); /* unary operator */
138: case tkDiv:
139: case tkMul:
140: return(80);
141: case tkPlus:
142: case tkMinus:
143: return(70);
144: case tkLShift:
145: case tkRShift:
146: return(60);
147: case tkLT:
148: case tkLE:
149: case tkGT:
150: case tkGE:
151: return(50);
152: case tkEqual:
153: case tkNotEqual:
154: return(40);
155: case tkBitAnd:
156: return(32);
157: case tkXOR:
158: return(31);
159: case tkBitOr:
160: return(30);
161: case tkLAND:
162: return(21);
163: case tkLOR:
164: return(20);
165: case tkAssPlus:
166: case tkAssMinus:
167: case tkAssMult:
168: case tkAssDiv:
169: case tkAssXOR:
170: case tkAssBAND:
171: case tkAssBOR:
172: case tkAssLeft:
173: case tkAssRight:
174: case tkAssMod:
175: case tkAssign:
176: return(3);
177: case tkComma:
178: case tkEOE:
179: case tkRP:
180: case tkIndex:
181: case tkRSB:
182: return(1);
183: } /* switch */
184: } /* PrecFTk */
185:
186:
187: /* V A L F A D R */
188:
189: export long ValFAdr(adrLong, ty)
190: long adrLong;
191: pTYR ty;
192: {
193: int cb, bt;
194: ADRT adrSrc, adrDest;
195: STUFFU stuff;
196:
197: if (ty->td.fConstant)
198: return(adrLong); /* it was a constant - ergo, it has no address */
199:
200: stuff.lng = 0;
201: adrSrc = adrLong;
202: cb = CbFTy(ty);
203: if (cb > 4)
204: cb = 4; /* this routine is not designed for more than a long */
205:
206: if (ty->td.st == stReg) {
207: #ifndef REGULUS
208: if (cb == CBCHAR) {
209: stuff.chars.chLoLo = GetReg(adrSrc);
210: }
211: else if (cb == CBSHORT) {
212: stuff.shorts.shortLo = GetReg(adrSrc);
213: }
214: else {
215: #if (CBINT == CBSHORT)
216: stuff.shorts.shortHi = GetReg(adrSrc);
217: stuff.shorts.shortLo = GetReg(adrSrc+1);
218: #else
219: stuff.lng = GetReg(adrSrc);
220: #endif
221: } /* if */
222: #else
223: if (trace(ptReadUser, vpid, cb,
224: &stuff, v_ar0+vrgOffset[adrSrc]) < 0)
225: UError("Bad Access");
226: #endif
227: goto extendSign;
228: } /* if */
229:
230: /* figure address we want this read into */
231: adrDest = (cb == 1) ? (ADRT) &(stuff.chars.chLoLo) :
232: (cb == 2) ? (ADRT) &(stuff.shorts.shortLo) :
233: (ADRT) &(stuff.lng);
234:
235: if (ty->td.st == stSpc) {
236: /* a `special' variable (lives in debuggers universe) */
237: MoveBytes(adrDest, adrSrc, cb);
238: goto extendSign;
239: } /* if */
240:
241: /* unfortunately, there are some special addresses which look like adrNil! */
242: if (adrSrc == adrNil)
243: return(0);
244:
245: if (cb > 0) {
246: GetBlock(adrSrc, spaceData, adrDest, cb);
247: return(stuff.lng);
248: }
249: else {
250: /* it must be a bit field spec */
251: /* This is dependent on the order the compiler allocates bits */
252: #ifdef BSD41
253: cb = (ty->valTy + ty->td.width + (SZCHAR-1)) / SZCHAR;
254: GetBlock(adrSrc, spaceData, &stuff.lng, cb);
255: stuff.lng = Extract(stuff.lng, ty->valTy, ty->td.width);
256: return(stuff.lng);
257: #else
258: Panic("Don't know how to handle bit fields for this machine");
259: #endif
260: } /* if */
261:
262: extendSign:
263: /* following forces sign extension */
264: bt = ty->td.bt;
265: if (TqFTy(ty, 1) == tqNil) { /* then it is a base type, not a pointer */
266: if (bt == btChar)
267: stuff.lng = stuff.chars.chLoLo;
268: else if (bt == btShort)
269: stuff.lng = stuff.shorts.shortLo;
270: #if (CBINT == CBSHORT)
271: else if (bt == btInt)
272: stuff.lng = stuff.shorts.shortLo;
273: #endif
274: }
275: return(stuff.lng);
276: } /* ValFAdr */
277:
278:
279: /* P U T V A L */
280:
281: export void PutVal(adrLong, ty, val)
282: long adrLong;
283: pTYR ty;
284: long val;
285: {
286: int cb;
287: ADRT adrDest, adrSrc;
288: STUFFU stuff;
289:
290: if (ty->td.fConstant)
291: return; /* it was a constant - ergo, it lives no where */
292:
293: stuff.lng = val;
294: adrDest = adrLong;
295: cb = CbFTy(ty);
296: if (cb > 4)
297: cb = 4; /* this routine is not designed for more than a long */
298:
299: /* figure address we want this read from */
300: adrSrc = (cb == 1) ? (ADRT) &(stuff.chars.chLoLo) :
301: (cb == 2) ? (ADRT) &(stuff.shorts.shortLo) :
302: (ADRT) &(stuff.lng);
303:
304: if (ty->td.st == stReg) {
305: #ifndef REGULUS
306: if (cb == CBCHAR) {
307: PutReg(adrDest, stuff.chars.chLoLo);
308: }
309: else if (cb == CBSHORT) {
310: PutReg(adrDest, stuff.shorts.shortLo);
311: }
312: else {
313: #if (CBIBT == CBSHORT)
314: PutReg(adrDest, stuff.shorts.shortHi);
315: PutReg(adrDest+1, stuff.shorts.shortLo);
316: #else
317: PutReg(adrDest, stuff.lng);
318: #endif
319: } /* if */
320: #else
321: if (trace(ptWriteUser, vpid, cb,
322: &stuff, v_ar0+vrgOffset[adrDest]) < 0)
323: UError("Bad Access");
324: #endif
325: return;
326: } /* if */
327:
328: if (ty->td.st == stSpc) {
329: /* a `local' variable */
330: MoveBytes(adrDest, adrSrc, cb);
331: return;
332: } /* if */
333:
334: if (cb > 0) {
335: PutBlock(adrDest, spaceData, adrSrc, cb);
336: }
337: else {
338: /* it must be a bit field */
339: #ifdef BSD41
340: cb = (ty->valTy + ty->td.width + (SZCHAR-1)) / SZCHAR;
341: GetBlock(adrDest, spaceData, &stuff.lng, cb);
342: SetBits(stuff.lng, ty->td.width, ty->valTy, val);
343: PutBlock(adrDest, spaceData, &stuff.lng, cb);
344: #else
345: Panic("Don't know how to handle bit fields for this machine");
346: #endif
347: } /* if */
348: } /* PutVal */
349:
350:
351: /* P S F D O O P */
352:
353: local PSE PsFDoOp()
354: {
355: /* this is the rotuine that actually does the TOP operator */
356: int cb1, cb2, tq, ipd;
357: ushort *rgDim;
358: ADRT adr, adrShort;
359: FLAGT fDidIt, fDoIntOp;
360: TKE tk;
361: TYR aty1[cTyMax], aty2[cTyMax], atyMax[cTyMax];
362: pTYR ty, ty1, ty2, tyMax;
363: long adr1, adr2, val1, val2;
364: STUFFU stuff;
365: #define cbAssMax 200
366: char buf[cbAssMax];
367:
368: ty1 = aty1;
369: ty2 = aty2;
370: tyMax = atyMax;
371:
372: if (viopMac < 0)
373: return(psFail);
374:
375: if (TOPOP == tkLP
376: OR TOPOP == tkBOE)
377: return(psFail); /* they should be waiting for one of these */
378: tk = PopOp();
379:
380: if (!FPopVar(&adr2, ty2)) /* every op needs at least one */
381: return(psFail);
382: val2 = ValFAdr(adr2, ty2);
383:
384: fDidIt = true;
385: switch (tk) {
386: /* unary operators */
387: default:
388: fDidIt = false;
389: break;
390: case tkUMinus:
391: ty2->td.fConstant = true;
392: ty2->td.st = stValue;
393: PushVar(-val2, ty2);
394: break;
395: case tkBang:
396: PushVar(lengthen(val2==0), vtyCnInt);
397: break;
398: case tkTilda:
399: ty2->td.fConstant = true;
400: ty2->td.st = stValue;
401: PushVar(~val2, ty2);
402: break;
403: case tkRef:
404: if (ty2->td.fConstant)
405: UError("You can't take the address of a constant");
406: if (ty2->td.st == stReg)
407: UError("You can't take the address of a register");
408: if (!FAdjTd(ty2, tqPtr)) /* add a pointer level */
409: UError("Type information overflow");
410: ty2->td.fConstant = true;
411: ty2->td.st = stValue;
412: PushVar(adr2, ty2);
413: break;
414: case tkDeref:
415: tq = TqFTy(ty2, 1);
416: if ((tq == tqPtr) OR (tq == tqArray))
417: FAdjTd(ty2, tqNil); /* remove tq */
418: ty2->td.st = stValue;
419: if (ty2->td.fConstant) {
420: ty2->td.fConstant = false;
421: PushVar(adr2, ty2);
422: }
423: else if (tq == tqArray) {
424: PushVar(adr2, ty2); /* array is pointer to itself */
425: }
426: else {
427: PushVar(val2, ty2);
428: } /* if */
429: break;
430: case tkInside:
431: adrShort = adr2;
432: ipd = IpdFAdr(adrShort);
433: val2 = (vpc >= vrgPd[ipd].adrStart)
434: AND (vpc < vrgPd[ipd+1].adrStart);
435: PushVar(val2, vtyCnInt);
436: break;
437: case tkSizeof:
438: val2 = CbFTy(ty2);
439: PushVar(val2, vtyCnInt);
440: break;
441: } /* switch */
442: if (fDidIt) /* we must have done one of them - go back */
443: return(psVar);
444:
445: /* not unary, so we pop another and try the binaries */
446: if (!FPopVar(&adr1, ty1))
447: return(psFail);
448: val1 = ValFAdr(adr1, ty1);
449:
450: fDidIt = true;
451: switch (tk) {
452: default:
453: fDidIt = false;
454: break;
455: case tkDot:
456: val1 = adr1; /* direct address, then do ptr */
457: case tkPtr:
458: val1 = AdrFField(val1, ty1, ty2);
459: /* ty1 is struct, ty2 is field */
460: PushVar(val1, ty2);
461: break;
462: case tkIndex: /* foo[x] */
463: tq = TqFTy(ty1, 1);
464: if (tq == tqArray)
465: val1 = adr1; /* array value IS the address */
466: FAdjTd(ty1, tqNil);/* remove ptr or array level */
467: adr1 = val1 + (val2 * CbFTy(ty1));
468: PushVar(adr1, ty1);
469: break;
470:
471: } /* switch */
472: if (fDidIt)
473: return(psVar);
474:
475: /* MaxFTyTy may try to do too much. It first determines if the types
476: * are such that integer operators may be applied to them (and returns
477: * a true/false on this) If so, it copies into tyMax the ty of the
478: * larger of the two operands.
479: */
480: fDoIntOp = MaxFTyTy(tyMax, ty1, ty2);
481: if ( (!fDoIntOp)
482: AND (tk != tkPtr)
483: AND (tk != tkDot)
484: AND (tk != tkAssign) ) {
485: /* they are trying something stupid, like adding structures together */
486: UError("Cannot allow that combination of operand(s) and operator");
487: } /* if */
488:
489: tyMax->td.fConstant = true; /* any op that DOESN'T want this turns it off */
490: tyMax->td.st = stValue;
491: /* binary operators */
492: fDidIt = true;
493: switch (tk) {
494: default:
495: fDidIt = false;
496: break;
497: case tkDiv:
498: val1 = val1 / val2;
499: break;
500: case tkMul:
501: val1 = val1 * val2;
502: break;
503: case tkPlus:
504: val1 = val1 + val2;
505: break;
506: case tkMinus:
507: val1 = val1 - val2;
508: break;
509: case tkBitAnd:
510: val1 = val1 & val2;
511: break;
512: case tkXOR:
513: val1 = val1 ^ val2;
514: break;
515: case tkBitOr:
516: val1 = val1 | val2;
517: break;
518: } /* switch */
519: if (fDidIt) {
520: PushVar(val1, tyMax);
521: return(psVar);
522: } /* if */
523:
524: fDidIt = true;
525: ty = vtyCnInt;
526: switch (tk) {
527: default:
528: fDidIt = false;
529: break;
530: case tkLT:
531: val1 = val1 < val2;
532: break;
533: case tkLE:
534: val1 = val1 <= val2;
535: break;
536: case tkGT:
537: val1 = val1 > val2;
538: break;
539: case tkGE:
540: val1 = val1 >= val2;
541: break;
542: case tkEqual:
543: val1 = val1 == val2;
544: break;
545: case tkNotEqual:
546: val1 = val1 != val2;
547: break;
548: case tkLAND:
549: val1 = val1 && val2;
550: break;
551: case tkLOR:
552: val1 = val1 || val2;
553: break;
554: case tkLShift:
555: if (ty1->td.bt == btShort) {
556: /* we do this to crop it to 16 bits */
557: stuff.lng = val1;
558: val1 = stuff.shorts.shortLo << val2;
559: }
560: else {
561: val1 = val1 << val2;
562: ty = vtyCnLong;
563: } /* if */
564: break;
565: case tkRShift:
566: if (ty1->td.bt == btShort) {
567: /* we do this to crop it to 16 bits */
568: stuff.lng = val1;
569: val1 = stuff.shorts.shortLo >> val2;
570: }
571: else {
572: val1 = val1 >> val2;
573: ty = vtyCnLong;
574: } /* if */
575: break;
576: } /* switch */
577: if (fDidIt) {
578: PushVar(val1, ty);
579: return(psVar);
580: } /* if */
581:
582: if (tk != tkAssign)
583: UError("Unknown operator");
584:
585: cb1 = CbFTy(ty1);
586: if (cb1 <= CBLONG) {
587: PutVal(adr1, ty1, val2);
588: }
589: else {
590: cb2 = CbFTy(ty2);
591: if (cb1 >= cbAssMax)
592: Panic("Too many bytes (> %d) moved in assignment", cbAssMax);
593: /* we transfer cb1 bytes, just to be safe */
594: adrShort = adr2;
595: GetBlock(adrShort, spaceData, (ADRT)buf, cb1);
596: adrShort = adr1;
597: PutBlock(adrShort, spaceData, (ADRT)buf, cb1);
598: if (cb1 != cb2) {
599: printf("WARNING: X=Y: X is %d bytes and Y is %d bytes\n",
600: cb1, cb2);
601: printf(" Moving %d bytes\n", cb1);
602: } /* if */
603: } /* if */
604: PushVar(adr1, ty1); /* leave dest on stack, too */
605: return(psVar);
606: } /* PsFDoOp */
607:
608:
609: /* P S F O P E R A T O R */
610:
611: local PSE PsFOperator(tk, ps)
612: TKE tk;
613: PSE ps;
614: {
615: /* this routine implements the precedence rules */
616: int prec;
617: TKE tkStop, tkNew;
618: long adr;
619: TYR rgTy[cTyMax];
620:
621: prec = PrecFTk(tk);
622: if (prec == 0)
623: Panic("Bad token in PsFOperator - [%d]", tk);
624:
625: if (ps == psOp) {
626: /* this had better be a unary operator */
627: switch (tk) {
628: case tkSizeof:
629: case tkInside:
630: case tkBang:
631: case tkTilda:
632: case tkBOE:
633: case tkLP:
634: PushOp(tk);
635: break;
636: /* these next ones map to something else */
637: case tkAmper:
638: PushOp(tkRef);
639: break;
640: case tkStar:
641: PushOp(tkDeref);
642: break;
643: case tkMinus:
644: PushOp(tkUMinus);
645: break;
646: case tkPlus: /* ignore it */
647: break;
648: default:
649: UError("Two operators in a row??");
650: } /* switch */
651: return(psOp);
652: } /* if */
653:
654: tkStop = tkNil;
655: switch (tk) { /* set our stop token for [], (), and (x,y,z) */
656: case tkEOE:
657: tkStop = tkBOE;
658: break;
659: case tkRSB:
660: tkStop = tkLSB;
661: break;
662: case tkComma:
663: case tkRP:
664: tkStop = tkLP;
665: break;
666: } /* switch */
667:
668: /* first process all higher precedence operators */
669: while (prec <= PrecFTk(TOPOP)) {
670: if (TOPOP == tkStop) {
671: PopOp(); /* eat top op */
672: return(psVar); /* by definition, "(x+y)" is a var */
673: }
674: else if (PrecFTk(TOPOP) == precParen) {
675: break; /* we pretend it is higher precedence than the paren */
676: } /* if */
677: if (PsFDoOp() == psFail) {
678: switch (tk) {
679: case tkRSB:
680: UError("Missing '['");
681: case tkRP:
682: UError("Missing '('");
683: case tkComma:
684: UError("Bad procedure call");
685: default:
686: UError("Badly formed expression");
687: } /* switch */
688: } /* if */
689: } /* while */
690:
691: tkNew = tkNil;
692: switch (tk) {
693: case tkAssPlus:
694: tkNew = tkPlus;
695: break;
696: case tkAssMinus:
697: tkNew = tkMinus;
698: break;
699: case tkAssMult:
700: tkNew = tkMul;
701: break;
702: case tkAssDiv:
703: tkNew = tkDiv;
704: break;
705: case tkAssXOR:
706: tkNew = tkXOR;
707: break;
708: case tkAssBAND:
709: tkNew = tkBitAnd;
710: break;
711: case tkAssBOR:
712: tkNew = tkBitOr;
713: break;
714: case tkAssLeft:
715: tkNew = tkLShift;
716: break;
717: case tkAssRight:
718: tkNew = tkRShift;
719: break;
720: case tkAssMod:
721: tkNew = tkModulo;
722: break;
723: } /* switch */
724: if (tkNew != tkNil) {
725: /* this is an 'assign with function' op e.g. *= or += */
726: /* replicate the top of the variable stack */
727: if (!FPopVar(&adr, rgTy))
728: UError("Bad Syntax");
729: PushVar(adr, rgTy);
730: PushVar(adr, rgTy);
731: PushOp(tkAssign);
732: tk = tkNew;
733: } /* if */
734:
735: PushOp(tk);
736: if (tk == tkLSB)
737: PushOp(tkIndex); /* we push the tkLSB and then the tkIndex */
738: return(psOp);
739: } /* PsFOperator */
740:
741:
742: /* T K F O P E R A N D */
743:
744: export TKE TkFOperand()
745: {
746: int iln, ifd, ipd, cnt;
747: short valShort;
748: char sbFloat[30];
749: long val;
750: TKE tk;
751: ADRT adr, fp, ap;
752: TYR ty[cTyMax];
753: STUFFU stuff;
754:
755: /* look at the current token and figure out what the hell it is */
756: /* successful cases fall out bottom and return tkAdr */
757: switch (vtk) {
758: default:
759: return(tkNil); /* nothing of interest */
760: case tkDot:
761: PushVar(vdot, vtyDot);
762: break;
763: case tkColon: /* they want us to search ONLY global space */
764: tk = TkNext();
765: if (tk != tkStr)
766: UError("Misformed global name");
767: if ((adr = AdrFGlobal(vsbTok, ty)) == adrNil)
768: UError("Unknown global - %s", vsbTok);
769: PushVar(lengthen(adr), ty);
770: break;
771: case tkCharConstant:
772: CopyTy(ty, vtyCnChar);
773: val = vsbTok[0];
774: PushVar(val, ty);
775: break;
776: case tkStrConstant:
777: adr = AdrFStore(vsbTok, vcbTok+1);
778: CopyTy(ty, vtyCnChar); /* it is a constant */
779: FAdjTd(ty, tqPtr); /* this makes it a 'char *' */
780: PushVar(lengthen(adr), ty);
781: break;
782: case tkNumber:
783: if (vsbTok[0] == '0') {
784: if (vsbTok[1] == 'x')
785: sscanf((vsbTok+2), "%X", &val);
786: else sscanf(vsbTok, "%O", &val);
787: }
788: else {
789: tk = TkPeek();
790: if (tk == tkDot) {
791: /* looks like a float constant */
792: strcpy(sbFloat, vsbTok);
793: TkNext(); /* eat the dot */
794: strcat(sbFloat, ".");
795: /* we allow them to say "10." instead of "10.0" */
796: if (tkNumber == TkPeek()) {
797: TkNext(); /* actually get the number */
798: strcat(sbFloat, vsbTok); /* get fractional part */
799: } /* if */
800: stuff.fl = atof(sbFloat);
801: PushVar(stuff.lng, vtyCnFloat); /* sorta kludgey */
802: return(tkNumber);
803: }
804: else {
805: val = atol(vsbTok);
806: } /* if */
807: } /* if */
808:
809: TkPeek();
810: /* did they specify long? */
811: if ((vcbPeek == 1)
812: AND (vsbTokPeek[0] == 'L' OR vsbTokPeek[0] == 'l')) {
813: TkNext(); /* actually eat the L or l */
814: PushVar(val, vtyCnLong);
815: }
816: else {
817: valShort = val & 0x0000ffff;
818: PushVar(val, (val==valShort) ? vtyCnInt : vtyCnLong);
819: }
820: return(tkNumber);
821: /* NOTREACHED */
822: break;
823: case tkStr:
824: if ((TOPOP == tkDot) OR (TOPOP == tkPtr)) {
825: /* we don't do anything until we PROCESS the field.
826: * so we jam the name in a record.
827: */
828: ty[0] = *vtyZeros;
829: ty[1] = *vtyZeros;
830: #ifdef BSD41
831: ty[0].sbVar = SbSafe(vsbTok);
832: #else
833: strncpy(ty[0].sbVar, vsbTok, cbVarMax);
834: #endif
835: ty[0].td.fConstant = true;
836: ty[0].td.st = stStruct;
837: PushVar(0L, ty);
838: return(psVar);
839: } /* if */
840:
841: /* is it a register or Special variable? */
842: if (vsbTok[0] == '$') {
843: if (FAdrFSpecial(vsbTok, ty, &adr)) {
844: PushVar(lengthen(adr), ty);
845: break;
846: } /* if */
847: UError("Unknown special variable `%s'", vsbTok);
848: } /* if */
849:
850: /* is it a local? */
851: if ((vipd != ipdNil)
852: AND ((adr=AdrFLocal(vipd, -1, vsbTok, ty)) != adrNil)) {
853: PushVar(lengthen(adr), ty);
854: break;
855: } /* if */
856:
857: /* is it a global? */
858: if ((adr = AdrFGlobal(vsbTok, ty)) != adrNil) {
859: PushVar(lengthen(adr), ty);
860: break;
861: } /* if */
862:
863: /* is it a procedure name? */
864: if ((ipd = IpdFName(vsbTok)) != ipdNil) {
865: /* it is a procedure name! is there anymore to the name? */
866: tk = TkPeek();
867: if (tk == tkDot) {
868: /* so far we know `procname.' */
869: TkNext(); /* eat dot */
870: /* we want full name of a local */
871: FpApFIpd(&fp, &ap, ipd, -1);
872: if (fp == 0)
873: UError("procedure %s not active",vrgPd[ipd].sbProc);
874: tk = TkNext();
875: cnt = -1; /* default - take first instance */
876: if (tk == tkNumber) {
877: /* we have `proc.3' (or something like that).
878: * they want a SPECIFIC instance of this proc
879: * at backtrace location #.
880: * This is useful for recursive procedures...
881: */
882: cnt = atoi(vsbTok);
883: if (TkNext() != tkDot)
884: UError("Need a `.' after the number");
885: ;
886: tk = TkNext();
887: } /* if */
888: if (tk != tkStr) {
889: /* procname.???? */
890: UError("Syntax error - bad local name '%s'",vsbTok);
891: } /* if */
892: if ((adr = AdrFLocal(ipd,cnt,vsbTok,ty))
893: != adrNil) {
894: PushVar(lengthen(adr), ty);
895: return(tkAdr);
896: }
897: else {
898: UError("No such local - %s.%s",
899: vrgPd[ipd].sbProc, vsbTok);
900: } /* if */
901: }
902: else if (tk == tkLP) {
903: /* we have `procname(' - must be a procedure call */
904: TkNext(); /* eat ( */
905: val = DoProc(ipd, ty, adrNil);
906: PushVar(val, ty);
907: break;
908: }
909: else if (tk == tkHash) {
910: TkNext(); /* eat the # */
911: tk = TkNext();
912: if (tk != tkNumber)
913: UError("'#' should be followed by a decimal line number.");
914: iln = atoi(vsbTok);
915: ifd = IfdFIpd(ipd);
916: adr = AdrFIfdLn(ifd, iln); /* get adr of this line */
917: PushVar(lengthen(adr), vtyCnInt);
918: }
919: else {
920: /* proc name followed by ???, give proc adr and type */
921: TyFLocal(ty, vrgPd[ipd].sbProc, vrgPd[ipd].isym);
922: PushVar(lengthen(vrgPd[ipd].adrStart), ty);
923: } /* if */
924: }
925: else if ((adr=AdrFLabel(vsbTok)) != adrNil) {
926: /* it is a label */
927: TkPeek();
928: if (vtkPeek == tkLP) {
929: /* we have `label(' - must be a procedure call */
930: TkNext(); /* eat ( */
931: val = DoProc(ipdNil, ty, adr);
932: PushVar(val, ty);
933: }
934: else {
935: PushVar(lengthen(adr), vtyCnInt);
936: }
937: }
938: else {
939: /* don't what it is, it is NOT something we can handle! */
940: return(tkNil);
941: } /* if */
942: break;
943: } /* switch */
944: return(tkAdr);
945: } /* TkFOperand */
946:
947:
948: /* T K F E X P R */
949:
950: export TKE TkFExpr(pret, ty)
951: long *pret;
952: pTYR ty;
953: {
954: int cbTemp;
955: PSE ps;
956: TKE tk, tkRet, tkTemp;
957: char *sbCmdTemp, sbTokTemp[50];
958:
959: if (vtk == tkNil) {
960: *pret = 0;
961: return(tkNil);
962: } /* if */
963:
964: /* save the token state in case we think it is garbage */
965: cbTemp = vcbTok;
966: sbCmdTemp = vsbCmd;
967: tk = tkTemp = vtk;
968: ps = psOp;
969: strcpy(sbTokTemp, vsbTok);
970:
971: PushOp(tkBOE); /* push a {ning-of-expression onto the stack */
972:
973: /* we do a little dance here to see if we have a pure number */
974: tkRet = TkFOperand();
975: if (tkRet != tkNil) {
976: ps = psVar;
977: tk = TkNext();
978: if ((tkRet == tkNumber) AND (PrecFTk(tk)==0)) {
979: tk = PopOp(); /* eat the BOE */
980: FPopVar(pret, ty);
981: return(tkNumber);
982: } /* if */
983: }
984: else if (PrecFTk(tk) == 0) {
985: /* it is neither an operator nor an operand */
986: goto bombout;
987: } /* if */
988:
989: if (tk == tkComma) {
990: PushOp(tkLP); /* makes procedure call code easier */
991: tk = TkNext();
992: } /* if */
993:
994: while (tk != tkNil) {
995: if ( (PrecFTk(tk) != 0)
996: AND ((tk != tkDot) OR (ps == psVar)) ) {
997: /* it is an operator */
998: ps = PsFOperator(tk, ps);
999: if (ps == psFail)
1000: goto bombout;
1001: if (tk == tkComma)
1002: break;
1003: }
1004: else {
1005: /* it's not an operator, is it an OPERAND?? */
1006: tk = TkFOperand();
1007: if (tk == tkNil) {
1008: ps = psFail;
1009: break; /* not operand - fall out of loop and see what happens */
1010: } /* if */
1011: ps = psVar; /* yup, it was an operand - and it's on the stack */
1012: } /* if */
1013: tk = TkNext();
1014: } /* while */
1015:
1016: /* one way or the other, someone thinks we might be done, try it and see */
1017: if (psFail != PsFOperator(tkEOE, ps)) {
1018: FPopVar(pret, ty); /* put final stuff in return variables */
1019: return(tkAdr);
1020: } /* if */
1021:
1022: bombout:
1023: /* something ain't right - reset the universe */
1024: vcbTok = cbTemp;
1025: vsbCmd = sbCmdTemp;
1026: vtk = tkTemp;
1027: strcpy(vsbTok, sbTokTemp);
1028: vivarMac = 0; /* stack pointer cleanup */
1029: viopMac = 0;
1030: return(tkNil);
1031: } /* TkFExpr */
1032:
1033:
1034: /* G E T E X P R */
1035:
1036: export long GetExpr(pty, tk)
1037: pTYR *pty;
1038: TKE tk;
1039: {
1040: long adrLong, i;
1041: static TYR ty[cTyMax];
1042: /* ty is used for callers to GetExp who don't want to be bothered
1043: * with allocating an ty.
1044: * NOTE(!): if they want this info for more than a statement or two,
1045: * they MUST copy it someplace else!!!
1046: */
1047:
1048: if (tk == tkNil)
1049: TkNext();
1050: if (TkFExpr(&adrLong, ty) != tkNil) {
1051: i = ValFAdr(adrLong, ty);
1052: *pty = ty;
1053: }
1054: else {
1055: *pty = tyNil;
1056: } /* if */
1057: return(i);
1058: } /* GetExpr */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.