1 /***** spin: flow.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 extern Symbol *Fname; 16 extern int nr_errs, lineno, verbose; 17 extern short has_unless, has_badelse; 18 19 Element *Al_El = ZE; 20 Label *labtab = (Label *) 0; 21 int Unique=0, Elcnt=0, DstepStart = -1; 22 23 static Lbreak *breakstack = (Lbreak *) 0; 24 static Lextok *innermost; 25 static SeqList *cur_s = (SeqList *) 0; 26 static int break_id=0; 27 28 static Element *if_seq(Lextok *); 29 static Element *new_el(Lextok *); 30 static Element *unless_seq(Lextok *); 31 static void add_el(Element *, Sequence *); 32 static void attach_escape(Sequence *, Sequence *); 33 static void mov_lab(Symbol *, Element *, Element *); 34 static void walk_atomic(Element *, Element *, int); 35 36 void 37 open_seq(int top) 38 { SeqList *t; 39 Sequence *s = (Sequence *) emalloc(sizeof(Sequence)); 40 41 t = seqlist(s, cur_s); 42 cur_s = t; 43 if (top) Elcnt = 1; 44 } 45 46 void 47 rem_Seq(void) 48 { 49 DstepStart = Unique; 50 } 51 52 void 53 unrem_Seq(void) 54 { 55 DstepStart = -1; 56 } 57 58 static int 59 Rjumpslocal(Element *q, Element *stop) 60 { Element *lb, *f; 61 SeqList *h; 62 63 /* allow no jumps out of a d_step sequence */ 64 for (f = q; f && f != stop; f = f->nxt) 65 { if (f && f->n && f->n->ntyp == GOTO) 66 { lb = get_lab(f->n, 0); 67 if (!lb || lb->Seqno < DstepStart) 68 { lineno = f->n->ln; 69 Fname = f->n->fn; 70 return 0; 71 } } 72 for (h = f->sub; h; h = h->nxt) 73 { if (!Rjumpslocal(h->this->frst, h->this->last)) 74 return 0; 75 76 } } 77 return 1; 78 } 79 80 void 81 cross_dsteps(Lextok *a, Lextok *b) 82 { 83 if (a && b 84 && a->indstep != b->indstep) 85 { lineno = a->ln; 86 Fname = a->fn; 87 fatal("jump into d_step sequence", (char *) 0); 88 } 89 } 90 91 int 92 is_skip(Lextok *n) 93 { 94 return (n->ntyp == PRINT 95 || n->ntyp == PRINTM 96 || (n->ntyp == 'c' 97 && n->lft 98 && n->lft->ntyp == CONST 99 && n->lft->val == 1)); 100 } 101 102 void 103 check_sequence(Sequence *s) 104 { Element *e, *le = ZE; 105 Lextok *n; 106 int cnt = 0; 107 108 for (e = s->frst; e; le = e, e = e->nxt) 109 { n = e->n; 110 if (is_skip(n) && !has_lab(e, 0)) 111 { cnt++; 112 if (cnt > 1 113 && n->ntyp != PRINT 114 && n->ntyp != PRINTM) 115 { if (verbose&32) 116 printf("spin: line %d %s, redundant skip\n", 117 n->ln, n->fn->name); 118 if (e != s->frst 119 && e != s->last 120 && e != s->extent) 121 { e->status |= DONE; /* not unreachable */ 122 le->nxt = e->nxt; /* remove it */ 123 e = le; 124 } 125 } 126 } else 127 cnt = 0; 128 } 129 } 130 131 void 132 prune_opts(Lextok *n) 133 { SeqList *l; 134 extern Symbol *context; 135 extern char *claimproc; 136 137 if (!n 138 || (context && claimproc && strcmp(context->name, claimproc) == 0)) 139 return; 140 141 for (l = n->sl; l; l = l->nxt) /* find sequences of unlabeled skips */ 142 check_sequence(l->this); 143 } 144 145 Sequence * 146 close_seq(int nottop) 147 { Sequence *s = cur_s->this; 148 Symbol *z; 149 150 if (nottop > 0 && (z = has_lab(s->frst, 0))) 151 { printf("error: (%s:%d) label %s placed incorrectly\n", 152 (s->frst->n)?s->frst->n->fn->name:"-", 153 (s->frst->n)?s->frst->n->ln:0, 154 z->name); 155 switch (nottop) { 156 case 1: 157 printf("=====> stmnt unless Label: stmnt\n"); 158 printf("sorry, cannot jump to the guard of an\n"); 159 printf("escape (it is not a unique state)\n"); 160 break; 161 case 2: 162 printf("=====> instead of "); 163 printf("\"Label: stmnt unless stmnt\"\n"); 164 printf("=====> always use "); 165 printf("\"Label: { stmnt unless stmnt }\"\n"); 166 break; 167 case 3: 168 printf("=====> instead of "); 169 printf("\"atomic { Label: statement ... }\"\n"); 170 printf("=====> always use "); 171 printf("\"Label: atomic { statement ... }\"\n"); 172 break; 173 case 4: 174 printf("=====> instead of "); 175 printf("\"d_step { Label: statement ... }\"\n"); 176 printf("=====> always use "); 177 printf("\"Label: d_step { statement ... }\"\n"); 178 break; 179 case 5: 180 printf("=====> instead of "); 181 printf("\"{ Label: statement ... }\"\n"); 182 printf("=====> always use "); 183 printf("\"Label: { statement ... }\"\n"); 184 break; 185 case 6: 186 printf("=====>instead of\n"); 187 printf(" do (or if)\n"); 188 printf(" :: ...\n"); 189 printf(" :: Label: statement\n"); 190 printf(" od (of fi)\n"); 191 printf("=====>always use\n"); 192 printf("Label: do (or if)\n"); 193 printf(" :: ...\n"); 194 printf(" :: statement\n"); 195 printf(" od (or fi)\n"); 196 break; 197 case 7: 198 printf("cannot happen - labels\n"); 199 break; 200 } 201 alldone(1); 202 } 203 204 if (nottop == 4 205 && !Rjumpslocal(s->frst, s->last)) 206 fatal("non_local jump in d_step sequence", (char *) 0); 207 208 cur_s = cur_s->nxt; 209 s->maxel = Elcnt; 210 s->extent = s->last; 211 if (!s->last) 212 fatal("sequence must have at least one statement", (char *) 0); 213 return s; 214 } 215 216 Lextok * 217 do_unless(Lextok *No, Lextok *Es) 218 { SeqList *Sl; 219 Lextok *Re = nn(ZN, UNLESS, ZN, ZN); 220 Re->ln = No->ln; 221 Re->fn = No->fn; 222 223 has_unless++; 224 if (Es->ntyp == NON_ATOMIC) 225 Sl = Es->sl; 226 else 227 { open_seq(0); add_seq(Es); 228 Sl = seqlist(close_seq(1), 0); 229 } 230 231 if (No->ntyp == NON_ATOMIC) 232 { No->sl->nxt = Sl; 233 Sl = No->sl; 234 } else if (No->ntyp == ':' 235 && (No->lft->ntyp == NON_ATOMIC 236 || No->lft->ntyp == ATOMIC 237 || No->lft->ntyp == D_STEP)) 238 { 239 int tok = No->lft->ntyp; 240 241 No->lft->sl->nxt = Sl; 242 Re->sl = No->lft->sl; 243 244 open_seq(0); add_seq(Re); 245 Re = nn(ZN, tok, ZN, ZN); 246 Re->sl = seqlist(close_seq(7), 0); 247 Re->ln = No->ln; 248 Re->fn = No->fn; 249 250 Re = nn(No, ':', Re, ZN); /* lift label */ 251 Re->ln = No->ln; 252 Re->fn = No->fn; 253 return Re; 254 } else 255 { open_seq(0); add_seq(No); 256 Sl = seqlist(close_seq(2), Sl); 257 } 258 259 Re->sl = Sl; 260 return Re; 261 } 262 263 SeqList * 264 seqlist(Sequence *s, SeqList *r) 265 { SeqList *t = (SeqList *) emalloc(sizeof(SeqList)); 266 267 t->this = s; 268 t->nxt = r; 269 return t; 270 } 271 272 static Element * 273 new_el(Lextok *n) 274 { Element *m; 275 276 if (n) 277 { if (n->ntyp == IF || n->ntyp == DO) 278 return if_seq(n); 279 if (n->ntyp == UNLESS) 280 return unless_seq(n); 281 } 282 m = (Element *) emalloc(sizeof(Element)); 283 m->n = n; 284 m->seqno = Elcnt++; 285 m->Seqno = Unique++; 286 m->Nxt = Al_El; Al_El = m; 287 return m; 288 } 289 290 static int 291 has_chanref(Lextok *n) 292 { 293 if (!n) return 0; 294 295 switch (n->ntyp) { 296 case 's': case 'r': 297 #if 0 298 case 'R': case LEN: 299 #endif 300 case FULL: case NFULL: 301 case EMPTY: case NEMPTY: 302 return 1; 303 default: 304 break; 305 } 306 if (has_chanref(n->lft)) 307 return 1; 308 309 return has_chanref(n->rgt); 310 } 311 312 void 313 loose_ends(void) /* properly tie-up ends of sub-sequences */ 314 { Element *e, *f; 315 316 for (e = Al_El; e; e = e->Nxt) 317 { if (!e->n 318 || !e->nxt) 319 continue; 320 switch (e->n->ntyp) { 321 case ATOMIC: 322 case NON_ATOMIC: 323 case D_STEP: 324 f = e->nxt; 325 while (f && f->n->ntyp == '.') 326 f = f->nxt; 327 if (0) printf("link %d, {%d .. %d} -> %d (ntyp=%d) was %d\n", 328 e->seqno, 329 e->n->sl->this->frst->seqno, 330 e->n->sl->this->last->seqno, 331 f?f->seqno:-1, f?f->n->ntyp:-1, 332 e->n->sl->this->last->nxt?e->n->sl->this->last->nxt->seqno:-1); 333 if (!e->n->sl->this->last->nxt) 334 e->n->sl->this->last->nxt = f; 335 else 336 { if (e->n->sl->this->last->nxt->n->ntyp != GOTO) 337 { if (!f || e->n->sl->this->last->nxt->seqno != f->seqno) 338 non_fatal("unexpected: loose ends", (char *)0); 339 } else 340 e->n->sl->this->last = e->n->sl->this->last->nxt; 341 /* 342 * fix_dest can push a goto into the nxt position 343 * in that case the goto wins and f is not needed 344 * but the last fields needs adjusting 345 */ 346 } 347 break; 348 } } 349 } 350 351 static Element * 352 if_seq(Lextok *n) 353 { int tok = n->ntyp; 354 SeqList *s = n->sl; 355 Element *e = new_el(ZN); 356 Element *t = new_el(nn(ZN,'.',ZN,ZN)); /* target */ 357 SeqList *z, *prev_z = (SeqList *) 0; 358 SeqList *move_else = (SeqList *) 0; /* to end of optionlist */ 359 int ref_chans = 0; 360 361 for (z = s; z; z = z->nxt) 362 { if (!z->this->frst) 363 continue; 364 if (z->this->frst->n->ntyp == ELSE) 365 { if (move_else) 366 fatal("duplicate `else'", (char *) 0); 367 if (z->nxt) /* is not already at the end */ 368 { move_else = z; 369 if (prev_z) 370 prev_z->nxt = z->nxt; 371 else 372 s = n->sl = z->nxt; 373 continue; 374 } 375 } else 376 ref_chans |= has_chanref(z->this->frst->n); 377 prev_z = z; 378 } 379 if (move_else) 380 { move_else->nxt = (SeqList *) 0; 381 /* if there is no prev, then else was at the end */ 382 if (!prev_z) fatal("cannot happen - if_seq", (char *) 0); 383 prev_z->nxt = move_else; 384 prev_z = move_else; 385 } 386 if (prev_z 387 && ref_chans 388 && prev_z->this->frst->n->ntyp == ELSE) 389 { prev_z->this->frst->n->val = 1; 390 has_badelse++; 391 non_fatal("dubious use of 'else' combined with i/o,", 392 (char *)0); 393 nr_errs--; 394 } 395 396 e->n = nn(n, tok, ZN, ZN); 397 e->n->sl = s; /* preserve as info only */ 398 e->sub = s; 399 for (z = s; z; prev_z = z, z = z->nxt) 400 add_el(t, z->this); /* append target */ 401 if (tok == DO) 402 { add_el(t, cur_s->this); /* target upfront */ 403 t = new_el(nn(n, BREAK, ZN, ZN)); /* break target */ 404 set_lab(break_dest(), t); /* new exit */ 405 breakstack = breakstack->nxt; /* pop stack */ 406 } 407 add_el(e, cur_s->this); 408 add_el(t, cur_s->this); 409 return e; /* destination node for label */ 410 } 411 412 static void 413 escape_el(Element *f, Sequence *e) 414 { SeqList *z; 415 416 for (z = f->esc; z; z = z->nxt) 417 if (z->this == e) 418 return; /* already there */ 419 420 /* cover the lower-level escapes of this state */ 421 for (z = f->esc; z; z = z->nxt) 422 attach_escape(z->this, e); 423 424 /* now attach escape to the state itself */ 425 426 f->esc = seqlist(e, f->esc); /* in lifo order... */ 427 #ifdef DEBUG 428 printf("attach %d (", e->frst->Seqno); 429 comment(stdout, e->frst->n, 0); 430 printf(") to %d (", f->Seqno); 431 comment(stdout, f->n, 0); 432 printf(")\n"); 433 #endif 434 switch (f->n->ntyp) { 435 case UNLESS: 436 attach_escape(f->sub->this, e); 437 break; 438 case IF: 439 case DO: 440 for (z = f->sub; z; z = z->nxt) 441 attach_escape(z->this, e); 442 break; 443 case D_STEP: 444 /* attach only to the guard stmnt */ 445 escape_el(f->n->sl->this->frst, e); 446 break; 447 case ATOMIC: 448 case NON_ATOMIC: 449 /* attach to all stmnts */ 450 attach_escape(f->n->sl->this, e); 451 break; 452 } 453 } 454 455 static void 456 attach_escape(Sequence *n, Sequence *e) 457 { Element *f; 458 459 for (f = n->frst; f; f = f->nxt) 460 { escape_el(f, e); 461 if (f == n->extent) 462 break; 463 } 464 } 465 466 static Element * 467 unless_seq(Lextok *n) 468 { SeqList *s = n->sl; 469 Element *e = new_el(ZN); 470 Element *t = new_el(nn(ZN,'.',ZN,ZN)); /* target */ 471 SeqList *z; 472 473 e->n = nn(n, UNLESS, ZN, ZN); 474 e->n->sl = s; /* info only */ 475 e->sub = s; 476 477 /* need 2 sequences: normal execution and escape */ 478 if (!s || !s->nxt || s->nxt->nxt) 479 fatal("unexpected unless structure", (char *)0); 480 481 /* append the target state to both */ 482 for (z = s; z; z = z->nxt) 483 add_el(t, z->this); 484 485 /* attach escapes to all states in normal sequence */ 486 attach_escape(s->this, s->nxt->this); 487 488 add_el(e, cur_s->this); 489 add_el(t, cur_s->this); 490 #ifdef DEBUG 491 printf("unless element (%d,%d):\n", e->Seqno, t->Seqno); 492 for (z = s; z; z = z->nxt) 493 { Element *x; printf("\t%d,%d,%d :: ", 494 z->this->frst->Seqno, 495 z->this->extent->Seqno, 496 z->this->last->Seqno); 497 for (x = z->this->frst; x; x = x->nxt) 498 printf("(%d)", x->Seqno); 499 printf("\n"); 500 } 501 #endif 502 return e; 503 } 504 505 Element * 506 mk_skip(void) 507 { Lextok *t = nn(ZN, CONST, ZN, ZN); 508 t->val = 1; 509 return new_el(nn(ZN, 'c', t, ZN)); 510 } 511 512 static void 513 add_el(Element *e, Sequence *s) 514 { 515 if (e->n->ntyp == GOTO) 516 { Symbol *z = has_lab(e, (1|2|4)); 517 if (z) 518 { Element *y; /* insert a skip */ 519 y = mk_skip(); 520 mov_lab(z, e, y); /* inherit label */ 521 add_el(y, s); 522 } } 523 #ifdef DEBUG 524 printf("add_el %d after %d -- ", 525 e->Seqno, (s->last)?s->last->Seqno:-1); 526 comment(stdout, e->n, 0); 527 printf("\n"); 528 #endif 529 if (!s->frst) 530 s->frst = e; 531 else 532 s->last->nxt = e; 533 s->last = e; 534 } 535 536 static Element * 537 colons(Lextok *n) 538 { 539 if (!n) 540 return ZE; 541 if (n->ntyp == ':') 542 { Element *e = colons(n->lft); 543 set_lab(n->sym, e); 544 return e; 545 } 546 innermost = n; 547 return new_el(n); 548 } 549 550 void 551 add_seq(Lextok *n) 552 { Element *e; 553 554 if (!n) return; 555 innermost = n; 556 e = colons(n); 557 if (innermost->ntyp != IF 558 && innermost->ntyp != DO 559 && innermost->ntyp != UNLESS) 560 add_el(e, cur_s->this); 561 } 562 563 void 564 set_lab(Symbol *s, Element *e) 565 { Label *l; extern Symbol *context; 566 567 if (!s) return; 568 for (l = labtab; l; l = l->nxt) 569 if (l->s == s && l->c == context) 570 { non_fatal("label %s redeclared", s->name); 571 break; 572 } 573 l = (Label *) emalloc(sizeof(Label)); 574 l->s = s; 575 l->c = context; 576 l->e = e; 577 l->nxt = labtab; 578 labtab = l; 579 } 580 581 Element * 582 get_lab(Lextok *n, int md) 583 { Label *l; 584 Symbol *s = n->sym; 585 586 for (l = labtab; l; l = l->nxt) 587 if (s == l->s) 588 return (l->e); 589 590 lineno = n->ln; 591 Fname = n->fn; 592 if (md) fatal("undefined label %s", s->name); 593 return ZE; 594 } 595 596 Symbol * 597 has_lab(Element *e, int special) 598 { Label *l; 599 600 for (l = labtab; l; l = l->nxt) 601 { if (e != l->e) 602 continue; 603 if (special == 0 604 || ((special&1) && !strncmp(l->s->name, "accept", 6)) 605 || ((special&2) && !strncmp(l->s->name, "end", 3)) 606 || ((special&4) && !strncmp(l->s->name, "progress", 8))) 607 return (l->s); 608 } 609 return ZS; 610 } 611 612 static void 613 mov_lab(Symbol *z, Element *e, Element *y) 614 { Label *l; 615 616 for (l = labtab; l; l = l->nxt) 617 if (e == l->e) 618 { l->e = y; 619 return; 620 } 621 if (e->n) 622 { lineno = e->n->ln; 623 Fname = e->n->fn; 624 } 625 fatal("cannot happen - mov_lab %s", z->name); 626 } 627 628 void 629 fix_dest(Symbol *c, Symbol *a) /* c:label name, a:proctype name */ 630 { Label *l; extern Symbol *context; 631 632 #if 0 633 printf("ref to label '%s' in proctype '%s', search:\n", 634 c->name, a->name); 635 for (l = labtab; l; l = l->nxt) 636 printf(" %s in %s\n", l->s->name, l->c->name); 637 #endif 638 639 for (l = labtab; l; l = l->nxt) 640 { if (strcmp(c->name, l->s->name) == 0 641 && strcmp(a->name, l->c->name) == 0) /* ? */ 642 break; 643 } 644 if (!l) 645 { printf("spin: label '%s' (proctype %s)\n", c->name, a->name); 646 non_fatal("unknown label '%s'", c->name); 647 if (context == a) 648 printf("spin: cannot remote ref a label inside the same proctype\n"); 649 return; 650 } 651 if (!l->e || !l->e->n) 652 fatal("fix_dest error (%s)", c->name); 653 if (l->e->n->ntyp == GOTO) 654 { Element *y = (Element *) emalloc(sizeof(Element)); 655 int keep_ln = l->e->n->ln; 656 Symbol *keep_fn = l->e->n->fn; 657 658 /* insert skip - or target is optimized away */ 659 y->n = l->e->n; /* copy of the goto */ 660 y->seqno = find_maxel(a); /* unique seqno within proc */ 661 y->nxt = l->e->nxt; 662 y->Seqno = Unique++; y->Nxt = Al_El; Al_El = y; 663 664 /* turn the original element+seqno into a skip */ 665 l->e->n = nn(ZN, 'c', nn(ZN, CONST, ZN, ZN), ZN); 666 l->e->n->ln = l->e->n->lft->ln = keep_ln; 667 l->e->n->fn = l->e->n->lft->fn = keep_fn; 668 l->e->n->lft->val = 1; 669 l->e->nxt = y; /* append the goto */ 670 } 671 l->e->status |= CHECK2; /* treat as if global */ 672 if (l->e->status & (ATOM | L_ATOM | D_ATOM)) 673 { non_fatal("cannot reference label inside atomic or d_step (%s)", 674 c->name); 675 } 676 } 677 678 int 679 find_lab(Symbol *s, Symbol *c, int markit) 680 { Label *l; 681 682 for (l = labtab; l; l = l->nxt) 683 { if (strcmp(s->name, l->s->name) == 0 684 && strcmp(c->name, l->c->name) == 0) 685 { l->visible |= markit; 686 return (l->e->seqno); 687 } } 688 return 0; 689 } 690 691 void 692 pushbreak(void) 693 { Lbreak *r = (Lbreak *) emalloc(sizeof(Lbreak)); 694 Symbol *l; 695 char buf[64]; 696 697 sprintf(buf, ":b%d", break_id++); 698 l = lookup(buf); 699 r->l = l; 700 r->nxt = breakstack; 701 breakstack = r; 702 } 703 704 Symbol * 705 break_dest(void) 706 { 707 if (!breakstack) 708 fatal("misplaced break statement", (char *)0); 709 return breakstack->l; 710 } 711 712 void 713 make_atomic(Sequence *s, int added) 714 { Element *f; 715 716 walk_atomic(s->frst, s->last, added); 717 718 f = s->last; 719 switch (f->n->ntyp) { /* is last step basic stmnt or sequence ? */ 720 case NON_ATOMIC: 721 case ATOMIC: 722 /* redo and search for the last step of that sequence */ 723 make_atomic(f->n->sl->this, added); 724 break; 725 726 case UNLESS: 727 /* escapes are folded into main sequence */ 728 make_atomic(f->sub->this, added); 729 break; 730 731 default: 732 f->status &= ~ATOM; 733 f->status |= L_ATOM; 734 break; 735 } 736 } 737 738 static void 739 walk_atomic(Element *a, Element *b, int added) 740 { Element *f; Symbol *ofn; int oln; 741 SeqList *h; 742 743 ofn = Fname; 744 oln = lineno; 745 for (f = a; ; f = f->nxt) 746 { f->status |= (ATOM|added); 747 switch (f->n->ntyp) { 748 case ATOMIC: 749 if (verbose&32) 750 printf("spin: warning, line %3d %s, atomic inside %s (ignored)\n", 751 f->n->ln, f->n->fn->name, (added)?"d_step":"atomic"); 752 goto mknonat; 753 case D_STEP: 754 if (!(verbose&32)) 755 { if (added) goto mknonat; 756 break; 757 } 758 printf("spin: warning, line %3d %s, d_step inside ", 759 f->n->ln, f->n->fn->name); 760 if (added) 761 { printf("d_step (ignored)\n"); 762 goto mknonat; 763 } 764 printf("atomic\n"); 765 break; 766 case NON_ATOMIC: 767 mknonat: f->n->ntyp = NON_ATOMIC; /* can jump here */ 768 h = f->n->sl; 769 walk_atomic(h->this->frst, h->this->last, added); 770 break; 771 case UNLESS: 772 if (added) 773 { printf("spin: error, line %3d %s, unless in d_step (ignored)\n", 774 f->n->ln, f->n->fn->name); 775 } 776 } 777 for (h = f->sub; h; h = h->nxt) 778 walk_atomic(h->this->frst, h->this->last, added); 779 if (f == b) 780 break; 781 } 782 Fname = ofn; 783 lineno = oln; 784 } 785 786 void 787 dumplabels(void) 788 { Label *l; 789 790 for (l = labtab; l; l = l->nxt) 791 if (l->c != 0 && l->s->name[0] != ':') 792 printf("label %s %d <%s>\n", 793 l->s->name, l->e->seqno, l->c->name); 794 } 795