OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [gas/] [app.c] - Diff between revs 156 and 816

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 156 Rev 816
/* This is the Assembler Pre-Processor
/* This is the Assembler Pre-Processor
   Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
   Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
   1999, 2000, 2001, 2002, 2003, 2006, 2007
   1999, 2000, 2001, 2002, 2003, 2006, 2007
   Free Software Foundation, Inc.
   Free Software Foundation, Inc.
 
 
   This file is part of GAS, the GNU Assembler.
   This file is part of GAS, the GNU Assembler.
 
 
   GAS is free software; you can redistribute it and/or modify
   GAS is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3, or (at your option)
   the Free Software Foundation; either version 3, or (at your option)
   any later version.
   any later version.
 
 
   GAS is distributed in the hope that it will be useful, but WITHOUT
   GAS is distributed in the hope that it will be useful, but WITHOUT
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
   License for more details.
   License for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with GAS; see the file COPYING.  If not, write to the Free
   along with GAS; see the file COPYING.  If not, write to the Free
   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
   02110-1301, USA.  */
   02110-1301, USA.  */
 
 
/* Modified by Allen Wirfs-Brock, Instantiations Inc 2/90.  */
/* Modified by Allen Wirfs-Brock, Instantiations Inc 2/90.  */
/* App, the assembler pre-processor.  This pre-processor strips out
/* App, the assembler pre-processor.  This pre-processor strips out
   excess spaces, turns single-quoted characters into a decimal
   excess spaces, turns single-quoted characters into a decimal
   constant, and turns the # in # <number> <filename> <garbage> into a
   constant, and turns the # in # <number> <filename> <garbage> into a
   .linefile.  This needs better error-handling.  */
   .linefile.  This needs better error-handling.  */
 
 
#include "as.h"
#include "as.h"
 
 
#if (__STDC__ != 1)
#if (__STDC__ != 1)
#ifndef const
#ifndef const
#define const  /* empty */
#define const  /* empty */
#endif
#endif
#endif
#endif
 
 
#ifdef TC_M68K
#ifdef TC_M68K
/* Whether we are scrubbing in m68k MRI mode.  This is different from
/* Whether we are scrubbing in m68k MRI mode.  This is different from
   flag_m68k_mri, because the two flags will be affected by the .mri
   flag_m68k_mri, because the two flags will be affected by the .mri
   pseudo-op at different times.  */
   pseudo-op at different times.  */
static int scrub_m68k_mri;
static int scrub_m68k_mri;
 
 
/* The pseudo-op which switches in and out of MRI mode.  See the
/* The pseudo-op which switches in and out of MRI mode.  See the
   comment in do_scrub_chars.  */
   comment in do_scrub_chars.  */
static const char mri_pseudo[] = ".mri 0";
static const char mri_pseudo[] = ".mri 0";
#else
#else
#define scrub_m68k_mri 0
#define scrub_m68k_mri 0
#endif
#endif
 
 
#if defined TC_ARM && defined OBJ_ELF
#if defined TC_ARM && defined OBJ_ELF
/* The pseudo-op for which we need to special-case `@' characters.
/* The pseudo-op for which we need to special-case `@' characters.
   See the comment in do_scrub_chars.  */
   See the comment in do_scrub_chars.  */
static const char   symver_pseudo[] = ".symver";
static const char   symver_pseudo[] = ".symver";
static const char * symver_state;
static const char * symver_state;
#endif
#endif
 
 
static char lex[256];
static char lex[256];
static const char symbol_chars[] =
static const char symbol_chars[] =
"$._ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
"$._ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
 
 
#define LEX_IS_SYMBOL_COMPONENT         1
#define LEX_IS_SYMBOL_COMPONENT         1
#define LEX_IS_WHITESPACE               2
#define LEX_IS_WHITESPACE               2
#define LEX_IS_LINE_SEPARATOR           3
#define LEX_IS_LINE_SEPARATOR           3
#define LEX_IS_COMMENT_START            4
#define LEX_IS_COMMENT_START            4
#define LEX_IS_LINE_COMMENT_START       5
#define LEX_IS_LINE_COMMENT_START       5
#define LEX_IS_TWOCHAR_COMMENT_1ST      6
#define LEX_IS_TWOCHAR_COMMENT_1ST      6
#define LEX_IS_STRINGQUOTE              8
#define LEX_IS_STRINGQUOTE              8
#define LEX_IS_COLON                    9
#define LEX_IS_COLON                    9
#define LEX_IS_NEWLINE                  10
#define LEX_IS_NEWLINE                  10
#define LEX_IS_ONECHAR_QUOTE            11
#define LEX_IS_ONECHAR_QUOTE            11
#ifdef TC_V850
#ifdef TC_V850
#define LEX_IS_DOUBLEDASH_1ST           12
#define LEX_IS_DOUBLEDASH_1ST           12
#endif
#endif
#ifdef TC_M32R
#ifdef TC_M32R
#define DOUBLEBAR_PARALLEL
#define DOUBLEBAR_PARALLEL
#endif
#endif
#ifdef DOUBLEBAR_PARALLEL
#ifdef DOUBLEBAR_PARALLEL
#define LEX_IS_DOUBLEBAR_1ST            13
#define LEX_IS_DOUBLEBAR_1ST            13
#endif
#endif
#define LEX_IS_PARALLEL_SEPARATOR       14
#define LEX_IS_PARALLEL_SEPARATOR       14
#define IS_SYMBOL_COMPONENT(c)          (lex[c] == LEX_IS_SYMBOL_COMPONENT)
#define IS_SYMBOL_COMPONENT(c)          (lex[c] == LEX_IS_SYMBOL_COMPONENT)
#define IS_WHITESPACE(c)                (lex[c] == LEX_IS_WHITESPACE)
#define IS_WHITESPACE(c)                (lex[c] == LEX_IS_WHITESPACE)
#define IS_LINE_SEPARATOR(c)            (lex[c] == LEX_IS_LINE_SEPARATOR)
#define IS_LINE_SEPARATOR(c)            (lex[c] == LEX_IS_LINE_SEPARATOR)
#define IS_PARALLEL_SEPARATOR(c)        (lex[c] == LEX_IS_PARALLEL_SEPARATOR)
#define IS_PARALLEL_SEPARATOR(c)        (lex[c] == LEX_IS_PARALLEL_SEPARATOR)
#define IS_COMMENT(c)                   (lex[c] == LEX_IS_COMMENT_START)
#define IS_COMMENT(c)                   (lex[c] == LEX_IS_COMMENT_START)
#define IS_LINE_COMMENT(c)              (lex[c] == LEX_IS_LINE_COMMENT_START)
#define IS_LINE_COMMENT(c)              (lex[c] == LEX_IS_LINE_COMMENT_START)
#define IS_NEWLINE(c)                   (lex[c] == LEX_IS_NEWLINE)
#define IS_NEWLINE(c)                   (lex[c] == LEX_IS_NEWLINE)
 
 
static int process_escape (int);
static int process_escape (int);
 
 
/* FIXME-soon: The entire lexer/parser thingy should be
/* FIXME-soon: The entire lexer/parser thingy should be
   built statically at compile time rather than dynamically
   built statically at compile time rather than dynamically
   each and every time the assembler is run.  xoxorich.  */
   each and every time the assembler is run.  xoxorich.  */
 
 
