1*48116Sbostic /*- 2*48116Sbostic * Copyright (c) 1980 The Regents of the University of California. 3*48116Sbostic * All rights reserved. 4*48116Sbostic * 5*48116Sbostic * %sccs.include.redist.c% 622206Sdist */ 7786Speter 814748Sthien #ifndef lint 9*48116Sbostic static char sccsid[] = "@(#)yyid.c 5.3 (Berkeley) 04/16/91"; 10*48116Sbostic #endif /* not lint */ 11786Speter 12786Speter #include "whoami.h" 1344619Sbostic #include <0.h> 1414748Sthien #include "tree_ty.h" /* must be included for yy.h */ 15786Speter #include "yy.h" 16786Speter 17786Speter #ifdef PI 1814748Sthien extern union semstack *yypv; 19786Speter /* 20786Speter * Determine whether the identifier whose name 21786Speter * is "cp" can possibly be a kind, which is a 22786Speter * namelist class. We look through the symbol 23786Speter * table for the first instance of cp as a non-field, 24786Speter * and at all instances of cp as a field. 25786Speter * If any of these are ok, we return true, else false. 26786Speter * It would be much better to handle with's correctly, 27786Speter * even to just know whether we are in a with at all. 28786Speter * 29786Speter * Note that we don't disallow constants on the lhs of assignment. 30786Speter */ 31786Speter identis(cp, kind) 32786Speter register char *cp; 33786Speter int kind; 34786Speter { 35786Speter register struct nl *p; 36786Speter int i; 37786Speter 38786Speter /* 39786Speter * Cp is NIL when error recovery inserts it. 40786Speter */ 41786Speter if (cp == NIL) 42786Speter return (1); 43786Speter 44786Speter /* 45786Speter * Record kind we want for possible later use by yyrecover 46786Speter */ 47786Speter yyidwant = kind; 48786Speter yyidhave = NIL; 49786Speter i = ( (int) cp ) & 077; 50786Speter for (p = disptab[i]; p != NIL; p = p->nl_next) 51786Speter if (p->symbol == cp) { 52786Speter if (yyidok(p, kind)) 53786Speter goto gotit; 54786Speter if (p->class != FIELD && p->class != BADUSE) 55786Speter break; 56786Speter } 57786Speter if (p != NIL) 58786Speter for (p = p->nl_next; p != NIL; p = p->nl_next) 59786Speter if (p->symbol == cp && p->class == FIELD && yyidok(p, kind)) 60786Speter goto gotit; 61786Speter return (0); 62786Speter gotit: 63786Speter if (p->class == BADUSE && !Recovery) { 64786Speter yybadref(p, OY.Yyeline); 6514748Sthien yypv[0].i_entry = NIL; 66786Speter } 67786Speter return (1); 68786Speter } 69786Speter 70786Speter /* 71786Speter * A bad reference to the identifier cp on line 72786Speter * line and use implying the addition of kindmask 73786Speter * to the mask of kind information. 74786Speter */ 7514748Sthien struct nl * 76786Speter yybaduse(cp, line, kindmask) 77786Speter register char *cp; 78786Speter int line, kindmask; 79786Speter { 80786Speter register struct nl *p, *oldp; 81786Speter int i; 82786Speter 83786Speter i = ( (int) cp ) & 077; 84786Speter for (p = disptab[i]; p != NIL; p = p->nl_next) 85786Speter if (p->symbol == cp) 86786Speter break; 87786Speter oldp = p; 88786Speter if (p == NIL || p->class != BADUSE) 8914748Sthien p = enter(defnl(cp, BADUSE, NLNIL, 0)); 903085Smckusic p->value[NL_KINDS] |= kindmask; 91786Speter yybadref(p, line); 92786Speter return (oldp); 93786Speter } 94786Speter 95786Speter /* 96786Speter * ud is initialized so that esavestr will allocate 97786Speter * sizeof ( struct udinfo ) bytes for the 'real' struct udinfo 98786Speter */ 9914748Sthien struct udinfo ud = { ~0 , (struct udinfo *) ~0 , 0}; 100786Speter /* 101786Speter * Record a reference to an undefined identifier, 102786Speter * or one which is improperly used. 103786Speter */ 104786Speter yybadref(p, line) 105786Speter register struct nl *p; 106786Speter int line; 107786Speter { 108786Speter register struct udinfo *udp; 109786Speter 11014748Sthien if (p->chain != NIL && ((struct udinfo *) p->chain)->ud_line == line) 111786Speter return; 11214748Sthien udp = (struct udinfo *) esavestr((char *) &ud); 113786Speter udp->ud_line = line; 11414748Sthien udp->ud_next = (struct udinfo *) p->chain; 11514748Sthien p->chain = (struct nl *) udp; 116786Speter } 117786Speter 1181201Speter #define varkinds ((1<<CONST)|(1<<VAR)|(1<<REF)|(1<<ARRAY)|(1<<PTR) \ 1191201Speter |(1<<RECORD)|(1<<FIELD)|(1<<FUNC)|(1<<FVAR) \ 1201201Speter |(1<<FFUNC)|(1<<PROC)|(1<<FPROC)) 121786Speter /* 122786Speter * Is the symbol in the p entry of the namelist 123786Speter * even possibly a kind kind? If not, update 124786Speter * what we have based on this encounter. 125786Speter */ 126786Speter yyidok(p, kind) 127786Speter register struct nl *p; 128786Speter int kind; 129786Speter { 130786Speter 131786Speter if (p->class == BADUSE) { 132786Speter if (kind == VAR) 133786Speter return (p->value[0] & varkinds); 134786Speter return (p->value[0] & (1 << kind)); 135786Speter } 136786Speter if (yyidok1(p, kind)) 137786Speter return (1); 138786Speter if (yyidhave != NIL) 139786Speter yyidhave = IMPROPER; 140786Speter else 141786Speter yyidhave = p->class; 142786Speter return (0); 143786Speter } 144786Speter 145786Speter yyidok1(p, kind) 146786Speter register struct nl *p; 147786Speter int kind; 148786Speter { 149786Speter 150786Speter switch (kind) { 15114748Sthien default: 152786Speter case FUNC: 1531201Speter return ( p -> class == FUNC 1541201Speter || p -> class == FVAR 1551201Speter || p -> class == FFUNC ); 1561201Speter case PROC: 1571201Speter return ( p -> class == PROC || p -> class == FPROC ); 158786Speter case CONST: 159786Speter case TYPE: 160786Speter case FIELD: 161786Speter return (p->class == kind); 162786Speter case VAR: 163786Speter return (p->class == CONST || yyisvar(p, NIL)); 164786Speter case ARRAY: 165786Speter case RECORD: 166786Speter return (yyisvar(p, kind)); 167786Speter case PTRFILE: 168786Speter return (yyisvar(p, PTR) || yyisvar(p, FILET)); 169786Speter } 170786Speter } 171786Speter 1727922Smckusick yyisvar(p, varclass) 173786Speter register struct nl *p; 1747922Smckusick int varclass; 175786Speter { 176786Speter 177786Speter switch (p->class) { 178786Speter case FIELD: 179786Speter case VAR: 180786Speter case REF: 181786Speter case FVAR: 182786Speter /* 183786Speter * We would prefer to return 184786Speter * parameterless functions only. 185786Speter */ 186786Speter case FUNC: 1871201Speter case FFUNC: 1887922Smckusick return (varclass == NIL || (p->type != NIL && p->type->class == varclass)); 1891201Speter case PROC: 1901201Speter case FPROC: 1917922Smckusick return ( varclass == NIL ); 192786Speter } 193786Speter return (0); 194786Speter } 195786Speter #endif 196786Speter #ifdef PXP 197786Speter #ifndef DEBUG 198786Speter identis() 199786Speter { 200786Speter 201786Speter return (1); 202786Speter } 203786Speter #endif 204786Speter #ifdef DEBUG 205786Speter extern char *classes[]; 206786Speter 207786Speter char kindchars[] "UCTVAQRDPF"; 208786Speter /* 209786Speter * Fake routine "identis" for pxp when testing error recovery. 210786Speter * Looks at letters in variable names to answer questions 211786Speter * about attributes. Mapping is 212786Speter * C const_id 213786Speter * T type_id 214786Speter * V var_id also if any of AQRDF 215786Speter * A array_id 216786Speter * Q ptr_id 217786Speter * R record_id 218786Speter * D field_id D for "dot" 219786Speter * P proc_id 220786Speter * F func_id 221786Speter */ 222786Speter identis(cp, kind) 223786Speter register char *cp; 224786Speter int kind; 225786Speter { 226786Speter register char *dp; 227786Speter char kindch; 228786Speter 229786Speter /* 230786Speter * Don't do anything unless -T 231786Speter */ 232786Speter if (!typetest) 233786Speter return (1); 234786Speter 235786Speter /* 236786Speter * Inserted symbols are always correct 237786Speter */ 238786Speter if (cp == NIL) 239786Speter return (1); 240786Speter /* 241786Speter * Set up the names for error messages 242786Speter */ 243786Speter yyidwant = classes[kind]; 244786Speter for (dp = kindchars; *dp; dp++) 245786Speter if (any(cp, *dp)) { 246786Speter yyidhave = classes[dp - kindchars]; 247786Speter break; 248786Speter } 249786Speter 250786Speter /* 251786Speter * U in the name means undefined 252786Speter */ 253786Speter if (any(cp, 'U')) 254786Speter return (0); 255786Speter 256786Speter kindch = kindchars[kind]; 257786Speter if (kindch == 'V') 258786Speter for (dp = "AQRDF"; *dp; dp++) 259786Speter if (any(cp, *dp)) 260786Speter return (1); 261786Speter return (any(cp, kindch)); 262786Speter } 263786Speter #endif 264786Speter #endif 265