aboutsummaryrefslogtreecommitdiff
path: root/gnu/gas/app.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/gas/app.c')
-rw-r--r--gnu/gas/app.c392
1 files changed, 392 insertions, 0 deletions
diff --git a/gnu/gas/app.c b/gnu/gas/app.c
new file mode 100644
index 000000000000..a0ec8a28e808
--- /dev/null
+++ b/gnu/gas/app.c
@@ -0,0 +1,392 @@
+/* This is the Assembler Pre-Processor
+ Copyright (C) 1987 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 1, 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.
+
+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, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* 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>;.file <filename> pair.
+ This needs better error-handling.
+ */
+#include <stdio.h>
+#ifdef USG
+#define bzero(s,n) memset(s,0,n)
+#endif
+#if !defined(__STDC__) && !defined(const)
+#define const /* Nothing */
+#endif
+
+static char lex [256];
+static const char symbol_chars[] =
+ "$._ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+
+extern const char comment_chars[];
+extern const char line_comment_chars[];
+
+#define LEX_IS_SYMBOL_COMPONENT (1)
+#define LEX_IS_WHITESPACE (2)
+#define LEX_IS_LINE_SEPERATOR (4)
+#define LEX_IS_COMMENT_START (8) /* JF added these two */
+#define LEX_IS_LINE_COMMENT_START (16)
+#define IS_SYMBOL_COMPONENT(c) (lex [c] & LEX_IS_SYMBOL_COMPONENT)
+#define IS_WHITESPACE(c) (lex [c] & LEX_IS_WHITESPACE)
+#define IS_LINE_SEPERATOR(c) (lex [c] & LEX_IS_LINE_SEPERATOR)
+#define IS_COMMENT(c) (lex [c] & LEX_IS_COMMENT_START)
+#define IS_LINE_COMMENT(c) (lex [c] & LEX_IS_LINE_COMMENT_START)
+
+void
+do_scrub_begin()
+{
+ const char *p;
+
+ bzero (lex, sizeof(lex)); /* Trust NOBODY! */
+ lex [' '] |= LEX_IS_WHITESPACE;
+ lex ['\t'] |= LEX_IS_WHITESPACE;
+ for (p =symbol_chars;*p;++p)
+ lex [*p] |= LEX_IS_SYMBOL_COMPONENT;
+ lex ['\n'] |= LEX_IS_LINE_SEPERATOR;
+#ifdef DONTDEF
+ lex [':'] |= LEX_IS_LINE_SEPERATOR;
+#endif
+ lex [';'] |= LEX_IS_LINE_SEPERATOR;
+ for (p=comment_chars;*p;p++)
+ lex[*p] |= LEX_IS_COMMENT_START;
+ for (p=line_comment_chars;*p;p++)
+ lex[*p] |= LEX_IS_LINE_COMMENT_START;
+}
+
+FILE *scrub_file;
+
+int
+scrub_from_file()
+{
+ return getc(scrub_file);
+}
+
+void
+scrub_to_file(ch)
+int ch;
+{
+ ungetc(ch,scrub_file);
+}
+
+char *scrub_string;
+char *scrub_last_string;
+
+int
+scrub_from_string()
+{
+ return scrub_string == scrub_last_string ? EOF : *scrub_string++;
+}
+
+void
+scrub_to_string(ch)
+int ch;
+{
+ *--scrub_string=ch;
+}
+
+int
+do_scrub_next_char(get,unget)
+int (*get)();
+void (*unget)();
+/* FILE *fp; */
+{
+ /* State 0: beginning of normal line
+ 1: After first whitespace on normal line (flush more white)
+ 2: After first non-white on normal line (keep 1white)
+ 3: after second white on normal line (flush white)
+ 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 .file, put out string.
+ 8: After putting out a .file string, flush until newline.
+ -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
+ */
+
+ static state;
+ static old_state;
+ static char *out_string;
+ static char out_buf[20];
+ static add_newlines;
+ int ch;
+
+ if(state==-1) {
+ ch= *out_string++;
+ if(*out_string==0) {
+ state=old_state;
+ old_state=3;
+ }
+ return ch;
+ }
+ if(state==-2) {
+ for(;;) {
+ do ch=(*get)();
+ while(ch!=EOF && ch!='\n' && ch!='*');
+ if(ch=='\n' || ch==EOF)
+ return ch;
+ ch=(*get)();
+ if(ch==EOF || ch=='/')
+ break;
+ (*unget)(ch);
+ }
+ state=old_state;
+ return ' ';
+ }
+ if(state==4) {
+ ch=(*get)();
+ if(ch==EOF || (ch>='0' && ch<='9'))
+ return ch;
+ else {
+ while(ch!=EOF && IS_WHITESPACE(ch))
+ ch=(*get)();
+ if(ch=='"') {
+ (*unget)(ch);
+ out_string="; .file ";
+ old_state=7;
+ state= -1;
+ return *out_string++;
+ } else {
+ while(ch!=EOF && ch!='\n')
+ ch=(*get)();
+ return ch;
+ }
+ }
+ }
+ if(state==5) {
+ ch=(*get)();
+ if(ch=='"') {
+ state=old_state;
+ return '"';
+ } else if(ch=='\\') {
+ state=6;
+ return ch;
+ } else if(ch==EOF) {
+ as_warn("End of file in string: inserted '\"'");
+ state=old_state;
+ (*unget)('\n');
+ return '"';
+ } else {
+ return ch;
+ }
+ }
+ if(state==6) {
+ state=5;
+ ch=(*get)();
+ switch(ch) {
+ /* This is neet. Turn "string
+ more string" into "string\n more string"
+ */
+ case '\n':
+ (*unget)('n');
+ add_newlines++;
+ return '\\';
+
+ case '"':
+ case '\\':
+ case 'b':
+ case 'f':
+ case 'n':
+ case 'r':
+ case 't':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ break;
+ default:
+ as_warn("Unknown escape '\\%c' in string: Ignored",ch);
+ break;
+
+ case EOF:
+ as_warn("End of file in string: '\"' inserted");
+ return '"';
+ }
+ return ch;
+ }
+
+ if(state==7) {
+ ch=(*get)();
+ state=5;
+ old_state=8;
+ return ch;
+ }
+
+ if(state==8) {
+ do ch= (*get)();
+ while(ch!='\n');
+ state=0;
+ return ch;
+ }
+
+ flushchar:
+ ch=(*get)();
+ switch(ch) {
+ case ' ':
+ case '\t':
+ do 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_SEPERATOR(ch)) {
+ (*unget)(ch);
+ goto flushchar;
+ }
+ (*unget)(ch);
+ if(state==0 || state==2) {
+ state++;
+ return ' ';
+ } else goto flushchar;
+
+ case '/':
+ ch=(*get)();
+ if(ch=='*') {
+ for(;;) {
+ do {
+ ch=(*get)();
+ if(ch=='\n')
+ add_newlines++;
+ } while(ch!=EOF && ch!='*');
+ ch=(*get)();
+ if(ch==EOF || ch=='/')
+ break;
+ (*unget)(ch);
+ }
+ if(ch==EOF)
+ as_warn("End of file in '/' '*' string: */ inserted");
+
+ (*unget)(' ');
+ goto flushchar;
+ } else {
+ if(IS_COMMENT('/') || (state==0 && IS_LINE_COMMENT('/'))) {
+ (*unget)(ch);
+ ch='/';
+ goto deal_misc;
+ }
+ if(ch!=EOF)
+ (*unget)(ch);
+ return '/';
+ }
+ break;
+
+ case '"':
+ old_state=state;
+ state=5;
+ return '"';
+ break;
+
+ case '\'':
+ ch=(*get)();
+ if(ch==EOF) {
+ as_warn("End-of-file after a ': \000 inserted");
+ ch=0;
+ }
+ sprintf(out_buf,"(%d)",ch&0xff);
+ old_state=state;
+ state= -1;
+ out_string=out_buf;
+ return *out_string++;
+
+ case ':':
+ if(state!=3)
+ state=0;
+ return ch;
+
+ case '\n':
+ if(add_newlines) {
+ --add_newlines;
+ (*unget)(ch);
+ }
+ case ';':
+ state=0;
+ return ch;
+
+ default:
+ deal_misc:
+ if(state==0 && IS_LINE_COMMENT(ch)) {
+ 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') {
+ while(ch!=EOF && ch!='\n')
+ ch=(*get)();
+ if(ch==EOF)
+ as_warn("EOF in Comment: Newline inserted");
+ state=0;
+ return '\n';
+ }
+ (*unget)(ch);
+ old_state=4;
+ state= -1;
+ out_string=".line ";
+ return *out_string++;
+
+ } else if(IS_COMMENT(ch)) {
+ do ch=(*get)();
+ while(ch!=EOF && ch!='\n');
+ if(ch==EOF)
+ as_warn("EOF in comment: Newline inserted");
+ state=0;
+ return '\n';
+
+ } else if(state==0) {
+ state=2;
+ return ch;
+ } else if(state==1) {
+ state=2;
+ return ch;
+ } else {
+ return ch;
+
+ }
+ case EOF:
+ if(state==0)
+ return ch;
+ as_warn("End-of-File not at end of a line");
+ }
+ return -1;
+}
+
+#ifdef TEST
+
+char comment_chars[] = "|";
+char line_comment_chars[] = "#";
+
+main()
+{
+ int ch;
+
+ app_begin();
+ while((ch=do_scrub_next_char(stdin))!=EOF)
+ putc(ch,stdout);
+}
+
+as_warn(str)
+char *str;
+{
+ fputs(str,stderr);
+ putc('\n',stderr);
+}
+#endif