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