From: Jeff Johnston Date: Thu, 12 Jul 2001 21:26:42 +0000 (+0000) Subject: 2001-07-12 Jeff Johnston X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=23969580f6bd5d3d0c65d962d34e39b9563ceca1;p=binutils-gdb.git 2001-07-12 Jeff Johnston * cgen-asm.in: Include "xregex.h" always to enable the libiberty regex support. (@arch@_cgen_build_insn_regex): New routine from Graydon. (@arch@_cgen_assemble_insn): Add Graydon's code to use regex to verify if it is worth parsing the insn as insn "x". Also update error message when insn is not a recognized format of the insn vs when the insn is completely unrecognized. --- diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index 4adba8a416c..be15b436737 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,13 @@ +2001-07-12 Jeff Johnston + + * cgen-asm.in: Include "xregex.h" always to enable the libiberty + regex support. + (@arch@_cgen_build_insn_regex): New routine from Graydon. + (@arch@_cgen_assemble_insn): Add Graydon's code to use regex + to verify if it is worth parsing the insn as insn "x". Also update + error message when insn is not a recognized format of the insn vs + when the insn is completely unrecognized. + 2001-07-11 Frank Ch. Eigler * cgen-dis.in (print_insn): Use cgen_get_insn_value instead of diff --git a/opcodes/cgen-asm.in b/opcodes/cgen-asm.in index aba8e46c2af..20380a29795 100644 --- a/opcodes/cgen-asm.in +++ b/opcodes/cgen-asm.in @@ -34,6 +34,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., #include "@prefix@-desc.h" #include "@prefix@-opc.h" #include "opintl.h" +#include "xregex.h" #undef min #define min(a,b) ((a) < (b) ? (a) : (b)) @@ -44,6 +45,104 @@ static const char * parse_insn_normal PARAMS ((CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *)); /* -- assembler routines inserted here */ + + +/* + Regex construction routine. + + This translates an opcode syntax string into a regex string, + by replacing any non-character syntax element (such as an + opcode) with the pattern '.*' + + It then compiles the regex and stores it in the opcode, for + later use by @arch@_cgen_assemble_insn + + returns NULL for success, an error message for failure +*/ + +char * +@arch@_cgen_build_insn_regex (insn) + CGEN_INSN *insn; +{ + CGEN_OPCODE *opc = CGEN_INSN_OPCODE (insn); + const char *mnem = CGEN_INSN_MNEMONIC (insn); + int mnem_len; + char rxbuf[CGEN_MAX_RX_ELEMENTS]; + char *rx = rxbuf; + const CGEN_SYNTAX_CHAR_TYPE *syn; + int reg_err; + + syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc)); + + /* Mnemonics come first in the syntax string */ + if (! CGEN_SYNTAX_MNEMONIC_P (* syn)) return "missing mnemonic in syntax string"; + ++syn; + + /* copy the literal mnemonic out of the insn */ + memset (rx, 0, CGEN_MAX_RX_ELEMENTS); + mnem_len = strlen(mnem); + memcpy (rx, mnem, mnem_len); + rx += mnem_len; + + /* copy any remaining literals from the syntax string into the rx */ + for(; * syn != 0 && rx < rxbuf + (CGEN_MAX_RX_ELEMENTS - 9); ++syn, ++rx) + { + if (CGEN_SYNTAX_CHAR_P (* syn)) + { + char tmp = CGEN_SYNTAX_CHAR (* syn); + switch (tmp) + { + /* escape any regex metacharacters in the syntax */ + case '.': case '[': case '\\': + case '*': case '^': case '$': + +#ifdef CGEN_ESCAPE_EXTENDED_REGEX + case '?': case '{': case '}': + case '(': case ')': case '*': + case '|': case '+': case ']': +#endif + + * rx++ = '\\'; + break; + } + /* insert syntax char into rx */ + * rx = tmp; + } + else + { + /* replace non-syntax fields with globs */ + * rx = '.'; + * ++rx = '*'; + } + } + + /* trailing whitespace ok */ + * rx++ = '['; + * rx++ = ' '; + * rx++ = '\t'; + * rx++ = ']'; + * rx++ = '*'; + + /* but anchor it after that */ + * rx++ = '$'; + * rx = '\0'; + + CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t)); + reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB|REG_ICASE); + + if (reg_err == 0) + return NULL; + else + { + static char msg[80]; + regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80); + regfree ((regex_t *) CGEN_INSN_RX (insn)); + free (CGEN_INSN_RX (insn)); + (CGEN_INSN_RX (insn)) = NULL; + return msg; + } +} + /* Default insn parser. @@ -211,6 +310,7 @@ const CGEN_INSN * CGEN_INSN_LIST *ilist; const char *parse_errmsg = NULL; const char *insert_errmsg = NULL; + int recognized_mnemonic = 0; /* Skip leading white space. */ while (isspace (* str)) @@ -226,6 +326,7 @@ const CGEN_INSN * for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist)) { const CGEN_INSN *insn = ilist->insn; + recognized_mnemonic = 1; #ifdef CGEN_VALIDATE_INSN_SUPPORTED /* not usually needed as unsupported opcodes shouldn't be in the hash lists */ @@ -242,6 +343,11 @@ const CGEN_INSN * str = start; + /* skip this insn if str doesn't look right lexically */ + if (CGEN_INSN_RX (insn) != NULL && + regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH) + continue; + /* Allow parse/insert handlers to obtain length of insn. */ CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn); @@ -269,6 +375,7 @@ const CGEN_INSN * Failing that, use parse_errmsg */ tmp_errmsg = (insert_errmsg ? insert_errmsg : parse_errmsg ? parse_errmsg : + recognized_mnemonic ? _("unrecognized form of instruction") : _("unrecognized instruction")); if (strlen (start) > 50)