ack/mach/proto/as/comm4.c
George Koehler 36f16b0cb8 Cut down some clang warnings
Edit C code to reduce warnings from clang.  Most warnings are for
implicit declarations of functions, but some warnings want me to add
parentheses or curly braces, or to cast arguments for printf().

Make a few other changes, like declaring float_cst() in h/con_float to
be static, and using C99 bool in ego/ra/makeitems.c and
ego/share/makecldef.c.  Such changes don't silence warnings; I make
such changes while I silence warnings in the same file.  In
float_cst(), rename parameter `str` to `float_str`, so it doesn't
share a name with the global variable `str`.

Remove `const` from `newmodule(const char *)` in mach/proto/as to
silence a warning.  I wrongly added the `const` in d347207.

For warnings about implicit declarations of functions, the fix is to
declare the function before calling it.  For example, my OpenBSD
system needs <sys/wait.h> to declare wait().

In util/int, add "whatever.h" to declare more functions.  Remove old
declarations from "mem.h", to prefer the newer declarations of the
same functions in "data.h" and "stack.h".
2019-10-30 18:36:38 -04:00

604 lines
11 KiB
C

/* $Id$ */
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
/* @(#)comm4.c 1.6 */
/*
* Micro processor assembler framework written by
* Johan Stevenson, Vrije Universiteit, Amsterdam
* modified by
* Johan Stevenson, Han Schaminee and Hans de Vries
* Philips S&I, T&M, PMDS, Eindhoven
*/
#include "comm0.h"
#include "comm1.h"
#include "y.tab.h"
#include "object.h"
extern YYSTYPE yylval;
static void pass_1(int, char **);
#ifdef ASLD
static void archive(void);
static int needed(void);
#endif
static void parse(char *);
static void pass_23(int);
static void setupoutput(void);
static void commfinish(void);
/* ========== Machine independent C routines ========== */
void stop(void) {
exit(nerrors != 0);
}
static void stop_on_signal(int sig) {
stop();
}
int
main(int argc, char **argv)
{
char *p;
int i;
static char sigs[] = {
SIGHUP, SIGINT, SIGQUIT, SIGTERM, 0
};
/* the next test should be performed by the
* preprocessor, but it cannot, so it is performed by the compiler.
*/
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++) != 0; )
if (signal(i, SIG_IGN) != SIG_IGN)
signal(i, stop_on_signal);
for (i = 0; i < argc; i++) {
p = argv[i];
if (*p++ != '-')
continue;
switch (*p++) {
case 'o':
if (*p != '\0') {
aoutpath = p;
break;
}
argv[i] = 0;
if (++i >= argc)
fatal("-o needs filename");
aoutpath = argv[i];
break;
case 'd':
#ifdef LISTING
dflag = 0;
while (*p >= '0' && *p <= '7')
dflag = (dflag << 3) + *p++ - '0';
if ((dflag & 0777) == 0)
dflag |= 0700;
dflag &= ~4;
#endif
break;
case 's':
sflag = 0;
while (*p >= '0' && *p <= '7')
sflag = (sflag << 3) + *p++ - '0';
break;
case 'r':
#ifdef RELOCATION
#ifdef ASLD
rflag = 1;
#endif /* ASLD */
#endif /* RELOCATION */
break;
case 'b':
#ifdef THREE_PASS
bflag = 1;
#endif
break;
#ifndef ASLD
case 'u':
case '\0':
uflag = 1;
break;
#endif
default:
continue;
}
argv[i] = 0;
}
#ifdef RELOCATION
if (rflag)
sflag |= SYM_SCT;
#endif /* RELOCATION */
pass_1(argc, argv);
#ifdef THREE_PASS
pass_23(PASS_2);
#endif
pass_23(PASS_3);
wr_close();
stop();
}
/* ---------- pass 1: arguments, modules, archives ---------- */
static void
pass_1(int argc, char **argv)
{
char *p;
item_t *ip;
#ifdef ASLD
char armagic[2];
#else
int nfile = 0;
#endif
#ifdef THREE_PASS
bitindex = -1;
nbits = BITCHUNK;
#endif
tempfile = tmpfile();
#ifdef LISTING
listmode = dflag;
if (listmode & 0440)
listfile = tmpfile();
#endif
for (ip = keytab; ip->i_type; ip++)
item_insert(ip, H_KEY+hash(ip->i_name));
machstart(PASS_1);
while (--argc >= 0) {
p = *argv++;
if (p == 0)
continue;
#ifndef ASLD
if (nfile != 0)
fatal("second source file %s", p);
nfile++;
#else
if (p[0] == '-' && p[1] == '\0') {
input = stdin;
parse("STDIN");
continue;
}
#endif
if ((input = fopen(p, "r")) == NULL)
fatal("can't open %s", p);
#ifdef ASLD
if (
fread(armagic, 2, 1, input) == 1
&&
((armagic[0]&0377) |
((unsigned)(armagic[1]&0377)<<8)) == ARMAG
) {
archive();
fclose(input);
continue;
}
rewind(input);
#endif
parse(p);
fclose(input);
}
#ifndef ASLD
if (nfile == 0) {
input = stdin;
parse("STDIN");
}
#endif
commfinish();
machfinish(PASS_1);
#ifdef ASLD
if (unresolved) {
int i;
nerrors++;
fflush(stdout);
fprintf(stderr, "unresolved references:\n");
for (i = 0; i < H_SIZE; i++) {
ip = hashtab[H_GLOBAL+i];
while (ip != 0) {
if ((ip->i_type & (S_EXT|S_TYP)) == (S_EXT|S_UND))
fprintf(stderr, "\t%s\n", ip->i_name);
ip = ip->i_next;
}
}
}
#else
if (unresolved)
outhead.oh_flags |= HF_LINK;
/*
if (nfile == 0)
fatal("no source file");
*/
#endif
}
#ifdef ASLD
static void
archive(void) {
long offset;
struct ar_hdr header;
char ar_name[AR_NAME_MAX+1];
char getsize[AR_TOTAL];
archmode++;
offset = 2;
for (;;) {
if (unresolved == 0)
break;
fseek(input,offset,0);
if (fread(getsize,AR_TOTAL,1,input) != 1)
break;
offset += AR_TOTAL;
strncpy(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 = header.ar_size;
ar_name[AR_NAME_MAX] = '\0';
parse(remember(ar_name));
}
offset += header.ar_size;
while (offset % 2)
offset++;
}
archmode = 0;
}
static int
needed(void)
{
int c, first;
item_t *ip;
int need;
#ifdef LISTING
int save;
save = listflag; listflag = 0;
#endif
need = 0;
peekc = -1;
first = 1;
for (;;) {
c = nextchar();
if (c == '\n') {
first = 1;
continue;
}
if (c == ' ' || c == '\t' || c == ',')
continue;
if (ISALPHA(c) == 0)
break;
if ((ip = item_search(readident(c))) == 0) {
if (first)
break;
continue;
}
if (first) {
if (ip == &keytab[KEYSECT]) {
while ((c = nextchar()) != '\n')
;
continue;
}
if (ip != &keytab[KEYDEFINE])
break;
first = 0;
}
if ((ip->i_type & S_TYP) == S_UND) {
need++;
break;
}
}
#ifdef LISTING
listflag = save;
#endif
return(need);
}
#endif /* ASLD */
static void
parse(char *s)
{
int i;
item_t *ip;
char *p;
for (p = s; *p; )
if (*p++ == '/')
s = p;
#ifdef ASLD
yylval.y_strp = s;
putval(MODULE);
#endif
for (i = 0; i < FB_SIZE; i++)
fb_ptr[FB_BACK+i] = 0;
newmodule(s);
peekc = -1;
yyparse();
/*
* Check for undefined symbols
*/
#ifdef ASLD
for (i = 0; i < H_SIZE; i++) {
while ((ip = hashtab[H_LOCAL+i])) {
/*
* cleanup local queue
*/
hashtab[H_LOCAL+i] = ip->i_next;
/*
* make undefined references extern
*/
if ((ip->i_type & (S_VAR|S_TYP)) == S_UND)
ip->i_type |= S_EXT;
/*
* relink externals in global queue
*/
if (ip->i_type & S_EXT)
item_insert(ip, H_GLOBAL+i);
}
}
#else
for (i = 0; i < H_SIZE; i++) {
for (ip = hashtab[H_LOCAL+i]; ip; ip = ip->i_next) {
if (ip->i_type & S_EXT)
continue;
if (ip->i_type != S_UND)
continue;
if (uflag == 0)
serror("undefined symbol %s", ip->i_name);
ip->i_type |= S_EXT;
}
}
#endif
/*
* Check for undefined numeric labels
*/
for (i = 0; i < FB_SIZE; i++) {
if ((ip = fb_ptr[FB_FORW+i]) == 0)
continue;
serror("undefined label %d", i);
fb_ptr[FB_FORW+i] = 0;
}
}
static void
pass_23(int n)
{
int i;
#ifdef ASLD
ADDR_T base = 0;
#endif
sect_t *sp;
if (nerrors)
stop();
pass = n;
#ifdef LISTING
listmode >>= 3;
if (listmode & 4)
rewind(listfile);
listeoln = 1;
#endif
#ifdef THREE_PASS
bitindex = -1;
nbits = BITCHUNK;
#endif
for (i = 0; i < FB_SIZE; i++)
fb_ptr[FB_FORW+i] = fb_ptr[FB_HEAD+i];
outhead.oh_nemit = 0;
for (sp = sect; sp < &sect[outhead.oh_nsect]; sp++) {
#ifdef ASLD
if (sp->s_flag & BASED) {
base = sp->s_base;
if (base % sp->s_lign)
fatal("base not aligned");
} else {
base += (sp->s_lign - 1);
base -= (base % sp->s_lign);
sp->s_base = base;
}
base += sp->s_size;
base += sp->s_comm;
#endif
outhead.oh_nemit += sp->s_size - sp->s_zero;
}
if (pass == PASS_3)
setupoutput();
for (sp = sect; sp < &sect[outhead.oh_nsect]; sp++) {
sp->s_size = 0;
sp->s_zero = 0;
#ifdef THREE_PASS
sp->s_gain = 0;
#endif
}
machstart(n);
#ifndef ASLD
newmodule(modulename);
#endif /* ASLD */
rewind(tempfile);
yyparse();
commfinish();
machfinish(n);
}
void
newmodule(char *s)
{
static char nmbuf[STRINGMAX];
switchsect(S_UND);
if (s && s != modulename) {
strncpy(nmbuf, s, STRINGMAX-1);
modulename = nmbuf;
}
else modulename = s;
lineno = 1;
#ifdef NEEDED
/*
* problem: it shows the name of the tempfile, not any name
* the user is familiar with. Moreover, it is not reproducable.
*/
if ((sflag & (SYM_EXT|SYM_LOC|SYM_LAB)) && PASS_SYMB)
newsymb(s, S_MOD, 0, (valu_t)0);
#endif
#ifdef LISTING
listtemp = 0;
if (dflag & 01000)
listtemp = listmode;
listflag = listtemp;
#endif
}
static void
setupoutput(void)
{
sect_t *sp;
long off;
struct outsect outsect;
struct outsect *pos = &outsect;
if (! wr_open(aoutpath)) {
fatal("can't create %s", aoutpath);
}
wr_ohead(&outhead);
/*
* section table generation
*/
off = SZ_HEAD;
off += (long)outhead.oh_nsect * SZ_SECT;
for (sp = sect; sp < &sect[outhead.oh_nsect]; sp++) {
sp->s_foff = off;
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
off += (long)outhead.oh_nrelo * SZ_RELO;
#endif
if (sflag == 0)
return;
off += (long)outhead.oh_nname * SZ_NAME;
outhead.oh_nchar = off; /* see newsymb() */
}
static void
commfinish(void)
{
#ifndef ASLD
int i;
#endif
struct common_t *cp;
item_t *ip;
sect_t *sp;
valu_t addr;
switchsect(S_UND);
/*
* assign .comm labels and produce .comm symbol table entries
*/
for (cp = commons; cp; cp = cp->c_next) {
ip = cp->c_it;
#ifndef ASLD
if (!( ip->i_type & S_EXT)) {
#endif
sp = &sect[(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) {
ip->i_valu -= sp->s_gain;
}
#endif
if ((sflag & SYM_EXT) && PASS_SYMB)
newsymb(
ip->i_name,
ip->i_type & (S_EXT|S_TYP),
0,
load(ip)
);
#else /* not ASLD */
#ifdef THREE_PASS
if (pass == PASS_2) {
cp->c_size -= sp->s_gain;
}
#endif /* THREE_PASS */
}
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,
0,
cp->c_size
);
}
#endif /* not ASLD */
}
if (PASS_SYMB == 0)
return;
#ifndef ASLD
/*
* produce symbol table entries for undefined's
*/
for (i = 0; i<H_SIZE; i++)
for (ip = hashtab[H_LOCAL+i]; ip; ip = ip->i_next) {
if (ip->i_type != (S_EXT|S_UND))
continue;
if (pass != PASS_3)
/*
* save symbol table index
* for possible relocation
*/
ip->i_valu = outhead.oh_nname;
newsymb(
ip->i_name,
S_EXT|S_UND,
0,
(valu_t)0
);
}
#endif /* not ASLD */
/*
* produce symbol table entries for sections
*/
if (sflag & SYM_SCT)
for (sp = sect; sp < &sect[outhead.oh_nsect]; sp++) {
ip = sp->s_item;
newsymb(
ip->i_name,
(ip->i_type | S_SCT),
0,
load(ip)
);
}
}