home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
213a.lha
/
Sozobon-C
/
ld
/
p1.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-02-14
|
6KB
|
429 lines
/* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg
*
* Permission is granted to anyone to use this software for any purpose
* on any computer system, and to redistribute it freely, with the
* following restrictions:
* 1) No charge may be made other than reasonable charges for reproduction.
* 2) Modified versions must be clearly marked as such.
* 3) The authors are not responsible for any harmful consequences
* of using this software, even if they result from defects in it.
*/
#include <stdio.h>
#include "ld.h"
extern int vflag, multipass, bflag;
char *myalloc();
struct sinfo *lookup();
int ifd;
pass0(s)
char *s;
{
register struct finfo *fp;
if (nfiles >= MAXFI) {
fprintf(stderr, "Too many files\n");
exit(1);
}
fp = &files[nfiles++];
fp->fname = s;
fp->fd = OPENBR(s);
if (fp->fd < 0) {
fprintf(stderr, "Cant open %s\n", s);
exit(1);
}
}
fpass1(fname)
char *fname;
{
char buf[81], *s, *savestr();
FILE *ffd;
ffd = fopen(fname, "r");
if (ffd == NULL) {
fprintf(stderr, "Cant open %s\n", fname);
exit(1);
}
while (fscanf(ffd, "%80s", buf) == 1) {
s = savestr(buf);
pass0(s);
}
}
pass1(fn)
{
register struct finfo *fp;
int i, n, nlost;
fp = &files[fn];
if (vflag)
printf("%s:\n", fp->fname);
ifd = fp->fd;
read(ifd, &i, sizeof(int));
if (i == OMAGIC)
doobj(fn);
else if (i == AMAGIC)
doarch(fn);
else {
fprintf(stderr,"File '%s' not a valid object file or library\n",
fp->fname);
exit(1);
}
}
doarch(fn)
{
struct arch a;
int i;
long astart, ostart, tell();
nskip = 0;
more:
i = read(ifd, &a, sizeof(a));
if (i != sizeof(a) || a.anm[0] == 0)
goto out;
ostart = tell(ifd);
astart = ostart + a.asize;
doaobj(ostart, fn, a.anm);
lseek(ifd, astart, 0);
goto more;
out:
if (multipass)
m_redo(fn);
}
doobj(fn)
{
int i;
i = read(ifd, (char *)&h + 2, sizeof(h)-2);
if (i != sizeof(h)-2) {
fprintf(stderr, "File '%s' not a valid object file\n",
files[fn].fname);
return;
}
doreally(&h, fn, NULL, NULL);
}
doreally(hp, fn, aname, sptr)
struct hdr *hp;
char *aname, *sptr;
{
register struct oinfo *p;
char *iptr;
long n, tell();
if (nobj >= MAXOBJ) {
fprintf(stderr, "Obj table overflow\n");
exit(1);
}
p = &obj[nobj];
p->fno = fn;
if (aname) {
strncpy(p->aname, aname, 14);
if (vflag)
printf("(%.14s)\n", aname);
}
p->oh = *hp;
p->tbase = textsize;
p->dbase = datasize;
p->bbase = bsssize;
n = hp->tsize+hp->dsize;
if (bflag) {
p->im_td = tell(ifd);
lseek(ifd, n, 1);
} else {
p->im_td = (long)myalloc(n);
lread(ifd, p->im_td, n);
}
if (sptr) {
lseek(ifd, hp->syms, 1);
} else {
sptr = myalloc(hp->syms);
lread(ifd, sptr, hp->syms);
}
p->im_sym = sptr;
if (bflag) {
p->im_rel = tell(ifd);
} else {
p->im_rel = (long)myalloc(n);
lread(ifd, p->im_rel, n);
}
textsize += hp->tsize;
datasize += hp->dsize;
bsssize += hp->bsize;
symabs(sptr);
n = hp->syms/sizeof(struct sym);
while (n--)
p1sym();
nobj++;
return 1;
}
doaobj(offs, fn, aname)
long offs;
char *aname;
{
long n;
int i;
char *iptr;
lseek(ifd, offs, 0);
i = read(ifd, &h, sizeof(h));
if (i != sizeof(h) || h.magic != OMAGIC) {
fprintf(stderr,
"Member '%s' of library '%s' not a valid object file\n",
aname, files[fn].fname);
return;
}
n = h.syms;
lseek(ifd, h.tsize+h.dsize, 1);
iptr = myalloc(n);
lread(ifd, iptr, n);
symabs(iptr);
if (norefs(h.syms)) {
if (multipass)
m_save(iptr, aname, offs);
else
free(iptr);
return;
} else {
lseek(ifd, offs + sizeof(h), 0);
}
doreally(&h, fn, aname, iptr);
}
m_save(iptr, aname, offs)
char *iptr;
char *aname;
long offs;
{
register struct skipstr *p;
if (nskip >= MAXLIB) {
fprintf(stderr, "Skip table overflow\n");
exit(1);
}
p = &skip[nskip];
strncpy(p->aname, aname, 14);
p->oh = h;
p->ims = iptr;
p->offs = offs;
nskip++;
}
m_redo(fn)
{
register struct skipstr *p;
int rescan, i;
if (vflag)
printf("Re-scan %s:\n", files[fn].fname);
/* if need skipped objs
doreally()
p->ims = NULL
rescan++
*/
again:
rescan = 0;
p = skip;
for (i=0; i<nskip; i++,p++) {
if (p->ims == 0)
continue;
symabs(p->ims);
if (norefs(p->oh.syms) == 0) {
lseek(ifd, p->offs + sizeof(h), 0);
doreally(&p->oh, fn, p->aname, p->ims);
p->ims = 0;
rescan++;
}
}
if (rescan)
goto again;
frees:
p = skip;
while (nskip--) {
if (p->ims)
free(p->ims);
p++;
}
}
norefs(sy)
long sy;
{
long n, ftell();
n = sy/sizeof(struct sym);
while (n--)
if (p1need())
return 0;
return 1;
}
p1sym()
{
struct sym s;
int i;
i = symread(&s);
if (i != 1)
return;
if (not_glob(s.flags))
return;
addsym(&s);
}
addsym(s)
struct sym *s;
{
register struct sinfo *sp;
if (oldsym(s))
return;
if (nsym >= MAXSYM) {
fprintf(stderr, "Sym table overflow\n");
exit(1);
}
sp = &sym[nsym];
sp->onum = nobj;
sp->sy = *s;
hashins(sp);
nsym++;
}
struct sym zsym;
undef(name)
char *name;
{
struct sym s;
int sv;
sv = nobj;
nobj = -1;
s = zsym;
strncpy(s.name, name, 8);
s.flags = 0x88;
s.value = 0;
addsym(&s);
nobj = sv;
}
p1need()
{
struct sym s;
int i;
i = symread(&s);
if (i != 1)
return 0;
if (not_glob(s.flags))
return 0;
if (needsym(&s))
return 1;
return 0;
}
needsym(sp)
struct sym *sp;
{
struct sinfo *ip;
int ofl, nfl;
nfl = sp->flags & 0xff;
if (nfl == 0x88 || nfl == 0xa8)
return 0;
ip = lookup(sp->name);
if (ip == NULL)
return 0;
ofl = ip->sy.flags & 0xff;
if (ofl == 0x88) {
if (vflag > 1)
printf("Needed %.8s\n", sp->name);
return 1;
}
return 0;
}
oldsym(sp)
struct sym *sp;
{
struct sinfo *ip;
int ofl, nfl;
ip = lookup(sp->name);
if (ip == NULL)
return 0;
ofl = ip->sy.flags & 0xff;
nfl = sp->flags & 0xff;
if (ofl == 0x88) {
ip->sy = *sp;
ip->onum = nobj;
} else if (nfl == 0x88) {
;
} else if (ofl == 0xa8 && nfl == 0xa8) {
if (ip->sy.value != sp->value) {
fprintf(stderr, "Common sizes differ %.8s %ld %ld\n",
ip->sy.name,
ip->sy.value, sp->value);
if (sp->value > ip->sy.value)
ip->sy.value = sp->value;
}
} else
fprintf(stderr, "Double def of %.8s %x %x\n", sp->name,
ofl, nfl);
return 1;
}
not_glob(x)
{
x &= 0xff;
if (x & 0x20)
return 0;
if (x == 0x88)
return 0;
return 1;
}