182 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			182 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* $Header$ */
 | 
						|
 | 
						|
#include <alloc.h>
 | 
						|
#include <assert.h>
 | 
						|
 | 
						|
#include "position.h"
 | 
						|
#include "scope.h"
 | 
						|
#include "idf.h"
 | 
						|
#include "symbol.h"
 | 
						|
#include "type.h"
 | 
						|
#include "message.h"
 | 
						|
#include "langdep.h"
 | 
						|
#include "expr.h"
 | 
						|
 | 
						|
int stack_offset;		/* for up and down commands */
 | 
						|
 | 
						|
extern long pointer_size;
 | 
						|
extern t_addr *get_EM_regs();
 | 
						|
extern char *memcpy();
 | 
						|
 | 
						|
/* Get the address of the object indicated by sym.
 | 
						|
   Return 0 on failure,
 | 
						|
	  address on success.
 | 
						|
   *psize will contain size of object.
 | 
						|
*/
 | 
						|
t_addr
 | 
						|
get_addr(sym, psize)
 | 
						|
  register p_symbol	sym;
 | 
						|
  long			*psize;
 | 
						|
{
 | 
						|
  p_type	tp = sym->sy_type;
 | 
						|
  long		size = tp->ty_size;
 | 
						|
  t_addr	*EM_regs;
 | 
						|
  int		i;
 | 
						|
  p_scope	sc, symsc;
 | 
						|
 | 
						|
  *psize = size;
 | 
						|
  switch(sym->sy_class) {
 | 
						|
  case VAR:
 | 
						|
	/* exists if child exists; nm_value contains addres */
 | 
						|
	return (t_addr) sym->sy_name.nm_value;
 | 
						|
  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++))) {
 | 
						|
			return 0;
 | 
						|
		}
 | 
						|
		if (! EM_regs[1]) {
 | 
						|
			error("%s not available", sym->sy_idf->id_text);
 | 
						|
			return 0;
 | 
						|
		}
 | 
						|
		sc = base_scope(get_scope_from_addr(EM_regs[2]));
 | 
						|
		if (! sc || sc->sc_start > EM_regs[2]) {
 | 
						|
			error("%s not available", sym->sy_idf->id_text);
 | 
						|
			sc = 0;
 | 
						|
			return 0;
 | 
						|
		}
 | 
						|
		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] +
 | 
						|
				  (t_addr) sym->sy_name.nm_value;
 | 
						|
	}
 | 
						|
 | 
						|
	/* 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;
 | 
						|
		t_addr a;
 | 
						|
		char *AB;
 | 
						|
 | 
						|
		size = proctype->ty_nbparams;
 | 
						|
		if (has_static_link(sc)) size += pointer_size;
 | 
						|
		AB = malloc((unsigned) size);
 | 
						|
		if (! AB) {
 | 
						|
			error("could not allocate enough memory");
 | 
						|
			break;
 | 
						|
		}
 | 
						|
		if (! get_bytes(size, EM_regs[1], AB)) {
 | 
						|
			break;
 | 
						|
		}
 | 
						|
		if ((size = tp->ty_size) == 0) {
 | 
						|
			size = compute_size(tp, AB);
 | 
						|
			*psize = size;
 | 
						|
		}
 | 
						|
		a = (t_addr) get_int(AB+sym->sy_name.nm_value, pointer_size, T_UNSIGNED);
 | 
						|
		free(AB);
 | 
						|
		return a;
 | 
						|
	}
 | 
						|
  default:
 | 
						|
	error("%s is not a variable", sym->sy_idf->id_text);
 | 
						|
	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.
 | 
						|
   For 'buf', storage is allocated by malloc; this storage must
 | 
						|
   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:
 | 
						|
	*buf = malloc((unsigned) size);
 | 
						|
	if (! *buf) {
 | 
						|
		error("could not allocate enough memory");
 | 
						|
		break;
 | 
						|
	}
 | 
						|
	switch(tp->ty_class) {
 | 
						|
	case T_REAL:
 | 
						|
		put_real(*buf, size, sym->sy_const.co_rval);
 | 
						|
		break;
 | 
						|
	case T_INTEGER:
 | 
						|
	case T_SUBRANGE:
 | 
						|
	case T_UNSIGNED:
 | 
						|
	case T_ENUM:
 | 
						|
		put_int(*buf, size, sym->sy_const.co_ival);
 | 
						|
		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;
 | 
						|
		*buf = malloc((unsigned) size);
 | 
						|
		if (! *buf) {
 | 
						|
			error("could not allocate enough memory");
 | 
						|
			break;
 | 
						|
		}
 | 
						|
		if (get_bytes(size, a, *buf)) {
 | 
						|
			retval = 1;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	break;
 | 
						|
  }
 | 
						|
 | 
						|
  if (retval == 0) {
 | 
						|
	if (*buf) free(*buf);
 | 
						|
	*buf = 0;
 | 
						|
	*psize = 0;
 | 
						|
  }
 | 
						|
  else *psize = size;
 | 
						|
 | 
						|
  return retval;
 | 
						|
}
 |