-/* Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
-
- Modified by Allen Wirfs-Brock, Instantiations Inc 2/90
- */
/* This is the Assembler Pre-Processor
- Copyright (C) 1987 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1990, 1991, 1992, 1994 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
along with GAS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, 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.app-file <filename>
+ # <number> <filename> <garbage> into a .line <number>\n.file <filename>
pair. This needs better error-handling.
*/
#include <stdio.h>
#include "as.h" /* For BAD_CASE() only */
-#if (__STDC__ != 1) && !defined(const)
-#define const /* Nothing */
+#if (__STDC__ != 1)
+#ifndef const
+#define const /* empty */
+#endif
#endif
static char lex[256];
#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));
+
/* 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. */
lex['\n'] = LEX_IS_NEWLINE;
lex[';'] = LEX_IS_LINE_SEPARATOR;
lex['"'] = LEX_IS_STRINGQUOTE;
+#ifndef TC_HPPA
lex['\''] = LEX_IS_ONECHAR_QUOTE;
+#endif
lex[':'] = LEX_IS_COLON;
is a comment char, then it isn't a line separator. */
for (p = symbol_chars; *p; ++p)
{
- lex[*p] = LEX_IS_SYMBOL_COMPONENT;
+ lex[(unsigned char) *p] = LEX_IS_SYMBOL_COMPONENT;
} /* declare symbol characters */
- for (p = line_comment_chars; *p; p++)
- {
- lex[*p] = LEX_IS_LINE_COMMENT_START;
- } /* declare line comment chars */
-
for (p = comment_chars; *p; p++)
{
- lex[*p] = LEX_IS_COMMENT_START;
+ lex[(unsigned char) *p] = LEX_IS_COMMENT_START;
} /* declare comment chars */
+ for (p = line_comment_chars; *p; p++)
+ {
+ lex[(unsigned char) *p] = LEX_IS_LINE_COMMENT_START;
+ } /* declare line comment chars */
+
for (p = line_separator_chars; *p; p++)
{
- lex[*p] = LEX_IS_LINE_SEPARATOR;
+ lex[(unsigned char) *p] = LEX_IS_LINE_SEPARATOR;
} /* declare line separators */
/* Only allow slash-star comments if slash is not in use */
saved->state = state;
saved->old_state = old_state;
saved->out_string = out_string;
- memcpy (out_buf, saved->out_buf, sizeof (out_buf));
+ memcpy (saved->out_buf, out_buf, sizeof (out_buf));
saved->add_newlines = add_newlines;
saved->scrub_string = scrub_string;
saved->scrub_last_string = scrub_last_string;
state = saved->state;
old_state = saved->old_state;
out_string = saved->out_string;
- memcpy (saved->out_buf, out_buf, sizeof (out_buf));
+ memcpy (out_buf, saved->out_buf, sizeof (out_buf));
add_newlines = saved->add_newlines;
scrub_string = saved->scrub_string;
scrub_last_string = saved->scrub_last_string;
/* @@ This assumes that \n &c are the same on host and target. This is not
necessarily true. */
-int
+static int
process_escape (ch)
- char ch;
+ int ch;
{
switch (ch)
{
4: after putting out a .line, 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 .app-file, put out string.
- 8: After putting out a .app-file string, flush until newline.
+ 7: After putting out a .appfile, put out string.
+ 8: After putting out a .appfile string, flush until newline.
9: After seeing symbol char in state 3 (keep 1white after symchar)
+ 10: After seeing whitespace in state 9 (keep white before symchar)
-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
*/
- /* I added state 9 because the MIPS ECOFF assembler uses constructs
- like ``.loc 1 20''. This was turning into ``.loc 120''. State 9
- ensures that a space is never dropped immediately following a
- character which could appear in a identifier. It is still
- dropped following a comma, so this has no effect for most
+ /* I added states 9 and 10 because the MIPS ECOFF assembler uses
+ constructs like ``.loc 1 20''. This was turning into ``.loc
+ 120''. States 9 and 10 ensure that a space is never dropped in
+ between characters which could appear in a identifier. Ian
register int ch, ch2 = 0;
+ int not_cpp_line = 0;
switch (state)
{
if (ch == '"')
{
(*unget) (ch);
- out_string = "\n.app-file ";
+ out_string = "\n\t.appfile ";
old_state = 7;
state = -1;
return *out_string++;
{
while (ch != EOF && ch != '\n')
ch = (*get) ();
+ state = 0;
return ch;
}
}
#ifdef BACKSLASH_V
case 'v':
#endif /* BACKSLASH_V */
+ case 'x':
+ case 'X':
case '0':
case '1':
case '2':
return ch;
}
- /* OK, we are somewhere in states 0 through 4 or 9 */
+ /* OK, we are somewhere in states 0 through 4 or 9 through 10 */
/* flushchar: */
ch = (*get) ();
{
case LEX_IS_WHITESPACE:
do
- ch = (*get) ();
+ /* Preserve a single whitespace character at the beginning of
+ a line. */
+ if (state == 0)
+ {
+ state = 1;
+ return ch;
+ }
+ else
+ ch = (*get) ();
while (ch != EOF && IS_WHITESPACE (ch));
if (ch == EOF)
return ch;
if (IS_COMMENT (ch) || (state == 0 && IS_LINE_COMMENT (ch)) || ch == '/' || IS_LINE_SEPARATOR (ch))
{
+ /* cpp never outputs a leading space before the #, so try to
+ avoid being confused. */
+ not_cpp_line = 1;
goto recycle;
}
#ifdef MRI
state++;
goto recycle; /* Punted leading sp */
case 1:
- BAD_CASE (state); /* We can't get here */
+ /* We can arrive here if we leave a leading whitespace character
+ at the beginning of a line. */
+ goto recycle;
case 2:
- case 9:
state = 3;
(*unget) (ch);
return ' '; /* Sp after opco */
case 3:
goto recycle; /* Sp in operands */
+ case 9:
+ case 10:
+ state = 10; /* Sp after symbol char */
+ goto recycle;
default:
BAD_CASE (state);
}
{
if (ch2 != EOF)
(*unget) (ch2);
+ if (state == 9 || state == 10)
+ state = 3;
return ch;
}
break;
case LEX_IS_STRINGQUOTE:
- old_state = state;
+ if (state == 9 || state == 10)
+ old_state = 3;
+ else
+ old_state = state;
state = 5;
return ch;
#ifndef MRI
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) ()) != '\'')
{
#ifdef REQUIRE_CHAR_CLOSE_QUOTE
{
return out_buf[0];
}
- old_state = state;
+ if (state == 9 || state == 10)
+ old_state = 3;
+ else
+ old_state = state;
state = -1;
out_string = out_buf;
return *out_string++;
#endif
#endif
case LEX_IS_COLON:
- if (state != 3)
+ if (state == 9 || state == 10)
+ state = 3;
+ else if (state != 3)
state = 0;
return ch;
return ch;
case LEX_IS_LINE_COMMENT_START:
- if (state != 0) /* Not at start of line, act normal */
- goto de_fault;
+ if (state == 0) /* Only comment at start of line. */
+ {
+ /* FIXME-someday: The two character comment stuff was badly
+ thought out. On i386, we want '/' as line comment start
+ AND we want C style comments. hence this hack. The
+ whole lexical process should be reworked. xoxorich. */
+ if (ch == '/')
+ {
+ ch2 = (*get) ();
+ if (ch2 == '*')
+ {
+ state = -2;
+ return (do_scrub_next_char (get, unget));
+ }
+ else
+ {
+ (*unget) (ch2);
+ }
+ } /* bad hack */
- /* FIXME-someday: The two character comment stuff was badly
- thought out. On i386, we want '/' as line comment start AND
- we want C style comments. hence this hack. The whole
- lexical process should be reworked. xoxorich. */
+ if (ch != '#')
+ not_cpp_line = 1;
- if (ch == '/')
- {
- ch2 = (*get) ();
- if (ch2 == '*')
+ do
+ ch = (*get) ();
+ while (ch != EOF && IS_WHITESPACE (ch));
+ if (ch == EOF)
{
- state = -2;
- return (do_scrub_next_char (get, unget));
+ as_warn ("EOF in comment: Newline inserted");
+ return '\n';
}
- else
+ if (ch < '0' || ch > '9' || not_cpp_line)
{
- (*unget) (ch2);
+ /* Non-numerics: Eat whole comment line */
+ while (ch != EOF && !IS_NEWLINE (ch))
+ ch = (*get) ();
+ if (ch == EOF)
+ as_warn ("EOF in Comment: Newline inserted");
+ state = 0;
+ return '\n';
}
- } /* bad hack */
-
- do
- ch = (*get) ();
- while (ch != EOF && IS_WHITESPACE (ch));
- if (ch == EOF)
- {
- as_warn ("EOF in comment: Newline inserted");
- return '\n';
- }
- if (ch < '0' || ch > '9')
- {
- /* Non-numerics: Eat whole comment line */
- while (ch != EOF && !IS_NEWLINE (ch))
- ch = (*get) ();
- if (ch == EOF)
- as_warn ("EOF in Comment: Newline inserted");
- state = 0;
- return '\n';
+ /* Numerics begin comment. Perhaps CPP `# 123 "filename"' */
+ (*unget) (ch);
+ old_state = 4;
+ state = -1;
+ out_string = "\t.appline ";
+ return *out_string++;
}
- /* Numerics begin comment. Perhaps CPP `# 123 "filename"' */
- (*unget) (ch);
- old_state = 4;
- state = -1;
- out_string = ".line ";
- return *out_string++;
+ /* We have a line comment character which is not at the start of
+ a line. If this is also a normal comment character, fall
+ through. Otherwise treat it as a default character. */
+ if (strchr (comment_chars, ch) == NULL)
+ goto de_fault;
+ /* Fall through. */
case LEX_IS_COMMENT_START:
do
ch = (*get) ();
return '\n';
case LEX_IS_SYMBOL_COMPONENT:
+ if (state == 10)
+ {
+ /* This is a symbol character following another symbol
+ character, with whitespace in between. We skipped the
+ whitespace earlier, so output it now. */
+ (*unget) (ch);
+ state = 3;
+ return ' ';
+ }
if (state == 3)
state = 9;
/* Fall through. */
state = 3;
return ch;
}
+ else if (state == 10)
+ {
+ state = 3;
+ return ch;
+ }
else
{
return ch; /* Opcode or operands already */
#endif
-/*
- * Local Variables:
- * comment-column: 0
- * fill-column: 131
- * End:
- */
-
/* end of app.c */