void
void
do_scrub_begin (int m68k_mri ATTRIBUTE_UNUSED)
do_scrub_begin (int m68k_mri ATTRIBUTE_UNUSED)
{
{
  const char *p;
  const char *p;
  int c;
  int c;
 
 
  lex[' '] = LEX_IS_WHITESPACE;
  lex[' '] = LEX_IS_WHITESPACE;
  lex['\t'] = LEX_IS_WHITESPACE;
  lex['\t'] = LEX_IS_WHITESPACE;
  lex['\r'] = LEX_IS_WHITESPACE;
  lex['\r'] = LEX_IS_WHITESPACE;
  lex['\n'] = LEX_IS_NEWLINE;
  lex['\n'] = LEX_IS_NEWLINE;
  lex[':'] = LEX_IS_COLON;
  lex[':'] = LEX_IS_COLON;
 
 
#ifdef TC_M68K
#ifdef TC_M68K
  scrub_m68k_mri = m68k_mri;
  scrub_m68k_mri = m68k_mri;
 
 
  if (! m68k_mri)
  if (! m68k_mri)
#endif
#endif
    {
    {
      lex['"'] = LEX_IS_STRINGQUOTE;
      lex['"'] = LEX_IS_STRINGQUOTE;
 
 
#if ! defined (TC_HPPA) && ! defined (TC_I370)
#if ! defined (TC_HPPA) && ! defined (TC_I370)
      /* I370 uses single-quotes to delimit integer, float constants.  */
      /* I370 uses single-quotes to delimit integer, float constants.  */
      lex['\''] = LEX_IS_ONECHAR_QUOTE;
      lex['\''] = LEX_IS_ONECHAR_QUOTE;
#endif
#endif
 
 
#ifdef SINGLE_QUOTE_STRINGS
#ifdef SINGLE_QUOTE_STRINGS
      lex['\''] = LEX_IS_STRINGQUOTE;
      lex['\''] = LEX_IS_STRINGQUOTE;
#endif
#endif
    }
    }
 
 
  /* Note: if any other character can be LEX_IS_STRINGQUOTE, the loop
  /* Note: if any other character can be LEX_IS_STRINGQUOTE, the loop
     in state 5 of do_scrub_chars must be changed.  */
     in state 5 of do_scrub_chars must be changed.  */
 
 
  /* Note that these override the previous defaults, e.g. if ';' is a
  /* Note that these override the previous defaults, e.g. if ';' is a
     comment char, then it isn't a line separator.  */
     comment char, then it isn't a line separator.  */
  for (p = symbol_chars; *p; ++p)
  for (p = symbol_chars; *p; ++p)
    lex[(unsigned char) *p] = LEX_IS_SYMBOL_COMPONENT;
    lex[(unsigned char) *p] = LEX_IS_SYMBOL_COMPONENT;
 
 
  for (c = 128; c < 256; ++c)
  for (c = 128; c < 256; ++c)
    lex[c] = LEX_IS_SYMBOL_COMPONENT;
    lex[c] = LEX_IS_SYMBOL_COMPONENT;
 
 
#ifdef tc_symbol_chars
#ifdef tc_symbol_chars
  /* This macro permits the processor to specify all characters which
  /* This macro permits the processor to specify all characters which
     may appears in an operand.  This will prevent the scrubber from
     may appears in an operand.  This will prevent the scrubber from
     discarding meaningful whitespace in certain cases.  The i386
     discarding meaningful whitespace in certain cases.  The i386
     backend uses this to support prefixes, which can confuse the
     backend uses this to support prefixes, which can confuse the
     scrubber as to whether it is parsing operands or opcodes.  */
     scrubber as to whether it is parsing operands or opcodes.  */
  for (p = tc_symbol_chars; *p; ++p)
  for (p = tc_symbol_chars; *p; ++p)
    lex[(unsigned char) *p] = LEX_IS_SYMBOL_COMPONENT;
    lex[(unsigned char) *p] = LEX_IS_SYMBOL_COMPONENT;
#endif
#endif
 
 
  /* The m68k backend wants to be able to change comment_chars.  */
  /* The m68k backend wants to be able to change comment_chars.  */
#ifndef tc_comment_chars
#ifndef tc_comment_chars
#define tc_comment_chars comment_chars
#define tc_comment_chars comment_chars
#endif
#endif
  for (p = tc_comment_chars; *p; p++)
  for (p = tc_comment_chars; *p; p++)
    lex[(unsigned char) *p] = LEX_IS_COMMENT_START;
    lex[(unsigned char) *p] = LEX_IS_COMMENT_START;
 
 
  for (p = line_comment_chars; *p; p++)
  for (p = line_comment_chars; *p; p++)
    lex[(unsigned char) *p] = LEX_IS_LINE_COMMENT_START;
    lex[(unsigned char) *p] = LEX_IS_LINE_COMMENT_START;
 
 
  for (p = line_separator_chars; *p; p++)
  for (p = line_separator_chars; *p; p++)
    lex[(unsigned char) *p] = LEX_IS_LINE_SEPARATOR;
    lex[(unsigned char) *p] = LEX_IS_LINE_SEPARATOR;
 
 
#ifdef tc_parallel_separator_chars
#ifdef tc_parallel_separator_chars
  /* This macro permits the processor to specify all characters which
  /* This macro permits the processor to specify all characters which
     separate parallel insns on the same line.  */
     separate parallel insns on the same line.  */
  for (p = tc_parallel_separator_chars; *p; p++)
  for (p = tc_parallel_separator_chars; *p; p++)
    lex[(unsigned char) *p] = LEX_IS_PARALLEL_SEPARATOR;
    lex[(unsigned char) *p] = LEX_IS_PARALLEL_SEPARATOR;
#endif
#endif
 
 
  /* Only allow slash-star comments if slash is not in use.
  /* Only allow slash-star comments if slash is not in use.
     FIXME: This isn't right.  We should always permit them.  */
     FIXME: This isn't right.  We should always permit them.  */
  if (lex['/'] == 0)
  if (lex['/'] == 0)
    lex['/'] = LEX_IS_TWOCHAR_COMMENT_1ST;
    lex['/'] = LEX_IS_TWOCHAR_COMMENT_1ST;
 
 
#ifdef TC_M68K
#ifdef TC_M68K
  if (m68k_mri)
  if (m68k_mri)
    {
    {
      lex['\''] = LEX_IS_STRINGQUOTE;
      lex['\''] = LEX_IS_STRINGQUOTE;
      lex[';'] = LEX_IS_COMMENT_START;
      lex[';'] = LEX_IS_COMMENT_START;
      lex['*'] = LEX_IS_LINE_COMMENT_START;
      lex['*'] = LEX_IS_LINE_COMMENT_START;
      /* The MRI documentation says '!' is LEX_IS_COMMENT_START, but
      /* The MRI documentation says '!' is LEX_IS_COMMENT_START, but
         then it can't be used in an expression.  */
         then it can't be used in an expression.  */
      lex['!'] = LEX_IS_LINE_COMMENT_START;
      lex['!'] = LEX_IS_LINE_COMMENT_START;
    }
    }
#endif
#endif
 
 
#ifdef TC_V850
#ifdef TC_V850
  lex['-'] = LEX_IS_DOUBLEDASH_1ST;
  lex['-'] = LEX_IS_DOUBLEDASH_1ST;
#endif
#endif
#ifdef DOUBLEBAR_PARALLEL
#ifdef DOUBLEBAR_PARALLEL
  lex['|'] = LEX_IS_DOUBLEBAR_1ST;
  lex['|'] = LEX_IS_DOUBLEBAR_1ST;
#endif
#endif
#ifdef TC_D30V
#ifdef TC_D30V
  /* Must do this is we want VLIW instruction with "->" or "<-".  */
  /* Must do this is we want VLIW instruction with "->" or "<-".  */
  lex['-'] = LEX_IS_SYMBOL_COMPONENT;
  lex['-'] = LEX_IS_SYMBOL_COMPONENT;
#endif
#endif
}
}
 
 
/* Saved state of the scrubber.  */
/* Saved state of the scrubber.  */
static int state;
static int state;
static int old_state;
static int old_state;
static char *out_string;
static char *out_string;
static char out_buf[20];
static char out_buf[20];
static int add_newlines;
static int add_newlines;
static char *saved_input;
static char *saved_input;
static int saved_input_len;
static int saved_input_len;
static char input_buffer[32 * 1024];
static char input_buffer[32 * 1024];
static const char *mri_state;
static const char *mri_state;
static char mri_last_ch;
static char mri_last_ch;
 
 
/* Data structure for saving the state of app across #include's.  Note that
/* Data structure for saving the state of app across #include's.  Note that
   app is called asynchronously to the parsing of the .include's, so our
   app is called asynchronously to the parsing of the .include's, so our
   state at the time .include is interpreted is completely unrelated.
   state at the time .include is interpreted is completely unrelated.
   That's why we have to save it all.  */
   That's why we have to save it all.  */
 
 
struct app_save
struct app_save
{
{
  int          state;
  int          state;
  int          old_state;
  int          old_state;
  char *       out_string;
  char *       out_string;
  char         out_buf[sizeof (out_buf)];
  char         out_buf[sizeof (out_buf)];
  int          add_newlines;
  int          add_newlines;
  char *       saved_input;
  char *       saved_input;
  int          saved_input_len;
  int          saved_input_len;
#ifdef TC_M68K
#ifdef TC_M68K
  int          scrub_m68k_mri;
  int          scrub_m68k_mri;
#endif
#endif
  const char * mri_state;
  const char * mri_state;
  char         mri_last_ch;
  char         mri_last_ch;
#if defined TC_ARM && defined OBJ_ELF
#if defined TC_ARM && defined OBJ_ELF
  const char * symver_state;
  const char * symver_state;
#endif
#endif
};
};
 
 
char *
char *
app_push (void)
app_push (void)
{
{
  register struct app_save *saved;
  register struct app_save *saved;
 
 
  saved = (struct app_save *) xmalloc (sizeof (*saved));
  saved = (struct app_save *) xmalloc (sizeof (*saved));
  saved->state = state;
  saved->state = state;
  saved->old_state = old_state;
  saved->old_state = old_state;
  saved->out_string = out_string;
  saved->out_string = out_string;
  memcpy (saved->out_buf, out_buf, sizeof (out_buf));
  memcpy (saved->out_buf, out_buf, sizeof (out_buf));
  saved->add_newlines = add_newlines;
  saved->add_newlines = add_newlines;
  if (saved_input == NULL)
  if (saved_input == NULL)
    saved->saved_input = NULL;
    saved->saved_input = NULL;
  else
  else
    {
    {
      saved->saved_input = xmalloc (saved_input_len);
      saved->saved_input = xmalloc (saved_input_len);
      memcpy (saved->saved_input, saved_input, saved_input_len);
      memcpy (saved->saved_input, saved_input, saved_input_len);
      saved->saved_input_len = saved_input_len;
      saved->saved_input_len = saved_input_len;
    }
    }
#ifdef TC_M68K
#ifdef TC_M68K
  saved->scrub_m68k_mri = scrub_m68k_mri;
  saved->scrub_m68k_mri = scrub_m68k_mri;
#endif
#endif
  saved->mri_state = mri_state;
  saved->mri_state = mri_state;
  saved->mri_last_ch = mri_last_ch;
  saved->mri_last_ch = mri_last_ch;
#if defined TC_ARM && defined OBJ_ELF
#if defined TC_ARM && defined OBJ_ELF
  saved->symver_state = symver_state;
  saved->symver_state = symver_state;
#endif
#endif
 
 
  /* do_scrub_begin() is not useful, just wastes time.  */
  /* do_scrub_begin() is not useful, just wastes time.  */
 
 
  state = 0;
  state = 0;
  saved_input = NULL;
  saved_input = NULL;
 
 
  return (char *) saved;
  return (char *) saved;
}
}
 
 
void
void
app_pop (char *arg)
app_pop (char *arg)
{
{
  register struct app_save *saved = (struct app_save *) arg;
  register struct app_save *saved = (struct app_save *) arg;
 
 
  /* There is no do_scrub_end ().  */
  /* There is no do_scrub_end ().  */
  state = saved->state;
  state = saved->state;
  old_state = saved->old_state;
  old_state = saved->old_state;
  out_string = saved->out_string;
  out_string = saved->out_string;
  memcpy (out_buf, saved->out_buf, sizeof (out_buf));
  memcpy (out_buf, saved->out_buf, sizeof (out_buf));
  add_newlines = saved->add_newlines;
  add_newlines = saved->add_newlines;
  if (saved->saved_input == NULL)
  if (saved->saved_input == NULL)
    saved_input = NULL;
    saved_input = NULL;
  else
  else
    {
    {
      assert (saved->saved_input_len <= (int) (sizeof input_buffer));
      assert (saved->saved_input_len <= (int) (sizeof input_buffer));
      memcpy (input_buffer, saved->saved_input, saved->saved_input_len);
      memcpy (input_buffer, saved->saved_input, saved->saved_input_len);
      saved_input = input_buffer;
      saved_input = input_buffer;
      saved_input_len = saved->saved_input_len;
      saved_input_len = saved->saved_input_len;
      free (saved->saved_input);
      free (saved->saved_input);
    }
    }
#ifdef TC_M68K
#ifdef TC_M68K
  scrub_m68k_mri = saved->scrub_m68k_mri;
  scrub_m68k_mri = saved->scrub_m68k_mri;
#endif
#endif
  mri_state = saved->mri_state;
  mri_state = saved->mri_state;
  mri_last_ch = saved->mri_last_ch;
  mri_last_ch = saved->mri_last_ch;
#if defined TC_ARM && defined OBJ_ELF
#if defined TC_ARM && defined OBJ_ELF
  symver_state = saved->symver_state;
  symver_state = saved->symver_state;
#endif
#endif
 
 
  free (arg);
  free (arg);
}
}
 
 
/* @@ This assumes that \n &c are the same on host and target.  This is not
/* @@ This assumes that \n &c are the same on host and target.  This is not
   necessarily true.  */
   necessarily true.  */
 
 
