YASM_EXPR_OR, /**< Bitwise OR. */
YASM_EXPR_AND, /**< Bitwise AND. */
YASM_EXPR_XOR, /**< Bitwise XOR. */
+ YASM_EXPR_XNOR, /**< Bitwise XNOR. */
YASM_EXPR_NOR, /**< Bitwise NOR. */
YASM_EXPR_SHL, /**< Shift left (logical). */
YASM_EXPR_SHR, /**< Shift right (logical). */
YASM_EXPR_LOR, /**< Logical OR. */
YASM_EXPR_LAND, /**< Logical AND. */
YASM_EXPR_LNOT, /**< Logical negation. */
+ YASM_EXPR_LXOR, /**< Logical XOR. */
+ YASM_EXPR_LXNOR, /**< Logical XNOR. */
+ YASM_EXPR_LNOR, /**< Logical NOR. */
YASM_EXPR_LT, /**< Less than comparison. */
YASM_EXPR_GT, /**< Greater than comparison. */
YASM_EXPR_EQ, /**< Equality comparison. */
static int
expr_is_constant(yasm_expr_op op, yasm_intnum *intn)
{
- return ((yasm_intnum_is_zero(intn) && op == YASM_EXPR_MUL) ||
- (yasm_intnum_is_zero(intn) && op == YASM_EXPR_AND) ||
+ int iszero = yasm_intnum_is_zero(intn);
+ return ((iszero && op == YASM_EXPR_MUL) ||
+ (iszero && op == YASM_EXPR_AND) ||
+ (iszero && op == YASM_EXPR_LAND) ||
(yasm_intnum_is_neg1(intn) && op == YASM_EXPR_OR));
}
static int
expr_can_destroy_int_left(yasm_expr_op op, yasm_intnum *intn)
{
+ int iszero = yasm_intnum_is_zero(intn);
return ((yasm_intnum_is_pos1(intn) && op == YASM_EXPR_MUL) ||
- (yasm_intnum_is_zero(intn) && op == YASM_EXPR_ADD) ||
+ (iszero && op == YASM_EXPR_ADD) ||
(yasm_intnum_is_neg1(intn) && op == YASM_EXPR_AND) ||
- (yasm_intnum_is_zero(intn) && op == YASM_EXPR_OR));
+ (!iszero && op == YASM_EXPR_LAND) ||
+ (iszero && op == YASM_EXPR_OR) ||
+ (iszero && op == YASM_EXPR_LOR));
}
/* Look for simple "right" identities like x+|-0, x*&/1 */
static int
expr_can_destroy_int_right(yasm_expr_op op, yasm_intnum *intn)
{
- return ((yasm_intnum_is_pos1(intn) && op == YASM_EXPR_MUL) ||
- (yasm_intnum_is_pos1(intn) && op == YASM_EXPR_DIV) ||
- (yasm_intnum_is_zero(intn) && op == YASM_EXPR_ADD) ||
- (yasm_intnum_is_zero(intn) && op == YASM_EXPR_SUB) ||
+ int iszero = yasm_intnum_is_zero(intn);
+ int ispos1 = yasm_intnum_is_pos1(intn);
+ return ((ispos1 && op == YASM_EXPR_MUL) ||
+ (ispos1 && op == YASM_EXPR_DIV) ||
+ (iszero && op == YASM_EXPR_ADD) ||
+ (iszero && op == YASM_EXPR_SUB) ||
(yasm_intnum_is_neg1(intn) && op == YASM_EXPR_AND) ||
- (yasm_intnum_is_zero(intn) && op == YASM_EXPR_OR) ||
- (yasm_intnum_is_zero(intn) && op == YASM_EXPR_SHL) ||
- (yasm_intnum_is_zero(intn) && op == YASM_EXPR_SHR));
+ (!iszero && op == YASM_EXPR_LAND) ||
+ (iszero && op == YASM_EXPR_OR) ||
+ (iszero && op == YASM_EXPR_LOR) ||
+ (iszero && op == YASM_EXPR_SHL) ||
+ (iszero && op == YASM_EXPR_SHR));
}
/* Check for and simplify identities. Returns new number of expr terms.
numterms = 1;
}
- /* Compute NOT and NEG on single intnum. */
+ /* Compute NOT, NEG, and LNOT on single intnum. */
if (numterms == 1 && int_term == 0 &&
- (e->op == YASM_EXPR_NOT || e->op == YASM_EXPR_NEG))
+ (e->op == YASM_EXPR_NOT || e->op == YASM_EXPR_NEG ||
+ e->op == YASM_EXPR_LNOT))
yasm_intnum_calc(e->terms[0].data.intn, e->op, NULL, e->line);
/* Change expression to IDENT if possible. */
*/
if ((e->op != YASM_EXPR_ADD && e->op != YASM_EXPR_MUL &&
e->op != YASM_EXPR_OR && e->op != YASM_EXPR_AND &&
- e->op != YASM_EXPR_XOR) ||
+ e->op != YASM_EXPR_LOR && e->op != YASM_EXPR_LAND &&
+ e->op != YASM_EXPR_LXOR && e->op != YASM_EXPR_XOR) ||
level_numterms <= fold_numterms) {
/* Downsize e if necessary */
if (fold_numterms < e->numterms && e->numterms > 2)
case YASM_EXPR_OR:
case YASM_EXPR_AND:
case YASM_EXPR_XOR:
+ case YASM_EXPR_LOR:
+ case YASM_EXPR_LAND:
+ case YASM_EXPR_LXOR:
/* Use mergesort to sort. It's fast on already sorted values and a
* stable sort (multiple terms of same type are kept in the same
* order).
case YASM_EXPR_XOR:
strcpy(opstr, "^");
break;
+ case YASM_EXPR_XNOR:
+ strcpy(opstr, "XNOR");
+ break;
case YASM_EXPR_NOR:
strcpy(opstr, "NOR");
break;
case YASM_EXPR_LNOT:
strcpy(opstr, "!");
break;
+ case YASM_EXPR_LXOR:
+ strcpy(opstr, "^^");
+ break;
+ case YASM_EXPR_LXNOR:
+ strcpy(opstr, "LXNOR");
+ break;
+ case YASM_EXPR_LNOR:
+ strcpy(opstr, "LNOR");
+ break;
case YASM_EXPR_LT:
strcpy(opstr, "<");
break;
case YASM_EXPR_XOR:
Set_ExclusiveOr(result, op1, op2);
break;
+ case YASM_EXPR_XNOR:
+ Set_ExclusiveOr(result, op1, op2);
+ Set_Complement(result, result);
+ break;
case YASM_EXPR_NOR:
Set_Union(result, op1, op2);
Set_Complement(result, result);
BitVector_Empty(result);
BitVector_LSB(result, BitVector_is_empty(op1));
break;
+ case YASM_EXPR_LXOR:
+ BitVector_Empty(result);
+ BitVector_LSB(result, !BitVector_is_empty(op1) ^
+ !BitVector_is_empty(op2));
+ break;
+ case YASM_EXPR_LXNOR:
+ BitVector_Empty(result);
+ BitVector_LSB(result, !(!BitVector_is_empty(op1) ^
+ !BitVector_is_empty(op2)));
+ break;
+ case YASM_EXPR_LNOR:
+ BitVector_Empty(result);
+ BitVector_LSB(result, !(!BitVector_is_empty(op1) ||
+ !BitVector_is_empty(op2)));
+ break;
case YASM_EXPR_EQ:
BitVector_Empty(result);
BitVector_LSB(result, BitVector_equal(op1, op2));
return size_leb128(val, 0);
}
+char *
+yasm_intnum_get_str(const yasm_intnum *intn)
+{
+ unsigned char *s;
+
+ switch (intn->type) {
+ case INTNUM_UL:
+ s = yasm_xmalloc(16);
+ sprintf((char *)s, "%lu", intn->val.ul);
+ return (char *)s;
+ break;
+ case INTNUM_BV:
+ return (char *)BitVector_to_Dec(intn->val.bv);
+ break;
+ }
+ /*@notreached@*/
+ return NULL;
+}
+
void
yasm_intnum_print(const yasm_intnum *intn, FILE *f)
{
*/
unsigned long yasm_size_uleb128(unsigned long v);
+/** Get an intnum as a signed decimal string. The returned string will
+ * contain a leading '-' if the intnum is negative.
+ * \param intn intnum
+ * \return Newly allocated string containing the decimal representation of
+ * the intnum.
+ */
+/*@only@*/ char *yasm_intnum_get_str(const yasm_intnum *intn);
+
/** Print an intnum. For debugging purposes.
* \param f file
* \param intn intnum
*/
#include <util.h>
#include <libyasm/coretype.h>
+#include <libyasm/intnum.h>
+#include <libyasm/expr.h>
#include <ctype.h>
#include "nasm.h"
#include "nasmlib.h"
#include "nasm-eval.h"
-/*#include "labels.h"*/
-
-#define TEMPEXPRS_DELTA 128
-#define TEMPEXPR_DELTA 8
static scanner scan; /* Address of scanner routine */
static efunc error; /* Address of error reporting routine */
-static lfunc labelfunc; /* Address of label routine */
-
-static struct ofmt *outfmt; /* Structure of addresses of output routines */
-
-static nasm_expr **tempexprs = NULL;
-static int ntempexprs;
-static int tempexprs_size = 0;
-
-static nasm_expr *tempexpr;
-static int ntempexpr;
-static int tempexpr_size;
static struct tokenval *tokval; /* The current token */
static int i; /* The t_type of tokval */
static void *scpriv;
-static loc_t *location; /* Pointer to current line's segment,offset */
-static int *opflags;
-
-static struct eval_hints *hint;
-
-static int in_abs_seg = 0; /* ABSOLUTE segment flag */
-static long abs_seg = 0; /* ABSOLUTE segment */
-static long abs_offset = 0; /* ABSOLUTE segment offset */
-
-/*
- * Unimportant cleanup is done to avoid confusing people who are trying
- * to debug real memory leaks
- */
-void nasm_eval_cleanup(void)
-{
- while (ntempexprs) {
- ntempexprs--;
- nasm_free (tempexprs[ntempexprs]);
- }
- nasm_free (tempexprs);
-}
-
-/*
- * Construct a temporary expression.
- */
-static void begintemp(void)
-{
- tempexpr = NULL;
- tempexpr_size = ntempexpr = 0;
-}
-
-static void addtotemp(long type, long value)
-{
- while (ntempexpr >= tempexpr_size) {
- tempexpr_size += TEMPEXPR_DELTA;
- tempexpr = nasm_realloc(tempexpr,
- tempexpr_size*sizeof(*tempexpr));
- }
- tempexpr[ntempexpr].type = type;
- tempexpr[ntempexpr++].value = value;
-}
-
-static nasm_expr *finishtemp(void)
-{
- addtotemp (0L, 0L); /* terminate */
- while (ntempexprs >= tempexprs_size) {
- tempexprs_size += TEMPEXPRS_DELTA;
- tempexprs = nasm_realloc(tempexprs,
- tempexprs_size*sizeof(*tempexprs));
- }
- return tempexprs[ntempexprs++] = tempexpr;
-}
-
-/*
- * Add two vector datatypes. We have some bizarre behaviour on far-
- * absolute segment types: we preserve them during addition _only_
- * if one of the segments is a truly pure scalar.
- */
-static nasm_expr *add_vectors(nasm_expr *p, nasm_expr *q)
-{
- int preserve;
-
- preserve = nasm_is_really_simple(p) || nasm_is_really_simple(q);
-
- begintemp();
-
- while (p->type && q->type &&
- p->type < EXPR_SEGBASE+SEG_ABS &&
- q->type < EXPR_SEGBASE+SEG_ABS)
- {
- int lasttype;
-
- if (p->type > q->type) {
- addtotemp(q->type, q->value);
- lasttype = q++->type;
- } else if (p->type < q->type) {
- addtotemp(p->type, p->value);
- lasttype = p++->type;
- } else { /* *p and *q have same type */
- long sum = p->value + q->value;
- if (sum)
- addtotemp(p->type, sum);
- lasttype = p->type;
- p++, q++;
- }
- if (lasttype == EXPR_UNKNOWN) {
- return finishtemp();
- }
- }
- while (p->type &&
- (preserve || p->type < EXPR_SEGBASE+SEG_ABS))
- {
- addtotemp(p->type, p->value);
- p++;
- }
- while (q->type &&
- (preserve || q->type < EXPR_SEGBASE+SEG_ABS))
- {
- addtotemp(q->type, q->value);
- q++;
- }
-
- return finishtemp();
-}
-
-/*
- * Multiply a vector by a scalar. Strip far-absolute segment part
- * if present.
- *
- * Explicit treatment of UNKNOWN is not required in this routine,
- * since it will silently do the Right Thing anyway.
- *
- * If `affect_hints' is set, we also change the hint type to
- * NOTBASE if a MAKEBASE hint points at a register being
- * multiplied. This allows [eax*1+ebx] to hint EBX rather than EAX
- * as the base register.
- */
-static nasm_expr *scalar_mult(nasm_expr *vect, long scalar, int affect_hints)
-{
- nasm_expr *p = vect;
-
- while (p->type && p->type < EXPR_SEGBASE+SEG_ABS) {
- p->value = scalar * (p->value);
- if (hint && hint->type == EAH_MAKEBASE &&
- p->type == hint->base && affect_hints)
- hint->type = EAH_NOTBASE;
- p++;
- }
- p->type = 0;
-
- return vect;
-}
-
-static nasm_expr *scalarvect (long scalar)
-{
- begintemp();
- addtotemp(EXPR_SIMPLE, scalar);
- return finishtemp();
-}
-
-static nasm_expr *unknown_expr (void)
-{
- begintemp();
- addtotemp(EXPR_UNKNOWN, 1L);
- return finishtemp();
-}
-
-/*
- * The SEG operator: calculate the segment part of a relocatable
- * value. Return NULL, as usual, if an error occurs. Report the
- * error too.
- */
-static nasm_expr *segment_part (nasm_expr *e)
-{
- long seg;
-
- if (nasm_is_unknown(e))
- return unknown_expr();
-
- if (!nasm_is_reloc(e)) {
- error(ERR_NONFATAL, "cannot apply SEG to a non-relocatable value");
- return NULL;
- }
-
- seg = nasm_reloc_seg(e);
- if (seg == NO_SEG) {
- error(ERR_NONFATAL, "cannot apply SEG to a non-relocatable value");
- return NULL;
- } else if (seg & SEG_ABS) {
- return scalarvect(seg & ~SEG_ABS);
- } else if (seg & 1) {
- error(ERR_NONFATAL, "SEG applied to something which"
- " is already a segment base");
- return NULL;
- }
- else {
- long base = outfmt->segbase(seg+1);
-
- begintemp();
- addtotemp((base == NO_SEG ? EXPR_UNKNOWN : EXPR_SEGBASE+base), 1L);
- return finishtemp();
- }
-}
/*
* Recursive-descent parser. Called with a single boolean operand,
* | number
*/
-static nasm_expr *rexp0(int), *rexp1(int), *rexp2(int), *rexp3(int);
+static yasm_expr *rexp0(void), *rexp1(void), *rexp2(void), *rexp3(void);
-static nasm_expr *expr0(int), *expr1(int), *expr2(int), *expr3(int);
-static nasm_expr *expr4(int), *expr5(int), *expr6(int);
+static yasm_expr *expr0(void), *expr1(void), *expr2(void), *expr3(void);
+static yasm_expr *expr4(void), *expr5(void), *expr6(void);
-static nasm_expr *(*bexpr)(int);
+static yasm_expr *(*bexpr)(void);
-static nasm_expr *rexp0(int critical)
+static yasm_expr *rexp0(void)
{
- nasm_expr *e, *f;
+ yasm_expr *e, *f;
- e = rexp1(critical);
+ e = rexp1();
if (!e)
return NULL;
while (i == TOKEN_DBL_OR)
{
i = scan(scpriv, tokval);
- f = rexp1(critical);
- if (!f)
+ f = rexp1();
+ if (!f) {
+ yasm_expr_destroy(e);
return NULL;
- if (!(nasm_is_simple(e) || nasm_is_just_unknown(e)) ||
- !(nasm_is_simple(f) || nasm_is_just_unknown(f)))
- {
- error(ERR_NONFATAL, "`|' operator may only be applied to"
- " scalar values");
}
- if (nasm_is_just_unknown(e) || nasm_is_just_unknown(f))
- e = unknown_expr();
- else
- e = scalarvect ((long) (nasm_reloc_value(e) || nasm_reloc_value(f)));
+ e = yasm_expr_create_tree(e, YASM_EXPR_LOR, f, 0);
}
return e;
}
-static nasm_expr *rexp1(int critical)
+static yasm_expr *rexp1(void)
{
- nasm_expr *e, *f;
+ yasm_expr *e, *f;
- e = rexp2(critical);
+ e = rexp2();
if (!e)
return NULL;
while (i == TOKEN_DBL_XOR)
{
i = scan(scpriv, tokval);
- f = rexp2(critical);
- if (!f)
+ f = rexp2();
+ if (!f) {
+ yasm_expr_destroy(e);
return NULL;
- if (!(nasm_is_simple(e) || nasm_is_just_unknown(e)) ||
- !(nasm_is_simple(f) || nasm_is_just_unknown(f)))
- {
- error(ERR_NONFATAL, "`^' operator may only be applied to"
- " scalar values");
}
- if (nasm_is_just_unknown(e) || nasm_is_just_unknown(f))
- e = unknown_expr();
- else
- e = scalarvect ((long) (!nasm_reloc_value(e) ^ !nasm_reloc_value(f)));
+ e = yasm_expr_create_tree(e, YASM_EXPR_LXOR, f, 0);
}
return e;
}
-static nasm_expr *rexp2(int critical)
+static yasm_expr *rexp2(void)
{
- nasm_expr *e, *f;
+ yasm_expr *e, *f;
- e = rexp3(critical);
+ e = rexp3();
if (!e)
return NULL;
while (i == TOKEN_DBL_AND)
{
i = scan(scpriv, tokval);
- f = rexp3(critical);
- if (!f)
+ f = rexp3();
+ if (!f) {
+ yasm_expr_destroy(e);
return NULL;
- if (!(nasm_is_simple(e) || nasm_is_just_unknown(e)) ||
- !(nasm_is_simple(f) || nasm_is_just_unknown(f)))
- {
- error(ERR_NONFATAL, "`&' operator may only be applied to"
- " scalar values");
}
- if (nasm_is_just_unknown(e) || nasm_is_just_unknown(f))
- e = unknown_expr();
- else
- e = scalarvect ((long) (nasm_reloc_value(e) && nasm_reloc_value(f)));
+
+ e = yasm_expr_create_tree(e, YASM_EXPR_LAND, f, 0);
}
return e;
}
-static nasm_expr *rexp3(int critical)
+static yasm_expr *rexp3(void)
{
- nasm_expr *e, *f;
- long v;
+ yasm_expr *e, *f;
- e = expr0(critical);
+ e = expr0();
if (!e)
return NULL;
{
int j = i;
i = scan(scpriv, tokval);
- f = expr0(critical);
- if (!f)
+ f = expr0();
+ if (!f) {
+ yasm_expr_destroy(e);
return NULL;
-
- e = add_vectors (e, scalar_mult(f, -1L, FALSE));
+ }
switch (j)
{
- case TOKEN_EQ: case TOKEN_NE:
- if (nasm_is_unknown(e))
- v = -1; /* means unknown */
- else if (!nasm_is_really_simple(e) || nasm_reloc_value(e) != 0)
- v = (j == TOKEN_NE); /* unequal, so return TRUE if NE */
- else
- v = (j == TOKEN_EQ); /* equal, so return TRUE if EQ */
- break;
- default:
- if (nasm_is_unknown(e))
- v = -1; /* means unknown */
- else if (!nasm_is_really_simple(e)) {
- error(ERR_NONFATAL, "`%s': operands differ by a non-scalar",
- (j == TOKEN_LE ? "<=" : j == TOKEN_LT ? "<" :
- j == TOKEN_GE ? ">=" : ">"));
- v = 0; /* must set it to _something_ */
- } else {
- int vv = nasm_reloc_value(e);
- if (vv == 0)
- v = (j == TOKEN_LE || j == TOKEN_GE);
- else if (vv > 0)
- v = (j == TOKEN_GE || j == TOKEN_GT);
- else /* vv < 0 */
- v = (j == TOKEN_LE || j == TOKEN_LT);
- }
- break;
+ case TOKEN_EQ:
+ e = yasm_expr_create_tree(e, YASM_EXPR_EQ, f, 0);
+ break;
+ case TOKEN_LT:
+ e = yasm_expr_create_tree(e, YASM_EXPR_LT, f, 0);
+ break;
+ case TOKEN_GT:
+ e = yasm_expr_create_tree(e, YASM_EXPR_GT, f, 0);
+ break;
+ case TOKEN_NE:
+ e = yasm_expr_create_tree(e, YASM_EXPR_NE, f, 0);
+ break;
+ case TOKEN_LE:
+ e = yasm_expr_create_tree(e, YASM_EXPR_LE, f, 0);
+ break;
+ case TOKEN_GE:
+ e = yasm_expr_create_tree(e, YASM_EXPR_GE, f, 0);
+ break;
}
-
- if (v == -1)
- e = unknown_expr();
- else
- e = scalarvect(v);
}
return e;
}
-static nasm_expr *expr0(int critical)
+static yasm_expr *expr0(void)
{
- nasm_expr *e, *f;
+ yasm_expr *e, *f;
- e = expr1(critical);
+ e = expr1();
if (!e)
return NULL;
while (i == '|')
{
i = scan(scpriv, tokval);
- f = expr1(critical);
- if (!f)
+ f = expr1();
+ if (!f) {
+ yasm_expr_destroy(e);
return NULL;
- if (!(nasm_is_simple(e) || nasm_is_just_unknown(e)) ||
- !(nasm_is_simple(f) || nasm_is_just_unknown(f)))
- {
- error(ERR_NONFATAL, "`|' operator may only be applied to"
- " scalar values");
}
- if (nasm_is_just_unknown(e) || nasm_is_just_unknown(f))
- e = unknown_expr();
- else
- e = scalarvect (nasm_reloc_value(e) | nasm_reloc_value(f));
+
+ e = yasm_expr_create_tree(e, YASM_EXPR_OR, f, 0);
}
return e;
}
-static nasm_expr *expr1(int critical)
+static yasm_expr *expr1(void)
{
- nasm_expr *e, *f;
+ yasm_expr *e, *f;
- e = expr2(critical);
+ e = expr2();
if (!e)
return NULL;
while (i == '^') {
i = scan(scpriv, tokval);
- f = expr2(critical);
- if (!f)
+ f = expr2();
+ if (!f) {
+ yasm_expr_destroy(e);
return NULL;
- if (!(nasm_is_simple(e) || nasm_is_just_unknown(e)) ||
- !(nasm_is_simple(f) || nasm_is_just_unknown(f)))
- {
- error(ERR_NONFATAL, "`^' operator may only be applied to"
- " scalar values");
}
- if (nasm_is_just_unknown(e) || nasm_is_just_unknown(f))
- e = unknown_expr();
- else
- e = scalarvect (nasm_reloc_value(e) ^ nasm_reloc_value(f));
+
+ e = yasm_expr_create_tree(e, YASM_EXPR_XOR, f, 0);
}
return e;
}
-static nasm_expr *expr2(int critical)
+static yasm_expr *expr2(void)
{
- nasm_expr *e, *f;
+ yasm_expr *e, *f;
- e = expr3(critical);
+ e = expr3();
if (!e)
return NULL;
while (i == '&') {
i = scan(scpriv, tokval);
- f = expr3(critical);
- if (!f)
+ f = expr3();
+ if (!f) {
+ yasm_expr_destroy(e);
return NULL;
- if (!(nasm_is_simple(e) || nasm_is_just_unknown(e)) ||
- !(nasm_is_simple(f) || nasm_is_just_unknown(f)))
- {
- error(ERR_NONFATAL, "`&' operator may only be applied to"
- " scalar values");
}
- if (nasm_is_just_unknown(e) || nasm_is_just_unknown(f))
- e = unknown_expr();
- else
- e = scalarvect (nasm_reloc_value(e) & nasm_reloc_value(f));
+
+ e = yasm_expr_create_tree(e, YASM_EXPR_AND, f, 0);
}
return e;
}
-static nasm_expr *expr3(int critical)
+static yasm_expr *expr3(void)
{
- nasm_expr *e, *f;
+ yasm_expr *e, *f;
- e = expr4(critical);
+ e = expr4();
if (!e)
return NULL;
{
int j = i;
i = scan(scpriv, tokval);
- f = expr4(critical);
- if (!f)
+ f = expr4();
+ if (!f) {
+ yasm_expr_destroy(e);
return NULL;
- if (!(nasm_is_simple(e) || nasm_is_just_unknown(e)) ||
- !(nasm_is_simple(f) || nasm_is_just_unknown(f)))
- {
- error(ERR_NONFATAL, "shift operator may only be applied to"
- " scalar values");
- } else if (nasm_is_just_unknown(e) || nasm_is_just_unknown(f)) {
- e = unknown_expr();
- } else switch (j) {
- case TOKEN_SHL:
- e = scalarvect (nasm_reloc_value(e) << nasm_reloc_value(f));
- break;
- case TOKEN_SHR:
- e = scalarvect ((long)(((unsigned long)nasm_reloc_value(e)) >>
- nasm_reloc_value(f)));
- break;
+ }
+
+ switch (j) {
+ case TOKEN_SHL:
+ e = yasm_expr_create_tree(e, YASM_EXPR_SHL, f, 0);
+ break;
+ case TOKEN_SHR:
+ e = yasm_expr_create_tree(e, YASM_EXPR_SHR, f, 0);
+ break;
}
}
return e;
}
-static nasm_expr *expr4(int critical)
+static yasm_expr *expr4(void)
{
- nasm_expr *e, *f;
+ yasm_expr *e, *f;
- e = expr5(critical);
+ e = expr5();
if (!e)
return NULL;
while (i == '+' || i == '-')
{
int j = i;
i = scan(scpriv, tokval);
- f = expr5(critical);
- if (!f)
+ f = expr5();
+ if (!f) {
+ yasm_expr_destroy(e);
return NULL;
+ }
switch (j) {
case '+':
- e = add_vectors (e, f);
+ e = yasm_expr_create_tree(e, YASM_EXPR_ADD, f, 0);
break;
case '-':
- e = add_vectors (e, scalar_mult(f, -1L, FALSE));
+ e = yasm_expr_create_tree(e, YASM_EXPR_SUB, f, 0);
break;
}
}
return e;
}
-static nasm_expr *expr5(int critical)
+static yasm_expr *expr5(void)
{
- nasm_expr *e, *f;
+ yasm_expr *e, *f;
+ yasm_intnum *ei, *fi;
- e = expr6(critical);
+ e = expr6();
if (!e)
return NULL;
while (i == '*' || i == '/' || i == '%' ||
{
int j = i;
i = scan(scpriv, tokval);
- f = expr6(critical);
- if (!f)
- return NULL;
- if (j != '*' && (!(nasm_is_simple(e) || nasm_is_just_unknown(e)) ||
- !(nasm_is_simple(f) || nasm_is_just_unknown(f))))
- {
- error(ERR_NONFATAL, "division operator may only be applied to"
- " scalar values");
- return NULL;
- }
- if (j != '*' && !nasm_is_unknown(f) && nasm_reloc_value(f) == 0) {
- error(ERR_NONFATAL, "division by zero");
+ f = expr6();
+ if (!f) {
+ yasm_expr_destroy(e);
return NULL;
}
switch (j) {
case '*':
- if (nasm_is_simple(e))
- e = scalar_mult (f, nasm_reloc_value(e), TRUE);
- else if (nasm_is_simple(f))
- e = scalar_mult (e, nasm_reloc_value(f), TRUE);
- else if (nasm_is_just_unknown(e) && nasm_is_just_unknown(f))
- e = unknown_expr();
- else {
- error(ERR_NONFATAL, "unable to multiply two "
- "non-scalar objects");
- return NULL;
- }
+ e = yasm_expr_create_tree(e, YASM_EXPR_MUL, f, 0);
break;
case '/':
- if (nasm_is_just_unknown(e) || nasm_is_just_unknown(f))
- e = unknown_expr();
- else
- e = scalarvect ((long)(((unsigned long)nasm_reloc_value(e)) /
- ((unsigned long)nasm_reloc_value(f))));
+ e = yasm_expr_create_tree(e, YASM_EXPR_DIV, f, 0);
break;
case '%':
- if (nasm_is_just_unknown(e) || nasm_is_just_unknown(f))
- e = unknown_expr();
- else
- e = scalarvect ((long)(((unsigned long)nasm_reloc_value(e)) %
- ((unsigned long)nasm_reloc_value(f))));
+ e = yasm_expr_create_tree(e, YASM_EXPR_MOD, f, 0);
break;
case TOKEN_SDIV:
- if (nasm_is_just_unknown(e) || nasm_is_just_unknown(f))
- e = unknown_expr();
- else
- e = scalarvect (((signed long)nasm_reloc_value(e)) /
- ((signed long)nasm_reloc_value(f)));
+ e = yasm_expr_create_tree(e, YASM_EXPR_SIGNDIV, f, 0);
break;
case TOKEN_SMOD:
- if (nasm_is_just_unknown(e) || nasm_is_just_unknown(f))
- e = unknown_expr();
- else
- e = scalarvect (((signed long)nasm_reloc_value(e)) %
- ((signed long)nasm_reloc_value(f)));
+ e = yasm_expr_create_tree(e, YASM_EXPR_SIGNMOD, f, 0);
break;
}
}
return e;
}
-static nasm_expr *expr6(int critical)
+static yasm_expr *expr6(void)
{
long type;
- nasm_expr *e;
+ yasm_expr *e = NULL;
+ yasm_intnum *ei;
long label_seg, label_ofs;
if (i == '-') {
i = scan(scpriv, tokval);
- e = expr6(critical);
+ e = expr6();
if (!e)
return NULL;
- return scalar_mult (e, -1L, FALSE);
+ return yasm_expr_create_branch(YASM_EXPR_NEG, e, 0);
} else if (i == '+') {
i = scan(scpriv, tokval);
- return expr6(critical);
+ return expr6();
} else if (i == '~') {
i = scan(scpriv, tokval);
- e = expr6(critical);
+ e = expr6();
if (!e)
return NULL;
- if (nasm_is_just_unknown(e))
- return unknown_expr();
- else if (!nasm_is_simple(e)) {
- error(ERR_NONFATAL, "`~' operator may only be applied to"
- " scalar values");
- return NULL;
- }
- return scalarvect(~nasm_reloc_value(e));
+ return yasm_expr_create_branch(YASM_EXPR_NOT, e, 0);
} else if (i == TOKEN_SEG) {
i = scan(scpriv, tokval);
- e = expr6(critical);
- if (!e)
- return NULL;
- e = segment_part(e);
+ e = expr6();
if (!e)
return NULL;
- if (nasm_is_unknown(e) && critical) {
- error(ERR_NONFATAL, "unable to determine segment base");
- return NULL;
- }
+ error(ERR_NONFATAL, "%s not supported", "SEG");
return e;
} else if (i == '(') {
i = scan(scpriv, tokval);
- e = bexpr(critical);
+ e = bexpr();
if (!e)
return NULL;
if (i != ')') {
i = scan(scpriv, tokval);
return e;
}
- else if (i == TOKEN_NUM || i == TOKEN_REG || i == TOKEN_ID ||
+ else if (i == TOKEN_NUM || i == TOKEN_ID ||
i == TOKEN_HERE || i == TOKEN_BASE)
{
- begintemp();
switch (i) {
case TOKEN_NUM:
- addtotemp(EXPR_SIMPLE, tokval->t_integer);
- break;
- case TOKEN_REG:
- addtotemp(tokval->t_integer, 1L);
- if (hint && hint->type == EAH_NOHINT)
- hint->base = tokval->t_integer, hint->type = EAH_MAKEBASE;
+ e = yasm_expr_create_ident(yasm_expr_int(tokval->t_integer), 0);
break;
case TOKEN_ID:
case TOKEN_HERE:
case TOKEN_BASE:
- /*
- * If !location->known, this indicates that no
- * symbol, Here or Base references are valid because we
- * are in preprocess-only mode.
- */
- if (!location || !location->known) {
- error(ERR_NONFATAL,
- "%s not supported",
- (i == TOKEN_ID ? "symbol references" :
- i == TOKEN_HERE ? "`$'" : "`$$'"));
- addtotemp(EXPR_UNKNOWN, 1L);
- break;
- }
-
- type = EXPR_SIMPLE; /* might get overridden by UNKNOWN */
- if (i == TOKEN_BASE)
- {
- label_seg = in_abs_seg ? abs_seg : location->segment;
- label_ofs = 0;
- } else if (i == TOKEN_HERE) {
- label_seg = in_abs_seg ? abs_seg : location->segment;
- label_ofs = in_abs_seg ? abs_offset : location->offset;
- } else {
- if (!labelfunc(tokval->t_charptr,&label_seg,&label_ofs))
- {
- if (critical == 2) {
- error (ERR_NONFATAL, "symbol `%s' undefined",
- tokval->t_charptr);
- return NULL;
- } else if (critical == 1) {
- error (ERR_NONFATAL,
- "symbol `%s' not defined before use",
- tokval->t_charptr);
- return NULL;
- } else {
- if (opflags)
- *opflags |= 1;
- type = EXPR_UNKNOWN;
- label_seg = NO_SEG;
- label_ofs = 1;
- }
- }
-#if 0
- if (opflags && nasm_is_extern (tokval->t_charptr))
- *opflags |= OPFLAG_EXTERN;
-#endif
- }
- addtotemp(type, label_ofs);
- if (label_seg!=NO_SEG)
- addtotemp(EXPR_SEGBASE + label_seg, 1L);
+ error(ERR_NONFATAL, "%s not supported",
+ (i == TOKEN_ID ? "symbol references" :
+ i == TOKEN_HERE ? "`$'" : "`$$'"));
+ e = yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_int(1)),
+ 0);
break;
}
i = scan(scpriv, tokval);
- return finishtemp();
+ return e;
} else {
error(ERR_NONFATAL, "expression syntax error");
return NULL;
}
}
-void nasm_eval_global_info (struct ofmt *output, lfunc lookup_label, loc_t *locp)
-{
- outfmt = output;
- labelfunc = lookup_label;
- location = locp;
-}
-
-nasm_expr *nasm_evaluate (scanner sc, void *scprivate, struct tokenval *tv,
- int *fwref, int critical, efunc report_error,
- struct eval_hints *hints)
+yasm_expr *nasm_evaluate (scanner sc, void *scprivate, struct tokenval *tv,
+ int critical, efunc report_error)
{
- nasm_expr *e;
- nasm_expr *f = NULL;
-
- hint = hints;
- if (hint)
- hint->type = EAH_NOHINT;
-
if (critical & CRITICAL) {
critical &= ~CRITICAL;
bexpr = rexp0;
scpriv = scprivate;
tokval = tv;
error = report_error;
- opflags = fwref;
if (tokval->t_type == TOKEN_INVALID)
i = scan(scpriv, tokval);
else
i = tokval->t_type;
- while (ntempexprs) { /* initialise temporary storage */
- ntempexprs--;
- nasm_free (tempexprs[ntempexprs]);
- }
-
- e = bexpr (critical);
- if (!e)
- return NULL;
-
- if (i == TOKEN_WRT) {
- i = scan(scpriv, tokval); /* eat the WRT */
- f = expr6 (critical);
- if (!f)
- return NULL;
- }
- e = scalar_mult (e, 1L, FALSE); /* strip far-absolute segment part */
- if (f) {
- nasm_expr *g;
- if (nasm_is_just_unknown(f))
- g = unknown_expr();
- else {
- long value;
- begintemp();
- if (!nasm_is_reloc(f)) {
- error(ERR_NONFATAL, "invalid right-hand operand to WRT");
- return NULL;
- }
- value = nasm_reloc_seg(f);
- if (value == NO_SEG)
- value = nasm_reloc_value(f) | SEG_ABS;
- else if (!(value & SEG_ABS) && !(value % 2) && critical)
- {
- error(ERR_NONFATAL, "invalid right-hand operand to WRT");
- return NULL;
- }
- addtotemp(EXPR_WRT, value);
- g = finishtemp();
- }
- e = add_vectors (e, g);
- }
- return e;
+ return bexpr ();
}
#ifndef NASM_EVAL_H
#define NASM_EVAL_H
-/*
- * Called once to tell the evaluator what output format is
- * providing segment-base details, and what function can be used to
- * look labels up.
- */
-void nasm_eval_global_info (struct ofmt *output, lfunc lookup_label, loc_t *locp);
-
/*
* The evaluator itself.
*/
-nasm_expr *nasm_evaluate (scanner sc, void *scprivate, struct tokenval *tv,
- int *fwref, int critical, efunc report_error,
- struct eval_hints *hints);
-
-void nasm_eval_cleanup(void);
+yasm_expr *nasm_evaluate (scanner sc, void *scprivate, struct tokenval *tv,
+ int critical, efunc report_error);
#endif
*/
#include <util.h>
#include <libyasm/coretype.h>
+#include <libyasm/intnum.h>
+#include <libyasm/expr.h>
#include <libyasm/file.h>
#include <stdarg.h>
#include <ctype.h>
MMacro *next;
char *name;
int casesense;
- int nparam_min, nparam_max;
+ long nparam_min, nparam_max;
int plus; /* is the last parameter greedy? */
int nolist; /* is this macro listing-inhibited? */
int in_progress;
MMacro *rep_nest; /* used for nesting %rep */
Token **params; /* actual parameters */
Token *iline; /* invocation line */
- int nparam, rotate, *paramlen;
+ long nparam, rotate, *paramlen;
unsigned long unique;
int lineno; /* Current line number on expansion */
};
static Token *expand_smacro(Token * tline);
static Token *expand_id(Token * tline);
static Context *get_ctx(char *name, int all_contexts);
-static void make_tok_num(Token * tok, long val);
+static void make_tok_num(Token * tok, yasm_intnum *val);
static void error(int severity, const char *fmt, ...);
static void *new_Block(size_t size);
static void delete_Blocks(void);
int j, casesense;
Token *t, *tt, **tptr, *origline;
struct tokenval tokval;
- nasm_expr *evalresult;
+ yasm_expr *evalresult;
+ yasm_intnum *intn;
origline = tline;
}
else
{
+ intn = nasm_readnum(tline->text, &j);
searching.nparam_min = searching.nparam_max =
- nasm_readnum(tline->text, &j);
+ yasm_intnum_get_int(intn);
+ yasm_intnum_destroy(intn);
if (j)
error(ERR_NONFATAL,
"unable to parse parameter count `%s'",
directives[i]);
else
{
- searching.nparam_max = nasm_readnum(tline->text, &j);
+ intn = nasm_readnum(tline->text, &j);
+ searching.nparam_max = yasm_intnum_get_int(intn);
+ yasm_intnum_destroy(intn);
if (j)
error(ERR_NONFATAL,
"unable to parse parameter count `%s'",
t = tline = expand_smacro(tline);
tptr = &t;
tokval.t_type = TOKEN_INVALID;
- evalresult = evaluate(ppscan, tptr, &tokval,
- NULL, pass | CRITICAL, error, NULL);
+ evalresult = evaluate(ppscan, tptr, &tokval, pass | CRITICAL,
+ error);
free_tlist(tline);
if (!evalresult)
return -1;
if (tokval.t_type)
error(ERR_WARNING,
"trailing garbage after expression ignored");
- if (!nasm_is_simple(evalresult))
+ intn = yasm_expr_get_intnum(&evalresult, NULL);
+ if (!intn)
{
error(ERR_NONFATAL,
"non-constant value given to `%s'", directives[i]);
+ yasm_expr_destroy(evalresult);
return -1;
}
- return nasm_reloc_value(evalresult) != 0;
+ j = !yasm_intnum_is_zero(intn);
+ yasm_expr_destroy(evalresult);
+ return j;
default:
error(ERR_FATAL,
Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
Line *l;
struct tokenval tokval;
- nasm_expr *evalresult;
+ yasm_expr *evalresult;
MMacro *tmp_defining; /* Used when manipulating rep_nest */
+ yasm_intnum *intn;
origline = tline;
}
else
{
+ intn = nasm_readnum(tline->text, &j);
defining->nparam_min = defining->nparam_max =
- nasm_readnum(tline->text, &j);
+ yasm_intnum_get_int(intn);
+ yasm_intnum_destroy(intn);
if (j)
error(ERR_NONFATAL,
"unable to parse parameter count `%s'",
(i == PP_IMACRO ? "i" : ""));
else
{
- defining->nparam_max = nasm_readnum(tline->text, &j);
+ intn = nasm_readnum(tline->text, &j);
+ defining->nparam_max = yasm_intnum_get_int(intn);
+ yasm_intnum_destroy(intn);
if (j)
error(ERR_NONFATAL,
"unable to parse parameter count `%s'",
tline = t;
tptr = &t;
tokval.t_type = TOKEN_INVALID;
- evalresult =
- evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
+ evalresult = evaluate(ppscan, tptr, &tokval, pass, error);
free_tlist(tline);
if (!evalresult)
return DIRECTIVE_FOUND;
if (tokval.t_type)
error(ERR_WARNING,
"trailing garbage after expression ignored");
- if (!nasm_is_simple(evalresult))
+ intn = yasm_expr_get_intnum(&evalresult, NULL);
+ if (!intn)
{
error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
+ yasm_expr_destroy(evalresult);
return DIRECTIVE_FOUND;
}
mmac = istk->mstk;
}
else
{
- mmac->rotate = mmac->rotate + nasm_reloc_value(evalresult);
+ mmac->rotate = mmac->rotate + yasm_intnum_get_int(intn);
if (mmac->rotate < 0)
mmac->rotate =
mmac->nparam - (-mmac->rotate) % mmac->nparam;
mmac->rotate %= mmac->nparam;
}
+ yasm_expr_destroy(evalresult);
return DIRECTIVE_FOUND;
case PP_REP:
t = expand_smacro(tline);
tptr = &t;
tokval.t_type = TOKEN_INVALID;
- evalresult =
- evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
+ evalresult = evaluate(ppscan, tptr, &tokval, pass, error);
if (!evalresult)
{
free_tlist(origline);
if (tokval.t_type)
error(ERR_WARNING,
"trailing garbage after expression ignored");
- if (!nasm_is_simple(evalresult))
+ intn = yasm_expr_get_intnum(&evalresult, NULL);
+ if (!intn)
{
error(ERR_NONFATAL, "non-constant value given to `%%rep'");
+ yasm_expr_destroy(evalresult);
return DIRECTIVE_FOUND;
}
- i = (int)nasm_reloc_value(evalresult) + 1;
+ i = (int)yasm_intnum_get_int(intn) + 1;
+ yasm_expr_destroy(evalresult);
}
else
{
macro_start = nasm_malloc(sizeof(*macro_start));
macro_start->next = NULL;
- make_tok_num(macro_start, (int)strlen(t->text) - 2);
+ make_tok_num(macro_start,
+ yasm_intnum_create_uint(strlen(t->text) - 2));
macro_start->mac = NULL;
/*
tt = t->next;
tptr = &tt;
tokval.t_type = TOKEN_INVALID;
- evalresult =
- evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
+ evalresult = evaluate(ppscan, tptr, &tokval, pass, error);
if (!evalresult)
{
free_tlist(tline);
free_tlist(origline);
return DIRECTIVE_FOUND;
}
- if (!nasm_is_simple(evalresult))
+ intn = yasm_expr_get_intnum(&evalresult, NULL);
+ if (!intn)
{
error(ERR_NONFATAL, "non-constant value given to `%%substr`");
free_tlist(tline);
free_tlist(origline);
+ yasm_expr_destroy(evalresult);
return DIRECTIVE_FOUND;
}
macro_start = nasm_malloc(sizeof(*macro_start));
macro_start->next = NULL;
macro_start->text = nasm_strdup("'''");
- if (evalresult->value > 0
- && evalresult->value < (int)strlen(t->text) - 1)
+ if (yasm_intnum_sign(intn) == 1
+ && yasm_intnum_get_uint(intn) < strlen(t->text) - 1)
{
- macro_start->text[1] = t->text[evalresult->value];
+ macro_start->text[1] = t->text[yasm_intnum_get_uint(intn)];
}
else
{
macro_start->text[2] = '\0';
}
+ yasm_expr_destroy(evalresult);
macro_start->type = TOK_STRING;
macro_start->mac = NULL;
t = tline;
tptr = &t;
tokval.t_type = TOKEN_INVALID;
- evalresult =
- evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
+ evalresult = evaluate(ppscan, tptr, &tokval, pass, error);
free_tlist(tline);
if (!evalresult)
{
error(ERR_WARNING,
"trailing garbage after expression ignored");
- if (!nasm_is_simple(evalresult))
+ intn = yasm_expr_get_intnum(&evalresult, NULL);
+ if (!intn)
{
error(ERR_NONFATAL,
"non-constant value given to `%%%sassign'",
(i == PP_IASSIGN ? "i" : ""));
free_tlist(origline);
+ yasm_expr_destroy(evalresult);
return DIRECTIVE_FOUND;
}
macro_start = nasm_malloc(sizeof(*macro_start));
macro_start->next = NULL;
- make_tok_num(macro_start, nasm_reloc_value(evalresult));
+ make_tok_num(macro_start, yasm_intnum_copy(intn));
+ yasm_expr_destroy(evalresult);
macro_start->mac = NULL;
/*
free_tlist(origline);
return DIRECTIVE_FOUND;
}
- k = nasm_readnum(tline->text, &j);
+ intn = nasm_readnum(tline->text, &j);
+ k = yasm_intnum_get_int(intn);
+ yasm_intnum_destroy(intn);
m = 1;
tline = tline->next;
if (tok_is_(tline, "+"))
free_tlist(origline);
return DIRECTIVE_FOUND;
}
- m = nasm_readnum(tline->text, &j);
+ intn = nasm_readnum(tline->text, &j);
+ m = yasm_intnum_get_int(intn);
+ yasm_intnum_destroy(intn);
tline = tline->next;
}
skip_white_(tline);
*/
case '0':
type = TOK_NUMBER;
- sprintf(tmpbuf, "%d", mac->nparam);
+ sprintf(tmpbuf, "%ld", mac->nparam);
text = nasm_strdup(tmpbuf);
break;
case '%':
if (!strcmp("__LINE__", m->name))
{
nasm_free(tline->text);
- make_tok_num(tline, nasm_src_get_linnum());
+ make_tok_num(tline, yasm_intnum_create_int(nasm_src_get_linnum()));
continue;
}
tline = delete_Token(tline);
Token **params, *t, *tt;
MMacro *m;
Line *l, *ll;
- int i, nparam, *paramlen;
+ int i, nparam;
+ long *paramlen;
t = tline;
skip_white_(t);
istk->mstk = NULL;
istk->fp = f;
istk->fname = NULL;
- nasm_src_set_fname(nasm_strdup(file));
+ nasm_free(nasm_src_set_fname(nasm_strdup(file)));
nasm_src_set_linnum(0);
istk->lineinc = 1;
defining = NULL;
}
static void
-make_tok_num(Token * tok, long val)
+make_tok_num(Token * tok, yasm_intnum *val)
{
- char numbuf[20];
- sprintf(numbuf, "%ld", val);
- tok->text = nasm_strdup(numbuf);
+ tok->text = yasm_intnum_get_str(val);
tok->type = TOK_NUMBER;
}
nasm_preproc_destroy(yasm_preproc *preproc)
{
nasmpp.cleanup(0);
- nasm_eval_cleanup();
yasm_xfree(preproc);
if (preproc_deps)
yasm_xfree(preproc_deps);
}
preproc_nasm->prior_linnum = linnum;
}
+ if (preproc_nasm->file_name) {
+ yasm_xfree(preproc_nasm->file_name);
+ preproc_nasm->file_name = NULL;
+ }
n = preproc_nasm->lineleft<max_size?preproc_nasm->lineleft:max_size;
strncpy(buf, preproc_nasm->linepos, n);
#define TRUE 1
#endif
-#define NO_SEG -1L /* null segment value */
-#define SEG_ABS 0x40000000L /* mask for far-absolute segments */
-
#ifndef FILENAME_MAX
#define FILENAME_MAX 256
#endif
#define IDLEN_MAX 4096
-/*
- * Name pollution problems: <time.h> on Digital UNIX pulls in some
- * strange hardware header file which sees fit to define R_SP. We
- * undefine it here so as not to break the enum below.
- */
-#ifdef R_SP
-#undef R_SP
-#endif
-
-/*
- * We must declare the existence of this structure type up here,
- * since we have to reference it before we define it...
- */
-struct ofmt;
-
/*
* -------------------------
* Error reporting functions
* -----------------------
*/
-/*
- * A label-lookup function should look like this.
- */
-typedef int (*lfunc) (char *label, long *segment, long *offset);
-
-/*
- * And a label-definition function like this. The boolean parameter
- * `is_norm' states whether the label is a `normal' label (which
- * should affect the local-label system), or something odder like
- * an EQU or a segment-base symbol, which shouldn't.
- */
-typedef void (*ldfunc) (char *label, long segment, long offset, char *special,
- int is_norm, int isextrn, struct ofmt *ofmt,
- efunc error);
-
/*
* List-file generators should look like this:
*/
*/
struct tokenval {
int t_type;
- long t_integer, t_inttwo;
+ yasm_intnum *t_integer, *t_inttwo;
char *t_charptr;
};
typedef int (*scanner) (void *private_data, struct tokenval *tv);
TOKEN_FLOAT /* floating-point constant */
};
-typedef struct {
- long segment;
- long offset;
- int known;
-} loc_t;
-
-/*
- * Expression-evaluator datatype. Expressions, within the
- * evaluator, are stored as an array of these beasts, terminated by
- * a record with type==0. Mostly, it's a vector type: each type
- * denotes some kind of a component, and the value denotes the
- * multiple of that component present in the expression. The
- * exception is the WRT type, whose `value' field denotes the
- * segment to which the expression is relative. These segments will
- * be segment-base types, i.e. either odd segment values or SEG_ABS
- * types. So it is still valid to assume that anything with a
- * `value' field of zero is insignificant.
- */
-typedef struct {
- long type; /* a register, or EXPR_xxx */
- long value; /* must be >= 32 bits */
-} nasm_expr;
-
-/*
- * The evaluator can also return hints about which of two registers
- * used in an expression should be the base register. See also the
- * `operand' structure.
- */
-struct eval_hints {
- int base;
- int type;
-};
-
/*
* The actual expression evaluator function looks like this. When
* called, it expects the first token of its expression to already
* be in `*tv'; if it is not, set tv->t_type to TOKEN_INVALID and
* it will start by calling the scanner.
*
- * If a forward reference happens during evaluation, the evaluator
- * must set `*fwref' to TRUE if `fwref' is non-NULL.
- *
* `critical' is non-zero if the expression may not contain forward
* references. The evaluator will report its own error if this
* occurs; if `critical' is 1, the error will be "symbol not
* syntax is recognised, in which relational operators such as =, <
* and >= are accepted, as well as low-precedence logical operators
* &&, ^^ and ||.
- *
- * If `hints' is non-NULL, it gets filled in with some hints as to
- * the base register in complex effective addresses.
*/
#define CRITICAL 0x100
-typedef nasm_expr *(*evalfunc) (scanner sc, void *scprivate, struct tokenval *tv,
- int *fwref, int critical, efunc error,
- struct eval_hints *hints);
-
-/*
- * Special values for expr->type. ASSUMPTION MADE HERE: the number
- * of distinct register names (i.e. possible "type" fields for an
- * expr structure) does not exceed 124 (EXPR_REG_START through
- * EXPR_REG_END).
- */
-#define EXPR_REG_START 1
-#define EXPR_REG_END 124
-#define EXPR_UNKNOWN 125L /* for forward references */
-#define EXPR_SIMPLE 126L
-#define EXPR_WRT 127L
-#define EXPR_SEGBASE 128L
+typedef yasm_expr *(*evalfunc) (scanner sc, void *scprivate, struct tokenval *tv,
+ int critical, efunc error);
/*
* Preprocessors ought to look like this:
LIST_INCBIN, LIST_TIMES
};
-/*
- * -----------------------------------------------------------
- * Format of the `insn' structure returned from `parser.c' and
- * passed into `assemble.c'
- * -----------------------------------------------------------
- */
-
-/*
- * Here we define the operand types. These are implemented as bit
- * masks, since some are subsets of others; e.g. AX in a MOV
- * instruction is a special operand type, whereas AX in other
- * contexts is just another 16-bit register. (Also, consider CL in
- * shift instructions, DX in OUT, etc.)
- */
-
-/* size, and other attributes, of the operand */
-#define BITS8 0x00000001L
-#define BITS16 0x00000002L
-#define BITS32 0x00000004L
-#define BITS64 0x00000008L /* FPU only */
-#define BITS80 0x00000010L /* FPU only */
-#define FAR 0x00000020L /* grotty: this means 16:16 or */
- /* 16:32, like in CALL/JMP */
-#define NEAR 0x00000040L
-#define SHORT 0x00000080L /* and this means what it says :) */
-
-#define SIZE_MASK 0x000000FFL /* all the size attributes */
-#define NON_SIZE (~SIZE_MASK)
-
-#define TO 0x00000100L /* reverse effect in FADD, FSUB &c */
-#define COLON 0x00000200L /* operand is followed by a colon */
-#define STRICT 0x00000400L /* do not optimize this operand */
-
-/* type of operand: memory reference, register, etc. */
-#define MEMORY 0x00204000L
-#define REGISTER 0x00001000L /* register number in 'basereg' */
-#define IMMEDIATE 0x00002000L
-
-#define REGMEM 0x00200000L /* for r/m, ie EA, operands */
-#define REGNORM 0x00201000L /* 'normal' reg, qualifies as EA */
-#define REG8 0x00201001L
-#define REG16 0x00201002L
-#define REG32 0x00201004L
-#define MMXREG 0x00201008L /* MMX registers */
-#define XMMREG 0x00201010L /* XMM Katmai reg */
-#define FPUREG 0x01000000L /* floating point stack registers */
-#define FPU0 0x01000800L /* FPU stack register zero */
-
-/* special register operands: these may be treated differently */
-#define REG_SMASK 0x00070000L /* a mask for the following */
-#define REG_ACCUM 0x00211000L /* accumulator: AL, AX or EAX */
-#define REG_AL 0x00211001L /* REG_ACCUM | BITSxx */
-#define REG_AX 0x00211002L /* ditto */
-#define REG_EAX 0x00211004L /* and again */
-#define REG_COUNT 0x00221000L /* counter: CL, CX or ECX */
-#define REG_CL 0x00221001L /* REG_COUNT | BITSxx */
-#define REG_CX 0x00221002L /* ditto */
-#define REG_ECX 0x00221004L /* another one */
-#define REG_DL 0x00241001L
-#define REG_DX 0x00241002L
-#define REG_EDX 0x00241004L
-#define REG_SREG 0x00081002L /* any segment register */
-#define REG_CS 0x01081002L /* CS */
-#define REG_DESS 0x02081002L /* DS, ES, SS (non-CS 86 registers) */
-#define REG_FSGS 0x04081002L /* FS, GS (386 extended registers) */
-#define REG_SEG67 0x08081002L /* Non-implemented segment registers */
-#define REG_CDT 0x00101004L /* CRn, DRn and TRn */
-#define REG_CREG 0x08101004L /* CRn */
-#define REG_DREG 0x10101004L /* DRn */
-#define REG_TREG 0x20101004L /* TRn */
-
-/* special type of EA */
-#define MEM_OFFS 0x00604000L /* simple [address] offset */
-
-/* special type of immediate operand */
-#define ONENESS 0x00800000L /* so UNITY == IMMEDIATE | ONENESS */
-#define UNITY 0x00802000L /* for shift/rotate instructions */
-#define BYTENESS 0x40000000L /* so SBYTE == IMMEDIATE | BYTENESS */
-#define SBYTE 0x40002000L /* for op r16/32,immediate instrs. */
-
-
-/* Register names automatically generated from regs.dat */
-/*#include "regs.h"*/
-
-enum { /* condition code names */
- C_A, C_AE, C_B, C_BE, C_C, C_E, C_G, C_GE, C_L, C_LE, C_NA, C_NAE,
- C_NB, C_NBE, C_NC, C_NE, C_NG, C_NGE, C_NL, C_NLE, C_NO, C_NP,
- C_NS, C_NZ, C_O, C_P, C_PE, C_PO, C_S, C_Z
-};
-#if 0
-/*
- * Note that because segment registers may be used as instruction
- * prefixes, we must ensure the enumerations for prefixes and
- * register names do not overlap.
- */
-enum { /* instruction prefixes */
- PREFIX_ENUM_START = REG_ENUM_LIMIT,
- P_A16 = PREFIX_ENUM_START, P_A32, P_LOCK, P_O16, P_O32, P_REP, P_REPE,
- P_REPNE, P_REPNZ, P_REPZ, P_TIMES
-};
-#endif
-enum { /* extended operand types */
- EOT_NOTHING, EOT_DB_STRING, EOT_DB_NUMBER
-};
-
-enum { /* special EA flags */
- EAF_BYTEOFFS = 1, /* force offset part to byte size */
- EAF_WORDOFFS = 2, /* force offset part to [d]word size */
- EAF_TIMESTWO = 4 /* really do EAX*2 not EAX+EAX */
-};
-
-enum { /* values for `hinttype' */
- EAH_NOHINT = 0, /* no hint at all - our discretion */
- EAH_MAKEBASE = 1, /* try to make given reg the base */
- EAH_NOTBASE = 2 /* try _not_ to make reg the base */
-};
-
-typedef struct { /* operand to an instruction */
- long type; /* type of operand */
- int addr_size; /* 0 means default; 16; 32 */
- int basereg, indexreg, scale; /* registers and scale involved */
- int hintbase, hinttype; /* hint as to real base register */
- long segment; /* immediate segment, if needed */
- long offset; /* any immediate number */
- long wrt; /* segment base it's relative to */
- int eaflags; /* special EA flags */
- int opflags; /* see OPFLAG_* defines below */
-} operand;
-
-#define OPFLAG_FORWARD 1 /* operand is a forward reference */
-#define OPFLAG_EXTERN 2 /* operand is an external reference */
-
-typedef struct extop { /* extended operand */
- struct extop *next; /* linked list */
- long type; /* defined above */
- char *stringval; /* if it's a string, then here it is */
- int stringlen; /* ... and here's how long it is */
- long segment; /* if it's a number/address, then... */
- long offset; /* ... it's given here ... */
- long wrt; /* ... and here */
-} extop;
-
-#define MAXPREFIX 4
-
-typedef struct { /* an instruction itself */
- char *label; /* the label defined, or NULL */
- int prefixes[MAXPREFIX]; /* instruction prefixes, if any */
- int nprefix; /* number of entries in above */
- int opcode; /* the opcode - not just the string */
- int condition; /* the condition code, if Jcc/SETcc */
- int operands; /* how many operands? 0-3
- * (more if db et al) */
- operand oprs[3]; /* the operands, defined as above */
- extop *eops; /* extended operands */
- int eops_float; /* true if DD and floating */
- long times; /* repeat count (TIMES prefix) */
- int forw_ref; /* is there a forward reference? */
-} insn;
-
-enum geninfo { GI_SWITCH };
-/*
- * ------------------------------------------------------------
- * The data structure defining an output format driver, and the
- * interfaces to the functions therein.
- * ------------------------------------------------------------
- */
-
-struct ofmt {
- /*
- * This is a short (one-liner) description of the type of
- * output generated by the driver.
- */
- const char *fullname;
-
- /*
- * This is a single keyword used to select the driver.
- */
- const char *shortname;
-
- /*
- * this is reserved for out module specific help.
- * It is set to NULL in all the out modules but is not implemented
- * in the main program
- */
- const char *helpstring;
-
- /*
- * this is a pointer to the first element of the debug information
- */
- struct dfmt **debug_formats;
-
- /*
- * and a pointer to the element that is being used
- * note: this is set to the default at compile time and changed if the
- * -F option is selected. If developing a set of new debug formats for
- * an output format, be sure to set this to whatever default you want
- *
- */
- struct dfmt *current_dfmt;
-
- /*
- * This, if non-NULL, is a NULL-terminated list of `char *'s
- * pointing to extra standard macros supplied by the object
- * format (e.g. a sensible initial default value of __SECT__,
- * and user-level equivalents for any format-specific
- * directives).
- */
- const char **stdmac;
-
- /*
- * This procedure is called at the start of an output session.
- * It tells the output format what file it will be writing to,
- * what routine to report errors through, and how to interface
- * to the label manager and expression evaluator if necessary.
- * It also gives it a chance to do other initialisation.
- */
- void (*init) (FILE *fp, efunc error, ldfunc ldef, evalfunc eval);
-
- /*
- * This procedure is called to pass generic information to the
- * object file. The first parameter gives the information type
- * (currently only command line switches)
- * and the second parameter gives the value. This function returns
- * 1 if recognized, 0 if unrecognized
- */
- int (*setinfo)(enum geninfo type, char **string);
-
- /*
- * This procedure is called by assemble() to write actual
- * generated code or data to the object file. Typically it
- * doesn't have to actually _write_ it, just store it for
- * later.
- *
- * The `type' argument specifies the type of output data, and
- * usually the size as well: its contents are described below.
- */
- void (*output) (long segto, const void *data, unsigned long type,
- long segment, long wrt);
-
- /*
- * This procedure is called once for every symbol defined in
- * the module being assembled. It gives the name and value of
- * the symbol, in NASM's terms, and indicates whether it has
- * been declared to be global. Note that the parameter "name",
- * when passed, will point to a piece of static storage
- * allocated inside the label manager - it's safe to keep using
- * that pointer, because the label manager doesn't clean up
- * until after the output driver has.
- *
- * Values of `is_global' are: 0 means the symbol is local; 1
- * means the symbol is global; 2 means the symbol is common (in
- * which case `offset' holds the _size_ of the variable).
- * Anything else is available for the output driver to use
- * internally.
- *
- * This routine explicitly _is_ allowed to call the label
- * manager to define further symbols, if it wants to, even
- * though it's been called _from_ the label manager. That much
- * re-entrancy is guaranteed in the label manager. However, the
- * label manager will in turn call this routine, so it should
- * be prepared to be re-entrant itself.
- *
- * The `special' parameter contains special information passed
- * through from the command that defined the label: it may have
- * been an EXTERN, a COMMON or a GLOBAL. The distinction should
- * be obvious to the output format from the other parameters.
- */
- void (*symdef) (char *name, long segment, long offset, int is_global,
- char *special);
-
- /*
- * This procedure is called when the source code requests a
- * segment change. It should return the corresponding segment
- * _number_ for the name, or NO_SEG if the name is not a valid
- * segment name.
- *
- * It may also be called with NULL, in which case it is to
- * return the _default_ section number for starting assembly in.
- *
- * It is allowed to modify the string it is given a pointer to.
- *
- * It is also allowed to specify a default instruction size for
- * the segment, by setting `*bits' to 16 or 32. Or, if it
- * doesn't wish to define a default, it can leave `bits' alone.
- */
- long (*section) (char *name, int pass, int *bits);
-
- /*
- * This procedure is called to modify the segment base values
- * returned from the SEG operator. It is given a segment base
- * value (i.e. a segment value with the low bit set), and is
- * required to produce in return a segment value which may be
- * different. It can map segment bases to absolute numbers by
- * means of returning SEG_ABS types.
- *
- * It should return NO_SEG if the segment base cannot be
- * determined; the evaluator (which calls this routine) is
- * responsible for throwing an error condition if that occurs
- * in pass two or in a critical expression.
- */
- long (*segbase) (long segment);
-
- /*
- * This procedure is called to allow the output driver to
- * process its own specific directives. When called, it has the
- * directive word in `directive' and the parameter string in
- * `value'. It is called in both assembly passes, and `pass'
- * will be either 1 or 2.
- *
- * This procedure should return zero if it does not _recognise_
- * the directive, so that the main program can report an error.
- * If it recognises the directive but then has its own errors,
- * it should report them itself and then return non-zero. It
- * should also return non-zero if it correctly processes the
- * directive.
- */
- int (*directive) (char *directive, char *value, int pass);
-
- /*
- * This procedure is called before anything else - even before
- * the "init" routine - and is passed the name of the input
- * file from which this output file is being generated. It
- * should return its preferred name for the output file in
- * `outname', if outname[0] is not '\0', and do nothing to
- * `outname' otherwise. Since it is called before the driver is
- * properly initialised, it has to be passed its error handler
- * separately.
- *
- * This procedure may also take its own copy of the input file
- * name for use in writing the output file: it is _guaranteed_
- * that it will be called before the "init" routine.
- *
- * The parameter `outname' points to an area of storage
- * guaranteed to be at least FILENAME_MAX in size.
- */
- void (*filename) (char *inname, char *outname, efunc error);
-
- /*
- * This procedure is called after assembly finishes, to allow
- * the output driver to clean itself up and free its memory.
- * Typically, it will also be the point at which the object
- * file actually gets _written_.
- *
- * One thing the cleanup routine should always do is to close
- * the output file pointer.
- */
- void (*cleanup) (int debuginfo);
-};
-
-/*
- * values for the `type' parameter to an output function. Each one
- * must have the actual number of _bytes_ added to it.
- *
- * Exceptions are OUT_RELxADR, which denote an x-byte relocation
- * which will be a relative jump. For this we need to know the
- * distance in bytes from the start of the relocated record until
- * the end of the containing instruction. _This_ is what is stored
- * in the size part of the parameter, in this case.
- *
- * Also OUT_RESERVE denotes reservation of N bytes of BSS space,
- * and the contents of the "data" parameter is irrelevant.
- *
- * The "data" parameter for the output function points to a "long",
- * containing the address in question, unless the type is
- * OUT_RAWDATA, in which case it points to an "unsigned char"
- * array.
- */
-#define OUT_RAWDATA 0x00000000UL
-#define OUT_ADDRESS 0x10000000UL
-#define OUT_REL2ADR 0x20000000UL
-#define OUT_REL4ADR 0x30000000UL
-#define OUT_RESERVE 0x40000000UL
-#define OUT_TYPMASK 0xF0000000UL
-#define OUT_SIZMASK 0x0FFFFFFFUL
-
-/*
- * ------------------------------------------------------------
- * The data structure defining a debug format driver, and the
- * interfaces to the functions therein.
- * ------------------------------------------------------------
- */
-
-struct dfmt {
-
- /*
- * This is a short (one-liner) description of the type of
- * output generated by the driver.
- */
- const char *fullname;
-
- /*
- * This is a single keyword used to select the driver.
- */
- const char *shortname;
-
-
- /*
- * init - called initially to set up local pointer to object format,
- * void pointer to implementation defined data, file pointer (which
- * probably won't be used, but who knows?), and error function.
- */
- void (*init) (struct ofmt * of, void * id, FILE * fp, efunc error);
-
- /*
- * linenum - called any time there is output with a change of
- * line number or file.
- */
- void (*linenum) (const char * filename, long linenumber, long segto);
-
- /*
- * debug_deflabel - called whenever a label is defined. Parameters
- * are the same as to 'symdef()' in the output format. This function
- * would be called before the output format version.
- */
-
- void (*debug_deflabel) (char * name, long segment, long offset,
- int is_global, char * special);
- /*
- * debug_directive - called whenever a DEBUG directive other than 'LINE'
- * is encountered. 'directive' contains the first parameter to the
- * DEBUG directive, and params contains the rest. For example,
- * 'DEBUG VAR _somevar:int' would translate to a call to this
- * function with 'directive' equal to "VAR" and 'params' equal to
- * "_somevar:int".
- */
- void (*debug_directive) (const char * directive, const char * params);
-
- /*
- * typevalue - called whenever the assembler wishes to register a type
- * for the last defined label. This routine MUST detect if a type was
- * already registered and not re-register it.
- */
- void (*debug_typevalue) (long type);
-
- /*
- * debug_output - called whenever output is required
- * 'type' is the type of info required, and this is format-specific
- */
- void (*debug_output) (int type, void *param);
-
- /*
- * cleanup - called after processing of file is complete
- */
- void (*cleanup) (void);
-
-};
-/*
- * The type definition macros
- * for debugging
- *
- * low 3 bits: reserved
- * next 5 bits: type
- * next 24 bits: number of elements for arrays (0 for labels)
- */
-
-#define TY_UNKNOWN 0x00
-#define TY_LABEL 0x08
-#define TY_BYTE 0x10
-#define TY_WORD 0x18
-#define TY_DWORD 0x20
-#define TY_FLOAT 0x28
-#define TY_QWORD 0x30
-#define TY_TBYTE 0x38
-#define TY_COMMON 0xE0
-#define TY_SEG 0xE8
-#define TY_EXTERN 0xF0
-#define TY_EQU 0xF8
-
-#define TYM_TYPE(x) ((x) & 0xF8)
-#define TYM_ELEMENTS(x) (((x) & 0xFFFFFF00) >> 8)
-
-#define TYS_ELEMENTS(x) ((x) << 8)
/*
* -----
* Other
extern int tasm_compatible_mode;
-/*
- * This declaration passes the "pass" number to all other modules
- * "pass0" assumes the values: 0, 0, ..., 0, 1, 2
- * where 0 = optimizing pass
- * 1 = pass 1
- * 2 = pass 2
- */
-
-extern int pass0; /* this is globally known */
-extern int optimizing;
-
#endif
*/
#include <util.h>
#include <libyasm/coretype.h>
+#include <libyasm/intnum.h>
#include <ctype.h>
#include "nasm.h"
#define lib_isnumchar(c) ( isalnum(c) || (c) == '$')
#define numvalue(c) ((c)>='a' ? (c)-'a'+10 : (c)>='A' ? (c)-'A'+10 : (c)-'0')
-long nasm_readnum (char *str, int *error)
+yasm_intnum *nasm_readnum (char *str, int *error)
{
- char *r = str, *q;
+ char *r = str, *q, *p;
long radix;
- unsigned long result, checklimit;
- int digit, last;
- int warn = FALSE;
- int sign = 1;
+ yasm_intnum *intn;
+ char save;
+ int digit;
+ int sign = 0;
*error = FALSE;
if (*r == '-')
{
r++;
- sign = -1;
+ sign = 1;
}
q = r;
*/
if (r >= q) {
*error = TRUE;
- return 0;
+ return yasm_intnum_create_uint(0);
}
- /*
- * `checklimit' must be 2**32 / radix. We can't do that in
- * 32-bit arithmetic, which we're (probably) using, so we
- * cheat: since we know that all radices we use are even, we
- * can divide 2**31 by radix/2 instead.
- */
- checklimit = 0x80000000UL / (radix>>1);
-
- /*
- * Calculate the highest allowable value for the last digit
- * of a 32 bit constant... in radix 10, it is 6, otherwise it is 0
- */
- last = (radix == 10 ? 6 : 0);
-
- result = 0;
- while (*r && r < q) {
- if (*r<'0' || (*r>'9' && *r<'A') || (digit = numvalue(*r)) >= radix)
+ /* Check for valid number of that radix */
+ p = r;
+ while (*p && p < q) {
+ if (*p<'0' || (*p>'9' && *p<'A') || (digit = numvalue(*p)) >= radix)
{
*error = TRUE;
- return 0;
- }
- if (result > checklimit ||
- (result == checklimit && digit >= last))
- {
- warn = TRUE;
- }
-
- result = radix * result + digit;
- r++;
- }
-#if 0
- if (warn)
- nasm_malloc_error (ERR_WARNING | ERR_PASS1 | ERR_WARN_NOV,
- "numeric constant %s does not fit in 32 bits",
- str);
-#endif
- return result*sign;
-}
-
-long nasm_readstrnum (char *str, int length, int *warn)
-{
- long charconst = 0;
- int i;
-
- *warn = FALSE;
-
- str += length;
- for (i=0; i<length; i++) {
- if (charconst & 0xff000000UL) {
- *warn = TRUE;
+ return yasm_intnum_create_uint(0);
}
- charconst = (charconst<<8) + (unsigned char) *--str;
+ p++;
}
- return charconst;
-}
-
-static long next_seg;
-
-void nasm_seg_init(void)
-{
- next_seg = 0;
-}
-
-long nasm_seg_alloc(void)
-{
- return (next_seg += 2) - 2;
-}
-
-/*
- * Return TRUE if the argument is a simple scalar. (Or a far-
- * absolute, which counts.)
- */
-int nasm_is_simple (nasm_expr *vect)
-{
- while (vect->type && !vect->value)
- vect++;
- if (!vect->type)
- return 1;
- if (vect->type != EXPR_SIMPLE)
- return 0;
- do {
- vect++;
- } while (vect->type && !vect->value);
- if (vect->type && vect->type < EXPR_SEGBASE+SEG_ABS) return 0;
- return 1;
-}
-/*
- * Return TRUE if the argument is a simple scalar, _NOT_ a far-
- * absolute.
- */
-int nasm_is_really_simple (nasm_expr *vect)
-{
- while (vect->type && !vect->value)
- vect++;
- if (!vect->type)
- return 1;
- if (vect->type != EXPR_SIMPLE)
- return 0;
- do {
- vect++;
- } while (vect->type && !vect->value);
- if (vect->type) return 0;
- return 1;
-}
-
-/*
- * Return TRUE if the argument is relocatable (i.e. a simple
- * scalar, plus at most one segment-base, plus possibly a WRT).
- */
-int nasm_is_reloc (nasm_expr *vect)
-{
- while (vect->type && !vect->value) /* skip initial value-0 terms */
- vect++;
- if (!vect->type) /* trivially return TRUE if nothing */
- return 1; /* is present apart from value-0s */
- if (vect->type < EXPR_SIMPLE) /* FALSE if a register is present */
- return 0;
- if (vect->type == EXPR_SIMPLE) { /* skip over a pure number term... */
- do {
- vect++;
- } while (vect->type && !vect->value);
- if (!vect->type) /* ...returning TRUE if that's all */
- return 1;
- }
- if (vect->type == EXPR_WRT) { /* skip over a WRT term... */
- do {
- vect++;
- } while (vect->type && !vect->value);
- if (!vect->type) /* ...returning TRUE if that's all */
- return 1;
+ /* Use intnum to actually do the conversion */
+ save = *q;
+ *q = '\0';
+ switch (radix) {
+ case 2:
+ intn = yasm_intnum_create_bin(r, 0);
+ break;
+ case 8:
+ intn = yasm_intnum_create_oct(r, 0);
+ break;
+ case 10:
+ intn = yasm_intnum_create_dec(r, 0);
+ break;
+ case 16:
+ intn = yasm_intnum_create_hex(r, 0);
+ break;
+ default:
+ *error = TRUE;
+ intn = yasm_intnum_create_uint(0);
+ break;
}
- if (vect->value != 0 && vect->value != 1)
- return 0; /* segment base multiplier non-unity */
- do { /* skip over _one_ seg-base term... */
- vect++;
- } while (vect->type && !vect->value);
- if (!vect->type) /* ...returning TRUE if that's all */
- return 1;
- return 0; /* And return FALSE if there's more */
-}
+ *q = save;
-/*
- * Return TRUE if the argument contains an `unknown' part.
- */
-int nasm_is_unknown(nasm_expr *vect)
-{
- while (vect->type && vect->type < EXPR_UNKNOWN)
- vect++;
- return (vect->type == EXPR_UNKNOWN);
-}
-
-/*
- * Return TRUE if the argument contains nothing but an `unknown'
- * part.
- */
-int nasm_is_just_unknown(nasm_expr *vect)
-{
- while (vect->type && !vect->value)
- vect++;
- return (vect->type == EXPR_UNKNOWN);
+ if (sign)
+ yasm_intnum_calc(intn, YASM_EXPR_NEG, NULL, 0);
+ return intn;
}
-/*
- * Return the scalar part of a relocatable vector. (Including
- * simple scalar vectors - those qualify as relocatable.)
- */
-long nasm_reloc_value (nasm_expr *vect)
+yasm_intnum *nasm_readstrnum (char *str, int length, int *warn)
{
- while (vect->type && !vect->value)
- vect++;
- if (!vect->type) return 0;
- if (vect->type == EXPR_SIMPLE)
- return vect->value;
- else
- return 0;
-}
+ char save;
+ yasm_intnum *intn;
-/*
- * Return the segment number of a relocatable vector, or NO_SEG for
- * simple scalars.
- */
-long nasm_reloc_seg (nasm_expr *vect)
-{
- while (vect->type && (vect->type == EXPR_WRT || !vect->value))
- vect++;
- if (vect->type == EXPR_SIMPLE) {
- do {
- vect++;
- } while (vect->type && (vect->type == EXPR_WRT || !vect->value));
- }
- if (!vect->type)
- return NO_SEG;
- else
- return vect->type - EXPR_SEGBASE;
-}
+ *warn = FALSE;
-/*
- * Return the WRT segment number of a relocatable vector, or NO_SEG
- * if no WRT part is present.
- */
-long nasm_reloc_wrt (nasm_expr *vect)
-{
- while (vect->type && vect->type < EXPR_WRT)
- vect++;
- if (vect->type == EXPR_WRT) {
- return vect->value;
- } else
- return NO_SEG;
-}
+ save = str[length];
+ str[length] = '\0';
+ intn = yasm_intnum_create_charconst_nasm(str, 0);
+ str[length] = save;
-/*
- * Binary search.
- */
-int nasm_bsi (char *string, const char **array, int size)
-{
- int i = -1, j = size; /* always, i < index < j */
- while (j-i >= 2) {
- int k = (i+j)/2;
- int l = strcmp(string, array[k]);
- if (l<0) /* it's in the first half */
- j = k;
- else if (l>0) /* it's in the second half */
- i = k;
- else /* we've got it :) */
- return k;
- }
- return -1; /* we haven't got it :( */
+ return intn;
}
static char *file_name = NULL;
*str = p;
}
-char *nasm_strcat(char *one, char *two)
+char *nasm_strcat(const char *one, const char *two)
{
char *rslt;
int l1=strlen(one);
* Convert a string into a number, using NASM number rules. Sets
* `*error' to TRUE if an error occurs, and FALSE otherwise.
*/
-long nasm_readnum(char *str, int *error);
+yasm_intnum *nasm_readnum(char *str, int *error);
/*
* Convert a character constant into a number. Sets
* str points to and length covers the middle of the string,
* without the quotes.
*/
-long nasm_readstrnum(char *str, int length, int *warn);
-
-/*
- * seg_init: Initialise the segment-number allocator.
- * seg_alloc: allocate a hitherto unused segment number.
- */
-void nasm_seg_init(void);
-long nasm_seg_alloc(void);
-
-#ifdef YASM_NASM_H
-/*
- * Library routines to manipulate expression data types.
- */
-int nasm_is_reloc(nasm_expr *);
-int nasm_is_simple(nasm_expr *);
-int nasm_is_really_simple (nasm_expr *);
-int nasm_is_unknown(nasm_expr *);
-int nasm_is_just_unknown(nasm_expr *);
-long nasm_reloc_value(nasm_expr *);
-long nasm_reloc_seg(nasm_expr *);
-long nasm_reloc_wrt(nasm_expr *);
-#endif
-
-/*
- * Binary search routine. Returns index into `array' of an entry
- * matching `string', or <0 if no match. `array' is taken to
- * contain `size' elements.
- */
-int nasm_bsi (char *string, const char **array, int size);
-
+yasm_intnum *nasm_readstrnum(char *str, int length, int *warn);
char *nasm_src_set_fname(char *newname);
char *nasm_src_get_fname(void);
int nasm_src_get(long *xline, char **xname);
void nasm_quote(char **str);
-char *nasm_strcat(char *one, char *two);
+char *nasm_strcat(const char *one, const char *two);
#endif
EXTRA_DIST += modules/preprocs/nasm/tests/ifcritical-err.errwarn
EXTRA_DIST += modules/preprocs/nasm/tests/noinclude-err.asm
EXTRA_DIST += modules/preprocs/nasm/tests/noinclude-err.errwarn
+EXTRA_DIST += modules/preprocs/nasm/tests/nasmpp-bigint.asm
+EXTRA_DIST += modules/preprocs/nasm/tests/nasmpp-bigint.errwarn
+EXTRA_DIST += modules/preprocs/nasm/tests/nasmpp-bigint.hex
EXTRA_DIST += modules/preprocs/nasm/tests/orgsect.asm
EXTRA_DIST += modules/preprocs/nasm/tests/orgsect.errwarn
EXTRA_DIST += modules/preprocs/nasm/tests/orgsect.hex
-:4: symbol references not supported
--:4: non-constant value given to `%if'
--- /dev/null
+%if 0x100000000000000 > 0x1000000000000
+db 0
+%endif