1*22191Sdist /* 2*22191Sdist * Copyright (c) 1980 Regents of the University of California. 3*22191Sdist * All rights reserved. The Berkeley software License Agreement 4*22191Sdist * specifies the terms and conditions for redistribution. 5*22191Sdist */ 6772Speter 718355Smckusick #ifndef lint 8*22191Sdist static char sccsid[] = "@(#)stab.c 5.1 (Berkeley) 06/05/85"; 9*22191Sdist #endif not lint 10826Speter 11772Speter /* 1218354Smckusick * Procedures to put out symbol table information 13826Speter * and stabs for separate compilation type checking. 1418354Smckusick * These use the .stabs, .stabn, and .stabd directives. 15772Speter */ 16772Speter 17772Speter #include "whoami.h" 18772Speter #ifdef PC 19772Speter /* and the rest of the file */ 20772Speter # include "0.h" 2110649Speter # include "objfmt.h" 2215952Smckusick # include "yy.h" 23772Speter # include <stab.h> 24772Speter 25842Speter /* 26842Speter * additional symbol definition for <stab.h> 27842Speter * that is used by the separate compilation facility -- 28842Speter * eventually, <stab.h> should be updated to include this 29842Speter */ 30772Speter 31842Speter # include "pstab.h" 32772Speter # include "pc.h" 33772Speter 3418354Smckusick 3518354Smckusick #define private static 3618354Smckusick 3718354Smckusick int oldway = 0; 3818354Smckusick 39772Speter /* 40826Speter * absolute value: line numbers are negative if error recovery. 41826Speter */ 42826Speter #define ABS( x ) ( x < 0 ? -x : x ) 4318355Smckusick long checksum(); 44826Speter 4518354Smckusick /* 4618354Smckusick * Generate information about variables. 4718354Smckusick */ 4818354Smckusick 4918354Smckusick stabgvar (p, length, line) 5018354Smckusick struct nl *p; 5118354Smckusick int length, line; 5218354Smckusick { 5318354Smckusick putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x", 5418354Smckusick 0, p->symbol, N_PC, N_PGVAR, ABS(line) 5518354Smckusick ); 5618354Smckusick if (oldway != 0) { 5718354Smckusick oldstabgvar(p->symbol, p2type(p->type), 0, length, line); 5818354Smckusick } else if (opt('g')) { 5918354Smckusick putprintf("\t.stabs\t\"%s:G", 1, p->symbol); 6018354Smckusick gentype(p->type); 6118354Smckusick putprintf("\",0x%x,0,0x%x,0", 0, N_GSYM, length); 6218354Smckusick } 6318354Smckusick } 6418354Smckusick 6518354Smckusick stablvar (p, offset, length) 6618354Smckusick struct nl *p; 6718354Smckusick int offset, length; 6818354Smckusick { 6918354Smckusick int level; 7018354Smckusick 7118354Smckusick level = (p->nl_block & 037); 7218354Smckusick if (oldway != 0) { 7318354Smckusick oldstablvar(p->symbol, p2type(p->type), level, offset, length); 7418354Smckusick } else if (opt('g')) { 7518354Smckusick putprintf("\t.stabs\t\"%s:", 1, p->symbol); 7618354Smckusick gentype(p->type); 7718354Smckusick putprintf("\",0x%x,0,0x%x,0x%x", 0, N_LSYM, length, offset); 7818354Smckusick } 7918354Smckusick } 8018354Smckusick 81826Speter /* 822164Speter * global variables 83772Speter */ 8418355Smckusick /*ARGSUSED*/ 8518354Smckusick oldstabgvar( name , type , offset , length , line ) 86772Speter char *name; 87772Speter int type; 88772Speter int offset; 89772Speter int length; 90826Speter int line; 91772Speter { 92772Speter if ( ! opt('g') ) { 93772Speter return; 94772Speter } 95772Speter putprintf( " .stabs \"" , 1 ); 9618355Smckusick putprintf( NAMEFORMAT , 1 , (int) name ); 972164Speter putprintf( "\",0x%x,0,0x%x,0" , 0 , N_GSYM , type ); 982164Speter putprintf( " .stabs \"" , 1 ); 9918355Smckusick putprintf( NAMEFORMAT , 1 , (int) name ); 1002164Speter putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length ); 1012164Speter } 1022164Speter 1032164Speter /* 1042164Speter * local variables 1052164Speter */ 10618355Smckusick /*ARGSUSED*/ 10718354Smckusick oldstablvar( name , type , level , offset , length ) 1082164Speter char *name; 1092164Speter int type; 1102164Speter int level; 1112164Speter int offset; 1122164Speter int length; 1132164Speter { 1142164Speter 1152164Speter if ( ! opt('g') ) { 1162164Speter return; 117772Speter } 118772Speter putprintf( " .stabs \"" , 1 ); 11918355Smckusick putprintf( NAMEFORMAT , 1 , (int) name ); 1202164Speter putprintf( "\",0x%x,0,0x%x,0x%x" , 0 , N_LSYM , type , -offset ); 1212164Speter putprintf( " .stabs \"" , 1 ); 12218355Smckusick putprintf( NAMEFORMAT , 1 , (int) name ); 123826Speter putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length ); 124772Speter } 125772Speter 126772Speter 12718354Smckusick stabparam (p, offset, length) 12818354Smckusick struct nl *p; 12918354Smckusick int offset, length; 13018354Smckusick { 13118354Smckusick if (oldway != 0) { 13218354Smckusick oldstabparam(p->symbol, p2type(p->type), offset, length); 13318354Smckusick } else if (opt('g')) { 13418354Smckusick putprintf("\t.stabs\t\"%s:", 1, p->symbol); 13518354Smckusick if (p->class == REF) { 13618354Smckusick putprintf("v", 1); 13718354Smckusick } else { 13818354Smckusick putprintf("p", 1); 13918354Smckusick } 14018354Smckusick gentype((p->class == FPROC || p->class ==FFUNC) ? p : p->type); 14118354Smckusick putprintf("\",0x%x,0,0x%x,0x%x", 0, N_PSYM, length, offset); 14218354Smckusick } 14318354Smckusick } 14418354Smckusick 145772Speter /* 146772Speter * parameters 147772Speter */ 14818354Smckusick oldstabparam( name , type , offset , length ) 149772Speter char *name; 150772Speter int type; 151772Speter int offset; 152772Speter int length; 153772Speter { 154772Speter 155772Speter if ( ! opt('g') ) { 156772Speter return; 157772Speter } 158772Speter putprintf( " .stabs \"" , 1 ); 15918355Smckusick putprintf( NAMEFORMAT , 1 , (int) name ); 160826Speter putprintf( "\",0x%x,0,0x%x,0x%x" , 0 , N_PSYM , type , offset ); 161772Speter putprintf( " .stabs \"" , 1 ); 16218355Smckusick putprintf( NAMEFORMAT , 1 , (int) name ); 163826Speter putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length ); 164772Speter } 165772Speter 166772Speter /* 167772Speter * fields 168772Speter */ 169772Speter 170772Speter /* 171772Speter * left brackets 17218354Smckusick * (dbx handles module-2 without these, so we won't use them either) 173772Speter */ 174772Speter stablbrac( level ) 175772Speter int level; 176772Speter { 177772Speter 17818354Smckusick if ( ! opt('g') || oldway == 0 ) { 179772Speter return; 180772Speter } 181826Speter putprintf( " .stabd 0x%x,0,0x%x" , 0 , N_LBRAC , level ); 182772Speter } 183772Speter 184772Speter /* 185772Speter * right brackets 186772Speter */ 187772Speter stabrbrac( level ) 188772Speter int level; 189772Speter { 190772Speter 19118354Smckusick if ( ! opt('g') || oldway == 0 ) { 192772Speter return; 193772Speter } 194826Speter putprintf( " .stabd 0x%x,0,0x%x" , 0 , N_RBRAC , level ); 195772Speter } 196772Speter 19718354Smckusick stabfunc (p, name, line, level) 19818354Smckusick struct nl *p; 19918354Smckusick char *name; 20018354Smckusick int line, level; 20118354Smckusick { 20218354Smckusick char extname[BUFSIZ],nestspec[BUFSIZ]; 20318354Smckusick 20418354Smckusick if ( level == 1 ) { 20518354Smckusick if (p->class == FUNC) { 20618354Smckusick putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x" , 20718354Smckusick 0 , name , N_PC , N_PGFUNC , ABS( line ) 20818354Smckusick ); 20918354Smckusick } else if (p->class == PROC) { 21018354Smckusick putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x" , 21118354Smckusick 0 , name , N_PC , N_PGPROC , ABS( line ) 21218354Smckusick ); 21318354Smckusick } 21418354Smckusick } 21518354Smckusick if (oldway != 0) { 21618354Smckusick oldstabfunc(name, p->class, line, level); 21718354Smckusick } else if (opt('g')) { 21818354Smckusick putprintf("\t.stabs\t\"%s:", 1, name); 21918354Smckusick if (p->class == FUNC) { 22018354Smckusick putprintf("F", 1); 22118354Smckusick gentype(p->type); 22218354Smckusick putprintf(",", 1); 22318354Smckusick } else { 22418354Smckusick putprintf("P,", 1); 22518354Smckusick } 22618354Smckusick sextname(extname, name, level); /* set extname to entry label */ 22718354Smckusick putprintf("%s,", 1, &(extname[1])); /* remove initial underbar */ 22818354Smckusick snestspec(nestspec, level); 22918354Smckusick putprintf("%s\",0x%x,0,0,%s", 0, nestspec, N_FUN, extname); 23018354Smckusick } 23118354Smckusick } 23218354Smckusick 233772Speter /* 23418354Smckusick * construct the colon-separated static nesting string into a 23518354Smckusick * caller-supplied buffer 23618354Smckusick */ 23718354Smckusick private snestspec(buffer, level) 23818354Smckusick char buffer[]; 23918354Smckusick int level; 24018354Smckusick { 24118354Smckusick char *starthere; 24218354Smckusick int i; 24318354Smckusick 24418354Smckusick if (level <= 1) { 24518354Smckusick buffer[0] = '\0'; 24618354Smckusick } else { 24718354Smckusick starthere = &buffer[0]; 24818354Smckusick for ( i = 1 ; i < level ; i++ ) { 24918354Smckusick sprintf(starthere, "%s:", enclosing[i]); 25018354Smckusick starthere += strlen(enclosing[i]) + 1; 25118354Smckusick } 25218354Smckusick *starthere-- = '\0'; /* remove last colon */ 25318354Smckusick if (starthere >= &buffer[BUFSIZ-1]) { 25418354Smckusick panic("snestspec"); 25518354Smckusick } 25618354Smckusick } 25718354Smckusick } 25818354Smckusick 25918354Smckusick /* 260772Speter * functions 261772Speter */ 26218354Smckusick oldstabfunc( name , typeclass , line , level ) 263772Speter char *name; 2647925Smckusick int typeclass; 265772Speter int line; 266772Speter long level; 267772Speter { 2683365Speter char extname[ BUFSIZ ]; 269772Speter 270826Speter /* 271826Speter * for sdb 272826Speter */ 273772Speter if ( ! opt('g') ) { 274772Speter return; 275772Speter } 276772Speter putprintf( " .stabs \"" , 1 ); 27718355Smckusick putprintf( NAMEFORMAT , 1 , (int) name ); 27818355Smckusick sextname( extname , name , (int) level ); 27918355Smckusick putprintf( "\",0x%x,0,0x%x,%s" , 0 , N_FUN , line , (int) extname ); 280772Speter } 281772Speter 282772Speter /* 283772Speter * source line numbers 284772Speter */ 285772Speter stabline( line ) 286772Speter int line; 287772Speter { 288772Speter if ( ! opt('g') ) { 289772Speter return; 290772Speter } 291826Speter putprintf( " .stabd 0x%x,0,0x%x" , 0 , N_SLINE , ABS( line ) ); 292772Speter } 293772Speter 294772Speter /* 29518354Smckusick * source files get none or more of these: 29618354Smckusick * one as they are entered, 29718354Smckusick * and one every time they are returned to from nested #includes 298772Speter */ 29918354Smckusick stabsource(filename, firsttime) 300772Speter char *filename; 30118354Smckusick bool firsttime; 30215952Smckusick { 30315952Smckusick int label; 30415952Smckusick 30515952Smckusick /* 30615952Smckusick * for separate compilation 30715952Smckusick */ 30815952Smckusick putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x", 0, 30918355Smckusick (int) filename, N_PC, N_PSO, N_FLAGCHECKSUM); 31015952Smckusick /* 31118354Smckusick * for debugger 31215952Smckusick */ 31315952Smckusick if ( ! opt('g') ) { 31415952Smckusick return; 315772Speter } 31618354Smckusick if (oldway != 0) { 31718355Smckusick label = (int) getlab(); 31818354Smckusick putprintf( " .stabs \"" , 1 ); 31918354Smckusick putprintf( NAMEFORMAT , 1 , filename ); 32018354Smckusick putprintf( "\",0x%x,0,0," , 1 , N_SO ); 32118354Smckusick putprintf( PREFIXFORMAT , 0 , LLABELPREFIX , label ); 32218354Smckusick putprintf( PREFIXFORMAT , 1 , LLABELPREFIX , label ); 32318354Smckusick putprintf( ":" , 0 ); 32418354Smckusick } else { 32518354Smckusick if (firsttime) { 32618354Smckusick putprintf( " .stabs \"" , 1 ); 32718354Smckusick putprintf( NAMEFORMAT , 1 , filename ); 32818354Smckusick putprintf( "\",0x%x,0,0,0" , 0 , N_SO ); 32918354Smckusick } 33018354Smckusick } 33115952Smckusick } 332772Speter 333772Speter /* 334772Speter * included files get one or more of these: 335772Speter * one as they are entered by a #include, 33615952Smckusick * and one every time they are returned to from nested #includes. 337772Speter */ 33815952Smckusick stabinclude(filename, firsttime) 339772Speter char *filename; 34015952Smckusick bool firsttime; 34115952Smckusick { 34218355Smckusick int label; 34315952Smckusick long check; 34415952Smckusick 34515952Smckusick /* 34615952Smckusick * for separate compilation 34715952Smckusick */ 34815952Smckusick if (firsttime) { 34915952Smckusick check = checksum(filename); 35015952Smckusick } else { 35115952Smckusick check = N_FLAGCHECKSUM; 35215952Smckusick } 35315952Smckusick putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x", 0, 35418355Smckusick (int) filename, N_PC, N_PSOL, check); 35515952Smckusick /* 35615952Smckusick * for sdb 35715952Smckusick */ 35815952Smckusick if ( ! opt('g') ) { 35915952Smckusick return; 36015952Smckusick } 36118354Smckusick if (oldway != 0) { 36218355Smckusick label = (int) getlab(); 36318354Smckusick putprintf( " .stabs \"" , 1 ); 36418354Smckusick putprintf( NAMEFORMAT , 1 , filename ); 36518354Smckusick putprintf( "\",0x%x,0,0," , 1 , N_SOL ); 36618354Smckusick putprintf( PREFIXFORMAT , 0 , LLABELPREFIX , label ); 36718354Smckusick putprintf( PREFIXFORMAT , 1 , LLABELPREFIX , label ); 36818354Smckusick putprintf( ":" , 0 ); 36918354Smckusick } 37015952Smckusick } 37115952Smckusick 37215952Smckusick /* 37315952Smckusick * anyone know a good checksum for ascii files? 37415952Smckusick * this does a rotate-left and then exclusive-or's in the character. 37515952Smckusick * also, it avoids returning checksums of 0. 37615952Smckusick * The rotate is implemented by shifting and adding back the 37715952Smckusick * sign bit when negative. 37815952Smckusick */ 37915952Smckusick long 38015952Smckusick checksum(filename) 38115952Smckusick char *filename; 38215952Smckusick { 38315952Smckusick FILE *filep; 38415952Smckusick register int input; 38515952Smckusick register long check; 38615952Smckusick 38715952Smckusick filep = fopen(filename, "r"); 38815952Smckusick if (filep == NULL) { 38915952Smckusick perror(filename); 39015952Smckusick pexit(DIED); 39115952Smckusick } 39215952Smckusick check = 0; 39315952Smckusick while ((input = getc(filep)) != EOF) { 39415952Smckusick if (check < 0) { 39515952Smckusick check <<= 1; 39615952Smckusick check += 1; 39715952Smckusick } else { 39815952Smckusick check <<= 1; 39915942Smckusick } 40015952Smckusick check ^= input; 40114128Speter } 40218355Smckusick (void) fclose(filep); 40315952Smckusick if ((unsigned) check <= N_FLAGCHECKSUM) { 40415952Smckusick return N_FLAGCHECKSUM + 1; 40515952Smckusick } else { 40615952Smckusick return check; 40715952Smckusick } 40815952Smckusick } 40914128Speter 410772Speter /* 411772Speter * global Pascal symbols : 412772Speter * labels, types, constants, and external procedure and function names: 413772Speter * These are used by the separate compilation facility 414772Speter * to be able to check for disjoint header files. 415772Speter */ 416772Speter 417826Speter /* 418826Speter * global labels 419826Speter */ 420842Speter stabglabel( label , line ) 421826Speter char *label; 422826Speter int line; 423772Speter { 424772Speter 425842Speter putprintf( " .stabs \"%s\",0x%x,0,0x%x,0x%x" , 0 42618355Smckusick , (int) label , N_PC , N_PGLABEL , ABS( line ) ); 427772Speter } 428772Speter 429826Speter /* 430826Speter * global constants 431826Speter */ 432842Speter stabgconst( const , line ) 433842Speter char *const; 434826Speter int line; 435772Speter { 436772Speter 437842Speter putprintf( " .stabs \"%s\",0x%x,0,0x%x,0x%x" , 0 43818355Smckusick , (int) const , N_PC , N_PGCONST , ABS( line ) ); 439772Speter } 440772Speter 44118354Smckusick /* 44218354Smckusick * Generate symbolic information about a constant. 44318354Smckusick */ 444772Speter 44518354Smckusick stabconst (c) 44618354Smckusick struct nl *c; 44718354Smckusick { 44818354Smckusick if (opt('g') && oldway == 0) { 44918354Smckusick putprintf("\t.stabs\t\"%s:c=", 1, c->symbol); 45018354Smckusick if (c->type == nl + TSTR) { 45118354Smckusick putprintf("s'%s'", 1, c->ptr[0]); 45218354Smckusick } else if (c->type == nl + T1CHAR) { 45318354Smckusick putprintf("c%d", 1, c->range[0]); 45418354Smckusick } else if (isa(c->type, "i")) { 45518354Smckusick putprintf("i%d", 1, c->range[0]); 45618354Smckusick } else if (isa(c->type, "d")) { 45718354Smckusick putprintf("r%g", 1, c->real); 45818354Smckusick } else { 45918354Smckusick putprintf("e", 1); 46018354Smckusick gentype(c->type); 46118354Smckusick putprintf(",%d", 1, c->range[0]); 46218354Smckusick } 46318354Smckusick putprintf("\",0x%x,0,0x%x,0x%x", 0, N_LSYM, 0, 0); 464772Speter } 46518354Smckusick } 466772Speter 46718354Smckusick stabgtype (name, type, line) 46818354Smckusick char *name; 46918354Smckusick struct nl *type; 47018354Smckusick int line; 47118354Smckusick { 47218354Smckusick putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x" , 47318354Smckusick 0, name, N_PC , N_PGTYPE, ABS(line) 47418354Smckusick ); 47518354Smckusick if (oldway == 0) { 47618354Smckusick stabltype(name, type); 47718354Smckusick } 47818354Smckusick } 479772Speter 48018354Smckusick stabltype (name, type) 48118354Smckusick char *name; 48218354Smckusick struct nl *type; 48318354Smckusick { 48418354Smckusick if (opt('g')) { 48518354Smckusick putprintf("\t.stabs\t\"%s:t", 1, name); 48618354Smckusick gentype(type); 48718354Smckusick putprintf("\",0x%x,0,0,0", 0, N_LSYM); 48818354Smckusick } 48918354Smckusick } 49018354Smckusick 491826Speter /* 492826Speter * external functions and procedures 493826Speter */ 4947925Smckusick stabefunc( name , typeclass , line ) 495826Speter char *name; 4967925Smckusick int typeclass; 497826Speter int line; 498772Speter { 499826Speter int type; 500772Speter 5017925Smckusick if ( typeclass == FUNC ) { 502842Speter type = N_PEFUNC; 5037925Smckusick } else if ( typeclass == PROC ) { 504842Speter type = N_PEPROC; 505826Speter } else { 506826Speter return; 507772Speter } 508842Speter putprintf( " .stabs \"%s\",0x%x,0,0x%x,0x%x" , 0 50918355Smckusick , (int) name , N_PC , type , ABS( line ) ); 510772Speter } 511772Speter 51218354Smckusick /* 51318354Smckusick * Generate type information encoded as a string for dbx. 51418354Smckusick * The fwdptrnum field is used only when the type is a pointer 51518354Smckusick * to a type that isn't known when it was entered. When the 51618354Smckusick * type field is filled for some such tptr, fixfwdtype should 51718354Smckusick * be called to output an equivalencing type definition. 51818354Smckusick */ 51918354Smckusick 52018354Smckusick typedef struct TypeDesc *TypeDesc; 52118354Smckusick 52218354Smckusick struct TypeDesc { 52318354Smckusick struct nl *tptr; 52418354Smckusick int tnum; 52518354Smckusick int fwdptrnum; 52618354Smckusick TypeDesc chain; 52718354Smckusick }; 52818354Smckusick 52918354Smckusick #define TABLESIZE 2003 53018354Smckusick 53118354Smckusick #define typehash(t) ( ( ((int) t) >> 2 ) % TABLESIZE ) 53218354Smckusick 53318354Smckusick private int tcount = 1; 53418354Smckusick private TypeDesc typetable[TABLESIZE]; 53518354Smckusick 53618354Smckusick private TypeDesc tdlookup (t) 53718354Smckusick struct nl *t; 53818354Smckusick { 53918354Smckusick register TypeDesc td; 54018354Smckusick 54118354Smckusick td = typetable[typehash(t)]; 54218354Smckusick while (td != NIL && td->tptr != t) { 54318354Smckusick td = td->chain; 54418354Smckusick } 54518354Smckusick return td; 54618354Smckusick } 54718354Smckusick 54818354Smckusick private int typelookup (t) 54918354Smckusick struct nl *t; 55018354Smckusick { 55118354Smckusick register TypeDesc td; 55218354Smckusick int r; 55318354Smckusick 55418354Smckusick td = tdlookup(t); 55518354Smckusick if (td == NIL) { 55618354Smckusick r = 0; 55718354Smckusick } else { 55818354Smckusick r = td->tnum; 55918354Smckusick } 56018354Smckusick return r; 56118354Smckusick } 56218354Smckusick 56318354Smckusick private int entertype (type) 56418354Smckusick struct nl *type; 56518354Smckusick { 56618354Smckusick register TypeDesc td; 56718354Smckusick register int i; 56818354Smckusick 56918354Smckusick td = (TypeDesc) malloc(sizeof(struct TypeDesc)); 57018354Smckusick td->tptr = type; 57118354Smckusick td->tnum = tcount; 57218354Smckusick td->fwdptrnum = 0; 57318354Smckusick ++tcount; 57418354Smckusick i = typehash(type); 57518354Smckusick td->chain = typetable[i]; 57618354Smckusick typetable[i] = td; 57718354Smckusick return td->tnum; 57818354Smckusick } 57918354Smckusick 58018354Smckusick /* 58118354Smckusick * The in_types table currently contains "boolean", "char", "integer", 58218354Smckusick * "real" and "_nil". (See nl.c for definition.) 58318354Smckusick * The lookup call below will give the TYPE class nl entry for these 58418354Smckusick * types. In each case except _nil, the type field of that entry is a RANGE 58518354Smckusick * class nl entry for the type. Sometimes other symbol table entries 58618354Smckusick * point to the TYPE entry (e.g., when there is a range over the base type), 58718354Smckusick * and other entries point to the RANGE entry (e.g., for a variable of the 58818354Smckusick * given type). We don't really want to distinguish between these uses 58918354Smckusick * in dbx, and since it appears that the RANGE entries are not reused if 59018354Smckusick * a range happens to coincide, we will give the two the same identifying 59118354Smckusick * dbx type number. 59218354Smckusick */ 59318354Smckusick 59418354Smckusick private inittypes() 59518354Smckusick { 59618354Smckusick int i; 59718354Smckusick extern char *in_types[]; 59818354Smckusick struct nl *p; 59918354Smckusick 60018354Smckusick for (i = 0; in_types[i] != NIL; i++) { 60118354Smckusick p = lookup(in_types[i]); 60218354Smckusick if (p != NIL) { 60318354Smckusick entertype(p); 60418354Smckusick if (p->type != NIL) { 60518354Smckusick --tcount; /* see comment above */ 60618354Smckusick entertype(p->type); 60718354Smckusick } 60818354Smckusick } 60918354Smckusick } 61018354Smckusick } 61118354Smckusick 61218354Smckusick static genarray (t) 61318354Smckusick struct nl *t; 61418354Smckusick { 61518354Smckusick register struct nl *p; 61618354Smckusick 61718354Smckusick putprintf("a", 1); 61818354Smckusick for (p = t->chain; p != NIL; p = p->chain) { 61918354Smckusick gentype(p); 62018354Smckusick putprintf(";", 1); 62118354Smckusick } 62218354Smckusick gentype(t->type); 62318354Smckusick } 62418354Smckusick 62518354Smckusick /* 62618354Smckusick * Really we should walk through ptr[NL_FIELDLIST] for the fields, 62718354Smckusick * and then do the variant tag and fields separately, but dbx 62818354Smckusick * doesn't support this yet. 62918354Smckusick * So, since all the fields of all the variants are on the chain, 63018354Smckusick * we walk through that. Except that this gives the fields in the 63118354Smckusick * reverse order, so we want to print in reverse order. 63218354Smckusick */ 63318354Smckusick 63418354Smckusick static genrecord (t) 63518354Smckusick struct nl *t; 63618354Smckusick { 63718354Smckusick putprintf("s%d", 1, t->value[NL_OFFS]); 63818354Smckusick if (t->chain != NIL) { 63918354Smckusick genrecfield(t->chain, 1); 64018354Smckusick } 64118354Smckusick putprintf(";", 1); 64218354Smckusick } 64318354Smckusick 64418354Smckusick static genrecfield (t, n) 64518354Smckusick struct nl *t; 64618354Smckusick int n; 64718354Smckusick { 64818354Smckusick if (t->chain != NULL) { 64918354Smckusick genrecfield(t->chain, n + 1); 65018354Smckusick if (n % 2 == 0) { 65118354Smckusick gencontinue(); 65218354Smckusick } 65318354Smckusick } 65418354Smckusick putprintf("%s:", 1, t->symbol); 65518354Smckusick gentype(t->type); 65618354Smckusick putprintf(",%d,%d;", 1, 8*t->value[NL_OFFS], 8*lwidth(t->type)); 65718354Smckusick } 65818354Smckusick 65918354Smckusick static genvarnt (t) 66018354Smckusick struct nl *t; 66118354Smckusick { 66218354Smckusick genrecord(t); 66318354Smckusick } 66418354Smckusick 66518354Smckusick static genptr (t) 66618354Smckusick struct nl *t; 66718354Smckusick { 66818354Smckusick register TypeDesc td; 66918354Smckusick 67018354Smckusick putprintf("*", 1); 67118354Smckusick if (t->type != NIL) { 67218354Smckusick gentype(t->type); 67318354Smckusick } else { 67418354Smckusick /* 67518354Smckusick * unresolved forward pointer: use tcount to represent what is 67618354Smckusick * begin pointed to, to be defined later 67718354Smckusick */ 67818354Smckusick td = tdlookup(t); 67918354Smckusick if (td == NIL) { 68018354Smckusick panic("nil ptr in stab.genptr"); 68118354Smckusick } 68218354Smckusick td->fwdptrnum = tcount; 68318354Smckusick putprintf("%d", 1, tcount); 68418354Smckusick ++tcount; 68518354Smckusick } 68618354Smckusick } 68718354Smckusick 68818354Smckusick /* 68918354Smckusick * The type t is a pointer which has just had its type field filled. 69018354Smckusick * We need to generate a type stab saying that the number saved 69118354Smckusick * in t's fwdptrnum is the same as the t->type's number 69218354Smckusick */ 69318354Smckusick 69418354Smckusick fixfwdtype (t) 69518354Smckusick struct nl *t; 69618354Smckusick { 69718354Smckusick register TypeDesc td; 69818354Smckusick 69918354Smckusick if (opt('g') && oldway == 0) { 70018354Smckusick td = tdlookup(t); 70118354Smckusick if (td != NIL) { 70218354Smckusick putprintf("\t.stabs\t\":t%d=", 1, td->fwdptrnum); 70318354Smckusick gentype(t->type); 70418354Smckusick putprintf("\",0x%x,0,0,0", 0, N_LSYM); 70518354Smckusick } 70618354Smckusick } 70718354Smckusick } 70818354Smckusick 70918354Smckusick static genenum (t) 71018354Smckusick struct nl *t; 71118354Smckusick { 71218354Smckusick register struct nl *e; 71318354Smckusick register int i; 71418354Smckusick 71518354Smckusick putprintf("e", 1); 71618354Smckusick i = 1; 71718354Smckusick e = t->chain; 71818354Smckusick while (e != NULL) { 71918354Smckusick if (i > 2) { 72018354Smckusick gencontinue(); 72118354Smckusick i = 0; 72218354Smckusick } 72318354Smckusick putprintf("%s:%d,", 1, e->symbol, e->range[0]); 72418354Smckusick e = e->chain; 72518354Smckusick ++i; 72618354Smckusick } 72718354Smckusick putprintf(";", 1); 72818354Smckusick } 72918354Smckusick 73018354Smckusick static genset (t) 73118354Smckusick struct nl *t; 73218354Smckusick { 73318354Smckusick putprintf("S", 1); 73418354Smckusick gentype(t->type); 73518354Smckusick } 73618354Smckusick 73718354Smckusick static genrange (t) 73818354Smckusick struct nl *t; 73918354Smckusick { 74018354Smckusick putprintf("r", 1); 74118354Smckusick gentype(t->type); 74218354Smckusick putprintf(";%d;%d", 1, t->range[0], t->range[1]); 74318354Smckusick } 74418354Smckusick 74518354Smckusick static genfparam (t) 74618354Smckusick struct nl *t; 74718354Smckusick { 74818354Smckusick struct nl *p; 74918354Smckusick int count; 75018354Smckusick 75118354Smckusick if (t->type != NULL) { 75218354Smckusick putprintf("f", 1); 75318354Smckusick gentype(t->type); 75418354Smckusick putprintf(",", 1); 75518354Smckusick } else { 75618354Smckusick putprintf("p", 1); 75718354Smckusick } 75818354Smckusick count = 0; 75918354Smckusick for (p = t->ptr[NL_FCHAIN]; p != NULL; p = p->chain) { 76018354Smckusick ++count; 76118354Smckusick } 76218354Smckusick putprintf("%d;", 1, count); 76318354Smckusick for (p = t->ptr[NL_FCHAIN]; p != NULL; p = p->chain) { 76418354Smckusick gentype(p->type); 76518354Smckusick putprintf(",%d;", 1, p->class); 76618354Smckusick } 76718354Smckusick } 76818354Smckusick 76918354Smckusick static genfile (t) 77018354Smckusick struct nl *t; 77118354Smckusick { 77218354Smckusick putprintf("d", 1); 77318354Smckusick gentype(t->type); 77418354Smckusick } 77518354Smckusick 77618354Smckusick static gentype (t) 77718354Smckusick struct nl *t; 77818354Smckusick { 77918354Smckusick int id; 78018354Smckusick 78118354Smckusick if (tcount == 1) { 78218354Smckusick inittypes(); 78318354Smckusick } 78418354Smckusick id = typelookup(t); 78518354Smckusick if (id != 0) { 78618354Smckusick putprintf("%d", 1, id); 78718354Smckusick } else if (t->class == SCAL && t->chain == NULL) { 78818354Smckusick id = typelookup(t->type); 78918354Smckusick if (id != 0) { 79018354Smckusick putprintf("%d", 1, id); 79118354Smckusick } else { 79218354Smckusick genenum(t->type); 79318354Smckusick } 79418354Smckusick } else { 79518354Smckusick id = entertype(t); 79618354Smckusick putprintf("%d=", 1, id); 79718354Smckusick switch (t->class) { 79818354Smckusick case TYPE: 79918354Smckusick gentype(t->type); 80018354Smckusick break; 80118354Smckusick 80218354Smckusick case ARRAY: 80318354Smckusick genarray(t); 80418354Smckusick break; 80518354Smckusick 80618354Smckusick case RECORD: 80718354Smckusick genrecord(t); 80818354Smckusick break; 80918354Smckusick 81018354Smckusick case VARNT: 81118354Smckusick genvarnt(t); 81218354Smckusick break; 81318354Smckusick 81418354Smckusick case REF: 81518354Smckusick gentype(t->type); 81618354Smckusick break; 81718354Smckusick 81818354Smckusick case PTR: 81918354Smckusick genptr(t); 82018354Smckusick break; 82118354Smckusick 82218354Smckusick case SET: 82318354Smckusick genset(t); 82418354Smckusick break; 82518354Smckusick 82618354Smckusick case RANGE: 82718354Smckusick genrange(t); 82818354Smckusick break; 82918354Smckusick 83018354Smckusick case SCAL: 83118354Smckusick genenum(t); 83218354Smckusick break; 83318354Smckusick 83418354Smckusick case FPROC: 83518354Smckusick case FFUNC: 83618354Smckusick genfparam(t); 83718354Smckusick break; 83818354Smckusick 83918354Smckusick case FILET: 84018354Smckusick case PTRFILE: 84118354Smckusick genfile(t); 84218354Smckusick break; 84318354Smckusick 84418354Smckusick default: 84518354Smckusick /* This shouldn't happen */ 84618354Smckusick /* Rather than bomb outright, let debugging go on */ 84718354Smckusick warning(); 84818354Smckusick error("Bad type class found in stab"); 84918354Smckusick putprintf("1", 1, t->class); 85018354Smckusick break; 85118354Smckusick } 85218354Smckusick } 85318354Smckusick } 85418354Smckusick 85518354Smckusick /* 85618354Smckusick * Continue stab information in a namelist new entry. This is necessary 85718354Smckusick * to avoid overflowing putprintf's buffer. 85818354Smckusick */ 85918354Smckusick 86018354Smckusick static gencontinue () 86118354Smckusick { 86218354Smckusick putprintf("?\",0x%x,0,0,0", 0, N_LSYM); 86318354Smckusick putprintf("\t.stabs\t\"", 1); 86418354Smckusick } 86518354Smckusick 866772Speter #endif PC 867