aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/tools/yasm/modules/parsers
diff options
context:
space:
mode:
authorsomov <somov@yandex-team.ru>2022-02-10 16:45:49 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:45:49 +0300
commit7489e4682331202b9c7d863c0898eb83d7b12c2b (patch)
tree9142afc54d335ea52910662635b898e79e192e49 /contrib/tools/yasm/modules/parsers
parenta5950576e397b1909261050b8c7da16db58f10b1 (diff)
downloadydb-7489e4682331202b9c7d863c0898eb83d7b12c2b.tar.gz
Restoring authorship annotation for <somov@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/tools/yasm/modules/parsers')
-rw-r--r--contrib/tools/yasm/modules/parsers/gas/gas-parse-intel.c180
-rw-r--r--contrib/tools/yasm/modules/parsers/gas/gas-parse.c3532
-rw-r--r--contrib/tools/yasm/modules/parsers/gas/gas-parser.c266
-rw-r--r--contrib/tools/yasm/modules/parsers/gas/gas-parser.h326
-rw-r--r--contrib/tools/yasm/modules/parsers/nasm/nasm-parse.c3360
-rw-r--r--contrib/tools/yasm/modules/parsers/nasm/nasm-parser-struct.h170
-rw-r--r--contrib/tools/yasm/modules/parsers/nasm/nasm-parser.c280
-rw-r--r--contrib/tools/yasm/modules/parsers/nasm/nasm-parser.h246
8 files changed, 4180 insertions, 4180 deletions
diff --git a/contrib/tools/yasm/modules/parsers/gas/gas-parse-intel.c b/contrib/tools/yasm/modules/parsers/gas/gas-parse-intel.c
index 170b0f96c2..9d412fc7d3 100644
--- a/contrib/tools/yasm/modules/parsers/gas/gas-parse-intel.c
+++ b/contrib/tools/yasm/modules/parsers/gas/gas-parse-intel.c
@@ -1,90 +1,90 @@
-/*
- * GAS-compatible parser Intel syntax support
- *
- * Copyright (C) 2010 Alexei Svitkine
- *
- * 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 author nor the names of other contributors
- * may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * 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>
-
-#include "modules/parsers/gas/gas-parser.h"
-#include "modules/parsers/nasm/nasm-parser-struct.h"
-
-extern yasm_bytecode *gas_intel_syntax_parse_instr(yasm_parser_nasm *parser_nasm, unsigned char *instr);
-
-#define SET_FIELDS(to, from) \
- (to)->object = (from)->object; \
- (to)->locallabel_base = (from)->locallabel_base; \
- (to)->locallabel_base_len = (from)->locallabel_base_len; \
- (to)->preproc = (from)->preproc; \
- (to)->errwarns = (from)->errwarns; \
- (to)->linemap = (from)->linemap; \
- (to)->prev_bc = (from)->prev_bc;
-
-yasm_bytecode *parse_instr_intel(yasm_parser_gas *parser_gas)
-{
- char *stok, *slim;
- unsigned char *line;
- size_t length;
-
- yasm_parser_nasm parser_nasm;
- yasm_bytecode *bc;
-
- memset(&parser_nasm, 0, sizeof(parser_nasm));
-
- yasm_arch_set_var(parser_gas->object->arch, "gas_intel_mode", 1);
- SET_FIELDS(&parser_nasm, parser_gas);
- parser_nasm.masm = 1;
-
- stok = (char *) parser_gas->s.tok;
- slim = (char *) parser_gas->s.lim;
- length = 0;
- while (&stok[length] < slim && stok[length] != '\n') {
- length++;
- }
-
- if (&stok[length] == slim && parser_gas->line) {
- line = yasm_xmalloc(length + parser_gas->lineleft + 1);
- memcpy(line, parser_gas->s.tok, length);
- memcpy(line + length, parser_gas->linepos, parser_gas->lineleft);
- length += parser_gas->lineleft;
- if (line[length - 1] == '\n') length--;
- } else {
- line = yasm_xmalloc(length + 1);
- memcpy(line, parser_gas->s.tok, length);
- }
- line[length] = '\0';
-
- bc = gas_intel_syntax_parse_instr(&parser_nasm, line);
-
- SET_FIELDS(parser_gas, &parser_nasm);
- yasm_arch_set_var(parser_gas->object->arch, "gas_intel_mode", 0);
-
- yasm_xfree(line);
-
- return bc;
-}
+/*
+ * GAS-compatible parser Intel syntax support
+ *
+ * Copyright (C) 2010 Alexei Svitkine
+ *
+ * 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 author nor the names of other contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 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>
+
+#include "modules/parsers/gas/gas-parser.h"
+#include "modules/parsers/nasm/nasm-parser-struct.h"
+
+extern yasm_bytecode *gas_intel_syntax_parse_instr(yasm_parser_nasm *parser_nasm, unsigned char *instr);
+
+#define SET_FIELDS(to, from) \
+ (to)->object = (from)->object; \
+ (to)->locallabel_base = (from)->locallabel_base; \
+ (to)->locallabel_base_len = (from)->locallabel_base_len; \
+ (to)->preproc = (from)->preproc; \
+ (to)->errwarns = (from)->errwarns; \
+ (to)->linemap = (from)->linemap; \
+ (to)->prev_bc = (from)->prev_bc;
+
+yasm_bytecode *parse_instr_intel(yasm_parser_gas *parser_gas)
+{
+ char *stok, *slim;
+ unsigned char *line;
+ size_t length;
+
+ yasm_parser_nasm parser_nasm;
+ yasm_bytecode *bc;
+
+ memset(&parser_nasm, 0, sizeof(parser_nasm));
+
+ yasm_arch_set_var(parser_gas->object->arch, "gas_intel_mode", 1);
+ SET_FIELDS(&parser_nasm, parser_gas);
+ parser_nasm.masm = 1;
+
+ stok = (char *) parser_gas->s.tok;
+ slim = (char *) parser_gas->s.lim;
+ length = 0;
+ while (&stok[length] < slim && stok[length] != '\n') {
+ length++;
+ }
+
+ if (&stok[length] == slim && parser_gas->line) {
+ line = yasm_xmalloc(length + parser_gas->lineleft + 1);
+ memcpy(line, parser_gas->s.tok, length);
+ memcpy(line + length, parser_gas->linepos, parser_gas->lineleft);
+ length += parser_gas->lineleft;
+ if (line[length - 1] == '\n') length--;
+ } else {
+ line = yasm_xmalloc(length + 1);
+ memcpy(line, parser_gas->s.tok, length);
+ }
+ line[length] = '\0';
+
+ bc = gas_intel_syntax_parse_instr(&parser_nasm, line);
+
+ SET_FIELDS(parser_gas, &parser_nasm);
+ yasm_arch_set_var(parser_gas->object->arch, "gas_intel_mode", 0);
+
+ yasm_xfree(line);
+
+ return bc;
+}
diff --git a/contrib/tools/yasm/modules/parsers/gas/gas-parse.c b/contrib/tools/yasm/modules/parsers/gas/gas-parse.c
index 5331c3ff66..14c86a70f4 100644
--- a/contrib/tools/yasm/modules/parsers/gas/gas-parse.c
+++ b/contrib/tools/yasm/modules/parsers/gas/gas-parse.c
@@ -1,1766 +1,1766 @@
-/*
- * GAS-compatible parser
- *
- * 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.
- * 3. Neither the name of the author nor the names of other contributors
- * may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * 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>
-
-#include <ctype.h>
-#include <limits.h>
-#include <math.h>
-
-#include "modules/parsers/gas/gas-parser.h"
-
-typedef struct dir_lookup {
- const char *name;
- yasm_bytecode * (*handler) (yasm_parser_gas *, unsigned int);
- unsigned int param;
- enum gas_parser_state newstate;
-} dir_lookup;
-
-static void cpp_line_marker(yasm_parser_gas *parser_gas);
-static void nasm_line_marker(yasm_parser_gas *parser_gas);
-static yasm_bytecode *parse_instr(yasm_parser_gas *parser_gas);
-static int parse_dirvals(yasm_parser_gas *parser_gas, yasm_valparamhead *vps);
-static int parse_datavals(yasm_parser_gas *parser_gas, yasm_datavalhead *dvs);
-static int parse_strvals(yasm_parser_gas *parser_gas, yasm_datavalhead *dvs);
-static yasm_effaddr *parse_memaddr(yasm_parser_gas *parser_gas);
-static yasm_insn_operand *parse_operand(yasm_parser_gas *parser_gas);
-static yasm_expr *parse_expr(yasm_parser_gas *parser_gas);
-static yasm_expr *parse_expr0(yasm_parser_gas *parser_gas);
-static yasm_expr *parse_expr1(yasm_parser_gas *parser_gas);
-static yasm_expr *parse_expr2(yasm_parser_gas *parser_gas);
-
-static void define_label(yasm_parser_gas *parser_gas, char *name, int local);
-static void define_lcomm(yasm_parser_gas *parser_gas, /*@only@*/ char *name,
- yasm_expr *size, /*@null@*/ yasm_expr *align);
-static yasm_section *gas_get_section
- (yasm_parser_gas *parser_gas, /*@only@*/ char *name, /*@null@*/ char *flags,
- /*@null@*/ char *type, /*@null@*/ yasm_valparamhead *objext_valparams,
- int builtin);
-static void gas_switch_section
- (yasm_parser_gas *parser_gas, /*@only@*/ const char *name,
- /*@null@*/ char *flags, /*@null@*/ char *type,
- /*@null@*/ yasm_valparamhead *objext_valparams, int builtin);
-static yasm_bytecode *gas_parser_align
- (yasm_parser_gas *parser_gas, yasm_section *sect, yasm_expr *boundval,
- /*@null@*/ yasm_expr *fillval, /*@null@*/ yasm_expr *maxskipval,
- int power2);
-static yasm_bytecode *gas_parser_dir_fill
- (yasm_parser_gas *parser_gas, /*@only@*/ yasm_expr *repeat,
- /*@only@*/ /*@null@*/ yasm_expr *size,
- /*@only@*/ /*@null@*/ yasm_expr *value);
-
-#define is_eol_tok(tok) ((tok) == '\n' || (tok) == ';' || (tok) == 0)
-#define is_eol() is_eol_tok(curtok)
-
-#define get_next_token() (curtok = gas_parser_lex(&curval, parser_gas))
-
-static void
-get_peek_token(yasm_parser_gas *parser_gas)
-{
- char savech = parser_gas->tokch;
- if (parser_gas->peek_token != NONE)
- yasm_internal_error(N_("can only have one token of lookahead"));
- parser_gas->peek_token =
- gas_parser_lex(&parser_gas->peek_tokval, parser_gas);
- parser_gas->peek_tokch = parser_gas->tokch;
- parser_gas->tokch = savech;
-}
-
-static void
-destroy_curtok_(yasm_parser_gas *parser_gas)
-{
- if (curtok < 256)
- ;
- else switch ((enum tokentype)curtok) {
- case INTNUM:
- yasm_intnum_destroy(curval.intn);
- break;
- case FLTNUM:
- yasm_floatnum_destroy(curval.flt);
- break;
- case ID:
- case LABEL:
- case STRING:
- yasm_xfree(curval.str.contents);
- break;
- default:
- break;
- }
- curtok = NONE; /* sanity */
-}
-#define destroy_curtok() destroy_curtok_(parser_gas)
-
-/* Eat all remaining tokens to EOL, discarding all of them. If there's any
- * intervening tokens, generates an error (junk at end of line).
- */
-static void
-demand_eol_(yasm_parser_gas *parser_gas)
-{
- if (is_eol())
- return;
-
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("junk at end of line, first unrecognized character is `%c'"),
- parser_gas->tokch);
-
- do {
- destroy_curtok();
- get_next_token();
- } while (!is_eol());
-}
-#define demand_eol() demand_eol_(parser_gas)
-
-static int
-expect_(yasm_parser_gas *parser_gas, int token)
-{
- static char strch[] = "` '";
- const char *str;
-
- if (curtok == token)
- return 1;
-
- switch (token) {
- case INTNUM: str = "integer"; break;
- case FLTNUM: str = "floating point value"; break;
- case STRING: str = "string"; break;
- case REG: str = "register"; break;
- case REGGROUP: str = "register group"; break;
- case SEGREG: str = "segment register"; break;
- case TARGETMOD: str = "target modifier"; break;
- case LEFT_OP: str = "<<"; break;
- case RIGHT_OP: str = ">>"; break;
- case ID: str = "identifier"; break;
- case LABEL: str = "label"; break;
- default:
- strch[1] = token;
- str = strch;
- break;
- }
- yasm_error_set(YASM_ERROR_PARSE, "expected %s", str);
- destroy_curtok();
- return 0;
-}
-#define expect(token) expect_(parser_gas, token)
-
-static yasm_bytecode *
-parse_line(yasm_parser_gas *parser_gas)
-{
- yasm_bytecode *bc;
- yasm_expr *e;
- yasm_valparamhead vps;
- char *id;
- const dir_lookup *dir;
-
- if (is_eol())
- return NULL;
-
- bc = parse_instr(parser_gas);
- if (bc)
- return bc;
-
- switch (curtok) {
- case ID:
- id = ID_val;
-
- /* See if it's a gas-specific directive */
- dir = (const dir_lookup *)HAMT_search(parser_gas->dirs, id);
- if (dir) {
- parser_gas->state = dir->newstate;
- get_next_token(); /* ID */
- return dir->handler(parser_gas, dir->param);
- }
-
- get_next_token(); /* ID */
- if (curtok == ':') {
- /* Label */
- parser_gas->state = INITIAL;
- get_next_token(); /* : */
- define_label(parser_gas, id, 0);
- return parse_line(parser_gas);
- } else if (curtok == '=') {
- /* EQU */
- /* TODO: allow redefinition, assigning to . (same as .org) */
- parser_gas->state = INITIAL;
- get_next_token(); /* = */
- e = parse_expr(parser_gas);
- if (e)
- yasm_symtab_define_equ(p_symtab, id, e, cur_line);
- else
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expression expected after `%s'"), "=");
- yasm_xfree(id);
- return NULL;
- }
-
- /* possibly a directive; try to parse it */
- parse_dirvals(parser_gas, &vps);
- if (!yasm_object_directive(p_object, id, "gas", &vps, NULL,
- cur_line)) {
- yasm_vps_delete(&vps);
- yasm_xfree(id);
- return NULL;
- }
- yasm_vps_delete(&vps);
- if (id[0] == '.')
- yasm_warn_set(YASM_WARN_GENERAL,
- N_("directive `%s' not recognized"), id);
- else
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("instruction not recognized: `%s'"), id);
- yasm_xfree(id);
- return NULL;
- case LABEL:
- define_label(parser_gas, LABEL_val, 0);
- get_next_token(); /* LABEL */
- return parse_line(parser_gas);
- case CPP_LINE_MARKER:
- get_next_token();
- cpp_line_marker(parser_gas);
- return NULL;
- case NASM_LINE_MARKER:
- get_next_token();
- nasm_line_marker(parser_gas);
- return NULL;
- default:
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("label or instruction expected at start of line"));
- return NULL;
- }
-}
-
-/*
- Handle line markers generated by cpp.
-
- We expect a positive integer (line) followed by a string (filename). If we
- fail to find either of these, we treat the line as a comment. There is a
- possibility of false positives (mistaking a comment for a line marker, when
- the comment is not intended as a line marker) but this cannot be avoided
- without adding a filter to the input before passing it to cpp.
-
- This function is only called if the preprocessor was 'cpp', since the
- CPP_LINE_MARKER token isn't generated for any other preprocessor. With any
- other preprocessor, anything after a '#' is always treated as a comment.
-*/
-static void
-cpp_line_marker(yasm_parser_gas *parser_gas)
-{
- yasm_valparamhead vps;
- yasm_valparam *vp;
- unsigned long line;
- char *filename;
-
- /* Line number. */
- if (curtok != INTNUM) {
- /* Skip over a comment. */
- while (curtok != '\n')
- get_next_token();
-
- return;
- }
-
- if (yasm_intnum_sign(INTNUM_val) < 0) {
- get_next_token(); /* INTNUM */
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("line number is negative"));
- return;
- }
-
- line = yasm_intnum_get_uint(INTNUM_val);
-
- /*
- Set to (line - 1) since the directive indicates that the *next* line
- will have the number given.
-
- cpp should never produce line=0, but the if keeps us safe just incase.
- */
- if (line != 0)
- line--;
-
- yasm_intnum_destroy(INTNUM_val);
- get_next_token(); /* INTNUM */
-
- /* File name, in quotes. */
- if (curtok != STRING) {
- /* Skip over a comment. */
- while (curtok != '\n')
- get_next_token();
-
- return;
- }
-
- filename = STRING_val.contents;
- get_next_token();
-
- /* Set linemap. */
- yasm_linemap_set(parser_gas->linemap, filename, 0, line, 1);
-
- /*
- The first line marker in the file (which should be on the first line
- of the file) will give us the name of the source file. This information
- needs to be passed on to the debug format module.
- */
- if (parser_gas->seen_line_marker == 0) {
- parser_gas->seen_line_marker = 1;
-
- yasm_vps_initialize(&vps);
- vp = yasm_vp_create_string(NULL, filename);
- yasm_vps_append(&vps, vp);
-
- yasm_object_directive(p_object, ".file", "gas", &vps, NULL, cur_line);
-
- yasm_vps_delete(&vps);
- } else
- yasm_xfree(filename);
-
- /* Skip flags. */
- while (1) {
- switch (curtok) {
- case INTNUM:
- break;
-
- case '\n':
- return;
-
- default:
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("junk at end of cpp line marker"));
- return;
- }
- get_next_token();
- }
-}
-
-/*
- Handle line markers generated by the nasm preproc.
-
- We expect a positive integer (line) followed by a plus sign, followed by
- another positive integer, followed by a string (filename).
-
- This function is only called if the preprocessor was 'nasm', since the
- NASM_LINE_MARKER token isn't generated for any other preprocessor.
-*/
-static void
-nasm_line_marker(yasm_parser_gas *parser_gas)
-{
- yasm_valparamhead vps;
- yasm_valparam *vp;
- unsigned long line, incr;
- char *filename;
-
- /* Line number. */
- if (!expect(INTNUM)) return;
-
- if (yasm_intnum_sign(INTNUM_val) < 0) {
- get_next_token(); /* INTNUM */
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("line number is negative"));
- return;
- }
-
- line = yasm_intnum_get_uint(INTNUM_val);
-
- /*
- Set to (line - 1) since the directive indicates that the *next* line
- will have the number given.
-
- cpp should never produce line=0, but the if keeps us safe just incase.
- */
- if (line != 0)
- line--;
-
- yasm_intnum_destroy(INTNUM_val);
- get_next_token(); /* INTNUM */
-
- if (!expect('+')) return;
- get_next_token(); /* + */
-
- /* Line number increment. */
- if (!expect(INTNUM)) return;
-
- if (yasm_intnum_sign(INTNUM_val) < 0) {
- get_next_token(); /* INTNUM */
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("line increment is negative"));
- return;
- }
-
- incr = yasm_intnum_get_uint(INTNUM_val);
- yasm_intnum_destroy(INTNUM_val);
-
- /* File name is not in quotes, so need to switch to a different tokenizer
- * state.
- */
- parser_gas->state = NASM_FILENAME;
- get_next_token(); /* INTNUM */
- if (!expect(STRING)) {
- parser_gas->state = INITIAL;
- return;
- }
-
- filename = STRING_val.contents;
-
- /* Set linemap. */
- yasm_linemap_set(parser_gas->linemap, filename, 0, line, incr);
-
- /*
- The first line marker in the file (which should be on the first line
- of the file) will give us the name of the source file. This information
- needs to be passed on to the debug format module.
- */
- if (parser_gas->seen_line_marker == 0) {
- parser_gas->seen_line_marker = 1;
-
- yasm_vps_initialize(&vps);
- vp = yasm_vp_create_string(NULL, filename);
- yasm_vps_append(&vps, vp);
-
- yasm_object_directive(p_object, ".file", "gas", &vps, NULL, cur_line);
-
- yasm_vps_delete(&vps);
- } else
- yasm_xfree(filename);
-
- /* We need to poke back on the \n that was consumed by the tokenizer */
- parser_gas->peek_token = '\n';
- get_next_token();
-}
-
-/* Line directive */
-static yasm_bytecode *
-dir_line(yasm_parser_gas *parser_gas, unsigned int param)
-{
- if (!expect(INTNUM)) return NULL;
- if (yasm_intnum_sign(INTNUM_val) < 0) {
- get_next_token(); /* INTNUM */
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("line number is negative"));
- return NULL;
- }
-
- parser_gas->dir_line = yasm_intnum_get_uint(INTNUM_val);
- yasm_intnum_destroy(INTNUM_val);
- get_next_token(); /* INTNUM */
-
- if (parser_gas->dir_fileline == 3) {
- /* Have both file and line */
- yasm_linemap_set(parser_gas->linemap, NULL, 0,
- parser_gas->dir_line, 1);
- } else if (parser_gas->dir_fileline == 1) {
- /* Had previous file directive only */
- parser_gas->dir_fileline = 3;
- yasm_linemap_set(parser_gas->linemap, parser_gas->dir_file, 0,
- parser_gas->dir_line, 1);
- } else {
- /* Didn't see file yet */
- parser_gas->dir_fileline = 2;
- }
- return NULL;
-}
-
-/* Alignment directives */
-
-static yasm_bytecode *
-dir_align(yasm_parser_gas *parser_gas, unsigned int param)
-{
- yasm_expr *bound, *fill=NULL, *maxskip=NULL;
-
- bound = parse_expr(parser_gas);
- if (!bound) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_(".align directive must specify alignment"));
- return NULL;
- }
-
- if (curtok == ',') {
- get_next_token(); /* ',' */
- fill = parse_expr(parser_gas);
- if (curtok == ',') {
- get_next_token(); /* ',' */
- maxskip = parse_expr(parser_gas);
- }
- }
-
- return gas_parser_align(parser_gas, cursect, bound, fill, maxskip,
- (int)param);
-}
-
-static yasm_bytecode *
-dir_org(yasm_parser_gas *parser_gas, unsigned int param)
-{
- yasm_intnum *start, *value=NULL;
- yasm_bytecode *bc;
-
- /* TODO: support expr instead of intnum */
- if (!expect(INTNUM)) return NULL;
- start = INTNUM_val;
- get_next_token(); /* INTNUM */
-
- if (curtok == ',') {
- get_next_token(); /* ',' */
- /* TODO: support expr instead of intnum */
- if (!expect(INTNUM)) return NULL;
- value = INTNUM_val;
- get_next_token(); /* INTNUM */
- }
- if (value) {
- bc = yasm_bc_create_org(yasm_intnum_get_uint(start),
- yasm_intnum_get_uint(value), cur_line);
- yasm_intnum_destroy(value);
- } else
- bc = yasm_bc_create_org(yasm_intnum_get_uint(start), 0,
- cur_line);
- yasm_intnum_destroy(start);
- return bc;
-}
-
-/* Data visibility directives */
-
-static yasm_bytecode *
-dir_local(yasm_parser_gas *parser_gas, unsigned int param)
-{
- if (!expect(ID)) return NULL;
- yasm_symtab_declare(p_symtab, ID_val, YASM_SYM_DLOCAL, cur_line);
- yasm_xfree(ID_val);
- get_next_token(); /* ID */
- return NULL;
-}
-
-static yasm_bytecode *
-dir_comm(yasm_parser_gas *parser_gas, unsigned int is_lcomm)
-{
- yasm_expr *align = NULL;
- /*@null@*/ /*@dependent@*/ yasm_symrec *sym;
- char *id;
- yasm_expr *e;
-
- if (!expect(ID)) return NULL;
- id = ID_val;
- get_next_token(); /* ID */
- if (!expect(',')) {
- yasm_xfree(id);
- return NULL;
- }
- get_next_token(); /* , */
- e = parse_expr(parser_gas);
- if (!e) {
- yasm_error_set(YASM_ERROR_SYNTAX, N_("size expected for `%s'"),
- ".COMM");
- return NULL;
- }
- if (curtok == ',') {
- /* Optional alignment expression */
- get_next_token(); /* ',' */
- align = parse_expr(parser_gas);
- }
- /* If already explicitly declared local, treat like LCOMM */
- if (is_lcomm
- || ((sym = yasm_symtab_get(p_symtab, id))
- && yasm_symrec_get_visibility(sym) == YASM_SYM_DLOCAL)) {
- define_lcomm(parser_gas, id, e, align);
- } else if (align) {
- /* Give third parameter as objext valparam */
- yasm_valparamhead *extvps = yasm_vps_create();
- yasm_valparam *vp = yasm_vp_create_expr(NULL, align);
- yasm_vps_append(extvps, vp);
-
- sym = yasm_symtab_declare(p_symtab, id, YASM_SYM_COMMON,
- cur_line);
- yasm_symrec_set_common_size(sym, e);
- yasm_symrec_set_objext_valparams(sym, extvps);
-
- yasm_xfree(id);
- } else {
- sym = yasm_symtab_declare(p_symtab, id, YASM_SYM_COMMON,
- cur_line);
- yasm_symrec_set_common_size(sym, e);
- yasm_xfree(id);
- }
- return NULL;
-}
-
-/* Integer data definition directives */
-
-static yasm_bytecode *
-dir_ascii(yasm_parser_gas *parser_gas, unsigned int withzero)
-{
- yasm_datavalhead dvs;
- if (!parse_strvals(parser_gas, &dvs))
- return NULL;
- return yasm_bc_create_data(&dvs, 1, (int)withzero, p_object->arch,
- cur_line);
-}
-
-static yasm_bytecode *
-dir_data(yasm_parser_gas *parser_gas, unsigned int size)
-{
- yasm_datavalhead dvs;
- if (!parse_datavals(parser_gas, &dvs))
- return NULL;
- return yasm_bc_create_data(&dvs, size, 0, p_object->arch, cur_line);
-}
-
-static yasm_bytecode *
-dir_leb128(yasm_parser_gas *parser_gas, unsigned int sign)
-{
- yasm_datavalhead dvs;
- if (!parse_datavals(parser_gas, &dvs))
- return NULL;
- return yasm_bc_create_leb128(&dvs, (int)sign, cur_line);
-}
-
-/* Empty space / fill data definition directives */
-
-static yasm_bytecode *
-dir_zero(yasm_parser_gas *parser_gas, unsigned int param)
-{
- yasm_bytecode *bc;
- yasm_datavalhead dvs;
- yasm_expr *e = parse_expr(parser_gas);
- if (!e) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expression expected after `%s'"), ".ZERO");
- return NULL;
- }
-
- yasm_dvs_initialize(&dvs);
- yasm_dvs_append(&dvs, yasm_dv_create_expr(
- p_expr_new_ident(yasm_expr_int(yasm_intnum_create_uint(0)))));
- bc = yasm_bc_create_data(&dvs, 1, 0, p_object->arch, cur_line);
- yasm_bc_set_multiple(bc, e);
- return bc;
-}
-
-static yasm_bytecode *
-dir_skip(yasm_parser_gas *parser_gas, unsigned int param)
-{
- yasm_expr *e, *e_val;
- yasm_bytecode *bc;
- yasm_datavalhead dvs;
-
- e = parse_expr(parser_gas);
- if (!e) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expression expected after `%s'"), ".SKIP");
- return NULL;
- }
- if (curtok != ',')
- return yasm_bc_create_reserve(e, 1, cur_line);
- get_next_token(); /* ',' */
- e_val = parse_expr(parser_gas);
- yasm_dvs_initialize(&dvs);
- yasm_dvs_append(&dvs, yasm_dv_create_expr(e_val));
- bc = yasm_bc_create_data(&dvs, 1, 0, p_object->arch, cur_line);
-
- yasm_bc_set_multiple(bc, e);
- return bc;
-}
-
-/* fill data definition directive */
-static yasm_bytecode *
-dir_fill(yasm_parser_gas *parser_gas, unsigned int param)
-{
- yasm_expr *sz=NULL, *val=NULL;
- yasm_expr *e = parse_expr(parser_gas);
- if (!e) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expression expected after `%s'"), ".FILL");
- return NULL;
- }
- if (curtok == ',') {
- get_next_token(); /* ',' */
- sz = parse_expr(parser_gas);
- if (curtok == ',') {
- get_next_token(); /* ',' */
- val = parse_expr(parser_gas);
- }
- }
- return gas_parser_dir_fill(parser_gas, e, sz, val);
-}
-
-/* Section directives */
-
-static yasm_bytecode *
-dir_bss_section(yasm_parser_gas *parser_gas, unsigned int param)
-{
- gas_switch_section(parser_gas, ".bss", NULL, NULL, NULL, 1);
- return NULL;
-}
-
-static yasm_bytecode *
-dir_data_section(yasm_parser_gas *parser_gas, unsigned int param)
-{
- gas_switch_section(parser_gas, ".data", NULL, NULL, NULL, 1);
- return NULL;
-}
-
-static yasm_bytecode *
-dir_text_section(yasm_parser_gas *parser_gas, unsigned int param)
-{
- gas_switch_section(parser_gas, ".text", NULL, NULL, NULL, 1);
- return NULL;
-}
-
-static yasm_bytecode *
-dir_section(yasm_parser_gas *parser_gas, unsigned int param)
-{
- /* DIR_SECTION ID ',' STRING ',' '@' ID ',' dirvals */
- char *sectname, *flags = NULL, *type = NULL;
- yasm_valparamhead vps;
- int have_vps = 0;
-
- if (!expect(ID)) return NULL;
- sectname = ID_val;
- get_next_token(); /* ID */
-
- if (curtok == ',') {
- get_next_token(); /* ',' */
- if (!expect(STRING)) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("flag string expected"));
- yasm_xfree(sectname);
- return NULL;
- }
- flags = STRING_val.contents;
- get_next_token(); /* STRING */
- }
-
- if (curtok == ',') {
- get_next_token(); /* ',' */
- if (!expect('@')) {
- yasm_xfree(sectname);
- yasm_xfree(flags);
- return NULL;
- }
- get_next_token(); /* '@' */
- if (!expect(ID)) {
- yasm_xfree(sectname);
- yasm_xfree(flags);
- return NULL;
- }
- type = ID_val;
- get_next_token(); /* ID */
- }
-
- if (curtok == ',') {
- get_next_token(); /* ',' */
- if (parse_dirvals(parser_gas, &vps))
- have_vps = 1;
- }
-
- gas_switch_section(parser_gas, sectname, flags, type,
- have_vps ? &vps : NULL, 0);
- yasm_xfree(sectname);
- yasm_xfree(flags);
- return NULL;
-}
-
-/* Other directives */
-
-static yasm_bytecode *
-dir_equ(yasm_parser_gas *parser_gas, unsigned int param)
-{
- yasm_expr *e;
- char *id;
-
- /* ID ',' expr */
- if (!expect(ID)) return NULL;
- id = ID_val;
- get_next_token(); /* ID */
- if (!expect(',')) {
- yasm_xfree(id);
- return NULL;
- }
- get_next_token(); /* ',' */
- e = parse_expr(parser_gas);
- if (e)
- yasm_symtab_define_equ(p_symtab, id, e, cur_line);
- else
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expression expected after `%s'"), ",");
- yasm_xfree(id);
- return NULL;
-}
-
-static yasm_bytecode *
-dir_file(yasm_parser_gas *parser_gas, unsigned int param)
-{
- yasm_valparamhead vps;
- yasm_valparam *vp;
-
- if (curtok == STRING) {
- /* No file number; this form also sets the assembler's
- * internal line number.
- */
- char *filename = STRING_val.contents;
-
- get_next_token(); /* STRING */
- if (parser_gas->dir_fileline == 3) {
- /* Have both file and line */
- const char *old_fn;
- unsigned long old_line;
-
- yasm_linemap_lookup(parser_gas->linemap, cur_line, &old_fn,
- &old_line);
- yasm_linemap_set(parser_gas->linemap, filename, 0, old_line,
- 1);
- } else if (parser_gas->dir_fileline == 2) {
- /* Had previous line directive only */
- parser_gas->dir_fileline = 3;
- yasm_linemap_set(parser_gas->linemap, filename, 0,
- parser_gas->dir_line, 1);
- } else {
- /* Didn't see line yet, save file */
- parser_gas->dir_fileline = 1;
- if (parser_gas->dir_file)
- yasm_xfree(parser_gas->dir_file);
- parser_gas->dir_file = yasm__xstrdup(filename);
- }
-
- /* Pass change along to debug format */
- yasm_vps_initialize(&vps);
- vp = yasm_vp_create_string(NULL, filename);
- yasm_vps_append(&vps, vp);
-
- yasm_object_directive(p_object, ".file", "gas", &vps, NULL,
- cur_line);
-
- yasm_vps_delete(&vps);
- return NULL;
- }
-
- /* fileno filename form */
- yasm_vps_initialize(&vps);
-
- if (!expect(INTNUM)) return NULL;
- vp = yasm_vp_create_expr(NULL,
- p_expr_new_ident(yasm_expr_int(INTNUM_val)));
- yasm_vps_append(&vps, vp);
- get_next_token(); /* INTNUM */
-
- if (!expect(STRING)) {
- yasm_vps_delete(&vps);
- return NULL;
- }
- vp = yasm_vp_create_string(NULL, STRING_val.contents);
- yasm_vps_append(&vps, vp);
- get_next_token(); /* STRING */
-
- yasm_object_directive(p_object, ".file", "gas", &vps, NULL,
- cur_line);
-
- yasm_vps_delete(&vps);
- return NULL;
-}
-
-
-static yasm_bytecode *
-dir_intel_syntax(yasm_parser_gas *parser_gas, unsigned int param)
-{
- parser_gas->intel_syntax = 1;
-
- do {
- destroy_curtok();
- get_next_token();
- } while (!is_eol());
- return NULL;
-}
-
-static yasm_bytecode *
-dir_att_syntax(yasm_parser_gas *parser_gas, unsigned int param)
-{
- parser_gas->intel_syntax = 0;
- return NULL;
-}
-
-static yasm_bytecode *
-parse_instr(yasm_parser_gas *parser_gas)
-{
- yasm_bytecode *bc;
- char *id;
- uintptr_t prefix;
-
- if (parser_gas->intel_syntax) {
- bc = parse_instr_intel(parser_gas);
- if (bc) {
- yasm_warn_disable(YASM_WARN_UNREC_CHAR);
- do {
- destroy_curtok();
- get_next_token();
- } while (!is_eol());
- yasm_warn_enable(YASM_WARN_UNREC_CHAR);
- }
- return bc;
- }
-
- if (curtok != ID)
- return NULL;
-
- id = ID_val;
-
- /* instructions/prefixes must start with a letter */
- if (!isalpha(id[0]))
- return NULL;
-
- /* check to be sure it's not a label or equ */
- get_peek_token(parser_gas);
- if (parser_gas->peek_token == ':' || parser_gas->peek_token == '=')
- return NULL;
-
- switch (yasm_arch_parse_check_insnprefix
- (p_object->arch, ID_val, ID_len, cur_line, &bc, &prefix)) {
- case YASM_ARCH_INSN:
- {
- yasm_insn *insn;
-
- /* Propagate errors in case we got a warning from the arch */
- yasm_errwarn_propagate(parser_gas->errwarns, cur_line);
-
- insn = yasm_bc_get_insn(bc);
-
- yasm_xfree(id);
- get_next_token(); /* ID */
- if (is_eol())
- return bc; /* no operands */
-
- /* parse operands */
- for (;;) {
- yasm_insn_operand *op = parse_operand(parser_gas);
- if (!op) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expression syntax error"));
- yasm_bc_destroy(bc);
- return NULL;
- }
- yasm_insn_ops_append(insn, op);
-
- if (is_eol())
- break;
- if (!expect(',')) {
- yasm_bc_destroy(bc);
- return NULL;
- }
- get_next_token();
- }
- return bc;
- }
- case YASM_ARCH_PREFIX:
- /* Propagate errors in case we got a warning from the arch */
- yasm_errwarn_propagate(parser_gas->errwarns, cur_line);
-
- yasm_xfree(id);
- get_next_token(); /* ID */
- bc = parse_instr(parser_gas);
- if (!bc)
- bc = yasm_arch_create_empty_insn(p_object->arch, cur_line);
- yasm_insn_add_prefix(yasm_bc_get_insn(bc), prefix);
- return bc;
- default:
- break;
- }
-
- /* Check for segment register used as prefix */
- switch (yasm_arch_parse_check_regtmod(p_object->arch, ID_val, ID_len,
- &prefix)) {
- case YASM_ARCH_SEGREG:
- yasm_xfree(id);
- get_next_token(); /* ID */
- bc = parse_instr(parser_gas);
- if (!bc)
- bc = yasm_arch_create_empty_insn(p_object->arch, cur_line);
- yasm_insn_add_seg_prefix(yasm_bc_get_insn(bc), prefix);
- return bc;
- default:
- return NULL;
- }
-}
-
-static int
-parse_dirvals(yasm_parser_gas *parser_gas, yasm_valparamhead *vps)
-{
- yasm_valparam *vp;
- yasm_expr *e;
- int num = 0;
-
- yasm_vps_initialize(vps);
-
- for (;;) {
- switch (curtok) {
- case ID:
- get_peek_token(parser_gas);
- switch (parser_gas->peek_token) {
- case '+': case '-':
- case '|': case '^': case '&': case '!':
- case '*': case '/': case '%': case LEFT_OP: case RIGHT_OP:
- e = parse_expr(parser_gas);
- vp = yasm_vp_create_expr(NULL, e);
- break;
- default:
- /* Just an ID */
- vp = yasm_vp_create_id(NULL, ID_val, '\0');
- get_next_token(); /* ID */
- break;
- }
- break;
- case STRING:
- vp = yasm_vp_create_string(NULL, STRING_val.contents);
- get_next_token(); /* STRING */
- break;
- case REG:
- e = p_expr_new_ident(yasm_expr_reg(REG_val));
- vp = yasm_vp_create_expr(NULL, e);
- get_next_token(); /* REG */
- break;
- case '@':
- /* XXX: is throwing it away *really* the right thing? */
- get_next_token(); /* @ */
- continue;
- default:
- e = parse_expr(parser_gas);
- if (!e)
- return num;
- vp = yasm_vp_create_expr(NULL, e);
- break;
- }
- yasm_vps_append(vps, vp);
- num++;
- if (curtok == ',')
- get_next_token(); /* ',' */
- }
- return num;
-}
-
-static int
-parse_datavals(yasm_parser_gas *parser_gas, yasm_datavalhead *dvs)
-{
- yasm_expr *e;
- yasm_dataval *dv;
- int num = 0;
-
- yasm_dvs_initialize(dvs);
-
- for (;;) {
- e = parse_expr(parser_gas);
- if (!e) {
- yasm_dvs_delete(dvs);
- yasm_dvs_initialize(dvs);
- return 0;
- }
- dv = yasm_dv_create_expr(e);
- yasm_dvs_append(dvs, dv);
- num++;
- if (curtok != ',')
- break;
- get_next_token(); /* ',' */
- }
- return num;
-}
-
-static int
-parse_strvals(yasm_parser_gas *parser_gas, yasm_datavalhead *dvs)
-{
- yasm_dataval *dv;
- int num = 0;
-
- yasm_dvs_initialize(dvs);
-
- for (;;) {
- if (!expect(STRING)) {
- yasm_dvs_delete(dvs);
- yasm_dvs_initialize(dvs);
- return 0;
- }
- dv = yasm_dv_create_string(STRING_val.contents, STRING_val.len);
- yasm_dvs_append(dvs, dv);
- get_next_token(); /* STRING */
- num++;
- if (curtok != ',')
- break;
- get_next_token(); /* ',' */
- }
- return num;
-}
-
-/* instruction operands */
-/* memory addresses */
-static yasm_effaddr *
-parse_memaddr(yasm_parser_gas *parser_gas)
-{
- yasm_effaddr *ea = NULL;
- yasm_expr *e1, *e2;
- int strong = 0;
-
- if (curtok == SEGREG) {
- uintptr_t segreg = SEGREG_val;
- get_next_token(); /* SEGREG */
- if (!expect(':')) return NULL;
- get_next_token(); /* ':' */
- ea = parse_memaddr(parser_gas);
- if (!ea)
- return NULL;
- yasm_ea_set_segreg(ea, segreg);
- return ea;
- }
-
- /* We want to parse a leading expression, except when it's actually
- * just a memory address (with no preceding expression) such as
- * (REG...) or (,...).
- */
- get_peek_token(parser_gas);
- if (curtok != '(' || (parser_gas->peek_token != REG
- && parser_gas->peek_token != ','))
- e1 = parse_expr(parser_gas);
- else
- e1 = NULL;
-
- if (curtok == '(') {
- int havereg = 0;
- uintptr_t reg = 0;
- yasm_intnum *scale = NULL;
-
- get_next_token(); /* '(' */
-
- /* base register */
- if (curtok == REG) {
- e2 = p_expr_new_ident(yasm_expr_reg(REG_val));
- get_next_token(); /* REG */
- } else
- e2 = p_expr_new_ident(yasm_expr_int(yasm_intnum_create_uint(0)));
-
- if (curtok == ')')
- goto done;
-
- if (!expect(',')) {
- yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid memory expression"));
- if (e1) yasm_expr_destroy(e1);
- yasm_expr_destroy(e2);
- return NULL;
- }
- get_next_token(); /* ',' */
-
- if (curtok == ')')
- goto done;
-
- /* index register */
- if (curtok == REG) {
- reg = REG_val;
- havereg = 1;
- get_next_token(); /* REG */
- if (curtok != ',') {
- scale = yasm_intnum_create_uint(1);
- goto done;
- }
- get_next_token(); /* ',' */
- }
-
- /* scale */
- if (!expect(INTNUM)) {
- yasm_error_set(YASM_ERROR_SYNTAX, N_("non-integer scale"));
- if (e1) yasm_expr_destroy(e1);
- yasm_expr_destroy(e2);
- return NULL;
- }
- scale = INTNUM_val;
- get_next_token(); /* INTNUM */
-
-done:
- if (!expect(')')) {
- yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid memory expression"));
- if (scale) yasm_intnum_destroy(scale);
- if (e1) yasm_expr_destroy(e1);
- yasm_expr_destroy(e2);
- return NULL;
- }
- get_next_token(); /* ')' */
-
- if (scale) {
- if (!havereg) {
- if (yasm_intnum_get_uint(scale) != 1)
- yasm_warn_set(YASM_WARN_GENERAL,
- N_("scale factor of %u without an index register"),
- yasm_intnum_get_uint(scale));
- yasm_intnum_destroy(scale);
- } else
- e2 = p_expr_new(yasm_expr_expr(e2), YASM_EXPR_ADD,
- yasm_expr_expr(p_expr_new(yasm_expr_reg(reg), YASM_EXPR_MUL,
- yasm_expr_int(scale))));
- }
-
- if (e1) {
- /* Ordering is critical here to correctly detecting presence of
- * RIP in RIP-relative expressions.
- */
- e1 = p_expr_new_tree(e2, YASM_EXPR_ADD, e1);
- } else
- e1 = e2;
- strong = 1;
- }
-
- if (!e1)
- return NULL;
- ea = yasm_arch_ea_create(p_object->arch, e1);
- if (strong)
- ea->strong = 1;
- return ea;
-}
-
-static yasm_insn_operand *
-parse_operand(yasm_parser_gas *parser_gas)
-{
- yasm_effaddr *ea;
- yasm_insn_operand *op;
- uintptr_t reg;
-
- switch (curtok) {
- case REG:
- reg = REG_val;
- get_next_token(); /* REG */
- return yasm_operand_create_reg(reg);
- case SEGREG:
- /* need to see if it's really a memory address */
- get_peek_token(parser_gas);
- if (parser_gas->peek_token == ':') {
- ea = parse_memaddr(parser_gas);
- if (!ea)
- return NULL;
- return yasm_operand_create_mem(ea);
- }
- reg = SEGREG_val;
- get_next_token(); /* SEGREG */
- return yasm_operand_create_segreg(reg);
- case REGGROUP:
- {
- unsigned long regindex;
- reg = REGGROUP_val;
- get_next_token(); /* REGGROUP */
- if (curtok != '(')
- return yasm_operand_create_reg(reg);
- get_next_token(); /* '(' */
- if (!expect(INTNUM)) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("integer register index expected"));
- return NULL;
- }
- regindex = yasm_intnum_get_uint(INTNUM_val);
- get_next_token(); /* INTNUM */
- if (!expect(')')) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("missing closing parenthesis for register index"));
- return NULL;
- }
- get_next_token(); /* ')' */
- reg = yasm_arch_reggroup_get_reg(p_object->arch, reg, regindex);
- if (reg == 0) {
- yasm_error_set(YASM_ERROR_SYNTAX, N_("bad register index `%u'"),
- regindex);
- return NULL;
- }
- return yasm_operand_create_reg(reg);
- }
- case '$':
- {
- yasm_expr *e;
- get_next_token(); /* '$' */
- e = parse_expr(parser_gas);
- if (!e) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expression missing after `%s'"), "$");
- return NULL;
- }
- return yasm_operand_create_imm(e);
- }
- case '*':
- get_next_token(); /* '*' */
- if (curtok == REG) {
- op = yasm_operand_create_reg(REG_val);
- get_next_token(); /* REG */
- } else {
- ea = parse_memaddr(parser_gas);
- if (!ea) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expression missing after `%s'"), "*");
- return NULL;
- }
- op = yasm_operand_create_mem(ea);
- }
- op->deref = 1;
- return op;
- default:
- ea = parse_memaddr(parser_gas);
- if (!ea)
- return NULL;
- return yasm_operand_create_mem(ea);
- }
-}
-
-/* Expression grammar parsed is:
- *
- * expr : expr0 [ {+,-} expr0...]
- * expr0 : expr1 [ {|,^,&,!} expr1...]
- * expr1 : expr2 [ {*,/,%,<<,>>} expr2...]
- * expr2 : { ~,+,- } expr2
- * | (expr)
- * | symbol
- * | number
- */
-
-static yasm_expr *
-parse_expr(yasm_parser_gas *parser_gas)
-{
- yasm_expr *e, *f;
- e = parse_expr0(parser_gas);
- if (!e)
- return NULL;
-
- while (curtok == '+' || curtok == '-') {
- int op = curtok;
- get_next_token();
- f = parse_expr0(parser_gas);
- if (!f) {
- yasm_expr_destroy(e);
- return NULL;
- }
-
- switch (op) {
- case '+': e = p_expr_new_tree(e, YASM_EXPR_ADD, f); break;
- case '-': e = p_expr_new_tree(e, YASM_EXPR_SUB, f); break;
- }
- }
- return e;
-}
-
-static yasm_expr *
-parse_expr0(yasm_parser_gas *parser_gas)
-{
- yasm_expr *e, *f;
- e = parse_expr1(parser_gas);
- if (!e)
- return NULL;
-
- while (curtok == '|' || curtok == '^' || curtok == '&' || curtok == '!') {
- int op = curtok;
- get_next_token();
- f = parse_expr1(parser_gas);
- if (!f) {
- yasm_expr_destroy(e);
- return NULL;
- }
-
- switch (op) {
- case '|': e = p_expr_new_tree(e, YASM_EXPR_OR, f); break;
- case '^': e = p_expr_new_tree(e, YASM_EXPR_XOR, f); break;
- case '&': e = p_expr_new_tree(e, YASM_EXPR_AND, f); break;
- case '!': e = p_expr_new_tree(e, YASM_EXPR_NOR, f); break;
- }
- }
- return e;
-}
-
-static yasm_expr *
-parse_expr1(yasm_parser_gas *parser_gas)
-{
- yasm_expr *e, *f;
- e = parse_expr2(parser_gas);
- if (!e)
- return NULL;
-
- while (curtok == '*' || curtok == '/' || curtok == '%' || curtok == LEFT_OP
- || curtok == RIGHT_OP) {
- int op = curtok;
- get_next_token();
- f = parse_expr2(parser_gas);
- if (!f) {
- yasm_expr_destroy(e);
- return NULL;
- }
-
- switch (op) {
- case '*': e = p_expr_new_tree(e, YASM_EXPR_MUL, f); break;
- case '/': e = p_expr_new_tree(e, YASM_EXPR_DIV, f); break;
- case '%': e = p_expr_new_tree(e, YASM_EXPR_MOD, f); break;
- case LEFT_OP: e = p_expr_new_tree(e, YASM_EXPR_SHL, f); break;
- case RIGHT_OP: e = p_expr_new_tree(e, YASM_EXPR_SHR, f); break;
- }
- }
- return e;
-}
-
-static yasm_expr *
-parse_expr2(yasm_parser_gas *parser_gas)
-{
- yasm_expr *e;
- yasm_symrec *sym;
-
- switch (curtok) {
- case '+':
- get_next_token();
- return parse_expr2(parser_gas);
- case '-':
- get_next_token();
- e = parse_expr2(parser_gas);
- if (!e)
- return NULL;
- return p_expr_new_branch(YASM_EXPR_NEG, e);
- case '~':
- get_next_token();
- e = parse_expr2(parser_gas);
- if (!e)
- return NULL;
- return p_expr_new_branch(YASM_EXPR_NOT, e);
- case '(':
- get_next_token();
- e = parse_expr(parser_gas);
- if (!e)
- return NULL;
- if (!expect(')')) {
- yasm_error_set(YASM_ERROR_SYNTAX, N_("missing parenthesis"));
- return NULL;
- }
- get_next_token();
- return e;
- case INTNUM:
- e = p_expr_new_ident(yasm_expr_int(INTNUM_val));
- get_next_token();
- return e;
- case FLTNUM:
- e = p_expr_new_ident(yasm_expr_float(FLTNUM_val));
- get_next_token();
- return e;
- case ID:
- {
- char *name = ID_val;
- get_next_token(); /* ID */
-
- /* "." references the current assembly position */
- if (name[1] == '\0' && name[0] == '.')
- sym = yasm_symtab_define_curpos(p_symtab, ".",
- parser_gas->prev_bc, cur_line);
- else
- sym = yasm_symtab_use(p_symtab, name, cur_line);
- yasm_xfree(name);
-
- if (curtok == '@') {
- yasm_symrec *wrt;
- /* TODO: this is needed for shared objects, e.g. sym@PLT */
- get_next_token(); /* '@' */
- if (!expect(ID)) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected identifier after `@'"));
- return NULL;
- }
- wrt = yasm_objfmt_get_special_sym(p_object, ID_val, "gas");
- yasm_xfree(ID_val);
- get_next_token(); /* ID */
- if (!wrt) {
- yasm_warn_set(YASM_WARN_GENERAL,
- N_("unrecognized identifier after `@'"));
- return p_expr_new_ident(yasm_expr_sym(sym));
- }
- return p_expr_new(yasm_expr_sym(sym), YASM_EXPR_WRT,
- yasm_expr_sym(wrt));
- }
-
- return p_expr_new_ident(yasm_expr_sym(sym));
- }
- default:
- return NULL;
- }
-}
-
-static void
-define_label(yasm_parser_gas *parser_gas, char *name, int local)
-{
- if (!local) {
- if (parser_gas->locallabel_base)
- yasm_xfree(parser_gas->locallabel_base);
- parser_gas->locallabel_base_len = strlen(name);
- parser_gas->locallabel_base =
- yasm_xmalloc(parser_gas->locallabel_base_len+1);
- strcpy(parser_gas->locallabel_base, name);
- }
-
- yasm_symtab_define_label(p_symtab, name, parser_gas->prev_bc, 1,
- cur_line);
- yasm_xfree(name);
-}
-
-static void
-define_lcomm(yasm_parser_gas *parser_gas, /*@only@*/ char *name,
- yasm_expr *size, /*@null@*/ yasm_expr *align)
-{
- /* Put into .bss section. */
- /*@dependent@*/ yasm_section *bss =
- gas_get_section(parser_gas, yasm__xstrdup(".bss"), NULL, NULL, NULL, 1);
-
- if (align) {
- /* XXX: assume alignment is in bytes, not power-of-two */
- yasm_section_bcs_append(bss, gas_parser_align(parser_gas, bss, align,
- NULL, NULL, 0));
- }
-
- yasm_symtab_define_label(p_symtab, name, yasm_section_bcs_last(bss), 1,
- cur_line);
- yasm_section_bcs_append(bss, yasm_bc_create_reserve(size, 1, cur_line));
- yasm_xfree(name);
-}
-
-static yasm_section *
-gas_get_section(yasm_parser_gas *parser_gas, char *name,
- /*@null@*/ char *flags, /*@null@*/ char *type,
- /*@null@*/ yasm_valparamhead *objext_valparams,
- int builtin)
-{
- yasm_valparamhead vps;
- yasm_valparam *vp;
- char *gasflags;
- yasm_section *new_section;
-
- yasm_vps_initialize(&vps);
- vp = yasm_vp_create_id(NULL, name, '\0');
- yasm_vps_append(&vps, vp);
-
- if (!builtin) {
- if (flags)
- gasflags = yasm__xstrdup(flags);
- else
- gasflags = yasm__xstrdup("");
- vp = yasm_vp_create_string(yasm__xstrdup("gasflags"), gasflags);
- yasm_vps_append(&vps, vp);
- if (type) {
- vp = yasm_vp_create_id(NULL, type, '\0');
- yasm_vps_append(&vps, vp);
- }
- }
-
- new_section = yasm_objfmt_section_switch(p_object, &vps, objext_valparams,
- cur_line);
-
- yasm_vps_delete(&vps);
- return new_section;
-}
-
-static void
-gas_switch_section(yasm_parser_gas *parser_gas, const char *name,
- /*@null@*/ char *flags, /*@null@*/ char *type,
- /*@null@*/ yasm_valparamhead *objext_valparams,
- int builtin)
-{
- yasm_section *new_section;
-
- new_section = gas_get_section(parser_gas, yasm__xstrdup(name), flags, type,
- objext_valparams, builtin);
- if (new_section) {
- cursect = new_section;
- parser_gas->prev_bc = yasm_section_bcs_last(new_section);
- } else
- yasm_error_set(YASM_ERROR_GENERAL, N_("invalid section name `%s'"),
- name);
-
- if (objext_valparams)
- yasm_vps_delete(objext_valparams);
-}
-
-static yasm_bytecode *
-gas_parser_align(yasm_parser_gas *parser_gas, yasm_section *sect,
- yasm_expr *boundval, /*@null@*/ yasm_expr *fillval,
- /*@null@*/ yasm_expr *maxskipval, int power2)
-{
- yasm_intnum *boundintn;
-
- /* Convert power of two to number of bytes if necessary */
- if (power2)
- boundval = yasm_expr_create(YASM_EXPR_SHL,
- yasm_expr_int(yasm_intnum_create_uint(1)),
- yasm_expr_expr(boundval), cur_line);
-
- /* Largest .align in the section specifies section alignment. */
- boundintn = yasm_expr_get_intnum(&boundval, 0);
- if (boundintn) {
- unsigned long boundint = yasm_intnum_get_uint(boundintn);
-
- /* Alignments must be a power of two. */
- if (is_exp2(boundint)) {
- if (boundint > yasm_section_get_align(sect))
- yasm_section_set_align(sect, boundint, cur_line);
- }
- }
-
- return yasm_bc_create_align(boundval, fillval, maxskipval,
- yasm_section_is_code(sect) ?
- yasm_arch_get_fill(p_object->arch) : NULL,
- cur_line);
-}
-
-static yasm_bytecode *
-gas_parser_dir_fill(yasm_parser_gas *parser_gas, /*@only@*/ yasm_expr *repeat,
- /*@only@*/ /*@null@*/ yasm_expr *size,
- /*@only@*/ /*@null@*/ yasm_expr *value)
-{
- yasm_datavalhead dvs;
- yasm_bytecode *bc;
- unsigned int ssize;
-
- if (size) {
- /*@dependent@*/ /*@null@*/ yasm_intnum *intn;
- intn = yasm_expr_get_intnum(&size, 0);
- if (!intn) {
- yasm_error_set(YASM_ERROR_NOT_ABSOLUTE,
- N_("size must be an absolute expression"));
- yasm_expr_destroy(repeat);
- yasm_expr_destroy(size);
- if (value)
- yasm_expr_destroy(value);
- return NULL;
- }
- ssize = yasm_intnum_get_uint(intn);
- } else
- ssize = 1;
-
- if (!value)
- value = yasm_expr_create_ident(
- yasm_expr_int(yasm_intnum_create_uint(0)), cur_line);
-
- yasm_dvs_initialize(&dvs);
- yasm_dvs_append(&dvs, yasm_dv_create_expr(value));
- bc = yasm_bc_create_data(&dvs, ssize, 0, p_object->arch, cur_line);
-
- yasm_bc_set_multiple(bc, repeat);
-
- return bc;
-}
-
-static dir_lookup dirs_static[] = {
- /* FIXME: Whether this is power-of-two or not depends on arch and objfmt. */
- {".align", dir_align, 0, INITIAL},
- {".p2align", dir_align, 1, INITIAL},
- {".balign", dir_align, 0, INITIAL},
- {".org", dir_org, 0, INITIAL},
- /* data visibility directives */
- {".local", dir_local, 0, INITIAL},
- {".comm", dir_comm, 0, INITIAL},
- {".lcomm", dir_comm, 1, INITIAL},
- /* integer data declaration directives */
- {".byte", dir_data, 1, INITIAL},
- {".2byte", dir_data, 2, INITIAL},
- {".4byte", dir_data, 4, INITIAL},
- {".8byte", dir_data, 8, INITIAL},
- {".16byte", dir_data, 16, INITIAL},
- /* TODO: These should depend on arch */
- {".short", dir_data, 2, INITIAL},
- {".int", dir_data, 4, INITIAL},
- {".long", dir_data, 4, INITIAL},
- {".hword", dir_data, 2, INITIAL},
- {".quad", dir_data, 8, INITIAL},
- {".octa", dir_data, 16, INITIAL},
- /* XXX: At least on x86, this is 2 bytes */
- {".value", dir_data, 2, INITIAL},
- /* ASCII data declaration directives */
- {".ascii", dir_ascii, 0, INITIAL}, /* no terminating zero */
- {".asciz", dir_ascii, 1, INITIAL}, /* add terminating zero */
- {".string", dir_ascii, 1, INITIAL}, /* add terminating zero */
- /* LEB128 integer data declaration directives */
- {".sleb128", dir_leb128, 1, INITIAL}, /* signed */
- {".uleb128", dir_leb128, 0, INITIAL}, /* unsigned */
- /* floating point data declaration directives */
- {".float", dir_data, 4, INITIAL},
- {".single", dir_data, 4, INITIAL},
- {".double", dir_data, 8, INITIAL},
- {".tfloat", dir_data, 10, INITIAL},
- /* section directives */
- {".bss", dir_bss_section, 0, INITIAL},
- {".data", dir_data_section, 0, INITIAL},
- {".text", dir_text_section, 0, INITIAL},
- {".section", dir_section, 0, SECTION_DIRECTIVE},
- /* empty space/fill directives */
- {".skip", dir_skip, 0, INITIAL},
- {".space", dir_skip, 0, INITIAL},
- {".fill", dir_fill, 0, INITIAL},
- {".zero", dir_zero, 0, INITIAL},
- /* syntax directives */
- {".intel_syntax", dir_intel_syntax, 0, INITIAL},
- {".att_syntax", dir_att_syntax, 0, INITIAL},
- /* other directives */
- {".equ", dir_equ, 0, INITIAL},
- {".file", dir_file, 0, INITIAL},
- {".line", dir_line, 0, INITIAL},
- {".set", dir_equ, 0, INITIAL}
-};
-
-static void
-no_delete(void *data)
-{
-}
-
-void
-gas_parser_parse(yasm_parser_gas *parser_gas)
-{
- dir_lookup word;
- unsigned int i;
- int replace = 1;
-
- word.name = ".word";
- word.handler = dir_data;
- word.param = yasm_arch_wordsize(p_object->arch)/8;
- word.newstate = INITIAL;
-
- /* Create directive lookup */
- parser_gas->dirs = HAMT_create(1, yasm_internal_error_);
- HAMT_insert(parser_gas->dirs, word.name, &word, &replace, no_delete);
- for (i=0; i<NELEMS(dirs_static); i++) {
- replace = 1;
- HAMT_insert(parser_gas->dirs, dirs_static[i].name,
- &dirs_static[i], &replace, no_delete);
- }
-
- while (get_next_token() != 0) {
- yasm_bytecode *bc = NULL, *temp_bc;
-
- if (!is_eol()) {
- bc = parse_line(parser_gas);
- demand_eol();
- }
-
- yasm_errwarn_propagate(parser_gas->errwarns, cur_line);
-
- temp_bc = yasm_section_bcs_append(cursect, bc);
- if (temp_bc)
- parser_gas->prev_bc = temp_bc;
- if (curtok == ';')
- continue; /* don't advance line number until \n */
- if (parser_gas->save_input)
- yasm_linemap_add_source(parser_gas->linemap,
- temp_bc,
- (char *)parser_gas->save_line[parser_gas->save_last ^ 1]);
- yasm_linemap_goto_next(parser_gas->linemap);
- parser_gas->dir_line++; /* keep track for .line followed by .file */
- }
-
- HAMT_destroy(parser_gas->dirs, no_delete);
-}
+/*
+ * GAS-compatible parser
+ *
+ * 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.
+ * 3. Neither the name of the author nor the names of other contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 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>
+
+#include <ctype.h>
+#include <limits.h>
+#include <math.h>
+
+#include "modules/parsers/gas/gas-parser.h"
+
+typedef struct dir_lookup {
+ const char *name;
+ yasm_bytecode * (*handler) (yasm_parser_gas *, unsigned int);
+ unsigned int param;
+ enum gas_parser_state newstate;
+} dir_lookup;
+
+static void cpp_line_marker(yasm_parser_gas *parser_gas);
+static void nasm_line_marker(yasm_parser_gas *parser_gas);
+static yasm_bytecode *parse_instr(yasm_parser_gas *parser_gas);
+static int parse_dirvals(yasm_parser_gas *parser_gas, yasm_valparamhead *vps);
+static int parse_datavals(yasm_parser_gas *parser_gas, yasm_datavalhead *dvs);
+static int parse_strvals(yasm_parser_gas *parser_gas, yasm_datavalhead *dvs);
+static yasm_effaddr *parse_memaddr(yasm_parser_gas *parser_gas);
+static yasm_insn_operand *parse_operand(yasm_parser_gas *parser_gas);
+static yasm_expr *parse_expr(yasm_parser_gas *parser_gas);
+static yasm_expr *parse_expr0(yasm_parser_gas *parser_gas);
+static yasm_expr *parse_expr1(yasm_parser_gas *parser_gas);
+static yasm_expr *parse_expr2(yasm_parser_gas *parser_gas);
+
+static void define_label(yasm_parser_gas *parser_gas, char *name, int local);
+static void define_lcomm(yasm_parser_gas *parser_gas, /*@only@*/ char *name,
+ yasm_expr *size, /*@null@*/ yasm_expr *align);
+static yasm_section *gas_get_section
+ (yasm_parser_gas *parser_gas, /*@only@*/ char *name, /*@null@*/ char *flags,
+ /*@null@*/ char *type, /*@null@*/ yasm_valparamhead *objext_valparams,
+ int builtin);
+static void gas_switch_section
+ (yasm_parser_gas *parser_gas, /*@only@*/ const char *name,
+ /*@null@*/ char *flags, /*@null@*/ char *type,
+ /*@null@*/ yasm_valparamhead *objext_valparams, int builtin);
+static yasm_bytecode *gas_parser_align
+ (yasm_parser_gas *parser_gas, yasm_section *sect, yasm_expr *boundval,
+ /*@null@*/ yasm_expr *fillval, /*@null@*/ yasm_expr *maxskipval,
+ int power2);
+static yasm_bytecode *gas_parser_dir_fill
+ (yasm_parser_gas *parser_gas, /*@only@*/ yasm_expr *repeat,
+ /*@only@*/ /*@null@*/ yasm_expr *size,
+ /*@only@*/ /*@null@*/ yasm_expr *value);
+
+#define is_eol_tok(tok) ((tok) == '\n' || (tok) == ';' || (tok) == 0)
+#define is_eol() is_eol_tok(curtok)
+
+#define get_next_token() (curtok = gas_parser_lex(&curval, parser_gas))
+
+static void
+get_peek_token(yasm_parser_gas *parser_gas)
+{
+ char savech = parser_gas->tokch;
+ if (parser_gas->peek_token != NONE)
+ yasm_internal_error(N_("can only have one token of lookahead"));
+ parser_gas->peek_token =
+ gas_parser_lex(&parser_gas->peek_tokval, parser_gas);
+ parser_gas->peek_tokch = parser_gas->tokch;
+ parser_gas->tokch = savech;
+}
+
+static void
+destroy_curtok_(yasm_parser_gas *parser_gas)
+{
+ if (curtok < 256)
+ ;
+ else switch ((enum tokentype)curtok) {
+ case INTNUM:
+ yasm_intnum_destroy(curval.intn);
+ break;
+ case FLTNUM:
+ yasm_floatnum_destroy(curval.flt);
+ break;
+ case ID:
+ case LABEL:
+ case STRING:
+ yasm_xfree(curval.str.contents);
+ break;
+ default:
+ break;
+ }
+ curtok = NONE; /* sanity */
+}
+#define destroy_curtok() destroy_curtok_(parser_gas)
+
+/* Eat all remaining tokens to EOL, discarding all of them. If there's any
+ * intervening tokens, generates an error (junk at end of line).
+ */
+static void
+demand_eol_(yasm_parser_gas *parser_gas)
+{
+ if (is_eol())
+ return;
+
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("junk at end of line, first unrecognized character is `%c'"),
+ parser_gas->tokch);
+
+ do {
+ destroy_curtok();
+ get_next_token();
+ } while (!is_eol());
+}
+#define demand_eol() demand_eol_(parser_gas)
+
+static int
+expect_(yasm_parser_gas *parser_gas, int token)
+{
+ static char strch[] = "` '";
+ const char *str;
+
+ if (curtok == token)
+ return 1;
+
+ switch (token) {
+ case INTNUM: str = "integer"; break;
+ case FLTNUM: str = "floating point value"; break;
+ case STRING: str = "string"; break;
+ case REG: str = "register"; break;
+ case REGGROUP: str = "register group"; break;
+ case SEGREG: str = "segment register"; break;
+ case TARGETMOD: str = "target modifier"; break;
+ case LEFT_OP: str = "<<"; break;
+ case RIGHT_OP: str = ">>"; break;
+ case ID: str = "identifier"; break;
+ case LABEL: str = "label"; break;
+ default:
+ strch[1] = token;
+ str = strch;
+ break;
+ }
+ yasm_error_set(YASM_ERROR_PARSE, "expected %s", str);
+ destroy_curtok();
+ return 0;
+}
+#define expect(token) expect_(parser_gas, token)
+
+static yasm_bytecode *
+parse_line(yasm_parser_gas *parser_gas)
+{
+ yasm_bytecode *bc;
+ yasm_expr *e;
+ yasm_valparamhead vps;
+ char *id;
+ const dir_lookup *dir;
+
+ if (is_eol())
+ return NULL;
+
+ bc = parse_instr(parser_gas);
+ if (bc)
+ return bc;
+
+ switch (curtok) {
+ case ID:
+ id = ID_val;
+
+ /* See if it's a gas-specific directive */
+ dir = (const dir_lookup *)HAMT_search(parser_gas->dirs, id);
+ if (dir) {
+ parser_gas->state = dir->newstate;
+ get_next_token(); /* ID */
+ return dir->handler(parser_gas, dir->param);
+ }
+
+ get_next_token(); /* ID */
+ if (curtok == ':') {
+ /* Label */
+ parser_gas->state = INITIAL;
+ get_next_token(); /* : */
+ define_label(parser_gas, id, 0);
+ return parse_line(parser_gas);
+ } else if (curtok == '=') {
+ /* EQU */
+ /* TODO: allow redefinition, assigning to . (same as .org) */
+ parser_gas->state = INITIAL;
+ get_next_token(); /* = */
+ e = parse_expr(parser_gas);
+ if (e)
+ yasm_symtab_define_equ(p_symtab, id, e, cur_line);
+ else
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expression expected after `%s'"), "=");
+ yasm_xfree(id);
+ return NULL;
+ }
+
+ /* possibly a directive; try to parse it */
+ parse_dirvals(parser_gas, &vps);
+ if (!yasm_object_directive(p_object, id, "gas", &vps, NULL,
+ cur_line)) {
+ yasm_vps_delete(&vps);
+ yasm_xfree(id);
+ return NULL;
+ }
+ yasm_vps_delete(&vps);
+ if (id[0] == '.')
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("directive `%s' not recognized"), id);
+ else
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("instruction not recognized: `%s'"), id);
+ yasm_xfree(id);
+ return NULL;
+ case LABEL:
+ define_label(parser_gas, LABEL_val, 0);
+ get_next_token(); /* LABEL */
+ return parse_line(parser_gas);
+ case CPP_LINE_MARKER:
+ get_next_token();
+ cpp_line_marker(parser_gas);
+ return NULL;
+ case NASM_LINE_MARKER:
+ get_next_token();
+ nasm_line_marker(parser_gas);
+ return NULL;
+ default:
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("label or instruction expected at start of line"));
+ return NULL;
+ }
+}
+
+/*
+ Handle line markers generated by cpp.
+
+ We expect a positive integer (line) followed by a string (filename). If we
+ fail to find either of these, we treat the line as a comment. There is a
+ possibility of false positives (mistaking a comment for a line marker, when
+ the comment is not intended as a line marker) but this cannot be avoided
+ without adding a filter to the input before passing it to cpp.
+
+ This function is only called if the preprocessor was 'cpp', since the
+ CPP_LINE_MARKER token isn't generated for any other preprocessor. With any
+ other preprocessor, anything after a '#' is always treated as a comment.
+*/
+static void
+cpp_line_marker(yasm_parser_gas *parser_gas)
+{
+ yasm_valparamhead vps;
+ yasm_valparam *vp;
+ unsigned long line;
+ char *filename;
+
+ /* Line number. */
+ if (curtok != INTNUM) {
+ /* Skip over a comment. */
+ while (curtok != '\n')
+ get_next_token();
+
+ return;
+ }
+
+ if (yasm_intnum_sign(INTNUM_val) < 0) {
+ get_next_token(); /* INTNUM */
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("line number is negative"));
+ return;
+ }
+
+ line = yasm_intnum_get_uint(INTNUM_val);
+
+ /*
+ Set to (line - 1) since the directive indicates that the *next* line
+ will have the number given.
+
+ cpp should never produce line=0, but the if keeps us safe just incase.
+ */
+ if (line != 0)
+ line--;
+
+ yasm_intnum_destroy(INTNUM_val);
+ get_next_token(); /* INTNUM */
+
+ /* File name, in quotes. */
+ if (curtok != STRING) {
+ /* Skip over a comment. */
+ while (curtok != '\n')
+ get_next_token();
+
+ return;
+ }
+
+ filename = STRING_val.contents;
+ get_next_token();
+
+ /* Set linemap. */
+ yasm_linemap_set(parser_gas->linemap, filename, 0, line, 1);
+
+ /*
+ The first line marker in the file (which should be on the first line
+ of the file) will give us the name of the source file. This information
+ needs to be passed on to the debug format module.
+ */
+ if (parser_gas->seen_line_marker == 0) {
+ parser_gas->seen_line_marker = 1;
+
+ yasm_vps_initialize(&vps);
+ vp = yasm_vp_create_string(NULL, filename);
+ yasm_vps_append(&vps, vp);
+
+ yasm_object_directive(p_object, ".file", "gas", &vps, NULL, cur_line);
+
+ yasm_vps_delete(&vps);
+ } else
+ yasm_xfree(filename);
+
+ /* Skip flags. */
+ while (1) {
+ switch (curtok) {
+ case INTNUM:
+ break;
+
+ case '\n':
+ return;
+
+ default:
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("junk at end of cpp line marker"));
+ return;
+ }
+ get_next_token();
+ }
+}
+
+/*
+ Handle line markers generated by the nasm preproc.
+
+ We expect a positive integer (line) followed by a plus sign, followed by
+ another positive integer, followed by a string (filename).
+
+ This function is only called if the preprocessor was 'nasm', since the
+ NASM_LINE_MARKER token isn't generated for any other preprocessor.
+*/
+static void
+nasm_line_marker(yasm_parser_gas *parser_gas)
+{
+ yasm_valparamhead vps;
+ yasm_valparam *vp;
+ unsigned long line, incr;
+ char *filename;
+
+ /* Line number. */
+ if (!expect(INTNUM)) return;
+
+ if (yasm_intnum_sign(INTNUM_val) < 0) {
+ get_next_token(); /* INTNUM */
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("line number is negative"));
+ return;
+ }
+
+ line = yasm_intnum_get_uint(INTNUM_val);
+
+ /*
+ Set to (line - 1) since the directive indicates that the *next* line
+ will have the number given.
+
+ cpp should never produce line=0, but the if keeps us safe just incase.
+ */
+ if (line != 0)
+ line--;
+
+ yasm_intnum_destroy(INTNUM_val);
+ get_next_token(); /* INTNUM */
+
+ if (!expect('+')) return;
+ get_next_token(); /* + */
+
+ /* Line number increment. */
+ if (!expect(INTNUM)) return;
+
+ if (yasm_intnum_sign(INTNUM_val) < 0) {
+ get_next_token(); /* INTNUM */
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("line increment is negative"));
+ return;
+ }
+
+ incr = yasm_intnum_get_uint(INTNUM_val);
+ yasm_intnum_destroy(INTNUM_val);
+
+ /* File name is not in quotes, so need to switch to a different tokenizer
+ * state.
+ */
+ parser_gas->state = NASM_FILENAME;
+ get_next_token(); /* INTNUM */
+ if (!expect(STRING)) {
+ parser_gas->state = INITIAL;
+ return;
+ }
+
+ filename = STRING_val.contents;
+
+ /* Set linemap. */
+ yasm_linemap_set(parser_gas->linemap, filename, 0, line, incr);
+
+ /*
+ The first line marker in the file (which should be on the first line
+ of the file) will give us the name of the source file. This information
+ needs to be passed on to the debug format module.
+ */
+ if (parser_gas->seen_line_marker == 0) {
+ parser_gas->seen_line_marker = 1;
+
+ yasm_vps_initialize(&vps);
+ vp = yasm_vp_create_string(NULL, filename);
+ yasm_vps_append(&vps, vp);
+
+ yasm_object_directive(p_object, ".file", "gas", &vps, NULL, cur_line);
+
+ yasm_vps_delete(&vps);
+ } else
+ yasm_xfree(filename);
+
+ /* We need to poke back on the \n that was consumed by the tokenizer */
+ parser_gas->peek_token = '\n';
+ get_next_token();
+}
+
+/* Line directive */
+static yasm_bytecode *
+dir_line(yasm_parser_gas *parser_gas, unsigned int param)
+{
+ if (!expect(INTNUM)) return NULL;
+ if (yasm_intnum_sign(INTNUM_val) < 0) {
+ get_next_token(); /* INTNUM */
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("line number is negative"));
+ return NULL;
+ }
+
+ parser_gas->dir_line = yasm_intnum_get_uint(INTNUM_val);
+ yasm_intnum_destroy(INTNUM_val);
+ get_next_token(); /* INTNUM */
+
+ if (parser_gas->dir_fileline == 3) {
+ /* Have both file and line */
+ yasm_linemap_set(parser_gas->linemap, NULL, 0,
+ parser_gas->dir_line, 1);
+ } else if (parser_gas->dir_fileline == 1) {
+ /* Had previous file directive only */
+ parser_gas->dir_fileline = 3;
+ yasm_linemap_set(parser_gas->linemap, parser_gas->dir_file, 0,
+ parser_gas->dir_line, 1);
+ } else {
+ /* Didn't see file yet */
+ parser_gas->dir_fileline = 2;
+ }
+ return NULL;
+}
+
+/* Alignment directives */
+
+static yasm_bytecode *
+dir_align(yasm_parser_gas *parser_gas, unsigned int param)
+{
+ yasm_expr *bound, *fill=NULL, *maxskip=NULL;
+
+ bound = parse_expr(parser_gas);
+ if (!bound) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_(".align directive must specify alignment"));
+ return NULL;
+ }
+
+ if (curtok == ',') {
+ get_next_token(); /* ',' */
+ fill = parse_expr(parser_gas);
+ if (curtok == ',') {
+ get_next_token(); /* ',' */
+ maxskip = parse_expr(parser_gas);
+ }
+ }
+
+ return gas_parser_align(parser_gas, cursect, bound, fill, maxskip,
+ (int)param);
+}
+
+static yasm_bytecode *
+dir_org(yasm_parser_gas *parser_gas, unsigned int param)
+{
+ yasm_intnum *start, *value=NULL;
+ yasm_bytecode *bc;
+
+ /* TODO: support expr instead of intnum */
+ if (!expect(INTNUM)) return NULL;
+ start = INTNUM_val;
+ get_next_token(); /* INTNUM */
+
+ if (curtok == ',') {
+ get_next_token(); /* ',' */
+ /* TODO: support expr instead of intnum */
+ if (!expect(INTNUM)) return NULL;
+ value = INTNUM_val;
+ get_next_token(); /* INTNUM */
+ }
+ if (value) {
+ bc = yasm_bc_create_org(yasm_intnum_get_uint(start),
+ yasm_intnum_get_uint(value), cur_line);
+ yasm_intnum_destroy(value);
+ } else
+ bc = yasm_bc_create_org(yasm_intnum_get_uint(start), 0,
+ cur_line);
+ yasm_intnum_destroy(start);
+ return bc;
+}
+
+/* Data visibility directives */
+
+static yasm_bytecode *
+dir_local(yasm_parser_gas *parser_gas, unsigned int param)
+{
+ if (!expect(ID)) return NULL;
+ yasm_symtab_declare(p_symtab, ID_val, YASM_SYM_DLOCAL, cur_line);
+ yasm_xfree(ID_val);
+ get_next_token(); /* ID */
+ return NULL;
+}
+
+static yasm_bytecode *
+dir_comm(yasm_parser_gas *parser_gas, unsigned int is_lcomm)
+{
+ yasm_expr *align = NULL;
+ /*@null@*/ /*@dependent@*/ yasm_symrec *sym;
+ char *id;
+ yasm_expr *e;
+
+ if (!expect(ID)) return NULL;
+ id = ID_val;
+ get_next_token(); /* ID */
+ if (!expect(',')) {
+ yasm_xfree(id);
+ return NULL;
+ }
+ get_next_token(); /* , */
+ e = parse_expr(parser_gas);
+ if (!e) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("size expected for `%s'"),
+ ".COMM");
+ return NULL;
+ }
+ if (curtok == ',') {
+ /* Optional alignment expression */
+ get_next_token(); /* ',' */
+ align = parse_expr(parser_gas);
+ }
+ /* If already explicitly declared local, treat like LCOMM */
+ if (is_lcomm
+ || ((sym = yasm_symtab_get(p_symtab, id))
+ && yasm_symrec_get_visibility(sym) == YASM_SYM_DLOCAL)) {
+ define_lcomm(parser_gas, id, e, align);
+ } else if (align) {
+ /* Give third parameter as objext valparam */
+ yasm_valparamhead *extvps = yasm_vps_create();
+ yasm_valparam *vp = yasm_vp_create_expr(NULL, align);
+ yasm_vps_append(extvps, vp);
+
+ sym = yasm_symtab_declare(p_symtab, id, YASM_SYM_COMMON,
+ cur_line);
+ yasm_symrec_set_common_size(sym, e);
+ yasm_symrec_set_objext_valparams(sym, extvps);
+
+ yasm_xfree(id);
+ } else {
+ sym = yasm_symtab_declare(p_symtab, id, YASM_SYM_COMMON,
+ cur_line);
+ yasm_symrec_set_common_size(sym, e);
+ yasm_xfree(id);
+ }
+ return NULL;
+}
+
+/* Integer data definition directives */
+
+static yasm_bytecode *
+dir_ascii(yasm_parser_gas *parser_gas, unsigned int withzero)
+{
+ yasm_datavalhead dvs;
+ if (!parse_strvals(parser_gas, &dvs))
+ return NULL;
+ return yasm_bc_create_data(&dvs, 1, (int)withzero, p_object->arch,
+ cur_line);
+}
+
+static yasm_bytecode *
+dir_data(yasm_parser_gas *parser_gas, unsigned int size)
+{
+ yasm_datavalhead dvs;
+ if (!parse_datavals(parser_gas, &dvs))
+ return NULL;
+ return yasm_bc_create_data(&dvs, size, 0, p_object->arch, cur_line);
+}
+
+static yasm_bytecode *
+dir_leb128(yasm_parser_gas *parser_gas, unsigned int sign)
+{
+ yasm_datavalhead dvs;
+ if (!parse_datavals(parser_gas, &dvs))
+ return NULL;
+ return yasm_bc_create_leb128(&dvs, (int)sign, cur_line);
+}
+
+/* Empty space / fill data definition directives */
+
+static yasm_bytecode *
+dir_zero(yasm_parser_gas *parser_gas, unsigned int param)
+{
+ yasm_bytecode *bc;
+ yasm_datavalhead dvs;
+ yasm_expr *e = parse_expr(parser_gas);
+ if (!e) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expression expected after `%s'"), ".ZERO");
+ return NULL;
+ }
+
+ yasm_dvs_initialize(&dvs);
+ yasm_dvs_append(&dvs, yasm_dv_create_expr(
+ p_expr_new_ident(yasm_expr_int(yasm_intnum_create_uint(0)))));
+ bc = yasm_bc_create_data(&dvs, 1, 0, p_object->arch, cur_line);
+ yasm_bc_set_multiple(bc, e);
+ return bc;
+}
+
+static yasm_bytecode *
+dir_skip(yasm_parser_gas *parser_gas, unsigned int param)
+{
+ yasm_expr *e, *e_val;
+ yasm_bytecode *bc;
+ yasm_datavalhead dvs;
+
+ e = parse_expr(parser_gas);
+ if (!e) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expression expected after `%s'"), ".SKIP");
+ return NULL;
+ }
+ if (curtok != ',')
+ return yasm_bc_create_reserve(e, 1, cur_line);
+ get_next_token(); /* ',' */
+ e_val = parse_expr(parser_gas);
+ yasm_dvs_initialize(&dvs);
+ yasm_dvs_append(&dvs, yasm_dv_create_expr(e_val));
+ bc = yasm_bc_create_data(&dvs, 1, 0, p_object->arch, cur_line);
+
+ yasm_bc_set_multiple(bc, e);
+ return bc;
+}
+
+/* fill data definition directive */
+static yasm_bytecode *
+dir_fill(yasm_parser_gas *parser_gas, unsigned int param)
+{
+ yasm_expr *sz=NULL, *val=NULL;
+ yasm_expr *e = parse_expr(parser_gas);
+ if (!e) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expression expected after `%s'"), ".FILL");
+ return NULL;
+ }
+ if (curtok == ',') {
+ get_next_token(); /* ',' */
+ sz = parse_expr(parser_gas);
+ if (curtok == ',') {
+ get_next_token(); /* ',' */
+ val = parse_expr(parser_gas);
+ }
+ }
+ return gas_parser_dir_fill(parser_gas, e, sz, val);
+}
+
+/* Section directives */
+
+static yasm_bytecode *
+dir_bss_section(yasm_parser_gas *parser_gas, unsigned int param)
+{
+ gas_switch_section(parser_gas, ".bss", NULL, NULL, NULL, 1);
+ return NULL;
+}
+
+static yasm_bytecode *
+dir_data_section(yasm_parser_gas *parser_gas, unsigned int param)
+{
+ gas_switch_section(parser_gas, ".data", NULL, NULL, NULL, 1);
+ return NULL;
+}
+
+static yasm_bytecode *
+dir_text_section(yasm_parser_gas *parser_gas, unsigned int param)
+{
+ gas_switch_section(parser_gas, ".text", NULL, NULL, NULL, 1);
+ return NULL;
+}
+
+static yasm_bytecode *
+dir_section(yasm_parser_gas *parser_gas, unsigned int param)
+{
+ /* DIR_SECTION ID ',' STRING ',' '@' ID ',' dirvals */
+ char *sectname, *flags = NULL, *type = NULL;
+ yasm_valparamhead vps;
+ int have_vps = 0;
+
+ if (!expect(ID)) return NULL;
+ sectname = ID_val;
+ get_next_token(); /* ID */
+
+ if (curtok == ',') {
+ get_next_token(); /* ',' */
+ if (!expect(STRING)) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("flag string expected"));
+ yasm_xfree(sectname);
+ return NULL;
+ }
+ flags = STRING_val.contents;
+ get_next_token(); /* STRING */
+ }
+
+ if (curtok == ',') {
+ get_next_token(); /* ',' */
+ if (!expect('@')) {
+ yasm_xfree(sectname);
+ yasm_xfree(flags);
+ return NULL;
+ }
+ get_next_token(); /* '@' */
+ if (!expect(ID)) {
+ yasm_xfree(sectname);
+ yasm_xfree(flags);
+ return NULL;
+ }
+ type = ID_val;
+ get_next_token(); /* ID */
+ }
+
+ if (curtok == ',') {
+ get_next_token(); /* ',' */
+ if (parse_dirvals(parser_gas, &vps))
+ have_vps = 1;
+ }
+
+ gas_switch_section(parser_gas, sectname, flags, type,
+ have_vps ? &vps : NULL, 0);
+ yasm_xfree(sectname);
+ yasm_xfree(flags);
+ return NULL;
+}
+
+/* Other directives */
+
+static yasm_bytecode *
+dir_equ(yasm_parser_gas *parser_gas, unsigned int param)
+{
+ yasm_expr *e;
+ char *id;
+
+ /* ID ',' expr */
+ if (!expect(ID)) return NULL;
+ id = ID_val;
+ get_next_token(); /* ID */
+ if (!expect(',')) {
+ yasm_xfree(id);
+ return NULL;
+ }
+ get_next_token(); /* ',' */
+ e = parse_expr(parser_gas);
+ if (e)
+ yasm_symtab_define_equ(p_symtab, id, e, cur_line);
+ else
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expression expected after `%s'"), ",");
+ yasm_xfree(id);
+ return NULL;
+}
+
+static yasm_bytecode *
+dir_file(yasm_parser_gas *parser_gas, unsigned int param)
+{
+ yasm_valparamhead vps;
+ yasm_valparam *vp;
+
+ if (curtok == STRING) {
+ /* No file number; this form also sets the assembler's
+ * internal line number.
+ */
+ char *filename = STRING_val.contents;
+
+ get_next_token(); /* STRING */
+ if (parser_gas->dir_fileline == 3) {
+ /* Have both file and line */
+ const char *old_fn;
+ unsigned long old_line;
+
+ yasm_linemap_lookup(parser_gas->linemap, cur_line, &old_fn,
+ &old_line);
+ yasm_linemap_set(parser_gas->linemap, filename, 0, old_line,
+ 1);
+ } else if (parser_gas->dir_fileline == 2) {
+ /* Had previous line directive only */
+ parser_gas->dir_fileline = 3;
+ yasm_linemap_set(parser_gas->linemap, filename, 0,
+ parser_gas->dir_line, 1);
+ } else {
+ /* Didn't see line yet, save file */
+ parser_gas->dir_fileline = 1;
+ if (parser_gas->dir_file)
+ yasm_xfree(parser_gas->dir_file);
+ parser_gas->dir_file = yasm__xstrdup(filename);
+ }
+
+ /* Pass change along to debug format */
+ yasm_vps_initialize(&vps);
+ vp = yasm_vp_create_string(NULL, filename);
+ yasm_vps_append(&vps, vp);
+
+ yasm_object_directive(p_object, ".file", "gas", &vps, NULL,
+ cur_line);
+
+ yasm_vps_delete(&vps);
+ return NULL;
+ }
+
+ /* fileno filename form */
+ yasm_vps_initialize(&vps);
+
+ if (!expect(INTNUM)) return NULL;
+ vp = yasm_vp_create_expr(NULL,
+ p_expr_new_ident(yasm_expr_int(INTNUM_val)));
+ yasm_vps_append(&vps, vp);
+ get_next_token(); /* INTNUM */
+
+ if (!expect(STRING)) {
+ yasm_vps_delete(&vps);
+ return NULL;
+ }
+ vp = yasm_vp_create_string(NULL, STRING_val.contents);
+ yasm_vps_append(&vps, vp);
+ get_next_token(); /* STRING */
+
+ yasm_object_directive(p_object, ".file", "gas", &vps, NULL,
+ cur_line);
+
+ yasm_vps_delete(&vps);
+ return NULL;
+}
+
+
+static yasm_bytecode *
+dir_intel_syntax(yasm_parser_gas *parser_gas, unsigned int param)
+{
+ parser_gas->intel_syntax = 1;
+
+ do {
+ destroy_curtok();
+ get_next_token();
+ } while (!is_eol());
+ return NULL;
+}
+
+static yasm_bytecode *
+dir_att_syntax(yasm_parser_gas *parser_gas, unsigned int param)
+{
+ parser_gas->intel_syntax = 0;
+ return NULL;
+}
+
+static yasm_bytecode *
+parse_instr(yasm_parser_gas *parser_gas)
+{
+ yasm_bytecode *bc;
+ char *id;
+ uintptr_t prefix;
+
+ if (parser_gas->intel_syntax) {
+ bc = parse_instr_intel(parser_gas);
+ if (bc) {
+ yasm_warn_disable(YASM_WARN_UNREC_CHAR);
+ do {
+ destroy_curtok();
+ get_next_token();
+ } while (!is_eol());
+ yasm_warn_enable(YASM_WARN_UNREC_CHAR);
+ }
+ return bc;
+ }
+
+ if (curtok != ID)
+ return NULL;
+
+ id = ID_val;
+
+ /* instructions/prefixes must start with a letter */
+ if (!isalpha(id[0]))
+ return NULL;
+
+ /* check to be sure it's not a label or equ */
+ get_peek_token(parser_gas);
+ if (parser_gas->peek_token == ':' || parser_gas->peek_token == '=')
+ return NULL;
+
+ switch (yasm_arch_parse_check_insnprefix
+ (p_object->arch, ID_val, ID_len, cur_line, &bc, &prefix)) {
+ case YASM_ARCH_INSN:
+ {
+ yasm_insn *insn;
+
+ /* Propagate errors in case we got a warning from the arch */
+ yasm_errwarn_propagate(parser_gas->errwarns, cur_line);
+
+ insn = yasm_bc_get_insn(bc);
+
+ yasm_xfree(id);
+ get_next_token(); /* ID */
+ if (is_eol())
+ return bc; /* no operands */
+
+ /* parse operands */
+ for (;;) {
+ yasm_insn_operand *op = parse_operand(parser_gas);
+ if (!op) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expression syntax error"));
+ yasm_bc_destroy(bc);
+ return NULL;
+ }
+ yasm_insn_ops_append(insn, op);
+
+ if (is_eol())
+ break;
+ if (!expect(',')) {
+ yasm_bc_destroy(bc);
+ return NULL;
+ }
+ get_next_token();
+ }
+ return bc;
+ }
+ case YASM_ARCH_PREFIX:
+ /* Propagate errors in case we got a warning from the arch */
+ yasm_errwarn_propagate(parser_gas->errwarns, cur_line);
+
+ yasm_xfree(id);
+ get_next_token(); /* ID */
+ bc = parse_instr(parser_gas);
+ if (!bc)
+ bc = yasm_arch_create_empty_insn(p_object->arch, cur_line);
+ yasm_insn_add_prefix(yasm_bc_get_insn(bc), prefix);
+ return bc;
+ default:
+ break;
+ }
+
+ /* Check for segment register used as prefix */
+ switch (yasm_arch_parse_check_regtmod(p_object->arch, ID_val, ID_len,
+ &prefix)) {
+ case YASM_ARCH_SEGREG:
+ yasm_xfree(id);
+ get_next_token(); /* ID */
+ bc = parse_instr(parser_gas);
+ if (!bc)
+ bc = yasm_arch_create_empty_insn(p_object->arch, cur_line);
+ yasm_insn_add_seg_prefix(yasm_bc_get_insn(bc), prefix);
+ return bc;
+ default:
+ return NULL;
+ }
+}
+
+static int
+parse_dirvals(yasm_parser_gas *parser_gas, yasm_valparamhead *vps)
+{
+ yasm_valparam *vp;
+ yasm_expr *e;
+ int num = 0;
+
+ yasm_vps_initialize(vps);
+
+ for (;;) {
+ switch (curtok) {
+ case ID:
+ get_peek_token(parser_gas);
+ switch (parser_gas->peek_token) {
+ case '+': case '-':
+ case '|': case '^': case '&': case '!':
+ case '*': case '/': case '%': case LEFT_OP: case RIGHT_OP:
+ e = parse_expr(parser_gas);
+ vp = yasm_vp_create_expr(NULL, e);
+ break;
+ default:
+ /* Just an ID */
+ vp = yasm_vp_create_id(NULL, ID_val, '\0');
+ get_next_token(); /* ID */
+ break;
+ }
+ break;
+ case STRING:
+ vp = yasm_vp_create_string(NULL, STRING_val.contents);
+ get_next_token(); /* STRING */
+ break;
+ case REG:
+ e = p_expr_new_ident(yasm_expr_reg(REG_val));
+ vp = yasm_vp_create_expr(NULL, e);
+ get_next_token(); /* REG */
+ break;
+ case '@':
+ /* XXX: is throwing it away *really* the right thing? */
+ get_next_token(); /* @ */
+ continue;
+ default:
+ e = parse_expr(parser_gas);
+ if (!e)
+ return num;
+ vp = yasm_vp_create_expr(NULL, e);
+ break;
+ }
+ yasm_vps_append(vps, vp);
+ num++;
+ if (curtok == ',')
+ get_next_token(); /* ',' */
+ }
+ return num;
+}
+
+static int
+parse_datavals(yasm_parser_gas *parser_gas, yasm_datavalhead *dvs)
+{
+ yasm_expr *e;
+ yasm_dataval *dv;
+ int num = 0;
+
+ yasm_dvs_initialize(dvs);
+
+ for (;;) {
+ e = parse_expr(parser_gas);
+ if (!e) {
+ yasm_dvs_delete(dvs);
+ yasm_dvs_initialize(dvs);
+ return 0;
+ }
+ dv = yasm_dv_create_expr(e);
+ yasm_dvs_append(dvs, dv);
+ num++;
+ if (curtok != ',')
+ break;
+ get_next_token(); /* ',' */
+ }
+ return num;
+}
+
+static int
+parse_strvals(yasm_parser_gas *parser_gas, yasm_datavalhead *dvs)
+{
+ yasm_dataval *dv;
+ int num = 0;
+
+ yasm_dvs_initialize(dvs);
+
+ for (;;) {
+ if (!expect(STRING)) {
+ yasm_dvs_delete(dvs);
+ yasm_dvs_initialize(dvs);
+ return 0;
+ }
+ dv = yasm_dv_create_string(STRING_val.contents, STRING_val.len);
+ yasm_dvs_append(dvs, dv);
+ get_next_token(); /* STRING */
+ num++;
+ if (curtok != ',')
+ break;
+ get_next_token(); /* ',' */
+ }
+ return num;
+}
+
+/* instruction operands */
+/* memory addresses */
+static yasm_effaddr *
+parse_memaddr(yasm_parser_gas *parser_gas)
+{
+ yasm_effaddr *ea = NULL;
+ yasm_expr *e1, *e2;
+ int strong = 0;
+
+ if (curtok == SEGREG) {
+ uintptr_t segreg = SEGREG_val;
+ get_next_token(); /* SEGREG */
+ if (!expect(':')) return NULL;
+ get_next_token(); /* ':' */
+ ea = parse_memaddr(parser_gas);
+ if (!ea)
+ return NULL;
+ yasm_ea_set_segreg(ea, segreg);
+ return ea;
+ }
+
+ /* We want to parse a leading expression, except when it's actually
+ * just a memory address (with no preceding expression) such as
+ * (REG...) or (,...).
+ */
+ get_peek_token(parser_gas);
+ if (curtok != '(' || (parser_gas->peek_token != REG
+ && parser_gas->peek_token != ','))
+ e1 = parse_expr(parser_gas);
+ else
+ e1 = NULL;
+
+ if (curtok == '(') {
+ int havereg = 0;
+ uintptr_t reg = 0;
+ yasm_intnum *scale = NULL;
+
+ get_next_token(); /* '(' */
+
+ /* base register */
+ if (curtok == REG) {
+ e2 = p_expr_new_ident(yasm_expr_reg(REG_val));
+ get_next_token(); /* REG */
+ } else
+ e2 = p_expr_new_ident(yasm_expr_int(yasm_intnum_create_uint(0)));
+
+ if (curtok == ')')
+ goto done;
+
+ if (!expect(',')) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid memory expression"));
+ if (e1) yasm_expr_destroy(e1);
+ yasm_expr_destroy(e2);
+ return NULL;
+ }
+ get_next_token(); /* ',' */
+
+ if (curtok == ')')
+ goto done;
+
+ /* index register */
+ if (curtok == REG) {
+ reg = REG_val;
+ havereg = 1;
+ get_next_token(); /* REG */
+ if (curtok != ',') {
+ scale = yasm_intnum_create_uint(1);
+ goto done;
+ }
+ get_next_token(); /* ',' */
+ }
+
+ /* scale */
+ if (!expect(INTNUM)) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("non-integer scale"));
+ if (e1) yasm_expr_destroy(e1);
+ yasm_expr_destroy(e2);
+ return NULL;
+ }
+ scale = INTNUM_val;
+ get_next_token(); /* INTNUM */
+
+done:
+ if (!expect(')')) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid memory expression"));
+ if (scale) yasm_intnum_destroy(scale);
+ if (e1) yasm_expr_destroy(e1);
+ yasm_expr_destroy(e2);
+ return NULL;
+ }
+ get_next_token(); /* ')' */
+
+ if (scale) {
+ if (!havereg) {
+ if (yasm_intnum_get_uint(scale) != 1)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("scale factor of %u without an index register"),
+ yasm_intnum_get_uint(scale));
+ yasm_intnum_destroy(scale);
+ } else
+ e2 = p_expr_new(yasm_expr_expr(e2), YASM_EXPR_ADD,
+ yasm_expr_expr(p_expr_new(yasm_expr_reg(reg), YASM_EXPR_MUL,
+ yasm_expr_int(scale))));
+ }
+
+ if (e1) {
+ /* Ordering is critical here to correctly detecting presence of
+ * RIP in RIP-relative expressions.
+ */
+ e1 = p_expr_new_tree(e2, YASM_EXPR_ADD, e1);
+ } else
+ e1 = e2;
+ strong = 1;
+ }
+
+ if (!e1)
+ return NULL;
+ ea = yasm_arch_ea_create(p_object->arch, e1);
+ if (strong)
+ ea->strong = 1;
+ return ea;
+}
+
+static yasm_insn_operand *
+parse_operand(yasm_parser_gas *parser_gas)
+{
+ yasm_effaddr *ea;
+ yasm_insn_operand *op;
+ uintptr_t reg;
+
+ switch (curtok) {
+ case REG:
+ reg = REG_val;
+ get_next_token(); /* REG */
+ return yasm_operand_create_reg(reg);
+ case SEGREG:
+ /* need to see if it's really a memory address */
+ get_peek_token(parser_gas);
+ if (parser_gas->peek_token == ':') {
+ ea = parse_memaddr(parser_gas);
+ if (!ea)
+ return NULL;
+ return yasm_operand_create_mem(ea);
+ }
+ reg = SEGREG_val;
+ get_next_token(); /* SEGREG */
+ return yasm_operand_create_segreg(reg);
+ case REGGROUP:
+ {
+ unsigned long regindex;
+ reg = REGGROUP_val;
+ get_next_token(); /* REGGROUP */
+ if (curtok != '(')
+ return yasm_operand_create_reg(reg);
+ get_next_token(); /* '(' */
+ if (!expect(INTNUM)) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("integer register index expected"));
+ return NULL;
+ }
+ regindex = yasm_intnum_get_uint(INTNUM_val);
+ get_next_token(); /* INTNUM */
+ if (!expect(')')) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("missing closing parenthesis for register index"));
+ return NULL;
+ }
+ get_next_token(); /* ')' */
+ reg = yasm_arch_reggroup_get_reg(p_object->arch, reg, regindex);
+ if (reg == 0) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("bad register index `%u'"),
+ regindex);
+ return NULL;
+ }
+ return yasm_operand_create_reg(reg);
+ }
+ case '$':
+ {
+ yasm_expr *e;
+ get_next_token(); /* '$' */
+ e = parse_expr(parser_gas);
+ if (!e) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expression missing after `%s'"), "$");
+ return NULL;
+ }
+ return yasm_operand_create_imm(e);
+ }
+ case '*':
+ get_next_token(); /* '*' */
+ if (curtok == REG) {
+ op = yasm_operand_create_reg(REG_val);
+ get_next_token(); /* REG */
+ } else {
+ ea = parse_memaddr(parser_gas);
+ if (!ea) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expression missing after `%s'"), "*");
+ return NULL;
+ }
+ op = yasm_operand_create_mem(ea);
+ }
+ op->deref = 1;
+ return op;
+ default:
+ ea = parse_memaddr(parser_gas);
+ if (!ea)
+ return NULL;
+ return yasm_operand_create_mem(ea);
+ }
+}
+
+/* Expression grammar parsed is:
+ *
+ * expr : expr0 [ {+,-} expr0...]
+ * expr0 : expr1 [ {|,^,&,!} expr1...]
+ * expr1 : expr2 [ {*,/,%,<<,>>} expr2...]
+ * expr2 : { ~,+,- } expr2
+ * | (expr)
+ * | symbol
+ * | number
+ */
+
+static yasm_expr *
+parse_expr(yasm_parser_gas *parser_gas)
+{
+ yasm_expr *e, *f;
+ e = parse_expr0(parser_gas);
+ if (!e)
+ return NULL;
+
+ while (curtok == '+' || curtok == '-') {
+ int op = curtok;
+ get_next_token();
+ f = parse_expr0(parser_gas);
+ if (!f) {
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+
+ switch (op) {
+ case '+': e = p_expr_new_tree(e, YASM_EXPR_ADD, f); break;
+ case '-': e = p_expr_new_tree(e, YASM_EXPR_SUB, f); break;
+ }
+ }
+ return e;
+}
+
+static yasm_expr *
+parse_expr0(yasm_parser_gas *parser_gas)
+{
+ yasm_expr *e, *f;
+ e = parse_expr1(parser_gas);
+ if (!e)
+ return NULL;
+
+ while (curtok == '|' || curtok == '^' || curtok == '&' || curtok == '!') {
+ int op = curtok;
+ get_next_token();
+ f = parse_expr1(parser_gas);
+ if (!f) {
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+
+ switch (op) {
+ case '|': e = p_expr_new_tree(e, YASM_EXPR_OR, f); break;
+ case '^': e = p_expr_new_tree(e, YASM_EXPR_XOR, f); break;
+ case '&': e = p_expr_new_tree(e, YASM_EXPR_AND, f); break;
+ case '!': e = p_expr_new_tree(e, YASM_EXPR_NOR, f); break;
+ }
+ }
+ return e;
+}
+
+static yasm_expr *
+parse_expr1(yasm_parser_gas *parser_gas)
+{
+ yasm_expr *e, *f;
+ e = parse_expr2(parser_gas);
+ if (!e)
+ return NULL;
+
+ while (curtok == '*' || curtok == '/' || curtok == '%' || curtok == LEFT_OP
+ || curtok == RIGHT_OP) {
+ int op = curtok;
+ get_next_token();
+ f = parse_expr2(parser_gas);
+ if (!f) {
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+
+ switch (op) {
+ case '*': e = p_expr_new_tree(e, YASM_EXPR_MUL, f); break;
+ case '/': e = p_expr_new_tree(e, YASM_EXPR_DIV, f); break;
+ case '%': e = p_expr_new_tree(e, YASM_EXPR_MOD, f); break;
+ case LEFT_OP: e = p_expr_new_tree(e, YASM_EXPR_SHL, f); break;
+ case RIGHT_OP: e = p_expr_new_tree(e, YASM_EXPR_SHR, f); break;
+ }
+ }
+ return e;
+}
+
+static yasm_expr *
+parse_expr2(yasm_parser_gas *parser_gas)
+{
+ yasm_expr *e;
+ yasm_symrec *sym;
+
+ switch (curtok) {
+ case '+':
+ get_next_token();
+ return parse_expr2(parser_gas);
+ case '-':
+ get_next_token();
+ e = parse_expr2(parser_gas);
+ if (!e)
+ return NULL;
+ return p_expr_new_branch(YASM_EXPR_NEG, e);
+ case '~':
+ get_next_token();
+ e = parse_expr2(parser_gas);
+ if (!e)
+ return NULL;
+ return p_expr_new_branch(YASM_EXPR_NOT, e);
+ case '(':
+ get_next_token();
+ e = parse_expr(parser_gas);
+ if (!e)
+ return NULL;
+ if (!expect(')')) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("missing parenthesis"));
+ return NULL;
+ }
+ get_next_token();
+ return e;
+ case INTNUM:
+ e = p_expr_new_ident(yasm_expr_int(INTNUM_val));
+ get_next_token();
+ return e;
+ case FLTNUM:
+ e = p_expr_new_ident(yasm_expr_float(FLTNUM_val));
+ get_next_token();
+ return e;
+ case ID:
+ {
+ char *name = ID_val;
+ get_next_token(); /* ID */
+
+ /* "." references the current assembly position */
+ if (name[1] == '\0' && name[0] == '.')
+ sym = yasm_symtab_define_curpos(p_symtab, ".",
+ parser_gas->prev_bc, cur_line);
+ else
+ sym = yasm_symtab_use(p_symtab, name, cur_line);
+ yasm_xfree(name);
+
+ if (curtok == '@') {
+ yasm_symrec *wrt;
+ /* TODO: this is needed for shared objects, e.g. sym@PLT */
+ get_next_token(); /* '@' */
+ if (!expect(ID)) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected identifier after `@'"));
+ return NULL;
+ }
+ wrt = yasm_objfmt_get_special_sym(p_object, ID_val, "gas");
+ yasm_xfree(ID_val);
+ get_next_token(); /* ID */
+ if (!wrt) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("unrecognized identifier after `@'"));
+ return p_expr_new_ident(yasm_expr_sym(sym));
+ }
+ return p_expr_new(yasm_expr_sym(sym), YASM_EXPR_WRT,
+ yasm_expr_sym(wrt));
+ }
+
+ return p_expr_new_ident(yasm_expr_sym(sym));
+ }
+ default:
+ return NULL;
+ }
+}
+
+static void
+define_label(yasm_parser_gas *parser_gas, char *name, int local)
+{
+ if (!local) {
+ if (parser_gas->locallabel_base)
+ yasm_xfree(parser_gas->locallabel_base);
+ parser_gas->locallabel_base_len = strlen(name);
+ parser_gas->locallabel_base =
+ yasm_xmalloc(parser_gas->locallabel_base_len+1);
+ strcpy(parser_gas->locallabel_base, name);
+ }
+
+ yasm_symtab_define_label(p_symtab, name, parser_gas->prev_bc, 1,
+ cur_line);
+ yasm_xfree(name);
+}
+
+static void
+define_lcomm(yasm_parser_gas *parser_gas, /*@only@*/ char *name,
+ yasm_expr *size, /*@null@*/ yasm_expr *align)
+{
+ /* Put into .bss section. */
+ /*@dependent@*/ yasm_section *bss =
+ gas_get_section(parser_gas, yasm__xstrdup(".bss"), NULL, NULL, NULL, 1);
+
+ if (align) {
+ /* XXX: assume alignment is in bytes, not power-of-two */
+ yasm_section_bcs_append(bss, gas_parser_align(parser_gas, bss, align,
+ NULL, NULL, 0));
+ }
+
+ yasm_symtab_define_label(p_symtab, name, yasm_section_bcs_last(bss), 1,
+ cur_line);
+ yasm_section_bcs_append(bss, yasm_bc_create_reserve(size, 1, cur_line));
+ yasm_xfree(name);
+}
+
+static yasm_section *
+gas_get_section(yasm_parser_gas *parser_gas, char *name,
+ /*@null@*/ char *flags, /*@null@*/ char *type,
+ /*@null@*/ yasm_valparamhead *objext_valparams,
+ int builtin)
+{
+ yasm_valparamhead vps;
+ yasm_valparam *vp;
+ char *gasflags;
+ yasm_section *new_section;
+
+ yasm_vps_initialize(&vps);
+ vp = yasm_vp_create_id(NULL, name, '\0');
+ yasm_vps_append(&vps, vp);
+
+ if (!builtin) {
+ if (flags)
+ gasflags = yasm__xstrdup(flags);
+ else
+ gasflags = yasm__xstrdup("");
+ vp = yasm_vp_create_string(yasm__xstrdup("gasflags"), gasflags);
+ yasm_vps_append(&vps, vp);
+ if (type) {
+ vp = yasm_vp_create_id(NULL, type, '\0');
+ yasm_vps_append(&vps, vp);
+ }
+ }
+
+ new_section = yasm_objfmt_section_switch(p_object, &vps, objext_valparams,
+ cur_line);
+
+ yasm_vps_delete(&vps);
+ return new_section;
+}
+
+static void
+gas_switch_section(yasm_parser_gas *parser_gas, const char *name,
+ /*@null@*/ char *flags, /*@null@*/ char *type,
+ /*@null@*/ yasm_valparamhead *objext_valparams,
+ int builtin)
+{
+ yasm_section *new_section;
+
+ new_section = gas_get_section(parser_gas, yasm__xstrdup(name), flags, type,
+ objext_valparams, builtin);
+ if (new_section) {
+ cursect = new_section;
+ parser_gas->prev_bc = yasm_section_bcs_last(new_section);
+ } else
+ yasm_error_set(YASM_ERROR_GENERAL, N_("invalid section name `%s'"),
+ name);
+
+ if (objext_valparams)
+ yasm_vps_delete(objext_valparams);
+}
+
+static yasm_bytecode *
+gas_parser_align(yasm_parser_gas *parser_gas, yasm_section *sect,
+ yasm_expr *boundval, /*@null@*/ yasm_expr *fillval,
+ /*@null@*/ yasm_expr *maxskipval, int power2)
+{
+ yasm_intnum *boundintn;
+
+ /* Convert power of two to number of bytes if necessary */
+ if (power2)
+ boundval = yasm_expr_create(YASM_EXPR_SHL,
+ yasm_expr_int(yasm_intnum_create_uint(1)),
+ yasm_expr_expr(boundval), cur_line);
+
+ /* Largest .align in the section specifies section alignment. */
+ boundintn = yasm_expr_get_intnum(&boundval, 0);
+ if (boundintn) {
+ unsigned long boundint = yasm_intnum_get_uint(boundintn);
+
+ /* Alignments must be a power of two. */
+ if (is_exp2(boundint)) {
+ if (boundint > yasm_section_get_align(sect))
+ yasm_section_set_align(sect, boundint, cur_line);
+ }
+ }
+
+ return yasm_bc_create_align(boundval, fillval, maxskipval,
+ yasm_section_is_code(sect) ?
+ yasm_arch_get_fill(p_object->arch) : NULL,
+ cur_line);
+}
+
+static yasm_bytecode *
+gas_parser_dir_fill(yasm_parser_gas *parser_gas, /*@only@*/ yasm_expr *repeat,
+ /*@only@*/ /*@null@*/ yasm_expr *size,
+ /*@only@*/ /*@null@*/ yasm_expr *value)
+{
+ yasm_datavalhead dvs;
+ yasm_bytecode *bc;
+ unsigned int ssize;
+
+ if (size) {
+ /*@dependent@*/ /*@null@*/ yasm_intnum *intn;
+ intn = yasm_expr_get_intnum(&size, 0);
+ if (!intn) {
+ yasm_error_set(YASM_ERROR_NOT_ABSOLUTE,
+ N_("size must be an absolute expression"));
+ yasm_expr_destroy(repeat);
+ yasm_expr_destroy(size);
+ if (value)
+ yasm_expr_destroy(value);
+ return NULL;
+ }
+ ssize = yasm_intnum_get_uint(intn);
+ } else
+ ssize = 1;
+
+ if (!value)
+ value = yasm_expr_create_ident(
+ yasm_expr_int(yasm_intnum_create_uint(0)), cur_line);
+
+ yasm_dvs_initialize(&dvs);
+ yasm_dvs_append(&dvs, yasm_dv_create_expr(value));
+ bc = yasm_bc_create_data(&dvs, ssize, 0, p_object->arch, cur_line);
+
+ yasm_bc_set_multiple(bc, repeat);
+
+ return bc;
+}
+
+static dir_lookup dirs_static[] = {
+ /* FIXME: Whether this is power-of-two or not depends on arch and objfmt. */
+ {".align", dir_align, 0, INITIAL},
+ {".p2align", dir_align, 1, INITIAL},
+ {".balign", dir_align, 0, INITIAL},
+ {".org", dir_org, 0, INITIAL},
+ /* data visibility directives */
+ {".local", dir_local, 0, INITIAL},
+ {".comm", dir_comm, 0, INITIAL},
+ {".lcomm", dir_comm, 1, INITIAL},
+ /* integer data declaration directives */
+ {".byte", dir_data, 1, INITIAL},
+ {".2byte", dir_data, 2, INITIAL},
+ {".4byte", dir_data, 4, INITIAL},
+ {".8byte", dir_data, 8, INITIAL},
+ {".16byte", dir_data, 16, INITIAL},
+ /* TODO: These should depend on arch */
+ {".short", dir_data, 2, INITIAL},
+ {".int", dir_data, 4, INITIAL},
+ {".long", dir_data, 4, INITIAL},
+ {".hword", dir_data, 2, INITIAL},
+ {".quad", dir_data, 8, INITIAL},
+ {".octa", dir_data, 16, INITIAL},
+ /* XXX: At least on x86, this is 2 bytes */
+ {".value", dir_data, 2, INITIAL},
+ /* ASCII data declaration directives */
+ {".ascii", dir_ascii, 0, INITIAL}, /* no terminating zero */
+ {".asciz", dir_ascii, 1, INITIAL}, /* add terminating zero */
+ {".string", dir_ascii, 1, INITIAL}, /* add terminating zero */
+ /* LEB128 integer data declaration directives */
+ {".sleb128", dir_leb128, 1, INITIAL}, /* signed */
+ {".uleb128", dir_leb128, 0, INITIAL}, /* unsigned */
+ /* floating point data declaration directives */
+ {".float", dir_data, 4, INITIAL},
+ {".single", dir_data, 4, INITIAL},
+ {".double", dir_data, 8, INITIAL},
+ {".tfloat", dir_data, 10, INITIAL},
+ /* section directives */
+ {".bss", dir_bss_section, 0, INITIAL},
+ {".data", dir_data_section, 0, INITIAL},
+ {".text", dir_text_section, 0, INITIAL},
+ {".section", dir_section, 0, SECTION_DIRECTIVE},
+ /* empty space/fill directives */
+ {".skip", dir_skip, 0, INITIAL},
+ {".space", dir_skip, 0, INITIAL},
+ {".fill", dir_fill, 0, INITIAL},
+ {".zero", dir_zero, 0, INITIAL},
+ /* syntax directives */
+ {".intel_syntax", dir_intel_syntax, 0, INITIAL},
+ {".att_syntax", dir_att_syntax, 0, INITIAL},
+ /* other directives */
+ {".equ", dir_equ, 0, INITIAL},
+ {".file", dir_file, 0, INITIAL},
+ {".line", dir_line, 0, INITIAL},
+ {".set", dir_equ, 0, INITIAL}
+};
+
+static void
+no_delete(void *data)
+{
+}
+
+void
+gas_parser_parse(yasm_parser_gas *parser_gas)
+{
+ dir_lookup word;
+ unsigned int i;
+ int replace = 1;
+
+ word.name = ".word";
+ word.handler = dir_data;
+ word.param = yasm_arch_wordsize(p_object->arch)/8;
+ word.newstate = INITIAL;
+
+ /* Create directive lookup */
+ parser_gas->dirs = HAMT_create(1, yasm_internal_error_);
+ HAMT_insert(parser_gas->dirs, word.name, &word, &replace, no_delete);
+ for (i=0; i<NELEMS(dirs_static); i++) {
+ replace = 1;
+ HAMT_insert(parser_gas->dirs, dirs_static[i].name,
+ &dirs_static[i], &replace, no_delete);
+ }
+
+ while (get_next_token() != 0) {
+ yasm_bytecode *bc = NULL, *temp_bc;
+
+ if (!is_eol()) {
+ bc = parse_line(parser_gas);
+ demand_eol();
+ }
+
+ yasm_errwarn_propagate(parser_gas->errwarns, cur_line);
+
+ temp_bc = yasm_section_bcs_append(cursect, bc);
+ if (temp_bc)
+ parser_gas->prev_bc = temp_bc;
+ if (curtok == ';')
+ continue; /* don't advance line number until \n */
+ if (parser_gas->save_input)
+ yasm_linemap_add_source(parser_gas->linemap,
+ temp_bc,
+ (char *)parser_gas->save_line[parser_gas->save_last ^ 1]);
+ yasm_linemap_goto_next(parser_gas->linemap);
+ parser_gas->dir_line++; /* keep track for .line followed by .file */
+ }
+
+ HAMT_destroy(parser_gas->dirs, no_delete);
+}
diff --git a/contrib/tools/yasm/modules/parsers/gas/gas-parser.c b/contrib/tools/yasm/modules/parsers/gas/gas-parser.c
index 9189b1fa08..088bcdad0a 100644
--- a/contrib/tools/yasm/modules/parsers/gas/gas-parser.c
+++ b/contrib/tools/yasm/modules/parsers/gas/gas-parser.c
@@ -1,133 +1,133 @@
-/*
- * GAS-compatible parser
- *
- * 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.
- * 3. Neither the name of the author nor the names of other contributors
- * may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * 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>
-
-#include "gas-parser.h"
-
-
-static void
-gas_parser_do_parse(yasm_object *object, yasm_preproc *pp,
- int save_input, yasm_linemap *linemap,
- yasm_errwarns *errwarns)
-{
- yasm_parser_gas parser_gas;
- int i;
-
- parser_gas.object = object;
- parser_gas.linemap = linemap;
-
- parser_gas.locallabel_base = (char *)NULL;
- parser_gas.locallabel_base_len = 0;
-
- parser_gas.dir_fileline = 0;
- parser_gas.dir_file = NULL;
- parser_gas.dir_line = 0;
- parser_gas.seen_line_marker = 0;
-
- parser_gas.preproc = pp;
- parser_gas.errwarns = errwarns;
-
- parser_gas.prev_bc = yasm_section_bcs_first(object->cur_section);
-
- parser_gas.save_input = save_input;
- parser_gas.save_last = 0;
-
- parser_gas.peek_token = NONE;
-
- parser_gas.line = NULL;
-
- /* initialize scanner structure */
- yasm_scanner_initialize(&parser_gas.s);
-
- parser_gas.state = INITIAL;
-
- for (i=0; i<10; i++)
- parser_gas.local[i] = 0;
-
- parser_gas.intel_syntax = 0;
-
- parser_gas.is_cpp_preproc =
- yasm__strcasecmp(((yasm_preproc_base*)pp)->module->keyword, "cpp") == 0;
- parser_gas.is_nasm_preproc =
- yasm__strcasecmp(((yasm_preproc_base*)pp)->module->keyword, "nasm") == 0;
-
- gas_parser_parse(&parser_gas);
-
- /* Check for ending inside a comment */
- if (parser_gas.state == COMMENT) {
- yasm_warn_set(YASM_WARN_GENERAL, N_("end of file in comment"));
- /* XXX: Minus two to compensate for already having moved past the EOF
- * in the linemap.
- */
- yasm_errwarn_propagate(errwarns,
- yasm_linemap_get_current(parser_gas.linemap)-2);
- }
-
- yasm_scanner_delete(&parser_gas.s);
-
- /* Free locallabel base if necessary */
- if (parser_gas.locallabel_base)
- yasm_xfree(parser_gas.locallabel_base);
-
- if (parser_gas.dir_file)
- yasm_xfree(parser_gas.dir_file);
-
- /* Convert all undefined symbols into extern symbols */
- yasm_symtab_parser_finalize(object->symtab, 1, errwarns);
-}
-
-/* Define valid preprocessors to use with this parser */
-static const char *gas_parser_preproc_keywords[] = {
- "gas",
- "raw",
- "cpp",
- "nasm",
- NULL
-};
-
-/* Define parser structure -- see parser.h for details */
-yasm_parser_module yasm_gas_LTX_parser = {
- "GNU AS (GAS)-compatible parser",
- "gas",
- gas_parser_preproc_keywords,
- "gas",
- NULL, /* No standard macros */
- gas_parser_do_parse
-};
-yasm_parser_module yasm_gnu_LTX_parser = {
- "GNU AS (GAS)-compatible parser",
- "gnu",
- gas_parser_preproc_keywords,
- "gas",
- NULL, /* No standard macros */
- gas_parser_do_parse
-};
+/*
+ * GAS-compatible parser
+ *
+ * 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.
+ * 3. Neither the name of the author nor the names of other contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 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>
+
+#include "gas-parser.h"
+
+
+static void
+gas_parser_do_parse(yasm_object *object, yasm_preproc *pp,
+ int save_input, yasm_linemap *linemap,
+ yasm_errwarns *errwarns)
+{
+ yasm_parser_gas parser_gas;
+ int i;
+
+ parser_gas.object = object;
+ parser_gas.linemap = linemap;
+
+ parser_gas.locallabel_base = (char *)NULL;
+ parser_gas.locallabel_base_len = 0;
+
+ parser_gas.dir_fileline = 0;
+ parser_gas.dir_file = NULL;
+ parser_gas.dir_line = 0;
+ parser_gas.seen_line_marker = 0;
+
+ parser_gas.preproc = pp;
+ parser_gas.errwarns = errwarns;
+
+ parser_gas.prev_bc = yasm_section_bcs_first(object->cur_section);
+
+ parser_gas.save_input = save_input;
+ parser_gas.save_last = 0;
+
+ parser_gas.peek_token = NONE;
+
+ parser_gas.line = NULL;
+
+ /* initialize scanner structure */
+ yasm_scanner_initialize(&parser_gas.s);
+
+ parser_gas.state = INITIAL;
+
+ for (i=0; i<10; i++)
+ parser_gas.local[i] = 0;
+
+ parser_gas.intel_syntax = 0;
+
+ parser_gas.is_cpp_preproc =
+ yasm__strcasecmp(((yasm_preproc_base*)pp)->module->keyword, "cpp") == 0;
+ parser_gas.is_nasm_preproc =
+ yasm__strcasecmp(((yasm_preproc_base*)pp)->module->keyword, "nasm") == 0;
+
+ gas_parser_parse(&parser_gas);
+
+ /* Check for ending inside a comment */
+ if (parser_gas.state == COMMENT) {
+ yasm_warn_set(YASM_WARN_GENERAL, N_("end of file in comment"));
+ /* XXX: Minus two to compensate for already having moved past the EOF
+ * in the linemap.
+ */
+ yasm_errwarn_propagate(errwarns,
+ yasm_linemap_get_current(parser_gas.linemap)-2);
+ }
+
+ yasm_scanner_delete(&parser_gas.s);
+
+ /* Free locallabel base if necessary */
+ if (parser_gas.locallabel_base)
+ yasm_xfree(parser_gas.locallabel_base);
+
+ if (parser_gas.dir_file)
+ yasm_xfree(parser_gas.dir_file);
+
+ /* Convert all undefined symbols into extern symbols */
+ yasm_symtab_parser_finalize(object->symtab, 1, errwarns);
+}
+
+/* Define valid preprocessors to use with this parser */
+static const char *gas_parser_preproc_keywords[] = {
+ "gas",
+ "raw",
+ "cpp",
+ "nasm",
+ NULL
+};
+
+/* Define parser structure -- see parser.h for details */
+yasm_parser_module yasm_gas_LTX_parser = {
+ "GNU AS (GAS)-compatible parser",
+ "gas",
+ gas_parser_preproc_keywords,
+ "gas",
+ NULL, /* No standard macros */
+ gas_parser_do_parse
+};
+yasm_parser_module yasm_gnu_LTX_parser = {
+ "GNU AS (GAS)-compatible parser",
+ "gnu",
+ gas_parser_preproc_keywords,
+ "gas",
+ NULL, /* No standard macros */
+ gas_parser_do_parse
+};
diff --git a/contrib/tools/yasm/modules/parsers/gas/gas-parser.h b/contrib/tools/yasm/modules/parsers/gas/gas-parser.h
index 86164f78de..99659e964a 100644
--- a/contrib/tools/yasm/modules/parsers/gas/gas-parser.h
+++ b/contrib/tools/yasm/modules/parsers/gas/gas-parser.h
@@ -1,163 +1,163 @@
-/*
- * GAS-compatible parser header file
- *
- * 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.
- * 3. Neither the name of the author nor the names of other contributors
- * may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * 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_GAS_PARSER_H
-#define YASM_GAS_PARSER_H
-
-#define YYCTYPE unsigned char
-
-#define MAX_SAVED_LINE_LEN 80
-
-enum tokentype {
- INTNUM = 258,
- FLTNUM,
- STRING,
- REG,
- REGGROUP,
- SEGREG,
- TARGETMOD,
- LEFT_OP,
- RIGHT_OP,
- ID,
- LABEL,
- CPP_LINE_MARKER,
- NASM_LINE_MARKER,
- NONE
-};
-
-typedef union {
- unsigned int int_info;
- yasm_intnum *intn;
- yasm_floatnum *flt;
- yasm_bytecode *bc;
- uintptr_t arch_data;
- struct {
- char *contents;
- size_t len;
- } str;
-} yystype;
-#define YYSTYPE yystype
-
-enum gas_parser_state {
- INITIAL,
- COMMENT,
- SECTION_DIRECTIVE,
- NASM_FILENAME
-};
-
-typedef struct yasm_parser_gas {
- /*@only@*/ yasm_object *object;
-
- /* last "base" label for local (.) labels */
- /*@null@*/ char *locallabel_base;
- size_t locallabel_base_len;
-
- /* .line/.file: we have to see both to start setting linemap versions */
- int dir_fileline;
- /*@null@*/ char *dir_file;
- unsigned long dir_line;
-
- /* Have we seen a line marker? */
- int seen_line_marker;
-
- /*@dependent@*/ yasm_preproc *preproc;
- /*@dependent@*/ yasm_errwarns *errwarns;
-
- /*@dependent@*/ yasm_linemap *linemap;
-
- /*@null@*/ yasm_bytecode *prev_bc;
- yasm_bytecode *temp_bc;
-
- int save_input;
- YYCTYPE save_line[2][MAX_SAVED_LINE_LEN];
- int save_last;
-
- /* Line data storage used in preproc_input(). */
- char *line, *linepos;
- size_t lineleft;
-
- yasm_scanner s;
- enum gas_parser_state state;
-
- int token; /* enum tokentype or any character */
- yystype tokval;
- char tokch; /* first character of token */
-
- /* one token of lookahead; used sparingly */
- int peek_token; /* NONE if none */
- yystype peek_tokval;
- char peek_tokch;
-
- /* Index of local labels; what's stored here is the /next/ index,
- * so these are all 0 at start.
- */
- unsigned long local[10];
-
- /* Parser-handled directives HAMT lookup */
- HAMT *dirs;
-
- int intel_syntax;
-
- int is_nasm_preproc;
- int is_cpp_preproc;
-} yasm_parser_gas;
-
-/* shorter access names to commonly used parser_gas fields */
-#define p_object (parser_gas->object)
-#define p_symtab (parser_gas->object->symtab)
-#define cursect (parser_gas->object->cur_section)
-#define curtok (parser_gas->token)
-#define curval (parser_gas->tokval)
-
-#define INTNUM_val (curval.intn)
-#define FLTNUM_val (curval.flt)
-#define STRING_val (curval.str)
-#define REG_val (curval.arch_data)
-#define REGGROUP_val (curval.arch_data)
-#define SEGREG_val (curval.arch_data)
-#define TARGETMOD_val (curval.arch_data)
-#define ID_val (curval.str.contents)
-#define ID_len (curval.str.len)
-#define LABEL_val (curval.str.contents)
-#define LABEL_len (curval.str.len)
-
-#define cur_line (yasm_linemap_get_current(parser_gas->linemap))
-
-#define p_expr_new(l,o,r) yasm_expr_create(o,l,r,cur_line)
-#define p_expr_new_tree(l,o,r) yasm_expr_create_tree(l,o,r,cur_line)
-#define p_expr_new_branch(o,r) yasm_expr_create_branch(o,r,cur_line)
-#define p_expr_new_ident(r) yasm_expr_create_ident(r,cur_line)
-
-yasm_bytecode *parse_instr_intel(yasm_parser_gas *parser_gas);
-
-void gas_parser_parse(yasm_parser_gas *parser_gas);
-void gas_parser_cleanup(yasm_parser_gas *parser_gas);
-int gas_parser_lex(YYSTYPE *lvalp, yasm_parser_gas *parser_gas);
-
-#endif
+/*
+ * GAS-compatible parser header file
+ *
+ * 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.
+ * 3. Neither the name of the author nor the names of other contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 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_GAS_PARSER_H
+#define YASM_GAS_PARSER_H
+
+#define YYCTYPE unsigned char
+
+#define MAX_SAVED_LINE_LEN 80
+
+enum tokentype {
+ INTNUM = 258,
+ FLTNUM,
+ STRING,
+ REG,
+ REGGROUP,
+ SEGREG,
+ TARGETMOD,
+ LEFT_OP,
+ RIGHT_OP,
+ ID,
+ LABEL,
+ CPP_LINE_MARKER,
+ NASM_LINE_MARKER,
+ NONE
+};
+
+typedef union {
+ unsigned int int_info;
+ yasm_intnum *intn;
+ yasm_floatnum *flt;
+ yasm_bytecode *bc;
+ uintptr_t arch_data;
+ struct {
+ char *contents;
+ size_t len;
+ } str;
+} yystype;
+#define YYSTYPE yystype
+
+enum gas_parser_state {
+ INITIAL,
+ COMMENT,
+ SECTION_DIRECTIVE,
+ NASM_FILENAME
+};
+
+typedef struct yasm_parser_gas {
+ /*@only@*/ yasm_object *object;
+
+ /* last "base" label for local (.) labels */
+ /*@null@*/ char *locallabel_base;
+ size_t locallabel_base_len;
+
+ /* .line/.file: we have to see both to start setting linemap versions */
+ int dir_fileline;
+ /*@null@*/ char *dir_file;
+ unsigned long dir_line;
+
+ /* Have we seen a line marker? */
+ int seen_line_marker;
+
+ /*@dependent@*/ yasm_preproc *preproc;
+ /*@dependent@*/ yasm_errwarns *errwarns;
+
+ /*@dependent@*/ yasm_linemap *linemap;
+
+ /*@null@*/ yasm_bytecode *prev_bc;
+ yasm_bytecode *temp_bc;
+
+ int save_input;
+ YYCTYPE save_line[2][MAX_SAVED_LINE_LEN];
+ int save_last;
+
+ /* Line data storage used in preproc_input(). */
+ char *line, *linepos;
+ size_t lineleft;
+
+ yasm_scanner s;
+ enum gas_parser_state state;
+
+ int token; /* enum tokentype or any character */
+ yystype tokval;
+ char tokch; /* first character of token */
+
+ /* one token of lookahead; used sparingly */
+ int peek_token; /* NONE if none */
+ yystype peek_tokval;
+ char peek_tokch;
+
+ /* Index of local labels; what's stored here is the /next/ index,
+ * so these are all 0 at start.
+ */
+ unsigned long local[10];
+
+ /* Parser-handled directives HAMT lookup */
+ HAMT *dirs;
+
+ int intel_syntax;
+
+ int is_nasm_preproc;
+ int is_cpp_preproc;
+} yasm_parser_gas;
+
+/* shorter access names to commonly used parser_gas fields */
+#define p_object (parser_gas->object)
+#define p_symtab (parser_gas->object->symtab)
+#define cursect (parser_gas->object->cur_section)
+#define curtok (parser_gas->token)
+#define curval (parser_gas->tokval)
+
+#define INTNUM_val (curval.intn)
+#define FLTNUM_val (curval.flt)
+#define STRING_val (curval.str)
+#define REG_val (curval.arch_data)
+#define REGGROUP_val (curval.arch_data)
+#define SEGREG_val (curval.arch_data)
+#define TARGETMOD_val (curval.arch_data)
+#define ID_val (curval.str.contents)
+#define ID_len (curval.str.len)
+#define LABEL_val (curval.str.contents)
+#define LABEL_len (curval.str.len)
+
+#define cur_line (yasm_linemap_get_current(parser_gas->linemap))
+
+#define p_expr_new(l,o,r) yasm_expr_create(o,l,r,cur_line)
+#define p_expr_new_tree(l,o,r) yasm_expr_create_tree(l,o,r,cur_line)
+#define p_expr_new_branch(o,r) yasm_expr_create_branch(o,r,cur_line)
+#define p_expr_new_ident(r) yasm_expr_create_ident(r,cur_line)
+
+yasm_bytecode *parse_instr_intel(yasm_parser_gas *parser_gas);
+
+void gas_parser_parse(yasm_parser_gas *parser_gas);
+void gas_parser_cleanup(yasm_parser_gas *parser_gas);
+int gas_parser_lex(YYSTYPE *lvalp, yasm_parser_gas *parser_gas);
+
+#endif
diff --git a/contrib/tools/yasm/modules/parsers/nasm/nasm-parse.c b/contrib/tools/yasm/modules/parsers/nasm/nasm-parse.c
index 63014abd5d..44d3b5d707 100644
--- a/contrib/tools/yasm/modules/parsers/nasm/nasm-parse.c
+++ b/contrib/tools/yasm/modules/parsers/nasm/nasm-parse.c
@@ -1,1680 +1,1680 @@
-/*
- * NASM-compatible parser
- *
- * Copyright (C) 2001-2007 Peter Johnson, Michael Urman
- *
- * 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>
-
-#include <math.h>
-
-#include "modules/parsers/nasm/nasm-parser.h"
-#include "modules/preprocs/nasm/nasm.h"
-
-typedef enum {
- NORM_EXPR,
- DIR_EXPR, /* Can't have seg:off or WRT anywhere */
- DV_EXPR /* Can't have registers anywhere */
-} expr_type;
-
-static yasm_bytecode *parse_line(yasm_parser_nasm *parser_nasm);
-static int parse_directive_valparams(yasm_parser_nasm *parser_nasm,
- /*@out@*/ yasm_valparamhead *vps);
-static yasm_bytecode *parse_times(yasm_parser_nasm *parser_nasm);
-static yasm_bytecode *parse_exp(yasm_parser_nasm *parser_nasm);
-static yasm_bytecode *parse_instr(yasm_parser_nasm *parser_nasm);
-static yasm_insn_operand *parse_operand(yasm_parser_nasm *parser_nasm);
-static yasm_insn_operand *parse_memaddr(yasm_parser_nasm *parser_nasm);
-static yasm_expr *parse_expr(yasm_parser_nasm *parser_nasm, expr_type type);
-static yasm_expr *parse_bexpr(yasm_parser_nasm *parser_nasm, expr_type type);
-static yasm_expr *parse_expr0(yasm_parser_nasm *parser_nasm, expr_type type);
-static yasm_expr *parse_expr1(yasm_parser_nasm *parser_nasm, expr_type type);
-static yasm_expr *parse_expr2(yasm_parser_nasm *parser_nasm, expr_type type);
-static yasm_expr *parse_expr3(yasm_parser_nasm *parser_nasm, expr_type type);
-static yasm_expr *parse_expr4(yasm_parser_nasm *parser_nasm, expr_type type);
-static yasm_expr *parse_expr5(yasm_parser_nasm *parser_nasm, expr_type type);
-static yasm_expr *parse_expr6(yasm_parser_nasm *parser_nasm, expr_type type);
-
-static void nasm_parser_directive
- (yasm_parser_nasm *parser_nasm, const char *name,
- /*@null@*/ yasm_valparamhead *valparams,
- /*@null@*/ yasm_valparamhead *objext_valparams);
-static void set_nonlocal_label(yasm_parser_nasm *parser_nasm, const char *name);
-static void define_label(yasm_parser_nasm *parser_nasm, /*@only@*/ char *name,
- unsigned int size);
-
-static void yasm_ea_set_implicit_size_segment(yasm_parser_nasm *parser_nasm,
- yasm_effaddr *ea, yasm_expr *e)
-{
- if (parser_nasm->tasm) {
- const char *segment = yasm_expr_segment(e);
- ea->data_len = yasm_expr_size(e);
- if (segment) {
- const char *segreg = tasm_get_segment_register(segment);
- if (segreg)
- yasm_arch_parse_check_regtmod(p_object->arch, segreg,
- strlen(segreg), &ea->segreg);
- }
- }
-}
-
-
-#define is_eol_tok(tok) ((tok) == 0)
-#define is_eol() is_eol_tok(curtok)
-
-#define get_next_token() (curtok = nasm_parser_lex(&curval, parser_nasm))
-
-static void
-get_peek_token(yasm_parser_nasm *parser_nasm)
-{
- char savech = parser_nasm->tokch;
- if (parser_nasm->peek_token != NONE)
- yasm_internal_error(N_("only can have one token of lookahead"));
- parser_nasm->peek_token =
- nasm_parser_lex(&parser_nasm->peek_tokval, parser_nasm);
- parser_nasm->peek_tokch = parser_nasm->tokch;
- parser_nasm->tokch = savech;
-}
-
-static void
-destroy_curtok_(yasm_parser_nasm *parser_nasm)
-{
- if (curtok < 256)
- ;
- else switch ((enum tokentype)curtok) {
- case INTNUM:
- yasm_intnum_destroy(curval.intn);
- break;
- case FLTNUM:
- yasm_floatnum_destroy(curval.flt);
- break;
- case DIRECTIVE_NAME:
- case FILENAME:
- case ID:
- case LOCAL_ID:
- case SPECIAL_ID:
- case NONLOCAL_ID:
- yasm_xfree(curval.str_val);
- break;
- case STRING:
- yasm_xfree(curval.str.contents);
- break;
- case INSN:
- yasm_bc_destroy(curval.bc);
- break;
- default:
- break;
- }
- curtok = NONE; /* sanity */
-}
-#define destroy_curtok() destroy_curtok_(parser_nasm)
-
-/* Eat all remaining tokens to EOL, discarding all of them. If there's any
- * intervening tokens, generates an error (junk at end of line).
- */
-static void
-demand_eol_(yasm_parser_nasm *parser_nasm)
-{
- if (is_eol())
- return;
-
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("junk at end of line, first unrecognized character is `%c'"),
- parser_nasm->tokch);
-
- do {
- destroy_curtok();
- get_next_token();
- } while (!is_eol());
-}
-#define demand_eol() demand_eol_(parser_nasm)
-
-static const char *
-describe_token(int token)
-{
- static char strch[] = "` '";
- const char *str;
-
- switch (token) {
- case 0: str = "end of line"; break;
- case INTNUM: str = "integer"; break;
- case FLTNUM: str = "floating point value"; break;
- case DIRECTIVE_NAME: str = "directive name"; break;
- case FILENAME: str = "filename"; break;
- case STRING: str = "string"; break;
- case SIZE_OVERRIDE: str = "size override"; break;
- case DECLARE_DATA: str = "DB/DW/etc."; break;
- case RESERVE_SPACE: str = "RESB/RESW/etc."; break;
- case INCBIN: str = "INCBIN"; break;
- case EQU: str = "EQU"; break;
- case TIMES: str = "TIMES"; break;
- case SEG: str = "SEG"; break;
- case WRT: str = "WRT"; break;
- case NOSPLIT: str = "NOSPLIT"; break;
- case STRICT: str = "STRICT"; break;
- case INSN: str = "instruction"; break;
- case PREFIX: str = "instruction prefix"; break;
- case REG: str = "register"; break;
- case REGGROUP: str = "register group"; break;
- case SEGREG: str = "segment register"; break;
- case TARGETMOD: str = "target modifier"; break;
- case LEFT_OP: str = "<<"; break;
- case RIGHT_OP: str = ">>"; break;
- case SIGNDIV: str = "//"; break;
- case SIGNMOD: str = "%%"; break;
- case START_SECTION_ID: str = "$$"; break;
- case ID: str = "identifier"; break;
- case LOCAL_ID: str = ".identifier"; break;
- case SPECIAL_ID: str = "..identifier"; break;
- case NONLOCAL_ID: str = "..@identifier"; break;
- case LINE: str = "%line"; break;
- default:
- strch[1] = token;
- str = strch;
- break;
- }
-
- return str;
-}
-
-static int
-expect_(yasm_parser_nasm *parser_nasm, int token)
-{
- if (curtok == token)
- return 1;
-
- yasm_error_set(YASM_ERROR_PARSE, "expected %s", describe_token(token));
- destroy_curtok();
- return 0;
-}
-#define expect(token) expect_(parser_nasm, token)
-
-void
-nasm_parser_parse(yasm_parser_nasm *parser_nasm)
-{
- unsigned char *line;
- while ((line = (unsigned char *)
- yasm_preproc_get_line(parser_nasm->preproc)) != NULL) {
- yasm_bytecode *bc = NULL, *temp_bc;
-
- parser_nasm->s.bot = line;
- parser_nasm->s.tok = line;
- parser_nasm->s.ptr = line;
- parser_nasm->s.cur = line;
- parser_nasm->s.lim = line + strlen((char *)line)+1;
- parser_nasm->s.top = parser_nasm->s.lim;
-
- get_next_token();
- if (!is_eol()) {
- bc = parse_line(parser_nasm);
- demand_eol();
- }
-
- if (parser_nasm->abspos) {
- /* If we're inside an absolute section, just add to the absolute
- * position rather than appending bytecodes to a section.
- * Only RES* are allowed in an absolute section, so this is easy.
- */
- if (bc) {
- /*@null@*/ const yasm_expr *numitems, *multiple;
- unsigned int itemsize;
- numitems = yasm_bc_reserve_numitems(bc, &itemsize);
- if (numitems) {
- yasm_expr *e;
- e = yasm_expr_create(YASM_EXPR_MUL,
- yasm_expr_expr(yasm_expr_copy(numitems)),
- yasm_expr_int(yasm_intnum_create_uint(itemsize)),
- cur_line);
- multiple = yasm_bc_get_multiple_expr(bc);
- if (multiple)
- e = yasm_expr_create_tree(e, YASM_EXPR_MUL,
- yasm_expr_copy(multiple),
- cur_line);
- parser_nasm->abspos = yasm_expr_create_tree(
- parser_nasm->abspos, YASM_EXPR_ADD, e, cur_line);
- } else
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("only RES* allowed within absolute section"));
- yasm_bc_destroy(bc);
- }
- temp_bc = NULL;
- } else if (bc) {
- temp_bc = yasm_section_bcs_append(cursect, bc);
- if (temp_bc)
- parser_nasm->prev_bc = temp_bc;
- } else
- temp_bc = NULL;
- yasm_errwarn_propagate(parser_nasm->errwarns, cur_line);
-
- if (parser_nasm->save_input)
- yasm_linemap_add_source(parser_nasm->linemap, temp_bc,
- (char *)line);
- yasm_linemap_goto_next(parser_nasm->linemap);
- yasm_xfree(line);
- }
-}
-
-/* All parse_* functions expect to be called with curtok being their first
- * token. They should return with curtok being the token *after* their
- * information.
- */
-
-static yasm_bytecode *
-parse_line(yasm_parser_nasm *parser_nasm)
-{
- yasm_bytecode *bc;
-
- bc = parse_exp(parser_nasm);
- if (bc)
- return bc;
-
- switch (curtok) {
- case LINE: /* LINE INTNUM '+' INTNUM FILENAME */
- {
- yasm_intnum *line, *incr;
- char *filename;
-
- get_next_token();
-
- if (!expect(INTNUM)) return NULL;
- line = INTNUM_val;
- get_next_token();
-
- if (!expect('+')) return NULL;
- get_next_token();
-
- if (!expect(INTNUM)) return NULL;
- incr = INTNUM_val;
- get_next_token();
-
- if (!expect(FILENAME)) return NULL;
- filename = FILENAME_val;
- get_next_token();
-
- /* %line indicates the line number of the *next* line, so subtract
- * out the increment when setting the line number.
- */
- yasm_linemap_set(parser_nasm->linemap, filename, 0,
- yasm_intnum_get_uint(line) - yasm_intnum_get_uint(incr),
- yasm_intnum_get_uint(incr));
- yasm_intnum_destroy(line);
- yasm_intnum_destroy(incr);
- yasm_xfree(filename);
- return NULL;
- }
- case '[': /* [ directive ] */
- {
- char *dirname;
- yasm_valparamhead dir_vps;
- int have_vps = 1;
-
- parser_nasm->state = DIRECTIVE;
- get_next_token();
-
- if (!expect(DIRECTIVE_NAME))
- return NULL;
- dirname = DIRECTIVE_NAME_val;
- get_next_token();
-
- /* ignore [warning]. TODO: actually implement */
- if (yasm__strcasecmp(dirname, "warning") == 0) {
- yasm_warn_set(YASM_WARN_GENERAL,
- N_("[warning] directive not supported; ignored"));
-
- /* throw away the rest of the directive tokens */
- while (!is_eol() && curtok != ']')
- {
- destroy_curtok();
- get_next_token();
- }
- expect(']');
- get_next_token();
- return NULL;
- }
-
- if (curtok == ']' || curtok == ':')
- have_vps = 0;
- else if (!parse_directive_valparams(parser_nasm, &dir_vps)) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("invalid arguments to [%s]"), dirname);
- yasm_xfree(dirname);
- return NULL;
- }
- if (curtok == ':') {
- yasm_valparamhead ext_vps;
- get_next_token();
- if (!parse_directive_valparams(parser_nasm, &ext_vps)) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("invalid arguments to [%s]"), dirname);
- yasm_xfree(dirname);
- return NULL;
- }
- nasm_parser_directive(parser_nasm, dirname,
- have_vps ? &dir_vps : NULL, &ext_vps);
- } else
- nasm_parser_directive(parser_nasm, dirname,
- have_vps ? &dir_vps : NULL, NULL);
- yasm_xfree(dirname);
- expect(']');
- get_next_token();
- return NULL;
- }
- case TIMES: /* TIMES expr exp */
- get_next_token();
- return parse_times(parser_nasm);
- case ID:
- case SPECIAL_ID:
- case NONLOCAL_ID:
- case LOCAL_ID:
- {
- char *name = ID_val;
- int local = parser_nasm->tasm
- ? (curtok == ID || curtok == LOCAL_ID ||
- (curtok == SPECIAL_ID && name[0] == '@'))
- : (curtok != ID);
- unsigned int size = 0;
-
- get_next_token();
- if (is_eol()) {
- /* label alone on the line */
- yasm_warn_set(YASM_WARN_ORPHAN_LABEL,
- N_("label alone on a line without a colon might be in error"));
- if (!local)
- set_nonlocal_label(parser_nasm, name);
- define_label(parser_nasm, name, 0);
- return NULL;
- }
- if (curtok == ':')
- get_next_token();
-
- if (curtok == EQU || (parser_nasm->tasm && curtok == '=')) {
- /* label EQU expr */
- yasm_expr *e;
- get_next_token();
-
- if (parser_nasm->tasm && curtok == SIZE_OVERRIDE) {
- size = SIZE_OVERRIDE_val;
- get_next_token();
- }
-
- e = parse_expr(parser_nasm, NORM_EXPR);
- if (!e) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expression expected after %s"), "EQU");
- yasm_xfree(name);
- return NULL;
- }
- yasm_symtab_define_equ(p_symtab, name, e, cur_line);
- yasm_xfree(name);
- return NULL;
- }
-
- if (parser_nasm->tasm && curtok == LABEL)
- get_next_token();
-
- if (parser_nasm->tasm && curtok == SIZE_OVERRIDE) {
- size = SIZE_OVERRIDE_val;
- get_next_token();
- }
-
- if (!local)
- set_nonlocal_label(parser_nasm, name);
-
- if (is_eol()) {
- define_label(parser_nasm, name, size);
- return NULL;
- }
- if (curtok == TIMES) {
- define_label(parser_nasm, name, size);
- get_next_token();
- return parse_times(parser_nasm);
- }
- bc = parse_exp(parser_nasm);
- if (!parser_nasm->tasm && !bc)
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("instruction expected after label"));
- if (parser_nasm->tasm && bc && !size)
- size = yasm_bc_elem_size(bc);
- define_label(parser_nasm, name, size);
- return bc;
- }
- default:
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("label or instruction expected at start of line"));
- return NULL;
- }
-}
-
-static int
-parse_directive_valparams(yasm_parser_nasm *parser_nasm,
- /*@out@*/ yasm_valparamhead *vps)
-{
- yasm_vps_initialize(vps);
- for (;;) {
- yasm_valparam *vp;
- yasm_expr *e;
- char *id = NULL;
-
- /* Look for value first */
- if (curtok == ID) {
- get_peek_token(parser_nasm);
- if (parser_nasm->peek_token == '=') {
- id = ID_val;
- get_next_token(); /* id */
- get_next_token(); /* '=' */
- }
- }
-
- /* Look for parameter */
- switch (curtok) {
- case STRING:
- vp = yasm_vp_create_string(id, STRING_val.contents);
- get_next_token();
- break;
- case ID:
- /* We need a peek token, but avoid error if we have one
- * already; we need to work whether or not we hit the
- * "value=" if test above.
- *
- * We cheat and peek ahead to see if this is just an ID or
- * the ID is part of an expression. We assume a + or - means
- * that it's part of an expression (e.g. "x+y" is parsed as
- * the expression "x+y" and not as "x", "+y").
- */
- if (parser_nasm->peek_token == NONE)
- get_peek_token(parser_nasm);
- switch (parser_nasm->peek_token) {
- case '|': case '^': case '&': case LEFT_OP: case RIGHT_OP:
- case '+': case '-':
- case '*': case '/': case '%': case SIGNDIV: case SIGNMOD:
- break;
- default:
- /* Just an id */
- vp = yasm_vp_create_id(id, ID_val, '$');
- get_next_token();
- goto next;
- }
- /*@fallthrough@*/
- default:
- e = parse_expr(parser_nasm, DIR_EXPR);
- if (!e) {
- yasm_vps_delete(vps);
- return 0;
- }
- vp = yasm_vp_create_expr(id, e);
- break;
- }
-next:
- yasm_vps_append(vps, vp);
- if (curtok == ',')
- get_next_token();
- if (curtok == ']' || curtok == ':' || is_eol())
- return 1;
- }
-}
-
-static yasm_bytecode *
-parse_times(yasm_parser_nasm *parser_nasm)
-{
- yasm_expr *multiple;
- yasm_bytecode *bc;
-
- multiple = parse_bexpr(parser_nasm, DV_EXPR);
- if (!multiple) {
- yasm_error_set(YASM_ERROR_SYNTAX, N_("expression expected after %s"),
- "TIMES");
- return NULL;
- }
- bc = parse_exp(parser_nasm);
- if (!bc) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("instruction expected after TIMES expression"));
- yasm_expr_destroy(multiple);
- return NULL;
- }
- yasm_bc_set_multiple(bc, multiple);
- return bc;
-}
-
-static yasm_bytecode *
-parse_exp(yasm_parser_nasm *parser_nasm)
-{
- yasm_bytecode *bc;
-
- bc = parse_instr(parser_nasm);
- if (bc)
- return bc;
-
- switch (curtok) {
- case DECLARE_DATA:
- {
- unsigned int size = DECLARE_DATA_val/8;
- yasm_datavalhead dvs;
- yasm_dataval *dv;
- yasm_expr *e, *e2;
-
- get_next_token();
-
- yasm_dvs_initialize(&dvs);
- for (;;) {
- if (curtok == STRING) {
- /* Peek ahead to see if we're in an expr. If we're not,
- * then generate a real string dataval.
- */
- get_peek_token(parser_nasm);
- if (parser_nasm->peek_token == ','
- || is_eol_tok(parser_nasm->peek_token)) {
- dv = yasm_dv_create_string(STRING_val.contents,
- STRING_val.len);
- get_next_token();
- goto dv_done;
- }
- }
- if (curtok == '?') {
- yasm_dvs_delete(&dvs);
- get_next_token();
- if (! is_eol_tok(curtok)) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("can not handle more than one '?'"));
- return NULL;
- }
- return yasm_bc_create_reserve(
- p_expr_new_ident(yasm_expr_int(
- yasm_intnum_create_uint(1))),
- size, cur_line);
- }
- if (!(e = parse_bexpr(parser_nasm, DV_EXPR))) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expression or string expected"));
- yasm_dvs_delete(&dvs);
- return NULL;
- }
- if (curtok == DUP) {
- get_next_token();
- if (curtok != '(') {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected ( after DUP"));
- goto error;
- }
- get_next_token();
- if (curtok == '?') {
- get_next_token();
- if (curtok != ')') {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected ) after DUPlicated expression"));
- goto error;
- }
- get_next_token();
- if (! is_eol_tok(curtok)) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("can not handle more than one '?'"));
- goto error;
- }
- yasm_dvs_delete(&dvs);
- return yasm_bc_create_reserve(e, size, cur_line);
- } else if ((e2 = parse_bexpr(parser_nasm, DV_EXPR))) {
- if (curtok != ')') {
- yasm_expr_destroy(e2);
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected ) after DUPlicated expression"));
- goto error;
- }
- get_next_token();
- dv = yasm_dv_create_expr(e2);
- yasm_dv_set_multiple(dv, e);
- } else {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expression or string expected"));
-error:
- yasm_expr_destroy(e);
- yasm_dvs_delete(&dvs);
- return NULL;
- }
- } else
- dv = yasm_dv_create_expr(e);
-dv_done:
- yasm_dvs_append(&dvs, dv);
- if (is_eol())
- break;
- if (!expect(',')) {
- yasm_dvs_delete(&dvs);
- return NULL;
- }
- get_next_token();
- if (is_eol()) /* allow trailing , on list */
- break;
- }
- return yasm_bc_create_data(&dvs, size, 0, p_object->arch,
- cur_line);
- }
- case RESERVE_SPACE:
- {
- unsigned int size = RESERVE_SPACE_val/8;
- yasm_expr *e;
- get_next_token();
- e = parse_bexpr(parser_nasm, DV_EXPR);
- if (!e) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expression expected after %s"), "RESx");
- return NULL;
- }
- return yasm_bc_create_reserve(e, size, cur_line);
- }
- case INCBIN:
- {
- char *filename;
- yasm_expr *start = NULL, *maxlen = NULL;
-
- get_next_token();
-
- if (!expect(STRING)) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("filename string expected after INCBIN"));
- return NULL;
- }
- filename = STRING_val.contents;
- get_next_token();
-
- /* optional start expression */
- if (curtok == ',')
- get_next_token();
- if (is_eol())
- goto incbin_done;
- start = parse_bexpr(parser_nasm, DV_EXPR);
- if (!start) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expression expected for INCBIN start"));
- return NULL;
- }
-
- /* optional maxlen expression */
- if (curtok == ',')
- get_next_token();
- if (is_eol())
- goto incbin_done;
- maxlen = parse_bexpr(parser_nasm, DV_EXPR);
- if (!maxlen) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expression expected for INCBIN maximum length"));
- return NULL;
- }
-
-incbin_done:
- return yasm_bc_create_incbin(filename, start, maxlen,
- parser_nasm->linemap, cur_line);
- }
- default:
- return NULL;
- }
-}
-
-static yasm_bytecode *
-parse_instr(yasm_parser_nasm *parser_nasm)
-{
- yasm_bytecode *bc;
-
- switch (curtok) {
- case INSN:
- {
- yasm_insn *insn;
- bc = INSN_val;
- insn = yasm_bc_get_insn(bc);
-
- get_next_token();
- if (is_eol())
- return bc; /* no operands */
-
- /* parse operands */
- for (;;) {
- yasm_insn_operand *op = parse_operand(parser_nasm);
- if (!op) {
- if (insn->num_operands == 0)
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("unexpected %s after instruction"),
- describe_token(curtok));
- else
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected operand, got %s"),
- describe_token(curtok));
- yasm_bc_destroy(bc);
- return NULL;
- }
- yasm_insn_ops_append(insn, op);
-
- if (is_eol())
- break;
- if (!expect(',')) {
- yasm_bc_destroy(bc);
- return NULL;
- }
- get_next_token();
- }
- return bc;
- }
- case PREFIX:
- {
- uintptr_t prefix = PREFIX_val;
- get_next_token();
- bc = parse_instr(parser_nasm);
- if (!bc)
- bc = yasm_arch_create_empty_insn(p_object->arch, cur_line);
- yasm_insn_add_prefix(yasm_bc_get_insn(bc), prefix);
- return bc;
- }
- case SEGREG:
- {
- uintptr_t segreg = SEGREG_val;
- get_next_token();
- bc = parse_instr(parser_nasm);
- if (!bc)
- bc = yasm_arch_create_empty_insn(p_object->arch, cur_line);
- yasm_insn_add_seg_prefix(yasm_bc_get_insn(bc), segreg);
- return bc;
- }
- default:
- return NULL;
- }
-}
-
-static yasm_insn_operand *
-parse_operand(yasm_parser_nasm *parser_nasm)
-{
- yasm_insn_operand *op;
- switch (curtok) {
- case '[':
- {
- get_next_token();
- op = parse_memaddr(parser_nasm);
-
- expect(']');
- get_next_token();
-
- if (!op) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("memory address expected"));
- return NULL;
- }
-
- if (parser_nasm->tasm && !is_eol() && curtok != ',') {
- yasm_expr *e = NULL, *f;
- yasm_effaddr *ea;
-
- switch (op->type) {
- case YASM_INSN__OPERAND_IMM:
- e = op->data.val;
- break;
- case YASM_INSN__OPERAND_MEMORY:
- if (op->data.ea->disp.rel) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("relative adressing not supported\n"));
- return NULL;
- }
- e = yasm_expr_copy(op->data.ea->disp.abs);
- yasm_arch_ea_destroy(p_object->arch, op->data.ea);
- break;
- case YASM_INSN__OPERAND_REG:
- case YASM_INSN__OPERAND_SEGREG:
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("register adressing not supported\n"));
- return NULL;
- }
- yasm_xfree(op);
- f = parse_bexpr(parser_nasm, NORM_EXPR);
- if (!f) {
- yasm_expr_destroy(e);
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected expression after ]"));
- return NULL;
- }
- e = p_expr_new_tree(e, YASM_EXPR_ADD, f);
- ea = yasm_arch_ea_create(p_object->arch, e);
- yasm_ea_set_implicit_size_segment(parser_nasm, ea, e);
- op = yasm_operand_create_mem(ea);
- }
- return op;
- }
- case OFFSET:
- {
- yasm_insn_operand *op2;
- get_next_token();
- if (parser_nasm->masm && curtok == ID && !yasm__strcasecmp(ID_val, "flat")) {
- get_next_token();
- if (curtok == ':') {
- get_next_token();
- }
- }
- op = parse_operand(parser_nasm);
- if (!op) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("memory address expected"));
- return NULL;
- }
- if (op->type == YASM_INSN__OPERAND_IMM)
- return op;
- if (op->type != YASM_INSN__OPERAND_MEMORY) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("OFFSET applied to non-memory operand"));
- return NULL;
- }
- if (op->data.ea->disp.rel) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("OFFSET applied to non-absolute memory operand"));
- return NULL;
- }
- if (op->data.ea->disp.abs)
- op2 = yasm_operand_create_imm(op->data.ea->disp.abs);
- else
- op2 = yasm_operand_create_imm(p_expr_new_ident(
- yasm_expr_int(yasm_intnum_create_uint(0))));
- yasm_xfree(op);
- return op2;
- }
- case SEGREG:
- {
- uintptr_t segreg = SEGREG_val;
- get_next_token();
- if (parser_nasm->tasm && curtok == ':') {
- get_next_token();
- op = parse_operand(parser_nasm);
- if (!op)
- return NULL;
- if (op->type == YASM_INSN__OPERAND_IMM) {
- yasm_effaddr *ea = yasm_arch_ea_create(p_object->arch,
- op->data.val);
- yasm_insn_operand *op2;
- yasm_ea_set_implicit_size_segment(parser_nasm, ea,
- op->data.val);
- op2 = yasm_operand_create_mem(ea);
- op2->size = op->size;
- yasm_xfree(op);
- op = op2;
- }
- if (op->type != YASM_INSN__OPERAND_MEMORY) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("segment applied to non-memory operand"));
- return NULL;
- }
- yasm_ea_set_segreg(op->data.ea, segreg);
- return op;
- }
- op = yasm_operand_create_segreg(segreg);
- return op;
- }
- case REG:
- op = yasm_operand_create_reg(REG_val);
- get_next_token();
- return op;
- case REGGROUP:
- {
- unsigned long regindex;
- uintptr_t reg = REGGROUP_val;
- get_next_token(); /* REGGROUP */
- if (curtok != '(')
- return yasm_operand_create_reg(reg);
- get_next_token(); /* '(' */
- if (!expect(INTNUM)) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("integer register index expected"));
- return NULL;
- }
- regindex = yasm_intnum_get_uint(INTNUM_val);
- get_next_token(); /* INTNUM */
- if (!expect(')')) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("missing closing parenthesis for register index"));
- return NULL;
- }
- get_next_token(); /* ')' */
- reg = yasm_arch_reggroup_get_reg(p_object->arch, reg, regindex);
- if (reg == 0) {
- yasm_error_set(YASM_ERROR_SYNTAX, N_("bad register index `%u'"),
- regindex);
- return NULL;
- }
- return yasm_operand_create_reg(reg);
- }
- case STRICT:
- get_next_token();
- op = parse_operand(parser_nasm);
- if (op)
- op->strict = 1;
- return op;
- case SIZE_OVERRIDE:
- {
- unsigned int size = SIZE_OVERRIDE_val;
- get_next_token();
- if (parser_nasm->masm && curtok == ID && !yasm__strcasecmp(ID_val, "ptr")) {
- get_next_token();
- }
- op = parse_operand(parser_nasm);
- if (!op)
- return NULL;
- if (op->type == YASM_INSN__OPERAND_REG &&
- yasm_arch_get_reg_size(p_object->arch, op->data.reg) != size)
- yasm_error_set(YASM_ERROR_TYPE,
- N_("cannot override register size"));
- else {
- /* Silently override others unless a warning is turned on.
- * This is to allow overrides such as:
- * %define arg1 dword [bp+4]
- * cmp word arg1, 2
- * Which expands to:
- * cmp word dword [bp+4], 2
- */
- if (op->size != 0) {
- if (op->size != size)
- yasm_warn_set(YASM_WARN_SIZE_OVERRIDE,
- N_("overriding operand size from %u-bit to %u-bit"),
- op->size, size);
- else
- yasm_warn_set(YASM_WARN_SIZE_OVERRIDE,
- N_("double operand size override"));
- }
- op->size = size;
- }
- return op;
- }
- case TARGETMOD:
- {
- uintptr_t tmod = TARGETMOD_val;
- get_next_token();
- op = parse_operand(parser_nasm);
- if (op)
- op->targetmod = tmod;
- return op;
- }
- case ID:
- case LOCAL_ID:
- case NONLOCAL_ID:
- if (parser_nasm->tasm) {
- get_peek_token(parser_nasm);
- if (parser_nasm->peek_token == '[') {
- yasm_symrec *sym = yasm_symtab_use(p_symtab, ID_val,
- cur_line);
- yasm_expr *e = p_expr_new_ident(yasm_expr_sym(sym)), *f;
- yasm_effaddr *ea;
- yasm_xfree(ID_val);
- get_next_token();
- get_next_token();
- f = parse_bexpr(parser_nasm, NORM_EXPR);
- if (!f) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected expression after ["));
- return NULL;
- }
- e = p_expr_new_tree(e, YASM_EXPR_ADD, f);
- if (!expect(']')) {
- yasm_error_set(YASM_ERROR_SYNTAX, N_("missing closing bracket"));
- return NULL;
- }
- get_next_token();
- ea = yasm_arch_ea_create(p_object->arch, e);
- yasm_ea_set_implicit_size_segment(parser_nasm, ea, e);
- op = yasm_operand_create_mem(ea);
- return op;
- }
- }
- /* Fallthrough */
- default:
- {
- yasm_expr *e = parse_bexpr(parser_nasm, NORM_EXPR);
- if (!e)
- return NULL;
- if (curtok != ':') {
- if (parser_nasm->tasm && yasm_expr_size(e)) {
- yasm_effaddr *ea = yasm_arch_ea_create(p_object->arch, e);
- yasm_ea_set_implicit_size_segment(parser_nasm, ea, e);
- op = yasm_operand_create_mem(ea);
- return op;
- } else if (curtok == '[') {
- yasm_expr *f;
- yasm_effaddr *ea;
- yasm_insn_operand *op2;
-
- op = parse_operand(parser_nasm);
- if (!op)
- return NULL;
-
- f = op->data.ea->disp.abs;
- e = p_expr_new_tree(e, YASM_EXPR_ADD, f);
- ea = yasm_arch_ea_create(p_object->arch, e);
- yasm_ea_set_implicit_size_segment(parser_nasm, ea, e);
- op2 = yasm_operand_create_mem(ea);
-
- yasm_xfree(op);
-
- return op2;
- } else {
- return yasm_operand_create_imm(e);
- }
- } else {
- yasm_expr *off;
- get_next_token();
- off = parse_bexpr(parser_nasm, NORM_EXPR);
- if (!off) {
- yasm_expr_destroy(e);
- return NULL;
- }
- op = yasm_operand_create_imm(off);
- op->seg = e;
- return op;
- }
- }
- }
-}
-
-/* memory addresses */
-static yasm_insn_operand *
-parse_memaddr(yasm_parser_nasm *parser_nasm)
-{
- yasm_insn_operand *op;
- switch (curtok) {
- case SEGREG:
- {
- uintptr_t segreg = SEGREG_val;
- get_next_token();
- if (!expect(':')) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("`:' required after segment register"));
- return NULL;
- }
- get_next_token();
- op = parse_memaddr(parser_nasm);
- if (op)
- yasm_ea_set_segreg(op->data.ea, segreg);
- return op;
- }
- case SIZE_OVERRIDE:
- {
- unsigned int size = SIZE_OVERRIDE_val;
- get_next_token();
- op = parse_memaddr(parser_nasm);
- if (op)
- op->data.ea->disp.size = size;
- return op;
- }
- case NOSPLIT:
- get_next_token();
- op = parse_memaddr(parser_nasm);
- if (op)
- op->data.ea->nosplit = 1;
- return op;
- case REL:
- get_next_token();
- op = parse_memaddr(parser_nasm);
- if (op) {
- op->data.ea->pc_rel = 1;
- op->data.ea->not_pc_rel = 0;
- }
- return op;
- case ABS:
- get_next_token();
- op = parse_memaddr(parser_nasm);
- if (op) {
- op->data.ea->pc_rel = 0;
- op->data.ea->not_pc_rel = 1;
- }
- return op;
- default:
- {
- yasm_expr *e = parse_bexpr(parser_nasm, NORM_EXPR);
- if (!e)
- return NULL;
- if (curtok != ':') {
- yasm_effaddr *ea = yasm_arch_ea_create(p_object->arch, e);
- yasm_ea_set_implicit_size_segment(parser_nasm, ea, e);
- return yasm_operand_create_mem(ea);
- } else {
- yasm_effaddr *ea;
- yasm_expr *off;
- get_next_token();
- off = parse_bexpr(parser_nasm, NORM_EXPR);
- if (!off) {
- yasm_expr_destroy(e);
- return NULL;
- }
- ea = yasm_arch_ea_create(p_object->arch, off);
- yasm_ea_set_implicit_size_segment(parser_nasm, ea, off);
- op = yasm_operand_create_mem(ea);
- op->seg = e;
- return op;
- }
- }
- }
-}
-
-/* Expression grammar parsed is:
- *
- * expr : bexpr [ : bexpr ]
- * bexpr : expr0 [ WRT expr6 ]
- * expr0 : expr1 [ {|} expr1...]
- * expr1 : expr2 [ {^} expr2...]
- * expr2 : expr3 [ {&} expr3...]
- * expr3 : expr4 [ {<<,>>} expr4...]
- * expr4 : expr5 [ {+,-} expr5...]
- * expr5 : expr6 [ {*,/,%,//,%%} expr6...]
- * expr6 : { ~,+,-,SEG } expr6
- * | (expr)
- * | symbol
- * | $
- * | number
- */
-
-#define parse_expr_common(leftfunc, tok, rightfunc, op) \
- do { \
- yasm_expr *e, *f; \
- e = leftfunc(parser_nasm, type); \
- if (!e) \
- return NULL; \
- \
- while (curtok == tok) { \
- get_next_token(); \
- f = rightfunc(parser_nasm, type); \
- if (!f) { \
- yasm_error_set(YASM_ERROR_SYNTAX, \
- N_("expected expression after %s"), \
- describe_token(op)); \
- yasm_expr_destroy(e); \
- return NULL; \
- } \
- e = p_expr_new_tree(e, op, f); \
- } \
- return e; \
- } while(0)
-
-static yasm_expr *
-parse_expr(yasm_parser_nasm *parser_nasm, expr_type type)
-{
- switch (type) {
- case DIR_EXPR:
- /* directive expressions can't handle seg:off or WRT */
- return parse_expr0(parser_nasm, type);
- default:
- parse_expr_common(parse_bexpr, ':', parse_bexpr, YASM_EXPR_SEGOFF);
- }
- /*@notreached@*/
- return NULL;
-}
-
-static yasm_expr *
-parse_bexpr(yasm_parser_nasm *parser_nasm, expr_type type)
-{
- parse_expr_common(parse_expr0, WRT, parse_expr6, YASM_EXPR_WRT);
-}
-
-static yasm_expr *
-parse_expr0(yasm_parser_nasm *parser_nasm, expr_type type)
-{
- parse_expr_common(parse_expr1, '|', parse_expr1, YASM_EXPR_OR);
-}
-
-static yasm_expr *
-parse_expr1(yasm_parser_nasm *parser_nasm, expr_type type)
-{
- parse_expr_common(parse_expr2, '^', parse_expr2, YASM_EXPR_XOR);
-}
-
-static yasm_expr *
-parse_expr2(yasm_parser_nasm *parser_nasm, expr_type type)
-{
- parse_expr_common(parse_expr3, '&', parse_expr3, YASM_EXPR_AND);
-}
-
-static yasm_expr *
-parse_expr3(yasm_parser_nasm *parser_nasm, expr_type type)
-{
- yasm_expr *e, *f;
- e = parse_expr4(parser_nasm, type);
- if (!e)
- return NULL;
-
- while (curtok == LEFT_OP || curtok == RIGHT_OP) {
- int op = curtok;
- get_next_token();
- f = parse_expr4(parser_nasm, type);
- if (!f) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected expression after %s"),
- describe_token(op));
- yasm_expr_destroy(e);
- return NULL;
- }
-
- switch (op) {
- case LEFT_OP: e = p_expr_new_tree(e, YASM_EXPR_SHL, f); break;
- case RIGHT_OP: e = p_expr_new_tree(e, YASM_EXPR_SHR, f); break;
- }
- }
- return e;
-}
-
-static yasm_expr *
-parse_expr4(yasm_parser_nasm *parser_nasm, expr_type type)
-{
- yasm_expr *e, *f;
- e = parse_expr5(parser_nasm, type);
- if (!e)
- return NULL;
-
- while (curtok == '+' || curtok == '-') {
- int op = curtok;
- get_next_token();
- f = parse_expr5(parser_nasm, type);
- if (!f) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected expression after %s"),
- describe_token(op));
- yasm_expr_destroy(e);
- return NULL;
- }
-
- switch (op) {
- case '+': e = p_expr_new_tree(e, YASM_EXPR_ADD, f); break;
- case '-': e = p_expr_new_tree(e, YASM_EXPR_SUB, f); break;
- }
- }
- return e;
-}
-
-static yasm_expr *
-parse_expr5(yasm_parser_nasm *parser_nasm, expr_type type)
-{
- yasm_expr *e, *f;
- e = parse_expr6(parser_nasm, type);
- if (!e)
- return NULL;
-
- while (curtok == '*' || curtok == '/' || curtok == '%'
- || curtok == SIGNDIV || curtok == SIGNMOD) {
- int op = curtok;
- get_next_token();
- f = parse_expr6(parser_nasm, type);
- if (!f) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected expression after %s"),
- describe_token(op));
- yasm_expr_destroy(e);
- return NULL;
- }
-
- switch (op) {
- case '*': e = p_expr_new_tree(e, YASM_EXPR_MUL, f); break;
- case '/': e = p_expr_new_tree(e, YASM_EXPR_DIV, f); break;
- case '%': e = p_expr_new_tree(e, YASM_EXPR_MOD, f); break;
- case SIGNDIV: e = p_expr_new_tree(e, YASM_EXPR_SIGNDIV, f); break;
- case SIGNMOD: e = p_expr_new_tree(e, YASM_EXPR_SIGNMOD, f); break;
- }
- }
- return e;
-}
-
-static yasm_expr *
-parse_expr6(yasm_parser_nasm *parser_nasm, expr_type type)
-{
- yasm_expr *e;
- yasm_symrec *sym;
-
- switch (curtok) {
- case '+':
- get_next_token();
- e = parse_expr6(parser_nasm, type);
- if (!e) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected expression after %s"), "`+'");
- }
- return e;
- case '-':
- get_next_token();
- e = parse_expr6(parser_nasm, type);
- if (!e) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected expression after %s"), "`-'");
- return NULL;
- }
- return p_expr_new_branch(YASM_EXPR_NEG, e);
- case '~':
- get_next_token();
- e = parse_expr6(parser_nasm, type);
- if (!e) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected expression after %s"), "`~'");
- return NULL;
- }
- return p_expr_new_branch(YASM_EXPR_NOT, e);
- case LOW:
- get_next_token();
- e = parse_expr6(parser_nasm, type);
- if (!e) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected expression after %s"), "LOW");
- return NULL;
- }
- return p_expr_new_tree(e, YASM_EXPR_AND,
- p_expr_new_ident(yasm_expr_int(yasm_intnum_create_uint(0xff))));
- case HIGH:
- get_next_token();
- e = parse_expr6(parser_nasm, type);
- if (!e) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected expression after %s"), "HIGH");
- return NULL;
- }
- return p_expr_new_tree(
- p_expr_new_tree(e, YASM_EXPR_SHR,
- p_expr_new_ident(yasm_expr_int(
- yasm_intnum_create_uint(8)))),
- YASM_EXPR_AND,
- p_expr_new_ident(yasm_expr_int(yasm_intnum_create_uint(0xff))));
- case SEG:
- get_next_token();
- e = parse_expr6(parser_nasm, type);
- if (!e) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected expression after %s"), "SEG");
- return NULL;
- }
- return p_expr_new_branch(YASM_EXPR_SEG, e);
- case '(':
- get_next_token();
- e = parse_expr(parser_nasm, type);
- if (!e) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected expression after %s"), "`('");
- return NULL;
- }
- if (!expect(')')) {
- yasm_error_set(YASM_ERROR_SYNTAX, N_("missing parenthesis"));
- return NULL;
- }
- get_next_token();
- return e;
- case INTNUM:
- e = p_expr_new_ident(yasm_expr_int(INTNUM_val));
- get_next_token();
- return e;
- case REG:
- if (type == DV_EXPR) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("data values can't have registers"));
- return NULL;
- }
- e = p_expr_new_ident(yasm_expr_reg(REG_val));
- get_next_token();
- return e;
- }
-
- /* directives allow very little and handle IDs specially */
- if (type == DIR_EXPR) {
- switch (curtok) {
- case ID:
- sym = yasm_symtab_use(p_symtab, ID_val, cur_line);
- e = p_expr_new_ident(yasm_expr_sym(sym));
- yasm_xfree(ID_val);
- break;
- default:
- return NULL;
- }
- } else switch (curtok) {
- case FLTNUM:
- e = p_expr_new_ident(yasm_expr_float(FLTNUM_val));
- break;
- case STRING:
- {
- yasm_intnum *intn;
- if (parser_nasm->tasm)
- intn = yasm_intnum_create_charconst_tasm(STRING_val.contents);
- else
- intn = yasm_intnum_create_charconst_nasm(STRING_val.contents);
- e = p_expr_new_ident(yasm_expr_int(intn));
- yasm_xfree(STRING_val.contents);
- break;
- }
- case SPECIAL_ID:
- sym = yasm_objfmt_get_special_sym(p_object, ID_val+2, "nasm");
- if (sym) {
- e = p_expr_new_ident(yasm_expr_sym(sym));
- yasm_xfree(ID_val);
- break;
- }
- /*@fallthrough@*/
- case ID:
- case LOCAL_ID:
- case NONLOCAL_ID:
- sym = yasm_symtab_use(p_symtab, ID_val, cur_line);
- e = p_expr_new_ident(yasm_expr_sym(sym));
- yasm_xfree(ID_val);
- break;
- case '$':
- /* "$" references the current assembly position */
- if (parser_nasm->abspos)
- e = yasm_expr_copy(parser_nasm->abspos);
- else {
- sym = yasm_symtab_define_curpos(p_symtab, "$",
- parser_nasm->prev_bc, cur_line);
- e = p_expr_new_ident(yasm_expr_sym(sym));
- }
- break;
- case START_SECTION_ID:
- /* "$$" references the start of the current section */
- if (parser_nasm->absstart)
- e = yasm_expr_copy(parser_nasm->absstart);
- else {
- sym = yasm_symtab_define_label(p_symtab, "$$",
- yasm_section_bcs_first(cursect), 0, cur_line);
- e = p_expr_new_ident(yasm_expr_sym(sym));
- }
- break;
- default:
- return NULL;
- }
-
- get_next_token();
- return e;
-}
-
-static void
-set_nonlocal_label(yasm_parser_nasm *parser_nasm, const char *name)
-{
- if (!parser_nasm->tasm || tasm_locals) {
- if (parser_nasm->locallabel_base)
- yasm_xfree(parser_nasm->locallabel_base);
- parser_nasm->locallabel_base_len = strlen(name);
- parser_nasm->locallabel_base =
- yasm_xmalloc(parser_nasm->locallabel_base_len+1);
- strcpy(parser_nasm->locallabel_base, name);
- }
-}
-
-static void
-define_label(yasm_parser_nasm *parser_nasm, char *name, unsigned int size)
-{
- yasm_symrec *symrec;
-
- if (parser_nasm->abspos)
- symrec = yasm_symtab_define_equ(p_symtab, name,
- yasm_expr_copy(parser_nasm->abspos),
- cur_line);
- else
- symrec = yasm_symtab_define_label(p_symtab, name, parser_nasm->prev_bc,
- 1, cur_line);
-
- yasm_symrec_set_size(symrec, size);
- yasm_symrec_set_segment(symrec, tasm_segment);
-
- yasm_xfree(name);
-}
-
-static void
-dir_align(yasm_object *object, yasm_valparamhead *valparams,
- yasm_valparamhead *objext_valparams, unsigned long line)
-{
- yasm_valparam *vp = yasm_vps_first(valparams);
- yasm_expr *boundval = yasm_vp_expr(vp, object->symtab, line);
- /*@depedent@*/ yasm_intnum *boundintn;
-
- /* Largest .align in the section specifies section alignment.
- * Note: this doesn't match NASM behavior, but is a lot more
- * intelligent!
- */
- if (boundval && (boundintn = yasm_expr_get_intnum(&boundval, 0))) {
- unsigned long boundint = yasm_intnum_get_uint(boundintn);
-
- /* Alignments must be a power of two. */
- if (is_exp2(boundint)) {
- if (boundint > yasm_section_get_align(object->cur_section))
- yasm_section_set_align(object->cur_section, boundint, line);
- }
- }
-
- /* As this directive is called only when nop is used as fill, always
- * use arch (nop) fill.
- */
- yasm_section_bcs_append(object->cur_section,
- yasm_bc_create_align(boundval, NULL, NULL,
- /*yasm_section_is_code(object->cur_section) ?*/
- yasm_arch_get_fill(object->arch)/* : NULL*/,
- line));
-}
-
-static void
-nasm_parser_directive(yasm_parser_nasm *parser_nasm, const char *name,
- yasm_valparamhead *valparams,
- yasm_valparamhead *objext_valparams)
-{
- unsigned long line = cur_line;
- yasm_valparam *vp;
-
- if (!yasm_object_directive(p_object, name, "nasm", valparams,
- objext_valparams, line))
- ;
- else if (yasm__strcasecmp(name, "absolute") == 0) {
- if (!valparams) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("directive `%s' requires an argument"),
- "absolute");
- } else {
- vp = yasm_vps_first(valparams);
- if (parser_nasm->absstart)
- yasm_expr_destroy(parser_nasm->absstart);
- if (parser_nasm->abspos)
- yasm_expr_destroy(parser_nasm->abspos);
- parser_nasm->absstart = yasm_vp_expr(vp, p_object->symtab, line);
- parser_nasm->abspos = yasm_expr_copy(parser_nasm->absstart);
- cursect = NULL;
- parser_nasm->prev_bc = NULL;
- }
- } else if (yasm__strcasecmp(name, "align") == 0) {
- /* Really, we shouldn't end up with an align directive in an absolute
- * section (as it's supposed to be only used for nop fill), but handle
- * it gracefully anyway.
- */
- if (parser_nasm->abspos) {
- yasm_expr *boundval, *e;
- vp = yasm_vps_first(valparams);
- boundval = yasm_vp_expr(vp, p_object->symtab, line);
- e = yasm_expr_create_tree(
- yasm_expr_create_tree(yasm_expr_copy(parser_nasm->absstart),
- YASM_EXPR_SUB,
- yasm_expr_copy(parser_nasm->abspos),
- cur_line),
- YASM_EXPR_AND,
- yasm_expr_create(YASM_EXPR_SUB, yasm_expr_expr(boundval),
- yasm_expr_int(yasm_intnum_create_uint(1)),
- cur_line),
- cur_line);
- parser_nasm->abspos = yasm_expr_create_tree(
- parser_nasm->abspos, YASM_EXPR_ADD, e, cur_line);
- } else if (!valparams) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("directive `%s' requires an argument"), "align");
- } else
- dir_align(p_object, valparams, objext_valparams, line);
- } else if (yasm__strcasecmp(name, "default") == 0) {
- if (!valparams)
- ;
- else {
- vp = yasm_vps_first(valparams);
- while (vp) {
- const char *id = yasm_vp_id(vp);
- if (id) {
- if (yasm__strcasecmp(id, "rel") == 0)
- yasm_arch_set_var(p_object->arch, "default_rel", 1);
- else if (yasm__strcasecmp(id, "abs") == 0)
- yasm_arch_set_var(p_object->arch, "default_rel", 0);
- else
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("unrecognized default `%s'"), id);
- } else
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("unrecognized default value"));
- vp = yasm_vps_next(vp);
- }
- }
- } else
- yasm_error_set(YASM_ERROR_SYNTAX, N_("unrecognized directive `%s'"),
- name);
-
- if (parser_nasm->absstart && cursect) {
- /* We switched to a new section. Get out of absolute section mode. */
- yasm_expr_destroy(parser_nasm->absstart);
- parser_nasm->absstart = NULL;
- if (parser_nasm->abspos) {
- yasm_expr_destroy(parser_nasm->abspos);
- parser_nasm->abspos = NULL;
- }
- }
-
- if (cursect) {
- /* In case cursect changed or a bytecode was added, update prev_bc. */
- parser_nasm->prev_bc = yasm_section_bcs_last(cursect);
- }
-
- if (valparams)
- yasm_vps_delete(valparams);
- if (objext_valparams)
- yasm_vps_delete(objext_valparams);
-}
-
-yasm_bytecode *
-gas_intel_syntax_parse_instr(yasm_parser_nasm *parser_nasm, unsigned char *instr)
-{
- yasm_bytecode *bc = NULL;
- char *sinstr = (char *) instr;
-
- parser_nasm->s.bot = instr;
- parser_nasm->s.tok = instr;
- parser_nasm->s.ptr = instr;
- parser_nasm->s.cur = instr;
- parser_nasm->s.lim = instr + strlen(sinstr) + 1;
- parser_nasm->s.top = parser_nasm->s.lim;
- parser_nasm->peek_token = NONE;
-
- get_next_token();
- if (!is_eol()) {
- bc = parse_instr(parser_nasm);
- }
-
- return bc;
-}
+/*
+ * NASM-compatible parser
+ *
+ * Copyright (C) 2001-2007 Peter Johnson, Michael Urman
+ *
+ * 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>
+
+#include <math.h>
+
+#include "modules/parsers/nasm/nasm-parser.h"
+#include "modules/preprocs/nasm/nasm.h"
+
+typedef enum {
+ NORM_EXPR,
+ DIR_EXPR, /* Can't have seg:off or WRT anywhere */
+ DV_EXPR /* Can't have registers anywhere */
+} expr_type;
+
+static yasm_bytecode *parse_line(yasm_parser_nasm *parser_nasm);
+static int parse_directive_valparams(yasm_parser_nasm *parser_nasm,
+ /*@out@*/ yasm_valparamhead *vps);
+static yasm_bytecode *parse_times(yasm_parser_nasm *parser_nasm);
+static yasm_bytecode *parse_exp(yasm_parser_nasm *parser_nasm);
+static yasm_bytecode *parse_instr(yasm_parser_nasm *parser_nasm);
+static yasm_insn_operand *parse_operand(yasm_parser_nasm *parser_nasm);
+static yasm_insn_operand *parse_memaddr(yasm_parser_nasm *parser_nasm);
+static yasm_expr *parse_expr(yasm_parser_nasm *parser_nasm, expr_type type);
+static yasm_expr *parse_bexpr(yasm_parser_nasm *parser_nasm, expr_type type);
+static yasm_expr *parse_expr0(yasm_parser_nasm *parser_nasm, expr_type type);
+static yasm_expr *parse_expr1(yasm_parser_nasm *parser_nasm, expr_type type);
+static yasm_expr *parse_expr2(yasm_parser_nasm *parser_nasm, expr_type type);
+static yasm_expr *parse_expr3(yasm_parser_nasm *parser_nasm, expr_type type);
+static yasm_expr *parse_expr4(yasm_parser_nasm *parser_nasm, expr_type type);
+static yasm_expr *parse_expr5(yasm_parser_nasm *parser_nasm, expr_type type);
+static yasm_expr *parse_expr6(yasm_parser_nasm *parser_nasm, expr_type type);
+
+static void nasm_parser_directive
+ (yasm_parser_nasm *parser_nasm, const char *name,
+ /*@null@*/ yasm_valparamhead *valparams,
+ /*@null@*/ yasm_valparamhead *objext_valparams);
+static void set_nonlocal_label(yasm_parser_nasm *parser_nasm, const char *name);
+static void define_label(yasm_parser_nasm *parser_nasm, /*@only@*/ char *name,
+ unsigned int size);
+
+static void yasm_ea_set_implicit_size_segment(yasm_parser_nasm *parser_nasm,
+ yasm_effaddr *ea, yasm_expr *e)
+{
+ if (parser_nasm->tasm) {
+ const char *segment = yasm_expr_segment(e);
+ ea->data_len = yasm_expr_size(e);
+ if (segment) {
+ const char *segreg = tasm_get_segment_register(segment);
+ if (segreg)
+ yasm_arch_parse_check_regtmod(p_object->arch, segreg,
+ strlen(segreg), &ea->segreg);
+ }
+ }
+}
+
+
+#define is_eol_tok(tok) ((tok) == 0)
+#define is_eol() is_eol_tok(curtok)
+
+#define get_next_token() (curtok = nasm_parser_lex(&curval, parser_nasm))
+
+static void
+get_peek_token(yasm_parser_nasm *parser_nasm)
+{
+ char savech = parser_nasm->tokch;
+ if (parser_nasm->peek_token != NONE)
+ yasm_internal_error(N_("only can have one token of lookahead"));
+ parser_nasm->peek_token =
+ nasm_parser_lex(&parser_nasm->peek_tokval, parser_nasm);
+ parser_nasm->peek_tokch = parser_nasm->tokch;
+ parser_nasm->tokch = savech;
+}
+
+static void
+destroy_curtok_(yasm_parser_nasm *parser_nasm)
+{
+ if (curtok < 256)
+ ;
+ else switch ((enum tokentype)curtok) {
+ case INTNUM:
+ yasm_intnum_destroy(curval.intn);
+ break;
+ case FLTNUM:
+ yasm_floatnum_destroy(curval.flt);
+ break;
+ case DIRECTIVE_NAME:
+ case FILENAME:
+ case ID:
+ case LOCAL_ID:
+ case SPECIAL_ID:
+ case NONLOCAL_ID:
+ yasm_xfree(curval.str_val);
+ break;
+ case STRING:
+ yasm_xfree(curval.str.contents);
+ break;
+ case INSN:
+ yasm_bc_destroy(curval.bc);
+ break;
+ default:
+ break;
+ }
+ curtok = NONE; /* sanity */
+}
+#define destroy_curtok() destroy_curtok_(parser_nasm)
+
+/* Eat all remaining tokens to EOL, discarding all of them. If there's any
+ * intervening tokens, generates an error (junk at end of line).
+ */
+static void
+demand_eol_(yasm_parser_nasm *parser_nasm)
+{
+ if (is_eol())
+ return;
+
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("junk at end of line, first unrecognized character is `%c'"),
+ parser_nasm->tokch);
+
+ do {
+ destroy_curtok();
+ get_next_token();
+ } while (!is_eol());
+}
+#define demand_eol() demand_eol_(parser_nasm)
+
+static const char *
+describe_token(int token)
+{
+ static char strch[] = "` '";
+ const char *str;
+
+ switch (token) {
+ case 0: str = "end of line"; break;
+ case INTNUM: str = "integer"; break;
+ case FLTNUM: str = "floating point value"; break;
+ case DIRECTIVE_NAME: str = "directive name"; break;
+ case FILENAME: str = "filename"; break;
+ case STRING: str = "string"; break;
+ case SIZE_OVERRIDE: str = "size override"; break;
+ case DECLARE_DATA: str = "DB/DW/etc."; break;
+ case RESERVE_SPACE: str = "RESB/RESW/etc."; break;
+ case INCBIN: str = "INCBIN"; break;
+ case EQU: str = "EQU"; break;
+ case TIMES: str = "TIMES"; break;
+ case SEG: str = "SEG"; break;
+ case WRT: str = "WRT"; break;
+ case NOSPLIT: str = "NOSPLIT"; break;
+ case STRICT: str = "STRICT"; break;
+ case INSN: str = "instruction"; break;
+ case PREFIX: str = "instruction prefix"; break;
+ case REG: str = "register"; break;
+ case REGGROUP: str = "register group"; break;
+ case SEGREG: str = "segment register"; break;
+ case TARGETMOD: str = "target modifier"; break;
+ case LEFT_OP: str = "<<"; break;
+ case RIGHT_OP: str = ">>"; break;
+ case SIGNDIV: str = "//"; break;
+ case SIGNMOD: str = "%%"; break;
+ case START_SECTION_ID: str = "$$"; break;
+ case ID: str = "identifier"; break;
+ case LOCAL_ID: str = ".identifier"; break;
+ case SPECIAL_ID: str = "..identifier"; break;
+ case NONLOCAL_ID: str = "..@identifier"; break;
+ case LINE: str = "%line"; break;
+ default:
+ strch[1] = token;
+ str = strch;
+ break;
+ }
+
+ return str;
+}
+
+static int
+expect_(yasm_parser_nasm *parser_nasm, int token)
+{
+ if (curtok == token)
+ return 1;
+
+ yasm_error_set(YASM_ERROR_PARSE, "expected %s", describe_token(token));
+ destroy_curtok();
+ return 0;
+}
+#define expect(token) expect_(parser_nasm, token)
+
+void
+nasm_parser_parse(yasm_parser_nasm *parser_nasm)
+{
+ unsigned char *line;
+ while ((line = (unsigned char *)
+ yasm_preproc_get_line(parser_nasm->preproc)) != NULL) {
+ yasm_bytecode *bc = NULL, *temp_bc;
+
+ parser_nasm->s.bot = line;
+ parser_nasm->s.tok = line;
+ parser_nasm->s.ptr = line;
+ parser_nasm->s.cur = line;
+ parser_nasm->s.lim = line + strlen((char *)line)+1;
+ parser_nasm->s.top = parser_nasm->s.lim;
+
+ get_next_token();
+ if (!is_eol()) {
+ bc = parse_line(parser_nasm);
+ demand_eol();
+ }
+
+ if (parser_nasm->abspos) {
+ /* If we're inside an absolute section, just add to the absolute
+ * position rather than appending bytecodes to a section.
+ * Only RES* are allowed in an absolute section, so this is easy.
+ */
+ if (bc) {
+ /*@null@*/ const yasm_expr *numitems, *multiple;
+ unsigned int itemsize;
+ numitems = yasm_bc_reserve_numitems(bc, &itemsize);
+ if (numitems) {
+ yasm_expr *e;
+ e = yasm_expr_create(YASM_EXPR_MUL,
+ yasm_expr_expr(yasm_expr_copy(numitems)),
+ yasm_expr_int(yasm_intnum_create_uint(itemsize)),
+ cur_line);
+ multiple = yasm_bc_get_multiple_expr(bc);
+ if (multiple)
+ e = yasm_expr_create_tree(e, YASM_EXPR_MUL,
+ yasm_expr_copy(multiple),
+ cur_line);
+ parser_nasm->abspos = yasm_expr_create_tree(
+ parser_nasm->abspos, YASM_EXPR_ADD, e, cur_line);
+ } else
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("only RES* allowed within absolute section"));
+ yasm_bc_destroy(bc);
+ }
+ temp_bc = NULL;
+ } else if (bc) {
+ temp_bc = yasm_section_bcs_append(cursect, bc);
+ if (temp_bc)
+ parser_nasm->prev_bc = temp_bc;
+ } else
+ temp_bc = NULL;
+ yasm_errwarn_propagate(parser_nasm->errwarns, cur_line);
+
+ if (parser_nasm->save_input)
+ yasm_linemap_add_source(parser_nasm->linemap, temp_bc,
+ (char *)line);
+ yasm_linemap_goto_next(parser_nasm->linemap);
+ yasm_xfree(line);
+ }
+}
+
+/* All parse_* functions expect to be called with curtok being their first
+ * token. They should return with curtok being the token *after* their
+ * information.
+ */
+
+static yasm_bytecode *
+parse_line(yasm_parser_nasm *parser_nasm)
+{
+ yasm_bytecode *bc;
+
+ bc = parse_exp(parser_nasm);
+ if (bc)
+ return bc;
+
+ switch (curtok) {
+ case LINE: /* LINE INTNUM '+' INTNUM FILENAME */
+ {
+ yasm_intnum *line, *incr;
+ char *filename;
+
+ get_next_token();
+
+ if (!expect(INTNUM)) return NULL;
+ line = INTNUM_val;
+ get_next_token();
+
+ if (!expect('+')) return NULL;
+ get_next_token();
+
+ if (!expect(INTNUM)) return NULL;
+ incr = INTNUM_val;
+ get_next_token();
+
+ if (!expect(FILENAME)) return NULL;
+ filename = FILENAME_val;
+ get_next_token();
+
+ /* %line indicates the line number of the *next* line, so subtract
+ * out the increment when setting the line number.
+ */
+ yasm_linemap_set(parser_nasm->linemap, filename, 0,
+ yasm_intnum_get_uint(line) - yasm_intnum_get_uint(incr),
+ yasm_intnum_get_uint(incr));
+ yasm_intnum_destroy(line);
+ yasm_intnum_destroy(incr);
+ yasm_xfree(filename);
+ return NULL;
+ }
+ case '[': /* [ directive ] */
+ {
+ char *dirname;
+ yasm_valparamhead dir_vps;
+ int have_vps = 1;
+
+ parser_nasm->state = DIRECTIVE;
+ get_next_token();
+
+ if (!expect(DIRECTIVE_NAME))
+ return NULL;
+ dirname = DIRECTIVE_NAME_val;
+ get_next_token();
+
+ /* ignore [warning]. TODO: actually implement */
+ if (yasm__strcasecmp(dirname, "warning") == 0) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("[warning] directive not supported; ignored"));
+
+ /* throw away the rest of the directive tokens */
+ while (!is_eol() && curtok != ']')
+ {
+ destroy_curtok();
+ get_next_token();
+ }
+ expect(']');
+ get_next_token();
+ return NULL;
+ }
+
+ if (curtok == ']' || curtok == ':')
+ have_vps = 0;
+ else if (!parse_directive_valparams(parser_nasm, &dir_vps)) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("invalid arguments to [%s]"), dirname);
+ yasm_xfree(dirname);
+ return NULL;
+ }
+ if (curtok == ':') {
+ yasm_valparamhead ext_vps;
+ get_next_token();
+ if (!parse_directive_valparams(parser_nasm, &ext_vps)) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("invalid arguments to [%s]"), dirname);
+ yasm_xfree(dirname);
+ return NULL;
+ }
+ nasm_parser_directive(parser_nasm, dirname,
+ have_vps ? &dir_vps : NULL, &ext_vps);
+ } else
+ nasm_parser_directive(parser_nasm, dirname,
+ have_vps ? &dir_vps : NULL, NULL);
+ yasm_xfree(dirname);
+ expect(']');
+ get_next_token();
+ return NULL;
+ }
+ case TIMES: /* TIMES expr exp */
+ get_next_token();
+ return parse_times(parser_nasm);
+ case ID:
+ case SPECIAL_ID:
+ case NONLOCAL_ID:
+ case LOCAL_ID:
+ {
+ char *name = ID_val;
+ int local = parser_nasm->tasm
+ ? (curtok == ID || curtok == LOCAL_ID ||
+ (curtok == SPECIAL_ID && name[0] == '@'))
+ : (curtok != ID);
+ unsigned int size = 0;
+
+ get_next_token();
+ if (is_eol()) {
+ /* label alone on the line */
+ yasm_warn_set(YASM_WARN_ORPHAN_LABEL,
+ N_("label alone on a line without a colon might be in error"));
+ if (!local)
+ set_nonlocal_label(parser_nasm, name);
+ define_label(parser_nasm, name, 0);
+ return NULL;
+ }
+ if (curtok == ':')
+ get_next_token();
+
+ if (curtok == EQU || (parser_nasm->tasm && curtok == '=')) {
+ /* label EQU expr */
+ yasm_expr *e;
+ get_next_token();
+
+ if (parser_nasm->tasm && curtok == SIZE_OVERRIDE) {
+ size = SIZE_OVERRIDE_val;
+ get_next_token();
+ }
+
+ e = parse_expr(parser_nasm, NORM_EXPR);
+ if (!e) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expression expected after %s"), "EQU");
+ yasm_xfree(name);
+ return NULL;
+ }
+ yasm_symtab_define_equ(p_symtab, name, e, cur_line);
+ yasm_xfree(name);
+ return NULL;
+ }
+
+ if (parser_nasm->tasm && curtok == LABEL)
+ get_next_token();
+
+ if (parser_nasm->tasm && curtok == SIZE_OVERRIDE) {
+ size = SIZE_OVERRIDE_val;
+ get_next_token();
+ }
+
+ if (!local)
+ set_nonlocal_label(parser_nasm, name);
+
+ if (is_eol()) {
+ define_label(parser_nasm, name, size);
+ return NULL;
+ }
+ if (curtok == TIMES) {
+ define_label(parser_nasm, name, size);
+ get_next_token();
+ return parse_times(parser_nasm);
+ }
+ bc = parse_exp(parser_nasm);
+ if (!parser_nasm->tasm && !bc)
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("instruction expected after label"));
+ if (parser_nasm->tasm && bc && !size)
+ size = yasm_bc_elem_size(bc);
+ define_label(parser_nasm, name, size);
+ return bc;
+ }
+ default:
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("label or instruction expected at start of line"));
+ return NULL;
+ }
+}
+
+static int
+parse_directive_valparams(yasm_parser_nasm *parser_nasm,
+ /*@out@*/ yasm_valparamhead *vps)
+{
+ yasm_vps_initialize(vps);
+ for (;;) {
+ yasm_valparam *vp;
+ yasm_expr *e;
+ char *id = NULL;
+
+ /* Look for value first */
+ if (curtok == ID) {
+ get_peek_token(parser_nasm);
+ if (parser_nasm->peek_token == '=') {
+ id = ID_val;
+ get_next_token(); /* id */
+ get_next_token(); /* '=' */
+ }
+ }
+
+ /* Look for parameter */
+ switch (curtok) {
+ case STRING:
+ vp = yasm_vp_create_string(id, STRING_val.contents);
+ get_next_token();
+ break;
+ case ID:
+ /* We need a peek token, but avoid error if we have one
+ * already; we need to work whether or not we hit the
+ * "value=" if test above.
+ *
+ * We cheat and peek ahead to see if this is just an ID or
+ * the ID is part of an expression. We assume a + or - means
+ * that it's part of an expression (e.g. "x+y" is parsed as
+ * the expression "x+y" and not as "x", "+y").
+ */
+ if (parser_nasm->peek_token == NONE)
+ get_peek_token(parser_nasm);
+ switch (parser_nasm->peek_token) {
+ case '|': case '^': case '&': case LEFT_OP: case RIGHT_OP:
+ case '+': case '-':
+ case '*': case '/': case '%': case SIGNDIV: case SIGNMOD:
+ break;
+ default:
+ /* Just an id */
+ vp = yasm_vp_create_id(id, ID_val, '$');
+ get_next_token();
+ goto next;
+ }
+ /*@fallthrough@*/
+ default:
+ e = parse_expr(parser_nasm, DIR_EXPR);
+ if (!e) {
+ yasm_vps_delete(vps);
+ return 0;
+ }
+ vp = yasm_vp_create_expr(id, e);
+ break;
+ }
+next:
+ yasm_vps_append(vps, vp);
+ if (curtok == ',')
+ get_next_token();
+ if (curtok == ']' || curtok == ':' || is_eol())
+ return 1;
+ }
+}
+
+static yasm_bytecode *
+parse_times(yasm_parser_nasm *parser_nasm)
+{
+ yasm_expr *multiple;
+ yasm_bytecode *bc;
+
+ multiple = parse_bexpr(parser_nasm, DV_EXPR);
+ if (!multiple) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("expression expected after %s"),
+ "TIMES");
+ return NULL;
+ }
+ bc = parse_exp(parser_nasm);
+ if (!bc) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("instruction expected after TIMES expression"));
+ yasm_expr_destroy(multiple);
+ return NULL;
+ }
+ yasm_bc_set_multiple(bc, multiple);
+ return bc;
+}
+
+static yasm_bytecode *
+parse_exp(yasm_parser_nasm *parser_nasm)
+{
+ yasm_bytecode *bc;
+
+ bc = parse_instr(parser_nasm);
+ if (bc)
+ return bc;
+
+ switch (curtok) {
+ case DECLARE_DATA:
+ {
+ unsigned int size = DECLARE_DATA_val/8;
+ yasm_datavalhead dvs;
+ yasm_dataval *dv;
+ yasm_expr *e, *e2;
+
+ get_next_token();
+
+ yasm_dvs_initialize(&dvs);
+ for (;;) {
+ if (curtok == STRING) {
+ /* Peek ahead to see if we're in an expr. If we're not,
+ * then generate a real string dataval.
+ */
+ get_peek_token(parser_nasm);
+ if (parser_nasm->peek_token == ','
+ || is_eol_tok(parser_nasm->peek_token)) {
+ dv = yasm_dv_create_string(STRING_val.contents,
+ STRING_val.len);
+ get_next_token();
+ goto dv_done;
+ }
+ }
+ if (curtok == '?') {
+ yasm_dvs_delete(&dvs);
+ get_next_token();
+ if (! is_eol_tok(curtok)) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("can not handle more than one '?'"));
+ return NULL;
+ }
+ return yasm_bc_create_reserve(
+ p_expr_new_ident(yasm_expr_int(
+ yasm_intnum_create_uint(1))),
+ size, cur_line);
+ }
+ if (!(e = parse_bexpr(parser_nasm, DV_EXPR))) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expression or string expected"));
+ yasm_dvs_delete(&dvs);
+ return NULL;
+ }
+ if (curtok == DUP) {
+ get_next_token();
+ if (curtok != '(') {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected ( after DUP"));
+ goto error;
+ }
+ get_next_token();
+ if (curtok == '?') {
+ get_next_token();
+ if (curtok != ')') {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected ) after DUPlicated expression"));
+ goto error;
+ }
+ get_next_token();
+ if (! is_eol_tok(curtok)) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("can not handle more than one '?'"));
+ goto error;
+ }
+ yasm_dvs_delete(&dvs);
+ return yasm_bc_create_reserve(e, size, cur_line);
+ } else if ((e2 = parse_bexpr(parser_nasm, DV_EXPR))) {
+ if (curtok != ')') {
+ yasm_expr_destroy(e2);
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected ) after DUPlicated expression"));
+ goto error;
+ }
+ get_next_token();
+ dv = yasm_dv_create_expr(e2);
+ yasm_dv_set_multiple(dv, e);
+ } else {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expression or string expected"));
+error:
+ yasm_expr_destroy(e);
+ yasm_dvs_delete(&dvs);
+ return NULL;
+ }
+ } else
+ dv = yasm_dv_create_expr(e);
+dv_done:
+ yasm_dvs_append(&dvs, dv);
+ if (is_eol())
+ break;
+ if (!expect(',')) {
+ yasm_dvs_delete(&dvs);
+ return NULL;
+ }
+ get_next_token();
+ if (is_eol()) /* allow trailing , on list */
+ break;
+ }
+ return yasm_bc_create_data(&dvs, size, 0, p_object->arch,
+ cur_line);
+ }
+ case RESERVE_SPACE:
+ {
+ unsigned int size = RESERVE_SPACE_val/8;
+ yasm_expr *e;
+ get_next_token();
+ e = parse_bexpr(parser_nasm, DV_EXPR);
+ if (!e) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expression expected after %s"), "RESx");
+ return NULL;
+ }
+ return yasm_bc_create_reserve(e, size, cur_line);
+ }
+ case INCBIN:
+ {
+ char *filename;
+ yasm_expr *start = NULL, *maxlen = NULL;
+
+ get_next_token();
+
+ if (!expect(STRING)) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("filename string expected after INCBIN"));
+ return NULL;
+ }
+ filename = STRING_val.contents;
+ get_next_token();
+
+ /* optional start expression */
+ if (curtok == ',')
+ get_next_token();
+ if (is_eol())
+ goto incbin_done;
+ start = parse_bexpr(parser_nasm, DV_EXPR);
+ if (!start) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expression expected for INCBIN start"));
+ return NULL;
+ }
+
+ /* optional maxlen expression */
+ if (curtok == ',')
+ get_next_token();
+ if (is_eol())
+ goto incbin_done;
+ maxlen = parse_bexpr(parser_nasm, DV_EXPR);
+ if (!maxlen) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expression expected for INCBIN maximum length"));
+ return NULL;
+ }
+
+incbin_done:
+ return yasm_bc_create_incbin(filename, start, maxlen,
+ parser_nasm->linemap, cur_line);
+ }
+ default:
+ return NULL;
+ }
+}
+
+static yasm_bytecode *
+parse_instr(yasm_parser_nasm *parser_nasm)
+{
+ yasm_bytecode *bc;
+
+ switch (curtok) {
+ case INSN:
+ {
+ yasm_insn *insn;
+ bc = INSN_val;
+ insn = yasm_bc_get_insn(bc);
+
+ get_next_token();
+ if (is_eol())
+ return bc; /* no operands */
+
+ /* parse operands */
+ for (;;) {
+ yasm_insn_operand *op = parse_operand(parser_nasm);
+ if (!op) {
+ if (insn->num_operands == 0)
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("unexpected %s after instruction"),
+ describe_token(curtok));
+ else
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected operand, got %s"),
+ describe_token(curtok));
+ yasm_bc_destroy(bc);
+ return NULL;
+ }
+ yasm_insn_ops_append(insn, op);
+
+ if (is_eol())
+ break;
+ if (!expect(',')) {
+ yasm_bc_destroy(bc);
+ return NULL;
+ }
+ get_next_token();
+ }
+ return bc;
+ }
+ case PREFIX:
+ {
+ uintptr_t prefix = PREFIX_val;
+ get_next_token();
+ bc = parse_instr(parser_nasm);
+ if (!bc)
+ bc = yasm_arch_create_empty_insn(p_object->arch, cur_line);
+ yasm_insn_add_prefix(yasm_bc_get_insn(bc), prefix);
+ return bc;
+ }
+ case SEGREG:
+ {
+ uintptr_t segreg = SEGREG_val;
+ get_next_token();
+ bc = parse_instr(parser_nasm);
+ if (!bc)
+ bc = yasm_arch_create_empty_insn(p_object->arch, cur_line);
+ yasm_insn_add_seg_prefix(yasm_bc_get_insn(bc), segreg);
+ return bc;
+ }
+ default:
+ return NULL;
+ }
+}
+
+static yasm_insn_operand *
+parse_operand(yasm_parser_nasm *parser_nasm)
+{
+ yasm_insn_operand *op;
+ switch (curtok) {
+ case '[':
+ {
+ get_next_token();
+ op = parse_memaddr(parser_nasm);
+
+ expect(']');
+ get_next_token();
+
+ if (!op) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("memory address expected"));
+ return NULL;
+ }
+
+ if (parser_nasm->tasm && !is_eol() && curtok != ',') {
+ yasm_expr *e = NULL, *f;
+ yasm_effaddr *ea;
+
+ switch (op->type) {
+ case YASM_INSN__OPERAND_IMM:
+ e = op->data.val;
+ break;
+ case YASM_INSN__OPERAND_MEMORY:
+ if (op->data.ea->disp.rel) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("relative adressing not supported\n"));
+ return NULL;
+ }
+ e = yasm_expr_copy(op->data.ea->disp.abs);
+ yasm_arch_ea_destroy(p_object->arch, op->data.ea);
+ break;
+ case YASM_INSN__OPERAND_REG:
+ case YASM_INSN__OPERAND_SEGREG:
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("register adressing not supported\n"));
+ return NULL;
+ }
+ yasm_xfree(op);
+ f = parse_bexpr(parser_nasm, NORM_EXPR);
+ if (!f) {
+ yasm_expr_destroy(e);
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected expression after ]"));
+ return NULL;
+ }
+ e = p_expr_new_tree(e, YASM_EXPR_ADD, f);
+ ea = yasm_arch_ea_create(p_object->arch, e);
+ yasm_ea_set_implicit_size_segment(parser_nasm, ea, e);
+ op = yasm_operand_create_mem(ea);
+ }
+ return op;
+ }
+ case OFFSET:
+ {
+ yasm_insn_operand *op2;
+ get_next_token();
+ if (parser_nasm->masm && curtok == ID && !yasm__strcasecmp(ID_val, "flat")) {
+ get_next_token();
+ if (curtok == ':') {
+ get_next_token();
+ }
+ }
+ op = parse_operand(parser_nasm);
+ if (!op) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("memory address expected"));
+ return NULL;
+ }
+ if (op->type == YASM_INSN__OPERAND_IMM)
+ return op;
+ if (op->type != YASM_INSN__OPERAND_MEMORY) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("OFFSET applied to non-memory operand"));
+ return NULL;
+ }
+ if (op->data.ea->disp.rel) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("OFFSET applied to non-absolute memory operand"));
+ return NULL;
+ }
+ if (op->data.ea->disp.abs)
+ op2 = yasm_operand_create_imm(op->data.ea->disp.abs);
+ else
+ op2 = yasm_operand_create_imm(p_expr_new_ident(
+ yasm_expr_int(yasm_intnum_create_uint(0))));
+ yasm_xfree(op);
+ return op2;
+ }
+ case SEGREG:
+ {
+ uintptr_t segreg = SEGREG_val;
+ get_next_token();
+ if (parser_nasm->tasm && curtok == ':') {
+ get_next_token();
+ op = parse_operand(parser_nasm);
+ if (!op)
+ return NULL;
+ if (op->type == YASM_INSN__OPERAND_IMM) {
+ yasm_effaddr *ea = yasm_arch_ea_create(p_object->arch,
+ op->data.val);
+ yasm_insn_operand *op2;
+ yasm_ea_set_implicit_size_segment(parser_nasm, ea,
+ op->data.val);
+ op2 = yasm_operand_create_mem(ea);
+ op2->size = op->size;
+ yasm_xfree(op);
+ op = op2;
+ }
+ if (op->type != YASM_INSN__OPERAND_MEMORY) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("segment applied to non-memory operand"));
+ return NULL;
+ }
+ yasm_ea_set_segreg(op->data.ea, segreg);
+ return op;
+ }
+ op = yasm_operand_create_segreg(segreg);
+ return op;
+ }
+ case REG:
+ op = yasm_operand_create_reg(REG_val);
+ get_next_token();
+ return op;
+ case REGGROUP:
+ {
+ unsigned long regindex;
+ uintptr_t reg = REGGROUP_val;
+ get_next_token(); /* REGGROUP */
+ if (curtok != '(')
+ return yasm_operand_create_reg(reg);
+ get_next_token(); /* '(' */
+ if (!expect(INTNUM)) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("integer register index expected"));
+ return NULL;
+ }
+ regindex = yasm_intnum_get_uint(INTNUM_val);
+ get_next_token(); /* INTNUM */
+ if (!expect(')')) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("missing closing parenthesis for register index"));
+ return NULL;
+ }
+ get_next_token(); /* ')' */
+ reg = yasm_arch_reggroup_get_reg(p_object->arch, reg, regindex);
+ if (reg == 0) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("bad register index `%u'"),
+ regindex);
+ return NULL;
+ }
+ return yasm_operand_create_reg(reg);
+ }
+ case STRICT:
+ get_next_token();
+ op = parse_operand(parser_nasm);
+ if (op)
+ op->strict = 1;
+ return op;
+ case SIZE_OVERRIDE:
+ {
+ unsigned int size = SIZE_OVERRIDE_val;
+ get_next_token();
+ if (parser_nasm->masm && curtok == ID && !yasm__strcasecmp(ID_val, "ptr")) {
+ get_next_token();
+ }
+ op = parse_operand(parser_nasm);
+ if (!op)
+ return NULL;
+ if (op->type == YASM_INSN__OPERAND_REG &&
+ yasm_arch_get_reg_size(p_object->arch, op->data.reg) != size)
+ yasm_error_set(YASM_ERROR_TYPE,
+ N_("cannot override register size"));
+ else {
+ /* Silently override others unless a warning is turned on.
+ * This is to allow overrides such as:
+ * %define arg1 dword [bp+4]
+ * cmp word arg1, 2
+ * Which expands to:
+ * cmp word dword [bp+4], 2
+ */
+ if (op->size != 0) {
+ if (op->size != size)
+ yasm_warn_set(YASM_WARN_SIZE_OVERRIDE,
+ N_("overriding operand size from %u-bit to %u-bit"),
+ op->size, size);
+ else
+ yasm_warn_set(YASM_WARN_SIZE_OVERRIDE,
+ N_("double operand size override"));
+ }
+ op->size = size;
+ }
+ return op;
+ }
+ case TARGETMOD:
+ {
+ uintptr_t tmod = TARGETMOD_val;
+ get_next_token();
+ op = parse_operand(parser_nasm);
+ if (op)
+ op->targetmod = tmod;
+ return op;
+ }
+ case ID:
+ case LOCAL_ID:
+ case NONLOCAL_ID:
+ if (parser_nasm->tasm) {
+ get_peek_token(parser_nasm);
+ if (parser_nasm->peek_token == '[') {
+ yasm_symrec *sym = yasm_symtab_use(p_symtab, ID_val,
+ cur_line);
+ yasm_expr *e = p_expr_new_ident(yasm_expr_sym(sym)), *f;
+ yasm_effaddr *ea;
+ yasm_xfree(ID_val);
+ get_next_token();
+ get_next_token();
+ f = parse_bexpr(parser_nasm, NORM_EXPR);
+ if (!f) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected expression after ["));
+ return NULL;
+ }
+ e = p_expr_new_tree(e, YASM_EXPR_ADD, f);
+ if (!expect(']')) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("missing closing bracket"));
+ return NULL;
+ }
+ get_next_token();
+ ea = yasm_arch_ea_create(p_object->arch, e);
+ yasm_ea_set_implicit_size_segment(parser_nasm, ea, e);
+ op = yasm_operand_create_mem(ea);
+ return op;
+ }
+ }
+ /* Fallthrough */
+ default:
+ {
+ yasm_expr *e = parse_bexpr(parser_nasm, NORM_EXPR);
+ if (!e)
+ return NULL;
+ if (curtok != ':') {
+ if (parser_nasm->tasm && yasm_expr_size(e)) {
+ yasm_effaddr *ea = yasm_arch_ea_create(p_object->arch, e);
+ yasm_ea_set_implicit_size_segment(parser_nasm, ea, e);
+ op = yasm_operand_create_mem(ea);
+ return op;
+ } else if (curtok == '[') {
+ yasm_expr *f;
+ yasm_effaddr *ea;
+ yasm_insn_operand *op2;
+
+ op = parse_operand(parser_nasm);
+ if (!op)
+ return NULL;
+
+ f = op->data.ea->disp.abs;
+ e = p_expr_new_tree(e, YASM_EXPR_ADD, f);
+ ea = yasm_arch_ea_create(p_object->arch, e);
+ yasm_ea_set_implicit_size_segment(parser_nasm, ea, e);
+ op2 = yasm_operand_create_mem(ea);
+
+ yasm_xfree(op);
+
+ return op2;
+ } else {
+ return yasm_operand_create_imm(e);
+ }
+ } else {
+ yasm_expr *off;
+ get_next_token();
+ off = parse_bexpr(parser_nasm, NORM_EXPR);
+ if (!off) {
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+ op = yasm_operand_create_imm(off);
+ op->seg = e;
+ return op;
+ }
+ }
+ }
+}
+
+/* memory addresses */
+static yasm_insn_operand *
+parse_memaddr(yasm_parser_nasm *parser_nasm)
+{
+ yasm_insn_operand *op;
+ switch (curtok) {
+ case SEGREG:
+ {
+ uintptr_t segreg = SEGREG_val;
+ get_next_token();
+ if (!expect(':')) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("`:' required after segment register"));
+ return NULL;
+ }
+ get_next_token();
+ op = parse_memaddr(parser_nasm);
+ if (op)
+ yasm_ea_set_segreg(op->data.ea, segreg);
+ return op;
+ }
+ case SIZE_OVERRIDE:
+ {
+ unsigned int size = SIZE_OVERRIDE_val;
+ get_next_token();
+ op = parse_memaddr(parser_nasm);
+ if (op)
+ op->data.ea->disp.size = size;
+ return op;
+ }
+ case NOSPLIT:
+ get_next_token();
+ op = parse_memaddr(parser_nasm);
+ if (op)
+ op->data.ea->nosplit = 1;
+ return op;
+ case REL:
+ get_next_token();
+ op = parse_memaddr(parser_nasm);
+ if (op) {
+ op->data.ea->pc_rel = 1;
+ op->data.ea->not_pc_rel = 0;
+ }
+ return op;
+ case ABS:
+ get_next_token();
+ op = parse_memaddr(parser_nasm);
+ if (op) {
+ op->data.ea->pc_rel = 0;
+ op->data.ea->not_pc_rel = 1;
+ }
+ return op;
+ default:
+ {
+ yasm_expr *e = parse_bexpr(parser_nasm, NORM_EXPR);
+ if (!e)
+ return NULL;
+ if (curtok != ':') {
+ yasm_effaddr *ea = yasm_arch_ea_create(p_object->arch, e);
+ yasm_ea_set_implicit_size_segment(parser_nasm, ea, e);
+ return yasm_operand_create_mem(ea);
+ } else {
+ yasm_effaddr *ea;
+ yasm_expr *off;
+ get_next_token();
+ off = parse_bexpr(parser_nasm, NORM_EXPR);
+ if (!off) {
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+ ea = yasm_arch_ea_create(p_object->arch, off);
+ yasm_ea_set_implicit_size_segment(parser_nasm, ea, off);
+ op = yasm_operand_create_mem(ea);
+ op->seg = e;
+ return op;
+ }
+ }
+ }
+}
+
+/* Expression grammar parsed is:
+ *
+ * expr : bexpr [ : bexpr ]
+ * bexpr : expr0 [ WRT expr6 ]
+ * expr0 : expr1 [ {|} expr1...]
+ * expr1 : expr2 [ {^} expr2...]
+ * expr2 : expr3 [ {&} expr3...]
+ * expr3 : expr4 [ {<<,>>} expr4...]
+ * expr4 : expr5 [ {+,-} expr5...]
+ * expr5 : expr6 [ {*,/,%,//,%%} expr6...]
+ * expr6 : { ~,+,-,SEG } expr6
+ * | (expr)
+ * | symbol
+ * | $
+ * | number
+ */
+
+#define parse_expr_common(leftfunc, tok, rightfunc, op) \
+ do { \
+ yasm_expr *e, *f; \
+ e = leftfunc(parser_nasm, type); \
+ if (!e) \
+ return NULL; \
+ \
+ while (curtok == tok) { \
+ get_next_token(); \
+ f = rightfunc(parser_nasm, type); \
+ if (!f) { \
+ yasm_error_set(YASM_ERROR_SYNTAX, \
+ N_("expected expression after %s"), \
+ describe_token(op)); \
+ yasm_expr_destroy(e); \
+ return NULL; \
+ } \
+ e = p_expr_new_tree(e, op, f); \
+ } \
+ return e; \
+ } while(0)
+
+static yasm_expr *
+parse_expr(yasm_parser_nasm *parser_nasm, expr_type type)
+{
+ switch (type) {
+ case DIR_EXPR:
+ /* directive expressions can't handle seg:off or WRT */
+ return parse_expr0(parser_nasm, type);
+ default:
+ parse_expr_common(parse_bexpr, ':', parse_bexpr, YASM_EXPR_SEGOFF);
+ }
+ /*@notreached@*/
+ return NULL;
+}
+
+static yasm_expr *
+parse_bexpr(yasm_parser_nasm *parser_nasm, expr_type type)
+{
+ parse_expr_common(parse_expr0, WRT, parse_expr6, YASM_EXPR_WRT);
+}
+
+static yasm_expr *
+parse_expr0(yasm_parser_nasm *parser_nasm, expr_type type)
+{
+ parse_expr_common(parse_expr1, '|', parse_expr1, YASM_EXPR_OR);
+}
+
+static yasm_expr *
+parse_expr1(yasm_parser_nasm *parser_nasm, expr_type type)
+{
+ parse_expr_common(parse_expr2, '^', parse_expr2, YASM_EXPR_XOR);
+}
+
+static yasm_expr *
+parse_expr2(yasm_parser_nasm *parser_nasm, expr_type type)
+{
+ parse_expr_common(parse_expr3, '&', parse_expr3, YASM_EXPR_AND);
+}
+
+static yasm_expr *
+parse_expr3(yasm_parser_nasm *parser_nasm, expr_type type)
+{
+ yasm_expr *e, *f;
+ e = parse_expr4(parser_nasm, type);
+ if (!e)
+ return NULL;
+
+ while (curtok == LEFT_OP || curtok == RIGHT_OP) {
+ int op = curtok;
+ get_next_token();
+ f = parse_expr4(parser_nasm, type);
+ if (!f) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected expression after %s"),
+ describe_token(op));
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+
+ switch (op) {
+ case LEFT_OP: e = p_expr_new_tree(e, YASM_EXPR_SHL, f); break;
+ case RIGHT_OP: e = p_expr_new_tree(e, YASM_EXPR_SHR, f); break;
+ }
+ }
+ return e;
+}
+
+static yasm_expr *
+parse_expr4(yasm_parser_nasm *parser_nasm, expr_type type)
+{
+ yasm_expr *e, *f;
+ e = parse_expr5(parser_nasm, type);
+ if (!e)
+ return NULL;
+
+ while (curtok == '+' || curtok == '-') {
+ int op = curtok;
+ get_next_token();
+ f = parse_expr5(parser_nasm, type);
+ if (!f) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected expression after %s"),
+ describe_token(op));
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+
+ switch (op) {
+ case '+': e = p_expr_new_tree(e, YASM_EXPR_ADD, f); break;
+ case '-': e = p_expr_new_tree(e, YASM_EXPR_SUB, f); break;
+ }
+ }
+ return e;
+}
+
+static yasm_expr *
+parse_expr5(yasm_parser_nasm *parser_nasm, expr_type type)
+{
+ yasm_expr *e, *f;
+ e = parse_expr6(parser_nasm, type);
+ if (!e)
+ return NULL;
+
+ while (curtok == '*' || curtok == '/' || curtok == '%'
+ || curtok == SIGNDIV || curtok == SIGNMOD) {
+ int op = curtok;
+ get_next_token();
+ f = parse_expr6(parser_nasm, type);
+ if (!f) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected expression after %s"),
+ describe_token(op));
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+
+ switch (op) {
+ case '*': e = p_expr_new_tree(e, YASM_EXPR_MUL, f); break;
+ case '/': e = p_expr_new_tree(e, YASM_EXPR_DIV, f); break;
+ case '%': e = p_expr_new_tree(e, YASM_EXPR_MOD, f); break;
+ case SIGNDIV: e = p_expr_new_tree(e, YASM_EXPR_SIGNDIV, f); break;
+ case SIGNMOD: e = p_expr_new_tree(e, YASM_EXPR_SIGNMOD, f); break;
+ }
+ }
+ return e;
+}
+
+static yasm_expr *
+parse_expr6(yasm_parser_nasm *parser_nasm, expr_type type)
+{
+ yasm_expr *e;
+ yasm_symrec *sym;
+
+ switch (curtok) {
+ case '+':
+ get_next_token();
+ e = parse_expr6(parser_nasm, type);
+ if (!e) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected expression after %s"), "`+'");
+ }
+ return e;
+ case '-':
+ get_next_token();
+ e = parse_expr6(parser_nasm, type);
+ if (!e) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected expression after %s"), "`-'");
+ return NULL;
+ }
+ return p_expr_new_branch(YASM_EXPR_NEG, e);
+ case '~':
+ get_next_token();
+ e = parse_expr6(parser_nasm, type);
+ if (!e) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected expression after %s"), "`~'");
+ return NULL;
+ }
+ return p_expr_new_branch(YASM_EXPR_NOT, e);
+ case LOW:
+ get_next_token();
+ e = parse_expr6(parser_nasm, type);
+ if (!e) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected expression after %s"), "LOW");
+ return NULL;
+ }
+ return p_expr_new_tree(e, YASM_EXPR_AND,
+ p_expr_new_ident(yasm_expr_int(yasm_intnum_create_uint(0xff))));
+ case HIGH:
+ get_next_token();
+ e = parse_expr6(parser_nasm, type);
+ if (!e) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected expression after %s"), "HIGH");
+ return NULL;
+ }
+ return p_expr_new_tree(
+ p_expr_new_tree(e, YASM_EXPR_SHR,
+ p_expr_new_ident(yasm_expr_int(
+ yasm_intnum_create_uint(8)))),
+ YASM_EXPR_AND,
+ p_expr_new_ident(yasm_expr_int(yasm_intnum_create_uint(0xff))));
+ case SEG:
+ get_next_token();
+ e = parse_expr6(parser_nasm, type);
+ if (!e) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected expression after %s"), "SEG");
+ return NULL;
+ }
+ return p_expr_new_branch(YASM_EXPR_SEG, e);
+ case '(':
+ get_next_token();
+ e = parse_expr(parser_nasm, type);
+ if (!e) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected expression after %s"), "`('");
+ return NULL;
+ }
+ if (!expect(')')) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("missing parenthesis"));
+ return NULL;
+ }
+ get_next_token();
+ return e;
+ case INTNUM:
+ e = p_expr_new_ident(yasm_expr_int(INTNUM_val));
+ get_next_token();
+ return e;
+ case REG:
+ if (type == DV_EXPR) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("data values can't have registers"));
+ return NULL;
+ }
+ e = p_expr_new_ident(yasm_expr_reg(REG_val));
+ get_next_token();
+ return e;
+ }
+
+ /* directives allow very little and handle IDs specially */
+ if (type == DIR_EXPR) {
+ switch (curtok) {
+ case ID:
+ sym = yasm_symtab_use(p_symtab, ID_val, cur_line);
+ e = p_expr_new_ident(yasm_expr_sym(sym));
+ yasm_xfree(ID_val);
+ break;
+ default:
+ return NULL;
+ }
+ } else switch (curtok) {
+ case FLTNUM:
+ e = p_expr_new_ident(yasm_expr_float(FLTNUM_val));
+ break;
+ case STRING:
+ {
+ yasm_intnum *intn;
+ if (parser_nasm->tasm)
+ intn = yasm_intnum_create_charconst_tasm(STRING_val.contents);
+ else
+ intn = yasm_intnum_create_charconst_nasm(STRING_val.contents);
+ e = p_expr_new_ident(yasm_expr_int(intn));
+ yasm_xfree(STRING_val.contents);
+ break;
+ }
+ case SPECIAL_ID:
+ sym = yasm_objfmt_get_special_sym(p_object, ID_val+2, "nasm");
+ if (sym) {
+ e = p_expr_new_ident(yasm_expr_sym(sym));
+ yasm_xfree(ID_val);
+ break;
+ }
+ /*@fallthrough@*/
+ case ID:
+ case LOCAL_ID:
+ case NONLOCAL_ID:
+ sym = yasm_symtab_use(p_symtab, ID_val, cur_line);
+ e = p_expr_new_ident(yasm_expr_sym(sym));
+ yasm_xfree(ID_val);
+ break;
+ case '$':
+ /* "$" references the current assembly position */
+ if (parser_nasm->abspos)
+ e = yasm_expr_copy(parser_nasm->abspos);
+ else {
+ sym = yasm_symtab_define_curpos(p_symtab, "$",
+ parser_nasm->prev_bc, cur_line);
+ e = p_expr_new_ident(yasm_expr_sym(sym));
+ }
+ break;
+ case START_SECTION_ID:
+ /* "$$" references the start of the current section */
+ if (parser_nasm->absstart)
+ e = yasm_expr_copy(parser_nasm->absstart);
+ else {
+ sym = yasm_symtab_define_label(p_symtab, "$$",
+ yasm_section_bcs_first(cursect), 0, cur_line);
+ e = p_expr_new_ident(yasm_expr_sym(sym));
+ }
+ break;
+ default:
+ return NULL;
+ }
+
+ get_next_token();
+ return e;
+}
+
+static void
+set_nonlocal_label(yasm_parser_nasm *parser_nasm, const char *name)
+{
+ if (!parser_nasm->tasm || tasm_locals) {
+ if (parser_nasm->locallabel_base)
+ yasm_xfree(parser_nasm->locallabel_base);
+ parser_nasm->locallabel_base_len = strlen(name);
+ parser_nasm->locallabel_base =
+ yasm_xmalloc(parser_nasm->locallabel_base_len+1);
+ strcpy(parser_nasm->locallabel_base, name);
+ }
+}
+
+static void
+define_label(yasm_parser_nasm *parser_nasm, char *name, unsigned int size)
+{
+ yasm_symrec *symrec;
+
+ if (parser_nasm->abspos)
+ symrec = yasm_symtab_define_equ(p_symtab, name,
+ yasm_expr_copy(parser_nasm->abspos),
+ cur_line);
+ else
+ symrec = yasm_symtab_define_label(p_symtab, name, parser_nasm->prev_bc,
+ 1, cur_line);
+
+ yasm_symrec_set_size(symrec, size);
+ yasm_symrec_set_segment(symrec, tasm_segment);
+
+ yasm_xfree(name);
+}
+
+static void
+dir_align(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_valparam *vp = yasm_vps_first(valparams);
+ yasm_expr *boundval = yasm_vp_expr(vp, object->symtab, line);
+ /*@depedent@*/ yasm_intnum *boundintn;
+
+ /* Largest .align in the section specifies section alignment.
+ * Note: this doesn't match NASM behavior, but is a lot more
+ * intelligent!
+ */
+ if (boundval && (boundintn = yasm_expr_get_intnum(&boundval, 0))) {
+ unsigned long boundint = yasm_intnum_get_uint(boundintn);
+
+ /* Alignments must be a power of two. */
+ if (is_exp2(boundint)) {
+ if (boundint > yasm_section_get_align(object->cur_section))
+ yasm_section_set_align(object->cur_section, boundint, line);
+ }
+ }
+
+ /* As this directive is called only when nop is used as fill, always
+ * use arch (nop) fill.
+ */
+ yasm_section_bcs_append(object->cur_section,
+ yasm_bc_create_align(boundval, NULL, NULL,
+ /*yasm_section_is_code(object->cur_section) ?*/
+ yasm_arch_get_fill(object->arch)/* : NULL*/,
+ line));
+}
+
+static void
+nasm_parser_directive(yasm_parser_nasm *parser_nasm, const char *name,
+ yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams)
+{
+ unsigned long line = cur_line;
+ yasm_valparam *vp;
+
+ if (!yasm_object_directive(p_object, name, "nasm", valparams,
+ objext_valparams, line))
+ ;
+ else if (yasm__strcasecmp(name, "absolute") == 0) {
+ if (!valparams) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("directive `%s' requires an argument"),
+ "absolute");
+ } else {
+ vp = yasm_vps_first(valparams);
+ if (parser_nasm->absstart)
+ yasm_expr_destroy(parser_nasm->absstart);
+ if (parser_nasm->abspos)
+ yasm_expr_destroy(parser_nasm->abspos);
+ parser_nasm->absstart = yasm_vp_expr(vp, p_object->symtab, line);
+ parser_nasm->abspos = yasm_expr_copy(parser_nasm->absstart);
+ cursect = NULL;
+ parser_nasm->prev_bc = NULL;
+ }
+ } else if (yasm__strcasecmp(name, "align") == 0) {
+ /* Really, we shouldn't end up with an align directive in an absolute
+ * section (as it's supposed to be only used for nop fill), but handle
+ * it gracefully anyway.
+ */
+ if (parser_nasm->abspos) {
+ yasm_expr *boundval, *e;
+ vp = yasm_vps_first(valparams);
+ boundval = yasm_vp_expr(vp, p_object->symtab, line);
+ e = yasm_expr_create_tree(
+ yasm_expr_create_tree(yasm_expr_copy(parser_nasm->absstart),
+ YASM_EXPR_SUB,
+ yasm_expr_copy(parser_nasm->abspos),
+ cur_line),
+ YASM_EXPR_AND,
+ yasm_expr_create(YASM_EXPR_SUB, yasm_expr_expr(boundval),
+ yasm_expr_int(yasm_intnum_create_uint(1)),
+ cur_line),
+ cur_line);
+ parser_nasm->abspos = yasm_expr_create_tree(
+ parser_nasm->abspos, YASM_EXPR_ADD, e, cur_line);
+ } else if (!valparams) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("directive `%s' requires an argument"), "align");
+ } else
+ dir_align(p_object, valparams, objext_valparams, line);
+ } else if (yasm__strcasecmp(name, "default") == 0) {
+ if (!valparams)
+ ;
+ else {
+ vp = yasm_vps_first(valparams);
+ while (vp) {
+ const char *id = yasm_vp_id(vp);
+ if (id) {
+ if (yasm__strcasecmp(id, "rel") == 0)
+ yasm_arch_set_var(p_object->arch, "default_rel", 1);
+ else if (yasm__strcasecmp(id, "abs") == 0)
+ yasm_arch_set_var(p_object->arch, "default_rel", 0);
+ else
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("unrecognized default `%s'"), id);
+ } else
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("unrecognized default value"));
+ vp = yasm_vps_next(vp);
+ }
+ }
+ } else
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("unrecognized directive `%s'"),
+ name);
+
+ if (parser_nasm->absstart && cursect) {
+ /* We switched to a new section. Get out of absolute section mode. */
+ yasm_expr_destroy(parser_nasm->absstart);
+ parser_nasm->absstart = NULL;
+ if (parser_nasm->abspos) {
+ yasm_expr_destroy(parser_nasm->abspos);
+ parser_nasm->abspos = NULL;
+ }
+ }
+
+ if (cursect) {
+ /* In case cursect changed or a bytecode was added, update prev_bc. */
+ parser_nasm->prev_bc = yasm_section_bcs_last(cursect);
+ }
+
+ if (valparams)
+ yasm_vps_delete(valparams);
+ if (objext_valparams)
+ yasm_vps_delete(objext_valparams);
+}
+
+yasm_bytecode *
+gas_intel_syntax_parse_instr(yasm_parser_nasm *parser_nasm, unsigned char *instr)
+{
+ yasm_bytecode *bc = NULL;
+ char *sinstr = (char *) instr;
+
+ parser_nasm->s.bot = instr;
+ parser_nasm->s.tok = instr;
+ parser_nasm->s.ptr = instr;
+ parser_nasm->s.cur = instr;
+ parser_nasm->s.lim = instr + strlen(sinstr) + 1;
+ parser_nasm->s.top = parser_nasm->s.lim;
+ parser_nasm->peek_token = NONE;
+
+ get_next_token();
+ if (!is_eol()) {
+ bc = parse_instr(parser_nasm);
+ }
+
+ return bc;
+}
diff --git a/contrib/tools/yasm/modules/parsers/nasm/nasm-parser-struct.h b/contrib/tools/yasm/modules/parsers/nasm/nasm-parser-struct.h
index 3cb5c8a132..b9223510ba 100644
--- a/contrib/tools/yasm/modules/parsers/nasm/nasm-parser-struct.h
+++ b/contrib/tools/yasm/modules/parsers/nasm/nasm-parser-struct.h
@@ -1,85 +1,85 @@
-/*
- * NASM-compatible parser struct 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_NASM_PARSER_STRUCT_H
-#define YASM_NASM_PARSER_STRUCT_H
-
-typedef union {
- unsigned int int_info;
- char *str_val;
- yasm_intnum *intn;
- yasm_floatnum *flt;
- yasm_bytecode *bc;
- uintptr_t arch_data;
- struct {
- char *contents;
- size_t len;
- } str;
-} nasm_yystype;
-
-typedef struct yasm_parser_nasm {
- int tasm;
- int masm;
-
- /*@only@*/ yasm_object *object;
-
- /* last "base" label for local (.) labels */
- /*@null@*/ char *locallabel_base;
- size_t locallabel_base_len;
-
- /*@dependent@*/ yasm_preproc *preproc;
- /*@dependent@*/ yasm_errwarns *errwarns;
-
- /*@dependent@*/ yasm_linemap *linemap;
-
- /*@null@*/ yasm_bytecode *prev_bc;
-
- int save_input;
-
- yasm_scanner s;
- int state;
-
- int token; /* enum tokentype or any character */
- nasm_yystype tokval;
- char tokch; /* first character of token */
-
- /* one token of lookahead; used sparingly */
- int peek_token; /* NONE if none */
- nasm_yystype peek_tokval;
- char peek_tokch;
-
- /* Starting point of the absolute section. NULL if not in an absolute
- * section.
- */
- /*@null@*/ yasm_expr *absstart;
-
- /* Current location inside an absolute section (including the start).
- * NULL if not in an absolute section.
- */
- /*@null@*/ yasm_expr *abspos;
-} yasm_parser_nasm;
-
-#endif
+/*
+ * NASM-compatible parser struct 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_NASM_PARSER_STRUCT_H
+#define YASM_NASM_PARSER_STRUCT_H
+
+typedef union {
+ unsigned int int_info;
+ char *str_val;
+ yasm_intnum *intn;
+ yasm_floatnum *flt;
+ yasm_bytecode *bc;
+ uintptr_t arch_data;
+ struct {
+ char *contents;
+ size_t len;
+ } str;
+} nasm_yystype;
+
+typedef struct yasm_parser_nasm {
+ int tasm;
+ int masm;
+
+ /*@only@*/ yasm_object *object;
+
+ /* last "base" label for local (.) labels */
+ /*@null@*/ char *locallabel_base;
+ size_t locallabel_base_len;
+
+ /*@dependent@*/ yasm_preproc *preproc;
+ /*@dependent@*/ yasm_errwarns *errwarns;
+
+ /*@dependent@*/ yasm_linemap *linemap;
+
+ /*@null@*/ yasm_bytecode *prev_bc;
+
+ int save_input;
+
+ yasm_scanner s;
+ int state;
+
+ int token; /* enum tokentype or any character */
+ nasm_yystype tokval;
+ char tokch; /* first character of token */
+
+ /* one token of lookahead; used sparingly */
+ int peek_token; /* NONE if none */
+ nasm_yystype peek_tokval;
+ char peek_tokch;
+
+ /* Starting point of the absolute section. NULL if not in an absolute
+ * section.
+ */
+ /*@null@*/ yasm_expr *absstart;
+
+ /* Current location inside an absolute section (including the start).
+ * NULL if not in an absolute section.
+ */
+ /*@null@*/ yasm_expr *abspos;
+} yasm_parser_nasm;
+
+#endif
diff --git a/contrib/tools/yasm/modules/parsers/nasm/nasm-parser.c b/contrib/tools/yasm/modules/parsers/nasm/nasm-parser.c
index 1ceaba7d41..bd166929f7 100644
--- a/contrib/tools/yasm/modules/parsers/nasm/nasm-parser.c
+++ b/contrib/tools/yasm/modules/parsers/nasm/nasm-parser.c
@@ -1,140 +1,140 @@
-/*
- * NASM-compatible parser
- *
- * 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.h>
-
-#include "nasm-parser.h"
-
-
-static void
-nasm_do_parse(yasm_object *object, yasm_preproc *pp, int save_input,
- yasm_linemap *linemap, yasm_errwarns *errwarns, int tasm)
-{
- yasm_parser_nasm parser_nasm;
-
- parser_nasm.tasm = tasm;
- parser_nasm.masm = 0;
-
- parser_nasm.object = object;
- parser_nasm.linemap = linemap;
-
- parser_nasm.locallabel_base = (char *)NULL;
- parser_nasm.locallabel_base_len = 0;
-
- parser_nasm.preproc = pp;
- parser_nasm.errwarns = errwarns;
-
- parser_nasm.prev_bc = yasm_section_bcs_first(object->cur_section);
-
- parser_nasm.save_input = save_input;
-
- parser_nasm.peek_token = NONE;
-
- parser_nasm.absstart = NULL;
- parser_nasm.abspos = NULL;
-
- /* initialize scanner structure */
- yasm_scanner_initialize(&parser_nasm.s);
-
- parser_nasm.state = INITIAL;
-
- nasm_parser_parse(&parser_nasm);
-
- /*yasm_scanner_delete(&parser_nasm.s);*/
-
- /* Free locallabel base if necessary */
- if (parser_nasm.locallabel_base)
- yasm_xfree(parser_nasm.locallabel_base);
-
- /* Check for undefined symbols */
- yasm_symtab_parser_finalize(object->symtab, 0, errwarns);
-}
-
-static void
-nasm_parser_do_parse(yasm_object *object, yasm_preproc *pp,
- int save_input, yasm_linemap *linemap,
- yasm_errwarns *errwarns)
-{
- nasm_do_parse(object, pp, save_input, linemap, errwarns, 0);
-}
-
-#include "nasm-macros.c"
-
-/* Define valid preprocessors to use with this parser */
-static const char *nasm_parser_preproc_keywords[] = {
- "raw",
- "nasm",
- NULL
-};
-
-static const yasm_stdmac nasm_parser_stdmacs[] = {
- { "nasm", "nasm", nasm_standard_mac },
- { NULL, NULL, NULL }
-};
-
-/* Define parser structure -- see parser.h for details */
-yasm_parser_module yasm_nasm_LTX_parser = {
- "NASM-compatible parser",
- "nasm",
- nasm_parser_preproc_keywords,
- "nasm",
- nasm_parser_stdmacs,
- nasm_parser_do_parse
-};
-
-static void
-tasm_parser_do_parse(yasm_object *object, yasm_preproc *pp,
- int save_input, yasm_linemap *linemap,
- yasm_errwarns *errwarns)
-{
- yasm_symtab_set_case_sensitive(object->symtab, 0);
- yasm_warn_disable(YASM_WARN_IMPLICIT_SIZE_OVERRIDE);
- nasm_do_parse(object, pp, save_input, linemap, errwarns, 1);
-}
-
-/* Define valid preprocessors to use with this parser */
-static const char *tasm_parser_preproc_keywords[] = {
- "raw",
- "tasm",
- NULL
-};
-
-static const yasm_stdmac tasm_parser_stdmacs[] = {
- { "tasm", "tasm", nasm_standard_mac },
- { NULL, NULL, NULL }
-};
-
-/* Define parser structure -- see parser.h for details */
-yasm_parser_module yasm_tasm_LTX_parser = {
- "TASM-compatible parser",
- "tasm",
- tasm_parser_preproc_keywords,
- "tasm",
- tasm_parser_stdmacs,
- tasm_parser_do_parse
-};
+/*
+ * NASM-compatible parser
+ *
+ * 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.h>
+
+#include "nasm-parser.h"
+
+
+static void
+nasm_do_parse(yasm_object *object, yasm_preproc *pp, int save_input,
+ yasm_linemap *linemap, yasm_errwarns *errwarns, int tasm)
+{
+ yasm_parser_nasm parser_nasm;
+
+ parser_nasm.tasm = tasm;
+ parser_nasm.masm = 0;
+
+ parser_nasm.object = object;
+ parser_nasm.linemap = linemap;
+
+ parser_nasm.locallabel_base = (char *)NULL;
+ parser_nasm.locallabel_base_len = 0;
+
+ parser_nasm.preproc = pp;
+ parser_nasm.errwarns = errwarns;
+
+ parser_nasm.prev_bc = yasm_section_bcs_first(object->cur_section);
+
+ parser_nasm.save_input = save_input;
+
+ parser_nasm.peek_token = NONE;
+
+ parser_nasm.absstart = NULL;
+ parser_nasm.abspos = NULL;
+
+ /* initialize scanner structure */
+ yasm_scanner_initialize(&parser_nasm.s);
+
+ parser_nasm.state = INITIAL;
+
+ nasm_parser_parse(&parser_nasm);
+
+ /*yasm_scanner_delete(&parser_nasm.s);*/
+
+ /* Free locallabel base if necessary */
+ if (parser_nasm.locallabel_base)
+ yasm_xfree(parser_nasm.locallabel_base);
+
+ /* Check for undefined symbols */
+ yasm_symtab_parser_finalize(object->symtab, 0, errwarns);
+}
+
+static void
+nasm_parser_do_parse(yasm_object *object, yasm_preproc *pp,
+ int save_input, yasm_linemap *linemap,
+ yasm_errwarns *errwarns)
+{
+ nasm_do_parse(object, pp, save_input, linemap, errwarns, 0);
+}
+
+#include "nasm-macros.c"
+
+/* Define valid preprocessors to use with this parser */
+static const char *nasm_parser_preproc_keywords[] = {
+ "raw",
+ "nasm",
+ NULL
+};
+
+static const yasm_stdmac nasm_parser_stdmacs[] = {
+ { "nasm", "nasm", nasm_standard_mac },
+ { NULL, NULL, NULL }
+};
+
+/* Define parser structure -- see parser.h for details */
+yasm_parser_module yasm_nasm_LTX_parser = {
+ "NASM-compatible parser",
+ "nasm",
+ nasm_parser_preproc_keywords,
+ "nasm",
+ nasm_parser_stdmacs,
+ nasm_parser_do_parse
+};
+
+static void
+tasm_parser_do_parse(yasm_object *object, yasm_preproc *pp,
+ int save_input, yasm_linemap *linemap,
+ yasm_errwarns *errwarns)
+{
+ yasm_symtab_set_case_sensitive(object->symtab, 0);
+ yasm_warn_disable(YASM_WARN_IMPLICIT_SIZE_OVERRIDE);
+ nasm_do_parse(object, pp, save_input, linemap, errwarns, 1);
+}
+
+/* Define valid preprocessors to use with this parser */
+static const char *tasm_parser_preproc_keywords[] = {
+ "raw",
+ "tasm",
+ NULL
+};
+
+static const yasm_stdmac tasm_parser_stdmacs[] = {
+ { "tasm", "tasm", nasm_standard_mac },
+ { NULL, NULL, NULL }
+};
+
+/* Define parser structure -- see parser.h for details */
+yasm_parser_module yasm_tasm_LTX_parser = {
+ "TASM-compatible parser",
+ "tasm",
+ tasm_parser_preproc_keywords,
+ "tasm",
+ tasm_parser_stdmacs,
+ tasm_parser_do_parse
+};
diff --git a/contrib/tools/yasm/modules/parsers/nasm/nasm-parser.h b/contrib/tools/yasm/modules/parsers/nasm/nasm-parser.h
index 0c7cc16c73..dc19cfb5e0 100644
--- a/contrib/tools/yasm/modules/parsers/nasm/nasm-parser.h
+++ b/contrib/tools/yasm/modules/parsers/nasm/nasm-parser.h
@@ -1,123 +1,123 @@
-/*
- * NASM-compatible parser 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_NASM_PARSER_H
-#define YASM_NASM_PARSER_H
-
-#include "nasm-parser-struct.h"
-
-#define YYCTYPE unsigned char
-
-#define MAX_SAVED_LINE_LEN 80
-
-enum tokentype {
- INTNUM = 258,
- FLTNUM,
- DIRECTIVE_NAME,
- FILENAME,
- STRING,
- SIZE_OVERRIDE,
- OFFSET,
- DECLARE_DATA,
- RESERVE_SPACE,
- LABEL,
- INCBIN,
- EQU,
- TIMES,
- DUP,
- SEG,
- WRT,
- ABS,
- REL,
- NOSPLIT,
- STRICT,
- INSN,
- PREFIX,
- REG,
- REGGROUP,
- SEGREG,
- TARGETMOD,
- LEFT_OP,
- RIGHT_OP,
- LOW,
- HIGH,
- SIGNDIV,
- SIGNMOD,
- START_SECTION_ID,
- ID,
- LOCAL_ID,
- SPECIAL_ID,
- NONLOCAL_ID,
- LINE,
- NONE /* special token for lookahead */
-};
-
-enum nasm_parser_state {
- INITIAL,
- DIRECTIVE,
- SECTION_DIRECTIVE,
- DIRECTIVE2,
- LINECHG,
- LINECHG2,
- INSTRUCTION
-};
-
-#define YYSTYPE nasm_yystype
-
-/* shorter access names to commonly used parser_nasm fields */
-#define p_object (parser_nasm->object)
-#define p_symtab (parser_nasm->object->symtab)
-#define cursect (parser_nasm->object->cur_section)
-#define curtok (parser_nasm->token)
-#define curval (parser_nasm->tokval)
-
-#define INTNUM_val (curval.intn)
-#define FLTNUM_val (curval.flt)
-#define DIRECTIVE_NAME_val (curval.str_val)
-#define FILENAME_val (curval.str_val)
-#define STRING_val (curval.str)
-#define SIZE_OVERRIDE_val (curval.int_info)
-#define DECLARE_DATA_val (curval.int_info)
-#define RESERVE_SPACE_val (curval.int_info)
-#define INSN_val (curval.bc)
-#define PREFIX_val (curval.arch_data)
-#define REG_val (curval.arch_data)
-#define REGGROUP_val (curval.arch_data)
-#define SEGREG_val (curval.arch_data)
-#define TARGETMOD_val (curval.arch_data)
-#define ID_val (curval.str_val)
-
-#define cur_line (yasm_linemap_get_current(parser_nasm->linemap))
-
-#define p_expr_new_tree(l,o,r) yasm_expr_create_tree(l,o,r,cur_line)
-#define p_expr_new_branch(o,r) yasm_expr_create_branch(o,r,cur_line)
-#define p_expr_new_ident(r) yasm_expr_create_ident(r,cur_line)
-
-void nasm_parser_parse(yasm_parser_nasm *parser_nasm);
-void nasm_parser_cleanup(yasm_parser_nasm *parser_nasm);
-int nasm_parser_lex(YYSTYPE *lvalp, yasm_parser_nasm *parser_nasm);
-
-#endif
+/*
+ * NASM-compatible parser 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_NASM_PARSER_H
+#define YASM_NASM_PARSER_H
+
+#include "nasm-parser-struct.h"
+
+#define YYCTYPE unsigned char
+
+#define MAX_SAVED_LINE_LEN 80
+
+enum tokentype {
+ INTNUM = 258,
+ FLTNUM,
+ DIRECTIVE_NAME,
+ FILENAME,
+ STRING,
+ SIZE_OVERRIDE,
+ OFFSET,
+ DECLARE_DATA,
+ RESERVE_SPACE,
+ LABEL,
+ INCBIN,
+ EQU,
+ TIMES,
+ DUP,
+ SEG,
+ WRT,
+ ABS,
+ REL,
+ NOSPLIT,
+ STRICT,
+ INSN,
+ PREFIX,
+ REG,
+ REGGROUP,
+ SEGREG,
+ TARGETMOD,
+ LEFT_OP,
+ RIGHT_OP,
+ LOW,
+ HIGH,
+ SIGNDIV,
+ SIGNMOD,
+ START_SECTION_ID,
+ ID,
+ LOCAL_ID,
+ SPECIAL_ID,
+ NONLOCAL_ID,
+ LINE,
+ NONE /* special token for lookahead */
+};
+
+enum nasm_parser_state {
+ INITIAL,
+ DIRECTIVE,
+ SECTION_DIRECTIVE,
+ DIRECTIVE2,
+ LINECHG,
+ LINECHG2,
+ INSTRUCTION
+};
+
+#define YYSTYPE nasm_yystype
+
+/* shorter access names to commonly used parser_nasm fields */
+#define p_object (parser_nasm->object)
+#define p_symtab (parser_nasm->object->symtab)
+#define cursect (parser_nasm->object->cur_section)
+#define curtok (parser_nasm->token)
+#define curval (parser_nasm->tokval)
+
+#define INTNUM_val (curval.intn)
+#define FLTNUM_val (curval.flt)
+#define DIRECTIVE_NAME_val (curval.str_val)
+#define FILENAME_val (curval.str_val)
+#define STRING_val (curval.str)
+#define SIZE_OVERRIDE_val (curval.int_info)
+#define DECLARE_DATA_val (curval.int_info)
+#define RESERVE_SPACE_val (curval.int_info)
+#define INSN_val (curval.bc)
+#define PREFIX_val (curval.arch_data)
+#define REG_val (curval.arch_data)
+#define REGGROUP_val (curval.arch_data)
+#define SEGREG_val (curval.arch_data)
+#define TARGETMOD_val (curval.arch_data)
+#define ID_val (curval.str_val)
+
+#define cur_line (yasm_linemap_get_current(parser_nasm->linemap))
+
+#define p_expr_new_tree(l,o,r) yasm_expr_create_tree(l,o,r,cur_line)
+#define p_expr_new_branch(o,r) yasm_expr_create_branch(o,r,cur_line)
+#define p_expr_new_ident(r) yasm_expr_create_ident(r,cur_line)
+
+void nasm_parser_parse(yasm_parser_nasm *parser_nasm);
+void nasm_parser_cleanup(yasm_parser_nasm *parser_nasm);
+int nasm_parser_lex(YYSTYPE *lvalp, yasm_parser_nasm *parser_nasm);
+
+#endif