Change the NASM preprocessor to use yasm_intnum and yasm_expr. This

decreases bloat and more importantly makes it possible to use >32-bit values
in the preprocessor.

This has NOT been heavily tested, so there may easily be bugs.  I've not yet
decided whether to merge this to 0.5.0 final for this reason.

Inspired by: Jason Chen <jchen@centtech.com> patches to use "long long"
rather than "long" in the preprocessor to enable >32-bit values.

* coretype.h (yasm_op): Add XNOR, LXOR, LXNOR, LNOR.
* intnum.c (yasm_intnum_calc): Calculate the above.
* expr.c (expr_is_constant, expr_can_destroy_int_left)
(expr_can_destroy_int_right, ...): Actually handle logical operations,
including the new ones.

* intnum.c (yasm_intnum_get_str): New; gets a signed decimal string
representation of an intnum.
* intnum.h (yasm_intnum_get_str): Prototype.

* nasmlib.c (nasm_strcat): Change parameters to const.
* nasmlib.h (nasm_strcat): Update prototype.

* nasm-preproc.c (nasm_preproc_input): Close a memory leak.

* nasm.h: Clean out a lot of cruft we don't use.
(tokenval): Change t_integer and t_inttwo to yasm_intnums.
(evalfunc): Remove fwref and hints parameters (cleanup), change return value
to yasm_expr.
* nasm-eval.c: Massively rewrite to just call appropriate yasm_expr creation
functions rather than calculating the value here.  Overall recursive descent
parsing structure is unchanged.
* nasmlib.c: Remove a lot of now-unused functions.
(nasm_readnum): Use yasm_intnum functions and return that.
(nasm_readstrnum): Likewise.
* nasmlib.h: Update prototypes.
* nasm-pp.c: Change to use intnum/expr as necessary.
* nasm-preproc.c (nasm_preproc_destroy): Don't call nasm_eval_cleanup,
it's been deleted.

* nasmpp-bigint.asm: New test for >32-bit preproc values.
* ifcritical-err.errwarn: The new code doesn't generate a duplicate warning.

svn path=/trunk/yasm/; revision=1485
0.5.0
Peter Johnson 19 years ago
parent e542de015a
commit a581559202
  1. 4
      libyasm/coretype.h
  2. 54
      libyasm/expr.c
  3. 38
      libyasm/intnum.c
  4. 8
      libyasm/intnum.h
  5. 674
      modules/preprocs/nasm/nasm-eval.c
  6. 14
      modules/preprocs/nasm/nasm-eval.h
  7. 112
      modules/preprocs/nasm/nasm-pp.c
  8. 5
      modules/preprocs/nasm/nasm-preproc.c
  9. 575
      modules/preprocs/nasm/nasm.h
  10. 273
      modules/preprocs/nasm/nasmlib.c
  11. 35
      modules/preprocs/nasm/nasmlib.h
  12. 3
      modules/preprocs/nasm/tests/Makefile.inc
  13. 1
      modules/preprocs/nasm/tests/ifcritical-err.errwarn
  14. 3
      modules/preprocs/nasm/tests/nasmpp-bigint.asm
  15. 0
      modules/preprocs/nasm/tests/nasmpp-bigint.errwarn
  16. 1
      modules/preprocs/nasm/tests/nasmpp-bigint.hex

@ -187,12 +187,16 @@ typedef enum {
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. */

@ -373,8 +373,10 @@ expr_xform_neg(/*@returned@*/ /*@only@*/ yasm_expr *e)
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));
}
@ -382,24 +384,31 @@ expr_is_constant(yasm_expr_op op, yasm_intnum *intn)
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.
@ -476,9 +485,10 @@ expr_simplify_identity(yasm_expr *e, int numterms, int int_term,
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. */
@ -598,7 +608,8 @@ expr_level_op(/*@returned@*/ /*@only@*/ yasm_expr *e, int fold_const,
*/
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)
@ -846,6 +857,9 @@ yasm_expr__order_terms(yasm_expr *e)
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).
@ -1188,6 +1202,9 @@ yasm_expr_print(const yasm_expr *e, FILE *f)
case YASM_EXPR_XOR:
strcpy(opstr, "^");
break;
case YASM_EXPR_XNOR:
strcpy(opstr, "XNOR");
break;
case YASM_EXPR_NOR:
strcpy(opstr, "NOR");
break;
@ -1206,6 +1223,15 @@ yasm_expr_print(const yasm_expr *e, FILE *f)
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;

