ack/util/ego/cs/cs_getent.c
2018-02-05 16:09:30 -05:00

229 lines
4.9 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 <em_mnem.h>
#include "../share/types.h"
#include "../share/aux.h"
#include "../share/debug.h"
#include "../share/global.h"
#include "cs.h"
#include "cs_aux.h"
#include "cs_entity.h"
#include "cs_stack.h"
#define WS1 0
#define WS2 1
#define PS 2
#define ARGW 3
#define ARDESC3 4
STATIC struct inf_entity {
byte inf_instr; /* Key. */
byte inf_used; /* Kind of entity used by key. */
byte inf_size; /* Indication of the size. */
} inf_table[] = {
op_adp, ENAOFFSETTED, PS,
op_dee, ENEXTERNAL, WS1,
op_del, ENLOCAL, WS1,
op_ine, ENEXTERNAL, WS1,
op_inl, ENLOCAL, WS1,
op_lae, ENAEXTERNAL, PS,
op_lal, ENALOCAL, PS,
op_lar, ENARRELEM, ARDESC3,
op_ldc, ENCONST, WS2,
op_lde, ENEXTERNAL, WS2,
op_ldf, ENOFFSETTED, WS2,
op_ldl, ENLOCAL, WS2,
op_lil, ENINDIR, WS1,
op_lim, ENIGNMASK, WS1,
op_loc, ENCONST, WS1,
op_loe, ENEXTERNAL, WS1,
op_lof, ENOFFSETTED, WS1,
op_loi, ENINDIR, ARGW,
op_lol, ENLOCAL, WS1,
op_lpi, ENPROC, PS,
op_lxa, ENAARGBASE, PS,
op_lxl, ENALOCBASE, PS,
op_sar, ENARRELEM, ARDESC3,
op_sde, ENEXTERNAL, WS2,
op_sdf, ENOFFSETTED, WS2,
op_sdl, ENLOCAL, WS2,
op_sil, ENINDIR, WS1,
op_sim, ENIGNMASK, WS1,
op_ste, ENEXTERNAL, WS1,
op_stf, ENOFFSETTED, WS1,
op_sti, ENINDIR, ARGW,
op_stl, ENLOCAL, WS1,
op_zer, ENCONST, ARGW,
op_zre, ENEXTERNAL, WS1,
op_zrf, ENFZER, ARGW,
op_zrl, ENLOCAL, WS1,
op_nop /* Delimitor. */
};
#define INFKEY(ip) (ip->inf_instr & BMASK)
#define ENKIND(ip) ip->inf_used
#define SIZEINF(ip) ip->inf_size
STATIC struct inf_entity *getinf(int n)
{
struct inf_entity *ip;
for (ip = &inf_table[0]; INFKEY(ip) != op_nop; ip++) {
if (INFKEY(ip) == n) return ip;
}
return (struct inf_entity *) 0;
}
entity_p getentity(line_p lnp, line_p *l_out)
{
/* Build the entities where lnp refers to, and enter them.
* If a token needs to be popped, the first line that pushed
* it is stored in *l_out.
* The main entity lnp refers to, is returned.
*/
struct entity en;
struct token tk;
struct inf_entity *ip;
valnum vn;
offset indexsize;
struct token adesc, index, arbase;
*l_out = lnp;
/* Lor is a special case. */
if (INSTR(lnp) == op_lor) {
offset off = off_set(lnp);
en.en_static = FALSE;
en.en_size = ps;
switch ((int) off == off ? (int) off : 3) {
default:
assert(FALSE);
break;
case 0:
en.en_kind = ENLOCBASE;
break;
case 1:
return (entity_p) 0;
case 2:
en.en_kind = ENHEAPPTR;
break;
}
return en_enter(&en);
}
if ( (ip = getinf(INSTR(lnp))) == (struct inf_entity *) 0)
return (entity_p) 0; /* It does not refer to any entity. */
/* Lil and sil refer to two entities. */
if (INSTR(lnp) == op_lil || INSTR(lnp) == op_sil) {
en.en_static = FALSE;
en.en_kind = ENLOCAL;
en.en_size = ps; /* Local must be a pointer. */
en.en_loc = off_set(lnp);
vn = en_enter(&en)->en_vn;
}
en.en_static = FALSE;
en.en_kind = ENKIND(ip);
/* Fill in the size of the entity. */
switch (SIZEINF(ip)) {
default:
assert(FALSE);
break;
case WS1:
en.en_size = ws;
break;
case WS2:
en.en_size = 2*ws;
break;
case PS:
en.en_size = ps;
break;
case ARGW:
if (TYPE(lnp) != OPNO) {
en.en_size = off_set(lnp);
} else {
Pop(&tk, (offset) ws);
*l_out = tk.tk_lfirst;
en.en_size = UNKNOWN_SIZE;
}
break;
case ARDESC3:
assert(en.en_kind == ENARRELEM);
if (TYPE(lnp) != OPNO) {
indexsize = off_set(lnp);
} else {
Pop(&tk, (offset) ws);
indexsize = UNKNOWN_SIZE;
}
Pop(&adesc, (offset) ps);
en.en_adesc = adesc.tk_vn;
Pop(&index, indexsize);
en.en_index = index.tk_vn;
Pop(&arbase, (offset) ps);
en.en_arbase = arbase.tk_vn;
*l_out = arbase.tk_lfirst;
en.en_size = array_elemsize(adesc.tk_vn);
break;
}
/* Fill in additional information. */
switch (en.en_kind) {
case ENFZER:
en.en_static = TRUE;
break;
case ENCONST:
en.en_static = TRUE;
en.en_val = off_set(lnp);
break;
case ENALOCAL:
en.en_static = TRUE;
case ENLOCAL:
en.en_loc = off_set(lnp);
break;
case ENAEXTERNAL:
en.en_static = TRUE;
case ENEXTERNAL:
en.en_ext = OBJ(lnp);
break;
case ENINDIR:
if (INSTR(lnp) == op_loi || INSTR(lnp) == op_sti) {
Pop(&tk, (offset) ps);
*l_out = tk.tk_lfirst;
vn = tk.tk_vn;
}
en.en_ind = vn;
break;
case ENAOFFSETTED:
en.en_static = TRUE;
case ENOFFSETTED:
Pop(&tk, (offset) ps);
*l_out = tk.tk_lfirst;
en.en_base = tk.tk_vn;
en.en_off = off_set(lnp);
break;
case ENALOCBASE:
case ENAARGBASE:
en.en_levels = off_set(lnp);
if (en.en_levels == 0) {
/* otherwise the program could change it */
en.en_static = TRUE;
}
break;
case ENPROC:
en.en_pro = PROC(lnp);
break;
case ENARRELEM:
/* We gathered the information in the previous switch.
*/
break;
}
return en_enter(&en);
}