include/
[external/binutils.git] / gas / app.c
index 074729f..56a0e12 100644 (file)
--- a/gas/app.c
+++ b/gas/app.c
@@ -1,33 +1,32 @@
 /* This is the Assembler Pre-Processor
    Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2002, 2003
+   1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007, 2008
    Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
    GAS is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
+   the Free Software Foundation; either version 3, or (at your option)
    any later version.
 
-   GAS is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
+   GAS is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
 
    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
-   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.  */
+   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
 
 /* Modified by Allen Wirfs-Brock, Instantiations Inc 2/90.  */
-/* App, the assembler pre-processor.  This pre-processor strips out excess
-   spaces, turns single-quoted characters into a decimal constant, and turns
-   # <number> <filename> <garbage> into a .line <number>\n.file <filename>
-   pair.  This needs better error-handling.  */
+/* App, the assembler pre-processor.  This pre-processor strips out
+   excess spaces, turns single-quoted characters into a decimal
+   constant, and turns the # in # <number> <filename> <garbage> into a
+   .linefile.  This needs better error-handling.  */
 
-#include <stdio.h>
-#include "as.h"                        /* For BAD_CASE() only.  */
+#include "as.h"
 
 #if (__STDC__ != 1)
 #ifndef const
 #endif
 #endif
 
+#ifdef H_TICK_HEX
+int enable_h_tick_hex = 0;
+#endif
+
 #ifdef TC_M68K
 /* 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
@@ -79,6 +82,9 @@ static const char symbol_chars[] =
 #define LEX_IS_DOUBLEBAR_1ST           13
 #endif
 #define LEX_IS_PARALLEL_SEPARATOR      14
+#ifdef H_TICK_HEX
+#define LEX_IS_H                       15
+#endif
 #define IS_SYMBOL_COMPONENT(c)         (lex[c] == LEX_IS_SYMBOL_COMPONENT)
 #define IS_WHITESPACE(c)               (lex[c] == LEX_IS_WHITESPACE)
 #define IS_LINE_SEPARATOR(c)           (lex[c] == LEX_IS_LINE_SEPARATOR)
@@ -87,15 +93,14 @@ static const char symbol_chars[] =
 #define IS_LINE_COMMENT(c)             (lex[c] == LEX_IS_LINE_COMMENT_START)
 #define        IS_NEWLINE(c)                   (lex[c] == LEX_IS_NEWLINE)
 
-static int process_escape PARAMS ((int));
+static int process_escape (int);
 
 /* FIXME-soon: The entire lexer/parser thingy should be
    built statically at compile time rather than dynamically
    each and every time the assembler is run.  xoxorich.  */
 
 void
-do_scrub_begin (m68k_mri)
-     int m68k_mri ATTRIBUTE_UNUSED;
+do_scrub_begin (int m68k_mri ATTRIBUTE_UNUSED)
 {
   const char *p;
   int c;
@@ -192,6 +197,14 @@ do_scrub_begin (m68k_mri)
   /* Must do this is we want VLIW instruction with "->" or "<-".  */
   lex['-'] = LEX_IS_SYMBOL_COMPONENT;
 #endif
+
+#ifdef H_TICK_HEX
+  if (enable_h_tick_hex)
+    {
+      lex['h'] = LEX_IS_H;
+      lex['H'] = LEX_IS_H;
+    }
+#endif
 }
 
 /* Saved state of the scrubber.  */
@@ -231,7 +244,7 @@ struct app_save
 };
 
 char *
-app_push ()
+app_push (void)
 {
   register struct app_save *saved;
 
@@ -245,7 +258,7 @@ app_push ()
     saved->saved_input = NULL;
   else
     {
-      saved->saved_input = xmalloc (saved_input_len);
+      saved->saved_input = (char *) xmalloc (saved_input_len);
       memcpy (saved->saved_input, saved_input, saved_input_len);
       saved->saved_input_len = saved_input_len;
     }
@@ -267,8 +280,7 @@ app_push ()
 }
 
 void
