aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/tools/yasm/libyasm
diff options
context:
space:
mode:
authorsomov <somov@yandex-team.ru>2022-02-10 16:45:47 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:45:47 +0300
commita5950576e397b1909261050b8c7da16db58f10b1 (patch)
tree7ba7677f6a4c3e19e2cefab34d16df2c8963b4d4 /contrib/tools/yasm/libyasm
parent81eddc8c0b55990194e112b02d127b87d54164a9 (diff)
downloadydb-a5950576e397b1909261050b8c7da16db58f10b1.tar.gz
Restoring authorship annotation for <somov@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/tools/yasm/libyasm')
-rw-r--r--contrib/tools/yasm/libyasm/arch.h990
-rw-r--r--contrib/tools/yasm/libyasm/assocdat.c276
-rw-r--r--contrib/tools/yasm/libyasm/assocdat.h152
-rw-r--r--contrib/tools/yasm/libyasm/bc-align.c490
-rw-r--r--contrib/tools/yasm/libyasm/bc-data.c1200
-rw-r--r--contrib/tools/yasm/libyasm/bc-incbin.c530
-rw-r--r--contrib/tools/yasm/libyasm/bc-org.c304
-rw-r--r--contrib/tools/yasm/libyasm/bc-reserve.c304
-rw-r--r--contrib/tools/yasm/libyasm/bitvect.c8090
-rw-r--r--contrib/tools/yasm/libyasm/bitvect.h1332
-rw-r--r--contrib/tools/yasm/libyasm/bytecode.c772
-rw-r--r--contrib/tools/yasm/libyasm/bytecode.h1276
-rw-r--r--contrib/tools/yasm/libyasm/cmake-module.c252
-rw-r--r--contrib/tools/yasm/libyasm/compat-queue.h912
-rw-r--r--contrib/tools/yasm/libyasm/coretype.h786
-rw-r--r--contrib/tools/yasm/libyasm/dbgfmt.h244
-rw-r--r--contrib/tools/yasm/libyasm/errwarn.c1058
-rw-r--r--contrib/tools/yasm/libyasm/errwarn.h696
-rw-r--r--contrib/tools/yasm/libyasm/expr.c3032
-rw-r--r--contrib/tools/yasm/libyasm/expr.h776
-rw-r--r--contrib/tools/yasm/libyasm/file.c1342
-rw-r--r--contrib/tools/yasm/libyasm/file.h1050
-rw-r--r--contrib/tools/yasm/libyasm/floatnum.c1520
-rw-r--r--contrib/tools/yasm/libyasm/floatnum.h262
-rw-r--r--contrib/tools/yasm/libyasm/genmodule.c456
-rw-r--r--contrib/tools/yasm/libyasm/hamt.c842
-rw-r--r--contrib/tools/yasm/libyasm/hamt.h246
-rw-r--r--contrib/tools/yasm/libyasm/insn.c590
-rw-r--r--contrib/tools/yasm/libyasm/insn.h538
-rw-r--r--contrib/tools/yasm/libyasm/intnum.c2192
-rw-r--r--contrib/tools/yasm/libyasm/intnum.h680
-rw-r--r--contrib/tools/yasm/libyasm/inttree.c1772
-rw-r--r--contrib/tools/yasm/libyasm/inttree.h140
-rw-r--r--contrib/tools/yasm/libyasm/linemap.c586
-rw-r--r--contrib/tools/yasm/libyasm/linemap.h282
-rw-r--r--contrib/tools/yasm/libyasm/listfmt.h248
-rw-r--r--contrib/tools/yasm/libyasm/md5.c616
-rw-r--r--contrib/tools/yasm/libyasm/md5.h64
-rw-r--r--contrib/tools/yasm/libyasm/mergesort.c722
-rw-r--r--contrib/tools/yasm/libyasm/module.h164
-rw-r--r--contrib/tools/yasm/libyasm/objfmt.h432
-rw-r--r--contrib/tools/yasm/libyasm/parser.h134
-rw-r--r--contrib/tools/yasm/libyasm/phash.c524
-rw-r--r--contrib/tools/yasm/libyasm/phash.h38
-rw-r--r--contrib/tools/yasm/libyasm/preproc.h420
-rw-r--r--contrib/tools/yasm/libyasm/section.c3162
-rw-r--r--contrib/tools/yasm/libyasm/section.h766
-rw-r--r--contrib/tools/yasm/libyasm/strcasecmp.c188
-rw-r--r--contrib/tools/yasm/libyasm/strsep.c164
-rw-r--r--contrib/tools/yasm/libyasm/symrec.c1428
-rw-r--r--contrib/tools/yasm/libyasm/symrec.h874
-rw-r--r--contrib/tools/yasm/libyasm/valparam.c770
-rw-r--r--contrib/tools/yasm/libyasm/valparam.h816
-rw-r--r--contrib/tools/yasm/libyasm/value.c1542
-rw-r--r--contrib/tools/yasm/libyasm/value.h344
-rw-r--r--contrib/tools/yasm/libyasm/xmalloc.c228
-rw-r--r--contrib/tools/yasm/libyasm/xstrdup.c136
57 files changed, 24875 insertions, 24875 deletions
diff --git a/contrib/tools/yasm/libyasm/arch.h b/contrib/tools/yasm/libyasm/arch.h
index 3da9f9fca3..1e7ee0c8ba 100644
--- a/contrib/tools/yasm/libyasm/arch.h
+++ b/contrib/tools/yasm/libyasm/arch.h
@@ -1,495 +1,495 @@
-/**
- * \file libyasm/arch.h
- * \brief YASM architecture interface.
- *
- * \license
- * Copyright (C) 2002-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- * \endlicense
- */
-#ifndef YASM_ARCH_H
-#define YASM_ARCH_H
-
-/** Errors that may be returned by yasm_arch_module::create(). */
-typedef enum yasm_arch_create_error {
- YASM_ARCH_CREATE_OK = 0, /**< No error. */
- YASM_ARCH_CREATE_BAD_MACHINE, /**< Unrecognized machine name. */
- YASM_ARCH_CREATE_BAD_PARSER /**< Unrecognized parser name. */
-} yasm_arch_create_error;
-
-/** Return values for yasm_arch_module::parse_check_insnprefix(). */
-typedef enum yasm_arch_insnprefix {
- YASM_ARCH_NOTINSNPREFIX = 0, /**< Unrecognized */
- YASM_ARCH_INSN, /**< An instruction */
- YASM_ARCH_PREFIX /**< An instruction prefix */
-} yasm_arch_insnprefix;
-
-/** Types of registers / target modifiers that may be returned by
- * yasm_arch_module::parse_check_regtmod().
- */
-typedef enum yasm_arch_regtmod {
- YASM_ARCH_NOTREGTMOD = 0, /**< Unrecognized */
- YASM_ARCH_REG, /**< A "normal" register */
- YASM_ARCH_REGGROUP, /**< A group of indexable registers */
- YASM_ARCH_SEGREG, /**< A segment register */
- YASM_ARCH_TARGETMOD /**< A target modifier (for jumps) */
-} yasm_arch_regtmod;
-
-#ifndef YASM_DOXYGEN
-/** Base #yasm_arch structure. Must be present as the first element in any
- * #yasm_arch implementation.
- */
-typedef struct yasm_arch_base {
- /** #yasm_arch_module implementation for this architecture. */
- const struct yasm_arch_module *module;
-} yasm_arch_base;
-#endif
-
-/** YASM machine subtype. A number of different machine types may be
- * associated with a single architecture. These may be specific CPU's, but
- * the ABI used to interface with the architecture should be the primary
- * differentiator between machines. Some object formats (ELF) use the machine
- * to determine parameters within the generated output.
- */
-typedef struct yasm_arch_machine {
- /** One-line description of the machine. */
- const char *name;
-
- /** Keyword used to select machine. */
- const char *keyword;
-} yasm_arch_machine;
-
-/** YASM architecture module interface.
- * \note All "data" in parser-related functions (yasm_arch_parse_*) needs to
- * start the parse initialized to 0 to make it okay for a parser-related
- * function to use/check previously stored data to see if it's been
- * called before on the same piece of data.
- */
-typedef struct yasm_arch_module {
- /** One-line description of the architecture.
- * Call yasm_arch_name() to get the name of a particular #yasm_arch.
- */
- const char *name;
-
- /** Keyword used to select architecture.
- * Call yasm_arch_keyword() to get the keyword of a particular #yasm_arch.
- */
- const char *keyword;
-
- /** NULL-terminated list of directives. NULL if none. */
- /*@null@*/ const yasm_directive *directives;
-
- /** Create architecture.
- * Module-level implementation of yasm_arch_create().
- * Call yasm_arch_create() instead of calling this function.
- */
- /*@only@*/ yasm_arch * (*create) (const char *machine, const char *parser,
- /*@out@*/ yasm_arch_create_error *error);
-
- /** Module-level implementation of yasm_arch_destroy().
- * Call yasm_arch_destroy() instead of calling this function.
- */
- void (*destroy) (/*@only@*/ yasm_arch *arch);
-
- /** Module-level implementation of yasm_arch_get_machine().
- * Call yasm_arch_get_machine() instead of calling this function.
- */
- const char * (*get_machine) (const yasm_arch *arch);
-
- /** Module-level implementation of yasm_arch_get_address_size().
- * Call yasm_arch_get_address_size() instead of calling this function.
- */
- unsigned int (*get_address_size) (const yasm_arch *arch);
-
- /** Module-level implementation of yasm_arch_set_var().
- * Call yasm_arch_set_var() instead of calling this function.
- */
- int (*set_var) (yasm_arch *arch, const char *var, unsigned long val);
-
- /** Module-level implementation of yasm_arch_parse_check_insnprefix().
- * Call yasm_arch_parse_check_insnprefix() instead of calling this function.
- */
- yasm_arch_insnprefix (*parse_check_insnprefix)
- (yasm_arch *arch, const char *id, size_t id_len, unsigned long line,
- /*@out@*/ /*@only@*/ yasm_bytecode **bc, /*@out@*/ uintptr_t *prefix);
-
- /** Module-level implementation of yasm_arch_parse_check_regtmod().
- * Call yasm_arch_parse_check_regtmod() instead of calling this function.
- */
- yasm_arch_regtmod (*parse_check_regtmod)
- (yasm_arch *arch, const char *id, size_t id_len,
- /*@out@*/ uintptr_t *data);
-
- /** Module-level implementation of yasm_arch_get_fill().
- * Call yasm_arch_get_fill() instead of calling this function.
- */
- const unsigned char ** (*get_fill) (const yasm_arch *arch);
-
- /** Module-level implementation of yasm_arch_floatnum_tobytes().
- * Call yasm_arch_floatnum_tobytes() instead of calling this function.
- */
- int (*floatnum_tobytes) (yasm_arch *arch, const yasm_floatnum *flt,
- unsigned char *buf, size_t destsize,
- size_t valsize, size_t shift, int warn);
-
- /** Module-level implementation of yasm_arch_intnum_tobytes().
- * Call yasm_arch_intnum_tobytes() instead of calling this function.
- */
- int (*intnum_tobytes) (yasm_arch *arch, const yasm_intnum *intn,
- unsigned char *buf, size_t destsize, size_t valsize,
- int shift, const yasm_bytecode *bc,
- int warn);
-
- /** Module-level implementation of yasm_arch_get_reg_size().
- * Call yasm_arch_get_reg_size() instead of calling this function.
- */
- unsigned int (*get_reg_size) (yasm_arch *arch, uintptr_t reg);
-
- /** Module-level implementation of yasm_arch_reggroup_get_reg().
- * Call yasm_arch_reggroup_get_reg() instead of calling this function.
- */
- uintptr_t (*reggroup_get_reg) (yasm_arch *arch, uintptr_t reggroup,
- unsigned long regindex);
-
- /** Module-level implementation of yasm_arch_reg_print().
- * Call yasm_arch_reg_print() instead of calling this function.
- */
- void (*reg_print) (yasm_arch *arch, uintptr_t reg, FILE *f);
-
- /** Module-level implementation of yasm_arch_segreg_print().
- * Call yasm_arch_segreg_print() instead of calling this function.
- */
- void (*segreg_print) (yasm_arch *arch, uintptr_t segreg, FILE *f);
-
- /** Module-level implementation of yasm_arch_ea_create().
- * Call yasm_arch_ea_create() instead of calling this function.
- */
- yasm_effaddr * (*ea_create) (yasm_arch *arch, /*@keep@*/ yasm_expr *e);
-
- /** Module-level implementation of yasm_arch_ea_destroy().
- * Call yasm_arch_ea_destroy() instead of calling this function.
- */
- void (*ea_destroy) (/*@only@*/ yasm_effaddr *ea);
-
- /** Module-level implementation of yasm_arch_ea_print().
- * Call yasm_arch_ea_print() instead of calling this function.
- */
- void (*ea_print) (const yasm_effaddr *ea, FILE *f, int indent_level);
-
- /** Module-level implementation of yasm_arch_create_empty_insn().
- * Call yasm_arch_create_empty_insn() instead of calling this function.
- */
- /*@only@*/ yasm_bytecode * (*create_empty_insn) (yasm_arch *arch,
- unsigned long line);
-
- /** NULL-terminated list of machines for this architecture.
- * Call yasm_arch_get_machine() to get the active machine of a particular
- * #yasm_arch.
- */
- const yasm_arch_machine *machines;
-
- /** Default machine keyword.
- * Call yasm_arch_get_machine() to get the active machine of a particular
- * #yasm_arch.
- */
- const char *default_machine_keyword;
-
- /** Canonical "word" size in bits.
- * Call yasm_arch_wordsize() to get the word size of a particular
- * #yasm_arch.
- */
- unsigned int wordsize;
-
- /** Worst case minimum instruction length in bytes.
- * Call yasm_arch_min_insn_len() to get the minimum instruction length of
- * a particular #yasm_arch.
- */
- unsigned int min_insn_len;
-} yasm_arch_module;
-
-/** Get the one-line description of an architecture.
- * \param arch architecture
- * \return One-line description of architecture.
- */
-const char *yasm_arch_name(const yasm_arch *arch);
-
-/** Get the keyword used to select an architecture.
- * \param arch architecture
- * \return Architecture keyword.
- */
-const char *yasm_arch_keyword(const yasm_arch *arch);
-
-/** Get the word size of an architecture.
- * \param arch architecture
- * \return Word size (in bits).
- */
-unsigned int yasm_arch_wordsize(const yasm_arch *arch);
-
-/** Get the minimum instruction length of an architecture.
- * \param arch architecture
- * \return Minimum instruction length (in bytes).
- */
-unsigned int yasm_arch_min_insn_len(const yasm_arch *arch);
-
-/** Create architecture.
- * \param module architecture module
- * \param machine keyword of machine in use (must be one listed in
- * #yasm_arch_module.machines)
- * \param parser keyword of parser in use
- * \param error error return value
- * \return NULL on error (error returned in error parameter), otherwise new
- * architecture.
- */
-/*@only@*/ yasm_arch *yasm_arch_create(const yasm_arch_module *module,
- const char *machine, const char *parser,
- /*@out@*/ yasm_arch_create_error *error);
-
-/** Clean up, free any architecture-allocated memory.
- * \param arch architecture
- */
-void yasm_arch_destroy(/*@only@*/ yasm_arch *arch);
-
-/** Get architecture's active machine name.
- * \param arch architecture
- * \return Active machine name.
- */
-const char *yasm_arch_get_machine(const yasm_arch *arch);
-
-/** Get architecture's active address size, in bits.
- * \param arch architecture
- * \return Active address size (in bits).
- */
-unsigned int yasm_arch_get_address_size(const yasm_arch *arch);
-
-/** Set any arch-specific variables. For example, "mode_bits" in x86.
- * \param arch architecture
- * \param var variable name
- * \param val value to set
- * \return Zero on success, non-zero on failure (variable does not exist).
- */
-int yasm_arch_set_var(yasm_arch *arch, const char *var, unsigned long val);
-
-/** Check an generic identifier to see if it matches architecture specific
- * names for instructions or instruction prefixes. Unrecognized identifiers
- * should return #YASM_ARCH_NOTINSNPREFIX so they can be treated as normal
- * symbols. Any additional data beyond just the type (almost always necessary)
- * should be returned into the space provided by the data parameter.
- * \param arch architecture
- * \param id identifier as in the input file
- * \param id_len length of id string
- * \param line virtual line
- * \param bc for instructions, yasm_insn-based bytecode is returned
- * (and NULL otherwise)
- * \param prefix for prefixes, yasm_arch-specific value is returned
- * (and 0 otherwise)
- * \return Identifier type (#YASM_ARCH_NOTINSNPREFIX if unrecognized)
- */
-yasm_arch_insnprefix yasm_arch_parse_check_insnprefix
- (yasm_arch *arch, const char *id, size_t id_len, unsigned long line,
- /*@out@*/ /*@only@*/ yasm_bytecode **bc, /*@out@*/ uintptr_t *prefix);
-
-/** Check an generic identifier to see if it matches architecture specific
- * names for registers or target modifiers. Unrecognized identifiers should
- * return #YASM_ARCH_NOTREGTMOD. Any additional data beyond just the type
- * (almost always necessary) should be returned into the space provided by the
- * data parameter.
- * \param arch architecture
- * \param id identifier as in the input file
- * \param id_len length of id string
- * \param data extra identification information (yasm_arch-specific)
- * [output]
- * \return Identifier type (#YASM_ARCH_NOTREGTMOD if unrecognized)
- */
-yasm_arch_regtmod yasm_arch_parse_check_regtmod
- (yasm_arch *arch, const char *id, size_t id_len,
- /*@out@*/ uintptr_t *data);
-
-/** Get NOP fill patterns for 1-15 bytes of fill.
- * \param arch architecture
- * \return 16-entry array of arrays; [0] is unused, [1] - [15] point to arrays
- * of 1-15 bytes (respectively) in length.
- */
-const unsigned char **yasm_arch_get_fill(const yasm_arch *arch);
-
-/** Output #yasm_floatnum to buffer. Puts the value into the least
- * significant bits of the destination, or may be shifted into more
- * significant bits by the shift parameter. The destination bits are
- * cleared before being set.
- * Architecture-specific because of endianness.
- * \param arch architecture
- * \param flt floating point value
- * \param buf buffer to write into
- * \param destsize destination size (in bytes)
- * \param valsize size (in bits)
- * \param shift left shift (in bits)
- * \param warn enables standard overflow/underflow warnings
- * \return Nonzero on error.
- */
-int yasm_arch_floatnum_tobytes(yasm_arch *arch, const yasm_floatnum *flt,
- unsigned char *buf, size_t destsize,
- size_t valsize, size_t shift, int warn);
-
-/** Output #yasm_intnum to buffer. Puts the value into the least
- * significant bits of the destination, or may be shifted into more
- * significant bits by the shift parameter. The destination bits are
- * cleared before being set.
- * \param arch architecture
- * \param intn integer value
- * \param buf buffer to write into
- * \param destsize destination size (in bytes)
- * \param valsize size (in bits)
- * \param shift left shift (in bits); may be negative to specify right
- * shift (standard warnings include truncation to boundary)
- * \param bc bytecode being output ("parent" of value)
- * \param warn enables standard warnings (value doesn't fit into
- * valsize bits)
- * \return Nonzero on error.
- */
-int yasm_arch_intnum_tobytes(yasm_arch *arch, const yasm_intnum *intn,
- unsigned char *buf, size_t destsize,
- size_t valsize, int shift,
- const yasm_bytecode *bc, int warn);
-
-/** Get the equivalent size of a register in bits.
- * \param arch architecture
- * \param reg register
- * \return 0 if there is no suitable equivalent size, otherwise the size.
- */
-unsigned int yasm_arch_get_reg_size(yasm_arch *arch, uintptr_t reg);
-
-/** Get a specific register of a register group, based on the register
- * group and the index within the group.
- * \param arch architecture
- * \param reggroup register group
- * \param regindex register index
- * \return 0 if regindex is not valid for that register group, otherwise the
- * specific register value.
- */
-uintptr_t yasm_arch_reggroup_get_reg(yasm_arch *arch, uintptr_t reggroup,
- unsigned long regindex);
-
-/** Print a register. For debugging purposes.
- * \param arch architecture
- * \param reg register
- * \param f file
- */
-void yasm_arch_reg_print(yasm_arch *arch, uintptr_t reg, FILE *f);
-
-/** Print a segment register. For debugging purposes.
- * \param arch architecture
- * \param segreg segment register
- * \param f file
- */
-void yasm_arch_segreg_print(yasm_arch *arch, uintptr_t segreg, FILE *f);
-
-/** Create an effective address from an expression.
- * \param arch architecture
- * \param e expression (kept, do not delete)
- * \return Newly allocated effective address.
- */
-yasm_effaddr *yasm_arch_ea_create(yasm_arch *arch, /*@keep@*/ yasm_expr *e);
-
-/** Delete (free allocated memory for) an effective address.
- * \param arch architecture
- * \param ea effective address (only pointer to it).
- */
-void yasm_arch_ea_destroy(yasm_arch *arch, /*@only@*/ yasm_effaddr *ea);
-
-/** Print an effective address. For debugging purposes.
- * \param arch architecture
- * \param ea effective address
- * \param f file
- * \param indent_level indentation level
- */
-void yasm_arch_ea_print(const yasm_arch *arch, const yasm_effaddr *ea,
- FILE *f, int indent_level);
-
-/** Create a bytecode that represents a single empty (0 length) instruction.
- * This is used for handling solitary prefixes.
- * \param arch architecture
- * \param line virtual line (from yasm_linemap)
- * \return Newly allocated bytecode.
- */
-/*@only@*/ yasm_bytecode *yasm_arch_create_empty_insn(yasm_arch *arch,
- unsigned long line);
-
-#ifndef YASM_DOXYGEN
-
-/* Inline macro implementations for arch functions */
-
-#define yasm_arch_name(arch) \
- (((yasm_arch_base *)arch)->module->name)
-#define yasm_arch_keyword(arch) \
- (((yasm_arch_base *)arch)->module->keyword)
-#define yasm_arch_wordsize(arch) \
- (((yasm_arch_base *)arch)->module->wordsize)
-#define yasm_arch_min_insn_len(arch) \
- (((yasm_arch_base *)arch)->module->min_insn_len)
-
-#define yasm_arch_create(module, machine, parser, error) \
- module->create(machine, parser, error)
-
-#define yasm_arch_destroy(arch) \
- ((yasm_arch_base *)arch)->module->destroy(arch)
-#define yasm_arch_get_machine(arch) \
- ((yasm_arch_base *)arch)->module->get_machine(arch)
-#define yasm_arch_get_address_size(arch) \
- ((yasm_arch_base *)arch)->module->get_address_size(arch)
-#define yasm_arch_set_var(arch, var, val) \
- ((yasm_arch_base *)arch)->module->set_var(arch, var, val)
-#define yasm_arch_parse_check_insnprefix(arch, id, id_len, line, bc, prefix) \
- ((yasm_arch_base *)arch)->module->parse_check_insnprefix \
- (arch, id, id_len, line, bc, prefix)
-#define yasm_arch_parse_check_regtmod(arch, id, id_len, data) \
- ((yasm_arch_base *)arch)->module->parse_check_regtmod \
- (arch, id, id_len, data)
-#define yasm_arch_get_fill(arch) \
- ((yasm_arch_base *)arch)->module->get_fill(arch)
-#define yasm_arch_floatnum_tobytes(arch, flt, buf, destsize, valsize, shift, \
- warn) \
- ((yasm_arch_base *)arch)->module->floatnum_tobytes \
- (arch, flt, buf, destsize, valsize, shift, warn)
-#define yasm_arch_intnum_tobytes(arch, intn, buf, destsize, valsize, shift, \
- bc, warn) \
- ((yasm_arch_base *)arch)->module->intnum_tobytes \
- (arch, intn, buf, destsize, valsize, shift, bc, warn)
-#define yasm_arch_get_reg_size(arch, reg) \
- ((yasm_arch_base *)arch)->module->get_reg_size(arch, reg)
-#define yasm_arch_reggroup_get_reg(arch, regg, regi) \
- ((yasm_arch_base *)arch)->module->reggroup_get_reg(arch, regg, regi)
-#define yasm_arch_reg_print(arch, reg, f) \
- ((yasm_arch_base *)arch)->module->reg_print(arch, reg, f)
-#define yasm_arch_segreg_print(arch, segreg, f) \
- ((yasm_arch_base *)arch)->module->segreg_print(arch, segreg, f)
-#define yasm_arch_ea_create(arch, e) \
- ((yasm_arch_base *)arch)->module->ea_create(arch, e)
-#define yasm_arch_ea_destroy(arch, ea) \
- ((yasm_arch_base *)arch)->module->ea_destroy(ea)
-#define yasm_arch_ea_print(arch, ea, f, i) \
- ((yasm_arch_base *)arch)->module->ea_print(ea, f, i)
-#define yasm_arch_create_empty_insn(arch, line) \
- ((yasm_arch_base *)arch)->module->create_empty_insn(arch, line)
-
-#endif
-
-#endif
+/**
+ * \file libyasm/arch.h
+ * \brief YASM architecture interface.
+ *
+ * \license
+ * Copyright (C) 2002-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * \endlicense
+ */
+#ifndef YASM_ARCH_H
+#define YASM_ARCH_H
+
+/** Errors that may be returned by yasm_arch_module::create(). */
+typedef enum yasm_arch_create_error {
+ YASM_ARCH_CREATE_OK = 0, /**< No error. */
+ YASM_ARCH_CREATE_BAD_MACHINE, /**< Unrecognized machine name. */
+ YASM_ARCH_CREATE_BAD_PARSER /**< Unrecognized parser name. */
+} yasm_arch_create_error;
+
+/** Return values for yasm_arch_module::parse_check_insnprefix(). */
+typedef enum yasm_arch_insnprefix {
+ YASM_ARCH_NOTINSNPREFIX = 0, /**< Unrecognized */
+ YASM_ARCH_INSN, /**< An instruction */
+ YASM_ARCH_PREFIX /**< An instruction prefix */
+} yasm_arch_insnprefix;
+
+/** Types of registers / target modifiers that may be returned by
+ * yasm_arch_module::parse_check_regtmod().
+ */
+typedef enum yasm_arch_regtmod {
+ YASM_ARCH_NOTREGTMOD = 0, /**< Unrecognized */
+ YASM_ARCH_REG, /**< A "normal" register */
+ YASM_ARCH_REGGROUP, /**< A group of indexable registers */
+ YASM_ARCH_SEGREG, /**< A segment register */
+ YASM_ARCH_TARGETMOD /**< A target modifier (for jumps) */
+} yasm_arch_regtmod;
+
+#ifndef YASM_DOXYGEN
+/** Base #yasm_arch structure. Must be present as the first element in any
+ * #yasm_arch implementation.
+ */
+typedef struct yasm_arch_base {
+ /** #yasm_arch_module implementation for this architecture. */
+ const struct yasm_arch_module *module;
+} yasm_arch_base;
+#endif
+
+/** YASM machine subtype. A number of different machine types may be
+ * associated with a single architecture. These may be specific CPU's, but
+ * the ABI used to interface with the architecture should be the primary
+ * differentiator between machines. Some object formats (ELF) use the machine
+ * to determine parameters within the generated output.
+ */
+typedef struct yasm_arch_machine {
+ /** One-line description of the machine. */
+ const char *name;
+
+ /** Keyword used to select machine. */
+ const char *keyword;
+} yasm_arch_machine;
+
+/** YASM architecture module interface.
+ * \note All "data" in parser-related functions (yasm_arch_parse_*) needs to
+ * start the parse initialized to 0 to make it okay for a parser-related
+ * function to use/check previously stored data to see if it's been
+ * called before on the same piece of data.
+ */
+typedef struct yasm_arch_module {
+ /** One-line description of the architecture.
+ * Call yasm_arch_name() to get the name of a particular #yasm_arch.
+ */
+ const char *name;
+
+ /** Keyword used to select architecture.
+ * Call yasm_arch_keyword() to get the keyword of a particular #yasm_arch.
+ */
+ const char *keyword;
+
+ /** NULL-terminated list of directives. NULL if none. */
+ /*@null@*/ const yasm_directive *directives;
+
+ /** Create architecture.
+ * Module-level implementation of yasm_arch_create().
+ * Call yasm_arch_create() instead of calling this function.
+ */
+ /*@only@*/ yasm_arch * (*create) (const char *machine, const char *parser,
+ /*@out@*/ yasm_arch_create_error *error);
+
+ /** Module-level implementation of yasm_arch_destroy().
+ * Call yasm_arch_destroy() instead of calling this function.
+ */
+ void (*destroy) (/*@only@*/ yasm_arch *arch);
+
+ /** Module-level implementation of yasm_arch_get_machine().
+ * Call yasm_arch_get_machine() instead of calling this function.
+ */
+ const char * (*get_machine) (const yasm_arch *arch);
+
+ /** Module-level implementation of yasm_arch_get_address_size().
+ * Call yasm_arch_get_address_size() instead of calling this function.
+ */
+ unsigned int (*get_address_size) (const yasm_arch *arch);
+
+ /** Module-level implementation of yasm_arch_set_var().
+ * Call yasm_arch_set_var() instead of calling this function.
+ */
+ int (*set_var) (yasm_arch *arch, const char *var, unsigned long val);
+
+ /** Module-level implementation of yasm_arch_parse_check_insnprefix().
+ * Call yasm_arch_parse_check_insnprefix() instead of calling this function.
+ */
+ yasm_arch_insnprefix (*parse_check_insnprefix)
+ (yasm_arch *arch, const char *id, size_t id_len, unsigned long line,
+ /*@out@*/ /*@only@*/ yasm_bytecode **bc, /*@out@*/ uintptr_t *prefix);
+
+ /** Module-level implementation of yasm_arch_parse_check_regtmod().
+ * Call yasm_arch_parse_check_regtmod() instead of calling this function.
+ */
+ yasm_arch_regtmod (*parse_check_regtmod)
+ (yasm_arch *arch, const char *id, size_t id_len,
+ /*@out@*/ uintptr_t *data);
+
+ /** Module-level implementation of yasm_arch_get_fill().
+ * Call yasm_arch_get_fill() instead of calling this function.
+ */
+ const unsigned char ** (*get_fill) (const yasm_arch *arch);
+
+ /** Module-level implementation of yasm_arch_floatnum_tobytes().
+ * Call yasm_arch_floatnum_tobytes() instead of calling this function.
+ */
+ int (*floatnum_tobytes) (yasm_arch *arch, const yasm_floatnum *flt,
+ unsigned char *buf, size_t destsize,
+ size_t valsize, size_t shift, int warn);
+
+ /** Module-level implementation of yasm_arch_intnum_tobytes().
+ * Call yasm_arch_intnum_tobytes() instead of calling this function.
+ */
+ int (*intnum_tobytes) (yasm_arch *arch, const yasm_intnum *intn,
+ unsigned char *buf, size_t destsize, size_t valsize,
+ int shift, const yasm_bytecode *bc,
+ int warn);
+
+ /** Module-level implementation of yasm_arch_get_reg_size().
+ * Call yasm_arch_get_reg_size() instead of calling this function.
+ */
+ unsigned int (*get_reg_size) (yasm_arch *arch, uintptr_t reg);
+
+ /** Module-level implementation of yasm_arch_reggroup_get_reg().
+ * Call yasm_arch_reggroup_get_reg() instead of calling this function.
+ */
+ uintptr_t (*reggroup_get_reg) (yasm_arch *arch, uintptr_t reggroup,
+ unsigned long regindex);
+
+ /** Module-level implementation of yasm_arch_reg_print().
+ * Call yasm_arch_reg_print() instead of calling this function.
+ */
+ void (*reg_print) (yasm_arch *arch, uintptr_t reg, FILE *f);
+
+ /** Module-level implementation of yasm_arch_segreg_print().
+ * Call yasm_arch_segreg_print() instead of calling this function.
+ */
+ void (*segreg_print) (yasm_arch *arch, uintptr_t segreg, FILE *f);
+
+ /** Module-level implementation of yasm_arch_ea_create().
+ * Call yasm_arch_ea_create() instead of calling this function.
+ */
+ yasm_effaddr * (*ea_create) (yasm_arch *arch, /*@keep@*/ yasm_expr *e);
+
+ /** Module-level implementation of yasm_arch_ea_destroy().
+ * Call yasm_arch_ea_destroy() instead of calling this function.
+ */
+ void (*ea_destroy) (/*@only@*/ yasm_effaddr *ea);
+
+ /** Module-level implementation of yasm_arch_ea_print().
+ * Call yasm_arch_ea_print() instead of calling this function.
+ */
+ void (*ea_print) (const yasm_effaddr *ea, FILE *f, int indent_level);
+
+ /** Module-level implementation of yasm_arch_create_empty_insn().
+ * Call yasm_arch_create_empty_insn() instead of calling this function.
+ */
+ /*@only@*/ yasm_bytecode * (*create_empty_insn) (yasm_arch *arch,
+ unsigned long line);
+
+ /** NULL-terminated list of machines for this architecture.
+ * Call yasm_arch_get_machine() to get the active machine of a particular
+ * #yasm_arch.
+ */
+ const yasm_arch_machine *machines;
+
+ /** Default machine keyword.
+ * Call yasm_arch_get_machine() to get the active machine of a particular
+ * #yasm_arch.
+ */
+ const char *default_machine_keyword;
+
+ /** Canonical "word" size in bits.
+ * Call yasm_arch_wordsize() to get the word size of a particular
+ * #yasm_arch.
+ */
+ unsigned int wordsize;
+
+ /** Worst case minimum instruction length in bytes.
+ * Call yasm_arch_min_insn_len() to get the minimum instruction length of
+ * a particular #yasm_arch.
+ */
+ unsigned int min_insn_len;
+} yasm_arch_module;
+
+/** Get the one-line description of an architecture.
+ * \param arch architecture
+ * \return One-line description of architecture.
+ */
+const char *yasm_arch_name(const yasm_arch *arch);
+
+/** Get the keyword used to select an architecture.
+ * \param arch architecture
+ * \return Architecture keyword.
+ */
+const char *yasm_arch_keyword(const yasm_arch *arch);
+
+/** Get the word size of an architecture.
+ * \param arch architecture
+ * \return Word size (in bits).
+ */
+unsigned int yasm_arch_wordsize(const yasm_arch *arch);
+
+/** Get the minimum instruction length of an architecture.
+ * \param arch architecture
+ * \return Minimum instruction length (in bytes).
+ */
+unsigned int yasm_arch_min_insn_len(const yasm_arch *arch);
+
+/** Create architecture.
+ * \param module architecture module
+ * \param machine keyword of machine in use (must be one listed in
+ * #yasm_arch_module.machines)
+ * \param parser keyword of parser in use
+ * \param error error return value
+ * \return NULL on error (error returned in error parameter), otherwise new
+ * architecture.
+ */
+/*@only@*/ yasm_arch *yasm_arch_create(const yasm_arch_module *module,
+ const char *machine, const char *parser,
+ /*@out@*/ yasm_arch_create_error *error);
+
+/** Clean up, free any architecture-allocated memory.
+ * \param arch architecture
+ */
+void yasm_arch_destroy(/*@only@*/ yasm_arch *arch);
+
+/** Get architecture's active machine name.
+ * \param arch architecture
+ * \return Active machine name.
+ */
+const char *yasm_arch_get_machine(const yasm_arch *arch);
+
+/** Get architecture's active address size, in bits.
+ * \param arch architecture
+ * \return Active address size (in bits).
+ */
+unsigned int yasm_arch_get_address_size(const yasm_arch *arch);
+
+/** Set any arch-specific variables. For example, "mode_bits" in x86.
+ * \param arch architecture
+ * \param var variable name
+ * \param val value to set
+ * \return Zero on success, non-zero on failure (variable does not exist).
+ */
+int yasm_arch_set_var(yasm_arch *arch, const char *var, unsigned long val);
+
+/** Check an generic identifier to see if it matches architecture specific
+ * names for instructions or instruction prefixes. Unrecognized identifiers
+ * should return #YASM_ARCH_NOTINSNPREFIX so they can be treated as normal
+ * symbols. Any additional data beyond just the type (almost always necessary)
+ * should be returned into the space provided by the data parameter.
+ * \param arch architecture
+ * \param id identifier as in the input file
+ * \param id_len length of id string
+ * \param line virtual line
+ * \param bc for instructions, yasm_insn-based bytecode is returned
+ * (and NULL otherwise)
+ * \param prefix for prefixes, yasm_arch-specific value is returned
+ * (and 0 otherwise)
+ * \return Identifier type (#YASM_ARCH_NOTINSNPREFIX if unrecognized)
+ */
+yasm_arch_insnprefix yasm_arch_parse_check_insnprefix
+ (yasm_arch *arch, const char *id, size_t id_len, unsigned long line,
+ /*@out@*/ /*@only@*/ yasm_bytecode **bc, /*@out@*/ uintptr_t *prefix);
+
+/** Check an generic identifier to see if it matches architecture specific
+ * names for registers or target modifiers. Unrecognized identifiers should
+ * return #YASM_ARCH_NOTREGTMOD. Any additional data beyond just the type
+ * (almost always necessary) should be returned into the space provided by the
+ * data parameter.
+ * \param arch architecture
+ * \param id identifier as in the input file
+ * \param id_len length of id string
+ * \param data extra identification information (yasm_arch-specific)
+ * [output]
+ * \return Identifier type (#YASM_ARCH_NOTREGTMOD if unrecognized)
+ */
+yasm_arch_regtmod yasm_arch_parse_check_regtmod
+ (yasm_arch *arch, const char *id, size_t id_len,
+ /*@out@*/ uintptr_t *data);
+
+/** Get NOP fill patterns for 1-15 bytes of fill.
+ * \param arch architecture
+ * \return 16-entry array of arrays; [0] is unused, [1] - [15] point to arrays
+ * of 1-15 bytes (respectively) in length.
+ */
+const unsigned char **yasm_arch_get_fill(const yasm_arch *arch);
+
+/** Output #yasm_floatnum to buffer. Puts the value into the least
+ * significant bits of the destination, or may be shifted into more
+ * significant bits by the shift parameter. The destination bits are
+ * cleared before being set.
+ * Architecture-specific because of endianness.
+ * \param arch architecture
+ * \param flt floating point value
+ * \param buf buffer to write into
+ * \param destsize destination size (in bytes)
+ * \param valsize size (in bits)
+ * \param shift left shift (in bits)
+ * \param warn enables standard overflow/underflow warnings
+ * \return Nonzero on error.
+ */
+int yasm_arch_floatnum_tobytes(yasm_arch *arch, const yasm_floatnum *flt,
+ unsigned char *buf, size_t destsize,
+ size_t valsize, size_t shift, int warn);
+
+/** Output #yasm_intnum to buffer. Puts the value into the least
+ * significant bits of the destination, or may be shifted into more
+ * significant bits by the shift parameter. The destination bits are
+ * cleared before being set.
+ * \param arch architecture
+ * \param intn integer value
+ * \param buf buffer to write into
+ * \param destsize destination size (in bytes)
+ * \param valsize size (in bits)
+ * \param shift left shift (in bits); may be negative to specify right
+ * shift (standard warnings include truncation to boundary)
+ * \param bc bytecode being output ("parent" of value)
+ * \param warn enables standard warnings (value doesn't fit into
+ * valsize bits)
+ * \return Nonzero on error.
+ */
+int yasm_arch_intnum_tobytes(yasm_arch *arch, const yasm_intnum *intn,
+ unsigned char *buf, size_t destsize,
+ size_t valsize, int shift,
+ const yasm_bytecode *bc, int warn);
+
+/** Get the equivalent size of a register in bits.
+ * \param arch architecture
+ * \param reg register
+ * \return 0 if there is no suitable equivalent size, otherwise the size.
+ */
+unsigned int yasm_arch_get_reg_size(yasm_arch *arch, uintptr_t reg);
+
+/** Get a specific register of a register group, based on the register
+ * group and the index within the group.
+ * \param arch architecture
+ * \param reggroup register group
+ * \param regindex register index
+ * \return 0 if regindex is not valid for that register group, otherwise the
+ * specific register value.
+ */
+uintptr_t yasm_arch_reggroup_get_reg(yasm_arch *arch, uintptr_t reggroup,
+ unsigned long regindex);
+
+/** Print a register. For debugging purposes.
+ * \param arch architecture
+ * \param reg register
+ * \param f file
+ */
+void yasm_arch_reg_print(yasm_arch *arch, uintptr_t reg, FILE *f);
+
+/** Print a segment register. For debugging purposes.
+ * \param arch architecture
+ * \param segreg segment register
+ * \param f file
+ */
+void yasm_arch_segreg_print(yasm_arch *arch, uintptr_t segreg, FILE *f);
+
+/** Create an effective address from an expression.
+ * \param arch architecture
+ * \param e expression (kept, do not delete)
+ * \return Newly allocated effective address.
+ */
+yasm_effaddr *yasm_arch_ea_create(yasm_arch *arch, /*@keep@*/ yasm_expr *e);
+
+/** Delete (free allocated memory for) an effective address.
+ * \param arch architecture
+ * \param ea effective address (only pointer to it).
+ */
+void yasm_arch_ea_destroy(yasm_arch *arch, /*@only@*/ yasm_effaddr *ea);
+
+/** Print an effective address. For debugging purposes.
+ * \param arch architecture
+ * \param ea effective address
+ * \param f file
+ * \param indent_level indentation level
+ */
+void yasm_arch_ea_print(const yasm_arch *arch, const yasm_effaddr *ea,
+ FILE *f, int indent_level);
+
+/** Create a bytecode that represents a single empty (0 length) instruction.
+ * This is used for handling solitary prefixes.
+ * \param arch architecture
+ * \param line virtual line (from yasm_linemap)
+ * \return Newly allocated bytecode.
+ */
+/*@only@*/ yasm_bytecode *yasm_arch_create_empty_insn(yasm_arch *arch,
+ unsigned long line);
+
+#ifndef YASM_DOXYGEN
+
+/* Inline macro implementations for arch functions */
+
+#define yasm_arch_name(arch) \
+ (((yasm_arch_base *)arch)->module->name)
+#define yasm_arch_keyword(arch) \
+ (((yasm_arch_base *)arch)->module->keyword)
+#define yasm_arch_wordsize(arch) \
+ (((yasm_arch_base *)arch)->module->wordsize)
+#define yasm_arch_min_insn_len(arch) \
+ (((yasm_arch_base *)arch)->module->min_insn_len)
+
+#define yasm_arch_create(module, machine, parser, error) \
+ module->create(machine, parser, error)
+
+#define yasm_arch_destroy(arch) \
+ ((yasm_arch_base *)arch)->module->destroy(arch)
+#define yasm_arch_get_machine(arch) \
+ ((yasm_arch_base *)arch)->module->get_machine(arch)
+#define yasm_arch_get_address_size(arch) \
+ ((yasm_arch_base *)arch)->module->get_address_size(arch)
+#define yasm_arch_set_var(arch, var, val) \
+ ((yasm_arch_base *)arch)->module->set_var(arch, var, val)
+#define yasm_arch_parse_check_insnprefix(arch, id, id_len, line, bc, prefix) \
+ ((yasm_arch_base *)arch)->module->parse_check_insnprefix \
+ (arch, id, id_len, line, bc, prefix)
+#define yasm_arch_parse_check_regtmod(arch, id, id_len, data) \
+ ((yasm_arch_base *)arch)->module->parse_check_regtmod \
+ (arch, id, id_len, data)
+#define yasm_arch_get_fill(arch) \
+ ((yasm_arch_base *)arch)->module->get_fill(arch)
+#define yasm_arch_floatnum_tobytes(arch, flt, buf, destsize, valsize, shift, \
+ warn) \
+ ((yasm_arch_base *)arch)->module->floatnum_tobytes \
+ (arch, flt, buf, destsize, valsize, shift, warn)
+#define yasm_arch_intnum_tobytes(arch, intn, buf, destsize, valsize, shift, \
+ bc, warn) \
+ ((yasm_arch_base *)arch)->module->intnum_tobytes \
+ (arch, intn, buf, destsize, valsize, shift, bc, warn)
+#define yasm_arch_get_reg_size(arch, reg) \
+ ((yasm_arch_base *)arch)->module->get_reg_size(arch, reg)
+#define yasm_arch_reggroup_get_reg(arch, regg, regi) \
+ ((yasm_arch_base *)arch)->module->reggroup_get_reg(arch, regg, regi)
+#define yasm_arch_reg_print(arch, reg, f) \
+ ((yasm_arch_base *)arch)->module->reg_print(arch, reg, f)
+#define yasm_arch_segreg_print(arch, segreg, f) \
+ ((yasm_arch_base *)arch)->module->segreg_print(arch, segreg, f)
+#define yasm_arch_ea_create(arch, e) \
+ ((yasm_arch_base *)arch)->module->ea_create(arch, e)
+#define yasm_arch_ea_destroy(arch, ea) \
+ ((yasm_arch_base *)arch)->module->ea_destroy(ea)
+#define yasm_arch_ea_print(arch, ea, f, i) \
+ ((yasm_arch_base *)arch)->module->ea_print(ea, f, i)
+#define yasm_arch_create_empty_insn(arch, line) \
+ ((yasm_arch_base *)arch)->module->create_empty_insn(arch, line)
+
+#endif
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/assocdat.c b/contrib/tools/yasm/libyasm/assocdat.c
index 560093685e..527c678fc1 100644
--- a/contrib/tools/yasm/libyasm/assocdat.c
+++ b/contrib/tools/yasm/libyasm/assocdat.c
@@ -1,138 +1,138 @@
-/*
- * YASM associated data storage (libyasm internal use)
- *
- * Copyright (C) 2003-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#include "util.h"
-
-#include "coretype.h"
-#include "assocdat.h"
-
-
-typedef struct assoc_data_item {
- const yasm_assoc_data_callback *callback;
- void *data;
-} assoc_data_item;
-
-struct yasm__assoc_data {
- assoc_data_item *vector;
- size_t size;
- size_t alloc;
-};
-
-
-yasm__assoc_data *
-yasm__assoc_data_create(void)
-{
- yasm__assoc_data *assoc_data = yasm_xmalloc(sizeof(yasm__assoc_data));
-
- assoc_data->size = 0;
- assoc_data->alloc = 2;
- assoc_data->vector = yasm_xmalloc(assoc_data->alloc *
- sizeof(assoc_data_item));
-
- return assoc_data;
-}
-
-void *
-yasm__assoc_data_get(yasm__assoc_data *assoc_data,
- const yasm_assoc_data_callback *callback)
-{
- size_t i;
-
- if (!assoc_data)
- return NULL;
-
- for (i=0; i<assoc_data->size; i++) {
- if (assoc_data->vector[i].callback == callback)
- return assoc_data->vector[i].data;
- }
- return NULL;
-}
-
-yasm__assoc_data *
-yasm__assoc_data_add(yasm__assoc_data *assoc_data_arg,
- const yasm_assoc_data_callback *callback, void *data)
-{
- yasm__assoc_data *assoc_data;
- assoc_data_item *item = NULL;
- size_t i;
-
- /* Create a new assoc_data if necessary */
- if (assoc_data_arg)
- assoc_data = assoc_data_arg;
- else
- assoc_data = yasm__assoc_data_create();
-
- /* See if there's already assocated data for this callback */
- for (i=0; i<assoc_data->size; i++) {
- if (assoc_data->vector[i].callback == callback) {
- item = &assoc_data->vector[i];
- break;
- }
- }
-
- /* No? Then append a new one */
- if (!item) {
- assoc_data->size++;
- if (assoc_data->size > assoc_data->alloc) {
- assoc_data->alloc *= 2;
- assoc_data->vector =
- yasm_xrealloc(assoc_data->vector,
- assoc_data->alloc * sizeof(assoc_data_item));
- }
- item = &assoc_data->vector[assoc_data->size-1];
- item->callback = callback;
- item->data = NULL;
- }
-
- /* Delete existing data (if any) */
- if (item->data && item->data != data)
- item->callback->destroy(item->data);
-
- item->data = data;
-
- return assoc_data;
-}
-
-void
-yasm__assoc_data_destroy(yasm__assoc_data *assoc_data)
-{
- size_t i;
-
- if (!assoc_data)
- return;
-
- for (i=0; i<assoc_data->size; i++)
- assoc_data->vector[i].callback->destroy(assoc_data->vector[i].data);
- yasm_xfree(assoc_data->vector);
- yasm_xfree(assoc_data);
-}
-
-void
-yasm__assoc_data_print(const yasm__assoc_data *assoc_data, FILE *f,
- int indent_level)
-{
- /*TODO*/
-}
+/*
+ * YASM associated data storage (libyasm internal use)
+ *
+ * Copyright (C) 2003-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "util.h"
+
+#include "coretype.h"
+#include "assocdat.h"
+
+
+typedef struct assoc_data_item {
+ const yasm_assoc_data_callback *callback;
+ void *data;
+} assoc_data_item;
+
+struct yasm__assoc_data {
+ assoc_data_item *vector;
+ size_t size;
+ size_t alloc;
+};
+
+
+yasm__assoc_data *
+yasm__assoc_data_create(void)
+{
+ yasm__assoc_data *assoc_data = yasm_xmalloc(sizeof(yasm__assoc_data));
+
+ assoc_data->size = 0;
+ assoc_data->alloc = 2;
+ assoc_data->vector = yasm_xmalloc(assoc_data->alloc *
+ sizeof(assoc_data_item));
+
+ return assoc_data;
+}
+
+void *
+yasm__assoc_data_get(yasm__assoc_data *assoc_data,
+ const yasm_assoc_data_callback *callback)
+{
+ size_t i;
+
+ if (!assoc_data)
+ return NULL;
+
+ for (i=0; i<assoc_data->size; i++) {
+ if (assoc_data->vector[i].callback == callback)
+ return assoc_data->vector[i].data;
+ }
+ return NULL;
+}
+
+yasm__assoc_data *
+yasm__assoc_data_add(yasm__assoc_data *assoc_data_arg,
+ const yasm_assoc_data_callback *callback, void *data)
+{
+ yasm__assoc_data *assoc_data;
+ assoc_data_item *item = NULL;
+ size_t i;
+
+ /* Create a new assoc_data if necessary */
+ if (assoc_data_arg)
+ assoc_data = assoc_data_arg;
+ else
+ assoc_data = yasm__assoc_data_create();
+
+ /* See if there's already assocated data for this callback */
+ for (i=0; i<assoc_data->size; i++) {
+ if (assoc_data->vector[i].callback == callback) {
+ item = &assoc_data->vector[i];
+ break;
+ }
+ }
+
+ /* No? Then append a new one */
+ if (!item) {
+ assoc_data->size++;
+ if (assoc_data->size > assoc_data->alloc) {
+ assoc_data->alloc *= 2;
+ assoc_data->vector =
+ yasm_xrealloc(assoc_data->vector,
+ assoc_data->alloc * sizeof(assoc_data_item));
+ }
+ item = &assoc_data->vector[assoc_data->size-1];
+ item->callback = callback;
+ item->data = NULL;
+ }
+
+ /* Delete existing data (if any) */
+ if (item->data && item->data != data)
+ item->callback->destroy(item->data);
+
+ item->data = data;
+
+ return assoc_data;
+}
+
+void
+yasm__assoc_data_destroy(yasm__assoc_data *assoc_data)
+{
+ size_t i;
+
+ if (!assoc_data)
+ return;
+
+ for (i=0; i<assoc_data->size; i++)
+ assoc_data->vector[i].callback->destroy(assoc_data->vector[i].data);
+ yasm_xfree(assoc_data->vector);
+ yasm_xfree(assoc_data);
+}
+
+void
+yasm__assoc_data_print(const yasm__assoc_data *assoc_data, FILE *f,
+ int indent_level)
+{
+ /*TODO*/
+}
diff --git a/contrib/tools/yasm/libyasm/assocdat.h b/contrib/tools/yasm/libyasm/assocdat.h
index cf42386775..79876335d2 100644
--- a/contrib/tools/yasm/libyasm/assocdat.h
+++ b/contrib/tools/yasm/libyasm/assocdat.h
@@ -1,76 +1,76 @@
-/**
- * \file assocdat.h
- * \brief YASM associated data storage (libyasm internal use)
- *
- * \license
- * Copyright (C) 2003-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- * \endlicense
- */
-#ifndef YASM_ASSOCDAT_H
-#define YASM_ASSOCDAT_H
-
-#ifndef YASM_LIB_DECL
-#define YASM_LIB_DECL
-#endif
-
-/** Associated data container. */
-typedef struct yasm__assoc_data yasm__assoc_data;
-
-/** Create an associated data container. */
-YASM_LIB_DECL
-/*@only@*/ yasm__assoc_data *yasm__assoc_data_create(void);
-
-/** Get associated data for a data callback.
- * \param assoc_data container of associated data
- * \param callback callback used when adding data
- * \return Associated data (NULL if none).
- */
-YASM_LIB_DECL
-/*@dependent@*/ /*@null@*/ void *yasm__assoc_data_get
- (/*@null@*/ yasm__assoc_data *assoc_data,
- const yasm_assoc_data_callback *callback);
-
-/** Add associated data to a associated data container.
- * \attention Deletes any existing associated data for that data callback.
- * \param assoc_data container of associated data
- * \param callback callback
- * \param data data to associate
- */
-YASM_LIB_DECL
-/*@only@*/ yasm__assoc_data *yasm__assoc_data_add
- (/*@null@*/ /*@only@*/ yasm__assoc_data *assoc_data,
- const yasm_assoc_data_callback *callback,
- /*@only@*/ /*@null@*/ void *data);
-
-/** Destroy all associated data in a container. */
-YASM_LIB_DECL
-void yasm__assoc_data_destroy
- (/*@null@*/ /*@only@*/ yasm__assoc_data *assoc_data);
-
-/** Print all associated data in a container. */
-YASM_LIB_DECL
-void yasm__assoc_data_print(const yasm__assoc_data *assoc_data, FILE *f,
- int indent_level);
-
-#endif
+/**
+ * \file assocdat.h
+ * \brief YASM associated data storage (libyasm internal use)
+ *
+ * \license
+ * Copyright (C) 2003-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * \endlicense
+ */
+#ifndef YASM_ASSOCDAT_H
+#define YASM_ASSOCDAT_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/** Associated data container. */
+typedef struct yasm__assoc_data yasm__assoc_data;
+
+/** Create an associated data container. */
+YASM_LIB_DECL
+/*@only@*/ yasm__assoc_data *yasm__assoc_data_create(void);
+
+/** Get associated data for a data callback.
+ * \param assoc_data container of associated data
+ * \param callback callback used when adding data
+ * \return Associated data (NULL if none).
+ */
+YASM_LIB_DECL
+/*@dependent@*/ /*@null@*/ void *yasm__assoc_data_get
+ (/*@null@*/ yasm__assoc_data *assoc_data,
+ const yasm_assoc_data_callback *callback);
+
+/** Add associated data to a associated data container.
+ * \attention Deletes any existing associated data for that data callback.
+ * \param assoc_data container of associated data
+ * \param callback callback
+ * \param data data to associate
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm__assoc_data *yasm__assoc_data_add
+ (/*@null@*/ /*@only@*/ yasm__assoc_data *assoc_data,
+ const yasm_assoc_data_callback *callback,
+ /*@only@*/ /*@null@*/ void *data);
+
+/** Destroy all associated data in a container. */
+YASM_LIB_DECL
+void yasm__assoc_data_destroy
+ (/*@null@*/ /*@only@*/ yasm__assoc_data *assoc_data);
+
+/** Print all associated data in a container. */
+YASM_LIB_DECL
+void yasm__assoc_data_print(const yasm__assoc_data *assoc_data, FILE *f,
+ int indent_level);
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/bc-align.c b/contrib/tools/yasm/libyasm/bc-align.c
index 2a47882ef0..42a9cc4671 100644
--- a/contrib/tools/yasm/libyasm/bc-align.c
+++ b/contrib/tools/yasm/libyasm/bc-align.c
@@ -1,245 +1,245 @@
-/*
- * Align bytecode
- *
- * Copyright (C) 2005-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#include "util.h"
-
-#include "libyasm-stdint.h"
-#include "coretype.h"
-
-#include "errwarn.h"
-#include "intnum.h"
-#include "expr.h"
-
-#include "bytecode.h"
-
-
-typedef struct bytecode_align {
- /*@only@*/ yasm_expr *boundary; /* alignment boundary */
-
- /* What to fill intervening locations with, NULL if using code_fill */
- /*@only@*/ /*@null@*/ yasm_expr *fill;
-
- /* Maximum number of bytes to skip, NULL if no maximum. */
- /*@only@*/ /*@null@*/ yasm_expr *maxskip;
-
- /* Code fill, NULL if using 0 fill */
- /*@null@*/ const unsigned char **code_fill;
-} bytecode_align;
-
-static void bc_align_destroy(void *contents);
-static void bc_align_print(const void *contents, FILE *f, int indent_level);
-static void bc_align_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
-static int bc_align_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
- void *add_span_data);
-static int bc_align_expand(yasm_bytecode *bc, int span, long old_val,
- long new_val, /*@out@*/ long *neg_thres,
- /*@out@*/ long *pos_thres);
-static int bc_align_tobytes(yasm_bytecode *bc, unsigned char **bufp,
- unsigned char *bufstart, void *d,
- yasm_output_value_func output_value,
- /*@null@*/ yasm_output_reloc_func output_reloc);
-
-static const yasm_bytecode_callback bc_align_callback = {
- bc_align_destroy,
- bc_align_print,
- bc_align_finalize,
- NULL,
- bc_align_calc_len,
- bc_align_expand,
- bc_align_tobytes,
- YASM_BC_SPECIAL_OFFSET
-};
-
-
-static void
-bc_align_destroy(void *contents)
-{
- bytecode_align *align = (bytecode_align *)contents;
- if (align->boundary)
- yasm_expr_destroy(align->boundary);
- if (align->fill)
- yasm_expr_destroy(align->fill);
- if (align->maxskip)
- yasm_expr_destroy(align->maxskip);
- yasm_xfree(contents);
-}
-
-static void
-bc_align_print(const void *contents, FILE *f, int indent_level)
-{
- const bytecode_align *align = (const bytecode_align *)contents;
- fprintf(f, "%*s_Align_\n", indent_level, "");
- fprintf(f, "%*sBoundary=", indent_level, "");
- yasm_expr_print(align->boundary, f);
- fprintf(f, "\n%*sFill=", indent_level, "");
- yasm_expr_print(align->fill, f);
- fprintf(f, "\n%*sMax Skip=", indent_level, "");
- yasm_expr_print(align->maxskip, f);
- fprintf(f, "\n");
-}
-
-static void
-bc_align_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
-{
- bytecode_align *align = (bytecode_align *)bc->contents;
- if (!yasm_expr_get_intnum(&align->boundary, 0))
- yasm_error_set(YASM_ERROR_NOT_CONSTANT,
- N_("align boundary must be a constant"));
- if (align->fill && !yasm_expr_get_intnum(&align->fill, 0))
- yasm_error_set(YASM_ERROR_NOT_CONSTANT,
- N_("align fill must be a constant"));
- if (align->maxskip && !yasm_expr_get_intnum(&align->maxskip, 0))
- yasm_error_set(YASM_ERROR_NOT_CONSTANT,
- N_("align maximum skip must be a constant"));
-}
-
-static int
-bc_align_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
- void *add_span_data)
-{
- long neg_thres = 0;
- long pos_thres = 0;
-
- if (bc_align_expand(bc, 0, 0, (long)bc->offset, &neg_thres,
- &pos_thres) < 0)
- return -1;
-
- return 0;
-}
-
-static int
-bc_align_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
- /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
-{
- bytecode_align *align = (bytecode_align *)bc->contents;
- unsigned long end;
- unsigned long boundary =
- yasm_intnum_get_uint(yasm_expr_get_intnum(&align->boundary, 0));
-
- if (boundary == 0) {
- bc->len = 0;
- *pos_thres = new_val;
- return 0;
- }
-
- end = (unsigned long)new_val;
- if ((unsigned long)new_val & (boundary-1))
- end = ((unsigned long)new_val & ~(boundary-1)) + boundary;
-
- *pos_thres = (long)end;
- bc->len = end - (unsigned long)new_val;
-
- if (align->maxskip) {
- unsigned long maxskip =
- yasm_intnum_get_uint(yasm_expr_get_intnum(&align->maxskip, 0));
- if (bc->len > maxskip) {
- *pos_thres = (long)end-maxskip-1;
- bc->len = 0;
- }
- }
- return 1;
-}
-
-static int
-bc_align_tobytes(yasm_bytecode *bc, unsigned char **bufp,
- unsigned char *bufstart, void *d,
- yasm_output_value_func output_value,
- /*@unused@*/ yasm_output_reloc_func output_reloc)
-{
- bytecode_align *align = (bytecode_align *)bc->contents;
- unsigned long len;
- unsigned long boundary =
- yasm_intnum_get_uint(yasm_expr_get_intnum(&align->boundary, 0));
-
- if (boundary == 0)
- return 0;
- else {
- unsigned long end = bc->offset;
- if (bc->offset & (boundary-1))
- end = (bc->offset & ~(boundary-1)) + boundary;
- len = end - bc->offset;
- if (len == 0)
- return 0;
- if (align->maxskip) {
- unsigned long maxskip =
- yasm_intnum_get_uint(yasm_expr_get_intnum(&align->maxskip, 0));
- if (len > maxskip)
- return 0;
- }
- }
-
- if (align->fill) {
- unsigned long v;
- v = yasm_intnum_get_uint(yasm_expr_get_intnum(&align->fill, 0));
- memset(*bufp, (int)v, len);
- *bufp += len;
- } else if (align->code_fill) {
- unsigned long maxlen = 15;
- while (!align->code_fill[maxlen] && maxlen>0)
- maxlen--;
- if (maxlen == 0) {
- yasm_error_set(YASM_ERROR_GENERAL,
- N_("could not find any code alignment size"));
- return 1;
- }
-
- /* Fill with maximum code fill as much as possible */
- while (len > maxlen) {
- memcpy(*bufp, align->code_fill[maxlen], maxlen);
- *bufp += maxlen;
- len -= maxlen;
- }
-
- if (!align->code_fill[len]) {
- yasm_error_set(YASM_ERROR_VALUE,
- N_("invalid alignment size %d"), len);
- return 1;
- }
- /* Handle rest of code fill */
- memcpy(*bufp, align->code_fill[len], len);
- *bufp += len;
- } else {
- /* Just fill with 0 */
- memset(*bufp, 0, len);
- *bufp += len;
- }
- return 0;
-}
-
-yasm_bytecode *
-yasm_bc_create_align(yasm_expr *boundary, yasm_expr *fill,
- yasm_expr *maxskip, const unsigned char **code_fill,
- unsigned long line)
-{
- bytecode_align *align = yasm_xmalloc(sizeof(bytecode_align));
-
- align->boundary = boundary;
- align->fill = fill;
- align->maxskip = maxskip;
- align->code_fill = code_fill;
-
- return yasm_bc_create_common(&bc_align_callback, align, line);
-}
+/*
+ * Align bytecode
+ *
+ * Copyright (C) 2005-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "util.h"
+
+#include "libyasm-stdint.h"
+#include "coretype.h"
+
+#include "errwarn.h"
+#include "intnum.h"
+#include "expr.h"
+
+#include "bytecode.h"
+
+
+typedef struct bytecode_align {
+ /*@only@*/ yasm_expr *boundary; /* alignment boundary */
+
+ /* What to fill intervening locations with, NULL if using code_fill */
+ /*@only@*/ /*@null@*/ yasm_expr *fill;
+
+ /* Maximum number of bytes to skip, NULL if no maximum. */
+ /*@only@*/ /*@null@*/ yasm_expr *maxskip;
+
+ /* Code fill, NULL if using 0 fill */
+ /*@null@*/ const unsigned char **code_fill;
+} bytecode_align;
+
+static void bc_align_destroy(void *contents);
+static void bc_align_print(const void *contents, FILE *f, int indent_level);
+static void bc_align_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
+static int bc_align_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data);
+static int bc_align_expand(yasm_bytecode *bc, int span, long old_val,
+ long new_val, /*@out@*/ long *neg_thres,
+ /*@out@*/ long *pos_thres);
+static int bc_align_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+static const yasm_bytecode_callback bc_align_callback = {
+ bc_align_destroy,
+ bc_align_print,
+ bc_align_finalize,
+ NULL,
+ bc_align_calc_len,
+ bc_align_expand,
+ bc_align_tobytes,
+ YASM_BC_SPECIAL_OFFSET
+};
+
+
+static void
+bc_align_destroy(void *contents)
+{
+ bytecode_align *align = (bytecode_align *)contents;
+ if (align->boundary)
+ yasm_expr_destroy(align->boundary);
+ if (align->fill)
+ yasm_expr_destroy(align->fill);
+ if (align->maxskip)
+ yasm_expr_destroy(align->maxskip);
+ yasm_xfree(contents);
+}
+
+static void
+bc_align_print(const void *contents, FILE *f, int indent_level)
+{
+ const bytecode_align *align = (const bytecode_align *)contents;
+ fprintf(f, "%*s_Align_\n", indent_level, "");
+ fprintf(f, "%*sBoundary=", indent_level, "");
+ yasm_expr_print(align->boundary, f);
+ fprintf(f, "\n%*sFill=", indent_level, "");
+ yasm_expr_print(align->fill, f);
+ fprintf(f, "\n%*sMax Skip=", indent_level, "");
+ yasm_expr_print(align->maxskip, f);
+ fprintf(f, "\n");
+}
+
+static void
+bc_align_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
+{
+ bytecode_align *align = (bytecode_align *)bc->contents;
+ if (!yasm_expr_get_intnum(&align->boundary, 0))
+ yasm_error_set(YASM_ERROR_NOT_CONSTANT,
+ N_("align boundary must be a constant"));
+ if (align->fill && !yasm_expr_get_intnum(&align->fill, 0))
+ yasm_error_set(YASM_ERROR_NOT_CONSTANT,
+ N_("align fill must be a constant"));
+ if (align->maxskip && !yasm_expr_get_intnum(&align->maxskip, 0))
+ yasm_error_set(YASM_ERROR_NOT_CONSTANT,
+ N_("align maximum skip must be a constant"));
+}
+
+static int
+bc_align_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ long neg_thres = 0;
+ long pos_thres = 0;
+
+ if (bc_align_expand(bc, 0, 0, (long)bc->offset, &neg_thres,
+ &pos_thres) < 0)
+ return -1;
+
+ return 0;
+}
+
+static int
+bc_align_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
+ /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
+{
+ bytecode_align *align = (bytecode_align *)bc->contents;
+ unsigned long end;
+ unsigned long boundary =
+ yasm_intnum_get_uint(yasm_expr_get_intnum(&align->boundary, 0));
+
+ if (boundary == 0) {
+ bc->len = 0;
+ *pos_thres = new_val;
+ return 0;
+ }
+
+ end = (unsigned long)new_val;
+ if ((unsigned long)new_val & (boundary-1))
+ end = ((unsigned long)new_val & ~(boundary-1)) + boundary;
+
+ *pos_thres = (long)end;
+ bc->len = end - (unsigned long)new_val;
+
+ if (align->maxskip) {
+ unsigned long maxskip =
+ yasm_intnum_get_uint(yasm_expr_get_intnum(&align->maxskip, 0));
+ if (bc->len > maxskip) {
+ *pos_thres = (long)end-maxskip-1;
+ bc->len = 0;
+ }
+ }
+ return 1;
+}
+
+static int
+bc_align_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@unused@*/ yasm_output_reloc_func output_reloc)
+{
+ bytecode_align *align = (bytecode_align *)bc->contents;
+ unsigned long len;
+ unsigned long boundary =
+ yasm_intnum_get_uint(yasm_expr_get_intnum(&align->boundary, 0));
+
+ if (boundary == 0)
+ return 0;
+ else {
+ unsigned long end = bc->offset;
+ if (bc->offset & (boundary-1))
+ end = (bc->offset & ~(boundary-1)) + boundary;
+ len = end - bc->offset;
+ if (len == 0)
+ return 0;
+ if (align->maxskip) {
+ unsigned long maxskip =
+ yasm_intnum_get_uint(yasm_expr_get_intnum(&align->maxskip, 0));
+ if (len > maxskip)
+ return 0;
+ }
+ }
+
+ if (align->fill) {
+ unsigned long v;
+ v = yasm_intnum_get_uint(yasm_expr_get_intnum(&align->fill, 0));
+ memset(*bufp, (int)v, len);
+ *bufp += len;
+ } else if (align->code_fill) {
+ unsigned long maxlen = 15;
+ while (!align->code_fill[maxlen] && maxlen>0)
+ maxlen--;
+ if (maxlen == 0) {
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("could not find any code alignment size"));
+ return 1;
+ }
+
+ /* Fill with maximum code fill as much as possible */
+ while (len > maxlen) {
+ memcpy(*bufp, align->code_fill[maxlen], maxlen);
+ *bufp += maxlen;
+ len -= maxlen;
+ }
+
+ if (!align->code_fill[len]) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("invalid alignment size %d"), len);
+ return 1;
+ }
+ /* Handle rest of code fill */
+ memcpy(*bufp, align->code_fill[len], len);
+ *bufp += len;
+ } else {
+ /* Just fill with 0 */
+ memset(*bufp, 0, len);
+ *bufp += len;
+ }
+ return 0;
+}
+
+yasm_bytecode *
+yasm_bc_create_align(yasm_expr *boundary, yasm_expr *fill,
+ yasm_expr *maxskip, const unsigned char **code_fill,
+ unsigned long line)
+{
+ bytecode_align *align = yasm_xmalloc(sizeof(bytecode_align));
+
+ align->boundary = boundary;
+ align->fill = fill;
+ align->maxskip = maxskip;
+ align->code_fill = code_fill;
+
+ return yasm_bc_create_common(&bc_align_callback, align, line);
+}
diff --git a/contrib/tools/yasm/libyasm/bc-data.c b/contrib/tools/yasm/libyasm/bc-data.c
index ebbdd6f97d..7c115a8b50 100644
--- a/contrib/tools/yasm/libyasm/bc-data.c
+++ b/contrib/tools/yasm/libyasm/bc-data.c
@@ -1,600 +1,600 @@
-/*
- * Data (and LEB128) bytecode
- *
- * Copyright (C) 2001-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#include "util.h"
-
-#include "libyasm-stdint.h"
-#include "coretype.h"
-
-#include "errwarn.h"
-#include "intnum.h"
-#include "expr.h"
-#include "value.h"
-
-#include "bytecode.h"
-#include "arch.h"
-
-
-struct yasm_dataval {
- /*@reldef@*/ STAILQ_ENTRY(yasm_dataval) link;
-
- enum { DV_EMPTY, DV_VALUE, DV_RAW, DV_ULEB128, DV_SLEB128, DV_RESERVE }
- type;
-
- union {
- yasm_value val;
- struct {
- /*@only@*/ unsigned char *contents;
- unsigned long len;
- } raw;
- } data;
-
- /* number of times data is repeated, NULL=1. */
- /*@only@*/ /*@null@*/ yasm_expr *multiple;
-};
-
-typedef struct bytecode_data {
- /* converted data (linked list) */
- yasm_datavalhead datahead;
-
- int item_size;
-} bytecode_data;
-
-static void bc_data_destroy(void *contents);
-static void bc_data_print(const void *contents, FILE *f, int indent_level);
-static void bc_data_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
-static int bc_data_item_size(yasm_bytecode *bc);
-static int bc_data_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
- void *add_span_data);
-static int bc_data_tobytes(yasm_bytecode *bc, unsigned char **bufp,
- unsigned char *bufstart, void *d,
- yasm_output_value_func output_value,
- /*@null@*/ yasm_output_reloc_func output_reloc);
-
-static const yasm_bytecode_callback bc_data_callback = {
- bc_data_destroy,
- bc_data_print,
- bc_data_finalize,
- bc_data_item_size,
- bc_data_calc_len,
- yasm_bc_expand_common,
- bc_data_tobytes,
- 0
-};
-
-
-static void
-bc_data_destroy(void *contents)
-{
- bytecode_data *bc_data = (bytecode_data *)contents;
- yasm_dvs_delete(&bc_data->datahead);
- yasm_xfree(contents);
-}
-
-static void
-bc_data_print(const void *contents, FILE *f, int indent_level)
-{
- const bytecode_data *bc_data = (const bytecode_data *)contents;
- fprintf(f, "%*s_Data_\n", indent_level, "");
- fprintf(f, "%*sElements:\n", indent_level+1, "");
- yasm_dvs_print(&bc_data->datahead, f, indent_level+2);
-}
-
-static void
-bc_data_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
-{
- bytecode_data *bc_data = (bytecode_data *)bc->contents;
- yasm_dataval *dv;
- yasm_intnum *intn;
-
- /* Convert values from simple expr to value. */
- STAILQ_FOREACH(dv, &bc_data->datahead, link) {
- switch (dv->type) {
- case DV_VALUE:
- if (yasm_value_finalize(&dv->data.val, prev_bc)) {
- yasm_error_set(YASM_ERROR_TOO_COMPLEX,
- N_("data expression too complex"));
- return;
- }
- break;
- case DV_ULEB128:
- case DV_SLEB128:
- intn = yasm_expr_get_intnum(&dv->data.val.abs, 0);
- if (!intn) {
- yasm_error_set(YASM_ERROR_NOT_CONSTANT,
- N_("LEB128 requires constant values"));
- return;
- }
- /* Warn for negative values in unsigned environment.
- * This could be an error instead: the likelihood this is
- * desired is very low!
- */
- if (yasm_intnum_sign(intn) == -1 && dv->type == DV_ULEB128)
- yasm_warn_set(YASM_WARN_GENERAL,
- N_("negative value in unsigned LEB128"));
- break;
- default:
- break;
- }
- if (dv->multiple) {
- yasm_value val;
- if (yasm_value_finalize_expr(&val, dv->multiple, prev_bc, 0))
- yasm_error_set(YASM_ERROR_TOO_COMPLEX,
- N_("multiple expression too complex"));
- else if (val.rel)
- yasm_error_set(YASM_ERROR_NOT_ABSOLUTE,
- N_("multiple expression not absolute"));
- dv->multiple = val.abs;
- }
- }
-}
-
-static int
-bc_data_item_size(yasm_bytecode *bc)
-{
- bytecode_data *bc_data = (bytecode_data *)bc->contents;
- return bc_data->item_size;
-}
-
-static int
-bc_data_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
- void *add_span_data)
-{
- bytecode_data *bc_data = (bytecode_data *)bc->contents;
- yasm_dataval *dv;
- yasm_intnum *intn;
- unsigned long len = 0;
- unsigned long multiple;
-
- /* Count up element sizes, rounding up string length. */
- STAILQ_FOREACH(dv, &bc_data->datahead, link) {
- switch (dv->type) {
- case DV_EMPTY:
- len = 0;
- break;
- case DV_VALUE:
- len = dv->data.val.size/8;
- break;
- case DV_RAW:
- len = dv->data.raw.len;
- break;
- case DV_ULEB128:
- case DV_SLEB128:
- intn = yasm_expr_get_intnum(&dv->data.val.abs, 0);
- if (!intn)
- yasm_internal_error(N_("non-constant in data_tobytes"));
- len = yasm_intnum_size_leb128(intn, dv->type == DV_SLEB128);
- break;
- case DV_RESERVE:
- len = dv->data.val.size/8;
- break;
- }
-
- if (!yasm_dv_get_multiple(dv, &multiple))
- len *= multiple;
-
- bc->len += len;
- }
-
- return 0;
-}
-
-static int
-bc_data_tobytes(yasm_bytecode *bc, unsigned char **bufp,
- unsigned char *bufstart, void *d,
- yasm_output_value_func output_value,
- /*@unused@*/ yasm_output_reloc_func output_reloc)
-{
- bytecode_data *bc_data = (bytecode_data *)bc->contents;
- yasm_dataval *dv;
- yasm_intnum *intn;
- unsigned int val_len;
- unsigned long multiple, i;
-
- STAILQ_FOREACH(dv, &bc_data->datahead, link) {
- if (yasm_dv_get_multiple(dv, &multiple) || multiple == 0)
- continue;
- switch (dv->type) {
- case DV_EMPTY:
- break;
- case DV_VALUE:
- val_len = dv->data.val.size/8;
- for (i=0; i<multiple; i++) {
- if (output_value(&dv->data.val, *bufp, val_len,
- (unsigned long)(*bufp-bufstart), bc, 1,
- d))
- return 1;
- *bufp += val_len;
- }
- break;
- case DV_RAW:
- for (i=0; i<multiple; i++) {
- memcpy(*bufp, dv->data.raw.contents, dv->data.raw.len);
- *bufp += dv->data.raw.len;
- }
- break;
- case DV_ULEB128:
- case DV_SLEB128:
- intn = yasm_expr_get_intnum(&dv->data.val.abs, 234);
- if (!intn)
- yasm_internal_error(N_("non-constant in data_tobytes"));
- for (i=0; i<multiple; i++) {
- *bufp +=
- yasm_intnum_get_leb128(intn, *bufp,
- dv->type == DV_SLEB128);
- }
- case DV_RESERVE:
- val_len = dv->data.val.size/8;
- for (i=0; i<multiple; i++) {
- memset(*bufp, 0, val_len);
- *bufp += val_len;
- }
- break;
- }
- }
-
- return 0;
-}
-
-yasm_bytecode *
-yasm_bc_create_data(yasm_datavalhead *datahead, unsigned int size,
- int append_zero, yasm_arch *arch, unsigned long line)
-{
- bytecode_data *data = yasm_xmalloc(sizeof(bytecode_data));
- yasm_bytecode *bc = yasm_bc_create_common(&bc_data_callback, data, line);
- yasm_dataval *dv, *dv2, *dvo;
- yasm_intnum *intn;
- unsigned long len = 0, rlen, i;
-
-
- yasm_dvs_initialize(&data->datahead);
- data->item_size = size;
-
- /* Prescan input data for length, etc. Careful: this needs to be
- * precisely paired with the second loop.
- */
- STAILQ_FOREACH(dv, datahead, link) {
- if (dv->multiple && dv->type != DV_EMPTY && len > 0) {
- /* Flush previous data */
- dvo = yasm_dv_create_raw(yasm_xmalloc(len), len);
- STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
- len = 0;
- }
- switch (dv->type) {
- case DV_EMPTY:
- break;
- case DV_VALUE:
- case DV_ULEB128:
- case DV_SLEB128:
- intn = yasm_expr_get_intnum(&dv->data.val.abs, 0);
- if (intn && dv->type == DV_VALUE && (arch || size == 1))
- len += size;
- else if (intn && dv->type == DV_ULEB128)
- len += yasm_intnum_size_leb128(intn, 0);
- else if (intn && dv->type == DV_SLEB128)
- len += yasm_intnum_size_leb128(intn, 1);
- else {
- if (len > 0) {
- /* Create bytecode for all previous len */
- dvo = yasm_dv_create_raw(yasm_xmalloc(len), len);
- STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
- len = 0;
- }
-
- /* Create bytecode for this value */
- dvo = yasm_xmalloc(sizeof(yasm_dataval));
- STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
- dvo->multiple = dv->multiple;
- }
- break;
- case DV_RAW:
- rlen = dv->data.raw.len;
- /* find count, rounding up to nearest multiple of size */
- rlen = (rlen + size - 1) / size;
- len += rlen*size;
- break;
- case DV_RESERVE:
- len += size;
- break;
- }
-
- if (dv->multiple && dv->type != DV_EMPTY && len > 0) {
- /* Flush this data */
- dvo = yasm_dv_create_raw(yasm_xmalloc(len), len);
- STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
- dvo->multiple = dv->multiple;
- len = 0;
- }
-
- if (append_zero)
- len++;
- }
-
- /* Create final dataval for any trailing length */
- if (len > 0) {
- dvo = yasm_dv_create_raw(yasm_xmalloc(len), len);
- STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
- }
-
- /* Second iteration: copy data and delete input datavals. */
- dv = STAILQ_FIRST(datahead);
- dvo = STAILQ_FIRST(&data->datahead);
- len = 0;
- while (dv && dvo) {
- if (dv->multiple && dv->type != DV_EMPTY && len > 0) {
- dvo = STAILQ_NEXT(dvo, link);
- len = 0;
- }
- switch (dv->type) {
- case DV_EMPTY:
- break;
- case DV_VALUE:
- case DV_ULEB128:
- case DV_SLEB128:
- intn = yasm_expr_get_intnum(&dv->data.val.abs, 0);
- if (intn && dv->type == DV_VALUE && (arch || size == 1)) {
- if (size == 1)
- yasm_intnum_get_sized(intn,
- &dvo->data.raw.contents[len],
- 1, 8, 0, 0, 1);
- else
- yasm_arch_intnum_tobytes(arch, intn,
- &dvo->data.raw.contents[len],
- size, size*8, 0, bc, 1);
- yasm_value_delete(&dv->data.val);
- len += size;
- } else if (intn && dv->type == DV_ULEB128) {
- len += yasm_intnum_get_leb128(intn,
- &dvo->data.raw.contents[len],
- 0);
- yasm_value_delete(&dv->data.val);
- } else if (intn && dv->type == DV_SLEB128) {
- len += yasm_intnum_get_leb128(intn,
- &dvo->data.raw.contents[len],
- 1);
- yasm_value_delete(&dv->data.val);
- } else {
- if (len > 0)
- dvo = STAILQ_NEXT(dvo, link);
- dvo->type = dv->type;
- dvo->data.val = dv->data.val; /* structure copy */
- dvo->data.val.size = size*8; /* remember size */
- dvo = STAILQ_NEXT(dvo, link);
- len = 0;
- }
- break;
- case DV_RAW:
- rlen = dv->data.raw.len;
- memcpy(&dvo->data.raw.contents[len], dv->data.raw.contents,
- rlen);
- yasm_xfree(dv->data.raw.contents);
- len += rlen;
- /* pad with 0's to nearest multiple of size */
- rlen %= size;
- if (rlen > 0) {
- rlen = size-rlen;
- for (i=0; i<rlen; i++)
- dvo->data.raw.contents[len++] = 0;
- }
- break;
- case DV_RESERVE:
- memset(&dvo->data.raw.contents[len], 0, size);
- len += size;
- break;
- }
-
- if (dv->multiple && dv->type != DV_EMPTY && len > 0) {
- dvo = STAILQ_NEXT(dvo, link);
- len = 0;
- }
-
- if (append_zero)
- dvo->data.raw.contents[len++] = 0;
- dv2 = STAILQ_NEXT(dv, link);
- yasm_xfree(dv);
- dv = dv2;
- }
-
- return bc;
-}
-
-yasm_bytecode *
-yasm_bc_create_leb128(yasm_datavalhead *datahead, int sign, unsigned long line)
-{
- yasm_dataval *dv;
-
- /* Convert all values into LEB type, error on strings/raws */
- STAILQ_FOREACH(dv, datahead, link) {
- switch (dv->type) {
- case DV_VALUE:
- dv->type = sign ? DV_SLEB128 : DV_ULEB128;
- break;
- case DV_RAW:
- yasm_error_set(YASM_ERROR_VALUE,
- N_("LEB128 does not allow string constants"));
- break;
- default:
- break;
- }
- }
-
- return yasm_bc_create_data(datahead, 0, 0, 0, line);
-}
-
-yasm_dataval *
-yasm_dv_create_expr(yasm_expr *e)
-{
- yasm_dataval *retval = yasm_xmalloc(sizeof(yasm_dataval));
-
- retval->type = DV_VALUE;
- yasm_value_initialize(&retval->data.val, e, 0);
- retval->multiple = NULL;
-
- return retval;
-}
-
-yasm_dataval *
-yasm_dv_create_raw(unsigned char *contents, unsigned long len)
-{
- yasm_dataval *retval = yasm_xmalloc(sizeof(yasm_dataval));
-
- retval->type = DV_RAW;
- retval->data.raw.contents = contents;
- retval->data.raw.len = len;
- retval->multiple = NULL;
-
- return retval;
-}
-
-yasm_dataval *
-yasm_dv_create_reserve(void)
-{
- yasm_dataval *retval = yasm_xmalloc(sizeof(yasm_dataval));
-
- retval->type = DV_RESERVE;
- retval->multiple = NULL;
-
- return retval;
-}
-
-yasm_value *
-yasm_dv_get_value(yasm_dataval *dv)
-{
- if (dv->type != DV_VALUE)
- return NULL;
- return &dv->data.val;
-}
-
-void
-yasm_dv_set_multiple(yasm_dataval *dv, yasm_expr *e)
-{
- if (dv->multiple)
- dv->multiple = yasm_expr_create_tree( dv->multiple, YASM_EXPR_MUL, e,
- e->line);
- else
- dv->multiple = e;
-}
-
-int
-yasm_dv_get_multiple(yasm_dataval *dv, unsigned long *multiple)
-{
- /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
-
- *multiple = 1;
- if (dv->multiple) {
- num = yasm_expr_get_intnum(&dv->multiple, 0);
- if (!num) {
- yasm_error_set(YASM_ERROR_VALUE,
- N_("could not determine multiple"));
- return 1;
- }
- if (yasm_intnum_sign(num) < 0) {
- yasm_error_set(YASM_ERROR_VALUE, N_("multiple is negative"));
- return 1;
- }
- *multiple = yasm_intnum_get_uint(num);
- }
- return 0;
-}
-
-void
-yasm_dvs_delete(yasm_datavalhead *headp)
-{
- yasm_dataval *cur, *next;
-
- cur = STAILQ_FIRST(headp);
- while (cur) {
- next = STAILQ_NEXT(cur, link);
- switch (cur->type) {
- case DV_VALUE:
- yasm_value_delete(&cur->data.val);
- break;
- case DV_RAW:
- yasm_xfree(cur->data.raw.contents);
- break;
- default:
- break;
- }
- if (cur->multiple)
- yasm_expr_destroy(cur->multiple);
- yasm_xfree(cur);
- cur = next;
- }
- STAILQ_INIT(headp);
-}
-
-yasm_dataval *
-yasm_dvs_append(yasm_datavalhead *headp, yasm_dataval *dv)
-{
- if (dv) {
- STAILQ_INSERT_TAIL(headp, dv, link);
- return dv;
- }
- return (yasm_dataval *)NULL;
-}
-
-void
-yasm_dvs_print(const yasm_datavalhead *head, FILE *f, int indent_level)
-{
- yasm_dataval *cur;
- unsigned long i;
-
- STAILQ_FOREACH(cur, head, link) {
- fprintf(f, "%*sMultiple=", indent_level, "");
- if (!cur->multiple)
- fprintf(f, "nil (1)");
- else
- yasm_expr_print(cur->multiple, f);
- switch (cur->type) {
- case DV_EMPTY:
- fprintf(f, "%*sEmpty\n", indent_level, "");
- break;
- case DV_VALUE:
- fprintf(f, "%*sValue:\n", indent_level, "");
- yasm_value_print(&cur->data.val, f, indent_level+1);
- break;
- case DV_RAW:
- fprintf(f, "%*sLength=%lu\n", indent_level, "",
- cur->data.raw.len);
- fprintf(f, "%*sBytes=[", indent_level, "");
- for (i=0; i<cur->data.raw.len; i++)
- fprintf(f, "0x%02x, ", cur->data.raw.contents[i]);
- fprintf(f, "]\n");
- break;
- case DV_ULEB128:
- fprintf(f, "%*sULEB128 value:\n", indent_level, "");
- yasm_value_print(&cur->data.val, f, indent_level+1);
- break;
- case DV_SLEB128:
- fprintf(f, "%*sSLEB128 value:\n", indent_level, "");
- yasm_value_print(&cur->data.val, f, indent_level+1);
- break;
- case DV_RESERVE:
- fprintf(f, "%*sReserved\n", indent_level, "");
- break;
- }
- }
-}
+/*
+ * Data (and LEB128) bytecode
+ *
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "util.h"
+
+#include "libyasm-stdint.h"
+#include "coretype.h"
+
+#include "errwarn.h"
+#include "intnum.h"
+#include "expr.h"
+#include "value.h"
+
+#include "bytecode.h"
+#include "arch.h"
+
+
+struct yasm_dataval {
+ /*@reldef@*/ STAILQ_ENTRY(yasm_dataval) link;
+
+ enum { DV_EMPTY, DV_VALUE, DV_RAW, DV_ULEB128, DV_SLEB128, DV_RESERVE }
+ type;
+
+ union {
+ yasm_value val;
+ struct {
+ /*@only@*/ unsigned char *contents;
+ unsigned long len;
+ } raw;
+ } data;
+
+ /* number of times data is repeated, NULL=1. */
+ /*@only@*/ /*@null@*/ yasm_expr *multiple;
+};
+
+typedef struct bytecode_data {
+ /* converted data (linked list) */
+ yasm_datavalhead datahead;
+
+ int item_size;
+} bytecode_data;
+
+static void bc_data_destroy(void *contents);
+static void bc_data_print(const void *contents, FILE *f, int indent_level);
+static void bc_data_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
+static int bc_data_item_size(yasm_bytecode *bc);
+static int bc_data_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data);
+static int bc_data_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+static const yasm_bytecode_callback bc_data_callback = {
+ bc_data_destroy,
+ bc_data_print,
+ bc_data_finalize,
+ bc_data_item_size,
+ bc_data_calc_len,
+ yasm_bc_expand_common,
+ bc_data_tobytes,
+ 0
+};
+
+
+static void
+bc_data_destroy(void *contents)
+{
+ bytecode_data *bc_data = (bytecode_data *)contents;
+ yasm_dvs_delete(&bc_data->datahead);
+ yasm_xfree(contents);
+}
+
+static void
+bc_data_print(const void *contents, FILE *f, int indent_level)
+{
+ const bytecode_data *bc_data = (const bytecode_data *)contents;
+ fprintf(f, "%*s_Data_\n", indent_level, "");
+ fprintf(f, "%*sElements:\n", indent_level+1, "");
+ yasm_dvs_print(&bc_data->datahead, f, indent_level+2);
+}
+
+static void
+bc_data_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
+{
+ bytecode_data *bc_data = (bytecode_data *)bc->contents;
+ yasm_dataval *dv;
+ yasm_intnum *intn;
+
+ /* Convert values from simple expr to value. */
+ STAILQ_FOREACH(dv, &bc_data->datahead, link) {
+ switch (dv->type) {
+ case DV_VALUE:
+ if (yasm_value_finalize(&dv->data.val, prev_bc)) {
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("data expression too complex"));
+ return;
+ }
+ break;
+ case DV_ULEB128:
+ case DV_SLEB128:
+ intn = yasm_expr_get_intnum(&dv->data.val.abs, 0);
+ if (!intn) {
+ yasm_error_set(YASM_ERROR_NOT_CONSTANT,
+ N_("LEB128 requires constant values"));
+ return;
+ }
+ /* Warn for negative values in unsigned environment.
+ * This could be an error instead: the likelihood this is
+ * desired is very low!
+ */
+ if (yasm_intnum_sign(intn) == -1 && dv->type == DV_ULEB128)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("negative value in unsigned LEB128"));
+ break;
+ default:
+ break;
+ }
+ if (dv->multiple) {
+ yasm_value val;
+ if (yasm_value_finalize_expr(&val, dv->multiple, prev_bc, 0))
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("multiple expression too complex"));
+ else if (val.rel)
+ yasm_error_set(YASM_ERROR_NOT_ABSOLUTE,
+ N_("multiple expression not absolute"));
+ dv->multiple = val.abs;
+ }
+ }
+}
+
+static int
+bc_data_item_size(yasm_bytecode *bc)
+{
+ bytecode_data *bc_data = (bytecode_data *)bc->contents;
+ return bc_data->item_size;
+}
+
+static int
+bc_data_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ bytecode_data *bc_data = (bytecode_data *)bc->contents;
+ yasm_dataval *dv;
+ yasm_intnum *intn;
+ unsigned long len = 0;
+ unsigned long multiple;
+
+ /* Count up element sizes, rounding up string length. */
+ STAILQ_FOREACH(dv, &bc_data->datahead, link) {
+ switch (dv->type) {
+ case DV_EMPTY:
+ len = 0;
+ break;
+ case DV_VALUE:
+ len = dv->data.val.size/8;
+ break;
+ case DV_RAW:
+ len = dv->data.raw.len;
+ break;
+ case DV_ULEB128:
+ case DV_SLEB128:
+ intn = yasm_expr_get_intnum(&dv->data.val.abs, 0);
+ if (!intn)
+ yasm_internal_error(N_("non-constant in data_tobytes"));
+ len = yasm_intnum_size_leb128(intn, dv->type == DV_SLEB128);
+ break;
+ case DV_RESERVE:
+ len = dv->data.val.size/8;
+ break;
+ }
+
+ if (!yasm_dv_get_multiple(dv, &multiple))
+ len *= multiple;
+
+ bc->len += len;
+ }
+
+ return 0;
+}
+
+static int
+bc_data_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@unused@*/ yasm_output_reloc_func output_reloc)
+{
+ bytecode_data *bc_data = (bytecode_data *)bc->contents;
+ yasm_dataval *dv;
+ yasm_intnum *intn;
+ unsigned int val_len;
+ unsigned long multiple, i;
+
+ STAILQ_FOREACH(dv, &bc_data->datahead, link) {
+ if (yasm_dv_get_multiple(dv, &multiple) || multiple == 0)
+ continue;
+ switch (dv->type) {
+ case DV_EMPTY:
+ break;
+ case DV_VALUE:
+ val_len = dv->data.val.size/8;
+ for (i=0; i<multiple; i++) {
+ if (output_value(&dv->data.val, *bufp, val_len,
+ (unsigned long)(*bufp-bufstart), bc, 1,
+ d))
+ return 1;
+ *bufp += val_len;
+ }
+ break;
+ case DV_RAW:
+ for (i=0; i<multiple; i++) {
+ memcpy(*bufp, dv->data.raw.contents, dv->data.raw.len);
+ *bufp += dv->data.raw.len;
+ }
+ break;
+ case DV_ULEB128:
+ case DV_SLEB128:
+ intn = yasm_expr_get_intnum(&dv->data.val.abs, 234);
+ if (!intn)
+ yasm_internal_error(N_("non-constant in data_tobytes"));
+ for (i=0; i<multiple; i++) {
+ *bufp +=
+ yasm_intnum_get_leb128(intn, *bufp,
+ dv->type == DV_SLEB128);
+ }
+ case DV_RESERVE:
+ val_len = dv->data.val.size/8;
+ for (i=0; i<multiple; i++) {
+ memset(*bufp, 0, val_len);
+ *bufp += val_len;
+ }
+ break;
+ }
+ }
+
+ return 0;
+}
+
+yasm_bytecode *
+yasm_bc_create_data(yasm_datavalhead *datahead, unsigned int size,
+ int append_zero, yasm_arch *arch, unsigned long line)
+{
+ bytecode_data *data = yasm_xmalloc(sizeof(bytecode_data));
+ yasm_bytecode *bc = yasm_bc_create_common(&bc_data_callback, data, line);
+ yasm_dataval *dv, *dv2, *dvo;
+ yasm_intnum *intn;
+ unsigned long len = 0, rlen, i;
+
+
+ yasm_dvs_initialize(&data->datahead);
+ data->item_size = size;
+
+ /* Prescan input data for length, etc. Careful: this needs to be
+ * precisely paired with the second loop.
+ */
+ STAILQ_FOREACH(dv, datahead, link) {
+ if (dv->multiple && dv->type != DV_EMPTY && len > 0) {
+ /* Flush previous data */
+ dvo = yasm_dv_create_raw(yasm_xmalloc(len), len);
+ STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
+ len = 0;
+ }
+ switch (dv->type) {
+ case DV_EMPTY:
+ break;
+ case DV_VALUE:
+ case DV_ULEB128:
+ case DV_SLEB128:
+ intn = yasm_expr_get_intnum(&dv->data.val.abs, 0);
+ if (intn && dv->type == DV_VALUE && (arch || size == 1))
+ len += size;
+ else if (intn && dv->type == DV_ULEB128)
+ len += yasm_intnum_size_leb128(intn, 0);
+ else if (intn && dv->type == DV_SLEB128)
+ len += yasm_intnum_size_leb128(intn, 1);
+ else {
+ if (len > 0) {
+ /* Create bytecode for all previous len */
+ dvo = yasm_dv_create_raw(yasm_xmalloc(len), len);
+ STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
+ len = 0;
+ }
+
+ /* Create bytecode for this value */
+ dvo = yasm_xmalloc(sizeof(yasm_dataval));
+ STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
+ dvo->multiple = dv->multiple;
+ }
+ break;
+ case DV_RAW:
+ rlen = dv->data.raw.len;
+ /* find count, rounding up to nearest multiple of size */
+ rlen = (rlen + size - 1) / size;
+ len += rlen*size;
+ break;
+ case DV_RESERVE:
+ len += size;
+ break;
+ }
+
+ if (dv->multiple && dv->type != DV_EMPTY && len > 0) {
+ /* Flush this data */
+ dvo = yasm_dv_create_raw(yasm_xmalloc(len), len);
+ STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
+ dvo->multiple = dv->multiple;
+ len = 0;
+ }
+
+ if (append_zero)
+ len++;
+ }
+
+ /* Create final dataval for any trailing length */
+ if (len > 0) {
+ dvo = yasm_dv_create_raw(yasm_xmalloc(len), len);
+ STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
+ }
+
+ /* Second iteration: copy data and delete input datavals. */
+ dv = STAILQ_FIRST(datahead);
+ dvo = STAILQ_FIRST(&data->datahead);
+ len = 0;
+ while (dv && dvo) {
+ if (dv->multiple && dv->type != DV_EMPTY && len > 0) {
+ dvo = STAILQ_NEXT(dvo, link);
+ len = 0;
+ }
+ switch (dv->type) {
+ case DV_EMPTY:
+ break;
+ case DV_VALUE:
+ case DV_ULEB128:
+ case DV_SLEB128:
+ intn = yasm_expr_get_intnum(&dv->data.val.abs, 0);
+ if (intn && dv->type == DV_VALUE && (arch || size == 1)) {
+ if (size == 1)
+ yasm_intnum_get_sized(intn,
+ &dvo->data.raw.contents[len],
+ 1, 8, 0, 0, 1);
+ else
+ yasm_arch_intnum_tobytes(arch, intn,
+ &dvo->data.raw.contents[len],
+ size, size*8, 0, bc, 1);
+ yasm_value_delete(&dv->data.val);
+ len += size;
+ } else if (intn && dv->type == DV_ULEB128) {
+ len += yasm_intnum_get_leb128(intn,
+ &dvo->data.raw.contents[len],
+ 0);
+ yasm_value_delete(&dv->data.val);
+ } else if (intn && dv->type == DV_SLEB128) {
+ len += yasm_intnum_get_leb128(intn,
+ &dvo->data.raw.contents[len],
+ 1);
+ yasm_value_delete(&dv->data.val);
+ } else {
+ if (len > 0)
+ dvo = STAILQ_NEXT(dvo, link);
+ dvo->type = dv->type;
+ dvo->data.val = dv->data.val; /* structure copy */
+ dvo->data.val.size = size*8; /* remember size */
+ dvo = STAILQ_NEXT(dvo, link);
+ len = 0;
+ }
+ break;
+ case DV_RAW:
+ rlen = dv->data.raw.len;
+ memcpy(&dvo->data.raw.contents[len], dv->data.raw.contents,
+ rlen);
+ yasm_xfree(dv->data.raw.contents);
+ len += rlen;
+ /* pad with 0's to nearest multiple of size */
+ rlen %= size;
+ if (rlen > 0) {
+ rlen = size-rlen;
+ for (i=0; i<rlen; i++)
+ dvo->data.raw.contents[len++] = 0;
+ }
+ break;
+ case DV_RESERVE:
+ memset(&dvo->data.raw.contents[len], 0, size);
+ len += size;
+ break;
+ }
+
+ if (dv->multiple && dv->type != DV_EMPTY && len > 0) {
+ dvo = STAILQ_NEXT(dvo, link);
+ len = 0;
+ }
+
+ if (append_zero)
+ dvo->data.raw.contents[len++] = 0;
+ dv2 = STAILQ_NEXT(dv, link);
+ yasm_xfree(dv);
+ dv = dv2;
+ }
+
+ return bc;
+}
+
+yasm_bytecode *
+yasm_bc_create_leb128(yasm_datavalhead *datahead, int sign, unsigned long line)
+{
+ yasm_dataval *dv;
+
+ /* Convert all values into LEB type, error on strings/raws */
+ STAILQ_FOREACH(dv, datahead, link) {
+ switch (dv->type) {
+ case DV_VALUE:
+ dv->type = sign ? DV_SLEB128 : DV_ULEB128;
+ break;
+ case DV_RAW:
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("LEB128 does not allow string constants"));
+ break;
+ default:
+ break;
+ }
+ }
+
+ return yasm_bc_create_data(datahead, 0, 0, 0, line);
+}
+
+yasm_dataval *
+yasm_dv_create_expr(yasm_expr *e)
+{
+ yasm_dataval *retval = yasm_xmalloc(sizeof(yasm_dataval));
+
+ retval->type = DV_VALUE;
+ yasm_value_initialize(&retval->data.val, e, 0);
+ retval->multiple = NULL;
+
+ return retval;
+}
+
+yasm_dataval *
+yasm_dv_create_raw(unsigned char *contents, unsigned long len)
+{
+ yasm_dataval *retval = yasm_xmalloc(sizeof(yasm_dataval));
+
+ retval->type = DV_RAW;
+ retval->data.raw.contents = contents;
+ retval->data.raw.len = len;
+ retval->multiple = NULL;
+
+ return retval;
+}
+
+yasm_dataval *
+yasm_dv_create_reserve(void)
+{
+ yasm_dataval *retval = yasm_xmalloc(sizeof(yasm_dataval));
+
+ retval->type = DV_RESERVE;
+ retval->multiple = NULL;
+
+ return retval;
+}
+
+yasm_value *
+yasm_dv_get_value(yasm_dataval *dv)
+{
+ if (dv->type != DV_VALUE)
+ return NULL;
+ return &dv->data.val;
+}
+
+void
+yasm_dv_set_multiple(yasm_dataval *dv, yasm_expr *e)
+{
+ if (dv->multiple)
+ dv->multiple = yasm_expr_create_tree( dv->multiple, YASM_EXPR_MUL, e,
+ e->line);
+ else
+ dv->multiple = e;
+}
+
+int
+yasm_dv_get_multiple(yasm_dataval *dv, unsigned long *multiple)
+{
+ /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
+
+ *multiple = 1;
+ if (dv->multiple) {
+ num = yasm_expr_get_intnum(&dv->multiple, 0);
+ if (!num) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("could not determine multiple"));
+ return 1;
+ }
+ if (yasm_intnum_sign(num) < 0) {
+ yasm_error_set(YASM_ERROR_VALUE, N_("multiple is negative"));
+ return 1;
+ }
+ *multiple = yasm_intnum_get_uint(num);
+ }
+ return 0;
+}
+
+void
+yasm_dvs_delete(yasm_datavalhead *headp)
+{
+ yasm_dataval *cur, *next;
+
+ cur = STAILQ_FIRST(headp);
+ while (cur) {
+ next = STAILQ_NEXT(cur, link);
+ switch (cur->type) {
+ case DV_VALUE:
+ yasm_value_delete(&cur->data.val);
+ break;
+ case DV_RAW:
+ yasm_xfree(cur->data.raw.contents);
+ break;
+ default:
+ break;
+ }
+ if (cur->multiple)
+ yasm_expr_destroy(cur->multiple);
+ yasm_xfree(cur);
+ cur = next;
+ }
+ STAILQ_INIT(headp);
+}
+
+yasm_dataval *
+yasm_dvs_append(yasm_datavalhead *headp, yasm_dataval *dv)
+{
+ if (dv) {
+ STAILQ_INSERT_TAIL(headp, dv, link);
+ return dv;
+ }
+ return (yasm_dataval *)NULL;
+}
+
+void
+yasm_dvs_print(const yasm_datavalhead *head, FILE *f, int indent_level)
+{
+ yasm_dataval *cur;
+ unsigned long i;
+
+ STAILQ_FOREACH(cur, head, link) {
+ fprintf(f, "%*sMultiple=", indent_level, "");
+ if (!cur->multiple)
+ fprintf(f, "nil (1)");
+ else
+ yasm_expr_print(cur->multiple, f);
+ switch (cur->type) {
+ case DV_EMPTY:
+ fprintf(f, "%*sEmpty\n", indent_level, "");
+ break;
+ case DV_VALUE:
+ fprintf(f, "%*sValue:\n", indent_level, "");
+ yasm_value_print(&cur->data.val, f, indent_level+1);
+ break;
+ case DV_RAW:
+ fprintf(f, "%*sLength=%lu\n", indent_level, "",
+ cur->data.raw.len);
+ fprintf(f, "%*sBytes=[", indent_level, "");
+ for (i=0; i<cur->data.raw.len; i++)
+ fprintf(f, "0x%02x, ", cur->data.raw.contents[i]);
+ fprintf(f, "]\n");
+ break;
+ case DV_ULEB128:
+ fprintf(f, "%*sULEB128 value:\n", indent_level, "");
+ yasm_value_print(&cur->data.val, f, indent_level+1);
+ break;
+ case DV_SLEB128:
+ fprintf(f, "%*sSLEB128 value:\n", indent_level, "");
+ yasm_value_print(&cur->data.val, f, indent_level+1);
+ break;
+ case DV_RESERVE:
+ fprintf(f, "%*sReserved\n", indent_level, "");
+ break;
+ }
+ }
+}
diff --git a/contrib/tools/yasm/libyasm/bc-incbin.c b/contrib/tools/yasm/libyasm/bc-incbin.c
index a8fec7d6ce..efa098dad7 100644
--- a/contrib/tools/yasm/libyasm/bc-incbin.c
+++ b/contrib/tools/yasm/libyasm/bc-incbin.c
@@ -1,265 +1,265 @@
-/*
- * Incbin bytecode
- *
- * Copyright (C) 2001-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#include "util.h"
-
-#include "libyasm-stdint.h"
-#include "coretype.h"
-
-#include "linemap.h"
-
-#include "errwarn.h"
-#include "intnum.h"
-#include "expr.h"
-#include "value.h"
-
-#include "bytecode.h"
-
-#include "file.h"
-
-
-typedef struct bytecode_incbin {
- /*@only@*/ char *filename; /* file to include data from */
- const char *from; /* filename of what contained incbin */
-
- /* starting offset to read from (NULL=0) */
- /*@only@*/ /*@null@*/ yasm_expr *start;
-
- /* maximum number of bytes to read (NULL=no limit) */
- /*@only@*/ /*@null@*/ yasm_expr *maxlen;
-} bytecode_incbin;
-
-static void bc_incbin_destroy(void *contents);
-static void bc_incbin_print(const void *contents, FILE *f, int indent_level);
-static void bc_incbin_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
-static int bc_incbin_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
- void *add_span_data);
-static int bc_incbin_tobytes(yasm_bytecode *bc, unsigned char **bufp,
- unsigned char *bufstart, void *d,
- yasm_output_value_func output_value,
- /*@null@*/ yasm_output_reloc_func output_reloc);
-
-static const yasm_bytecode_callback bc_incbin_callback = {
- bc_incbin_destroy,
- bc_incbin_print,
- bc_incbin_finalize,
- NULL,
- bc_incbin_calc_len,
- yasm_bc_expand_common,
- bc_incbin_tobytes,
- 0
-};
-
-
-static void
-bc_incbin_destroy(void *contents)
-{
- bytecode_incbin *incbin = (bytecode_incbin *)contents;
- yasm_xfree(incbin->filename);
- yasm_expr_destroy(incbin->start);
- yasm_expr_destroy(incbin->maxlen);
- yasm_xfree(contents);
-}
-
-static void
-bc_incbin_print(const void *contents, FILE *f, int indent_level)
-{
- const bytecode_incbin *incbin = (const bytecode_incbin *)contents;
- fprintf(f, "%*s_IncBin_\n", indent_level, "");
- fprintf(f, "%*sFilename=`%s'\n", indent_level, "",
- incbin->filename);
- fprintf(f, "%*sStart=", indent_level, "");
- if (!incbin->start)
- fprintf(f, "nil (0)");
- else
- yasm_expr_print(incbin->start, f);
- fprintf(f, "%*sMax Len=", indent_level, "");
- if (!incbin->maxlen)
- fprintf(f, "nil (unlimited)");
- else
- yasm_expr_print(incbin->maxlen, f);
- fprintf(f, "\n");
-}
-
-static void
-bc_incbin_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
-{
- bytecode_incbin *incbin = (bytecode_incbin *)bc->contents;
- yasm_value val;
-
- if (yasm_value_finalize_expr(&val, incbin->start, prev_bc, 0))
- yasm_error_set(YASM_ERROR_TOO_COMPLEX,
- N_("start expression too complex"));
- else if (val.rel)
- yasm_error_set(YASM_ERROR_NOT_ABSOLUTE,
- N_("start expression not absolute"));
- incbin->start = val.abs;
-
- if (yasm_value_finalize_expr(&val, incbin->maxlen, prev_bc, 0))
- yasm_error_set(YASM_ERROR_TOO_COMPLEX,
- N_("maximum length expression too complex"));
- else if (val.rel)
- yasm_error_set(YASM_ERROR_NOT_ABSOLUTE,
- N_("maximum length expression not absolute"));
- incbin->maxlen = val.abs;
-}
-
-static int
-bc_incbin_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
- void *add_span_data)
-{
- bytecode_incbin *incbin = (bytecode_incbin *)bc->contents;
- FILE *f;
- /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
- unsigned long start = 0, maxlen = 0xFFFFFFFFUL, flen;
-
- /* Try to convert start to integer value */
- if (incbin->start) {
- num = yasm_expr_get_intnum(&incbin->start, 0);
- if (num)
- start = yasm_intnum_get_uint(num);
- if (!num) {
- /* FIXME */
- yasm_error_set(YASM_ERROR_NOT_IMPLEMENTED,
- N_("incbin does not yet understand non-constant"));
- return -1;
- }
- }
-
- /* Try to convert maxlen to integer value */
- if (incbin->maxlen) {
- num = yasm_expr_get_intnum(&incbin->maxlen, 0);
- if (num)
- maxlen = yasm_intnum_get_uint(num);
- if (!num) {
- /* FIXME */
- yasm_error_set(YASM_ERROR_NOT_IMPLEMENTED,
- N_("incbin does not yet understand non-constant"));
- return -1;
- }
- }
-
- /* Open file and determine its length */
- f = yasm_fopen_include(incbin->filename, incbin->from, "rb", NULL);
- if (!f) {
- yasm_error_set(YASM_ERROR_IO,
- N_("`incbin': unable to open file `%s'"),
- incbin->filename);
- return -1;
- }
- if (fseek(f, 0L, SEEK_END) < 0) {
- yasm_error_set(YASM_ERROR_IO,
- N_("`incbin': unable to seek on file `%s'"),
- incbin->filename);
- return -1;
- }
- flen = (unsigned long)ftell(f);
- fclose(f);
-
- /* Compute length of incbin from start, maxlen, and len */
- if (start > flen) {
- yasm_warn_set(YASM_WARN_GENERAL,
- N_("`incbin': start past end of file `%s'"),
- incbin->filename);
- start = flen;
- }
- flen -= start;
- if (incbin->maxlen)
- if (maxlen < flen)
- flen = maxlen;
- bc->len += flen;
- return 0;
-}
-
-static int
-bc_incbin_tobytes(yasm_bytecode *bc, unsigned char **bufp,
- unsigned char *bufstart, void *d,
- yasm_output_value_func output_value,
- /*@unused@*/ yasm_output_reloc_func output_reloc)
-{
- bytecode_incbin *incbin = (bytecode_incbin *)bc->contents;
- FILE *f;
- /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
- unsigned long start = 0;
-
- /* Convert start to integer value */
- if (incbin->start) {
- num = yasm_expr_get_intnum(&incbin->start, 0);
- if (!num)
- yasm_internal_error(
- N_("could not determine start in bc_tobytes_incbin"));
- start = yasm_intnum_get_uint(num);
- }
-
- /* Open file */
- f = yasm_fopen_include(incbin->filename, incbin->from, "rb", NULL);
- if (!f) {
- yasm_error_set(YASM_ERROR_IO, N_("`incbin': unable to open file `%s'"),
- incbin->filename);
- return 1;
- }
-
- /* Seek to start of data */
- if (fseek(f, (long)start, SEEK_SET) < 0) {
- yasm_error_set(YASM_ERROR_IO,
- N_("`incbin': unable to seek on file `%s'"),
- incbin->filename);
- fclose(f);
- return 1;
- }
-
- /* Read len bytes */
- if (fread(*bufp, 1, (size_t)bc->len, f) < (size_t)bc->len) {
- yasm_error_set(YASM_ERROR_IO,
- N_("`incbin': unable to read %lu bytes from file `%s'"),
- bc->len, incbin->filename);
- fclose(f);
- return 1;
- }
-
- *bufp += bc->len;
- fclose(f);
- return 0;
-}
-
-yasm_bytecode *
-yasm_bc_create_incbin(char *filename, yasm_expr *start, yasm_expr *maxlen,
- yasm_linemap *linemap, unsigned long line)
-{
- bytecode_incbin *incbin = yasm_xmalloc(sizeof(bytecode_incbin));
- unsigned long xline;
-
- /* Find from filename based on line number */
- yasm_linemap_lookup(linemap, line, &incbin->from, &xline);
-
- /*@-mustfree@*/
- incbin->filename = filename;
- incbin->start = start;
- incbin->maxlen = maxlen;
- /*@=mustfree@*/
-
- return yasm_bc_create_common(&bc_incbin_callback, incbin, line);
-}
+/*
+ * Incbin bytecode
+ *
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "util.h"
+
+#include "libyasm-stdint.h"
+#include "coretype.h"
+
+#include "linemap.h"
+
+#include "errwarn.h"
+#include "intnum.h"
+#include "expr.h"
+#include "value.h"
+
+#include "bytecode.h"
+
+#include "file.h"
+
+
+typedef struct bytecode_incbin {
+ /*@only@*/ char *filename; /* file to include data from */
+ const char *from; /* filename of what contained incbin */
+
+ /* starting offset to read from (NULL=0) */
+ /*@only@*/ /*@null@*/ yasm_expr *start;
+
+ /* maximum number of bytes to read (NULL=no limit) */
+ /*@only@*/ /*@null@*/ yasm_expr *maxlen;
+} bytecode_incbin;
+
+static void bc_incbin_destroy(void *contents);
+static void bc_incbin_print(const void *contents, FILE *f, int indent_level);
+static void bc_incbin_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
+static int bc_incbin_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data);
+static int bc_incbin_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+static const yasm_bytecode_callback bc_incbin_callback = {
+ bc_incbin_destroy,
+ bc_incbin_print,
+ bc_incbin_finalize,
+ NULL,
+ bc_incbin_calc_len,
+ yasm_bc_expand_common,
+ bc_incbin_tobytes,
+ 0
+};
+
+
+static void
+bc_incbin_destroy(void *contents)
+{
+ bytecode_incbin *incbin = (bytecode_incbin *)contents;
+ yasm_xfree(incbin->filename);
+ yasm_expr_destroy(incbin->start);
+ yasm_expr_destroy(incbin->maxlen);
+ yasm_xfree(contents);
+}
+
+static void
+bc_incbin_print(const void *contents, FILE *f, int indent_level)
+{
+ const bytecode_incbin *incbin = (const bytecode_incbin *)contents;
+ fprintf(f, "%*s_IncBin_\n", indent_level, "");
+ fprintf(f, "%*sFilename=`%s'\n", indent_level, "",
+ incbin->filename);
+ fprintf(f, "%*sStart=", indent_level, "");
+ if (!incbin->start)
+ fprintf(f, "nil (0)");
+ else
+ yasm_expr_print(incbin->start, f);
+ fprintf(f, "%*sMax Len=", indent_level, "");
+ if (!incbin->maxlen)
+ fprintf(f, "nil (unlimited)");
+ else
+ yasm_expr_print(incbin->maxlen, f);
+ fprintf(f, "\n");
+}
+
+static void
+bc_incbin_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
+{
+ bytecode_incbin *incbin = (bytecode_incbin *)bc->contents;
+ yasm_value val;
+
+ if (yasm_value_finalize_expr(&val, incbin->start, prev_bc, 0))
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("start expression too complex"));
+ else if (val.rel)
+ yasm_error_set(YASM_ERROR_NOT_ABSOLUTE,
+ N_("start expression not absolute"));
+ incbin->start = val.abs;
+
+ if (yasm_value_finalize_expr(&val, incbin->maxlen, prev_bc, 0))
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("maximum length expression too complex"));
+ else if (val.rel)
+ yasm_error_set(YASM_ERROR_NOT_ABSOLUTE,
+ N_("maximum length expression not absolute"));
+ incbin->maxlen = val.abs;
+}
+
+static int
+bc_incbin_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ bytecode_incbin *incbin = (bytecode_incbin *)bc->contents;
+ FILE *f;
+ /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
+ unsigned long start = 0, maxlen = 0xFFFFFFFFUL, flen;
+
+ /* Try to convert start to integer value */
+ if (incbin->start) {
+ num = yasm_expr_get_intnum(&incbin->start, 0);
+ if (num)
+ start = yasm_intnum_get_uint(num);
+ if (!num) {
+ /* FIXME */
+ yasm_error_set(YASM_ERROR_NOT_IMPLEMENTED,
+ N_("incbin does not yet understand non-constant"));
+ return -1;
+ }
+ }
+
+ /* Try to convert maxlen to integer value */
+ if (incbin->maxlen) {
+ num = yasm_expr_get_intnum(&incbin->maxlen, 0);
+ if (num)
+ maxlen = yasm_intnum_get_uint(num);
+ if (!num) {
+ /* FIXME */
+ yasm_error_set(YASM_ERROR_NOT_IMPLEMENTED,
+ N_("incbin does not yet understand non-constant"));
+ return -1;
+ }
+ }
+
+ /* Open file and determine its length */
+ f = yasm_fopen_include(incbin->filename, incbin->from, "rb", NULL);
+ if (!f) {
+ yasm_error_set(YASM_ERROR_IO,
+ N_("`incbin': unable to open file `%s'"),
+ incbin->filename);
+ return -1;
+ }
+ if (fseek(f, 0L, SEEK_END) < 0) {
+ yasm_error_set(YASM_ERROR_IO,
+ N_("`incbin': unable to seek on file `%s'"),
+ incbin->filename);
+ return -1;
+ }
+ flen = (unsigned long)ftell(f);
+ fclose(f);
+
+ /* Compute length of incbin from start, maxlen, and len */
+ if (start > flen) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("`incbin': start past end of file `%s'"),
+ incbin->filename);
+ start = flen;
+ }
+ flen -= start;
+ if (incbin->maxlen)
+ if (maxlen < flen)
+ flen = maxlen;
+ bc->len += flen;
+ return 0;
+}
+
+static int
+bc_incbin_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@unused@*/ yasm_output_reloc_func output_reloc)
+{
+ bytecode_incbin *incbin = (bytecode_incbin *)bc->contents;
+ FILE *f;
+ /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
+ unsigned long start = 0;
+
+ /* Convert start to integer value */
+ if (incbin->start) {
+ num = yasm_expr_get_intnum(&incbin->start, 0);
+ if (!num)
+ yasm_internal_error(
+ N_("could not determine start in bc_tobytes_incbin"));
+ start = yasm_intnum_get_uint(num);
+ }
+
+ /* Open file */
+ f = yasm_fopen_include(incbin->filename, incbin->from, "rb", NULL);
+ if (!f) {
+ yasm_error_set(YASM_ERROR_IO, N_("`incbin': unable to open file `%s'"),
+ incbin->filename);
+ return 1;
+ }
+
+ /* Seek to start of data */
+ if (fseek(f, (long)start, SEEK_SET) < 0) {
+ yasm_error_set(YASM_ERROR_IO,
+ N_("`incbin': unable to seek on file `%s'"),
+ incbin->filename);
+ fclose(f);
+ return 1;
+ }
+
+ /* Read len bytes */
+ if (fread(*bufp, 1, (size_t)bc->len, f) < (size_t)bc->len) {
+ yasm_error_set(YASM_ERROR_IO,
+ N_("`incbin': unable to read %lu bytes from file `%s'"),
+ bc->len, incbin->filename);
+ fclose(f);
+ return 1;
+ }
+
+ *bufp += bc->len;
+ fclose(f);
+ return 0;
+}
+
+yasm_bytecode *
+yasm_bc_create_incbin(char *filename, yasm_expr *start, yasm_expr *maxlen,
+ yasm_linemap *linemap, unsigned long line)
+{
+ bytecode_incbin *incbin = yasm_xmalloc(sizeof(bytecode_incbin));
+ unsigned long xline;
+
+ /* Find from filename based on line number */
+ yasm_linemap_lookup(linemap, line, &incbin->from, &xline);
+
+ /*@-mustfree@*/
+ incbin->filename = filename;
+ incbin->start = start;
+ incbin->maxlen = maxlen;
+ /*@=mustfree@*/
+
+ return yasm_bc_create_common(&bc_incbin_callback, incbin, line);
+}
diff --git a/contrib/tools/yasm/libyasm/bc-org.c b/contrib/tools/yasm/libyasm/bc-org.c
index 7ef96c8412..36dc255343 100644
--- a/contrib/tools/yasm/libyasm/bc-org.c
+++ b/contrib/tools/yasm/libyasm/bc-org.c
@@ -1,152 +1,152 @@
-/*
- * ORG bytecode
- *
- * Copyright (C) 2005-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#include "util.h"
-
-#include "libyasm-stdint.h"
-#include "coretype.h"
-#include "file.h"
-
-#include "errwarn.h"
-#include "intnum.h"
-#include "expr.h"
-#include "value.h"
-
-#include "bytecode.h"
-
-
-typedef struct bytecode_org {
- unsigned long start; /* target starting offset within section */
- unsigned long fill; /* fill value */
-} bytecode_org;
-
-static void bc_org_destroy(void *contents);
-static void bc_org_print(const void *contents, FILE *f, int indent_level);
-static void bc_org_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
-static int bc_org_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
- void *add_span_data);
-static int bc_org_expand(yasm_bytecode *bc, int span, long old_val,
- long new_val, /*@out@*/ long *neg_thres,
- /*@out@*/ long *pos_thres);
-static int bc_org_tobytes(yasm_bytecode *bc, unsigned char **bufp,
- unsigned char *bufstart, void *d,
- yasm_output_value_func output_value,
- /*@null@*/ yasm_output_reloc_func output_reloc);
-
-static const yasm_bytecode_callback bc_org_callback = {
- bc_org_destroy,
- bc_org_print,
- bc_org_finalize,
- NULL,
- bc_org_calc_len,
- bc_org_expand,
- bc_org_tobytes,
- YASM_BC_SPECIAL_OFFSET
-};
-
-
-static void
-bc_org_destroy(void *contents)
-{
- yasm_xfree(contents);
-}
-
-static void
-bc_org_print(const void *contents, FILE *f, int indent_level)
-{
- const bytecode_org *org = (const bytecode_org *)contents;
- fprintf(f, "%*s_Org_\n", indent_level, "");
- fprintf(f, "%*sStart=%lu\n", indent_level, "", org->start);
-}
-
-static void
-bc_org_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
-{
-}
-
-static int
-bc_org_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
- void *add_span_data)
-{
- bytecode_org *org = (bytecode_org *)bc->contents;
- long neg_thres = 0;
- long pos_thres = org->start;
-
- if (bc_org_expand(bc, 0, 0, (long)bc->offset, &neg_thres, &pos_thres) < 0)
- return -1;
-
- return 0;
-}
-
-static int
-bc_org_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
- /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
-{
- bytecode_org *org = (bytecode_org *)bc->contents;
-
- /* Check for overrun */
- if ((unsigned long)new_val > org->start) {
- yasm_error_set(YASM_ERROR_GENERAL,
- N_("ORG overlap with already existing data"));
- return -1;
- }
-
- /* Generate space to start offset */
- bc->len = org->start - new_val;
- return 1;
-}
-
-static int
-bc_org_tobytes(yasm_bytecode *bc, unsigned char **bufp,
- unsigned char *bufstart, void *d,
- yasm_output_value_func output_value,
- /*@unused@*/ yasm_output_reloc_func output_reloc)
-{
- bytecode_org *org = (bytecode_org *)bc->contents;
- unsigned long len, i;
-
- /* Sanity check for overrun */
- if (bc->offset > org->start) {
- yasm_error_set(YASM_ERROR_GENERAL,
- N_("ORG overlap with already existing data"));
- return 1;
- }
- len = org->start - bc->offset;
- for (i=0; i<len; i++)
- YASM_WRITE_8(*bufp, org->fill); /* XXX: handle more than 8 bit? */
- return 0;
-}
-
-yasm_bytecode *
-yasm_bc_create_org(unsigned long start, unsigned long fill, unsigned long line)
-{
- bytecode_org *org = yasm_xmalloc(sizeof(bytecode_org));
-
- org->start = start;
- org->fill = fill;
-
- return yasm_bc_create_common(&bc_org_callback, org, line);
-}
+/*
+ * ORG bytecode
+ *
+ * Copyright (C) 2005-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "util.h"
+
+#include "libyasm-stdint.h"
+#include "coretype.h"
+#include "file.h"
+
+#include "errwarn.h"
+#include "intnum.h"
+#include "expr.h"
+#include "value.h"
+
+#include "bytecode.h"
+
+
+typedef struct bytecode_org {
+ unsigned long start; /* target starting offset within section */
+ unsigned long fill; /* fill value */
+} bytecode_org;
+
+static void bc_org_destroy(void *contents);
+static void bc_org_print(const void *contents, FILE *f, int indent_level);
+static void bc_org_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
+static int bc_org_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data);
+static int bc_org_expand(yasm_bytecode *bc, int span, long old_val,
+ long new_val, /*@out@*/ long *neg_thres,
+ /*@out@*/ long *pos_thres);
+static int bc_org_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+static const yasm_bytecode_callback bc_org_callback = {
+ bc_org_destroy,
+ bc_org_print,
+ bc_org_finalize,
+ NULL,
+ bc_org_calc_len,
+ bc_org_expand,
+ bc_org_tobytes,
+ YASM_BC_SPECIAL_OFFSET
+};
+
+
+static void
+bc_org_destroy(void *contents)
+{
+ yasm_xfree(contents);
+}
+
+static void
+bc_org_print(const void *contents, FILE *f, int indent_level)
+{
+ const bytecode_org *org = (const bytecode_org *)contents;
+ fprintf(f, "%*s_Org_\n", indent_level, "");
+ fprintf(f, "%*sStart=%lu\n", indent_level, "", org->start);
+}
+
+static void
+bc_org_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
+{
+}
+
+static int
+bc_org_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ bytecode_org *org = (bytecode_org *)bc->contents;
+ long neg_thres = 0;
+ long pos_thres = org->start;
+
+ if (bc_org_expand(bc, 0, 0, (long)bc->offset, &neg_thres, &pos_thres) < 0)
+ return -1;
+
+ return 0;
+}
+
+static int
+bc_org_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
+ /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
+{
+ bytecode_org *org = (bytecode_org *)bc->contents;
+
+ /* Check for overrun */
+ if ((unsigned long)new_val > org->start) {
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("ORG overlap with already existing data"));
+ return -1;
+ }
+
+ /* Generate space to start offset */
+ bc->len = org->start - new_val;
+ return 1;
+}
+
+static int
+bc_org_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@unused@*/ yasm_output_reloc_func output_reloc)
+{
+ bytecode_org *org = (bytecode_org *)bc->contents;
+ unsigned long len, i;
+
+ /* Sanity check for overrun */
+ if (bc->offset > org->start) {
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("ORG overlap with already existing data"));
+ return 1;
+ }
+ len = org->start - bc->offset;
+ for (i=0; i<len; i++)
+ YASM_WRITE_8(*bufp, org->fill); /* XXX: handle more than 8 bit? */
+ return 0;
+}
+
+yasm_bytecode *
+yasm_bc_create_org(unsigned long start, unsigned long fill, unsigned long line)
+{
+ bytecode_org *org = yasm_xmalloc(sizeof(bytecode_org));
+
+ org->start = start;
+ org->fill = fill;
+
+ return yasm_bc_create_common(&bc_org_callback, org, line);
+}
diff --git a/contrib/tools/yasm/libyasm/bc-reserve.c b/contrib/tools/yasm/libyasm/bc-reserve.c
index 197175b4e5..f687f1410f 100644
--- a/contrib/tools/yasm/libyasm/bc-reserve.c
+++ b/contrib/tools/yasm/libyasm/bc-reserve.c
@@ -1,152 +1,152 @@
-/*
- * Bytecode utility functions
- *
- * Copyright (C) 2001-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#include "util.h"
-
-#include "libyasm-stdint.h"
-#include "coretype.h"
-
-#include "errwarn.h"
-#include "intnum.h"
-#include "expr.h"
-#include "value.h"
-
-#include "bytecode.h"
-
-
-typedef struct bytecode_reserve {
- /*@only@*/ /*@null@*/ yasm_expr *numitems; /* number of items to reserve */
- unsigned int itemsize; /* size of each item (in bytes) */
-} bytecode_reserve;
-
-static void bc_reserve_destroy(void *contents);
-static void bc_reserve_print(const void *contents, FILE *f, int indent_level);
-static void bc_reserve_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
-static int bc_reserve_elem_size(yasm_bytecode *bc);
-static int bc_reserve_calc_len(yasm_bytecode *bc,
- yasm_bc_add_span_func add_span,
- void *add_span_data);
-static int bc_reserve_tobytes(yasm_bytecode *bc, unsigned char **bufp,
- unsigned char *bufstart, void *d,
- yasm_output_value_func output_value,
- /*@null@*/ yasm_output_reloc_func output_reloc);
-
-static const yasm_bytecode_callback bc_reserve_callback = {
- bc_reserve_destroy,
- bc_reserve_print,
- bc_reserve_finalize,
- bc_reserve_elem_size,
- bc_reserve_calc_len,
- yasm_bc_expand_common,
- bc_reserve_tobytes,
- YASM_BC_SPECIAL_RESERVE
-};
-
-
-static void
-bc_reserve_destroy(void *contents)
-{
- bytecode_reserve *reserve = (bytecode_reserve *)contents;
- yasm_expr_destroy(reserve->numitems);
- yasm_xfree(contents);
-}
-
-static void
-bc_reserve_print(const void *contents, FILE *f, int indent_level)
-{
- const bytecode_reserve *reserve = (const bytecode_reserve *)contents;
- fprintf(f, "%*s_Reserve_\n", indent_level, "");
- fprintf(f, "%*sNum Items=", indent_level, "");
- yasm_expr_print(reserve->numitems, f);
- fprintf(f, "\n%*sItem Size=%u\n", indent_level, "", reserve->itemsize);
-}
-
-static void
-bc_reserve_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
-{
- bytecode_reserve *reserve = (bytecode_reserve *)bc->contents;
- /* multiply reserve expression into multiple */
- if (!bc->multiple)
- bc->multiple = reserve->numitems;
- else
- bc->multiple = yasm_expr_create_tree(bc->multiple, YASM_EXPR_MUL,
- reserve->numitems, bc->line);
- reserve->numitems = NULL;
-}
-
-static int
-bc_reserve_elem_size(yasm_bytecode *bc)
-{
- bytecode_reserve *reserve = (bytecode_reserve *)bc->contents;
- return reserve->itemsize;
-}
-
-static int
-bc_reserve_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
- void *add_span_data)
-{
- bytecode_reserve *reserve = (bytecode_reserve *)bc->contents;
- bc->len += reserve->itemsize;
- return 0;
-}
-
-static int
-bc_reserve_tobytes(yasm_bytecode *bc, unsigned char **bufp,
- unsigned char *bufstart, void *d,
- yasm_output_value_func output_value,
- /*@unused@*/ yasm_output_reloc_func output_reloc)
-{
- yasm_internal_error(N_("bc_reserve_tobytes called"));
- /*@notreached@*/
- return 1;
-}
-
-yasm_bytecode *
-yasm_bc_create_reserve(yasm_expr *numitems, unsigned int itemsize,
- unsigned long line)
-{
- bytecode_reserve *reserve = yasm_xmalloc(sizeof(bytecode_reserve));
-
- /*@-mustfree@*/
- reserve->numitems = numitems;
- /*@=mustfree@*/
- reserve->itemsize = itemsize;
-
- return yasm_bc_create_common(&bc_reserve_callback, reserve, line);
-}
-
-const yasm_expr *
-yasm_bc_reserve_numitems(yasm_bytecode *bc, unsigned int *itemsize)
-{
- bytecode_reserve *reserve;
-
- if (bc->callback != &bc_reserve_callback)
- return NULL;
-
- reserve = (bytecode_reserve *)bc->contents;
- *itemsize = reserve->itemsize;
- return reserve->numitems;
-}
+/*
+ * Bytecode utility functions
+ *
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "util.h"
+
+#include "libyasm-stdint.h"
+#include "coretype.h"
+
+#include "errwarn.h"
+#include "intnum.h"
+#include "expr.h"
+#include "value.h"
+
+#include "bytecode.h"
+
+
+typedef struct bytecode_reserve {
+ /*@only@*/ /*@null@*/ yasm_expr *numitems; /* number of items to reserve */
+ unsigned int itemsize; /* size of each item (in bytes) */
+} bytecode_reserve;
+
+static void bc_reserve_destroy(void *contents);
+static void bc_reserve_print(const void *contents, FILE *f, int indent_level);
+static void bc_reserve_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
+static int bc_reserve_elem_size(yasm_bytecode *bc);
+static int bc_reserve_calc_len(yasm_bytecode *bc,
+ yasm_bc_add_span_func add_span,
+ void *add_span_data);
+static int bc_reserve_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+static const yasm_bytecode_callback bc_reserve_callback = {
+ bc_reserve_destroy,
+ bc_reserve_print,
+ bc_reserve_finalize,
+ bc_reserve_elem_size,
+ bc_reserve_calc_len,
+ yasm_bc_expand_common,
+ bc_reserve_tobytes,
+ YASM_BC_SPECIAL_RESERVE
+};
+
+
+static void
+bc_reserve_destroy(void *contents)
+{
+ bytecode_reserve *reserve = (bytecode_reserve *)contents;
+ yasm_expr_destroy(reserve->numitems);
+ yasm_xfree(contents);
+}
+
+static void
+bc_reserve_print(const void *contents, FILE *f, int indent_level)
+{
+ const bytecode_reserve *reserve = (const bytecode_reserve *)contents;
+ fprintf(f, "%*s_Reserve_\n", indent_level, "");
+ fprintf(f, "%*sNum Items=", indent_level, "");
+ yasm_expr_print(reserve->numitems, f);
+ fprintf(f, "\n%*sItem Size=%u\n", indent_level, "", reserve->itemsize);
+}
+
+static void
+bc_reserve_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
+{
+ bytecode_reserve *reserve = (bytecode_reserve *)bc->contents;
+ /* multiply reserve expression into multiple */
+ if (!bc->multiple)
+ bc->multiple = reserve->numitems;
+ else
+ bc->multiple = yasm_expr_create_tree(bc->multiple, YASM_EXPR_MUL,
+ reserve->numitems, bc->line);
+ reserve->numitems = NULL;
+}
+
+static int
+bc_reserve_elem_size(yasm_bytecode *bc)
+{
+ bytecode_reserve *reserve = (bytecode_reserve *)bc->contents;
+ return reserve->itemsize;
+}
+
+static int
+bc_reserve_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ bytecode_reserve *reserve = (bytecode_reserve *)bc->contents;
+ bc->len += reserve->itemsize;
+ return 0;
+}
+
+static int
+bc_reserve_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@unused@*/ yasm_output_reloc_func output_reloc)
+{
+ yasm_internal_error(N_("bc_reserve_tobytes called"));
+ /*@notreached@*/
+ return 1;
+}
+
+yasm_bytecode *
+yasm_bc_create_reserve(yasm_expr *numitems, unsigned int itemsize,
+ unsigned long line)
+{
+ bytecode_reserve *reserve = yasm_xmalloc(sizeof(bytecode_reserve));
+
+ /*@-mustfree@*/
+ reserve->numitems = numitems;
+ /*@=mustfree@*/
+ reserve->itemsize = itemsize;
+
+ return yasm_bc_create_common(&bc_reserve_callback, reserve, line);
+}
+
+const yasm_expr *
+yasm_bc_reserve_numitems(yasm_bytecode *bc, unsigned int *itemsize)
+{
+ bytecode_reserve *reserve;
+
+ if (bc->callback != &bc_reserve_callback)
+ return NULL;
+
+ reserve = (bytecode_reserve *)bc->contents;
+ *itemsize = reserve->itemsize;
+ return reserve->numitems;
+}
diff --git a/contrib/tools/yasm/libyasm/bitvect.c b/contrib/tools/yasm/libyasm/bitvect.c
index dfb08252b0..b1d5bdae11 100644
--- a/contrib/tools/yasm/libyasm/bitvect.c
+++ b/contrib/tools/yasm/libyasm/bitvect.c
@@ -1,4045 +1,4045 @@
-#include "util.h"
-
-#include "coretype.h"
-
-/*****************************************************************************/
-/* MODULE NAME: BitVector.c MODULE TYPE: (adt) */
-/*****************************************************************************/
-/* MODULE IMPORTS: */
-/*****************************************************************************/
-#include <ctype.h> /* MODULE TYPE: (sys) */
-#include <limits.h> /* MODULE TYPE: (sys) */
-#include <string.h> /* MODULE TYPE: (sys) */
-/*****************************************************************************/
-/* MODULE INTERFACE: */
-/*****************************************************************************/
-#include "bitvect.h"
-
-/* ToolBox.h */
-#define and && /* logical (boolean) operators: lower case */
-#define or ||
-#define not !
-
-#define AND & /* binary (bitwise) operators: UPPER CASE */
-#define OR |
-#define XOR ^
-#define NOT ~
-#define SHL <<
-#define SHR >>
-
-#ifdef ENABLE_MODULO
-#define mod % /* arithmetic operators */
-#endif
-
-#define blockdef(name,size) unsigned char name[size]
-#define blocktypedef(name,size) typedef unsigned char name[size]
-
-/*****************************************************************************/
-/* MODULE RESOURCES: */
-/*****************************************************************************/
-
-#define bits_(BitVector) *(BitVector-3)
-#define size_(BitVector) *(BitVector-2)
-#define mask_(BitVector) *(BitVector-1)
-
-#define ERRCODE_TYPE "sizeof(word) > sizeof(size_t)"
-#define ERRCODE_BITS "bits(word) != sizeof(word)*8"
-#define ERRCODE_WORD "bits(word) < 16"
-#define ERRCODE_LONG "bits(word) > bits(long)"
-#define ERRCODE_POWR "bits(word) != 2^x"
-#define ERRCODE_LOGA "bits(word) != 2^ld(bits(word))"
-#define ERRCODE_NULL "unable to allocate memory"
-#define ERRCODE_INDX "index out of range"
-#define ERRCODE_ORDR "minimum > maximum index"
-#define ERRCODE_SIZE "bit vector size mismatch"
-#define ERRCODE_PARS "input string syntax error"
-#define ERRCODE_OVFL "numeric overflow error"
-#define ERRCODE_SAME "result vector(s) must be distinct"
-#define ERRCODE_EXPO "exponent must be positive"
-#define ERRCODE_ZERO "division by zero error"
-#define ERRCODE_OOPS "unexpected internal error - please contact author"
-
-const N_int BitVector_BYTENORM[256] =
-{
- 0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x03,
- 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, /* 0x00 */
- 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
- 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, /* 0x10 */
- 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
- 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, /* 0x20 */
- 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
- 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, /* 0x30 */
- 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
- 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, /* 0x40 */
- 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
- 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, /* 0x50 */
- 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
- 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, /* 0x60 */
- 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
- 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, /* 0x70 */
- 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
- 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, /* 0x80 */
- 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
- 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, /* 0x90 */
- 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
- 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, /* 0xA0 */
- 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
- 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, /* 0xB0 */
- 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
- 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, /* 0xC0 */
- 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
- 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, /* 0xD0 */
- 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
- 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, /* 0xE0 */
- 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07,
- 0x05, 0x06, 0x06, 0x07, 0x06, 0x07, 0x07, 0x08 /* 0xF0 */
-};
-
-/*****************************************************************************/
-/* MODULE IMPLEMENTATION: */
-/*****************************************************************************/
-
- /**********************************************/
- /* global implementation-intrinsic constants: */
- /**********************************************/
-
-#define BIT_VECTOR_HIDDEN_WORDS 3
-
- /*****************************************************************/
- /* global machine-dependent constants (set by "BitVector_Boot"): */
- /*****************************************************************/
-
-static N_word BITS; /* = # of bits in machine word (must be power of 2) */
-static N_word MODMASK; /* = BITS - 1 (mask for calculating modulo BITS) */
-static N_word LOGBITS; /* = ld(BITS) (logarithmus dualis) */
-static N_word FACTOR; /* = ld(BITS / 8) (ld of # of bytes) */
-
-static N_word LSB = 1; /* = mask for least significant bit */
-static N_word MSB; /* = mask for most significant bit */
-
-static N_word LONGBITS; /* = # of bits in unsigned long */
-
-static N_word LOG10; /* = logarithm to base 10 of BITS - 1 */
-static N_word EXP10; /* = largest possible power of 10 in signed int */
-
- /********************************************************************/
- /* global bit mask table for fast access (set by "BitVector_Boot"): */
- /********************************************************************/
-
-static wordptr BITMASKTAB;
-
- /*****************************/
- /* global macro definitions: */
- /*****************************/
-
-#define BIT_VECTOR_ZERO_WORDS(target,count) \
- while (count-- > 0) *target++ = 0;
-
-#define BIT_VECTOR_FILL_WORDS(target,fill,count) \
- while (count-- > 0) *target++ = fill;
-
-#define BIT_VECTOR_FLIP_WORDS(target,flip,count) \
- while (count-- > 0) *target++ ^= flip;
-
-#define BIT_VECTOR_COPY_WORDS(target,source,count) \
- while (count-- > 0) *target++ = *source++;
-
-#define BIT_VECTOR_BACK_WORDS(target,source,count) \
- { target += count; source += count; while (count-- > 0) *--target = *--source; }
-
-#define BIT_VECTOR_CLR_BIT(address,index) \
- *(address+(index>>LOGBITS)) &= NOT BITMASKTAB[index AND MODMASK];
-
-#define BIT_VECTOR_SET_BIT(address,index) \
- *(address+(index>>LOGBITS)) |= BITMASKTAB[index AND MODMASK];
-
-#define BIT_VECTOR_TST_BIT(address,index) \
- ((*(address+(index>>LOGBITS)) AND BITMASKTAB[index AND MODMASK]) != 0)
-
-#define BIT_VECTOR_FLP_BIT(address,index,mask) \
- (mask = BITMASKTAB[index AND MODMASK]), \
- (((*(addr+(index>>LOGBITS)) ^= mask) AND mask) != 0)
-
-#define BIT_VECTOR_DIGITIZE(type,value,digit) \
- value = (type) ((digit = value) / 10); \
- digit -= value * 10; \
- digit += (type) '0';
-
- /*********************************************************/
- /* private low-level functions (potentially dangerous!): */
- /*********************************************************/
-
-static N_word power10(N_word x)
-{
- N_word y = 1;
-
- while (x-- > 0) y *= 10;
- return(y);
-}
-
-static void BIT_VECTOR_zro_words(wordptr addr, N_word count)
-{
- BIT_VECTOR_ZERO_WORDS(addr,count)
-}
-
-static void BIT_VECTOR_cpy_words(wordptr target, wordptr source, N_word count)
-{
- BIT_VECTOR_COPY_WORDS(target,source,count)
-}
-
-static void BIT_VECTOR_mov_words(wordptr target, wordptr source, N_word count)
-{
- if (target != source)
- {
- if (target < source) BIT_VECTOR_COPY_WORDS(target,source,count)
- else BIT_VECTOR_BACK_WORDS(target,source,count)
- }
-}
-
-static void BIT_VECTOR_ins_words(wordptr addr, N_word total, N_word count,
- boolean clear)
-{
- N_word length;
-
- if ((total > 0) and (count > 0))
- {
- if (count > total) count = total;
- length = total - count;
- if (length > 0) BIT_VECTOR_mov_words(addr+count,addr,length);
- if (clear) BIT_VECTOR_zro_words(addr,count);
- }
-}
-
-static void BIT_VECTOR_del_words(wordptr addr, N_word total, N_word count,
- boolean clear)
-{
- N_word length;
-
- if ((total > 0) and (count > 0))
- {
- if (count > total) count = total;
- length = total - count;
- if (length > 0) BIT_VECTOR_mov_words(addr,addr+count,length);
- if (clear) BIT_VECTOR_zro_words(addr+length,count);
- }
-}
-
-static void BIT_VECTOR_reverse(charptr string, N_word length)
-{
- charptr last;
- N_char temp;
-
- if (length > 1)
- {
- last = string + length - 1;
- while (string < last)
- {
- temp = *string;
- *string = *last;
- *last = temp;
- string++;
- last--;
- }
- }
-}
-
-static N_word BIT_VECTOR_int2str(charptr string, N_word value)
-{
- N_word length;
- N_word digit;
- charptr work;
-
- work = string;
- if (value > 0)
- {
- length = 0;
- while (value > 0)
- {
- BIT_VECTOR_DIGITIZE(N_word,value,digit)
- *work++ = (N_char) digit;
- length++;
- }
- BIT_VECTOR_reverse(string,length);
- }
- else
- {
- length = 1;
- *work++ = (N_char) '0';
- }
- return(length);
-}
-
-static N_word BIT_VECTOR_str2int(charptr string, N_word *value)
-{
- N_word length;
- N_word digit;
-
- *value = 0;
- length = 0;
- digit = (N_word) *string++;
- /* separate because isdigit() is likely a macro! */
- while (isdigit((int)digit) != 0)
- {
- length++;
- digit -= (N_word) '0';
- if (*value) *value *= 10;
- *value += digit;
- digit = (N_word) *string++;
- }
- return(length);
-}
-
- /********************************************/
- /* routine to convert error code to string: */
- /********************************************/
-
-const char * BitVector_Error(ErrCode error)
-{
- switch (error)
- {
- case ErrCode_Ok: return( NULL ); break;
- case ErrCode_Type: return( ERRCODE_TYPE ); break;
- case ErrCode_Bits: return( ERRCODE_BITS ); break;
- case ErrCode_Word: return( ERRCODE_WORD ); break;
- case ErrCode_Long: return( ERRCODE_LONG ); break;
- case ErrCode_Powr: return( ERRCODE_POWR ); break;
- case ErrCode_Loga: return( ERRCODE_LOGA ); break;
- case ErrCode_Null: return( ERRCODE_NULL ); break;
- case ErrCode_Indx: return( ERRCODE_INDX ); break;
- case ErrCode_Ordr: return( ERRCODE_ORDR ); break;
- case ErrCode_Size: return( ERRCODE_SIZE ); break;
- case ErrCode_Pars: return( ERRCODE_PARS ); break;
- case ErrCode_Ovfl: return( ERRCODE_OVFL ); break;
- case ErrCode_Same: return( ERRCODE_SAME ); break;
- case ErrCode_Expo: return( ERRCODE_EXPO ); break;
- case ErrCode_Zero: return( ERRCODE_ZERO ); break;
- default: return( ERRCODE_OOPS ); break;
- }
-}
-
- /*****************************************/
- /* automatic self-configuration routine: */
- /*****************************************/
-
- /*******************************************************/
- /* */
- /* MUST be called once prior to any other function */
- /* to initialize the machine dependent constants */
- /* of this package! (But call only ONCE, or you */
- /* will suffer memory leaks!) */
- /* */
- /*******************************************************/
-
-ErrCode BitVector_Boot(void)
-{
- N_long longsample = 1L;
- N_word sample = LSB;
- N_word lsb;
-
- if (sizeof(N_word) > sizeof(size_t)) return(ErrCode_Type);
-
- BITS = 1;
- while (sample <<= 1) BITS++; /* determine # of bits in a machine word */
-
- if (BITS != (sizeof(N_word) << 3)) return(ErrCode_Bits);
-
- if (BITS < 16) return(ErrCode_Word);
-
- LONGBITS = 1;
- while (longsample <<= 1) LONGBITS++; /* = # of bits in an unsigned long */
-
- if (BITS > LONGBITS) return(ErrCode_Long);
-
- LOGBITS = 0;
- sample = BITS;
- lsb = (sample AND LSB);
- while ((sample >>= 1) and (not lsb))
- {
- LOGBITS++;
- lsb = (sample AND LSB);
- }
-
- if (sample) return(ErrCode_Powr); /* # of bits is not a power of 2! */
-
- if (BITS != (LSB << LOGBITS)) return(ErrCode_Loga);
-
- MODMASK = BITS - 1;
- FACTOR = LOGBITS - 3; /* ld(BITS / 8) = ld(BITS) - ld(8) = ld(BITS) - 3 */
- MSB = (LSB << MODMASK);
-
- BITMASKTAB = (wordptr) yasm_xmalloc((size_t) (BITS << FACTOR));
-
- if (BITMASKTAB == NULL) return(ErrCode_Null);
-
- for ( sample = 0; sample < BITS; sample++ )
- {
- BITMASKTAB[sample] = (LSB << sample);
- }
-
- LOG10 = (N_word) (MODMASK * 0.30103); /* = (BITS - 1) * ( ln 2 / ln 10 ) */
- EXP10 = power10(LOG10);
-
- return(ErrCode_Ok);
-}
-
-void BitVector_Shutdown(void)
-{
- if (BITMASKTAB) yasm_xfree(BITMASKTAB);
-}
-
-N_word BitVector_Size(N_int bits) /* bit vector size (# of words) */
-{
- N_word size;
-
- size = bits >> LOGBITS;
- if (bits AND MODMASK) size++;
- return(size);
-}
-
-N_word BitVector_Mask(N_int bits) /* bit vector mask (unused bits) */
-{
- N_word mask;
-
- mask = bits AND MODMASK;
- if (mask) mask = (N_word) ~(~0L << mask); else mask = (N_word) ~0L;
- return(mask);
-}
-
-const char * BitVector_Version(void)
-{
- return("6.4");
-}
-
-N_int BitVector_Word_Bits(void)
-{
- return(BITS);
-}
-
-N_int BitVector_Long_Bits(void)
-{
- return(LONGBITS);
-}
-
-/********************************************************************/
-/* */
-/* WARNING: Do not "free()" constant character strings, i.e., */
-/* don't call "BitVector_Dispose()" for strings returned */
-/* by "BitVector_Error()" or "BitVector_Version()"! */
-/* */
-/* ONLY call this function for strings allocated with "malloc()", */
-/* i.e., the strings returned by the functions "BitVector_to_*()" */
-/* and "BitVector_Block_Read()"! */
-/* */
-/********************************************************************/
-
-void BitVector_Dispose(charptr string) /* free string */
-{
- if (string != NULL) yasm_xfree((voidptr) string);
-}
-
-void BitVector_Destroy(wordptr addr) /* free bitvec */
-{
- if (addr != NULL)
- {
- addr -= BIT_VECTOR_HIDDEN_WORDS;
- yasm_xfree((voidptr) addr);
- }
-}
-
-void BitVector_Destroy_List(listptr list, N_int count) /* free list */
-{
- listptr slot;
-
- if (list != NULL)
- {
- slot = list;
- while (count-- > 0)
- {
- BitVector_Destroy(*slot++);
- }
- free((voidptr) list);
- }
-}
-
-wordptr BitVector_Create(N_int bits, boolean clear) /* malloc */
-{
- N_word size;
- N_word mask;
- N_word bytes;
- wordptr addr;
- wordptr zero;
-
- size = BitVector_Size(bits);
- mask = BitVector_Mask(bits);
- bytes = (size + BIT_VECTOR_HIDDEN_WORDS) << FACTOR;
- addr = (wordptr) yasm_xmalloc((size_t) bytes);
- if (addr != NULL)
- {
- *addr++ = bits;
- *addr++ = size;
- *addr++ = mask;
- if (clear)
- {
- zero = addr;
- BIT_VECTOR_ZERO_WORDS(zero,size)
- }
- }
- return(addr);
-}
-
-listptr BitVector_Create_List(N_int bits, boolean clear, N_int count)
-{
- listptr list = NULL;
- listptr slot;
- wordptr addr;
- N_int i;
-
- if (count > 0)
- {
- list = (listptr) malloc(sizeof(wordptr) * count);
- if (list != NULL)
- {
- slot = list;
- for ( i = 0; i < count; i++ )
- {
- addr = BitVector_Create(bits,clear);
- if (addr == NULL)
- {
- BitVector_Destroy_List(list,i);
- return(NULL);
- }
- *slot++ = addr;
- }
- }
- }
- return(list);
-}
-
-wordptr BitVector_Resize(wordptr oldaddr, N_int bits) /* realloc */
-{
- N_word bytes;
- N_word oldsize;
- N_word oldmask;
- N_word newsize;
- N_word newmask;
- wordptr newaddr;
- wordptr source;
- wordptr target;
-
- oldsize = size_(oldaddr);
- oldmask = mask_(oldaddr);
- newsize = BitVector_Size(bits);
- newmask = BitVector_Mask(bits);
- if (oldsize > 0) *(oldaddr+oldsize-1) &= oldmask;
- if (newsize <= oldsize)
- {
- newaddr = oldaddr;
- bits_(newaddr) = bits;
- size_(newaddr) = newsize;
- mask_(newaddr) = newmask;
- if (newsize > 0) *(newaddr+newsize-1) &= newmask;
- }
- else
- {
- bytes = (newsize + BIT_VECTOR_HIDDEN_WORDS) << FACTOR;
- newaddr = (wordptr) yasm_xmalloc((size_t) bytes);
- if (newaddr != NULL)
- {
- *newaddr++ = bits;
- *newaddr++ = newsize;
- *newaddr++ = newmask;
- target = newaddr;
- source = oldaddr;
- newsize -= oldsize;
- BIT_VECTOR_COPY_WORDS(target,source,oldsize)
- BIT_VECTOR_ZERO_WORDS(target,newsize)
- }
- BitVector_Destroy(oldaddr);
- }
- return(newaddr);
-}
-
-wordptr BitVector_Shadow(wordptr addr) /* makes new, same size but empty */
-{
- return( BitVector_Create(bits_(addr),true) );
-}
-
-wordptr BitVector_Clone(wordptr addr) /* makes exact duplicate */
-{
- N_word bits;
- wordptr twin;
-
- bits = bits_(addr);
- twin = BitVector_Create(bits,false);
- if ((twin != NULL) and (bits > 0))
- BIT_VECTOR_cpy_words(twin,addr,size_(addr));
- return(twin);
-}
-
-wordptr BitVector_Concat(wordptr X, wordptr Y) /* returns concatenation */
-{
- /* BEWARE that X = most significant part, Y = least significant part! */
-
- N_word bitsX;
- N_word bitsY;
- N_word bitsZ;
- wordptr Z;
-
- bitsX = bits_(X);
- bitsY = bits_(Y);
- bitsZ = bitsX + bitsY;
- Z = BitVector_Create(bitsZ,false);
- if ((Z != NULL) and (bitsZ > 0))
- {
- BIT_VECTOR_cpy_words(Z,Y,size_(Y));
- BitVector_Interval_Copy(Z,X,bitsY,0,bitsX);
- *(Z+size_(Z)-1) &= mask_(Z);
- }
- return(Z);
-}
-
-void BitVector_Copy(wordptr X, wordptr Y) /* X = Y */
-{
- N_word sizeX = size_(X);
- N_word sizeY = size_(Y);
- N_word maskX = mask_(X);
- N_word maskY = mask_(Y);
- N_word fill = 0;
- wordptr lastX;
- wordptr lastY;
-
- if ((X != Y) and (sizeX > 0))
- {
- lastX = X + sizeX - 1;
- if (sizeY > 0)
- {
- lastY = Y + sizeY - 1;
- if ( (*lastY AND (maskY AND NOT (maskY >> 1))) == 0 ) *lastY &= maskY;
- else
- {
- fill = (N_word) ~0L;
- *lastY |= NOT maskY;
- }
- while ((sizeX > 0) and (sizeY > 0))
- {
- *X++ = *Y++;
- sizeX--;
- sizeY--;
- }
- *lastY &= maskY;
- }
- while (sizeX-- > 0) *X++ = fill;
- *lastX &= maskX;
- }
-}
-
-void BitVector_Empty(wordptr addr) /* X = {} clr all */
-{
- N_word size = size_(addr);
-
- BIT_VECTOR_ZERO_WORDS(addr,size)
-}
-
-void BitVector_Fill(wordptr addr) /* X = ~{} set all */
-{
- N_word size = size_(addr);
- N_word mask = mask_(addr);
- N_word fill = (N_word) ~0L;
-
- if (size > 0)
- {
- BIT_VECTOR_FILL_WORDS(addr,fill,size)
- *(--addr) &= mask;
- }
-}
-
-void BitVector_Flip(wordptr addr) /* X = ~X flip all */
-{
- N_word size = size_(addr);
- N_word mask = mask_(addr);
- N_word flip = (N_word) ~0L;
-
- if (size > 0)
- {
- BIT_VECTOR_FLIP_WORDS(addr,flip,size)
- *(--addr) &= mask;
- }
-}
-
-void BitVector_Primes(wordptr addr)
-{
- N_word bits = bits_(addr);
- N_word size = size_(addr);
- wordptr work;
- N_word temp;
- N_word i,j;
-
- if (size > 0)
- {
- temp = 0xAAAA;
- i = BITS >> 4;
- while (--i > 0)
- {
- temp <<= 16;
- temp |= 0xAAAA;
- }
- i = size;
- work = addr;
- *work++ = temp XOR 0x0006;
- while (--i > 0) *work++ = temp;
- for ( i = 3; (j = i * i) < bits; i += 2 )
- {
- for ( ; j < bits; j += i ) BIT_VECTOR_CLR_BIT(addr,j)
- }
- *(addr+size-1) &= mask_(addr);
- }
-}
-
-void BitVector_Reverse(wordptr X, wordptr Y)
-{
- N_word bits = bits_(X);
- N_word mask;
- N_word bit;
- N_word value;
-
- if (bits > 0)
- {
- if (X == Y) BitVector_Interval_Reverse(X,0,bits-1);
- else if (bits == bits_(Y))
- {
-/* mask = mask_(Y); */
-/* mask &= NOT (mask >> 1); */
- mask = BITMASKTAB[(bits-1) AND MODMASK];
- Y += size_(Y) - 1;
- value = 0;
- bit = LSB;
- while (bits-- > 0)
- {
- if ((*Y AND mask) != 0)
- {
- value |= bit;
- }
- if (not (mask >>= 1))
- {
- Y--;
- mask = MSB;
- }
- if (not (bit <<= 1))
- {
- *X++ = value;
- value = 0;
- bit = LSB;
- }
- }
- if (bit > LSB) *X = value;
- }
- }
-}
-
-void BitVector_Interval_Empty(wordptr addr, N_int lower, N_int upper)
-{ /* X = X \ [lower..upper] */
- N_word bits = bits_(addr);
- N_word size = size_(addr);
- wordptr loaddr;
- wordptr hiaddr;
- N_word lobase;
- N_word hibase;
- N_word lomask;
- N_word himask;
- N_word diff;
-
- if ((size > 0) and (lower < bits) and (upper < bits) and (lower <= upper))
- {
- lobase = lower >> LOGBITS;
- hibase = upper >> LOGBITS;
- diff = hibase - lobase;
- loaddr = addr + lobase;
- hiaddr = addr + hibase;
-
- lomask = (N_word) (~0L << (lower AND MODMASK));
- himask = (N_word) ~((~0L << (upper AND MODMASK)) << 1);
-
- if (diff == 0)
- {
- *loaddr &= NOT (lomask AND himask);
- }
- else
- {
- *loaddr++ &= NOT lomask;
- while (--diff > 0)
- {
- *loaddr++ = 0;
- }
- *hiaddr &= NOT himask;
- }
- }
-}
-
-void BitVector_Interval_Fill(wordptr addr, N_int lower, N_int upper)
-{ /* X = X + [lower..upper] */
- N_word bits = bits_(addr);
- N_word size = size_(addr);
- N_word fill = (N_word) ~0L;
- wordptr loaddr;
- wordptr hiaddr;
- N_word lobase;
- N_word hibase;
- N_word lomask;
- N_word himask;
- N_word diff;
-
- if ((size > 0) and (lower < bits) and (upper < bits) and (lower <= upper))
- {
- lobase = lower >> LOGBITS;
- hibase = upper >> LOGBITS;
- diff = hibase - lobase;
- loaddr = addr + lobase;
- hiaddr = addr + hibase;
-
- lomask = (N_word) (~0L << (lower AND MODMASK));
- himask = (N_word) ~((~0L << (upper AND MODMASK)) << 1);
-
- if (diff == 0)
- {
- *loaddr |= (lomask AND himask);
- }
- else
- {
- *loaddr++ |= lomask;
- while (--diff > 0)
- {
- *loaddr++ = fill;
- }
- *hiaddr |= himask;
- }
- *(addr+size-1) &= mask_(addr);
- }
-}
-
-void BitVector_Interval_Flip(wordptr addr, N_int lower, N_int upper)
-{ /* X = X ^ [lower..upper] */
- N_word bits = bits_(addr);
- N_word size = size_(addr);
- N_word flip = (N_word) ~0L;
- wordptr loaddr;
- wordptr hiaddr;
- N_word lobase;
- N_word hibase;
- N_word lomask;
- N_word himask;
- N_word diff;
-
- if ((size > 0) and (lower < bits) and (upper < bits) and (lower <= upper))
- {
- lobase = lower >> LOGBITS;
- hibase = upper >> LOGBITS;
- diff = hibase - lobase;
- loaddr = addr + lobase;
- hiaddr = addr + hibase;
-
- lomask = (N_word) (~0L << (lower AND MODMASK));
- himask = (N_word) ~((~0L << (upper AND MODMASK)) << 1);
-
- if (diff == 0)
- {
- *loaddr ^= (lomask AND himask);
- }
- else
- {
- *loaddr++ ^= lomask;
- while (--diff > 0)
- {
- *loaddr++ ^= flip;
- }
- *hiaddr ^= himask;
- }
- *(addr+size-1) &= mask_(addr);
- }
-}
-
-void BitVector_Interval_Reverse(wordptr addr, N_int lower, N_int upper)
-{
- N_word bits = bits_(addr);
- wordptr loaddr;
- wordptr hiaddr;
- N_word lomask;
- N_word himask;
-
- if ((bits > 0) and (lower < bits) and (upper < bits) and (lower < upper))
- {
- loaddr = addr + (lower >> LOGBITS);
- hiaddr = addr + (upper >> LOGBITS);
- lomask = BITMASKTAB[lower AND MODMASK];
- himask = BITMASKTAB[upper AND MODMASK];
- for ( bits = upper - lower + 1; bits > 1; bits -= 2 )
- {
- if (((*loaddr AND lomask) != 0) XOR ((*hiaddr AND himask) != 0))
- {
- *loaddr ^= lomask; /* swap bits only if they differ! */
- *hiaddr ^= himask;
- }
- if (not (lomask <<= 1))
- {
- lomask = LSB;
- loaddr++;
- }
- if (not (himask >>= 1))
- {
- himask = MSB;
- hiaddr--;
- }
- }
- }
-}
-
-boolean BitVector_interval_scan_inc(wordptr addr, N_int start,
- N_intptr min, N_intptr max)
-{
- N_word size = size_(addr);
- N_word mask = mask_(addr);
- N_word offset;
- N_word bitmask;
- N_word value;
- boolean empty;
-
- if ((size == 0) or (start >= bits_(addr))) return(FALSE);
-
- *min = start;
- *max = start;
-
- offset = start >> LOGBITS;
-
- *(addr+size-1) &= mask;
-
- addr += offset;
- size -= offset;
-
- bitmask = BITMASKTAB[start AND MODMASK];
- mask = NOT (bitmask OR (bitmask - 1));
-
- value = *addr++;
- if ((value AND bitmask) == 0)
- {
- value &= mask;
- if (value == 0)
- {
- offset++;
- empty = TRUE;
- while (empty and (--size > 0))
- {
- if ((value = *addr++)) empty = false; else offset++;
- }
- if (empty) return(FALSE);
- }
- start = offset << LOGBITS;
- bitmask = LSB;
- mask = value;
- while (not (mask AND LSB))
- {
- bitmask <<= 1;
- mask >>= 1;
- start++;
- }
- mask = NOT (bitmask OR (bitmask - 1));
- *min = start;
- *max = start;
- }
- value = NOT value;
- value &= mask;
- if (value == 0)
- {
- offset++;
- empty = TRUE;
- while (empty and (--size > 0))
- {
- if ((value = NOT *addr++)) empty = false; else offset++;
- }
- if (empty) value = LSB;
- }
- start = offset << LOGBITS;
- while (not (value AND LSB))
- {
- value >>= 1;
- start++;
- }
- *max = --start;
- return(TRUE);
-}
-
-boolean BitVector_interval_scan_dec(wordptr addr, N_int start,
- N_intptr min, N_intptr max)
-{
- N_word size = size_(addr);
- N_word mask = mask_(addr);
- N_word offset;
- N_word bitmask;
- N_word value;
- boolean empty;
-
- if ((size == 0) or (start >= bits_(addr))) return(FALSE);
-
- *min = start;
- *max = start;
-
- offset = start >> LOGBITS;
-
- if (offset >= size) return(FALSE);
-
- *(addr+size-1) &= mask;
-
- addr += offset;
- size = ++offset;
-
- bitmask = BITMASKTAB[start AND MODMASK];
- mask = (bitmask - 1);
-
- value = *addr--;
- if ((value AND bitmask) == 0)
- {
- value &= mask;
- if (value == 0)
- {
- offset--;
- empty = TRUE;
- while (empty and (--size > 0))
- {
- if ((value = *addr--)) empty = false; else offset--;
- }
- if (empty) return(FALSE);
- }
- start = offset << LOGBITS;
- bitmask = MSB;
- mask = value;
- while (not (mask AND MSB))
- {
- bitmask >>= 1;
- mask <<= 1;
- start--;
- }
- mask = (bitmask - 1);
- *max = --start;
- *min = start;
- }
- value = NOT value;
- value &= mask;
- if (value == 0)
- {
- offset--;
- empty = TRUE;
- while (empty and (--size > 0))
- {
- if ((value = NOT *addr--)) empty = false; else offset--;
- }
- if (empty) value = MSB;
- }
- start = offset << LOGBITS;
- while (not (value AND MSB))
- {
- value <<= 1;
- start--;
- }
- *min = start;
- return(TRUE);
-}
-
-void BitVector_Interval_Copy(wordptr X, wordptr Y, N_int Xoffset,
- N_int Yoffset, N_int length)
-{
- N_word bitsX = bits_(X);
- N_word bitsY = bits_(Y);
- N_word source = 0; /* silence compiler warning */
- N_word target = 0; /* silence compiler warning */
- N_word s_lo_base;
- N_word s_hi_base;
- N_word s_lo_bit;
- N_word s_hi_bit;
- N_word s_base;
- N_word s_lower = 0; /* silence compiler warning */
- N_word s_upper = 0; /* silence compiler warning */
- N_word s_bits;
- N_word s_min;
- N_word s_max;
- N_word t_lo_base;
- N_word t_hi_base;
- N_word t_lo_bit;
- N_word t_hi_bit;
- N_word t_base;
- N_word t_lower = 0; /* silence compiler warning */
- N_word t_upper = 0; /* silence compiler warning */
- N_word t_bits;
- N_word t_min;
- N_word mask;
- N_word bits;
- N_word sel;
- boolean ascending;
- boolean notfirst;
- wordptr Z = X;
-
- if ((length > 0) and (Xoffset < bitsX) and (Yoffset < bitsY))
- {
- if ((Xoffset + length) > bitsX) length = bitsX - Xoffset;
- if ((Yoffset + length) > bitsY) length = bitsY - Yoffset;
-
- ascending = (Xoffset <= Yoffset);
-
- s_lo_base = Yoffset >> LOGBITS;
- s_lo_bit = Yoffset AND MODMASK;
- Yoffset += --length;
- s_hi_base = Yoffset >> LOGBITS;
- s_hi_bit = Yoffset AND MODMASK;
-
- t_lo_base = Xoffset >> LOGBITS;
- t_lo_bit = Xoffset AND MODMASK;
- Xoffset += length;
- t_hi_base = Xoffset >> LOGBITS;
- t_hi_bit = Xoffset AND MODMASK;
-
- if (ascending)
- {
- s_base = s_lo_base;
- t_base = t_lo_base;
- }
- else
- {
- s_base = s_hi_base;
- t_base = t_hi_base;
- }
- s_bits = 0;
- t_bits = 0;
- Y += s_base;
- X += t_base;
- notfirst = FALSE;
- while (TRUE)
- {
- if (t_bits == 0)
- {
- if (notfirst)
- {
- *X = target;
- if (ascending)
- {
- if (t_base == t_hi_base) break;
- t_base++;
- X++;
- }
- else
- {
- if (t_base == t_lo_base) break;
- t_base--;
- X--;
- }
- }
- sel = ((t_base == t_hi_base) << 1) OR (t_base == t_lo_base);
- switch (sel)
- {
- case 0:
- t_lower = 0;
- t_upper = BITS - 1;
- t_bits = BITS;
- target = 0;
- break;
- case 1:
- t_lower = t_lo_bit;
- t_upper = BITS - 1;
- t_bits = BITS - t_lo_bit;
- mask = (N_word) (~0L << t_lower);
- target = *X AND NOT mask;
- break;
- case 2:
- t_lower = 0;
- t_upper = t_hi_bit;
- t_bits = t_hi_bit + 1;
- mask = (N_word) ((~0L << t_upper) << 1);
- target = *X AND mask;
- break;
- case 3:
- t_lower = t_lo_bit;
- t_upper = t_hi_bit;
- t_bits = t_hi_bit - t_lo_bit + 1;
- mask = (N_word) (~0L << t_lower);
- mask &= (N_word) ~((~0L << t_upper) << 1);
- target = *X AND NOT mask;
- break;
- }
- }
- if (s_bits == 0)
- {
- if (notfirst)
- {
- if (ascending)
- {
- if (s_base == s_hi_base) break;
- s_base++;
- Y++;
- }
- else
- {
- if (s_base == s_lo_base) break;
- s_base--;
- Y--;
- }
- }
- source = *Y;
- sel = ((s_base == s_hi_base) << 1) OR (s_base == s_lo_base);
- switch (sel)
- {
- case 0:
- s_lower = 0;
- s_upper = BITS - 1;
- s_bits = BITS;
- break;
- case 1:
- s_lower = s_lo_bit;
- s_upper = BITS - 1;
- s_bits = BITS - s_lo_bit;
- break;
- case 2:
- s_lower = 0;
- s_upper = s_hi_bit;
- s_bits = s_hi_bit + 1;
- break;
- case 3:
- s_lower = s_lo_bit;
- s_upper = s_hi_bit;
- s_bits = s_hi_bit - s_lo_bit + 1;
- break;
- }
- }
- notfirst = TRUE;
- if (s_bits > t_bits)
- {
- bits = t_bits - 1;
- if (ascending)
- {
- s_min = s_lower;
- s_max = s_lower + bits;
- }
- else
- {
- s_max = s_upper;
- s_min = s_upper - bits;
- }
- t_min = t_lower;
- }
- else
- {
- bits = s_bits - 1;
- if (ascending) t_min = t_lower;
- else t_min = t_upper - bits;
- s_min = s_lower;
- s_max = s_upper;
- }
- bits++;
- mask = (N_word) (~0L << s_min);
- mask &= (N_word) ~((~0L << s_max) << 1);
- if (s_min == t_min) target |= (source AND mask);
- else
- {
- if (s_min < t_min) target |= (source AND mask) << (t_min-s_min);
- else target |= (source AND mask) >> (s_min-t_min);
- }
- if (ascending)
- {
- s_lower += bits;
- t_lower += bits;
- }
- else
- {
- s_upper -= bits;
- t_upper -= bits;
- }
- s_bits -= bits;
- t_bits -= bits;
- }
- *(Z+size_(Z)-1) &= mask_(Z);
- }
-}
-
-
-wordptr BitVector_Interval_Substitute(wordptr X, wordptr Y,
- N_int Xoffset, N_int Xlength,
- N_int Yoffset, N_int Ylength)
-{
- N_word Xbits = bits_(X);
- N_word Ybits = bits_(Y);
- N_word limit;
- N_word diff;
-
- if ((Xoffset <= Xbits) and (Yoffset <= Ybits))
- {
- limit = Xoffset + Xlength;
- if (limit > Xbits)
- {
- limit = Xbits;
- Xlength = Xbits - Xoffset;
- }
- if ((Yoffset + Ylength) > Ybits)
- {
- Ylength = Ybits - Yoffset;
- }
- if (Xlength == Ylength)
- {
- if ((Ylength > 0) and ((X != Y) or (Xoffset != Yoffset)))
- {
- BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
- }
- }
- else /* Xlength != Ylength */
- {
- if (Xlength > Ylength)
- {
- diff = Xlength - Ylength;
- if (Ylength > 0) BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
- if (limit < Xbits) BitVector_Delete(X,Xoffset+Ylength,diff,FALSE);
- if ((X = BitVector_Resize(X,Xbits-diff)) == NULL) return(NULL);
- }
- else /* Ylength > Xlength ==> Ylength > 0 */
- {
- diff = Ylength - Xlength;
- if (X != Y)
- {
- if ((X = BitVector_Resize(X,Xbits+diff)) == NULL) return(NULL);
- if (limit < Xbits) BitVector_Insert(X,limit,diff,FALSE);
- BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
- }
- else /* in-place */
- {
- if ((Y = X = BitVector_Resize(X,Xbits+diff)) == NULL) return(NULL);
- if (limit >= Xbits)
- {
- BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
- }
- else /* limit < Xbits */
- {
- BitVector_Insert(X,limit,diff,FALSE);
- if ((Yoffset+Ylength) <= limit)
- {
- BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
- }
- else /* overlaps or lies above critical area */
- {
- if (limit <= Yoffset)
- {
- Yoffset += diff;
- BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
- }
- else /* Yoffset < limit */
- {
- Xlength = limit - Yoffset;
- BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Xlength);
- Yoffset = Xoffset + Ylength; /* = limit + diff */
- Xoffset += Xlength;
- Ylength -= Xlength;
- BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
- }
- }
- }
- }
- }
- }
- }
- return(X);
-}
-
-boolean BitVector_is_empty(wordptr addr) /* X == {} ? */
-{
- N_word size = size_(addr);
- boolean r = TRUE;
-
- if (size > 0)
- {
- *(addr+size-1) &= mask_(addr);
- while (r and (size-- > 0)) r = ( *addr++ == 0 );
- }
- return(r);
-}
-
-boolean BitVector_is_full(wordptr addr) /* X == ~{} ? */
-{
- N_word size = size_(addr);
- N_word mask = mask_(addr);
- boolean r = FALSE;
- wordptr last;
-
- if (size > 0)
- {
- r = TRUE;
- last = addr + size - 1;
- *last |= NOT mask;
- while (r and (size-- > 0)) r = ( NOT *addr++ == 0 );
- *last &= mask;
- }
- return(r);
-}
-
-boolean BitVector_equal(wordptr X, wordptr Y) /* X == Y ? */
-{
- N_word size = size_(X);
- N_word mask = mask_(X);
- boolean r = FALSE;
-
- if (bits_(X) == bits_(Y))
- {
- r = TRUE;
- if (size > 0)
- {
- *(X+size-1) &= mask;
- *(Y+size-1) &= mask;
- while (r and (size-- > 0)) r = (*X++ == *Y++);
- }
- }
- return(r);
-}
-
-Z_int BitVector_Lexicompare(wordptr X, wordptr Y) /* X <,=,> Y ? */
-{ /* unsigned */
- N_word bitsX = bits_(X);
- N_word bitsY = bits_(Y);
- N_word size = size_(X);
- boolean r = TRUE;
-
- if (bitsX == bitsY)
- {
- if (size > 0)
- {
- X += size;
- Y += size;
- while (r and (size-- > 0)) r = (*(--X) == *(--Y));
- }
- if (r) return((Z_int) 0);
- else
- {
- if (*X < *Y) return((Z_int) -1); else return((Z_int) 1);
- }
- }
- else
- {
- if (bitsX < bitsY) return((Z_int) -1); else return((Z_int) 1);
- }
-}
-
-Z_int BitVector_Compare(wordptr X, wordptr Y) /* X <,=,> Y ? */
-{ /* signed */
- N_word bitsX = bits_(X);
- N_word bitsY = bits_(Y);
- N_word size = size_(X);
- N_word mask = mask_(X);
- N_word sign;
- boolean r = TRUE;
-
- if (bitsX == bitsY)
- {
- if (size > 0)
- {
- X += size;
- Y += size;
- mask &= NOT (mask >> 1);
- if ((sign = (*(X-1) AND mask)) != (*(Y-1) AND mask))
- {
- if (sign) return((Z_int) -1); else return((Z_int) 1);
- }
- while (r and (size-- > 0)) r = (*(--X) == *(--Y));
- }
- if (r) return((Z_int) 0);
- else
- {
- if (*X < *Y) return((Z_int) -1); else return((Z_int) 1);
- }
- }
- else
- {
- if (bitsX < bitsY) return((Z_int) -1); else return((Z_int) 1);
- }
-}
-
-charptr BitVector_to_Hex(wordptr addr)
-{
- N_word bits = bits_(addr);
- N_word size = size_(addr);
- N_word value;
- N_word count;
- N_word digit;
- N_word length;
- charptr string;
-
- length = bits >> 2;
- if (bits AND 0x0003) length++;
- string = (charptr) yasm_xmalloc((size_t) (length+1));
- if (string == NULL) return(NULL);
- string += length;
- *string = (N_char) '\0';
- if (size > 0)
- {
- *(addr+size-1) &= mask_(addr);
- while ((size-- > 0) and (length > 0))
- {
- value = *addr++;
- count = BITS >> 2;
- while ((count-- > 0) and (length > 0))
- {
- digit = value AND 0x000F;
- if (digit > 9) digit += (N_word) 'A' - 10;
- else digit += (N_word) '0';
- *(--string) = (N_char) digit; length--;
- if ((count > 0) and (length > 0)) value >>= 4;
- }
- }
- }
- return(string);
-}
-
-ErrCode BitVector_from_Hex(wordptr addr, charptr string)
-{
- N_word size = size_(addr);
- N_word mask = mask_(addr);
- boolean ok = TRUE;
- size_t length;
- N_word value;
- N_word count;
- int digit;
-
- if (size > 0)
- {
- length = strlen((char *) string);
- string += length;
- while (size-- > 0)
- {
- value = 0;
- for ( count = 0; (ok and (length > 0) and (count < BITS)); count += 4 )
- {
- digit = (int) *(--string); length--;
- /* separate because toupper() is likely a macro! */
- digit = toupper(digit);
- if (digit == '_')
- count -= 4;
- else if ((ok = (isxdigit(digit) != 0)))
- {
- if (digit >= (int) 'A') digit -= (int) 'A' - 10;
- else digit -= (int) '0';
- value |= (((N_word) digit) << count);
- }
- }
- *addr++ = value;
- }
- *(--addr) &= mask;
- }
- if (ok) return(ErrCode_Ok);
- else return(ErrCode_Pars);
-}
-
-ErrCode BitVector_from_Oct(wordptr addr, charptr string)
-{
- N_word size = size_(addr);
- N_word mask = mask_(addr);
- boolean ok = TRUE;
- size_t length;
- N_word value;
- N_word value_fill = 0;
- N_word count;
- Z_word count_fill = 0;
- int digit = 0;
-
- if (size > 0)
- {
- length = strlen((char *) string);
- string += length;
- while (size-- > 0)
- {
- value = value_fill;
- for ( count = count_fill; (ok and (length > 0) and (count < BITS)); count += 3 )
- {
- digit = (int) *(--string); length--;
- if (digit == '_')
- count -= 3;
- else if ((ok = (isdigit(digit) && digit != '8' && digit != '9')) != 0)
- {
- digit -= (int) '0';
- value |= (((N_word) digit) << count);
- }
- }
- count_fill = (Z_word)count-(Z_word)BITS;
- if (count_fill > 0)
- value_fill = (((N_word) digit) >> (3-count_fill));
- else
- value_fill = 0;
- *addr++ = value;
- }
- *(--addr) &= mask;
- }
- if (ok) return(ErrCode_Ok);
- else return(ErrCode_Pars);
-}
-
-charptr BitVector_to_Bin(wordptr addr)
-{
- N_word size = size_(addr);
- N_word value;
- N_word count;
- N_word digit;
- N_word length;
- charptr string;
-
- length = bits_(addr);
- string = (charptr) yasm_xmalloc((size_t) (length+1));
- if (string == NULL) return(NULL);
- string += length;
- *string = (N_char) '\0';
- if (size > 0)
- {
- *(addr+size-1) &= mask_(addr);
- while (size-- > 0)
- {
- value = *addr++;
- count = BITS;
- if (count > length) count = length;
- while (count-- > 0)
- {
- digit = value AND 0x0001;
- digit += (N_word) '0';
- *(--string) = (N_char) digit; length--;
- if (count > 0) value >>= 1;
- }
- }
- }
- return(string);
-}
-
-ErrCode BitVector_from_Bin(wordptr addr, charptr string)
-{
- N_word size = size_(addr);
- N_word mask = mask_(addr);
- boolean ok = TRUE;
- size_t length;
- N_word value;
- N_word count;
- int digit;
-
- if (size > 0)
- {
- length = strlen((char *) string);
- string += length;
- while (size-- > 0)
- {
- value = 0;
- for ( count = 0; (ok and (length > 0) and (count < BITS)); count++ )
- {
- digit = (int) *(--string); length--;
- switch (digit)
- {
- case (int) '0':
- break;
- case (int) '1':
- value |= BITMASKTAB[count];
- break;
- case (int) '_':
- count--;
- break;
- default:
- ok = FALSE;
- break;
- }
- }
- *addr++ = value;
- }
- *(--addr) &= mask;
- }
- if (ok) return(ErrCode_Ok);
- else return(ErrCode_Pars);
-}
-
-charptr BitVector_to_Dec(wordptr addr)
-{
- N_word bits = bits_(addr);
- N_word length;
- N_word digits;
- N_word count;
- N_word q;
- N_word r;
- boolean loop;
- charptr result;
- charptr string;
- wordptr quot;
- wordptr rest;
- wordptr temp;
- wordptr base;
- Z_int sign;
-
- length = (N_word) (bits / 3.3); /* digits = bits * ln(2) / ln(10) */
- length += 2; /* compensate for truncating & provide space for minus sign */
- result = (charptr) yasm_xmalloc((size_t) (length+1)); /* remember the '\0'! */
- if (result == NULL) return(NULL);
- string = result;
- sign = BitVector_Sign(addr);
- if ((bits < 4) or (sign == 0))
- {
- if (bits > 0) digits = *addr; else digits = (N_word) 0;
- if (sign < 0) digits = ((N_word)(-((Z_word)digits))) AND mask_(addr);
- *string++ = (N_char) digits + (N_char) '0';
- digits = 1;
- }
- else
- {
- quot = BitVector_Create(bits,FALSE);
- if (quot == NULL)
- {
- BitVector_Dispose(result);
- return(NULL);
- }
- rest = BitVector_Create(bits,FALSE);
- if (rest == NULL)
- {
- BitVector_Dispose(result);
- BitVector_Destroy(quot);
- return(NULL);
- }
- temp = BitVector_Create(bits,FALSE);
- if (temp == NULL)
- {
- BitVector_Dispose(result);
- BitVector_Destroy(quot);
- BitVector_Destroy(rest);
- return(NULL);
- }
- base = BitVector_Create(bits,TRUE);
- if (base == NULL)
- {
- BitVector_Dispose(result);
- BitVector_Destroy(quot);
- BitVector_Destroy(rest);
- BitVector_Destroy(temp);
- return(NULL);
- }
- if (sign < 0) BitVector_Negate(quot,addr);
- else BitVector_Copy(quot,addr);
- digits = 0;
- *base = EXP10;
- loop = (bits >= BITS);
- do
- {
- if (loop)
- {
- BitVector_Copy(temp,quot);
- if (BitVector_Div_Pos(quot,temp,base,rest))
- {
- BitVector_Dispose(result); /* emergency exit */
- BitVector_Destroy(quot);
- BitVector_Destroy(rest); /* should never occur */
- BitVector_Destroy(temp); /* under normal operation */
- BitVector_Destroy(base);
- return(NULL);
- }
- loop = not BitVector_is_empty(quot);
- q = *rest;
- }
- else q = *quot;
- count = LOG10;
- while (((loop and (count-- > 0)) or ((not loop) and (q != 0))) and
- (digits < length))
- {
- if (q != 0)
- {
- BIT_VECTOR_DIGITIZE(N_word,q,r)
- }
- else r = (N_word) '0';
- *string++ = (N_char) r;
- digits++;
- }
- }
- while (loop and (digits < length));
- BitVector_Destroy(quot);
- BitVector_Destroy(rest);
- BitVector_Destroy(temp);
- BitVector_Destroy(base);
- }
- if ((sign < 0) and (digits < length))
- {
- *string++ = (N_char) '-';
- digits++;
- }
- *string = (N_char) '\0';
- BIT_VECTOR_reverse(result,digits);
- return(result);
-}
-
-struct BitVector_from_Dec_static_data {
- wordptr term;
- wordptr base;
- wordptr prod;
- wordptr rank;
- wordptr temp;
-};
-
-BitVector_from_Dec_static_data *BitVector_from_Dec_static_Boot(N_word bits)
-{
- BitVector_from_Dec_static_data *data;
-
- data = yasm_xmalloc(sizeof(BitVector_from_Dec_static_data));
-
- if (bits > 0)
- {
- data->term = BitVector_Create(BITS,FALSE);
- data->base = BitVector_Create(BITS,FALSE);
- data->prod = BitVector_Create(bits,FALSE);
- data->rank = BitVector_Create(bits,FALSE);
- data->temp = BitVector_Create(bits,FALSE);
- } else {
- data->term = NULL;
- data->base = NULL;
- data->prod = NULL;
- data->rank = NULL;
- data->temp = NULL;
- }
- return data;
-}
-
-void BitVector_from_Dec_static_Shutdown(BitVector_from_Dec_static_data *data)
-{
- if (data) {
- BitVector_Destroy(data->term);
- BitVector_Destroy(data->base);
- BitVector_Destroy(data->prod);
- BitVector_Destroy(data->rank);
- BitVector_Destroy(data->temp);
- }
- yasm_xfree(data);
-}
-
-ErrCode BitVector_from_Dec_static(BitVector_from_Dec_static_data *data,
- wordptr addr, charptr string)
-{
- ErrCode error = ErrCode_Ok;
- N_word bits = bits_(addr);
- N_word mask = mask_(addr);
- boolean init = (bits > BITS);
- boolean minus;
- boolean shift;
- boolean carry;
- wordptr term;
- wordptr base;
- wordptr prod;
- wordptr rank;
- wordptr temp;
- N_word accu;
- N_word powr;
- N_word count;
- size_t length;
- int digit;
-
- if (bits > 0)
- {
- term = data->term;
- base = data->base;
- prod = data->prod;
- rank = data->rank;
- temp = data->temp;
-
- length = strlen((char *) string);
- if (length == 0) return(ErrCode_Pars);
- digit = (int) *string;
- if ((minus = (digit == (int) '-')) or
- (digit == (int) '+'))
- {
- string++;
- if (--length == 0) return(ErrCode_Pars);
- }
- string += length;
- if (init)
- {
- BitVector_Empty(prod);
- BitVector_Empty(rank);
- }
- BitVector_Empty(addr);
- *base = EXP10;
- shift = FALSE;
- while ((not error) and (length > 0))
- {
- accu = 0;
- powr = 1;
- count = LOG10;
- while ((not error) and (length > 0) and (count-- > 0))
- {
- digit = (int) *(--string); length--;
- /* separate because isdigit() is likely a macro! */
- if (isdigit(digit) != 0)
- {
- accu += ((N_word) digit - (N_word) '0') * powr;
- powr *= 10;
- }
- else error = ErrCode_Pars;
- }
- if (not error)
- {
- if (shift)
- {
- *term = accu;
- BitVector_Copy(temp,rank);
- error = BitVector_Mul_Pos(prod,temp,term,FALSE);
- }
- else
- {
- *prod = accu;
- if ((not init) and ((accu AND NOT mask) != 0)) error = ErrCode_Ovfl;
- }
- if (not error)
- {
- carry = FALSE;
- BitVector_compute(addr,addr,prod,FALSE,&carry);
- /* ignores sign change (= overflow) but not */
- /* numbers too large (= carry) for resulting bit vector */
- if (carry) error = ErrCode_Ovfl;
- else
- {
- if (length > 0)
- {
- if (shift)
- {
- BitVector_Copy(temp,rank);
- error = BitVector_Mul_Pos(rank,temp,base,FALSE);
- }
- else
- {
- *rank = *base;
- shift = TRUE;
- }
- }
- }
- }
- }
- }
- if (not error and minus)
- {
- BitVector_Negate(addr,addr);
- if ((*(addr + size_(addr) - 1) AND mask AND NOT (mask >> 1)) == 0)
- error = ErrCode_Ovfl;
- }
- }
- return(error);
-}
-
-ErrCode BitVector_from_Dec(wordptr addr, charptr string)
-{
- ErrCode error = ErrCode_Ok;
- N_word bits = bits_(addr);
- N_word mask = mask_(addr);
- boolean init = (bits > BITS);
- boolean minus;
- boolean shift;
- boolean carry;
- wordptr term;
- wordptr base;
- wordptr prod;
- wordptr rank;
- wordptr temp;
- N_word accu;
- N_word powr;
- N_word count;
- size_t length;
- int digit;
-
- if (bits > 0)
- {
- length = strlen((char *) string);
- if (length == 0) return(ErrCode_Pars);
- digit = (int) *string;
- if ((minus = (digit == (int) '-')) or
- (digit == (int) '+'))
- {
- string++;
- if (--length == 0) return(ErrCode_Pars);
- }
- string += length;
- term = BitVector_Create(BITS,FALSE);
- if (term == NULL)
- {
- return(ErrCode_Null);
- }
- base = BitVector_Create(BITS,FALSE);
- if (base == NULL)
- {
- BitVector_Destroy(term);
- return(ErrCode_Null);
- }
- prod = BitVector_Create(bits,init);
- if (prod == NULL)
- {
- BitVector_Destroy(term);
- BitVector_Destroy(base);
- return(ErrCode_Null);
- }
- rank = BitVector_Create(bits,init);
- if (rank == NULL)
- {
- BitVector_Destroy(term);
- BitVector_Destroy(base);
- BitVector_Destroy(prod);
- return(ErrCode_Null);
- }
- temp = BitVector_Create(bits,FALSE);
- if (temp == NULL)
- {
- BitVector_Destroy(term);
- BitVector_Destroy(base);
- BitVector_Destroy(prod);
- BitVector_Destroy(rank);
- return(ErrCode_Null);
- }
- BitVector_Empty(addr);
- *base = EXP10;
- shift = FALSE;
- while ((not error) and (length > 0))
- {
- accu = 0;
- powr = 1;
- count = LOG10;
- while ((not error) and (length > 0) and (count-- > 0))
- {
- digit = (int) *(--string); length--;
- /* separate because isdigit() is likely a macro! */
- if (isdigit(digit) != 0)
- {
- accu += ((N_word) digit - (N_word) '0') * powr;
- powr *= 10;
- }
- else error = ErrCode_Pars;
- }
- if (not error)
- {
- if (shift)
- {
- *term = accu;
- BitVector_Copy(temp,rank);
- error = BitVector_Mul_Pos(prod,temp,term,FALSE);
- }
- else
- {
- *prod = accu;
- if ((not init) and ((accu AND NOT mask) != 0)) error = ErrCode_Ovfl;
- }
- if (not error)
- {
- carry = FALSE;
- BitVector_compute(addr,addr,prod,FALSE,&carry);
- /* ignores sign change (= overflow) but not */
- /* numbers too large (= carry) for resulting bit vector */
- if (carry) error = ErrCode_Ovfl;
- else
- {
- if (length > 0)
- {
- if (shift)
- {
- BitVector_Copy(temp,rank);
- error = BitVector_Mul_Pos(rank,temp,base,FALSE);
- }
- else
- {
- *rank = *base;
- shift = TRUE;
- }
- }
- }
- }
- }
- }
- BitVector_Destroy(term);
- BitVector_Destroy(base);
- BitVector_Destroy(prod);
- BitVector_Destroy(rank);
- BitVector_Destroy(temp);
- if (not error and minus)
- {
- BitVector_Negate(addr,addr);
- if ((*(addr + size_(addr) - 1) AND mask AND NOT (mask >> 1)) == 0)
- error = ErrCode_Ovfl;
- }
- }
- return(error);
-}
-
-charptr BitVector_to_Enum(wordptr addr)
-{
- N_word bits = bits_(addr);
- N_word sample;
- N_word length;
- N_word digits;
- N_word factor;
- N_word power;
- N_word start;
- N_word min;
- N_word max;
- charptr string;
- charptr target;
- boolean comma;
-
- if (bits > 0)
- {
- sample = bits - 1; /* greatest possible index */
- length = 2; /* account for index 0 and terminating '\0' */
- digits = 1; /* account for intervening dashes and commas */
- factor = 1;
- power = 10;
- while (sample >= (power-1))
- {
- length += ++digits * factor * 6; /* 9,90,900,9000,... (9*2/3 = 6) */
- factor = power;
- power *= 10;
- }
- if (sample > --factor)
- {
- sample -= factor;
- factor = (N_word) ( sample / 3 );
- factor = (factor << 1) + (sample - (factor * 3));
- length += ++digits * factor;
- }
- }
- else length = 1;
- string = (charptr) yasm_xmalloc((size_t) length);
- if (string == NULL) return(NULL);
- start = 0;
- comma = FALSE;
- target = string;
- while ((start < bits) and BitVector_interval_scan_inc(addr,start,&min,&max))
- {
- start = max + 2;
- if (comma) *target++ = (N_char) ',';
- if (min == max)
- {
- target += BIT_VECTOR_int2str(target,min);
- }
- else
- {
- if (min+1 == max)
- {
- target += BIT_VECTOR_int2str(target,min);
- *target++ = (N_char) ',';
- target += BIT_VECTOR_int2str(target,max);
- }
- else
- {
- target += BIT_VECTOR_int2str(target,min);
- *target++ = (N_char) '-';
- target += BIT_VECTOR_int2str(target,max);
- }
- }
- comma = TRUE;
- }
- *target = (N_char) '\0';
- return(string);
-}
-
-ErrCode BitVector_from_Enum(wordptr addr, charptr string)
-{
- ErrCode error = ErrCode_Ok;
- N_word bits = bits_(addr);
- N_word state = 1;
- N_word token;
- N_word indx = 0; /* silence compiler warning */
- N_word start = 0; /* silence compiler warning */
-
- if (bits > 0)
- {
- BitVector_Empty(addr);
- while ((not error) and (state != 0))
- {
- token = (N_word) *string;
- /* separate because isdigit() is likely a macro! */
- if (isdigit((int)token) != 0)
- {
- string += BIT_VECTOR_str2int(string,&indx);
- if (indx < bits) token = (N_word) '0';
- else error = ErrCode_Indx;
- }
- else string++;
- if (not error)
- switch (state)
- {
- case 1:
- switch (token)
- {
- case (N_word) '0':
- state = 2;
- break;
- case (N_word) '\0':
- state = 0;
- break;
- default:
- error = ErrCode_Pars;
- break;
- }
- break;
- case 2:
- switch (token)
- {
- case (N_word) '-':
- start = indx;
- state = 3;
- break;
- case (N_word) ',':
- BIT_VECTOR_SET_BIT(addr,indx)
- state = 5;
- break;
- case (N_word) '\0':
- BIT_VECTOR_SET_BIT(addr,indx)
- state = 0;
- break;
- default:
- error = ErrCode_Pars;
- break;
- }
- break;
- case 3:
- switch (token)
- {
- case (N_word) '0':
- if (start < indx)
- BitVector_Interval_Fill(addr,start,indx);
- else if (start == indx)
- BIT_VECTOR_SET_BIT(addr,indx)
- else error = ErrCode_Ordr;
- state = 4;
- break;
- default:
- error = ErrCode_Pars;
- break;
- }
- break;
- case 4:
- switch (token)
- {
- case (N_word) ',':
- state = 5;
- break;
- case (N_word) '\0':
- state = 0;
- break;
- default:
- error = ErrCode_Pars;
- break;
- }
- break;
- case 5:
- switch (token)
- {
- case (N_word) '0':
- state = 2;
- break;
- default:
- error = ErrCode_Pars;
- break;
- }
- break;
- }
- }
- }
- return(error);
-}
-
-void BitVector_Bit_Off(wordptr addr, N_int indx) /* X = X \ {x} */
-{
- if (indx < bits_(addr)) BIT_VECTOR_CLR_BIT(addr,indx)
-}
-
-void BitVector_Bit_On(wordptr addr, N_int indx) /* X = X + {x} */
-{
- if (indx < bits_(addr)) BIT_VECTOR_SET_BIT(addr,indx)
-}
-
-boolean BitVector_bit_flip(wordptr addr, N_int indx) /* X=(X+{x})\(X*{x}) */
-{
- N_word mask;
-
- if (indx < bits_(addr)) return( BIT_VECTOR_FLP_BIT(addr,indx,mask) );
- else return( FALSE );
-}
-
-boolean BitVector_bit_test(wordptr addr, N_int indx) /* {x} in X ? */
-{
- if (indx < bits_(addr)) return( BIT_VECTOR_TST_BIT(addr,indx) );
- else return( FALSE );
-}
-
-void BitVector_Bit_Copy(wordptr addr, N_int indx, boolean bit)
-{
- if (indx < bits_(addr))
- {
- if (bit) BIT_VECTOR_SET_BIT(addr,indx)
- else BIT_VECTOR_CLR_BIT(addr,indx)
- }
-}
-
-void BitVector_LSB(wordptr addr, boolean bit)
-{
- if (bits_(addr) > 0)
- {
- if (bit) *addr |= LSB;
- else *addr &= NOT LSB;
- }
-}
-
-void BitVector_MSB(wordptr addr, boolean bit)
-{
- N_word size = size_(addr);
- N_word mask = mask_(addr);
-
- if (size-- > 0)
- {
- if (bit) *(addr+size) |= mask AND NOT (mask >> 1);
- else *(addr+size) &= NOT mask OR (mask >> 1);
- }
-}
-
-boolean BitVector_lsb_(wordptr addr)
-{
- if (size_(addr) > 0) return( (*addr AND LSB) != 0 );
- else return( FALSE );
-}
-
-boolean BitVector_msb_(wordptr addr)
-{
- N_word size = size_(addr);
- N_word mask = mask_(addr);
-
- if (size-- > 0)
- return( (*(addr+size) AND (mask AND NOT (mask >> 1))) != 0 );
- else
- return( FALSE );
-}
-
-boolean BitVector_rotate_left(wordptr addr)
-{
- N_word size = size_(addr);
- N_word mask = mask_(addr);
- N_word msb;
- boolean carry_in;
- boolean carry_out = FALSE;
-
- if (size > 0)
- {
- msb = mask AND NOT (mask >> 1);
- carry_in = ((*(addr+size-1) AND msb) != 0);
- while (size-- > 1)
- {
- carry_out = ((*addr AND MSB) != 0);
- *addr <<= 1;
- if (carry_in) *addr |= LSB;
- carry_in = carry_out;
- addr++;
- }
- carry_out = ((*addr AND msb) != 0);
- *addr <<= 1;
- if (carry_in) *addr |= LSB;
- *addr &= mask;
- }
- return(carry_out);
-}
-
-boolean BitVector_rotate_right(wordptr addr)
-{
- N_word size = size_(addr);
- N_word mask = mask_(addr);
- N_word msb;
- boolean carry_in;
- boolean carry_out = FALSE;
-
- if (size > 0)
- {
- msb = mask AND NOT (mask >> 1);
- carry_in = ((*addr AND LSB) != 0);
- addr += size-1;
- *addr &= mask;
- carry_out = ((*addr AND LSB) != 0);
- *addr >>= 1;
- if (carry_in) *addr |= msb;
- carry_in = carry_out;
- addr--;
- size--;
- while (size-- > 0)
- {
- carry_out = ((*addr AND LSB) != 0);
- *addr >>= 1;
- if (carry_in) *addr |= MSB;
- carry_in = carry_out;
- addr--;
- }
- }
- return(carry_out);
-}
-
-boolean BitVector_shift_left(wordptr addr, boolean carry_in)
-{
- N_word size = size_(addr);
- N_word mask = mask_(addr);
- N_word msb;
- boolean carry_out = carry_in;
-
- if (size > 0)
- {
- msb = mask AND NOT (mask >> 1);
- while (size-- > 1)
- {
- carry_out = ((*addr AND MSB) != 0);
- *addr <<= 1;
- if (carry_in) *addr |= LSB;
- carry_in = carry_out;
- addr++;
- }
- carry_out = ((*addr AND msb) != 0);
- *addr <<= 1;
- if (carry_in) *addr |= LSB;
- *addr &= mask;
- }
- return(carry_out);
-}
-
-boolean BitVector_shift_right(wordptr addr, boolean carry_in)
-{
- N_word size = size_(addr);
- N_word mask = mask_(addr);
- N_word msb;
- boolean carry_out = carry_in;
-
- if (size > 0)
- {
- msb = mask AND NOT (mask >> 1);
- addr += size-1;
- *addr &= mask;
- carry_out = ((*addr AND LSB) != 0);
- *addr >>= 1;
- if (carry_in) *addr |= msb;
- carry_in = carry_out;
- addr--;
- size--;
- while (size-- > 0)
- {
- carry_out = ((*addr AND LSB) != 0);
- *addr >>= 1;
- if (carry_in) *addr |= MSB;
- carry_in = carry_out;
- addr--;
- }
- }
- return(carry_out);
-}
-
-void BitVector_Move_Left(wordptr addr, N_int bits)
-{
- N_word count;
- N_word words;
-
- if (bits > 0)
- {
- count = bits AND MODMASK;
- words = bits >> LOGBITS;
- if (bits >= bits_(addr)) BitVector_Empty(addr);
- else
- {
- while (count-- > 0) BitVector_shift_left(addr,0);
- BitVector_Word_Insert(addr,0,words,TRUE);
- }
- }
-}
-
-void BitVector_Move_Right(wordptr addr, N_int bits)
-{
- N_word count;
- N_word words;
-
- if (bits > 0)
- {
- count = bits AND MODMASK;
- words = bits >> LOGBITS;
- if (bits >= bits_(addr)) BitVector_Empty(addr);
- else
- {
- while (count-- > 0) BitVector_shift_right(addr,0);
- BitVector_Word_Delete(addr,0,words,TRUE);
- }
- }
-}
-
-void BitVector_Insert(wordptr addr, N_int offset, N_int count, boolean clear)
-{
- N_word bits = bits_(addr);
- N_word last;
-
- if ((count > 0) and (offset < bits))
- {
- last = offset + count;
- if (last < bits)
- {
- BitVector_Interval_Copy(addr,addr,last,offset,(bits-last));
- }
- else last = bits;
- if (clear) BitVector_Interval_Empty(addr,offset,(last-1));
- }
-}
-
-void BitVector_Delete(wordptr addr, N_int offset, N_int count, boolean clear)
-{
- N_word bits = bits_(addr);
- N_word last;
-
- if ((count > 0) and (offset < bits))
- {
- last = offset + count;
- if (last < bits)
- {
- BitVector_Interval_Copy(addr,addr,offset,last,(bits-last));
- }
- else count = bits - offset;
- if (clear) BitVector_Interval_Empty(addr,(bits-count),(bits-1));
- }
-}
-
-boolean BitVector_increment(wordptr addr) /* X++ */
-{
- N_word size = size_(addr);
- N_word mask = mask_(addr);
- wordptr last = addr + size - 1;
- boolean carry = TRUE;
-
- if (size > 0)
- {
- *last |= NOT mask;
- while (carry and (size-- > 0))
- {
- carry = (++(*addr++) == 0);
- }
- *last &= mask;
- }
- return(carry);
-}
-
-boolean BitVector_decrement(wordptr addr) /* X-- */
-{
- N_word size = size_(addr);
- N_word mask = mask_(addr);
- wordptr last = addr + size - 1;
- boolean carry = TRUE;
-
- if (size > 0)
- {
- *last &= mask;
- while (carry and (size-- > 0))
- {
- carry = (*addr == 0);
- --(*addr++);
- }
- *last &= mask;
- }
- return(carry);
-}
-
-boolean BitVector_compute(wordptr X, wordptr Y, wordptr Z, boolean minus, boolean *carry)
-{
- N_word size = size_(X);
- N_word mask = mask_(X);
- N_word vv = 0;
- N_word cc;
- N_word mm;
- N_word yy;
- N_word zz;
- N_word lo;
- N_word hi;
-
- if (size > 0)
- {
- if (minus) cc = (*carry == 0);
- else cc = (*carry != 0);
- /* deal with (size-1) least significant full words first: */
- while (--size > 0)
- {
- yy = *Y++;
- if (minus) zz = (N_word) NOT ( Z ? *Z++ : 0 );
- else zz = (N_word) ( Z ? *Z++ : 0 );
- lo = (yy AND LSB) + (zz AND LSB) + cc;
- hi = (yy >> 1) + (zz >> 1) + (lo >> 1);
- cc = ((hi AND MSB) != 0);
- *X++ = (hi << 1) OR (lo AND LSB);
- }
- /* deal with most significant word (may be used only partially): */
- yy = *Y AND mask;
- if (minus) zz = (N_word) NOT ( Z ? *Z : 0 );
- else zz = (N_word) ( Z ? *Z : 0 );
- zz &= mask;
- if (mask == LSB) /* special case, only one bit used */
- {
- vv = cc;
- lo = yy + zz + cc;
- cc = (lo >> 1);
- vv ^= cc;
- *X = lo AND LSB;
- }
- else
- {
- if (NOT mask) /* not all bits are used, but more than one */
- {
- mm = (mask >> 1);
- vv = (yy AND mm) + (zz AND mm) + cc;
- mm = mask AND NOT mm;
- lo = yy + zz + cc;
- cc = (lo >> 1);
- vv ^= cc;
- vv &= mm;
- cc &= mm;
- *X = lo AND mask;
- }
- else /* other special case, all bits are used */
- {
- mm = NOT MSB;
- lo = (yy AND mm) + (zz AND mm) + cc;
- vv = lo AND MSB;
- hi = ((yy AND MSB) >> 1) + ((zz AND MSB) >> 1) + (vv >> 1);
- cc = hi AND MSB;
- vv ^= cc;
- *X = (hi << 1) OR (lo AND mm);
- }
- }
- if (minus) *carry = (cc == 0);
- else *carry = (cc != 0);
- }
- return(vv != 0);
-}
-
-boolean BitVector_add(wordptr X, wordptr Y, wordptr Z, boolean *carry)
-{
- return(BitVector_compute(X,Y,Z,FALSE,carry));
-}
-
-boolean BitVector_sub(wordptr X, wordptr Y, wordptr Z, boolean *carry)
-{
- return(BitVector_compute(X,Y,Z,TRUE,carry));
-}
-
-boolean BitVector_inc(wordptr X, wordptr Y)
-{
- boolean carry = TRUE;
-
- return(BitVector_compute(X,Y,NULL,FALSE,&carry));
-}
-
-boolean BitVector_dec(wordptr X, wordptr Y)
-{
- boolean carry = TRUE;
-
- return(BitVector_compute(X,Y,NULL,TRUE,&carry));
-}
-
-void BitVector_Negate(wordptr X, wordptr Y)
-{
- N_word size = size_(X);
- N_word mask = mask_(X);
- boolean carry = TRUE;
-
- if (size > 0)
- {
- while (size-- > 0)
- {
- *X = NOT *Y++;
- if (carry)
- {
- carry = (++(*X) == 0);
- }
- X++;
- }
- *(--X) &= mask;
- }
-}
-
-void BitVector_Absolute(wordptr X, wordptr Y)
-{
- N_word size = size_(Y);
- N_word mask = mask_(Y);
-
- if (size > 0)
- {
- if (*(Y+size-1) AND (mask AND NOT (mask >> 1))) BitVector_Negate(X,Y);
- else BitVector_Copy(X,Y);
- }
-}
-
-Z_int BitVector_Sign(wordptr addr)
-{
- N_word size = size_(addr);
- N_word mask = mask_(addr);
- wordptr last = addr + size - 1;
- boolean r = TRUE;
-
- if (size > 0)
- {
- *last &= mask;
- while (r and (size-- > 0)) r = ( *addr++ == 0 );
- }
- if (r) return((Z_int) 0);
- else
- {
- if (*last AND (mask AND NOT (mask >> 1))) return((Z_int) -1);
- else return((Z_int) 1);
- }
-}
-
-ErrCode BitVector_Mul_Pos(wordptr X, wordptr Y, wordptr Z, boolean strict)
-{
- N_word mask;
- N_word limit;
- N_word count;
- Z_long last;
- wordptr sign;
- boolean carry;
- boolean overflow;
- boolean ok = TRUE;
-
- /*
- Requirements:
- - X, Y and Z must be distinct
- - X and Y must have equal sizes (whereas Z may be any size!)
- - Z should always contain the SMALLER of the two factors Y and Z
- Constraints:
- - The contents of Y (and of X, of course) are destroyed
- (only Z is preserved!)
- */
-
- if ((X == Y) or (X == Z) or (Y == Z)) return(ErrCode_Same);
- if (bits_(X) != bits_(Y)) return(ErrCode_Size);
- BitVector_Empty(X);
- if (BitVector_is_empty(Y)) return(ErrCode_Ok); /* exit also taken if bits_(Y)==0 */
- if ((last = Set_Max(Z)) < 0L) return(ErrCode_Ok);
- limit = (N_word) last;
- sign = Y + size_(Y) - 1;
- mask = mask_(Y);
- *sign &= mask;
- mask &= NOT (mask >> 1);
- for ( count = 0; (ok and (count <= limit)); count++ )
- {
- if ( BIT_VECTOR_TST_BIT(Z,count) )
- {
- carry = false;
- overflow = BitVector_compute(X,X,Y,false,&carry);
- if (strict) ok = not (carry or overflow);
- else ok = not carry;
- }
- if (ok and (count < limit))
- {
- carry = BitVector_shift_left(Y,0);
- if (strict)
- {
- overflow = ((*sign AND mask) != 0);
- ok = not (carry or overflow);
- }
- else ok = not carry;
- }
- }
- if (ok) return(ErrCode_Ok); else return(ErrCode_Ovfl);
-}
-
-ErrCode BitVector_Multiply(wordptr X, wordptr Y, wordptr Z)
-{
- ErrCode error = ErrCode_Ok;
- N_word bit_x = bits_(X);
- N_word bit_y = bits_(Y);
- N_word bit_z = bits_(Z);
- N_word size;
- N_word mask;
- N_word msb;
- wordptr ptr_y;
- wordptr ptr_z;
- boolean sgn_x;
- boolean sgn_y;
- boolean sgn_z;
- boolean zero;
- wordptr A;
- wordptr B;
-
- /*
- Requirements:
- - Y and Z must have equal sizes
- - X must have at least the same size as Y and Z but may be larger (!)
- Features:
- - The contents of Y and Z are preserved
- - X may be identical with Y or Z (or both!)
- (in-place multiplication is possible!)
- */
-
- if ((bit_y != bit_z) or (bit_x < bit_y)) return(ErrCode_Size);
- if (BitVector_is_empty(Y) or BitVector_is_empty(Z))
- {
- BitVector_Empty(X);
- }
- else
- {
- A = BitVector_Create(bit_y,FALSE);
- if (A == NULL) return(ErrCode_Null);
- B = BitVector_Create(bit_z,FALSE);
- if (B == NULL) { BitVector_Destroy(A); return(ErrCode_Null); }
- size = size_(Y);
- mask = mask_(Y);
- msb = (mask AND NOT (mask >> 1));
- sgn_y = (((*(Y+size-1) &= mask) AND msb) != 0);
- sgn_z = (((*(Z+size-1) &= mask) AND msb) != 0);
- sgn_x = sgn_y XOR sgn_z;
- if (sgn_y) BitVector_Negate(A,Y); else BitVector_Copy(A,Y);
- if (sgn_z) BitVector_Negate(B,Z); else BitVector_Copy(B,Z);
- ptr_y = A + size;
- ptr_z = B + size;
- zero = TRUE;
- while (zero and (size-- > 0))
- {
- zero &= (*(--ptr_y) == 0);
- zero &= (*(--ptr_z) == 0);
- }
- if (*ptr_y > *ptr_z)
- {
- if (bit_x > bit_y)
- {
- A = BitVector_Resize(A,bit_x);
- if (A == NULL) { BitVector_Destroy(B); return(ErrCode_Null); }
- }
- error = BitVector_Mul_Pos(X,A,B,TRUE);
- }
- else
- {
- if (bit_x > bit_z)
- {
- B = BitVector_Resize(B,bit_x);
- if (B == NULL) { BitVector_Destroy(A); return(ErrCode_Null); }
- }
- error = BitVector_Mul_Pos(X,B,A,TRUE);
- }
- if ((not error) and sgn_x) BitVector_Negate(X,X);
- BitVector_Destroy(A);
- BitVector_Destroy(B);
- }
- return(error);
-}
-
-ErrCode BitVector_Div_Pos(wordptr Q, wordptr X, wordptr Y, wordptr R)
-{
- N_word bits = bits_(Q);
- N_word mask;
- wordptr addr;
- Z_long last;
- boolean flag;
- boolean copy = FALSE; /* flags whether valid rest is in R (0) or X (1) */
-
- /*
- Requirements:
- - All bit vectors must have equal sizes
- - Q, X, Y and R must all be distinct bit vectors
- - Y must be non-zero (of course!)
- Constraints:
- - The contents of X (and Q and R, of course) are destroyed
- (only Y is preserved!)
- */
-
- if ((bits != bits_(X)) or (bits != bits_(Y)) or (bits != bits_(R)))
- return(ErrCode_Size);
- if ((Q == X) or (Q == Y) or (Q == R) or (X == Y) or (X == R) or (Y == R))
- return(ErrCode_Same);
- if (BitVector_is_empty(Y))
- return(ErrCode_Zero);
-
- BitVector_Empty(R);
- BitVector_Copy(Q,X);
- if ((last = Set_Max(Q)) < 0L) return(ErrCode_Ok);
- bits = (N_word) ++last;
- while (bits-- > 0)
- {
- addr = Q + (bits >> LOGBITS);
- mask = BITMASKTAB[bits AND MODMASK];
- flag = ((*addr AND mask) != 0);
- if (copy)
- {
- BitVector_shift_left(X,flag);
- flag = FALSE;
- BitVector_compute(R,X,Y,TRUE,&flag);
- }
- else
- {
- BitVector_shift_left(R,flag);
- flag = FALSE;
- BitVector_compute(X,R,Y,TRUE,&flag);
- }
- if (flag) *addr &= NOT mask;
- else
- {
- *addr |= mask;
- copy = not copy;
- }
- }
- if (copy) BitVector_Copy(R,X);
- return(ErrCode_Ok);
-}
-
-ErrCode BitVector_Divide(wordptr Q, wordptr X, wordptr Y, wordptr R)
-{
- ErrCode error = ErrCode_Ok;
- N_word bits = bits_(Q);
- N_word size = size_(Q);
- N_word mask = mask_(Q);
- N_word msb = (mask AND NOT (mask >> 1));
- boolean sgn_q;
- boolean sgn_x;
- boolean sgn_y;
- wordptr A;
- wordptr B;
-
- /*
- Requirements:
- - All bit vectors must have equal sizes
- - Q and R must be two distinct bit vectors
- - Y must be non-zero (of course!)
- Features:
- - The contents of X and Y are preserved
- - Q may be identical with X or Y (or both)
- (in-place division is possible!)
- - R may be identical with X or Y (or both)
- (but not identical with Q!)
- */
-
- if ((bits != bits_(X)) or (bits != bits_(Y)) or (bits != bits_(R)))
- return(ErrCode_Size);
- if (Q == R)
- return(ErrCode_Same);
- if (BitVector_is_empty(Y))
- return(ErrCode_Zero);
-
- if (BitVector_is_empty(X))
- {
- BitVector_Empty(Q);
- BitVector_Empty(R);
- }
- else
- {
- A = BitVector_Create(bits,FALSE);
- if (A == NULL) return(ErrCode_Null);
- B = BitVector_Create(bits,FALSE);
- if (B == NULL) { BitVector_Destroy(A); return(ErrCode_Null); }
- size--;
- sgn_x = (((*(X+size) &= mask) AND msb) != 0);
- sgn_y = (((*(Y+size) &= mask) AND msb) != 0);
- sgn_q = sgn_x XOR sgn_y;
- if (sgn_x) BitVector_Negate(A,X); else BitVector_Copy(A,X);
- if (sgn_y) BitVector_Negate(B,Y); else BitVector_Copy(B,Y);
- if (not (error = BitVector_Div_Pos(Q,A,B,R)))
- {
- if (sgn_q) BitVector_Negate(Q,Q);
- if (sgn_x) BitVector_Negate(R,R);
- }
- BitVector_Destroy(A);
- BitVector_Destroy(B);
- }
- return(error);
-}
-
-ErrCode BitVector_GCD(wordptr X, wordptr Y, wordptr Z)
-{
- ErrCode error = ErrCode_Ok;
- N_word bits = bits_(X);
- N_word size = size_(X);
- N_word mask = mask_(X);
- N_word msb = (mask AND NOT (mask >> 1));
- boolean sgn_a;
- boolean sgn_b;
- boolean sgn_r;
- wordptr Q;
- wordptr R;
- wordptr A;
- wordptr B;
- wordptr T;
-
- /*
- Requirements:
- - All bit vectors must have equal sizes
- Features:
- - The contents of Y and Z are preserved
- - X may be identical with Y or Z (or both)
- (in-place is possible!)
- - GCD(0,z) == GCD(z,0) == z
- - negative values are handled correctly
- */
-
- if ((bits != bits_(Y)) or (bits != bits_(Z))) return(ErrCode_Size);
- if (BitVector_is_empty(Y))
- {
- if (X != Z) BitVector_Copy(X,Z);
- return(ErrCode_Ok);
- }
- if (BitVector_is_empty(Z))
- {
- if (X != Y) BitVector_Copy(X,Y);
- return(ErrCode_Ok);
- }
- Q = BitVector_Create(bits,false);
- if (Q == NULL)
- {
- return(ErrCode_Null);
- }
- R = BitVector_Create(bits,FALSE);
- if (R == NULL)
- {
- BitVector_Destroy(Q);
- return(ErrCode_Null);
- }
- A = BitVector_Create(bits,FALSE);
- if (A == NULL)
- {
- BitVector_Destroy(Q);
- BitVector_Destroy(R);
- return(ErrCode_Null);
- }
- B = BitVector_Create(bits,FALSE);
- if (B == NULL)
- {
- BitVector_Destroy(Q);
- BitVector_Destroy(R);
- BitVector_Destroy(A);
- return(ErrCode_Null);
- }
- size--;
- sgn_a = (((*(Y+size) &= mask) AND msb) != 0);
- sgn_b = (((*(Z+size) &= mask) AND msb) != 0);
- if (sgn_a) BitVector_Negate(A,Y); else BitVector_Copy(A,Y);
- if (sgn_b) BitVector_Negate(B,Z); else BitVector_Copy(B,Z);
- while (not error)
- {
- if (not (error = BitVector_Div_Pos(Q,A,B,R)))
- {
- if (BitVector_is_empty(R)) break;
- T = A; sgn_r = sgn_a;
- A = B; sgn_a = sgn_b;
- B = R; sgn_b = sgn_r;
- R = T;
- }
- }
- if (not error)
- {
- if (sgn_b) BitVector_Negate(X,B); else BitVector_Copy(X,B);
- }
- BitVector_Destroy(Q);
- BitVector_Destroy(R);
- BitVector_Destroy(A);
- BitVector_Destroy(B);
- return(error);
-}
-
-ErrCode BitVector_GCD2(wordptr U, wordptr V, wordptr W, wordptr X, wordptr Y)
-{
- ErrCode error = ErrCode_Ok;
- N_word bits = bits_(U);
- N_word size = size_(U);
- N_word mask = mask_(U);
- N_word msb = (mask AND NOT (mask >> 1));
- boolean minus;
- boolean carry;
- boolean sgn_q;
- boolean sgn_r;
- boolean sgn_a;
- boolean sgn_b;
- boolean sgn_x;
- boolean sgn_y;
- listptr L;
- wordptr Q;
- wordptr R;
- wordptr A;
- wordptr B;
- wordptr T;
- wordptr X1;
- wordptr X2;
- wordptr X3;
- wordptr Y1;
- wordptr Y2;
- wordptr Y3;
- wordptr Z;
-
- /*
- Requirements:
- - All bit vectors must have equal sizes
- - U, V, and W must all be distinct bit vectors
- Features:
- - The contents of X and Y are preserved
- - U, V and W may be identical with X or Y (or both,
- provided that U, V and W are mutually distinct)
- (i.e., in-place is possible!)
- - GCD(0,z) == GCD(z,0) == z
- - negative values are handled correctly
- */
-
- if ((bits != bits_(V)) or
- (bits != bits_(W)) or
- (bits != bits_(X)) or
- (bits != bits_(Y)))
- {
- return(ErrCode_Size);
- }
- if ((U == V) or (U == W) or (V == W))
- {
- return(ErrCode_Same);
- }
- if (BitVector_is_empty(X))
- {
- if (U != Y) BitVector_Copy(U,Y);
- BitVector_Empty(V);
- BitVector_Empty(W);
- *W = 1;
- return(ErrCode_Ok);
- }
- if (BitVector_is_empty(Y))
- {
- if (U != X) BitVector_Copy(U,X);
- BitVector_Empty(V);
- BitVector_Empty(W);
- *V = 1;
- return(ErrCode_Ok);
- }
- if ((L = BitVector_Create_List(bits,false,11)) == NULL)
- {
- return(ErrCode_Null);
- }
- Q = L[0];
- R = L[1];
- A = L[2];
- B = L[3];
- X1 = L[4];
- X2 = L[5];
- X3 = L[6];
- Y1 = L[7];
- Y2 = L[8];
- Y3 = L[9];
- Z = L[10];
- size--;
- sgn_a = (((*(X+size) &= mask) AND msb) != 0);
- sgn_b = (((*(Y+size) &= mask) AND msb) != 0);
- if (sgn_a) BitVector_Negate(A,X); else BitVector_Copy(A,X);
- if (sgn_b) BitVector_Negate(B,Y); else BitVector_Copy(B,Y);
- BitVector_Empty(X1);
- BitVector_Empty(X2);
- *X1 = 1;
- BitVector_Empty(Y1);
- BitVector_Empty(Y2);
- *Y2 = 1;
- sgn_x = false;
- sgn_y = false;
- while (not error)
- {
- if ((error = BitVector_Div_Pos(Q,A,B,R)))
- {
- break;
- }
- if (BitVector_is_empty(R))
- {
- break;
- }
- sgn_q = sgn_a XOR sgn_b;
-
- if (sgn_x) BitVector_Negate(Z,X2); else BitVector_Copy(Z,X2);
- if ((error = BitVector_Mul_Pos(X3,Z,Q,true)))
- {
- break;
- }
- minus = not (sgn_x XOR sgn_q);
- carry = 0;
- if (BitVector_compute(X3,X1,X3,minus,&carry))
- {
- error = ErrCode_Ovfl;
- break;
- }
- sgn_x = (((*(X3+size) &= mask) AND msb) != 0);
-
- if (sgn_y) BitVector_Negate(Z,Y2); else BitVector_Copy(Z,Y2);
- if ((error = BitVector_Mul_Pos(Y3,Z,Q,true)))
- {
- break;
- }
- minus = not (sgn_y XOR sgn_q);
- carry = 0;
- if (BitVector_compute(Y3,Y1,Y3,minus,&carry))
- {
- error = ErrCode_Ovfl;
- break;
- }
- sgn_y = (((*(Y3+size) &= mask) AND msb) != 0);
-
- T = A; sgn_r = sgn_a;
- A = B; sgn_a = sgn_b;
- B = R; sgn_b = sgn_r;
- R = T;
-
- T = X1;
- X1 = X2;
- X2 = X3;
- X3 = T;
-
- T = Y1;
- Y1 = Y2;
- Y2 = Y3;
- Y3 = T;
- }
- if (not error)
- {
- if (sgn_b) BitVector_Negate(U,B); else BitVector_Copy(U,B);
- BitVector_Copy(V,X2);
- BitVector_Copy(W,Y2);
- }
- BitVector_Destroy_List(L,11);
- return(error);
-}
-
-ErrCode BitVector_Power(wordptr X, wordptr Y, wordptr Z)
-{
- ErrCode error = ErrCode_Ok;
- N_word bits = bits_(X);
- boolean first = TRUE;
- Z_long last;
- N_word limit;
- N_word count;
- wordptr T;
-
- /*
- Requirements:
- - X must have at least the same size as Y but may be larger (!)
- - X may not be identical with Z
- - Z must be positive
- Features:
- - The contents of Y and Z are preserved
- */
-
- if (X == Z) return(ErrCode_Same);
- if (bits < bits_(Y)) return(ErrCode_Size);
- if (BitVector_msb_(Z)) return(ErrCode_Expo);
- if ((last = Set_Max(Z)) < 0L)
- {
- if (bits < 2) return(ErrCode_Ovfl);
- BitVector_Empty(X);
- *X |= LSB;
- return(ErrCode_Ok); /* anything ^ 0 == 1 */
- }
- if (BitVector_is_empty(Y))
- {
- if (X != Y) BitVector_Empty(X);
- return(ErrCode_Ok); /* 0 ^ anything not zero == 0 */
- }
- T = BitVector_Create(bits,FALSE);
- if (T == NULL) return(ErrCode_Null);
- limit = (N_word) last;
- for ( count = 0; ((!error) and (count <= limit)); count++ )
- {
- if ( BIT_VECTOR_TST_BIT(Z,count) )
- {
- if (first)
- {
- first = FALSE;
- if (count) { BitVector_Copy(X,T); }
- else { if (X != Y) BitVector_Copy(X,Y); }
- }
- else error = BitVector_Multiply(X,T,X); /* order important because T > X */
- }
- if ((!error) and (count < limit))
- {
- if (count) error = BitVector_Multiply(T,T,T);
- else error = BitVector_Multiply(T,Y,Y);
- }
- }
- BitVector_Destroy(T);
- return(error);
-}
-
-void BitVector_Block_Store(wordptr addr, charptr buffer, N_int length)
-{
- N_word size = size_(addr);
- N_word mask = mask_(addr);
- N_word value;
- N_word count;
-
- /* provide translation for independence of endian-ness: */
- if (size > 0)
- {
- while (size-- > 0)
- {
- value = 0;
- for ( count = 0; (length > 0) and (count < BITS); count += 8 )
- {
- value |= (((N_word) *buffer++) << count); length--;
- }
- *addr++ = value;
- }
- *(--addr) &= mask;
- }
-}
-
-charptr BitVector_Block_Read(wordptr addr, N_intptr length)
-{
- N_word size = size_(addr);
- N_word value;
- N_word count;
- charptr buffer;
- charptr target;
-
- /* provide translation for independence of endian-ness: */
- *length = size << FACTOR;
- buffer = (charptr) yasm_xmalloc((size_t) ((*length)+1));
- if (buffer == NULL) return(NULL);
- target = buffer;
- if (size > 0)
- {
- *(addr+size-1) &= mask_(addr);
- while (size-- > 0)
- {
- value = *addr++;
- count = BITS >> 3;
- while (count-- > 0)
- {
- *target++ = (N_char) (value AND 0x00FF);
- if (count > 0) value >>= 8;
- }
- }
- }
- *target = (N_char) '\0';
- return(buffer);
-}
-
-void BitVector_Word_Store(wordptr addr, N_int offset, N_int value)
-{
- N_word size = size_(addr);
-
- if (size > 0)
- {
- if (offset < size) *(addr+offset) = value;
- *(addr+size-1) &= mask_(addr);
- }
-}
-
-N_int BitVector_Word_Read(wordptr addr, N_int offset)
-{
- N_word size = size_(addr);
-
- if (size > 0)
- {
- *(addr+size-1) &= mask_(addr);
- if (offset < size) return( *(addr+offset) );
- }
- return( (N_int) 0 );
-}
-
-void BitVector_Word_Insert(wordptr addr, N_int offset, N_int count,
- boolean clear)
-{
- N_word size = size_(addr);
- N_word mask = mask_(addr);
- wordptr last = addr+size-1;
-
- if (size > 0)
- {
- *last &= mask;
- if (offset > size) offset = size;
- BIT_VECTOR_ins_words(addr+offset,size-offset,count,clear);
- *last &= mask;
- }
-}
-
-void BitVector_Word_Delete(wordptr addr, N_int offset, N_int count,
- boolean clear)
-{
- N_word size = size_(addr);
- N_word mask = mask_(addr);
- wordptr last = addr+size-1;
-
- if (size > 0)
- {
- *last &= mask;
- if (offset > size) offset = size;
- BIT_VECTOR_del_words(addr+offset,size-offset,count,clear);
- *last &= mask;
- }
-}
-
-void BitVector_Chunk_Store(wordptr addr, N_int chunksize, N_int offset,
- N_long value)
-{
- N_word bits = bits_(addr);
- N_word mask;
- N_word temp;
-
- if ((chunksize > 0) and (offset < bits))
- {
- if (chunksize > LONGBITS) chunksize = LONGBITS;
- if ((offset + chunksize) > bits) chunksize = bits - offset;
- addr += offset >> LOGBITS;
- offset &= MODMASK;
- while (chunksize > 0)
- {
- mask = (N_word) (~0L << offset);
- bits = offset + chunksize;
- if (bits < BITS)
- {
- mask &= (N_word) ~(~0L << bits);
- bits = chunksize;
- }
- else bits = BITS - offset;
- temp = (N_word) (value << offset);
- temp &= mask;
- *addr &= NOT mask;
- *addr++ |= temp;
- value >>= bits;
- chunksize -= bits;
- offset = 0;
- }
- }
-}
-
-N_long BitVector_Chunk_Read(wordptr addr, N_int chunksize, N_int offset)
-{
- N_word bits = bits_(addr);
- N_word chunkbits = 0;
- N_long value = 0L;
- N_long temp;
- N_word mask;
-
- if ((chunksize > 0) and (offset < bits))
- {
- if (chunksize > LONGBITS) chunksize = LONGBITS;
- if ((offset + chunksize) > bits) chunksize = bits - offset;
- addr += offset >> LOGBITS;
- offset &= MODMASK;
- while (chunksize > 0)
- {
- bits = offset + chunksize;
- if (bits < BITS)
- {
- mask = (N_word) ~(~0L << bits);
- bits = chunksize;
- }
- else
- {
- mask = (N_word) ~0L;
- bits = BITS - offset;
- }
- temp = (N_long) ((*addr++ AND mask) >> offset);
- value |= temp << chunkbits;
- chunkbits += bits;
- chunksize -= bits;
- offset = 0;
- }
- }
- return(value);
-}
-
- /*******************/
- /* set operations: */
- /*******************/
-
-void Set_Union(wordptr X, wordptr Y, wordptr Z) /* X = Y + Z */
-{
- N_word bits = bits_(X);
- N_word size = size_(X);
- N_word mask = mask_(X);
-
- if ((size > 0) and (bits == bits_(Y)) and (bits == bits_(Z)))
- {
- while (size-- > 0) *X++ = *Y++ OR *Z++;
- *(--X) &= mask;
- }
-}
-
-void Set_Intersection(wordptr X, wordptr Y, wordptr Z) /* X = Y * Z */
-{
- N_word bits = bits_(X);
- N_word size = size_(X);
- N_word mask = mask_(X);
-
- if ((size > 0) and (bits == bits_(Y)) and (bits == bits_(Z)))
- {
- while (size-- > 0) *X++ = *Y++ AND *Z++;
- *(--X) &= mask;
- }
-}
-
-void Set_Difference(wordptr X, wordptr Y, wordptr Z) /* X = Y \ Z */
-{
- N_word bits = bits_(X);
- N_word size = size_(X);
- N_word mask = mask_(X);
-
- if ((size > 0) and (bits == bits_(Y)) and (bits == bits_(Z)))
- {
- while (size-- > 0) *X++ = *Y++ AND NOT *Z++;
- *(--X) &= mask;
- }
-}
-
-void Set_ExclusiveOr(wordptr X, wordptr Y, wordptr Z) /* X=(Y+Z)\(Y*Z) */
-{
- N_word bits = bits_(X);
- N_word size = size_(X);
- N_word mask = mask_(X);
-
- if ((size > 0) and (bits == bits_(Y)) and (bits == bits_(Z)))
- {
- while (size-- > 0) *X++ = *Y++ XOR *Z++;
- *(--X) &= mask;
- }
-}
-
-void Set_Complement(wordptr X, wordptr Y) /* X = ~Y */
-{
- N_word size = size_(X);
- N_word mask = mask_(X);
-
- if ((size > 0) and (bits_(X) == bits_(Y)))
- {
- while (size-- > 0) *X++ = NOT *Y++;
- *(--X) &= mask;
- }
-}
-
- /******************/
- /* set functions: */
- /******************/
-
-boolean Set_subset(wordptr X, wordptr Y) /* X subset Y ? */
-{
- N_word size = size_(X);
- boolean r = FALSE;
-
- if ((size > 0) and (bits_(X) == bits_(Y)))
- {
- r = TRUE;
- while (r and (size-- > 0)) r = ((*X++ AND NOT *Y++) == 0);
- }
- return(r);
-}
-
-N_int Set_Norm(wordptr addr) /* = | X | */
-{
- byteptr byte;
- N_word bytes;
- N_int n;
-
- byte = (byteptr) addr;
- bytes = size_(addr) << FACTOR;
- n = 0;
- while (bytes-- > 0)
- {
- n += BitVector_BYTENORM[*byte++];
- }
- return(n);
-}
-
-N_int Set_Norm2(wordptr addr) /* = | X | */
-{
- N_word size = size_(addr);
- N_word w0,w1;
- N_int n,k;
-
- n = 0;
- while (size-- > 0)
- {
- k = 0;
- w1 = NOT (w0 = *addr++);
- while (w0 and w1)
- {
- w0 &= w0 - 1;
- w1 &= w1 - 1;
- k++;
- }
- if (w0 == 0) n += k;
- else n += BITS - k;
- }
- return(n);
-}
-
-N_int Set_Norm3(wordptr addr) /* = | X | */
-{
- N_word size = size_(addr);
- N_int count = 0;
- N_word c;
-
- while (size-- > 0)
- {
- c = *addr++;
- while (c)
- {
- c &= c - 1;
- count++;
- }
- }
- return(count);
-}
-
-Z_long Set_Min(wordptr addr) /* = min(X) */
-{
- boolean empty = TRUE;
- N_word size = size_(addr);
- N_word i = 0;
- N_word c = 0; /* silence compiler warning */
-
- while (empty and (size-- > 0))
- {
- if ((c = *addr++)) empty = false; else i++;
- }
- if (empty) return((Z_long) LONG_MAX); /* plus infinity */
- i <<= LOGBITS;
- while (not (c AND LSB))
- {
- c >>= 1;
- i++;
- }
- return((Z_long) i);
-}
-
-Z_long Set_Max(wordptr addr) /* = max(X) */
-{
- boolean empty = TRUE;
- N_word size = size_(addr);
- N_word i = size;
- N_word c = 0; /* silence compiler warning */
-
- addr += size-1;
- while (empty and (size-- > 0))
- {
- if ((c = *addr--)) empty = false; else i--;
- }
- if (empty) return((Z_long) LONG_MIN); /* minus infinity */
- i <<= LOGBITS;
- while (not (c AND MSB))
- {
- c <<= 1;
- i--;
- }
- return((Z_long) --i);
-}
-
- /**********************************/
- /* matrix-of-booleans operations: */
- /**********************************/
-
-void Matrix_Multiplication(wordptr X, N_int rowsX, N_int colsX,
- wordptr Y, N_int rowsY, N_int colsY,
- wordptr Z, N_int rowsZ, N_int colsZ)
-{
- N_word i;
- N_word j;
- N_word k;
- N_word indxX;
- N_word indxY;
- N_word indxZ;
- N_word termX;
- N_word termY;
- N_word sum;
-
- if ((colsY == rowsZ) and (rowsX == rowsY) and (colsX == colsZ) and
- (bits_(X) == rowsX*colsX) and
- (bits_(Y) == rowsY*colsY) and
- (bits_(Z) == rowsZ*colsZ))
- {
- for ( i = 0; i < rowsY; i++ )
- {
- termX = i * colsX;
- termY = i * colsY;
- for ( j = 0; j < colsZ; j++ )
- {
- indxX = termX + j;
- sum = 0;
- for ( k = 0; k < colsY; k++ )
- {
- indxY = termY + k;
- indxZ = k * colsZ + j;
- if ( BIT_VECTOR_TST_BIT(Y,indxY) &&
- BIT_VECTOR_TST_BIT(Z,indxZ) ) sum ^= 1;
- }
- if (sum) BIT_VECTOR_SET_BIT(X,indxX)
- else BIT_VECTOR_CLR_BIT(X,indxX)
- }
- }
- }
-}
-
-void Matrix_Product(wordptr X, N_int rowsX, N_int colsX,
- wordptr Y, N_int rowsY, N_int colsY,
- wordptr Z, N_int rowsZ, N_int colsZ)
-{
- N_word i;
- N_word j;
- N_word k;
- N_word indxX;
- N_word indxY;
- N_word indxZ;
- N_word termX;
- N_word termY;
- N_word sum;
-
- if ((colsY == rowsZ) and (rowsX == rowsY) and (colsX == colsZ) and
- (bits_(X) == rowsX*colsX) and
- (bits_(Y) == rowsY*colsY) and
- (bits_(Z) == rowsZ*colsZ))
- {
- for ( i = 0; i < rowsY; i++ )
- {
- termX = i * colsX;
- termY = i * colsY;
- for ( j = 0; j < colsZ; j++ )
- {
- indxX = termX + j;
- sum = 0;
- for ( k = 0; k < colsY; k++ )
- {
- indxY = termY + k;
- indxZ = k * colsZ + j;
- if ( BIT_VECTOR_TST_BIT(Y,indxY) &&
- BIT_VECTOR_TST_BIT(Z,indxZ) ) sum |= 1;
- }
- if (sum) BIT_VECTOR_SET_BIT(X,indxX)
- else BIT_VECTOR_CLR_BIT(X,indxX)
- }
- }
- }
-}
-
-void Matrix_Closure(wordptr addr, N_int rows, N_int cols)
-{
- N_word i;
- N_word j;
- N_word k;
- N_word ii;
- N_word ij;
- N_word ik;
- N_word kj;
- N_word termi;
- N_word termk;
-
- if ((rows == cols) and (bits_(addr) == rows*cols))
- {
- for ( i = 0; i < rows; i++ )
- {
- ii = i * cols + i;
- BIT_VECTOR_SET_BIT(addr,ii)
- }
- for ( k = 0; k < rows; k++ )
- {
- termk = k * cols;
- for ( i = 0; i < rows; i++ )
- {
- termi = i * cols;
- ik = termi + k;
- for ( j = 0; j < rows; j++ )
- {
- ij = termi + j;
- kj = termk + j;
- if ( BIT_VECTOR_TST_BIT(addr,ik) &&
- BIT_VECTOR_TST_BIT(addr,kj) )
- BIT_VECTOR_SET_BIT(addr,ij)
- }
- }
- }
- }
-}
-
-void Matrix_Transpose(wordptr X, N_int rowsX, N_int colsX,
- wordptr Y, N_int rowsY, N_int colsY)
-{
- N_word i;
- N_word j;
- N_word ii;
- N_word ij;
- N_word ji;
- N_word addii;
- N_word addij;
- N_word addji;
- N_word bitii;
- N_word bitij;
- N_word bitji;
- N_word termi;
- N_word termj;
- boolean swap;
-
- /* BEWARE that "in-place" is ONLY possible if the matrix is quadratic!! */
-
- if ((rowsX == colsY) and (colsX == rowsY) and
- (bits_(X) == rowsX*colsX) and
- (bits_(Y) == rowsY*colsY))
- {
- if (rowsY == colsY) /* in-place is possible! */
- {
- for ( i = 0; i < rowsY; i++ )
- {
- termi = i * colsY;
- for ( j = 0; j < i; j++ )
- {
- termj = j * colsX;
- ij = termi + j;
- ji = termj + i;
- addij = ij >> LOGBITS;
- addji = ji >> LOGBITS;
- bitij = BITMASKTAB[ij AND MODMASK];
- bitji = BITMASKTAB[ji AND MODMASK];
- swap = ((*(Y+addij) AND bitij) != 0);
- if ((*(Y+addji) AND bitji) != 0)
- *(X+addij) |= bitij;
- else
- *(X+addij) &= NOT bitij;
- if (swap)
- *(X+addji) |= bitji;
- else
- *(X+addji) &= NOT bitji;
- }
- ii = termi + i;
- addii = ii >> LOGBITS;
- bitii = BITMASKTAB[ii AND MODMASK];
- if ((*(Y+addii) AND bitii) != 0)
- *(X+addii) |= bitii;
- else
- *(X+addii) &= NOT bitii;
- }
- }
- else /* rowsX != colsX, in-place is NOT possible! */
- {
- for ( i = 0; i < rowsY; i++ )
- {
- termi = i * colsY;
- for ( j = 0; j < colsY; j++ )
- {
- termj = j * colsX;
- ij = termi + j;
- ji = termj + i;
- addij = ij >> LOGBITS;
- addji = ji >> LOGBITS;
- bitij = BITMASKTAB[ij AND MODMASK];
- bitji = BITMASKTAB[ji AND MODMASK];
- if ((*(Y+addij) AND bitij) != 0)
- *(X+addji) |= bitji;
- else
- *(X+addji) &= NOT bitji;
- }
- }
- }
- }
-}
-
-/*****************************************************************************/
-/* VERSION: 6.4 */
-/*****************************************************************************/
-/* VERSION HISTORY: */
-/*****************************************************************************/
-/* */
-/* Version 6.4 03.10.04 Added C++ comp. directives. Improved "Norm()". */
-/* Version 6.3 28.09.02 Added "Create_List()" and "GCD2()". */
-/* Version 6.2 15.09.02 Overhauled error handling. Fixed "GCD()". */
-/* Version 6.1 08.10.01 Make VMS linker happy: _lsb,_msb => _lsb_,_msb_ */
-/* Version 6.0 08.10.00 Corrected overflow handling. */
-/* Version 5.8 14.07.00 Added "Power()". Changed "Copy()". */
-/* Version 5.7 19.05.99 Quickened "Div_Pos()". Added "Product()". */
-/* Version 5.6 02.11.98 Leading zeros eliminated in "to_Hex()". */
-/* Version 5.5 21.09.98 Fixed bug of uninitialized "error" in Multiply. */
-/* Version 5.4 07.09.98 Fixed bug of uninitialized "error" in Divide. */
-/* Version 5.3 12.05.98 Improved Norm. Completed history. */
-/* Version 5.2 31.03.98 Improved Norm. */
-/* Version 5.1 09.03.98 No changes. */
-/* Version 5.0 01.03.98 Major additions and rewrite. */
-/* Version 4.2 16.07.97 Added is_empty, is_full. */
-/* Version 4.1 30.06.97 Added word-ins/del, move-left/right, inc/dec. */
-/* Version 4.0 23.04.97 Rewrite. Added bit shift and bool. matrix ops. */
-/* Version 3.2 04.02.97 Added interval methods. */
-/* Version 3.1 21.01.97 Fixed bug on 64 bit machines. */
-/* Version 3.0 12.01.97 Added flip. */
-/* Version 2.0 14.12.96 Efficiency and consistency improvements. */
-/* Version 1.1 08.01.96 Added Resize and ExclusiveOr. */
-/* Version 1.0 14.12.95 First version under UNIX (with Perl module). */
-/* Version 0.9 01.11.93 First version of C library under MS-DOS. */
-/* Version 0.1 ??.??.89 First version in Turbo Pascal under CP/M. */
-/* */
-/*****************************************************************************/
-/* AUTHOR: */
-/*****************************************************************************/
-/* */
-/* Steffen Beyer */
-/* mailto:sb@engelschall.com */
-/* http://www.engelschall.com/u/sb/download/ */
-/* */
-/*****************************************************************************/
-/* COPYRIGHT: */
-/*****************************************************************************/
-/* */
-/* Copyright (c) 1995 - 2004 by Steffen Beyer. */
-/* All rights reserved. */
-/* */
-/*****************************************************************************/
-/* LICENSE: */
-/*****************************************************************************/
-/* This package is free software; you can use, modify and redistribute */
-/* it under the same terms as Perl itself, i.e., under the terms of */
-/* the "Artistic License" or the "GNU General Public License". */
-/* */
-/* The C library at the core of this Perl module can additionally */
-/* be used, modified and redistributed under the terms of the */
-/* "GNU Library General Public License". */
-/* */
-/*****************************************************************************/
-/* ARTISTIC LICENSE: */
-/*****************************************************************************/
-/*
- The "Artistic License"
-
- Preamble
-
-The intent of this document is to state the conditions under which a
-Package may be copied, such that the Copyright Holder maintains some
-semblance of artistic control over the development of the package,
-while giving the users of the package the right to use and distribute
-the Package in a more-or-less customary fashion, plus the right to make
-reasonable modifications.
-
-Definitions:
-
- "Package" refers to the collection of files distributed by the
- Copyright Holder, and derivatives of that collection of files
- created through textual modification.
-
- "Standard Version" refers to such a Package if it has not been
- modified, or has been modified in accordance with the wishes
- of the Copyright Holder as specified below.
-
- "Copyright Holder" is whoever is named in the copyright or
- copyrights for the package.
-
- "You" is you, if you're thinking about copying or distributing
- this Package.
-
- "Reasonable copying fee" is whatever you can justify on the
- basis of media cost, duplication charges, time of people involved,
- and so on. (You will not be required to justify it to the
- Copyright Holder, but only to the computing community at large
- as a market that must bear the fee.)
-
- "Freely Available" means that no fee is charged for the item
- itself, though there may be fees involved in handling the item.
- It also means that recipients of the item may redistribute it
- under the same conditions they received it.
-
-1. You may make and give away verbatim copies of the source form of the
-Standard Version of this Package without restriction, provided that you
-duplicate all of the original copyright notices and associated disclaimers.
-
-2. You may apply bug fixes, portability fixes and other modifications
-derived from the Public Domain or from the Copyright Holder. A Package
-modified in such a way shall still be considered the Standard Version.
-
-3. You may otherwise modify your copy of this Package in any way, provided
-that you insert a prominent notice in each changed file stating how and
-when you changed that file, and provided that you do at least ONE of the
-following:
-
- a) place your modifications in the Public Domain or otherwise make them
- Freely Available, such as by posting said modifications to Usenet or
- an equivalent medium, or placing the modifications on a major archive
- site such as uunet.uu.net, or by allowing the Copyright Holder to include
- your modifications in the Standard Version of the Package.
-
- b) use the modified Package only within your corporation or organization.
-
- c) rename any non-standard executables so the names do not conflict
- with standard executables, which must also be provided, and provide
- a separate manual page for each non-standard executable that clearly
- documents how it differs from the Standard Version.
-
- d) make other distribution arrangements with the Copyright Holder.
-
-4. You may distribute the programs of this Package in object code or
-executable form, provided that you do at least ONE of the following:
-
- a) distribute a Standard Version of the executables and library files,
- together with instructions (in the manual page or equivalent) on where
- to get the Standard Version.
-
- b) accompany the distribution with the machine-readable source of
- the Package with your modifications.
-
- c) give non-standard executables non-standard names, and clearly
- document the differences in manual pages (or equivalent), together
- with instructions on where to get the Standard Version.
-
- d) make other distribution arrangements with the Copyright Holder.
-
-5. You may charge a reasonable copying fee for any distribution of this
-Package. You may charge any fee you choose for support of this
-Package. You may not charge a fee for this Package itself. However,
-you may distribute this Package in aggregate with other (possibly
-commercial) programs as part of a larger (possibly commercial) software
-distribution provided that you do not advertise this Package as a
-product of your own. You may embed this Package's interpreter within
-an executable of yours (by linking); this shall be construed as a mere
-form of aggregation, provided that the complete Standard Version of the
-interpreter is so embedded.
-
-6. The scripts and library files supplied as input to or produced as
-output from the programs of this Package do not automatically fall
-under the copyright of this Package, but belong to whoever generated
-them, and may be sold commercially, and may be aggregated with this
-Package. If such scripts or library files are aggregated with this
-Package via the so-called "undump" or "unexec" methods of producing a
-binary executable image, then distribution of such an image shall
-neither be construed as a distribution of this Package nor shall it
-fall under the restrictions of Paragraphs 3 and 4, provided that you do
-not represent such an executable image as a Standard Version of this
-Package.
-
-7. C subroutines (or comparably compiled subroutines in other
-languages) supplied by you and linked into this Package in order to
-emulate subroutines and variables of the language defined by this
-Package shall not be considered part of this Package, but are the
-equivalent of input as in Paragraph 6, provided these subroutines do
-not change the language in any way that would cause it to fail the
-regression tests for the language.
-
-8. Aggregation of this Package with a commercial distribution is always
-permitted provided that the use of this Package is embedded; that is,
-when no overt attempt is made to make this Package's interfaces visible
-to the end user of the commercial distribution. Such use shall not be
-construed as a distribution of this Package.
-
-9. The name of the Copyright Holder may not be used to endorse or promote
-products derived from this software without specific prior written permission.
-
-10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
-IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
-WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-
- The End
-*/
-/*****************************************************************************/
-/* GNU GENERAL PUBLIC LICENSE: */
-/*****************************************************************************/
-/* This program is free software; you can redistribute it and/or */
-/* modify it under the terms of the GNU General Public License */
-/* as published by the Free Software Foundation; either version 2 */
-/* of the License, or (at your option) any later version. */
-/* */
-/* This program is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
-/* GNU General Public License for more details. */
-/* */
-/* You should have received a copy of the GNU General Public License */
-/* along with this program; if not, write to the */
-/* Free Software Foundation, Inc., */
-/* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-/* */
-/*****************************************************************************/
-/* GNU LIBRARY GENERAL PUBLIC LICENSE: */
-/*****************************************************************************/
-/* This library is free software; you can redistribute it and/or */
-/* modify it under the terms of the GNU Library General Public */
-/* License as published by the Free Software Foundation; either */
-/* version 2 of the License, or (at your option) any later version. */
-/* */
-/* This library is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
-/* Library General Public License for more details. */
-/* */
-/* You should have received a copy of the GNU Library General Public */
-/* License along with this library; if not, write to the */
-/* Free Software Foundation, Inc., */
-/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/* */
-/* or download a copy from ftp://ftp.gnu.org/pub/gnu/COPYING.LIB-2.0 */
-/* */
-/*****************************************************************************/
+#include "util.h"
+
+#include "coretype.h"
+
+/*****************************************************************************/
+/* MODULE NAME: BitVector.c MODULE TYPE: (adt) */
+/*****************************************************************************/
+/* MODULE IMPORTS: */
+/*****************************************************************************/
+#include <ctype.h> /* MODULE TYPE: (sys) */
+#include <limits.h> /* MODULE TYPE: (sys) */
+#include <string.h> /* MODULE TYPE: (sys) */
+/*****************************************************************************/
+/* MODULE INTERFACE: */
+/*****************************************************************************/
+#include "bitvect.h"
+
+/* ToolBox.h */
+#define and && /* logical (boolean) operators: lower case */
+#define or ||
+#define not !
+
+#define AND & /* binary (bitwise) operators: UPPER CASE */
+#define OR |
+#define XOR ^
+#define NOT ~
+#define SHL <<
+#define SHR >>
+
+#ifdef ENABLE_MODULO
+#define mod % /* arithmetic operators */
+#endif
+
+#define blockdef(name,size) unsigned char name[size]
+#define blocktypedef(name,size) typedef unsigned char name[size]
+
+/*****************************************************************************/
+/* MODULE RESOURCES: */
+/*****************************************************************************/
+
+#define bits_(BitVector) *(BitVector-3)
+#define size_(BitVector) *(BitVector-2)
+#define mask_(BitVector) *(BitVector-1)
+
+#define ERRCODE_TYPE "sizeof(word) > sizeof(size_t)"
+#define ERRCODE_BITS "bits(word) != sizeof(word)*8"
+#define ERRCODE_WORD "bits(word) < 16"
+#define ERRCODE_LONG "bits(word) > bits(long)"
+#define ERRCODE_POWR "bits(word) != 2^x"
+#define ERRCODE_LOGA "bits(word) != 2^ld(bits(word))"
+#define ERRCODE_NULL "unable to allocate memory"
+#define ERRCODE_INDX "index out of range"
+#define ERRCODE_ORDR "minimum > maximum index"
+#define ERRCODE_SIZE "bit vector size mismatch"
+#define ERRCODE_PARS "input string syntax error"
+#define ERRCODE_OVFL "numeric overflow error"
+#define ERRCODE_SAME "result vector(s) must be distinct"
+#define ERRCODE_EXPO "exponent must be positive"
+#define ERRCODE_ZERO "division by zero error"
+#define ERRCODE_OOPS "unexpected internal error - please contact author"
+
+const N_int BitVector_BYTENORM[256] =
+{
+ 0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x03,
+ 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, /* 0x00 */
+ 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
+ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, /* 0x10 */
+ 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
+ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, /* 0x20 */
+ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
+ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, /* 0x30 */
+ 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
+ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, /* 0x40 */
+ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
+ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, /* 0x50 */
+ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
+ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, /* 0x60 */
+ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
+ 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, /* 0x70 */
+ 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
+ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, /* 0x80 */
+ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
+ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, /* 0x90 */
+ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
+ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, /* 0xA0 */
+ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
+ 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, /* 0xB0 */
+ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
+ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, /* 0xC0 */
+ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
+ 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, /* 0xD0 */
+ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
+ 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, /* 0xE0 */
+ 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07,
+ 0x05, 0x06, 0x06, 0x07, 0x06, 0x07, 0x07, 0x08 /* 0xF0 */
+};
+
+/*****************************************************************************/
+/* MODULE IMPLEMENTATION: */
+/*****************************************************************************/
+
+ /**********************************************/
+ /* global implementation-intrinsic constants: */
+ /**********************************************/
+
+#define BIT_VECTOR_HIDDEN_WORDS 3
+
+ /*****************************************************************/
+ /* global machine-dependent constants (set by "BitVector_Boot"): */
+ /*****************************************************************/
+
+static N_word BITS; /* = # of bits in machine word (must be power of 2) */
+static N_word MODMASK; /* = BITS - 1 (mask for calculating modulo BITS) */
+static N_word LOGBITS; /* = ld(BITS) (logarithmus dualis) */
+static N_word FACTOR; /* = ld(BITS / 8) (ld of # of bytes) */
+
+static N_word LSB = 1; /* = mask for least significant bit */
+static N_word MSB; /* = mask for most significant bit */
+
+static N_word LONGBITS; /* = # of bits in unsigned long */
+
+static N_word LOG10; /* = logarithm to base 10 of BITS - 1 */
+static N_word EXP10; /* = largest possible power of 10 in signed int */
+
+ /********************************************************************/
+ /* global bit mask table for fast access (set by "BitVector_Boot"): */
+ /********************************************************************/
+
+static wordptr BITMASKTAB;
+
+ /*****************************/
+ /* global macro definitions: */
+ /*****************************/
+
+#define BIT_VECTOR_ZERO_WORDS(target,count) \
+ while (count-- > 0) *target++ = 0;
+
+#define BIT_VECTOR_FILL_WORDS(target,fill,count) \
+ while (count-- > 0) *target++ = fill;
+
+#define BIT_VECTOR_FLIP_WORDS(target,flip,count) \
+ while (count-- > 0) *target++ ^= flip;
+
+#define BIT_VECTOR_COPY_WORDS(target,source,count) \
+ while (count-- > 0) *target++ = *source++;
+
+#define BIT_VECTOR_BACK_WORDS(target,source,count) \
+ { target += count; source += count; while (count-- > 0) *--target = *--source; }
+
+#define BIT_VECTOR_CLR_BIT(address,index) \
+ *(address+(index>>LOGBITS)) &= NOT BITMASKTAB[index AND MODMASK];
+
+#define BIT_VECTOR_SET_BIT(address,index) \
+ *(address+(index>>LOGBITS)) |= BITMASKTAB[index AND MODMASK];
+
+#define BIT_VECTOR_TST_BIT(address,index) \
+ ((*(address+(index>>LOGBITS)) AND BITMASKTAB[index AND MODMASK]) != 0)
+
+#define BIT_VECTOR_FLP_BIT(address,index,mask) \
+ (mask = BITMASKTAB[index AND MODMASK]), \
+ (((*(addr+(index>>LOGBITS)) ^= mask) AND mask) != 0)
+
+#define BIT_VECTOR_DIGITIZE(type,value,digit) \
+ value = (type) ((digit = value) / 10); \
+ digit -= value * 10; \
+ digit += (type) '0';
+
+ /*********************************************************/
+ /* private low-level functions (potentially dangerous!): */
+ /*********************************************************/
+
+static N_word power10(N_word x)
+{
+ N_word y = 1;
+
+ while (x-- > 0) y *= 10;
+ return(y);
+}
+
+static void BIT_VECTOR_zro_words(wordptr addr, N_word count)
+{
+ BIT_VECTOR_ZERO_WORDS(addr,count)
+}
+
+static void BIT_VECTOR_cpy_words(wordptr target, wordptr source, N_word count)
+{
+ BIT_VECTOR_COPY_WORDS(target,source,count)
+}
+
+static void BIT_VECTOR_mov_words(wordptr target, wordptr source, N_word count)
+{
+ if (target != source)
+ {
+ if (target < source) BIT_VECTOR_COPY_WORDS(target,source,count)
+ else BIT_VECTOR_BACK_WORDS(target,source,count)
+ }
+}
+
+static void BIT_VECTOR_ins_words(wordptr addr, N_word total, N_word count,
+ boolean clear)
+{
+ N_word length;
+
+ if ((total > 0) and (count > 0))
+ {
+ if (count > total) count = total;
+ length = total - count;
+ if (length > 0) BIT_VECTOR_mov_words(addr+count,addr,length);
+ if (clear) BIT_VECTOR_zro_words(addr,count);
+ }
+}
+
+static void BIT_VECTOR_del_words(wordptr addr, N_word total, N_word count,
+ boolean clear)
+{
+ N_word length;
+
+ if ((total > 0) and (count > 0))
+ {
+ if (count > total) count = total;
+ length = total - count;
+ if (length > 0) BIT_VECTOR_mov_words(addr,addr+count,length);
+ if (clear) BIT_VECTOR_zro_words(addr+length,count);
+ }
+}
+
+static void BIT_VECTOR_reverse(charptr string, N_word length)
+{
+ charptr last;
+ N_char temp;
+
+ if (length > 1)
+ {
+ last = string + length - 1;
+ while (string < last)
+ {
+ temp = *string;
+ *string = *last;
+ *last = temp;
+ string++;
+ last--;
+ }
+ }
+}
+
+static N_word BIT_VECTOR_int2str(charptr string, N_word value)
+{
+ N_word length;
+ N_word digit;
+ charptr work;
+
+ work = string;
+ if (value > 0)
+ {
+ length = 0;
+ while (value > 0)
+ {
+ BIT_VECTOR_DIGITIZE(N_word,value,digit)
+ *work++ = (N_char) digit;
+ length++;
+ }
+ BIT_VECTOR_reverse(string,length);
+ }
+ else
+ {
+ length = 1;
+ *work++ = (N_char) '0';
+ }
+ return(length);
+}
+
+static N_word BIT_VECTOR_str2int(charptr string, N_word *value)
+{
+ N_word length;
+ N_word digit;
+
+ *value = 0;
+ length = 0;
+ digit = (N_word) *string++;
+ /* separate because isdigit() is likely a macro! */
+ while (isdigit((int)digit) != 0)
+ {
+ length++;
+ digit -= (N_word) '0';
+ if (*value) *value *= 10;
+ *value += digit;
+ digit = (N_word) *string++;
+ }
+ return(length);
+}
+
+ /********************************************/
+ /* routine to convert error code to string: */
+ /********************************************/
+
+const char * BitVector_Error(ErrCode error)
+{
+ switch (error)
+ {
+ case ErrCode_Ok: return( NULL ); break;
+ case ErrCode_Type: return( ERRCODE_TYPE ); break;
+ case ErrCode_Bits: return( ERRCODE_BITS ); break;
+ case ErrCode_Word: return( ERRCODE_WORD ); break;
+ case ErrCode_Long: return( ERRCODE_LONG ); break;
+ case ErrCode_Powr: return( ERRCODE_POWR ); break;
+ case ErrCode_Loga: return( ERRCODE_LOGA ); break;
+ case ErrCode_Null: return( ERRCODE_NULL ); break;
+ case ErrCode_Indx: return( ERRCODE_INDX ); break;
+ case ErrCode_Ordr: return( ERRCODE_ORDR ); break;
+ case ErrCode_Size: return( ERRCODE_SIZE ); break;
+ case ErrCode_Pars: return( ERRCODE_PARS ); break;
+ case ErrCode_Ovfl: return( ERRCODE_OVFL ); break;
+ case ErrCode_Same: return( ERRCODE_SAME ); break;
+ case ErrCode_Expo: return( ERRCODE_EXPO ); break;
+ case ErrCode_Zero: return( ERRCODE_ZERO ); break;
+ default: return( ERRCODE_OOPS ); break;
+ }
+}
+
+ /*****************************************/
+ /* automatic self-configuration routine: */
+ /*****************************************/
+
+ /*******************************************************/
+ /* */
+ /* MUST be called once prior to any other function */
+ /* to initialize the machine dependent constants */
+ /* of this package! (But call only ONCE, or you */
+ /* will suffer memory leaks!) */
+ /* */
+ /*******************************************************/
+
+ErrCode BitVector_Boot(void)
+{
+ N_long longsample = 1L;
+ N_word sample = LSB;
+ N_word lsb;
+
+ if (sizeof(N_word) > sizeof(size_t)) return(ErrCode_Type);
+
+ BITS = 1;
+ while (sample <<= 1) BITS++; /* determine # of bits in a machine word */
+
+ if (BITS != (sizeof(N_word) << 3)) return(ErrCode_Bits);
+
+ if (BITS < 16) return(ErrCode_Word);
+
+ LONGBITS = 1;
+ while (longsample <<= 1) LONGBITS++; /* = # of bits in an unsigned long */
+
+ if (BITS > LONGBITS) return(ErrCode_Long);
+
+ LOGBITS = 0;
+ sample = BITS;
+ lsb = (sample AND LSB);
+ while ((sample >>= 1) and (not lsb))
+ {
+ LOGBITS++;
+ lsb = (sample AND LSB);
+ }
+
+ if (sample) return(ErrCode_Powr); /* # of bits is not a power of 2! */
+
+ if (BITS != (LSB << LOGBITS)) return(ErrCode_Loga);
+
+ MODMASK = BITS - 1;
+ FACTOR = LOGBITS - 3; /* ld(BITS / 8) = ld(BITS) - ld(8) = ld(BITS) - 3 */
+ MSB = (LSB << MODMASK);
+
+ BITMASKTAB = (wordptr) yasm_xmalloc((size_t) (BITS << FACTOR));
+
+ if (BITMASKTAB == NULL) return(ErrCode_Null);
+
+ for ( sample = 0; sample < BITS; sample++ )
+ {
+ BITMASKTAB[sample] = (LSB << sample);
+ }
+
+ LOG10 = (N_word) (MODMASK * 0.30103); /* = (BITS - 1) * ( ln 2 / ln 10 ) */
+ EXP10 = power10(LOG10);
+
+ return(ErrCode_Ok);
+}
+
+void BitVector_Shutdown(void)
+{
+ if (BITMASKTAB) yasm_xfree(BITMASKTAB);
+}
+
+N_word BitVector_Size(N_int bits) /* bit vector size (# of words) */
+{
+ N_word size;
+
+ size = bits >> LOGBITS;
+ if (bits AND MODMASK) size++;
+ return(size);
+}
+
+N_word BitVector_Mask(N_int bits) /* bit vector mask (unused bits) */
+{
+ N_word mask;
+
+ mask = bits AND MODMASK;
+ if (mask) mask = (N_word) ~(~0L << mask); else mask = (N_word) ~0L;
+ return(mask);
+}
+
+const char * BitVector_Version(void)
+{
+ return("6.4");
+}
+
+N_int BitVector_Word_Bits(void)
+{
+ return(BITS);
+}
+
+N_int BitVector_Long_Bits(void)
+{
+ return(LONGBITS);
+}
+
+/********************************************************************/
+/* */
+/* WARNING: Do not "free()" constant character strings, i.e., */
+/* don't call "BitVector_Dispose()" for strings returned */
+/* by "BitVector_Error()" or "BitVector_Version()"! */
+/* */
+/* ONLY call this function for strings allocated with "malloc()", */
+/* i.e., the strings returned by the functions "BitVector_to_*()" */
+/* and "BitVector_Block_Read()"! */
+/* */
+/********************************************************************/
+
+void BitVector_Dispose(charptr string) /* free string */
+{
+ if (string != NULL) yasm_xfree((voidptr) string);
+}
+
+void BitVector_Destroy(wordptr addr) /* free bitvec */
+{
+ if (addr != NULL)
+ {
+ addr -= BIT_VECTOR_HIDDEN_WORDS;
+ yasm_xfree((voidptr) addr);
+ }
+}
+
+void BitVector_Destroy_List(listptr list, N_int count) /* free list */
+{
+ listptr slot;
+
+ if (list != NULL)
+ {
+ slot = list;
+ while (count-- > 0)
+ {
+ BitVector_Destroy(*slot++);
+ }
+ free((voidptr) list);
+ }
+}
+
+wordptr BitVector_Create(N_int bits, boolean clear) /* malloc */
+{
+ N_word size;
+ N_word mask;
+ N_word bytes;
+ wordptr addr;
+ wordptr zero;
+
+ size = BitVector_Size(bits);
+ mask = BitVector_Mask(bits);
+ bytes = (size + BIT_VECTOR_HIDDEN_WORDS) << FACTOR;
+ addr = (wordptr) yasm_xmalloc((size_t) bytes);
+ if (addr != NULL)
+ {
+ *addr++ = bits;
+ *addr++ = size;
+ *addr++ = mask;
+ if (clear)
+ {
+ zero = addr;
+ BIT_VECTOR_ZERO_WORDS(zero,size)
+ }
+ }
+ return(addr);
+}
+
+listptr BitVector_Create_List(N_int bits, boolean clear, N_int count)
+{
+ listptr list = NULL;
+ listptr slot;
+ wordptr addr;
+ N_int i;
+
+ if (count > 0)
+ {
+ list = (listptr) malloc(sizeof(wordptr) * count);
+ if (list != NULL)
+ {
+ slot = list;
+ for ( i = 0; i < count; i++ )
+ {
+ addr = BitVector_Create(bits,clear);
+ if (addr == NULL)
+ {
+ BitVector_Destroy_List(list,i);
+ return(NULL);
+ }
+ *slot++ = addr;
+ }
+ }
+ }
+ return(list);
+}
+
+wordptr BitVector_Resize(wordptr oldaddr, N_int bits) /* realloc */
+{
+ N_word bytes;
+ N_word oldsize;
+ N_word oldmask;
+ N_word newsize;
+ N_word newmask;
+ wordptr newaddr;
+ wordptr source;
+ wordptr target;
+
+ oldsize = size_(oldaddr);
+ oldmask = mask_(oldaddr);
+ newsize = BitVector_Size(bits);
+ newmask = BitVector_Mask(bits);
+ if (oldsize > 0) *(oldaddr+oldsize-1) &= oldmask;
+ if (newsize <= oldsize)
+ {
+ newaddr = oldaddr;
+ bits_(newaddr) = bits;
+ size_(newaddr) = newsize;
+ mask_(newaddr) = newmask;
+ if (newsize > 0) *(newaddr+newsize-1) &= newmask;
+ }
+ else
+ {
+ bytes = (newsize + BIT_VECTOR_HIDDEN_WORDS) << FACTOR;
+ newaddr = (wordptr) yasm_xmalloc((size_t) bytes);
+ if (newaddr != NULL)
+ {
+ *newaddr++ = bits;
+ *newaddr++ = newsize;
+ *newaddr++ = newmask;
+ target = newaddr;
+ source = oldaddr;
+ newsize -= oldsize;
+ BIT_VECTOR_COPY_WORDS(target,source,oldsize)
+ BIT_VECTOR_ZERO_WORDS(target,newsize)
+ }
+ BitVector_Destroy(oldaddr);
+ }
+ return(newaddr);
+}
+
+wordptr BitVector_Shadow(wordptr addr) /* makes new, same size but empty */
+{
+ return( BitVector_Create(bits_(addr),true) );
+}
+
+wordptr BitVector_Clone(wordptr addr) /* makes exact duplicate */
+{
+ N_word bits;
+ wordptr twin;
+
+ bits = bits_(addr);
+ twin = BitVector_Create(bits,false);
+ if ((twin != NULL) and (bits > 0))
+ BIT_VECTOR_cpy_words(twin,addr,size_(addr));
+ return(twin);
+}
+
+wordptr BitVector_Concat(wordptr X, wordptr Y) /* returns concatenation */
+{
+ /* BEWARE that X = most significant part, Y = least significant part! */
+
+ N_word bitsX;
+ N_word bitsY;
+ N_word bitsZ;
+ wordptr Z;
+
+ bitsX = bits_(X);
+ bitsY = bits_(Y);
+ bitsZ = bitsX + bitsY;
+ Z = BitVector_Create(bitsZ,false);
+ if ((Z != NULL) and (bitsZ > 0))
+ {
+ BIT_VECTOR_cpy_words(Z,Y,size_(Y));
+ BitVector_Interval_Copy(Z,X,bitsY,0,bitsX);
+ *(Z+size_(Z)-1) &= mask_(Z);
+ }
+ return(Z);
+}
+
+void BitVector_Copy(wordptr X, wordptr Y) /* X = Y */
+{
+ N_word sizeX = size_(X);
+ N_word sizeY = size_(Y);
+ N_word maskX = mask_(X);
+ N_word maskY = mask_(Y);
+ N_word fill = 0;
+ wordptr lastX;
+ wordptr lastY;
+
+ if ((X != Y) and (sizeX > 0))
+ {
+ lastX = X + sizeX - 1;
+ if (sizeY > 0)
+ {
+ lastY = Y + sizeY - 1;
+ if ( (*lastY AND (maskY AND NOT (maskY >> 1))) == 0 ) *lastY &= maskY;
+ else
+ {
+ fill = (N_word) ~0L;
+ *lastY |= NOT maskY;
+ }
+ while ((sizeX > 0) and (sizeY > 0))
+ {
+ *X++ = *Y++;
+ sizeX--;
+ sizeY--;
+ }
+ *lastY &= maskY;
+ }
+ while (sizeX-- > 0) *X++ = fill;
+ *lastX &= maskX;
+ }
+}
+
+void BitVector_Empty(wordptr addr) /* X = {} clr all */
+{
+ N_word size = size_(addr);
+
+ BIT_VECTOR_ZERO_WORDS(addr,size)
+}
+
+void BitVector_Fill(wordptr addr) /* X = ~{} set all */
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ N_word fill = (N_word) ~0L;
+
+ if (size > 0)
+ {
+ BIT_VECTOR_FILL_WORDS(addr,fill,size)
+ *(--addr) &= mask;
+ }
+}
+
+void BitVector_Flip(wordptr addr) /* X = ~X flip all */
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ N_word flip = (N_word) ~0L;
+
+ if (size > 0)
+ {
+ BIT_VECTOR_FLIP_WORDS(addr,flip,size)
+ *(--addr) &= mask;
+ }
+}
+
+void BitVector_Primes(wordptr addr)
+{
+ N_word bits = bits_(addr);
+ N_word size = size_(addr);
+ wordptr work;
+ N_word temp;
+ N_word i,j;
+
+ if (size > 0)
+ {
+ temp = 0xAAAA;
+ i = BITS >> 4;
+ while (--i > 0)
+ {
+ temp <<= 16;
+ temp |= 0xAAAA;
+ }
+ i = size;
+ work = addr;
+ *work++ = temp XOR 0x0006;
+ while (--i > 0) *work++ = temp;
+ for ( i = 3; (j = i * i) < bits; i += 2 )
+ {
+ for ( ; j < bits; j += i ) BIT_VECTOR_CLR_BIT(addr,j)
+ }
+ *(addr+size-1) &= mask_(addr);
+ }
+}
+
+void BitVector_Reverse(wordptr X, wordptr Y)
+{
+ N_word bits = bits_(X);
+ N_word mask;
+ N_word bit;
+ N_word value;
+
+ if (bits > 0)
+ {
+ if (X == Y) BitVector_Interval_Reverse(X,0,bits-1);
+ else if (bits == bits_(Y))
+ {
+/* mask = mask_(Y); */
+/* mask &= NOT (mask >> 1); */
+ mask = BITMASKTAB[(bits-1) AND MODMASK];
+ Y += size_(Y) - 1;
+ value = 0;
+ bit = LSB;
+ while (bits-- > 0)
+ {
+ if ((*Y AND mask) != 0)
+ {
+ value |= bit;
+ }
+ if (not (mask >>= 1))
+ {
+ Y--;
+ mask = MSB;
+ }
+ if (not (bit <<= 1))
+ {
+ *X++ = value;
+ value = 0;
+ bit = LSB;
+ }
+ }
+ if (bit > LSB) *X = value;
+ }
+ }
+}
+
+void BitVector_Interval_Empty(wordptr addr, N_int lower, N_int upper)
+{ /* X = X \ [lower..upper] */
+ N_word bits = bits_(addr);
+ N_word size = size_(addr);
+ wordptr loaddr;
+ wordptr hiaddr;
+ N_word lobase;
+ N_word hibase;
+ N_word lomask;
+ N_word himask;
+ N_word diff;
+
+ if ((size > 0) and (lower < bits) and (upper < bits) and (lower <= upper))
+ {
+ lobase = lower >> LOGBITS;
+ hibase = upper >> LOGBITS;
+ diff = hibase - lobase;
+ loaddr = addr + lobase;
+ hiaddr = addr + hibase;
+
+ lomask = (N_word) (~0L << (lower AND MODMASK));
+ himask = (N_word) ~((~0L << (upper AND MODMASK)) << 1);
+
+ if (diff == 0)
+ {
+ *loaddr &= NOT (lomask AND himask);
+ }
+ else
+ {
+ *loaddr++ &= NOT lomask;
+ while (--diff > 0)
+ {
+ *loaddr++ = 0;
+ }
+ *hiaddr &= NOT himask;
+ }
+ }
+}
+
+void BitVector_Interval_Fill(wordptr addr, N_int lower, N_int upper)
+{ /* X = X + [lower..upper] */
+ N_word bits = bits_(addr);
+ N_word size = size_(addr);
+ N_word fill = (N_word) ~0L;
+ wordptr loaddr;
+ wordptr hiaddr;
+ N_word lobase;
+ N_word hibase;
+ N_word lomask;
+ N_word himask;
+ N_word diff;
+
+ if ((size > 0) and (lower < bits) and (upper < bits) and (lower <= upper))
+ {
+ lobase = lower >> LOGBITS;
+ hibase = upper >> LOGBITS;
+ diff = hibase - lobase;
+ loaddr = addr + lobase;
+ hiaddr = addr + hibase;
+
+ lomask = (N_word) (~0L << (lower AND MODMASK));
+ himask = (N_word) ~((~0L << (upper AND MODMASK)) << 1);
+
+ if (diff == 0)
+ {
+ *loaddr |= (lomask AND himask);
+ }
+ else
+ {
+ *loaddr++ |= lomask;
+ while (--diff > 0)
+ {
+ *loaddr++ = fill;
+ }
+ *hiaddr |= himask;
+ }
+ *(addr+size-1) &= mask_(addr);
+ }
+}
+
+void BitVector_Interval_Flip(wordptr addr, N_int lower, N_int upper)
+{ /* X = X ^ [lower..upper] */
+ N_word bits = bits_(addr);
+ N_word size = size_(addr);
+ N_word flip = (N_word) ~0L;
+ wordptr loaddr;
+ wordptr hiaddr;
+ N_word lobase;
+ N_word hibase;
+ N_word lomask;
+ N_word himask;
+ N_word diff;
+
+ if ((size > 0) and (lower < bits) and (upper < bits) and (lower <= upper))
+ {
+ lobase = lower >> LOGBITS;
+ hibase = upper >> LOGBITS;
+ diff = hibase - lobase;
+ loaddr = addr + lobase;
+ hiaddr = addr + hibase;
+
+ lomask = (N_word) (~0L << (lower AND MODMASK));
+ himask = (N_word) ~((~0L << (upper AND MODMASK)) << 1);
+
+ if (diff == 0)
+ {
+ *loaddr ^= (lomask AND himask);
+ }
+ else
+ {
+ *loaddr++ ^= lomask;
+ while (--diff > 0)
+ {
+ *loaddr++ ^= flip;
+ }
+ *hiaddr ^= himask;
+ }
+ *(addr+size-1) &= mask_(addr);
+ }
+}
+
+void BitVector_Interval_Reverse(wordptr addr, N_int lower, N_int upper)
+{
+ N_word bits = bits_(addr);
+ wordptr loaddr;
+ wordptr hiaddr;
+ N_word lomask;
+ N_word himask;
+
+ if ((bits > 0) and (lower < bits) and (upper < bits) and (lower < upper))
+ {
+ loaddr = addr + (lower >> LOGBITS);
+ hiaddr = addr + (upper >> LOGBITS);
+ lomask = BITMASKTAB[lower AND MODMASK];
+ himask = BITMASKTAB[upper AND MODMASK];
+ for ( bits = upper - lower + 1; bits > 1; bits -= 2 )
+ {
+ if (((*loaddr AND lomask) != 0) XOR ((*hiaddr AND himask) != 0))
+ {
+ *loaddr ^= lomask; /* swap bits only if they differ! */
+ *hiaddr ^= himask;
+ }
+ if (not (lomask <<= 1))
+ {
+ lomask = LSB;
+ loaddr++;
+ }
+ if (not (himask >>= 1))
+ {
+ himask = MSB;
+ hiaddr--;
+ }
+ }
+ }
+}
+
+boolean BitVector_interval_scan_inc(wordptr addr, N_int start,
+ N_intptr min, N_intptr max)
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ N_word offset;
+ N_word bitmask;
+ N_word value;
+ boolean empty;
+
+ if ((size == 0) or (start >= bits_(addr))) return(FALSE);
+
+ *min = start;
+ *max = start;
+
+ offset = start >> LOGBITS;
+
+ *(addr+size-1) &= mask;
+
+ addr += offset;
+ size -= offset;
+
+ bitmask = BITMASKTAB[start AND MODMASK];
+ mask = NOT (bitmask OR (bitmask - 1));
+
+ value = *addr++;
+ if ((value AND bitmask) == 0)
+ {
+ value &= mask;
+ if (value == 0)
+ {
+ offset++;
+ empty = TRUE;
+ while (empty and (--size > 0))
+ {
+ if ((value = *addr++)) empty = false; else offset++;
+ }
+ if (empty) return(FALSE);
+ }
+ start = offset << LOGBITS;
+ bitmask = LSB;
+ mask = value;
+ while (not (mask AND LSB))
+ {
+ bitmask <<= 1;
+ mask >>= 1;
+ start++;
+ }
+ mask = NOT (bitmask OR (bitmask - 1));
+ *min = start;
+ *max = start;
+ }
+ value = NOT value;
+ value &= mask;
+ if (value == 0)
+ {
+ offset++;
+ empty = TRUE;
+ while (empty and (--size > 0))
+ {
+ if ((value = NOT *addr++)) empty = false; else offset++;
+ }
+ if (empty) value = LSB;
+ }
+ start = offset << LOGBITS;
+ while (not (value AND LSB))
+ {
+ value >>= 1;
+ start++;
+ }
+ *max = --start;
+ return(TRUE);
+}
+
+boolean BitVector_interval_scan_dec(wordptr addr, N_int start,
+ N_intptr min, N_intptr max)
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ N_word offset;
+ N_word bitmask;
+ N_word value;
+ boolean empty;
+
+ if ((size == 0) or (start >= bits_(addr))) return(FALSE);
+
+ *min = start;
+ *max = start;
+
+ offset = start >> LOGBITS;
+
+ if (offset >= size) return(FALSE);
+
+ *(addr+size-1) &= mask;
+
+ addr += offset;
+ size = ++offset;
+
+ bitmask = BITMASKTAB[start AND MODMASK];
+ mask = (bitmask - 1);
+
+ value = *addr--;
+ if ((value AND bitmask) == 0)
+ {
+ value &= mask;
+ if (value == 0)
+ {
+ offset--;
+ empty = TRUE;
+ while (empty and (--size > 0))
+ {
+ if ((value = *addr--)) empty = false; else offset--;
+ }
+ if (empty) return(FALSE);
+ }
+ start = offset << LOGBITS;
+ bitmask = MSB;
+ mask = value;
+ while (not (mask AND MSB))
+ {
+ bitmask >>= 1;
+ mask <<= 1;
+ start--;
+ }
+ mask = (bitmask - 1);
+ *max = --start;
+ *min = start;
+ }
+ value = NOT value;
+ value &= mask;
+ if (value == 0)
+ {
+ offset--;
+ empty = TRUE;
+ while (empty and (--size > 0))
+ {
+ if ((value = NOT *addr--)) empty = false; else offset--;
+ }
+ if (empty) value = MSB;
+ }
+ start = offset << LOGBITS;
+ while (not (value AND MSB))
+ {
+ value <<= 1;
+ start--;
+ }
+ *min = start;
+ return(TRUE);
+}
+
+void BitVector_Interval_Copy(wordptr X, wordptr Y, N_int Xoffset,
+ N_int Yoffset, N_int length)
+{
+ N_word bitsX = bits_(X);
+ N_word bitsY = bits_(Y);
+ N_word source = 0; /* silence compiler warning */
+ N_word target = 0; /* silence compiler warning */
+ N_word s_lo_base;
+ N_word s_hi_base;
+ N_word s_lo_bit;
+ N_word s_hi_bit;
+ N_word s_base;
+ N_word s_lower = 0; /* silence compiler warning */
+ N_word s_upper = 0; /* silence compiler warning */
+ N_word s_bits;
+ N_word s_min;
+ N_word s_max;
+ N_word t_lo_base;
+ N_word t_hi_base;
+ N_word t_lo_bit;
+ N_word t_hi_bit;
+ N_word t_base;
+ N_word t_lower = 0; /* silence compiler warning */
+ N_word t_upper = 0; /* silence compiler warning */
+ N_word t_bits;
+ N_word t_min;
+ N_word mask;
+ N_word bits;
+ N_word sel;
+ boolean ascending;
+ boolean notfirst;
+ wordptr Z = X;
+
+ if ((length > 0) and (Xoffset < bitsX) and (Yoffset < bitsY))
+ {
+ if ((Xoffset + length) > bitsX) length = bitsX - Xoffset;
+ if ((Yoffset + length) > bitsY) length = bitsY - Yoffset;
+
+ ascending = (Xoffset <= Yoffset);
+
+ s_lo_base = Yoffset >> LOGBITS;
+ s_lo_bit = Yoffset AND MODMASK;
+ Yoffset += --length;
+ s_hi_base = Yoffset >> LOGBITS;
+ s_hi_bit = Yoffset AND MODMASK;
+
+ t_lo_base = Xoffset >> LOGBITS;
+ t_lo_bit = Xoffset AND MODMASK;
+ Xoffset += length;
+ t_hi_base = Xoffset >> LOGBITS;
+ t_hi_bit = Xoffset AND MODMASK;
+
+ if (ascending)
+ {
+ s_base = s_lo_base;
+ t_base = t_lo_base;
+ }
+ else
+ {
+ s_base = s_hi_base;
+ t_base = t_hi_base;
+ }
+ s_bits = 0;
+ t_bits = 0;
+ Y += s_base;
+ X += t_base;
+ notfirst = FALSE;
+ while (TRUE)
+ {
+ if (t_bits == 0)
+ {
+ if (notfirst)
+ {
+ *X = target;
+ if (ascending)
+ {
+ if (t_base == t_hi_base) break;
+ t_base++;
+ X++;
+ }
+ else
+ {
+ if (t_base == t_lo_base) break;
+ t_base--;
+ X--;
+ }
+ }
+ sel = ((t_base == t_hi_base) << 1) OR (t_base == t_lo_base);
+ switch (sel)
+ {
+ case 0:
+ t_lower = 0;
+ t_upper = BITS - 1;
+ t_bits = BITS;
+ target = 0;
+ break;
+ case 1:
+ t_lower = t_lo_bit;
+ t_upper = BITS - 1;
+ t_bits = BITS - t_lo_bit;
+ mask = (N_word) (~0L << t_lower);
+ target = *X AND NOT mask;
+ break;
+ case 2:
+ t_lower = 0;
+ t_upper = t_hi_bit;
+ t_bits = t_hi_bit + 1;
+ mask = (N_word) ((~0L << t_upper) << 1);
+ target = *X AND mask;
+ break;
+ case 3:
+ t_lower = t_lo_bit;
+ t_upper = t_hi_bit;
+ t_bits = t_hi_bit - t_lo_bit + 1;
+ mask = (N_word) (~0L << t_lower);
+ mask &= (N_word) ~((~0L << t_upper) << 1);
+ target = *X AND NOT mask;
+ break;
+ }
+ }
+ if (s_bits == 0)
+ {
+ if (notfirst)
+ {
+ if (ascending)
+ {
+ if (s_base == s_hi_base) break;
+ s_base++;
+ Y++;
+ }
+ else
+ {
+ if (s_base == s_lo_base) break;
+ s_base--;
+ Y--;
+ }
+ }
+ source = *Y;
+ sel = ((s_base == s_hi_base) << 1) OR (s_base == s_lo_base);
+ switch (sel)
+ {
+ case 0:
+ s_lower = 0;
+ s_upper = BITS - 1;
+ s_bits = BITS;
+ break;
+ case 1:
+ s_lower = s_lo_bit;
+ s_upper = BITS - 1;
+ s_bits = BITS - s_lo_bit;
+ break;
+ case 2:
+ s_lower = 0;
+ s_upper = s_hi_bit;
+ s_bits = s_hi_bit + 1;
+ break;
+ case 3:
+ s_lower = s_lo_bit;
+ s_upper = s_hi_bit;
+ s_bits = s_hi_bit - s_lo_bit + 1;
+ break;
+ }
+ }
+ notfirst = TRUE;
+ if (s_bits > t_bits)
+ {
+ bits = t_bits - 1;
+ if (ascending)
+ {
+ s_min = s_lower;
+ s_max = s_lower + bits;
+ }
+ else
+ {
+ s_max = s_upper;
+ s_min = s_upper - bits;
+ }
+ t_min = t_lower;
+ }
+ else
+ {
+ bits = s_bits - 1;
+ if (ascending) t_min = t_lower;
+ else t_min = t_upper - bits;
+ s_min = s_lower;
+ s_max = s_upper;
+ }
+ bits++;
+ mask = (N_word) (~0L << s_min);
+ mask &= (N_word) ~((~0L << s_max) << 1);
+ if (s_min == t_min) target |= (source AND mask);
+ else
+ {
+ if (s_min < t_min) target |= (source AND mask) << (t_min-s_min);
+ else target |= (source AND mask) >> (s_min-t_min);
+ }
+ if (ascending)
+ {
+ s_lower += bits;
+ t_lower += bits;
+ }
+ else
+ {
+ s_upper -= bits;
+ t_upper -= bits;
+ }
+ s_bits -= bits;
+ t_bits -= bits;
+ }
+ *(Z+size_(Z)-1) &= mask_(Z);
+ }
+}
+
+
+wordptr BitVector_Interval_Substitute(wordptr X, wordptr Y,
+ N_int Xoffset, N_int Xlength,
+ N_int Yoffset, N_int Ylength)
+{
+ N_word Xbits = bits_(X);
+ N_word Ybits = bits_(Y);
+ N_word limit;
+ N_word diff;
+
+ if ((Xoffset <= Xbits) and (Yoffset <= Ybits))
+ {
+ limit = Xoffset + Xlength;
+ if (limit > Xbits)
+ {
+ limit = Xbits;
+ Xlength = Xbits - Xoffset;
+ }
+ if ((Yoffset + Ylength) > Ybits)
+ {
+ Ylength = Ybits - Yoffset;
+ }
+ if (Xlength == Ylength)
+ {
+ if ((Ylength > 0) and ((X != Y) or (Xoffset != Yoffset)))
+ {
+ BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
+ }
+ }
+ else /* Xlength != Ylength */
+ {
+ if (Xlength > Ylength)
+ {
+ diff = Xlength - Ylength;
+ if (Ylength > 0) BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
+ if (limit < Xbits) BitVector_Delete(X,Xoffset+Ylength,diff,FALSE);
+ if ((X = BitVector_Resize(X,Xbits-diff)) == NULL) return(NULL);
+ }
+ else /* Ylength > Xlength ==> Ylength > 0 */
+ {
+ diff = Ylength - Xlength;
+ if (X != Y)
+ {
+ if ((X = BitVector_Resize(X,Xbits+diff)) == NULL) return(NULL);
+ if (limit < Xbits) BitVector_Insert(X,limit,diff,FALSE);
+ BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
+ }
+ else /* in-place */
+ {
+ if ((Y = X = BitVector_Resize(X,Xbits+diff)) == NULL) return(NULL);
+ if (limit >= Xbits)
+ {
+ BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
+ }
+ else /* limit < Xbits */
+ {
+ BitVector_Insert(X,limit,diff,FALSE);
+ if ((Yoffset+Ylength) <= limit)
+ {
+ BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
+ }
+ else /* overlaps or lies above critical area */
+ {
+ if (limit <= Yoffset)
+ {
+ Yoffset += diff;
+ BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
+ }
+ else /* Yoffset < limit */
+ {
+ Xlength = limit - Yoffset;
+ BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Xlength);
+ Yoffset = Xoffset + Ylength; /* = limit + diff */
+ Xoffset += Xlength;
+ Ylength -= Xlength;
+ BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return(X);
+}
+
+boolean BitVector_is_empty(wordptr addr) /* X == {} ? */
+{
+ N_word size = size_(addr);
+ boolean r = TRUE;
+
+ if (size > 0)
+ {
+ *(addr+size-1) &= mask_(addr);
+ while (r and (size-- > 0)) r = ( *addr++ == 0 );
+ }
+ return(r);
+}
+
+boolean BitVector_is_full(wordptr addr) /* X == ~{} ? */
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ boolean r = FALSE;
+ wordptr last;
+
+ if (size > 0)
+ {
+ r = TRUE;
+ last = addr + size - 1;
+ *last |= NOT mask;
+ while (r and (size-- > 0)) r = ( NOT *addr++ == 0 );
+ *last &= mask;
+ }
+ return(r);
+}
+
+boolean BitVector_equal(wordptr X, wordptr Y) /* X == Y ? */
+{
+ N_word size = size_(X);
+ N_word mask = mask_(X);
+ boolean r = FALSE;
+
+ if (bits_(X) == bits_(Y))
+ {
+ r = TRUE;
+ if (size > 0)
+ {
+ *(X+size-1) &= mask;
+ *(Y+size-1) &= mask;
+ while (r and (size-- > 0)) r = (*X++ == *Y++);
+ }
+ }
+ return(r);
+}
+
+Z_int BitVector_Lexicompare(wordptr X, wordptr Y) /* X <,=,> Y ? */
+{ /* unsigned */
+ N_word bitsX = bits_(X);
+ N_word bitsY = bits_(Y);
+ N_word size = size_(X);
+ boolean r = TRUE;
+
+ if (bitsX == bitsY)
+ {
+ if (size > 0)
+ {
+ X += size;
+ Y += size;
+ while (r and (size-- > 0)) r = (*(--X) == *(--Y));
+ }
+ if (r) return((Z_int) 0);
+ else
+ {
+ if (*X < *Y) return((Z_int) -1); else return((Z_int) 1);
+ }
+ }
+ else
+ {
+ if (bitsX < bitsY) return((Z_int) -1); else return((Z_int) 1);
+ }
+}
+
+Z_int BitVector_Compare(wordptr X, wordptr Y) /* X <,=,> Y ? */
+{ /* signed */
+ N_word bitsX = bits_(X);
+ N_word bitsY = bits_(Y);
+ N_word size = size_(X);
+ N_word mask = mask_(X);
+ N_word sign;
+ boolean r = TRUE;
+
+ if (bitsX == bitsY)
+ {
+ if (size > 0)
+ {
+ X += size;
+ Y += size;
+ mask &= NOT (mask >> 1);
+ if ((sign = (*(X-1) AND mask)) != (*(Y-1) AND mask))
+ {
+ if (sign) return((Z_int) -1); else return((Z_int) 1);
+ }
+ while (r and (size-- > 0)) r = (*(--X) == *(--Y));
+ }
+ if (r) return((Z_int) 0);
+ else
+ {
+ if (*X < *Y) return((Z_int) -1); else return((Z_int) 1);
+ }
+ }
+ else
+ {
+ if (bitsX < bitsY) return((Z_int) -1); else return((Z_int) 1);
+ }
+}
+
+charptr BitVector_to_Hex(wordptr addr)
+{
+ N_word bits = bits_(addr);
+ N_word size = size_(addr);
+ N_word value;
+ N_word count;
+ N_word digit;
+ N_word length;
+ charptr string;
+
+ length = bits >> 2;
+ if (bits AND 0x0003) length++;
+ string = (charptr) yasm_xmalloc((size_t) (length+1));
+ if (string == NULL) return(NULL);
+ string += length;
+ *string = (N_char) '\0';
+ if (size > 0)
+ {
+ *(addr+size-1) &= mask_(addr);
+ while ((size-- > 0) and (length > 0))
+ {
+ value = *addr++;
+ count = BITS >> 2;
+ while ((count-- > 0) and (length > 0))
+ {
+ digit = value AND 0x000F;
+ if (digit > 9) digit += (N_word) 'A' - 10;
+ else digit += (N_word) '0';
+ *(--string) = (N_char) digit; length--;
+ if ((count > 0) and (length > 0)) value >>= 4;
+ }
+ }
+ }
+ return(string);
+}
+
+ErrCode BitVector_from_Hex(wordptr addr, charptr string)
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ boolean ok = TRUE;
+ size_t length;
+ N_word value;
+ N_word count;
+ int digit;
+
+ if (size > 0)
+ {
+ length = strlen((char *) string);
+ string += length;
+ while (size-- > 0)
+ {
+ value = 0;
+ for ( count = 0; (ok and (length > 0) and (count < BITS)); count += 4 )
+ {
+ digit = (int) *(--string); length--;
+ /* separate because toupper() is likely a macro! */
+ digit = toupper(digit);
+ if (digit == '_')
+ count -= 4;
+ else if ((ok = (isxdigit(digit) != 0)))
+ {
+ if (digit >= (int) 'A') digit -= (int) 'A' - 10;
+ else digit -= (int) '0';
+ value |= (((N_word) digit) << count);
+ }
+ }
+ *addr++ = value;
+ }
+ *(--addr) &= mask;
+ }
+ if (ok) return(ErrCode_Ok);
+ else return(ErrCode_Pars);
+}
+
+ErrCode BitVector_from_Oct(wordptr addr, charptr string)
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ boolean ok = TRUE;
+ size_t length;
+ N_word value;
+ N_word value_fill = 0;
+ N_word count;
+ Z_word count_fill = 0;
+ int digit = 0;
+
+ if (size > 0)
+ {
+ length = strlen((char *) string);
+ string += length;
+ while (size-- > 0)
+ {
+ value = value_fill;
+ for ( count = count_fill; (ok and (length > 0) and (count < BITS)); count += 3 )
+ {
+ digit = (int) *(--string); length--;
+ if (digit == '_')
+ count -= 3;
+ else if ((ok = (isdigit(digit) && digit != '8' && digit != '9')) != 0)
+ {
+ digit -= (int) '0';
+ value |= (((N_word) digit) << count);
+ }
+ }
+ count_fill = (Z_word)count-(Z_word)BITS;
+ if (count_fill > 0)
+ value_fill = (((N_word) digit) >> (3-count_fill));
+ else
+ value_fill = 0;
+ *addr++ = value;
+ }
+ *(--addr) &= mask;
+ }
+ if (ok) return(ErrCode_Ok);
+ else return(ErrCode_Pars);
+}
+
+charptr BitVector_to_Bin(wordptr addr)
+{
+ N_word size = size_(addr);
+ N_word value;
+ N_word count;
+ N_word digit;
+ N_word length;
+ charptr string;
+
+ length = bits_(addr);
+ string = (charptr) yasm_xmalloc((size_t) (length+1));
+ if (string == NULL) return(NULL);
+ string += length;
+ *string = (N_char) '\0';
+ if (size > 0)
+ {
+ *(addr+size-1) &= mask_(addr);
+ while (size-- > 0)
+ {
+ value = *addr++;
+ count = BITS;
+ if (count > length) count = length;
+ while (count-- > 0)
+ {
+ digit = value AND 0x0001;
+ digit += (N_word) '0';
+ *(--string) = (N_char) digit; length--;
+ if (count > 0) value >>= 1;
+ }
+ }
+ }
+ return(string);
+}
+
+ErrCode BitVector_from_Bin(wordptr addr, charptr string)
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ boolean ok = TRUE;
+ size_t length;
+ N_word value;
+ N_word count;
+ int digit;
+
+ if (size > 0)
+ {
+ length = strlen((char *) string);
+ string += length;
+ while (size-- > 0)
+ {
+ value = 0;
+ for ( count = 0; (ok and (length > 0) and (count < BITS)); count++ )
+ {
+ digit = (int) *(--string); length--;
+ switch (digit)
+ {
+ case (int) '0':
+ break;
+ case (int) '1':
+ value |= BITMASKTAB[count];
+ break;
+ case (int) '_':
+ count--;
+ break;
+ default:
+ ok = FALSE;
+ break;
+ }
+ }
+ *addr++ = value;
+ }
+ *(--addr) &= mask;
+ }
+ if (ok) return(ErrCode_Ok);
+ else return(ErrCode_Pars);
+}
+
+charptr BitVector_to_Dec(wordptr addr)
+{
+ N_word bits = bits_(addr);
+ N_word length;
+ N_word digits;
+ N_word count;
+ N_word q;
+ N_word r;
+ boolean loop;
+ charptr result;
+ charptr string;
+ wordptr quot;
+ wordptr rest;
+ wordptr temp;
+ wordptr base;
+ Z_int sign;
+
+ length = (N_word) (bits / 3.3); /* digits = bits * ln(2) / ln(10) */
+ length += 2; /* compensate for truncating & provide space for minus sign */
+ result = (charptr) yasm_xmalloc((size_t) (length+1)); /* remember the '\0'! */
+ if (result == NULL) return(NULL);
+ string = result;
+ sign = BitVector_Sign(addr);
+ if ((bits < 4) or (sign == 0))
+ {
+ if (bits > 0) digits = *addr; else digits = (N_word) 0;
+ if (sign < 0) digits = ((N_word)(-((Z_word)digits))) AND mask_(addr);
+ *string++ = (N_char) digits + (N_char) '0';
+ digits = 1;
+ }
+ else
+ {
+ quot = BitVector_Create(bits,FALSE);
+ if (quot == NULL)
+ {
+ BitVector_Dispose(result);
+ return(NULL);
+ }
+ rest = BitVector_Create(bits,FALSE);
+ if (rest == NULL)
+ {
+ BitVector_Dispose(result);
+ BitVector_Destroy(quot);
+ return(NULL);
+ }
+ temp = BitVector_Create(bits,FALSE);
+ if (temp == NULL)
+ {
+ BitVector_Dispose(result);
+ BitVector_Destroy(quot);
+ BitVector_Destroy(rest);
+ return(NULL);
+ }
+ base = BitVector_Create(bits,TRUE);
+ if (base == NULL)
+ {
+ BitVector_Dispose(result);
+ BitVector_Destroy(quot);
+ BitVector_Destroy(rest);
+ BitVector_Destroy(temp);
+ return(NULL);
+ }
+ if (sign < 0) BitVector_Negate(quot,addr);
+ else BitVector_Copy(quot,addr);
+ digits = 0;
+ *base = EXP10;
+ loop = (bits >= BITS);
+ do
+ {
+ if (loop)
+ {
+ BitVector_Copy(temp,quot);
+ if (BitVector_Div_Pos(quot,temp,base,rest))
+ {
+ BitVector_Dispose(result); /* emergency exit */
+ BitVector_Destroy(quot);
+ BitVector_Destroy(rest); /* should never occur */
+ BitVector_Destroy(temp); /* under normal operation */
+ BitVector_Destroy(base);
+ return(NULL);
+ }
+ loop = not BitVector_is_empty(quot);
+ q = *rest;
+ }
+ else q = *quot;
+ count = LOG10;
+ while (((loop and (count-- > 0)) or ((not loop) and (q != 0))) and
+ (digits < length))
+ {
+ if (q != 0)
+ {
+ BIT_VECTOR_DIGITIZE(N_word,q,r)
+ }
+ else r = (N_word) '0';
+ *string++ = (N_char) r;
+ digits++;
+ }
+ }
+ while (loop and (digits < length));
+ BitVector_Destroy(quot);
+ BitVector_Destroy(rest);
+ BitVector_Destroy(temp);
+ BitVector_Destroy(base);
+ }
+ if ((sign < 0) and (digits < length))
+ {
+ *string++ = (N_char) '-';
+ digits++;
+ }
+ *string = (N_char) '\0';
+ BIT_VECTOR_reverse(result,digits);
+ return(result);
+}
+
+struct BitVector_from_Dec_static_data {
+ wordptr term;
+ wordptr base;
+ wordptr prod;
+ wordptr rank;
+ wordptr temp;
+};
+
+BitVector_from_Dec_static_data *BitVector_from_Dec_static_Boot(N_word bits)
+{
+ BitVector_from_Dec_static_data *data;
+
+ data = yasm_xmalloc(sizeof(BitVector_from_Dec_static_data));
+
+ if (bits > 0)
+ {
+ data->term = BitVector_Create(BITS,FALSE);
+ data->base = BitVector_Create(BITS,FALSE);
+ data->prod = BitVector_Create(bits,FALSE);
+ data->rank = BitVector_Create(bits,FALSE);
+ data->temp = BitVector_Create(bits,FALSE);
+ } else {
+ data->term = NULL;
+ data->base = NULL;
+ data->prod = NULL;
+ data->rank = NULL;
+ data->temp = NULL;
+ }
+ return data;
+}
+
+void BitVector_from_Dec_static_Shutdown(BitVector_from_Dec_static_data *data)
+{
+ if (data) {
+ BitVector_Destroy(data->term);
+ BitVector_Destroy(data->base);
+ BitVector_Destroy(data->prod);
+ BitVector_Destroy(data->rank);
+ BitVector_Destroy(data->temp);
+ }
+ yasm_xfree(data);
+}
+
+ErrCode BitVector_from_Dec_static(BitVector_from_Dec_static_data *data,
+ wordptr addr, charptr string)
+{
+ ErrCode error = ErrCode_Ok;
+ N_word bits = bits_(addr);
+ N_word mask = mask_(addr);
+ boolean init = (bits > BITS);
+ boolean minus;
+ boolean shift;
+ boolean carry;
+ wordptr term;
+ wordptr base;
+ wordptr prod;
+ wordptr rank;
+ wordptr temp;
+ N_word accu;
+ N_word powr;
+ N_word count;
+ size_t length;
+ int digit;
+
+ if (bits > 0)
+ {
+ term = data->term;
+ base = data->base;
+ prod = data->prod;
+ rank = data->rank;
+ temp = data->temp;
+
+ length = strlen((char *) string);
+ if (length == 0) return(ErrCode_Pars);
+ digit = (int) *string;
+ if ((minus = (digit == (int) '-')) or
+ (digit == (int) '+'))
+ {
+ string++;
+ if (--length == 0) return(ErrCode_Pars);
+ }
+ string += length;
+ if (init)
+ {
+ BitVector_Empty(prod);
+ BitVector_Empty(rank);
+ }
+ BitVector_Empty(addr);
+ *base = EXP10;
+ shift = FALSE;
+ while ((not error) and (length > 0))
+ {
+ accu = 0;
+ powr = 1;
+ count = LOG10;
+ while ((not error) and (length > 0) and (count-- > 0))
+ {
+ digit = (int) *(--string); length--;
+ /* separate because isdigit() is likely a macro! */
+ if (isdigit(digit) != 0)
+ {
+ accu += ((N_word) digit - (N_word) '0') * powr;
+ powr *= 10;
+ }
+ else error = ErrCode_Pars;
+ }
+ if (not error)
+ {
+ if (shift)
+ {
+ *term = accu;
+ BitVector_Copy(temp,rank);
+ error = BitVector_Mul_Pos(prod,temp,term,FALSE);
+ }
+ else
+ {
+ *prod = accu;
+ if ((not init) and ((accu AND NOT mask) != 0)) error = ErrCode_Ovfl;
+ }
+ if (not error)
+ {
+ carry = FALSE;
+ BitVector_compute(addr,addr,prod,FALSE,&carry);
+ /* ignores sign change (= overflow) but not */
+ /* numbers too large (= carry) for resulting bit vector */
+ if (carry) error = ErrCode_Ovfl;
+ else
+ {
+ if (length > 0)
+ {
+ if (shift)
+ {
+ BitVector_Copy(temp,rank);
+ error = BitVector_Mul_Pos(rank,temp,base,FALSE);
+ }
+ else
+ {
+ *rank = *base;
+ shift = TRUE;
+ }
+ }
+ }
+ }
+ }
+ }
+ if (not error and minus)
+ {
+ BitVector_Negate(addr,addr);
+ if ((*(addr + size_(addr) - 1) AND mask AND NOT (mask >> 1)) == 0)
+ error = ErrCode_Ovfl;
+ }
+ }
+ return(error);
+}
+
+ErrCode BitVector_from_Dec(wordptr addr, charptr string)
+{
+ ErrCode error = ErrCode_Ok;
+ N_word bits = bits_(addr);
+ N_word mask = mask_(addr);
+ boolean init = (bits > BITS);
+ boolean minus;
+ boolean shift;
+ boolean carry;
+ wordptr term;
+ wordptr base;
+ wordptr prod;
+ wordptr rank;
+ wordptr temp;
+ N_word accu;
+ N_word powr;
+ N_word count;
+ size_t length;
+ int digit;
+
+ if (bits > 0)
+ {
+ length = strlen((char *) string);
+ if (length == 0) return(ErrCode_Pars);
+ digit = (int) *string;
+ if ((minus = (digit == (int) '-')) or
+ (digit == (int) '+'))
+ {
+ string++;
+ if (--length == 0) return(ErrCode_Pars);
+ }
+ string += length;
+ term = BitVector_Create(BITS,FALSE);
+ if (term == NULL)
+ {
+ return(ErrCode_Null);
+ }
+ base = BitVector_Create(BITS,FALSE);
+ if (base == NULL)
+ {
+ BitVector_Destroy(term);
+ return(ErrCode_Null);
+ }
+ prod = BitVector_Create(bits,init);
+ if (prod == NULL)
+ {
+ BitVector_Destroy(term);
+ BitVector_Destroy(base);
+ return(ErrCode_Null);
+ }
+ rank = BitVector_Create(bits,init);
+ if (rank == NULL)
+ {
+ BitVector_Destroy(term);
+ BitVector_Destroy(base);
+ BitVector_Destroy(prod);
+ return(ErrCode_Null);
+ }
+ temp = BitVector_Create(bits,FALSE);
+ if (temp == NULL)
+ {
+ BitVector_Destroy(term);
+ BitVector_Destroy(base);
+ BitVector_Destroy(prod);
+ BitVector_Destroy(rank);
+ return(ErrCode_Null);
+ }
+ BitVector_Empty(addr);
+ *base = EXP10;
+ shift = FALSE;
+ while ((not error) and (length > 0))
+ {
+ accu = 0;
+ powr = 1;
+ count = LOG10;
+ while ((not error) and (length > 0) and (count-- > 0))
+ {
+ digit = (int) *(--string); length--;
+ /* separate because isdigit() is likely a macro! */
+ if (isdigit(digit) != 0)
+ {
+ accu += ((N_word) digit - (N_word) '0') * powr;
+ powr *= 10;
+ }
+ else error = ErrCode_Pars;
+ }
+ if (not error)
+ {
+ if (shift)
+ {
+ *term = accu;
+ BitVector_Copy(temp,rank);
+ error = BitVector_Mul_Pos(prod,temp,term,FALSE);
+ }
+ else
+ {
+ *prod = accu;
+ if ((not init) and ((accu AND NOT mask) != 0)) error = ErrCode_Ovfl;
+ }
+ if (not error)
+ {
+ carry = FALSE;
+ BitVector_compute(addr,addr,prod,FALSE,&carry);
+ /* ignores sign change (= overflow) but not */
+ /* numbers too large (= carry) for resulting bit vector */
+ if (carry) error = ErrCode_Ovfl;
+ else
+ {
+ if (length > 0)
+ {
+ if (shift)
+ {
+ BitVector_Copy(temp,rank);
+ error = BitVector_Mul_Pos(rank,temp,base,FALSE);
+ }
+ else
+ {
+ *rank = *base;
+ shift = TRUE;
+ }
+ }
+ }
+ }
+ }
+ }
+ BitVector_Destroy(term);
+ BitVector_Destroy(base);
+ BitVector_Destroy(prod);
+ BitVector_Destroy(rank);
+ BitVector_Destroy(temp);
+ if (not error and minus)
+ {
+ BitVector_Negate(addr,addr);
+ if ((*(addr + size_(addr) - 1) AND mask AND NOT (mask >> 1)) == 0)
+ error = ErrCode_Ovfl;
+ }
+ }
+ return(error);
+}
+
+charptr BitVector_to_Enum(wordptr addr)
+{
+ N_word bits = bits_(addr);
+ N_word sample;
+ N_word length;
+ N_word digits;
+ N_word factor;
+ N_word power;
+ N_word start;
+ N_word min;
+ N_word max;
+ charptr string;
+ charptr target;
+ boolean comma;
+
+ if (bits > 0)
+ {
+ sample = bits - 1; /* greatest possible index */
+ length = 2; /* account for index 0 and terminating '\0' */
+ digits = 1; /* account for intervening dashes and commas */
+ factor = 1;
+ power = 10;
+ while (sample >= (power-1))
+ {
+ length += ++digits * factor * 6; /* 9,90,900,9000,... (9*2/3 = 6) */
+ factor = power;
+ power *= 10;
+ }
+ if (sample > --factor)
+ {
+ sample -= factor;
+ factor = (N_word) ( sample / 3 );
+ factor = (factor << 1) + (sample - (factor * 3));
+ length += ++digits * factor;
+ }
+ }
+ else length = 1;
+ string = (charptr) yasm_xmalloc((size_t) length);
+ if (string == NULL) return(NULL);
+ start = 0;
+ comma = FALSE;
+ target = string;
+ while ((start < bits) and BitVector_interval_scan_inc(addr,start,&min,&max))
+ {
+ start = max + 2;
+ if (comma) *target++ = (N_char) ',';
+ if (min == max)
+ {
+ target += BIT_VECTOR_int2str(target,min);
+ }
+ else
+ {
+ if (min+1 == max)
+ {
+ target += BIT_VECTOR_int2str(target,min);
+ *target++ = (N_char) ',';
+ target += BIT_VECTOR_int2str(target,max);
+ }
+ else
+ {
+ target += BIT_VECTOR_int2str(target,min);
+ *target++ = (N_char) '-';
+ target += BIT_VECTOR_int2str(target,max);
+ }
+ }
+ comma = TRUE;
+ }
+ *target = (N_char) '\0';
+ return(string);
+}
+
+ErrCode BitVector_from_Enum(wordptr addr, charptr string)
+{
+ ErrCode error = ErrCode_Ok;
+ N_word bits = bits_(addr);
+ N_word state = 1;
+ N_word token;
+ N_word indx = 0; /* silence compiler warning */
+ N_word start = 0; /* silence compiler warning */
+
+ if (bits > 0)
+ {
+ BitVector_Empty(addr);
+ while ((not error) and (state != 0))
+ {
+ token = (N_word) *string;
+ /* separate because isdigit() is likely a macro! */
+ if (isdigit((int)token) != 0)
+ {
+ string += BIT_VECTOR_str2int(string,&indx);
+ if (indx < bits) token = (N_word) '0';
+ else error = ErrCode_Indx;
+ }
+ else string++;
+ if (not error)
+ switch (state)
+ {
+ case 1:
+ switch (token)
+ {
+ case (N_word) '0':
+ state = 2;
+ break;
+ case (N_word) '\0':
+ state = 0;
+ break;
+ default:
+ error = ErrCode_Pars;
+ break;
+ }
+ break;
+ case 2:
+ switch (token)
+ {
+ case (N_word) '-':
+ start = indx;
+ state = 3;
+ break;
+ case (N_word) ',':
+ BIT_VECTOR_SET_BIT(addr,indx)
+ state = 5;
+ break;
+ case (N_word) '\0':
+ BIT_VECTOR_SET_BIT(addr,indx)
+ state = 0;
+ break;
+ default:
+ error = ErrCode_Pars;
+ break;
+ }
+ break;
+ case 3:
+ switch (token)
+ {
+ case (N_word) '0':
+ if (start < indx)
+ BitVector_Interval_Fill(addr,start,indx);
+ else if (start == indx)
+ BIT_VECTOR_SET_BIT(addr,indx)
+ else error = ErrCode_Ordr;
+ state = 4;
+ break;
+ default:
+ error = ErrCode_Pars;
+ break;
+ }
+ break;
+ case 4:
+ switch (token)
+ {
+ case (N_word) ',':
+ state = 5;
+ break;
+ case (N_word) '\0':
+ state = 0;
+ break;
+ default:
+ error = ErrCode_Pars;
+ break;
+ }
+ break;
+ case 5:
+ switch (token)
+ {
+ case (N_word) '0':
+ state = 2;
+ break;
+ default:
+ error = ErrCode_Pars;
+ break;
+ }
+ break;
+ }
+ }
+ }
+ return(error);
+}
+
+void BitVector_Bit_Off(wordptr addr, N_int indx) /* X = X \ {x} */
+{
+ if (indx < bits_(addr)) BIT_VECTOR_CLR_BIT(addr,indx)
+}
+
+void BitVector_Bit_On(wordptr addr, N_int indx) /* X = X + {x} */
+{
+ if (indx < bits_(addr)) BIT_VECTOR_SET_BIT(addr,indx)
+}
+
+boolean BitVector_bit_flip(wordptr addr, N_int indx) /* X=(X+{x})\(X*{x}) */
+{
+ N_word mask;
+
+ if (indx < bits_(addr)) return( BIT_VECTOR_FLP_BIT(addr,indx,mask) );
+ else return( FALSE );
+}
+
+boolean BitVector_bit_test(wordptr addr, N_int indx) /* {x} in X ? */
+{
+ if (indx < bits_(addr)) return( BIT_VECTOR_TST_BIT(addr,indx) );
+ else return( FALSE );
+}
+
+void BitVector_Bit_Copy(wordptr addr, N_int indx, boolean bit)
+{
+ if (indx < bits_(addr))
+ {
+ if (bit) BIT_VECTOR_SET_BIT(addr,indx)
+ else BIT_VECTOR_CLR_BIT(addr,indx)
+ }
+}
+
+void BitVector_LSB(wordptr addr, boolean bit)
+{
+ if (bits_(addr) > 0)
+ {
+ if (bit) *addr |= LSB;
+ else *addr &= NOT LSB;
+ }
+}
+
+void BitVector_MSB(wordptr addr, boolean bit)
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+
+ if (size-- > 0)
+ {
+ if (bit) *(addr+size) |= mask AND NOT (mask >> 1);
+ else *(addr+size) &= NOT mask OR (mask >> 1);
+ }
+}
+
+boolean BitVector_lsb_(wordptr addr)
+{
+ if (size_(addr) > 0) return( (*addr AND LSB) != 0 );
+ else return( FALSE );
+}
+
+boolean BitVector_msb_(wordptr addr)
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+
+ if (size-- > 0)
+ return( (*(addr+size) AND (mask AND NOT (mask >> 1))) != 0 );
+ else
+ return( FALSE );
+}
+
+boolean BitVector_rotate_left(wordptr addr)
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ N_word msb;
+ boolean carry_in;
+ boolean carry_out = FALSE;
+
+ if (size > 0)
+ {
+ msb = mask AND NOT (mask >> 1);
+ carry_in = ((*(addr+size-1) AND msb) != 0);
+ while (size-- > 1)
+ {
+ carry_out = ((*addr AND MSB) != 0);
+ *addr <<= 1;
+ if (carry_in) *addr |= LSB;
+ carry_in = carry_out;
+ addr++;
+ }
+ carry_out = ((*addr AND msb) != 0);
+ *addr <<= 1;
+ if (carry_in) *addr |= LSB;
+ *addr &= mask;
+ }
+ return(carry_out);
+}
+
+boolean BitVector_rotate_right(wordptr addr)
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ N_word msb;
+ boolean carry_in;
+ boolean carry_out = FALSE;
+
+ if (size > 0)
+ {
+ msb = mask AND NOT (mask >> 1);
+ carry_in = ((*addr AND LSB) != 0);
+ addr += size-1;
+ *addr &= mask;
+ carry_out = ((*addr AND LSB) != 0);
+ *addr >>= 1;
+ if (carry_in) *addr |= msb;
+ carry_in = carry_out;
+ addr--;
+ size--;
+ while (size-- > 0)
+ {
+ carry_out = ((*addr AND LSB) != 0);
+ *addr >>= 1;
+ if (carry_in) *addr |= MSB;
+ carry_in = carry_out;
+ addr--;
+ }
+ }
+ return(carry_out);
+}
+
+boolean BitVector_shift_left(wordptr addr, boolean carry_in)
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ N_word msb;
+ boolean carry_out = carry_in;
+
+ if (size > 0)
+ {
+ msb = mask AND NOT (mask >> 1);
+ while (size-- > 1)
+ {
+ carry_out = ((*addr AND MSB) != 0);
+ *addr <<= 1;
+ if (carry_in) *addr |= LSB;
+ carry_in = carry_out;
+ addr++;
+ }
+ carry_out = ((*addr AND msb) != 0);
+ *addr <<= 1;
+ if (carry_in) *addr |= LSB;
+ *addr &= mask;
+ }
+ return(carry_out);
+}
+
+boolean BitVector_shift_right(wordptr addr, boolean carry_in)
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ N_word msb;
+ boolean carry_out = carry_in;
+
+ if (size > 0)
+ {
+ msb = mask AND NOT (mask >> 1);
+ addr += size-1;
+ *addr &= mask;
+ carry_out = ((*addr AND LSB) != 0);
+ *addr >>= 1;
+ if (carry_in) *addr |= msb;
+ carry_in = carry_out;
+ addr--;
+ size--;
+ while (size-- > 0)
+ {
+ carry_out = ((*addr AND LSB) != 0);
+ *addr >>= 1;
+ if (carry_in) *addr |= MSB;
+ carry_in = carry_out;
+ addr--;
+ }
+ }
+ return(carry_out);
+}
+
+void BitVector_Move_Left(wordptr addr, N_int bits)
+{
+ N_word count;
+ N_word words;
+
+ if (bits > 0)
+ {
+ count = bits AND MODMASK;
+ words = bits >> LOGBITS;
+ if (bits >= bits_(addr)) BitVector_Empty(addr);
+ else
+ {
+ while (count-- > 0) BitVector_shift_left(addr,0);
+ BitVector_Word_Insert(addr,0,words,TRUE);
+ }
+ }
+}
+
+void BitVector_Move_Right(wordptr addr, N_int bits)
+{
+ N_word count;
+ N_word words;
+
+ if (bits > 0)
+ {
+ count = bits AND MODMASK;
+ words = bits >> LOGBITS;
+ if (bits >= bits_(addr)) BitVector_Empty(addr);
+ else
+ {
+ while (count-- > 0) BitVector_shift_right(addr,0);
+ BitVector_Word_Delete(addr,0,words,TRUE);
+ }
+ }
+}
+
+void BitVector_Insert(wordptr addr, N_int offset, N_int count, boolean clear)
+{
+ N_word bits = bits_(addr);
+ N_word last;
+
+ if ((count > 0) and (offset < bits))
+ {
+ last = offset + count;
+ if (last < bits)
+ {
+ BitVector_Interval_Copy(addr,addr,last,offset,(bits-last));
+ }
+ else last = bits;
+ if (clear) BitVector_Interval_Empty(addr,offset,(last-1));
+ }
+}
+
+void BitVector_Delete(wordptr addr, N_int offset, N_int count, boolean clear)
+{
+ N_word bits = bits_(addr);
+ N_word last;
+
+ if ((count > 0) and (offset < bits))
+ {
+ last = offset + count;
+ if (last < bits)
+ {
+ BitVector_Interval_Copy(addr,addr,offset,last,(bits-last));
+ }
+ else count = bits - offset;
+ if (clear) BitVector_Interval_Empty(addr,(bits-count),(bits-1));
+ }
+}
+
+boolean BitVector_increment(wordptr addr) /* X++ */
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ wordptr last = addr + size - 1;
+ boolean carry = TRUE;
+
+ if (size > 0)
+ {
+ *last |= NOT mask;
+ while (carry and (size-- > 0))
+ {
+ carry = (++(*addr++) == 0);
+ }
+ *last &= mask;
+ }
+ return(carry);
+}
+
+boolean BitVector_decrement(wordptr addr) /* X-- */
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ wordptr last = addr + size - 1;
+ boolean carry = TRUE;
+
+ if (size > 0)
+ {
+ *last &= mask;
+ while (carry and (size-- > 0))
+ {
+ carry = (*addr == 0);
+ --(*addr++);
+ }
+ *last &= mask;
+ }
+ return(carry);
+}
+
+boolean BitVector_compute(wordptr X, wordptr Y, wordptr Z, boolean minus, boolean *carry)
+{
+ N_word size = size_(X);
+ N_word mask = mask_(X);
+ N_word vv = 0;
+ N_word cc;
+ N_word mm;
+ N_word yy;
+ N_word zz;
+ N_word lo;
+ N_word hi;
+
+ if (size > 0)
+ {
+ if (minus) cc = (*carry == 0);
+ else cc = (*carry != 0);
+ /* deal with (size-1) least significant full words first: */
+ while (--size > 0)
+ {
+ yy = *Y++;
+ if (minus) zz = (N_word) NOT ( Z ? *Z++ : 0 );
+ else zz = (N_word) ( Z ? *Z++ : 0 );
+ lo = (yy AND LSB) + (zz AND LSB) + cc;
+ hi = (yy >> 1) + (zz >> 1) + (lo >> 1);
+ cc = ((hi AND MSB) != 0);
+ *X++ = (hi << 1) OR (lo AND LSB);
+ }
+ /* deal with most significant word (may be used only partially): */
+ yy = *Y AND mask;
+ if (minus) zz = (N_word) NOT ( Z ? *Z : 0 );
+ else zz = (N_word) ( Z ? *Z : 0 );
+ zz &= mask;
+ if (mask == LSB) /* special case, only one bit used */
+ {
+ vv = cc;
+ lo = yy + zz + cc;
+ cc = (lo >> 1);
+ vv ^= cc;
+ *X = lo AND LSB;
+ }
+ else
+ {
+ if (NOT mask) /* not all bits are used, but more than one */
+ {
+ mm = (mask >> 1);
+ vv = (yy AND mm) + (zz AND mm) + cc;
+ mm = mask AND NOT mm;
+ lo = yy + zz + cc;
+ cc = (lo >> 1);
+ vv ^= cc;
+ vv &= mm;
+ cc &= mm;
+ *X = lo AND mask;
+ }
+ else /* other special case, all bits are used */
+ {
+ mm = NOT MSB;
+ lo = (yy AND mm) + (zz AND mm) + cc;
+ vv = lo AND MSB;
+ hi = ((yy AND MSB) >> 1) + ((zz AND MSB) >> 1) + (vv >> 1);
+ cc = hi AND MSB;
+ vv ^= cc;
+ *X = (hi << 1) OR (lo AND mm);
+ }
+ }
+ if (minus) *carry = (cc == 0);
+ else *carry = (cc != 0);
+ }
+ return(vv != 0);
+}
+
+boolean BitVector_add(wordptr X, wordptr Y, wordptr Z, boolean *carry)
+{
+ return(BitVector_compute(X,Y,Z,FALSE,carry));
+}
+
+boolean BitVector_sub(wordptr X, wordptr Y, wordptr Z, boolean *carry)
+{
+ return(BitVector_compute(X,Y,Z,TRUE,carry));
+}
+
+boolean BitVector_inc(wordptr X, wordptr Y)
+{
+ boolean carry = TRUE;
+
+ return(BitVector_compute(X,Y,NULL,FALSE,&carry));
+}
+
+boolean BitVector_dec(wordptr X, wordptr Y)
+{
+ boolean carry = TRUE;
+
+ return(BitVector_compute(X,Y,NULL,TRUE,&carry));
+}
+
+void BitVector_Negate(wordptr X, wordptr Y)
+{
+ N_word size = size_(X);
+ N_word mask = mask_(X);
+ boolean carry = TRUE;
+
+ if (size > 0)
+ {
+ while (size-- > 0)
+ {
+ *X = NOT *Y++;
+ if (carry)
+ {
+ carry = (++(*X) == 0);
+ }
+ X++;
+ }
+ *(--X) &= mask;
+ }
+}
+
+void BitVector_Absolute(wordptr X, wordptr Y)
+{
+ N_word size = size_(Y);
+ N_word mask = mask_(Y);
+
+ if (size > 0)
+ {
+ if (*(Y+size-1) AND (mask AND NOT (mask >> 1))) BitVector_Negate(X,Y);
+ else BitVector_Copy(X,Y);
+ }
+}
+
+Z_int BitVector_Sign(wordptr addr)
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ wordptr last = addr + size - 1;
+ boolean r = TRUE;
+
+ if (size > 0)
+ {
+ *last &= mask;
+ while (r and (size-- > 0)) r = ( *addr++ == 0 );
+ }
+ if (r) return((Z_int) 0);
+ else
+ {
+ if (*last AND (mask AND NOT (mask >> 1))) return((Z_int) -1);
+ else return((Z_int) 1);
+ }
+}
+
+ErrCode BitVector_Mul_Pos(wordptr X, wordptr Y, wordptr Z, boolean strict)
+{
+ N_word mask;
+ N_word limit;
+ N_word count;
+ Z_long last;
+ wordptr sign;
+ boolean carry;
+ boolean overflow;
+ boolean ok = TRUE;
+
+ /*
+ Requirements:
+ - X, Y and Z must be distinct
+ - X and Y must have equal sizes (whereas Z may be any size!)
+ - Z should always contain the SMALLER of the two factors Y and Z
+ Constraints:
+ - The contents of Y (and of X, of course) are destroyed
+ (only Z is preserved!)
+ */
+
+ if ((X == Y) or (X == Z) or (Y == Z)) return(ErrCode_Same);
+ if (bits_(X) != bits_(Y)) return(ErrCode_Size);
+ BitVector_Empty(X);
+ if (BitVector_is_empty(Y)) return(ErrCode_Ok); /* exit also taken if bits_(Y)==0 */
+ if ((last = Set_Max(Z)) < 0L) return(ErrCode_Ok);
+ limit = (N_word) last;
+ sign = Y + size_(Y) - 1;
+ mask = mask_(Y);
+ *sign &= mask;
+ mask &= NOT (mask >> 1);
+ for ( count = 0; (ok and (count <= limit)); count++ )
+ {
+ if ( BIT_VECTOR_TST_BIT(Z,count) )
+ {
+ carry = false;
+ overflow = BitVector_compute(X,X,Y,false,&carry);
+ if (strict) ok = not (carry or overflow);
+ else ok = not carry;
+ }
+ if (ok and (count < limit))
+ {
+ carry = BitVector_shift_left(Y,0);
+ if (strict)
+ {
+ overflow = ((*sign AND mask) != 0);
+ ok = not (carry or overflow);
+ }
+ else ok = not carry;
+ }
+ }
+ if (ok) return(ErrCode_Ok); else return(ErrCode_Ovfl);
+}
+
+ErrCode BitVector_Multiply(wordptr X, wordptr Y, wordptr Z)
+{
+ ErrCode error = ErrCode_Ok;
+ N_word bit_x = bits_(X);
+ N_word bit_y = bits_(Y);
+ N_word bit_z = bits_(Z);
+ N_word size;
+ N_word mask;
+ N_word msb;
+ wordptr ptr_y;
+ wordptr ptr_z;
+ boolean sgn_x;
+ boolean sgn_y;
+ boolean sgn_z;
+ boolean zero;
+ wordptr A;
+ wordptr B;
+
+ /*
+ Requirements:
+ - Y and Z must have equal sizes
+ - X must have at least the same size as Y and Z but may be larger (!)
+ Features:
+ - The contents of Y and Z are preserved
+ - X may be identical with Y or Z (or both!)
+ (in-place multiplication is possible!)
+ */
+
+ if ((bit_y != bit_z) or (bit_x < bit_y)) return(ErrCode_Size);
+ if (BitVector_is_empty(Y) or BitVector_is_empty(Z))
+ {
+ BitVector_Empty(X);
+ }
+ else
+ {
+ A = BitVector_Create(bit_y,FALSE);
+ if (A == NULL) return(ErrCode_Null);
+ B = BitVector_Create(bit_z,FALSE);
+ if (B == NULL) { BitVector_Destroy(A); return(ErrCode_Null); }
+ size = size_(Y);
+ mask = mask_(Y);
+ msb = (mask AND NOT (mask >> 1));
+ sgn_y = (((*(Y+size-1) &= mask) AND msb) != 0);
+ sgn_z = (((*(Z+size-1) &= mask) AND msb) != 0);
+ sgn_x = sgn_y XOR sgn_z;
+ if (sgn_y) BitVector_Negate(A,Y); else BitVector_Copy(A,Y);
+ if (sgn_z) BitVector_Negate(B,Z); else BitVector_Copy(B,Z);
+ ptr_y = A + size;
+ ptr_z = B + size;
+ zero = TRUE;
+ while (zero and (size-- > 0))
+ {
+ zero &= (*(--ptr_y) == 0);
+ zero &= (*(--ptr_z) == 0);
+ }
+ if (*ptr_y > *ptr_z)
+ {
+ if (bit_x > bit_y)
+ {
+ A = BitVector_Resize(A,bit_x);
+ if (A == NULL) { BitVector_Destroy(B); return(ErrCode_Null); }
+ }
+ error = BitVector_Mul_Pos(X,A,B,TRUE);
+ }
+ else
+ {
+ if (bit_x > bit_z)
+ {
+ B = BitVector_Resize(B,bit_x);
+ if (B == NULL) { BitVector_Destroy(A); return(ErrCode_Null); }
+ }
+ error = BitVector_Mul_Pos(X,B,A,TRUE);
+ }
+ if ((not error) and sgn_x) BitVector_Negate(X,X);
+ BitVector_Destroy(A);
+ BitVector_Destroy(B);
+ }
+ return(error);
+}
+
+ErrCode BitVector_Div_Pos(wordptr Q, wordptr X, wordptr Y, wordptr R)
+{
+ N_word bits = bits_(Q);
+ N_word mask;
+ wordptr addr;
+ Z_long last;
+ boolean flag;
+ boolean copy = FALSE; /* flags whether valid rest is in R (0) or X (1) */
+
+ /*
+ Requirements:
+ - All bit vectors must have equal sizes
+ - Q, X, Y and R must all be distinct bit vectors
+ - Y must be non-zero (of course!)
+ Constraints:
+ - The contents of X (and Q and R, of course) are destroyed
+ (only Y is preserved!)
+ */
+
+ if ((bits != bits_(X)) or (bits != bits_(Y)) or (bits != bits_(R)))
+ return(ErrCode_Size);
+ if ((Q == X) or (Q == Y) or (Q == R) or (X == Y) or (X == R) or (Y == R))
+ return(ErrCode_Same);
+ if (BitVector_is_empty(Y))
+ return(ErrCode_Zero);
+
+ BitVector_Empty(R);
+ BitVector_Copy(Q,X);
+ if ((last = Set_Max(Q)) < 0L) return(ErrCode_Ok);
+ bits = (N_word) ++last;
+ while (bits-- > 0)
+ {
+ addr = Q + (bits >> LOGBITS);
+ mask = BITMASKTAB[bits AND MODMASK];
+ flag = ((*addr AND mask) != 0);
+ if (copy)
+ {
+ BitVector_shift_left(X,flag);
+ flag = FALSE;
+ BitVector_compute(R,X,Y,TRUE,&flag);
+ }
+ else
+ {
+ BitVector_shift_left(R,flag);
+ flag = FALSE;
+ BitVector_compute(X,R,Y,TRUE,&flag);
+ }
+ if (flag) *addr &= NOT mask;
+ else
+ {
+ *addr |= mask;
+ copy = not copy;
+ }
+ }
+ if (copy) BitVector_Copy(R,X);
+ return(ErrCode_Ok);
+}
+
+ErrCode BitVector_Divide(wordptr Q, wordptr X, wordptr Y, wordptr R)
+{
+ ErrCode error = ErrCode_Ok;
+ N_word bits = bits_(Q);
+ N_word size = size_(Q);
+ N_word mask = mask_(Q);
+ N_word msb = (mask AND NOT (mask >> 1));
+ boolean sgn_q;
+ boolean sgn_x;
+ boolean sgn_y;
+ wordptr A;
+ wordptr B;
+
+ /*
+ Requirements:
+ - All bit vectors must have equal sizes
+ - Q and R must be two distinct bit vectors
+ - Y must be non-zero (of course!)
+ Features:
+ - The contents of X and Y are preserved
+ - Q may be identical with X or Y (or both)
+ (in-place division is possible!)
+ - R may be identical with X or Y (or both)
+ (but not identical with Q!)
+ */
+
+ if ((bits != bits_(X)) or (bits != bits_(Y)) or (bits != bits_(R)))
+ return(ErrCode_Size);
+ if (Q == R)
+ return(ErrCode_Same);
+ if (BitVector_is_empty(Y))
+ return(ErrCode_Zero);
+
+ if (BitVector_is_empty(X))
+ {
+ BitVector_Empty(Q);
+ BitVector_Empty(R);
+ }
+ else
+ {
+ A = BitVector_Create(bits,FALSE);
+ if (A == NULL) return(ErrCode_Null);
+ B = BitVector_Create(bits,FALSE);
+ if (B == NULL) { BitVector_Destroy(A); return(ErrCode_Null); }
+ size--;
+ sgn_x = (((*(X+size) &= mask) AND msb) != 0);
+ sgn_y = (((*(Y+size) &= mask) AND msb) != 0);
+ sgn_q = sgn_x XOR sgn_y;
+ if (sgn_x) BitVector_Negate(A,X); else BitVector_Copy(A,X);
+ if (sgn_y) BitVector_Negate(B,Y); else BitVector_Copy(B,Y);
+ if (not (error = BitVector_Div_Pos(Q,A,B,R)))
+ {
+ if (sgn_q) BitVector_Negate(Q,Q);
+ if (sgn_x) BitVector_Negate(R,R);
+ }
+ BitVector_Destroy(A);
+ BitVector_Destroy(B);
+ }
+ return(error);
+}
+
+ErrCode BitVector_GCD(wordptr X, wordptr Y, wordptr Z)
+{
+ ErrCode error = ErrCode_Ok;
+ N_word bits = bits_(X);
+ N_word size = size_(X);
+ N_word mask = mask_(X);
+ N_word msb = (mask AND NOT (mask >> 1));
+ boolean sgn_a;
+ boolean sgn_b;
+ boolean sgn_r;
+ wordptr Q;
+ wordptr R;
+ wordptr A;
+ wordptr B;
+ wordptr T;
+
+ /*
+ Requirements:
+ - All bit vectors must have equal sizes
+ Features:
+ - The contents of Y and Z are preserved
+ - X may be identical with Y or Z (or both)
+ (in-place is possible!)
+ - GCD(0,z) == GCD(z,0) == z
+ - negative values are handled correctly
+ */
+
+ if ((bits != bits_(Y)) or (bits != bits_(Z))) return(ErrCode_Size);
+ if (BitVector_is_empty(Y))
+ {
+ if (X != Z) BitVector_Copy(X,Z);
+ return(ErrCode_Ok);
+ }
+ if (BitVector_is_empty(Z))
+ {
+ if (X != Y) BitVector_Copy(X,Y);
+ return(ErrCode_Ok);
+ }
+ Q = BitVector_Create(bits,false);
+ if (Q == NULL)
+ {
+ return(ErrCode_Null);
+ }
+ R = BitVector_Create(bits,FALSE);
+ if (R == NULL)
+ {
+ BitVector_Destroy(Q);
+ return(ErrCode_Null);
+ }
+ A = BitVector_Create(bits,FALSE);
+ if (A == NULL)
+ {
+ BitVector_Destroy(Q);
+ BitVector_Destroy(R);
+ return(ErrCode_Null);
+ }
+ B = BitVector_Create(bits,FALSE);
+ if (B == NULL)
+ {
+ BitVector_Destroy(Q);
+ BitVector_Destroy(R);
+ BitVector_Destroy(A);
+ return(ErrCode_Null);
+ }
+ size--;
+ sgn_a = (((*(Y+size) &= mask) AND msb) != 0);
+ sgn_b = (((*(Z+size) &= mask) AND msb) != 0);
+ if (sgn_a) BitVector_Negate(A,Y); else BitVector_Copy(A,Y);
+ if (sgn_b) BitVector_Negate(B,Z); else BitVector_Copy(B,Z);
+ while (not error)
+ {
+ if (not (error = BitVector_Div_Pos(Q,A,B,R)))
+ {
+ if (BitVector_is_empty(R)) break;
+ T = A; sgn_r = sgn_a;
+ A = B; sgn_a = sgn_b;
+ B = R; sgn_b = sgn_r;
+ R = T;
+ }
+ }
+ if (not error)
+ {
+ if (sgn_b) BitVector_Negate(X,B); else BitVector_Copy(X,B);
+ }
+ BitVector_Destroy(Q);
+ BitVector_Destroy(R);
+ BitVector_Destroy(A);
+ BitVector_Destroy(B);
+ return(error);
+}
+
+ErrCode BitVector_GCD2(wordptr U, wordptr V, wordptr W, wordptr X, wordptr Y)
+{
+ ErrCode error = ErrCode_Ok;
+ N_word bits = bits_(U);
+ N_word size = size_(U);
+ N_word mask = mask_(U);
+ N_word msb = (mask AND NOT (mask >> 1));
+ boolean minus;
+ boolean carry;
+ boolean sgn_q;
+ boolean sgn_r;
+ boolean sgn_a;
+ boolean sgn_b;
+ boolean sgn_x;
+ boolean sgn_y;
+ listptr L;
+ wordptr Q;
+ wordptr R;
+ wordptr A;
+ wordptr B;
+ wordptr T;
+ wordptr X1;
+ wordptr X2;
+ wordptr X3;
+ wordptr Y1;
+ wordptr Y2;
+ wordptr Y3;
+ wordptr Z;
+
+ /*
+ Requirements:
+ - All bit vectors must have equal sizes
+ - U, V, and W must all be distinct bit vectors
+ Features:
+ - The contents of X and Y are preserved
+ - U, V and W may be identical with X or Y (or both,
+ provided that U, V and W are mutually distinct)
+ (i.e., in-place is possible!)
+ - GCD(0,z) == GCD(z,0) == z
+ - negative values are handled correctly
+ */
+
+ if ((bits != bits_(V)) or
+ (bits != bits_(W)) or
+ (bits != bits_(X)) or
+ (bits != bits_(Y)))
+ {
+ return(ErrCode_Size);
+ }
+ if ((U == V) or (U == W) or (V == W))
+ {
+ return(ErrCode_Same);
+ }
+ if (BitVector_is_empty(X))
+ {
+ if (U != Y) BitVector_Copy(U,Y);
+ BitVector_Empty(V);
+ BitVector_Empty(W);
+ *W = 1;
+ return(ErrCode_Ok);
+ }
+ if (BitVector_is_empty(Y))
+ {
+ if (U != X) BitVector_Copy(U,X);
+ BitVector_Empty(V);
+ BitVector_Empty(W);
+ *V = 1;
+ return(ErrCode_Ok);
+ }
+ if ((L = BitVector_Create_List(bits,false,11)) == NULL)
+ {
+ return(ErrCode_Null);
+ }
+ Q = L[0];
+ R = L[1];
+ A = L[2];
+ B = L[3];
+ X1 = L[4];
+ X2 = L[5];
+ X3 = L[6];
+ Y1 = L[7];
+ Y2 = L[8];
+ Y3 = L[9];
+ Z = L[10];
+ size--;
+ sgn_a = (((*(X+size) &= mask) AND msb) != 0);
+ sgn_b = (((*(Y+size) &= mask) AND msb) != 0);
+ if (sgn_a) BitVector_Negate(A,X); else BitVector_Copy(A,X);
+ if (sgn_b) BitVector_Negate(B,Y); else BitVector_Copy(B,Y);
+ BitVector_Empty(X1);
+ BitVector_Empty(X2);
+ *X1 = 1;
+ BitVector_Empty(Y1);
+ BitVector_Empty(Y2);
+ *Y2 = 1;
+ sgn_x = false;
+ sgn_y = false;
+ while (not error)
+ {
+ if ((error = BitVector_Div_Pos(Q,A,B,R)))
+ {
+ break;
+ }
+ if (BitVector_is_empty(R))
+ {
+ break;
+ }
+ sgn_q = sgn_a XOR sgn_b;
+
+ if (sgn_x) BitVector_Negate(Z,X2); else BitVector_Copy(Z,X2);
+ if ((error = BitVector_Mul_Pos(X3,Z,Q,true)))
+ {
+ break;
+ }
+ minus = not (sgn_x XOR sgn_q);
+ carry = 0;
+ if (BitVector_compute(X3,X1,X3,minus,&carry))
+ {
+ error = ErrCode_Ovfl;
+ break;
+ }
+ sgn_x = (((*(X3+size) &= mask) AND msb) != 0);
+
+ if (sgn_y) BitVector_Negate(Z,Y2); else BitVector_Copy(Z,Y2);
+ if ((error = BitVector_Mul_Pos(Y3,Z,Q,true)))
+ {
+ break;
+ }
+ minus = not (sgn_y XOR sgn_q);
+ carry = 0;
+ if (BitVector_compute(Y3,Y1,Y3,minus,&carry))
+ {
+ error = ErrCode_Ovfl;
+ break;
+ }
+ sgn_y = (((*(Y3+size) &= mask) AND msb) != 0);
+
+ T = A; sgn_r = sgn_a;
+ A = B; sgn_a = sgn_b;
+ B = R; sgn_b = sgn_r;
+ R = T;
+
+ T = X1;
+ X1 = X2;
+ X2 = X3;
+ X3 = T;
+
+ T = Y1;
+ Y1 = Y2;
+ Y2 = Y3;
+ Y3 = T;
+ }
+ if (not error)
+ {
+ if (sgn_b) BitVector_Negate(U,B); else BitVector_Copy(U,B);
+ BitVector_Copy(V,X2);
+ BitVector_Copy(W,Y2);
+ }
+ BitVector_Destroy_List(L,11);
+ return(error);
+}
+
+ErrCode BitVector_Power(wordptr X, wordptr Y, wordptr Z)
+{
+ ErrCode error = ErrCode_Ok;
+ N_word bits = bits_(X);
+ boolean first = TRUE;
+ Z_long last;
+ N_word limit;
+ N_word count;
+ wordptr T;
+
+ /*
+ Requirements:
+ - X must have at least the same size as Y but may be larger (!)
+ - X may not be identical with Z
+ - Z must be positive
+ Features:
+ - The contents of Y and Z are preserved
+ */
+
+ if (X == Z) return(ErrCode_Same);
+ if (bits < bits_(Y)) return(ErrCode_Size);
+ if (BitVector_msb_(Z)) return(ErrCode_Expo);
+ if ((last = Set_Max(Z)) < 0L)
+ {
+ if (bits < 2) return(ErrCode_Ovfl);
+ BitVector_Empty(X);
+ *X |= LSB;
+ return(ErrCode_Ok); /* anything ^ 0 == 1 */
+ }
+ if (BitVector_is_empty(Y))
+ {
+ if (X != Y) BitVector_Empty(X);
+ return(ErrCode_Ok); /* 0 ^ anything not zero == 0 */
+ }
+ T = BitVector_Create(bits,FALSE);
+ if (T == NULL) return(ErrCode_Null);
+ limit = (N_word) last;
+ for ( count = 0; ((!error) and (count <= limit)); count++ )
+ {
+ if ( BIT_VECTOR_TST_BIT(Z,count) )
+ {
+ if (first)
+ {
+ first = FALSE;
+ if (count) { BitVector_Copy(X,T); }
+ else { if (X != Y) BitVector_Copy(X,Y); }
+ }
+ else error = BitVector_Multiply(X,T,X); /* order important because T > X */
+ }
+ if ((!error) and (count < limit))
+ {
+ if (count) error = BitVector_Multiply(T,T,T);
+ else error = BitVector_Multiply(T,Y,Y);
+ }
+ }
+ BitVector_Destroy(T);
+ return(error);
+}
+
+void BitVector_Block_Store(wordptr addr, charptr buffer, N_int length)
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ N_word value;
+ N_word count;
+
+ /* provide translation for independence of endian-ness: */
+ if (size > 0)
+ {
+ while (size-- > 0)
+ {
+ value = 0;
+ for ( count = 0; (length > 0) and (count < BITS); count += 8 )
+ {
+ value |= (((N_word) *buffer++) << count); length--;
+ }
+ *addr++ = value;
+ }
+ *(--addr) &= mask;
+ }
+}
+
+charptr BitVector_Block_Read(wordptr addr, N_intptr length)
+{
+ N_word size = size_(addr);
+ N_word value;
+ N_word count;
+ charptr buffer;
+ charptr target;
+
+ /* provide translation for independence of endian-ness: */
+ *length = size << FACTOR;
+ buffer = (charptr) yasm_xmalloc((size_t) ((*length)+1));
+ if (buffer == NULL) return(NULL);
+ target = buffer;
+ if (size > 0)
+ {
+ *(addr+size-1) &= mask_(addr);
+ while (size-- > 0)
+ {
+ value = *addr++;
+ count = BITS >> 3;
+ while (count-- > 0)
+ {
+ *target++ = (N_char) (value AND 0x00FF);
+ if (count > 0) value >>= 8;
+ }
+ }
+ }
+ *target = (N_char) '\0';
+ return(buffer);
+}
+
+void BitVector_Word_Store(wordptr addr, N_int offset, N_int value)
+{
+ N_word size = size_(addr);
+
+ if (size > 0)
+ {
+ if (offset < size) *(addr+offset) = value;
+ *(addr+size-1) &= mask_(addr);
+ }
+}
+
+N_int BitVector_Word_Read(wordptr addr, N_int offset)
+{
+ N_word size = size_(addr);
+
+ if (size > 0)
+ {
+ *(addr+size-1) &= mask_(addr);
+ if (offset < size) return( *(addr+offset) );
+ }
+ return( (N_int) 0 );
+}
+
+void BitVector_Word_Insert(wordptr addr, N_int offset, N_int count,
+ boolean clear)
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ wordptr last = addr+size-1;
+
+ if (size > 0)
+ {
+ *last &= mask;
+ if (offset > size) offset = size;
+ BIT_VECTOR_ins_words(addr+offset,size-offset,count,clear);
+ *last &= mask;
+ }
+}
+
+void BitVector_Word_Delete(wordptr addr, N_int offset, N_int count,
+ boolean clear)
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ wordptr last = addr+size-1;
+
+ if (size > 0)
+ {
+ *last &= mask;
+ if (offset > size) offset = size;
+ BIT_VECTOR_del_words(addr+offset,size-offset,count,clear);
+ *last &= mask;
+ }
+}
+
+void BitVector_Chunk_Store(wordptr addr, N_int chunksize, N_int offset,
+ N_long value)
+{
+ N_word bits = bits_(addr);
+ N_word mask;
+ N_word temp;
+
+ if ((chunksize > 0) and (offset < bits))
+ {
+ if (chunksize > LONGBITS) chunksize = LONGBITS;
+ if ((offset + chunksize) > bits) chunksize = bits - offset;
+ addr += offset >> LOGBITS;
+ offset &= MODMASK;
+ while (chunksize > 0)
+ {
+ mask = (N_word) (~0L << offset);
+ bits = offset + chunksize;
+ if (bits < BITS)
+ {
+ mask &= (N_word) ~(~0L << bits);
+ bits = chunksize;
+ }
+ else bits = BITS - offset;
+ temp = (N_word) (value << offset);
+ temp &= mask;
+ *addr &= NOT mask;
+ *addr++ |= temp;
+ value >>= bits;
+ chunksize -= bits;
+ offset = 0;
+ }
+ }
+}
+
+N_long BitVector_Chunk_Read(wordptr addr, N_int chunksize, N_int offset)
+{
+ N_word bits = bits_(addr);
+ N_word chunkbits = 0;
+ N_long value = 0L;
+ N_long temp;
+ N_word mask;
+
+ if ((chunksize > 0) and (offset < bits))
+ {
+ if (chunksize > LONGBITS) chunksize = LONGBITS;
+ if ((offset + chunksize) > bits) chunksize = bits - offset;
+ addr += offset >> LOGBITS;
+ offset &= MODMASK;
+ while (chunksize > 0)
+ {
+ bits = offset + chunksize;
+ if (bits < BITS)
+ {
+ mask = (N_word) ~(~0L << bits);
+ bits = chunksize;
+ }
+ else
+ {
+ mask = (N_word) ~0L;
+ bits = BITS - offset;
+ }
+ temp = (N_long) ((*addr++ AND mask) >> offset);
+ value |= temp << chunkbits;
+ chunkbits += bits;
+ chunksize -= bits;
+ offset = 0;
+ }
+ }
+ return(value);
+}
+
+ /*******************/
+ /* set operations: */
+ /*******************/
+
+void Set_Union(wordptr X, wordptr Y, wordptr Z) /* X = Y + Z */
+{
+ N_word bits = bits_(X);
+ N_word size = size_(X);
+ N_word mask = mask_(X);
+
+ if ((size > 0) and (bits == bits_(Y)) and (bits == bits_(Z)))
+ {
+ while (size-- > 0) *X++ = *Y++ OR *Z++;
+ *(--X) &= mask;
+ }
+}
+
+void Set_Intersection(wordptr X, wordptr Y, wordptr Z) /* X = Y * Z */
+{
+ N_word bits = bits_(X);
+ N_word size = size_(X);
+ N_word mask = mask_(X);
+
+ if ((size > 0) and (bits == bits_(Y)) and (bits == bits_(Z)))
+ {
+ while (size-- > 0) *X++ = *Y++ AND *Z++;
+ *(--X) &= mask;
+ }
+}
+
+void Set_Difference(wordptr X, wordptr Y, wordptr Z) /* X = Y \ Z */
+{
+ N_word bits = bits_(X);
+ N_word size = size_(X);
+ N_word mask = mask_(X);
+
+ if ((size > 0) and (bits == bits_(Y)) and (bits == bits_(Z)))
+ {
+ while (size-- > 0) *X++ = *Y++ AND NOT *Z++;
+ *(--X) &= mask;
+ }
+}
+
+void Set_ExclusiveOr(wordptr X, wordptr Y, wordptr Z) /* X=(Y+Z)\(Y*Z) */
+{
+ N_word bits = bits_(X);
+ N_word size = size_(X);
+ N_word mask = mask_(X);
+
+ if ((size > 0) and (bits == bits_(Y)) and (bits == bits_(Z)))
+ {
+ while (size-- > 0) *X++ = *Y++ XOR *Z++;
+ *(--X) &= mask;
+ }
+}
+
+void Set_Complement(wordptr X, wordptr Y) /* X = ~Y */
+{
+ N_word size = size_(X);
+ N_word mask = mask_(X);
+
+ if ((size > 0) and (bits_(X) == bits_(Y)))
+ {
+ while (size-- > 0) *X++ = NOT *Y++;
+ *(--X) &= mask;
+ }
+}
+
+ /******************/
+ /* set functions: */
+ /******************/
+
+boolean Set_subset(wordptr X, wordptr Y) /* X subset Y ? */
+{
+ N_word size = size_(X);
+ boolean r = FALSE;
+
+ if ((size > 0) and (bits_(X) == bits_(Y)))
+ {
+ r = TRUE;
+ while (r and (size-- > 0)) r = ((*X++ AND NOT *Y++) == 0);
+ }
+ return(r);
+}
+
+N_int Set_Norm(wordptr addr) /* = | X | */
+{
+ byteptr byte;
+ N_word bytes;
+ N_int n;
+
+ byte = (byteptr) addr;
+ bytes = size_(addr) << FACTOR;
+ n = 0;
+ while (bytes-- > 0)
+ {
+ n += BitVector_BYTENORM[*byte++];
+ }
+ return(n);
+}
+
+N_int Set_Norm2(wordptr addr) /* = | X | */
+{
+ N_word size = size_(addr);
+ N_word w0,w1;
+ N_int n,k;
+
+ n = 0;
+ while (size-- > 0)
+ {
+ k = 0;
+ w1 = NOT (w0 = *addr++);
+ while (w0 and w1)
+ {
+ w0 &= w0 - 1;
+ w1 &= w1 - 1;
+ k++;
+ }
+ if (w0 == 0) n += k;
+ else n += BITS - k;
+ }
+ return(n);
+}
+
+N_int Set_Norm3(wordptr addr) /* = | X | */
+{
+ N_word size = size_(addr);
+ N_int count = 0;
+ N_word c;
+
+ while (size-- > 0)
+ {
+ c = *addr++;
+ while (c)
+ {
+ c &= c - 1;
+ count++;
+ }
+ }
+ return(count);
+}
+
+Z_long Set_Min(wordptr addr) /* = min(X) */
+{
+ boolean empty = TRUE;
+ N_word size = size_(addr);
+ N_word i = 0;
+ N_word c = 0; /* silence compiler warning */
+
+ while (empty and (size-- > 0))
+ {
+ if ((c = *addr++)) empty = false; else i++;
+ }
+ if (empty) return((Z_long) LONG_MAX); /* plus infinity */
+ i <<= LOGBITS;
+ while (not (c AND LSB))
+ {
+ c >>= 1;
+ i++;
+ }
+ return((Z_long) i);
+}
+
+Z_long Set_Max(wordptr addr) /* = max(X) */
+{
+ boolean empty = TRUE;
+ N_word size = size_(addr);
+ N_word i = size;
+ N_word c = 0; /* silence compiler warning */
+
+ addr += size-1;
+ while (empty and (size-- > 0))
+ {
+ if ((c = *addr--)) empty = false; else i--;
+ }
+ if (empty) return((Z_long) LONG_MIN); /* minus infinity */
+ i <<= LOGBITS;
+ while (not (c AND MSB))
+ {
+ c <<= 1;
+ i--;
+ }
+ return((Z_long) --i);
+}
+
+ /**********************************/
+ /* matrix-of-booleans operations: */
+ /**********************************/
+
+void Matrix_Multiplication(wordptr X, N_int rowsX, N_int colsX,
+ wordptr Y, N_int rowsY, N_int colsY,
+ wordptr Z, N_int rowsZ, N_int colsZ)
+{
+ N_word i;
+ N_word j;
+ N_word k;
+ N_word indxX;
+ N_word indxY;
+ N_word indxZ;
+ N_word termX;
+ N_word termY;
+ N_word sum;
+
+ if ((colsY == rowsZ) and (rowsX == rowsY) and (colsX == colsZ) and
+ (bits_(X) == rowsX*colsX) and
+ (bits_(Y) == rowsY*colsY) and
+ (bits_(Z) == rowsZ*colsZ))
+ {
+ for ( i = 0; i < rowsY; i++ )
+ {
+ termX = i * colsX;
+ termY = i * colsY;
+ for ( j = 0; j < colsZ; j++ )
+ {
+ indxX = termX + j;
+ sum = 0;
+ for ( k = 0; k < colsY; k++ )
+ {
+ indxY = termY + k;
+ indxZ = k * colsZ + j;
+ if ( BIT_VECTOR_TST_BIT(Y,indxY) &&
+ BIT_VECTOR_TST_BIT(Z,indxZ) ) sum ^= 1;
+ }
+ if (sum) BIT_VECTOR_SET_BIT(X,indxX)
+ else BIT_VECTOR_CLR_BIT(X,indxX)
+ }
+ }
+ }
+}
+
+void Matrix_Product(wordptr X, N_int rowsX, N_int colsX,
+ wordptr Y, N_int rowsY, N_int colsY,
+ wordptr Z, N_int rowsZ, N_int colsZ)
+{
+ N_word i;
+ N_word j;
+ N_word k;
+ N_word indxX;
+ N_word indxY;
+ N_word indxZ;
+ N_word termX;
+ N_word termY;
+ N_word sum;
+
+ if ((colsY == rowsZ) and (rowsX == rowsY) and (colsX == colsZ) and
+ (bits_(X) == rowsX*colsX) and
+ (bits_(Y) == rowsY*colsY) and
+ (bits_(Z) == rowsZ*colsZ))
+ {
+ for ( i = 0; i < rowsY; i++ )
+ {
+ termX = i * colsX;
+ termY = i * colsY;
+ for ( j = 0; j < colsZ; j++ )
+ {
+ indxX = termX + j;
+ sum = 0;
+ for ( k = 0; k < colsY; k++ )
+ {
+ indxY = termY + k;
+ indxZ = k * colsZ + j;
+ if ( BIT_VECTOR_TST_BIT(Y,indxY) &&
+ BIT_VECTOR_TST_BIT(Z,indxZ) ) sum |= 1;
+ }
+ if (sum) BIT_VECTOR_SET_BIT(X,indxX)
+ else BIT_VECTOR_CLR_BIT(X,indxX)
+ }
+ }
+ }
+}
+
+void Matrix_Closure(wordptr addr, N_int rows, N_int cols)
+{
+ N_word i;
+ N_word j;
+ N_word k;
+ N_word ii;
+ N_word ij;
+ N_word ik;
+ N_word kj;
+ N_word termi;
+ N_word termk;
+
+ if ((rows == cols) and (bits_(addr) == rows*cols))
+ {
+ for ( i = 0; i < rows; i++ )
+ {
+ ii = i * cols + i;
+ BIT_VECTOR_SET_BIT(addr,ii)
+ }
+ for ( k = 0; k < rows; k++ )
+ {
+ termk = k * cols;
+ for ( i = 0; i < rows; i++ )
+ {
+ termi = i * cols;
+ ik = termi + k;
+ for ( j = 0; j < rows; j++ )
+ {
+ ij = termi + j;
+ kj = termk + j;
+ if ( BIT_VECTOR_TST_BIT(addr,ik) &&
+ BIT_VECTOR_TST_BIT(addr,kj) )
+ BIT_VECTOR_SET_BIT(addr,ij)
+ }
+ }
+ }
+ }
+}
+
+void Matrix_Transpose(wordptr X, N_int rowsX, N_int colsX,
+ wordptr Y, N_int rowsY, N_int colsY)
+{
+ N_word i;
+ N_word j;
+ N_word ii;
+ N_word ij;
+ N_word ji;
+ N_word addii;
+ N_word addij;
+ N_word addji;
+ N_word bitii;
+ N_word bitij;
+ N_word bitji;
+ N_word termi;
+ N_word termj;
+ boolean swap;
+
+ /* BEWARE that "in-place" is ONLY possible if the matrix is quadratic!! */
+
+ if ((rowsX == colsY) and (colsX == rowsY) and
+ (bits_(X) == rowsX*colsX) and
+ (bits_(Y) == rowsY*colsY))
+ {
+ if (rowsY == colsY) /* in-place is possible! */
+ {
+ for ( i = 0; i < rowsY; i++ )
+ {
+ termi = i * colsY;
+ for ( j = 0; j < i; j++ )
+ {
+ termj = j * colsX;
+ ij = termi + j;
+ ji = termj + i;
+ addij = ij >> LOGBITS;
+ addji = ji >> LOGBITS;
+ bitij = BITMASKTAB[ij AND MODMASK];
+ bitji = BITMASKTAB[ji AND MODMASK];
+ swap = ((*(Y+addij) AND bitij) != 0);
+ if ((*(Y+addji) AND bitji) != 0)
+ *(X+addij) |= bitij;
+ else
+ *(X+addij) &= NOT bitij;
+ if (swap)
+ *(X+addji) |= bitji;
+ else
+ *(X+addji) &= NOT bitji;
+ }
+ ii = termi + i;
+ addii = ii >> LOGBITS;
+ bitii = BITMASKTAB[ii AND MODMASK];
+ if ((*(Y+addii) AND bitii) != 0)
+ *(X+addii) |= bitii;
+ else
+ *(X+addii) &= NOT bitii;
+ }
+ }
+ else /* rowsX != colsX, in-place is NOT possible! */
+ {
+ for ( i = 0; i < rowsY; i++ )
+ {
+ termi = i * colsY;
+ for ( j = 0; j < colsY; j++ )
+ {
+ termj = j * colsX;
+ ij = termi + j;
+ ji = termj + i;
+ addij = ij >> LOGBITS;
+ addji = ji >> LOGBITS;
+ bitij = BITMASKTAB[ij AND MODMASK];
+ bitji = BITMASKTAB[ji AND MODMASK];
+ if ((*(Y+addij) AND bitij) != 0)
+ *(X+addji) |= bitji;
+ else
+ *(X+addji) &= NOT bitji;
+ }
+ }
+ }
+ }
+}
+
+/*****************************************************************************/
+/* VERSION: 6.4 */
+/*****************************************************************************/
+/* VERSION HISTORY: */
+/*****************************************************************************/
+/* */
+/* Version 6.4 03.10.04 Added C++ comp. directives. Improved "Norm()". */
+/* Version 6.3 28.09.02 Added "Create_List()" and "GCD2()". */
+/* Version 6.2 15.09.02 Overhauled error handling. Fixed "GCD()". */
+/* Version 6.1 08.10.01 Make VMS linker happy: _lsb,_msb => _lsb_,_msb_ */
+/* Version 6.0 08.10.00 Corrected overflow handling. */
+/* Version 5.8 14.07.00 Added "Power()". Changed "Copy()". */
+/* Version 5.7 19.05.99 Quickened "Div_Pos()". Added "Product()". */
+/* Version 5.6 02.11.98 Leading zeros eliminated in "to_Hex()". */
+/* Version 5.5 21.09.98 Fixed bug of uninitialized "error" in Multiply. */
+/* Version 5.4 07.09.98 Fixed bug of uninitialized "error" in Divide. */
+/* Version 5.3 12.05.98 Improved Norm. Completed history. */
+/* Version 5.2 31.03.98 Improved Norm. */
+/* Version 5.1 09.03.98 No changes. */
+/* Version 5.0 01.03.98 Major additions and rewrite. */
+/* Version 4.2 16.07.97 Added is_empty, is_full. */
+/* Version 4.1 30.06.97 Added word-ins/del, move-left/right, inc/dec. */
+/* Version 4.0 23.04.97 Rewrite. Added bit shift and bool. matrix ops. */
+/* Version 3.2 04.02.97 Added interval methods. */
+/* Version 3.1 21.01.97 Fixed bug on 64 bit machines. */
+/* Version 3.0 12.01.97 Added flip. */
+/* Version 2.0 14.12.96 Efficiency and consistency improvements. */
+/* Version 1.1 08.01.96 Added Resize and ExclusiveOr. */
+/* Version 1.0 14.12.95 First version under UNIX (with Perl module). */
+/* Version 0.9 01.11.93 First version of C library under MS-DOS. */
+/* Version 0.1 ??.??.89 First version in Turbo Pascal under CP/M. */
+/* */
+/*****************************************************************************/
+/* AUTHOR: */
+/*****************************************************************************/
+/* */
+/* Steffen Beyer */
+/* mailto:sb@engelschall.com */
+/* http://www.engelschall.com/u/sb/download/ */
+/* */
+/*****************************************************************************/
+/* COPYRIGHT: */
+/*****************************************************************************/
+/* */
+/* Copyright (c) 1995 - 2004 by Steffen Beyer. */
+/* All rights reserved. */
+/* */
+/*****************************************************************************/
+/* LICENSE: */
+/*****************************************************************************/
+/* This package is free software; you can use, modify and redistribute */
+/* it under the same terms as Perl itself, i.e., under the terms of */
+/* the "Artistic License" or the "GNU General Public License". */
+/* */
+/* The C library at the core of this Perl module can additionally */
+/* be used, modified and redistributed under the terms of the */
+/* "GNU Library General Public License". */
+/* */
+/*****************************************************************************/
+/* ARTISTIC LICENSE: */
+/*****************************************************************************/
+/*
+ The "Artistic License"
+
+ Preamble
+
+The intent of this document is to state the conditions under which a
+Package may be copied, such that the Copyright Holder maintains some
+semblance of artistic control over the development of the package,
+while giving the users of the package the right to use and distribute
+the Package in a more-or-less customary fashion, plus the right to make
+reasonable modifications.
+
+Definitions:
+
+ "Package" refers to the collection of files distributed by the
+ Copyright Holder, and derivatives of that collection of files
+ created through textual modification.
+
+ "Standard Version" refers to such a Package if it has not been
+ modified, or has been modified in accordance with the wishes
+ of the Copyright Holder as specified below.
+
+ "Copyright Holder" is whoever is named in the copyright or
+ copyrights for the package.
+
+ "You" is you, if you're thinking about copying or distributing
+ this Package.
+
+ "Reasonable copying fee" is whatever you can justify on the
+ basis of media cost, duplication charges, time of people involved,
+ and so on. (You will not be required to justify it to the
+ Copyright Holder, but only to the computing community at large
+ as a market that must bear the fee.)
+
+ "Freely Available" means that no fee is charged for the item
+ itself, though there may be fees involved in handling the item.
+ It also means that recipients of the item may redistribute it
+ under the same conditions they received it.
+
+1. You may make and give away verbatim copies of the source form of the
+Standard Version of this Package without restriction, provided that you
+duplicate all of the original copyright notices and associated disclaimers.
+
+2. You may apply bug fixes, portability fixes and other modifications
+derived from the Public Domain or from the Copyright Holder. A Package
+modified in such a way shall still be considered the Standard Version.
+
+3. You may otherwise modify your copy of this Package in any way, provided
+that you insert a prominent notice in each changed file stating how and
+when you changed that file, and provided that you do at least ONE of the
+following:
+
+ a) place your modifications in the Public Domain or otherwise make them
+ Freely Available, such as by posting said modifications to Usenet or
+ an equivalent medium, or placing the modifications on a major archive
+ site such as uunet.uu.net, or by allowing the Copyright Holder to include
+ your modifications in the Standard Version of the Package.
+
+ b) use the modified Package only within your corporation or organization.
+
+ c) rename any non-standard executables so the names do not conflict
+ with standard executables, which must also be provided, and provide
+ a separate manual page for each non-standard executable that clearly
+ documents how it differs from the Standard Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+
+4. You may distribute the programs of this Package in object code or
+executable form, provided that you do at least ONE of the following:
+
+ a) distribute a Standard Version of the executables and library files,
+ together with instructions (in the manual page or equivalent) on where
+ to get the Standard Version.
+
+ b) accompany the distribution with the machine-readable source of
+ the Package with your modifications.
+
+ c) give non-standard executables non-standard names, and clearly
+ document the differences in manual pages (or equivalent), together
+ with instructions on where to get the Standard Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+
+5. You may charge a reasonable copying fee for any distribution of this
+Package. You may charge any fee you choose for support of this
+Package. You may not charge a fee for this Package itself. However,
+you may distribute this Package in aggregate with other (possibly
+commercial) programs as part of a larger (possibly commercial) software
+distribution provided that you do not advertise this Package as a
+product of your own. You may embed this Package's interpreter within
+an executable of yours (by linking); this shall be construed as a mere
+form of aggregation, provided that the complete Standard Version of the
+interpreter is so embedded.
+
+6. The scripts and library files supplied as input to or produced as
+output from the programs of this Package do not automatically fall
+under the copyright of this Package, but belong to whoever generated
+them, and may be sold commercially, and may be aggregated with this
+Package. If such scripts or library files are aggregated with this
+Package via the so-called "undump" or "unexec" methods of producing a
+binary executable image, then distribution of such an image shall
+neither be construed as a distribution of this Package nor shall it
+fall under the restrictions of Paragraphs 3 and 4, provided that you do
+not represent such an executable image as a Standard Version of this
+Package.
+
+7. C subroutines (or comparably compiled subroutines in other
+languages) supplied by you and linked into this Package in order to
+emulate subroutines and variables of the language defined by this
+Package shall not be considered part of this Package, but are the
+equivalent of input as in Paragraph 6, provided these subroutines do
+not change the language in any way that would cause it to fail the
+regression tests for the language.
+
+8. Aggregation of this Package with a commercial distribution is always
+permitted provided that the use of this Package is embedded; that is,
+when no overt attempt is made to make this Package's interfaces visible
+to the end user of the commercial distribution. Such use shall not be
+construed as a distribution of this Package.
+
+9. The name of the Copyright Holder may not be used to endorse or promote
+products derived from this software without specific prior written permission.
+
+10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+ The End
+*/
+/*****************************************************************************/
+/* GNU GENERAL PUBLIC LICENSE: */
+/*****************************************************************************/
+/* This program is free software; you can redistribute it and/or */
+/* modify it under the terms of the GNU General Public License */
+/* as published by the Free Software Foundation; either version 2 */
+/* of the License, or (at your option) any later version. */
+/* */
+/* This program is distributed in the hope that it will be useful, */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
+/* GNU General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License */
+/* along with this program; if not, write to the */
+/* Free Software Foundation, Inc., */
+/* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+/* */
+/*****************************************************************************/
+/* GNU LIBRARY GENERAL PUBLIC LICENSE: */
+/*****************************************************************************/
+/* This library is free software; you can redistribute it and/or */
+/* modify it under the terms of the GNU Library General Public */
+/* License as published by the Free Software Foundation; either */
+/* version 2 of the License, or (at your option) any later version. */
+/* */
+/* This library is distributed in the hope that it will be useful, */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
+/* Library General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU Library General Public */
+/* License along with this library; if not, write to the */
+/* Free Software Foundation, Inc., */
+/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+/* */
+/* or download a copy from ftp://ftp.gnu.org/pub/gnu/COPYING.LIB-2.0 */
+/* */
+/*****************************************************************************/
diff --git a/contrib/tools/yasm/libyasm/bitvect.h b/contrib/tools/yasm/libyasm/bitvect.h
index 3aee3a5319..df4914adf4 100644
--- a/contrib/tools/yasm/libyasm/bitvect.h
+++ b/contrib/tools/yasm/libyasm/bitvect.h
@@ -1,666 +1,666 @@
-#ifndef YASM_BITVECT_H
-#define YASM_BITVECT_H
-/*****************************************************************************/
-/* MODULE NAME: BitVector.h MODULE TYPE: (adt) */
-/*****************************************************************************/
-/* MODULE IMPORTS: */
-/*****************************************************************************/
-
-/* ToolBox.h */
-/*****************************************************************************/
-/* NOTE: The type names that have been chosen here are somewhat weird on */
-/* purpose, in order to avoid name clashes with system header files */
-/* and your own application(s) which might - directly or indirectly - */
-/* include this definitions file. */
-/*****************************************************************************/
-#ifndef YASM_LIB_DECL
-#define YASM_LIB_DECL
-#endif
-
-typedef unsigned char N_char;
-typedef unsigned char N_byte;
-typedef unsigned short N_short;
-typedef unsigned short N_shortword;
-typedef unsigned int N_int;
-typedef unsigned int N_word;
-typedef unsigned long N_long;
-typedef unsigned long N_longword;
-
-/* Mnemonic 1: The natural numbers, N = { 0, 1, 2, 3, ... } */
-/* Mnemonic 2: Nnnn = u_N_signed, _N_ot signed */
-
-typedef signed char Z_char;
-typedef signed char Z_byte;
-typedef signed short Z_short;
-typedef signed short Z_shortword;
-typedef signed int Z_int;
-typedef signed int Z_word;
-typedef signed long Z_long;
-typedef signed long Z_longword;
-
-/* Mnemonic 1: The whole numbers, Z = { 0, -1, 1, -2, 2, -3, 3, ... } */
-/* Mnemonic 2: Zzzz = Ssss_igned */
-
-typedef void *voidptr;
-typedef N_char *charptr;
-typedef N_byte *byteptr;
-typedef N_short *shortptr;
-typedef N_shortword *shortwordptr;
-typedef N_int *intptr;
-typedef N_word *wordptr;
-typedef N_long *longptr;
-typedef N_longword *longwordptr;
-
-typedef N_char *N_charptr;
-typedef N_byte *N_byteptr;
-typedef N_short *N_shortptr;
-typedef N_shortword *N_shortwordptr;
-typedef N_int *N_intptr;
-typedef N_word *N_wordptr;
-typedef N_long *N_longptr;
-typedef N_longword *N_longwordptr;
-
-typedef Z_char *Z_charptr;
-typedef Z_byte *Z_byteptr;
-typedef Z_short *Z_shortptr;
-typedef Z_shortword *Z_shortwordptr;
-typedef Z_int *Z_intptr;
-typedef Z_word *Z_wordptr;
-typedef Z_long *Z_longptr;
-typedef Z_longword *Z_longwordptr;
-
-#ifndef FALSE
-#define FALSE (0!=0)
-#endif
-
-#ifndef TRUE
-#define TRUE (0==0)
-#endif
-
-#ifdef __cplusplus
- typedef bool boolean;
-#else
- #ifdef MACOS_TRADITIONAL
- #define boolean Boolean
- #else
- typedef enum boolean { false = FALSE, true = TRUE } boolean;
- #endif
-#endif
-
-/*****************************************************************************/
-/* MODULE INTERFACE: */
-/*****************************************************************************/
-
-typedef enum ErrCode
- {
- ErrCode_Ok = 0, /* everything went allright */
-
- ErrCode_Type, /* types word and size_t have incompatible sizes */
- ErrCode_Bits, /* bits of word and sizeof(word) are inconsistent */
- ErrCode_Word, /* size of word is less than 16 bits */
- ErrCode_Long, /* size of word is greater than size of long */
- ErrCode_Powr, /* number of bits of word is not a power of two */
- ErrCode_Loga, /* error in calculation of logarithm */
-
- ErrCode_Null, /* unable to allocate memory */
-
- ErrCode_Indx, /* index out of range */
- ErrCode_Ordr, /* minimum > maximum index */
- ErrCode_Size, /* bit vector size mismatch */
- ErrCode_Pars, /* input string syntax error */
- ErrCode_Ovfl, /* numeric overflow error */
- ErrCode_Same, /* operands must be distinct */
- ErrCode_Expo, /* exponent must be positive */
- ErrCode_Zero /* division by zero error */
- } ErrCode;
-
-typedef wordptr *listptr;
-
-/* ===> MISCELLANEOUS BASIC FUNCTIONS: <=== */
-
-YASM_LIB_DECL
-const char * BitVector_Error (ErrCode error); /* return string for err code */
-
-YASM_LIB_DECL
-ErrCode BitVector_Boot (void); /* 0 = ok, 1..7 = error */
-YASM_LIB_DECL
-void BitVector_Shutdown (void); /* undo Boot */
-
-YASM_LIB_DECL
-N_word BitVector_Size (N_int bits); /* bit vector size (# of words) */
-YASM_LIB_DECL
-N_word BitVector_Mask (N_int bits); /* bit vector mask (unused bits) */
-
-/* ===> CLASS METHODS: <=== */
-
-YASM_LIB_DECL
-const char * BitVector_Version (void); /* returns version string */
-
-YASM_LIB_DECL
-N_int BitVector_Word_Bits (void); /* return # of bits in machine word */
-YASM_LIB_DECL
-N_int BitVector_Long_Bits (void); /* return # of bits in unsigned long */
-
-/* ===> CONSTRUCTOR METHODS: <=== */
-
-YASM_LIB_DECL
-/*@only@*/ wordptr BitVector_Create (N_int bits, boolean clear); /* malloc */
-YASM_LIB_DECL
-listptr BitVector_Create_List(N_int bits, boolean clear, N_int count);
-
-YASM_LIB_DECL
-wordptr BitVector_Resize (wordptr oldaddr, N_int bits); /* realloc */
-
-YASM_LIB_DECL
-wordptr BitVector_Shadow (wordptr addr); /* make new same size but empty */
-YASM_LIB_DECL
-wordptr BitVector_Clone (wordptr addr); /* make exact duplicate */
-
-YASM_LIB_DECL
-wordptr BitVector_Concat (wordptr X, wordptr Y); /* return concatenation */
-
-/* ===> DESTRUCTOR METHODS: <=== */
-
-YASM_LIB_DECL
-void BitVector_Dispose (/*@only@*/ /*@out@*/ charptr string); /* string */
-YASM_LIB_DECL
-void BitVector_Destroy (/*@only@*/ wordptr addr); /* bitvec */
-YASM_LIB_DECL
-void BitVector_Destroy_List (listptr list, N_int count); /* list */
-
-/* ===> OBJECT METHODS: <=== */
-
-/* ===> bit vector copy function: */
-
-YASM_LIB_DECL
-void BitVector_Copy (wordptr X, wordptr Y); /* X = Y */
-
-/* ===> bit vector initialization: */
-
-YASM_LIB_DECL
-void BitVector_Empty (wordptr addr); /* X = {} */
-YASM_LIB_DECL
-void BitVector_Fill (wordptr addr); /* X = ~{} */
-YASM_LIB_DECL
-void BitVector_Flip (wordptr addr); /* X = ~X */
-
-YASM_LIB_DECL
-void BitVector_Primes (wordptr addr);
-
-/* ===> miscellaneous functions: */
-
-YASM_LIB_DECL
-void BitVector_Reverse (wordptr X, wordptr Y);
-
-/* ===> bit vector interval operations and functions: */
-
-YASM_LIB_DECL
-void BitVector_Interval_Empty (/*@out@*/ wordptr addr, N_int lower, N_int upper);
-YASM_LIB_DECL
-void BitVector_Interval_Fill (/*@out@*/ wordptr addr, N_int lower, N_int upper);
-YASM_LIB_DECL
-void BitVector_Interval_Flip (/*@out@*/ wordptr addr, N_int lower, N_int upper);
-YASM_LIB_DECL
-void BitVector_Interval_Reverse (/*@out@*/ wordptr addr, N_int lower, N_int upper);
-
-YASM_LIB_DECL
-boolean BitVector_interval_scan_inc (wordptr addr, N_int start,
- N_intptr min, N_intptr max);
-YASM_LIB_DECL
-boolean BitVector_interval_scan_dec (wordptr addr, N_int start,
- N_intptr min, N_intptr max);
-
-YASM_LIB_DECL
-void BitVector_Interval_Copy (/*@out@*/ wordptr X, wordptr Y, N_int Xoffset,
- N_int Yoffset, N_int length);
-
-YASM_LIB_DECL
-wordptr BitVector_Interval_Substitute(/*@out@*/ wordptr X, wordptr Y,
- N_int Xoffset, N_int Xlength,
- N_int Yoffset, N_int Ylength);
-
-/* ===> bit vector test functions: */
-
-YASM_LIB_DECL
-boolean BitVector_is_empty (wordptr addr); /* X == {} ? */
-YASM_LIB_DECL
-boolean BitVector_is_full (wordptr addr); /* X == ~{} ? */
-
-YASM_LIB_DECL
-boolean BitVector_equal (wordptr X, wordptr Y); /* X == Y ? */
-YASM_LIB_DECL
-Z_int BitVector_Lexicompare(wordptr X, wordptr Y); /* X <,=,> Y ? */
-YASM_LIB_DECL
-Z_int BitVector_Compare (wordptr X, wordptr Y); /* X <,=,> Y ? */
-
-/* ===> bit vector string conversion functions: */
-
-YASM_LIB_DECL
-/*@only@*/ charptr BitVector_to_Hex (wordptr addr);
-YASM_LIB_DECL
-ErrCode BitVector_from_Hex (/*@out@*/wordptr addr, charptr string);
-
-YASM_LIB_DECL
-ErrCode BitVector_from_Oct(/*@out@*/ wordptr addr, charptr string);
-
-YASM_LIB_DECL
-/*@only@*/ charptr BitVector_to_Bin (wordptr addr);
-YASM_LIB_DECL
-ErrCode BitVector_from_Bin (/*@out@*/ wordptr addr, charptr string);
-
-YASM_LIB_DECL
-/*@only@*/ charptr BitVector_to_Dec (wordptr addr);
-YASM_LIB_DECL
-ErrCode BitVector_from_Dec (/*@out@*/ wordptr addr, charptr string);
-
-typedef struct BitVector_from_Dec_static_data BitVector_from_Dec_static_data;
-YASM_LIB_DECL
-BitVector_from_Dec_static_data *BitVector_from_Dec_static_Boot(N_word bits);
-YASM_LIB_DECL
-void BitVector_from_Dec_static_Shutdown(/*@null@*/ BitVector_from_Dec_static_data *data);
-YASM_LIB_DECL
-ErrCode BitVector_from_Dec_static(BitVector_from_Dec_static_data *data,
- /*@out@*/ wordptr addr, charptr string);
-
-YASM_LIB_DECL
-/*@only@*/ charptr BitVector_to_Enum (wordptr addr);
-YASM_LIB_DECL
-ErrCode BitVector_from_Enum (/*@out@*/ wordptr addr, charptr string);
-
-/* ===> bit vector bit operations, functions & tests: */
-
-YASM_LIB_DECL
-void BitVector_Bit_Off (/*@out@*/ wordptr addr, N_int indx); /* X = X \ {x} */
-YASM_LIB_DECL
-void BitVector_Bit_On (/*@out@*/ wordptr addr, N_int indx); /* X = X + {x} */
-YASM_LIB_DECL
-boolean BitVector_bit_flip (/*@out@*/ wordptr addr, N_int indx); /* (X+{x})\(X*{x}) */
-
-YASM_LIB_DECL
-boolean BitVector_bit_test (wordptr addr, N_int indx); /* {x} in X ? */
-
-YASM_LIB_DECL
-void BitVector_Bit_Copy (/*@out@*/ wordptr addr, N_int indx, boolean bit);
-
-/* ===> bit vector bit shift & rotate functions: */
-
-YASM_LIB_DECL
-void BitVector_LSB (/*@out@*/ wordptr addr, boolean bit);
-YASM_LIB_DECL
-void BitVector_MSB (/*@out@*/ wordptr addr, boolean bit);
-YASM_LIB_DECL
-boolean BitVector_lsb_ (wordptr addr);
-YASM_LIB_DECL
-boolean BitVector_msb_ (wordptr addr);
-YASM_LIB_DECL
-boolean /*@alt void@*/ BitVector_rotate_left (wordptr addr);
-YASM_LIB_DECL
-boolean /*@alt void@*/ BitVector_rotate_right (wordptr addr);
-YASM_LIB_DECL
-boolean /*@alt void@*/ BitVector_shift_left (wordptr addr, boolean carry_in);
-YASM_LIB_DECL
-boolean /*@alt void@*/ BitVector_shift_right (wordptr addr, boolean carry_in);
-YASM_LIB_DECL
-void BitVector_Move_Left (wordptr addr, N_int bits);
-YASM_LIB_DECL
-void BitVector_Move_Right (wordptr addr, N_int bits);
-
-/* ===> bit vector insert/delete bits: */
-
-YASM_LIB_DECL
-void BitVector_Insert (wordptr addr, N_int offset, N_int count,
- boolean clear);
-YASM_LIB_DECL
-void BitVector_Delete (wordptr addr, N_int offset, N_int count,
- boolean clear);
-
-/* ===> bit vector arithmetic: */
-
-YASM_LIB_DECL
-boolean /*@alt void@*/ BitVector_increment (wordptr addr); /* X++ */
-YASM_LIB_DECL
-boolean /*@alt void@*/ BitVector_decrement (wordptr addr); /* X-- */
-
-YASM_LIB_DECL
-boolean /*@alt void@*/ BitVector_compute (wordptr X, wordptr Y, wordptr Z, boolean minus,
- boolean *carry);
-YASM_LIB_DECL
-boolean /*@alt void@*/ BitVector_add (wordptr X, wordptr Y, wordptr Z, boolean *carry);
-YASM_LIB_DECL
-boolean /*@alt void@*/ BitVector_sub (wordptr X, wordptr Y, wordptr Z, boolean *carry);
-YASM_LIB_DECL
-boolean /*@alt void@*/ BitVector_inc (wordptr X, wordptr Y);
-YASM_LIB_DECL
-boolean /*@alt void@*/ BitVector_dec (wordptr X, wordptr Y);
-
-YASM_LIB_DECL
-void BitVector_Negate (wordptr X, wordptr Y);
-YASM_LIB_DECL
-void BitVector_Absolute (wordptr X, wordptr Y);
-YASM_LIB_DECL
-Z_int BitVector_Sign (wordptr addr);
-YASM_LIB_DECL
-ErrCode BitVector_Mul_Pos (wordptr X, wordptr Y, wordptr Z, boolean strict);
-YASM_LIB_DECL
-ErrCode BitVector_Multiply (wordptr X, wordptr Y, wordptr Z);
-YASM_LIB_DECL
-ErrCode BitVector_Div_Pos (wordptr Q, wordptr X, wordptr Y, wordptr R);
-YASM_LIB_DECL
-ErrCode BitVector_Divide (wordptr Q, wordptr X, wordptr Y, wordptr R);
-YASM_LIB_DECL
-ErrCode BitVector_GCD (wordptr X, wordptr Y, wordptr Z);
-YASM_LIB_DECL
-ErrCode BitVector_GCD2 (wordptr U, wordptr V, wordptr W, /* O */
- wordptr X, wordptr Y); /* I */
-YASM_LIB_DECL
-ErrCode BitVector_Power (wordptr X, wordptr Y, wordptr Z);
-
-/* ===> direct memory access functions: */
-
-YASM_LIB_DECL
-void BitVector_Block_Store(wordptr addr, charptr buffer, N_int length);
-YASM_LIB_DECL
-charptr BitVector_Block_Read (wordptr addr, /*@out@*/ N_intptr length);
-
-/* ===> word array functions: */
-
-YASM_LIB_DECL
-void BitVector_Word_Store (wordptr addr, N_int offset, N_int value);
-YASM_LIB_DECL
-N_int BitVector_Word_Read (wordptr addr, N_int offset);
-
-YASM_LIB_DECL
-void BitVector_Word_Insert(wordptr addr, N_int offset, N_int count,
- boolean clear);
-YASM_LIB_DECL
-void BitVector_Word_Delete(wordptr addr, N_int offset, N_int count,
- boolean clear);
-
-/* ===> arbitrary size chunk functions: */
-
-YASM_LIB_DECL
-void BitVector_Chunk_Store(wordptr addr, N_int chunksize,
- N_int offset, N_long value);
-YASM_LIB_DECL
-N_long BitVector_Chunk_Read (wordptr addr, N_int chunksize,
- N_int offset);
-
-/* ===> set operations: */
-
-YASM_LIB_DECL
-void Set_Union (wordptr X, wordptr Y, wordptr Z); /* X = Y + Z */
-YASM_LIB_DECL
-void Set_Intersection (wordptr X, wordptr Y, wordptr Z); /* X = Y * Z */
-YASM_LIB_DECL
-void Set_Difference (wordptr X, wordptr Y, wordptr Z); /* X = Y \ Z */
-YASM_LIB_DECL
-void Set_ExclusiveOr (wordptr X, wordptr Y, wordptr Z); /*(Y+Z)\(Y*Z)*/
-YASM_LIB_DECL
-void Set_Complement (wordptr X, wordptr Y); /* X = ~Y */
-
-/* ===> set functions: */
-
-YASM_LIB_DECL
-boolean Set_subset (wordptr X, wordptr Y); /* X in Y ? */
-
-YASM_LIB_DECL
-N_int Set_Norm (wordptr addr); /* = | X | */
-YASM_LIB_DECL
-N_int Set_Norm2 (wordptr addr); /* = | X | */
-YASM_LIB_DECL
-N_int Set_Norm3 (wordptr addr); /* = | X | */
-YASM_LIB_DECL
-Z_long Set_Min (wordptr addr); /* = min(X) */
-YASM_LIB_DECL
-Z_long Set_Max (wordptr addr); /* = max(X) */
-
-/* ===> matrix-of-booleans operations: */
-
-YASM_LIB_DECL
-void Matrix_Multiplication(wordptr X, N_int rowsX, N_int colsX,
- wordptr Y, N_int rowsY, N_int colsY,
- wordptr Z, N_int rowsZ, N_int colsZ);
-
-YASM_LIB_DECL
-void Matrix_Product (wordptr X, N_int rowsX, N_int colsX,
- wordptr Y, N_int rowsY, N_int colsY,
- wordptr Z, N_int rowsZ, N_int colsZ);
-
-YASM_LIB_DECL
-void Matrix_Closure (wordptr addr, N_int rows, N_int cols);
-
-YASM_LIB_DECL
-void Matrix_Transpose (wordptr X, N_int rowsX, N_int colsX,
- wordptr Y, N_int rowsY, N_int colsY);
-
-/*****************************************************************************/
-/* VERSION: 6.4 */
-/*****************************************************************************/
-/* VERSION HISTORY: */
-/*****************************************************************************/
-/* */
-/* Version 6.4 03.10.04 Added C++ comp. directives. Improved "Norm()". */
-/* Version 6.3 28.09.02 Added "Create_List()" and "GCD2()". */
-/* Version 6.2 15.09.02 Overhauled error handling. Fixed "GCD()". */
-/* Version 6.1 08.10.01 Make VMS linker happy: _lsb,_msb => _lsb_,_msb_ */
-/* Version 6.0 08.10.00 Corrected overflow handling. */
-/* Version 5.8 14.07.00 Added "Power()". Changed "Copy()". */
-/* Version 5.7 19.05.99 Quickened "Div_Pos()". Added "Product()". */
-/* Version 5.6 02.11.98 Leading zeros eliminated in "to_Hex()". */
-/* Version 5.5 21.09.98 Fixed bug of uninitialized "error" in Multiply. */
-/* Version 5.4 07.09.98 Fixed bug of uninitialized "error" in Divide. */
-/* Version 5.3 12.05.98 Improved Norm. Completed history. */
-/* Version 5.2 31.03.98 Improved Norm. */
-/* Version 5.1 09.03.98 No changes. */
-/* Version 5.0 01.03.98 Major additions and rewrite. */
-/* Version 4.2 16.07.97 Added is_empty, is_full. */
-/* Version 4.1 30.06.97 Added word-ins/del, move-left/right, inc/dec. */
-/* Version 4.0 23.04.97 Rewrite. Added bit shift and bool. matrix ops. */
-/* Version 3.2 04.02.97 Added interval methods. */
-/* Version 3.1 21.01.97 Fixed bug on 64 bit machines. */
-/* Version 3.0 12.01.97 Added flip. */
-/* Version 2.0 14.12.96 Efficiency and consistency improvements. */
-/* Version 1.1 08.01.96 Added Resize and ExclusiveOr. */
-/* Version 1.0 14.12.95 First version under UNIX (with Perl module). */
-/* Version 0.9 01.11.93 First version of C library under MS-DOS. */
-/* Version 0.1 ??.??.89 First version in Turbo Pascal under CP/M. */
-/* */
-/*****************************************************************************/
-/* AUTHOR: */
-/*****************************************************************************/
-/* */
-/* Steffen Beyer */
-/* mailto:sb@engelschall.com */
-/* http://www.engelschall.com/u/sb/download/ */
-/* */
-/*****************************************************************************/
-/* COPYRIGHT: */
-/*****************************************************************************/
-/* */
-/* Copyright (c) 1995 - 2004 by Steffen Beyer. */
-/* All rights reserved. */
-/* */
-/*****************************************************************************/
-/* LICENSE: */
-/*****************************************************************************/
-/* This package is free software; you can use, modify and redistribute */
-/* it under the same terms as Perl itself, i.e., under the terms of */
-/* the "Artistic License" or the "GNU General Public License". */
-/* */
-/* The C library at the core of this Perl module can additionally */
-/* be used, modified and redistributed under the terms of the */
-/* "GNU Library General Public License". */
-/* */
-/*****************************************************************************/
-/* ARTISTIC LICENSE: */
-/*****************************************************************************/
-/*
- The "Artistic License"
-
- Preamble
-
-The intent of this document is to state the conditions under which a
-Package may be copied, such that the Copyright Holder maintains some
-semblance of artistic control over the development of the package,
-while giving the users of the package the right to use and distribute
-the Package in a more-or-less customary fashion, plus the right to make
-reasonable modifications.
-
-Definitions:
-
- "Package" refers to the collection of files distributed by the
- Copyright Holder, and derivatives of that collection of files
- created through textual modification.
-
- "Standard Version" refers to such a Package if it has not been
- modified, or has been modified in accordance with the wishes
- of the Copyright Holder as specified below.
-
- "Copyright Holder" is whoever is named in the copyright or
- copyrights for the package.
-
- "You" is you, if you're thinking about copying or distributing
- this Package.
-
- "Reasonable copying fee" is whatever you can justify on the
- basis of media cost, duplication charges, time of people involved,
- and so on. (You will not be required to justify it to the
- Copyright Holder, but only to the computing community at large
- as a market that must bear the fee.)
-
- "Freely Available" means that no fee is charged for the item
- itself, though there may be fees involved in handling the item.
- It also means that recipients of the item may redistribute it
- under the same conditions they received it.
-
-1. You may make and give away verbatim copies of the source form of the
-Standard Version of this Package without restriction, provided that you
-duplicate all of the original copyright notices and associated disclaimers.
-
-2. You may apply bug fixes, portability fixes and other modifications
-derived from the Public Domain or from the Copyright Holder. A Package
-modified in such a way shall still be considered the Standard Version.
-
-3. You may otherwise modify your copy of this Package in any way, provided
-that you insert a prominent notice in each changed file stating how and
-when you changed that file, and provided that you do at least ONE of the
-following:
-
- a) place your modifications in the Public Domain or otherwise make them
- Freely Available, such as by posting said modifications to Usenet or
- an equivalent medium, or placing the modifications on a major archive
- site such as uunet.uu.net, or by allowing the Copyright Holder to include
- your modifications in the Standard Version of the Package.
-
- b) use the modified Package only within your corporation or organization.
-
- c) rename any non-standard executables so the names do not conflict
- with standard executables, which must also be provided, and provide
- a separate manual page for each non-standard executable that clearly
- documents how it differs from the Standard Version.
-
- d) make other distribution arrangements with the Copyright Holder.
-
-4. You may distribute the programs of this Package in object code or
-executable form, provided that you do at least ONE of the following:
-
- a) distribute a Standard Version of the executables and library files,
- together with instructions (in the manual page or equivalent) on where
- to get the Standard Version.
-
- b) accompany the distribution with the machine-readable source of
- the Package with your modifications.
-
- c) give non-standard executables non-standard names, and clearly
- document the differences in manual pages (or equivalent), together
- with instructions on where to get the Standard Version.
-
- d) make other distribution arrangements with the Copyright Holder.
-
-5. You may charge a reasonable copying fee for any distribution of this
-Package. You may charge any fee you choose for support of this
-Package. You may not charge a fee for this Package itself. However,
-you may distribute this Package in aggregate with other (possibly
-commercial) programs as part of a larger (possibly commercial) software
-distribution provided that you do not advertise this Package as a
-product of your own. You may embed this Package's interpreter within
-an executable of yours (by linking); this shall be construed as a mere
-form of aggregation, provided that the complete Standard Version of the
-interpreter is so embedded.
-
-6. The scripts and library files supplied as input to or produced as
-output from the programs of this Package do not automatically fall
-under the copyright of this Package, but belong to whoever generated
-them, and may be sold commercially, and may be aggregated with this
-Package. If such scripts or library files are aggregated with this
-Package via the so-called "undump" or "unexec" methods of producing a
-binary executable image, then distribution of such an image shall
-neither be construed as a distribution of this Package nor shall it
-fall under the restrictions of Paragraphs 3 and 4, provided that you do
-not represent such an executable image as a Standard Version of this
-Package.
-
-7. C subroutines (or comparably compiled subroutines in other
-languages) supplied by you and linked into this Package in order to
-emulate subroutines and variables of the language defined by this
-Package shall not be considered part of this Package, but are the
-equivalent of input as in Paragraph 6, provided these subroutines do
-not change the language in any way that would cause it to fail the
-regression tests for the language.
-
-8. Aggregation of this Package with a commercial distribution is always
-permitted provided that the use of this Package is embedded; that is,
-when no overt attempt is made to make this Package's interfaces visible
-to the end user of the commercial distribution. Such use shall not be
-construed as a distribution of this Package.
-
-9. The name of the Copyright Holder may not be used to endorse or promote
-products derived from this software without specific prior written permission.
-
-10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
-IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
-WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-
- The End
-*/
-/*****************************************************************************/
-/* GNU GENERAL PUBLIC LICENSE: */
-/*****************************************************************************/
-/* This program is free software; you can redistribute it and/or */
-/* modify it under the terms of the GNU General Public License */
-/* as published by the Free Software Foundation; either version 2 */
-/* of the License, or (at your option) any later version. */
-/* */
-/* This program is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
-/* GNU General Public License for more details. */
-/* */
-/* You should have received a copy of the GNU General Public License */
-/* along with this program; if not, write to the */
-/* Free Software Foundation, Inc., */
-/* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-/* */
-/*****************************************************************************/
-/* GNU LIBRARY GENERAL PUBLIC LICENSE: */
-/*****************************************************************************/
-/* */
-/* This library is free software; you can redistribute it and/or */
-/* modify it under the terms of the GNU Library General Public */
-/* License as published by the Free Software Foundation; either */
-/* version 2 of the License, or (at your option) any later version. */
-/* */
-/* This library is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
-/* Library General Public License for more details. */
-/* */
-/* You should have received a copy of the GNU Library General Public */
-/* License along with this library; if not, write to the */
-/* Free Software Foundation, Inc., */
-/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/* */
-/* or download a copy from ftp://ftp.gnu.org/pub/gnu/COPYING.LIB-2.0 */
-/* */
-/*****************************************************************************/
-#endif
+#ifndef YASM_BITVECT_H
+#define YASM_BITVECT_H
+/*****************************************************************************/
+/* MODULE NAME: BitVector.h MODULE TYPE: (adt) */
+/*****************************************************************************/
+/* MODULE IMPORTS: */
+/*****************************************************************************/
+
+/* ToolBox.h */
+/*****************************************************************************/
+/* NOTE: The type names that have been chosen here are somewhat weird on */
+/* purpose, in order to avoid name clashes with system header files */
+/* and your own application(s) which might - directly or indirectly - */
+/* include this definitions file. */
+/*****************************************************************************/
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+typedef unsigned char N_char;
+typedef unsigned char N_byte;
+typedef unsigned short N_short;
+typedef unsigned short N_shortword;
+typedef unsigned int N_int;
+typedef unsigned int N_word;
+typedef unsigned long N_long;
+typedef unsigned long N_longword;
+
+/* Mnemonic 1: The natural numbers, N = { 0, 1, 2, 3, ... } */
+/* Mnemonic 2: Nnnn = u_N_signed, _N_ot signed */
+
+typedef signed char Z_char;
+typedef signed char Z_byte;
+typedef signed short Z_short;
+typedef signed short Z_shortword;
+typedef signed int Z_int;
+typedef signed int Z_word;
+typedef signed long Z_long;
+typedef signed long Z_longword;
+
+/* Mnemonic 1: The whole numbers, Z = { 0, -1, 1, -2, 2, -3, 3, ... } */
+/* Mnemonic 2: Zzzz = Ssss_igned */
+
+typedef void *voidptr;
+typedef N_char *charptr;
+typedef N_byte *byteptr;
+typedef N_short *shortptr;
+typedef N_shortword *shortwordptr;
+typedef N_int *intptr;
+typedef N_word *wordptr;
+typedef N_long *longptr;
+typedef N_longword *longwordptr;
+
+typedef N_char *N_charptr;
+typedef N_byte *N_byteptr;
+typedef N_short *N_shortptr;
+typedef N_shortword *N_shortwordptr;
+typedef N_int *N_intptr;
+typedef N_word *N_wordptr;
+typedef N_long *N_longptr;
+typedef N_longword *N_longwordptr;
+
+typedef Z_char *Z_charptr;
+typedef Z_byte *Z_byteptr;
+typedef Z_short *Z_shortptr;
+typedef Z_shortword *Z_shortwordptr;
+typedef Z_int *Z_intptr;
+typedef Z_word *Z_wordptr;
+typedef Z_long *Z_longptr;
+typedef Z_longword *Z_longwordptr;
+
+#ifndef FALSE
+#define FALSE (0!=0)
+#endif
+
+#ifndef TRUE
+#define TRUE (0==0)
+#endif
+
+#ifdef __cplusplus
+ typedef bool boolean;
+#else
+ #ifdef MACOS_TRADITIONAL
+ #define boolean Boolean
+ #else
+ typedef enum boolean { false = FALSE, true = TRUE } boolean;
+ #endif
+#endif
+
+/*****************************************************************************/
+/* MODULE INTERFACE: */
+/*****************************************************************************/
+
+typedef enum ErrCode
+ {
+ ErrCode_Ok = 0, /* everything went allright */
+
+ ErrCode_Type, /* types word and size_t have incompatible sizes */
+ ErrCode_Bits, /* bits of word and sizeof(word) are inconsistent */
+ ErrCode_Word, /* size of word is less than 16 bits */
+ ErrCode_Long, /* size of word is greater than size of long */
+ ErrCode_Powr, /* number of bits of word is not a power of two */
+ ErrCode_Loga, /* error in calculation of logarithm */
+
+ ErrCode_Null, /* unable to allocate memory */
+
+ ErrCode_Indx, /* index out of range */
+ ErrCode_Ordr, /* minimum > maximum index */
+ ErrCode_Size, /* bit vector size mismatch */
+ ErrCode_Pars, /* input string syntax error */
+ ErrCode_Ovfl, /* numeric overflow error */
+ ErrCode_Same, /* operands must be distinct */
+ ErrCode_Expo, /* exponent must be positive */
+ ErrCode_Zero /* division by zero error */
+ } ErrCode;
+
+typedef wordptr *listptr;
+
+/* ===> MISCELLANEOUS BASIC FUNCTIONS: <=== */
+
+YASM_LIB_DECL
+const char * BitVector_Error (ErrCode error); /* return string for err code */
+
+YASM_LIB_DECL
+ErrCode BitVector_Boot (void); /* 0 = ok, 1..7 = error */
+YASM_LIB_DECL
+void BitVector_Shutdown (void); /* undo Boot */
+
+YASM_LIB_DECL
+N_word BitVector_Size (N_int bits); /* bit vector size (# of words) */
+YASM_LIB_DECL
+N_word BitVector_Mask (N_int bits); /* bit vector mask (unused bits) */
+
+/* ===> CLASS METHODS: <=== */
+
+YASM_LIB_DECL
+const char * BitVector_Version (void); /* returns version string */
+
+YASM_LIB_DECL
+N_int BitVector_Word_Bits (void); /* return # of bits in machine word */
+YASM_LIB_DECL
+N_int BitVector_Long_Bits (void); /* return # of bits in unsigned long */
+
+/* ===> CONSTRUCTOR METHODS: <=== */
+
+YASM_LIB_DECL
+/*@only@*/ wordptr BitVector_Create (N_int bits, boolean clear); /* malloc */
+YASM_LIB_DECL
+listptr BitVector_Create_List(N_int bits, boolean clear, N_int count);
+
+YASM_LIB_DECL
+wordptr BitVector_Resize (wordptr oldaddr, N_int bits); /* realloc */
+
+YASM_LIB_DECL
+wordptr BitVector_Shadow (wordptr addr); /* make new same size but empty */
+YASM_LIB_DECL
+wordptr BitVector_Clone (wordptr addr); /* make exact duplicate */
+
+YASM_LIB_DECL
+wordptr BitVector_Concat (wordptr X, wordptr Y); /* return concatenation */
+
+/* ===> DESTRUCTOR METHODS: <=== */
+
+YASM_LIB_DECL
+void BitVector_Dispose (/*@only@*/ /*@out@*/ charptr string); /* string */
+YASM_LIB_DECL
+void BitVector_Destroy (/*@only@*/ wordptr addr); /* bitvec */
+YASM_LIB_DECL
+void BitVector_Destroy_List (listptr list, N_int count); /* list */
+
+/* ===> OBJECT METHODS: <=== */
+
+/* ===> bit vector copy function: */
+
+YASM_LIB_DECL
+void BitVector_Copy (wordptr X, wordptr Y); /* X = Y */
+
+/* ===> bit vector initialization: */
+
+YASM_LIB_DECL
+void BitVector_Empty (wordptr addr); /* X = {} */
+YASM_LIB_DECL
+void BitVector_Fill (wordptr addr); /* X = ~{} */
+YASM_LIB_DECL
+void BitVector_Flip (wordptr addr); /* X = ~X */
+
+YASM_LIB_DECL
+void BitVector_Primes (wordptr addr);
+
+/* ===> miscellaneous functions: */
+
+YASM_LIB_DECL
+void BitVector_Reverse (wordptr X, wordptr Y);
+
+/* ===> bit vector interval operations and functions: */
+
+YASM_LIB_DECL
+void BitVector_Interval_Empty (/*@out@*/ wordptr addr, N_int lower, N_int upper);
+YASM_LIB_DECL
+void BitVector_Interval_Fill (/*@out@*/ wordptr addr, N_int lower, N_int upper);
+YASM_LIB_DECL
+void BitVector_Interval_Flip (/*@out@*/ wordptr addr, N_int lower, N_int upper);
+YASM_LIB_DECL
+void BitVector_Interval_Reverse (/*@out@*/ wordptr addr, N_int lower, N_int upper);
+
+YASM_LIB_DECL
+boolean BitVector_interval_scan_inc (wordptr addr, N_int start,
+ N_intptr min, N_intptr max);
+YASM_LIB_DECL
+boolean BitVector_interval_scan_dec (wordptr addr, N_int start,
+ N_intptr min, N_intptr max);
+
+YASM_LIB_DECL
+void BitVector_Interval_Copy (/*@out@*/ wordptr X, wordptr Y, N_int Xoffset,
+ N_int Yoffset, N_int length);
+
+YASM_LIB_DECL
+wordptr BitVector_Interval_Substitute(/*@out@*/ wordptr X, wordptr Y,
+ N_int Xoffset, N_int Xlength,
+ N_int Yoffset, N_int Ylength);
+
+/* ===> bit vector test functions: */
+
+YASM_LIB_DECL
+boolean BitVector_is_empty (wordptr addr); /* X == {} ? */
+YASM_LIB_DECL
+boolean BitVector_is_full (wordptr addr); /* X == ~{} ? */
+
+YASM_LIB_DECL
+boolean BitVector_equal (wordptr X, wordptr Y); /* X == Y ? */
+YASM_LIB_DECL
+Z_int BitVector_Lexicompare(wordptr X, wordptr Y); /* X <,=,> Y ? */
+YASM_LIB_DECL
+Z_int BitVector_Compare (wordptr X, wordptr Y); /* X <,=,> Y ? */
+
+/* ===> bit vector string conversion functions: */
+
+YASM_LIB_DECL
+/*@only@*/ charptr BitVector_to_Hex (wordptr addr);
+YASM_LIB_DECL
+ErrCode BitVector_from_Hex (/*@out@*/wordptr addr, charptr string);
+
+YASM_LIB_DECL
+ErrCode BitVector_from_Oct(/*@out@*/ wordptr addr, charptr string);
+
+YASM_LIB_DECL
+/*@only@*/ charptr BitVector_to_Bin (wordptr addr);
+YASM_LIB_DECL
+ErrCode BitVector_from_Bin (/*@out@*/ wordptr addr, charptr string);
+
+YASM_LIB_DECL
+/*@only@*/ charptr BitVector_to_Dec (wordptr addr);
+YASM_LIB_DECL
+ErrCode BitVector_from_Dec (/*@out@*/ wordptr addr, charptr string);
+
+typedef struct BitVector_from_Dec_static_data BitVector_from_Dec_static_data;
+YASM_LIB_DECL
+BitVector_from_Dec_static_data *BitVector_from_Dec_static_Boot(N_word bits);
+YASM_LIB_DECL
+void BitVector_from_Dec_static_Shutdown(/*@null@*/ BitVector_from_Dec_static_data *data);
+YASM_LIB_DECL
+ErrCode BitVector_from_Dec_static(BitVector_from_Dec_static_data *data,
+ /*@out@*/ wordptr addr, charptr string);
+
+YASM_LIB_DECL
+/*@only@*/ charptr BitVector_to_Enum (wordptr addr);
+YASM_LIB_DECL
+ErrCode BitVector_from_Enum (/*@out@*/ wordptr addr, charptr string);
+
+/* ===> bit vector bit operations, functions & tests: */
+
+YASM_LIB_DECL
+void BitVector_Bit_Off (/*@out@*/ wordptr addr, N_int indx); /* X = X \ {x} */
+YASM_LIB_DECL
+void BitVector_Bit_On (/*@out@*/ wordptr addr, N_int indx); /* X = X + {x} */
+YASM_LIB_DECL
+boolean BitVector_bit_flip (/*@out@*/ wordptr addr, N_int indx); /* (X+{x})\(X*{x}) */
+
+YASM_LIB_DECL
+boolean BitVector_bit_test (wordptr addr, N_int indx); /* {x} in X ? */
+
+YASM_LIB_DECL
+void BitVector_Bit_Copy (/*@out@*/ wordptr addr, N_int indx, boolean bit);
+
+/* ===> bit vector bit shift & rotate functions: */
+
+YASM_LIB_DECL
+void BitVector_LSB (/*@out@*/ wordptr addr, boolean bit);
+YASM_LIB_DECL
+void BitVector_MSB (/*@out@*/ wordptr addr, boolean bit);
+YASM_LIB_DECL
+boolean BitVector_lsb_ (wordptr addr);
+YASM_LIB_DECL
+boolean BitVector_msb_ (wordptr addr);
+YASM_LIB_DECL
+boolean /*@alt void@*/ BitVector_rotate_left (wordptr addr);
+YASM_LIB_DECL
+boolean /*@alt void@*/ BitVector_rotate_right (wordptr addr);
+YASM_LIB_DECL
+boolean /*@alt void@*/ BitVector_shift_left (wordptr addr, boolean carry_in);
+YASM_LIB_DECL
+boolean /*@alt void@*/ BitVector_shift_right (wordptr addr, boolean carry_in);
+YASM_LIB_DECL
+void BitVector_Move_Left (wordptr addr, N_int bits);
+YASM_LIB_DECL
+void BitVector_Move_Right (wordptr addr, N_int bits);
+
+/* ===> bit vector insert/delete bits: */
+
+YASM_LIB_DECL
+void BitVector_Insert (wordptr addr, N_int offset, N_int count,
+ boolean clear);
+YASM_LIB_DECL
+void BitVector_Delete (wordptr addr, N_int offset, N_int count,
+ boolean clear);
+
+/* ===> bit vector arithmetic: */
+
+YASM_LIB_DECL
+boolean /*@alt void@*/ BitVector_increment (wordptr addr); /* X++ */
+YASM_LIB_DECL
+boolean /*@alt void@*/ BitVector_decrement (wordptr addr); /* X-- */
+
+YASM_LIB_DECL
+boolean /*@alt void@*/ BitVector_compute (wordptr X, wordptr Y, wordptr Z, boolean minus,
+ boolean *carry);
+YASM_LIB_DECL
+boolean /*@alt void@*/ BitVector_add (wordptr X, wordptr Y, wordptr Z, boolean *carry);
+YASM_LIB_DECL
+boolean /*@alt void@*/ BitVector_sub (wordptr X, wordptr Y, wordptr Z, boolean *carry);
+YASM_LIB_DECL
+boolean /*@alt void@*/ BitVector_inc (wordptr X, wordptr Y);
+YASM_LIB_DECL
+boolean /*@alt void@*/ BitVector_dec (wordptr X, wordptr Y);
+
+YASM_LIB_DECL
+void BitVector_Negate (wordptr X, wordptr Y);
+YASM_LIB_DECL
+void BitVector_Absolute (wordptr X, wordptr Y);
+YASM_LIB_DECL
+Z_int BitVector_Sign (wordptr addr);
+YASM_LIB_DECL
+ErrCode BitVector_Mul_Pos (wordptr X, wordptr Y, wordptr Z, boolean strict);
+YASM_LIB_DECL
+ErrCode BitVector_Multiply (wordptr X, wordptr Y, wordptr Z);
+YASM_LIB_DECL
+ErrCode BitVector_Div_Pos (wordptr Q, wordptr X, wordptr Y, wordptr R);
+YASM_LIB_DECL
+ErrCode BitVector_Divide (wordptr Q, wordptr X, wordptr Y, wordptr R);
+YASM_LIB_DECL
+ErrCode BitVector_GCD (wordptr X, wordptr Y, wordptr Z);
+YASM_LIB_DECL
+ErrCode BitVector_GCD2 (wordptr U, wordptr V, wordptr W, /* O */
+ wordptr X, wordptr Y); /* I */
+YASM_LIB_DECL
+ErrCode BitVector_Power (wordptr X, wordptr Y, wordptr Z);
+
+/* ===> direct memory access functions: */
+
+YASM_LIB_DECL
+void BitVector_Block_Store(wordptr addr, charptr buffer, N_int length);
+YASM_LIB_DECL
+charptr BitVector_Block_Read (wordptr addr, /*@out@*/ N_intptr length);
+
+/* ===> word array functions: */
+
+YASM_LIB_DECL
+void BitVector_Word_Store (wordptr addr, N_int offset, N_int value);
+YASM_LIB_DECL
+N_int BitVector_Word_Read (wordptr addr, N_int offset);
+
+YASM_LIB_DECL
+void BitVector_Word_Insert(wordptr addr, N_int offset, N_int count,
+ boolean clear);
+YASM_LIB_DECL
+void BitVector_Word_Delete(wordptr addr, N_int offset, N_int count,
+ boolean clear);
+
+/* ===> arbitrary size chunk functions: */
+
+YASM_LIB_DECL
+void BitVector_Chunk_Store(wordptr addr, N_int chunksize,
+ N_int offset, N_long value);
+YASM_LIB_DECL
+N_long BitVector_Chunk_Read (wordptr addr, N_int chunksize,
+ N_int offset);
+
+/* ===> set operations: */
+
+YASM_LIB_DECL
+void Set_Union (wordptr X, wordptr Y, wordptr Z); /* X = Y + Z */
+YASM_LIB_DECL
+void Set_Intersection (wordptr X, wordptr Y, wordptr Z); /* X = Y * Z */
+YASM_LIB_DECL
+void Set_Difference (wordptr X, wordptr Y, wordptr Z); /* X = Y \ Z */
+YASM_LIB_DECL
+void Set_ExclusiveOr (wordptr X, wordptr Y, wordptr Z); /*(Y+Z)\(Y*Z)*/
+YASM_LIB_DECL
+void Set_Complement (wordptr X, wordptr Y); /* X = ~Y */
+
+/* ===> set functions: */
+
+YASM_LIB_DECL
+boolean Set_subset (wordptr X, wordptr Y); /* X in Y ? */
+
+YASM_LIB_DECL
+N_int Set_Norm (wordptr addr); /* = | X | */
+YASM_LIB_DECL
+N_int Set_Norm2 (wordptr addr); /* = | X | */
+YASM_LIB_DECL
+N_int Set_Norm3 (wordptr addr); /* = | X | */
+YASM_LIB_DECL
+Z_long Set_Min (wordptr addr); /* = min(X) */
+YASM_LIB_DECL
+Z_long Set_Max (wordptr addr); /* = max(X) */
+
+/* ===> matrix-of-booleans operations: */
+
+YASM_LIB_DECL
+void Matrix_Multiplication(wordptr X, N_int rowsX, N_int colsX,
+ wordptr Y, N_int rowsY, N_int colsY,
+ wordptr Z, N_int rowsZ, N_int colsZ);
+
+YASM_LIB_DECL
+void Matrix_Product (wordptr X, N_int rowsX, N_int colsX,
+ wordptr Y, N_int rowsY, N_int colsY,
+ wordptr Z, N_int rowsZ, N_int colsZ);
+
+YASM_LIB_DECL
+void Matrix_Closure (wordptr addr, N_int rows, N_int cols);
+
+YASM_LIB_DECL
+void Matrix_Transpose (wordptr X, N_int rowsX, N_int colsX,
+ wordptr Y, N_int rowsY, N_int colsY);
+
+/*****************************************************************************/
+/* VERSION: 6.4 */
+/*****************************************************************************/
+/* VERSION HISTORY: */
+/*****************************************************************************/
+/* */
+/* Version 6.4 03.10.04 Added C++ comp. directives. Improved "Norm()". */
+/* Version 6.3 28.09.02 Added "Create_List()" and "GCD2()". */
+/* Version 6.2 15.09.02 Overhauled error handling. Fixed "GCD()". */
+/* Version 6.1 08.10.01 Make VMS linker happy: _lsb,_msb => _lsb_,_msb_ */
+/* Version 6.0 08.10.00 Corrected overflow handling. */
+/* Version 5.8 14.07.00 Added "Power()". Changed "Copy()". */
+/* Version 5.7 19.05.99 Quickened "Div_Pos()". Added "Product()". */
+/* Version 5.6 02.11.98 Leading zeros eliminated in "to_Hex()". */
+/* Version 5.5 21.09.98 Fixed bug of uninitialized "error" in Multiply. */
+/* Version 5.4 07.09.98 Fixed bug of uninitialized "error" in Divide. */
+/* Version 5.3 12.05.98 Improved Norm. Completed history. */
+/* Version 5.2 31.03.98 Improved Norm. */
+/* Version 5.1 09.03.98 No changes. */
+/* Version 5.0 01.03.98 Major additions and rewrite. */
+/* Version 4.2 16.07.97 Added is_empty, is_full. */
+/* Version 4.1 30.06.97 Added word-ins/del, move-left/right, inc/dec. */
+/* Version 4.0 23.04.97 Rewrite. Added bit shift and bool. matrix ops. */
+/* Version 3.2 04.02.97 Added interval methods. */
+/* Version 3.1 21.01.97 Fixed bug on 64 bit machines. */
+/* Version 3.0 12.01.97 Added flip. */
+/* Version 2.0 14.12.96 Efficiency and consistency improvements. */
+/* Version 1.1 08.01.96 Added Resize and ExclusiveOr. */
+/* Version 1.0 14.12.95 First version under UNIX (with Perl module). */
+/* Version 0.9 01.11.93 First version of C library under MS-DOS. */
+/* Version 0.1 ??.??.89 First version in Turbo Pascal under CP/M. */
+/* */
+/*****************************************************************************/
+/* AUTHOR: */
+/*****************************************************************************/
+/* */
+/* Steffen Beyer */
+/* mailto:sb@engelschall.com */
+/* http://www.engelschall.com/u/sb/download/ */
+/* */
+/*****************************************************************************/
+/* COPYRIGHT: */
+/*****************************************************************************/
+/* */
+/* Copyright (c) 1995 - 2004 by Steffen Beyer. */
+/* All rights reserved. */
+/* */
+/*****************************************************************************/
+/* LICENSE: */
+/*****************************************************************************/
+/* This package is free software; you can use, modify and redistribute */
+/* it under the same terms as Perl itself, i.e., under the terms of */
+/* the "Artistic License" or the "GNU General Public License". */
+/* */
+/* The C library at the core of this Perl module can additionally */
+/* be used, modified and redistributed under the terms of the */
+/* "GNU Library General Public License". */
+/* */
+/*****************************************************************************/
+/* ARTISTIC LICENSE: */
+/*****************************************************************************/
+/*
+ The "Artistic License"
+
+ Preamble
+
+The intent of this document is to state the conditions under which a
+Package may be copied, such that the Copyright Holder maintains some
+semblance of artistic control over the development of the package,
+while giving the users of the package the right to use and distribute
+the Package in a more-or-less customary fashion, plus the right to make
+reasonable modifications.
+
+Definitions:
+
+ "Package" refers to the collection of files distributed by the
+ Copyright Holder, and derivatives of that collection of files
+ created through textual modification.
+
+ "Standard Version" refers to such a Package if it has not been
+ modified, or has been modified in accordance with the wishes
+ of the Copyright Holder as specified below.
+
+ "Copyright Holder" is whoever is named in the copyright or
+ copyrights for the package.
+
+ "You" is you, if you're thinking about copying or distributing
+ this Package.
+
+ "Reasonable copying fee" is whatever you can justify on the
+ basis of media cost, duplication charges, time of people involved,
+ and so on. (You will not be required to justify it to the
+ Copyright Holder, but only to the computing community at large
+ as a market that must bear the fee.)
+
+ "Freely Available" means that no fee is charged for the item
+ itself, though there may be fees involved in handling the item.
+ It also means that recipients of the item may redistribute it
+ under the same conditions they received it.
+
+1. You may make and give away verbatim copies of the source form of the
+Standard Version of this Package without restriction, provided that you
+duplicate all of the original copyright notices and associated disclaimers.
+
+2. You may apply bug fixes, portability fixes and other modifications
+derived from the Public Domain or from the Copyright Holder. A Package
+modified in such a way shall still be considered the Standard Version.
+
+3. You may otherwise modify your copy of this Package in any way, provided
+that you insert a prominent notice in each changed file stating how and
+when you changed that file, and provided that you do at least ONE of the
+following:
+
+ a) place your modifications in the Public Domain or otherwise make them
+ Freely Available, such as by posting said modifications to Usenet or
+ an equivalent medium, or placing the modifications on a major archive
+ site such as uunet.uu.net, or by allowing the Copyright Holder to include
+ your modifications in the Standard Version of the Package.
+
+ b) use the modified Package only within your corporation or organization.
+
+ c) rename any non-standard executables so the names do not conflict
+ with standard executables, which must also be provided, and provide
+ a separate manual page for each non-standard executable that clearly
+ documents how it differs from the Standard Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+
+4. You may distribute the programs of this Package in object code or
+executable form, provided that you do at least ONE of the following:
+
+ a) distribute a Standard Version of the executables and library files,
+ together with instructions (in the manual page or equivalent) on where
+ to get the Standard Version.
+
+ b) accompany the distribution with the machine-readable source of
+ the Package with your modifications.
+
+ c) give non-standard executables non-standard names, and clearly
+ document the differences in manual pages (or equivalent), together
+ with instructions on where to get the Standard Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+
+5. You may charge a reasonable copying fee for any distribution of this
+Package. You may charge any fee you choose for support of this
+Package. You may not charge a fee for this Package itself. However,
+you may distribute this Package in aggregate with other (possibly
+commercial) programs as part of a larger (possibly commercial) software
+distribution provided that you do not advertise this Package as a
+product of your own. You may embed this Package's interpreter within
+an executable of yours (by linking); this shall be construed as a mere
+form of aggregation, provided that the complete Standard Version of the
+interpreter is so embedded.
+
+6. The scripts and library files supplied as input to or produced as
+output from the programs of this Package do not automatically fall
+under the copyright of this Package, but belong to whoever generated
+them, and may be sold commercially, and may be aggregated with this
+Package. If such scripts or library files are aggregated with this
+Package via the so-called "undump" or "unexec" methods of producing a
+binary executable image, then distribution of such an image shall
+neither be construed as a distribution of this Package nor shall it
+fall under the restrictions of Paragraphs 3 and 4, provided that you do
+not represent such an executable image as a Standard Version of this
+Package.
+
+7. C subroutines (or comparably compiled subroutines in other
+languages) supplied by you and linked into this Package in order to
+emulate subroutines and variables of the language defined by this
+Package shall not be considered part of this Package, but are the
+equivalent of input as in Paragraph 6, provided these subroutines do
+not change the language in any way that would cause it to fail the
+regression tests for the language.
+
+8. Aggregation of this Package with a commercial distribution is always
+permitted provided that the use of this Package is embedded; that is,
+when no overt attempt is made to make this Package's interfaces visible
+to the end user of the commercial distribution. Such use shall not be
+construed as a distribution of this Package.
+
+9. The name of the Copyright Holder may not be used to endorse or promote
+products derived from this software without specific prior written permission.
+
+10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+ The End
+*/
+/*****************************************************************************/
+/* GNU GENERAL PUBLIC LICENSE: */
+/*****************************************************************************/
+/* This program is free software; you can redistribute it and/or */
+/* modify it under the terms of the GNU General Public License */
+/* as published by the Free Software Foundation; either version 2 */
+/* of the License, or (at your option) any later version. */
+/* */
+/* This program is distributed in the hope that it will be useful, */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
+/* GNU General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License */
+/* along with this program; if not, write to the */
+/* Free Software Foundation, Inc., */
+/* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+/* */
+/*****************************************************************************/
+/* GNU LIBRARY GENERAL PUBLIC LICENSE: */
+/*****************************************************************************/
+/* */
+/* This library is free software; you can redistribute it and/or */
+/* modify it under the terms of the GNU Library General Public */
+/* License as published by the Free Software Foundation; either */
+/* version 2 of the License, or (at your option) any later version. */
+/* */
+/* This library is distributed in the hope that it will be useful, */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
+/* Library General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU Library General Public */
+/* License along with this library; if not, write to the */
+/* Free Software Foundation, Inc., */
+/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+/* */
+/* or download a copy from ftp://ftp.gnu.org/pub/gnu/COPYING.LIB-2.0 */
+/* */
+/*****************************************************************************/
+#endif
diff --git a/contrib/tools/yasm/libyasm/bytecode.c b/contrib/tools/yasm/libyasm/bytecode.c
index f864bae0aa..ee28c2b0d9 100644
--- a/contrib/tools/yasm/libyasm/bytecode.c
+++ b/contrib/tools/yasm/libyasm/bytecode.c
@@ -1,386 +1,386 @@
-/*
- * Bytecode utility functions
- *
- * Copyright (C) 2001-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#include "util.h"
-
-#include "libyasm-stdint.h"
-#include "coretype.h"
-
-#include "errwarn.h"
-#include "intnum.h"
-#include "expr.h"
-#include "value.h"
-#include "symrec.h"
-
-#include "bytecode.h"
-
-
-void
-yasm_bc_set_multiple(yasm_bytecode *bc, yasm_expr *e)
-{
- if (bc->multiple)
- bc->multiple = yasm_expr_create_tree(bc->multiple, YASM_EXPR_MUL, e,
- e->line);
- else
- bc->multiple = e;
-}
-
-void
-yasm_bc_finalize_common(yasm_bytecode *bc, yasm_bytecode *prev_bc)
-{
-}
-
-int
-yasm_bc_calc_len_common(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
- void *add_span_data)
-{
- yasm_internal_error(N_("bytecode length cannot be calculated"));
- /*@unreached@*/
- return 0;
-}
-
-int
-yasm_bc_expand_common(yasm_bytecode *bc, int span, long old_val, long new_val,
- /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
-{
- yasm_internal_error(N_("bytecode does not have any dependent spans"));
- /*@unreached@*/
- return 0;
-}
-
-int
-yasm_bc_tobytes_common(yasm_bytecode *bc, unsigned char **buf,
- unsigned char *bufstart, void *d,
- yasm_output_value_func output_value,
- /*@null@*/ yasm_output_reloc_func output_reloc)
-{
- yasm_internal_error(N_("bytecode cannot be converted to bytes"));
- /*@unreached@*/
- return 0;
-}
-
-void
-yasm_bc_transform(yasm_bytecode *bc, const yasm_bytecode_callback *callback,
- void *contents)
-{
- if (bc->callback)
- bc->callback->destroy(bc->contents);
- bc->callback = callback;
- bc->contents = contents;
-}
-
-yasm_bytecode *
-yasm_bc_create_common(const yasm_bytecode_callback *callback, void *contents,
- unsigned long line)
-{
- yasm_bytecode *bc = yasm_xmalloc(sizeof(yasm_bytecode));
-
- bc->callback = callback;
- bc->section = NULL;
- bc->multiple = (yasm_expr *)NULL;
- bc->len = 0;
- bc->mult_int = 1;
- bc->line = line;
- bc->offset = ~0UL; /* obviously incorrect / uninitialized value */
- bc->symrecs = NULL;
- bc->contents = contents;
-
- return bc;
-}
-
-yasm_section *
-yasm_bc_get_section(yasm_bytecode *bc)
-{
- return bc->section;
-}
-
-void
-yasm_bc__add_symrec(yasm_bytecode *bc, yasm_symrec *sym)
-{
- if (!bc->symrecs) {
- bc->symrecs = yasm_xmalloc(2*sizeof(yasm_symrec *));
- bc->symrecs[0] = sym;
- bc->symrecs[1] = NULL;
- } else {
- /* Very inefficient implementation for large numbers of symbols. But
- * that would be very unusual, so use the simple algorithm instead.
- */
- size_t count = 1;
- while (bc->symrecs[count])
- count++;
- bc->symrecs = yasm_xrealloc(bc->symrecs,
- (count+2)*sizeof(yasm_symrec *));
- bc->symrecs[count] = sym;
- bc->symrecs[count+1] = NULL;
- }
-}
-
-void
-yasm_bc_destroy(yasm_bytecode *bc)
-{
- if (!bc)
- return;
-
- if (bc->callback)
- bc->callback->destroy(bc->contents);
- yasm_expr_destroy(bc->multiple);
- if (bc->symrecs)
- yasm_xfree(bc->symrecs);
- yasm_xfree(bc);
-}
-
-void
-yasm_bc_print(const yasm_bytecode *bc, FILE *f, int indent_level)
-{
- if (!bc->callback)
- fprintf(f, "%*s_Empty_\n", indent_level, "");
- else
- bc->callback->print(bc->contents, f, indent_level);
- fprintf(f, "%*sMultiple=", indent_level, "");
- if (!bc->multiple)
- fprintf(f, "nil (1)");
- else
- yasm_expr_print(bc->multiple, f);
- fprintf(f, "\n%*sLength=%lu\n", indent_level, "", bc->len);
- fprintf(f, "%*sLine Index=%lu\n", indent_level, "", bc->line);
- fprintf(f, "%*sOffset=%lx\n", indent_level, "", bc->offset);
-}
-
-void
-yasm_bc_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
-{
- if (bc->callback)
- bc->callback->finalize(bc, prev_bc);
- if (bc->multiple) {
- yasm_value val;
-
- if (yasm_value_finalize_expr(&val, bc->multiple, prev_bc, 0))
- yasm_error_set(YASM_ERROR_TOO_COMPLEX,
- N_("multiple expression too complex"));
- else if (val.rel)
- yasm_error_set(YASM_ERROR_NOT_ABSOLUTE,
- N_("multiple expression not absolute"));
- /* Finalize creates NULL output if value=0, but bc->multiple is NULL
- * if value=1 (this difference is to make the common case small).
- * However, this means we need to set bc->multiple explicitly to 0
- * here if val.abs is NULL.
- */
- if (val.abs)
- bc->multiple = val.abs;
- else
- bc->multiple = yasm_expr_create_ident(
- yasm_expr_int(yasm_intnum_create_uint(0)), bc->line);
- }
-}
-
-/*@null@*/ yasm_intnum *
-yasm_calc_bc_dist(yasm_bytecode *precbc1, yasm_bytecode *precbc2)
-{
- unsigned long dist2, dist1;
- yasm_intnum *intn;
-
- if (precbc1->section != precbc2->section)
- return NULL;
-
- dist1 = yasm_bc_next_offset(precbc1);
- dist2 = yasm_bc_next_offset(precbc2);
- if (dist2 < dist1) {
- intn = yasm_intnum_create_uint(dist1 - dist2);
- yasm_intnum_calc(intn, YASM_EXPR_NEG, NULL);
- return intn;
- }
- dist2 -= dist1;
- return yasm_intnum_create_uint(dist2);
-}
-
-unsigned long
-yasm_bc_next_offset(yasm_bytecode *precbc)
-{
- return precbc->offset + precbc->len*precbc->mult_int;
-}
-
-int
-yasm_bc_elem_size(yasm_bytecode *bc)
-{
- if (!bc->callback) {
- yasm_internal_error(N_("got empty bytecode in yasm_bc_elem_size"));
- return 0;
- } else if (!bc->callback->elem_size)
- return 0;
- else
- return bc->callback->elem_size(bc);
-}
-
-int
-yasm_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
- void *add_span_data)
-{
- int retval = 0;
-
- bc->len = 0;
-
- if (!bc->callback)
- yasm_internal_error(N_("got empty bytecode in yasm_bc_calc_len"));
- else
- retval = bc->callback->calc_len(bc, add_span, add_span_data);
-
- /* Check for multiples */
- bc->mult_int = 1;
- if (bc->multiple) {
- /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
-
- num = yasm_expr_get_intnum(&bc->multiple, 0);
- if (num) {
- if (yasm_intnum_sign(num) < 0) {
- yasm_error_set(YASM_ERROR_VALUE, N_("multiple is negative"));
- retval = -1;
- } else
- bc->mult_int = yasm_intnum_get_int(num);
- } else {
- if (yasm_expr__contains(bc->multiple, YASM_EXPR_FLOAT)) {
- yasm_error_set(YASM_ERROR_VALUE,
- N_("expression must not contain floating point value"));
- retval = -1;
- } else {
- yasm_value value;
- yasm_value_initialize(&value, bc->multiple, 0);
- add_span(add_span_data, bc, 0, &value, 0, 0);
- bc->mult_int = 0; /* assume 0 to start */
- }
- }
- }
-
- /* If we got an error somewhere along the line, clear out any calc len */
- if (retval < 0)
- bc->len = 0;
-
- return retval;
-}
-
-int
-yasm_bc_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
- /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
-{
- if (span == 0) {
- bc->mult_int = new_val;
- return 1;
- }
- if (!bc->callback) {
- yasm_internal_error(N_("got empty bytecode in yasm_bc_expand"));
- /*@unreached@*/
- return -1;
- } else
- return bc->callback->expand(bc, span, old_val, new_val, neg_thres,
- pos_thres);
-}
-
-/*@null@*/ /*@only@*/ unsigned char *
-yasm_bc_tobytes(yasm_bytecode *bc, unsigned char *buf, unsigned long *bufsize,
- /*@out@*/ int *gap, void *d,
- yasm_output_value_func output_value,
- /*@null@*/ yasm_output_reloc_func output_reloc)
- /*@sets *buf@*/
-{
- /*@only@*/ /*@null@*/ unsigned char *mybuf = NULL;
- unsigned char *bufstart;
- unsigned char *origbuf, *destbuf;
- long i;
- int error = 0;
-
- long mult;
- if (yasm_bc_get_multiple(bc, &mult, 1) || mult == 0) {
- *bufsize = 0;
- return NULL;
- }
- bc->mult_int = mult;
-
- /* special case for reserve bytecodes */
- if (bc->callback->special == YASM_BC_SPECIAL_RESERVE) {
- *bufsize = bc->len*bc->mult_int;
- *gap = 1;
- return NULL; /* we didn't allocate a buffer */
- }
- *gap = 0;
-
- if (*bufsize < bc->len*bc->mult_int) {
- mybuf = yasm_xmalloc(bc->len*bc->mult_int);
- destbuf = mybuf;
- } else
- destbuf = buf;
- bufstart = destbuf;
-
- *bufsize = bc->len*bc->mult_int;
-
- if (!bc->callback)
- yasm_internal_error(N_("got empty bytecode in bc_tobytes"));
- else for (i=0; i<bc->mult_int; i++) {
- origbuf = destbuf;
- error = bc->callback->tobytes(bc, &destbuf, bufstart, d, output_value,
- output_reloc);
-
- if (!error && ((unsigned long)(destbuf - origbuf) != bc->len))
- yasm_internal_error(
- N_("written length does not match optimized length"));
- }
-
- return mybuf;
-}
-
-int
-yasm_bc_get_multiple(yasm_bytecode *bc, long *multiple, int calc_bc_dist)
-{
- /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
-
- *multiple = 1;
- if (bc->multiple) {
- num = yasm_expr_get_intnum(&bc->multiple, calc_bc_dist);
- if (!num) {
- yasm_error_set(YASM_ERROR_VALUE,
- N_("could not determine multiple"));
- return 1;
- }
- if (yasm_intnum_sign(num) < 0) {
- yasm_error_set(YASM_ERROR_VALUE, N_("multiple is negative"));
- return 1;
- }
- *multiple = yasm_intnum_get_int(num);
- }
- return 0;
-}
-
-const yasm_expr *
-yasm_bc_get_multiple_expr(const yasm_bytecode *bc)
-{
- return bc->multiple;
-}
-
-yasm_insn *
-yasm_bc_get_insn(yasm_bytecode *bc)
-{
- if (bc->callback->special != YASM_BC_SPECIAL_INSN)
- return NULL;
- return (yasm_insn *)bc->contents;
-}
+/*
+ * Bytecode utility functions
+ *
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "util.h"
+
+#include "libyasm-stdint.h"
+#include "coretype.h"
+
+#include "errwarn.h"
+#include "intnum.h"
+#include "expr.h"
+#include "value.h"
+#include "symrec.h"
+
+#include "bytecode.h"
+
+
+void
+yasm_bc_set_multiple(yasm_bytecode *bc, yasm_expr *e)
+{
+ if (bc->multiple)
+ bc->multiple = yasm_expr_create_tree(bc->multiple, YASM_EXPR_MUL, e,
+ e->line);
+ else
+ bc->multiple = e;
+}
+
+void
+yasm_bc_finalize_common(yasm_bytecode *bc, yasm_bytecode *prev_bc)
+{
+}
+
+int
+yasm_bc_calc_len_common(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ yasm_internal_error(N_("bytecode length cannot be calculated"));
+ /*@unreached@*/
+ return 0;
+}
+
+int
+yasm_bc_expand_common(yasm_bytecode *bc, int span, long old_val, long new_val,
+ /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
+{
+ yasm_internal_error(N_("bytecode does not have any dependent spans"));
+ /*@unreached@*/
+ return 0;
+}
+
+int
+yasm_bc_tobytes_common(yasm_bytecode *bc, unsigned char **buf,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc)
+{
+ yasm_internal_error(N_("bytecode cannot be converted to bytes"));
+ /*@unreached@*/
+ return 0;
+}
+
+void
+yasm_bc_transform(yasm_bytecode *bc, const yasm_bytecode_callback *callback,
+ void *contents)
+{
+ if (bc->callback)
+ bc->callback->destroy(bc->contents);
+ bc->callback = callback;
+ bc->contents = contents;
+}
+
+yasm_bytecode *
+yasm_bc_create_common(const yasm_bytecode_callback *callback, void *contents,
+ unsigned long line)
+{
+ yasm_bytecode *bc = yasm_xmalloc(sizeof(yasm_bytecode));
+
+ bc->callback = callback;
+ bc->section = NULL;
+ bc->multiple = (yasm_expr *)NULL;
+ bc->len = 0;
+ bc->mult_int = 1;
+ bc->line = line;
+ bc->offset = ~0UL; /* obviously incorrect / uninitialized value */
+ bc->symrecs = NULL;
+ bc->contents = contents;
+
+ return bc;
+}
+
+yasm_section *
+yasm_bc_get_section(yasm_bytecode *bc)
+{
+ return bc->section;
+}
+
+void
+yasm_bc__add_symrec(yasm_bytecode *bc, yasm_symrec *sym)
+{
+ if (!bc->symrecs) {
+ bc->symrecs = yasm_xmalloc(2*sizeof(yasm_symrec *));
+ bc->symrecs[0] = sym;
+ bc->symrecs[1] = NULL;
+ } else {
+ /* Very inefficient implementation for large numbers of symbols. But
+ * that would be very unusual, so use the simple algorithm instead.
+ */
+ size_t count = 1;
+ while (bc->symrecs[count])
+ count++;
+ bc->symrecs = yasm_xrealloc(bc->symrecs,
+ (count+2)*sizeof(yasm_symrec *));
+ bc->symrecs[count] = sym;
+ bc->symrecs[count+1] = NULL;
+ }
+}
+
+void
+yasm_bc_destroy(yasm_bytecode *bc)
+{
+ if (!bc)
+ return;
+
+ if (bc->callback)
+ bc->callback->destroy(bc->contents);
+ yasm_expr_destroy(bc->multiple);
+ if (bc->symrecs)
+ yasm_xfree(bc->symrecs);
+ yasm_xfree(bc);
+}
+
+void
+yasm_bc_print(const yasm_bytecode *bc, FILE *f, int indent_level)
+{
+ if (!bc->callback)
+ fprintf(f, "%*s_Empty_\n", indent_level, "");
+ else
+ bc->callback->print(bc->contents, f, indent_level);
+ fprintf(f, "%*sMultiple=", indent_level, "");
+ if (!bc->multiple)
+ fprintf(f, "nil (1)");
+ else
+ yasm_expr_print(bc->multiple, f);
+ fprintf(f, "\n%*sLength=%lu\n", indent_level, "", bc->len);
+ fprintf(f, "%*sLine Index=%lu\n", indent_level, "", bc->line);
+ fprintf(f, "%*sOffset=%lx\n", indent_level, "", bc->offset);
+}
+
+void
+yasm_bc_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
+{
+ if (bc->callback)
+ bc->callback->finalize(bc, prev_bc);
+ if (bc->multiple) {
+ yasm_value val;
+
+ if (yasm_value_finalize_expr(&val, bc->multiple, prev_bc, 0))
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("multiple expression too complex"));
+ else if (val.rel)
+ yasm_error_set(YASM_ERROR_NOT_ABSOLUTE,
+ N_("multiple expression not absolute"));
+ /* Finalize creates NULL output if value=0, but bc->multiple is NULL
+ * if value=1 (this difference is to make the common case small).
+ * However, this means we need to set bc->multiple explicitly to 0
+ * here if val.abs is NULL.
+ */
+ if (val.abs)
+ bc->multiple = val.abs;
+ else
+ bc->multiple = yasm_expr_create_ident(
+ yasm_expr_int(yasm_intnum_create_uint(0)), bc->line);
+ }
+}
+
+/*@null@*/ yasm_intnum *
+yasm_calc_bc_dist(yasm_bytecode *precbc1, yasm_bytecode *precbc2)
+{
+ unsigned long dist2, dist1;
+ yasm_intnum *intn;
+
+ if (precbc1->section != precbc2->section)
+ return NULL;
+
+ dist1 = yasm_bc_next_offset(precbc1);
+ dist2 = yasm_bc_next_offset(precbc2);
+ if (dist2 < dist1) {
+ intn = yasm_intnum_create_uint(dist1 - dist2);
+ yasm_intnum_calc(intn, YASM_EXPR_NEG, NULL);
+ return intn;
+ }
+ dist2 -= dist1;
+ return yasm_intnum_create_uint(dist2);
+}
+
+unsigned long
+yasm_bc_next_offset(yasm_bytecode *precbc)
+{
+ return precbc->offset + precbc->len*precbc->mult_int;
+}
+
+int
+yasm_bc_elem_size(yasm_bytecode *bc)
+{
+ if (!bc->callback) {
+ yasm_internal_error(N_("got empty bytecode in yasm_bc_elem_size"));
+ return 0;
+ } else if (!bc->callback->elem_size)
+ return 0;
+ else
+ return bc->callback->elem_size(bc);
+}
+
+int
+yasm_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ int retval = 0;
+
+ bc->len = 0;
+
+ if (!bc->callback)
+ yasm_internal_error(N_("got empty bytecode in yasm_bc_calc_len"));
+ else
+ retval = bc->callback->calc_len(bc, add_span, add_span_data);
+
+ /* Check for multiples */
+ bc->mult_int = 1;
+ if (bc->multiple) {
+ /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
+
+ num = yasm_expr_get_intnum(&bc->multiple, 0);
+ if (num) {
+ if (yasm_intnum_sign(num) < 0) {
+ yasm_error_set(YASM_ERROR_VALUE, N_("multiple is negative"));
+ retval = -1;
+ } else
+ bc->mult_int = yasm_intnum_get_int(num);
+ } else {
+ if (yasm_expr__contains(bc->multiple, YASM_EXPR_FLOAT)) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("expression must not contain floating point value"));
+ retval = -1;
+ } else {
+ yasm_value value;
+ yasm_value_initialize(&value, bc->multiple, 0);
+ add_span(add_span_data, bc, 0, &value, 0, 0);
+ bc->mult_int = 0; /* assume 0 to start */
+ }
+ }
+ }
+
+ /* If we got an error somewhere along the line, clear out any calc len */
+ if (retval < 0)
+ bc->len = 0;
+
+ return retval;
+}
+
+int
+yasm_bc_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
+ /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
+{
+ if (span == 0) {
+ bc->mult_int = new_val;
+ return 1;
+ }
+ if (!bc->callback) {
+ yasm_internal_error(N_("got empty bytecode in yasm_bc_expand"));
+ /*@unreached@*/
+ return -1;
+ } else
+ return bc->callback->expand(bc, span, old_val, new_val, neg_thres,
+ pos_thres);
+}
+
+/*@null@*/ /*@only@*/ unsigned char *
+yasm_bc_tobytes(yasm_bytecode *bc, unsigned char *buf, unsigned long *bufsize,
+ /*@out@*/ int *gap, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc)
+ /*@sets *buf@*/
+{
+ /*@only@*/ /*@null@*/ unsigned char *mybuf = NULL;
+ unsigned char *bufstart;
+ unsigned char *origbuf, *destbuf;
+ long i;
+ int error = 0;
+
+ long mult;
+ if (yasm_bc_get_multiple(bc, &mult, 1) || mult == 0) {
+ *bufsize = 0;
+ return NULL;
+ }
+ bc->mult_int = mult;
+
+ /* special case for reserve bytecodes */
+ if (bc->callback->special == YASM_BC_SPECIAL_RESERVE) {
+ *bufsize = bc->len*bc->mult_int;
+ *gap = 1;
+ return NULL; /* we didn't allocate a buffer */
+ }
+ *gap = 0;
+
+ if (*bufsize < bc->len*bc->mult_int) {
+ mybuf = yasm_xmalloc(bc->len*bc->mult_int);
+ destbuf = mybuf;
+ } else
+ destbuf = buf;
+ bufstart = destbuf;
+
+ *bufsize = bc->len*bc->mult_int;
+
+ if (!bc->callback)
+ yasm_internal_error(N_("got empty bytecode in bc_tobytes"));
+ else for (i=0; i<bc->mult_int; i++) {
+ origbuf = destbuf;
+ error = bc->callback->tobytes(bc, &destbuf, bufstart, d, output_value,
+ output_reloc);
+
+ if (!error && ((unsigned long)(destbuf - origbuf) != bc->len))
+ yasm_internal_error(
+ N_("written length does not match optimized length"));
+ }
+
+ return mybuf;
+}
+
+int
+yasm_bc_get_multiple(yasm_bytecode *bc, long *multiple, int calc_bc_dist)
+{
+ /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
+
+ *multiple = 1;
+ if (bc->multiple) {
+ num = yasm_expr_get_intnum(&bc->multiple, calc_bc_dist);
+ if (!num) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("could not determine multiple"));
+ return 1;
+ }
+ if (yasm_intnum_sign(num) < 0) {
+ yasm_error_set(YASM_ERROR_VALUE, N_("multiple is negative"));
+ return 1;
+ }
+ *multiple = yasm_intnum_get_int(num);
+ }
+ return 0;
+}
+
+const yasm_expr *
+yasm_bc_get_multiple_expr(const yasm_bytecode *bc)
+{
+ return bc->multiple;
+}
+
+yasm_insn *
+yasm_bc_get_insn(yasm_bytecode *bc)
+{
+ if (bc->callback->special != YASM_BC_SPECIAL_INSN)
+ return NULL;
+ return (yasm_insn *)bc->contents;
+}
diff --git a/contrib/tools/yasm/libyasm/bytecode.h b/contrib/tools/yasm/libyasm/bytecode.h
index 47cd26244b..fc75e57d0e 100644
--- a/contrib/tools/yasm/libyasm/bytecode.h
+++ b/contrib/tools/yasm/libyasm/bytecode.h
@@ -1,638 +1,638 @@
-/**
- * \file libyasm/bytecode.h
- * \brief YASM bytecode interface.
- *
- * \license
- * Copyright (C) 2001-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- * \endlicense
- */
-#ifndef YASM_BYTECODE_H
-#define YASM_BYTECODE_H
-
-#ifndef YASM_LIB_DECL
-#define YASM_LIB_DECL
-#endif
-
-/** A data value (opaque type). */
-typedef struct yasm_dataval yasm_dataval;
-/** A list of data values. */
-typedef struct yasm_datavalhead yasm_datavalhead;
-
-/** Linked list of data values. */
-/*@reldef@*/ STAILQ_HEAD(yasm_datavalhead, yasm_dataval);
-
-/** Add a dependent span for a bytecode.
- * \param add_span_data add_span_data passed into bc_calc_len()
- * \param bc bytecode containing span
- * \param id non-zero identifier for span; may be any non-zero value
- * if <0, expand is called for any change;
- * if >0, expand is only called when exceeds threshold
- * \param value dependent value for bytecode expansion
- * \param neg_thres negative threshold for long/short decision
- * \param pos_thres positive threshold for long/short decision
- */
-typedef void (*yasm_bc_add_span_func)
- (void *add_span_data, yasm_bytecode *bc, int id, const yasm_value *value,
- long neg_thres, long pos_thres);
-
-/** Bytecode callback structure. Any implementation of a specific bytecode
- * must implement these functions and this callback structure. The bytecode
- * implementation-specific data is stored in #yasm_bytecode.contents.
- */
-typedef struct yasm_bytecode_callback {
- /** Destroys the implementation-specific data.
- * Called from yasm_bc_destroy().
- * \param contents #yasm_bytecode.contents
- */
- void (*destroy) (/*@only@*/ void *contents);
-
- /** Prints the implementation-specific data (for debugging purposes).
- * Called from yasm_bc_print().
- * \param contents #yasm_bytecode.contents
- * \param f file
- * \param indent_level indentation level
- */
- void (*print) (const void *contents, FILE *f, int indent_level);
-
- /** Finalizes the bytecode after parsing. Called from yasm_bc_finalize().
- * A generic fill-in for this is yasm_bc_finalize_common().
- * \param bc bytecode
- * \param prev_bc bytecode directly preceding bc
- */
- void (*finalize) (yasm_bytecode *bc, yasm_bytecode *prev_bc);
-
- /** Return elements size of a data bytecode.
- * This function should return the size of each elements of a data
- * bytecode, for proper dereference of symbols attached to it.
- * \param bc bytecode
- * \return 0 if element size is unknown.
- */
- int (*elem_size) (yasm_bytecode *bc);
-
- /** Calculates the minimum size of a bytecode.
- * Called from yasm_bc_calc_len().
- * A generic fill-in for this is yasm_bc_calc_len_common(), but as this
- * function internal errors when called, be very careful when using it!
- * This function should simply add to bc->len and not set it directly
- * (it's initialized by yasm_bc_calc_len() prior to passing control to
- * this function).
- *
- * \param bc bytecode
- * \param add_span function to call to add a span
- * \param add_span_data extra data to be passed to add_span function
- * \return 0 if no error occurred, nonzero if there was an error
- * recognized (and output) during execution.
- * \note May store to bytecode updated expressions.
- */
- int (*calc_len) (yasm_bytecode *bc, yasm_bc_add_span_func add_span,
- void *add_span_data);
-
- /** Recalculates the bytecode's length based on an expanded span length.
- * Called from yasm_bc_expand().
- * A generic fill-in for this is yasm_bc_expand_common(), but as this
- * function internal errors when called, if used, ensure that calc_len()
- * never adds a span.
- * This function should simply add to bc->len to increase the length by
- * a delta amount.
- * \param bc bytecode
- * \param span span ID (as given to add_span in calc_len)
- * \param old_val previous span value
- * \param new_val new span value
- * \param neg_thres negative threshold for long/short decision
- * (returned)
- * \param pos_thres positive threshold for long/short decision
- * (returned)
- * \return 0 if bc no longer dependent on this span's length, negative if
- * there was an error recognized (and output) during execution,
- * and positive if bc size may increase for this span further
- * based on the new negative and positive thresholds returned.
- * \note May store to bytecode updated expressions.
- */
- int (*expand) (yasm_bytecode *bc, int span, long old_val, long new_val,
- /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres);
-
- /** Convert a bytecode into its byte representation.
- * Called from yasm_bc_tobytes().
- * A generic fill-in for this is yasm_bc_tobytes_common(), but as this
- * function internal errors when called, be very careful when using it!
- * \param bc bytecode
- * \param bufp byte representation destination buffer;
- * should be incremented as it's written to,
- * so that on return its delta from the
- * passed-in buf matches the bytecode length
- * (it's okay not to do this if an error
- * indication is returned)
- * \param bufstart For calculating the correct offset parameter for
- * the \a output_value calls: *bufp - bufstart.
- * \param d data to pass to each call to
- * output_value/output_reloc
- * \param output_value function to call to convert values into their byte
- * representation
- * \param output_reloc function to call to output relocation entries
- * for a single sym
- * \return Nonzero on error, 0 on success.
- * \note May result in non-reversible changes to the bytecode, but it's
- * preferable if calling this function twice would result in the
- * same output.
- */
- int (*tobytes) (yasm_bytecode *bc, unsigned char **bufp,
- unsigned char *bufstart, void *d,
- yasm_output_value_func output_value,
- /*@null@*/ yasm_output_reloc_func output_reloc);
-
- /** Special bytecode classifications. Most bytecode types should use
- * #YASM_BC_SPECIAL_NONE. Others cause special handling to kick in
- * in various parts of yasm.
- */
- enum yasm_bytecode_special_type {
- YASM_BC_SPECIAL_NONE = 0,
-
- /** Bytecode reserves space instead of outputting data. */
- YASM_BC_SPECIAL_RESERVE,
-
- /** Adjusts offset instead of calculating len. */
- YASM_BC_SPECIAL_OFFSET,
-
- /** Instruction bytecode. */
- YASM_BC_SPECIAL_INSN
- } special;
-} yasm_bytecode_callback;
-
-/** A bytecode. */
-struct yasm_bytecode {
- /** Bytecodes are stored as a singly linked list, with tail insertion.
- * \see section.h (#yasm_section).
- */
- /*@reldef@*/ STAILQ_ENTRY(yasm_bytecode) link;
-
- /** The bytecode callback structure for this bytecode. May be NULL
- * during partial initialization.
- */
- /*@null@*/ const yasm_bytecode_callback *callback;
-
- /** Pointer to section containing bytecode; NULL if not part of a
- * section.
- */
- /*@dependent@*/ /*@null@*/ yasm_section *section;
-
- /** Number of times bytecode is repeated.
- * NULL=1 (to save space in the common case).
- */
- /*@only@*/ /*@null@*/ yasm_expr *multiple;
-
- /** Total length of entire bytecode (not including multiple copies). */
- unsigned long len;
-
- /** Number of copies, integer version. */
- long mult_int;
-
- /** Line number where bytecode was defined. */
- unsigned long line;
-
- /** Offset of bytecode from beginning of its section.
- * 0-based, ~0UL (e.g. all 1 bits) if unknown.
- */
- unsigned long offset;
-
- /** Unique integer index of bytecode. Used during optimization. */
- unsigned long bc_index;
-
- /** NULL-terminated array of labels that point to this bytecode (as the
- * bytecode previous to the label). NULL if no labels point here.
- */
- /*@null@*/ yasm_symrec **symrecs;
-
- /** Implementation-specific data (type identified by callback). */
- void *contents;
-};
-
-/** Create a bytecode of any specified type.
- * \param callback bytecode callback functions, if NULL, creates empty
- * bytecode (may not be resolved or output)
- * \param contents type-specific data
- * \param line virtual line (from yasm_linemap)
- * \return Newly allocated bytecode of the specified type.
- */
-YASM_LIB_DECL
-/*@only@*/ yasm_bytecode *yasm_bc_create_common
- (/*@null@*/ const yasm_bytecode_callback *callback,
- /*@only@*/ /*@null@*/ void *contents, unsigned long line);
-
-/** Transform a bytecode of any type into a different type.
- * \param bc bytecode to transform
- * \param callback new bytecode callback function
- * \param contents new type-specific data
- */
-YASM_LIB_DECL
-void yasm_bc_transform(yasm_bytecode *bc,
- const yasm_bytecode_callback *callback,
- void *contents);
-
-/** Common bytecode callback finalize function, for where no finalization
- * is ever required for this type of bytecode.
- */
-YASM_LIB_DECL
-void yasm_bc_finalize_common(yasm_bytecode *bc, yasm_bytecode *prev_bc);
-
-/** Common bytecode callback calc_len function, for where the bytecode has
- * no calculatable length. Causes an internal error if called.
- */
-YASM_LIB_DECL
-int yasm_bc_calc_len_common(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
- void *add_span_data);
-
-/** Common bytecode callback expand function, for where the bytecode is
- * always short (calc_len never calls add_span). Causes an internal
- * error if called.
- */
-YASM_LIB_DECL
-int yasm_bc_expand_common
- (yasm_bytecode *bc, int span, long old_val, long new_val,
- /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres);
-
-/** Common bytecode callback tobytes function, for where the bytecode
- * cannot be converted to bytes. Causes an internal error if called.
- */
-YASM_LIB_DECL
-int yasm_bc_tobytes_common
- (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d,
- yasm_output_value_func output_value,
- /*@null@*/ yasm_output_reloc_func output_reloc);
-
-/** Get the next bytecode in a linked list of bytecodes.
- * \param bc bytecode
- * \return Next bytecode.
- */
-#define yasm_bc__next(bc) STAILQ_NEXT(bc, link)
-
-/** Set multiple field of a bytecode.
- * A bytecode can be repeated a number of times when output. This function
- * sets that multiple.
- * \param bc bytecode
- * \param e multiple (kept, do not free)
- */
-YASM_LIB_DECL
-void yasm_bc_set_multiple(yasm_bytecode *bc, /*@keep@*/ yasm_expr *e);
-
-/** Create a bytecode containing data value(s).
- * \param datahead list of data values (kept, do not free)
- * \param size storage size (in bytes) for each data value
- * \param append_zero append a single zero byte after each data value
- * (if non-zero)
- * \param arch architecture (optional); if provided, data items
- * are directly simplified to bytes if possible
- * \param line virtual line (from yasm_linemap)
- * \return Newly allocated bytecode.
- */
-YASM_LIB_DECL
-/*@only@*/ yasm_bytecode *yasm_bc_create_data
- (yasm_datavalhead *datahead, unsigned int size, int append_zero,
- /*@null@*/ yasm_arch *arch, unsigned long line);
-
-/** Create a bytecode containing LEB128-encoded data value(s).
- * \param datahead list of data values (kept, do not free)
- * \param sign signedness (1=signed, 0=unsigned) of each data value
- * \param line virtual line (from yasm_linemap)
- * \return Newly allocated bytecode.
- */
-YASM_LIB_DECL
-/*@only@*/ yasm_bytecode *yasm_bc_create_leb128
- (yasm_datavalhead *datahead, int sign, unsigned long line);
-
-/** Create a bytecode reserving space.
- * \param numitems number of reserve "items" (kept, do not free)
- * \param itemsize reserved size (in bytes) for each item
- * \param line virtual line (from yasm_linemap)
- * \return Newly allocated bytecode.
- */
-YASM_LIB_DECL
-/*@only@*/ yasm_bytecode *yasm_bc_create_reserve
- (/*@only@*/ yasm_expr *numitems, unsigned int itemsize,
- unsigned long line);
-
-/** Get the number of items and itemsize for a reserve bytecode. If bc
- * is not a reserve bytecode, returns NULL.
- * \param bc bytecode
- * \param itemsize reserved size (in bytes) for each item (returned)
- * \return NULL if bc is not a reserve bytecode, otherwise an expression
- * for the number of items to reserve.
- */
-YASM_LIB_DECL
-/*@null@*/ const yasm_expr *yasm_bc_reserve_numitems
- (yasm_bytecode *bc, /*@out@*/ unsigned int *itemsize);
-
-/** Create a bytecode that includes a binary file verbatim.
- * \param filename path to binary file (kept, do not free)
- * \param start starting location in file (in bytes) to read data from
- * (kept, do not free); may be NULL to indicate 0
- * \param maxlen maximum number of bytes to read from the file (kept, do
- * do not free); may be NULL to indicate no maximum
- * \param linemap line mapping repository
- * \param line virtual line (from yasm_linemap) for the bytecode
- * \return Newly allocated bytecode.
- */
-YASM_LIB_DECL
-/*@only@*/ yasm_bytecode *yasm_bc_create_incbin
- (/*@only@*/ char *filename, /*@only@*/ /*@null@*/ yasm_expr *start,
- /*@only@*/ /*@null@*/ yasm_expr *maxlen, yasm_linemap *linemap,
- unsigned long line);
-
-/** Create a bytecode that aligns the following bytecode to a boundary.
- * \param boundary byte alignment (must be a power of two)
- * \param fill fill data (if NULL, code_fill or 0 is used)
- * \param maxskip maximum number of bytes to skip
- * \param code_fill code fill data (if NULL, 0 is used)
- * \param line virtual line (from yasm_linemap)
- * \return Newly allocated bytecode.
- * \note The precedence on generated fill is as follows:
- * - from fill parameter (if not NULL)
- * - from code_fill parameter (if not NULL)
- * - 0
- */
-YASM_LIB_DECL
-/*@only@*/ yasm_bytecode *yasm_bc_create_align
- (/*@keep@*/ yasm_expr *boundary, /*@keep@*/ /*@null@*/ yasm_expr *fill,
- /*@keep@*/ /*@null@*/ yasm_expr *maxskip,
- /*@null@*/ const unsigned char **code_fill, unsigned long line);
-
-/** Create a bytecode that puts the following bytecode at a fixed section
- * offset.
- * \param start section offset of following bytecode
- * \param fill fill value
- * \param line virtual line (from yasm_linemap)
- * \return Newly allocated bytecode.
- */
-YASM_LIB_DECL
-/*@only@*/ yasm_bytecode *yasm_bc_create_org
- (unsigned long start, unsigned long fill, unsigned long line);
-
-/** Get the section that contains a particular bytecode.
- * \param bc bytecode
- * \return Section containing bc (can be NULL if bytecode is not part of a
- * section).
- */
-YASM_LIB_DECL
-/*@dependent@*/ /*@null@*/ yasm_section *yasm_bc_get_section
- (yasm_bytecode *bc);
-
-/** Add to the list of symrecs that reference a bytecode. For symrec use
- * only.
- * \param bc bytecode
- * \param sym symbol
- */
-YASM_LIB_DECL
-void yasm_bc__add_symrec(yasm_bytecode *bc, /*@dependent@*/ yasm_symrec *sym);
-
-/** Delete (free allocated memory for) a bytecode.
- * \param bc bytecode (only pointer to it); may be NULL
- */
-YASM_LIB_DECL
-void yasm_bc_destroy(/*@only@*/ /*@null@*/ yasm_bytecode *bc);
-
-/** Print a bytecode. For debugging purposes.
- * \param f file
- * \param indent_level indentation level
- * \param bc bytecode
- */
-YASM_LIB_DECL
-void yasm_bc_print(const yasm_bytecode *bc, FILE *f, int indent_level);
-
-/** Finalize a bytecode after parsing.
- * \param bc bytecode
- * \param prev_bc bytecode directly preceding bc in a list of bytecodes
- */
-YASM_LIB_DECL
-void yasm_bc_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
-
-/** Determine the distance between the starting offsets of two bytecodes.
- * \param precbc1 preceding bytecode to the first bytecode
- * \param precbc2 preceding bytecode to the second bytecode
- * \return Distance in bytes between the two bytecodes (bc2-bc1), or NULL if
- * the distance was indeterminate.
- * \warning Only valid /after/ optimization.
- */
-YASM_LIB_DECL
-/*@null@*/ /*@only@*/ yasm_intnum *yasm_calc_bc_dist
- (yasm_bytecode *precbc1, yasm_bytecode *precbc2);
-
-/** Get the offset of the next bytecode (the next bytecode doesn't have to
- * actually exist).
- * \param precbc preceding bytecode
- * \return Offset of the next bytecode in bytes.
- * \warning Only valid /after/ optimization.
- */
-YASM_LIB_DECL
-unsigned long yasm_bc_next_offset(yasm_bytecode *precbc);
-
-/** Return elemens size of a data bytecode.
- * Returns the size of each elements of a data bytecode, for proper dereference
- * of symbols attached to it.
- * \param bc bytecode
- * \return 0 if element size is unknown
- */
-YASM_LIB_DECL
-int yasm_bc_elem_size(yasm_bytecode *bc);
-
-/** Resolve EQUs in a bytecode and calculate its minimum size.
- * Generates dependent bytecode spans for cases where, if the length spanned
- * increases, it could cause the bytecode size to increase.
- * Any bytecode multiple is NOT included in the length or spans generation;
- * this must be handled at a higher level.
- * \param bc bytecode
- * \param add_span function to call to add a span
- * \param add_span_data extra data to be passed to add_span function
- * \return 0 if no error occurred, nonzero if there was an error recognized
- * (and output) during execution.
- * \note May store to bytecode updated expressions and the short length.
- */
-YASM_LIB_DECL
-int yasm_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
- void *add_span_data);
-
-/** Recalculate a bytecode's length based on an expanded span length.
- * \param bc bytecode
- * \param span span ID (as given to yasm_bc_add_span_func in
- * yasm_bc_calc_len)
- * \param old_val previous span value
- * \param new_val new span value
- * \param neg_thres negative threshold for long/short decision (returned)
- * \param pos_thres positive threshold for long/short decision (returned)
- * \return 0 if bc no longer dependent on this span's length, negative if
- * there was an error recognized (and output) during execution, and
- * positive if bc size may increase for this span further based on the
- * new negative and positive thresholds returned.
- * \note May store to bytecode updated expressions and the updated length.
- */
-YASM_LIB_DECL
-int yasm_bc_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
- /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres);
-
-/** Convert a bytecode into its byte representation.
- * \param bc bytecode
- * \param buf byte representation destination buffer
- * \param bufsize size of buf (in bytes) prior to call; size of the
- * generated data after call
- * \param gap if nonzero, indicates the data does not really need to
- * exist in the object file; if nonzero, contents of buf
- * are undefined [output]
- * \param d data to pass to each call to output_value/output_reloc
- * \param output_value function to call to convert values into their byte
- * representation
- * \param output_reloc function to call to output relocation entries
- * for a single sym
- * \return Newly allocated buffer that should be used instead of buf for
- * reading the byte representation, or NULL if buf was big enough to
- * hold the entire byte representation.
- * \note Calling twice on the same bytecode may \em not produce the same
- * results on the second call, as calling this function may result in
- * non-reversible changes to the bytecode.
- */
-YASM_LIB_DECL
-/*@null@*/ /*@only@*/ unsigned char *yasm_bc_tobytes
- (yasm_bytecode *bc, unsigned char *buf, unsigned long *bufsize,
- /*@out@*/ int *gap, void *d, yasm_output_value_func output_value,
- /*@null@*/ yasm_output_reloc_func output_reloc)
- /*@sets *buf@*/;
-
-/** Get the bytecode multiple value as an integer.
- * \param bc bytecode
- * \param multiple multiple value (output)
- * \param calc_bc_dist nonzero if distances between bytecodes should be
- * calculated, 0 if error should be returned in this case
- * \return 1 on error (set with yasm_error_set), 0 on success.
- */
-YASM_LIB_DECL
-int yasm_bc_get_multiple(yasm_bytecode *bc, /*@out@*/ long *multiple,
- int calc_bc_dist);
-
-/** Get the bytecode multiple value as an expression.
- * \param bc bytecode
- * \return Bytecode multiple, NULL if =1.
- */
-YASM_LIB_DECL
-const yasm_expr *yasm_bc_get_multiple_expr(const yasm_bytecode *bc);
-
-/** Get a #yasm_insn structure from an instruction bytecode (if possible).
- * \param bc bytecode
- * \return Instruction details if bytecode is an instruction bytecode,
- * otherwise NULL.
- */
-YASM_LIB_DECL
-/*@dependent@*/ /*@null@*/ yasm_insn *yasm_bc_get_insn(yasm_bytecode *bc);
-
-/** Create a new data value from an expression.
- * \param expn expression
- * \return Newly allocated data value.
- */
-YASM_LIB_DECL
-yasm_dataval *yasm_dv_create_expr(/*@keep@*/ yasm_expr *expn);
-
-/** Create a new data value from a string.
- * \param contents string (may contain NULs)
- * \param len length of string
- * \return Newly allocated data value.
- */
-YASM_LIB_DECL
-yasm_dataval *yasm_dv_create_string(/*@keep@*/ char *contents, size_t len);
-
-/** Create a new data value from raw bytes data.
- * \param contents raw data (may contain NULs)
- * \param len length
- * \return Newly allocated data value.
- */
-YASM_LIB_DECL
-yasm_dataval *yasm_dv_create_raw(/*@keep@*/ unsigned char *contents,
- unsigned long len);
-
-/** Create a new uninitialized data value.
- * \return Newly allocated data value.
- */
-YASM_LIB_DECL
-yasm_dataval *yasm_dv_create_reserve(void);
-
-#ifndef YASM_DOXYGEN
-#define yasm_dv_create_string(s, l) yasm_dv_create_raw((unsigned char *)(s), \
- (unsigned long)(l))
-#endif
-
-/** Get the underlying value of a data value.
- * \param dv data value
- * \return Value, or null if non-value (e.g. string or raw).
- */
-YASM_LIB_DECL
-yasm_value *yasm_dv_get_value(yasm_dataval *dv);
-
-/** Set multiple field of a data value.
- * A data value can be repeated a number of times when output. This function
- * sets that multiple.
- * \param dv data value
- * \param e multiple (kept, do not free)
- */
-YASM_LIB_DECL
-void yasm_dv_set_multiple(yasm_dataval *dv, /*@keep@*/ yasm_expr *e);
-
-/** Get the data value multiple value as an unsigned long integer.
- * \param dv data value
- * \param multiple multiple value (output)
- * \return 1 on error (set with yasm_error_set), 0 on success.
- */
-YASM_LIB_DECL
-int yasm_dv_get_multiple(yasm_dataval *dv, /*@out@*/ unsigned long *multiple);
-
-/** Initialize a list of data values.
- * \param headp list of data values
- */
-void yasm_dvs_initialize(yasm_datavalhead *headp);
-#ifndef YASM_DOXYGEN
-#define yasm_dvs_initialize(headp) STAILQ_INIT(headp)
-#endif
-
-/** Delete (free allocated memory for) a list of data values.
- * \param headp list of data values
- */
-YASM_LIB_DECL
-void yasm_dvs_delete(yasm_datavalhead *headp);
-
-/** Add data value to the end of a list of data values.
- * \note Does not make a copy of the data value; so don't pass this function
- * static or local variables, and discard the dv pointer after calling
- * this function.
- * \param headp data value list
- * \param dv data value (may be NULL)
- * \return If data value was actually appended (it wasn't NULL), the data
- * value; otherwise NULL.
- */
-YASM_LIB_DECL
-/*@null@*/ yasm_dataval *yasm_dvs_append
- (yasm_datavalhead *headp, /*@returned@*/ /*@null@*/ yasm_dataval *dv);
-
-/** Print a data value list. For debugging purposes.
- * \param f file
- * \param indent_level indentation level
- * \param headp data value list
- */
-YASM_LIB_DECL
-void yasm_dvs_print(const yasm_datavalhead *headp, FILE *f, int indent_level);
-
-#endif
+/**
+ * \file libyasm/bytecode.h
+ * \brief YASM bytecode interface.
+ *
+ * \license
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * \endlicense
+ */
+#ifndef YASM_BYTECODE_H
+#define YASM_BYTECODE_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/** A data value (opaque type). */
+typedef struct yasm_dataval yasm_dataval;
+/** A list of data values. */
+typedef struct yasm_datavalhead yasm_datavalhead;
+
+/** Linked list of data values. */
+/*@reldef@*/ STAILQ_HEAD(yasm_datavalhead, yasm_dataval);
+
+/** Add a dependent span for a bytecode.
+ * \param add_span_data add_span_data passed into bc_calc_len()
+ * \param bc bytecode containing span
+ * \param id non-zero identifier for span; may be any non-zero value
+ * if <0, expand is called for any change;
+ * if >0, expand is only called when exceeds threshold
+ * \param value dependent value for bytecode expansion
+ * \param neg_thres negative threshold for long/short decision
+ * \param pos_thres positive threshold for long/short decision
+ */
+typedef void (*yasm_bc_add_span_func)
+ (void *add_span_data, yasm_bytecode *bc, int id, const yasm_value *value,
+ long neg_thres, long pos_thres);
+
+/** Bytecode callback structure. Any implementation of a specific bytecode
+ * must implement these functions and this callback structure. The bytecode
+ * implementation-specific data is stored in #yasm_bytecode.contents.
+ */
+typedef struct yasm_bytecode_callback {
+ /** Destroys the implementation-specific data.
+ * Called from yasm_bc_destroy().
+ * \param contents #yasm_bytecode.contents
+ */
+ void (*destroy) (/*@only@*/ void *contents);
+
+ /** Prints the implementation-specific data (for debugging purposes).
+ * Called from yasm_bc_print().
+ * \param contents #yasm_bytecode.contents
+ * \param f file
+ * \param indent_level indentation level
+ */
+ void (*print) (const void *contents, FILE *f, int indent_level);
+
+ /** Finalizes the bytecode after parsing. Called from yasm_bc_finalize().
+ * A generic fill-in for this is yasm_bc_finalize_common().
+ * \param bc bytecode
+ * \param prev_bc bytecode directly preceding bc
+ */
+ void (*finalize) (yasm_bytecode *bc, yasm_bytecode *prev_bc);
+
+ /** Return elements size of a data bytecode.
+ * This function should return the size of each elements of a data
+ * bytecode, for proper dereference of symbols attached to it.
+ * \param bc bytecode
+ * \return 0 if element size is unknown.
+ */
+ int (*elem_size) (yasm_bytecode *bc);
+
+ /** Calculates the minimum size of a bytecode.
+ * Called from yasm_bc_calc_len().
+ * A generic fill-in for this is yasm_bc_calc_len_common(), but as this
+ * function internal errors when called, be very careful when using it!
+ * This function should simply add to bc->len and not set it directly
+ * (it's initialized by yasm_bc_calc_len() prior to passing control to
+ * this function).
+ *
+ * \param bc bytecode
+ * \param add_span function to call to add a span
+ * \param add_span_data extra data to be passed to add_span function
+ * \return 0 if no error occurred, nonzero if there was an error
+ * recognized (and output) during execution.
+ * \note May store to bytecode updated expressions.
+ */
+ int (*calc_len) (yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data);
+
+ /** Recalculates the bytecode's length based on an expanded span length.
+ * Called from yasm_bc_expand().
+ * A generic fill-in for this is yasm_bc_expand_common(), but as this
+ * function internal errors when called, if used, ensure that calc_len()
+ * never adds a span.
+ * This function should simply add to bc->len to increase the length by
+ * a delta amount.
+ * \param bc bytecode
+ * \param span span ID (as given to add_span in calc_len)
+ * \param old_val previous span value
+ * \param new_val new span value
+ * \param neg_thres negative threshold for long/short decision
+ * (returned)
+ * \param pos_thres positive threshold for long/short decision
+ * (returned)
+ * \return 0 if bc no longer dependent on this span's length, negative if
+ * there was an error recognized (and output) during execution,
+ * and positive if bc size may increase for this span further
+ * based on the new negative and positive thresholds returned.
+ * \note May store to bytecode updated expressions.
+ */
+ int (*expand) (yasm_bytecode *bc, int span, long old_val, long new_val,
+ /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres);
+
+ /** Convert a bytecode into its byte representation.
+ * Called from yasm_bc_tobytes().
+ * A generic fill-in for this is yasm_bc_tobytes_common(), but as this
+ * function internal errors when called, be very careful when using it!
+ * \param bc bytecode
+ * \param bufp byte representation destination buffer;
+ * should be incremented as it's written to,
+ * so that on return its delta from the
+ * passed-in buf matches the bytecode length
+ * (it's okay not to do this if an error
+ * indication is returned)
+ * \param bufstart For calculating the correct offset parameter for
+ * the \a output_value calls: *bufp - bufstart.
+ * \param d data to pass to each call to
+ * output_value/output_reloc
+ * \param output_value function to call to convert values into their byte
+ * representation
+ * \param output_reloc function to call to output relocation entries
+ * for a single sym
+ * \return Nonzero on error, 0 on success.
+ * \note May result in non-reversible changes to the bytecode, but it's
+ * preferable if calling this function twice would result in the
+ * same output.
+ */
+ int (*tobytes) (yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+ /** Special bytecode classifications. Most bytecode types should use
+ * #YASM_BC_SPECIAL_NONE. Others cause special handling to kick in
+ * in various parts of yasm.
+ */
+ enum yasm_bytecode_special_type {
+ YASM_BC_SPECIAL_NONE = 0,
+
+ /** Bytecode reserves space instead of outputting data. */
+ YASM_BC_SPECIAL_RESERVE,
+
+ /** Adjusts offset instead of calculating len. */
+ YASM_BC_SPECIAL_OFFSET,
+
+ /** Instruction bytecode. */
+ YASM_BC_SPECIAL_INSN
+ } special;
+} yasm_bytecode_callback;
+
+/** A bytecode. */
+struct yasm_bytecode {
+ /** Bytecodes are stored as a singly linked list, with tail insertion.
+ * \see section.h (#yasm_section).
+ */
+ /*@reldef@*/ STAILQ_ENTRY(yasm_bytecode) link;
+
+ /** The bytecode callback structure for this bytecode. May be NULL
+ * during partial initialization.
+ */
+ /*@null@*/ const yasm_bytecode_callback *callback;
+
+ /** Pointer to section containing bytecode; NULL if not part of a
+ * section.
+ */
+ /*@dependent@*/ /*@null@*/ yasm_section *section;
+
+ /** Number of times bytecode is repeated.
+ * NULL=1 (to save space in the common case).
+ */
+ /*@only@*/ /*@null@*/ yasm_expr *multiple;
+
+ /** Total length of entire bytecode (not including multiple copies). */
+ unsigned long len;
+
+ /** Number of copies, integer version. */
+ long mult_int;
+
+ /** Line number where bytecode was defined. */
+ unsigned long line;
+
+ /** Offset of bytecode from beginning of its section.
+ * 0-based, ~0UL (e.g. all 1 bits) if unknown.
+ */
+ unsigned long offset;
+
+ /** Unique integer index of bytecode. Used during optimization. */
+ unsigned long bc_index;
+
+ /** NULL-terminated array of labels that point to this bytecode (as the
+ * bytecode previous to the label). NULL if no labels point here.
+ */
+ /*@null@*/ yasm_symrec **symrecs;
+
+ /** Implementation-specific data (type identified by callback). */
+ void *contents;
+};
+
+/** Create a bytecode of any specified type.
+ * \param callback bytecode callback functions, if NULL, creates empty
+ * bytecode (may not be resolved or output)
+ * \param contents type-specific data
+ * \param line virtual line (from yasm_linemap)
+ * \return Newly allocated bytecode of the specified type.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_bytecode *yasm_bc_create_common
+ (/*@null@*/ const yasm_bytecode_callback *callback,
+ /*@only@*/ /*@null@*/ void *contents, unsigned long line);
+
+/** Transform a bytecode of any type into a different type.
+ * \param bc bytecode to transform
+ * \param callback new bytecode callback function
+ * \param contents new type-specific data
+ */
+YASM_LIB_DECL
+void yasm_bc_transform(yasm_bytecode *bc,
+ const yasm_bytecode_callback *callback,
+ void *contents);
+
+/** Common bytecode callback finalize function, for where no finalization
+ * is ever required for this type of bytecode.
+ */
+YASM_LIB_DECL
+void yasm_bc_finalize_common(yasm_bytecode *bc, yasm_bytecode *prev_bc);
+
+/** Common bytecode callback calc_len function, for where the bytecode has
+ * no calculatable length. Causes an internal error if called.
+ */
+YASM_LIB_DECL
+int yasm_bc_calc_len_common(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data);
+
+/** Common bytecode callback expand function, for where the bytecode is
+ * always short (calc_len never calls add_span). Causes an internal
+ * error if called.
+ */
+YASM_LIB_DECL
+int yasm_bc_expand_common
+ (yasm_bytecode *bc, int span, long old_val, long new_val,
+ /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres);
+
+/** Common bytecode callback tobytes function, for where the bytecode
+ * cannot be converted to bytes. Causes an internal error if called.
+ */
+YASM_LIB_DECL
+int yasm_bc_tobytes_common
+ (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+/** Get the next bytecode in a linked list of bytecodes.
+ * \param bc bytecode
+ * \return Next bytecode.
+ */
+#define yasm_bc__next(bc) STAILQ_NEXT(bc, link)
+
+/** Set multiple field of a bytecode.
+ * A bytecode can be repeated a number of times when output. This function
+ * sets that multiple.
+ * \param bc bytecode
+ * \param e multiple (kept, do not free)
+ */
+YASM_LIB_DECL
+void yasm_bc_set_multiple(yasm_bytecode *bc, /*@keep@*/ yasm_expr *e);
+
+/** Create a bytecode containing data value(s).
+ * \param datahead list of data values (kept, do not free)
+ * \param size storage size (in bytes) for each data value
+ * \param append_zero append a single zero byte after each data value
+ * (if non-zero)
+ * \param arch architecture (optional); if provided, data items
+ * are directly simplified to bytes if possible
+ * \param line virtual line (from yasm_linemap)
+ * \return Newly allocated bytecode.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_bytecode *yasm_bc_create_data
+ (yasm_datavalhead *datahead, unsigned int size, int append_zero,
+ /*@null@*/ yasm_arch *arch, unsigned long line);
+
+/** Create a bytecode containing LEB128-encoded data value(s).
+ * \param datahead list of data values (kept, do not free)
+ * \param sign signedness (1=signed, 0=unsigned) of each data value
+ * \param line virtual line (from yasm_linemap)
+ * \return Newly allocated bytecode.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_bytecode *yasm_bc_create_leb128
+ (yasm_datavalhead *datahead, int sign, unsigned long line);
+
+/** Create a bytecode reserving space.
+ * \param numitems number of reserve "items" (kept, do not free)
+ * \param itemsize reserved size (in bytes) for each item
+ * \param line virtual line (from yasm_linemap)
+ * \return Newly allocated bytecode.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_bytecode *yasm_bc_create_reserve
+ (/*@only@*/ yasm_expr *numitems, unsigned int itemsize,
+ unsigned long line);
+
+/** Get the number of items and itemsize for a reserve bytecode. If bc
+ * is not a reserve bytecode, returns NULL.
+ * \param bc bytecode
+ * \param itemsize reserved size (in bytes) for each item (returned)
+ * \return NULL if bc is not a reserve bytecode, otherwise an expression
+ * for the number of items to reserve.
+ */
+YASM_LIB_DECL
+/*@null@*/ const yasm_expr *yasm_bc_reserve_numitems
+ (yasm_bytecode *bc, /*@out@*/ unsigned int *itemsize);
+
+/** Create a bytecode that includes a binary file verbatim.
+ * \param filename path to binary file (kept, do not free)
+ * \param start starting location in file (in bytes) to read data from
+ * (kept, do not free); may be NULL to indicate 0
+ * \param maxlen maximum number of bytes to read from the file (kept, do
+ * do not free); may be NULL to indicate no maximum
+ * \param linemap line mapping repository
+ * \param line virtual line (from yasm_linemap) for the bytecode
+ * \return Newly allocated bytecode.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_bytecode *yasm_bc_create_incbin
+ (/*@only@*/ char *filename, /*@only@*/ /*@null@*/ yasm_expr *start,
+ /*@only@*/ /*@null@*/ yasm_expr *maxlen, yasm_linemap *linemap,
+ unsigned long line);
+
+/** Create a bytecode that aligns the following bytecode to a boundary.
+ * \param boundary byte alignment (must be a power of two)
+ * \param fill fill data (if NULL, code_fill or 0 is used)
+ * \param maxskip maximum number of bytes to skip
+ * \param code_fill code fill data (if NULL, 0 is used)
+ * \param line virtual line (from yasm_linemap)
+ * \return Newly allocated bytecode.
+ * \note The precedence on generated fill is as follows:
+ * - from fill parameter (if not NULL)
+ * - from code_fill parameter (if not NULL)
+ * - 0
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_bytecode *yasm_bc_create_align
+ (/*@keep@*/ yasm_expr *boundary, /*@keep@*/ /*@null@*/ yasm_expr *fill,
+ /*@keep@*/ /*@null@*/ yasm_expr *maxskip,
+ /*@null@*/ const unsigned char **code_fill, unsigned long line);
+
+/** Create a bytecode that puts the following bytecode at a fixed section
+ * offset.
+ * \param start section offset of following bytecode
+ * \param fill fill value
+ * \param line virtual line (from yasm_linemap)
+ * \return Newly allocated bytecode.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_bytecode *yasm_bc_create_org
+ (unsigned long start, unsigned long fill, unsigned long line);
+
+/** Get the section that contains a particular bytecode.
+ * \param bc bytecode
+ * \return Section containing bc (can be NULL if bytecode is not part of a
+ * section).
+ */
+YASM_LIB_DECL
+/*@dependent@*/ /*@null@*/ yasm_section *yasm_bc_get_section
+ (yasm_bytecode *bc);
+
+/** Add to the list of symrecs that reference a bytecode. For symrec use
+ * only.
+ * \param bc bytecode
+ * \param sym symbol
+ */
+YASM_LIB_DECL
+void yasm_bc__add_symrec(yasm_bytecode *bc, /*@dependent@*/ yasm_symrec *sym);
+
+/** Delete (free allocated memory for) a bytecode.
+ * \param bc bytecode (only pointer to it); may be NULL
+ */
+YASM_LIB_DECL
+void yasm_bc_destroy(/*@only@*/ /*@null@*/ yasm_bytecode *bc);
+
+/** Print a bytecode. For debugging purposes.
+ * \param f file
+ * \param indent_level indentation level
+ * \param bc bytecode
+ */
+YASM_LIB_DECL
+void yasm_bc_print(const yasm_bytecode *bc, FILE *f, int indent_level);
+
+/** Finalize a bytecode after parsing.
+ * \param bc bytecode
+ * \param prev_bc bytecode directly preceding bc in a list of bytecodes
+ */
+YASM_LIB_DECL
+void yasm_bc_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
+
+/** Determine the distance between the starting offsets of two bytecodes.
+ * \param precbc1 preceding bytecode to the first bytecode
+ * \param precbc2 preceding bytecode to the second bytecode
+ * \return Distance in bytes between the two bytecodes (bc2-bc1), or NULL if
+ * the distance was indeterminate.
+ * \warning Only valid /after/ optimization.
+ */
+YASM_LIB_DECL
+/*@null@*/ /*@only@*/ yasm_intnum *yasm_calc_bc_dist
+ (yasm_bytecode *precbc1, yasm_bytecode *precbc2);
+
+/** Get the offset of the next bytecode (the next bytecode doesn't have to
+ * actually exist).
+ * \param precbc preceding bytecode
+ * \return Offset of the next bytecode in bytes.
+ * \warning Only valid /after/ optimization.
+ */
+YASM_LIB_DECL
+unsigned long yasm_bc_next_offset(yasm_bytecode *precbc);
+
+/** Return elemens size of a data bytecode.
+ * Returns the size of each elements of a data bytecode, for proper dereference
+ * of symbols attached to it.
+ * \param bc bytecode
+ * \return 0 if element size is unknown
+ */
+YASM_LIB_DECL
+int yasm_bc_elem_size(yasm_bytecode *bc);
+
+/** Resolve EQUs in a bytecode and calculate its minimum size.
+ * Generates dependent bytecode spans for cases where, if the length spanned
+ * increases, it could cause the bytecode size to increase.
+ * Any bytecode multiple is NOT included in the length or spans generation;
+ * this must be handled at a higher level.
+ * \param bc bytecode
+ * \param add_span function to call to add a span
+ * \param add_span_data extra data to be passed to add_span function
+ * \return 0 if no error occurred, nonzero if there was an error recognized
+ * (and output) during execution.
+ * \note May store to bytecode updated expressions and the short length.
+ */
+YASM_LIB_DECL
+int yasm_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data);
+
+/** Recalculate a bytecode's length based on an expanded span length.
+ * \param bc bytecode
+ * \param span span ID (as given to yasm_bc_add_span_func in
+ * yasm_bc_calc_len)
+ * \param old_val previous span value
+ * \param new_val new span value
+ * \param neg_thres negative threshold for long/short decision (returned)
+ * \param pos_thres positive threshold for long/short decision (returned)
+ * \return 0 if bc no longer dependent on this span's length, negative if
+ * there was an error recognized (and output) during execution, and
+ * positive if bc size may increase for this span further based on the
+ * new negative and positive thresholds returned.
+ * \note May store to bytecode updated expressions and the updated length.
+ */
+YASM_LIB_DECL
+int yasm_bc_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
+ /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres);
+
+/** Convert a bytecode into its byte representation.
+ * \param bc bytecode
+ * \param buf byte representation destination buffer
+ * \param bufsize size of buf (in bytes) prior to call; size of the
+ * generated data after call
+ * \param gap if nonzero, indicates the data does not really need to
+ * exist in the object file; if nonzero, contents of buf
+ * are undefined [output]
+ * \param d data to pass to each call to output_value/output_reloc
+ * \param output_value function to call to convert values into their byte
+ * representation
+ * \param output_reloc function to call to output relocation entries
+ * for a single sym
+ * \return Newly allocated buffer that should be used instead of buf for
+ * reading the byte representation, or NULL if buf was big enough to
+ * hold the entire byte representation.
+ * \note Calling twice on the same bytecode may \em not produce the same
+ * results on the second call, as calling this function may result in
+ * non-reversible changes to the bytecode.
+ */
+YASM_LIB_DECL
+/*@null@*/ /*@only@*/ unsigned char *yasm_bc_tobytes
+ (yasm_bytecode *bc, unsigned char *buf, unsigned long *bufsize,
+ /*@out@*/ int *gap, void *d, yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc)
+ /*@sets *buf@*/;
+
+/** Get the bytecode multiple value as an integer.
+ * \param bc bytecode
+ * \param multiple multiple value (output)
+ * \param calc_bc_dist nonzero if distances between bytecodes should be
+ * calculated, 0 if error should be returned in this case
+ * \return 1 on error (set with yasm_error_set), 0 on success.
+ */
+YASM_LIB_DECL
+int yasm_bc_get_multiple(yasm_bytecode *bc, /*@out@*/ long *multiple,
+ int calc_bc_dist);
+
+/** Get the bytecode multiple value as an expression.
+ * \param bc bytecode
+ * \return Bytecode multiple, NULL if =1.
+ */
+YASM_LIB_DECL
+const yasm_expr *yasm_bc_get_multiple_expr(const yasm_bytecode *bc);
+
+/** Get a #yasm_insn structure from an instruction bytecode (if possible).
+ * \param bc bytecode
+ * \return Instruction details if bytecode is an instruction bytecode,
+ * otherwise NULL.
+ */
+YASM_LIB_DECL
+/*@dependent@*/ /*@null@*/ yasm_insn *yasm_bc_get_insn(yasm_bytecode *bc);
+
+/** Create a new data value from an expression.
+ * \param expn expression
+ * \return Newly allocated data value.
+ */
+YASM_LIB_DECL
+yasm_dataval *yasm_dv_create_expr(/*@keep@*/ yasm_expr *expn);
+
+/** Create a new data value from a string.
+ * \param contents string (may contain NULs)
+ * \param len length of string
+ * \return Newly allocated data value.
+ */
+YASM_LIB_DECL
+yasm_dataval *yasm_dv_create_string(/*@keep@*/ char *contents, size_t len);
+
+/** Create a new data value from raw bytes data.
+ * \param contents raw data (may contain NULs)
+ * \param len length
+ * \return Newly allocated data value.
+ */
+YASM_LIB_DECL
+yasm_dataval *yasm_dv_create_raw(/*@keep@*/ unsigned char *contents,
+ unsigned long len);
+
+/** Create a new uninitialized data value.
+ * \return Newly allocated data value.
+ */
+YASM_LIB_DECL
+yasm_dataval *yasm_dv_create_reserve(void);
+
+#ifndef YASM_DOXYGEN
+#define yasm_dv_create_string(s, l) yasm_dv_create_raw((unsigned char *)(s), \
+ (unsigned long)(l))
+#endif
+
+/** Get the underlying value of a data value.
+ * \param dv data value
+ * \return Value, or null if non-value (e.g. string or raw).
+ */
+YASM_LIB_DECL
+yasm_value *yasm_dv_get_value(yasm_dataval *dv);
+
+/** Set multiple field of a data value.
+ * A data value can be repeated a number of times when output. This function
+ * sets that multiple.
+ * \param dv data value
+ * \param e multiple (kept, do not free)
+ */
+YASM_LIB_DECL
+void yasm_dv_set_multiple(yasm_dataval *dv, /*@keep@*/ yasm_expr *e);
+
+/** Get the data value multiple value as an unsigned long integer.
+ * \param dv data value
+ * \param multiple multiple value (output)
+ * \return 1 on error (set with yasm_error_set), 0 on success.
+ */
+YASM_LIB_DECL
+int yasm_dv_get_multiple(yasm_dataval *dv, /*@out@*/ unsigned long *multiple);
+
+/** Initialize a list of data values.
+ * \param headp list of data values
+ */
+void yasm_dvs_initialize(yasm_datavalhead *headp);
+#ifndef YASM_DOXYGEN
+#define yasm_dvs_initialize(headp) STAILQ_INIT(headp)
+#endif
+
+/** Delete (free allocated memory for) a list of data values.
+ * \param headp list of data values
+ */
+YASM_LIB_DECL
+void yasm_dvs_delete(yasm_datavalhead *headp);
+
+/** Add data value to the end of a list of data values.
+ * \note Does not make a copy of the data value; so don't pass this function
+ * static or local variables, and discard the dv pointer after calling
+ * this function.
+ * \param headp data value list
+ * \param dv data value (may be NULL)
+ * \return If data value was actually appended (it wasn't NULL), the data
+ * value; otherwise NULL.
+ */
+YASM_LIB_DECL
+/*@null@*/ yasm_dataval *yasm_dvs_append
+ (yasm_datavalhead *headp, /*@returned@*/ /*@null@*/ yasm_dataval *dv);
+
+/** Print a data value list. For debugging purposes.
+ * \param f file
+ * \param indent_level indentation level
+ * \param headp data value list
+ */
+YASM_LIB_DECL
+void yasm_dvs_print(const yasm_datavalhead *headp, FILE *f, int indent_level);
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/cmake-module.c b/contrib/tools/yasm/libyasm/cmake-module.c
index 2ee39ca88f..6ddf9e317f 100644
--- a/contrib/tools/yasm/libyasm/cmake-module.c
+++ b/contrib/tools/yasm/libyasm/cmake-module.c
@@ -1,126 +1,126 @@
-/*
- * YASM module loader
- *
- * Copyright (C) 2004-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#include <util.h>
-
-#include <libyasm.h>
-
-
-typedef struct loaded_module {
- const char *keyword; /* module keyword */
- void *data; /* associated data */
-} loaded_module;
-
-static HAMT *loaded_modules[] = {NULL, NULL, NULL, NULL, NULL, NULL};
-
-static void
-load_module_destroy(/*@only@*/ void *data)
-{
- /* do nothing */
-}
-
-void *
-yasm_load_module(yasm_module_type type, const char *keyword)
-{
- if (!loaded_modules[type])
- return NULL;
- return HAMT_search(loaded_modules[type], keyword);
-}
-
-void
-yasm_register_module(yasm_module_type type, const char *keyword, void *data)
-{
- int replace = 1;
-
- assert(type < sizeof(loaded_modules));
-
- if (!loaded_modules[type])
- loaded_modules[type] = HAMT_create(0, yasm_internal_error_);
-
- HAMT_insert(loaded_modules[type], keyword, data, &replace,
- load_module_destroy);
-}
-
-typedef struct {
- yasm_module_type type;
- void (*printfunc) (const char *name, const char *keyword);
-} list_one_data;
-
-static int
-yasm_list_one_module(void *node, void *d)
-{
- list_one_data *data = (list_one_data *)d;
- yasm_arch_module *arch;
- yasm_dbgfmt_module *dbgfmt;
- yasm_objfmt_module *objfmt;
- yasm_listfmt_module *listfmt;
- yasm_parser_module *parser;
- yasm_preproc_module *preproc;
-
- switch (data->type) {
- case YASM_MODULE_ARCH:
- arch = node;
- data->printfunc(arch->name, arch->keyword);
- break;
- case YASM_MODULE_DBGFMT:
- dbgfmt = node;
- data->printfunc(dbgfmt->name, dbgfmt->keyword);
- break;
- case YASM_MODULE_OBJFMT:
- objfmt = node;
- data->printfunc(objfmt->name, objfmt->keyword);
- break;
- case YASM_MODULE_LISTFMT:
- listfmt = node;
- data->printfunc(listfmt->name, listfmt->keyword);
- break;
- case YASM_MODULE_PARSER:
- parser = node;
- data->printfunc(parser->name, parser->keyword);
- break;
- case YASM_MODULE_PREPROC:
- preproc = node;
- data->printfunc(preproc->name, preproc->keyword);
- break;
- }
- return 0;
-}
-
-void
-yasm_list_modules(yasm_module_type type,
- void (*printfunc) (const char *name, const char *keyword))
-{
- list_one_data data;
-
- /* Go through available list, and try to load each one */
- if (!loaded_modules[type])
- return;
-
- data.type = type;
- data.printfunc = printfunc;
-
- HAMT_traverse(loaded_modules[type], &data, yasm_list_one_module);
-}
+/*
+ * YASM module loader
+ *
+ * Copyright (C) 2004-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <util.h>
+
+#include <libyasm.h>
+
+
+typedef struct loaded_module {
+ const char *keyword; /* module keyword */
+ void *data; /* associated data */
+} loaded_module;
+
+static HAMT *loaded_modules[] = {NULL, NULL, NULL, NULL, NULL, NULL};
+
+static void
+load_module_destroy(/*@only@*/ void *data)
+{
+ /* do nothing */
+}
+
+void *
+yasm_load_module(yasm_module_type type, const char *keyword)
+{
+ if (!loaded_modules[type])
+ return NULL;
+ return HAMT_search(loaded_modules[type], keyword);
+}
+
+void
+yasm_register_module(yasm_module_type type, const char *keyword, void *data)
+{
+ int replace = 1;
+
+ assert(type < sizeof(loaded_modules));
+
+ if (!loaded_modules[type])
+ loaded_modules[type] = HAMT_create(0, yasm_internal_error_);
+
+ HAMT_insert(loaded_modules[type], keyword, data, &replace,
+ load_module_destroy);
+}
+
+typedef struct {
+ yasm_module_type type;
+ void (*printfunc) (const char *name, const char *keyword);
+} list_one_data;
+
+static int
+yasm_list_one_module(void *node, void *d)
+{
+ list_one_data *data = (list_one_data *)d;
+ yasm_arch_module *arch;
+ yasm_dbgfmt_module *dbgfmt;
+ yasm_objfmt_module *objfmt;
+ yasm_listfmt_module *listfmt;
+ yasm_parser_module *parser;
+ yasm_preproc_module *preproc;
+
+ switch (data->type) {
+ case YASM_MODULE_ARCH:
+ arch = node;
+ data->printfunc(arch->name, arch->keyword);
+ break;
+ case YASM_MODULE_DBGFMT:
+ dbgfmt = node;
+ data->printfunc(dbgfmt->name, dbgfmt->keyword);
+ break;
+ case YASM_MODULE_OBJFMT:
+ objfmt = node;
+ data->printfunc(objfmt->name, objfmt->keyword);
+ break;
+ case YASM_MODULE_LISTFMT:
+ listfmt = node;
+ data->printfunc(listfmt->name, listfmt->keyword);
+ break;
+ case YASM_MODULE_PARSER:
+ parser = node;
+ data->printfunc(parser->name, parser->keyword);
+ break;
+ case YASM_MODULE_PREPROC:
+ preproc = node;
+ data->printfunc(preproc->name, preproc->keyword);
+ break;
+ }
+ return 0;
+}
+
+void
+yasm_list_modules(yasm_module_type type,
+ void (*printfunc) (const char *name, const char *keyword))
+{
+ list_one_data data;
+
+ /* Go through available list, and try to load each one */
+ if (!loaded_modules[type])
+ return;
+
+ data.type = type;
+ data.printfunc = printfunc;
+
+ HAMT_traverse(loaded_modules[type], &data, yasm_list_one_module);
+}
diff --git a/contrib/tools/yasm/libyasm/compat-queue.h b/contrib/tools/yasm/libyasm/compat-queue.h
index da9eff4694..bd0c930f69 100644
--- a/contrib/tools/yasm/libyasm/compat-queue.h
+++ b/contrib/tools/yasm/libyasm/compat-queue.h
@@ -1,456 +1,456 @@
-/*
- * <sys/queue.h> implementation for systems that don't have it.
- *
- * Copyright (c) 1991, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)queue.h 8.5 (Berkeley) 8/20/94
- * $FreeBSD: src/sys/sys/queue.h,v 1.32.2.4 2001/03/31 03:33:39 hsu Exp $
- */
-
-#ifndef SYS_QUEUE_H
-#define SYS_QUEUE_H
-
-/*
- * This file defines four types of data structures: singly-linked lists,
- * singly-linked tail queues, lists and tail queues.
- *
- * A singly-linked list is headed by a single forward pointer. The elements
- * are singly linked for minimum space and pointer manipulation overhead at
- * the expense of O(n) removal for arbitrary elements. New elements can be
- * added to the list after an existing element or at the head of the list.
- * Elements being removed from the head of the list should use the explicit
- * macro for this purpose for optimum efficiency. A singly-linked list may
- * only be traversed in the forward direction. Singly-linked lists are ideal
- * for applications with large datasets and few or no removals or for
- * implementing a LIFO queue.
- *
- * A singly-linked tail queue is headed by a pair of pointers, one to the
- * head of the list and the other to the tail of the list. The elements are
- * singly linked for minimum space and pointer manipulation overhead at the
- * expense of O(n) removal for arbitrary elements. New elements can be added
- * to the list after an existing element, at the head of the list, or at the
- * end of the list. Elements being removed from the head of the tail queue
- * should use the explicit macro for this purpose for optimum efficiency.
- * A singly-linked tail queue may only be traversed in the forward direction.
- * Singly-linked tail queues are ideal for applications with large datasets
- * and few or no removals or for implementing a FIFO queue.
- *
- * A list is headed by a single forward pointer (or an array of forward
- * pointers for a hash table header). The elements are doubly linked
- * so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before
- * or after an existing element or at the head of the list. A list
- * may only be traversed in the forward direction.
- *
- * A tail queue is headed by a pair of pointers, one to the head of the
- * list and the other to the tail of the list. The elements are doubly
- * linked so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before or
- * after an existing element, at the head of the list, or at the end of
- * the list. A tail queue may be traversed in either direction.
- *
- * For details on the use of these macros, see the queue(3) manual page.
- *
- *
- * SLIST LIST STAILQ TAILQ
- * _HEAD + + + +
- * _HEAD_INITIALIZER + + + +
- * _ENTRY + + + +
- * _INIT + + + +
- * _EMPTY + + + +
- * _FIRST + + + +
- * _NEXT + + + +
- * _PREV - - - +
- * _LAST - - + +
- * _FOREACH + + + +
- * _FOREACH_SAFE + + + +
- * _FOREACH_REVERSE - - - +
- * _FOREACH_REVERSE_SAFE - - - +
- * _INSERT_HEAD + + + +
- * _INSERT_BEFORE - + - +
- * _INSERT_AFTER + + + +
- * _INSERT_TAIL - - + +
- * _CONCAT - - + +
- * _REMOVE_HEAD + - + -
- * _REMOVE + + + +
- *
- */
-
-/*
- * Singly-linked List declarations.
- */
-#define SLIST_HEAD(name, type) \
-struct name { \
- struct type *slh_first; /* first element */ \
-}
-
-#define SLIST_HEAD_INITIALIZER(head) \
- { NULL }
-
-#define SLIST_ENTRY(type) \
-struct { \
- struct type *sle_next; /* next element */ \
-}
-
-/*
- * Singly-linked List functions.
- */
-#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
-
-#define SLIST_FIRST(head) ((head)->slh_first)
-
-#define SLIST_FOREACH(var, head, field) \
- for ((var) = SLIST_FIRST((head)); \
- (var); \
- (var) = SLIST_NEXT((var), field))
-
-#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
- for ((var) = SLIST_FIRST((head)); \
- (var) && ((tvar) = SLIST_NEXT((var), field), 1); \
- (var) = (tvar))
-
-#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
- for ((varp) = &SLIST_FIRST((head)); \
- ((var) = *(varp)) != NULL; \
- (varp) = &SLIST_NEXT((var), field))
-
-#define SLIST_INIT(head) do { \
- SLIST_FIRST((head)) = NULL; \
-} while (0)
-
-#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
- SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
- SLIST_NEXT((slistelm), field) = (elm); \
-} while (0)
-
-#define SLIST_INSERT_HEAD(head, elm, field) do { \
- SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
- SLIST_FIRST((head)) = (elm); \
-} while (0)
-
-#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
-
-#define SLIST_REMOVE(head, elm, type, field) do { \
- if (SLIST_FIRST((head)) == (elm)) { \
- SLIST_REMOVE_HEAD((head), field); \
- } \
- else { \
- struct type *curelm = SLIST_FIRST((head)); \
- while (SLIST_NEXT(curelm, field) != (elm)) \
- curelm = SLIST_NEXT(curelm, field); \
- SLIST_NEXT(curelm, field) = \
- SLIST_NEXT(SLIST_NEXT(curelm, field), field); \
- } \
-} while (0)
-
-#define SLIST_REMOVE_HEAD(head, field) do { \
- SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
-} while (0)
-
-/*
- * Singly-linked Tail queue declarations.
- */
-#define STAILQ_HEAD(name, type) \
-struct name { \
- struct type *stqh_first;/* first element */ \
- struct type **stqh_last;/* addr of last next element */ \
-}
-
-#define STAILQ_HEAD_INITIALIZER(head) \
- { NULL, &(head).stqh_first }
-
-#define STAILQ_ENTRY(type) \
-struct { \
- struct type *stqe_next; /* next element */ \
-}
-
-/*
- * Singly-linked Tail queue functions.
- */
-#define STAILQ_CONCAT(head1, head2) do { \
- if (!STAILQ_EMPTY((head2))) { \
- *(head1)->stqh_last = (head2)->stqh_first; \
- (head1)->stqh_last = (head2)->stqh_last; \
- STAILQ_INIT((head2)); \
- } \
-} while (0)
-
-#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
-
-#define STAILQ_FIRST(head) ((head)->stqh_first)
-
-#define STAILQ_FOREACH(var, head, field) \
- for((var) = STAILQ_FIRST((head)); \
- (var); \
- (var) = STAILQ_NEXT((var), field))
-
-
-#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
- for ((var) = STAILQ_FIRST((head)); \
- (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
- (var) = (tvar))
-
-#define STAILQ_INIT(head) do { \
- STAILQ_FIRST((head)) = NULL; \
- (head)->stqh_last = &STAILQ_FIRST((head)); \
-} while (0)
-
-#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
- if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
- (head)->stqh_last = &STAILQ_NEXT((elm), field); \
- STAILQ_NEXT((tqelm), field) = (elm); \
-} while (0)
-
-#define STAILQ_INSERT_HEAD(head, elm, field) do { \
- if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
- (head)->stqh_last = &STAILQ_NEXT((elm), field); \
- STAILQ_FIRST((head)) = (elm); \
-} while (0)
-
-#define STAILQ_INSERT_TAIL(head, elm, field) do { \
- STAILQ_NEXT((elm), field) = NULL; \
- *(head)->stqh_last = (elm); \
- (head)->stqh_last = &STAILQ_NEXT((elm), field); \
-} while (0)
-
-#define STAILQ_LAST(head, type, field) \
- (STAILQ_EMPTY((head)) ? \
- NULL : \
- ((struct type *) \
- ((char *)((head)->stqh_last) - offsetof(struct type, field))))
-
-#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
-
-#define STAILQ_REMOVE(head, elm, type, field) do { \
- if (STAILQ_FIRST((head)) == (elm)) { \
- STAILQ_REMOVE_HEAD((head), field); \
- } \
- else { \
- struct type *curelm = STAILQ_FIRST((head)); \
- while (STAILQ_NEXT(curelm, field) != (elm)) \
- curelm = STAILQ_NEXT(curelm, field); \
- if ((STAILQ_NEXT(curelm, field) = \
- STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\
- (head)->stqh_last = &STAILQ_NEXT((curelm), field);\
- } \
-} while (0)
-
-#define STAILQ_REMOVE_HEAD(head, field) do { \
- if ((STAILQ_FIRST((head)) = \
- STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
- (head)->stqh_last = &STAILQ_FIRST((head)); \
-} while (0)
-
-#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \
- if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \
- (head)->stqh_last = &STAILQ_FIRST((head)); \
-} while (0)
-
-/*
- * List declarations.
- */
-#define LIST_HEAD(name, type) \
-struct name { \
- struct type *lh_first; /* first element */ \
-}
-
-#define LIST_HEAD_INITIALIZER(head) \
- { NULL }
-
-#define LIST_ENTRY(type) \
-struct { \
- struct type *le_next; /* next element */ \
- struct type **le_prev; /* address of previous next element */ \
-}
-
-/*
- * List functions.
- */
-
-#define LIST_EMPTY(head) ((head)->lh_first == NULL)
-
-#define LIST_FIRST(head) ((head)->lh_first)
-
-#define LIST_FOREACH(var, head, field) \
- for ((var) = LIST_FIRST((head)); \
- (var); \
- (var) = LIST_NEXT((var), field))
-
-#define LIST_FOREACH_SAFE(var, head, field, tvar) \
- for ((var) = LIST_FIRST((head)); \
- (var) && ((tvar) = LIST_NEXT((var), field), 1); \
- (var) = (tvar))
-
-#define LIST_INIT(head) do { \
- LIST_FIRST((head)) = NULL; \
-} while (0)
-
-#define LIST_INSERT_AFTER(listelm, elm, field) do { \
- if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
- LIST_NEXT((listelm), field)->field.le_prev = \
- &LIST_NEXT((elm), field); \
- LIST_NEXT((listelm), field) = (elm); \
- (elm)->field.le_prev = &LIST_NEXT((listelm), field); \
-} while (0)
-
-#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
- (elm)->field.le_prev = (listelm)->field.le_prev; \
- LIST_NEXT((elm), field) = (listelm); \
- *(listelm)->field.le_prev = (elm); \
- (listelm)->field.le_prev = &LIST_NEXT((elm), field); \
-} while (0)
-
-#define LIST_INSERT_HEAD(head, elm, field) do { \
- if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
- LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
- LIST_FIRST((head)) = (elm); \
- (elm)->field.le_prev = &LIST_FIRST((head)); \
-} while (0)
-
-#define LIST_NEXT(elm, field) ((elm)->field.le_next)
-
-#define LIST_REMOVE(elm, field) do { \
- if (LIST_NEXT((elm), field) != NULL) \
- LIST_NEXT((elm), field)->field.le_prev = \
- (elm)->field.le_prev; \
- *(elm)->field.le_prev = LIST_NEXT((elm), field); \
-} while (0)
-
-/*
- * Tail queue declarations.
- */
-#define TAILQ_HEAD(name, type) \
-struct name { \
- struct type *tqh_first; /* first element */ \
- struct type **tqh_last; /* addr of last next element */ \
-}
-
-#define TAILQ_HEAD_INITIALIZER(head) \
- { NULL, &(head).tqh_first }
-
-#define TAILQ_ENTRY(type) \
-struct { \
- struct type *tqe_next; /* next element */ \
- struct type **tqe_prev; /* address of previous next element */ \
-}
-
-/*
- * Tail queue functions.
- */
-#define TAILQ_CONCAT(head1, head2, field) do { \
- if (!TAILQ_EMPTY(head2)) { \
- *(head1)->tqh_last = (head2)->tqh_first; \
- (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
- (head1)->tqh_last = (head2)->tqh_last; \
- TAILQ_INIT((head2)); \
- } \
-} while (0)
-
-#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
-
-#define TAILQ_FIRST(head) ((head)->tqh_first)
-
-#define TAILQ_FOREACH(var, head, field) \
- for ((var) = TAILQ_FIRST((head)); \
- (var); \
- (var) = TAILQ_NEXT((var), field))
-
-#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
- for ((var) = TAILQ_FIRST((head)); \
- (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
- (var) = (tvar))
-
-#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
- for ((var) = TAILQ_LAST((head), headname); \
- (var); \
- (var) = TAILQ_PREV((var), headname, field))
-
-#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
- for ((var) = TAILQ_LAST((head), headname); \
- (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
- (var) = (tvar))
-
-#define TAILQ_INIT(head) do { \
- TAILQ_FIRST((head)) = NULL; \
- (head)->tqh_last = &TAILQ_FIRST((head)); \
-} while (0)
-
-#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
- if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
- TAILQ_NEXT((elm), field)->field.tqe_prev = \
- &TAILQ_NEXT((elm), field); \
- else { \
- (head)->tqh_last = &TAILQ_NEXT((elm), field); \
- } \
- TAILQ_NEXT((listelm), field) = (elm); \
- (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
-} while (0)
-
-#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
- (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
- TAILQ_NEXT((elm), field) = (listelm); \
- *(listelm)->field.tqe_prev = (elm); \
- (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
-} while (0)
-
-#define TAILQ_INSERT_HEAD(head, elm, field) do { \
- if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
- TAILQ_FIRST((head))->field.tqe_prev = \
- &TAILQ_NEXT((elm), field); \
- else \
- (head)->tqh_last = &TAILQ_NEXT((elm), field); \
- TAILQ_FIRST((head)) = (elm); \
- (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
-} while (0)
-
-#define TAILQ_INSERT_TAIL(head, elm, field) do { \
- TAILQ_NEXT((elm), field) = NULL; \
- (elm)->field.tqe_prev = (head)->tqh_last; \
- *(head)->tqh_last = (elm); \
- (head)->tqh_last = &TAILQ_NEXT((elm), field); \
-} while (0)
-
-#define TAILQ_LAST(head, headname) \
- (*(((struct headname *)((head)->tqh_last))->tqh_last))
-
-#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
-
-#define TAILQ_PREV(elm, headname, field) \
- (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
-
-#define TAILQ_REMOVE(head, elm, field) do { \
- if ((TAILQ_NEXT((elm), field)) != NULL) \
- TAILQ_NEXT((elm), field)->field.tqe_prev = \
- (elm)->field.tqe_prev; \
- else { \
- (head)->tqh_last = (elm)->field.tqe_prev; \
- } \
- *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
-} while (0)
-
-#endif /* !SYS_QUEUE_H */
+/*
+ * <sys/queue.h> implementation for systems that don't have it.
+ *
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)queue.h 8.5 (Berkeley) 8/20/94
+ * $FreeBSD: src/sys/sys/queue.h,v 1.32.2.4 2001/03/31 03:33:39 hsu Exp $
+ */
+
+#ifndef SYS_QUEUE_H
+#define SYS_QUEUE_H
+
+/*
+ * This file defines four types of data structures: singly-linked lists,
+ * singly-linked tail queues, lists and tail queues.
+ *
+ * A singly-linked list is headed by a single forward pointer. The elements
+ * are singly linked for minimum space and pointer manipulation overhead at
+ * the expense of O(n) removal for arbitrary elements. New elements can be
+ * added to the list after an existing element or at the head of the list.
+ * Elements being removed from the head of the list should use the explicit
+ * macro for this purpose for optimum efficiency. A singly-linked list may
+ * only be traversed in the forward direction. Singly-linked lists are ideal
+ * for applications with large datasets and few or no removals or for
+ * implementing a LIFO queue.
+ *
+ * A singly-linked tail queue is headed by a pair of pointers, one to the
+ * head of the list and the other to the tail of the list. The elements are
+ * singly linked for minimum space and pointer manipulation overhead at the
+ * expense of O(n) removal for arbitrary elements. New elements can be added
+ * to the list after an existing element, at the head of the list, or at the
+ * end of the list. Elements being removed from the head of the tail queue
+ * should use the explicit macro for this purpose for optimum efficiency.
+ * A singly-linked tail queue may only be traversed in the forward direction.
+ * Singly-linked tail queues are ideal for applications with large datasets
+ * and few or no removals or for implementing a FIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ *
+ *
+ * SLIST LIST STAILQ TAILQ
+ * _HEAD + + + +
+ * _HEAD_INITIALIZER + + + +
+ * _ENTRY + + + +
+ * _INIT + + + +
+ * _EMPTY + + + +
+ * _FIRST + + + +
+ * _NEXT + + + +
+ * _PREV - - - +
+ * _LAST - - + +
+ * _FOREACH + + + +
+ * _FOREACH_SAFE + + + +
+ * _FOREACH_REVERSE - - - +
+ * _FOREACH_REVERSE_SAFE - - - +
+ * _INSERT_HEAD + + + +
+ * _INSERT_BEFORE - + - +
+ * _INSERT_AFTER + + + +
+ * _INSERT_TAIL - - + +
+ * _CONCAT - - + +
+ * _REMOVE_HEAD + - + -
+ * _REMOVE + + + +
+ *
+ */
+
+/*
+ * Singly-linked List declarations.
+ */
+#define SLIST_HEAD(name, type) \
+struct name { \
+ struct type *slh_first; /* first element */ \
+}
+
+#define SLIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define SLIST_ENTRY(type) \
+struct { \
+ struct type *sle_next; /* next element */ \
+}
+
+/*
+ * Singly-linked List functions.
+ */
+#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
+
+#define SLIST_FIRST(head) ((head)->slh_first)
+
+#define SLIST_FOREACH(var, head, field) \
+ for ((var) = SLIST_FIRST((head)); \
+ (var); \
+ (var) = SLIST_NEXT((var), field))
+
+#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = SLIST_FIRST((head)); \
+ (var) && ((tvar) = SLIST_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
+ for ((varp) = &SLIST_FIRST((head)); \
+ ((var) = *(varp)) != NULL; \
+ (varp) = &SLIST_NEXT((var), field))
+
+#define SLIST_INIT(head) do { \
+ SLIST_FIRST((head)) = NULL; \
+} while (0)
+
+#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
+ SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
+ SLIST_NEXT((slistelm), field) = (elm); \
+} while (0)
+
+#define SLIST_INSERT_HEAD(head, elm, field) do { \
+ SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
+ SLIST_FIRST((head)) = (elm); \
+} while (0)
+
+#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
+
+#define SLIST_REMOVE(head, elm, type, field) do { \
+ if (SLIST_FIRST((head)) == (elm)) { \
+ SLIST_REMOVE_HEAD((head), field); \
+ } \
+ else { \
+ struct type *curelm = SLIST_FIRST((head)); \
+ while (SLIST_NEXT(curelm, field) != (elm)) \
+ curelm = SLIST_NEXT(curelm, field); \
+ SLIST_NEXT(curelm, field) = \
+ SLIST_NEXT(SLIST_NEXT(curelm, field), field); \
+ } \
+} while (0)
+
+#define SLIST_REMOVE_HEAD(head, field) do { \
+ SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
+} while (0)
+
+/*
+ * Singly-linked Tail queue declarations.
+ */
+#define STAILQ_HEAD(name, type) \
+struct name { \
+ struct type *stqh_first;/* first element */ \
+ struct type **stqh_last;/* addr of last next element */ \
+}
+
+#define STAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).stqh_first }
+
+#define STAILQ_ENTRY(type) \
+struct { \
+ struct type *stqe_next; /* next element */ \
+}
+
+/*
+ * Singly-linked Tail queue functions.
+ */
+#define STAILQ_CONCAT(head1, head2) do { \
+ if (!STAILQ_EMPTY((head2))) { \
+ *(head1)->stqh_last = (head2)->stqh_first; \
+ (head1)->stqh_last = (head2)->stqh_last; \
+ STAILQ_INIT((head2)); \
+ } \
+} while (0)
+
+#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
+
+#define STAILQ_FIRST(head) ((head)->stqh_first)
+
+#define STAILQ_FOREACH(var, head, field) \
+ for((var) = STAILQ_FIRST((head)); \
+ (var); \
+ (var) = STAILQ_NEXT((var), field))
+
+
+#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = STAILQ_FIRST((head)); \
+ (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define STAILQ_INIT(head) do { \
+ STAILQ_FIRST((head)) = NULL; \
+ (head)->stqh_last = &STAILQ_FIRST((head)); \
+} while (0)
+
+#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
+ if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+ STAILQ_NEXT((tqelm), field) = (elm); \
+} while (0)
+
+#define STAILQ_INSERT_HEAD(head, elm, field) do { \
+ if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+ STAILQ_FIRST((head)) = (elm); \
+} while (0)
+
+#define STAILQ_INSERT_TAIL(head, elm, field) do { \
+ STAILQ_NEXT((elm), field) = NULL; \
+ *(head)->stqh_last = (elm); \
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+} while (0)
+
+#define STAILQ_LAST(head, type, field) \
+ (STAILQ_EMPTY((head)) ? \
+ NULL : \
+ ((struct type *) \
+ ((char *)((head)->stqh_last) - offsetof(struct type, field))))
+
+#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
+
+#define STAILQ_REMOVE(head, elm, type, field) do { \
+ if (STAILQ_FIRST((head)) == (elm)) { \
+ STAILQ_REMOVE_HEAD((head), field); \
+ } \
+ else { \
+ struct type *curelm = STAILQ_FIRST((head)); \
+ while (STAILQ_NEXT(curelm, field) != (elm)) \
+ curelm = STAILQ_NEXT(curelm, field); \
+ if ((STAILQ_NEXT(curelm, field) = \
+ STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\
+ (head)->stqh_last = &STAILQ_NEXT((curelm), field);\
+ } \
+} while (0)
+
+#define STAILQ_REMOVE_HEAD(head, field) do { \
+ if ((STAILQ_FIRST((head)) = \
+ STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
+ (head)->stqh_last = &STAILQ_FIRST((head)); \
+} while (0)
+
+#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \
+ if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \
+ (head)->stqh_last = &STAILQ_FIRST((head)); \
+} while (0)
+
+/*
+ * List declarations.
+ */
+#define LIST_HEAD(name, type) \
+struct name { \
+ struct type *lh_first; /* first element */ \
+}
+
+#define LIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define LIST_ENTRY(type) \
+struct { \
+ struct type *le_next; /* next element */ \
+ struct type **le_prev; /* address of previous next element */ \
+}
+
+/*
+ * List functions.
+ */
+
+#define LIST_EMPTY(head) ((head)->lh_first == NULL)
+
+#define LIST_FIRST(head) ((head)->lh_first)
+
+#define LIST_FOREACH(var, head, field) \
+ for ((var) = LIST_FIRST((head)); \
+ (var); \
+ (var) = LIST_NEXT((var), field))
+
+#define LIST_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = LIST_FIRST((head)); \
+ (var) && ((tvar) = LIST_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define LIST_INIT(head) do { \
+ LIST_FIRST((head)) = NULL; \
+} while (0)
+
+#define LIST_INSERT_AFTER(listelm, elm, field) do { \
+ if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
+ LIST_NEXT((listelm), field)->field.le_prev = \
+ &LIST_NEXT((elm), field); \
+ LIST_NEXT((listelm), field) = (elm); \
+ (elm)->field.le_prev = &LIST_NEXT((listelm), field); \
+} while (0)
+
+#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.le_prev = (listelm)->field.le_prev; \
+ LIST_NEXT((elm), field) = (listelm); \
+ *(listelm)->field.le_prev = (elm); \
+ (listelm)->field.le_prev = &LIST_NEXT((elm), field); \
+} while (0)
+
+#define LIST_INSERT_HEAD(head, elm, field) do { \
+ if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
+ LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
+ LIST_FIRST((head)) = (elm); \
+ (elm)->field.le_prev = &LIST_FIRST((head)); \
+} while (0)
+
+#define LIST_NEXT(elm, field) ((elm)->field.le_next)
+
+#define LIST_REMOVE(elm, field) do { \
+ if (LIST_NEXT((elm), field) != NULL) \
+ LIST_NEXT((elm), field)->field.le_prev = \
+ (elm)->field.le_prev; \
+ *(elm)->field.le_prev = LIST_NEXT((elm), field); \
+} while (0)
+
+/*
+ * Tail queue declarations.
+ */
+#define TAILQ_HEAD(name, type) \
+struct name { \
+ struct type *tqh_first; /* first element */ \
+ struct type **tqh_last; /* addr of last next element */ \
+}
+
+#define TAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).tqh_first }
+
+#define TAILQ_ENTRY(type) \
+struct { \
+ struct type *tqe_next; /* next element */ \
+ struct type **tqe_prev; /* address of previous next element */ \
+}
+
+/*
+ * Tail queue functions.
+ */
+#define TAILQ_CONCAT(head1, head2, field) do { \
+ if (!TAILQ_EMPTY(head2)) { \
+ *(head1)->tqh_last = (head2)->tqh_first; \
+ (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
+ (head1)->tqh_last = (head2)->tqh_last; \
+ TAILQ_INIT((head2)); \
+ } \
+} while (0)
+
+#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
+
+#define TAILQ_FIRST(head) ((head)->tqh_first)
+
+#define TAILQ_FOREACH(var, head, field) \
+ for ((var) = TAILQ_FIRST((head)); \
+ (var); \
+ (var) = TAILQ_NEXT((var), field))
+
+#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = TAILQ_FIRST((head)); \
+ (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
+ for ((var) = TAILQ_LAST((head), headname); \
+ (var); \
+ (var) = TAILQ_PREV((var), headname, field))
+
+#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
+ for ((var) = TAILQ_LAST((head), headname); \
+ (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
+ (var) = (tvar))
+
+#define TAILQ_INIT(head) do { \
+ TAILQ_FIRST((head)) = NULL; \
+ (head)->tqh_last = &TAILQ_FIRST((head)); \
+} while (0)
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
+ TAILQ_NEXT((elm), field)->field.tqe_prev = \
+ &TAILQ_NEXT((elm), field); \
+ else { \
+ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
+ } \
+ TAILQ_NEXT((listelm), field) = (elm); \
+ (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
+} while (0)
+
+#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
+ TAILQ_NEXT((elm), field) = (listelm); \
+ *(listelm)->field.tqe_prev = (elm); \
+ (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
+} while (0)
+
+#define TAILQ_INSERT_HEAD(head, elm, field) do { \
+ if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
+ TAILQ_FIRST((head))->field.tqe_prev = \
+ &TAILQ_NEXT((elm), field); \
+ else \
+ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
+ TAILQ_FIRST((head)) = (elm); \
+ (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
+} while (0)
+
+#define TAILQ_INSERT_TAIL(head, elm, field) do { \
+ TAILQ_NEXT((elm), field) = NULL; \
+ (elm)->field.tqe_prev = (head)->tqh_last; \
+ *(head)->tqh_last = (elm); \
+ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
+} while (0)
+
+#define TAILQ_LAST(head, headname) \
+ (*(((struct headname *)((head)->tqh_last))->tqh_last))
+
+#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+
+#define TAILQ_PREV(elm, headname, field) \
+ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+
+#define TAILQ_REMOVE(head, elm, field) do { \
+ if ((TAILQ_NEXT((elm), field)) != NULL) \
+ TAILQ_NEXT((elm), field)->field.tqe_prev = \
+ (elm)->field.tqe_prev; \
+ else { \
+ (head)->tqh_last = (elm)->field.tqe_prev; \
+ } \
+ *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
+} while (0)
+
+#endif /* !SYS_QUEUE_H */
diff --git a/contrib/tools/yasm/libyasm/coretype.h b/contrib/tools/yasm/libyasm/coretype.h
index 624e3c445c..ead8f1d480 100644
--- a/contrib/tools/yasm/libyasm/coretype.h
+++ b/contrib/tools/yasm/libyasm/coretype.h
@@ -1,393 +1,393 @@
-/**
- * \file libyasm/coretype.h
- * \brief YASM core types and utility functions.
- *
- * \license
- * Copyright (C) 2001-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- * \endlicense
- */
-#ifndef YASM_CORETYPE_H
-#define YASM_CORETYPE_H
-
-#ifndef YASM_LIB_DECL
-#define YASM_LIB_DECL
-#endif
-
-/** Architecture instance (mostly opaque type). \see arch.h for details. */
-typedef struct yasm_arch yasm_arch;
-/** Preprocessor interface. \see preproc.h for details. */
-typedef struct yasm_preproc yasm_preproc;
-/** Parser instance (mostly opaque type). \see parser.h for details. */
-typedef struct yasm_parser yasm_parser;
-/** Object format interface. \see objfmt.h for details. */
-typedef struct yasm_objfmt yasm_objfmt;
-/** Debug format interface. \see dbgfmt.h for details. */
-typedef struct yasm_dbgfmt yasm_dbgfmt;
-/** List format interface. \see listfmt.h for details. */
-typedef struct yasm_listfmt yasm_listfmt;
-
-/** Object format module interface. \see objfmt.h for details. */
-typedef struct yasm_objfmt_module yasm_objfmt_module;
-/** Debug format module interface. \see dbgfmt.h for details. */
-typedef struct yasm_dbgfmt_module yasm_dbgfmt_module;
-
-/** Standard macro structure for modules that allows association of a set of
- * standard macros with a parser/preprocessor combination.
- * A NULL-terminated array of these structures is used in a number of module
- * interfaces.
- */
-typedef struct yasm_stdmac {
- const char *parser; /**< Parser keyword */
- const char *preproc; /**< Preprocessor keyword */
-
- /** NULL-terminated array of standard macros. May be NULL if no standard
- * macros should be added for this preprocessor.
- */
- const char **macros;
-} yasm_stdmac;
-
-/** YASM associated data callback structure. Many data structures can have
- * arbitrary data associated with them.
- */
-typedef struct yasm_assoc_data_callback {
- /** Free memory allocated for associated data.
- * \param data associated data
- */
- void (*destroy) (/*@only@*/ void *data);
-
- /** Print a description of allocated data. For debugging purposes.
- * \param data associated data
- * \param f output file
- * \param indent_level indentation level
- */
- void (*print) (void *data, FILE *f, int indent_level);
-} yasm_assoc_data_callback;
-
-/** Set of collected error/warnings (opaque type).
- * \see errwarn.h for details.
- */
-typedef struct yasm_errwarns yasm_errwarns;
-
-/** Bytecode. \see bytecode.h for details and related functions. */
-typedef struct yasm_bytecode yasm_bytecode;
-
-/** Object. \see section.h for details and related functions. */
-typedef struct yasm_object yasm_object;
-
-/** Section (opaque type). \see section.h for related functions. */
-typedef struct yasm_section yasm_section;
-
-/** Symbol table (opaque type). \see symrec.h for related functions. */
-typedef struct yasm_symtab yasm_symtab;
-
-/** Symbol record (opaque type). \see symrec.h for related functions. */
-typedef struct yasm_symrec yasm_symrec;
-
-/** Expression. \see expr.h for details and related functions. */
-typedef struct yasm_expr yasm_expr;
-/** Integer value (opaque type). \see intnum.h for related functions. */
-typedef struct yasm_intnum yasm_intnum;
-/** Floating point value (opaque type).
- * \see floatnum.h for related functions.
- */
-typedef struct yasm_floatnum yasm_floatnum;
-
-/** A value. May be absolute or relative. Outside the parser, yasm_expr
- * should only be used for absolute exprs. Anything that could contain
- * a relocatable value should use this structure instead.
- * \see value.h for related functions.
- */
-typedef struct yasm_value {
- /** The absolute portion of the value. May contain *differences* between
- * symrecs but not standalone symrecs. May be NULL if there is no
- * absolute portion (e.g. the absolute portion is 0).
- */
- /*@null@*/ /*@only@*/ yasm_expr *abs;
-
- /** The relative portion of the value. This is the portion that may
- * need to generate a relocation. May be NULL if no relative portion.
- */
- /*@null@*/ /*@dependent@*/ yasm_symrec *rel;
-
- /** What the relative portion is in reference to. NULL if the default. */
- /*@null@*/ /*@dependent@*/ yasm_symrec *wrt;
-
- /** If the segment of the relative portion should be used, not the
- * relative portion itself. Boolean.
- */
- unsigned int seg_of : 1;
-
- /** If the relative portion of the value should be shifted right
- * (supported only by a few object formats). If just the absolute portion
- * should be shifted, that must be in the abs expr, not here!
- */
- unsigned int rshift : 7;
-
- /** Indicates the relative portion of the value should be relocated
- * relative to the current assembly position rather than relative to the
- * section start. "Current assembly position" here refers to the starting
- * address of the bytecode containing this value. Boolean.
- */
- unsigned int curpos_rel : 1;
-
- /** Indicates that curpos_rel was set due to IP-relative relocation;
- * in some objfmt/arch combinations (e.g. win64/x86-amd64) this info
- * is needed to generate special relocations.
- */
- unsigned int ip_rel : 1;
-
- /** Indicates the value is a jump target address (rather than a simple
- * data address). In some objfmt/arch combinations (e.g. macho/amd64)
- * this info is needed to generate special relocations.
- */
- unsigned int jump_target : 1;
-
- /** Indicates the relative portion of the value should be relocated
- * relative to its own section start rather than relative to the
- * section start of the bytecode containing this value. E.g. the value
- * resulting from the relative portion should be the offset from its
- * section start. Boolean.
- */
- unsigned int section_rel : 1;
-
- /** Indicates overflow warnings have been disabled for this value. */
- unsigned int no_warn : 1;
-
- /** Sign of the value. Nonzero if the final value should be treated as
- * signed, 0 if it should be treated as signed.
- */
- unsigned int sign : 1;
-
- /** Size of the value, in bits. */
- unsigned int size : 8;
-} yasm_value;
-
-/** Maximum value of #yasm_value.rshift */
-#define YASM_VALUE_RSHIFT_MAX 127
-
-/** Line number mapping repository (opaque type). \see linemap.h for related
- * functions.
- */
-typedef struct yasm_linemap yasm_linemap;
-
-/** Value/parameter pair (opaque type).
- * \see valparam.h for related functions.
- */
-typedef struct yasm_valparam yasm_valparam;
-/** List of value/parameters (opaque type).
- * \see valparam.h for related functions.
- */
-typedef struct yasm_valparamhead yasm_valparamhead;
-/** Directive list entry.
- * \see valparam.h for details and related functions.
- */
-typedef struct yasm_directive yasm_directive;
-
-/** An effective address.
- * \see insn.h for related functions.
- */
-typedef struct yasm_effaddr yasm_effaddr;
-
-/** An instruction.
- * \see insn.h for related functions.
- */
-typedef struct yasm_insn yasm_insn;
-
-/** Expression operators usable in #yasm_expr expressions. */
-typedef enum yasm_expr_op {
- YASM_EXPR_IDENT, /**< No operation, just a value. */
- YASM_EXPR_ADD, /**< Arithmetic addition (+). */
- YASM_EXPR_SUB, /**< Arithmetic subtraction (-). */
- YASM_EXPR_MUL, /**< Arithmetic multiplication (*). */
- YASM_EXPR_DIV, /**< Arithmetic unsigned division. */
- YASM_EXPR_SIGNDIV, /**< Arithmetic signed division. */
- YASM_EXPR_MOD, /**< Arithmetic unsigned modulus. */
- YASM_EXPR_SIGNMOD, /**< Arithmetic signed modulus. */
- YASM_EXPR_NEG, /**< Arithmetic negation (-). */
- YASM_EXPR_NOT, /**< Bitwise negation. */
- 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. */
- YASM_EXPR_LE, /**< Less than or equal to comparison. */
- YASM_EXPR_GE, /**< Greater than or equal to comparison. */
- YASM_EXPR_NE, /**< Not equal comparison. */
- YASM_EXPR_NONNUM, /**< Start of non-numeric operations (not an op). */
- YASM_EXPR_SEG, /**< SEG operator (gets segment portion of address). */
- YASM_EXPR_WRT, /**< WRT operator (gets offset of address relative to
- * some other segment). */
- YASM_EXPR_SEGOFF /**< The ':' in segment:offset. */
-} yasm_expr_op;
-
-/** Convert yasm_value to its byte representation. Usually implemented by
- * object formats to keep track of relocations and verify legal expressions.
- * Must put the value into the least significant bits of the destination,
- * unless shifted into more significant bits by the shift parameter. The
- * destination bits must be cleared before being set.
- * \param value value
- * \param buf buffer for byte representation
- * \param destsize destination size (in bytes)
- * \param offset offset (in bytes) of the expr contents from the start
- * of the bytecode (needed for relative)
- * \param bc current bytecode (usually passed into higher-level
- * calling function)
- * \param warn enables standard warnings: zero for none;
- * nonzero for overflow/underflow floating point warnings
- * \param d objfmt-specific data (passed into higher-level calling
- * function)
- * \return Nonzero if an error occurred, 0 otherwise.
- */
-typedef int (*yasm_output_value_func)
- (yasm_value *value, /*@out@*/ unsigned char *buf, unsigned int destsize,
- unsigned long offset, yasm_bytecode *bc, int warn, /*@null@*/ void *d);
-
-/** Convert a symbol reference to its byte representation. Usually implemented
- * by object formats and debug formats to keep track of relocations generated
- * by themselves.
- * \param sym symbol
- * \param bc current bytecode (usually passed into higher-level
- * calling function)
- * \param buf buffer for byte representation
- * \param destsize destination size (in bytes)
- * \param valsize size (in bits)
- * \param warn enables standard warnings: zero for none;
- * nonzero for overflow/underflow floating point warnings;
- * negative for signed integer warnings,
- * positive for unsigned integer warnings
- * \param d objfmt-specific data (passed into higher-level calling
- * function)
- * \return Nonzero if an error occurred, 0 otherwise.
- */
-typedef int (*yasm_output_reloc_func)
- (yasm_symrec *sym, yasm_bytecode *bc, unsigned char *buf,
- unsigned int destsize, unsigned int valsize, int warn, void *d);
-
-/** Sort an array using merge sort algorithm.
- * \internal
- * \param base base of array
- * \param nmemb number of elements in array
- * \param size size of each array element
- * \param compar element comparison function
- */
-YASM_LIB_DECL
-int yasm__mergesort(void *base, size_t nmemb, size_t size,
- int (*compar)(const void *, const void *));
-
-/** Separate string by delimiters.
- * \internal
- * \param stringp string
- * \param delim set of 1 or more delimiters
- * \return First/next substring.
- */
-YASM_LIB_DECL
-/*@null@*/ char *yasm__strsep(char **stringp, const char *delim);
-
-/** Compare two strings, ignoring case differences.
- * \internal
- * \param s1 string 1
- * \param s2 string 2
- * \return 0 if strings are equal, -1 if s1<s2, 1 if s1>s2.
- */
-YASM_LIB_DECL
-int yasm__strcasecmp(const char *s1, const char *s2);
-
-/** Compare portion of two strings, ignoring case differences.
- * \internal
- * \param s1 string 1
- * \param s2 string 2
- * \param n maximum number of characters to compare
- * \return 0 if strings are equal, -1 if s1<s2, 1 if s1>s2.
- */
-YASM_LIB_DECL
-int yasm__strncasecmp(const char *s1, const char *s2, size_t n);
-
-/** strdup() implementation using yasm_xmalloc().
- * \internal
- * \param str string
- * \return Newly allocated duplicate string.
- */
-YASM_LIB_DECL
-/*@only@*/ char *yasm__xstrdup(const char *str);
-
-/** strndup() implementation using yasm_xmalloc().
- * \internal
- * \param str string
- * \param max maximum number of characters to copy
- * \return Newly allocated duplicate string.
- */
-YASM_LIB_DECL
-/*@only@*/ char *yasm__xstrndup(const char *str, size_t max);
-
-/** Error-checking memory allocation. A default implementation is provided
- * that calls yasm_fatal() on allocation errors.
- * A replacement should \em never return NULL.
- * \param size number of bytes to allocate
- * \return Allocated memory block.
- */
-YASM_LIB_DECL
-extern /*@only@*/ /*@out@*/ void * (*yasm_xmalloc) (size_t size);
-
-/** Error-checking memory allocation (with clear-to-0). A default
- * implementation is provided that calls yasm_fatal() on allocation errors.
- * A replacement should \em never return NULL.
- * \param size number of elements to allocate
- * \param elsize size (in bytes) of each element
- * \return Allocated and cleared memory block.
- */
-YASM_LIB_DECL
-extern /*@only@*/ void * (*yasm_xcalloc) (size_t nelem, size_t elsize);
-
-/** Error-checking memory reallocation. A default implementation is provided
- * that calls yasm_fatal() on allocation errors. A replacement should
- * \em never return NULL.
- * \param oldmem memory block to resize
- * \param elsize new size, in bytes
- * \return Re-allocated memory block.
- */
-YASM_LIB_DECL
-extern /*@only@*/ void * (*yasm_xrealloc)
- (/*@only@*/ /*@out@*/ /*@returned@*/ /*@null@*/ void *oldmem, size_t size)
- /*@modifies oldmem@*/;
-
-/** Error-checking memory deallocation. A default implementation is provided
- * that calls yasm_fatal() on allocation errors.
- * \param p memory block to free
- */
-YASM_LIB_DECL
-extern void (*yasm_xfree) (/*@only@*/ /*@out@*/ /*@null@*/ void *p)
- /*@modifies p@*/;
-
-#endif
+/**
+ * \file libyasm/coretype.h
+ * \brief YASM core types and utility functions.
+ *
+ * \license
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * \endlicense
+ */
+#ifndef YASM_CORETYPE_H
+#define YASM_CORETYPE_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/** Architecture instance (mostly opaque type). \see arch.h for details. */
+typedef struct yasm_arch yasm_arch;
+/** Preprocessor interface. \see preproc.h for details. */
+typedef struct yasm_preproc yasm_preproc;
+/** Parser instance (mostly opaque type). \see parser.h for details. */
+typedef struct yasm_parser yasm_parser;
+/** Object format interface. \see objfmt.h for details. */
+typedef struct yasm_objfmt yasm_objfmt;
+/** Debug format interface. \see dbgfmt.h for details. */
+typedef struct yasm_dbgfmt yasm_dbgfmt;
+/** List format interface. \see listfmt.h for details. */
+typedef struct yasm_listfmt yasm_listfmt;
+
+/** Object format module interface. \see objfmt.h for details. */
+typedef struct yasm_objfmt_module yasm_objfmt_module;
+/** Debug format module interface. \see dbgfmt.h for details. */
+typedef struct yasm_dbgfmt_module yasm_dbgfmt_module;
+
+/** Standard macro structure for modules that allows association of a set of
+ * standard macros with a parser/preprocessor combination.
+ * A NULL-terminated array of these structures is used in a number of module
+ * interfaces.
+ */
+typedef struct yasm_stdmac {
+ const char *parser; /**< Parser keyword */
+ const char *preproc; /**< Preprocessor keyword */
+
+ /** NULL-terminated array of standard macros. May be NULL if no standard
+ * macros should be added for this preprocessor.
+ */
+ const char **macros;
+} yasm_stdmac;
+
+/** YASM associated data callback structure. Many data structures can have
+ * arbitrary data associated with them.
+ */
+typedef struct yasm_assoc_data_callback {
+ /** Free memory allocated for associated data.
+ * \param data associated data
+ */
+ void (*destroy) (/*@only@*/ void *data);
+
+ /** Print a description of allocated data. For debugging purposes.
+ * \param data associated data
+ * \param f output file
+ * \param indent_level indentation level
+ */
+ void (*print) (void *data, FILE *f, int indent_level);
+} yasm_assoc_data_callback;
+
+/** Set of collected error/warnings (opaque type).
+ * \see errwarn.h for details.
+ */
+typedef struct yasm_errwarns yasm_errwarns;
+
+/** Bytecode. \see bytecode.h for details and related functions. */
+typedef struct yasm_bytecode yasm_bytecode;
+
+/** Object. \see section.h for details and related functions. */
+typedef struct yasm_object yasm_object;
+
+/** Section (opaque type). \see section.h for related functions. */
+typedef struct yasm_section yasm_section;
+
+/** Symbol table (opaque type). \see symrec.h for related functions. */
+typedef struct yasm_symtab yasm_symtab;
+
+/** Symbol record (opaque type). \see symrec.h for related functions. */
+typedef struct yasm_symrec yasm_symrec;
+
+/** Expression. \see expr.h for details and related functions. */
+typedef struct yasm_expr yasm_expr;
+/** Integer value (opaque type). \see intnum.h for related functions. */
+typedef struct yasm_intnum yasm_intnum;
+/** Floating point value (opaque type).
+ * \see floatnum.h for related functions.
+ */
+typedef struct yasm_floatnum yasm_floatnum;
+
+/** A value. May be absolute or relative. Outside the parser, yasm_expr
+ * should only be used for absolute exprs. Anything that could contain
+ * a relocatable value should use this structure instead.
+ * \see value.h for related functions.
+ */
+typedef struct yasm_value {
+ /** The absolute portion of the value. May contain *differences* between
+ * symrecs but not standalone symrecs. May be NULL if there is no
+ * absolute portion (e.g. the absolute portion is 0).
+ */
+ /*@null@*/ /*@only@*/ yasm_expr *abs;
+
+ /** The relative portion of the value. This is the portion that may
+ * need to generate a relocation. May be NULL if no relative portion.
+ */
+ /*@null@*/ /*@dependent@*/ yasm_symrec *rel;
+
+ /** What the relative portion is in reference to. NULL if the default. */
+ /*@null@*/ /*@dependent@*/ yasm_symrec *wrt;
+
+ /** If the segment of the relative portion should be used, not the
+ * relative portion itself. Boolean.
+ */
+ unsigned int seg_of : 1;
+
+ /** If the relative portion of the value should be shifted right
+ * (supported only by a few object formats). If just the absolute portion
+ * should be shifted, that must be in the abs expr, not here!
+ */
+ unsigned int rshift : 7;
+
+ /** Indicates the relative portion of the value should be relocated
+ * relative to the current assembly position rather than relative to the
+ * section start. "Current assembly position" here refers to the starting
+ * address of the bytecode containing this value. Boolean.
+ */
+ unsigned int curpos_rel : 1;
+
+ /** Indicates that curpos_rel was set due to IP-relative relocation;
+ * in some objfmt/arch combinations (e.g. win64/x86-amd64) this info
+ * is needed to generate special relocations.
+ */
+ unsigned int ip_rel : 1;
+
+ /** Indicates the value is a jump target address (rather than a simple
+ * data address). In some objfmt/arch combinations (e.g. macho/amd64)
+ * this info is needed to generate special relocations.
+ */
+ unsigned int jump_target : 1;
+
+ /** Indicates the relative portion of the value should be relocated
+ * relative to its own section start rather than relative to the
+ * section start of the bytecode containing this value. E.g. the value
+ * resulting from the relative portion should be the offset from its
+ * section start. Boolean.
+ */
+ unsigned int section_rel : 1;
+
+ /** Indicates overflow warnings have been disabled for this value. */
+ unsigned int no_warn : 1;
+
+ /** Sign of the value. Nonzero if the final value should be treated as
+ * signed, 0 if it should be treated as signed.
+ */
+ unsigned int sign : 1;
+
+ /** Size of the value, in bits. */
+ unsigned int size : 8;
+} yasm_value;
+
+/** Maximum value of #yasm_value.rshift */
+#define YASM_VALUE_RSHIFT_MAX 127
+
+/** Line number mapping repository (opaque type). \see linemap.h for related
+ * functions.
+ */
+typedef struct yasm_linemap yasm_linemap;
+
+/** Value/parameter pair (opaque type).
+ * \see valparam.h for related functions.
+ */
+typedef struct yasm_valparam yasm_valparam;
+/** List of value/parameters (opaque type).
+ * \see valparam.h for related functions.
+ */
+typedef struct yasm_valparamhead yasm_valparamhead;
+/** Directive list entry.
+ * \see valparam.h for details and related functions.
+ */
+typedef struct yasm_directive yasm_directive;
+
+/** An effective address.
+ * \see insn.h for related functions.
+ */
+typedef struct yasm_effaddr yasm_effaddr;
+
+/** An instruction.
+ * \see insn.h for related functions.
+ */
+typedef struct yasm_insn yasm_insn;
+
+/** Expression operators usable in #yasm_expr expressions. */
+typedef enum yasm_expr_op {
+ YASM_EXPR_IDENT, /**< No operation, just a value. */
+ YASM_EXPR_ADD, /**< Arithmetic addition (+). */
+ YASM_EXPR_SUB, /**< Arithmetic subtraction (-). */
+ YASM_EXPR_MUL, /**< Arithmetic multiplication (*). */
+ YASM_EXPR_DIV, /**< Arithmetic unsigned division. */
+ YASM_EXPR_SIGNDIV, /**< Arithmetic signed division. */
+ YASM_EXPR_MOD, /**< Arithmetic unsigned modulus. */
+ YASM_EXPR_SIGNMOD, /**< Arithmetic signed modulus. */
+ YASM_EXPR_NEG, /**< Arithmetic negation (-). */
+ YASM_EXPR_NOT, /**< Bitwise negation. */
+ 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. */
+ YASM_EXPR_LE, /**< Less than or equal to comparison. */
+ YASM_EXPR_GE, /**< Greater than or equal to comparison. */
+ YASM_EXPR_NE, /**< Not equal comparison. */
+ YASM_EXPR_NONNUM, /**< Start of non-numeric operations (not an op). */
+ YASM_EXPR_SEG, /**< SEG operator (gets segment portion of address). */
+ YASM_EXPR_WRT, /**< WRT operator (gets offset of address relative to
+ * some other segment). */
+ YASM_EXPR_SEGOFF /**< The ':' in segment:offset. */
+} yasm_expr_op;
+
+/** Convert yasm_value to its byte representation. Usually implemented by
+ * object formats to keep track of relocations and verify legal expressions.
+ * Must put the value into the least significant bits of the destination,
+ * unless shifted into more significant bits by the shift parameter. The
+ * destination bits must be cleared before being set.
+ * \param value value
+ * \param buf buffer for byte representation
+ * \param destsize destination size (in bytes)
+ * \param offset offset (in bytes) of the expr contents from the start
+ * of the bytecode (needed for relative)
+ * \param bc current bytecode (usually passed into higher-level
+ * calling function)
+ * \param warn enables standard warnings: zero for none;
+ * nonzero for overflow/underflow floating point warnings
+ * \param d objfmt-specific data (passed into higher-level calling
+ * function)
+ * \return Nonzero if an error occurred, 0 otherwise.
+ */
+typedef int (*yasm_output_value_func)
+ (yasm_value *value, /*@out@*/ unsigned char *buf, unsigned int destsize,
+ unsigned long offset, yasm_bytecode *bc, int warn, /*@null@*/ void *d);
+
+/** Convert a symbol reference to its byte representation. Usually implemented
+ * by object formats and debug formats to keep track of relocations generated
+ * by themselves.
+ * \param sym symbol
+ * \param bc current bytecode (usually passed into higher-level
+ * calling function)
+ * \param buf buffer for byte representation
+ * \param destsize destination size (in bytes)
+ * \param valsize size (in bits)
+ * \param warn enables standard warnings: zero for none;
+ * nonzero for overflow/underflow floating point warnings;
+ * negative for signed integer warnings,
+ * positive for unsigned integer warnings
+ * \param d objfmt-specific data (passed into higher-level calling
+ * function)
+ * \return Nonzero if an error occurred, 0 otherwise.
+ */
+typedef int (*yasm_output_reloc_func)
+ (yasm_symrec *sym, yasm_bytecode *bc, unsigned char *buf,
+ unsigned int destsize, unsigned int valsize, int warn, void *d);
+
+/** Sort an array using merge sort algorithm.
+ * \internal
+ * \param base base of array
+ * \param nmemb number of elements in array
+ * \param size size of each array element
+ * \param compar element comparison function
+ */
+YASM_LIB_DECL
+int yasm__mergesort(void *base, size_t nmemb, size_t size,
+ int (*compar)(const void *, const void *));
+
+/** Separate string by delimiters.
+ * \internal
+ * \param stringp string
+ * \param delim set of 1 or more delimiters
+ * \return First/next substring.
+ */
+YASM_LIB_DECL
+/*@null@*/ char *yasm__strsep(char **stringp, const char *delim);
+
+/** Compare two strings, ignoring case differences.
+ * \internal
+ * \param s1 string 1
+ * \param s2 string 2
+ * \return 0 if strings are equal, -1 if s1<s2, 1 if s1>s2.
+ */
+YASM_LIB_DECL
+int yasm__strcasecmp(const char *s1, const char *s2);
+
+/** Compare portion of two strings, ignoring case differences.
+ * \internal
+ * \param s1 string 1
+ * \param s2 string 2
+ * \param n maximum number of characters to compare
+ * \return 0 if strings are equal, -1 if s1<s2, 1 if s1>s2.
+ */
+YASM_LIB_DECL
+int yasm__strncasecmp(const char *s1, const char *s2, size_t n);
+
+/** strdup() implementation using yasm_xmalloc().
+ * \internal
+ * \param str string
+ * \return Newly allocated duplicate string.
+ */
+YASM_LIB_DECL
+/*@only@*/ char *yasm__xstrdup(const char *str);
+
+/** strndup() implementation using yasm_xmalloc().
+ * \internal
+ * \param str string
+ * \param max maximum number of characters to copy
+ * \return Newly allocated duplicate string.
+ */
+YASM_LIB_DECL
+/*@only@*/ char *yasm__xstrndup(const char *str, size_t max);
+
+/** Error-checking memory allocation. A default implementation is provided
+ * that calls yasm_fatal() on allocation errors.
+ * A replacement should \em never return NULL.
+ * \param size number of bytes to allocate
+ * \return Allocated memory block.
+ */
+YASM_LIB_DECL
+extern /*@only@*/ /*@out@*/ void * (*yasm_xmalloc) (size_t size);
+
+/** Error-checking memory allocation (with clear-to-0). A default
+ * implementation is provided that calls yasm_fatal() on allocation errors.
+ * A replacement should \em never return NULL.
+ * \param size number of elements to allocate
+ * \param elsize size (in bytes) of each element
+ * \return Allocated and cleared memory block.
+ */
+YASM_LIB_DECL
+extern /*@only@*/ void * (*yasm_xcalloc) (size_t nelem, size_t elsize);
+
+/** Error-checking memory reallocation. A default implementation is provided
+ * that calls yasm_fatal() on allocation errors. A replacement should
+ * \em never return NULL.
+ * \param oldmem memory block to resize
+ * \param elsize new size, in bytes
+ * \return Re-allocated memory block.
+ */
+YASM_LIB_DECL
+extern /*@only@*/ void * (*yasm_xrealloc)
+ (/*@only@*/ /*@out@*/ /*@returned@*/ /*@null@*/ void *oldmem, size_t size)
+ /*@modifies oldmem@*/;
+
+/** Error-checking memory deallocation. A default implementation is provided
+ * that calls yasm_fatal() on allocation errors.
+ * \param p memory block to free
+ */
+YASM_LIB_DECL
+extern void (*yasm_xfree) (/*@only@*/ /*@out@*/ /*@null@*/ void *p)
+ /*@modifies p@*/;
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/dbgfmt.h b/contrib/tools/yasm/libyasm/dbgfmt.h
index 2e5ea867ee..97e3470d20 100644
--- a/contrib/tools/yasm/libyasm/dbgfmt.h
+++ b/contrib/tools/yasm/libyasm/dbgfmt.h
@@ -1,74 +1,74 @@
-/**
- * \file libyasm/dbgfmt.h
- * \brief YASM debug format interface.
- *
- * \license
- * Copyright (C) 2002-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- * \endlicense
- */
-#ifndef YASM_DBGFMT_H
-#define YASM_DBGFMT_H
-
-#ifndef YASM_DOXYGEN
-/** Base #yasm_dbgfmt structure. Must be present as the first element in any
- * #yasm_dbgfmt implementation.
- */
-typedef struct yasm_dbgfmt_base {
- /** #yasm_dbgfmt_module implementation for this debug format. */
- const struct yasm_dbgfmt_module *module;
-} yasm_dbgfmt_base;
-#endif
-
-/** Debug format module interface. */
-struct yasm_dbgfmt_module {
- /** One-line description of the debug format. */
- const char *name;
-
- /** Keyword used to select debug format. */
- const char *keyword;
-
- /** NULL-terminated list of directives. NULL if none. */
- /*@null@*/ const yasm_directive *directives;
-
- /** Create debug format.
- * Module-level implementation of yasm_dbgfmt_create().
- * The filenames are provided solely for informational purposes.
- * \param object object
- * \return NULL if object format does not provide needed support.
- */
- /*@null@*/ /*@only@*/ yasm_dbgfmt * (*create) (yasm_object *object);
-
- /** Module-level implementation of yasm_dbgfmt_destroy().
- * Call yasm_dbgfmt_destroy() instead of calling this function.
- */
- void (*destroy) (/*@only@*/ yasm_dbgfmt *dbgfmt);
-
- /** Module-level implementation of yasm_dbgfmt_generate().
- * Call yasm_dbgfmt_generate() instead of calling this function.
- */
- void (*generate) (yasm_object *object, yasm_linemap *linemap,
- yasm_errwarns *errwarns);
+/**
+ * \file libyasm/dbgfmt.h
+ * \brief YASM debug format interface.
+ *
+ * \license
+ * Copyright (C) 2002-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * \endlicense
+ */
+#ifndef YASM_DBGFMT_H
+#define YASM_DBGFMT_H
+
+#ifndef YASM_DOXYGEN
+/** Base #yasm_dbgfmt structure. Must be present as the first element in any
+ * #yasm_dbgfmt implementation.
+ */
+typedef struct yasm_dbgfmt_base {
+ /** #yasm_dbgfmt_module implementation for this debug format. */
+ const struct yasm_dbgfmt_module *module;
+} yasm_dbgfmt_base;
+#endif
+
+/** Debug format module interface. */
+struct yasm_dbgfmt_module {
+ /** One-line description of the debug format. */
+ const char *name;
+
+ /** Keyword used to select debug format. */
+ const char *keyword;
+
+ /** NULL-terminated list of directives. NULL if none. */
+ /*@null@*/ const yasm_directive *directives;
+
+ /** Create debug format.
+ * Module-level implementation of yasm_dbgfmt_create().
+ * The filenames are provided solely for informational purposes.
+ * \param object object
+ * \return NULL if object format does not provide needed support.
+ */
+ /*@null@*/ /*@only@*/ yasm_dbgfmt * (*create) (yasm_object *object);
+
+ /** Module-level implementation of yasm_dbgfmt_destroy().
+ * Call yasm_dbgfmt_destroy() instead of calling this function.
+ */
+ void (*destroy) (/*@only@*/ yasm_dbgfmt *dbgfmt);
+
+ /** Module-level implementation of yasm_dbgfmt_generate().
+ * Call yasm_dbgfmt_generate() instead of calling this function.
+ */
+ void (*generate) (yasm_object *object, yasm_linemap *linemap,
+ yasm_errwarns *errwarns);
/**
* --replace params
@@ -78,54 +78,54 @@ struct yasm_dbgfmt_module {
* Number of elements in replace_map
*/
int replace_map_size;
-};
-
-/** Get the keyword used to select a debug format.
- * \param dbgfmt debug format
- * \return keyword
- */
-const char *yasm_dbgfmt_keyword(const yasm_dbgfmt *dbgfmt);
-
-/** Initialize debug output for use. Must call before any other debug
- * format functions. The filenames are provided solely for informational
- * purposes.
- * \param module debug format module
- * \param object object to generate debugging information for
- * \return NULL if object format does not provide needed support.
- */
-/*@null@*/ /*@only@*/ yasm_dbgfmt *yasm_dbgfmt_create
- (const yasm_dbgfmt_module *module, yasm_object *object);
-
-/** Cleans up any allocated debug format memory.
- * \param dbgfmt debug format
- */
-void yasm_dbgfmt_destroy(/*@only@*/ yasm_dbgfmt *dbgfmt);
-
-/** Generate debugging information bytecodes.
- * \param object object
- * \param linemap virtual/physical line mapping
- * \param errwarns error/warning set
- * \note Errors and warnings are stored into errwarns.
- */
-void yasm_dbgfmt_generate(yasm_object *object, yasm_linemap *linemap,
- yasm_errwarns *errwarns);
-
-#ifndef YASM_DOXYGEN
-
-/* Inline macro implementations for dbgfmt functions */
-
-#define yasm_dbgfmt_keyword(dbgfmt) \
- (((yasm_dbgfmt_base *)dbgfmt)->module->keyword)
-
-#define yasm_dbgfmt_create(module, object) \
- module->create(object)
-
-#define yasm_dbgfmt_destroy(dbgfmt) \
- ((yasm_dbgfmt_base *)dbgfmt)->module->destroy(dbgfmt)
-#define yasm_dbgfmt_generate(object, linemap, ews) \
- ((yasm_dbgfmt_base *)((object)->dbgfmt))->module->generate \
- (object, linemap, ews)
-
-#endif
-
-#endif
+};
+
+/** Get the keyword used to select a debug format.
+ * \param dbgfmt debug format
+ * \return keyword
+ */
+const char *yasm_dbgfmt_keyword(const yasm_dbgfmt *dbgfmt);
+
+/** Initialize debug output for use. Must call before any other debug
+ * format functions. The filenames are provided solely for informational
+ * purposes.
+ * \param module debug format module
+ * \param object object to generate debugging information for
+ * \return NULL if object format does not provide needed support.
+ */
+/*@null@*/ /*@only@*/ yasm_dbgfmt *yasm_dbgfmt_create
+ (const yasm_dbgfmt_module *module, yasm_object *object);
+
+/** Cleans up any allocated debug format memory.
+ * \param dbgfmt debug format
+ */
+void yasm_dbgfmt_destroy(/*@only@*/ yasm_dbgfmt *dbgfmt);
+
+/** Generate debugging information bytecodes.
+ * \param object object
+ * \param linemap virtual/physical line mapping
+ * \param errwarns error/warning set
+ * \note Errors and warnings are stored into errwarns.
+ */
+void yasm_dbgfmt_generate(yasm_object *object, yasm_linemap *linemap,
+ yasm_errwarns *errwarns);
+
+#ifndef YASM_DOXYGEN
+
+/* Inline macro implementations for dbgfmt functions */
+
+#define yasm_dbgfmt_keyword(dbgfmt) \
+ (((yasm_dbgfmt_base *)dbgfmt)->module->keyword)
+
+#define yasm_dbgfmt_create(module, object) \
+ module->create(object)
+
+#define yasm_dbgfmt_destroy(dbgfmt) \
+ ((yasm_dbgfmt_base *)dbgfmt)->module->destroy(dbgfmt)
+#define yasm_dbgfmt_generate(object, linemap, ews) \
+ ((yasm_dbgfmt_base *)((object)->dbgfmt))->module->generate \
+ (object, linemap, ews)
+
+#endif
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/errwarn.c b/contrib/tools/yasm/libyasm/errwarn.c
index f759cf8f71..4266253bbc 100644
--- a/contrib/tools/yasm/libyasm/errwarn.c
+++ b/contrib/tools/yasm/libyasm/errwarn.c
@@ -1,533 +1,533 @@
-/*
- * Error and warning reporting and related functions.
- *
- * Copyright (C) 2001-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#include "util.h"
-
-#include <ctype.h>
+/*
+ * Error and warning reporting and related functions.
+ *
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "util.h"
+
+#include <ctype.h>
#include <errno.h>
-#include <stdarg.h>
-
-#include "coretype.h"
-
-#include "linemap.h"
-#include "errwarn.h"
-
-
-#define MSG_MAXSIZE 1024
-
-#if !defined(HAVE_TOASCII) || defined(lint)
-# define toascii(c) ((c) & 0x7F)
-#endif
-
-/* Default handlers for replacable functions */
-static /*@exits@*/ void def_internal_error_
- (const char *file, unsigned int line, const char *message);
-static /*@exits@*/ void def_fatal(const char *message, va_list va);
-static const char *def_gettext_hook(const char *msgid);
-
-/* Storage for errwarn's "extern" functions */
-/*@exits@*/ void (*yasm_internal_error_)
- (const char *file, unsigned int line, const char *message)
- = def_internal_error_;
-/*@exits@*/ void (*yasm_fatal) (const char *message, va_list va) = def_fatal;
-const char * (*yasm_gettext_hook) (const char *msgid) = def_gettext_hook;
-
-/* Error indicator */
-/* yasm_eclass is not static so that yasm_error_occurred macro can access it */
-yasm_error_class yasm_eclass;
-static /*@only@*/ /*@null@*/ char *yasm_estr;
-static unsigned long yasm_exrefline;
-static /*@only@*/ /*@null@*/ char *yasm_exrefstr;
-
-/* Warning indicator */
-typedef struct warn {
- /*@reldef@*/ STAILQ_ENTRY(warn) link;
-
- yasm_warn_class wclass;
- /*@owned@*/ /*@null@*/ char *wstr;
-} warn;
-static STAILQ_HEAD(warn_head, warn) yasm_warns;
-
-/* Enabled warnings. See errwarn.h for a list. */
-static unsigned long warn_class_enabled;
-
-typedef struct errwarn_data {
- /*@reldef@*/ SLIST_ENTRY(errwarn_data) link;
-
- enum { WE_UNKNOWN, WE_ERROR, WE_WARNING, WE_PARSERERROR } type;
-
- unsigned long line;
- unsigned long xrefline;
- /*@owned@*/ char *msg;
- /*@owned@*/ char *xrefmsg;
-} errwarn_data;
-
-struct yasm_errwarns {
- /*@reldef@*/ SLIST_HEAD(errwarn_head, errwarn_data) errwarns;
-
- /* Total error count */
- unsigned int ecount;
-
- /* Total warning count */
- unsigned int wcount;
-
- /* Last inserted error/warning. Used to speed up insertions. */
- /*@null@*/ errwarn_data *previous_we;
-};
-
-/* Static buffer for use by conv_unprint(). */
-static char unprint[5];
-
-
-static const char *
-def_gettext_hook(const char *msgid)
-{
- return msgid;
-}
-
-void
-yasm_errwarn_initialize(void)
-{
- /* Default enabled warnings. See errwarn.h for a list. */
- warn_class_enabled =
- (1UL<<YASM_WARN_GENERAL) | (1UL<<YASM_WARN_UNREC_CHAR) |
- (1UL<<YASM_WARN_PREPROC) | (0UL<<YASM_WARN_ORPHAN_LABEL) |
- (1UL<<YASM_WARN_UNINIT_CONTENTS) | (0UL<<YASM_WARN_SIZE_OVERRIDE) |
- (1UL<<YASM_WARN_IMPLICIT_SIZE_OVERRIDE);
-
- yasm_eclass = YASM_ERROR_NONE;
- yasm_estr = NULL;
- yasm_exrefline = 0;
- yasm_exrefstr = NULL;
-
- STAILQ_INIT(&yasm_warns);
-}
-
-void
-yasm_errwarn_cleanup(void)
-{
- yasm_error_clear();
- yasm_warn_clear();
-}
-
-/* Convert a possibly unprintable character into a printable string, using
- * standard cat(1) convention for unprintable characters.
- */
-char *
-yasm__conv_unprint(int ch)
-{
- int pos = 0;
-
- if (((ch & ~0x7F) != 0) /*!isascii(ch)*/ && !isprint(ch)) {
- unprint[pos++] = 'M';
- unprint[pos++] = '-';
- ch &= toascii(ch);
- }
- if (iscntrl(ch)) {
- unprint[pos++] = '^';
- unprint[pos++] = (ch == '\177') ? '?' : ch | 0100;
- } else
- unprint[pos++] = ch;
- unprint[pos] = '\0';
-
- return unprint;
-}
-
-/* Report an internal error. Essentially a fatal error with trace info.
- * Exit immediately because it's essentially an assert() trap.
- */
-static void
-def_internal_error_(const char *file, unsigned int line, const char *message)
-{
- fprintf(stderr,
- yasm_gettext_hook(N_("INTERNAL ERROR at %s, line %u: %s\n")),
- file, line, yasm_gettext_hook(message));
-#ifdef HAVE_ABORT
- abort();
-#else
- exit(EXIT_FAILURE);
-#endif
-}
-
-/* Report a fatal error. These are unrecoverable (such as running out of
- * memory), so just exit immediately.
- */
-static void
-def_fatal(const char *fmt, va_list va)
-{
- fprintf(stderr, "%s: ", yasm_gettext_hook(N_("FATAL")));
- vfprintf(stderr, yasm_gettext_hook(fmt), va);
- fputc('\n', stderr);
- exit(EXIT_FAILURE);
-}
-
-/* Create an errwarn structure in the correct linked list location.
- * If replace_parser_error is nonzero, overwrites the last error if its
- * type is WE_PARSERERROR.
- */
-static errwarn_data *
-errwarn_data_new(yasm_errwarns *errwarns, unsigned long line,
- int replace_parser_error)
-{
- errwarn_data *first, *next, *ins_we, *we;
- enum { INS_NONE, INS_HEAD, INS_AFTER } action = INS_NONE;
-
- /* Find the entry with either line=line or the last one with line<line.
- * Start with the last entry added to speed the search.
- */
- ins_we = errwarns->previous_we;
- first = SLIST_FIRST(&errwarns->errwarns);
- if (!ins_we || !first)
- action = INS_HEAD;
- while (action == INS_NONE) {
- next = SLIST_NEXT(ins_we, link);
- if (line < ins_we->line) {
- if (ins_we == first)
- action = INS_HEAD;
- else
- ins_we = first;
- } else if (!next)
- action = INS_AFTER;
- else if (line >= ins_we->line && line < next->line)
- action = INS_AFTER;
- else
- ins_we = next;
- }
-
- if (replace_parser_error && ins_we && ins_we->type == WE_PARSERERROR) {
- /* overwrite last error */
- we = ins_we;
- } else {
- /* add a new error */
- we = yasm_xmalloc(sizeof(errwarn_data));
-
- we->type = WE_UNKNOWN;
- we->line = line;
- we->xrefline = 0;
- we->msg = NULL;
- we->xrefmsg = NULL;
-
- if (action == INS_HEAD)
- SLIST_INSERT_HEAD(&errwarns->errwarns, we, link);
- else if (action == INS_AFTER) {
- assert(ins_we != NULL);
- SLIST_INSERT_AFTER(ins_we, we, link);
- } else
- yasm_internal_error(N_("Unexpected errwarn insert action"));
- }
-
- /* Remember previous err/warn */
- errwarns->previous_we = we;
-
- return we;
-}
-
-void
-yasm_error_clear(void)
-{
- if (yasm_estr)
- yasm_xfree(yasm_estr);
- if (yasm_exrefstr)
- yasm_xfree(yasm_exrefstr);
- yasm_eclass = YASM_ERROR_NONE;
- yasm_estr = NULL;
- yasm_exrefline = 0;
- yasm_exrefstr = NULL;
-}
-
-int
-yasm_error_matches(yasm_error_class eclass)
-{
- if (yasm_eclass == YASM_ERROR_NONE)
- return eclass == YASM_ERROR_NONE;
- if (yasm_eclass == YASM_ERROR_GENERAL)
- return eclass == YASM_ERROR_GENERAL;
- return (yasm_eclass & eclass) == eclass;
-}
-
-void
-yasm_error_set_va(yasm_error_class eclass, const char *format, va_list va)
-{
- if (yasm_eclass != YASM_ERROR_NONE)
- return;
-
- yasm_eclass = eclass;
- yasm_estr = yasm_xmalloc(MSG_MAXSIZE+1);
-#ifdef HAVE_VSNPRINTF
- vsnprintf(yasm_estr, MSG_MAXSIZE, yasm_gettext_hook(format), va);
-#else
- vsprintf(yasm_estr, yasm_gettext_hook(format), va);
-#endif
-}
-
-void
-yasm_error_set(yasm_error_class eclass, const char *format, ...)
-{
- va_list va;
- va_start(va, format);
- yasm_error_set_va(eclass, format, va);
- va_end(va);
-}
-
-void
-yasm_error_set_xref_va(unsigned long xrefline, const char *format, va_list va)
-{
- if (yasm_eclass != YASM_ERROR_NONE)
- return;
-
- yasm_exrefline = xrefline;
-
- yasm_exrefstr = yasm_xmalloc(MSG_MAXSIZE+1);
-#ifdef HAVE_VSNPRINTF
- vsnprintf(yasm_exrefstr, MSG_MAXSIZE, yasm_gettext_hook(format), va);
-#else
- vsprintf(yasm_exrefstr, yasm_gettext_hook(format), va);
-#endif
-}
-
-void
-yasm_error_set_xref(unsigned long xrefline, const char *format, ...)
-{
- va_list va;
- va_start(va, format);
- yasm_error_set_xref_va(xrefline, format, va);
- va_end(va);
-}
-
-void
-yasm_error_fetch(yasm_error_class *eclass, char **str, unsigned long *xrefline,
- char **xrefstr)
-{
- *eclass = yasm_eclass;
- *str = yasm_estr;
- *xrefline = yasm_exrefline;
- *xrefstr = yasm_exrefstr;
- yasm_eclass = YASM_ERROR_NONE;
- yasm_estr = NULL;
- yasm_exrefline = 0;
- yasm_exrefstr = NULL;
-}
-
-void yasm_warn_clear(void)
-{
- /* Delete all error/warnings */
- while (!STAILQ_EMPTY(&yasm_warns)) {
- warn *w = STAILQ_FIRST(&yasm_warns);
-
- if (w->wstr)
- yasm_xfree(w->wstr);
-
- STAILQ_REMOVE_HEAD(&yasm_warns, link);
- yasm_xfree(w);
- }
-}
-
-yasm_warn_class
-yasm_warn_occurred(void)
-{
- if (STAILQ_EMPTY(&yasm_warns))
- return YASM_WARN_NONE;
- return STAILQ_FIRST(&yasm_warns)->wclass;
-}
-
-void
-yasm_warn_set_va(yasm_warn_class wclass, const char *format, va_list va)
-{
- warn *w;
-
- if (!(warn_class_enabled & (1UL<<wclass)))
- return; /* warning is part of disabled class */
-
- w = yasm_xmalloc(sizeof(warn));
- w->wclass = wclass;
- w->wstr = yasm_xmalloc(MSG_MAXSIZE+1);
-#ifdef HAVE_VSNPRINTF
- vsnprintf(w->wstr, MSG_MAXSIZE, yasm_gettext_hook(format), va);
-#else
- vsprintf(w->wstr, yasm_gettext_hook(format), va);
-#endif
- STAILQ_INSERT_TAIL(&yasm_warns, w, link);
-}
-
-void
-yasm_warn_set(yasm_warn_class wclass, const char *format, ...)
-{
- va_list va;
- va_start(va, format);
- yasm_warn_set_va(wclass, format, va);
- va_end(va);
-}
-
-void
-yasm_warn_fetch(yasm_warn_class *wclass, char **str)
-{
- warn *w = STAILQ_FIRST(&yasm_warns);
-
- if (!w) {
- *wclass = YASM_WARN_NONE;
- *str = NULL;
- return;
- }
-
- *wclass = w->wclass;
- *str = w->wstr;
-
- STAILQ_REMOVE_HEAD(&yasm_warns, link);
- yasm_xfree(w);
-}
-
-void
-yasm_warn_enable(yasm_warn_class num)
-{
- warn_class_enabled |= (1UL<<num);
-}
-
-void
-yasm_warn_disable(yasm_warn_class num)
-{
- warn_class_enabled &= ~(1UL<<num);
-}
-
-void
-yasm_warn_disable_all(void)
-{
- warn_class_enabled = 0;
-}
-
-yasm_errwarns *
-yasm_errwarns_create(void)
-{
- yasm_errwarns *errwarns = yasm_xmalloc(sizeof(yasm_errwarns));
- SLIST_INIT(&errwarns->errwarns);
- errwarns->ecount = 0;
- errwarns->wcount = 0;
- errwarns->previous_we = NULL;
- return errwarns;
-}
-
-void
-yasm_errwarns_destroy(yasm_errwarns *errwarns)
-{
- errwarn_data *we;
-
- /* Delete all error/warnings */
- while (!SLIST_EMPTY(&errwarns->errwarns)) {
- we = SLIST_FIRST(&errwarns->errwarns);
- if (we->msg)
- yasm_xfree(we->msg);
- if (we->xrefmsg)
- yasm_xfree(we->xrefmsg);
-
- SLIST_REMOVE_HEAD(&errwarns->errwarns, link);
- yasm_xfree(we);
- }
-
- yasm_xfree(errwarns);
-}
-
-void
-yasm_errwarn_propagate(yasm_errwarns *errwarns, unsigned long line)
-{
- if (yasm_eclass != YASM_ERROR_NONE) {
- errwarn_data *we = errwarn_data_new(errwarns, line, 1);
- yasm_error_class eclass;
-
- yasm_error_fetch(&eclass, &we->msg, &we->xrefline, &we->xrefmsg);
- if (eclass != YASM_ERROR_GENERAL
- && (eclass & YASM_ERROR_PARSE) == YASM_ERROR_PARSE)
- we->type = WE_PARSERERROR;
- else
- we->type = WE_ERROR;
- errwarns->ecount++;
- }
-
- while (!STAILQ_EMPTY(&yasm_warns)) {
- errwarn_data *we = errwarn_data_new(errwarns, line, 0);
- yasm_warn_class wclass;
-
- yasm_warn_fetch(&wclass, &we->msg);
- we->type = WE_WARNING;
- errwarns->wcount++;
- }
-}
-
-unsigned int
-yasm_errwarns_num_errors(yasm_errwarns *errwarns, int warning_as_error)
-{
- if (warning_as_error)
- return errwarns->ecount+errwarns->wcount;
- else
- return errwarns->ecount;
-}
-
-void
-yasm_errwarns_output_all(yasm_errwarns *errwarns, yasm_linemap *lm,
- int warning_as_error,
- yasm_print_error_func print_error,
- yasm_print_warning_func print_warning)
-{
- errwarn_data *we;
- const char *filename, *xref_filename;
- unsigned long line, xref_line;
-
- /* If we're treating warnings as errors, tell the user about it. */
- if (warning_as_error && warning_as_error != 2) {
- print_error("", 0,
- yasm_gettext_hook(N_("warnings being treated as errors")),
- NULL, 0, NULL);
- warning_as_error = 2;
- }
-
- /* Output error/warnings. */
- SLIST_FOREACH(we, &errwarns->errwarns, link) {
- /* Output error/warning */
- yasm_linemap_lookup(lm, we->line, &filename, &line);
- if (we->xrefline)
- yasm_linemap_lookup(lm, we->xrefline, &xref_filename, &xref_line);
- else {
- xref_filename = NULL;
- xref_line = 0;
- }
- if (we->type == WE_ERROR || we->type == WE_PARSERERROR)
- print_error(filename, line, we->msg, xref_filename, xref_line,
- we->xrefmsg);
- else
- print_warning(filename, line, we->msg);
- }
-}
-
-void
-yasm__fatal(const char *message, ...)
-{
- va_list va;
- va_start(va, message);
- yasm_fatal(message, va);
- /*@notreached@*/
- va_end(va);
-}
+#include <stdarg.h>
+
+#include "coretype.h"
+
+#include "linemap.h"
+#include "errwarn.h"
+
+
+#define MSG_MAXSIZE 1024
+
+#if !defined(HAVE_TOASCII) || defined(lint)
+# define toascii(c) ((c) & 0x7F)
+#endif
+
+/* Default handlers for replacable functions */
+static /*@exits@*/ void def_internal_error_
+ (const char *file, unsigned int line, const char *message);
+static /*@exits@*/ void def_fatal(const char *message, va_list va);
+static const char *def_gettext_hook(const char *msgid);
+
+/* Storage for errwarn's "extern" functions */
+/*@exits@*/ void (*yasm_internal_error_)
+ (const char *file, unsigned int line, const char *message)
+ = def_internal_error_;
+/*@exits@*/ void (*yasm_fatal) (const char *message, va_list va) = def_fatal;
+const char * (*yasm_gettext_hook) (const char *msgid) = def_gettext_hook;
+
+/* Error indicator */
+/* yasm_eclass is not static so that yasm_error_occurred macro can access it */
+yasm_error_class yasm_eclass;
+static /*@only@*/ /*@null@*/ char *yasm_estr;
+static unsigned long yasm_exrefline;
+static /*@only@*/ /*@null@*/ char *yasm_exrefstr;
+
+/* Warning indicator */
+typedef struct warn {
+ /*@reldef@*/ STAILQ_ENTRY(warn) link;
+
+ yasm_warn_class wclass;
+ /*@owned@*/ /*@null@*/ char *wstr;
+} warn;
+static STAILQ_HEAD(warn_head, warn) yasm_warns;
+
+/* Enabled warnings. See errwarn.h for a list. */
+static unsigned long warn_class_enabled;
+
+typedef struct errwarn_data {
+ /*@reldef@*/ SLIST_ENTRY(errwarn_data) link;
+
+ enum { WE_UNKNOWN, WE_ERROR, WE_WARNING, WE_PARSERERROR } type;
+
+ unsigned long line;
+ unsigned long xrefline;
+ /*@owned@*/ char *msg;
+ /*@owned@*/ char *xrefmsg;
+} errwarn_data;
+
+struct yasm_errwarns {
+ /*@reldef@*/ SLIST_HEAD(errwarn_head, errwarn_data) errwarns;
+
+ /* Total error count */
+ unsigned int ecount;
+
+ /* Total warning count */
+ unsigned int wcount;
+
+ /* Last inserted error/warning. Used to speed up insertions. */
+ /*@null@*/ errwarn_data *previous_we;
+};
+
+/* Static buffer for use by conv_unprint(). */
+static char unprint[5];
+
+
+static const char *
+def_gettext_hook(const char *msgid)
+{
+ return msgid;
+}
+
+void
+yasm_errwarn_initialize(void)
+{
+ /* Default enabled warnings. See errwarn.h for a list. */
+ warn_class_enabled =
+ (1UL<<YASM_WARN_GENERAL) | (1UL<<YASM_WARN_UNREC_CHAR) |
+ (1UL<<YASM_WARN_PREPROC) | (0UL<<YASM_WARN_ORPHAN_LABEL) |
+ (1UL<<YASM_WARN_UNINIT_CONTENTS) | (0UL<<YASM_WARN_SIZE_OVERRIDE) |
+ (1UL<<YASM_WARN_IMPLICIT_SIZE_OVERRIDE);
+
+ yasm_eclass = YASM_ERROR_NONE;
+ yasm_estr = NULL;
+ yasm_exrefline = 0;
+ yasm_exrefstr = NULL;
+
+ STAILQ_INIT(&yasm_warns);
+}
+
+void
+yasm_errwarn_cleanup(void)
+{
+ yasm_error_clear();
+ yasm_warn_clear();
+}
+
+/* Convert a possibly unprintable character into a printable string, using
+ * standard cat(1) convention for unprintable characters.
+ */
+char *
+yasm__conv_unprint(int ch)
+{
+ int pos = 0;
+
+ if (((ch & ~0x7F) != 0) /*!isascii(ch)*/ && !isprint(ch)) {
+ unprint[pos++] = 'M';
+ unprint[pos++] = '-';
+ ch &= toascii(ch);
+ }
+ if (iscntrl(ch)) {
+ unprint[pos++] = '^';
+ unprint[pos++] = (ch == '\177') ? '?' : ch | 0100;
+ } else
+ unprint[pos++] = ch;
+ unprint[pos] = '\0';
+
+ return unprint;
+}
+
+/* Report an internal error. Essentially a fatal error with trace info.
+ * Exit immediately because it's essentially an assert() trap.
+ */
+static void
+def_internal_error_(const char *file, unsigned int line, const char *message)
+{
+ fprintf(stderr,
+ yasm_gettext_hook(N_("INTERNAL ERROR at %s, line %u: %s\n")),
+ file, line, yasm_gettext_hook(message));
+#ifdef HAVE_ABORT
+ abort();
+#else
+ exit(EXIT_FAILURE);
+#endif
+}
+
+/* Report a fatal error. These are unrecoverable (such as running out of
+ * memory), so just exit immediately.
+ */
+static void
+def_fatal(const char *fmt, va_list va)
+{
+ fprintf(stderr, "%s: ", yasm_gettext_hook(N_("FATAL")));
+ vfprintf(stderr, yasm_gettext_hook(fmt), va);
+ fputc('\n', stderr);
+ exit(EXIT_FAILURE);
+}
+
+/* Create an errwarn structure in the correct linked list location.
+ * If replace_parser_error is nonzero, overwrites the last error if its
+ * type is WE_PARSERERROR.
+ */
+static errwarn_data *
+errwarn_data_new(yasm_errwarns *errwarns, unsigned long line,
+ int replace_parser_error)
+{
+ errwarn_data *first, *next, *ins_we, *we;
+ enum { INS_NONE, INS_HEAD, INS_AFTER } action = INS_NONE;
+
+ /* Find the entry with either line=line or the last one with line<line.
+ * Start with the last entry added to speed the search.
+ */
+ ins_we = errwarns->previous_we;
+ first = SLIST_FIRST(&errwarns->errwarns);
+ if (!ins_we || !first)
+ action = INS_HEAD;
+ while (action == INS_NONE) {
+ next = SLIST_NEXT(ins_we, link);
+ if (line < ins_we->line) {
+ if (ins_we == first)
+ action = INS_HEAD;
+ else
+ ins_we = first;
+ } else if (!next)
+ action = INS_AFTER;
+ else if (line >= ins_we->line && line < next->line)
+ action = INS_AFTER;
+ else
+ ins_we = next;
+ }
+
+ if (replace_parser_error && ins_we && ins_we->type == WE_PARSERERROR) {
+ /* overwrite last error */
+ we = ins_we;
+ } else {
+ /* add a new error */
+ we = yasm_xmalloc(sizeof(errwarn_data));
+
+ we->type = WE_UNKNOWN;
+ we->line = line;
+ we->xrefline = 0;
+ we->msg = NULL;
+ we->xrefmsg = NULL;
+
+ if (action == INS_HEAD)
+ SLIST_INSERT_HEAD(&errwarns->errwarns, we, link);
+ else if (action == INS_AFTER) {
+ assert(ins_we != NULL);
+ SLIST_INSERT_AFTER(ins_we, we, link);
+ } else
+ yasm_internal_error(N_("Unexpected errwarn insert action"));
+ }
+
+ /* Remember previous err/warn */
+ errwarns->previous_we = we;
+
+ return we;
+}
+
+void
+yasm_error_clear(void)
+{
+ if (yasm_estr)
+ yasm_xfree(yasm_estr);
+ if (yasm_exrefstr)
+ yasm_xfree(yasm_exrefstr);
+ yasm_eclass = YASM_ERROR_NONE;
+ yasm_estr = NULL;
+ yasm_exrefline = 0;
+ yasm_exrefstr = NULL;
+}
+
+int
+yasm_error_matches(yasm_error_class eclass)
+{
+ if (yasm_eclass == YASM_ERROR_NONE)
+ return eclass == YASM_ERROR_NONE;
+ if (yasm_eclass == YASM_ERROR_GENERAL)
+ return eclass == YASM_ERROR_GENERAL;
+ return (yasm_eclass & eclass) == eclass;
+}
+
+void
+yasm_error_set_va(yasm_error_class eclass, const char *format, va_list va)
+{
+ if (yasm_eclass != YASM_ERROR_NONE)
+ return;
+
+ yasm_eclass = eclass;
+ yasm_estr = yasm_xmalloc(MSG_MAXSIZE+1);
+#ifdef HAVE_VSNPRINTF
+ vsnprintf(yasm_estr, MSG_MAXSIZE, yasm_gettext_hook(format), va);
+#else
+ vsprintf(yasm_estr, yasm_gettext_hook(format), va);
+#endif
+}
+
+void
+yasm_error_set(yasm_error_class eclass, const char *format, ...)
+{
+ va_list va;
+ va_start(va, format);
+ yasm_error_set_va(eclass, format, va);
+ va_end(va);
+}
+
+void
+yasm_error_set_xref_va(unsigned long xrefline, const char *format, va_list va)
+{
+ if (yasm_eclass != YASM_ERROR_NONE)
+ return;
+
+ yasm_exrefline = xrefline;
+
+ yasm_exrefstr = yasm_xmalloc(MSG_MAXSIZE+1);
+#ifdef HAVE_VSNPRINTF
+ vsnprintf(yasm_exrefstr, MSG_MAXSIZE, yasm_gettext_hook(format), va);
+#else
+ vsprintf(yasm_exrefstr, yasm_gettext_hook(format), va);
+#endif
+}
+
+void
+yasm_error_set_xref(unsigned long xrefline, const char *format, ...)
+{
+ va_list va;
+ va_start(va, format);
+ yasm_error_set_xref_va(xrefline, format, va);
+ va_end(va);
+}
+
+void
+yasm_error_fetch(yasm_error_class *eclass, char **str, unsigned long *xrefline,
+ char **xrefstr)
+{
+ *eclass = yasm_eclass;
+ *str = yasm_estr;
+ *xrefline = yasm_exrefline;
+ *xrefstr = yasm_exrefstr;
+ yasm_eclass = YASM_ERROR_NONE;
+ yasm_estr = NULL;
+ yasm_exrefline = 0;
+ yasm_exrefstr = NULL;
+}
+
+void yasm_warn_clear(void)
+{
+ /* Delete all error/warnings */
+ while (!STAILQ_EMPTY(&yasm_warns)) {
+ warn *w = STAILQ_FIRST(&yasm_warns);
+
+ if (w->wstr)
+ yasm_xfree(w->wstr);
+
+ STAILQ_REMOVE_HEAD(&yasm_warns, link);
+ yasm_xfree(w);
+ }
+}
+
+yasm_warn_class
+yasm_warn_occurred(void)
+{
+ if (STAILQ_EMPTY(&yasm_warns))
+ return YASM_WARN_NONE;
+ return STAILQ_FIRST(&yasm_warns)->wclass;
+}
+
+void
+yasm_warn_set_va(yasm_warn_class wclass, const char *format, va_list va)
+{
+ warn *w;
+
+ if (!(warn_class_enabled & (1UL<<wclass)))
+ return; /* warning is part of disabled class */
+
+ w = yasm_xmalloc(sizeof(warn));
+ w->wclass = wclass;
+ w->wstr = yasm_xmalloc(MSG_MAXSIZE+1);
+#ifdef HAVE_VSNPRINTF
+ vsnprintf(w->wstr, MSG_MAXSIZE, yasm_gettext_hook(format), va);
+#else
+ vsprintf(w->wstr, yasm_gettext_hook(format), va);
+#endif
+ STAILQ_INSERT_TAIL(&yasm_warns, w, link);
+}
+
+void
+yasm_warn_set(yasm_warn_class wclass, const char *format, ...)
+{
+ va_list va;
+ va_start(va, format);
+ yasm_warn_set_va(wclass, format, va);
+ va_end(va);
+}
+
+void
+yasm_warn_fetch(yasm_warn_class *wclass, char **str)
+{
+ warn *w = STAILQ_FIRST(&yasm_warns);
+
+ if (!w) {
+ *wclass = YASM_WARN_NONE;
+ *str = NULL;
+ return;
+ }
+
+ *wclass = w->wclass;
+ *str = w->wstr;
+
+ STAILQ_REMOVE_HEAD(&yasm_warns, link);
+ yasm_xfree(w);
+}
+
+void
+yasm_warn_enable(yasm_warn_class num)
+{
+ warn_class_enabled |= (1UL<<num);
+}
+
+void
+yasm_warn_disable(yasm_warn_class num)
+{
+ warn_class_enabled &= ~(1UL<<num);
+}
+
+void
+yasm_warn_disable_all(void)
+{
+ warn_class_enabled = 0;
+}
+
+yasm_errwarns *
+yasm_errwarns_create(void)
+{
+ yasm_errwarns *errwarns = yasm_xmalloc(sizeof(yasm_errwarns));
+ SLIST_INIT(&errwarns->errwarns);
+ errwarns->ecount = 0;
+ errwarns->wcount = 0;
+ errwarns->previous_we = NULL;
+ return errwarns;
+}
+
+void
+yasm_errwarns_destroy(yasm_errwarns *errwarns)
+{
+ errwarn_data *we;
+
+ /* Delete all error/warnings */
+ while (!SLIST_EMPTY(&errwarns->errwarns)) {
+ we = SLIST_FIRST(&errwarns->errwarns);
+ if (we->msg)
+ yasm_xfree(we->msg);
+ if (we->xrefmsg)
+ yasm_xfree(we->xrefmsg);
+
+ SLIST_REMOVE_HEAD(&errwarns->errwarns, link);
+ yasm_xfree(we);
+ }
+
+ yasm_xfree(errwarns);
+}
+
+void
+yasm_errwarn_propagate(yasm_errwarns *errwarns, unsigned long line)
+{
+ if (yasm_eclass != YASM_ERROR_NONE) {
+ errwarn_data *we = errwarn_data_new(errwarns, line, 1);
+ yasm_error_class eclass;
+
+ yasm_error_fetch(&eclass, &we->msg, &we->xrefline, &we->xrefmsg);
+ if (eclass != YASM_ERROR_GENERAL
+ && (eclass & YASM_ERROR_PARSE) == YASM_ERROR_PARSE)
+ we->type = WE_PARSERERROR;
+ else
+ we->type = WE_ERROR;
+ errwarns->ecount++;
+ }
+
+ while (!STAILQ_EMPTY(&yasm_warns)) {
+ errwarn_data *we = errwarn_data_new(errwarns, line, 0);
+ yasm_warn_class wclass;
+
+ yasm_warn_fetch(&wclass, &we->msg);
+ we->type = WE_WARNING;
+ errwarns->wcount++;
+ }
+}
+
+unsigned int
+yasm_errwarns_num_errors(yasm_errwarns *errwarns, int warning_as_error)
+{
+ if (warning_as_error)
+ return errwarns->ecount+errwarns->wcount;
+ else
+ return errwarns->ecount;
+}
+
+void
+yasm_errwarns_output_all(yasm_errwarns *errwarns, yasm_linemap *lm,
+ int warning_as_error,
+ yasm_print_error_func print_error,
+ yasm_print_warning_func print_warning)
+{
+ errwarn_data *we;
+ const char *filename, *xref_filename;
+ unsigned long line, xref_line;
+
+ /* If we're treating warnings as errors, tell the user about it. */
+ if (warning_as_error && warning_as_error != 2) {
+ print_error("", 0,
+ yasm_gettext_hook(N_("warnings being treated as errors")),
+ NULL, 0, NULL);
+ warning_as_error = 2;
+ }
+
+ /* Output error/warnings. */
+ SLIST_FOREACH(we, &errwarns->errwarns, link) {
+ /* Output error/warning */
+ yasm_linemap_lookup(lm, we->line, &filename, &line);
+ if (we->xrefline)
+ yasm_linemap_lookup(lm, we->xrefline, &xref_filename, &xref_line);
+ else {
+ xref_filename = NULL;
+ xref_line = 0;
+ }
+ if (we->type == WE_ERROR || we->type == WE_PARSERERROR)
+ print_error(filename, line, we->msg, xref_filename, xref_line,
+ we->xrefmsg);
+ else
+ print_warning(filename, line, we->msg);
+ }
+}
+
+void
+yasm__fatal(const char *message, ...)
+{
+ va_list va;
+ va_start(va, message);
+ yasm_fatal(message, va);
+ /*@notreached@*/
+ va_end(va);
+}
void
yasm__fatal_missing_input_file(const char *message, const char *filename)
diff --git a/contrib/tools/yasm/libyasm/errwarn.h b/contrib/tools/yasm/libyasm/errwarn.h
index f8e4f10ec3..4333528ce8 100644
--- a/contrib/tools/yasm/libyasm/errwarn.h
+++ b/contrib/tools/yasm/libyasm/errwarn.h
@@ -1,351 +1,351 @@
-/**
- * \file libyasm/errwarn.h
- * \brief YASM error and warning reporting interface.
- *
- * \license
- * Copyright (C) 2001-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- * \endlicense
- */
-#ifndef YASM_ERRWARN_H
-#define YASM_ERRWARN_H
-
-#ifndef YASM_LIB_DECL
-#define YASM_LIB_DECL
-#endif
-
-/** Warning classes (that may be enabled/disabled). */
-typedef enum yasm_warn_class {
- YASM_WARN_NONE = 0, /**< No warning */
- YASM_WARN_GENERAL, /**< Non-specific warnings */
- YASM_WARN_UNREC_CHAR, /**< Unrecognized characters (while tokenizing) */
- YASM_WARN_PREPROC, /**< Preprocessor warnings */
- YASM_WARN_ORPHAN_LABEL, /**< Label alone on a line without a colon */
- YASM_WARN_UNINIT_CONTENTS, /**< Uninitialized space in code/data section */
- YASM_WARN_SIZE_OVERRIDE,/**< Double size override */
- YASM_WARN_IMPLICIT_SIZE_OVERRIDE /**< Implicit size override */
-} yasm_warn_class;
-
-/** Error classes. Bitmask-based to support limited subclassing. */
-typedef enum yasm_error_class {
- YASM_ERROR_NONE = 0x0000, /**< No error */
- YASM_ERROR_GENERAL = 0xFFFF, /**< Non-specific */
- YASM_ERROR_ARITHMETIC = 0x0001, /**< Arithmetic error (general) */
- YASM_ERROR_OVERFLOW = 0x8001, /**< Arithmetic overflow */
- YASM_ERROR_FLOATING_POINT = 0x4001, /**< Floating point error */
- YASM_ERROR_ZERO_DIVISION = 0x2001, /**< Divide-by-zero */
- YASM_ERROR_ASSERTION = 0x0002, /**< Assertion error */
- YASM_ERROR_VALUE = 0x0004, /**< Value inappropriate
- * (e.g. not in range) */
- YASM_ERROR_NOT_ABSOLUTE = 0x8004, /**< Absolute expression required */
- YASM_ERROR_TOO_COMPLEX = 0x4004, /**< Expression too complex */
- YASM_ERROR_NOT_CONSTANT = 0x2004, /**< Constant expression required */
- YASM_ERROR_IO = 0x0008, /**< I/O error */
- YASM_ERROR_NOT_IMPLEMENTED = 0x0010, /**< Not implemented error */
- YASM_ERROR_TYPE = 0x0020, /**< Type error */
- YASM_ERROR_SYNTAX = 0x0040, /**< Syntax error */
- YASM_ERROR_PARSE = 0x8040 /**< Parser error */
-} yasm_error_class;
-
-/** Initialize any internal data structures. */
-YASM_LIB_DECL
-void yasm_errwarn_initialize(void);
-
-/** Clean up any memory allocated by yasm_errwarn_initialize() or other
- * functions.
- */
-YASM_LIB_DECL
-void yasm_errwarn_cleanup(void);
-
-/** Reporting point of internal errors. These are usually due to sanity
- * check failures in the code.
- * \warning This function must NOT return to calling code; exit or longjmp
- * instead.
- * \param file source file (ala __FILE__)
- * \param line source line (ala __LINE__)
- * \param message internal error message
- */
-YASM_LIB_DECL
-extern /*@exits@*/ void (*yasm_internal_error_)
- (const char *file, unsigned int line, const char *message);
-
-/** Easily-callable version of yasm_internal_error_(). Automatically uses
- * __FILE__ and __LINE__ as the file and line.
- * \param message internal error message
- */
-#define yasm_internal_error(message) \
- yasm_internal_error_(__FILE__, __LINE__, message)
-
-/** Reporting point of fatal errors.
- * \warning This function must NOT return to calling code; exit or longjmp
- * instead.
- * \param message fatal error message
- * \param va va_list argument list for message
- */
-YASM_LIB_DECL
-extern /*@exits@*/ void (*yasm_fatal) (const char *message, va_list va);
-
-/** Reporting point of fatal errors, with variable arguments (internal only).
- * \warning This function calls #yasm_fatal, and thus does not return to the
- * calling code.
- * \param message fatal error message
- * \param ... argument list for message
- */
-YASM_LIB_DECL
-/*@exits@*/ void yasm__fatal(const char *message, ...);
-
+/**
+ * \file libyasm/errwarn.h
+ * \brief YASM error and warning reporting interface.
+ *
+ * \license
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * \endlicense
+ */
+#ifndef YASM_ERRWARN_H
+#define YASM_ERRWARN_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/** Warning classes (that may be enabled/disabled). */
+typedef enum yasm_warn_class {
+ YASM_WARN_NONE = 0, /**< No warning */
+ YASM_WARN_GENERAL, /**< Non-specific warnings */
+ YASM_WARN_UNREC_CHAR, /**< Unrecognized characters (while tokenizing) */
+ YASM_WARN_PREPROC, /**< Preprocessor warnings */
+ YASM_WARN_ORPHAN_LABEL, /**< Label alone on a line without a colon */
+ YASM_WARN_UNINIT_CONTENTS, /**< Uninitialized space in code/data section */
+ YASM_WARN_SIZE_OVERRIDE,/**< Double size override */
+ YASM_WARN_IMPLICIT_SIZE_OVERRIDE /**< Implicit size override */
+} yasm_warn_class;
+
+/** Error classes. Bitmask-based to support limited subclassing. */
+typedef enum yasm_error_class {
+ YASM_ERROR_NONE = 0x0000, /**< No error */
+ YASM_ERROR_GENERAL = 0xFFFF, /**< Non-specific */
+ YASM_ERROR_ARITHMETIC = 0x0001, /**< Arithmetic error (general) */
+ YASM_ERROR_OVERFLOW = 0x8001, /**< Arithmetic overflow */
+ YASM_ERROR_FLOATING_POINT = 0x4001, /**< Floating point error */
+ YASM_ERROR_ZERO_DIVISION = 0x2001, /**< Divide-by-zero */
+ YASM_ERROR_ASSERTION = 0x0002, /**< Assertion error */
+ YASM_ERROR_VALUE = 0x0004, /**< Value inappropriate
+ * (e.g. not in range) */
+ YASM_ERROR_NOT_ABSOLUTE = 0x8004, /**< Absolute expression required */
+ YASM_ERROR_TOO_COMPLEX = 0x4004, /**< Expression too complex */
+ YASM_ERROR_NOT_CONSTANT = 0x2004, /**< Constant expression required */
+ YASM_ERROR_IO = 0x0008, /**< I/O error */
+ YASM_ERROR_NOT_IMPLEMENTED = 0x0010, /**< Not implemented error */
+ YASM_ERROR_TYPE = 0x0020, /**< Type error */
+ YASM_ERROR_SYNTAX = 0x0040, /**< Syntax error */
+ YASM_ERROR_PARSE = 0x8040 /**< Parser error */
+} yasm_error_class;
+
+/** Initialize any internal data structures. */
+YASM_LIB_DECL
+void yasm_errwarn_initialize(void);
+
+/** Clean up any memory allocated by yasm_errwarn_initialize() or other
+ * functions.
+ */
+YASM_LIB_DECL
+void yasm_errwarn_cleanup(void);
+
+/** Reporting point of internal errors. These are usually due to sanity
+ * check failures in the code.
+ * \warning This function must NOT return to calling code; exit or longjmp
+ * instead.
+ * \param file source file (ala __FILE__)
+ * \param line source line (ala __LINE__)
+ * \param message internal error message
+ */
+YASM_LIB_DECL
+extern /*@exits@*/ void (*yasm_internal_error_)
+ (const char *file, unsigned int line, const char *message);
+
+/** Easily-callable version of yasm_internal_error_(). Automatically uses
+ * __FILE__ and __LINE__ as the file and line.
+ * \param message internal error message
+ */
+#define yasm_internal_error(message) \
+ yasm_internal_error_(__FILE__, __LINE__, message)
+
+/** Reporting point of fatal errors.
+ * \warning This function must NOT return to calling code; exit or longjmp
+ * instead.
+ * \param message fatal error message
+ * \param va va_list argument list for message
+ */
+YASM_LIB_DECL
+extern /*@exits@*/ void (*yasm_fatal) (const char *message, va_list va);
+
+/** Reporting point of fatal errors, with variable arguments (internal only).
+ * \warning This function calls #yasm_fatal, and thus does not return to the
+ * calling code.
+ * \param message fatal error message
+ * \param ... argument list for message
+ */
+YASM_LIB_DECL
+/*@exits@*/ void yasm__fatal(const char *message, ...);
+
YASM_LIB_DECL
/*@exits@*/ void yasm__fatal_missing_input_file(const char *message, const char *filename);
-/** Unconditionally clear the error indicator, freeing any associated data.
- * Has no effect if the error indicator is not set.
- */
-YASM_LIB_DECL
-void yasm_error_clear(void);
-
-/** Get the error indicator. YASM_ERROR_NONE is returned if no error has
- * been set. Note that as YASM_ERROR_NONE is 0, the return value can also
- * be treated as a boolean value.
- * \return Current error indicator.
- */
-yasm_error_class yasm_error_occurred(void);
-
-/** Check the error indicator against an error class. To check if any error
- * has been set, check against the YASM_ERROR_GENERAL class. This function
- * properly checks error subclasses.
- * \param eclass base error class to check against
- * \return Nonzero if error indicator is set and a subclass of eclass, 0
- * otherwise.
- */
-YASM_LIB_DECL
-int yasm_error_matches(yasm_error_class eclass);
-
-#ifndef YASM_DOXYGEN
-YASM_LIB_DECL
-extern yasm_error_class yasm_eclass;
-#define yasm_error_occurred() yasm_eclass
-#endif
-
-/** Set the error indicator (va_list version). Has no effect if the error
- * indicator is already set.
- * \param eclass error class
- * \param format printf format string
- * \param va argument list for format
- */
-YASM_LIB_DECL
-void yasm_error_set_va(yasm_error_class eclass, const char *format, va_list va);
-
-/** Set the error indicator. Has no effect if the error indicator is already
- * set.
- * \param eclass error class
- * \param format printf format string
- * \param ... argument list for format
- */
-YASM_LIB_DECL
-void yasm_error_set(yasm_error_class eclass, const char *format, ...)
- /*@printflike@*/;
-
-/** Set a cross-reference for a new error (va_list version). Has no effect
- * if the error indicator is already set (e.g. with yasm_error_set()). This
- * function must be called prior to its corresponding yasm_error_set() call.
- * \param xrefline virtual line to cross-reference to (should not be 0)
- * \param format printf format string
- * \param va argument list for format
- */
-YASM_LIB_DECL
-void yasm_error_set_xref_va(unsigned long xrefline, const char *format,
- va_list va);
-
-/** Set a cross-reference for a new error. Has no effect if the error
- * indicator is already set (e.g. with yasm_error_set()). This function
- * must be called prior to its corresponding yasm_error_set() call.
- * \param xrefline virtual line to cross-reference to (should not be 0)
- * \param format printf format string
- * \param ... argument list for format
- */
-YASM_LIB_DECL
-void yasm_error_set_xref(unsigned long xrefline, const char *format, ...)
- /*@printflike@*/;
-
-/** Fetch the error indicator and all associated data. If the error
- * indicator is set, the output pointers are set to the current error
- * indicator values, and the error indicator is cleared.
- * The code using this function is then responsible for yasm_xfree()'ing
- * str and xrefstr (if non-NULL). If the error indicator is not set,
- * all output values are set to 0 (including eclass, which is set to
- * YASM_ERROR_NONE).
- * \param eclass error class (output)
- * \param str error message
- * \param xrefline virtual line used for cross-referencing (0 if no xref)
- * \param xrefstr cross-reference error message (NULL if no xref)
- */
-YASM_LIB_DECL
-void yasm_error_fetch(/*@out@*/ yasm_error_class *eclass,
- /*@out@*/ /*@only@*/ /*@null@*/ char **str,
- /*@out@*/ unsigned long *xrefline,
- /*@out@*/ /*@only@*/ /*@null@*/ char **xrefstr);
-
-/** Unconditionally clear all warning indicators, freeing any associated data.
- * Has no effect if no warning indicators have been set.
- */
-YASM_LIB_DECL
-void yasm_warn_clear(void);
-
-/** Get the first warning indicator. YASM_WARN_NONE is returned if no warning
- * has been set. Note that as YASM_WARN_NONE is 0, the return value can also
- * be treated as a boolean value.
- * \return First warning indicator.
- */
-YASM_LIB_DECL
-yasm_warn_class yasm_warn_occurred(void);
-
-/** Add a warning indicator (va_list version).
- * \param wclass warning class
- * \param format printf format string
- * \param va argument list for format
- */
-YASM_LIB_DECL
-void yasm_warn_set_va(yasm_warn_class wclass, const char *format, va_list va);
-
-/** Add a warning indicator.
- * \param wclass warning class
- * \param format printf format string
- * \param ... argument list for format
- */
-YASM_LIB_DECL
-void yasm_warn_set(yasm_warn_class wclass, const char *format, ...)
- /*@printflike@*/;
-
-/** Fetch the first warning indicator and all associated data. If there
- * is at least one warning indicator, the output pointers are set to the
- * first warning indicator values, and first warning indicator is removed.
- * The code using this function is then responsible for yasm_xfree()'ing
- * str and xrefstr (if non-NULL). If there is no warning indicator set,
- * all output values are set to 0 (including wclass, which is set to
- * YASM_WARN_NONE).
- * \param wclass warning class (output)
- * \param str warning message
- */
-YASM_LIB_DECL
-void yasm_warn_fetch(/*@out@*/ yasm_warn_class *wclass,
- /*@out@*/ /*@only@*/ char **str);
-
-/** Enable a class of warnings.
- * \param wclass warning class
- */
-YASM_LIB_DECL
-void yasm_warn_enable(yasm_warn_class wclass);
-
-/** Disable a class of warnings.
- * \param wclass warning class
- */
-YASM_LIB_DECL
-void yasm_warn_disable(yasm_warn_class wclass);
-
-/** Disable all classes of warnings. */
-YASM_LIB_DECL
-void yasm_warn_disable_all(void);
-
-/** Create an error/warning set for collection of multiple error/warnings.
- * \return Newly allocated set.
- */
-YASM_LIB_DECL
-/*@only@*/ yasm_errwarns *yasm_errwarns_create(void);
-
-/** Destroy an error/warning set.
- * \param errwarns error/warning set
- */
-YASM_LIB_DECL
-void yasm_errwarns_destroy(/*@only@*/ yasm_errwarns *errwarns);
-
-/** Propagate error indicator and warning indicator(s) to an error/warning set.
- * Has no effect if the error indicator and warning indicator are not set.
- * Does not print immediately; yasm_errwarn_output_all() outputs
- * accumulated errors and warnings.
- * Generally multiple errors on the same line will be reported, but errors
- * of class YASM_ERROR_PARSE will get overwritten by any other class on the
- * same line.
- * \param errwarns error/warning set
- * \param line virtual line
- */
-YASM_LIB_DECL
-void yasm_errwarn_propagate(yasm_errwarns *errwarns, unsigned long line);
-
-/** Get total number of errors logged.
- * \param errwarns error/warning set
- * \param warning_as_error if nonzero, warnings are treated as errors.
- * \return Number of errors.
- */
-YASM_LIB_DECL
-unsigned int yasm_errwarns_num_errors(yasm_errwarns *errwarns,
- int warning_as_error);
-
-/** Print out an error.
- * \param fn filename of source file
- * \param line line number
- * \param msg error message
- * \param xref_fn cross-referenced source filename
- * \param xref_line cross-referenced line number
- * \param xref_msg cross-referenced error message
- */
-typedef void (*yasm_print_error_func)
- (const char *fn, unsigned long line, const char *msg,
- /*@null@*/ const char *xref_fn, unsigned long xref_line,
- /*@null@*/ const char *xref_msg);
-
-/** Print out a warning.
- * \param fn filename of source file
- * \param line line number
- * \param msg warning message
- */
-typedef void (*yasm_print_warning_func)
- (const char *fn, unsigned long line, const char *msg);
-
-/** Outputs error/warning set in sorted order (sorted by virtual line number).
- * \param errwarns error/warning set
- * \param lm line map (to convert virtual lines into filename/line pairs)
- * \param warning_as_error if nonzero, treat warnings as errors.
- * \param print_error function called to print out errors
- * \param print_warning function called to print out warnings
- */
-YASM_LIB_DECL
-void yasm_errwarns_output_all
- (yasm_errwarns *errwarns, yasm_linemap *lm, int warning_as_error,
- yasm_print_error_func print_error, yasm_print_warning_func print_warning);
-
-/** Convert a possibly unprintable character into a printable string.
- * \internal
- * \param ch possibly unprintable character
- * \return Printable string representation (static buffer).
- */
-YASM_LIB_DECL
-char *yasm__conv_unprint(int ch);
-
-/** Hook for library users to map to gettext() if GNU gettext is being used.
- * \param msgid message catalog identifier
- * \return Translated message.
- */
-YASM_LIB_DECL
-extern const char * (*yasm_gettext_hook) (const char *msgid);
-
-#endif
+/** Unconditionally clear the error indicator, freeing any associated data.
+ * Has no effect if the error indicator is not set.
+ */
+YASM_LIB_DECL
+void yasm_error_clear(void);
+
+/** Get the error indicator. YASM_ERROR_NONE is returned if no error has
+ * been set. Note that as YASM_ERROR_NONE is 0, the return value can also
+ * be treated as a boolean value.
+ * \return Current error indicator.
+ */
+yasm_error_class yasm_error_occurred(void);
+
+/** Check the error indicator against an error class. To check if any error
+ * has been set, check against the YASM_ERROR_GENERAL class. This function
+ * properly checks error subclasses.
+ * \param eclass base error class to check against
+ * \return Nonzero if error indicator is set and a subclass of eclass, 0
+ * otherwise.
+ */
+YASM_LIB_DECL
+int yasm_error_matches(yasm_error_class eclass);
+
+#ifndef YASM_DOXYGEN
+YASM_LIB_DECL
+extern yasm_error_class yasm_eclass;
+#define yasm_error_occurred() yasm_eclass
+#endif
+
+/** Set the error indicator (va_list version). Has no effect if the error
+ * indicator is already set.
+ * \param eclass error class
+ * \param format printf format string
+ * \param va argument list for format
+ */
+YASM_LIB_DECL
+void yasm_error_set_va(yasm_error_class eclass, const char *format, va_list va);
+
+/** Set the error indicator. Has no effect if the error indicator is already
+ * set.
+ * \param eclass error class
+ * \param format printf format string
+ * \param ... argument list for format
+ */
+YASM_LIB_DECL
+void yasm_error_set(yasm_error_class eclass, const char *format, ...)
+ /*@printflike@*/;
+
+/** Set a cross-reference for a new error (va_list version). Has no effect
+ * if the error indicator is already set (e.g. with yasm_error_set()). This
+ * function must be called prior to its corresponding yasm_error_set() call.
+ * \param xrefline virtual line to cross-reference to (should not be 0)
+ * \param format printf format string
+ * \param va argument list for format
+ */
+YASM_LIB_DECL
+void yasm_error_set_xref_va(unsigned long xrefline, const char *format,
+ va_list va);
+
+/** Set a cross-reference for a new error. Has no effect if the error
+ * indicator is already set (e.g. with yasm_error_set()). This function
+ * must be called prior to its corresponding yasm_error_set() call.
+ * \param xrefline virtual line to cross-reference to (should not be 0)
+ * \param format printf format string
+ * \param ... argument list for format
+ */
+YASM_LIB_DECL
+void yasm_error_set_xref(unsigned long xrefline, const char *format, ...)
+ /*@printflike@*/;
+
+/** Fetch the error indicator and all associated data. If the error
+ * indicator is set, the output pointers are set to the current error
+ * indicator values, and the error indicator is cleared.
+ * The code using this function is then responsible for yasm_xfree()'ing
+ * str and xrefstr (if non-NULL). If the error indicator is not set,
+ * all output values are set to 0 (including eclass, which is set to
+ * YASM_ERROR_NONE).
+ * \param eclass error class (output)
+ * \param str error message
+ * \param xrefline virtual line used for cross-referencing (0 if no xref)
+ * \param xrefstr cross-reference error message (NULL if no xref)
+ */
+YASM_LIB_DECL
+void yasm_error_fetch(/*@out@*/ yasm_error_class *eclass,
+ /*@out@*/ /*@only@*/ /*@null@*/ char **str,
+ /*@out@*/ unsigned long *xrefline,
+ /*@out@*/ /*@only@*/ /*@null@*/ char **xrefstr);
+
+/** Unconditionally clear all warning indicators, freeing any associated data.
+ * Has no effect if no warning indicators have been set.
+ */
+YASM_LIB_DECL
+void yasm_warn_clear(void);
+
+/** Get the first warning indicator. YASM_WARN_NONE is returned if no warning
+ * has been set. Note that as YASM_WARN_NONE is 0, the return value can also
+ * be treated as a boolean value.
+ * \return First warning indicator.
+ */
+YASM_LIB_DECL
+yasm_warn_class yasm_warn_occurred(void);
+
+/** Add a warning indicator (va_list version).
+ * \param wclass warning class
+ * \param format printf format string
+ * \param va argument list for format
+ */
+YASM_LIB_DECL
+void yasm_warn_set_va(yasm_warn_class wclass, const char *format, va_list va);
+
+/** Add a warning indicator.
+ * \param wclass warning class
+ * \param format printf format string
+ * \param ... argument list for format
+ */
+YASM_LIB_DECL
+void yasm_warn_set(yasm_warn_class wclass, const char *format, ...)
+ /*@printflike@*/;
+
+/** Fetch the first warning indicator and all associated data. If there
+ * is at least one warning indicator, the output pointers are set to the
+ * first warning indicator values, and first warning indicator is removed.
+ * The code using this function is then responsible for yasm_xfree()'ing
+ * str and xrefstr (if non-NULL). If there is no warning indicator set,
+ * all output values are set to 0 (including wclass, which is set to
+ * YASM_WARN_NONE).
+ * \param wclass warning class (output)
+ * \param str warning message
+ */
+YASM_LIB_DECL
+void yasm_warn_fetch(/*@out@*/ yasm_warn_class *wclass,
+ /*@out@*/ /*@only@*/ char **str);
+
+/** Enable a class of warnings.
+ * \param wclass warning class
+ */
+YASM_LIB_DECL
+void yasm_warn_enable(yasm_warn_class wclass);
+
+/** Disable a class of warnings.
+ * \param wclass warning class
+ */
+YASM_LIB_DECL
+void yasm_warn_disable(yasm_warn_class wclass);
+
+/** Disable all classes of warnings. */
+YASM_LIB_DECL
+void yasm_warn_disable_all(void);
+
+/** Create an error/warning set for collection of multiple error/warnings.
+ * \return Newly allocated set.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_errwarns *yasm_errwarns_create(void);
+
+/** Destroy an error/warning set.
+ * \param errwarns error/warning set
+ */
+YASM_LIB_DECL
+void yasm_errwarns_destroy(/*@only@*/ yasm_errwarns *errwarns);
+
+/** Propagate error indicator and warning indicator(s) to an error/warning set.
+ * Has no effect if the error indicator and warning indicator are not set.
+ * Does not print immediately; yasm_errwarn_output_all() outputs
+ * accumulated errors and warnings.
+ * Generally multiple errors on the same line will be reported, but errors
+ * of class YASM_ERROR_PARSE will get overwritten by any other class on the
+ * same line.
+ * \param errwarns error/warning set
+ * \param line virtual line
+ */
+YASM_LIB_DECL
+void yasm_errwarn_propagate(yasm_errwarns *errwarns, unsigned long line);
+
+/** Get total number of errors logged.
+ * \param errwarns error/warning set
+ * \param warning_as_error if nonzero, warnings are treated as errors.
+ * \return Number of errors.
+ */
+YASM_LIB_DECL
+unsigned int yasm_errwarns_num_errors(yasm_errwarns *errwarns,
+ int warning_as_error);
+
+/** Print out an error.
+ * \param fn filename of source file
+ * \param line line number
+ * \param msg error message
+ * \param xref_fn cross-referenced source filename
+ * \param xref_line cross-referenced line number
+ * \param xref_msg cross-referenced error message
+ */
+typedef void (*yasm_print_error_func)
+ (const char *fn, unsigned long line, const char *msg,
+ /*@null@*/ const char *xref_fn, unsigned long xref_line,
+ /*@null@*/ const char *xref_msg);
+
+/** Print out a warning.
+ * \param fn filename of source file
+ * \param line line number
+ * \param msg warning message
+ */
+typedef void (*yasm_print_warning_func)
+ (const char *fn, unsigned long line, const char *msg);
+
+/** Outputs error/warning set in sorted order (sorted by virtual line number).
+ * \param errwarns error/warning set
+ * \param lm line map (to convert virtual lines into filename/line pairs)
+ * \param warning_as_error if nonzero, treat warnings as errors.
+ * \param print_error function called to print out errors
+ * \param print_warning function called to print out warnings
+ */
+YASM_LIB_DECL
+void yasm_errwarns_output_all
+ (yasm_errwarns *errwarns, yasm_linemap *lm, int warning_as_error,
+ yasm_print_error_func print_error, yasm_print_warning_func print_warning);
+
+/** Convert a possibly unprintable character into a printable string.
+ * \internal
+ * \param ch possibly unprintable character
+ * \return Printable string representation (static buffer).
+ */
+YASM_LIB_DECL
+char *yasm__conv_unprint(int ch);
+
+/** Hook for library users to map to gettext() if GNU gettext is being used.
+ * \param msgid message catalog identifier
+ * \return Translated message.
+ */
+YASM_LIB_DECL
+extern const char * (*yasm_gettext_hook) (const char *msgid);
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/expr.c b/contrib/tools/yasm/libyasm/expr.c
index c2c868ede2..4c9958449d 100644
--- a/contrib/tools/yasm/libyasm/expr.c
+++ b/contrib/tools/yasm/libyasm/expr.c
@@ -1,1516 +1,1516 @@
-/*
- * Expression handling
- *
- * Copyright (C) 2001-2007 Michael Urman, Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#include "util.h"
-
-#include "libyasm-stdint.h"
-#include "coretype.h"
-#include "bitvect.h"
-
-#include "errwarn.h"
-#include "intnum.h"
-#include "floatnum.h"
-#include "expr.h"
-#include "symrec.h"
-
-#include "bytecode.h"
-#include "section.h"
-
-#include "arch.h"
-
-
-static /*@only@*/ yasm_expr *expr_level_op
- (/*@returned@*/ /*@only@*/ yasm_expr *e, int fold_const,
- int simplify_ident, int simplify_reg_mul);
-static int expr_traverse_nodes_post(/*@null@*/ yasm_expr *e,
- /*@null@*/ void *d,
- int (*func) (/*@null@*/ yasm_expr *e,
- /*@null@*/ void *d));
-static void expr_delete_term(yasm_expr__item *term, int recurse);
-
-/* Bitmap of used items. We should really never need more than 2 at a time,
- * so 31 is pretty much overkill.
- */
-static unsigned long itempool_used = 0;
-static yasm_expr__item itempool[31];
-
-/* allocate a new expression node, with children as defined.
- * If it's a unary operator, put the element in left and set right=NULL. */
-/*@-compmempass@*/
-yasm_expr *
-yasm_expr_create(yasm_expr_op op, yasm_expr__item *left,
- yasm_expr__item *right, unsigned long line)
-{
- yasm_expr *ptr, *sube;
- unsigned long z;
- ptr = yasm_xmalloc(sizeof(yasm_expr));
-
- ptr->op = op;
- ptr->numterms = 0;
- ptr->terms[0].type = YASM_EXPR_NONE;
- ptr->terms[1].type = YASM_EXPR_NONE;
- if (left) {
- ptr->terms[0] = *left; /* structure copy */
- z = (unsigned long)(left-itempool);
- if (z>=31)
- yasm_internal_error(N_("could not find expritem in pool"));
- itempool_used &= ~(1<<z);
- ptr->numterms++;
-
- /* Search downward until we find something *other* than an
- * IDENT, then bring it up to the current level.
- */
- while (ptr->terms[0].type == YASM_EXPR_EXPR &&
- ptr->terms[0].data.expn->op == YASM_EXPR_IDENT) {
- sube = ptr->terms[0].data.expn;
- ptr->terms[0] = sube->terms[0]; /* structure copy */
- /*@-usereleased@*/
- yasm_xfree(sube);
- /*@=usereleased@*/
- }
- } else {
- yasm_internal_error(N_("Right side of expression must exist"));
- }
-
- if (right) {
- ptr->terms[1] = *right; /* structure copy */
- z = (unsigned long)(right-itempool);
- if (z>=31)
- yasm_internal_error(N_("could not find expritem in pool"));
- itempool_used &= ~(1<<z);
- ptr->numterms++;
-
- /* Search downward until we find something *other* than an
- * IDENT, then bring it up to the current level.
- */
- while (ptr->terms[1].type == YASM_EXPR_EXPR &&
- ptr->terms[1].data.expn->op == YASM_EXPR_IDENT) {
- sube = ptr->terms[1].data.expn;
- ptr->terms[1] = sube->terms[0]; /* structure copy */
- /*@-usereleased@*/
- yasm_xfree(sube);
- /*@=usereleased@*/
- }
- }
-
- ptr->line = line;
-
- return expr_level_op(ptr, 1, 1, 0);
-}
-/*@=compmempass@*/
-
-/* helpers */
-static yasm_expr__item *
-expr_get_item(void)
-{
- int z = 0;
- unsigned long v = itempool_used & 0x7fffffff;
-
- while (v & 1) {
- v >>= 1;
- z++;
- }
- if (z>=31)
- yasm_internal_error(N_("too many expritems"));
- itempool_used |= 1<<z;
- return &itempool[z];
-}
-
-yasm_expr__item *
-yasm_expr_precbc(yasm_bytecode *precbc)
-{
- yasm_expr__item *e = expr_get_item();
- e->type = YASM_EXPR_PRECBC;
- e->data.precbc = precbc;
- return e;
-}
-
-yasm_expr__item *
-yasm_expr_sym(yasm_symrec *s)
-{
- yasm_expr__item *e = expr_get_item();
- e->type = YASM_EXPR_SYM;
- e->data.sym = s;
- return e;
-}
-
-yasm_expr__item *
-yasm_expr_expr(yasm_expr *x)
-{
- yasm_expr__item *e = expr_get_item();
- e->type = YASM_EXPR_EXPR;
- e->data.expn = x;
- return e;
-}
-
-yasm_expr__item *
-yasm_expr_int(yasm_intnum *i)
-{
- yasm_expr__item *e = expr_get_item();
- e->type = YASM_EXPR_INT;
- e->data.intn = i;
- return e;
-}
-
-yasm_expr__item *
-yasm_expr_float(yasm_floatnum *f)
-{
- yasm_expr__item *e = expr_get_item();
- e->type = YASM_EXPR_FLOAT;
- e->data.flt = f;
- return e;
-}
-
-yasm_expr__item *
-yasm_expr_reg(uintptr_t reg)
-{
- yasm_expr__item *e = expr_get_item();
- e->type = YASM_EXPR_REG;
- e->data.reg = reg;
- return e;
-}
-
-/* Transforms instances of symrec-symrec [symrec+(-1*symrec)] into single
- * expritems if possible. Uses a simple n^2 algorithm because n is usually
- * quite small. Also works for precbc-precbc (or symrec-precbc,
- * precbc-symrec).
- */
-static /*@only@*/ yasm_expr *
-expr_xform_bc_dist_base(/*@returned@*/ /*@only@*/ yasm_expr *e,
- /*@null@*/ void *cbd,
- int (*callback) (yasm_expr__item *ei,
- yasm_bytecode *precbc,
- yasm_bytecode *precbc2,
- void *cbd))
-{
- int i;
- /*@dependent@*/ yasm_section *sect;
- /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc;
- int numterms;
-
- /* Handle symrec-symrec in ADD exprs by looking for (-1*symrec) and
- * symrec term pairs (where both symrecs are in the same segment).
- */
- if (e->op != YASM_EXPR_ADD)
- return e;
-
- for (i=0; i<e->numterms; i++) {
- int j;
- yasm_expr *sube;
- yasm_intnum *intn;
- yasm_symrec *sym = NULL;
- /*@dependent@*/ yasm_section *sect2;
- /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc2;
-
- /* First look for an (-1*symrec) term */
- if (e->terms[i].type != YASM_EXPR_EXPR)
- continue;
- sube = e->terms[i].data.expn;
- if (sube->op != YASM_EXPR_MUL || sube->numterms != 2)
- continue;
-
- if (sube->terms[0].type == YASM_EXPR_INT &&
- (sube->terms[1].type == YASM_EXPR_SYM ||
- sube->terms[1].type == YASM_EXPR_PRECBC)) {
- intn = sube->terms[0].data.intn;
- if (sube->terms[1].type == YASM_EXPR_PRECBC)
- precbc = sube->terms[1].data.precbc;
- else
- sym = sube->terms[1].data.sym;
- } else if ((sube->terms[0].type == YASM_EXPR_SYM ||
- sube->terms[0].type == YASM_EXPR_PRECBC) &&
- sube->terms[1].type == YASM_EXPR_INT) {
- if (sube->terms[0].type == YASM_EXPR_PRECBC)
- precbc = sube->terms[0].data.precbc;
- else
- sym = sube->terms[0].data.sym;
- intn = sube->terms[1].data.intn;
- } else
- continue;
-
- if (!yasm_intnum_is_neg1(intn))
- continue;
-
- if (sym && !yasm_symrec_get_label(sym, &precbc))
- continue;
- sect2 = yasm_bc_get_section(precbc);
-
- /* Now look for a symrec term in the same segment */
- for (j=0; j<e->numterms; j++) {
- if (((e->terms[j].type == YASM_EXPR_SYM &&
- yasm_symrec_get_label(e->terms[j].data.sym, &precbc2)) ||
- (e->terms[j].type == YASM_EXPR_PRECBC &&
- (precbc2 = e->terms[j].data.precbc))) &&
- (sect = yasm_bc_get_section(precbc2)) &&
- sect == sect2 &&
- callback(&e->terms[j], precbc, precbc2, cbd)) {
- /* Delete the matching (-1*symrec) term */
- yasm_expr_destroy(sube);
- e->terms[i].type = YASM_EXPR_NONE;
- break; /* stop looking for matching symrec term */
- }
- }
- }
-
- /* Clean up any deleted (EXPR_NONE) terms */
- numterms = 0;
- for (i=0; i<e->numterms; i++) {
- if (e->terms[i].type != YASM_EXPR_NONE)
- e->terms[numterms++] = e->terms[i]; /* structure copy */
- }
- if (e->numterms != numterms) {
- e->numterms = numterms;
- e = yasm_xrealloc(e, sizeof(yasm_expr)+((numterms<2) ? 0 :
- sizeof(yasm_expr__item)*(numterms-2)));
- if (numterms == 1)
- e->op = YASM_EXPR_IDENT;
- }
-
- return e;
-}
-
-static int
-expr_xform_bc_dist_cb(yasm_expr__item *ei, yasm_bytecode *precbc,
- yasm_bytecode *precbc2, /*@null@*/ void *d)
-{
- yasm_intnum *dist = yasm_calc_bc_dist(precbc, precbc2);
- if (!dist)
- return 0;
- /* Change the term to an integer */
- ei->type = YASM_EXPR_INT;
- ei->data.intn = dist;
- return 1;
-}
-
-/* Transforms instances of symrec-symrec [symrec+(-1*symrec)] into integers if
- * possible.
- */
-static /*@only@*/ yasm_expr *
-expr_xform_bc_dist(/*@returned@*/ /*@only@*/ yasm_expr *e)
-{
- return expr_xform_bc_dist_base(e, NULL, expr_xform_bc_dist_cb);
-}
-
-typedef struct bc_dist_subst_cbd {
- void (*callback) (unsigned int subst, yasm_bytecode *precbc,
- yasm_bytecode *precbc2, void *cbd);
- void *cbd;
- unsigned int subst;
-} bc_dist_subst_cbd;
-
-static int
-expr_bc_dist_subst_cb(yasm_expr__item *ei, yasm_bytecode *precbc,
- yasm_bytecode *precbc2, /*@null@*/ void *d)
-{
- bc_dist_subst_cbd *my_cbd = d;
- assert(my_cbd != NULL);
- /* Call higher-level callback */
- my_cbd->callback(my_cbd->subst, precbc, precbc2, my_cbd->cbd);
- /* Change the term to an subst */
- ei->type = YASM_EXPR_SUBST;
- ei->data.subst = my_cbd->subst;
- my_cbd->subst++;
- return 1;
-}
-
-static yasm_expr *
-expr_xform_bc_dist_subst(yasm_expr *e, void *d)
-{
- return expr_xform_bc_dist_base(e, d, expr_bc_dist_subst_cb);
-}
-
-int
-yasm_expr__bc_dist_subst(yasm_expr **ep, void *cbd,
- void (*callback) (unsigned int subst,
- yasm_bytecode *precbc,
- yasm_bytecode *precbc2,
- void *cbd))
-{
- bc_dist_subst_cbd my_cbd; /* callback info for low-level callback */
- my_cbd.callback = callback;
- my_cbd.cbd = cbd;
- my_cbd.subst = 0;
- *ep = yasm_expr__level_tree(*ep, 1, 1, 1, 0, &expr_xform_bc_dist_subst,
- &my_cbd);
- return my_cbd.subst;
-}
-
-/* Negate just a single ExprItem by building a -1*ei subexpression */
-static void
-expr_xform_neg_item(yasm_expr *e, yasm_expr__item *ei)
-{
- yasm_expr *sube = yasm_xmalloc(sizeof(yasm_expr));
-
- /* Build -1*ei subexpression */
- sube->op = YASM_EXPR_MUL;
- sube->line = e->line;
- sube->numterms = 2;
- sube->terms[0].type = YASM_EXPR_INT;
- sube->terms[0].data.intn = yasm_intnum_create_int(-1);
- sube->terms[1] = *ei; /* structure copy */
-
- /* Replace original ExprItem with subexp */
- ei->type = YASM_EXPR_EXPR;
- ei->data.expn = sube;
-}
-
-/* Negates e by multiplying by -1, with distribution over lower-precedence
- * operators (eg ADD) and special handling to simplify result w/ADD, NEG, and
- * others.
- *
- * Returns a possibly reallocated e.
- */
-static /*@only@*/ yasm_expr *
-expr_xform_neg_helper(/*@returned@*/ /*@only@*/ yasm_expr *e)
-{
- yasm_expr *ne;
- int i;
-
- switch (e->op) {
- case YASM_EXPR_ADD:
- /* distribute (recursively if expr) over terms */
- for (i=0; i<e->numterms; i++) {
- if (e->terms[i].type == YASM_EXPR_EXPR)
- e->terms[i].data.expn =
- expr_xform_neg_helper(e->terms[i].data.expn);
- else
- expr_xform_neg_item(e, &e->terms[i]);
- }
- break;
- case YASM_EXPR_SUB:
- /* change op to ADD, and recursively negate left side (if expr) */
- e->op = YASM_EXPR_ADD;
- if (e->terms[0].type == YASM_EXPR_EXPR)
- e->terms[0].data.expn =
- expr_xform_neg_helper(e->terms[0].data.expn);
- else
- expr_xform_neg_item(e, &e->terms[0]);
- break;
- case YASM_EXPR_NEG:
- /* Negating a negated value? Make it an IDENT. */
- e->op = YASM_EXPR_IDENT;
- break;
- case YASM_EXPR_IDENT:
- /* Negating an ident? Change it into a MUL w/ -1 if there's no
- * floatnums present below; if there ARE floatnums, recurse.
- */
- if (e->terms[0].type == YASM_EXPR_FLOAT)
- yasm_floatnum_calc(e->terms[0].data.flt, YASM_EXPR_NEG, NULL);
- else if (e->terms[0].type == YASM_EXPR_INT)
- yasm_intnum_calc(e->terms[0].data.intn, YASM_EXPR_NEG, NULL);
- else if (e->terms[0].type == YASM_EXPR_EXPR &&
- yasm_expr__contains(e->terms[0].data.expn, YASM_EXPR_FLOAT))
- expr_xform_neg_helper(e->terms[0].data.expn);
- else {
- e->op = YASM_EXPR_MUL;
- e->numterms = 2;
- e->terms[1].type = YASM_EXPR_INT;
- e->terms[1].data.intn = yasm_intnum_create_int(-1);
- }
- break;
- default:
- /* Everything else. MUL will be combined when it's leveled.
- * Make a new expr (to replace e) with -1*e.
- */
- ne = yasm_xmalloc(sizeof(yasm_expr));
- ne->op = YASM_EXPR_MUL;
- ne->line = e->line;
- ne->numterms = 2;
- ne->terms[0].type = YASM_EXPR_INT;
- ne->terms[0].data.intn = yasm_intnum_create_int(-1);
- ne->terms[1].type = YASM_EXPR_EXPR;
- ne->terms[1].data.expn = e;
- return ne;
- }
- return e;
-}
-
-/* Transforms negatives into expressions that are easier to combine:
- * -x -> -1*x
- * a-b -> a+(-1*b)
- *
- * Call post-order on an expression tree to transform the entire tree.
- *
- * Returns a possibly reallocated e.
- */
-static /*@only@*/ yasm_expr *
-expr_xform_neg(/*@returned@*/ /*@only@*/ yasm_expr *e)
-{
- switch (e->op) {
- case YASM_EXPR_NEG:
- /* Turn -x into -1*x */
- e->op = YASM_EXPR_IDENT;
- return expr_xform_neg_helper(e);
- case YASM_EXPR_SUB:
- /* Turn a-b into a+(-1*b) */
-
- /* change op to ADD, and recursively negate right side (if expr) */
- e->op = YASM_EXPR_ADD;
- if (e->terms[1].type == YASM_EXPR_EXPR)
- e->terms[1].data.expn =
- expr_xform_neg_helper(e->terms[1].data.expn);
- else
- expr_xform_neg_item(e, &e->terms[1]);
- break;
- default:
- break;
- }
-
- return e;
-}
-
-/* Look for simple identities that make the entire result constant:
- * 0*&x, -1|x, etc.
- */
-static int
-expr_is_constant(yasm_expr_op op, yasm_intnum *intn)
-{
- 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));
-}
-
-/* Look for simple "left" identities like 0+x, 1*x, etc. */
-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) ||
- (iszero && op == YASM_EXPR_ADD) ||
- (yasm_intnum_is_neg1(intn) && op == YASM_EXPR_AND) ||
- (!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)
-{
- 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) ||
- (!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.
- * Sets e->op = EXPR_IDENT if numterms ends up being 1.
- * Uses numterms parameter instead of e->numterms for basis of "new" number
- * of terms.
- * Assumes int_term is *only* integer term in e.
- * NOTE: Really designed to only be used by expr_level_op().
- */
-static int
-expr_simplify_identity(yasm_expr *e, int numterms, int *int_term,
- int simplify_reg_mul)
-{
- int i;
- int save_numterms;
-
- /* Don't do this step if it's 1*REG. Save and restore numterms so
- * yasm_expr__contains() works correctly.
- */
- save_numterms = e->numterms;
- e->numterms = numterms;
- if (simplify_reg_mul || e->op != YASM_EXPR_MUL
- || !yasm_intnum_is_pos1(e->terms[*int_term].data.intn)
- || !yasm_expr__contains(e, YASM_EXPR_REG)) {
- /* Check for simple identities that delete the intnum.
- * Don't delete if the intnum is the only thing in the expn.
- */
- if ((*int_term == 0 && numterms > 1 &&
- expr_can_destroy_int_left(e->op, e->terms[0].data.intn)) ||
- (*int_term > 0 &&
- expr_can_destroy_int_right(e->op,
- e->terms[*int_term].data.intn))) {
- /* Delete the intnum */
- yasm_intnum_destroy(e->terms[*int_term].data.intn);
-
- /* Slide everything to its right over by 1 */
- if (*int_term != numterms-1) /* if it wasn't last.. */
- memmove(&e->terms[*int_term], &e->terms[*int_term+1],
- (numterms-1-*int_term)*sizeof(yasm_expr__item));
-
- /* Update numterms */
- numterms--;
- *int_term = -1; /* no longer an int term */
- }
- }
- e->numterms = save_numterms;
-
- /* Check for simple identites that delete everything BUT the intnum.
- * Don't bother if the intnum is the only thing in the expn.
- */
- if (numterms > 1 && *int_term != -1 &&
- expr_is_constant(e->op, e->terms[*int_term].data.intn)) {
- /* Loop through, deleting everything but the integer term */
- for (i=0; i<e->numterms; i++)
- if (i != *int_term)
- expr_delete_term(&e->terms[i], 1);
-
- /* Move integer term to the first term (if not already there) */
- if (*int_term != 0)
- e->terms[0] = e->terms[*int_term]; /* structure copy */
-
- /* Set numterms to 1 */
- numterms = 1;
- }
-
- /* 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_LNOT))
- yasm_intnum_calc(e->terms[0].data.intn, e->op, NULL);
-
- /* Change expression to IDENT if possible. */
- if (numterms == 1)
- e->op = YASM_EXPR_IDENT;
-
- /* Return the updated numterms */
- return numterms;
-}
-
-/* Levels the expression tree starting at e. Eg:
- * a+(b+c) -> a+b+c
- * (a+b)+(c+d) -> a+b+c+d
- * Naturally, only levels operators that allow more than two operand terms.
- * NOTE: only does *one* level of leveling (no recursion). Should be called
- * post-order on a tree to combine deeper levels.
- * Also brings up any IDENT values into the current level (for ALL operators).
- * Folds (combines by evaluation) *integer* constant values if fold_const != 0.
- *
- * Returns a possibly reallocated e.
- */
-/*@-mustfree@*/
-static /*@only@*/ yasm_expr *
-expr_level_op(/*@returned@*/ /*@only@*/ yasm_expr *e, int fold_const,
- int simplify_ident, int simplify_reg_mul)
-{
- int i, j, o, fold_numterms, level_numterms, level_fold_numterms;
- int first_int_term = -1;
-
- /* Determine how many operands will need to be brought up (for leveling).
- * Go ahead and bring up any IDENT'ed values.
- */
- while (e->op == YASM_EXPR_IDENT && e->terms[0].type == YASM_EXPR_EXPR) {
- yasm_expr *sube = e->terms[0].data.expn;
- yasm_xfree(e);
- e = sube;
- }
-
- /* If non-numeric expression, don't fold constants. */
- if (e->op > YASM_EXPR_NONNUM)
- fold_const = 0;
-
- level_numterms = e->numterms;
- level_fold_numterms = 0;
- for (i=0; i<e->numterms; i++) {
- /* Search downward until we find something *other* than an
- * IDENT, then bring it up to the current level.
- */
- while (e->terms[i].type == YASM_EXPR_EXPR &&
- e->terms[i].data.expn->op == YASM_EXPR_IDENT) {
- yasm_expr *sube = e->terms[i].data.expn;
- e->terms[i] = sube->terms[0];
- yasm_xfree(sube);
- }
-
- if (e->terms[i].type == YASM_EXPR_EXPR &&
- e->terms[i].data.expn->op == e->op) {
- /* It's an expression w/the same operator, add in its numterms.
- * But don't forget to subtract one for the expr itself!
- */
- level_numterms += e->terms[i].data.expn->numterms - 1;
-
- /* If we're folding constants, count up the number of constants
- * that will be merged in.
- */
- if (fold_const)
- for (j=0; j<e->terms[i].data.expn->numterms; j++)
- if (e->terms[i].data.expn->terms[j].type ==
- YASM_EXPR_INT)
- level_fold_numterms++;
- }
-
- /* Find the first integer term (if one is present) if we're folding
- * constants.
- */
- if (fold_const && first_int_term == -1 &&
- e->terms[i].type == YASM_EXPR_INT)
- first_int_term = i;
- }
-
- /* Look for other integer terms if there's one and combine.
- * Also eliminate empty spaces when combining and adjust numterms
- * variables.
- */
- fold_numterms = e->numterms;
- if (first_int_term != -1) {
- for (i=first_int_term+1, o=first_int_term+1; i<e->numterms; i++) {
- if (e->terms[i].type == YASM_EXPR_INT) {
- yasm_intnum_calc(e->terms[first_int_term].data.intn, e->op,
- e->terms[i].data.intn);
- fold_numterms--;
- level_numterms--;
- /* make sure to delete folded intnum */
- yasm_intnum_destroy(e->terms[i].data.intn);
- } else if (o != i) {
- /* copy term if it changed places */
- e->terms[o++] = e->terms[i];
- } else
- o++;
- }
-
- if (simplify_ident) {
- int new_fold_numterms;
- /* Simplify identities and make IDENT if possible. */
- new_fold_numterms =
- expr_simplify_identity(e, fold_numterms, &first_int_term,
- simplify_reg_mul);
- level_numterms -= fold_numterms-new_fold_numterms;
- fold_numterms = new_fold_numterms;
- }
- if (fold_numterms == 1)
- e->op = YASM_EXPR_IDENT;
- }
-
- /* Only level operators that allow more than two operand terms.
- * Also don't bother leveling if it's not necessary to bring up any terms.
- */
- 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_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)
- e = yasm_xrealloc(e, sizeof(yasm_expr)+((fold_numterms<2) ? 0 :
- sizeof(yasm_expr__item)*(fold_numterms-2)));
- /* Update numterms */
- e->numterms = fold_numterms;
- return e;
- }
-
- /* Adjust numterms for constant folding from terms being "pulled up".
- * Careful: if there's no integer term in e, then save space for it.
- */
- if (fold_const) {
- level_numterms -= level_fold_numterms;
- if (first_int_term == -1 && level_fold_numterms != 0)
- level_numterms++;
- }
-
- /* Alloc more (or conceivably less, but not usually) space for e */
- e = yasm_xrealloc(e, sizeof(yasm_expr)+((level_numterms<2) ? 0 :
- sizeof(yasm_expr__item)*(level_numterms-2)));
-
- /* Copy up ExprItem's. Iterate from right to left to keep the same
- * ordering as was present originally.
- * Combine integer terms as necessary.
- */
- for (i=fold_numterms-1, o=level_numterms-1; i>=0; i--) {
- if (e->terms[i].type == YASM_EXPR_EXPR &&
- e->terms[i].data.expn->op == e->op) {
- /* bring up subexpression */
- yasm_expr *sube = e->terms[i].data.expn;
-
- /* copy terms right to left */
- for (j=sube->numterms-1; j>=0; j--) {
- if (fold_const && sube->terms[j].type == YASM_EXPR_INT) {
- /* Need to fold it in.. but if there's no int term already,
- * just copy into a new one.
- */
- if (first_int_term == -1) {
- first_int_term = o--;
- e->terms[first_int_term] = sube->terms[j]; /* struc */
- } else {
- yasm_intnum_calc(e->terms[first_int_term].data.intn,
- e->op, sube->terms[j].data.intn);
- /* make sure to delete folded intnum */
- yasm_intnum_destroy(sube->terms[j].data.intn);
- }
- } else {
- if (o == first_int_term)
- o--;
- e->terms[o--] = sube->terms[j]; /* structure copy */
- }
- }
-
- /* delete subexpression, but *don't delete nodes* (as we've just
- * copied them!)
- */
- yasm_xfree(sube);
- } else if (o != i) {
- /* copy operand if it changed places */
- if (o == first_int_term)
- o--;
- e->terms[o] = e->terms[i];
- /* If we moved the first_int_term, change first_int_num too */
- if (i == first_int_term)
- first_int_term = o;
- o--;
- } else
- o--;
- }
-
- /* Simplify identities, make IDENT if possible, and save to e->numterms. */
- if (simplify_ident && first_int_term != -1) {
- e->numterms = expr_simplify_identity(e, level_numterms,
- &first_int_term, simplify_reg_mul);
- } else {
- e->numterms = level_numterms;
- if (level_numterms == 1)
- e->op = YASM_EXPR_IDENT;
- }
-
- return e;
-}
-/*@=mustfree@*/
-
-typedef SLIST_HEAD(yasm__exprhead, yasm__exprentry) yasm__exprhead;
-typedef struct yasm__exprentry {
- /*@reldef@*/ SLIST_ENTRY(yasm__exprentry) next;
- /*@null@*/ const yasm_expr *e;
-} yasm__exprentry;
-
-static yasm_expr *
-expr_expand_equ(yasm_expr *e, yasm__exprhead *eh)
-{
- int i;
- yasm__exprentry ee;
-
- /* traverse terms */
- for (i=0; i<e->numterms; i++) {
- const yasm_expr *equ_expr;
-
- /* Expand equ's. */
- if (e->terms[i].type == YASM_EXPR_SYM &&
- (equ_expr = yasm_symrec_get_equ(e->terms[i].data.sym))) {
- yasm__exprentry *np;
-
- /* Check for circular reference */
- SLIST_FOREACH(np, eh, next) {
- if (np->e == equ_expr) {
- yasm_error_set(YASM_ERROR_TOO_COMPLEX,
- N_("circular reference detected"));
- return e;
- }
- }
-
- e->terms[i].type = YASM_EXPR_EXPR;
- e->terms[i].data.expn = yasm_expr_copy(equ_expr);
-
- /* Remember we saw this equ and recurse */
- ee.e = equ_expr;
- SLIST_INSERT_HEAD(eh, &ee, next);
- e->terms[i].data.expn = expr_expand_equ(e->terms[i].data.expn, eh);
- SLIST_REMOVE_HEAD(eh, next);
- } else if (e->terms[i].type == YASM_EXPR_EXPR)
- /* Recurse */
- e->terms[i].data.expn = expr_expand_equ(e->terms[i].data.expn, eh);
- }
-
- return e;
-}
-
-static yasm_expr *
-expr_level_tree(yasm_expr *e, int fold_const, int simplify_ident,
- int simplify_reg_mul, int calc_bc_dist,
- yasm_expr_xform_func expr_xform_extra,
- void *expr_xform_extra_data)
-{
- int i;
-
- e = expr_xform_neg(e);
-
- /* traverse terms */
- for (i=0; i<e->numterms; i++) {
- /* Recurse */
- if (e->terms[i].type == YASM_EXPR_EXPR)
- e->terms[i].data.expn =
- expr_level_tree(e->terms[i].data.expn, fold_const,
- simplify_ident, simplify_reg_mul, calc_bc_dist,
- expr_xform_extra, expr_xform_extra_data);
- }
-
- /* Check for SEG of SEG:OFF, if we match, simplify to just the segment */
- if (e->op == YASM_EXPR_SEG && e->terms[0].type == YASM_EXPR_EXPR &&
- e->terms[0].data.expn->op == YASM_EXPR_SEGOFF) {
- e->op = YASM_EXPR_IDENT;
- e->terms[0].data.expn->op = YASM_EXPR_IDENT;
- /* Destroy the second (offset) term */
- e->terms[0].data.expn->numterms = 1;
- expr_delete_term(&e->terms[0].data.expn->terms[1], 1);
- }
-
- /* do callback */
- e = expr_level_op(e, fold_const, simplify_ident, simplify_reg_mul);
- if (calc_bc_dist || expr_xform_extra) {
- if (calc_bc_dist)
- e = expr_xform_bc_dist(e);
- if (expr_xform_extra)
- e = expr_xform_extra(e, expr_xform_extra_data);
- e = expr_level_tree(e, fold_const, simplify_ident, simplify_reg_mul,
- 0, NULL, NULL);
- }
- return e;
-}
-
-/* Level an entire expn tree, expanding equ's as we go */
-yasm_expr *
-yasm_expr__level_tree(yasm_expr *e, int fold_const, int simplify_ident,
- int simplify_reg_mul, int calc_bc_dist,
- yasm_expr_xform_func expr_xform_extra,
- void *expr_xform_extra_data)
-{
- yasm__exprhead eh;
- SLIST_INIT(&eh);
-
- if (!e)
- return 0;
-
- e = expr_expand_equ(e, &eh);
- e = expr_level_tree(e, fold_const, simplify_ident, simplify_reg_mul,
- calc_bc_dist, expr_xform_extra, expr_xform_extra_data);
-
- return e;
-}
-
-/* Comparison function for expr_order_terms().
- * Assumes ExprType enum is in canonical order.
- */
-static int
-expr_order_terms_compare(const void *va, const void *vb)
-{
- const yasm_expr__item *a = va, *b = vb;
- return (a->type - b->type);
-}
-
-/* Reorder terms of e into canonical order. Only reorders if reordering
- * doesn't change meaning of expression. (eg, doesn't reorder SUB).
- * Canonical order: REG, INT, FLOAT, SYM, EXPR.
- * Multiple terms of a single type are kept in the same order as in
- * the original expression.
- * NOTE: Only performs reordering on *one* level (no recursion).
- */
-void
-yasm_expr__order_terms(yasm_expr *e)
-{
- /* don't bother reordering if only one element */
- if (e->numterms == 1)
- return;
-
- /* only reorder some types of operations */
- switch (e->op) {
- case YASM_EXPR_ADD:
- case YASM_EXPR_MUL:
- 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).
- */
- yasm__mergesort(e->terms, (size_t)e->numterms,
- sizeof(yasm_expr__item), expr_order_terms_compare);
- break;
- default:
- break;
- }
-}
-
-static void
-expr_item_copy(yasm_expr__item *dest, const yasm_expr__item *src)
-{
- dest->type = src->type;
- switch (src->type) {
- case YASM_EXPR_SYM:
- /* Symbols don't need to be copied */
- dest->data.sym = src->data.sym;
- break;
- case YASM_EXPR_PRECBC:
- /* Nor do direct bytecode references */
- dest->data.precbc = src->data.precbc;
- break;
- case YASM_EXPR_EXPR:
- dest->data.expn = yasm_expr__copy_except(src->data.expn, -1);
- break;
- case YASM_EXPR_INT:
- dest->data.intn = yasm_intnum_copy(src->data.intn);
- break;
- case YASM_EXPR_FLOAT:
- dest->data.flt = yasm_floatnum_copy(src->data.flt);
- break;
- case YASM_EXPR_REG:
- dest->data.reg = src->data.reg;
- break;
- case YASM_EXPR_SUBST:
- dest->data.subst = src->data.subst;
- break;
- default:
- break;
- }
-}
-
-/* Copy entire expression EXCEPT for index "except" at *top level only*. */
-yasm_expr *
-yasm_expr__copy_except(const yasm_expr *e, int except)
-{
- yasm_expr *n;
- int i;
-
- n = yasm_xmalloc(sizeof(yasm_expr) +
- sizeof(yasm_expr__item)*(e->numterms<2?0:e->numterms-2));
-
- n->op = e->op;
- n->line = e->line;
- n->numterms = e->numterms;
- for (i=0; i<e->numterms; i++) {
- if (i != except)
- expr_item_copy(&n->terms[i], &e->terms[i]);
- }
-
- return n;
-}
-
-static void
-expr_delete_term(yasm_expr__item *term, int recurse)
-{
- switch (term->type) {
- case YASM_EXPR_INT:
- yasm_intnum_destroy(term->data.intn);
- break;
- case YASM_EXPR_FLOAT:
- yasm_floatnum_destroy(term->data.flt);
- break;
- case YASM_EXPR_EXPR:
- if (recurse)
- yasm_expr_destroy(term->data.expn);
- break;
- default:
- break;
- }
-}
-
-static int
-expr_destroy_each(/*@only@*/ yasm_expr *e, /*@unused@*/ void *d)
-{
- int i;
- for (i=0; i<e->numterms; i++)
- expr_delete_term(&e->terms[i], 0);
- yasm_xfree(e); /* free ourselves */
- return 0; /* don't stop recursion */
-}
-
-/*@-mustfree@*/
-void
-yasm_expr_destroy(yasm_expr *e)
-{
- expr_traverse_nodes_post(e, NULL, expr_destroy_each);
-}
-/*@=mustfree@*/
-
-int
-yasm_expr_is_op(const yasm_expr *e, yasm_expr_op op)
-{
- return (e->op == op);
-}
-
-static int
-expr_contains_callback(const yasm_expr__item *ei, void *d)
-{
- yasm_expr__type *t = d;
- return (ei->type & *t);
-}
-
-int
-yasm_expr__contains(const yasm_expr *e, yasm_expr__type t)
-{
- return yasm_expr__traverse_leaves_in_const(e, &t, expr_contains_callback);
-}
-
-typedef struct subst_cbd {
- unsigned int num_items;
- const yasm_expr__item *items;
-} subst_cbd;
-
-static int
-expr_subst_callback(yasm_expr__item *ei, void *d)
-{
- subst_cbd *cbd = d;
- if (ei->type != YASM_EXPR_SUBST)
- return 0;
- if (ei->data.subst >= cbd->num_items)
- return 1; /* error */
- expr_item_copy(ei, &cbd->items[ei->data.subst]);
- return 0;
-}
-
-int
-yasm_expr__subst(yasm_expr *e, unsigned int num_items,
- const yasm_expr__item *items)
-{
- subst_cbd cbd;
- cbd.num_items = num_items;
- cbd.items = items;
- return yasm_expr__traverse_leaves_in(e, &cbd, expr_subst_callback);
-}
-
-/* Traverse over expression tree, calling func for each operation AFTER the
- * branches (if expressions) have been traversed (eg, postorder
- * traversal). The data pointer d is passed to each func call.
- *
- * Stops early (and returns 1) if func returns 1. Otherwise returns 0.
- */
-static int
-expr_traverse_nodes_post(yasm_expr *e, void *d,
- int (*func) (/*@null@*/ yasm_expr *e,
- /*@null@*/ void *d))
-{
- int i;
-
- if (!e)
- return 0;
-
- /* traverse terms */
- for (i=0; i<e->numterms; i++) {
- if (e->terms[i].type == YASM_EXPR_EXPR &&
- expr_traverse_nodes_post(e->terms[i].data.expn, d, func))
- return 1;
- }
-
- /* do callback */
- return func(e, d);
-}
-
-/* Traverse over expression tree in order, calling func for each leaf
- * (non-operation). The data pointer d is passed to each func call.
- *
- * Stops early (and returns 1) if func returns 1. Otherwise returns 0.
- */
-int
-yasm_expr__traverse_leaves_in_const(const yasm_expr *e, void *d,
- int (*func) (/*@null@*/ const yasm_expr__item *ei, /*@null@*/ void *d))
-{
- int i;
-
- if (!e)
- return 0;
-
- for (i=0; i<e->numterms; i++) {
- if (e->terms[i].type == YASM_EXPR_EXPR) {
- if (yasm_expr__traverse_leaves_in_const(e->terms[i].data.expn, d,
- func))
- return 1;
- } else {
- if (func(&e->terms[i], d))
- return 1;
- }
- }
- return 0;
-}
-
-/* Traverse over expression tree in order, calling func for each leaf
- * (non-operation). The data pointer d is passed to each func call.
- *
- * Stops early (and returns 1) if func returns 1. Otherwise returns 0.
- */
-int
-yasm_expr__traverse_leaves_in(yasm_expr *e, void *d,
- int (*func) (/*@null@*/ yasm_expr__item *ei, /*@null@*/ void *d))
-{
- int i;
-
- if (!e)
- return 0;
-
- for (i=0; i<e->numterms; i++) {
- if (e->terms[i].type == YASM_EXPR_EXPR) {
- if (yasm_expr__traverse_leaves_in(e->terms[i].data.expn, d, func))
- return 1;
- } else {
- if (func(&e->terms[i], d))
- return 1;
- }
- }
- return 0;
-}
-
-yasm_expr *
-yasm_expr_extract_deep_segoff(yasm_expr **ep)
-{
- yasm_expr *retval;
- yasm_expr *e = *ep;
- int i;
-
- /* Try to extract at this level */
- retval = yasm_expr_extract_segoff(ep);
- if (retval)
- return retval;
-
- /* Not at this level? Search any expr children. */
- for (i=0; i<e->numterms; i++) {
- if (e->terms[i].type == YASM_EXPR_EXPR) {
- retval = yasm_expr_extract_deep_segoff(&e->terms[i].data.expn);
- if (retval)
- return retval;
- }
- }
-
- /* Didn't find one */
- return NULL;
-}
-
-yasm_expr *
-yasm_expr_extract_segoff(yasm_expr **ep)
-{
- yasm_expr *retval;
- yasm_expr *e = *ep;
-
- /* If not SEG:OFF, we can't do this transformation */
- if (e->op != YASM_EXPR_SEGOFF)
- return NULL;
-
- /* Extract the SEG portion out to its own expression */
- if (e->terms[0].type == YASM_EXPR_EXPR)
- retval = e->terms[0].data.expn;
- else {
- /* Need to build IDENT expression to hold non-expression contents */
- retval = yasm_xmalloc(sizeof(yasm_expr));
- retval->op = YASM_EXPR_IDENT;
- retval->numterms = 1;
- retval->terms[0] = e->terms[0]; /* structure copy */
- }
-
- /* Delete the SEG: portion by changing the expression into an IDENT */
- e->op = YASM_EXPR_IDENT;
- e->numterms = 1;
- e->terms[0] = e->terms[1]; /* structure copy */
-
- return retval;
-}
-
-yasm_expr *
-yasm_expr_extract_wrt(yasm_expr **ep)
-{
- yasm_expr *retval;
- yasm_expr *e = *ep;
-
- /* If not WRT, we can't do this transformation */
- if (e->op != YASM_EXPR_WRT)
- return NULL;
-
- /* Extract the right side portion out to its own expression */
- if (e->terms[1].type == YASM_EXPR_EXPR)
- retval = e->terms[1].data.expn;
- else {
- /* Need to build IDENT expression to hold non-expression contents */
- retval = yasm_xmalloc(sizeof(yasm_expr));
- retval->op = YASM_EXPR_IDENT;
- retval->numterms = 1;
- retval->terms[0] = e->terms[1]; /* structure copy */
- }
-
- /* Delete the right side portion by changing the expr into an IDENT */
- e->op = YASM_EXPR_IDENT;
- e->numterms = 1;
-
- return retval;
-}
-
-/*@-unqualifiedtrans -nullderef -nullstate -onlytrans@*/
-yasm_intnum *
-yasm_expr_get_intnum(yasm_expr **ep, int calc_bc_dist)
-{
- *ep = yasm_expr_simplify(*ep, calc_bc_dist);
-
- if ((*ep)->op == YASM_EXPR_IDENT && (*ep)->terms[0].type == YASM_EXPR_INT)
- return (*ep)->terms[0].data.intn;
- else
- return (yasm_intnum *)NULL;
-}
-/*@=unqualifiedtrans =nullderef -nullstate -onlytrans@*/
-
-/*@-unqualifiedtrans -nullderef -nullstate -onlytrans@*/
-const yasm_symrec *
-yasm_expr_get_symrec(yasm_expr **ep, int simplify)
-{
- if (simplify)
- *ep = yasm_expr_simplify(*ep, 0);
-
- if ((*ep)->op == YASM_EXPR_IDENT && (*ep)->terms[0].type == YASM_EXPR_SYM)
- return (*ep)->terms[0].data.sym;
- else
- return (yasm_symrec *)NULL;
-}
-/*@=unqualifiedtrans =nullderef -nullstate -onlytrans@*/
-
-/*@-unqualifiedtrans -nullderef -nullstate -onlytrans@*/
-const uintptr_t *
-yasm_expr_get_reg(yasm_expr **ep, int simplify)
-{
- if (simplify)
- *ep = yasm_expr_simplify(*ep, 0);
-
- if ((*ep)->op == YASM_EXPR_IDENT && (*ep)->terms[0].type == YASM_EXPR_REG)
- return &((*ep)->terms[0].data.reg);
- else
- return NULL;
-}
-/*@=unqualifiedtrans =nullderef -nullstate -onlytrans@*/
-
-void
-yasm_expr_print(const yasm_expr *e, FILE *f)
-{
- char opstr[8];
- int i;
-
- if (!e) {
- fprintf(f, "(nil)");
- return;
- }
-
- switch (e->op) {
- case YASM_EXPR_ADD:
- strcpy(opstr, "+");
- break;
- case YASM_EXPR_SUB:
- strcpy(opstr, "-");
- break;
- case YASM_EXPR_MUL:
- strcpy(opstr, "*");
- break;
- case YASM_EXPR_DIV:
- strcpy(opstr, "/");
- break;
- case YASM_EXPR_SIGNDIV:
- strcpy(opstr, "//");
- break;
- case YASM_EXPR_MOD:
- strcpy(opstr, "%");
- break;
- case YASM_EXPR_SIGNMOD:
- strcpy(opstr, "%%");
- break;
- case YASM_EXPR_NEG:
- fprintf(f, "-");
- opstr[0] = 0;
- break;
- case YASM_EXPR_NOT:
- fprintf(f, "~");
- opstr[0] = 0;
- break;
- case YASM_EXPR_OR:
- strcpy(opstr, "|");
- break;
- case YASM_EXPR_AND:
- strcpy(opstr, "&");
- break;
- 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_SHL:
- strcpy(opstr, "<<");
- break;
- case YASM_EXPR_SHR:
- strcpy(opstr, ">>");
- break;
- case YASM_EXPR_LOR:
- strcpy(opstr, "||");
- break;
- case YASM_EXPR_LAND:
- strcpy(opstr, "&&");
- 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_GT:
- strcpy(opstr, ">");
- break;
- case YASM_EXPR_LE:
- strcpy(opstr, "<=");
- break;
- case YASM_EXPR_GE:
- strcpy(opstr, ">=");
- break;
- case YASM_EXPR_NE:
- strcpy(opstr, "!=");
- break;
- case YASM_EXPR_EQ:
- strcpy(opstr, "==");
- break;
- case YASM_EXPR_SEG:
- fprintf(f, "SEG ");
- opstr[0] = 0;
- break;
- case YASM_EXPR_WRT:
- strcpy(opstr, " WRT ");
- break;
- case YASM_EXPR_SEGOFF:
- strcpy(opstr, ":");
- break;
- case YASM_EXPR_IDENT:
- opstr[0] = 0;
- break;
- default:
- strcpy(opstr, " !UNK! ");
- break;
- }
- for (i=0; i<e->numterms; i++) {
- switch (e->terms[i].type) {
- case YASM_EXPR_PRECBC:
- fprintf(f, "{%lx}",
- yasm_bc_next_offset(e->terms[i].data.precbc));
- break;
- case YASM_EXPR_SYM:
- fprintf(f, "%s", yasm_symrec_get_name(e->terms[i].data.sym));
- break;
- case YASM_EXPR_EXPR:
- fprintf(f, "(");
- yasm_expr_print(e->terms[i].data.expn, f);
- fprintf(f, ")");
- break;
- case YASM_EXPR_INT:
- yasm_intnum_print(e->terms[i].data.intn, f);
- break;
- case YASM_EXPR_FLOAT:
- yasm_floatnum_print(e->terms[i].data.flt, f);
- break;
- case YASM_EXPR_REG:
- /* FIXME */
- /*yasm_arch_reg_print(arch, e->terms[i].data.reg, f);*/
- break;
- case YASM_EXPR_SUBST:
- fprintf(f, "[%u]", e->terms[i].data.subst);
- break;
- case YASM_EXPR_NONE:
- break;
- }
- if (i < e->numterms-1)
- fprintf(f, "%s", opstr);
- }
-}
-
-unsigned int
-yasm_expr_size(const yasm_expr *e)
-{
- int i;
- int seen = 0;
- unsigned int size = 0, newsize;
-
- if (e->op == YASM_EXPR_IDENT) {
- if (e->terms[0].type == YASM_EXPR_SYM)
- return yasm_symrec_get_size(e->terms[0].data.sym);
- return 0;
- }
- if (e->op != YASM_EXPR_ADD && e->op != YASM_EXPR_SUB)
- return 0;
-
- for (i=0; i<e->numterms; i++) {
- newsize = 0;
- switch (e->terms[i].type) {
- case YASM_EXPR_EXPR:
- newsize = yasm_expr_size(e->terms[i].data.expn);
- break;
- case YASM_EXPR_SYM:
- newsize = yasm_symrec_get_size(e->terms[i].data.sym);
- break;
- default:
- break;
- }
- if (newsize) {
- size = newsize;
- if (seen)
- /* either sum of idents (?!) or substract of idents */
- return 0;
- seen = 1;
- }
- }
- /* exactly one offset */
- return size;
-}
-
-const char *
-yasm_expr_segment(const yasm_expr *e)
-{
- int i;
- int seen = 0;
- const char *segment = NULL;
-
- if (e->op == YASM_EXPR_IDENT) {
- if (e->terms[0].type == YASM_EXPR_SYM)
- return yasm_symrec_get_segment(e->terms[0].data.sym);
- return NULL;
- }
- if (e->op != YASM_EXPR_ADD && e->op != YASM_EXPR_SUB)
- return NULL;
-
- for (i=0; i<e->numterms; i++) {
- if ((e->op == YASM_EXPR_ADD || !i) &&
- e->terms[i].type == YASM_EXPR_EXPR) {
- if ((segment = yasm_expr_segment(e->terms[i].data.expn))) {
- if (seen) {
- /* either sum of idents (?!) or substract of idents */
- return NULL;
- }
- seen = 1;
- }
- }
- }
- /* exactly one offset */
- return segment;
-}
+/*
+ * Expression handling
+ *
+ * Copyright (C) 2001-2007 Michael Urman, Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "util.h"
+
+#include "libyasm-stdint.h"
+#include "coretype.h"
+#include "bitvect.h"
+
+#include "errwarn.h"
+#include "intnum.h"
+#include "floatnum.h"
+#include "expr.h"
+#include "symrec.h"
+
+#include "bytecode.h"
+#include "section.h"
+
+#include "arch.h"
+
+
+static /*@only@*/ yasm_expr *expr_level_op
+ (/*@returned@*/ /*@only@*/ yasm_expr *e, int fold_const,
+ int simplify_ident, int simplify_reg_mul);
+static int expr_traverse_nodes_post(/*@null@*/ yasm_expr *e,
+ /*@null@*/ void *d,
+ int (*func) (/*@null@*/ yasm_expr *e,
+ /*@null@*/ void *d));
+static void expr_delete_term(yasm_expr__item *term, int recurse);
+
+/* Bitmap of used items. We should really never need more than 2 at a time,
+ * so 31 is pretty much overkill.
+ */
+static unsigned long itempool_used = 0;
+static yasm_expr__item itempool[31];
+
+/* allocate a new expression node, with children as defined.
+ * If it's a unary operator, put the element in left and set right=NULL. */
+/*@-compmempass@*/
+yasm_expr *
+yasm_expr_create(yasm_expr_op op, yasm_expr__item *left,
+ yasm_expr__item *right, unsigned long line)
+{
+ yasm_expr *ptr, *sube;
+ unsigned long z;
+ ptr = yasm_xmalloc(sizeof(yasm_expr));
+
+ ptr->op = op;
+ ptr->numterms = 0;
+ ptr->terms[0].type = YASM_EXPR_NONE;
+ ptr->terms[1].type = YASM_EXPR_NONE;
+ if (left) {
+ ptr->terms[0] = *left; /* structure copy */
+ z = (unsigned long)(left-itempool);
+ if (z>=31)
+ yasm_internal_error(N_("could not find expritem in pool"));
+ itempool_used &= ~(1<<z);
+ ptr->numterms++;
+
+ /* Search downward until we find something *other* than an
+ * IDENT, then bring it up to the current level.
+ */
+ while (ptr->terms[0].type == YASM_EXPR_EXPR &&
+ ptr->terms[0].data.expn->op == YASM_EXPR_IDENT) {
+ sube = ptr->terms[0].data.expn;
+ ptr->terms[0] = sube->terms[0]; /* structure copy */
+ /*@-usereleased@*/
+ yasm_xfree(sube);
+ /*@=usereleased@*/
+ }
+ } else {
+ yasm_internal_error(N_("Right side of expression must exist"));
+ }
+
+ if (right) {
+ ptr->terms[1] = *right; /* structure copy */
+ z = (unsigned long)(right-itempool);
+ if (z>=31)
+ yasm_internal_error(N_("could not find expritem in pool"));
+ itempool_used &= ~(1<<z);
+ ptr->numterms++;
+
+ /* Search downward until we find something *other* than an
+ * IDENT, then bring it up to the current level.
+ */
+ while (ptr->terms[1].type == YASM_EXPR_EXPR &&
+ ptr->terms[1].data.expn->op == YASM_EXPR_IDENT) {
+ sube = ptr->terms[1].data.expn;
+ ptr->terms[1] = sube->terms[0]; /* structure copy */
+ /*@-usereleased@*/
+ yasm_xfree(sube);
+ /*@=usereleased@*/
+ }
+ }
+
+ ptr->line = line;
+
+ return expr_level_op(ptr, 1, 1, 0);
+}
+/*@=compmempass@*/
+
+/* helpers */
+static yasm_expr__item *
+expr_get_item(void)
+{
+ int z = 0;
+ unsigned long v = itempool_used & 0x7fffffff;
+
+ while (v & 1) {
+ v >>= 1;
+ z++;
+ }
+ if (z>=31)
+ yasm_internal_error(N_("too many expritems"));
+ itempool_used |= 1<<z;
+ return &itempool[z];
+}
+
+yasm_expr__item *
+yasm_expr_precbc(yasm_bytecode *precbc)
+{
+ yasm_expr__item *e = expr_get_item();
+ e->type = YASM_EXPR_PRECBC;
+ e->data.precbc = precbc;
+ return e;
+}
+
+yasm_expr__item *
+yasm_expr_sym(yasm_symrec *s)
+{
+ yasm_expr__item *e = expr_get_item();
+ e->type = YASM_EXPR_SYM;
+ e->data.sym = s;
+ return e;
+}
+
+yasm_expr__item *
+yasm_expr_expr(yasm_expr *x)
+{
+ yasm_expr__item *e = expr_get_item();
+ e->type = YASM_EXPR_EXPR;
+ e->data.expn = x;
+ return e;
+}
+
+yasm_expr__item *
+yasm_expr_int(yasm_intnum *i)
+{
+ yasm_expr__item *e = expr_get_item();
+ e->type = YASM_EXPR_INT;
+ e->data.intn = i;
+ return e;
+}
+
+yasm_expr__item *
+yasm_expr_float(yasm_floatnum *f)
+{
+ yasm_expr__item *e = expr_get_item();
+ e->type = YASM_EXPR_FLOAT;
+ e->data.flt = f;
+ return e;
+}
+
+yasm_expr__item *
+yasm_expr_reg(uintptr_t reg)
+{
+ yasm_expr__item *e = expr_get_item();
+ e->type = YASM_EXPR_REG;
+ e->data.reg = reg;
+ return e;
+}
+
+/* Transforms instances of symrec-symrec [symrec+(-1*symrec)] into single
+ * expritems if possible. Uses a simple n^2 algorithm because n is usually
+ * quite small. Also works for precbc-precbc (or symrec-precbc,
+ * precbc-symrec).
+ */
+static /*@only@*/ yasm_expr *
+expr_xform_bc_dist_base(/*@returned@*/ /*@only@*/ yasm_expr *e,
+ /*@null@*/ void *cbd,
+ int (*callback) (yasm_expr__item *ei,
+ yasm_bytecode *precbc,
+ yasm_bytecode *precbc2,
+ void *cbd))
+{
+ int i;
+ /*@dependent@*/ yasm_section *sect;
+ /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc;
+ int numterms;
+
+ /* Handle symrec-symrec in ADD exprs by looking for (-1*symrec) and
+ * symrec term pairs (where both symrecs are in the same segment).
+ */
+ if (e->op != YASM_EXPR_ADD)
+ return e;
+
+ for (i=0; i<e->numterms; i++) {
+ int j;
+ yasm_expr *sube;
+ yasm_intnum *intn;
+ yasm_symrec *sym = NULL;
+ /*@dependent@*/ yasm_section *sect2;
+ /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc2;
+
+ /* First look for an (-1*symrec) term */
+ if (e->terms[i].type != YASM_EXPR_EXPR)
+ continue;
+ sube = e->terms[i].data.expn;
+ if (sube->op != YASM_EXPR_MUL || sube->numterms != 2)
+ continue;
+
+ if (sube->terms[0].type == YASM_EXPR_INT &&
+ (sube->terms[1].type == YASM_EXPR_SYM ||
+ sube->terms[1].type == YASM_EXPR_PRECBC)) {
+ intn = sube->terms[0].data.intn;
+ if (sube->terms[1].type == YASM_EXPR_PRECBC)
+ precbc = sube->terms[1].data.precbc;
+ else
+ sym = sube->terms[1].data.sym;
+ } else if ((sube->terms[0].type == YASM_EXPR_SYM ||
+ sube->terms[0].type == YASM_EXPR_PRECBC) &&
+ sube->terms[1].type == YASM_EXPR_INT) {
+ if (sube->terms[0].type == YASM_EXPR_PRECBC)
+ precbc = sube->terms[0].data.precbc;
+ else
+ sym = sube->terms[0].data.sym;
+ intn = sube->terms[1].data.intn;
+ } else
+ continue;
+
+ if (!yasm_intnum_is_neg1(intn))
+ continue;
+
+ if (sym && !yasm_symrec_get_label(sym, &precbc))
+ continue;
+ sect2 = yasm_bc_get_section(precbc);
+
+ /* Now look for a symrec term in the same segment */
+ for (j=0; j<e->numterms; j++) {
+ if (((e->terms[j].type == YASM_EXPR_SYM &&
+ yasm_symrec_get_label(e->terms[j].data.sym, &precbc2)) ||
+ (e->terms[j].type == YASM_EXPR_PRECBC &&
+ (precbc2 = e->terms[j].data.precbc))) &&
+ (sect = yasm_bc_get_section(precbc2)) &&
+ sect == sect2 &&
+ callback(&e->terms[j], precbc, precbc2, cbd)) {
+ /* Delete the matching (-1*symrec) term */
+ yasm_expr_destroy(sube);
+ e->terms[i].type = YASM_EXPR_NONE;
+ break; /* stop looking for matching symrec term */
+ }
+ }
+ }
+
+ /* Clean up any deleted (EXPR_NONE) terms */
+ numterms = 0;
+ for (i=0; i<e->numterms; i++) {
+ if (e->terms[i].type != YASM_EXPR_NONE)
+ e->terms[numterms++] = e->terms[i]; /* structure copy */
+ }
+ if (e->numterms != numterms) {
+ e->numterms = numterms;
+ e = yasm_xrealloc(e, sizeof(yasm_expr)+((numterms<2) ? 0 :
+ sizeof(yasm_expr__item)*(numterms-2)));
+ if (numterms == 1)
+ e->op = YASM_EXPR_IDENT;
+ }
+
+ return e;
+}
+
+static int
+expr_xform_bc_dist_cb(yasm_expr__item *ei, yasm_bytecode *precbc,
+ yasm_bytecode *precbc2, /*@null@*/ void *d)
+{
+ yasm_intnum *dist = yasm_calc_bc_dist(precbc, precbc2);
+ if (!dist)
+ return 0;
+ /* Change the term to an integer */
+ ei->type = YASM_EXPR_INT;
+ ei->data.intn = dist;
+ return 1;
+}
+
+/* Transforms instances of symrec-symrec [symrec+(-1*symrec)] into integers if
+ * possible.
+ */
+static /*@only@*/ yasm_expr *
+expr_xform_bc_dist(/*@returned@*/ /*@only@*/ yasm_expr *e)
+{
+ return expr_xform_bc_dist_base(e, NULL, expr_xform_bc_dist_cb);
+}
+
+typedef struct bc_dist_subst_cbd {
+ void (*callback) (unsigned int subst, yasm_bytecode *precbc,
+ yasm_bytecode *precbc2, void *cbd);
+ void *cbd;
+ unsigned int subst;
+} bc_dist_subst_cbd;
+
+static int
+expr_bc_dist_subst_cb(yasm_expr__item *ei, yasm_bytecode *precbc,
+ yasm_bytecode *precbc2, /*@null@*/ void *d)
+{
+ bc_dist_subst_cbd *my_cbd = d;
+ assert(my_cbd != NULL);
+ /* Call higher-level callback */
+ my_cbd->callback(my_cbd->subst, precbc, precbc2, my_cbd->cbd);
+ /* Change the term to an subst */
+ ei->type = YASM_EXPR_SUBST;
+ ei->data.subst = my_cbd->subst;
+ my_cbd->subst++;
+ return 1;
+}
+
+static yasm_expr *
+expr_xform_bc_dist_subst(yasm_expr *e, void *d)
+{
+ return expr_xform_bc_dist_base(e, d, expr_bc_dist_subst_cb);
+}
+
+int
+yasm_expr__bc_dist_subst(yasm_expr **ep, void *cbd,
+ void (*callback) (unsigned int subst,
+ yasm_bytecode *precbc,
+ yasm_bytecode *precbc2,
+ void *cbd))
+{
+ bc_dist_subst_cbd my_cbd; /* callback info for low-level callback */
+ my_cbd.callback = callback;
+ my_cbd.cbd = cbd;
+ my_cbd.subst = 0;
+ *ep = yasm_expr__level_tree(*ep, 1, 1, 1, 0, &expr_xform_bc_dist_subst,
+ &my_cbd);
+ return my_cbd.subst;
+}
+
+/* Negate just a single ExprItem by building a -1*ei subexpression */
+static void
+expr_xform_neg_item(yasm_expr *e, yasm_expr__item *ei)
+{
+ yasm_expr *sube = yasm_xmalloc(sizeof(yasm_expr));
+
+ /* Build -1*ei subexpression */
+ sube->op = YASM_EXPR_MUL;
+ sube->line = e->line;
+ sube->numterms = 2;
+ sube->terms[0].type = YASM_EXPR_INT;
+ sube->terms[0].data.intn = yasm_intnum_create_int(-1);
+ sube->terms[1] = *ei; /* structure copy */
+
+ /* Replace original ExprItem with subexp */
+ ei->type = YASM_EXPR_EXPR;
+ ei->data.expn = sube;
+}
+
+/* Negates e by multiplying by -1, with distribution over lower-precedence
+ * operators (eg ADD) and special handling to simplify result w/ADD, NEG, and
+ * others.
+ *
+ * Returns a possibly reallocated e.
+ */
+static /*@only@*/ yasm_expr *
+expr_xform_neg_helper(/*@returned@*/ /*@only@*/ yasm_expr *e)
+{
+ yasm_expr *ne;
+ int i;
+
+ switch (e->op) {
+ case YASM_EXPR_ADD:
+ /* distribute (recursively if expr) over terms */
+ for (i=0; i<e->numterms; i++) {
+ if (e->terms[i].type == YASM_EXPR_EXPR)
+ e->terms[i].data.expn =
+ expr_xform_neg_helper(e->terms[i].data.expn);
+ else
+ expr_xform_neg_item(e, &e->terms[i]);
+ }
+ break;
+ case YASM_EXPR_SUB:
+ /* change op to ADD, and recursively negate left side (if expr) */
+ e->op = YASM_EXPR_ADD;
+ if (e->terms[0].type == YASM_EXPR_EXPR)
+ e->terms[0].data.expn =
+ expr_xform_neg_helper(e->terms[0].data.expn);
+ else
+ expr_xform_neg_item(e, &e->terms[0]);
+ break;
+ case YASM_EXPR_NEG:
+ /* Negating a negated value? Make it an IDENT. */
+ e->op = YASM_EXPR_IDENT;
+ break;
+ case YASM_EXPR_IDENT:
+ /* Negating an ident? Change it into a MUL w/ -1 if there's no
+ * floatnums present below; if there ARE floatnums, recurse.
+ */
+ if (e->terms[0].type == YASM_EXPR_FLOAT)
+ yasm_floatnum_calc(e->terms[0].data.flt, YASM_EXPR_NEG, NULL);
+ else if (e->terms[0].type == YASM_EXPR_INT)
+ yasm_intnum_calc(e->terms[0].data.intn, YASM_EXPR_NEG, NULL);
+ else if (e->terms[0].type == YASM_EXPR_EXPR &&
+ yasm_expr__contains(e->terms[0].data.expn, YASM_EXPR_FLOAT))
+ expr_xform_neg_helper(e->terms[0].data.expn);
+ else {
+ e->op = YASM_EXPR_MUL;
+ e->numterms = 2;
+ e->terms[1].type = YASM_EXPR_INT;
+ e->terms[1].data.intn = yasm_intnum_create_int(-1);
+ }
+ break;
+ default:
+ /* Everything else. MUL will be combined when it's leveled.
+ * Make a new expr (to replace e) with -1*e.
+ */
+ ne = yasm_xmalloc(sizeof(yasm_expr));
+ ne->op = YASM_EXPR_MUL;
+ ne->line = e->line;
+ ne->numterms = 2;
+ ne->terms[0].type = YASM_EXPR_INT;
+ ne->terms[0].data.intn = yasm_intnum_create_int(-1);
+ ne->terms[1].type = YASM_EXPR_EXPR;
+ ne->terms[1].data.expn = e;
+ return ne;
+ }
+ return e;
+}
+
+/* Transforms negatives into expressions that are easier to combine:
+ * -x -> -1*x
+ * a-b -> a+(-1*b)
+ *
+ * Call post-order on an expression tree to transform the entire tree.
+ *
+ * Returns a possibly reallocated e.
+ */
+static /*@only@*/ yasm_expr *
+expr_xform_neg(/*@returned@*/ /*@only@*/ yasm_expr *e)
+{
+ switch (e->op) {
+ case YASM_EXPR_NEG:
+ /* Turn -x into -1*x */
+ e->op = YASM_EXPR_IDENT;
+ return expr_xform_neg_helper(e);
+ case YASM_EXPR_SUB:
+ /* Turn a-b into a+(-1*b) */
+
+ /* change op to ADD, and recursively negate right side (if expr) */
+ e->op = YASM_EXPR_ADD;
+ if (e->terms[1].type == YASM_EXPR_EXPR)
+ e->terms[1].data.expn =
+ expr_xform_neg_helper(e->terms[1].data.expn);
+ else
+ expr_xform_neg_item(e, &e->terms[1]);
+ break;
+ default:
+ break;
+ }
+
+ return e;
+}
+
+/* Look for simple identities that make the entire result constant:
+ * 0*&x, -1|x, etc.
+ */
+static int
+expr_is_constant(yasm_expr_op op, yasm_intnum *intn)
+{
+ 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));
+}
+
+/* Look for simple "left" identities like 0+x, 1*x, etc. */
+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) ||
+ (iszero && op == YASM_EXPR_ADD) ||
+ (yasm_intnum_is_neg1(intn) && op == YASM_EXPR_AND) ||
+ (!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)
+{
+ 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) ||
+ (!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.
+ * Sets e->op = EXPR_IDENT if numterms ends up being 1.
+ * Uses numterms parameter instead of e->numterms for basis of "new" number
+ * of terms.
+ * Assumes int_term is *only* integer term in e.
+ * NOTE: Really designed to only be used by expr_level_op().
+ */
+static int
+expr_simplify_identity(yasm_expr *e, int numterms, int *int_term,
+ int simplify_reg_mul)
+{
+ int i;
+ int save_numterms;
+
+ /* Don't do this step if it's 1*REG. Save and restore numterms so
+ * yasm_expr__contains() works correctly.
+ */
+ save_numterms = e->numterms;
+ e->numterms = numterms;
+ if (simplify_reg_mul || e->op != YASM_EXPR_MUL
+ || !yasm_intnum_is_pos1(e->terms[*int_term].data.intn)
+ || !yasm_expr__contains(e, YASM_EXPR_REG)) {
+ /* Check for simple identities that delete the intnum.
+ * Don't delete if the intnum is the only thing in the expn.
+ */
+ if ((*int_term == 0 && numterms > 1 &&
+ expr_can_destroy_int_left(e->op, e->terms[0].data.intn)) ||
+ (*int_term > 0 &&
+ expr_can_destroy_int_right(e->op,
+ e->terms[*int_term].data.intn))) {
+ /* Delete the intnum */
+ yasm_intnum_destroy(e->terms[*int_term].data.intn);
+
+ /* Slide everything to its right over by 1 */
+ if (*int_term != numterms-1) /* if it wasn't last.. */
+ memmove(&e->terms[*int_term], &e->terms[*int_term+1],
+ (numterms-1-*int_term)*sizeof(yasm_expr__item));
+
+ /* Update numterms */
+ numterms--;
+ *int_term = -1; /* no longer an int term */
+ }
+ }
+ e->numterms = save_numterms;
+
+ /* Check for simple identites that delete everything BUT the intnum.
+ * Don't bother if the intnum is the only thing in the expn.
+ */
+ if (numterms > 1 && *int_term != -1 &&
+ expr_is_constant(e->op, e->terms[*int_term].data.intn)) {
+ /* Loop through, deleting everything but the integer term */
+ for (i=0; i<e->numterms; i++)
+ if (i != *int_term)
+ expr_delete_term(&e->terms[i], 1);
+
+ /* Move integer term to the first term (if not already there) */
+ if (*int_term != 0)
+ e->terms[0] = e->terms[*int_term]; /* structure copy */
+
+ /* Set numterms to 1 */
+ numterms = 1;
+ }
+
+ /* 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_LNOT))
+ yasm_intnum_calc(e->terms[0].data.intn, e->op, NULL);
+
+ /* Change expression to IDENT if possible. */
+ if (numterms == 1)
+ e->op = YASM_EXPR_IDENT;
+
+ /* Return the updated numterms */
+ return numterms;
+}
+
+/* Levels the expression tree starting at e. Eg:
+ * a+(b+c) -> a+b+c
+ * (a+b)+(c+d) -> a+b+c+d
+ * Naturally, only levels operators that allow more than two operand terms.
+ * NOTE: only does *one* level of leveling (no recursion). Should be called
+ * post-order on a tree to combine deeper levels.
+ * Also brings up any IDENT values into the current level (for ALL operators).
+ * Folds (combines by evaluation) *integer* constant values if fold_const != 0.
+ *
+ * Returns a possibly reallocated e.
+ */
+/*@-mustfree@*/
+static /*@only@*/ yasm_expr *
+expr_level_op(/*@returned@*/ /*@only@*/ yasm_expr *e, int fold_const,
+ int simplify_ident, int simplify_reg_mul)
+{
+ int i, j, o, fold_numterms, level_numterms, level_fold_numterms;
+ int first_int_term = -1;
+
+ /* Determine how many operands will need to be brought up (for leveling).
+ * Go ahead and bring up any IDENT'ed values.
+ */
+ while (e->op == YASM_EXPR_IDENT && e->terms[0].type == YASM_EXPR_EXPR) {
+ yasm_expr *sube = e->terms[0].data.expn;
+ yasm_xfree(e);
+ e = sube;
+ }
+
+ /* If non-numeric expression, don't fold constants. */
+ if (e->op > YASM_EXPR_NONNUM)
+ fold_const = 0;
+
+ level_numterms = e->numterms;
+ level_fold_numterms = 0;
+ for (i=0; i<e->numterms; i++) {
+ /* Search downward until we find something *other* than an
+ * IDENT, then bring it up to the current level.
+ */
+ while (e->terms[i].type == YASM_EXPR_EXPR &&
+ e->terms[i].data.expn->op == YASM_EXPR_IDENT) {
+ yasm_expr *sube = e->terms[i].data.expn;
+ e->terms[i] = sube->terms[0];
+ yasm_xfree(sube);
+ }
+
+ if (e->terms[i].type == YASM_EXPR_EXPR &&
+ e->terms[i].data.expn->op == e->op) {
+ /* It's an expression w/the same operator, add in its numterms.
+ * But don't forget to subtract one for the expr itself!
+ */
+ level_numterms += e->terms[i].data.expn->numterms - 1;
+
+ /* If we're folding constants, count up the number of constants
+ * that will be merged in.
+ */
+ if (fold_const)
+ for (j=0; j<e->terms[i].data.expn->numterms; j++)
+ if (e->terms[i].data.expn->terms[j].type ==
+ YASM_EXPR_INT)
+ level_fold_numterms++;
+ }
+
+ /* Find the first integer term (if one is present) if we're folding
+ * constants.
+ */
+ if (fold_const && first_int_term == -1 &&
+ e->terms[i].type == YASM_EXPR_INT)
+ first_int_term = i;
+ }
+
+ /* Look for other integer terms if there's one and combine.
+ * Also eliminate empty spaces when combining and adjust numterms
+ * variables.
+ */
+ fold_numterms = e->numterms;
+ if (first_int_term != -1) {
+ for (i=first_int_term+1, o=first_int_term+1; i<e->numterms; i++) {
+ if (e->terms[i].type == YASM_EXPR_INT) {
+ yasm_intnum_calc(e->terms[first_int_term].data.intn, e->op,
+ e->terms[i].data.intn);
+ fold_numterms--;
+ level_numterms--;
+ /* make sure to delete folded intnum */
+ yasm_intnum_destroy(e->terms[i].data.intn);
+ } else if (o != i) {
+ /* copy term if it changed places */
+ e->terms[o++] = e->terms[i];
+ } else
+ o++;
+ }
+
+ if (simplify_ident) {
+ int new_fold_numterms;
+ /* Simplify identities and make IDENT if possible. */
+ new_fold_numterms =
+ expr_simplify_identity(e, fold_numterms, &first_int_term,
+ simplify_reg_mul);
+ level_numterms -= fold_numterms-new_fold_numterms;
+ fold_numterms = new_fold_numterms;
+ }
+ if (fold_numterms == 1)
+ e->op = YASM_EXPR_IDENT;
+ }
+
+ /* Only level operators that allow more than two operand terms.
+ * Also don't bother leveling if it's not necessary to bring up any terms.
+ */
+ 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_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)
+ e = yasm_xrealloc(e, sizeof(yasm_expr)+((fold_numterms<2) ? 0 :
+ sizeof(yasm_expr__item)*(fold_numterms-2)));
+ /* Update numterms */
+ e->numterms = fold_numterms;
+ return e;
+ }
+
+ /* Adjust numterms for constant folding from terms being "pulled up".
+ * Careful: if there's no integer term in e, then save space for it.
+ */
+ if (fold_const) {
+ level_numterms -= level_fold_numterms;
+ if (first_int_term == -1 && level_fold_numterms != 0)
+ level_numterms++;
+ }
+
+ /* Alloc more (or conceivably less, but not usually) space for e */
+ e = yasm_xrealloc(e, sizeof(yasm_expr)+((level_numterms<2) ? 0 :
+ sizeof(yasm_expr__item)*(level_numterms-2)));
+
+ /* Copy up ExprItem's. Iterate from right to left to keep the same
+ * ordering as was present originally.
+ * Combine integer terms as necessary.
+ */
+ for (i=fold_numterms-1, o=level_numterms-1; i>=0; i--) {
+ if (e->terms[i].type == YASM_EXPR_EXPR &&
+ e->terms[i].data.expn->op == e->op) {
+ /* bring up subexpression */
+ yasm_expr *sube = e->terms[i].data.expn;
+
+ /* copy terms right to left */
+ for (j=sube->numterms-1; j>=0; j--) {
+ if (fold_const && sube->terms[j].type == YASM_EXPR_INT) {
+ /* Need to fold it in.. but if there's no int term already,
+ * just copy into a new one.
+ */
+ if (first_int_term == -1) {
+ first_int_term = o--;
+ e->terms[first_int_term] = sube->terms[j]; /* struc */
+ } else {
+ yasm_intnum_calc(e->terms[first_int_term].data.intn,
+ e->op, sube->terms[j].data.intn);
+ /* make sure to delete folded intnum */
+ yasm_intnum_destroy(sube->terms[j].data.intn);
+ }
+ } else {
+ if (o == first_int_term)
+ o--;
+ e->terms[o--] = sube->terms[j]; /* structure copy */
+ }
+ }
+
+ /* delete subexpression, but *don't delete nodes* (as we've just
+ * copied them!)
+ */
+ yasm_xfree(sube);
+ } else if (o != i) {
+ /* copy operand if it changed places */
+ if (o == first_int_term)
+ o--;
+ e->terms[o] = e->terms[i];
+ /* If we moved the first_int_term, change first_int_num too */
+ if (i == first_int_term)
+ first_int_term = o;
+ o--;
+ } else
+ o--;
+ }
+
+ /* Simplify identities, make IDENT if possible, and save to e->numterms. */
+ if (simplify_ident && first_int_term != -1) {
+ e->numterms = expr_simplify_identity(e, level_numterms,
+ &first_int_term, simplify_reg_mul);
+ } else {
+ e->numterms = level_numterms;
+ if (level_numterms == 1)
+ e->op = YASM_EXPR_IDENT;
+ }
+
+ return e;
+}
+/*@=mustfree@*/
+
+typedef SLIST_HEAD(yasm__exprhead, yasm__exprentry) yasm__exprhead;
+typedef struct yasm__exprentry {
+ /*@reldef@*/ SLIST_ENTRY(yasm__exprentry) next;
+ /*@null@*/ const yasm_expr *e;
+} yasm__exprentry;
+
+static yasm_expr *
+expr_expand_equ(yasm_expr *e, yasm__exprhead *eh)
+{
+ int i;
+ yasm__exprentry ee;
+
+ /* traverse terms */
+ for (i=0; i<e->numterms; i++) {
+ const yasm_expr *equ_expr;
+
+ /* Expand equ's. */
+ if (e->terms[i].type == YASM_EXPR_SYM &&
+ (equ_expr = yasm_symrec_get_equ(e->terms[i].data.sym))) {
+ yasm__exprentry *np;
+
+ /* Check for circular reference */
+ SLIST_FOREACH(np, eh, next) {
+ if (np->e == equ_expr) {
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("circular reference detected"));
+ return e;
+ }
+ }
+
+ e->terms[i].type = YASM_EXPR_EXPR;
+ e->terms[i].data.expn = yasm_expr_copy(equ_expr);
+
+ /* Remember we saw this equ and recurse */
+ ee.e = equ_expr;
+ SLIST_INSERT_HEAD(eh, &ee, next);
+ e->terms[i].data.expn = expr_expand_equ(e->terms[i].data.expn, eh);
+ SLIST_REMOVE_HEAD(eh, next);
+ } else if (e->terms[i].type == YASM_EXPR_EXPR)
+ /* Recurse */
+ e->terms[i].data.expn = expr_expand_equ(e->terms[i].data.expn, eh);
+ }
+
+ return e;
+}
+
+static yasm_expr *
+expr_level_tree(yasm_expr *e, int fold_const, int simplify_ident,
+ int simplify_reg_mul, int calc_bc_dist,
+ yasm_expr_xform_func expr_xform_extra,
+ void *expr_xform_extra_data)
+{
+ int i;
+
+ e = expr_xform_neg(e);
+
+ /* traverse terms */
+ for (i=0; i<e->numterms; i++) {
+ /* Recurse */
+ if (e->terms[i].type == YASM_EXPR_EXPR)
+ e->terms[i].data.expn =
+ expr_level_tree(e->terms[i].data.expn, fold_const,
+ simplify_ident, simplify_reg_mul, calc_bc_dist,
+ expr_xform_extra, expr_xform_extra_data);
+ }
+
+ /* Check for SEG of SEG:OFF, if we match, simplify to just the segment */
+ if (e->op == YASM_EXPR_SEG && e->terms[0].type == YASM_EXPR_EXPR &&
+ e->terms[0].data.expn->op == YASM_EXPR_SEGOFF) {
+ e->op = YASM_EXPR_IDENT;
+ e->terms[0].data.expn->op = YASM_EXPR_IDENT;
+ /* Destroy the second (offset) term */
+ e->terms[0].data.expn->numterms = 1;
+ expr_delete_term(&e->terms[0].data.expn->terms[1], 1);
+ }
+
+ /* do callback */
+ e = expr_level_op(e, fold_const, simplify_ident, simplify_reg_mul);
+ if (calc_bc_dist || expr_xform_extra) {
+ if (calc_bc_dist)
+ e = expr_xform_bc_dist(e);
+ if (expr_xform_extra)
+ e = expr_xform_extra(e, expr_xform_extra_data);
+ e = expr_level_tree(e, fold_const, simplify_ident, simplify_reg_mul,
+ 0, NULL, NULL);
+ }
+ return e;
+}
+
+/* Level an entire expn tree, expanding equ's as we go */
+yasm_expr *
+yasm_expr__level_tree(yasm_expr *e, int fold_const, int simplify_ident,
+ int simplify_reg_mul, int calc_bc_dist,
+ yasm_expr_xform_func expr_xform_extra,
+ void *expr_xform_extra_data)
+{
+ yasm__exprhead eh;
+ SLIST_INIT(&eh);
+
+ if (!e)
+ return 0;
+
+ e = expr_expand_equ(e, &eh);
+ e = expr_level_tree(e, fold_const, simplify_ident, simplify_reg_mul,
+ calc_bc_dist, expr_xform_extra, expr_xform_extra_data);
+
+ return e;
+}
+
+/* Comparison function for expr_order_terms().
+ * Assumes ExprType enum is in canonical order.
+ */
+static int
+expr_order_terms_compare(const void *va, const void *vb)
+{
+ const yasm_expr__item *a = va, *b = vb;
+ return (a->type - b->type);
+}
+
+/* Reorder terms of e into canonical order. Only reorders if reordering
+ * doesn't change meaning of expression. (eg, doesn't reorder SUB).
+ * Canonical order: REG, INT, FLOAT, SYM, EXPR.
+ * Multiple terms of a single type are kept in the same order as in
+ * the original expression.
+ * NOTE: Only performs reordering on *one* level (no recursion).
+ */
+void
+yasm_expr__order_terms(yasm_expr *e)
+{
+ /* don't bother reordering if only one element */
+ if (e->numterms == 1)
+ return;
+
+ /* only reorder some types of operations */
+ switch (e->op) {
+ case YASM_EXPR_ADD:
+ case YASM_EXPR_MUL:
+ 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).
+ */
+ yasm__mergesort(e->terms, (size_t)e->numterms,
+ sizeof(yasm_expr__item), expr_order_terms_compare);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+expr_item_copy(yasm_expr__item *dest, const yasm_expr__item *src)
+{
+ dest->type = src->type;
+ switch (src->type) {
+ case YASM_EXPR_SYM:
+ /* Symbols don't need to be copied */
+ dest->data.sym = src->data.sym;
+ break;
+ case YASM_EXPR_PRECBC:
+ /* Nor do direct bytecode references */
+ dest->data.precbc = src->data.precbc;
+ break;
+ case YASM_EXPR_EXPR:
+ dest->data.expn = yasm_expr__copy_except(src->data.expn, -1);
+ break;
+ case YASM_EXPR_INT:
+ dest->data.intn = yasm_intnum_copy(src->data.intn);
+ break;
+ case YASM_EXPR_FLOAT:
+ dest->data.flt = yasm_floatnum_copy(src->data.flt);
+ break;
+ case YASM_EXPR_REG:
+ dest->data.reg = src->data.reg;
+ break;
+ case YASM_EXPR_SUBST:
+ dest->data.subst = src->data.subst;
+ break;
+ default:
+ break;
+ }
+}
+
+/* Copy entire expression EXCEPT for index "except" at *top level only*. */
+yasm_expr *
+yasm_expr__copy_except(const yasm_expr *e, int except)
+{
+ yasm_expr *n;
+ int i;
+
+ n = yasm_xmalloc(sizeof(yasm_expr) +
+ sizeof(yasm_expr__item)*(e->numterms<2?0:e->numterms-2));
+
+ n->op = e->op;
+ n->line = e->line;
+ n->numterms = e->numterms;
+ for (i=0; i<e->numterms; i++) {
+ if (i != except)
+ expr_item_copy(&n->terms[i], &e->terms[i]);
+ }
+
+ return n;
+}
+
+static void
+expr_delete_term(yasm_expr__item *term, int recurse)
+{
+ switch (term->type) {
+ case YASM_EXPR_INT:
+ yasm_intnum_destroy(term->data.intn);
+ break;
+ case YASM_EXPR_FLOAT:
+ yasm_floatnum_destroy(term->data.flt);
+ break;
+ case YASM_EXPR_EXPR:
+ if (recurse)
+ yasm_expr_destroy(term->data.expn);
+ break;
+ default:
+ break;
+ }
+}
+
+static int
+expr_destroy_each(/*@only@*/ yasm_expr *e, /*@unused@*/ void *d)
+{
+ int i;
+ for (i=0; i<e->numterms; i++)
+ expr_delete_term(&e->terms[i], 0);
+ yasm_xfree(e); /* free ourselves */
+ return 0; /* don't stop recursion */
+}
+
+/*@-mustfree@*/
+void
+yasm_expr_destroy(yasm_expr *e)
+{
+ expr_traverse_nodes_post(e, NULL, expr_destroy_each);
+}
+/*@=mustfree@*/
+
+int
+yasm_expr_is_op(const yasm_expr *e, yasm_expr_op op)
+{
+ return (e->op == op);
+}
+
+static int
+expr_contains_callback(const yasm_expr__item *ei, void *d)
+{
+ yasm_expr__type *t = d;
+ return (ei->type & *t);
+}
+
+int
+yasm_expr__contains(const yasm_expr *e, yasm_expr__type t)
+{
+ return yasm_expr__traverse_leaves_in_const(e, &t, expr_contains_callback);
+}
+
+typedef struct subst_cbd {
+ unsigned int num_items;
+ const yasm_expr__item *items;
+} subst_cbd;
+
+static int
+expr_subst_callback(yasm_expr__item *ei, void *d)
+{
+ subst_cbd *cbd = d;
+ if (ei->type != YASM_EXPR_SUBST)
+ return 0;
+ if (ei->data.subst >= cbd->num_items)
+ return 1; /* error */
+ expr_item_copy(ei, &cbd->items[ei->data.subst]);
+ return 0;
+}
+
+int
+yasm_expr__subst(yasm_expr *e, unsigned int num_items,
+ const yasm_expr__item *items)
+{
+ subst_cbd cbd;
+ cbd.num_items = num_items;
+ cbd.items = items;
+ return yasm_expr__traverse_leaves_in(e, &cbd, expr_subst_callback);
+}
+
+/* Traverse over expression tree, calling func for each operation AFTER the
+ * branches (if expressions) have been traversed (eg, postorder
+ * traversal). The data pointer d is passed to each func call.
+ *
+ * Stops early (and returns 1) if func returns 1. Otherwise returns 0.
+ */
+static int
+expr_traverse_nodes_post(yasm_expr *e, void *d,
+ int (*func) (/*@null@*/ yasm_expr *e,
+ /*@null@*/ void *d))
+{
+ int i;
+
+ if (!e)
+ return 0;
+
+ /* traverse terms */
+ for (i=0; i<e->numterms; i++) {
+ if (e->terms[i].type == YASM_EXPR_EXPR &&
+ expr_traverse_nodes_post(e->terms[i].data.expn, d, func))
+ return 1;
+ }
+
+ /* do callback */
+ return func(e, d);
+}
+
+/* Traverse over expression tree in order, calling func for each leaf
+ * (non-operation). The data pointer d is passed to each func call.
+ *
+ * Stops early (and returns 1) if func returns 1. Otherwise returns 0.
+ */
+int
+yasm_expr__traverse_leaves_in_const(const yasm_expr *e, void *d,
+ int (*func) (/*@null@*/ const yasm_expr__item *ei, /*@null@*/ void *d))
+{
+ int i;
+
+ if (!e)
+ return 0;
+
+ for (i=0; i<e->numterms; i++) {
+ if (e->terms[i].type == YASM_EXPR_EXPR) {
+ if (yasm_expr__traverse_leaves_in_const(e->terms[i].data.expn, d,
+ func))
+ return 1;
+ } else {
+ if (func(&e->terms[i], d))
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* Traverse over expression tree in order, calling func for each leaf
+ * (non-operation). The data pointer d is passed to each func call.
+ *
+ * Stops early (and returns 1) if func returns 1. Otherwise returns 0.
+ */
+int
+yasm_expr__traverse_leaves_in(yasm_expr *e, void *d,
+ int (*func) (/*@null@*/ yasm_expr__item *ei, /*@null@*/ void *d))
+{
+ int i;
+
+ if (!e)
+ return 0;
+
+ for (i=0; i<e->numterms; i++) {
+ if (e->terms[i].type == YASM_EXPR_EXPR) {
+ if (yasm_expr__traverse_leaves_in(e->terms[i].data.expn, d, func))
+ return 1;
+ } else {
+ if (func(&e->terms[i], d))
+ return 1;
+ }
+ }
+ return 0;
+}
+
+yasm_expr *
+yasm_expr_extract_deep_segoff(yasm_expr **ep)
+{
+ yasm_expr *retval;
+ yasm_expr *e = *ep;
+ int i;
+
+ /* Try to extract at this level */
+ retval = yasm_expr_extract_segoff(ep);
+ if (retval)
+ return retval;
+
+ /* Not at this level? Search any expr children. */
+ for (i=0; i<e->numterms; i++) {
+ if (e->terms[i].type == YASM_EXPR_EXPR) {
+ retval = yasm_expr_extract_deep_segoff(&e->terms[i].data.expn);
+ if (retval)
+ return retval;
+ }
+ }
+
+ /* Didn't find one */
+ return NULL;
+}
+
+yasm_expr *
+yasm_expr_extract_segoff(yasm_expr **ep)
+{
+ yasm_expr *retval;
+ yasm_expr *e = *ep;
+
+ /* If not SEG:OFF, we can't do this transformation */
+ if (e->op != YASM_EXPR_SEGOFF)
+ return NULL;
+
+ /* Extract the SEG portion out to its own expression */
+ if (e->terms[0].type == YASM_EXPR_EXPR)
+ retval = e->terms[0].data.expn;
+ else {
+ /* Need to build IDENT expression to hold non-expression contents */
+ retval = yasm_xmalloc(sizeof(yasm_expr));
+ retval->op = YASM_EXPR_IDENT;
+ retval->numterms = 1;
+ retval->terms[0] = e->terms[0]; /* structure copy */
+ }
+
+ /* Delete the SEG: portion by changing the expression into an IDENT */
+ e->op = YASM_EXPR_IDENT;
+ e->numterms = 1;
+ e->terms[0] = e->terms[1]; /* structure copy */
+
+ return retval;
+}
+
+yasm_expr *
+yasm_expr_extract_wrt(yasm_expr **ep)
+{
+ yasm_expr *retval;
+ yasm_expr *e = *ep;
+
+ /* If not WRT, we can't do this transformation */
+ if (e->op != YASM_EXPR_WRT)
+ return NULL;
+
+ /* Extract the right side portion out to its own expression */
+ if (e->terms[1].type == YASM_EXPR_EXPR)
+ retval = e->terms[1].data.expn;
+ else {
+ /* Need to build IDENT expression to hold non-expression contents */
+ retval = yasm_xmalloc(sizeof(yasm_expr));
+ retval->op = YASM_EXPR_IDENT;
+ retval->numterms = 1;
+ retval->terms[0] = e->terms[1]; /* structure copy */
+ }
+
+ /* Delete the right side portion by changing the expr into an IDENT */
+ e->op = YASM_EXPR_IDENT;
+ e->numterms = 1;
+
+ return retval;
+}
+
+/*@-unqualifiedtrans -nullderef -nullstate -onlytrans@*/
+yasm_intnum *
+yasm_expr_get_intnum(yasm_expr **ep, int calc_bc_dist)
+{
+ *ep = yasm_expr_simplify(*ep, calc_bc_dist);
+
+ if ((*ep)->op == YASM_EXPR_IDENT && (*ep)->terms[0].type == YASM_EXPR_INT)
+ return (*ep)->terms[0].data.intn;
+ else
+ return (yasm_intnum *)NULL;
+}
+/*@=unqualifiedtrans =nullderef -nullstate -onlytrans@*/
+
+/*@-unqualifiedtrans -nullderef -nullstate -onlytrans@*/
+const yasm_symrec *
+yasm_expr_get_symrec(yasm_expr **ep, int simplify)
+{
+ if (simplify)
+ *ep = yasm_expr_simplify(*ep, 0);
+
+ if ((*ep)->op == YASM_EXPR_IDENT && (*ep)->terms[0].type == YASM_EXPR_SYM)
+ return (*ep)->terms[0].data.sym;
+ else
+ return (yasm_symrec *)NULL;
+}
+/*@=unqualifiedtrans =nullderef -nullstate -onlytrans@*/
+
+/*@-unqualifiedtrans -nullderef -nullstate -onlytrans@*/
+const uintptr_t *
+yasm_expr_get_reg(yasm_expr **ep, int simplify)
+{
+ if (simplify)
+ *ep = yasm_expr_simplify(*ep, 0);
+
+ if ((*ep)->op == YASM_EXPR_IDENT && (*ep)->terms[0].type == YASM_EXPR_REG)
+ return &((*ep)->terms[0].data.reg);
+ else
+ return NULL;
+}
+/*@=unqualifiedtrans =nullderef -nullstate -onlytrans@*/
+
+void
+yasm_expr_print(const yasm_expr *e, FILE *f)
+{
+ char opstr[8];
+ int i;
+
+ if (!e) {
+ fprintf(f, "(nil)");
+ return;
+ }
+
+ switch (e->op) {
+ case YASM_EXPR_ADD:
+ strcpy(opstr, "+");
+ break;
+ case YASM_EXPR_SUB:
+ strcpy(opstr, "-");
+ break;
+ case YASM_EXPR_MUL:
+ strcpy(opstr, "*");
+ break;
+ case YASM_EXPR_DIV:
+ strcpy(opstr, "/");
+ break;
+ case YASM_EXPR_SIGNDIV:
+ strcpy(opstr, "//");
+ break;
+ case YASM_EXPR_MOD:
+ strcpy(opstr, "%");
+ break;
+ case YASM_EXPR_SIGNMOD:
+ strcpy(opstr, "%%");
+ break;
+ case YASM_EXPR_NEG:
+ fprintf(f, "-");
+ opstr[0] = 0;
+ break;
+ case YASM_EXPR_NOT:
+ fprintf(f, "~");
+ opstr[0] = 0;
+ break;
+ case YASM_EXPR_OR:
+ strcpy(opstr, "|");
+ break;
+ case YASM_EXPR_AND:
+ strcpy(opstr, "&");
+ break;
+ 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_SHL:
+ strcpy(opstr, "<<");
+ break;
+ case YASM_EXPR_SHR:
+ strcpy(opstr, ">>");
+ break;
+ case YASM_EXPR_LOR:
+ strcpy(opstr, "||");
+ break;
+ case YASM_EXPR_LAND:
+ strcpy(opstr, "&&");
+ 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_GT:
+ strcpy(opstr, ">");
+ break;
+ case YASM_EXPR_LE:
+ strcpy(opstr, "<=");
+ break;
+ case YASM_EXPR_GE:
+ strcpy(opstr, ">=");
+ break;
+ case YASM_EXPR_NE:
+ strcpy(opstr, "!=");
+ break;
+ case YASM_EXPR_EQ:
+ strcpy(opstr, "==");
+ break;
+ case YASM_EXPR_SEG:
+ fprintf(f, "SEG ");
+ opstr[0] = 0;
+ break;
+ case YASM_EXPR_WRT:
+ strcpy(opstr, " WRT ");
+ break;
+ case YASM_EXPR_SEGOFF:
+ strcpy(opstr, ":");
+ break;
+ case YASM_EXPR_IDENT:
+ opstr[0] = 0;
+ break;
+ default:
+ strcpy(opstr, " !UNK! ");
+ break;
+ }
+ for (i=0; i<e->numterms; i++) {
+ switch (e->terms[i].type) {
+ case YASM_EXPR_PRECBC:
+ fprintf(f, "{%lx}",
+ yasm_bc_next_offset(e->terms[i].data.precbc));
+ break;
+ case YASM_EXPR_SYM:
+ fprintf(f, "%s", yasm_symrec_get_name(e->terms[i].data.sym));
+ break;
+ case YASM_EXPR_EXPR:
+ fprintf(f, "(");
+ yasm_expr_print(e->terms[i].data.expn, f);
+ fprintf(f, ")");
+ break;
+ case YASM_EXPR_INT:
+ yasm_intnum_print(e->terms[i].data.intn, f);
+ break;
+ case YASM_EXPR_FLOAT:
+ yasm_floatnum_print(e->terms[i].data.flt, f);
+ break;
+ case YASM_EXPR_REG:
+ /* FIXME */
+ /*yasm_arch_reg_print(arch, e->terms[i].data.reg, f);*/
+ break;
+ case YASM_EXPR_SUBST:
+ fprintf(f, "[%u]", e->terms[i].data.subst);
+ break;
+ case YASM_EXPR_NONE:
+ break;
+ }
+ if (i < e->numterms-1)
+ fprintf(f, "%s", opstr);
+ }
+}
+
+unsigned int
+yasm_expr_size(const yasm_expr *e)
+{
+ int i;
+ int seen = 0;
+ unsigned int size = 0, newsize;
+
+ if (e->op == YASM_EXPR_IDENT) {
+ if (e->terms[0].type == YASM_EXPR_SYM)
+ return yasm_symrec_get_size(e->terms[0].data.sym);
+ return 0;
+ }
+ if (e->op != YASM_EXPR_ADD && e->op != YASM_EXPR_SUB)
+ return 0;
+
+ for (i=0; i<e->numterms; i++) {
+ newsize = 0;
+ switch (e->terms[i].type) {
+ case YASM_EXPR_EXPR:
+ newsize = yasm_expr_size(e->terms[i].data.expn);
+ break;
+ case YASM_EXPR_SYM:
+ newsize = yasm_symrec_get_size(e->terms[i].data.sym);
+ break;
+ default:
+ break;
+ }
+ if (newsize) {
+ size = newsize;
+ if (seen)
+ /* either sum of idents (?!) or substract of idents */
+ return 0;
+ seen = 1;
+ }
+ }
+ /* exactly one offset */
+ return size;
+}
+
+const char *
+yasm_expr_segment(const yasm_expr *e)
+{
+ int i;
+ int seen = 0;
+ const char *segment = NULL;
+
+ if (e->op == YASM_EXPR_IDENT) {
+ if (e->terms[0].type == YASM_EXPR_SYM)
+ return yasm_symrec_get_segment(e->terms[0].data.sym);
+ return NULL;
+ }
+ if (e->op != YASM_EXPR_ADD && e->op != YASM_EXPR_SUB)
+ return NULL;
+
+ for (i=0; i<e->numterms; i++) {
+ if ((e->op == YASM_EXPR_ADD || !i) &&
+ e->terms[i].type == YASM_EXPR_EXPR) {
+ if ((segment = yasm_expr_segment(e->terms[i].data.expn))) {
+ if (seen) {
+ /* either sum of idents (?!) or substract of idents */
+ return NULL;
+ }
+ seen = 1;
+ }
+ }
+ }
+ /* exactly one offset */
+ return segment;
+}
diff --git a/contrib/tools/yasm/libyasm/expr.h b/contrib/tools/yasm/libyasm/expr.h
index 0de62dfed7..b68bff0c81 100644
--- a/contrib/tools/yasm/libyasm/expr.h
+++ b/contrib/tools/yasm/libyasm/expr.h
@@ -1,388 +1,388 @@
-/**
- * \file libyasm/expr.h
- * \brief YASM expression interface.
- *
- * \license
- * Copyright (C) 2001-2007 Michael Urman, Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- * \endlicense
- */
-#ifndef YASM_EXPR_H
-#define YASM_EXPR_H
-
-#ifndef YASM_LIB_DECL
-#define YASM_LIB_DECL
-#endif
-
-/** Type of an expression item. Types are listed in canonical sorting order.
- * See expr_order_terms().
- * Note #YASM_EXPR_PRECBC must be used carefully (in a-b pairs), as only
- * symrecs can become the relative term in a #yasm_value.
- */
-typedef enum yasm_expr__type {
- YASM_EXPR_NONE = 0, /**< Nothing */
- YASM_EXPR_REG = 1<<0, /**< Register */
- YASM_EXPR_INT = 1<<1, /**< Integer value */
- YASM_EXPR_SUBST = 1<<2, /**< Substitution placeholder */
- YASM_EXPR_FLOAT = 1<<3, /**< Floating point value */
- YASM_EXPR_SYM = 1<<4, /**< Symbol */
- YASM_EXPR_PRECBC = 1<<5,/**< Direct bytecode ref (rather than via sym) */
- YASM_EXPR_EXPR = 1<<6 /**< Subexpression */
-} yasm_expr__type;
-
-/** Expression item. */
-typedef struct yasm_expr__item {
- yasm_expr__type type; /**< Type */
-
- /** Expression item data. Correct value depends on type. */
- union {
- yasm_bytecode *precbc; /**< Direct bytecode ref (YASM_EXPR_PRECBC) */
- yasm_symrec *sym; /**< Symbol (YASM_EXPR_SYM) */
- yasm_expr *expn; /**< Subexpression (YASM_EXPR_EXPR) */
- yasm_intnum *intn; /**< Integer value (YASM_EXPR_INT) */
- yasm_floatnum *flt; /**< Floating point value (YASM_EXPR_FLOAT) */
- uintptr_t reg; /**< Register (YASM_EXPR_REG) */
- unsigned int subst; /**< Subst placeholder (YASM_EXPR_SUBST) */
- } data;
-} yasm_expr__item;
-
-/** Expression. */
-struct yasm_expr {
- yasm_expr_op op; /**< Operation. */
- unsigned long line; /**< Line number where expression was defined. */
- int numterms; /**< Number of terms in the expression. */
-
- /** Terms of the expression. Structure may be extended to include more
- * terms, as some operations may allow more than two operand terms
- * (ADD, MUL, OR, AND, XOR).
- */
- yasm_expr__item terms[2];
-};
-
-/** Create a new expression e=a op b.
- * \param op operation
- * \param a expression item a
- * \param b expression item b (optional depending on op)
- * \param line virtual line (where expression defined)
- * \return Newly allocated expression.
- */
-YASM_LIB_DECL
-/*@only@*/ yasm_expr *yasm_expr_create
- (yasm_expr_op op, /*@only@*/ yasm_expr__item *a,
- /*@only@*/ /*@null@*/ yasm_expr__item *b, unsigned long line);
-
-/** Create a new preceding-bytecode expression item.
- * \param precbc preceding bytecode
- * \return Newly allocated expression item.
- */
-YASM_LIB_DECL
-/*@only@*/ yasm_expr__item *yasm_expr_precbc(/*@keep@*/ yasm_bytecode *precbc);
-
-/** Create a new symbol expression item.
- * \param sym symbol
- * \return Newly allocated expression item.
- */
-YASM_LIB_DECL
-/*@only@*/ yasm_expr__item *yasm_expr_sym(/*@keep@*/ yasm_symrec *sym);
-
-/** Create a new expression expression item.
- * \param e expression
- * \return Newly allocated expression item.
- */
-YASM_LIB_DECL
-/*@only@*/ yasm_expr__item *yasm_expr_expr(/*@keep@*/ yasm_expr *e);
-
-/** Create a new intnum expression item.
- * \param intn intnum
- * \return Newly allocated expression item.
- */
-YASM_LIB_DECL
-/*@only@*/ yasm_expr__item *yasm_expr_int(/*@keep@*/ yasm_intnum *intn);
-
-/** Create a new floatnum expression item.
- * \param flt floatnum
- * \return Newly allocated expression item.
- */
-YASM_LIB_DECL
-/*@only@*/ yasm_expr__item *yasm_expr_float(/*@keep@*/ yasm_floatnum *flt);
-
-/** Create a new register expression item.
- * \param reg register
- * \return Newly allocated expression item.
- */
-YASM_LIB_DECL
-/*@only@*/ yasm_expr__item *yasm_expr_reg(uintptr_t reg);
-
-/** Create a new expression tree e=l op r.
- * \param l expression for left side of new expression
- * \param o operation
- * \param r expression for right side of new expression
- * \param i line index
- * \return Newly allocated expression.
- */
-#define yasm_expr_create_tree(l,o,r,i) \
- yasm_expr_create ((o), yasm_expr_expr(l), yasm_expr_expr(r), i)
-
-/** Create a new expression branch e=op r.
- * \param o operation
- * \param r expression for right side of new expression
- * \param i line index
- * \return Newly allocated expression.
- */
-#define yasm_expr_create_branch(o,r,i) \
- yasm_expr_create ((o), yasm_expr_expr(r), (yasm_expr__item *)NULL, i)
-
-/** Create a new expression identity e=r.
- * \param r expression for identity within new expression
- * \param i line index
- * \return Newly allocated expression.
- */
-#define yasm_expr_create_ident(r,i) \
- yasm_expr_create (YASM_EXPR_IDENT, (r), (yasm_expr__item *)NULL, i)
-
-/** Duplicate an expression.
- * \param e expression
- * \return Newly allocated expression identical to e.
- */
-yasm_expr *yasm_expr_copy(const yasm_expr *e);
-#ifndef YASM_DOXYGEN
-#define yasm_expr_copy(e) yasm_expr__copy_except(e, -1)
-#endif
-
-/** Destroy (free allocated memory for) an expression.
- * \param e expression
- */
-YASM_LIB_DECL
-void yasm_expr_destroy(/*@only@*/ /*@null@*/ yasm_expr *e);
-
-/** Determine if an expression is a specified operation (at the top level).
- * \param e expression
- * \param op operator
- * \return Nonzero if the expression was the specified operation at the top
- * level, zero otherwise.
- */
-YASM_LIB_DECL
-int yasm_expr_is_op(const yasm_expr *e, yasm_expr_op op);
-
-/** Extra transformation function for yasm_expr__level_tree().
- * \param e expression being simplified
- * \param d data provided as expr_xform_extra_data to
- * yasm_expr__level_tree()
- * \return Transformed e.
- */
-typedef /*@only@*/ yasm_expr * (*yasm_expr_xform_func)
- (/*@returned@*/ /*@only@*/ yasm_expr *e, /*@null@*/ void *d);
-
-/** Level an entire expression tree.
- * \internal
- * \param e expression
- * \param fold_const enable constant folding if nonzero
- * \param simplify_ident simplify identities
- * \param simplify_reg_mul simplify REG*1 identities
- * \param calc_bc_dist nonzero if distances between bytecodes should be
- * calculated, 0 if they should be left intact
- * \param expr_xform_extra extra transformation function
- * \param expr_xform_extra_data data to pass to expr_xform_extra
- * \return Leveled expression.
- */
-YASM_LIB_DECL
-/*@only@*/ /*@null@*/ yasm_expr *yasm_expr__level_tree
- (/*@returned@*/ /*@only@*/ /*@null@*/ yasm_expr *e, int fold_const,
- int simplify_ident, int simplify_reg_mul, int calc_bc_dist,
- /*@null@*/ yasm_expr_xform_func expr_xform_extra,
- /*@null@*/ void *expr_xform_extra_data);
-
-/** Simplify an expression as much as possible. Eliminates extraneous
- * branches and simplifies integer-only subexpressions. Simplified version
- * of yasm_expr__level_tree().
- * \param e expression
- * \param cbd if distance between bytecodes should be calculated
- * \return Simplified expression.
- */
-#define yasm_expr_simplify(e, cbd) \
- yasm_expr__level_tree(e, 1, 1, 1, cbd, NULL, NULL)
-
-/** Extract the segment portion of an expression containing SEG:OFF, leaving
- * the offset.
- * \param ep expression (pointer to)
- * \return NULL if unable to extract a segment (expr does not contain a
- * YASM_EXPR_SEGOFF operator), otherwise the segment expression.
- * The input expression is modified such that on return, it's the
- * offset expression.
- */
-YASM_LIB_DECL
-/*@only@*/ /*@null@*/ yasm_expr *yasm_expr_extract_deep_segoff(yasm_expr **ep);
-
-/** Extract the segment portion of a SEG:OFF expression, leaving the offset.
- * \param ep expression (pointer to)
- * \return NULL if unable to extract a segment (YASM_EXPR_SEGOFF not the
- * top-level operator), otherwise the segment expression. The input
- * expression is modified such that on return, it's the offset
- * expression.
- */
-YASM_LIB_DECL
-/*@only@*/ /*@null@*/ yasm_expr *yasm_expr_extract_segoff(yasm_expr **ep);
-
-/** Extract the right portion (y) of a x WRT y expression, leaving the left
- * portion (x).
- * \param ep expression (pointer to)
- * \return NULL if unable to extract (YASM_EXPR_WRT not the top-level
- * operator), otherwise the right side of the WRT expression. The
- * input expression is modified such that on return, it's the left side
- * of the WRT expression.
- */
-YASM_LIB_DECL
-/*@only@*/ /*@null@*/ yasm_expr *yasm_expr_extract_wrt(yasm_expr **ep);
-
-/** Get the integer value of an expression if it's just an integer.
- * \param ep expression (pointer to)
- * \param calc_bc_dist nonzero if distances between bytecodes should be
- * calculated, 0 if NULL should be returned in this case
- * \return NULL if the expression is too complex (contains anything other than
- * integers, ie floats, non-valued labels, registers); otherwise the
- * intnum value of the expression.
- */
-YASM_LIB_DECL
-/*@dependent@*/ /*@null@*/ yasm_intnum *yasm_expr_get_intnum
- (yasm_expr **ep, int calc_bc_dist);
-
-/** Get the symbol value of an expression if it's just a symbol.
- * \param ep expression (pointer to)
- * \param simplify if nonzero, simplify the expression first
- * \return NULL if the expression is too complex; otherwise the symbol value of
- * the expression.
- */
-YASM_LIB_DECL
-/*@dependent@*/ /*@null@*/ const yasm_symrec *yasm_expr_get_symrec
- (yasm_expr **ep, int simplify);
-
-/** Get the register value of an expression if it's just a register.
- * \param ep expression (pointer to)
- * \param simplify if nonzero, simplify the expression first
- * \return NULL if the expression is too complex; otherwise the register value
- * of the expression.
- */
-YASM_LIB_DECL
-/*@dependent@*/ /*@null@*/ const uintptr_t *yasm_expr_get_reg
- (yasm_expr **ep, int simplify);
-
-/** Print an expression. For debugging purposes.
- * \param e expression
- * \param f file
- */
-YASM_LIB_DECL
-void yasm_expr_print(/*@null@*/ const yasm_expr *e, FILE *f);
-
-/** Return the size of an expression, if the user provided it
- * \param e expression
- */
-YASM_LIB_DECL
-unsigned int yasm_expr_size(const yasm_expr *e);
-
-/** Return the segment of an expression, if the user provided it
- * \param e expression
- */
-YASM_LIB_DECL
-const char *yasm_expr_segment(const yasm_expr *e);
-
-/** Traverse over expression tree in order (const version).
- * Calls func for each leaf (non-operation).
- * \param e expression
- * \param d data passed to each call to func
- * \param func callback function
- * \return Stops early (and returns 1) if func returns 1.
- * Otherwise returns 0.
- */
-YASM_LIB_DECL
-int yasm_expr__traverse_leaves_in_const
- (const yasm_expr *e, /*@null@*/ void *d,
- int (*func) (/*@null@*/ const yasm_expr__item *ei, /*@null@*/ void *d));
-
-/** Traverse over expression tree in order.
- * Calls func for each leaf (non-operation).
- * \param e expression
- * \param d data passed to each call to func
- * \param func callback function
- * \return Stops early (and returns 1) if func returns 1.
- * Otherwise returns 0.
- */
-YASM_LIB_DECL
-int yasm_expr__traverse_leaves_in
- (yasm_expr *e, /*@null@*/ void *d,
- int (*func) (/*@null@*/ yasm_expr__item *ei, /*@null@*/ void *d));
-
-/** Reorder terms of e into canonical order. Only reorders if reordering
- * doesn't change meaning of expression. (eg, doesn't reorder SUB).
- * Canonical order: REG, INT, FLOAT, SYM, EXPR.
- * Multiple terms of a single type are kept in the same order as in
- * the original expression.
- * \param e expression
- * \note Only performs reordering on *one* level (no recursion).
- */
-YASM_LIB_DECL
-void yasm_expr__order_terms(yasm_expr *e);
-
-/** Copy entire expression EXCEPT for index "except" at *top level only*.
- * \param e expression
- * \param except term index not to copy; -1 to copy all terms
- * \return Newly allocated copy of expression.
- */
-YASM_LIB_DECL
-yasm_expr *yasm_expr__copy_except(const yasm_expr *e, int except);
-
-/** Test if expression contains an item. Searches recursively into
- * subexpressions.
- * \param e expression
- * \param t type of item to look for
- * \return Nonzero if expression contains an item of type t, zero if not.
- */
-YASM_LIB_DECL
-int yasm_expr__contains(const yasm_expr *e, yasm_expr__type t);
-
-/** Transform symrec-symrec terms in expression into #YASM_EXPR_SUBST items.
- * Calls the callback function for each symrec-symrec term.
- * \param ep expression (pointer to)
- * \param cbd callback data passed to callback function
- * \param callback callback function: given subst index for bytecode
- * pair, bytecode pair (bc2-bc1), and cbd (callback data)
- * \return Number of transformations made.
- */
-YASM_LIB_DECL
-int yasm_expr__bc_dist_subst(yasm_expr **ep, void *cbd,
- void (*callback) (unsigned int subst,
- yasm_bytecode *precbc,
- yasm_bytecode *precbc2,
- void *cbd));
-
-/** Substitute items into expr YASM_EXPR_SUBST items (by index). Items are
- * copied, so caller is responsible for freeing array of items.
- * \param e expression
- * \param num_items number of items in items array
- * \param items items array
- * \return 1 on error (index out of range).
- */
-YASM_LIB_DECL
-int yasm_expr__subst(yasm_expr *e, unsigned int num_items,
- const yasm_expr__item *items);
-
-#endif
+/**
+ * \file libyasm/expr.h
+ * \brief YASM expression interface.
+ *
+ * \license
+ * Copyright (C) 2001-2007 Michael Urman, Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * \endlicense
+ */
+#ifndef YASM_EXPR_H
+#define YASM_EXPR_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/** Type of an expression item. Types are listed in canonical sorting order.
+ * See expr_order_terms().
+ * Note #YASM_EXPR_PRECBC must be used carefully (in a-b pairs), as only
+ * symrecs can become the relative term in a #yasm_value.
+ */
+typedef enum yasm_expr__type {
+ YASM_EXPR_NONE = 0, /**< Nothing */
+ YASM_EXPR_REG = 1<<0, /**< Register */
+ YASM_EXPR_INT = 1<<1, /**< Integer value */
+ YASM_EXPR_SUBST = 1<<2, /**< Substitution placeholder */
+ YASM_EXPR_FLOAT = 1<<3, /**< Floating point value */
+ YASM_EXPR_SYM = 1<<4, /**< Symbol */
+ YASM_EXPR_PRECBC = 1<<5,/**< Direct bytecode ref (rather than via sym) */
+ YASM_EXPR_EXPR = 1<<6 /**< Subexpression */
+} yasm_expr__type;
+
+/** Expression item. */
+typedef struct yasm_expr__item {
+ yasm_expr__type type; /**< Type */
+
+ /** Expression item data. Correct value depends on type. */
+ union {
+ yasm_bytecode *precbc; /**< Direct bytecode ref (YASM_EXPR_PRECBC) */
+ yasm_symrec *sym; /**< Symbol (YASM_EXPR_SYM) */
+ yasm_expr *expn; /**< Subexpression (YASM_EXPR_EXPR) */
+ yasm_intnum *intn; /**< Integer value (YASM_EXPR_INT) */
+ yasm_floatnum *flt; /**< Floating point value (YASM_EXPR_FLOAT) */
+ uintptr_t reg; /**< Register (YASM_EXPR_REG) */
+ unsigned int subst; /**< Subst placeholder (YASM_EXPR_SUBST) */
+ } data;
+} yasm_expr__item;
+
+/** Expression. */
+struct yasm_expr {
+ yasm_expr_op op; /**< Operation. */
+ unsigned long line; /**< Line number where expression was defined. */
+ int numterms; /**< Number of terms in the expression. */
+
+ /** Terms of the expression. Structure may be extended to include more
+ * terms, as some operations may allow more than two operand terms
+ * (ADD, MUL, OR, AND, XOR).
+ */
+ yasm_expr__item terms[2];
+};
+
+/** Create a new expression e=a op b.
+ * \param op operation
+ * \param a expression item a
+ * \param b expression item b (optional depending on op)
+ * \param line virtual line (where expression defined)
+ * \return Newly allocated expression.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_expr *yasm_expr_create
+ (yasm_expr_op op, /*@only@*/ yasm_expr__item *a,
+ /*@only@*/ /*@null@*/ yasm_expr__item *b, unsigned long line);
+
+/** Create a new preceding-bytecode expression item.
+ * \param precbc preceding bytecode
+ * \return Newly allocated expression item.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_expr__item *yasm_expr_precbc(/*@keep@*/ yasm_bytecode *precbc);
+
+/** Create a new symbol expression item.
+ * \param sym symbol
+ * \return Newly allocated expression item.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_expr__item *yasm_expr_sym(/*@keep@*/ yasm_symrec *sym);
+
+/** Create a new expression expression item.
+ * \param e expression
+ * \return Newly allocated expression item.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_expr__item *yasm_expr_expr(/*@keep@*/ yasm_expr *e);
+
+/** Create a new intnum expression item.
+ * \param intn intnum
+ * \return Newly allocated expression item.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_expr__item *yasm_expr_int(/*@keep@*/ yasm_intnum *intn);
+
+/** Create a new floatnum expression item.
+ * \param flt floatnum
+ * \return Newly allocated expression item.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_expr__item *yasm_expr_float(/*@keep@*/ yasm_floatnum *flt);
+
+/** Create a new register expression item.
+ * \param reg register
+ * \return Newly allocated expression item.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_expr__item *yasm_expr_reg(uintptr_t reg);
+
+/** Create a new expression tree e=l op r.
+ * \param l expression for left side of new expression
+ * \param o operation
+ * \param r expression for right side of new expression
+ * \param i line index
+ * \return Newly allocated expression.
+ */
+#define yasm_expr_create_tree(l,o,r,i) \
+ yasm_expr_create ((o), yasm_expr_expr(l), yasm_expr_expr(r), i)
+
+/** Create a new expression branch e=op r.
+ * \param o operation
+ * \param r expression for right side of new expression
+ * \param i line index
+ * \return Newly allocated expression.
+ */
+#define yasm_expr_create_branch(o,r,i) \
+ yasm_expr_create ((o), yasm_expr_expr(r), (yasm_expr__item *)NULL, i)
+
+/** Create a new expression identity e=r.
+ * \param r expression for identity within new expression
+ * \param i line index
+ * \return Newly allocated expression.
+ */
+#define yasm_expr_create_ident(r,i) \
+ yasm_expr_create (YASM_EXPR_IDENT, (r), (yasm_expr__item *)NULL, i)
+
+/** Duplicate an expression.
+ * \param e expression
+ * \return Newly allocated expression identical to e.
+ */
+yasm_expr *yasm_expr_copy(const yasm_expr *e);
+#ifndef YASM_DOXYGEN
+#define yasm_expr_copy(e) yasm_expr__copy_except(e, -1)
+#endif
+
+/** Destroy (free allocated memory for) an expression.
+ * \param e expression
+ */
+YASM_LIB_DECL
+void yasm_expr_destroy(/*@only@*/ /*@null@*/ yasm_expr *e);
+
+/** Determine if an expression is a specified operation (at the top level).
+ * \param e expression
+ * \param op operator
+ * \return Nonzero if the expression was the specified operation at the top
+ * level, zero otherwise.
+ */
+YASM_LIB_DECL
+int yasm_expr_is_op(const yasm_expr *e, yasm_expr_op op);
+
+/** Extra transformation function for yasm_expr__level_tree().
+ * \param e expression being simplified
+ * \param d data provided as expr_xform_extra_data to
+ * yasm_expr__level_tree()
+ * \return Transformed e.
+ */
+typedef /*@only@*/ yasm_expr * (*yasm_expr_xform_func)
+ (/*@returned@*/ /*@only@*/ yasm_expr *e, /*@null@*/ void *d);
+
+/** Level an entire expression tree.
+ * \internal
+ * \param e expression
+ * \param fold_const enable constant folding if nonzero
+ * \param simplify_ident simplify identities
+ * \param simplify_reg_mul simplify REG*1 identities
+ * \param calc_bc_dist nonzero if distances between bytecodes should be
+ * calculated, 0 if they should be left intact
+ * \param expr_xform_extra extra transformation function
+ * \param expr_xform_extra_data data to pass to expr_xform_extra
+ * \return Leveled expression.
+ */
+YASM_LIB_DECL
+/*@only@*/ /*@null@*/ yasm_expr *yasm_expr__level_tree
+ (/*@returned@*/ /*@only@*/ /*@null@*/ yasm_expr *e, int fold_const,
+ int simplify_ident, int simplify_reg_mul, int calc_bc_dist,
+ /*@null@*/ yasm_expr_xform_func expr_xform_extra,
+ /*@null@*/ void *expr_xform_extra_data);
+
+/** Simplify an expression as much as possible. Eliminates extraneous
+ * branches and simplifies integer-only subexpressions. Simplified version
+ * of yasm_expr__level_tree().
+ * \param e expression
+ * \param cbd if distance between bytecodes should be calculated
+ * \return Simplified expression.
+ */
+#define yasm_expr_simplify(e, cbd) \
+ yasm_expr__level_tree(e, 1, 1, 1, cbd, NULL, NULL)
+
+/** Extract the segment portion of an expression containing SEG:OFF, leaving
+ * the offset.
+ * \param ep expression (pointer to)
+ * \return NULL if unable to extract a segment (expr does not contain a
+ * YASM_EXPR_SEGOFF operator), otherwise the segment expression.
+ * The input expression is modified such that on return, it's the
+ * offset expression.
+ */
+YASM_LIB_DECL
+/*@only@*/ /*@null@*/ yasm_expr *yasm_expr_extract_deep_segoff(yasm_expr **ep);
+
+/** Extract the segment portion of a SEG:OFF expression, leaving the offset.
+ * \param ep expression (pointer to)
+ * \return NULL if unable to extract a segment (YASM_EXPR_SEGOFF not the
+ * top-level operator), otherwise the segment expression. The input
+ * expression is modified such that on return, it's the offset
+ * expression.
+ */
+YASM_LIB_DECL
+/*@only@*/ /*@null@*/ yasm_expr *yasm_expr_extract_segoff(yasm_expr **ep);
+
+/** Extract the right portion (y) of a x WRT y expression, leaving the left
+ * portion (x).
+ * \param ep expression (pointer to)
+ * \return NULL if unable to extract (YASM_EXPR_WRT not the top-level
+ * operator), otherwise the right side of the WRT expression. The
+ * input expression is modified such that on return, it's the left side
+ * of the WRT expression.
+ */
+YASM_LIB_DECL
+/*@only@*/ /*@null@*/ yasm_expr *yasm_expr_extract_wrt(yasm_expr **ep);
+
+/** Get the integer value of an expression if it's just an integer.
+ * \param ep expression (pointer to)
+ * \param calc_bc_dist nonzero if distances between bytecodes should be
+ * calculated, 0 if NULL should be returned in this case
+ * \return NULL if the expression is too complex (contains anything other than
+ * integers, ie floats, non-valued labels, registers); otherwise the
+ * intnum value of the expression.
+ */
+YASM_LIB_DECL
+/*@dependent@*/ /*@null@*/ yasm_intnum *yasm_expr_get_intnum
+ (yasm_expr **ep, int calc_bc_dist);
+
+/** Get the symbol value of an expression if it's just a symbol.
+ * \param ep expression (pointer to)
+ * \param simplify if nonzero, simplify the expression first
+ * \return NULL if the expression is too complex; otherwise the symbol value of
+ * the expression.
+ */
+YASM_LIB_DECL
+/*@dependent@*/ /*@null@*/ const yasm_symrec *yasm_expr_get_symrec
+ (yasm_expr **ep, int simplify);
+
+/** Get the register value of an expression if it's just a register.
+ * \param ep expression (pointer to)
+ * \param simplify if nonzero, simplify the expression first
+ * \return NULL if the expression is too complex; otherwise the register value
+ * of the expression.
+ */
+YASM_LIB_DECL
+/*@dependent@*/ /*@null@*/ const uintptr_t *yasm_expr_get_reg
+ (yasm_expr **ep, int simplify);
+
+/** Print an expression. For debugging purposes.
+ * \param e expression
+ * \param f file
+ */
+YASM_LIB_DECL
+void yasm_expr_print(/*@null@*/ const yasm_expr *e, FILE *f);
+
+/** Return the size of an expression, if the user provided it
+ * \param e expression
+ */
+YASM_LIB_DECL
+unsigned int yasm_expr_size(const yasm_expr *e);
+
+/** Return the segment of an expression, if the user provided it
+ * \param e expression
+ */
+YASM_LIB_DECL
+const char *yasm_expr_segment(const yasm_expr *e);
+
+/** Traverse over expression tree in order (const version).
+ * Calls func for each leaf (non-operation).
+ * \param e expression
+ * \param d data passed to each call to func
+ * \param func callback function
+ * \return Stops early (and returns 1) if func returns 1.
+ * Otherwise returns 0.
+ */
+YASM_LIB_DECL
+int yasm_expr__traverse_leaves_in_const
+ (const yasm_expr *e, /*@null@*/ void *d,
+ int (*func) (/*@null@*/ const yasm_expr__item *ei, /*@null@*/ void *d));
+
+/** Traverse over expression tree in order.
+ * Calls func for each leaf (non-operation).
+ * \param e expression
+ * \param d data passed to each call to func
+ * \param func callback function
+ * \return Stops early (and returns 1) if func returns 1.
+ * Otherwise returns 0.
+ */
+YASM_LIB_DECL
+int yasm_expr__traverse_leaves_in
+ (yasm_expr *e, /*@null@*/ void *d,
+ int (*func) (/*@null@*/ yasm_expr__item *ei, /*@null@*/ void *d));
+
+/** Reorder terms of e into canonical order. Only reorders if reordering
+ * doesn't change meaning of expression. (eg, doesn't reorder SUB).
+ * Canonical order: REG, INT, FLOAT, SYM, EXPR.
+ * Multiple terms of a single type are kept in the same order as in
+ * the original expression.
+ * \param e expression
+ * \note Only performs reordering on *one* level (no recursion).
+ */
+YASM_LIB_DECL
+void yasm_expr__order_terms(yasm_expr *e);
+
+/** Copy entire expression EXCEPT for index "except" at *top level only*.
+ * \param e expression
+ * \param except term index not to copy; -1 to copy all terms
+ * \return Newly allocated copy of expression.
+ */
+YASM_LIB_DECL
+yasm_expr *yasm_expr__copy_except(const yasm_expr *e, int except);
+
+/** Test if expression contains an item. Searches recursively into
+ * subexpressions.
+ * \param e expression
+ * \param t type of item to look for
+ * \return Nonzero if expression contains an item of type t, zero if not.
+ */
+YASM_LIB_DECL
+int yasm_expr__contains(const yasm_expr *e, yasm_expr__type t);
+
+/** Transform symrec-symrec terms in expression into #YASM_EXPR_SUBST items.
+ * Calls the callback function for each symrec-symrec term.
+ * \param ep expression (pointer to)
+ * \param cbd callback data passed to callback function
+ * \param callback callback function: given subst index for bytecode
+ * pair, bytecode pair (bc2-bc1), and cbd (callback data)
+ * \return Number of transformations made.
+ */
+YASM_LIB_DECL
+int yasm_expr__bc_dist_subst(yasm_expr **ep, void *cbd,
+ void (*callback) (unsigned int subst,
+ yasm_bytecode *precbc,
+ yasm_bytecode *precbc2,
+ void *cbd));
+
+/** Substitute items into expr YASM_EXPR_SUBST items (by index). Items are
+ * copied, so caller is responsible for freeing array of items.
+ * \param e expression
+ * \param num_items number of items in items array
+ * \param items items array
+ * \return 1 on error (index out of range).
+ */
+YASM_LIB_DECL
+int yasm_expr__subst(yasm_expr *e, unsigned int num_items,
+ const yasm_expr__item *items);
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/file.c b/contrib/tools/yasm/libyasm/file.c
index fc7dab6c17..c4adde0a3a 100644
--- a/contrib/tools/yasm/libyasm/file.c
+++ b/contrib/tools/yasm/libyasm/file.c
@@ -1,672 +1,672 @@
-/*
- * File helper functions.
- *
- * Copyright (C) 2001-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#include <util.h>
-
-/* Need either unistd.h or direct.h to prototype getcwd() and mkdir() */
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef HAVE_DIRECT_H
-#include <direct.h>
-#endif
-
-#ifdef _WIN32
-#include <io.h>
-#endif
-
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-
-#include <ctype.h>
-#include <errno.h>
-
-#include "errwarn.h"
-#include "file.h"
-
-#define BSIZE 8192 /* Fill block size */
-
-
-void
-yasm_scanner_initialize(yasm_scanner *s)
-{
- s->bot = NULL;
- s->tok = NULL;
- s->ptr = NULL;
- s->cur = NULL;
- s->lim = NULL;
- s->top = NULL;
- s->eof = NULL;
-}
-
-void
-yasm_scanner_delete(yasm_scanner *s)
-{
- if (s->bot) {
- yasm_xfree(s->bot);
- s->bot = NULL;
- }
-}
-
-int
-yasm_fill_helper(yasm_scanner *s, unsigned char **cursor,
- size_t (*input_func) (void *d, unsigned char *buf,
- size_t max),
- void *input_func_data)
-{
- size_t cnt;
- int first = 0;
-
- if (s->eof)
- return 0;
-
- cnt = s->tok - s->bot;
- if (cnt > 0) {
- memmove(s->bot, s->tok, (size_t)(s->lim - s->tok));
- s->tok = s->bot;
- s->ptr -= cnt;
- *cursor -= cnt;
- s->lim -= cnt;
- }
- if (!s->bot)
- first = 1;
- if ((s->top - s->lim) < BSIZE) {
- unsigned char *buf = yasm_xmalloc((size_t)(s->lim - s->bot) + BSIZE);
- memcpy(buf, s->tok, (size_t)(s->lim - s->tok));
- s->tok = buf;
- s->ptr = &buf[s->ptr - s->bot];
- *cursor = &buf[*cursor - s->bot];
- s->lim = &buf[s->lim - s->bot];
- s->top = &s->lim[BSIZE];
- if (s->bot)
- yasm_xfree(s->bot);
- s->bot = buf;
- }
- if ((cnt = input_func(input_func_data, s->lim, BSIZE)) == 0) {
- s->eof = &s->lim[cnt];
- *s->eof++ = '\n';
- }
- s->lim += cnt;
- return first;
-}
-
-void
-yasm_unescape_cstring(unsigned char *str, size_t *len)
-{
- unsigned char *s = str;
- unsigned char *o = str;
- unsigned char t[4];
-
- while ((size_t)(s-str)<*len) {
- if (*s == '\\' && (size_t)(&s[1]-str)<*len) {
- s++;
- switch (*s) {
- case 'b': *o = '\b'; s++; break;
- case 'f': *o = '\f'; s++; break;
- case 'n': *o = '\n'; s++; break;
- case 'r': *o = '\r'; s++; break;
- case 't': *o = '\t'; s++; break;
- case 'x':
- /* hex escape; grab last two digits */
- s++;
- while ((size_t)(&s[2]-str)<*len && isxdigit(s[0])
- && isxdigit(s[1]) && isxdigit(s[2]))
- s++;
- if ((size_t)(s-str)<*len && isxdigit(*s)) {
- t[0] = *s++;
- t[1] = '\0';
- t[2] = '\0';
- if ((size_t)(s-str)<*len && isxdigit(*s))
- t[1] = *s++;
- *o = (unsigned char)strtoul((char *)t, NULL, 16);
- } else
- *o = '\0';
- break;
- default:
- if (isdigit(*s)) {
- int warn = 0;
- /* octal escape */
- if (*s > '7')
- warn = 1;
- *o = *s++ - '0';
- if ((size_t)(s-str)<*len && isdigit(*s)) {
- if (*s > '7')
- warn = 1;
- *o <<= 3;
- *o += *s++ - '0';
- if ((size_t)(s-str)<*len && isdigit(*s)) {
- if (*s > '7')
- warn = 1;
- *o <<= 3;
- *o += *s++ - '0';
- }
- }
- if (warn)
- yasm_warn_set(YASM_WARN_GENERAL,
- N_("octal value out of range"));
- } else
- *o = *s++;
- break;
- }
- o++;
- } else
- *o++ = *s++;
- }
- *len = o-str;
-}
-
-size_t
-yasm__splitpath_unix(const char *path, /*@out@*/ const char **tail)
-{
- const char *s;
- s = strrchr(path, '/');
- if (!s) {
- /* No head */
- *tail = path;
- return 0;
- }
- *tail = s+1;
- /* Strip trailing ./ on path */
- while ((s-1)>=path && *(s-1) == '.' && *s == '/'
- && !((s-2)>=path && *(s-2) == '.'))
- s -= 2;
- /* Strip trailing slashes on path (except leading) */
- while (s>path && *s == '/')
- s--;
- /* Return length of head */
- return s-path+1;
-}
-
-size_t
-yasm__splitpath_win(const char *path, /*@out@*/ const char **tail)
-{
- const char *basepath = path;
- const char *s;
-
- /* split off drive letter first, if any */
- if (isalpha(path[0]) && path[1] == ':')
- basepath += 2;
-
- s = basepath;
- while (*s != '\0')
- s++;
- while (s >= basepath && *s != '\\' && *s != '/')
- s--;
- if (s < basepath) {
- *tail = basepath;
- if (path == basepath)
- return 0; /* No head */
- else
- return 2; /* Drive letter is head */
- }
- *tail = s+1;
- /* Strip trailing .\ or ./ on path */
- while ((s-1)>=basepath && *(s-1) == '.' && (*s == '/' || *s == '\\')
- && !((s-2)>=basepath && *(s-2) == '.'))
- s -= 2;
- /* Strip trailing slashes on path (except leading) */
- while (s>basepath && (*s == '/' || *s == '\\'))
- s--;
- /* Return length of head */
- return s-path+1;
-}
-
-char *
-yasm__getcwd(void)
-{
- char *buf;
- size_t size;
-
- size = 1024;
- buf = yasm_xmalloc(size);
-
- if (getenv("YASM_TEST_SUITE")) {
- strcpy(buf, "./");
- return buf;
- }
-
- while (getcwd(buf, size-1) == NULL) {
- if (errno != ERANGE) {
- yasm__fatal(N_("could not determine current working directory"));
- yasm_xfree(buf);
- return NULL;
- }
- size *= 2;
- buf = yasm_xrealloc(buf, size);
- }
-
- /* append a '/' if not already present */
- size = strlen(buf);
- if (buf[size-1] != '\\' && buf[size-1] != '/') {
- buf[size] = '/';
- buf[size+1] = '\0';
- }
- return buf;
-}
-
-char *
-yasm__abspath(const char *path)
-{
- char *curdir, *abspath;
-
- curdir = yasm__getcwd();
- abspath = yasm__combpath(curdir, path);
- yasm_xfree(curdir);
-
- return abspath;
-}
-
-char *
-yasm__combpath_unix(const char *from, const char *to)
-{
- const char *tail;
- size_t pathlen, i, j;
- char *out;
-
- if (to[0] == '/') {
- /* absolute "to" */
- out = yasm_xmalloc(strlen(to)+1);
- /* Combine any double slashes when copying */
- for (j=0; *to; to++) {
- if (*to == '/' && *(to+1) == '/')
- continue;
- out[j++] = *to;
- }
- out[j++] = '\0';
- return out;
- }
-
- /* Get path component; note this strips trailing slash */
- pathlen = yasm__splitpath_unix(from, &tail);
-
- out = yasm_xmalloc(pathlen+strlen(to)+2); /* worst case maximum len */
-
- /* Combine any double slashes when copying */
- for (i=0, j=0; i<pathlen; i++) {
- if (i<pathlen-1 && from[i] == '/' && from[i+1] == '/')
- continue;
- out[j++] = from[i];
- }
- pathlen = j;
-
- /* Add trailing slash back in */
- if (pathlen > 0 && out[pathlen-1] != '/')
- out[pathlen++] = '/';
-
- /* Now scan from left to right through "to", stripping off "." and "..";
- * if we see "..", back up one directory in out unless last directory in
- * out is also "..".
- *
- * Note this does NOT back through ..'s in the "from" path; this is just
- * as well as that could skip symlinks (e.g. "foo/bar/.." might not be
- * the same as "foo").
- */
- for (;;) {
- if (to[0] == '.' && to[1] == '/') {
- to += 2; /* current directory */
- while (*to == '/')
- to++; /* strip off any additional slashes */
- } else if (pathlen == 0)
- break; /* no more "from" path left, we're done */
- else if (to[0] == '.' && to[1] == '.' && to[2] == '/') {
- if (pathlen >= 3 && out[pathlen-1] == '/' && out[pathlen-2] == '.'
- && out[pathlen-3] == '.') {
- /* can't ".." against a "..", so we're done. */
- break;
- }
-
- to += 3; /* throw away "../" */
- while (*to == '/')
- to++; /* strip off any additional slashes */
-
- /* and back out last directory in "out" if not already at root */
- if (pathlen > 1) {
- pathlen--; /* strip off trailing '/' */
- while (pathlen > 0 && out[pathlen-1] != '/')
- pathlen--;
- }
- } else
- break;
- }
-
- /* Copy "to" to tail of output, and we're done */
- /* Combine any double slashes when copying */
- for (j=pathlen; *to; to++) {
- if (*to == '/' && *(to+1) == '/')
- continue;
- out[j++] = *to;
- }
- out[j++] = '\0';
-
- return out;
-}
-
-char *
-yasm__combpath_win(const char *from, const char *to)
-{
- const char *tail;
- size_t pathlen, i, j;
- char *out;
-
- if ((isalpha(to[0]) && to[1] == ':') || (to[0] == '/' || to[0] == '\\')) {
- /* absolute or drive letter "to" */
- out = yasm_xmalloc(strlen(to)+1);
- /* Combine any double slashes when copying */
- for (j=0; *to; to++) {
- if ((*to == '/' || *to == '\\')
- && (*(to+1) == '/' || *(to+1) == '\\'))
- continue;
- if (*to == '/')
- out[j++] = '\\';
- else
- out[j++] = *to;
- }
- out[j++] = '\0';
- return out;
- }
-
- /* Get path component; note this strips trailing slash */
- pathlen = yasm__splitpath_win(from, &tail);
-
- out = yasm_xmalloc(pathlen+strlen(to)+2); /* worst case maximum len */
-
- /* Combine any double slashes when copying */
- for (i=0, j=0; i<pathlen; i++) {
- if (i<pathlen-1 && (from[i] == '/' || from[i] == '\\')
- && (from[i+1] == '/' || from[i+1] == '\\'))
- continue;
- if (from[i] == '/')
- out[j++] = '\\';
- else
- out[j++] = from[i];
- }
- pathlen = j;
-
- /* Add trailing slash back in, unless it's only a raw drive letter */
- if (pathlen > 0 && out[pathlen-1] != '\\'
- && !(pathlen == 2 && isalpha(out[0]) && out[1] == ':'))
- out[pathlen++] = '\\';
-
- /* Now scan from left to right through "to", stripping off "." and "..";
- * if we see "..", back up one directory in out unless last directory in
- * out is also "..".
- *
- * Note this does NOT back through ..'s in the "from" path; this is just
- * as well as that could skip symlinks (e.g. "foo/bar/.." might not be
- * the same as "foo").
- */
- for (;;) {
- if (to[0] == '.' && (to[1] == '/' || to[1] == '\\')) {
- to += 2; /* current directory */
- while (*to == '/' || *to == '\\')
- to++; /* strip off any additional slashes */
- } else if (pathlen == 0
- || (pathlen == 2 && isalpha(out[0]) && out[1] == ':'))
- break; /* no more "from" path left, we're done */
- else if (to[0] == '.' && to[1] == '.'
- && (to[2] == '/' || to[2] == '\\')) {
- if (pathlen >= 3 && out[pathlen-1] == '\\'
- && out[pathlen-2] == '.' && out[pathlen-3] == '.') {
- /* can't ".." against a "..", so we're done. */
- break;
- }
-
- to += 3; /* throw away "../" (or "..\") */
- while (*to == '/' || *to == '\\')
- to++; /* strip off any additional slashes */
-
- /* and back out last directory in "out" if not already at root */
- if (pathlen > 1) {
- pathlen--; /* strip off trailing '/' */
- while (pathlen > 0 && out[pathlen-1] != '\\')
- pathlen--;
- }
- } else
- break;
- }
-
- /* Copy "to" to tail of output, and we're done */
- /* Combine any double slashes when copying */
- for (j=pathlen; *to; to++) {
- if ((*to == '/' || *to == '\\') && (*(to+1) == '/' || *(to+1) == '\\'))
- continue;
- if (*to == '/')
- out[j++] = '\\';
- else
- out[j++] = *to;
- }
- out[j++] = '\0';
-
- return out;
-}
-
-size_t
-yasm__createpath_common(const char *path, int win)
-{
- const char *pp = path, *pe;
- char *ts, *tp;
- size_t len, lth;
-
- lth = len = strlen(path);
- ts = tp = (char *) malloc(len + 1);
- pe = pp + len;
- while (pe > pp) {
- if ((win && *pe == '\\') || *pe == '/')
- break;
- --pe;
- --lth;
- }
-
- while (pp <= pe) {
- if (pp == pe || (win && *pp == '\\') || *pp == '/') {
-#ifdef _WIN32
- struct _finddata_t fi;
- intptr_t h;
+/*
+ * File helper functions.
+ *
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <util.h>
+
+/* Need either unistd.h or direct.h to prototype getcwd() and mkdir() */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_DIRECT_H
+#include <direct.h>
+#endif
+
+#ifdef _WIN32
+#include <io.h>
+#endif
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+
+#include "errwarn.h"
+#include "file.h"
+
+#define BSIZE 8192 /* Fill block size */
+
+
+void
+yasm_scanner_initialize(yasm_scanner *s)
+{
+ s->bot = NULL;
+ s->tok = NULL;
+ s->ptr = NULL;
+ s->cur = NULL;
+ s->lim = NULL;
+ s->top = NULL;
+ s->eof = NULL;
+}
+
+void
+yasm_scanner_delete(yasm_scanner *s)
+{
+ if (s->bot) {
+ yasm_xfree(s->bot);
+ s->bot = NULL;
+ }
+}
+
+int
+yasm_fill_helper(yasm_scanner *s, unsigned char **cursor,
+ size_t (*input_func) (void *d, unsigned char *buf,
+ size_t max),
+ void *input_func_data)
+{
+ size_t cnt;
+ int first = 0;
+
+ if (s->eof)
+ return 0;
+
+ cnt = s->tok - s->bot;
+ if (cnt > 0) {
+ memmove(s->bot, s->tok, (size_t)(s->lim - s->tok));
+ s->tok = s->bot;
+ s->ptr -= cnt;
+ *cursor -= cnt;
+ s->lim -= cnt;
+ }
+ if (!s->bot)
+ first = 1;
+ if ((s->top - s->lim) < BSIZE) {
+ unsigned char *buf = yasm_xmalloc((size_t)(s->lim - s->bot) + BSIZE);
+ memcpy(buf, s->tok, (size_t)(s->lim - s->tok));
+ s->tok = buf;
+ s->ptr = &buf[s->ptr - s->bot];
+ *cursor = &buf[*cursor - s->bot];
+ s->lim = &buf[s->lim - s->bot];
+ s->top = &s->lim[BSIZE];
+ if (s->bot)
+ yasm_xfree(s->bot);
+ s->bot = buf;
+ }
+ if ((cnt = input_func(input_func_data, s->lim, BSIZE)) == 0) {
+ s->eof = &s->lim[cnt];
+ *s->eof++ = '\n';
+ }
+ s->lim += cnt;
+ return first;
+}
+
+void
+yasm_unescape_cstring(unsigned char *str, size_t *len)
+{
+ unsigned char *s = str;
+ unsigned char *o = str;
+ unsigned char t[4];
+
+ while ((size_t)(s-str)<*len) {
+ if (*s == '\\' && (size_t)(&s[1]-str)<*len) {
+ s++;
+ switch (*s) {
+ case 'b': *o = '\b'; s++; break;
+ case 'f': *o = '\f'; s++; break;
+ case 'n': *o = '\n'; s++; break;
+ case 'r': *o = '\r'; s++; break;
+ case 't': *o = '\t'; s++; break;
+ case 'x':
+ /* hex escape; grab last two digits */
+ s++;
+ while ((size_t)(&s[2]-str)<*len && isxdigit(s[0])
+ && isxdigit(s[1]) && isxdigit(s[2]))
+ s++;
+ if ((size_t)(s-str)<*len && isxdigit(*s)) {
+ t[0] = *s++;
+ t[1] = '\0';
+ t[2] = '\0';
+ if ((size_t)(s-str)<*len && isxdigit(*s))
+ t[1] = *s++;
+ *o = (unsigned char)strtoul((char *)t, NULL, 16);
+ } else
+ *o = '\0';
+ break;
+ default:
+ if (isdigit(*s)) {
+ int warn = 0;
+ /* octal escape */
+ if (*s > '7')
+ warn = 1;
+ *o = *s++ - '0';
+ if ((size_t)(s-str)<*len && isdigit(*s)) {
+ if (*s > '7')
+ warn = 1;
+ *o <<= 3;
+ *o += *s++ - '0';
+ if ((size_t)(s-str)<*len && isdigit(*s)) {
+ if (*s > '7')
+ warn = 1;
+ *o <<= 3;
+ *o += *s++ - '0';
+ }
+ }
+ if (warn)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("octal value out of range"));
+ } else
+ *o = *s++;
+ break;
+ }
+ o++;
+ } else
+ *o++ = *s++;
+ }
+ *len = o-str;
+}
+
+size_t
+yasm__splitpath_unix(const char *path, /*@out@*/ const char **tail)
+{
+ const char *s;
+ s = strrchr(path, '/');
+ if (!s) {
+ /* No head */
+ *tail = path;
+ return 0;
+ }
+ *tail = s+1;
+ /* Strip trailing ./ on path */
+ while ((s-1)>=path && *(s-1) == '.' && *s == '/'
+ && !((s-2)>=path && *(s-2) == '.'))
+ s -= 2;
+ /* Strip trailing slashes on path (except leading) */
+ while (s>path && *s == '/')
+ s--;
+ /* Return length of head */
+ return s-path+1;
+}
+
+size_t
+yasm__splitpath_win(const char *path, /*@out@*/ const char **tail)
+{
+ const char *basepath = path;
+ const char *s;
+
+ /* split off drive letter first, if any */
+ if (isalpha(path[0]) && path[1] == ':')
+ basepath += 2;
+
+ s = basepath;
+ while (*s != '\0')
+ s++;
+ while (s >= basepath && *s != '\\' && *s != '/')
+ s--;
+ if (s < basepath) {
+ *tail = basepath;
+ if (path == basepath)
+ return 0; /* No head */
+ else
+ return 2; /* Drive letter is head */
+ }
+ *tail = s+1;
+ /* Strip trailing .\ or ./ on path */
+ while ((s-1)>=basepath && *(s-1) == '.' && (*s == '/' || *s == '\\')
+ && !((s-2)>=basepath && *(s-2) == '.'))
+ s -= 2;
+ /* Strip trailing slashes on path (except leading) */
+ while (s>basepath && (*s == '/' || *s == '\\'))
+ s--;
+ /* Return length of head */
+ return s-path+1;
+}
+
+char *
+yasm__getcwd(void)
+{
+ char *buf;
+ size_t size;
+
+ size = 1024;
+ buf = yasm_xmalloc(size);
+
+ if (getenv("YASM_TEST_SUITE")) {
+ strcpy(buf, "./");
+ return buf;
+ }
+
+ while (getcwd(buf, size-1) == NULL) {
+ if (errno != ERANGE) {
+ yasm__fatal(N_("could not determine current working directory"));
+ yasm_xfree(buf);
+ return NULL;
+ }
+ size *= 2;
+ buf = yasm_xrealloc(buf, size);
+ }
+
+ /* append a '/' if not already present */
+ size = strlen(buf);
+ if (buf[size-1] != '\\' && buf[size-1] != '/') {
+ buf[size] = '/';
+ buf[size+1] = '\0';
+ }
+ return buf;
+}
+
+char *
+yasm__abspath(const char *path)
+{
+ char *curdir, *abspath;
+
+ curdir = yasm__getcwd();
+ abspath = yasm__combpath(curdir, path);
+ yasm_xfree(curdir);
+
+ return abspath;
+}
+
+char *
+yasm__combpath_unix(const char *from, const char *to)
+{
+ const char *tail;
+ size_t pathlen, i, j;
+ char *out;
+
+ if (to[0] == '/') {
+ /* absolute "to" */
+ out = yasm_xmalloc(strlen(to)+1);
+ /* Combine any double slashes when copying */
+ for (j=0; *to; to++) {
+ if (*to == '/' && *(to+1) == '/')
+ continue;
+ out[j++] = *to;
+ }
+ out[j++] = '\0';
+ return out;
+ }
+
+ /* Get path component; note this strips trailing slash */
+ pathlen = yasm__splitpath_unix(from, &tail);
+
+ out = yasm_xmalloc(pathlen+strlen(to)+2); /* worst case maximum len */
+
+ /* Combine any double slashes when copying */
+ for (i=0, j=0; i<pathlen; i++) {
+ if (i<pathlen-1 && from[i] == '/' && from[i+1] == '/')
+ continue;
+ out[j++] = from[i];
+ }
+ pathlen = j;
+
+ /* Add trailing slash back in */
+ if (pathlen > 0 && out[pathlen-1] != '/')
+ out[pathlen++] = '/';
+
+ /* Now scan from left to right through "to", stripping off "." and "..";
+ * if we see "..", back up one directory in out unless last directory in
+ * out is also "..".
+ *
+ * Note this does NOT back through ..'s in the "from" path; this is just
+ * as well as that could skip symlinks (e.g. "foo/bar/.." might not be
+ * the same as "foo").
+ */
+ for (;;) {
+ if (to[0] == '.' && to[1] == '/') {
+ to += 2; /* current directory */
+ while (*to == '/')
+ to++; /* strip off any additional slashes */
+ } else if (pathlen == 0)
+ break; /* no more "from" path left, we're done */
+ else if (to[0] == '.' && to[1] == '.' && to[2] == '/') {
+ if (pathlen >= 3 && out[pathlen-1] == '/' && out[pathlen-2] == '.'
+ && out[pathlen-3] == '.') {
+ /* can't ".." against a "..", so we're done. */
+ break;
+ }
+
+ to += 3; /* throw away "../" */
+ while (*to == '/')
+ to++; /* strip off any additional slashes */
+
+ /* and back out last directory in "out" if not already at root */
+ if (pathlen > 1) {
+ pathlen--; /* strip off trailing '/' */
+ while (pathlen > 0 && out[pathlen-1] != '/')
+ pathlen--;
+ }
+ } else
+ break;
+ }
+
+ /* Copy "to" to tail of output, and we're done */
+ /* Combine any double slashes when copying */
+ for (j=pathlen; *to; to++) {
+ if (*to == '/' && *(to+1) == '/')
+ continue;
+ out[j++] = *to;
+ }
+ out[j++] = '\0';
+
+ return out;
+}
+
+char *
+yasm__combpath_win(const char *from, const char *to)
+{
+ const char *tail;
+ size_t pathlen, i, j;
+ char *out;
+
+ if ((isalpha(to[0]) && to[1] == ':') || (to[0] == '/' || to[0] == '\\')) {
+ /* absolute or drive letter "to" */
+ out = yasm_xmalloc(strlen(to)+1);
+ /* Combine any double slashes when copying */
+ for (j=0; *to; to++) {
+ if ((*to == '/' || *to == '\\')
+ && (*(to+1) == '/' || *(to+1) == '\\'))
+ continue;
+ if (*to == '/')
+ out[j++] = '\\';
+ else
+ out[j++] = *to;
+ }
+ out[j++] = '\0';
+ return out;
+ }
+
+ /* Get path component; note this strips trailing slash */
+ pathlen = yasm__splitpath_win(from, &tail);
+
+ out = yasm_xmalloc(pathlen+strlen(to)+2); /* worst case maximum len */
+
+ /* Combine any double slashes when copying */
+ for (i=0, j=0; i<pathlen; i++) {
+ if (i<pathlen-1 && (from[i] == '/' || from[i] == '\\')
+ && (from[i+1] == '/' || from[i+1] == '\\'))
+ continue;
+ if (from[i] == '/')
+ out[j++] = '\\';
+ else
+ out[j++] = from[i];
+ }
+ pathlen = j;
+
+ /* Add trailing slash back in, unless it's only a raw drive letter */
+ if (pathlen > 0 && out[pathlen-1] != '\\'
+ && !(pathlen == 2 && isalpha(out[0]) && out[1] == ':'))
+ out[pathlen++] = '\\';
+
+ /* Now scan from left to right through "to", stripping off "." and "..";
+ * if we see "..", back up one directory in out unless last directory in
+ * out is also "..".
+ *
+ * Note this does NOT back through ..'s in the "from" path; this is just
+ * as well as that could skip symlinks (e.g. "foo/bar/.." might not be
+ * the same as "foo").
+ */
+ for (;;) {
+ if (to[0] == '.' && (to[1] == '/' || to[1] == '\\')) {
+ to += 2; /* current directory */
+ while (*to == '/' || *to == '\\')
+ to++; /* strip off any additional slashes */
+ } else if (pathlen == 0
+ || (pathlen == 2 && isalpha(out[0]) && out[1] == ':'))
+ break; /* no more "from" path left, we're done */
+ else if (to[0] == '.' && to[1] == '.'
+ && (to[2] == '/' || to[2] == '\\')) {
+ if (pathlen >= 3 && out[pathlen-1] == '\\'
+ && out[pathlen-2] == '.' && out[pathlen-3] == '.') {
+ /* can't ".." against a "..", so we're done. */
+ break;
+ }
+
+ to += 3; /* throw away "../" (or "..\") */
+ while (*to == '/' || *to == '\\')
+ to++; /* strip off any additional slashes */
+
+ /* and back out last directory in "out" if not already at root */
+ if (pathlen > 1) {
+ pathlen--; /* strip off trailing '/' */
+ while (pathlen > 0 && out[pathlen-1] != '\\')
+ pathlen--;
+ }
+ } else
+ break;
+ }
+
+ /* Copy "to" to tail of output, and we're done */
+ /* Combine any double slashes when copying */
+ for (j=pathlen; *to; to++) {
+ if ((*to == '/' || *to == '\\') && (*(to+1) == '/' || *(to+1) == '\\'))
+ continue;
+ if (*to == '/')
+ out[j++] = '\\';
+ else
+ out[j++] = *to;
+ }
+ out[j++] = '\0';
+
+ return out;
+}
+
+size_t
+yasm__createpath_common(const char *path, int win)
+{
+ const char *pp = path, *pe;
+ char *ts, *tp;
+ size_t len, lth;
+
+ lth = len = strlen(path);
+ ts = tp = (char *) malloc(len + 1);
+ pe = pp + len;
+ while (pe > pp) {
+ if ((win && *pe == '\\') || *pe == '/')
+ break;
+ --pe;
+ --lth;
+ }
+
+ while (pp <= pe) {
+ if (pp == pe || (win && *pp == '\\') || *pp == '/') {
+#ifdef _WIN32
+ struct _finddata_t fi;
+ intptr_t h;
+#elif defined(HAVE_SYS_STAT_H)
+ struct stat fi;
+#endif
+ *tp = '\0';
+
+#ifdef _WIN32
+ h = _findfirst(ts, &fi);
+ if (h != -1) {
+ if (fi.attrib != _A_SUBDIR) {
+ _findclose(h);
+ break;
+ }
+ } else if (errno == ENOENT) {
+ if (_mkdir(ts) == -1) {
+ _findclose(h);
+ lth = -1;
+ break;
+ }
+ }
+ _findclose(h);
#elif defined(HAVE_SYS_STAT_H)
- struct stat fi;
-#endif
- *tp = '\0';
-
-#ifdef _WIN32
- h = _findfirst(ts, &fi);
- if (h != -1) {
- if (fi.attrib != _A_SUBDIR) {
- _findclose(h);
- break;
- }
- } else if (errno == ENOENT) {
- if (_mkdir(ts) == -1) {
- _findclose(h);
- lth = -1;
- break;
- }
- }
- _findclose(h);
-#elif defined(HAVE_SYS_STAT_H)
- if (stat(ts, &fi) != -1) {
- if (!S_ISDIR(fi.st_mode))
- break;
- } else if (errno == ENOENT) {
- if (mkdir(ts, 0755) == -1) {
- lth = 0;
- break;
- }
- }
-#else
- break;
-#endif
- }
- *tp++ = *pp++;
- }
- free(ts);
- return lth;
-}
-
-typedef struct incpath {
- STAILQ_ENTRY(incpath) link;
- /*@owned@*/ char *path;
-} incpath;
-
-STAILQ_HEAD(incpath_head, incpath) incpaths = STAILQ_HEAD_INITIALIZER(incpaths);
-
-FILE *
-yasm_fopen_include(const char *iname, const char *from, const char *mode,
- char **oname)
-{
- FILE *f;
- char *combine;
- incpath *np;
-
- /* Try directly relative to from first, then each of the include paths */
- if (from) {
- combine = yasm__combpath(from, iname);
- f = fopen(combine, mode);
- if (f) {
- if (oname)
- *oname = combine;
- else
- yasm_xfree(combine);
- return f;
- }
- yasm_xfree(combine);
- }
-
- STAILQ_FOREACH(np, &incpaths, link) {
- combine = yasm__combpath(np->path, iname);
- f = fopen(combine, mode);
- if (f) {
- if (oname)
- *oname = combine;
- else
- yasm_xfree(combine);
- return f;
- }
- yasm_xfree(combine);
- }
-
- if (oname)
- *oname = NULL;
- return NULL;
-}
-
-void
-yasm_delete_include_paths(void)
-{
- incpath *n1, *n2;
-
- n1 = STAILQ_FIRST(&incpaths);
- while (n1) {
- n2 = STAILQ_NEXT(n1, link);
- yasm_xfree(n1->path);
- yasm_xfree(n1);
- n1 = n2;
- }
- STAILQ_INIT(&incpaths);
-}
-
-const char *
-yasm_get_include_dir(void **iter)
-{
- incpath *p = (incpath *)*iter;
-
- if (!p)
- p = STAILQ_FIRST(&incpaths);
- else
- p = STAILQ_NEXT(p, link);
-
- *iter = p;
- if (p)
- return p->path;
- else
- return NULL;
-}
-
-void
-yasm_add_include_path(const char *path)
-{
- incpath *np = yasm_xmalloc(sizeof(incpath));
- size_t len = strlen(path);
-
- np->path = yasm_xmalloc(len+2);
- memcpy(np->path, path, len+1);
- /* Add trailing slash if it is missing */
- if (path[len-1] != '\\' && path[len-1] != '/') {
- np->path[len] = '/';
- np->path[len+1] = '\0';
- }
-
- STAILQ_INSERT_TAIL(&incpaths, np, link);
-}
-
-size_t
-yasm_fwrite_16_l(unsigned short val, FILE *f)
-{
- if (fputc(val & 0xFF, f) == EOF)
- return 0;
- if (fputc((val >> 8) & 0xFF, f) == EOF)
- return 0;
- return 1;
-}
-
-size_t
-yasm_fwrite_32_l(unsigned long val, FILE *f)
-{
- if (fputc((int)(val & 0xFF), f) == EOF)
- return 0;
- if (fputc((int)((val >> 8) & 0xFF), f) == EOF)
- return 0;
- if (fputc((int)((val >> 16) & 0xFF), f) == EOF)
- return 0;
- if (fputc((int)((val >> 24) & 0xFF), f) == EOF)
- return 0;
- return 1;
-}
-
-size_t
-yasm_fwrite_16_b(unsigned short val, FILE *f)
-{
- if (fputc((val >> 8) & 0xFF, f) == EOF)
- return 0;
- if (fputc(val & 0xFF, f) == EOF)
- return 0;
- return 1;
-}
-
-size_t
-yasm_fwrite_32_b(unsigned long val, FILE *f)
-{
- if (fputc((int)((val >> 24) & 0xFF), f) == EOF)
- return 0;
- if (fputc((int)((val >> 16) & 0xFF), f) == EOF)
- return 0;
- if (fputc((int)((val >> 8) & 0xFF), f) == EOF)
- return 0;
- if (fputc((int)(val & 0xFF), f) == EOF)
- return 0;
- return 1;
-}
+ if (stat(ts, &fi) != -1) {
+ if (!S_ISDIR(fi.st_mode))
+ break;
+ } else if (errno == ENOENT) {
+ if (mkdir(ts, 0755) == -1) {
+ lth = 0;
+ break;
+ }
+ }
+#else
+ break;
+#endif
+ }
+ *tp++ = *pp++;
+ }
+ free(ts);
+ return lth;
+}
+
+typedef struct incpath {
+ STAILQ_ENTRY(incpath) link;
+ /*@owned@*/ char *path;
+} incpath;
+
+STAILQ_HEAD(incpath_head, incpath) incpaths = STAILQ_HEAD_INITIALIZER(incpaths);
+
+FILE *
+yasm_fopen_include(const char *iname, const char *from, const char *mode,
+ char **oname)
+{
+ FILE *f;
+ char *combine;
+ incpath *np;
+
+ /* Try directly relative to from first, then each of the include paths */
+ if (from) {
+ combine = yasm__combpath(from, iname);
+ f = fopen(combine, mode);
+ if (f) {
+ if (oname)
+ *oname = combine;
+ else
+ yasm_xfree(combine);
+ return f;
+ }
+ yasm_xfree(combine);
+ }
+
+ STAILQ_FOREACH(np, &incpaths, link) {
+ combine = yasm__combpath(np->path, iname);
+ f = fopen(combine, mode);
+ if (f) {
+ if (oname)
+ *oname = combine;
+ else
+ yasm_xfree(combine);
+ return f;
+ }
+ yasm_xfree(combine);
+ }
+
+ if (oname)
+ *oname = NULL;
+ return NULL;
+}
+
+void
+yasm_delete_include_paths(void)
+{
+ incpath *n1, *n2;
+
+ n1 = STAILQ_FIRST(&incpaths);
+ while (n1) {
+ n2 = STAILQ_NEXT(n1, link);
+ yasm_xfree(n1->path);
+ yasm_xfree(n1);
+ n1 = n2;
+ }
+ STAILQ_INIT(&incpaths);
+}
+
+const char *
+yasm_get_include_dir(void **iter)
+{
+ incpath *p = (incpath *)*iter;
+
+ if (!p)
+ p = STAILQ_FIRST(&incpaths);
+ else
+ p = STAILQ_NEXT(p, link);
+
+ *iter = p;
+ if (p)
+ return p->path;
+ else
+ return NULL;
+}
+
+void
+yasm_add_include_path(const char *path)
+{
+ incpath *np = yasm_xmalloc(sizeof(incpath));
+ size_t len = strlen(path);
+
+ np->path = yasm_xmalloc(len+2);
+ memcpy(np->path, path, len+1);
+ /* Add trailing slash if it is missing */
+ if (path[len-1] != '\\' && path[len-1] != '/') {
+ np->path[len] = '/';
+ np->path[len+1] = '\0';
+ }
+
+ STAILQ_INSERT_TAIL(&incpaths, np, link);
+}
+
+size_t
+yasm_fwrite_16_l(unsigned short val, FILE *f)
+{
+ if (fputc(val & 0xFF, f) == EOF)
+ return 0;
+ if (fputc((val >> 8) & 0xFF, f) == EOF)
+ return 0;
+ return 1;
+}
+
+size_t
+yasm_fwrite_32_l(unsigned long val, FILE *f)
+{
+ if (fputc((int)(val & 0xFF), f) == EOF)
+ return 0;
+ if (fputc((int)((val >> 8) & 0xFF), f) == EOF)
+ return 0;
+ if (fputc((int)((val >> 16) & 0xFF), f) == EOF)
+ return 0;
+ if (fputc((int)((val >> 24) & 0xFF), f) == EOF)
+ return 0;
+ return 1;
+}
+
+size_t
+yasm_fwrite_16_b(unsigned short val, FILE *f)
+{
+ if (fputc((val >> 8) & 0xFF, f) == EOF)
+ return 0;
+ if (fputc(val & 0xFF, f) == EOF)
+ return 0;
+ return 1;
+}
+
+size_t
+yasm_fwrite_32_b(unsigned long val, FILE *f)
+{
+ if (fputc((int)((val >> 24) & 0xFF), f) == EOF)
+ return 0;
+ if (fputc((int)((val >> 16) & 0xFF), f) == EOF)
+ return 0;
+ if (fputc((int)((val >> 8) & 0xFF), f) == EOF)
+ return 0;
+ if (fputc((int)(val & 0xFF), f) == EOF)
+ return 0;
+ return 1;
+}
diff --git a/contrib/tools/yasm/libyasm/file.h b/contrib/tools/yasm/libyasm/file.h
index 1e9b87b0d5..01bca80cdc 100644
--- a/contrib/tools/yasm/libyasm/file.h
+++ b/contrib/tools/yasm/libyasm/file.h
@@ -1,525 +1,525 @@
-/**
- * \file libyasm/file.h
- * \brief YASM file helpers.
- *
- * \license
- * Copyright (C) 2001-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- * \endlicense
- */
-#ifndef YASM_FILE_H
-#define YASM_FILE_H
-
-#ifndef YASM_LIB_DECL
-#define YASM_LIB_DECL
-#endif
-
-/** Re2c scanner state. */
-typedef struct yasm_scanner {
- unsigned char *bot; /**< Bottom of scan buffer */
- unsigned char *tok; /**< Start of token */
- unsigned char *ptr; /**< Scan marker */
- unsigned char *cur; /**< Cursor (1 past end of token) */
- unsigned char *lim; /**< Limit of good data */
- unsigned char *top; /**< Top of scan buffer */
- unsigned char *eof; /**< End of file */
-} yasm_scanner;
-
-/** Initialize scanner state.
- * \param scanner Re2c scanner state
- */
-YASM_LIB_DECL
-void yasm_scanner_initialize(yasm_scanner *scanner);
-
-/** Frees any memory used by scanner state; does not free state itself.
- * \param scanner Re2c scanner state
- */
-YASM_LIB_DECL
-void yasm_scanner_delete(yasm_scanner *scanner);
-
-/** Fill a scanner state structure with data coming from an input function.
- * \param scanner Re2c scanner state
- * \param cursor Re2c scan cursor
- * \param input_func Input function to read data; takes buffer and maximum
- * number of bytes, returns number of bytes read.
- * \param input_func_data Data to pass as the first parameter to input_func
- * \return 1 if this was the first time this function was called on this
- * scanner state, 0 otherwise.
- */
-YASM_LIB_DECL
-int yasm_fill_helper
- (yasm_scanner *scanner, unsigned char **cursor,
- size_t (*input_func) (void *d, unsigned char *buf, size_t max),
- void *input_func_data);
-
-/** Unescape a string with C-style escapes. Handles b, f, n, r, t, and hex
- * and octal escapes. String is updated in-place.
- * Edge cases:
- * - hex escapes: reads as many hex digits as possible, takes last 2 as value.
- * - oct escapes: takes up to 3 digits 0-9 and scales appropriately, with
- * warning.
- * \param str C-style string (updated in place)
- * \param len length of string (updated with new length)
- */
-YASM_LIB_DECL
-void yasm_unescape_cstring(unsigned char *str, size_t *len);
-
-/** Split a UNIX pathname into head (directory) and tail (base filename)
- * portions.
- * \internal
- * \param path pathname
- * \param tail (returned) base filename
- * \return Length of head (directory).
- */
-YASM_LIB_DECL
-size_t yasm__splitpath_unix(const char *path, /*@out@*/ const char **tail);
-
-/** Split a Windows pathname into head (directory) and tail (base filename)
- * portions.
- * \internal
- * \param path pathname
- * \param tail (returned) base filename
- * \return Length of head (directory).
- */
-YASM_LIB_DECL
-size_t yasm__splitpath_win(const char *path, /*@out@*/ const char **tail);
-
-/** Split a pathname into head (directory) and tail (base filename) portions.
- * Unless otherwise defined, defaults to yasm__splitpath_unix().
- * \internal
- * \param path pathname
- * \param tail (returned) base filename
- * \return Length of head (directory).
- */
-#ifndef yasm__splitpath
-# if defined (_WIN32) || defined (WIN32) || defined (__MSDOS__) || \
- defined (__DJGPP__) || defined (__OS2__)
-# define yasm__splitpath(path, tail) yasm__splitpath_win(path, tail)
-# else
-# define yasm__splitpath(path, tail) yasm__splitpath_unix(path, tail)
-# endif
-#endif
-
-/** Get the current working directory.
- * \internal
- * \return Current working directory pathname (newly allocated).
- */
-YASM_LIB_DECL
-/*@only@*/ char *yasm__getcwd(void);
-
-/** Convert a relative or absolute pathname into an absolute pathname.
- * \internal
- * \param path pathname
- * \return Absolute version of path (newly allocated).
- */
-YASM_LIB_DECL
-/*@only@*/ char *yasm__abspath(const char *path);
-
-/** Build a UNIX pathname that is equivalent to accessing the "to" pathname
- * when you're in the directory containing "from". Result is relative if both
- * from and to are relative.
- * \internal
- * \param from from pathname
- * \param to to pathname
- * \return Combined path (newly allocated).
- */
-YASM_LIB_DECL
-char *yasm__combpath_unix(const char *from, const char *to);
-
-/** Build a Windows pathname that is equivalent to accessing the "to" pathname
- * when you're in the directory containing "from". Result is relative if both
- * from and to are relative.
- * \internal
- * \param from from pathname
- * \param to to pathname
- * \return Combined path (newly allocated).
- */
-YASM_LIB_DECL
-char *yasm__combpath_win(const char *from, const char *to);
-
-/** Build a pathname that is equivalent to accessing the "to" pathname
- * when you're in the directory containing "from". Result is relative if both
- * from and to are relative.
- * Unless otherwise defined, defaults to yasm__combpath_unix().
- * \internal
- * \param from from pathname
- * \param to to pathname
- * \return Combined path (newly allocated).
- */
-#ifndef yasm__combpath
-# if defined (_WIN32) || defined (WIN32) || defined (__MSDOS__) || \
- defined (__DJGPP__) || defined (__OS2__)
-# define yasm__combpath(from, to) yasm__combpath_win(from, to)
-# else
-# define yasm__combpath(from, to) yasm__combpath_unix(from, to)
-# endif
-#endif
-
-/** Recursively create tree of directories needed for pathname.
- * \internal
- * \param path pathname
- * \param win handle windows paths
- * \return Length of directory portion of pathname.
- */
-YASM_LIB_DECL
-size_t yasm__createpath_common(const char *path, int win);
-
-/** Recursively create tree of directories needed for pathname.
- * Unless otherwise defined, defaults to yasm__createpath_unix().
- * \internal
- * \param path pathname
- * \return Length of directory portion of pathname.
- */
-#ifndef yasm__createpath
-# if defined (_WIN32) || defined (WIN32) || defined (__MSDOS__) || \
- defined (__DJGPP__) || defined (__OS2__)
-# define yasm__createpath(path) yasm__createpath_common(path, 1)
-# else
-# define yasm__createpath(path) yasm__createpath_common(path, 0)
-# endif
-#endif
-
-/** Try to find and open an include file, searching through include paths.
- * First iname is looked for relative to the directory containing "from", then
- * it's looked for relative to each of the include paths.
- *
- * All pathnames may be either absolute or relative; from, oname, and
- * include paths, if relative, are relative from the current working directory.
- *
- * First match wins; the full pathname (newly allocated) to the opened file
- * is saved into oname, and the fopen'ed FILE * is returned. If not found,
- * NULL is returned.
- *
- * \param iname file to include
- * \param from file doing the including
- * \param mode fopen mode string
- * \param oname full pathname of included file (may be relative). NULL
- * may be passed if this is unwanted.
- * \return fopen'ed include file, or NULL if not found.
- */
-YASM_LIB_DECL
-/*@null@*/ FILE *yasm_fopen_include
- (const char *iname, const char *from, const char *mode,
- /*@null@*/ /*@out@*/ /*@only@*/ char **oname);
-
-/** Delete any stored include paths added by yasm_add_include_path().
- */
-YASM_LIB_DECL
-void yasm_delete_include_paths(void);
-
-/** Iterate through include paths.
-*/
-YASM_LIB_DECL
-const char * yasm_get_include_dir(void **iter);
-
-/** Add an include path for use by yasm_fopen_include().
- * If path is relative, it is treated by yasm_fopen_include() as relative to
- * the current working directory.
- *
- * \param path path to add
- */
-YASM_LIB_DECL
-void yasm_add_include_path(const char *path);
-
-/** Write an 8-bit value to a buffer, incrementing buffer pointer.
- * \note Only works properly if ptr is an (unsigned char *).
- * \param ptr buffer
- * \param val 8-bit value
- */
-#define YASM_WRITE_8(ptr, val) \
- *((ptr)++) = (unsigned char)((val) & 0xFF)
-
-/** Write a 16-bit value to a buffer in little endian, incrementing buffer
- * pointer.
- * \note Only works properly if ptr is an (unsigned char *).
- * \param ptr buffer
- * \param val 16-bit value
- */
-#define YASM_WRITE_16_L(ptr, val) \
- do { \
- *((ptr)++) = (unsigned char)((val) & 0xFF); \
- *((ptr)++) = (unsigned char)(((val) >> 8) & 0xFF); \
- } while (0)
-
-/** Write a 32-bit value to a buffer in little endian, incrementing buffer
- * pointer.
- * \note Only works properly if ptr is an (unsigned char *).
- * \param ptr buffer
- * \param val 32-bit value
- */
-#define YASM_WRITE_32_L(ptr, val) \
- do { \
- *((ptr)++) = (unsigned char)((val) & 0xFF); \
- *((ptr)++) = (unsigned char)(((val) >> 8) & 0xFF); \
- *((ptr)++) = (unsigned char)(((val) >> 16) & 0xFF); \
- *((ptr)++) = (unsigned char)(((val) >> 24) & 0xFF); \
- } while (0)
-
-/** Write a 16-bit value to a buffer in big endian, incrementing buffer
- * pointer.
- * \note Only works properly if ptr is an (unsigned char *).
- * \param ptr buffer
- * \param val 16-bit value
- */
-#define YASM_WRITE_16_B(ptr, val) \
- do { \
- *((ptr)++) = (unsigned char)(((val) >> 8) & 0xFF); \
- *((ptr)++) = (unsigned char)((val) & 0xFF); \
- } while (0)
-
-/** Write a 32-bit value to a buffer in big endian, incrementing buffer
- * pointer.
- * \note Only works properly if ptr is an (unsigned char *).
- * \param ptr buffer
- * \param val 32-bit value
- */
-#define YASM_WRITE_32_B(ptr, val) \
- do { \
- *((ptr)++) = (unsigned char)(((val) >> 24) & 0xFF); \
- *((ptr)++) = (unsigned char)(((val) >> 16) & 0xFF); \
- *((ptr)++) = (unsigned char)(((val) >> 8) & 0xFF); \
- *((ptr)++) = (unsigned char)((val) & 0xFF); \
- } while (0)
-
-
-/** Write an 8-bit value to a buffer. Does not increment buffer pointer.
- * \note Only works properly if ptr is an (unsigned char *).
- * \param ptr buffer
- * \param val 8-bit value
- */
-#define YASM_SAVE_8(ptr, val) \
- *(ptr) = (unsigned char)((val) & 0xFF)
-
-/** Write a 16-bit value to a buffer in little endian. Does not increment
- * buffer pointer.
- * \note Only works properly if ptr is an (unsigned char *).
- * \param ptr buffer
- * \param val 16-bit value
- */
-#define YASM_SAVE_16_L(ptr, val) \
- do { \
- *(ptr) = (unsigned char)((val) & 0xFF); \
- *((ptr)+1) = (unsigned char)(((val) >> 8) & 0xFF); \
- } while (0)
-
-/** Write a 32-bit value to a buffer in little endian. Does not increment
- * buffer pointer.
- * \note Only works properly if ptr is an (unsigned char *).
- * \param ptr buffer
- * \param val 32-bit value
- */
-#define YASM_SAVE_32_L(ptr, val) \
- do { \
- *(ptr) = (unsigned char)((val) & 0xFF); \
- *((ptr)+1) = (unsigned char)(((val) >> 8) & 0xFF); \
- *((ptr)+2) = (unsigned char)(((val) >> 16) & 0xFF); \
- *((ptr)+3) = (unsigned char)(((val) >> 24) & 0xFF); \
- } while (0)
-
-/** Write a 16-bit value to a buffer in big endian. Does not increment buffer
- * pointer.
- * \note Only works properly if ptr is an (unsigned char *).
- * \param ptr buffer
- * \param val 16-bit value
- */
-#define YASM_SAVE_16_B(ptr, val) \
- do { \
- *(ptr) = (unsigned char)(((val) >> 8) & 0xFF); \
- *((ptr)+1) = (unsigned char)((val) & 0xFF); \
- } while (0)
-
-/** Write a 32-bit value to a buffer in big endian. Does not increment buffer
- * pointer.
- * \note Only works properly if ptr is an (unsigned char *).
- * \param ptr buffer
- * \param val 32-bit value
- */
-#define YASM_SAVE_32_B(ptr, val) \
- do { \
- *(ptr) = (unsigned char)(((val) >> 24) & 0xFF); \
- *((ptr)+1) = (unsigned char)(((val) >> 16) & 0xFF); \
- *((ptr)+2) = (unsigned char)(((val) >> 8) & 0xFF); \
- *((ptr)+3) = (unsigned char)((val) & 0xFF); \
- } while (0)
-
-/** Direct-to-file version of YASM_SAVE_16_L().
- * \note Using the macro multiple times with a single fwrite() call will
- * probably be faster than calling this function many times.
- * \param val 16-bit value
- * \param f file
- * \return 1 if the write was successful, 0 if not (just like fwrite()).
- */
-YASM_LIB_DECL
-size_t yasm_fwrite_16_l(unsigned short val, FILE *f);
-
-/** Direct-to-file version of YASM_SAVE_32_L().
- * \note Using the macro multiple times with a single fwrite() call will
- * probably be faster than calling this function many times.
- * \param val 32-bit value
- * \param f file
- * \return 1 if the write was successful, 0 if not (just like fwrite()).
- */
-YASM_LIB_DECL
-size_t yasm_fwrite_32_l(unsigned long val, FILE *f);
-
-/** Direct-to-file version of YASM_SAVE_16_B().
- * \note Using the macro multiple times with a single fwrite() call will
- * probably be faster than calling this function many times.
- * \param val 16-bit value
- * \param f file
- * \return 1 if the write was successful, 0 if not (just like fwrite()).
- */
-YASM_LIB_DECL
-size_t yasm_fwrite_16_b(unsigned short val, FILE *f);
-
-/** Direct-to-file version of YASM_SAVE_32_B().
- * \note Using the macro multiple times with a single fwrite() call will
- * probably be faster than calling this function many times.
- * \param val 32-bit value
- * \param f file
- * \return 1 if the write was successful, 0 if not (just like fwrite()).
- */
-YASM_LIB_DECL
-size_t yasm_fwrite_32_b(unsigned long val, FILE *f);
-
-/** Read an 8-bit value from a buffer, incrementing buffer pointer.
- * \note Only works properly if ptr is an (unsigned char *).
- * \param ptr buffer
- * \param val 8-bit value
- */
-#define YASM_READ_8(val, ptr) \
- (val) = *((ptr)++) & 0xFF
-
-/** Read a 16-bit value from a buffer in little endian, incrementing buffer
- * pointer.
- * \note Only works properly if ptr is an (unsigned char *).
- * \param ptr buffer
- * \param val 16-bit value
- */
-#define YASM_READ_16_L(val, ptr) \
- do { \
- (val) = *((ptr)++) & 0xFF; \
- (val) |= (*((ptr)++) & 0xFF) << 8; \
- } while (0)
-
-/** Read a 32-bit value from a buffer in little endian, incrementing buffer
- * pointer.
- * \note Only works properly if ptr is an (unsigned char *).
- * \param ptr buffer
- * \param val 32-bit value
- */
-#define YASM_READ_32_L(val, ptr) \
- do { \
- (val) = *((ptr)++) & 0xFF; \
- (val) |= (*((ptr)++) & 0xFF) << 8; \
- (val) |= (*((ptr)++) & 0xFF) << 16; \
- (val) |= (*((ptr)++) & 0xFF) << 24; \
- } while (0)
-
-/** Read a 16-bit value from a buffer in big endian, incrementing buffer
- * pointer.
- * \note Only works properly if ptr is an (unsigned char *).
- * \param ptr buffer
- * \param val 16-bit value
- */
-#define YASM_READ_16_B(val, ptr) \
- do { \
- (val) = (*((ptr)++) & 0xFF) << 8; \
- (val) |= *((ptr)++) & 0xFF; \
- } while (0)
-
-/** Read a 32-bit value from a buffer in big endian, incrementing buffer
- * pointer.
- * \note Only works properly if ptr is an (unsigned char *).
- * \param ptr buffer
- * \param val 32-bit value
- */
-#define YASM_READ_32_B(val, ptr) \
- do { \
- (val) = (*((ptr)++) & 0xFF) << 24; \
- (val) |= (*((ptr)++) & 0xFF) << 16; \
- (val) |= (*((ptr)++) & 0xFF) << 8; \
- (val) |= *((ptr)++) & 0xFF; \
- } while (0)
-
-/** Read an 8-bit value from a buffer. Does not increment buffer pointer.
- * \note Only works properly if ptr is an (unsigned char *).
- * \param ptr buffer
- * \param val 8-bit value
- */
-#define YASM_LOAD_8(val, ptr) \
- (val) = *(ptr) & 0xFF
-
-/** Read a 16-bit value from a buffer in little endian. Does not increment
- * buffer pointer.
- * \note Only works properly if ptr is an (unsigned char *).
- * \param ptr buffer
- * \param val 16-bit value
- */
-#define YASM_LOAD_16_L(val, ptr) \
- do { \
- (val) = *(ptr) & 0xFF; \
- (val) |= (*((ptr)+1) & 0xFF) << 8; \
- } while (0)
-
-/** Read a 32-bit value from a buffer in little endian. Does not increment
- * buffer pointer.
- * \note Only works properly if ptr is an (unsigned char *).
- * \param ptr buffer
- * \param val 32-bit value
- */
-#define YASM_LOAD_32_L(val, ptr) \
- do { \
- (val) = (unsigned long)(*(ptr) & 0xFF); \
- (val) |= (unsigned long)((*((ptr)+1) & 0xFF) << 8); \
- (val) |= (unsigned long)((*((ptr)+2) & 0xFF) << 16); \
- (val) |= (unsigned long)((*((ptr)+3) & 0xFF) << 24); \
- } while (0)
-
-/** Read a 16-bit value from a buffer in big endian. Does not increment buffer
- * pointer.
- * \note Only works properly if ptr is an (unsigned char *).
- * \param ptr buffer
- * \param val 16-bit value
- */
-#define YASM_LOAD_16_B(val, ptr) \
- do { \
- (val) = (*(ptr) & 0xFF) << 8; \
- (val) |= *((ptr)+1) & 0xFF; \
- } while (0)
-
-/** Read a 32-bit value from a buffer in big endian. Does not increment buffer
- * pointer.
- * \note Only works properly if ptr is an (unsigned char *).
- * \param ptr buffer
- * \param val 32-bit value
- */
-#define YASM_LOAD_32_B(val, ptr) \
- do { \
- (val) = (unsigned long)((*(ptr) & 0xFF) << 24); \
- (val) |= (unsigned long)((*((ptr)+1) & 0xFF) << 16); \
- (val) |= (unsigned long)((*((ptr)+2) & 0xFF) << 8); \
- (val) |= (unsigned long)(*((ptr)+3) & 0xFF); \
- } while (0)
-
-#endif
+/**
+ * \file libyasm/file.h
+ * \brief YASM file helpers.
+ *
+ * \license
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * \endlicense
+ */
+#ifndef YASM_FILE_H
+#define YASM_FILE_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/** Re2c scanner state. */
+typedef struct yasm_scanner {
+ unsigned char *bot; /**< Bottom of scan buffer */
+ unsigned char *tok; /**< Start of token */
+ unsigned char *ptr; /**< Scan marker */
+ unsigned char *cur; /**< Cursor (1 past end of token) */
+ unsigned char *lim; /**< Limit of good data */
+ unsigned char *top; /**< Top of scan buffer */
+ unsigned char *eof; /**< End of file */
+} yasm_scanner;
+
+/** Initialize scanner state.
+ * \param scanner Re2c scanner state
+ */
+YASM_LIB_DECL
+void yasm_scanner_initialize(yasm_scanner *scanner);
+
+/** Frees any memory used by scanner state; does not free state itself.
+ * \param scanner Re2c scanner state
+ */
+YASM_LIB_DECL
+void yasm_scanner_delete(yasm_scanner *scanner);
+
+/** Fill a scanner state structure with data coming from an input function.
+ * \param scanner Re2c scanner state
+ * \param cursor Re2c scan cursor
+ * \param input_func Input function to read data; takes buffer and maximum
+ * number of bytes, returns number of bytes read.
+ * \param input_func_data Data to pass as the first parameter to input_func
+ * \return 1 if this was the first time this function was called on this
+ * scanner state, 0 otherwise.
+ */
+YASM_LIB_DECL
+int yasm_fill_helper
+ (yasm_scanner *scanner, unsigned char **cursor,
+ size_t (*input_func) (void *d, unsigned char *buf, size_t max),
+ void *input_func_data);
+
+/** Unescape a string with C-style escapes. Handles b, f, n, r, t, and hex
+ * and octal escapes. String is updated in-place.
+ * Edge cases:
+ * - hex escapes: reads as many hex digits as possible, takes last 2 as value.
+ * - oct escapes: takes up to 3 digits 0-9 and scales appropriately, with
+ * warning.
+ * \param str C-style string (updated in place)
+ * \param len length of string (updated with new length)
+ */
+YASM_LIB_DECL
+void yasm_unescape_cstring(unsigned char *str, size_t *len);
+
+/** Split a UNIX pathname into head (directory) and tail (base filename)
+ * portions.
+ * \internal
+ * \param path pathname
+ * \param tail (returned) base filename
+ * \return Length of head (directory).
+ */
+YASM_LIB_DECL
+size_t yasm__splitpath_unix(const char *path, /*@out@*/ const char **tail);
+
+/** Split a Windows pathname into head (directory) and tail (base filename)
+ * portions.
+ * \internal
+ * \param path pathname
+ * \param tail (returned) base filename
+ * \return Length of head (directory).
+ */
+YASM_LIB_DECL
+size_t yasm__splitpath_win(const char *path, /*@out@*/ const char **tail);
+
+/** Split a pathname into head (directory) and tail (base filename) portions.
+ * Unless otherwise defined, defaults to yasm__splitpath_unix().
+ * \internal
+ * \param path pathname
+ * \param tail (returned) base filename
+ * \return Length of head (directory).
+ */
+#ifndef yasm__splitpath
+# if defined (_WIN32) || defined (WIN32) || defined (__MSDOS__) || \
+ defined (__DJGPP__) || defined (__OS2__)
+# define yasm__splitpath(path, tail) yasm__splitpath_win(path, tail)
+# else
+# define yasm__splitpath(path, tail) yasm__splitpath_unix(path, tail)
+# endif
+#endif
+
+/** Get the current working directory.
+ * \internal
+ * \return Current working directory pathname (newly allocated).
+ */
+YASM_LIB_DECL
+/*@only@*/ char *yasm__getcwd(void);
+
+/** Convert a relative or absolute pathname into an absolute pathname.
+ * \internal
+ * \param path pathname
+ * \return Absolute version of path (newly allocated).
+ */
+YASM_LIB_DECL
+/*@only@*/ char *yasm__abspath(const char *path);
+
+/** Build a UNIX pathname that is equivalent to accessing the "to" pathname
+ * when you're in the directory containing "from". Result is relative if both
+ * from and to are relative.
+ * \internal
+ * \param from from pathname
+ * \param to to pathname
+ * \return Combined path (newly allocated).
+ */
+YASM_LIB_DECL
+char *yasm__combpath_unix(const char *from, const char *to);
+
+/** Build a Windows pathname that is equivalent to accessing the "to" pathname
+ * when you're in the directory containing "from". Result is relative if both
+ * from and to are relative.
+ * \internal
+ * \param from from pathname
+ * \param to to pathname
+ * \return Combined path (newly allocated).
+ */
+YASM_LIB_DECL
+char *yasm__combpath_win(const char *from, const char *to);
+
+/** Build a pathname that is equivalent to accessing the "to" pathname
+ * when you're in the directory containing "from". Result is relative if both
+ * from and to are relative.
+ * Unless otherwise defined, defaults to yasm__combpath_unix().
+ * \internal
+ * \param from from pathname
+ * \param to to pathname
+ * \return Combined path (newly allocated).
+ */
+#ifndef yasm__combpath
+# if defined (_WIN32) || defined (WIN32) || defined (__MSDOS__) || \
+ defined (__DJGPP__) || defined (__OS2__)
+# define yasm__combpath(from, to) yasm__combpath_win(from, to)
+# else
+# define yasm__combpath(from, to) yasm__combpath_unix(from, to)
+# endif
+#endif
+
+/** Recursively create tree of directories needed for pathname.
+ * \internal
+ * \param path pathname
+ * \param win handle windows paths
+ * \return Length of directory portion of pathname.
+ */
+YASM_LIB_DECL
+size_t yasm__createpath_common(const char *path, int win);
+
+/** Recursively create tree of directories needed for pathname.
+ * Unless otherwise defined, defaults to yasm__createpath_unix().
+ * \internal
+ * \param path pathname
+ * \return Length of directory portion of pathname.
+ */
+#ifndef yasm__createpath
+# if defined (_WIN32) || defined (WIN32) || defined (__MSDOS__) || \
+ defined (__DJGPP__) || defined (__OS2__)
+# define yasm__createpath(path) yasm__createpath_common(path, 1)
+# else
+# define yasm__createpath(path) yasm__createpath_common(path, 0)
+# endif
+#endif
+
+/** Try to find and open an include file, searching through include paths.
+ * First iname is looked for relative to the directory containing "from", then
+ * it's looked for relative to each of the include paths.
+ *
+ * All pathnames may be either absolute or relative; from, oname, and
+ * include paths, if relative, are relative from the current working directory.
+ *
+ * First match wins; the full pathname (newly allocated) to the opened file
+ * is saved into oname, and the fopen'ed FILE * is returned. If not found,
+ * NULL is returned.
+ *
+ * \param iname file to include
+ * \param from file doing the including
+ * \param mode fopen mode string
+ * \param oname full pathname of included file (may be relative). NULL
+ * may be passed if this is unwanted.
+ * \return fopen'ed include file, or NULL if not found.
+ */
+YASM_LIB_DECL
+/*@null@*/ FILE *yasm_fopen_include
+ (const char *iname, const char *from, const char *mode,
+ /*@null@*/ /*@out@*/ /*@only@*/ char **oname);
+
+/** Delete any stored include paths added by yasm_add_include_path().
+ */
+YASM_LIB_DECL
+void yasm_delete_include_paths(void);
+
+/** Iterate through include paths.
+*/
+YASM_LIB_DECL
+const char * yasm_get_include_dir(void **iter);
+
+/** Add an include path for use by yasm_fopen_include().
+ * If path is relative, it is treated by yasm_fopen_include() as relative to
+ * the current working directory.
+ *
+ * \param path path to add
+ */
+YASM_LIB_DECL
+void yasm_add_include_path(const char *path);
+
+/** Write an 8-bit value to a buffer, incrementing buffer pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 8-bit value
+ */
+#define YASM_WRITE_8(ptr, val) \
+ *((ptr)++) = (unsigned char)((val) & 0xFF)
+
+/** Write a 16-bit value to a buffer in little endian, incrementing buffer
+ * pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 16-bit value
+ */
+#define YASM_WRITE_16_L(ptr, val) \
+ do { \
+ *((ptr)++) = (unsigned char)((val) & 0xFF); \
+ *((ptr)++) = (unsigned char)(((val) >> 8) & 0xFF); \
+ } while (0)
+
+/** Write a 32-bit value to a buffer in little endian, incrementing buffer
+ * pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 32-bit value
+ */
+#define YASM_WRITE_32_L(ptr, val) \
+ do { \
+ *((ptr)++) = (unsigned char)((val) & 0xFF); \
+ *((ptr)++) = (unsigned char)(((val) >> 8) & 0xFF); \
+ *((ptr)++) = (unsigned char)(((val) >> 16) & 0xFF); \
+ *((ptr)++) = (unsigned char)(((val) >> 24) & 0xFF); \
+ } while (0)
+
+/** Write a 16-bit value to a buffer in big endian, incrementing buffer
+ * pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 16-bit value
+ */
+#define YASM_WRITE_16_B(ptr, val) \
+ do { \
+ *((ptr)++) = (unsigned char)(((val) >> 8) & 0xFF); \
+ *((ptr)++) = (unsigned char)((val) & 0xFF); \
+ } while (0)
+
+/** Write a 32-bit value to a buffer in big endian, incrementing buffer
+ * pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 32-bit value
+ */
+#define YASM_WRITE_32_B(ptr, val) \
+ do { \
+ *((ptr)++) = (unsigned char)(((val) >> 24) & 0xFF); \
+ *((ptr)++) = (unsigned char)(((val) >> 16) & 0xFF); \
+ *((ptr)++) = (unsigned char)(((val) >> 8) & 0xFF); \
+ *((ptr)++) = (unsigned char)((val) & 0xFF); \
+ } while (0)
+
+
+/** Write an 8-bit value to a buffer. Does not increment buffer pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 8-bit value
+ */
+#define YASM_SAVE_8(ptr, val) \
+ *(ptr) = (unsigned char)((val) & 0xFF)
+
+/** Write a 16-bit value to a buffer in little endian. Does not increment
+ * buffer pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 16-bit value
+ */
+#define YASM_SAVE_16_L(ptr, val) \
+ do { \
+ *(ptr) = (unsigned char)((val) & 0xFF); \
+ *((ptr)+1) = (unsigned char)(((val) >> 8) & 0xFF); \
+ } while (0)
+
+/** Write a 32-bit value to a buffer in little endian. Does not increment
+ * buffer pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 32-bit value
+ */
+#define YASM_SAVE_32_L(ptr, val) \
+ do { \
+ *(ptr) = (unsigned char)((val) & 0xFF); \
+ *((ptr)+1) = (unsigned char)(((val) >> 8) & 0xFF); \
+ *((ptr)+2) = (unsigned char)(((val) >> 16) & 0xFF); \
+ *((ptr)+3) = (unsigned char)(((val) >> 24) & 0xFF); \
+ } while (0)
+
+/** Write a 16-bit value to a buffer in big endian. Does not increment buffer
+ * pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 16-bit value
+ */
+#define YASM_SAVE_16_B(ptr, val) \
+ do { \
+ *(ptr) = (unsigned char)(((val) >> 8) & 0xFF); \
+ *((ptr)+1) = (unsigned char)((val) & 0xFF); \
+ } while (0)
+
+/** Write a 32-bit value to a buffer in big endian. Does not increment buffer
+ * pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 32-bit value
+ */
+#define YASM_SAVE_32_B(ptr, val) \
+ do { \
+ *(ptr) = (unsigned char)(((val) >> 24) & 0xFF); \
+ *((ptr)+1) = (unsigned char)(((val) >> 16) & 0xFF); \
+ *((ptr)+2) = (unsigned char)(((val) >> 8) & 0xFF); \
+ *((ptr)+3) = (unsigned char)((val) & 0xFF); \
+ } while (0)
+
+/** Direct-to-file version of YASM_SAVE_16_L().
+ * \note Using the macro multiple times with a single fwrite() call will
+ * probably be faster than calling this function many times.
+ * \param val 16-bit value
+ * \param f file
+ * \return 1 if the write was successful, 0 if not (just like fwrite()).
+ */
+YASM_LIB_DECL
+size_t yasm_fwrite_16_l(unsigned short val, FILE *f);
+
+/** Direct-to-file version of YASM_SAVE_32_L().
+ * \note Using the macro multiple times with a single fwrite() call will
+ * probably be faster than calling this function many times.
+ * \param val 32-bit value
+ * \param f file
+ * \return 1 if the write was successful, 0 if not (just like fwrite()).
+ */
+YASM_LIB_DECL
+size_t yasm_fwrite_32_l(unsigned long val, FILE *f);
+
+/** Direct-to-file version of YASM_SAVE_16_B().
+ * \note Using the macro multiple times with a single fwrite() call will
+ * probably be faster than calling this function many times.
+ * \param val 16-bit value
+ * \param f file
+ * \return 1 if the write was successful, 0 if not (just like fwrite()).
+ */
+YASM_LIB_DECL
+size_t yasm_fwrite_16_b(unsigned short val, FILE *f);
+
+/** Direct-to-file version of YASM_SAVE_32_B().
+ * \note Using the macro multiple times with a single fwrite() call will
+ * probably be faster than calling this function many times.
+ * \param val 32-bit value
+ * \param f file
+ * \return 1 if the write was successful, 0 if not (just like fwrite()).
+ */
+YASM_LIB_DECL
+size_t yasm_fwrite_32_b(unsigned long val, FILE *f);
+
+/** Read an 8-bit value from a buffer, incrementing buffer pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 8-bit value
+ */
+#define YASM_READ_8(val, ptr) \
+ (val) = *((ptr)++) & 0xFF
+
+/** Read a 16-bit value from a buffer in little endian, incrementing buffer
+ * pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 16-bit value
+ */
+#define YASM_READ_16_L(val, ptr) \
+ do { \
+ (val) = *((ptr)++) & 0xFF; \
+ (val) |= (*((ptr)++) & 0xFF) << 8; \
+ } while (0)
+
+/** Read a 32-bit value from a buffer in little endian, incrementing buffer
+ * pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 32-bit value
+ */
+#define YASM_READ_32_L(val, ptr) \
+ do { \
+ (val) = *((ptr)++) & 0xFF; \
+ (val) |= (*((ptr)++) & 0xFF) << 8; \
+ (val) |= (*((ptr)++) & 0xFF) << 16; \
+ (val) |= (*((ptr)++) & 0xFF) << 24; \
+ } while (0)
+
+/** Read a 16-bit value from a buffer in big endian, incrementing buffer
+ * pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 16-bit value
+ */
+#define YASM_READ_16_B(val, ptr) \
+ do { \
+ (val) = (*((ptr)++) & 0xFF) << 8; \
+ (val) |= *((ptr)++) & 0xFF; \
+ } while (0)
+
+/** Read a 32-bit value from a buffer in big endian, incrementing buffer
+ * pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 32-bit value
+ */
+#define YASM_READ_32_B(val, ptr) \
+ do { \
+ (val) = (*((ptr)++) & 0xFF) << 24; \
+ (val) |= (*((ptr)++) & 0xFF) << 16; \
+ (val) |= (*((ptr)++) & 0xFF) << 8; \
+ (val) |= *((ptr)++) & 0xFF; \
+ } while (0)
+
+/** Read an 8-bit value from a buffer. Does not increment buffer pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 8-bit value
+ */
+#define YASM_LOAD_8(val, ptr) \
+ (val) = *(ptr) & 0xFF
+
+/** Read a 16-bit value from a buffer in little endian. Does not increment
+ * buffer pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 16-bit value
+ */
+#define YASM_LOAD_16_L(val, ptr) \
+ do { \
+ (val) = *(ptr) & 0xFF; \
+ (val) |= (*((ptr)+1) & 0xFF) << 8; \
+ } while (0)
+
+/** Read a 32-bit value from a buffer in little endian. Does not increment
+ * buffer pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 32-bit value
+ */
+#define YASM_LOAD_32_L(val, ptr) \
+ do { \
+ (val) = (unsigned long)(*(ptr) & 0xFF); \
+ (val) |= (unsigned long)((*((ptr)+1) & 0xFF) << 8); \
+ (val) |= (unsigned long)((*((ptr)+2) & 0xFF) << 16); \
+ (val) |= (unsigned long)((*((ptr)+3) & 0xFF) << 24); \
+ } while (0)
+
+/** Read a 16-bit value from a buffer in big endian. Does not increment buffer
+ * pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 16-bit value
+ */
+#define YASM_LOAD_16_B(val, ptr) \
+ do { \
+ (val) = (*(ptr) & 0xFF) << 8; \
+ (val) |= *((ptr)+1) & 0xFF; \
+ } while (0)
+
+/** Read a 32-bit value from a buffer in big endian. Does not increment buffer
+ * pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 32-bit value
+ */
+#define YASM_LOAD_32_B(val, ptr) \
+ do { \
+ (val) = (unsigned long)((*(ptr) & 0xFF) << 24); \
+ (val) |= (unsigned long)((*((ptr)+1) & 0xFF) << 16); \
+ (val) |= (unsigned long)((*((ptr)+2) & 0xFF) << 8); \
+ (val) |= (unsigned long)(*((ptr)+3) & 0xFF); \
+ } while (0)
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/floatnum.c b/contrib/tools/yasm/libyasm/floatnum.c
index ab67c2b2e4..98eabeebcf 100644
--- a/contrib/tools/yasm/libyasm/floatnum.c
+++ b/contrib/tools/yasm/libyasm/floatnum.c
@@ -1,760 +1,760 @@
-/*
- * Floating point number functions.
- *
- * Copyright (C) 2001-2007 Peter Johnson
- *
- * Based on public-domain x86 assembly code by Randall Hyde (8/28/91).
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#include "util.h"
-
-#include <ctype.h>
-
-#include "coretype.h"
-#include "bitvect.h"
-#include "file.h"
-
-#include "errwarn.h"
-#include "floatnum.h"
-
-
-/* 97-bit internal floating point format:
- * 0000000s eeeeeeee eeeeeeee m.....................................m
- * Sign exponent mantissa (80 bits)
- * 79 0
- *
- * Only L.O. bit of Sign byte is significant. The rest is zero.
- * Exponent is bias 32767.
- * Mantissa does NOT have an implied one bit (it's explicit).
- */
-struct yasm_floatnum {
- /*@only@*/ wordptr mantissa; /* Allocated to MANT_BITS bits */
- unsigned short exponent;
- unsigned char sign;
- unsigned char flags;
-};
-
-/* constants describing parameters of internal floating point format */
-#define MANT_BITS 80
-#define MANT_BYTES 10
-#define MANT_SIGDIGITS 24
-#define EXP_BIAS 0x7FFF
-#define EXP_INF 0xFFFF
-#define EXP_MAX 0xFFFE
-#define EXP_MIN 1
-#define EXP_ZERO 0
-
-/* Flag settings for flags field */
-#define FLAG_ISZERO 1<<0
-
-/* Note this structure integrates the floatnum structure */
-typedef struct POT_Entry_s {
- yasm_floatnum f;
- int dec_exponent;
-} POT_Entry;
-
-/* "Source" for POT_Entry. */
-typedef struct POT_Entry_Source_s {
- unsigned char mantissa[MANT_BYTES]; /* little endian mantissa */
- unsigned short exponent; /* Bias 32767 exponent */
-} POT_Entry_Source;
-
-/* Power of ten tables used by the floating point I/O routines.
- * The POT_Table? arrays are built from the POT_Table?_Source arrays at
- * runtime by POT_Table_Init().
- */
-
-/* This table contains the powers of ten raised to negative powers of two:
- *
- * entry[12-n] = 10 ** (-2 ** n) for 0 <= n <= 12.
- * entry[13] = 1.0
- */
-static /*@only@*/ POT_Entry *POT_TableN;
-static POT_Entry_Source POT_TableN_Source[] = {
- {{0xe3,0x2d,0xde,0x9f,0xce,0xd2,0xc8,0x04,0xdd,0xa6},0x4ad8}, /* 1e-4096 */
- {{0x25,0x49,0xe4,0x2d,0x36,0x34,0x4f,0x53,0xae,0xce},0x656b}, /* 1e-2048 */
- {{0xa6,0x87,0xbd,0xc0,0x57,0xda,0xa5,0x82,0xa6,0xa2},0x72b5}, /* 1e-1024 */
- {{0x33,0x71,0x1c,0xd2,0x23,0xdb,0x32,0xee,0x49,0x90},0x795a}, /* 1e-512 */
- {{0x91,0xfa,0x39,0x19,0x7a,0x63,0x25,0x43,0x31,0xc0},0x7cac}, /* 1e-256 */
- {{0x7d,0xac,0xa0,0xe4,0xbc,0x64,0x7c,0x46,0xd0,0xdd},0x7e55}, /* 1e-128 */
- {{0x24,0x3f,0xa5,0xe9,0x39,0xa5,0x27,0xea,0x7f,0xa8},0x7f2a}, /* 1e-64 */
- {{0xde,0x67,0xba,0x94,0x39,0x45,0xad,0x1e,0xb1,0xcf},0x7f94}, /* 1e-32 */
- {{0x2f,0x4c,0x5b,0xe1,0x4d,0xc4,0xbe,0x94,0x95,0xe6},0x7fc9}, /* 1e-16 */
- {{0xc2,0xfd,0xfc,0xce,0x61,0x84,0x11,0x77,0xcc,0xab},0x7fe4}, /* 1e-8 */
- {{0xc3,0xd3,0x2b,0x65,0x19,0xe2,0x58,0x17,0xb7,0xd1},0x7ff1}, /* 1e-4 */
- {{0x71,0x3d,0x0a,0xd7,0xa3,0x70,0x3d,0x0a,0xd7,0xa3},0x7ff8}, /* 1e-2 */
- {{0xcd,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc},0x7ffb}, /* 1e-1 */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80},0x7fff}, /* 1e-0 */
-};
-
-/* This table contains the powers of ten raised to positive powers of two:
- *
- * entry[12-n] = 10 ** (2 ** n) for 0 <= n <= 12.
- * entry[13] = 1.0
- * entry[-1] = entry[0];
- *
- * There is a -1 entry since it is possible for the algorithm to back up
- * before the table. This -1 entry is created at runtime by duplicating the
- * 0 entry.
- */
-static /*@only@*/ POT_Entry *POT_TableP;
-static POT_Entry_Source POT_TableP_Source[] = {
- {{0x4c,0xc9,0x9a,0x97,0x20,0x8a,0x02,0x52,0x60,0xc4},0xb525}, /* 1e+4096 */
- {{0x4d,0xa7,0xe4,0x5d,0x3d,0xc5,0x5d,0x3b,0x8b,0x9e},0x9a92}, /* 1e+2048 */
- {{0x0d,0x65,0x17,0x0c,0x75,0x81,0x86,0x75,0x76,0xc9},0x8d48}, /* 1e+1024 */
- {{0x65,0xcc,0xc6,0x91,0x0e,0xa6,0xae,0xa0,0x19,0xe3},0x86a3}, /* 1e+512 */
- {{0xbc,0xdd,0x8d,0xde,0xf9,0x9d,0xfb,0xeb,0x7e,0xaa},0x8351}, /* 1e+256 */
- {{0x6f,0xc6,0xdf,0x8c,0xe9,0x80,0xc9,0x47,0xba,0x93},0x81a8}, /* 1e+128 */
- {{0xbf,0x3c,0xd5,0xa6,0xcf,0xff,0x49,0x1f,0x78,0xc2},0x80d3}, /* 1e+64 */
- {{0x20,0xf0,0x9d,0xb5,0x70,0x2b,0xa8,0xad,0xc5,0x9d},0x8069}, /* 1e+32 */
- {{0x00,0x00,0x00,0x00,0x00,0x04,0xbf,0xc9,0x1b,0x8e},0x8034}, /* 1e+16 */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0xbc,0xbe},0x8019}, /* 1e+8 */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x9c},0x800c}, /* 1e+4 */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8},0x8005}, /* 1e+2 */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0},0x8002}, /* 1e+1 */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80},0x7fff}, /* 1e+0 */
-};
-
-
-static void
-POT_Table_Init_Entry(/*@out@*/ POT_Entry *e, POT_Entry_Source *s, int dec_exp)
-{
- /* Save decimal exponent */
- e->dec_exponent = dec_exp;
-
- /* Initialize mantissa */
- e->f.mantissa = BitVector_Create(MANT_BITS, FALSE);
- BitVector_Block_Store(e->f.mantissa, s->mantissa, MANT_BYTES);
-
- /* Initialize exponent */
- e->f.exponent = s->exponent;
-
- /* Set sign to 0 (positive) */
- e->f.sign = 0;
-
- /* Clear flags */
- e->f.flags = 0;
-}
-
-/*@-compdef@*/
-void
-yasm_floatnum_initialize(void)
-/*@globals undef POT_TableN, undef POT_TableP, POT_TableP_Source,
- POT_TableN_Source @*/
-{
- int dec_exp = 1;
- int i;
-
- /* Allocate space for two POT tables */
- POT_TableN = yasm_xmalloc(14*sizeof(POT_Entry));
- POT_TableP = yasm_xmalloc(15*sizeof(POT_Entry)); /* note 1 extra for -1 */
-
- /* Initialize entry[0..12] */
- for (i=12; i>=0; i--) {
- POT_Table_Init_Entry(&POT_TableN[i], &POT_TableN_Source[i], 0-dec_exp);
- POT_Table_Init_Entry(&POT_TableP[i+1], &POT_TableP_Source[i], dec_exp);
- dec_exp *= 2; /* Update decimal exponent */
- }
-
- /* Initialize entry[13] */
- POT_Table_Init_Entry(&POT_TableN[13], &POT_TableN_Source[13], 0);
- POT_Table_Init_Entry(&POT_TableP[14], &POT_TableP_Source[13], 0);
-
- /* Initialize entry[-1] for POT_TableP */
- POT_Table_Init_Entry(&POT_TableP[0], &POT_TableP_Source[0], 4096);
-
- /* Offset POT_TableP so that [0] becomes [-1] */
- POT_TableP++;
-}
-/*@=compdef@*/
-
-/*@-globstate@*/
-void
-yasm_floatnum_cleanup(void)
-{
- int i;
-
- /* Un-offset POT_TableP */
- POT_TableP--;
-
- for (i=0; i<14; i++) {
- BitVector_Destroy(POT_TableN[i].f.mantissa);
- BitVector_Destroy(POT_TableP[i].f.mantissa);
- }
- BitVector_Destroy(POT_TableP[14].f.mantissa);
-
- yasm_xfree(POT_TableN);
- yasm_xfree(POT_TableP);
-}
-/*@=globstate@*/
-
-static void
-floatnum_normalize(yasm_floatnum *flt)
-{
- long norm_amt;
-
- if (BitVector_is_empty(flt->mantissa)) {
- flt->exponent = 0;
- return;
- }
-
- /* Look for the highest set bit, shift to make it the MSB, and adjust
- * exponent. Don't let exponent go negative. */
- norm_amt = (MANT_BITS-1)-Set_Max(flt->mantissa);
- if (norm_amt > (long)flt->exponent)
- norm_amt = (long)flt->exponent;
- BitVector_Move_Left(flt->mantissa, (N_int)norm_amt);
- flt->exponent -= (unsigned short)norm_amt;
-}
-
-/* acc *= op */
-static void
-floatnum_mul(yasm_floatnum *acc, const yasm_floatnum *op)
-{
- long expon;
- wordptr product, op1, op2;
- long norm_amt;
-
- /* Compute the new sign */
- acc->sign ^= op->sign;
-
- /* Check for multiply by 0 */
- if (BitVector_is_empty(acc->mantissa) || BitVector_is_empty(op->mantissa)) {
- BitVector_Empty(acc->mantissa);
- acc->exponent = EXP_ZERO;
- return;
- }
-
- /* Add exponents, checking for overflow/underflow. */
- expon = (((int)acc->exponent)-EXP_BIAS) + (((int)op->exponent)-EXP_BIAS);
- expon += EXP_BIAS;
- if (expon > EXP_MAX) {
- /* Overflow; return infinity. */
- BitVector_Empty(acc->mantissa);
- acc->exponent = EXP_INF;
- return;
- } else if (expon < EXP_MIN) {
- /* Underflow; return zero. */
- BitVector_Empty(acc->mantissa);
- acc->exponent = EXP_ZERO;
- return;
- }
-
- /* Add one to the final exponent, as the multiply shifts one extra time. */
- acc->exponent = (unsigned short)(expon+1);
-
- /* Allocate space for the multiply result */
- product = BitVector_Create((N_int)((MANT_BITS+1)*2), FALSE);
-
- /* Allocate 1-bit-longer fields to force the operands to be unsigned */
- op1 = BitVector_Create((N_int)(MANT_BITS+1), FALSE);
- op2 = BitVector_Create((N_int)(MANT_BITS+1), FALSE);
-
- /* Make the operands unsigned after copying from original operands */
- BitVector_Copy(op1, acc->mantissa);
- BitVector_MSB(op1, 0);
- BitVector_Copy(op2, op->mantissa);
- BitVector_MSB(op2, 0);
-
- /* Compute the product of the mantissas */
- BitVector_Multiply(product, op1, op2);
-
- /* Normalize the product. Note: we know the product is non-zero because
- * both of the original operands were non-zero.
- *
- * Look for the highest set bit, shift to make it the MSB, and adjust
- * exponent. Don't let exponent go negative.
- */
- norm_amt = (MANT_BITS*2-1)-Set_Max(product);
- if (norm_amt > (long)acc->exponent)
- norm_amt = (long)acc->exponent;
- BitVector_Move_Left(product, (N_int)norm_amt);
- acc->exponent -= (unsigned short)norm_amt;
-
- /* Store the highest bits of the result */
- BitVector_Interval_Copy(acc->mantissa, product, 0, MANT_BITS, MANT_BITS);
-
- /* Free allocated variables */
- BitVector_Destroy(product);
- BitVector_Destroy(op1);
- BitVector_Destroy(op2);
-}
-
-yasm_floatnum *
-yasm_floatnum_create(const char *str)
-{
- yasm_floatnum *flt;
- int dec_exponent, dec_exp_add; /* decimal (powers of 10) exponent */
- int POT_index;
- wordptr operand[2];
- int sig_digits;
- int decimal_pt;
- boolean carry;
-
- flt = yasm_xmalloc(sizeof(yasm_floatnum));
-
- flt->mantissa = BitVector_Create(MANT_BITS, TRUE);
-
- /* allocate and initialize calculation variables */
- operand[0] = BitVector_Create(MANT_BITS, TRUE);
- operand[1] = BitVector_Create(MANT_BITS, TRUE);
- dec_exponent = 0;
- sig_digits = 0;
- decimal_pt = 1;
-
- /* set initial flags to 0 */
- flt->flags = 0;
-
- /* check for + or - character and skip */
- if (*str == '-') {
- flt->sign = 1;
- str++;
- } else if (*str == '+') {
- flt->sign = 0;
- str++;
- } else
- flt->sign = 0;
-
- /* eliminate any leading zeros (which do not count as significant digits) */
- while (*str == '0')
- str++;
-
- /* When we reach the end of the leading zeros, first check for a decimal
- * point. If the number is of the form "0---0.0000" we need to get rid
- * of the zeros after the decimal point and not count them as significant
- * digits.
- */
- if (*str == '.') {
- str++;
- while (*str == '0') {
- str++;
- dec_exponent--;
- }
- } else {
- /* The number is of the form "yyy.xxxx" (where y <> 0). */
- while (isdigit(*str)) {
- /* See if we've processed more than the max significant digits: */
- if (sig_digits < MANT_SIGDIGITS) {
- /* Multiply mantissa by 10 [x = (x<<1)+(x<<3)] */
- BitVector_shift_left(flt->mantissa, 0);
- BitVector_Copy(operand[0], flt->mantissa);
- BitVector_Move_Left(flt->mantissa, 2);
- carry = 0;
- BitVector_add(operand[1], operand[0], flt->mantissa, &carry);
-
- /* Add in current digit */
- BitVector_Empty(operand[0]);
- BitVector_Chunk_Store(operand[0], 4, 0, (N_long)(*str-'0'));
- carry = 0;
- BitVector_add(flt->mantissa, operand[1], operand[0], &carry);
- } else {
- /* Can't integrate more digits with mantissa, so instead just
- * raise by a power of ten.
- */
- dec_exponent++;
- }
- sig_digits++;
- str++;
- }
-
- if (*str == '.')
- str++;
- else
- decimal_pt = 0;
- }
-
- if (decimal_pt) {
- /* Process the digits to the right of the decimal point. */
- while (isdigit(*str)) {
- /* See if we've processed more than 19 significant digits: */
- if (sig_digits < 19) {
- /* Raise by a power of ten */
- dec_exponent--;
-
- /* Multiply mantissa by 10 [x = (x<<1)+(x<<3)] */
- BitVector_shift_left(flt->mantissa, 0);
- BitVector_Copy(operand[0], flt->mantissa);
- BitVector_Move_Left(flt->mantissa, 2);
- carry = 0;
- BitVector_add(operand[1], operand[0], flt->mantissa, &carry);
-
- /* Add in current digit */
- BitVector_Empty(operand[0]);
- BitVector_Chunk_Store(operand[0], 4, 0, (N_long)(*str-'0'));
- carry = 0;
- BitVector_add(flt->mantissa, operand[1], operand[0], &carry);
- }
- sig_digits++;
- str++;
- }
- }
-
- if (*str == 'e' || *str == 'E') {
- str++;
- /* We just saw the "E" character, now read in the exponent value and
- * add it into dec_exponent.
- */
- dec_exp_add = 0;
- sscanf(str, "%d", &dec_exp_add);
- dec_exponent += dec_exp_add;
- }
-
- /* Free calculation variables. */
- BitVector_Destroy(operand[1]);
- BitVector_Destroy(operand[0]);
-
- /* Normalize the number, checking for 0 first. */
- if (BitVector_is_empty(flt->mantissa)) {
- /* Mantissa is 0, zero exponent too. */
- flt->exponent = 0;
- /* Set zero flag so output functions don't see 0 value as underflow. */
- flt->flags |= FLAG_ISZERO;
- /* Return 0 value. */
- return flt;
- }
- /* Exponent if already norm. */
- flt->exponent = (unsigned short)(0x7FFF+(MANT_BITS-1));
- floatnum_normalize(flt);
-
- /* The number is normalized. Now multiply by 10 the number of times
- * specified in DecExponent. This uses the power of ten tables to speed
- * up this operation (and make it more accurate).
- */
- if (dec_exponent > 0) {
- POT_index = 0;
- /* Until we hit 1.0 or finish exponent or overflow */
- while ((POT_index < 14) && (dec_exponent != 0) &&
- (flt->exponent != EXP_INF)) {
- /* Find the first power of ten in the table which is just less than
- * the exponent.
- */
- while (dec_exponent < POT_TableP[POT_index].dec_exponent)
- POT_index++;
-
- if (POT_index < 14) {
- /* Subtract out what we're multiplying in from exponent */
- dec_exponent -= POT_TableP[POT_index].dec_exponent;
-
- /* Multiply by current power of 10 */
- floatnum_mul(flt, &POT_TableP[POT_index].f);
- }
- }
- } else if (dec_exponent < 0) {
- POT_index = 0;
- /* Until we hit 1.0 or finish exponent or underflow */
- while ((POT_index < 14) && (dec_exponent != 0) &&
- (flt->exponent != EXP_ZERO)) {
- /* Find the first power of ten in the table which is just less than
- * the exponent.
- */
- while (dec_exponent > POT_TableN[POT_index].dec_exponent)
- POT_index++;
-
- if (POT_index < 14) {
- /* Subtract out what we're multiplying in from exponent */
- dec_exponent -= POT_TableN[POT_index].dec_exponent;
-
- /* Multiply by current power of 10 */
- floatnum_mul(flt, &POT_TableN[POT_index].f);
- }
- }
- }
-
- /* Round the result. (Don't round underflow or overflow). Also don't
- * increment if this would cause the mantissa to wrap.
- */
- if ((flt->exponent != EXP_INF) && (flt->exponent != EXP_ZERO) &&
- !BitVector_is_full(flt->mantissa))
- BitVector_increment(flt->mantissa);
-
- return flt;
-}
-
-yasm_floatnum *
-yasm_floatnum_copy(const yasm_floatnum *flt)
-{
- yasm_floatnum *f = yasm_xmalloc(sizeof(yasm_floatnum));
-
- f->mantissa = BitVector_Clone(flt->mantissa);
- f->exponent = flt->exponent;
- f->sign = flt->sign;
- f->flags = flt->flags;
-
- return f;
-}
-
-void
-yasm_floatnum_destroy(yasm_floatnum *flt)
-{
- BitVector_Destroy(flt->mantissa);
- yasm_xfree(flt);
-}
-
-int
-yasm_floatnum_calc(yasm_floatnum *acc, yasm_expr_op op,
- /*@unused@*/ yasm_floatnum *operand)
-{
- if (op != YASM_EXPR_NEG) {
- yasm_error_set(YASM_ERROR_FLOATING_POINT,
- N_("Unsupported floating-point arithmetic operation"));
- return 1;
- }
- acc->sign ^= 1;
- return 0;
-}
-
-int
-yasm_floatnum_get_int(const yasm_floatnum *flt, unsigned long *ret_val)
-{
- unsigned char t[4];
-
- if (yasm_floatnum_get_sized(flt, t, 4, 32, 0, 0, 0)) {
- *ret_val = 0xDEADBEEFUL; /* Obviously incorrect return value */
- return 1;
- }
-
- YASM_LOAD_32_L(*ret_val, &t[0]);
- return 0;
-}
-
-/* Function used by conversion routines to actually perform the conversion.
- *
- * ptr -> the array to return the little-endian floating point value into.
- * flt -> the floating point value to convert.
- * byte_size -> the size in bytes of the output format.
- * mant_bits -> the size in bits of the output mantissa.
- * implicit1 -> does the output format have an implicit 1? 1=yes, 0=no.
- * exp_bits -> the size in bits of the output exponent.
- *
- * Returns 0 on success, 1 if overflow, -1 if underflow.
- */
-static int
-floatnum_get_common(const yasm_floatnum *flt, /*@out@*/ unsigned char *ptr,
- N_int byte_size, N_int mant_bits, int implicit1,
- N_int exp_bits)
-{
- long exponent = (long)flt->exponent;
- wordptr output;
- charptr buf;
- unsigned int len;
- unsigned int overflow = 0, underflow = 0;
- int retval = 0;
- long exp_bias = (1<<(exp_bits-1))-1;
- long exp_inf = (1<<exp_bits)-1;
-
- output = BitVector_Create(byte_size*8, TRUE);
-
- /* copy mantissa */
- BitVector_Interval_Copy(output, flt->mantissa, 0,
- (N_int)((MANT_BITS-implicit1)-mant_bits),
- mant_bits);
-
- /* round mantissa */
- if (BitVector_bit_test(flt->mantissa, (MANT_BITS-implicit1)-(mant_bits+1)))
- BitVector_increment(output);
-
- if (BitVector_bit_test(output, mant_bits)) {
- /* overflowed, so zero mantissa (and set explicit bit if necessary) */
- BitVector_Empty(output);
- BitVector_Bit_Copy(output, mant_bits-1, !implicit1);
- /* and up the exponent (checking for overflow) */
- if (exponent+1 >= EXP_INF)
- overflow = 1;
- else
- exponent++;
- }
-
- /* adjust the exponent to the output bias, checking for overflow */
- exponent -= EXP_BIAS-exp_bias;
- if (exponent >= exp_inf)
- overflow = 1;
- else if (exponent <= 0)
- underflow = 1;
-
- /* underflow and overflow both set!? */
- if (underflow && overflow)
- yasm_internal_error(N_("Both underflow and overflow set"));
-
- /* check for underflow or overflow and set up appropriate output */
- if (underflow) {
- BitVector_Empty(output);
- exponent = 0;
- if (!(flt->flags & FLAG_ISZERO))
- retval = -1;
- } else if (overflow) {
- BitVector_Empty(output);
- exponent = exp_inf;
- retval = 1;
- }
-
- /* move exponent into place */
- BitVector_Chunk_Store(output, exp_bits, mant_bits, (N_long)exponent);
-
- /* merge in sign bit */
- BitVector_Bit_Copy(output, byte_size*8-1, flt->sign);
-
- /* get little-endian bytes */
- buf = BitVector_Block_Read(output, &len);
- if (len < byte_size)
- yasm_internal_error(
- N_("Byte length of BitVector does not match bit length"));
-
- /* copy to output */
- memcpy(ptr, buf, byte_size*sizeof(unsigned char));
-
- /* free allocated resources */
- yasm_xfree(buf);
-
- BitVector_Destroy(output);
-
- return retval;
-}
-
-/* IEEE-754r "half precision" format:
- * 16 bits:
- * 15 9 Bit 0
- * | | |
- * seee eemm mmmm mmmm
- *
- * e = bias 15 exponent
- * s = sign bit
- * m = mantissa bits, bit 10 is an implied one bit.
- *
- * IEEE-754 (Intel) "single precision" format:
- * 32 bits:
- * Bit 31 Bit 22 Bit 0
- * | | |
- * seeeeeee emmmmmmm mmmmmmmm mmmmmmmm
- *
- * e = bias 127 exponent
- * s = sign bit
- * m = mantissa bits, bit 23 is an implied one bit.
- *
- * IEEE-754 (Intel) "double precision" format:
- * 64 bits:
- * bit 63 bit 51 bit 0
- * | | |
- * seeeeeee eeeemmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm
- *
- * e = bias 1023 exponent.
- * s = sign bit.
- * m = mantissa bits. Bit 52 is an implied one bit.
- *
- * IEEE-754 (Intel) "extended precision" format:
- * 80 bits:
- * bit 79 bit 63 bit 0
- * | | |
- * seeeeeee eeeeeeee mmmmmmmm m...m m...m m...m m...m m...m
- *
- * e = bias 16383 exponent
- * m = 64 bit mantissa with NO implied bit!
- * s = sign (for mantissa)
- */
-int
-yasm_floatnum_get_sized(const yasm_floatnum *flt, unsigned char *ptr,
- size_t destsize, size_t valsize, size_t shift,
- int bigendian, int warn)
-{
- int retval;
- if (destsize*8 != valsize || shift>0 || bigendian) {
- /* TODO */
- yasm_internal_error(N_("unsupported floatnum functionality"));
- }
- switch (destsize) {
- case 2:
- retval = floatnum_get_common(flt, ptr, 2, 10, 1, 5);
- break;
- case 4:
- retval = floatnum_get_common(flt, ptr, 4, 23, 1, 8);
- break;
- case 8:
- retval = floatnum_get_common(flt, ptr, 8, 52, 1, 11);
- break;
- case 10:
- retval = floatnum_get_common(flt, ptr, 10, 64, 0, 15);
- break;
- default:
- yasm_internal_error(N_("Invalid float conversion size"));
- /*@notreached@*/
- return 1;
- }
- if (warn) {
- if (retval < 0)
- yasm_warn_set(YASM_WARN_GENERAL,
- N_("underflow in floating point expression"));
- else if (retval > 0)
- yasm_warn_set(YASM_WARN_GENERAL,
- N_("overflow in floating point expression"));
- }
- return retval;
-}
-
-/* 1 if the size is valid, 0 if it isn't */
-int
-yasm_floatnum_check_size(/*@unused@*/ const yasm_floatnum *flt, size_t size)
-{
- switch (size) {
- case 16:
- case 32:
- case 64:
- case 80:
- return 1;
- default:
- return 0;
- }
-}
-
-void
-yasm_floatnum_print(const yasm_floatnum *flt, FILE *f)
-{
- unsigned char out[10];
- unsigned char *str;
- int i;
-
- /* Internal format */
- str = BitVector_to_Hex(flt->mantissa);
- fprintf(f, "%c %s *2^%04x\n", flt->sign?'-':'+', (char *)str,
- flt->exponent);
- yasm_xfree(str);
-
- /* 32-bit (single precision) format */
- fprintf(f, "32-bit: %d: ",
- yasm_floatnum_get_sized(flt, out, 4, 32, 0, 0, 0));
- for (i=0; i<4; i++)
- fprintf(f, "%02x ", out[i]);
- fprintf(f, "\n");
-
- /* 64-bit (double precision) format */
- fprintf(f, "64-bit: %d: ",
- yasm_floatnum_get_sized(flt, out, 8, 64, 0, 0, 0));
- for (i=0; i<8; i++)
- fprintf(f, "%02x ", out[i]);
- fprintf(f, "\n");
-
- /* 80-bit (extended precision) format */
- fprintf(f, "80-bit: %d: ",
- yasm_floatnum_get_sized(flt, out, 10, 80, 0, 0, 0));
- for (i=0; i<10; i++)
- fprintf(f, "%02x ", out[i]);
- fprintf(f, "\n");
-}
+/*
+ * Floating point number functions.
+ *
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Based on public-domain x86 assembly code by Randall Hyde (8/28/91).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "util.h"
+
+#include <ctype.h>
+
+#include "coretype.h"
+#include "bitvect.h"
+#include "file.h"
+
+#include "errwarn.h"
+#include "floatnum.h"
+
+
+/* 97-bit internal floating point format:
+ * 0000000s eeeeeeee eeeeeeee m.....................................m
+ * Sign exponent mantissa (80 bits)
+ * 79 0
+ *
+ * Only L.O. bit of Sign byte is significant. The rest is zero.
+ * Exponent is bias 32767.
+ * Mantissa does NOT have an implied one bit (it's explicit).
+ */
+struct yasm_floatnum {
+ /*@only@*/ wordptr mantissa; /* Allocated to MANT_BITS bits */
+ unsigned short exponent;
+ unsigned char sign;
+ unsigned char flags;
+};
+
+/* constants describing parameters of internal floating point format */
+#define MANT_BITS 80
+#define MANT_BYTES 10
+#define MANT_SIGDIGITS 24
+#define EXP_BIAS 0x7FFF
+#define EXP_INF 0xFFFF
+#define EXP_MAX 0xFFFE
+#define EXP_MIN 1
+#define EXP_ZERO 0
+
+/* Flag settings for flags field */
+#define FLAG_ISZERO 1<<0
+
+/* Note this structure integrates the floatnum structure */
+typedef struct POT_Entry_s {
+ yasm_floatnum f;
+ int dec_exponent;
+} POT_Entry;
+
+/* "Source" for POT_Entry. */
+typedef struct POT_Entry_Source_s {
+ unsigned char mantissa[MANT_BYTES]; /* little endian mantissa */
+ unsigned short exponent; /* Bias 32767 exponent */
+} POT_Entry_Source;
+
+/* Power of ten tables used by the floating point I/O routines.
+ * The POT_Table? arrays are built from the POT_Table?_Source arrays at
+ * runtime by POT_Table_Init().
+ */
+
+/* This table contains the powers of ten raised to negative powers of two:
+ *
+ * entry[12-n] = 10 ** (-2 ** n) for 0 <= n <= 12.
+ * entry[13] = 1.0
+ */
+static /*@only@*/ POT_Entry *POT_TableN;
+static POT_Entry_Source POT_TableN_Source[] = {
+ {{0xe3,0x2d,0xde,0x9f,0xce,0xd2,0xc8,0x04,0xdd,0xa6},0x4ad8}, /* 1e-4096 */
+ {{0x25,0x49,0xe4,0x2d,0x36,0x34,0x4f,0x53,0xae,0xce},0x656b}, /* 1e-2048 */
+ {{0xa6,0x87,0xbd,0xc0,0x57,0xda,0xa5,0x82,0xa6,0xa2},0x72b5}, /* 1e-1024 */
+ {{0x33,0x71,0x1c,0xd2,0x23,0xdb,0x32,0xee,0x49,0x90},0x795a}, /* 1e-512 */
+ {{0x91,0xfa,0x39,0x19,0x7a,0x63,0x25,0x43,0x31,0xc0},0x7cac}, /* 1e-256 */
+ {{0x7d,0xac,0xa0,0xe4,0xbc,0x64,0x7c,0x46,0xd0,0xdd},0x7e55}, /* 1e-128 */
+ {{0x24,0x3f,0xa5,0xe9,0x39,0xa5,0x27,0xea,0x7f,0xa8},0x7f2a}, /* 1e-64 */
+ {{0xde,0x67,0xba,0x94,0x39,0x45,0xad,0x1e,0xb1,0xcf},0x7f94}, /* 1e-32 */
+ {{0x2f,0x4c,0x5b,0xe1,0x4d,0xc4,0xbe,0x94,0x95,0xe6},0x7fc9}, /* 1e-16 */
+ {{0xc2,0xfd,0xfc,0xce,0x61,0x84,0x11,0x77,0xcc,0xab},0x7fe4}, /* 1e-8 */
+ {{0xc3,0xd3,0x2b,0x65,0x19,0xe2,0x58,0x17,0xb7,0xd1},0x7ff1}, /* 1e-4 */
+ {{0x71,0x3d,0x0a,0xd7,0xa3,0x70,0x3d,0x0a,0xd7,0xa3},0x7ff8}, /* 1e-2 */
+ {{0xcd,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc},0x7ffb}, /* 1e-1 */
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80},0x7fff}, /* 1e-0 */
+};
+
+/* This table contains the powers of ten raised to positive powers of two:
+ *
+ * entry[12-n] = 10 ** (2 ** n) for 0 <= n <= 12.
+ * entry[13] = 1.0
+ * entry[-1] = entry[0];
+ *
+ * There is a -1 entry since it is possible for the algorithm to back up
+ * before the table. This -1 entry is created at runtime by duplicating the
+ * 0 entry.
+ */
+static /*@only@*/ POT_Entry *POT_TableP;
+static POT_Entry_Source POT_TableP_Source[] = {
+ {{0x4c,0xc9,0x9a,0x97,0x20,0x8a,0x02,0x52,0x60,0xc4},0xb525}, /* 1e+4096 */
+ {{0x4d,0xa7,0xe4,0x5d,0x3d,0xc5,0x5d,0x3b,0x8b,0x9e},0x9a92}, /* 1e+2048 */
+ {{0x0d,0x65,0x17,0x0c,0x75,0x81,0x86,0x75,0x76,0xc9},0x8d48}, /* 1e+1024 */
+ {{0x65,0xcc,0xc6,0x91,0x0e,0xa6,0xae,0xa0,0x19,0xe3},0x86a3}, /* 1e+512 */
+ {{0xbc,0xdd,0x8d,0xde,0xf9,0x9d,0xfb,0xeb,0x7e,0xaa},0x8351}, /* 1e+256 */
+ {{0x6f,0xc6,0xdf,0x8c,0xe9,0x80,0xc9,0x47,0xba,0x93},0x81a8}, /* 1e+128 */
+ {{0xbf,0x3c,0xd5,0xa6,0xcf,0xff,0x49,0x1f,0x78,0xc2},0x80d3}, /* 1e+64 */
+ {{0x20,0xf0,0x9d,0xb5,0x70,0x2b,0xa8,0xad,0xc5,0x9d},0x8069}, /* 1e+32 */
+ {{0x00,0x00,0x00,0x00,0x00,0x04,0xbf,0xc9,0x1b,0x8e},0x8034}, /* 1e+16 */
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0xbc,0xbe},0x8019}, /* 1e+8 */
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x9c},0x800c}, /* 1e+4 */
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8},0x8005}, /* 1e+2 */
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0},0x8002}, /* 1e+1 */
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80},0x7fff}, /* 1e+0 */
+};
+
+
+static void
+POT_Table_Init_Entry(/*@out@*/ POT_Entry *e, POT_Entry_Source *s, int dec_exp)
+{
+ /* Save decimal exponent */
+ e->dec_exponent = dec_exp;
+
+ /* Initialize mantissa */
+ e->f.mantissa = BitVector_Create(MANT_BITS, FALSE);
+ BitVector_Block_Store(e->f.mantissa, s->mantissa, MANT_BYTES);
+
+ /* Initialize exponent */
+ e->f.exponent = s->exponent;
+
+ /* Set sign to 0 (positive) */
+ e->f.sign = 0;
+
+ /* Clear flags */
+ e->f.flags = 0;
+}
+
+/*@-compdef@*/
+void
+yasm_floatnum_initialize(void)
+/*@globals undef POT_TableN, undef POT_TableP, POT_TableP_Source,
+ POT_TableN_Source @*/
+{
+ int dec_exp = 1;
+ int i;
+
+ /* Allocate space for two POT tables */
+ POT_TableN = yasm_xmalloc(14*sizeof(POT_Entry));
+ POT_TableP = yasm_xmalloc(15*sizeof(POT_Entry)); /* note 1 extra for -1 */
+
+ /* Initialize entry[0..12] */
+ for (i=12; i>=0; i--) {
+ POT_Table_Init_Entry(&POT_TableN[i], &POT_TableN_Source[i], 0-dec_exp);
+ POT_Table_Init_Entry(&POT_TableP[i+1], &POT_TableP_Source[i], dec_exp);
+ dec_exp *= 2; /* Update decimal exponent */
+ }
+
+ /* Initialize entry[13] */
+ POT_Table_Init_Entry(&POT_TableN[13], &POT_TableN_Source[13], 0);
+ POT_Table_Init_Entry(&POT_TableP[14], &POT_TableP_Source[13], 0);
+
+ /* Initialize entry[-1] for POT_TableP */
+ POT_Table_Init_Entry(&POT_TableP[0], &POT_TableP_Source[0], 4096);
+
+ /* Offset POT_TableP so that [0] becomes [-1] */
+ POT_TableP++;
+}
+/*@=compdef@*/
+
+/*@-globstate@*/
+void
+yasm_floatnum_cleanup(void)
+{
+ int i;
+
+ /* Un-offset POT_TableP */
+ POT_TableP--;
+
+ for (i=0; i<14; i++) {
+ BitVector_Destroy(POT_TableN[i].f.mantissa);
+ BitVector_Destroy(POT_TableP[i].f.mantissa);
+ }
+ BitVector_Destroy(POT_TableP[14].f.mantissa);
+
+ yasm_xfree(POT_TableN);
+ yasm_xfree(POT_TableP);
+}
+/*@=globstate@*/
+
+static void
+floatnum_normalize(yasm_floatnum *flt)
+{
+ long norm_amt;
+
+ if (BitVector_is_empty(flt->mantissa)) {
+ flt->exponent = 0;
+ return;
+ }
+
+ /* Look for the highest set bit, shift to make it the MSB, and adjust
+ * exponent. Don't let exponent go negative. */
+ norm_amt = (MANT_BITS-1)-Set_Max(flt->mantissa);
+ if (norm_amt > (long)flt->exponent)
+ norm_amt = (long)flt->exponent;
+ BitVector_Move_Left(flt->mantissa, (N_int)norm_amt);
+ flt->exponent -= (unsigned short)norm_amt;
+}
+
+/* acc *= op */
+static void
+floatnum_mul(yasm_floatnum *acc, const yasm_floatnum *op)
+{
+ long expon;
+ wordptr product, op1, op2;
+ long norm_amt;
+
+ /* Compute the new sign */
+ acc->sign ^= op->sign;
+
+ /* Check for multiply by 0 */
+ if (BitVector_is_empty(acc->mantissa) || BitVector_is_empty(op->mantissa)) {
+ BitVector_Empty(acc->mantissa);
+ acc->exponent = EXP_ZERO;
+ return;
+ }
+
+ /* Add exponents, checking for overflow/underflow. */
+ expon = (((int)acc->exponent)-EXP_BIAS) + (((int)op->exponent)-EXP_BIAS);
+ expon += EXP_BIAS;
+ if (expon > EXP_MAX) {
+ /* Overflow; return infinity. */
+ BitVector_Empty(acc->mantissa);
+ acc->exponent = EXP_INF;
+ return;
+ } else if (expon < EXP_MIN) {
+ /* Underflow; return zero. */
+ BitVector_Empty(acc->mantissa);
+ acc->exponent = EXP_ZERO;
+ return;
+ }
+
+ /* Add one to the final exponent, as the multiply shifts one extra time. */
+ acc->exponent = (unsigned short)(expon+1);
+
+ /* Allocate space for the multiply result */
+ product = BitVector_Create((N_int)((MANT_BITS+1)*2), FALSE);
+
+ /* Allocate 1-bit-longer fields to force the operands to be unsigned */
+ op1 = BitVector_Create((N_int)(MANT_BITS+1), FALSE);
+ op2 = BitVector_Create((N_int)(MANT_BITS+1), FALSE);
+
+ /* Make the operands unsigned after copying from original operands */
+ BitVector_Copy(op1, acc->mantissa);
+ BitVector_MSB(op1, 0);
+ BitVector_Copy(op2, op->mantissa);
+ BitVector_MSB(op2, 0);
+
+ /* Compute the product of the mantissas */
+ BitVector_Multiply(product, op1, op2);
+
+ /* Normalize the product. Note: we know the product is non-zero because
+ * both of the original operands were non-zero.
+ *
+ * Look for the highest set bit, shift to make it the MSB, and adjust
+ * exponent. Don't let exponent go negative.
+ */
+ norm_amt = (MANT_BITS*2-1)-Set_Max(product);
+ if (norm_amt > (long)acc->exponent)
+ norm_amt = (long)acc->exponent;
+ BitVector_Move_Left(product, (N_int)norm_amt);
+ acc->exponent -= (unsigned short)norm_amt;
+
+ /* Store the highest bits of the result */
+ BitVector_Interval_Copy(acc->mantissa, product, 0, MANT_BITS, MANT_BITS);
+
+ /* Free allocated variables */
+ BitVector_Destroy(product);
+ BitVector_Destroy(op1);
+ BitVector_Destroy(op2);
+}
+
+yasm_floatnum *
+yasm_floatnum_create(const char *str)
+{
+ yasm_floatnum *flt;
+ int dec_exponent, dec_exp_add; /* decimal (powers of 10) exponent */
+ int POT_index;
+ wordptr operand[2];
+ int sig_digits;
+ int decimal_pt;
+ boolean carry;
+
+ flt = yasm_xmalloc(sizeof(yasm_floatnum));
+
+ flt->mantissa = BitVector_Create(MANT_BITS, TRUE);
+
+ /* allocate and initialize calculation variables */
+ operand[0] = BitVector_Create(MANT_BITS, TRUE);
+ operand[1] = BitVector_Create(MANT_BITS, TRUE);
+ dec_exponent = 0;
+ sig_digits = 0;
+ decimal_pt = 1;
+
+ /* set initial flags to 0 */
+ flt->flags = 0;
+
+ /* check for + or - character and skip */
+ if (*str == '-') {
+ flt->sign = 1;
+ str++;
+ } else if (*str == '+') {
+ flt->sign = 0;
+ str++;
+ } else
+ flt->sign = 0;
+
+ /* eliminate any leading zeros (which do not count as significant digits) */
+ while (*str == '0')
+ str++;
+
+ /* When we reach the end of the leading zeros, first check for a decimal
+ * point. If the number is of the form "0---0.0000" we need to get rid
+ * of the zeros after the decimal point and not count them as significant
+ * digits.
+ */
+ if (*str == '.') {
+ str++;
+ while (*str == '0') {
+ str++;
+ dec_exponent--;
+ }
+ } else {
+ /* The number is of the form "yyy.xxxx" (where y <> 0). */
+ while (isdigit(*str)) {
+ /* See if we've processed more than the max significant digits: */
+ if (sig_digits < MANT_SIGDIGITS) {
+ /* Multiply mantissa by 10 [x = (x<<1)+(x<<3)] */
+ BitVector_shift_left(flt->mantissa, 0);
+ BitVector_Copy(operand[0], flt->mantissa);
+ BitVector_Move_Left(flt->mantissa, 2);
+ carry = 0;
+ BitVector_add(operand[1], operand[0], flt->mantissa, &carry);
+
+ /* Add in current digit */
+ BitVector_Empty(operand[0]);
+ BitVector_Chunk_Store(operand[0], 4, 0, (N_long)(*str-'0'));
+ carry = 0;
+ BitVector_add(flt->mantissa, operand[1], operand[0], &carry);
+ } else {
+ /* Can't integrate more digits with mantissa, so instead just
+ * raise by a power of ten.
+ */
+ dec_exponent++;
+ }
+ sig_digits++;
+ str++;
+ }
+
+ if (*str == '.')
+ str++;
+ else
+ decimal_pt = 0;
+ }
+
+ if (decimal_pt) {
+ /* Process the digits to the right of the decimal point. */
+ while (isdigit(*str)) {
+ /* See if we've processed more than 19 significant digits: */
+ if (sig_digits < 19) {
+ /* Raise by a power of ten */
+ dec_exponent--;
+
+ /* Multiply mantissa by 10 [x = (x<<1)+(x<<3)] */
+ BitVector_shift_left(flt->mantissa, 0);
+ BitVector_Copy(operand[0], flt->mantissa);
+ BitVector_Move_Left(flt->mantissa, 2);
+ carry = 0;
+ BitVector_add(operand[1], operand[0], flt->mantissa, &carry);
+
+ /* Add in current digit */
+ BitVector_Empty(operand[0]);
+ BitVector_Chunk_Store(operand[0], 4, 0, (N_long)(*str-'0'));
+ carry = 0;
+ BitVector_add(flt->mantissa, operand[1], operand[0], &carry);
+ }
+ sig_digits++;
+ str++;
+ }
+ }
+
+ if (*str == 'e' || *str == 'E') {
+ str++;
+ /* We just saw the "E" character, now read in the exponent value and
+ * add it into dec_exponent.
+ */
+ dec_exp_add = 0;
+ sscanf(str, "%d", &dec_exp_add);
+ dec_exponent += dec_exp_add;
+ }
+
+ /* Free calculation variables. */
+ BitVector_Destroy(operand[1]);
+ BitVector_Destroy(operand[0]);
+
+ /* Normalize the number, checking for 0 first. */
+ if (BitVector_is_empty(flt->mantissa)) {
+ /* Mantissa is 0, zero exponent too. */
+ flt->exponent = 0;
+ /* Set zero flag so output functions don't see 0 value as underflow. */
+ flt->flags |= FLAG_ISZERO;
+ /* Return 0 value. */
+ return flt;
+ }
+ /* Exponent if already norm. */
+ flt->exponent = (unsigned short)(0x7FFF+(MANT_BITS-1));
+ floatnum_normalize(flt);
+
+ /* The number is normalized. Now multiply by 10 the number of times
+ * specified in DecExponent. This uses the power of ten tables to speed
+ * up this operation (and make it more accurate).
+ */
+ if (dec_exponent > 0) {
+ POT_index = 0;
+ /* Until we hit 1.0 or finish exponent or overflow */
+ while ((POT_index < 14) && (dec_exponent != 0) &&
+ (flt->exponent != EXP_INF)) {
+ /* Find the first power of ten in the table which is just less than
+ * the exponent.
+ */
+ while (dec_exponent < POT_TableP[POT_index].dec_exponent)
+ POT_index++;
+
+ if (POT_index < 14) {
+ /* Subtract out what we're multiplying in from exponent */
+ dec_exponent -= POT_TableP[POT_index].dec_exponent;
+
+ /* Multiply by current power of 10 */
+ floatnum_mul(flt, &POT_TableP[POT_index].f);
+ }
+ }
+ } else if (dec_exponent < 0) {
+ POT_index = 0;
+ /* Until we hit 1.0 or finish exponent or underflow */
+ while ((POT_index < 14) && (dec_exponent != 0) &&
+ (flt->exponent != EXP_ZERO)) {
+ /* Find the first power of ten in the table which is just less than
+ * the exponent.
+ */
+ while (dec_exponent > POT_TableN[POT_index].dec_exponent)
+ POT_index++;
+
+ if (POT_index < 14) {
+ /* Subtract out what we're multiplying in from exponent */
+ dec_exponent -= POT_TableN[POT_index].dec_exponent;
+
+ /* Multiply by current power of 10 */
+ floatnum_mul(flt, &POT_TableN[POT_index].f);
+ }
+ }
+ }
+
+ /* Round the result. (Don't round underflow or overflow). Also don't
+ * increment if this would cause the mantissa to wrap.
+ */
+ if ((flt->exponent != EXP_INF) && (flt->exponent != EXP_ZERO) &&
+ !BitVector_is_full(flt->mantissa))
+ BitVector_increment(flt->mantissa);
+
+ return flt;
+}
+
+yasm_floatnum *
+yasm_floatnum_copy(const yasm_floatnum *flt)
+{
+ yasm_floatnum *f = yasm_xmalloc(sizeof(yasm_floatnum));
+
+ f->mantissa = BitVector_Clone(flt->mantissa);
+ f->exponent = flt->exponent;
+ f->sign = flt->sign;
+ f->flags = flt->flags;
+
+ return f;
+}
+
+void
+yasm_floatnum_destroy(yasm_floatnum *flt)
+{
+ BitVector_Destroy(flt->mantissa);
+ yasm_xfree(flt);
+}
+
+int
+yasm_floatnum_calc(yasm_floatnum *acc, yasm_expr_op op,
+ /*@unused@*/ yasm_floatnum *operand)
+{
+ if (op != YASM_EXPR_NEG) {
+ yasm_error_set(YASM_ERROR_FLOATING_POINT,
+ N_("Unsupported floating-point arithmetic operation"));
+ return 1;
+ }
+ acc->sign ^= 1;
+ return 0;
+}
+
+int
+yasm_floatnum_get_int(const yasm_floatnum *flt, unsigned long *ret_val)
+{
+ unsigned char t[4];
+
+ if (yasm_floatnum_get_sized(flt, t, 4, 32, 0, 0, 0)) {
+ *ret_val = 0xDEADBEEFUL; /* Obviously incorrect return value */
+ return 1;
+ }
+
+ YASM_LOAD_32_L(*ret_val, &t[0]);
+ return 0;
+}
+
+/* Function used by conversion routines to actually perform the conversion.
+ *
+ * ptr -> the array to return the little-endian floating point value into.
+ * flt -> the floating point value to convert.
+ * byte_size -> the size in bytes of the output format.
+ * mant_bits -> the size in bits of the output mantissa.
+ * implicit1 -> does the output format have an implicit 1? 1=yes, 0=no.
+ * exp_bits -> the size in bits of the output exponent.
+ *
+ * Returns 0 on success, 1 if overflow, -1 if underflow.
+ */
+static int
+floatnum_get_common(const yasm_floatnum *flt, /*@out@*/ unsigned char *ptr,
+ N_int byte_size, N_int mant_bits, int implicit1,
+ N_int exp_bits)
+{
+ long exponent = (long)flt->exponent;
+ wordptr output;
+ charptr buf;
+ unsigned int len;
+ unsigned int overflow = 0, underflow = 0;
+ int retval = 0;
+ long exp_bias = (1<<(exp_bits-1))-1;
+ long exp_inf = (1<<exp_bits)-1;
+
+ output = BitVector_Create(byte_size*8, TRUE);
+
+ /* copy mantissa */
+ BitVector_Interval_Copy(output, flt->mantissa, 0,
+ (N_int)((MANT_BITS-implicit1)-mant_bits),
+ mant_bits);
+
+ /* round mantissa */
+ if (BitVector_bit_test(flt->mantissa, (MANT_BITS-implicit1)-(mant_bits+1)))
+ BitVector_increment(output);
+
+ if (BitVector_bit_test(output, mant_bits)) {
+ /* overflowed, so zero mantissa (and set explicit bit if necessary) */
+ BitVector_Empty(output);
+ BitVector_Bit_Copy(output, mant_bits-1, !implicit1);
+ /* and up the exponent (checking for overflow) */
+ if (exponent+1 >= EXP_INF)
+ overflow = 1;
+ else
+ exponent++;
+ }
+
+ /* adjust the exponent to the output bias, checking for overflow */
+ exponent -= EXP_BIAS-exp_bias;
+ if (exponent >= exp_inf)
+ overflow = 1;
+ else if (exponent <= 0)
+ underflow = 1;
+
+ /* underflow and overflow both set!? */
+ if (underflow && overflow)
+ yasm_internal_error(N_("Both underflow and overflow set"));
+
+ /* check for underflow or overflow and set up appropriate output */
+ if (underflow) {
+ BitVector_Empty(output);
+ exponent = 0;
+ if (!(flt->flags & FLAG_ISZERO))
+ retval = -1;
+ } else if (overflow) {
+ BitVector_Empty(output);
+ exponent = exp_inf;
+ retval = 1;
+ }
+
+ /* move exponent into place */
+ BitVector_Chunk_Store(output, exp_bits, mant_bits, (N_long)exponent);
+
+ /* merge in sign bit */
+ BitVector_Bit_Copy(output, byte_size*8-1, flt->sign);
+
+ /* get little-endian bytes */
+ buf = BitVector_Block_Read(output, &len);
+ if (len < byte_size)
+ yasm_internal_error(
+ N_("Byte length of BitVector does not match bit length"));
+
+ /* copy to output */
+ memcpy(ptr, buf, byte_size*sizeof(unsigned char));
+
+ /* free allocated resources */
+ yasm_xfree(buf);
+
+ BitVector_Destroy(output);
+
+ return retval;
+}
+
+/* IEEE-754r "half precision" format:
+ * 16 bits:
+ * 15 9 Bit 0
+ * | | |
+ * seee eemm mmmm mmmm
+ *
+ * e = bias 15 exponent
+ * s = sign bit
+ * m = mantissa bits, bit 10 is an implied one bit.
+ *
+ * IEEE-754 (Intel) "single precision" format:
+ * 32 bits:
+ * Bit 31 Bit 22 Bit 0
+ * | | |
+ * seeeeeee emmmmmmm mmmmmmmm mmmmmmmm
+ *
+ * e = bias 127 exponent
+ * s = sign bit
+ * m = mantissa bits, bit 23 is an implied one bit.
+ *
+ * IEEE-754 (Intel) "double precision" format:
+ * 64 bits:
+ * bit 63 bit 51 bit 0
+ * | | |
+ * seeeeeee eeeemmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm
+ *
+ * e = bias 1023 exponent.
+ * s = sign bit.
+ * m = mantissa bits. Bit 52 is an implied one bit.
+ *
+ * IEEE-754 (Intel) "extended precision" format:
+ * 80 bits:
+ * bit 79 bit 63 bit 0
+ * | | |
+ * seeeeeee eeeeeeee mmmmmmmm m...m m...m m...m m...m m...m
+ *
+ * e = bias 16383 exponent
+ * m = 64 bit mantissa with NO implied bit!
+ * s = sign (for mantissa)
+ */
+int
+yasm_floatnum_get_sized(const yasm_floatnum *flt, unsigned char *ptr,
+ size_t destsize, size_t valsize, size_t shift,
+ int bigendian, int warn)
+{
+ int retval;
+ if (destsize*8 != valsize || shift>0 || bigendian) {
+ /* TODO */
+ yasm_internal_error(N_("unsupported floatnum functionality"));
+ }
+ switch (destsize) {
+ case 2:
+ retval = floatnum_get_common(flt, ptr, 2, 10, 1, 5);
+ break;
+ case 4:
+ retval = floatnum_get_common(flt, ptr, 4, 23, 1, 8);
+ break;
+ case 8:
+ retval = floatnum_get_common(flt, ptr, 8, 52, 1, 11);
+ break;
+ case 10:
+ retval = floatnum_get_common(flt, ptr, 10, 64, 0, 15);
+ break;
+ default:
+ yasm_internal_error(N_("Invalid float conversion size"));
+ /*@notreached@*/
+ return 1;
+ }
+ if (warn) {
+ if (retval < 0)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("underflow in floating point expression"));
+ else if (retval > 0)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("overflow in floating point expression"));
+ }
+ return retval;
+}
+
+/* 1 if the size is valid, 0 if it isn't */
+int
+yasm_floatnum_check_size(/*@unused@*/ const yasm_floatnum *flt, size_t size)
+{
+ switch (size) {
+ case 16:
+ case 32:
+ case 64:
+ case 80:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+void
+yasm_floatnum_print(const yasm_floatnum *flt, FILE *f)
+{
+ unsigned char out[10];
+ unsigned char *str;
+ int i;
+
+ /* Internal format */
+ str = BitVector_to_Hex(flt->mantissa);
+ fprintf(f, "%c %s *2^%04x\n", flt->sign?'-':'+', (char *)str,
+ flt->exponent);
+ yasm_xfree(str);
+
+ /* 32-bit (single precision) format */
+ fprintf(f, "32-bit: %d: ",
+ yasm_floatnum_get_sized(flt, out, 4, 32, 0, 0, 0));
+ for (i=0; i<4; i++)
+ fprintf(f, "%02x ", out[i]);
+ fprintf(f, "\n");
+
+ /* 64-bit (double precision) format */
+ fprintf(f, "64-bit: %d: ",
+ yasm_floatnum_get_sized(flt, out, 8, 64, 0, 0, 0));
+ for (i=0; i<8; i++)
+ fprintf(f, "%02x ", out[i]);
+ fprintf(f, "\n");
+
+ /* 80-bit (extended precision) format */
+ fprintf(f, "80-bit: %d: ",
+ yasm_floatnum_get_sized(flt, out, 10, 80, 0, 0, 0));
+ for (i=0; i<10; i++)
+ fprintf(f, "%02x ", out[i]);
+ fprintf(f, "\n");
+}
diff --git a/contrib/tools/yasm/libyasm/floatnum.h b/contrib/tools/yasm/libyasm/floatnum.h
index d2c7042097..78739519c4 100644
--- a/contrib/tools/yasm/libyasm/floatnum.h
+++ b/contrib/tools/yasm/libyasm/floatnum.h
@@ -1,131 +1,131 @@
-/**
- * \file libyasm/floatnum.h
- * \brief YASM floating point (IEEE) interface.
- *
- * \license
- * Copyright (C) 2001-2007 Peter Johnson
- *
- * Based on public-domain x86 assembly code by Randall Hyde (8/28/91).
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- * \endlicense
- */
-#ifndef YASM_FLOATNUM_H
-#define YASM_FLOATNUM_H
-
-#ifndef YASM_LIB_DECL
-#define YASM_LIB_DECL
-#endif
-
-/** Initialize floatnum internal data structures. */
-YASM_LIB_DECL
-void yasm_floatnum_initialize(void);
-
-/** Clean up internal floatnum allocations. */
-YASM_LIB_DECL
-void yasm_floatnum_cleanup(void);
-
-/** Create a new floatnum from a decimal string. The input string must be in
- * standard C representation ([+-]123.456e[-+]789).
- * \param str floating point decimal string
- * \return Newly allocated floatnum.
- */
-YASM_LIB_DECL
-/*@only@*/ yasm_floatnum *yasm_floatnum_create(const char *str);
-
-/** Duplicate a floatnum.
- * \param flt floatnum
- * \return Newly allocated floatnum with the same value as flt.
- */
-YASM_LIB_DECL
-/*@only@*/ yasm_floatnum *yasm_floatnum_copy(const yasm_floatnum *flt);
-
-/** Destroy (free allocated memory for) a floatnum.
- * \param flt floatnum
- */
-YASM_LIB_DECL
-void yasm_floatnum_destroy(/*@only@*/ yasm_floatnum *flt);
-
-/** Floating point calculation function: acc = acc op operand.
- * \note Not all operations in yasm_expr_op may be supported; unsupported
- * operations will result in an error.
- * \param acc floatnum accumulator
- * \param op operation
- * \param operand floatnum operand
- * \return Nonzero on error.
- */
-YASM_LIB_DECL
-int yasm_floatnum_calc(yasm_floatnum *acc, yasm_expr_op op,
- yasm_floatnum *operand);
-
-/** Convert a floatnum to single-precision and return as 32-bit value.
- * The 32-bit value is a "standard" C value (eg, of unknown endian).
- * \param flt floatnum
- * \param ret_val pointer to storage for 32-bit output
- * \return Nonzero if flt can't fit into single precision: -1 if underflow
- * occurred, 1 if overflow occurred.
- */
-YASM_LIB_DECL
-int yasm_floatnum_get_int(const yasm_floatnum *flt,
- /*@out@*/ unsigned long *ret_val);
-
-/** Output a #yasm_floatnum to buffer in little-endian or big-endian. Puts the
- * value into the least significant bits of the destination, or may be shifted
- * into more significant bits by the shift parameter. The destination bits are
- * cleared before being set. [0] should be the first byte output to the file.
- * \note Not all sizes are valid. Currently, only 32 (single-precision), 64
- * (double-precision), and 80 (extended-precision) are valid sizes.
- * Use yasm_floatnum_check_size() to check for supported sizes.
- * \param flt floatnum
- * \param ptr pointer to storage for size bytes of output
- * \param destsize destination size (in bytes)
- * \param valsize size (in bits)
- * \param shift left shift (in bits)
- * \param bigendian endianness (nonzero=big, zero=little)
- * \param warn enables standard overflow/underflow warnings
- * \return Nonzero if flt can't fit into the specified precision: -1 if
- * underflow occurred, 1 if overflow occurred.
- */
-YASM_LIB_DECL
-int yasm_floatnum_get_sized(const yasm_floatnum *flt, unsigned char *ptr,
- size_t destsize, size_t valsize, size_t shift,
- int bigendian, int warn);
-
-/** Basic check to see if size is valid for flt conversion (using
- * yasm_floatnum_get_sized()). Doesn't actually check for underflow/overflow
- * but rather checks for size=32,64,80
- * (at present).
- * \param flt floatnum
- * \param size number of bits of output space
- * \return 1 if valid size, 0 if invalid size.
- */
-YASM_LIB_DECL
-int yasm_floatnum_check_size(const yasm_floatnum *flt, size_t size);
-
-/** Print various representations of a floatnum. For debugging purposes only.
- * \param f file
- * \param flt floatnum
- */
-YASM_LIB_DECL
-void yasm_floatnum_print(const yasm_floatnum *flt, FILE *f);
-
-#endif
+/**
+ * \file libyasm/floatnum.h
+ * \brief YASM floating point (IEEE) interface.
+ *
+ * \license
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Based on public-domain x86 assembly code by Randall Hyde (8/28/91).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * \endlicense
+ */
+#ifndef YASM_FLOATNUM_H
+#define YASM_FLOATNUM_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/** Initialize floatnum internal data structures. */
+YASM_LIB_DECL
+void yasm_floatnum_initialize(void);
+
+/** Clean up internal floatnum allocations. */
+YASM_LIB_DECL
+void yasm_floatnum_cleanup(void);
+
+/** Create a new floatnum from a decimal string. The input string must be in
+ * standard C representation ([+-]123.456e[-+]789).
+ * \param str floating point decimal string
+ * \return Newly allocated floatnum.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_floatnum *yasm_floatnum_create(const char *str);
+
+/** Duplicate a floatnum.
+ * \param flt floatnum
+ * \return Newly allocated floatnum with the same value as flt.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_floatnum *yasm_floatnum_copy(const yasm_floatnum *flt);
+
+/** Destroy (free allocated memory for) a floatnum.
+ * \param flt floatnum
+ */
+YASM_LIB_DECL
+void yasm_floatnum_destroy(/*@only@*/ yasm_floatnum *flt);
+
+/** Floating point calculation function: acc = acc op operand.
+ * \note Not all operations in yasm_expr_op may be supported; unsupported
+ * operations will result in an error.
+ * \param acc floatnum accumulator
+ * \param op operation
+ * \param operand floatnum operand
+ * \return Nonzero on error.
+ */
+YASM_LIB_DECL
+int yasm_floatnum_calc(yasm_floatnum *acc, yasm_expr_op op,
+ yasm_floatnum *operand);
+
+/** Convert a floatnum to single-precision and return as 32-bit value.
+ * The 32-bit value is a "standard" C value (eg, of unknown endian).
+ * \param flt floatnum
+ * \param ret_val pointer to storage for 32-bit output
+ * \return Nonzero if flt can't fit into single precision: -1 if underflow
+ * occurred, 1 if overflow occurred.
+ */
+YASM_LIB_DECL
+int yasm_floatnum_get_int(const yasm_floatnum *flt,
+ /*@out@*/ unsigned long *ret_val);
+
+/** Output a #yasm_floatnum to buffer in little-endian or big-endian. Puts the
+ * value into the least significant bits of the destination, or may be shifted
+ * into more significant bits by the shift parameter. The destination bits are
+ * cleared before being set. [0] should be the first byte output to the file.
+ * \note Not all sizes are valid. Currently, only 32 (single-precision), 64
+ * (double-precision), and 80 (extended-precision) are valid sizes.
+ * Use yasm_floatnum_check_size() to check for supported sizes.
+ * \param flt floatnum
+ * \param ptr pointer to storage for size bytes of output
+ * \param destsize destination size (in bytes)
+ * \param valsize size (in bits)
+ * \param shift left shift (in bits)
+ * \param bigendian endianness (nonzero=big, zero=little)
+ * \param warn enables standard overflow/underflow warnings
+ * \return Nonzero if flt can't fit into the specified precision: -1 if
+ * underflow occurred, 1 if overflow occurred.
+ */
+YASM_LIB_DECL
+int yasm_floatnum_get_sized(const yasm_floatnum *flt, unsigned char *ptr,
+ size_t destsize, size_t valsize, size_t shift,
+ int bigendian, int warn);
+
+/** Basic check to see if size is valid for flt conversion (using
+ * yasm_floatnum_get_sized()). Doesn't actually check for underflow/overflow
+ * but rather checks for size=32,64,80
+ * (at present).
+ * \param flt floatnum
+ * \param size number of bits of output space
+ * \return 1 if valid size, 0 if invalid size.
+ */
+YASM_LIB_DECL
+int yasm_floatnum_check_size(const yasm_floatnum *flt, size_t size);
+
+/** Print various representations of a floatnum. For debugging purposes only.
+ * \param f file
+ * \param flt floatnum
+ */
+YASM_LIB_DECL
+void yasm_floatnum_print(const yasm_floatnum *flt, FILE *f);
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/genmodule.c b/contrib/tools/yasm/libyasm/genmodule.c
index 867d93a5b2..7ada3504c6 100644
--- a/contrib/tools/yasm/libyasm/genmodule.c
+++ b/contrib/tools/yasm/libyasm/genmodule.c
@@ -1,228 +1,228 @@
-/*
- *
- * Generate module.c from module.in and Makefile.am or Makefile.
- *
- * Copyright (C) 2004-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "compat-queue.h"
-
-#define OUTPUT "module.c"
-#define MAXNAME 128
-#define MAXLINE 1024
-#define MAXMODULES 128
-#define MAXINCLUDES 256
-
-typedef struct include {
- STAILQ_ENTRY(include) link;
- char *filename;
-} include;
-
-int
-main(int argc, char *argv[])
-{
- FILE *in, *out;
- char *str;
- int i;
- size_t len;
- char *strp;
- char *modules[MAXMODULES];
- int num_modules = 0;
- STAILQ_HEAD(includehead, include) includes =
- STAILQ_HEAD_INITIALIZER(includes);
- include *inc;
- int isam = 0;
- int linecont = 0;
-
- if (argc != 3) {
- fprintf(stderr, "Usage: %s <module.in> <Makefile[.am]>\n", argv[0]);
- return EXIT_FAILURE;
- }
-
- str = malloc(MAXLINE);
-
- /* Starting with initial input Makefile, look for include <file> or
- * YASM_MODULES += <module>. Note this currently doesn't handle
- * a relative starting path.
- */
- len = strlen(argv[2]);
- inc = malloc(sizeof(include));
- inc->filename = malloc(len+1);
- strcpy(inc->filename, argv[2]);
- STAILQ_INSERT_TAIL(&includes, inc, link);
-
- isam = argv[2][len-2] == 'a' && argv[2][len-1] == 'm';
-
- while (!STAILQ_EMPTY(&includes)) {
- inc = STAILQ_FIRST(&includes);
- STAILQ_REMOVE_HEAD(&includes, link);
- in = fopen(inc->filename, "rt");
- if (!in) {
- fprintf(stderr, "Could not open `%s'.\n", inc->filename);
- return EXIT_FAILURE;
- }
- free(inc->filename);
- free(inc);
-
- while (fgets(str, MAXLINE, in)) {
- /* Strip off any trailing whitespace */
- len = strlen(str);
- if (len > 0) {
- strp = &str[len-1];
- while (len > 0 && isspace(*strp)) {
- *strp-- = '\0';
- len--;
- }
- }
-
- strp = str;
-
- /* Skip whitespace */
- while (isspace(*strp))
- strp++;
-
- /* Skip comments */
- if (*strp == '#')
- continue;
-
- /* If line continuation, skip to continue copy */
- if (linecont)
- goto keepgoing;
-
- /* Check for include if original input is .am file */
- if (isam && strncmp(strp, "include", 7) == 0 && isspace(strp[7])) {
- strp += 7;
- while (isspace(*strp))
- strp++;
- /* Build new include and add to end of list */
- inc = malloc(sizeof(include));
- inc->filename = malloc(strlen(strp)+1);
- strcpy(inc->filename, strp);
- STAILQ_INSERT_TAIL(&includes, inc, link);
- continue;
- }
-
- /* Check for YASM_MODULES = or += */
- if (strncmp(strp, "YASM_MODULES", 12) != 0)
- continue;
- strp += 12;
- while (isspace(*strp))
- strp++;
- if (strncmp(strp, "+=", 2) != 0 && *strp != '=')
- continue;
- if (*strp == '+')
- strp++;
- strp++;
- while (isspace(*strp))
- strp++;
-
-keepgoing:
- /* Check for continuation */
- if (len > 0 && str[len-1] == '\\') {
- str[len-1] = '\0';
- while (isspace(*strp))
- *strp-- = '\0';
- linecont = 1;
- } else
- linecont = 0;
-
- while (*strp != '\0') {
- /* Copy module name */
- modules[num_modules] = malloc(MAXNAME);
- len = 0;
- while (*strp != '\0' && !isspace(*strp))
- modules[num_modules][len++] = *strp++;
- modules[num_modules][len] = '\0';
- num_modules++;
-
- while (isspace(*strp))
- strp++;
- }
- }
- fclose(in);
- }
-
- out = fopen(OUTPUT, "wt");
-
- if (!out) {
- fprintf(stderr, "Could not open `%s'.\n", OUTPUT);
- return EXIT_FAILURE;
- }
-
- fprintf(out, "/* This file auto-generated by genmodule.c"
- " - don't edit it */\n\n");
-
- in = fopen(argv[1], "rt");
- if (!in) {
- fprintf(stderr, "Could not open `%s'.\n", argv[1]);
- fclose(out);
- remove(OUTPUT);
- return EXIT_FAILURE;
- }
-
- len = 0;
- while (fgets(str, MAXLINE, in)) {
- if (strncmp(str, "MODULES_", 8) == 0) {
- len = 0;
- strp = str+8;
- while (*strp != '\0' && *strp != '_') {
- len++;
- strp++;
- }
- *strp = '\0';
-
- for (i=0; i<num_modules; i++) {
- if (strncmp(modules[i], str+8, len) == 0) {
- fprintf(out, " {\"%s\", &yasm_%s_LTX_%s},\n",
- modules[i]+len+1, modules[i]+len+1, str+8);
- }
- }
- } else if (strncmp(str, "EXTERN_LIST", 11) == 0) {
- for (i=0; i<num_modules; i++) {
- strcpy(str, modules[i]);
- strp = str;
- while (*strp != '\0' && *strp != '_')
- strp++;
- *strp++ = '\0';
-
- fprintf(out, "extern yasm_%s_module yasm_%s_LTX_%s;\n",
- str, strp, str);
- }
- } else
- fputs(str, out);
- }
-
- fclose(in);
- fclose(out);
-
- for (i=0; i<num_modules; i++)
- free(modules[i]);
- free(str);
-
- return EXIT_SUCCESS;
-}
+/*
+ *
+ * Generate module.c from module.in and Makefile.am or Makefile.
+ *
+ * Copyright (C) 2004-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "compat-queue.h"
+
+#define OUTPUT "module.c"
+#define MAXNAME 128
+#define MAXLINE 1024
+#define MAXMODULES 128
+#define MAXINCLUDES 256
+
+typedef struct include {
+ STAILQ_ENTRY(include) link;
+ char *filename;
+} include;
+
+int
+main(int argc, char *argv[])
+{
+ FILE *in, *out;
+ char *str;
+ int i;
+ size_t len;
+ char *strp;
+ char *modules[MAXMODULES];
+ int num_modules = 0;
+ STAILQ_HEAD(includehead, include) includes =
+ STAILQ_HEAD_INITIALIZER(includes);
+ include *inc;
+ int isam = 0;
+ int linecont = 0;
+
+ if (argc != 3) {
+ fprintf(stderr, "Usage: %s <module.in> <Makefile[.am]>\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ str = malloc(MAXLINE);
+
+ /* Starting with initial input Makefile, look for include <file> or
+ * YASM_MODULES += <module>. Note this currently doesn't handle
+ * a relative starting path.
+ */
+ len = strlen(argv[2]);
+ inc = malloc(sizeof(include));
+ inc->filename = malloc(len+1);
+ strcpy(inc->filename, argv[2]);
+ STAILQ_INSERT_TAIL(&includes, inc, link);
+
+ isam = argv[2][len-2] == 'a' && argv[2][len-1] == 'm';
+
+ while (!STAILQ_EMPTY(&includes)) {
+ inc = STAILQ_FIRST(&includes);
+ STAILQ_REMOVE_HEAD(&includes, link);
+ in = fopen(inc->filename, "rt");
+ if (!in) {
+ fprintf(stderr, "Could not open `%s'.\n", inc->filename);
+ return EXIT_FAILURE;
+ }
+ free(inc->filename);
+ free(inc);
+
+ while (fgets(str, MAXLINE, in)) {
+ /* Strip off any trailing whitespace */
+ len = strlen(str);
+ if (len > 0) {
+ strp = &str[len-1];
+ while (len > 0 && isspace(*strp)) {
+ *strp-- = '\0';
+ len--;
+ }
+ }
+
+ strp = str;
+
+ /* Skip whitespace */
+ while (isspace(*strp))
+ strp++;
+
+ /* Skip comments */
+ if (*strp == '#')
+ continue;
+
+ /* If line continuation, skip to continue copy */
+ if (linecont)
+ goto keepgoing;
+
+ /* Check for include if original input is .am file */
+ if (isam && strncmp(strp, "include", 7) == 0 && isspace(strp[7])) {
+ strp += 7;
+ while (isspace(*strp))
+ strp++;
+ /* Build new include and add to end of list */
+ inc = malloc(sizeof(include));
+ inc->filename = malloc(strlen(strp)+1);
+ strcpy(inc->filename, strp);
+ STAILQ_INSERT_TAIL(&includes, inc, link);
+ continue;
+ }
+
+ /* Check for YASM_MODULES = or += */
+ if (strncmp(strp, "YASM_MODULES", 12) != 0)
+ continue;
+ strp += 12;
+ while (isspace(*strp))
+ strp++;
+ if (strncmp(strp, "+=", 2) != 0 && *strp != '=')
+ continue;
+ if (*strp == '+')
+ strp++;
+ strp++;
+ while (isspace(*strp))
+ strp++;
+
+keepgoing:
+ /* Check for continuation */
+ if (len > 0 && str[len-1] == '\\') {
+ str[len-1] = '\0';
+ while (isspace(*strp))
+ *strp-- = '\0';
+ linecont = 1;
+ } else
+ linecont = 0;
+
+ while (*strp != '\0') {
+ /* Copy module name */
+ modules[num_modules] = malloc(MAXNAME);
+ len = 0;
+ while (*strp != '\0' && !isspace(*strp))
+ modules[num_modules][len++] = *strp++;
+ modules[num_modules][len] = '\0';
+ num_modules++;
+
+ while (isspace(*strp))
+ strp++;
+ }
+ }
+ fclose(in);
+ }
+
+ out = fopen(OUTPUT, "wt");
+
+ if (!out) {
+ fprintf(stderr, "Could not open `%s'.\n", OUTPUT);
+ return EXIT_FAILURE;
+ }
+
+ fprintf(out, "/* This file auto-generated by genmodule.c"
+ " - don't edit it */\n\n");
+
+ in = fopen(argv[1], "rt");
+ if (!in) {
+ fprintf(stderr, "Could not open `%s'.\n", argv[1]);
+ fclose(out);
+ remove(OUTPUT);
+ return EXIT_FAILURE;
+ }
+
+ len = 0;
+ while (fgets(str, MAXLINE, in)) {
+ if (strncmp(str, "MODULES_", 8) == 0) {
+ len = 0;
+ strp = str+8;
+ while (*strp != '\0' && *strp != '_') {
+ len++;
+ strp++;
+ }
+ *strp = '\0';
+
+ for (i=0; i<num_modules; i++) {
+ if (strncmp(modules[i], str+8, len) == 0) {
+ fprintf(out, " {\"%s\", &yasm_%s_LTX_%s},\n",
+ modules[i]+len+1, modules[i]+len+1, str+8);
+ }
+ }
+ } else if (strncmp(str, "EXTERN_LIST", 11) == 0) {
+ for (i=0; i<num_modules; i++) {
+ strcpy(str, modules[i]);
+ strp = str;
+ while (*strp != '\0' && *strp != '_')
+ strp++;
+ *strp++ = '\0';
+
+ fprintf(out, "extern yasm_%s_module yasm_%s_LTX_%s;\n",
+ str, strp, str);
+ }
+ } else
+ fputs(str, out);
+ }
+
+ fclose(in);
+ fclose(out);
+
+ for (i=0; i<num_modules; i++)
+ free(modules[i]);
+ free(str);
+
+ return EXIT_SUCCESS;
+}
diff --git a/contrib/tools/yasm/libyasm/hamt.c b/contrib/tools/yasm/libyasm/hamt.c
index 59b7592109..d5f3f05f2b 100644
--- a/contrib/tools/yasm/libyasm/hamt.c
+++ b/contrib/tools/yasm/libyasm/hamt.c
@@ -1,421 +1,421 @@
-/*
- * Hash Array Mapped Trie (HAMT) implementation
- *
- * Copyright (C) 2001-2007 Peter Johnson
- *
- * Based on the paper "Ideal Hash Tries" by Phil Bagwell [2000].
- * One algorithmic change from that described in the paper: we use the LSB's
- * of the key to index the root table and move upward in the key rather than
- * use the MSBs as described in the paper. The LSBs have more entropy.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#include "util.h"
-
-#include <ctype.h>
-
-#include "libyasm-stdint.h"
-#include "coretype.h"
-#include "hamt.h"
-
-struct HAMTEntry {
- STAILQ_ENTRY(HAMTEntry) next; /* next hash table entry */
- /*@dependent@*/ const char *str; /* string being hashed */
- /*@owned@*/ void *data; /* data pointer being stored */
-};
-
-typedef struct HAMTNode {
- unsigned long BitMapKey; /* 32 bits, bitmap or hash key */
- uintptr_t BaseValue; /* Base of HAMTNode list or value */
-} HAMTNode;
-
-struct HAMT {
- STAILQ_HEAD(HAMTEntryHead, HAMTEntry) entries;
- HAMTNode *root;
- /*@exits@*/ void (*error_func) (const char *file, unsigned int line,
- const char *message);
- unsigned long (*HashKey) (const char *key);
- unsigned long (*ReHashKey) (const char *key, int Level);
- int (*CmpKey) (const char *s1, const char *s2);
-};
-
-/* XXX make a portable version of this. This depends on the pointer being
- * 4 or 2-byte aligned (as it uses the LSB of the pointer variable to store
- * the subtrie flag!
- */
-#define IsSubTrie(n) ((n)->BaseValue & 1)
-#define SetSubTrie(h, n, v) do { \
- if ((uintptr_t)(v) & 1) \
- h->error_func(__FILE__, __LINE__, \
- N_("Subtrie is seen as subtrie before flag is set (misaligned?)")); \
- (n)->BaseValue = (uintptr_t)(v) | 1; \
- } while (0)
-#define SetValue(h, n, v) do { \
- if ((uintptr_t)(v) & 1) \
- h->error_func(__FILE__, __LINE__, \
- N_("Value is seen as subtrie (misaligned?)")); \
- (n)->BaseValue = (uintptr_t)(v); \
- } while (0)
-#define GetSubTrie(n) (HAMTNode *)(((n)->BaseValue | 1) ^ 1)
-
-static unsigned long
-HashKey(const char *key)
-{
- unsigned long a=31415, b=27183, vHash;
- for (vHash=0; *key; key++, a*=b)
- vHash = a*vHash + *key;
- return vHash;
-}
-
-static unsigned long
-ReHashKey(const char *key, int Level)
-{
- unsigned long a=31415, b=27183, vHash;
- for (vHash=0; *key; key++, a*=b)
- vHash = a*vHash*(unsigned long)Level + *key;
- return vHash;
-}
-
-static unsigned long
-HashKey_nocase(const char *key)
-{
- unsigned long a=31415, b=27183, vHash;
- for (vHash=0; *key; key++, a*=b)
- vHash = a*vHash + tolower(*key);
- return vHash;
-}
-
-static unsigned long
-ReHashKey_nocase(const char *key, int Level)
-{
- unsigned long a=31415, b=27183, vHash;
- for (vHash=0; *key; key++, a*=b)
- vHash = a*vHash*(unsigned long)Level + tolower(*key);
- return vHash;
-}
-
-HAMT *
-HAMT_create(int nocase, /*@exits@*/ void (*error_func)
- (const char *file, unsigned int line, const char *message))
-{
- /*@out@*/ HAMT *hamt = yasm_xmalloc(sizeof(HAMT));
- int i;
-
- STAILQ_INIT(&hamt->entries);
- hamt->root = yasm_xmalloc(32*sizeof(HAMTNode));
-
- for (i=0; i<32; i++) {
- hamt->root[i].BitMapKey = 0;
- hamt->root[i].BaseValue = 0;
- }
-
- hamt->error_func = error_func;
- if (nocase) {
- hamt->HashKey = HashKey_nocase;
- hamt->ReHashKey = ReHashKey_nocase;
- hamt->CmpKey = yasm__strcasecmp;
- } else {
- hamt->HashKey = HashKey;
- hamt->ReHashKey = ReHashKey;
- hamt->CmpKey = strcmp;
- }
-
- return hamt;
-}
-
-static void
-HAMT_delete_trie(HAMTNode *node)
-{
- if (IsSubTrie(node)) {
- unsigned long i, Size;
-
- /* Count total number of bits in bitmap to determine size */
- BitCount(Size, node->BitMapKey);
- Size &= 0x1F;
- if (Size == 0)
- Size = 32;
-
- for (i=0; i<Size; i++)
- HAMT_delete_trie(&(GetSubTrie(node))[i]);
- yasm_xfree(GetSubTrie(node));
- }
-}
-
-void
-HAMT_destroy(HAMT *hamt, void (*deletefunc) (/*@only@*/ void *data))
-{
- int i;
-
- /* delete entries */
- while (!STAILQ_EMPTY(&hamt->entries)) {
- HAMTEntry *entry;
- entry = STAILQ_FIRST(&hamt->entries);
- STAILQ_REMOVE_HEAD(&hamt->entries, next);
- deletefunc(entry->data);
- yasm_xfree(entry);
- }
-
- /* delete trie */
- for (i=0; i<32; i++)
- HAMT_delete_trie(&hamt->root[i]);
-
- yasm_xfree(hamt->root);
- yasm_xfree(hamt);
-}
-
-int
-HAMT_traverse(HAMT *hamt, void *d,
- int (*func) (/*@dependent@*/ /*@null@*/ void *node,
- /*@null@*/ void *d))
-{
- HAMTEntry *entry;
- STAILQ_FOREACH(entry, &hamt->entries, next) {
- int retval = func(entry->data, d);
- if (retval != 0)
- return retval;
- }
- return 0;
-}
-
-const HAMTEntry *
-HAMT_first(const HAMT *hamt)
-{
- return STAILQ_FIRST(&hamt->entries);
-}
-
-const HAMTEntry *
-HAMT_next(const HAMTEntry *prev)
-{
- return STAILQ_NEXT(prev, next);
-}
-
-void *
-HAMTEntry_get_data(const HAMTEntry *entry)
-{
- return entry->data;
-}
-
-/*@-temptrans -kepttrans -mustfree@*/
-void *
-HAMT_insert(HAMT *hamt, const char *str, void *data, int *replace,
- void (*deletefunc) (/*@only@*/ void *data))
-{
- HAMTNode *node, *newnodes;
- HAMTEntry *entry;
- unsigned long key, keypart, Map;
- int keypartbits = 0;
- int level = 0;
-
- key = hamt->HashKey(str);
- keypart = key & 0x1F;
- node = &hamt->root[keypart];
-
- if (!node->BaseValue) {
- node->BitMapKey = key;
- entry = yasm_xmalloc(sizeof(HAMTEntry));
- entry->str = str;
- entry->data = data;
- STAILQ_INSERT_TAIL(&hamt->entries, entry, next);
- SetValue(hamt, node, entry);
- if (IsSubTrie(node))
- hamt->error_func(__FILE__, __LINE__,
- N_("Data is seen as subtrie (misaligned?)"));
- *replace = 1;
- return data;
- }
-
- for (;;) {
- if (!(IsSubTrie(node))) {
- if (node->BitMapKey == key
- && hamt->CmpKey(((HAMTEntry *)(node->BaseValue))->str,
- str) == 0) {
- /*@-branchstate@*/
- if (*replace) {
- deletefunc(((HAMTEntry *)(node->BaseValue))->data);
- ((HAMTEntry *)(node->BaseValue))->str = str;
- ((HAMTEntry *)(node->BaseValue))->data = data;
- } else
- deletefunc(data);
- /*@=branchstate@*/
- return ((HAMTEntry *)(node->BaseValue))->data;
- } else {
- unsigned long key2 = node->BitMapKey;
- /* build tree downward until keys differ */
- for (;;) {
- unsigned long keypart2;
-
- /* replace node with subtrie */
- keypartbits += 5;
- if (keypartbits > 30) {
- /* Exceeded 32 bits: rehash */
- key = hamt->ReHashKey(str, level);
- key2 = hamt->ReHashKey(
- ((HAMTEntry *)(node->BaseValue))->str, level);
- keypartbits = 0;
- }
- keypart = (key >> keypartbits) & 0x1F;
- keypart2 = (key2 >> keypartbits) & 0x1F;
-
- if (keypart == keypart2) {
- /* Still equal, build one-node subtrie and continue
- * downward.
- */
- newnodes = yasm_xmalloc(sizeof(HAMTNode));
- newnodes[0].BitMapKey = key2;
- newnodes[0].BaseValue = node->BaseValue;
- node->BitMapKey = 1<<keypart;
- SetSubTrie(hamt, node, newnodes);
- node = &newnodes[0];
- level++;
- } else {
- /* partitioned: allocate two-node subtrie */
- newnodes = yasm_xmalloc(2*sizeof(HAMTNode));
-
- entry = yasm_xmalloc(sizeof(HAMTEntry));
- entry->str = str;
- entry->data = data;
- STAILQ_INSERT_TAIL(&hamt->entries, entry, next);
-
- /* Copy nodes into subtrie based on order */
- if (keypart2 < keypart) {
- newnodes[0].BitMapKey = key2;
- newnodes[0].BaseValue = node->BaseValue;
- newnodes[1].BitMapKey = key;
- SetValue(hamt, &newnodes[1], entry);
- } else {
- newnodes[0].BitMapKey = key;
- SetValue(hamt, &newnodes[0], entry);
- newnodes[1].BitMapKey = key2;
- newnodes[1].BaseValue = node->BaseValue;
- }
-
- /* Set bits in bitmap corresponding to keys */
- node->BitMapKey = (1UL<<keypart) | (1UL<<keypart2);
- SetSubTrie(hamt, node, newnodes);
- *replace = 1;
- return data;
- }
- }
- }
- }
-
- /* Subtrie: look up in bitmap */
- keypartbits += 5;
- if (keypartbits > 30) {
- /* Exceeded 32 bits of current key: rehash */
- key = hamt->ReHashKey(str, level);
- keypartbits = 0;
- }
- keypart = (key >> keypartbits) & 0x1F;
- if (!(node->BitMapKey & (1<<keypart))) {
- /* bit is 0 in bitmap -> add node to table */
- unsigned long Size;
-
- /* set bit to 1 */
- node->BitMapKey |= 1<<keypart;
-
- /* Count total number of bits in bitmap to determine new size */
- BitCount(Size, node->BitMapKey);
- Size &= 0x1F;
- if (Size == 0)
- Size = 32;
- newnodes = yasm_xmalloc(Size*sizeof(HAMTNode));
-
- /* Count bits below to find where to insert new node at */
- BitCount(Map, node->BitMapKey & ~((~0UL)<<keypart));
- Map &= 0x1F; /* Clamp to <32 */
- /* Copy existing nodes leaving gap for new node */
- memcpy(newnodes, GetSubTrie(node), Map*sizeof(HAMTNode));
- memcpy(&newnodes[Map+1], &(GetSubTrie(node))[Map],
- (Size-Map-1)*sizeof(HAMTNode));
- /* Delete old subtrie */
- yasm_xfree(GetSubTrie(node));
- /* Set up new node */
- newnodes[Map].BitMapKey = key;
- entry = yasm_xmalloc(sizeof(HAMTEntry));
- entry->str = str;
- entry->data = data;
- STAILQ_INSERT_TAIL(&hamt->entries, entry, next);
- SetValue(hamt, &newnodes[Map], entry);
- SetSubTrie(hamt, node, newnodes);
-
- *replace = 1;
- return data;
- }
-
- /* Count bits below */
- BitCount(Map, node->BitMapKey & ~((~0UL)<<keypart));
- Map &= 0x1F; /* Clamp to <32 */
-
- /* Go down a level */
- level++;
- node = &(GetSubTrie(node))[Map];
- }
-}
-/*@=temptrans =kepttrans =mustfree@*/
-
-void *
-HAMT_search(HAMT *hamt, const char *str)
-{
- HAMTNode *node;
- unsigned long key, keypart, Map;
- int keypartbits = 0;
- int level = 0;
-
- key = hamt->HashKey(str);
- keypart = key & 0x1F;
- node = &hamt->root[keypart];
-
- if (!node->BaseValue)
- return NULL;
-
- for (;;) {
- if (!(IsSubTrie(node))) {
- if (node->BitMapKey == key
- && hamt->CmpKey(((HAMTEntry *)(node->BaseValue))->str,
- str) == 0)
- return ((HAMTEntry *)(node->BaseValue))->data;
- else
- return NULL;
- }
-
- /* Subtree: look up in bitmap */
- keypartbits += 5;
- if (keypartbits > 30) {
- /* Exceeded 32 bits of current key: rehash */
- key = hamt->ReHashKey(str, level);
- keypartbits = 0;
- }
- keypart = (key >> keypartbits) & 0x1F;
- if (!(node->BitMapKey & (1<<keypart)))
- return NULL; /* bit is 0 in bitmap -> no match */
-
- /* Count bits below */
- BitCount(Map, node->BitMapKey & ~((~0UL)<<keypart));
- Map &= 0x1F; /* Clamp to <32 */
-
- /* Go down a level */
- level++;
- node = &(GetSubTrie(node))[Map];
- }
-}
-
+/*
+ * Hash Array Mapped Trie (HAMT) implementation
+ *
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Based on the paper "Ideal Hash Tries" by Phil Bagwell [2000].
+ * One algorithmic change from that described in the paper: we use the LSB's
+ * of the key to index the root table and move upward in the key rather than
+ * use the MSBs as described in the paper. The LSBs have more entropy.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "util.h"
+
+#include <ctype.h>
+
+#include "libyasm-stdint.h"
+#include "coretype.h"
+#include "hamt.h"
+
+struct HAMTEntry {
+ STAILQ_ENTRY(HAMTEntry) next; /* next hash table entry */
+ /*@dependent@*/ const char *str; /* string being hashed */
+ /*@owned@*/ void *data; /* data pointer being stored */
+};
+
+typedef struct HAMTNode {
+ unsigned long BitMapKey; /* 32 bits, bitmap or hash key */
+ uintptr_t BaseValue; /* Base of HAMTNode list or value */
+} HAMTNode;
+
+struct HAMT {
+ STAILQ_HEAD(HAMTEntryHead, HAMTEntry) entries;
+ HAMTNode *root;
+ /*@exits@*/ void (*error_func) (const char *file, unsigned int line,
+ const char *message);
+ unsigned long (*HashKey) (const char *key);
+ unsigned long (*ReHashKey) (const char *key, int Level);
+ int (*CmpKey) (const char *s1, const char *s2);
+};
+
+/* XXX make a portable version of this. This depends on the pointer being
+ * 4 or 2-byte aligned (as it uses the LSB of the pointer variable to store
+ * the subtrie flag!
+ */
+#define IsSubTrie(n) ((n)->BaseValue & 1)
+#define SetSubTrie(h, n, v) do { \
+ if ((uintptr_t)(v) & 1) \
+ h->error_func(__FILE__, __LINE__, \
+ N_("Subtrie is seen as subtrie before flag is set (misaligned?)")); \
+ (n)->BaseValue = (uintptr_t)(v) | 1; \
+ } while (0)
+#define SetValue(h, n, v) do { \
+ if ((uintptr_t)(v) & 1) \
+ h->error_func(__FILE__, __LINE__, \
+ N_("Value is seen as subtrie (misaligned?)")); \
+ (n)->BaseValue = (uintptr_t)(v); \
+ } while (0)
+#define GetSubTrie(n) (HAMTNode *)(((n)->BaseValue | 1) ^ 1)
+
+static unsigned long
+HashKey(const char *key)
+{
+ unsigned long a=31415, b=27183, vHash;
+ for (vHash=0; *key; key++, a*=b)
+ vHash = a*vHash + *key;
+ return vHash;
+}
+
+static unsigned long
+ReHashKey(const char *key, int Level)
+{
+ unsigned long a=31415, b=27183, vHash;
+ for (vHash=0; *key; key++, a*=b)
+ vHash = a*vHash*(unsigned long)Level + *key;
+ return vHash;
+}
+
+static unsigned long
+HashKey_nocase(const char *key)
+{
+ unsigned long a=31415, b=27183, vHash;
+ for (vHash=0; *key; key++, a*=b)
+ vHash = a*vHash + tolower(*key);
+ return vHash;
+}
+
+static unsigned long
+ReHashKey_nocase(const char *key, int Level)
+{
+ unsigned long a=31415, b=27183, vHash;
+ for (vHash=0; *key; key++, a*=b)
+ vHash = a*vHash*(unsigned long)Level + tolower(*key);
+ return vHash;
+}
+
+HAMT *
+HAMT_create(int nocase, /*@exits@*/ void (*error_func)
+ (const char *file, unsigned int line, const char *message))
+{
+ /*@out@*/ HAMT *hamt = yasm_xmalloc(sizeof(HAMT));
+ int i;
+
+ STAILQ_INIT(&hamt->entries);
+ hamt->root = yasm_xmalloc(32*sizeof(HAMTNode));
+
+ for (i=0; i<32; i++) {
+ hamt->root[i].BitMapKey = 0;
+ hamt->root[i].BaseValue = 0;
+ }
+
+ hamt->error_func = error_func;
+ if (nocase) {
+ hamt->HashKey = HashKey_nocase;
+ hamt->ReHashKey = ReHashKey_nocase;
+ hamt->CmpKey = yasm__strcasecmp;
+ } else {
+ hamt->HashKey = HashKey;
+ hamt->ReHashKey = ReHashKey;
+ hamt->CmpKey = strcmp;
+ }
+
+ return hamt;
+}
+
+static void
+HAMT_delete_trie(HAMTNode *node)
+{
+ if (IsSubTrie(node)) {
+ unsigned long i, Size;
+
+ /* Count total number of bits in bitmap to determine size */
+ BitCount(Size, node->BitMapKey);
+ Size &= 0x1F;
+ if (Size == 0)
+ Size = 32;
+
+ for (i=0; i<Size; i++)
+ HAMT_delete_trie(&(GetSubTrie(node))[i]);
+ yasm_xfree(GetSubTrie(node));
+ }
+}
+
+void
+HAMT_destroy(HAMT *hamt, void (*deletefunc) (/*@only@*/ void *data))
+{
+ int i;
+
+ /* delete entries */
+ while (!STAILQ_EMPTY(&hamt->entries)) {
+ HAMTEntry *entry;
+ entry = STAILQ_FIRST(&hamt->entries);
+ STAILQ_REMOVE_HEAD(&hamt->entries, next);
+ deletefunc(entry->data);
+ yasm_xfree(entry);
+ }
+
+ /* delete trie */
+ for (i=0; i<32; i++)
+ HAMT_delete_trie(&hamt->root[i]);
+
+ yasm_xfree(hamt->root);
+ yasm_xfree(hamt);
+}
+
+int
+HAMT_traverse(HAMT *hamt, void *d,
+ int (*func) (/*@dependent@*/ /*@null@*/ void *node,
+ /*@null@*/ void *d))
+{
+ HAMTEntry *entry;
+ STAILQ_FOREACH(entry, &hamt->entries, next) {
+ int retval = func(entry->data, d);
+ if (retval != 0)
+ return retval;
+ }
+ return 0;
+}
+
+const HAMTEntry *
+HAMT_first(const HAMT *hamt)
+{
+ return STAILQ_FIRST(&hamt->entries);
+}
+
+const HAMTEntry *
+HAMT_next(const HAMTEntry *prev)
+{
+ return STAILQ_NEXT(prev, next);
+}
+
+void *
+HAMTEntry_get_data(const HAMTEntry *entry)
+{
+ return entry->data;
+}
+
+/*@-temptrans -kepttrans -mustfree@*/
+void *
+HAMT_insert(HAMT *hamt, const char *str, void *data, int *replace,
+ void (*deletefunc) (/*@only@*/ void *data))
+{
+ HAMTNode *node, *newnodes;
+ HAMTEntry *entry;
+ unsigned long key, keypart, Map;
+ int keypartbits = 0;
+ int level = 0;
+
+ key = hamt->HashKey(str);
+ keypart = key & 0x1F;
+ node = &hamt->root[keypart];
+
+ if (!node->BaseValue) {
+ node->BitMapKey = key;
+ entry = yasm_xmalloc(sizeof(HAMTEntry));
+ entry->str = str;
+ entry->data = data;
+ STAILQ_INSERT_TAIL(&hamt->entries, entry, next);
+ SetValue(hamt, node, entry);
+ if (IsSubTrie(node))
+ hamt->error_func(__FILE__, __LINE__,
+ N_("Data is seen as subtrie (misaligned?)"));
+ *replace = 1;
+ return data;
+ }
+
+ for (;;) {
+ if (!(IsSubTrie(node))) {
+ if (node->BitMapKey == key
+ && hamt->CmpKey(((HAMTEntry *)(node->BaseValue))->str,
+ str) == 0) {
+ /*@-branchstate@*/
+ if (*replace) {
+ deletefunc(((HAMTEntry *)(node->BaseValue))->data);
+ ((HAMTEntry *)(node->BaseValue))->str = str;
+ ((HAMTEntry *)(node->BaseValue))->data = data;
+ } else
+ deletefunc(data);
+ /*@=branchstate@*/
+ return ((HAMTEntry *)(node->BaseValue))->data;
+ } else {
+ unsigned long key2 = node->BitMapKey;
+ /* build tree downward until keys differ */
+ for (;;) {
+ unsigned long keypart2;
+
+ /* replace node with subtrie */
+ keypartbits += 5;
+ if (keypartbits > 30) {
+ /* Exceeded 32 bits: rehash */
+ key = hamt->ReHashKey(str, level);
+ key2 = hamt->ReHashKey(
+ ((HAMTEntry *)(node->BaseValue))->str, level);
+ keypartbits = 0;
+ }
+ keypart = (key >> keypartbits) & 0x1F;
+ keypart2 = (key2 >> keypartbits) & 0x1F;
+
+ if (keypart == keypart2) {
+ /* Still equal, build one-node subtrie and continue
+ * downward.
+ */
+ newnodes = yasm_xmalloc(sizeof(HAMTNode));
+ newnodes[0].BitMapKey = key2;
+ newnodes[0].BaseValue = node->BaseValue;
+ node->BitMapKey = 1<<keypart;
+ SetSubTrie(hamt, node, newnodes);
+ node = &newnodes[0];
+ level++;
+ } else {
+ /* partitioned: allocate two-node subtrie */
+ newnodes = yasm_xmalloc(2*sizeof(HAMTNode));
+
+ entry = yasm_xmalloc(sizeof(HAMTEntry));
+ entry->str = str;
+ entry->data = data;
+ STAILQ_INSERT_TAIL(&hamt->entries, entry, next);
+
+ /* Copy nodes into subtrie based on order */
+ if (keypart2 < keypart) {
+ newnodes[0].BitMapKey = key2;
+ newnodes[0].BaseValue = node->BaseValue;
+ newnodes[1].BitMapKey = key;
+ SetValue(hamt, &newnodes[1], entry);
+ } else {
+ newnodes[0].BitMapKey = key;
+ SetValue(hamt, &newnodes[0], entry);
+ newnodes[1].BitMapKey = key2;
+ newnodes[1].BaseValue = node->BaseValue;
+ }
+
+ /* Set bits in bitmap corresponding to keys */
+ node->BitMapKey = (1UL<<keypart) | (1UL<<keypart2);
+ SetSubTrie(hamt, node, newnodes);
+ *replace = 1;
+ return data;
+ }
+ }
+ }
+ }
+
+ /* Subtrie: look up in bitmap */
+ keypartbits += 5;
+ if (keypartbits > 30) {
+ /* Exceeded 32 bits of current key: rehash */
+ key = hamt->ReHashKey(str, level);
+ keypartbits = 0;
+ }
+ keypart = (key >> keypartbits) & 0x1F;
+ if (!(node->BitMapKey & (1<<keypart))) {
+ /* bit is 0 in bitmap -> add node to table */
+ unsigned long Size;
+
+ /* set bit to 1 */
+ node->BitMapKey |= 1<<keypart;
+
+ /* Count total number of bits in bitmap to determine new size */
+ BitCount(Size, node->BitMapKey);
+ Size &= 0x1F;
+ if (Size == 0)
+ Size = 32;
+ newnodes = yasm_xmalloc(Size*sizeof(HAMTNode));
+
+ /* Count bits below to find where to insert new node at */
+ BitCount(Map, node->BitMapKey & ~((~0UL)<<keypart));
+ Map &= 0x1F; /* Clamp to <32 */
+ /* Copy existing nodes leaving gap for new node */
+ memcpy(newnodes, GetSubTrie(node), Map*sizeof(HAMTNode));
+ memcpy(&newnodes[Map+1], &(GetSubTrie(node))[Map],
+ (Size-Map-1)*sizeof(HAMTNode));
+ /* Delete old subtrie */
+ yasm_xfree(GetSubTrie(node));
+ /* Set up new node */
+ newnodes[Map].BitMapKey = key;
+ entry = yasm_xmalloc(sizeof(HAMTEntry));
+ entry->str = str;
+ entry->data = data;
+ STAILQ_INSERT_TAIL(&hamt->entries, entry, next);
+ SetValue(hamt, &newnodes[Map], entry);
+ SetSubTrie(hamt, node, newnodes);
+
+ *replace = 1;
+ return data;
+ }
+
+ /* Count bits below */
+ BitCount(Map, node->BitMapKey & ~((~0UL)<<keypart));
+ Map &= 0x1F; /* Clamp to <32 */
+
+ /* Go down a level */
+ level++;
+ node = &(GetSubTrie(node))[Map];
+ }
+}
+/*@=temptrans =kepttrans =mustfree@*/
+
+void *
+HAMT_search(HAMT *hamt, const char *str)
+{
+ HAMTNode *node;
+ unsigned long key, keypart, Map;
+ int keypartbits = 0;
+ int level = 0;
+
+ key = hamt->HashKey(str);
+ keypart = key & 0x1F;
+ node = &hamt->root[keypart];
+
+ if (!node->BaseValue)
+ return NULL;
+
+ for (;;) {
+ if (!(IsSubTrie(node))) {
+ if (node->BitMapKey == key
+ && hamt->CmpKey(((HAMTEntry *)(node->BaseValue))->str,
+ str) == 0)
+ return ((HAMTEntry *)(node->BaseValue))->data;
+ else
+ return NULL;
+ }
+
+ /* Subtree: look up in bitmap */
+ keypartbits += 5;
+ if (keypartbits > 30) {
+ /* Exceeded 32 bits of current key: rehash */
+ key = hamt->ReHashKey(str, level);
+ keypartbits = 0;
+ }
+ keypart = (key >> keypartbits) & 0x1F;
+ if (!(node->BitMapKey & (1<<keypart)))
+ return NULL; /* bit is 0 in bitmap -> no match */
+
+ /* Count bits below */
+ BitCount(Map, node->BitMapKey & ~((~0UL)<<keypart));
+ Map &= 0x1F; /* Clamp to <32 */
+
+ /* Go down a level */
+ level++;
+ node = &(GetSubTrie(node))[Map];
+ }
+}
+
diff --git a/contrib/tools/yasm/libyasm/hamt.h b/contrib/tools/yasm/libyasm/hamt.h
index 1ce9b77536..0964f83350 100644
--- a/contrib/tools/yasm/libyasm/hamt.h
+++ b/contrib/tools/yasm/libyasm/hamt.h
@@ -1,123 +1,123 @@
-/**
- * \file libyasm/hamt.h
- * \brief Hash Array Mapped Trie (HAMT) functions.
- *
- * \license
- * Copyright (C) 2001-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- * \endlicense
- */
-#ifndef YASM_HAMT_H
-#define YASM_HAMT_H
-
-#ifndef YASM_LIB_DECL
-#define YASM_LIB_DECL
-#endif
-
-/** Hash array mapped trie data structure (opaque type). */
-typedef struct HAMT HAMT;
-/** Hash array mapped trie entry (opaque type). */
-typedef struct HAMTEntry HAMTEntry;
-
-/** Create new, empty, HAMT. error_func() is called when an internal error is
- * encountered--it should NOT return to the calling function.
- * \param nocase nonzero if HAMT should be case-insensitive
- * \param error_func function called on internal error
- * \return New, empty, hash array mapped trie.
- */
-YASM_LIB_DECL
-HAMT *HAMT_create(int nocase, /*@exits@*/ void (*error_func)
- (const char *file, unsigned int line, const char *message));
-
-/** Delete HAMT and all data associated with it. Uses deletefunc() to delete
- * each data item.
- * \param hamt Hash array mapped trie
- * \param deletefunc Data deletion function
- */
-YASM_LIB_DECL
-void HAMT_destroy(/*@only@*/ HAMT *hamt,
- void (*deletefunc) (/*@only@*/ void *data));
-
-/** Insert key into HAMT, associating it with data.
- * If the key is not present in the HAMT, inserts it, sets *replace to 1, and
- * returns the data passed in.
- * If the key is already present and *replace is 0, deletes the data passed
- * in using deletefunc() and returns the data currently associated with the
- * key.
- * If the key is already present and *replace is 1, deletes the data currently
- * associated with the key using deletefunc() and replaces it with the data
- * passed in.
- * \param hamt Hash array mapped trie
- * \param str Key
- * \param data Data to associate with key
- * \param replace See above description
- * \param deletefunc Data deletion function if data is replaced
- * \return Data now associated with key.
- */
-YASM_LIB_DECL
-/*@dependent@*/ void *HAMT_insert(HAMT *hamt, /*@dependent@*/ const char *str,
- /*@only@*/ void *data, int *replace,
- void (*deletefunc) (/*@only@*/ void *data));
-
-/** Search for the data associated with a key in the HAMT.
- * \param hamt Hash array mapped trie
- * \param str Key
- * \return NULL if key/data not present in HAMT, otherwise associated data.
- */
-YASM_LIB_DECL
-/*@dependent@*/ /*@null@*/ void *HAMT_search(HAMT *hamt, const char *str);
-
-/** Traverse over all keys in HAMT, calling function on each data item.
- * \param hamt Hash array mapped trie
- * \param d Data to pass to each call to func.
- * \param func Function to call
- * \return Stops early (and returns func's return value) if func returns a
- * nonzero value; otherwise 0.
- */
-YASM_LIB_DECL
-int HAMT_traverse(HAMT *hamt, /*@null@*/ void *d,
- int (*func) (/*@dependent@*/ /*@null@*/ void *node,
- /*@null@*/ void *d));
-
-/** Get the first entry in a HAMT.
- * \param hamt Hash array mapped trie
- * \return First entry in HAMT, or NULL if HAMT is empty.
- */
-YASM_LIB_DECL
-const HAMTEntry *HAMT_first(const HAMT *hamt);
-
-/** Get the next entry in a HAMT.
- * \param prev Previous entry in HAMT
- * \return Next entry in HAMT, or NULL if no more entries.
- */
-YASM_LIB_DECL
-/*@null@*/ const HAMTEntry *HAMT_next(const HAMTEntry *prev);
-
-/** Get the corresponding data for a HAMT entry.
- * \param entry HAMT entry (as returned by HAMT_first() and HAMT_next())
- * \return Corresponding data item.
- */
-YASM_LIB_DECL
-void *HAMTEntry_get_data(const HAMTEntry *entry);
-
-#endif
+/**
+ * \file libyasm/hamt.h
+ * \brief Hash Array Mapped Trie (HAMT) functions.
+ *
+ * \license
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * \endlicense
+ */
+#ifndef YASM_HAMT_H
+#define YASM_HAMT_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/** Hash array mapped trie data structure (opaque type). */
+typedef struct HAMT HAMT;
+/** Hash array mapped trie entry (opaque type). */
+typedef struct HAMTEntry HAMTEntry;
+
+/** Create new, empty, HAMT. error_func() is called when an internal error is
+ * encountered--it should NOT return to the calling function.
+ * \param nocase nonzero if HAMT should be case-insensitive
+ * \param error_func function called on internal error
+ * \return New, empty, hash array mapped trie.
+ */
+YASM_LIB_DECL
+HAMT *HAMT_create(int nocase, /*@exits@*/ void (*error_func)
+ (const char *file, unsigned int line, const char *message));
+
+/** Delete HAMT and all data associated with it. Uses deletefunc() to delete
+ * each data item.
+ * \param hamt Hash array mapped trie
+ * \param deletefunc Data deletion function
+ */
+YASM_LIB_DECL
+void HAMT_destroy(/*@only@*/ HAMT *hamt,
+ void (*deletefunc) (/*@only@*/ void *data));
+
+/** Insert key into HAMT, associating it with data.
+ * If the key is not present in the HAMT, inserts it, sets *replace to 1, and
+ * returns the data passed in.
+ * If the key is already present and *replace is 0, deletes the data passed
+ * in using deletefunc() and returns the data currently associated with the
+ * key.
+ * If the key is already present and *replace is 1, deletes the data currently
+ * associated with the key using deletefunc() and replaces it with the data
+ * passed in.
+ * \param hamt Hash array mapped trie
+ * \param str Key
+ * \param data Data to associate with key
+ * \param replace See above description
+ * \param deletefunc Data deletion function if data is replaced
+ * \return Data now associated with key.
+ */
+YASM_LIB_DECL
+/*@dependent@*/ void *HAMT_insert(HAMT *hamt, /*@dependent@*/ const char *str,
+ /*@only@*/ void *data, int *replace,
+ void (*deletefunc) (/*@only@*/ void *data));
+
+/** Search for the data associated with a key in the HAMT.
+ * \param hamt Hash array mapped trie
+ * \param str Key
+ * \return NULL if key/data not present in HAMT, otherwise associated data.
+ */
+YASM_LIB_DECL
+/*@dependent@*/ /*@null@*/ void *HAMT_search(HAMT *hamt, const char *str);
+
+/** Traverse over all keys in HAMT, calling function on each data item.
+ * \param hamt Hash array mapped trie
+ * \param d Data to pass to each call to func.
+ * \param func Function to call
+ * \return Stops early (and returns func's return value) if func returns a
+ * nonzero value; otherwise 0.
+ */
+YASM_LIB_DECL
+int HAMT_traverse(HAMT *hamt, /*@null@*/ void *d,
+ int (*func) (/*@dependent@*/ /*@null@*/ void *node,
+ /*@null@*/ void *d));
+
+/** Get the first entry in a HAMT.
+ * \param hamt Hash array mapped trie
+ * \return First entry in HAMT, or NULL if HAMT is empty.
+ */
+YASM_LIB_DECL
+const HAMTEntry *HAMT_first(const HAMT *hamt);
+
+/** Get the next entry in a HAMT.
+ * \param prev Previous entry in HAMT
+ * \return Next entry in HAMT, or NULL if no more entries.
+ */
+YASM_LIB_DECL
+/*@null@*/ const HAMTEntry *HAMT_next(const HAMTEntry *prev);
+
+/** Get the corresponding data for a HAMT entry.
+ * \param entry HAMT entry (as returned by HAMT_first() and HAMT_next())
+ * \return Corresponding data item.
+ */
+YASM_LIB_DECL
+void *HAMTEntry_get_data(const HAMTEntry *entry);
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/insn.c b/contrib/tools/yasm/libyasm/insn.c
index 8f7a4c1978..a1ebbfc568 100644
--- a/contrib/tools/yasm/libyasm/insn.c
+++ b/contrib/tools/yasm/libyasm/insn.c
@@ -1,295 +1,295 @@
-/*
- * Mnemonic instruction bytecode
- *
- * Copyright (C) 2005-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#include "util.h"
-
-#include "libyasm-stdint.h"
-#include "coretype.h"
-
-#include "errwarn.h"
-#include "expr.h"
-#include "value.h"
-
-#include "bytecode.h"
-#include "insn.h"
-#include "arch.h"
-
-
-void
-yasm_ea_set_segreg(yasm_effaddr *ea, uintptr_t segreg)
-{
- if (!ea)
- return;
-
- if (segreg != 0 && ea->segreg != 0)
- yasm_warn_set(YASM_WARN_GENERAL,
- N_("multiple segment overrides, using leftmost"));
-
- ea->segreg = segreg;
-}
-
-yasm_insn_operand *
-yasm_operand_create_reg(uintptr_t reg)
-{
- yasm_insn_operand *retval = yasm_xmalloc(sizeof(yasm_insn_operand));
-
- retval->type = YASM_INSN__OPERAND_REG;
- retval->data.reg = reg;
- retval->seg = 0;
- retval->targetmod = 0;
- retval->size = 0;
- retval->deref = 0;
- retval->strict = 0;
-
- return retval;
-}
-
-yasm_insn_operand *
-yasm_operand_create_segreg(uintptr_t segreg)
-{
- yasm_insn_operand *retval = yasm_xmalloc(sizeof(yasm_insn_operand));
-
- retval->type = YASM_INSN__OPERAND_SEGREG;
- retval->data.reg = segreg;
- retval->seg = 0;
- retval->targetmod = 0;
- retval->size = 0;
- retval->deref = 0;
- retval->strict = 0;
-
- return retval;
-}
-
-yasm_insn_operand *
-yasm_operand_create_mem(/*@only@*/ yasm_effaddr *ea)
-{
- yasm_insn_operand *retval = yasm_xmalloc(sizeof(yasm_insn_operand));
-
- retval->type = YASM_INSN__OPERAND_MEMORY;
- retval->data.ea = ea;
- retval->seg = 0;
- retval->targetmod = 0;
- retval->size = 0;
- retval->deref = 0;
- retval->strict = 0;
- retval->size = ea->data_len * 8;
-
- return retval;
-}
-
-yasm_insn_operand *
-yasm_operand_create_imm(/*@only@*/ yasm_expr *val)
-{
- yasm_insn_operand *retval;
- const uintptr_t *reg;
-
- reg = yasm_expr_get_reg(&val, 0);
- if (reg) {
- retval = yasm_operand_create_reg(*reg);
- yasm_expr_destroy(val);
- } else {
- retval = yasm_xmalloc(sizeof(yasm_insn_operand));
- retval->type = YASM_INSN__OPERAND_IMM;
- retval->data.val = val;
- retval->seg = 0;
- retval->targetmod = 0;
- retval->size = 0;
- retval->deref = 0;
- retval->strict = 0;
- }
-
- return retval;
-}
-
-yasm_insn_operand *
-yasm_insn_ops_append(yasm_insn *insn, yasm_insn_operand *op)
-{
- if (op) {
- insn->num_operands++;
- STAILQ_INSERT_TAIL(&insn->operands, op, link);
- return op;
- }
- return (yasm_insn_operand *)NULL;
-}
-
-void
-yasm_insn_add_prefix(yasm_insn *insn, uintptr_t prefix)
-{
- insn->prefixes =
- yasm_xrealloc(insn->prefixes,
- (insn->num_prefixes+1)*sizeof(uintptr_t));
- insn->prefixes[insn->num_prefixes] = prefix;
- insn->num_prefixes++;
-}
-
-void
-yasm_insn_add_seg_prefix(yasm_insn *insn, uintptr_t segreg)
-{
- insn->segregs =
- yasm_xrealloc(insn->segregs, (insn->num_segregs+1)*sizeof(uintptr_t));
- insn->segregs[insn->num_segregs] = segreg;
- insn->num_segregs++;
-}
-
-void
-yasm_insn_initialize(yasm_insn *insn)
-{
- STAILQ_INIT(&insn->operands);
-
- insn->prefixes = NULL;
- insn->segregs = NULL;
-
- insn->num_operands = 0;
- insn->num_prefixes = 0;
- insn->num_segregs = 0;
-}
-
-void
-yasm_insn_delete(yasm_insn *insn,
- void (*ea_destroy) (/*@only@*/ yasm_effaddr *))
-{
- if (insn->num_operands > 0) {
- yasm_insn_operand *cur, *next;
-
- cur = STAILQ_FIRST(&insn->operands);
- while (cur) {
- next = STAILQ_NEXT(cur, link);
- switch (cur->type) {
- case YASM_INSN__OPERAND_MEMORY:
- ea_destroy(cur->data.ea);
- break;
- case YASM_INSN__OPERAND_IMM:
- yasm_expr_destroy(cur->data.val);
- break;
- default:
- break;
- }
- yasm_xfree(cur);
- cur = next;
- }
- }
- if (insn->num_prefixes > 0)
- yasm_xfree(insn->prefixes);
- if (insn->num_segregs > 0)
- yasm_xfree(insn->segregs);
-}
-
-void
-yasm_insn_print(const yasm_insn *insn, FILE *f, int indent_level)
-{
- const yasm_insn_operand *op;
-
- STAILQ_FOREACH (op, &insn->operands, link) {
- switch (op->type) {
- case YASM_INSN__OPERAND_REG:
- fprintf(f, "%*sReg=", indent_level, "");
- /*yasm_arch_reg_print(arch, op->data.reg, f);*/
- fprintf(f, "\n");
- break;
- case YASM_INSN__OPERAND_SEGREG:
- fprintf(f, "%*sSegReg=", indent_level, "");
- /*yasm_arch_segreg_print(arch, op->data.reg, f);*/
- fprintf(f, "\n");
- break;
- case YASM_INSN__OPERAND_MEMORY:
- fprintf(f, "%*sMemory=\n", indent_level, "");
- /*yasm_arch_ea_print(arch, op->data.ea, f, indent_level);*/
- break;
- case YASM_INSN__OPERAND_IMM:
- fprintf(f, "%*sImm=", indent_level, "");
- yasm_expr_print(op->data.val, f);
- fprintf(f, "\n");
- break;
- }
- fprintf(f, "%*sTargetMod=%lx\n", indent_level+1, "",
- (unsigned long)op->targetmod);
- fprintf(f, "%*sSize=%u\n", indent_level+1, "", op->size);
- fprintf(f, "%*sDeref=%d, Strict=%d\n", indent_level+1, "",
- (int)op->deref, (int)op->strict);
- }
-}
-
-void
-yasm_insn_finalize(yasm_insn *insn)
-{
- unsigned int i;
- yasm_insn_operand *op;
- yasm_error_class eclass;
- char *str, *xrefstr;
- unsigned long xrefline;
-
- /* Simplify the operands' expressions first. */
- for (i = 0, op = yasm_insn_ops_first(insn);
- op && i<insn->num_operands; op = yasm_insn_op_next(op), i++) {
- /* Check operand type */
- switch (op->type) {
- case YASM_INSN__OPERAND_MEMORY:
- /* Don't get over-ambitious here; some archs' memory expr
- * parser are sensitive to the presence of *1, etc, so don't
- * simplify reg*1 identities.
- */
- if (op->data.ea)
- op->data.ea->disp.abs =
- yasm_expr__level_tree(op->data.ea->disp.abs, 1, 1, 0,
- 0, NULL, NULL);
- if (yasm_error_occurred()) {
- /* Add a pointer to where it was used to the error */
- yasm_error_fetch(&eclass, &str, &xrefline, &xrefstr);
- if (xrefstr) {
- yasm_error_set_xref(xrefline, "%s", xrefstr);
- yasm_xfree(xrefstr);
- }
- if (str) {
- yasm_error_set(eclass, "%s in memory expression", str);
- yasm_xfree(str);
- }
- return;
- }
- break;
- case YASM_INSN__OPERAND_IMM:
- op->data.val =
- yasm_expr__level_tree(op->data.val, 1, 1, 1, 0, NULL,
- NULL);
- if (yasm_error_occurred()) {
- /* Add a pointer to where it was used to the error */
- yasm_error_fetch(&eclass, &str, &xrefline, &xrefstr);
- if (xrefstr) {
- yasm_error_set_xref(xrefline, "%s", xrefstr);
- yasm_xfree(xrefstr);
- }
- if (str) {
- yasm_error_set(eclass, "%s in immediate expression",
- str);
- yasm_xfree(str);
- }
- return;
- }
- break;
- default:
- break;
- }
- }
-}
+/*
+ * Mnemonic instruction bytecode
+ *
+ * Copyright (C) 2005-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "util.h"
+
+#include "libyasm-stdint.h"
+#include "coretype.h"
+
+#include "errwarn.h"
+#include "expr.h"
+#include "value.h"
+
+#include "bytecode.h"
+#include "insn.h"
+#include "arch.h"
+
+
+void
+yasm_ea_set_segreg(yasm_effaddr *ea, uintptr_t segreg)
+{
+ if (!ea)
+ return;
+
+ if (segreg != 0 && ea->segreg != 0)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("multiple segment overrides, using leftmost"));
+
+ ea->segreg = segreg;
+}
+
+yasm_insn_operand *
+yasm_operand_create_reg(uintptr_t reg)
+{
+ yasm_insn_operand *retval = yasm_xmalloc(sizeof(yasm_insn_operand));
+
+ retval->type = YASM_INSN__OPERAND_REG;
+ retval->data.reg = reg;
+ retval->seg = 0;
+ retval->targetmod = 0;
+ retval->size = 0;
+ retval->deref = 0;
+ retval->strict = 0;
+
+ return retval;
+}
+
+yasm_insn_operand *
+yasm_operand_create_segreg(uintptr_t segreg)
+{
+ yasm_insn_operand *retval = yasm_xmalloc(sizeof(yasm_insn_operand));
+
+ retval->type = YASM_INSN__OPERAND_SEGREG;
+ retval->data.reg = segreg;
+ retval->seg = 0;
+ retval->targetmod = 0;
+ retval->size = 0;
+ retval->deref = 0;
+ retval->strict = 0;
+
+ return retval;
+}
+
+yasm_insn_operand *
+yasm_operand_create_mem(/*@only@*/ yasm_effaddr *ea)
+{
+ yasm_insn_operand *retval = yasm_xmalloc(sizeof(yasm_insn_operand));
+
+ retval->type = YASM_INSN__OPERAND_MEMORY;
+ retval->data.ea = ea;
+ retval->seg = 0;
+ retval->targetmod = 0;
+ retval->size = 0;
+ retval->deref = 0;
+ retval->strict = 0;
+ retval->size = ea->data_len * 8;
+
+ return retval;
+}
+
+yasm_insn_operand *
+yasm_operand_create_imm(/*@only@*/ yasm_expr *val)
+{
+ yasm_insn_operand *retval;
+ const uintptr_t *reg;
+
+ reg = yasm_expr_get_reg(&val, 0);
+ if (reg) {
+ retval = yasm_operand_create_reg(*reg);
+ yasm_expr_destroy(val);
+ } else {
+ retval = yasm_xmalloc(sizeof(yasm_insn_operand));
+ retval->type = YASM_INSN__OPERAND_IMM;
+ retval->data.val = val;
+ retval->seg = 0;
+ retval->targetmod = 0;
+ retval->size = 0;
+ retval->deref = 0;
+ retval->strict = 0;
+ }
+
+ return retval;
+}
+
+yasm_insn_operand *
+yasm_insn_ops_append(yasm_insn *insn, yasm_insn_operand *op)
+{
+ if (op) {
+ insn->num_operands++;
+ STAILQ_INSERT_TAIL(&insn->operands, op, link);
+ return op;
+ }
+ return (yasm_insn_operand *)NULL;
+}
+
+void
+yasm_insn_add_prefix(yasm_insn *insn, uintptr_t prefix)
+{
+ insn->prefixes =
+ yasm_xrealloc(insn->prefixes,
+ (insn->num_prefixes+1)*sizeof(uintptr_t));
+ insn->prefixes[insn->num_prefixes] = prefix;
+ insn->num_prefixes++;
+}
+
+void
+yasm_insn_add_seg_prefix(yasm_insn *insn, uintptr_t segreg)
+{
+ insn->segregs =
+ yasm_xrealloc(insn->segregs, (insn->num_segregs+1)*sizeof(uintptr_t));
+ insn->segregs[insn->num_segregs] = segreg;
+ insn->num_segregs++;
+}
+
+void
+yasm_insn_initialize(yasm_insn *insn)
+{
+ STAILQ_INIT(&insn->operands);
+
+ insn->prefixes = NULL;
+ insn->segregs = NULL;
+
+ insn->num_operands = 0;
+ insn->num_prefixes = 0;
+ insn->num_segregs = 0;
+}
+
+void
+yasm_insn_delete(yasm_insn *insn,
+ void (*ea_destroy) (/*@only@*/ yasm_effaddr *))
+{
+ if (insn->num_operands > 0) {
+ yasm_insn_operand *cur, *next;
+
+ cur = STAILQ_FIRST(&insn->operands);
+ while (cur) {
+ next = STAILQ_NEXT(cur, link);
+ switch (cur->type) {
+ case YASM_INSN__OPERAND_MEMORY:
+ ea_destroy(cur->data.ea);
+ break;
+ case YASM_INSN__OPERAND_IMM:
+ yasm_expr_destroy(cur->data.val);
+ break;
+ default:
+ break;
+ }
+ yasm_xfree(cur);
+ cur = next;
+ }
+ }
+ if (insn->num_prefixes > 0)
+ yasm_xfree(insn->prefixes);
+ if (insn->num_segregs > 0)
+ yasm_xfree(insn->segregs);
+}
+
+void
+yasm_insn_print(const yasm_insn *insn, FILE *f, int indent_level)
+{
+ const yasm_insn_operand *op;
+
+ STAILQ_FOREACH (op, &insn->operands, link) {
+ switch (op->type) {
+ case YASM_INSN__OPERAND_REG:
+ fprintf(f, "%*sReg=", indent_level, "");
+ /*yasm_arch_reg_print(arch, op->data.reg, f);*/
+ fprintf(f, "\n");
+ break;
+ case YASM_INSN__OPERAND_SEGREG:
+ fprintf(f, "%*sSegReg=", indent_level, "");
+ /*yasm_arch_segreg_print(arch, op->data.reg, f);*/
+ fprintf(f, "\n");
+ break;
+ case YASM_INSN__OPERAND_MEMORY:
+ fprintf(f, "%*sMemory=\n", indent_level, "");
+ /*yasm_arch_ea_print(arch, op->data.ea, f, indent_level);*/
+ break;
+ case YASM_INSN__OPERAND_IMM:
+ fprintf(f, "%*sImm=", indent_level, "");
+ yasm_expr_print(op->data.val, f);
+ fprintf(f, "\n");
+ break;
+ }
+ fprintf(f, "%*sTargetMod=%lx\n", indent_level+1, "",
+ (unsigned long)op->targetmod);
+ fprintf(f, "%*sSize=%u\n", indent_level+1, "", op->size);
+ fprintf(f, "%*sDeref=%d, Strict=%d\n", indent_level+1, "",
+ (int)op->deref, (int)op->strict);
+ }
+}
+
+void
+yasm_insn_finalize(yasm_insn *insn)
+{
+ unsigned int i;
+ yasm_insn_operand *op;
+ yasm_error_class eclass;
+ char *str, *xrefstr;
+ unsigned long xrefline;
+
+ /* Simplify the operands' expressions first. */
+ for (i = 0, op = yasm_insn_ops_first(insn);
+ op && i<insn->num_operands; op = yasm_insn_op_next(op), i++) {
+ /* Check operand type */
+ switch (op->type) {
+ case YASM_INSN__OPERAND_MEMORY:
+ /* Don't get over-ambitious here; some archs' memory expr
+ * parser are sensitive to the presence of *1, etc, so don't
+ * simplify reg*1 identities.
+ */
+ if (op->data.ea)
+ op->data.ea->disp.abs =
+ yasm_expr__level_tree(op->data.ea->disp.abs, 1, 1, 0,
+ 0, NULL, NULL);
+ if (yasm_error_occurred()) {
+ /* Add a pointer to where it was used to the error */
+ yasm_error_fetch(&eclass, &str, &xrefline, &xrefstr);
+ if (xrefstr) {
+ yasm_error_set_xref(xrefline, "%s", xrefstr);
+ yasm_xfree(xrefstr);
+ }
+ if (str) {
+ yasm_error_set(eclass, "%s in memory expression", str);
+ yasm_xfree(str);
+ }
+ return;
+ }
+ break;
+ case YASM_INSN__OPERAND_IMM:
+ op->data.val =
+ yasm_expr__level_tree(op->data.val, 1, 1, 1, 0, NULL,
+ NULL);
+ if (yasm_error_occurred()) {
+ /* Add a pointer to where it was used to the error */
+ yasm_error_fetch(&eclass, &str, &xrefline, &xrefstr);
+ if (xrefstr) {
+ yasm_error_set_xref(xrefline, "%s", xrefstr);
+ yasm_xfree(xrefstr);
+ }
+ if (str) {
+ yasm_error_set(eclass, "%s in immediate expression",
+ str);
+ yasm_xfree(str);
+ }
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
diff --git a/contrib/tools/yasm/libyasm/insn.h b/contrib/tools/yasm/libyasm/insn.h
index d2d175d039..7400afbc88 100644
--- a/contrib/tools/yasm/libyasm/insn.h
+++ b/contrib/tools/yasm/libyasm/insn.h
@@ -1,269 +1,269 @@
-/**
- * \file libyasm/insn.h
- * \brief YASM mnenomic instruction.
- *
- * \license
- * Copyright (C) 2002-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- * \endlicense
- */
-#ifndef YASM_INSN_H
-#define YASM_INSN_H
-
-#ifndef YASM_LIB_DECL
-#define YASM_LIB_DECL
-#endif
-
-/** Base structure for an effective address. As with all base
- * structures, must be present as the first element in any
- * #yasm_arch implementation of an effective address.
- */
-struct yasm_effaddr {
- yasm_value disp; /**< address displacement */
-
- /** Segment register override (0 if none). */
- uintptr_t segreg;
-
- /** 1 if length of disp must be >0. */
- unsigned int need_nonzero_len:1;
-
- /** 1 if a displacement should be present in the output. */
- unsigned int need_disp:1;
-
- /** 1 if reg*2 should not be split into reg+reg. (0 if not).
- * This flag indicates (for architectures that support complex effective
- * addresses such as x86) if various types of complex effective addresses
- * can be split into different forms in order to minimize instruction
- * length.
- */
- unsigned int nosplit:1;
-
- /** 1 if effective address is /definitely/ an effective address.
- * This is used in e.g. the GAS parser to differentiate
- * between "expr" (which might or might not be an effective address) and
- * "expr(,1)" (which is definitely an effective address).
- */
- unsigned int strong:1;
-
- /** 1 if effective address is forced PC-relative. */
- unsigned int pc_rel:1;
-
- /** 1 if effective address is forced non-PC-relative. */
- unsigned int not_pc_rel:1;
-
- /** length of pointed data (in bytes), 0 if unknown. */
- unsigned int data_len;
-};
-
-/** An instruction operand (opaque type). */
-typedef struct yasm_insn_operand yasm_insn_operand;
-
-/** The type of an instruction operand. */
-typedef enum yasm_insn_operand_type {
- YASM_INSN__OPERAND_REG = 1, /**< A register. */
- YASM_INSN__OPERAND_SEGREG, /**< A segment register. */
- YASM_INSN__OPERAND_MEMORY, /**< An effective address
- * (memory reference). */
- YASM_INSN__OPERAND_IMM /**< An immediate or jump target. */
-} yasm_insn_operand_type;
-
-/** An instruction operand. */
-struct yasm_insn_operand {
- /** Link for building linked list of operands. \internal */
- /*@reldef@*/ STAILQ_ENTRY(yasm_insn_operand) link;
-
- /** Operand data. */
- union {
- uintptr_t reg; /**< Arch data for reg/segreg. */
- yasm_effaddr *ea; /**< Effective address for memory references. */
- yasm_expr *val; /**< Value of immediate or jump target. */
- } data;
-
- yasm_expr *seg; /**< Segment expression */
-
- uintptr_t targetmod; /**< Arch target modifier, 0 if none. */
-
- /** Specified size of the operand, in bits. 0 if not user-specified. */
- unsigned int size:16;
-
- /** Nonzero if dereference. Used for "*foo" in GAS.
- * The reason for this is that by default in GAS, an unprefixed value
- * is a memory address, except for jumps/calls, in which case it needs a
- * "*" prefix to become a memory address (otherwise it's an immediate).
- * This isn't knowable in the parser stage, so the parser sets this flag
- * to indicate the "*" prefix has been used, and the arch needs to adjust
- * the operand type appropriately depending on the instruction type.
- */
- unsigned int deref:1;
-
- /** Nonzero if strict. Used for "strict foo" in NASM.
- * This is used to inhibit optimization on otherwise "sized" values.
- * For example, the user may just want to be explicit with the size on
- * "push dword 4", but not actually want to force the immediate size to
- * 4 bytes (rather wanting the optimizer to optimize it down to 1 byte as
- * though "dword" was not specified). To indicate the immediate should
- * actually be forced to 4 bytes, the user needs to write
- * "push strict dword 4", which sets this flag.
- */
- unsigned int strict:1;
-
- /** Operand type. */
- unsigned int type:4;
-};
-
-/** Base structure for "instruction" bytecodes. These are the mnenomic
- * (rather than raw) representation of instructions. As with all base
- * structures, must be present as the first element in any
- * #yasm_arch implementation of mnenomic instruction bytecodes.
- */
-struct yasm_insn {
- /** Linked list of operands. */
- /*@reldef@*/ STAILQ_HEAD(yasm_insn_operands, yasm_insn_operand) operands;
-
- /** Array of prefixes. */
- /*@null@*/ uintptr_t *prefixes;
-
- /** Array of segment prefixes. */
- /*@null@*/ uintptr_t *segregs;
-
- unsigned int num_operands; /**< Number of operands. */
- unsigned int num_prefixes; /**< Number of prefixes. */
- unsigned int num_segregs; /**< Number of segment prefixes. */
-};
-
-/** Set segment override for an effective address.
- * Some architectures (such as x86) support segment overrides on effective
- * addresses. A override of an override will result in a warning.
- * \param ea effective address
- * \param segreg segment register (0 if none)
- */
-YASM_LIB_DECL
-void yasm_ea_set_segreg(yasm_effaddr *ea, uintptr_t segreg);
-
-/** Create an instruction operand from a register.
- * \param reg register
- * \return Newly allocated operand.
- */
-YASM_LIB_DECL
-yasm_insn_operand *yasm_operand_create_reg(uintptr_t reg);
-
-/** Create an instruction operand from a segment register.
- * \param segreg segment register
- * \return Newly allocated operand.
- */
-YASM_LIB_DECL
-yasm_insn_operand *yasm_operand_create_segreg(uintptr_t segreg);
-
-/** Create an instruction operand from an effective address.
- * \param ea effective address
- * \return Newly allocated operand.
- */
-YASM_LIB_DECL
-yasm_insn_operand *yasm_operand_create_mem(/*@only@*/ yasm_effaddr *ea);
-
-/** Create an instruction operand from an immediate expression.
- * Looks for cases of a single register and creates a register variant of
- * #yasm_insn_operand.
- * \param val immediate expression
- * \return Newly allocated operand.
- */
-YASM_LIB_DECL
-yasm_insn_operand *yasm_operand_create_imm(/*@only@*/ yasm_expr *val);
-
-/** Get the first operand in an instruction.
- * \param insn instruction
- * \return First operand (NULL if no operands).
- */
-yasm_insn_operand *yasm_insn_ops_first(yasm_insn *insn);
-#define yasm_insn_ops_first(insn) STAILQ_FIRST(&((insn)->operands))
-
-/** Get the next operand in an instruction.
- * \param op previous operand
- * \return Next operand (NULL if op was the last operand).
- */
-yasm_insn_operand *yasm_insn_op_next(yasm_insn_operand *op);
-#define yasm_insn_op_next(cur) STAILQ_NEXT(cur, link)
-
-/** Add operand to the end of an instruction.
- * \note Does not make a copy of the operand; so don't pass this function
- * static or local variables, and discard the op pointer after calling
- * this function.
- * \param insn instruction
- * \param op operand (may be NULL)
- * \return If operand was actually appended (it wasn't NULL), the operand;
- * otherwise NULL.
- */
-YASM_LIB_DECL
-/*@null@*/ yasm_insn_operand *yasm_insn_ops_append
- (yasm_insn *insn,
- /*@returned@*/ /*@null@*/ yasm_insn_operand *op);
-
-/** Associate a prefix with an instruction.
- * \param insn instruction
- * \param prefix data that identifies the prefix
- */
-YASM_LIB_DECL
-void yasm_insn_add_prefix(yasm_insn *insn, uintptr_t prefix);
-
-/** Associate a segment prefix with an instruction.
- * \param insn instruction
- * \param segreg data that identifies the segment register
- */
-YASM_LIB_DECL
-void yasm_insn_add_seg_prefix(yasm_insn *insn, uintptr_t segreg);
-
-/** Initialize the common parts of an instruction.
- * \internal For use by yasm_arch implementations only.
- * \param insn instruction
- */
-YASM_LIB_DECL
-void yasm_insn_initialize(/*@out@*/ yasm_insn *insn);
-
-/** Delete the common parts of an instruction.
- * \internal For use by yasm_arch implementations only.
- * \param insn instruction
- * \param content if nonzero, deletes content of each operand
- * \param arch architecture
- */
-YASM_LIB_DECL
-void yasm_insn_delete(yasm_insn *insn,
- void (*ea_destroy) (/*@only@*/ yasm_effaddr *));
-
-/** Print a list of instruction operands. For debugging purposes.
- * \internal For use by yasm_arch implementations only.
- * \param insn instruction
- * \param f file
- * \param indent_level indentation level
- * \param arch architecture
- */
-YASM_LIB_DECL
-void yasm_insn_print(const yasm_insn *insn, FILE *f, int indent_level);
-
-/** Finalize the common parts of an instruction.
- * \internal For use by yasm_arch implementations only.
- * \param insn instruction
- */
-YASM_LIB_DECL
-void yasm_insn_finalize(yasm_insn *insn);
-
-#endif
+/**
+ * \file libyasm/insn.h
+ * \brief YASM mnenomic instruction.
+ *
+ * \license
+ * Copyright (C) 2002-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * \endlicense
+ */
+#ifndef YASM_INSN_H
+#define YASM_INSN_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/** Base structure for an effective address. As with all base
+ * structures, must be present as the first element in any
+ * #yasm_arch implementation of an effective address.
+ */
+struct yasm_effaddr {
+ yasm_value disp; /**< address displacement */
+
+ /** Segment register override (0 if none). */
+ uintptr_t segreg;
+
+ /** 1 if length of disp must be >0. */
+ unsigned int need_nonzero_len:1;
+
+ /** 1 if a displacement should be present in the output. */
+ unsigned int need_disp:1;
+
+ /** 1 if reg*2 should not be split into reg+reg. (0 if not).
+ * This flag indicates (for architectures that support complex effective
+ * addresses such as x86) if various types of complex effective addresses
+ * can be split into different forms in order to minimize instruction
+ * length.
+ */
+ unsigned int nosplit:1;
+
+ /** 1 if effective address is /definitely/ an effective address.
+ * This is used in e.g. the GAS parser to differentiate
+ * between "expr" (which might or might not be an effective address) and
+ * "expr(,1)" (which is definitely an effective address).
+ */
+ unsigned int strong:1;
+
+ /** 1 if effective address is forced PC-relative. */
+ unsigned int pc_rel:1;
+
+ /** 1 if effective address is forced non-PC-relative. */
+ unsigned int not_pc_rel:1;
+
+ /** length of pointed data (in bytes), 0 if unknown. */
+ unsigned int data_len;
+};
+
+/** An instruction operand (opaque type). */
+typedef struct yasm_insn_operand yasm_insn_operand;
+
+/** The type of an instruction operand. */
+typedef enum yasm_insn_operand_type {
+ YASM_INSN__OPERAND_REG = 1, /**< A register. */
+ YASM_INSN__OPERAND_SEGREG, /**< A segment register. */
+ YASM_INSN__OPERAND_MEMORY, /**< An effective address
+ * (memory reference). */
+ YASM_INSN__OPERAND_IMM /**< An immediate or jump target. */
+} yasm_insn_operand_type;
+
+/** An instruction operand. */
+struct yasm_insn_operand {
+ /** Link for building linked list of operands. \internal */
+ /*@reldef@*/ STAILQ_ENTRY(yasm_insn_operand) link;
+
+ /** Operand data. */
+ union {
+ uintptr_t reg; /**< Arch data for reg/segreg. */
+ yasm_effaddr *ea; /**< Effective address for memory references. */
+ yasm_expr *val; /**< Value of immediate or jump target. */
+ } data;
+
+ yasm_expr *seg; /**< Segment expression */
+
+ uintptr_t targetmod; /**< Arch target modifier, 0 if none. */
+
+ /** Specified size of the operand, in bits. 0 if not user-specified. */
+ unsigned int size:16;
+
+ /** Nonzero if dereference. Used for "*foo" in GAS.
+ * The reason for this is that by default in GAS, an unprefixed value
+ * is a memory address, except for jumps/calls, in which case it needs a
+ * "*" prefix to become a memory address (otherwise it's an immediate).
+ * This isn't knowable in the parser stage, so the parser sets this flag
+ * to indicate the "*" prefix has been used, and the arch needs to adjust
+ * the operand type appropriately depending on the instruction type.
+ */
+ unsigned int deref:1;
+
+ /** Nonzero if strict. Used for "strict foo" in NASM.
+ * This is used to inhibit optimization on otherwise "sized" values.
+ * For example, the user may just want to be explicit with the size on
+ * "push dword 4", but not actually want to force the immediate size to
+ * 4 bytes (rather wanting the optimizer to optimize it down to 1 byte as
+ * though "dword" was not specified). To indicate the immediate should
+ * actually be forced to 4 bytes, the user needs to write
+ * "push strict dword 4", which sets this flag.
+ */
+ unsigned int strict:1;
+
+ /** Operand type. */
+ unsigned int type:4;
+};
+
+/** Base structure for "instruction" bytecodes. These are the mnenomic
+ * (rather than raw) representation of instructions. As with all base
+ * structures, must be present as the first element in any
+ * #yasm_arch implementation of mnenomic instruction bytecodes.
+ */
+struct yasm_insn {
+ /** Linked list of operands. */
+ /*@reldef@*/ STAILQ_HEAD(yasm_insn_operands, yasm_insn_operand) operands;
+
+ /** Array of prefixes. */
+ /*@null@*/ uintptr_t *prefixes;
+
+ /** Array of segment prefixes. */
+ /*@null@*/ uintptr_t *segregs;
+
+ unsigned int num_operands; /**< Number of operands. */
+ unsigned int num_prefixes; /**< Number of prefixes. */
+ unsigned int num_segregs; /**< Number of segment prefixes. */
+};
+
+/** Set segment override for an effective address.
+ * Some architectures (such as x86) support segment overrides on effective
+ * addresses. A override of an override will result in a warning.
+ * \param ea effective address
+ * \param segreg segment register (0 if none)
+ */
+YASM_LIB_DECL
+void yasm_ea_set_segreg(yasm_effaddr *ea, uintptr_t segreg);
+
+/** Create an instruction operand from a register.
+ * \param reg register
+ * \return Newly allocated operand.
+ */
+YASM_LIB_DECL
+yasm_insn_operand *yasm_operand_create_reg(uintptr_t reg);
+
+/** Create an instruction operand from a segment register.
+ * \param segreg segment register
+ * \return Newly allocated operand.
+ */
+YASM_LIB_DECL
+yasm_insn_operand *yasm_operand_create_segreg(uintptr_t segreg);
+
+/** Create an instruction operand from an effective address.
+ * \param ea effective address
+ * \return Newly allocated operand.
+ */
+YASM_LIB_DECL
+yasm_insn_operand *yasm_operand_create_mem(/*@only@*/ yasm_effaddr *ea);
+
+/** Create an instruction operand from an immediate expression.
+ * Looks for cases of a single register and creates a register variant of
+ * #yasm_insn_operand.
+ * \param val immediate expression
+ * \return Newly allocated operand.
+ */
+YASM_LIB_DECL
+yasm_insn_operand *yasm_operand_create_imm(/*@only@*/ yasm_expr *val);
+
+/** Get the first operand in an instruction.
+ * \param insn instruction
+ * \return First operand (NULL if no operands).
+ */
+yasm_insn_operand *yasm_insn_ops_first(yasm_insn *insn);
+#define yasm_insn_ops_first(insn) STAILQ_FIRST(&((insn)->operands))
+
+/** Get the next operand in an instruction.
+ * \param op previous operand
+ * \return Next operand (NULL if op was the last operand).
+ */
+yasm_insn_operand *yasm_insn_op_next(yasm_insn_operand *op);
+#define yasm_insn_op_next(cur) STAILQ_NEXT(cur, link)
+
+/** Add operand to the end of an instruction.
+ * \note Does not make a copy of the operand; so don't pass this function
+ * static or local variables, and discard the op pointer after calling
+ * this function.
+ * \param insn instruction
+ * \param op operand (may be NULL)
+ * \return If operand was actually appended (it wasn't NULL), the operand;
+ * otherwise NULL.
+ */
+YASM_LIB_DECL
+/*@null@*/ yasm_insn_operand *yasm_insn_ops_append
+ (yasm_insn *insn,
+ /*@returned@*/ /*@null@*/ yasm_insn_operand *op);
+
+/** Associate a prefix with an instruction.
+ * \param insn instruction
+ * \param prefix data that identifies the prefix
+ */
+YASM_LIB_DECL
+void yasm_insn_add_prefix(yasm_insn *insn, uintptr_t prefix);
+
+/** Associate a segment prefix with an instruction.
+ * \param insn instruction
+ * \param segreg data that identifies the segment register
+ */
+YASM_LIB_DECL
+void yasm_insn_add_seg_prefix(yasm_insn *insn, uintptr_t segreg);
+
+/** Initialize the common parts of an instruction.
+ * \internal For use by yasm_arch implementations only.
+ * \param insn instruction
+ */
+YASM_LIB_DECL
+void yasm_insn_initialize(/*@out@*/ yasm_insn *insn);
+
+/** Delete the common parts of an instruction.
+ * \internal For use by yasm_arch implementations only.
+ * \param insn instruction
+ * \param content if nonzero, deletes content of each operand
+ * \param arch architecture
+ */
+YASM_LIB_DECL
+void yasm_insn_delete(yasm_insn *insn,
+ void (*ea_destroy) (/*@only@*/ yasm_effaddr *));
+
+/** Print a list of instruction operands. For debugging purposes.
+ * \internal For use by yasm_arch implementations only.
+ * \param insn instruction
+ * \param f file
+ * \param indent_level indentation level
+ * \param arch architecture
+ */
+YASM_LIB_DECL
+void yasm_insn_print(const yasm_insn *insn, FILE *f, int indent_level);
+
+/** Finalize the common parts of an instruction.
+ * \internal For use by yasm_arch implementations only.
+ * \param insn instruction
+ */
+YASM_LIB_DECL
+void yasm_insn_finalize(yasm_insn *insn);
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/intnum.c b/contrib/tools/yasm/libyasm/intnum.c
index 6feba33481..961bf31394 100644
--- a/contrib/tools/yasm/libyasm/intnum.c
+++ b/contrib/tools/yasm/libyasm/intnum.c
@@ -1,1096 +1,1096 @@
-/*
- * Integer number functions.
- *
- * Copyright (C) 2001-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#include "util.h"
-
-#include <ctype.h>
-#include <limits.h>
-
-#include "coretype.h"
-#include "bitvect.h"
-#include "file.h"
-
-#include "errwarn.h"
-#include "intnum.h"
-
-
-/* "Native" "word" size for intnum calculations. */
-#define BITVECT_NATIVE_SIZE 256
-
-struct yasm_intnum {
- union val {
- long l; /* integer value (for integers <32 bits) */
- wordptr bv; /* bit vector (for integers >=32 bits) */
- } val;
- enum { INTNUM_L, INTNUM_BV } type;
-};
-
-/* static bitvect used for conversions */
-static /*@only@*/ wordptr conv_bv;
-
-/* static bitvects used for computation */
-static /*@only@*/ wordptr result, spare, op1static, op2static;
-
-static /*@only@*/ BitVector_from_Dec_static_data *from_dec_data;
-
-
-void
-yasm_intnum_initialize(void)
-{
- conv_bv = BitVector_Create(BITVECT_NATIVE_SIZE, FALSE);
- result = BitVector_Create(BITVECT_NATIVE_SIZE, FALSE);
- spare = BitVector_Create(BITVECT_NATIVE_SIZE, FALSE);
- op1static = BitVector_Create(BITVECT_NATIVE_SIZE, FALSE);
- op2static = BitVector_Create(BITVECT_NATIVE_SIZE, FALSE);
- from_dec_data = BitVector_from_Dec_static_Boot(BITVECT_NATIVE_SIZE);
-}
-
-void
-yasm_intnum_cleanup(void)
-{
- BitVector_from_Dec_static_Shutdown(from_dec_data);
- BitVector_Destroy(op2static);
- BitVector_Destroy(op1static);
- BitVector_Destroy(spare);
- BitVector_Destroy(result);
- BitVector_Destroy(conv_bv);
-}
-
-/* Compress a bitvector into intnum storage.
- * If saved as a bitvector, clones the passed bitvector.
- * Can modify the passed bitvector.
- */
-static void
-intnum_frombv(/*@out@*/ yasm_intnum *intn, wordptr bv)
-{
- if (Set_Max(bv) < 31) {
- intn->type = INTNUM_L;
- intn->val.l = (long)BitVector_Chunk_Read(bv, 31, 0);
- } else if (BitVector_msb_(bv)) {
- /* Negative, negate and see if we'll fit into a long. */
- unsigned long ul;
- BitVector_Negate(bv, bv);
- if (Set_Max(bv) >= 32 ||
- ((ul = BitVector_Chunk_Read(bv, 32, 0)) & 0x80000000)) {
- /* too negative */
- BitVector_Negate(bv, bv);
- intn->type = INTNUM_BV;
- intn->val.bv = BitVector_Clone(bv);
- } else {
- intn->type = INTNUM_L;
- intn->val.l = -((long)ul);
- }
- } else {
- intn->type = INTNUM_BV;
- intn->val.bv = BitVector_Clone(bv);
- }
-}
-
-/* If intnum is a BV, returns its bitvector directly.
- * If not, converts into passed bv and returns that instead.
- */
-static wordptr
-intnum_tobv(/*@returned@*/ wordptr bv, const yasm_intnum *intn)
-{
- if (intn->type == INTNUM_BV)
- return intn->val.bv;
-
- BitVector_Empty(bv);
- if (intn->val.l >= 0)
- BitVector_Chunk_Store(bv, 32, 0, (unsigned long)intn->val.l);
- else {
- BitVector_Chunk_Store(bv, 32, 0, (unsigned long)-intn->val.l);
- BitVector_Negate(bv, bv);
- }
- return bv;
-}
-
-yasm_intnum *
-yasm_intnum_create_dec(char *str)
-{
- yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
-
- switch (BitVector_from_Dec_static(from_dec_data, conv_bv,
- (unsigned char *)str)) {
- case ErrCode_Pars:
- yasm_error_set(YASM_ERROR_VALUE, N_("invalid decimal literal"));
- break;
- case ErrCode_Ovfl:
- yasm_error_set(YASM_ERROR_OVERFLOW,
- N_("Numeric constant too large for internal format"));
- break;
- default:
- break;
- }
- intnum_frombv(intn, conv_bv);
- return intn;
-}
-
-yasm_intnum *
-yasm_intnum_create_bin(char *str)
-{
- yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
-
- switch (BitVector_from_Bin(conv_bv, (unsigned char *)str)) {
- case ErrCode_Pars:
- yasm_error_set(YASM_ERROR_VALUE, N_("invalid binary literal"));
- break;
- case ErrCode_Ovfl:
- yasm_error_set(YASM_ERROR_OVERFLOW,
- N_("Numeric constant too large for internal format"));
- break;
- default:
- break;
- }
- intnum_frombv(intn, conv_bv);
- return intn;
-}
-
-yasm_intnum *
-yasm_intnum_create_oct(char *str)
-{
- yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
-
- switch (BitVector_from_Oct(conv_bv, (unsigned char *)str)) {
- case ErrCode_Pars:
- yasm_error_set(YASM_ERROR_VALUE, N_("invalid octal literal"));
- break;
- case ErrCode_Ovfl:
- yasm_error_set(YASM_ERROR_OVERFLOW,
- N_("Numeric constant too large for internal format"));
- break;
- default:
- break;
- }
- intnum_frombv(intn, conv_bv);
- return intn;
-}
-
-yasm_intnum *
-yasm_intnum_create_hex(char *str)
-{
- yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
-
- switch (BitVector_from_Hex(conv_bv, (unsigned char *)str)) {
- case ErrCode_Pars:
- yasm_error_set(YASM_ERROR_VALUE, N_("invalid hex literal"));
- break;
- case ErrCode_Ovfl:
- yasm_error_set(YASM_ERROR_OVERFLOW,
- N_("Numeric constant too large for internal format"));
- break;
- default:
- break;
- }
- intnum_frombv(intn, conv_bv);
- return intn;
-}
-
-/*@-usedef -compdef -uniondef@*/
-yasm_intnum *
-yasm_intnum_create_charconst_nasm(const char *str)
-{
- yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
- size_t len = strlen(str);
-
- if(len*8 > BITVECT_NATIVE_SIZE)
- yasm_error_set(YASM_ERROR_OVERFLOW,
- N_("Character constant too large for internal format"));
-
- /* be conservative in choosing bitvect in case MSB is set */
- if (len > 3) {
- BitVector_Empty(conv_bv);
- intn->type = INTNUM_BV;
- } else {
- intn->val.l = 0;
- intn->type = INTNUM_L;
- }
-
- switch (len) {
- case 3:
- intn->val.l |= ((unsigned long)str[2]) & 0xff;
- intn->val.l <<= 8;
- /*@fallthrough@*/
- case 2:
- intn->val.l |= ((unsigned long)str[1]) & 0xff;
- intn->val.l <<= 8;
- /*@fallthrough@*/
- case 1:
- intn->val.l |= ((unsigned long)str[0]) & 0xff;
- case 0:
- break;
- default:
- /* >=32 bit conversion */
- while (len) {
- BitVector_Move_Left(conv_bv, 8);
- BitVector_Chunk_Store(conv_bv, 8, 0,
- ((unsigned long)str[--len]) & 0xff);
- }
- intn->val.bv = BitVector_Clone(conv_bv);
- }
-
- return intn;
-}
-
-yasm_intnum *
-yasm_intnum_create_charconst_tasm(const char *str)
-{
- yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
- size_t len = strlen(str);
- size_t i;
-
- if(len*8 > BITVECT_NATIVE_SIZE)
- yasm_error_set(YASM_ERROR_OVERFLOW,
- N_("Character constant too large for internal format"));
-
- /* be conservative in choosing bitvect in case MSB is set */
- if (len > 3) {
- BitVector_Empty(conv_bv);
- intn->type = INTNUM_BV;
- } else {
- intn->val.l = 0;
- intn->type = INTNUM_L;
- }
-
- /* tasm uses big endian notation */
- i = 0;
- switch (len) {
- case 3:
- intn->val.l |= ((unsigned long)str[i++]) & 0xff;
- intn->val.l <<= 8;
- /*@fallthrough@*/
- case 2:
- intn->val.l |= ((unsigned long)str[i++]) & 0xff;
- intn->val.l <<= 8;
- /*@fallthrough@*/
- case 1:
- intn->val.l |= ((unsigned long)str[i++]) & 0xff;
- case 0:
- break;
- default:
- /* >=32 bit conversion */
- while (i < len) {
- BitVector_Chunk_Store(conv_bv, 8, (len-i-1)*8,
- ((unsigned long)str[i]) & 0xff);
- i++;
- }
- intn->val.bv = BitVector_Clone(conv_bv);
- }
-
- return intn;
-}
-/*@=usedef =compdef =uniondef@*/
-
-yasm_intnum *
-yasm_intnum_create_uint(unsigned long i)
-{
- yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
-
- if (i > LONG_MAX) {
- /* Too big, store as bitvector */
- intn->val.bv = BitVector_Create(BITVECT_NATIVE_SIZE, TRUE);
- intn->type = INTNUM_BV;
- BitVector_Chunk_Store(intn->val.bv, 32, 0, i);
- } else {
- intn->val.l = (long)i;
- intn->type = INTNUM_L;
- }
-
- return intn;
-}
-
-yasm_intnum *
-yasm_intnum_create_int(long i)
-{
- yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
-
- intn->val.l = i;
- intn->type = INTNUM_L;
-
- return intn;
-}
-
-yasm_intnum *
-yasm_intnum_create_leb128(const unsigned char *ptr, int sign,
- unsigned long *size)
-{
- yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
- const unsigned char *ptr_orig = ptr;
- unsigned long i = 0;
-
- BitVector_Empty(conv_bv);
- for (;;) {
- BitVector_Chunk_Store(conv_bv, 7, i, *ptr);
- i += 7;
- if ((*ptr & 0x80) != 0x80)
- break;
- ptr++;
- }
-
- *size = (unsigned long)(ptr-ptr_orig)+1;
-
- if(i > BITVECT_NATIVE_SIZE)
- yasm_error_set(YASM_ERROR_OVERFLOW,
- N_("Numeric constant too large for internal format"));
- else if (sign && (*ptr & 0x40) == 0x40)
- BitVector_Interval_Fill(conv_bv, i, BITVECT_NATIVE_SIZE-1);
-
- intnum_frombv(intn, conv_bv);
- return intn;
-}
-
-yasm_intnum *
-yasm_intnum_create_sized(unsigned char *ptr, int sign, size_t srcsize,
- int bigendian)
-{
- yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
- unsigned long i = 0;
-
- if (srcsize*8 > BITVECT_NATIVE_SIZE)
- yasm_error_set(YASM_ERROR_OVERFLOW,
- N_("Numeric constant too large for internal format"));
-
- /* Read the buffer into a bitvect */
- BitVector_Empty(conv_bv);
- if (bigendian) {
- /* TODO */
- yasm_internal_error(N_("big endian not implemented"));
- } else {
- for (i = 0; i < srcsize; i++)
- BitVector_Chunk_Store(conv_bv, 8, i*8, ptr[i]);
- }
-
- /* Sign extend if needed */
- if (srcsize*8 < BITVECT_NATIVE_SIZE && sign && (ptr[i-1] & 0x80) == 0x80)
- BitVector_Interval_Fill(conv_bv, i*8, BITVECT_NATIVE_SIZE-1);
-
- intnum_frombv(intn, conv_bv);
- return intn;
-}
-
-yasm_intnum *
-yasm_intnum_copy(const yasm_intnum *intn)
-{
- yasm_intnum *n = yasm_xmalloc(sizeof(yasm_intnum));
-
- switch (intn->type) {
- case INTNUM_L:
- n->val.l = intn->val.l;
- break;
- case INTNUM_BV:
- n->val.bv = BitVector_Clone(intn->val.bv);
- break;
- }
- n->type = intn->type;
-
- return n;
-}
-
-void
-yasm_intnum_destroy(yasm_intnum *intn)
-{
- if (intn->type == INTNUM_BV)
- BitVector_Destroy(intn->val.bv);
- yasm_xfree(intn);
-}
-
-/*@-nullderef -nullpass -branchstate@*/
-int
-yasm_intnum_calc(yasm_intnum *acc, yasm_expr_op op, yasm_intnum *operand)
-{
- boolean carry = 0;
- wordptr op1, op2 = NULL;
- N_int count;
-
- /* Always do computations with in full bit vector.
- * Bit vector results must be calculated through intermediate storage.
- */
- op1 = intnum_tobv(op1static, acc);
- if (operand)
- op2 = intnum_tobv(op2static, operand);
-
- if (!operand && op != YASM_EXPR_NEG && op != YASM_EXPR_NOT &&
- op != YASM_EXPR_LNOT) {
- yasm_error_set(YASM_ERROR_ARITHMETIC,
- N_("operation needs an operand"));
- BitVector_Empty(result);
- return 1;
- }
-
- /* A operation does a bitvector computation if result is allocated. */
- switch (op) {
- case YASM_EXPR_ADD:
- BitVector_add(result, op1, op2, &carry);
- break;
- case YASM_EXPR_SUB:
- BitVector_sub(result, op1, op2, &carry);
- break;
- case YASM_EXPR_MUL:
- BitVector_Multiply(result, op1, op2);
- break;
- case YASM_EXPR_DIV:
- /* TODO: make sure op1 and op2 are unsigned */
- if (BitVector_is_empty(op2)) {
- yasm_error_set(YASM_ERROR_ZERO_DIVISION, N_("divide by zero"));
- BitVector_Empty(result);
- return 1;
- } else
- BitVector_Divide(result, op1, op2, spare);
- break;
- case YASM_EXPR_SIGNDIV:
- if (BitVector_is_empty(op2)) {
- yasm_error_set(YASM_ERROR_ZERO_DIVISION, N_("divide by zero"));
- BitVector_Empty(result);
- return 1;
- } else
- BitVector_Divide(result, op1, op2, spare);
- break;
- case YASM_EXPR_MOD:
- /* TODO: make sure op1 and op2 are unsigned */
- if (BitVector_is_empty(op2)) {
- yasm_error_set(YASM_ERROR_ZERO_DIVISION, N_("divide by zero"));
- BitVector_Empty(result);
- return 1;
- } else
- BitVector_Divide(spare, op1, op2, result);
- break;
- case YASM_EXPR_SIGNMOD:
- if (BitVector_is_empty(op2)) {
- yasm_error_set(YASM_ERROR_ZERO_DIVISION, N_("divide by zero"));
- BitVector_Empty(result);
- return 1;
- } else
- BitVector_Divide(spare, op1, op2, result);
- break;
- case YASM_EXPR_NEG:
- BitVector_Negate(result, op1);
- break;
- case YASM_EXPR_NOT:
- Set_Complement(result, op1);
- break;
- case YASM_EXPR_OR:
- Set_Union(result, op1, op2);
- break;
- case YASM_EXPR_AND:
- Set_Intersection(result, op1, op2);
- 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);
- break;
- case YASM_EXPR_SHL:
- if (operand->type == INTNUM_L && operand->val.l >= 0) {
- BitVector_Copy(result, op1);
- BitVector_Move_Left(result, (N_int)operand->val.l);
- } else /* don't even bother, just zero result */
- BitVector_Empty(result);
- break;
- case YASM_EXPR_SHR:
- if (operand->type == INTNUM_L && operand->val.l >= 0) {
- BitVector_Copy(result, op1);
- carry = BitVector_msb_(op1);
- count = (N_int)operand->val.l;
- while (count-- > 0)
- BitVector_shift_right(result, carry);
- } else /* don't even bother, just zero result */
- BitVector_Empty(result);
- break;
- case YASM_EXPR_LOR:
- BitVector_Empty(result);
- BitVector_LSB(result, !BitVector_is_empty(op1) ||
- !BitVector_is_empty(op2));
- break;
- case YASM_EXPR_LAND:
- BitVector_Empty(result);
- BitVector_LSB(result, !BitVector_is_empty(op1) &&
- !BitVector_is_empty(op2));
- break;
- case YASM_EXPR_LNOT:
- 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));
- break;
- case YASM_EXPR_LT:
- BitVector_Empty(result);
- BitVector_LSB(result, BitVector_Compare(op1, op2) < 0);
- break;
- case YASM_EXPR_GT:
- BitVector_Empty(result);
- BitVector_LSB(result, BitVector_Compare(op1, op2) > 0);
- break;
- case YASM_EXPR_LE:
- BitVector_Empty(result);
- BitVector_LSB(result, BitVector_Compare(op1, op2) <= 0);
- break;
- case YASM_EXPR_GE:
- BitVector_Empty(result);
- BitVector_LSB(result, BitVector_Compare(op1, op2) >= 0);
- break;
- case YASM_EXPR_NE:
- BitVector_Empty(result);
- BitVector_LSB(result, !BitVector_equal(op1, op2));
- break;
- case YASM_EXPR_SEG:
- yasm_error_set(YASM_ERROR_ARITHMETIC, N_("invalid use of '%s'"),
- "SEG");
- break;
- case YASM_EXPR_WRT:
- yasm_error_set(YASM_ERROR_ARITHMETIC, N_("invalid use of '%s'"),
- "WRT");
- break;
- case YASM_EXPR_SEGOFF:
- yasm_error_set(YASM_ERROR_ARITHMETIC, N_("invalid use of '%s'"),
- ":");
- break;
- case YASM_EXPR_IDENT:
- if (result)
- BitVector_Copy(result, op1);
- break;
- default:
- yasm_error_set(YASM_ERROR_ARITHMETIC,
- N_("invalid operation in intnum calculation"));
- BitVector_Empty(result);
- return 1;
- }
-
- /* Try to fit the result into 32 bits if possible */
- if (acc->type == INTNUM_BV)
- BitVector_Destroy(acc->val.bv);
- intnum_frombv(acc, result);
- return 0;
-}
-/*@=nullderef =nullpass =branchstate@*/
-
-int
-yasm_intnum_compare(const yasm_intnum *intn1, const yasm_intnum *intn2)
-{
- wordptr op1, op2;
-
- if (intn1->type == INTNUM_L && intn2->type == INTNUM_L) {
- if (intn1->val.l < intn2->val.l)
- return -1;
- if (intn1->val.l > intn2->val.l)
- return 1;
- return 0;
- }
-
- op1 = intnum_tobv(op1static, intn1);
- op2 = intnum_tobv(op2static, intn2);
- return BitVector_Compare(op1, op2);
-}
-
-void
-yasm_intnum_zero(yasm_intnum *intn)
-{
- yasm_intnum_set_int(intn, 0);
-}
-
-void
-yasm_intnum_set(yasm_intnum *intn, const yasm_intnum *val)
-{
- if (intn->type == val->type) {
- switch (val->type) {
- case INTNUM_L:
- intn->val.l = val->val.l;
- break;
- case INTNUM_BV:
- BitVector_Copy(intn->val.bv, val->val.bv);
- break;
- }
- } else {
- switch (val->type) {
- case INTNUM_L:
- BitVector_Destroy(intn->val.bv);
- intn->val.l = val->val.l;
- break;
- case INTNUM_BV:
- intn->val.bv = BitVector_Clone(val->val.bv);
- break;
- }
- intn->type = val->type;
- }
-}
-
-void
-yasm_intnum_set_uint(yasm_intnum *intn, unsigned long val)
-{
- if (val > LONG_MAX) {
- if (intn->type != INTNUM_BV) {
- intn->val.bv = BitVector_Create(BITVECT_NATIVE_SIZE, TRUE);
- intn->type = INTNUM_BV;
- }
- BitVector_Chunk_Store(intn->val.bv, 32, 0, val);
- } else {
- if (intn->type == INTNUM_BV) {
- BitVector_Destroy(intn->val.bv);
- intn->type = INTNUM_L;
- }
- intn->val.l = (long)val;
- }
-}
-
-void
-yasm_intnum_set_int(yasm_intnum *intn, long val)
-{
- if (intn->type == INTNUM_BV)
- BitVector_Destroy(intn->val.bv);
- intn->type = INTNUM_L;
- intn->val.l = val;
-}
-
-int
-yasm_intnum_is_zero(const yasm_intnum *intn)
-{
- return (intn->type == INTNUM_L && intn->val.l == 0);
-}
-
-int
-yasm_intnum_is_pos1(const yasm_intnum *intn)
-{
- return (intn->type == INTNUM_L && intn->val.l == 1);
-}
-
-int
-yasm_intnum_is_neg1(const yasm_intnum *intn)
-{
- return (intn->type == INTNUM_L && intn->val.l == -1);
-}
-
-int
-yasm_intnum_sign(const yasm_intnum *intn)
-{
- if (intn->type == INTNUM_L) {
- if (intn->val.l == 0)
- return 0;
- else if (intn->val.l < 0)
- return -1;
- else
- return 1;
- } else
- return BitVector_Sign(intn->val.bv);
-}
-
-unsigned long
-yasm_intnum_get_uint(const yasm_intnum *intn)
-{
- switch (intn->type) {
- case INTNUM_L:
- if (intn->val.l < 0)
- return 0;
- return (unsigned long)intn->val.l;
- case INTNUM_BV:
- if (BitVector_msb_(intn->val.bv))
- return 0;
- if (Set_Max(intn->val.bv) > 32)
- return ULONG_MAX;
- return BitVector_Chunk_Read(intn->val.bv, 32, 0);
- default:
- yasm_internal_error(N_("unknown intnum type"));
- /*@notreached@*/
- return 0;
- }
-}
-
-long
-yasm_intnum_get_int(const yasm_intnum *intn)
-{
- switch (intn->type) {
- case INTNUM_L:
- return intn->val.l;
- case INTNUM_BV:
- if (BitVector_msb_(intn->val.bv)) {
- /* it's negative: negate the bitvector to get a positive
- * number, then negate the positive number.
- */
- unsigned long ul;
-
- BitVector_Negate(conv_bv, intn->val.bv);
- if (Set_Max(conv_bv) >= 32) {
- /* too negative */
- return LONG_MIN;
- }
- ul = BitVector_Chunk_Read(conv_bv, 32, 0);
- /* check for too negative */
- return (ul & 0x80000000) ? LONG_MIN : -((long)ul);
- }
-
- /* it's positive, and since it's a BV, it must be >0x7FFFFFFF */
- return LONG_MAX;
- default:
- yasm_internal_error(N_("unknown intnum type"));
- /*@notreached@*/
- return 0;
- }
-}
-
-void
-yasm_intnum_get_sized(const yasm_intnum *intn, unsigned char *ptr,
- size_t destsize, size_t valsize, int shift,
- int bigendian, int warn)
-{
- wordptr op1 = op1static, op2;
- unsigned char *buf;
- unsigned int len;
- size_t rshift = shift < 0 ? (size_t)(-shift) : 0;
- int carry_in;
-
- /* Currently don't support destinations larger than our native size */
- if (destsize*8 > BITVECT_NATIVE_SIZE)
- yasm_internal_error(N_("destination too large"));
-
- /* General size warnings */
- if (warn<0 && !yasm_intnum_check_size(intn, valsize, rshift, 1))
- yasm_warn_set(YASM_WARN_GENERAL,
- N_("value does not fit in signed %d bit field"),
- valsize);
- if (warn>0 && !yasm_intnum_check_size(intn, valsize, rshift, 2))
- yasm_warn_set(YASM_WARN_GENERAL,
- N_("value does not fit in %d bit field"), valsize);
-
- /* Read the original data into a bitvect */
- if (bigendian) {
- /* TODO */
- yasm_internal_error(N_("big endian not implemented"));
- } else
- BitVector_Block_Store(op1, ptr, (N_int)destsize);
-
- /* If not already a bitvect, convert value to be written to a bitvect */
- op2 = intnum_tobv(op2static, intn);
-
- /* Check low bits if right shifting and warnings enabled */
- if (warn && rshift > 0) {
- BitVector_Copy(conv_bv, op2);
- BitVector_Move_Left(conv_bv, (N_int)(BITVECT_NATIVE_SIZE-rshift));
- if (!BitVector_is_empty(conv_bv))
- yasm_warn_set(YASM_WARN_GENERAL,
- N_("misaligned value, truncating to boundary"));
- }
-
- /* Shift right if needed */
- if (rshift > 0) {
- carry_in = BitVector_msb_(op2);
- while (rshift-- > 0)
- BitVector_shift_right(op2, carry_in);
- shift = 0;
- }
-
- /* Write the new value into the destination bitvect */
- BitVector_Interval_Copy(op1, op2, (unsigned int)shift, 0, (N_int)valsize);
-
- /* Write out the new data */
- buf = BitVector_Block_Read(op1, &len);
- if (bigendian) {
- /* TODO */
- yasm_internal_error(N_("big endian not implemented"));
- } else
- memcpy(ptr, buf, destsize);
- yasm_xfree(buf);
-}
-
-/* Return 1 if okay size, 0 if not */
-int
-yasm_intnum_check_size(const yasm_intnum *intn, size_t size, size_t rshift,
- int rangetype)
-{
- wordptr val;
-
- /* If not already a bitvect, convert value to a bitvect */
- if (intn->type == INTNUM_BV) {
- if (rshift > 0) {
- val = conv_bv;
- BitVector_Copy(val, intn->val.bv);
- } else
- val = intn->val.bv;
- } else
- val = intnum_tobv(conv_bv, intn);
-
- if (size >= BITVECT_NATIVE_SIZE)
- return 1;
-
- if (rshift > 0) {
- int carry_in = BitVector_msb_(val);
- while (rshift-- > 0)
- BitVector_shift_right(val, carry_in);
- }
-
- if (rangetype > 0) {
- if (BitVector_msb_(val)) {
- /* it's negative */
- int retval;
-
- BitVector_Negate(conv_bv, val);
- BitVector_dec(conv_bv, conv_bv);
- retval = Set_Max(conv_bv) < (long)size-1;
-
- return retval;
- }
-
- if (rangetype == 1)
- size--;
- }
- return (Set_Max(val) < (long)size);
-}
-
-int
-yasm_intnum_in_range(const yasm_intnum *intn, long low, long high)
-{
- wordptr val = intnum_tobv(result, intn);
- wordptr lval = op1static;
- wordptr hval = op2static;
-
- /* Convert high and low to bitvects */
- BitVector_Empty(lval);
- if (low >= 0)
- BitVector_Chunk_Store(lval, 32, 0, (unsigned long)low);
- else {
- BitVector_Chunk_Store(lval, 32, 0, (unsigned long)(-low));
- BitVector_Negate(lval, lval);
- }
-
- BitVector_Empty(hval);
- if (high >= 0)
- BitVector_Chunk_Store(hval, 32, 0, (unsigned long)high);
- else {
- BitVector_Chunk_Store(hval, 32, 0, (unsigned long)(-high));
- BitVector_Negate(hval, hval);
- }
-
- /* Compare! */
- return (BitVector_Compare(val, lval) >= 0
- && BitVector_Compare(val, hval) <= 0);
-}
-
-static unsigned long
-get_leb128(wordptr val, unsigned char *ptr, int sign)
-{
- unsigned long i, size;
- unsigned char *ptr_orig = ptr;
-
- if (sign) {
- /* Signed mode */
- if (BitVector_msb_(val)) {
- /* Negative */
- BitVector_Negate(conv_bv, val);
- size = Set_Max(conv_bv)+2;
- } else {
- /* Positive */
- size = Set_Max(val)+2;
- }
- } else {
- /* Unsigned mode */
- size = Set_Max(val)+1;
- }
-
- /* Positive/Unsigned write */
- for (i=0; i<size; i += 7) {
- *ptr = (unsigned char)BitVector_Chunk_Read(val, 7, i);
- *ptr |= 0x80;
- ptr++;
- }
- *(ptr-1) &= 0x7F; /* Clear MSB of last byte */
- return (unsigned long)(ptr-ptr_orig);
-}
-
-static unsigned long
-size_leb128(wordptr val, int sign)
-{
- if (sign) {
- /* Signed mode */
- if (BitVector_msb_(val)) {
- /* Negative */
- BitVector_Negate(conv_bv, val);
- return (Set_Max(conv_bv)+8)/7;
- } else {
- /* Positive */
- return (Set_Max(val)+8)/7;
- }
- } else {
- /* Unsigned mode */
- return (Set_Max(val)+7)/7;
- }
-}
-
-unsigned long
-yasm_intnum_get_leb128(const yasm_intnum *intn, unsigned char *ptr, int sign)
-{
- wordptr val;
-
- /* Shortcut 0 */
- if (intn->type == INTNUM_L && intn->val.l == 0) {
- *ptr = 0;
- return 1;
- }
-
- /* If not already a bitvect, convert value to be written to a bitvect */
- val = intnum_tobv(op1static, intn);
-
- return get_leb128(val, ptr, sign);
-}
-
-unsigned long
-yasm_intnum_size_leb128(const yasm_intnum *intn, int sign)
-{
- wordptr val;
-
- /* Shortcut 0 */
- if (intn->type == INTNUM_L && intn->val.l == 0) {
- return 1;
- }
-
- /* If not already a bitvect, convert value to a bitvect */
- val = intnum_tobv(op1static, intn);
-
- return size_leb128(val, sign);
-}
-
-unsigned long
-yasm_get_sleb128(long v, unsigned char *ptr)
-{
- wordptr val = op1static;
-
- /* Shortcut 0 */
- if (v == 0) {
- *ptr = 0;
- return 1;
- }
-
- BitVector_Empty(val);
- if (v >= 0)
- BitVector_Chunk_Store(val, 32, 0, (unsigned long)v);
- else {
- BitVector_Chunk_Store(val, 32, 0, (unsigned long)(-v));
- BitVector_Negate(val, val);
- }
- return get_leb128(val, ptr, 1);
-}
-
-unsigned long
-yasm_size_sleb128(long v)
-{
- wordptr val = op1static;
-
- if (v == 0)
- return 1;
-
- BitVector_Empty(val);
- if (v >= 0)
- BitVector_Chunk_Store(val, 32, 0, (unsigned long)v);
- else {
- BitVector_Chunk_Store(val, 32, 0, (unsigned long)(-v));
- BitVector_Negate(val, val);
- }
- return size_leb128(val, 1);
-}
-
-unsigned long
-yasm_get_uleb128(unsigned long v, unsigned char *ptr)
-{
- wordptr val = op1static;
-
- /* Shortcut 0 */
- if (v == 0) {
- *ptr = 0;
- return 1;
- }
-
- BitVector_Empty(val);
- BitVector_Chunk_Store(val, 32, 0, v);
- return get_leb128(val, ptr, 0);
-}
-
-unsigned long
-yasm_size_uleb128(unsigned long v)
-{
- wordptr val = op1static;
-
- if (v == 0)
- return 1;
-
- BitVector_Empty(val);
- BitVector_Chunk_Store(val, 32, 0, v);
- return size_leb128(val, 0);
-}
-
-char *
-yasm_intnum_get_str(const yasm_intnum *intn)
-{
- unsigned char *s;
-
- switch (intn->type) {
- case INTNUM_L:
- s = yasm_xmalloc(16);
- sprintf((char *)s, "%ld", intn->val.l);
- 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 char *s;
-
- switch (intn->type) {
- case INTNUM_L:
- fprintf(f, "0x%lx", intn->val.l);
- break;
- case INTNUM_BV:
- s = BitVector_to_Hex(intn->val.bv);
- fprintf(f, "0x%s", (char *)s);
- yasm_xfree(s);
- break;
- }
-}
+/*
+ * Integer number functions.
+ *
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "util.h"
+
+#include <ctype.h>
+#include <limits.h>
+
+#include "coretype.h"
+#include "bitvect.h"
+#include "file.h"
+
+#include "errwarn.h"
+#include "intnum.h"
+
+
+/* "Native" "word" size for intnum calculations. */
+#define BITVECT_NATIVE_SIZE 256
+
+struct yasm_intnum {
+ union val {
+ long l; /* integer value (for integers <32 bits) */
+ wordptr bv; /* bit vector (for integers >=32 bits) */
+ } val;
+ enum { INTNUM_L, INTNUM_BV } type;
+};
+
+/* static bitvect used for conversions */
+static /*@only@*/ wordptr conv_bv;
+
+/* static bitvects used for computation */
+static /*@only@*/ wordptr result, spare, op1static, op2static;
+
+static /*@only@*/ BitVector_from_Dec_static_data *from_dec_data;
+
+
+void
+yasm_intnum_initialize(void)
+{
+ conv_bv = BitVector_Create(BITVECT_NATIVE_SIZE, FALSE);
+ result = BitVector_Create(BITVECT_NATIVE_SIZE, FALSE);
+ spare = BitVector_Create(BITVECT_NATIVE_SIZE, FALSE);
+ op1static = BitVector_Create(BITVECT_NATIVE_SIZE, FALSE);
+ op2static = BitVector_Create(BITVECT_NATIVE_SIZE, FALSE);
+ from_dec_data = BitVector_from_Dec_static_Boot(BITVECT_NATIVE_SIZE);
+}
+
+void
+yasm_intnum_cleanup(void)
+{
+ BitVector_from_Dec_static_Shutdown(from_dec_data);
+ BitVector_Destroy(op2static);
+ BitVector_Destroy(op1static);
+ BitVector_Destroy(spare);
+ BitVector_Destroy(result);
+ BitVector_Destroy(conv_bv);
+}
+
+/* Compress a bitvector into intnum storage.
+ * If saved as a bitvector, clones the passed bitvector.
+ * Can modify the passed bitvector.
+ */
+static void
+intnum_frombv(/*@out@*/ yasm_intnum *intn, wordptr bv)
+{
+ if (Set_Max(bv) < 31) {
+ intn->type = INTNUM_L;
+ intn->val.l = (long)BitVector_Chunk_Read(bv, 31, 0);
+ } else if (BitVector_msb_(bv)) {
+ /* Negative, negate and see if we'll fit into a long. */
+ unsigned long ul;
+ BitVector_Negate(bv, bv);
+ if (Set_Max(bv) >= 32 ||
+ ((ul = BitVector_Chunk_Read(bv, 32, 0)) & 0x80000000)) {
+ /* too negative */
+ BitVector_Negate(bv, bv);
+ intn->type = INTNUM_BV;
+ intn->val.bv = BitVector_Clone(bv);
+ } else {
+ intn->type = INTNUM_L;
+ intn->val.l = -((long)ul);
+ }
+ } else {
+ intn->type = INTNUM_BV;
+ intn->val.bv = BitVector_Clone(bv);
+ }
+}
+
+/* If intnum is a BV, returns its bitvector directly.
+ * If not, converts into passed bv and returns that instead.
+ */
+static wordptr
+intnum_tobv(/*@returned@*/ wordptr bv, const yasm_intnum *intn)
+{
+ if (intn->type == INTNUM_BV)
+ return intn->val.bv;
+
+ BitVector_Empty(bv);
+ if (intn->val.l >= 0)
+ BitVector_Chunk_Store(bv, 32, 0, (unsigned long)intn->val.l);
+ else {
+ BitVector_Chunk_Store(bv, 32, 0, (unsigned long)-intn->val.l);
+ BitVector_Negate(bv, bv);
+ }
+ return bv;
+}
+
+yasm_intnum *
+yasm_intnum_create_dec(char *str)
+{
+ yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
+
+ switch (BitVector_from_Dec_static(from_dec_data, conv_bv,
+ (unsigned char *)str)) {
+ case ErrCode_Pars:
+ yasm_error_set(YASM_ERROR_VALUE, N_("invalid decimal literal"));
+ break;
+ case ErrCode_Ovfl:
+ yasm_error_set(YASM_ERROR_OVERFLOW,
+ N_("Numeric constant too large for internal format"));
+ break;
+ default:
+ break;
+ }
+ intnum_frombv(intn, conv_bv);
+ return intn;
+}
+
+yasm_intnum *
+yasm_intnum_create_bin(char *str)
+{
+ yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
+
+ switch (BitVector_from_Bin(conv_bv, (unsigned char *)str)) {
+ case ErrCode_Pars:
+ yasm_error_set(YASM_ERROR_VALUE, N_("invalid binary literal"));
+ break;
+ case ErrCode_Ovfl:
+ yasm_error_set(YASM_ERROR_OVERFLOW,
+ N_("Numeric constant too large for internal format"));
+ break;
+ default:
+ break;
+ }
+ intnum_frombv(intn, conv_bv);
+ return intn;
+}
+
+yasm_intnum *
+yasm_intnum_create_oct(char *str)
+{
+ yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
+
+ switch (BitVector_from_Oct(conv_bv, (unsigned char *)str)) {
+ case ErrCode_Pars:
+ yasm_error_set(YASM_ERROR_VALUE, N_("invalid octal literal"));
+ break;
+ case ErrCode_Ovfl:
+ yasm_error_set(YASM_ERROR_OVERFLOW,
+ N_("Numeric constant too large for internal format"));
+ break;
+ default:
+ break;
+ }
+ intnum_frombv(intn, conv_bv);
+ return intn;
+}
+
+yasm_intnum *
+yasm_intnum_create_hex(char *str)
+{
+ yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
+
+ switch (BitVector_from_Hex(conv_bv, (unsigned char *)str)) {
+ case ErrCode_Pars:
+ yasm_error_set(YASM_ERROR_VALUE, N_("invalid hex literal"));
+ break;
+ case ErrCode_Ovfl:
+ yasm_error_set(YASM_ERROR_OVERFLOW,
+ N_("Numeric constant too large for internal format"));
+ break;
+ default:
+ break;
+ }
+ intnum_frombv(intn, conv_bv);
+ return intn;
+}
+
+/*@-usedef -compdef -uniondef@*/
+yasm_intnum *
+yasm_intnum_create_charconst_nasm(const char *str)
+{
+ yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
+ size_t len = strlen(str);
+
+ if(len*8 > BITVECT_NATIVE_SIZE)
+ yasm_error_set(YASM_ERROR_OVERFLOW,
+ N_("Character constant too large for internal format"));
+
+ /* be conservative in choosing bitvect in case MSB is set */
+ if (len > 3) {
+ BitVector_Empty(conv_bv);
+ intn->type = INTNUM_BV;
+ } else {
+ intn->val.l = 0;
+ intn->type = INTNUM_L;
+ }
+
+ switch (len) {
+ case 3:
+ intn->val.l |= ((unsigned long)str[2]) & 0xff;
+ intn->val.l <<= 8;
+ /*@fallthrough@*/
+ case 2:
+ intn->val.l |= ((unsigned long)str[1]) & 0xff;
+ intn->val.l <<= 8;
+ /*@fallthrough@*/
+ case 1:
+ intn->val.l |= ((unsigned long)str[0]) & 0xff;
+ case 0:
+ break;
+ default:
+ /* >=32 bit conversion */
+ while (len) {
+ BitVector_Move_Left(conv_bv, 8);
+ BitVector_Chunk_Store(conv_bv, 8, 0,
+ ((unsigned long)str[--len]) & 0xff);
+ }
+ intn->val.bv = BitVector_Clone(conv_bv);
+ }
+
+ return intn;
+}
+
+yasm_intnum *
+yasm_intnum_create_charconst_tasm(const char *str)
+{
+ yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
+ size_t len = strlen(str);
+ size_t i;
+
+ if(len*8 > BITVECT_NATIVE_SIZE)
+ yasm_error_set(YASM_ERROR_OVERFLOW,
+ N_("Character constant too large for internal format"));
+
+ /* be conservative in choosing bitvect in case MSB is set */
+ if (len > 3) {
+ BitVector_Empty(conv_bv);
+ intn->type = INTNUM_BV;
+ } else {
+ intn->val.l = 0;
+ intn->type = INTNUM_L;
+ }
+
+ /* tasm uses big endian notation */
+ i = 0;
+ switch (len) {
+ case 3:
+ intn->val.l |= ((unsigned long)str[i++]) & 0xff;
+ intn->val.l <<= 8;
+ /*@fallthrough@*/
+ case 2:
+ intn->val.l |= ((unsigned long)str[i++]) & 0xff;
+ intn->val.l <<= 8;
+ /*@fallthrough@*/
+ case 1:
+ intn->val.l |= ((unsigned long)str[i++]) & 0xff;
+ case 0:
+ break;
+ default:
+ /* >=32 bit conversion */
+ while (i < len) {
+ BitVector_Chunk_Store(conv_bv, 8, (len-i-1)*8,
+ ((unsigned long)str[i]) & 0xff);
+ i++;
+ }
+ intn->val.bv = BitVector_Clone(conv_bv);
+ }
+
+ return intn;
+}
+/*@=usedef =compdef =uniondef@*/
+
+yasm_intnum *
+yasm_intnum_create_uint(unsigned long i)
+{
+ yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
+
+ if (i > LONG_MAX) {
+ /* Too big, store as bitvector */
+ intn->val.bv = BitVector_Create(BITVECT_NATIVE_SIZE, TRUE);
+ intn->type = INTNUM_BV;
+ BitVector_Chunk_Store(intn->val.bv, 32, 0, i);
+ } else {
+ intn->val.l = (long)i;
+ intn->type = INTNUM_L;
+ }
+
+ return intn;
+}
+
+yasm_intnum *
+yasm_intnum_create_int(long i)
+{
+ yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
+
+ intn->val.l = i;
+ intn->type = INTNUM_L;
+
+ return intn;
+}
+
+yasm_intnum *
+yasm_intnum_create_leb128(const unsigned char *ptr, int sign,
+ unsigned long *size)
+{
+ yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
+ const unsigned char *ptr_orig = ptr;
+ unsigned long i = 0;
+
+ BitVector_Empty(conv_bv);
+ for (;;) {
+ BitVector_Chunk_Store(conv_bv, 7, i, *ptr);
+ i += 7;
+ if ((*ptr & 0x80) != 0x80)
+ break;
+ ptr++;
+ }
+
+ *size = (unsigned long)(ptr-ptr_orig)+1;
+
+ if(i > BITVECT_NATIVE_SIZE)
+ yasm_error_set(YASM_ERROR_OVERFLOW,
+ N_("Numeric constant too large for internal format"));
+ else if (sign && (*ptr & 0x40) == 0x40)
+ BitVector_Interval_Fill(conv_bv, i, BITVECT_NATIVE_SIZE-1);
+
+ intnum_frombv(intn, conv_bv);
+ return intn;
+}
+
+yasm_intnum *
+yasm_intnum_create_sized(unsigned char *ptr, int sign, size_t srcsize,
+ int bigendian)
+{
+ yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
+ unsigned long i = 0;
+
+ if (srcsize*8 > BITVECT_NATIVE_SIZE)
+ yasm_error_set(YASM_ERROR_OVERFLOW,
+ N_("Numeric constant too large for internal format"));
+
+ /* Read the buffer into a bitvect */
+ BitVector_Empty(conv_bv);
+ if (bigendian) {
+ /* TODO */
+ yasm_internal_error(N_("big endian not implemented"));
+ } else {
+ for (i = 0; i < srcsize; i++)
+ BitVector_Chunk_Store(conv_bv, 8, i*8, ptr[i]);
+ }
+
+ /* Sign extend if needed */
+ if (srcsize*8 < BITVECT_NATIVE_SIZE && sign && (ptr[i-1] & 0x80) == 0x80)
+ BitVector_Interval_Fill(conv_bv, i*8, BITVECT_NATIVE_SIZE-1);
+
+ intnum_frombv(intn, conv_bv);
+ return intn;
+}
+
+yasm_intnum *
+yasm_intnum_copy(const yasm_intnum *intn)
+{
+ yasm_intnum *n = yasm_xmalloc(sizeof(yasm_intnum));
+
+ switch (intn->type) {
+ case INTNUM_L:
+ n->val.l = intn->val.l;
+ break;
+ case INTNUM_BV:
+ n->val.bv = BitVector_Clone(intn->val.bv);
+ break;
+ }
+ n->type = intn->type;
+
+ return n;
+}
+
+void
+yasm_intnum_destroy(yasm_intnum *intn)
+{
+ if (intn->type == INTNUM_BV)
+ BitVector_Destroy(intn->val.bv);
+ yasm_xfree(intn);
+}
+
+/*@-nullderef -nullpass -branchstate@*/
+int
+yasm_intnum_calc(yasm_intnum *acc, yasm_expr_op op, yasm_intnum *operand)
+{
+ boolean carry = 0;
+ wordptr op1, op2 = NULL;
+ N_int count;
+
+ /* Always do computations with in full bit vector.
+ * Bit vector results must be calculated through intermediate storage.
+ */
+ op1 = intnum_tobv(op1static, acc);
+ if (operand)
+ op2 = intnum_tobv(op2static, operand);
+
+ if (!operand && op != YASM_EXPR_NEG && op != YASM_EXPR_NOT &&
+ op != YASM_EXPR_LNOT) {
+ yasm_error_set(YASM_ERROR_ARITHMETIC,
+ N_("operation needs an operand"));
+ BitVector_Empty(result);
+ return 1;
+ }
+
+ /* A operation does a bitvector computation if result is allocated. */
+ switch (op) {
+ case YASM_EXPR_ADD:
+ BitVector_add(result, op1, op2, &carry);
+ break;
+ case YASM_EXPR_SUB:
+ BitVector_sub(result, op1, op2, &carry);
+ break;
+ case YASM_EXPR_MUL:
+ BitVector_Multiply(result, op1, op2);
+ break;
+ case YASM_EXPR_DIV:
+ /* TODO: make sure op1 and op2 are unsigned */
+ if (BitVector_is_empty(op2)) {
+ yasm_error_set(YASM_ERROR_ZERO_DIVISION, N_("divide by zero"));
+ BitVector_Empty(result);
+ return 1;
+ } else
+ BitVector_Divide(result, op1, op2, spare);
+ break;
+ case YASM_EXPR_SIGNDIV:
+ if (BitVector_is_empty(op2)) {
+ yasm_error_set(YASM_ERROR_ZERO_DIVISION, N_("divide by zero"));
+ BitVector_Empty(result);
+ return 1;
+ } else
+ BitVector_Divide(result, op1, op2, spare);
+ break;
+ case YASM_EXPR_MOD:
+ /* TODO: make sure op1 and op2 are unsigned */
+ if (BitVector_is_empty(op2)) {
+ yasm_error_set(YASM_ERROR_ZERO_DIVISION, N_("divide by zero"));
+ BitVector_Empty(result);
+ return 1;
+ } else
+ BitVector_Divide(spare, op1, op2, result);
+ break;
+ case YASM_EXPR_SIGNMOD:
+ if (BitVector_is_empty(op2)) {
+ yasm_error_set(YASM_ERROR_ZERO_DIVISION, N_("divide by zero"));
+ BitVector_Empty(result);
+ return 1;
+ } else
+ BitVector_Divide(spare, op1, op2, result);
+ break;
+ case YASM_EXPR_NEG:
+ BitVector_Negate(result, op1);
+ break;
+ case YASM_EXPR_NOT:
+ Set_Complement(result, op1);
+ break;
+ case YASM_EXPR_OR:
+ Set_Union(result, op1, op2);
+ break;
+ case YASM_EXPR_AND:
+ Set_Intersection(result, op1, op2);
+ 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);
+ break;
+ case YASM_EXPR_SHL:
+ if (operand->type == INTNUM_L && operand->val.l >= 0) {
+ BitVector_Copy(result, op1);
+ BitVector_Move_Left(result, (N_int)operand->val.l);
+ } else /* don't even bother, just zero result */
+ BitVector_Empty(result);
+ break;
+ case YASM_EXPR_SHR:
+ if (operand->type == INTNUM_L && operand->val.l >= 0) {
+ BitVector_Copy(result, op1);
+ carry = BitVector_msb_(op1);
+ count = (N_int)operand->val.l;
+ while (count-- > 0)
+ BitVector_shift_right(result, carry);
+ } else /* don't even bother, just zero result */
+ BitVector_Empty(result);
+ break;
+ case YASM_EXPR_LOR:
+ BitVector_Empty(result);
+ BitVector_LSB(result, !BitVector_is_empty(op1) ||
+ !BitVector_is_empty(op2));
+ break;
+ case YASM_EXPR_LAND:
+ BitVector_Empty(result);
+ BitVector_LSB(result, !BitVector_is_empty(op1) &&
+ !BitVector_is_empty(op2));
+ break;
+ case YASM_EXPR_LNOT:
+ 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));
+ break;
+ case YASM_EXPR_LT:
+ BitVector_Empty(result);
+ BitVector_LSB(result, BitVector_Compare(op1, op2) < 0);
+ break;
+ case YASM_EXPR_GT:
+ BitVector_Empty(result);
+ BitVector_LSB(result, BitVector_Compare(op1, op2) > 0);
+ break;
+ case YASM_EXPR_LE:
+ BitVector_Empty(result);
+ BitVector_LSB(result, BitVector_Compare(op1, op2) <= 0);
+ break;
+ case YASM_EXPR_GE:
+ BitVector_Empty(result);
+ BitVector_LSB(result, BitVector_Compare(op1, op2) >= 0);
+ break;
+ case YASM_EXPR_NE:
+ BitVector_Empty(result);
+ BitVector_LSB(result, !BitVector_equal(op1, op2));
+ break;
+ case YASM_EXPR_SEG:
+ yasm_error_set(YASM_ERROR_ARITHMETIC, N_("invalid use of '%s'"),
+ "SEG");
+ break;
+ case YASM_EXPR_WRT:
+ yasm_error_set(YASM_ERROR_ARITHMETIC, N_("invalid use of '%s'"),
+ "WRT");
+ break;
+ case YASM_EXPR_SEGOFF:
+ yasm_error_set(YASM_ERROR_ARITHMETIC, N_("invalid use of '%s'"),
+ ":");
+ break;
+ case YASM_EXPR_IDENT:
+ if (result)
+ BitVector_Copy(result, op1);
+ break;
+ default:
+ yasm_error_set(YASM_ERROR_ARITHMETIC,
+ N_("invalid operation in intnum calculation"));
+ BitVector_Empty(result);
+ return 1;
+ }
+
+ /* Try to fit the result into 32 bits if possible */
+ if (acc->type == INTNUM_BV)
+ BitVector_Destroy(acc->val.bv);
+ intnum_frombv(acc, result);
+ return 0;
+}
+/*@=nullderef =nullpass =branchstate@*/
+
+int
+yasm_intnum_compare(const yasm_intnum *intn1, const yasm_intnum *intn2)
+{
+ wordptr op1, op2;
+
+ if (intn1->type == INTNUM_L && intn2->type == INTNUM_L) {
+ if (intn1->val.l < intn2->val.l)
+ return -1;
+ if (intn1->val.l > intn2->val.l)
+ return 1;
+ return 0;
+ }
+
+ op1 = intnum_tobv(op1static, intn1);
+ op2 = intnum_tobv(op2static, intn2);
+ return BitVector_Compare(op1, op2);
+}
+
+void
+yasm_intnum_zero(yasm_intnum *intn)
+{
+ yasm_intnum_set_int(intn, 0);
+}
+
+void
+yasm_intnum_set(yasm_intnum *intn, const yasm_intnum *val)
+{
+ if (intn->type == val->type) {
+ switch (val->type) {
+ case INTNUM_L:
+ intn->val.l = val->val.l;
+ break;
+ case INTNUM_BV:
+ BitVector_Copy(intn->val.bv, val->val.bv);
+ break;
+ }
+ } else {
+ switch (val->type) {
+ case INTNUM_L:
+ BitVector_Destroy(intn->val.bv);
+ intn->val.l = val->val.l;
+ break;
+ case INTNUM_BV:
+ intn->val.bv = BitVector_Clone(val->val.bv);
+ break;
+ }
+ intn->type = val->type;
+ }
+}
+
+void
+yasm_intnum_set_uint(yasm_intnum *intn, unsigned long val)
+{
+ if (val > LONG_MAX) {
+ if (intn->type != INTNUM_BV) {
+ intn->val.bv = BitVector_Create(BITVECT_NATIVE_SIZE, TRUE);
+ intn->type = INTNUM_BV;
+ }
+ BitVector_Chunk_Store(intn->val.bv, 32, 0, val);
+ } else {
+ if (intn->type == INTNUM_BV) {
+ BitVector_Destroy(intn->val.bv);
+ intn->type = INTNUM_L;
+ }
+ intn->val.l = (long)val;
+ }
+}
+
+void
+yasm_intnum_set_int(yasm_intnum *intn, long val)
+{
+ if (intn->type == INTNUM_BV)
+ BitVector_Destroy(intn->val.bv);
+ intn->type = INTNUM_L;
+ intn->val.l = val;
+}
+
+int
+yasm_intnum_is_zero(const yasm_intnum *intn)
+{
+ return (intn->type == INTNUM_L && intn->val.l == 0);
+}
+
+int
+yasm_intnum_is_pos1(const yasm_intnum *intn)
+{
+ return (intn->type == INTNUM_L && intn->val.l == 1);
+}
+
+int
+yasm_intnum_is_neg1(const yasm_intnum *intn)
+{
+ return (intn->type == INTNUM_L && intn->val.l == -1);
+}
+
+int
+yasm_intnum_sign(const yasm_intnum *intn)
+{
+ if (intn->type == INTNUM_L) {
+ if (intn->val.l == 0)
+ return 0;
+ else if (intn->val.l < 0)
+ return -1;
+ else
+ return 1;
+ } else
+ return BitVector_Sign(intn->val.bv);
+}
+
+unsigned long
+yasm_intnum_get_uint(const yasm_intnum *intn)
+{
+ switch (intn->type) {
+ case INTNUM_L:
+ if (intn->val.l < 0)
+ return 0;
+ return (unsigned long)intn->val.l;
+ case INTNUM_BV:
+ if (BitVector_msb_(intn->val.bv))
+ return 0;
+ if (Set_Max(intn->val.bv) > 32)
+ return ULONG_MAX;
+ return BitVector_Chunk_Read(intn->val.bv, 32, 0);
+ default:
+ yasm_internal_error(N_("unknown intnum type"));
+ /*@notreached@*/
+ return 0;
+ }
+}
+
+long
+yasm_intnum_get_int(const yasm_intnum *intn)
+{
+ switch (intn->type) {
+ case INTNUM_L:
+ return intn->val.l;
+ case INTNUM_BV:
+ if (BitVector_msb_(intn->val.bv)) {
+ /* it's negative: negate the bitvector to get a positive
+ * number, then negate the positive number.
+ */
+ unsigned long ul;
+
+ BitVector_Negate(conv_bv, intn->val.bv);
+ if (Set_Max(conv_bv) >= 32) {
+ /* too negative */
+ return LONG_MIN;
+ }
+ ul = BitVector_Chunk_Read(conv_bv, 32, 0);
+ /* check for too negative */
+ return (ul & 0x80000000) ? LONG_MIN : -((long)ul);
+ }
+
+ /* it's positive, and since it's a BV, it must be >0x7FFFFFFF */
+ return LONG_MAX;
+ default:
+ yasm_internal_error(N_("unknown intnum type"));
+ /*@notreached@*/
+ return 0;
+ }
+}
+
+void
+yasm_intnum_get_sized(const yasm_intnum *intn, unsigned char *ptr,
+ size_t destsize, size_t valsize, int shift,
+ int bigendian, int warn)
+{
+ wordptr op1 = op1static, op2;
+ unsigned char *buf;
+ unsigned int len;
+ size_t rshift = shift < 0 ? (size_t)(-shift) : 0;
+ int carry_in;
+
+ /* Currently don't support destinations larger than our native size */
+ if (destsize*8 > BITVECT_NATIVE_SIZE)
+ yasm_internal_error(N_("destination too large"));
+
+ /* General size warnings */
+ if (warn<0 && !yasm_intnum_check_size(intn, valsize, rshift, 1))
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("value does not fit in signed %d bit field"),
+ valsize);
+ if (warn>0 && !yasm_intnum_check_size(intn, valsize, rshift, 2))
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("value does not fit in %d bit field"), valsize);
+
+ /* Read the original data into a bitvect */
+ if (bigendian) {
+ /* TODO */
+ yasm_internal_error(N_("big endian not implemented"));
+ } else
+ BitVector_Block_Store(op1, ptr, (N_int)destsize);
+
+ /* If not already a bitvect, convert value to be written to a bitvect */
+ op2 = intnum_tobv(op2static, intn);
+
+ /* Check low bits if right shifting and warnings enabled */
+ if (warn && rshift > 0) {
+ BitVector_Copy(conv_bv, op2);
+ BitVector_Move_Left(conv_bv, (N_int)(BITVECT_NATIVE_SIZE-rshift));
+ if (!BitVector_is_empty(conv_bv))
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("misaligned value, truncating to boundary"));
+ }
+
+ /* Shift right if needed */
+ if (rshift > 0) {
+ carry_in = BitVector_msb_(op2);
+ while (rshift-- > 0)
+ BitVector_shift_right(op2, carry_in);
+ shift = 0;
+ }
+
+ /* Write the new value into the destination bitvect */
+ BitVector_Interval_Copy(op1, op2, (unsigned int)shift, 0, (N_int)valsize);
+
+ /* Write out the new data */
+ buf = BitVector_Block_Read(op1, &len);
+ if (bigendian) {
+ /* TODO */
+ yasm_internal_error(N_("big endian not implemented"));
+ } else
+ memcpy(ptr, buf, destsize);
+ yasm_xfree(buf);
+}
+
+/* Return 1 if okay size, 0 if not */
+int
+yasm_intnum_check_size(const yasm_intnum *intn, size_t size, size_t rshift,
+ int rangetype)
+{
+ wordptr val;
+
+ /* If not already a bitvect, convert value to a bitvect */
+ if (intn->type == INTNUM_BV) {
+ if (rshift > 0) {
+ val = conv_bv;
+ BitVector_Copy(val, intn->val.bv);
+ } else
+ val = intn->val.bv;
+ } else
+ val = intnum_tobv(conv_bv, intn);
+
+ if (size >= BITVECT_NATIVE_SIZE)
+ return 1;
+
+ if (rshift > 0) {
+ int carry_in = BitVector_msb_(val);
+ while (rshift-- > 0)
+ BitVector_shift_right(val, carry_in);
+ }
+
+ if (rangetype > 0) {
+ if (BitVector_msb_(val)) {
+ /* it's negative */
+ int retval;
+
+ BitVector_Negate(conv_bv, val);
+ BitVector_dec(conv_bv, conv_bv);
+ retval = Set_Max(conv_bv) < (long)size-1;
+
+ return retval;
+ }
+
+ if (rangetype == 1)
+ size--;
+ }
+ return (Set_Max(val) < (long)size);
+}
+
+int
+yasm_intnum_in_range(const yasm_intnum *intn, long low, long high)
+{
+ wordptr val = intnum_tobv(result, intn);
+ wordptr lval = op1static;
+ wordptr hval = op2static;
+
+ /* Convert high and low to bitvects */
+ BitVector_Empty(lval);
+ if (low >= 0)
+ BitVector_Chunk_Store(lval, 32, 0, (unsigned long)low);
+ else {
+ BitVector_Chunk_Store(lval, 32, 0, (unsigned long)(-low));
+ BitVector_Negate(lval, lval);
+ }
+
+ BitVector_Empty(hval);
+ if (high >= 0)
+ BitVector_Chunk_Store(hval, 32, 0, (unsigned long)high);
+ else {
+ BitVector_Chunk_Store(hval, 32, 0, (unsigned long)(-high));
+ BitVector_Negate(hval, hval);
+ }
+
+ /* Compare! */
+ return (BitVector_Compare(val, lval) >= 0
+ && BitVector_Compare(val, hval) <= 0);
+}
+
+static unsigned long
+get_leb128(wordptr val, unsigned char *ptr, int sign)
+{
+ unsigned long i, size;
+ unsigned char *ptr_orig = ptr;
+
+ if (sign) {
+ /* Signed mode */
+ if (BitVector_msb_(val)) {
+ /* Negative */
+ BitVector_Negate(conv_bv, val);
+ size = Set_Max(conv_bv)+2;
+ } else {
+ /* Positive */
+ size = Set_Max(val)+2;
+ }
+ } else {
+ /* Unsigned mode */
+ size = Set_Max(val)+1;
+ }
+
+ /* Positive/Unsigned write */
+ for (i=0; i<size; i += 7) {
+ *ptr = (unsigned char)BitVector_Chunk_Read(val, 7, i);
+ *ptr |= 0x80;
+ ptr++;
+ }
+ *(ptr-1) &= 0x7F; /* Clear MSB of last byte */
+ return (unsigned long)(ptr-ptr_orig);
+}
+
+static unsigned long
+size_leb128(wordptr val, int sign)
+{
+ if (sign) {
+ /* Signed mode */
+ if (BitVector_msb_(val)) {
+ /* Negative */
+ BitVector_Negate(conv_bv, val);
+ return (Set_Max(conv_bv)+8)/7;
+ } else {
+ /* Positive */
+ return (Set_Max(val)+8)/7;
+ }
+ } else {
+ /* Unsigned mode */
+ return (Set_Max(val)+7)/7;
+ }
+}
+
+unsigned long
+yasm_intnum_get_leb128(const yasm_intnum *intn, unsigned char *ptr, int sign)
+{
+ wordptr val;
+
+ /* Shortcut 0 */
+ if (intn->type == INTNUM_L && intn->val.l == 0) {
+ *ptr = 0;
+ return 1;
+ }
+
+ /* If not already a bitvect, convert value to be written to a bitvect */
+ val = intnum_tobv(op1static, intn);
+
+ return get_leb128(val, ptr, sign);
+}
+
+unsigned long
+yasm_intnum_size_leb128(const yasm_intnum *intn, int sign)
+{
+ wordptr val;
+
+ /* Shortcut 0 */
+ if (intn->type == INTNUM_L && intn->val.l == 0) {
+ return 1;
+ }
+
+ /* If not already a bitvect, convert value to a bitvect */
+ val = intnum_tobv(op1static, intn);
+
+ return size_leb128(val, sign);
+}
+
+unsigned long
+yasm_get_sleb128(long v, unsigned char *ptr)
+{
+ wordptr val = op1static;
+
+ /* Shortcut 0 */
+ if (v == 0) {
+ *ptr = 0;
+ return 1;
+ }
+
+ BitVector_Empty(val);
+ if (v >= 0)
+ BitVector_Chunk_Store(val, 32, 0, (unsigned long)v);
+ else {
+ BitVector_Chunk_Store(val, 32, 0, (unsigned long)(-v));
+ BitVector_Negate(val, val);
+ }
+ return get_leb128(val, ptr, 1);
+}
+
+unsigned long
+yasm_size_sleb128(long v)
+{
+ wordptr val = op1static;
+
+ if (v == 0)
+ return 1;
+
+ BitVector_Empty(val);
+ if (v >= 0)
+ BitVector_Chunk_Store(val, 32, 0, (unsigned long)v);
+ else {
+ BitVector_Chunk_Store(val, 32, 0, (unsigned long)(-v));
+ BitVector_Negate(val, val);
+ }
+ return size_leb128(val, 1);
+}
+
+unsigned long
+yasm_get_uleb128(unsigned long v, unsigned char *ptr)
+{
+ wordptr val = op1static;
+
+ /* Shortcut 0 */
+ if (v == 0) {
+ *ptr = 0;
+ return 1;
+ }
+
+ BitVector_Empty(val);
+ BitVector_Chunk_Store(val, 32, 0, v);
+ return get_leb128(val, ptr, 0);
+}
+
+unsigned long
+yasm_size_uleb128(unsigned long v)
+{
+ wordptr val = op1static;
+
+ if (v == 0)
+ return 1;
+
+ BitVector_Empty(val);
+ BitVector_Chunk_Store(val, 32, 0, v);
+ return size_leb128(val, 0);
+}
+
+char *
+yasm_intnum_get_str(const yasm_intnum *intn)
+{
+ unsigned char *s;
+
+ switch (intn->type) {
+ case INTNUM_L:
+ s = yasm_xmalloc(16);
+ sprintf((char *)s, "%ld", intn->val.l);
+ 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 char *s;
+
+ switch (intn->type) {
+ case INTNUM_L:
+ fprintf(f, "0x%lx", intn->val.l);
+ break;
+ case INTNUM_BV:
+ s = BitVector_to_Hex(intn->val.bv);
+ fprintf(f, "0x%s", (char *)s);
+ yasm_xfree(s);
+ break;
+ }
+}
diff --git a/contrib/tools/yasm/libyasm/intnum.h b/contrib/tools/yasm/libyasm/intnum.h
index bec832cf31..b035fc451b 100644
--- a/contrib/tools/yasm/libyasm/intnum.h
+++ b/contrib/tools/yasm/libyasm/intnum.h
@@ -1,340 +1,340 @@
-/**
- * \file libyasm/intnum.h
- * \brief YASM integer number interface.
- *
- * \license
- * Copyright (C) 2001-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- * \endlicense
- */
-#ifndef YASM_INTNUM_H
-#define YASM_INTNUM_H
-
-#ifndef YASM_LIB_DECL
-#define YASM_LIB_DECL
-#endif
-
-/** Initialize intnum internal data structures. */
-YASM_LIB_DECL
-void yasm_intnum_initialize(void);
-
-/** Clean up internal intnum allocations. */
-YASM_LIB_DECL
-void yasm_intnum_cleanup(void);
-
-/** Create a new intnum from a decimal string.
- * \param str decimal string
- * \return Newly allocated intnum.
- */
-YASM_LIB_DECL
-/*@only@*/ yasm_intnum *yasm_intnum_create_dec(char *str);
-
-/** Create a new intnum from a binary string.
- * \param str binary string
- * \return Newly allocated intnum.
- */
-YASM_LIB_DECL
-/*@only@*/ yasm_intnum *yasm_intnum_create_bin(char *str);
-
-/** Create a new intnum from an octal string.
- * \param str octal string
- * \return Newly allocated intnum.
- */
-YASM_LIB_DECL
-/*@only@*/ yasm_intnum *yasm_intnum_create_oct(char *str);
-
-/** Create a new intnum from a hexidecimal string.
- * \param str hexidecimal string
- * \return Newly allocated intnum.
- */
-YASM_LIB_DECL
-/*@only@*/ yasm_intnum *yasm_intnum_create_hex(char *str);
-
-/** Convert character constant to integer value, using NASM rules. NASM syntax
- * supports automatic conversion from strings such as 'abcd' to a 32-bit
- * integer value (little endian order). This function performs those conversions.
- * \param str character constant string
- * \return Newly allocated intnum.
- */
-YASM_LIB_DECL
-/*@only@*/ yasm_intnum *yasm_intnum_create_charconst_nasm(const char *str);
-
-/** Convert character constant to integer value, using TASM rules. TASM syntax
- * supports automatic conversion from strings such as 'abcd' to a 32-bit
- * integer value (big endian order). This function performs those conversions.
- * \param str character constant string
- * \return Newly allocated intnum.
- */
-YASM_LIB_DECL
-/*@only@*/ yasm_intnum *yasm_intnum_create_charconst_tasm(const char *str);
-
-/** Create a new intnum from an unsigned integer value.
- * \param i unsigned integer value
- * \return Newly allocated intnum.
- */
-YASM_LIB_DECL
-/*@only@*/ yasm_intnum *yasm_intnum_create_uint(unsigned long i);
-
-/** Create a new intnum from an signed integer value.
- * \param i signed integer value
- * \return Newly allocated intnum.
- */
-YASM_LIB_DECL
-/*@only@*/ yasm_intnum *yasm_intnum_create_int(long i);
-
-/** Create a new intnum from LEB128-encoded form.
- * \param ptr pointer to start of LEB128 encoded form
- * \param sign signed (1) or unsigned (0) LEB128 format
- * \param size number of bytes read from ptr (output)
- * \return Newly allocated intnum. Number of bytes read returned into
- * bytes_read parameter.
- */
-YASM_LIB_DECL
-/*@only@*/ yasm_intnum *yasm_intnum_create_leb128
- (const unsigned char *ptr, int sign, /*@out@*/ unsigned long *size);
-
-/** Create a new intnum from a little-endian or big-endian buffer.
- * In little endian, the LSB is in ptr[0].
- * \param ptr pointer to start of buffer
- * \param sign signed (1) or unsigned (0) source
- * \param srcsize source buffer size (in bytes)
- * \param bigendian endianness (nonzero=big, zero=little)
- */
-YASM_LIB_DECL
-/*@only@*/ yasm_intnum *yasm_intnum_create_sized
- (unsigned char *ptr, int sign, size_t srcsize, int bigendian);
-
-/** Duplicate an intnum.
- * \param intn intnum
- * \return Newly allocated intnum with the same value as intn.
- */
-YASM_LIB_DECL
-/*@only@*/ yasm_intnum *yasm_intnum_copy(const yasm_intnum *intn);
-
-/** Destroy (free allocated memory for) an intnum.
- * \param intn intnum
- */
-YASM_LIB_DECL
-void yasm_intnum_destroy(/*@only@*/ yasm_intnum *intn);
-
-/** Floating point calculation function: acc = acc op operand.
- * \note Not all operations in yasm_expr_op may be supported; unsupported
- * operations will result in an error.
- * \param acc intnum accumulator
- * \param op operation
- * \param operand intnum operand
- * \return Nonzero if error occurred.
- */
-YASM_LIB_DECL
-int yasm_intnum_calc(yasm_intnum *acc, yasm_expr_op op, yasm_intnum *operand);
-
-/** Compare two intnums.
- * \param intn1 first intnum
- * \param intn2 second intnum
- * \return -1 if intn1 < intn2, 0 if intn1 == intn2, 1 if intn1 > intn2.
- */
-YASM_LIB_DECL
-int yasm_intnum_compare(const yasm_intnum *intn1, const yasm_intnum *intn2);
-
-/** Zero an intnum.
- * \param intn intnum
- */
-YASM_LIB_DECL
-void yasm_intnum_zero(yasm_intnum *intn);
-
-/** Set an intnum to the value of another intnum.
- * \param intn intnum
- * \param val intnum to get value from
- */
-YASM_LIB_DECL
-void yasm_intnum_set(yasm_intnum *intn, const yasm_intnum *val);
-
-/** Set an intnum to an unsigned integer.
- * \param intn intnum
- * \param val integer value
- */
-YASM_LIB_DECL
-void yasm_intnum_set_uint(yasm_intnum *intn, unsigned long val);
-
-/** Set an intnum to an signed integer.
- * \param intn intnum
- * \param val integer value
- */
-YASM_LIB_DECL
-void yasm_intnum_set_int(yasm_intnum *intn, long val);
-
-/** Simple value check for 0.
- * \param acc intnum
- * \return Nonzero if acc==0.
- */
-YASM_LIB_DECL
-int yasm_intnum_is_zero(const yasm_intnum *acc);
-
-/** Simple value check for 1.
- * \param acc intnum
- * \return Nonzero if acc==1.
- */
-YASM_LIB_DECL
-int yasm_intnum_is_pos1(const yasm_intnum *acc);
-
-/** Simple value check for -1.
- * \param acc intnum
- * \return Nonzero if acc==-1.
- */
-YASM_LIB_DECL
-int yasm_intnum_is_neg1(const yasm_intnum *acc);
-
-/** Simple sign check.
- * \param acc intnum
- * \return -1 if negative, 0 if zero, +1 if positive
- */
-YASM_LIB_DECL
-int yasm_intnum_sign(const yasm_intnum *acc);
-
-/** Convert an intnum to an unsigned 32-bit value. The value is in "standard"
- * C format (eg, of unknown endian).
- * \note Parameter intnum is truncated to fit into 32 bits. Use
- * intnum_check_size() to check for overflow.
- * \param intn intnum
- * \return Unsigned 32-bit value of intn.
- */
-YASM_LIB_DECL
-unsigned long yasm_intnum_get_uint(const yasm_intnum *intn);
-
-/** Convert an intnum to a signed 32-bit value. The value is in "standard" C
- * format (eg, of unknown endian).
- * \note Parameter intnum is truncated to fit into 32 bits. Use
- * intnum_check_size() to check for overflow.
- * \param intn intnum
- * \return Signed 32-bit value of intn.
- */
-YASM_LIB_DECL
-long yasm_intnum_get_int(const yasm_intnum *intn);
-
-/** Output #yasm_intnum to buffer in little-endian or big-endian. Puts the
- * value into the least significant bits of the destination, or may be shifted
- * into more significant bits by the shift parameter. The destination bits are
- * cleared before being set. [0] should be the first byte output to the file.
- * \param intn intnum
- * \param ptr pointer to storage for size bytes of output
- * \param destsize destination size (in bytes)
- * \param valsize size (in bits)
- * \param shift left shift (in bits); may be negative to specify right
- * shift (standard warnings include truncation to boundary)
- * \param bigendian endianness (nonzero=big, zero=little)
- * \param warn enables standard warnings (value doesn't fit into valsize
- * bits): <0=signed warnings, >0=unsigned warnings, 0=no warn
- */
-YASM_LIB_DECL
-void yasm_intnum_get_sized(const yasm_intnum *intn, unsigned char *ptr,
- size_t destsize, size_t valsize, int shift,
- int bigendian, int warn);
-
-/** Check to see if intnum will fit without overflow into size bits.
- * \param intn intnum
- * \param size number of bits of output space
- * \param rshift right shift
- * \param rangetype signed/unsigned range selection:
- * 0 => (0, unsigned max);
- * 1 => (signed min, signed max);
- * 2 => (signed min, unsigned max)
- * \return Nonzero if intnum will fit.
- */
-YASM_LIB_DECL
-int yasm_intnum_check_size(const yasm_intnum *intn, size_t size,
- size_t rshift, int rangetype);
-
-/** Check to see if intnum will fit into a particular numeric range.
- * \param intn intnum
- * \param low low end of range (inclusive)
- * \param high high end of range (inclusive)
- * \return Nonzero if intnum is within range.
- */
-YASM_LIB_DECL
-int yasm_intnum_in_range(const yasm_intnum *intn, long low, long high);
-
-/** Output #yasm_intnum to buffer in LEB128-encoded form.
- * \param intn intnum
- * \param ptr pointer to storage for output bytes
- * \param sign signedness of LEB128 encoding (0=unsigned, 1=signed)
- * \return Number of bytes generated.
- */
-YASM_LIB_DECL
-unsigned long yasm_intnum_get_leb128(const yasm_intnum *intn,
- unsigned char *ptr, int sign);
-
-/** Calculate number of bytes LEB128-encoded form of #yasm_intnum will take.
- * \param intn intnum
- * \param sign signedness of LEB128 encoding (0=unsigned, 1=signed)
- * \return Number of bytes.
- */
-YASM_LIB_DECL
-unsigned long yasm_intnum_size_leb128(const yasm_intnum *intn, int sign);
-
-/** Output integer to buffer in signed LEB128-encoded form.
- * \param v integer
- * \param ptr pointer to storage for output bytes
- * \return Number of bytes generated.
- */
-YASM_LIB_DECL
-unsigned long yasm_get_sleb128(long v, unsigned char *ptr);
-
-/** Calculate number of bytes signed LEB128-encoded form of integer will take.
- * \param v integer
- * \return Number of bytes.
- */
-YASM_LIB_DECL
-unsigned long yasm_size_sleb128(long v);
-
-/** Output integer to buffer in unsigned LEB128-encoded form.
- * \param v integer
- * \param ptr pointer to storage for output bytes
- * \return Number of bytes generated.
- */
-YASM_LIB_DECL
-unsigned long yasm_get_uleb128(unsigned long v, unsigned char *ptr);
-
-/** Calculate number of bytes unsigned LEB128-encoded form of integer will take.
- * \param v integer
- * \return Number of bytes.
- */
-YASM_LIB_DECL
-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.
- */
-YASM_LIB_DECL
-/*@only@*/ char *yasm_intnum_get_str(const yasm_intnum *intn);
-
-/** Print an intnum. For debugging purposes.
- * \param f file
- * \param intn intnum
- */
-YASM_LIB_DECL
-void yasm_intnum_print(const yasm_intnum *intn, FILE *f);
-
-#endif
+/**
+ * \file libyasm/intnum.h
+ * \brief YASM integer number interface.
+ *
+ * \license
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * \endlicense
+ */
+#ifndef YASM_INTNUM_H
+#define YASM_INTNUM_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/** Initialize intnum internal data structures. */
+YASM_LIB_DECL
+void yasm_intnum_initialize(void);
+
+/** Clean up internal intnum allocations. */
+YASM_LIB_DECL
+void yasm_intnum_cleanup(void);
+
+/** Create a new intnum from a decimal string.
+ * \param str decimal string
+ * \return Newly allocated intnum.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_intnum *yasm_intnum_create_dec(char *str);
+
+/** Create a new intnum from a binary string.
+ * \param str binary string
+ * \return Newly allocated intnum.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_intnum *yasm_intnum_create_bin(char *str);
+
+/** Create a new intnum from an octal string.
+ * \param str octal string
+ * \return Newly allocated intnum.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_intnum *yasm_intnum_create_oct(char *str);
+
+/** Create a new intnum from a hexidecimal string.
+ * \param str hexidecimal string
+ * \return Newly allocated intnum.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_intnum *yasm_intnum_create_hex(char *str);
+
+/** Convert character constant to integer value, using NASM rules. NASM syntax
+ * supports automatic conversion from strings such as 'abcd' to a 32-bit
+ * integer value (little endian order). This function performs those conversions.
+ * \param str character constant string
+ * \return Newly allocated intnum.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_intnum *yasm_intnum_create_charconst_nasm(const char *str);
+
+/** Convert character constant to integer value, using TASM rules. TASM syntax
+ * supports automatic conversion from strings such as 'abcd' to a 32-bit
+ * integer value (big endian order). This function performs those conversions.
+ * \param str character constant string
+ * \return Newly allocated intnum.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_intnum *yasm_intnum_create_charconst_tasm(const char *str);
+
+/** Create a new intnum from an unsigned integer value.
+ * \param i unsigned integer value
+ * \return Newly allocated intnum.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_intnum *yasm_intnum_create_uint(unsigned long i);
+
+/** Create a new intnum from an signed integer value.
+ * \param i signed integer value
+ * \return Newly allocated intnum.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_intnum *yasm_intnum_create_int(long i);
+
+/** Create a new intnum from LEB128-encoded form.
+ * \param ptr pointer to start of LEB128 encoded form
+ * \param sign signed (1) or unsigned (0) LEB128 format
+ * \param size number of bytes read from ptr (output)
+ * \return Newly allocated intnum. Number of bytes read returned into
+ * bytes_read parameter.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_intnum *yasm_intnum_create_leb128
+ (const unsigned char *ptr, int sign, /*@out@*/ unsigned long *size);
+
+/** Create a new intnum from a little-endian or big-endian buffer.
+ * In little endian, the LSB is in ptr[0].
+ * \param ptr pointer to start of buffer
+ * \param sign signed (1) or unsigned (0) source
+ * \param srcsize source buffer size (in bytes)
+ * \param bigendian endianness (nonzero=big, zero=little)
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_intnum *yasm_intnum_create_sized
+ (unsigned char *ptr, int sign, size_t srcsize, int bigendian);
+
+/** Duplicate an intnum.
+ * \param intn intnum
+ * \return Newly allocated intnum with the same value as intn.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_intnum *yasm_intnum_copy(const yasm_intnum *intn);
+
+/** Destroy (free allocated memory for) an intnum.
+ * \param intn intnum
+ */
+YASM_LIB_DECL
+void yasm_intnum_destroy(/*@only@*/ yasm_intnum *intn);
+
+/** Floating point calculation function: acc = acc op operand.
+ * \note Not all operations in yasm_expr_op may be supported; unsupported
+ * operations will result in an error.
+ * \param acc intnum accumulator
+ * \param op operation
+ * \param operand intnum operand
+ * \return Nonzero if error occurred.
+ */
+YASM_LIB_DECL
+int yasm_intnum_calc(yasm_intnum *acc, yasm_expr_op op, yasm_intnum *operand);
+
+/** Compare two intnums.
+ * \param intn1 first intnum
+ * \param intn2 second intnum
+ * \return -1 if intn1 < intn2, 0 if intn1 == intn2, 1 if intn1 > intn2.
+ */
+YASM_LIB_DECL
+int yasm_intnum_compare(const yasm_intnum *intn1, const yasm_intnum *intn2);
+
+/** Zero an intnum.
+ * \param intn intnum
+ */
+YASM_LIB_DECL
+void yasm_intnum_zero(yasm_intnum *intn);
+
+/** Set an intnum to the value of another intnum.
+ * \param intn intnum
+ * \param val intnum to get value from
+ */
+YASM_LIB_DECL
+void yasm_intnum_set(yasm_intnum *intn, const yasm_intnum *val);
+
+/** Set an intnum to an unsigned integer.
+ * \param intn intnum
+ * \param val integer value
+ */
+YASM_LIB_DECL
+void yasm_intnum_set_uint(yasm_intnum *intn, unsigned long val);
+
+/** Set an intnum to an signed integer.
+ * \param intn intnum
+ * \param val integer value
+ */
+YASM_LIB_DECL
+void yasm_intnum_set_int(yasm_intnum *intn, long val);
+
+/** Simple value check for 0.
+ * \param acc intnum
+ * \return Nonzero if acc==0.
+ */
+YASM_LIB_DECL
+int yasm_intnum_is_zero(const yasm_intnum *acc);
+
+/** Simple value check for 1.
+ * \param acc intnum
+ * \return Nonzero if acc==1.
+ */
+YASM_LIB_DECL
+int yasm_intnum_is_pos1(const yasm_intnum *acc);
+
+/** Simple value check for -1.
+ * \param acc intnum
+ * \return Nonzero if acc==-1.
+ */
+YASM_LIB_DECL
+int yasm_intnum_is_neg1(const yasm_intnum *acc);
+
+/** Simple sign check.
+ * \param acc intnum
+ * \return -1 if negative, 0 if zero, +1 if positive
+ */
+YASM_LIB_DECL
+int yasm_intnum_sign(const yasm_intnum *acc);
+
+/** Convert an intnum to an unsigned 32-bit value. The value is in "standard"
+ * C format (eg, of unknown endian).
+ * \note Parameter intnum is truncated to fit into 32 bits. Use
+ * intnum_check_size() to check for overflow.
+ * \param intn intnum
+ * \return Unsigned 32-bit value of intn.
+ */
+YASM_LIB_DECL
+unsigned long yasm_intnum_get_uint(const yasm_intnum *intn);
+
+/** Convert an intnum to a signed 32-bit value. The value is in "standard" C
+ * format (eg, of unknown endian).
+ * \note Parameter intnum is truncated to fit into 32 bits. Use
+ * intnum_check_size() to check for overflow.
+ * \param intn intnum
+ * \return Signed 32-bit value of intn.
+ */
+YASM_LIB_DECL
+long yasm_intnum_get_int(const yasm_intnum *intn);
+
+/** Output #yasm_intnum to buffer in little-endian or big-endian. Puts the
+ * value into the least significant bits of the destination, or may be shifted
+ * into more significant bits by the shift parameter. The destination bits are
+ * cleared before being set. [0] should be the first byte output to the file.
+ * \param intn intnum
+ * \param ptr pointer to storage for size bytes of output
+ * \param destsize destination size (in bytes)
+ * \param valsize size (in bits)
+ * \param shift left shift (in bits); may be negative to specify right
+ * shift (standard warnings include truncation to boundary)
+ * \param bigendian endianness (nonzero=big, zero=little)
+ * \param warn enables standard warnings (value doesn't fit into valsize
+ * bits): <0=signed warnings, >0=unsigned warnings, 0=no warn
+ */
+YASM_LIB_DECL
+void yasm_intnum_get_sized(const yasm_intnum *intn, unsigned char *ptr,
+ size_t destsize, size_t valsize, int shift,
+ int bigendian, int warn);
+
+/** Check to see if intnum will fit without overflow into size bits.
+ * \param intn intnum
+ * \param size number of bits of output space
+ * \param rshift right shift
+ * \param rangetype signed/unsigned range selection:
+ * 0 => (0, unsigned max);
+ * 1 => (signed min, signed max);
+ * 2 => (signed min, unsigned max)
+ * \return Nonzero if intnum will fit.
+ */
+YASM_LIB_DECL
+int yasm_intnum_check_size(const yasm_intnum *intn, size_t size,
+ size_t rshift, int rangetype);
+
+/** Check to see if intnum will fit into a particular numeric range.
+ * \param intn intnum
+ * \param low low end of range (inclusive)
+ * \param high high end of range (inclusive)
+ * \return Nonzero if intnum is within range.
+ */
+YASM_LIB_DECL
+int yasm_intnum_in_range(const yasm_intnum *intn, long low, long high);
+
+/** Output #yasm_intnum to buffer in LEB128-encoded form.
+ * \param intn intnum
+ * \param ptr pointer to storage for output bytes
+ * \param sign signedness of LEB128 encoding (0=unsigned, 1=signed)
+ * \return Number of bytes generated.
+ */
+YASM_LIB_DECL
+unsigned long yasm_intnum_get_leb128(const yasm_intnum *intn,
+ unsigned char *ptr, int sign);
+
+/** Calculate number of bytes LEB128-encoded form of #yasm_intnum will take.
+ * \param intn intnum
+ * \param sign signedness of LEB128 encoding (0=unsigned, 1=signed)
+ * \return Number of bytes.
+ */
+YASM_LIB_DECL
+unsigned long yasm_intnum_size_leb128(const yasm_intnum *intn, int sign);
+
+/** Output integer to buffer in signed LEB128-encoded form.
+ * \param v integer
+ * \param ptr pointer to storage for output bytes
+ * \return Number of bytes generated.
+ */
+YASM_LIB_DECL
+unsigned long yasm_get_sleb128(long v, unsigned char *ptr);
+
+/** Calculate number of bytes signed LEB128-encoded form of integer will take.
+ * \param v integer
+ * \return Number of bytes.
+ */
+YASM_LIB_DECL
+unsigned long yasm_size_sleb128(long v);
+
+/** Output integer to buffer in unsigned LEB128-encoded form.
+ * \param v integer
+ * \param ptr pointer to storage for output bytes
+ * \return Number of bytes generated.
+ */
+YASM_LIB_DECL
+unsigned long yasm_get_uleb128(unsigned long v, unsigned char *ptr);
+
+/** Calculate number of bytes unsigned LEB128-encoded form of integer will take.
+ * \param v integer
+ * \return Number of bytes.
+ */
+YASM_LIB_DECL
+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.
+ */
+YASM_LIB_DECL
+/*@only@*/ char *yasm_intnum_get_str(const yasm_intnum *intn);
+
+/** Print an intnum. For debugging purposes.
+ * \param f file
+ * \param intn intnum
+ */
+YASM_LIB_DECL
+void yasm_intnum_print(const yasm_intnum *intn, FILE *f);
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/inttree.c b/contrib/tools/yasm/libyasm/inttree.c
index 2ae10e9b9c..1c21b3ce02 100644
--- a/contrib/tools/yasm/libyasm/inttree.c
+++ b/contrib/tools/yasm/libyasm/inttree.c
@@ -1,891 +1,891 @@
-#include "util.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <limits.h>
-#include <math.h>
-#include "coretype.h"
-#include "inttree.h"
-
-#define VERIFY(condition) \
-if (!(condition)) { \
-fprintf(stderr, "Assumption \"%s\"\nFailed in file %s: at line:%i\n", \
-#condition,__FILE__,__LINE__); \
-abort();}
-
-/*#define DEBUG_ASSERT 1*/
-
-#ifdef DEBUG_ASSERT
-static void Assert(int assertion, const char *error)
-{
- if (!assertion) {
- fprintf(stderr, "Assertion Failed: %s\n", error);
- abort();
- }
-}
-#endif
-
-/* If the symbol CHECK_INTERVAL_TREE_ASSUMPTIONS is defined then the
- * code does a lot of extra checking to make sure certain assumptions
- * are satisfied. This only needs to be done if you suspect bugs are
- * present or if you make significant changes and want to make sure
- * your changes didn't mess anything up.
- */
-/*#define CHECK_INTERVAL_TREE_ASSUMPTIONS 1*/
-
-static IntervalTreeNode *ITN_create(long low, long high, void *data);
-
-static void LeftRotate(IntervalTree *, IntervalTreeNode *);
-static void RightRotate(IntervalTree *, IntervalTreeNode *);
-static void TreeInsertHelp(IntervalTree *, IntervalTreeNode *);
-static void TreePrintHelper(const IntervalTree *, IntervalTreeNode *);
-static void FixUpMaxHigh(IntervalTree *, IntervalTreeNode *);
-static void DeleteFixUp(IntervalTree *, IntervalTreeNode *);
-#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
-static void CheckMaxHighFields(const IntervalTree *, IntervalTreeNode *);
-static int CheckMaxHighFieldsHelper(const IntervalTree *, IntervalTreeNode *y,
- const int currentHigh, int match);
-static void IT_CheckAssumptions(const IntervalTree *);
-#endif
-
-/* define a function to find the maximum of two objects. */
-#define ITMax(a, b) ( (a > b) ? a : b )
-
-IntervalTreeNode *
-ITN_create(long low, long high, void *data)
-{
- IntervalTreeNode *itn = yasm_xmalloc(sizeof(IntervalTreeNode));
- itn->data = data;
- if (low < high) {
- itn->low = low;
- itn->high = high;
- } else {
- itn->low = high;
- itn->high = low;
- }
- itn->maxHigh = high;
- return itn;
-}
-
-IntervalTree *
-IT_create(void)
-{
- IntervalTree *it = yasm_xmalloc(sizeof(IntervalTree));
-
- it->nil = ITN_create(LONG_MIN, LONG_MIN, NULL);
- it->nil->left = it->nil;
- it->nil->right = it->nil;
- it->nil->parent = it->nil;
- it->nil->red = 0;
-
- it->root = ITN_create(LONG_MAX, LONG_MAX, NULL);
- it->root->left = it->nil;
- it->root->right = it->nil;
- it->root->parent = it->nil;
- it->root->red = 0;
-
- /* the following are used for the Enumerate function */
- it->recursionNodeStackSize = 128;
- it->recursionNodeStack = (it_recursion_node *)
- yasm_xmalloc(it->recursionNodeStackSize*sizeof(it_recursion_node));
- it->recursionNodeStackTop = 1;
- it->recursionNodeStack[0].start_node = NULL;
-
- return it;
-}
-
-/***********************************************************************/
-/* FUNCTION: LeftRotate */
-/**/
-/* INPUTS: the node to rotate on */
-/**/
-/* OUTPUT: None */
-/**/
-/* Modifies Input: this, x */
-/**/
-/* EFFECTS: Rotates as described in _Introduction_To_Algorithms by */
-/* Cormen, Leiserson, Rivest (Chapter 14). Basically this */
-/* makes the parent of x be to the left of x, x the parent of */
-/* its parent before the rotation and fixes other pointers */
-/* accordingly. Also updates the maxHigh fields of x and y */
-/* after rotation. */
-/***********************************************************************/
-
-static void
-LeftRotate(IntervalTree *it, IntervalTreeNode *x)
-{
- IntervalTreeNode *y;
-
- /* I originally wrote this function to use the sentinel for
- * nil to avoid checking for nil. However this introduces a
- * very subtle bug because sometimes this function modifies
- * the parent pointer of nil. This can be a problem if a
- * function which calls LeftRotate also uses the nil sentinel
- * and expects the nil sentinel's parent pointer to be unchanged
- * after calling this function. For example, when DeleteFixUP
- * calls LeftRotate it expects the parent pointer of nil to be
- * unchanged.
- */
-
- y=x->right;
- x->right=y->left;
-
- if (y->left != it->nil)
- y->left->parent=x; /* used to use sentinel here */
- /* and do an unconditional assignment instead of testing for nil */
+#include "util.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+#include <math.h>
+#include "coretype.h"
+#include "inttree.h"
+
+#define VERIFY(condition) \
+if (!(condition)) { \
+fprintf(stderr, "Assumption \"%s\"\nFailed in file %s: at line:%i\n", \
+#condition,__FILE__,__LINE__); \
+abort();}
+
+/*#define DEBUG_ASSERT 1*/
+
+#ifdef DEBUG_ASSERT
+static void Assert(int assertion, const char *error)
+{
+ if (!assertion) {
+ fprintf(stderr, "Assertion Failed: %s\n", error);
+ abort();
+ }
+}
+#endif
+
+/* If the symbol CHECK_INTERVAL_TREE_ASSUMPTIONS is defined then the
+ * code does a lot of extra checking to make sure certain assumptions
+ * are satisfied. This only needs to be done if you suspect bugs are
+ * present or if you make significant changes and want to make sure
+ * your changes didn't mess anything up.
+ */
+/*#define CHECK_INTERVAL_TREE_ASSUMPTIONS 1*/
+
+static IntervalTreeNode *ITN_create(long low, long high, void *data);
+
+static void LeftRotate(IntervalTree *, IntervalTreeNode *);
+static void RightRotate(IntervalTree *, IntervalTreeNode *);
+static void TreeInsertHelp(IntervalTree *, IntervalTreeNode *);
+static void TreePrintHelper(const IntervalTree *, IntervalTreeNode *);
+static void FixUpMaxHigh(IntervalTree *, IntervalTreeNode *);
+static void DeleteFixUp(IntervalTree *, IntervalTreeNode *);
+#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
+static void CheckMaxHighFields(const IntervalTree *, IntervalTreeNode *);
+static int CheckMaxHighFieldsHelper(const IntervalTree *, IntervalTreeNode *y,
+ const int currentHigh, int match);
+static void IT_CheckAssumptions(const IntervalTree *);
+#endif
+
+/* define a function to find the maximum of two objects. */
+#define ITMax(a, b) ( (a > b) ? a : b )
+
+IntervalTreeNode *
+ITN_create(long low, long high, void *data)
+{
+ IntervalTreeNode *itn = yasm_xmalloc(sizeof(IntervalTreeNode));
+ itn->data = data;
+ if (low < high) {
+ itn->low = low;
+ itn->high = high;
+ } else {
+ itn->low = high;
+ itn->high = low;
+ }
+ itn->maxHigh = high;
+ return itn;
+}
+
+IntervalTree *
+IT_create(void)
+{
+ IntervalTree *it = yasm_xmalloc(sizeof(IntervalTree));
+
+ it->nil = ITN_create(LONG_MIN, LONG_MIN, NULL);
+ it->nil->left = it->nil;
+ it->nil->right = it->nil;
+ it->nil->parent = it->nil;
+ it->nil->red = 0;
+
+ it->root = ITN_create(LONG_MAX, LONG_MAX, NULL);
+ it->root->left = it->nil;
+ it->root->right = it->nil;
+ it->root->parent = it->nil;
+ it->root->red = 0;
+
+ /* the following are used for the Enumerate function */
+ it->recursionNodeStackSize = 128;
+ it->recursionNodeStack = (it_recursion_node *)
+ yasm_xmalloc(it->recursionNodeStackSize*sizeof(it_recursion_node));
+ it->recursionNodeStackTop = 1;
+ it->recursionNodeStack[0].start_node = NULL;
+
+ return it;
+}
+
+/***********************************************************************/
+/* FUNCTION: LeftRotate */
+/**/
+/* INPUTS: the node to rotate on */
+/**/
+/* OUTPUT: None */
+/**/
+/* Modifies Input: this, x */
+/**/
+/* EFFECTS: Rotates as described in _Introduction_To_Algorithms by */
+/* Cormen, Leiserson, Rivest (Chapter 14). Basically this */
+/* makes the parent of x be to the left of x, x the parent of */
+/* its parent before the rotation and fixes other pointers */
+/* accordingly. Also updates the maxHigh fields of x and y */
+/* after rotation. */
+/***********************************************************************/
+
+static void
+LeftRotate(IntervalTree *it, IntervalTreeNode *x)
+{
+ IntervalTreeNode *y;
- y->parent=x->parent;
-
- /* Instead of checking if x->parent is the root as in the book, we
- * count on the root sentinel to implicitly take care of this case
- */
- if (x == x->parent->left)
- x->parent->left=y;
- else
- x->parent->right=y;
- y->left=x;
- x->parent=y;
-
- x->maxHigh=ITMax(x->left->maxHigh,ITMax(x->right->maxHigh,x->high));
- y->maxHigh=ITMax(x->maxHigh,ITMax(y->right->maxHigh,y->high));
-#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
- IT_CheckAssumptions(it);
-#elif defined(DEBUG_ASSERT)
- Assert(!it->nil->red,"nil not red in ITLeftRotate");
- Assert((it->nil->maxHigh=LONG_MIN),
- "nil->maxHigh != LONG_MIN in ITLeftRotate");
-#endif
-}
-
-
-/***********************************************************************/
-/* FUNCTION: RightRotate */
-/**/
-/* INPUTS: node to rotate on */
-/**/
-/* OUTPUT: None */
-/**/
-/* Modifies Input?: this, y */
-/**/
-/* EFFECTS: Rotates as described in _Introduction_To_Algorithms by */
-/* Cormen, Leiserson, Rivest (Chapter 14). Basically this */
-/* makes the parent of x be to the left of x, x the parent of */
-/* its parent before the rotation and fixes other pointers */
-/* accordingly. Also updates the maxHigh fields of x and y */
-/* after rotation. */
-/***********************************************************************/
-
-
-static void
-RightRotate(IntervalTree *it, IntervalTreeNode *y)
-{
- IntervalTreeNode *x;
-
- /* I originally wrote this function to use the sentinel for
- * nil to avoid checking for nil. However this introduces a
- * very subtle bug because sometimes this function modifies
- * the parent pointer of nil. This can be a problem if a
- * function which calls LeftRotate also uses the nil sentinel
- * and expects the nil sentinel's parent pointer to be unchanged
- * after calling this function. For example, when DeleteFixUP
- * calls LeftRotate it expects the parent pointer of nil to be
- * unchanged.
- */
-
- x=y->left;
- y->left=x->right;
-
- if (it->nil != x->right)
- x->right->parent=y; /*used to use sentinel here */
- /* and do an unconditional assignment instead of testing for nil */
-
- /* Instead of checking if x->parent is the root as in the book, we
- * count on the root sentinel to implicitly take care of this case
- */
- x->parent=y->parent;
- if (y == y->parent->left)
- y->parent->left=x;
- else
- y->parent->right=x;
- x->right=y;
- y->parent=x;
-
- y->maxHigh=ITMax(y->left->maxHigh,ITMax(y->right->maxHigh,y->high));
- x->maxHigh=ITMax(x->left->maxHigh,ITMax(y->maxHigh,x->high));
-#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
- IT_CheckAssumptions(it);
-#elif defined(DEBUG_ASSERT)
- Assert(!it->nil->red,"nil not red in ITRightRotate");
- Assert((it->nil->maxHigh=LONG_MIN),
- "nil->maxHigh != LONG_MIN in ITRightRotate");
-#endif
-}
-
-/***********************************************************************/
-/* FUNCTION: TreeInsertHelp */
-/**/
-/* INPUTS: z is the node to insert */
-/**/
-/* OUTPUT: none */
-/**/
-/* Modifies Input: this, z */
-/**/
-/* EFFECTS: Inserts z into the tree as if it were a regular binary tree */
-/* using the algorithm described in _Introduction_To_Algorithms_ */
-/* by Cormen et al. This funciton is only intended to be called */
-/* by the InsertTree function and not by the user */
-/***********************************************************************/
-
-static void
-TreeInsertHelp(IntervalTree *it, IntervalTreeNode *z)
-{
- /* This function should only be called by InsertITTree (see above) */
- IntervalTreeNode* x;
- IntervalTreeNode* y;
-
- z->left=z->right=it->nil;
- y=it->root;
- x=it->root->left;
- while( x != it->nil) {
- y=x;
- if (x->low > z->low)
- x=x->left;
- else /* x->low <= z->low */
- x=x->right;
- }
- z->parent=y;
- if ((y == it->root) || (y->low > z->low))
- y->left=z;
- else
- y->right=z;
-
-#if defined(DEBUG_ASSERT)
- Assert(!it->nil->red,"nil not red in ITTreeInsertHelp");
- Assert((it->nil->maxHigh=INT_MIN),
- "nil->maxHigh != INT_MIN in ITTreeInsertHelp");
-#endif
-}
-
-
-/***********************************************************************/
-/* FUNCTION: FixUpMaxHigh */
-/**/
-/* INPUTS: x is the node to start from*/
-/**/
-/* OUTPUT: none */
-/**/
-/* Modifies Input: this */
-/**/
-/* EFFECTS: Travels up to the root fixing the maxHigh fields after */
-/* an insertion or deletion */
-/***********************************************************************/
-
-static void
-FixUpMaxHigh(IntervalTree *it, IntervalTreeNode *x)
-{
- while(x != it->root) {
- x->maxHigh=ITMax(x->high,ITMax(x->left->maxHigh,x->right->maxHigh));
- x=x->parent;
- }
-#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
- IT_CheckAssumptions(it);
-#endif
-}
-
-/* Before calling InsertNode the node x should have its key set */
-
-/***********************************************************************/
-/* FUNCTION: InsertNode */
-/**/
-/* INPUTS: newInterval is the interval to insert*/
-/**/
-/* OUTPUT: This function returns a pointer to the newly inserted node */
-/* which is guarunteed to be valid until this node is deleted. */
-/* What this means is if another data structure stores this */
-/* pointer then the tree does not need to be searched when this */
-/* is to be deleted. */
-/**/
-/* Modifies Input: tree */
-/**/
-/* EFFECTS: Creates a node node which contains the appropriate key and */
-/* info pointers and inserts it into the tree. */
-/***********************************************************************/
-
-IntervalTreeNode *
-IT_insert(IntervalTree *it, long low, long high, void *data)
-{
- IntervalTreeNode *x, *y, *newNode;
-
- x = ITN_create(low, high, data);
- TreeInsertHelp(it, x);
- FixUpMaxHigh(it, x->parent);
- newNode = x;
- x->red=1;
- while(x->parent->red) { /* use sentinel instead of checking for root */
- if (x->parent == x->parent->parent->left) {
- y=x->parent->parent->right;
- if (y->red) {
- x->parent->red=0;
- y->red=0;
- x->parent->parent->red=1;
- x=x->parent->parent;
- } else {
- if (x == x->parent->right) {
- x=x->parent;
- LeftRotate(it, x);
- }
- x->parent->red=0;
- x->parent->parent->red=1;
- RightRotate(it, x->parent->parent);
+ /* I originally wrote this function to use the sentinel for
+ * nil to avoid checking for nil. However this introduces a
+ * very subtle bug because sometimes this function modifies
+ * the parent pointer of nil. This can be a problem if a
+ * function which calls LeftRotate also uses the nil sentinel
+ * and expects the nil sentinel's parent pointer to be unchanged
+ * after calling this function. For example, when DeleteFixUP
+ * calls LeftRotate it expects the parent pointer of nil to be
+ * unchanged.
+ */
+
+ y=x->right;
+ x->right=y->left;
+
+ if (y->left != it->nil)
+ y->left->parent=x; /* used to use sentinel here */
+ /* and do an unconditional assignment instead of testing for nil */
+
+ y->parent=x->parent;
+
+ /* Instead of checking if x->parent is the root as in the book, we
+ * count on the root sentinel to implicitly take care of this case
+ */
+ if (x == x->parent->left)
+ x->parent->left=y;
+ else
+ x->parent->right=y;
+ y->left=x;
+ x->parent=y;
+
+ x->maxHigh=ITMax(x->left->maxHigh,ITMax(x->right->maxHigh,x->high));
+ y->maxHigh=ITMax(x->maxHigh,ITMax(y->right->maxHigh,y->high));
+#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
+ IT_CheckAssumptions(it);
+#elif defined(DEBUG_ASSERT)
+ Assert(!it->nil->red,"nil not red in ITLeftRotate");
+ Assert((it->nil->maxHigh=LONG_MIN),
+ "nil->maxHigh != LONG_MIN in ITLeftRotate");
+#endif
+}
+
+
+/***********************************************************************/
+/* FUNCTION: RightRotate */
+/**/
+/* INPUTS: node to rotate on */
+/**/
+/* OUTPUT: None */
+/**/
+/* Modifies Input?: this, y */
+/**/
+/* EFFECTS: Rotates as described in _Introduction_To_Algorithms by */
+/* Cormen, Leiserson, Rivest (Chapter 14). Basically this */
+/* makes the parent of x be to the left of x, x the parent of */
+/* its parent before the rotation and fixes other pointers */
+/* accordingly. Also updates the maxHigh fields of x and y */
+/* after rotation. */
+/***********************************************************************/
+
+
+static void
+RightRotate(IntervalTree *it, IntervalTreeNode *y)
+{
+ IntervalTreeNode *x;
+
+ /* I originally wrote this function to use the sentinel for
+ * nil to avoid checking for nil. However this introduces a
+ * very subtle bug because sometimes this function modifies
+ * the parent pointer of nil. This can be a problem if a
+ * function which calls LeftRotate also uses the nil sentinel
+ * and expects the nil sentinel's parent pointer to be unchanged
+ * after calling this function. For example, when DeleteFixUP
+ * calls LeftRotate it expects the parent pointer of nil to be
+ * unchanged.
+ */
+
+ x=y->left;
+ y->left=x->right;
+
+ if (it->nil != x->right)
+ x->right->parent=y; /*used to use sentinel here */
+ /* and do an unconditional assignment instead of testing for nil */
+
+ /* Instead of checking if x->parent is the root as in the book, we
+ * count on the root sentinel to implicitly take care of this case
+ */
+ x->parent=y->parent;
+ if (y == y->parent->left)
+ y->parent->left=x;
+ else
+ y->parent->right=x;
+ x->right=y;
+ y->parent=x;
+
+ y->maxHigh=ITMax(y->left->maxHigh,ITMax(y->right->maxHigh,y->high));
+ x->maxHigh=ITMax(x->left->maxHigh,ITMax(y->maxHigh,x->high));
+#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
+ IT_CheckAssumptions(it);
+#elif defined(DEBUG_ASSERT)
+ Assert(!it->nil->red,"nil not red in ITRightRotate");
+ Assert((it->nil->maxHigh=LONG_MIN),
+ "nil->maxHigh != LONG_MIN in ITRightRotate");
+#endif
+}
+
+/***********************************************************************/
+/* FUNCTION: TreeInsertHelp */
+/**/
+/* INPUTS: z is the node to insert */
+/**/
+/* OUTPUT: none */
+/**/
+/* Modifies Input: this, z */
+/**/
+/* EFFECTS: Inserts z into the tree as if it were a regular binary tree */
+/* using the algorithm described in _Introduction_To_Algorithms_ */
+/* by Cormen et al. This funciton is only intended to be called */
+/* by the InsertTree function and not by the user */
+/***********************************************************************/
+
+static void
+TreeInsertHelp(IntervalTree *it, IntervalTreeNode *z)
+{
+ /* This function should only be called by InsertITTree (see above) */
+ IntervalTreeNode* x;
+ IntervalTreeNode* y;
+
+ z->left=z->right=it->nil;
+ y=it->root;
+ x=it->root->left;
+ while( x != it->nil) {
+ y=x;
+ if (x->low > z->low)
+ x=x->left;
+ else /* x->low <= z->low */
+ x=x->right;
+ }
+ z->parent=y;
+ if ((y == it->root) || (y->low > z->low))
+ y->left=z;
+ else
+ y->right=z;
+
+#if defined(DEBUG_ASSERT)
+ Assert(!it->nil->red,"nil not red in ITTreeInsertHelp");
+ Assert((it->nil->maxHigh=INT_MIN),
+ "nil->maxHigh != INT_MIN in ITTreeInsertHelp");
+#endif
+}
+
+
+/***********************************************************************/
+/* FUNCTION: FixUpMaxHigh */
+/**/
+/* INPUTS: x is the node to start from*/
+/**/
+/* OUTPUT: none */
+/**/
+/* Modifies Input: this */
+/**/
+/* EFFECTS: Travels up to the root fixing the maxHigh fields after */
+/* an insertion or deletion */
+/***********************************************************************/
+
+static void
+FixUpMaxHigh(IntervalTree *it, IntervalTreeNode *x)
+{
+ while(x != it->root) {
+ x->maxHigh=ITMax(x->high,ITMax(x->left->maxHigh,x->right->maxHigh));
+ x=x->parent;
+ }
+#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
+ IT_CheckAssumptions(it);
+#endif
+}
+
+/* Before calling InsertNode the node x should have its key set */
+
+/***********************************************************************/
+/* FUNCTION: InsertNode */
+/**/
+/* INPUTS: newInterval is the interval to insert*/
+/**/
+/* OUTPUT: This function returns a pointer to the newly inserted node */
+/* which is guarunteed to be valid until this node is deleted. */
+/* What this means is if another data structure stores this */
+/* pointer then the tree does not need to be searched when this */
+/* is to be deleted. */
+/**/
+/* Modifies Input: tree */
+/**/
+/* EFFECTS: Creates a node node which contains the appropriate key and */
+/* info pointers and inserts it into the tree. */
+/***********************************************************************/
+
+IntervalTreeNode *
+IT_insert(IntervalTree *it, long low, long high, void *data)
+{
+ IntervalTreeNode *x, *y, *newNode;
+
+ x = ITN_create(low, high, data);
+ TreeInsertHelp(it, x);
+ FixUpMaxHigh(it, x->parent);
+ newNode = x;
+ x->red=1;
+ while(x->parent->red) { /* use sentinel instead of checking for root */
+ if (x->parent == x->parent->parent->left) {
+ y=x->parent->parent->right;
+ if (y->red) {
+ x->parent->red=0;
+ y->red=0;
+ x->parent->parent->red=1;
+ x=x->parent->parent;
+ } else {
+ if (x == x->parent->right) {
+ x=x->parent;
+ LeftRotate(it, x);
+ }
+ x->parent->red=0;
+ x->parent->parent->red=1;
+ RightRotate(it, x->parent->parent);
+ }
+ } else { /* case for x->parent == x->parent->parent->right */
+ /* this part is just like the section above with */
+ /* left and right interchanged */
+ y=x->parent->parent->left;
+ if (y->red) {
+ x->parent->red=0;
+ y->red=0;
+ x->parent->parent->red=1;
+ x=x->parent->parent;
+ } else {
+ if (x == x->parent->left) {
+ x=x->parent;
+ RightRotate(it, x);
+ }
+ x->parent->red=0;
+ x->parent->parent->red=1;
+ LeftRotate(it, x->parent->parent);
+ }
+ }
+ }
+ it->root->left->red=0;
+
+#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
+ IT_CheckAssumptions(it);
+#elif defined(DEBUG_ASSERT)
+ Assert(!it->nil->red,"nil not red in ITTreeInsert");
+ Assert(!it->root->red,"root not red in ITTreeInsert");
+ Assert((it->nil->maxHigh=LONG_MIN),
+ "nil->maxHigh != LONG_MIN in ITTreeInsert");
+#endif
+ return newNode;
+}
+
+/***********************************************************************/
+/* FUNCTION: GetSuccessorOf */
+/**/
+/* INPUTS: x is the node we want the succesor of */
+/**/
+/* OUTPUT: This function returns the successor of x or NULL if no */
+/* successor exists. */
+/**/
+/* Modifies Input: none */
+/**/
+/* Note: uses the algorithm in _Introduction_To_Algorithms_ */
+/***********************************************************************/
+
+IntervalTreeNode *
+IT_get_successor(const IntervalTree *it, IntervalTreeNode *x)
+{
+ IntervalTreeNode *y;
+
+ if (it->nil != (y = x->right)) { /* assignment to y is intentional */
+ while(y->left != it->nil) /* returns the minium of the right subtree of x */
+ y=y->left;
+ return y;
+ } else {
+ y=x->parent;
+ while(x == y->right) { /* sentinel used instead of checking for nil */
+ x=y;
+ y=y->parent;
+ }
+ if (y == it->root)
+ return(it->nil);
+ return y;
+ }
+}
+
+/***********************************************************************/
+/* FUNCTION: GetPredecessorOf */
+/**/
+/* INPUTS: x is the node to get predecessor of */
+/**/
+/* OUTPUT: This function returns the predecessor of x or NULL if no */
+/* predecessor exists. */
+/**/
+/* Modifies Input: none */
+/**/
+/* Note: uses the algorithm in _Introduction_To_Algorithms_ */
+/***********************************************************************/
+
+IntervalTreeNode *
+IT_get_predecessor(const IntervalTree *it, IntervalTreeNode *x)
+{
+ IntervalTreeNode *y;
+
+ if (it->nil != (y = x->left)) { /* assignment to y is intentional */
+ while(y->right != it->nil) /* returns the maximum of the left subtree of x */
+ y=y->right;
+ return y;
+ } else {
+ y=x->parent;
+ while(x == y->left) {
+ if (y == it->root)
+ return(it->nil);
+ x=y;
+ y=y->parent;
+ }
+ return y;
+ }
+}
+
+/***********************************************************************/
+/* FUNCTION: Print */
+/**/
+/* INPUTS: none */
+/**/
+/* OUTPUT: none */
+/**/
+/* EFFECTS: This function recursively prints the nodes of the tree */
+/* inorder. */
+/**/
+/* Modifies Input: none */
+/**/
+/* Note: This function should only be called from ITTreePrint */
+/***********************************************************************/
+
+static void
+ITN_print(const IntervalTreeNode *itn, IntervalTreeNode *nil,
+ IntervalTreeNode *root)
+{
+ printf(", l=%li, h=%li, mH=%li", itn->low, itn->high, itn->maxHigh);
+ printf(" l->low=");
+ if (itn->left == nil)
+ printf("NULL");
+ else
+ printf("%li", itn->left->low);
+ printf(" r->low=");
+ if (itn->right == nil)
+ printf("NULL");
+ else
+ printf("%li", itn->right->low);
+ printf(" p->low=");
+ if (itn->parent == root)
+ printf("NULL");
+ else
+ printf("%li", itn->parent->low);
+ printf(" red=%i\n", itn->red);
+}
+
+static void
+TreePrintHelper(const IntervalTree *it, IntervalTreeNode *x)
+{
+ if (x != it->nil) {
+ TreePrintHelper(it, x->left);
+ ITN_print(x, it->nil, it->root);
+ TreePrintHelper(it, x->right);
+ }
+}
+
+void
+IT_destroy(IntervalTree *it)
+{
+ IntervalTreeNode *x = it->root->left;
+ SLIST_HEAD(node_head, nodeent)
+ stuffToFree = SLIST_HEAD_INITIALIZER(stuffToFree);
+ struct nodeent {
+ SLIST_ENTRY(nodeent) link;
+ struct IntervalTreeNode *node;
+ } *np;
+
+ if (x != it->nil) {
+ if (x->left != it->nil) {
+ np = yasm_xmalloc(sizeof(struct nodeent));
+ np->node = x->left;
+ SLIST_INSERT_HEAD(&stuffToFree, np, link);
+ }
+ if (x->right != it->nil) {
+ np = yasm_xmalloc(sizeof(struct nodeent));
+ np->node = x->right;
+ SLIST_INSERT_HEAD(&stuffToFree, np, link);
+ }
+ yasm_xfree(x);
+ while (!SLIST_EMPTY(&stuffToFree)) {
+ np = SLIST_FIRST(&stuffToFree);
+ x = np->node;
+ SLIST_REMOVE_HEAD(&stuffToFree, link);
+ yasm_xfree(np);
+
+ if (x->left != it->nil) {
+ np = yasm_xmalloc(sizeof(struct nodeent));
+ np->node = x->left;
+ SLIST_INSERT_HEAD(&stuffToFree, np, link);
}
- } else { /* case for x->parent == x->parent->parent->right */
- /* this part is just like the section above with */
- /* left and right interchanged */
- y=x->parent->parent->left;
- if (y->red) {
- x->parent->red=0;
- y->red=0;
- x->parent->parent->red=1;
- x=x->parent->parent;
- } else {
- if (x == x->parent->left) {
- x=x->parent;
- RightRotate(it, x);
- }
- x->parent->red=0;
- x->parent->parent->red=1;
- LeftRotate(it, x->parent->parent);
+ if (x->right != it->nil) {
+ np = yasm_xmalloc(sizeof(struct nodeent));
+ np->node = x->right;
+ SLIST_INSERT_HEAD(&stuffToFree, np, link);
}
- }
- }
- it->root->left->red=0;
-
-#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
- IT_CheckAssumptions(it);
-#elif defined(DEBUG_ASSERT)
- Assert(!it->nil->red,"nil not red in ITTreeInsert");
- Assert(!it->root->red,"root not red in ITTreeInsert");
- Assert((it->nil->maxHigh=LONG_MIN),
- "nil->maxHigh != LONG_MIN in ITTreeInsert");
-#endif
- return newNode;
-}
-
-/***********************************************************************/
-/* FUNCTION: GetSuccessorOf */
-/**/
-/* INPUTS: x is the node we want the succesor of */
-/**/
-/* OUTPUT: This function returns the successor of x or NULL if no */
-/* successor exists. */
-/**/
-/* Modifies Input: none */
-/**/
-/* Note: uses the algorithm in _Introduction_To_Algorithms_ */
-/***********************************************************************/
-
-IntervalTreeNode *
-IT_get_successor(const IntervalTree *it, IntervalTreeNode *x)
+ yasm_xfree(x);
+ }
+ }
+
+ yasm_xfree(it->nil);
+ yasm_xfree(it->root);
+ yasm_xfree(it->recursionNodeStack);
+ yasm_xfree(it);
+}
+
+
+/***********************************************************************/
+/* FUNCTION: Print */
+/**/
+/* INPUTS: none */
+/**/
+/* OUTPUT: none */
+/**/
+/* EFFECT: This function recursively prints the nodes of the tree */
+/* inorder. */
+/**/
+/* Modifies Input: none */
+/**/
+/***********************************************************************/
+
+void
+IT_print(const IntervalTree *it)
{
- IntervalTreeNode *y;
-
- if (it->nil != (y = x->right)) { /* assignment to y is intentional */
- while(y->left != it->nil) /* returns the minium of the right subtree of x */
- y=y->left;
- return y;
- } else {
- y=x->parent;
- while(x == y->right) { /* sentinel used instead of checking for nil */
- x=y;
- y=y->parent;
- }
- if (y == it->root)
- return(it->nil);
- return y;
- }
-}
-
-/***********************************************************************/
-/* FUNCTION: GetPredecessorOf */
-/**/
-/* INPUTS: x is the node to get predecessor of */
-/**/
-/* OUTPUT: This function returns the predecessor of x or NULL if no */
-/* predecessor exists. */
-/**/
-/* Modifies Input: none */
-/**/
-/* Note: uses the algorithm in _Introduction_To_Algorithms_ */
-/***********************************************************************/
-
-IntervalTreeNode *
-IT_get_predecessor(const IntervalTree *it, IntervalTreeNode *x)
-{
- IntervalTreeNode *y;
-
- if (it->nil != (y = x->left)) { /* assignment to y is intentional */
- while(y->right != it->nil) /* returns the maximum of the left subtree of x */
- y=y->right;
- return y;
- } else {
- y=x->parent;
- while(x == y->left) {
- if (y == it->root)
- return(it->nil);
- x=y;
- y=y->parent;
- }
- return y;
- }
-}
-
-/***********************************************************************/
-/* FUNCTION: Print */
-/**/
-/* INPUTS: none */
-/**/
-/* OUTPUT: none */
-/**/
-/* EFFECTS: This function recursively prints the nodes of the tree */
-/* inorder. */
-/**/
-/* Modifies Input: none */
-/**/
-/* Note: This function should only be called from ITTreePrint */
-/***********************************************************************/
-
-static void
-ITN_print(const IntervalTreeNode *itn, IntervalTreeNode *nil,
- IntervalTreeNode *root)
-{
- printf(", l=%li, h=%li, mH=%li", itn->low, itn->high, itn->maxHigh);
- printf(" l->low=");
- if (itn->left == nil)
- printf("NULL");
- else
- printf("%li", itn->left->low);
- printf(" r->low=");
- if (itn->right == nil)
- printf("NULL");
- else
- printf("%li", itn->right->low);
- printf(" p->low=");
- if (itn->parent == root)
- printf("NULL");
- else
- printf("%li", itn->parent->low);
- printf(" red=%i\n", itn->red);
-}
-
-static void
-TreePrintHelper(const IntervalTree *it, IntervalTreeNode *x)
-{
- if (x != it->nil) {
- TreePrintHelper(it, x->left);
- ITN_print(x, it->nil, it->root);
- TreePrintHelper(it, x->right);
- }
-}
-
-void
-IT_destroy(IntervalTree *it)
-{
- IntervalTreeNode *x = it->root->left;
- SLIST_HEAD(node_head, nodeent)
- stuffToFree = SLIST_HEAD_INITIALIZER(stuffToFree);
- struct nodeent {
- SLIST_ENTRY(nodeent) link;
- struct IntervalTreeNode *node;
- } *np;
-
- if (x != it->nil) {
- if (x->left != it->nil) {
- np = yasm_xmalloc(sizeof(struct nodeent));
- np->node = x->left;
- SLIST_INSERT_HEAD(&stuffToFree, np, link);
- }
- if (x->right != it->nil) {
- np = yasm_xmalloc(sizeof(struct nodeent));
- np->node = x->right;
- SLIST_INSERT_HEAD(&stuffToFree, np, link);
- }
- yasm_xfree(x);
- while (!SLIST_EMPTY(&stuffToFree)) {
- np = SLIST_FIRST(&stuffToFree);
- x = np->node;
- SLIST_REMOVE_HEAD(&stuffToFree, link);
- yasm_xfree(np);
-
- if (x->left != it->nil) {
- np = yasm_xmalloc(sizeof(struct nodeent));
- np->node = x->left;
- SLIST_INSERT_HEAD(&stuffToFree, np, link);
- }
- if (x->right != it->nil) {
- np = yasm_xmalloc(sizeof(struct nodeent));
- np->node = x->right;
- SLIST_INSERT_HEAD(&stuffToFree, np, link);
- }
- yasm_xfree(x);
- }
- }
-
- yasm_xfree(it->nil);
- yasm_xfree(it->root);
- yasm_xfree(it->recursionNodeStack);
- yasm_xfree(it);
-}
-
-
-/***********************************************************************/
-/* FUNCTION: Print */
-/**/
-/* INPUTS: none */
-/**/
-/* OUTPUT: none */
-/**/
-/* EFFECT: This function recursively prints the nodes of the tree */
-/* inorder. */
-/**/
-/* Modifies Input: none */
-/**/
-/***********************************************************************/
-
-void
-IT_print(const IntervalTree *it)
-{
- TreePrintHelper(it, it->root->left);
-}
-
-/***********************************************************************/
-/* FUNCTION: DeleteFixUp */
-/**/
-/* INPUTS: x is the child of the spliced */
-/* out node in DeleteNode. */
-/**/
-/* OUTPUT: none */
-/**/
-/* EFFECT: Performs rotations and changes colors to restore red-black */
-/* properties after a node is deleted */
-/**/
-/* Modifies Input: this, x */
-/**/
-/* The algorithm from this function is from _Introduction_To_Algorithms_ */
-/***********************************************************************/
-
-static void
-DeleteFixUp(IntervalTree *it, IntervalTreeNode *x)
-{
- IntervalTreeNode *w;
- IntervalTreeNode *rootLeft = it->root->left;
-
- while ((!x->red) && (rootLeft != x)) {
- if (x == x->parent->left) {
- w=x->parent->right;
- if (w->red) {
- w->red=0;
- x->parent->red=1;
- LeftRotate(it, x->parent);
- w=x->parent->right;
- }
- if ( (!w->right->red) && (!w->left->red) ) {
- w->red=1;
- x=x->parent;
- } else {
- if (!w->right->red) {
- w->left->red=0;
- w->red=1;
- RightRotate(it, w);
- w=x->parent->right;
- }
- w->red=x->parent->red;
- x->parent->red=0;
- w->right->red=0;
- LeftRotate(it, x->parent);
- x=rootLeft; /* this is to exit while loop */
- }
- } else { /* the code below is has left and right switched from above */
- w=x->parent->left;
- if (w->red) {
- w->red=0;
- x->parent->red=1;
- RightRotate(it, x->parent);
- w=x->parent->left;
- }
- if ((!w->right->red) && (!w->left->red)) {
- w->red=1;
- x=x->parent;
- } else {
- if (!w->left->red) {
- w->right->red=0;
- w->red=1;
- LeftRotate(it, w);
- w=x->parent->left;
- }
- w->red=x->parent->red;
- x->parent->red=0;
- w->left->red=0;
- RightRotate(it, x->parent);
- x=rootLeft; /* this is to exit while loop */
- }
- }
- }
- x->red=0;
-
-#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
- IT_CheckAssumptions(it);
-#elif defined(DEBUG_ASSERT)
- Assert(!it->nil->red,"nil not black in ITDeleteFixUp");
- Assert((it->nil->maxHigh=LONG_MIN),
- "nil->maxHigh != LONG_MIN in ITDeleteFixUp");
-#endif
-}
-
-
-/***********************************************************************/
-/* FUNCTION: DeleteNode */
-/**/
-/* INPUTS: tree is the tree to delete node z from */
-/**/
-/* OUTPUT: returns the Interval stored at deleted node */
-/**/
-/* EFFECT: Deletes z from tree and but don't call destructor */
-/* Then calls FixUpMaxHigh to fix maxHigh fields then calls */
-/* ITDeleteFixUp to restore red-black properties */
-/**/
-/* Modifies Input: z */
-/**/
-/* The algorithm from this function is from _Introduction_To_Algorithms_ */
-/***********************************************************************/
-
-void *
-IT_delete_node(IntervalTree *it, IntervalTreeNode *z, long *low, long *high)
-{
- IntervalTreeNode *x, *y;
- void *returnValue = z->data;
- if (low)
- *low = z->low;
- if (high)
- *high = z->high;
-
- y= ((z->left == it->nil) || (z->right == it->nil)) ?
- z : IT_get_successor(it, z);
- x= (y->left == it->nil) ? y->right : y->left;
- if (it->root == (x->parent = y->parent))
- /* assignment of y->p to x->p is intentional */
- it->root->left=x;
- else {
- if (y == y->parent->left)
- y->parent->left=x;
- else
- y->parent->right=x;
- }
- if (y != z) { /* y should not be nil in this case */
-
-#ifdef DEBUG_ASSERT
- Assert( (y!=it->nil),"y is nil in DeleteNode \n");
-#endif
- /* y is the node to splice out and x is its child */
-
- y->maxHigh = INT_MIN;
- y->left=z->left;
- y->right=z->right;
- y->parent=z->parent;
- z->left->parent=z->right->parent=y;
- if (z == z->parent->left)
- z->parent->left=y;
- else
- z->parent->right=y;
- FixUpMaxHigh(it, x->parent);
- if (!(y->red)) {
- y->red = z->red;
- DeleteFixUp(it, x);
- } else
+ TreePrintHelper(it, it->root->left);
+}
+
+/***********************************************************************/
+/* FUNCTION: DeleteFixUp */
+/**/
+/* INPUTS: x is the child of the spliced */
+/* out node in DeleteNode. */
+/**/
+/* OUTPUT: none */
+/**/
+/* EFFECT: Performs rotations and changes colors to restore red-black */
+/* properties after a node is deleted */
+/**/
+/* Modifies Input: this, x */
+/**/
+/* The algorithm from this function is from _Introduction_To_Algorithms_ */
+/***********************************************************************/
+
+static void
+DeleteFixUp(IntervalTree *it, IntervalTreeNode *x)
+{
+ IntervalTreeNode *w;
+ IntervalTreeNode *rootLeft = it->root->left;
+
+ while ((!x->red) && (rootLeft != x)) {
+ if (x == x->parent->left) {
+ w=x->parent->right;
+ if (w->red) {
+ w->red=0;
+ x->parent->red=1;
+ LeftRotate(it, x->parent);
+ w=x->parent->right;
+ }
+ if ( (!w->right->red) && (!w->left->red) ) {
+ w->red=1;
+ x=x->parent;
+ } else {
+ if (!w->right->red) {
+ w->left->red=0;
+ w->red=1;
+ RightRotate(it, w);
+ w=x->parent->right;
+ }
+ w->red=x->parent->red;
+ x->parent->red=0;
+ w->right->red=0;
+ LeftRotate(it, x->parent);
+ x=rootLeft; /* this is to exit while loop */
+ }
+ } else { /* the code below is has left and right switched from above */
+ w=x->parent->left;
+ if (w->red) {
+ w->red=0;
+ x->parent->red=1;
+ RightRotate(it, x->parent);
+ w=x->parent->left;
+ }
+ if ((!w->right->red) && (!w->left->red)) {
+ w->red=1;
+ x=x->parent;
+ } else {
+ if (!w->left->red) {
+ w->right->red=0;
+ w->red=1;
+ LeftRotate(it, w);
+ w=x->parent->left;
+ }
+ w->red=x->parent->red;
+ x->parent->red=0;
+ w->left->red=0;
+ RightRotate(it, x->parent);
+ x=rootLeft; /* this is to exit while loop */
+ }
+ }
+ }
+ x->red=0;
+
+#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
+ IT_CheckAssumptions(it);
+#elif defined(DEBUG_ASSERT)
+ Assert(!it->nil->red,"nil not black in ITDeleteFixUp");
+ Assert((it->nil->maxHigh=LONG_MIN),
+ "nil->maxHigh != LONG_MIN in ITDeleteFixUp");
+#endif
+}
+
+
+/***********************************************************************/
+/* FUNCTION: DeleteNode */
+/**/
+/* INPUTS: tree is the tree to delete node z from */
+/**/
+/* OUTPUT: returns the Interval stored at deleted node */
+/**/
+/* EFFECT: Deletes z from tree and but don't call destructor */
+/* Then calls FixUpMaxHigh to fix maxHigh fields then calls */
+/* ITDeleteFixUp to restore red-black properties */
+/**/
+/* Modifies Input: z */
+/**/
+/* The algorithm from this function is from _Introduction_To_Algorithms_ */
+/***********************************************************************/
+
+void *
+IT_delete_node(IntervalTree *it, IntervalTreeNode *z, long *low, long *high)
+{
+ IntervalTreeNode *x, *y;
+ void *returnValue = z->data;
+ if (low)
+ *low = z->low;
+ if (high)
+ *high = z->high;
+
+ y= ((z->left == it->nil) || (z->right == it->nil)) ?
+ z : IT_get_successor(it, z);
+ x= (y->left == it->nil) ? y->right : y->left;
+ if (it->root == (x->parent = y->parent))
+ /* assignment of y->p to x->p is intentional */
+ it->root->left=x;
+ else {
+ if (y == y->parent->left)
+ y->parent->left=x;
+ else
+ y->parent->right=x;
+ }
+ if (y != z) { /* y should not be nil in this case */
+
+#ifdef DEBUG_ASSERT
+ Assert( (y!=it->nil),"y is nil in DeleteNode \n");
+#endif
+ /* y is the node to splice out and x is its child */
+
+ y->maxHigh = INT_MIN;
+ y->left=z->left;
+ y->right=z->right;
+ y->parent=z->parent;
+ z->left->parent=z->right->parent=y;
+ if (z == z->parent->left)
+ z->parent->left=y;
+ else
+ z->parent->right=y;
+ FixUpMaxHigh(it, x->parent);
+ if (!(y->red)) {
y->red = z->red;
- yasm_xfree(z);
-#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
- IT_CheckAssumptions(it);
-#elif defined(DEBUG_ASSERT)
- Assert(!it->nil->red,"nil not black in ITDelete");
- Assert((it->nil->maxHigh=LONG_MIN),"nil->maxHigh != LONG_MIN in ITDelete");
-#endif
- } else {
- FixUpMaxHigh(it, x->parent);
- if (!(y->red))
- DeleteFixUp(it, x);
- yasm_xfree(y);
-#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
- IT_CheckAssumptions(it);
-#elif defined(DEBUG_ASSERT)
- Assert(!it->nil->red,"nil not black in ITDelete");
- Assert((it->nil->maxHigh=LONG_MIN),"nil->maxHigh != LONG_MIN in ITDelete");
-#endif
- }
- return returnValue;
-}
-
-
-/***********************************************************************/
-/* FUNCTION: Overlap */
-/**/
-/* INPUTS: [a1,a2] and [b1,b2] are the low and high endpoints of two */
-/* closed intervals. */
-/**/
-/* OUTPUT: stack containing pointers to the nodes between [low,high] */
-/**/
-/* Modifies Input: none */
-/**/
-/* EFFECT: returns 1 if the intervals overlap, and 0 otherwise */
-/***********************************************************************/
-
-static int
-Overlap(int a1, int a2, int b1, int b2)
-{
- if (a1 <= b1)
- return (b1 <= a2);
- else
- return (a1 <= b2);
-}
-
-
-/***********************************************************************/
-/* FUNCTION: Enumerate */
-/**/
-/* INPUTS: tree is the tree to look for intervals overlapping the */
-/* closed interval [low,high] */
-/**/
-/* OUTPUT: stack containing pointers to the nodes overlapping */
-/* [low,high] */
-/**/
-/* Modifies Input: none */
-/**/
-/* EFFECT: Returns a stack containing pointers to nodes containing */
-/* intervals which overlap [low,high] in O(max(N,k*log(N))) */
-/* where N is the number of intervals in the tree and k is */
-/* the number of overlapping intervals */
-/**/
-/* Note: This basic idea for this function comes from the */
-/* _Introduction_To_Algorithms_ book by Cormen et al, but */
-/* modifications were made to return all overlapping intervals */
-/* instead of just the first overlapping interval as in the */
-/* book. The natural way to do this would require recursive */
-/* calls of a basic search function. I translated the */
-/* recursive version into an interative version with a stack */
-/* as described below. */
-/***********************************************************************/
-
-
-
-/* The basic idea for the function below is to take the IntervalSearch
- * function from the book and modify to find all overlapping intervals
- * instead of just one. This means that any time we take the left
- * branch down the tree we must also check the right branch if and only if
- * we find an overlapping interval in that left branch. Note this is a
- * recursive condition because if we go left at the root then go left
- * again at the first left child and find an overlap in the left subtree
- * of the left child of root we must recursively check the right subtree
- * of the left child of root as well as the right child of root.
- */
-void
-IT_enumerate(IntervalTree *it, long low, long high, void *cbd,
- void (*callback) (IntervalTreeNode *node, void *cbd))
-{
- IntervalTreeNode *x=it->root->left;
- int stuffToDo = (x != it->nil);
-
- /* Possible speed up: add min field to prune right searches */
-
-#ifdef DEBUG_ASSERT
- Assert((it->recursionNodeStackTop == 1),
- "recursionStack not empty when entering IntervalTree::Enumerate");
-#endif
- it->currentParent = 0;
-
- while (stuffToDo) {
- if (Overlap(low,high,x->low,x->high) ) {
- callback(x, cbd);
- it->recursionNodeStack[it->currentParent].tryRightBranch=1;
- }
- if(x->left->maxHigh >= low) { /* implies x != nil */
- if (it->recursionNodeStackTop == it->recursionNodeStackSize) {
- it->recursionNodeStackSize *= 2;
- it->recursionNodeStack = (it_recursion_node *)
- yasm_xrealloc(it->recursionNodeStack,
- it->recursionNodeStackSize * sizeof(it_recursion_node));
- }
- it->recursionNodeStack[it->recursionNodeStackTop].start_node = x;
- it->recursionNodeStack[it->recursionNodeStackTop].tryRightBranch = 0;
- it->recursionNodeStack[it->recursionNodeStackTop].parentIndex = it->currentParent;
- it->currentParent = it->recursionNodeStackTop++;
- x = x->left;
- } else {
- x = x->right;
- }
- stuffToDo = (x != it->nil);
- while (!stuffToDo && (it->recursionNodeStackTop > 1)) {
- if (it->recursionNodeStack[--it->recursionNodeStackTop].tryRightBranch) {
- x=it->recursionNodeStack[it->recursionNodeStackTop].start_node->right;
- it->currentParent=it->recursionNodeStack[it->recursionNodeStackTop].parentIndex;
- it->recursionNodeStack[it->currentParent].tryRightBranch=1;
- stuffToDo = (x != it->nil);
- }
- }
- }
-#ifdef DEBUG_ASSERT
- Assert((it->recursionNodeStackTop == 1),
- "recursionStack not empty when exiting IntervalTree::Enumerate");
-#endif
-}
-
-#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
-
-static int
-CheckMaxHighFieldsHelper(const IntervalTree *it, IntervalTreeNode *y,
- int currentHigh, int match)
-{
- if (y != it->nil) {
- match = CheckMaxHighFieldsHelper(it, y->left, currentHigh, match) ?
- 1 : match;
- VERIFY(y->high <= currentHigh);
- if (y->high == currentHigh)
- match = 1;
- match = CheckMaxHighFieldsHelper(it, y->right, currentHigh, match) ?
- 1 : match;
- }
- return match;
-}
-
-
-
-/* Make sure the maxHigh fields for everything makes sense. *
- * If something is wrong, print a warning and exit */
-static void
-CheckMaxHighFields(const IntervalTree *it, IntervalTreeNode *x)
-{
- if (x != it->nil) {
- CheckMaxHighFields(it, x->left);
- if(!(CheckMaxHighFieldsHelper(it, x, x->maxHigh, 0) > 0)) {
- fprintf(stderr, "error found in CheckMaxHighFields.\n");
- abort();
- }
- CheckMaxHighFields(it, x->right);
- }
-}
-
-static void
-IT_CheckAssumptions(const IntervalTree *it)
-{
- VERIFY(it->nil->low == INT_MIN);
- VERIFY(it->nil->high == INT_MIN);
- VERIFY(it->nil->maxHigh == INT_MIN);
- VERIFY(it->root->low == INT_MAX);
- VERIFY(it->root->high == INT_MAX);
- VERIFY(it->root->maxHigh == INT_MAX);
- VERIFY(it->nil->data == NULL);
- VERIFY(it->root->data == NULL);
- VERIFY(it->nil->red == 0);
- VERIFY(it->root->red == 0);
- CheckMaxHighFields(it, it->root->left);
-}
-#endif
-
+ DeleteFixUp(it, x);
+ } else
+ y->red = z->red;
+ yasm_xfree(z);
+#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
+ IT_CheckAssumptions(it);
+#elif defined(DEBUG_ASSERT)
+ Assert(!it->nil->red,"nil not black in ITDelete");
+ Assert((it->nil->maxHigh=LONG_MIN),"nil->maxHigh != LONG_MIN in ITDelete");
+#endif
+ } else {
+ FixUpMaxHigh(it, x->parent);
+ if (!(y->red))
+ DeleteFixUp(it, x);
+ yasm_xfree(y);
+#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
+ IT_CheckAssumptions(it);
+#elif defined(DEBUG_ASSERT)
+ Assert(!it->nil->red,"nil not black in ITDelete");
+ Assert((it->nil->maxHigh=LONG_MIN),"nil->maxHigh != LONG_MIN in ITDelete");
+#endif
+ }
+ return returnValue;
+}
+
+
+/***********************************************************************/
+/* FUNCTION: Overlap */
+/**/
+/* INPUTS: [a1,a2] and [b1,b2] are the low and high endpoints of two */
+/* closed intervals. */
+/**/
+/* OUTPUT: stack containing pointers to the nodes between [low,high] */
+/**/
+/* Modifies Input: none */
+/**/
+/* EFFECT: returns 1 if the intervals overlap, and 0 otherwise */
+/***********************************************************************/
+
+static int
+Overlap(int a1, int a2, int b1, int b2)
+{
+ if (a1 <= b1)
+ return (b1 <= a2);
+ else
+ return (a1 <= b2);
+}
+
+
+/***********************************************************************/
+/* FUNCTION: Enumerate */
+/**/
+/* INPUTS: tree is the tree to look for intervals overlapping the */
+/* closed interval [low,high] */
+/**/
+/* OUTPUT: stack containing pointers to the nodes overlapping */
+/* [low,high] */
+/**/
+/* Modifies Input: none */
+/**/
+/* EFFECT: Returns a stack containing pointers to nodes containing */
+/* intervals which overlap [low,high] in O(max(N,k*log(N))) */
+/* where N is the number of intervals in the tree and k is */
+/* the number of overlapping intervals */
+/**/
+/* Note: This basic idea for this function comes from the */
+/* _Introduction_To_Algorithms_ book by Cormen et al, but */
+/* modifications were made to return all overlapping intervals */
+/* instead of just the first overlapping interval as in the */
+/* book. The natural way to do this would require recursive */
+/* calls of a basic search function. I translated the */
+/* recursive version into an interative version with a stack */
+/* as described below. */
+/***********************************************************************/
+
+
+
+/* The basic idea for the function below is to take the IntervalSearch
+ * function from the book and modify to find all overlapping intervals
+ * instead of just one. This means that any time we take the left
+ * branch down the tree we must also check the right branch if and only if
+ * we find an overlapping interval in that left branch. Note this is a
+ * recursive condition because if we go left at the root then go left
+ * again at the first left child and find an overlap in the left subtree
+ * of the left child of root we must recursively check the right subtree
+ * of the left child of root as well as the right child of root.
+ */
+void
+IT_enumerate(IntervalTree *it, long low, long high, void *cbd,
+ void (*callback) (IntervalTreeNode *node, void *cbd))
+{
+ IntervalTreeNode *x=it->root->left;
+ int stuffToDo = (x != it->nil);
+
+ /* Possible speed up: add min field to prune right searches */
+
+#ifdef DEBUG_ASSERT
+ Assert((it->recursionNodeStackTop == 1),
+ "recursionStack not empty when entering IntervalTree::Enumerate");
+#endif
+ it->currentParent = 0;
+
+ while (stuffToDo) {
+ if (Overlap(low,high,x->low,x->high) ) {
+ callback(x, cbd);
+ it->recursionNodeStack[it->currentParent].tryRightBranch=1;
+ }
+ if(x->left->maxHigh >= low) { /* implies x != nil */
+ if (it->recursionNodeStackTop == it->recursionNodeStackSize) {
+ it->recursionNodeStackSize *= 2;
+ it->recursionNodeStack = (it_recursion_node *)
+ yasm_xrealloc(it->recursionNodeStack,
+ it->recursionNodeStackSize * sizeof(it_recursion_node));
+ }
+ it->recursionNodeStack[it->recursionNodeStackTop].start_node = x;
+ it->recursionNodeStack[it->recursionNodeStackTop].tryRightBranch = 0;
+ it->recursionNodeStack[it->recursionNodeStackTop].parentIndex = it->currentParent;
+ it->currentParent = it->recursionNodeStackTop++;
+ x = x->left;
+ } else {
+ x = x->right;
+ }
+ stuffToDo = (x != it->nil);
+ while (!stuffToDo && (it->recursionNodeStackTop > 1)) {
+ if (it->recursionNodeStack[--it->recursionNodeStackTop].tryRightBranch) {
+ x=it->recursionNodeStack[it->recursionNodeStackTop].start_node->right;
+ it->currentParent=it->recursionNodeStack[it->recursionNodeStackTop].parentIndex;
+ it->recursionNodeStack[it->currentParent].tryRightBranch=1;
+ stuffToDo = (x != it->nil);
+ }
+ }
+ }
+#ifdef DEBUG_ASSERT
+ Assert((it->recursionNodeStackTop == 1),
+ "recursionStack not empty when exiting IntervalTree::Enumerate");
+#endif
+}
+
+#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
+
+static int
+CheckMaxHighFieldsHelper(const IntervalTree *it, IntervalTreeNode *y,
+ int currentHigh, int match)
+{
+ if (y != it->nil) {
+ match = CheckMaxHighFieldsHelper(it, y->left, currentHigh, match) ?
+ 1 : match;
+ VERIFY(y->high <= currentHigh);
+ if (y->high == currentHigh)
+ match = 1;
+ match = CheckMaxHighFieldsHelper(it, y->right, currentHigh, match) ?
+ 1 : match;
+ }
+ return match;
+}
+
+
+
+/* Make sure the maxHigh fields for everything makes sense. *
+ * If something is wrong, print a warning and exit */
+static void
+CheckMaxHighFields(const IntervalTree *it, IntervalTreeNode *x)
+{
+ if (x != it->nil) {
+ CheckMaxHighFields(it, x->left);
+ if(!(CheckMaxHighFieldsHelper(it, x, x->maxHigh, 0) > 0)) {
+ fprintf(stderr, "error found in CheckMaxHighFields.\n");
+ abort();
+ }
+ CheckMaxHighFields(it, x->right);
+ }
+}
+
+static void
+IT_CheckAssumptions(const IntervalTree *it)
+{
+ VERIFY(it->nil->low == INT_MIN);
+ VERIFY(it->nil->high == INT_MIN);
+ VERIFY(it->nil->maxHigh == INT_MIN);
+ VERIFY(it->root->low == INT_MAX);
+ VERIFY(it->root->high == INT_MAX);
+ VERIFY(it->root->maxHigh == INT_MAX);
+ VERIFY(it->nil->data == NULL);
+ VERIFY(it->root->data == NULL);
+ VERIFY(it->nil->red == 0);
+ VERIFY(it->root->red == 0);
+ CheckMaxHighFields(it, it->root->left);
+}
+#endif
+
diff --git a/contrib/tools/yasm/libyasm/inttree.h b/contrib/tools/yasm/libyasm/inttree.h
index f7a7651512..44d45527ec 100644
--- a/contrib/tools/yasm/libyasm/inttree.h
+++ b/contrib/tools/yasm/libyasm/inttree.h
@@ -1,70 +1,70 @@
-#ifndef YASM_INTTREE_H
-#define YASM_INTTREE_H
-
-#ifndef YASM_LIB_DECL
-#define YASM_LIB_DECL
-#endif
-
-/* The interval_tree.h and interval_tree.cc files contain code for
- * interval trees implemented using red-black-trees as described in
- * the book _Introduction_To_Algorithms_ by Cormen, Leisserson,
- * and Rivest.
- */
-
-typedef struct IntervalTreeNode {
- struct IntervalTreeNode *left, *right, *parent;
- void *data;
- long low;
- long high;
- long maxHigh;
- int red; /* if red=0 then the node is black */
-} IntervalTreeNode;
-
-typedef struct it_recursion_node {
- /* This structure stores the information needed when we take the
- * right branch in searching for intervals but possibly come back
- * and check the left branch as well.
- */
- IntervalTreeNode *start_node;
- unsigned int parentIndex;
- int tryRightBranch;
-} it_recursion_node;
-
-typedef struct IntervalTree {
- /* A sentinel is used for root and for nil. These sentinels are
- * created when ITTreeCreate is called. root->left should always
- * point to the node which is the root of the tree. nil points to a
- * node which should always be black but has aribtrary children and
- * parent and no key or info. The point of using these sentinels is so
- * that the root and nil nodes do not require special cases in the code
- */
- IntervalTreeNode *root;
- IntervalTreeNode *nil;
-
-/*private:*/
- unsigned int recursionNodeStackSize;
- it_recursion_node * recursionNodeStack;
- unsigned int currentParent;
- unsigned int recursionNodeStackTop;
-} IntervalTree;
-
-YASM_LIB_DECL
-IntervalTree *IT_create(void);
-YASM_LIB_DECL
-void IT_destroy(IntervalTree *);
-YASM_LIB_DECL
-void IT_print(const IntervalTree *);
-YASM_LIB_DECL
-void *IT_delete_node(IntervalTree *, IntervalTreeNode *, long *low,
- long *high);
-YASM_LIB_DECL
-IntervalTreeNode *IT_insert(IntervalTree *, long low, long high, void *data);
-YASM_LIB_DECL
-IntervalTreeNode *IT_get_predecessor(const IntervalTree *, IntervalTreeNode *);
-YASM_LIB_DECL
-IntervalTreeNode *IT_get_successor(const IntervalTree *, IntervalTreeNode *);
-YASM_LIB_DECL
-void IT_enumerate(IntervalTree *, long low, long high, void *cbd,
- void (*callback) (IntervalTreeNode *node, void *cbd));
-
-#endif
+#ifndef YASM_INTTREE_H
+#define YASM_INTTREE_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/* The interval_tree.h and interval_tree.cc files contain code for
+ * interval trees implemented using red-black-trees as described in
+ * the book _Introduction_To_Algorithms_ by Cormen, Leisserson,
+ * and Rivest.
+ */
+
+typedef struct IntervalTreeNode {
+ struct IntervalTreeNode *left, *right, *parent;
+ void *data;
+ long low;
+ long high;
+ long maxHigh;
+ int red; /* if red=0 then the node is black */
+} IntervalTreeNode;
+
+typedef struct it_recursion_node {
+ /* This structure stores the information needed when we take the
+ * right branch in searching for intervals but possibly come back
+ * and check the left branch as well.
+ */
+ IntervalTreeNode *start_node;
+ unsigned int parentIndex;
+ int tryRightBranch;
+} it_recursion_node;
+
+typedef struct IntervalTree {
+ /* A sentinel is used for root and for nil. These sentinels are
+ * created when ITTreeCreate is called. root->left should always
+ * point to the node which is the root of the tree. nil points to a
+ * node which should always be black but has aribtrary children and
+ * parent and no key or info. The point of using these sentinels is so
+ * that the root and nil nodes do not require special cases in the code
+ */
+ IntervalTreeNode *root;
+ IntervalTreeNode *nil;
+
+/*private:*/
+ unsigned int recursionNodeStackSize;
+ it_recursion_node * recursionNodeStack;
+ unsigned int currentParent;
+ unsigned int recursionNodeStackTop;
+} IntervalTree;
+
+YASM_LIB_DECL
+IntervalTree *IT_create(void);
+YASM_LIB_DECL
+void IT_destroy(IntervalTree *);
+YASM_LIB_DECL
+void IT_print(const IntervalTree *);
+YASM_LIB_DECL
+void *IT_delete_node(IntervalTree *, IntervalTreeNode *, long *low,
+ long *high);
+YASM_LIB_DECL
+IntervalTreeNode *IT_insert(IntervalTree *, long low, long high, void *data);
+YASM_LIB_DECL
+IntervalTreeNode *IT_get_predecessor(const IntervalTree *, IntervalTreeNode *);
+YASM_LIB_DECL
+IntervalTreeNode *IT_get_successor(const IntervalTree *, IntervalTreeNode *);
+YASM_LIB_DECL
+void IT_enumerate(IntervalTree *, long low, long high, void *cbd,
+ void (*callback) (IntervalTreeNode *node, void *cbd));
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/linemap.c b/contrib/tools/yasm/libyasm/linemap.c
index 42201d3c07..859407ba5e 100644
--- a/contrib/tools/yasm/libyasm/linemap.c
+++ b/contrib/tools/yasm/libyasm/linemap.c
@@ -1,293 +1,293 @@
-/*
- * YASM assembler virtual line mapping handling (for parse stage)
- *
- * Copyright (C) 2002-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#include "util.h"
-
-#include "coretype.h"
-#include "hamt.h"
-
-#include "errwarn.h"
-#include "linemap.h"
-
-
-typedef struct line_mapping {
- /* monotonically increasing virtual line */
- unsigned long line;
-
- /* related info */
- /* "original" source filename */
- /*@null@*/ /*@dependent@*/ const char *filename;
- /* "original" source base line number */
- unsigned long file_line;
- /* "original" source line number increment (for following lines) */
- unsigned long line_inc;
-} line_mapping;
-
-typedef struct line_source_info {
- /* first bytecode on line; NULL if no bytecodes on line */
- /*@null@*/ /*@dependent@*/ yasm_bytecode *bc;
-
- /* source code line */
- /*@owned@*/ char *source;
-} line_source_info;
-
-struct yasm_linemap {
- /* Shared storage for filenames */
- /*@only@*/ /*@null@*/ HAMT *filenames;
-
- /* Current virtual line number. */
- unsigned long current;
-
- /* Mappings from virtual to physical line numbers */
- struct line_mapping *map_vector;
- unsigned long map_size;
- unsigned long map_allocated;
-
- /* Bytecode and source line information */
- /*@only@*/ line_source_info *source_info;
- size_t source_info_size;
-};
-
-static void
-filename_delete_one(/*@only@*/ void *d)
-{
- yasm_xfree(d);
-}
-
-void
-yasm_linemap_set(yasm_linemap *linemap, const char *filename,
- unsigned long virtual_line, unsigned long file_line,
- unsigned long line_inc)
-{
- char *copy;
- unsigned long i;
- int replace = 0;
- line_mapping *mapping = NULL;
-
- if (virtual_line == 0) {
- virtual_line = linemap->current;
- }
-
- /* Replace all existing mappings that have line numbers >= this one. */
- for (i = linemap->map_size; i > 0; i--) {
- if (linemap->map_vector[i-1].line < virtual_line) {
- if (i < linemap->map_size) {
- mapping = &linemap->map_vector[i];
- linemap->map_size = i + 1;
- }
- break;
- }
- }
-
- if (mapping == NULL) {
- /* Create a new mapping in the map */
- if (linemap->map_size >= linemap->map_allocated) {
- /* allocate another size bins when full for 2x space */
- linemap->map_vector = yasm_xrealloc(linemap->map_vector,
- 2*linemap->map_allocated*sizeof(line_mapping));
- linemap->map_allocated *= 2;
- }
- mapping = &linemap->map_vector[linemap->map_size];
- linemap->map_size++;
- }
-
- /* Fill it */
-
- if (!filename) {
- if (linemap->map_size >= 2)
- mapping->filename =
- linemap->map_vector[linemap->map_size-2].filename;
- else
- filename = "unknown";
- }
- if (filename) {
- /* Copy the filename (via shared storage) */
- copy = yasm__xstrdup(filename);
- /*@-aliasunique@*/
- mapping->filename = HAMT_insert(linemap->filenames, copy, copy,
- &replace, filename_delete_one);
- /*@=aliasunique@*/
- }
-
- mapping->line = virtual_line;
- mapping->file_line = file_line;
- mapping->line_inc = line_inc;
-}
-
-unsigned long
-yasm_linemap_poke(yasm_linemap *linemap, const char *filename,
- unsigned long file_line)
-{
- unsigned long line;
- line_mapping *mapping;
-
- linemap->current++;
- yasm_linemap_set(linemap, filename, 0, file_line, 0);
-
- mapping = &linemap->map_vector[linemap->map_size-1];
-
- line = linemap->current;
-
- linemap->current++;
- yasm_linemap_set(linemap, mapping->filename, 0,
- mapping->file_line +
- mapping->line_inc*(linemap->current-2-mapping->line),
- mapping->line_inc);
-
- return line;
-}
-
-yasm_linemap *
-yasm_linemap_create(void)
-{
- size_t i;
- yasm_linemap *linemap = yasm_xmalloc(sizeof(yasm_linemap));
-
- linemap->filenames = HAMT_create(0, yasm_internal_error_);
-
- linemap->current = 1;
-
- /* initialize mapping vector */
- linemap->map_vector = yasm_xmalloc(8*sizeof(line_mapping));
- linemap->map_size = 0;
- linemap->map_allocated = 8;
-
- /* initialize source line information array */
- linemap->source_info_size = 2;
- linemap->source_info = yasm_xmalloc(linemap->source_info_size *
- sizeof(line_source_info));
- for (i=0; i<linemap->source_info_size; i++) {
- linemap->source_info[i].bc = NULL;
- linemap->source_info[i].source = NULL;
- }
-
- return linemap;
-}
-
-void
-yasm_linemap_destroy(yasm_linemap *linemap)
-{
- size_t i;
- for (i=0; i<linemap->source_info_size; i++) {
- if (linemap->source_info[i].source)
- yasm_xfree(linemap->source_info[i].source);
- }
- yasm_xfree(linemap->source_info);
-
- yasm_xfree(linemap->map_vector);
-
- if (linemap->filenames)
- HAMT_destroy(linemap->filenames, filename_delete_one);
-
- yasm_xfree(linemap);
-}
-
-unsigned long
-yasm_linemap_get_current(yasm_linemap *linemap)
-{
- return linemap->current;
-}
-
-void
-yasm_linemap_add_source(yasm_linemap *linemap, yasm_bytecode *bc,
- const char *source)
-{
- size_t i;
-
- while (linemap->current > linemap->source_info_size) {
- /* allocate another size bins when full for 2x space */
- linemap->source_info = yasm_xrealloc(linemap->source_info,
- 2*linemap->source_info_size*sizeof(line_source_info));
- for (i=linemap->source_info_size; i<linemap->source_info_size*2; i++) {
- linemap->source_info[i].bc = NULL;
- linemap->source_info[i].source = NULL;
- }
- linemap->source_info_size *= 2;
- }
-
- /* Delete existing info for that line (if any) */
- if (linemap->source_info[linemap->current-1].source)
- yasm_xfree(linemap->source_info[linemap->current-1].source);
-
- linemap->source_info[linemap->current-1].bc = bc;
- linemap->source_info[linemap->current-1].source = yasm__xstrdup(source);
-}
-
-unsigned long
-yasm_linemap_goto_next(yasm_linemap *linemap)
-{
- return ++(linemap->current);
-}
-
-void
-yasm_linemap_lookup(yasm_linemap *linemap, unsigned long line,
- const char **filename, unsigned long *file_line)
-{
- line_mapping *mapping;
- unsigned long vindex, step;
-
- assert(line <= linemap->current);
-
- /* Binary search through map to find highest line_index <= index */
- vindex = 0;
- /* start step as the greatest power of 2 <= size */
- step = 1;
- while (step*2<=linemap->map_size)
- step*=2;
- while (step>0) {
- if (vindex+step < linemap->map_size
- && linemap->map_vector[vindex+step].line <= line)
- vindex += step;
- step /= 2;
- }
- mapping = &linemap->map_vector[vindex];
-
- *filename = mapping->filename;
- *file_line = (line ? mapping->file_line + mapping->line_inc*(line-mapping->line) : 0);
-}
-
-int
-yasm_linemap_traverse_filenames(yasm_linemap *linemap, /*@null@*/ void *d,
- int (*func) (const char *filename, void *d))
-{
- return HAMT_traverse(linemap->filenames, d, (int (*) (void *, void *))func);
-}
-
-int
-yasm_linemap_get_source(yasm_linemap *linemap, unsigned long line,
- yasm_bytecode **bcp, const char **sourcep)
-{
- if (line > linemap->source_info_size) {
- *bcp = NULL;
- *sourcep = NULL;
- return 1;
- }
-
- *bcp = linemap->source_info[line-1].bc;
- *sourcep = linemap->source_info[line-1].source;
-
- return (!(*sourcep));
-}
+/*
+ * YASM assembler virtual line mapping handling (for parse stage)
+ *
+ * Copyright (C) 2002-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "util.h"
+
+#include "coretype.h"
+#include "hamt.h"
+
+#include "errwarn.h"
+#include "linemap.h"
+
+
+typedef struct line_mapping {
+ /* monotonically increasing virtual line */
+ unsigned long line;
+
+ /* related info */
+ /* "original" source filename */
+ /*@null@*/ /*@dependent@*/ const char *filename;
+ /* "original" source base line number */
+ unsigned long file_line;
+ /* "original" source line number increment (for following lines) */
+ unsigned long line_inc;
+} line_mapping;
+
+typedef struct line_source_info {
+ /* first bytecode on line; NULL if no bytecodes on line */
+ /*@null@*/ /*@dependent@*/ yasm_bytecode *bc;
+
+ /* source code line */
+ /*@owned@*/ char *source;
+} line_source_info;
+
+struct yasm_linemap {
+ /* Shared storage for filenames */
+ /*@only@*/ /*@null@*/ HAMT *filenames;
+
+ /* Current virtual line number. */
+ unsigned long current;
+
+ /* Mappings from virtual to physical line numbers */
+ struct line_mapping *map_vector;
+ unsigned long map_size;
+ unsigned long map_allocated;
+
+ /* Bytecode and source line information */
+ /*@only@*/ line_source_info *source_info;
+ size_t source_info_size;
+};
+
+static void
+filename_delete_one(/*@only@*/ void *d)
+{
+ yasm_xfree(d);
+}
+
+void
+yasm_linemap_set(yasm_linemap *linemap, const char *filename,
+ unsigned long virtual_line, unsigned long file_line,
+ unsigned long line_inc)
+{
+ char *copy;
+ unsigned long i;
+ int replace = 0;
+ line_mapping *mapping = NULL;
+
+ if (virtual_line == 0) {
+ virtual_line = linemap->current;
+ }
+
+ /* Replace all existing mappings that have line numbers >= this one. */
+ for (i = linemap->map_size; i > 0; i--) {
+ if (linemap->map_vector[i-1].line < virtual_line) {
+ if (i < linemap->map_size) {
+ mapping = &linemap->map_vector[i];
+ linemap->map_size = i + 1;
+ }
+ break;
+ }
+ }
+
+ if (mapping == NULL) {
+ /* Create a new mapping in the map */
+ if (linemap->map_size >= linemap->map_allocated) {
+ /* allocate another size bins when full for 2x space */
+ linemap->map_vector = yasm_xrealloc(linemap->map_vector,
+ 2*linemap->map_allocated*sizeof(line_mapping));
+ linemap->map_allocated *= 2;
+ }
+ mapping = &linemap->map_vector[linemap->map_size];
+ linemap->map_size++;
+ }
+
+ /* Fill it */
+
+ if (!filename) {
+ if (linemap->map_size >= 2)
+ mapping->filename =
+ linemap->map_vector[linemap->map_size-2].filename;
+ else
+ filename = "unknown";
+ }
+ if (filename) {
+ /* Copy the filename (via shared storage) */
+ copy = yasm__xstrdup(filename);
+ /*@-aliasunique@*/
+ mapping->filename = HAMT_insert(linemap->filenames, copy, copy,
+ &replace, filename_delete_one);
+ /*@=aliasunique@*/
+ }
+
+ mapping->line = virtual_line;
+ mapping->file_line = file_line;
+ mapping->line_inc = line_inc;
+}
+
+unsigned long
+yasm_linemap_poke(yasm_linemap *linemap, const char *filename,
+ unsigned long file_line)
+{
+ unsigned long line;
+ line_mapping *mapping;
+
+ linemap->current++;
+ yasm_linemap_set(linemap, filename, 0, file_line, 0);
+
+ mapping = &linemap->map_vector[linemap->map_size-1];
+
+ line = linemap->current;
+
+ linemap->current++;
+ yasm_linemap_set(linemap, mapping->filename, 0,
+ mapping->file_line +
+ mapping->line_inc*(linemap->current-2-mapping->line),
+ mapping->line_inc);
+
+ return line;
+}
+
+yasm_linemap *
+yasm_linemap_create(void)
+{
+ size_t i;
+ yasm_linemap *linemap = yasm_xmalloc(sizeof(yasm_linemap));
+
+ linemap->filenames = HAMT_create(0, yasm_internal_error_);
+
+ linemap->current = 1;
+
+ /* initialize mapping vector */
+ linemap->map_vector = yasm_xmalloc(8*sizeof(line_mapping));
+ linemap->map_size = 0;
+ linemap->map_allocated = 8;
+
+ /* initialize source line information array */
+ linemap->source_info_size = 2;
+ linemap->source_info = yasm_xmalloc(linemap->source_info_size *
+ sizeof(line_source_info));
+ for (i=0; i<linemap->source_info_size; i++) {
+ linemap->source_info[i].bc = NULL;
+ linemap->source_info[i].source = NULL;
+ }
+
+ return linemap;
+}
+
+void
+yasm_linemap_destroy(yasm_linemap *linemap)
+{
+ size_t i;
+ for (i=0; i<linemap->source_info_size; i++) {
+ if (linemap->source_info[i].source)
+ yasm_xfree(linemap->source_info[i].source);
+ }
+ yasm_xfree(linemap->source_info);
+
+ yasm_xfree(linemap->map_vector);
+
+ if (linemap->filenames)
+ HAMT_destroy(linemap->filenames, filename_delete_one);
+
+ yasm_xfree(linemap);
+}
+
+unsigned long
+yasm_linemap_get_current(yasm_linemap *linemap)
+{
+ return linemap->current;
+}
+
+void
+yasm_linemap_add_source(yasm_linemap *linemap, yasm_bytecode *bc,
+ const char *source)
+{
+ size_t i;
+
+ while (linemap->current > linemap->source_info_size) {
+ /* allocate another size bins when full for 2x space */
+ linemap->source_info = yasm_xrealloc(linemap->source_info,
+ 2*linemap->source_info_size*sizeof(line_source_info));
+ for (i=linemap->source_info_size; i<linemap->source_info_size*2; i++) {
+ linemap->source_info[i].bc = NULL;
+ linemap->source_info[i].source = NULL;
+ }
+ linemap->source_info_size *= 2;
+ }
+
+ /* Delete existing info for that line (if any) */
+ if (linemap->source_info[linemap->current-1].source)
+ yasm_xfree(linemap->source_info[linemap->current-1].source);
+
+ linemap->source_info[linemap->current-1].bc = bc;
+ linemap->source_info[linemap->current-1].source = yasm__xstrdup(source);
+}
+
+unsigned long
+yasm_linemap_goto_next(yasm_linemap *linemap)
+{
+ return ++(linemap->current);
+}
+
+void
+yasm_linemap_lookup(yasm_linemap *linemap, unsigned long line,
+ const char **filename, unsigned long *file_line)
+{
+ line_mapping *mapping;
+ unsigned long vindex, step;
+
+ assert(line <= linemap->current);
+
+ /* Binary search through map to find highest line_index <= index */
+ vindex = 0;
+ /* start step as the greatest power of 2 <= size */
+ step = 1;
+ while (step*2<=linemap->map_size)
+ step*=2;
+ while (step>0) {
+ if (vindex+step < linemap->map_size
+ && linemap->map_vector[vindex+step].line <= line)
+ vindex += step;
+ step /= 2;
+ }
+ mapping = &linemap->map_vector[vindex];
+
+ *filename = mapping->filename;
+ *file_line = (line ? mapping->file_line + mapping->line_inc*(line-mapping->line) : 0);
+}
+
+int
+yasm_linemap_traverse_filenames(yasm_linemap *linemap, /*@null@*/ void *d,
+ int (*func) (const char *filename, void *d))
+{
+ return HAMT_traverse(linemap->filenames, d, (int (*) (void *, void *))func);
+}
+
+int
+yasm_linemap_get_source(yasm_linemap *linemap, unsigned long line,
+ yasm_bytecode **bcp, const char **sourcep)
+{
+ if (line > linemap->source_info_size) {
+ *bcp = NULL;
+ *sourcep = NULL;
+ return 1;
+ }
+
+ *bcp = linemap->source_info[line-1].bc;
+ *sourcep = linemap->source_info[line-1].source;
+
+ return (!(*sourcep));
+}
diff --git a/contrib/tools/yasm/libyasm/linemap.h b/contrib/tools/yasm/libyasm/linemap.h
index 1c5aa4626a..2a9b140e42 100644
--- a/contrib/tools/yasm/libyasm/linemap.h
+++ b/contrib/tools/yasm/libyasm/linemap.h
@@ -1,141 +1,141 @@
-/**
- * \file libyasm/linemap.h
- * \brief YASM virtual line mapping interface.
- *
- * \license
- * Copyright (C) 2002-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- * \endlicense
- */
-#ifndef YASM_LINEMAP_H
-#define YASM_LINEMAP_H
-
-#ifndef YASM_LIB_DECL
-#define YASM_LIB_DECL
-#endif
-
-/** Create a new line mapping repository.
- * \return New repository.
- */
-YASM_LIB_DECL
-yasm_linemap *yasm_linemap_create(void);
-
-/** Clean up any memory allocated for a repository.
- * \param linemap line mapping repository
- */
-YASM_LIB_DECL
-void yasm_linemap_destroy(yasm_linemap *linemap);
-
-/** Get the current line position in a repository.
- * \param linemap line mapping repository
- * \return Current virtual line.
- */
-YASM_LIB_DECL
-unsigned long yasm_linemap_get_current(yasm_linemap *linemap);
-
-/** Get bytecode and source line information, if any, for a virtual line.
- * \param linemap line mapping repository
- * \param line virtual line
- * \param bcp pointer to return bytecode into
- * \param sourcep pointer to return source code line pointer into
- * \return Zero if source line information available for line, nonzero if not.
- * \note If source line information is not available, bcp and sourcep targets
- * are set to NULL.
- */
-YASM_LIB_DECL
-int yasm_linemap_get_source(yasm_linemap *linemap, unsigned long line,
- /*@null@*/ yasm_bytecode **bcp,
- const char **sourcep);
-
-/** Add bytecode and source line information to the current virtual line.
- * \attention Deletes any existing bytecode and source line information for
- * the current virtual line.
- * \param linemap line mapping repository
- * \param bc bytecode (if any)
- * \param source source code line
- * \note The source code line pointer is NOT kept, it is strdup'ed.
- */
-YASM_LIB_DECL
-void yasm_linemap_add_source(yasm_linemap *linemap,
- /*@null@*/ yasm_bytecode *bc,
- const char *source);
-
-/** Go to the next line (increments the current virtual line).
- * \param linemap line mapping repository
- * \return The current (new) virtual line.
- */
-YASM_LIB_DECL
-unsigned long yasm_linemap_goto_next(yasm_linemap *linemap);
-
-/** Set a new file/line physical association starting point at the specified
- * virtual line. line_inc indicates how much the "real" line is incremented
- * by for each virtual line increment (0 is perfectly legal).
- * \param linemap line mapping repository
- * \param filename physical file name (if NULL, not changed)
- * \param virtual_line virtual line number (if 0, linemap->current is used)
- * \param file_line physical line number
- * \param line_inc line increment
- */
-YASM_LIB_DECL
-void yasm_linemap_set(yasm_linemap *linemap, /*@null@*/ const char *filename,
- unsigned long virtual_line, unsigned long file_line,
- unsigned long line_inc);
-
-/** Poke a single file/line association, restoring the original physical
- * association starting point. Caution: increments the current virtual line
- * twice.
- * \param linemap line mapping repository
- * \param filename physical file name (if NULL, not changed)
- * \param file_line physical line number
- * \return The virtual line number of the poked association.
- */
-YASM_LIB_DECL
-unsigned long yasm_linemap_poke(yasm_linemap *linemap,
- /*@null@*/ const char *filename,
- unsigned long file_line);
-
-/** Look up the associated physical file and line for a virtual line.
- * \param linemap line mapping repository
- * \param line virtual line
- * \param filename physical file name (output)
- * \param file_line physical line number (output)
- */
-YASM_LIB_DECL
-void yasm_linemap_lookup(yasm_linemap *linemap, unsigned long line,
- /*@out@*/ const char **filename,
- /*@out@*/ unsigned long *file_line);
-
-/** Traverses all filenames used in a linemap, calling a function on each
- * filename.
- * \param linemap line mapping repository
- * \param d data pointer passed to func on each call
- * \param func function
- * \return Stops early (and returns func's return value) if func returns a
- * nonzero value; otherwise 0.
- */
-YASM_LIB_DECL
-int yasm_linemap_traverse_filenames
- (yasm_linemap *linemap, /*@null@*/ void *d,
- int (*func) (const char *filename, void *d));
-
-#endif
+/**
+ * \file libyasm/linemap.h
+ * \brief YASM virtual line mapping interface.
+ *
+ * \license
+ * Copyright (C) 2002-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * \endlicense
+ */
+#ifndef YASM_LINEMAP_H
+#define YASM_LINEMAP_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/** Create a new line mapping repository.
+ * \return New repository.
+ */
+YASM_LIB_DECL
+yasm_linemap *yasm_linemap_create(void);
+
+/** Clean up any memory allocated for a repository.
+ * \param linemap line mapping repository
+ */
+YASM_LIB_DECL
+void yasm_linemap_destroy(yasm_linemap *linemap);
+
+/** Get the current line position in a repository.
+ * \param linemap line mapping repository
+ * \return Current virtual line.
+ */
+YASM_LIB_DECL
+unsigned long yasm_linemap_get_current(yasm_linemap *linemap);
+
+/** Get bytecode and source line information, if any, for a virtual line.
+ * \param linemap line mapping repository
+ * \param line virtual line
+ * \param bcp pointer to return bytecode into
+ * \param sourcep pointer to return source code line pointer into
+ * \return Zero if source line information available for line, nonzero if not.
+ * \note If source line information is not available, bcp and sourcep targets
+ * are set to NULL.
+ */
+YASM_LIB_DECL
+int yasm_linemap_get_source(yasm_linemap *linemap, unsigned long line,
+ /*@null@*/ yasm_bytecode **bcp,
+ const char **sourcep);
+
+/** Add bytecode and source line information to the current virtual line.
+ * \attention Deletes any existing bytecode and source line information for
+ * the current virtual line.
+ * \param linemap line mapping repository
+ * \param bc bytecode (if any)
+ * \param source source code line
+ * \note The source code line pointer is NOT kept, it is strdup'ed.
+ */
+YASM_LIB_DECL
+void yasm_linemap_add_source(yasm_linemap *linemap,
+ /*@null@*/ yasm_bytecode *bc,
+ const char *source);
+
+/** Go to the next line (increments the current virtual line).
+ * \param linemap line mapping repository
+ * \return The current (new) virtual line.
+ */
+YASM_LIB_DECL
+unsigned long yasm_linemap_goto_next(yasm_linemap *linemap);
+
+/** Set a new file/line physical association starting point at the specified
+ * virtual line. line_inc indicates how much the "real" line is incremented
+ * by for each virtual line increment (0 is perfectly legal).
+ * \param linemap line mapping repository
+ * \param filename physical file name (if NULL, not changed)
+ * \param virtual_line virtual line number (if 0, linemap->current is used)
+ * \param file_line physical line number
+ * \param line_inc line increment
+ */
+YASM_LIB_DECL
+void yasm_linemap_set(yasm_linemap *linemap, /*@null@*/ const char *filename,
+ unsigned long virtual_line, unsigned long file_line,
+ unsigned long line_inc);
+
+/** Poke a single file/line association, restoring the original physical
+ * association starting point. Caution: increments the current virtual line
+ * twice.
+ * \param linemap line mapping repository
+ * \param filename physical file name (if NULL, not changed)
+ * \param file_line physical line number
+ * \return The virtual line number of the poked association.
+ */
+YASM_LIB_DECL
+unsigned long yasm_linemap_poke(yasm_linemap *linemap,
+ /*@null@*/ const char *filename,
+ unsigned long file_line);
+
+/** Look up the associated physical file and line for a virtual line.
+ * \param linemap line mapping repository
+ * \param line virtual line
+ * \param filename physical file name (output)
+ * \param file_line physical line number (output)
+ */
+YASM_LIB_DECL
+void yasm_linemap_lookup(yasm_linemap *linemap, unsigned long line,
+ /*@out@*/ const char **filename,
+ /*@out@*/ unsigned long *file_line);
+
+/** Traverses all filenames used in a linemap, calling a function on each
+ * filename.
+ * \param linemap line mapping repository
+ * \param d data pointer passed to func on each call
+ * \param func function
+ * \return Stops early (and returns func's return value) if func returns a
+ * nonzero value; otherwise 0.
+ */
+YASM_LIB_DECL
+int yasm_linemap_traverse_filenames
+ (yasm_linemap *linemap, /*@null@*/ void *d,
+ int (*func) (const char *filename, void *d));
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/listfmt.h b/contrib/tools/yasm/libyasm/listfmt.h
index 945f28e58b..c428de3628 100644
--- a/contrib/tools/yasm/libyasm/listfmt.h
+++ b/contrib/tools/yasm/libyasm/listfmt.h
@@ -1,124 +1,124 @@
-/**
- * \file libyasm/listfmt.h
- * \brief YASM list format interface.
- *
- * \license
- * Copyright (C) 2004-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- * \endlicense
- */
-#ifndef YASM_LISTFMT_H
-#define YASM_LISTFMT_H
-
-#ifndef YASM_DOXYGEN
-/** Base #yasm_listfmt structure. Must be present as the first element in any
- * #yasm_listfmt implementation.
- */
-typedef struct yasm_listfmt_base {
- /** #yasm_listfmt_module implementation for this list format. */
- const struct yasm_listfmt_module *module;
-} yasm_listfmt_base;
-#endif
-
-/** YASM list format module interface. */
-typedef struct yasm_listfmt_module {
- /** One-line description of the list format. */
- const char *name;
-
- /** Keyword used to select list format. */
- const char *keyword;
-
- /** Create list format.
- * Module-level implementation of yasm_listfmt_create().
- * The filenames are provided solely for informational purposes.
- * \param in_filename primary input filename
- * \param obj_filename object filename
- * \return NULL if unable to initialize.
- */
- /*@null@*/ /*@only@*/ yasm_listfmt * (*create)
- (const char *in_filename, const char *obj_filename);
-
- /** Module-level implementation of yasm_listfmt_destroy().
- * Call yasm_listfmt_destroy() instead of calling this function.
- */
- void (*destroy) (/*@only@*/ yasm_listfmt *listfmt);
-
- /** Module-level implementation of yasm_listfmt_output().
- * Call yasm_listfmt_output() instead of calling this function.
- */
- void (*output) (yasm_listfmt *listfmt, FILE *f, yasm_linemap *linemap,
- yasm_arch *arch);
-} yasm_listfmt_module;
-
-/** Get the keyword used to select a list format.
- * \param listfmt list format
- * \return keyword
- */
-const char *yasm_listfmt_keyword(const yasm_listfmt *listfmt);
-
-/** Initialize list format for use. Must call before any other list
- * format functions. The filenames are provided solely for informational
- * purposes.
- * \param module list format module
- * \param in_filename primary input filename
- * \param obj_filename object filename
- * \return NULL if object format does not provide needed support.
- */
-/*@null@*/ /*@only@*/ yasm_listfmt *yasm_listfmt_create
- (const yasm_listfmt_module *module, const char *in_filename,
- const char *obj_filename);
-
-/** Cleans up any allocated list format memory.
- * \param listfmt list format
- */
-void yasm_listfmt_destroy(/*@only@*/ yasm_listfmt *listfmt);
-
-/** Write out list to the list file.
- * This function may call all read-only yasm_* functions as necessary.
- * \param listfmt list format
- * \param f output list file
- * \param linemap line mapping repository
- * \param arch architecture
- */
-void yasm_listfmt_output(yasm_listfmt *listfmt, FILE *f,
- yasm_linemap *linemap, yasm_arch *arch);
-
-#ifndef YASM_DOXYGEN
-
-/* Inline macro implementations for listfmt functions */
-
-#define yasm_listfmt_keyword(listfmt) \
- (((yasm_listfmt_base *)listfmt)->module->keyword)
-
-#define yasm_listfmt_create(module, in_filename, obj_filename) \
- module->create(in_filename, obj_filename)
-
-#define yasm_listfmt_destroy(listfmt) \
- ((yasm_listfmt_base *)listfmt)->module->destroy(listfmt)
-
-#define yasm_listfmt_output(listfmt, f, linemap, a) \
- ((yasm_listfmt_base *)listfmt)->module->output(listfmt, f, linemap, a)
-
-#endif
-
-#endif
+/**
+ * \file libyasm/listfmt.h
+ * \brief YASM list format interface.
+ *
+ * \license
+ * Copyright (C) 2004-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * \endlicense
+ */
+#ifndef YASM_LISTFMT_H
+#define YASM_LISTFMT_H
+
+#ifndef YASM_DOXYGEN
+/** Base #yasm_listfmt structure. Must be present as the first element in any
+ * #yasm_listfmt implementation.
+ */
+typedef struct yasm_listfmt_base {
+ /** #yasm_listfmt_module implementation for this list format. */
+ const struct yasm_listfmt_module *module;
+} yasm_listfmt_base;
+#endif
+
+/** YASM list format module interface. */
+typedef struct yasm_listfmt_module {
+ /** One-line description of the list format. */
+ const char *name;
+
+ /** Keyword used to select list format. */
+ const char *keyword;
+
+ /** Create list format.
+ * Module-level implementation of yasm_listfmt_create().
+ * The filenames are provided solely for informational purposes.
+ * \param in_filename primary input filename
+ * \param obj_filename object filename
+ * \return NULL if unable to initialize.
+ */
+ /*@null@*/ /*@only@*/ yasm_listfmt * (*create)
+ (const char *in_filename, const char *obj_filename);
+
+ /** Module-level implementation of yasm_listfmt_destroy().
+ * Call yasm_listfmt_destroy() instead of calling this function.
+ */
+ void (*destroy) (/*@only@*/ yasm_listfmt *listfmt);
+
+ /** Module-level implementation of yasm_listfmt_output().
+ * Call yasm_listfmt_output() instead of calling this function.
+ */
+ void (*output) (yasm_listfmt *listfmt, FILE *f, yasm_linemap *linemap,
+ yasm_arch *arch);
+} yasm_listfmt_module;
+
+/** Get the keyword used to select a list format.
+ * \param listfmt list format
+ * \return keyword
+ */
+const char *yasm_listfmt_keyword(const yasm_listfmt *listfmt);
+
+/** Initialize list format for use. Must call before any other list
+ * format functions. The filenames are provided solely for informational
+ * purposes.
+ * \param module list format module
+ * \param in_filename primary input filename
+ * \param obj_filename object filename
+ * \return NULL if object format does not provide needed support.
+ */
+/*@null@*/ /*@only@*/ yasm_listfmt *yasm_listfmt_create
+ (const yasm_listfmt_module *module, const char *in_filename,
+ const char *obj_filename);
+
+/** Cleans up any allocated list format memory.
+ * \param listfmt list format
+ */
+void yasm_listfmt_destroy(/*@only@*/ yasm_listfmt *listfmt);
+
+/** Write out list to the list file.
+ * This function may call all read-only yasm_* functions as necessary.
+ * \param listfmt list format
+ * \param f output list file
+ * \param linemap line mapping repository
+ * \param arch architecture
+ */
+void yasm_listfmt_output(yasm_listfmt *listfmt, FILE *f,
+ yasm_linemap *linemap, yasm_arch *arch);
+
+#ifndef YASM_DOXYGEN
+
+/* Inline macro implementations for listfmt functions */
+
+#define yasm_listfmt_keyword(listfmt) \
+ (((yasm_listfmt_base *)listfmt)->module->keyword)
+
+#define yasm_listfmt_create(module, in_filename, obj_filename) \
+ module->create(in_filename, obj_filename)
+
+#define yasm_listfmt_destroy(listfmt) \
+ ((yasm_listfmt_base *)listfmt)->module->destroy(listfmt)
+
+#define yasm_listfmt_output(listfmt, f, linemap, a) \
+ ((yasm_listfmt_base *)listfmt)->module->output(listfmt, f, linemap, a)
+
+#endif
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/md5.c b/contrib/tools/yasm/libyasm/md5.c
index b009842f5c..c188c453e7 100644
--- a/contrib/tools/yasm/libyasm/md5.c
+++ b/contrib/tools/yasm/libyasm/md5.c
@@ -1,309 +1,309 @@
-/*
- * This code implements the MD5 message-digest algorithm.
- * The algorithm is due to Ron Rivest. This code was
- * written by Colin Plumb in 1993, no copyright is claimed.
- * This code is in the public domain; do with it what you wish.
- *
- * Equivalent code is available from RSA Data Security, Inc.
- * This code has been tested against that, and is equivalent,
- * except that you don't need to include two pages of legalese
- * with every copy.
- *
- * To compute the message digest of a chunk of bytes, declare an
- * MD5Context structure, pass it to MD5Init, call MD5Update as
- * needed on buffers full of bytes, and then call MD5Final, which
- * will fill a supplied 16-byte array with the digest.
- */
-
-/* This code was modified in 1997 by Jim Kingdon of Cyclic Software to
- not require an integer type which is exactly 32 bits. This work
- draws on the changes for the same purpose by Tatu Ylonen
- <ylo@cs.hut.fi> as part of SSH, but since I didn't actually use
- that code, there is no copyright issue. I hereby disclaim
- copyright in any changes I have made; this code remains in the
- public domain. */
-
-/* Note regarding cvs_* namespace: this avoids potential conflicts
- with libraries such as some versions of Kerberos. No particular
- need to worry about whether the system supplies an MD5 library, as
- this file is only about 3k of object code. */
-
-#include <util.h>
-
-#include "md5.h"
-
-/* Little-endian byte-swapping routines. Note that these do not
- depend on the size of datatypes such as cvs_uint32, nor do they require
- us to detect the endianness of the machine we are running on. It
- is possible they should be macros for speed, but I would be
- surprised if they were a performance bottleneck for MD5. */
-
-static unsigned long
-getu32(const unsigned char *addr)
-{
- return (((((unsigned long)addr[3] << 8) | addr[2]) << 8)
- | addr[1]) << 8 | addr[0];
-}
-
-static void
-putu32(unsigned long data, unsigned char *addr)
-{
- addr[0] = (unsigned char)data;
- addr[1] = (unsigned char)(data >> 8);
- addr[2] = (unsigned char)(data >> 16);
- addr[3] = (unsigned char)(data >> 24);
-}
-
-/*
- * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
- * initialization constants.
- */
-void
-yasm_md5_init(yasm_md5_context *ctx)
-{
- ctx->buf[0] = 0x67452301;
- ctx->buf[1] = 0xefcdab89;
- ctx->buf[2] = 0x98badcfe;
- ctx->buf[3] = 0x10325476;
-
- ctx->bits[0] = 0;
- ctx->bits[1] = 0;
-}
-
-/*
- * Update context to reflect the concatenation of another buffer full
- * of bytes.
- */
-void
-yasm_md5_update(yasm_md5_context *ctx, unsigned char const *buf,
- unsigned long len)
-{
- unsigned long t;
-
- /* Update bitcount */
-
- t = ctx->bits[0];
- if ((ctx->bits[0] = (t + ((unsigned long)len << 3)) & 0xffffffff) < t)
- ctx->bits[1]++; /* Carry from low to high */
- ctx->bits[1] += len >> 29;
-
- t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
-
- /* Handle any leading odd-sized chunks */
-
- if ( t ) {
- unsigned char *p = ctx->in + t;
-
- t = 64-t;
- if (len < t) {
- memcpy(p, buf, len);
- return;
- }
- memcpy(p, buf, t);
- yasm_md5_transform (ctx->buf, ctx->in);
- buf += t;
- len -= t;
- }
-
- /* Process data in 64-byte chunks */
-
- while (len >= 64) {
- memcpy(ctx->in, buf, 64);
- yasm_md5_transform (ctx->buf, ctx->in);
- buf += 64;
- len -= 64;
- }
-
- /* Handle any remaining bytes of data. */
-
- memcpy(ctx->in, buf, len);
-}
-
-/*
- * Final wrapup - pad to 64-byte boundary with the bit pattern
- * 1 0* (64-bit count of bits processed, MSB-first)
- */
-void
-yasm_md5_final(unsigned char digest[16], yasm_md5_context *ctx)
-{
- unsigned count;
- unsigned char *p;
-
- /* Compute number of bytes mod 64 */
- count = (ctx->bits[0] >> 3) & 0x3F;
-
- /* Set the first char of padding to 0x80. This is safe since there is
- always at least one byte free */
- p = ctx->in + count;
- *p++ = 0x80;
-
- /* Bytes of padding needed to make 64 bytes */
- count = 64 - 1 - count;
-
- /* Pad out to 56 mod 64 */
- if (count < 8) {
- /* Two lots of padding: Pad the first block to 64 bytes */
- memset(p, 0, count);
- yasm_md5_transform (ctx->buf, ctx->in);
-
- /* Now fill the next block with 56 bytes */
- memset(ctx->in, 0, 56);
- } else {
- /* Pad block to 56 bytes */
- memset(p, 0, count-8);
- }
-
- /* Append length in bits and transform */
- putu32(ctx->bits[0], ctx->in + 56);
- putu32(ctx->bits[1], ctx->in + 60);
-
- yasm_md5_transform (ctx->buf, ctx->in);
- putu32(ctx->buf[0], digest);
- putu32(ctx->buf[1], digest + 4);
- putu32(ctx->buf[2], digest + 8);
- putu32(ctx->buf[3], digest + 12);
- memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
-}
-
-#ifndef ASM_MD5
-
-/* The four core functions - F1 is optimized somewhat */
-
-/* #define F1(x, y, z) (x & y | ~x & z) */
-#define F1(x, y, z) (z ^ (x & (y ^ z)))
-#define F2(x, y, z) F1(z, x, y)
-#define F3(x, y, z) (x ^ y ^ z)
-#define F4(x, y, z) (y ^ (x | ~z))
-
-/* This is the central step in the MD5 algorithm. */
-#define MD5STEP(f, w, x, y, z, data, s) \
- ( w += f(x, y, z) + data, w &= 0xffffffff, w = w<<s | w>>(32-s), w += x )
-
-/*
- * The core of the MD5 algorithm, this alters an existing MD5 hash to
- * reflect the addition of 16 longwords of new data. MD5Update blocks
- * the data and converts bytes into longwords for this routine.
- */
-void
-yasm_md5_transform(unsigned long buf[4], const unsigned char inraw[64])
-{
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest. This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+
+/* This code was modified in 1997 by Jim Kingdon of Cyclic Software to
+ not require an integer type which is exactly 32 bits. This work
+ draws on the changes for the same purpose by Tatu Ylonen
+ <ylo@cs.hut.fi> as part of SSH, but since I didn't actually use
+ that code, there is no copyright issue. I hereby disclaim
+ copyright in any changes I have made; this code remains in the
+ public domain. */
+
+/* Note regarding cvs_* namespace: this avoids potential conflicts
+ with libraries such as some versions of Kerberos. No particular
+ need to worry about whether the system supplies an MD5 library, as
+ this file is only about 3k of object code. */
+
+#include <util.h>
+
+#include "md5.h"
+
+/* Little-endian byte-swapping routines. Note that these do not
+ depend on the size of datatypes such as cvs_uint32, nor do they require
+ us to detect the endianness of the machine we are running on. It
+ is possible they should be macros for speed, but I would be
+ surprised if they were a performance bottleneck for MD5. */
+
+static unsigned long
+getu32(const unsigned char *addr)
+{
+ return (((((unsigned long)addr[3] << 8) | addr[2]) << 8)
+ | addr[1]) << 8 | addr[0];
+}
+
+static void
+putu32(unsigned long data, unsigned char *addr)
+{
+ addr[0] = (unsigned char)data;
+ addr[1] = (unsigned char)(data >> 8);
+ addr[2] = (unsigned char)(data >> 16);
+ addr[3] = (unsigned char)(data >> 24);
+}
+
+/*
+ * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void
+yasm_md5_init(yasm_md5_context *ctx)
+{
+ ctx->buf[0] = 0x67452301;
+ ctx->buf[1] = 0xefcdab89;
+ ctx->buf[2] = 0x98badcfe;
+ ctx->buf[3] = 0x10325476;
+
+ ctx->bits[0] = 0;
+ ctx->bits[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+yasm_md5_update(yasm_md5_context *ctx, unsigned char const *buf,
+ unsigned long len)
+{
+ unsigned long t;
+
+ /* Update bitcount */
+
+ t = ctx->bits[0];
+ if ((ctx->bits[0] = (t + ((unsigned long)len << 3)) & 0xffffffff) < t)
+ ctx->bits[1]++; /* Carry from low to high */
+ ctx->bits[1] += len >> 29;
+
+ t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
+
+ /* Handle any leading odd-sized chunks */
+
+ if ( t ) {
+ unsigned char *p = ctx->in + t;
+
+ t = 64-t;
+ if (len < t) {
+ memcpy(p, buf, len);
+ return;
+ }
+ memcpy(p, buf, t);
+ yasm_md5_transform (ctx->buf, ctx->in);
+ buf += t;
+ len -= t;
+ }
+
+ /* Process data in 64-byte chunks */
+
+ while (len >= 64) {
+ memcpy(ctx->in, buf, 64);
+ yasm_md5_transform (ctx->buf, ctx->in);
+ buf += 64;
+ len -= 64;
+ }
+
+ /* Handle any remaining bytes of data. */
+
+ memcpy(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void
+yasm_md5_final(unsigned char digest[16], yasm_md5_context *ctx)
+{
+ unsigned count;
+ unsigned char *p;
+
+ /* Compute number of bytes mod 64 */
+ count = (ctx->bits[0] >> 3) & 0x3F;
+
+ /* Set the first char of padding to 0x80. This is safe since there is
+ always at least one byte free */
+ p = ctx->in + count;
+ *p++ = 0x80;
+
+ /* Bytes of padding needed to make 64 bytes */
+ count = 64 - 1 - count;
+
+ /* Pad out to 56 mod 64 */
+ if (count < 8) {
+ /* Two lots of padding: Pad the first block to 64 bytes */
+ memset(p, 0, count);
+ yasm_md5_transform (ctx->buf, ctx->in);
+
+ /* Now fill the next block with 56 bytes */
+ memset(ctx->in, 0, 56);
+ } else {
+ /* Pad block to 56 bytes */
+ memset(p, 0, count-8);
+ }
+
+ /* Append length in bits and transform */
+ putu32(ctx->bits[0], ctx->in + 56);
+ putu32(ctx->bits[1], ctx->in + 60);
+
+ yasm_md5_transform (ctx->buf, ctx->in);
+ putu32(ctx->buf[0], digest);
+ putu32(ctx->buf[1], digest + 4);
+ putu32(ctx->buf[2], digest + 8);
+ putu32(ctx->buf[3], digest + 12);
+ memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
+}
+
+#ifndef ASM_MD5
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+ ( w += f(x, y, z) + data, w &= 0xffffffff, w = w<<s | w>>(32-s), w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data. MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+void
+yasm_md5_transform(unsigned long buf[4], const unsigned char inraw[64])
+{
unsigned long a, b, c, d;
- unsigned long in[16];
- int i;
-
- for (i = 0; i < 16; ++i)
- in[i] = getu32 (inraw + 4 * i);
-
- a = buf[0];
- b = buf[1];
- c = buf[2];
- d = buf[3];
-
- MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7);
- MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
- MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
- MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
- MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7);
- MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
- MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
- MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
- MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7);
- MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
- MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
- MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
- MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7);
- MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
- MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
- MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
-
- MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5);
- MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9);
- MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
- MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
- MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5);
- MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9);
- MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
- MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
- MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5);
- MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9);
- MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
- MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
- MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5);
- MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9);
- MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
- MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
-
- MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4);
- MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
- MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
- MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
- MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4);
- MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
- MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
- MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
- MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4);
- MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
- MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
- MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
- MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4);
- MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
- MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
- MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
-
- MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6);
- MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
- MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
- MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
- MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6);
- MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
- MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
- MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
- MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6);
- MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
- MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
- MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
- MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6);
- MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
- MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
- MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
-
- buf[0] += a;
- buf[1] += b;
- buf[2] += c;
- buf[3] += d;
-}
-#endif
-
-#ifdef TEST
-/* Simple test program. Can use it to manually run the tests from
- RFC1321 for example. */
-#include <stdio.h>
-
-int
-main (int argc, char **argv)
-{
- yasm_md5_context context;
- unsigned char checksum[16];
- int i;
- int j;
-
- if (argc < 2)
- {
- fprintf (stderr, "usage: %s string-to-hash\n", argv[0]);
- exit (1);
- }
- for (j = 1; j < argc; ++j)
- {
- printf ("MD5 (\"%s\") = ", argv[j]);
- yasm_md5_init (&context);
- yasm_md5_update (&context, argv[j], strlen (argv[j]));
- yasm_md5_final (checksum, &context);
- for (i = 0; i < 16; i++)
- {
- printf ("%02x", (unsigned int) checksum[i]);
- }
- printf ("\n");
- }
- return 0;
-}
-#endif /* TEST */
+ unsigned long in[16];
+ int i;
+
+ for (i = 0; i < 16; ++i)
+ in[i] = getu32 (inraw + 4 * i);
+
+ a = buf[0];
+ b = buf[1];
+ c = buf[2];
+ d = buf[3];
+
+ MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
+#endif
+
+#ifdef TEST
+/* Simple test program. Can use it to manually run the tests from
+ RFC1321 for example. */
+#include <stdio.h>
+
+int
+main (int argc, char **argv)
+{
+ yasm_md5_context context;
+ unsigned char checksum[16];
+ int i;
+ int j;
+
+ if (argc < 2)
+ {
+ fprintf (stderr, "usage: %s string-to-hash\n", argv[0]);
+ exit (1);
+ }
+ for (j = 1; j < argc; ++j)
+ {
+ printf ("MD5 (\"%s\") = ", argv[j]);
+ yasm_md5_init (&context);
+ yasm_md5_update (&context, argv[j], strlen (argv[j]));
+ yasm_md5_final (checksum, &context);
+ for (i = 0; i < 16; i++)
+ {
+ printf ("%02x", (unsigned int) checksum[i]);
+ }
+ printf ("\n");
+ }
+ return 0;
+}
+#endif /* TEST */
diff --git a/contrib/tools/yasm/libyasm/md5.h b/contrib/tools/yasm/libyasm/md5.h
index 7872fda7a1..20b4de5e7a 100644
--- a/contrib/tools/yasm/libyasm/md5.h
+++ b/contrib/tools/yasm/libyasm/md5.h
@@ -1,32 +1,32 @@
-/* See md5.c for explanation and copyright information. */
-
-#ifndef YASM_MD5_H
-#define YASM_MD5_H
-
-#ifndef YASM_LIB_DECL
-#define YASM_LIB_DECL
-#endif
-
-/* Unlike previous versions of this code, uint32 need not be exactly
- 32 bits, merely 32 bits or more. Choosing a data type which is 32
- bits instead of 64 is not important; speed is considerably more
- important. ANSI guarantees that "unsigned long" will be big enough,
- and always using it seems to have few disadvantages. */
-
-typedef struct yasm_md5_context {
- unsigned long buf[4];
- unsigned long bits[2];
- unsigned char in[64];
-} yasm_md5_context;
-
-YASM_LIB_DECL
-void yasm_md5_init(yasm_md5_context *context);
-YASM_LIB_DECL
-void yasm_md5_update(yasm_md5_context *context, unsigned char const *buf,
- unsigned long len);
-YASM_LIB_DECL
-void yasm_md5_final(unsigned char digest[16], yasm_md5_context *context);
-YASM_LIB_DECL
-void yasm_md5_transform(unsigned long buf[4], const unsigned char in[64]);
-
-#endif /* !YASM_MD5_H */
+/* See md5.c for explanation and copyright information. */
+
+#ifndef YASM_MD5_H
+#define YASM_MD5_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/* Unlike previous versions of this code, uint32 need not be exactly
+ 32 bits, merely 32 bits or more. Choosing a data type which is 32
+ bits instead of 64 is not important; speed is considerably more
+ important. ANSI guarantees that "unsigned long" will be big enough,
+ and always using it seems to have few disadvantages. */
+
+typedef struct yasm_md5_context {
+ unsigned long buf[4];
+ unsigned long bits[2];
+ unsigned char in[64];
+} yasm_md5_context;
+
+YASM_LIB_DECL
+void yasm_md5_init(yasm_md5_context *context);
+YASM_LIB_DECL
+void yasm_md5_update(yasm_md5_context *context, unsigned char const *buf,
+ unsigned long len);
+YASM_LIB_DECL
+void yasm_md5_final(unsigned char digest[16], yasm_md5_context *context);
+YASM_LIB_DECL
+void yasm_md5_transform(unsigned long buf[4], const unsigned char in[64]);
+
+#endif /* !YASM_MD5_H */
diff --git a/contrib/tools/yasm/libyasm/mergesort.c b/contrib/tools/yasm/libyasm/mergesort.c
index 3eeaa8273b..8b4a7d250d 100644
--- a/contrib/tools/yasm/libyasm/mergesort.c
+++ b/contrib/tools/yasm/libyasm/mergesort.c
@@ -1,361 +1,361 @@
-/*
- * mergesort() implementation for systems that don't have it.
- *
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Peter McIlroy.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include "util.h"
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)merge.c 8.2 (Berkeley) 2/14/94";
-#endif /* LIBC_SCCS and not lint */
-
-#ifdef HAVE_MERGESORT
-#undef yasm__mergesort
-#endif
-
-#ifndef HAVE_MERGESORT
-/*
- * Hybrid exponential search/linear search merge sort with hybrid
- * natural/pairwise first pass. Requires about .3% more comparisons
- * for random data than LSMS with pairwise first pass alone.
- * It works for objects as small as two bytes.
- */
-
-#define NATURAL
-#define THRESHOLD 16 /* Best choice for natural merge cut-off. */
-
-/* #define NATURAL to get hybrid natural merge.
- * (The default is pairwise merging.)
- */
-
-#include <errno.h>
-#include <string.h>
-
-static void setup(unsigned char *, unsigned char *, size_t, size_t,
- int (*)(const void *, const void *));
-static void insertionsort(unsigned char *, size_t, size_t,
- int (*)(const void *, const void *));
-
-#define ISIZE sizeof(int)
-#define PSIZE sizeof(unsigned char *)
-#define ICOPY_LIST(src, dst, last) \
- do \
- *(int*)dst = *(int*)src, src += ISIZE, dst += ISIZE; \
- while(src < last)
-#define ICOPY_ELT(src, dst, i) \
- do \
- *(int*) dst = *(int*) src, src += ISIZE, dst += ISIZE; \
- while (i -= ISIZE)
-
-#define CCOPY_LIST(src, dst, last) \
- do \
- *dst++ = *src++; \
- while (src < last)
-#define CCOPY_ELT(src, dst, i) \
- do \
- *dst++ = *src++; \
- while (i -= 1)
-
-/*
- * Find the next possible pointer head. (Trickery for forcing an array
- * to do double duty as a linked list when objects do not align with word
- * boundaries.
- */
-/* Assumption: PSIZE is a power of 2. */
-#define EVAL(p) (unsigned char **) \
- ((unsigned char *)0 + \
- (((unsigned char *)p + PSIZE - 1 - (unsigned char *) 0) & ~(PSIZE - 1)))
-#endif /*HAVE_MERGESORT*/
-
-/*
- * Arguments are as for qsort.
- */
-int
-yasm__mergesort(void *base, size_t nmemb, size_t size,
- int (*cmp)(const void *, const void *))
-{
-#ifdef HAVE_MERGESORT
- return mergesort(base, nmemb, size, cmp);
-#else
- size_t i;
- int sense;
- int big, iflag;
- unsigned char *f1, *f2, *t, *b, *tp2, *q, *l1, *l2;
- unsigned char *list2, *list1, *p2, *p, *last, **p1;
-
- if (size < PSIZE / 2) { /* Pointers must fit into 2 * size. */
-#ifdef EINVAL
- errno = EINVAL;
-#endif
- return (-1);
- }
-
- if (nmemb == 0)
- return (0);
-
- /*
- * XXX
- * Stupid subtraction for the Cray.
- */
- iflag = 0;
- if (!(size % ISIZE) && !(((char *)base - (char *)0) % ISIZE))
- iflag = 1;
-
- if ((list2 = yasm_xmalloc(nmemb * size + PSIZE)) == NULL)
- return (-1);
-
- list1 = base;
- setup(list1, list2, nmemb, size, cmp);
- last = list2 + nmemb * size;
- i = 0;
- big = 0;
- while (*EVAL(list2) != last) {
- l2 = list1;
- p1 = EVAL(list1);
- for (tp2 = p2 = list2; p2 != last; p1 = EVAL(l2)) {
- p2 = *EVAL(p2);
- f1 = l2;
- f2 = l1 = list1 + (p2 - list2);
- if (p2 != last)
- p2 = *EVAL(p2);
- l2 = list1 + (p2 - list2);
- while (f1 < l1 && f2 < l2) {
- if ((*cmp)(f1, f2) <= 0) {
- q = f2;
- b = f1, t = l1;
- sense = -1;
- } else {
- q = f1;
- b = f2, t = l2;
- sense = 0;
- }
- if (!big) { /* here i = 0 */
- while ((b += size) < t && cmp(q, b) >sense)
- if (++i == 6) {
- big = 1;
- goto EXPONENTIAL;
- }
- } else {
-EXPONENTIAL: for (i = size; ; i <<= 1)
- if ((p = (b + i)) >= t) {
- if ((p = t - size) > b &&
- (*cmp)(q, p) <= sense)
- t = p;
- else
- b = p;
- break;
- } else if ((*cmp)(q, p) <= sense) {
- t = p;
- if (i == size)
- big = 0;
- goto FASTCASE;
- } else
- b = p;
- while (t > b+size) {
- i = (((t - b) / size) >> 1) * size;
- if ((*cmp)(q, p = b + i) <= sense)
- t = p;
- else
- b = p;
- }
- goto COPY;
-FASTCASE: while (i > size)
- if ((*cmp)(q,
- p = b + (i >>= 1)) <= sense)
- t = p;
- else
- b = p;
-COPY: b = t;
- }
- i = size;
- if (q == f1) {
- if (iflag) {
- ICOPY_LIST(f2, tp2, b);
- ICOPY_ELT(f1, tp2, i);
- } else {
- CCOPY_LIST(f2, tp2, b);
- CCOPY_ELT(f1, tp2, i);
- }
- } else {
- if (iflag) {
- ICOPY_LIST(f1, tp2, b);
- ICOPY_ELT(f2, tp2, i);
- } else {
- CCOPY_LIST(f1, tp2, b);
- CCOPY_ELT(f2, tp2, i);
- }
- }
- }
- if (f2 < l2) {
- if (iflag)
- ICOPY_LIST(f2, tp2, l2);
- else
- CCOPY_LIST(f2, tp2, l2);
- } else if (f1 < l1) {
- if (iflag)
- ICOPY_LIST(f1, tp2, l1);
- else
- CCOPY_LIST(f1, tp2, l1);
- }
- *p1 = l2;
- }
- tp2 = list1; /* swap list1, list2 */
- list1 = list2;
- list2 = tp2;
- last = list2 + nmemb*size;
- }
- if (base == list2) {
- memmove(list2, list1, nmemb*size);
- list2 = list1;
- }
- yasm_xfree(list2);
- return (0);
-#endif /*HAVE_MERGESORT*/
-}
-
-#ifndef HAVE_MERGESORT
-
-#define swap(a, b) { \
- s = b; \
- i = size; \
- do { \
- tmp = *a; *a++ = *s; *s++ = tmp; \
- } while (--i); \
- a -= size; \
- }
-#define reverse(bot, top) { \
- s = top; \
- do { \
- i = size; \
- do { \
- tmp = *bot; *bot++ = *s; *s++ = tmp; \
- } while (--i); \
- s -= size2; \
- } while(bot < s); \
-}
-
-/*
- * Optional hybrid natural/pairwise first pass. Eats up list1 in runs of
- * increasing order, list2 in a corresponding linked list. Checks for runs
- * when THRESHOLD/2 pairs compare with same sense. (Only used when NATURAL
- * is defined. Otherwise simple pairwise merging is used.)
- */
-void
-setup(unsigned char *list1, unsigned char *list2, size_t n, size_t size,
- int (*cmp)(const void *, const void *))
-{
- size_t i;
- unsigned int tmp;
- int length, sense;
- size_t size2;
- unsigned char *f1, *f2, *s, *l2, *last, *p2;
-
- size2 = size*2;
- if (n <= 5) {
- insertionsort(list1, n, size, cmp);
- *EVAL(list2) = (unsigned char*) list2 + n*size;
- return;
- }
- /*
- * Avoid running pointers out of bounds; limit n to evens
- * for simplicity.
- */
- i = 4 + (n & 1);
- insertionsort(list1 + (n - i) * size, i, size, cmp);
- last = list1 + size * (n - i);
- *EVAL(list2 + (last - list1)) = list2 + n * size;
-
-#ifdef NATURAL
- p2 = list2;
- f1 = list1;
- sense = (cmp(f1, f1 + size) > 0);
- for (; f1 < last; sense = !sense) {
- length = 2;
- /* Find pairs with same sense. */
- for (f2 = f1 + size2; f2 < last; f2 += size2) {
- if ((cmp(f2, f2+ size) > 0) != sense)
- break;
- length += 2;
- }
- if (length < THRESHOLD) { /* Pairwise merge */
- do {
- p2 = *EVAL(p2) = f1 + size2 - list1 + list2;
- if (sense > 0)
- swap (f1, f1 + size);
- } while ((f1 += size2) < f2);
- } else { /* Natural merge */
- l2 = f2;
- for (f2 = f1 + size2; f2 < l2; f2 += size2) {
- if ((cmp(f2-size, f2) > 0) != sense) {
- p2 = *EVAL(p2) = f2 - list1 + list2;
- if (sense > 0)
- reverse(f1, f2-size);
- f1 = f2;
- }
- }
- if (sense > 0)
- reverse (f1, f2-size);
- f1 = f2;
- if (f2 < last || cmp(f2 - size, f2) > 0)
- p2 = *EVAL(p2) = f2 - list1 + list2;
- else
- p2 = *EVAL(p2) = list2 + n*size;
- }
- }
-#else /* pairwise merge only. */
- for (f1 = list1, p2 = list2; f1 < last; f1 += size2) {
- p2 = *EVAL(p2) = p2 + size2;
- if (cmp (f1, f1 + size) > 0)
- swap(f1, f1 + size);
- }
-#endif /* NATURAL */
-}
-
-/*
- * This is to avoid out-of-bounds addresses in sorting the
- * last 4 elements.
- */
-static void
-insertionsort(unsigned char *a, size_t n, size_t size,
- int (*cmp)(const void *, const void *))
-{
- unsigned char *ai, *s, *t, *u, tmp;
- size_t i;
-
- for (ai = a+size; --n >= 1; ai += size)
- for (t = ai; t > a; t -= size) {
- u = t - size;
- if (cmp(u, t) <= 0)
- break;
- swap(u, t);
- }
-}
-#endif /*HAVE_MERGESORT*/
+/*
+ * mergesort() implementation for systems that don't have it.
+ *
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Peter McIlroy.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "util.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)merge.c 8.2 (Berkeley) 2/14/94";
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef HAVE_MERGESORT
+#undef yasm__mergesort
+#endif
+
+#ifndef HAVE_MERGESORT
+/*
+ * Hybrid exponential search/linear search merge sort with hybrid
+ * natural/pairwise first pass. Requires about .3% more comparisons
+ * for random data than LSMS with pairwise first pass alone.
+ * It works for objects as small as two bytes.
+ */
+
+#define NATURAL
+#define THRESHOLD 16 /* Best choice for natural merge cut-off. */
+
+/* #define NATURAL to get hybrid natural merge.
+ * (The default is pairwise merging.)
+ */
+
+#include <errno.h>
+#include <string.h>
+
+static void setup(unsigned char *, unsigned char *, size_t, size_t,
+ int (*)(const void *, const void *));
+static void insertionsort(unsigned char *, size_t, size_t,
+ int (*)(const void *, const void *));
+
+#define ISIZE sizeof(int)
+#define PSIZE sizeof(unsigned char *)
+#define ICOPY_LIST(src, dst, last) \
+ do \
+ *(int*)dst = *(int*)src, src += ISIZE, dst += ISIZE; \
+ while(src < last)
+#define ICOPY_ELT(src, dst, i) \
+ do \
+ *(int*) dst = *(int*) src, src += ISIZE, dst += ISIZE; \
+ while (i -= ISIZE)
+
+#define CCOPY_LIST(src, dst, last) \
+ do \
+ *dst++ = *src++; \
+ while (src < last)
+#define CCOPY_ELT(src, dst, i) \
+ do \
+ *dst++ = *src++; \
+ while (i -= 1)
+
+/*
+ * Find the next possible pointer head. (Trickery for forcing an array
+ * to do double duty as a linked list when objects do not align with word
+ * boundaries.
+ */
+/* Assumption: PSIZE is a power of 2. */
+#define EVAL(p) (unsigned char **) \
+ ((unsigned char *)0 + \
+ (((unsigned char *)p + PSIZE - 1 - (unsigned char *) 0) & ~(PSIZE - 1)))
+#endif /*HAVE_MERGESORT*/
+
+/*
+ * Arguments are as for qsort.
+ */
+int
+yasm__mergesort(void *base, size_t nmemb, size_t size,
+ int (*cmp)(const void *, const void *))
+{
+#ifdef HAVE_MERGESORT
+ return mergesort(base, nmemb, size, cmp);
+#else
+ size_t i;
+ int sense;
+ int big, iflag;
+ unsigned char *f1, *f2, *t, *b, *tp2, *q, *l1, *l2;
+ unsigned char *list2, *list1, *p2, *p, *last, **p1;
+
+ if (size < PSIZE / 2) { /* Pointers must fit into 2 * size. */
+#ifdef EINVAL
+ errno = EINVAL;
+#endif
+ return (-1);
+ }
+
+ if (nmemb == 0)
+ return (0);
+
+ /*
+ * XXX
+ * Stupid subtraction for the Cray.
+ */
+ iflag = 0;
+ if (!(size % ISIZE) && !(((char *)base - (char *)0) % ISIZE))
+ iflag = 1;
+
+ if ((list2 = yasm_xmalloc(nmemb * size + PSIZE)) == NULL)
+ return (-1);
+
+ list1 = base;
+ setup(list1, list2, nmemb, size, cmp);
+ last = list2 + nmemb * size;
+ i = 0;
+ big = 0;
+ while (*EVAL(list2) != last) {
+ l2 = list1;
+ p1 = EVAL(list1);
+ for (tp2 = p2 = list2; p2 != last; p1 = EVAL(l2)) {
+ p2 = *EVAL(p2);
+ f1 = l2;
+ f2 = l1 = list1 + (p2 - list2);
+ if (p2 != last)
+ p2 = *EVAL(p2);
+ l2 = list1 + (p2 - list2);
+ while (f1 < l1 && f2 < l2) {
+ if ((*cmp)(f1, f2) <= 0) {
+ q = f2;
+ b = f1, t = l1;
+ sense = -1;
+ } else {
+ q = f1;
+ b = f2, t = l2;
+ sense = 0;
+ }
+ if (!big) { /* here i = 0 */
+ while ((b += size) < t && cmp(q, b) >sense)
+ if (++i == 6) {
+ big = 1;
+ goto EXPONENTIAL;
+ }
+ } else {
+EXPONENTIAL: for (i = size; ; i <<= 1)
+ if ((p = (b + i)) >= t) {
+ if ((p = t - size) > b &&
+ (*cmp)(q, p) <= sense)
+ t = p;
+ else
+ b = p;
+ break;
+ } else if ((*cmp)(q, p) <= sense) {
+ t = p;
+ if (i == size)
+ big = 0;
+ goto FASTCASE;
+ } else
+ b = p;
+ while (t > b+size) {
+ i = (((t - b) / size) >> 1) * size;
+ if ((*cmp)(q, p = b + i) <= sense)
+ t = p;
+ else
+ b = p;
+ }
+ goto COPY;
+FASTCASE: while (i > size)
+ if ((*cmp)(q,
+ p = b + (i >>= 1)) <= sense)
+ t = p;
+ else
+ b = p;
+COPY: b = t;
+ }
+ i = size;
+ if (q == f1) {
+ if (iflag) {
+ ICOPY_LIST(f2, tp2, b);
+ ICOPY_ELT(f1, tp2, i);
+ } else {
+ CCOPY_LIST(f2, tp2, b);
+ CCOPY_ELT(f1, tp2, i);
+ }
+ } else {
+ if (iflag) {
+ ICOPY_LIST(f1, tp2, b);
+ ICOPY_ELT(f2, tp2, i);
+ } else {
+ CCOPY_LIST(f1, tp2, b);
+ CCOPY_ELT(f2, tp2, i);
+ }
+ }
+ }
+ if (f2 < l2) {
+ if (iflag)
+ ICOPY_LIST(f2, tp2, l2);
+ else
+ CCOPY_LIST(f2, tp2, l2);
+ } else if (f1 < l1) {
+ if (iflag)
+ ICOPY_LIST(f1, tp2, l1);
+ else
+ CCOPY_LIST(f1, tp2, l1);
+ }
+ *p1 = l2;
+ }
+ tp2 = list1; /* swap list1, list2 */
+ list1 = list2;
+ list2 = tp2;
+ last = list2 + nmemb*size;
+ }
+ if (base == list2) {
+ memmove(list2, list1, nmemb*size);
+ list2 = list1;
+ }
+ yasm_xfree(list2);
+ return (0);
+#endif /*HAVE_MERGESORT*/
+}
+
+#ifndef HAVE_MERGESORT
+
+#define swap(a, b) { \
+ s = b; \
+ i = size; \
+ do { \
+ tmp = *a; *a++ = *s; *s++ = tmp; \
+ } while (--i); \
+ a -= size; \
+ }
+#define reverse(bot, top) { \
+ s = top; \
+ do { \
+ i = size; \
+ do { \
+ tmp = *bot; *bot++ = *s; *s++ = tmp; \
+ } while (--i); \
+ s -= size2; \
+ } while(bot < s); \
+}
+
+/*
+ * Optional hybrid natural/pairwise first pass. Eats up list1 in runs of
+ * increasing order, list2 in a corresponding linked list. Checks for runs
+ * when THRESHOLD/2 pairs compare with same sense. (Only used when NATURAL
+ * is defined. Otherwise simple pairwise merging is used.)
+ */
+void
+setup(unsigned char *list1, unsigned char *list2, size_t n, size_t size,
+ int (*cmp)(const void *, const void *))
+{
+ size_t i;
+ unsigned int tmp;
+ int length, sense;
+ size_t size2;
+ unsigned char *f1, *f2, *s, *l2, *last, *p2;
+
+ size2 = size*2;
+ if (n <= 5) {
+ insertionsort(list1, n, size, cmp);
+ *EVAL(list2) = (unsigned char*) list2 + n*size;
+ return;
+ }
+ /*
+ * Avoid running pointers out of bounds; limit n to evens
+ * for simplicity.
+ */
+ i = 4 + (n & 1);
+ insertionsort(list1 + (n - i) * size, i, size, cmp);
+ last = list1 + size * (n - i);
+ *EVAL(list2 + (last - list1)) = list2 + n * size;
+
+#ifdef NATURAL
+ p2 = list2;
+ f1 = list1;
+ sense = (cmp(f1, f1 + size) > 0);
+ for (; f1 < last; sense = !sense) {
+ length = 2;
+ /* Find pairs with same sense. */
+ for (f2 = f1 + size2; f2 < last; f2 += size2) {
+ if ((cmp(f2, f2+ size) > 0) != sense)
+ break;
+ length += 2;
+ }
+ if (length < THRESHOLD) { /* Pairwise merge */
+ do {
+ p2 = *EVAL(p2) = f1 + size2 - list1 + list2;
+ if (sense > 0)
+ swap (f1, f1 + size);
+ } while ((f1 += size2) < f2);
+ } else { /* Natural merge */
+ l2 = f2;
+ for (f2 = f1 + size2; f2 < l2; f2 += size2) {
+ if ((cmp(f2-size, f2) > 0) != sense) {
+ p2 = *EVAL(p2) = f2 - list1 + list2;
+ if (sense > 0)
+ reverse(f1, f2-size);
+ f1 = f2;
+ }
+ }
+ if (sense > 0)
+ reverse (f1, f2-size);
+ f1 = f2;
+ if (f2 < last || cmp(f2 - size, f2) > 0)
+ p2 = *EVAL(p2) = f2 - list1 + list2;
+ else
+ p2 = *EVAL(p2) = list2 + n*size;
+ }
+ }
+#else /* pairwise merge only. */
+ for (f1 = list1, p2 = list2; f1 < last; f1 += size2) {
+ p2 = *EVAL(p2) = p2 + size2;
+ if (cmp (f1, f1 + size) > 0)
+ swap(f1, f1 + size);
+ }
+#endif /* NATURAL */
+}
+
+/*
+ * This is to avoid out-of-bounds addresses in sorting the
+ * last 4 elements.
+ */
+static void
+insertionsort(unsigned char *a, size_t n, size_t size,
+ int (*cmp)(const void *, const void *))
+{
+ unsigned char *ai, *s, *t, *u, tmp;
+ size_t i;
+
+ for (ai = a+size; --n >= 1; ai += size)
+ for (t = ai; t > a; t -= size) {
+ u = t - size;
+ if (cmp(u, t) <= 0)
+ break;
+ swap(u, t);
+ }
+}
+#endif /*HAVE_MERGESORT*/
diff --git a/contrib/tools/yasm/libyasm/module.h b/contrib/tools/yasm/libyasm/module.h
index 220017deec..5e19e26ab1 100644
--- a/contrib/tools/yasm/libyasm/module.h
+++ b/contrib/tools/yasm/libyasm/module.h
@@ -1,82 +1,82 @@
-/*
- * YASM module loader header file
- *
- * Copyright (C) 2002-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef YASM_MODULE_H
-#define YASM_MODULE_H
-
-#ifndef YASM_LIB_DECL
-#define YASM_LIB_DECL
-#endif
-
-typedef enum yasm_module_type {
- YASM_MODULE_ARCH = 0,
- YASM_MODULE_DBGFMT,
- YASM_MODULE_OBJFMT,
- YASM_MODULE_LISTFMT,
- YASM_MODULE_PARSER,
- YASM_MODULE_PREPROC
-} yasm_module_type;
-
-YASM_LIB_DECL
-/*@dependent@*/ /*@null@*/ void *yasm_load_module
- (yasm_module_type type, const char *keyword);
-
-#define yasm_load_arch(keyword) \
- yasm_load_module(YASM_MODULE_ARCH, keyword)
-#define yasm_load_dbgfmt(keyword) \
- yasm_load_module(YASM_MODULE_DBGFMT, keyword)
-#define yasm_load_objfmt(keyword) \
- yasm_load_module(YASM_MODULE_OBJFMT, keyword)
-#define yasm_load_listfmt(keyword) \
- yasm_load_module(YASM_MODULE_LISTFMT, keyword)
-#define yasm_load_parser(keyword) \
- yasm_load_module(YASM_MODULE_PARSER, keyword)
-#define yasm_load_preproc(keyword) \
- yasm_load_module(YASM_MODULE_PREPROC, keyword)
-
-YASM_LIB_DECL
-void yasm_list_modules
- (yasm_module_type type,
- void (*printfunc) (const char *name, const char *keyword));
-
-#define yasm_list_arch(func) \
- yasm_list_modules(YASM_MODULE_ARCH, func)
-#define yasm_list_dbgfmt(func) \
- yasm_list_modules(YASM_MODULE_DBGFMT, func)
-#define yasm_list_objfmt(func) \
- yasm_list_modules(YASM_MODULE_OBJFMT, func)
-#define yasm_list_listfmt(func) \
- yasm_list_modules(YASM_MODULE_LISTFMT, func)
-#define yasm_list_parser(func) \
- yasm_list_modules(YASM_MODULE_PARSER, func)
-#define yasm_list_preproc(func) \
- yasm_list_modules(YASM_MODULE_PREPROC, func)
-
-YASM_LIB_DECL
-void yasm_register_module(yasm_module_type type, const char *keyword,
- void *data);
-
-#endif
+/*
+ * YASM module loader header file
+ *
+ * Copyright (C) 2002-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef YASM_MODULE_H
+#define YASM_MODULE_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+typedef enum yasm_module_type {
+ YASM_MODULE_ARCH = 0,
+ YASM_MODULE_DBGFMT,
+ YASM_MODULE_OBJFMT,
+ YASM_MODULE_LISTFMT,
+ YASM_MODULE_PARSER,
+ YASM_MODULE_PREPROC
+} yasm_module_type;
+
+YASM_LIB_DECL
+/*@dependent@*/ /*@null@*/ void *yasm_load_module
+ (yasm_module_type type, const char *keyword);
+
+#define yasm_load_arch(keyword) \
+ yasm_load_module(YASM_MODULE_ARCH, keyword)
+#define yasm_load_dbgfmt(keyword) \
+ yasm_load_module(YASM_MODULE_DBGFMT, keyword)
+#define yasm_load_objfmt(keyword) \
+ yasm_load_module(YASM_MODULE_OBJFMT, keyword)
+#define yasm_load_listfmt(keyword) \
+ yasm_load_module(YASM_MODULE_LISTFMT, keyword)
+#define yasm_load_parser(keyword) \
+ yasm_load_module(YASM_MODULE_PARSER, keyword)
+#define yasm_load_preproc(keyword) \
+ yasm_load_module(YASM_MODULE_PREPROC, keyword)
+
+YASM_LIB_DECL
+void yasm_list_modules
+ (yasm_module_type type,
+ void (*printfunc) (const char *name, const char *keyword));
+
+#define yasm_list_arch(func) \
+ yasm_list_modules(YASM_MODULE_ARCH, func)
+#define yasm_list_dbgfmt(func) \
+ yasm_list_modules(YASM_MODULE_DBGFMT, func)
+#define yasm_list_objfmt(func) \
+ yasm_list_modules(YASM_MODULE_OBJFMT, func)
+#define yasm_list_listfmt(func) \
+ yasm_list_modules(YASM_MODULE_LISTFMT, func)
+#define yasm_list_parser(func) \
+ yasm_list_modules(YASM_MODULE_PARSER, func)
+#define yasm_list_preproc(func) \
+ yasm_list_modules(YASM_MODULE_PREPROC, func)
+
+YASM_LIB_DECL
+void yasm_register_module(yasm_module_type type, const char *keyword,
+ void *data);
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/objfmt.h b/contrib/tools/yasm/libyasm/objfmt.h
index a8b5f8a161..624d698a99 100644
--- a/contrib/tools/yasm/libyasm/objfmt.h
+++ b/contrib/tools/yasm/libyasm/objfmt.h
@@ -1,128 +1,128 @@
-/**
- * \file libyasm/objfmt.h
- * \brief YASM object format module interface.
- *
- * \license
- * Copyright (C) 2001-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- * \endlicense
- */
-#ifndef YASM_OBJFMT_H
-#define YASM_OBJFMT_H
-
-#ifndef YASM_DOXYGEN
-/** Base #yasm_objfmt structure. Must be present as the first element in any
- * #yasm_objfmt implementation.
- */
-typedef struct yasm_objfmt_base {
- /** #yasm_objfmt_module implementation for this object format. */
- const struct yasm_objfmt_module *module;
-} yasm_objfmt_base;
-#endif
-
-/** Object format module interface. */
-struct yasm_objfmt_module {
- /** One-line description of the object format. */
- const char *name;
-
- /** Keyword used to select object format. */
- const char *keyword;
-
- /** Default output file extension (without the '.').
- * NULL means no extension, with no '.', while "" includes the '.'.
- */
- /*@null@*/ const char *extension;
-
- /** Default (starting) x86 BITS setting. This only appies to the x86
- * architecture; other architectures ignore this setting.
- */
- const unsigned char default_x86_mode_bits;
-
- /** If @ signs should be legal in identifiers. */
- const unsigned char id_at_ok;
-
- /** NULL-terminated list of debug format (yasm_dbgfmt) keywords that are
- * valid to use with this object format. The null debug format
- * (null_dbgfmt, "null") should always be in this list so it's possible to
- * have no debug output.
- */
- const char **dbgfmt_keywords;
-
- /** Default debug format keyword (set even if there's only one available to
- * use).
- */
- const char *default_dbgfmt_keyword;
-
- /** NULL-terminated list of directives. NULL if none. */
- /*@null@*/ const yasm_directive *directives;
-
- /** NULL-terminated list of standard macro lookups. NULL if none. */
- const yasm_stdmac *stdmacs;
-
- /** Create object format.
- * Module-level implementation of yasm_objfmt_create().
- * Call yasm_objfmt_create() instead of calling this function.
- * \param object object
- * \param a architecture in use
- * \return NULL if architecture/machine combination not supported.
- */
- /*@null@*/ /*@only@*/ yasm_objfmt * (*create) (yasm_object *object);
-
- /** Module-level implementation of yasm_objfmt_output().
- * Call yasm_objfmt_output() instead of calling this function.
- */
- void (*output) (yasm_object *o, FILE *f, int all_syms,
- yasm_errwarns *errwarns);
-
- /** Module-level implementation of yasm_objfmt_destroy().
- * Call yasm_objfmt_destroy() instead of calling this function.
- */
- void (*destroy) (/*@only@*/ yasm_objfmt *objfmt);
-
- /** Module-level implementation of yasm_objfmt_add_default_section().
- * Call yasm_objfmt_add_default_section() instead of calling this function.
- */
- yasm_section * (*add_default_section) (yasm_object *object);
-
- /** Module-level implementation of yasm_objfmt_init_new_section().
- * Call yasm_objfmt_init_new_section() instead of calling this function.
- */
- void (*init_new_section) (yasm_section *section, unsigned long line);
-
- /** Module-level implementation of yasm_objfmt_section_switch().
- * Call yasm_objfmt_section_switch() instead of calling this function.
- */
- /*@observer@*/ /*@null@*/ yasm_section *
- (*section_switch)(yasm_object *object, yasm_valparamhead *valparams,
- /*@null@*/ yasm_valparamhead *objext_valparams,
- unsigned long line);
-
- /** Module-level implementation of yasm_objfmt_get_special_sym().
- * Call yasm_objfmt_get_special_sym() instead of calling this function.
- */
- /*@observer@*/ /*@null@*/ yasm_symrec *
- (*get_special_sym)(yasm_object *object, const char *name,
- const char *parser);
+/**
+ * \file libyasm/objfmt.h
+ * \brief YASM object format module interface.
+ *
+ * \license
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * \endlicense
+ */
+#ifndef YASM_OBJFMT_H
+#define YASM_OBJFMT_H
+
+#ifndef YASM_DOXYGEN
+/** Base #yasm_objfmt structure. Must be present as the first element in any
+ * #yasm_objfmt implementation.
+ */
+typedef struct yasm_objfmt_base {
+ /** #yasm_objfmt_module implementation for this object format. */
+ const struct yasm_objfmt_module *module;
+} yasm_objfmt_base;
+#endif
+
+/** Object format module interface. */
+struct yasm_objfmt_module {
+ /** One-line description of the object format. */
+ const char *name;
+
+ /** Keyword used to select object format. */
+ const char *keyword;
+
+ /** Default output file extension (without the '.').
+ * NULL means no extension, with no '.', while "" includes the '.'.
+ */
+ /*@null@*/ const char *extension;
+
+ /** Default (starting) x86 BITS setting. This only appies to the x86
+ * architecture; other architectures ignore this setting.
+ */
+ const unsigned char default_x86_mode_bits;
+
+ /** If @ signs should be legal in identifiers. */
+ const unsigned char id_at_ok;
+
+ /** NULL-terminated list of debug format (yasm_dbgfmt) keywords that are
+ * valid to use with this object format. The null debug format
+ * (null_dbgfmt, "null") should always be in this list so it's possible to
+ * have no debug output.
+ */
+ const char **dbgfmt_keywords;
+
+ /** Default debug format keyword (set even if there's only one available to
+ * use).
+ */
+ const char *default_dbgfmt_keyword;
+
+ /** NULL-terminated list of directives. NULL if none. */
+ /*@null@*/ const yasm_directive *directives;
+
+ /** NULL-terminated list of standard macro lookups. NULL if none. */
+ const yasm_stdmac *stdmacs;
+
+ /** Create object format.
+ * Module-level implementation of yasm_objfmt_create().
+ * Call yasm_objfmt_create() instead of calling this function.
+ * \param object object
+ * \param a architecture in use
+ * \return NULL if architecture/machine combination not supported.
+ */
+ /*@null@*/ /*@only@*/ yasm_objfmt * (*create) (yasm_object *object);
+
+ /** Module-level implementation of yasm_objfmt_output().
+ * Call yasm_objfmt_output() instead of calling this function.
+ */
+ void (*output) (yasm_object *o, FILE *f, int all_syms,
+ yasm_errwarns *errwarns);
+
+ /** Module-level implementation of yasm_objfmt_destroy().
+ * Call yasm_objfmt_destroy() instead of calling this function.
+ */
+ void (*destroy) (/*@only@*/ yasm_objfmt *objfmt);
+
+ /** Module-level implementation of yasm_objfmt_add_default_section().
+ * Call yasm_objfmt_add_default_section() instead of calling this function.
+ */
+ yasm_section * (*add_default_section) (yasm_object *object);
+
+ /** Module-level implementation of yasm_objfmt_init_new_section().
+ * Call yasm_objfmt_init_new_section() instead of calling this function.
+ */
+ void (*init_new_section) (yasm_section *section, unsigned long line);
+
+ /** Module-level implementation of yasm_objfmt_section_switch().
+ * Call yasm_objfmt_section_switch() instead of calling this function.
+ */
+ /*@observer@*/ /*@null@*/ yasm_section *
+ (*section_switch)(yasm_object *object, yasm_valparamhead *valparams,
+ /*@null@*/ yasm_valparamhead *objext_valparams,
+ unsigned long line);
+
+ /** Module-level implementation of yasm_objfmt_get_special_sym().
+ * Call yasm_objfmt_get_special_sym() instead of calling this function.
+ */
+ /*@observer@*/ /*@null@*/ yasm_symrec *
+ (*get_special_sym)(yasm_object *object, const char *name,
+ const char *parser);
/**
* --replace params
@@ -132,94 +132,94 @@ struct yasm_objfmt_module {
* Number of elements in replace_map
*/
int replace_map_size;
-};
-
-/** Create object format.
- * \param module object format module
- * \param object object
- * \return NULL if architecture/machine combination not supported.
- */
-/*@null@*/ /*@only@*/ yasm_objfmt *yasm_objfmt_create
- (const yasm_objfmt_module *module, yasm_object *object);
-
-/** Write out (post-optimized) sections to the object file.
- * This function may call yasm_symrec_* functions as necessary (including
- * yasm_symrec_traverse()) to retrieve symbolic information.
- * \param object object
- * \param f output object file
- * \param all_syms if nonzero, all symbols should be included in
- * the object file
- * \param errwarns error/warning set
- * \note Errors and warnings are stored into errwarns.
- */
-void yasm_objfmt_output(yasm_object *object, FILE *f, int all_syms,
- yasm_errwarns *errwarns);
-
-/** Cleans up any allocated object format memory.
- * \param objfmt object format
- */
-void yasm_objfmt_destroy(/*@only@*/ yasm_objfmt *objfmt);
-
-/** Add a default section to an object.
- * \param object object
- * \return Default section.
- */
-yasm_section *yasm_objfmt_add_default_section(yasm_object *object);
-
-/** Initialize the object-format specific portion of a section. Called
- * by yasm_object_get_general(); in general should not be directly called.
- * \param section section
- * \param line virtual line (from yasm_linemap)
- */
-void yasm_objfmt_init_new_section(yasm_object *object, unsigned long line);
-
-/** Switch object file sections. The first val of the valparams should
- * be the section name. Calls yasm_object_get_general() to actually get
- * the section.
- * \param object object
- * \param valparams value/parameters
- * \param objext_valparams object format-specific value/parameters
- * \param line virtual line (from yasm_linemap)
- * \return NULL on error, otherwise new section.
- */
-/*@observer@*/ /*@null@*/ yasm_section *yasm_objfmt_section_switch
- (yasm_object *object, yasm_valparamhead *valparams,
- /*@null@*/ yasm_valparamhead *objext_valparams, unsigned long line);
-
-/** Get a special symbol. Special symbols are generally used to generate
- * special relocation types via the WRT mechanism.
- * \param object object
- * \param name symbol name (not including any parser-specific prefix)
- * \param parser parser keyword
- * \return NULL if unrecognized, otherwise special symbol.
- */
-/*@observer@*/ /*@null@*/ yasm_symrec *yasm_objfmt_get_special_sym
- (yasm_object *object, const char *name, const char *parser);
-
-#ifndef YASM_DOXYGEN
-
-/* Inline macro implementations for objfmt functions */
-
-#define yasm_objfmt_create(module, object) module->create(object)
-
-#define yasm_objfmt_output(object, f, all_syms, ews) \
- ((yasm_objfmt_base *)((object)->objfmt))->module->output \
- (object, f, all_syms, ews)
-#define yasm_objfmt_destroy(objfmt) \
- ((yasm_objfmt_base *)objfmt)->module->destroy(objfmt)
-#define yasm_objfmt_section_switch(object, vpms, oe_vpms, line) \
- ((yasm_objfmt_base *)((object)->objfmt))->module->section_switch \
- (object, vpms, oe_vpms, line)
-#define yasm_objfmt_add_default_section(object) \
- ((yasm_objfmt_base *)((object)->objfmt))->module->add_default_section \
- (object)
-#define yasm_objfmt_init_new_section(section, line) \
- ((yasm_objfmt_base *)((object)->objfmt))->module->init_new_section \
- (section, line)
-#define yasm_objfmt_get_special_sym(object, name, parser) \
- ((yasm_objfmt_base *)((object)->objfmt))->module->get_special_sym \
- (object, name, parser)
-
-#endif
-
-#endif
+};
+
+/** Create object format.
+ * \param module object format module
+ * \param object object
+ * \return NULL if architecture/machine combination not supported.
+ */
+/*@null@*/ /*@only@*/ yasm_objfmt *yasm_objfmt_create
+ (const yasm_objfmt_module *module, yasm_object *object);
+
+/** Write out (post-optimized) sections to the object file.
+ * This function may call yasm_symrec_* functions as necessary (including
+ * yasm_symrec_traverse()) to retrieve symbolic information.
+ * \param object object
+ * \param f output object file
+ * \param all_syms if nonzero, all symbols should be included in
+ * the object file
+ * \param errwarns error/warning set
+ * \note Errors and warnings are stored into errwarns.
+ */
+void yasm_objfmt_output(yasm_object *object, FILE *f, int all_syms,
+ yasm_errwarns *errwarns);
+
+/** Cleans up any allocated object format memory.
+ * \param objfmt object format
+ */
+void yasm_objfmt_destroy(/*@only@*/ yasm_objfmt *objfmt);
+
+/** Add a default section to an object.
+ * \param object object
+ * \return Default section.
+ */
+yasm_section *yasm_objfmt_add_default_section(yasm_object *object);
+
+/** Initialize the object-format specific portion of a section. Called
+ * by yasm_object_get_general(); in general should not be directly called.
+ * \param section section
+ * \param line virtual line (from yasm_linemap)
+ */
+void yasm_objfmt_init_new_section(yasm_object *object, unsigned long line);
+
+/** Switch object file sections. The first val of the valparams should
+ * be the section name. Calls yasm_object_get_general() to actually get
+ * the section.
+ * \param object object
+ * \param valparams value/parameters
+ * \param objext_valparams object format-specific value/parameters
+ * \param line virtual line (from yasm_linemap)
+ * \return NULL on error, otherwise new section.
+ */
+/*@observer@*/ /*@null@*/ yasm_section *yasm_objfmt_section_switch
+ (yasm_object *object, yasm_valparamhead *valparams,
+ /*@null@*/ yasm_valparamhead *objext_valparams, unsigned long line);
+
+/** Get a special symbol. Special symbols are generally used to generate
+ * special relocation types via the WRT mechanism.
+ * \param object object
+ * \param name symbol name (not including any parser-specific prefix)
+ * \param parser parser keyword
+ * \return NULL if unrecognized, otherwise special symbol.
+ */
+/*@observer@*/ /*@null@*/ yasm_symrec *yasm_objfmt_get_special_sym
+ (yasm_object *object, const char *name, const char *parser);
+
+#ifndef YASM_DOXYGEN
+
+/* Inline macro implementations for objfmt functions */
+
+#define yasm_objfmt_create(module, object) module->create(object)
+
+#define yasm_objfmt_output(object, f, all_syms, ews) \
+ ((yasm_objfmt_base *)((object)->objfmt))->module->output \
+ (object, f, all_syms, ews)
+#define yasm_objfmt_destroy(objfmt) \
+ ((yasm_objfmt_base *)objfmt)->module->destroy(objfmt)
+#define yasm_objfmt_section_switch(object, vpms, oe_vpms, line) \
+ ((yasm_objfmt_base *)((object)->objfmt))->module->section_switch \
+ (object, vpms, oe_vpms, line)
+#define yasm_objfmt_add_default_section(object) \
+ ((yasm_objfmt_base *)((object)->objfmt))->module->add_default_section \
+ (object)
+#define yasm_objfmt_init_new_section(section, line) \
+ ((yasm_objfmt_base *)((object)->objfmt))->module->init_new_section \
+ (section, line)
+#define yasm_objfmt_get_special_sym(object, name, parser) \
+ ((yasm_objfmt_base *)((object)->objfmt))->module->get_special_sym \
+ (object, name, parser)
+
+#endif
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/parser.h b/contrib/tools/yasm/libyasm/parser.h
index 93d4d33232..568560f671 100644
--- a/contrib/tools/yasm/libyasm/parser.h
+++ b/contrib/tools/yasm/libyasm/parser.h
@@ -1,67 +1,67 @@
-/**
- * \file libyasm/parser.h
- * \brief YASM parser module interface.
- *
- * \license
- * Copyright (C) 2001-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- * \endlicense
- */
-#ifndef YASM_PARSER_H
-#define YASM_PARSER_H
-
-/** YASM parser module interface. The "front end" of the assembler. */
-typedef struct yasm_parser_module {
- /** One-line description of the parser */
- const char *name;
-
- /** Keyword used to select parser on the command line */
- const char *keyword;
-
- /** NULL-terminated list of preprocessors that are valid to use with this
- * parser. The raw preprocessor (raw_preproc) should always be in this
- * list so it's always possible to have no preprocessing done.
- */
- const char **preproc_keywords;
-
- /** Default preprocessor. */
- const char *default_preproc_keyword;
-
- /** NULL-terminated list of standard macro lookups. NULL if none. */
- const yasm_stdmac *stdmacs;
-
- /** Parse a source file into an object.
- * \param object object to parse into (already created)
- * \param pp preprocessor
- * \param save_input nonzero if the parser should save the original
- * lines of source into the object's linemap (via
- * yasm_linemap_add_data()).
- * \param errwarns error/warning set
- * \note Parse errors and warnings are stored into errwarns.
- */
- void (*do_parse)
- (yasm_object *object, yasm_preproc *pp, int save_input,
- yasm_linemap *linemap, yasm_errwarns *errwarns);
-} yasm_parser_module;
-
-#endif
+/**
+ * \file libyasm/parser.h
+ * \brief YASM parser module interface.
+ *
+ * \license
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * \endlicense
+ */
+#ifndef YASM_PARSER_H
+#define YASM_PARSER_H
+
+/** YASM parser module interface. The "front end" of the assembler. */
+typedef struct yasm_parser_module {
+ /** One-line description of the parser */
+ const char *name;
+
+ /** Keyword used to select parser on the command line */
+ const char *keyword;
+
+ /** NULL-terminated list of preprocessors that are valid to use with this
+ * parser. The raw preprocessor (raw_preproc) should always be in this
+ * list so it's always possible to have no preprocessing done.
+ */
+ const char **preproc_keywords;
+
+ /** Default preprocessor. */
+ const char *default_preproc_keyword;
+
+ /** NULL-terminated list of standard macro lookups. NULL if none. */
+ const yasm_stdmac *stdmacs;
+
+ /** Parse a source file into an object.
+ * \param object object to parse into (already created)
+ * \param pp preprocessor
+ * \param save_input nonzero if the parser should save the original
+ * lines of source into the object's linemap (via
+ * yasm_linemap_add_data()).
+ * \param errwarns error/warning set
+ * \note Parse errors and warnings are stored into errwarns.
+ */
+ void (*do_parse)
+ (yasm_object *object, yasm_preproc *pp, int save_input,
+ yasm_linemap *linemap, yasm_errwarns *errwarns);
+} yasm_parser_module;
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/phash.c b/contrib/tools/yasm/libyasm/phash.c
index 29e073aae1..518d5d38cc 100644
--- a/contrib/tools/yasm/libyasm/phash.c
+++ b/contrib/tools/yasm/libyasm/phash.c
@@ -1,268 +1,268 @@
-/* Modified for use with yasm by Peter Johnson. */
-#include "util.h"
-
-/*
---------------------------------------------------------------------
-lookupa.c, by Bob Jenkins, December 1996. Same as lookup2.c
-Use this code however you wish. Public Domain. No warranty.
-Source is http://burtleburtle.net/bob/c/lookupa.c
---------------------------------------------------------------------
-*/
-#include "phash.h"
-
-#define ub4 unsigned long
-
-#define hashsize(n) ((ub4)1<<(n))
-#define hashmask(n) (hashsize(n)-1)
-
-/*
---------------------------------------------------------------------
-mix -- mix 3 32-bit values reversibly.
-For every delta with one or two bit set, and the deltas of all three
- high bits or all three low bits, whether the original value of a,b,c
- is almost all zero or is uniformly distributed,
-* If mix() is run forward or backward, at least 32 bits in a,b,c
- have at least 1/4 probability of changing.
-* If mix() is run forward, every bit of c will change between 1/3 and
- 2/3 of the time. (Well, 22/100 and 78/100 for some 2-bit deltas.)
-mix() was built out of 36 single-cycle latency instructions in a
- structure that could supported 2x parallelism, like so:
- a -= b;
- a -= c; x = (c>>13);
- b -= c; a ^= x;
- b -= a; x = (a<<8);
- c -= a; b ^= x;
- c -= b; x = (b>>13);
- ...
- Unfortunately, superscalar Pentiums and Sparcs can't take advantage
- of that parallelism. They've also turned some of those single-cycle
- latency instructions into multi-cycle latency instructions. Still,
- this is the fastest good hash I could find. There were about 2^^68
- to choose from. I only looked at a billion or so.
---------------------------------------------------------------------
-*/
-#define mix(a,b,c) \
-{ \
- a -= b; a -= c; a ^= (c>>13); \
- a &= 0xffffffff; \
- b -= c; b -= a; b ^= (a<<8); \
- b &= 0xffffffff; \
- c -= a; c -= b; c ^= (b>>13); \
- c &= 0xffffffff; \
- a -= b; a -= c; a ^= (c>>12); \
- a &= 0xffffffff; \
- b -= c; b -= a; b ^= (a<<16); \
- b &= 0xffffffff; \
- c -= a; c -= b; c ^= (b>>5); \
- c &= 0xffffffff; \
- a -= b; a -= c; a ^= (c>>3); \
- a &= 0xffffffff; \
- b -= c; b -= a; b ^= (a<<10); \
- b &= 0xffffffff; \
- c -= a; c -= b; c ^= (b>>15); \
- c &= 0xffffffff; \
-}
-
-/*
---------------------------------------------------------------------
-lookup() -- hash a variable-length key into a 32-bit value
- k : the key (the unaligned variable-length array of bytes)
- len : the length of the key, counting by bytes
- level : can be any 4-byte value
-Returns a 32-bit value. Every bit of the key affects every bit of
-the return value. Every 1-bit and 2-bit delta achieves avalanche.
-About 6len+35 instructions.
-
-The best hash table sizes are powers of 2. There is no need to do
-mod a prime (mod is sooo slow!). If you need less than 32 bits,
-use a bitmask. For example, if you need only 10 bits, do
- h = (h & hashmask(10));
-In which case, the hash table should have hashsize(10) elements.
-
-If you are hashing n strings (ub1 **)k, do it like this:
- for (i=0, h=0; i<n; ++i) h = lookup( k[i], len[i], h);
-
-By Bob Jenkins, 1996. bob_jenkins@burtleburtle.net. You may use this
-code any way you wish, private, educational, or commercial.
-
-See http://burtleburtle.net/bob/hash/evahash.html
-Use for hash table lookup, or anything where one collision in 2^32 is
-acceptable. Do NOT use for cryptographic purposes.
---------------------------------------------------------------------
-*/
-
-unsigned long
-phash_lookup(
- register const char *sk, /* the key */
- register size_t length, /* the length of the key */
- register unsigned long level) /* the previous hash, or an arbitrary value */
-{
+/* Modified for use with yasm by Peter Johnson. */
+#include "util.h"
+
+/*
+--------------------------------------------------------------------
+lookupa.c, by Bob Jenkins, December 1996. Same as lookup2.c
+Use this code however you wish. Public Domain. No warranty.
+Source is http://burtleburtle.net/bob/c/lookupa.c
+--------------------------------------------------------------------
+*/
+#include "phash.h"
+
+#define ub4 unsigned long
+
+#define hashsize(n) ((ub4)1<<(n))
+#define hashmask(n) (hashsize(n)-1)
+
+/*
+--------------------------------------------------------------------
+mix -- mix 3 32-bit values reversibly.
+For every delta with one or two bit set, and the deltas of all three
+ high bits or all three low bits, whether the original value of a,b,c
+ is almost all zero or is uniformly distributed,
+* If mix() is run forward or backward, at least 32 bits in a,b,c
+ have at least 1/4 probability of changing.
+* If mix() is run forward, every bit of c will change between 1/3 and
+ 2/3 of the time. (Well, 22/100 and 78/100 for some 2-bit deltas.)
+mix() was built out of 36 single-cycle latency instructions in a
+ structure that could supported 2x parallelism, like so:
+ a -= b;
+ a -= c; x = (c>>13);
+ b -= c; a ^= x;
+ b -= a; x = (a<<8);
+ c -= a; b ^= x;
+ c -= b; x = (b>>13);
+ ...
+ Unfortunately, superscalar Pentiums and Sparcs can't take advantage
+ of that parallelism. They've also turned some of those single-cycle
+ latency instructions into multi-cycle latency instructions. Still,
+ this is the fastest good hash I could find. There were about 2^^68
+ to choose from. I only looked at a billion or so.
+--------------------------------------------------------------------
+*/
+#define mix(a,b,c) \
+{ \
+ a -= b; a -= c; a ^= (c>>13); \
+ a &= 0xffffffff; \
+ b -= c; b -= a; b ^= (a<<8); \
+ b &= 0xffffffff; \
+ c -= a; c -= b; c ^= (b>>13); \
+ c &= 0xffffffff; \
+ a -= b; a -= c; a ^= (c>>12); \
+ a &= 0xffffffff; \
+ b -= c; b -= a; b ^= (a<<16); \
+ b &= 0xffffffff; \
+ c -= a; c -= b; c ^= (b>>5); \
+ c &= 0xffffffff; \
+ a -= b; a -= c; a ^= (c>>3); \
+ a &= 0xffffffff; \
+ b -= c; b -= a; b ^= (a<<10); \
+ b &= 0xffffffff; \
+ c -= a; c -= b; c ^= (b>>15); \
+ c &= 0xffffffff; \
+}
+
+/*
+--------------------------------------------------------------------
+lookup() -- hash a variable-length key into a 32-bit value
+ k : the key (the unaligned variable-length array of bytes)
+ len : the length of the key, counting by bytes
+ level : can be any 4-byte value
+Returns a 32-bit value. Every bit of the key affects every bit of
+the return value. Every 1-bit and 2-bit delta achieves avalanche.
+About 6len+35 instructions.
+
+The best hash table sizes are powers of 2. There is no need to do
+mod a prime (mod is sooo slow!). If you need less than 32 bits,
+use a bitmask. For example, if you need only 10 bits, do
+ h = (h & hashmask(10));
+In which case, the hash table should have hashsize(10) elements.
+
+If you are hashing n strings (ub1 **)k, do it like this:
+ for (i=0, h=0; i<n; ++i) h = lookup( k[i], len[i], h);
+
+By Bob Jenkins, 1996. bob_jenkins@burtleburtle.net. You may use this
+code any way you wish, private, educational, or commercial.
+
+See http://burtleburtle.net/bob/hash/evahash.html
+Use for hash table lookup, or anything where one collision in 2^32 is
+acceptable. Do NOT use for cryptographic purposes.
+--------------------------------------------------------------------
+*/
+
+unsigned long
+phash_lookup(
+ register const char *sk, /* the key */
+ register size_t length, /* the length of the key */
+ register unsigned long level) /* the previous hash, or an arbitrary value */
+{
unsigned long a,b,c;
size_t len;
const unsigned char *k = (const unsigned char *)sk;
-
- /* Set up the internal state */
- len = length;
- a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
- c = level; /* the previous hash value */
-
- /*---------------------------------------- handle most of the key */
- while (len >= 12)
- {
- a += (k[0] +((ub4)k[1]<<8) +((ub4)k[2]<<16) +((ub4)k[3]<<24));
- a &= 0xffffffff;
- b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24));
- b &= 0xffffffff;
- c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24));
- c &= 0xffffffff;
- mix(a,b,c);
- k += 12; len -= 12;
- }
-
- /*------------------------------------- handle the last 11 bytes */
- c += (ub4)length;
- switch(len) /* all the case statements fall through */
- {
- case 11: c+=((ub4)k[10]<<24);
- case 10: c+=((ub4)k[9]<<16);
- case 9 : c+=((ub4)k[8]<<8);
- c &= 0xffffffff;
- /* the first byte of c is reserved for the length */
- case 8 : b+=((ub4)k[7]<<24);
- case 7 : b+=((ub4)k[6]<<16);
- case 6 : b+=((ub4)k[5]<<8);
- case 5 : b+=k[4];
- b &= 0xffffffff;
- case 4 : a+=((ub4)k[3]<<24);
- case 3 : a+=((ub4)k[2]<<16);
- case 2 : a+=((ub4)k[1]<<8);
- case 1 : a+=k[0];
- a &= 0xffffffff;
- /* case 0: nothing left to add */
- }
- mix(a,b,c);
- /*-------------------------------------------- report the result */
- return c;
-}
-
-
-/*
---------------------------------------------------------------------
-mixc -- mixc 8 4-bit values as quickly and thoroughly as possible.
-Repeating mix() three times achieves avalanche.
-Repeating mix() four times eliminates all funnels and all
- characteristics stronger than 2^{-11}.
---------------------------------------------------------------------
-*/
-#define mixc(a,b,c,d,e,f,g,h) \
-{ \
- a^=b<<11; d+=a; b+=c; \
- b^=c>>2; e+=b; c+=d; \
- c^=d<<8; f+=c; d+=e; \
- d^=e>>16; g+=d; e+=f; \
- e^=f<<10; h+=e; f+=g; \
- f^=g>>4; a+=f; g+=h; \
- g^=h<<8; b+=g; h+=a; \
- h^=a>>9; c+=h; a+=b; \
-}
-
-/*
---------------------------------------------------------------------
-checksum() -- hash a variable-length key into a 256-bit value
- k : the key (the unaligned variable-length array of bytes)
- len : the length of the key, counting by bytes
- state : an array of CHECKSTATE 4-byte values (256 bits)
-The state is the checksum. Every bit of the key affects every bit of
-the state. There are no funnels. About 112+6.875len instructions.
-
-If you are hashing n strings (ub1 **)k, do it like this:
- for (i=0; i<8; ++i) state[i] = 0x9e3779b9;
- for (i=0, h=0; i<n; ++i) checksum( k[i], len[i], state);
-
-(c) Bob Jenkins, 1996. bob_jenkins@burtleburtle.net. You may use this
-code any way you wish, private, educational, or commercial, as long
-as this whole comment accompanies it.
-
-See http://burtleburtle.net/bob/hash/evahash.html
-Use to detect changes between revisions of documents, assuming nobody
-is trying to cause collisions. Do NOT use for cryptography.
---------------------------------------------------------------------
-*/
-void
-phash_checksum(
- register const char *sk,
- register size_t len,
- register unsigned long *state)
-{
+
+ /* Set up the internal state */
+ len = length;
+ a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
+ c = level; /* the previous hash value */
+
+ /*---------------------------------------- handle most of the key */
+ while (len >= 12)
+ {
+ a += (k[0] +((ub4)k[1]<<8) +((ub4)k[2]<<16) +((ub4)k[3]<<24));
+ a &= 0xffffffff;
+ b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24));
+ b &= 0xffffffff;
+ c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24));
+ c &= 0xffffffff;
+ mix(a,b,c);
+ k += 12; len -= 12;
+ }
+
+ /*------------------------------------- handle the last 11 bytes */
+ c += (ub4)length;
+ switch(len) /* all the case statements fall through */
+ {
+ case 11: c+=((ub4)k[10]<<24);
+ case 10: c+=((ub4)k[9]<<16);
+ case 9 : c+=((ub4)k[8]<<8);
+ c &= 0xffffffff;
+ /* the first byte of c is reserved for the length */
+ case 8 : b+=((ub4)k[7]<<24);
+ case 7 : b+=((ub4)k[6]<<16);
+ case 6 : b+=((ub4)k[5]<<8);
+ case 5 : b+=k[4];
+ b &= 0xffffffff;
+ case 4 : a+=((ub4)k[3]<<24);
+ case 3 : a+=((ub4)k[2]<<16);
+ case 2 : a+=((ub4)k[1]<<8);
+ case 1 : a+=k[0];
+ a &= 0xffffffff;
+ /* case 0: nothing left to add */
+ }
+ mix(a,b,c);
+ /*-------------------------------------------- report the result */
+ return c;
+}
+
+
+/*
+--------------------------------------------------------------------
+mixc -- mixc 8 4-bit values as quickly and thoroughly as possible.
+Repeating mix() three times achieves avalanche.
+Repeating mix() four times eliminates all funnels and all
+ characteristics stronger than 2^{-11}.
+--------------------------------------------------------------------
+*/
+#define mixc(a,b,c,d,e,f,g,h) \
+{ \
+ a^=b<<11; d+=a; b+=c; \
+ b^=c>>2; e+=b; c+=d; \
+ c^=d<<8; f+=c; d+=e; \
+ d^=e>>16; g+=d; e+=f; \
+ e^=f<<10; h+=e; f+=g; \
+ f^=g>>4; a+=f; g+=h; \
+ g^=h<<8; b+=g; h+=a; \
+ h^=a>>9; c+=h; a+=b; \
+}
+
+/*
+--------------------------------------------------------------------
+checksum() -- hash a variable-length key into a 256-bit value
+ k : the key (the unaligned variable-length array of bytes)
+ len : the length of the key, counting by bytes
+ state : an array of CHECKSTATE 4-byte values (256 bits)
+The state is the checksum. Every bit of the key affects every bit of
+the state. There are no funnels. About 112+6.875len instructions.
+
+If you are hashing n strings (ub1 **)k, do it like this:
+ for (i=0; i<8; ++i) state[i] = 0x9e3779b9;
+ for (i=0, h=0; i<n; ++i) checksum( k[i], len[i], state);
+
+(c) Bob Jenkins, 1996. bob_jenkins@burtleburtle.net. You may use this
+code any way you wish, private, educational, or commercial, as long
+as this whole comment accompanies it.
+
+See http://burtleburtle.net/bob/hash/evahash.html
+Use to detect changes between revisions of documents, assuming nobody
+is trying to cause collisions. Do NOT use for cryptography.
+--------------------------------------------------------------------
+*/
+void
+phash_checksum(
+ register const char *sk,
+ register size_t len,
+ register unsigned long *state)
+{
unsigned long a,b,c,d,e,f,g,h;
size_t length;
const unsigned char *k = (const unsigned char *)sk;
-
- /* Use the length and level; add in the golden ratio. */
- length = len;
- a=state[0]; b=state[1]; c=state[2]; d=state[3];
- e=state[4]; f=state[5]; g=state[6]; h=state[7];
-
- /*---------------------------------------- handle most of the key */
- while (len >= 32)
- {
- a += (k[0] +(k[1]<<8) +(k[2]<<16) +(k[3]<<24));
- b += (k[4] +(k[5]<<8) +(k[6]<<16) +(k[7]<<24));
- c += (k[8] +(k[9]<<8) +(k[10]<<16)+(k[11]<<24));
- d += (k[12]+(k[13]<<8)+(k[14]<<16)+(k[15]<<24));
- e += (k[16]+(k[17]<<8)+(k[18]<<16)+(k[19]<<24));
- f += (k[20]+(k[21]<<8)+(k[22]<<16)+(k[23]<<24));
- g += (k[24]+(k[25]<<8)+(k[26]<<16)+(k[27]<<24));
- h += (k[28]+(k[29]<<8)+(k[30]<<16)+(k[31]<<24));
- mixc(a,b,c,d,e,f,g,h);
- mixc(a,b,c,d,e,f,g,h);
- mixc(a,b,c,d,e,f,g,h);
- mixc(a,b,c,d,e,f,g,h);
- k += 32; len -= 32;
- }
-
- /*------------------------------------- handle the last 31 bytes */
- h += (ub4)length;
- switch(len)
- {
- case 31: h+=(k[30]<<24);
- case 30: h+=(k[29]<<16);
- case 29: h+=(k[28]<<8);
- case 28: g+=(k[27]<<24);
- case 27: g+=(k[26]<<16);
- case 26: g+=(k[25]<<8);
- case 25: g+=k[24];
- case 24: f+=(k[23]<<24);
- case 23: f+=(k[22]<<16);
- case 22: f+=(k[21]<<8);
- case 21: f+=k[20];
- case 20: e+=(k[19]<<24);
- case 19: e+=(k[18]<<16);
- case 18: e+=(k[17]<<8);
- case 17: e+=k[16];
- case 16: d+=(k[15]<<24);
- case 15: d+=(k[14]<<16);
- case 14: d+=(k[13]<<8);
- case 13: d+=k[12];
- case 12: c+=(k[11]<<24);
- case 11: c+=(k[10]<<16);
- case 10: c+=(k[9]<<8);
- case 9 : c+=k[8];
- case 8 : b+=(k[7]<<24);
- case 7 : b+=(k[6]<<16);
- case 6 : b+=(k[5]<<8);
- case 5 : b+=k[4];
- case 4 : a+=(k[3]<<24);
- case 3 : a+=(k[2]<<16);
- case 2 : a+=(k[1]<<8);
- case 1 : a+=k[0];
- }
- mixc(a,b,c,d,e,f,g,h);
- mixc(a,b,c,d,e,f,g,h);
- mixc(a,b,c,d,e,f,g,h);
- mixc(a,b,c,d,e,f,g,h);
-
- /*-------------------------------------------- report the result */
- state[0]=a; state[1]=b; state[2]=c; state[3]=d;
- state[4]=e; state[5]=f; state[6]=g; state[7]=h;
-}
+
+ /* Use the length and level; add in the golden ratio. */
+ length = len;
+ a=state[0]; b=state[1]; c=state[2]; d=state[3];
+ e=state[4]; f=state[5]; g=state[6]; h=state[7];
+
+ /*---------------------------------------- handle most of the key */
+ while (len >= 32)
+ {
+ a += (k[0] +(k[1]<<8) +(k[2]<<16) +(k[3]<<24));
+ b += (k[4] +(k[5]<<8) +(k[6]<<16) +(k[7]<<24));
+ c += (k[8] +(k[9]<<8) +(k[10]<<16)+(k[11]<<24));
+ d += (k[12]+(k[13]<<8)+(k[14]<<16)+(k[15]<<24));
+ e += (k[16]+(k[17]<<8)+(k[18]<<16)+(k[19]<<24));
+ f += (k[20]+(k[21]<<8)+(k[22]<<16)+(k[23]<<24));
+ g += (k[24]+(k[25]<<8)+(k[26]<<16)+(k[27]<<24));
+ h += (k[28]+(k[29]<<8)+(k[30]<<16)+(k[31]<<24));
+ mixc(a,b,c,d,e,f,g,h);
+ mixc(a,b,c,d,e,f,g,h);
+ mixc(a,b,c,d,e,f,g,h);
+ mixc(a,b,c,d,e,f,g,h);
+ k += 32; len -= 32;
+ }
+
+ /*------------------------------------- handle the last 31 bytes */
+ h += (ub4)length;
+ switch(len)
+ {
+ case 31: h+=(k[30]<<24);
+ case 30: h+=(k[29]<<16);
+ case 29: h+=(k[28]<<8);
+ case 28: g+=(k[27]<<24);
+ case 27: g+=(k[26]<<16);
+ case 26: g+=(k[25]<<8);
+ case 25: g+=k[24];
+ case 24: f+=(k[23]<<24);
+ case 23: f+=(k[22]<<16);
+ case 22: f+=(k[21]<<8);
+ case 21: f+=k[20];
+ case 20: e+=(k[19]<<24);
+ case 19: e+=(k[18]<<16);
+ case 18: e+=(k[17]<<8);
+ case 17: e+=k[16];
+ case 16: d+=(k[15]<<24);
+ case 15: d+=(k[14]<<16);
+ case 14: d+=(k[13]<<8);
+ case 13: d+=k[12];
+ case 12: c+=(k[11]<<24);
+ case 11: c+=(k[10]<<16);
+ case 10: c+=(k[9]<<8);
+ case 9 : c+=k[8];
+ case 8 : b+=(k[7]<<24);
+ case 7 : b+=(k[6]<<16);
+ case 6 : b+=(k[5]<<8);
+ case 5 : b+=k[4];
+ case 4 : a+=(k[3]<<24);
+ case 3 : a+=(k[2]<<16);
+ case 2 : a+=(k[1]<<8);
+ case 1 : a+=k[0];
+ }
+ mixc(a,b,c,d,e,f,g,h);
+ mixc(a,b,c,d,e,f,g,h);
+ mixc(a,b,c,d,e,f,g,h);
+ mixc(a,b,c,d,e,f,g,h);
+
+ /*-------------------------------------------- report the result */
+ state[0]=a; state[1]=b; state[2]=c; state[3]=d;
+ state[4]=e; state[5]=f; state[6]=g; state[7]=h;
+}
diff --git a/contrib/tools/yasm/libyasm/phash.h b/contrib/tools/yasm/libyasm/phash.h
index 2273a5df20..5bf105f0dd 100644
--- a/contrib/tools/yasm/libyasm/phash.h
+++ b/contrib/tools/yasm/libyasm/phash.h
@@ -1,19 +1,19 @@
-/* Modified for use with yasm by Peter Johnson. */
-/*
-------------------------------------------------------------------------------
-By Bob Jenkins, September 1996.
-lookupa.h, a hash function for table lookup, same function as lookup.c.
-Use this code in any way you wish. Public Domain. It has no warranty.
-Source is http://burtleburtle.net/bob/c/lookupa.h
-------------------------------------------------------------------------------
-*/
-
-#ifndef YASM_LIB_DECL
-#define YASM_LIB_DECL
-#endif
-
-YASM_LIB_DECL
-unsigned long phash_lookup(const char *k, size_t length,
- unsigned long level);
-YASM_LIB_DECL
-void phash_checksum(const char *k, size_t length, unsigned long *state);
+/* Modified for use with yasm by Peter Johnson. */
+/*
+------------------------------------------------------------------------------
+By Bob Jenkins, September 1996.
+lookupa.h, a hash function for table lookup, same function as lookup.c.
+Use this code in any way you wish. Public Domain. It has no warranty.
+Source is http://burtleburtle.net/bob/c/lookupa.h
+------------------------------------------------------------------------------
+*/
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+YASM_LIB_DECL
+unsigned long phash_lookup(const char *k, size_t length,
+ unsigned long level);
+YASM_LIB_DECL
+void phash_checksum(const char *k, size_t length, unsigned long *state);
diff --git a/contrib/tools/yasm/libyasm/preproc.h b/contrib/tools/yasm/libyasm/preproc.h
index 751b19e4b0..7c0845c431 100644
--- a/contrib/tools/yasm/libyasm/preproc.h
+++ b/contrib/tools/yasm/libyasm/preproc.h
@@ -1,210 +1,210 @@
-/**
- * \file libyasm/preproc.h
- * \brief YASM preprocessor module interface.
- *
- * \license
- * Copyright (C) 2001-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- * \endlicense
- */
-#ifndef YASM_PREPROC_H
-#define YASM_PREPROC_H
-
-#ifndef YASM_DOXYGEN
-/** Base #yasm_preproc structure. Must be present as the first element in any
- * #yasm_preproc implementation.
- */
-typedef struct yasm_preproc_base {
- /** #yasm_preproc_module implementation for this preprocessor. */
- const struct yasm_preproc_module *module;
-} yasm_preproc_base;
-#endif
-
-/** YASM preprocesor module interface. */
-typedef struct yasm_preproc_module {
- /** One-line description of the preprocessor. */
- const char *name;
-
- /** Keyword used to select preprocessor on the command line. */
- const char *keyword;
-
- /** Create preprocessor.
- * Module-level implementation of yasm_preproc_create().
- * Call yasm_preproc_create() instead of calling this function.
- *
- * \param in_filename initial starting filename, or "-" to read from
- * stdin
- * \param symtab symbol table (may be NULL if none)
- * \param lm line mapping repository
- * \param errwarns error/warnning set.
- * \return New preprocessor.
- *
- * \note Any preprocessor errors and warnings are stored into errwarns.
- */
- /*@only@*/ yasm_preproc * (*create) (const char *in_filename,
- yasm_symtab *symtab,
- yasm_linemap *lm,
- yasm_errwarns *errwarns);
-
- /** Module-level implementation of yasm_preproc_destroy().
- * Call yasm_preproc_destroy() instead of calling this function.
- */
- void (*destroy) (/*@only@*/ yasm_preproc *preproc);
-
- /** Module-level implementation of yasm_preproc_get_line().
- * Call yasm_preproc_get_line() instead of calling this function.
- */
- char * (*get_line) (yasm_preproc *preproc);
-
- /** Module-level implementation of yasm_preproc_get_included_file().
- * Call yasm_preproc_get_included_file() instead of calling this function.
- */
- size_t (*get_included_file) (yasm_preproc *preproc, /*@out@*/ char *buf,
- size_t max_size);
-
- /** Module-level implementation of yasm_preproc_add_include_file().
- * Call yasm_preproc_add_include_file() instead of calling this function.
- */
- void (*add_include_file) (yasm_preproc *preproc, const char *filename);
-
- /** Module-level implementation of yasm_preproc_predefine_macro().
- * Call yasm_preproc_predefine_macro() instead of calling this function.
- */
- void (*predefine_macro) (yasm_preproc *preproc, const char *macronameval);
-
- /** Module-level implementation of yasm_preproc_undefine_macro().
- * Call yasm_preproc_undefine_macro() instead of calling this function.
- */
- void (*undefine_macro) (yasm_preproc *preproc, const char *macroname);
-
- /** Module-level implementation of yasm_preproc_builtin_define().
- * Call yasm_preproc_builtin_define() instead of calling this function.
- */
- void (*define_builtin) (yasm_preproc *preproc, const char *macronameval);
-
- /** Module-level implementation of yasm_preproc_add_standard().
- * Call yasm_preproc_add_standard() instead of calling this function.
- */
- void (*add_standard) (yasm_preproc *preproc, const char **macros);
-} yasm_preproc_module;
-
-/** Initialize preprocessor.
- * The preprocessor needs access to the object format module to find out
- * any output format specific macros.
- * \param module preprocessor module
- * \param in_filename initial starting filename, or "-" to read from stdin
- * \param symtab symbol table (may be NULL if none)
- * \param lm line mapping repository
- * \param errwarns error/warning set
- * \return New preprocessor.
- * \note Errors/warnings are stored into errwarns.
- */
-/*@only@*/ yasm_preproc *yasm_preproc_create
- (yasm_preproc_module *module, const char *in_filename,
- yasm_symtab *symtab, yasm_linemap *lm, yasm_errwarns *errwarns);
-
-/** Cleans up any allocated preproc memory.
- * \param preproc preprocessor
- */
-void yasm_preproc_destroy(/*@only@*/ yasm_preproc *preproc);
-
-/** Gets a single line of preprocessed source code.
- * \param preproc preprocessor
- * \return Allocated line of code, without the trailing \n.
- */
-char *yasm_preproc_get_line(yasm_preproc *preproc);
-
-/** Get the next filename included by the source code.
- * \param preproc preprocessor
- * \param buf destination buffer for filename
- * \param max_size maximum number of bytes that can be returned in buf
- * \return Actual number of bytes returned in buf.
- */
-size_t yasm_preproc_get_included_file(yasm_preproc *preproc,
- /*@out@*/ char *buf, size_t max_size);
-
-/** Pre-include a file.
- * \param preproc preprocessor
- * \param filename filename
- */
-void yasm_preproc_add_include_file(yasm_preproc *preproc,
- const char *filename);
-
-/** Pre-define a macro.
- * \param preproc preprocessor
- * \param macronameval "name=value" string
- */
-void yasm_preproc_predefine_macro(yasm_preproc *preproc,
- const char *macronameval);
-
-/** Un-define a macro.
- * \param preproc preprocessor
- * \param macroname macro name
- */
-void yasm_preproc_undefine_macro(yasm_preproc *preproc, const char *macroname);
-
-/** Define a builtin macro, preprocessed before the "standard" macros.
- * \param preproc preprocessor
- * \param macronameval "name=value" string
- */
-void yasm_preproc_define_builtin(yasm_preproc *preproc,
- const char *macronameval);
-
-/** Define additional standard macros, preprocessed after the builtins but
- * prior to any user-defined macros.
- * \param preproc preprocessor
- * \param macros NULL-terminated array of macro strings
- */
-void yasm_preproc_add_standard(yasm_preproc *preproc,
- const char **macros);
-
-#ifndef YASM_DOXYGEN
-
-/* Inline macro implementations for preproc functions */
-
-#define yasm_preproc_create(module, in_filename, symtab, lm, ews) \
- module->create(in_filename, symtab, lm, ews)
-
-#define yasm_preproc_destroy(preproc) \
- ((yasm_preproc_base *)preproc)->module->destroy(preproc)
-#define yasm_preproc_get_line(preproc) \
- ((yasm_preproc_base *)preproc)->module->get_line(preproc)
-#define yasm_preproc_get_included_file(preproc, buf, max_size) \
- ((yasm_preproc_base *)preproc)->module->get_included_file(preproc, buf, max_size)
-#define yasm_preproc_add_include_file(preproc, filename) \
- ((yasm_preproc_base *)preproc)->module->add_include_file(preproc, filename)
-#define yasm_preproc_predefine_macro(preproc, macronameval) \
- ((yasm_preproc_base *)preproc)->module->predefine_macro(preproc, \
- macronameval)
-#define yasm_preproc_undefine_macro(preproc, macroname) \
- ((yasm_preproc_base *)preproc)->module->undefine_macro(preproc, macroname)
-#define yasm_preproc_define_builtin(preproc, macronameval) \
- ((yasm_preproc_base *)preproc)->module->define_builtin(preproc, \
- macronameval)
-#define yasm_preproc_add_standard(preproc, macros) \
- ((yasm_preproc_base *)preproc)->module->add_standard(preproc, \
- macros)
-
-#endif
-
-#endif
+/**
+ * \file libyasm/preproc.h
+ * \brief YASM preprocessor module interface.
+ *
+ * \license
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * \endlicense
+ */
+#ifndef YASM_PREPROC_H
+#define YASM_PREPROC_H
+
+#ifndef YASM_DOXYGEN
+/** Base #yasm_preproc structure. Must be present as the first element in any
+ * #yasm_preproc implementation.
+ */
+typedef struct yasm_preproc_base {
+ /** #yasm_preproc_module implementation for this preprocessor. */
+ const struct yasm_preproc_module *module;
+} yasm_preproc_base;
+#endif
+
+/** YASM preprocesor module interface. */
+typedef struct yasm_preproc_module {
+ /** One-line description of the preprocessor. */
+ const char *name;
+
+ /** Keyword used to select preprocessor on the command line. */
+ const char *keyword;
+
+ /** Create preprocessor.
+ * Module-level implementation of yasm_preproc_create().
+ * Call yasm_preproc_create() instead of calling this function.
+ *
+ * \param in_filename initial starting filename, or "-" to read from
+ * stdin
+ * \param symtab symbol table (may be NULL if none)
+ * \param lm line mapping repository
+ * \param errwarns error/warnning set.
+ * \return New preprocessor.
+ *
+ * \note Any preprocessor errors and warnings are stored into errwarns.
+ */
+ /*@only@*/ yasm_preproc * (*create) (const char *in_filename,
+ yasm_symtab *symtab,
+ yasm_linemap *lm,
+ yasm_errwarns *errwarns);
+
+ /** Module-level implementation of yasm_preproc_destroy().
+ * Call yasm_preproc_destroy() instead of calling this function.
+ */
+ void (*destroy) (/*@only@*/ yasm_preproc *preproc);
+
+ /** Module-level implementation of yasm_preproc_get_line().
+ * Call yasm_preproc_get_line() instead of calling this function.
+ */
+ char * (*get_line) (yasm_preproc *preproc);
+
+ /** Module-level implementation of yasm_preproc_get_included_file().
+ * Call yasm_preproc_get_included_file() instead of calling this function.
+ */
+ size_t (*get_included_file) (yasm_preproc *preproc, /*@out@*/ char *buf,
+ size_t max_size);
+
+ /** Module-level implementation of yasm_preproc_add_include_file().
+ * Call yasm_preproc_add_include_file() instead of calling this function.
+ */
+ void (*add_include_file) (yasm_preproc *preproc, const char *filename);
+
+ /** Module-level implementation of yasm_preproc_predefine_macro().
+ * Call yasm_preproc_predefine_macro() instead of calling this function.
+ */
+ void (*predefine_macro) (yasm_preproc *preproc, const char *macronameval);
+
+ /** Module-level implementation of yasm_preproc_undefine_macro().
+ * Call yasm_preproc_undefine_macro() instead of calling this function.
+ */
+ void (*undefine_macro) (yasm_preproc *preproc, const char *macroname);
+
+ /** Module-level implementation of yasm_preproc_builtin_define().
+ * Call yasm_preproc_builtin_define() instead of calling this function.
+ */
+ void (*define_builtin) (yasm_preproc *preproc, const char *macronameval);
+
+ /** Module-level implementation of yasm_preproc_add_standard().
+ * Call yasm_preproc_add_standard() instead of calling this function.
+ */
+ void (*add_standard) (yasm_preproc *preproc, const char **macros);
+} yasm_preproc_module;
+
+/** Initialize preprocessor.
+ * The preprocessor needs access to the object format module to find out
+ * any output format specific macros.
+ * \param module preprocessor module
+ * \param in_filename initial starting filename, or "-" to read from stdin
+ * \param symtab symbol table (may be NULL if none)
+ * \param lm line mapping repository
+ * \param errwarns error/warning set
+ * \return New preprocessor.
+ * \note Errors/warnings are stored into errwarns.
+ */
+/*@only@*/ yasm_preproc *yasm_preproc_create
+ (yasm_preproc_module *module, const char *in_filename,
+ yasm_symtab *symtab, yasm_linemap *lm, yasm_errwarns *errwarns);
+
+/** Cleans up any allocated preproc memory.
+ * \param preproc preprocessor
+ */
+void yasm_preproc_destroy(/*@only@*/ yasm_preproc *preproc);
+
+/** Gets a single line of preprocessed source code.
+ * \param preproc preprocessor
+ * \return Allocated line of code, without the trailing \n.
+ */
+char *yasm_preproc_get_line(yasm_preproc *preproc);
+
+/** Get the next filename included by the source code.
+ * \param preproc preprocessor
+ * \param buf destination buffer for filename
+ * \param max_size maximum number of bytes that can be returned in buf
+ * \return Actual number of bytes returned in buf.
+ */
+size_t yasm_preproc_get_included_file(yasm_preproc *preproc,
+ /*@out@*/ char *buf, size_t max_size);
+
+/** Pre-include a file.
+ * \param preproc preprocessor
+ * \param filename filename
+ */
+void yasm_preproc_add_include_file(yasm_preproc *preproc,
+ const char *filename);
+
+/** Pre-define a macro.
+ * \param preproc preprocessor
+ * \param macronameval "name=value" string
+ */
+void yasm_preproc_predefine_macro(yasm_preproc *preproc,
+ const char *macronameval);
+
+/** Un-define a macro.
+ * \param preproc preprocessor
+ * \param macroname macro name
+ */
+void yasm_preproc_undefine_macro(yasm_preproc *preproc, const char *macroname);
+
+/** Define a builtin macro, preprocessed before the "standard" macros.
+ * \param preproc preprocessor
+ * \param macronameval "name=value" string
+ */
+void yasm_preproc_define_builtin(yasm_preproc *preproc,
+ const char *macronameval);
+
+/** Define additional standard macros, preprocessed after the builtins but
+ * prior to any user-defined macros.
+ * \param preproc preprocessor
+ * \param macros NULL-terminated array of macro strings
+ */
+void yasm_preproc_add_standard(yasm_preproc *preproc,
+ const char **macros);
+
+#ifndef YASM_DOXYGEN
+
+/* Inline macro implementations for preproc functions */
+
+#define yasm_preproc_create(module, in_filename, symtab, lm, ews) \
+ module->create(in_filename, symtab, lm, ews)
+
+#define yasm_preproc_destroy(preproc) \
+ ((yasm_preproc_base *)preproc)->module->destroy(preproc)
+#define yasm_preproc_get_line(preproc) \
+ ((yasm_preproc_base *)preproc)->module->get_line(preproc)
+#define yasm_preproc_get_included_file(preproc, buf, max_size) \
+ ((yasm_preproc_base *)preproc)->module->get_included_file(preproc, buf, max_size)
+#define yasm_preproc_add_include_file(preproc, filename) \
+ ((yasm_preproc_base *)preproc)->module->add_include_file(preproc, filename)
+#define yasm_preproc_predefine_macro(preproc, macronameval) \
+ ((yasm_preproc_base *)preproc)->module->predefine_macro(preproc, \
+ macronameval)
+#define yasm_preproc_undefine_macro(preproc, macroname) \
+ ((yasm_preproc_base *)preproc)->module->undefine_macro(preproc, macroname)
+#define yasm_preproc_define_builtin(preproc, macronameval) \
+ ((yasm_preproc_base *)preproc)->module->define_builtin(preproc, \
+ macronameval)
+#define yasm_preproc_add_standard(preproc, macros) \
+ ((yasm_preproc_base *)preproc)->module->add_standard(preproc, \
+ macros)
+
+#endif
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/section.c b/contrib/tools/yasm/libyasm/section.c
index 729d7770a4..e43a5395f6 100644
--- a/contrib/tools/yasm/libyasm/section.c
+++ b/contrib/tools/yasm/libyasm/section.c
@@ -1,1585 +1,1585 @@
-/*
- * Section utility functions
- *
- * Copyright (C) 2001-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#include "util.h"
-
-#include <limits.h>
-
-#include "libyasm-stdint.h"
-#include "coretype.h"
-#include "hamt.h"
-#include "valparam.h"
-#include "assocdat.h"
-
-#include "linemap.h"
-#include "errwarn.h"
-#include "intnum.h"
-#include "expr.h"
-#include "value.h"
-#include "symrec.h"
-
-#include "bytecode.h"
-#include "arch.h"
-#include "section.h"
-
-#include "dbgfmt.h"
-#include "objfmt.h"
-
-#include "inttree.h"
-
-
-struct yasm_section {
- /*@reldef@*/ STAILQ_ENTRY(yasm_section) link;
-
- /*@dependent@*/ yasm_object *object; /* Pointer to parent object */
-
- /*@owned@*/ char *name; /* strdup()'ed name (given by user) */
-
- /* associated data; NULL if none */
- /*@null@*/ /*@only@*/ yasm__assoc_data *assoc_data;
-
- unsigned long align; /* Section alignment */
-
- unsigned long opt_flags; /* storage for optimizer flags */
-
- int code; /* section contains code (instructions) */
- int res_only; /* allow only resb family of bytecodes? */
- int def; /* "default" section, e.g. not specified by
- using section directive */
-
- /* the bytecodes for the section's contents */
- /*@reldef@*/ STAILQ_HEAD(yasm_bytecodehead, yasm_bytecode) bcs;
-
- /* the relocations for the section */
- /*@reldef@*/ STAILQ_HEAD(yasm_relochead, yasm_reloc) relocs;
-
- void (*destroy_reloc) (/*@only@*/ void *reloc);
-};
-
-static void yasm_section_destroy(/*@only@*/ yasm_section *sect);
-
-/* Wrapper around directive for HAMT insertion */
-typedef struct yasm_directive_wrap {
- const yasm_directive *directive;
-} yasm_directive_wrap;
-
-/*
- * Standard "builtin" object directives.
- */
-
-static void
-dir_extern(yasm_object *object, yasm_valparamhead *valparams,
- yasm_valparamhead *objext_valparams, unsigned long line)
-{
- yasm_valparam *vp = yasm_vps_first(valparams);
- yasm_symrec *sym;
- sym = yasm_symtab_declare(object->symtab, yasm_vp_id(vp), YASM_SYM_EXTERN,
- line);
- if (objext_valparams) {
- yasm_valparamhead *vps = yasm_vps_create();
- *vps = *objext_valparams; /* structure copy */
- yasm_vps_initialize(objext_valparams); /* don't double-free */
- yasm_symrec_set_objext_valparams(sym, vps);
- }
-}
-
-static void
-dir_global(yasm_object *object, yasm_valparamhead *valparams,
- yasm_valparamhead *objext_valparams, unsigned long line)
-{
- yasm_valparam *vp = yasm_vps_first(valparams);
- yasm_symrec *sym;
- sym = yasm_symtab_declare(object->symtab, yasm_vp_id(vp), YASM_SYM_GLOBAL,
- line);
- if (objext_valparams) {
- yasm_valparamhead *vps = yasm_vps_create();
- *vps = *objext_valparams; /* structure copy */
- yasm_vps_initialize(objext_valparams); /* don't double-free */
- yasm_symrec_set_objext_valparams(sym, vps);
- }
-}
-
-static void
-dir_common(yasm_object *object, yasm_valparamhead *valparams,
- yasm_valparamhead *objext_valparams, unsigned long line)
-{
- yasm_valparam *vp = yasm_vps_first(valparams);
- yasm_valparam *vp2 = yasm_vps_next(vp);
- yasm_expr *size = yasm_vp_expr(vp2, object->symtab, line);
- yasm_symrec *sym;
-
- if (!size) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("no size specified in %s declaration"), "COMMON");
- return;
- }
- sym = yasm_symtab_declare(object->symtab, yasm_vp_id(vp), YASM_SYM_COMMON,
- line);
- yasm_symrec_set_common_size(sym, size);
- if (objext_valparams) {
- yasm_valparamhead *vps = yasm_vps_create();
- *vps = *objext_valparams; /* structure copy */
- yasm_vps_initialize(objext_valparams); /* don't double-free */
- yasm_symrec_set_objext_valparams(sym, vps);
- }
-}
-
-static void
-dir_section(yasm_object *object, yasm_valparamhead *valparams,
- yasm_valparamhead *objext_valparams, unsigned long line)
-{
- yasm_section *new_section =
- yasm_objfmt_section_switch(object, valparams, objext_valparams, line);
- if (new_section)
- object->cur_section = new_section;
- else
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("invalid argument to directive `%s'"), "SECTION");
-}
-
-static const yasm_directive object_directives[] = {
- { ".extern", "gas", dir_extern, YASM_DIR_ID_REQUIRED },
- { ".global", "gas", dir_global, YASM_DIR_ID_REQUIRED },
- { ".globl", "gas", dir_global, YASM_DIR_ID_REQUIRED },
- { "extern", "nasm", dir_extern, YASM_DIR_ID_REQUIRED },
- { "global", "nasm", dir_global, YASM_DIR_ID_REQUIRED },
- { "common", "nasm", dir_common, YASM_DIR_ID_REQUIRED },
- { "section", "nasm", dir_section, YASM_DIR_ARG_REQUIRED },
- { "segment", "nasm", dir_section, YASM_DIR_ARG_REQUIRED },
- { NULL, NULL, NULL, 0 }
-};
-
-static void
-directive_level2_delete(/*@only@*/ void *data)
-{
- yasm_xfree(data);
-}
-
-static void
-directive_level1_delete(/*@only@*/ void *data)
-{
- HAMT_destroy(data, directive_level2_delete);
-}
-
-static void
-directives_add(yasm_object *object, /*@null@*/ const yasm_directive *dir)
-{
- if (!dir)
- return;
-
- while (dir->name) {
- HAMT *level2 = HAMT_search(object->directives, dir->parser);
- int replace;
- yasm_directive_wrap *wrap = yasm_xmalloc(sizeof(yasm_directive_wrap));
-
- if (!level2) {
- replace = 0;
- level2 = HAMT_insert(object->directives, dir->parser,
- HAMT_create(1, yasm_internal_error_),
- &replace, directive_level1_delete);
- }
- replace = 0;
- wrap->directive = dir;
- HAMT_insert(level2, dir->name, wrap, &replace,
- directive_level2_delete);
- dir++;
- }
-}
-
-/*@-compdestroy@*/
-yasm_object *
-yasm_object_create(const char *src_filename, const char *obj_filename,
- /*@kept@*/ yasm_arch *arch,
- const yasm_objfmt_module *objfmt_module,
- const yasm_dbgfmt_module *dbgfmt_module)
-{
- yasm_object *object = yasm_xmalloc(sizeof(yasm_object));
- int matched, i;
-
- object->src_filename = yasm__xstrdup(src_filename);
+/*
+ * Section utility functions
+ *
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "util.h"
+
+#include <limits.h>
+
+#include "libyasm-stdint.h"
+#include "coretype.h"
+#include "hamt.h"
+#include "valparam.h"
+#include "assocdat.h"
+
+#include "linemap.h"
+#include "errwarn.h"
+#include "intnum.h"
+#include "expr.h"
+#include "value.h"
+#include "symrec.h"
+
+#include "bytecode.h"
+#include "arch.h"
+#include "section.h"
+
+#include "dbgfmt.h"
+#include "objfmt.h"
+
+#include "inttree.h"
+
+
+struct yasm_section {
+ /*@reldef@*/ STAILQ_ENTRY(yasm_section) link;
+
+ /*@dependent@*/ yasm_object *object; /* Pointer to parent object */
+
+ /*@owned@*/ char *name; /* strdup()'ed name (given by user) */
+
+ /* associated data; NULL if none */
+ /*@null@*/ /*@only@*/ yasm__assoc_data *assoc_data;
+
+ unsigned long align; /* Section alignment */
+
+ unsigned long opt_flags; /* storage for optimizer flags */
+
+ int code; /* section contains code (instructions) */
+ int res_only; /* allow only resb family of bytecodes? */
+ int def; /* "default" section, e.g. not specified by
+ using section directive */
+
+ /* the bytecodes for the section's contents */
+ /*@reldef@*/ STAILQ_HEAD(yasm_bytecodehead, yasm_bytecode) bcs;
+
+ /* the relocations for the section */
+ /*@reldef@*/ STAILQ_HEAD(yasm_relochead, yasm_reloc) relocs;
+
+ void (*destroy_reloc) (/*@only@*/ void *reloc);
+};
+
+static void yasm_section_destroy(/*@only@*/ yasm_section *sect);
+
+/* Wrapper around directive for HAMT insertion */
+typedef struct yasm_directive_wrap {
+ const yasm_directive *directive;
+} yasm_directive_wrap;
+
+/*
+ * Standard "builtin" object directives.
+ */
+
+static void
+dir_extern(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_valparam *vp = yasm_vps_first(valparams);
+ yasm_symrec *sym;
+ sym = yasm_symtab_declare(object->symtab, yasm_vp_id(vp), YASM_SYM_EXTERN,
+ line);
+ if (objext_valparams) {
+ yasm_valparamhead *vps = yasm_vps_create();
+ *vps = *objext_valparams; /* structure copy */
+ yasm_vps_initialize(objext_valparams); /* don't double-free */
+ yasm_symrec_set_objext_valparams(sym, vps);
+ }
+}
+
+static void
+dir_global(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_valparam *vp = yasm_vps_first(valparams);
+ yasm_symrec *sym;
+ sym = yasm_symtab_declare(object->symtab, yasm_vp_id(vp), YASM_SYM_GLOBAL,
+ line);
+ if (objext_valparams) {
+ yasm_valparamhead *vps = yasm_vps_create();
+ *vps = *objext_valparams; /* structure copy */
+ yasm_vps_initialize(objext_valparams); /* don't double-free */
+ yasm_symrec_set_objext_valparams(sym, vps);
+ }
+}
+
+static void
+dir_common(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_valparam *vp = yasm_vps_first(valparams);
+ yasm_valparam *vp2 = yasm_vps_next(vp);
+ yasm_expr *size = yasm_vp_expr(vp2, object->symtab, line);
+ yasm_symrec *sym;
+
+ if (!size) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("no size specified in %s declaration"), "COMMON");
+ return;
+ }
+ sym = yasm_symtab_declare(object->symtab, yasm_vp_id(vp), YASM_SYM_COMMON,
+ line);
+ yasm_symrec_set_common_size(sym, size);
+ if (objext_valparams) {
+ yasm_valparamhead *vps = yasm_vps_create();
+ *vps = *objext_valparams; /* structure copy */
+ yasm_vps_initialize(objext_valparams); /* don't double-free */
+ yasm_symrec_set_objext_valparams(sym, vps);
+ }
+}
+
+static void
+dir_section(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_section *new_section =
+ yasm_objfmt_section_switch(object, valparams, objext_valparams, line);
+ if (new_section)
+ object->cur_section = new_section;
+ else
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("invalid argument to directive `%s'"), "SECTION");
+}
+
+static const yasm_directive object_directives[] = {
+ { ".extern", "gas", dir_extern, YASM_DIR_ID_REQUIRED },
+ { ".global", "gas", dir_global, YASM_DIR_ID_REQUIRED },
+ { ".globl", "gas", dir_global, YASM_DIR_ID_REQUIRED },
+ { "extern", "nasm", dir_extern, YASM_DIR_ID_REQUIRED },
+ { "global", "nasm", dir_global, YASM_DIR_ID_REQUIRED },
+ { "common", "nasm", dir_common, YASM_DIR_ID_REQUIRED },
+ { "section", "nasm", dir_section, YASM_DIR_ARG_REQUIRED },
+ { "segment", "nasm", dir_section, YASM_DIR_ARG_REQUIRED },
+ { NULL, NULL, NULL, 0 }
+};
+
+static void
+directive_level2_delete(/*@only@*/ void *data)
+{
+ yasm_xfree(data);
+}
+
+static void
+directive_level1_delete(/*@only@*/ void *data)
+{
+ HAMT_destroy(data, directive_level2_delete);
+}
+
+static void
+directives_add(yasm_object *object, /*@null@*/ const yasm_directive *dir)
+{
+ if (!dir)
+ return;
+
+ while (dir->name) {
+ HAMT *level2 = HAMT_search(object->directives, dir->parser);
+ int replace;
+ yasm_directive_wrap *wrap = yasm_xmalloc(sizeof(yasm_directive_wrap));
+
+ if (!level2) {
+ replace = 0;
+ level2 = HAMT_insert(object->directives, dir->parser,
+ HAMT_create(1, yasm_internal_error_),
+ &replace, directive_level1_delete);
+ }
+ replace = 0;
+ wrap->directive = dir;
+ HAMT_insert(level2, dir->name, wrap, &replace,
+ directive_level2_delete);
+ dir++;
+ }
+}
+
+/*@-compdestroy@*/
+yasm_object *
+yasm_object_create(const char *src_filename, const char *obj_filename,
+ /*@kept@*/ yasm_arch *arch,
+ const yasm_objfmt_module *objfmt_module,
+ const yasm_dbgfmt_module *dbgfmt_module)
+{
+ yasm_object *object = yasm_xmalloc(sizeof(yasm_object));
+ int matched, i;
+
+ object->src_filename = yasm__xstrdup(src_filename);
object->deb_filename = NULL;
- object->obj_filename = yasm__xstrdup(obj_filename);
-
- /* No prefix/suffix */
- object->global_prefix = yasm__xstrdup("");
- object->global_suffix = yasm__xstrdup("");
-
- /* Create empty symbol table */
- object->symtab = yasm_symtab_create();
-
- /* Initialize sections linked list */
- STAILQ_INIT(&object->sections);
-
- /* Create directives HAMT */
- object->directives = HAMT_create(1, yasm_internal_error_);
-
- /* Initialize the target architecture */
- object->arch = arch;
-
- /* Initialize things to NULL in case of error */
- object->dbgfmt = NULL;
-
- /* Initialize the object format */
- object->objfmt = yasm_objfmt_create(objfmt_module, object);
- if (!object->objfmt) {
- yasm_error_set(YASM_ERROR_GENERAL,
- N_("object format `%s' does not support architecture `%s' machine `%s'"),
- objfmt_module->keyword, ((yasm_arch_base *)arch)->module->keyword,
- yasm_arch_get_machine(arch));
- goto error;
- }
-
- /* Get a fresh copy of objfmt_module as it may have changed. */
- objfmt_module = ((yasm_objfmt_base *)object->objfmt)->module;
-
- /* Add an initial "default" section to object */
- object->cur_section = yasm_objfmt_add_default_section(object);
-
- /* Check to see if the requested debug format is in the allowed list
- * for the active object format.
- */
- matched = 0;
- for (i=0; objfmt_module->dbgfmt_keywords[i]; i++) {
- if (yasm__strcasecmp(objfmt_module->dbgfmt_keywords[i],
- dbgfmt_module->keyword) == 0) {
- matched = 1;
- break;
- }
- }
-
- if (!matched) {
- yasm_error_set(YASM_ERROR_GENERAL,
- N_("`%s' is not a valid debug format for object format `%s'"),
- dbgfmt_module->keyword, objfmt_module->keyword);
- goto error;
- }
-
- /* Initialize the debug format */
- object->dbgfmt = yasm_dbgfmt_create(dbgfmt_module, object);
- if (!object->dbgfmt) {
- yasm_error_set(YASM_ERROR_GENERAL,
- N_("debug format `%s' does not work with object format `%s'"),
- dbgfmt_module->keyword, objfmt_module->keyword);
- goto error;
- }
-
- /* Add directives to HAMT. Note ordering here determines priority. */
- directives_add(object,
- ((yasm_objfmt_base *)object->objfmt)->module->directives);
- directives_add(object,
- ((yasm_dbgfmt_base *)object->dbgfmt)->module->directives);
- directives_add(object,
- ((yasm_arch_base *)object->arch)->module->directives);
- directives_add(object, object_directives);
-
- return object;
-
-error:
- yasm_object_destroy(object);
- return NULL;
-}
-/*@=compdestroy@*/
-
-/*@-onlytrans@*/
-yasm_section *
-yasm_object_get_general(yasm_object *object, const char *name,
- unsigned long align, int code, int res_only,
- int *isnew, unsigned long line)
-{
- yasm_section *s;
- yasm_bytecode *bc;
-
- /* Search through current sections to see if we already have one with
- * that name.
- */
- STAILQ_FOREACH(s, &object->sections, link) {
- if (strcmp(s->name, name) == 0) {
- *isnew = 0;
- return s;
- }
- }
-
- /* No: we have to allocate and create a new one. */
-
- /* Okay, the name is valid; now allocate and initialize */
- s = yasm_xcalloc(1, sizeof(yasm_section));
- STAILQ_INSERT_TAIL(&object->sections, s, link);
-
- s->object = object;
- s->name = yasm__xstrdup(name);
- s->assoc_data = NULL;
- s->align = align;
-
- /* Initialize bytecodes with one empty bytecode (acts as "prior" for first
- * real bytecode in section.
- */
- STAILQ_INIT(&s->bcs);
- bc = yasm_bc_create_common(NULL, NULL, 0);
- bc->section = s;
- bc->offset = 0;
- STAILQ_INSERT_TAIL(&s->bcs, bc, link);
-
- /* Initialize relocs */
- STAILQ_INIT(&s->relocs);
- s->destroy_reloc = NULL;
-
- s->code = code;
- s->res_only = res_only;
- s->def = 0;
-
- /* Initialize object format specific data */
- yasm_objfmt_init_new_section(s, line);
-
- *isnew = 1;
- return s;
-}
-/*@=onlytrans@*/
-
-int
-yasm_object_directive(yasm_object *object, const char *name,
- const char *parser, yasm_valparamhead *valparams,
- yasm_valparamhead *objext_valparams,
- unsigned long line)
-{
- HAMT *level2;
- yasm_directive_wrap *wrap;
-
- level2 = HAMT_search(object->directives, parser);
- if (!level2)
- return 1;
-
- wrap = HAMT_search(level2, name);
- if (!wrap)
- return 1;
-
- yasm_call_directive(wrap->directive, object, valparams, objext_valparams,
- line);
- return 0;
-}
-
-void
-yasm_object_set_source_fn(yasm_object *object, const char *src_filename)
-{
- yasm_xfree(object->src_filename);
- object->src_filename = yasm__xstrdup(src_filename);
+ object->obj_filename = yasm__xstrdup(obj_filename);
+
+ /* No prefix/suffix */
+ object->global_prefix = yasm__xstrdup("");
+ object->global_suffix = yasm__xstrdup("");
+
+ /* Create empty symbol table */
+ object->symtab = yasm_symtab_create();
+
+ /* Initialize sections linked list */
+ STAILQ_INIT(&object->sections);
+
+ /* Create directives HAMT */
+ object->directives = HAMT_create(1, yasm_internal_error_);
+
+ /* Initialize the target architecture */
+ object->arch = arch;
+
+ /* Initialize things to NULL in case of error */
+ object->dbgfmt = NULL;
+
+ /* Initialize the object format */
+ object->objfmt = yasm_objfmt_create(objfmt_module, object);
+ if (!object->objfmt) {
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("object format `%s' does not support architecture `%s' machine `%s'"),
+ objfmt_module->keyword, ((yasm_arch_base *)arch)->module->keyword,
+ yasm_arch_get_machine(arch));
+ goto error;
+ }
+
+ /* Get a fresh copy of objfmt_module as it may have changed. */
+ objfmt_module = ((yasm_objfmt_base *)object->objfmt)->module;
+
+ /* Add an initial "default" section to object */
+ object->cur_section = yasm_objfmt_add_default_section(object);
+
+ /* Check to see if the requested debug format is in the allowed list
+ * for the active object format.
+ */
+ matched = 0;
+ for (i=0; objfmt_module->dbgfmt_keywords[i]; i++) {
+ if (yasm__strcasecmp(objfmt_module->dbgfmt_keywords[i],
+ dbgfmt_module->keyword) == 0) {
+ matched = 1;
+ break;
+ }
+ }
+
+ if (!matched) {
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("`%s' is not a valid debug format for object format `%s'"),
+ dbgfmt_module->keyword, objfmt_module->keyword);
+ goto error;
+ }
+
+ /* Initialize the debug format */
+ object->dbgfmt = yasm_dbgfmt_create(dbgfmt_module, object);
+ if (!object->dbgfmt) {
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("debug format `%s' does not work with object format `%s'"),
+ dbgfmt_module->keyword, objfmt_module->keyword);
+ goto error;
+ }
+
+ /* Add directives to HAMT. Note ordering here determines priority. */
+ directives_add(object,
+ ((yasm_objfmt_base *)object->objfmt)->module->directives);
+ directives_add(object,
+ ((yasm_dbgfmt_base *)object->dbgfmt)->module->directives);
+ directives_add(object,
+ ((yasm_arch_base *)object->arch)->module->directives);
+ directives_add(object, object_directives);
+
+ return object;
+
+error:
+ yasm_object_destroy(object);
+ return NULL;
+}
+/*@=compdestroy@*/
+
+/*@-onlytrans@*/
+yasm_section *
+yasm_object_get_general(yasm_object *object, const char *name,
+ unsigned long align, int code, int res_only,
+ int *isnew, unsigned long line)
+{
+ yasm_section *s;
+ yasm_bytecode *bc;
+
+ /* Search through current sections to see if we already have one with
+ * that name.
+ */
+ STAILQ_FOREACH(s, &object->sections, link) {
+ if (strcmp(s->name, name) == 0) {
+ *isnew = 0;
+ return s;
+ }
+ }
+
+ /* No: we have to allocate and create a new one. */
+
+ /* Okay, the name is valid; now allocate and initialize */
+ s = yasm_xcalloc(1, sizeof(yasm_section));
+ STAILQ_INSERT_TAIL(&object->sections, s, link);
+
+ s->object = object;
+ s->name = yasm__xstrdup(name);
+ s->assoc_data = NULL;
+ s->align = align;
+
+ /* Initialize bytecodes with one empty bytecode (acts as "prior" for first
+ * real bytecode in section.
+ */
+ STAILQ_INIT(&s->bcs);
+ bc = yasm_bc_create_common(NULL, NULL, 0);
+ bc->section = s;
+ bc->offset = 0;
+ STAILQ_INSERT_TAIL(&s->bcs, bc, link);
+
+ /* Initialize relocs */
+ STAILQ_INIT(&s->relocs);
+ s->destroy_reloc = NULL;
+
+ s->code = code;
+ s->res_only = res_only;
+ s->def = 0;
+
+ /* Initialize object format specific data */
+ yasm_objfmt_init_new_section(s, line);
+
+ *isnew = 1;
+ return s;
+}
+/*@=onlytrans@*/
+
+int
+yasm_object_directive(yasm_object *object, const char *name,
+ const char *parser, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams,
+ unsigned long line)
+{
+ HAMT *level2;
+ yasm_directive_wrap *wrap;
+
+ level2 = HAMT_search(object->directives, parser);
+ if (!level2)
+ return 1;
+
+ wrap = HAMT_search(level2, name);
+ if (!wrap)
+ return 1;
+
+ yasm_call_directive(wrap->directive, object, valparams, objext_valparams,
+ line);
+ return 0;
+}
+
+void
+yasm_object_set_source_fn(yasm_object *object, const char *src_filename)
+{
+ yasm_xfree(object->src_filename);
+ object->src_filename = yasm__xstrdup(src_filename);
yasm_xfree(object->deb_filename);
object->deb_filename = NULL;
-}
-
-void
-yasm_object_set_global_prefix(yasm_object *object, const char *prefix)
-{
- yasm_xfree(object->global_prefix);
- object->global_prefix = yasm__xstrdup(prefix);
-}
-
-void
-yasm_object_set_global_suffix(yasm_object *object, const char *suffix)
-{
- yasm_xfree(object->global_suffix);
- object->global_suffix = yasm__xstrdup(suffix);
-}
-
-int
-yasm_section_is_code(yasm_section *sect)
-{
- return sect->code;
-}
-
-unsigned long
-yasm_section_get_opt_flags(const yasm_section *sect)
-{
- return sect->opt_flags;
-}
-
-void
-yasm_section_set_opt_flags(yasm_section *sect, unsigned long opt_flags)
-{
- sect->opt_flags = opt_flags;
-}
-
-int
-yasm_section_is_default(const yasm_section *sect)
-{
- return sect->def;
-}
-
-void
-yasm_section_set_default(yasm_section *sect, int def)
-{
- sect->def = def;
-}
-
-yasm_object *
-yasm_section_get_object(const yasm_section *sect)
-{
- return sect->object;
-}
-
-void *
-yasm_section_get_data(yasm_section *sect,
- const yasm_assoc_data_callback *callback)
-{
- return yasm__assoc_data_get(sect->assoc_data, callback);
-}
-
-void
-yasm_section_add_data(yasm_section *sect,
- const yasm_assoc_data_callback *callback, void *data)
-{
- sect->assoc_data = yasm__assoc_data_add(sect->assoc_data, callback, data);
-}
-
-void
-yasm_object_destroy(yasm_object *object)
-{
- yasm_section *cur, *next;
-
- /* Delete object format, debug format, and arch. This can be called
- * due to an error in yasm_object_create(), so look out for NULLs.
- */
- if (object->objfmt)
- yasm_objfmt_destroy(object->objfmt);
- if (object->dbgfmt)
- yasm_dbgfmt_destroy(object->dbgfmt);
-
- /* Delete sections */
- cur = STAILQ_FIRST(&object->sections);
- while (cur) {
- next = STAILQ_NEXT(cur, link);
- yasm_section_destroy(cur);
- cur = next;
- }
-
- /* Delete directives HAMT */
- HAMT_destroy(object->directives, directive_level1_delete);
-
- /* Delete prefix/suffix */
- yasm_xfree(object->global_prefix);
- yasm_xfree(object->global_suffix);
-
- /* Delete associated filenames */
- yasm_xfree(object->src_filename);
+}
+
+void
+yasm_object_set_global_prefix(yasm_object *object, const char *prefix)
+{
+ yasm_xfree(object->global_prefix);
+ object->global_prefix = yasm__xstrdup(prefix);
+}
+
+void
+yasm_object_set_global_suffix(yasm_object *object, const char *suffix)
+{
+ yasm_xfree(object->global_suffix);
+ object->global_suffix = yasm__xstrdup(suffix);
+}
+
+int
+yasm_section_is_code(yasm_section *sect)
+{
+ return sect->code;
+}
+
+unsigned long
+yasm_section_get_opt_flags(const yasm_section *sect)
+{
+ return sect->opt_flags;
+}
+
+void
+yasm_section_set_opt_flags(yasm_section *sect, unsigned long opt_flags)
+{
+ sect->opt_flags = opt_flags;
+}
+
+int
+yasm_section_is_default(const yasm_section *sect)
+{
+ return sect->def;
+}
+
+void
+yasm_section_set_default(yasm_section *sect, int def)
+{
+ sect->def = def;
+}
+
+yasm_object *
+yasm_section_get_object(const yasm_section *sect)
+{
+ return sect->object;
+}
+
+void *
+yasm_section_get_data(yasm_section *sect,
+ const yasm_assoc_data_callback *callback)
+{
+ return yasm__assoc_data_get(sect->assoc_data, callback);
+}
+
+void
+yasm_section_add_data(yasm_section *sect,
+ const yasm_assoc_data_callback *callback, void *data)
+{
+ sect->assoc_data = yasm__assoc_data_add(sect->assoc_data, callback, data);
+}
+
+void
+yasm_object_destroy(yasm_object *object)
+{
+ yasm_section *cur, *next;
+
+ /* Delete object format, debug format, and arch. This can be called
+ * due to an error in yasm_object_create(), so look out for NULLs.
+ */
+ if (object->objfmt)
+ yasm_objfmt_destroy(object->objfmt);
+ if (object->dbgfmt)
+ yasm_dbgfmt_destroy(object->dbgfmt);
+
+ /* Delete sections */
+ cur = STAILQ_FIRST(&object->sections);
+ while (cur) {
+ next = STAILQ_NEXT(cur, link);
+ yasm_section_destroy(cur);
+ cur = next;
+ }
+
+ /* Delete directives HAMT */
+ HAMT_destroy(object->directives, directive_level1_delete);
+
+ /* Delete prefix/suffix */
+ yasm_xfree(object->global_prefix);
+ yasm_xfree(object->global_suffix);
+
+ /* Delete associated filenames */
+ yasm_xfree(object->src_filename);
yasm_xfree(object->deb_filename);
- yasm_xfree(object->obj_filename);
-
- /* Delete symbol table */
- yasm_symtab_destroy(object->symtab);
-
- /* Delete architecture */
- if (object->arch)
- yasm_arch_destroy(object->arch);
-
- yasm_xfree(object);
-}
-
-void
-yasm_object_print(const yasm_object *object, FILE *f, int indent_level)
-{
- yasm_section *cur;
-
- /* Print symbol table */
- fprintf(f, "%*sSymbol Table:\n", indent_level, "");
- yasm_symtab_print(object->symtab, f, indent_level+1);
-
- /* Print sections and bytecodes */
- STAILQ_FOREACH(cur, &object->sections, link) {
- fprintf(f, "%*sSection:\n", indent_level, "");
- yasm_section_print(cur, f, indent_level+1, 1);
- }
-}
-
-void
-yasm_object_finalize(yasm_object *object, yasm_errwarns *errwarns)
-{
- yasm_section *sect;
-
- /* Iterate through sections */
- STAILQ_FOREACH(sect, &object->sections, link) {
- yasm_bytecode *cur = STAILQ_FIRST(&sect->bcs);
- yasm_bytecode *prev;
-
- /* Skip our locally created empty bytecode first. */
- prev = cur;
- cur = STAILQ_NEXT(cur, link);
-
- /* Iterate through the remainder, if any. */
- while (cur) {
- /* Finalize */
- yasm_bc_finalize(cur, prev);
- yasm_errwarn_propagate(errwarns, cur->line);
- prev = cur;
- cur = STAILQ_NEXT(cur, link);
- }
- }
-}
-
-int
-yasm_object_sections_traverse(yasm_object *object, /*@null@*/ void *d,
- int (*func) (yasm_section *sect,
- /*@null@*/ void *d))
-{
- yasm_section *cur;
-
- STAILQ_FOREACH(cur, &object->sections, link) {
- int retval = func(cur, d);
- if (retval != 0)
- return retval;
- }
- return 0;
-}
-
-/*@-onlytrans@*/
-yasm_section *
-yasm_object_find_general(yasm_object *object, const char *name)
-{
- yasm_section *cur;
-
- STAILQ_FOREACH(cur, &object->sections, link) {
- if (strcmp(cur->name, name) == 0)
- return cur;
- }
- return NULL;
-}
-/*@=onlytrans@*/
-
-void
-yasm_section_add_reloc(yasm_section *sect, yasm_reloc *reloc,
- void (*destroy_func) (/*@only@*/ void *reloc))
-{
- STAILQ_INSERT_TAIL(&sect->relocs, reloc, link);
- if (!destroy_func)
- yasm_internal_error(N_("NULL destroy function given to add_reloc"));
- else if (sect->destroy_reloc && destroy_func != sect->destroy_reloc)
- yasm_internal_error(N_("different destroy function given to add_reloc"));
- sect->destroy_reloc = destroy_func;
-}
-
-/*@null@*/ yasm_reloc *
-yasm_section_relocs_first(yasm_section *sect)
-{
- return STAILQ_FIRST(&sect->relocs);
-}
-
-#undef yasm_section_reloc_next
-/*@null@*/ yasm_reloc *
-yasm_section_reloc_next(yasm_reloc *reloc)
-{
- return STAILQ_NEXT(reloc, link);
-}
-
-void
-yasm_reloc_get(yasm_reloc *reloc, yasm_intnum **addrp, yasm_symrec **symp)
-{
- *addrp = reloc->addr;
- *symp = reloc->sym;
-}
-
-
-yasm_bytecode *
-yasm_section_bcs_first(yasm_section *sect)
-{
- return STAILQ_FIRST(&sect->bcs);
-}
-
-yasm_bytecode *
-yasm_section_bcs_last(yasm_section *sect)
-{
- return STAILQ_LAST(&sect->bcs, yasm_bytecode, link);
-}
-
-yasm_bytecode *
-yasm_section_bcs_append(yasm_section *sect, yasm_bytecode *bc)
-{
- if (bc) {
- if (bc->callback) {
- bc->section = sect; /* record parent section */
- STAILQ_INSERT_TAIL(&sect->bcs, bc, link);
- return bc;
- } else
- yasm_xfree(bc);
- }
- return (yasm_bytecode *)NULL;
-}
-
-int
-yasm_section_bcs_traverse(yasm_section *sect,
- /*@null@*/ yasm_errwarns *errwarns,
- /*@null@*/ void *d,
- int (*func) (yasm_bytecode *bc, /*@null@*/ void *d))
-{
- yasm_bytecode *cur = STAILQ_FIRST(&sect->bcs);
-
- /* Skip our locally created empty bytecode first. */
- cur = STAILQ_NEXT(cur, link);
-
- /* Iterate through the remainder, if any. */
- while (cur) {
- int retval = func(cur, d);
- if (errwarns)
- yasm_errwarn_propagate(errwarns, cur->line);
- if (retval != 0)
- return retval;
- cur = STAILQ_NEXT(cur, link);
- }
- return 0;
-}
-
-const char *
-yasm_section_get_name(const yasm_section *sect)
-{
- return sect->name;
-}
-
-void
-yasm_section_set_align(yasm_section *sect, unsigned long align,
- unsigned long line)
-{
- sect->align = align;
-}
-
-unsigned long
-yasm_section_get_align(const yasm_section *sect)
-{
- return sect->align;
-}
-
-static void
-yasm_section_destroy(yasm_section *sect)
-{
- yasm_bytecode *cur, *next;
- yasm_reloc *r_cur, *r_next;
-
- if (!sect)
- return;
-
- yasm_xfree(sect->name);
- yasm__assoc_data_destroy(sect->assoc_data);
-
- /* Delete bytecodes */
- cur = STAILQ_FIRST(&sect->bcs);
- while (cur) {
- next = STAILQ_NEXT(cur, link);
- yasm_bc_destroy(cur);
- cur = next;
- }
-
- /* Delete relocations */
- r_cur = STAILQ_FIRST(&sect->relocs);
- while (r_cur) {
- r_next = STAILQ_NEXT(r_cur, link);
- yasm_intnum_destroy(r_cur->addr);
- sect->destroy_reloc(r_cur);
- r_cur = r_next;
- }
-
- yasm_xfree(sect);
-}
-
-void
-yasm_section_print(const yasm_section *sect, FILE *f, int indent_level,
- int print_bcs)
-{
- if (!sect) {
- fprintf(f, "%*s(none)\n", indent_level, "");
- return;
- }
-
- fprintf(f, "%*sname=%s\n", indent_level, "", sect->name);
-
- if (sect->assoc_data) {
- fprintf(f, "%*sAssociated data:\n", indent_level, "");
- yasm__assoc_data_print(sect->assoc_data, f, indent_level+1);
- }
-
- if (print_bcs) {
- yasm_bytecode *cur;
-
- fprintf(f, "%*sBytecodes:\n", indent_level, "");
-
- STAILQ_FOREACH(cur, &sect->bcs, link) {
- fprintf(f, "%*sNext Bytecode:\n", indent_level+1, "");
- yasm_bc_print(cur, f, indent_level+2);
- }
- }
-}
-
-/*
- * Robertson (1977) optimizer
- * Based (somewhat loosely) on the algorithm given in:
- * MRC Technical Summary Report # 1779
- * CODE GENERATION FOR SHORT/LONG ADDRESS MACHINES
- * Edward L. Robertson
- * Mathematics Research Center
- * University of Wisconsin-Madison
- * 610 Walnut Street
- * Madison, Wisconsin 53706
- * August 1977
- *
- * Key components of algorithm:
- * - start assuming all short forms
- * - build spans for short->long transition dependencies
- * - if a long form is needed, walk the dependencies and update
- * Major differences from Robertson's algorithm:
- * - detection of cycles
- * - any difference of two locations is allowed
- * - handling of alignment/org gaps (offset setting)
- * - handling of multiples
- *
- * Data structures:
- * - Interval tree to store spans and associated data
- * - Queues QA and QB
- *
- * Each span keeps track of:
- * - Associated bytecode (bytecode that depends on the span length)
- * - Active/inactive state (starts out active)
- * - Sign (negative/positive; negative being "backwards" in address)
- * - Current length in bytes
- * - New length in bytes
- * - Negative/Positive thresholds
- * - Span ID (unique within each bytecode)
- *
- * How org and align and any other offset-based bytecodes are handled:
- *
- * Some portions are critical values that must not depend on any bytecode
- * offset (either relative or absolute).
- *
- * All offset-setters (ORG and ALIGN) are put into a linked list in section
- * order (e.g. increasing offset order). Each span keeps track of the next
- * offset-setter following the span's associated bytecode.
- *
- * When a bytecode is expanded, the next offset-setter is examined. The
- * offset-setter may be able to absorb the expansion (e.g. any offset
- * following it would not change), or it may have to move forward (in the
- * case of align) or error (in the case of org). If it has to move forward,
- * following offset-setters must also be examined for absorption or moving
- * forward. In either case, the ongoing offset is updated as well as the
- * lengths of any spans dependent on the offset-setter.
- *
- * Alignment/ORG value is critical value.
- * Cannot be combined with TIMES.
- *
- * How times is handled:
- *
- * TIMES: Handled separately from bytecode "raw" size. If not span-dependent,
- * trivial (just multiplied in at any bytecode size increase). Span
- * dependent times update on any change (span ID 0). If the resultant
- * next bytecode offset would be less than the old next bytecode offset,
- * error. Otherwise increase offset and update dependent spans.
- *
- * To reduce interval tree size, a first expansion pass is performed
- * before the spans are added to the tree.
- *
- * Basic algorithm outline:
- *
- * 1. Initialization:
- * a. Number bytecodes sequentially (via bc_index) and calculate offsets
- * of all bytecodes assuming minimum length, building a list of all
- * dependent spans as we go.
- * "minimum" here means absolute minimum:
- * - align/org (offset-based) bumps offset as normal
- * - times values (with span-dependent values) assumed to be 0
- * b. Iterate over spans. Set span length based on bytecode offsets
- * determined in 1a. If span is "certainly" long because the span
- * is an absolute reference to another section (or external) or the
- * distance calculated based on the minimum length is greater than the
- * span's threshold, expand the span's bytecode, and if no further
- * expansion can result, mark span as inactive.
- * c. Iterate over bytecodes to update all bytecode offsets based on new
- * (expanded) lengths calculated in 1b.
- * d. Iterate over active spans. Add span to interval tree. Update span's
- * length based on new bytecode offsets determined in 1c. If span's
- * length exceeds long threshold, add that span to Q.
- * 2. Main loop:
- * While Q not empty:
- * Expand BC dependent on span at head of Q (and remove span from Q).
- * Update span:
- * If BC no longer dependent on span, mark span as inactive.
- * If BC has new thresholds for span, update span.
- * If BC increased in size, for each active span that contains BC:
- * Increase span length by difference between short and long BC length.
- * If span exceeds long threshold (or is flagged to recalculate on any
- * change), add it to tail of Q.
- * 3. Final pass over bytecodes to generate final offsets.
- */
-
-typedef struct yasm_span yasm_span;
-
-typedef struct yasm_offset_setter {
- /* Linked list in section order (e.g. offset order) */
- /*@reldef@*/ STAILQ_ENTRY(yasm_offset_setter) link;
-
- /*@dependent@*/ yasm_bytecode *bc;
-
- unsigned long cur_val, new_val;
- unsigned long thres;
-} yasm_offset_setter;
-
-typedef struct yasm_span_term {
- yasm_bytecode *precbc, *precbc2;
- yasm_span *span; /* span this term is a member of */
- long cur_val, new_val;
- unsigned int subst;
-} yasm_span_term;
-
-struct yasm_span {
- /*@reldef@*/ TAILQ_ENTRY(yasm_span) link; /* for allocation tracking */
- /*@reldef@*/ STAILQ_ENTRY(yasm_span) linkq; /* for Q */
-
- /*@dependent@*/ yasm_bytecode *bc;
-
- yasm_value depval;
-
- /* span term for relative portion of value */
- yasm_span_term *rel_term;
- /* span terms in absolute portion of value */
- yasm_span_term *terms;
- yasm_expr__item *items;
- unsigned int num_terms;
-
- long cur_val;
- long new_val;
-
- long neg_thres;
- long pos_thres;
-
- int id;
-
- int active;
-
- /* NULL-terminated array of spans that led to this span. Used only for
- * checking for circular references (cycles) with id=0 spans.
- */
- yasm_span **backtrace;
- int backtrace_size;
-
- /* First offset setter following this span's bytecode */
- yasm_offset_setter *os;
-};
-
-typedef struct optimize_data {
- /*@reldef@*/ TAILQ_HEAD(yasm_span_head, yasm_span) spans;
- /*@reldef@*/ STAILQ_HEAD(yasm_span_shead, yasm_span) QA, QB;
- /*@only@*/ IntervalTree *itree;
- /*@reldef@*/ STAILQ_HEAD(offset_setters_head, yasm_offset_setter)
- offset_setters;
- long len_diff; /* used only for optimize_term_expand */
- yasm_span *span; /* used only for check_cycle */
- yasm_offset_setter *os;
-} optimize_data;
-
-static yasm_span *
-create_span(yasm_bytecode *bc, int id, /*@null@*/ const yasm_value *value,
- long neg_thres, long pos_thres, yasm_offset_setter *os)
-{
- yasm_span *span = yasm_xmalloc(sizeof(yasm_span));
-
- span->bc = bc;
- if (value)
- yasm_value_init_copy(&span->depval, value);
- else
- yasm_value_initialize(&span->depval, NULL, 0);
- span->rel_term = NULL;
- span->terms = NULL;
- span->items = NULL;
- span->num_terms = 0;
- span->cur_val = 0;
- span->new_val = 0;
- span->neg_thres = neg_thres;
- span->pos_thres = pos_thres;
- span->id = id;
- span->active = 1;
- span->backtrace = NULL;
- span->backtrace_size = 0;
- span->os = os;
-
- return span;
-}
-
-static void
-optimize_add_span(void *add_span_data, yasm_bytecode *bc, int id,
- const yasm_value *value, long neg_thres, long pos_thres)
-{
- optimize_data *optd = (optimize_data *)add_span_data;
- yasm_span *span;
- span = create_span(bc, id, value, neg_thres, pos_thres, optd->os);
- TAILQ_INSERT_TAIL(&optd->spans, span, link);
-}
-
-static void
-add_span_term(unsigned int subst, yasm_bytecode *precbc,
- yasm_bytecode *precbc2, void *d)
-{
- yasm_span *span = d;
- yasm_intnum *intn;
-
- if (subst >= span->num_terms) {
- /* Linear expansion since total number is essentially always small */
- span->num_terms = subst+1;
- span->terms = yasm_xrealloc(span->terms,
- span->num_terms*sizeof(yasm_span_term));
- }
- span->terms[subst].precbc = precbc;
- span->terms[subst].precbc2 = precbc2;
- span->terms[subst].span = span;
- span->terms[subst].subst = subst;
-
- intn = yasm_calc_bc_dist(precbc, precbc2);
- if (!intn)
- yasm_internal_error(N_("could not calculate bc distance"));
- span->terms[subst].cur_val = 0;
- span->terms[subst].new_val = yasm_intnum_get_int(intn);
- yasm_intnum_destroy(intn);
-}
-
-static void
-span_create_terms(yasm_span *span)
-{
- unsigned int i;
-
- /* Split out sym-sym terms in absolute portion of dependent value */
- if (span->depval.abs) {
- span->num_terms = yasm_expr__bc_dist_subst(&span->depval.abs, span,
- add_span_term);
- if (span->num_terms > 0) {
- span->items = yasm_xmalloc(span->num_terms*sizeof(yasm_expr__item));
- for (i=0; i<span->num_terms; i++) {
- /* Create items with dummy value */
- span->items[i].type = YASM_EXPR_INT;
- span->items[i].data.intn = yasm_intnum_create_int(0);
-
- /* Check for circular references */
- if (span->id <= 0 &&
- ((span->bc->bc_index > span->terms[i].precbc->bc_index &&
- span->bc->bc_index <= span->terms[i].precbc2->bc_index) ||
- (span->bc->bc_index > span->terms[i].precbc2->bc_index &&
- span->bc->bc_index <= span->terms[i].precbc->bc_index)))
- yasm_error_set(YASM_ERROR_VALUE,
- N_("circular reference detected"));
- }
- }
- }
-
- /* Create term for relative portion of dependent value */
- if (span->depval.rel) {
- yasm_bytecode *rel_precbc;
- int sym_local;
-
- sym_local = yasm_symrec_get_label(span->depval.rel, &rel_precbc);
- if (span->depval.wrt || span->depval.seg_of || span->depval.section_rel
- || !sym_local)
- return; /* we can't handle SEG, WRT, or external symbols */
- if (rel_precbc->section != span->bc->section)
- return; /* not in this section */
- if (!span->depval.curpos_rel)
- return; /* not PC-relative */
-
- span->rel_term = yasm_xmalloc(sizeof(yasm_span_term));
- span->rel_term->precbc = NULL;
- span->rel_term->precbc2 = rel_precbc;
- span->rel_term->span = span;
- span->rel_term->subst = ~0U;
-
- span->rel_term->cur_val = 0;
- span->rel_term->new_val = yasm_bc_next_offset(rel_precbc) -
- span->bc->offset;
- }
-}
-
-/* Recalculate span value based on current span replacement values.
- * Returns 1 if span needs expansion (e.g. exceeded thresholds).
- */
-static int
-recalc_normal_span(yasm_span *span)
-{
- span->new_val = 0;
-
- if (span->depval.abs) {
- yasm_expr *abs_copy = yasm_expr_copy(span->depval.abs);
- /*@null@*/ /*@dependent@*/ yasm_intnum *num;
-
- /* Update sym-sym terms and substitute back into expr */
- unsigned int i;
- for (i=0; i<span->num_terms; i++)
- yasm_intnum_set_int(span->items[i].data.intn,
- span->terms[i].new_val);
- yasm_expr__subst(abs_copy, span->num_terms, span->items);
- num = yasm_expr_get_intnum(&abs_copy, 0);
- if (num)
- span->new_val = yasm_intnum_get_int(num);
- else
- span->new_val = LONG_MAX; /* too complex; force to longest form */
- yasm_expr_destroy(abs_copy);
- }
-
- if (span->rel_term) {
- if (span->new_val != LONG_MAX && span->rel_term->new_val != LONG_MAX)
- span->new_val += span->rel_term->new_val >> span->depval.rshift;
- else
- span->new_val = LONG_MAX; /* too complex; force to longest form */
- } else if (span->depval.rel)
- span->new_val = LONG_MAX; /* too complex; force to longest form */
-
- if (span->new_val == LONG_MAX)
- span->active = 0;
-
- /* If id<=0, flag update on any change */
- if (span->id <= 0)
- return (span->new_val != span->cur_val);
-
- return (span->new_val < span->neg_thres
- || span->new_val > span->pos_thres);
-}
-
-/* Updates all bytecode offsets. For offset-based bytecodes, calls expand
- * to determine new length.
- */
-static int
-update_all_bc_offsets(yasm_object *object, yasm_errwarns *errwarns)
-{
- yasm_section *sect;
- int saw_error = 0;
-
- STAILQ_FOREACH(sect, &object->sections, link) {
- unsigned long offset = 0;
-
- yasm_bytecode *bc = STAILQ_FIRST(&sect->bcs);
- yasm_bytecode *prevbc;
-
- /* Skip our locally created empty bytecode first. */
- prevbc = bc;
- bc = STAILQ_NEXT(bc, link);
-
- /* Iterate through the remainder, if any. */
- while (bc) {
- if (bc->callback->special == YASM_BC_SPECIAL_OFFSET) {
- /* Recalculate/adjust len of offset-based bytecodes here */
- long neg_thres = 0;
- long pos_thres = (long)yasm_bc_next_offset(bc);
- int retval = yasm_bc_expand(bc, 1, 0,
- (long)yasm_bc_next_offset(prevbc),
- &neg_thres, &pos_thres);
- yasm_errwarn_propagate(errwarns, bc->line);
- if (retval < 0)
- saw_error = 1;
- }
- bc->offset = offset;
- offset += bc->len*bc->mult_int;
- prevbc = bc;
- bc = STAILQ_NEXT(bc, link);
- }
- }
- return saw_error;
-}
-
-static void
-span_destroy(/*@only@*/ yasm_span *span)
-{
- unsigned int i;
-
- yasm_value_delete(&span->depval);
- if (span->rel_term)
- yasm_xfree(span->rel_term);
- if (span->terms)
- yasm_xfree(span->terms);
- if (span->items) {
- for (i=0; i<span->num_terms; i++)
- yasm_intnum_destroy(span->items[i].data.intn);
- yasm_xfree(span->items);
- }
- if (span->backtrace)
- yasm_xfree(span->backtrace);
- yasm_xfree(span);
-}
-
-static void
-optimize_cleanup(optimize_data *optd)
-{
- yasm_span *s1, *s2;
- yasm_offset_setter *os1, *os2;
-
- IT_destroy(optd->itree);
-
- s1 = TAILQ_FIRST(&optd->spans);
- while (s1) {
- s2 = TAILQ_NEXT(s1, link);
- span_destroy(s1);
- s1 = s2;
- }
-
- os1 = STAILQ_FIRST(&optd->offset_setters);
- while (os1) {
- os2 = STAILQ_NEXT(os1, link);
- yasm_xfree(os1);
- os1 = os2;
- }
-}
-
-static void
-optimize_itree_add(IntervalTree *itree, yasm_span *span, yasm_span_term *term)
-{
- long precbc_index, precbc2_index;
- unsigned long low, high;
-
- /* Update term length */
- if (term->precbc)
- precbc_index = term->precbc->bc_index;
- else
- precbc_index = span->bc->bc_index-1;
-
- if (term->precbc2)
- precbc2_index = term->precbc2->bc_index;
- else
- precbc2_index = span->bc->bc_index-1;
-
- if (precbc_index < precbc2_index) {
- low = precbc_index+1;
- high = precbc2_index;
- } else if (precbc_index > precbc2_index) {
- low = precbc2_index+1;
- high = precbc_index;
- } else
- return; /* difference is same bc - always 0! */
-
- IT_insert(itree, (long)low, (long)high, term);
-}
-
-static void
-check_cycle(IntervalTreeNode *node, void *d)
-{
- optimize_data *optd = d;
- yasm_span_term *term = node->data;
- yasm_span *depspan = term->span;
- int i;
- int depspan_bt_alloc;
-
- /* Only check for cycles in id=0 spans */
- if (depspan->id > 0)
- return;
-
- /* Check for a circular reference by looking to see if this dependent
- * span is in our backtrace.
- */
- if (optd->span->backtrace) {
- for (i=0; i<optd->span->backtrace_size; i++) {
- if (optd->span->backtrace[i] == depspan)
- yasm_error_set(YASM_ERROR_VALUE,
- N_("circular reference detected"));
- }
- }
-
- /* Add our complete backtrace and ourselves to backtrace of dependent
- * span.
- */
- if (!depspan->backtrace) {
- depspan->backtrace = yasm_xmalloc((optd->span->backtrace_size+1)*
- sizeof(yasm_span *));
- if (optd->span->backtrace_size > 0)
- memcpy(depspan->backtrace, optd->span->backtrace,
- optd->span->backtrace_size*sizeof(yasm_span *));
- depspan->backtrace[optd->span->backtrace_size] = optd->span;
- depspan->backtrace_size = optd->span->backtrace_size+1;
- return;
- }
-
- /* Add our complete backtrace, checking for duplicates */
- depspan_bt_alloc = depspan->backtrace_size;
- for (i=0; i<optd->span->backtrace_size; i++) {
- int present = 0;
- int j;
- for (j=0; j<depspan->backtrace_size; j++) {
- if (optd->span->backtrace[i] == optd->span->backtrace[j]) {
- present = 1;
- break;
- }
- }
- if (present)
- continue;
- /* Not already in array; add it. */
- if (depspan->backtrace_size >= depspan_bt_alloc)
- {
- depspan_bt_alloc *= 2;
- depspan->backtrace =
- yasm_xrealloc(depspan->backtrace,
- depspan_bt_alloc*sizeof(yasm_span *));
- }
- depspan->backtrace[depspan->backtrace_size] = optd->span->backtrace[i];
- depspan->backtrace_size++;
- }
-
- /* Add ourselves. */
- if (depspan->backtrace_size >= depspan_bt_alloc)
- {
- depspan_bt_alloc++;
- depspan->backtrace =
- yasm_xrealloc(depspan->backtrace,
- depspan_bt_alloc*sizeof(yasm_span *));
- }
- depspan->backtrace[depspan->backtrace_size] = optd->span;
- depspan->backtrace_size++;
-}
-
-static void
-optimize_term_expand(IntervalTreeNode *node, void *d)
-{
- optimize_data *optd = d;
- yasm_span_term *term = node->data;
- yasm_span *span = term->span;
- long len_diff = optd->len_diff;
- long precbc_index, precbc2_index;
-
- /* Don't expand inactive spans */
- if (!span->active)
- return;
-
- /* Update term length */
- if (term->precbc)
- precbc_index = term->precbc->bc_index;
- else
- precbc_index = span->bc->bc_index-1;
-
- if (term->precbc2)
- precbc2_index = term->precbc2->bc_index;
- else
- precbc2_index = span->bc->bc_index-1;
-
- if (precbc_index < precbc2_index)
- term->new_val += len_diff;
- else
- term->new_val -= len_diff;
-
- /* If already on Q, don't re-add */
- if (span->active == 2)
- return;
-
- /* Update term and check against thresholds */
- if (!recalc_normal_span(span))
- return; /* didn't exceed thresholds, we're done */
-
- /* Exceeded thresholds, need to add to Q for expansion */
- if (span->id <= 0)
- STAILQ_INSERT_TAIL(&optd->QA, span, linkq);
- else
- STAILQ_INSERT_TAIL(&optd->QB, span, linkq);
- span->active = 2; /* Mark as being in Q */
-}
-
-void
-yasm_object_optimize(yasm_object *object, yasm_errwarns *errwarns)
-{
- yasm_section *sect;
- unsigned long bc_index = 0;
- int saw_error = 0;
- optimize_data optd;
- yasm_span *span, *span_temp;
- yasm_offset_setter *os;
- int retval;
- unsigned int i;
-
- TAILQ_INIT(&optd.spans);
- STAILQ_INIT(&optd.offset_setters);
- optd.itree = IT_create();
-
- /* Create an placeholder offset setter for spans to point to; this will
- * get updated if/when we actually run into one.
- */
- os = yasm_xmalloc(sizeof(yasm_offset_setter));
- os->bc = NULL;
- os->cur_val = 0;
- os->new_val = 0;
- os->thres = 0;
- STAILQ_INSERT_TAIL(&optd.offset_setters, os, link);
- optd.os = os;
-
- /* Step 1a */
- STAILQ_FOREACH(sect, &object->sections, link) {
- unsigned long offset = 0;
-
- yasm_bytecode *bc = STAILQ_FIRST(&sect->bcs);
-
- bc->bc_index = bc_index++;
-
- /* Skip our locally created empty bytecode first. */
- bc = STAILQ_NEXT(bc, link);
-
- /* Iterate through the remainder, if any. */
- while (bc) {
- bc->bc_index = bc_index++;
- bc->offset = offset;
-
- retval = yasm_bc_calc_len(bc, optimize_add_span, &optd);
- yasm_errwarn_propagate(errwarns, bc->line);
- if (retval)
- saw_error = 1;
- else {
- if (bc->callback->special == YASM_BC_SPECIAL_OFFSET) {
- /* Remember it as offset setter */
- os->bc = bc;
- os->thres = yasm_bc_next_offset(bc);
-
- /* Create new placeholder */
- os = yasm_xmalloc(sizeof(yasm_offset_setter));
- os->bc = NULL;
- os->cur_val = 0;
- os->new_val = 0;
- os->thres = 0;
- STAILQ_INSERT_TAIL(&optd.offset_setters, os, link);
- optd.os = os;
-
- if (bc->multiple) {
- yasm_error_set(YASM_ERROR_VALUE,
- N_("cannot combine multiples and setting assembly position"));
- yasm_errwarn_propagate(errwarns, bc->line);
- saw_error = 1;
- }
- }
-
- offset += bc->len*bc->mult_int;
- }
-
- bc = STAILQ_NEXT(bc, link);
- }
- }
-
- if (saw_error) {
- optimize_cleanup(&optd);
- return;
- }
-
- /* Step 1b */
- TAILQ_FOREACH_SAFE(span, &optd.spans, link, span_temp) {
- span_create_terms(span);
- if (yasm_error_occurred()) {
- yasm_errwarn_propagate(errwarns, span->bc->line);
- saw_error = 1;
- } else if (recalc_normal_span(span)) {
- retval = yasm_bc_expand(span->bc, span->id, span->cur_val,
- span->new_val, &span->neg_thres,
- &span->pos_thres);
- yasm_errwarn_propagate(errwarns, span->bc->line);
- if (retval < 0)
- saw_error = 1;
- else if (retval > 0) {
- if (!span->active) {
- yasm_error_set(YASM_ERROR_VALUE,
- N_("secondary expansion of an external/complex value"));
- yasm_errwarn_propagate(errwarns, span->bc->line);
- saw_error = 1;
- }
- } else {
- TAILQ_REMOVE(&optd.spans, span, link);
- span_destroy(span);
- continue;
- }
- }
- span->cur_val = span->new_val;
- }
-
- if (saw_error) {
- optimize_cleanup(&optd);
- return;
- }
-
- /* Step 1c */
- if (update_all_bc_offsets(object, errwarns)) {
- optimize_cleanup(&optd);
- return;
- }
-
- /* Step 1d */
- STAILQ_INIT(&optd.QB);
- TAILQ_FOREACH(span, &optd.spans, link) {
- yasm_intnum *intn;
-
- /* Update span terms based on new bc offsets */
- for (i=0; i<span->num_terms; i++) {
- intn = yasm_calc_bc_dist(span->terms[i].precbc,
- span->terms[i].precbc2);
- if (!intn)
- yasm_internal_error(N_("could not calculate bc distance"));
- span->terms[i].cur_val = span->terms[i].new_val;
- span->terms[i].new_val = yasm_intnum_get_int(intn);
- yasm_intnum_destroy(intn);
- }
- if (span->rel_term) {
- span->rel_term->cur_val = span->rel_term->new_val;
- if (span->rel_term->precbc2)
- span->rel_term->new_val =
- yasm_bc_next_offset(span->rel_term->precbc2) -
- span->bc->offset;
- else
- span->rel_term->new_val = span->bc->offset -
- yasm_bc_next_offset(span->rel_term->precbc);
- }
-
- if (recalc_normal_span(span)) {
- /* Exceeded threshold, add span to QB */
- STAILQ_INSERT_TAIL(&optd.QB, span, linkq);
- span->active = 2;
- }
- }
-
- /* Do we need step 2? If not, go ahead and exit. */
- if (STAILQ_EMPTY(&optd.QB)) {
- optimize_cleanup(&optd);
- return;
- }
-
- /* Update offset-setters values */
- STAILQ_FOREACH(os, &optd.offset_setters, link) {
- if (!os->bc)
- continue;
- os->thres = yasm_bc_next_offset(os->bc);
- os->new_val = os->bc->offset;
- os->cur_val = os->new_val;
- }
-
- /* Build up interval tree */
- TAILQ_FOREACH(span, &optd.spans, link) {
- for (i=0; i<span->num_terms; i++)
- optimize_itree_add(optd.itree, span, &span->terms[i]);
- if (span->rel_term)
- optimize_itree_add(optd.itree, span, span->rel_term);
- }
-
- /* Look for cycles in times expansion (span.id==0) */
- TAILQ_FOREACH(span, &optd.spans, link) {
- if (span->id > 0)
- continue;
- optd.span = span;
- IT_enumerate(optd.itree, (long)span->bc->bc_index,
- (long)span->bc->bc_index, &optd, check_cycle);
- if (yasm_error_occurred()) {
- yasm_errwarn_propagate(errwarns, span->bc->line);
- saw_error = 1;
- }
- }
-
- if (saw_error) {
- optimize_cleanup(&optd);
- return;
- }
-
- /* Step 2 */
- STAILQ_INIT(&optd.QA);
- while (!STAILQ_EMPTY(&optd.QA) || !(STAILQ_EMPTY(&optd.QB))) {
- unsigned long orig_len;
- long offset_diff;
-
- /* QA is for TIMES, update those first, then update non-TIMES.
- * This is so that TIMES can absorb increases before we look at
- * expanding non-TIMES BCs.
- */
- if (!STAILQ_EMPTY(&optd.QA)) {
- span = STAILQ_FIRST(&optd.QA);
- STAILQ_REMOVE_HEAD(&optd.QA, linkq);
- } else {
- span = STAILQ_FIRST(&optd.QB);
- STAILQ_REMOVE_HEAD(&optd.QB, linkq);
- }
-
- if (!span->active)
- continue;
- span->active = 1; /* no longer in Q */
-
- /* Make sure we ended up ultimately exceeding thresholds; due to
- * offset BCs we may have been placed on Q and then reduced in size
- * again.
- */
- if (!recalc_normal_span(span))
- continue;
-
- orig_len = span->bc->len * span->bc->mult_int;
-
- retval = yasm_bc_expand(span->bc, span->id, span->cur_val,
- span->new_val, &span->neg_thres,
- &span->pos_thres);
- yasm_errwarn_propagate(errwarns, span->bc->line);
-
- if (retval < 0) {
- /* error */
- saw_error = 1;
- continue;
- } else if (retval > 0) {
- /* another threshold, keep active */
- for (i=0; i<span->num_terms; i++)
- span->terms[i].cur_val = span->terms[i].new_val;
- if (span->rel_term)
- span->rel_term->cur_val = span->rel_term->new_val;
- span->cur_val = span->new_val;
- } else
- span->active = 0; /* we're done with this span */
-
- optd.len_diff = span->bc->len * span->bc->mult_int - orig_len;
- if (optd.len_diff == 0)
- continue; /* didn't increase in size */
-
- /* Iterate over all spans dependent across the bc just expanded */
- IT_enumerate(optd.itree, (long)span->bc->bc_index,
- (long)span->bc->bc_index, &optd, optimize_term_expand);
-
- /* Iterate over offset-setters that follow the bc just expanded.
- * Stop iteration if:
- * - no more offset-setters in this section
- * - offset-setter didn't move its following offset
- */
- os = span->os;
- offset_diff = optd.len_diff;
- while (os->bc && os->bc->section == span->bc->section
- && offset_diff != 0) {
- unsigned long old_next_offset = os->cur_val + os->bc->len;
- long neg_thres_temp;
-
- if (offset_diff < 0 && (unsigned long)(-offset_diff) > os->new_val)
- yasm_internal_error(N_("org/align went to negative offset"));
- os->new_val += offset_diff;
-
- orig_len = os->bc->len;
- retval = yasm_bc_expand(os->bc, 1, (long)os->cur_val,
- (long)os->new_val, &neg_thres_temp,
- (long *)&os->thres);
- yasm_errwarn_propagate(errwarns, os->bc->line);
-
- offset_diff = os->new_val + os->bc->len - old_next_offset;
- optd.len_diff = os->bc->len - orig_len;
- if (optd.len_diff != 0)
- IT_enumerate(optd.itree, (long)os->bc->bc_index,
- (long)os->bc->bc_index, &optd, optimize_term_expand);
-
- os->cur_val = os->new_val;
- os = STAILQ_NEXT(os, link);
- }
- }
-
- if (saw_error) {
- optimize_cleanup(&optd);
- return;
- }
-
- /* Step 3 */
- update_all_bc_offsets(object, errwarns);
- optimize_cleanup(&optd);
-}
+ yasm_xfree(object->obj_filename);
+
+ /* Delete symbol table */
+ yasm_symtab_destroy(object->symtab);
+
+ /* Delete architecture */
+ if (object->arch)
+ yasm_arch_destroy(object->arch);
+
+ yasm_xfree(object);
+}
+
+void
+yasm_object_print(const yasm_object *object, FILE *f, int indent_level)
+{
+ yasm_section *cur;
+
+ /* Print symbol table */
+ fprintf(f, "%*sSymbol Table:\n", indent_level, "");
+ yasm_symtab_print(object->symtab, f, indent_level+1);
+
+ /* Print sections and bytecodes */
+ STAILQ_FOREACH(cur, &object->sections, link) {
+ fprintf(f, "%*sSection:\n", indent_level, "");
+ yasm_section_print(cur, f, indent_level+1, 1);
+ }
+}
+
+void
+yasm_object_finalize(yasm_object *object, yasm_errwarns *errwarns)
+{
+ yasm_section *sect;
+
+ /* Iterate through sections */
+ STAILQ_FOREACH(sect, &object->sections, link) {
+ yasm_bytecode *cur = STAILQ_FIRST(&sect->bcs);
+ yasm_bytecode *prev;
+
+ /* Skip our locally created empty bytecode first. */
+ prev = cur;
+ cur = STAILQ_NEXT(cur, link);
+
+ /* Iterate through the remainder, if any. */
+ while (cur) {
+ /* Finalize */
+ yasm_bc_finalize(cur, prev);
+ yasm_errwarn_propagate(errwarns, cur->line);
+ prev = cur;
+ cur = STAILQ_NEXT(cur, link);
+ }
+ }
+}
+
+int
+yasm_object_sections_traverse(yasm_object *object, /*@null@*/ void *d,
+ int (*func) (yasm_section *sect,
+ /*@null@*/ void *d))
+{
+ yasm_section *cur;
+
+ STAILQ_FOREACH(cur, &object->sections, link) {
+ int retval = func(cur, d);
+ if (retval != 0)
+ return retval;
+ }
+ return 0;
+}
+
+/*@-onlytrans@*/
+yasm_section *
+yasm_object_find_general(yasm_object *object, const char *name)
+{
+ yasm_section *cur;
+
+ STAILQ_FOREACH(cur, &object->sections, link) {
+ if (strcmp(cur->name, name) == 0)
+ return cur;
+ }
+ return NULL;
+}
+/*@=onlytrans@*/
+
+void
+yasm_section_add_reloc(yasm_section *sect, yasm_reloc *reloc,
+ void (*destroy_func) (/*@only@*/ void *reloc))
+{
+ STAILQ_INSERT_TAIL(&sect->relocs, reloc, link);
+ if (!destroy_func)
+ yasm_internal_error(N_("NULL destroy function given to add_reloc"));
+ else if (sect->destroy_reloc && destroy_func != sect->destroy_reloc)
+ yasm_internal_error(N_("different destroy function given to add_reloc"));
+ sect->destroy_reloc = destroy_func;
+}
+
+/*@null@*/ yasm_reloc *
+yasm_section_relocs_first(yasm_section *sect)
+{
+ return STAILQ_FIRST(&sect->relocs);
+}
+
+#undef yasm_section_reloc_next
+/*@null@*/ yasm_reloc *
+yasm_section_reloc_next(yasm_reloc *reloc)
+{
+ return STAILQ_NEXT(reloc, link);
+}
+
+void
+yasm_reloc_get(yasm_reloc *reloc, yasm_intnum **addrp, yasm_symrec **symp)
+{
+ *addrp = reloc->addr;
+ *symp = reloc->sym;
+}
+
+
+yasm_bytecode *
+yasm_section_bcs_first(yasm_section *sect)
+{
+ return STAILQ_FIRST(&sect->bcs);
+}
+
+yasm_bytecode *
+yasm_section_bcs_last(yasm_section *sect)
+{
+ return STAILQ_LAST(&sect->bcs, yasm_bytecode, link);
+}
+
+yasm_bytecode *
+yasm_section_bcs_append(yasm_section *sect, yasm_bytecode *bc)
+{
+ if (bc) {
+ if (bc->callback) {
+ bc->section = sect; /* record parent section */
+ STAILQ_INSERT_TAIL(&sect->bcs, bc, link);
+ return bc;
+ } else
+ yasm_xfree(bc);
+ }
+ return (yasm_bytecode *)NULL;
+}
+
+int
+yasm_section_bcs_traverse(yasm_section *sect,
+ /*@null@*/ yasm_errwarns *errwarns,
+ /*@null@*/ void *d,
+ int (*func) (yasm_bytecode *bc, /*@null@*/ void *d))
+{
+ yasm_bytecode *cur = STAILQ_FIRST(&sect->bcs);
+
+ /* Skip our locally created empty bytecode first. */
+ cur = STAILQ_NEXT(cur, link);
+
+ /* Iterate through the remainder, if any. */
+ while (cur) {
+ int retval = func(cur, d);
+ if (errwarns)
+ yasm_errwarn_propagate(errwarns, cur->line);
+ if (retval != 0)
+ return retval;
+ cur = STAILQ_NEXT(cur, link);
+ }
+ return 0;
+}
+
+const char *
+yasm_section_get_name(const yasm_section *sect)
+{
+ return sect->name;
+}
+
+void
+yasm_section_set_align(yasm_section *sect, unsigned long align,
+ unsigned long line)
+{
+ sect->align = align;
+}
+
+unsigned long
+yasm_section_get_align(const yasm_section *sect)
+{
+ return sect->align;
+}
+
+static void
+yasm_section_destroy(yasm_section *sect)
+{
+ yasm_bytecode *cur, *next;
+ yasm_reloc *r_cur, *r_next;
+
+ if (!sect)
+ return;
+
+ yasm_xfree(sect->name);
+ yasm__assoc_data_destroy(sect->assoc_data);
+
+ /* Delete bytecodes */
+ cur = STAILQ_FIRST(&sect->bcs);
+ while (cur) {
+ next = STAILQ_NEXT(cur, link);
+ yasm_bc_destroy(cur);
+ cur = next;
+ }
+
+ /* Delete relocations */
+ r_cur = STAILQ_FIRST(&sect->relocs);
+ while (r_cur) {
+ r_next = STAILQ_NEXT(r_cur, link);
+ yasm_intnum_destroy(r_cur->addr);
+ sect->destroy_reloc(r_cur);
+ r_cur = r_next;
+ }
+
+ yasm_xfree(sect);
+}
+
+void
+yasm_section_print(const yasm_section *sect, FILE *f, int indent_level,
+ int print_bcs)
+{
+ if (!sect) {
+ fprintf(f, "%*s(none)\n", indent_level, "");
+ return;
+ }
+
+ fprintf(f, "%*sname=%s\n", indent_level, "", sect->name);
+
+ if (sect->assoc_data) {
+ fprintf(f, "%*sAssociated data:\n", indent_level, "");
+ yasm__assoc_data_print(sect->assoc_data, f, indent_level+1);
+ }
+
+ if (print_bcs) {
+ yasm_bytecode *cur;
+
+ fprintf(f, "%*sBytecodes:\n", indent_level, "");
+
+ STAILQ_FOREACH(cur, &sect->bcs, link) {
+ fprintf(f, "%*sNext Bytecode:\n", indent_level+1, "");
+ yasm_bc_print(cur, f, indent_level+2);
+ }
+ }
+}
+
+/*
+ * Robertson (1977) optimizer
+ * Based (somewhat loosely) on the algorithm given in:
+ * MRC Technical Summary Report # 1779
+ * CODE GENERATION FOR SHORT/LONG ADDRESS MACHINES
+ * Edward L. Robertson
+ * Mathematics Research Center
+ * University of Wisconsin-Madison
+ * 610 Walnut Street
+ * Madison, Wisconsin 53706
+ * August 1977
+ *
+ * Key components of algorithm:
+ * - start assuming all short forms
+ * - build spans for short->long transition dependencies
+ * - if a long form is needed, walk the dependencies and update
+ * Major differences from Robertson's algorithm:
+ * - detection of cycles
+ * - any difference of two locations is allowed
+ * - handling of alignment/org gaps (offset setting)
+ * - handling of multiples
+ *
+ * Data structures:
+ * - Interval tree to store spans and associated data
+ * - Queues QA and QB
+ *
+ * Each span keeps track of:
+ * - Associated bytecode (bytecode that depends on the span length)
+ * - Active/inactive state (starts out active)
+ * - Sign (negative/positive; negative being "backwards" in address)
+ * - Current length in bytes
+ * - New length in bytes
+ * - Negative/Positive thresholds
+ * - Span ID (unique within each bytecode)
+ *
+ * How org and align and any other offset-based bytecodes are handled:
+ *
+ * Some portions are critical values that must not depend on any bytecode
+ * offset (either relative or absolute).
+ *
+ * All offset-setters (ORG and ALIGN) are put into a linked list in section
+ * order (e.g. increasing offset order). Each span keeps track of the next
+ * offset-setter following the span's associated bytecode.
+ *
+ * When a bytecode is expanded, the next offset-setter is examined. The
+ * offset-setter may be able to absorb the expansion (e.g. any offset
+ * following it would not change), or it may have to move forward (in the
+ * case of align) or error (in the case of org). If it has to move forward,
+ * following offset-setters must also be examined for absorption or moving
+ * forward. In either case, the ongoing offset is updated as well as the
+ * lengths of any spans dependent on the offset-setter.
+ *
+ * Alignment/ORG value is critical value.
+ * Cannot be combined with TIMES.
+ *
+ * How times is handled:
+ *
+ * TIMES: Handled separately from bytecode "raw" size. If not span-dependent,
+ * trivial (just multiplied in at any bytecode size increase). Span
+ * dependent times update on any change (span ID 0). If the resultant
+ * next bytecode offset would be less than the old next bytecode offset,
+ * error. Otherwise increase offset and update dependent spans.
+ *
+ * To reduce interval tree size, a first expansion pass is performed
+ * before the spans are added to the tree.
+ *
+ * Basic algorithm outline:
+ *
+ * 1. Initialization:
+ * a. Number bytecodes sequentially (via bc_index) and calculate offsets
+ * of all bytecodes assuming minimum length, building a list of all
+ * dependent spans as we go.
+ * "minimum" here means absolute minimum:
+ * - align/org (offset-based) bumps offset as normal
+ * - times values (with span-dependent values) assumed to be 0
+ * b. Iterate over spans. Set span length based on bytecode offsets
+ * determined in 1a. If span is "certainly" long because the span
+ * is an absolute reference to another section (or external) or the
+ * distance calculated based on the minimum length is greater than the
+ * span's threshold, expand the span's bytecode, and if no further
+ * expansion can result, mark span as inactive.
+ * c. Iterate over bytecodes to update all bytecode offsets based on new
+ * (expanded) lengths calculated in 1b.
+ * d. Iterate over active spans. Add span to interval tree. Update span's
+ * length based on new bytecode offsets determined in 1c. If span's
+ * length exceeds long threshold, add that span to Q.
+ * 2. Main loop:
+ * While Q not empty:
+ * Expand BC dependent on span at head of Q (and remove span from Q).
+ * Update span:
+ * If BC no longer dependent on span, mark span as inactive.
+ * If BC has new thresholds for span, update span.
+ * If BC increased in size, for each active span that contains BC:
+ * Increase span length by difference between short and long BC length.
+ * If span exceeds long threshold (or is flagged to recalculate on any
+ * change), add it to tail of Q.
+ * 3. Final pass over bytecodes to generate final offsets.
+ */
+
+typedef struct yasm_span yasm_span;
+
+typedef struct yasm_offset_setter {
+ /* Linked list in section order (e.g. offset order) */
+ /*@reldef@*/ STAILQ_ENTRY(yasm_offset_setter) link;
+
+ /*@dependent@*/ yasm_bytecode *bc;
+
+ unsigned long cur_val, new_val;
+ unsigned long thres;
+} yasm_offset_setter;
+
+typedef struct yasm_span_term {
+ yasm_bytecode *precbc, *precbc2;
+ yasm_span *span; /* span this term is a member of */
+ long cur_val, new_val;
+ unsigned int subst;
+} yasm_span_term;
+
+struct yasm_span {
+ /*@reldef@*/ TAILQ_ENTRY(yasm_span) link; /* for allocation tracking */
+ /*@reldef@*/ STAILQ_ENTRY(yasm_span) linkq; /* for Q */
+
+ /*@dependent@*/ yasm_bytecode *bc;
+
+ yasm_value depval;
+
+ /* span term for relative portion of value */
+ yasm_span_term *rel_term;
+ /* span terms in absolute portion of value */
+ yasm_span_term *terms;
+ yasm_expr__item *items;
+ unsigned int num_terms;
+
+ long cur_val;
+ long new_val;
+
+ long neg_thres;
+ long pos_thres;
+
+ int id;
+
+ int active;
+
+ /* NULL-terminated array of spans that led to this span. Used only for
+ * checking for circular references (cycles) with id=0 spans.
+ */
+ yasm_span **backtrace;
+ int backtrace_size;
+
+ /* First offset setter following this span's bytecode */
+ yasm_offset_setter *os;
+};
+
+typedef struct optimize_data {
+ /*@reldef@*/ TAILQ_HEAD(yasm_span_head, yasm_span) spans;
+ /*@reldef@*/ STAILQ_HEAD(yasm_span_shead, yasm_span) QA, QB;
+ /*@only@*/ IntervalTree *itree;
+ /*@reldef@*/ STAILQ_HEAD(offset_setters_head, yasm_offset_setter)
+ offset_setters;
+ long len_diff; /* used only for optimize_term_expand */
+ yasm_span *span; /* used only for check_cycle */
+ yasm_offset_setter *os;
+} optimize_data;
+
+static yasm_span *
+create_span(yasm_bytecode *bc, int id, /*@null@*/ const yasm_value *value,
+ long neg_thres, long pos_thres, yasm_offset_setter *os)
+{
+ yasm_span *span = yasm_xmalloc(sizeof(yasm_span));
+
+ span->bc = bc;
+ if (value)
+ yasm_value_init_copy(&span->depval, value);
+ else
+ yasm_value_initialize(&span->depval, NULL, 0);
+ span->rel_term = NULL;
+ span->terms = NULL;
+ span->items = NULL;
+ span->num_terms = 0;
+ span->cur_val = 0;
+ span->new_val = 0;
+ span->neg_thres = neg_thres;
+ span->pos_thres = pos_thres;
+ span->id = id;
+ span->active = 1;
+ span->backtrace = NULL;
+ span->backtrace_size = 0;
+ span->os = os;
+
+ return span;
+}
+
+static void
+optimize_add_span(void *add_span_data, yasm_bytecode *bc, int id,
+ const yasm_value *value, long neg_thres, long pos_thres)
+{
+ optimize_data *optd = (optimize_data *)add_span_data;
+ yasm_span *span;
+ span = create_span(bc, id, value, neg_thres, pos_thres, optd->os);
+ TAILQ_INSERT_TAIL(&optd->spans, span, link);
+}
+
+static void
+add_span_term(unsigned int subst, yasm_bytecode *precbc,
+ yasm_bytecode *precbc2, void *d)
+{
+ yasm_span *span = d;
+ yasm_intnum *intn;
+
+ if (subst >= span->num_terms) {
+ /* Linear expansion since total number is essentially always small */
+ span->num_terms = subst+1;
+ span->terms = yasm_xrealloc(span->terms,
+ span->num_terms*sizeof(yasm_span_term));
+ }
+ span->terms[subst].precbc = precbc;
+ span->terms[subst].precbc2 = precbc2;
+ span->terms[subst].span = span;
+ span->terms[subst].subst = subst;
+
+ intn = yasm_calc_bc_dist(precbc, precbc2);
+ if (!intn)
+ yasm_internal_error(N_("could not calculate bc distance"));
+ span->terms[subst].cur_val = 0;
+ span->terms[subst].new_val = yasm_intnum_get_int(intn);
+ yasm_intnum_destroy(intn);
+}
+
+static void
+span_create_terms(yasm_span *span)
+{
+ unsigned int i;
+
+ /* Split out sym-sym terms in absolute portion of dependent value */
+ if (span->depval.abs) {
+ span->num_terms = yasm_expr__bc_dist_subst(&span->depval.abs, span,
+ add_span_term);
+ if (span->num_terms > 0) {
+ span->items = yasm_xmalloc(span->num_terms*sizeof(yasm_expr__item));
+ for (i=0; i<span->num_terms; i++) {
+ /* Create items with dummy value */
+ span->items[i].type = YASM_EXPR_INT;
+ span->items[i].data.intn = yasm_intnum_create_int(0);
+
+ /* Check for circular references */
+ if (span->id <= 0 &&
+ ((span->bc->bc_index > span->terms[i].precbc->bc_index &&
+ span->bc->bc_index <= span->terms[i].precbc2->bc_index) ||
+ (span->bc->bc_index > span->terms[i].precbc2->bc_index &&
+ span->bc->bc_index <= span->terms[i].precbc->bc_index)))
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("circular reference detected"));
+ }
+ }
+ }
+
+ /* Create term for relative portion of dependent value */
+ if (span->depval.rel) {
+ yasm_bytecode *rel_precbc;
+ int sym_local;
+
+ sym_local = yasm_symrec_get_label(span->depval.rel, &rel_precbc);
+ if (span->depval.wrt || span->depval.seg_of || span->depval.section_rel
+ || !sym_local)
+ return; /* we can't handle SEG, WRT, or external symbols */
+ if (rel_precbc->section != span->bc->section)
+ return; /* not in this section */
+ if (!span->depval.curpos_rel)
+ return; /* not PC-relative */
+
+ span->rel_term = yasm_xmalloc(sizeof(yasm_span_term));
+ span->rel_term->precbc = NULL;
+ span->rel_term->precbc2 = rel_precbc;
+ span->rel_term->span = span;
+ span->rel_term->subst = ~0U;
+
+ span->rel_term->cur_val = 0;
+ span->rel_term->new_val = yasm_bc_next_offset(rel_precbc) -
+ span->bc->offset;
+ }
+}
+
+/* Recalculate span value based on current span replacement values.
+ * Returns 1 if span needs expansion (e.g. exceeded thresholds).
+ */
+static int
+recalc_normal_span(yasm_span *span)
+{
+ span->new_val = 0;
+
+ if (span->depval.abs) {
+ yasm_expr *abs_copy = yasm_expr_copy(span->depval.abs);
+ /*@null@*/ /*@dependent@*/ yasm_intnum *num;
+
+ /* Update sym-sym terms and substitute back into expr */
+ unsigned int i;
+ for (i=0; i<span->num_terms; i++)
+ yasm_intnum_set_int(span->items[i].data.intn,
+ span->terms[i].new_val);
+ yasm_expr__subst(abs_copy, span->num_terms, span->items);
+ num = yasm_expr_get_intnum(&abs_copy, 0);
+ if (num)
+ span->new_val = yasm_intnum_get_int(num);
+ else
+ span->new_val = LONG_MAX; /* too complex; force to longest form */
+ yasm_expr_destroy(abs_copy);
+ }
+
+ if (span->rel_term) {
+ if (span->new_val != LONG_MAX && span->rel_term->new_val != LONG_MAX)
+ span->new_val += span->rel_term->new_val >> span->depval.rshift;
+ else
+ span->new_val = LONG_MAX; /* too complex; force to longest form */
+ } else if (span->depval.rel)
+ span->new_val = LONG_MAX; /* too complex; force to longest form */
+
+ if (span->new_val == LONG_MAX)
+ span->active = 0;
+
+ /* If id<=0, flag update on any change */
+ if (span->id <= 0)
+ return (span->new_val != span->cur_val);
+
+ return (span->new_val < span->neg_thres
+ || span->new_val > span->pos_thres);
+}
+
+/* Updates all bytecode offsets. For offset-based bytecodes, calls expand
+ * to determine new length.
+ */
+static int
+update_all_bc_offsets(yasm_object *object, yasm_errwarns *errwarns)
+{
+ yasm_section *sect;
+ int saw_error = 0;
+
+ STAILQ_FOREACH(sect, &object->sections, link) {
+ unsigned long offset = 0;
+
+ yasm_bytecode *bc = STAILQ_FIRST(&sect->bcs);
+ yasm_bytecode *prevbc;
+
+ /* Skip our locally created empty bytecode first. */
+ prevbc = bc;
+ bc = STAILQ_NEXT(bc, link);
+
+ /* Iterate through the remainder, if any. */
+ while (bc) {
+ if (bc->callback->special == YASM_BC_SPECIAL_OFFSET) {
+ /* Recalculate/adjust len of offset-based bytecodes here */
+ long neg_thres = 0;
+ long pos_thres = (long)yasm_bc_next_offset(bc);
+ int retval = yasm_bc_expand(bc, 1, 0,
+ (long)yasm_bc_next_offset(prevbc),
+ &neg_thres, &pos_thres);
+ yasm_errwarn_propagate(errwarns, bc->line);
+ if (retval < 0)
+ saw_error = 1;
+ }
+ bc->offset = offset;
+ offset += bc->len*bc->mult_int;
+ prevbc = bc;
+ bc = STAILQ_NEXT(bc, link);
+ }
+ }
+ return saw_error;
+}
+
+static void
+span_destroy(/*@only@*/ yasm_span *span)
+{
+ unsigned int i;
+
+ yasm_value_delete(&span->depval);
+ if (span->rel_term)
+ yasm_xfree(span->rel_term);
+ if (span->terms)
+ yasm_xfree(span->terms);
+ if (span->items) {
+ for (i=0; i<span->num_terms; i++)
+ yasm_intnum_destroy(span->items[i].data.intn);
+ yasm_xfree(span->items);
+ }
+ if (span->backtrace)
+ yasm_xfree(span->backtrace);
+ yasm_xfree(span);
+}
+
+static void
+optimize_cleanup(optimize_data *optd)
+{
+ yasm_span *s1, *s2;
+ yasm_offset_setter *os1, *os2;
+
+ IT_destroy(optd->itree);
+
+ s1 = TAILQ_FIRST(&optd->spans);
+ while (s1) {
+ s2 = TAILQ_NEXT(s1, link);
+ span_destroy(s1);
+ s1 = s2;
+ }
+
+ os1 = STAILQ_FIRST(&optd->offset_setters);
+ while (os1) {
+ os2 = STAILQ_NEXT(os1, link);
+ yasm_xfree(os1);
+ os1 = os2;
+ }
+}
+
+static void
+optimize_itree_add(IntervalTree *itree, yasm_span *span, yasm_span_term *term)
+{
+ long precbc_index, precbc2_index;
+ unsigned long low, high;
+
+ /* Update term length */
+ if (term->precbc)
+ precbc_index = term->precbc->bc_index;
+ else
+ precbc_index = span->bc->bc_index-1;
+
+ if (term->precbc2)
+ precbc2_index = term->precbc2->bc_index;
+ else
+ precbc2_index = span->bc->bc_index-1;
+
+ if (precbc_index < precbc2_index) {
+ low = precbc_index+1;
+ high = precbc2_index;
+ } else if (precbc_index > precbc2_index) {
+ low = precbc2_index+1;
+ high = precbc_index;
+ } else
+ return; /* difference is same bc - always 0! */
+
+ IT_insert(itree, (long)low, (long)high, term);
+}
+
+static void
+check_cycle(IntervalTreeNode *node, void *d)
+{
+ optimize_data *optd = d;
+ yasm_span_term *term = node->data;
+ yasm_span *depspan = term->span;
+ int i;
+ int depspan_bt_alloc;
+
+ /* Only check for cycles in id=0 spans */
+ if (depspan->id > 0)
+ return;
+
+ /* Check for a circular reference by looking to see if this dependent
+ * span is in our backtrace.
+ */
+ if (optd->span->backtrace) {
+ for (i=0; i<optd->span->backtrace_size; i++) {
+ if (optd->span->backtrace[i] == depspan)
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("circular reference detected"));
+ }
+ }
+
+ /* Add our complete backtrace and ourselves to backtrace of dependent
+ * span.
+ */
+ if (!depspan->backtrace) {
+ depspan->backtrace = yasm_xmalloc((optd->span->backtrace_size+1)*
+ sizeof(yasm_span *));
+ if (optd->span->backtrace_size > 0)
+ memcpy(depspan->backtrace, optd->span->backtrace,
+ optd->span->backtrace_size*sizeof(yasm_span *));
+ depspan->backtrace[optd->span->backtrace_size] = optd->span;
+ depspan->backtrace_size = optd->span->backtrace_size+1;
+ return;
+ }
+
+ /* Add our complete backtrace, checking for duplicates */
+ depspan_bt_alloc = depspan->backtrace_size;
+ for (i=0; i<optd->span->backtrace_size; i++) {
+ int present = 0;
+ int j;
+ for (j=0; j<depspan->backtrace_size; j++) {
+ if (optd->span->backtrace[i] == optd->span->backtrace[j]) {
+ present = 1;
+ break;
+ }
+ }
+ if (present)
+ continue;
+ /* Not already in array; add it. */
+ if (depspan->backtrace_size >= depspan_bt_alloc)
+ {
+ depspan_bt_alloc *= 2;
+ depspan->backtrace =
+ yasm_xrealloc(depspan->backtrace,
+ depspan_bt_alloc*sizeof(yasm_span *));
+ }
+ depspan->backtrace[depspan->backtrace_size] = optd->span->backtrace[i];
+ depspan->backtrace_size++;
+ }
+
+ /* Add ourselves. */
+ if (depspan->backtrace_size >= depspan_bt_alloc)
+ {
+ depspan_bt_alloc++;
+ depspan->backtrace =
+ yasm_xrealloc(depspan->backtrace,
+ depspan_bt_alloc*sizeof(yasm_span *));
+ }
+ depspan->backtrace[depspan->backtrace_size] = optd->span;
+ depspan->backtrace_size++;
+}
+
+static void
+optimize_term_expand(IntervalTreeNode *node, void *d)
+{
+ optimize_data *optd = d;
+ yasm_span_term *term = node->data;
+ yasm_span *span = term->span;
+ long len_diff = optd->len_diff;
+ long precbc_index, precbc2_index;
+
+ /* Don't expand inactive spans */
+ if (!span->active)
+ return;
+
+ /* Update term length */
+ if (term->precbc)
+ precbc_index = term->precbc->bc_index;
+ else
+ precbc_index = span->bc->bc_index-1;
+
+ if (term->precbc2)
+ precbc2_index = term->precbc2->bc_index;
+ else
+ precbc2_index = span->bc->bc_index-1;
+
+ if (precbc_index < precbc2_index)
+ term->new_val += len_diff;
+ else
+ term->new_val -= len_diff;
+
+ /* If already on Q, don't re-add */
+ if (span->active == 2)
+ return;
+
+ /* Update term and check against thresholds */
+ if (!recalc_normal_span(span))
+ return; /* didn't exceed thresholds, we're done */
+
+ /* Exceeded thresholds, need to add to Q for expansion */
+ if (span->id <= 0)
+ STAILQ_INSERT_TAIL(&optd->QA, span, linkq);
+ else
+ STAILQ_INSERT_TAIL(&optd->QB, span, linkq);
+ span->active = 2; /* Mark as being in Q */
+}
+
+void
+yasm_object_optimize(yasm_object *object, yasm_errwarns *errwarns)
+{
+ yasm_section *sect;
+ unsigned long bc_index = 0;
+ int saw_error = 0;
+ optimize_data optd;
+ yasm_span *span, *span_temp;
+ yasm_offset_setter *os;
+ int retval;
+ unsigned int i;
+
+ TAILQ_INIT(&optd.spans);
+ STAILQ_INIT(&optd.offset_setters);
+ optd.itree = IT_create();
+
+ /* Create an placeholder offset setter for spans to point to; this will
+ * get updated if/when we actually run into one.
+ */
+ os = yasm_xmalloc(sizeof(yasm_offset_setter));
+ os->bc = NULL;
+ os->cur_val = 0;
+ os->new_val = 0;
+ os->thres = 0;
+ STAILQ_INSERT_TAIL(&optd.offset_setters, os, link);
+ optd.os = os;
+
+ /* Step 1a */
+ STAILQ_FOREACH(sect, &object->sections, link) {
+ unsigned long offset = 0;
+
+ yasm_bytecode *bc = STAILQ_FIRST(&sect->bcs);
+
+ bc->bc_index = bc_index++;
+
+ /* Skip our locally created empty bytecode first. */
+ bc = STAILQ_NEXT(bc, link);
+
+ /* Iterate through the remainder, if any. */
+ while (bc) {
+ bc->bc_index = bc_index++;
+ bc->offset = offset;
+
+ retval = yasm_bc_calc_len(bc, optimize_add_span, &optd);
+ yasm_errwarn_propagate(errwarns, bc->line);
+ if (retval)
+ saw_error = 1;
+ else {
+ if (bc->callback->special == YASM_BC_SPECIAL_OFFSET) {
+ /* Remember it as offset setter */
+ os->bc = bc;
+ os->thres = yasm_bc_next_offset(bc);
+
+ /* Create new placeholder */
+ os = yasm_xmalloc(sizeof(yasm_offset_setter));
+ os->bc = NULL;
+ os->cur_val = 0;
+ os->new_val = 0;
+ os->thres = 0;
+ STAILQ_INSERT_TAIL(&optd.offset_setters, os, link);
+ optd.os = os;
+
+ if (bc->multiple) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("cannot combine multiples and setting assembly position"));
+ yasm_errwarn_propagate(errwarns, bc->line);
+ saw_error = 1;
+ }
+ }
+
+ offset += bc->len*bc->mult_int;
+ }
+
+ bc = STAILQ_NEXT(bc, link);
+ }
+ }
+
+ if (saw_error) {
+ optimize_cleanup(&optd);
+ return;
+ }
+
+ /* Step 1b */
+ TAILQ_FOREACH_SAFE(span, &optd.spans, link, span_temp) {
+ span_create_terms(span);
+ if (yasm_error_occurred()) {
+ yasm_errwarn_propagate(errwarns, span->bc->line);
+ saw_error = 1;
+ } else if (recalc_normal_span(span)) {
+ retval = yasm_bc_expand(span->bc, span->id, span->cur_val,
+ span->new_val, &span->neg_thres,
+ &span->pos_thres);
+ yasm_errwarn_propagate(errwarns, span->bc->line);
+ if (retval < 0)
+ saw_error = 1;
+ else if (retval > 0) {
+ if (!span->active) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("secondary expansion of an external/complex value"));
+ yasm_errwarn_propagate(errwarns, span->bc->line);
+ saw_error = 1;
+ }
+ } else {
+ TAILQ_REMOVE(&optd.spans, span, link);
+ span_destroy(span);
+ continue;
+ }
+ }
+ span->cur_val = span->new_val;
+ }
+
+ if (saw_error) {
+ optimize_cleanup(&optd);
+ return;
+ }
+
+ /* Step 1c */
+ if (update_all_bc_offsets(object, errwarns)) {
+ optimize_cleanup(&optd);
+ return;
+ }
+
+ /* Step 1d */
+ STAILQ_INIT(&optd.QB);
+ TAILQ_FOREACH(span, &optd.spans, link) {
+ yasm_intnum *intn;
+
+ /* Update span terms based on new bc offsets */
+ for (i=0; i<span->num_terms; i++) {
+ intn = yasm_calc_bc_dist(span->terms[i].precbc,
+ span->terms[i].precbc2);
+ if (!intn)
+ yasm_internal_error(N_("could not calculate bc distance"));
+ span->terms[i].cur_val = span->terms[i].new_val;
+ span->terms[i].new_val = yasm_intnum_get_int(intn);
+ yasm_intnum_destroy(intn);
+ }
+ if (span->rel_term) {
+ span->rel_term->cur_val = span->rel_term->new_val;
+ if (span->rel_term->precbc2)
+ span->rel_term->new_val =
+ yasm_bc_next_offset(span->rel_term->precbc2) -
+ span->bc->offset;
+ else
+ span->rel_term->new_val = span->bc->offset -
+ yasm_bc_next_offset(span->rel_term->precbc);
+ }
+
+ if (recalc_normal_span(span)) {
+ /* Exceeded threshold, add span to QB */
+ STAILQ_INSERT_TAIL(&optd.QB, span, linkq);
+ span->active = 2;
+ }
+ }
+
+ /* Do we need step 2? If not, go ahead and exit. */
+ if (STAILQ_EMPTY(&optd.QB)) {
+ optimize_cleanup(&optd);
+ return;
+ }
+
+ /* Update offset-setters values */
+ STAILQ_FOREACH(os, &optd.offset_setters, link) {
+ if (!os->bc)
+ continue;
+ os->thres = yasm_bc_next_offset(os->bc);
+ os->new_val = os->bc->offset;
+ os->cur_val = os->new_val;
+ }
+
+ /* Build up interval tree */
+ TAILQ_FOREACH(span, &optd.spans, link) {
+ for (i=0; i<span->num_terms; i++)
+ optimize_itree_add(optd.itree, span, &span->terms[i]);
+ if (span->rel_term)
+ optimize_itree_add(optd.itree, span, span->rel_term);
+ }
+
+ /* Look for cycles in times expansion (span.id==0) */
+ TAILQ_FOREACH(span, &optd.spans, link) {
+ if (span->id > 0)
+ continue;
+ optd.span = span;
+ IT_enumerate(optd.itree, (long)span->bc->bc_index,
+ (long)span->bc->bc_index, &optd, check_cycle);
+ if (yasm_error_occurred()) {
+ yasm_errwarn_propagate(errwarns, span->bc->line);
+ saw_error = 1;
+ }
+ }
+
+ if (saw_error) {
+ optimize_cleanup(&optd);
+ return;
+ }
+
+ /* Step 2 */
+ STAILQ_INIT(&optd.QA);
+ while (!STAILQ_EMPTY(&optd.QA) || !(STAILQ_EMPTY(&optd.QB))) {
+ unsigned long orig_len;
+ long offset_diff;
+
+ /* QA is for TIMES, update those first, then update non-TIMES.
+ * This is so that TIMES can absorb increases before we look at
+ * expanding non-TIMES BCs.
+ */
+ if (!STAILQ_EMPTY(&optd.QA)) {
+ span = STAILQ_FIRST(&optd.QA);
+ STAILQ_REMOVE_HEAD(&optd.QA, linkq);
+ } else {
+ span = STAILQ_FIRST(&optd.QB);
+ STAILQ_REMOVE_HEAD(&optd.QB, linkq);
+ }
+
+ if (!span->active)
+ continue;
+ span->active = 1; /* no longer in Q */
+
+ /* Make sure we ended up ultimately exceeding thresholds; due to
+ * offset BCs we may have been placed on Q and then reduced in size
+ * again.
+ */
+ if (!recalc_normal_span(span))
+ continue;
+
+ orig_len = span->bc->len * span->bc->mult_int;
+
+ retval = yasm_bc_expand(span->bc, span->id, span->cur_val,
+ span->new_val, &span->neg_thres,
+ &span->pos_thres);
+ yasm_errwarn_propagate(errwarns, span->bc->line);
+
+ if (retval < 0) {
+ /* error */
+ saw_error = 1;
+ continue;
+ } else if (retval > 0) {
+ /* another threshold, keep active */
+ for (i=0; i<span->num_terms; i++)
+ span->terms[i].cur_val = span->terms[i].new_val;
+ if (span->rel_term)
+ span->rel_term->cur_val = span->rel_term->new_val;
+ span->cur_val = span->new_val;
+ } else
+ span->active = 0; /* we're done with this span */
+
+ optd.len_diff = span->bc->len * span->bc->mult_int - orig_len;
+ if (optd.len_diff == 0)
+ continue; /* didn't increase in size */
+
+ /* Iterate over all spans dependent across the bc just expanded */
+ IT_enumerate(optd.itree, (long)span->bc->bc_index,
+ (long)span->bc->bc_index, &optd, optimize_term_expand);
+
+ /* Iterate over offset-setters that follow the bc just expanded.
+ * Stop iteration if:
+ * - no more offset-setters in this section
+ * - offset-setter didn't move its following offset
+ */
+ os = span->os;
+ offset_diff = optd.len_diff;
+ while (os->bc && os->bc->section == span->bc->section
+ && offset_diff != 0) {
+ unsigned long old_next_offset = os->cur_val + os->bc->len;
+ long neg_thres_temp;
+
+ if (offset_diff < 0 && (unsigned long)(-offset_diff) > os->new_val)
+ yasm_internal_error(N_("org/align went to negative offset"));
+ os->new_val += offset_diff;
+
+ orig_len = os->bc->len;
+ retval = yasm_bc_expand(os->bc, 1, (long)os->cur_val,
+ (long)os->new_val, &neg_thres_temp,
+ (long *)&os->thres);
+ yasm_errwarn_propagate(errwarns, os->bc->line);
+
+ offset_diff = os->new_val + os->bc->len - old_next_offset;
+ optd.len_diff = os->bc->len - orig_len;
+ if (optd.len_diff != 0)
+ IT_enumerate(optd.itree, (long)os->bc->bc_index,
+ (long)os->bc->bc_index, &optd, optimize_term_expand);
+
+ os->cur_val = os->new_val;
+ os = STAILQ_NEXT(os, link);
+ }
+ }
+
+ if (saw_error) {
+ optimize_cleanup(&optd);
+ return;
+ }
+
+ /* Step 3 */
+ update_all_bc_offsets(object, errwarns);
+ optimize_cleanup(&optd);
+}
diff --git a/contrib/tools/yasm/libyasm/section.h b/contrib/tools/yasm/libyasm/section.h
index 521031f3a5..dd88117348 100644
--- a/contrib/tools/yasm/libyasm/section.h
+++ b/contrib/tools/yasm/libyasm/section.h
@@ -1,384 +1,384 @@
-/**
- * \file libyasm/section.h
- * \brief YASM section interface.
- *
- * \license
- * Copyright (C) 2001-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- * \endlicense
- */
-#ifndef YASM_SECTION_H
-#define YASM_SECTION_H
-
-#ifndef YASM_LIB_DECL
-#define YASM_LIB_DECL
-#endif
-
-/** Basic YASM relocation. Object formats will need to extend this
- * structure with additional fields for relocation type, etc.
- */
-typedef struct yasm_reloc yasm_reloc;
-
-struct yasm_reloc {
- /*@reldef@*/ STAILQ_ENTRY(yasm_reloc) link; /**< Link to next reloc */
- yasm_intnum *addr; /**< Offset (address) within section */
- /*@dependent@*/ yasm_symrec *sym; /**< Relocated symbol */
-};
-
-/** An object. This is the internal representation of an object file. */
-struct yasm_object {
- /*@owned@*/ char *src_filename; /**< Source filename */
+/**
+ * \file libyasm/section.h
+ * \brief YASM section interface.
+ *
+ * \license
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * \endlicense
+ */
+#ifndef YASM_SECTION_H
+#define YASM_SECTION_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/** Basic YASM relocation. Object formats will need to extend this
+ * structure with additional fields for relocation type, etc.
+ */
+typedef struct yasm_reloc yasm_reloc;
+
+struct yasm_reloc {
+ /*@reldef@*/ STAILQ_ENTRY(yasm_reloc) link; /**< Link to next reloc */
+ yasm_intnum *addr; /**< Offset (address) within section */
+ /*@dependent@*/ yasm_symrec *sym; /**< Relocated symbol */
+};
+
+/** An object. This is the internal representation of an object file. */
+struct yasm_object {
+ /*@owned@*/ char *src_filename; /**< Source filename */
/*@owned@*/ char *deb_filename; /**< Debug filename */
- /*@owned@*/ char *obj_filename; /**< Object filename */
-
- /*@owned@*/ yasm_symtab *symtab; /**< Symbol table */
- /*@owned@*/ yasm_arch *arch; /**< Target architecture */
- /*@owned@*/ yasm_objfmt *objfmt; /**< Object format */
- /*@owned@*/ yasm_dbgfmt *dbgfmt; /**< Debug format */
-
- /** Currently active section. Used by some directives. NULL if no
- * section active.
- */
- /*@dependent@*/ /*@null@*/ yasm_section *cur_section;
-
- /** Linked list of sections. */
- /*@reldef@*/ STAILQ_HEAD(yasm_sectionhead, yasm_section) sections;
-
- /** Directives, organized as two level HAMT; first level is parser,
- * second level is directive name.
- */
- /*@owned@*/ struct HAMT *directives;
-
- /** Prefix prepended to externally-visible symbols (empty string if none) */
- /*@owned@*/ char *global_prefix;
-
- /** Suffix appended to externally-visible symbols (empty string if none) */
- /*@owned@*/ char *global_suffix;
-};
-
-/** Create a new object. A default section is created as the first section.
- * An empty symbol table (yasm_symtab) and line mapping (yasm_linemap) are
- * automatically created.
- * \param src_filename source filename (e.g. "file.asm")
- * \param obj_filename object filename (e.g. "file.o")
- * \param arch architecture
- * \param objfmt_module object format module
- * \param dbgfmt_module debug format module
- * \return Newly allocated object, or NULL on error.
- */
-YASM_LIB_DECL
-/*@null@*/ /*@only@*/ yasm_object *yasm_object_create
- (const char *src_filename, const char *obj_filename,
- /*@kept@*/ yasm_arch *arch,
- const yasm_objfmt_module *objfmt_module,
- const yasm_dbgfmt_module *dbgfmt_module);
-
-/** Create a new, or continue an existing, general section. The section is
- * added to the object if there's not already a section by that name.
- * \param object object
- * \param name section name
- * \param align alignment in bytes (0 if none)
- * \param code if nonzero, section is intended to contain code
- * (e.g. alignment should be made with NOP instructions, not 0)
- * \param res_only if nonzero, only space-reserving bytecodes are allowed in
- * the section (ignored if section already exists)
- * \param isnew output; set to nonzero if section did not already exist
- * \param line virtual line of section declaration (ignored if section
- * already exists)
- * \return New section.
- */
-YASM_LIB_DECL
-/*@dependent@*/ yasm_section *yasm_object_get_general
- (yasm_object *object, const char *name, unsigned long align, int code,
- int res_only, /*@out@*/ int *isnew, unsigned long line);
-
-/** Handle a directive. Passed down to object format, debug format, or
- * architecture as appropriate.
- * \param object object
- * \param name directive name
- * \param parser parser keyword
- * \param valparams value/parameters
- * \param objext_valparams "object format-specific" value/parameters
- * \param line virtual line (from yasm_linemap)
- * \return 0 if directive recognized, nonzero if unrecognized.
- */
-YASM_LIB_DECL
-int yasm_object_directive(yasm_object *object, const char *name,
- const char *parser, yasm_valparamhead *valparams,
- yasm_valparamhead *objext_valparams,
- unsigned long line);
-
-/** Delete (free allocated memory for) an object. All sections in the
- * object and all bytecodes within those sections are also deleted.
- * \param object object
- */
-YASM_LIB_DECL
-void yasm_object_destroy(/*@only@*/ yasm_object *object);
-
-/** Print an object. For debugging purposes.
- * \param object object
- * \param f file
- * \param indent_level indentation level
- */
-YASM_LIB_DECL
-void yasm_object_print(const yasm_object *object, FILE *f, int indent_level);
-
-/** Finalize an object after parsing.
- * \param object object
- * \param errwarns error/warning set
- * \note Errors/warnings are stored into errwarns.
- */
-YASM_LIB_DECL
-void yasm_object_finalize(yasm_object *object, yasm_errwarns *errwarns);
-
-/** Traverses all sections in an object, calling a function on each section.
- * \param object object
- * \param d data pointer passed to func on each call
- * \param func function
- * \return Stops early (and returns func's return value) if func returns a
- * nonzero value; otherwise 0.
- */
-YASM_LIB_DECL
-int yasm_object_sections_traverse
- (yasm_object *object, /*@null@*/ void *d,
- int (*func) (yasm_section *sect, /*@null@*/ void *d));
-
-/** Find a general section in an object, based on its name.
- * \param object object
- * \param name section name
- * \return Section matching name, or NULL if no match found.
- */
-YASM_LIB_DECL
-/*@dependent@*/ /*@null@*/ yasm_section *yasm_object_find_general
- (yasm_object *object, const char *name);
-
-/** Change the source filename for an object.
- * \param object object
- * \param src_filename new source filename (e.g. "file.asm")
- */
-YASM_LIB_DECL
-void yasm_object_set_source_fn(yasm_object *object, const char *src_filename);
-
-/** Change the prefix used for externally-visible symbols.
- * \param object object
- * \param prefix new prefix
- */
-YASM_LIB_DECL
-void yasm_object_set_global_prefix(yasm_object *object, const char *prefix);
-
-/** Change the suffix used for externally-visible symbols.
- * \param object object
- * \param suffix new suffix
- */
-YASM_LIB_DECL
-void yasm_object_set_global_suffix(yasm_object *object, const char *suffix);
-
-/** Optimize an object. Takes the unoptimized object and optimizes it.
- * If successful, the object is ready for output to an object file.
- * \param object object
- * \param errwarns error/warning set
- * \note Optimization failures are stored into errwarns.
- */
-YASM_LIB_DECL
-void yasm_object_optimize(yasm_object *object, yasm_errwarns *errwarns);
-
-/** Determine if a section is flagged to contain code.
- * \param sect section
- * \return Nonzero if section is flagged to contain code.
- */
-YASM_LIB_DECL
-int yasm_section_is_code(yasm_section *sect);
-
-/** Get yasm_optimizer-specific flags. For yasm_optimizer use only.
- * \param sect section
- * \return Optimizer-specific flags.
- */
-YASM_LIB_DECL
-unsigned long yasm_section_get_opt_flags(const yasm_section *sect);
-
-/** Set yasm_optimizer-specific flags. For yasm_optimizer use only.
- * \param sect section
- * \param opt_flags optimizer-specific flags.
- */
-YASM_LIB_DECL
-void yasm_section_set_opt_flags(yasm_section *sect, unsigned long opt_flags);
-
-/** Determine if a section was declared as the "default" section (e.g. not
- * created through a section directive).
- * \param sect section
- * \return Nonzero if section was declared as default.
- */
-YASM_LIB_DECL
-int yasm_section_is_default(const yasm_section *sect);
-
-/** Set section "default" flag to a new value.
- * \param sect section
- * \param def new value of default flag
- */
-YASM_LIB_DECL
-void yasm_section_set_default(yasm_section *sect, int def);
-
-/** Get object owner of a section.
- * \param sect section
- * \return Object this section is a part of.
- */
-YASM_LIB_DECL
-yasm_object *yasm_section_get_object(const yasm_section *sect);
-
-/** Get assocated data for a section and data callback.
- * \param sect section
- * \param callback callback used when adding data
- * \return Associated data (NULL if none).
- */
-YASM_LIB_DECL
-/*@dependent@*/ /*@null@*/ void *yasm_section_get_data
- (yasm_section *sect, const yasm_assoc_data_callback *callback);
-
-/** Add associated data to a section.
- * \attention Deletes any existing associated data for that data callback.
- * \param sect section
- * \param callback callback
- * \param data data to associate
- */
-YASM_LIB_DECL
-void yasm_section_add_data(yasm_section *sect,
- const yasm_assoc_data_callback *callback,
- /*@null@*/ /*@only@*/ void *data);
-
-/** Add a relocation to a section.
- * \param sect section
- * \param reloc relocation
- * \param destroy_func function that can destroy the relocation
- * \note Does not make a copy of reloc. The same destroy_func must be
- * used for all relocations in a section or an internal error will occur.
- * The section will destroy the relocation address; it is the caller's
- * responsibility to destroy any other allocated data.
- */
-YASM_LIB_DECL
-void yasm_section_add_reloc(yasm_section *sect, yasm_reloc *reloc,
- void (*destroy_func) (/*@only@*/ void *reloc));
-
-/** Get the first relocation for a section.
- * \param sect section
- * \return First relocation for section. NULL if no relocations.
- */
-YASM_LIB_DECL
-/*@null@*/ yasm_reloc *yasm_section_relocs_first(yasm_section *sect);
-
-/** Get the next relocation for a section.
- * \param reloc previous relocation
- * \return Next relocation for section. NULL if no more relocations.
- */
-/*@null@*/ yasm_reloc *yasm_section_reloc_next(yasm_reloc *reloc);
-#ifndef YASM_DOXYGEN
-#define yasm_section_reloc_next(x) STAILQ_NEXT((x), link)
-#endif
-
-/** Get the basic relocation information for a relocation.
- * \param reloc relocation
- * \param addrp address of relocation within section (returned)
- * \param symp relocated symbol (returned)
- */
-YASM_LIB_DECL
-void yasm_reloc_get(yasm_reloc *reloc, yasm_intnum **addrp,
- /*@dependent@*/ yasm_symrec **symp);
-
-/** Get the first bytecode in a section.
- * \param sect section
- * \return First bytecode in section (at least one empty bytecode is always
- * present).
- */
-YASM_LIB_DECL
-yasm_bytecode *yasm_section_bcs_first(yasm_section *sect);
-
-/** Get the last bytecode in a section.
- * \param sect section
- * \return Last bytecode in section (at least one empty bytecode is always
- * present).
- */
-YASM_LIB_DECL
-yasm_bytecode *yasm_section_bcs_last(yasm_section *sect);
-
-/** Add bytecode to the end of a section.
- * \note Does not make a copy of bc; so don't pass this function static or
- * local variables, and discard the bc pointer after calling this
- * function.
- * \param sect section
- * \param bc bytecode (may be NULL)
- * \return If bytecode was actually appended (it wasn't NULL or empty), the
- * bytecode; otherwise NULL.
- */
-YASM_LIB_DECL
-/*@only@*/ /*@null@*/ yasm_bytecode *yasm_section_bcs_append
- (yasm_section *sect,
- /*@returned@*/ /*@only@*/ /*@null@*/ yasm_bytecode *bc);
-
-/** Traverses all bytecodes in a section, calling a function on each bytecode.
- * \param sect section
- * \param errwarns error/warning set (may be NULL)
- * \param d data pointer passed to func on each call (may be NULL)
- * \param func function
- * \return Stops early (and returns func's return value) if func returns a
- * nonzero value; otherwise 0.
- * \note If errwarns is non-NULL, yasm_errwarn_propagate() is called after
- * each call to func (with the bytecode's line number).
- */
-YASM_LIB_DECL
-int yasm_section_bcs_traverse
- (yasm_section *sect, /*@null@*/ yasm_errwarns *errwarns,
- /*@null@*/ void *d, int (*func) (yasm_bytecode *bc, /*@null@*/ void *d));
-
-/** Get name of a section.
- * \param sect section
- * \return Section name.
- */
-YASM_LIB_DECL
-/*@observer@*/ const char *yasm_section_get_name(const yasm_section *sect);
-
-/** Change alignment of a section.
- * \param sect section
- * \param align alignment in bytes
- * \param line virtual line
- */
-YASM_LIB_DECL
-void yasm_section_set_align(yasm_section *sect, unsigned long align,
- unsigned long line);
-
-/** Get alignment of a section.
- * \param sect section
- * \return Alignment in bytes (0 if none).
- */
-YASM_LIB_DECL
-unsigned long yasm_section_get_align(const yasm_section *sect);
-
-/** Print a section. For debugging purposes.
- * \param f file
- * \param indent_level indentation level
- * \param sect section
- * \param print_bcs if nonzero, print bytecodes within section
- */
-YASM_LIB_DECL
-void yasm_section_print(/*@null@*/ const yasm_section *sect, FILE *f,
- int indent_level, int print_bcs);
-
-#endif
+ /*@owned@*/ char *obj_filename; /**< Object filename */
+
+ /*@owned@*/ yasm_symtab *symtab; /**< Symbol table */
+ /*@owned@*/ yasm_arch *arch; /**< Target architecture */
+ /*@owned@*/ yasm_objfmt *objfmt; /**< Object format */
+ /*@owned@*/ yasm_dbgfmt *dbgfmt; /**< Debug format */
+
+ /** Currently active section. Used by some directives. NULL if no
+ * section active.
+ */
+ /*@dependent@*/ /*@null@*/ yasm_section *cur_section;
+
+ /** Linked list of sections. */
+ /*@reldef@*/ STAILQ_HEAD(yasm_sectionhead, yasm_section) sections;
+
+ /** Directives, organized as two level HAMT; first level is parser,
+ * second level is directive name.
+ */
+ /*@owned@*/ struct HAMT *directives;
+
+ /** Prefix prepended to externally-visible symbols (empty string if none) */
+ /*@owned@*/ char *global_prefix;
+
+ /** Suffix appended to externally-visible symbols (empty string if none) */
+ /*@owned@*/ char *global_suffix;
+};
+
+/** Create a new object. A default section is created as the first section.
+ * An empty symbol table (yasm_symtab) and line mapping (yasm_linemap) are
+ * automatically created.
+ * \param src_filename source filename (e.g. "file.asm")
+ * \param obj_filename object filename (e.g. "file.o")
+ * \param arch architecture
+ * \param objfmt_module object format module
+ * \param dbgfmt_module debug format module
+ * \return Newly allocated object, or NULL on error.
+ */
+YASM_LIB_DECL
+/*@null@*/ /*@only@*/ yasm_object *yasm_object_create
+ (const char *src_filename, const char *obj_filename,
+ /*@kept@*/ yasm_arch *arch,
+ const yasm_objfmt_module *objfmt_module,
+ const yasm_dbgfmt_module *dbgfmt_module);
+
+/** Create a new, or continue an existing, general section. The section is
+ * added to the object if there's not already a section by that name.
+ * \param object object
+ * \param name section name
+ * \param align alignment in bytes (0 if none)
+ * \param code if nonzero, section is intended to contain code
+ * (e.g. alignment should be made with NOP instructions, not 0)
+ * \param res_only if nonzero, only space-reserving bytecodes are allowed in
+ * the section (ignored if section already exists)
+ * \param isnew output; set to nonzero if section did not already exist
+ * \param line virtual line of section declaration (ignored if section
+ * already exists)
+ * \return New section.
+ */
+YASM_LIB_DECL
+/*@dependent@*/ yasm_section *yasm_object_get_general
+ (yasm_object *object, const char *name, unsigned long align, int code,
+ int res_only, /*@out@*/ int *isnew, unsigned long line);
+
+/** Handle a directive. Passed down to object format, debug format, or
+ * architecture as appropriate.
+ * \param object object
+ * \param name directive name
+ * \param parser parser keyword
+ * \param valparams value/parameters
+ * \param objext_valparams "object format-specific" value/parameters
+ * \param line virtual line (from yasm_linemap)
+ * \return 0 if directive recognized, nonzero if unrecognized.
+ */
+YASM_LIB_DECL
+int yasm_object_directive(yasm_object *object, const char *name,
+ const char *parser, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams,
+ unsigned long line);
+
+/** Delete (free allocated memory for) an object. All sections in the
+ * object and all bytecodes within those sections are also deleted.
+ * \param object object
+ */
+YASM_LIB_DECL
+void yasm_object_destroy(/*@only@*/ yasm_object *object);
+
+/** Print an object. For debugging purposes.
+ * \param object object
+ * \param f file
+ * \param indent_level indentation level
+ */
+YASM_LIB_DECL
+void yasm_object_print(const yasm_object *object, FILE *f, int indent_level);
+
+/** Finalize an object after parsing.
+ * \param object object
+ * \param errwarns error/warning set
+ * \note Errors/warnings are stored into errwarns.
+ */
+YASM_LIB_DECL
+void yasm_object_finalize(yasm_object *object, yasm_errwarns *errwarns);
+
+/** Traverses all sections in an object, calling a function on each section.
+ * \param object object
+ * \param d data pointer passed to func on each call
+ * \param func function
+ * \return Stops early (and returns func's return value) if func returns a
+ * nonzero value; otherwise 0.
+ */
+YASM_LIB_DECL
+int yasm_object_sections_traverse
+ (yasm_object *object, /*@null@*/ void *d,
+ int (*func) (yasm_section *sect, /*@null@*/ void *d));
+
+/** Find a general section in an object, based on its name.
+ * \param object object
+ * \param name section name
+ * \return Section matching name, or NULL if no match found.
+ */
+YASM_LIB_DECL
+/*@dependent@*/ /*@null@*/ yasm_section *yasm_object_find_general
+ (yasm_object *object, const char *name);
+
+/** Change the source filename for an object.
+ * \param object object
+ * \param src_filename new source filename (e.g. "file.asm")
+ */
+YASM_LIB_DECL
+void yasm_object_set_source_fn(yasm_object *object, const char *src_filename);
+
+/** Change the prefix used for externally-visible symbols.
+ * \param object object
+ * \param prefix new prefix
+ */
+YASM_LIB_DECL
+void yasm_object_set_global_prefix(yasm_object *object, const char *prefix);
+
+/** Change the suffix used for externally-visible symbols.
+ * \param object object
+ * \param suffix new suffix
+ */
+YASM_LIB_DECL
+void yasm_object_set_global_suffix(yasm_object *object, const char *suffix);
+
+/** Optimize an object. Takes the unoptimized object and optimizes it.
+ * If successful, the object is ready for output to an object file.
+ * \param object object
+ * \param errwarns error/warning set
+ * \note Optimization failures are stored into errwarns.
+ */
+YASM_LIB_DECL
+void yasm_object_optimize(yasm_object *object, yasm_errwarns *errwarns);
+
+/** Determine if a section is flagged to contain code.
+ * \param sect section
+ * \return Nonzero if section is flagged to contain code.
+ */
+YASM_LIB_DECL
+int yasm_section_is_code(yasm_section *sect);
+
+/** Get yasm_optimizer-specific flags. For yasm_optimizer use only.
+ * \param sect section
+ * \return Optimizer-specific flags.
+ */
+YASM_LIB_DECL
+unsigned long yasm_section_get_opt_flags(const yasm_section *sect);
+
+/** Set yasm_optimizer-specific flags. For yasm_optimizer use only.
+ * \param sect section
+ * \param opt_flags optimizer-specific flags.
+ */
+YASM_LIB_DECL
+void yasm_section_set_opt_flags(yasm_section *sect, unsigned long opt_flags);
+
+/** Determine if a section was declared as the "default" section (e.g. not
+ * created through a section directive).
+ * \param sect section
+ * \return Nonzero if section was declared as default.
+ */
+YASM_LIB_DECL
+int yasm_section_is_default(const yasm_section *sect);
+
+/** Set section "default" flag to a new value.
+ * \param sect section
+ * \param def new value of default flag
+ */
+YASM_LIB_DECL
+void yasm_section_set_default(yasm_section *sect, int def);
+
+/** Get object owner of a section.
+ * \param sect section
+ * \return Object this section is a part of.
+ */
+YASM_LIB_DECL
+yasm_object *yasm_section_get_object(const yasm_section *sect);
+
+/** Get assocated data for a section and data callback.
+ * \param sect section
+ * \param callback callback used when adding data
+ * \return Associated data (NULL if none).
+ */
+YASM_LIB_DECL
+/*@dependent@*/ /*@null@*/ void *yasm_section_get_data
+ (yasm_section *sect, const yasm_assoc_data_callback *callback);
+
+/** Add associated data to a section.
+ * \attention Deletes any existing associated data for that data callback.
+ * \param sect section
+ * \param callback callback
+ * \param data data to associate
+ */
+YASM_LIB_DECL
+void yasm_section_add_data(yasm_section *sect,
+ const yasm_assoc_data_callback *callback,
+ /*@null@*/ /*@only@*/ void *data);
+
+/** Add a relocation to a section.
+ * \param sect section
+ * \param reloc relocation
+ * \param destroy_func function that can destroy the relocation
+ * \note Does not make a copy of reloc. The same destroy_func must be
+ * used for all relocations in a section or an internal error will occur.
+ * The section will destroy the relocation address; it is the caller's
+ * responsibility to destroy any other allocated data.
+ */
+YASM_LIB_DECL
+void yasm_section_add_reloc(yasm_section *sect, yasm_reloc *reloc,
+ void (*destroy_func) (/*@only@*/ void *reloc));
+
+/** Get the first relocation for a section.
+ * \param sect section
+ * \return First relocation for section. NULL if no relocations.
+ */
+YASM_LIB_DECL
+/*@null@*/ yasm_reloc *yasm_section_relocs_first(yasm_section *sect);
+
+/** Get the next relocation for a section.
+ * \param reloc previous relocation
+ * \return Next relocation for section. NULL if no more relocations.
+ */
+/*@null@*/ yasm_reloc *yasm_section_reloc_next(yasm_reloc *reloc);
+#ifndef YASM_DOXYGEN
+#define yasm_section_reloc_next(x) STAILQ_NEXT((x), link)
+#endif
+
+/** Get the basic relocation information for a relocation.
+ * \param reloc relocation
+ * \param addrp address of relocation within section (returned)
+ * \param symp relocated symbol (returned)
+ */
+YASM_LIB_DECL
+void yasm_reloc_get(yasm_reloc *reloc, yasm_intnum **addrp,
+ /*@dependent@*/ yasm_symrec **symp);
+
+/** Get the first bytecode in a section.
+ * \param sect section
+ * \return First bytecode in section (at least one empty bytecode is always
+ * present).
+ */
+YASM_LIB_DECL
+yasm_bytecode *yasm_section_bcs_first(yasm_section *sect);
+
+/** Get the last bytecode in a section.
+ * \param sect section
+ * \return Last bytecode in section (at least one empty bytecode is always
+ * present).
+ */
+YASM_LIB_DECL
+yasm_bytecode *yasm_section_bcs_last(yasm_section *sect);
+
+/** Add bytecode to the end of a section.
+ * \note Does not make a copy of bc; so don't pass this function static or
+ * local variables, and discard the bc pointer after calling this
+ * function.
+ * \param sect section
+ * \param bc bytecode (may be NULL)
+ * \return If bytecode was actually appended (it wasn't NULL or empty), the
+ * bytecode; otherwise NULL.
+ */
+YASM_LIB_DECL
+/*@only@*/ /*@null@*/ yasm_bytecode *yasm_section_bcs_append
+ (yasm_section *sect,
+ /*@returned@*/ /*@only@*/ /*@null@*/ yasm_bytecode *bc);
+
+/** Traverses all bytecodes in a section, calling a function on each bytecode.
+ * \param sect section
+ * \param errwarns error/warning set (may be NULL)
+ * \param d data pointer passed to func on each call (may be NULL)
+ * \param func function
+ * \return Stops early (and returns func's return value) if func returns a
+ * nonzero value; otherwise 0.
+ * \note If errwarns is non-NULL, yasm_errwarn_propagate() is called after
+ * each call to func (with the bytecode's line number).
+ */
+YASM_LIB_DECL
+int yasm_section_bcs_traverse
+ (yasm_section *sect, /*@null@*/ yasm_errwarns *errwarns,
+ /*@null@*/ void *d, int (*func) (yasm_bytecode *bc, /*@null@*/ void *d));
+
+/** Get name of a section.
+ * \param sect section
+ * \return Section name.
+ */
+YASM_LIB_DECL
+/*@observer@*/ const char *yasm_section_get_name(const yasm_section *sect);
+
+/** Change alignment of a section.
+ * \param sect section
+ * \param align alignment in bytes
+ * \param line virtual line
+ */
+YASM_LIB_DECL
+void yasm_section_set_align(yasm_section *sect, unsigned long align,
+ unsigned long line);
+
+/** Get alignment of a section.
+ * \param sect section
+ * \return Alignment in bytes (0 if none).
+ */
+YASM_LIB_DECL
+unsigned long yasm_section_get_align(const yasm_section *sect);
+
+/** Print a section. For debugging purposes.
+ * \param f file
+ * \param indent_level indentation level
+ * \param sect section
+ * \param print_bcs if nonzero, print bytecodes within section
+ */
+YASM_LIB_DECL
+void yasm_section_print(/*@null@*/ const yasm_section *sect, FILE *f,
+ int indent_level, int print_bcs);
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/strcasecmp.c b/contrib/tools/yasm/libyasm/strcasecmp.c
index a87bd88bc9..a905ec7724 100644
--- a/contrib/tools/yasm/libyasm/strcasecmp.c
+++ b/contrib/tools/yasm/libyasm/strcasecmp.c
@@ -1,94 +1,94 @@
-/*
- * strcasecmp() implementation for systems that don't have it or stricmp()
- * or strcmpi().
- *
- * Copyright (c) 1987, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include "util.h"
-
-#ifndef USE_OUR_OWN_STRCASECMP
-#undef yasm__strcasecmp
-#undef yasm__strncasecmp
-#endif
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)strcasecmp.c 8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
-
-#include <ctype.h>
-
-int
-yasm__strcasecmp(const char *s1, const char *s2)
-{
-#ifdef HAVE_STRCASECMP
- return strcasecmp(s1, s2);
-#elif HAVE_STRICMP
- return stricmp(s1, s2);
-#elif HAVE__STRICMP
- return _stricmp(s1, s2);
-#elif HAVE_STRCMPI
- return strcmpi(s1, s2);
-#else
- const unsigned char
- *us1 = (const unsigned char *)s1,
- *us2 = (const unsigned char *)s2;
-
- while (tolower(*us1) == tolower(*us2++))
- if (*us1++ == '\0')
- return (0);
- return (tolower(*us1) - tolower(*--us2));
-#endif
-}
-
-int
-yasm__strncasecmp(const char *s1, const char *s2, size_t n)
-{
-#ifdef HAVE_STRCASECMP
- return strncasecmp(s1, s2, n);
-#elif HAVE_STRICMP
- return strnicmp(s1, s2, n);
-#elif HAVE__STRNICMP
- return _strnicmp(s1, s2, n);
-#elif HAVE_STRCMPI
- return strncmpi(s1, s2, n);
-#else
- const unsigned char
- *us1 = (const unsigned char *)s1,
- *us2 = (const unsigned char *)s2;
-
- if (n != 0) {
- do {
- if (tolower(*us1) != tolower(*us2++))
- return (tolower(*us1) - tolower(*--us2));
- if (*us1++ == '\0')
- break;
- } while (--n != 0);
- }
- return (0);
-#endif
-}
+/*
+ * strcasecmp() implementation for systems that don't have it or stricmp()
+ * or strcmpi().
+ *
+ * Copyright (c) 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "util.h"
+
+#ifndef USE_OUR_OWN_STRCASECMP
+#undef yasm__strcasecmp
+#undef yasm__strncasecmp
+#endif
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strcasecmp.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <ctype.h>
+
+int
+yasm__strcasecmp(const char *s1, const char *s2)
+{
+#ifdef HAVE_STRCASECMP
+ return strcasecmp(s1, s2);
+#elif HAVE_STRICMP
+ return stricmp(s1, s2);
+#elif HAVE__STRICMP
+ return _stricmp(s1, s2);
+#elif HAVE_STRCMPI
+ return strcmpi(s1, s2);
+#else
+ const unsigned char
+ *us1 = (const unsigned char *)s1,
+ *us2 = (const unsigned char *)s2;
+
+ while (tolower(*us1) == tolower(*us2++))
+ if (*us1++ == '\0')
+ return (0);
+ return (tolower(*us1) - tolower(*--us2));
+#endif
+}
+
+int
+yasm__strncasecmp(const char *s1, const char *s2, size_t n)
+{
+#ifdef HAVE_STRCASECMP
+ return strncasecmp(s1, s2, n);
+#elif HAVE_STRICMP
+ return strnicmp(s1, s2, n);
+#elif HAVE__STRNICMP
+ return _strnicmp(s1, s2, n);
+#elif HAVE_STRCMPI
+ return strncmpi(s1, s2, n);
+#else
+ const unsigned char
+ *us1 = (const unsigned char *)s1,
+ *us2 = (const unsigned char *)s2;
+
+ if (n != 0) {
+ do {
+ if (tolower(*us1) != tolower(*us2++))
+ return (tolower(*us1) - tolower(*--us2));
+ if (*us1++ == '\0')
+ break;
+ } while (--n != 0);
+ }
+ return (0);
+#endif
+}
diff --git a/contrib/tools/yasm/libyasm/strsep.c b/contrib/tools/yasm/libyasm/strsep.c
index 5688a60879..8320acf056 100644
--- a/contrib/tools/yasm/libyasm/strsep.c
+++ b/contrib/tools/yasm/libyasm/strsep.c
@@ -1,85 +1,85 @@
-/*
- * strsep() implementation for systems that don't have it.
- *
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#define NO_STRING_INLINES
-#include "util.h"
-
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)strsep.c 8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
-
-#ifdef HAVE_STRSEP
-#undef yasm__strsep
-#endif
-
-/*
- * Get next token from string *stringp, where tokens are possibly-empty
- * strings separated by characters from delim.
- *
- * Writes NULs into the string at *stringp to end tokens.
- * delim need not remain constant from call to call.
- * On return, *stringp points past the last NUL written (if there might
- * be further tokens), or is NULL (if there are definitely no more tokens).
- *
- * If *stringp is NULL, strsep returns NULL.
- */
-/*@-nullstate@*/
-char *
-yasm__strsep(char **stringp, const char *delim)
-{
-#ifdef HAVE_STRSEP
- return strsep(stringp, delim);
-#else
+/*
+ * strsep() implementation for systems that don't have it.
+ *
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#define NO_STRING_INLINES
+#include "util.h"
+
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strsep.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef HAVE_STRSEP
+#undef yasm__strsep
+#endif
+
+/*
+ * Get next token from string *stringp, where tokens are possibly-empty
+ * strings separated by characters from delim.
+ *
+ * Writes NULs into the string at *stringp to end tokens.
+ * delim need not remain constant from call to call.
+ * On return, *stringp points past the last NUL written (if there might
+ * be further tokens), or is NULL (if there are definitely no more tokens).
+ *
+ * If *stringp is NULL, strsep returns NULL.
+ */
+/*@-nullstate@*/
+char *
+yasm__strsep(char **stringp, const char *delim)
+{
+#ifdef HAVE_STRSEP
+ return strsep(stringp, delim);
+#else
char *s;
const char *spanp;
int c, sc;
- char *tok;
-
- if ((s = *stringp) == NULL)
- return (NULL);
- for (tok = s;;) {
- c = *s++;
- spanp = delim;
- do {
- if ((sc = *spanp++) == c) {
- if (c == 0)
- s = NULL;
- else
- s[-1] = 0;
- *stringp = s;
- return (tok);
- }
- } while (sc != 0);
- }
- /* NOTREACHED */
-#endif
-}
-/*@=nullstate@*/
+ char *tok;
+
+ if ((s = *stringp) == NULL)
+ return (NULL);
+ for (tok = s;;) {
+ c = *s++;
+ spanp = delim;
+ do {
+ if ((sc = *spanp++) == c) {
+ if (c == 0)
+ s = NULL;
+ else
+ s[-1] = 0;
+ *stringp = s;
+ return (tok);
+ }
+ } while (sc != 0);
+ }
+ /* NOTREACHED */
+#endif
+}
+/*@=nullstate@*/
diff --git a/contrib/tools/yasm/libyasm/symrec.c b/contrib/tools/yasm/libyasm/symrec.c
index 694f0c6768..1c188c99d8 100644
--- a/contrib/tools/yasm/libyasm/symrec.c
+++ b/contrib/tools/yasm/libyasm/symrec.c
@@ -1,714 +1,714 @@
-/*
- * Symbol table handling
- *
- * Copyright (C) 2001-2007 Michael Urman, Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#include "util.h"
-
-#include <limits.h>
-#include <ctype.h>
-
-#include "libyasm-stdint.h"
-#include "coretype.h"
-#include "valparam.h"
-#include "hamt.h"
-#include "assocdat.h"
-
-#include "errwarn.h"
-#include "intnum.h"
-#include "floatnum.h"
-#include "expr.h"
-#include "symrec.h"
-
-#include "bytecode.h"
-#include "section.h"
-#include "objfmt.h"
-
-
-typedef enum {
- SYM_UNKNOWN, /* for unknown type (COMMON/EXTERN) */
- SYM_EQU, /* for EQU defined symbols (expressions) */
- SYM_LABEL, /* for labels */
- SYM_CURPOS, /* for labels representing the current
- assembly position */
- SYM_SPECIAL /* for special symbols that need to be in
- the symbol table but otherwise have no
- purpose */
-} sym_type;
-
-struct yasm_symrec {
- char *name;
- sym_type type;
- yasm_sym_status status;
- yasm_sym_vis visibility;
- unsigned long def_line; /* line where symbol was first defined */
- unsigned long decl_line; /* line where symbol was first declared */
- unsigned long use_line; /* line where symbol was first used */
- union {
- yasm_expr *expn; /* equ value */
-
- /* bytecode immediately preceding a label */
- /*@dependent@*/ yasm_bytecode *precbc;
- } value;
- unsigned int size; /* 0 if not user-defined */
- const char *segment; /* for segmented systems like DOS */
-
- /* associated data; NULL if none */
- /*@null@*/ /*@only@*/ yasm__assoc_data *assoc_data;
-};
-
-/* Linked list of symbols not in the symbol table. */
-typedef struct non_table_symrec_s {
- /*@reldef@*/ SLIST_ENTRY(non_table_symrec_s) link;
- /*@owned@*/ yasm_symrec *rec;
-} non_table_symrec;
-
-struct yasm_symtab {
- /* The symbol table: a hash array mapped trie (HAMT). */
- /*@only@*/ HAMT *sym_table;
- /* Symbols not in the table */
- SLIST_HEAD(nontablesymhead_s, non_table_symrec_s) non_table_syms;
-
- int case_sensitive;
-};
-
-static void
-objext_valparams_destroy(void *data)
-{
- yasm_vps_destroy((yasm_valparamhead *)data);
-}
-
-static void
-objext_valparams_print(void *data, FILE *f, int indent_level)
-{
- yasm_vps_print((yasm_valparamhead *)data, f);
-}
-
-static yasm_assoc_data_callback objext_valparams_cb = {
- objext_valparams_destroy,
- objext_valparams_print
-};
-
-static void
-common_size_destroy(void *data)
-{
- yasm_expr **e = (yasm_expr **)data;
- yasm_expr_destroy(*e);
- yasm_xfree(data);
-}
-
-static void
-common_size_print(void *data, FILE *f, int indent_level)
-{
- yasm_expr **e = (yasm_expr **)data;
- yasm_expr_print(*e, f);
-}
-
-static yasm_assoc_data_callback common_size_cb = {
- common_size_destroy,
- common_size_print
-};
-
-yasm_symtab *
-yasm_symtab_create(void)
-{
- yasm_symtab *symtab = yasm_xmalloc(sizeof(yasm_symtab));
- symtab->sym_table = HAMT_create(0, yasm_internal_error_);
- SLIST_INIT(&symtab->non_table_syms);
- symtab->case_sensitive = 1;
- return symtab;
-}
-
-void
-yasm_symtab_set_case_sensitive(yasm_symtab *symtab, int sensitive)
-{
- symtab->case_sensitive = sensitive;
-}
-
-static void
-symrec_destroy_one(/*@only@*/ void *d)
-{
- yasm_symrec *sym = d;
- yasm_xfree(sym->name);
- if (sym->type == SYM_EQU && (sym->status & YASM_SYM_VALUED))
- yasm_expr_destroy(sym->value.expn);
- yasm__assoc_data_destroy(sym->assoc_data);
- yasm_xfree(sym);
-}
-
-static /*@partial@*/ yasm_symrec *
-symrec_new_common(/*@keep@*/ char *name, int case_sensitive)
-{
- yasm_symrec *rec = yasm_xmalloc(sizeof(yasm_symrec));
-
- if (!case_sensitive) {
- char *c;
- for (c=name; *c; c++)
- *c = tolower(*c);
- }
-
- rec->name = name;
- rec->type = SYM_UNKNOWN;
- rec->def_line = 0;
- rec->decl_line = 0;
- rec->use_line = 0;
- rec->visibility = YASM_SYM_LOCAL;
- rec->size = 0;
- rec->segment = NULL;
- rec->assoc_data = NULL;
- return rec;
-}
-
-static /*@partial@*/ /*@dependent@*/ yasm_symrec *
-symtab_get_or_new_in_table(yasm_symtab *symtab, /*@only@*/ char *name)
-{
- yasm_symrec *rec = symrec_new_common(name, symtab->case_sensitive);
- int replace = 0;
-
- rec->status = YASM_SYM_NOSTATUS;
-
- if (!symtab->case_sensitive) {
- char *c;
- for (c=name; *c; c++)
- *c = tolower(*c);
- }
-
- return HAMT_insert(symtab->sym_table, name, rec, &replace,
- symrec_destroy_one);
-}
-
-static /*@partial@*/ /*@dependent@*/ yasm_symrec *
-symtab_get_or_new_not_in_table(yasm_symtab *symtab, /*@only@*/ char *name)
-{
- non_table_symrec *sym = yasm_xmalloc(sizeof(non_table_symrec));
- sym->rec = symrec_new_common(name, symtab->case_sensitive);
-
- sym->rec->status = YASM_SYM_NOTINTABLE;
-
- SLIST_INSERT_HEAD(&symtab->non_table_syms, sym, link);
-
- return sym->rec;
-}
-
-/* create a new symrec */
-/*@-freshtrans -mustfree@*/
-static /*@partial@*/ /*@dependent@*/ yasm_symrec *
-symtab_get_or_new(yasm_symtab *symtab, const char *name, int in_table)
-{
- char *symname = yasm__xstrdup(name);
-
- if (in_table)
- return symtab_get_or_new_in_table(symtab, symname);
- else
- return symtab_get_or_new_not_in_table(symtab, symname);
-}
-/*@=freshtrans =mustfree@*/
-
-int
-yasm_symtab_traverse(yasm_symtab *symtab, void *d,
- int (*func) (yasm_symrec *sym, void *d))
-{
- return HAMT_traverse(symtab->sym_table, d, (int (*) (void *, void *))func);
-}
-
-const yasm_symtab_iter *
-yasm_symtab_first(const yasm_symtab *symtab)
-{
- return (const yasm_symtab_iter *)HAMT_first(symtab->sym_table);
-}
-
-/*@null@*/ const yasm_symtab_iter *
-yasm_symtab_next(const yasm_symtab_iter *prev)
-{
- return (const yasm_symtab_iter *)HAMT_next((const HAMTEntry *)prev);
-}
-
-yasm_symrec *
-yasm_symtab_iter_value(const yasm_symtab_iter *cur)
-{
- return (yasm_symrec *)HAMTEntry_get_data((const HAMTEntry *)cur);
-}
-
-yasm_symrec *
-yasm_symtab_abs_sym(yasm_symtab *symtab)
-{
- yasm_symrec *rec = symtab_get_or_new(symtab, "", 1);
- rec->def_line = 0;
- rec->decl_line = 0;
- rec->use_line = 0;
- rec->type = SYM_EQU;
- rec->value.expn =
- yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_uint(0)), 0);
- rec->status |= YASM_SYM_DEFINED|YASM_SYM_VALUED|YASM_SYM_USED;
- return rec;
-}
-
-yasm_symrec *
-yasm_symtab_use(yasm_symtab *symtab, const char *name, unsigned long line)
-{
- yasm_symrec *rec = symtab_get_or_new(symtab, name, 1);
- if (rec->use_line == 0)
- rec->use_line = line; /* set line number of first use */
- rec->status |= YASM_SYM_USED;
- return rec;
-}
-
-yasm_symrec *
-yasm_symtab_get(yasm_symtab *symtab, const char *name)
-{
- if (!symtab->case_sensitive) {
- char *_name = yasm__xstrdup(name);
- char *c;
- yasm_symrec *ret;
- for (c=_name; *c; c++)
- *c = tolower(*c);
- ret = HAMT_search(symtab->sym_table, _name);
- yasm_xfree(_name);
- return ret;
- } else
- return HAMT_search(symtab->sym_table, name);
-}
-
-static /*@dependent@*/ yasm_symrec *
-symtab_define(yasm_symtab *symtab, const char *name, sym_type type,
- int in_table, unsigned long line)
-{
- yasm_symrec *rec = symtab_get_or_new(symtab, name, in_table);
-
- /* Has it been defined before (either by DEFINED or COMMON/EXTERN)? */
- if (rec->status & YASM_SYM_DEFINED) {
- yasm_error_set_xref(rec->def_line!=0 ? rec->def_line : rec->decl_line,
- N_("`%s' previously defined here"), name);
- yasm_error_set(YASM_ERROR_GENERAL, N_("redefinition of `%s'"),
- name);
- } else {
- if (rec->visibility & YASM_SYM_EXTERN)
- yasm_warn_set(YASM_WARN_GENERAL,
- N_("`%s' both defined and declared extern"), name);
- rec->def_line = line; /* set line number of definition */
- rec->type = type;
- rec->status |= YASM_SYM_DEFINED;
- rec->size = 0;
- rec->segment = NULL;
- }
- return rec;
-}
-
-yasm_symrec *
-yasm_symtab_define_equ(yasm_symtab *symtab, const char *name, yasm_expr *e,
- unsigned long line)
-{
- yasm_symrec *rec = symtab_define(symtab, name, SYM_EQU, 1, line);
- if (yasm_error_occurred())
- return rec;
- rec->value.expn = e;
- rec->status |= YASM_SYM_VALUED;
- return rec;
-}
-
-yasm_symrec *
-yasm_symtab_define_label(yasm_symtab *symtab, const char *name,
- yasm_bytecode *precbc, int in_table,
- unsigned long line)
-{
- yasm_symrec *rec = symtab_define(symtab, name, SYM_LABEL, in_table, line);
- if (yasm_error_occurred())
- return rec;
- rec->value.precbc = precbc;
- if (in_table && precbc)
- yasm_bc__add_symrec(precbc, rec);
- return rec;
-}
-
-yasm_symrec *
-yasm_symtab_define_curpos(yasm_symtab *symtab, const char *name,
- yasm_bytecode *precbc, unsigned long line)
-{
- yasm_symrec *rec = symtab_define(symtab, name, SYM_CURPOS, 0, line);
- if (yasm_error_occurred())
- return rec;
- rec->value.precbc = precbc;
- return rec;
-}
-
-yasm_symrec *
-yasm_symtab_define_special(yasm_symtab *symtab, const char *name,
- yasm_sym_vis vis)
-{
- yasm_symrec *rec = symtab_define(symtab, name, SYM_SPECIAL, 1, 0);
- if (yasm_error_occurred())
- return rec;
- rec->status |= YASM_SYM_VALUED;
- rec->visibility = vis;
- return rec;
-}
-
-yasm_symrec *
-yasm_symtab_declare(yasm_symtab *symtab, const char *name, yasm_sym_vis vis,
- unsigned long line)
-{
- yasm_symrec *rec = symtab_get_or_new(symtab, name, 1);
- yasm_symrec_declare(rec, vis, line);
- return rec;
-}
-
-void
-yasm_symrec_declare(yasm_symrec *rec, yasm_sym_vis vis, unsigned long line)
-{
- /* Allowable combinations:
- * Existing State-------------- vis New State-------------------
- * DEFINED GLOBAL COMMON EXTERN GCE DEFINED GLOBAL COMMON EXTERN
- * 0 - 0 0 GCE 0 G C E
- * 0 - 0 1 GE 0 G 0 E
- * 0 - 1 0 GC 0 G C 0
- * X 0 - 1 1
- * 1 - 0 0 G 1 G 0 0
- * X 1 - - 1
- * X 1 - 1 -
- */
- if ((vis == YASM_SYM_GLOBAL) ||
- (!(rec->status & YASM_SYM_DEFINED) &&
- (!(rec->visibility & (YASM_SYM_COMMON | YASM_SYM_EXTERN)) ||
- ((rec->visibility & YASM_SYM_COMMON) && (vis == YASM_SYM_COMMON)) ||
- ((rec->visibility & YASM_SYM_EXTERN) && (vis == YASM_SYM_EXTERN))))) {
- rec->decl_line = line;
- rec->visibility |= vis;
- } else
- yasm_error_set(YASM_ERROR_GENERAL,
- N_("duplicate definition of `%s'; first defined on line %lu"),
- rec->name, rec->def_line!=0 ? rec->def_line : rec->decl_line);
-}
-
-typedef struct symtab_finalize_info {
- unsigned long firstundef_line;
- int undef_extern;
- yasm_errwarns *errwarns;
-} symtab_finalize_info;
-
-static int
-symtab_parser_finalize_checksym(yasm_symrec *sym, /*@null@*/ void *d)
-{
- symtab_finalize_info *info = (symtab_finalize_info *)d;
-
- /* error if a symbol is used but never defined or extern/common declared */
- if ((sym->status & YASM_SYM_USED) && !(sym->status & YASM_SYM_DEFINED) &&
- !(sym->visibility & (YASM_SYM_EXTERN | YASM_SYM_COMMON))) {
- if (info->undef_extern)
- sym->visibility |= YASM_SYM_EXTERN;
- else {
- yasm_error_set(YASM_ERROR_GENERAL,
- N_("undefined symbol `%s' (first use)"), sym->name);
- yasm_errwarn_propagate(info->errwarns, sym->use_line);
- if (sym->use_line < info->firstundef_line)
- info->firstundef_line = sym->use_line;
- }
- }
-
- return 0;
-}
-
-void
-yasm_symtab_parser_finalize(yasm_symtab *symtab, int undef_extern,
- yasm_errwarns *errwarns)
-{
- symtab_finalize_info info;
- info.firstundef_line = ULONG_MAX;
- info.undef_extern = undef_extern;
- info.errwarns = errwarns;
- yasm_symtab_traverse(symtab, &info, symtab_parser_finalize_checksym);
- if (info.firstundef_line < ULONG_MAX) {
- yasm_error_set(YASM_ERROR_GENERAL,
- N_(" (Each undefined symbol is reported only once.)"));
- yasm_errwarn_propagate(errwarns, info.firstundef_line);
- }
-}
-
-void
-yasm_symtab_destroy(yasm_symtab *symtab)
-{
- HAMT_destroy(symtab->sym_table, symrec_destroy_one);
-
- while (!SLIST_EMPTY(&symtab->non_table_syms)) {
- non_table_symrec *sym = SLIST_FIRST(&symtab->non_table_syms);
- SLIST_REMOVE_HEAD(&symtab->non_table_syms, link);
- symrec_destroy_one(sym->rec);
- yasm_xfree(sym);
- }
-
- yasm_xfree(symtab);
-}
-
-typedef struct symrec_print_data {
- FILE *f;
- int indent_level;
-} symrec_print_data;
-
-/*@+voidabstract@*/
-static int
-symrec_print_wrapper(yasm_symrec *sym, /*@null@*/ void *d)
-{
- symrec_print_data *data = (symrec_print_data *)d;
- assert(data != NULL);
- fprintf(data->f, "%*sSymbol `%s'\n", data->indent_level, "", sym->name);
- yasm_symrec_print(sym, data->f, data->indent_level+1);
- return 0;
-}
-
-void
-yasm_symtab_print(yasm_symtab *symtab, FILE *f, int indent_level)
-{
- symrec_print_data data;
- data.f = f;
- data.indent_level = indent_level;
- yasm_symtab_traverse(symtab, &data, symrec_print_wrapper);
-}
-/*@=voidabstract@*/
-
-const char *
-yasm_symrec_get_name(const yasm_symrec *sym)
-{
- return sym->name;
-}
-
-char *
-yasm_symrec_get_global_name(const yasm_symrec *sym, const yasm_object *object)
-{
- if (sym->visibility & (YASM_SYM_GLOBAL|YASM_SYM_COMMON|YASM_SYM_EXTERN)) {
- char *name = yasm_xmalloc(strlen(object->global_prefix) +
- strlen(sym->name) +
- strlen(object->global_suffix) + 1);
- strcpy(name, object->global_prefix);
- strcat(name, sym->name);
- strcat(name, object->global_suffix);
- return name;
- }
- return yasm__xstrdup(sym->name);
-}
-
-yasm_sym_vis
-yasm_symrec_get_visibility(const yasm_symrec *sym)
-{
- return sym->visibility;
-}
-
-yasm_sym_status
-yasm_symrec_get_status(const yasm_symrec *sym)
-{
- return sym->status;
-}
-
-unsigned long
-yasm_symrec_get_def_line(const yasm_symrec *sym)
-{
- return sym->def_line;
-}
-
-unsigned long
-yasm_symrec_get_decl_line(const yasm_symrec *sym)
-{
- return sym->decl_line;
-}
-
-unsigned long
-yasm_symrec_get_use_line(const yasm_symrec *sym)
-{
- return sym->use_line;
-}
-
-const yasm_expr *
-yasm_symrec_get_equ(const yasm_symrec *sym)
-{
- if (sym->type == SYM_EQU && (sym->status & YASM_SYM_VALUED))
- return sym->value.expn;
- return (const yasm_expr *)NULL;
-}
-
-int
-yasm_symrec_get_label(const yasm_symrec *sym,
- yasm_symrec_get_label_bytecodep *precbc)
-{
- if (!(sym->type == SYM_LABEL || sym->type == SYM_CURPOS)
- || !sym->value.precbc) {
- *precbc = (yasm_symrec_get_label_bytecodep)0xDEADBEEF;
- return 0;
- }
- *precbc = sym->value.precbc;
- return 1;
-}
-
-void
-yasm_symrec_set_size(yasm_symrec *sym, int size)
-{
- sym->size = size;
-}
-
-int
-yasm_symrec_get_size(const yasm_symrec *sym)
-{
- return sym->size;
-}
-
-void
-yasm_symrec_set_segment(yasm_symrec *sym, const char *segment)
-{
- sym->segment = segment;
-}
-
-const char *
-yasm_symrec_get_segment(const yasm_symrec *sym)
-{
- return sym->segment;
-}
-
-int
-yasm_symrec_is_abs(const yasm_symrec *sym)
-{
- return (sym->def_line == 0 && sym->type == SYM_EQU &&
- sym->name[0] == '\0');
-}
-
-int
-yasm_symrec_is_special(const yasm_symrec *sym)
-{
- return (sym->type == SYM_SPECIAL);
-}
-
-int
-yasm_symrec_is_curpos(const yasm_symrec *sym)
-{
- return (sym->type == SYM_CURPOS);
-}
-
-void
-yasm_symrec_set_objext_valparams(yasm_symrec *sym,
- /*@only@*/ yasm_valparamhead *objext_valparams)
-{
- yasm_symrec_add_data(sym, &objext_valparams_cb, objext_valparams);
-}
-
-yasm_valparamhead *
-yasm_symrec_get_objext_valparams(yasm_symrec *sym)
-{
- return yasm_symrec_get_data(sym, &objext_valparams_cb);
-}
-
-void
-yasm_symrec_set_common_size(yasm_symrec *sym,
- /*@only@*/ yasm_expr *common_size)
-{
- yasm_expr **ep = yasm_xmalloc(sizeof(yasm_expr *));
- *ep = common_size;
- yasm_symrec_add_data(sym, &common_size_cb, ep);
-}
-
-yasm_expr **
-yasm_symrec_get_common_size(yasm_symrec *sym)
-{
- return (yasm_expr **)yasm_symrec_get_data(sym, &common_size_cb);
-}
-
-void *
-yasm_symrec_get_data(yasm_symrec *sym,
- const yasm_assoc_data_callback *callback)
-{
- return yasm__assoc_data_get(sym->assoc_data, callback);
-}
-
-void
-yasm_symrec_add_data(yasm_symrec *sym,
- const yasm_assoc_data_callback *callback, void *data)
-{
- sym->assoc_data = yasm__assoc_data_add(sym->assoc_data, callback, data);
-}
-
-void
-yasm_symrec_print(const yasm_symrec *sym, FILE *f, int indent_level)
-{
- switch (sym->type) {
- case SYM_UNKNOWN:
- fprintf(f, "%*s-Unknown (Common/Extern)-\n", indent_level, "");
- break;
- case SYM_EQU:
- fprintf(f, "%*s_EQU_\n", indent_level, "");
- fprintf(f, "%*sExpn=", indent_level, "");
- if (sym->status & YASM_SYM_VALUED)
- yasm_expr_print(sym->value.expn, f);
- else
- fprintf(f, "***UNVALUED***");
- fprintf(f, "\n");
- break;
- case SYM_LABEL:
- case SYM_CURPOS:
- fprintf(f, "%*s_%s_\n%*sSection:\n", indent_level, "",
- sym->type == SYM_LABEL ? "Label" : "CurPos",
- indent_level, "");
- yasm_section_print(yasm_bc_get_section(sym->value.precbc), f,
- indent_level+1, 0);
- fprintf(f, "%*sPreceding bytecode:\n", indent_level, "");
- yasm_bc_print(sym->value.precbc, f, indent_level+1);
- break;
- case SYM_SPECIAL:
- fprintf(f, "%*s-Special-\n", indent_level, "");
- break;
- }
-
- fprintf(f, "%*sStatus=", indent_level, "");
- if (sym->status == YASM_SYM_NOSTATUS)
- fprintf(f, "None\n");
- else {
- if (sym->status & YASM_SYM_USED)
- fprintf(f, "Used,");
- if (sym->status & YASM_SYM_DEFINED)
- fprintf(f, "Defined,");
- if (sym->status & YASM_SYM_VALUED)
- fprintf(f, "Valued,");
- if (sym->status & YASM_SYM_NOTINTABLE)
- fprintf(f, "Not in Table,");
- fprintf(f, "\n");
- }
-
- fprintf(f, "%*sVisibility=", indent_level, "");
- if (sym->visibility == YASM_SYM_LOCAL)
- fprintf(f, "Local\n");
- else {
- if (sym->visibility & YASM_SYM_GLOBAL)
- fprintf(f, "Global,");
- if (sym->visibility & YASM_SYM_COMMON)
- fprintf(f, "Common,");
- if (sym->visibility & YASM_SYM_EXTERN)
- fprintf(f, "Extern,");
- fprintf(f, "\n");
- }
-
- if (sym->assoc_data) {
- fprintf(f, "%*sAssociated data:\n", indent_level, "");
- yasm__assoc_data_print(sym->assoc_data, f, indent_level+1);
- }
-
- fprintf(f, "%*sLine Index (Defined)=%lu\n", indent_level, "",
- sym->def_line);
- fprintf(f, "%*sLine Index (Declared)=%lu\n", indent_level, "",
- sym->decl_line);
- fprintf(f, "%*sLine Index (Used)=%lu\n", indent_level, "", sym->use_line);
-}
+/*
+ * Symbol table handling
+ *
+ * Copyright (C) 2001-2007 Michael Urman, Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "util.h"
+
+#include <limits.h>
+#include <ctype.h>
+
+#include "libyasm-stdint.h"
+#include "coretype.h"
+#include "valparam.h"
+#include "hamt.h"
+#include "assocdat.h"
+
+#include "errwarn.h"
+#include "intnum.h"
+#include "floatnum.h"
+#include "expr.h"
+#include "symrec.h"
+
+#include "bytecode.h"
+#include "section.h"
+#include "objfmt.h"
+
+
+typedef enum {
+ SYM_UNKNOWN, /* for unknown type (COMMON/EXTERN) */
+ SYM_EQU, /* for EQU defined symbols (expressions) */
+ SYM_LABEL, /* for labels */
+ SYM_CURPOS, /* for labels representing the current
+ assembly position */
+ SYM_SPECIAL /* for special symbols that need to be in
+ the symbol table but otherwise have no
+ purpose */
+} sym_type;
+
+struct yasm_symrec {
+ char *name;
+ sym_type type;
+ yasm_sym_status status;
+ yasm_sym_vis visibility;
+ unsigned long def_line; /* line where symbol was first defined */
+ unsigned long decl_line; /* line where symbol was first declared */
+ unsigned long use_line; /* line where symbol was first used */
+ union {
+ yasm_expr *expn; /* equ value */
+
+ /* bytecode immediately preceding a label */
+ /*@dependent@*/ yasm_bytecode *precbc;
+ } value;
+ unsigned int size; /* 0 if not user-defined */
+ const char *segment; /* for segmented systems like DOS */
+
+ /* associated data; NULL if none */
+ /*@null@*/ /*@only@*/ yasm__assoc_data *assoc_data;
+};
+
+/* Linked list of symbols not in the symbol table. */
+typedef struct non_table_symrec_s {
+ /*@reldef@*/ SLIST_ENTRY(non_table_symrec_s) link;
+ /*@owned@*/ yasm_symrec *rec;
+} non_table_symrec;
+
+struct yasm_symtab {
+ /* The symbol table: a hash array mapped trie (HAMT). */
+ /*@only@*/ HAMT *sym_table;
+ /* Symbols not in the table */
+ SLIST_HEAD(nontablesymhead_s, non_table_symrec_s) non_table_syms;
+
+ int case_sensitive;
+};
+
+static void
+objext_valparams_destroy(void *data)
+{
+ yasm_vps_destroy((yasm_valparamhead *)data);
+}
+
+static void
+objext_valparams_print(void *data, FILE *f, int indent_level)
+{
+ yasm_vps_print((yasm_valparamhead *)data, f);
+}
+
+static yasm_assoc_data_callback objext_valparams_cb = {
+ objext_valparams_destroy,
+ objext_valparams_print
+};
+
+static void
+common_size_destroy(void *data)
+{
+ yasm_expr **e = (yasm_expr **)data;
+ yasm_expr_destroy(*e);
+ yasm_xfree(data);
+}
+
+static void
+common_size_print(void *data, FILE *f, int indent_level)
+{
+ yasm_expr **e = (yasm_expr **)data;
+ yasm_expr_print(*e, f);
+}
+
+static yasm_assoc_data_callback common_size_cb = {
+ common_size_destroy,
+ common_size_print
+};
+
+yasm_symtab *
+yasm_symtab_create(void)
+{
+ yasm_symtab *symtab = yasm_xmalloc(sizeof(yasm_symtab));
+ symtab->sym_table = HAMT_create(0, yasm_internal_error_);
+ SLIST_INIT(&symtab->non_table_syms);
+ symtab->case_sensitive = 1;
+ return symtab;
+}
+
+void
+yasm_symtab_set_case_sensitive(yasm_symtab *symtab, int sensitive)
+{
+ symtab->case_sensitive = sensitive;
+}
+
+static void
+symrec_destroy_one(/*@only@*/ void *d)
+{
+ yasm_symrec *sym = d;
+ yasm_xfree(sym->name);
+ if (sym->type == SYM_EQU && (sym->status & YASM_SYM_VALUED))
+ yasm_expr_destroy(sym->value.expn);
+ yasm__assoc_data_destroy(sym->assoc_data);
+ yasm_xfree(sym);
+}
+
+static /*@partial@*/ yasm_symrec *
+symrec_new_common(/*@keep@*/ char *name, int case_sensitive)
+{
+ yasm_symrec *rec = yasm_xmalloc(sizeof(yasm_symrec));
+
+ if (!case_sensitive) {
+ char *c;
+ for (c=name; *c; c++)
+ *c = tolower(*c);
+ }
+
+ rec->name = name;
+ rec->type = SYM_UNKNOWN;
+ rec->def_line = 0;
+ rec->decl_line = 0;
+ rec->use_line = 0;
+ rec->visibility = YASM_SYM_LOCAL;
+ rec->size = 0;
+ rec->segment = NULL;
+ rec->assoc_data = NULL;
+ return rec;
+}
+
+static /*@partial@*/ /*@dependent@*/ yasm_symrec *
+symtab_get_or_new_in_table(yasm_symtab *symtab, /*@only@*/ char *name)
+{
+ yasm_symrec *rec = symrec_new_common(name, symtab->case_sensitive);
+ int replace = 0;
+
+ rec->status = YASM_SYM_NOSTATUS;
+
+ if (!symtab->case_sensitive) {
+ char *c;
+ for (c=name; *c; c++)
+ *c = tolower(*c);
+ }
+
+ return HAMT_insert(symtab->sym_table, name, rec, &replace,
+ symrec_destroy_one);
+}
+
+static /*@partial@*/ /*@dependent@*/ yasm_symrec *
+symtab_get_or_new_not_in_table(yasm_symtab *symtab, /*@only@*/ char *name)
+{
+ non_table_symrec *sym = yasm_xmalloc(sizeof(non_table_symrec));
+ sym->rec = symrec_new_common(name, symtab->case_sensitive);
+
+ sym->rec->status = YASM_SYM_NOTINTABLE;
+
+ SLIST_INSERT_HEAD(&symtab->non_table_syms, sym, link);
+
+ return sym->rec;
+}
+
+/* create a new symrec */
+/*@-freshtrans -mustfree@*/
+static /*@partial@*/ /*@dependent@*/ yasm_symrec *
+symtab_get_or_new(yasm_symtab *symtab, const char *name, int in_table)
+{
+ char *symname = yasm__xstrdup(name);
+
+ if (in_table)
+ return symtab_get_or_new_in_table(symtab, symname);
+ else
+ return symtab_get_or_new_not_in_table(symtab, symname);
+}
+/*@=freshtrans =mustfree@*/
+
+int
+yasm_symtab_traverse(yasm_symtab *symtab, void *d,
+ int (*func) (yasm_symrec *sym, void *d))
+{
+ return HAMT_traverse(symtab->sym_table, d, (int (*) (void *, void *))func);
+}
+
+const yasm_symtab_iter *
+yasm_symtab_first(const yasm_symtab *symtab)
+{
+ return (const yasm_symtab_iter *)HAMT_first(symtab->sym_table);
+}
+
+/*@null@*/ const yasm_symtab_iter *
+yasm_symtab_next(const yasm_symtab_iter *prev)
+{
+ return (const yasm_symtab_iter *)HAMT_next((const HAMTEntry *)prev);
+}
+
+yasm_symrec *
+yasm_symtab_iter_value(const yasm_symtab_iter *cur)
+{
+ return (yasm_symrec *)HAMTEntry_get_data((const HAMTEntry *)cur);
+}
+
+yasm_symrec *
+yasm_symtab_abs_sym(yasm_symtab *symtab)
+{
+ yasm_symrec *rec = symtab_get_or_new(symtab, "", 1);
+ rec->def_line = 0;
+ rec->decl_line = 0;
+ rec->use_line = 0;
+ rec->type = SYM_EQU;
+ rec->value.expn =
+ yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_uint(0)), 0);
+ rec->status |= YASM_SYM_DEFINED|YASM_SYM_VALUED|YASM_SYM_USED;
+ return rec;
+}
+
+yasm_symrec *
+yasm_symtab_use(yasm_symtab *symtab, const char *name, unsigned long line)
+{
+ yasm_symrec *rec = symtab_get_or_new(symtab, name, 1);
+ if (rec->use_line == 0)
+ rec->use_line = line; /* set line number of first use */
+ rec->status |= YASM_SYM_USED;
+ return rec;
+}
+
+yasm_symrec *
+yasm_symtab_get(yasm_symtab *symtab, const char *name)
+{
+ if (!symtab->case_sensitive) {
+ char *_name = yasm__xstrdup(name);
+ char *c;
+ yasm_symrec *ret;
+ for (c=_name; *c; c++)
+ *c = tolower(*c);
+ ret = HAMT_search(symtab->sym_table, _name);
+ yasm_xfree(_name);
+ return ret;
+ } else
+ return HAMT_search(symtab->sym_table, name);
+}
+
+static /*@dependent@*/ yasm_symrec *
+symtab_define(yasm_symtab *symtab, const char *name, sym_type type,
+ int in_table, unsigned long line)
+{
+ yasm_symrec *rec = symtab_get_or_new(symtab, name, in_table);
+
+ /* Has it been defined before (either by DEFINED or COMMON/EXTERN)? */
+ if (rec->status & YASM_SYM_DEFINED) {
+ yasm_error_set_xref(rec->def_line!=0 ? rec->def_line : rec->decl_line,
+ N_("`%s' previously defined here"), name);
+ yasm_error_set(YASM_ERROR_GENERAL, N_("redefinition of `%s'"),
+ name);
+ } else {
+ if (rec->visibility & YASM_SYM_EXTERN)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("`%s' both defined and declared extern"), name);
+ rec->def_line = line; /* set line number of definition */
+ rec->type = type;
+ rec->status |= YASM_SYM_DEFINED;
+ rec->size = 0;
+ rec->segment = NULL;
+ }
+ return rec;
+}
+
+yasm_symrec *
+yasm_symtab_define_equ(yasm_symtab *symtab, const char *name, yasm_expr *e,
+ unsigned long line)
+{
+ yasm_symrec *rec = symtab_define(symtab, name, SYM_EQU, 1, line);
+ if (yasm_error_occurred())
+ return rec;
+ rec->value.expn = e;
+ rec->status |= YASM_SYM_VALUED;
+ return rec;
+}
+
+yasm_symrec *
+yasm_symtab_define_label(yasm_symtab *symtab, const char *name,
+ yasm_bytecode *precbc, int in_table,
+ unsigned long line)
+{
+ yasm_symrec *rec = symtab_define(symtab, name, SYM_LABEL, in_table, line);
+ if (yasm_error_occurred())
+ return rec;
+ rec->value.precbc = precbc;
+ if (in_table && precbc)
+ yasm_bc__add_symrec(precbc, rec);
+ return rec;
+}
+
+yasm_symrec *
+yasm_symtab_define_curpos(yasm_symtab *symtab, const char *name,
+ yasm_bytecode *precbc, unsigned long line)
+{
+ yasm_symrec *rec = symtab_define(symtab, name, SYM_CURPOS, 0, line);
+ if (yasm_error_occurred())
+ return rec;
+ rec->value.precbc = precbc;
+ return rec;
+}
+
+yasm_symrec *
+yasm_symtab_define_special(yasm_symtab *symtab, const char *name,
+ yasm_sym_vis vis)
+{
+ yasm_symrec *rec = symtab_define(symtab, name, SYM_SPECIAL, 1, 0);
+ if (yasm_error_occurred())
+ return rec;
+ rec->status |= YASM_SYM_VALUED;
+ rec->visibility = vis;
+ return rec;
+}
+
+yasm_symrec *
+yasm_symtab_declare(yasm_symtab *symtab, const char *name, yasm_sym_vis vis,
+ unsigned long line)
+{
+ yasm_symrec *rec = symtab_get_or_new(symtab, name, 1);
+ yasm_symrec_declare(rec, vis, line);
+ return rec;
+}
+
+void
+yasm_symrec_declare(yasm_symrec *rec, yasm_sym_vis vis, unsigned long line)
+{
+ /* Allowable combinations:
+ * Existing State-------------- vis New State-------------------
+ * DEFINED GLOBAL COMMON EXTERN GCE DEFINED GLOBAL COMMON EXTERN
+ * 0 - 0 0 GCE 0 G C E
+ * 0 - 0 1 GE 0 G 0 E
+ * 0 - 1 0 GC 0 G C 0
+ * X 0 - 1 1
+ * 1 - 0 0 G 1 G 0 0
+ * X 1 - - 1
+ * X 1 - 1 -
+ */
+ if ((vis == YASM_SYM_GLOBAL) ||
+ (!(rec->status & YASM_SYM_DEFINED) &&
+ (!(rec->visibility & (YASM_SYM_COMMON | YASM_SYM_EXTERN)) ||
+ ((rec->visibility & YASM_SYM_COMMON) && (vis == YASM_SYM_COMMON)) ||
+ ((rec->visibility & YASM_SYM_EXTERN) && (vis == YASM_SYM_EXTERN))))) {
+ rec->decl_line = line;
+ rec->visibility |= vis;
+ } else
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("duplicate definition of `%s'; first defined on line %lu"),
+ rec->name, rec->def_line!=0 ? rec->def_line : rec->decl_line);
+}
+
+typedef struct symtab_finalize_info {
+ unsigned long firstundef_line;
+ int undef_extern;
+ yasm_errwarns *errwarns;
+} symtab_finalize_info;
+
+static int
+symtab_parser_finalize_checksym(yasm_symrec *sym, /*@null@*/ void *d)
+{
+ symtab_finalize_info *info = (symtab_finalize_info *)d;
+
+ /* error if a symbol is used but never defined or extern/common declared */
+ if ((sym->status & YASM_SYM_USED) && !(sym->status & YASM_SYM_DEFINED) &&
+ !(sym->visibility & (YASM_SYM_EXTERN | YASM_SYM_COMMON))) {
+ if (info->undef_extern)
+ sym->visibility |= YASM_SYM_EXTERN;
+ else {
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("undefined symbol `%s' (first use)"), sym->name);
+ yasm_errwarn_propagate(info->errwarns, sym->use_line);
+ if (sym->use_line < info->firstundef_line)
+ info->firstundef_line = sym->use_line;
+ }
+ }
+
+ return 0;
+}
+
+void
+yasm_symtab_parser_finalize(yasm_symtab *symtab, int undef_extern,
+ yasm_errwarns *errwarns)
+{
+ symtab_finalize_info info;
+ info.firstundef_line = ULONG_MAX;
+ info.undef_extern = undef_extern;
+ info.errwarns = errwarns;
+ yasm_symtab_traverse(symtab, &info, symtab_parser_finalize_checksym);
+ if (info.firstundef_line < ULONG_MAX) {
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_(" (Each undefined symbol is reported only once.)"));
+ yasm_errwarn_propagate(errwarns, info.firstundef_line);
+ }
+}
+
+void
+yasm_symtab_destroy(yasm_symtab *symtab)
+{
+ HAMT_destroy(symtab->sym_table, symrec_destroy_one);
+
+ while (!SLIST_EMPTY(&symtab->non_table_syms)) {
+ non_table_symrec *sym = SLIST_FIRST(&symtab->non_table_syms);
+ SLIST_REMOVE_HEAD(&symtab->non_table_syms, link);
+ symrec_destroy_one(sym->rec);
+ yasm_xfree(sym);
+ }
+
+ yasm_xfree(symtab);
+}
+
+typedef struct symrec_print_data {
+ FILE *f;
+ int indent_level;
+} symrec_print_data;
+
+/*@+voidabstract@*/
+static int
+symrec_print_wrapper(yasm_symrec *sym, /*@null@*/ void *d)
+{
+ symrec_print_data *data = (symrec_print_data *)d;
+ assert(data != NULL);
+ fprintf(data->f, "%*sSymbol `%s'\n", data->indent_level, "", sym->name);
+ yasm_symrec_print(sym, data->f, data->indent_level+1);
+ return 0;
+}
+
+void
+yasm_symtab_print(yasm_symtab *symtab, FILE *f, int indent_level)
+{
+ symrec_print_data data;
+ data.f = f;
+ data.indent_level = indent_level;
+ yasm_symtab_traverse(symtab, &data, symrec_print_wrapper);
+}
+/*@=voidabstract@*/
+
+const char *
+yasm_symrec_get_name(const yasm_symrec *sym)
+{
+ return sym->name;
+}
+
+char *
+yasm_symrec_get_global_name(const yasm_symrec *sym, const yasm_object *object)
+{
+ if (sym->visibility & (YASM_SYM_GLOBAL|YASM_SYM_COMMON|YASM_SYM_EXTERN)) {
+ char *name = yasm_xmalloc(strlen(object->global_prefix) +
+ strlen(sym->name) +
+ strlen(object->global_suffix) + 1);
+ strcpy(name, object->global_prefix);
+ strcat(name, sym->name);
+ strcat(name, object->global_suffix);
+ return name;
+ }
+ return yasm__xstrdup(sym->name);
+}
+
+yasm_sym_vis
+yasm_symrec_get_visibility(const yasm_symrec *sym)
+{
+ return sym->visibility;
+}
+
+yasm_sym_status
+yasm_symrec_get_status(const yasm_symrec *sym)
+{
+ return sym->status;
+}
+
+unsigned long
+yasm_symrec_get_def_line(const yasm_symrec *sym)
+{
+ return sym->def_line;
+}
+
+unsigned long
+yasm_symrec_get_decl_line(const yasm_symrec *sym)
+{
+ return sym->decl_line;
+}
+
+unsigned long
+yasm_symrec_get_use_line(const yasm_symrec *sym)
+{
+ return sym->use_line;
+}
+
+const yasm_expr *
+yasm_symrec_get_equ(const yasm_symrec *sym)
+{
+ if (sym->type == SYM_EQU && (sym->status & YASM_SYM_VALUED))
+ return sym->value.expn;
+ return (const yasm_expr *)NULL;
+}
+
+int
+yasm_symrec_get_label(const yasm_symrec *sym,
+ yasm_symrec_get_label_bytecodep *precbc)
+{
+ if (!(sym->type == SYM_LABEL || sym->type == SYM_CURPOS)
+ || !sym->value.precbc) {
+ *precbc = (yasm_symrec_get_label_bytecodep)0xDEADBEEF;
+ return 0;
+ }
+ *precbc = sym->value.precbc;
+ return 1;
+}
+
+void
+yasm_symrec_set_size(yasm_symrec *sym, int size)
+{
+ sym->size = size;
+}
+
+int
+yasm_symrec_get_size(const yasm_symrec *sym)
+{
+ return sym->size;
+}
+
+void
+yasm_symrec_set_segment(yasm_symrec *sym, const char *segment)
+{
+ sym->segment = segment;
+}
+
+const char *
+yasm_symrec_get_segment(const yasm_symrec *sym)
+{
+ return sym->segment;
+}
+
+int
+yasm_symrec_is_abs(const yasm_symrec *sym)
+{
+ return (sym->def_line == 0 && sym->type == SYM_EQU &&
+ sym->name[0] == '\0');
+}
+
+int
+yasm_symrec_is_special(const yasm_symrec *sym)
+{
+ return (sym->type == SYM_SPECIAL);
+}
+
+int
+yasm_symrec_is_curpos(const yasm_symrec *sym)
+{
+ return (sym->type == SYM_CURPOS);
+}
+
+void
+yasm_symrec_set_objext_valparams(yasm_symrec *sym,
+ /*@only@*/ yasm_valparamhead *objext_valparams)
+{
+ yasm_symrec_add_data(sym, &objext_valparams_cb, objext_valparams);
+}
+
+yasm_valparamhead *
+yasm_symrec_get_objext_valparams(yasm_symrec *sym)
+{
+ return yasm_symrec_get_data(sym, &objext_valparams_cb);
+}
+
+void
+yasm_symrec_set_common_size(yasm_symrec *sym,
+ /*@only@*/ yasm_expr *common_size)
+{
+ yasm_expr **ep = yasm_xmalloc(sizeof(yasm_expr *));
+ *ep = common_size;
+ yasm_symrec_add_data(sym, &common_size_cb, ep);
+}
+
+yasm_expr **
+yasm_symrec_get_common_size(yasm_symrec *sym)
+{
+ return (yasm_expr **)yasm_symrec_get_data(sym, &common_size_cb);
+}
+
+void *
+yasm_symrec_get_data(yasm_symrec *sym,
+ const yasm_assoc_data_callback *callback)
+{
+ return yasm__assoc_data_get(sym->assoc_data, callback);
+}
+
+void
+yasm_symrec_add_data(yasm_symrec *sym,
+ const yasm_assoc_data_callback *callback, void *data)
+{
+ sym->assoc_data = yasm__assoc_data_add(sym->assoc_data, callback, data);
+}
+
+void
+yasm_symrec_print(const yasm_symrec *sym, FILE *f, int indent_level)
+{
+ switch (sym->type) {
+ case SYM_UNKNOWN:
+ fprintf(f, "%*s-Unknown (Common/Extern)-\n", indent_level, "");
+ break;
+ case SYM_EQU:
+ fprintf(f, "%*s_EQU_\n", indent_level, "");
+ fprintf(f, "%*sExpn=", indent_level, "");
+ if (sym->status & YASM_SYM_VALUED)
+ yasm_expr_print(sym->value.expn, f);
+ else
+ fprintf(f, "***UNVALUED***");
+ fprintf(f, "\n");
+ break;
+ case SYM_LABEL:
+ case SYM_CURPOS:
+ fprintf(f, "%*s_%s_\n%*sSection:\n", indent_level, "",
+ sym->type == SYM_LABEL ? "Label" : "CurPos",
+ indent_level, "");
+ yasm_section_print(yasm_bc_get_section(sym->value.precbc), f,
+ indent_level+1, 0);
+ fprintf(f, "%*sPreceding bytecode:\n", indent_level, "");
+ yasm_bc_print(sym->value.precbc, f, indent_level+1);
+ break;
+ case SYM_SPECIAL:
+ fprintf(f, "%*s-Special-\n", indent_level, "");
+ break;
+ }
+
+ fprintf(f, "%*sStatus=", indent_level, "");
+ if (sym->status == YASM_SYM_NOSTATUS)
+ fprintf(f, "None\n");
+ else {
+ if (sym->status & YASM_SYM_USED)
+ fprintf(f, "Used,");
+ if (sym->status & YASM_SYM_DEFINED)
+ fprintf(f, "Defined,");
+ if (sym->status & YASM_SYM_VALUED)
+ fprintf(f, "Valued,");
+ if (sym->status & YASM_SYM_NOTINTABLE)
+ fprintf(f, "Not in Table,");
+ fprintf(f, "\n");
+ }
+
+ fprintf(f, "%*sVisibility=", indent_level, "");
+ if (sym->visibility == YASM_SYM_LOCAL)
+ fprintf(f, "Local\n");
+ else {
+ if (sym->visibility & YASM_SYM_GLOBAL)
+ fprintf(f, "Global,");
+ if (sym->visibility & YASM_SYM_COMMON)
+ fprintf(f, "Common,");
+ if (sym->visibility & YASM_SYM_EXTERN)
+ fprintf(f, "Extern,");
+ fprintf(f, "\n");
+ }
+
+ if (sym->assoc_data) {
+ fprintf(f, "%*sAssociated data:\n", indent_level, "");
+ yasm__assoc_data_print(sym->assoc_data, f, indent_level+1);
+ }
+
+ fprintf(f, "%*sLine Index (Defined)=%lu\n", indent_level, "",
+ sym->def_line);
+ fprintf(f, "%*sLine Index (Declared)=%lu\n", indent_level, "",
+ sym->decl_line);
+ fprintf(f, "%*sLine Index (Used)=%lu\n", indent_level, "", sym->use_line);
+}
diff --git a/contrib/tools/yasm/libyasm/symrec.h b/contrib/tools/yasm/libyasm/symrec.h
index b1f797c647..3ff464e688 100644
--- a/contrib/tools/yasm/libyasm/symrec.h
+++ b/contrib/tools/yasm/libyasm/symrec.h
@@ -1,437 +1,437 @@
-/**
- * \file libyasm/symrec.h
- * \brief YASM symbol table interface.
- *
- * \license
- * Copyright (C) 2001-2007 Michael Urman, Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- * \endlicense
- */
-#ifndef YASM_SYMREC_H
-#define YASM_SYMREC_H
-
-#ifndef YASM_LIB_DECL
-#define YASM_LIB_DECL
-#endif
-
-/** Symbol status. YASM_SYM_DEFINED is set by yasm_symtab_define_label(),
- * yasm_symtab_define_equ(), or yasm_symtab_declare()/yasm_symrec_declare()
- * with a visibility of #YASM_SYM_EXTERN or #YASM_SYM_COMMON.
- */
-typedef enum yasm_sym_status {
- YASM_SYM_NOSTATUS = 0, /**< no status */
- YASM_SYM_USED = 1 << 0, /**< for use before definition */
- YASM_SYM_DEFINED = 1 << 1, /**< once it's been defined in the file */
- YASM_SYM_VALUED = 1 << 2, /**< once its value has been determined */
- YASM_SYM_NOTINTABLE = 1 << 3 /**< if it's not in sym_table (ex. '$') */
-} yasm_sym_status;
-
-/** Symbol record visibility.
- * \note YASM_SYM_EXTERN and YASM_SYM_COMMON are mutually exclusive.
- */
-typedef enum yasm_sym_vis {
- YASM_SYM_LOCAL = 0, /**< Default, local only */
- YASM_SYM_GLOBAL = 1 << 0, /**< If symbol is declared GLOBAL */
- YASM_SYM_COMMON = 1 << 1, /**< If symbol is declared COMMON */
- YASM_SYM_EXTERN = 1 << 2, /**< If symbol is declared EXTERN */
- YASM_SYM_DLOCAL = 1 << 3 /**< If symbol is explicitly declared LOCAL */
-} yasm_sym_vis;
-
-/** Create a new symbol table. */
-YASM_LIB_DECL
-yasm_symtab *yasm_symtab_create(void);
-
-/** Destroy a symbol table and all internal symbols.
- * \param symtab symbol table
- * \warning All yasm_symrec *'s into this symbol table become invalid after
- * this is called!
- */
-YASM_LIB_DECL
-void yasm_symtab_destroy(/*@only@*/ yasm_symtab *symtab);
-
-/** Set the symbol table to be case sensitive or not.
- * Should be called before adding any symbol.
- * \param symtab symbol table
- * \param sensitive whether the symbol table should be case sensitive.
- */
-YASM_LIB_DECL
-void yasm_symtab_set_case_sensitive(yasm_symtab *symtab, int sensitive);
-
-/** Get a reference to the symbol table's "absolute" symbol. This is
- * essentially an EQU with no name and value 0, and is used for relocating
- * absolute current-position-relative values.
- * \see yasm_value_set_curpos_rel().
- * \param symtab symbol table
- * \return Absolute symbol (dependent pointer, do not free).
- */
-YASM_LIB_DECL
-/*@dependent@*/ yasm_symrec *yasm_symtab_abs_sym(yasm_symtab *symtab);
-
-/** Get a reference to (use) a symbol. The symbol does not necessarily need to
- * be defined before it is used.
- * \param symtab symbol table
- * \param name symbol name
- * \param line virtual line where referenced
- * \return Symbol (dependent pointer, do not free).
- */
-YASM_LIB_DECL
-/*@dependent@*/ yasm_symrec *yasm_symtab_use
- (yasm_symtab *symtab, const char *name, unsigned long line);
-
-/** Get a reference to a symbol, without "using" it. Should be used for cases
- * when an internal assembler usage of a symbol shouldn't be treated like a
- * normal user symbol usage.
- * \param symtab symbol table
- * \param name symbol name
- * \return Symbol (dependent pointer, do not free). May be NULL if symbol
- * doesn't exist.
- */
-YASM_LIB_DECL
-/*@null@*/ /*@dependent@*/ yasm_symrec *yasm_symtab_get
- (yasm_symtab *symtab, const char *name);
-
-/** Define a symbol as an EQU value.
- * \param symtab symbol table
- * \param name symbol (EQU) name
- * \param e EQU value (expression)
- * \param line virtual line of EQU
- * \return Symbol (dependent pointer, do not free).
- */
-YASM_LIB_DECL
-/*@dependent@*/ yasm_symrec *yasm_symtab_define_equ
- (yasm_symtab *symtab, const char *name, /*@keep@*/ yasm_expr *e,
- unsigned long line);
-
-/** Define a symbol as a label.
- * \param symtab symbol table
- * \param name symbol (label) name
- * \param precbc bytecode preceding label
- * \param in_table nonzero if the label should be inserted into the symbol
- * table (some specially-generated ones should not be)
- * \param line virtual line of label
- * \return Symbol (dependent pointer, do not free).
- */
-YASM_LIB_DECL
-/*@dependent@*/ yasm_symrec *yasm_symtab_define_label
- (yasm_symtab *symtab, const char *name,
- /*@dependent@*/ yasm_bytecode *precbc, int in_table, unsigned long line);
-
-/** Define a symbol as a label representing the current assembly position.
- * This should be used for this purpose instead of yasm_symtab_define_label()
- * as value_finalize_scan() looks for usage of this symbol type for special
- * handling. The symbol created is not inserted into the symbol table.
- * \param symtab symbol table
- * \param name symbol (label) name
- * \param precbc bytecode preceding label
- * \param line virtual line of label
- * \return Symbol (dependent pointer, do not free).
- */
-YASM_LIB_DECL
-/*@dependent@*/ yasm_symrec *yasm_symtab_define_curpos
- (yasm_symtab *symtab, const char *name,
- /*@dependent@*/ yasm_bytecode *precbc, unsigned long line);
-
-/** Define a special symbol that will appear in the symbol table and have a
- * defined name, but have no other data associated with it within the
- * standard symrec.
- * \param symtab symbol table
- * \param name symbol name
- * \param vis symbol visibility
- * \return Symbol (dependent pointer, do not free).
- */
-YASM_LIB_DECL
-/*@dependent@*/ yasm_symrec *yasm_symtab_define_special
- (yasm_symtab *symtab, const char *name, yasm_sym_vis vis);
-
-/** Declare external visibility of a symbol.
- * \note Not all visibility combinations are allowed.
- * \param symtab symbol table
- * \param name symbol name
- * \param vis visibility
- * \param line virtual line of visibility-setting
- * \return Symbol (dependent pointer, do not free).
- */
-YASM_LIB_DECL
-/*@dependent@*/ yasm_symrec *yasm_symtab_declare
- (yasm_symtab *symtab, const char *name, yasm_sym_vis vis,
- unsigned long line);
-
-/** Declare external visibility of a symbol.
- * \note Not all visibility combinations are allowed.
- * \param symrec symbol
- * \param vis visibility
- * \param line virtual line of visibility-setting
- */
-YASM_LIB_DECL
-void yasm_symrec_declare(yasm_symrec *symrec, yasm_sym_vis vis,
- unsigned long line);
-
-/** Callback function for yasm_symrec_traverse().
- * \param sym symbol
- * \param d data passed into yasm_symrec_traverse()
- * \return Nonzero to stop symbol traversal.
- */
-typedef int (*yasm_symtab_traverse_callback)
- (yasm_symrec *sym, /*@null@*/ void *d);
-
-/** Traverse all symbols in the symbol table.
- * \param symtab symbol table
- * \param d data to pass to each call of callback function
- * \param func callback function called on each symbol
- * \return Nonzero value returned by callback function if it ever returned
- * nonzero.
- */
-YASM_LIB_DECL
-int /*@alt void@*/ yasm_symtab_traverse
- (yasm_symtab *symtab, /*@null@*/ void *d,
- yasm_symtab_traverse_callback func);
-
-/** Symbol table iterator (opaque type). */
-typedef struct yasm_symtab_iter yasm_symtab_iter;
-
-/** Get an iterator pointing to the first symbol in the symbol table.
- * \param symtab symbol table
- * \return Iterator for the symbol table.
- */
-YASM_LIB_DECL
-const yasm_symtab_iter *yasm_symtab_first(const yasm_symtab *symtab);
-
-/** Move a symbol table iterator to the next symbol in the symbol table.
- * \param prev Previous iterator value
- * \return Next iterator value, or NULL if no more symbols in the table.
- */
-YASM_LIB_DECL
-/*@null@*/ const yasm_symtab_iter *yasm_symtab_next
- (const yasm_symtab_iter *prev);
-
-/** Get the symbol corresponding to the current symbol table iterator value.
- * \param cur iterator value
- * \return Corresponding symbol.
- */
-YASM_LIB_DECL
-yasm_symrec *yasm_symtab_iter_value(const yasm_symtab_iter *cur);
-
-/** Finalize symbol table after parsing stage. Checks for symbols that are
- * used but never defined or declared #YASM_SYM_EXTERN or #YASM_SYM_COMMON.
- * \param symtab symbol table
- * \param undef_extern if nonzero, all undef syms should be declared extern
- * \param errwarns error/warning set
- * \note Errors/warnings are stored into errwarns.
- */
-YASM_LIB_DECL
-void yasm_symtab_parser_finalize(yasm_symtab *symtab, int undef_extern,
- yasm_errwarns *errwarns);
-
-/** Print the symbol table. For debugging purposes.
- * \param symtab symbol table
- * \param f file
- * \param indent_level indentation level
- */
-YASM_LIB_DECL
-void yasm_symtab_print(yasm_symtab *symtab, FILE *f, int indent_level);
-
-/** Get the name of a symbol.
- * \param sym symbol
- * \return Symbol name.
- */
-YASM_LIB_DECL
-/*@observer@*/ const char *yasm_symrec_get_name(const yasm_symrec *sym);
-
-/** Get the externally-visible (global) name of a symbol.
- * \param sym symbol
- * \param object object
- * \return Externally-visible symbol name (allocated, caller must free).
- */
-YASM_LIB_DECL
-/*@only@*/ char *yasm_symrec_get_global_name(const yasm_symrec *sym,
- const yasm_object *object);
-
-/** Get the visibility of a symbol.
- * \param sym symbol
- * \return Symbol visibility.
- */
-YASM_LIB_DECL
-yasm_sym_vis yasm_symrec_get_visibility(const yasm_symrec *sym);
-
-/** Get the status of a symbol.
- * \param sym symbol
- * \return Symbol status.
- */
-YASM_LIB_DECL
-yasm_sym_status yasm_symrec_get_status(const yasm_symrec *sym);
-
-/** Get the virtual line of where a symbol was first defined.
- * \param sym symbol
- * \return line virtual line
- */
-YASM_LIB_DECL
-unsigned long yasm_symrec_get_def_line(const yasm_symrec *sym);
-
-/** Get the virtual line of where a symbol was first declared.
- * \param sym symbol
- * \return line virtual line
- */
-YASM_LIB_DECL
-unsigned long yasm_symrec_get_decl_line(const yasm_symrec *sym);
-
-/** Get the virtual line of where a symbol was first used.
- * \param sym symbol
- * \return line virtual line
- */
-YASM_LIB_DECL
-unsigned long yasm_symrec_get_use_line(const yasm_symrec *sym);
-
-/** Get EQU value of a symbol.
- * \param sym symbol
- * \return EQU value, or NULL if symbol is not an EQU or is not defined.
- */
-YASM_LIB_DECL
-/*@observer@*/ /*@null@*/ const yasm_expr *yasm_symrec_get_equ
- (const yasm_symrec *sym);
-
-/** Dependent pointer to a bytecode. */
-typedef /*@dependent@*/ yasm_bytecode *yasm_symrec_get_label_bytecodep;
-
-/** Get the label location of a symbol.
- * \param sym symbol
- * \param precbc bytecode preceding label (output)
- * \return 0 if not symbol is not a label or if the symbol's visibility is
- * #YASM_SYM_EXTERN or #YASM_SYM_COMMON (not defined in the file).
- */
-YASM_LIB_DECL
-int yasm_symrec_get_label(const yasm_symrec *sym,
- /*@out@*/ yasm_symrec_get_label_bytecodep *precbc);
-
-/** Set the size of a symbol.
- * \param sym symbol
- * \param size size to be set
- */
-YASM_LIB_DECL
-void yasm_symrec_set_size(yasm_symrec *sym, int size);
-
-/** Get the size of a symbol.
- * \param sym symbol
- * \return size of the symbol, 0 if none specified by the user.
- */
-YASM_LIB_DECL
-int yasm_symrec_get_size(const yasm_symrec *sym);
-
-/** Set the segment of a symbol.
- * \param sym symbol
- * \param segment segment to be set
- */
-YASM_LIB_DECL
-void yasm_symrec_set_segment(yasm_symrec *sym, const char *segment);
-
-/** Get the segment of a symbol.
- * \param sym symbol
- * \return segment of the symbol, NULL if none specified by the user.
- */
-YASM_LIB_DECL
-const char *yasm_symrec_get_segment(const yasm_symrec *sym);
-
-/** Determine if symbol is the "absolute" symbol created by
- * yasm_symtab_abs_sym().
- * \param sym symbol
- * \return 0 if symbol is not the "absolute" symbol, nonzero otherwise.
- */
-YASM_LIB_DECL
-int yasm_symrec_is_abs(const yasm_symrec *sym);
-
-/** Determine if symbol is a special symbol.
- * \param sym symbol
- * \return 0 if symbol is not a special symbol, nonzero otherwise.
- */
-YASM_LIB_DECL
-int yasm_symrec_is_special(const yasm_symrec *sym);
-
-/** Determine if symbol is a label representing the current assembly position.
- * \param sym symbol
- * \return 0 if symbol is not a current position label, nonzero otherwise.
- */
-YASM_LIB_DECL
-int yasm_symrec_is_curpos(const yasm_symrec *sym);
-
-/** Set object-extended valparams.
- * \param sym symbol
- * \param objext_valparams object-extended valparams
- */
-YASM_LIB_DECL
-void yasm_symrec_set_objext_valparams
- (yasm_symrec *sym, /*@only@*/ yasm_valparamhead *objext_valparams);
-
-/** Get object-extended valparams, if any, associated with symbol's
- * declaration.
- * \param sym symbol
- * \return Object-extended valparams (NULL if none).
- */
-YASM_LIB_DECL
-/*@null@*/ /*@dependent@*/ yasm_valparamhead *yasm_symrec_get_objext_valparams
- (yasm_symrec *sym);
-
-/** Set common size of symbol.
- * \param sym symbol
- * \param common_size common size expression
- */
-YASM_LIB_DECL
-void yasm_symrec_set_common_size
- (yasm_symrec *sym, /*@only@*/ yasm_expr *common_size);
-
-/** Get common size of symbol, if symbol is declared COMMON and a size was set
- * for it.
- * \param sym symbol
- * \return Common size (NULL if none).
- */
-YASM_LIB_DECL
-/*@dependent@*/ /*@null@*/ yasm_expr **yasm_symrec_get_common_size
- (yasm_symrec *sym);
-
-/** Get associated data for a symbol and data callback.
- * \param sym symbol
- * \param callback callback used when adding data
- * \return Associated data (NULL if none).
- */
-YASM_LIB_DECL
-/*@dependent@*/ /*@null@*/ void *yasm_symrec_get_data
- (yasm_symrec *sym, const yasm_assoc_data_callback *callback);
-
-/** Add associated data to a symbol.
- * \attention Deletes any existing associated data for that data callback.
- * \param sym symbol
- * \param callback callback
- * \param data data to associate
- */
-YASM_LIB_DECL
-void yasm_symrec_add_data(yasm_symrec *sym,
- const yasm_assoc_data_callback *callback,
- /*@only@*/ /*@null@*/ void *data);
-
-/** Print a symbol. For debugging purposes.
- * \param f file
- * \param indent_level indentation level
- * \param sym symbol
- */
-YASM_LIB_DECL
-void yasm_symrec_print(const yasm_symrec *sym, FILE *f, int indent_level);
-
-#endif
+/**
+ * \file libyasm/symrec.h
+ * \brief YASM symbol table interface.
+ *
+ * \license
+ * Copyright (C) 2001-2007 Michael Urman, Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * \endlicense
+ */
+#ifndef YASM_SYMREC_H
+#define YASM_SYMREC_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/** Symbol status. YASM_SYM_DEFINED is set by yasm_symtab_define_label(),
+ * yasm_symtab_define_equ(), or yasm_symtab_declare()/yasm_symrec_declare()
+ * with a visibility of #YASM_SYM_EXTERN or #YASM_SYM_COMMON.
+ */
+typedef enum yasm_sym_status {
+ YASM_SYM_NOSTATUS = 0, /**< no status */
+ YASM_SYM_USED = 1 << 0, /**< for use before definition */
+ YASM_SYM_DEFINED = 1 << 1, /**< once it's been defined in the file */
+ YASM_SYM_VALUED = 1 << 2, /**< once its value has been determined */
+ YASM_SYM_NOTINTABLE = 1 << 3 /**< if it's not in sym_table (ex. '$') */
+} yasm_sym_status;
+
+/** Symbol record visibility.
+ * \note YASM_SYM_EXTERN and YASM_SYM_COMMON are mutually exclusive.
+ */
+typedef enum yasm_sym_vis {
+ YASM_SYM_LOCAL = 0, /**< Default, local only */
+ YASM_SYM_GLOBAL = 1 << 0, /**< If symbol is declared GLOBAL */
+ YASM_SYM_COMMON = 1 << 1, /**< If symbol is declared COMMON */
+ YASM_SYM_EXTERN = 1 << 2, /**< If symbol is declared EXTERN */
+ YASM_SYM_DLOCAL = 1 << 3 /**< If symbol is explicitly declared LOCAL */
+} yasm_sym_vis;
+
+/** Create a new symbol table. */
+YASM_LIB_DECL
+yasm_symtab *yasm_symtab_create(void);
+
+/** Destroy a symbol table and all internal symbols.
+ * \param symtab symbol table
+ * \warning All yasm_symrec *'s into this symbol table become invalid after
+ * this is called!
+ */
+YASM_LIB_DECL
+void yasm_symtab_destroy(/*@only@*/ yasm_symtab *symtab);
+
+/** Set the symbol table to be case sensitive or not.
+ * Should be called before adding any symbol.
+ * \param symtab symbol table
+ * \param sensitive whether the symbol table should be case sensitive.
+ */
+YASM_LIB_DECL
+void yasm_symtab_set_case_sensitive(yasm_symtab *symtab, int sensitive);
+
+/** Get a reference to the symbol table's "absolute" symbol. This is
+ * essentially an EQU with no name and value 0, and is used for relocating
+ * absolute current-position-relative values.
+ * \see yasm_value_set_curpos_rel().
+ * \param symtab symbol table
+ * \return Absolute symbol (dependent pointer, do not free).
+ */
+YASM_LIB_DECL
+/*@dependent@*/ yasm_symrec *yasm_symtab_abs_sym(yasm_symtab *symtab);
+
+/** Get a reference to (use) a symbol. The symbol does not necessarily need to
+ * be defined before it is used.
+ * \param symtab symbol table
+ * \param name symbol name
+ * \param line virtual line where referenced
+ * \return Symbol (dependent pointer, do not free).
+ */
+YASM_LIB_DECL
+/*@dependent@*/ yasm_symrec *yasm_symtab_use
+ (yasm_symtab *symtab, const char *name, unsigned long line);
+
+/** Get a reference to a symbol, without "using" it. Should be used for cases
+ * when an internal assembler usage of a symbol shouldn't be treated like a
+ * normal user symbol usage.
+ * \param symtab symbol table
+ * \param name symbol name
+ * \return Symbol (dependent pointer, do not free). May be NULL if symbol
+ * doesn't exist.
+ */
+YASM_LIB_DECL
+/*@null@*/ /*@dependent@*/ yasm_symrec *yasm_symtab_get
+ (yasm_symtab *symtab, const char *name);
+
+/** Define a symbol as an EQU value.
+ * \param symtab symbol table
+ * \param name symbol (EQU) name
+ * \param e EQU value (expression)
+ * \param line virtual line of EQU
+ * \return Symbol (dependent pointer, do not free).
+ */
+YASM_LIB_DECL
+/*@dependent@*/ yasm_symrec *yasm_symtab_define_equ
+ (yasm_symtab *symtab, const char *name, /*@keep@*/ yasm_expr *e,
+ unsigned long line);
+
+/** Define a symbol as a label.
+ * \param symtab symbol table
+ * \param name symbol (label) name
+ * \param precbc bytecode preceding label
+ * \param in_table nonzero if the label should be inserted into the symbol
+ * table (some specially-generated ones should not be)
+ * \param line virtual line of label
+ * \return Symbol (dependent pointer, do not free).
+ */
+YASM_LIB_DECL
+/*@dependent@*/ yasm_symrec *yasm_symtab_define_label
+ (yasm_symtab *symtab, const char *name,
+ /*@dependent@*/ yasm_bytecode *precbc, int in_table, unsigned long line);
+
+/** Define a symbol as a label representing the current assembly position.
+ * This should be used for this purpose instead of yasm_symtab_define_label()
+ * as value_finalize_scan() looks for usage of this symbol type for special
+ * handling. The symbol created is not inserted into the symbol table.
+ * \param symtab symbol table
+ * \param name symbol (label) name
+ * \param precbc bytecode preceding label
+ * \param line virtual line of label
+ * \return Symbol (dependent pointer, do not free).
+ */
+YASM_LIB_DECL
+/*@dependent@*/ yasm_symrec *yasm_symtab_define_curpos
+ (yasm_symtab *symtab, const char *name,
+ /*@dependent@*/ yasm_bytecode *precbc, unsigned long line);
+
+/** Define a special symbol that will appear in the symbol table and have a
+ * defined name, but have no other data associated with it within the
+ * standard symrec.
+ * \param symtab symbol table
+ * \param name symbol name
+ * \param vis symbol visibility
+ * \return Symbol (dependent pointer, do not free).
+ */
+YASM_LIB_DECL
+/*@dependent@*/ yasm_symrec *yasm_symtab_define_special
+ (yasm_symtab *symtab, const char *name, yasm_sym_vis vis);
+
+/** Declare external visibility of a symbol.
+ * \note Not all visibility combinations are allowed.
+ * \param symtab symbol table
+ * \param name symbol name
+ * \param vis visibility
+ * \param line virtual line of visibility-setting
+ * \return Symbol (dependent pointer, do not free).
+ */
+YASM_LIB_DECL
+/*@dependent@*/ yasm_symrec *yasm_symtab_declare
+ (yasm_symtab *symtab, const char *name, yasm_sym_vis vis,
+ unsigned long line);
+
+/** Declare external visibility of a symbol.
+ * \note Not all visibility combinations are allowed.
+ * \param symrec symbol
+ * \param vis visibility
+ * \param line virtual line of visibility-setting
+ */
+YASM_LIB_DECL
+void yasm_symrec_declare(yasm_symrec *symrec, yasm_sym_vis vis,
+ unsigned long line);
+
+/** Callback function for yasm_symrec_traverse().
+ * \param sym symbol
+ * \param d data passed into yasm_symrec_traverse()
+ * \return Nonzero to stop symbol traversal.
+ */
+typedef int (*yasm_symtab_traverse_callback)
+ (yasm_symrec *sym, /*@null@*/ void *d);
+
+/** Traverse all symbols in the symbol table.
+ * \param symtab symbol table
+ * \param d data to pass to each call of callback function
+ * \param func callback function called on each symbol
+ * \return Nonzero value returned by callback function if it ever returned
+ * nonzero.
+ */
+YASM_LIB_DECL
+int /*@alt void@*/ yasm_symtab_traverse
+ (yasm_symtab *symtab, /*@null@*/ void *d,
+ yasm_symtab_traverse_callback func);
+
+/** Symbol table iterator (opaque type). */
+typedef struct yasm_symtab_iter yasm_symtab_iter;
+
+/** Get an iterator pointing to the first symbol in the symbol table.
+ * \param symtab symbol table
+ * \return Iterator for the symbol table.
+ */
+YASM_LIB_DECL
+const yasm_symtab_iter *yasm_symtab_first(const yasm_symtab *symtab);
+
+/** Move a symbol table iterator to the next symbol in the symbol table.
+ * \param prev Previous iterator value
+ * \return Next iterator value, or NULL if no more symbols in the table.
+ */
+YASM_LIB_DECL
+/*@null@*/ const yasm_symtab_iter *yasm_symtab_next
+ (const yasm_symtab_iter *prev);
+
+/** Get the symbol corresponding to the current symbol table iterator value.
+ * \param cur iterator value
+ * \return Corresponding symbol.
+ */
+YASM_LIB_DECL
+yasm_symrec *yasm_symtab_iter_value(const yasm_symtab_iter *cur);
+
+/** Finalize symbol table after parsing stage. Checks for symbols that are
+ * used but never defined or declared #YASM_SYM_EXTERN or #YASM_SYM_COMMON.
+ * \param symtab symbol table
+ * \param undef_extern if nonzero, all undef syms should be declared extern
+ * \param errwarns error/warning set
+ * \note Errors/warnings are stored into errwarns.
+ */
+YASM_LIB_DECL
+void yasm_symtab_parser_finalize(yasm_symtab *symtab, int undef_extern,
+ yasm_errwarns *errwarns);
+
+/** Print the symbol table. For debugging purposes.
+ * \param symtab symbol table
+ * \param f file
+ * \param indent_level indentation level
+ */
+YASM_LIB_DECL
+void yasm_symtab_print(yasm_symtab *symtab, FILE *f, int indent_level);
+
+/** Get the name of a symbol.
+ * \param sym symbol
+ * \return Symbol name.
+ */
+YASM_LIB_DECL
+/*@observer@*/ const char *yasm_symrec_get_name(const yasm_symrec *sym);
+
+/** Get the externally-visible (global) name of a symbol.
+ * \param sym symbol
+ * \param object object
+ * \return Externally-visible symbol name (allocated, caller must free).
+ */
+YASM_LIB_DECL
+/*@only@*/ char *yasm_symrec_get_global_name(const yasm_symrec *sym,
+ const yasm_object *object);
+
+/** Get the visibility of a symbol.
+ * \param sym symbol
+ * \return Symbol visibility.
+ */
+YASM_LIB_DECL
+yasm_sym_vis yasm_symrec_get_visibility(const yasm_symrec *sym);
+
+/** Get the status of a symbol.
+ * \param sym symbol
+ * \return Symbol status.
+ */
+YASM_LIB_DECL
+yasm_sym_status yasm_symrec_get_status(const yasm_symrec *sym);
+
+/** Get the virtual line of where a symbol was first defined.
+ * \param sym symbol
+ * \return line virtual line
+ */
+YASM_LIB_DECL
+unsigned long yasm_symrec_get_def_line(const yasm_symrec *sym);
+
+/** Get the virtual line of where a symbol was first declared.
+ * \param sym symbol
+ * \return line virtual line
+ */
+YASM_LIB_DECL
+unsigned long yasm_symrec_get_decl_line(const yasm_symrec *sym);
+
+/** Get the virtual line of where a symbol was first used.
+ * \param sym symbol
+ * \return line virtual line
+ */
+YASM_LIB_DECL
+unsigned long yasm_symrec_get_use_line(const yasm_symrec *sym);
+
+/** Get EQU value of a symbol.
+ * \param sym symbol
+ * \return EQU value, or NULL if symbol is not an EQU or is not defined.
+ */
+YASM_LIB_DECL
+/*@observer@*/ /*@null@*/ const yasm_expr *yasm_symrec_get_equ
+ (const yasm_symrec *sym);
+
+/** Dependent pointer to a bytecode. */
+typedef /*@dependent@*/ yasm_bytecode *yasm_symrec_get_label_bytecodep;
+
+/** Get the label location of a symbol.
+ * \param sym symbol
+ * \param precbc bytecode preceding label (output)
+ * \return 0 if not symbol is not a label or if the symbol's visibility is
+ * #YASM_SYM_EXTERN or #YASM_SYM_COMMON (not defined in the file).
+ */
+YASM_LIB_DECL
+int yasm_symrec_get_label(const yasm_symrec *sym,
+ /*@out@*/ yasm_symrec_get_label_bytecodep *precbc);
+
+/** Set the size of a symbol.
+ * \param sym symbol
+ * \param size size to be set
+ */
+YASM_LIB_DECL
+void yasm_symrec_set_size(yasm_symrec *sym, int size);
+
+/** Get the size of a symbol.
+ * \param sym symbol
+ * \return size of the symbol, 0 if none specified by the user.
+ */
+YASM_LIB_DECL
+int yasm_symrec_get_size(const yasm_symrec *sym);
+
+/** Set the segment of a symbol.
+ * \param sym symbol
+ * \param segment segment to be set
+ */
+YASM_LIB_DECL
+void yasm_symrec_set_segment(yasm_symrec *sym, const char *segment);
+
+/** Get the segment of a symbol.
+ * \param sym symbol
+ * \return segment of the symbol, NULL if none specified by the user.
+ */
+YASM_LIB_DECL
+const char *yasm_symrec_get_segment(const yasm_symrec *sym);
+
+/** Determine if symbol is the "absolute" symbol created by
+ * yasm_symtab_abs_sym().
+ * \param sym symbol
+ * \return 0 if symbol is not the "absolute" symbol, nonzero otherwise.
+ */
+YASM_LIB_DECL
+int yasm_symrec_is_abs(const yasm_symrec *sym);
+
+/** Determine if symbol is a special symbol.
+ * \param sym symbol
+ * \return 0 if symbol is not a special symbol, nonzero otherwise.
+ */
+YASM_LIB_DECL
+int yasm_symrec_is_special(const yasm_symrec *sym);
+
+/** Determine if symbol is a label representing the current assembly position.
+ * \param sym symbol
+ * \return 0 if symbol is not a current position label, nonzero otherwise.
+ */
+YASM_LIB_DECL
+int yasm_symrec_is_curpos(const yasm_symrec *sym);
+
+/** Set object-extended valparams.
+ * \param sym symbol
+ * \param objext_valparams object-extended valparams
+ */
+YASM_LIB_DECL
+void yasm_symrec_set_objext_valparams
+ (yasm_symrec *sym, /*@only@*/ yasm_valparamhead *objext_valparams);
+
+/** Get object-extended valparams, if any, associated with symbol's
+ * declaration.
+ * \param sym symbol
+ * \return Object-extended valparams (NULL if none).
+ */
+YASM_LIB_DECL
+/*@null@*/ /*@dependent@*/ yasm_valparamhead *yasm_symrec_get_objext_valparams
+ (yasm_symrec *sym);
+
+/** Set common size of symbol.
+ * \param sym symbol
+ * \param common_size common size expression
+ */
+YASM_LIB_DECL
+void yasm_symrec_set_common_size
+ (yasm_symrec *sym, /*@only@*/ yasm_expr *common_size);
+
+/** Get common size of symbol, if symbol is declared COMMON and a size was set
+ * for it.
+ * \param sym symbol
+ * \return Common size (NULL if none).
+ */
+YASM_LIB_DECL
+/*@dependent@*/ /*@null@*/ yasm_expr **yasm_symrec_get_common_size
+ (yasm_symrec *sym);
+
+/** Get associated data for a symbol and data callback.
+ * \param sym symbol
+ * \param callback callback used when adding data
+ * \return Associated data (NULL if none).
+ */
+YASM_LIB_DECL
+/*@dependent@*/ /*@null@*/ void *yasm_symrec_get_data
+ (yasm_symrec *sym, const yasm_assoc_data_callback *callback);
+
+/** Add associated data to a symbol.
+ * \attention Deletes any existing associated data for that data callback.
+ * \param sym symbol
+ * \param callback callback
+ * \param data data to associate
+ */
+YASM_LIB_DECL
+void yasm_symrec_add_data(yasm_symrec *sym,
+ const yasm_assoc_data_callback *callback,
+ /*@only@*/ /*@null@*/ void *data);
+
+/** Print a symbol. For debugging purposes.
+ * \param f file
+ * \param indent_level indentation level
+ * \param sym symbol
+ */
+YASM_LIB_DECL
+void yasm_symrec_print(const yasm_symrec *sym, FILE *f, int indent_level);
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/valparam.c b/contrib/tools/yasm/libyasm/valparam.c
index 88e41a7c5d..a1e2acdd1a 100644
--- a/contrib/tools/yasm/libyasm/valparam.c
+++ b/contrib/tools/yasm/libyasm/valparam.c
@@ -1,385 +1,385 @@
-/*
- * Value/Parameter type functions
- *
- * Copyright (C) 2001-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#include "util.h"
-
-#include "libyasm-stdint.h"
-#include "coretype.h"
-#include "valparam.h"
-
-#include "errwarn.h"
-#include "intnum.h"
-#include "expr.h"
-#include "symrec.h"
-
-#include "section.h"
-
-void
-yasm_call_directive(const yasm_directive *directive, yasm_object *object,
- yasm_valparamhead *valparams,
- yasm_valparamhead *objext_valparams, unsigned long line)
-{
- yasm_valparam *vp;
-
- if ((directive->flags & (YASM_DIR_ARG_REQUIRED|YASM_DIR_ID_REQUIRED)) &&
- (!valparams || !yasm_vps_first(valparams))) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("directive `%s' requires an argument"),
- directive->name);
- return;
- }
- if (valparams) {
- vp = yasm_vps_first(valparams);
- if ((directive->flags & YASM_DIR_ID_REQUIRED) &&
- vp->type != YASM_PARAM_ID) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("directive `%s' requires an identifier parameter"),
- directive->name);
- return;
- }
- }
- directive->handler(object, valparams, objext_valparams, line);
-}
-
-yasm_valparam *
-yasm_vp_create_id(/*@keep@*/ char *v, /*@keep@*/ char *p, int id_prefix)
-{
- yasm_valparam *r = yasm_xmalloc(sizeof(yasm_valparam));
- r->val = v;
- r->type = YASM_PARAM_ID;
- r->param.id = p;
- r->id_prefix = (char)id_prefix;
- return r;
-}
-
-yasm_valparam *
-yasm_vp_create_string(/*@keep@*/ char *v, /*@keep@*/ char *p)
-{
- yasm_valparam *r = yasm_xmalloc(sizeof(yasm_valparam));
- r->val = v;
- r->type = YASM_PARAM_STRING;
- r->param.str = p;
- r->id_prefix = '\0';
- return r;
-}
-
-yasm_valparam *
-yasm_vp_create_expr(/*@keep@*/ char *v, /*@keep@*/ yasm_expr *p)
-{
- yasm_valparam *r = yasm_xmalloc(sizeof(yasm_valparam));
- r->val = v;
- r->type = YASM_PARAM_EXPR;
- r->param.e = p;
- r->id_prefix = '\0';
- return r;
-}
-
-/*@null@*/ /*@only@*/ yasm_expr *
-yasm_vp_expr(const yasm_valparam *vp, yasm_symtab *symtab, unsigned long line)
-{
- if (!vp)
- return NULL;
- switch (vp->type) {
- case YASM_PARAM_ID:
- return yasm_expr_create_ident(yasm_expr_sym(
- yasm_symtab_use(symtab, yasm_vp_id(vp), line)), line);
- case YASM_PARAM_EXPR:
- return yasm_expr_copy(vp->param.e);
- default:
- return NULL;
- }
-}
-
-/*@null@*/ /*@dependent@*/ const char *
-yasm_vp_string(const yasm_valparam *vp)
-{
- if (!vp)
- return NULL;
- switch (vp->type) {
- case YASM_PARAM_ID:
- return vp->param.id;
- case YASM_PARAM_STRING:
- return vp->param.str;
- default:
- return NULL;
- }
-}
-
-/*@null@*/ /*@dependent@*/ const char *
-yasm_vp_id(const yasm_valparam *vp)
-{
- if (!vp)
- return NULL;
- if (vp->type == YASM_PARAM_ID) {
- if (vp->param.id[0] == vp->id_prefix)
- return &vp->param.id[1];
- else
- return vp->param.id;
- }
- return NULL;
-}
-
-void
-yasm_vps_delete(yasm_valparamhead *headp)
-{
- yasm_valparam *cur, *next;
-
- cur = STAILQ_FIRST(headp);
- while (cur) {
- next = STAILQ_NEXT(cur, link);
- if (cur->val)
- yasm_xfree(cur->val);
- switch (cur->type) {
- case YASM_PARAM_ID:
- yasm_xfree(cur->param.id);
- break;
- case YASM_PARAM_STRING:
- yasm_xfree(cur->param.str);
- break;
- case YASM_PARAM_EXPR:
- yasm_expr_destroy(cur->param.e);
- break;
- }
- yasm_xfree(cur);
- cur = next;
- }
- STAILQ_INIT(headp);
-}
-
-void
-yasm_vps_print(const yasm_valparamhead *headp, FILE *f)
-{
- const yasm_valparam *vp;
-
- if(!headp) {
- fprintf(f, "(none)");
- return;
- }
-
- yasm_vps_foreach(vp, headp) {
- if (vp->val)
- fprintf(f, "(\"%s\",", vp->val);
- else
- fprintf(f, "((nil),");
- switch (vp->type) {
- case YASM_PARAM_ID:
- fprintf(f, "%s", vp->param.id);
- break;
- case YASM_PARAM_STRING:
- fprintf(f, "\"%s\"", vp->param.str);
- break;
- case YASM_PARAM_EXPR:
- yasm_expr_print(vp->param.e, f);
- break;
- }
- fprintf(f, ")");
- if (yasm_vps_next(vp))
- fprintf(f, ",");
- }
-}
-
-yasm_valparamhead *
-yasm_vps_create(void)
-{
- yasm_valparamhead *headp = yasm_xmalloc(sizeof(yasm_valparamhead));
- yasm_vps_initialize(headp);
- return headp;
-}
-
-void
-yasm_vps_destroy(yasm_valparamhead *headp)
-{
- yasm_vps_delete(headp);
- yasm_xfree(headp);
-}
-
-int
-yasm_dir_helper(void *obj, yasm_valparam *vp_first, unsigned long line,
- const yasm_dir_help *help, size_t nhelp, void *data,
- int (*helper_valparam) (void *obj, yasm_valparam *vp,
- unsigned long line, void *data))
-{
- yasm_valparam *vp = vp_first;
- int anymatched = 0;
- int matched;
-
- if (!vp)
- return 0;
-
- do {
- const char *s;
- size_t i;
-
- matched = 0;
- if (!vp->val && (s = yasm_vp_id(vp))) {
- for (i=0; i<nhelp; i++) {
- if (help[i].needsparam == 0 &&
- yasm__strcasecmp(s, help[i].name) == 0) {
- if (help[i].helper(obj, vp, line,
- ((char *)data)+help[i].off,
- help[i].arg) != 0)
- return -1;
- matched = 1;
- anymatched = 1;
- break;
- }
- }
- } else if (vp->val) {
- for (i=0; i<nhelp; i++) {
- if (help[i].needsparam == 1 &&
- yasm__strcasecmp(vp->val, help[i].name) == 0) {
- if (help[i].helper(obj, vp, line,
- ((char *)data)+help[i].off,
- help[i].arg) != 0)
- return -1;
- matched = 1;
- anymatched = 1;
- break;
- }
- }
- }
-
- if (!matched) {
- int final = helper_valparam(obj, vp, line, data);
- if (final < 0)
- return -1;
- if (final > 0)
- anymatched = 1;
- }
- } while((vp = yasm_vps_next(vp)));
-
- return anymatched;
-}
-
-int
-yasm_dir_helper_flag_or(void *obj, yasm_valparam *vp, unsigned long line,
- void *d, uintptr_t flag)
-{
- unsigned long *flags = (unsigned long *)d;
- *flags |= flag;
- return 0;
-}
-
-int
-yasm_dir_helper_flag_and(void *obj, yasm_valparam *vp, unsigned long line,
- void *d, uintptr_t flag)
-{
- unsigned long *flags = (unsigned long *)d;
- *flags &= ~flag;
- return 0;
-}
-
-int
-yasm_dir_helper_flag_set(void *obj, yasm_valparam *vp, unsigned long line,
- void *d, uintptr_t flag)
-{
- unsigned long *flags = (unsigned long *)d;
- *flags = flag;
- return 0;
-}
-
-int
-yasm_dir_helper_expr(void *obj, yasm_valparam *vp, unsigned long line,
- void *data, uintptr_t arg)
-{
- yasm_object *object = (yasm_object *)obj;
- yasm_expr **expr = (yasm_expr **)data;
-
- if (*expr)
- yasm_expr_destroy(*expr);
- if (!(*expr = yasm_vp_expr(vp, object->symtab, line))) {
- yasm_error_set(YASM_ERROR_VALUE, N_("argument to `%s' is not an expression"),
- vp->val);
- return -1;
- }
- return 0;
-}
-
-int
-yasm_dir_helper_intn(void *obj, yasm_valparam *vp, unsigned long line,
- void *data, uintptr_t arg)
-{
- yasm_object *object = (yasm_object *)obj;
- /*@only@*/ /*@null@*/ yasm_expr *e;
- /*@dependent@*/ /*@null@*/ yasm_intnum *local;
- yasm_intnum **intn = (yasm_intnum **)data;
-
- if (*intn)
- yasm_intnum_destroy(*intn);
- if (!(e = yasm_vp_expr(vp, object->symtab, line)) ||
- !(local = yasm_expr_get_intnum(&e, 0))) {
- yasm_error_set(YASM_ERROR_NOT_CONSTANT,
- N_("argument to `%s' is not an integer"),
- vp->val);
- if (e)
- yasm_expr_destroy(e);
- return -1;
- }
- *intn = yasm_intnum_copy(local);
- yasm_expr_destroy(e);
- return 0;
-}
-
-int
-yasm_dir_helper_string(void *obj, yasm_valparam *vp, unsigned long line,
- void *data, uintptr_t arg)
-{
- /*@dependent@*/ /*@null@*/ const char *local;
- char **s = (char **)data;
-
- if (*s)
- yasm_xfree(*s);
- if (!(local = yasm_vp_string(vp))) {
- yasm_error_set(YASM_ERROR_VALUE,
- N_("argument to `%s' is not a string or identifier"),
- vp->val);
- return -1;
- }
- *s = yasm__xstrdup(local);
- return 0;
-}
-
-int
-yasm_dir_helper_valparam_warn(void *obj, yasm_valparam *vp,
- unsigned long line, void *data)
-{
- const char *s;
-
- if (vp->val) {
- yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized qualifier `%s'"),
- vp->val);
- return 0;
- }
-
- if ((s = yasm_vp_id(vp)))
- yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized qualifier `%s'"), s);
- else if (vp->type == YASM_PARAM_STRING)
- yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized string qualifier"));
- else
- yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized numeric qualifier"));
-
- return 0;
-}
+/*
+ * Value/Parameter type functions
+ *
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "util.h"
+
+#include "libyasm-stdint.h"
+#include "coretype.h"
+#include "valparam.h"
+
+#include "errwarn.h"
+#include "intnum.h"
+#include "expr.h"
+#include "symrec.h"
+
+#include "section.h"
+
+void
+yasm_call_directive(const yasm_directive *directive, yasm_object *object,
+ yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_valparam *vp;
+
+ if ((directive->flags & (YASM_DIR_ARG_REQUIRED|YASM_DIR_ID_REQUIRED)) &&
+ (!valparams || !yasm_vps_first(valparams))) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("directive `%s' requires an argument"),
+ directive->name);
+ return;
+ }
+ if (valparams) {
+ vp = yasm_vps_first(valparams);
+ if ((directive->flags & YASM_DIR_ID_REQUIRED) &&
+ vp->type != YASM_PARAM_ID) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("directive `%s' requires an identifier parameter"),
+ directive->name);
+ return;
+ }
+ }
+ directive->handler(object, valparams, objext_valparams, line);
+}
+
+yasm_valparam *
+yasm_vp_create_id(/*@keep@*/ char *v, /*@keep@*/ char *p, int id_prefix)
+{
+ yasm_valparam *r = yasm_xmalloc(sizeof(yasm_valparam));
+ r->val = v;
+ r->type = YASM_PARAM_ID;
+ r->param.id = p;
+ r->id_prefix = (char)id_prefix;
+ return r;
+}
+
+yasm_valparam *
+yasm_vp_create_string(/*@keep@*/ char *v, /*@keep@*/ char *p)
+{
+ yasm_valparam *r = yasm_xmalloc(sizeof(yasm_valparam));
+ r->val = v;
+ r->type = YASM_PARAM_STRING;
+ r->param.str = p;
+ r->id_prefix = '\0';
+ return r;
+}
+
+yasm_valparam *
+yasm_vp_create_expr(/*@keep@*/ char *v, /*@keep@*/ yasm_expr *p)
+{
+ yasm_valparam *r = yasm_xmalloc(sizeof(yasm_valparam));
+ r->val = v;
+ r->type = YASM_PARAM_EXPR;
+ r->param.e = p;
+ r->id_prefix = '\0';
+ return r;
+}
+
+/*@null@*/ /*@only@*/ yasm_expr *
+yasm_vp_expr(const yasm_valparam *vp, yasm_symtab *symtab, unsigned long line)
+{
+ if (!vp)
+ return NULL;
+ switch (vp->type) {
+ case YASM_PARAM_ID:
+ return yasm_expr_create_ident(yasm_expr_sym(
+ yasm_symtab_use(symtab, yasm_vp_id(vp), line)), line);
+ case YASM_PARAM_EXPR:
+ return yasm_expr_copy(vp->param.e);
+ default:
+ return NULL;
+ }
+}
+
+/*@null@*/ /*@dependent@*/ const char *
+yasm_vp_string(const yasm_valparam *vp)
+{
+ if (!vp)
+ return NULL;
+ switch (vp->type) {
+ case YASM_PARAM_ID:
+ return vp->param.id;
+ case YASM_PARAM_STRING:
+ return vp->param.str;
+ default:
+ return NULL;
+ }
+}
+
+/*@null@*/ /*@dependent@*/ const char *
+yasm_vp_id(const yasm_valparam *vp)
+{
+ if (!vp)
+ return NULL;
+ if (vp->type == YASM_PARAM_ID) {
+ if (vp->param.id[0] == vp->id_prefix)
+ return &vp->param.id[1];
+ else
+ return vp->param.id;
+ }
+ return NULL;
+}
+
+void
+yasm_vps_delete(yasm_valparamhead *headp)
+{
+ yasm_valparam *cur, *next;
+
+ cur = STAILQ_FIRST(headp);
+ while (cur) {
+ next = STAILQ_NEXT(cur, link);
+ if (cur->val)
+ yasm_xfree(cur->val);
+ switch (cur->type) {
+ case YASM_PARAM_ID:
+ yasm_xfree(cur->param.id);
+ break;
+ case YASM_PARAM_STRING:
+ yasm_xfree(cur->param.str);
+ break;
+ case YASM_PARAM_EXPR:
+ yasm_expr_destroy(cur->param.e);
+ break;
+ }
+ yasm_xfree(cur);
+ cur = next;
+ }
+ STAILQ_INIT(headp);
+}
+
+void
+yasm_vps_print(const yasm_valparamhead *headp, FILE *f)
+{
+ const yasm_valparam *vp;
+
+ if(!headp) {
+ fprintf(f, "(none)");
+ return;
+ }
+
+ yasm_vps_foreach(vp, headp) {
+ if (vp->val)
+ fprintf(f, "(\"%s\",", vp->val);
+ else
+ fprintf(f, "((nil),");
+ switch (vp->type) {
+ case YASM_PARAM_ID:
+ fprintf(f, "%s", vp->param.id);
+ break;
+ case YASM_PARAM_STRING:
+ fprintf(f, "\"%s\"", vp->param.str);
+ break;
+ case YASM_PARAM_EXPR:
+ yasm_expr_print(vp->param.e, f);
+ break;
+ }
+ fprintf(f, ")");
+ if (yasm_vps_next(vp))
+ fprintf(f, ",");
+ }
+}
+
+yasm_valparamhead *
+yasm_vps_create(void)
+{
+ yasm_valparamhead *headp = yasm_xmalloc(sizeof(yasm_valparamhead));
+ yasm_vps_initialize(headp);
+ return headp;
+}
+
+void
+yasm_vps_destroy(yasm_valparamhead *headp)
+{
+ yasm_vps_delete(headp);
+ yasm_xfree(headp);
+}
+
+int
+yasm_dir_helper(void *obj, yasm_valparam *vp_first, unsigned long line,
+ const yasm_dir_help *help, size_t nhelp, void *data,
+ int (*helper_valparam) (void *obj, yasm_valparam *vp,
+ unsigned long line, void *data))
+{
+ yasm_valparam *vp = vp_first;
+ int anymatched = 0;
+ int matched;
+
+ if (!vp)
+ return 0;
+
+ do {
+ const char *s;
+ size_t i;
+
+ matched = 0;
+ if (!vp->val && (s = yasm_vp_id(vp))) {
+ for (i=0; i<nhelp; i++) {
+ if (help[i].needsparam == 0 &&
+ yasm__strcasecmp(s, help[i].name) == 0) {
+ if (help[i].helper(obj, vp, line,
+ ((char *)data)+help[i].off,
+ help[i].arg) != 0)
+ return -1;
+ matched = 1;
+ anymatched = 1;
+ break;
+ }
+ }
+ } else if (vp->val) {
+ for (i=0; i<nhelp; i++) {
+ if (help[i].needsparam == 1 &&
+ yasm__strcasecmp(vp->val, help[i].name) == 0) {
+ if (help[i].helper(obj, vp, line,
+ ((char *)data)+help[i].off,
+ help[i].arg) != 0)
+ return -1;
+ matched = 1;
+ anymatched = 1;
+ break;
+ }
+ }
+ }
+
+ if (!matched) {
+ int final = helper_valparam(obj, vp, line, data);
+ if (final < 0)
+ return -1;
+ if (final > 0)
+ anymatched = 1;
+ }
+ } while((vp = yasm_vps_next(vp)));
+
+ return anymatched;
+}
+
+int
+yasm_dir_helper_flag_or(void *obj, yasm_valparam *vp, unsigned long line,
+ void *d, uintptr_t flag)
+{
+ unsigned long *flags = (unsigned long *)d;
+ *flags |= flag;
+ return 0;
+}
+
+int
+yasm_dir_helper_flag_and(void *obj, yasm_valparam *vp, unsigned long line,
+ void *d, uintptr_t flag)
+{
+ unsigned long *flags = (unsigned long *)d;
+ *flags &= ~flag;
+ return 0;
+}
+
+int
+yasm_dir_helper_flag_set(void *obj, yasm_valparam *vp, unsigned long line,
+ void *d, uintptr_t flag)
+{
+ unsigned long *flags = (unsigned long *)d;
+ *flags = flag;
+ return 0;
+}
+
+int
+yasm_dir_helper_expr(void *obj, yasm_valparam *vp, unsigned long line,
+ void *data, uintptr_t arg)
+{
+ yasm_object *object = (yasm_object *)obj;
+ yasm_expr **expr = (yasm_expr **)data;
+
+ if (*expr)
+ yasm_expr_destroy(*expr);
+ if (!(*expr = yasm_vp_expr(vp, object->symtab, line))) {
+ yasm_error_set(YASM_ERROR_VALUE, N_("argument to `%s' is not an expression"),
+ vp->val);
+ return -1;
+ }
+ return 0;
+}
+
+int
+yasm_dir_helper_intn(void *obj, yasm_valparam *vp, unsigned long line,
+ void *data, uintptr_t arg)
+{
+ yasm_object *object = (yasm_object *)obj;
+ /*@only@*/ /*@null@*/ yasm_expr *e;
+ /*@dependent@*/ /*@null@*/ yasm_intnum *local;
+ yasm_intnum **intn = (yasm_intnum **)data;
+
+ if (*intn)
+ yasm_intnum_destroy(*intn);
+ if (!(e = yasm_vp_expr(vp, object->symtab, line)) ||
+ !(local = yasm_expr_get_intnum(&e, 0))) {
+ yasm_error_set(YASM_ERROR_NOT_CONSTANT,
+ N_("argument to `%s' is not an integer"),
+ vp->val);
+ if (e)
+ yasm_expr_destroy(e);
+ return -1;
+ }
+ *intn = yasm_intnum_copy(local);
+ yasm_expr_destroy(e);
+ return 0;
+}
+
+int
+yasm_dir_helper_string(void *obj, yasm_valparam *vp, unsigned long line,
+ void *data, uintptr_t arg)
+{
+ /*@dependent@*/ /*@null@*/ const char *local;
+ char **s = (char **)data;
+
+ if (*s)
+ yasm_xfree(*s);
+ if (!(local = yasm_vp_string(vp))) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("argument to `%s' is not a string or identifier"),
+ vp->val);
+ return -1;
+ }
+ *s = yasm__xstrdup(local);
+ return 0;
+}
+
+int
+yasm_dir_helper_valparam_warn(void *obj, yasm_valparam *vp,
+ unsigned long line, void *data)
+{
+ const char *s;
+
+ if (vp->val) {
+ yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized qualifier `%s'"),
+ vp->val);
+ return 0;
+ }
+
+ if ((s = yasm_vp_id(vp)))
+ yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized qualifier `%s'"), s);
+ else if (vp->type == YASM_PARAM_STRING)
+ yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized string qualifier"));
+ else
+ yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized numeric qualifier"));
+
+ return 0;
+}
diff --git a/contrib/tools/yasm/libyasm/valparam.h b/contrib/tools/yasm/libyasm/valparam.h
index d7343d4955..0167558540 100644
--- a/contrib/tools/yasm/libyasm/valparam.h
+++ b/contrib/tools/yasm/libyasm/valparam.h
@@ -1,408 +1,408 @@
-/**
- * \file libyasm/valparam.h
- * \brief YASM value/parameter interface.
- *
- * \license
- * Copyright (C) 2001-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- * \endlicense
- */
-#ifndef YASM_VALPARAM_H
-#define YASM_VALPARAM_H
-
-#ifndef YASM_LIB_DECL
-#define YASM_LIB_DECL
-#endif
-
-/** Value/parameter pair. \internal */
-struct yasm_valparam {
- /*@reldef@*/ STAILQ_ENTRY(yasm_valparam) link; /**< Next pair in list */
- /*@owned@*/ /*@null@*/ char *val; /**< Value */
-
- /** Parameter type. */
- enum yasm_param_type {
- YASM_PARAM_ID, /**< Identifier */
- YASM_PARAM_STRING, /**< String */
- YASM_PARAM_EXPR /**< Expression */
- } type; /**< Parameter type */
-
- /** Parameter value. */
- union yasm_param {
- /*@owned@*/ char *id; /**< Identifier */
- /*@owned@*/ char *str; /**< String */
- /*@owned@*/ yasm_expr *e; /**< Expression */
- } param; /**< Parameter */
-
- /** Prefix character that indicates a raw identifier. When
- * yasm_vp_string() is called on a #YASM_PARAM_ID, all characters are
- * returned. When yasm_vp_id() is called on a #YASM_PARAM_ID, if the
- * identifier begins with this character, this character is stripped
- * from the returned value.
- */
- char id_prefix;
-};
-
-/** Linked list of value/parameter pairs. \internal */
-/*@reldef@*/ STAILQ_HEAD(yasm_valparamhead, yasm_valparam);
-
-/** Directive list entry structure. */
-struct yasm_directive {
- /** Directive name. GAS directives should include the ".", NASM
- * directives should just be the raw name (not including the []).
- * NULL entry required to terminate list of directives.
- */
- /*@null@*/ const char *name;
-
- const char *parser; /**< Parser keyword */
-
- /** Handler callback function for the directive.
- * \param object object
- * \param valparams value/parameters
- * \param objext_valparams object format-specific value/parameters
- * \param line virtual line (from yasm_linemap)
- */
- void (*handler) (yasm_object *object, yasm_valparamhead *valparams,
- yasm_valparamhead *objext_valparams, unsigned long line);
-
- /** Flags for pre-handler parameter checking. */
- enum yasm_directive_flags {
- YASM_DIR_ANY = 0, /**< Any valparams accepted */
- YASM_DIR_ARG_REQUIRED = 1, /**< Require at least 1 valparam */
- YASM_DIR_ID_REQUIRED = 2 /**< First valparam must be ID */
- } flags;
-};
-
-/** Call a directive. Performs any valparam checks asked for by the
- * directive prior to call. Note that for a variety of reasons, a directive
- * can generate an error.
- * \param directive directive
- * \param object object
- * \param valparams value/parameters
- * \param objext_valparams object format-specific value/parameters
- * \param line virtual line (from yasm_linemap)
- */
-YASM_LIB_DECL
-void yasm_call_directive(const yasm_directive *directive, yasm_object *object,
- yasm_valparamhead *valparams,
- yasm_valparamhead *objext_valparams,
- unsigned long line);
-
-/** Create a new valparam with identifier parameter.
- * \param v value
- * \param p parameter
- * \param id_prefix identifier prefix for raw identifiers
- * \return Newly allocated valparam.
- */
-YASM_LIB_DECL
-yasm_valparam *yasm_vp_create_id(/*@keep@*/ char *v, /*@keep@*/ char *p,
- int id_prefix);
-
-/** Create a new valparam with string parameter.
- * \param v value
- * \param p parameter
- * \return Newly allocated valparam.
- */
-YASM_LIB_DECL
-yasm_valparam *yasm_vp_create_string(/*@keep@*/ char *v, /*@keep@*/ char *p);
-
-/** Create a new valparam with expression parameter.
- * \param v value
- * \param p parameter
- * \return Newly allocated valparam.
- */
-YASM_LIB_DECL
-yasm_valparam *yasm_vp_create_expr(/*@keep@*/ char *v,
- /*@keep@*/ yasm_expr *p);
-
-/** Get a valparam parameter as an expr. If the parameter is an identifier,
- * it's treated as a symbol (yasm_symtab_use() is called to convert it).
- * \param vp valparam
- * \param symtab symbol table
- * \param line virtual line
- * \return Expression, or NULL if vp is NULL or the parameter cannot be
- * converted to an expression.
- */
-YASM_LIB_DECL
-/*@null@*/ /*@only@*/ yasm_expr *yasm_vp_expr
- (const yasm_valparam *vp, yasm_symtab *symtab, unsigned long line);
-
-/** Get a valparam parameter as a string. If the parameter is an identifier,
- * it's treated as a string.
- * \param vp valparam
- * \return String, or NULL if vp is NULL or the parameter cannot be realized
- * as a string.
- */
-YASM_LIB_DECL
-/*@null@*/ /*@dependent@*/ const char *yasm_vp_string(const yasm_valparam *vp);
-
-/** Get a valparam parameter as an identifier.
- * \param vp valparam
- * \return Identifier (string), or NULL if vp is NULL or the parameter is not
- * an identifier.
- */
-YASM_LIB_DECL
-/*@null@*/ /*@dependent@*/ const char *yasm_vp_id(const yasm_valparam *vp);
-
-/** Create a new linked list of valparams.
- * \return Newly allocated valparam list.
- */
-YASM_LIB_DECL
-yasm_valparamhead *yasm_vps_create(void);
-
-/** Destroy a list of valparams (created with yasm_vps_create).
- * \param headp list of valparams
- */
-YASM_LIB_DECL
-void yasm_vps_destroy(yasm_valparamhead *headp);
-
-/** Initialize linked list of valparams.
- * \param headp linked list
- */
-void yasm_vps_initialize(/*@out@*/ yasm_valparamhead *headp);
-#ifndef YASM_DOXYGEN
-#define yasm_vps_initialize(headp) STAILQ_INIT(headp)
-#endif
-
-/** Destroy (free allocated memory for) linked list of valparams (created with
- * yasm_vps_initialize).
- * \warning Deletes val/params.
- * \param headp linked list
- */
-YASM_LIB_DECL
-void yasm_vps_delete(yasm_valparamhead *headp);
-
-/** Append valparam to tail of linked list.
- * \param headp linked list
- * \param vp valparam
- */
-void yasm_vps_append(yasm_valparamhead *headp, /*@keep@*/ yasm_valparam *vp);
-#ifndef YASM_DOXYGEN
-#define yasm_vps_append(headp, vp) do { \
- if (vp) \
- STAILQ_INSERT_TAIL(headp, vp, link); \
- } while(0)
-#endif
-
-/** Get first valparam in linked list.
- * \param headp linked list
- * \return First valparam in linked list.
- */
-/*@null@*/ /*@dependent@*/ yasm_valparam *yasm_vps_first
- (yasm_valparamhead *headp);
-#ifndef YASM_DOXYGEN
-#define yasm_vps_first(headp) STAILQ_FIRST(headp)
-#endif
-
-/** Get next valparam in linked list.
- * \param cur previous valparam in linked list
- * \return Next valparam in linked list.
- */
-/*@null@*/ /*@dependent@*/ yasm_valparam *yasm_vps_next(yasm_valparam *cur);
-#ifndef YASM_DOXYGEN
-#define yasm_vps_next(cur) STAILQ_NEXT(cur, link)
-#endif
-
-/** Iterate through linked list of valparams.
- * \internal
- * \param iter iterator variable
- * \param headp linked list
- */
-#ifndef YASM_DOXYGEN
-#define yasm_vps_foreach(iter, headp) STAILQ_FOREACH(iter, headp, link)
-#endif
-
-/** Print linked list of valparams. For debugging purposes.
- * \param f file
- * \param headp linked list
- */
-YASM_LIB_DECL
-void yasm_vps_print(/*@null@*/ const yasm_valparamhead *headp, FILE *f);
-
-/** Directive valparam parse helper structure. */
-typedef struct yasm_dir_help {
- /** Value portion of val=param (if needsparam=1), or standalone identifier
- * (if needsparam=0).
- */
- const char *name;
-
- /** 1 if value requires parameter, 0 if it must not have a parameter. */
- int needsparam;
-
- /** Helper callback function if name and parameter existence match.
- * \param obj obj passed into yasm_dir_helper()
- * \param vp value/parameter
- * \param line line passed into yasm_dir_helper()
- * \param data data passed into yasm_dir_helper() plus
- #yasm_dir_help.off offset
- * \param arg #yasm_dir_help.arg argument
- * \return -1 on error, 0 otherwise.
- */
- int (*helper) (void *obj, yasm_valparam *vp, unsigned long line,
- void *data, uintptr_t arg);
-
- /** Offset added to data pointer passed into yasm_dir_helper() before
- * data pointer is given to #yasm_dir_help.helper(). This is so that
- * a structure can be passed into yasm_dir_helper() and this can be an
- * offsetof() to point the helper function to a specific structure
- * member.
- */
- size_t off;
-
- /** Argument to pass in as the arg parameter to #yasm_dir_help.helper().
- */
- uintptr_t arg;
-} yasm_dir_help;
-
-/** Help parse a list of directive value/parameters. Takes an array of
- * #yasm_dir_help structures and tries to match val=param (or just val)
- * against the passed value/parameters. When no match is found in the
- * array of help structures, calls helper_valparam.
- * \param obj object to be passed to yasm_dir_help.helper() or
- * helper_valparam() callback
- * \param vp_first first value/parameter to examine
- * \param line virtual line number; passed down to helper callback
- * \param help array of #yasm_dir_help structures
- * \param nhelp number of array elements
- * \param data base data pointer; if a match is found,
- * the respective #yasm_dir_help.off is added to this
- * prior to it being passed to the helper callback
- * \param helper_valparam catch-all callback; should return -1 on error,
- * 0 if not matched, 1 if matched.
- * \return -1 on error, 1 if any arguments matched (including via
- * catch-all callback), 0 if no match.
- */
-YASM_LIB_DECL
-int yasm_dir_helper(void *obj, yasm_valparam *vp_first, unsigned long line,
- const yasm_dir_help *help, size_t nhelp, void *data,
- int (*helper_valparam) (void *object,
- yasm_valparam *vp,
- unsigned long line,
- void *data));
-
-/** Standard helper for yasm_dir_helper() that simply sets a flag when called.
- * It does not look at the vp; rather, it uses the value of the arg parameter,
- * and stores an unsigned long value to data.
- * \param obj unused
- * \param vp unused
- * \param line unused
- * \param data pointer to an unsigned long
- * \param arg flag to set
- * \return 0
- */
-YASM_LIB_DECL
-int yasm_dir_helper_flag_set(void *obj, yasm_valparam *vp, unsigned long line,
- void *data, uintptr_t arg);
-
-/** Standard helper for yasm_dir_helper() that simply ORs a flag when called.
- * It does not look at the vp; rather, it uses the value of the arg parameter,
- * and ORs it with the unsigned long value in data.
- * \param obj unused
- * \param vp unused
- * \param line unused
- * \param data pointer to an unsigned long
- * \param arg flag to OR
- * \return 0
- */
-YASM_LIB_DECL
-int yasm_dir_helper_flag_or(void *obj, yasm_valparam *vp, unsigned long line,
- void *data, uintptr_t arg);
-
-/** Standard helper for yasm_dir_helper() that simply ANDs a flag when called.
- * It does not look at the vp; rather, it uses the value of the arg parameter,
- * and ANDs its inverse (~) with the unsigned long value in data.
- * \param obj unused
- * \param vp unused
- * \param line unused
- * \param data pointer to an unsigned long
- * \param arg flag to AND
- * \return 0
- */
-YASM_LIB_DECL
-int yasm_dir_helper_flag_and(void *obj, yasm_valparam *vp, unsigned long line,
- void *data, uintptr_t arg);
-
-/** Standard helper for yasm_dir_helper() that parses an expr parameter.
- * The #yasm_dir_help structure that uses this function should have
- * needsparam=1. The obj parameter to yasm_dir_helper() when this helper
- * is used MUST point to a #yasm_object. In addition, the data parameter
- * that is ultimately passed to this function (e.g. yasm_dir_helper() data
- * parameter plus #yasm_dir_help.off) must point to a #yasm_expr *
- * initialized to NULL.
- * \param obj object; must be #yasm_object
- * \param vp valparam
- * \param line virtual line number
- * \param data pointer to #yasm_expr *
- * \param arg unused argument
- * \return -1 on error, 0 otherwise.
- */
-YASM_LIB_DECL
-int yasm_dir_helper_expr(void *obj, yasm_valparam *vp, unsigned long line,
- void *data, uintptr_t arg);
-
-/** Standard helper for yasm_dir_helper() that parses an intnum parameter.
- * The #yasm_dir_help structure that uses this function should have
- * needsparam=1. The obj parameter to yasm_dir_helper() when this helper
- * is used MUST point to a #yasm_object. In addition, the data parameter
- * that is ultimately passed to this function (e.g. yasm_dir_helper() data
- * parameter plus #yasm_dir_help.off) must point to a #yasm_intnum *
- * initialized to NULL.
- * \param obj object; must be #yasm_object
- * \param vp valparam
- * \param line virtual line number
- * \param data pointer to #yasm_intnum *
- * \param arg unused argument
- * \return -1 on error, 0 otherwise.
- */
-YASM_LIB_DECL
-int yasm_dir_helper_intn(void *obj, yasm_valparam *vp, unsigned long line,
- void *data, uintptr_t arg);
-
-/** Standard helper for yasm_dir_helper() that parses an string (or
- * standalone identifier) parameter.
- * The #yasm_dir_help structure that uses this function should have
- * needsparam=1. The data parameter that is ultimately passed to this
- * function (e.g. yasm_dir_helper() data parameter plus #yasm_dir_help.off)
- * must point to a char * initialized to NULL.
- * \param obj unused
- * \param vp valparam
- * \param line unused
- * \param data pointer to char *
- * \param arg unused
- * \return -1 on error, 0 otherwise.
- */
-YASM_LIB_DECL
-int yasm_dir_helper_string(void *obj, yasm_valparam *vp, unsigned long line,
- void *data, uintptr_t arg);
-
-/** Standard catch-all callback fro yasm_dir_helper(). Generates standard
- * warning for all valparams.
- * \param obj unused
- * \param vp valparam
- * \param line unused
- * \param data unused
- * \return 0
- */
-YASM_LIB_DECL
-int yasm_dir_helper_valparam_warn(void *obj, yasm_valparam *vp,
- unsigned long line, void *data);
-#endif
+/**
+ * \file libyasm/valparam.h
+ * \brief YASM value/parameter interface.
+ *
+ * \license
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * \endlicense
+ */
+#ifndef YASM_VALPARAM_H
+#define YASM_VALPARAM_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/** Value/parameter pair. \internal */
+struct yasm_valparam {
+ /*@reldef@*/ STAILQ_ENTRY(yasm_valparam) link; /**< Next pair in list */
+ /*@owned@*/ /*@null@*/ char *val; /**< Value */
+
+ /** Parameter type. */
+ enum yasm_param_type {
+ YASM_PARAM_ID, /**< Identifier */
+ YASM_PARAM_STRING, /**< String */
+ YASM_PARAM_EXPR /**< Expression */
+ } type; /**< Parameter type */
+
+ /** Parameter value. */
+ union yasm_param {
+ /*@owned@*/ char *id; /**< Identifier */
+ /*@owned@*/ char *str; /**< String */
+ /*@owned@*/ yasm_expr *e; /**< Expression */
+ } param; /**< Parameter */
+
+ /** Prefix character that indicates a raw identifier. When
+ * yasm_vp_string() is called on a #YASM_PARAM_ID, all characters are
+ * returned. When yasm_vp_id() is called on a #YASM_PARAM_ID, if the
+ * identifier begins with this character, this character is stripped
+ * from the returned value.
+ */
+ char id_prefix;
+};
+
+/** Linked list of value/parameter pairs. \internal */
+/*@reldef@*/ STAILQ_HEAD(yasm_valparamhead, yasm_valparam);
+
+/** Directive list entry structure. */
+struct yasm_directive {
+ /** Directive name. GAS directives should include the ".", NASM
+ * directives should just be the raw name (not including the []).
+ * NULL entry required to terminate list of directives.
+ */
+ /*@null@*/ const char *name;
+
+ const char *parser; /**< Parser keyword */
+
+ /** Handler callback function for the directive.
+ * \param object object
+ * \param valparams value/parameters
+ * \param objext_valparams object format-specific value/parameters
+ * \param line virtual line (from yasm_linemap)
+ */
+ void (*handler) (yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line);
+
+ /** Flags for pre-handler parameter checking. */
+ enum yasm_directive_flags {
+ YASM_DIR_ANY = 0, /**< Any valparams accepted */
+ YASM_DIR_ARG_REQUIRED = 1, /**< Require at least 1 valparam */
+ YASM_DIR_ID_REQUIRED = 2 /**< First valparam must be ID */
+ } flags;
+};
+
+/** Call a directive. Performs any valparam checks asked for by the
+ * directive prior to call. Note that for a variety of reasons, a directive
+ * can generate an error.
+ * \param directive directive
+ * \param object object
+ * \param valparams value/parameters
+ * \param objext_valparams object format-specific value/parameters
+ * \param line virtual line (from yasm_linemap)
+ */
+YASM_LIB_DECL
+void yasm_call_directive(const yasm_directive *directive, yasm_object *object,
+ yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams,
+ unsigned long line);
+
+/** Create a new valparam with identifier parameter.
+ * \param v value
+ * \param p parameter
+ * \param id_prefix identifier prefix for raw identifiers
+ * \return Newly allocated valparam.
+ */
+YASM_LIB_DECL
+yasm_valparam *yasm_vp_create_id(/*@keep@*/ char *v, /*@keep@*/ char *p,
+ int id_prefix);
+
+/** Create a new valparam with string parameter.
+ * \param v value
+ * \param p parameter
+ * \return Newly allocated valparam.
+ */
+YASM_LIB_DECL
+yasm_valparam *yasm_vp_create_string(/*@keep@*/ char *v, /*@keep@*/ char *p);
+
+/** Create a new valparam with expression parameter.
+ * \param v value
+ * \param p parameter
+ * \return Newly allocated valparam.
+ */
+YASM_LIB_DECL
+yasm_valparam *yasm_vp_create_expr(/*@keep@*/ char *v,
+ /*@keep@*/ yasm_expr *p);
+
+/** Get a valparam parameter as an expr. If the parameter is an identifier,
+ * it's treated as a symbol (yasm_symtab_use() is called to convert it).
+ * \param vp valparam
+ * \param symtab symbol table
+ * \param line virtual line
+ * \return Expression, or NULL if vp is NULL or the parameter cannot be
+ * converted to an expression.
+ */
+YASM_LIB_DECL
+/*@null@*/ /*@only@*/ yasm_expr *yasm_vp_expr
+ (const yasm_valparam *vp, yasm_symtab *symtab, unsigned long line);
+
+/** Get a valparam parameter as a string. If the parameter is an identifier,
+ * it's treated as a string.
+ * \param vp valparam
+ * \return String, or NULL if vp is NULL or the parameter cannot be realized
+ * as a string.
+ */
+YASM_LIB_DECL
+/*@null@*/ /*@dependent@*/ const char *yasm_vp_string(const yasm_valparam *vp);
+
+/** Get a valparam parameter as an identifier.
+ * \param vp valparam
+ * \return Identifier (string), or NULL if vp is NULL or the parameter is not
+ * an identifier.
+ */
+YASM_LIB_DECL
+/*@null@*/ /*@dependent@*/ const char *yasm_vp_id(const yasm_valparam *vp);
+
+/** Create a new linked list of valparams.
+ * \return Newly allocated valparam list.
+ */
+YASM_LIB_DECL
+yasm_valparamhead *yasm_vps_create(void);
+
+/** Destroy a list of valparams (created with yasm_vps_create).
+ * \param headp list of valparams
+ */
+YASM_LIB_DECL
+void yasm_vps_destroy(yasm_valparamhead *headp);
+
+/** Initialize linked list of valparams.
+ * \param headp linked list
+ */
+void yasm_vps_initialize(/*@out@*/ yasm_valparamhead *headp);
+#ifndef YASM_DOXYGEN
+#define yasm_vps_initialize(headp) STAILQ_INIT(headp)
+#endif
+
+/** Destroy (free allocated memory for) linked list of valparams (created with
+ * yasm_vps_initialize).
+ * \warning Deletes val/params.
+ * \param headp linked list
+ */
+YASM_LIB_DECL
+void yasm_vps_delete(yasm_valparamhead *headp);
+
+/** Append valparam to tail of linked list.
+ * \param headp linked list
+ * \param vp valparam
+ */
+void yasm_vps_append(yasm_valparamhead *headp, /*@keep@*/ yasm_valparam *vp);
+#ifndef YASM_DOXYGEN
+#define yasm_vps_append(headp, vp) do { \
+ if (vp) \
+ STAILQ_INSERT_TAIL(headp, vp, link); \
+ } while(0)
+#endif
+
+/** Get first valparam in linked list.
+ * \param headp linked list
+ * \return First valparam in linked list.
+ */
+/*@null@*/ /*@dependent@*/ yasm_valparam *yasm_vps_first
+ (yasm_valparamhead *headp);
+#ifndef YASM_DOXYGEN
+#define yasm_vps_first(headp) STAILQ_FIRST(headp)
+#endif
+
+/** Get next valparam in linked list.
+ * \param cur previous valparam in linked list
+ * \return Next valparam in linked list.
+ */
+/*@null@*/ /*@dependent@*/ yasm_valparam *yasm_vps_next(yasm_valparam *cur);
+#ifndef YASM_DOXYGEN
+#define yasm_vps_next(cur) STAILQ_NEXT(cur, link)
+#endif
+
+/** Iterate through linked list of valparams.
+ * \internal
+ * \param iter iterator variable
+ * \param headp linked list
+ */
+#ifndef YASM_DOXYGEN
+#define yasm_vps_foreach(iter, headp) STAILQ_FOREACH(iter, headp, link)
+#endif
+
+/** Print linked list of valparams. For debugging purposes.
+ * \param f file
+ * \param headp linked list
+ */
+YASM_LIB_DECL
+void yasm_vps_print(/*@null@*/ const yasm_valparamhead *headp, FILE *f);
+
+/** Directive valparam parse helper structure. */
+typedef struct yasm_dir_help {
+ /** Value portion of val=param (if needsparam=1), or standalone identifier
+ * (if needsparam=0).
+ */
+ const char *name;
+
+ /** 1 if value requires parameter, 0 if it must not have a parameter. */
+ int needsparam;
+
+ /** Helper callback function if name and parameter existence match.
+ * \param obj obj passed into yasm_dir_helper()
+ * \param vp value/parameter
+ * \param line line passed into yasm_dir_helper()
+ * \param data data passed into yasm_dir_helper() plus
+ #yasm_dir_help.off offset
+ * \param arg #yasm_dir_help.arg argument
+ * \return -1 on error, 0 otherwise.
+ */
+ int (*helper) (void *obj, yasm_valparam *vp, unsigned long line,
+ void *data, uintptr_t arg);
+
+ /** Offset added to data pointer passed into yasm_dir_helper() before
+ * data pointer is given to #yasm_dir_help.helper(). This is so that
+ * a structure can be passed into yasm_dir_helper() and this can be an
+ * offsetof() to point the helper function to a specific structure
+ * member.
+ */
+ size_t off;
+
+ /** Argument to pass in as the arg parameter to #yasm_dir_help.helper().
+ */
+ uintptr_t arg;
+} yasm_dir_help;
+
+/** Help parse a list of directive value/parameters. Takes an array of
+ * #yasm_dir_help structures and tries to match val=param (or just val)
+ * against the passed value/parameters. When no match is found in the
+ * array of help structures, calls helper_valparam.
+ * \param obj object to be passed to yasm_dir_help.helper() or
+ * helper_valparam() callback
+ * \param vp_first first value/parameter to examine
+ * \param line virtual line number; passed down to helper callback
+ * \param help array of #yasm_dir_help structures
+ * \param nhelp number of array elements
+ * \param data base data pointer; if a match is found,
+ * the respective #yasm_dir_help.off is added to this
+ * prior to it being passed to the helper callback
+ * \param helper_valparam catch-all callback; should return -1 on error,
+ * 0 if not matched, 1 if matched.
+ * \return -1 on error, 1 if any arguments matched (including via
+ * catch-all callback), 0 if no match.
+ */
+YASM_LIB_DECL
+int yasm_dir_helper(void *obj, yasm_valparam *vp_first, unsigned long line,
+ const yasm_dir_help *help, size_t nhelp, void *data,
+ int (*helper_valparam) (void *object,
+ yasm_valparam *vp,
+ unsigned long line,
+ void *data));
+
+/** Standard helper for yasm_dir_helper() that simply sets a flag when called.
+ * It does not look at the vp; rather, it uses the value of the arg parameter,
+ * and stores an unsigned long value to data.
+ * \param obj unused
+ * \param vp unused
+ * \param line unused
+ * \param data pointer to an unsigned long
+ * \param arg flag to set
+ * \return 0
+ */
+YASM_LIB_DECL
+int yasm_dir_helper_flag_set(void *obj, yasm_valparam *vp, unsigned long line,
+ void *data, uintptr_t arg);
+
+/** Standard helper for yasm_dir_helper() that simply ORs a flag when called.
+ * It does not look at the vp; rather, it uses the value of the arg parameter,
+ * and ORs it with the unsigned long value in data.
+ * \param obj unused
+ * \param vp unused
+ * \param line unused
+ * \param data pointer to an unsigned long
+ * \param arg flag to OR
+ * \return 0
+ */
+YASM_LIB_DECL
+int yasm_dir_helper_flag_or(void *obj, yasm_valparam *vp, unsigned long line,
+ void *data, uintptr_t arg);
+
+/** Standard helper for yasm_dir_helper() that simply ANDs a flag when called.
+ * It does not look at the vp; rather, it uses the value of the arg parameter,
+ * and ANDs its inverse (~) with the unsigned long value in data.
+ * \param obj unused
+ * \param vp unused
+ * \param line unused
+ * \param data pointer to an unsigned long
+ * \param arg flag to AND
+ * \return 0
+ */
+YASM_LIB_DECL
+int yasm_dir_helper_flag_and(void *obj, yasm_valparam *vp, unsigned long line,
+ void *data, uintptr_t arg);
+
+/** Standard helper for yasm_dir_helper() that parses an expr parameter.
+ * The #yasm_dir_help structure that uses this function should have
+ * needsparam=1. The obj parameter to yasm_dir_helper() when this helper
+ * is used MUST point to a #yasm_object. In addition, the data parameter
+ * that is ultimately passed to this function (e.g. yasm_dir_helper() data
+ * parameter plus #yasm_dir_help.off) must point to a #yasm_expr *
+ * initialized to NULL.
+ * \param obj object; must be #yasm_object
+ * \param vp valparam
+ * \param line virtual line number
+ * \param data pointer to #yasm_expr *
+ * \param arg unused argument
+ * \return -1 on error, 0 otherwise.
+ */
+YASM_LIB_DECL
+int yasm_dir_helper_expr(void *obj, yasm_valparam *vp, unsigned long line,
+ void *data, uintptr_t arg);
+
+/** Standard helper for yasm_dir_helper() that parses an intnum parameter.
+ * The #yasm_dir_help structure that uses this function should have
+ * needsparam=1. The obj parameter to yasm_dir_helper() when this helper
+ * is used MUST point to a #yasm_object. In addition, the data parameter
+ * that is ultimately passed to this function (e.g. yasm_dir_helper() data
+ * parameter plus #yasm_dir_help.off) must point to a #yasm_intnum *
+ * initialized to NULL.
+ * \param obj object; must be #yasm_object
+ * \param vp valparam
+ * \param line virtual line number
+ * \param data pointer to #yasm_intnum *
+ * \param arg unused argument
+ * \return -1 on error, 0 otherwise.
+ */
+YASM_LIB_DECL
+int yasm_dir_helper_intn(void *obj, yasm_valparam *vp, unsigned long line,
+ void *data, uintptr_t arg);
+
+/** Standard helper for yasm_dir_helper() that parses an string (or
+ * standalone identifier) parameter.
+ * The #yasm_dir_help structure that uses this function should have
+ * needsparam=1. The data parameter that is ultimately passed to this
+ * function (e.g. yasm_dir_helper() data parameter plus #yasm_dir_help.off)
+ * must point to a char * initialized to NULL.
+ * \param obj unused
+ * \param vp valparam
+ * \param line unused
+ * \param data pointer to char *
+ * \param arg unused
+ * \return -1 on error, 0 otherwise.
+ */
+YASM_LIB_DECL
+int yasm_dir_helper_string(void *obj, yasm_valparam *vp, unsigned long line,
+ void *data, uintptr_t arg);
+
+/** Standard catch-all callback fro yasm_dir_helper(). Generates standard
+ * warning for all valparams.
+ * \param obj unused
+ * \param vp valparam
+ * \param line unused
+ * \param data unused
+ * \return 0
+ */
+YASM_LIB_DECL
+int yasm_dir_helper_valparam_warn(void *obj, yasm_valparam *vp,
+ unsigned long line, void *data);
+#endif
diff --git a/contrib/tools/yasm/libyasm/value.c b/contrib/tools/yasm/libyasm/value.c
index 3ab73c1cec..714b80f0c4 100644
--- a/contrib/tools/yasm/libyasm/value.c
+++ b/contrib/tools/yasm/libyasm/value.c
@@ -1,771 +1,771 @@
-/*
- * Value handling
- *
- * Copyright (C) 2006-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#include "util.h"
-
-#include "libyasm-stdint.h"
-#include "coretype.h"
-#include "bitvect.h"
-
-#include "errwarn.h"
-#include "intnum.h"
-#include "floatnum.h"
-#include "expr.h"
-#include "value.h"
-#include "symrec.h"
-
-#include "bytecode.h"
-#include "section.h"
-
-#include "arch.h"
-
-
-void
-yasm_value_initialize(/*@out@*/ yasm_value *value,
- /*@null@*/ /*@kept@*/ yasm_expr *e, unsigned int size)
-{
- value->abs = e;
- value->rel = NULL;
- value->wrt = NULL;
- value->seg_of = 0;
- value->rshift = 0;
- value->curpos_rel = 0;
- value->ip_rel = 0;
- value->jump_target = 0;
- value->section_rel = 0;
- value->no_warn = 0;
- value->sign = 0;
- value->size = size;
-}
-
-void
-yasm_value_init_sym(/*@out@*/ yasm_value *value, /*@null@*/ yasm_symrec *sym,
- unsigned int size)
-{
- value->abs = NULL;
- value->rel = sym;
- value->wrt = NULL;
- value->seg_of = 0;
- value->rshift = 0;
- value->curpos_rel = 0;
- value->ip_rel = 0;
- value->jump_target = 0;
- value->section_rel = 0;
- value->no_warn = 0;
- value->sign = 0;
- value->size = size;
-}
-
-void
-yasm_value_init_copy(yasm_value *value, const yasm_value *orig)
-{
- value->abs = orig->abs ? yasm_expr_copy(orig->abs) : NULL;
- value->rel = orig->rel;
- value->wrt = orig->wrt;
- value->seg_of = orig->seg_of;
- value->rshift = orig->rshift;
- value->curpos_rel = orig->curpos_rel;
- value->ip_rel = orig->ip_rel;
- value->jump_target = orig->jump_target;
- value->section_rel = orig->section_rel;
- value->no_warn = orig->no_warn;
- value->sign = orig->sign;
- value->size = orig->size;
-}
-
-void
-yasm_value_delete(yasm_value *value)
-{
- if (value->abs)
- yasm_expr_destroy(value->abs);
- value->abs = NULL;
- value->rel = NULL;
-}
-
-void
-yasm_value_set_curpos_rel(yasm_value *value, yasm_bytecode *bc,
- unsigned int ip_rel)
-{
- value->curpos_rel = 1;
- value->ip_rel = ip_rel;
- /* In order for us to correctly output curpos-relative values, we must
- * have a relative portion of the value. If one doesn't exist, point
- * to a custom absolute symbol.
- */
- if (!value->rel) {
- yasm_object *object = yasm_section_get_object(yasm_bc_get_section(bc));
- value->rel = yasm_symtab_abs_sym(object->symtab);
- }
-}
-
-static int
-value_finalize_scan(yasm_value *value, yasm_expr *e,
- /*@null@*/ yasm_bytecode *expr_precbc, int ssym_not_ok)
-{
- int i;
- /*@dependent@*/ yasm_section *sect;
- /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc;
-
- unsigned long shamt; /* for SHR */
-
- /* Yes, this has a maximum upper bound on 32 terms, based on an
- * "insane number of terms" (and ease of implementation) WAG.
- * The right way to do this would be a stack-based alloca, but that's
- * not ISO C. We really don't want to malloc here as this function is
- * hit a lot!
- *
- * This is a bitmask to keep things small, as this is a recursive
- * routine and we don't want to eat up stack space.
- */
- unsigned long used; /* for ADD */
-
- /* Thanks to this running after a simplify, we don't need to iterate
- * down through IDENTs or handle SUB.
- *
- * We scan for a single symrec, gathering info along the way. After
- * we've found the symrec, we keep scanning but error if we find
- * another one. We pull out the single symrec and any legal operations
- * performed on it.
- *
- * Also, if we find a float anywhere, we don't allow mixing of a single
- * symrec with it.
- */
- switch (e->op) {
- case YASM_EXPR_ADD:
- /* Okay for single symrec anywhere in expr.
- * Check for single symrec anywhere.
- * Handle symrec-symrec by checking for (-1*symrec)
- * and symrec term pairs (where both symrecs are in the same
- * segment).
- */
- if (e->numterms > 32)
- yasm__fatal(N_("expression on line %d has too many add terms;"
- " internal limit of 32"), e->line);
-
- used = 0;
-
- for (i=0; i<e->numterms; i++) {
- int j;
- yasm_expr *sube;
- yasm_intnum *intn;
- yasm_symrec *sym;
- /*@dependent@*/ yasm_section *sect2;
- /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc2;
-
- /* First look for an (-1*symrec) term */
- if (e->terms[i].type != YASM_EXPR_EXPR)
- continue;
- sube = e->terms[i].data.expn;
-
- if (sube->op != YASM_EXPR_MUL || sube->numterms != 2) {
- /* recurse instead */
- if (value_finalize_scan(value, sube, expr_precbc,
- ssym_not_ok))
- return 1;
- continue;
- }
-
- if (sube->terms[0].type == YASM_EXPR_INT &&
- sube->terms[1].type == YASM_EXPR_SYM) {
- intn = sube->terms[0].data.intn;
- sym = sube->terms[1].data.sym;
- } else if (sube->terms[0].type == YASM_EXPR_SYM &&
- sube->terms[1].type == YASM_EXPR_INT) {
- sym = sube->terms[0].data.sym;
- intn = sube->terms[1].data.intn;
- } else {
- if (value_finalize_scan(value, sube, expr_precbc,
- ssym_not_ok))
- return 1;
- continue;
- }
-
- if (!yasm_intnum_is_neg1(intn)) {
- if (value_finalize_scan(value, sube, expr_precbc,
- ssym_not_ok))
- return 1;
- continue;
- }
-
- /* Look for the same symrec term; even if both are external,
- * they should cancel out.
- */
- for (j=0; j<e->numterms; j++) {
- if (e->terms[j].type == YASM_EXPR_SYM
- && e->terms[j].data.sym == sym
- && (used & (1<<j)) == 0) {
- /* Mark as used */
- used |= 1<<j;
-
- /* Replace both symrec portions with 0 */
- yasm_expr_destroy(sube);
- e->terms[i].type = YASM_EXPR_INT;
- e->terms[i].data.intn = yasm_intnum_create_uint(0);
- e->terms[j].type = YASM_EXPR_INT;
- e->terms[j].data.intn = yasm_intnum_create_uint(0);
-
- break; /* stop looking */
- }
- }
- if (j != e->numterms)
- continue;
-
- if (!yasm_symrec_get_label(sym, &precbc)) {
- if (value_finalize_scan(value, sube, expr_precbc,
- ssym_not_ok))
- return 1;
- continue;
- }
- sect2 = yasm_bc_get_section(precbc);
-
- /* Now look for a unused symrec term in the same segment */
- for (j=0; j<e->numterms; j++) {
- if (e->terms[j].type == YASM_EXPR_SYM
- && yasm_symrec_get_label(e->terms[j].data.sym,
- &precbc2)
- && (sect = yasm_bc_get_section(precbc2))
- && sect == sect2
- && (used & (1<<j)) == 0) {
- /* Mark as used */
- used |= 1<<j;
- break; /* stop looking */
- }
- }
-
- /* We didn't match in the same segment. If the
- * -1*symrec is actually -1*curpos, we can match
- * unused symrec terms in other segments and generate
- * a curpos-relative reloc.
- *
- * Similarly, handle -1*symrec in other segment via the
- * following transformation:
- * other-this = (other-.)+(.-this)
- * We can only do this transformation if "this" is in
- * this expr's segment.
- *
- * Don't do this if we've already become curpos-relative.
- * The unmatched symrec will be caught below.
- */
- if (j == e->numterms && !value->curpos_rel
- && (yasm_symrec_is_curpos(sym)
- || (expr_precbc
- && sect2 == yasm_bc_get_section(expr_precbc)))) {
- for (j=0; j<e->numterms; j++) {
- if (e->terms[j].type == YASM_EXPR_SYM
- && !yasm_symrec_get_equ(e->terms[j].data.sym)
- && !yasm_symrec_is_special(e->terms[j].data.sym)
- && (used & (1<<j)) == 0) {
- /* Mark as used */
- used |= 1<<j;
- /* Mark value as curpos-relative */
- if (value->rel || ssym_not_ok)
- return 1;
- value->rel = e->terms[j].data.sym;
- value->curpos_rel = 1;
- if (yasm_symrec_is_curpos(sym)) {
- /* Replace both symrec portions with 0 */
- yasm_expr_destroy(sube);
- e->terms[i].type = YASM_EXPR_INT;
- e->terms[i].data.intn =
- yasm_intnum_create_uint(0);
- e->terms[j].type = YASM_EXPR_INT;
- e->terms[j].data.intn =
- yasm_intnum_create_uint(0);
- } else {
- /* Replace positive portion with curpos */
- yasm_object *object =
- yasm_section_get_object(sect2);
- yasm_symtab *symtab = object->symtab;
- e->terms[j].data.sym =
- yasm_symtab_define_curpos
- (symtab, ".", expr_precbc, e->line);
- }
- break; /* stop looking */
- }
- }
- }
-
-
- if (j == e->numterms)
- return 1; /* We didn't find a match! */
- }
-
- /* Look for unmatched symrecs. If we've already found one or
- * we don't WANT to find one, error out.
- */
- for (i=0; i<e->numterms; i++) {
- if (e->terms[i].type == YASM_EXPR_SYM
- && (used & (1<<i)) == 0) {
- if (value->rel || ssym_not_ok)
- return 1;
- value->rel = e->terms[i].data.sym;
- /* and replace with 0 */
- e->terms[i].type = YASM_EXPR_INT;
- e->terms[i].data.intn = yasm_intnum_create_uint(0);
- }
- }
- break;
- case YASM_EXPR_SHR:
- /* Okay for single symrec in LHS and constant on RHS.
- * Single symrecs are not okay on RHS.
- * If RHS is non-constant, don't allow single symrec on LHS.
- * XXX: should rshift be an expr instead??
- */
-
- /* Check for single sym on LHS */
- if (e->terms[0].type != YASM_EXPR_SYM)
- break;
-
- /* If we already have a sym, we can't take another one */
- if (value->rel || ssym_not_ok)
- return 1;
-
- /* RHS must be a positive integer */
- if (e->terms[1].type != YASM_EXPR_INT)
- return 1; /* can't shift sym by non-constant integer */
- shamt = yasm_intnum_get_uint(e->terms[1].data.intn);
- if ((shamt + value->rshift) > YASM_VALUE_RSHIFT_MAX)
- return 1; /* total shift would be too large */
-
- /* Update value */
- value->rshift += shamt;
- value->rel = e->terms[0].data.sym;
-
- /* Replace symbol with 0 */
- e->terms[0].type = YASM_EXPR_INT;
- e->terms[0].data.intn = yasm_intnum_create_uint(0);
-
- /* Just leave SHR in place */
- break;
- case YASM_EXPR_SEG:
- /* Okay for single symrec (can only be done once).
- * Not okay for anything BUT a single symrec as an immediate
- * child.
- */
- if (e->terms[0].type != YASM_EXPR_SYM)
- return 1;
-
- if (value->seg_of)
- return 1; /* multiple SEG not legal */
- value->seg_of = 1;
-
- if (value->rel || ssym_not_ok)
- return 1; /* got a relative portion somewhere else? */
- value->rel = e->terms[0].data.sym;
-
- /* replace with ident'ed 0 */
- e->op = YASM_EXPR_IDENT;
- e->terms[0].type = YASM_EXPR_INT;
- e->terms[0].data.intn = yasm_intnum_create_uint(0);
- break;
- case YASM_EXPR_WRT:
- /* Okay for single symrec in LHS and either a register or single
- * symrec (as an immediate child) on RHS.
- * If a single symrec on RHS, can only be done once.
- * WRT reg is left in expr for arch to look at.
- */
-
- /* Handle RHS */
- switch (e->terms[1].type) {
- case YASM_EXPR_SYM:
- if (value->wrt)
- return 1;
- value->wrt = e->terms[1].data.sym;
- /* and drop the WRT portion */
- e->op = YASM_EXPR_IDENT;
- e->numterms = 1;
- break;
- case YASM_EXPR_REG:
- break; /* ignore */
- default:
- return 1;
- }
-
- /* Handle LHS */
- switch (e->terms[0].type) {
- case YASM_EXPR_SYM:
- if (value->rel || ssym_not_ok)
- return 1;
- value->rel = e->terms[0].data.sym;
- /* and replace with 0 */
- e->terms[0].type = YASM_EXPR_INT;
- e->terms[0].data.intn = yasm_intnum_create_uint(0);
- break;
- case YASM_EXPR_EXPR:
- /* recurse */
- return value_finalize_scan(value, e->terms[0].data.expn,
- expr_precbc, ssym_not_ok);
- default:
- break; /* ignore */
- }
-
- break;
- default:
- /* Single symrec not allowed anywhere */
- for (i=0; i<e->numterms; i++) {
- switch (e->terms[i].type) {
- case YASM_EXPR_SYM:
- return 1;
- case YASM_EXPR_EXPR:
- /* recurse */
- return value_finalize_scan(value,
- e->terms[i].data.expn,
- expr_precbc, 1);
- default:
- break;
- }
- }
- break;
- }
-
- return 0;
-}
-
-int
-yasm_value_finalize_expr(yasm_value *value, yasm_expr *e,
- yasm_bytecode *precbc, unsigned int size)
-{
- if (!e) {
- yasm_value_initialize(value, NULL, size);
- return 0;
- }
- yasm_value_initialize(value, e, size);
- return yasm_value_finalize(value, precbc);
-}
-
-int
-yasm_value_finalize(yasm_value *value, yasm_bytecode *precbc)
-{
- if (!value->abs)
- return 0;
-
- value->abs = yasm_expr__level_tree(value->abs, 1, 1, 0, 0, NULL, NULL);
-
- /* quit early if there was an issue in simplify() */
- if (yasm_error_occurred())
- return 1;
-
- /* Strip top-level AND masking to an all-1s mask the same size
- * of the value size. This allows forced avoidance of overflow warnings.
- */
- if (value->abs->op == YASM_EXPR_AND) {
- int term;
-
- /* Calculate 1<<size - 1 value */
- yasm_intnum *mask = yasm_intnum_create_uint(1);
- yasm_intnum *mask_tmp = yasm_intnum_create_uint(value->size);
- yasm_intnum_calc(mask, YASM_EXPR_SHL, mask_tmp);
- yasm_intnum_set_uint(mask_tmp, 1);
- yasm_intnum_calc(mask, YASM_EXPR_SUB, mask_tmp);
- yasm_intnum_destroy(mask_tmp);
-
- /* Walk terms and delete matching masks */
- for (term=value->abs->numterms-1; term>=0; term--) {
- if (value->abs->terms[term].type == YASM_EXPR_INT &&
- yasm_intnum_compare(value->abs->terms[term].data.intn,
- mask) == 0) {
- /* Delete the intnum */
- yasm_intnum_destroy(value->abs->terms[term].data.intn);
-
- /* Slide everything to its right over by 1 */
- if (term != value->abs->numterms-1) /* if it wasn't last.. */
- memmove(&value->abs->terms[term],
- &value->abs->terms[term+1],
- (value->abs->numterms-1-term)*
- sizeof(yasm_expr__item));
-
- /* Update numterms */
- value->abs->numterms--;
-
- /* Indicate warnings have been disabled */
- value->no_warn = 1;
- }
- }
- if (value->abs->numterms == 1)
- value->abs->op = YASM_EXPR_IDENT;
- yasm_intnum_destroy(mask);
- }
-
- /* Handle trivial (IDENT) cases immediately */
- if (value->abs->op == YASM_EXPR_IDENT) {
- switch (value->abs->terms[0].type) {
- case YASM_EXPR_INT:
- if (yasm_intnum_is_zero(value->abs->terms[0].data.intn)) {
- yasm_expr_destroy(value->abs);
- value->abs = NULL;
- }
- return 0;
- case YASM_EXPR_REG:
- case YASM_EXPR_FLOAT:
- return 0;
- case YASM_EXPR_SYM:
- value->rel = value->abs->terms[0].data.sym;
- yasm_expr_destroy(value->abs);
- value->abs = NULL;
- return 0;
- case YASM_EXPR_EXPR:
- /* Bring up lower values. */
- while (value->abs->op == YASM_EXPR_IDENT
- && value->abs->terms[0].type == YASM_EXPR_EXPR) {
- yasm_expr *sube = value->abs->terms[0].data.expn;
- yasm_xfree(value->abs);
- value->abs = sube;
- }
- break;
- default:
- yasm_internal_error(N_("unexpected expr term type"));
- }
- }
-
- if (value_finalize_scan(value, value->abs, precbc, 0))
- return 1;
-
- value->abs = yasm_expr__level_tree(value->abs, 1, 1, 0, 0, NULL, NULL);
-
- /* Simplify 0 in abs to NULL */
- if (value->abs->op == YASM_EXPR_IDENT
- && value->abs->terms[0].type == YASM_EXPR_INT
- && yasm_intnum_is_zero(value->abs->terms[0].data.intn)) {
- yasm_expr_destroy(value->abs);
- value->abs = NULL;
- }
- return 0;
-}
-
-yasm_intnum *
-yasm_value_get_intnum(yasm_value *value, yasm_bytecode *bc, int calc_bc_dist)
-{
- /*@dependent@*/ /*@null@*/ yasm_intnum *intn = NULL;
- /*@only@*/ yasm_intnum *outval;
- int sym_local;
-
- if (value->abs) {
- /* Handle integer expressions, if non-integer or too complex, return
- * NULL.
- */
- intn = yasm_expr_get_intnum(&value->abs, calc_bc_dist);
- if (!intn)
- return NULL;
- }
-
- if (value->rel) {
- /* If relative portion is not in bc section, return NULL.
- * Otherwise get the relative portion's offset.
- */
- /*@dependent@*/ yasm_bytecode *rel_prevbc;
- unsigned long dist;
-
- if (!bc)
- return NULL; /* Can't calculate relative value */
-
- sym_local = yasm_symrec_get_label(value->rel, &rel_prevbc);
- if (value->wrt || value->seg_of || value->section_rel || !sym_local)
- return NULL; /* we can't handle SEG, WRT, or external symbols */
- if (rel_prevbc->section != bc->section)
- return NULL; /* not in this section */
- if (!value->curpos_rel)
- return NULL; /* not PC-relative */
-
- /* Calculate value relative to current assembly position */
- dist = yasm_bc_next_offset(rel_prevbc);
- if (dist < bc->offset) {
- outval = yasm_intnum_create_uint(bc->offset - dist);
- yasm_intnum_calc(outval, YASM_EXPR_NEG, NULL);
- } else {
- dist -= bc->offset;
- outval = yasm_intnum_create_uint(dist);
- }
-
- if (value->rshift > 0) {
- /*@only@*/ yasm_intnum *shamt =
- yasm_intnum_create_uint((unsigned long)value->rshift);
- yasm_intnum_calc(outval, YASM_EXPR_SHR, shamt);
- yasm_intnum_destroy(shamt);
- }
- /* Add in absolute portion */
- if (intn)
- yasm_intnum_calc(outval, YASM_EXPR_ADD, intn);
- return outval;
- }
-
- if (intn)
- return yasm_intnum_copy(intn);
-
- /* No absolute or relative portions: output 0 */
- return yasm_intnum_create_uint(0);
-}
-
-int
-yasm_value_output_basic(yasm_value *value, /*@out@*/ unsigned char *buf,
- size_t destsize, yasm_bytecode *bc, int warn,
- yasm_arch *arch)
-{
- /*@dependent@*/ /*@null@*/ yasm_intnum *intn = NULL;
- /*@only@*/ yasm_intnum *outval;
- int sym_local;
- int retval = 1;
- unsigned int valsize = value->size;
-
- if (value->no_warn)
- warn = 0;
-
- if (value->abs) {
- /* Handle floating point expressions */
- if (!value->rel && value->abs->op == YASM_EXPR_IDENT
- && value->abs->terms[0].type == YASM_EXPR_FLOAT) {
- if (yasm_arch_floatnum_tobytes(arch, value->abs->terms[0].data.flt,
- buf, destsize, valsize, 0, warn))
- return -1;
- else
- return 1;
- }
-
- /* Check for complex float expressions */
- if (yasm_expr__contains(value->abs, YASM_EXPR_FLOAT)) {
- yasm_error_set(YASM_ERROR_FLOATING_POINT,
- N_("floating point expression too complex"));
- return -1;
- }
-
- /* Handle normal integer expressions */
- intn = yasm_expr_get_intnum(&value->abs, 1);
-
- if (!intn) {
- /* Second try before erroring: yasm_expr_get_intnum doesn't handle
- * SEG:OFF, so try simplifying out any to just the OFF portion,
- * then getting the intnum again.
- */
- yasm_expr *seg = yasm_expr_extract_deep_segoff(&value->abs);
- if (seg)
- yasm_expr_destroy(seg);
- intn = yasm_expr_get_intnum(&value->abs, 1);
- }
-
- if (!intn) {
- /* Still don't have an integer! */
- yasm_error_set(YASM_ERROR_TOO_COMPLEX,
- N_("expression too complex"));
- return -1;
- }
- }
-
- /* Adjust warn for signed/unsigned integer warnings */
- if (warn != 0)
- warn = value->sign ? -1 : 1;
-
- if (value->rel) {
- /* If relative portion is not in bc section, don't try to handle it
- * here. Otherwise get the relative portion's offset.
- */
- /*@dependent@*/ yasm_bytecode *rel_prevbc;
- unsigned long dist;
-
- sym_local = yasm_symrec_get_label(value->rel, &rel_prevbc);
- if (value->wrt || value->seg_of || value->section_rel || !sym_local)
- return 0; /* we can't handle SEG, WRT, or external symbols */
- if (rel_prevbc->section != bc->section)
- return 0; /* not in this section */
- if (!value->curpos_rel)
- return 0; /* not PC-relative */
-
- /* Calculate value relative to current assembly position */
- dist = yasm_bc_next_offset(rel_prevbc);
- if (dist < bc->offset) {
- outval = yasm_intnum_create_uint(bc->offset - dist);
- yasm_intnum_calc(outval, YASM_EXPR_NEG, NULL);
- } else {
- dist -= bc->offset;
- outval = yasm_intnum_create_uint(dist);
- }
-
- if (value->rshift > 0) {
- /*@only@*/ yasm_intnum *shamt =
- yasm_intnum_create_uint((unsigned long)value->rshift);
- yasm_intnum_calc(outval, YASM_EXPR_SHR, shamt);
- yasm_intnum_destroy(shamt);
- }
- /* Add in absolute portion */
- if (intn)
- yasm_intnum_calc(outval, YASM_EXPR_ADD, intn);
- /* Output! */
- if (yasm_arch_intnum_tobytes(arch, outval, buf, destsize, valsize, 0,
- bc, warn))
- retval = -1;
- yasm_intnum_destroy(outval);
- return retval;
- }
-
- if (value->seg_of || value->rshift || value->curpos_rel || value->ip_rel
- || value->section_rel)
- return 0; /* We can't handle this with just an absolute */
-
- if (intn) {
- /* Output just absolute portion */
- if (yasm_arch_intnum_tobytes(arch, intn, buf, destsize, valsize, 0, bc,
- warn))
- retval = -1;
- } else {
- /* No absolute or relative portions: output 0 */
- outval = yasm_intnum_create_uint(0);
- if (yasm_arch_intnum_tobytes(arch, outval, buf, destsize, valsize, 0,
- bc, warn))
- retval = -1;
- yasm_intnum_destroy(outval);
- }
- return retval;
-}
-
-void
-yasm_value_print(const yasm_value *value, FILE *f, int indent_level)
-{
- fprintf(f, "%*s%u-bit, %ssigned", indent_level, "", value->size,
- value->sign ? "" : "un");
- fprintf(f, "%*sAbsolute portion=", indent_level, "");
- yasm_expr_print(value->abs, f);
- fprintf(f, "\n");
- if (value->rel) {
- fprintf(f, "%*sRelative to=%s%s\n", indent_level, "",
- value->seg_of ? "SEG " : "",
- yasm_symrec_get_name(value->rel));
- if (value->wrt)
- fprintf(f, "%*s(With respect to=%s)\n", indent_level, "",
- yasm_symrec_get_name(value->wrt));
- if (value->rshift > 0)
- fprintf(f, "%*s(Right shifted by=%u)\n", indent_level, "",
- value->rshift);
- if (value->curpos_rel)
- fprintf(f, "%*s(Relative to current position)\n", indent_level,
- "");
- if (value->ip_rel)
- fprintf(f, "%*s(IP-relative)\n", indent_level, "");
- if (value->jump_target)
- fprintf(f, "%*s(Jump target)\n", indent_level, "");
- if (value->section_rel)
- fprintf(f, "%*s(Section-relative)\n", indent_level, "");
- if (value->no_warn)
- fprintf(f, "%*s(Overflow warnings disabled)\n", indent_level, "");
- }
-}
+/*
+ * Value handling
+ *
+ * Copyright (C) 2006-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "util.h"
+
+#include "libyasm-stdint.h"
+#include "coretype.h"
+#include "bitvect.h"
+
+#include "errwarn.h"
+#include "intnum.h"
+#include "floatnum.h"
+#include "expr.h"
+#include "value.h"
+#include "symrec.h"
+
+#include "bytecode.h"
+#include "section.h"
+
+#include "arch.h"
+
+
+void
+yasm_value_initialize(/*@out@*/ yasm_value *value,
+ /*@null@*/ /*@kept@*/ yasm_expr *e, unsigned int size)
+{
+ value->abs = e;
+ value->rel = NULL;
+ value->wrt = NULL;
+ value->seg_of = 0;
+ value->rshift = 0;
+ value->curpos_rel = 0;
+ value->ip_rel = 0;
+ value->jump_target = 0;
+ value->section_rel = 0;
+ value->no_warn = 0;
+ value->sign = 0;
+ value->size = size;
+}
+
+void
+yasm_value_init_sym(/*@out@*/ yasm_value *value, /*@null@*/ yasm_symrec *sym,
+ unsigned int size)
+{
+ value->abs = NULL;
+ value->rel = sym;
+ value->wrt = NULL;
+ value->seg_of = 0;
+ value->rshift = 0;
+ value->curpos_rel = 0;
+ value->ip_rel = 0;
+ value->jump_target = 0;
+ value->section_rel = 0;
+ value->no_warn = 0;
+ value->sign = 0;
+ value->size = size;
+}
+
+void
+yasm_value_init_copy(yasm_value *value, const yasm_value *orig)
+{
+ value->abs = orig->abs ? yasm_expr_copy(orig->abs) : NULL;
+ value->rel = orig->rel;
+ value->wrt = orig->wrt;
+ value->seg_of = orig->seg_of;
+ value->rshift = orig->rshift;
+ value->curpos_rel = orig->curpos_rel;
+ value->ip_rel = orig->ip_rel;
+ value->jump_target = orig->jump_target;
+ value->section_rel = orig->section_rel;
+ value->no_warn = orig->no_warn;
+ value->sign = orig->sign;
+ value->size = orig->size;
+}
+
+void
+yasm_value_delete(yasm_value *value)
+{
+ if (value->abs)
+ yasm_expr_destroy(value->abs);
+ value->abs = NULL;
+ value->rel = NULL;
+}
+
+void
+yasm_value_set_curpos_rel(yasm_value *value, yasm_bytecode *bc,
+ unsigned int ip_rel)
+{
+ value->curpos_rel = 1;
+ value->ip_rel = ip_rel;
+ /* In order for us to correctly output curpos-relative values, we must
+ * have a relative portion of the value. If one doesn't exist, point
+ * to a custom absolute symbol.
+ */
+ if (!value->rel) {
+ yasm_object *object = yasm_section_get_object(yasm_bc_get_section(bc));
+ value->rel = yasm_symtab_abs_sym(object->symtab);
+ }
+}
+
+static int
+value_finalize_scan(yasm_value *value, yasm_expr *e,
+ /*@null@*/ yasm_bytecode *expr_precbc, int ssym_not_ok)
+{
+ int i;
+ /*@dependent@*/ yasm_section *sect;
+ /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc;
+
+ unsigned long shamt; /* for SHR */
+
+ /* Yes, this has a maximum upper bound on 32 terms, based on an
+ * "insane number of terms" (and ease of implementation) WAG.
+ * The right way to do this would be a stack-based alloca, but that's
+ * not ISO C. We really don't want to malloc here as this function is
+ * hit a lot!
+ *
+ * This is a bitmask to keep things small, as this is a recursive
+ * routine and we don't want to eat up stack space.
+ */
+ unsigned long used; /* for ADD */
+
+ /* Thanks to this running after a simplify, we don't need to iterate
+ * down through IDENTs or handle SUB.
+ *
+ * We scan for a single symrec, gathering info along the way. After
+ * we've found the symrec, we keep scanning but error if we find
+ * another one. We pull out the single symrec and any legal operations
+ * performed on it.
+ *
+ * Also, if we find a float anywhere, we don't allow mixing of a single
+ * symrec with it.
+ */
+ switch (e->op) {
+ case YASM_EXPR_ADD:
+ /* Okay for single symrec anywhere in expr.
+ * Check for single symrec anywhere.
+ * Handle symrec-symrec by checking for (-1*symrec)
+ * and symrec term pairs (where both symrecs are in the same
+ * segment).
+ */
+ if (e->numterms > 32)
+ yasm__fatal(N_("expression on line %d has too many add terms;"
+ " internal limit of 32"), e->line);
+
+ used = 0;
+
+ for (i=0; i<e->numterms; i++) {
+ int j;
+ yasm_expr *sube;
+ yasm_intnum *intn;
+ yasm_symrec *sym;
+ /*@dependent@*/ yasm_section *sect2;
+ /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc2;
+
+ /* First look for an (-1*symrec) term */
+ if (e->terms[i].type != YASM_EXPR_EXPR)
+ continue;
+ sube = e->terms[i].data.expn;
+
+ if (sube->op != YASM_EXPR_MUL || sube->numterms != 2) {
+ /* recurse instead */
+ if (value_finalize_scan(value, sube, expr_precbc,
+ ssym_not_ok))
+ return 1;
+ continue;
+ }
+
+ if (sube->terms[0].type == YASM_EXPR_INT &&
+ sube->terms[1].type == YASM_EXPR_SYM) {
+ intn = sube->terms[0].data.intn;
+ sym = sube->terms[1].data.sym;
+ } else if (sube->terms[0].type == YASM_EXPR_SYM &&
+ sube->terms[1].type == YASM_EXPR_INT) {
+ sym = sube->terms[0].data.sym;
+ intn = sube->terms[1].data.intn;
+ } else {
+ if (value_finalize_scan(value, sube, expr_precbc,
+ ssym_not_ok))
+ return 1;
+ continue;
+ }
+
+ if (!yasm_intnum_is_neg1(intn)) {
+ if (value_finalize_scan(value, sube, expr_precbc,
+ ssym_not_ok))
+ return 1;
+ continue;
+ }
+
+ /* Look for the same symrec term; even if both are external,
+ * they should cancel out.
+ */
+ for (j=0; j<e->numterms; j++) {
+ if (e->terms[j].type == YASM_EXPR_SYM
+ && e->terms[j].data.sym == sym
+ && (used & (1<<j)) == 0) {
+ /* Mark as used */
+ used |= 1<<j;
+
+ /* Replace both symrec portions with 0 */
+ yasm_expr_destroy(sube);
+ e->terms[i].type = YASM_EXPR_INT;
+ e->terms[i].data.intn = yasm_intnum_create_uint(0);
+ e->terms[j].type = YASM_EXPR_INT;
+ e->terms[j].data.intn = yasm_intnum_create_uint(0);
+
+ break; /* stop looking */
+ }
+ }
+ if (j != e->numterms)
+ continue;
+
+ if (!yasm_symrec_get_label(sym, &precbc)) {
+ if (value_finalize_scan(value, sube, expr_precbc,
+ ssym_not_ok))
+ return 1;
+ continue;
+ }
+ sect2 = yasm_bc_get_section(precbc);
+
+ /* Now look for a unused symrec term in the same segment */
+ for (j=0; j<e->numterms; j++) {
+ if (e->terms[j].type == YASM_EXPR_SYM
+ && yasm_symrec_get_label(e->terms[j].data.sym,
+ &precbc2)
+ && (sect = yasm_bc_get_section(precbc2))
+ && sect == sect2
+ && (used & (1<<j)) == 0) {
+ /* Mark as used */
+ used |= 1<<j;
+ break; /* stop looking */
+ }
+ }
+
+ /* We didn't match in the same segment. If the
+ * -1*symrec is actually -1*curpos, we can match
+ * unused symrec terms in other segments and generate
+ * a curpos-relative reloc.
+ *
+ * Similarly, handle -1*symrec in other segment via the
+ * following transformation:
+ * other-this = (other-.)+(.-this)
+ * We can only do this transformation if "this" is in
+ * this expr's segment.
+ *
+ * Don't do this if we've already become curpos-relative.
+ * The unmatched symrec will be caught below.
+ */
+ if (j == e->numterms && !value->curpos_rel
+ && (yasm_symrec_is_curpos(sym)
+ || (expr_precbc
+ && sect2 == yasm_bc_get_section(expr_precbc)))) {
+ for (j=0; j<e->numterms; j++) {
+ if (e->terms[j].type == YASM_EXPR_SYM
+ && !yasm_symrec_get_equ(e->terms[j].data.sym)
+ && !yasm_symrec_is_special(e->terms[j].data.sym)
+ && (used & (1<<j)) == 0) {
+ /* Mark as used */
+ used |= 1<<j;
+ /* Mark value as curpos-relative */
+ if (value->rel || ssym_not_ok)
+ return 1;
+ value->rel = e->terms[j].data.sym;
+ value->curpos_rel = 1;
+ if (yasm_symrec_is_curpos(sym)) {
+ /* Replace both symrec portions with 0 */
+ yasm_expr_destroy(sube);
+ e->terms[i].type = YASM_EXPR_INT;
+ e->terms[i].data.intn =
+ yasm_intnum_create_uint(0);
+ e->terms[j].type = YASM_EXPR_INT;
+ e->terms[j].data.intn =
+ yasm_intnum_create_uint(0);
+ } else {
+ /* Replace positive portion with curpos */
+ yasm_object *object =
+ yasm_section_get_object(sect2);
+ yasm_symtab *symtab = object->symtab;
+ e->terms[j].data.sym =
+ yasm_symtab_define_curpos
+ (symtab, ".", expr_precbc, e->line);
+ }
+ break; /* stop looking */
+ }
+ }
+ }
+
+
+ if (j == e->numterms)
+ return 1; /* We didn't find a match! */
+ }
+
+ /* Look for unmatched symrecs. If we've already found one or
+ * we don't WANT to find one, error out.
+ */
+ for (i=0; i<e->numterms; i++) {
+ if (e->terms[i].type == YASM_EXPR_SYM
+ && (used & (1<<i)) == 0) {
+ if (value->rel || ssym_not_ok)
+ return 1;
+ value->rel = e->terms[i].data.sym;
+ /* and replace with 0 */
+ e->terms[i].type = YASM_EXPR_INT;
+ e->terms[i].data.intn = yasm_intnum_create_uint(0);
+ }
+ }
+ break;
+ case YASM_EXPR_SHR:
+ /* Okay for single symrec in LHS and constant on RHS.
+ * Single symrecs are not okay on RHS.
+ * If RHS is non-constant, don't allow single symrec on LHS.
+ * XXX: should rshift be an expr instead??
+ */
+
+ /* Check for single sym on LHS */
+ if (e->terms[0].type != YASM_EXPR_SYM)
+ break;
+
+ /* If we already have a sym, we can't take another one */
+ if (value->rel || ssym_not_ok)
+ return 1;
+
+ /* RHS must be a positive integer */
+ if (e->terms[1].type != YASM_EXPR_INT)
+ return 1; /* can't shift sym by non-constant integer */
+ shamt = yasm_intnum_get_uint(e->terms[1].data.intn);
+ if ((shamt + value->rshift) > YASM_VALUE_RSHIFT_MAX)
+ return 1; /* total shift would be too large */
+
+ /* Update value */
+ value->rshift += shamt;
+ value->rel = e->terms[0].data.sym;
+
+ /* Replace symbol with 0 */
+ e->terms[0].type = YASM_EXPR_INT;
+ e->terms[0].data.intn = yasm_intnum_create_uint(0);
+
+ /* Just leave SHR in place */
+ break;
+ case YASM_EXPR_SEG:
+ /* Okay for single symrec (can only be done once).
+ * Not okay for anything BUT a single symrec as an immediate
+ * child.
+ */
+ if (e->terms[0].type != YASM_EXPR_SYM)
+ return 1;
+
+ if (value->seg_of)
+ return 1; /* multiple SEG not legal */
+ value->seg_of = 1;
+
+ if (value->rel || ssym_not_ok)
+ return 1; /* got a relative portion somewhere else? */
+ value->rel = e->terms[0].data.sym;
+
+ /* replace with ident'ed 0 */
+ e->op = YASM_EXPR_IDENT;
+ e->terms[0].type = YASM_EXPR_INT;
+ e->terms[0].data.intn = yasm_intnum_create_uint(0);
+ break;
+ case YASM_EXPR_WRT:
+ /* Okay for single symrec in LHS and either a register or single
+ * symrec (as an immediate child) on RHS.
+ * If a single symrec on RHS, can only be done once.
+ * WRT reg is left in expr for arch to look at.
+ */
+
+ /* Handle RHS */
+ switch (e->terms[1].type) {
+ case YASM_EXPR_SYM:
+ if (value->wrt)
+ return 1;
+ value->wrt = e->terms[1].data.sym;
+ /* and drop the WRT portion */
+ e->op = YASM_EXPR_IDENT;
+ e->numterms = 1;
+ break;
+ case YASM_EXPR_REG:
+ break; /* ignore */
+ default:
+ return 1;
+ }
+
+ /* Handle LHS */
+ switch (e->terms[0].type) {
+ case YASM_EXPR_SYM:
+ if (value->rel || ssym_not_ok)
+ return 1;
+ value->rel = e->terms[0].data.sym;
+ /* and replace with 0 */
+ e->terms[0].type = YASM_EXPR_INT;
+ e->terms[0].data.intn = yasm_intnum_create_uint(0);
+ break;
+ case YASM_EXPR_EXPR:
+ /* recurse */
+ return value_finalize_scan(value, e->terms[0].data.expn,
+ expr_precbc, ssym_not_ok);
+ default:
+ break; /* ignore */
+ }
+
+ break;
+ default:
+ /* Single symrec not allowed anywhere */
+ for (i=0; i<e->numterms; i++) {
+ switch (e->terms[i].type) {
+ case YASM_EXPR_SYM:
+ return 1;
+ case YASM_EXPR_EXPR:
+ /* recurse */
+ return value_finalize_scan(value,
+ e->terms[i].data.expn,
+ expr_precbc, 1);
+ default:
+ break;
+ }
+ }
+ break;
+ }
+
+ return 0;
+}
+
+int
+yasm_value_finalize_expr(yasm_value *value, yasm_expr *e,
+ yasm_bytecode *precbc, unsigned int size)
+{
+ if (!e) {
+ yasm_value_initialize(value, NULL, size);
+ return 0;
+ }
+ yasm_value_initialize(value, e, size);
+ return yasm_value_finalize(value, precbc);
+}
+
+int
+yasm_value_finalize(yasm_value *value, yasm_bytecode *precbc)
+{
+ if (!value->abs)
+ return 0;
+
+ value->abs = yasm_expr__level_tree(value->abs, 1, 1, 0, 0, NULL, NULL);
+
+ /* quit early if there was an issue in simplify() */
+ if (yasm_error_occurred())
+ return 1;
+
+ /* Strip top-level AND masking to an all-1s mask the same size
+ * of the value size. This allows forced avoidance of overflow warnings.
+ */
+ if (value->abs->op == YASM_EXPR_AND) {
+ int term;
+
+ /* Calculate 1<<size - 1 value */
+ yasm_intnum *mask = yasm_intnum_create_uint(1);
+ yasm_intnum *mask_tmp = yasm_intnum_create_uint(value->size);
+ yasm_intnum_calc(mask, YASM_EXPR_SHL, mask_tmp);
+ yasm_intnum_set_uint(mask_tmp, 1);
+ yasm_intnum_calc(mask, YASM_EXPR_SUB, mask_tmp);
+ yasm_intnum_destroy(mask_tmp);
+
+ /* Walk terms and delete matching masks */
+ for (term=value->abs->numterms-1; term>=0; term--) {
+ if (value->abs->terms[term].type == YASM_EXPR_INT &&
+ yasm_intnum_compare(value->abs->terms[term].data.intn,
+ mask) == 0) {
+ /* Delete the intnum */
+ yasm_intnum_destroy(value->abs->terms[term].data.intn);
+
+ /* Slide everything to its right over by 1 */
+ if (term != value->abs->numterms-1) /* if it wasn't last.. */
+ memmove(&value->abs->terms[term],
+ &value->abs->terms[term+1],
+ (value->abs->numterms-1-term)*
+ sizeof(yasm_expr__item));
+
+ /* Update numterms */
+ value->abs->numterms--;
+
+ /* Indicate warnings have been disabled */
+ value->no_warn = 1;
+ }
+ }
+ if (value->abs->numterms == 1)
+ value->abs->op = YASM_EXPR_IDENT;
+ yasm_intnum_destroy(mask);
+ }
+
+ /* Handle trivial (IDENT) cases immediately */
+ if (value->abs->op == YASM_EXPR_IDENT) {
+ switch (value->abs->terms[0].type) {
+ case YASM_EXPR_INT:
+ if (yasm_intnum_is_zero(value->abs->terms[0].data.intn)) {
+ yasm_expr_destroy(value->abs);
+ value->abs = NULL;
+ }
+ return 0;
+ case YASM_EXPR_REG:
+ case YASM_EXPR_FLOAT:
+ return 0;
+ case YASM_EXPR_SYM:
+ value->rel = value->abs->terms[0].data.sym;
+ yasm_expr_destroy(value->abs);
+ value->abs = NULL;
+ return 0;
+ case YASM_EXPR_EXPR:
+ /* Bring up lower values. */
+ while (value->abs->op == YASM_EXPR_IDENT
+ && value->abs->terms[0].type == YASM_EXPR_EXPR) {
+ yasm_expr *sube = value->abs->terms[0].data.expn;
+ yasm_xfree(value->abs);
+ value->abs = sube;
+ }
+ break;
+ default:
+ yasm_internal_error(N_("unexpected expr term type"));
+ }
+ }
+
+ if (value_finalize_scan(value, value->abs, precbc, 0))
+ return 1;
+
+ value->abs = yasm_expr__level_tree(value->abs, 1, 1, 0, 0, NULL, NULL);
+
+ /* Simplify 0 in abs to NULL */
+ if (value->abs->op == YASM_EXPR_IDENT
+ && value->abs->terms[0].type == YASM_EXPR_INT
+ && yasm_intnum_is_zero(value->abs->terms[0].data.intn)) {
+ yasm_expr_destroy(value->abs);
+ value->abs = NULL;
+ }
+ return 0;
+}
+
+yasm_intnum *
+yasm_value_get_intnum(yasm_value *value, yasm_bytecode *bc, int calc_bc_dist)
+{
+ /*@dependent@*/ /*@null@*/ yasm_intnum *intn = NULL;
+ /*@only@*/ yasm_intnum *outval;
+ int sym_local;
+
+ if (value->abs) {
+ /* Handle integer expressions, if non-integer or too complex, return
+ * NULL.
+ */
+ intn = yasm_expr_get_intnum(&value->abs, calc_bc_dist);
+ if (!intn)
+ return NULL;
+ }
+
+ if (value->rel) {
+ /* If relative portion is not in bc section, return NULL.
+ * Otherwise get the relative portion's offset.
+ */
+ /*@dependent@*/ yasm_bytecode *rel_prevbc;
+ unsigned long dist;
+
+ if (!bc)
+ return NULL; /* Can't calculate relative value */
+
+ sym_local = yasm_symrec_get_label(value->rel, &rel_prevbc);
+ if (value->wrt || value->seg_of || value->section_rel || !sym_local)
+ return NULL; /* we can't handle SEG, WRT, or external symbols */
+ if (rel_prevbc->section != bc->section)
+ return NULL; /* not in this section */
+ if (!value->curpos_rel)
+ return NULL; /* not PC-relative */
+
+ /* Calculate value relative to current assembly position */
+ dist = yasm_bc_next_offset(rel_prevbc);
+ if (dist < bc->offset) {
+ outval = yasm_intnum_create_uint(bc->offset - dist);
+ yasm_intnum_calc(outval, YASM_EXPR_NEG, NULL);
+ } else {
+ dist -= bc->offset;
+ outval = yasm_intnum_create_uint(dist);
+ }
+
+ if (value->rshift > 0) {
+ /*@only@*/ yasm_intnum *shamt =
+ yasm_intnum_create_uint((unsigned long)value->rshift);
+ yasm_intnum_calc(outval, YASM_EXPR_SHR, shamt);
+ yasm_intnum_destroy(shamt);
+ }
+ /* Add in absolute portion */
+ if (intn)
+ yasm_intnum_calc(outval, YASM_EXPR_ADD, intn);
+ return outval;
+ }
+
+ if (intn)
+ return yasm_intnum_copy(intn);
+
+ /* No absolute or relative portions: output 0 */
+ return yasm_intnum_create_uint(0);
+}
+
+int
+yasm_value_output_basic(yasm_value *value, /*@out@*/ unsigned char *buf,
+ size_t destsize, yasm_bytecode *bc, int warn,
+ yasm_arch *arch)
+{
+ /*@dependent@*/ /*@null@*/ yasm_intnum *intn = NULL;
+ /*@only@*/ yasm_intnum *outval;
+ int sym_local;
+ int retval = 1;
+ unsigned int valsize = value->size;
+
+ if (value->no_warn)
+ warn = 0;
+
+ if (value->abs) {
+ /* Handle floating point expressions */
+ if (!value->rel && value->abs->op == YASM_EXPR_IDENT
+ && value->abs->terms[0].type == YASM_EXPR_FLOAT) {
+ if (yasm_arch_floatnum_tobytes(arch, value->abs->terms[0].data.flt,
+ buf, destsize, valsize, 0, warn))
+ return -1;
+ else
+ return 1;
+ }
+
+ /* Check for complex float expressions */
+ if (yasm_expr__contains(value->abs, YASM_EXPR_FLOAT)) {
+ yasm_error_set(YASM_ERROR_FLOATING_POINT,
+ N_("floating point expression too complex"));
+ return -1;
+ }
+
+ /* Handle normal integer expressions */
+ intn = yasm_expr_get_intnum(&value->abs, 1);
+
+ if (!intn) {
+ /* Second try before erroring: yasm_expr_get_intnum doesn't handle
+ * SEG:OFF, so try simplifying out any to just the OFF portion,
+ * then getting the intnum again.
+ */
+ yasm_expr *seg = yasm_expr_extract_deep_segoff(&value->abs);
+ if (seg)
+ yasm_expr_destroy(seg);
+ intn = yasm_expr_get_intnum(&value->abs, 1);
+ }
+
+ if (!intn) {
+ /* Still don't have an integer! */
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("expression too complex"));
+ return -1;
+ }
+ }
+
+ /* Adjust warn for signed/unsigned integer warnings */
+ if (warn != 0)
+ warn = value->sign ? -1 : 1;
+
+ if (value->rel) {
+ /* If relative portion is not in bc section, don't try to handle it
+ * here. Otherwise get the relative portion's offset.
+ */
+ /*@dependent@*/ yasm_bytecode *rel_prevbc;
+ unsigned long dist;
+
+ sym_local = yasm_symrec_get_label(value->rel, &rel_prevbc);
+ if (value->wrt || value->seg_of || value->section_rel || !sym_local)
+ return 0; /* we can't handle SEG, WRT, or external symbols */
+ if (rel_prevbc->section != bc->section)
+ return 0; /* not in this section */
+ if (!value->curpos_rel)
+ return 0; /* not PC-relative */
+
+ /* Calculate value relative to current assembly position */
+ dist = yasm_bc_next_offset(rel_prevbc);
+ if (dist < bc->offset) {
+ outval = yasm_intnum_create_uint(bc->offset - dist);
+ yasm_intnum_calc(outval, YASM_EXPR_NEG, NULL);
+ } else {
+ dist -= bc->offset;
+ outval = yasm_intnum_create_uint(dist);
+ }
+
+ if (value->rshift > 0) {
+ /*@only@*/ yasm_intnum *shamt =
+ yasm_intnum_create_uint((unsigned long)value->rshift);
+ yasm_intnum_calc(outval, YASM_EXPR_SHR, shamt);
+ yasm_intnum_destroy(shamt);
+ }
+ /* Add in absolute portion */
+ if (intn)
+ yasm_intnum_calc(outval, YASM_EXPR_ADD, intn);
+ /* Output! */
+ if (yasm_arch_intnum_tobytes(arch, outval, buf, destsize, valsize, 0,
+ bc, warn))
+ retval = -1;
+ yasm_intnum_destroy(outval);
+ return retval;
+ }
+
+ if (value->seg_of || value->rshift || value->curpos_rel || value->ip_rel
+ || value->section_rel)
+ return 0; /* We can't handle this with just an absolute */
+
+ if (intn) {
+ /* Output just absolute portion */
+ if (yasm_arch_intnum_tobytes(arch, intn, buf, destsize, valsize, 0, bc,
+ warn))
+ retval = -1;
+ } else {
+ /* No absolute or relative portions: output 0 */
+ outval = yasm_intnum_create_uint(0);
+ if (yasm_arch_intnum_tobytes(arch, outval, buf, destsize, valsize, 0,
+ bc, warn))
+ retval = -1;
+ yasm_intnum_destroy(outval);
+ }
+ return retval;
+}
+
+void
+yasm_value_print(const yasm_value *value, FILE *f, int indent_level)
+{
+ fprintf(f, "%*s%u-bit, %ssigned", indent_level, "", value->size,
+ value->sign ? "" : "un");
+ fprintf(f, "%*sAbsolute portion=", indent_level, "");
+ yasm_expr_print(value->abs, f);
+ fprintf(f, "\n");
+ if (value->rel) {
+ fprintf(f, "%*sRelative to=%s%s\n", indent_level, "",
+ value->seg_of ? "SEG " : "",
+ yasm_symrec_get_name(value->rel));
+ if (value->wrt)
+ fprintf(f, "%*s(With respect to=%s)\n", indent_level, "",
+ yasm_symrec_get_name(value->wrt));
+ if (value->rshift > 0)
+ fprintf(f, "%*s(Right shifted by=%u)\n", indent_level, "",
+ value->rshift);
+ if (value->curpos_rel)
+ fprintf(f, "%*s(Relative to current position)\n", indent_level,
+ "");
+ if (value->ip_rel)
+ fprintf(f, "%*s(IP-relative)\n", indent_level, "");
+ if (value->jump_target)
+ fprintf(f, "%*s(Jump target)\n", indent_level, "");
+ if (value->section_rel)
+ fprintf(f, "%*s(Section-relative)\n", indent_level, "");
+ if (value->no_warn)
+ fprintf(f, "%*s(Overflow warnings disabled)\n", indent_level, "");
+ }
+}
diff --git a/contrib/tools/yasm/libyasm/value.h b/contrib/tools/yasm/libyasm/value.h
index 4dc294bcc3..8582bf1add 100644
--- a/contrib/tools/yasm/libyasm/value.h
+++ b/contrib/tools/yasm/libyasm/value.h
@@ -1,172 +1,172 @@
-/**
- * \file libyasm/value.h
- * \brief YASM value interface.
- *
- * \license
- * Copyright (C) 2006-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- * \endlicense
- */
-#ifndef YASM_VALUE_H
-#define YASM_VALUE_H
-
-#ifndef YASM_LIB_DECL
-#define YASM_LIB_DECL
-#endif
-
-/** Initialize a #yasm_value with just an expression. No processing is
- * performed, the expression is simply stuck into value.abs and the other
- * fields are initialized. Use yasm_expr_extract_value() to perform "smart"
- * processing into a #yasm_value. This function is intended for use during
- * parsing simply to ensure all fields of the value are initialized; after
- * the parse is complete, yasm_value_extract() should be called to finalize
- * the value. The value defaults to unsigned.
- * \param value value to be initialized
- * \param e expression (kept)
- * \param size value size (in bits)
- */
-YASM_LIB_DECL
-void yasm_value_initialize(/*@out@*/ yasm_value *value,
- /*@null@*/ /*@kept@*/ yasm_expr *e,
- unsigned int size);
-
-/** Initialize a #yasm_value with just a symrec. No processing is performed,
- * the symrec is simply stuck into value.rel and the other fields are
- * initialized.
- * \param value value to be initialized
- * \param sym symrec
- * \param size value size (in bits)
- */
-YASM_LIB_DECL
-void yasm_value_init_sym(/*@out@*/ yasm_value *value,
- /*@null@*/ yasm_symrec *sym, unsigned int size);
-
-/** Initialize a #yasm_value as a copy of another yasm_value. Any expressions
- * within orig are copied, so it's safe to delete the copy.
- * \param value value (copy to create)
- * \param orig original value
- */
-YASM_LIB_DECL
-void yasm_value_init_copy(yasm_value *value, const yasm_value *orig);
-
-/** Frees any memory inside value; does not free value itself.
- * \param value value
- */
-YASM_LIB_DECL
-void yasm_value_delete(yasm_value *value);
-
-/** Set a value to be relative to the current assembly position rather than
- * relative to the section start.
- * \param value value
- * \param bc bytecode containing value
- * \param ip_rel if nonzero, indicates IP-relative data relocation,
- * sometimes used to generate special relocations
- * \note If value is just an absolute value, will get an absolute symrec to
- * reference to (via bc's symbol table).
- */
-YASM_LIB_DECL
-void yasm_value_set_curpos_rel(yasm_value *value, yasm_bytecode *bc,
- unsigned int ip_rel);
-
-/** Perform yasm_value_finalize_expr() on a value that already exists from
- * being initialized with yasm_value_initialize().
- * \param value value
- * \param precbc previous bytecode to bytecode containing value
- * \return Nonzero if value could not be split.
- */
-YASM_LIB_DECL
-int yasm_value_finalize(yasm_value *value, /*@null@*/ yasm_bytecode *precbc);
-
-/** Break a #yasm_expr into a #yasm_value constituent parts. Extracts
- * the relative portion of the value, SEG and WRT portions, and top-level
- * right shift, if any. Places the remaining expr into the absolute
- * portion of the value. Essentially a combination of yasm_value_initialize()
- * and yasm_value_finalize(). First expands references to symrecs in
- * absolute sections by expanding with the absolute section start plus the
- * symrec offset within the absolute section.
- * \param value value to store split portions into
- * \param e expression input
- * \param precbc previous bytecode to bytecode containing expression
- * \param size value size (in bits)
- * \return Nonzero if the expr could not be split into a value for some
- * reason (e.g. the relative portion was not added, but multiplied,
- * etc).
- * \warning Do not use e after this call. Even if an error is returned, e
- * is stored into value.
- * \note This should only be called after the parse is complete. Calling
- * before the parse is complete will usually result in an error return.
- */
-YASM_LIB_DECL
-int yasm_value_finalize_expr(/*@out@*/ yasm_value *value,
- /*@null@*/ /*@kept@*/ yasm_expr *e,
- /*@null@*/ yasm_bytecode *precbc,
- unsigned int size);
-
-/** Get value if absolute or PC-relative section-local relative. Returns NULL
- * otherwise.
- * \param value value
- * \param bc current bytecode (for PC-relative calculation); if
- * NULL, NULL is returned for PC-relative values.
- * \param calc_bc_dist if nonzero, calculates bytecode distances in absolute
- * portion of value
- * \note Adds in value.rel (correctly) if PC-relative and in the same section
- * as bc (and there is no WRT or SEG).
- * \return Intnum if can be resolved to integer value, otherwise NULL.
- */
-YASM_LIB_DECL
-/*@null@*/ /*@only@*/ yasm_intnum *yasm_value_get_intnum
- (yasm_value *value, /*@null@*/ yasm_bytecode *bc, int calc_bc_dist);
-
-/** Output value if constant or PC-relative section-local. This should be
- * used from objfmt yasm_output_value_func() functions.
- * functions.
- * \param value value
- * \param buf buffer for byte representation
- * \param destsize destination size (in bytes)
- * \param bc current bytecode (usually passed into higher-level
- * calling function)
- * \param warn enables standard warnings: zero for none;
- * nonzero for overflow/underflow floating point and
- * integer warnings
- * \param arch architecture
- * \note Adds in value.rel (correctly) if PC-relative and in the same section
- * as bc (and there is no WRT or SEG); if this is not the desired
- * behavior, e.g. a reloc is needed in this case, don't use this
- * function!
- * \return 0 if no value output due to value needing relocation;
- * 1 if value output; -1 if error.
- */
-YASM_LIB_DECL
-int yasm_value_output_basic
- (yasm_value *value, /*@out@*/ unsigned char *buf, size_t destsize,
- yasm_bytecode *bc, int warn, yasm_arch *arch);
-
-/** Print a value. For debugging purposes.
- * \param value value
- * \param indent_level indentation level
- * \param f file
- */
-YASM_LIB_DECL
-void yasm_value_print(const yasm_value *value, FILE *f, int indent_level);
-
-#endif
+/**
+ * \file libyasm/value.h
+ * \brief YASM value interface.
+ *
+ * \license
+ * Copyright (C) 2006-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * \endlicense
+ */
+#ifndef YASM_VALUE_H
+#define YASM_VALUE_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/** Initialize a #yasm_value with just an expression. No processing is
+ * performed, the expression is simply stuck into value.abs and the other
+ * fields are initialized. Use yasm_expr_extract_value() to perform "smart"
+ * processing into a #yasm_value. This function is intended for use during
+ * parsing simply to ensure all fields of the value are initialized; after
+ * the parse is complete, yasm_value_extract() should be called to finalize
+ * the value. The value defaults to unsigned.
+ * \param value value to be initialized
+ * \param e expression (kept)
+ * \param size value size (in bits)
+ */
+YASM_LIB_DECL
+void yasm_value_initialize(/*@out@*/ yasm_value *value,
+ /*@null@*/ /*@kept@*/ yasm_expr *e,
+ unsigned int size);
+
+/** Initialize a #yasm_value with just a symrec. No processing is performed,
+ * the symrec is simply stuck into value.rel and the other fields are
+ * initialized.
+ * \param value value to be initialized
+ * \param sym symrec
+ * \param size value size (in bits)
+ */
+YASM_LIB_DECL
+void yasm_value_init_sym(/*@out@*/ yasm_value *value,
+ /*@null@*/ yasm_symrec *sym, unsigned int size);
+
+/** Initialize a #yasm_value as a copy of another yasm_value. Any expressions
+ * within orig are copied, so it's safe to delete the copy.
+ * \param value value (copy to create)
+ * \param orig original value
+ */
+YASM_LIB_DECL
+void yasm_value_init_copy(yasm_value *value, const yasm_value *orig);
+
+/** Frees any memory inside value; does not free value itself.
+ * \param value value
+ */
+YASM_LIB_DECL
+void yasm_value_delete(yasm_value *value);
+
+/** Set a value to be relative to the current assembly position rather than
+ * relative to the section start.
+ * \param value value
+ * \param bc bytecode containing value
+ * \param ip_rel if nonzero, indicates IP-relative data relocation,
+ * sometimes used to generate special relocations
+ * \note If value is just an absolute value, will get an absolute symrec to
+ * reference to (via bc's symbol table).
+ */
+YASM_LIB_DECL
+void yasm_value_set_curpos_rel(yasm_value *value, yasm_bytecode *bc,
+ unsigned int ip_rel);
+
+/** Perform yasm_value_finalize_expr() on a value that already exists from
+ * being initialized with yasm_value_initialize().
+ * \param value value
+ * \param precbc previous bytecode to bytecode containing value
+ * \return Nonzero if value could not be split.
+ */
+YASM_LIB_DECL
+int yasm_value_finalize(yasm_value *value, /*@null@*/ yasm_bytecode *precbc);
+
+/** Break a #yasm_expr into a #yasm_value constituent parts. Extracts
+ * the relative portion of the value, SEG and WRT portions, and top-level
+ * right shift, if any. Places the remaining expr into the absolute
+ * portion of the value. Essentially a combination of yasm_value_initialize()
+ * and yasm_value_finalize(). First expands references to symrecs in
+ * absolute sections by expanding with the absolute section start plus the
+ * symrec offset within the absolute section.
+ * \param value value to store split portions into
+ * \param e expression input
+ * \param precbc previous bytecode to bytecode containing expression
+ * \param size value size (in bits)
+ * \return Nonzero if the expr could not be split into a value for some
+ * reason (e.g. the relative portion was not added, but multiplied,
+ * etc).
+ * \warning Do not use e after this call. Even if an error is returned, e
+ * is stored into value.
+ * \note This should only be called after the parse is complete. Calling
+ * before the parse is complete will usually result in an error return.
+ */
+YASM_LIB_DECL
+int yasm_value_finalize_expr(/*@out@*/ yasm_value *value,
+ /*@null@*/ /*@kept@*/ yasm_expr *e,
+ /*@null@*/ yasm_bytecode *precbc,
+ unsigned int size);
+
+/** Get value if absolute or PC-relative section-local relative. Returns NULL
+ * otherwise.
+ * \param value value
+ * \param bc current bytecode (for PC-relative calculation); if
+ * NULL, NULL is returned for PC-relative values.
+ * \param calc_bc_dist if nonzero, calculates bytecode distances in absolute
+ * portion of value
+ * \note Adds in value.rel (correctly) if PC-relative and in the same section
+ * as bc (and there is no WRT or SEG).
+ * \return Intnum if can be resolved to integer value, otherwise NULL.
+ */
+YASM_LIB_DECL
+/*@null@*/ /*@only@*/ yasm_intnum *yasm_value_get_intnum
+ (yasm_value *value, /*@null@*/ yasm_bytecode *bc, int calc_bc_dist);
+
+/** Output value if constant or PC-relative section-local. This should be
+ * used from objfmt yasm_output_value_func() functions.
+ * functions.
+ * \param value value
+ * \param buf buffer for byte representation
+ * \param destsize destination size (in bytes)
+ * \param bc current bytecode (usually passed into higher-level
+ * calling function)
+ * \param warn enables standard warnings: zero for none;
+ * nonzero for overflow/underflow floating point and
+ * integer warnings
+ * \param arch architecture
+ * \note Adds in value.rel (correctly) if PC-relative and in the same section
+ * as bc (and there is no WRT or SEG); if this is not the desired
+ * behavior, e.g. a reloc is needed in this case, don't use this
+ * function!
+ * \return 0 if no value output due to value needing relocation;
+ * 1 if value output; -1 if error.
+ */
+YASM_LIB_DECL
+int yasm_value_output_basic
+ (yasm_value *value, /*@out@*/ unsigned char *buf, size_t destsize,
+ yasm_bytecode *bc, int warn, yasm_arch *arch);
+
+/** Print a value. For debugging purposes.
+ * \param value value
+ * \param indent_level indentation level
+ * \param f file
+ */
+YASM_LIB_DECL
+void yasm_value_print(const yasm_value *value, FILE *f, int indent_level);
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/xmalloc.c b/contrib/tools/yasm/libyasm/xmalloc.c
index 81b608c078..8931a42b30 100644
--- a/contrib/tools/yasm/libyasm/xmalloc.c
+++ b/contrib/tools/yasm/libyasm/xmalloc.c
@@ -1,114 +1,114 @@
-/*
- * Memory allocation routines with error checking. Idea from GNU libiberty.
- *
- * Copyright (C) 2001-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#include "util.h"
-
-#include "coretype.h"
-#include "errwarn.h"
-
-
-#ifdef WITH_DMALLOC
-#undef yasm_xmalloc
-#undef yasm_xcalloc
-#undef yasm_xrealloc
-#undef yasm_xfree
-#endif
-
-static /*@only@*/ /*@out@*/ void *def_xmalloc(size_t size);
-static /*@only@*/ void *def_xcalloc(size_t nelem, size_t elsize);
-static /*@only@*/ void *def_xrealloc
- (/*@only@*/ /*@out@*/ /*@returned@*/ /*@null@*/ void *oldmem, size_t size)
- /*@modifies oldmem@*/;
-static void def_xfree(/*@only@*/ /*@out@*/ /*@null@*/ void *p)
- /*@modifies p@*/;
-
-/* storage for global function pointers */
-YASM_LIB_DECL
-/*@only@*/ /*@out@*/ void * (*yasm_xmalloc) (size_t size) = def_xmalloc;
-YASM_LIB_DECL
-/*@only@*/ void * (*yasm_xcalloc) (size_t nelem, size_t elsize) = def_xcalloc;
-YASM_LIB_DECL
-/*@only@*/ void * (*yasm_xrealloc)
- (/*@only@*/ /*@out@*/ /*@returned@*/ /*@null@*/ void *oldmem, size_t size)
- /*@modifies oldmem@*/ = def_xrealloc;
-YASM_LIB_DECL
-void (*yasm_xfree) (/*@only@*/ /*@out@*/ /*@null@*/ void *p)
- /*@modifies p@*/ = def_xfree;
-
-
-static void *
-def_xmalloc(size_t size)
-{
- void *newmem;
-
- if (size == 0)
- size = 1;
- newmem = malloc(size);
- if (!newmem)
- yasm__fatal(N_("out of memory"));
-
- return newmem;
-}
-
-static void *
-def_xcalloc(size_t nelem, size_t elsize)
-{
- void *newmem;
-
- if (nelem == 0 || elsize == 0)
- nelem = elsize = 1;
-
- newmem = calloc(nelem, elsize);
- if (!newmem)
- yasm__fatal(N_("out of memory"));
-
- return newmem;
-}
-
-static void *
-def_xrealloc(void *oldmem, size_t size)
-{
- void *newmem;
-
- if (size == 0)
- size = 1;
- if (!oldmem)
- newmem = malloc(size);
- else
- newmem = realloc(oldmem, size);
- if (!newmem)
- yasm__fatal(N_("out of memory"));
-
- return newmem;
-}
-
-static void
-def_xfree(void *p)
-{
- if (!p)
- return;
- free(p);
-}
+/*
+ * Memory allocation routines with error checking. Idea from GNU libiberty.
+ *
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "util.h"
+
+#include "coretype.h"
+#include "errwarn.h"
+
+
+#ifdef WITH_DMALLOC
+#undef yasm_xmalloc
+#undef yasm_xcalloc
+#undef yasm_xrealloc
+#undef yasm_xfree
+#endif
+
+static /*@only@*/ /*@out@*/ void *def_xmalloc(size_t size);
+static /*@only@*/ void *def_xcalloc(size_t nelem, size_t elsize);
+static /*@only@*/ void *def_xrealloc
+ (/*@only@*/ /*@out@*/ /*@returned@*/ /*@null@*/ void *oldmem, size_t size)
+ /*@modifies oldmem@*/;
+static void def_xfree(/*@only@*/ /*@out@*/ /*@null@*/ void *p)
+ /*@modifies p@*/;
+
+/* storage for global function pointers */
+YASM_LIB_DECL
+/*@only@*/ /*@out@*/ void * (*yasm_xmalloc) (size_t size) = def_xmalloc;
+YASM_LIB_DECL
+/*@only@*/ void * (*yasm_xcalloc) (size_t nelem, size_t elsize) = def_xcalloc;
+YASM_LIB_DECL
+/*@only@*/ void * (*yasm_xrealloc)
+ (/*@only@*/ /*@out@*/ /*@returned@*/ /*@null@*/ void *oldmem, size_t size)
+ /*@modifies oldmem@*/ = def_xrealloc;
+YASM_LIB_DECL
+void (*yasm_xfree) (/*@only@*/ /*@out@*/ /*@null@*/ void *p)
+ /*@modifies p@*/ = def_xfree;
+
+
+static void *
+def_xmalloc(size_t size)
+{
+ void *newmem;
+
+ if (size == 0)
+ size = 1;
+ newmem = malloc(size);
+ if (!newmem)
+ yasm__fatal(N_("out of memory"));
+
+ return newmem;
+}
+
+static void *
+def_xcalloc(size_t nelem, size_t elsize)
+{
+ void *newmem;
+
+ if (nelem == 0 || elsize == 0)
+ nelem = elsize = 1;
+
+ newmem = calloc(nelem, elsize);
+ if (!newmem)
+ yasm__fatal(N_("out of memory"));
+
+ return newmem;
+}
+
+static void *
+def_xrealloc(void *oldmem, size_t size)
+{
+ void *newmem;
+
+ if (size == 0)
+ size = 1;
+ if (!oldmem)
+ newmem = malloc(size);
+ else
+ newmem = realloc(oldmem, size);
+ if (!newmem)
+ yasm__fatal(N_("out of memory"));
+
+ return newmem;
+}
+
+static void
+def_xfree(void *p)
+{
+ if (!p)
+ return;
+ free(p);
+}
diff --git a/contrib/tools/yasm/libyasm/xstrdup.c b/contrib/tools/yasm/libyasm/xstrdup.c
index b187704f0e..5932efcbdf 100644
--- a/contrib/tools/yasm/libyasm/xstrdup.c
+++ b/contrib/tools/yasm/libyasm/xstrdup.c
@@ -1,68 +1,68 @@
-/*
- * strdup() implementation with error checking (using xmalloc).
- *
- * Copyright (c) 1988, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include "util.h"
-
-#include "coretype.h"
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)strdup.c 8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
-
-
-#ifdef WITH_DMALLOC
-#undef yasm__xstrdup
-#endif
-
-char *
-yasm__xstrdup(const char *str)
-{
- size_t len;
- char *copy;
-
- len = strlen(str) + 1;
- copy = yasm_xmalloc(len);
- memcpy(copy, str, len);
- return (copy);
-}
-
-char *
-yasm__xstrndup(const char *str, size_t max)
-{
- size_t len = 0;
- char *copy;
-
- while (len < max && str[len] != '\0')
- len++;
- copy = yasm_xmalloc(len+1);
- memcpy(copy, str, len);
- copy[len] = '\0';
- return (copy);
-}
+/*
+ * strdup() implementation with error checking (using xmalloc).
+ *
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "util.h"
+
+#include "coretype.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strdup.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+
+#ifdef WITH_DMALLOC
+#undef yasm__xstrdup
+#endif
+
+char *
+yasm__xstrdup(const char *str)
+{
+ size_t len;
+ char *copy;
+
+ len = strlen(str) + 1;
+ copy = yasm_xmalloc(len);
+ memcpy(copy, str, len);
+ return (copy);
+}
+
+char *
+yasm__xstrndup(const char *str, size_t max)
+{
+ size_t len = 0;
+ char *copy;
+
+ while (len < max && str[len] != '\0')
+ len++;
+ copy = yasm_xmalloc(len+1);
+ memcpy(copy, str, len);
+ copy[len] = '\0';
+ return (copy);
+}