1*786Speter /* Copyright (c) 1979 Regents of the University of California */ 2*786Speter 3*786Speter static char sccsid[] = "@(#)yyid.c 1.1 08/27/80"; 4*786Speter 5*786Speter #include "whoami.h" 6*786Speter #include "0.h" 7*786Speter #include "yy.h" 8*786Speter 9*786Speter #ifdef PI 10*786Speter extern int *yypv; 11*786Speter /* 12*786Speter * Determine whether the identifier whose name 13*786Speter * is "cp" can possibly be a kind, which is a 14*786Speter * namelist class. We look through the symbol 15*786Speter * table for the first instance of cp as a non-field, 16*786Speter * and at all instances of cp as a field. 17*786Speter * If any of these are ok, we return true, else false. 18*786Speter * It would be much better to handle with's correctly, 19*786Speter * even to just know whether we are in a with at all. 20*786Speter * 21*786Speter * Note that we don't disallow constants on the lhs of assignment. 22*786Speter */ 23*786Speter identis(cp, kind) 24*786Speter register char *cp; 25*786Speter int kind; 26*786Speter { 27*786Speter register struct nl *p; 28*786Speter int i; 29*786Speter 30*786Speter /* 31*786Speter * Cp is NIL when error recovery inserts it. 32*786Speter */ 33*786Speter if (cp == NIL) 34*786Speter return (1); 35*786Speter 36*786Speter /* 37*786Speter * Record kind we want for possible later use by yyrecover 38*786Speter */ 39*786Speter yyidwant = kind; 40*786Speter yyidhave = NIL; 41*786Speter i = ( (int) cp ) & 077; 42*786Speter for (p = disptab[i]; p != NIL; p = p->nl_next) 43*786Speter if (p->symbol == cp) { 44*786Speter if (yyidok(p, kind)) 45*786Speter goto gotit; 46*786Speter if (p->class != FIELD && p->class != BADUSE) 47*786Speter break; 48*786Speter } 49*786Speter if (p != NIL) 50*786Speter for (p = p->nl_next; p != NIL; p = p->nl_next) 51*786Speter if (p->symbol == cp && p->class == FIELD && yyidok(p, kind)) 52*786Speter goto gotit; 53*786Speter return (0); 54*786Speter gotit: 55*786Speter if (p->class == BADUSE && !Recovery) { 56*786Speter yybadref(p, OY.Yyeline); 57*786Speter yypv[0] = NIL; 58*786Speter } 59*786Speter return (1); 60*786Speter } 61*786Speter 62*786Speter /* 63*786Speter * A bad reference to the identifier cp on line 64*786Speter * line and use implying the addition of kindmask 65*786Speter * to the mask of kind information. 66*786Speter */ 67*786Speter yybaduse(cp, line, kindmask) 68*786Speter register char *cp; 69*786Speter int line, kindmask; 70*786Speter { 71*786Speter register struct nl *p, *oldp; 72*786Speter int i; 73*786Speter 74*786Speter i = ( (int) cp ) & 077; 75*786Speter for (p = disptab[i]; p != NIL; p = p->nl_next) 76*786Speter if (p->symbol == cp) 77*786Speter break; 78*786Speter oldp = p; 79*786Speter if (p == NIL || p->class != BADUSE) 80*786Speter p = enter(defnl(cp, BADUSE, 0, 0)); 81*786Speter p->value[NL_KINDS] =| kindmask; 82*786Speter yybadref(p, line); 83*786Speter return (oldp); 84*786Speter } 85*786Speter 86*786Speter /* 87*786Speter * ud is initialized so that esavestr will allocate 88*786Speter * sizeof ( struct udinfo ) bytes for the 'real' struct udinfo 89*786Speter */ 90*786Speter struct udinfo ud = { ~0 , ~0 , 0}; 91*786Speter /* 92*786Speter * Record a reference to an undefined identifier, 93*786Speter * or one which is improperly used. 94*786Speter */ 95*786Speter yybadref(p, line) 96*786Speter register struct nl *p; 97*786Speter int line; 98*786Speter { 99*786Speter register struct udinfo *udp; 100*786Speter 101*786Speter if (p->chain != NIL && p->chain->ud_line == line) 102*786Speter return; 103*786Speter udp = esavestr(&ud); 104*786Speter udp->ud_line = line; 105*786Speter udp->ud_next = p->chain; 106*786Speter p->chain = udp; 107*786Speter } 108*786Speter 109*786Speter #define varkinds ((1<<CONST)|(1<<VAR)|(1<<REF)|(1<<ARRAY)|(1<<PTR)|(1<<RECORD)|(1<<FIELD)|(1<<FUNC)|(1<<FVAR)) 110*786Speter /* 111*786Speter * Is the symbol in the p entry of the namelist 112*786Speter * even possibly a kind kind? If not, update 113*786Speter * what we have based on this encounter. 114*786Speter */ 115*786Speter yyidok(p, kind) 116*786Speter register struct nl *p; 117*786Speter int kind; 118*786Speter { 119*786Speter 120*786Speter if (p->class == BADUSE) { 121*786Speter if (kind == VAR) 122*786Speter return (p->value[0] & varkinds); 123*786Speter return (p->value[0] & (1 << kind)); 124*786Speter } 125*786Speter if (yyidok1(p, kind)) 126*786Speter return (1); 127*786Speter if (yyidhave != NIL) 128*786Speter yyidhave = IMPROPER; 129*786Speter else 130*786Speter yyidhave = p->class; 131*786Speter return (0); 132*786Speter } 133*786Speter 134*786Speter yyidok1(p, kind) 135*786Speter register struct nl *p; 136*786Speter int kind; 137*786Speter { 138*786Speter int i; 139*786Speter 140*786Speter switch (kind) { 141*786Speter case FUNC: 142*786Speter if (p->class == FVAR) 143*786Speter return(1); 144*786Speter case CONST: 145*786Speter case TYPE: 146*786Speter case PROC: 147*786Speter case FIELD: 148*786Speter return (p->class == kind); 149*786Speter case VAR: 150*786Speter return (p->class == CONST || yyisvar(p, NIL)); 151*786Speter case ARRAY: 152*786Speter case RECORD: 153*786Speter return (yyisvar(p, kind)); 154*786Speter case PTRFILE: 155*786Speter return (yyisvar(p, PTR) || yyisvar(p, FILET)); 156*786Speter } 157*786Speter } 158*786Speter 159*786Speter yyisvar(p, class) 160*786Speter register struct nl *p; 161*786Speter int class; 162*786Speter { 163*786Speter 164*786Speter switch (p->class) { 165*786Speter case FIELD: 166*786Speter case VAR: 167*786Speter case REF: 168*786Speter case FVAR: 169*786Speter /* 170*786Speter * We would prefer to return 171*786Speter * parameterless functions only. 172*786Speter */ 173*786Speter case FUNC: 174*786Speter return (class == NIL || (p->type != NIL && p->type->class == class)); 175*786Speter } 176*786Speter return (0); 177*786Speter } 178*786Speter #endif 179*786Speter #ifdef PXP 180*786Speter #ifndef DEBUG 181*786Speter identis() 182*786Speter { 183*786Speter 184*786Speter return (1); 185*786Speter } 186*786Speter #endif 187*786Speter #ifdef DEBUG 188*786Speter extern char *classes[]; 189*786Speter 190*786Speter char kindchars[] "UCTVAQRDPF"; 191*786Speter /* 192*786Speter * Fake routine "identis" for pxp when testing error recovery. 193*786Speter * Looks at letters in variable names to answer questions 194*786Speter * about attributes. Mapping is 195*786Speter * C const_id 196*786Speter * T type_id 197*786Speter * V var_id also if any of AQRDF 198*786Speter * A array_id 199*786Speter * Q ptr_id 200*786Speter * R record_id 201*786Speter * D field_id D for "dot" 202*786Speter * P proc_id 203*786Speter * F func_id 204*786Speter */ 205*786Speter identis(cp, kind) 206*786Speter register char *cp; 207*786Speter int kind; 208*786Speter { 209*786Speter register char *dp; 210*786Speter char kindch; 211*786Speter 212*786Speter /* 213*786Speter * Don't do anything unless -T 214*786Speter */ 215*786Speter if (!typetest) 216*786Speter return (1); 217*786Speter 218*786Speter /* 219*786Speter * Inserted symbols are always correct 220*786Speter */ 221*786Speter if (cp == NIL) 222*786Speter return (1); 223*786Speter /* 224*786Speter * Set up the names for error messages 225*786Speter */ 226*786Speter yyidwant = classes[kind]; 227*786Speter for (dp = kindchars; *dp; dp++) 228*786Speter if (any(cp, *dp)) { 229*786Speter yyidhave = classes[dp - kindchars]; 230*786Speter break; 231*786Speter } 232*786Speter 233*786Speter /* 234*786Speter * U in the name means undefined 235*786Speter */ 236*786Speter if (any(cp, 'U')) 237*786Speter return (0); 238*786Speter 239*786Speter kindch = kindchars[kind]; 240*786Speter if (kindch == 'V') 241*786Speter for (dp = "AQRDF"; *dp; dp++) 242*786Speter if (any(cp, *dp)) 243*786Speter return (1); 244*786Speter return (any(cp, kindch)); 245*786Speter } 246*786Speter #endif 247*786Speter #endif 248