1*48116Sbostic /*- 2*48116Sbostic * Copyright (c) 1980 The Regents of the University of California. 3*48116Sbostic * All rights reserved. 4*48116Sbostic * 5*48116Sbostic * %sccs.include.redist.c% 622191Sdist */ 7772Speter 818355Smckusick #ifndef lint 9*48116Sbostic static char sccsid[] = "@(#)stab.c 5.4 (Berkeley) 04/16/91"; 10*48116Sbostic #endif /* not lint */ 11826Speter 12772Speter /* 1318354Smckusick * Procedures to put out symbol table information 14826Speter * and stabs for separate compilation type checking. 1518354Smckusick * These use the .stabs, .stabn, and .stabd directives. 16772Speter */ 17772Speter 18772Speter #include "whoami.h" 19772Speter #ifdef PC 20772Speter /* and the rest of the file */ 21772Speter # include "0.h" 2210649Speter # include "objfmt.h" 2315952Smckusick # include "yy.h" 24772Speter # include <stab.h> 25772Speter 26842Speter /* 27842Speter * additional symbol definition for <stab.h> 28842Speter * that is used by the separate compilation facility -- 29842Speter * eventually, <stab.h> should be updated to include this 30842Speter */ 31772Speter 32842Speter # include "pstab.h" 33772Speter # include "pc.h" 34772Speter 3518354Smckusick 3618354Smckusick #define private static 3718354Smckusick 3818354Smckusick int oldway = 0; 3918354Smckusick 40772Speter /* 41826Speter * absolute value: line numbers are negative if error recovery. 42826Speter */ 43826Speter #define ABS( x ) ( x < 0 ? -x : x ) 4418355Smckusick long checksum(); 45826Speter 4618354Smckusick /* 4718354Smckusick * Generate information about variables. 4818354Smckusick */ 4918354Smckusick 5018354Smckusick stabgvar (p, length, line) 5118354Smckusick struct nl *p; 5218354Smckusick int length, line; 5318354Smckusick { 5418354Smckusick putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x", 5518354Smckusick 0, p->symbol, N_PC, N_PGVAR, ABS(line) 5618354Smckusick ); 5718354Smckusick if (oldway != 0) { 5818354Smckusick oldstabgvar(p->symbol, p2type(p->type), 0, length, line); 5918354Smckusick } else if (opt('g')) { 6018354Smckusick putprintf("\t.stabs\t\"%s:G", 1, p->symbol); 6118354Smckusick gentype(p->type); 6218354Smckusick putprintf("\",0x%x,0,0x%x,0", 0, N_GSYM, length); 6318354Smckusick } 6418354Smckusick } 6518354Smckusick 6618354Smckusick stablvar (p, offset, length) 6718354Smckusick struct nl *p; 6818354Smckusick int offset, length; 6918354Smckusick { 7018354Smckusick int level; 7118354Smckusick 7218354Smckusick level = (p->nl_block & 037); 7318354Smckusick if (oldway != 0) { 7418354Smckusick oldstablvar(p->symbol, p2type(p->type), level, offset, length); 7518354Smckusick } else if (opt('g')) { 7618354Smckusick putprintf("\t.stabs\t\"%s:", 1, p->symbol); 7718354Smckusick gentype(p->type); 7818354Smckusick putprintf("\",0x%x,0,0x%x,0x%x", 0, N_LSYM, length, offset); 7918354Smckusick } 8018354Smckusick } 8118354Smckusick 82826Speter /* 832164Speter * global variables 84772Speter */ 8518355Smckusick /*ARGSUSED*/ 8618354Smckusick oldstabgvar( name , type , offset , length , line ) 87772Speter char *name; 88772Speter int type; 89772Speter int offset; 90772Speter int length; 91826Speter int line; 92772Speter { 93772Speter if ( ! opt('g') ) { 94772Speter return; 95772Speter } 96772Speter putprintf( " .stabs \"" , 1 ); 9718355Smckusick putprintf( NAMEFORMAT , 1 , (int) name ); 982164Speter putprintf( "\",0x%x,0,0x%x,0" , 0 , N_GSYM , type ); 992164Speter putprintf( " .stabs \"" , 1 ); 10018355Smckusick putprintf( NAMEFORMAT , 1 , (int) name ); 1012164Speter putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length ); 1022164Speter } 1032164Speter 1042164Speter /* 1052164Speter * local variables 1062164Speter */ 10718355Smckusick /*ARGSUSED*/ 10818354Smckusick oldstablvar( name , type , level , offset , length ) 1092164Speter char *name; 1102164Speter int type; 1112164Speter int level; 1122164Speter int offset; 1132164Speter int length; 1142164Speter { 1152164Speter 1162164Speter if ( ! opt('g') ) { 1172164Speter return; 118772Speter } 119772Speter putprintf( " .stabs \"" , 1 ); 12018355Smckusick putprintf( NAMEFORMAT , 1 , (int) name ); 1212164Speter putprintf( "\",0x%x,0,0x%x,0x%x" , 0 , N_LSYM , type , -offset ); 1222164Speter putprintf( " .stabs \"" , 1 ); 12318355Smckusick putprintf( NAMEFORMAT , 1 , (int) name ); 124826Speter putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length ); 125772Speter } 126772Speter 127772Speter 12818354Smckusick stabparam (p, offset, length) 12918354Smckusick struct nl *p; 13018354Smckusick int offset, length; 13118354Smckusick { 13218354Smckusick if (oldway != 0) { 13318354Smckusick oldstabparam(p->symbol, p2type(p->type), offset, length); 13418354Smckusick } else if (opt('g')) { 13518354Smckusick putprintf("\t.stabs\t\"%s:", 1, p->symbol); 13618354Smckusick if (p->class == REF) { 13718354Smckusick putprintf("v", 1); 13818354Smckusick } else { 13918354Smckusick putprintf("p", 1); 14018354Smckusick } 14118354Smckusick gentype((p->class == FPROC || p->class ==FFUNC) ? p : p->type); 14218354Smckusick putprintf("\",0x%x,0,0x%x,0x%x", 0, N_PSYM, length, offset); 14318354Smckusick } 14418354Smckusick } 14518354Smckusick 146772Speter /* 147772Speter * parameters 148772Speter */ 14918354Smckusick oldstabparam( name , type , offset , length ) 150772Speter char *name; 151772Speter int type; 152772Speter int offset; 153772Speter int length; 154772Speter { 155772Speter 156772Speter if ( ! opt('g') ) { 157772Speter return; 158772Speter } 159772Speter putprintf( " .stabs \"" , 1 ); 16018355Smckusick putprintf( NAMEFORMAT , 1 , (int) name ); 161826Speter putprintf( "\",0x%x,0,0x%x,0x%x" , 0 , N_PSYM , type , offset ); 162772Speter putprintf( " .stabs \"" , 1 ); 16318355Smckusick putprintf( NAMEFORMAT , 1 , (int) name ); 164826Speter putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length ); 165772Speter } 166772Speter 167772Speter /* 168772Speter * fields 169772Speter */ 170772Speter 171772Speter /* 172772Speter * left brackets 17318354Smckusick * (dbx handles module-2 without these, so we won't use them either) 174772Speter */ 175772Speter stablbrac( level ) 176772Speter int level; 177772Speter { 178772Speter 17918354Smckusick if ( ! opt('g') || oldway == 0 ) { 180772Speter return; 181772Speter } 182826Speter putprintf( " .stabd 0x%x,0,0x%x" , 0 , N_LBRAC , level ); 183772Speter } 184772Speter 185772Speter /* 186772Speter * right brackets 187772Speter */ 188772Speter stabrbrac( level ) 189772Speter int level; 190772Speter { 191772Speter 19218354Smckusick if ( ! opt('g') || oldway == 0 ) { 193772Speter return; 194772Speter } 195826Speter putprintf( " .stabd 0x%x,0,0x%x" , 0 , N_RBRAC , level ); 196772Speter } 197772Speter 19818354Smckusick stabfunc (p, name, line, level) 19918354Smckusick struct nl *p; 20018354Smckusick char *name; 20118354Smckusick int line, level; 20218354Smckusick { 20318354Smckusick char extname[BUFSIZ],nestspec[BUFSIZ]; 20418354Smckusick 20518354Smckusick if ( level == 1 ) { 20618354Smckusick if (p->class == FUNC) { 20718354Smckusick putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x" , 20818354Smckusick 0 , name , N_PC , N_PGFUNC , ABS( line ) 20918354Smckusick ); 21018354Smckusick } else if (p->class == PROC) { 21118354Smckusick putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x" , 21218354Smckusick 0 , name , N_PC , N_PGPROC , ABS( line ) 21318354Smckusick ); 21418354Smckusick } 21518354Smckusick } 21618354Smckusick if (oldway != 0) { 21718354Smckusick oldstabfunc(name, p->class, line, level); 21818354Smckusick } else if (opt('g')) { 21918354Smckusick putprintf("\t.stabs\t\"%s:", 1, name); 22018354Smckusick if (p->class == FUNC) { 22118354Smckusick putprintf("F", 1); 22218354Smckusick gentype(p->type); 22318354Smckusick putprintf(",", 1); 22418354Smckusick } else { 22518354Smckusick putprintf("P,", 1); 22618354Smckusick } 22718354Smckusick sextname(extname, name, level); /* set extname to entry label */ 22818354Smckusick putprintf("%s,", 1, &(extname[1])); /* remove initial underbar */ 22918354Smckusick snestspec(nestspec, level); 23018354Smckusick putprintf("%s\",0x%x,0,0,%s", 0, nestspec, N_FUN, extname); 23118354Smckusick } 23218354Smckusick } 23318354Smckusick 234772Speter /* 23518354Smckusick * construct the colon-separated static nesting string into a 23618354Smckusick * caller-supplied buffer 23718354Smckusick */ 23818354Smckusick private snestspec(buffer, level) 23918354Smckusick char buffer[]; 24018354Smckusick int level; 24118354Smckusick { 24218354Smckusick char *starthere; 24318354Smckusick int i; 24418354Smckusick 24518354Smckusick if (level <= 1) { 24618354Smckusick buffer[0] = '\0'; 24718354Smckusick } else { 24818354Smckusick starthere = &buffer[0]; 24918354Smckusick for ( i = 1 ; i < level ; i++ ) { 25018354Smckusick sprintf(starthere, "%s:", enclosing[i]); 25118354Smckusick starthere += strlen(enclosing[i]) + 1; 25218354Smckusick } 25325263Smckusick *--starthere = '\0'; /* remove last colon */ 25418354Smckusick if (starthere >= &buffer[BUFSIZ-1]) { 25518354Smckusick panic("snestspec"); 25618354Smckusick } 25718354Smckusick } 25818354Smckusick } 25918354Smckusick 26018354Smckusick /* 261772Speter * functions 262772Speter */ 26318354Smckusick oldstabfunc( name , typeclass , line , level ) 264772Speter char *name; 2657925Smckusick int typeclass; 266772Speter int line; 267772Speter long level; 268772Speter { 2693365Speter char extname[ BUFSIZ ]; 270772Speter 271826Speter /* 272826Speter * for sdb 273826Speter */ 274772Speter if ( ! opt('g') ) { 275772Speter return; 276772Speter } 277772Speter putprintf( " .stabs \"" , 1 ); 27818355Smckusick putprintf( NAMEFORMAT , 1 , (int) name ); 27918355Smckusick sextname( extname , name , (int) level ); 28018355Smckusick putprintf( "\",0x%x,0,0x%x,%s" , 0 , N_FUN , line , (int) extname ); 281772Speter } 282772Speter 283772Speter /* 284772Speter * source line numbers 285772Speter */ 286772Speter stabline( line ) 287772Speter int line; 288772Speter { 289772Speter if ( ! opt('g') ) { 290772Speter return; 291772Speter } 292826Speter putprintf( " .stabd 0x%x,0,0x%x" , 0 , N_SLINE , ABS( line ) ); 293772Speter } 294772Speter 295772Speter /* 29618354Smckusick * source files get none or more of these: 29718354Smckusick * one as they are entered, 29818354Smckusick * and one every time they are returned to from nested #includes 299772Speter */ 30018354Smckusick stabsource(filename, firsttime) 301772Speter char *filename; 30218354Smckusick bool firsttime; 30315952Smckusick { 30415952Smckusick int label; 30515952Smckusick 30615952Smckusick /* 30715952Smckusick * for separate compilation 30815952Smckusick */ 30915952Smckusick putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x", 0, 31018355Smckusick (int) filename, N_PC, N_PSO, N_FLAGCHECKSUM); 31115952Smckusick /* 31218354Smckusick * for debugger 31315952Smckusick */ 31415952Smckusick if ( ! opt('g') ) { 31515952Smckusick return; 316772Speter } 31718354Smckusick if (oldway != 0) { 31818355Smckusick label = (int) getlab(); 31918354Smckusick putprintf( " .stabs \"" , 1 ); 32018354Smckusick putprintf( NAMEFORMAT , 1 , filename ); 32118354Smckusick putprintf( "\",0x%x,0,0," , 1 , N_SO ); 32218354Smckusick putprintf( PREFIXFORMAT , 0 , LLABELPREFIX , label ); 32318354Smckusick putprintf( PREFIXFORMAT , 1 , LLABELPREFIX , label ); 32418354Smckusick putprintf( ":" , 0 ); 32518354Smckusick } else { 32618354Smckusick if (firsttime) { 32718354Smckusick putprintf( " .stabs \"" , 1 ); 32818354Smckusick putprintf( NAMEFORMAT , 1 , filename ); 32918354Smckusick putprintf( "\",0x%x,0,0,0" , 0 , N_SO ); 33018354Smckusick } 33118354Smckusick } 33215952Smckusick } 333772Speter 334772Speter /* 335772Speter * included files get one or more of these: 336772Speter * one as they are entered by a #include, 33715952Smckusick * and one every time they are returned to from nested #includes. 338772Speter */ 33915952Smckusick stabinclude(filename, firsttime) 340772Speter char *filename; 34115952Smckusick bool firsttime; 34215952Smckusick { 34318355Smckusick int label; 34415952Smckusick long check; 34515952Smckusick 34615952Smckusick /* 34715952Smckusick * for separate compilation 34815952Smckusick */ 34915952Smckusick if (firsttime) { 35015952Smckusick check = checksum(filename); 35115952Smckusick } else { 35215952Smckusick check = N_FLAGCHECKSUM; 35315952Smckusick } 35415952Smckusick putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x", 0, 35518355Smckusick (int) filename, N_PC, N_PSOL, check); 35615952Smckusick /* 35715952Smckusick * for sdb 35815952Smckusick */ 35915952Smckusick if ( ! opt('g') ) { 36015952Smckusick return; 36115952Smckusick } 36218354Smckusick if (oldway != 0) { 36318355Smckusick label = (int) getlab(); 36418354Smckusick putprintf( " .stabs \"" , 1 ); 36518354Smckusick putprintf( NAMEFORMAT , 1 , filename ); 36618354Smckusick putprintf( "\",0x%x,0,0," , 1 , N_SOL ); 36718354Smckusick putprintf( PREFIXFORMAT , 0 , LLABELPREFIX , label ); 36818354Smckusick putprintf( PREFIXFORMAT , 1 , LLABELPREFIX , label ); 36918354Smckusick putprintf( ":" , 0 ); 37018354Smckusick } 37115952Smckusick } 37215952Smckusick 37315952Smckusick /* 37415952Smckusick * anyone know a good checksum for ascii files? 37515952Smckusick * this does a rotate-left and then exclusive-or's in the character. 37615952Smckusick * also, it avoids returning checksums of 0. 37715952Smckusick * The rotate is implemented by shifting and adding back the 37815952Smckusick * sign bit when negative. 37915952Smckusick */ 38015952Smckusick long 38115952Smckusick checksum(filename) 38215952Smckusick char *filename; 38315952Smckusick { 38415952Smckusick FILE *filep; 38515952Smckusick register int input; 38615952Smckusick register long check; 38715952Smckusick 38815952Smckusick filep = fopen(filename, "r"); 38915952Smckusick if (filep == NULL) { 39015952Smckusick perror(filename); 39115952Smckusick pexit(DIED); 39215952Smckusick } 39315952Smckusick check = 0; 39415952Smckusick while ((input = getc(filep)) != EOF) { 39515952Smckusick if (check < 0) { 39615952Smckusick check <<= 1; 39715952Smckusick check += 1; 39815952Smckusick } else { 39915952Smckusick check <<= 1; 40015942Smckusick } 40115952Smckusick check ^= input; 40214128Speter } 40318355Smckusick (void) fclose(filep); 40415952Smckusick if ((unsigned) check <= N_FLAGCHECKSUM) { 40515952Smckusick return N_FLAGCHECKSUM + 1; 40615952Smckusick } else { 40715952Smckusick return check; 40815952Smckusick } 40915952Smckusick } 41014128Speter 411772Speter /* 412772Speter * global Pascal symbols : 413772Speter * labels, types, constants, and external procedure and function names: 414772Speter * These are used by the separate compilation facility 415772Speter * to be able to check for disjoint header files. 416772Speter */ 417772Speter 418826Speter /* 419826Speter * global labels 420826Speter */ 421842Speter stabglabel( label , line ) 422826Speter char *label; 423826Speter int line; 424772Speter { 425772Speter 426842Speter putprintf( " .stabs \"%s\",0x%x,0,0x%x,0x%x" , 0 42718355Smckusick , (int) label , N_PC , N_PGLABEL , ABS( line ) ); 428772Speter } 429772Speter 430826Speter /* 431826Speter * global constants 432826Speter */ 43333236Sbostic stabgconst( constant , line ) 43433236Sbostic char *constant; 435826Speter int line; 436772Speter { 437772Speter 438842Speter putprintf( " .stabs \"%s\",0x%x,0,0x%x,0x%x" , 0 43933236Sbostic , (int) constant , N_PC , N_PGCONST , ABS( line ) ); 440772Speter } 441772Speter 44218354Smckusick /* 44318354Smckusick * Generate symbolic information about a constant. 44418354Smckusick */ 445772Speter 44618354Smckusick stabconst (c) 44718354Smckusick struct nl *c; 44818354Smckusick { 44918354Smckusick if (opt('g') && oldway == 0) { 45018354Smckusick putprintf("\t.stabs\t\"%s:c=", 1, c->symbol); 45118354Smckusick if (c->type == nl + TSTR) { 45218354Smckusick putprintf("s'%s'", 1, c->ptr[0]); 45318354Smckusick } else if (c->type == nl + T1CHAR) { 45418354Smckusick putprintf("c%d", 1, c->range[0]); 45518354Smckusick } else if (isa(c->type, "i")) { 45618354Smckusick putprintf("i%d", 1, c->range[0]); 45718354Smckusick } else if (isa(c->type, "d")) { 45818354Smckusick putprintf("r%g", 1, c->real); 45918354Smckusick } else { 46018354Smckusick putprintf("e", 1); 46118354Smckusick gentype(c->type); 46218354Smckusick putprintf(",%d", 1, c->range[0]); 46318354Smckusick } 46418354Smckusick putprintf("\",0x%x,0,0x%x,0x%x", 0, N_LSYM, 0, 0); 465772Speter } 46618354Smckusick } 467772Speter 46818354Smckusick stabgtype (name, type, line) 46918354Smckusick char *name; 47018354Smckusick struct nl *type; 47118354Smckusick int line; 47218354Smckusick { 47318354Smckusick putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x" , 47418354Smckusick 0, name, N_PC , N_PGTYPE, ABS(line) 47518354Smckusick ); 47618354Smckusick if (oldway == 0) { 47718354Smckusick stabltype(name, type); 47818354Smckusick } 47918354Smckusick } 480772Speter 48118354Smckusick stabltype (name, type) 48218354Smckusick char *name; 48318354Smckusick struct nl *type; 48418354Smckusick { 48518354Smckusick if (opt('g')) { 48618354Smckusick putprintf("\t.stabs\t\"%s:t", 1, name); 48718354Smckusick gentype(type); 48818354Smckusick putprintf("\",0x%x,0,0,0", 0, N_LSYM); 48918354Smckusick } 49018354Smckusick } 49118354Smckusick 492826Speter /* 493826Speter * external functions and procedures 494826Speter */ 4957925Smckusick stabefunc( name , typeclass , line ) 496826Speter char *name; 4977925Smckusick int typeclass; 498826Speter int line; 499772Speter { 500826Speter int type; 501772Speter 5027925Smckusick if ( typeclass == FUNC ) { 503842Speter type = N_PEFUNC; 5047925Smckusick } else if ( typeclass == PROC ) { 505842Speter type = N_PEPROC; 506826Speter } else { 507826Speter return; 508772Speter } 509842Speter putprintf( " .stabs \"%s\",0x%x,0,0x%x,0x%x" , 0 51018355Smckusick , (int) name , N_PC , type , ABS( line ) ); 511772Speter } 512772Speter 51318354Smckusick /* 51418354Smckusick * Generate type information encoded as a string for dbx. 51518354Smckusick * The fwdptrnum field is used only when the type is a pointer 51618354Smckusick * to a type that isn't known when it was entered. When the 51718354Smckusick * type field is filled for some such tptr, fixfwdtype should 51818354Smckusick * be called to output an equivalencing type definition. 51918354Smckusick */ 52018354Smckusick 52118354Smckusick typedef struct TypeDesc *TypeDesc; 52218354Smckusick 52318354Smckusick struct TypeDesc { 52418354Smckusick struct nl *tptr; 52518354Smckusick int tnum; 52618354Smckusick int fwdptrnum; 52718354Smckusick TypeDesc chain; 52818354Smckusick }; 52918354Smckusick 53018354Smckusick #define TABLESIZE 2003 53118354Smckusick 53218354Smckusick #define typehash(t) ( ( ((int) t) >> 2 ) % TABLESIZE ) 53318354Smckusick 53418354Smckusick private int tcount = 1; 53518354Smckusick private TypeDesc typetable[TABLESIZE]; 53618354Smckusick 53718354Smckusick private TypeDesc tdlookup (t) 53818354Smckusick struct nl *t; 53918354Smckusick { 54018354Smckusick register TypeDesc td; 54118354Smckusick 54218354Smckusick td = typetable[typehash(t)]; 54318354Smckusick while (td != NIL && td->tptr != t) { 54418354Smckusick td = td->chain; 54518354Smckusick } 54618354Smckusick return td; 54718354Smckusick } 54818354Smckusick 54918354Smckusick private int typelookup (t) 55018354Smckusick struct nl *t; 55118354Smckusick { 55218354Smckusick register TypeDesc td; 55318354Smckusick int r; 55418354Smckusick 55518354Smckusick td = tdlookup(t); 55618354Smckusick if (td == NIL) { 55718354Smckusick r = 0; 55818354Smckusick } else { 55918354Smckusick r = td->tnum; 56018354Smckusick } 56118354Smckusick return r; 56218354Smckusick } 56318354Smckusick 56418354Smckusick private int entertype (type) 56518354Smckusick struct nl *type; 56618354Smckusick { 56718354Smckusick register TypeDesc td; 56818354Smckusick register int i; 56918354Smckusick 57018354Smckusick td = (TypeDesc) malloc(sizeof(struct TypeDesc)); 57118354Smckusick td->tptr = type; 57218354Smckusick td->tnum = tcount; 57318354Smckusick td->fwdptrnum = 0; 57418354Smckusick ++tcount; 57518354Smckusick i = typehash(type); 57618354Smckusick td->chain = typetable[i]; 57718354Smckusick typetable[i] = td; 57818354Smckusick return td->tnum; 57918354Smckusick } 58018354Smckusick 58118354Smckusick /* 58218354Smckusick * The in_types table currently contains "boolean", "char", "integer", 58318354Smckusick * "real" and "_nil". (See nl.c for definition.) 58418354Smckusick * The lookup call below will give the TYPE class nl entry for these 58518354Smckusick * types. In each case except _nil, the type field of that entry is a RANGE 58618354Smckusick * class nl entry for the type. Sometimes other symbol table entries 58718354Smckusick * point to the TYPE entry (e.g., when there is a range over the base type), 58818354Smckusick * and other entries point to the RANGE entry (e.g., for a variable of the 58918354Smckusick * given type). We don't really want to distinguish between these uses 59018354Smckusick * in dbx, and since it appears that the RANGE entries are not reused if 59118354Smckusick * a range happens to coincide, we will give the two the same identifying 59218354Smckusick * dbx type number. 59318354Smckusick */ 59418354Smckusick 59518354Smckusick private inittypes() 59618354Smckusick { 59718354Smckusick int i; 59818354Smckusick extern char *in_types[]; 59918354Smckusick struct nl *p; 60018354Smckusick 60118354Smckusick for (i = 0; in_types[i] != NIL; i++) { 60218354Smckusick p = lookup(in_types[i]); 60318354Smckusick if (p != NIL) { 60418354Smckusick entertype(p); 60518354Smckusick if (p->type != NIL) { 60618354Smckusick --tcount; /* see comment above */ 60718354Smckusick entertype(p->type); 60818354Smckusick } 60918354Smckusick } 61018354Smckusick } 61118354Smckusick } 61218354Smckusick 61318354Smckusick static genarray (t) 61418354Smckusick struct nl *t; 61518354Smckusick { 61618354Smckusick register struct nl *p; 61718354Smckusick 61818354Smckusick for (p = t->chain; p != NIL; p = p->chain) { 61925263Smckusick putprintf("a", 1); 62018354Smckusick gentype(p); 62118354Smckusick putprintf(";", 1); 62218354Smckusick } 62318354Smckusick gentype(t->type); 62418354Smckusick } 62518354Smckusick 62618354Smckusick /* 62718354Smckusick * Really we should walk through ptr[NL_FIELDLIST] for the fields, 62818354Smckusick * and then do the variant tag and fields separately, but dbx 62918354Smckusick * doesn't support this yet. 63018354Smckusick * So, since all the fields of all the variants are on the chain, 63118354Smckusick * we walk through that. Except that this gives the fields in the 63218354Smckusick * reverse order, so we want to print in reverse order. 63318354Smckusick */ 63418354Smckusick 63518354Smckusick static genrecord (t) 63618354Smckusick struct nl *t; 63718354Smckusick { 63818354Smckusick putprintf("s%d", 1, t->value[NL_OFFS]); 63918354Smckusick if (t->chain != NIL) { 64018354Smckusick genrecfield(t->chain, 1); 64118354Smckusick } 64218354Smckusick putprintf(";", 1); 64318354Smckusick } 64418354Smckusick 64518354Smckusick static genrecfield (t, n) 64618354Smckusick struct nl *t; 64718354Smckusick int n; 64818354Smckusick { 64918354Smckusick if (t->chain != NULL) { 65018354Smckusick genrecfield(t->chain, n + 1); 65118354Smckusick if (n % 2 == 0) { 65218354Smckusick gencontinue(); 65318354Smckusick } 65418354Smckusick } 65518354Smckusick putprintf("%s:", 1, t->symbol); 65618354Smckusick gentype(t->type); 65718354Smckusick putprintf(",%d,%d;", 1, 8*t->value[NL_OFFS], 8*lwidth(t->type)); 65818354Smckusick } 65918354Smckusick 66018354Smckusick static genvarnt (t) 66118354Smckusick struct nl *t; 66218354Smckusick { 66318354Smckusick genrecord(t); 66418354Smckusick } 66518354Smckusick 66618354Smckusick static genptr (t) 66718354Smckusick struct nl *t; 66818354Smckusick { 66918354Smckusick register TypeDesc td; 67018354Smckusick 67118354Smckusick putprintf("*", 1); 67218354Smckusick if (t->type != NIL) { 67318354Smckusick gentype(t->type); 67418354Smckusick } else { 67518354Smckusick /* 67618354Smckusick * unresolved forward pointer: use tcount to represent what is 67718354Smckusick * begin pointed to, to be defined later 67818354Smckusick */ 67918354Smckusick td = tdlookup(t); 68018354Smckusick if (td == NIL) { 68118354Smckusick panic("nil ptr in stab.genptr"); 68218354Smckusick } 68318354Smckusick td->fwdptrnum = tcount; 68418354Smckusick putprintf("%d", 1, tcount); 68518354Smckusick ++tcount; 68618354Smckusick } 68718354Smckusick } 68818354Smckusick 68918354Smckusick /* 69018354Smckusick * The type t is a pointer which has just had its type field filled. 69118354Smckusick * We need to generate a type stab saying that the number saved 69218354Smckusick * in t's fwdptrnum is the same as the t->type's number 69318354Smckusick */ 69418354Smckusick 69518354Smckusick fixfwdtype (t) 69618354Smckusick struct nl *t; 69718354Smckusick { 69818354Smckusick register TypeDesc td; 69918354Smckusick 70018354Smckusick if (opt('g') && oldway == 0) { 70118354Smckusick td = tdlookup(t); 70218354Smckusick if (td != NIL) { 70318354Smckusick putprintf("\t.stabs\t\":t%d=", 1, td->fwdptrnum); 70418354Smckusick gentype(t->type); 70518354Smckusick putprintf("\",0x%x,0,0,0", 0, N_LSYM); 70618354Smckusick } 70718354Smckusick } 70818354Smckusick } 70918354Smckusick 71018354Smckusick static genenum (t) 71118354Smckusick struct nl *t; 71218354Smckusick { 71318354Smckusick register struct nl *e; 71418354Smckusick register int i; 71518354Smckusick 71618354Smckusick putprintf("e", 1); 71718354Smckusick i = 1; 71818354Smckusick e = t->chain; 71918354Smckusick while (e != NULL) { 72018354Smckusick if (i > 2) { 72118354Smckusick gencontinue(); 72218354Smckusick i = 0; 72318354Smckusick } 72418354Smckusick putprintf("%s:%d,", 1, e->symbol, e->range[0]); 72518354Smckusick e = e->chain; 72618354Smckusick ++i; 72718354Smckusick } 72818354Smckusick putprintf(";", 1); 72918354Smckusick } 73018354Smckusick 73118354Smckusick static genset (t) 73218354Smckusick struct nl *t; 73318354Smckusick { 73418354Smckusick putprintf("S", 1); 73518354Smckusick gentype(t->type); 73618354Smckusick } 73718354Smckusick 73818354Smckusick static genrange (t) 73918354Smckusick struct nl *t; 74018354Smckusick { 74118354Smckusick putprintf("r", 1); 74218354Smckusick gentype(t->type); 74318354Smckusick putprintf(";%d;%d", 1, t->range[0], t->range[1]); 74418354Smckusick } 74518354Smckusick 74618354Smckusick static genfparam (t) 74718354Smckusick struct nl *t; 74818354Smckusick { 74918354Smckusick struct nl *p; 75018354Smckusick int count; 75118354Smckusick 75218354Smckusick if (t->type != NULL) { 75318354Smckusick putprintf("f", 1); 75418354Smckusick gentype(t->type); 75518354Smckusick putprintf(",", 1); 75618354Smckusick } else { 75718354Smckusick putprintf("p", 1); 75818354Smckusick } 75918354Smckusick count = 0; 76018354Smckusick for (p = t->ptr[NL_FCHAIN]; p != NULL; p = p->chain) { 76118354Smckusick ++count; 76218354Smckusick } 76318354Smckusick putprintf("%d;", 1, count); 76418354Smckusick for (p = t->ptr[NL_FCHAIN]; p != NULL; p = p->chain) { 76518354Smckusick gentype(p->type); 76618354Smckusick putprintf(",%d;", 1, p->class); 76718354Smckusick } 76818354Smckusick } 76918354Smckusick 77018354Smckusick static genfile (t) 77118354Smckusick struct nl *t; 77218354Smckusick { 77318354Smckusick putprintf("d", 1); 77418354Smckusick gentype(t->type); 77518354Smckusick } 77618354Smckusick 77718354Smckusick static gentype (t) 77818354Smckusick struct nl *t; 77918354Smckusick { 78018354Smckusick int id; 78118354Smckusick 78218354Smckusick if (tcount == 1) { 78318354Smckusick inittypes(); 78418354Smckusick } 78518354Smckusick id = typelookup(t); 78618354Smckusick if (id != 0) { 78718354Smckusick putprintf("%d", 1, id); 78818354Smckusick } else if (t->class == SCAL && t->chain == NULL) { 78918354Smckusick id = typelookup(t->type); 79018354Smckusick if (id != 0) { 79118354Smckusick putprintf("%d", 1, id); 79218354Smckusick } else { 79318354Smckusick genenum(t->type); 79418354Smckusick } 79518354Smckusick } else { 79618354Smckusick id = entertype(t); 79718354Smckusick putprintf("%d=", 1, id); 79818354Smckusick switch (t->class) { 79918354Smckusick case TYPE: 80018354Smckusick gentype(t->type); 80118354Smckusick break; 80218354Smckusick 80318354Smckusick case ARRAY: 80418354Smckusick genarray(t); 80518354Smckusick break; 80618354Smckusick 80718354Smckusick case RECORD: 80818354Smckusick genrecord(t); 80918354Smckusick break; 81018354Smckusick 81118354Smckusick case VARNT: 81218354Smckusick genvarnt(t); 81318354Smckusick break; 81418354Smckusick 81518354Smckusick case REF: 81618354Smckusick gentype(t->type); 81718354Smckusick break; 81818354Smckusick 81918354Smckusick case PTR: 82018354Smckusick genptr(t); 82118354Smckusick break; 82218354Smckusick 82318354Smckusick case SET: 82418354Smckusick genset(t); 82518354Smckusick break; 82618354Smckusick 82718354Smckusick case RANGE: 82818354Smckusick genrange(t); 82918354Smckusick break; 83018354Smckusick 83118354Smckusick case SCAL: 83218354Smckusick genenum(t); 83318354Smckusick break; 83418354Smckusick 83518354Smckusick case FPROC: 83618354Smckusick case FFUNC: 83718354Smckusick genfparam(t); 83818354Smckusick break; 83918354Smckusick 84018354Smckusick case FILET: 84118354Smckusick case PTRFILE: 84218354Smckusick genfile(t); 84318354Smckusick break; 84418354Smckusick 84518354Smckusick default: 84618354Smckusick /* This shouldn't happen */ 84718354Smckusick /* Rather than bomb outright, let debugging go on */ 84818354Smckusick warning(); 84918354Smckusick error("Bad type class found in stab"); 85018354Smckusick putprintf("1", 1, t->class); 85118354Smckusick break; 85218354Smckusick } 85318354Smckusick } 85418354Smckusick } 85518354Smckusick 85618354Smckusick /* 85718354Smckusick * Continue stab information in a namelist new entry. This is necessary 85818354Smckusick * to avoid overflowing putprintf's buffer. 85918354Smckusick */ 86018354Smckusick 86118354Smckusick static gencontinue () 86218354Smckusick { 86318354Smckusick putprintf("?\",0x%x,0,0,0", 0, N_LSYM); 86418354Smckusick putprintf("\t.stabs\t\"", 1); 86518354Smckusick } 86618354Smckusick 867772Speter #endif PC 868