00
00
00
-16
+17
00
00
00
00
00
00
-16
+17
00
00
00
03
00
78
+70
+74
+72
00
00
00
00
+40
00
00
00
-00
+02
00
00
00
03
00
+78
+00
00
00
-03
00
-78
-70
-74
-72
00
00
00
00
-40
00
00
00
-02
+03
00
00
00
libyasm_a_SOURCES += modules/parsers/nasm/nasm-parser.c
libyasm_a_SOURCES += modules/parsers/nasm/nasm-parser.h
-libyasm_a_SOURCES += modules/parsers/nasm/nasm-defs.h
-libyasm_a_SOURCES += modules/parsers/nasm/nasm-bison.y
-libyasm_a_SOURCES += nasm-bison.h
+libyasm_a_SOURCES += modules/parsers/nasm/nasm-parse.c
libyasm_a_SOURCES += nasm-token.c
YASM_MODULES += parser_nasm
nasm-token.c: $(srcdir)/modules/parsers/nasm/nasm-token.re re2c$(EXEEXT)
$(top_builddir)/re2c$(EXEEXT) -b -o $@ $(srcdir)/modules/parsers/nasm/nasm-token.re
-BUILT_SOURCES += nasm-bison.c
-BUILT_SOURCES += nasm-bison.h
BUILT_SOURCES += nasm-token.c
-CLEANFILES += nasm-bison.c
-CLEANFILES += nasm-bison.h
CLEANFILES += nasm-token.c
EXTRA_DIST += modules/parsers/nasm/tests/Makefile.inc
+++ /dev/null
-/*
- * NASM-compatible bison parser
- *
- * Copyright (C) 2001 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>
-RCSID("$Id$");
-
-#define YASM_LIB_INTERNAL
-#define YASM_EXPR_INTERNAL
-#include <libyasm.h>
-
-#ifdef STDC_HEADERS
-# include <math.h>
-#endif
-
-#include "modules/parsers/nasm/nasm-parser.h"
-#include "modules/parsers/nasm/nasm-defs.h"
-
-static void nasm_parser_directive
- (yasm_parser_nasm *parser_nasm, const char *name,
- yasm_valparamhead *valparams,
- /*@null@*/ yasm_valparamhead *objext_valparams);
-static int fix_directive_symrec(/*@null@*/ yasm_expr__item *ei,
- /*@null@*/ void *d);
-static void define_label(yasm_parser_nasm *parser_nasm, /*@only@*/ char *name,
- int local);
-
-#define nasm_parser_error(s) yasm_error_set(YASM_ERROR_PARSE, "%s", s)
-#define YYPARSE_PARAM parser_nasm_arg
-#define YYLEX_PARAM parser_nasm_arg
-#define parser_nasm ((yasm_parser_nasm *)parser_nasm_arg)
-#define nasm_parser_debug (parser_nasm->debug)
-
-/*@-usedef -nullassign -memtrans -usereleased -compdef -mustfree@*/
-%}
-
-%pure_parser
-
-%union {
- unsigned int int_info;
- char *str_val;
- yasm_intnum *intn;
- yasm_floatnum *flt;
- yasm_symrec *sym;
- unsigned long arch_data[4];
- yasm_effaddr *ea;
- yasm_expr *exp;
- yasm_datavalhead datahead;
- yasm_dataval *data;
- yasm_bytecode *bc;
- yasm_valparamhead dir_valparams;
- yasm_valparam *dir_valparam;
- struct {
- yasm_insn_operands operands;
- int num_operands;
- } insn_operands;
- yasm_insn_operand *insn_operand;
- struct {
- char *name;
- int local;
- } label;
- struct {
- char *contents;
- size_t len;
- } str;
-}
-
-%token <intn> INTNUM
-%token <flt> FLTNUM
-%token <str_val> DIRECTIVE_NAME FILENAME
-%token <str> STRING ONECHARSTR
-%token <int_info> SIZE_OVERRIDE
-%token <int_info> DECLARE_DATA
-%token <int_info> RESERVE_SPACE
-%token INCBIN EQU TIMES
-%token SEG WRT NOSPLIT STRICT
-%token <arch_data> INSN PREFIX REG SEGREG TARGETMOD
-%token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD START_SECTION_ID
-%token <str_val> ID LOCAL_ID SPECIAL_ID
-%token LINE
-
-%type <bc> line lineexp exp instr
-
-%type <ea> memaddr
-%type <exp> dvexpr expr direxpr
-%type <sym> explabel
-%type <label> label_id label
-%type <data> dataval
-%type <datahead> datavals
-%type <dir_valparams> directive_valparams
-%type <dir_valparam> directive_valparam
-%type <insn_operands> operands
-%type <insn_operand> operand
-%type <str> string
-
-%left ':'
-%left WRT
-%left '|'
-%left '^'
-%left '&'
-%left LEFT_OP RIGHT_OP
-%left '-' '+'
-%left '*' '/' SIGNDIV '%' SIGNMOD
-%nonassoc UNARYOP
-%nonassoc SEG
-
-%%
-input: /* empty */
- | input line {
- yasm_errwarn_propagate(parser_nasm->errwarns, cur_line);
- parser_nasm->temp_bc =
- yasm_section_bcs_append(parser_nasm->cur_section, $2);
- if (parser_nasm->temp_bc)
- parser_nasm->prev_bc = parser_nasm->temp_bc;
- if (parser_nasm->save_input)
- yasm_linemap_add_source(parser_nasm->linemap,
- parser_nasm->temp_bc,
- (char *)parser_nasm->save_line[parser_nasm->save_last ^ 1]);
- yasm_linemap_goto_next(parser_nasm->linemap);
- }
-;
-
-line: '\n' { $$ = (yasm_bytecode *)NULL; }
- | lineexp '\n'
- | LINE INTNUM '+' INTNUM FILENAME '\n' {
- /* %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, $5,
- yasm_intnum_get_uint($2) - yasm_intnum_get_uint($4),
- yasm_intnum_get_uint($4));
- yasm_intnum_destroy($2);
- yasm_intnum_destroy($4);
- yasm_xfree($5);
- $$ = (yasm_bytecode *)NULL;
- }
- | '[' { parser_nasm->state = DIRECTIVE; } directive ']' '\n' {
- $$ = (yasm_bytecode *)NULL;
- }
- | error '\n' {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("label or instruction expected at start of line"));
- $$ = (yasm_bytecode *)NULL;
- yyerrok;
- }
-;
-
-lineexp: exp
- | TIMES expr exp { $$ = $3; yasm_bc_set_multiple($$, $2); }
- | label_id {
- yasm_warn_set(YASM_WARN_ORPHAN_LABEL,
- N_("label alone on a line without a colon might be in error"));
- $$ = (yasm_bytecode *)NULL;
- define_label(parser_nasm, $1.name, $1.local);
- }
- | label_id ':' {
- $$ = (yasm_bytecode *)NULL;
- define_label(parser_nasm, $1.name, $1.local);
- }
- | label exp {
- $$ = $2;
- define_label(parser_nasm, $1.name, $1.local);
- }
- | label TIMES expr exp {
- $$ = $4;
- yasm_bc_set_multiple($$, $3);
- define_label(parser_nasm, $1.name, $1.local);
- }
- | label EQU expr {
- $$ = (yasm_bytecode *)NULL;
- yasm_symtab_define_equ(p_symtab, $1.name, $3, cur_line);
- yasm_xfree($1.name);
- }
-;
-
-exp: instr
- | DECLARE_DATA datavals {
- $$ = yasm_bc_create_data(&$2, $1/8, 0, parser_nasm->arch, cur_line);
- }
- | RESERVE_SPACE expr {
- $$ = yasm_bc_create_reserve($2, $1/8, cur_line);
- }
- | INCBIN string {
- $$ = yasm_bc_create_incbin($2.contents, NULL, NULL,
- parser_nasm->linemap, cur_line);
- }
- | INCBIN string ',' {
- $$ = yasm_bc_create_incbin($2.contents, NULL, NULL,
- parser_nasm->linemap, cur_line);
- }
- | INCBIN string ',' expr {
- $$ = yasm_bc_create_incbin($2.contents, $4, NULL,
- parser_nasm->linemap, cur_line);
- }
- | INCBIN string ',' expr ',' {
- $$ = yasm_bc_create_incbin($2.contents, $4, NULL,
- parser_nasm->linemap, cur_line);
- }
- | INCBIN string ',' expr ',' expr {
- $$ = yasm_bc_create_incbin($2.contents, $4, $6, parser_nasm->linemap,
- cur_line);
- }
-;
-
-instr: INSN {
- $$ = yasm_bc_create_insn(parser_nasm->arch, $1, 0, NULL, cur_line);
- }
- | INSN operands {
- $$ = yasm_bc_create_insn(parser_nasm->arch, $1, $2.num_operands,
- &$2.operands, cur_line);
- }
- | INSN error {
- yasm_error_set(YASM_ERROR_SYNTAX, N_("expression syntax error"));
- $$ = NULL;
- }
- | PREFIX instr {
- $$ = $2;
- yasm_bc_insn_add_prefix($$, $1);
- }
- | SEGREG instr {
- $$ = $2;
- yasm_bc_insn_add_seg_prefix($$, $1[0]);
- }
-;
-
-datavals: dataval {
- yasm_dvs_initialize(&$$);
- yasm_dvs_append(&$$, $1);
- }
- | datavals ',' dataval { yasm_dvs_append(&$1, $3); $$ = $1; }
- | datavals ',' { $$ = $1; }
-;
-
-dataval: dvexpr { $$ = yasm_dv_create_expr($1); }
- | STRING {
- $$ = yasm_dv_create_string($1.contents, $1.len);
- }
- | error {
- yasm_error_set(YASM_ERROR_SYNTAX, N_("expression syntax error"));
- $$ = (yasm_dataval *)NULL;
- }
-;
-
-label: label_id
- | label_id ':' { $$ = $1; }
-;
-
-label_id: ID { $$.name = $1; $$.local = 0; }
- | SPECIAL_ID { $$.name = $1; $$.local = 1; }
- | LOCAL_ID { $$.name = $1; $$.local = 1; }
-;
-
-/* directives */
-directive: DIRECTIVE_NAME directive_val {
- yasm_xfree($1);
- }
- | DIRECTIVE_NAME error {
- yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid arguments to [%s]"), $1);
- yasm_xfree($1);
- }
-;
-
- /* $<str_val>0 is the DIRECTIVE_NAME */
- /* After : is (optional) object-format specific extension */
-directive_val: directive_valparams {
- nasm_parser_directive(parser_nasm, $<str_val>0, &$1, NULL);
- }
- | directive_valparams ':' directive_valparams {
- nasm_parser_directive(parser_nasm, $<str_val>0, &$1, &$3);
- }
-;
-
-directive_valparams: directive_valparam {
- yasm_vps_initialize(&$$);
- yasm_vps_append(&$$, $1);
- }
- | directive_valparams directive_valparam {
- yasm_vps_append(&$1, $2);
- $$ = $1;
- }
- | directive_valparams ',' directive_valparam {
- yasm_vps_append(&$1, $3);
- $$ = $1;
- }
-;
-
-directive_valparam: direxpr {
- /* If direxpr is just an ID, put it in val and delete the expr.
- * Otherwise, we need to go through the expr and replace the current
- * (local) symrecs with the use of global ones.
- */
- const /*@null@*/ yasm_symrec *vp_symrec;
- if ((vp_symrec = yasm_expr_get_symrec(&$1, 0))) {
- $$ = yasm_vp_create(yasm__xstrdup(yasm_symrec_get_name(vp_symrec)),
- NULL);
- yasm_expr_destroy($1);
- } else {
- yasm_expr__traverse_leaves_in($1, parser_nasm,
- fix_directive_symrec);
- $$ = yasm_vp_create(NULL, $1);
- }
- }
- | string { $$ = yasm_vp_create($1.contents, NULL); }
- | ID '=' direxpr {
- yasm_expr__traverse_leaves_in($3, parser_nasm, fix_directive_symrec);
- $$ = yasm_vp_create($1, $3);
- }
-;
-
-/* memory addresses */
-memaddr: expr {
- $$ = yasm_arch_ea_create(parser_nasm->arch, $1);
- }
- | SEGREG ':' memaddr {
- $$ = $3;
- yasm_ea_set_segreg($$, $1[0]);
- }
- | SIZE_OVERRIDE memaddr { $$ = $2; yasm_ea_set_len($$, $1); }
- | NOSPLIT memaddr { $$ = $2; yasm_ea_set_nosplit($$, 1); }
-;
-
-/* instruction operands */
-operands: operand {
- yasm_ops_initialize(&$$.operands);
- yasm_ops_append(&$$.operands, $1);
- $$.num_operands = 1;
- }
- | operands ',' operand {
- yasm_ops_append(&$1.operands, $3);
- $$.operands = $1.operands;
- $$.num_operands = $1.num_operands+1;
- }
-;
-
-operand: '[' memaddr ']' { $$ = yasm_operand_create_mem($2); }
- | expr { $$ = yasm_operand_create_imm($1); }
- | SEGREG { $$ = yasm_operand_create_segreg($1[0]); }
- | STRICT operand { $$ = $2; $$->strict = 1; }
- | SIZE_OVERRIDE operand {
- $$ = $2;
- if ($$->type == YASM_INSN__OPERAND_REG &&
- yasm_arch_get_reg_size(parser_nasm->arch, $$->data.reg) != $1)
- yasm_error_set(YASM_ERROR_TYPE,
- N_("cannot override register size"));
- else
- $$->size = $1;
- }
- | TARGETMOD operand { $$ = $2; $$->targetmod = $1[0]; }
-;
-
-/* expression trees */
-
-/* expr w/o FLTNUM and unary + and -, for use in directives */
-direxpr: INTNUM { $$ = p_expr_new_ident(yasm_expr_int($1)); }
- | ID {
- $$ = p_expr_new_ident(yasm_expr_sym(
- yasm_symtab_define_label(p_symtab, $1,
- yasm_section_bcs_first(parser_nasm->cur_section), 0,
- cur_line)));
- yasm_xfree($1);
- }
- | direxpr '|' direxpr { $$ = p_expr_new_tree($1, YASM_EXPR_OR, $3); }
- | direxpr '^' direxpr { $$ = p_expr_new_tree($1, YASM_EXPR_XOR, $3); }
- | direxpr '&' direxpr { $$ = p_expr_new_tree($1, YASM_EXPR_AND, $3); }
- | direxpr LEFT_OP direxpr { $$ = p_expr_new_tree($1, YASM_EXPR_SHL, $3); }
- | direxpr RIGHT_OP direxpr { $$ = p_expr_new_tree($1, YASM_EXPR_SHR, $3); }
- | direxpr '+' direxpr { $$ = p_expr_new_tree($1, YASM_EXPR_ADD, $3); }
- | direxpr '-' direxpr { $$ = p_expr_new_tree($1, YASM_EXPR_SUB, $3); }
- | direxpr '*' direxpr { $$ = p_expr_new_tree($1, YASM_EXPR_MUL, $3); }
- | direxpr '/' direxpr { $$ = p_expr_new_tree($1, YASM_EXPR_DIV, $3); }
- | direxpr SIGNDIV direxpr { $$ = p_expr_new_tree($1, YASM_EXPR_SIGNDIV, $3); }
- | direxpr '%' direxpr { $$ = p_expr_new_tree($1, YASM_EXPR_MOD, $3); }
- | direxpr SIGNMOD direxpr { $$ = p_expr_new_tree($1, YASM_EXPR_SIGNMOD, $3); }
- /*| '!' expr { $$ = p_expr_new_branch(YASM_EXPR_LNOT, $2); }*/
- | '~' direxpr %prec UNARYOP { $$ = p_expr_new_branch(YASM_EXPR_NOT, $2); }
- | '(' direxpr ')' { $$ = $2; }
-;
-
-dvexpr: INTNUM { $$ = p_expr_new_ident(yasm_expr_int($1)); }
- | FLTNUM { $$ = p_expr_new_ident(yasm_expr_float($1)); }
- | ONECHARSTR {
- $$ = p_expr_new_ident(yasm_expr_int(
- yasm_intnum_create_charconst_nasm($1.contents)));
- yasm_xfree($1.contents);
- }
- | explabel { $$ = p_expr_new_ident(yasm_expr_sym($1)); }
- /*| dvexpr '||' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_LOR, $3); }*/
- | dvexpr '|' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_OR, $3); }
- | dvexpr '^' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_XOR, $3); }
- /*| dvexpr '&&' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_LAND, $3); }*/
- | dvexpr '&' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_AND, $3); }
- /*| dvexpr '==' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_EQUALS, $3); }*/
- /*| dvexpr '>' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_GT, $3); }*/
- /*| dvexpr '<' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_GT, $3); }*/
- /*| dvexpr '>=' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_GE, $3); }*/
- /*| dvexpr '<=' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_GE, $3); }*/
- /*| dvexpr '!=' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_NE, $3); }*/
- | dvexpr LEFT_OP dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_SHL, $3); }
- | dvexpr RIGHT_OP dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_SHR, $3); }
- | dvexpr '+' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_ADD, $3); }
- | dvexpr '-' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_SUB, $3); }
- | dvexpr '*' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_MUL, $3); }
- | dvexpr '/' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_DIV, $3); }
- | dvexpr SIGNDIV dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_SIGNDIV, $3); }
- | dvexpr '%' dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_MOD, $3); }
- | dvexpr SIGNMOD dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_SIGNMOD, $3); }
- | '+' dvexpr %prec UNARYOP { $$ = $2; }
- | '-' dvexpr %prec UNARYOP { $$ = p_expr_new_branch(YASM_EXPR_NEG, $2); }
- /*| '!' dvexpr { $$ = p_expr_new_branch(YASM_EXPR_LNOT, $2); }*/
- | '~' dvexpr %prec UNARYOP { $$ = p_expr_new_branch(YASM_EXPR_NOT, $2); }
- | SEG dvexpr { $$ = p_expr_new_branch(YASM_EXPR_SEG, $2); }
- | dvexpr WRT dvexpr { $$ = p_expr_new_tree($1, YASM_EXPR_WRT, $3); }
- | '(' dvexpr ')' { $$ = $2; }
-;
-
-/* Expressions for operands and memory expressions.
- * We don't attempt to check memory expressions for validity here.
- * Essentially the same as dvexpr above but adds REG and string.
- */
-expr: INTNUM { $$ = p_expr_new_ident(yasm_expr_int($1)); }
- | FLTNUM { $$ = p_expr_new_ident(yasm_expr_float($1)); }
- | REG { $$ = p_expr_new_ident(yasm_expr_reg($1[0])); }
- | string {
- $$ = p_expr_new_ident(yasm_expr_int(
- yasm_intnum_create_charconst_nasm($1.contents)));
- yasm_xfree($1.contents);
- }
- | explabel { $$ = p_expr_new_ident(yasm_expr_sym($1)); }
- /*| expr '||' expr { $$ = p_expr_new_tree($1, YASM_EXPR_LOR, $3); }*/
- | expr '|' expr { $$ = p_expr_new_tree($1, YASM_EXPR_OR, $3); }
- | expr '^' expr { $$ = p_expr_new_tree($1, YASM_EXPR_XOR, $3); }
- /*| expr '&&' expr { $$ = p_expr_new_tree($1, YASM_EXPR_LAND, $3); }*/
- | expr '&' expr { $$ = p_expr_new_tree($1, YASM_EXPR_AND, $3); }
- /*| expr '==' expr { $$ = p_expr_new_tree($1, YASM_EXPR_EQUALS, $3); }*/
- /*| expr '>' expr { $$ = p_expr_new_tree($1, YASM_EXPR_GT, $3); }*/
- /*| expr '<' expr { $$ = p_expr_new_tree($1, YASM_EXPR_GT, $3); }*/
- /*| expr '>=' expr { $$ = p_expr_new_tree($1, YASM_EXPR_GE, $3); }*/
- /*| expr '<=' expr { $$ = p_expr_new_tree($1, YASM_EXPR_GE, $3); }*/
- /*| expr '!=' expr { $$ = p_expr_new_tree($1, YASM_EXPR_NE, $3); }*/
- | expr LEFT_OP expr { $$ = p_expr_new_tree($1, YASM_EXPR_SHL, $3); }
- | expr RIGHT_OP expr { $$ = p_expr_new_tree($1, YASM_EXPR_SHR, $3); }
- | expr '+' expr { $$ = p_expr_new_tree($1, YASM_EXPR_ADD, $3); }
- | expr '-' expr { $$ = p_expr_new_tree($1, YASM_EXPR_SUB, $3); }
- | expr '*' expr { $$ = p_expr_new_tree($1, YASM_EXPR_MUL, $3); }
- | expr '/' expr { $$ = p_expr_new_tree($1, YASM_EXPR_DIV, $3); }
- | expr SIGNDIV expr { $$ = p_expr_new_tree($1, YASM_EXPR_SIGNDIV, $3); }
- | expr '%' expr { $$ = p_expr_new_tree($1, YASM_EXPR_MOD, $3); }
- | expr SIGNMOD expr { $$ = p_expr_new_tree($1, YASM_EXPR_SIGNMOD, $3); }
- | '+' expr %prec UNARYOP { $$ = $2; }
- | '-' expr %prec UNARYOP { $$ = p_expr_new_branch(YASM_EXPR_NEG, $2); }
- /*| '!' expr { $$ = p_expr_new_branch(YASM_EXPR_LNOT, $2); }*/
- | '~' expr %prec UNARYOP { $$ = p_expr_new_branch(YASM_EXPR_NOT, $2); }
- | SEG expr { $$ = p_expr_new_branch(YASM_EXPR_SEG, $2); }
- | expr WRT expr { $$ = p_expr_new_tree($1, YASM_EXPR_WRT, $3); }
- | expr ':' expr { $$ = p_expr_new_tree($1, YASM_EXPR_SEGOFF, $3); }
- | '(' expr ')' { $$ = $2; }
-;
-
-explabel: ID {
- $$ = yasm_symtab_use(p_symtab, $1, cur_line);
- yasm_xfree($1);
- }
- | SPECIAL_ID {
- $$ = yasm_symtab_use(p_symtab, $1, cur_line);
- yasm_xfree($1);
- }
- | LOCAL_ID {
- $$ = yasm_symtab_use(p_symtab, $1, cur_line);
- yasm_xfree($1);
- }
- | '$' {
- /* "$" references the current assembly position */
- $$ = yasm_symtab_define_curpos(p_symtab, "$", parser_nasm->prev_bc,
- cur_line);
- }
- | START_SECTION_ID {
- /* "$$" references the start of the current section */
- $$ = yasm_symtab_define_label(p_symtab, "$$",
- yasm_section_bcs_first(parser_nasm->cur_section), 0, cur_line);
- }
-;
-
-string: STRING | ONECHARSTR;
-
-%%
-/*@=usedef =nullassign =memtrans =usereleased =compdef =mustfree@*/
-
-#undef parser_nasm
-
-static void
-define_label(yasm_parser_nasm *parser_nasm, char *name, int local)
-{
- if (!local) {
- 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);
- }
-
- yasm_symtab_define_label(p_symtab, name, parser_nasm->prev_bc, 1,
- cur_line);
- yasm_xfree(name);
-}
-
-static int
-fix_directive_symrec(yasm_expr__item *ei, void *d)
-{
- yasm_parser_nasm *parser_nasm = (yasm_parser_nasm *)d;
- if (!ei || ei->type != YASM_EXPR_SYM)
- return 0;
-
- /* FIXME: Delete current symrec */
- ei->data.sym =
- yasm_symtab_use(p_symtab, yasm_symrec_get_name(ei->data.sym),
- cur_line);
-
- return 0;
-}
-
-static void
-nasm_parser_directive(yasm_parser_nasm *parser_nasm, const char *name,
- yasm_valparamhead *valparams,
- yasm_valparamhead *objext_valparams)
-{
- yasm_valparam *vp, *vp2;
- unsigned long line = cur_line;
-
- /* Handle (mostly) output-format independent directives here */
- if (yasm__strcasecmp(name, "extern") == 0) {
- vp = yasm_vps_first(valparams);
- if (vp->val) {
- yasm_objfmt_extern_declare(parser_nasm->objfmt, vp->val,
- objext_valparams, line);
- } else
- yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid argument to [%s]"),
- "EXTERN");
- } else if (yasm__strcasecmp(name, "global") == 0) {
- vp = yasm_vps_first(valparams);
- if (vp->val) {
- yasm_objfmt_global_declare(parser_nasm->objfmt, vp->val,
- objext_valparams, line);
- } else
- yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid argument to [%s]"),
- "GLOBAL");
- } else if (yasm__strcasecmp(name, "common") == 0) {
- vp = yasm_vps_first(valparams);
- if (vp->val) {
- vp2 = yasm_vps_next(vp);
- if (!vp2 || (!vp2->val && !vp2->param))
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("no size specified in %s declaration"),
- "COMMON");
- else {
- if (vp2->val) {
- yasm_objfmt_common_declare(parser_nasm->objfmt, vp->val,
- p_expr_new_ident(yasm_expr_sym(
- yasm_symtab_use(p_symtab, vp2->val, line))),
- objext_valparams, line);
- } else if (vp2->param) {
- yasm_objfmt_common_declare(parser_nasm->objfmt, vp->val,
- vp2->param, objext_valparams,
- line);
- vp2->param = NULL;
- }
- }
- } else
- yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid argument to [%s]"),
- "COMMON");
- } else if (yasm__strcasecmp(name, "section") == 0 ||
- yasm__strcasecmp(name, "segment") == 0) {
- yasm_section *new_section =
- yasm_objfmt_section_switch(parser_nasm->objfmt, valparams,
- objext_valparams, line);
- if (new_section) {
- parser_nasm->cur_section = new_section;
- parser_nasm->prev_bc = yasm_section_bcs_last(new_section);
- } else
- yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid argument to [%s]"),
- "SECTION");
- } else if (yasm__strcasecmp(name, "absolute") == 0) {
- /* it can be just an ID or a complete expression, so handle both. */
- vp = yasm_vps_first(valparams);
- if (vp->val)
- parser_nasm->cur_section =
- yasm_object_create_absolute(parser_nasm->object,
- p_expr_new_ident(yasm_expr_sym(
- yasm_symtab_use(p_symtab, vp->val, line))), line);
- else if (vp->param) {
- parser_nasm->cur_section =
- yasm_object_create_absolute(parser_nasm->object, vp->param,
- line);
- vp->param = NULL;
- }
- parser_nasm->prev_bc = yasm_section_bcs_last(parser_nasm->cur_section);
- } else if (yasm__strcasecmp(name, "align") == 0) {
- /*@only@*/ yasm_expr *boundval;
- /*@depedent@*/ yasm_intnum *boundintn;
-
- /* it can be just an ID or a complete expression, so handle both. */
- vp = yasm_vps_first(valparams);
- if (vp->val)
- boundval = p_expr_new_ident(yasm_expr_sym(
- yasm_symtab_use(p_symtab, vp->val, line)));
- else if (vp->param) {
- boundval = vp->param;
- vp->param = NULL;
- }
-
- /* Largest .align in the section specifies section alignment.
- * Note: this doesn't match NASM behavior, but is a lot more
- * intelligent!
- */
- 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(parser_nasm->cur_section))
- yasm_section_set_align(parser_nasm->cur_section, boundint,
- cur_line);
- }
- }
-
- /* As this directive is called only when nop is used as fill, always
- * use arch (nop) fill.
- */
- parser_nasm->prev_bc =
- yasm_section_bcs_append(parser_nasm->cur_section,
- yasm_bc_create_align(boundval, NULL, NULL,
- /*yasm_section_is_code(parser_nasm->cur_section) ?*/
- yasm_arch_get_fill(parser_nasm->arch)/* : NULL*/,
- cur_line));
- } else if (yasm__strcasecmp(name, "cpu") == 0) {
- yasm_vps_foreach(vp, valparams) {
- if (vp->val)
- yasm_arch_parse_cpu(parser_nasm->arch, vp->val,
- strlen(vp->val));
- else if (vp->param) {
- const yasm_intnum *intcpu;
- intcpu = yasm_expr_get_intnum(&vp->param, 0);
- if (!intcpu)
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("invalid argument to [%s]"), "CPU");
- else {
- char strcpu[16];
- sprintf(strcpu, "%lu", yasm_intnum_get_uint(intcpu));
- yasm_arch_parse_cpu(parser_nasm->arch, strcpu,
- strlen(strcpu));
- }
- }
- }
- } else if (!yasm_arch_parse_directive(parser_nasm->arch, name, valparams,
- objext_valparams, parser_nasm->object, line)) {
- ;
- } else if (!yasm_dbgfmt_directive(parser_nasm->dbgfmt, name,
- parser_nasm->cur_section, valparams,
- line)) {
- ;
- } else if (yasm_objfmt_directive(parser_nasm->objfmt, name, valparams,
- objext_valparams, line)) {
- yasm_error_set(YASM_ERROR_SYNTAX, N_("unrecognized directive [%s]"),
- name);
- }
-
- yasm_vps_delete(valparams);
- if (objext_valparams)
- yasm_vps_delete(objext_valparams);
-}
+++ /dev/null
-/* $Id$
- * Variable name redefinitions for NASM-compatible parser
- *
- * Copyright (C) 2001 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.
- */
-#define yy_create_buffer nasm_parser__create_buffer
-#define yy_delete_buffer nasm_parser__delete_buffer
-#define yy_init_buffer nasm_parser__init_buffer
-#define yy_load_buffer_state nasm_parser__load_buffer_state
-#define yy_switch_to_buffer nasm_parser__switch_to_buffer
-#define yyact nasm_parser_act
-#define yyback nasm_parser_back
-#define yybgin nasm_parser_bgin
-#define yychar nasm_parser_char
-#define yychk nasm_parser_chk
-#define yycrank nasm_parser_crank
-#define yydebug nasm_parser_debug
-#define yydef nasm_parser_def
-#define yyerrflag nasm_parser_errflag
-#define yyerror nasm_parser_error
-#define yyestate nasm_parser_estate
-#define yyexca nasm_parser_exca
-#define yyextra nasm_parser_extra
-#define yyfnd nasm_parser_fnd
-#define yyin nasm_parser_in
-#define yyinput nasm_parser_input
-#define yyleng nasm_parser_leng
-#define yylex nasm_parser_lex
-#define yylineno nasm_parser_lineno
-#define yylook nasm_parser_look
-#define yylsp nasm_parser_lsp
-#define yylstate nasm_parser_lstate
-#define yylval nasm_parser_lval
-#define yymatch nasm_parser_match
-#define yymorfg nasm_parser_morfg
-#define yynerrs nasm_parser_nerrs
-#define yyolsp nasm_parser_olsp
-#define yyout nasm_parser_out
-#define yyoutput nasm_parser_output
-#define yypact nasm_parser_pact
-#define yyparse nasm_parser_parse
-#define yypgo nasm_parser_pgo
-#define yyprevious nasm_parser_previous
-#define yyps nasm_parser_ps
-#define yypv nasm_parser_pv
-#define yyr1 nasm_parser_r1
-#define yyr2 nasm_parser_r2
-#define yyreds nasm_parser_reds
-#define yyrestart nasm_parser_restart
-#define yys nasm_parser_s
-#define yysbuf nasm_parser_sbuf
-#define yysptr nasm_parser_sptr
-#define yystate nasm_parser_state
-#define yysvec nasm_parser_svec
-#define yytchar nasm_parser_tchar
-#define yytext nasm_parser_text
-#define yytmp nasm_parser_tmp
-#define yytoks nasm_parser_toks
-#define yytop nasm_parser_top
-#define yyunput nasm_parser_unput
-#define yyv nasm_parser_v
-#define yyval nasm_parser_val
-#define yyvstop nasm_parser_vstop
-/*#define yywrap nasm_parser_wrap*/
--- /dev/null
+/*
+ * NASM-compatible parser
+ *
+ * Copyright (C) 2001 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>
+RCSID("$Id$");
+
+#define YASM_LIB_INTERNAL
+#define YASM_EXPR_INTERNAL
+#include <libyasm.h>
+
+#ifdef STDC_HEADERS
+# include <math.h>
+#endif
+
+#include "modules/parsers/nasm/nasm-parser.h"
+
+typedef enum {
+ NORM_EXPR,
+ DIR_EXPR,
+ DV_EXPR
+} 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_effaddr *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,
+ yasm_valparamhead *valparams,
+ /*@null@*/ yasm_valparamhead *objext_valparams);
+static int fix_directive_symrec(/*@null@*/ yasm_expr__item *ei,
+ /*@null@*/ void *d);
+static void define_label(yasm_parser_nasm *parser_nasm, /*@only@*/ char *name,
+ int local);
+
+#define is_eol_tok(tok) ((tok) == '\n' || (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:
+ yasm_xfree(curval.str_val);
+ break;
+ case STRING:
+ yasm_xfree(curval.str.contents);
+ break;
+ default:
+ break;
+ }
+ curtok = 0; /* 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)
+{
+ size_t zero = 0;
+ char ch;
+
+ 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 {
+ get_next_token();
+ destroy_curtok();
+ } while (!is_eol());
+}
+#define demand_eol() demand_eol_(parser_nasm)
+
+static int
+expect_(yasm_parser_nasm *parser_nasm, int token)
+{
+ static char strch[] = "expected ` '";
+ const char *str;
+
+ if (curtok == token)
+ return 1;
+
+ switch (token) {
+ case INTNUM: str = "expected integer"; break;
+ case FLTNUM: str = "expected floating point value"; break;
+ case DIRECTIVE_NAME: str = "expected directive name"; break;
+ case FILENAME: str = "expected filename"; break;
+ case STRING: str = "expected string"; break;
+ case SIZE_OVERRIDE: str = "expected size override"; break;
+ case DECLARE_DATA: str = "expected DB/DW/etc."; break;
+ case RESERVE_SPACE: str = "expected RESB/RESW/etc."; break;
+ case INCBIN: str = "expected INCBIN"; break;
+ case EQU: str = "expected EQU"; break;
+ case TIMES: str = "expected TIMES"; break;
+ case SEG: str = "expected SEG"; break;
+ case WRT: str = "expected WRT"; break;
+ case NOSPLIT: str = "expected NOSPLIT"; break;
+ case STRICT: str = "expected STRICT"; break;
+ case INSN: str = "expected instruction"; break;
+ case PREFIX: str = "expected instruction prefix"; break;
+ case REG: str = "expected register"; break;
+ case SEGREG: str = "expected segment register"; break;
+ case TARGETMOD: str = "expected target modifier"; break;
+ case LEFT_OP: str = "expected <<"; break;
+ case RIGHT_OP: str = "expected >>"; break;
+ case SIGNDIV: str = "expected //"; break;
+ case SIGNMOD: str = "expected %%"; break;
+ case START_SECTION_ID: str = "expected $$"; break;
+ case ID: str = "expected identifier"; break;
+ case LOCAL_ID: str = "expected .identifier"; break;
+ case SPECIAL_ID: str = "expected ..identifier"; break;
+ case LINE: str = "expected %line"; break;
+ default:
+ strch[10] = token;
+ str = strch;
+ break;
+ }
+ yasm_error_set(YASM_ERROR_PARSE, str);
+ destroy_curtok();
+ return 0;
+}
+#define expect(token) expect_(parser_nasm, token)
+
+void
+nasm_parser_parse(yasm_parser_nasm *parser_nasm)
+{
+ while (get_next_token() != 0) {
+ yasm_bytecode *bc = NULL, *temp_bc;
+
+ if (!is_eol()) {
+ bc = parse_line(parser_nasm);
+ demand_eol();
+ }
+
+ yasm_errwarn_propagate(parser_nasm->errwarns, cur_line);
+
+ temp_bc = yasm_section_bcs_append(parser_nasm->cur_section, bc);
+ if (temp_bc)
+ parser_nasm->prev_bc = temp_bc;
+ if (parser_nasm->save_input)
+ yasm_linemap_add_source(parser_nasm->linemap,
+ temp_bc,
+ (char *)parser_nasm->save_line[parser_nasm->save_last ^ 1]);
+ yasm_linemap_goto_next(parser_nasm->linemap);
+ }
+}
+
+/* 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;
+
+ 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,
+ 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;
+
+ parser_nasm->state = DIRECTIVE;
+ get_next_token();
+
+ if (!expect(DIRECTIVE_NAME))
+ return NULL;
+ dirname = DIRECTIVE_NAME_val;
+ get_next_token();
+
+ 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, &dir_vps,
+ &ext_vps);
+ } else
+ nasm_parser_directive(parser_nasm, dirname, &dir_vps, 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 LOCAL_ID:
+ {
+ char *name = ID_val;
+ int local = (curtok != ID);
+
+ 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"));
+ define_label(parser_nasm, name, local);
+ return NULL;
+ }
+ if (curtok == ':')
+ get_next_token();
+
+ if (curtok == EQU) {
+ /* label EQU expr */
+ yasm_expr *e;
+ 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;
+ }
+
+ define_label(parser_nasm, name, local);
+ if (is_eol())
+ return NULL;
+ if (curtok == TIMES) {
+ get_next_token();
+ return parse_times(parser_nasm);
+ }
+ bc = parse_exp(parser_nasm);
+ if (!bc)
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("instruction expected after label"));
+ return bc;
+ }
+ default:
+ bc = parse_exp(parser_nasm);
+ if (!bc)
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("label or instruction expected at start of line"));
+ return bc;
+ }
+}
+
+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;
+
+ switch (curtok) {
+ case STRING:
+ vp = yasm_vp_create(STRING_val.contents, NULL);
+ get_next_token();
+ break;
+ case ID:
+ {
+ char *id = ID_val;
+ get_peek_token(parser_nasm);
+ if (parser_nasm->peek_token == '=') {
+ get_next_token(); /* id */
+ get_next_token(); /* = */
+ e = parse_expr(parser_nasm, DIR_EXPR);
+ if (!e) {
+ yasm_vps_delete(vps);
+ return 0;
+ }
+ yasm_expr__traverse_leaves_in(e, parser_nasm,
+ fix_directive_symrec);
+ vp = yasm_vp_create(id, e);
+ break;
+ }
+ if (parser_nasm->peek_token == ','
+ || parser_nasm->peek_token == ']'
+ || parser_nasm->peek_token == ':') {
+ /* Try to catch just IDs here first */
+ get_next_token(); /* id */
+ vp = yasm_vp_create(id, NULL);
+ break;
+ }
+ /*@fallthrough@*/
+ }
+ default:
+ {
+ /* If direxpr is just an ID, put it in val and delete the expr.
+ * Otherwise, we need to go through the expr and replace the
+ * current (local) symrecs with the use of global ones.
+ */
+ const /*@null@*/ yasm_symrec *vp_symrec;
+ e = parse_expr(parser_nasm, DIR_EXPR);
+ if (!e) {
+ yasm_vps_delete(vps);
+ return 0;
+ }
+ if ((vp_symrec = yasm_expr_get_symrec(&e, 0))) {
+ vp = yasm_vp_create(
+ yasm__xstrdup(yasm_symrec_get_name(vp_symrec)), NULL);
+ yasm_expr_destroy(e);
+ } else {
+ yasm_expr__traverse_leaves_in(e, parser_nasm,
+ fix_directive_symrec);
+ vp = yasm_vp_create(NULL, e);
+ }
+ }
+ }
+
+ 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_expr(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)
+{
+ switch (curtok) {
+ case DECLARE_DATA:
+ {
+ unsigned int size = DECLARE_DATA_val/8;
+ yasm_datavalhead dvs;
+ yasm_dataval *dv;
+ yasm_expr *e;
+
+ 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 ((e = parse_expr(parser_nasm, DV_EXPR)))
+ dv = yasm_dv_create_expr(e);
+ else {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expression or string expected"));
+ yasm_dvs_delete(&dvs);
+ return NULL;
+ }
+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, parser_nasm->arch,
+ cur_line);
+ }
+ case RESERVE_SPACE:
+ {
+ unsigned int size = RESERVE_SPACE_val/8;
+ yasm_expr *e;
+ get_next_token();
+ e = parse_expr(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_expr(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_expr(parser_nasm, DV_EXPR);
+ if (!start) {
+ 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 parse_instr(parser_nasm);
+ }
+}
+
+static yasm_bytecode *
+parse_instr(yasm_parser_nasm *parser_nasm)
+{
+ switch (curtok) {
+ case INSN:
+ {
+ yystype insn = curval; /* structure copy */
+ yasm_insn_operands operands;
+ int num_operands = 0;
+
+ get_next_token();
+ if (is_eol()) {
+ /* no operands */
+ return yasm_bc_create_insn(parser_nasm->arch, insn.arch_data,
+ 0, NULL, cur_line);
+ }
+
+ /* parse operands */
+ yasm_ops_initialize(&operands);
+ for (;;) {
+ yasm_insn_operand *op = parse_operand(parser_nasm);
+ if (!op) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expression syntax error"));
+ yasm_ops_delete(&operands, 1);
+ return NULL;
+ }
+ yasm_ops_append(&operands, op);
+ num_operands++;
+
+ if (is_eol())
+ break;
+ if (!expect(',')) {
+ yasm_ops_delete(&operands, 1);
+ return NULL;
+ }
+ get_next_token();
+ }
+ return yasm_bc_create_insn(parser_nasm->arch, insn.arch_data,
+ num_operands, &operands, cur_line);
+ }
+ case PREFIX: {
+ yystype prefix = curval; /* structure copy */
+ yasm_bytecode *bc;
+ get_next_token();
+ bc = parse_instr(parser_nasm);
+ if (bc)
+ yasm_bc_insn_add_prefix(bc, prefix.arch_data);
+ return bc;
+ }
+ case SEGREG: {
+ unsigned long segreg = SEGREG_val[0];
+ yasm_bytecode *bc;
+ get_next_token();
+ bc = parse_instr(parser_nasm);
+ if (bc)
+ yasm_bc_insn_add_seg_prefix(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 '[':
+ {
+ yasm_effaddr *ea;
+ get_next_token();
+ ea = parse_memaddr(parser_nasm);
+
+ expect(']');
+ get_next_token();
+
+ if (!ea) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("memory address expected"));
+ return NULL;
+ }
+ return yasm_operand_create_mem(ea);
+ }
+ case SEGREG:
+ op = yasm_operand_create_segreg(SEGREG_val[0]);
+ get_next_token();
+ return op;
+ case REG:
+ op = yasm_operand_create_reg(REG_val[0]);
+ get_next_token();
+ return op;
+ 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();
+ op = parse_operand(parser_nasm);
+ if (!op)
+ return NULL;
+ if (op->type == YASM_INSN__OPERAND_REG &&
+ yasm_arch_get_reg_size(parser_nasm->arch, op->data.reg) != size)
+ yasm_error_set(YASM_ERROR_TYPE,
+ N_("cannot override register size"));
+ else
+ op->size = size;
+ return op;
+ }
+ case TARGETMOD:
+ {
+ unsigned long tmod = TARGETMOD_val[0];
+ get_next_token();
+ op = parse_operand(parser_nasm);
+ if (op)
+ op->targetmod = tmod;
+ return op;
+ }
+ default:
+ {
+ yasm_expr *e = parse_expr(parser_nasm, NORM_EXPR);
+ if (!e)
+ return NULL;
+ return yasm_operand_create_imm(e);
+ }
+ }
+}
+
+/* memory addresses */
+static yasm_effaddr *
+parse_memaddr(yasm_parser_nasm *parser_nasm)
+{
+ yasm_effaddr *ea;
+ switch (curtok) {
+ case SEGREG:
+ {
+ unsigned long segreg = SEGREG_val[0];
+ get_next_token();
+ if (!expect(':')) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("`:' required after segment register"));
+ return NULL;
+ }
+ get_next_token();
+ ea = parse_memaddr(parser_nasm);
+ if (ea)
+ yasm_ea_set_segreg(ea, segreg);
+ return ea;
+ }
+ case SIZE_OVERRIDE:
+ {
+ unsigned int size = SIZE_OVERRIDE_val;
+ get_next_token();
+ ea = parse_memaddr(parser_nasm);
+ if (ea)
+ yasm_ea_set_len(ea, size);
+ return ea;
+ }
+ case NOSPLIT:
+ get_next_token();
+ ea = parse_memaddr(parser_nasm);
+ if (ea)
+ yasm_ea_set_nosplit(ea, 1);
+ return ea;
+ default:
+ {
+ yasm_expr *e = parse_expr(parser_nasm, NORM_EXPR);
+ if (!e)
+ return NULL;
+ return yasm_arch_ea_create(parser_nasm->arch, e);
+ }
+ }
+}
+
+/* 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_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 NORM_EXPR:
+ parse_expr_common(parse_bexpr, ':', parse_bexpr, YASM_EXPR_SEGOFF);
+ case DV_EXPR:
+ /* dataval expressions can't handle seg:off */
+ return parse_bexpr(parser_nasm, type);
+ case DIR_EXPR:
+ /* directive expressions can't handle seg:off or WRT */
+ return parse_expr0(parser_nasm, type);
+ }
+ /*@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_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_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_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;
+
+ /* directives allow very little and handle IDs specially */
+ if (type == DIR_EXPR) {
+ switch (curtok) {
+ case '~':
+ get_next_token();
+ e = parse_expr6(parser_nasm, type);
+ if (!e)
+ return NULL;
+ return p_expr_new_branch(YASM_EXPR_NOT, e);
+ case '(':
+ get_next_token();
+ e = parse_expr(parser_nasm, type);
+ 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));
+ break;
+ case ID:
+ e = p_expr_new_ident(yasm_expr_sym(
+ yasm_symtab_define_label(p_symtab, ID_val,
+ yasm_section_bcs_first(parser_nasm->cur_section), 0,
+ cur_line)));
+ yasm_xfree(ID_val);
+ break;
+ default:
+ return NULL;
+ }
+ } else switch (curtok) {
+ case '+':
+ get_next_token();
+ return parse_expr6(parser_nasm, type);
+ case '-':
+ get_next_token();
+ e = parse_expr6(parser_nasm, type);
+ if (!e)
+ return NULL;
+ return p_expr_new_branch(YASM_EXPR_NEG, e);
+ case '~':
+ get_next_token();
+ e = parse_expr6(parser_nasm, type);
+ if (!e)
+ return NULL;
+ return p_expr_new_branch(YASM_EXPR_NOT, e);
+ case SEG:
+ get_next_token();
+ e = parse_expr6(parser_nasm, type);
+ if (!e)
+ return NULL;
+ return p_expr_new_branch(YASM_EXPR_SEG, e);
+ case '(':
+ get_next_token();
+ e = parse_expr(parser_nasm, type);
+ 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));
+ break;
+ case FLTNUM:
+ e = p_expr_new_ident(yasm_expr_float(FLTNUM_val));
+ break;
+ 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[0]));
+ break;
+ case STRING:
+ e = p_expr_new_ident(yasm_expr_int(
+ yasm_intnum_create_charconst_nasm(STRING_val.contents)));
+ yasm_xfree(STRING_val.contents);
+ break;
+ case ID:
+ case SPECIAL_ID:
+ case LOCAL_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 */
+ 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 */
+ sym = yasm_symtab_define_label(p_symtab, "$$",
+ yasm_section_bcs_first(parser_nasm->cur_section), 0, cur_line);
+ e = p_expr_new_ident(yasm_expr_sym(sym));
+ break;
+ default:
+ return NULL;
+ }
+ get_next_token();
+ return e;
+}
+
+static void
+define_label(yasm_parser_nasm *parser_nasm, char *name, int local)
+{
+ if (!local) {
+ 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);
+ }
+
+ yasm_symtab_define_label(p_symtab, name, parser_nasm->prev_bc, 1,
+ cur_line);
+ yasm_xfree(name);
+}
+
+static int
+fix_directive_symrec(yasm_expr__item *ei, void *d)
+{
+ yasm_parser_nasm *parser_nasm = (yasm_parser_nasm *)d;
+ if (!ei || ei->type != YASM_EXPR_SYM)
+ return 0;
+
+ /* FIXME: Delete current symrec */
+ ei->data.sym =
+ yasm_symtab_use(p_symtab, yasm_symrec_get_name(ei->data.sym),
+ cur_line);
+
+ return 0;
+}
+
+static void
+nasm_parser_directive(yasm_parser_nasm *parser_nasm, const char *name,
+ yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams)
+{
+ yasm_valparam *vp, *vp2;
+ unsigned long line = cur_line;
+
+ /* Handle (mostly) output-format independent directives here */
+ if (yasm__strcasecmp(name, "extern") == 0) {
+ vp = yasm_vps_first(valparams);
+ if (vp->val) {
+ yasm_objfmt_extern_declare(parser_nasm->objfmt, vp->val,
+ objext_valparams, line);
+ } else
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid argument to [%s]"),
+ "EXTERN");
+ } else if (yasm__strcasecmp(name, "global") == 0) {
+ vp = yasm_vps_first(valparams);
+ if (vp->val) {
+ yasm_objfmt_global_declare(parser_nasm->objfmt, vp->val,
+ objext_valparams, line);
+ } else
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid argument to [%s]"),
+ "GLOBAL");
+ } else if (yasm__strcasecmp(name, "common") == 0) {
+ vp = yasm_vps_first(valparams);
+ if (vp->val) {
+ vp2 = yasm_vps_next(vp);
+ if (!vp2 || (!vp2->val && !vp2->param))
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("no size specified in %s declaration"),
+ "COMMON");
+ else {
+ if (vp2->val) {
+ yasm_objfmt_common_declare(parser_nasm->objfmt, vp->val,
+ p_expr_new_ident(yasm_expr_sym(
+ yasm_symtab_use(p_symtab, vp2->val, line))),
+ objext_valparams, line);
+ } else if (vp2->param) {
+ yasm_objfmt_common_declare(parser_nasm->objfmt, vp->val,
+ vp2->param, objext_valparams,
+ line);
+ vp2->param = NULL;
+ }
+ }
+ } else
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid argument to [%s]"),
+ "COMMON");
+ } else if (yasm__strcasecmp(name, "section") == 0 ||
+ yasm__strcasecmp(name, "segment") == 0) {
+ yasm_section *new_section =
+ yasm_objfmt_section_switch(parser_nasm->objfmt, valparams,
+ objext_valparams, line);
+ if (new_section) {
+ parser_nasm->cur_section = new_section;
+ parser_nasm->prev_bc = yasm_section_bcs_last(new_section);
+ } else
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid argument to [%s]"),
+ "SECTION");
+ } else if (yasm__strcasecmp(name, "absolute") == 0) {
+ /* it can be just an ID or a complete expression, so handle both. */
+ vp = yasm_vps_first(valparams);
+ if (vp->val)
+ parser_nasm->cur_section =
+ yasm_object_create_absolute(parser_nasm->object,
+ p_expr_new_ident(yasm_expr_sym(
+ yasm_symtab_use(p_symtab, vp->val, line))), line);
+ else if (vp->param) {
+ parser_nasm->cur_section =
+ yasm_object_create_absolute(parser_nasm->object, vp->param,
+ line);
+ vp->param = NULL;
+ }
+ parser_nasm->prev_bc = yasm_section_bcs_last(parser_nasm->cur_section);
+ } else if (yasm__strcasecmp(name, "align") == 0) {
+ /*@only@*/ yasm_expr *boundval;
+ /*@depedent@*/ yasm_intnum *boundintn;
+
+ /* it can be just an ID or a complete expression, so handle both. */
+ vp = yasm_vps_first(valparams);
+ if (vp->val)
+ boundval = p_expr_new_ident(yasm_expr_sym(
+ yasm_symtab_use(p_symtab, vp->val, line)));
+ else if (vp->param) {
+ boundval = vp->param;
+ vp->param = NULL;
+ }
+
+ /* Largest .align in the section specifies section alignment.
+ * Note: this doesn't match NASM behavior, but is a lot more
+ * intelligent!
+ */
+ 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(parser_nasm->cur_section))
+ yasm_section_set_align(parser_nasm->cur_section, boundint,
+ cur_line);
+ }
+ }
+
+ /* As this directive is called only when nop is used as fill, always
+ * use arch (nop) fill.
+ */
+ parser_nasm->prev_bc =
+ yasm_section_bcs_append(parser_nasm->cur_section,
+ yasm_bc_create_align(boundval, NULL, NULL,
+ /*yasm_section_is_code(parser_nasm->cur_section) ?*/
+ yasm_arch_get_fill(parser_nasm->arch)/* : NULL*/,
+ cur_line));
+ } else if (yasm__strcasecmp(name, "cpu") == 0) {
+ yasm_vps_foreach(vp, valparams) {
+ if (vp->val)
+ yasm_arch_parse_cpu(parser_nasm->arch, vp->val,
+ strlen(vp->val));
+ else if (vp->param) {
+ const yasm_intnum *intcpu;
+ intcpu = yasm_expr_get_intnum(&vp->param, 0);
+ if (!intcpu)
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("invalid argument to [%s]"), "CPU");
+ else {
+ char strcpu[16];
+ sprintf(strcpu, "%lu", yasm_intnum_get_uint(intcpu));
+ yasm_arch_parse_cpu(parser_nasm->arch, strcpu,
+ strlen(strcpu));
+ }
+ }
+ }
+ } else if (!yasm_arch_parse_directive(parser_nasm->arch, name, valparams,
+ objext_valparams, parser_nasm->object, line)) {
+ ;
+ } else if (!yasm_dbgfmt_directive(parser_nasm->dbgfmt, name,
+ parser_nasm->cur_section, valparams,
+ line)) {
+ ;
+ } else if (yasm_objfmt_directive(parser_nasm->objfmt, name, valparams,
+ objext_valparams, line)) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("unrecognized directive [%s]"),
+ name);
+ }
+
+ yasm_vps_delete(valparams);
+ if (objext_valparams)
+ yasm_vps_delete(objext_valparams);
+}
parser_nasm.save_input = save_input;
parser_nasm.save_last = 0;
+ parser_nasm.peek_token = NONE;
+
/* initialize scanner structure */
yasm_scanner_initialize(&parser_nasm.s);
#ifndef YASM_NASM_PARSER_H
#define YASM_NASM_PARSER_H
-#include "nasm-bison.h"
-
#define YYCTYPE unsigned char
#define MAX_SAVED_LINE_LEN 80
+enum tokentype {
+ INTNUM = 258,
+ FLTNUM,
+ DIRECTIVE_NAME,
+ FILENAME,
+ STRING,
+ SIZE_OVERRIDE,
+ DECLARE_DATA,
+ RESERVE_SPACE,
+ INCBIN,
+ EQU,
+ TIMES,
+ SEG,
+ WRT,
+ NOSPLIT,
+ STRICT,
+ INSN,
+ PREFIX,
+ REG,
+ SEGREG,
+ TARGETMOD,
+ LEFT_OP,
+ RIGHT_OP,
+ SIGNDIV,
+ SIGNMOD,
+ START_SECTION_ID,
+ ID,
+ LOCAL_ID,
+ SPECIAL_ID,
+ LINE,
+ NONE /* special token for lookahead */
+};
+
+typedef union {
+ unsigned int int_info;
+ char *str_val;
+ yasm_intnum *intn;
+ yasm_floatnum *flt;
+ unsigned long arch_data[4];
+ struct {
+ char *contents;
+ size_t len;
+ } str;
+} yystype;
+#define YYSTYPE yystype
+
typedef struct yasm_parser_nasm {
FILE *in;
int debug;
/*@dependent@*/ yasm_symtab *symtab;
/*@null@*/ yasm_bytecode *prev_bc;
- yasm_bytecode *temp_bc;
int save_input;
YYCTYPE save_line[2][MAX_SAVED_LINE_LEN];
LINECHG2,
INSTRUCTION
} 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;
} yasm_parser_nasm;
/* shorter access names to commonly used parser_nasm fields */
#define p_symtab (parser_nasm->symtab)
+#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.arch_data)
+#define PREFIX_val (curval.arch_data)
+#define REG_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_branch(o,r) yasm_expr_create_branch(o,r,cur_line)
#define p_expr_new_ident(r) yasm_expr_create_ident(r,cur_line)
-int nasm_parser_parse(void *parser_nasm_arg);
+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);
#include <libyasm.h>
#include "modules/parsers/nasm/nasm-parser.h"
-#include "modules/parsers/nasm/nasm-defs.h"
#define BSIZE 8192
#define YYMARKER (s->ptr)
#define YYFILL(n) {fill(parser_nasm, &cursor);}
-#define RETURN(i) {s->cur = cursor; return i;}
+#define RETURN(i) {s->cur = cursor; parser_nasm->tokch = s->tok[0]; \
+ return i;}
#define SCANINIT() {s->tok = cursor;}
size_t count, len;
YYCTYPE savech;
+ /* Handle one token of lookahead */
+ if (parser_nasm->peek_token != NONE) {
+ int tok = parser_nasm->peek_token;
+ *lvalp = parser_nasm->peek_tokval; /* structure copy */
+ parser_nasm->tokch = parser_nasm->peek_tokch;
+ parser_nasm->peek_token = NONE;
+ return tok;
+ }
+
/* Catch EOF */
if (s->eof && cursor == s->eof)
return 0;
lvalp->str.len = count;
if (parser_nasm->save_input)
cursor = save_line(parser_nasm, cursor);
- if (count == 1)
- RETURN(ONECHARSTR);
RETURN(STRING);
}
strbuf[count] = '\0';
lvalp->str.contents = (char *)strbuf;
lvalp->str.len = count;
- if (count == 1)
- RETURN(ONECHARSTR);
RETURN(STRING);
}