|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1980 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char sccsid[] = "@(#)stab.c 5.3 (Berkeley) 1/3/88"; ! 9: #endif not lint ! 10: ! 11: /* ! 12: * Procedures to put out symbol table information ! 13: * and stabs for separate compilation type checking. ! 14: * These use the .stabs, .stabn, and .stabd directives. ! 15: */ ! 16: ! 17: #include "whoami.h" ! 18: #ifdef PC ! 19: /* and the rest of the file */ ! 20: # include "0.h" ! 21: # include "objfmt.h" ! 22: # include "yy.h" ! 23: # include <stab.h> ! 24: ! 25: /* ! 26: * additional symbol definition for <stab.h> ! 27: * that is used by the separate compilation facility -- ! 28: * eventually, <stab.h> should be updated to include this ! 29: */ ! 30: ! 31: # include "pstab.h" ! 32: # include "pc.h" ! 33: ! 34: ! 35: #define private static ! 36: ! 37: int oldway = 0; ! 38: ! 39: /* ! 40: * absolute value: line numbers are negative if error recovery. ! 41: */ ! 42: #define ABS( x ) ( x < 0 ? -x : x ) ! 43: long checksum(); ! 44: ! 45: /* ! 46: * Generate information about variables. ! 47: */ ! 48: ! 49: stabgvar (p, length, line) ! 50: struct nl *p; ! 51: int length, line; ! 52: { ! 53: putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x", ! 54: 0, p->symbol, N_PC, N_PGVAR, ABS(line) ! 55: ); ! 56: if (oldway != 0) { ! 57: oldstabgvar(p->symbol, p2type(p->type), 0, length, line); ! 58: } else if (opt('g')) { ! 59: putprintf("\t.stabs\t\"%s:G", 1, p->symbol); ! 60: gentype(p->type); ! 61: putprintf("\",0x%x,0,0x%x,0", 0, N_GSYM, length); ! 62: } ! 63: } ! 64: ! 65: stablvar (p, offset, length) ! 66: struct nl *p; ! 67: int offset, length; ! 68: { ! 69: int level; ! 70: ! 71: level = (p->nl_block & 037); ! 72: if (oldway != 0) { ! 73: oldstablvar(p->symbol, p2type(p->type), level, offset, length); ! 74: } else if (opt('g')) { ! 75: putprintf("\t.stabs\t\"%s:", 1, p->symbol); ! 76: gentype(p->type); ! 77: putprintf("\",0x%x,0,0x%x,0x%x", 0, N_LSYM, length, offset); ! 78: } ! 79: } ! 80: ! 81: /* ! 82: * global variables ! 83: */ ! 84: /*ARGSUSED*/ ! 85: oldstabgvar( name , type , offset , length , line ) ! 86: char *name; ! 87: int type; ! 88: int offset; ! 89: int length; ! 90: int line; ! 91: { ! 92: if ( ! opt('g') ) { ! 93: return; ! 94: } ! 95: putprintf( " .stabs \"" , 1 ); ! 96: putprintf( NAMEFORMAT , 1 , (int) name ); ! 97: putprintf( "\",0x%x,0,0x%x,0" , 0 , N_GSYM , type ); ! 98: putprintf( " .stabs \"" , 1 ); ! 99: putprintf( NAMEFORMAT , 1 , (int) name ); ! 100: putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length ); ! 101: } ! 102: ! 103: /* ! 104: * local variables ! 105: */ ! 106: /*ARGSUSED*/ ! 107: oldstablvar( name , type , level , offset , length ) ! 108: char *name; ! 109: int type; ! 110: int level; ! 111: int offset; ! 112: int length; ! 113: { ! 114: ! 115: if ( ! opt('g') ) { ! 116: return; ! 117: } ! 118: putprintf( " .stabs \"" , 1 ); ! 119: putprintf( NAMEFORMAT , 1 , (int) name ); ! 120: putprintf( "\",0x%x,0,0x%x,0x%x" , 0 , N_LSYM , type , -offset ); ! 121: putprintf( " .stabs \"" , 1 ); ! 122: putprintf( NAMEFORMAT , 1 , (int) name ); ! 123: putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length ); ! 124: } ! 125: ! 126: ! 127: stabparam (p, offset, length) ! 128: struct nl *p; ! 129: int offset, length; ! 130: { ! 131: if (oldway != 0) { ! 132: oldstabparam(p->symbol, p2type(p->type), offset, length); ! 133: } else if (opt('g')) { ! 134: putprintf("\t.stabs\t\"%s:", 1, p->symbol); ! 135: if (p->class == REF) { ! 136: putprintf("v", 1); ! 137: } else { ! 138: putprintf("p", 1); ! 139: } ! 140: gentype((p->class == FPROC || p->class ==FFUNC) ? p : p->type); ! 141: putprintf("\",0x%x,0,0x%x,0x%x", 0, N_PSYM, length, offset); ! 142: } ! 143: } ! 144: ! 145: /* ! 146: * parameters ! 147: */ ! 148: oldstabparam( name , type , offset , length ) ! 149: char *name; ! 150: int type; ! 151: int offset; ! 152: int length; ! 153: { ! 154: ! 155: if ( ! opt('g') ) { ! 156: return; ! 157: } ! 158: putprintf( " .stabs \"" , 1 ); ! 159: putprintf( NAMEFORMAT , 1 , (int) name ); ! 160: putprintf( "\",0x%x,0,0x%x,0x%x" , 0 , N_PSYM , type , offset ); ! 161: putprintf( " .stabs \"" , 1 ); ! 162: putprintf( NAMEFORMAT , 1 , (int) name ); ! 163: putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length ); ! 164: } ! 165: ! 166: /* ! 167: * fields ! 168: */ ! 169: ! 170: /* ! 171: * left brackets ! 172: * (dbx handles module-2 without these, so we won't use them either) ! 173: */ ! 174: stablbrac( level ) ! 175: int level; ! 176: { ! 177: ! 178: if ( ! opt('g') || oldway == 0 ) { ! 179: return; ! 180: } ! 181: putprintf( " .stabd 0x%x,0,0x%x" , 0 , N_LBRAC , level ); ! 182: } ! 183: ! 184: /* ! 185: * right brackets ! 186: */ ! 187: stabrbrac( level ) ! 188: int level; ! 189: { ! 190: ! 191: if ( ! opt('g') || oldway == 0 ) { ! 192: return; ! 193: } ! 194: putprintf( " .stabd 0x%x,0,0x%x" , 0 , N_RBRAC , level ); ! 195: } ! 196: ! 197: stabfunc (p, name, line, level) ! 198: struct nl *p; ! 199: char *name; ! 200: int line, level; ! 201: { ! 202: char extname[BUFSIZ],nestspec[BUFSIZ]; ! 203: ! 204: if ( level == 1 ) { ! 205: if (p->class == FUNC) { ! 206: putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x" , ! 207: 0 , name , N_PC , N_PGFUNC , ABS( line ) ! 208: ); ! 209: } else if (p->class == PROC) { ! 210: putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x" , ! 211: 0 , name , N_PC , N_PGPROC , ABS( line ) ! 212: ); ! 213: } ! 214: } ! 215: if (oldway != 0) { ! 216: oldstabfunc(name, p->class, line, level); ! 217: } else if (opt('g')) { ! 218: putprintf("\t.stabs\t\"%s:", 1, name); ! 219: if (p->class == FUNC) { ! 220: putprintf("F", 1); ! 221: gentype(p->type); ! 222: putprintf(",", 1); ! 223: } else { ! 224: putprintf("P,", 1); ! 225: } ! 226: sextname(extname, name, level); /* set extname to entry label */ ! 227: putprintf("%s,", 1, &(extname[1])); /* remove initial underbar */ ! 228: snestspec(nestspec, level); ! 229: putprintf("%s\",0x%x,0,0,%s", 0, nestspec, N_FUN, extname); ! 230: } ! 231: } ! 232: ! 233: /* ! 234: * construct the colon-separated static nesting string into a ! 235: * caller-supplied buffer ! 236: */ ! 237: private snestspec(buffer, level) ! 238: char buffer[]; ! 239: int level; ! 240: { ! 241: char *starthere; ! 242: int i; ! 243: ! 244: if (level <= 1) { ! 245: buffer[0] = '\0'; ! 246: } else { ! 247: starthere = &buffer[0]; ! 248: for ( i = 1 ; i < level ; i++ ) { ! 249: sprintf(starthere, "%s:", enclosing[i]); ! 250: starthere += strlen(enclosing[i]) + 1; ! 251: } ! 252: *--starthere = '\0'; /* remove last colon */ ! 253: if (starthere >= &buffer[BUFSIZ-1]) { ! 254: panic("snestspec"); ! 255: } ! 256: } ! 257: } ! 258: ! 259: /* ! 260: * functions ! 261: */ ! 262: oldstabfunc( name , typeclass , line , level ) ! 263: char *name; ! 264: int typeclass; ! 265: int line; ! 266: long level; ! 267: { ! 268: char extname[ BUFSIZ ]; ! 269: ! 270: /* ! 271: * for sdb ! 272: */ ! 273: if ( ! opt('g') ) { ! 274: return; ! 275: } ! 276: putprintf( " .stabs \"" , 1 ); ! 277: putprintf( NAMEFORMAT , 1 , (int) name ); ! 278: sextname( extname , name , (int) level ); ! 279: putprintf( "\",0x%x,0,0x%x,%s" , 0 , N_FUN , line , (int) extname ); ! 280: } ! 281: ! 282: /* ! 283: * source line numbers ! 284: */ ! 285: stabline( line ) ! 286: int line; ! 287: { ! 288: if ( ! opt('g') ) { ! 289: return; ! 290: } ! 291: putprintf( " .stabd 0x%x,0,0x%x" , 0 , N_SLINE , ABS( line ) ); ! 292: } ! 293: ! 294: /* ! 295: * source files get none or more of these: ! 296: * one as they are entered, ! 297: * and one every time they are returned to from nested #includes ! 298: */ ! 299: stabsource(filename, firsttime) ! 300: char *filename; ! 301: bool firsttime; ! 302: { ! 303: int label; ! 304: ! 305: /* ! 306: * for separate compilation ! 307: */ ! 308: putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x", 0, ! 309: (int) filename, N_PC, N_PSO, N_FLAGCHECKSUM); ! 310: /* ! 311: * for debugger ! 312: */ ! 313: if ( ! opt('g') ) { ! 314: return; ! 315: } ! 316: if (oldway != 0) { ! 317: label = (int) getlab(); ! 318: putprintf( " .stabs \"" , 1 ); ! 319: putprintf( NAMEFORMAT , 1 , filename ); ! 320: putprintf( "\",0x%x,0,0," , 1 , N_SO ); ! 321: putprintf( PREFIXFORMAT , 0 , LLABELPREFIX , label ); ! 322: putprintf( PREFIXFORMAT , 1 , LLABELPREFIX , label ); ! 323: putprintf( ":" , 0 ); ! 324: } else { ! 325: if (firsttime) { ! 326: putprintf( " .stabs \"" , 1 ); ! 327: putprintf( NAMEFORMAT , 1 , filename ); ! 328: putprintf( "\",0x%x,0,0,0" , 0 , N_SO ); ! 329: } ! 330: } ! 331: } ! 332: ! 333: /* ! 334: * included files get one or more of these: ! 335: * one as they are entered by a #include, ! 336: * and one every time they are returned to from nested #includes. ! 337: */ ! 338: stabinclude(filename, firsttime) ! 339: char *filename; ! 340: bool firsttime; ! 341: { ! 342: int label; ! 343: long check; ! 344: ! 345: /* ! 346: * for separate compilation ! 347: */ ! 348: if (firsttime) { ! 349: check = checksum(filename); ! 350: } else { ! 351: check = N_FLAGCHECKSUM; ! 352: } ! 353: putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x", 0, ! 354: (int) filename, N_PC, N_PSOL, check); ! 355: /* ! 356: * for sdb ! 357: */ ! 358: if ( ! opt('g') ) { ! 359: return; ! 360: } ! 361: if (oldway != 0) { ! 362: label = (int) getlab(); ! 363: putprintf( " .stabs \"" , 1 ); ! 364: putprintf( NAMEFORMAT , 1 , filename ); ! 365: putprintf( "\",0x%x,0,0," , 1 , N_SOL ); ! 366: putprintf( PREFIXFORMAT , 0 , LLABELPREFIX , label ); ! 367: putprintf( PREFIXFORMAT , 1 , LLABELPREFIX , label ); ! 368: putprintf( ":" , 0 ); ! 369: } ! 370: } ! 371: ! 372: /* ! 373: * anyone know a good checksum for ascii files? ! 374: * this does a rotate-left and then exclusive-or's in the character. ! 375: * also, it avoids returning checksums of 0. ! 376: * The rotate is implemented by shifting and adding back the ! 377: * sign bit when negative. ! 378: */ ! 379: long ! 380: checksum(filename) ! 381: char *filename; ! 382: { ! 383: FILE *filep; ! 384: register int input; ! 385: register long check; ! 386: ! 387: filep = fopen(filename, "r"); ! 388: if (filep == NULL) { ! 389: perror(filename); ! 390: pexit(DIED); ! 391: } ! 392: check = 0; ! 393: while ((input = getc(filep)) != EOF) { ! 394: if (check < 0) { ! 395: check <<= 1; ! 396: check += 1; ! 397: } else { ! 398: check <<= 1; ! 399: } ! 400: check ^= input; ! 401: } ! 402: (void) fclose(filep); ! 403: if ((unsigned) check <= N_FLAGCHECKSUM) { ! 404: return N_FLAGCHECKSUM + 1; ! 405: } else { ! 406: return check; ! 407: } ! 408: } ! 409: ! 410: /* ! 411: * global Pascal symbols : ! 412: * labels, types, constants, and external procedure and function names: ! 413: * These are used by the separate compilation facility ! 414: * to be able to check for disjoint header files. ! 415: */ ! 416: ! 417: /* ! 418: * global labels ! 419: */ ! 420: stabglabel( label , line ) ! 421: char *label; ! 422: int line; ! 423: { ! 424: ! 425: putprintf( " .stabs \"%s\",0x%x,0,0x%x,0x%x" , 0 ! 426: , (int) label , N_PC , N_PGLABEL , ABS( line ) ); ! 427: } ! 428: ! 429: /* ! 430: * global constants ! 431: */ ! 432: stabgconst( constant , line ) ! 433: char *constant; ! 434: int line; ! 435: { ! 436: ! 437: putprintf( " .stabs \"%s\",0x%x,0,0x%x,0x%x" , 0 ! 438: , (int) constant , N_PC , N_PGCONST , ABS( line ) ); ! 439: } ! 440: ! 441: /* ! 442: * Generate symbolic information about a constant. ! 443: */ ! 444: ! 445: stabconst (c) ! 446: struct nl *c; ! 447: { ! 448: if (opt('g') && oldway == 0) { ! 449: putprintf("\t.stabs\t\"%s:c=", 1, c->symbol); ! 450: if (c->type == nl + TSTR) { ! 451: putprintf("s'%s'", 1, c->ptr[0]); ! 452: } else if (c->type == nl + T1CHAR) { ! 453: putprintf("c%d", 1, c->range[0]); ! 454: } else if (isa(c->type, "i")) { ! 455: putprintf("i%d", 1, c->range[0]); ! 456: } else if (isa(c->type, "d")) { ! 457: putprintf("r%g", 1, c->real); ! 458: } else { ! 459: putprintf("e", 1); ! 460: gentype(c->type); ! 461: putprintf(",%d", 1, c->range[0]); ! 462: } ! 463: putprintf("\",0x%x,0,0x%x,0x%x", 0, N_LSYM, 0, 0); ! 464: } ! 465: } ! 466: ! 467: stabgtype (name, type, line) ! 468: char *name; ! 469: struct nl *type; ! 470: int line; ! 471: { ! 472: putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x" , ! 473: 0, name, N_PC , N_PGTYPE, ABS(line) ! 474: ); ! 475: if (oldway == 0) { ! 476: stabltype(name, type); ! 477: } ! 478: } ! 479: ! 480: stabltype (name, type) ! 481: char *name; ! 482: struct nl *type; ! 483: { ! 484: if (opt('g')) { ! 485: putprintf("\t.stabs\t\"%s:t", 1, name); ! 486: gentype(type); ! 487: putprintf("\",0x%x,0,0,0", 0, N_LSYM); ! 488: } ! 489: } ! 490: ! 491: /* ! 492: * external functions and procedures ! 493: */ ! 494: stabefunc( name , typeclass , line ) ! 495: char *name; ! 496: int typeclass; ! 497: int line; ! 498: { ! 499: int type; ! 500: ! 501: if ( typeclass == FUNC ) { ! 502: type = N_PEFUNC; ! 503: } else if ( typeclass == PROC ) { ! 504: type = N_PEPROC; ! 505: } else { ! 506: return; ! 507: } ! 508: putprintf( " .stabs \"%s\",0x%x,0,0x%x,0x%x" , 0 ! 509: , (int) name , N_PC , type , ABS( line ) ); ! 510: } ! 511: ! 512: /* ! 513: * Generate type information encoded as a string for dbx. ! 514: * The fwdptrnum field is used only when the type is a pointer ! 515: * to a type that isn't known when it was entered. When the ! 516: * type field is filled for some such tptr, fixfwdtype should ! 517: * be called to output an equivalencing type definition. ! 518: */ ! 519: ! 520: typedef struct TypeDesc *TypeDesc; ! 521: ! 522: struct TypeDesc { ! 523: struct nl *tptr; ! 524: int tnum; ! 525: int fwdptrnum; ! 526: TypeDesc chain; ! 527: }; ! 528: ! 529: #define TABLESIZE 2003 ! 530: ! 531: #define typehash(t) ( ( ((int) t) >> 2 ) % TABLESIZE ) ! 532: ! 533: private int tcount = 1; ! 534: private TypeDesc typetable[TABLESIZE]; ! 535: ! 536: private TypeDesc tdlookup (t) ! 537: struct nl *t; ! 538: { ! 539: register TypeDesc td; ! 540: ! 541: td = typetable[typehash(t)]; ! 542: while (td != NIL && td->tptr != t) { ! 543: td = td->chain; ! 544: } ! 545: return td; ! 546: } ! 547: ! 548: private int typelookup (t) ! 549: struct nl *t; ! 550: { ! 551: register TypeDesc td; ! 552: int r; ! 553: ! 554: td = tdlookup(t); ! 555: if (td == NIL) { ! 556: r = 0; ! 557: } else { ! 558: r = td->tnum; ! 559: } ! 560: return r; ! 561: } ! 562: ! 563: private int entertype (type) ! 564: struct nl *type; ! 565: { ! 566: register TypeDesc td; ! 567: register int i; ! 568: ! 569: td = (TypeDesc) malloc(sizeof(struct TypeDesc)); ! 570: td->tptr = type; ! 571: td->tnum = tcount; ! 572: td->fwdptrnum = 0; ! 573: ++tcount; ! 574: i = typehash(type); ! 575: td->chain = typetable[i]; ! 576: typetable[i] = td; ! 577: return td->tnum; ! 578: } ! 579: ! 580: /* ! 581: * The in_types table currently contains "boolean", "char", "integer", ! 582: * "real" and "_nil". (See nl.c for definition.) ! 583: * The lookup call below will give the TYPE class nl entry for these ! 584: * types. In each case except _nil, the type field of that entry is a RANGE ! 585: * class nl entry for the type. Sometimes other symbol table entries ! 586: * point to the TYPE entry (e.g., when there is a range over the base type), ! 587: * and other entries point to the RANGE entry (e.g., for a variable of the ! 588: * given type). We don't really want to distinguish between these uses ! 589: * in dbx, and since it appears that the RANGE entries are not reused if ! 590: * a range happens to coincide, we will give the two the same identifying ! 591: * dbx type number. ! 592: */ ! 593: ! 594: private inittypes() ! 595: { ! 596: int i; ! 597: extern char *in_types[]; ! 598: struct nl *p; ! 599: ! 600: for (i = 0; in_types[i] != NIL; i++) { ! 601: p = lookup(in_types[i]); ! 602: if (p != NIL) { ! 603: entertype(p); ! 604: if (p->type != NIL) { ! 605: --tcount; /* see comment above */ ! 606: entertype(p->type); ! 607: } ! 608: } ! 609: } ! 610: } ! 611: ! 612: static genarray (t) ! 613: struct nl *t; ! 614: { ! 615: register struct nl *p; ! 616: ! 617: for (p = t->chain; p != NIL; p = p->chain) { ! 618: putprintf("a", 1); ! 619: gentype(p); ! 620: putprintf(";", 1); ! 621: } ! 622: gentype(t->type); ! 623: } ! 624: ! 625: /* ! 626: * Really we should walk through ptr[NL_FIELDLIST] for the fields, ! 627: * and then do the variant tag and fields separately, but dbx ! 628: * doesn't support this yet. ! 629: * So, since all the fields of all the variants are on the chain, ! 630: * we walk through that. Except that this gives the fields in the ! 631: * reverse order, so we want to print in reverse order. ! 632: */ ! 633: ! 634: static genrecord (t) ! 635: struct nl *t; ! 636: { ! 637: putprintf("s%d", 1, t->value[NL_OFFS]); ! 638: if (t->chain != NIL) { ! 639: genrecfield(t->chain, 1); ! 640: } ! 641: putprintf(";", 1); ! 642: } ! 643: ! 644: static genrecfield (t, n) ! 645: struct nl *t; ! 646: int n; ! 647: { ! 648: if (t->chain != NULL) { ! 649: genrecfield(t->chain, n + 1); ! 650: if (n % 2 == 0) { ! 651: gencontinue(); ! 652: } ! 653: } ! 654: putprintf("%s:", 1, t->symbol); ! 655: gentype(t->type); ! 656: putprintf(",%d,%d;", 1, 8*t->value[NL_OFFS], 8*lwidth(t->type)); ! 657: } ! 658: ! 659: static genvarnt (t) ! 660: struct nl *t; ! 661: { ! 662: genrecord(t); ! 663: } ! 664: ! 665: static genptr (t) ! 666: struct nl *t; ! 667: { ! 668: register TypeDesc td; ! 669: ! 670: putprintf("*", 1); ! 671: if (t->type != NIL) { ! 672: gentype(t->type); ! 673: } else { ! 674: /* ! 675: * unresolved forward pointer: use tcount to represent what is ! 676: * begin pointed to, to be defined later ! 677: */ ! 678: td = tdlookup(t); ! 679: if (td == NIL) { ! 680: panic("nil ptr in stab.genptr"); ! 681: } ! 682: td->fwdptrnum = tcount; ! 683: putprintf("%d", 1, tcount); ! 684: ++tcount; ! 685: } ! 686: } ! 687: ! 688: /* ! 689: * The type t is a pointer which has just had its type field filled. ! 690: * We need to generate a type stab saying that the number saved ! 691: * in t's fwdptrnum is the same as the t->type's number ! 692: */ ! 693: ! 694: fixfwdtype (t) ! 695: struct nl *t; ! 696: { ! 697: register TypeDesc td; ! 698: ! 699: if (opt('g') && oldway == 0) { ! 700: td = tdlookup(t); ! 701: if (td != NIL) { ! 702: putprintf("\t.stabs\t\":t%d=", 1, td->fwdptrnum); ! 703: gentype(t->type); ! 704: putprintf("\",0x%x,0,0,0", 0, N_LSYM); ! 705: } ! 706: } ! 707: } ! 708: ! 709: static genenum (t) ! 710: struct nl *t; ! 711: { ! 712: register struct nl *e; ! 713: register int i; ! 714: ! 715: putprintf("e", 1); ! 716: i = 1; ! 717: e = t->chain; ! 718: while (e != NULL) { ! 719: if (i > 2) { ! 720: gencontinue(); ! 721: i = 0; ! 722: } ! 723: putprintf("%s:%d,", 1, e->symbol, e->range[0]); ! 724: e = e->chain; ! 725: ++i; ! 726: } ! 727: putprintf(";", 1); ! 728: } ! 729: ! 730: static genset (t) ! 731: struct nl *t; ! 732: { ! 733: putprintf("S", 1); ! 734: gentype(t->type); ! 735: } ! 736: ! 737: static genrange (t) ! 738: struct nl *t; ! 739: { ! 740: putprintf("r", 1); ! 741: gentype(t->type); ! 742: putprintf(";%d;%d", 1, t->range[0], t->range[1]); ! 743: } ! 744: ! 745: static genfparam (t) ! 746: struct nl *t; ! 747: { ! 748: struct nl *p; ! 749: int count; ! 750: ! 751: if (t->type != NULL) { ! 752: putprintf("f", 1); ! 753: gentype(t->type); ! 754: putprintf(",", 1); ! 755: } else { ! 756: putprintf("p", 1); ! 757: } ! 758: count = 0; ! 759: for (p = t->ptr[NL_FCHAIN]; p != NULL; p = p->chain) { ! 760: ++count; ! 761: } ! 762: putprintf("%d;", 1, count); ! 763: for (p = t->ptr[NL_FCHAIN]; p != NULL; p = p->chain) { ! 764: gentype(p->type); ! 765: putprintf(",%d;", 1, p->class); ! 766: } ! 767: } ! 768: ! 769: static genfile (t) ! 770: struct nl *t; ! 771: { ! 772: putprintf("d", 1); ! 773: gentype(t->type); ! 774: } ! 775: ! 776: static gentype (t) ! 777: struct nl *t; ! 778: { ! 779: int id; ! 780: ! 781: if (tcount == 1) { ! 782: inittypes(); ! 783: } ! 784: id = typelookup(t); ! 785: if (id != 0) { ! 786: putprintf("%d", 1, id); ! 787: } else if (t->class == SCAL && t->chain == NULL) { ! 788: id = typelookup(t->type); ! 789: if (id != 0) { ! 790: putprintf("%d", 1, id); ! 791: } else { ! 792: genenum(t->type); ! 793: } ! 794: } else { ! 795: id = entertype(t); ! 796: putprintf("%d=", 1, id); ! 797: switch (t->class) { ! 798: case TYPE: ! 799: gentype(t->type); ! 800: break; ! 801: ! 802: case ARRAY: ! 803: genarray(t); ! 804: break; ! 805: ! 806: case RECORD: ! 807: genrecord(t); ! 808: break; ! 809: ! 810: case VARNT: ! 811: genvarnt(t); ! 812: break; ! 813: ! 814: case REF: ! 815: gentype(t->type); ! 816: break; ! 817: ! 818: case PTR: ! 819: genptr(t); ! 820: break; ! 821: ! 822: case SET: ! 823: genset(t); ! 824: break; ! 825: ! 826: case RANGE: ! 827: genrange(t); ! 828: break; ! 829: ! 830: case SCAL: ! 831: genenum(t); ! 832: break; ! 833: ! 834: case FPROC: ! 835: case FFUNC: ! 836: genfparam(t); ! 837: break; ! 838: ! 839: case FILET: ! 840: case PTRFILE: ! 841: genfile(t); ! 842: break; ! 843: ! 844: default: ! 845: /* This shouldn't happen */ ! 846: /* Rather than bomb outright, let debugging go on */ ! 847: warning(); ! 848: error("Bad type class found in stab"); ! 849: putprintf("1", 1, t->class); ! 850: break; ! 851: } ! 852: } ! 853: } ! 854: ! 855: /* ! 856: * Continue stab information in a namelist new entry. This is necessary ! 857: * to avoid overflowing putprintf's buffer. ! 858: */ ! 859: ! 860: static gencontinue () ! 861: { ! 862: putprintf("?\",0x%x,0,0,0", 0, N_LSYM); ! 863: putprintf("\t.stabs\t\"", 1); ! 864: } ! 865: ! 866: #endif PC
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.