1826Speter /* Copyright (c) 1980 Regents of the University of California */ 2772Speter 3*18354Smckusick static char sccsid[] = "@(#)stab.c 1.9.1.1 03/15/85"; 4826Speter 5772Speter /* 6*18354Smckusick * Procedures to put out symbol table information 7826Speter * and stabs for separate compilation type checking. 8*18354Smckusick * These use the .stabs, .stabn, and .stabd directives. 9772Speter */ 10772Speter 11772Speter #include "whoami.h" 12772Speter #ifdef PC 13772Speter /* and the rest of the file */ 14772Speter # include "0.h" 1510649Speter # include "objfmt.h" 1615952Smckusick # include "yy.h" 17772Speter # include <stab.h> 18772Speter 19842Speter /* 20842Speter * additional symbol definition for <stab.h> 21842Speter * that is used by the separate compilation facility -- 22842Speter * eventually, <stab.h> should be updated to include this 23842Speter */ 24772Speter 25842Speter # include "pstab.h" 26772Speter # include "pc.h" 27772Speter 28*18354Smckusick 29*18354Smckusick #define private static 30*18354Smckusick 31*18354Smckusick int oldway = 0; 32*18354Smckusick 33772Speter /* 34826Speter * absolute value: line numbers are negative if error recovery. 35826Speter */ 36826Speter #define ABS( x ) ( x < 0 ? -x : x ) 37826Speter 38*18354Smckusick /* 39*18354Smckusick * Generate information about variables. 40*18354Smckusick */ 41*18354Smckusick 42*18354Smckusick stabgvar (p, length, line) 43*18354Smckusick struct nl *p; 44*18354Smckusick int length, line; 45*18354Smckusick { 46*18354Smckusick putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x", 47*18354Smckusick 0, p->symbol, N_PC, N_PGVAR, ABS(line) 48*18354Smckusick ); 49*18354Smckusick if (oldway != 0) { 50*18354Smckusick oldstabgvar(p->symbol, p2type(p->type), 0, length, line); 51*18354Smckusick } else if (opt('g')) { 52*18354Smckusick putprintf("\t.stabs\t\"%s:G", 1, p->symbol); 53*18354Smckusick gentype(p->type); 54*18354Smckusick putprintf("\",0x%x,0,0x%x,0", 0, N_GSYM, length); 55*18354Smckusick } 56*18354Smckusick } 57*18354Smckusick 58*18354Smckusick stablvar (p, offset, length) 59*18354Smckusick struct nl *p; 60*18354Smckusick int offset, length; 61*18354Smckusick { 62*18354Smckusick int level; 63*18354Smckusick 64*18354Smckusick level = (p->nl_block & 037); 65*18354Smckusick if (oldway != 0) { 66*18354Smckusick oldstablvar(p->symbol, p2type(p->type), level, offset, length); 67*18354Smckusick } else if (opt('g')) { 68*18354Smckusick putprintf("\t.stabs\t\"%s:", 1, p->symbol); 69*18354Smckusick gentype(p->type); 70*18354Smckusick putprintf("\",0x%x,0,0x%x,0x%x", 0, N_LSYM, length, offset); 71*18354Smckusick } 72*18354Smckusick } 73*18354Smckusick 74826Speter /* 752164Speter * global variables 76772Speter */ 77*18354Smckusick oldstabgvar( name , type , offset , length , line ) 78772Speter char *name; 79772Speter int type; 80772Speter int offset; 81772Speter int length; 82826Speter int line; 83772Speter { 84772Speter if ( ! opt('g') ) { 85772Speter return; 86772Speter } 87772Speter putprintf( " .stabs \"" , 1 ); 88*18354Smckusick putprintf( NAMEFORMAT , 1 , name ); 892164Speter putprintf( "\",0x%x,0,0x%x,0" , 0 , N_GSYM , type ); 902164Speter putprintf( " .stabs \"" , 1 ); 91*18354Smckusick putprintf( NAMEFORMAT , 1 , name ); 922164Speter putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length ); 932164Speter } 942164Speter 952164Speter /* 962164Speter * local variables 972164Speter */ 98*18354Smckusick oldstablvar( name , type , level , offset , length ) 992164Speter char *name; 1002164Speter int type; 1012164Speter int level; 1022164Speter int offset; 1032164Speter int length; 1042164Speter { 1052164Speter 1062164Speter if ( ! opt('g') ) { 1072164Speter return; 108772Speter } 109772Speter putprintf( " .stabs \"" , 1 ); 110*18354Smckusick putprintf( NAMEFORMAT , 1 , name ); 1112164Speter putprintf( "\",0x%x,0,0x%x,0x%x" , 0 , N_LSYM , type , -offset ); 1122164Speter putprintf( " .stabs \"" , 1 ); 113*18354Smckusick putprintf( NAMEFORMAT , 1 , name ); 114826Speter putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length ); 115772Speter } 116772Speter 117772Speter 118*18354Smckusick stabparam (p, offset, length) 119*18354Smckusick struct nl *p; 120*18354Smckusick int offset, length; 121*18354Smckusick { 122*18354Smckusick if (oldway != 0) { 123*18354Smckusick oldstabparam(p->symbol, p2type(p->type), offset, length); 124*18354Smckusick } else if (opt('g')) { 125*18354Smckusick putprintf("\t.stabs\t\"%s:", 1, p->symbol); 126*18354Smckusick if (p->class == REF) { 127*18354Smckusick putprintf("v", 1); 128*18354Smckusick } else { 129*18354Smckusick putprintf("p", 1); 130*18354Smckusick } 131*18354Smckusick gentype((p->class == FPROC || p->class ==FFUNC) ? p : p->type); 132*18354Smckusick putprintf("\",0x%x,0,0x%x,0x%x", 0, N_PSYM, length, offset); 133*18354Smckusick } 134*18354Smckusick } 135*18354Smckusick 136772Speter /* 137772Speter * parameters 138772Speter */ 139*18354Smckusick oldstabparam( name , type , offset , length ) 140772Speter char *name; 141772Speter int type; 142772Speter int offset; 143772Speter int length; 144772Speter { 145772Speter 146772Speter if ( ! opt('g') ) { 147772Speter return; 148772Speter } 149772Speter putprintf( " .stabs \"" , 1 ); 150*18354Smckusick putprintf( NAMEFORMAT , 1 , name ); 151826Speter putprintf( "\",0x%x,0,0x%x,0x%x" , 0 , N_PSYM , type , offset ); 152772Speter putprintf( " .stabs \"" , 1 ); 153*18354Smckusick putprintf( NAMEFORMAT , 1 , name ); 154826Speter putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length ); 155772Speter } 156772Speter 157772Speter /* 158772Speter * fields 159772Speter */ 160*18354Smckusick stabfield( name , type , offset , length ) 161*18354Smckusick char *name; 162*18354Smckusick int type; 163*18354Smckusick int offset; 164*18354Smckusick int length; 165*18354Smckusick { 166*18354Smckusick 167*18354Smckusick if ( ! opt('g') ) { 168*18354Smckusick return; 169*18354Smckusick } 170*18354Smckusick putprintf( " .stabs \"" , 1 ); 171*18354Smckusick putprintf( NAMEFORMAT , 1 , name ); 172*18354Smckusick putprintf( "\",0x%x,0,0x%x,0x%x" , 0 , N_SSYM , type , offset ); 173*18354Smckusick putprintf( " .stabs \"" , 1 ); 174*18354Smckusick putprintf( NAMEFORMAT , 1 , name ); 175*18354Smckusick putprintf( "\",0x%x,0,0,0x%x" , 0 , N_LENG , length ); 176*18354Smckusick } 177772Speter 178772Speter /* 179772Speter * left brackets 180*18354Smckusick * (dbx handles module-2 without these, so we won't use them either) 181772Speter */ 182772Speter stablbrac( level ) 183772Speter int level; 184772Speter { 185772Speter 186*18354Smckusick if ( ! opt('g') || oldway == 0 ) { 187772Speter return; 188772Speter } 189826Speter putprintf( " .stabd 0x%x,0,0x%x" , 0 , N_LBRAC , level ); 190772Speter } 191772Speter 192772Speter /* 193772Speter * right brackets 194772Speter */ 195772Speter stabrbrac( level ) 196772Speter int level; 197772Speter { 198772Speter 199*18354Smckusick if ( ! opt('g') || oldway == 0 ) { 200772Speter return; 201772Speter } 202826Speter putprintf( " .stabd 0x%x,0,0x%x" , 0 , N_RBRAC , level ); 203772Speter } 204772Speter 205*18354Smckusick stabfunc (p, name, line, level) 206*18354Smckusick struct nl *p; 207*18354Smckusick char *name; 208*18354Smckusick int line, level; 209*18354Smckusick { 210*18354Smckusick char extname[BUFSIZ],nestspec[BUFSIZ]; 211*18354Smckusick 212*18354Smckusick if ( level == 1 ) { 213*18354Smckusick if (p->class == FUNC) { 214*18354Smckusick putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x" , 215*18354Smckusick 0 , name , N_PC , N_PGFUNC , ABS( line ) 216*18354Smckusick ); 217*18354Smckusick } else if (p->class == PROC) { 218*18354Smckusick putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x" , 219*18354Smckusick 0 , name , N_PC , N_PGPROC , ABS( line ) 220*18354Smckusick ); 221*18354Smckusick } 222*18354Smckusick } 223*18354Smckusick if (oldway != 0) { 224*18354Smckusick oldstabfunc(name, p->class, line, level); 225*18354Smckusick } else if (opt('g')) { 226*18354Smckusick putprintf("\t.stabs\t\"%s:", 1, name); 227*18354Smckusick if (p->class == FUNC) { 228*18354Smckusick putprintf("F", 1); 229*18354Smckusick gentype(p->type); 230*18354Smckusick putprintf(",", 1); 231*18354Smckusick } else { 232*18354Smckusick putprintf("P,", 1); 233*18354Smckusick } 234*18354Smckusick sextname(extname, name, level); /* set extname to entry label */ 235*18354Smckusick putprintf("%s,", 1, &(extname[1])); /* remove initial underbar */ 236*18354Smckusick snestspec(nestspec, level); 237*18354Smckusick putprintf("%s\",0x%x,0,0,%s", 0, nestspec, N_FUN, extname); 238*18354Smckusick } 239*18354Smckusick } 240*18354Smckusick 241772Speter /* 242*18354Smckusick * construct the colon-separated static nesting string into a 243*18354Smckusick * caller-supplied buffer 244*18354Smckusick */ 245*18354Smckusick private snestspec(buffer, level) 246*18354Smckusick char buffer[]; 247*18354Smckusick int level; 248*18354Smckusick { 249*18354Smckusick char *starthere; 250*18354Smckusick int i; 251*18354Smckusick 252*18354Smckusick if (level <= 1) { 253*18354Smckusick buffer[0] = '\0'; 254*18354Smckusick } else { 255*18354Smckusick starthere = &buffer[0]; 256*18354Smckusick for ( i = 1 ; i < level ; i++ ) { 257*18354Smckusick sprintf(starthere, "%s:", enclosing[i]); 258*18354Smckusick starthere += strlen(enclosing[i]) + 1; 259*18354Smckusick } 260*18354Smckusick *starthere-- = '\0'; /* remove last colon */ 261*18354Smckusick if (starthere >= &buffer[BUFSIZ-1]) { 262*18354Smckusick panic("snestspec"); 263*18354Smckusick } 264*18354Smckusick } 265*18354Smckusick } 266*18354Smckusick 267*18354Smckusick /* 268772Speter * functions 269772Speter */ 270*18354Smckusick oldstabfunc( name , typeclass , line , level ) 271772Speter char *name; 2727925Smckusick int typeclass; 273772Speter int line; 274772Speter long level; 275772Speter { 276*18354Smckusick int type; 277*18354Smckusick long i; 2783365Speter char extname[ BUFSIZ ]; 279772Speter 280826Speter /* 281826Speter * for sdb 282826Speter */ 283772Speter if ( ! opt('g') ) { 284772Speter return; 285772Speter } 286772Speter putprintf( " .stabs \"" , 1 ); 287*18354Smckusick putprintf( NAMEFORMAT , 1 , name ); 288*18354Smckusick sextname( extname , name , level ); 289*18354Smckusick putprintf( "\",0x%x,0,0x%x,%s" , 0 , N_FUN , line , extname ); 290772Speter } 291772Speter 292772Speter /* 293772Speter * source line numbers 294772Speter */ 295772Speter stabline( line ) 296772Speter int line; 297772Speter { 298772Speter if ( ! opt('g') ) { 299772Speter return; 300772Speter } 301826Speter putprintf( " .stabd 0x%x,0,0x%x" , 0 , N_SLINE , ABS( line ) ); 302772Speter } 303772Speter 304772Speter /* 305*18354Smckusick * source files get none or more of these: 306*18354Smckusick * one as they are entered, 307*18354Smckusick * and one every time they are returned to from nested #includes 308772Speter */ 309*18354Smckusick stabsource(filename, firsttime) 310772Speter char *filename; 311*18354Smckusick bool firsttime; 31215952Smckusick { 31315952Smckusick int label; 31415952Smckusick 31515952Smckusick /* 31615952Smckusick * for separate compilation 31715952Smckusick */ 31815952Smckusick putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x", 0, 319*18354Smckusick filename, N_PC, N_PSO, N_FLAGCHECKSUM); 32015952Smckusick /* 321*18354Smckusick * for debugger 32215952Smckusick */ 32315952Smckusick if ( ! opt('g') ) { 32415952Smckusick return; 325772Speter } 326*18354Smckusick if (oldway != 0) { 327*18354Smckusick label = getlab(); 328*18354Smckusick putprintf( " .stabs \"" , 1 ); 329*18354Smckusick putprintf( NAMEFORMAT , 1 , filename ); 330*18354Smckusick putprintf( "\",0x%x,0,0," , 1 , N_SO ); 331*18354Smckusick putprintf( PREFIXFORMAT , 0 , LLABELPREFIX , label ); 332*18354Smckusick putprintf( PREFIXFORMAT , 1 , LLABELPREFIX , label ); 333*18354Smckusick putprintf( ":" , 0 ); 334*18354Smckusick } else { 335*18354Smckusick if (firsttime) { 336*18354Smckusick putprintf( " .stabs \"" , 1 ); 337*18354Smckusick putprintf( NAMEFORMAT , 1 , filename ); 338*18354Smckusick putprintf( "\",0x%x,0,0,0" , 0 , N_SO ); 339*18354Smckusick } 340*18354Smckusick } 34115952Smckusick } 342772Speter 343772Speter /* 344772Speter * included files get one or more of these: 345772Speter * one as they are entered by a #include, 34615952Smckusick * and one every time they are returned to from nested #includes. 347772Speter */ 34815952Smckusick stabinclude(filename, firsttime) 349772Speter char *filename; 35015952Smckusick bool firsttime; 35115952Smckusick { 352*18354Smckusick int label; 35315952Smckusick long check; 35415952Smckusick 35515952Smckusick /* 35615952Smckusick * for separate compilation 35715952Smckusick */ 35815952Smckusick if (firsttime) { 35915952Smckusick check = checksum(filename); 36015952Smckusick } else { 36115952Smckusick check = N_FLAGCHECKSUM; 36215952Smckusick } 36315952Smckusick putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x", 0, 364*18354Smckusick filename, N_PC, N_PSOL, check); 36515952Smckusick /* 36615952Smckusick * for sdb 36715952Smckusick */ 36815952Smckusick if ( ! opt('g') ) { 36915952Smckusick return; 37015952Smckusick } 371*18354Smckusick if (oldway != 0) { 372*18354Smckusick label = getlab(); 373*18354Smckusick putprintf( " .stabs \"" , 1 ); 374*18354Smckusick putprintf( NAMEFORMAT , 1 , filename ); 375*18354Smckusick putprintf( "\",0x%x,0,0," , 1 , N_SOL ); 376*18354Smckusick putprintf( PREFIXFORMAT , 0 , LLABELPREFIX , label ); 377*18354Smckusick putprintf( PREFIXFORMAT , 1 , LLABELPREFIX , label ); 378*18354Smckusick putprintf( ":" , 0 ); 379*18354Smckusick } 38015952Smckusick } 38115952Smckusick 38215952Smckusick /* 38315952Smckusick * anyone know a good checksum for ascii files? 38415952Smckusick * this does a rotate-left and then exclusive-or's in the character. 38515952Smckusick * also, it avoids returning checksums of 0. 38615952Smckusick * The rotate is implemented by shifting and adding back the 38715952Smckusick * sign bit when negative. 38815952Smckusick */ 38915952Smckusick long 39015952Smckusick checksum(filename) 39115952Smckusick char *filename; 39215952Smckusick { 39315952Smckusick FILE *filep; 39415952Smckusick register int input; 39515952Smckusick register long check; 39615952Smckusick 39715952Smckusick filep = fopen(filename, "r"); 39815952Smckusick if (filep == NULL) { 39915952Smckusick perror(filename); 40015952Smckusick pexit(DIED); 40115952Smckusick } 40215952Smckusick check = 0; 40315952Smckusick while ((input = getc(filep)) != EOF) { 40415952Smckusick if (check < 0) { 40515952Smckusick check <<= 1; 40615952Smckusick check += 1; 40715952Smckusick } else { 40815952Smckusick check <<= 1; 40915942Smckusick } 41015952Smckusick check ^= input; 41114128Speter } 412*18354Smckusick fclose(filep); 41315952Smckusick if ((unsigned) check <= N_FLAGCHECKSUM) { 41415952Smckusick return N_FLAGCHECKSUM + 1; 41515952Smckusick } else { 41615952Smckusick return check; 41715952Smckusick } 41815952Smckusick } 41914128Speter 420772Speter /* 421772Speter * global Pascal symbols : 422772Speter * labels, types, constants, and external procedure and function names: 423772Speter * These are used by the separate compilation facility 424772Speter * to be able to check for disjoint header files. 425772Speter */ 426772Speter 427826Speter /* 428826Speter * global labels 429826Speter */ 430842Speter stabglabel( label , line ) 431826Speter char *label; 432826Speter int line; 433772Speter { 434772Speter 435842Speter putprintf( " .stabs \"%s\",0x%x,0,0x%x,0x%x" , 0 436*18354Smckusick , label , N_PC , N_PGLABEL , ABS( line ) ); 437772Speter } 438772Speter 439826Speter /* 440826Speter * global constants 441826Speter */ 442842Speter stabgconst( const , line ) 443842Speter char *const; 444826Speter int line; 445772Speter { 446772Speter 447842Speter putprintf( " .stabs \"%s\",0x%x,0,0x%x,0x%x" , 0 448*18354Smckusick , const , N_PC , N_PGCONST , ABS( line ) ); 449772Speter } 450772Speter 451*18354Smckusick /* 452*18354Smckusick * Generate symbolic information about a constant. 453*18354Smckusick */ 454772Speter 455*18354Smckusick stabconst (c) 456*18354Smckusick struct nl *c; 457*18354Smckusick { 458*18354Smckusick if (opt('g') && oldway == 0) { 459*18354Smckusick putprintf("\t.stabs\t\"%s:c=", 1, c->symbol); 460*18354Smckusick if (c->type == nl + TSTR) { 461*18354Smckusick putprintf("s'%s'", 1, c->ptr[0]); 462*18354Smckusick } else if (c->type == nl + T1CHAR) { 463*18354Smckusick putprintf("c%d", 1, c->range[0]); 464*18354Smckusick } else if (isa(c->type, "i")) { 465*18354Smckusick putprintf("i%d", 1, c->range[0]); 466*18354Smckusick } else if (isa(c->type, "d")) { 467*18354Smckusick putprintf("r%g", 1, c->real); 468*18354Smckusick } else { 469*18354Smckusick putprintf("e", 1); 470*18354Smckusick gentype(c->type); 471*18354Smckusick putprintf(",%d", 1, c->range[0]); 472*18354Smckusick } 473*18354Smckusick putprintf("\",0x%x,0,0x%x,0x%x", 0, N_LSYM, 0, 0); 474772Speter } 475*18354Smckusick } 476772Speter 477*18354Smckusick stabgtype (name, type, line) 478*18354Smckusick char *name; 479*18354Smckusick struct nl *type; 480*18354Smckusick int line; 481*18354Smckusick { 482*18354Smckusick putprintf(" .stabs \"%s\",0x%x,0,0x%x,0x%x" , 483*18354Smckusick 0, name, N_PC , N_PGTYPE, ABS(line) 484*18354Smckusick ); 485*18354Smckusick if (oldway == 0) { 486*18354Smckusick stabltype(name, type); 487*18354Smckusick } 488*18354Smckusick } 489772Speter 490*18354Smckusick stabltype (name, type) 491*18354Smckusick char *name; 492*18354Smckusick struct nl *type; 493*18354Smckusick { 494*18354Smckusick if (opt('g')) { 495*18354Smckusick putprintf("\t.stabs\t\"%s:t", 1, name); 496*18354Smckusick gentype(type); 497*18354Smckusick putprintf("\",0x%x,0,0,0", 0, N_LSYM); 498*18354Smckusick } 499*18354Smckusick } 500*18354Smckusick 501826Speter /* 502826Speter * external functions and procedures 503826Speter */ 5047925Smckusick stabefunc( name , typeclass , line ) 505826Speter char *name; 5067925Smckusick int typeclass; 507826Speter int line; 508772Speter { 509826Speter int type; 510772Speter 5117925Smckusick if ( typeclass == FUNC ) { 512842Speter type = N_PEFUNC; 5137925Smckusick } else if ( typeclass == PROC ) { 514842Speter type = N_PEPROC; 515826Speter } else { 516826Speter return; 517772Speter } 518842Speter putprintf( " .stabs \"%s\",0x%x,0,0x%x,0x%x" , 0 519*18354Smckusick , name , N_PC , type , ABS( line ) ); 520772Speter } 521772Speter 522*18354Smckusick /* 523*18354Smckusick * Generate type information encoded as a string for dbx. 524*18354Smckusick * The fwdptrnum field is used only when the type is a pointer 525*18354Smckusick * to a type that isn't known when it was entered. When the 526*18354Smckusick * type field is filled for some such tptr, fixfwdtype should 527*18354Smckusick * be called to output an equivalencing type definition. 528*18354Smckusick */ 529*18354Smckusick 530*18354Smckusick typedef struct TypeDesc *TypeDesc; 531*18354Smckusick 532*18354Smckusick struct TypeDesc { 533*18354Smckusick struct nl *tptr; 534*18354Smckusick int tnum; 535*18354Smckusick int fwdptrnum; 536*18354Smckusick TypeDesc chain; 537*18354Smckusick }; 538*18354Smckusick 539*18354Smckusick #define TABLESIZE 2003 540*18354Smckusick 541*18354Smckusick #define typehash(t) ( ( ((int) t) >> 2 ) % TABLESIZE ) 542*18354Smckusick 543*18354Smckusick private int tcount = 1; 544*18354Smckusick private TypeDesc typetable[TABLESIZE]; 545*18354Smckusick 546*18354Smckusick private TypeDesc tdlookup (t) 547*18354Smckusick struct nl *t; 548*18354Smckusick { 549*18354Smckusick register TypeDesc td; 550*18354Smckusick 551*18354Smckusick td = typetable[typehash(t)]; 552*18354Smckusick while (td != NIL && td->tptr != t) { 553*18354Smckusick td = td->chain; 554*18354Smckusick } 555*18354Smckusick return td; 556*18354Smckusick } 557*18354Smckusick 558*18354Smckusick private int typelookup (t) 559*18354Smckusick struct nl *t; 560*18354Smckusick { 561*18354Smckusick register TypeDesc td; 562*18354Smckusick int r; 563*18354Smckusick 564*18354Smckusick td = tdlookup(t); 565*18354Smckusick if (td == NIL) { 566*18354Smckusick r = 0; 567*18354Smckusick } else { 568*18354Smckusick r = td->tnum; 569*18354Smckusick } 570*18354Smckusick return r; 571*18354Smckusick } 572*18354Smckusick 573*18354Smckusick private int entertype (type) 574*18354Smckusick struct nl *type; 575*18354Smckusick { 576*18354Smckusick register TypeDesc td; 577*18354Smckusick register int i; 578*18354Smckusick 579*18354Smckusick td = (TypeDesc) malloc(sizeof(struct TypeDesc)); 580*18354Smckusick td->tptr = type; 581*18354Smckusick td->tnum = tcount; 582*18354Smckusick td->fwdptrnum = 0; 583*18354Smckusick ++tcount; 584*18354Smckusick i = typehash(type); 585*18354Smckusick td->chain = typetable[i]; 586*18354Smckusick typetable[i] = td; 587*18354Smckusick return td->tnum; 588*18354Smckusick } 589*18354Smckusick 590*18354Smckusick /* 591*18354Smckusick * The in_types table currently contains "boolean", "char", "integer", 592*18354Smckusick * "real" and "_nil". (See nl.c for definition.) 593*18354Smckusick * The lookup call below will give the TYPE class nl entry for these 594*18354Smckusick * types. In each case except _nil, the type field of that entry is a RANGE 595*18354Smckusick * class nl entry for the type. Sometimes other symbol table entries 596*18354Smckusick * point to the TYPE entry (e.g., when there is a range over the base type), 597*18354Smckusick * and other entries point to the RANGE entry (e.g., for a variable of the 598*18354Smckusick * given type). We don't really want to distinguish between these uses 599*18354Smckusick * in dbx, and since it appears that the RANGE entries are not reused if 600*18354Smckusick * a range happens to coincide, we will give the two the same identifying 601*18354Smckusick * dbx type number. 602*18354Smckusick */ 603*18354Smckusick 604*18354Smckusick private inittypes() 605*18354Smckusick { 606*18354Smckusick int i; 607*18354Smckusick extern char *in_types[]; 608*18354Smckusick struct nl *p; 609*18354Smckusick 610*18354Smckusick for (i = 0; in_types[i] != NIL; i++) { 611*18354Smckusick p = lookup(in_types[i]); 612*18354Smckusick if (p != NIL) { 613*18354Smckusick entertype(p); 614*18354Smckusick if (p->type != NIL) { 615*18354Smckusick --tcount; /* see comment above */ 616*18354Smckusick entertype(p->type); 617*18354Smckusick } 618*18354Smckusick } 619*18354Smckusick } 620*18354Smckusick } 621*18354Smckusick 622*18354Smckusick static genarray (t) 623*18354Smckusick struct nl *t; 624*18354Smckusick { 625*18354Smckusick register struct nl *p; 626*18354Smckusick 627*18354Smckusick putprintf("a", 1); 628*18354Smckusick for (p = t->chain; p != NIL; p = p->chain) { 629*18354Smckusick gentype(p); 630*18354Smckusick putprintf(";", 1); 631*18354Smckusick } 632*18354Smckusick gentype(t->type); 633*18354Smckusick } 634*18354Smckusick 635*18354Smckusick /* 636*18354Smckusick * Really we should walk through ptr[NL_FIELDLIST] for the fields, 637*18354Smckusick * and then do the variant tag and fields separately, but dbx 638*18354Smckusick * doesn't support this yet. 639*18354Smckusick * So, since all the fields of all the variants are on the chain, 640*18354Smckusick * we walk through that. Except that this gives the fields in the 641*18354Smckusick * reverse order, so we want to print in reverse order. 642*18354Smckusick */ 643*18354Smckusick 644*18354Smckusick static genrecord (t) 645*18354Smckusick struct nl *t; 646*18354Smckusick { 647*18354Smckusick putprintf("s%d", 1, t->value[NL_OFFS]); 648*18354Smckusick if (t->chain != NIL) { 649*18354Smckusick genrecfield(t->chain, 1); 650*18354Smckusick } 651*18354Smckusick putprintf(";", 1); 652*18354Smckusick } 653*18354Smckusick 654*18354Smckusick static genrecfield (t, n) 655*18354Smckusick struct nl *t; 656*18354Smckusick int n; 657*18354Smckusick { 658*18354Smckusick if (t->chain != NULL) { 659*18354Smckusick genrecfield(t->chain, n + 1); 660*18354Smckusick if (n % 2 == 0) { 661*18354Smckusick gencontinue(); 662*18354Smckusick } 663*18354Smckusick } 664*18354Smckusick putprintf("%s:", 1, t->symbol); 665*18354Smckusick gentype(t->type); 666*18354Smckusick putprintf(",%d,%d;", 1, 8*t->value[NL_OFFS], 8*lwidth(t->type)); 667*18354Smckusick } 668*18354Smckusick 669*18354Smckusick static genvarnt (t) 670*18354Smckusick struct nl *t; 671*18354Smckusick { 672*18354Smckusick genrecord(t); 673*18354Smckusick } 674*18354Smckusick 675*18354Smckusick static genptr (t) 676*18354Smckusick struct nl *t; 677*18354Smckusick { 678*18354Smckusick register TypeDesc td; 679*18354Smckusick 680*18354Smckusick putprintf("*", 1); 681*18354Smckusick if (t->type != NIL) { 682*18354Smckusick gentype(t->type); 683*18354Smckusick } else { 684*18354Smckusick /* 685*18354Smckusick * unresolved forward pointer: use tcount to represent what is 686*18354Smckusick * begin pointed to, to be defined later 687*18354Smckusick */ 688*18354Smckusick td = tdlookup(t); 689*18354Smckusick if (td == NIL) { 690*18354Smckusick panic("nil ptr in stab.genptr"); 691*18354Smckusick } 692*18354Smckusick td->fwdptrnum = tcount; 693*18354Smckusick putprintf("%d", 1, tcount); 694*18354Smckusick ++tcount; 695*18354Smckusick } 696*18354Smckusick } 697*18354Smckusick 698*18354Smckusick /* 699*18354Smckusick * The type t is a pointer which has just had its type field filled. 700*18354Smckusick * We need to generate a type stab saying that the number saved 701*18354Smckusick * in t's fwdptrnum is the same as the t->type's number 702*18354Smckusick */ 703*18354Smckusick 704*18354Smckusick fixfwdtype (t) 705*18354Smckusick struct nl *t; 706*18354Smckusick { 707*18354Smckusick register TypeDesc td; 708*18354Smckusick 709*18354Smckusick if (opt('g') && oldway == 0) { 710*18354Smckusick td = tdlookup(t); 711*18354Smckusick if (td != NIL) { 712*18354Smckusick putprintf("\t.stabs\t\":t%d=", 1, td->fwdptrnum); 713*18354Smckusick gentype(t->type); 714*18354Smckusick putprintf("\",0x%x,0,0,0", 0, N_LSYM); 715*18354Smckusick } 716*18354Smckusick } 717*18354Smckusick } 718*18354Smckusick 719*18354Smckusick static genenum (t) 720*18354Smckusick struct nl *t; 721*18354Smckusick { 722*18354Smckusick register struct nl *e; 723*18354Smckusick register int i; 724*18354Smckusick 725*18354Smckusick putprintf("e", 1); 726*18354Smckusick i = 1; 727*18354Smckusick e = t->chain; 728*18354Smckusick while (e != NULL) { 729*18354Smckusick if (i > 2) { 730*18354Smckusick gencontinue(); 731*18354Smckusick i = 0; 732*18354Smckusick } 733*18354Smckusick putprintf("%s:%d,", 1, e->symbol, e->range[0]); 734*18354Smckusick e = e->chain; 735*18354Smckusick ++i; 736*18354Smckusick } 737*18354Smckusick putprintf(";", 1); 738*18354Smckusick } 739*18354Smckusick 740*18354Smckusick static genset (t) 741*18354Smckusick struct nl *t; 742*18354Smckusick { 743*18354Smckusick putprintf("S", 1); 744*18354Smckusick gentype(t->type); 745*18354Smckusick } 746*18354Smckusick 747*18354Smckusick static genrange (t) 748*18354Smckusick struct nl *t; 749*18354Smckusick { 750*18354Smckusick putprintf("r", 1); 751*18354Smckusick gentype(t->type); 752*18354Smckusick putprintf(";%d;%d", 1, t->range[0], t->range[1]); 753*18354Smckusick } 754*18354Smckusick 755*18354Smckusick static genfparam (t) 756*18354Smckusick struct nl *t; 757*18354Smckusick { 758*18354Smckusick struct nl *p; 759*18354Smckusick int count; 760*18354Smckusick 761*18354Smckusick if (t->type != NULL) { 762*18354Smckusick putprintf("f", 1); 763*18354Smckusick gentype(t->type); 764*18354Smckusick putprintf(",", 1); 765*18354Smckusick } else { 766*18354Smckusick putprintf("p", 1); 767*18354Smckusick } 768*18354Smckusick count = 0; 769*18354Smckusick for (p = t->ptr[NL_FCHAIN]; p != NULL; p = p->chain) { 770*18354Smckusick ++count; 771*18354Smckusick } 772*18354Smckusick putprintf("%d;", 1, count); 773*18354Smckusick for (p = t->ptr[NL_FCHAIN]; p != NULL; p = p->chain) { 774*18354Smckusick gentype(p->type); 775*18354Smckusick putprintf(",%d;", 1, p->class); 776*18354Smckusick } 777*18354Smckusick } 778*18354Smckusick 779*18354Smckusick static genfile (t) 780*18354Smckusick struct nl *t; 781*18354Smckusick { 782*18354Smckusick putprintf("d", 1); 783*18354Smckusick gentype(t->type); 784*18354Smckusick } 785*18354Smckusick 786*18354Smckusick static gentype (t) 787*18354Smckusick struct nl *t; 788*18354Smckusick { 789*18354Smckusick int id; 790*18354Smckusick 791*18354Smckusick if (tcount == 1) { 792*18354Smckusick inittypes(); 793*18354Smckusick } 794*18354Smckusick id = typelookup(t); 795*18354Smckusick if (id != 0) { 796*18354Smckusick putprintf("%d", 1, id); 797*18354Smckusick } else if (t->class == SCAL && t->chain == NULL) { 798*18354Smckusick id = typelookup(t->type); 799*18354Smckusick if (id != 0) { 800*18354Smckusick putprintf("%d", 1, id); 801*18354Smckusick } else { 802*18354Smckusick genenum(t->type); 803*18354Smckusick } 804*18354Smckusick } else { 805*18354Smckusick id = entertype(t); 806*18354Smckusick putprintf("%d=", 1, id); 807*18354Smckusick switch (t->class) { 808*18354Smckusick case TYPE: 809*18354Smckusick gentype(t->type); 810*18354Smckusick break; 811*18354Smckusick 812*18354Smckusick case ARRAY: 813*18354Smckusick genarray(t); 814*18354Smckusick break; 815*18354Smckusick 816*18354Smckusick case RECORD: 817*18354Smckusick genrecord(t); 818*18354Smckusick break; 819*18354Smckusick 820*18354Smckusick case VARNT: 821*18354Smckusick genvarnt(t); 822*18354Smckusick break; 823*18354Smckusick 824*18354Smckusick case REF: 825*18354Smckusick gentype(t->type); 826*18354Smckusick break; 827*18354Smckusick 828*18354Smckusick case PTR: 829*18354Smckusick genptr(t); 830*18354Smckusick break; 831*18354Smckusick 832*18354Smckusick case SET: 833*18354Smckusick genset(t); 834*18354Smckusick break; 835*18354Smckusick 836*18354Smckusick case RANGE: 837*18354Smckusick genrange(t); 838*18354Smckusick break; 839*18354Smckusick 840*18354Smckusick case SCAL: 841*18354Smckusick genenum(t); 842*18354Smckusick break; 843*18354Smckusick 844*18354Smckusick case FPROC: 845*18354Smckusick case FFUNC: 846*18354Smckusick genfparam(t); 847*18354Smckusick break; 848*18354Smckusick 849*18354Smckusick case FILET: 850*18354Smckusick case PTRFILE: 851*18354Smckusick genfile(t); 852*18354Smckusick break; 853*18354Smckusick 854*18354Smckusick default: 855*18354Smckusick /* This shouldn't happen */ 856*18354Smckusick /* Rather than bomb outright, let debugging go on */ 857*18354Smckusick warning(); 858*18354Smckusick error("Bad type class found in stab"); 859*18354Smckusick putprintf("1", 1, t->class); 860*18354Smckusick break; 861*18354Smckusick } 862*18354Smckusick } 863*18354Smckusick } 864*18354Smckusick 865*18354Smckusick /* 866*18354Smckusick * Continue stab information in a namelist new entry. This is necessary 867*18354Smckusick * to avoid overflowing putprintf's buffer. 868*18354Smckusick */ 869*18354Smckusick 870*18354Smckusick static gencontinue () 871*18354Smckusick { 872*18354Smckusick putprintf("?\",0x%x,0,0,0", 0, N_LSYM); 873*18354Smckusick putprintf("\t.stabs\t\"", 1); 874*18354Smckusick } 875*18354Smckusick 876772Speter #endif PC 877