static int
static int
process_escape (int ch)
process_escape (int ch)
{
{
  switch (ch)
  switch (ch)
    {
    {
    case 'b':
    case 'b':
      return '\b';
      return '\b';
    case 'f':
    case 'f':
      return '\f';
      return '\f';
    case 'n':
    case 'n':
      return '\n';
      return '\n';
    case 'r':
    case 'r':
      return '\r';
      return '\r';
    case 't':
    case 't':
      return '\t';
      return '\t';
    case '\'':
    case '\'':
      return '\'';
      return '\'';
    case '"':
    case '"':
      return '\"';
      return '\"';
    default:
    default:
      return ch;
      return ch;
    }
    }
}
}
 
 
/* This function is called to process input characters.  The GET
/* This function is called to process input characters.  The GET
   parameter is used to retrieve more input characters.  GET should
   parameter is used to retrieve more input characters.  GET should
   set its parameter to point to a buffer, and return the length of
   set its parameter to point to a buffer, and return the length of
   the buffer; it should return 0 at end of file.  The scrubbed output
   the buffer; it should return 0 at end of file.  The scrubbed output
   characters are put into the buffer starting at TOSTART; the TOSTART
   characters are put into the buffer starting at TOSTART; the TOSTART
   buffer is TOLEN bytes in length.  The function returns the number
   buffer is TOLEN bytes in length.  The function returns the number
   of scrubbed characters put into TOSTART.  This will be TOLEN unless
   of scrubbed characters put into TOSTART.  This will be TOLEN unless
   end of file was seen.  This function is arranged as a state
   end of file was seen.  This function is arranged as a state
   machine, and saves its state so that it may return at any point.
   machine, and saves its state so that it may return at any point.
   This is the way the old code used to work.  */
   This is the way the old code used to work.  */
 
 
