1826Speter /* Copyright (c) 1980 Regents of the University of California */ 2772Speter 3*18355Smckusick #ifndef lint 4*18355Smckusick static char sccsid[] = "@(#)stab.c 2.3 03/15/85"; 5*18355Smckusick #endif 6826Speter 7772Speter /* 818354Smckusick * Procedures to put out symbol table information 9826Speter * and stabs for separate compilation type checking. 1018354Smckusick * These use the .stabs, .stabn, and .stabd directives. 11772Speter */ 12772Speter 13772Speter #include "whoami.h" 14772Speter #ifdef PC 15772Speter /* and the rest of the file */ 16772Speter # include "0.h" 1710649Speter # include "objfmt.h" 1815952Smckusick # include "yy.h" 19772Speter # include <stab.h> 20772Speter 21842Speter /* 22842Speter * additional symbol definition for <stab.h> 23842Speter * that is used by the separate compilation facility -- 24842Speter * eventually, <stab.h> should be updated to include this 25842Speter */ 26772Speter 27842Speter # include "pstab.h" 28772Speter # include "pc.h" 29772Speter 3018354Smckusick 3118354Smckusick #define private static 3218354Smckusick 3318354Smckusick int oldway = 0; 3418354Smckusick 35772Speter /* 36826Speter * absolute value: line numbers are negative if error recovery. 37826Speter */ 38826Speter #define ABS( x ) ( x < 0 ? -x : x ) 39*18355Smckusick long checksum(); 40826Speter 4118354Smckusick /* 4218354Smckusick * Generate information about variables. 4318354Smckusick */ 4418354Smckusick 4518354Smckusick stabgvar (p, length, line) 4618354Smckusick struct nl *p; 4718354Smckusick int length, line; 4818354Smckusick { 4918354Smckusick putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x", 5018354Smckusick 0, p->symbol, N_PC, N_PGVAR, ABS(line) 5118354Smckusick ); 5218354Smckusick if (oldway != 0) { 5318354Smckusick oldstabgvar(p->symbol, p2type(p->type), 0, length, line); 5418354Smckusick } else if (opt('g')) { 5518354Smckusick putprintf("\t.stabs\t\"%s:G", 1, p->symbol); 5618354Smckusick gentype(p->type); 5718354Smckusick putprintf("\",0x%x,0,0x%x,0", 0, N_GSYM, length); 5818354Smckusick } 5918354Smckusick } 6018354Smckusick 6118354Smckusick stablvar (p, offset, length) 6218354Smckusick struct nl *p; 6318354Smckusick int offset, length; 6418354Smckusick { 6518354Smckusick int level; 6618354Smckusick 6718354Smckusick level = (p->nl_block & 037); 6818354Smckusick if (oldway != 0) { 6918354Smckusick oldstablvar(p->symbol, p2type(p->type), level, offset, length); 7018354Smckusick } else if (opt('g')) { 7118354Smckusick putprintf("\t.stabs\t\"%s:", 1, p->symbol); 7218354Smckusick gentype(p->type); 7318354Smckusick putprintf("\",0x%x,0,0x%x,0x%x", 0, N_LSYM, length, offset); 7418354Smckusick } 7518354Smckusick } 7618354Smckusick 77826Speter /* 782164Speter * global variables 79772Speter */ 80*18355Smckusick /*ARGSUSED*/ 8118354Smckusick oldstabgvar( name , type , offset , length , line ) 82772Speter char *name; 83772Speter int type; 84772Speter int offset; 85772Speter int length; 86826Speter int line; 87772Speter { 88772Speter if ( ! opt('g') ) { 89772Speter return; 90772Speter } 91772Speter putprintf( " .stabs \"" , 1 ); 92*18355Smckusick putprintf( NAMEFORMAT , 1 , (int) name ); 932164Speter putprintf( "\",0x%x,0,0x%x,0" , 0 , N_GSYM , type ); 942164Speter putprintf( " .stabs \"" , 1 ); 95*18355Smckusick putprintf( NAMEFORMAT , 1 , (int) name ); 962164Speter putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length ); 972164Speter } 982164Speter 992164Speter /* 1002164Speter * local variables 1012164Speter */ 102*18355Smckusick /*ARGSUSED*/ 10318354Smckusick oldstablvar( name , type , level , offset , length ) 1042164Speter char *name; 1052164Speter int type; 1062164Speter int level; 1072164Speter int offset; 1082164Speter int length; 1092164Speter { 1102164Speter 1112164Speter if ( ! opt('g') ) { 1122164Speter return; 113772Speter } 114772Speter putprintf( " .stabs \"" , 1 ); 115*18355Smckusick putprintf( NAMEFORMAT , 1 , (int) name ); 1162164Speter putprintf( "\",0x%x,0,0x%x,0x%x" , 0 , N_LSYM , type , -offset ); 1172164Speter putprintf( " .stabs \"" , 1 ); 118*18355Smckusick putprintf( NAMEFORMAT , 1 , (int) name ); 119826Speter putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length ); 120772Speter } 121772Speter 122772Speter 12318354Smckusick stabparam (p, offset, length) 12418354Smckusick struct nl *p; 12518354Smckusick int offset, length; 12618354Smckusick { 12718354Smckusick if (oldway != 0) { 12818354Smckusick oldstabparam(p->symbol, p2type(p->type), offset, length); 12918354Smckusick } else if (opt('g')) { 13018354Smckusick putprintf("\t.stabs\t\"%s:", 1, p->symbol); 13118354Smckusick if (p->class == REF) { 13218354Smckusick putprintf("v", 1); 13318354Smckusick } else { 13418354Smckusick putprintf("p", 1); 13518354Smckusick } 13618354Smckusick gentype((p->class == FPROC || p->class ==FFUNC) ? p : p->type); 13718354Smckusick putprintf("\",0x%x,0,0x%x,0x%x", 0, N_PSYM, length, offset); 13818354Smckusick } 13918354Smckusick } 14018354Smckusick 141772Speter /* 142772Speter * parameters 143772Speter */ 14418354Smckusick oldstabparam( name , type , offset , length ) 145772Speter char *name; 146772Speter int type; 147772Speter int offset; 148772Speter int length; 149772Speter { 150772Speter 151772Speter if ( ! opt('g') ) { 152772Speter return; 153772Speter } 154772Speter putprintf( " .stabs \"" , 1 ); 155*18355Smckusick putprintf( NAMEFORMAT , 1 , (int) name ); 156826Speter putprintf( "\",0x%x,0,0x%x,0x%x" , 0 , N_PSYM , type , offset ); 157772Speter putprintf( " .stabs \"" , 1 ); 158*18355Smckusick putprintf( NAMEFORMAT , 1 , (int) name ); 159826Speter putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length ); 160772Speter } 161772Speter 162772Speter /* 163772Speter * fields 164772Speter */ 165772Speter 166772Speter /* 167772Speter * left brackets 16818354Smckusick * (dbx handles module-2 without these, so we won't use them either) 169772Speter */ 170772Speter stablbrac( level ) 171772Speter int level; 172772Speter { 173772Speter 17418354Smckusick if ( ! opt('g') || oldway == 0 ) { 175772Speter return; 176772Speter } 177826Speter putprintf( " .stabd 0x%x,0,0x%x" , 0 , N_LBRAC , level ); 178772Speter } 179772Speter 180772Speter /* 181772Speter * right brackets 182772Speter */ 183772Speter stabrbrac( level ) 184772Speter int level; 185772Speter { 186772Speter 18718354Smckusick if ( ! opt('g') || oldway == 0 ) { 188772Speter return; 189772Speter } 190826Speter putprintf( " .stabd 0x%x,0,0x%x" , 0 , N_RBRAC , level ); 191772Speter } 192772Speter 19318354Smckusick stabfunc (p, name, line, level) 19418354Smckusick struct nl *p; 19518354Smckusick char *name; 19618354Smckusick int line, level; 19718354Smckusick { 19818354Smckusick char extname[BUFSIZ],nestspec[BUFSIZ]; 19918354Smckusick 20018354Smckusick if ( level == 1 ) { 20118354Smckusick if (p->class == FUNC) { 20218354Smckusick putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x" , 20318354Smckusick 0 , name , N_PC , N_PGFUNC , ABS( line ) 20418354Smckusick ); 20518354Smckusick } else if (p->class == PROC) { 20618354Smckusick putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x" , 20718354Smckusick 0 , name , N_PC , N_PGPROC , ABS( line ) 20818354Smckusick ); 20918354Smckusick } 21018354Smckusick } 21118354Smckusick if (oldway != 0) { 21218354Smckusick oldstabfunc(name, p->class, line, level); 21318354Smckusick } else if (opt('g')) { 21418354Smckusick putprintf("\t.stabs\t\"%s:", 1, name); 21518354Smckusick if (p->class == FUNC) { 21618354Smckusick putprintf("F", 1); 21718354Smckusick gentype(p->type); 21818354Smckusick putprintf(",", 1); 21918354Smckusick } else { 22018354Smckusick putprintf("P,", 1); 22118354Smckusick } 22218354Smckusick sextname(extname, name, level); /* set extname to entry label */ 22318354Smckusick putprintf("%s,", 1, &(extname[1])); /* remove initial underbar */ 22418354Smckusick snestspec(nestspec, level); 22518354Smckusick putprintf("%s\",0x%x,0,0,%s", 0, nestspec, N_FUN, extname); 22618354Smckusick } 22718354Smckusick } 22818354Smckusick 229772Speter /* 23018354Smckusick * construct the colon-separated static nesting string into a 23118354Smckusick * caller-supplied buffer 23218354Smckusick */ 23318354Smckusick private snestspec(buffer, level) 23418354Smckusick char buffer[]; 23518354Smckusick int level; 23618354Smckusick { 23718354Smckusick char *starthere; 23818354Smckusick int i; 23918354Smckusick 24018354Smckusick if (level <= 1) { 24118354Smckusick buffer[0] = '\0'; 24218354Smckusick } else { 24318354Smckusick starthere = &buffer[0]; 24418354Smckusick for ( i = 1 ; i < level ; i++ ) { 24518354Smckusick sprintf(starthere, "%s:", enclosing[i]); 24618354Smckusick starthere += strlen(enclosing[i]) + 1; 24718354Smckusick } 24818354Smckusick *starthere-- = '\0'; /* remove last colon */ 24918354Smckusick if (starthere >= &buffer[BUFSIZ-1]) { 25018354Smckusick panic("snestspec"); 25118354Smckusick } 25218354Smckusick } 25318354Smckusick } 25418354Smckusick 25518354Smckusick /* 256772Speter * functions 257772Speter */ 25818354Smckusick oldstabfunc( name , typeclass , line , level ) 259772Speter char *name; 2607925Smckusick int typeclass; 261772Speter int line; 262772Speter long level; 263772Speter { 2643365Speter char extname[ BUFSIZ ]; 265772Speter 266826Speter /* 267826Speter * for sdb 268826Speter */ 269772Speter if ( ! opt('g') ) { 270772Speter return; 271772Speter } 272772Speter putprintf( " .stabs \"" , 1 ); 273*18355Smckusick putprintf( NAMEFORMAT , 1 , (int) name ); 274*18355Smckusick sextname( extname , name , (int) level ); 275*18355Smckusick putprintf( "\",0x%x,0,0x%x,%s" , 0 , N_FUN , line , (int) extname ); 276772Speter } 277772Speter 278772Speter /* 279772Speter * source line numbers 280772Speter */ 281772Speter stabline( line ) 282772Speter int line; 283772Speter { 284772Speter if ( ! opt('g') ) { 285772Speter return; 286772Speter } 287826Speter putprintf( " .stabd 0x%x,0,0x%x" , 0 , N_SLINE , ABS( line ) ); 288772Speter } 289772Speter 290772Speter /* 29118354Smckusick * source files get none or more of these: 29218354Smckusick * one as they are entered, 29318354Smckusick * and one every time they are returned to from nested #includes 294772Speter */ 29518354Smckusick stabsource(filename, firsttime) 296772Speter char *filename; 29718354Smckusick bool firsttime; 29815952Smckusick { 29915952Smckusick int label; 30015952Smckusick 30115952Smckusick /* 30215952Smckusick * for separate compilation 30315952Smckusick */ 30415952Smckusick putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x", 0, 305*18355Smckusick (int) filename, N_PC, N_PSO, N_FLAGCHECKSUM); 30615952Smckusick /* 30718354Smckusick * for debugger 30815952Smckusick */ 30915952Smckusick if ( ! opt('g') ) { 31015952Smckusick return; 311772Speter } 31218354Smckusick if (oldway != 0) { 313*18355Smckusick label = (int) getlab(); 31418354Smckusick putprintf( " .stabs \"" , 1 ); 31518354Smckusick putprintf( NAMEFORMAT , 1 , filename ); 31618354Smckusick putprintf( "\",0x%x,0,0," , 1 , N_SO ); 31718354Smckusick putprintf( PREFIXFORMAT , 0 , LLABELPREFIX , label ); 31818354Smckusick putprintf( PREFIXFORMAT , 1 , LLABELPREFIX , label ); 31918354Smckusick putprintf( ":" , 0 ); 32018354Smckusick } else { 32118354Smckusick if (firsttime) { 32218354Smckusick putprintf( " .stabs \"" , 1 ); 32318354Smckusick putprintf( NAMEFORMAT , 1 , filename ); 32418354Smckusick putprintf( "\",0x%x,0,0,0" , 0 , N_SO ); 32518354Smckusick } 32618354Smckusick } 32715952Smckusick } 328772Speter 329772Speter /* 330772Speter * included files get one or more of these: 331772Speter * one as they are entered by a #include, 33215952Smckusick * and one every time they are returned to from nested #includes. 333772Speter */ 33415952Smckusick stabinclude(filename, firsttime) 335772Speter char *filename; 33615952Smckusick bool firsttime; 33715952Smckusick { 338*18355Smckusick int label; 33915952Smckusick long check; 34015952Smckusick 34115952Smckusick /* 34215952Smckusick * for separate compilation 34315952Smckusick */ 34415952Smckusick if (firsttime) { 34515952Smckusick check = checksum(filename); 34615952Smckusick } else { 34715952Smckusick check = N_FLAGCHECKSUM; 34815952Smckusick } 34915952Smckusick putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x", 0, 350*18355Smckusick (int) filename, N_PC, N_PSOL, check); 35115952Smckusick /* 35215952Smckusick * for sdb 35315952Smckusick */ 35415952Smckusick if ( ! opt('g') ) { 35515952Smckusick return; 35615952Smckusick } 35718354Smckusick if (oldway != 0) { 358*18355Smckusick label = (int) getlab(); 35918354Smckusick putprintf( " .stabs \"" , 1 ); 36018354Smckusick putprintf( NAMEFORMAT , 1 , filename ); 36118354Smckusick putprintf( "\",0x%x,0,0," , 1 , N_SOL ); 36218354Smckusick putprintf( PREFIXFORMAT , 0 , LLABELPREFIX , label ); 36318354Smckusick putprintf( PREFIXFORMAT , 1 , LLABELPREFIX , label ); 36418354Smckusick putprintf( ":" , 0 ); 36518354Smckusick } 36615952Smckusick } 36715952Smckusick 36815952Smckusick /* 36915952Smckusick * anyone know a good checksum for ascii files? 37015952Smckusick * this does a rotate-left and then exclusive-or's in the character. 37115952Smckusick * also, it avoids returning checksums of 0. 37215952Smckusick * The rotate is implemented by shifting and adding back the 37315952Smckusick * sign bit when negative. 37415952Smckusick */ 37515952Smckusick long 37615952Smckusick checksum(filename) 37715952Smckusick char *filename; 37815952Smckusick { 37915952Smckusick FILE *filep; 38015952Smckusick register int input; 38115952Smckusick register long check; 38215952Smckusick 38315952Smckusick filep = fopen(filename, "r"); 38415952Smckusick if (filep == NULL) { 38515952Smckusick perror(filename); 38615952Smckusick pexit(DIED); 38715952Smckusick } 38815952Smckusick check = 0; 38915952Smckusick while ((input = getc(filep)) != EOF) { 39015952Smckusick if (check < 0) { 39115952Smckusick check <<= 1; 39215952Smckusick check += 1; 39315952Smckusick } else { 39415952Smckusick check <<= 1; 39515942Smckusick } 39615952Smckusick check ^= input; 39714128Speter } 398*18355Smckusick (void) fclose(filep); 39915952Smckusick if ((unsigned) check <= N_FLAGCHECKSUM) { 40015952Smckusick return N_FLAGCHECKSUM + 1; 40115952Smckusick } else { 40215952Smckusick return check; 40315952Smckusick } 40415952Smckusick } 40514128Speter 406772Speter /* 407772Speter * global Pascal symbols : 408772Speter * labels, types, constants, and external procedure and function names: 409772Speter * These are used by the separate compilation facility 410772Speter * to be able to check for disjoint header files. 411772Speter */ 412772Speter 413826Speter /* 414826Speter * global labels 415826Speter */ 416842Speter stabglabel( label , line ) 417826Speter char *label; 418826Speter int line; 419772Speter { 420772Speter 421842Speter putprintf( " .stabs \"%s\",0x%x,0,0x%x,0x%x" , 0 422*18355Smckusick , (int) label , N_PC , N_PGLABEL , ABS( line ) ); 423772Speter } 424772Speter 425826Speter /* 426826Speter * global constants 427826Speter */ 428842Speter stabgconst( const , line ) 429842Speter char *const; 430826Speter int line; 431772Speter { 432772Speter 433842Speter putprintf( " .stabs \"%s\",0x%x,0,0x%x,0x%x" , 0 434*18355Smckusick , (int) const , N_PC , N_PGCONST , ABS( line ) ); 435772Speter } 436772Speter 43718354Smckusick /* 43818354Smckusick * Generate symbolic information about a constant. 43918354Smckusick */ 440772Speter 44118354Smckusick stabconst (c) 44218354Smckusick struct nl *c; 44318354Smckusick { 44418354Smckusick if (opt('g') && oldway == 0) { 44518354Smckusick putprintf("\t.stabs\t\"%s:c=", 1, c->symbol); 44618354Smckusick if (c->type == nl + TSTR) { 44718354Smckusick putprintf("s'%s'", 1, c->ptr[0]); 44818354Smckusick } else if (c->type == nl + T1CHAR) { 44918354Smckusick putprintf("c%d", 1, c->range[0]); 45018354Smckusick } else if (isa(c->type, "i")) { 45118354Smckusick putprintf("i%d", 1, c->range[0]); 45218354Smckusick } else if (isa(c->type, "d")) { 45318354Smckusick putprintf("r%g", 1, c->real); 45418354Smckusick } else { 45518354Smckusick putprintf("e", 1); 45618354Smckusick gentype(c->type); 45718354Smckusick putprintf(",%d", 1, c->range[0]); 45818354Smckusick } 45918354Smckusick putprintf("\",0x%x,0,0x%x,0x%x", 0, N_LSYM, 0, 0); 460772Speter } 46118354Smckusick } 462772Speter 46318354Smckusick stabgtype (name, type, line) 46418354Smckusick char *name; 46518354Smckusick struct nl *type; 46618354Smckusick int line; 46718354Smckusick { 46818354Smckusick putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x" , 46918354Smckusick 0, name, N_PC , N_PGTYPE, ABS(line) 47018354Smckusick ); 47118354Smckusick if (oldway == 0) { 47218354Smckusick stabltype(name, type); 47318354Smckusick } 47418354Smckusick } 475772Speter 47618354Smckusick stabltype (name, type) 47718354Smckusick char *name; 47818354Smckusick struct nl *type; 47918354Smckusick { 48018354Smckusick if (opt('g')) { 48118354Smckusick putprintf("\t.stabs\t\"%s:t", 1, name); 48218354Smckusick gentype(type); 48318354Smckusick putprintf("\",0x%x,0,0,0", 0, N_LSYM); 48418354Smckusick } 48518354Smckusick } 48618354Smckusick 487826Speter /* 488826Speter * external functions and procedures 489826Speter */ 4907925Smckusick stabefunc( name , typeclass , line ) 491826Speter char *name; 4927925Smckusick int typeclass; 493826Speter int line; 494772Speter { 495826Speter int type; 496772Speter 4977925Smckusick if ( typeclass == FUNC ) { 498842Speter type = N_PEFUNC; 4997925Smckusick } else if ( typeclass == PROC ) { 500842Speter type = N_PEPROC; 501826Speter } else { 502826Speter return; 503772Speter } 504842Speter putprintf( " .stabs \"%s\",0x%x,0,0x%x,0x%x" , 0 505*18355Smckusick , (int) name , N_PC , type , ABS( line ) ); 506772Speter } 507772Speter 50818354Smckusick /* 50918354Smckusick * Generate type information encoded as a string for dbx. 51018354Smckusick * The fwdptrnum field is used only when the type is a pointer 51118354Smckusick * to a type that isn't known when it was entered. When the 51218354Smckusick * type field is filled for some such tptr, fixfwdtype should 51318354Smckusick * be called to output an equivalencing type definition. 51418354Smckusick */ 51518354Smckusick 51618354Smckusick typedef struct TypeDesc *TypeDesc; 51718354Smckusick 51818354Smckusick struct TypeDesc { 51918354Smckusick struct nl *tptr; 52018354Smckusick int tnum; 52118354Smckusick int fwdptrnum; 52218354Smckusick TypeDesc chain; 52318354Smckusick }; 52418354Smckusick 52518354Smckusick #define TABLESIZE 2003 52618354Smckusick 52718354Smckusick #define typehash(t) ( ( ((int) t) >> 2 ) % TABLESIZE ) 52818354Smckusick 52918354Smckusick private int tcount = 1; 53018354Smckusick private TypeDesc typetable[TABLESIZE]; 53118354Smckusick 53218354Smckusick private TypeDesc tdlookup (t) 53318354Smckusick struct nl *t; 53418354Smckusick { 53518354Smckusick register TypeDesc td; 53618354Smckusick 53718354Smckusick td = typetable[typehash(t)]; 53818354Smckusick while (td != NIL && td->tptr != t) { 53918354Smckusick td = td->chain; 54018354Smckusick } 54118354Smckusick return td; 54218354Smckusick } 54318354Smckusick 54418354Smckusick private int typelookup (t) 54518354Smckusick struct nl *t; 54618354Smckusick { 54718354Smckusick register TypeDesc td; 54818354Smckusick int r; 54918354Smckusick 55018354Smckusick td = tdlookup(t); 55118354Smckusick if (td == NIL) { 55218354Smckusick r = 0; 55318354Smckusick } else { 55418354Smckusick r = td->tnum; 55518354Smckusick } 55618354Smckusick return r; 55718354Smckusick } 55818354Smckusick 55918354Smckusick private int entertype (type) 56018354Smckusick struct nl *type; 56118354Smckusick { 56218354Smckusick register TypeDesc td; 56318354Smckusick register int i; 56418354Smckusick 56518354Smckusick td = (TypeDesc) malloc(sizeof(struct TypeDesc)); 56618354Smckusick td->tptr = type; 56718354Smckusick td->tnum = tcount; 56818354Smckusick td->fwdptrnum = 0; 56918354Smckusick ++tcount; 57018354Smckusick i = typehash(type); 57118354Smckusick td->chain = typetable[i]; 57218354Smckusick typetable[i] = td; 57318354Smckusick return td->tnum; 57418354Smckusick } 57518354Smckusick 57618354Smckusick /* 57718354Smckusick * The in_types table currently contains "boolean", "char", "integer", 57818354Smckusick * "real" and "_nil". (See nl.c for definition.) 57918354Smckusick * The lookup call below will give the TYPE class nl entry for these 58018354Smckusick * types. In each case except _nil, the type field of that entry is a RANGE 58118354Smckusick * class nl entry for the type. Sometimes other symbol table entries 58218354Smckusick * point to the TYPE entry (e.g., when there is a range over the base type), 58318354Smckusick * and other entries point to the RANGE entry (e.g., for a variable of the 58418354Smckusick * given type). We don't really want to distinguish between these uses 58518354Smckusick * in dbx, and since it appears that the RANGE entries are not reused if 58618354Smckusick * a range happens to coincide, we will give the two the same identifying 58718354Smckusick * dbx type number. 58818354Smckusick */ 58918354Smckusick 59018354Smckusick private inittypes() 59118354Smckusick { 59218354Smckusick int i; 59318354Smckusick extern char *in_types[]; 59418354Smckusick struct nl *p; 59518354Smckusick 59618354Smckusick for (i = 0; in_types[i] != NIL; i++) { 59718354Smckusick p = lookup(in_types[i]); 59818354Smckusick if (p != NIL) { 59918354Smckusick entertype(p); 60018354Smckusick if (p->type != NIL) { 60118354Smckusick --tcount; /* see comment above */ 60218354Smckusick entertype(p->type); 60318354Smckusick } 60418354Smckusick } 60518354Smckusick } 60618354Smckusick } 60718354Smckusick 60818354Smckusick static genarray (t) 60918354Smckusick struct nl *t; 61018354Smckusick { 61118354Smckusick register struct nl *p; 61218354Smckusick 61318354Smckusick putprintf("a", 1); 61418354Smckusick for (p = t->chain; p != NIL; p = p->chain) { 61518354Smckusick gentype(p); 61618354Smckusick putprintf(";", 1); 61718354Smckusick } 61818354Smckusick gentype(t->type); 61918354Smckusick } 62018354Smckusick 62118354Smckusick /* 62218354Smckusick * Really we should walk through ptr[NL_FIELDLIST] for the fields, 62318354Smckusick * and then do the variant tag and fields separately, but dbx 62418354Smckusick * doesn't support this yet. 62518354Smckusick * So, since all the fields of all the variants are on the chain, 62618354Smckusick * we walk through that. Except that this gives the fields in the 62718354Smckusick * reverse order, so we want to print in reverse order. 62818354Smckusick */ 62918354Smckusick 63018354Smckusick static genrecord (t) 63118354Smckusick struct nl *t; 63218354Smckusick { 63318354Smckusick putprintf("s%d", 1, t->value[NL_OFFS]); 63418354Smckusick if (t->chain != NIL) { 63518354Smckusick genrecfield(t->chain, 1); 63618354Smckusick } 63718354Smckusick putprintf(";", 1); 63818354Smckusick } 63918354Smckusick 64018354Smckusick static genrecfield (t, n) 64118354Smckusick struct nl *t; 64218354Smckusick int n; 64318354Smckusick { 64418354Smckusick if (t->chain != NULL) { 64518354Smckusick genrecfield(t->chain, n + 1); 64618354Smckusick if (n % 2 == 0) { 64718354Smckusick gencontinue(); 64818354Smckusick } 64918354Smckusick } 65018354Smckusick putprintf("%s:", 1, t->symbol); 65118354Smckusick gentype(t->type); 65218354Smckusick putprintf(",%d,%d;", 1, 8*t->value[NL_OFFS], 8*lwidth(t->type)); 65318354Smckusick } 65418354Smckusick 65518354Smckusick static genvarnt (t) 65618354Smckusick struct nl *t; 65718354Smckusick { 65818354Smckusick genrecord(t); 65918354Smckusick } 66018354Smckusick 66118354Smckusick static genptr (t) 66218354Smckusick struct nl *t; 66318354Smckusick { 66418354Smckusick register TypeDesc td; 66518354Smckusick 66618354Smckusick putprintf("*", 1); 66718354Smckusick if (t->type != NIL) { 66818354Smckusick gentype(t->type); 66918354Smckusick } else { 67018354Smckusick /* 67118354Smckusick * unresolved forward pointer: use tcount to represent what is 67218354Smckusick * begin pointed to, to be defined later 67318354Smckusick */ 67418354Smckusick td = tdlookup(t); 67518354Smckusick if (td == NIL) { 67618354Smckusick panic("nil ptr in stab.genptr"); 67718354Smckusick } 67818354Smckusick td->fwdptrnum = tcount; 67918354Smckusick putprintf("%d", 1, tcount); 68018354Smckusick ++tcount; 68118354Smckusick } 68218354Smckusick } 68318354Smckusick 68418354Smckusick /* 68518354Smckusick * The type t is a pointer which has just had its type field filled. 68618354Smckusick * We need to generate a type stab saying that the number saved 68718354Smckusick * in t's fwdptrnum is the same as the t->type's number 68818354Smckusick */ 68918354Smckusick 69018354Smckusick fixfwdtype (t) 69118354Smckusick struct nl *t; 69218354Smckusick { 69318354Smckusick register TypeDesc td; 69418354Smckusick 69518354Smckusick if (opt('g') && oldway == 0) { 69618354Smckusick td = tdlookup(t); 69718354Smckusick if (td != NIL) { 69818354Smckusick putprintf("\t.stabs\t\":t%d=", 1, td->fwdptrnum); 69918354Smckusick gentype(t->type); 70018354Smckusick putprintf("\",0x%x,0,0,0", 0, N_LSYM); 70118354Smckusick } 70218354Smckusick } 70318354Smckusick } 70418354Smckusick 70518354Smckusick static genenum (t) 70618354Smckusick struct nl *t; 70718354Smckusick { 70818354Smckusick register struct nl *e; 70918354Smckusick register int i; 71018354Smckusick 71118354Smckusick putprintf("e", 1); 71218354Smckusick i = 1; 71318354Smckusick e = t->chain; 71418354Smckusick while (e != NULL) { 71518354Smckusick if (i > 2) { 71618354Smckusick gencontinue(); 71718354Smckusick i = 0; 71818354Smckusick } 71918354Smckusick putprintf("%s:%d,", 1, e->symbol, e->range[0]); 72018354Smckusick e = e->chain; 72118354Smckusick ++i; 72218354Smckusick } 72318354Smckusick putprintf(";", 1); 72418354Smckusick } 72518354Smckusick 72618354Smckusick static genset (t) 72718354Smckusick struct nl *t; 72818354Smckusick { 72918354Smckusick putprintf("S", 1); 73018354Smckusick gentype(t->type); 73118354Smckusick } 73218354Smckusick 73318354Smckusick static genrange (t) 73418354Smckusick struct nl *t; 73518354Smckusick { 73618354Smckusick putprintf("r", 1); 73718354Smckusick gentype(t->type); 73818354Smckusick putprintf(";%d;%d", 1, t->range[0], t->range[1]); 73918354Smckusick } 74018354Smckusick 74118354Smckusick static genfparam (t) 74218354Smckusick struct nl *t; 74318354Smckusick { 74418354Smckusick struct nl *p; 74518354Smckusick int count; 74618354Smckusick 74718354Smckusick if (t->type != NULL) { 74818354Smckusick putprintf("f", 1); 74918354Smckusick gentype(t->type); 75018354Smckusick putprintf(",", 1); 75118354Smckusick } else { 75218354Smckusick putprintf("p", 1); 75318354Smckusick } 75418354Smckusick count = 0; 75518354Smckusick for (p = t->ptr[NL_FCHAIN]; p != NULL; p = p->chain) { 75618354Smckusick ++count; 75718354Smckusick } 75818354Smckusick putprintf("%d;", 1, count); 75918354Smckusick for (p = t->ptr[NL_FCHAIN]; p != NULL; p = p->chain) { 76018354Smckusick gentype(p->type); 76118354Smckusick putprintf(",%d;", 1, p->class); 76218354Smckusick } 76318354Smckusick } 76418354Smckusick 76518354Smckusick static genfile (t) 76618354Smckusick struct nl *t; 76718354Smckusick { 76818354Smckusick putprintf("d", 1); 76918354Smckusick gentype(t->type); 77018354Smckusick } 77118354Smckusick 77218354Smckusick static gentype (t) 77318354Smckusick struct nl *t; 77418354Smckusick { 77518354Smckusick int id; 77618354Smckusick 77718354Smckusick if (tcount == 1) { 77818354Smckusick inittypes(); 77918354Smckusick } 78018354Smckusick id = typelookup(t); 78118354Smckusick if (id != 0) { 78218354Smckusick putprintf("%d", 1, id); 78318354Smckusick } else if (t->class == SCAL && t->chain == NULL) { 78418354Smckusick id = typelookup(t->type); 78518354Smckusick if (id != 0) { 78618354Smckusick putprintf("%d", 1, id); 78718354Smckusick } else { 78818354Smckusick genenum(t->type); 78918354Smckusick } 79018354Smckusick } else { 79118354Smckusick id = entertype(t); 79218354Smckusick putprintf("%d=", 1, id); 79318354Smckusick switch (t->class) { 79418354Smckusick case TYPE: 79518354Smckusick gentype(t->type); 79618354Smckusick break; 79718354Smckusick 79818354Smckusick case ARRAY: 79918354Smckusick genarray(t); 80018354Smckusick break; 80118354Smckusick 80218354Smckusick case RECORD: 80318354Smckusick genrecord(t); 80418354Smckusick break; 80518354Smckusick 80618354Smckusick case VARNT: 80718354Smckusick genvarnt(t); 80818354Smckusick break; 80918354Smckusick 81018354Smckusick case REF: 81118354Smckusick gentype(t->type); 81218354Smckusick break; 81318354Smckusick 81418354Smckusick case PTR: 81518354Smckusick genptr(t); 81618354Smckusick break; 81718354Smckusick 81818354Smckusick case SET: 81918354Smckusick genset(t); 82018354Smckusick break; 82118354Smckusick 82218354Smckusick case RANGE: 82318354Smckusick genrange(t); 82418354Smckusick break; 82518354Smckusick 82618354Smckusick case SCAL: 82718354Smckusick genenum(t); 82818354Smckusick break; 82918354Smckusick 83018354Smckusick case FPROC: 83118354Smckusick case FFUNC: 83218354Smckusick genfparam(t); 83318354Smckusick break; 83418354Smckusick 83518354Smckusick case FILET: 83618354Smckusick case PTRFILE: 83718354Smckusick genfile(t); 83818354Smckusick break; 83918354Smckusick 84018354Smckusick default: 84118354Smckusick /* This shouldn't happen */ 84218354Smckusick /* Rather than bomb outright, let debugging go on */ 84318354Smckusick warning(); 84418354Smckusick error("Bad type class found in stab"); 84518354Smckusick putprintf("1", 1, t->class); 84618354Smckusick break; 84718354Smckusick } 84818354Smckusick } 84918354Smckusick } 85018354Smckusick 85118354Smckusick /* 85218354Smckusick * Continue stab information in a namelist new entry. This is necessary 85318354Smckusick * to avoid overflowing putprintf's buffer. 85418354Smckusick */ 85518354Smckusick 85618354Smckusick static gencontinue () 85718354Smckusick { 85818354Smckusick putprintf("?\",0x%x,0,0,0", 0, N_LSYM); 85918354Smckusick putprintf("\t.stabs\t\"", 1); 86018354Smckusick } 86118354Smckusick 862772Speter #endif PC 863