[comp.sys.apollo] GCC & G++ on Apollo's; Part 4 of 4

dclemans@mntgfx.mentor.com (Dave Clemans @ APD x1292) (05/30/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 4 (of 4)."
# Contents:  coff.c
# Wrapped by dclemans@dclemans on Mon May 29 13:06:57 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'coff.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'coff.c'\"
else
echo shar: Extracting \"'coff.c'\" \(53153 characters\)
sed "s/^X//" >'coff.c' <<'END_OF_FILE'
X/*
X * Write out a COFF format file, based on information
X * from a GNU format object file.
X */
X#include <stdio.h>
X#include <string.h>
X#include <memory.h>
X#include <sys/types.h>
X#include <sys/stat.h>
Xextern char *malloc();
Xextern char *realloc();
Xextern long time();
Xextern char *getcwd();
X
X#include "//dclemans/gnu/src/gcc/version.c"
X#define GNU_VERSION "//dclemans/gnu/src/gcc/version.c"
X
X/*
X * C language startup
X */
X/*
X    Apollo C startup stuff; we must add it on our own (if main in file...)
X    This is what it should look like (from expanded listing)
X
X     001C:                   <apollo_c_startup>
X     001C:4E560000                     LINK      SB,#0
X     0020:487A000E                     PEA       ->main
X     0024:4EB900000000                 JSR       <transfer vector> unix_$main
X     002A:4E5E                         UNLK      SB
X     002C:4E75                         RTS      
X     002E:2048                         MOVEA.L   A0,A0
X     0030:00000000                     AC        ->main
X*/
Xstatic long c_apollo_start[6] =
X{
X    0x4e560000, 0x487a000e, 0x4eb90000, 0x00004e5e, 0x4e752048, 0x00000000
X};
X#define C_RELOC_UNIXMAIN  10              /* point at jsr unix_$main (past jsr word) */
X#define C_RELOC_MAIN      20              /* point at ac main */
X
X/*
X * C++ language startup
X */
X/*
X    GNU C++ startup stuff for Apollo (& gnu2coff); we must add it on our own (if main in file...)
X    This is what it looks like:
X
X    We depend on sr10 (or compatible) /usr/lib/crt0.o being linked in
X
X    ** Text section
X    00008130                   _main:
X    00008130 4E56 0000                LINK    A6,#0000
X    00008134 2F0D                     MOVE.L  A5,-(A7)
X    00008136 2A79 00000000            MOVE.L  _GLOBAL_$$HEADER,A5
X    0000813C 4A8D                     TST.L   A5
X    0000813E 6710                     BEQ     +10
X    00008140 206D 0004                MOVE.L  0004(A5),A0
X    00008144 4A88                     TST.L   A0
X    00008146 6702                     BEQ     +02
X    00008148 4E90                     JSR     (A0)
X    0000814A 2A55                     MOVE.L  (A5),A5
X    0000814C 4A8D                     TST.L   A5
X    0000814E 66F0                     BNE     +F0
X    00008150 4EB9 00000000            JSR     main
X    00008156 2A79 00000000            MOVE.L  _GLOBAL_$$HEADER,A5
X    0000815C 4A8D                     TST.L   A5
X    0000815E 6710                     BEQ     +10
X    00008160 206D 0008                MOVE.L  0008(A5),A0
X    00008164 4A88                     TST.L   A0
X    00008166 6702                     BEQ     +02
X    00008168 4E90                     JSR     (A0)
X    0000816A 2A55                     MOVE.L  (A5),A5
X    0000816C 4A8D                     TST.L   A5
X    0000816E 66F0                     BNE     +F0
X    00008170 2A5F                     MOVE.L  (A7)+,A5
X    00008172 4E5E                     UNLK    A6
X    00008174 4E75                     RTS
X*/
Xstatic long cc_apollo_start[18] =
X{
X    0x4e560000, 0x2f0d2a79, 0x00000000, 0x4a8d6710, 0x206d0004,
X    0x4a886702, 0x4e902a55, 0x4a8d66f0, 0x4eb90000, 0x00002a79,
X    0x00000000, 0x4a8d6710, 0x206d0008, 0x4a886702, 0x4e902a55,
X    0x4a8d66f0, 0x2a5f4e5e, 0x4e750000
X};
X#define CC_RELOC_MAIN           0x22
X#define CC_RELOC_HDR1           0x08
X#define CC_RELOC_HDR2           0x28
X
X#define START_SYM       "unix_$main"
X#define START_CODESYM   "<apollo_c_startup>"
Xstatic char *apollo_start = (char *)NULL;
Xstatic long apollo_start_size = 0;
X
X#include <a.out.h>
X#include <apollo/base.h>
X#include <sri.h>
X#include <mir.h>
Xextern void uid_$gen();
X
X#include "gnu2coff.h"
X
Xextern void coff_text_reloc();
Xextern long coff_def_undef();
X
Xstatic struct filehdr  *s_filehdr;
Xstatic struct aouthdr  *s_domainhdr;
Xstruct scnhdr   *s_text;               static char *text_ptr;
Xstatic struct scnhdr   *s_aptv;        static char *aptv_ptr;
Xstruct scnhdr   *s_data;               static char *data_ptr;
Xstruct scnhdr   *s_bss;
Xstatic char *s_syms;                   static long n_syms;
Xstatic char *s_string;                 static long n_string;
Xstatic struct reloc    *s_t_reloc;     static long n_t_reloc;
Xstatic struct reloc    tr;
Xstatic long text_sym = -STEXT;
Xstatic struct reloc    *s_d_reloc;     static long n_d_reloc;
Xstatic struct reloc    dr;
Xstatic long data_sym = -SDATA;
Xstatic long bss_sym = -SBSS;
Xstatic struct reloc    *s_a_reloc;     static long n_a_reloc;
Xstatic struct reloc    ar;
Xstatic long aptv_sym = -SAPTV;
Xstatic struct scnhdr   *s_sri;         static char *sri_recs;     static long n_sri_recs;
Xstatic struct scnhdr   *s_mir;         static char *mir_recs;
Xstatic struct lineno   *s_t_lines;     static long n_t_lines;
Xstatic char *s_patches;                static long n_patches;
X
Xvoid coff_filehdr()
X{
X    s_filehdr = (struct filehdr *)malloc(FILHSZ);
X    if (s_filehdr == (struct filehdr *)NULL)
X    {   /* enough memory? */
X        fprintf(stderr,"gnu2coff: no memory for coff filehdr\n");
X        exit(1);
X    }
X    s_filehdr->f_magic = APOLLOM68KMAGIC;
X    s_filehdr->f_nscns = 0;                 /* set later */
X    s_filehdr->f_timdat = time(0L);
X    s_filehdr->f_symptr = 0;                /* set later */
X    s_filehdr->f_nsyms = 0;                 /* set later */
X    s_filehdr->f_opthdr = sizeof(struct aouthdr);
X    s_filehdr->f_flags = F_LSYMS;           /* corresponds to current version; i.e. most debug stuff not there */
X
X    s_domainhdr = (struct aouthdr *)malloc(sizeof(struct aouthdr));
X    if (s_domainhdr == (struct aouthdr *)NULL)
X    {   /* enough memory? */
X        fprintf(stderr,"gnu2coff: no memory for coff domainhdr\n");
X        exit(1);
X    }
X    s_domainhdr->vformat = APOLLO_COFF_VERSION_NUMBER;
X    s_domainhdr->vstamp = 0;
X    s_domainhdr->tsize = 0;                 /* set later */
X    s_domainhdr->dsize = 0;                 /* set later */
X    s_domainhdr->bsize = 0;                 /* set later */
X    s_domainhdr->entry = 0;                 /* set later */
X    s_domainhdr->text_start = 0;            /* set later */
X    s_domainhdr->data_start = 0;            /* set later */
X    s_domainhdr->o_sri = 0;                 /* set later */
X    s_domainhdr->o_inlib = 0;
X#ifdef  never
X    uid_$gen(s_domainhdr->vid);
X#endif
X    s_domainhdr->vid[0] = 0;
X    s_domainhdr->vid[1] = 0;
X}   /* end of coff_filehdr */
X
Xvoid coff_text(textptr,size)
Xchar *textptr;
Xlong size;
X{
X    register int i;
X
X    s_text = (struct scnhdr *)malloc(SCNHSZ);
X    if (s_text == (struct scnhdr *)NULL)
X    {   /* enough memory? */
X        fprintf(stderr,"gnu2coff: no memory for text header\n");
X        exit(1);
X    }
X    for (i = 0; i < sizeof s_text->s_name; i++)
X        s_text->s_name[i] = '\0';
X    strcpy(s_text->s_name,_TEXT);
X    s_text->s_paddr = 0;
X    s_text->s_vaddr = 0;
X    s_text->s_size = size;
X    s_text->s_scnptr = 0;                   /* set later */
X    s_text->s_relptr = 0;                   /* set later */
X    s_text->s_lnnoptr = 0;                  /* set later */
X    s_text->s_nreloc = 0;                   /* set later */
X    s_text->s_nlnno = 0;                    /* set later */
X    s_text->s_flags = STYP_INSTRUCTION|STYP_TEXT;
X    text_ptr = textptr;
X
X    s_aptv = (struct scnhdr *)malloc(SCNHSZ);
X    if (s_aptv == (struct scnhdr *)NULL)
X    {   /* enough memory? */
X        fprintf(stderr,"gnu2coff: no memory for aptv header\n");
X        exit(1);
X    }
X    for (i = 0; i < sizeof s_aptv->s_name; i++)
X        s_aptv->s_name[i] = '\0';
X    strcpy(s_aptv->s_name,_APTV);
X    s_aptv->s_paddr = 0;
X    s_aptv->s_vaddr = 0;
X    s_aptv->s_size = 0;
X    s_aptv->s_scnptr = 0;                   /* set later */
X    s_aptv->s_relptr = 0;                   /* set later */
X    s_aptv->s_lnnoptr = 0;                  /* set later */
X    s_aptv->s_nreloc = 0;                   /* set later */
X    s_aptv->s_nlnno = 0;                    /* set later */
X    s_aptv->s_flags = STYP_DATA;
X    aptv_ptr = (char *)NULL;
X
X    s_filehdr->f_nscns += 2;
X}   /* end of coff_text */
X
Xvoid coff_data(dataptr,size)
Xchar *dataptr;
Xlong size;
X{
X    register int i;
X
X    s_data = (struct scnhdr *)malloc(SCNHSZ);
X    if (s_data == (struct scnhdr *)NULL)
X    {   /* enough memory? */
X        fprintf(stderr,"gnu2coff: no memory for data header\n");
X        exit(1);
X    }
X    for (i = 0; i < sizeof s_data->s_name; i++)
X        s_data->s_name[i] = '\0';
X    strcpy(s_data->s_name,_DATA);
X    s_data->s_paddr = 0;
X    s_data->s_vaddr = 0;
X    s_data->s_size = size;
X    s_data->s_scnptr = 0;                   /* set later */
X    s_data->s_relptr = 0;                   /* set later */
X    s_data->s_lnnoptr = 0;                  /* set later */
X    s_data->s_nreloc = 0;                   /* set later */
X    s_data->s_nlnno = 0;                    /* set later */
X    if (size != 0)
X        s_data->s_flags = STYP_ZERO|STYP_DATA;
X    else s_data->s_flags = STYP_BSS;
X    data_ptr = dataptr;
X
X    s_filehdr->f_nscns++;
X}   /* end of coff_data */
X
Xvoid coff_bss(size)
Xlong size;
X{
X    register int i;
X
X    s_bss = (struct scnhdr *)malloc(SCNHSZ);
X    if (s_bss == (struct scnhdr *)NULL)
X    {   /* enough memory? */
X        fprintf(stderr,"gnu2coff: no memory for bss header\n");
X        exit(1);
X    }
X    for (i = 0; i < sizeof s_bss->s_name; i++)
X        s_bss->s_name[i] = '\0';
X    strcpy(s_bss->s_name,_BSS);
X    s_bss->s_paddr = 0;
X    s_bss->s_vaddr = 0;
X    s_bss->s_size = size;
X    s_bss->s_scnptr = 0;                   /* set later */
X    s_bss->s_relptr = 0;                   /* set later */
X    s_bss->s_lnnoptr = 0;                  /* set later */
X    s_bss->s_nreloc = 0;                   /* set later */
X    s_bss->s_nlnno = 0;                    /* set later */
X    s_bss->s_flags = STYP_BSS;
X
X    s_filehdr->f_nscns++;
X}   /* end of coff_bss */
X
Xstatic long new_string(string)
Xchar *string;
X{
X    register char *p;
X    register long newlen;
X    register long index;
X
X    if (s_string != (char *)NULL)
X    {   /* already in table? */
X        for (p = s_string; p < &s_string[n_string]; p++)
X        {   /* look at each piece */
X            if (strcmp(string,p) == 0)
X            {   /* found a match? */
X                index = (long)(p - s_string);
X                return index+sizeof n_string;
X            }
X            while (*p)
X                p++;
X        }
X    }
X
X    newlen = strlen(string) + 1;
X    if (n_string == 0)
X    {   /* if no table yet */
X        index = 0;
X        s_string = (char *)malloc(newlen + 1);
X        if (s_string == (char *)NULL)
X        {   /* enough memory? */
X            fprintf(stderr,"gnu2coff: no memory for strings\n");
X            exit(1);
X        }
X        n_string = newlen + 1;
X    }
X    else
X    {   /* bump existing table */
X        index = n_string - 1;
X        s_string = (char *)realloc(s_string,n_string + newlen);
X        if (s_string == (char *)NULL)
X        {   /* enough memory? */
X            fprintf(stderr,"gnu2coff: no memory for strings\n");
X            exit(1);
X        }
X        n_string += newlen;
X    }
X    for (p = &s_string[index]; newlen >= 0; newlen--)
X        *p++ = '\0';
X    strcpy(&s_string[index],string);
X    return index+sizeof n_string;
X}   /* end of new_string */
X
Xstruct syment *coff_symbol_space(count,number)
Xlong count;
Xlong *number;
X{
X    register char *s;
X
X    *number = n_syms;
X    if (n_syms == 0)
X    {   /* first creation? */
X        s_syms = (char *)malloc(count*SYMESZ);
X        if (s_syms == (char *)NULL)
X        {   /* enough memory? */
X            fprintf(stderr,"gnu2coff: no memory for coff symbols\n");
X            exit(1);
X        }
X        n_syms = count;
X    }
X    else
X    {   /* increase space? */
X        s_syms = (char *)realloc(s_syms,(n_syms+count)*SYMESZ);
X        if (s_syms == (char *)NULL)
X        {   /* enough memory? */
X            fprintf(stderr,"gnu2coff: no memory for coff symbols\n");
X            exit(1);
X        }
X        n_syms += count;
X    }
X    s = (char *)((long)s_syms + (*number * SYMESZ));
X    memset(s,'\0',count * SYMESZ);
X    return (struct syment *)s;
X}   /* end of coff_symbol_space */
X
Xstruct syment *coff_symbol_addr(symnum)
Xlong symnum;
X{
X    return (struct syment *)((long)s_syms + (symnum * SYMESZ));
X}   /* end of coff_symbol_addr */
X
Xstatic char *current_path = (char *)NULL;
X
Xlong coff_def_file(file)
Xchar *file;
X{
X    register long i;
X    long symnum;
X    struct syment *s;
X    union auxent *a;
X    char buffer[BUFSIZ*2];
X
X    if (current_path == (char *)NULL)
X        current_path = getcwd((char *)NULL,BUFSIZ);
X    if (*file != '/')
X    {   /* pseudo-full path */
X        sprintf(buffer,"%s/%s",current_path,file);
X        file = buffer;
X    }
X
X    s = coff_symbol_space(2L,&symnum);
X    a = (union auxent *)((long)s_syms + ((symnum+1) * SYMESZ));
X
X    strcpy(s->n_name,".file");
X    s->n_value = -1;                    /* fix later */
X    s->n_scnum = -2;
X    s->n_type = T_NULL;
X    s->n_sclass = C_FILE;
X    s->n_numaux = 1;
X    if (strlen(file) <= FILNMLEN)
X    {   /* put in directly */
X        strncpy(a->x_file.x_fname,file,FILNMLEN);
X    }
X    else
X    {   /* put in string table */
X        a->x_file._n_n._n_offset = new_string(file);
X        a->x_file._n_n._n_zeroes = 0;
X    }
X
X    for (i = 0; i < symnum; i++)
X    {   /* fix any previous files? */
X        s = (struct syment *)((long)s_syms + (i * SYMESZ));
X        if (s->n_sclass == C_FILE && s->n_value == -1)
X        {   /* found what we need to fix */
X            s->n_value = symnum;
X            break;
X        }
X        i += s->n_numaux;
X    }
X
X    return symnum;
X}   /* end of coff_def_file */
X
Xlong coff_def_symbol(name,value,type,ext)
Xchar *name;
Xlong value;
Xint type;
Xint ext;
X{
X    register long i;
X    long symnum,usymnum;
X    struct syment *s;
X    union auxent *a;
X    long *ptr;
X
X    if (ext && *name == '_')
X        name++;
X
X    if (strncmp("_GLOBAL_$I$",name,11) == 0 || strncmp("_GLOBAL_$D$",name,11) == 0)
X    {   /* set up C++ static constructor/destructor */
X        cplusplus_mode = 1;
X        if (strncmp("_GLOBAL_$I$",name,11) == 0)
X            cplusplus_ctor = value;
X        else cplusplus_dtor = value;
X    }
X
X    s = coff_symbol_space(1L,&symnum);
X
X    if (strlen(name) <= SYMNMLEN)
X        memccpy(s->n_name,name,'\0',SYMNMLEN);
X    else
X    {   /* put in string table */
X        s->n_zeroes = 0;
X        s->n_offset = new_string(name);
X    }
X    s->n_value = value;
X    s->n_numaux = 0;
X    if (ext)
X        s->n_sclass = C_EXT;    /* dummy placeholder */
X    else s->n_sclass = C_STAT;  /* dummy placeholder */
X    s->n_type = T_INT;          /* dummy placeholder */
X    if (type == STEXT && ext)
X        s->n_type |= (DT_FCN << N_BTSHFT);
X    s->n_scnum = type;
X    if (type == STEXT && strcmp(name,"gcc_compiled.") != 0)
X    {   /* add in aux entry */
X        s->n_numaux = 1;
X        a = (union auxent *)coff_symbol_space(1L,&usymnum);
X        /* assert that symnum+1==usymnum */
X        a->x_sym.x_tagndx = 0;                          /* what to do here? */
X        a->x_sym.x_misc.x_fsize = 0;                    /* what to do here? */
X        a->x_sym.x_fcn.x_lnnoptr = 0;                   /* what to do here? */
X        a->x_sym.x_fcn.x_endndx = 0;                    /* what to do here? */
X        a->x_sym.x_tvndx = 0;
X    }
X
X    if (strcmp(name,"main") == 0 && cplusplus_main != 1)
X    {   /* then need to add apollo startup code */
X        cplusplus_main = 1;
X        if (type != STEXT)
X            printf("** main not in text section?\n");
X        s_domainhdr->entry = s_text->s_size;
X        if (!cplusplus_mode)
X        {   /* if just ordinary C stuff */
X            apollo_start = (char *)c_apollo_start;
X            apollo_start_size = sizeof c_apollo_start;
X            usymnum = coff_def_undef(START_SYM,1);
X            coff_text_reloc(C_RELOC_MAIN+s_text->s_size,symnum);
X            coff_text_reloc(C_RELOC_UNIXMAIN+s_text->s_size,usymnum);
X        }
X        else
X        {   /* put in our C++ stuff */
X            apollo_start = (char *)cc_apollo_start;
X            apollo_start_size = sizeof cc_apollo_start;
X            coff_text_reloc(CC_RELOC_MAIN+s_text->s_size,symnum);
X            coff_text_reloc(CC_RELOC_HDR1+s_text->s_size,-SGLOBAL);
X            coff_text_reloc(CC_RELOC_HDR2+s_text->s_size,-SGLOBAL);
X            s = coff_symbol_addr(symnum);
X            memccpy(s->n_name,"_main",'\0',SYMNMLEN);
X            (void) coff_def_symbol("main",s_text->s_size,STEXT,1);
X            ptr = (long *)&apollo_start[CC_RELOC_MAIN];
X            *ptr = value;
X        }
X        (void) coff_def_symbol(START_CODESYM,s_text->s_size,STEXT,1);
X    }
X
X    return symnum;
X}   /* end of coff_def_symbol */
X
Xlong coff_def_undef(name,ext)
Xchar *name;
Xint ext;
X{
X    register long i;
X    long symnum;
X    struct syment *s;
X          
X    if (ext && *name == '_')
X        name++;
X
X    s = coff_symbol_space(1L,&symnum);
X
X    if (strlen(name) <= SYMNMLEN)
X        memccpy(s->n_name,name,'\0',SYMNMLEN);
X    else
X    {   /* put in string table */
X        s->n_zeroes = 0;
X        s->n_offset = new_string(name);
X    }
X    s->n_scnum = 0;
X    s->n_value = 0;
X    s->n_numaux = 0;
X    if (ext)
X        s->n_sclass = C_EXT;    /* dummy placeholder */
X    else s->n_sclass = C_STAT;  /* dummy placeholder */
X    s->n_type = T_INT | (DT_FCN << N_BTSHFT);
X
X    return symnum;
X}   /* end of coff_def_undef */
X
Xlong coff_def_section(num,addr,size,nreloc,nline)
Xint num;
Xlong addr;
Xlong size;
Xint nreloc;
Xint nline;
X{
X    register long i;
X    long symnum;
X    struct syment *s;
X    union auxent *a;
X    char *name;
X
X    switch (num)
X    {   /* what name? */
X        case STEXT:
X            name = _TEXT;
X            break;
X        case SAPTV:
X            name = _APTV;
X            break;
X        case SDATA:
X            name = _DATA;
X            break;
X        case SBSS:
X            name = _BSS;
X            break;
X        case SSRI:
X            name =_SRI;
X            break;
X        case SMIR:
X            name =_MIR;
X            break;
X        default:
X            fprintf(stderr,"gnu2coff: logic error in coff_def_section!\n");
X            exit(1);
X    }
X    if (s_data == (struct scnhdr *)NULL && num == SDATA)
X    {   /* conflict? */
X        fprintf(stderr,"gnu2coff: logic error in coff_def_section!\n");
X        exit(1);
X    }
X    if (s_bss == (struct scnhdr *)NULL && num == SBSS)
X    {   /* conflict? */
X        fprintf(stderr,"gnu2coff: logic error in coff_def_section!\n");
X        exit(1);
X    }
X
X    s = coff_symbol_space(2L,&symnum);
X    a = (union auxent *)((long)s_syms + ((symnum+1) * SYMESZ));
X
X    if (strlen(name) <= SYMNMLEN)
X        memccpy(s->n_name,name,'\0',SYMNMLEN);
X    else
X    {   /* put in string table */
X        s->n_zeroes = 0;
X        s->n_offset = new_string(name);
X    }
X    s->n_scnum = num;
X    s->n_value = addr;
X    s->n_numaux = 1;
X    s->n_sclass = C_STAT;
X    s->n_type = T_NULL;
X    a->x_scn.x_scnlen = size;
X    a->x_scn.x_nreloc = nreloc;
X    a->x_scn.x_nlinno = nline;
X
X    switch (num)
X    {   /* save symbol pointers */
X        case STEXT:
X            text_sym = symnum;
X            break;
X        case SDATA:
X            data_sym = symnum;
X            break;
X        case SAPTV:
X            aptv_sym = symnum;
X            break;
X        case SBSS:
X            bss_sym = symnum;
X            break;
X    }
X
X    return symnum;
X}   /* end of coff_def_section */
X
Xvoid coff_aptv_reloc(vaddr,symnum)
Xlong vaddr;
Xlong symnum;
X{
X    long aentry;
X    struct reloc *r;
X
X    if (n_a_reloc == 0)
X    {   /* create first entry? */
X        aentry = 0;
X        s_a_reloc = (struct reloc *)malloc(RELSZ);
X        if (s_a_reloc == (struct reloc *)NULL)
X        {   /* enough memory? */
X            fprintf(stderr,"gnu2coff: no memory for aptv reloc entries\n");
X            exit(1);
X        }
X        n_a_reloc = 1;
X    }
X    else
X    {   /* bump existing stuff */
X        aentry = n_a_reloc;
X        s_a_reloc = (struct reloc *)realloc(s_a_reloc,(n_a_reloc+1)*RELSZ);
X        if (s_a_reloc == (struct reloc *)NULL)
X        {   /* enough memory? */
X            fprintf(stderr,"gnu2coff: no memory for aptv reloc entries\n");
X            exit(1);
X        }
X        n_a_reloc++;
X    }
X    r = (struct reloc *)((long)s_a_reloc + (aentry * RELSZ));
X
X    r->r_vaddr = vaddr;
X    r->r_symndx = symnum;
X    r->r_type = R_DIR32;
X
X    if (s_aptv->s_nreloc != S_NRELOC_ESC)
X        s_aptv->s_nreloc++;
X    if (s_aptv->s_nreloc == 0)
X    {   /* if it overflowed */
X        s_aptv->s_nreloc = S_NRELOC_ESC;
X        ar.r_vaddr = n_a_reloc;
X        ar.r_symndx = 0;
X        ar.r_type = R_NRELOC;
X    }
X    if (ar.r_vaddr != 0)
X        ar.r_vaddr = n_a_reloc;
X}   /* end of coff_aptv_reloc */
X
Xlong coff_aptv_entry(symnum)
Xlong symnum;
X{
X    long vaddr;
X    long *word;
X    short *instr;
X
X    if (s_aptv->s_size == 0)
X    {   /* if first entry */
X        aptv_ptr = (char *)malloc(sizeof(short)+sizeof(long));
X        if (aptv_ptr == (char *)NULL)
X        {   /* enough memory? */
X            fprintf(stderr,"gnu2coff: no memory for aptv entries\n");
X            exit(1);
X        }
X    }
X    else
X    {   /* bump existing stuff */
X        aptv_ptr = (char *)realloc(aptv_ptr,s_aptv->s_size+sizeof(short)+sizeof(long));
X        if (aptv_ptr == (char *)NULL)
X        {   /* enough memory? */
X            fprintf(stderr,"gnu2coff: no memory for aptv entries\n");
X            exit(1);
X        }
X    }
X    instr = (short *)&aptv_ptr[s_aptv->s_size];
X    *instr = JUMP_INSTR;
X    word = (long *)&aptv_ptr[s_aptv->s_size+sizeof(short)];
X    *word = 0;
X    vaddr = s_aptv->s_size;
X    s_aptv->s_size += sizeof(short)+sizeof(long);
X    return vaddr;
X}   /* end of coff_aptv_entry */
X
Xlong coff_patch_space(length,memaddr)
Xlong length;
Xchar **memaddr;
X{
X    long vaddr;
X    long newlen;
X    char *ptr;
X    long *word;
X    short *instr;
X
X    if (s_data == (struct scnhdr *)NULL)
X        coff_data((char *)NULL,0);
X
X    vaddr = n_patches;
X    newlen = ((n_patches + length + sizeof(long) - 1) / sizeof(long)) * sizeof(long);
X    if (n_patches == 0)
X    {   /* if first alloc */
X        s_patches = (char *)malloc(newlen);
X        if (s_patches == (char *)NULL)
X        {   /* enough memory? */
X            fprintf(stderr,"gnu2coff: no memory for data patches\n");
X            exit(1);
X        }
X    }
X    else
X    {   /* bump existing size */
X        s_patches = (char *)realloc(s_patches,newlen);
X        if (s_patches == (char *)NULL)
X        {   /* enough memory? */
X            fprintf(stderr,"gnu2coff: no memory for data patches\n");
X            exit(1);
X        }
X    }
X    n_patches = newlen;
X    *memaddr = &s_patches[vaddr];
X    return vaddr;
X}   /* end of coff_patch_space */
X
Xvoid coff_text_reloc(vaddr,symnum)
Xlong vaddr;
Xlong symnum;
X{
X    long tentry;
X    struct reloc *r,*nr;
X    struct syment *s;
X    long *word;
X    short *instr;
X    char *name;
X
X    if (n_t_reloc == 0)
X    {   /* create first entry? */
X        tentry = 0;
X        s_t_reloc = (struct reloc *)malloc(RELSZ);
X        if (s_t_reloc == (struct reloc *)NULL)
X        {   /* enough memory? */
X            fprintf(stderr,"gnu2coff: no memory for text reloc entries\n");
X            exit(1);
X        }
X        n_t_reloc = 1;
X    }
X    else
X    {   /* bump existing stuff */
X        tentry = n_t_reloc;
X        s_t_reloc = (struct reloc *)realloc(s_t_reloc,(n_t_reloc+1)*RELSZ);
X        if (s_t_reloc == (struct reloc *)NULL)
X        {   /* enough memory? */
X            fprintf(stderr,"gnu2coff: no memory for text reloc entries\n");
X            exit(1);
X        }
X        n_t_reloc++;
X    }
X    r = (struct reloc *)((long)s_t_reloc + (tentry * RELSZ));
X
X    r->r_vaddr = vaddr;
X    r->r_symndx = symnum;
X    r->r_type = R_DIR32;
X
X    if (s_text->s_nreloc != S_NRELOC_ESC)
X        s_text->s_nreloc++;
X    if (s_text->s_nreloc == 0)
X    {   /* if it overflowed */
X        s_text->s_nreloc = S_NRELOC_ESC;
X        tr.r_vaddr = n_t_reloc;
X        tr.r_symndx = 0;
X        tr.r_type = R_NRELOC;
X    }
X    if (tr.r_vaddr != 0)
X        tr.r_vaddr = n_t_reloc;
X
X    if (vaddr < s_text->s_size)
X        word = (long *)&text_ptr[vaddr];
X    else word = (long *)((long)apollo_start + vaddr - s_text->s_size);
X    s = (struct syment *)((long)s_syms + (symnum * SYMESZ));
X    if (symnum >= 0)
X    {   /* if a good symbol pointer */
X        if (s->n_zeroes == 0)
X            name = &s_string[s->n_offset - sizeof n_string];
X        else name = s->n_name;
X        ref_undefined(name,(char *)word,r,s,s_a_reloc,n_a_reloc);
X    }
X}   /* end of coff_text_reloc */
X
Xvoid coff_data_reloc(vaddr,symnum)
Xlong vaddr;
Xlong symnum;
X{
X    long dentry;
X    struct reloc *r;
X
X    if (s_data == (struct scnhdr *)NULL)
X        printf("** data relocation without data section\n");
X
X    if (n_d_reloc == 0)
X    {   /* create first entry? */
X        dentry = 0;
X        s_d_reloc = (struct reloc *)malloc(RELSZ);
X        if (s_d_reloc == (struct reloc *)NULL)
X        {   /* enough memory? */
X            fprintf(stderr,"gnu2coff: no memory for data reloc entries\n");
X            exit(1);
X        }
X        n_d_reloc = 1;
X    }
X    else
X    {   /* bump existing stuff */
X        dentry = n_d_reloc;
X        s_d_reloc = (struct reloc *)realloc(s_d_reloc,(n_d_reloc+1)*RELSZ);
X        if (s_d_reloc == (struct reloc *)NULL)
X        {   /* enough memory? */
X            fprintf(stderr,"gnu2coff: no memory for data reloc entries\n");
X            exit(1);
X        }
X        n_d_reloc++;
X    }
X    r = (struct reloc *)((long)s_d_reloc + (dentry * RELSZ));
X
X    r->r_vaddr = vaddr;
X    r->r_symndx = symnum;
X    r->r_type = R_DIR32;
X
X    if (s_data != (struct scnhdr *)NULL && s_data->s_nreloc != S_NRELOC_ESC)
X        s_data->s_nreloc++;
X    if (s_data != (struct scnhdr *)NULL && s_data->s_nreloc == 0)
X    {   /* if it overflowed */
X        s_data->s_nreloc = S_NRELOC_ESC;
X        dr.r_vaddr = n_d_reloc;
X        dr.r_symndx = 0;
X        dr.r_type = R_NRELOC;
X    }
X    if (dr.r_vaddr != 0)
X        dr.r_vaddr = n_d_reloc;
X}   /* end of coff_data_reloc */
X
X/*
X * What resources does this code need?
X * Apollo magic...
X */
Xvoid coff_def_sri()
X{
X    register int i;
X    srihdr *sh;
X    srirec *sr;
X
X    s_sri = (struct scnhdr *)malloc(SCNHSZ);
X    if (s_sri == (struct scnhdr *)NULL)
X    {   /* enough memory? */
X        fprintf(stderr,"gnu2coff: no memory for sri header\n");
X        exit(1);
X    }
X    for (i = 0; i < sizeof s_sri->s_name; i++)
X        s_sri->s_name[i] = '\0';
X    strcpy(s_sri->s_name,_SRI);
X    s_sri->s_paddr = 0;
X    s_sri->s_vaddr = 0;
X    s_sri->s_scnptr = 0;                   /* set later */
X    s_sri->s_relptr = 0;
X    s_sri->s_lnnoptr = 0;
X    s_sri->s_nreloc = 0;
X    s_sri->s_nlnno = 0;
X    s_sri->s_flags = STYP_INFO;
X                       
X    n_sri_recs = 6;
X    s_sri->s_size = (n_sri_recs*SRIRECSZ)+SRIHDRSZ;
X    sri_recs = (char *)malloc(s_sri->s_size);
X    if (sri_recs == (char *)NULL)
X    {   /* enough memory? */
X        fprintf(stderr,"gnu2coff: no memory for sri recs\n");
X        exit(1);
X    }
X    sh = (srihdr *)sri_recs;
X    sr = (srirec *)&sri_recs[SRIHDRSZ];
X    sh->nsris = 6;
X    sr[0].kind = software_sri_kind;
X    sr[0].combine = take_or_rule;
X    sr[0].info.value = xrs_software_flag;
X    sr[1].kind = software_sri_kind;
X    sr[1].combine = take_or_rule;
X    sr[1].info.value = reg_save_software_flag;
X    sr[2].kind = systype_sri_kind;
X    sr[2].combine = take_special_rule;
X    sr[2].info.value = 2;               /* is this sys5?  where does this value come from? */
X    sr[3].kind = runtype_sri_kind;
X    sr[3].combine = take_special_rule;
X    sr[3].info.value = 2;               /* is this sys5?  where does this value come from? */
X    sr[4].kind = stacksize_sri_kind;
X    sr[4].combine = take_max_rule;
X    sr[4].info.value = gen_stack_size;  /* 512K stack space (at least) */
X    sr[5].kind = hardware_sri_kind;     /* 68020+/68881+ hardware */
X    sr[5].combine = take_or_rule;
X    sr[5].info.value = m020_hardware_flag|m881_hardware_flag;
X
X    s_filehdr->f_nscns++;
X}   /* end of coff_def_sri */
X
X/*
X * What tool built this code?
X * Apollo magic...
X */
Xvoid coff_def_mir(module)
Xchar *module;
X{
X    register int i;
X    mirhdr *mh;
X    mir *mr;
X    char buffer[BUFSIZ];
X    char mname[BUFSIZ];
X    struct stat statb;
X
X    s_mir = (struct scnhdr *)malloc(SCNHSZ);
X    if (s_mir == (struct scnhdr *)NULL)
X    {   /* enough memory? */
X        fprintf(stderr,"gnu2coff: no memory for mir header\n");
X        exit(1);
X    }
X    for (i = 0; i < sizeof s_mir->s_name; i++)
X        s_mir->s_name[i] = '\0';
X    strcpy(s_mir->s_name,_MIR);
X    s_mir->s_paddr = 0;
X    s_mir->s_vaddr = 0;
X    s_mir->s_scnptr = 0;                   /* set later */
X    s_mir->s_relptr = 0;
X    s_mir->s_lnnoptr = 0;
X    s_mir->s_nreloc = 0;
X    s_mir->s_nlnno = 0;
X    s_mir->s_flags = STYP_INFO;
X
X    sprintf(buffer,"GNU C System Version %s",version_string);
X    strcpy(mname,module);
X    if (mname[strlen(mname)-2] == '.' && mname[strlen(mname)-1] == 'o')
X        mname[strlen(mname)-2] = '\0';
X
X#define MIR_MAKER_SIZE          14
X#define MIR_MODULE_NAME_SIZE    8
X    s_mir->s_size = MIRHDRSZ + MIR_MAKER_SIZE + MIR_MODULE_NAME_SIZE;
X    mir_recs = (char *)malloc(s_mir->s_size);
X    if (mir_recs == (char *)NULL)
X    {   /* enough memory? */
X        fprintf(stderr,"gnu2coff: no memory for mir recs\n");
X        exit(1);
X    }
X    mh = (mirhdr *)mir_recs;
X    mh->nmirs = 2;
X    mr = (mir *)&mir_recs[MIRHDRSZ];
X    mr->kind = maker_mir_kind;
X    mr->mir_size = MIR_MAKER_SIZE;
X    mr->info.mir_maker.version = 0;
X    stat(GNU_VERSION,&statb);
X    mr->info.mir_maker.creation_time = statb.st_mtime;
X    mr->info.mir_maker.maker_name_offset = new_string(buffer);
X    mr = (mir *)&mir_recs[MIRHDRSZ + MIR_MAKER_SIZE];
X    mr->kind = module_name_mir_kind;
X    mr->mir_size = MIR_MODULE_NAME_SIZE;
X    mr->info.mir_module_name.module_name_offset = new_string(mname);
X
X    s_filehdr->f_nscns++;
X}   /* end of coff_def_mir */
X
Xlong coff_text_line(addr,line)
Xlong addr;
Xshort line;
X{
X    register long lentry;
X    register struct lineno *l;
X
X    lentry = n_t_lines;
X    if (n_t_lines == 0)
X    {   /* if nothing yet */
X        s_t_lines = (struct lineno *)malloc(LINESZ);
X        if (s_t_lines == (struct lineno *)NULL)
X        {   /* enough memory? */
X            fprintf(stderr,"gnu2coff: no memory for text line numbers\n");
X            exit(1);
X        }
X        n_t_lines = 1;
X    }
X    else
X    {   /* bump existing stuff */
X        s_t_lines = (struct lineno *)realloc(s_t_lines,(n_t_lines+1)*LINESZ);
X        if (s_t_lines == (struct lineno *)NULL)
X        {   /* enough memory? */
X            fprintf(stderr,"gnu2coff: no memory for text line numbers\n");
X            exit(1);
X        }
X        n_t_lines++;
X    }
X    l = (struct lineno *)((long)s_t_lines + (lentry * LINESZ));
X    l->l_addr.l_paddr = addr;
X    l->l_lnno = line;
X    return lentry;
X}   /* end of coff_text_line */
X
Xstatic void coff_patch_reloc()
X{
X    register long i;
X    register struct reloc *r;
X
X    for (i = 0; i < n_t_reloc; i++)
X    {   /* patch pre-built section symbol refs */
X        r = (struct reloc *)((long)s_t_reloc + (i * RELSZ));
X        switch (r->r_symndx)
X        {   /* anything need patching? */
X            case -STEXT:
X                r->r_symndx = text_sym;
X                break;
X            case -SDATA:
X                if (s_data == (struct scnhdr *)NULL)
X                    printf("** data reference in text relocation without data section\n");
X                r->r_symndx = data_sym;
X                break;
X            case -SBSS:
X                if (s_bss == (struct scnhdr *)NULL)
X                    printf("** bss reference in text relocation without bss section\n");
X                r->r_symndx = bss_sym;
X                break;
X            case -SAPTV:
X                r->r_symndx = aptv_sym;
X                break;
X            case -SGLOBAL:
X                r->r_symndx = cplusplus_gsym;
X                break;
X        }
X    }
X    for (i = 0; i < n_a_reloc; i++)
X    {   /* patch pre-built section symbol refs */
X        r = (struct reloc *)((long)s_a_reloc + (i * RELSZ));
X        switch (r->r_symndx)
X        {   /* anything need patching? */
X            case -STEXT:
X                r->r_symndx = text_sym;
X                break;
X            case -SDATA:
X                if (s_data == (struct scnhdr *)NULL)
X                    printf("** data reference in aptv relocation without data section\n");
X                r->r_symndx = data_sym;
X                break;
X            case -SBSS:
X                if (s_bss == (struct scnhdr *)NULL)
X                    printf("** bss reference in aptv relocation without bss section\n");
X                r->r_symndx = bss_sym;
X                break;
X            case -SAPTV:
X                r->r_symndx = aptv_sym;
X                break;
X        }
X    }
X    for (i = 0; i < n_d_reloc; i++)
X    {   /* patch pre-built section symbol refs */
X        r = (struct reloc *)((long)s_d_reloc + (i * RELSZ));
X        switch (r->r_symndx)
X        {   /* anything need patching? */
X            case -STEXT:
X                r->r_symndx = text_sym;
X                break;
X            case -SDATA:
X                if (s_data == (struct scnhdr *)NULL)
X                    printf("** data reference in data relocation without data section\n");
X                r->r_symndx = data_sym;
X                break;
X            case -SBSS:
X                if (s_bss == (struct scnhdr *)NULL)
X                    printf("** bss reference in data relocation without bss section\n");
X                r->r_symndx = bss_sym;
X                break;
X            case -SAPTV:
X                r->r_symndx = aptv_sym;
X                break;
X        }
X    }
X}   /* end of coff_patch_reloc */
X
Xstatic void coff_patch_syms()
X{
X    register long i;
X    union auxent *a;
X    struct syment *s;
X    long scnmap[6];
X    struct syment *last_funcs;
X    union auxent *last_func,*last_bf;
X
X    /* patch section numbers in symbols */
X    scnmap[STEXT-1] = i = 1;
X    if (s_data != (struct scnhdr *)NULL)
X        scnmap[SDATA-1] = ++i;
X    scnmap[SAPTV-1] = ++i;
X    if (s_bss != (struct scnhdr *)NULL)
X        scnmap[SBSS-1] = ++i;
X    scnmap[SSRI-1] = ++i;
X    scnmap[SMIR-1] = ++i;
X    for (i = 0; i < n_syms; i++)
X    {   /* for each symbol */
X        s = (struct syment *)((long)s_syms + (i * SYMESZ));
X        if (s->n_scnum > 0)
X            s->n_scnum = scnmap[s->n_scnum-1];
X        i += s->n_numaux;
X    }
X
X    /* patch chained symtab symbols */
X    last_func = last_bf = (union auxent *)NULL;
X    last_funcs = (struct syment *)NULL;
X    for (i = 0; i < n_syms; i++)
X    {   /* make symtab entries correct */
X        s = (struct syment *)((long)s_syms + (i * SYMESZ));
X        a = (union auxent *)((long)s_syms + ((i+1) * SYMESZ));
X        if (s->n_sclass == C_FILE && s->n_value == -1)
X        {   /* found what we need to fix */
X            s->n_value = n_syms-1;
X        }
X        else if (s->n_sclass == C_FCN)
X        {   /* found a function thingy */
X            if (strcmp(s->n_name,".bf") != 0 && strcmp(s->n_name,".ef") != 0)
X            {   /* if not a function body */
X                a->x_sym.x_fcnary.x_fcn.x_lnnoptr = s_text->s_lnnoptr +
X                    (a->x_sym.x_fcnary.x_fcn.x_lnnoptr * LINESZ);
X                if (last_func != (union auxent *)NULL)
X                {   /* we can finish the record */
X                    last_func->x_sym.x_misc.x_fsize = s->n_value - last_funcs->n_value;
X                    last_func->x_sym.x_fcnary.x_fcn.x_endndx = i;
X                    last_funcs->n_sclass = last_func->x_sym.x_tvndx;
X                    last_func->x_sym.x_tvndx = 0;
X                }
X                last_funcs = s;
X                last_func = a;
X            }
X            else if (strcmp(s->n_name,".bf") == 0)
X            {   /* do stuff for body */
X                if (last_bf != (union auxent *)NULL)
X                    last_bf->x_sym.x_fcnary.x_fcn.x_endndx = i;
X                last_bf = a;
X            }
X            else
X            {   /* do stuff for function end */
X                /* nothing needed so far */
X            }
X        }
X        else if (s->n_scnum == 0)
X            s->n_type = T_NULL;
X        i += s->n_numaux;
X    }
X    if (last_func != (union auxent *)NULL)
X    {   /* finish out last function */
X        last_func->x_sym.x_misc.x_fsize = s_text->s_size - last_funcs->n_value;
X        last_func->x_sym.x_fcnary.x_fcn.x_endndx = n_syms-1;
X        last_funcs->n_sclass = last_func->x_sym.x_tvndx;
X        last_func->x_sym.x_tvndx = 0;
X    }
X    if (last_bf != (union auxent *)NULL)
X        last_bf->x_sym.x_fcnary.x_fcn.x_endndx = n_syms-1;
X
X    /* patch section header symbols */
X/*  s = (struct syment *)((long)s_syms + (text_sym * SYMESZ)); */
X    a = (union auxent *)((long)s_syms + ((text_sym+1) * SYMESZ));
X    a->x_scn.x_scnlen += apollo_start_size;
X    if (n_t_reloc > 0)
X        a->x_scn.x_nreloc = s_text->s_nreloc;
X    if (n_t_lines > 0)
X        a->x_scn.x_nlinno = n_t_lines;
X
X    s = (struct syment *)((long)s_syms + (aptv_sym * SYMESZ));
X    a = (union auxent *)((long)s_syms + ((aptv_sym+1) * SYMESZ));
X    s->n_value = s_text->s_size + apollo_start_size;
X    if (s_data != (struct scnhdr *)NULL)
X        s->n_value += s_data->s_size + n_patches;
X    a->x_scn.x_scnlen = s_aptv->s_size;
X    if (n_a_reloc > 0)
X        a->x_scn.x_nreloc = s_aptv->s_nreloc;
X
X    s = (struct syment *)((long)s_syms + (data_sym * SYMESZ));
X    a = (union auxent *)((long)s_syms + ((data_sym+1) * SYMESZ));
X    if (s_data != (struct scnhdr *)NULL)
X    {   /* if a data section */
X        s->n_value = s_text->s_size + apollo_start_size;
X        a->x_scn.x_scnlen = s_data->s_size + n_patches;
X        if (n_d_reloc > 0)
X            a->x_scn.x_nreloc = s_data->s_nreloc;
X    }
X
X    s = (struct syment *)((long)s_syms + (bss_sym * SYMESZ));
X/*  a = (union auxent *)((long)s_syms + ((bss_sym+1) * SYMESZ)); */
X    if (s_bss != (struct scnhdr *)NULL)
X        s->n_value = s_text->s_size + apollo_start_size +
X            (s_data != (struct scnhdr *)NULL) ? s_data->s_size : 0 + n_patches + s_aptv->s_size;
X}   /* end of coff_patch_syms */
X
Xstatic void coff_patch_sections()
X{
X    register long fileptr;
X
X    fileptr = FILHSZ + sizeof(struct aouthdr) + (s_filehdr->f_nscns * SCNHSZ);
X
X    s_text->s_scnptr = fileptr;
X    fileptr += s_text->s_size + apollo_start_size;
X    if (s_data != (struct scnhdr *)NULL)
X    {   /* if a data section */
X        s_data->s_scnptr = fileptr;
X        fileptr += s_data->s_size + n_patches;
X    }
X    s_aptv->s_scnptr = fileptr;
X    fileptr += s_aptv->s_size;
X    s_sri->s_scnptr = fileptr;
X    fileptr += s_sri->s_size;
X    s_mir->s_scnptr = fileptr;
X    fileptr += s_mir->s_size;
X    if (n_t_reloc > 0)
X    {   /* set up text reloc */
X        s_text->s_relptr = fileptr;
X        fileptr += n_t_reloc * RELSZ;
X    }
X    if (n_d_reloc > 0)
X    {   /* set up data reloc */
X        if (s_data != (struct scnhdr *)NULL)
X        {   /* if a data section really exists */
X            s_data->s_relptr = fileptr;
X            fileptr += n_d_reloc * RELSZ;
X        }
X    }
X    if (n_a_reloc > 0)
X    {   /* set up aptv reloc */
X        s_aptv->s_relptr = fileptr;
X        fileptr += n_a_reloc * RELSZ;
X    }
X    if (n_t_lines > 0)
X    {   /* set up text lines */
X        s_text->s_nlnno = n_t_lines;
X        s_text->s_lnnoptr = fileptr;
X        fileptr += n_t_lines * LINESZ;
X    }
X
X    if (s_bss != (struct scnhdr *)NULL)
X        s_bss->s_size = ((s_bss->s_size + sizeof(long) - 1) / sizeof(long)) * sizeof(long);
X
X    /* finally, point at the symbol table */
X    s_filehdr->f_symptr = fileptr;
X    s_filehdr->f_nsyms = n_syms;
X}   /* end of coff_patch_sections */
X
Xstatic void coff_remap_file()
X{
X    register long i;
X    register struct reloc *r;
X    register struct syment *s;
X    struct lineno *lp;
X    long text,data;
X    long ptr;
X    long *word;
X
X    /* very apollo specific magic; in fact this whole function is apollo magic */
X    text = 0x8000;
X    data = text + 0x8000;
X    while ((text + s_text->s_size + apollo_start_size) > data)
X        data += 0x8000;
X
X    if (s_domainhdr->entry != 0)
X        s_domainhdr->entry += text + s_text->s_scnptr;
X    s_domainhdr->text_start = text;
X    s_domainhdr->data_start = data;
X    s_domainhdr->o_sri += text;
X
X    s_text->s_paddr = s_text->s_vaddr = text + s_text->s_scnptr;
X    ptr = data;
X    if (s_data != (struct scnhdr *)NULL)
X    {   /* if a data section */
X        s_data->s_paddr = s_data->s_vaddr = ptr;
X        ptr += s_data->s_size + n_patches;
X    }
X    s_aptv->s_paddr = s_aptv->s_vaddr = ptr;
X    ptr += s_aptv->s_size;
X    if (s_bss != (struct scnhdr *)NULL)
X    {   /* if a bss section */
X        s_bss->s_paddr = s_bss->s_vaddr = ptr;
X/*      ptr += s_bss->s_size;   */
X    }
X
X    for (i = 0; i < n_syms; i++)
X    {   /* fix the symbol table */
X        s = (struct syment *)((long)s_syms + (i * SYMESZ));
X        /* if (s->n_type != T_NULL) */ switch (s->n_scnum)
X        {   /* a symbol that needs fixing? */
X            case STEXT:
X                s->n_value += s_text->s_vaddr;
X                break;
X            case SAPTV:
X                s->n_value += s_aptv->s_vaddr;
X                break;
X            case SDATA:
X                if (s_data == (struct scnhdr *)NULL)
X                    break;
X                s->n_value += s_data->s_vaddr - s_text->s_size;
X                break;
X            case SBSS:
X#ifdef  never
X                if (s_bss == (struct scnhdr *)NULL)
X                    break;
X                s->n_value += s_bss->s_vaddr;
X#endif
X                break;
X        }
X        i += s->n_numaux;
X    }
X    s = (struct syment *)((long)s_syms + (text_sym * SYMESZ));
X    s->n_value = s_text->s_vaddr;
X    s = (struct syment *)((long)s_syms + (aptv_sym * SYMESZ));
X    s->n_value = s_aptv->s_vaddr;
X    s = (struct syment *)((long)s_syms + (data_sym * SYMESZ));
X    if (s_data != (struct scnhdr *)NULL)
X        s->n_value = s_data->s_vaddr;
X    s = (struct syment *)((long)s_syms + (bss_sym * SYMESZ));
X    if (s_bss != (struct scnhdr *)NULL)
X        s->n_value = s_bss->s_vaddr;
X
X    for (i = 0; i < n_t_reloc; i++)
X    {   /* text relocations */
X        r = (struct reloc *)((long)s_t_reloc + (i * RELSZ));
X        if (r->r_vaddr < s_text->s_size)
X            word = (long *)&text_ptr[r->r_vaddr];
X        else word = (long *)((long)apollo_start + (r->r_vaddr - s_text->s_size));
X        s = (struct syment *)((long)s_syms + (r->r_symndx * SYMESZ));
X        if (r->r_symndx == text_sym)
X            *word += s_text->s_vaddr;
X        else if (r->r_symndx == aptv_sym)
X            *word += s_aptv->s_vaddr;
X        else if (r->r_symndx == data_sym && s_data != (struct scnhdr *)NULL)
X            *word += s_data->s_vaddr - s_text->s_size;
X        else if (r->r_symndx == bss_sym && s_bss != (struct scnhdr *)NULL)
X            *word += s_bss->s_vaddr - s_text->s_size - (s_data != (struct scnhdr *)NULL ? s_data->s_size : 0);
X        else if (cplusplus_mode && r->r_symndx == cplusplus_gsym)
X            *word = s->n_value;
X        else switch (s->n_scnum)
X        {   /* fix based on type */
X            case STEXT:
X                *word += s_text->s_vaddr;
X                break;
X            case SAPTV:
X                *word += s_aptv->s_vaddr;
X                break;
X            case SDATA:
X                *word += s_data->s_vaddr - s_text->s_size;
X                break;
X            case SBSS:
X                *word += s_bss->s_vaddr - s_text->s_size - s_data->s_size;
X                break;
X        }
X        r->r_vaddr += s_text->s_vaddr;
X        if (r->r_vaddr < s_text->s_vaddr || r->r_vaddr >= (s_text->s_vaddr + s_text->s_size + apollo_start_size))
X            printf("** bad text relocation: %d: 0x%08x\n",i,r->r_vaddr);
X    }
X    for (i = 0; i < n_a_reloc; i++)
X    {   /* aptv relocations */
X        r = (struct reloc *)((long)s_a_reloc + (i * RELSZ));
X        r->r_vaddr += s_aptv->s_vaddr;
X        if (r->r_vaddr < s_aptv->s_vaddr || r->r_vaddr >= (s_aptv->s_vaddr + s_aptv->s_size))
X            printf("** bad aptv relocation: %d: 0x%08x\n",i,r->r_vaddr);
X    }
X    if (s_data != (struct scnhdr *)NULL) for (i = 0; i < n_d_reloc; i++)
X    {   /* data relocations */
X        r = (struct reloc *)((long)s_d_reloc + (i * RELSZ));
X        if (r->r_vaddr < s_data->s_size)
X            word = (long *)&data_ptr[r->r_vaddr];
X        else word = (long *)&s_patches[r->r_vaddr - s_data->s_size];
X        s = (struct syment *)((long)s_syms + (r->r_symndx * SYMESZ));
X        if (r->r_symndx == text_sym && s_text != (struct scnhdr *)NULL)
X            *word += s_text->s_vaddr;
X        else if (r->r_symndx == data_sym && s_data != (struct scnhdr *)NULL)
X            *word += s_data->s_vaddr - s_text->s_size;
X        else if (r->r_symndx == bss_sym && s_bss != (struct scnhdr *)NULL)
X            *word += s_bss->s_vaddr - s_text->s_size - (s_data != (struct scnhdr *)NULL ? s_data->s_size : 0);
X        else switch (s->n_scnum)
X        {   /* fix based on type */
X            case STEXT:
X                *word += s_text->s_vaddr;
X                break;
X            case SAPTV:
X                *word += s_aptv->s_vaddr;
X                break;
X            case SDATA:
X                *word += s_data->s_vaddr - s_text->s_size;
X                break;
X            case SBSS:
X                *word += s_bss->s_vaddr - s_text->s_size - s_data->s_size;
X                break;
X        }
X        r->r_vaddr += s_data->s_vaddr;
X        if (r->r_vaddr < s_data->s_vaddr || r->r_vaddr >= (s_data->s_vaddr + s_data->s_size + n_patches))
X            printf("** bad data relocation: %d: 0x%08x\n",i,r->r_vaddr);
X    }
X
X    for (i = 0; i < n_t_lines; i++)
X    {   /* adjust line number pointers */
X        lp = (struct lineno *)((long)s_t_lines + (i * LINESZ));
X        if (lp->l_lnno == 0)
X            continue;
X        lp->l_addr.l_paddr += s_text->s_vaddr;
X    }
X}   /* end of coff_remap_file */
X
Xvoid coff_finish()              /* finish off in-memory representation */
X{
X    long aptv_size;
X    long *word;
X    long relptr;
X
X    relptr = 0;
X    (void) coff_def_section(STEXT,relptr,s_text->s_size,n_t_reloc,0/* line numbers? */);
X    relptr += s_text->s_size;
X    if (s_data != (struct scnhdr *)NULL)
X    {   /* if a data section */
X        (void) coff_def_section(SDATA,relptr,s_data->s_size,n_d_reloc,0/* line numbers? */);
X        relptr += s_data->s_size + n_patches;
X    }
X    (void) coff_def_section(SAPTV,relptr,s_aptv->s_size,n_a_reloc,0);
X    relptr += s_aptv->s_size;
X    if (s_bss != (struct scnhdr *)NULL)
X    {   /* if a bss section */
X        (void) coff_def_section(SBSS,relptr,s_bss->s_size,0,0/* line numbers? */);
X/*      relptr += s_bss->size;  */
X    }
X#ifdef  never
X    (void) coff_def_section(SSRI,0,s_sri->s_size,0,0);
X    (void) coff_def_section(SMIR,0,s_mir->s_size,0,0);
X#endif
X
X    if (tr.r_vaddr != 0)
X        n_t_reloc++;
X    if (dr.r_vaddr != 0)
X        n_d_reloc++;
X    if (ar.r_vaddr != 0)
X        n_a_reloc++;
X    aptv_size = s_aptv->s_size;
X    if (s_aptv->s_size % sizeof(long) != 0)
X        s_aptv->s_size += sizeof(short);
X
X    if (n_t_lines == 0)
X        s_filehdr->f_flags |= F_LNNO;
X
X    /* do not change the order of the following three calls */
X    coff_patch_sections();
X    coff_patch_syms();
X    coff_patch_reloc();
X
X    s_domainhdr->tsize = s_text->s_size + apollo_start_size;
X    if (s_data != (struct scnhdr *)NULL)
X        s_domainhdr->dsize = s_data->s_size + n_patches;
X    if (s_bss != (struct scnhdr *)NULL)
X        s_domainhdr->bsize = s_bss->s_size;
X    s_domainhdr->data_start = s_domainhdr->tsize + s_aptv->s_size;
X    s_domainhdr->o_sri = s_sri->s_scnptr;
X
X    coff_remap_file();
X
X    if (tr.r_vaddr != 0)
X        n_t_reloc--;
X    if (dr.r_vaddr != 0)
X        n_d_reloc--;
X    if (ar.r_vaddr != 0)
X        n_a_reloc--;
X    s_aptv->s_size = aptv_size;
X
X    if (show_coff_code)
X    {   /* disassemble what we just built? */
X        disasm("Text section",text_ptr,s_text->s_size,s_text->s_vaddr);
X        if (apollo_start_size != 0)
X            disasm("Apollo startup code",apollo_start,apollo_start_size,s_text->s_vaddr+s_text->s_size);
X        if (n_patches > 0)
X            disasm("Data relocation patches",s_patches,n_patches,s_data->s_vaddr+s_data->s_size);
X        if (s_aptv->s_size > 0)
X            disasm("APTV section",aptv_ptr,s_aptv->s_size,s_aptv->s_vaddr);
X    }
X}   /* end of coff_finish */
X
Xvoid coff_write(file)
Xchar *file;
X{
X    char buffer[BUFSIZ];
X    register char *p;
X    FILE *fp;
X    long aptv_size;
X    short zero = 0;
X
X    p = strrchr(file,'.');
X    if (p == (char *)NULL)
X    {   /* if no dots */
X        sprintf(buffer,"%s_coff",file);
X    }
X    else
X    {   /* more complex name */
X        strncpy(buffer,file,(int)(p-file));
X        buffer[(int)(p-file)] = '\0';
X        strcat(buffer,"_coff");
X        strcat(buffer,p);
X    }
X    unlink(buffer);
X    fp = fopen(buffer,"w");
X    if (fp == (FILE *)NULL)
X    {   /* got the file? */
X        fprintf(stderr,"gnu2coff: unable to create %s\n",buffer);
X        exit(1);
X    }
X
X    aptv_size = s_aptv->s_size;
X    if (s_aptv->s_size % sizeof(long) != 0)
X        s_aptv->s_size += sizeof(short);
X    s_text->s_size += apollo_start_size;
X    if (s_data != (struct scnhdr *)NULL)
X        s_data->s_size += n_patches;
X
X    fwrite(s_filehdr,FILHSZ,1,fp);
X    fwrite(s_domainhdr,sizeof (struct aouthdr),1,fp);
X    fwrite(s_text,SCNHSZ,1,fp);
X    if (s_data != (struct scnhdr *)NULL)
X        fwrite(s_data,SCNHSZ,1,fp);
X    fwrite(s_aptv,SCNHSZ,1,fp);
X    if (s_bss != (struct scnhdr *)NULL)
X        fwrite(s_bss,SCNHSZ,1,fp);
X    fwrite(s_sri,SCNHSZ,1,fp);
X    fwrite(s_mir,SCNHSZ,1,fp);
X    if (s_domainhdr->tsize-apollo_start_size != 0)
X        fwrite(text_ptr,s_domainhdr->tsize-apollo_start_size,1,fp);
X    if (apollo_start_size != 0)
X        fwrite(apollo_start,apollo_start_size,1,fp);
X    if (s_domainhdr->dsize-n_patches != 0)
X        fwrite(data_ptr,s_domainhdr->dsize-n_patches,1,fp);
X    if (n_patches != 0)
X        fwrite(s_patches,n_patches,1,fp);
X    if (aptv_ptr != (char *)NULL)
X        fwrite(aptv_ptr,aptv_size,1,fp);
X    if (aptv_size != s_aptv->s_size)
X        fwrite(&zero,sizeof(short),1,fp);
X    fwrite(sri_recs,s_sri->s_size,1,fp);
X    fwrite(mir_recs,s_mir->s_size,1,fp);
X    if (tr.r_vaddr != 0)
X        fwrite(&tr,RELSZ,1,fp);
X    if (n_t_reloc != 0)
X        fwrite(s_t_reloc,RELSZ,n_t_reloc,fp);
X    if (dr.r_vaddr != 0)
X        fwrite(&dr,RELSZ,1,fp);
X    if (n_d_reloc != 0)
X        fwrite(s_d_reloc,RELSZ,n_d_reloc,fp);
X    if (ar.r_vaddr != 0)
X        fwrite(&ar,RELSZ,1,fp);
X    if (n_a_reloc != 0)
X        fwrite(s_a_reloc,RELSZ,n_a_reloc,fp);
X    if (n_t_lines != 0)
X        fwrite(s_t_lines,LINESZ,n_t_lines,fp);
X    fwrite(s_syms,SYMESZ,n_syms,fp);
X    n_string += sizeof n_string;
X    fwrite(&n_string,sizeof n_string,1,fp);
X    n_string -= sizeof n_string;
X    fwrite(s_string,1,n_string,fp);
X
X    fclose(fp);
X    s_aptv->s_size = aptv_size;
X    s_text->s_size -= apollo_start_size;
X    if (s_data != (struct scnhdr *)NULL)
X        s_data->s_size -= n_patches;
X}   /* end of coff_write */
X
Xchar *coff_findsym(vaddr)
Xlong vaddr;
X{
X    register long i;
X    register struct syment *s;
X
X    if ((struct syment *)s_syms == (struct syment *)NULL)
X        return (char *)NULL;
X
X    for (i = 0; i < n_syms; i++)
X    {   /* fix the symbol table */
X        s = (struct syment *)((long)s_syms + (i * SYMESZ));
X        if (s->n_value == vaddr)
X        {   /* if found the symbol */
X            if (s->n_zeroes != 0)
X                return s->n_name;
X            else
X                return &s_string[s->n_offset - sizeof n_string];
X        }
X        i += s->n_numaux;
X    }
X    return (char *)NULL;
X}   /* end of coff_findsym */
X
Xchar *coff_findsym_reloc(vaddr,value)
Xlong vaddr;
Xlong *value;
X{
X    register long i;
X    register struct syment *s;
X    register struct reloc *r;
X
X    if ((struct syment *)s_syms == (struct syment *)NULL)
X        return (char *)NULL;
X
X    for (i = 0; i < n_t_reloc; i++)
X    {   /* text relocations */
X        r = (struct reloc *)((long)s_t_reloc + (i * RELSZ));
X        if (r->r_vaddr == vaddr)
X        {   /* if have sym */
X            s = (struct syment *)((long)s_syms + (r->r_symndx * SYMESZ));
X            *value = s->n_value;
X            if (s->n_zeroes != 0)
X                return s->n_name;
X            else
X                return &s_string[s->n_offset - sizeof n_string];
X        }
X    }
X    for (i = 0; i < n_d_reloc; i++)
X    {   /* data relocations */
X        r = (struct reloc *)((long)s_d_reloc + (i * RELSZ));
X        if (r->r_vaddr == vaddr)
X        {   /* if have sym */
X            s = (struct syment *)((long)s_syms + (r->r_symndx * SYMESZ));
X            *value = s->n_value;
X            if (s->n_zeroes != 0)
X                return s->n_name;
X            else
X                return &s_string[s->n_offset - sizeof n_string];
X        }
X    }
X    for (i = 0; i < n_a_reloc; i++)
X    {   /* aptv relocations */
X        r = (struct reloc *)((long)s_a_reloc + (i * RELSZ));
X        if (r->r_vaddr == vaddr)
X        {   /* if have sym */
X            s = (struct syment *)((long)s_syms + (r->r_symndx * SYMESZ));
X            *value = s->n_value;
X            if (s->n_zeroes != 0)
X                return s->n_name;
X            else
X                return &s_string[s->n_offset - sizeof n_string];
X        }
X    }
X    return (char *)NULL;
X}   /* end of coff_findsym_reloc */
END_OF_FILE
if test 53153 -ne `wc -c <'coff.c'`; then
    echo shar: \"'coff.c'\" unpacked with wrong size!
fi
chmod +x 'coff.c'
# end of 'coff.c'
fi
echo shar: End of archive 4 \(of 4\).
cp /dev/null ark4isdone
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