@ -396,6 +396,10 @@ yasm_intnum_calc(yasm_intnum *acc, yasm_expr_op op, yasm_intnum *operand,
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);
@ -428,6 +432,21 @@ yasm_intnum_calc(yasm_intnum *acc, yasm_expr_op op, yasm_intnum *operand,
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));
@ -859,6 +878,25 @@ yasm_size_uleb128(unsigned long v)
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)
{

@ -251,6 +251,14 @@ unsigned long yasm_get_uleb128(unsigned long v, unsigned char *ptr);
*/
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

@ -9,217 +9,21 @@
*/
#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,
@ -254,104 +58,83 @@ static nasm_expr *segment_part (nasm_expr *e)
* | 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;
@ -360,137 +143,106 @@ static nasm_expr *rexp3(int critical)
{
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;
@ -498,60 +250,58 @@ static nasm_expr *expr3(int critical)
{
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 == '%' ||
@ -559,111 +309,64 @@ static nasm_expr *expr5(int critical)
{
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 != ')') {
@ -673,100 +376,34 @@ static nasm_expr *expr6(int critical)
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;
@ -777,52 +414,11 @@ nasm_expr *nasm_evaluate (scanner sc, void *scprivate, struct tokenval *tv,
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 ();
}

@ -9,20 +9,10 @@
#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

@ -35,6 +35,8 @@
*/
#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>
@ -88,7 +90,7 @@ struct MMacro
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;
@ -101,7 +103,7 @@ struct MMacro
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 */
};
@ -415,7 +417,7 @@ static Token *expand_mmac_params(Token * tline);
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);
@ -1422,7 +1424,8 @@ if_condition(Token * tline, int i)
int j, casesense;
Token *t, *tt, **tptr, *origline;
struct tokenval tokval;
nasm_expr *evalresult;
yasm_expr *evalresult;
yasm_intnum *intn;
origline = tline;
@ -1589,8 +1592,10 @@ if_condition(Token * tline, int i)
}
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'",
@ -1607,7 +1612,9 @@ if_condition(Token * tline, int i)
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'",
@ -1694,21 +1701,25 @@ if_condition(Token * tline, int i)
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,
@ -1758,8 +1769,9 @@ do_directive(Token * tline)
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;
@ -2341,8 +2353,10 @@ do_directive(Token * 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'",
@ -2359,7 +2373,9 @@ do_directive(Token * tline)
(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'",
@ -2445,17 +2461,18 @@ do_directive(Token * tline)
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;
@ -2473,13 +2490,14 @@ do_directive(Token * tline)
}
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:
@ -2502,8 +2520,7 @@ do_directive(Token * tline)
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);
@ -2512,12 +2529,15 @@ do_directive(Token * tline)
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
{
@ -2816,7 +2836,8 @@ do_directive(Token * tline)
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;
/*
@ -2896,34 +2917,36 @@ do_directive(Token * tline)
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;
@ -2993,8 +3016,7 @@ do_directive(Token * tline)
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)
{
@ -3006,18 +3028,21 @@ do_directive(Token * tline)
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;
/*
@ -3068,7 +3093,9 @@ do_directive(Token * tline)
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, "+"))
@ -3080,7 +3107,9 @@ do_directive(Token * 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);
@ -3187,7 +3216,7 @@ expand_mmac_params(Token * tline)
*/
case '0':
type = TOK_NUMBER;
sprintf(tmpbuf, "%d", mac->nparam);
sprintf(tmpbuf, "%ld", mac->nparam);
text = nasm_strdup(tmpbuf);
break;
case '%':
@ -3420,7 +3449,7 @@ expand_smacro(Token * tline)
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);
@ -3901,7 +3930,8 @@ expand_mmacro(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);
@ -4098,7 +4128,7 @@ pp_reset(FILE *f, const char *file, int apass, efunc errfunc, evalfunc eval,
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;
@ -4506,11 +4536,9 @@ pp_extra_stdmac(const char **macros)
}
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;
}

@ -149,7 +149,6 @@ static void
nasm_preproc_destroy(yasm_preproc *preproc)
{
nasmpp.cleanup(0);
nasm_eval_cleanup();
yasm_xfree(preproc);
if (preproc_deps)
yasm_xfree(preproc_deps);
@ -189,6 +188,10 @@ nasm_preproc_input(yasm_preproc *preproc, char *buf, size_t max_size)
}
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);

@ -21,9 +21,6 @@
#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
@ -38,21 +35,6 @@
#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
@ -101,21 +83,6 @@ typedef void (*efunc) (int severity, const char *fmt, ...);
* -----------------------
*/
/*
* 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:
*/
@ -186,7 +153,7 @@ typedef struct {
*/
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);
@ -212,48 +179,12 @@ enum { /* token types, other than chars */
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
@ -265,27 +196,10 @@ struct eval_hints {
* 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:
@ -348,478 +262,6 @@ enum {
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
@ -835,15 +277,4 @@ struct dfmt {
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

@ -7,6 +7,7 @@
*/
#include <util.h>
#include <libyasm/coretype.h>
#include <libyasm/intnum.h>
#include <ctype.h>
#include "nasm.h"
@ -16,14 +17,14 @@
#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;
@ -36,7 +37,7 @@ long nasm_readnum (char *str, int *error)
if (*r == '-')
{
r++;
sign = -1;
sign = 1;
}
q = r;
@ -69,237 +70,61 @@ long nasm_readnum (char *str, int *error)
*/
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;
@ -365,7 +190,7 @@ void nasm_quote(char **str)
*str = p;
}
char *nasm_strcat(char *one, char *two)
char *nasm_strcat(const char *one, const char *two)
{
char *rslt;
int l1=strlen(one);

@ -32,7 +32,7 @@
* 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
@ -40,36 +40,7 @@ long nasm_readnum(char *str, int *error);
* 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);
@ -84,6 +55,6 @@ long nasm_src_get_linnum(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

@ -7,6 +7,9 @@ EXTRA_DIST += modules/preprocs/nasm/tests/ifcritical-err.asm
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

@ -1,2 +1 @@
-:4: symbol references not supported
-:4: non-constant value given to `%if'

@ -0,0 +1,3 @@
%if 0x100000000000000 > 0x1000000000000
db 0
%endif
Loading…
Cancel
Save