#include "cdb2.h" /* Copyright (c) 1982 by J. David Kirkland, Jr. */ union valun { int intval; int *ptrval; }; ishex(c) char c; { return isdigit(c) || ('a'<=c&&c<='f') || ('A'<=c&&c<='F'); } struct stentry *findsym (symbol) char *symbol; { /* Look up a symbol in the symbol table. The null-terminated string * "symbol" is searched for in the table. If it is present, findsym * returns a pointer to the correct symbol table entry; else, a * diagnostic is printed and ERROR is returned. * Normally, first the local symbols for the current function are * searched, followed by the globals; but if the symbol is preceeded * by a backslash, only the global symbols are searched. */ char s[8], t[9], globflag; struct stentry *p; globflag = '\\' == *symbol; movmem(&symbol[globflag],t,8); t[8] = 0; str07cpy(s,t); if ((!globflag) && NIL!=(p=curfnt->fntst)) for (; p->stname[7]!=0xff; p--) { if (str7eq(s,p->stname)) return p; } for (p=globalp; p>localp; p--) { if (str7eq(s,p->stname)) return p; } printf("no symbol %s\n",symbol); return ERROR; } char get_token(sp,t,valp) char **sp, *t; int *valp; { /* get_token isolates the next token on the input line. * sp is a pointer to a pointer to an array of characters forming the * line to be scanned. *sp is updated to point to the next unprocessed * character once get_token has gotten its token. * The token scanned is copied into t; valp is set to the integer value * of the token iff the token is an integer. * get_token returns the "class" of the token, which can be * (i) INTEGER (a decimal or hex integer), (ii) ID (a sequence of * _, alpha, or digits that doesn't start with a digit), (iii) POINT * (the sequence "->"), or (iv) any special character. * */ char class, *s, *tt; tt = t; s = *sp; while(isspace(*s)) ++s; if (isalpha(*s) || *s=='_' || *s=='\\') { /* identifier */ class = ID; do if (t-tt<=8) *t++ = *s; while (isdigit(*++s) || isalpha(*s) || *s == '_'); } else if (isdigit(*s) || ((*s=='-' || *s=='+') && isdigit(*(s+1)) ) ) { class = INTEGER; do if ('x' == tolower(*s)) { class = HEX; t = tt; } else if (t-tt<=8) *t++ = *s; else if (class!=BAD) { printf("integer too long\n"); class = BAD; } while (ishex(*++s) || *s == 'x'); *t = 0; if (class!=BAD) { sscanf(tt,(class==INTEGER) ? "%d" : "%x",valp); class = INTEGER; } } else { if (class = *s) s++; if (class == '-' && *s == '>') { class = POINT; ++s; } *t++ = class; } *t = 0; /* * if (debug) printf("get_token returning class = %c, token = <%s>, value = %d\n", class, tt, *valp); * */ *sp = s; return class; } invalid(t) char t; { if (t>=0x20 && t<0x80) printf("'%c'",t); else printf("'\\%o'",t); } sizeelt(type) struct sttype *type; { /* compute the size, in bytes, of a single element of * the object described by "type". */ if (type->tlind!=0 || type->tptfnf) return 2; else if (type->ttype==STRUCT) if (type->tsptr) return type->tsize.p->stsize; else return type->tsize.u; else if (type->ttype==CHAR) return 1; else return 2; } sizeary(s) struct stentry *s; { /* Compute the size, in bytes, of the array with the symbol table entry * pointed to by s. * Method: find the variable that follows this variable, and compute * the difference in adrs fields. Special cases occur when the * array in question is (i) the last element in a structure, * (ii) the last local variable in a function, or (iii) the last * global variable. (This is the order in which we treat them below.) */ struct stentry *next; unsigned naddr, *up; next = s-1; if (STELT(*s)) if (STELT(*next)) naddr = next->stadrs; else { for (next = s; WHAT(*++next)!=2; ) ; naddr = next->stsize; } else { while (next->stname[7]!=0xff && (WHAT(*next)!=0 || STELT(*next)) ) next--; if (next->stname[7] == 0xff) if (LOCAL(*s)) { up = &(next->stname[5]); naddr = *up; #ifdef DEBUG if (debug) printf(" local sfsize = %04x\n", naddr); #endif } else naddr = endext() - externs(); else naddr = next->stadrs; } return naddr - s->stadrs; } gettt(s,t) struct stentry *s; struct sttype *t; { /* Copy information from a symbol table entry into a sttype structure. * Most of this is done solely to make it easier to change the data * so copied when exp or primary needs to do so. */ t->tptfnf = PTFNF(*s); t->ttype = TYPE(*s); t->tsptr = SPTR(*s); t->tlind = LIND(*s); t->tforml = FORML(*s); t->tadrs = s->stadrs; t->tsize.u = s->stsize; t->tdimsz = s->stdimsz; if (t->tdimsz && !t->tforml) t->tmul = sizeary(s)/sizeelt(t); else t->tmul = 1; } exp (s, term, type) char **s, term; struct sttype *type; { /* exp() processes expressions. * expression := *expression * primary * * s is the command line pointer-to-pointer; term is the character * that marks the end of the expression; it is usually either * '\0', ']', or ')'. * exp returns the value computed for the expression (i.e., the * address defined by the symbolic reference or the actual value * of the integer entered), and sets *type as appropriate. */ char token[10], class, *ss; union valun aval; #ifdef DEBUG if (debug) printf("exp( %s, '%c')\n",*s,term); #endif ss = *s; class = get_token(s, token, aval); if (class=='*') { aval.intval = exp(s,term,type); aval.intval = *aval.ptrval; if (type->tlind) type->tlind--; else if (type->tdimsz!=0xff00) { if (type->ttype==CHAR) aval.intval &= 0xff; type->ttype = INT; } #ifdef DEBUG if (debug) printf("exp [*] returning %04x = %d\n",aval.intval,aval.intval); #endif return aval.intval; } else if (class==term) { printf("empty expression at "); invalid(term); putchar('\n'); type->ttype = ERROR; return; } else if (class==BAD) { type->ttype = ERROR; return; } *s = ss; return primary(s,term,type); } /* unsigned baseaddr(stab) struct stentry *stab; { unsigned result; if (LOCAL(*stab)) { if (cursn==0) { result = &(cursave->caller_return); result -= curfnt->fntfsize + 2; } else result = cursave->bc; if (FORML(*stab)) result += 4 + curfnt->fntfsize; } else { #ifdef DEBUG if (debug) printf("globbase = %04x\n",globbase); #endif result = globbase; } return result; } */ unsigned do_stentry(stab,type) struct stentry *stab; struct sttype *type; { unsigned base; gettt(stab,type); if (STELT(*stab)) base = 0; else if (LOCAL(*stab)) { if (cursn==0) { base = &(cursave->caller_return); base -= curfnt->fntfsize + 2; } else base = cursave->bc; if (FORML(*stab)) base += 4 + curfnt->fntfsize; } else base = globbase; #ifdef DEBUG if (debug) printf("adrs = %04x, base = %04x\n",type->tadrs,base); #endif return base + type->tadrs; } do_id (ident, type) char *ident; struct sttype *type; { /* do_id processes an identifier by looking up the symbol given * in "ident" in the symbol table and computing the absolute * memory address of that symbol. This address is returned, and * type is set. */ struct stentry *stab; if (ERROR==(stab = findsym(ident))) type->ttype = BAD; else return do_stentry(stab,type); } do_index(s, aval, type) char **s; union valun *aval; struct sttype *type; { /* do_index processes a single subscript to an already-processed * primary. aval and type contain the address and other information * derived from the primary; do_index updates all this information * to take the indexing into account. * s is pointer-to-pointer to input line. */ union valun bval; struct sttype type2; char token[10]; int i, scale; if (type->tforml) aval->intval = *aval->ptrval; bval.intval = exp(s,']', type2 ); if (type2.ttype==BAD) { type->ttype = BAD; return; } get_token(s, token, aval); i = (type2.ttype==VALUE) ? bval.intval : *bval.ptrval; if (type2.tlind==0 && type2.ttype==CHAR) i &= 0xff; scale = sizeelt(type); #ifdef DEBUG if (debug) printf(" scale = %d, i = %d, dimsz = %04x\n",scale,i,type->tdimsz); #endif if (type->tdimsz!=0xff00) { scale *= type->tdimsz; type->tmul = type->tdimsz; type->tdimsz = 0xff00; #ifdef DEBUG if (debug) printf(" new scale = %d, mul = %04x\n",scale,type->tmul); #endif } else { type->tmul = 1; type->tdimsz = 0; } aval->intval += scale * i; } do_struct(class, s, aval, type) char class; char **s; union valun *aval; struct sttype *type; { /* do_struct processes a structure reference to an already-processed * primary. aval and type contain the address and other information * derived from the primary; do_struct updates all this information * to take the structure reference into account. * class contains either '.' or POINT and tells do_struct whether * aval contains the address of the structure or the address of a * pointer to the structure. * s is pointer-to-pointer to input line. */ char token[10]; union valun bval; struct stentry *stab; if (class==POINT) aval->intval = *aval->ptrval; get_token(s, token, bval); if (ERROR==(stab = findsym(token))) type->ttype = BAD; else if (!STELT(*stab)) { printf("%s is not a structure element\n", token); type->ttype = BAD; } else { aval->intval += stab->stadrs; gettt(stab,type); } } primary (s, term, type) char **s, term; struct sttype *type; { /* primary() processes primaries. * primary := (expression) * primary[expression] * primary->indentifier * primary.indentifier * * s is the command line pointer-to-pointer; term is the character * that marks the end of the expression; it is usually either * '\0', ']', or ')'. * primary returns the value computed for the expression (i.e., the * address defined by the symbolic reference or the actual value * of the integer entered), and sets *type as appropriate. */ char token[10], class, *ss; union valun aval, bval; #ifdef DEBUG if (debug) printf("primary( %s, '%c' )\n", *s, term); #endif class = get_token(s, token, aval); if (class=='(') { aval.intval = exp(s,')',type); get_token(s, token, aval); } else if (class==ID) aval.intval = do_id(token,type); else if (class==INTEGER) { type->ttype = VALUE; type->tdimsz = 0; type->tmul = 1; type->tptfnf = 0; type->tlind = 0; } else { if (class!=BAD) { printf("invalid primary at token %s", token); printf(", identifier or integer expected\n"); } type->ttype = BAD; } ss = *s; while (type->ttype!=BAD && term != (class=get_token(s, token, bval))) { if (class=='[') do_index(s, aval, type); else if (class==POINT || class=='.') do_struct(class, s, aval, type); else if (class==INTEGER || class=='\'' || class==ID) break; else { if (class!=BAD) { printf("invalid primary at token "); invalid(class); putchar('\n'); } type->ttype = BAD; } ss = *s; } *s = ss; #ifdef DEBUG if (debug) printf("primary returning type = %d, value = %04x = %d\n", type->ttype, aval.intval, aval.intval); if (debug) printf(" lind = %d, size = %d, mul = %04x, dimsz = %04x\n", type->tlind, type->tsize, type->tmul, type->tdimsz); #endif return aval.intval; }