many changes
authorceriel <none@none>
Wed, 12 Sep 1990 16:13:59 +0000 (16:13 +0000)
committerceriel <none@none>
Wed, 12 Sep 1990 16:13:59 +0000 (16:13 +0000)
16 files changed:
util/grind/Amakefile
util/grind/char.ct
util/grind/commands.g
util/grind/dbx_string.g
util/grind/default.c [new file with mode: 0644]
util/grind/expr.c
util/grind/expr.h [new file with mode: 0644]
util/grind/langdep.cc
util/grind/langdep.h
util/grind/list.c
util/grind/modula-2.c
util/grind/print.c
util/grind/tree.c
util/grind/type.c
util/grind/type.hh
util/grind/value.c

index 09f3ae0..e90a8a9 100644 (file)
@@ -61,6 +61,7 @@ CSRC = {
        value.c,
        type.c,
        rd.c,
+       default.c,
        modula-2.c
 } ;
 
index 21a4fba..9682c33 100644 (file)
@@ -65,7 +65,7 @@ STSIMP:,<>{}:`
 %      ISTOKEN
 %
 %C
-1:-abcefiprstuvxAEFGLMPQSTVX,;:+=()*
+1:-acefiprstuvxAEFGLMPQSTVX,;:+=()*
 %T char istoken[] = {
 %p
 %T};
index 11e90e2..32f782b 100644 (file)
@@ -16,6 +16,7 @@
 #include       "tree.h"
 #include       "langdep.h"
 #include       "token.h"
+#include       "expr.h"
 
 extern char    *Salloc();
 extern t_lineno        currline;
@@ -278,10 +279,11 @@ factor(p_tree *p;)
 |
   designator(p)
 |
-  PREF_OP              { *p = mknode(OP_UNOP, (p_tree) 0);
+                       { *p = mknode(OP_UNOP, (p_tree) 0);
                          (*p)->t_whichoper = (int) tok.ival;
                        }
-  factor(&(*p)->t_args[0])
+  [ PREF_OP | PREF_OR_BIN_OP ]
+  expression(&(*p)->t_args[0], prio((*p)->t_whichoper))
 ;
 
 designator(p_tree *p;)
@@ -294,7 +296,7 @@ designator(p_tree *p;)
        name(&(*p)->t_args[1])
   |
        '['             { *p = mknode(OP_BINOP, *p, (p_tree) 0);
-                         (*p)->t_whichoper = '[';
+                         (*p)->t_whichoper = E_ARRAY;
                        }
        expression(&(*p)->t_args[1], 1)
        ']'
@@ -407,14 +409,6 @@ LLlex()
        if (in_expression) TOK = (*currlang->get_name)(c);
        else TOK = get_name(c);
        break;
-  case STDOT:
-       c = getc(db_in);
-       if (c == EOF || class(c) != STNUM) {
-               ungetc(c,db_in);
-               TOK = '.';
-               break;
-       }
-       /* Fall through */
   case STNUM:
        TOK = (*currlang->get_number)(c);
        break;
@@ -459,144 +453,6 @@ get_name(c)
   return id->id_reserved ? id->id_reserved : NAME;
 }
 
-static int
-quoted(ch)
-  int  ch;
-{
-  /*   quoted() replaces an escaped character sequence by the
-       character meant.
-  */
-  /* first char after backslash already in ch */
-  if (!is_oct(ch)) {           /* a quoted char */
-       switch (ch) {
-       case 'n':
-               ch = '\n';
-               break;
-       case 't':
-               ch = '\t';
-               break;
-       case 'b':
-               ch = '\b';
-               break;
-       case 'r':
-               ch = '\r';
-               break;
-       case 'f':
-               ch = '\f';
-               break;
-       }
-  }
-  else {                               /* a quoted octal */
-       register int oct = 0, cnt = 0;
-
-       do {
-               oct = oct*8 + (ch-'0');
-               ch = getc(db_in);
-       } while (is_oct(ch) && ++cnt < 3);
-       ungetc(ch, db_in);
-       ch = oct;
-  }
-  return ch&0377;
-
-}
-
-int 
-get_string(c)
-  int  c;
-{
-  register int ch;
-  char buf[512];
-  register int len = 0;
-
-  while (ch = getc(db_in), ch != c) {
-       if (ch == '\n') {
-               error("newline in string");
-               break;
-       }
-       if (ch == '\\') {
-               ch = getc(db_in);
-               ch = quoted(ch);
-       }
-       buf[len++] = ch;
-  }
-  buf[len++] = 0;
-  tok.str = Salloc(buf, (unsigned) len);
-  return STRING;
-}
-
-static int
-val_in_base(c, base)
-  register int c;
-{
-  return is_dig(c) 
-       ? c - '0'
-       : base != 16
-         ? -1
-         : is_hex(c)
-           ? (c - 'a' + 10) & 017
-           : -1;
-}
-
-int
-get_number(c)
-  register int c;
-{
-  char buf[512+1];
-  register int base = 10;
-  register char *p = &buf[0];
-  register long val = 0;
-  register int val_c;
-
-  if (c == '0') {
-       /* check if next char is an 'x' or an 'X' */
-       c = getc(db_in);
-       if (c == 'x' || c == 'X') {
-               base = 16;
-               c = getc(db_in);
-       }
-       else    base = 8;
-  }
-  while (val_c = val_in_base(c, base), val_c >= 0) {
-       val = val * base + val_c;
-       if (p - buf < 512) *p++ = c;
-       c = getc(db_in);
-  }
-  if (base == 16 || !((c == '.' || c == 'e' || c == 'E'))) {
-       ungetc(c, db_in);
-       tok.ival = val;
-       return INTEGER;
-  }
-  if (c == '.') {
-       if (p - buf < 512) *p++ = c;
-       c = getc(db_in);
-  }
-  while (is_dig(c)) {
-       if (p - buf < 512) *p++ = c;
-       c = getc(db_in);
-  }
-  if (c == 'e' || c == 'E') {
-       if (p - buf < 512) *p++ = c;
-       c = getc(db_in);
-       if (c == '+' || c == '-') {
-               if (p - buf < 512) *p++ = c;
-               c = getc(db_in);
-       }
-       if (! is_dig(c)) {
-               error("malformed floating constant");
-       }
-       while (is_dig(c)) {
-               if (p - buf < 512) *p++ = c;
-               c = getc(db_in);
-       }
-  }
-  ungetc(c, db_in);
-  *p++ = 0;
-  if (p == &buf[512+1]) {
-       error("floating point constant too long");
-  }
-  return REAL;
-}
-
 extern char * symbol2str();
 
 LLmessage(t)
index 3882985..0c545e6 100644 (file)
@@ -156,8 +156,10 @@ const_name(p_symbol cst;)
 :
   '='
   [
+/*
        'b' integer_const(&(cst->sy_const.co_ival))     /* boolean */
-  |
+/*  |
+*/
        'c' integer_const(&(cst->sy_const.co_ival))     /* character */
                                { cst->sy_type = char_type; }
   |
@@ -470,14 +472,17 @@ structure_type(register p_type tp;)
 enum_type(register p_type tp;)
   { register struct literal *litp;
     long maxval = 0;
+    register p_symbol s;
   }
 :
-  [                    { litp = get_literal_space(tp);
-                       }
+  [                    { litp = get_literal_space(tp); }
        name(&(litp->lit_name))
        integer_const(&(litp->lit_val)) ',' 
                        { if (maxval < litp->lit_val) maxval = litp->lit_val;
                          AllowName = 1;
+                         s = NewSymbol(litp->lit_name, CurrentScope, CONST, (struct outname *) 0);
+                         s->sy_const.co_ival = litp->lit_val;
+                         s->sy_type = tp;
                        }
   ]*
   ';'                  { end_literal(tp, maxval); }
diff --git a/util/grind/default.c b/util/grind/default.c
new file mode 100644 (file)
index 0000000..4f9a9e1
--- /dev/null
@@ -0,0 +1,340 @@
+/* $Header$ */
+
+/* Language dependant support; this one is default */
+
+#include <stdio.h>
+#include <alloc.h>
+
+#include "position.h"
+#include "class.h"
+#include "langdep.h"
+#include "Lpars.h"
+#include "idf.h"
+#include "token.h"
+#include "expr.h"
+#include "tree.h"
+#include "operator.h"
+
+extern FILE *db_out, *db_in;
+
+extern int
+       get_name();
+
+extern double
+       atof();
+
+static int
+       print_string(),
+       get_number(),
+       get_string(),
+       get_token(),
+       print_op(),
+       op_prio();
+
+static long
+       array_elsize();
+
+static struct langdep def = {
+       0,
+
+       "%ld",
+       "0%lo",
+       "0x%lX",
+       "%lu",
+       "0x%lX",
+       "%g",
+       "'\\%o'",
+
+       "[",
+       "]",
+       "(",
+       ")",
+       "{",
+       "}",
+
+       print_string,
+       array_elsize,
+       op_prio,
+       get_string,
+       get_name,
+       get_number,
+       get_token,
+       print_op
+};
+
+struct langdep *def_dep = &def;
+
+static int
+print_string(s)
+  char *s;
+{
+  register char        *str = s;
+  int delim = '\'';
+
+  while (*str) {
+       if (*str++ == '\'') delim = '"';
+  }
+  fprintf(db_out, "%c%s%c", delim, s, delim);
+}
+
+extern long    int_size;
+
+static long
+array_elsize(size)
+  long size;
+{
+  if (! (int_size % size)) return size;
+  if (! (size % int_size)) return size;
+  return ((size + int_size - 1) / int_size) * int_size;
+}
+
+/*ARGSUSED*/
+static int
+op_prio(op)
+  int  op;
+{
+  return 1;
+}
+
+static int
+val_in_base(c, base)
+  register int c;
+{
+  return is_dig(c) 
+       ? c - '0'
+       : base != 16
+         ? -1
+         : is_hex(c)
+           ? (c - 'a' + 10) & 017
+           : -1;
+}
+
+static int
+get_number(c)
+  register int c;
+{
+  char buf[512+1];
+  register int base = 10;
+  register char *p = &buf[0];
+  register long val = 0;
+  register int val_c;
+
+  if (c == '0') {
+       /* check if next char is an 'x' or an 'X' */
+       c = getc(db_in);
+       if (c == 'x' || c == 'X') {
+               base = 16;
+               c = getc(db_in);
+       }
+       else    base = 8;
+  }
+  while (val_c = val_in_base(c, base), val_c >= 0) {
+       val = val * base + val_c;
+       if (p - buf < 512) *p++ = c;
+       c = getc(db_in);
+  }
+  if (base == 16 || !((c == '.' || c == 'e' || c == 'E'))) {
+       ungetc(c, db_in);
+       tok.ival = val;
+       return INTEGER;
+  }
+  if (c == '.') {
+       if (p - buf < 512) *p++ = c;
+       c = getc(db_in);
+  }
+  while (is_dig(c)) {
+       if (p - buf < 512) *p++ = c;
+       c = getc(db_in);
+  }
+  if (c == 'e' || c == 'E') {
+       if (p - buf < 512) *p++ = c;
+       c = getc(db_in);
+       if (c == '+' || c == '-') {
+               if (p - buf < 512) *p++ = c;
+               c = getc(db_in);
+       }
+       if (! is_dig(c)) {
+               error("malformed floating constant");
+       }
+       while (is_dig(c)) {
+               if (p - buf < 512) *p++ = c;
+               c = getc(db_in);
+       }
+  }
+  ungetc(c, db_in);
+  *p++ = 0;
+  if (p == &buf[512+1]) {
+       error("floating point constant too long");
+  }
+  tok.fval = atof(buf);
+  return REAL;
+}
+
+static int
+get_token(c)
+  register int c;
+{
+  switch(c) {
+  case '`':
+  case ':':
+  case ',':
+       return c;
+  case '.':
+       return get_number(c);
+  default:
+       error("illegal character 0%o", c);
+       return LLlex();
+  }
+}
+
+static int
+quoted(ch)
+  int  ch;
+{
+  /*   quoted() replaces an escaped character sequence by the
+       character meant.
+  */
+  /* first char after backslash already in ch */
+  if (!is_oct(ch)) {           /* a quoted char */
+       switch (ch) {
+       case 'n':
+               ch = '\n';
+               break;
+       case 't':
+               ch = '\t';
+               break;
+       case 'b':
+               ch = '\b';
+               break;
+       case 'r':
+               ch = '\r';
+               break;
+       case 'f':
+               ch = '\f';
+               break;
+       }
+  }
+  else {                               /* a quoted octal */
+       register int oct = 0, cnt = 0;
+
+       do {
+               oct = oct*8 + (ch-'0');
+               ch = getc(db_in);
+       } while (is_oct(ch) && ++cnt < 3);
+       ungetc(ch, db_in);
+       ch = oct;
+  }
+  return ch&0377;
+
+}
+
+static int 
+get_string(c)
+  int  c;
+{
+  register int ch;
+  char buf[512];
+  register int len = 0;
+
+  while (ch = getc(db_in), ch != c) {
+       if (ch == '\n') {
+               error("newline in string");
+               break;
+       }
+       if (ch == '\\') {
+               ch = getc(db_in);
+               ch = quoted(ch);
+       }
+       buf[len++] = ch;
+  }
+  buf[len++] = 0;
+  tok.str = Salloc(buf, (unsigned) len);
+  return STRING;
+}
+
+static int
+print_op(p)
+  p_tree       p;
+{
+  switch(p->t_oper) {
+  case OP_UNOP:
+       switch(p->t_whichoper) {
+       case E_MIN:
+               fputs("-", db_out);
+               print_node(p->t_args[0], 0);
+               break;
+       case E_PLUS:
+               fputs("+", db_out);
+               print_node(p->t_args[0], 0);
+               break;
+       case E_NOT:
+               fputs("~", db_out);
+               print_node(p->t_args[0], 0);
+               break;
+       case E_DEREF:
+               fputs("*", db_out);
+               print_node(p->t_args[0], 0);
+               break;
+       }
+       break;
+  case OP_BINOP:
+       fputs("(", db_out);
+       print_node(p->t_args[0], 0);
+       switch(p->t_whichoper) {
+       case E_AND:
+               fputs("&&", db_out);
+               break;
+       case E_OR:
+               fputs("||", db_out);
+               break;
+       case E_ZDIV:
+               fputs("/", db_out);
+               break;
+       case E_ZMOD:
+               fputs("%", db_out);
+               break;
+       case E_DIV:
+               fputs(" div ", db_out);
+               break;
+       case E_MOD:
+               fputs(" mod ", db_out);
+               break;
+       case E_IN:
+               fputs(" in ", db_out);
+               break;
+       case E_PLUS:
+               fputs("+", db_out);
+               break;
+       case E_MIN:
+               fputs("-", db_out);
+               break;
+       case E_MUL:
+               fputs("*", db_out);
+               break;
+       case E_EQUAL:
+               fputs("==", db_out);
+               break;
+       case E_NOTEQUAL:
+               fputs("!=", db_out);
+               break;
+       case E_LTEQUAL:
+               fputs("<=", db_out);
+               break;
+       case E_GTEQUAL:
+               fputs(">=", db_out);
+               break;
+       case E_LT:
+               fputs("<", db_out);
+               break;
+       case E_GT:
+               fputs(">", db_out);
+               break;
+       case E_SELECT:
+               fputs(".", db_out);
+               break;
+       }
+       print_node(p->t_args[1], 0);
+       fputs(")", db_out);
+       break;
+  }
+}
index fe786e5..a499b54 100644 (file)
 /* $Header$ */
 
