#include "sysdep.h"
#include <stdio.h>
#include "ansidecl.h"
#include "bfd.h"
#include "symcat.h"
#include "ms1-desc.h"
#include "ms1-opc.h"
#include "opintl.h"
#include "xregex.h"
#include "libiberty.h"
#include "safe-ctype.h"
#undef min
#define min(a,b) ((a) < (b) ? (a) : (b))
#undef max
#define max(a,b) ((a) > (b) ? (a) : (b))
static const char * parse_insn_normal
(CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *);
static int
signed_out_of_bounds (long val)
{
if ((val < -32768) || (val > 32767))
return 1;
return 0;
}
static const char *
parse_imm16 (CGEN_CPU_DESC cd,
const char **strp,
int opindex,
void *arg)
{
signed long * valuep = (signed long *) arg;
const char *errmsg;
enum cgen_parse_operand_result result_type;
bfd_reloc_code_real_type code = BFD_RELOC_NONE;
bfd_vma value;
if (opindex == (CGEN_OPERAND_TYPE) MS1_OPERAND_IMM16O)
{
code = BFD_RELOC_16_PCREL;
errmsg = cgen_parse_address (cd, strp, opindex, code,
& result_type, & value);
if (errmsg == NULL)
{
if (signed_out_of_bounds (value))
errmsg = _("Operand out of range. Must be between -32768 and 32767.");
}
*valuep = value;
return errmsg;
}
if (strncmp (*strp, "%hi16", 5) == 0)
{
*strp += 5;
code = BFD_RELOC_HI16;
}
else if (strncmp (*strp, "%lo16", 5) == 0)
{
*strp += 5;
code = BFD_RELOC_LO16;
}
if (code != BFD_RELOC_NONE)
{
errmsg = cgen_parse_address (cd, strp, opindex, code,
& result_type, & value);
if (errmsg == NULL)
{
switch (result_type)
{
case (CGEN_PARSE_OPERAND_RESULT_NUMBER):
if (code == BFD_RELOC_HI16)
value = (value >> 16) & 0xFFFF;
else if (code == BFD_RELOC_LO16)
value = value & 0xFFFF;
else
errmsg = _("Biiiig Trouble in parse_imm16!");
break;
case (CGEN_PARSE_OPERAND_RESULT_QUEUED):
break;
default:
errmsg = _("%operator operand is not a symbol");
break;
}
}
*valuep = value;
}
else
{
int parse_signed = (opindex == (CGEN_OPERAND_TYPE)MS1_OPERAND_IMM16);
if ((*strp)[0] == '0'
&& ((*strp)[1] == 'x' || (*strp)[1] == 'X'))
parse_signed = 0;
if (parse_signed)
{
errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
if (errmsg == NULL)
{
#if 0
if (*valuep & 0x8000)
value = 0xffff0000 | *valuep;
else
value = *valuep;
if (signed_out_of_bounds (value))
errmsg = _("Operand out of range. Must be between -32768 and 32767.");
*valuep &= 0xFFFF;
#endif
}
}
else
{
errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, (unsigned long *) valuep);
if (opindex == (CGEN_OPERAND_TYPE) MS1_OPERAND_IMM16
&& *valuep >= 0x8000
&& *valuep <= 0xffff)
*valuep -= 0x10000;
}
}
return errmsg;
}
static const char *
parse_dup (CGEN_CPU_DESC cd,
const char **strp,
int opindex,
unsigned long *valuep)
{
const char *errmsg = NULL;
if (strncmp (*strp, "dup", 3) == 0 || strncmp (*strp, "DUP", 3) == 0)
{
*strp += 3;
*valuep = 1;
}
else if (strncmp (*strp, "xx", 2) == 0 || strncmp (*strp, "XX", 2) == 0)
{
*strp += 2;
*valuep = 0;
}
else
errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
return errmsg;
}
static const char *
parse_ball (CGEN_CPU_DESC cd,
const char **strp,
int opindex,
unsigned long *valuep)
{
const char *errmsg = NULL;
if (strncmp (*strp, "all", 3) == 0 || strncmp (*strp, "ALL", 3) == 0)
{
*strp += 3;
*valuep = 1;
}
else if (strncmp (*strp, "one", 3) == 0 || strncmp (*strp, "ONE", 3) == 0)
{
*strp += 3;
*valuep = 0;
}
else
errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
return errmsg;
}
static const char *
parse_xmode (CGEN_CPU_DESC cd,
const char **strp,
int opindex,
unsigned long *valuep)
{
const char *errmsg = NULL;
if (strncmp (*strp, "pm", 2) == 0 || strncmp (*strp, "PM", 2) == 0)
{
*strp += 2;
*valuep = 1;
}
else if (strncmp (*strp, "xm", 2) == 0 || strncmp (*strp, "XM", 2) == 0)
{
*strp += 2;
*valuep = 0;
}
else
errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
return errmsg;
}
static const char *
parse_rc (CGEN_CPU_DESC cd,
const char **strp,
int opindex,
unsigned long *valuep)
{
const char *errmsg = NULL;
if (strncmp (*strp, "r", 1) == 0 || strncmp (*strp, "R", 1) == 0)
{
*strp += 1;
*valuep = 1;
}
else if (strncmp (*strp, "c", 1) == 0 || strncmp (*strp, "C", 1) == 0)
{
*strp += 1;
*valuep = 0;
}
else
errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
return errmsg;
}
static const char *
parse_cbrb (CGEN_CPU_DESC cd,
const char **strp,
int opindex,
unsigned long *valuep)
{
const char *errmsg = NULL;
if (strncmp (*strp, "rb", 2) == 0 || strncmp (*strp, "RB", 2) == 0)
{
*strp += 2;
*valuep = 1;
}
else if (strncmp (*strp, "cb", 2) == 0 || strncmp (*strp, "CB", 2) == 0)
{
*strp += 2;
*valuep = 0;
}
else
errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
return errmsg;
}
static const char *
parse_rbbc (CGEN_CPU_DESC cd,
const char **strp,
int opindex,
unsigned long *valuep)
{
const char *errmsg = NULL;
if (strncmp (*strp, "rt", 2) == 0 || strncmp (*strp, "RT", 2) == 0)
{
*strp += 2;
*valuep = 0;
}
else if (strncmp (*strp, "br1", 3) == 0 || strncmp (*strp, "BR1", 3) == 0)
{
*strp += 3;
*valuep = 1;
}
else if (strncmp (*strp, "br2", 3) == 0 || strncmp (*strp, "BR2", 3) == 0)
{
*strp += 3;
*valuep = 2;
}
else if (strncmp (*strp, "cs", 2) == 0 || strncmp (*strp, "CS", 2) == 0)
{
*strp += 2;
*valuep = 3;
}
else
errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
return errmsg;
}
static const char *
parse_type (CGEN_CPU_DESC cd,
const char **strp,
int opindex,
unsigned long *valuep)
{
const char *errmsg = NULL;
if (strncmp (*strp, "odd", 3) == 0 || strncmp (*strp, "ODD", 3) == 0)
{
*strp += 3;
*valuep = 0;
}
else if (strncmp (*strp, "even", 4) == 0 || strncmp (*strp, "EVEN", 4) == 0)
{
*strp += 4;
*valuep = 1;
}
else if (strncmp (*strp, "oe", 2) == 0 || strncmp (*strp, "OE", 2) == 0)
{
*strp += 2;
*valuep = 2;
}
else
errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
if ((errmsg == NULL) && (*valuep == 3))
errmsg = _("invalid operand. type may have values 0,1,2 only.");
return errmsg;
}
const char * ms1_cgen_parse_operand
(CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
const char *
ms1_cgen_parse_operand (CGEN_CPU_DESC cd,
int opindex,
const char ** strp,
CGEN_FIELDS * fields)
{
const char * errmsg = NULL;
long junk ATTRIBUTE_UNUSED;
switch (opindex)
{
case MS1_OPERAND_A23 :
errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_A23, (unsigned long *) (& fields->f_a23));
break;
case MS1_OPERAND_BALL :
errmsg = parse_ball (cd, strp, MS1_OPERAND_BALL, (unsigned long *) (& fields->f_ball));
break;
case MS1_OPERAND_BALL2 :
errmsg = parse_ball (cd, strp, MS1_OPERAND_BALL2, (unsigned long *) (& fields->f_ball2));
break;
case MS1_OPERAND_BANKADDR :
errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_BANKADDR, (unsigned long *) (& fields->f_bankaddr));
break;
case MS1_OPERAND_BRC :
errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_BRC, (unsigned long *) (& fields->f_brc));
break;
case MS1_OPERAND_BRC2 :
errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_BRC2, (unsigned long *) (& fields->f_brc2));
break;
case MS1_OPERAND_CBRB :
errmsg = parse_cbrb (cd, strp, MS1_OPERAND_CBRB, (unsigned long *) (& fields->f_cbrb));
break;
case MS1_OPERAND_CBS :
errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_CBS, (unsigned long *) (& fields->f_cbs));
break;
case MS1_OPERAND_CBX :
errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_CBX, (unsigned long *) (& fields->f_cbx));
break;
case MS1_OPERAND_CCB :
errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_CCB, (unsigned long *) (& fields->f_ccb));
break;
case MS1_OPERAND_CDB :
errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_CDB, (unsigned long *) (& fields->f_cdb));
break;
case MS1_OPERAND_CELL :
errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_CELL, (unsigned long *) (& fields->f_cell));
break;
case MS1_OPERAND_COLNUM :
errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_COLNUM, (unsigned long *) (& fields->f_colnum));
break;
case MS1_OPERAND_CONTNUM :
errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_CONTNUM, (unsigned long *) (& fields->f_contnum));
break;
case MS1_OPERAND_CR :
errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_CR, (unsigned long *) (& fields->f_cr));
break;
case MS1_OPERAND_CTXDISP :
errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_CTXDISP, (unsigned long *) (& fields->f_ctxdisp));
break;
case MS1_OPERAND_DUP :
errmsg = parse_dup (cd, strp, MS1_OPERAND_DUP, (unsigned long *) (& fields->f_dup));
break;
case MS1_OPERAND_FBDISP :
errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_FBDISP, (unsigned long *) (& fields->f_fbdisp));
break;
case MS1_OPERAND_FBINCR :
errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_FBINCR, (unsigned long *) (& fields->f_fbincr));
break;
case MS1_OPERAND_FRDR :
errmsg = cgen_parse_keyword (cd, strp, & ms1_cgen_opval_h_spr, & fields->f_dr);
break;
case MS1_OPERAND_FRDRRR :
errmsg = cgen_parse_keyword (cd, strp, & ms1_cgen_opval_h_spr, & fields->f_drrr);
break;
case MS1_OPERAND_FRSR1 :
errmsg = cgen_parse_keyword (cd, strp, & ms1_cgen_opval_h_spr, & fields->f_sr1);
break;
case MS1_OPERAND_FRSR2 :
errmsg = cgen_parse_keyword (cd, strp, & ms1_cgen_opval_h_spr, & fields->f_sr2);
break;
case MS1_OPERAND_ID :
errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_ID, (unsigned long *) (& fields->f_id));
break;
case MS1_OPERAND_IMM16 :
errmsg = parse_imm16 (cd, strp, MS1_OPERAND_IMM16, (long *) (& fields->f_imm16s));
break;
case MS1_OPERAND_IMM16O :
errmsg = parse_imm16 (cd, strp, MS1_OPERAND_IMM16O, (unsigned long *) (& fields->f_imm16s));
break;
case MS1_OPERAND_IMM16Z :
errmsg = parse_imm16 (cd, strp, MS1_OPERAND_IMM16Z, (unsigned long *) (& fields->f_imm16u));
break;
case MS1_OPERAND_INCAMT :
errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_INCAMT, (unsigned long *) (& fields->f_incamt));
break;
case MS1_OPERAND_INCR :
errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_INCR, (unsigned long *) (& fields->f_incr));
break;
case MS1_OPERAND_LENGTH :
errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_LENGTH, (unsigned long *) (& fields->f_length));
break;
case MS1_OPERAND_MASK :
errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_MASK, (unsigned long *) (& fields->f_mask));
break;
case MS1_OPERAND_MASK1 :
errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_MASK1, (unsigned long *) (& fields->f_mask1));
break;
case MS1_OPERAND_MODE :
errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_MODE, (unsigned long *) (& fields->f_mode));
break;
case MS1_OPERAND_PERM :
errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_PERM, (unsigned long *) (& fields->f_perm));
break;
case MS1_OPERAND_RBBC :
errmsg = parse_rbbc (cd, strp, MS1_OPERAND_RBBC, (unsigned long *) (& fields->f_rbbc));
break;
case MS1_OPERAND_RC :
errmsg = parse_rc (cd, strp, MS1_OPERAND_RC, (unsigned long *) (& fields->f_rc));
break;
case MS1_OPERAND_RC1 :
errmsg = parse_rc (cd, strp, MS1_OPERAND_RC1, (unsigned long *) (& fields->f_rc1));
break;
case MS1_OPERAND_RC2 :
errmsg = parse_rc (cd, strp, MS1_OPERAND_RC2, (unsigned long *) (& fields->f_rc2));
break;
case MS1_OPERAND_RCNUM :
errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_RCNUM, (unsigned long *) (& fields->f_rcnum));
break;
case MS1_OPERAND_RDA :
errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_RDA, (unsigned long *) (& fields->f_rda));
break;
case MS1_OPERAND_ROWNUM :
errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_ROWNUM, (unsigned long *) (& fields->f_rownum));
break;
case MS1_OPERAND_ROWNUM1 :
errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_ROWNUM1, (unsigned long *) (& fields->f_rownum1));
break;
case MS1_OPERAND_ROWNUM2 :
errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_ROWNUM2, (unsigned long *) (& fields->f_rownum2));
break;
case MS1_OPERAND_SIZE :
errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_SIZE, (unsigned long *) (& fields->f_size));
break;
case MS1_OPERAND_TYPE :
errmsg = parse_type (cd, strp, MS1_OPERAND_TYPE, (unsigned long *) (& fields->f_type));
break;
case MS1_OPERAND_WR :
errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_WR, (unsigned long *) (& fields->f_wr));
break;
case MS1_OPERAND_XMODE :
errmsg = parse_xmode (cd, strp, MS1_OPERAND_XMODE, (unsigned long *) (& fields->f_xmode));
break;
default :
fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
abort ();
}
return errmsg;
}
cgen_parse_fn * const ms1_cgen_parse_handlers[] =
{
parse_insn_normal,
};
void
ms1_cgen_init_asm (CGEN_CPU_DESC cd)
{
ms1_cgen_init_opcode_table (cd);
ms1_cgen_init_ibld_table (cd);
cd->parse_handlers = & ms1_cgen_parse_handlers[0];
cd->parse_operand = ms1_cgen_parse_operand;
}
char *
ms1_cgen_build_insn_regex (CGEN_INSN *insn)
{
CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
const char *mnem = CGEN_INSN_MNEMONIC (insn);
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));
if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
return _("missing mnemonic in syntax string");
++syn;
for (; *mnem; mnem++)
{
char c = *mnem;
if (ISALPHA (c))
{
*rx++ = '[';
*rx++ = TOLOWER (c);
*rx++ = TOUPPER (c);
*rx++ = ']';
}
else
*rx++ = c;
}
for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
{
if (CGEN_SYNTAX_CHAR_P (* syn))
{
char c = CGEN_SYNTAX_CHAR (* syn);
switch (c)
{
case '.': case '[': case '\\':
case '*': case '^': case '$':
#ifdef CGEN_ESCAPE_EXTENDED_REGEX
case '?': case '{': case '}':
case '(': case ')': case '*':
case '|': case '+': case ']':
#endif
*rx++ = '\\';
*rx++ = c;
break;
default:
if (ISALPHA (c))
{
*rx++ = '[';
*rx++ = TOLOWER (c);
*rx++ = TOUPPER (c);
*rx++ = ']';
}
else
*rx++ = c;
break;
}
}
else
{
*rx++ = '.';
*rx++ = '*';
}
}
* rx++ = '[';
* rx++ = ' ';
* rx++ = '\t';
* rx++ = ']';
* rx++ = '*';
* rx++ = '$';
* rx = '\0';
CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
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;
}
}
static const char *
parse_insn_normal (CGEN_CPU_DESC cd,
const CGEN_INSN *insn,
const char **strp,
CGEN_FIELDS *fields)
{
const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
const char *str = *strp;
const char *errmsg;
const char *p;
const CGEN_SYNTAX_CHAR_TYPE * syn;
#ifdef CGEN_MNEMONIC_OPERANDS
int past_opcode_p;
#endif
p = CGEN_INSN_MNEMONIC (insn);
while (*p && TOLOWER (*p) == TOLOWER (*str))
++p, ++str;
if (* p)
return _("unrecognized instruction");
#ifndef CGEN_MNEMONIC_OPERANDS
if (* str && ! ISSPACE (* str))
return _("unrecognized instruction");
#endif
CGEN_INIT_PARSE (cd);
cgen_init_parse_operand (cd);
#ifdef CGEN_MNEMONIC_OPERANDS
past_opcode_p = 0;
#endif
syn = CGEN_SYNTAX_STRING (syntax);
if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
abort ();
++syn;
while (* syn != 0)
{
if (CGEN_SYNTAX_CHAR_P (* syn))
{
if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
{
#ifdef CGEN_MNEMONIC_OPERANDS
if (CGEN_SYNTAX_CHAR(* syn) == ' ')
past_opcode_p = 1;
#endif
++ syn;
++ str;
}
else if (*str)
{
static char msg [80];
sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
CGEN_SYNTAX_CHAR(*syn), *str);
return msg;
}
else
{
static char msg [80];
sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
CGEN_SYNTAX_CHAR(*syn));
return msg;
}
continue;
}
errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
&str, fields);
if (errmsg)
return errmsg;
++ syn;
}
if (* syn == 0)
{
while (ISSPACE (* str))
++ str;
if (* str != '\0')
return _("junk at end of line");
return NULL;
}
return _("unrecognized instruction");
}
const CGEN_INSN *
ms1_cgen_assemble_insn (CGEN_CPU_DESC cd,
const char *str,
CGEN_FIELDS *fields,
CGEN_INSN_BYTES_PTR buf,
char **errmsg)
{
const char *start;
CGEN_INSN_LIST *ilist;
const char *parse_errmsg = NULL;
const char *insert_errmsg = NULL;
int recognized_mnemonic = 0;
while (ISSPACE (* str))
++ str;
ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
start = str;
for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
{
const CGEN_INSN *insn = ilist->insn;
recognized_mnemonic = 1;
#ifdef CGEN_VALIDATE_INSN_SUPPORTED
if (! ms1_cgen_insn_supported (cd, insn))
continue;
#endif
if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
continue;
str = start;
if (CGEN_INSN_RX (insn) != NULL &&
regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
continue;
CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
if (parse_errmsg != NULL)
continue;
insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
(bfd_vma) 0);
if (insert_errmsg != NULL)
continue;
return insn;
}
{
static char errbuf[150];
#ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
const char *tmp_errmsg;
tmp_errmsg = (insert_errmsg ? insert_errmsg :
parse_errmsg ? parse_errmsg :
recognized_mnemonic ?
_("unrecognized form of instruction") :
_("unrecognized instruction"));
if (strlen (start) > 50)
sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
else
sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
#else
if (strlen (start) > 50)
sprintf (errbuf, _("bad instruction `%.50s...'"), start);
else
sprintf (errbuf, _("bad instruction `%.50s'"), start);
#endif
*errmsg = errbuf;
return NULL;
}
}