-app_pop (arg)
-     char *arg;
+app_pop (char *arg)
 {
   register struct app_save *saved = (struct app_save *) arg;
 
@@ -282,7 +294,7 @@ app_pop (arg)
     saved_input = NULL;
   else
     {
-      assert (saved->saved_input_len <= (int) (sizeof input_buffer));
+      gas_assert (saved->saved_input_len <= (int) (sizeof input_buffer));
       memcpy (input_buffer, saved->saved_input, saved->saved_input_len);
       saved_input = input_buffer;
       saved_input_len = saved->saved_input_len;
@@ -304,8 +316,7 @@ app_pop (arg)
    necessarily true.  */
 
 static int
-process_escape (ch)
-     int ch;
+process_escape (int ch)
 {
   switch (ch)
     {
@@ -340,10 +351,7 @@ process_escape (ch)
    This is the way the old code used to work.  */
 
 int
-do_scrub_chars (get, tostart, tolen)
-     int (*get) PARAMS ((char *, int));
-     char *tostart;
-     int tolen;
+do_scrub_chars (int (*get) (char *, int), char *tostart, int tolen)
 {
   char *to = tostart;
   char *toend = tostart + tolen;
@@ -351,16 +359,18 @@ do_scrub_chars (get, tostart, tolen)
   char *fromend;
   int fromlen;
   register int ch, ch2 = 0;
+  /* Character that started the string we're working on.  */
+  static char quotechar;
 
   /*State 0: beginning of normal line
          1: After first whitespace on line (flush more white)
          2: After first non-white (opcode) on line (keep 1white)
          3: after second white on line (into operands) (flush white)
-         4: after putting out a .line, put out digits
+         4: after putting out a .linefile, put out digits
          5: parsing a string, then go to old-state
          6: putting out \ escape in a "d string.
-         7: After putting out a .appfile, put out string.
-         8: After putting out a .appfile string, flush until newline.
+         7: no longer used
+         8: no longer used
          9: After seeing symbol char in state 3 (keep 1white after 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)
@@ -380,6 +390,10 @@ do_scrub_chars (get, tostart, tolen)
         15: After seeing a `(' at state 1, looking for a `)' as
             predicate.
 #endif
+#ifdef TC_Z80
+        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
+#endif
          */
 
   /* I added states 9 and 10 because the MIPS ECOFF assembler uses
@@ -511,14 +525,10 @@ do_scrub_chars (get, tostart, tolen)
                ch = GET ();
              if (ch == '"')
                {
-                 UNGET (ch);
-                 if (scrub_m68k_mri)
-                   out_string = "\n\tappfile ";
-                 else
-                   out_string = "\n\t.appfile ";
-                 old_state = 7;
-                 state = -1;
-                 PUT (*out_string++);
+                 quotechar = ch;
+                 state = 5;
+                 old_state = 3;
+                 PUT (ch);
                }
              else
                {
@@ -542,11 +552,8 @@ do_scrub_chars (get, tostart, tolen)
            for (s = from; s < fromend; s++)
              {
                ch = *s;
-               /* This condition must be changed if the type of any
-                  other character can be LEX_IS_STRINGQUOTE.  */
                if (ch == '\\'
-                   || ch == '"'
-                   || ch == '\''
+                   || ch == quotechar
                    || ch == '\n')
                  break;
              }
@@ -558,18 +565,26 @@ do_scrub_chars (get, tostart, tolen)
                memcpy (to, from, len);
                to += len;
                from += len;
+               if (to >= toend)
+                 goto tofull;
              }
          }
 
          ch = GET ();
          if (ch == EOF)
            {
-             as_warn (_("end of file in string; inserted '\"'"));
+             /* This buffer is here specifically so
+                that the UNGET below will work.  */
+             static char one_char_buf[1];
+
+             as_warn (_("end of file in string; '%c' inserted"), quotechar);
              state = old_state;
+             from = fromend = one_char_buf + 1;
+             fromlen = 1;
              UNGET ('\n');
-             PUT ('"');
+             PUT (quotechar);
            }
-         else if (lex[ch] == LEX_IS_STRINGQUOTE)
+         else if (ch == quotechar)
            {
              state = old_state;
              PUT (ch);
@@ -609,8 +624,8 @@ do_scrub_chars (get, tostart, tolen)
              continue;
 
            case EOF:
-             as_warn (_("end of file in string; '\"' inserted"));
-             PUT ('"');
+             as_warn (_("end of file in string; '%c' inserted"), quotechar);
+             PUT (quotechar);
              continue;
 
            case '"':
@@ -642,25 +657,6 @@ do_scrub_chars (get, tostart, tolen)
          PUT (ch);
          continue;
 
-       case 7:
-         ch = GET ();
-         state = 5;
-         old_state = 8;
-         if (ch == EOF)
-           goto fromeof;
-         PUT (ch);
-         continue;
-
-       case 8:
-         do
-           ch = GET ();
-         while (ch != '\n' && ch != EOF);
-         if (ch == EOF)
-           goto fromeof;
-         state = 0;
-         PUT (ch);
-         continue;
-
 #ifdef DOUBLEBAR_PARALLEL
        case 13:
          ch = GET ();
@@ -673,6 +669,32 @@ do_scrub_chars (get, tostart, tolen)
          PUT ('|');
          continue;
 #endif
+#ifdef TC_Z80
+       case 16:
+         /* We have seen an 'a' at the start of a symbol, look for an 'f'.  */
+         ch = GET ();
+         if (ch == 'f' || ch == 'F') 
+           {
+             state = 17;
+             PUT (ch);
+           }
+         else
+           {
+             state = 9;
+             break;
+           }
+       case 17:
+         /* We have seen "af" at the start of a symbol,
+            a ' here is a part of that symbol.  */
+         ch = GET ();
+         state = 9;
+         if (ch == '\'')
+           /* Change to avoid warning about unclosed string.  */
+           PUT ('`');
+         else if (ch != EOF)
+           UNGET (ch);
+         break;
+#endif
        }
 
       /* OK, we are somewhere in states 0 through 4 or 9 through 11.  */
@@ -690,7 +712,11 @@ do_scrub_chars (get, tostart, tolen)
       else if (state == 14 || state == 15)
        {
          if (ch == ')')
-           state -= 14;
+           {
+             state -= 14;
+             PUT (ch);
+             ch = GET ();
+           }
          else
            {
              PUT (ch);
@@ -821,7 +847,8 @@ do_scrub_chars (get, tostart, tolen)
              /* Only keep this white if there's no white *after* the
                 colon.  */
              ch2 = GET ();
-             UNGET (ch2);
+             if (ch2 != EOF)
+               UNGET (ch2);
              if (!IS_WHITESPACE (ch2))
                {
                  state = 9;
@@ -862,9 +889,6 @@ do_scrub_chars (get, tostart, tolen)
 
          switch (state)
            {
-           case 0:
-             state++;
-             goto recycle;     /* Punted leading sp */
            case 1:
              /* We can arrive here if we leave a leading whitespace
                 character at the beginning of a line.  */
@@ -977,6 +1001,7 @@ do_scrub_chars (get, tostart, tolen)
          break;
 
        case LEX_IS_STRINGQUOTE:
+         quotechar = ch;
          if (state == 10)
            {
              /* Preserve the whitespace in foo "bar".  */
@@ -999,6 +1024,16 @@ do_scrub_chars (get, tostart, tolen)
 
 #ifndef IEEE_STYLE
        case LEX_IS_ONECHAR_QUOTE:
+#ifdef H_TICK_HEX
+         if (state == 9 && enable_h_tick_hex)
+           {
+             char c;
+
+             c = GET ();
+             as_warn ("'%c found after symbol", c);
+             UNGET (c);
+           }
+#endif
          if (state == 10)
            {
              /* Preserve the whitespace in foo 'b'.  */
@@ -1087,7 +1122,8 @@ do_scrub_chars (get, tostart, tolen)
          ch2 = GET ();
          if (ch2 != '-')
            {
-             UNGET (ch2);
+             if (ch2 != EOF)
+               UNGET (ch2);
              goto de_fault;
            }
          /* Read and skip to end of line.  */
@@ -1107,7 +1143,8 @@ do_scrub_chars (get, tostart, tolen)
 #ifdef DOUBLEBAR_PARALLEL
        case LEX_IS_DOUBLEBAR_1ST:
          ch2 = GET ();
-         UNGET (ch2);
+         if (ch2 != EOF)
+           UNGET (ch2);
          if (ch2 != '|')
            goto de_fault;
 
@@ -1173,9 +1210,9 @@ do_scrub_chars (get, tostart, tolen)
              old_state = 4;
              state = -1;
              if (scrub_m68k_mri)
-               out_string = "\tappline ";
+               out_string = "\tlinefile ";
              else
-               out_string = "\t.appline ";
+               out_string = "\t.linefile ";
              PUT (*out_string++);
              break;
            }
@@ -1218,6 +1255,15 @@ do_scrub_chars (get, tostart, tolen)
          if ((symver_state != NULL) && (*symver_state == 0))
            goto de_fault;
 #endif
+
+#ifdef TC_ARM
+         /* For the ARM, care is needed not to damage occurrences of \@
+            by stripping the @ onwards.  Yuck.  */
+         if (to > tostart && *(to - 1) == '\\')
+           /* Do not treat the @ as a start-of-comment.  */
+           goto de_fault;
+#endif
+
 #ifdef WARN_COMMENTS
          if (!found_comment)
            as_where (&found_comment_file, &found_comment);
@@ -1233,6 +1279,26 @@ do_scrub_chars (get, tostart, tolen)
          PUT ('\n');
          break;
 
+#ifdef H_TICK_HEX
+       case LEX_IS_H:
+         /* Look for strings like H'[0-9A-Fa-f] and if found, replace
+            the H' with 0x to make them gas-style hex characters.  */
+         if (enable_h_tick_hex)
+           {
+             char quot;
+
+             quot = GET ();
+             if (quot == '\'')
+               {
+                 UNGET ('x');
+                 ch = '0';
+               }
+             else
+               UNGET (quot);
+           }
+         /* FALL THROUGH */
+#endif
+
        case LEX_IS_SYMBOL_COMPONENT:
          if (state == 10)
            {
@@ -1245,6 +1311,31 @@ do_scrub_chars (get, tostart, tolen)
              break;
            }
 
+#ifdef TC_Z80
+         /* "af'" is a symbol containing '\''.  */
+         if (state == 3 && (ch == 'a' || ch == 'A')) 
+           {
+             state = 16;
+             PUT (ch);
+             ch = GET ();
+             if (ch == 'f' || ch == 'F') 
+               {
+                 state = 17;
+                 PUT (ch);
+                 break;
+               }
+             else
+               {
+                 state = 9;
+                 if (!IS_SYMBOL_COMPONENT (ch)) 
+                   {
+                     if (ch != EOF)
+                       UNGET (ch);
+                     break;
+                   }
+               }
+           }
+#endif
          if (state == 3)
            state = 9;
 
@@ -1284,26 +1375,11 @@ do_scrub_chars (get, tostart, tolen)
              if (len > 0)
                {
                  PUT (ch);
-                 if (len > 8)
-                   {
-                     memcpy (to, from, len);
-                     to += len;
-                     from += len;
-                   }
-                 else
-                   {
-                     switch (len)
-                       {
-                       case 8: *to++ = *from++;
-                       case 7: *to++ = *from++;
-                       case 6: *to++ = *from++;
-                       case 5: *to++ = *from++;
-                       case 4: *to++ = *from++;
-                       case 3: *to++ = *from++;
-                       case 2: *to++ = *from++;
-                       case 1: *to++ = *from++;
-                       }
-                   }
+                 memcpy (to, from, len);
+                 to += len;
+                 from += len;
+                 if (to >= toend)
+                   goto tofull;
                  ch = GET ();
                }
            }
@@ -1314,13 +1390,11 @@ do_scrub_chars (get, tostart, tolen)
          /* Some relatively `normal' character.  */
          if (state == 0)
            {
-             if (IS_SYMBOL_COMPONENT (ch))
-               state = 11;     /* Now seeing label definition.  */
+             state = 11;       /* Now seeing label definition.  */
            }
          else if (state == 1)
            {
-             if (IS_SYMBOL_COMPONENT (ch))
-               state = 2;      /* Ditto.  */
+             state = 2;        /* Ditto.  */
            }
          else if (state == 9)
            {
@@ -1343,7 +1417,15 @@ do_scrub_chars (get, tostart, tolen)
                     the space.  We don't have enough information to
                     make the right choice, so here we are making the
                     choice which is more likely to be correct.  */
-                 PUT (' ');
+                 if (to + 1 >= toend)
+                   {
+                     /* If we're near the end of the buffer, save the
+                        character for the next time round.  Otherwise
+                        we'll lose our state.  */
+                     UNGET (ch);
+                     goto tofull;
+                   }
+                 *to++ = ' ';
                }
 
              state = 3;
@@ -1372,4 +1454,3 @@ do_scrub_chars (get, tostart, tolen)
 
   return to - tostart;
 }
-