+#include <stdio.h>
+#include <alloc.h>
+#include <assert.h>
+
 #include "position.h"
 #include "operator.h"
 #include "tree.h"
 #include "expr.h"
+#include "symbol.h"
+#include "type.h"
+#include "langdep.h"
+
+extern FILE    *db_out;
+
+static long
+get_int(buf, size)
+  char *buf;
+  long size;
+{
+  switch((int)size) {
+  case 1:
+       return *buf & 0xFF;
+  case 2:
+       return *((short *) buf) & 0xFFFF;
+  default:
+       return *((long *) buf);
+  }
+  /* NOTREACHED */
+}
+
+static double
+get_real(buf, size)
+  char *buf;
+  long size;
+{
+  switch((int) size) {
+  case sizeof(float):
+       return *((float *) buf);
+  default:
+       return *((double *) buf);
+  }
+  /*NOTREACHED*/
+}
+
+static
+put_int(buf, size, value)
+  char *buf;
+  long size;
+  long value;
+{
+  switch((int)size) {
+  case 1:
+       *buf = value;
+       break;
+  case 2:
+       *((short *) buf) = value;
+       break;
+  default:
+       *((long *) buf) = value;
+       break;
+  }
+  /* NOTREACHED */
+}
+
+static
+put_real(buf, size, value)
+  char *buf;
+  long size;
+  double value;
+{
+  switch((int)size) {
+  case sizeof(float):
+       *((float *) buf) = value;
+       break;
+  default:
+       *((double *) buf) = value;
+       break;
+  }
+  /* NOTREACHED */
+}
+
+static int
+convert(pbuf, psize, ptp, tp)
+  char **pbuf;
+  long *psize;
+  p_type *ptp;
+  p_type tp;
+{
+  long l;
+  double d;
+
+  if (*ptp == tp) return 1;
+  if (tp->ty_size > *psize) {
+       *pbuf = Realloc(*pbuf, (unsigned int) tp->ty_size);
+  }
+  if ((*ptp)->ty_class == T_SUBRANGE) *ptp = (*ptp)->ty_base;
+  switch((*ptp)->ty_class) {
+  case T_INTEGER:
+  case T_UNSIGNED:
+  case T_POINTER:
+  case T_ENUM:
+       l = get_int(*pbuf, *psize);
+       if (tp == bool_type) l = l != 0;
+       switch(tp->ty_class) {
+       case T_SUBRANGE:
+       case T_INTEGER:
+       case T_UNSIGNED:
+       case T_POINTER:
+       case T_ENUM:
+               put_int(*pbuf, tp->ty_size, l);
+               *psize = tp->ty_size;
+               *ptp = tp;
+               return 1;
+       case T_REAL:
+               put_real(*pbuf,
+                        tp->ty_size,
+                        (*ptp)->ty_class == T_INTEGER 
+                               ? (double) l
+                               : (double) (unsigned long) l);
+               *psize = tp->ty_size;
+               *ptp = tp;
+               return 1;
+       default:
+               break;
+       }
+       break;
+  case T_REAL:
+       d = get_real(*pbuf, *psize);
+       switch(tp->ty_class) {
+       case T_ENUM:
+       case T_SUBRANGE:
+       case T_INTEGER:
+       case T_UNSIGNED:
+       case T_POINTER:
+               if (tp == bool_type) put_int(*pbuf, tp->ty_size, (long) (d != 0));
+               else put_int(*pbuf, tp->ty_size, (long) d);
+               *psize = tp->ty_size;
+               *ptp = tp;
+               return 1;
+       case T_REAL:
+               put_real(*pbuf, tp->ty_size, d);
+               *psize = tp->ty_size;
+               *ptp = tp;
+               return 1;
+       default:
+               break;
+       }
+       break;
+  default:
+       break;
+  }
+  error("illegal conversion");
+  return 0;
+}
 
 int
 eval_cond(p)
   p_tree       p;
 {
-  /* to be written !!! */
-  return 1;
+  char *buf;
+  long size;
+  p_type tp;
+  long val;
+
+  if (eval_expr(p, &buf, &size, &tp)) {
+       if (convert(&buf, &size, &tp, currlang->has_bool_type ? bool_type : int_type)) {
+               val = get_int(buf, size);
+               if (buf) free(buf);
+               return (int) val;
+       }
+       if (buf) free(buf);
+  }
+  return 0;
+}
+
+static int
+do_not(p, pbuf, psize, ptp)
+  p_tree       p;
+  char         **pbuf;
+  long         *psize;
+  p_type       *ptp;
+{
+  if (eval_expr(p->t_args[0], pbuf, psize, ptp) &&
+      convert(pbuf, psize, ptp, currlang->has_bool_type ? bool_type : int_type)) {
+       put_int(*pbuf, *psize, (long) !get_int(*pbuf, *psize));
+       return 1;
+  }
+  return 0;
+}
+
+static int
+do_deref(p, pbuf, psize, ptp)
+  p_tree       p;
+  char         **pbuf;
+  long         *psize;
+  p_type       *ptp;
+{
+  char *addr;
+
+  if (eval_expr(p->t_args[0], pbuf, psize, ptp)) {
+       switch((*ptp)->ty_class) {
+       case T_POINTER:
+               addr = *((char **) (*pbuf));
+               free(*pbuf);
+               *ptp = (*ptp)->ty_ptrto;
+               *psize = (*ptp)->ty_size;
+               *pbuf = Malloc((unsigned) (*ptp)->ty_size);
+               if (! get_bytes(*psize, (t_addr) addr, *pbuf)) {
+                       error("could not get value");
+                       break;
+               }
+               return 1;
+       default:
+               error("illegal operand of DEREF");
+               break;
+       }
+  }
+  return 0;
+}
+
+static int
+do_unmin(p, pbuf, psize, ptp)
+  p_tree       p;
+  char         **pbuf;
+  long         *psize;
+  p_type       *ptp;
+{
+  if (eval_expr(p->t_args[0], pbuf, psize, ptp)) {
+       switch((*ptp)->ty_class) {
+       case T_SUBRANGE:
+       case T_INTEGER:
+       case T_ENUM:
+       case T_UNSIGNED:
+               put_int(*pbuf, *psize, -get_int(*pbuf, *psize));
+               return 1;
+       case T_REAL:
+               put_real(*pbuf, *psize, -get_real(*pbuf, *psize));
+               return 1;
+       default:
+               error("illegal operand of unary -");
+               break;
+       }
+  }
+  return 0;
+}
+
+static int
+do_unplus(p, pbuf, psize, ptp)
+  p_tree       p;
+  char         **pbuf;
+  long         *psize;
+  p_type       *ptp;
+{
+  if (eval_expr(p->t_args[0], pbuf, psize, ptp)) {
+       switch((*ptp)->ty_class) {
+       case T_SUBRANGE:
+       case T_INTEGER:
+       case T_ENUM:
+       case T_UNSIGNED:
+       case T_REAL:
+               return 1;
+       default:
+               error("illegal operand of unary +");
+               break;
+       }
+  }
+  return 0;
+}
+
+static int (*un_op[])() = {
+  0,
+  do_not,
+  do_deref,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  do_unplus,
+  do_unmin,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0
+};
+
+static p_type
+balance(tp1, tp2)
+  p_type       tp1, tp2;
+{
+
+  if (tp1->ty_class == T_SUBRANGE) tp1 = tp1->ty_base;
+  if (tp2->ty_class == T_SUBRANGE) tp2 = tp2->ty_base;
+  if (tp1 == tp2) return tp2;
+  if (tp2->ty_class == T_REAL) {
+       p_type tmp = tp1; tp1 = tp2; tp2 = tmp;
+  }
+  if (tp1->ty_class == T_REAL) {
+       switch(tp2->ty_class) {
+       case T_INTEGER:
+       case T_UNSIGNED:
+       case T_ENUM:
+               return tp1;
+       case T_REAL:
+               return tp1->ty_size > tp2->ty_size ? tp1 : tp2;
+       default:
+               error("illegal type combination");
+               return 0;
+       }
+  }
+  if (tp2->ty_class == T_POINTER) {
+       p_type tmp = tp1; tp1 = tp2; tp2 = tmp;
+  }
+  if (tp1->ty_class == T_POINTER) {
+       switch(tp2->ty_class) {
+       case T_INTEGER:
+       case T_UNSIGNED:
+       case T_POINTER:
+       case T_ENUM:
+               return tp1;
+       default:
+               error("illegal type combination");
+               return 0;
+       }
+  }
+  if (tp2->ty_class == T_UNSIGNED) {
+       p_type tmp = tp1; tp1 = tp2; tp2 = tmp;
+  }
+  if (tp1->ty_class == T_UNSIGNED) {
+       switch(tp2->ty_class) {
+       case T_INTEGER:
+       case T_UNSIGNED:
+               if (tp1->ty_size >= tp2->ty_size) return tp1;
+               return tp2;
+       case T_ENUM:
+               return tp1;
+       default:
+               error("illegal type combination");
+               return 0;
+       }
+  }
+  if (tp2->ty_class == T_INTEGER) {
+       p_type tmp = tp1; tp1 = tp2; tp2 = tmp;
+  }
+  if (tp1->ty_class == T_INTEGER) {
+       switch(tp2->ty_class) {
+       case T_INTEGER:
+               if (tp1->ty_size >= tp2->ty_size) return tp1;
+               return tp2;
+       case T_ENUM:
+               return tp1;
+       default:
+               error("illegal type combination");
+               return 0;
+       }
+  }
+  error("illegal type combination");
+  return 0;
+}
+
+static int
+do_andor(p, pbuf, psize, ptp)
+  p_tree       p;
+  char         **pbuf;
+  long         *psize;
+  p_type       *ptp;
+{
+  long         l1, l2;
+  char         *buf;
+  long         size;
+  p_type       tp;
+
+  if (eval_expr(p->t_args[0], pbuf, psize, ptp) &&
+      convert(pbuf, psize, ptp, currlang->has_bool_type ? bool_type : int_type) &&
+      eval_expr(p->t_args[1], &buf, &size, &tp) &&
+      convert(&buf, &size, &tp, currlang->has_bool_type ? bool_type : int_type)) {
+       l1 = get_int(*pbuf, *psize);
+       l2 = get_int(buf, size);
+       put_int(*pbuf,
+               *psize,
+               p->t_whichoper == E_AND 
+                       ? (long)(l1 && l2) 
+                       : (long)(l1 || l2));
+       free(buf);
+       return 1;
+  }
+  free(buf);
+  return 0;
+}
+
+static int
+do_arith(p, pbuf, psize, ptp)
+  p_tree       p;
+  char         **pbuf;
+  long         *psize;
+  p_type       *ptp;
+{
+  long         l1, l2;
+  double       d1, d2;
+  char         *buf = 0;
+  long         size;
+  p_type       tp, balance_tp;
+
+  if (eval_expr(p->t_args[0], pbuf, psize, ptp) &&
+      eval_expr(p->t_args[1], &buf, &size, &tp) &&
+      (balance_tp = balance(*ptp, tp)) &&
+      convert(pbuf, psize, ptp, balance_tp) &&
+      convert(&buf, &size, &tp, balance_tp)) {
+       switch(balance_tp->ty_class) {
+       case T_INTEGER:
+       case T_ENUM:
+       case T_UNSIGNED:
+               l1 = get_int(*pbuf, *psize);
+               l2 = get_int(buf, size);
+               free(buf);
+               buf = 0;
+               switch(p->t_whichoper) {
+               case E_PLUS:
+                       l1 += l2;
+                       break;
+               case E_MIN:
+                       l1 -= l2;
+                       break;
+               case E_MUL:
+                       l1 *= l2;
+                       break;
+               case E_DIV:
+               case E_ZDIV:
+                       if (! l2) {
+                               error("division by 0");
+                               return 0;
+                       }
+                       if (balance_tp->ty_class == T_INTEGER) {
+                               if ((l1 < 0) != (l2 < 0)) {
+                                       if (l1 < 0) l1 = - l1;
+                                       else l2 = -l2;
+                                       if (p->t_whichoper == E_DIV) {
+                                           l1 = -((l1+l2-1)/l2);
+                                       }
+                                       else {
+                                           l1 = -(l1/l2);
+                                       }
+                               }
+                               else l1 /= l2;
+                       }
+                       else l1 = (unsigned long) l1 /
+                                 (unsigned long) l2;
+                       break;
+               case E_MOD:
+               case E_ZMOD:
+                       if (! l2) {
+                               error("modulo by 0");
+                               return 0;
+                       }
+                       if (balance_tp->ty_class == T_INTEGER) {
+                               if ((l1 < 0) != (l2 < 0)) {
+                                       if (l1 < 0) l1 = - l1;
+                                       else l2 = -l2;
+                                       if (p->t_whichoper == E_MOD) {
+                                           l1 = ((l1+l2-1)/l2)*l2 - l1;
+                                       }
+                                       else {
+                                           l1 = (l1/l2)*l2 - l1;
+                                       }
+                               }
+                               else l1 %= l2;
+                       }
+                       else l1 = (unsigned long) l1 %
+                                 (unsigned long) l2;
+                       break;
+               }
+               put_int(*pbuf, *psize, l1);
+               break;
+       case T_REAL:
+               d1 = get_real(*pbuf, *psize);
+               d2 = get_real(buf, size);
+               free(buf);
+               buf = 0;
+               switch(p->t_whichoper) {
+               case E_DIV:
+               case E_ZDIV:
+                       if (d2 == 0.0) {
+                               error("division by 0.0");
+                               return 0;
+                       }
+                       d1 /= d2;
+                       break;
+               case E_PLUS:
+                       d1 += d2;
+                       break;
+               case E_MIN:
+                       d1 -= d2;
+                       break;
+               case E_MUL:
+                       d1 *= d2;
+                       break;
+               }
+               put_real(*pbuf, *psize, d1);
+               break;
+       default:
+               error("illegal operand type(s)");
+               free(buf);
+               return 0;
+       }
+       return 1;
+  }
+  if (buf) free(buf);
+  return 0;
+}
+
+static int
+do_cmp(p, pbuf, psize, ptp)
+  p_tree       p;
+  char         **pbuf;
+  long         *psize;
+  p_type       *ptp;
+{
+  long         l1, l2;
+  double       d1, d2;
+  char         *buf = 0;
+  long         size;
+  p_type       tp, balance_tp;
+
+  if (eval_expr(p->t_args[0], pbuf, psize, ptp) &&
+      eval_expr(p->t_args[1], &buf, &size, &tp) &&
+      (balance_tp = balance(*ptp, tp)) &&
+      convert(pbuf, psize, ptp, balance_tp) &&
+      convert(&buf, &size, &tp, balance_tp)) {
+       switch(balance_tp->ty_class) {
+       case T_INTEGER:
+       case T_ENUM:
+       case T_UNSIGNED:
+       case T_POINTER:
+               l1 = get_int(*pbuf, *psize);
+               l2 = get_int(buf, size);
+               free(buf);
+               buf = 0;
+               switch(p->t_whichoper) {
+               case E_EQUAL:
+                       l1 = l1 == l2;
+                       break;
+               case E_NOTEQUAL:
+                       l1 = l1 != l2;
+                       break;
+               case E_LTEQUAL:
+                       if (balance_tp->ty_class == T_INTEGER) {
+                               l1 = l1 <= l2;
+                       }
+                       else    l1 = (unsigned long) l1 <=
+                                    (unsigned long) l2;
+                       break;
+               case E_LT:
+                       if (balance_tp->ty_class == T_INTEGER) {
+                               l1 = l1 < l2;
+                       }
+                       else    l1 = (unsigned long) l1 <
+                                    (unsigned long) l2;
+                       break;
+               case E_GTEQUAL:
+                       if (balance_tp->ty_class == T_INTEGER) {
+                               l1 = l1 >= l2;
+                       }
+                       else    l1 = (unsigned long) l1 >=
+                                    (unsigned long) l2;
+                       break;
+               case E_GT:
+                       if (balance_tp->ty_class == T_INTEGER) {
+                               l1 = l1 > l2;
+                       }
+                       else    l1 = (unsigned long) l1 >
+                                    (unsigned long) l2;
+                       break;
+               }
+               break;
+       case T_REAL:
+               d1 = get_real(*pbuf, *psize);
+               d2 = get_real(buf, size);
+               free(buf);
+               buf = 0;
+               switch(p->t_whichoper) {
+               case E_EQUAL:
+                       l1 = d1 == d2;
+                       break;
+               case E_NOTEQUAL:
+                       l1 = d1 != d2;
+                       break;
+               case E_LTEQUAL:
+                       l1 = d1 <= d2;
+                       break;
+               case E_LT:
+                       l1 = d1 < d2;
+                       break;
+               case E_GTEQUAL:
+                       l1 = d1 >= d2;
+                       break;
+               case E_GT:
+                       l1 = d1 > d2;
+                       break;
+               }
+               break;
+       }
+       if (*psize < int_size) {
+               *psize = int_size;
+               free(*pbuf);
+               *pbuf = Malloc((unsigned int) int_size);
+       }
+       else    *psize = int_size;
+       if (currlang->has_bool_type) {
+               *ptp = bool_type;
+       }
+       else    *ptp = int_type;
+       put_int(*pbuf, *psize, l1);
+       return 1;
+  }
+  if (buf) free(buf);
+  return 0;
+}
+
+static int
+do_in(p, pbuf, psize, ptp)
+  p_tree       p;
+  char         **pbuf;
+  long         *psize;
+  p_type       *ptp;
+{
+  long         l;
+  char         *buf = 0;
+  long         size;
+  p_type       tp;
+
+  error("IN not implemented");         /* ??? */
+  return 0;
+}
+
+static int
+do_array(p, pbuf, psize, ptp)
+  p_tree       p;
+  char         **pbuf;
+  long         *psize;
+  p_type       *ptp;
+{
+  long         l;
+  char         *buf = 0;
+  long         size;
+  p_type       tp;
+
+  error("[ not implemented");  /* ??? */
+  return 0;
+}
+
+static int
+do_select(p, pbuf, psize, ptp)
+  p_tree       p;
+  char         **pbuf;
+  long         *psize;
+  p_type       *ptp;
+{
+  long         l;
+  char         *buf = 0;
+  long         size;
+  p_type       tp;
+
+  error("SELECT not implemented");     /* ??? */
+  return 0;
+}
+
+static int (*bin_op[])() = {
+  0,
+  0,
+  0,
+  do_andor,
+  do_andor,
+  do_arith,
+  do_arith,
+  do_arith,
+  do_arith,
+  do_in,
+  do_array,
+  do_arith,
+  do_arith,
+  do_arith,
+  do_cmp,
+  do_cmp,
+  do_cmp,
+  do_cmp,
+  do_cmp,
+  do_cmp,
+  do_select
+};
+
+int
+eval_expr(p, pbuf, psize, ptp)
+  p_tree       p;
+  char         **pbuf;
+  long         *psize;
+  p_type       *ptp;
+{
+  register p_symbol    sym;
+  int  retval = 0;
+
+  switch(p->t_oper) {
+  case OP_NAME:
+  case OP_SELECT:
+       sym = identify(p, VAR|REGVAR|LOCVAR|VARPAR|CONST);
+       if (! sym) return 0;
+       if (! get_value(sym, pbuf, psize)) {
+               print_node(p, 0);
+               fputs(" currently not available\n", db_out);
+               break;
+       }
+       *ptp = sym->sy_type;
+       retval = 1;
+       break;
+
+  case OP_INTEGER:
+       *pbuf = Malloc(sizeof(long));
+       *psize = sizeof(long);
+       *ptp = long_type;
+       *((long *) (*pbuf)) = p->t_ival;
+       retval = 1;
+       break;
+
+  case OP_REAL:
+       *pbuf = Malloc(sizeof(double));
+       *psize = sizeof(double);
+       *ptp = double_type;
+       *((double *) (*pbuf)) = p->t_fval;
+       retval = 1;
+       break;
+
+  case OP_STRING:
+       *pbuf = Malloc(sizeof(char *));
+       *psize = sizeof(char *);
+       *ptp = string_type;
+       *((char **) (*pbuf)) = p->t_sval;
+       retval = 1;
+       break;
+
+  case OP_UNOP:
+       retval = (*un_op[p->t_whichoper])(p, pbuf, psize, ptp);
+       break;
+
+  case OP_BINOP:
+       retval = (*bin_op[p->t_whichoper])(p, pbuf, psize, ptp);
+       break;
+  default:
+       assert(0);
+       break;
+  }
+  if (! retval) {
+       if (*pbuf) {
+               free(*pbuf);
+               *pbuf = 0;
+       }
+       *psize = 0;
+  }
+  return retval;
 }
