ack/util/ass/assci.c

1080 lines
19 KiB
C
Raw Permalink Normal View History

1984-07-02 15:35:56 +00:00
/*
1987-03-10 01:26:51 +00:00
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
1984-07-02 15:35:56 +00:00
*
*/
#include "ass00.h"
#include "assex.h"
2019-03-17 14:41:25 +00:00
#include "assci.h"
#include "asscm.h"
#include "assrl.h"
1991-08-27 09:45:37 +00:00
#include <em_mes.h>
#include <em_pseu.h>
#include <em_ptyp.h>
1984-07-02 15:35:56 +00:00
/*
* read compact code and fill in tables
*/
2019-03-17 14:41:25 +00:00
static int tabval;
static cons_t argval;
1984-07-02 15:35:56 +00:00
2019-03-17 14:41:25 +00:00
static int oksizes; /* MES EMX,.,. seen */
1984-07-02 15:35:56 +00:00
2019-03-17 14:41:25 +00:00
static enum m_type
{
CON, ROM, HOLBSS
} memtype;
static int valtype; /* Transfer of type information between
valsize, inpseudo and putval
*/
1984-07-02 15:35:56 +00:00
2019-03-17 14:41:25 +00:00
/* Forward declarations
* Yes, there is a better way to reorder to avoid these forward
* declarations, but its complex to do, so we use the lazy way
*/
static int getarg(int);
static cons_t getint(void);
static glob_t *getlab(int);
static char *getdig(char *, unsigned int);
static void make_string(unsigned int);
static void getstring(void);
static void inident(void);
static char *inproname(void);
static int needed(void);
static cons_t valsize(void);
static void setline(void);
static void inpseudo(int);
static void compact_line(void);
static cons_t maxval(int);
static void setsizes(void);
static void exchange(int, int);
static void doinsert(line_t *, int, int);
static void putval(void);
static void chkstart(void);
static void typealign(enum m_type);
static void sizealign(cons_t);
static void extconst(cons_t);
static void extbss(cons_t);
static void extloc(register locl_t *);
static void extglob(glob_t *, cons_t);
static void extpro(proc_t *);
static void extstring(void);
static void extxcon(int);
static long myatol(register char *);
static void extvcon(int);
static int table3(int i)
{
switch (i)
{
1984-07-02 15:35:56 +00:00
case sp_ilb1:
tabval = get8();
break;
case sp_dlb1:
make_string(get8());
2019-03-17 14:41:25 +00:00
i = sp_dnam;
1984-07-02 15:35:56 +00:00
break;
case sp_dlb2:
tabval = get16();
2019-03-17 14:41:25 +00:00
if (tabval < 0)
{
error("illegal data label .%d", tabval);
tabval = 0;
1984-07-02 15:35:56 +00:00
}
make_string(tabval);
2019-03-17 14:41:25 +00:00
i = sp_dnam;
1984-07-02 15:35:56 +00:00
break;
case sp_cst2:
argval = get16();
break;
case sp_ilb2:
tabval = get16();
2019-03-17 14:41:25 +00:00
if (tabval < 0)
{
error("illegal instruction label %d", tabval);
tabval = 0;
1984-07-02 15:35:56 +00:00
}
i = sp_ilb1;
break;
case sp_cst4:
i = sp_cst2;
argval = get32();
break;
case sp_dnam:
case sp_pnam:
inident();
2019-03-17 14:41:25 +00:00
break;
1984-07-02 15:35:56 +00:00
case sp_scon:
2019-03-17 14:41:25 +00:00
getstring();
1984-07-02 15:35:56 +00:00
break;
case sp_doff:
getarg(sym_ptyp);
getarg(cst_ptyp);
break;
case sp_icon:
case sp_ucon:
case sp_fcon:
getarg(cst_ptyp);
consiz = argval;
2019-03-17 14:41:25 +00:00
if (consiz < wordsize ? wordsize % consiz != 0 : consiz % wordsize != 0)
{
fatal("illegal object size");
1984-07-02 15:35:56 +00:00
}
getstring();
break;
}
2019-03-17 14:41:25 +00:00
return (i);
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
int get16(void)
{
1984-07-02 15:35:56 +00:00
register int l_byte, h_byte;
l_byte = get8();
h_byte = get8();
2019-03-17 14:41:25 +00:00
if (h_byte >= 128)
h_byte -= 256;
return l_byte | (h_byte * 256);
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
int getu16(void)
{
register int l_byte, h_byte;
l_byte = get8();
h_byte = get8();
2019-03-17 14:41:25 +00:00
return l_byte | (h_byte * 256);
}
2019-03-17 14:41:25 +00:00
cons_t get32(void)
{
1984-07-02 15:35:56 +00:00
register cons_t l;
register int h_byte;
2019-03-17 14:41:25 +00:00
l = get8();
l |= (unsigned) get8() * 256;
l |= get8() * 256L * 256L;
h_byte = get8();
if (h_byte >= 128)
h_byte -= 256;
return l | (h_byte * 256L * 256 * 256L);
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
static int table1(void)
{
register int i;
1984-07-02 15:35:56 +00:00
i = xget8();
2019-03-17 14:41:25 +00:00
if (i < sp_fmnem + sp_nmnem && i >= sp_fmnem)
{
tabval = i - sp_fmnem;
return (sp_fmnem);
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
if (i < sp_fpseu + sp_npseu && i >= sp_fpseu)
{
1984-07-02 15:35:56 +00:00
tabval = i;
2019-03-17 14:41:25 +00:00
return (sp_fpseu);
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
if (i < sp_filb0 + sp_nilb0 && i >= sp_filb0)
{
1984-07-02 15:35:56 +00:00
tabval = i - sp_filb0;
2019-03-17 14:41:25 +00:00
return (sp_ilb1);
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
return (table3(i));
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
static int table2(void)
{
register int i;
1984-07-02 15:35:56 +00:00
i = get8();
2019-03-17 14:41:25 +00:00
if (i < sp_fcst0 + sp_ncst0 && i >= sp_fcst0)
{
1984-07-02 15:35:56 +00:00
argval = i - sp_zcst0;
2019-03-17 14:41:25 +00:00
return (sp_cst2);
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
return (table3(i));
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
/* Read argument of instruction */
static int getarg(int typset)
{
register int t, argtyp;
1984-07-02 15:35:56 +00:00
argtyp = t = table2();
t -= sp_fspec;
t = 1 << t;
if ((typset & t) == 0)
2019-03-17 14:41:25 +00:00
error("bad argument type %d", argtyp);
return (argtyp);
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
static cons_t getint(void)
{
1984-07-02 15:35:56 +00:00
getarg(cst_ptyp);
2019-03-17 14:41:25 +00:00
return (argval);
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
static glob_t *getlab(int status)
{
1984-07-02 15:35:56 +00:00
getarg(sym_ptyp);
2019-03-17 14:41:25 +00:00
return (glo2lookup(string, status));
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
static char *getdig(char *str, unsigned int number)
{
register int remain;
2019-03-17 14:41:25 +00:00
remain = number % 10;
number /= 10;
2019-03-17 14:41:25 +00:00
if (number)
str = getdig(str, number);
*str++ = '0' + remain;
return str;
}
2019-03-17 14:41:25 +00:00
static void make_string(unsigned int n)
{
string[0] = '.';
2019-03-17 14:41:25 +00:00
*getdig(&string[1], n) = 0;
}
2019-03-17 14:41:25 +00:00
static void getstring(void)
{
register char *p;
2019-03-17 14:41:25 +00:00
register int n;
getarg(cst_ptyp);
2019-03-17 14:41:25 +00:00
if (argval < 0 || argval >= MAXSTRING - 1)
fatal("string/identifier too long");
strlngth = n = argval;
p = string;
while (--n >= 0)
*p++ = get8();
2019-03-17 14:41:25 +00:00
*p = 0;
}
2019-03-17 14:41:25 +00:00
static void inident(void)
{
getstring();
}
2019-03-17 14:41:25 +00:00
static char *inproname(void)
{
1984-07-02 15:35:56 +00:00
getarg(ptyp(sp_pnam));
2019-03-17 14:41:25 +00:00
return (string);
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
static int needed(void)
{
1984-07-02 15:35:56 +00:00
register glob_t *g;
register proc_t *p;
2019-03-17 14:41:25 +00:00
for (;;)
{
switch (table2())
{
case sp_dnam:
if ( (g = xglolookup(string, SEARCHING)) != NULL)
{
if ((g->g_status & DEF) != 0)
continue;
}
else
continue;
break;
case sp_pnam:
p = searchproc(string, xprocs, oursize->n_xproc);
if (p->p_name)
{
1984-07-02 15:35:56 +00:00
if ((p->p_status & DEF) != 0)
2019-03-17 14:41:25 +00:00
continue;
}
else
continue;
break;
default:
error("Unexpected byte after ms_ext");
case sp_cend:
return FALSE;
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
while (table2() != sp_cend)
;
return TRUE;
1984-07-02 15:35:56 +00:00
}
}
2019-03-17 14:41:25 +00:00
static cons_t valsize(void)
{
switch (valtype = table2())
{ /* valtype is used by putval and inpseudo */
1984-07-02 15:35:56 +00:00
case sp_cst2:
2019-03-17 14:41:25 +00:00
return wordsize;
1984-07-02 15:35:56 +00:00
case sp_ilb1:
case sp_dnam:
case sp_doff:
case sp_pnam:
2019-03-17 14:41:25 +00:00
return ptrsize;
1984-07-02 15:35:56 +00:00
case sp_scon:
2019-03-17 14:41:25 +00:00
return strlngth;
1984-07-02 15:35:56 +00:00
case sp_fcon:
case sp_icon:
case sp_ucon:
2019-03-17 14:41:25 +00:00
return consiz;
1984-07-02 15:35:56 +00:00
case sp_cend:
2019-03-17 14:41:25 +00:00
return 0;
1984-07-02 15:35:56 +00:00
default:
2019-03-17 14:41:25 +00:00
fatal("value expected");
return 0;
1984-07-02 15:35:56 +00:00
/* NOTREACHED */
}
}
2019-03-17 14:41:25 +00:00
void newline(int type)
{
register line_t *n_lnp;
if (type > VALLOW)
type = VALLOW;
n_lnp = lnp_cast getarea((unsigned) linesize[type]);
n_lnp->l_next = pstate.s_fline;
pstate.s_fline = n_lnp;
n_lnp->type1 = type;
n_lnp->opoff = NO_OFF;
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
static void setline(void)
{
1984-07-02 15:35:56 +00:00
2019-03-17 14:41:25 +00:00
/* Get line numbers correct */
1984-07-02 15:35:56 +00:00
2019-03-17 14:41:25 +00:00
if (pstate.s_fline &&
ctrunc(pstate.s_fline->instr_num) == sp_fpseu)
{
/* Already one present */
pstate.s_fline->ad.ad_ln.ln_extra++;
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
else
{
newline(LINES);
pstate.s_fline->instr_num = sp_fpseu;
pstate.s_fline->ad.ad_ln.ln_extra = 0;
pstate.s_fline->ad.ad_ln.ln_first = line_num;
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
static void inpseudo(int instr_no)
{
1984-07-02 15:35:56 +00:00
cons_t cst;
register proc_t *prptr;
cons_t objsize;
2019-03-17 14:41:25 +00:00
cons_t par1, par2;
1984-07-02 15:35:56 +00:00
register char *pars;
/*
* get operands of pseudo (if needed) and process it.
*/
2019-03-17 14:41:25 +00:00
switch (ctrunc(instr_no))
{
1984-07-02 15:35:56 +00:00
case ps_bss:
2019-03-17 14:41:25 +00:00
chkstart();
typealign(HOLBSS);
cst = getint(); /* number of bytes */
1984-07-02 15:35:56 +00:00
extbss(cst);
break;
case ps_hol:
2019-03-17 14:41:25 +00:00
chkstart();
typealign(HOLBSS);
holsize = getint();
holbase = databytes;
1984-07-02 15:35:56 +00:00
extbss(holsize);
break;
case ps_rom:
case ps_con:
2019-03-17 14:41:25 +00:00
chkstart();
typealign( ctrunc(instr_no) == ps_rom ? ROM : CON);
while ((objsize = valsize()) != 0)
{
if (valtype != sp_scon)
sizealign(objsize);
putval();
databytes += objsize;
1984-07-02 15:35:56 +00:00
}
break;
case ps_end:
2019-03-17 14:41:25 +00:00
prptr = pstate.s_curpro;
if (prptr == prp_cast 0)
fatal("unexpected END");
1984-07-02 15:35:56 +00:00
proctab[prptr->p_num].pr_off = textbytes;
2019-03-17 14:41:25 +00:00
if (procflag)
{
printf("%6lu\t%6lo\t%5d\t%-12s\t%s", textbytes, textbytes,
prptr->p_num, prptr->p_name, curfile);
1984-07-02 15:35:56 +00:00
if (archmode)
2019-03-17 14:41:25 +00:00
printf("(%.14s)", archhdr.ar_name);
1984-07-02 15:35:56 +00:00
printf("\n");
}
2019-03-17 14:41:25 +00:00
par2 = proctab[prptr->p_num].pr_loc;
if (getarg(cst_ptyp | ptyp(sp_cend)) == sp_cend)
{
if (par2 == -1)
{
fatal("size of local area unspecified");
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
}
else
{
if (par2 != -1 && argval != par2)
{
fatal("inconsistent local area size");
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
proctab[prptr->p_num].pr_loc = argval;
1984-07-02 15:35:56 +00:00
}
setline();
do_proc();
break;
case ps_mes:
2019-03-17 14:41:25 +00:00
switch ( int_cast getint())
{
1984-07-02 15:35:56 +00:00
case ms_err:
2019-03-17 14:41:25 +00:00
error("module with error");
ertrap();
1984-07-02 15:35:56 +00:00
/* NOTREACHED */
case ms_emx:
2019-03-17 14:41:25 +00:00
if (oksizes)
{
if (wordsize != getint())
{
1984-07-02 15:35:56 +00:00
fatal("Inconsistent word size");
}
2019-03-17 14:41:25 +00:00
if (ptrsize != getint())
{
1984-07-02 15:35:56 +00:00
fatal("Inconsistent pointer size");
}
2019-03-17 14:41:25 +00:00
}
else
{
oksizes++;
wordsize = getint();
ptrsize = getint();
if (wordsize != 2 && wordsize != 4)
{
1984-07-02 15:35:56 +00:00
fatal("Illegal word size");
}
2019-03-17 14:41:25 +00:00
if (ptrsize != 2 && ptrsize != 4)
{
1984-07-02 15:35:56 +00:00
fatal("Illegal pointer size");
}
2019-03-17 14:41:25 +00:00
setsizes();
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
++mod_sizes;
1984-07-02 15:35:56 +00:00
break;
case ms_src:
break;
case ms_flt:
2019-03-17 14:41:25 +00:00
intflags |= 020;
break; /*floats used*/
1984-07-02 15:35:56 +00:00
case ms_ext:
2019-03-17 14:41:25 +00:00
if (!needed())
{
eof_seen++;
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
if (line_num > 2)
{
werror("mes ms_ext must be first or second pseudo");
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
return;
1984-07-02 15:35:56 +00:00
}
while (table2() != sp_cend)
;
break;
case ps_exc:
par1 = getint();
par2 = getint();
if (par1 == 0 || par2 == 0)
break;
2019-03-17 14:41:25 +00:00
exchange((int) par2, (int) par1);
1984-07-02 15:35:56 +00:00
break;
case ps_exa:
getlab(EXTERNING);
break;
case ps_ina:
getlab(INTERNING);
break;
case ps_pro:
2019-03-17 14:41:25 +00:00
chkstart();
1984-07-02 15:35:56 +00:00
initproc();
pars = inproname();
2019-03-17 14:41:25 +00:00
if (getarg(cst_ptyp | ptyp(sp_cend)) == sp_cend)
{
par2 = -1;
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
else
{
par2 = argval;
}
prptr = prolookup(pars, PRO_DEF);
1984-07-02 15:35:56 +00:00
proctab[prptr->p_num].pr_loc = par2;
2019-03-17 14:41:25 +00:00
pstate.s_curpro = prptr;
1984-07-02 15:35:56 +00:00
break;
case ps_inp:
2019-03-17 14:41:25 +00:00
prptr = prolookup(inproname(), PRO_INT);
1984-07-02 15:35:56 +00:00
break;
case ps_exp:
2019-03-17 14:41:25 +00:00
prptr = prolookup(inproname(), PRO_EXT);
1984-07-02 15:35:56 +00:00
break;
default:
fatal("unknown pseudo");
}
2019-03-17 14:41:25 +00:00
if (!mod_sizes)
fatal("Missing size specification");
if (databytes > maxadr)
error("Maximum data area size exceeded");
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
/*
* read one "line" of compact code.
*/
static void compact_line(void)
{
register int instr_no;
1984-07-02 15:35:56 +00:00
2019-03-17 14:41:25 +00:00
curglosym = 0;
switch (table1())
{
default:
fatal("unknown byte at start of \"line\""); /* NOTREACHED */
case EOF:
eof_seen++;
while (pstate.s_prevstat != pst_cast 0)
{
error("missing end");
do_proc();
}
return;
case sp_fmnem:
if (pstate.s_curpro == prp_cast 0)
{
error("instruction outside procedure");
}
instr_no = tabval;
if ((em_flag[instr_no] & EM_PAR) == PAR_NO)
{
newline(MISSING);
pstate.s_fline->instr_num = instr_no;
return;
}
/*
* This instruction should have an opcode, so read it after
* this switch.
*/
break;
case sp_dnam:
chkstart();
align(wordsize);
curglosym = glo2lookup(string, DEFINING);
curglosym->g_val.g_addr = databytes;
lastglosym = curglosym;
setline();
line_num++;
if (table1() != sp_fpseu)
fatal("no pseudo after data label");
case sp_fpseu:
inpseudo(tabval);
setline();
return;
case sp_ilb1:
newline(LOCSYM);
pstate.s_fline->ad.ad_lp = loclookup(tabval, DEFINING);
pstate.s_fline->instr_num = sp_ilb1;
return;
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
/*
* Now process argument
*/
switch (table2())
{
default:
fatal("unknown byte at start of argument"); /*NOTREACHED*/
case sp_cst2:
if ((em_flag[instr_no] & EM_PAR) == PAR_B)
{
/* value indicates a label */
newline(LOCSYM);
pstate.s_fline->ad.ad_lp = loclookup((int) argval, OCCURRING);
}
else
{
if (argval >= VAL1(VALLOW) && argval <= VAL1(VALHIGH))
{
newline(VALLOW);
pstate.s_fline->type1 = argval + VALMID;
}
else
{
newline(CONST);
pstate.s_fline->ad.ad_i = argval;
pstate.s_fline->type1 = CONST;
}
}
break;
case sp_ilb1:
newline(LOCSYM);
pstate.s_fline->ad.ad_lp = loclookup(tabval, OCCURRING);
break;
case sp_dnam:
newline(GLOSYM);
pstate.s_fline->ad.ad_gp = glo2lookup(string, OCCURRING);
break;
case sp_pnam:
newline(PROCNAME);
pstate.s_fline->ad.ad_pp = prolookup(string, PRO_OCC);
break;
case sp_cend:
if ((em_flag[instr_no] & EM_PAR) != PAR_W)
{
fatal("missing operand");
}
newline(MISSING);
break;
case sp_doff:
newline(GLOOFF);
pstate.s_fline->ad.ad_df.df_i = argval;
pstate.s_fline->ad.ad_df.df_gp = glo2lookup(string, OCCURRING);
break;
}
pstate.s_fline->instr_num = instr_no;
return;
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
void read_compact(void)
{
init_module();
pass = 1;
eof_seen = 0;
do
{
compact_line();
line_num++;
} while (!eof_seen);
endproc(); /* Throw away unwanted garbage */
if (mod_sizes)
end_module();
/* mod_sizes is only false for rejected library modules */
}
static cons_t maxval(int bits)
{
1984-07-02 15:35:56 +00:00
/* find the maximum positive value,
* fitting in 'bits' bits AND
* fitting in a 'cons_t' .
*/
2019-03-17 14:41:25 +00:00
cons_t val;
val = 1;
while (bits--)
{
val <<= 1;
if (val < 0)
return ~val;
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
return val - 1;
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
static void setsizes(void)
{
maxadr = maxval(8 * ptrsize);
maxint = maxval(8 * wordsize - 1);
maxunsig = maxval(8 * wordsize);
maxdint = maxval(2 * 8 * wordsize - 1);
maxdunsig = maxval(2 * 8 * wordsize);
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
static void exchange(int p1, int p2)
{
int size, line;
register line_t *t_lnp, *a_lnp, *b_lnp;
1984-07-02 15:35:56 +00:00
/* Since the lines are linked backwards it is easy
* to count the number of lines backwards.
* Each instr counts for 1, each pseudo for ln_extra + 1.
* The line numbers in error messages etc. are INCORRECT
* If exc's are used.
*/
2019-03-17 14:41:25 +00:00
line = line_num;
size = 0;
newline(LINES);
a_lnp = pstate.s_fline;
a_lnp->instr_num = sp_fpseu;
a_lnp->ad.ad_ln.ln_first = line;
a_lnp->ad.ad_ln.ln_extra = -1;
for (; a_lnp; a_lnp = a_lnp->l_next)
{
line--;
switch (ctrunc(a_lnp->instr_num))
{
case sp_fpseu:
line = a_lnp->ad.ad_ln.ln_first;
size += a_lnp->ad.ad_ln.ln_extra;
break;
case sp_ilb1:
a_lnp->ad.ad_lp->l_min -= p2;
break;
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
size++;
if (size >= p1)
break;
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
if ((size -= p1) > 0)
{
if ( ctrunc(a_lnp->instr_num) != sp_fpseu)
{
fatal("EXC inconsistency");
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
doinsert(a_lnp, line, size - 1);
a_lnp->ad.ad_ln.ln_extra -= size;
size = 0;
}
else
{
if (a_lnp)
doinsert(a_lnp, line, -1);
}
b_lnp = a_lnp;
while (b_lnp)
{
b_lnp = b_lnp->l_next;
line--;
switch (ctrunc(b_lnp->instr_num))
{
case sp_fpseu:
size += b_lnp->ad.ad_ln.ln_extra;
line = b_lnp->ad.ad_ln.ln_first;
break;
case sp_ilb1:
b_lnp->ad.ad_lp->l_min += p1;
break;
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
size++;
if (size >= p2)
break;
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
if (!b_lnp)
{ /* if a_lnp==0, so is b_lnp */
fatal("Cannot perform exchange");
}
2019-03-17 14:41:25 +00:00
if ((size -= p2) > 0)
{
if ( ctrunc(b_lnp->instr_num) != sp_fpseu)
{
fatal("EXC inconsistency");
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
doinsert(b_lnp, line, size - 1);
b_lnp->ad.ad_ln.ln_extra -= size;
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
else
{
doinsert(b_lnp, line, -1);
}
t_lnp = b_lnp->l_next;
b_lnp->l_next = pstate.s_fline;
pstate.s_fline = a_lnp->l_next;
a_lnp->l_next = t_lnp;
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
static void doinsert(line_t *lnp, int first, int extra)
{
1984-07-02 15:35:56 +00:00
/* Beware : s_fline will be clobbered and restored */
2019-03-17 14:41:25 +00:00
register line_t *t_lnp;
t_lnp = pstate.s_fline;
pstate.s_fline = lnp->l_next;
newline(LINES);
pstate.s_fline->instr_num = sp_fpseu;
pstate.s_fline->ad.ad_ln.ln_first = first;
pstate.s_fline->ad.ad_ln.ln_extra = extra;
lnp->l_next = pstate.s_fline;
pstate.s_fline = t_lnp; /* restore */
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
static void putval(void)
{
switch (valtype)
{
1984-07-02 15:35:56 +00:00
case sp_cst2:
extconst(argval);
2019-03-17 14:41:25 +00:00
return;
1984-07-02 15:35:56 +00:00
case sp_ilb1:
2019-03-17 14:41:25 +00:00
extloc(loclookup(tabval, OCCURRING));
return;
1984-07-02 15:35:56 +00:00
case sp_dnam:
2019-03-17 14:41:25 +00:00
extglob(glo2lookup(string, OCCURRING), (cons_t) 0);
return;
1984-07-02 15:35:56 +00:00
case sp_doff:
2019-03-17 14:41:25 +00:00
extglob(glo2lookup(string, OCCURRING), argval);
return;
1984-07-02 15:35:56 +00:00
case sp_pnam:
2019-03-17 14:41:25 +00:00
extpro(prolookup(string, PRO_OCC));
return;
1984-07-02 15:35:56 +00:00
case sp_scon:
2019-03-17 14:41:25 +00:00
extstring();
return;
1984-07-02 15:35:56 +00:00
case sp_fcon:
2019-03-17 14:41:25 +00:00
extxcon(DATA_FCON);
return;
1984-07-02 15:35:56 +00:00
case sp_icon:
2019-03-17 14:41:25 +00:00
extvcon(DATA_ICON);
return;
1984-07-02 15:35:56 +00:00
case sp_ucon:
2019-03-17 14:41:25 +00:00
extvcon(DATA_UCON);
return;
1984-07-02 15:35:56 +00:00
default:
2019-03-17 14:41:25 +00:00
fatal("putval notreached");
1984-07-02 15:35:56 +00:00
/* NOTREACHED */
}
}
2019-03-17 14:41:25 +00:00
static void chkstart(void)
{
static int absout = 0;
1984-07-02 15:35:56 +00:00
2019-03-17 14:41:25 +00:00
if (absout)
return;
if (!oksizes)
fatal("missing size specification");
set_mode(DATA_CONST);
extconst((cons_t) 0);
databytes = wordsize;
set_mode(DATA_REP);
if (wordsize < ABSSIZE)
{
register int factor = ABSSIZE / wordsize - 1;
extadr((cons_t) factor);
databytes += factor * wordsize;
}
2019-03-17 14:41:25 +00:00
absout++;
memtype = HOLBSS;
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
static void typealign(enum m_type new)
{
if (memtype == new)
return;
1984-07-02 15:35:56 +00:00
align(wordsize);
2019-03-17 14:41:25 +00:00
memtype = new;
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
static void sizealign(cons_t size)
{
align(size > wordsize ? wordsize : (int) size);
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
void align(int size)
{
while (databytes % size)
{
set_mode(DATA_BYTES);
ext8(0);
databytes++;
1984-07-02 15:35:56 +00:00
}
}
2019-03-17 14:41:25 +00:00
static void extconst(cons_t n)
{
set_mode(DATA_CONST);
1984-07-02 15:35:56 +00:00
extword(n);
}
2019-03-17 14:41:25 +00:00
static void extbss(cons_t n)
{
cons_t objsize, amount;
cons_t sv_argval;
int sv_tabval;
1984-07-02 15:35:56 +00:00
2019-03-17 14:41:25 +00:00
if (n <= 0)
{
if (n < 0)
werror("negative bss/hol size");
if (table2() == sp_cend || table2() == sp_cend)
{
werror("Unexpected end-of-line");
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
return;
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
set_mode(DATA_NUL); /* flush descriptor */
objsize = valsize();
if (objsize == 0)
{
1984-07-02 15:35:56 +00:00
werror("Unexpected end-of-line");
return;
}
2019-03-17 14:41:25 +00:00
if (n % objsize != 0)
error("BSS/HOL incompatible sizes");
sv_tabval = tabval;
sv_argval = argval;
1984-07-02 15:35:56 +00:00
getarg(sp_cst2);
2019-03-17 14:41:25 +00:00
if (argval < 0 || argval > 1)
error("illegal last argument");
databytes += n;
if (argval == 1)
{
tabval = sv_tabval;
argval = sv_argval;
putval();
2019-03-17 14:41:25 +00:00
amount = n / objsize;
if (amount > 1)
{
set_mode(DATA_REP);
2019-03-17 14:41:25 +00:00
extadr(amount - 1);
}
}
2019-03-17 14:41:25 +00:00
else
{
n = (n + wordsize - 1) / wordsize;
2019-03-17 14:41:25 +00:00
while (n > MAXBYTE)
{
set_mode(DATA_BSS);
ext8(MAXBYTE);
n -= MAXBYTE;
}
set_mode(DATA_BSS);
ext8((int) n);
}
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
static void extloc(register locl_t *lbp)
{
1984-07-02 15:35:56 +00:00
/*
* assemble a pointer constant from a local label.
* For example con *1
*/
set_mode(DATA_IPTR);
2019-03-17 14:41:25 +00:00
data_reloc( chp_cast lbp, dataoff, RELLOC);
extadr((cons_t) 0);
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
static void extglob(glob_t *agbp, cons_t off)
{
1984-07-02 15:35:56 +00:00
register glob_t *gbp;
/*
* generate a word of data that is defined by a global symbol.
* Various relocation has to be prepared here in some cases
*/
2019-03-17 14:41:25 +00:00
gbp = agbp;
set_mode(DATA_DPTR);
2019-03-17 14:41:25 +00:00
if (gbp->g_status & DEF)
{
extadr(gbp->g_val.g_addr + off);
}
else
{
data_reloc( chp_cast gbp, dataoff, RELGLO);
1984-07-02 15:35:56 +00:00
extadr(off);
}
}
2019-03-17 14:41:25 +00:00
static void extpro(proc_t *aprp)
{
1984-07-02 15:35:56 +00:00
/*
2019-03-17 14:41:25 +00:00
* generate a address that is defined by a procedure descriptor.
1984-07-02 15:35:56 +00:00
*/
2019-03-17 14:41:25 +00:00
consiz = ptrsize;
set_mode(DATA_UCON);
extarb((int) ptrsize, (long) (aprp->p_num));
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
static void extstring(void )
{
1984-07-02 15:35:56 +00:00
register char *s;
2019-03-17 14:41:25 +00:00
register int n;
1984-07-02 15:35:56 +00:00
/*
* generate data for a string.
*/
2019-03-17 14:41:25 +00:00
for (n = strlngth, s = string; n--;)
{
set_mode(DATA_BYTES);
1984-07-02 15:35:56 +00:00
ext8(*s++);
}
2019-03-17 14:41:25 +00:00
return;
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
static void extxcon(int header)
{
register char *s;
register int n;
1984-07-02 15:35:56 +00:00
/*
* generate data for a floating constant initialized by a string.
*/
set_mode(header);
2019-03-17 14:41:25 +00:00
s = string;
for (n = strlngth; n--;)
{
if (*s == 0)
error("Zero byte in initializer");
1984-07-02 15:35:56 +00:00
ext8(*s++);
}
ext8(0);
2019-03-17 14:41:25 +00:00
return;
1984-07-02 15:35:56 +00:00
}
/* Added atol() that ignores overflow. --Ceriel */
2019-03-17 14:41:25 +00:00
static long myatol(register char *s)
{
register long total = 0;
register unsigned digit;
int minus = 0;
while (*s == ' ' || *s == '\t')
s++;
if (*s == '+')
s++;
else if (*s == '-')
{
s++;
minus = 1;
}
while ((digit = *s++ - '0') < 10)
{
total *= 10;
total += digit;
}
return (minus ? -total : total);
}
static void extvcon(int header)
{
1984-07-02 15:35:56 +00:00
/*
* generate data for a constant initialized by a string.
*/
set_mode(header);
2019-03-17 14:41:25 +00:00
if (consiz > 4)
{
error("Size of initializer exceeds loader capability");
1984-07-02 15:35:56 +00:00
}
2019-03-17 14:41:25 +00:00
extarb((int) consiz, myatol(string));
return;
1984-07-02 15:35:56 +00:00
}