ack/util/ego/ca/ca_put.c
George Koehler 17bc9cdef7 More void, fewer clang warnings in util/ego
Most warnings are for functions implicitly returning int.  Change most
of these functions to return void.  (Traditional K&R C had no void
type, but C89 has it.)

Add prototypes to most function declarations in headers.  This is
easy, because ego declares most of its extern functions, and the
comments listed most parameters.  There were a few outdated or missing
declarations, and a few .c files that failed to include an .h with the
declarations.

Add prototypes to a few function definitions in .c files.  Most
functions still have traditional K&R definitions.  Most STATIC
functions still don't have prototypes, because they have no earlier
declaration where I would have added the prototype.

Change some prototypes in util/ego/share/alloc.h.  Functions newmap()
and oldmap() handle an array of pointers to something; change the
array's type from `short **` to `void **`.  Callers use casts to go
between `void **` and the correct type, like `line_p *`.  Function
oldtable() takes a `short *`, not a `short **`; I added the wrong type
in 5bbbaf4.

Make a few other changes to silence warnings.  There are a few places
where clang wants extra parentheses in the code.

Edit util/ego/ra/build.lua to add the missing dependency on ra*.h; I
needed this to prevent crashes from ra.
2019-11-01 15:27:16 -04:00

409 lines
7.6 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".
*/
#include <stdio.h>
#include <em_spec.h>
#include <em_pseu.h>
#include <em_mnem.h>
#include <em_flag.h>
#include <em_mes.h>
#include "../share/types.h"
#include "ca.h"
#include "ca_put.h"
#include "../share/debug.h"
#include "../share/def.h"
#include "../share/map.h"
#include "../share/alloc.h"
#define outbyte(b) putc(b,outfile)
FILE *outfile;
STATIC proc_p thispro;
STATIC void outinst(int m) {
outbyte( (byte) m );
}
STATIC void coutshort(short i) {
outbyte( (byte) (i&BMASK) );
outbyte( (byte) (i>>8) );
}
STATIC void coutint(short i) {
if (i>= -sp_zcst0 && i< sp_ncst0-sp_zcst0)
outbyte( (byte) (i+sp_zcst0+sp_fcst0) );
else {
outbyte( (byte) sp_cst2) ;
coutshort(i);
}
}
STATIC void coutoff(offset off) {
if ((short) off == off)
coutint((short) off);
else {
outbyte( (byte) sp_cst4) ;
coutshort( (short) (off&0177777L) );
coutshort( (short) (off>>16) );
}
}
STATIC void outsym(const char *s, int t)
{
register byte *p;
register unsigned num;
if (s[0] == '.') {
num = atoi(&s[1]);
if (num < 256) {
outbyte( (byte) sp_dlb1) ;
outbyte( (byte) (num) );
} else {
outbyte( (byte) sp_dlb2) ;
coutshort((short) num);
}
} else {
p= s;
while (*p && p < &s[IDL])
p++;
num = p - s;
outbyte( (byte) t);
coutint((short) num);
p = s;
while (num--)
outbyte( (byte) *p++ );
}
}
STATIC void outdsym(dblock_p dbl)
{
if (dnames[dbl->d_id]) outsym(dnames[dbl->d_id],sp_dnam);
}
STATIC void outpsym(proc_p p)
{
outsym(pnames[p->p_id],sp_pnam);
}
STATIC void outddef(short id) {
dblock_p dbl;
dbl = dmap[id];
dbl->d_flags2 |= DF_SYMOUT;
if (dbl->d_flags1 & DF_EXTERNAL) {
outinst(ps_exa);
outdsym(dbl);
}
}
STATIC void outpdef(proc_p p) {
p->p_flags2 |= PF_SYMOUT;
if (p->p_flags1 & PF_EXTERNAL) {
outinst(ps_exp);
outpsym(p);
}
}
STATIC void outdocc(obj_p obj) {
dblock_p dbl;
dbl = obj->o_dblock;
if ((dbl->d_flags2 & DF_SYMOUT) == 0) {
dbl->d_flags2 |= DF_SYMOUT;
if (dnames[dbl->d_id] != 0 &&
(dbl->d_flags1 & DF_EXTERNAL) == 0) {
outinst(ps_ina);
outdsym(dbl);
}
}
}
STATIC void outpocc(proc_p p) {
if ((p->p_flags2 & PF_SYMOUT) == 0) {
p->p_flags2 |= PF_SYMOUT;
if ((p->p_flags1 & PF_EXTERNAL) == 0) {
outinst(ps_inp);
outpsym(p);
}
}
}
STATIC void coutobject(obj_p obj)
{
/* In general, an object is defined by a global data
* label and an offset. There are two special cases:
* the label is omitted if the object is part of the current
* hol block; the offset is omitted if it is 0 and the label
* was not omitted.
*/
if (dnames[obj->o_dblock->d_id] == 0) {
coutoff(obj->o_off);
} else {
if (obj->o_off == 0) {
outdsym(obj->o_dblock);
} else {
outbyte((byte) sp_doff);
outdsym(obj->o_dblock);
coutoff(obj->o_off);
}
}
}
STATIC void cputstr(argb_p abp) {
register argb_p tbp;
register length;
length = 0;
tbp = abp;
while (tbp!= (argb_p) 0) {
length += tbp->ab_index;
tbp = tbp->ab_next;
}
coutint(length);
while (abp != (argb_p) 0) {
for (length=0;length<abp->ab_index;length++)
outbyte( (byte) abp->ab_contents[length] );
abp = abp->ab_next;
}
}
STATIC void outnum(int n)
{
if (n < 256) {
outbyte((byte) sp_ilb1);
outbyte((byte) n);
} else {
outbyte((byte) sp_ilb2);
coutshort((short) n);
}
}
STATIC void numlab(int n)
{
if (n < sp_nilb0) {
outbyte((byte) (n + sp_filb0));
} else {
outnum(n);
}
}
STATIC void cputargs(line_p lnp)
{
register arg_p ap;
int cnt = 0;
ap = ARG(lnp);
while (ap != (arg_p) 0) {
switch(ap->a_type) {
case ARGOFF:
coutoff(ap->a_a.a_offset);
break;
case ARGOBJECT:
coutobject(ap->a_a.a_obj);
break;
case ARGPROC:
outpsym(ap->a_a.a_proc);
break;
case ARGINSTRLAB:
outnum(ap->a_a.a_instrlab);
break;
case ARGSTRING:
outbyte((byte) sp_scon);
cputstr(&ap->a_a.a_string);
break;
case ARGICN:
outbyte((byte) sp_icon);
goto casecon;
case ARGUCN:
outbyte((byte) sp_ucon);
goto casecon;
case ARGFCN:
outbyte((byte) sp_fcon);
casecon:
coutint(ap->a_a.a_con.ac_length);
cputstr(&ap->a_a.a_con.ac_con);
break;
default:
assert(FALSE);
}
ap = ap->a_next;
/* Avoid generating extremely long CON or ROM statements */
if (cnt++ > 10 && ap != (arg_p) 0 &&
(INSTR(lnp) == ps_con || INSTR(lnp) == ps_rom)) {
cnt = 0;
outbyte((byte) sp_cend);
outinst(INSTR(lnp));
}
}
}
STATIC void outoperand(line_p lnp)
{
/* Output the operand of instruction lnp */
switch(TYPE(lnp)) {
case OPNO:
if (INSTR(lnp) <= sp_lmnem &&
(em_flag[INSTR(lnp)-sp_fmnem]&EM_PAR) != PAR_NO) {
outbyte((byte) sp_cend);
}
break;
case OPSHORT:
if (INSTR(lnp) == ps_sym) {
outsym(dnames[SHORT(lnp)],sp_dnam);
} else {
coutint(SHORT(lnp));
}
break;
case OPOFFSET:
coutoff(OFFSET(lnp));
break;
case OPINSTRLAB:
if (INSTR(lnp) == op_lab) {
numlab(INSTRLAB(lnp));
} else {
if (INSTR(lnp) < sp_fpseu) {
coutint(INSTRLAB(lnp));
} else {
numlab(INSTRLAB(lnp));
}
}
break;
case OPOBJECT:
coutobject(OBJ(lnp));
break;
case OPPROC:
outpsym(PROC(lnp));
break;
case OPLIST:
cputargs(lnp);
switch(INSTR(lnp)) {
case ps_con:
case ps_rom:
case ps_mes:
outbyte((byte) sp_cend);
/* list terminator */
break;
}
break;
default:
assert(FALSE);
}
}
STATIC void outvisibility(line_p lnp)
{
/* In EM names of datalabels and procedures can be made
* externally visible, so they can be used in other files.
* There are special EM pseudo-instructions to state
* explicitly that a certain identifier is externally
* visible (ps_exa,ps_exp) or invisible (ps_ina,ps_inp).
* If there is no such pseudo for a certain identifier,
* the identifier is external only if its first use
* in the current file is an applied occurrence.
* Unfortunately the global optimizer may change the
* order of defining and applied occurrences.
* In the first optimizer pass (ic) we record for each identifier
* whether it is external or not. If necessary we generate
* pseudo instructions here.
*/
arg_p ap;
short instr;
instr = INSTR(lnp);
switch(TYPE(lnp)) {
case OPOBJECT:
outdocc(OBJ(lnp));
/* applied occurrence of a data label */
break;
case OPSHORT:
if (instr == ps_sym) {
outddef(SHORT(lnp));
/* defining occ. data label */
}
break;
case OPPROC:
if (instr == ps_pro) {
outpdef(PROC(lnp));
/* defining occ. procedure */
} else {
outpocc(PROC(lnp));
}
break;
case OPLIST:
for (ap = ARG(lnp); ap != (arg_p) 0; ap = ap->a_next) {
switch(ap->a_type) {
case ARGOBJECT:
outdocc(ap->a_a.a_obj);
break;
case ARGPROC:
outpocc(ap->a_a.a_proc);
break;
}
}
break;
}
}
void cputlines(line_p l, FILE *lf)
{
/* Output the lines in Campact assembly language
* format.
*/
line_p next,lnp;
outfile = lf;
for (lnp = l; lnp != (line_p) 0; lnp = next) {
next = lnp->l_next;
outvisibility(lnp); /* take care of visibiltity rules */
if (INSTR(lnp) != ps_sym && INSTR(lnp) != op_lab) {
outinst(INSTR(lnp));
}
outoperand(lnp);
switch(INSTR(lnp)) {
case ps_pro:
thispro = PROC(lnp);
/* fall through ... */
case ps_end:
coutoff(thispro->p_localbytes);
}
oldline(lnp);
}
if (lmap != (line_p *) 0) {
oldmap((void **) lmap,llength);
lmap = (line_p *) 0;
}
}
void cputmagic(FILE *lf)
{
/* write the magic number */
outfile = lf;
coutshort(sp_magic);
}