#include "globals.h"
#include "errwarn.h"
+#include "floatnum.h"
#include "expr.h"
#include "bytecode.h"
+#include "section.h"
RCSID("$IdPath$");
ptr = &im_static;
/* FIXME: this will leak expr's if static is used */
- ptr->val = expr_new_ident(EXPR_NUM, ExprNum(int_val));
+ ptr->val = expr_new_ident(EXPR_INT, ExprInt(int_val));
if ((int_val & 0xFF) == int_val)
ptr->len = 1;
return bc;
}
+int
+bytecode_get_offset(section *sect, bytecode *bc, unsigned long *ret_val)
+{
+ return 0; /* TODO */
+}
+
void
bytecode_print(bytecode *bc)
{
printf("Offset=%lx BITS=%u\n", bc->offset, bc->mode_bits);
}
-void
+bytecode *
bytecodes_append(bytecodehead *headp, bytecode *bc)
{
if (bc) {
- if (bc->type != BC_EMPTY)
+ if (bc->type != BC_EMPTY) {
STAILQ_INSERT_TAIL(headp, bc, link);
- else
+ return bc;
+ } else {
free(bc);
+ }
}
+ return (bytecode *)NULL;
}
dataval *
}
dataval *
-dataval_new_float(double float_val)
+dataval_new_float(floatnum *flt)
{
dataval *retval = malloc(sizeof(dataval));
Fatal(FATAL_NOMEM);
retval->type = DV_FLOAT;
- retval->data.float_val = float_val;
+ retval->data.flt = flt;
return retval;
}
printf("\n");
break;
case DV_FLOAT:
- printf(" Float=%e\n", cur->data.float_val);
+ printf(" Float=");
+ floatnum_print(cur->data.flt);
+ printf("\n");
break;
case DV_STRING:
printf(" String=%s\n", cur->data.str_val);
#ifndef YASM_BYTECODE_H
#define YASM_BYTECODE_H
+struct section_s;
+
typedef struct effaddr_s {
struct expr_s *disp; /* address displacement */
unsigned char len; /* length of disp (in bytes), 0 if none */
union {
struct expr_s *exp;
- double float_val;
+ struct floatnum_s *flt;
char *str_val;
} data;
} dataval;
bytecode *bytecode_new_reserve(struct expr_s *numitems,
unsigned long itemsize);
+/* Gets the offset of the bytecode specified by bc if possible.
+ * Return value is IF POSSIBLE, not the value.
+ */
+int bytecode_get_offset(struct section_s *sect, bytecode *bc,
+ unsigned long *ret_val);
+
void bytecode_print(bytecode *bc);
/* void bytecodes_initialize(bytecodehead *headp); */
/* Adds bc to the list of bytecodes headp.
* NOTE: Does not make a copy of bc; so don't pass this function
* static or local variables, and discard the bc pointer after calling
- * this function.
+ * this function. If bc was actually appended (it wasn't NULL or empty),
+ * then returns bc, otherwise returns NULL.
*/
-void bytecodes_append(bytecodehead *headp, bytecode *bc);
+bytecode *bytecodes_append(bytecodehead *headp, bytecode *bc);
dataval *dataval_new_expr(struct expr_s *exp);
-dataval *dataval_new_float(double float_val);
+dataval *dataval_new_float(struct floatnum_s *flt);
dataval *dataval_new_string(char *str_val);
void dataval_print(datavalhead *head);
/* $IdPath$
* Expression handling
*
- * Copyright (C) 2001 Michael Urman
+ * Copyright (C) 2001 Michael Urman, Peter Johnson
*
* This file is part of YASM.
*
#include "globals.h"
#include "errwarn.h"
+#include "floatnum.h"
#include "expr.h"
#include "symrec.h"
ptr->op = op;
ptr->rtype = rtype;
switch (ltype) {
- case EXPR_NUM:
case EXPR_SYM:
case EXPR_EXPR:
+ case EXPR_INT:
+ case EXPR_FLOAT:
memcpy(&ptr->left, &left, sizeof(ExprItem));
break;
case EXPR_NONE:
break;
}
switch (rtype) {
- case EXPR_NUM:
case EXPR_SYM:
case EXPR_EXPR:
+ case EXPR_INT:
+ case EXPR_FLOAT:
memcpy(&ptr->right, &right, sizeof(ExprItem));
break;
case EXPR_NONE:
ExprExpr(expr *x)
{
ExprItem e;
- e.expr = x;
+ e.exp = x;
return e;
}
ExprItem
-ExprNum(unsigned long n)
+ExprInt(unsigned long i)
{
ExprItem e;
- e.num = n;
+ e.int_val = i;
+ return e;
+}
+
+ExprItem
+ExprFloat(floatnum *f)
+{
+ ExprItem e;
+
+ e.flt = f;
return e;
}
{
ExprItem e;
- e.num = 0;
+ e.int_val = 0;
return e;
}
expr_simplify(expr *e)
{
int simplified = 0;
+ unsigned long int_val;
/* try to simplify the left side */
if (e->ltype == EXPR_EXPR) {
/* if the left subexpr isn't an IDENT, recurse simplification */
- if (e->left.expr->op != EXPR_IDENT)
- simplified |= expr_simplify(e->left.expr);
+ if (e->left.exp->op != EXPR_IDENT)
+ simplified |= expr_simplify(e->left.exp);
/* if the left subexpr is just an IDENT (or string thereof),
* pull it up into the current node */
- while (e->ltype == EXPR_EXPR && e->left.expr->op == EXPR_IDENT) {
+ while (e->ltype == EXPR_EXPR && e->left.exp->op == EXPR_IDENT) {
ExprItem tmp;
- e->ltype = e->left.expr->rtype;
- memcpy(&tmp, &(e->left.expr->right), sizeof(ExprItem));
- free(e->left.expr);
- memcpy(&(e->left.num), &tmp, sizeof(ExprItem));
+ e->ltype = e->left.exp->rtype;
+ memcpy(&tmp, &(e->left.exp->right), sizeof(ExprItem));
+ free(e->left.exp);
+ memcpy(&(e->left.int_val), &tmp, sizeof(ExprItem));
simplified = 1;
}
} else if (e->ltype == EXPR_SYM) {
- /* if it's a symbol that has a defined value, turn it into a
- * number */
- if (e->left.sym->status & SYM_VALUED) {
- e->ltype = EXPR_NUM;
+ /* try to get value of symbol */
+ if (symrec_get_int_value(e->left.sym, &int_val, 0)) {
+ e->ltype = EXPR_INT;
/* don't try to free the symrec here. */
- e->left.num = e->left.sym->value;
+ e->left.int_val = int_val;
simplified = 1;
}
}
/* ditto on the right */
if (e->rtype == EXPR_EXPR) {
- if (e->right.expr->op != EXPR_IDENT)
- simplified |= expr_simplify(e->right.expr);
+ if (e->right.exp->op != EXPR_IDENT)
+ simplified |= expr_simplify(e->right.exp);
- while (e->rtype == EXPR_EXPR && e->right.expr->op == EXPR_IDENT) {
+ while (e->rtype == EXPR_EXPR && e->right.exp->op == EXPR_IDENT) {
ExprItem tmp;
- e->rtype = e->right.expr->rtype;
- memcpy(&tmp, &(e->right.expr->right), sizeof(ExprItem));
- free(e->right.expr);
- memcpy(&(e->right.num), &tmp, sizeof(ExprItem));
+ e->rtype = e->right.exp->rtype;
+ memcpy(&tmp, &(e->right.exp->right), sizeof(ExprItem));
+ free(e->right.exp);
+ memcpy(&(e->right.int_val), &tmp, sizeof(ExprItem));
simplified = 1;
}
} else if (e->rtype == EXPR_SYM) {
- if (e->right.sym->status & SYM_VALUED) {
- e->rtype = EXPR_NUM;
+ if (symrec_get_int_value(e->right.sym, &int_val, 0)) {
+ e->rtype = EXPR_INT;
/* don't try to free the symrec here. */
- e->right.num = e->right.sym->value;
+ e->right.int_val = int_val;
simplified = 1;
}
}
- if ((e->ltype == EXPR_NUM || e->ltype == EXPR_NONE)
- && e->rtype == EXPR_NUM && e->op != EXPR_IDENT) {
+ if ((e->ltype == EXPR_INT || e->ltype == EXPR_NONE)
+ && e->rtype == EXPR_INT && e->op != EXPR_IDENT) {
switch (e->op) {
case EXPR_ADD:
- e->right.num = e->left.num + e->right.num;
+ e->right.int_val = e->left.int_val + e->right.int_val;
break;
case EXPR_SUB:
- e->right.num = e->left.num - e->right.num;
+ e->right.int_val = e->left.int_val - e->right.int_val;
break;
case EXPR_MUL:
- e->right.num = e->left.num * e->right.num;
+ e->right.int_val = e->left.int_val * e->right.int_val;
break;
case EXPR_DIV:
- e->right.num = e->left.num / e->right.num;
+ e->right.int_val = e->left.int_val / e->right.int_val;
break;
case EXPR_MOD:
- e->right.num = e->left.num % e->right.num;
+ e->right.int_val = e->left.int_val % e->right.int_val;
break;
case EXPR_NEG:
- e->right.num = -(e->right.num);
+ e->right.int_val = -(e->right.int_val);
break;
case EXPR_NOT:
- e->right.num = ~(e->right.num);
+ e->right.int_val = ~(e->right.int_val);
break;
case EXPR_OR:
- e->right.num = e->left.num | e->right.num;
+ e->right.int_val = e->left.int_val | e->right.int_val;
break;
case EXPR_AND:
- e->right.num = e->left.num & e->right.num;
+ e->right.int_val = e->left.int_val & e->right.int_val;
break;
case EXPR_XOR:
- e->right.num = e->left.num ^ e->right.num;
+ e->right.int_val = e->left.int_val ^ e->right.int_val;
break;
case EXPR_SHL:
- e->right.num = e->right.num << e->left.num;
+ e->right.int_val = e->right.int_val << e->left.int_val;
break;
case EXPR_SHR:
- e->right.num = e->right.num << e->left.num;
+ e->right.int_val = e->right.int_val << e->left.int_val;
break;
case EXPR_LOR:
- e->right.num = e->left.num || e->right.num;
+ e->right.int_val = e->left.int_val || e->right.int_val;
break;
case EXPR_LAND:
- e->right.num = e->left.num && e->right.num;
+ e->right.int_val = e->left.int_val && e->right.int_val;
break;
case EXPR_LNOT:
- e->right.num = !e->right.num;
+ e->right.int_val = !e->right.int_val;
break;
case EXPR_EQ:
- e->right.num = e->right.num == e->left.num;
+ e->right.int_val = e->right.int_val == e->left.int_val;
break;
case EXPR_LT:
- e->right.num = e->right.num < e->left.num;
+ e->right.int_val = e->right.int_val < e->left.int_val;
break;
case EXPR_GT:
- e->right.num = e->right.num > e->left.num;
+ e->right.int_val = e->right.int_val > e->left.int_val;
break;
case EXPR_LE:
- e->right.num = e->right.num <= e->left.num;
+ e->right.int_val = e->right.int_val <= e->left.int_val;
break;
case EXPR_GE:
- e->right.num = e->right.num >= e->left.num;
+ e->right.int_val = e->right.int_val >= e->left.int_val;
break;
case EXPR_NE:
- e->right.num = e->right.num != e->left.num;
+ e->right.int_val = e->right.int_val != e->left.int_val;
break;
case EXPR_IDENT:
break;
}
/* catch simple identities like 0+x, 1*x, etc., for x not a num */
- else if (e->ltype == EXPR_NUM && ((e->left.num == 1 && e->op == EXPR_MUL)
- || (e->left.num == 0 &&
+ else if (e->ltype == EXPR_INT && ((e->left.int_val == 1 && e->op == EXPR_MUL)
+ || (e->left.int_val == 0 &&
e->op == EXPR_ADD)
- || (e->left.num == -1 &&
+ || (e->left.int_val == -1 &&
e->op == EXPR_AND)
- || (e->left.num == 0 &&
+ || (e->left.int_val == 0 &&
e->op == EXPR_OR))) {
e->op = EXPR_IDENT;
simplified = 1;
}
/* and the corresponding x+|-0, x*&/1 */
- else if (e->rtype == EXPR_NUM && ((e->right.num == 1 && e->op == EXPR_MUL)
- || (e->right.num == 1 &&
+ else if (e->rtype == EXPR_INT && ((e->right.int_val == 1 && e->op == EXPR_MUL)
+ || (e->right.int_val == 1 &&
e->op == EXPR_DIV)
- || (e->right.num == 0 &&
+ || (e->right.int_val == 0 &&
e->op == EXPR_ADD)
- || (e->right.num == 0 &&
+ || (e->right.int_val == 0 &&
e->op == EXPR_SUB)
- || (e->right.num == -1 &&
+ || (e->right.int_val == -1 &&
e->op == EXPR_AND)
- || (e->right.num == 0 &&
+ || (e->right.int_val == 0 &&
e->op == EXPR_OR)
- || (e->right.num == 0 &&
+ || (e->right.int_val == 0 &&
e->op == EXPR_SHL)
- || (e->right.num == 0 &&
+ || (e->right.int_val == 0 &&
e->op == EXPR_SHR))) {
e->op = EXPR_IDENT;
e->rtype = e->ltype;
int
expr_get_value(expr *e, unsigned long *retval)
{
- while (!(e->op == EXPR_IDENT && e->rtype == EXPR_NUM)
+ while (!(e->op == EXPR_IDENT && e->rtype == EXPR_INT)
&& expr_simplify(e)) ;
- if (e->op == EXPR_IDENT && e->rtype == EXPR_NUM) {
- *retval = e->right.num;
+ if (e->op == EXPR_IDENT && e->rtype == EXPR_INT) {
+ *retval = e->right.int_val;
return 1;
} else
return 0;
{
if (e->op != EXPR_IDENT) {
switch (e->ltype) {
- case EXPR_NUM:
- printf("%lu", e->left.num);
- break;
case EXPR_SYM:
printf("%s", e->left.sym->name);
break;
case EXPR_EXPR:
printf("(");
- expr_print(e->left.expr);
-
+ expr_print(e->left.exp);
printf(")");
+ break;
+ case EXPR_INT:
+ printf("%lu", e->left.int_val);
+ break;
+ case EXPR_FLOAT:
+ floatnum_print(e->left.flt);
+ break;
case EXPR_NONE:
break;
}
break;
}
switch (e->rtype) {
- case EXPR_NUM:
- printf("%lu", e->right.num);
- break;
case EXPR_SYM:
printf("%s", e->right.sym->name);
break;
case EXPR_EXPR:
printf("(");
- expr_print(e->right.expr);
-
+ expr_print(e->right.exp);
printf(")");
+ break;
+ case EXPR_INT:
+ printf("%lu", e->right.int_val);
+ break;
+ case EXPR_FLOAT:
+ floatnum_print(e->right.flt);
+ break;
case EXPR_NONE:
break;
}
/* $IdPath$
* Expression handling header file
*
- * Copyright (C) 2001 Michael Urman
+ * Copyright (C) 2001 Michael Urman, Peter Johnson
*
* This file is part of YASM.
*
typedef enum {
EXPR_NONE, /* for left side of a NOT, NEG, etc. */
- EXPR_NUM,
+ EXPR_SYM,
EXPR_EXPR,
- EXPR_SYM
+ EXPR_INT,
+ EXPR_FLOAT
} ExprType;
typedef union expritem_u {
struct symrec_s *sym;
- struct expr_s *expr;
- unsigned long num;
+ struct expr_s *exp;
+ unsigned long int_val;
+ struct floatnum_s *flt;
} ExprItem;
typedef struct expr_s {
ExprItem ExprSym(struct symrec_s *);
ExprItem ExprExpr(expr *);
-ExprItem ExprNum(unsigned long);
+ExprItem ExprInt(unsigned long);
+ExprItem ExprFloat(struct floatnum_s *);
ExprItem ExprNone(void);
#define expr_new_tree(l,o,r) \
--- /dev/null
+/* $IdPath$
+ * Floating point number functions.
+ *
+ * Copyright (C) 2001 Peter Johnson
+ *
+ * This file is part of YASM.
+ *
+ * YASM is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * YASM is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "util.h"
+
+#include <stdio.h>
+
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+#endif
+
+#include "errwarn.h"
+#include "floatnum.h"
+
+RCSID("$IdPath$");
+
+floatnum *
+floatnum_new(char *str)
+{
+ floatnum *flt = malloc(sizeof(floatnum));
+ if (!flt)
+ Fatal(FATAL_NOMEM);
+ /* TODO */
+ return flt;
+}
+
+unsigned long
+floatnum_get_int(floatnum *flt)
+{
+ return 0; /* TODO */
+}
+
+unsigned char *
+floatnum_get_single(unsigned char *ptr, floatnum *flt)
+{
+ return ptr; /* TODO */
+}
+
+unsigned char *
+floatnum_get_double(unsigned char *ptr, floatnum *flt)
+{
+ return ptr; /* TODO */
+}
+
+unsigned char *
+floatnum_get_extended(unsigned char *ptr, floatnum *flt)
+{
+ return ptr; /* TODO */
+}
+
+void
+floatnum_print(floatnum *flt)
+{
+ /* TODO */
+}
--- /dev/null
+/* $IdPath$
+ * Floating point number functions header file.
+ *
+ * Copyright (C) 2001 Peter Johnson
+ *
+ * This file is part of YASM.
+ *
+ * YASM is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * YASM is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef YASM_FLOATNUM_H
+#define YASM_FLOATNUM_H
+
+typedef struct floatnum_s {
+ unsigned char extval[10]; /* float stored in extended precision */
+} floatnum;
+
+floatnum *floatnum_new(char *str);
+unsigned long floatnum_get_int(floatnum *flt);
+unsigned char *floatnum_get_single(unsigned char *ptr, floatnum *flt);
+unsigned char *floatnum_get_double(unsigned char *ptr, floatnum *flt);
+unsigned char *floatnum_get_extended(unsigned char *ptr, floatnum *flt);
+
+void floatnum_print(floatnum *flt);
+
+#endif
/* $IdPath$
* Symbol table handling
*
- * Copyright (C) 2001 Michael Urman
+ * Copyright (C) 2001 Michael Urman, Peter Johnson
*
* This file is part of YASM.
*
#include "globals.h"
#include "errwarn.h"
+#include "floatnum.h"
#include "symrec.h"
+#include "bytecode.h"
+#include "section.h"
+
RCSID("$IdPath$");
/* private functions */
-static symrec *symrec_get_or_new(char *, SymType);
+static symrec *symrec_get_or_new(const char *);
+static symrec *symrec_define(const char *, SymType type);
/* The symbol table: a ternary tree. */
static ternary_tree sym_table = (ternary_tree)NULL;
/* create a new symrec */
static symrec *
-symrec_get_or_new(char *name, SymType type)
+symrec_get_or_new(const char *name)
{
symrec *rec, *rec2;
rec->name = strdup(name);
if (!rec->name)
Fatal(FATAL_NOMEM);
- rec->type = type;
- rec->value = 0;
+ rec->type = SYM_UNKNOWN;
rec->filename = strdup(filename);
rec->line = line_number;
rec->status = SYM_NOSTATUS;
+ rec->visibility = SYM_LOCAL;
return rec;
}
/* call a function with each symrec. stop early if 0 returned */
void
-symrec_foreach(int (*func) (char *name, symrec *rec))
+symrec_foreach(int (*func) (const char *name, symrec *rec))
{
+ /* TODO */
}
symrec *
-symrec_use(char *name, SymType type)
+symrec_use(const char *name)
{
- symrec *rec;
+ symrec *rec = symrec_get_or_new(name);
- rec = symrec_get_or_new(name, type);
rec->status |= SYM_USED;
return rec;
}
+static symrec *
+symrec_define(const char *name, SymType type)
+{
+ symrec *rec = symrec_get_or_new(name);
+
+ /* Has it been defined before (either by DEFINED or COMMON/EXTERN)? */
+ if (rec->status & SYM_DEFINED) {
+ Error(_("duplicate definition of `%s'; first defined on line %d"),
+ name, rec->line);
+ } else {
+ rec->line = line_number; /* set line number of definition */
+ rec->type = type;
+ rec->status |= SYM_DEFINED;
+ }
+ return rec;
+}
+
+symrec *
+symrec_define_constant_int(const char *name, unsigned long int_val)
+{
+ symrec *rec = symrec_define(name, SYM_CONSTANT_INT);
+ rec->value.int_val = int_val;
+ rec->status |= SYM_VALUED;
+ return rec;
+}
+
symrec *
-symrec_define(char *name, SymType type)
+symrec_define_constant_float(const char *name, floatnum *flt)
{
- symrec *rec;
+ symrec *rec = symrec_define(name, SYM_CONSTANT_FLOAT);
+ rec->value.flt = flt;
+ rec->status |= SYM_VALUED;
+ return rec;
+}
- rec = symrec_get_or_new(name, type);
- if (rec->status & SYM_DECLARED)
- Error(_("duplicate definition of `%s'; previously defined on line %d"),
+symrec *
+symrec_define_label(const char *name, section *sect, bytecode *precbc)
+{
+ symrec *rec = symrec_define(name, SYM_LABEL);
+ rec->value.label.sect = sect;
+ rec->value.label.bc = precbc;
+ return rec;
+}
+
+symrec *
+symrec_declare(const char *name, SymVisibility vis)
+{
+ symrec *rec = symrec_get_or_new(name);
+
+ /* Don't allow EXTERN and COMMON if symbol has already been DEFINED. */
+ /* Also, EXTERN and COMMON are mutually exclusive. */
+ if ((rec->status & SYM_DEFINED) ||
+ ((rec->visibility & SYM_COMMON) && (vis == SYM_EXTERN)) ||
+ ((rec->visibility & SYM_EXTERN) && (vis == SYM_COMMON))) {
+ Error(_("duplicate definition of `%s'; first defined on line %d"),
name, rec->line);
- rec->line = line_number; /* set line number of definition */
- rec->status |= SYM_DECLARED;
+ } else {
+ rec->line = line_number; /* set line number of declaration */
+ rec->visibility |= vis;
+
+ /* If declared as COMMON or EXTERN, set as DEFINED. */
+ if ((vis == SYM_COMMON) || (vis == SYM_EXTERN))
+ rec->status |= SYM_DEFINED;
+ }
return rec;
}
+
+int
+symrec_get_int_value(const symrec *sym, unsigned long *ret_val,
+ int resolve_label)
+{
+ /* If we already know the value, just return it. */
+ if (sym->status & SYM_VALUED) {
+ switch (sym->type) {
+ case SYM_CONSTANT_INT:
+ *ret_val = sym->value.int_val;
+ break;
+ case SYM_CONSTANT_FLOAT:
+ *ret_val = floatnum_get_int(sym->value.flt);
+ break;
+ case SYM_LABEL:
+ if (!bytecode_get_offset(sym->value.label.sect,
+ sym->value.label.bc, ret_val))
+ InternalError(__LINE__, __FILE__,
+ _("Label symbol is valued but cannot get offset"));
+ case SYM_UNKNOWN:
+ InternalError(__LINE__, __FILE__,
+ _("Have a valued symbol but of unknown type"));
+ }
+ return 1;
+ }
+
+ /* Try to get offset of unvalued label */
+ if (resolve_label && sym->type == SYM_LABEL)
+ return bytecode_get_offset(sym->value.label.sect, sym->value.label.bc,
+ ret_val);
+
+ /* We can't get the value right now. */
+ return 0;
+}
/* $IdPath$
* Symbol table handling header file
*
- * Copyright (C) 2001 Michael Urman
+ * Copyright (C) 2001 Michael Urman, Peter Johnson
*
* This file is part of YASM.
*
#ifndef YASM_SYMREC_H
#define YASM_SYMREC_H
+/* DEFINED is set with EXTERN and COMMON below */
typedef enum {
SYM_NOSTATUS = 0,
- SYM_USED = 1 << 0, /* for using variables before declared */
- SYM_DECLARED = 1 << 1, /* once it's been declared */
+ SYM_USED = 1 << 0, /* for using variables before definition */
+ SYM_DEFINED = 1 << 1, /* once it's been defined in the file */
SYM_VALUED = 1 << 2 /* once its value has been determined */
} SymStatus;
+/* EXTERN and COMMON are mutually exclusive */
typedef enum {
- SYM_CONSTANT, /* for EQU defined symbols */
+ SYM_LOCAL = 0, /* default, local only */
+ SYM_GLOBAL = 1 << 0, /* if it's declared GLOBAL */
+ SYM_COMMON = 1 << 1, /* if it's declared COMMON */
+ SYM_EXTERN = 1 << 2 /* if it's declared EXTERN */
+} SymVisibility;
+
+typedef enum {
+ SYM_UNKNOWN, /* for unknown type (COMMON/EXTERN) */
+ SYM_CONSTANT_INT, /* for EQU defined symbols (integers) */
+ SYM_CONSTANT_FLOAT, /* (floating point) */
SYM_LABEL /* for labels */
} SymType;
char *name;
SymType type;
SymStatus status;
+ SymVisibility visibility;
char *filename; /* file and line */
- int line; /* symbol was first declared or used on */
- double value;
+ unsigned long line; /* symbol was first declared or used on */
+ union {
+ unsigned long int_val; /* integer constant */
+ struct floatnum_s *flt; /* floating point constant */
+ struct label_s { /* bytecode immediately preceding a label */
+ struct section_s *sect;
+ struct bytecode_s *bc;
+ } label;
+ } value;
} symrec;
-symrec *symrec_use(char *name, SymType type);
-symrec *symrec_define(char *name, SymType type);
-void symrec_foreach(int (*func) (char *name, symrec *rec));
+symrec *symrec_use(const char *name);
+symrec *symrec_define_constant_int(const char *name, unsigned long int_val);
+symrec *symrec_define_constant_float(const char *name, struct floatnum_s *flt);
+symrec *symrec_define_label(const char *name, struct section_s *sect,
+ struct bytecode_s *precbc);
+symrec *symrec_declare(const char *name, SymVisibility vis);
+
+/* Get the numeric 32-bit value of a symbol if possible.
+ * Return value is IF POSSIBLE, not the value.
+ * If resolve_label is true, tries to get offset of labels, otherwise it
+ * returns not possible.
+ */
+int symrec_get_int_value(const symrec *sym, unsigned long *ret_val,
+ int resolve_label);
+
+void symrec_foreach(int (*func) (const char *name, symrec *rec));
#endif
/* $IdPath$
* Expression handling
*
- * Copyright (C) 2001 Michael Urman
+ * Copyright (C) 2001 Michael Urman, Peter Johnson
*
* This file is part of YASM.
*
#include "globals.h"
#include "errwarn.h"
+#include "floatnum.h"
#include "expr.h"
#include "symrec.h"
ptr->op = op;
ptr->rtype = rtype;
switch (ltype) {
- case EXPR_NUM:
case EXPR_SYM:
case EXPR_EXPR:
+ case EXPR_INT:
+ case EXPR_FLOAT:
memcpy(&ptr->left, &left, sizeof(ExprItem));
break;
case EXPR_NONE:
break;
}
switch (rtype) {
- case EXPR_NUM:
case EXPR_SYM:
case EXPR_EXPR:
+ case EXPR_INT:
+ case EXPR_FLOAT:
memcpy(&ptr->right, &right, sizeof(ExprItem));
break;
case EXPR_NONE:
ExprExpr(expr *x)
{
ExprItem e;
- e.expr = x;
+ e.exp = x;
return e;
}
ExprItem
-ExprNum(unsigned long n)
+ExprInt(unsigned long i)
{
ExprItem e;
- e.num = n;
+ e.int_val = i;
+ return e;
+}
+
+ExprItem
+ExprFloat(floatnum *f)
+{
+ ExprItem e;
+
+ e.flt = f;
return e;
}
{
ExprItem e;
- e.num = 0;
+ e.int_val = 0;
return e;
}
expr_simplify(expr *e)
{
int simplified = 0;
+ unsigned long int_val;
/* try to simplify the left side */
if (e->ltype == EXPR_EXPR) {
/* if the left subexpr isn't an IDENT, recurse simplification */
- if (e->left.expr->op != EXPR_IDENT)
- simplified |= expr_simplify(e->left.expr);
+ if (e->left.exp->op != EXPR_IDENT)
+ simplified |= expr_simplify(e->left.exp);
/* if the left subexpr is just an IDENT (or string thereof),
* pull it up into the current node */
- while (e->ltype == EXPR_EXPR && e->left.expr->op == EXPR_IDENT) {
+ while (e->ltype == EXPR_EXPR && e->left.exp->op == EXPR_IDENT) {
ExprItem tmp;
- e->ltype = e->left.expr->rtype;
- memcpy(&tmp, &(e->left.expr->right), sizeof(ExprItem));
- free(e->left.expr);
- memcpy(&(e->left.num), &tmp, sizeof(ExprItem));
+ e->ltype = e->left.exp->rtype;
+ memcpy(&tmp, &(e->left.exp->right), sizeof(ExprItem));
+ free(e->left.exp);
+ memcpy(&(e->left.int_val), &tmp, sizeof(ExprItem));
simplified = 1;
}
} else if (e->ltype == EXPR_SYM) {
- /* if it's a symbol that has a defined value, turn it into a
- * number */
- if (e->left.sym->status & SYM_VALUED) {
- e->ltype = EXPR_NUM;
+ /* try to get value of symbol */
+ if (symrec_get_int_value(e->left.sym, &int_val, 0)) {
+ e->ltype = EXPR_INT;
/* don't try to free the symrec here. */
- e->left.num = e->left.sym->value;
+ e->left.int_val = int_val;
simplified = 1;
}
}
/* ditto on the right */
if (e->rtype == EXPR_EXPR) {
- if (e->right.expr->op != EXPR_IDENT)
- simplified |= expr_simplify(e->right.expr);
+ if (e->right.exp->op != EXPR_IDENT)
+ simplified |= expr_simplify(e->right.exp);
- while (e->rtype == EXPR_EXPR && e->right.expr->op == EXPR_IDENT) {
+ while (e->rtype == EXPR_EXPR && e->right.exp->op == EXPR_IDENT) {
ExprItem tmp;
- e->rtype = e->right.expr->rtype;
- memcpy(&tmp, &(e->right.expr->right), sizeof(ExprItem));
- free(e->right.expr);
- memcpy(&(e->right.num), &tmp, sizeof(ExprItem));
+ e->rtype = e->right.exp->rtype;
+ memcpy(&tmp, &(e->right.exp->right), sizeof(ExprItem));
+ free(e->right.exp);
+ memcpy(&(e->right.int_val), &tmp, sizeof(ExprItem));
simplified = 1;
}
} else if (e->rtype == EXPR_SYM) {
- if (e->right.sym->status & SYM_VALUED) {
- e->rtype = EXPR_NUM;
+ if (symrec_get_int_value(e->right.sym, &int_val, 0)) {
+ e->rtype = EXPR_INT;
/* don't try to free the symrec here. */
- e->right.num = e->right.sym->value;
+ e->right.int_val = int_val;
simplified = 1;
}
}
- if ((e->ltype == EXPR_NUM || e->ltype == EXPR_NONE)
- && e->rtype == EXPR_NUM && e->op != EXPR_IDENT) {
+ if ((e->ltype == EXPR_INT || e->ltype == EXPR_NONE)
+ && e->rtype == EXPR_INT && e->op != EXPR_IDENT) {
switch (e->op) {
case EXPR_ADD:
- e->right.num = e->left.num + e->right.num;
+ e->right.int_val = e->left.int_val + e->right.int_val;
break;
case EXPR_SUB:
- e->right.num = e->left.num - e->right.num;
+ e->right.int_val = e->left.int_val - e->right.int_val;
break;
case EXPR_MUL:
- e->right.num = e->left.num * e->right.num;
+ e->right.int_val = e->left.int_val * e->right.int_val;
break;
case EXPR_DIV:
- e->right.num = e->left.num / e->right.num;
+ e->right.int_val = e->left.int_val / e->right.int_val;
break;
case EXPR_MOD:
- e->right.num = e->left.num % e->right.num;
+ e->right.int_val = e->left.int_val % e->right.int_val;
break;
case EXPR_NEG:
- e->right.num = -(e->right.num);
+ e->right.int_val = -(e->right.int_val);
break;
case EXPR_NOT:
- e->right.num = ~(e->right.num);
+ e->right.int_val = ~(e->right.int_val);
break;
case EXPR_OR:
- e->right.num = e->left.num | e->right.num;
+ e->right.int_val = e->left.int_val | e->right.int_val;
break;
case EXPR_AND:
- e->right.num = e->left.num & e->right.num;
+ e->right.int_val = e->left.int_val & e->right.int_val;
break;
case EXPR_XOR:
- e->right.num = e->left.num ^ e->right.num;
+ e->right.int_val = e->left.int_val ^ e->right.int_val;
break;
case EXPR_SHL:
- e->right.num = e->right.num << e->left.num;
+ e->right.int_val = e->right.int_val << e->left.int_val;
break;
case EXPR_SHR:
- e->right.num = e->right.num << e->left.num;
+ e->right.int_val = e->right.int_val << e->left.int_val;
break;
case EXPR_LOR:
- e->right.num = e->left.num || e->right.num;
+ e->right.int_val = e->left.int_val || e->right.int_val;
break;
case EXPR_LAND:
- e->right.num = e->left.num && e->right.num;
+ e->right.int_val = e->left.int_val && e->right.int_val;
break;
case EXPR_LNOT:
- e->right.num = !e->right.num;
+ e->right.int_val = !e->right.int_val;
break;
case EXPR_EQ:
- e->right.num = e->right.num == e->left.num;
+ e->right.int_val = e->right.int_val == e->left.int_val;
break;
case EXPR_LT:
- e->right.num = e->right.num < e->left.num;
+ e->right.int_val = e->right.int_val < e->left.int_val;
break;
case EXPR_GT:
- e->right.num = e->right.num > e->left.num;
+ e->right.int_val = e->right.int_val > e->left.int_val;
break;
case EXPR_LE:
- e->right.num = e->right.num <= e->left.num;
+ e->right.int_val = e->right.int_val <= e->left.int_val;
break;
case EXPR_GE:
- e->right.num = e->right.num >= e->left.num;
+ e->right.int_val = e->right.int_val >= e->left.int_val;
break;
case EXPR_NE:
- e->right.num = e->right.num != e->left.num;
+ e->right.int_val = e->right.int_val != e->left.int_val;
break;
case EXPR_IDENT:
break;
}
/* catch simple identities like 0+x, 1*x, etc., for x not a num */
- else if (e->ltype == EXPR_NUM && ((e->left.num == 1 && e->op == EXPR_MUL)
- || (e->left.num == 0 &&
+ else if (e->ltype == EXPR_INT && ((e->left.int_val == 1 && e->op == EXPR_MUL)
+ || (e->left.int_val == 0 &&
e->op == EXPR_ADD)
- || (e->left.num == -1 &&
+ || (e->left.int_val == -1 &&
e->op == EXPR_AND)
- || (e->left.num == 0 &&
+ || (e->left.int_val == 0 &&
e->op == EXPR_OR))) {
e->op = EXPR_IDENT;
simplified = 1;
}
/* and the corresponding x+|-0, x*&/1 */
- else if (e->rtype == EXPR_NUM && ((e->right.num == 1 && e->op == EXPR_MUL)
- || (e->right.num == 1 &&
+ else if (e->rtype == EXPR_INT && ((e->right.int_val == 1 && e->op == EXPR_MUL)
+ || (e->right.int_val == 1 &&
e->op == EXPR_DIV)
- || (e->right.num == 0 &&
+ || (e->right.int_val == 0 &&
e->op == EXPR_ADD)
- || (e->right.num == 0 &&
+ || (e->right.int_val == 0 &&
e->op == EXPR_SUB)
- || (e->right.num == -1 &&
+ || (e->right.int_val == -1 &&
e->op == EXPR_AND)
- || (e->right.num == 0 &&
+ || (e->right.int_val == 0 &&
e->op == EXPR_OR)
- || (e->right.num == 0 &&
+ || (e->right.int_val == 0 &&
e->op == EXPR_SHL)
- || (e->right.num == 0 &&
+ || (e->right.int_val == 0 &&
e->op == EXPR_SHR))) {
e->op = EXPR_IDENT;
e->rtype = e->ltype;
int
expr_get_value(expr *e, unsigned long *retval)
{
- while (!(e->op == EXPR_IDENT && e->rtype == EXPR_NUM)
+ while (!(e->op == EXPR_IDENT && e->rtype == EXPR_INT)
&& expr_simplify(e)) ;
- if (e->op == EXPR_IDENT && e->rtype == EXPR_NUM) {
- *retval = e->right.num;
+ if (e->op == EXPR_IDENT && e->rtype == EXPR_INT) {
+ *retval = e->right.int_val;
return 1;
} else
return 0;
{
if (e->op != EXPR_IDENT) {
switch (e->ltype) {
- case EXPR_NUM:
- printf("%lu", e->left.num);
- break;
case EXPR_SYM:
printf("%s", e->left.sym->name);
break;
case EXPR_EXPR:
printf("(");
- expr_print(e->left.expr);
-
+ expr_print(e->left.exp);
printf(")");
+ break;
+ case EXPR_INT:
+ printf("%lu", e->left.int_val);
+ break;
+ case EXPR_FLOAT:
+ floatnum_print(e->left.flt);
+ break;
case EXPR_NONE:
break;
}
break;
}
switch (e->rtype) {
- case EXPR_NUM:
- printf("%lu", e->right.num);
- break;
case EXPR_SYM:
printf("%s", e->right.sym->name);
break;
case EXPR_EXPR:
printf("(");
- expr_print(e->right.expr);
-
+ expr_print(e->right.exp);
printf(")");
+ break;
+ case EXPR_INT:
+ printf("%lu", e->right.int_val);
+ break;
+ case EXPR_FLOAT:
+ floatnum_print(e->right.flt);
+ break;
case EXPR_NONE:
break;
}
/* $IdPath$
* Expression handling
*
- * Copyright (C) 2001 Michael Urman
+ * Copyright (C) 2001 Michael Urman, Peter Johnson
*
* This file is part of YASM.
*
#include "globals.h"
#include "errwarn.h"
+#include "floatnum.h"
#include "expr.h"
#include "symrec.h"
ptr->op = op;
ptr->rtype = rtype;
switch (ltype) {
- case EXPR_NUM:
case EXPR_SYM:
case EXPR_EXPR:
+ case EXPR_INT:
+ case EXPR_FLOAT:
memcpy(&ptr->left, &left, sizeof(ExprItem));
break;
case EXPR_NONE:
break;
}
switch (rtype) {
- case EXPR_NUM:
case EXPR_SYM:
case EXPR_EXPR:
+ case EXPR_INT:
+ case EXPR_FLOAT:
memcpy(&ptr->right, &right, sizeof(ExprItem));
break;
case EXPR_NONE:
ExprExpr(expr *x)
{
ExprItem e;
- e.expr = x;
+ e.exp = x;
return e;
}
ExprItem
-ExprNum(unsigned long n)
+ExprInt(unsigned long i)
{
ExprItem e;
- e.num = n;
+ e.int_val = i;
+ return e;
+}
+
+ExprItem
+ExprFloat(floatnum *f)
+{
+ ExprItem e;
+
+ e.flt = f;
return e;
}
{
ExprItem e;
- e.num = 0;
+ e.int_val = 0;
return e;
}
expr_simplify(expr *e)
{
int simplified = 0;
+ unsigned long int_val;
/* try to simplify the left side */
if (e->ltype == EXPR_EXPR) {
/* if the left subexpr isn't an IDENT, recurse simplification */
- if (e->left.expr->op != EXPR_IDENT)
- simplified |= expr_simplify(e->left.expr);
+ if (e->left.exp->op != EXPR_IDENT)
+ simplified |= expr_simplify(e->left.exp);
/* if the left subexpr is just an IDENT (or string thereof),
* pull it up into the current node */
- while (e->ltype == EXPR_EXPR && e->left.expr->op == EXPR_IDENT) {
+ while (e->ltype == EXPR_EXPR && e->left.exp->op == EXPR_IDENT) {
ExprItem tmp;
- e->ltype = e->left.expr->rtype;
- memcpy(&tmp, &(e->left.expr->right), sizeof(ExprItem));
- free(e->left.expr);
- memcpy(&(e->left.num), &tmp, sizeof(ExprItem));
+ e->ltype = e->left.exp->rtype;
+ memcpy(&tmp, &(e->left.exp->right), sizeof(ExprItem));
+ free(e->left.exp);
+ memcpy(&(e->left.int_val), &tmp, sizeof(ExprItem));
simplified = 1;
}
} else if (e->ltype == EXPR_SYM) {
- /* if it's a symbol that has a defined value, turn it into a
- * number */
- if (e->left.sym->status & SYM_VALUED) {
- e->ltype = EXPR_NUM;
+ /* try to get value of symbol */
+ if (symrec_get_int_value(e->left.sym, &int_val, 0)) {
+ e->ltype = EXPR_INT;
/* don't try to free the symrec here. */
- e->left.num = e->left.sym->value;
+ e->left.int_val = int_val;
simplified = 1;
}
}
/* ditto on the right */
if (e->rtype == EXPR_EXPR) {
- if (e->right.expr->op != EXPR_IDENT)
- simplified |= expr_simplify(e->right.expr);
+ if (e->right.exp->op != EXPR_IDENT)
+ simplified |= expr_simplify(e->right.exp);
- while (e->rtype == EXPR_EXPR && e->right.expr->op == EXPR_IDENT) {
+ while (e->rtype == EXPR_EXPR && e->right.exp->op == EXPR_IDENT) {
ExprItem tmp;
- e->rtype = e->right.expr->rtype;
- memcpy(&tmp, &(e->right.expr->right), sizeof(ExprItem));
- free(e->right.expr);
- memcpy(&(e->right.num), &tmp, sizeof(ExprItem));
+ e->rtype = e->right.exp->rtype;
+ memcpy(&tmp, &(e->right.exp->right), sizeof(ExprItem));
+ free(e->right.exp);
+ memcpy(&(e->right.int_val), &tmp, sizeof(ExprItem));
simplified = 1;
}
} else if (e->rtype == EXPR_SYM) {
- if (e->right.sym->status & SYM_VALUED) {
- e->rtype = EXPR_NUM;
+ if (symrec_get_int_value(e->right.sym, &int_val, 0)) {
+ e->rtype = EXPR_INT;
/* don't try to free the symrec here. */
- e->right.num = e->right.sym->value;
+ e->right.int_val = int_val;
simplified = 1;
}
}
- if ((e->ltype == EXPR_NUM || e->ltype == EXPR_NONE)
- && e->rtype == EXPR_NUM && e->op != EXPR_IDENT) {
+ if ((e->ltype == EXPR_INT || e->ltype == EXPR_NONE)
+ && e->rtype == EXPR_INT && e->op != EXPR_IDENT) {
switch (e->op) {
case EXPR_ADD:
- e->right.num = e->left.num + e->right.num;
+ e->right.int_val = e->left.int_val + e->right.int_val;
break;
case EXPR_SUB:
- e->right.num = e->left.num - e->right.num;
+ e->right.int_val = e->left.int_val - e->right.int_val;
break;
case EXPR_MUL:
- e->right.num = e->left.num * e->right.num;
+ e->right.int_val = e->left.int_val * e->right.int_val;
break;
case EXPR_DIV:
- e->right.num = e->left.num / e->right.num;
+ e->right.int_val = e->left.int_val / e->right.int_val;
break;
case EXPR_MOD:
- e->right.num = e->left.num % e->right.num;
+ e->right.int_val = e->left.int_val % e->right.int_val;
break;
case EXPR_NEG:
- e->right.num = -(e->right.num);
+ e->right.int_val = -(e->right.int_val);
break;
case EXPR_NOT:
- e->right.num = ~(e->right.num);
+ e->right.int_val = ~(e->right.int_val);
break;
case EXPR_OR:
- e->right.num = e->left.num | e->right.num;
+ e->right.int_val = e->left.int_val | e->right.int_val;
break;
case EXPR_AND:
- e->right.num = e->left.num & e->right.num;
+ e->right.int_val = e->left.int_val & e->right.int_val;
break;
case EXPR_XOR:
- e->right.num = e->left.num ^ e->right.num;
+ e->right.int_val = e->left.int_val ^ e->right.int_val;
break;
case EXPR_SHL:
- e->right.num = e->right.num << e->left.num;
+ e->right.int_val = e->right.int_val << e->left.int_val;
break;
case EXPR_SHR:
- e->right.num = e->right.num << e->left.num;
+ e->right.int_val = e->right.int_val << e->left.int_val;
break;
case EXPR_LOR:
- e->right.num = e->left.num || e->right.num;
+ e->right.int_val = e->left.int_val || e->right.int_val;
break;
case EXPR_LAND:
- e->right.num = e->left.num && e->right.num;
+ e->right.int_val = e->left.int_val && e->right.int_val;
break;
case EXPR_LNOT:
- e->right.num = !e->right.num;
+ e->right.int_val = !e->right.int_val;
break;
case EXPR_EQ:
- e->right.num = e->right.num == e->left.num;
+ e->right.int_val = e->right.int_val == e->left.int_val;
break;
case EXPR_LT:
- e->right.num = e->right.num < e->left.num;
+ e->right.int_val = e->right.int_val < e->left.int_val;
break;
case EXPR_GT:
- e->right.num = e->right.num > e->left.num;
+ e->right.int_val = e->right.int_val > e->left.int_val;
break;
case EXPR_LE:
- e->right.num = e->right.num <= e->left.num;
+ e->right.int_val = e->right.int_val <= e->left.int_val;
break;
case EXPR_GE:
- e->right.num = e->right.num >= e->left.num;
+ e->right.int_val = e->right.int_val >= e->left.int_val;
break;
case EXPR_NE:
- e->right.num = e->right.num != e->left.num;
+ e->right.int_val = e->right.int_val != e->left.int_val;
break;
case EXPR_IDENT:
break;
}
/* catch simple identities like 0+x, 1*x, etc., for x not a num */
- else if (e->ltype == EXPR_NUM && ((e->left.num == 1 && e->op == EXPR_MUL)
- || (e->left.num == 0 &&
+ else if (e->ltype == EXPR_INT && ((e->left.int_val == 1 && e->op == EXPR_MUL)
+ || (e->left.int_val == 0 &&
e->op == EXPR_ADD)
- || (e->left.num == -1 &&
+ || (e->left.int_val == -1 &&
e->op == EXPR_AND)
- || (e->left.num == 0 &&
+ || (e->left.int_val == 0 &&
e->op == EXPR_OR))) {
e->op = EXPR_IDENT;
simplified = 1;
}
/* and the corresponding x+|-0, x*&/1 */
- else if (e->rtype == EXPR_NUM && ((e->right.num == 1 && e->op == EXPR_MUL)
- || (e->right.num == 1 &&
+ else if (e->rtype == EXPR_INT && ((e->right.int_val == 1 && e->op == EXPR_MUL)
+ || (e->right.int_val == 1 &&
e->op == EXPR_DIV)
- || (e->right.num == 0 &&
+ || (e->right.int_val == 0 &&
e->op == EXPR_ADD)
- || (e->right.num == 0 &&
+ || (e->right.int_val == 0 &&
e->op == EXPR_SUB)
- || (e->right.num == -1 &&
+ || (e->right.int_val == -1 &&
e->op == EXPR_AND)
- || (e->right.num == 0 &&
+ || (e->right.int_val == 0 &&
e->op == EXPR_OR)
- || (e->right.num == 0 &&
+ || (e->right.int_val == 0 &&
e->op == EXPR_SHL)
- || (e->right.num == 0 &&
+ || (e->right.int_val == 0 &&
e->op == EXPR_SHR))) {
e->op = EXPR_IDENT;
e->rtype = e->ltype;
int
expr_get_value(expr *e, unsigned long *retval)
{
- while (!(e->op == EXPR_IDENT && e->rtype == EXPR_NUM)
+ while (!(e->op == EXPR_IDENT && e->rtype == EXPR_INT)
&& expr_simplify(e)) ;
- if (e->op == EXPR_IDENT && e->rtype == EXPR_NUM) {
- *retval = e->right.num;
+ if (e->op == EXPR_IDENT && e->rtype == EXPR_INT) {
+ *retval = e->right.int_val;
return 1;
} else
return 0;
{
if (e->op != EXPR_IDENT) {
switch (e->ltype) {
- case EXPR_NUM:
- printf("%lu", e->left.num);
- break;
case EXPR_SYM:
printf("%s", e->left.sym->name);
break;
case EXPR_EXPR:
printf("(");
- expr_print(e->left.expr);
-
+ expr_print(e->left.exp);
printf(")");
+ break;
+ case EXPR_INT:
+ printf("%lu", e->left.int_val);
+ break;
+ case EXPR_FLOAT:
+ floatnum_print(e->left.flt);
+ break;
case EXPR_NONE:
break;
}
break;
}
switch (e->rtype) {
- case EXPR_NUM:
- printf("%lu", e->right.num);
- break;
case EXPR_SYM:
printf("%s", e->right.sym->name);
break;
case EXPR_EXPR:
printf("(");
- expr_print(e->right.expr);
-
+ expr_print(e->right.exp);
printf(")");
+ break;
+ case EXPR_INT:
+ printf("%lu", e->right.int_val);
+ break;
+ case EXPR_FLOAT:
+ floatnum_print(e->right.flt);
+ break;
case EXPR_NONE:
break;
}
#include "globals.h"
#include "errwarn.h"
+#include "floatnum.h"
#include "expr.h"
#include "symrec.h"
extern section *nasm_parser_cur_section;
extern char *nasm_parser_locallabel_base;
+static bytecode *nasm_parser_prev_bc = (bytecode *)NULL;
+static bytecode *nasm_parser_temp_bc;
+
%}
%union {
unsigned long int_val;
char *str_val;
- double double_val;
- symrec *sym;
- struct {
- char *name;
- int line;
- } syminfo;
+ floatnum *flt;
unsigned char groupdata[4];
effaddr *ea;
expr *exp;
}
%token <int_val> INTNUM
-%token <double_val> FLTNUM
+%token <flt> FLTNUM
%token <str_val> DIRECTIVE_NAME DIRECTIVE_VAL STRING
%token <int_val> BYTE WORD DWORD QWORD TWORD DQWORD
%token <int_val> DECLARE_DATA
%token <int_val> REG_AL REG_CL REG_DL REG_BL REG_AH REG_CH REG_DH REG_BH
%token <int_val> REG_ES REG_CS REG_SS REG_DS REG_FS REG_GS
%token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD
-%token <syminfo> ID LOCAL_ID SPECIAL_ID
+%token <str_val> ID LOCAL_ID SPECIAL_ID
/* instruction tokens (dynamically generated) */
/* @TOKENS@ */
%type <ea> rm8 rm16 rm32 rm64 rm128
%type <im_val> imm imm8x imm16x imm32x imm8 imm16 imm32
%type <exp> expr expr_no_string
-%type <syminfo> explabel
-%type <sym> label_id
+%type <str_val> explabel label_id
%type <tgt_val> target
%type <data> dataval
%type <datahead> datavals
%%
input: /* empty */
| input line {
- bytecodes_append(&nasm_parser_cur_section->bc, $2);
+ nasm_parser_temp_bc = bytecodes_append(&nasm_parser_cur_section->bc,
+ $2);
+ if (nasm_parser_temp_bc)
+ nasm_parser_prev_bc = nasm_parser_temp_bc;
line_number++;
}
;
}
;
-label: label_id { $1->value = 0; } /* TODO: add pointer to bytecode */
- | label_id ':' { $1->value = 0; } /* TODO: add pointer to bytecode */
+label: label_id {
+ symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc);
+ }
+ | label_id ':' {
+ symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc);
+ }
;
label_id: ID {
- $$ = symrec_define($1.name, SYM_LABEL);
- nasm_parser_locallabel_base = strdup($1.name);
+ $$ = $1;
+ nasm_parser_locallabel_base = strdup($1);
}
- | SPECIAL_ID { $$ = symrec_define($1.name, SYM_LABEL); }
- | LOCAL_ID { $$ = symrec_define($1.name, SYM_LABEL); }
+ | SPECIAL_ID
+ | LOCAL_ID
;
/* directives */
directive: '[' DIRECTIVE_NAME DIRECTIVE_VAL ']' {
- if (strcasecmp($2, "section") == 0)
+ if (strcasecmp($2, "section") == 0) {
nasm_parser_cur_section = sections_switch(&nasm_parser_sections,
nasm_parser_objfmt, $3);
- else
+ nasm_parser_prev_bc = (bytecode *)NULL;
+ } else {
printf("Directive: Name='%s' Value='%s'\n", $2, $3);
+ }
}
| '[' DIRECTIVE_NAME DIRECTIVE_VAL error {
Error(_("missing `%c'"), ']');
;
/* expression trees */
-expr_no_string: INTNUM { $$ = expr_new_ident(EXPR_NUM, ExprNum($1)); }
+expr_no_string: INTNUM { $$ = expr_new_ident(EXPR_INT, ExprInt($1)); }
| explabel {
- $$ = expr_new_ident(EXPR_SYM, ExprSym(symrec_use($1.name, SYM_LABEL)));
+ $$ = expr_new_ident(EXPR_SYM, ExprSym(symrec_use($1)));
}
/*| expr '||' expr { $$ = expr_new_tree($1, EXPR_LOR, $3); }*/
| expr '|' expr { $$ = expr_new_tree($1, EXPR_OR, $3); }
expr: expr_no_string
| STRING {
- $$ = expr_new_ident (EXPR_NUM, ExprNum(ConvertCharConstToInt($1)));
+ $$ = expr_new_ident (EXPR_INT, ExprInt(ConvertCharConstToInt($1)));
}
;
#include "globals.h"
#include "errwarn.h"
+#include "floatnum.h"
#include "expr.h"
#include "symrec.h"
extern section *nasm_parser_cur_section;
extern char *nasm_parser_locallabel_base;
+static bytecode *nasm_parser_prev_bc = (bytecode *)NULL;
+static bytecode *nasm_parser_temp_bc;
+
%}
%union {
unsigned long int_val;
char *str_val;
- double double_val;
- symrec *sym;
- struct {
- char *name;
- int line;
- } syminfo;
+ floatnum *flt;
unsigned char groupdata[4];
effaddr *ea;
expr *exp;
}
%token <int_val> INTNUM
-%token <double_val> FLTNUM
+%token <flt> FLTNUM
%token <str_val> DIRECTIVE_NAME DIRECTIVE_VAL STRING
%token <int_val> BYTE WORD DWORD QWORD TWORD DQWORD
%token <int_val> DECLARE_DATA
%token <int_val> REG_AL REG_CL REG_DL REG_BL REG_AH REG_CH REG_DH REG_BH
%token <int_val> REG_ES REG_CS REG_SS REG_DS REG_FS REG_GS
%token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD
-%token <syminfo> ID LOCAL_ID SPECIAL_ID
+%token <str_val> ID LOCAL_ID SPECIAL_ID
/* instruction tokens (dynamically generated) */
/* @TOKENS@ */
%type <ea> rm8 rm16 rm32 rm64 rm128
%type <im_val> imm imm8x imm16x imm32x imm8 imm16 imm32
%type <exp> expr expr_no_string
-%type <syminfo> explabel
-%type <sym> label_id
+%type <str_val> explabel label_id
%type <tgt_val> target
%type <data> dataval
%type <datahead> datavals
%%
input: /* empty */
| input line {
- bytecodes_append(&nasm_parser_cur_section->bc, $2);
+ nasm_parser_temp_bc = bytecodes_append(&nasm_parser_cur_section->bc,
+ $2);
+ if (nasm_parser_temp_bc)
+ nasm_parser_prev_bc = nasm_parser_temp_bc;
line_number++;
}
;
}
;
-label: label_id { $1->value = 0; } /* TODO: add pointer to bytecode */
- | label_id ':' { $1->value = 0; } /* TODO: add pointer to bytecode */
+label: label_id {
+ symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc);
+ }
+ | label_id ':' {
+ symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc);
+ }
;
label_id: ID {
- $$ = symrec_define($1.name, SYM_LABEL);
- nasm_parser_locallabel_base = strdup($1.name);
+ $$ = $1;
+ nasm_parser_locallabel_base = strdup($1);
}
- | SPECIAL_ID { $$ = symrec_define($1.name, SYM_LABEL); }
- | LOCAL_ID { $$ = symrec_define($1.name, SYM_LABEL); }
+ | SPECIAL_ID
+ | LOCAL_ID
;
/* directives */
directive: '[' DIRECTIVE_NAME DIRECTIVE_VAL ']' {
- if (strcasecmp($2, "section") == 0)
+ if (strcasecmp($2, "section") == 0) {
nasm_parser_cur_section = sections_switch(&nasm_parser_sections,
nasm_parser_objfmt, $3);
- else
+ nasm_parser_prev_bc = (bytecode *)NULL;
+ } else {
printf("Directive: Name='%s' Value='%s'\n", $2, $3);
+ }
}
| '[' DIRECTIVE_NAME DIRECTIVE_VAL error {
Error(_("missing `%c'"), ']');
;
/* expression trees */
-expr_no_string: INTNUM { $$ = expr_new_ident(EXPR_NUM, ExprNum($1)); }
+expr_no_string: INTNUM { $$ = expr_new_ident(EXPR_INT, ExprInt($1)); }
| explabel {
- $$ = expr_new_ident(EXPR_SYM, ExprSym(symrec_use($1.name, SYM_LABEL)));
+ $$ = expr_new_ident(EXPR_SYM, ExprSym(symrec_use($1)));
}
/*| expr '||' expr { $$ = expr_new_tree($1, EXPR_LOR, $3); }*/
| expr '|' expr { $$ = expr_new_tree($1, EXPR_OR, $3); }
expr: expr_no_string
| STRING {
- $$ = expr_new_ident (EXPR_NUM, ExprNum(ConvertCharConstToInt($1)));
+ $$ = expr_new_ident (EXPR_INT, ExprInt(ConvertCharConstToInt($1)));
}
;
#define _(String) gettext(String)
#include "errwarn.h"
+#include "floatnum.h"
#include "expr.h"
#include "symrec.h"
/* floating point value */
{DIGIT}+\.{DIGIT}*(e[-+]?{DIGIT}+)? {
- yylval.double_val = strtod(yytext, (char **)NULL);
+ yylval.flt = floatnum_new(yytext);
return FLTNUM;
}
/* special non-local ..@label and labels like ..start */
$$|$|\.\.[a-z0-9_$#@~.?]+ {
- yylval.syminfo.name = strdup(yytext);
- if (!yylval.syminfo.name)
+ yylval.str_val = strdup(yytext);
+ if (!yylval.str_val)
Fatal(FATAL_NOMEM);
- yylval.syminfo.line = line_number;
return SPECIAL_ID;
}
\.[a-z0-9_$#@~?][a-z0-9_$#@~.?]* {
if (!nasm_parser_locallabel_base) {
Warning(_("no non-local label before `%s'"), yytext);
- yylval.syminfo.name = strdup(yytext);
- if (!yylval.syminfo.name)
+ yylval.str_val = strdup(yytext);
+ if (!yylval.str_val)
Fatal(FATAL_NOMEM);
} else {
- yylval.syminfo.name = malloc(strlen(yytext) +
- strlen(nasm_parser_locallabel_base) + 1);
- if (!yylval.syminfo.name)
+ yylval.str_val = malloc(strlen(yytext) +
+ strlen(nasm_parser_locallabel_base) + 1);
+ if (!yylval.str_val)
Fatal(FATAL_NOMEM);
- strcpy(yylval.syminfo.name, nasm_parser_locallabel_base);
- strcat(yylval.syminfo.name, yytext);
+ strcpy(yylval.str_val, nasm_parser_locallabel_base);
+ strcat(yylval.str_val, yytext);
}
- yylval.syminfo.line = line_number;
return LOCAL_ID;
}
/* label */
[a-z_?][a-z0-9_$#@~.?]* {
- yylval.syminfo.name = strdup(yytext);
- if (!yylval.syminfo.name)
+ yylval.str_val = strdup(yytext);
+ if (!yylval.str_val)
Fatal(FATAL_NOMEM);
- yylval.syminfo.line = line_number;
return ID;
}
parser.c \
parser.h \
optimizer.h \
+ floatnum.c \
+ floatnum.h \
ternary.c \
ternary.h \
strcasecmp.c
/* $IdPath$
* Expression handling
*
- * Copyright (C) 2001 Michael Urman
+ * Copyright (C) 2001 Michael Urman, Peter Johnson
*
* This file is part of YASM.
*
#include "globals.h"
#include "errwarn.h"
+#include "floatnum.h"
#include "expr.h"
#include "symrec.h"
ptr->op = op;
ptr->rtype = rtype;
switch (ltype) {
- case EXPR_NUM:
case EXPR_SYM:
case EXPR_EXPR:
+ case EXPR_INT:
+ case EXPR_FLOAT:
memcpy(&ptr->left, &left, sizeof(ExprItem));
break;
case EXPR_NONE:
break;
}
switch (rtype) {
- case EXPR_NUM:
case EXPR_SYM:
case EXPR_EXPR:
+ case EXPR_INT:
+ case EXPR_FLOAT:
memcpy(&ptr->right, &right, sizeof(ExprItem));
break;
case EXPR_NONE:
ExprExpr(expr *x)
{
ExprItem e;
- e.expr = x;
+ e.exp = x;
return e;
}
ExprItem
-ExprNum(unsigned long n)
+ExprInt(unsigned long i)
{
ExprItem e;
- e.num = n;
+ e.int_val = i;
+ return e;
+}
+
+ExprItem
+ExprFloat(floatnum *f)
+{
+ ExprItem e;
+
+ e.flt = f;
return e;
}
{
ExprItem e;
- e.num = 0;
+ e.int_val = 0;
return e;
}
expr_simplify(expr *e)
{
int simplified = 0;
+ unsigned long int_val;
/* try to simplify the left side */
if (e->ltype == EXPR_EXPR) {
/* if the left subexpr isn't an IDENT, recurse simplification */
- if (e->left.expr->op != EXPR_IDENT)
- simplified |= expr_simplify(e->left.expr);
+ if (e->left.exp->op != EXPR_IDENT)
+ simplified |= expr_simplify(e->left.exp);
/* if the left subexpr is just an IDENT (or string thereof),
* pull it up into the current node */
- while (e->ltype == EXPR_EXPR && e->left.expr->op == EXPR_IDENT) {
+ while (e->ltype == EXPR_EXPR && e->left.exp->op == EXPR_IDENT) {
ExprItem tmp;
- e->ltype = e->left.expr->rtype;
- memcpy(&tmp, &(e->left.expr->right), sizeof(ExprItem));
- free(e->left.expr);
- memcpy(&(e->left.num), &tmp, sizeof(ExprItem));
+ e->ltype = e->left.exp->rtype;
+ memcpy(&tmp, &(e->left.exp->right), sizeof(ExprItem));
+ free(e->left.exp);
+ memcpy(&(e->left.int_val), &tmp, sizeof(ExprItem));
simplified = 1;
}
} else if (e->ltype == EXPR_SYM) {
- /* if it's a symbol that has a defined value, turn it into a
- * number */
- if (e->left.sym->status & SYM_VALUED) {
- e->ltype = EXPR_NUM;
+ /* try to get value of symbol */
+ if (symrec_get_int_value(e->left.sym, &int_val, 0)) {
+ e->ltype = EXPR_INT;
/* don't try to free the symrec here. */
- e->left.num = e->left.sym->value;
+ e->left.int_val = int_val;
simplified = 1;
}
}
/* ditto on the right */
if (e->rtype == EXPR_EXPR) {
- if (e->right.expr->op != EXPR_IDENT)
- simplified |= expr_simplify(e->right.expr);
+ if (e->right.exp->op != EXPR_IDENT)
+ simplified |= expr_simplify(e->right.exp);
- while (e->rtype == EXPR_EXPR && e->right.expr->op == EXPR_IDENT) {
+ while (e->rtype == EXPR_EXPR && e->right.exp->op == EXPR_IDENT) {
ExprItem tmp;
- e->rtype = e->right.expr->rtype;
- memcpy(&tmp, &(e->right.expr->right), sizeof(ExprItem));
- free(e->right.expr);
- memcpy(&(e->right.num), &tmp, sizeof(ExprItem));
+ e->rtype = e->right.exp->rtype;
+ memcpy(&tmp, &(e->right.exp->right), sizeof(ExprItem));
+ free(e->right.exp);
+ memcpy(&(e->right.int_val), &tmp, sizeof(ExprItem));
simplified = 1;
}
} else if (e->rtype == EXPR_SYM) {
- if (e->right.sym->status & SYM_VALUED) {
- e->rtype = EXPR_NUM;
+ if (symrec_get_int_value(e->right.sym, &int_val, 0)) {
+ e->rtype = EXPR_INT;
/* don't try to free the symrec here. */
- e->right.num = e->right.sym->value;
+ e->right.int_val = int_val;
simplified = 1;
}
}
- if ((e->ltype == EXPR_NUM || e->ltype == EXPR_NONE)
- && e->rtype == EXPR_NUM && e->op != EXPR_IDENT) {
+ if ((e->ltype == EXPR_INT || e->ltype == EXPR_NONE)
+ && e->rtype == EXPR_INT && e->op != EXPR_IDENT) {
switch (e->op) {
case EXPR_ADD:
- e->right.num = e->left.num + e->right.num;
+ e->right.int_val = e->left.int_val + e->right.int_val;
break;
case EXPR_SUB:
- e->right.num = e->left.num - e->right.num;
+ e->right.int_val = e->left.int_val - e->right.int_val;
break;
case EXPR_MUL:
- e->right.num = e->left.num * e->right.num;
+ e->right.int_val = e->left.int_val * e->right.int_val;
break;
case EXPR_DIV:
- e->right.num = e->left.num / e->right.num;
+ e->right.int_val = e->left.int_val / e->right.int_val;
break;
case EXPR_MOD:
- e->right.num = e->left.num % e->right.num;
+ e->right.int_val = e->left.int_val % e->right.int_val;
break;
case EXPR_NEG:
- e->right.num = -(e->right.num);
+ e->right.int_val = -(e->right.int_val);
break;
case EXPR_NOT:
- e->right.num = ~(e->right.num);
+ e->right.int_val = ~(e->right.int_val);
break;
case EXPR_OR:
- e->right.num = e->left.num | e->right.num;
+ e->right.int_val = e->left.int_val | e->right.int_val;
break;
case EXPR_AND:
- e->right.num = e->left.num & e->right.num;
+ e->right.int_val = e->left.int_val & e->right.int_val;
break;
case EXPR_XOR:
- e->right.num = e->left.num ^ e->right.num;
+ e->right.int_val = e->left.int_val ^ e->right.int_val;
break;
case EXPR_SHL:
- e->right.num = e->right.num << e->left.num;
+ e->right.int_val = e->right.int_val << e->left.int_val;
break;
case EXPR_SHR:
- e->right.num = e->right.num << e->left.num;
+ e->right.int_val = e->right.int_val << e->left.int_val;
break;
case EXPR_LOR:
- e->right.num = e->left.num || e->right.num;
+ e->right.int_val = e->left.int_val || e->right.int_val;
break;
case EXPR_LAND:
- e->right.num = e->left.num && e->right.num;
+ e->right.int_val = e->left.int_val && e->right.int_val;
break;
case EXPR_LNOT:
- e->right.num = !e->right.num;
+ e->right.int_val = !e->right.int_val;
break;
case EXPR_EQ:
- e->right.num = e->right.num == e->left.num;
+ e->right.int_val = e->right.int_val == e->left.int_val;
break;
case EXPR_LT:
- e->right.num = e->right.num < e->left.num;
+ e->right.int_val = e->right.int_val < e->left.int_val;
break;
case EXPR_GT:
- e->right.num = e->right.num > e->left.num;
+ e->right.int_val = e->right.int_val > e->left.int_val;
break;
case EXPR_LE:
- e->right.num = e->right.num <= e->left.num;
+ e->right.int_val = e->right.int_val <= e->left.int_val;
break;
case EXPR_GE:
- e->right.num = e->right.num >= e->left.num;
+ e->right.int_val = e->right.int_val >= e->left.int_val;
break;
case EXPR_NE:
- e->right.num = e->right.num != e->left.num;
+ e->right.int_val = e->right.int_val != e->left.int_val;
break;
case EXPR_IDENT:
break;
}
/* catch simple identities like 0+x, 1*x, etc., for x not a num */
- else if (e->ltype == EXPR_NUM && ((e->left.num == 1 && e->op == EXPR_MUL)
- || (e->left.num == 0 &&
+ else if (e->ltype == EXPR_INT && ((e->left.int_val == 1 && e->op == EXPR_MUL)
+ || (e->left.int_val == 0 &&
e->op == EXPR_ADD)
- || (e->left.num == -1 &&
+ || (e->left.int_val == -1 &&
e->op == EXPR_AND)
- || (e->left.num == 0 &&
+ || (e->left.int_val == 0 &&
e->op == EXPR_OR))) {
e->op = EXPR_IDENT;
simplified = 1;
}
/* and the corresponding x+|-0, x*&/1 */
- else if (e->rtype == EXPR_NUM && ((e->right.num == 1 && e->op == EXPR_MUL)
- || (e->right.num == 1 &&
+ else if (e->rtype == EXPR_INT && ((e->right.int_val == 1 && e->op == EXPR_MUL)
+ || (e->right.int_val == 1 &&
e->op == EXPR_DIV)
- || (e->right.num == 0 &&
+ || (e->right.int_val == 0 &&
e->op == EXPR_ADD)
- || (e->right.num == 0 &&
+ || (e->right.int_val == 0 &&
e->op == EXPR_SUB)
- || (e->right.num == -1 &&
+ || (e->right.int_val == -1 &&
e->op == EXPR_AND)
- || (e->right.num == 0 &&
+ || (e->right.int_val == 0 &&
e->op == EXPR_OR)
- || (e->right.num == 0 &&
+ || (e->right.int_val == 0 &&
e->op == EXPR_SHL)
- || (e->right.num == 0 &&
+ || (e->right.int_val == 0 &&
e->op == EXPR_SHR))) {
e->op = EXPR_IDENT;
e->rtype = e->ltype;
int
expr_get_value(expr *e, unsigned long *retval)
{
- while (!(e->op == EXPR_IDENT && e->rtype == EXPR_NUM)
+ while (!(e->op == EXPR_IDENT && e->rtype == EXPR_INT)
&& expr_simplify(e)) ;
- if (e->op == EXPR_IDENT && e->rtype == EXPR_NUM) {
- *retval = e->right.num;
+ if (e->op == EXPR_IDENT && e->rtype == EXPR_INT) {
+ *retval = e->right.int_val;
return 1;
} else
return 0;
{
if (e->op != EXPR_IDENT) {
switch (e->ltype) {
- case EXPR_NUM:
- printf("%lu", e->left.num);
- break;
case EXPR_SYM:
printf("%s", e->left.sym->name);
break;
case EXPR_EXPR:
printf("(");
- expr_print(e->left.expr);
-
+ expr_print(e->left.exp);
printf(")");
+ break;
+ case EXPR_INT:
+ printf("%lu", e->left.int_val);
+ break;
+ case EXPR_FLOAT:
+ floatnum_print(e->left.flt);
+ break;
case EXPR_NONE:
break;
}
break;
}
switch (e->rtype) {
- case EXPR_NUM:
- printf("%lu", e->right.num);
- break;
case EXPR_SYM:
printf("%s", e->right.sym->name);
break;
case EXPR_EXPR:
printf("(");
- expr_print(e->right.expr);
-
+ expr_print(e->right.exp);
printf(")");
+ break;
+ case EXPR_INT:
+ printf("%lu", e->right.int_val);
+ break;
+ case EXPR_FLOAT:
+ floatnum_print(e->right.flt);
+ break;
case EXPR_NONE:
break;
}
/* $IdPath$
* Expression handling
*
- * Copyright (C) 2001 Michael Urman
+ * Copyright (C) 2001 Michael Urman, Peter Johnson
*
* This file is part of YASM.
*
#include "globals.h"
#include "errwarn.h"
+#include "floatnum.h"
#include "expr.h"
#include "symrec.h"
ptr->op = op;
ptr->rtype = rtype;
switch (ltype) {
- case EXPR_NUM:
case EXPR_SYM:
case EXPR_EXPR:
+ case EXPR_INT:
+ case EXPR_FLOAT:
memcpy(&ptr->left, &left, sizeof(ExprItem));
break;
case EXPR_NONE:
break;
}
switch (rtype) {
- case EXPR_NUM:
case EXPR_SYM:
case EXPR_EXPR:
+ case EXPR_INT:
+ case EXPR_FLOAT:
memcpy(&ptr->right, &right, sizeof(ExprItem));
break;
case EXPR_NONE:
ExprExpr(expr *x)
{
ExprItem e;
- e.expr = x;
+ e.exp = x;
return e;
}
ExprItem
-ExprNum(unsigned long n)
+ExprInt(unsigned long i)
{
ExprItem e;
- e.num = n;
+ e.int_val = i;
+ return e;
+}
+
+ExprItem
+ExprFloat(floatnum *f)
+{
+ ExprItem e;
+
+ e.flt = f;
return e;
}
{
ExprItem e;
- e.num = 0;
+ e.int_val = 0;
return e;
}
expr_simplify(expr *e)
{
int simplified = 0;
+ unsigned long int_val;
/* try to simplify the left side */
if (e->ltype == EXPR_EXPR) {
/* if the left subexpr isn't an IDENT, recurse simplification */
- if (e->left.expr->op != EXPR_IDENT)
- simplified |= expr_simplify(e->left.expr);
+ if (e->left.exp->op != EXPR_IDENT)
+ simplified |= expr_simplify(e->left.exp);
/* if the left subexpr is just an IDENT (or string thereof),
* pull it up into the current node */
- while (e->ltype == EXPR_EXPR && e->left.expr->op == EXPR_IDENT) {
+ while (e->ltype == EXPR_EXPR && e->left.exp->op == EXPR_IDENT) {
ExprItem tmp;
- e->ltype = e->left.expr->rtype;
- memcpy(&tmp, &(e->left.expr->right), sizeof(ExprItem));
- free(e->left.expr);
- memcpy(&(e->left.num), &tmp, sizeof(ExprItem));
+ e->ltype = e->left.exp->rtype;
+ memcpy(&tmp, &(e->left.exp->right), sizeof(ExprItem));
+ free(e->left.exp);
+ memcpy(&(e->left.int_val), &tmp, sizeof(ExprItem));
simplified = 1;
}
} else if (e->ltype == EXPR_SYM) {
- /* if it's a symbol that has a defined value, turn it into a
- * number */
- if (e->left.sym->status & SYM_VALUED) {
- e->ltype = EXPR_NUM;
+ /* try to get value of symbol */
+ if (symrec_get_int_value(e->left.sym, &int_val, 0)) {
+ e->ltype = EXPR_INT;
/* don't try to free the symrec here. */
- e->left.num = e->left.sym->value;
+ e->left.int_val = int_val;
simplified = 1;
}
}
/* ditto on the right */
if (e->rtype == EXPR_EXPR) {
- if (e->right.expr->op != EXPR_IDENT)
- simplified |= expr_simplify(e->right.expr);
+ if (e->right.exp->op != EXPR_IDENT)
+ simplified |= expr_simplify(e->right.exp);
- while (e->rtype == EXPR_EXPR && e->right.expr->op == EXPR_IDENT) {
+ while (e->rtype == EXPR_EXPR && e->right.exp->op == EXPR_IDENT) {
ExprItem tmp;
- e->rtype = e->right.expr->rtype;
- memcpy(&tmp, &(e->right.expr->right), sizeof(ExprItem));
- free(e->right.expr);
- memcpy(&(e->right.num), &tmp, sizeof(ExprItem));
+ e->rtype = e->right.exp->rtype;
+ memcpy(&tmp, &(e->right.exp->right), sizeof(ExprItem));
+ free(e->right.exp);
+ memcpy(&(e->right.int_val), &tmp, sizeof(ExprItem));
simplified = 1;
}
} else if (e->rtype == EXPR_SYM) {
- if (e->right.sym->status & SYM_VALUED) {
- e->rtype = EXPR_NUM;
+ if (symrec_get_int_value(e->right.sym, &int_val, 0)) {
+ e->rtype = EXPR_INT;
/* don't try to free the symrec here. */
- e->right.num = e->right.sym->value;
+ e->right.int_val = int_val;
simplified = 1;
}
}
- if ((e->ltype == EXPR_NUM || e->ltype == EXPR_NONE)
- && e->rtype == EXPR_NUM && e->op != EXPR_IDENT) {
+ if ((e->ltype == EXPR_INT || e->ltype == EXPR_NONE)
+ && e->rtype == EXPR_INT && e->op != EXPR_IDENT) {
switch (e->op) {
case EXPR_ADD:
- e->right.num = e->left.num + e->right.num;
+ e->right.int_val = e->left.int_val + e->right.int_val;
break;
case EXPR_SUB:
- e->right.num = e->left.num - e->right.num;
+ e->right.int_val = e->left.int_val - e->right.int_val;
break;
case EXPR_MUL:
- e->right.num = e->left.num * e->right.num;
+ e->right.int_val = e->left.int_val * e->right.int_val;
break;
case EXPR_DIV:
- e->right.num = e->left.num / e->right.num;
+ e->right.int_val = e->left.int_val / e->right.int_val;
break;
case EXPR_MOD:
- e->right.num = e->left.num % e->right.num;
+ e->right.int_val = e->left.int_val % e->right.int_val;
break;
case EXPR_NEG:
- e->right.num = -(e->right.num);
+ e->right.int_val = -(e->right.int_val);
break;
case EXPR_NOT:
- e->right.num = ~(e->right.num);
+ e->right.int_val = ~(e->right.int_val);
break;
case EXPR_OR:
- e->right.num = e->left.num | e->right.num;
+ e->right.int_val = e->left.int_val | e->right.int_val;
break;
case EXPR_AND:
- e->right.num = e->left.num & e->right.num;
+ e->right.int_val = e->left.int_val & e->right.int_val;
break;
case EXPR_XOR:
- e->right.num = e->left.num ^ e->right.num;
+ e->right.int_val = e->left.int_val ^ e->right.int_val;
break;
case EXPR_SHL:
- e->right.num = e->right.num << e->left.num;
+ e->right.int_val = e->right.int_val << e->left.int_val;
break;
case EXPR_SHR:
- e->right.num = e->right.num << e->left.num;
+ e->right.int_val = e->right.int_val << e->left.int_val;
break;
case EXPR_LOR:
- e->right.num = e->left.num || e->right.num;
+ e->right.int_val = e->left.int_val || e->right.int_val;
break;
case EXPR_LAND:
- e->right.num = e->left.num && e->right.num;
+ e->right.int_val = e->left.int_val && e->right.int_val;
break;
case EXPR_LNOT:
- e->right.num = !e->right.num;
+ e->right.int_val = !e->right.int_val;
break;
case EXPR_EQ:
- e->right.num = e->right.num == e->left.num;
+ e->right.int_val = e->right.int_val == e->left.int_val;
break;
case EXPR_LT:
- e->right.num = e->right.num < e->left.num;
+ e->right.int_val = e->right.int_val < e->left.int_val;
break;
case EXPR_GT:
- e->right.num = e->right.num > e->left.num;
+ e->right.int_val = e->right.int_val > e->left.int_val;
break;
case EXPR_LE:
- e->right.num = e->right.num <= e->left.num;
+ e->right.int_val = e->right.int_val <= e->left.int_val;
break;
case EXPR_GE:
- e->right.num = e->right.num >= e->left.num;
+ e->right.int_val = e->right.int_val >= e->left.int_val;
break;
case EXPR_NE:
- e->right.num = e->right.num != e->left.num;
+ e->right.int_val = e->right.int_val != e->left.int_val;
break;
case EXPR_IDENT:
break;
}
/* catch simple identities like 0+x, 1*x, etc., for x not a num */
- else if (e->ltype == EXPR_NUM && ((e->left.num == 1 && e->op == EXPR_MUL)
- || (e->left.num == 0 &&
+ else if (e->ltype == EXPR_INT && ((e->left.int_val == 1 && e->op == EXPR_MUL)
+ || (e->left.int_val == 0 &&
e->op == EXPR_ADD)
- || (e->left.num == -1 &&
+ || (e->left.int_val == -1 &&
e->op == EXPR_AND)
- || (e->left.num == 0 &&
+ || (e->left.int_val == 0 &&
e->op == EXPR_OR))) {
e->op = EXPR_IDENT;
simplified = 1;
}
/* and the corresponding x+|-0, x*&/1 */
- else if (e->rtype == EXPR_NUM && ((e->right.num == 1 && e->op == EXPR_MUL)
- || (e->right.num == 1 &&
+ else if (e->rtype == EXPR_INT && ((e->right.int_val == 1 && e->op == EXPR_MUL)
+ || (e->right.int_val == 1 &&
e->op == EXPR_DIV)
- || (e->right.num == 0 &&
+ || (e->right.int_val == 0 &&
e->op == EXPR_ADD)
- || (e->right.num == 0 &&
+ || (e->right.int_val == 0 &&
e->op == EXPR_SUB)
- || (e->right.num == -1 &&
+ || (e->right.int_val == -1 &&
e->op == EXPR_AND)
- || (e->right.num == 0 &&
+ || (e->right.int_val == 0 &&
e->op == EXPR_OR)
- || (e->right.num == 0 &&
+ || (e->right.int_val == 0 &&
e->op == EXPR_SHL)
- || (e->right.num == 0 &&
+ || (e->right.int_val == 0 &&
e->op == EXPR_SHR))) {
e->op = EXPR_IDENT;
e->rtype = e->ltype;
int
expr_get_value(expr *e, unsigned long *retval)
{
- while (!(e->op == EXPR_IDENT && e->rtype == EXPR_NUM)
+ while (!(e->op == EXPR_IDENT && e->rtype == EXPR_INT)
&& expr_simplify(e)) ;
- if (e->op == EXPR_IDENT && e->rtype == EXPR_NUM) {
- *retval = e->right.num;
+ if (e->op == EXPR_IDENT && e->rtype == EXPR_INT) {
+ *retval = e->right.int_val;
return 1;
} else
return 0;
{
if (e->op != EXPR_IDENT) {
switch (e->ltype) {
- case EXPR_NUM:
- printf("%lu", e->left.num);
- break;
case EXPR_SYM:
printf("%s", e->left.sym->name);
break;
case EXPR_EXPR:
printf("(");
- expr_print(e->left.expr);
-
+ expr_print(e->left.exp);
printf(")");
+ break;
+ case EXPR_INT:
+ printf("%lu", e->left.int_val);
+ break;
+ case EXPR_FLOAT:
+ floatnum_print(e->left.flt);
+ break;
case EXPR_NONE:
break;
}
break;
}
switch (e->rtype) {
- case EXPR_NUM:
- printf("%lu", e->right.num);
- break;
case EXPR_SYM:
printf("%s", e->right.sym->name);
break;
case EXPR_EXPR:
printf("(");
- expr_print(e->right.expr);
-
+ expr_print(e->right.exp);
printf(")");
+ break;
+ case EXPR_INT:
+ printf("%lu", e->right.int_val);
+ break;
+ case EXPR_FLOAT:
+ floatnum_print(e->right.flt);
+ break;
case EXPR_NONE:
break;
}
#include "globals.h"
#include "errwarn.h"
+#include "floatnum.h"
#include "expr.h"
#include "bytecode.h"
+#include "section.h"
RCSID("$IdPath$");
ptr = &im_static;
/* FIXME: this will leak expr's if static is used */
- ptr->val = expr_new_ident(EXPR_NUM, ExprNum(int_val));
+ ptr->val = expr_new_ident(EXPR_INT, ExprInt(int_val));
if ((int_val & 0xFF) == int_val)
ptr->len = 1;
return bc;
}
+int
+bytecode_get_offset(section *sect, bytecode *bc, unsigned long *ret_val)
+{
+ return 0; /* TODO */
+}
+
void
bytecode_print(bytecode *bc)
{
printf("Offset=%lx BITS=%u\n", bc->offset, bc->mode_bits);
}
-void
+bytecode *
bytecodes_append(bytecodehead *headp, bytecode *bc)
{
if (bc) {
- if (bc->type != BC_EMPTY)
+ if (bc->type != BC_EMPTY) {
STAILQ_INSERT_TAIL(headp, bc, link);
- else
+ return bc;
+ } else {
free(bc);
+ }
}
+ return (bytecode *)NULL;
}
dataval *
}
dataval *
-dataval_new_float(double float_val)
+dataval_new_float(floatnum *flt)
{
dataval *retval = malloc(sizeof(dataval));
Fatal(FATAL_NOMEM);
retval->type = DV_FLOAT;
- retval->data.float_val = float_val;
+ retval->data.flt = flt;
return retval;
}
printf("\n");
break;
case DV_FLOAT:
- printf(" Float=%e\n", cur->data.float_val);
+ printf(" Float=");
+ floatnum_print(cur->data.flt);
+ printf("\n");
break;
case DV_STRING:
printf(" String=%s\n", cur->data.str_val);
#ifndef YASM_BYTECODE_H
#define YASM_BYTECODE_H
+struct section_s;
+
typedef struct effaddr_s {
struct expr_s *disp; /* address displacement */
unsigned char len; /* length of disp (in bytes), 0 if none */
union {
struct expr_s *exp;
- double float_val;
+ struct floatnum_s *flt;
char *str_val;
} data;
} dataval;
bytecode *bytecode_new_reserve(struct expr_s *numitems,
unsigned long itemsize);
+/* Gets the offset of the bytecode specified by bc if possible.
+ * Return value is IF POSSIBLE, not the value.
+ */
+int bytecode_get_offset(struct section_s *sect, bytecode *bc,
+ unsigned long *ret_val);
+
void bytecode_print(bytecode *bc);
/* void bytecodes_initialize(bytecodehead *headp); */
/* Adds bc to the list of bytecodes headp.
* NOTE: Does not make a copy of bc; so don't pass this function
* static or local variables, and discard the bc pointer after calling
- * this function.
+ * this function. If bc was actually appended (it wasn't NULL or empty),
+ * then returns bc, otherwise returns NULL.
*/
-void bytecodes_append(bytecodehead *headp, bytecode *bc);
+bytecode *bytecodes_append(bytecodehead *headp, bytecode *bc);
dataval *dataval_new_expr(struct expr_s *exp);
-dataval *dataval_new_float(double float_val);
+dataval *dataval_new_float(struct floatnum_s *flt);
dataval *dataval_new_string(char *str_val);
void dataval_print(datavalhead *head);
/* $IdPath$
* Expression handling
*
- * Copyright (C) 2001 Michael Urman
+ * Copyright (C) 2001 Michael Urman, Peter Johnson
*
* This file is part of YASM.
*
#include "globals.h"
#include "errwarn.h"
+#include "floatnum.h"
#include "expr.h"
#include "symrec.h"
ptr->op = op;
ptr->rtype = rtype;
switch (ltype) {
- case EXPR_NUM:
case EXPR_SYM:
case EXPR_EXPR:
+ case EXPR_INT:
+ case EXPR_FLOAT:
memcpy(&ptr->left, &left, sizeof(ExprItem));
break;
case EXPR_NONE:
break;
}
switch (rtype) {
- case EXPR_NUM:
case EXPR_SYM:
case EXPR_EXPR:
+ case EXPR_INT:
+ case EXPR_FLOAT:
memcpy(&ptr->right, &right, sizeof(ExprItem));
break;
case EXPR_NONE:
ExprExpr(expr *x)
{
ExprItem e;
- e.expr = x;
+ e.exp = x;
return e;
}
ExprItem
-ExprNum(unsigned long n)
+ExprInt(unsigned long i)
{
ExprItem e;
- e.num = n;
+ e.int_val = i;
+ return e;
+}
+
+ExprItem
+ExprFloat(floatnum *f)
+{
+ ExprItem e;
+
+ e.flt = f;
return e;
}
{
ExprItem e;
- e.num = 0;
+ e.int_val = 0;
return e;
}
expr_simplify(expr *e)
{
int simplified = 0;
+ unsigned long int_val;
/* try to simplify the left side */
if (e->ltype == EXPR_EXPR) {
/* if the left subexpr isn't an IDENT, recurse simplification */
- if (e->left.expr->op != EXPR_IDENT)
- simplified |= expr_simplify(e->left.expr);
+ if (e->left.exp->op != EXPR_IDENT)
+ simplified |= expr_simplify(e->left.exp);
/* if the left subexpr is just an IDENT (or string thereof),
* pull it up into the current node */
- while (e->ltype == EXPR_EXPR && e->left.expr->op == EXPR_IDENT) {
+ while (e->ltype == EXPR_EXPR && e->left.exp->op == EXPR_IDENT) {
ExprItem tmp;
- e->ltype = e->left.expr->rtype;
- memcpy(&tmp, &(e->left.expr->right), sizeof(ExprItem));
- free(e->left.expr);
- memcpy(&(e->left.num), &tmp, sizeof(ExprItem));
+ e->ltype = e->left.exp->rtype;
+ memcpy(&tmp, &(e->left.exp->right), sizeof(ExprItem));
+ free(e->left.exp);
+ memcpy(&(e->left.int_val), &tmp, sizeof(ExprItem));
simplified = 1;
}
} else if (e->ltype == EXPR_SYM) {
- /* if it's a symbol that has a defined value, turn it into a
- * number */
- if (e->left.sym->status & SYM_VALUED) {
- e->ltype = EXPR_NUM;
+ /* try to get value of symbol */
+ if (symrec_get_int_value(e->left.sym, &int_val, 0)) {
+ e->ltype = EXPR_INT;
/* don't try to free the symrec here. */
- e->left.num = e->left.sym->value;
+ e->left.int_val = int_val;
simplified = 1;
}
}
/* ditto on the right */
if (e->rtype == EXPR_EXPR) {
- if (e->right.expr->op != EXPR_IDENT)
- simplified |= expr_simplify(e->right.expr);
+ if (e->right.exp->op != EXPR_IDENT)
+ simplified |= expr_simplify(e->right.exp);
- while (e->rtype == EXPR_EXPR && e->right.expr->op == EXPR_IDENT) {
+ while (e->rtype == EXPR_EXPR && e->right.exp->op == EXPR_IDENT) {
ExprItem tmp;
- e->rtype = e->right.expr->rtype;
- memcpy(&tmp, &(e->right.expr->right), sizeof(ExprItem));
- free(e->right.expr);
- memcpy(&(e->right.num), &tmp, sizeof(ExprItem));
+ e->rtype = e->right.exp->rtype;
+ memcpy(&tmp, &(e->right.exp->right), sizeof(ExprItem));
+ free(e->right.exp);
+ memcpy(&(e->right.int_val), &tmp, sizeof(ExprItem));
simplified = 1;
}
} else if (e->rtype == EXPR_SYM) {
- if (e->right.sym->status & SYM_VALUED) {
- e->rtype = EXPR_NUM;
+ if (symrec_get_int_value(e->right.sym, &int_val, 0)) {
+ e->rtype = EXPR_INT;
/* don't try to free the symrec here. */
- e->right.num = e->right.sym->value;
+ e->right.int_val = int_val;
simplified = 1;
}
}
- if ((e->ltype == EXPR_NUM || e->ltype == EXPR_NONE)
- && e->rtype == EXPR_NUM && e->op != EXPR_IDENT) {
+ if ((e->ltype == EXPR_INT || e->ltype == EXPR_NONE)
+ && e->rtype == EXPR_INT && e->op != EXPR_IDENT) {
switch (e->op) {
case EXPR_ADD:
- e->right.num = e->left.num + e->right.num;
+ e->right.int_val = e->left.int_val + e->right.int_val;
break;
case EXPR_SUB:
- e->right.num = e->left.num - e->right.num;
+ e->right.int_val = e->left.int_val - e->right.int_val;
break;
case EXPR_MUL:
- e->right.num = e->left.num * e->right.num;
+ e->right.int_val = e->left.int_val * e->right.int_val;
break;
case EXPR_DIV:
- e->right.num = e->left.num / e->right.num;
+ e->right.int_val = e->left.int_val / e->right.int_val;
break;
case EXPR_MOD:
- e->right.num = e->left.num % e->right.num;
+ e->right.int_val = e->left.int_val % e->right.int_val;
break;
case EXPR_NEG:
- e->right.num = -(e->right.num);
+ e->right.int_val = -(e->right.int_val);
break;
case EXPR_NOT:
- e->right.num = ~(e->right.num);
+ e->right.int_val = ~(e->right.int_val);
break;
case EXPR_OR:
- e->right.num = e->left.num | e->right.num;
+ e->right.int_val = e->left.int_val | e->right.int_val;
break;
case EXPR_AND:
- e->right.num = e->left.num & e->right.num;
+ e->right.int_val = e->left.int_val & e->right.int_val;
break;
case EXPR_XOR:
- e->right.num = e->left.num ^ e->right.num;
+ e->right.int_val = e->left.int_val ^ e->right.int_val;
break;
case EXPR_SHL:
- e->right.num = e->right.num << e->left.num;
+ e->right.int_val = e->right.int_val << e->left.int_val;
break;
case EXPR_SHR:
- e->right.num = e->right.num << e->left.num;
+ e->right.int_val = e->right.int_val << e->left.int_val;
break;
case EXPR_LOR:
- e->right.num = e->left.num || e->right.num;
+ e->right.int_val = e->left.int_val || e->right.int_val;
break;
case EXPR_LAND:
- e->right.num = e->left.num && e->right.num;
+ e->right.int_val = e->left.int_val && e->right.int_val;
break;
case EXPR_LNOT:
- e->right.num = !e->right.num;
+ e->right.int_val = !e->right.int_val;
break;
case EXPR_EQ:
- e->right.num = e->right.num == e->left.num;
+ e->right.int_val = e->right.int_val == e->left.int_val;
break;
case EXPR_LT:
- e->right.num = e->right.num < e->left.num;
+ e->right.int_val = e->right.int_val < e->left.int_val;
break;
case EXPR_GT:
- e->right.num = e->right.num > e->left.num;
+ e->right.int_val = e->right.int_val > e->left.int_val;
break;
case EXPR_LE:
- e->right.num = e->right.num <= e->left.num;
+ e->right.int_val = e->right.int_val <= e->left.int_val;
break;
case EXPR_GE:
- e->right.num = e->right.num >= e->left.num;
+ e->right.int_val = e->right.int_val >= e->left.int_val;
break;
case EXPR_NE:
- e->right.num = e->right.num != e->left.num;
+ e->right.int_val = e->right.int_val != e->left.int_val;
break;
case EXPR_IDENT:
break;
}
/* catch simple identities like 0+x, 1*x, etc., for x not a num */
- else if (e->ltype == EXPR_NUM && ((e->left.num == 1 && e->op == EXPR_MUL)
- || (e->left.num == 0 &&
+ else if (e->ltype == EXPR_INT && ((e->left.int_val == 1 && e->op == EXPR_MUL)
+ || (e->left.int_val == 0 &&
e->op == EXPR_ADD)
- || (e->left.num == -1 &&
+ || (e->left.int_val == -1 &&
e->op == EXPR_AND)
- || (e->left.num == 0 &&
+ || (e->left.int_val == 0 &&
e->op == EXPR_OR))) {
e->op = EXPR_IDENT;
simplified = 1;
}
/* and the corresponding x+|-0, x*&/1 */
- else if (e->rtype == EXPR_NUM && ((e->right.num == 1 && e->op == EXPR_MUL)
- || (e->right.num == 1 &&
+ else if (e->rtype == EXPR_INT && ((e->right.int_val == 1 && e->op == EXPR_MUL)
+ || (e->right.int_val == 1 &&
e->op == EXPR_DIV)
- || (e->right.num == 0 &&
+ || (e->right.int_val == 0 &&
e->op == EXPR_ADD)
- || (e->right.num == 0 &&
+ || (e->right.int_val == 0 &&
e->op == EXPR_SUB)
- || (e->right.num == -1 &&
+ || (e->right.int_val == -1 &&
e->op == EXPR_AND)
- || (e->right.num == 0 &&
+ || (e->right.int_val == 0 &&
e->op == EXPR_OR)
- || (e->right.num == 0 &&
+ || (e->right.int_val == 0 &&
e->op == EXPR_SHL)
- || (e->right.num == 0 &&
+ || (e->right.int_val == 0 &&
e->op == EXPR_SHR))) {
e->op = EXPR_IDENT;
e->rtype = e->ltype;
int
expr_get_value(expr *e, unsigned long *retval)
{
- while (!(e->op == EXPR_IDENT && e->rtype == EXPR_NUM)
+ while (!(e->op == EXPR_IDENT && e->rtype == EXPR_INT)
&& expr_simplify(e)) ;
- if (e->op == EXPR_IDENT && e->rtype == EXPR_NUM) {
- *retval = e->right.num;
+ if (e->op == EXPR_IDENT && e->rtype == EXPR_INT) {
+ *retval = e->right.int_val;
return 1;
} else
return 0;
{
if (e->op != EXPR_IDENT) {
switch (e->ltype) {
- case EXPR_NUM:
- printf("%lu", e->left.num);
- break;
case EXPR_SYM:
printf("%s", e->left.sym->name);
break;
case EXPR_EXPR:
printf("(");
- expr_print(e->left.expr);
-
+ expr_print(e->left.exp);
printf(")");
+ break;
+ case EXPR_INT:
+ printf("%lu", e->left.int_val);
+ break;
+ case EXPR_FLOAT:
+ floatnum_print(e->left.flt);
+ break;
case EXPR_NONE:
break;
}
break;
}
switch (e->rtype) {
- case EXPR_NUM:
- printf("%lu", e->right.num);
- break;
case EXPR_SYM:
printf("%s", e->right.sym->name);
break;
case EXPR_EXPR:
printf("(");
- expr_print(e->right.expr);
-
+ expr_print(e->right.exp);
printf(")");
+ break;
+ case EXPR_INT:
+ printf("%lu", e->right.int_val);
+ break;
+ case EXPR_FLOAT:
+ floatnum_print(e->right.flt);
+ break;
case EXPR_NONE:
break;
}
/* $IdPath$
* Expression handling header file
*
- * Copyright (C) 2001 Michael Urman
+ * Copyright (C) 2001 Michael Urman, Peter Johnson
*
* This file is part of YASM.
*
typedef enum {
EXPR_NONE, /* for left side of a NOT, NEG, etc. */
- EXPR_NUM,
+ EXPR_SYM,
EXPR_EXPR,
- EXPR_SYM
+ EXPR_INT,
+ EXPR_FLOAT
} ExprType;
typedef union expritem_u {
struct symrec_s *sym;
- struct expr_s *expr;
- unsigned long num;
+ struct expr_s *exp;
+ unsigned long int_val;
+ struct floatnum_s *flt;
} ExprItem;
typedef struct expr_s {
ExprItem ExprSym(struct symrec_s *);
ExprItem ExprExpr(expr *);
-ExprItem ExprNum(unsigned long);
+ExprItem ExprInt(unsigned long);
+ExprItem ExprFloat(struct floatnum_s *);
ExprItem ExprNone(void);
#define expr_new_tree(l,o,r) \
--- /dev/null
+/* $IdPath$
+ * Floating point number functions.
+ *
+ * Copyright (C) 2001 Peter Johnson
+ *
+ * This file is part of YASM.
+ *
+ * YASM is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * YASM is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "util.h"
+
+#include <stdio.h>
+
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+#endif
+
+#include "errwarn.h"
+#include "floatnum.h"
+
+RCSID("$IdPath$");
+
+floatnum *
+floatnum_new(char *str)
+{
+ floatnum *flt = malloc(sizeof(floatnum));
+ if (!flt)
+ Fatal(FATAL_NOMEM);
+ /* TODO */
+ return flt;
+}
+
+unsigned long
+floatnum_get_int(floatnum *flt)
+{
+ return 0; /* TODO */
+}
+
+unsigned char *
+floatnum_get_single(unsigned char *ptr, floatnum *flt)
+{
+ return ptr; /* TODO */
+}
+
+unsigned char *
+floatnum_get_double(unsigned char *ptr, floatnum *flt)
+{
+ return ptr; /* TODO */
+}
+
+unsigned char *
+floatnum_get_extended(unsigned char *ptr, floatnum *flt)
+{
+ return ptr; /* TODO */
+}
+
+void
+floatnum_print(floatnum *flt)
+{
+ /* TODO */
+}
--- /dev/null
+/* $IdPath$
+ * Floating point number functions header file.
+ *
+ * Copyright (C) 2001 Peter Johnson
+ *
+ * This file is part of YASM.
+ *
+ * YASM is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * YASM is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef YASM_FLOATNUM_H
+#define YASM_FLOATNUM_H
+
+typedef struct floatnum_s {
+ unsigned char extval[10]; /* float stored in extended precision */
+} floatnum;
+
+floatnum *floatnum_new(char *str);
+unsigned long floatnum_get_int(floatnum *flt);
+unsigned char *floatnum_get_single(unsigned char *ptr, floatnum *flt);
+unsigned char *floatnum_get_double(unsigned char *ptr, floatnum *flt);
+unsigned char *floatnum_get_extended(unsigned char *ptr, floatnum *flt);
+
+void floatnum_print(floatnum *flt);
+
+#endif
#include "globals.h"
#include "errwarn.h"
+#include "floatnum.h"
#include "expr.h"
#include "symrec.h"
extern section *nasm_parser_cur_section;
extern char *nasm_parser_locallabel_base;
+static bytecode *nasm_parser_prev_bc = (bytecode *)NULL;
+static bytecode *nasm_parser_temp_bc;
+
%}
%union {
unsigned long int_val;
char *str_val;
- double double_val;
- symrec *sym;
- struct {
- char *name;
- int line;
- } syminfo;
+ floatnum *flt;
unsigned char groupdata[4];
effaddr *ea;
expr *exp;
}
%token <int_val> INTNUM
-%token <double_val> FLTNUM
+%token <flt> FLTNUM
%token <str_val> DIRECTIVE_NAME DIRECTIVE_VAL STRING
%token <int_val> BYTE WORD DWORD QWORD TWORD DQWORD
%token <int_val> DECLARE_DATA
%token <int_val> REG_AL REG_CL REG_DL REG_BL REG_AH REG_CH REG_DH REG_BH
%token <int_val> REG_ES REG_CS REG_SS REG_DS REG_FS REG_GS
%token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD
-%token <syminfo> ID LOCAL_ID SPECIAL_ID
+%token <str_val> ID LOCAL_ID SPECIAL_ID
/* instruction tokens (dynamically generated) */
/* @TOKENS@ */
%type <ea> rm8 rm16 rm32 rm64 rm128
%type <im_val> imm imm8x imm16x imm32x imm8 imm16 imm32
%type <exp> expr expr_no_string
-%type <syminfo> explabel
-%type <sym> label_id
+%type <str_val> explabel label_id
%type <tgt_val> target
%type <data> dataval
%type <datahead> datavals
%%
input: /* empty */
| input line {
- bytecodes_append(&nasm_parser_cur_section->bc, $2);
+ nasm_parser_temp_bc = bytecodes_append(&nasm_parser_cur_section->bc,
+ $2);
+ if (nasm_parser_temp_bc)
+ nasm_parser_prev_bc = nasm_parser_temp_bc;
line_number++;
}
;
}
;
-label: label_id { $1->value = 0; } /* TODO: add pointer to bytecode */
- | label_id ':' { $1->value = 0; } /* TODO: add pointer to bytecode */
+label: label_id {
+ symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc);
+ }
+ | label_id ':' {
+ symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc);
+ }
;
label_id: ID {
- $$ = symrec_define($1.name, SYM_LABEL);
- nasm_parser_locallabel_base = strdup($1.name);
+ $$ = $1;
+ nasm_parser_locallabel_base = strdup($1);
}
- | SPECIAL_ID { $$ = symrec_define($1.name, SYM_LABEL); }
- | LOCAL_ID { $$ = symrec_define($1.name, SYM_LABEL); }
+ | SPECIAL_ID
+ | LOCAL_ID
;
/* directives */
directive: '[' DIRECTIVE_NAME DIRECTIVE_VAL ']' {
- if (strcasecmp($2, "section") == 0)
+ if (strcasecmp($2, "section") == 0) {
nasm_parser_cur_section = sections_switch(&nasm_parser_sections,
nasm_parser_objfmt, $3);
- else
+ nasm_parser_prev_bc = (bytecode *)NULL;
+ } else {
printf("Directive: Name='%s' Value='%s'\n", $2, $3);
+ }
}
| '[' DIRECTIVE_NAME DIRECTIVE_VAL error {
Error(_("missing `%c'"), ']');
;
/* expression trees */
-expr_no_string: INTNUM { $$ = expr_new_ident(EXPR_NUM, ExprNum($1)); }
+expr_no_string: INTNUM { $$ = expr_new_ident(EXPR_INT, ExprInt($1)); }
| explabel {
- $$ = expr_new_ident(EXPR_SYM, ExprSym(symrec_use($1.name, SYM_LABEL)));
+ $$ = expr_new_ident(EXPR_SYM, ExprSym(symrec_use($1)));
}
/*| expr '||' expr { $$ = expr_new_tree($1, EXPR_LOR, $3); }*/
| expr '|' expr { $$ = expr_new_tree($1, EXPR_OR, $3); }
expr: expr_no_string
| STRING {
- $$ = expr_new_ident (EXPR_NUM, ExprNum(ConvertCharConstToInt($1)));
+ $$ = expr_new_ident (EXPR_INT, ExprInt(ConvertCharConstToInt($1)));
}
;
#include "globals.h"
#include "errwarn.h"
+#include "floatnum.h"
#include "expr.h"
#include "symrec.h"
extern section *nasm_parser_cur_section;
extern char *nasm_parser_locallabel_base;
+static bytecode *nasm_parser_prev_bc = (bytecode *)NULL;
+static bytecode *nasm_parser_temp_bc;
+
%}
%union {
unsigned long int_val;
char *str_val;
- double double_val;
- symrec *sym;
- struct {
- char *name;
- int line;
- } syminfo;
+ floatnum *flt;
unsigned char groupdata[4];
effaddr *ea;
expr *exp;
}
%token <int_val> INTNUM
-%token <double_val> FLTNUM
+%token <flt> FLTNUM
%token <str_val> DIRECTIVE_NAME DIRECTIVE_VAL STRING
%token <int_val> BYTE WORD DWORD QWORD TWORD DQWORD
%token <int_val> DECLARE_DATA
%token <int_val> REG_AL REG_CL REG_DL REG_BL REG_AH REG_CH REG_DH REG_BH
%token <int_val> REG_ES REG_CS REG_SS REG_DS REG_FS REG_GS
%token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD
-%token <syminfo> ID LOCAL_ID SPECIAL_ID
+%token <str_val> ID LOCAL_ID SPECIAL_ID
/* instruction tokens (dynamically generated) */
/* @TOKENS@ */
%type <ea> rm8 rm16 rm32 rm64 rm128
%type <im_val> imm imm8x imm16x imm32x imm8 imm16 imm32
%type <exp> expr expr_no_string
-%type <syminfo> explabel
-%type <sym> label_id
+%type <str_val> explabel label_id
%type <tgt_val> target
%type <data> dataval
%type <datahead> datavals
%%
input: /* empty */
| input line {
- bytecodes_append(&nasm_parser_cur_section->bc, $2);
+ nasm_parser_temp_bc = bytecodes_append(&nasm_parser_cur_section->bc,
+ $2);
+ if (nasm_parser_temp_bc)
+ nasm_parser_prev_bc = nasm_parser_temp_bc;
line_number++;
}
;
}
;
-label: label_id { $1->value = 0; } /* TODO: add pointer to bytecode */
- | label_id ':' { $1->value = 0; } /* TODO: add pointer to bytecode */
+label: label_id {
+ symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc);
+ }
+ | label_id ':' {
+ symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc);
+ }
;
label_id: ID {
- $$ = symrec_define($1.name, SYM_LABEL);
- nasm_parser_locallabel_base = strdup($1.name);
+ $$ = $1;
+ nasm_parser_locallabel_base = strdup($1);
}
- | SPECIAL_ID { $$ = symrec_define($1.name, SYM_LABEL); }
- | LOCAL_ID { $$ = symrec_define($1.name, SYM_LABEL); }
+ | SPECIAL_ID
+ | LOCAL_ID
;
/* directives */
directive: '[' DIRECTIVE_NAME DIRECTIVE_VAL ']' {
- if (strcasecmp($2, "section") == 0)
+ if (strcasecmp($2, "section") == 0) {
nasm_parser_cur_section = sections_switch(&nasm_parser_sections,
nasm_parser_objfmt, $3);
- else
+ nasm_parser_prev_bc = (bytecode *)NULL;
+ } else {
printf("Directive: Name='%s' Value='%s'\n", $2, $3);
+ }
}
| '[' DIRECTIVE_NAME DIRECTIVE_VAL error {
Error(_("missing `%c'"), ']');
;
/* expression trees */
-expr_no_string: INTNUM { $$ = expr_new_ident(EXPR_NUM, ExprNum($1)); }
+expr_no_string: INTNUM { $$ = expr_new_ident(EXPR_INT, ExprInt($1)); }
| explabel {
- $$ = expr_new_ident(EXPR_SYM, ExprSym(symrec_use($1.name, SYM_LABEL)));
+ $$ = expr_new_ident(EXPR_SYM, ExprSym(symrec_use($1)));
}
/*| expr '||' expr { $$ = expr_new_tree($1, EXPR_LOR, $3); }*/
| expr '|' expr { $$ = expr_new_tree($1, EXPR_OR, $3); }
expr: expr_no_string
| STRING {
- $$ = expr_new_ident (EXPR_NUM, ExprNum(ConvertCharConstToInt($1)));
+ $$ = expr_new_ident (EXPR_INT, ExprInt(ConvertCharConstToInt($1)));
}
;
#define _(String) gettext(String)
#include "errwarn.h"
+#include "floatnum.h"
#include "expr.h"
#include "symrec.h"
/* floating point value */
{DIGIT}+\.{DIGIT}*(e[-+]?{DIGIT}+)? {
- yylval.double_val = strtod(yytext, (char **)NULL);
+ yylval.flt = floatnum_new(yytext);
return FLTNUM;
}
/* special non-local ..@label and labels like ..start */
$$|$|\.\.[a-z0-9_$#@~.?]+ {
- yylval.syminfo.name = strdup(yytext);
- if (!yylval.syminfo.name)
+ yylval.str_val = strdup(yytext);
+ if (!yylval.str_val)
Fatal(FATAL_NOMEM);
- yylval.syminfo.line = line_number;
return SPECIAL_ID;
}
\.[a-z0-9_$#@~?][a-z0-9_$#@~.?]* {
if (!nasm_parser_locallabel_base) {
Warning(_("no non-local label before `%s'"), yytext);
- yylval.syminfo.name = strdup(yytext);
- if (!yylval.syminfo.name)
+ yylval.str_val = strdup(yytext);
+ if (!yylval.str_val)
Fatal(FATAL_NOMEM);
} else {
- yylval.syminfo.name = malloc(strlen(yytext) +
- strlen(nasm_parser_locallabel_base) + 1);
- if (!yylval.syminfo.name)
+ yylval.str_val = malloc(strlen(yytext) +
+ strlen(nasm_parser_locallabel_base) + 1);
+ if (!yylval.str_val)
Fatal(FATAL_NOMEM);
- strcpy(yylval.syminfo.name, nasm_parser_locallabel_base);
- strcat(yylval.syminfo.name, yytext);
+ strcpy(yylval.str_val, nasm_parser_locallabel_base);
+ strcat(yylval.str_val, yytext);
}
- yylval.syminfo.line = line_number;
return LOCAL_ID;
}
/* label */
[a-z_?][a-z0-9_$#@~.?]* {
- yylval.syminfo.name = strdup(yytext);
- if (!yylval.syminfo.name)
+ yylval.str_val = strdup(yytext);
+ if (!yylval.str_val)
Fatal(FATAL_NOMEM);
- yylval.syminfo.line = line_number;
return ID;
}
/* $IdPath$
* Symbol table handling
*
- * Copyright (C) 2001 Michael Urman
+ * Copyright (C) 2001 Michael Urman, Peter Johnson
*
* This file is part of YASM.
*
#include "globals.h"
#include "errwarn.h"
+#include "floatnum.h"
#include "symrec.h"
+#include "bytecode.h"
+#include "section.h"
+
RCSID("$IdPath$");
/* private functions */
-static symrec *symrec_get_or_new(char *, SymType);
+static symrec *symrec_get_or_new(const char *);
+static symrec *symrec_define(const char *, SymType type);
/* The symbol table: a ternary tree. */
static ternary_tree sym_table = (ternary_tree)NULL;
/* create a new symrec */
static symrec *
-symrec_get_or_new(char *name, SymType type)
+symrec_get_or_new(const char *name)
{
symrec *rec, *rec2;
rec->name = strdup(name);
if (!rec->name)
Fatal(FATAL_NOMEM);
- rec->type = type;
- rec->value = 0;
+ rec->type = SYM_UNKNOWN;
rec->filename = strdup(filename);
rec->line = line_number;
rec->status = SYM_NOSTATUS;
+ rec->visibility = SYM_LOCAL;
return rec;
}
/* call a function with each symrec. stop early if 0 returned */
void
-symrec_foreach(int (*func) (char *name, symrec *rec))
+symrec_foreach(int (*func) (const char *name, symrec *rec))
{
+ /* TODO */
}
symrec *
-symrec_use(char *name, SymType type)
+symrec_use(const char *name)
{
- symrec *rec;
+ symrec *rec = symrec_get_or_new(name);
- rec = symrec_get_or_new(name, type);
rec->status |= SYM_USED;
return rec;
}
+static symrec *
+symrec_define(const char *name, SymType type)
+{
+ symrec *rec = symrec_get_or_new(name);
+
+ /* Has it been defined before (either by DEFINED or COMMON/EXTERN)? */
+ if (rec->status & SYM_DEFINED) {
+ Error(_("duplicate definition of `%s'; first defined on line %d"),
+ name, rec->line);
+ } else {
+ rec->line = line_number; /* set line number of definition */
+ rec->type = type;
+ rec->status |= SYM_DEFINED;
+ }
+ return rec;
+}
+
+symrec *
+symrec_define_constant_int(const char *name, unsigned long int_val)
+{
+ symrec *rec = symrec_define(name, SYM_CONSTANT_INT);
+ rec->value.int_val = int_val;
+ rec->status |= SYM_VALUED;
+ return rec;
+}
+
symrec *
-symrec_define(char *name, SymType type)
+symrec_define_constant_float(const char *name, floatnum *flt)
{
- symrec *rec;
+ symrec *rec = symrec_define(name, SYM_CONSTANT_FLOAT);
+ rec->value.flt = flt;
+ rec->status |= SYM_VALUED;
+ return rec;
+}
- rec = symrec_get_or_new(name, type);
- if (rec->status & SYM_DECLARED)
- Error(_("duplicate definition of `%s'; previously defined on line %d"),
+symrec *
+symrec_define_label(const char *name, section *sect, bytecode *precbc)
+{
+ symrec *rec = symrec_define(name, SYM_LABEL);
+ rec->value.label.sect = sect;
+ rec->value.label.bc = precbc;
+ return rec;
+}
+
+symrec *
+symrec_declare(const char *name, SymVisibility vis)
+{
+ symrec *rec = symrec_get_or_new(name);
+
+ /* Don't allow EXTERN and COMMON if symbol has already been DEFINED. */
+ /* Also, EXTERN and COMMON are mutually exclusive. */
+ if ((rec->status & SYM_DEFINED) ||
+ ((rec->visibility & SYM_COMMON) && (vis == SYM_EXTERN)) ||
+ ((rec->visibility & SYM_EXTERN) && (vis == SYM_COMMON))) {
+ Error(_("duplicate definition of `%s'; first defined on line %d"),
name, rec->line);
- rec->line = line_number; /* set line number of definition */
- rec->status |= SYM_DECLARED;
+ } else {
+ rec->line = line_number; /* set line number of declaration */
+ rec->visibility |= vis;
+
+ /* If declared as COMMON or EXTERN, set as DEFINED. */
+ if ((vis == SYM_COMMON) || (vis == SYM_EXTERN))
+ rec->status |= SYM_DEFINED;
+ }
return rec;
}
+
+int
+symrec_get_int_value(const symrec *sym, unsigned long *ret_val,
+ int resolve_label)
+{
+ /* If we already know the value, just return it. */
+ if (sym->status & SYM_VALUED) {
+ switch (sym->type) {
+ case SYM_CONSTANT_INT:
+ *ret_val = sym->value.int_val;
+ break;
+ case SYM_CONSTANT_FLOAT:
+ *ret_val = floatnum_get_int(sym->value.flt);
+ break;
+ case SYM_LABEL:
+ if (!bytecode_get_offset(sym->value.label.sect,
+ sym->value.label.bc, ret_val))
+ InternalError(__LINE__, __FILE__,
+ _("Label symbol is valued but cannot get offset"));
+ case SYM_UNKNOWN:
+ InternalError(__LINE__, __FILE__,
+ _("Have a valued symbol but of unknown type"));
+ }
+ return 1;
+ }
+
+ /* Try to get offset of unvalued label */
+ if (resolve_label && sym->type == SYM_LABEL)
+ return bytecode_get_offset(sym->value.label.sect, sym->value.label.bc,
+ ret_val);
+
+ /* We can't get the value right now. */
+ return 0;
+}
/* $IdPath$
* Symbol table handling header file
*
- * Copyright (C) 2001 Michael Urman
+ * Copyright (C) 2001 Michael Urman, Peter Johnson
*
* This file is part of YASM.
*
#ifndef YASM_SYMREC_H
#define YASM_SYMREC_H
+/* DEFINED is set with EXTERN and COMMON below */
typedef enum {
SYM_NOSTATUS = 0,
- SYM_USED = 1 << 0, /* for using variables before declared */
- SYM_DECLARED = 1 << 1, /* once it's been declared */
+ SYM_USED = 1 << 0, /* for using variables before definition */
+ SYM_DEFINED = 1 << 1, /* once it's been defined in the file */
SYM_VALUED = 1 << 2 /* once its value has been determined */
} SymStatus;
+/* EXTERN and COMMON are mutually exclusive */
typedef enum {
- SYM_CONSTANT, /* for EQU defined symbols */
+ SYM_LOCAL = 0, /* default, local only */
+ SYM_GLOBAL = 1 << 0, /* if it's declared GLOBAL */
+ SYM_COMMON = 1 << 1, /* if it's declared COMMON */
+ SYM_EXTERN = 1 << 2 /* if it's declared EXTERN */
+} SymVisibility;
+
+typedef enum {
+ SYM_UNKNOWN, /* for unknown type (COMMON/EXTERN) */
+ SYM_CONSTANT_INT, /* for EQU defined symbols (integers) */
+ SYM_CONSTANT_FLOAT, /* (floating point) */
SYM_LABEL /* for labels */
} SymType;
char *name;
SymType type;
SymStatus status;
+ SymVisibility visibility;
char *filename; /* file and line */
- int line; /* symbol was first declared or used on */
- double value;
+ unsigned long line; /* symbol was first declared or used on */
+ union {
+ unsigned long int_val; /* integer constant */
+ struct floatnum_s *flt; /* floating point constant */
+ struct label_s { /* bytecode immediately preceding a label */
+ struct section_s *sect;
+ struct bytecode_s *bc;
+ } label;
+ } value;
} symrec;
-symrec *symrec_use(char *name, SymType type);
-symrec *symrec_define(char *name, SymType type);
-void symrec_foreach(int (*func) (char *name, symrec *rec));
+symrec *symrec_use(const char *name);
+symrec *symrec_define_constant_int(const char *name, unsigned long int_val);
+symrec *symrec_define_constant_float(const char *name, struct floatnum_s *flt);
+symrec *symrec_define_label(const char *name, struct section_s *sect,
+ struct bytecode_s *precbc);
+symrec *symrec_declare(const char *name, SymVisibility vis);
+
+/* Get the numeric 32-bit value of a symbol if possible.
+ * Return value is IF POSSIBLE, not the value.
+ * If resolve_label is true, tries to get offset of labels, otherwise it
+ * returns not possible.
+ */
+int symrec_get_int_value(const symrec *sym, unsigned long *ret_val,
+ int resolve_label);
+
+void symrec_foreach(int (*func) (const char *name, symrec *rec));
#endif