From a64e41603632cf4eca649b0d4891706bb3fb7f86 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Tue, 27 Sep 2005 07:07:07 +0000 Subject: [PATCH] Split arch module parse_check_id into parse_check_reg, parse_check_reggroup, parse_check_segreg, parse_check_insn, parse_check_prefix, and parse_check_targetmod. This will allow for future improvements to identifier handling in the various parsers. svn path=/trunk/yasm/; revision=1249 --- libyasm/arch.h | 168 +++++++++++--- modules/arch/lc3b/lc3barch.c | 7 +- modules/arch/lc3b/lc3barch.h | 19 +- modules/arch/lc3b/lc3bid.re | 60 ++++- modules/arch/x86/x86arch.c | 7 +- modules/arch/x86/x86arch.h | 19 +- modules/arch/x86/x86id.re | 361 +++++++++++++++-------------- modules/parsers/gas/gas-token.re | 84 +++---- modules/parsers/nasm/nasm-token.re | 56 +++-- 9 files changed, 489 insertions(+), 292 deletions(-) diff --git a/libyasm/arch.h b/libyasm/arch.h index f3e704f2..72564c75 100644 --- a/libyasm/arch.h +++ b/libyasm/arch.h @@ -34,17 +34,6 @@ #ifndef YASM_ARCH_H #define YASM_ARCH_H -/** Return value from yasm_arch_module::parse_check_id(). */ -typedef enum { - YASM_ARCH_CHECK_ID_NONE = 0, /**< Just a normal identifier. */ - YASM_ARCH_CHECK_ID_INSN, /**< An instruction. */ - YASM_ARCH_CHECK_ID_PREFIX, /**< An instruction prefix. */ - YASM_ARCH_CHECK_ID_REG, /**< A register. */ - YASM_ARCH_CHECK_ID_REGGROUP, /**< A register group. */ - YASM_ARCH_CHECK_ID_SEGREG,/**< a segment register (for memory overrides). */ - YASM_ARCH_CHECK_ID_TARGETMOD /**< A target modifier (for jumps) */ -} yasm_arch_check_id_retval; - /** Errors that may be returned by yasm_arch_module::create(). */ typedef enum { YASM_ARCH_CREATE_OK = 0, /**< No error. */ @@ -127,11 +116,46 @@ typedef struct yasm_arch_module { void (*parse_cpu) (yasm_arch *arch, const char *cpuid, unsigned long line); - /** Module-level implementation of yasm_arch_parse_check_id(). - * Call yasm_arch_parse_check_id() instead of calling this function. + /** Module-level implementation of yasm_arch_parse_check_reg(). + * Call yasm_arch_parse_check_reg() instead of calling this function. + */ + int (*parse_check_reg) + (yasm_arch *arch, /*@out@*/ unsigned long data[1], const char *id, + unsigned long line); + + /** Module-level implementation of yasm_arch_parse_check_reggroup(). + * Call yasm_arch_parse_check_reggroup() instead of calling this function. + */ + int (*parse_check_reggroup) + (yasm_arch *arch, /*@out@*/ unsigned long data[1], const char *id, + unsigned long line); + + /** Module-level implementation of yasm_arch_parse_check_segreg(). + * Call yasm_arch_parse_check_segreg() instead of calling this function. */ - yasm_arch_check_id_retval (*parse_check_id) - (yasm_arch *arch, unsigned long data[4], const char *id, + int (*parse_check_segreg) + (yasm_arch *arch, /*@out@*/ unsigned long data[1], const char *id, + unsigned long line); + + /** Module-level implementation of yasm_arch_parse_check_insn(). + * Call yasm_arch_parse_check_insn() instead of calling this function. + */ + int (*parse_check_insn) + (yasm_arch *arch, /*@out@*/ unsigned long data[4], const char *id, + unsigned long line); + + /** Module-level implementation of yasm_arch_parse_check_prefix(). + * Call yasm_arch_parse_check_prefix() instead of calling this function. + */ + int (*parse_check_prefix) + (yasm_arch *arch, /*@out@*/ unsigned long data[4], const char *id, + unsigned long line); + + /** Module-level implementation of yasm_arch_parse_check_targetmod(). + * Call yasm_arch_parse_check_targetmod() instead of calling this function. + */ + int (*parse_check_targetmod) + (yasm_arch *arch, /*@out@*/ unsigned long data[1], const char *id, unsigned long line); /** Module-level implementation of yasm_arch_parse_directive(). @@ -320,23 +344,99 @@ void yasm_arch_parse_cpu(yasm_arch *arch, const char *cpuid, unsigned long line); /** Check an generic identifier to see if it matches architecture specific - * names for instructions, registers, etc. Unrecognized identifiers should - * be returned as #YASM_ARCH_CHECK_ID_NONE so they can be treated as normal - * symbols. Any additional data beyond just the type (almost always - * necessary) should be returned into the space provided by the data - * parameter. - * \note Even though this is passed a data[4], only data[0] should be used - * for #YASM_ARCH_CHECK_ID_TARGETMOD, #YASM_ARCH_CHECK_ID_REG, and - * #YASM_ARCH_CHECK_ID_SEGREG return values. + * names for registers. Unrecognized identifiers should return 0 + * so they can be treated as normal symbols. Any additional data beyond + * just the type (almost always necessary) should be returned into the + * space provided by the data parameter. + * \param arch architecture + * \param data extra identification information (yasm_arch-specific) + * [output] + * \param id identifier as in the input file + * \param line virtual line (from yasm_linemap) + * \return 1 if id is a register, 0 if not. + */ +int yasm_arch_parse_check_reg + (yasm_arch *arch, /*@out@*/ unsigned long data[1], const char *id, + unsigned long line); + +/** Check an generic identifier to see if it matches architecture specific + * names for register groups. Unrecognized identifiers should return 0 + * so they can be treated as normal symbols. Any additional data beyond + * just the type (almost always necessary) should be returned into the + * space provided by the data parameter. + * \param arch architecture + * \param data extra identification information (yasm_arch-specific) + * [output] + * \param id identifier as in the input file + * \param line virtual line (from yasm_linemap) + * \return 1 if id is a register, 0 if not. + */ +int yasm_arch_parse_check_reggroup + (yasm_arch *arch, /*@out@*/ unsigned long data[1], const char *id, + unsigned long line); + +/** Check an generic identifier to see if it matches architecture specific + * names for segment registers. Unrecognized identifiers should return 0 + * so they can be treated as normal symbols. Any additional data beyond + * just the type (almost always necessary) should be returned into the + * space provided by the data parameter. + * \param arch architecture + * \param data extra identification information (yasm_arch-specific) + * [output] + * \param id identifier as in the input file + * \param line virtual line (from yasm_linemap) + * \return 1 if id is a register, 0 if not. + */ +int yasm_arch_parse_check_segreg + (yasm_arch *arch, /*@out@*/ unsigned long data[1], const char *id, + unsigned long line); + +/** Check an generic identifier to see if it matches architecture specific + * names for instructions. Unrecognized identifiers should return 0 + * so they can be treated as normal symbols. Any additional data beyond + * just the type (almost always necessary) should be returned into the + * space provided by the data parameter. + * \param arch architecture + * \param data extra identification information (yasm_arch-specific) + * [output] + * \param id identifier as in the input file + * \param line virtual line (from yasm_linemap) + * \return 1 if id is a register, 0 if not. + */ +int yasm_arch_parse_check_insn + (yasm_arch *arch, /*@out@*/ unsigned long data[4], const char *id, + unsigned long line); + +/** Check an generic identifier to see if it matches architecture specific + * names for prefixes. Unrecognized identifiers should return 0 + * so they can be treated as normal symbols. Any additional data beyond + * just the type (almost always necessary) should be returned into the + * space provided by the data parameter. + * \param arch architecture + * \param data extra identification information (yasm_arch-specific) + * [output] + * \param id identifier as in the input file + * \param line virtual line (from yasm_linemap) + * \return 1 if id is a register, 0 if not. + */ +int yasm_arch_parse_check_prefix + (yasm_arch *arch, /*@out@*/ unsigned long data[4], const char *id, + unsigned long line); + +/** Check an generic identifier to see if it matches architecture specific + * names for target modifiers. Unrecognized identifiers should return 0 + * so they can be treated as normal symbols. Any additional data beyond + * just the type (almost always necessary) should be returned into the + * space provided by the data parameter. * \param arch architecture * \param data extra identification information (yasm_arch-specific) * [output] * \param id identifier as in the input file * \param line virtual line (from yasm_linemap) - * \return General type of identifier (#yasm_arch_check_id_retval). + * \return 1 if id is a register, 0 if not. */ -yasm_arch_check_id_retval yasm_arch_parse_check_id - (yasm_arch *arch, unsigned long data[4], const char *id, +int yasm_arch_parse_check_targetmod + (yasm_arch *arch, /*@out@*/ unsigned long data[1], const char *id, unsigned long line); /** Handle architecture-specific directives. @@ -498,8 +598,20 @@ yasm_effaddr *yasm_arch_ea_create(yasm_arch *arch, /*@keep@*/ yasm_expr *e); ((yasm_arch_base *)arch)->module->set_var(arch, var, val) #define yasm_arch_parse_cpu(arch, cpuid, line) \ ((yasm_arch_base *)arch)->module->parse_cpu(arch, cpuid, line) -#define yasm_arch_parse_check_id(arch, data, id, line) \ - ((yasm_arch_base *)arch)->module->parse_check_id(arch, data, id, line) +#define yasm_arch_parse_check_reg(arch, data, id, line) \ + ((yasm_arch_base *)arch)->module->parse_check_reg(arch, data, id, line) +#define yasm_arch_parse_check_reggroup(arch, data, id, line) \ + ((yasm_arch_base *)arch)->module->parse_check_reggroup(arch, data, id, \ + line) +#define yasm_arch_parse_check_segreg(arch, data, id, line) \ + ((yasm_arch_base *)arch)->module->parse_check_segreg(arch, data, id, line) +#define yasm_arch_parse_check_insn(arch, data, id, line) \ + ((yasm_arch_base *)arch)->module->parse_check_insn(arch, data, id, line) +#define yasm_arch_parse_check_prefix(arch, data, id, line) \ + ((yasm_arch_base *)arch)->module->parse_check_prefix(arch, data, id, line) +#define yasm_arch_parse_check_targetmod(arch, data, id, line) \ + ((yasm_arch_base *)arch)->module->parse_check_targetmod(arch, data, id, \ + line) #define yasm_arch_parse_directive(arch, name, valparams, objext_valparams, \ object, line) \ ((yasm_arch_base *)arch)->module->parse_directive \ diff --git a/modules/arch/lc3b/lc3barch.c b/modules/arch/lc3b/lc3barch.c index 9e3c6112..e2071ab8 100644 --- a/modules/arch/lc3b/lc3barch.c +++ b/modules/arch/lc3b/lc3barch.c @@ -140,7 +140,12 @@ yasm_arch_module yasm_lc3b_LTX_arch = { lc3b_get_machine, lc3b_set_var, yasm_lc3b__parse_cpu, - yasm_lc3b__parse_check_id, + yasm_lc3b__parse_check_reg, + yasm_lc3b__parse_check_reggroup, + yasm_lc3b__parse_check_segreg, + yasm_lc3b__parse_check_insn, + yasm_lc3b__parse_check_prefix, + yasm_lc3b__parse_check_targetmod, lc3b_parse_directive, yasm_lc3b__finalize_insn, lc3b_floatnum_tobytes, diff --git a/modules/arch/lc3b/lc3barch.h b/modules/arch/lc3b/lc3barch.h index 1dbaa163..f034d4da 100644 --- a/modules/arch/lc3b/lc3barch.h +++ b/modules/arch/lc3b/lc3barch.h @@ -55,8 +55,23 @@ void yasm_lc3b__bc_transform_insn(yasm_bytecode *bc, lc3b_insn *insn); void yasm_lc3b__parse_cpu(yasm_arch *arch, const char *cpuid, unsigned long line); -yasm_arch_check_id_retval yasm_lc3b__parse_check_id - (yasm_arch *arch, unsigned long data[2], const char *id, +int yasm_lc3b__parse_check_reg + (yasm_arch *arch, unsigned long data[1], const char *id, + unsigned long line); +int yasm_lc3b__parse_check_reggroup + (yasm_arch *arch, unsigned long data[1], const char *id, + unsigned long line); +int yasm_lc3b__parse_check_segreg + (yasm_arch *arch, unsigned long data[1], const char *id, + unsigned long line); +int yasm_lc3b__parse_check_insn + (yasm_arch *arch, unsigned long data[4], const char *id, + unsigned long line); +int yasm_lc3b__parse_check_prefix + (yasm_arch *arch, unsigned long data[4], const char *id, + unsigned long line); +int yasm_lc3b__parse_check_targetmod + (yasm_arch *arch, unsigned long data[1], const char *id, unsigned long line); void yasm_lc3b__finalize_insn diff --git a/modules/arch/lc3b/lc3bid.re b/modules/arch/lc3b/lc3bid.re index 183ef434..35625044 100644 --- a/modules/arch/lc3b/lc3bid.re +++ b/modules/arch/lc3b/lc3bid.re @@ -119,7 +119,7 @@ typedef struct lc3b_insn_info { #define RET_INSN(group, mod) do { \ DEF_INSN_DATA(group, mod); \ - return YASM_ARCH_CHECK_ID_INSN; \ + return 1; \ } while (0) /* @@ -348,20 +348,50 @@ yasm_lc3b__parse_cpu(yasm_arch *arch, const char *id, unsigned long line) { } -yasm_arch_check_id_retval -yasm_lc3b__parse_check_id(yasm_arch *arch, unsigned long data[4], - const char *id, unsigned long line) +int +yasm_lc3b__parse_check_reg(yasm_arch *arch, unsigned long data[1], + const char *id, unsigned long line) { const char *oid = id; /*const char *marker;*/ /*!re2c - /* integer registers */ R [0-7] { data[0] = (oid[1]-'0'); - return YASM_ARCH_CHECK_ID_REG; + return 1; } + /* catchalls */ + [\001-\377]+ { + return 0; + } + [\000] { + return 0; + } + */ +} + +int +yasm_lc3b__parse_check_reggroup(yasm_arch *arch, unsigned long data[1], + const char *id, unsigned long line) +{ + return 0; +} + +int +yasm_lc3b__parse_check_segreg(yasm_arch *arch, unsigned long data[1], + const char *id, unsigned long line) +{ + return 0; +} + +int +yasm_lc3b__parse_check_insn(yasm_arch *arch, unsigned long data[4], + const char *id, unsigned long line) +{ + const char *oid = id; + /*const char *marker;*/ + /*!re2c /* instructions */ A D D { RET_INSN(addand, 0x00); } @@ -402,10 +432,24 @@ yasm_lc3b__parse_check_id(yasm_arch *arch, unsigned long data[4], /* catchalls */ [\001-\377]+ { - return YASM_ARCH_CHECK_ID_NONE; + return 0; } [\000] { - return YASM_ARCH_CHECK_ID_NONE; + return 0; } */ } + +int +yasm_lc3b__parse_check_prefix(yasm_arch *arch, unsigned long data[4], + const char *id, unsigned long line) +{ + return 0; +} + +int +yasm_lc3b__parse_check_targetmod(yasm_arch *arch, unsigned long data[1], + const char *id, unsigned long line) +{ + return 0; +} diff --git a/modules/arch/x86/x86arch.c b/modules/arch/x86/x86arch.c index bdb23c8d..7486afb2 100644 --- a/modules/arch/x86/x86arch.c +++ b/modules/arch/x86/x86arch.c @@ -262,7 +262,12 @@ yasm_arch_module yasm_x86_LTX_arch = { x86_get_machine, x86_set_var, yasm_x86__parse_cpu, - yasm_x86__parse_check_id, + yasm_x86__parse_check_reg, + yasm_x86__parse_check_reggroup, + yasm_x86__parse_check_segreg, + yasm_x86__parse_check_insn, + yasm_x86__parse_check_prefix, + yasm_x86__parse_check_targetmod, x86_parse_directive, yasm_x86__finalize_insn, yasm_x86__floatnum_tobytes, diff --git a/modules/arch/x86/x86arch.h b/modules/arch/x86/x86arch.h index f2e9580c..bfc55dd3 100644 --- a/modules/arch/x86/x86arch.h +++ b/modules/arch/x86/x86arch.h @@ -261,8 +261,23 @@ int yasm_x86__expr_checkea void yasm_x86__parse_cpu(yasm_arch *arch, const char *cpuid, unsigned long line); -yasm_arch_check_id_retval yasm_x86__parse_check_id - (yasm_arch *arch, unsigned long data[4], const char *id, +int yasm_x86__parse_check_reg + (yasm_arch *arch, /*@out@*/ unsigned long data[1], const char *id, + unsigned long line); +int yasm_x86__parse_check_reggroup + (yasm_arch *arch, /*@out@*/ unsigned long data[1], const char *id, + unsigned long line); +int yasm_x86__parse_check_segreg + (yasm_arch *arch, /*@out@*/ unsigned long data[1], const char *id, + unsigned long line); +int yasm_x86__parse_check_insn + (yasm_arch *arch, /*@out@*/ unsigned long data[4], const char *id, + unsigned long line); +int yasm_x86__parse_check_prefix + (yasm_arch *arch, /*@out@*/ unsigned long data[4], const char *id, + unsigned long line); +int yasm_x86__parse_check_targetmod + (yasm_arch *arch, /*@out@*/ unsigned long data[1], const char *id, unsigned long line); void yasm_x86__finalize_insn diff --git a/modules/arch/x86/x86id.re b/modules/arch/x86/x86id.re index aba41ce3..23d4934c 100644 --- a/modules/arch/x86/x86id.re +++ b/modules/arch/x86/x86id.re @@ -2904,41 +2904,41 @@ yasm_x86__parse_cpu(yasm_arch *arch, const char *id, unsigned long line) */ } -static yasm_arch_check_id_retval -yasm_x86__parse_check_targetmod(yasm_arch *arch, unsigned long data[4], +int +yasm_x86__parse_check_targetmod(yasm_arch *arch, unsigned long data[1], const char *id, unsigned long line) { /*!re2c /* target modifiers */ N E A R { data[0] = X86_NEAR; - return YASM_ARCH_CHECK_ID_TARGETMOD; + return 1; } S H O R T { data[0] = X86_SHORT; - return YASM_ARCH_CHECK_ID_TARGETMOD; + return 1; } F A R { data[0] = X86_FAR; - return YASM_ARCH_CHECK_ID_TARGETMOD; + return 1; } T O { data[0] = X86_TO; - return YASM_ARCH_CHECK_ID_TARGETMOD; + return 1; } /* catchalls */ [\001-\377]+ { - return YASM_ARCH_CHECK_ID_NONE; + return 0; } [\000] { - return YASM_ARCH_CHECK_ID_NONE; + return 0; } */ - return YASM_ARCH_CHECK_ID_NONE; + return 0; } -static yasm_arch_check_id_retval +int yasm_x86__parse_check_prefix(yasm_arch *arch, unsigned long data[4], const char *id, unsigned long line) { @@ -2949,95 +2949,95 @@ yasm_x86__parse_check_prefix(yasm_arch *arch, unsigned long data[4], O "16" { data[0] = X86_OPERSIZE; data[1] = 16; - return YASM_ARCH_CHECK_ID_PREFIX; + return 1; } O "32" { data[0] = X86_OPERSIZE; data[1] = 32; - return YASM_ARCH_CHECK_ID_PREFIX; + return 1; } O "64" { if (arch_x86->mode_bits != 64) { yasm__warning(YASM_WARN_GENERAL, line, N_("`%s' is a prefix in 64-bit mode"), oid); - return YASM_ARCH_CHECK_ID_NONE; + return 0; } data[0] = X86_OPERSIZE; data[1] = 64; - return YASM_ARCH_CHECK_ID_PREFIX; + return 1; } /* address size overrides */ A "16" { if (arch_x86->mode_bits == 64) { yasm__error(line, N_("Cannot override address size to 16 bits in 64-bit mode")); - return YASM_ARCH_CHECK_ID_NONE; + return 0; } data[0] = X86_ADDRSIZE; data[1] = 16; - return YASM_ARCH_CHECK_ID_PREFIX; + return 1; } A "32" { data[0] = X86_ADDRSIZE; data[1] = 32; - return YASM_ARCH_CHECK_ID_PREFIX; + return 1; } A "64" { if (arch_x86->mode_bits != 64) { yasm__warning(YASM_WARN_GENERAL, line, N_("`%s' is a prefix in 64-bit mode"), oid); - return YASM_ARCH_CHECK_ID_NONE; + return 0; } data[0] = X86_ADDRSIZE; data[1] = 64; - return YASM_ARCH_CHECK_ID_PREFIX; + return 1; } /* instruction prefixes */ L O C K { data[0] = X86_LOCKREP; data[1] = 0xF0; - return YASM_ARCH_CHECK_ID_PREFIX; + return 1; } R E P N E { data[0] = X86_LOCKREP; data[1] = 0xF2; - return YASM_ARCH_CHECK_ID_PREFIX; + return 1; } R E P N Z { data[0] = X86_LOCKREP; data[1] = 0xF2; - return YASM_ARCH_CHECK_ID_PREFIX; + return 1; } R E P { data[0] = X86_LOCKREP; data[1] = 0xF3; - return YASM_ARCH_CHECK_ID_PREFIX; + return 1; } R E P E { data[0] = X86_LOCKREP; data[1] = 0xF3; - return YASM_ARCH_CHECK_ID_PREFIX; + return 1; } R E P Z { data[0] = X86_LOCKREP; data[1] = 0xF3; - return YASM_ARCH_CHECK_ID_PREFIX; + return 1; } /* catchalls */ [\001-\377]+ { - return YASM_ARCH_CHECK_ID_NONE; + return 0; } [\000] { - return YASM_ARCH_CHECK_ID_NONE; + return 0; } */ - return YASM_ARCH_CHECK_ID_NONE; + return 0; } -static yasm_arch_check_id_retval -yasm_x86__parse_check_reg(yasm_arch *arch, unsigned long data[4], +int +yasm_x86__parse_check_reg(yasm_arch *arch, unsigned long data[1], const char *id, unsigned long line) { yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch; @@ -3048,68 +3048,47 @@ yasm_x86__parse_check_reg(yasm_arch *arch, unsigned long data[4], if (arch_x86->mode_bits != 64 && oid[2] == '8') { yasm__warning(YASM_WARN_GENERAL, line, N_("`%s' is a register in 64-bit mode"), oid); - return YASM_ARCH_CHECK_ID_NONE; + return 0; } data[0] = X86_CRREG | (oid[2]-'0'); - return YASM_ARCH_CHECK_ID_REG; + return 1; } D R [0-7] { data[0] = X86_DRREG | (oid[2]-'0'); - return YASM_ARCH_CHECK_ID_REG; + return 1; } T R [0-7] { data[0] = X86_TRREG | (oid[2]-'0'); - return YASM_ARCH_CHECK_ID_REG; + return 1; } /* floating point, MMX, and SSE/SSE2 registers */ S T [0-7] { data[0] = X86_FPUREG | (oid[2]-'0'); - return YASM_ARCH_CHECK_ID_REG; - } - S T { - if (arch_x86->parser == X86_PARSER_GAS) { - data[0] = X86_FPUREG; - return YASM_ARCH_CHECK_ID_REGGROUP; - } else - return YASM_ARCH_CHECK_ID_NONE; + return 1; } M M [0-7] { data[0] = X86_MMXREG | (oid[2]-'0'); - return YASM_ARCH_CHECK_ID_REG; - } - M M { - if (arch_x86->parser == X86_PARSER_GAS) { - data[0] = X86_MMXREG; - return YASM_ARCH_CHECK_ID_REGGROUP; - } else - return YASM_ARCH_CHECK_ID_NONE; + return 1; } X M M [0-9] { if (arch_x86->mode_bits != 64 && (oid[3] == '8' || oid[3] == '9')) { yasm__warning(YASM_WARN_GENERAL, line, N_("`%s' is a register in 64-bit mode"), oid); - return YASM_ARCH_CHECK_ID_NONE; + return 0; } data[0] = X86_XMMREG | (oid[3]-'0'); - return YASM_ARCH_CHECK_ID_REG; + return 1; } X M M "1" [0-5] { if (arch_x86->mode_bits != 64) { yasm__warning(YASM_WARN_GENERAL, line, N_("`%s' is a register in 64-bit mode"), oid); - return YASM_ARCH_CHECK_ID_NONE; + return 0; } data[0] = X86_XMMREG | (10+oid[4]-'0'); - return YASM_ARCH_CHECK_ID_REG; - } - X M M { - if (arch_x86->parser == X86_PARSER_GAS) { - data[0] = X86_XMMREG; - return YASM_ARCH_CHECK_ID_REGGROUP; - } else - return YASM_ARCH_CHECK_ID_NONE; + return 1; } /* integer registers */ @@ -3117,256 +3096,305 @@ yasm_x86__parse_check_reg(yasm_arch *arch, unsigned long data[4], if (arch_x86->mode_bits != 64) { yasm__warning(YASM_WARN_GENERAL, line, N_("`%s' is a register in 64-bit mode"), oid); - return YASM_ARCH_CHECK_ID_NONE; + return 0; } data[0] = X86_REG64 | 0; - return YASM_ARCH_CHECK_ID_REG; + return 1; } R C X { if (arch_x86->mode_bits != 64) { yasm__warning(YASM_WARN_GENERAL, line, N_("`%s' is a register in 64-bit mode"), oid); - return YASM_ARCH_CHECK_ID_NONE; + return 0; } data[0] = X86_REG64 | 1; - return YASM_ARCH_CHECK_ID_REG; + return 1; } R D X { if (arch_x86->mode_bits != 64) { yasm__warning(YASM_WARN_GENERAL, line, N_("`%s' is a register in 64-bit mode"), oid); - return YASM_ARCH_CHECK_ID_NONE; + return 0; } data[0] = X86_REG64 | 2; - return YASM_ARCH_CHECK_ID_REG; + return 1; } R B X { if (arch_x86->mode_bits != 64) { yasm__warning(YASM_WARN_GENERAL, line, N_("`%s' is a register in 64-bit mode"), oid); - return YASM_ARCH_CHECK_ID_NONE; + return 0; } data[0] = X86_REG64 | 3; - return YASM_ARCH_CHECK_ID_REG; + return 1; } R S P { if (arch_x86->mode_bits != 64) { yasm__warning(YASM_WARN_GENERAL, line, N_("`%s' is a register in 64-bit mode"), oid); - return YASM_ARCH_CHECK_ID_NONE; + return 0; } data[0] = X86_REG64 | 4; - return YASM_ARCH_CHECK_ID_REG; + return 1; } R B P { if (arch_x86->mode_bits != 64) { yasm__warning(YASM_WARN_GENERAL, line, N_("`%s' is a register in 64-bit mode"), oid); - return YASM_ARCH_CHECK_ID_NONE; + return 0; } data[0] = X86_REG64 | 5; - return YASM_ARCH_CHECK_ID_REG; + return 1; } R S I { if (arch_x86->mode_bits != 64) { yasm__warning(YASM_WARN_GENERAL, line, N_("`%s' is a register in 64-bit mode"), oid); - return YASM_ARCH_CHECK_ID_NONE; + return 0; } data[0] = X86_REG64 | 6; - return YASM_ARCH_CHECK_ID_REG; + return 1; } R D I { if (arch_x86->mode_bits != 64) { yasm__warning(YASM_WARN_GENERAL, line, N_("`%s' is a register in 64-bit mode"), oid); - return YASM_ARCH_CHECK_ID_NONE; + return 0; } data[0] = X86_REG64 | 7; - return YASM_ARCH_CHECK_ID_REG; + return 1; } R [8-9] { if (arch_x86->mode_bits != 64) { yasm__warning(YASM_WARN_GENERAL, line, N_("`%s' is a register in 64-bit mode"), oid); - return YASM_ARCH_CHECK_ID_NONE; + return 0; } data[0] = X86_REG64 | (oid[1]-'0'); - return YASM_ARCH_CHECK_ID_REG; + return 1; } R "1" [0-5] { if (arch_x86->mode_bits != 64) { yasm__warning(YASM_WARN_GENERAL, line, N_("`%s' is a register in 64-bit mode"), oid); - return YASM_ARCH_CHECK_ID_NONE; + return 0; } data[0] = X86_REG64 | (10+oid[2]-'0'); - return YASM_ARCH_CHECK_ID_REG; + return 1; } - E A X { data[0] = X86_REG32 | 0; return YASM_ARCH_CHECK_ID_REG; } - E C X { data[0] = X86_REG32 | 1; return YASM_ARCH_CHECK_ID_REG; } - E D X { data[0] = X86_REG32 | 2; return YASM_ARCH_CHECK_ID_REG; } - E B X { data[0] = X86_REG32 | 3; return YASM_ARCH_CHECK_ID_REG; } - E S P { data[0] = X86_REG32 | 4; return YASM_ARCH_CHECK_ID_REG; } - E B P { data[0] = X86_REG32 | 5; return YASM_ARCH_CHECK_ID_REG; } - E S I { data[0] = X86_REG32 | 6; return YASM_ARCH_CHECK_ID_REG; } - E D I { data[0] = X86_REG32 | 7; return YASM_ARCH_CHECK_ID_REG; } + E A X { data[0] = X86_REG32 | 0; return 1; } + E C X { data[0] = X86_REG32 | 1; return 1; } + E D X { data[0] = X86_REG32 | 2; return 1; } + E B X { data[0] = X86_REG32 | 3; return 1; } + E S P { data[0] = X86_REG32 | 4; return 1; } + E B P { data[0] = X86_REG32 | 5; return 1; } + E S I { data[0] = X86_REG32 | 6; return 1; } + E D I { data[0] = X86_REG32 | 7; return 1; } R [8-9] D { if (arch_x86->mode_bits != 64) { yasm__warning(YASM_WARN_GENERAL, line, N_("`%s' is a register in 64-bit mode"), oid); - return YASM_ARCH_CHECK_ID_NONE; + return 0; } data[0] = X86_REG32 | (oid[1]-'0'); - return YASM_ARCH_CHECK_ID_REG; + return 1; } R "1" [0-5] D { if (arch_x86->mode_bits != 64) { yasm__warning(YASM_WARN_GENERAL, line, N_("`%s' is a register in 64-bit mode"), oid); - return YASM_ARCH_CHECK_ID_NONE; + return 0; } data[0] = X86_REG32 | (10+oid[2]-'0'); - return YASM_ARCH_CHECK_ID_REG; + return 1; } - A X { data[0] = X86_REG16 | 0; return YASM_ARCH_CHECK_ID_REG; } - C X { data[0] = X86_REG16 | 1; return YASM_ARCH_CHECK_ID_REG; } - D X { data[0] = X86_REG16 | 2; return YASM_ARCH_CHECK_ID_REG; } - B X { data[0] = X86_REG16 | 3; return YASM_ARCH_CHECK_ID_REG; } - S P { data[0] = X86_REG16 | 4; return YASM_ARCH_CHECK_ID_REG; } - B P { data[0] = X86_REG16 | 5; return YASM_ARCH_CHECK_ID_REG; } - S I { data[0] = X86_REG16 | 6; return YASM_ARCH_CHECK_ID_REG; } - D I { data[0] = X86_REG16 | 7; return YASM_ARCH_CHECK_ID_REG; } + A X { data[0] = X86_REG16 | 0; return 1; } + C X { data[0] = X86_REG16 | 1; return 1; } + D X { data[0] = X86_REG16 | 2; return 1; } + B X { data[0] = X86_REG16 | 3; return 1; } + S P { data[0] = X86_REG16 | 4; return 1; } + B P { data[0] = X86_REG16 | 5; return 1; } + S I { data[0] = X86_REG16 | 6; return 1; } + D I { data[0] = X86_REG16 | 7; return 1; } R [8-9] W { if (arch_x86->mode_bits != 64) { yasm__warning(YASM_WARN_GENERAL, line, N_("`%s' is a register in 64-bit mode"), oid); - return YASM_ARCH_CHECK_ID_NONE; + return 0; } data[0] = X86_REG16 | (oid[1]-'0'); - return YASM_ARCH_CHECK_ID_REG; + return 1; } R "1" [0-5] W { if (arch_x86->mode_bits != 64) { yasm__warning(YASM_WARN_GENERAL, line, N_("`%s' is a register in 64-bit mode"), oid); - return YASM_ARCH_CHECK_ID_NONE; + return 0; } data[0] = X86_REG16 | (10+oid[2]-'0'); - return YASM_ARCH_CHECK_ID_REG; + return 1; } - A L { data[0] = X86_REG8 | 0; return YASM_ARCH_CHECK_ID_REG; } - C L { data[0] = X86_REG8 | 1; return YASM_ARCH_CHECK_ID_REG; } - D L { data[0] = X86_REG8 | 2; return YASM_ARCH_CHECK_ID_REG; } - B L { data[0] = X86_REG8 | 3; return YASM_ARCH_CHECK_ID_REG; } - A H { data[0] = X86_REG8 | 4; return YASM_ARCH_CHECK_ID_REG; } - C H { data[0] = X86_REG8 | 5; return YASM_ARCH_CHECK_ID_REG; } - D H { data[0] = X86_REG8 | 6; return YASM_ARCH_CHECK_ID_REG; } - B H { data[0] = X86_REG8 | 7; return YASM_ARCH_CHECK_ID_REG; } + A L { data[0] = X86_REG8 | 0; return 1; } + C L { data[0] = X86_REG8 | 1; return 1; } + D L { data[0] = X86_REG8 | 2; return 1; } + B L { data[0] = X86_REG8 | 3; return 1; } + A H { data[0] = X86_REG8 | 4; return 1; } + C H { data[0] = X86_REG8 | 5; return 1; } + D H { data[0] = X86_REG8 | 6; return 1; } + B H { data[0] = X86_REG8 | 7; return 1; } S P L { if (arch_x86->mode_bits != 64) { yasm__warning(YASM_WARN_GENERAL, line, N_("`%s' is a register in 64-bit mode"), oid); - return YASM_ARCH_CHECK_ID_NONE; + return 0; } data[0] = X86_REG8X | 4; - return YASM_ARCH_CHECK_ID_REG; + return 1; } B P L { if (arch_x86->mode_bits != 64) { yasm__warning(YASM_WARN_GENERAL, line, N_("`%s' is a register in 64-bit mode"), oid); - return YASM_ARCH_CHECK_ID_NONE; + return 0; } data[0] = X86_REG8X | 5; - return YASM_ARCH_CHECK_ID_REG; + return 1; } S I L { if (arch_x86->mode_bits != 64) { yasm__warning(YASM_WARN_GENERAL, line, N_("`%s' is a register in 64-bit mode"), oid); - return YASM_ARCH_CHECK_ID_NONE; + return 0; } data[0] = X86_REG8X | 6; - return YASM_ARCH_CHECK_ID_REG; + return 1; } D I L { if (arch_x86->mode_bits != 64) { yasm__warning(YASM_WARN_GENERAL, line, N_("`%s' is a register in 64-bit mode"), oid); - return YASM_ARCH_CHECK_ID_NONE; + return 0; } data[0] = X86_REG8X | 7; - return YASM_ARCH_CHECK_ID_REG; + return 1; } R [8-9] B { if (arch_x86->mode_bits != 64) { yasm__warning(YASM_WARN_GENERAL, line, N_("`%s' is a register in 64-bit mode"), oid); - return YASM_ARCH_CHECK_ID_NONE; + return 0; } data[0] = X86_REG8 | (oid[1]-'0'); - return YASM_ARCH_CHECK_ID_REG; + return 1; } R "1" [0-5] B { if (arch_x86->mode_bits != 64) { yasm__warning(YASM_WARN_GENERAL, line, N_("`%s' is a register in 64-bit mode"), oid); - return YASM_ARCH_CHECK_ID_NONE; + return 0; } data[0] = X86_REG8 | (10+oid[2]-'0'); - return YASM_ARCH_CHECK_ID_REG; + return 1; + } + + /* RIP for 64-bit mode IP-relative offsets */ + R I P { + if (arch_x86->mode_bits != 64) { + yasm__warning(YASM_WARN_GENERAL, line, + N_("`%s' is a register in 64-bit mode"), oid); + return 0; + } + data[0] = X86_RIP; + return 1; + } + + /* catchalls */ + [\001-\377]+ { + return 0; + } + [\000] { + return 0; + } + */ + return 0; +} + +int +yasm_x86__parse_check_reggroup(yasm_arch *arch, unsigned long data[1], + const char *id, unsigned long line) +{ + const char *oid = id; + /*!re2c + /* floating point, MMX, and SSE/SSE2 registers */ + S T { + data[0] = X86_FPUREG; + return 1; + } + M M { + data[0] = X86_MMXREG; + return 1; } + X M M { + data[0] = X86_XMMREG; + return 1; + } + + /* catchalls */ + [\001-\377]+ { + return 0; + } + [\000] { + return 0; + } + */ + return 0; +} +int +yasm_x86__parse_check_segreg(yasm_arch *arch, unsigned long data[1], + const char *id, unsigned long line) +{ + yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch; + const char *oid = id; + /*!re2c /* segment registers */ E S { if (arch_x86->mode_bits == 64) yasm__warning(YASM_WARN_GENERAL, line, N_("`%s' segment register ignored in 64-bit mode"), oid); data[0] = 0x2600; - return YASM_ARCH_CHECK_ID_SEGREG; + return 1; } - C S { data[0] = 0x2e01; return YASM_ARCH_CHECK_ID_SEGREG; } + C S { data[0] = 0x2e01; return 1; } S S { if (arch_x86->mode_bits == 64) yasm__warning(YASM_WARN_GENERAL, line, N_("`%s' segment register ignored in 64-bit mode"), oid); data[0] = 0x3602; - return YASM_ARCH_CHECK_ID_SEGREG; + return 1; } D S { if (arch_x86->mode_bits == 64) yasm__warning(YASM_WARN_GENERAL, line, N_("`%s' segment register ignored in 64-bit mode"), oid); data[0] = 0x3e03; - return YASM_ARCH_CHECK_ID_SEGREG; - } - F S { data[0] = 0x6404; return YASM_ARCH_CHECK_ID_SEGREG; } - G S { data[0] = 0x6505; return YASM_ARCH_CHECK_ID_SEGREG; } - - /* RIP for 64-bit mode IP-relative offsets */ - R I P { - if (arch_x86->mode_bits != 64) { - yasm__warning(YASM_WARN_GENERAL, line, - N_("`%s' is a register in 64-bit mode"), oid); - return YASM_ARCH_CHECK_ID_NONE; - } - data[0] = X86_RIP; - return YASM_ARCH_CHECK_ID_REG; + return 1; } + F S { data[0] = 0x6404; return 1; } + G S { data[0] = 0x6505; return 1; } /* catchalls */ [\001-\377]+ { - return YASM_ARCH_CHECK_ID_NONE; + return 0; } [\000] { - return YASM_ARCH_CHECK_ID_NONE; + return 0; } */ - return YASM_ARCH_CHECK_ID_NONE; + return 0; } #define RET_INSN(nosuffixsize, group, mod, cpu) do { \ @@ -3383,17 +3411,17 @@ yasm_x86__parse_check_reg(yasm_arch *arch, unsigned long data[4], #define RET_INSN_GAS(nosuffixsize, group, mod, cpu) do { \ if (arch_x86->parser != X86_PARSER_GAS) \ - return YASM_ARCH_CHECK_ID_NONE; \ + return 0; \ RET_INSN(nosuffixsize, group, mod, cpu); \ } while (0) #define RET_INSN_NONGAS(nosuffixsize, group, mod, cpu) do { \ if (arch_x86->parser == X86_PARSER_GAS) \ - return YASM_ARCH_CHECK_ID_NONE; \ + return 0; \ RET_INSN(nosuffixsize, group, mod, cpu); \ } while (0) -static yasm_arch_check_id_retval +int yasm_x86__parse_check_insn(yasm_arch *arch, unsigned long data[4], const char *id, unsigned long line) { @@ -4283,17 +4311,17 @@ yasm_x86__parse_check_insn(yasm_arch *arch, unsigned long data[4], /* catchalls */ [\001-\377]+ { - return YASM_ARCH_CHECK_ID_NONE; + return 0; } [\000] { - return YASM_ARCH_CHECK_ID_NONE; + return 0; } */ done: if (suffix) { /* If not using the GAS parser, no instructions have suffixes. */ if (arch_x86->parser != X86_PARSER_GAS) - return YASM_ARCH_CHECK_ID_NONE; + return 0; /* Match suffixes */ switch (id[suffix_ofs]) { @@ -4325,37 +4353,12 @@ done: yasm__warning(YASM_WARN_GENERAL, line, N_("`%s' is an instruction in 64-bit mode"), oid); - return YASM_ARCH_CHECK_ID_NONE; + return 0; } if (not64 && arch_x86->mode_bits == 64) { yasm__error(line, N_("`%s' invalid in 64-bit mode"), oid); DEF_INSN_DATA(not64, 0, CPU_Not64); - return YASM_ARCH_CHECK_ID_INSN; + return 1; } - return YASM_ARCH_CHECK_ID_INSN; -} - -yasm_arch_check_id_retval -yasm_x86__parse_check_id(yasm_arch *arch, unsigned long data[4], - const char *id, unsigned long line) -{ - yasm_arch_check_id_retval rv; - - rv = yasm_x86__parse_check_reg(arch, data, id, line); - if (rv != YASM_ARCH_CHECK_ID_NONE) - return rv; - - rv = yasm_x86__parse_check_insn(arch, data, id, line); - if (rv != YASM_ARCH_CHECK_ID_NONE) - return rv; - - rv = yasm_x86__parse_check_prefix(arch, data, id, line); - if (rv != YASM_ARCH_CHECK_ID_NONE) - return rv; - - rv = yasm_x86__parse_check_targetmod(arch, data, id, line); - if (rv != YASM_ARCH_CHECK_ID_NONE) - return rv; - - return YASM_ARCH_CHECK_ID_NONE; + return 1; } diff --git a/modules/parsers/gas/gas-token.re b/modules/parsers/gas/gas-token.re index 84542d04..1d775e35 100644 --- a/modules/parsers/gas/gas-token.re +++ b/modules/parsers/gas/gas-token.re @@ -198,7 +198,6 @@ gas_parser_lex(YYSTYPE *lvalp, yasm_parser_gas *parser_gas) YYCTYPE *cursor = s->cur; size_t count; YYCTYPE savech; - yasm_arch_check_id_retval check_id_ret; /* Catch EOF */ if (s->eof && cursor == s->eof) @@ -342,59 +341,52 @@ scan: [%][a-z0-9]+ { savech = s->tok[TOKLEN]; s->tok[TOKLEN] = '\0'; - check_id_ret = yasm_arch_parse_check_id(parser_gas->arch, - lvalp->arch_data, s->tok+1, - cur_line); - s->tok[TOKLEN] = savech; - switch (check_id_ret) { - case YASM_ARCH_CHECK_ID_REG: - RETURN(REG); - case YASM_ARCH_CHECK_ID_REGGROUP: - RETURN(REGGROUP); - case YASM_ARCH_CHECK_ID_SEGREG: - RETURN(SEGREG); - default: - s->tok[TOKLEN] = '\0'; - yasm__error(cur_line, - N_("Unrecognized register name `%s'"), s->tok); - s->tok[TOKLEN] = savech; - lvalp->arch_data[0] = 0; - lvalp->arch_data[1] = 0; - lvalp->arch_data[2] = 0; - lvalp->arch_data[3] = 0; - RETURN(REG); + if (yasm_arch_parse_check_reg(parser_gas->arch, lvalp->arch_data, + s->tok+1, cur_line)) { + s->tok[TOKLEN] = savech; + RETURN(REG); + } + if (yasm_arch_parse_check_reggroup(parser_gas->arch, + lvalp->arch_data, s->tok+1, + cur_line)) { + s->tok[TOKLEN] = savech; + RETURN(REGGROUP); + } + if (yasm_arch_parse_check_segreg(parser_gas->arch, + lvalp->arch_data, s->tok+1, + cur_line)) { + s->tok[TOKLEN] = savech; + RETURN(SEGREG); } + yasm__error(cur_line, N_("Unrecognized register name `%s'"), + s->tok); + s->tok[TOKLEN] = savech; + lvalp->arch_data[0] = 0; + lvalp->arch_data[1] = 0; + lvalp->arch_data[2] = 0; + lvalp->arch_data[3] = 0; + RETURN(REG); } /* identifier that may be an instruction, etc. */ [a-zA-Z][a-zA-Z0-9_$.]* { savech = s->tok[TOKLEN]; s->tok[TOKLEN] = '\0'; - check_id_ret = yasm_arch_parse_check_id(parser_gas->arch, - lvalp->arch_data, s->tok, - cur_line); - s->tok[TOKLEN] = savech; - switch (check_id_ret) { - case YASM_ARCH_CHECK_ID_NONE: - /* Just an identifier, return as such. */ - lvalp->str_val = yasm__xstrndup(s->tok, TOKLEN); - RETURN(ID); - case YASM_ARCH_CHECK_ID_INSN: - RETURN(INSN); - case YASM_ARCH_CHECK_ID_PREFIX: - RETURN(PREFIX); - case YASM_ARCH_CHECK_ID_TARGETMOD: - RETURN(TARGETMOD); - case YASM_ARCH_CHECK_ID_REG: - case YASM_ARCH_CHECK_ID_SEGREG: - lvalp->str_val = yasm__xstrndup(s->tok, TOKLEN); - RETURN(ID); - default: - yasm__warning(YASM_WARN_GENERAL, cur_line, - N_("Arch feature not supported, treating as identifier")); - lvalp->str_val = yasm__xstrndup(s->tok, TOKLEN); - RETURN(ID); + if (yasm_arch_parse_check_insn(parser_gas->arch, lvalp->arch_data, + s->tok, cur_line)) { + s->tok[TOKLEN] = savech; + RETURN(INSN); } + if (yasm_arch_parse_check_prefix(parser_gas->arch, + lvalp->arch_data, s->tok, + cur_line)) { + s->tok[TOKLEN] = savech; + RETURN(PREFIX); + } + s->tok[TOKLEN] = savech; + /* Just an identifier, return as such. */ + lvalp->str_val = yasm__xstrndup(s->tok, TOKLEN); + RETURN(ID); } "#" (any \ [\n])* { goto scan; } diff --git a/modules/parsers/nasm/nasm-token.re b/modules/parsers/nasm/nasm-token.re index c0a43bc3..e21a9fb5 100644 --- a/modules/parsers/nasm/nasm-token.re +++ b/modules/parsers/nasm/nasm-token.re @@ -186,7 +186,6 @@ nasm_parser_lex(YYSTYPE *lvalp, yasm_parser_nasm *parser_nasm) YYCTYPE endch; size_t count, len; YYCTYPE savech; - yasm_arch_check_id_retval check_id_ret; /* Catch EOF */ if (s->eof && cursor == s->eof) @@ -409,31 +408,38 @@ scan: [a-zA-Z_?][a-zA-Z0-9_$#@~.?]* { savech = s->tok[TOKLEN]; s->tok[TOKLEN] = '\0'; - check_id_ret = yasm_arch_parse_check_id(parser_nasm->arch, - lvalp->arch_data, s->tok, - cur_line); - s->tok[TOKLEN] = savech; - switch (check_id_ret) { - case YASM_ARCH_CHECK_ID_NONE: - /* Just an identifier, return as such. */ - lvalp->str_val = yasm__xstrndup(s->tok, TOKLEN); - RETURN(ID); - case YASM_ARCH_CHECK_ID_INSN: - RETURN(INSN); - case YASM_ARCH_CHECK_ID_PREFIX: - RETURN(PREFIX); - case YASM_ARCH_CHECK_ID_REG: - RETURN(REG); - case YASM_ARCH_CHECK_ID_SEGREG: - RETURN(SEGREG); - case YASM_ARCH_CHECK_ID_TARGETMOD: - RETURN(TARGETMOD); - default: - yasm__warning(YASM_WARN_GENERAL, cur_line, - N_("Arch feature not supported, treating as identifier")); - lvalp->str_val = yasm__xstrndup(s->tok, TOKLEN); - RETURN(ID); + if (yasm_arch_parse_check_reg(parser_nasm->arch, lvalp->arch_data, + s->tok, cur_line)) { + s->tok[TOKLEN] = savech; + RETURN(REG); + } + if (yasm_arch_parse_check_insn(parser_nasm->arch, lvalp->arch_data, + s->tok, cur_line)) { + s->tok[TOKLEN] = savech; + RETURN(INSN); + } + if (yasm_arch_parse_check_segreg(parser_nasm->arch, + lvalp->arch_data, s->tok, + cur_line)) { + s->tok[TOKLEN] = savech; + RETURN(SEGREG); + } + if (yasm_arch_parse_check_prefix(parser_nasm->arch, + lvalp->arch_data, s->tok, + cur_line)) { + s->tok[TOKLEN] = savech; + RETURN(PREFIX); } + if (yasm_arch_parse_check_targetmod(parser_nasm->arch, + lvalp->arch_data, s->tok, + cur_line)) { + s->tok[TOKLEN] = savech; + RETURN(TARGETMOD); + } + s->tok[TOKLEN] = savech; + /* Just an identifier, return as such. */ + lvalp->str_val = yasm__xstrndup(s->tok, TOKLEN); + RETURN(ID); } ";" (any \ [\n])* { goto scan; } -- 2.40.0