| 1 | /***** spin: structs.c *****/ |
| 2 | |
| 3 | /* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */ |
| 4 | /* All Rights Reserved. This software is for educational purposes only. */ |
| 5 | /* No guarantee whatsoever is expressed or implied by the distribution of */ |
| 6 | /* this code. Permission is given to distribute this code provided that */ |
| 7 | /* this introductory message is not removed and no monies are exchanged. */ |
| 8 | /* Software written by Gerard J. Holzmann. For tool documentation see: */ |
| 9 | /* http://spinroot.com/ */ |
| 10 | /* Send all bug-reports and/or questions to: bugs@spinroot.com */ |
| 11 | |
| 12 | #include "spin.h" |
| 13 | #include "y.tab.h" |
| 14 | |
| 15 | typedef struct UType { |
| 16 | Symbol *nm; /* name of the type */ |
| 17 | Lextok *cn; /* contents */ |
| 18 | struct UType *nxt; /* linked list */ |
| 19 | } UType; |
| 20 | |
| 21 | extern Symbol *Fname; |
| 22 | extern int lineno, depth, Expand_Ok, has_hidden; |
| 23 | |
| 24 | Symbol *owner; |
| 25 | |
| 26 | static UType *Unames = 0; |
| 27 | static UType *Pnames = 0; |
| 28 | |
| 29 | static Lextok *cpnn(Lextok *, int, int, int); |
| 30 | extern void sr_mesg(FILE *, int, int); |
| 31 | |
| 32 | void |
| 33 | setuname(Lextok *n) |
| 34 | { UType *tmp; |
| 35 | |
| 36 | if (!owner) |
| 37 | fatal("illegal reference inside typedef", (char *) 0); |
| 38 | |
| 39 | for (tmp = Unames; tmp; tmp = tmp->nxt) |
| 40 | if (!strcmp(owner->name, tmp->nm->name)) |
| 41 | { non_fatal("typename %s was defined before", |
| 42 | tmp->nm->name); |
| 43 | return; |
| 44 | } |
| 45 | |
| 46 | tmp = (UType *) emalloc(sizeof(UType)); |
| 47 | tmp->nm = owner; |
| 48 | tmp->cn = n; |
| 49 | tmp->nxt = Unames; |
| 50 | Unames = tmp; |
| 51 | } |
| 52 | |
| 53 | static void |
| 54 | putUname(FILE *fd, UType *tmp) |
| 55 | { Lextok *fp, *tl; |
| 56 | |
| 57 | if (!tmp) return; |
| 58 | putUname(fd, tmp->nxt); /* postorder */ |
| 59 | fprintf(fd, "struct %s { /* user defined type */\n", |
| 60 | tmp->nm->name); |
| 61 | for (fp = tmp->cn; fp; fp = fp->rgt) |
| 62 | for (tl = fp->lft; tl; tl = tl->rgt) |
| 63 | typ2c(tl->sym); |
| 64 | fprintf(fd, "};\n"); |
| 65 | } |
| 66 | |
| 67 | void |
| 68 | putunames(FILE *fd) |
| 69 | { |
| 70 | putUname(fd, Unames); |
| 71 | } |
| 72 | |
| 73 | int |
| 74 | isutype(char *t) |
| 75 | { UType *tmp; |
| 76 | |
| 77 | for (tmp = Unames; tmp; tmp = tmp->nxt) |
| 78 | { if (!strcmp(t, tmp->nm->name)) |
| 79 | return 1; |
| 80 | } |
| 81 | return 0; |
| 82 | } |
| 83 | |
| 84 | Lextok * |
| 85 | getuname(Symbol *t) |
| 86 | { UType *tmp; |
| 87 | |
| 88 | for (tmp = Unames; tmp; tmp = tmp->nxt) |
| 89 | { if (!strcmp(t->name, tmp->nm->name)) |
| 90 | return tmp->cn; |
| 91 | } |
| 92 | fatal("%s is not a typename", t->name); |
| 93 | return (Lextok *)0; |
| 94 | } |
| 95 | |
| 96 | void |
| 97 | setutype(Lextok *p, Symbol *t, Lextok *vis) /* user-defined types */ |
| 98 | { int oln = lineno; |
| 99 | Symbol *ofn = Fname; |
| 100 | Lextok *m, *n; |
| 101 | |
| 102 | m = getuname(t); |
| 103 | for (n = p; n; n = n->rgt) |
| 104 | { lineno = n->ln; |
| 105 | Fname = n->fn; |
| 106 | if (n->sym->type) |
| 107 | non_fatal("redeclaration of '%s'", n->sym->name); |
| 108 | |
| 109 | if (n->sym->nbits > 0) |
| 110 | non_fatal("(%s) only an unsigned can have width-field", |
| 111 | n->sym->name); |
| 112 | |
| 113 | if (Expand_Ok) |
| 114 | n->sym->hidden |= (4|8|16); /* formal par */ |
| 115 | |
| 116 | if (vis) |
| 117 | { if (strncmp(vis->sym->name, ":hide:", (size_t) 6) == 0) |
| 118 | { n->sym->hidden |= 1; |
| 119 | has_hidden++; |
| 120 | } else if (strncmp(vis->sym->name, ":show:", (size_t) 6) == 0) |
| 121 | n->sym->hidden |= 2; |
| 122 | else if (strncmp(vis->sym->name, ":local:", (size_t) 7) == 0) |
| 123 | n->sym->hidden |= 64; |
| 124 | } |
| 125 | n->sym->type = STRUCT; /* classification */ |
| 126 | n->sym->Slst = m; /* structure itself */ |
| 127 | n->sym->Snm = t; /* name of typedef */ |
| 128 | n->sym->Nid = 0; /* this is no chan */ |
| 129 | n->sym->hidden |= 4; |
| 130 | if (n->sym->nel <= 0) |
| 131 | non_fatal("bad array size for '%s'", n->sym->name); |
| 132 | } |
| 133 | lineno = oln; |
| 134 | Fname = ofn; |
| 135 | } |
| 136 | |
| 137 | static Symbol * |
| 138 | do_same(Lextok *n, Symbol *v, int xinit) |
| 139 | { Lextok *tmp, *fp, *tl; |
| 140 | int ix = eval(n->lft); |
| 141 | int oln = lineno; |
| 142 | Symbol *ofn = Fname; |
| 143 | |
| 144 | lineno = n->ln; |
| 145 | Fname = n->fn; |
| 146 | |
| 147 | /* n->sym->type == STRUCT |
| 148 | * index: n->lft |
| 149 | * subfields: n->rgt |
| 150 | * structure template: n->sym->Slst |
| 151 | * runtime values: n->sym->Sval |
| 152 | */ |
| 153 | if (xinit) ini_struct(v); /* once, at top level */ |
| 154 | |
| 155 | if (ix >= v->nel || ix < 0) |
| 156 | { printf("spin: indexing %s[%d] - size is %d\n", |
| 157 | v->name, ix, v->nel); |
| 158 | fatal("indexing error \'%s\'", v->name); |
| 159 | } |
| 160 | if (!n->rgt || !n->rgt->lft) |
| 161 | { non_fatal("no subfields %s", v->name); /* i.e., wants all */ |
| 162 | lineno = oln; Fname = ofn; |
| 163 | return ZS; |
| 164 | } |
| 165 | |
| 166 | if (n->rgt->ntyp != '.') |
| 167 | { printf("bad subfield type %d\n", n->rgt->ntyp); |
| 168 | alldone(1); |
| 169 | } |
| 170 | |
| 171 | tmp = n->rgt->lft; |
| 172 | if (tmp->ntyp != NAME && tmp->ntyp != TYPE) |
| 173 | { printf("bad subfield entry %d\n", tmp->ntyp); |
| 174 | alldone(1); |
| 175 | } |
| 176 | for (fp = v->Sval[ix]; fp; fp = fp->rgt) |
| 177 | for (tl = fp->lft; tl; tl = tl->rgt) |
| 178 | if (!strcmp(tl->sym->name, tmp->sym->name)) |
| 179 | { lineno = oln; Fname = ofn; |
| 180 | return tl->sym; |
| 181 | } |
| 182 | fatal("cannot locate subfield %s", tmp->sym->name); |
| 183 | return ZS; |
| 184 | } |
| 185 | |
| 186 | int |
| 187 | Rval_struct(Lextok *n, Symbol *v, int xinit) /* n varref, v valref */ |
| 188 | { Symbol *tl; |
| 189 | Lextok *tmp; |
| 190 | int ix; |
| 191 | |
| 192 | if (!n || !(tl = do_same(n, v, xinit))) |
| 193 | return 0; |
| 194 | |
| 195 | tmp = n->rgt->lft; |
| 196 | if (tmp->sym->type == STRUCT) |
| 197 | { return Rval_struct(tmp, tl, 0); |
| 198 | } else if (tmp->rgt) |
| 199 | fatal("non-zero 'rgt' on non-structure", 0); |
| 200 | |
| 201 | ix = eval(tmp->lft); |
| 202 | if (ix >= tl->nel || ix < 0) |
| 203 | fatal("indexing error \'%s\'", tl->name); |
| 204 | |
| 205 | return cast_val(tl->type, tl->val[ix], tl->nbits); |
| 206 | } |
| 207 | |
| 208 | int |
| 209 | Lval_struct(Lextok *n, Symbol *v, int xinit, int a) /* a = assigned value */ |
| 210 | { Symbol *tl; |
| 211 | Lextok *tmp; |
| 212 | int ix; |
| 213 | |
| 214 | if (!(tl = do_same(n, v, xinit))) |
| 215 | return 1; |
| 216 | |
| 217 | tmp = n->rgt->lft; |
| 218 | if (tmp->sym->type == STRUCT) |
| 219 | return Lval_struct(tmp, tl, 0, a); |
| 220 | else if (tmp->rgt) |
| 221 | fatal("non-zero 'rgt' on non-structure", 0); |
| 222 | |
| 223 | ix = eval(tmp->lft); |
| 224 | if (ix >= tl->nel || ix < 0) |
| 225 | fatal("indexing error \'%s\'", tl->name); |
| 226 | |
| 227 | if (tl->nbits > 0) |
| 228 | a = (a & ((1<<tl->nbits)-1)); |
| 229 | |
| 230 | if (a != tl->val[ix]) |
| 231 | { tl->val[ix] = a; |
| 232 | tl->setat = depth; |
| 233 | } |
| 234 | return 1; |
| 235 | } |
| 236 | |
| 237 | int |
| 238 | Cnt_flds(Lextok *m) |
| 239 | { Lextok *fp, *tl, *n; |
| 240 | int cnt = 0; |
| 241 | |
| 242 | if (m->ntyp == ',') |
| 243 | { n = m; |
| 244 | goto is_lst; |
| 245 | } |
| 246 | if (!m->sym || m->ntyp != STRUCT) |
| 247 | return 1; |
| 248 | |
| 249 | n = getuname(m->sym); |
| 250 | is_lst: |
| 251 | for (fp = n; fp; fp = fp->rgt) |
| 252 | for (tl = fp->lft; tl; tl = tl->rgt) |
| 253 | { if (tl->sym->type == STRUCT) |
| 254 | { if (tl->sym->nel != 1) |
| 255 | fatal("array of structures in param list, %s", |
| 256 | tl->sym->name); |
| 257 | cnt += Cnt_flds(tl->sym->Slst); |
| 258 | } else |
| 259 | cnt += tl->sym->nel; |
| 260 | } |
| 261 | return cnt; |
| 262 | } |
| 263 | |
| 264 | int |
| 265 | Sym_typ(Lextok *t) |
| 266 | { Symbol *s = t->sym; |
| 267 | |
| 268 | if (!s) return 0; |
| 269 | |
| 270 | if (s->type != STRUCT) |
| 271 | return s->type; |
| 272 | |
| 273 | if (!t->rgt |
| 274 | || t->rgt->ntyp != '.' /* gh: had ! in wrong place */ |
| 275 | || !t->rgt->lft) |
| 276 | return STRUCT; /* not a field reference */ |
| 277 | |
| 278 | return Sym_typ(t->rgt->lft); |
| 279 | } |
| 280 | |
| 281 | int |
| 282 | Width_set(int *wdth, int i, Lextok *n) |
| 283 | { Lextok *fp, *tl; |
| 284 | int j = i, k; |
| 285 | |
| 286 | for (fp = n; fp; fp = fp->rgt) |
| 287 | for (tl = fp->lft; tl; tl = tl->rgt) |
| 288 | { if (tl->sym->type == STRUCT) |
| 289 | j = Width_set(wdth, j, tl->sym->Slst); |
| 290 | else |
| 291 | { for (k = 0; k < tl->sym->nel; k++, j++) |
| 292 | wdth[j] = tl->sym->type; |
| 293 | } } |
| 294 | return j; |
| 295 | } |
| 296 | |
| 297 | void |
| 298 | ini_struct(Symbol *s) |
| 299 | { int i; Lextok *fp, *tl; |
| 300 | |
| 301 | if (s->type != STRUCT) /* last step */ |
| 302 | { (void) checkvar(s, 0); |
| 303 | return; |
| 304 | } |
| 305 | if (s->Sval == (Lextok **) 0) |
| 306 | { s->Sval = (Lextok **) emalloc(s->nel * sizeof(Lextok *)); |
| 307 | for (i = 0; i < s->nel; i++) |
| 308 | { s->Sval[i] = cpnn(s->Slst, 1, 1, 1); |
| 309 | |
| 310 | for (fp = s->Sval[i]; fp; fp = fp->rgt) |
| 311 | for (tl = fp->lft; tl; tl = tl->rgt) |
| 312 | ini_struct(tl->sym); |
| 313 | } } |
| 314 | } |
| 315 | |
| 316 | static Lextok * |
| 317 | cpnn(Lextok *s, int L, int R, int S) |
| 318 | { Lextok *d; extern int Nid; |
| 319 | |
| 320 | if (!s) return ZN; |
| 321 | |
| 322 | d = (Lextok *) emalloc(sizeof(Lextok)); |
| 323 | d->ntyp = s->ntyp; |
| 324 | d->val = s->val; |
| 325 | d->ln = s->ln; |
| 326 | d->fn = s->fn; |
| 327 | d->sym = s->sym; |
| 328 | if (L) d->lft = cpnn(s->lft, 1, 1, S); |
| 329 | if (R) d->rgt = cpnn(s->rgt, 1, 1, S); |
| 330 | |
| 331 | if (S && s->sym) |
| 332 | { d->sym = (Symbol *) emalloc(sizeof(Symbol)); |
| 333 | memcpy(d->sym, s->sym, sizeof(Symbol)); |
| 334 | if (d->sym->type == CHAN) |
| 335 | d->sym->Nid = ++Nid; |
| 336 | } |
| 337 | if (s->sq || s->sl) |
| 338 | fatal("cannot happen cpnn", (char *) 0); |
| 339 | |
| 340 | return d; |
| 341 | } |
| 342 | |
| 343 | int |
| 344 | full_name(FILE *fd, Lextok *n, Symbol *v, int xinit) |
| 345 | { Symbol *tl; |
| 346 | Lextok *tmp; |
| 347 | int hiddenarrays = 0; |
| 348 | |
| 349 | fprintf(fd, "%s", v->name); |
| 350 | |
| 351 | if (!n || !(tl = do_same(n, v, xinit))) |
| 352 | return 0; |
| 353 | tmp = n->rgt->lft; |
| 354 | |
| 355 | if (tmp->sym->type == STRUCT) |
| 356 | { fprintf(fd, "."); |
| 357 | hiddenarrays = full_name(fd, tmp, tl, 0); |
| 358 | goto out; |
| 359 | } |
| 360 | fprintf(fd, ".%s", tl->name); |
| 361 | out: if (tmp->sym->nel > 1) |
| 362 | { fprintf(fd, "[%d]", eval(tmp->lft)); |
| 363 | hiddenarrays = 1; |
| 364 | } |
| 365 | return hiddenarrays; |
| 366 | } |
| 367 | |
| 368 | void |
| 369 | validref(Lextok *p, Lextok *c) |
| 370 | { Lextok *fp, *tl; |
| 371 | char lbuf[512]; |
| 372 | |
| 373 | for (fp = p->sym->Slst; fp; fp = fp->rgt) |
| 374 | for (tl = fp->lft; tl; tl = tl->rgt) |
| 375 | if (strcmp(tl->sym->name, c->sym->name) == 0) |
| 376 | return; |
| 377 | |
| 378 | sprintf(lbuf, "no field '%s' defined in structure '%s'\n", |
| 379 | c->sym->name, p->sym->name); |
| 380 | non_fatal(lbuf, (char *) 0); |
| 381 | } |
| 382 | |
| 383 | void |
| 384 | struct_name(Lextok *n, Symbol *v, int xinit, char *buf) |
| 385 | { Symbol *tl; |
| 386 | Lextok *tmp; |
| 387 | char lbuf[512]; |
| 388 | |
| 389 | if (!n || !(tl = do_same(n, v, xinit))) |
| 390 | return; |
| 391 | tmp = n->rgt->lft; |
| 392 | if (tmp->sym->type == STRUCT) |
| 393 | { strcat(buf, "."); |
| 394 | struct_name(tmp, tl, 0, buf); |
| 395 | return; |
| 396 | } |
| 397 | sprintf(lbuf, ".%s", tl->name); |
| 398 | strcat(buf, lbuf); |
| 399 | if (tmp->sym->nel > 1) |
| 400 | { sprintf(lbuf, "[%d]", eval(tmp->lft)); |
| 401 | strcat(buf, lbuf); |
| 402 | } |
| 403 | } |
| 404 | |
| 405 | void |
| 406 | walk2_struct(char *s, Symbol *z) |
| 407 | { Lextok *fp, *tl; |
| 408 | char eprefix[128]; |
| 409 | int ix; |
| 410 | extern void Done_case(char *, Symbol *); |
| 411 | |
| 412 | ini_struct(z); |
| 413 | if (z->nel == 1) |
| 414 | sprintf(eprefix, "%s%s.", s, z->name); |
| 415 | for (ix = 0; ix < z->nel; ix++) |
| 416 | { if (z->nel > 1) |
| 417 | sprintf(eprefix, "%s%s[%d].", s, z->name, ix); |
| 418 | for (fp = z->Sval[ix]; fp; fp = fp->rgt) |
| 419 | for (tl = fp->lft; tl; tl = tl->rgt) |
| 420 | { if (tl->sym->type == STRUCT) |
| 421 | walk2_struct(eprefix, tl->sym); |
| 422 | else if (tl->sym->type == CHAN) |
| 423 | Done_case(eprefix, tl->sym); |
| 424 | } } |
| 425 | } |
| 426 | |
| 427 | void |
| 428 | walk_struct(FILE *ofd, int dowhat, char *s, Symbol *z, char *a, char *b, char *c) |
| 429 | { Lextok *fp, *tl; |
| 430 | char eprefix[128]; |
| 431 | int ix; |
| 432 | |
| 433 | ini_struct(z); |
| 434 | if (z->nel == 1) |
| 435 | sprintf(eprefix, "%s%s.", s, z->name); |
| 436 | for (ix = 0; ix < z->nel; ix++) |
| 437 | { if (z->nel > 1) |
| 438 | sprintf(eprefix, "%s%s[%d].", s, z->name, ix); |
| 439 | for (fp = z->Sval[ix]; fp; fp = fp->rgt) |
| 440 | for (tl = fp->lft; tl; tl = tl->rgt) |
| 441 | { if (tl->sym->type == STRUCT) |
| 442 | walk_struct(ofd, dowhat, eprefix, tl->sym, a,b,c); |
| 443 | else |
| 444 | do_var(ofd, dowhat, eprefix, tl->sym, a,b,c); |
| 445 | } } |
| 446 | } |
| 447 | |
| 448 | void |
| 449 | c_struct(FILE *fd, char *ipref, Symbol *z) |
| 450 | { Lextok *fp, *tl; |
| 451 | char pref[256], eprefix[300]; |
| 452 | int ix; |
| 453 | |
| 454 | ini_struct(z); |
| 455 | |
| 456 | for (ix = 0; ix < z->nel; ix++) |
| 457 | for (fp = z->Sval[ix]; fp; fp = fp->rgt) |
| 458 | for (tl = fp->lft; tl; tl = tl->rgt) |
| 459 | { strcpy(eprefix, ipref); |
| 460 | if (z->nel > 1) |
| 461 | { /* insert index before last '.' */ |
| 462 | eprefix[strlen(eprefix)-1] = '\0'; |
| 463 | sprintf(pref, "[ %d ].", ix); |
| 464 | strcat(eprefix, pref); |
| 465 | } |
| 466 | if (tl->sym->type == STRUCT) |
| 467 | { strcat(eprefix, tl->sym->name); |
| 468 | strcat(eprefix, "."); |
| 469 | c_struct(fd, eprefix, tl->sym); |
| 470 | } else |
| 471 | c_var(fd, eprefix, tl->sym); |
| 472 | } |
| 473 | } |
| 474 | |
| 475 | void |
| 476 | dump_struct(Symbol *z, char *prefix, RunList *r) |
| 477 | { Lextok *fp, *tl; |
| 478 | char eprefix[256]; |
| 479 | int ix, jx; |
| 480 | |
| 481 | ini_struct(z); |
| 482 | |
| 483 | for (ix = 0; ix < z->nel; ix++) |
| 484 | { if (z->nel > 1) |
| 485 | sprintf(eprefix, "%s[%d]", prefix, ix); |
| 486 | else |
| 487 | strcpy(eprefix, prefix); |
| 488 | |
| 489 | for (fp = z->Sval[ix]; fp; fp = fp->rgt) |
| 490 | for (tl = fp->lft; tl; tl = tl->rgt) |
| 491 | { if (tl->sym->type == STRUCT) |
| 492 | { char pref[300]; |
| 493 | strcpy(pref, eprefix); |
| 494 | strcat(pref, "."); |
| 495 | strcat(pref, tl->sym->name); |
| 496 | dump_struct(tl->sym, pref, r); |
| 497 | } else |
| 498 | for (jx = 0; jx < tl->sym->nel; jx++) |
| 499 | { if (tl->sym->type == CHAN) |
| 500 | doq(tl->sym, jx, r); |
| 501 | else |
| 502 | { printf("\t\t"); |
| 503 | if (r) |
| 504 | printf("%s(%d):", r->n->name, r->pid); |
| 505 | printf("%s.%s", eprefix, tl->sym->name); |
| 506 | if (tl->sym->nel > 1) |
| 507 | printf("[%d]", jx); |
| 508 | printf(" = "); |
| 509 | sr_mesg(stdout, tl->sym->val[jx], |
| 510 | tl->sym->type == MTYPE); |
| 511 | printf("\n"); |
| 512 | } } } |
| 513 | } |
| 514 | } |
| 515 | |
| 516 | static int |
| 517 | retrieve(Lextok **targ, int i, int want, Lextok *n, int Ntyp) |
| 518 | { Lextok *fp, *tl; |
| 519 | int j = i, k; |
| 520 | |
| 521 | for (fp = n; fp; fp = fp->rgt) |
| 522 | for (tl = fp->lft; tl; tl = tl->rgt) |
| 523 | { if (tl->sym->type == STRUCT) |
| 524 | { j = retrieve(targ, j, want, tl->sym->Slst, Ntyp); |
| 525 | if (j < 0) |
| 526 | { Lextok *x = cpnn(tl, 1, 0, 0); |
| 527 | x->rgt = nn(ZN, '.', (*targ), ZN); |
| 528 | (*targ) = x; |
| 529 | return -1; |
| 530 | } |
| 531 | } else |
| 532 | { for (k = 0; k < tl->sym->nel; k++, j++) |
| 533 | { if (j == want) |
| 534 | { *targ = cpnn(tl, 1, 0, 0); |
| 535 | (*targ)->lft = nn(ZN, CONST, ZN, ZN); |
| 536 | (*targ)->lft->val = k; |
| 537 | if (Ntyp) |
| 538 | (*targ)->ntyp = (short) Ntyp; |
| 539 | return -1; |
| 540 | } |
| 541 | } } } |
| 542 | return j; |
| 543 | } |
| 544 | |
| 545 | static int |
| 546 | is_explicit(Lextok *n) |
| 547 | { |
| 548 | if (!n) return 0; |
| 549 | if (!n->sym) fatal("unexpected - no symbol", 0); |
| 550 | if (n->sym->type != STRUCT) return 1; |
| 551 | if (!n->rgt) return 0; |
| 552 | if (n->rgt->ntyp != '.') |
| 553 | { lineno = n->ln; |
| 554 | Fname = n->fn; |
| 555 | printf("ntyp %d\n", n->rgt->ntyp); |
| 556 | fatal("unexpected %s, no '.'", n->sym->name); |
| 557 | } |
| 558 | return is_explicit(n->rgt->lft); |
| 559 | } |
| 560 | |
| 561 | Lextok * |
| 562 | expand(Lextok *n, int Ok) |
| 563 | /* turn rgt-lnked list of struct nms, into ',' list of flds */ |
| 564 | { Lextok *x = ZN, *y; |
| 565 | |
| 566 | if (!Ok) return n; |
| 567 | |
| 568 | while (n) |
| 569 | { y = mk_explicit(n, 1, 0); |
| 570 | if (x) |
| 571 | (void) tail_add(x, y); |
| 572 | else |
| 573 | x = y; |
| 574 | |
| 575 | n = n->rgt; |
| 576 | } |
| 577 | return x; |
| 578 | } |
| 579 | |
| 580 | Lextok * |
| 581 | mk_explicit(Lextok *n, int Ok, int Ntyp) |
| 582 | /* produce a single ',' list of fields */ |
| 583 | { Lextok *bld = ZN, *x; |
| 584 | int i, cnt; extern int IArgs; |
| 585 | |
| 586 | if (n->sym->type != STRUCT |
| 587 | || is_explicit(n)) |
| 588 | return n; |
| 589 | |
| 590 | if (n->rgt |
| 591 | && n->rgt->ntyp == '.' |
| 592 | && n->rgt->lft |
| 593 | && n->rgt->lft->sym |
| 594 | && n->rgt->lft->sym->type == STRUCT) |
| 595 | { Lextok *y; |
| 596 | bld = mk_explicit(n->rgt->lft, Ok, Ntyp); |
| 597 | for (x = bld; x; x = x->rgt) |
| 598 | { y = cpnn(n, 1, 0, 0); |
| 599 | y->rgt = nn(ZN, '.', x->lft, ZN); |
| 600 | x->lft = y; |
| 601 | } |
| 602 | |
| 603 | return bld; |
| 604 | } |
| 605 | |
| 606 | if (!Ok || !n->sym->Slst) |
| 607 | { if (IArgs) return n; |
| 608 | printf("spin: saw '"); |
| 609 | comment(stdout, n, 0); |
| 610 | printf("'\n"); |
| 611 | fatal("incomplete structure ref '%s'", n->sym->name); |
| 612 | } |
| 613 | |
| 614 | cnt = Cnt_flds(n->sym->Slst); |
| 615 | for (i = cnt-1; i >= 0; i--) |
| 616 | { bld = nn(ZN, ',', ZN, bld); |
| 617 | if (retrieve(&(bld->lft), 0, i, n->sym->Slst, Ntyp) >= 0) |
| 618 | { printf("cannot retrieve field %d\n", i); |
| 619 | fatal("bad structure %s", n->sym->name); |
| 620 | } |
| 621 | x = cpnn(n, 1, 0, 0); |
| 622 | x->rgt = nn(ZN, '.', bld->lft, ZN); |
| 623 | bld->lft = x; |
| 624 | } |
| 625 | return bld; |
| 626 | } |
| 627 | |
| 628 | Lextok * |
| 629 | tail_add(Lextok *a, Lextok *b) |
| 630 | { Lextok *t; |
| 631 | |
| 632 | for (t = a; t->rgt; t = t->rgt) |
| 633 | if (t->ntyp != ',') |
| 634 | fatal("unexpected type - tail_add", 0); |
| 635 | t->rgt = b; |
| 636 | return a; |
| 637 | } |
| 638 | |
| 639 | void |
| 640 | setpname(Lextok *n) |
| 641 | { UType *tmp; |
| 642 | |
| 643 | for (tmp = Pnames; tmp; tmp = tmp->nxt) |
| 644 | if (!strcmp(n->sym->name, tmp->nm->name)) |
| 645 | { non_fatal("proctype %s redefined", |
| 646 | n->sym->name); |
| 647 | return; |
| 648 | } |
| 649 | tmp = (UType *) emalloc(sizeof(UType)); |
| 650 | tmp->nm = n->sym; |
| 651 | tmp->nxt = Pnames; |
| 652 | Pnames = tmp; |
| 653 | } |
| 654 | |
| 655 | int |
| 656 | isproctype(char *t) |
| 657 | { UType *tmp; |
| 658 | |
| 659 | for (tmp = Pnames; tmp; tmp = tmp->nxt) |
| 660 | { if (!strcmp(t, tmp->nm->name)) |
| 661 | return 1; |
| 662 | } |
| 663 | return 0; |
| 664 | } |