diff --git a/util/grind/expr.h b/util/grind/expr.h
new file mode 100644 (file)
index 0000000..dea4577
--- /dev/null
@@ -0,0 +1,28 @@
+/* $Header$ */
+
+/* expression operators. Do not change values, as they are used as
+   indices into arrays.
+*/
+
+#define E_NOT  1
+#define E_DEREF        2
+#define E_AND  3
+#define E_OR   4
+#define E_DIV  5               /* equal to truncated quotient */
+#define E_MOD  6               /* x = (x E_DIV y) * y + x E_MOD y,
+                                  0 <= (x E_MOD y) < y
+                               */
+#define E_ZDIV 7               /* quotient rounded to 0 */
+#define E_ZMOD 8               /* remainder of E_ZDIV */
+#define E_IN   9               /* set membership */
+#define E_ARRAY        10
+#define E_PLUS 11
+#define E_MIN  12
+#define E_MUL  13
+#define E_EQUAL        14
+#define E_NOTEQUAL 15
+#define E_LTEQUAL 16
+#define E_GTEQUAL 17
+#define E_LT   18
+#define E_GT   19
+#define E_SELECT 20
index 930de6a..2dc5253 100644 (file)
@@ -44,4 +44,7 @@ find_language(suff)
        if (! strcmp(p->l_suff, suff)) break;
        p = p->l_next;
   }
