home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / pascal / src / stab.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-16  |  18.9 KB  |  894 lines

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