/* This is the Assembler Pre-Processor
Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003
+ 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009, 2010, 2012
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
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
#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)
/* 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. */
static char out_buf[20];
static int add_newlines;
static char *saved_input;
-static int saved_input_len;
+static size_t saved_input_len;
static char input_buffer[32 * 1024];
static const char *mri_state;
static char mri_last_ch;
char out_buf[sizeof (out_buf)];
int add_newlines;
char * saved_input;
- int saved_input_len;
+ size_t saved_input_len;
#ifdef TC_M68K
int scrub_m68k_mri;
#endif
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;
}
state = 0;
saved_input = NULL;
+ add_newlines = 0;
return (char *) saved;
}
saved_input = NULL;
else
{
- assert (saved->saved_input_len <= (int) (sizeof input_buffer));
+ gas_assert (saved->saved_input_len <= sizeof (input_buffer));
memcpy (input_buffer, saved->saved_input, saved->saved_input_len);
saved_input = input_buffer;
saved_input_len = saved->saved_input_len;
machine, and saves its state so that it may return at any point.
This is the way the old code used to work. */
-int
-do_scrub_chars (int (*get) (char *, int), char *tostart, int tolen)
+size_t
+do_scrub_chars (size_t (*get) (char *, size_t), char *tostart, size_t tolen)
{
char *to = tostart;
char *toend = tostart + tolen;
char *from;
char *fromend;
- int fromlen;
+ size_t fromlen;
register int ch, ch2 = 0;
/* Character that started the string we're working on. */
static char quotechar;
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)
13: After seeing a vertical bar, looking for a second
vertical bar as a parallel expression separator.
#endif
-#ifdef TC_IA64
- 14: After seeing a `(' at state 0, looking for a `)' as
- predicate.
- 15: After seeing a `(' at state 1, looking for a `)' as
- predicate.
+#ifdef TC_PREDICATE_START_CHAR
+ 14: After seeing a predicate start character at state 0, looking
+ for a predicate end character as predicate.
+ 15: After seeing a predicate start character at state 1, looking
+ for a predicate end character as predicate.
#endif
#ifdef TC_Z80
16: After seeing an 'a' or an 'A' at the start of a symbol
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
{
GET and PUT macros. */
{
char *s;
- int len;
+ ptrdiff_t len;
for (s = from; s < fromend; s++)
{
memcpy (to, from, len);
to += len;
from += len;
+ if (to >= toend)
+ goto tofull;
}
}
ch = GET ();
if (ch == EOF)
{
+ /* 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 (quotechar);
}
PUT (ch);
continue;
- case 7:
- ch = GET ();
- quotechar = ch;
- state = 5;
- old_state = 8;
- 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 ();
line from just after the first white space. */
state = 1;
PUT ('|');
+#ifdef TC_TIC6X
+ /* "||^" is used for SPMASKed instructions. */
+ ch = GET ();
+ if (ch == EOF)
+ goto fromeof;
+ else if (ch == '^')
+ PUT ('^');
+ else
+ UNGET (ch);
+#endif
continue;
#endif
#ifdef TC_Z80
if (ch == '\'')
/* Change to avoid warning about unclosed string. */
PUT ('`');
- else
+ else if (ch != EOF)
UNGET (ch);
break;
#endif
/* flushchar: */
ch = GET ();
-#ifdef TC_IA64
- if (ch == '(' && (state == 0 || state == 1))
+#ifdef TC_PREDICATE_START_CHAR
+ if (ch == TC_PREDICATE_START_CHAR && (state == 0 || state == 1))
{
state += 14;
PUT (ch);
}
else if (state == 14 || state == 15)
{
- if (ch == ')')
+ if (ch == TC_PREDICATE_END_CHAR)
{
state -= 14;
PUT (ch);
/* 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;
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. */
PUT (' ');
break;
case 3:
+#ifndef TC_KEEP_OPERAND_SPACES
+ /* For TI C6X, we keep these spaces as they may separate
+ functional unit specifiers from operands. */
if (scrub_m68k_mri)
+#endif
{
/* In MRI mode, we keep these spaces. */
UNGET (ch);
goto recycle; /* Sp in operands */
case 9:
case 10:
+#ifndef TC_KEEP_OPERAND_SPACES
if (scrub_m68k_mri)
+#endif
{
/* In MRI mode, we keep these spaces. */
state = 3;
#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'. */
ch2 = GET ();
if (ch2 != '-')
{
- UNGET (ch2);
+ if (ch2 != EOF)
+ UNGET (ch2);
goto de_fault;
}
/* Read and skip to end of line. */
#ifdef DOUBLEBAR_PARALLEL
case LEX_IS_DOUBLEBAR_1ST:
ch2 = GET ();
- UNGET (ch2);
+ if (ch2 != EOF)
+ UNGET (ch2);
if (ch2 != '|')
goto de_fault;
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;
}
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);
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)
{
else
{
state = 9;
- if (!IS_SYMBOL_COMPONENT (ch))
+ if (ch == EOF || !IS_SYMBOL_COMPONENT (ch))
{
- UNGET (ch);
+ if (ch != EOF)
+ UNGET (ch);
break;
}
}
)
{
char *s;
- int len;
+ ptrdiff_t len;
for (s = from; s < fromend; s++)
{
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;
return to - tostart;
}
-