[comp.sys.apollo] Version 0.6 of gnu2coff converter; part 3 of 4

dclemans@mentor.com (Dave Clemans @ APD x1292) (06/15/89)

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 3 (of 4)."
# Contents:  symbolic.c
# Wrapped by dclemans@dclemans on Wed Jun 14 14:59:43 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'symbolic.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'symbolic.c'\"
else
echo shar: Extracting \"'symbolic.c'\" \(22081 characters\)
sed "s/^X//" >'symbolic.c' <<'END_OF_FILE'
X/*
X * Symbolic debug symbol converter for the
X * GNU->COFF object file format conversion tool.
X */
X#include <stdio.h>
X#include <ctype.h>
X#include <string.h>
X#include <memory.h>
Xextern char *malloc();
Xextern long atol();
X
X#include "gnu2coff.h"
Xextern struct syment *coff_symbol_addr();
Xextern struct syment *coff_symbol_space();
Xextern long coff_text_line();
X
X#include <syms.h>
X#undef  n_name
X#undef  n_nptr
X#undef  n_zeroes
X#undef  n_offset
X#undef  N_ABS
X#include <linenum.h>
X
X#include "/gnu/src/gdb/a.out.gnu.h"
X#include "/gnu/src/gdb/stab.gnu.h"
X
Xstruct  type_def
X{
X    char                *name;
X    long                size;
X    long                low;
X    long                high;
X    long                typenum;
X    long                typeof;
X    long                flags;
X#define IS_FUNC         0x0001
X#define IS_POINTER      0x0002
X#define IS_ARRAY        0x0004
X#define IS_STRUCT       0x0008
X#define IS_ENUM         0x0010
X    struct type_def     *members;
X    struct type_def     *memend;
X    struct type_def     *next;
X};
X
Xstruct  sym_lvar
X{
X    char                *name;
X    long                value;
X    int                 is_register;
X    long                typenum;
X    struct sym_lvar     *next;
X};
X
Xstruct  sym_line
X{
X    long                number;
X    long                address;
X    struct sym_line     *next;
X};
X
Xstruct  sym_func
X{
X    char                *name;
X    long                value;
X    long                symbol;
X    long                typenum;
X    long                bstart,bline;
X    long                estart,eline;
X    struct sym_line     *lines;
X    struct sym_line     *lines_bottom;
X    struct sym_lvar     *parms;
X    struct sym_lvar     *parms_bottom;
X    struct sym_lvar     *lvars;
X    struct sym_lvar     *lvars_bottom;
X};
X
Xstatic struct sym_func current;
Xstatic struct type_def *types;
Xstatic struct type_def *types_bottom;
Xstatic struct type_def *globals;
Xstatic struct type_def *globals_bottom;
X
Xstatic long get_typenum(p)
Xchar *p;
X{
X    if (isdigit(*p))
X        return atol(p);
X    else return atol(p+1);
X}   /* end of get_typenum */
X
Xvoid get_name(td,f,l)
Xstruct type_def *td;
Xchar *f;
Xchar *l;
X{
X    td->name = (char *)malloc((int)(l - f) + 1);
X    if (td->name == (char *)NULL)
X    {   /* if no memory */
X        fprintf(stderr,"gnu2coff: no memory for names\n");
X        exit(1);
X    }
X    strncpy(td->name,f,(int)(l - f));
X    td->name[(int)(l - f)] = '\0';
X}   /* end of get_name */
X
Xstatic struct type_def *want_continuation;
X
Xstatic char *get_enum(t,td)
Xchar *t;
Xstruct type_def *td;
X{
X    register char *l;
X    struct type_def *newtd;
X
X    newtd = (struct type_def *)malloc(sizeof(struct type_def));
X    if (newtd == (struct type_def *)NULL)
X    {   /* if no memory */
X        fprintf(stderr,"gnu2coff: no memory for types\n");
X        exit(1);
X    }
X    newtd->low = newtd->high = newtd->flags = newtd->typenum = newtd->size = newtd->typeof = 0;
X    newtd->members = newtd->memend = newtd->next = (struct type_def *)NULL;
X
X    l = strchr(t,':');
X    if (l == (char *)NULL)
X    {   /* if error */
X        for (l = t; *l && *l != ','; l++)
X            /* do nothing */;
X        return l;
X    }
X    get_name(newtd,t,l);
X    newtd->size = atol(l+1);
X    if (td->members == (struct type_def *)NULL)
X        td->members = td->memend = newtd;
X    else
X    {   /* tack onto end */
X        td->memend->next = newtd;
X        td->memend = newtd;
X    }
X
X    while (*l && *l != ',')
X        l++;
X    if (*l == ',')
X        l++;
X    return l;
X}   /* end of get_enum */
X
Xstatic char *get_type(t,td)
Xchar *t;
Xstruct type_def **td;
X{
X    register char *l;
X    struct type_def *newtd;
X    char type;
X
X    want_continuation = (struct type_def *)NULL;
X
X    if (!isdigit(*t))
X    {   /* if a name present */
X        l = strchr(t,':');
X        if (l == (char *)NULL)
X        {   /* if doesn't look good */
X            fprintf(stderr,"gnu2coff: apparent bad type line(1): %s\n",t);
X            for (l = t; *l; l++)
X                /* do nothing */;
X            return l;
X        }
X    }
X    else l = t;
X    *td = (struct type_def *)malloc(sizeof(struct type_def));
X    if (*td == (struct type_def *)NULL)
X    {   /* if no memory */
X        fprintf(stderr,"gnu2coff: no memory for types\n");
X        exit(1);
X    }
X    (*td)->low = (*td)->high = (*td)->flags = (*td)->typenum = (*td)->size = (*td)->typeof = 0;
X    (*td)->members = (*td)->memend = (*td)->next = (struct type_def *)NULL;
X    if (l != t)
X    {   /* if a name present */
X        get_name(*td,t,l);
X    }
X    else (*td)->name = (char *)NULL;
X    type = *++l;
X    if (isdigit(type))
X        (*td)->typenum = atol(--l);
X    else if (isdigit(*++l))
X        (*td)->typenum = atol(l);
X    else
X    {   /* bad type number */
X        if (*l == '\\')
X        {   /* really just a continuation */
X            want_continuation = *td;
X            return l+1;
X        }
X        fprintf(stderr,"gnu2coff: apparent bad type line(2): %s\n",t);
X        for (l = t; *l; l++)
X            /* do nothing */;
X        return l;
X    }
X    while (isdigit(*l))
X        l++;
X    if (*l != '=')
X    {   /* check for use of existing type */
X        (*td)->typeof = (*td)->typenum;
X        (*td)->typenum = 0;
X        while (*l && *l != ';')
X            l++;
X        if (*l == ';')
X            l++;
X        return l;
X    }
X    l++;
X    while (*l && *l != ';' && !isdigit(*l)) switch (*l)
X    {   /* what kind of type */
X        case 'r':
X        case 'R':
X            l++;
X            break;
X        case 's':
X        case 'S':
X            (*td)->flags |= IS_STRUCT;
X            l++;
X            (*td)->size = atol(l);
X            while (*l && isdigit(*l))
X                l++;
X            while (*l && *l != ';' && *l != '\\')
X            {   /* while struct members possible */
X                l = get_type(l,&newtd);
X                if ((*td)->members == (struct type_def *)NULL)
X                    (*td)->members = (*td)->memend = newtd;
X                else
X                {   /* tack onto end */
X                    (*td)->memend->next = newtd;
X                    (*td)->memend = newtd;
X                }
X            }
X            if (*l == '\\')
X                want_continuation = *td;
X            if (*l) l++;
X            break;
X        case 'e':
X        case 'E':
X            (*td)->flags |= IS_ENUM;
X            l++;
X            while (*l && *l != ';' && *l != '\\')
X                l = get_enum(l,*td);
X            if (*l == '\\')
X                want_continuation = *td;
X            if (*l) l++;
X            break;
X        case '*':
X            (*td)->flags |= IS_POINTER;
X            l++;
X            (*td)->typeof = atol(l);
X            while (*l && *l != ';')
X                l++;
X            break;
X        case 'a':
X        case 'A':
X            (*td)->flags |= IS_ARRAY;
X            l++;
X            break;
X        default:
X            fprintf(stderr,"gnu2coff: apparent bad type line(4): %s\n",t);
X            for (l = t; *l; l++)
X                /* do nothing */;
X            return l;
X    }
X    (*td)->size = atol(l);
X    while (*l && isdigit(*l))
X        l++;
X    if ((*td)->flags & IS_ARRAY)
X    {   /* get sizes */
X        l++;
X        (*td)->low = atol(l);
X        while (*l && isdigit(*l))
X            l++;
X        l++;
X        (*td)->high = atol(l);
X        while (*l && isdigit(*l))
X            l++;
X        l++;
X        (*td)->typeof = atol(l);
X        while (*l && isdigit(*l))
X            l++;
X    }
X
X    while (*l && *l != ';')
X        l++;
X    if (*l == ';')
X        l++;
X    return l;
X}   /* end of get_type */
X
Xstatic void decode_type(s)
Xstruct nlist *s;
X{
X    register char *p,*n;
X    char *t;
X    struct type_def *td,*newtd;
X
X    if (want_continuation)
X    {   /* if continuing previous def */
X        td = want_continuation;
X        want_continuation = (struct type_def *)NULL;
X        if (td->flags & IS_ENUM)
X        {   /* fill an enum? */
X            p = s->n_un.n_name;
X            while (*p && *p != ';' && *p != '\\')
X                p = get_enum(p,td);
X            if (*p == '\\')
X                want_continuation = td;
X        }
X        else if (td->flags & IS_STRUCT)
X        {   /* a structure? */
X            p = s->n_un.n_name;
X            while (*p && *p != ';' && *p != '\\')
X            {   /* while members are possible */
X                p = get_type(p,&newtd);
X                if (td->members == (struct type_def *)NULL)
X                    td->members = td->memend = newtd;
X                else
X                {   /* tack onto end */
X                    td->memend->next = newtd;
X                    td->memend = newtd;
X                }
X            }
X            if (*p == '\\')
X                want_continuation = td;
X        }
X        else
X        {   /* unknown */
X            (void)get_type(s->n_un.n_name,&td);
X        }
X        return;
X    }
X
X    (void) get_type(s->n_un.n_name,&td);
X    if (types == (struct type_def *)NULL)
X        types = types_bottom = td;
X    else
X    {   /* tack onto end */
X        types_bottom->next = td;
X        types_bottom = td;
X    }
X}   /* end of decode_type */
X
Xstatic char *lookup_type(number)
Xlong number;
X{
X    register struct type_def *td;
X
X    for (td = types; td != (struct type_def *)NULL; td = td->next)
X    {   /* do we know this type? */
X        if (td->typenum == number)
X            return td->name;
X    }
X    return "unknown";
X}   /* end of lookup_type */
X
Xstatic void dump_current()
X{
X    struct sym_line *sl,*slp;
X    struct sym_lvar *lv,*lvp;
X    long symnum;
X    struct syment *func;
X    union auxent *func_aux;
X    struct syment *s;
X    union auxent *a;
X
X    if (current.name == (char *)NULL || strcmp(current.name,".text") == 0)
X        return;
X
X    if (current.lines != (struct sym_line *)NULL)
X    {   /* if line number info */
X        if (current.bline == 0)
X        {   /* if not set yet */
X            if (current.lines->next != (struct sym_line *)NULL)
X            {   /* get info from guessed at start */
X                current.bline = current.lines->next->number;
X                current.bstart = current.lines->next->address;
X            }
X            else
X            {   /* get only info available */
X                current.bline = current.lines->number;
X                current.bstart = current.lines->address;
X            }
X        }
X        if (current.eline == 0)
X        {   /* if not set yet */
X            for (sl = current.lines; sl != (struct sym_line *)NULL; sl = sl->next)
X            {   /* copy in the info */
X                current.eline = sl->number;
X                current.estart = sl->address;
X            }
X        }
X        s = coff_symbol_space(2L,&symnum);
X        func = coff_symbol_addr(current.symbol);
X        func_aux = (union auxent *)coff_symbol_addr(current.symbol+1);
X        func_aux->x_sym.x_tvndx = func->n_sclass;
X        func->n_sclass = C_FCN;
X        func_aux->x_sym.x_tagndx = symnum;
X        func_aux->x_sym.x_fcnary.x_fcn.x_lnnoptr = coff_text_line(current.symbol,(short)0)+1;
X        strcpy(s->_n._n_name,".bf");
X        s->n_value = current.bstart;
X        s->n_scnum = STEXT;
X        s->n_type = T_NULL;
X        s->n_sclass = C_FCN;
X        s->n_numaux = 1;
X        a = (union auxent *)coff_symbol_addr(symnum+1);
X        a->x_sym.x_misc.x_lnsz.x_lnno = current.bline;
X        if (current.lines != (struct sym_line *)NULL)
X        {   /* if some line numbers to insert */
X            for (sl = current.lines->next; sl != (struct sym_line *)NULL; sl = sl->next)
X            {   /* stick in the source lines */
X                if (sl->number <= current.bline)
X                    continue;
X                (void) coff_text_line(sl->address,(short)sl->number-current.bline);
X            }
X        }
X        s = coff_symbol_space(2L,&symnum);
X        strcpy(s->_n._n_name,".ef");
X        s->n_value = current.estart;
X        s->n_scnum = STEXT;
X        s->n_type = T_NULL;
X        s->n_sclass = C_FCN;
X        s->n_numaux = 1;
X        a = (union auxent *)coff_symbol_addr(symnum+1);
X        a->x_sym.x_misc.x_lnsz.x_lnno = current.eline;
X    }
X
X    if (show_func_structure)
X    {   /* what does this function look like? */
X        if (current.lines != (struct sym_line *)NULL)
X            printf("%d=0x%x:",current.lines->number-1,current.lines->address);
X        printf("%s ",lookup_type(current.typenum));
X        printf("%s(",current.name);
X        for (lv = current.parms; lv != (struct sym_lvar *)NULL; lv = lv->next)
X        {   /* check for parameters */
X            if (lv->is_register)
X                printf("%s %s=r%d",lookup_type(lv->typenum),lv->name,lv->is_register);
X            else printf("%s %s=%d",lookup_type(lv->typenum),lv->name,lv->value);
X            if (lv->next != (struct sym_lvar *)NULL)
X                printf(",");
X        }
X        printf(")\n");
X        printf("%d=%x:{\n",current.bline,current.bstart);
X        for (lv = current.lvars; lv != (struct sym_lvar *)NULL; lv = lv->next)
X        {   /* check for local variables */
X            if (lv->is_register)
X                printf("%s %s=r%d\n",lookup_type(lv->typenum),lv->name,lv->is_register);
X            else printf("%s %s=%d\n",lookup_type(lv->typenum),lv->name,lv->value);
X        }
X        if (current.lines != (struct sym_line *)NULL)
X        {   /* if a line number chain */
X            for (sl = current.lines->next; sl != (struct sym_line *)NULL; sl = sl->next)
X            {   /* and the line number table */
X                printf("\t%5d:0x%x\n",sl->number,sl->address);
X            }
X        }
X        printf("%d=%x:}\n",current.eline,current.estart);
X    }
X
X    for (sl = current.lines; sl != (struct sym_line *)NULL; )
X    {   /* dump the old line chain */
X        slp = sl;
X        sl = sl->next;
X        free(slp);
X    }
X    for (lv = current.parms; lv != (struct sym_lvar *)NULL; )
X    {   /* dump the old parms chain */
X        lvp = lv;
X        lv = lv->next;
X        free(lvp->name);
X        free(lvp);
X    }
X    for (lv = current.lvars; lv != (struct sym_lvar *)NULL; )
X    {   /* dump the old lvars chain */
X        lvp = lv;
X        lv = lv->next;
X        free(lvp->name);
X        free(lvp);
X    }
X    current.name = (char *)NULL;
X    current.value = 0;
X    current.typenum = 0;
X    current.lines = current.lines_bottom = (struct sym_line *)NULL;
X    current.parms = current.parms_bottom = (struct sym_lvar *)NULL;
X    current.lvars = current.lvars_bottom = (struct sym_lvar *)NULL;
X    current.bstart = current.bline = 0;
X    current.estart = current.eline = 0;
X    current.symbol = 0;
X}   /* end of dump_current */
X
Xvoid sym_enter(s,symbol)
Xstruct nlist *s;
Xlong symbol;
X{
X    register char *p;
X    struct sym_line *sl;
X    struct sym_lvar *lv;
X    struct type_def *td;
X
X    if (s == (struct nlist *)NULL)
X    {   /* if just to dump pending stuff */
X        dump_current();
X        return;
X    }
X    if (s->n_value == 0)
X    {   /* skip undefined or similar stuff; but check for typedef */
X        if ((s->n_type & 0xFF) == N_LSYM)
X            decode_type(s);
X        return;
X    }
X
X    switch ((s->n_type & 0xFF) & ~N_EXT)
X    {   /* what do we need to do to the symbol? */
X        case N_TEXT:        /* start of function */
X            dump_current();
X            current.name = s->n_un.n_name;
X            if (s->n_type & N_EXT && s->n_un.n_name[0] == '_')
X                current.name++;
X            current.value = s->n_value;
X            current.symbol = symbol;
X            current.typenum = 0;
X            break;
X        case N_SLINE:       /* line number */
X            sl = (struct sym_line *)malloc(sizeof(struct sym_line));
X            if (sl == (struct sym_line *)NULL)
X            {   /* enough memory? */
X                fprintf(stderr,"gnu2coff: no memory for source lines\n");
X                exit(1);
X            }
X            sl->next = (struct sym_line *)NULL;
X            sl->number = s->n_desc;
X            sl->address = s->n_value;
X            if (current.lines == (struct sym_line *)NULL)
X                current.lines = current.lines_bottom = sl;
X            else
X            {   /* tack onto end */
X                current.lines_bottom->next = sl;
X                current.lines_bottom = sl;
X            }
X            break;
X        case N_FUN:         /* end of function text; parms, local vars can follow */
X            p = strchr(s->n_un.n_name,':');
X            if (p == (char *)NULL || current.name == (char *)NULL ||
X                strlen(current.name) != (int)(p - s->n_un.n_name) ||
X                strncmp(current.name,s->n_un.n_name,(int)(p - s->n_un.n_name)) != 0)
X            {   /* check to make sure we are still in sequence */
X                printf("** function decode out of sequence: %s,%s\n",
X                    current.name != (char *)NULL ? current.name : "(NULL)",s->n_un.n_name);
X            }
X            current.typenum = get_typenum(p + 1);
X            break;
X        case N_PSYM:        /* a parameter */
X            p = strchr(s->n_un.n_name,':');
X            if (p == (char *)NULL)
X            {   /* then something wrong */
X                printf("** bad parameter: %s\n",s->n_un.n_name);
X                return;
X            }
X            lv = (struct sym_lvar *)malloc(sizeof(struct sym_lvar));
X            if (lv == (struct sym_lvar *)NULL)
X            {   /* enough memory? */
X                fprintf(stderr,"gnu2coff: no memory for local vars\n");
X                exit(1);
X            }
X            lv->next = (struct sym_lvar *)NULL;
X            lv->is_register = 0;
X            lv->name = (char *)malloc((int)(p - s->n_un.n_name) + 1);
X            if (lv->name == (char *)NULL)
X            {   /* out of memory? */
X                fprintf(stderr,"gnu2coff: no memory for names\n");
X                exit(1);
X            }
X            strncpy(lv->name,s->n_un.n_name,(int)(p - s->n_un.n_name));
X            lv->name[(int)(p - s->n_un.n_name)] = '\0';
X            lv->value = s->n_value;
X            lv->typenum = get_typenum(p + 1);
X            if (current.parms == (struct sym_lvar *)NULL)
X                current.parms = current.parms_bottom = lv;
X            else
X            {   /* tack onto end */
X                current.parms_bottom->next = lv;
X                current.parms_bottom = lv;
X            }
X            break;
X        case N_GSYM:        /* a global variable */
X            (void) get_type(s->n_un.n_name,&td);
X            if (globals == (struct type_def *)NULL)
X                globals = globals_bottom = td;
X            else
X            {   /* tack onto end */
X                globals_bottom->next = td;
X                globals_bottom = td;
X            }
X            break;
X        case N_RSYM:        /* local register variable, or mark a parm as a register */
X            p = strchr(s->n_un.n_name,':');
X            if (p == (char *)NULL)
X            {   /* then something wrong */
X                printf("** bad local symbol: %s\n",s->n_un.n_name);
X                return;
X            }
X            for (lv = current.parms; lv != (struct sym_lvar *)NULL; lv = lv->next)
X            {   /* is this a parameter? */
X                if (strlen(lv->name) == (int)(p - s->n_un.n_name) &&
X                    strncmp(lv->name,s->n_un.n_name,(int)(p - s->n_un.n_name)) == 0)
X                {   /* a match means that it is a parameter */
X                    lv->is_register = s->n_value;
X                    return;
X                }
X            }
X            /* FALL THROUGH! */
X        case N_LSYM:        /* local variable on stack */
X            p = strchr(s->n_un.n_name,':');
X            if (p == (char *)NULL)
X            {   /* then something wrong */
X                printf("** bad local symbol: %s\n",s->n_un.n_name);
X                return;
X            }
X            lv = (struct sym_lvar *)malloc(sizeof(struct sym_lvar));
X            if (lv == (struct sym_lvar *)NULL)
X            {   /* enough memory? */
X                fprintf(stderr,"gnu2coff: no memory for local vars\n");
X                exit(1);
X            }
X            lv->next = (struct sym_lvar *)NULL;
X            if (((s->n_type & 0xFF) & ~N_EXT) == N_LSYM)
X                lv->is_register = 0;
X            else lv->is_register = s->n_value;
X            lv->name = (char *)malloc((int)(p - s->n_un.n_name) + 1);
X            if (lv->name == (char *)NULL)
X            {   /* out of memory? */
X                fprintf(stderr,"gnu2coff: no memory for names\n");
X                exit(1);
X            }
X            strncpy(lv->name,s->n_un.n_name,(int)(p - s->n_un.n_name));
X            lv->name[(int)(p - s->n_un.n_name)] = '\0';
X            lv->value = s->n_value;
X            lv->typenum = get_typenum(p + 1);
X            if (current.lvars == (struct sym_lvar *)NULL)
X                current.lvars = current.lvars_bottom = lv;
X            else
X            {   /* tack onto end */
X                current.lvars_bottom->next = lv;
X                current.lvars_bottom = lv;
X            }
X            break;
X        case N_LBRAC:       /* start of basic block */
X            if (current.bline == 0)
X            {   /* if not set yet */
X                current.bstart = s->n_value;
X                for (sl = current.lines; sl != (struct sym_line *)NULL; sl = sl->next)
X                {   /* look for the right line number */
X                    if (sl->address == s->n_value)
X                    {   /* if we found the match */
X                        current.bline = sl->number;
X                        break;
X                    }
X                }
X            }
X            break;
X        case N_RBRAC:       /* end of basic block */
X            if (current.eline == 0)
X            {   /* if not set yet */
X                current.estart = s->n_value;
X                for (sl = current.lines; sl != (struct sym_line *)NULL; sl = sl->next)
X                {   /* look for the right line number */
X                    if (sl->address == s->n_value)
X                    {   /* if we found the match */
X                        current.eline = sl->number;
X                        break;
X                    }
X                }
X            }
X            break;
X        default:            /* just ignore it */
X            break;
X    }
X}   /* end of sym_enter */
END_OF_FILE
if test 22081 -ne `wc -c <'symbolic.c'`; then
    echo shar: \"'symbolic.c'\" unpacked with wrong size!
fi
# end of 'symbolic.c'
fi
echo shar: End of archive 3 \(of 4\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 4 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0