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