int
int
do_scrub_chars (int (*get) (char *, int), char *tostart, int tolen)
do_scrub_chars (int (*get) (char *, int), char *tostart, int tolen)
{
{
  char *to = tostart;
  char *to = tostart;
  char *toend = tostart + tolen;
  char *toend = tostart + tolen;
  char *from;
  char *from;
  char *fromend;
  char *fromend;
  int fromlen;
  int fromlen;
  register int ch, ch2 = 0;
  register int ch, ch2 = 0;
  /* Character that started the string we're working on.  */
  /* Character that started the string we're working on.  */
  static char quotechar;
  static char quotechar;
 
 
  /*State 0: beginning of normal line
  /*State 0: beginning of normal line
          1: After first whitespace on line (flush more white)
          1: After first whitespace on line (flush more white)
          2: After first non-white (opcode) on line (keep 1white)
          2: After first non-white (opcode) on line (keep 1white)
          3: after second white on line (into operands) (flush white)
          3: after second white on line (into operands) (flush white)
          4: after putting out a .linefile, put out digits
          4: after putting out a .linefile, put out digits
          5: parsing a string, then go to old-state
          5: parsing a string, then go to old-state
          6: putting out \ escape in a "d string.
          6: putting out \ escape in a "d string.
          7: no longer used
          7: no longer used
          8: no longer used
          8: no longer used
          9: After seeing symbol char in state 3 (keep 1white after symchar)
          9: After seeing symbol char in state 3 (keep 1white after symchar)
         10: After seeing whitespace in state 9 (keep white before symchar)
         10: After seeing whitespace in state 9 (keep white before symchar)
         11: After seeing a symbol character in state 0 (eg a label definition)
         11: After seeing a symbol character in state 0 (eg a label definition)
         -1: output string in out_string and go to the state in old_state
         -1: output string in out_string and go to the state in old_state
         -2: flush text until a '*' '/' is seen, then go to state old_state
         -2: flush text until a '*' '/' is seen, then go to state old_state
#ifdef TC_V850
#ifdef TC_V850
         12: After seeing a dash, looking for a second dash as a start
         12: After seeing a dash, looking for a second dash as a start
             of comment.
             of comment.
#endif
#endif
#ifdef DOUBLEBAR_PARALLEL
#ifdef DOUBLEBAR_PARALLEL
         13: After seeing a vertical bar, looking for a second
         13: After seeing a vertical bar, looking for a second
             vertical bar as a parallel expression separator.
             vertical bar as a parallel expression separator.
#endif
#endif
#ifdef TC_IA64
#ifdef TC_IA64
         14: After seeing a `(' at state 0, looking for a `)' as
         14: After seeing a `(' at state 0, looking for a `)' as
             predicate.
             predicate.
         15: After seeing a `(' at state 1, looking for a `)' as
         15: After seeing a `(' at state 1, looking for a `)' as
             predicate.
             predicate.
#endif
#endif
#ifdef TC_Z80
#ifdef TC_Z80
         16: After seeing an 'a' or an 'A' at the start of a symbol
         16: After seeing an 'a' or an 'A' at the start of a symbol
         17: After seeing an 'f' or an 'F' in state 16
         17: After seeing an 'f' or an 'F' in state 16
#endif
#endif
          */
          */
 
 
  /* I added states 9 and 10 because the MIPS ECOFF assembler uses
  /* I added states 9 and 10 because the MIPS ECOFF assembler uses
     constructs like ``.loc 1 20''.  This was turning into ``.loc
     constructs like ``.loc 1 20''.  This was turning into ``.loc
     120''.  States 9 and 10 ensure that a space is never dropped in
     120''.  States 9 and 10 ensure that a space is never dropped in
     between characters which could appear in an identifier.  Ian
     between characters which could appear in an identifier.  Ian
     Taylor, ian@cygnus.com.
     Taylor, ian@cygnus.com.
 
 
     I added state 11 so that something like "Lfoo add %r25,%r26,%r27" works
     I added state 11 so that something like "Lfoo add %r25,%r26,%r27" works
     correctly on the PA (and any other target where colons are optional).
     correctly on the PA (and any other target where colons are optional).
     Jeff Law, law@cs.utah.edu.
     Jeff Law, law@cs.utah.edu.
 
 
     I added state 13 so that something like "cmp r1, r2 || trap #1" does not
     I added state 13 so that something like "cmp r1, r2 || trap #1" does not
     get squashed into "cmp r1,r2||trap#1", with the all important space
     get squashed into "cmp r1,r2||trap#1", with the all important space
     between the 'trap' and the '#1' being eliminated.  nickc@cygnus.com  */
     between the 'trap' and the '#1' being eliminated.  nickc@cygnus.com  */
 
 
  /* This macro gets the next input character.  */
  /* This macro gets the next input character.  */
 
 
#define GET()                                                   \
#define GET()                                                   \
  (from < fromend                                               \
  (from < fromend                                               \
   ? * (unsigned char *) (from++)                               \
   ? * (unsigned char *) (from++)                               \
   : (saved_input = NULL,                                       \
   : (saved_input = NULL,                                       \
      fromlen = (*get) (input_buffer, sizeof input_buffer),     \
      fromlen = (*get) (input_buffer, sizeof input_buffer),     \
      from = input_buffer,                                      \
      from = input_buffer,                                      \
      fromend = from + fromlen,                                 \
      fromend = from + fromlen,                                 \
      (fromlen == 0                                              \
      (fromlen == 0                                              \
       ? EOF                                                    \
       ? EOF                                                    \
       : * (unsigned char *) (from++))))
       : * (unsigned char *) (from++))))
 
 
  /* This macro pushes a character back on the input stream.  */
  /* This macro pushes a character back on the input stream.  */
 
 
#define UNGET(uch) (*--from = (uch))
#define UNGET(uch) (*--from = (uch))
 
 
  /* This macro puts a character into the output buffer.  If this
  /* This macro puts a character into the output buffer.  If this
     character fills the output buffer, this macro jumps to the label
     character fills the output buffer, this macro jumps to the label
     TOFULL.  We use this rather ugly approach because we need to
     TOFULL.  We use this rather ugly approach because we need to
     handle two different termination conditions: EOF on the input
     handle two different termination conditions: EOF on the input
     stream, and a full output buffer.  It would be simpler if we
     stream, and a full output buffer.  It would be simpler if we
     always read in the entire input stream before processing it, but
     always read in the entire input stream before processing it, but
     I don't want to make such a significant change to the assembler's
     I don't want to make such a significant change to the assembler's
     memory usage.  */
     memory usage.  */
 
 
#define PUT(pch)                                \
#define PUT(pch)                                \
  do                                            \
  do                                            \
    {                                           \
    {                                           \
      *to++ = (pch);                            \
      *to++ = (pch);                            \
      if (to >= toend)                          \
      if (to >= toend)                          \
        goto tofull;                            \
        goto tofull;                            \
    }                                           \
    }                                           \
  while (0)
  while (0)
 
 
  if (saved_input != NULL)
  if (saved_input != NULL)
    {
    {
      from = saved_input;
      from = saved_input;
      fromend = from + saved_input_len;
      fromend = from + saved_input_len;
    }
    }
  else
  else
    {
    {
      fromlen = (*get) (input_buffer, sizeof input_buffer);
      fromlen = (*get) (input_buffer, sizeof input_buffer);
      if (fromlen == 0)
      if (fromlen == 0)
        return 0;
        return 0;
      from = input_buffer;
      from = input_buffer;
      fromend = from + fromlen;
      fromend = from + fromlen;
    }
    }
 
 
  while (1)
  while (1)
    {
    {
      /* The cases in this switch end with continue, in order to
      /* The cases in this switch end with continue, in order to
         branch back to the top of this while loop and generate the
         branch back to the top of this while loop and generate the
         next output character in the appropriate state.  */
         next output character in the appropriate state.  */
      switch (state)
      switch (state)
        {
        {
        case -1:
        case -1:
          ch = *out_string++;
          ch = *out_string++;
          if (*out_string == '\0')
          if (*out_string == '\0')
            {
            {
              state = old_state;
              state = old_state;
              old_state = 3;
              old_state = 3;
            }
            }
          PUT (ch);
          PUT (ch);
          continue;
          continue;
 
 
        case -2:
        case -2:
          for (;;)
          for (;;)
            {
            {
              do
              do
                {
                {
                  ch = GET ();
                  ch = GET ();
 
 
                  if (ch == EOF)
                  if (ch == EOF)
                    {
                    {
                      as_warn (_("end of file in comment"));
                      as_warn (_("end of file in comment"));
                      goto fromeof;
                      goto fromeof;
                    }
                    }
 
 
                  if (ch == '\n')
                  if (ch == '\n')
                    PUT ('\n');
                    PUT ('\n');
                }
                }
              while (ch != '*');
              while (ch != '*');
 
 
              while ((ch = GET ()) == '*')
              while ((ch = GET ()) == '*')
                ;
                ;
 
 
              if (ch == EOF)
              if (ch == EOF)
                {
                {
                  as_warn (_("end of file in comment"));
                  as_warn (_("end of file in comment"));
                  goto fromeof;
                  goto fromeof;
                }
                }
 
 
              if (ch == '/')
              if (ch == '/')
                break;
                break;
 
 
              UNGET (ch);
              UNGET (ch);
            }
            }
 
 
          state = old_state;
          state = old_state;
          UNGET (' ');
          UNGET (' ');
          continue;
          continue;
 
 
        case 4:
        case 4:
          ch = GET ();
          ch = GET ();
          if (ch == EOF)
          if (ch == EOF)
            goto fromeof;
            goto fromeof;
          else if (ch >= '0' && ch <= '9')
          else if (ch >= '0' && ch <= '9')
            PUT (ch);
            PUT (ch);
          else
          else
            {
            {
              while (ch != EOF && IS_WHITESPACE (ch))
              while (ch != EOF && IS_WHITESPACE (ch))
                ch = GET ();
                ch = GET ();
              if (ch == '"')
              if (ch == '"')
                {
                {
                  quotechar = ch;
                  quotechar = ch;
                  state = 5;
                  state = 5;
                  old_state = 3;
                  old_state = 3;
                  PUT (ch);
                  PUT (ch);
                }
                }
              else
              else
                {
                {
                  while (ch != EOF && ch != '\n')
                  while (ch != EOF && ch != '\n')
                    ch = GET ();
                    ch = GET ();
                  state = 0;
                  state = 0;
                  PUT (ch);
                  PUT (ch);
                }
                }
            }
            }
          continue;
          continue;
 
 
        case 5:
        case 5:
          /* We are going to copy everything up to a quote character,
          /* We are going to copy everything up to a quote character,
             with special handling for a backslash.  We try to
             with special handling for a backslash.  We try to
             optimize the copying in the simple case without using the
             optimize the copying in the simple case without using the
             GET and PUT macros.  */
             GET and PUT macros.  */
          {
          {
            char *s;
            char *s;
            int len;
            int len;
 
 
            for (s = from; s < fromend; s++)
            for (s = from; s < fromend; s++)
              {
              {
                ch = *s;
                ch = *s;
                if (ch == '\\'
                if (ch == '\\'
                    || ch == quotechar
                    || ch == quotechar
                    || ch == '\n')
                    || ch == '\n')
                  break;
                  break;
              }
              }
            len = s - from;
            len = s - from;
            if (len > toend - to)
            if (len > toend - to)
              len = toend - to;
              len = toend - to;
            if (len > 0)
            if (len > 0)
              {
              {
                memcpy (to, from, len);
                memcpy (to, from, len);
                to += len;
                to += len;
                from += len;
                from += len;
                if (to >= toend)
                if (to >= toend)
                  goto tofull;
                  goto tofull;
              }
              }
          }
          }
 
 
          ch = GET ();
          ch = GET ();
          if (ch == EOF)
          if (ch == EOF)
            {
            {
              /* This buffer is here specifically so
              /* This buffer is here specifically so
                 that the UNGET below will work.  */
                 that the UNGET below will work.  */
              static char one_char_buf[1];
              static char one_char_buf[1];
 
 
              as_warn (_("end of file in string; '%c' inserted"), quotechar);
              as_warn (_("end of file in string; '%c' inserted"), quotechar);
              state = old_state;
              state = old_state;
              from = fromend = one_char_buf + 1;
              from = fromend = one_char_buf + 1;
              fromlen = 1;
              fromlen = 1;
              UNGET ('\n');
              UNGET ('\n');
              PUT (quotechar);
              PUT (quotechar);
            }
            }
          else if (ch == quotechar)
          else if (ch == quotechar)
            {
            {
              state = old_state;
              state = old_state;
              PUT (ch);
              PUT (ch);
            }
            }
#ifndef NO_STRING_ESCAPES
#ifndef NO_STRING_ESCAPES
          else if (ch == '\\')
          else if (ch == '\\')
            {
            {
              state = 6;
              state = 6;
              PUT (ch);
              PUT (ch);
            }
            }
#endif
#endif
          else if (scrub_m68k_mri && ch == '\n')
          else if (scrub_m68k_mri && ch == '\n')
            {
            {
              /* Just quietly terminate the string.  This permits lines like
              /* Just quietly terminate the string.  This permits lines like
                   bne  label   loop if we haven't reach end yet.  */
                   bne  label   loop if we haven't reach end yet.  */
              state = old_state;
              state = old_state;
              UNGET (ch);
              UNGET (ch);
              PUT ('\'');
              PUT ('\'');
            }
            }
          else
          else
            {
            {
              PUT (ch);
              PUT (ch);
            }
            }
          continue;
          continue;
 
 
        case 6:
        case 6:
          state = 5;
          state = 5;
          ch = GET ();
          ch = GET ();
          switch (ch)
          switch (ch)
            {
            {
              /* Handle strings broken across lines, by turning '\n' into
              /* Handle strings broken across lines, by turning '\n' into
                 '\\' and 'n'.  */
                 '\\' and 'n'.  */
            case '\n':
            case '\n':
              UNGET ('n');
              UNGET ('n');
              add_newlines++;
              add_newlines++;
              PUT ('\\');
              PUT ('\\');
              continue;
              continue;
 
 
            case EOF:
            case EOF:
              as_warn (_("end of file in string; '%c' inserted"), quotechar);
              as_warn (_("end of file in string; '%c' inserted"), quotechar);
              PUT (quotechar);
              PUT (quotechar);
              continue;
              continue;
 
 
            case '"':
            case '"':
            case '\\':
            case '\\':
            case 'b':
            case 'b':
            case 'f':
            case 'f':
            case 'n':
            case 'n':
            case 'r':
            case 'r':
            case 't':
            case 't':
            case 'v':
            case 'v':
            case 'x':
            case 'x':
            case 'X':
            case 'X':
            case '0':
            case '0':
            case '1':
            case '1':
            case '2':
            case '2':
            case '3':
            case '3':
            case '4':
            case '4':
            case '5':
            case '5':
            case '6':
            case '6':
            case '7':
            case '7':
              break;
              break;
 
 
            default:
            default:
#ifdef ONLY_STANDARD_ESCAPES
#ifdef ONLY_STANDARD_ESCAPES
              as_warn (_("unknown escape '\\%c' in string; ignored"), ch);
              as_warn (_("unknown escape '\\%c' in string; ignored"), ch);
#endif
#endif
              break;
              break;
            }
            }
          PUT (ch);
          PUT (ch);
          continue;
          continue;
 
 
#ifdef DOUBLEBAR_PARALLEL
#ifdef DOUBLEBAR_PARALLEL
        case 13:
        case 13:
          ch = GET ();
          ch = GET ();
          if (ch != '|')
          if (ch != '|')
            abort ();
            abort ();
 
 
          /* Reset back to state 1 and pretend that we are parsing a
          /* Reset back to state 1 and pretend that we are parsing a
             line from just after the first white space.  */
             line from just after the first white space.  */
          state = 1;
          state = 1;
          PUT ('|');
          PUT ('|');
          continue;
          continue;
#endif
#endif
#ifdef TC_Z80
#ifdef TC_Z80
        case 16:
        case 16:
          /* We have seen an 'a' at the start of a symbol, look for an 'f'.  */
          /* We have seen an 'a' at the start of a symbol, look for an 'f'.  */
          ch = GET ();
          ch = GET ();
          if (ch == 'f' || ch == 'F')
          if (ch == 'f' || ch == 'F')
            {
            {
              state = 17;
              state = 17;
              PUT (ch);
              PUT (ch);
            }
            }
          else
          else
            {
            {
              state = 9;
              state = 9;
              break;
              break;
            }
            }
        case 17:
        case 17:
          /* We have seen "af" at the start of a symbol,
          /* We have seen "af" at the start of a symbol,
             a ' here is a part of that symbol.  */
             a ' here is a part of that symbol.  */
          ch = GET ();
          ch = GET ();
          state = 9;
          state = 9;
          if (ch == '\'')
          if (ch == '\'')
            /* Change to avoid warning about unclosed string.  */
            /* Change to avoid warning about unclosed string.  */
            PUT ('`');
            PUT ('`');
          else
          else
            UNGET (ch);
            UNGET (ch);
          break;
          break;
#endif
#endif
        }
        }
 
 
      /* OK, we are somewhere in states 0 through 4 or 9 through 11.  */
      /* OK, we are somewhere in states 0 through 4 or 9 through 11.  */
 
 
      /* flushchar: */
      /* flushchar: */
      ch = GET ();
      ch = GET ();
 
 
#ifdef TC_IA64
#ifdef TC_IA64
      if (ch == '(' && (state == 0 || state == 1))
      if (ch == '(' && (state == 0 || state == 1))
        {
        {
          state += 14;
          state += 14;
          PUT (ch);
          PUT (ch);
          continue;
          continue;
        }
        }
      else if (state == 14 || state == 15)
      else if (state == 14 || state == 15)
        {
        {
          if (ch == ')')
          if (ch == ')')
            {
            {
              state -= 14;
              state -= 14;
              PUT (ch);
              PUT (ch);
              ch = GET ();
              ch = GET ();
            }
            }
          else
          else
            {
            {
              PUT (ch);
              PUT (ch);
              continue;
              continue;
            }
            }
        }
        }
#endif
#endif
 
 
    recycle:
    recycle:
 
 
#if defined TC_ARM && defined OBJ_ELF
#if defined TC_ARM && defined OBJ_ELF
      /* We need to watch out for .symver directives.  See the comment later
      /* We need to watch out for .symver directives.  See the comment later
         in this function.  */
         in this function.  */
      if (symver_state == NULL)
      if (symver_state == NULL)
        {
        {
          if ((state == 0 || state == 1) && ch == symver_pseudo[0])
          if ((state == 0 || state == 1) && ch == symver_pseudo[0])
            symver_state = symver_pseudo + 1;
            symver_state = symver_pseudo + 1;
        }
        }
      else
      else
        {
        {
          /* We advance to the next state if we find the right
          /* We advance to the next state if we find the right
             character.  */
             character.  */
          if (ch != '\0' && (*symver_state == ch))
          if (ch != '\0' && (*symver_state == ch))
            ++symver_state;
            ++symver_state;
          else if (*symver_state != '\0')
          else if (*symver_state != '\0')
            /* We did not get the expected character, or we didn't
            /* We did not get the expected character, or we didn't
               get a valid terminating character after seeing the
               get a valid terminating character after seeing the
               entire pseudo-op, so we must go back to the beginning.  */
               entire pseudo-op, so we must go back to the beginning.  */
            symver_state = NULL;
            symver_state = NULL;
          else
          else
            {
            {
              /* We've read the entire pseudo-op.  If this is the end
              /* We've read the entire pseudo-op.  If this is the end
                 of the line, go back to the beginning.  */
                 of the line, go back to the beginning.  */
              if (IS_NEWLINE (ch))
              if (IS_NEWLINE (ch))
                symver_state = NULL;
                symver_state = NULL;
            }
            }
        }
        }
#endif /* TC_ARM && OBJ_ELF */
#endif /* TC_ARM && OBJ_ELF */
 
 
#ifdef TC_M68K
#ifdef TC_M68K
      /* We want to have pseudo-ops which control whether we are in
      /* We want to have pseudo-ops which control whether we are in
         MRI mode or not.  Unfortunately, since m68k MRI mode affects
         MRI mode or not.  Unfortunately, since m68k MRI mode affects
         the scrubber, that means that we need a special purpose
         the scrubber, that means that we need a special purpose
         recognizer here.  */
         recognizer here.  */
      if (mri_state == NULL)
      if (mri_state == NULL)
        {
        {
          if ((state == 0 || state == 1)
          if ((state == 0 || state == 1)
              && ch == mri_pseudo[0])
              && ch == mri_pseudo[0])
            mri_state = mri_pseudo + 1;
            mri_state = mri_pseudo + 1;
        }
        }
      else
      else
        {
        {
          /* We advance to the next state if we find the right
          /* We advance to the next state if we find the right
             character, or if we need a space character and we get any
             character, or if we need a space character and we get any
             whitespace character, or if we need a '0' and we get a
             whitespace character, or if we need a '0' and we get a
             '1' (this is so that we only need one state to handle
             '1' (this is so that we only need one state to handle
             ``.mri 0'' and ``.mri 1'').  */
             ``.mri 0'' and ``.mri 1'').  */
          if (ch != '\0'
          if (ch != '\0'
              && (*mri_state == ch
              && (*mri_state == ch
                  || (*mri_state == ' '
                  || (*mri_state == ' '
                      && lex[ch] == LEX_IS_WHITESPACE)
                      && lex[ch] == LEX_IS_WHITESPACE)
                  || (*mri_state == '0'
                  || (*mri_state == '0'
                      && ch == '1')))
                      && ch == '1')))
            {
            {
              mri_last_ch = ch;
              mri_last_ch = ch;
              ++mri_state;
              ++mri_state;
            }
            }
          else if (*mri_state != '\0'
          else if (*mri_state != '\0'
                   || (lex[ch] != LEX_IS_WHITESPACE
                   || (lex[ch] != LEX_IS_WHITESPACE
                       && lex[ch] != LEX_IS_NEWLINE))
                       && lex[ch] != LEX_IS_NEWLINE))
            {
            {
              /* We did not get the expected character, or we didn't
              /* We did not get the expected character, or we didn't
                 get a valid terminating character after seeing the
                 get a valid terminating character after seeing the
                 entire pseudo-op, so we must go back to the
                 entire pseudo-op, so we must go back to the
                 beginning.  */
                 beginning.  */
              mri_state = NULL;
              mri_state = NULL;
            }
            }
          else
          else
            {
            {
              /* We've read the entire pseudo-op.  mips_last_ch is
              /* We've read the entire pseudo-op.  mips_last_ch is
                 either '0' or '1' indicating whether to enter or
                 either '0' or '1' indicating whether to enter or
                 leave MRI mode.  */
                 leave MRI mode.  */
              do_scrub_begin (mri_last_ch == '1');
              do_scrub_begin (mri_last_ch == '1');
              mri_state = NULL;
              mri_state = NULL;
 
 
              /* We continue handling the character as usual.  The
              /* We continue handling the character as usual.  The
                 main gas reader must also handle the .mri pseudo-op
                 main gas reader must also handle the .mri pseudo-op
                 to control expression parsing and the like.  */
                 to control expression parsing and the like.  */
            }
            }
        }
        }
#endif
#endif
 
 
      if (ch == EOF)
      if (ch == EOF)
        {
        {
          if (state != 0)
          if (state != 0)
            {
            {
              as_warn (_("end of file not at end of a line; newline inserted"));
              as_warn (_("end of file not at end of a line; newline inserted"));
              state = 0;
              state = 0;
              PUT ('\n');
              PUT ('\n');
            }
            }
          goto fromeof;
          goto fromeof;
        }
        }
 
 
      switch (lex[ch])
      switch (lex[ch])
        {
        {
        case LEX_IS_WHITESPACE:
        case LEX_IS_WHITESPACE:
          do
          do
            {
            {
              ch = GET ();
              ch = GET ();
            }
            }
          while (ch != EOF && IS_WHITESPACE (ch));
          while (ch != EOF && IS_WHITESPACE (ch));
          if (ch == EOF)
          if (ch == EOF)
            goto fromeof;
            goto fromeof;
 
 
          if (state == 0)
          if (state == 0)
            {
            {
              /* Preserve a single whitespace character at the
              /* Preserve a single whitespace character at the
                 beginning of a line.  */
                 beginning of a line.  */
              state = 1;
              state = 1;
              UNGET (ch);
              UNGET (ch);
              PUT (' ');
              PUT (' ');
              break;
              break;
            }
            }
 
 
#ifdef KEEP_WHITE_AROUND_COLON
#ifdef KEEP_WHITE_AROUND_COLON
          if (lex[ch] == LEX_IS_COLON)
          if (lex[ch] == LEX_IS_COLON)
            {
            {
              /* Only keep this white if there's no white *after* the
              /* Only keep this white if there's no white *after* the
                 colon.  */
                 colon.  */
              ch2 = GET ();
              ch2 = GET ();
              UNGET (ch2);
              UNGET (ch2);
              if (!IS_WHITESPACE (ch2))
              if (!IS_WHITESPACE (ch2))
                {
                {
                  state = 9;
                  state = 9;
                  UNGET (ch);
                  UNGET (ch);
                  PUT (' ');
                  PUT (' ');
                  break;
                  break;
                }
                }
            }
            }
#endif
#endif
          if (IS_COMMENT (ch)
          if (IS_COMMENT (ch)
              || ch == '/'
              || ch == '/'
              || IS_LINE_SEPARATOR (ch)
              || IS_LINE_SEPARATOR (ch)
              || IS_PARALLEL_SEPARATOR (ch))
              || IS_PARALLEL_SEPARATOR (ch))
            {
            {
              if (scrub_m68k_mri)
              if (scrub_m68k_mri)
                {
                {
                  /* In MRI mode, we keep these spaces.  */
                  /* In MRI mode, we keep these spaces.  */
                  UNGET (ch);
                  UNGET (ch);
                  PUT (' ');
                  PUT (' ');
                  break;
                  break;
                }
                }
              goto recycle;
              goto recycle;
            }
            }
 
 
          /* If we're in state 2 or 11, we've seen a non-white
          /* If we're in state 2 or 11, we've seen a non-white
             character followed by whitespace.  If the next character
             character followed by whitespace.  If the next character
             is ':', this is whitespace after a label name which we
             is ':', this is whitespace after a label name which we
             normally must ignore.  In MRI mode, though, spaces are
             normally must ignore.  In MRI mode, though, spaces are
             not permitted between the label and the colon.  */
             not permitted between the label and the colon.  */
          if ((state == 2 || state == 11)
          if ((state == 2 || state == 11)
              && lex[ch] == LEX_IS_COLON
              && lex[ch] == LEX_IS_COLON
              && ! scrub_m68k_mri)
              && ! scrub_m68k_mri)
            {
            {
              state = 1;
              state = 1;
              PUT (ch);
              PUT (ch);
              break;
              break;
            }
            }
 
 
          switch (state)
          switch (state)
            {
            {
            case 1:
            case 1:
              /* We can arrive here if we leave a leading whitespace
              /* We can arrive here if we leave a leading whitespace
                 character at the beginning of a line.  */
                 character at the beginning of a line.  */
              goto recycle;
              goto recycle;
            case 2:
            case 2:
              state = 3;
              state = 3;
              if (to + 1 < toend)
              if (to + 1 < toend)
                {
                {
                  /* Optimize common case by skipping UNGET/GET.  */
                  /* Optimize common case by skipping UNGET/GET.  */
                  PUT (' ');    /* Sp after opco */
                  PUT (' ');    /* Sp after opco */
                  goto recycle;
                  goto recycle;
                }
                }
              UNGET (ch);
              UNGET (ch);
              PUT (' ');
              PUT (' ');
              break;
              break;
            case 3:
            case 3:
              if (scrub_m68k_mri)
              if (scrub_m68k_mri)
                {
                {
                  /* In MRI mode, we keep these spaces.  */
                  /* In MRI mode, we keep these spaces.  */
                  UNGET (ch);
                  UNGET (ch);
                  PUT (' ');
                  PUT (' ');
                  break;
                  break;
                }
                }
              goto recycle;     /* Sp in operands */
              goto recycle;     /* Sp in operands */
            case 9:
            case 9:
            case 10:
            case 10:
              if (scrub_m68k_mri)
              if (scrub_m68k_mri)
                {
                {
                  /* In MRI mode, we keep these spaces.  */
                  /* In MRI mode, we keep these spaces.  */
                  state = 3;
                  state = 3;
                  UNGET (ch);
                  UNGET (ch);
                  PUT (' ');
                  PUT (' ');
                  break;
                  break;
                }
                }
              state = 10;       /* Sp after symbol char */
              state = 10;       /* Sp after symbol char */
              goto recycle;
              goto recycle;
            case 11:
            case 11:
              if (LABELS_WITHOUT_COLONS || flag_m68k_mri)
              if (LABELS_WITHOUT_COLONS || flag_m68k_mri)
                state = 1;
                state = 1;
              else
              else
                {
                {
                  /* We know that ch is not ':', since we tested that
                  /* We know that ch is not ':', since we tested that
                     case above.  Therefore this is not a label, so it
                     case above.  Therefore this is not a label, so it
                     must be the opcode, and we've just seen the
                     must be the opcode, and we've just seen the
                     whitespace after it.  */
                     whitespace after it.  */
                  state = 3;
                  state = 3;
                }
                }
              UNGET (ch);
              UNGET (ch);
              PUT (' ');        /* Sp after label definition.  */
              PUT (' ');        /* Sp after label definition.  */
              break;
              break;
            default:
            default:
              BAD_CASE (state);
              BAD_CASE (state);
            }
            }
          break;
          break;
 
 
        case LEX_IS_TWOCHAR_COMMENT_1ST:
        case LEX_IS_TWOCHAR_COMMENT_1ST:
          ch2 = GET ();
          ch2 = GET ();
          if (ch2 == '*')
          if (ch2 == '*')
            {
            {
              for (;;)
              for (;;)
                {
                {
                  do
                  do
                    {
                    {
                      ch2 = GET ();
                      ch2 = GET ();
                      if (ch2 != EOF && IS_NEWLINE (ch2))
                      if (ch2 != EOF && IS_NEWLINE (ch2))
                        add_newlines++;
                        add_newlines++;
                    }
                    }
                  while (ch2 != EOF && ch2 != '*');
                  while (ch2 != EOF && ch2 != '*');
 
 
                  while (ch2 == '*')
                  while (ch2 == '*')
                    ch2 = GET ();
                    ch2 = GET ();
 
 
                  if (ch2 == EOF || ch2 == '/')
                  if (ch2 == EOF || ch2 == '/')
                    break;
                    break;
 
 
                  /* This UNGET will ensure that we count newlines
                  /* This UNGET will ensure that we count newlines
                     correctly.  */
                     correctly.  */
                  UNGET (ch2);
                  UNGET (ch2);
                }
                }
 
 
              if (ch2 == EOF)
              if (ch2 == EOF)
                as_warn (_("end of file in multiline comment"));
                as_warn (_("end of file in multiline comment"));
 
 
              ch = ' ';
              ch = ' ';
              goto recycle;
              goto recycle;
            }
            }
#ifdef DOUBLESLASH_LINE_COMMENTS
#ifdef DOUBLESLASH_LINE_COMMENTS
          else if (ch2 == '/')
          else if (ch2 == '/')
            {
            {
              do
              do
                {
                {
                  ch = GET ();
                  ch = GET ();
                }
                }
              while (ch != EOF && !IS_NEWLINE (ch));
              while (ch != EOF && !IS_NEWLINE (ch));
              if (ch == EOF)
              if (ch == EOF)
                as_warn ("end of file in comment; newline inserted");
                as_warn ("end of file in comment; newline inserted");
              state = 0;
              state = 0;
              PUT ('\n');
              PUT ('\n');
              break;
              break;
            }
            }
#endif
#endif
          else
          else
            {
            {
              if (ch2 != EOF)
              if (ch2 != EOF)
                UNGET (ch2);
                UNGET (ch2);
              if (state == 9 || state == 10)
              if (state == 9 || state == 10)
                state = 3;
                state = 3;
              PUT (ch);
              PUT (ch);
            }
            }
          break;
          break;
 
 
        case LEX_IS_STRINGQUOTE:
        case LEX_IS_STRINGQUOTE:
          quotechar = ch;
          quotechar = ch;
          if (state == 10)
          if (state == 10)
            {
            {
              /* Preserve the whitespace in foo "bar".  */
              /* Preserve the whitespace in foo "bar".  */
              UNGET (ch);
              UNGET (ch);
              state = 3;
              state = 3;
              PUT (' ');
              PUT (' ');
 
 
              /* PUT didn't jump out.  We could just break, but we
              /* PUT didn't jump out.  We could just break, but we
                 know what will happen, so optimize a bit.  */
                 know what will happen, so optimize a bit.  */
              ch = GET ();
              ch = GET ();
              old_state = 3;
              old_state = 3;
            }
            }
          else if (state == 9)
          else if (state == 9)
            old_state = 3;
            old_state = 3;
          else
          else
            old_state = state;
            old_state = state;
          state = 5;
          state = 5;
          PUT (ch);
          PUT (ch);
          break;
          break;
 
 
#ifndef IEEE_STYLE
#ifndef IEEE_STYLE
        case LEX_IS_ONECHAR_QUOTE:
        case LEX_IS_ONECHAR_QUOTE:
          if (state == 10)
          if (state == 10)
            {
            {
              /* Preserve the whitespace in foo 'b'.  */
              /* Preserve the whitespace in foo 'b'.  */
              UNGET (ch);
              UNGET (ch);
              state = 3;
              state = 3;
              PUT (' ');
              PUT (' ');
              break;
              break;
            }
            }
          ch = GET ();
          ch = GET ();
          if (ch == EOF)
          if (ch == EOF)
            {
            {
              as_warn (_("end of file after a one-character quote; \\0 inserted"));
              as_warn (_("end of file after a one-character quote; \\0 inserted"));
              ch = 0;
              ch = 0;
            }
            }
          if (ch == '\\')
          if (ch == '\\')
            {
            {
              ch = GET ();
              ch = GET ();
              if (ch == EOF)
              if (ch == EOF)
                {
                {
                  as_warn (_("end of file in escape character"));
                  as_warn (_("end of file in escape character"));
                  ch = '\\';
                  ch = '\\';
                }
                }
              else
              else
                ch = process_escape (ch);
                ch = process_escape (ch);
            }
            }
          sprintf (out_buf, "%d", (int) (unsigned char) ch);
          sprintf (out_buf, "%d", (int) (unsigned char) ch);
 
 
          /* None of these 'x constants for us.  We want 'x'.  */
          /* None of these 'x constants for us.  We want 'x'.  */
          if ((ch = GET ()) != '\'')
          if ((ch = GET ()) != '\'')
            {
            {
#ifdef REQUIRE_CHAR_CLOSE_QUOTE
#ifdef REQUIRE_CHAR_CLOSE_QUOTE
              as_warn (_("missing close quote; (assumed)"));
              as_warn (_("missing close quote; (assumed)"));
#else
#else
              if (ch != EOF)
              if (ch != EOF)
                UNGET (ch);
                UNGET (ch);
#endif
#endif
            }
            }
          if (strlen (out_buf) == 1)
          if (strlen (out_buf) == 1)
            {
            {
              PUT (out_buf[0]);
              PUT (out_buf[0]);
              break;
              break;
            }
            }
          if (state == 9)
          if (state == 9)
            old_state = 3;
            old_state = 3;
          else
          else
            old_state = state;
            old_state = state;
          state = -1;
          state = -1;
          out_string = out_buf;
          out_string = out_buf;
          PUT (*out_string++);
          PUT (*out_string++);
          break;
          break;
#endif
#endif
 
 
        case LEX_IS_COLON:
        case LEX_IS_COLON:
#ifdef KEEP_WHITE_AROUND_COLON
#ifdef KEEP_WHITE_AROUND_COLON
          state = 9;
          state = 9;
#else
#else
          if (state == 9 || state == 10)
          if (state == 9 || state == 10)
            state = 3;
            state = 3;
          else if (state != 3)
          else if (state != 3)
            state = 1;
            state = 1;
#endif
#endif
          PUT (ch);
          PUT (ch);
          break;
          break;
 
 
        case LEX_IS_NEWLINE:
        case LEX_IS_NEWLINE:
          /* Roll out a bunch of newlines from inside comments, etc.  */
          /* Roll out a bunch of newlines from inside comments, etc.  */
          if (add_newlines)
          if (add_newlines)
            {
            {
              --add_newlines;
              --add_newlines;
              UNGET (ch);
              UNGET (ch);
            }
            }
          /* Fall through.  */
          /* Fall through.  */
 
 
        case LEX_IS_LINE_SEPARATOR:
        case LEX_IS_LINE_SEPARATOR:
          state = 0;
          state = 0;
          PUT (ch);
          PUT (ch);
          break;
          break;
 
 
        case LEX_IS_PARALLEL_SEPARATOR:
        case LEX_IS_PARALLEL_SEPARATOR:
          state = 1;
          state = 1;
          PUT (ch);
          PUT (ch);
          break;
          break;
 
 
#ifdef TC_V850
#ifdef TC_V850
        case LEX_IS_DOUBLEDASH_1ST:
        case LEX_IS_DOUBLEDASH_1ST:
          ch2 = GET ();
          ch2 = GET ();
          if (ch2 != '-')
          if (ch2 != '-')
            {
            {
              UNGET (ch2);
              UNGET (ch2);
              goto de_fault;
              goto de_fault;
            }
            }
          /* Read and skip to end of line.  */
          /* Read and skip to end of line.  */
          do
          do
            {
            {
              ch = GET ();
              ch = GET ();
            }
            }
          while (ch != EOF && ch != '\n');
          while (ch != EOF && ch != '\n');
 
 
          if (ch == EOF)
          if (ch == EOF)
            as_warn (_("end of file in comment; newline inserted"));
            as_warn (_("end of file in comment; newline inserted"));
 
 
          state = 0;
          state = 0;
          PUT ('\n');
          PUT ('\n');
          break;
          break;
#endif
#endif
#ifdef DOUBLEBAR_PARALLEL
#ifdef DOUBLEBAR_PARALLEL
        case LEX_IS_DOUBLEBAR_1ST:
        case LEX_IS_DOUBLEBAR_1ST:
          ch2 = GET ();
          ch2 = GET ();
          UNGET (ch2);
          UNGET (ch2);
          if (ch2 != '|')
          if (ch2 != '|')
            goto de_fault;
            goto de_fault;
 
 
          /* Handle '||' in two states as invoking PUT twice might
          /* Handle '||' in two states as invoking PUT twice might
             result in the first one jumping out of this loop.  We'd
             result in the first one jumping out of this loop.  We'd
             then lose track of the state and one '|' char.  */
             then lose track of the state and one '|' char.  */
          state = 13;
          state = 13;
          PUT ('|');
          PUT ('|');
          break;
          break;
#endif
#endif
        case LEX_IS_LINE_COMMENT_START:
        case LEX_IS_LINE_COMMENT_START:
          /* FIXME-someday: The two character comment stuff was badly
          /* FIXME-someday: The two character comment stuff was badly
             thought out.  On i386, we want '/' as line comment start
             thought out.  On i386, we want '/' as line comment start
             AND we want C style comments.  hence this hack.  The
             AND we want C style comments.  hence this hack.  The
             whole lexical process should be reworked.  xoxorich.  */
             whole lexical process should be reworked.  xoxorich.  */
          if (ch == '/')
          if (ch == '/')
            {
            {
              ch2 = GET ();
              ch2 = GET ();
              if (ch2 == '*')
              if (ch2 == '*')
                {
                {
                  old_state = 3;
                  old_state = 3;
                  state = -2;
                  state = -2;
                  break;
                  break;
                }
                }
              else
              else
                {
                {
                  UNGET (ch2);
                  UNGET (ch2);
                }
                }
            }
            }
 
 
          if (state == 0 || state == 1)  /* Only comment at start of line.  */
          if (state == 0 || state == 1)  /* Only comment at start of line.  */
            {
            {
              int startch;
              int startch;
 
 
              startch = ch;
              startch = ch;
 
 
              do
              do
                {
                {
                  ch = GET ();
                  ch = GET ();
                }
                }
              while (ch != EOF && IS_WHITESPACE (ch));
              while (ch != EOF && IS_WHITESPACE (ch));
 
 
              if (ch == EOF)
              if (ch == EOF)
                {
                {
                  as_warn (_("end of file in comment; newline inserted"));
                  as_warn (_("end of file in comment; newline inserted"));
                  PUT ('\n');
                  PUT ('\n');
                  break;
                  break;
                }
                }
 
 
              if (ch < '0' || ch > '9' || state != 0 || startch != '#')
              if (ch < '0' || ch > '9' || state != 0 || startch != '#')
                {
                {
                  /* Not a cpp line.  */
                  /* Not a cpp line.  */
                  while (ch != EOF && !IS_NEWLINE (ch))
                  while (ch != EOF && !IS_NEWLINE (ch))
                    ch = GET ();
                    ch = GET ();
                  if (ch == EOF)
                  if (ch == EOF)
                    as_warn (_("end of file in comment; newline inserted"));
                    as_warn (_("end of file in comment; newline inserted"));
                  state = 0;
                  state = 0;
                  PUT ('\n');
                  PUT ('\n');
                  break;
                  break;
                }
                }
              /* Looks like `# 123 "filename"' from cpp.  */
              /* Looks like `# 123 "filename"' from cpp.  */
              UNGET (ch);
              UNGET (ch);
              old_state = 4;
              old_state = 4;
              state = -1;
              state = -1;
              if (scrub_m68k_mri)
              if (scrub_m68k_mri)
                out_string = "\tlinefile ";
                out_string = "\tlinefile ";
              else
              else
                out_string = "\t.linefile ";
                out_string = "\t.linefile ";
              PUT (*out_string++);
              PUT (*out_string++);
              break;
              break;
            }
            }
 
 
#ifdef TC_D10V
#ifdef TC_D10V
          /* All insns end in a char for which LEX_IS_SYMBOL_COMPONENT is true.
          /* All insns end in a char for which LEX_IS_SYMBOL_COMPONENT is true.
             Trap is the only short insn that has a first operand that is
             Trap is the only short insn that has a first operand that is
             neither register nor label.
             neither register nor label.
             We must prevent exef0f ||trap #1 to degenerate to exef0f ||trap#1 .
             We must prevent exef0f ||trap #1 to degenerate to exef0f ||trap#1 .
             We can't make '#' LEX_IS_SYMBOL_COMPONENT because it is
             We can't make '#' LEX_IS_SYMBOL_COMPONENT because it is
             already LEX_IS_LINE_COMMENT_START.  However, it is the
             already LEX_IS_LINE_COMMENT_START.  However, it is the
             only character in line_comment_chars for d10v, hence we
             only character in line_comment_chars for d10v, hence we
             can recognize it as such.  */
             can recognize it as such.  */
          /* An alternative approach would be to reset the state to 1 when
          /* An alternative approach would be to reset the state to 1 when
             we see '||', '<'- or '->', but that seems to be overkill.  */
             we see '||', '<'- or '->', but that seems to be overkill.  */
          if (state == 10)
          if (state == 10)
            PUT (' ');
            PUT (' ');
#endif
#endif
          /* We have a line comment character which is not at the
          /* We have a line comment character which is not at the
             start of a line.  If this is also a normal comment
             start of a line.  If this is also a normal comment
             character, fall through.  Otherwise treat it as a default
             character, fall through.  Otherwise treat it as a default
             character.  */
             character.  */
          if (strchr (tc_comment_chars, ch) == NULL
          if (strchr (tc_comment_chars, ch) == NULL
              && (! scrub_m68k_mri
              && (! scrub_m68k_mri
                  || (ch != '!' && ch != '*')))
                  || (ch != '!' && ch != '*')))
            goto de_fault;
            goto de_fault;
          if (scrub_m68k_mri
          if (scrub_m68k_mri
              && (ch == '!' || ch == '*' || ch == '#')
              && (ch == '!' || ch == '*' || ch == '#')
              && state != 1
              && state != 1
              && state != 10)
              && state != 10)
            goto de_fault;
            goto de_fault;
          /* Fall through.  */
          /* Fall through.  */
        case LEX_IS_COMMENT_START:
        case LEX_IS_COMMENT_START:
#if defined TC_ARM && defined OBJ_ELF
#if defined TC_ARM && defined OBJ_ELF
          /* On the ARM, `@' is the comment character.
          /* On the ARM, `@' is the comment character.
             Unfortunately this is also a special character in ELF .symver
             Unfortunately this is also a special character in ELF .symver
             directives (and .type, though we deal with those another way).
             directives (and .type, though we deal with those another way).
             So we check if this line is such a directive, and treat
             So we check if this line is such a directive, and treat
             the character as default if so.  This is a hack.  */
             the character as default if so.  This is a hack.  */
          if ((symver_state != NULL) && (*symver_state == 0))
          if ((symver_state != NULL) && (*symver_state == 0))
            goto de_fault;
            goto de_fault;
#endif
#endif
 
 
#ifdef TC_ARM
#ifdef TC_ARM
          /* For the ARM, care is needed not to damage occurrences of \@
          /* For the ARM, care is needed not to damage occurrences of \@
             by stripping the @ onwards.  Yuck.  */
             by stripping the @ onwards.  Yuck.  */
          if (to > tostart && *(to - 1) == '\\')
          if (to > tostart && *(to - 1) == '\\')
            /* Do not treat the @ as a start-of-comment.  */
            /* Do not treat the @ as a start-of-comment.  */
            goto de_fault;
            goto de_fault;
#endif
#endif
 
 
#ifdef WARN_COMMENTS
#ifdef WARN_COMMENTS
          if (!found_comment)
          if (!found_comment)
            as_where (&found_comment_file, &found_comment);
            as_where (&found_comment_file, &found_comment);
#endif
#endif
          do
          do
            {
            {
              ch = GET ();
              ch = GET ();
            }
            }
          while (ch != EOF && !IS_NEWLINE (ch));
          while (ch != EOF && !IS_NEWLINE (ch));
          if (ch == EOF)
          if (ch == EOF)
            as_warn (_("end of file in comment; newline inserted"));
            as_warn (_("end of file in comment; newline inserted"));
          state = 0;
          state = 0;
          PUT ('\n');
          PUT ('\n');
          break;
          break;
 
 
        case LEX_IS_SYMBOL_COMPONENT:
        case LEX_IS_SYMBOL_COMPONENT:
          if (state == 10)
          if (state == 10)
            {
            {
              /* This is a symbol character following another symbol
              /* This is a symbol character following another symbol
                 character, with whitespace in between.  We skipped
                 character, with whitespace in between.  We skipped
                 the whitespace earlier, so output it now.  */
                 the whitespace earlier, so output it now.  */
              UNGET (ch);
              UNGET (ch);
              state = 3;
              state = 3;
              PUT (' ');
              PUT (' ');
              break;
              break;
            }
            }
 
 
#ifdef TC_Z80
#ifdef TC_Z80
          /* "af'" is a symbol containing '\''.  */
          /* "af'" is a symbol containing '\''.  */
          if (state == 3 && (ch == 'a' || ch == 'A'))
          if (state == 3 && (ch == 'a' || ch == 'A'))
            {
            {
              state = 16;
              state = 16;
              PUT (ch);
              PUT (ch);
              ch = GET ();
              ch = GET ();
              if (ch == 'f' || ch == 'F')
              if (ch == 'f' || ch == 'F')
                {
                {
                  state = 17;
                  state = 17;
                  PUT (ch);
                  PUT (ch);
                  break;
                  break;
                }
                }
              else
              else
                {
                {
                  state = 9;
                  state = 9;
                  if (!IS_SYMBOL_COMPONENT (ch))
                  if (!IS_SYMBOL_COMPONENT (ch))
                    {
                    {
                      UNGET (ch);
                      UNGET (ch);
                      break;
                      break;
                    }
                    }
                }
                }
            }
            }
#endif
#endif
          if (state == 3)
          if (state == 3)
            state = 9;
            state = 9;
 
 
          /* This is a common case.  Quickly copy CH and all the
          /* This is a common case.  Quickly copy CH and all the
             following symbol component or normal characters.  */
             following symbol component or normal characters.  */
          if (to + 1 < toend
          if (to + 1 < toend
              && mri_state == NULL
              && mri_state == NULL
#if defined TC_ARM && defined OBJ_ELF
#if defined TC_ARM && defined OBJ_ELF
              && symver_state == NULL
              && symver_state == NULL
#endif
#endif
              )
              )
            {
            {
              char *s;
              char *s;
              int len;
              int len;
 
 
              for (s = from; s < fromend; s++)
              for (s = from; s < fromend; s++)
                {
                {
                  int type;
                  int type;
 
 
                  ch2 = *(unsigned char *) s;
                  ch2 = *(unsigned char *) s;
                  type = lex[ch2];
                  type = lex[ch2];
                  if (type != 0
                  if (type != 0
                      && type != LEX_IS_SYMBOL_COMPONENT)
                      && type != LEX_IS_SYMBOL_COMPONENT)
                    break;
                    break;
                }
                }
 
 
              if (s > from)
              if (s > from)
                /* Handle the last character normally, for
                /* Handle the last character normally, for
                   simplicity.  */
                   simplicity.  */
                --s;
                --s;
 
 
              len = s - from;
              len = s - from;
 
 
              if (len > (toend - to) - 1)
              if (len > (toend - to) - 1)
                len = (toend - to) - 1;
                len = (toend - to) - 1;
 
 
              if (len > 0)
              if (len > 0)
                {
                {
                  PUT (ch);
                  PUT (ch);
                  memcpy (to, from, len);
                  memcpy (to, from, len);
                  to += len;
                  to += len;
                  from += len;
                  from += len;
                  if (to >= toend)
                  if (to >= toend)
                    goto tofull;
                    goto tofull;
                  ch = GET ();
                  ch = GET ();
                }
                }
            }
            }
 
 
          /* Fall through.  */
          /* Fall through.  */
        default:
        default:
        de_fault:
        de_fault:
          /* Some relatively `normal' character.  */
          /* Some relatively `normal' character.  */
          if (state == 0)
          if (state == 0)
            {
            {
              state = 11;       /* Now seeing label definition.  */
              state = 11;       /* Now seeing label definition.  */
            }
            }
          else if (state == 1)
          else if (state == 1)
            {
            {
              state = 2;        /* Ditto.  */
              state = 2;        /* Ditto.  */
            }
            }
          else if (state == 9)
          else if (state == 9)
            {
            {
              if (!IS_SYMBOL_COMPONENT (ch))
              if (!IS_SYMBOL_COMPONENT (ch))
                state = 3;
                state = 3;
            }
            }
          else if (state == 10)
          else if (state == 10)
            {
            {
              if (ch == '\\')
              if (ch == '\\')
                {
                {
                  /* Special handling for backslash: a backslash may
                  /* Special handling for backslash: a backslash may
                     be the beginning of a formal parameter (of a
                     be the beginning of a formal parameter (of a
                     macro) following another symbol character, with
                     macro) following another symbol character, with
                     whitespace in between.  If that is the case, we
                     whitespace in between.  If that is the case, we
                     output a space before the parameter.  Strictly
                     output a space before the parameter.  Strictly
                     speaking, correct handling depends upon what the
                     speaking, correct handling depends upon what the
                     macro parameter expands into; if the parameter
                     macro parameter expands into; if the parameter
                     expands into something which does not start with
                     expands into something which does not start with
                     an operand character, then we don't want to keep
                     an operand character, then we don't want to keep
                     the space.  We don't have enough information to
                     the space.  We don't have enough information to
                     make the right choice, so here we are making the
                     make the right choice, so here we are making the
                     choice which is more likely to be correct.  */
                     choice which is more likely to be correct.  */
                  if (to + 1 >= toend)
                  if (to + 1 >= toend)
                    {
                    {
                      /* If we're near the end of the buffer, save the
                      /* If we're near the end of the buffer, save the
                         character for the next time round.  Otherwise
                         character for the next time round.  Otherwise
                         we'll lose our state.  */
                         we'll lose our state.  */
                      UNGET (ch);
                      UNGET (ch);
                      goto tofull;
                      goto tofull;
                    }
                    }
                  *to++ = ' ';
                  *to++ = ' ';
                }
                }
 
 
              state = 3;
              state = 3;
            }
            }
          PUT (ch);
          PUT (ch);
          break;
          break;
        }
        }
    }
    }
 
 
  /*NOTREACHED*/
  /*NOTREACHED*/
 
 
 fromeof:
 fromeof:
  /* We have reached the end of the input.  */
  /* We have reached the end of the input.  */
  return to - tostart;
  return to - tostart;
 
 
 tofull:
 tofull:
  /* The output buffer is full.  Save any input we have not yet
  /* The output buffer is full.  Save any input we have not yet
     processed.  */
     processed.  */
  if (fromend > from)
  if (fromend > from)
    {
    {
      saved_input = from;
      saved_input = from;
      saved_input_len = fromend - from;
      saved_input_len = fromend - from;
    }
    }
  else
  else
    saved_input = NULL;
    saved_input = NULL;
 
 
  return to - tostart;
  return to - tostart;
}
}
 
 
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.