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