1786Speter /* Copyright (c) 1979 Regents of the University of California */ 2786Speter 3*7922Smckusick static char sccsid[] = "@(#)yyid.c 1.4 08/26/82"; 4786Speter 5786Speter #include "whoami.h" 6786Speter #include "0.h" 7786Speter #include "yy.h" 8786Speter 9786Speter #ifdef PI 10786Speter extern int *yypv; 11786Speter /* 12786Speter * Determine whether the identifier whose name 13786Speter * is "cp" can possibly be a kind, which is a 14786Speter * namelist class. We look through the symbol 15786Speter * table for the first instance of cp as a non-field, 16786Speter * and at all instances of cp as a field. 17786Speter * If any of these are ok, we return true, else false. 18786Speter * It would be much better to handle with's correctly, 19786Speter * even to just know whether we are in a with at all. 20786Speter * 21786Speter * Note that we don't disallow constants on the lhs of assignment. 22786Speter */ 23786Speter identis(cp, kind) 24786Speter register char *cp; 25786Speter int kind; 26786Speter { 27786Speter register struct nl *p; 28786Speter int i; 29786Speter 30786Speter /* 31786Speter * Cp is NIL when error recovery inserts it. 32786Speter */ 33786Speter if (cp == NIL) 34786Speter return (1); 35786Speter 36786Speter /* 37786Speter * Record kind we want for possible later use by yyrecover 38786Speter */ 39786Speter yyidwant = kind; 40786Speter yyidhave = NIL; 41786Speter i = ( (int) cp ) & 077; 42786Speter for (p = disptab[i]; p != NIL; p = p->nl_next) 43786Speter if (p->symbol == cp) { 44786Speter if (yyidok(p, kind)) 45786Speter goto gotit; 46786Speter if (p->class != FIELD && p->class != BADUSE) 47786Speter break; 48786Speter } 49786Speter if (p != NIL) 50786Speter for (p = p->nl_next; p != NIL; p = p->nl_next) 51786Speter if (p->symbol == cp && p->class == FIELD && yyidok(p, kind)) 52786Speter goto gotit; 53786Speter return (0); 54786Speter gotit: 55786Speter if (p->class == BADUSE && !Recovery) { 56786Speter yybadref(p, OY.Yyeline); 57786Speter yypv[0] = NIL; 58786Speter } 59786Speter return (1); 60786Speter } 61786Speter 62786Speter /* 63786Speter * A bad reference to the identifier cp on line 64786Speter * line and use implying the addition of kindmask 65786Speter * to the mask of kind information. 66786Speter */ 67786Speter yybaduse(cp, line, kindmask) 68786Speter register char *cp; 69786Speter int line, kindmask; 70786Speter { 71786Speter register struct nl *p, *oldp; 72786Speter int i; 73786Speter 74786Speter i = ( (int) cp ) & 077; 75786Speter for (p = disptab[i]; p != NIL; p = p->nl_next) 76786Speter if (p->symbol == cp) 77786Speter break; 78786Speter oldp = p; 79786Speter if (p == NIL || p->class != BADUSE) 80786Speter p = enter(defnl(cp, BADUSE, 0, 0)); 813085Smckusic p->value[NL_KINDS] |= kindmask; 82786Speter yybadref(p, line); 83786Speter return (oldp); 84786Speter } 85786Speter 86786Speter /* 87786Speter * ud is initialized so that esavestr will allocate 88786Speter * sizeof ( struct udinfo ) bytes for the 'real' struct udinfo 89786Speter */ 90786Speter struct udinfo ud = { ~0 , ~0 , 0}; 91786Speter /* 92786Speter * Record a reference to an undefined identifier, 93786Speter * or one which is improperly used. 94786Speter */ 95786Speter yybadref(p, line) 96786Speter register struct nl *p; 97786Speter int line; 98786Speter { 99786Speter register struct udinfo *udp; 100786Speter 101786Speter if (p->chain != NIL && p->chain->ud_line == line) 102786Speter return; 103786Speter udp = esavestr(&ud); 104786Speter udp->ud_line = line; 105786Speter udp->ud_next = p->chain; 106786Speter p->chain = udp; 107786Speter } 108786Speter 1091201Speter #define varkinds ((1<<CONST)|(1<<VAR)|(1<<REF)|(1<<ARRAY)|(1<<PTR) \ 1101201Speter |(1<<RECORD)|(1<<FIELD)|(1<<FUNC)|(1<<FVAR) \ 1111201Speter |(1<<FFUNC)|(1<<PROC)|(1<<FPROC)) 112786Speter /* 113786Speter * Is the symbol in the p entry of the namelist 114786Speter * even possibly a kind kind? If not, update 115786Speter * what we have based on this encounter. 116786Speter */ 117786Speter yyidok(p, kind) 118786Speter register struct nl *p; 119786Speter int kind; 120786Speter { 121786Speter 122786Speter if (p->class == BADUSE) { 123786Speter if (kind == VAR) 124786Speter return (p->value[0] & varkinds); 125786Speter return (p->value[0] & (1 << kind)); 126786Speter } 127786Speter if (yyidok1(p, kind)) 128786Speter return (1); 129786Speter if (yyidhave != NIL) 130786Speter yyidhave = IMPROPER; 131786Speter else 132786Speter yyidhave = p->class; 133786Speter return (0); 134786Speter } 135786Speter 136786Speter yyidok1(p, kind) 137786Speter register struct nl *p; 138786Speter int kind; 139786Speter { 140786Speter int i; 141786Speter 142786Speter switch (kind) { 143786Speter case FUNC: 1441201Speter return ( p -> class == FUNC 1451201Speter || p -> class == FVAR 1461201Speter || p -> class == FFUNC ); 1471201Speter case PROC: 1481201Speter return ( p -> class == PROC || p -> class == FPROC ); 149786Speter case CONST: 150786Speter case TYPE: 151786Speter case FIELD: 152786Speter return (p->class == kind); 153786Speter case VAR: 154786Speter return (p->class == CONST || yyisvar(p, NIL)); 155786Speter case ARRAY: 156786Speter case RECORD: 157786Speter return (yyisvar(p, kind)); 158786Speter case PTRFILE: 159786Speter return (yyisvar(p, PTR) || yyisvar(p, FILET)); 160786Speter } 161786Speter } 162786Speter 163*7922Smckusick yyisvar(p, varclass) 164786Speter register struct nl *p; 165*7922Smckusick int varclass; 166786Speter { 167786Speter 168786Speter switch (p->class) { 169786Speter case FIELD: 170786Speter case VAR: 171786Speter case REF: 172786Speter case FVAR: 173786Speter /* 174786Speter * We would prefer to return 175786Speter * parameterless functions only. 176786Speter */ 177786Speter case FUNC: 1781201Speter case FFUNC: 179*7922Smckusick return (varclass == NIL || (p->type != NIL && p->type->class == varclass)); 1801201Speter case PROC: 1811201Speter case FPROC: 182*7922Smckusick return ( varclass == NIL ); 183786Speter } 184786Speter return (0); 185786Speter } 186786Speter #endif 187786Speter #ifdef PXP 188786Speter #ifndef DEBUG 189786Speter identis() 190786Speter { 191786Speter 192786Speter return (1); 193786Speter } 194786Speter #endif 195786Speter #ifdef DEBUG 196786Speter extern char *classes[]; 197786Speter 198786Speter char kindchars[] "UCTVAQRDPF"; 199786Speter /* 200786Speter * Fake routine "identis" for pxp when testing error recovery. 201786Speter * Looks at letters in variable names to answer questions 202786Speter * about attributes. Mapping is 203786Speter * C const_id 204786Speter * T type_id 205786Speter * V var_id also if any of AQRDF 206786Speter * A array_id 207786Speter * Q ptr_id 208786Speter * R record_id 209786Speter * D field_id D for "dot" 210786Speter * P proc_id 211786Speter * F func_id 212786Speter */ 213786Speter identis(cp, kind) 214786Speter register char *cp; 215786Speter int kind; 216786Speter { 217786Speter register char *dp; 218786Speter char kindch; 219786Speter 220786Speter /* 221786Speter * Don't do anything unless -T 222786Speter */ 223786Speter if (!typetest) 224786Speter return (1); 225786Speter 226786Speter /* 227786Speter * Inserted symbols are always correct 228786Speter */ 229786Speter if (cp == NIL) 230786Speter return (1); 231786Speter /* 232786Speter * Set up the names for error messages 233786Speter */ 234786Speter yyidwant = classes[kind]; 235786Speter for (dp = kindchars; *dp; dp++) 236786Speter if (any(cp, *dp)) { 237786Speter yyidhave = classes[dp - kindchars]; 238786Speter break; 239786Speter } 240786Speter 241786Speter /* 242786Speter * U in the name means undefined 243786Speter */ 244786Speter if (any(cp, 'U')) 245786Speter return (0); 246786Speter 247786Speter kindch = kindchars[kind]; 248786Speter if (kindch == 'V') 249786Speter for (dp = "AQRDF"; *dp; dp++) 250786Speter if (any(cp, *dp)) 251786Speter return (1); 252786Speter return (any(cp, kindch)); 253786Speter } 254786Speter #endif 255786Speter #endif 256