+  if (! currlang) {
+       currlang = def_dep;
+  }
 }
index b6a3792..e641ce2 100644 (file)
@@ -3,6 +3,9 @@
 /* language-dependent routines and formats, together in one structure: */
 
 struct langdep {
+  /* language info: */
+  int  has_bool_type;          /* set if language has a boolean type */
+
   /* formats (for fprintf): */
   char *decint_fmt;            /* decimal ints (format for long) */
   char *octint_fmt;            /* octal ints (format for long) */
@@ -28,9 +31,10 @@ struct langdep {
   int  (*get_name)();
   int  (*get_number)();
   int  (*get_token)();
+  int  (*printop)();
 };
 
-extern struct langdep  *m2_dep, *currlang;
+extern struct langdep  *m2_dep, *def_dep, *currlang;
 
 extern int find_language();
 
index ee59684..c1b4342 100644 (file)
@@ -12,6 +12,7 @@ static        line_positions();
 extern char    *dirs[];
 extern FILE    *fopen();
 extern FILE    *db_out;
+extern t_lineno        currline;
 #define        window_size     21
 
 static int
@@ -103,7 +104,7 @@ lines(file, l1, l2)
   for (n = l1; n <= l2; n++) {
        register int    c;
 
-       fprintf(db_out, "%6d  ", n);
+       fprintf(db_out, "%c%5d\t", n == currline ? '>' : ' ', n);
        do {
                c = getc(f);
                if (c != EOF) putc(c, db_out);
index b494912..00ea429 100644 (file)
@@ -3,19 +3,21 @@
 /* Language dependant support; this one is for Modula-2 */
 
 #include <stdio.h>
+#include <alloc.h>
+#include <assert.h>
 
+#include "position.h"
 #include "class.h"
 #include "langdep.h"
 #include "Lpars.h"
 #include "idf.h"
 #include "token.h"
 #include "expr.h"
+#include "tree.h"
+#include "operator.h"
 
 extern FILE *db_out, *db_in;
 
-extern int
-       get_string();
-
 extern double
        atof();
 
@@ -24,12 +26,16 @@ static int
        get_number(),
        get_name(),
        get_token(),
+       get_string(),
+       print_op(),
        op_prio();
 
 static long
        array_elsize();
 
 static struct langdep m2 = {
+       1,
+
        "%ld",
        "%loB",
        "%lXH",
@@ -51,7 +57,8 @@ static struct langdep m2 = {
        get_string,
        get_name,
        get_number,
-       get_token
+       get_token,
+       print_op
 };
 
 struct langdep *m2_dep = &m2;
@@ -84,7 +91,33 @@ static int
 op_prio(op)
   int  op;
 {
-  /* ??? to be written ??? */
+  switch(op) {
+  case E_NOT:
+       return 5;
+
+  case E_SELECT:
+       return 9;
+
+  case E_AND:
+  case E_MUL:
+  case E_DIV:
+  case E_MOD:
+       return 4;
+
+  case E_PLUS:
+  case E_MIN:
+  case E_OR:
+       return 3;
+
+  case E_IN:
+  case E_EQUAL:
+  case E_NOTEQUAL:
+  case E_LTEQUAL:
+  case E_GTEQUAL:
+  case E_LT:
+  case E_GT:
+       return 2;
+  }
   return 1;
 }
 
@@ -371,3 +404,104 @@ get_token(c)
        return LLlex();
   }
 }
+
+static int 
+get_string(c)
+  int  c;
+{
+  register int ch;
+  char buf[512];
+  register int len = 0;
+
+  while (ch = getc(db_in), ch != c) {
+       if (ch == '\n') {
+               error("newline in string");
+               break;
+       }
+       buf[len++] = ch;
+  }
+  buf[len++] = 0;
+  tok.str = Salloc(buf, (unsigned) len);
+  return STRING;
+}
+
+static int
+print_op(p)
+  p_tree       p;
+{
+  switch(p->t_oper) {
+  case OP_UNOP:
+       switch(p->t_whichoper) {
+       case E_MIN:
+               fputs("-", db_out);
+               print_node(p->t_args[0], 0);
+               break;
+       case E_PLUS:
+               fputs("+", db_out);
+               print_node(p->t_args[0], 0);
+               break;
+       case E_NOT:
+               fputs("~", db_out);
+               print_node(p->t_args[0], 0);
+               break;
+       case E_DEREF:
+               print_node(p->t_args[0], 0);
+               fputs("^", db_out);
+               break;
+       }
+       break;
+  case OP_BINOP:
+       fputs("(", db_out);
+       print_node(p->t_args[0], 0);
+       switch(p->t_whichoper) {
+       case E_AND:
+               fputs("&", db_out);
+               break;
+       case E_OR:
+               fputs("|", db_out);
+               break;
+       case E_DIV:
+               fputs("/", db_out);
+               break;
+       case E_MOD:
+               fputs(" MOD ", db_out);
+               break;
+       case E_IN:
+               fputs(" IN ", db_out);
+               break;
+       case E_PLUS:
+               fputs("+", db_out);
+               break;
+       case E_MIN:
+               fputs("-", db_out);
+               break;
+       case E_MUL:
+               fputs("*", db_out);
+               break;
+       case E_EQUAL:
+               fputs("=", db_out);
+               break;
+       case E_NOTEQUAL:
+               fputs("#", db_out);
+               break;
+       case E_LTEQUAL:
+               fputs("<=", db_out);
+               break;
+       case E_GTEQUAL:
+               fputs(">=", db_out);
+               break;
+       case E_LT:
+               fputs("<", db_out);
+               break;
+       case E_GT:
+               fputs(">", db_out);
+               break;
+       case E_SELECT:
+               fputs(".", db_out);
+               break;
+       }
+       print_node(p->t_args[1], 0);
+       fputs(")", db_out);
+       break;
+  }
+}
index dc8eaa4..287dda7 100644 (file)
@@ -176,10 +176,10 @@ print_val(tp, tp_sz, addr, compressed, indent)
        for (i = tp->ty_nfields; i; i--, fld++) {
                long sz = fld->fld_type->ty_size;
                if (! compressed) fprintf(db_out, "%s = ", fld->fld_name);
-               if (fld->fld_bitsize != sz << 3) {
+               if (fld->fld_bitsize < sz << 3) {
                        /* apparently a bit field */
                        /* ??? */
-                       fprintf(db_out, "<bitfield, %d, %d>", fld->fld_bitsize, fld->fld_type->ty_size);
+                       fprintf(db_out, "<bitfield, %d, %ld>", fld->fld_bitsize, sz);
                }
                else print_val(fld->fld_type, sz, addr+(fld->fld_pos>>3), compressed, indent);
                if (compressed && i > 1) {
index 51771ff..a034e76 100644 (file)
@@ -15,6 +15,7 @@
 #include       "scope.h"
 #include       "symbol.h"
 #include       "langdep.h"
+#include       "type.h"
 
 extern FILE    *db_out;
 extern t_lineno        currline;
@@ -210,13 +211,17 @@ print_node(p, top_level)
        fputs(p->t_str, db_out);
        break;
   case OP_INTEGER:
-       fprintf(db_out, "%d", p->t_ival);
+       fprintf(db_out, currlang->decint_fmt, p->t_ival);
        break;
   case OP_STRING:
-       fprintf(db_out, "%s", p->t_sval);
+       (*currlang->printstring)(p->t_sval);
        break;
   case OP_REAL:
-       fprintf(db_out, "%.14g", p->t_fval);
+       fprintf(db_out, currlang->real_fmt, p->t_fval);
+       break;
+  case OP_UNOP:
+  case OP_BINOP:
+       (*currlang->printop)(p);
        break;
   }
   if (top_level) fputs("\n", db_out);
@@ -263,8 +268,8 @@ do_list(p)
 {
   if (currfile) {
        lines(currfile->sy_file,
-             p->t_args[0] ? (int) p->t_args[0]->t_ival : (int) currline,
-             p->t_args[1] ? (int) p->t_args[1]->t_ival : (int) currline+9);
+             p->t_args[0] ? (int) p->t_args[0]->t_ival : (int) currline-4,
+             p->t_args[1] ? (int) p->t_args[1]->t_ival : (int) currline+5);
        currline = p->t_args[1] ? p->t_args[1]->t_ival + 1 : currline + 10;
   }
   else fprintf(db_out, "no current file\n");
@@ -535,7 +540,9 @@ do_delete(p)
 do_print(p)
   p_tree       p;
 {
-  p_symbol sym;
+  char *buf;
+  long size;
+  p_type tp;
 
   switch(p->t_oper) {
   case OP_PRINT:
@@ -545,15 +552,14 @@ do_print(p)
        do_print(p->t_args[0]);
        do_print(p->t_args[1]);
        break;
-  case OP_NAME:
-  case OP_SELECT:
-       sym = identify(p, VAR|REGVAR|LOCVAR|VARPAR|CONST);
-       if (! sym) return;
+  default:
+       if (! eval_expr(p, &buf, &size, &tp)) return;
        print_node(p, 0);
-       if (! print_sym(sym)) {
-               fputs(" currently not available\n", db_out);
-               break;
-       }
+       fputs(" = ", db_out);
+       print_val(tp, size, buf, 0, 0);
+       if (buf) free(buf);
+       fputs("\n", db_out);
+       break;
   }
 }
 
index 111f1f4..85730a9 100644 (file)
@@ -12,7 +12,7 @@
 #include "message.h"
 #include "langdep.h"
 
-p_type int_type, char_type, short_type, long_type;
+p_type int_type, char_type, short_type, long_type, bool_type;
 p_type uint_type, uchar_type, ushort_type, ulong_type;
 p_type void_type, incomplete_type;
 p_type float_type, double_type;
@@ -49,7 +49,7 @@ struct integer_types {
 };
 
 static struct integer_types i_types[4];
-static struct integer_types u_types[5];
+static struct integer_types u_types[4];
 
 #define ufit(n, nb)    Xfit(n, nb, ubounds)
 #define ifit(n, nb)    Xfit(n, nb, ibounds)
@@ -76,10 +76,14 @@ subrange_type(A, base_index, c1, c2, result_index)
                        return void_type;
                }
 
-               /* c1 = 0 and c2 = 127 -> char ??? */
-               if (c1 == 0 && c2 == 127) {
+               if ((c1 == 0 || c1 == -128) && c2 == 127) {
                        return char_type;
                }
+
+               if (c1 == 0 && c2 == 255) {
+                       return uchar_type;
+               }
+
                itself = 1;
        }
   }
@@ -242,7 +246,6 @@ init_types()
   u_types[0].maxval = max_uns[(int)int_size]; u_types[0].type = uint_type;
   u_types[1].maxval = max_uns[(int)short_size]; u_types[1].type = ushort_type;
   u_types[2].maxval = max_uns[(int)long_size]; u_types[2].type = ulong_type;
-  u_types[3].maxval = max_uns[1]; u_types[3].type = uchar_type;
 }
 
 /*
@@ -323,6 +326,7 @@ end_literal(tp, maxval)
   if (ufit(maxval, 1)) tp->ty_size = 1;
   else if (ufit(maxval, (int)short_size)) tp->ty_size = short_size;
   else tp->ty_size = int_size;
+  if (! bool_type) bool_type = tp;
 }
 
 long
index 0ddc228..54816aa 100644 (file)
@@ -112,7 +112,8 @@ extern long
        param_size(),
        compute_size();
 
-extern p_type  char_type, uchar_type,
+extern p_type  char_type, uchar_type, bool_type, int_type,
                long_type, double_type, string_type;
 extern p_type  void_type, incomplete_type;
+extern long    int_size;
 
index f9896e4..205b31d 100644 (file)
@@ -46,10 +46,10 @@ get_value(sym, buf, psize)
        }
        break;
   case CONST:
-       *buf = Malloc((unsigned) tp->ty_size);
+       *buf = Malloc((unsigned) size);
        switch(tp->ty_class) {
        case T_REAL:
-               if (tp->ty_size != sizeof(double)) {
+               if (size != sizeof(double)) {
                        *((float *) *buf) = sym->sy_const.co_rval;
                }
                else    *((double *) *buf) = sym->sy_const.co_rval;
@@ -58,10 +58,10 @@ get_value(sym, buf, psize)
        case T_SUBRANGE:
        case T_UNSIGNED:
        case T_ENUM:
-               if (tp->ty_size == 1) {
+               if (size == 1) {
                        *((char *) *buf) = sym->sy_const.co_ival;
                }
-               else if (tp->ty_size == 2) {
+               else if (size == 2) {
                        *((short *) *buf) = sym->sy_const.co_ival;
                }
                else {
@@ -69,10 +69,10 @@ get_value(sym, buf, psize)
                }
                break;
        case T_SET:
-               memcpy(*buf, sym->sy_const.co_setval, (int) tp->ty_size);
+               memcpy(*buf, sym->sy_const.co_setval, (int) size);
                break;
        case T_STRING:
-               memcpy(*buf, sym->sy_const.co_sval, (int) tp->ty_size);
+               memcpy(*buf, sym->sy_const.co_sval, (int) size);
                break;
        default:
                fatal("strange constant");
@@ -140,7 +140,6 @@ get_value(sym, buf, psize)
                }
        }
        *buf = Malloc((unsigned) size);
-       *psize = size;
        if (get_bytes(size,
                      (t_addr) BUFTOA(AB+sym->sy_name.nm_value),
                      *buf)) {
@@ -155,6 +154,7 @@ get_value(sym, buf, psize)
        *buf = 0;
        *psize = 0;
   }
+  else *psize = size;
 
   return retval;
 }