* DEBUG: for debugging purposes only
* TMPDIR: directory for temporary files
* ASLD: combined assembler/linker
- * AOUTSEEK: seek on a.out instead of multiple opens
*/
/* ========== constants (use #undef, #define in mach0.c) ========== */
/* ========== default option setting ========== */
-#ifndef NOLD
-#define ASLD /* default ON */
-#endif
-
#ifndef ASLD
#ifndef RELOCATION
separate linker only possible if relocation info produced
#endif
#ifdef ASLD
-#include "aar.h"
+#include "arch.h"
#endif
#include "out.h"
/* miscellaneous */
#define KEYDEFINE 0
+#define KEYSECT 12
#define DOTGAIN DOTSCT->s_gain
/* ========== type declarations ========== */
char *i_name; /* symbol name */
};
+struct common_t {
+ struct common_t *
+ c_next;
+ struct item_t *c_it;
+#ifndef ASLD
+ valu_t c_size;
+#endif
+};
+
+typedef struct common_t common_t;
+
typedef struct item_t item_t;
struct sect_t {
/*
* extra type bits out of S_ETC, internal use only
-#ifndef DUK
- * S_COM:
- * - symbols declared by .comm
-#endif DUK
* S_VAR:
* - type not known at end of PASS_1 (S_VAR|S_UND)
* - value not known at end of PASS_2 (S_VAR|S_ABS)
* S_DOT:
* - dot expression
*/
-#ifndef DUK
-#define S_COM 0x0100
-#endif DUK
#define S_VAR 0x0200
#define S_DOT 0x0400
/* should be tested by preprocessor
* due to error in preprocessor it cannot
- * test performed at runtime now
+ * test performed at compiletime by a switch now
* #if (S_ETC|S_COM|S_VAR|S_DOT) != S_ETC
* incorrect type bits
* #endif
#define PARTCHAR 3
#define PARTS 4
-#ifdef AOUTSEEK
-#define AOUTPART(p) if(aoutpart!=p){aoutpart=p;fseek(aoutfile,aoutseek[p],0);}
-#define AOUTPUTC(c,p) {putc(c,aoutfile);aoutseek[p]++;if(ferror(aoutfile))werror();}
+#ifdef BYTES_REVERSED
+#ifdef WORDS_REVERSED
+#define MACHREL_BWR (RELBR|RELWR)
+#else
+#define MACHREL_BWR (RELBR)
+#endif
#else
-#define AOUTPART(p) /* empty */
-#define AOUTPUTC(c,p) {putc(c,aoutfile[p]);if(ferror(aoutfile[p]))werror();}
+#ifdef WORDS_REVERSED
+#define MACHREL_BWR (RELWR)
+#else
+#define MACHREL_BWR (0)
+#endif
#endif
/* -s option (symbol table info) */
extern char *progname; /* for error messages */
extern char *modulename; /* for error messages */
+extern common_t *commons; /* header of commons list */
#ifdef ASLD
extern short archmode; /* scanning archives */
extern FILE *input;
extern FILE *tempfile;
-#ifdef AOUTSEEK
-extern FILE *aoutfile;
-extern int aoutpart INIT(-1);
-extern long aoutseek[PARTS];
-#else
-extern FILE *aoutfile[PARTS];
-#endif
-
extern char stringbuf[STRINGMAX];
/* contains last string value */
extern addr_t DOTVAL; /* DOTSCT->s_size + DOTSCT->s_base */
extern short DOTTYP; /* S_MIN..S_MAX or S_UND */
+extern ushort nname; /* Counts name table index in PASS_3 */
+
extern item_t *hashtab[H_TOTAL];
extern short hashindex; /* see item_search() */
{
#ifdef RELOCATION
if (rflag != 0 && PASS_RELO)
-#ifdef DUK
-#ifdef BYTES_REVERSED
-#ifdef WORDS_REVERSED
- newrelo($1.typ,
- (int)$<y_word>0 | RELBR | RELWR
- );
-#else WORDS_REVERSED
- newrelo($1.typ, (int)$<y_word>0|RELBR);
-#endif WORDS_REVERSED
-#else BYTES_REVERSED
-#ifdef WORDS_REVERSED
- newrelo($1.typ, (int)$<y_word>0|RELWR);
-#else WORDS_REVERSED
- newrelo($1.typ, (int)$<y_word>0);
-#endif WORDS_REVERSED
-#endif BYTES_REVERSED
-#else DUK
- newrelo($1.typ, (int)$<y_word>0);
-#endif DUK
+ newrelo($1.typ, (int)$<y_word>0|MACHREL_BWR);
#endif
emitx($1.val, (int)$<y_word>0);
}
{
#ifdef RELOCATION
if (rflag != 0 && PASS_RELO)
-#ifdef DUK
-#ifdef BYTES_REVERSED
-#ifdef WORDS_REVERSED
- newrelo($3.typ,
- (int)$<y_word>0 | RELBR | RELWR
- );
-#else WORDS_REVERSED
- newrelo($3.typ, (int)$<y_word>0|RELBR);
-#endif WORDS_REVERSED
-#else BYTES_REVERSED
-#ifdef WORDS_REVERSED
- newrelo($3.typ, (int)$<y_word>0|RELWR);
-#else WORDS_REVERSED
- newrelo($3.typ, (int)$<y_word>0);
-#endif WORDS_REVERSED
-#endif BYTES_REVERSED
-#else DUK
- newrelo($3.typ, (int)$<y_word>0);
-#endif DUK
+ newrelo($3.typ, (int)$<y_word>0|MACHREL_BWR);
#endif
emitx($3.val, (int)$<y_word>0);
}
#include "comm1.h"
+#undef extern
+
struct outhead outhead = {
O_MAGIC, O_STAMP, 0
-#ifndef DUK
-#ifdef BYTES_REVERSED
- | HF_BREV
-#endif
-#ifdef WORDS_REVERSED
- | HF_WREV
-#endif
-#endif DUK
};
#include "y.tab.h"
SIGHUP, SIGINT, SIGQUIT, SIGTERM, 0
};
- /* this test should be performed by the
- * preprocessor, but it cannot
+ /* the next test should be performed by the
+ * preprocessor, but it cannot, so it is performed by the compiler.
*/
- if ((S_ETC|S_COM|S_VAR|S_DOT) != S_ETC)
- fatal("incorrect type bits");
+
+ switch(0) {
+ case 1: break;
+ case (S_ETC|S_COM|S_VAR|S_DOT) != S_ETC : break;
+ }
progname = *argv++; argc--;
for (p = sigs; i = *p++; )
pass_23(PASS_2);
#endif
pass_23(PASS_3);
+ wr_close();
stop();
}
pass_1(argc, argv)
char **argv;
{
- register i;
register char *p;
register item_t *ip;
#ifdef ASLD
- char armagic[SZMAGIC];
+ char armagic[2];
#else
register nfile = 0;
#endif
p = *argv++;
if (p == 0)
continue;
-#ifdef ASLD
+#ifndef ASLD
+ if (nfile != 0)
+ fatal("second source file %s", p);
+ nfile++;
+#endif
if (p[0] == '-' && p[1] == '\0') {
input = stdin;
parse("STDIN");
continue;
}
-#else
- if (nfile != 0)
- fatal("second source file %s", p);
- nfile++;
-#endif
+
if ((input = fopen(p, "r")) == NULL)
fatal("can't open %s", p);
#ifdef ASLD
if (
- fread(armagic, SZMAGIC, 1, input) == 1
+ fread(armagic, 2, 1, input) == 1
&&
- strncmp(armagic, ARMAGIC, SZMAGIC) == 0
+ ((armagic[0]&0377) |
+ ((unsigned)(armagic[1]&0377)<<8)) == ARMAG
) {
archive();
fclose(input);
machfinish(PASS_1);
#ifdef ASLD
if (unresolved) {
+ register int i;
+
nerrors++;
fflush(stdout);
fprintf(stderr, "unresolved references:\n");
}
#ifdef ASLD
-archive()
-{
+archive() {
register long offset;
- register i;
- register long modsize;
- char modhead[SZMHEAD];
+ struct ar_hdr header;
+ char getsize[AR_TOTAL];
archmode++;
- offset = SZMAGIC;
+ offset = 2;
for (;;) {
if (unresolved == 0)
break;
- fseek(input, offset, 0);
- if (fread(modhead, SZMHEAD, 1, input) != 1)
+ fseek(input,offset,0);
+ if (fread(getsize,AR_TOTAL,1,input) != 1)
break;
- if (
- strncmp(&modhead[OFF_BEG], STR_BEG, LEN_BEG)
- ||
- strncmp(&modhead[OFF_END], STR_END, LEN_END)
- )
- fatal("bad archive");
- offset += SZMHEAD;
- modsize = atol(&modhead[OFF_SIZ]);
- archsize = modsize;
+ offset += AR_TOTAL;
+ strncpy(header.ar_name,getsize,sizeof header.ar_name) ;
+ header.ar_size= (((((long) (getsize[AR_SIZE+1]&0377))<<8)+
+ ((long) (getsize[AR_SIZE ]&0377))<<8)+
+ ((long) (getsize[AR_SIZE+3]&0377))<<8)+
+ ((long) (getsize[AR_SIZE+2]&0377)) ;
+ archsize = header.ar_size;
if (needed()) {
- fseek(input, offset, 0);
- archsize = modsize;
- for (i = 0; i < LEN_NAM; i++)
- if (modhead[OFF_NAM+i] == ' ')
- break;
- modhead[OFF_NAM+i] = '\0';
- parse(remember(&modhead[OFF_NAM]));
+ fseek(input,offset,0);
+ archsize = header.ar_size;
+ header.ar_name[14] = '\0';
+ parse(remember(header.ar_name));
}
- offset += modsize;
+ offset += header.ar_size;
+ while (offset % 2)
+ offset++;
}
archmode = 0;
}
continue;
}
if (first) {
+ if (ip == &keytab[KEYSECT]) {
+ while ((c = nextchar()) != '\n')
+ ;
+ continue;
+ }
+
if (ip != &keytab[KEYDEFINE])
break;
first = 0;
register sect_t *sp;
register long off;
struct outsect outsect;
+ register struct outsect *pos = &outsect;
-#ifdef AOUTSEEK
-#define AOUTseek(p,o) {aoutseek[p]=o;}
- aoutfile = ffcreat(aoutpath);
-#else
-#define AOUTseek(p,o) {fseek(aoutfile[p],o,0);}
- aoutfile[PARTEMIT]=ffcreat(aoutpath);
-#ifdef RELOCATION
- aoutfile[PARTRELO]=ffcreat(aoutpath);
-#endif
- aoutfile[PARTNAME]=ffcreat(aoutpath);
- aoutfile[PARTCHAR]=ffcreat(aoutpath);
-#endif
- /*
- * header generation
- */
- AOUTseek(PARTEMIT, 0);
- putofmt((char *)&outhead, SF_HEAD, PARTEMIT);
+ if (! wr_open(aoutpath)) {
+ fatal("can't create %s", aoutpath);
+ }
+ wr_ohead(&outhead);
/*
* section table generation
*/
off += (long)outhead.oh_nsect * SZ_SECT;
for (sp = sect; sp < §[outhead.oh_nsect]; sp++) {
sp->s_foff = off;
- outsect.os_base = SETBASE(sp);
- outsect.os_size = sp->s_size + sp->s_comm;
- outsect.os_foff = sp->s_foff;
- outsect.os_flen = sp->s_size - sp->s_zero;
- outsect.os_lign = sp->s_lign;
- off += outsect.os_flen;
- putofmt((char *)&outsect, SF_SECT, PARTEMIT);
+ pos->os_base = SETBASE(sp);
+ pos->os_size = sp->s_size + sp->s_comm;
+ pos->os_foff = sp->s_foff;
+ pos->os_flen = sp->s_size - sp->s_zero;
+ pos->os_lign = sp->s_lign;
+ off += pos->os_flen;
+ wr_sect(pos, 1);
}
#ifdef RELOCATION
- AOUTseek(PARTRELO, off);
off += (long)outhead.oh_nrelo * SZ_RELO;
#endif
if (sflag == 0)
return;
- AOUTseek(PARTNAME, off);
off += (long)outhead.oh_nname * SZ_NAME;
- AOUTseek(PARTCHAR, off);
outhead.oh_nchar = off; /* see newsymb() */
-#undef AOUTseek
}
commfinish()
{
- register i;
+#ifndef ASLD
+ register int i;
+#endif
+ register struct common_t *cp;
register item_t *ip;
register sect_t *sp;
register valu_t addr;
switchsect(S_UND);
-#ifdef ASLD
/*
* assign .comm labels and produce .comm symbol table entries
*/
- for (i = 0; i<H_SIZE; i++)
- for (ip = hashtab[H_GLOBAL+i]; ip; ip = ip->i_next) {
- if ((ip->i_type & S_COM) == 0)
- continue;
+ for (cp = commons; cp; cp = cp->c_next) {
+ ip = cp->c_it;
+#ifndef ASLD
+ if (!( ip->i_type & S_EXT)) {
+#endif
sp = §[(ip->i_type & S_TYP) - S_MIN];
if (pass == PASS_1) {
addr = sp->s_size + sp->s_comm;
sp->s_comm += ip->i_valu;
ip->i_valu = addr;
+#ifndef ASLD
+ ip->i_type &= ~S_COM;
+#endif
}
+#ifdef ASLD
#ifdef THREE_PASS
- if (pass == PASS_2)
+ if (pass == PASS_2) {
ip->i_valu -= sp->s_gain;
+ }
#endif
if ((sflag & SYM_EXT) && PASS_SYMB)
newsymb(
(short)0,
load(ip)
);
+#else not ASLD
+#ifdef THREE_PASS
+ if (pass == PASS_2) {
+ cp->c_size -= sp->s_gain;
+ }
+#endif THREE_PASS
}
-#endif
+ if (pass == PASS_1) cp->c_size = ip->i_valu;
+ if (PASS_SYMB) {
+ if (pass != PASS_3 && (ip->i_type & S_EXT)) {
+ ip->i_valu = outhead.oh_nname;
+ }
+ newsymb(
+ ip->i_name,
+ ip->i_type,
+ (short) 0,
+ cp->c_size
+ );
+ }
+#endif not ASLD
+ }
if (PASS_SYMB == 0)
return;
#ifndef ASLD
* for possible relocation
*/
ip->i_valu = outhead.oh_nname;
- if (sflag & SYM_SCT)
- newsymb(
- ip->i_name,
- S_EXT|S_UND,
- (short)0,
- (valu_t)0
- );
+ newsymb(
+ ip->i_name,
+ S_EXT|S_UND,
+ (short)0,
+ (valu_t)0
+ );
}
-#endif ASLD
+#endif not ASLD
/*
* produce symbol table entries for sections
*/
#endif
case STRING:
p = stringbuf;
-#ifdef DUK
- *p++ = n = getc(tempfile);
- p[n] = '\0';
- break;
-#else DUK
- *p++ = n = getc(tempfile); break;
-#endif DUK
+ *p++ = n = getc(tempfile); p[n] = '\0'; break;
case OP_EQ:
case OP_NE:
case OP_LE:
break;
if (c == '\\')
c = inescape();
-#ifdef DUK
if (p >= &stringbuf[STRINGMAX - 1])
-#else DUK
- if (p >= &stringbuf[STRINGMAX])
-#endif DUK
fatal("string buffer overflow");
*p++ = c;
}
stringbuf[0] = p - stringbuf - 1;
-#ifdef DUK
*p = '\0';
-#endif DUK
return(STRING);
}
sp = §[typ - S_MIN];
sp->s_item = ip;
sp->s_lign = ALIGNSECT;
-#ifdef DUK
+#ifndef ASLD
ip->i_type = typ;
-#else DUK
+#else
ip->i_type = typ | S_EXT;
-#endif DUK
+#endif
ip->i_valu = 0;
} else if (typ >= S_MIN) {
sp = §[typ - S_MIN];
}
/*
- * NOTE: A rather different solution is used for ASLD and NOLD:
- * ASLD:
+ * NOTE: A rather different solution is used for ASLD and not ASLD:
+ * ASLD, or local commons:
* - maximum length of .comm is recorded in i_valu during PASS_1
* - address of .comm is recorded in i_valu in later passes:
* assigned at end of PASS_1, corrected for s_gain at end of PASS_2
- * - symbol table entries are produced in commfinish()
- * NOLD:
- * - i_valu cannot be used since it is needed for relocation info
- * - only one .comm with a particular symbol is allowed per module
- * - symbol table entries are produced in newcomm()
+ * not ASLD:
+ * - maximum length of .comm is recorded in i_valu during PASS_1
+ * - i_valu is used for relocation info during PASS_3
*/
newcomm(ip, val)
register item_t *ip;
/* printf("declare %s: %o\n", ip->i_name, DOTTYP); */
if ((ip->i_type & ~S_EXT) == S_UND) {
--unresolved;
- ip->i_type = S_COM|S_EXT|DOTTYP;
-#ifdef ASLD
+ ip->i_type = S_COM|DOTTYP|(ip->i_type&S_EXT);
ip->i_valu = val;
- } else if (ip->i_type == (S_COM|S_EXT|DOTTYP)) {
+ new_common(ip);
+ } else if (ip->i_type == (S_COM|DOTTYP|(ip->i_type&S_EXT))) {
if (ip->i_valu < val)
ip->i_valu = val;
-#endif
} else
serror("multiple declared");
}
-#ifndef ASLD
- if (PASS_SYMB == 0)
- return;
- if (pass != PASS_3)
- /*
- * save symbol table index
- * for possible relocation
- */
- ip->i_valu = outhead.oh_nname;
-#ifdef DUK
- newsymb(ip->i_name, S_COM|S_EXT|DOTTYP, (short)0, val);
-#else DUK
- newsymb(ip->i_name, S_EXT|DOTTYP, (short)0, val);
-#endif DUK
-#endif
}
switchsect(newtyp)
assert(newtyp >= S_MIN);
sp = §[newtyp - S_MIN];
if (pass == PASS_3) {
-#ifdef AOUTSEEK
- aoutpart = -1;
- aoutseek[PARTEMIT] = sp->s_foff + sp->s_size - sp->s_zero;
-#else
- fseek(aoutfile[PARTEMIT], sp->s_foff + sp->s_size - sp->s_zero, 0);
-#endif
+ wr_outsect(newtyp - S_MIN);
}
DOTVAL = sp->s_size + sp->s_base;
DOTSCT = sp;
DOTGAIN += (bytes - 1) - gap;
#endif
}
- /* I don't play the os_zero game here, but plainly write out zero's */
- /* Led abuses trailing zero parts */
- while (gap--) emit1(0) ;
+ DOTVAL += gap;
+ sp->s_zero += gap;
}
#ifdef RELOCATION
short s;
{
struct outrelo outrelo;
-#ifdef DUK
int iscomm;
-#endif DUK
if (rflag == 0)
return;
* b=a
* a: .data2 0
*/
-#ifdef DUK
iscomm = s & S_COM;
-#endif DUK
s &= ~S_COM;
if ((n & RELPC) == 0 && s == S_ABS)
return;
outrelo.or_type = (char)n;
outrelo.or_sect = (char)DOTTYP;
#ifndef ASLD
-#ifdef DUK
if (s == S_UND || iscomm) {
-#else DUK
- if (s == S_UND) {
-#endif DUK
assert(relonami != 0);
outrelo.or_nami = relonami-1;
relonami = 0;
;
}
outrelo.or_addr = (long)DOTVAL;
- putofmt((char *)&outrelo, SF_RELO, PARTRELO);
+ wr_relo(&outrelo, 1);
}
#endif
outhead.oh_nname++;
return;
}
+ nname++;
if (name) {
- AOUTPART(PARTCHAR);
+ int len = strlen(name) + 1;
+
+ wr_string(name, len);
outname.on_foff = outhead.oh_nchar;
- do {
- AOUTPUTC(*name, PARTCHAR);
- outhead.oh_nchar++;
- } while (*name++);
+ outhead.oh_nchar += len;
} else
outname.on_foff = 0;
outname.on_type = type;
outname.on_desc = desc;
outname.on_valu = valu & ~((0xFFFFFFFF)<<(8*sizeof(valu_t)));
- putofmt((char *)&outname, SF_NAME, PARTNAME);
+ wr_name(&outname, 1);
+}
+
+new_common(ip)
+ item_t *ip;
+{
+ register struct common_t *cp;
+ static nleft = 0;
+ static struct common_t *next;
+
+ if (--nleft < 0) {
+ next = (struct common_t *) sbrk(MEMINCR);
+ if ((int) next == -1) {
+ fatal("out of memory");
+ }
+ nleft += (MEMINCR / sizeof (struct common_t));
+ }
+ cp = next++;
+ cp->c_next = commons;
+ cp->c_it = ip;
+ commons = cp;
}
return(ip->i_valu);
return(ip->i_valu + sect[typ].s_base);
#else
-#ifdef DUK
if ((ip->i_type & S_TYP) == S_UND || (ip->i_type & S_COM)) {
-#else DUK
- if ((ip->i_type & S_TYP) == S_UND) {
-#endif DUK
if (pass == PASS_3) {
if (relonami != 0)
serror("relocation error");
assert(fitsmall || (*p & bit) == 0);
return(*p & bit);
}
+ /*NOTREACHED*/
}
#endif
DOTSCT->s_zero = 0;
break;
case PASS_3:
- AOUTPART(PARTEMIT);
+ wr_outsect(DOTTYP-S_MIN);
while (DOTSCT->s_zero) {
- AOUTPUTC(0, PARTEMIT);
+ wr_putc(0);
DOTSCT->s_zero--;
}
- AOUTPUTC(arg, PARTEMIT);
+ wr_putc(arg);
break;
}
DOTVAL++;
emitx(val, n)
valu_t val;
-register n;
+int n;
{
switch (n) {
case 1:
FILE *
fftemp(path, tail)
-char *path;
+char *path, *tail;
{
register char *dir;
return(ffcreat(mktemp(path)));
}
-putofmt(p, s, part)
-register char *p;
-register char *s;
-{
- register i;
- register long l;
-
- AOUTPART(part);
- while (i = *s++) {
- switch (i -= '0') {
-/* case 0: p++; break; */
- case 1:
- l = (long) *((char *)p); p += sizeof(char );
- break;
- case 2:
- l = (long) *((short *)p); p += sizeof(short);
- break;
- case 4:
- l = (long) *((long *)p); p += sizeof(long );
- break;
- default:
- assert(0);
- }
- while (--i >= 0) {
- AOUTPUTC((int)l, part);
- l >>= 8;
- }
- }
-}
-
/* ---------- Error handling ---------- */
yyerror(){} /* we will do our own error printing */
fatal("no sections");
}
-werror()
+wr_fatal()
{
fatal("write error");
}