ack/util/grind/value.c

183 lines
3.7 KiB
C
Raw Normal View History

1990-08-31 18:22:53 +00:00
/* $Header$ */
#include <alloc.h>
1990-09-19 14:31:12 +00:00
#include <assert.h>
1990-08-31 18:22:53 +00:00
#include "position.h"
#include "scope.h"
1990-10-17 17:00:03 +00:00
#include "idf.h"
1990-08-31 18:22:53 +00:00
#include "symbol.h"
#include "type.h"
#include "message.h"
1990-09-19 14:31:12 +00:00
#include "langdep.h"
1990-09-25 17:40:47 +00:00
#include "expr.h"
1990-08-31 18:22:53 +00:00
int stack_offset; /* for up and down commands */
extern long pointer_size;
extern t_addr *get_EM_regs();
1990-09-07 14:56:24 +00:00
extern char *memcpy();
1990-08-31 18:22:53 +00:00
1990-09-19 14:31:12 +00:00
/* Get the address of the object indicated by sym.
1990-08-31 18:22:53 +00:00
Return 0 on failure,
1990-09-19 14:31:12 +00:00
address on success.
*psize will contain size of object.
1990-08-31 18:22:53 +00:00
*/
1990-09-19 14:31:12 +00:00
t_addr
get_addr(sym, psize)
1990-08-31 18:22:53 +00:00
register p_symbol sym;
1990-09-19 14:31:12 +00:00
long *psize;
1990-08-31 18:22:53 +00:00
{
p_type tp = sym->sy_type;
long size = tp->ty_size;
t_addr *EM_regs;
int i;
p_scope sc, symsc;
1990-09-19 14:31:12 +00:00
*psize = size;
1990-08-31 18:22:53 +00:00
switch(sym->sy_class) {
case VAR:
/* exists if child exists; nm_value contains addres */
1990-09-19 14:31:12 +00:00
return (t_addr) sym->sy_name.nm_value;
1990-08-31 18:22:53 +00:00
case VARPAR:
case LOCVAR:
/* first find the stack frame in which it resides */
symsc = base_scope(sym->sy_scope);
/* now symsc contains the scope where the storage for sym is
allocated. Now find it on the stack of child.
*/
i = stack_offset;
for (;;) {
sc = 0;
if (! (EM_regs = get_EM_regs(i++))) {
1990-10-17 17:00:03 +00:00
return 0;
1990-08-31 18:22:53 +00:00
}
if (! EM_regs[1]) {
1990-10-17 17:00:03 +00:00
error("%s not available", sym->sy_idf->id_text);
return 0;
1990-08-31 18:22:53 +00:00
}
sc = base_scope(get_scope_from_addr(EM_regs[2]));
if (! sc || sc->sc_start > EM_regs[2]) {
1990-10-17 17:00:03 +00:00
error("%s not available", sym->sy_idf->id_text);
1990-08-31 18:22:53 +00:00
sc = 0;
1990-10-17 17:00:03 +00:00
return 0;
1990-08-31 18:22:53 +00:00
}
if (sc == symsc) break; /* found it */
}
if (sym->sy_class == LOCVAR) {
/* Either local variable or value parameter */
return EM_regs[sym->sy_name.nm_value < 0 ? 0 : 1] +
1990-09-19 14:31:12 +00:00
(t_addr) sym->sy_name.nm_value;
1990-08-31 18:22:53 +00:00
}
/* If we get here, we have a var parameter. Get the parameters
of the current procedure invocation.
*/
{
p_type proctype = sc->sc_definedby->sy_type;
1990-09-19 14:31:12 +00:00
t_addr a;
char *AB;
1990-08-31 18:22:53 +00:00
size = proctype->ty_nbparams;
if (has_static_link(sc)) size += pointer_size;
1990-09-25 17:40:47 +00:00
AB = malloc((unsigned) size);
if (! AB) {
error("could not allocate enough memory");
break;
}
if (! get_bytes(size, EM_regs[1], AB)) {
1990-08-31 18:22:53 +00:00
break;
}
if ((size = tp->ty_size) == 0) {
1990-09-07 14:56:24 +00:00
size = compute_size(tp, AB);
1990-09-19 14:31:12 +00:00
*psize = size;
1990-08-31 18:22:53 +00:00
}
1990-09-25 17:40:47 +00:00
a = (t_addr) get_int(AB+sym->sy_name.nm_value, pointer_size, T_UNSIGNED);
1990-09-19 14:31:12 +00:00
free(AB);
return a;
1990-08-31 18:22:53 +00:00
}
1990-09-19 14:31:12 +00:00
default:
1990-10-17 17:00:03 +00:00
error("%s is not a variable", sym->sy_idf->id_text);
1990-09-19 14:31:12 +00:00
break;
}
return 0;
}
/* Get the value of the symbol indicated by sym.
Return 0 on failure,
1 on success.
On success, 'buf' contains the value, and 'size' contains the size.
1990-09-25 17:40:47 +00:00
For 'buf', storage is allocated by malloc; this storage must
1990-09-19 14:31:12 +00:00
be freed by caller (I don't like this any more than you do, but caller
does not know sizes).
*/
int
get_value(sym, buf, psize)
register p_symbol sym;
char **buf;
long *psize;
{
p_type tp = sym->sy_type;
int retval = 0;
t_addr a;
long size = tp->ty_size;
*buf = 0;
switch(sym->sy_class) {
case CONST:
1990-09-25 17:40:47 +00:00
*buf = malloc((unsigned) size);
if (! *buf) {
error("could not allocate enough memory");
break;
}
1990-09-19 14:31:12 +00:00
switch(tp->ty_class) {
case T_REAL:
1990-09-25 17:40:47 +00:00
put_real(*buf, size, sym->sy_const.co_rval);
1990-09-19 14:31:12 +00:00
break;
case T_INTEGER:
case T_SUBRANGE:
case T_UNSIGNED:
case T_ENUM:
1990-09-25 17:40:47 +00:00
put_int(*buf, size, sym->sy_const.co_ival);
1990-09-19 14:31:12 +00:00
break;
case T_SET:
memcpy(*buf, sym->sy_const.co_setval, (int) size);
break;
case T_STRING:
memcpy(*buf, sym->sy_const.co_sval, (int) size);
break;
default:
fatal("strange constant");
}
retval = 1;
break;
case VAR:
case VARPAR:
case LOCVAR:
a = get_addr(sym, psize);
if (a) {
size = *psize;
1990-09-25 17:40:47 +00:00
*buf = malloc((unsigned) size);
if (! *buf) {
1990-10-17 17:00:03 +00:00
error("could not allocate enough memory");
1990-09-25 17:40:47 +00:00
break;
}
1990-09-19 14:31:12 +00:00
if (get_bytes(size, a, *buf)) {
retval = 1;
}
1990-08-31 18:22:53 +00:00
}
break;
}
if (retval == 0) {
if (*buf) free(*buf);
*buf = 0;
1990-09-07 14:56:24 +00:00
*psize = 0;
1990-08-31 18:22:53 +00:00
}
1990-09-12 16:13:59 +00:00
else *psize = size;
1990-08-31 18:22:53 +00:00
return retval;
}