--- /dev/null
+PLATFORM = 6809
+CC = m6809-unknown-gcc
+# These are wrappers for lwasm and lwar
+ASM = m6809-unknown-as
+AR = m6809-unknown-ar
+LINKER = lwlink
+CFLAGS = -I../../Library/include -I../../Library/include/6502 -Wall -pedantic -fno-strict-aliasing
+COPT = -Os
+LINKER_OPT = --format=raw -L../../Library/libs -lc6809
+LIBGCCDIR = $(dir $(shell $(CC) -print-libgcc-file-name))
+LINKER_OPT += -L$(LIBGCCDIR) -lgcc -m cpp.map
+LINKER_OPT += --script=../util/$(TARGET).link
+ASM_OPT = -o
+CRT0 = ../../Library/libs/crt0_6809.o
+
+OBJS = cpp.o hash.o main.o token1.o token2.o
+
+all: cpp
+
+cpp: main.o cpp.o hash.o token1.o token2.o
+ $(LINKER) -o $@ $(LINKER_OPT) $(CRT0) $(OBJS)
+
+clean realclean:
+ rm -f cpp main.o cpp.o hash.o token1.o token2.o tmp.h *~
+
+maintclean: realclean
+ rm -f token1.h token2.h
+
+main.o: cc.h
+cpp.o: cc.h
+hash.o: cc.h
+tree.o: cc.h
+
+token1.o: token1.h
+token2.o: token2.h
+
+token1.h: token1.tok
+ gperf -aptTc -N is_ctok -H hash1 token1.tok > tmp.h
+ mv tmp.h token1.h
+
+token2.h: token2.tok
+ gperf -aptTc -k1,3 -N is_ckey -H hash2 token2.tok > tmp.h
+ mv tmp.h token2.h
--- /dev/null
+
+#ifndef P
+#if __STDC__
+#define P(x) x
+#else
+#define P(x) ()
+#endif
+#endif
+
+extern void cfatal P((char*));
+extern void cerror P((char*));
+extern void cwarn P((char*));
+extern FILE * open_include P((char*, char*, int));
+
+extern FILE * curfile;
+extern char curword[];
+extern char * c_fname;
+extern int c_lineno;
+extern int alltok;
+extern int dialect;
+
+#define DI_KNR 1
+#define DI_ANSI 2
+
+extern int gettok P((void));
+
+struct token_trans { char * name; int token; };
+struct token_trans * is_ctok P((const char *str, unsigned int len));
+struct token_trans * is_ckey P((const char *str, unsigned int len));
+
+#define WORDSIZE 128
+#define TK_WSPACE 256
+#define TK_WORD 257
+#define TK_NUM 258
+#define TK_FLT 259
+#define TK_QUOT 260
+#define TK_STR 261
+#define TK_FILE 262
+#define TK_LINE 263
+#define TK_COPY 264
+
+#define TKS_CTOK 0x200
+#define TKS_CKEY 0x300
+
+#define TK_NE_OP (TKS_CTOK+ 0)
+#define TK_MOD_ASSIGN (TKS_CTOK+ 1)
+#define TK_AND_OP (TKS_CTOK+ 2)
+#define TK_AND_ASSIGN (TKS_CTOK+ 3)
+#define TK_MUL_ASSIGN (TKS_CTOK+ 4)
+#define TK_INC_OP (TKS_CTOK+ 5)
+#define TK_ADD_ASSIGN (TKS_CTOK+ 6)
+#define TK_DEC_OP (TKS_CTOK+ 7)
+#define TK_SUB_ASSIGN (TKS_CTOK+ 8)
+#define TK_PTR_OP (TKS_CTOK+ 9)
+#define TK_ELLIPSIS (TKS_CTOK+10)
+#define TK_DIV_ASSIGN (TKS_CTOK+11)
+#define TK_LEFT_OP (TKS_CTOK+12)
+#define TK_LEFT_ASSIGN (TKS_CTOK+13)
+#define TK_LE_OP (TKS_CTOK+14)
+#define TK_EQ_OP (TKS_CTOK+15)
+#define TK_GE_OP (TKS_CTOK+16)
+#define TK_RIGHT_OP (TKS_CTOK+17)
+#define TK_RIGHT_ASSIGN (TKS_CTOK+18)
+#define TK_XOR_ASSIGN (TKS_CTOK+19)
+#define TK_OR_ASSIGN (TKS_CTOK+20)
+#define TK_OR_OP (TKS_CTOK+21)
+
+#define TK_AUTO (TKS_CKEY+ 0)
+#define TK_BREAK (TKS_CKEY+ 1)
+#define TK_CASE (TKS_CKEY+ 2)
+#define TK_CHAR (TKS_CKEY+ 3)
+#define TK_CONST (TKS_CKEY+ 4)
+#define TK_CONTINUE (TKS_CKEY+ 5)
+#define TK_DEFAULT (TKS_CKEY+ 6)
+#define TK_DO (TKS_CKEY+ 7)
+#define TK_DOUBLE (TKS_CKEY+ 8)
+#define TK_ELSE (TKS_CKEY+ 9)
+#define TK_ENUM (TKS_CKEY+10)
+#define TK_EXTERN (TKS_CKEY+11)
+#define TK_FLOAT (TKS_CKEY+12)
+#define TK_FOR (TKS_CKEY+13)
+#define TK_GOTO (TKS_CKEY+14)
+#define TK_IF (TKS_CKEY+15)
+#define TK_INT (TKS_CKEY+16)
+#define TK_LONG (TKS_CKEY+17)
+#define TK_REGISTER (TKS_CKEY+18)
+#define TK_RETURN (TKS_CKEY+19)
+#define TK_SHORT (TKS_CKEY+20)
+#define TK_SIGNED (TKS_CKEY+21)
+#define TK_SIZEOF (TKS_CKEY+22)
+#define TK_STATIC (TKS_CKEY+23)
+#define TK_STRUCT (TKS_CKEY+24)
+#define TK_SWITCH (TKS_CKEY+25)
+#define TK_TYPEDEF (TKS_CKEY+26)
+#define TK_UNION (TKS_CKEY+27)
+#define TK_UNSIGNED (TKS_CKEY+28)
+#define TK_VOID (TKS_CKEY+29)
+#define TK_VOLATILE (TKS_CKEY+30)
+#define TK_WHILE (TKS_CKEY+31)
+
+#define MAX_INCLUDE 64 /* Nested includes */
+#define MAX_DEFINE 64 /* Nested defines */
+
+extern char * set_entry P((int,char*,void*));
+extern void * read_entry P((int,char*));
+
+struct define_item
+{
+ struct define_arg * next;
+ char * name;
+ int arg_count; /* -1 = none; >=0 = brackets with N args */
+ int in_use; /* Skip this one for looking up #defines */
+ int varargs; /* No warning if unexpected arguments. */
+ char value[1]; /* [arg,]*value */
+};
--- /dev/null
+
+#include <stdio.h>
+#include <string.h>
+#ifdef __STDC__
+#include <stdlib.h>
+#else
+#include <malloc.h>
+#endif
+#include "cc.h"
+
+#define CPP_DEBUG 0 /* LOTS of junk to stderr. */
+
+/*
+ * This file comprises the 'guts' of a C preprocessor.
+ *
+ * Functions exported from this file:
+ * gettok() Returns the next token from the source
+ * curword contains the text of the token
+ *
+ * Variables
+ * curword Contains the text of the last token parsed.
+ * curfile Currently open primary file
+ * c_fname Name of file being parsed
+ * c_lineno Current line number in file being parsed.
+ *
+ * alltok Control flag for the kind of tokens you want (C or generic)
+ * dialect Control flag to change the preprocessor for Ansi C.
+ *
+ * TODO:
+ * #asm -> asm("...") translation.
+ * ?: in #if expressions
+ * Complete #line directive.
+ * \n in "\n" in a stringized argument.
+ * Comments in stringized arguments should be deleted.
+ *
+ * Poss: Seperate current directory for #include from errors (#line).
+ * (For editors that hunt down source files)
+ * Poss: C99 Variable macro args.
+ */
+
+#define KEEP_SPACE 0
+#define SKIP_SPACE 1
+
+#define EOT 4
+#define SYN 22
+
+char curword[WORDSIZE];
+int alltok = 0;
+int dialect = 0;
+
+FILE * curfile;
+char * c_fname;
+int c_lineno = 0;
+
+#ifdef __BCC__
+typedef long int_type; /* Used for preprocessor expressions */
+#else
+typedef int int_type; /* Used for preprocessor expressions */
+#endif
+static int curtok = 0; /* Used for preprocessor expressions */
+
+static int fi_count = 0;
+static FILE * saved_files[MAX_INCLUDE];
+static char * saved_fname[MAX_INCLUDE];
+static int saved_lines[MAX_INCLUDE];
+
+static char * def_ptr = 0;
+static char * def_start = 0;
+static struct define_item * def_ref = 0;
+
+static int def_count =0;
+static char * saved_def[MAX_DEFINE];
+static char * saved_start[MAX_DEFINE];
+static long saved_unputc[MAX_DEFINE];
+static struct define_item * saved_ref[MAX_DEFINE];
+
+static long unputc = 0;
+
+static int last_char = '\n';
+static int in_preproc = 0;
+static int dont_subst = 0;
+static int quoted_str = 0;
+
+static int if_count = 0;
+static int if_false = 0;
+static int if_has_else = 0;
+static int if_hidden = 0;
+static unsigned int if_stack = 0;
+
+struct arg_store {
+ char * name;
+ char * value;
+ int in_define;
+};
+
+static int chget P((void));
+static int chget_raw P((void));
+static void unchget P((int));
+static int gettok_nosub P((void));
+static int get_onetok P((int));
+static int pgetc P((void));
+static int do_preproc P((void));
+static int do_proc_copy_hashline P((void));
+static int do_proc_if P((int));
+static void do_proc_include P((void));
+static void do_proc_define P((void));
+static void do_proc_undef P((void));
+static void do_proc_else P((void));
+static void do_proc_endif P((void));
+static void do_proc_tail P((void));
+static int get_if_expression P((void));
+static int_type get_expression P((int));
+static int_type get_exp_value P((void));
+static void gen_substrings P((char *, char *, int, int));
+static char * insert_substrings P((char *, struct arg_store *, int));
+
+int
+gettok()
+{
+ int ch;
+
+ for(;;)
+ {
+ /* Tokenised C-Preprocessing */
+ if (!quoted_str)
+ {
+ if (alltok)
+ ch = get_onetok(KEEP_SPACE);
+ else
+ ch = get_onetok(SKIP_SPACE);
+
+ if( ch == '"' || ch == '\'' )
+ quoted_str = ch;
+
+ if( ch == TK_WORD )
+ {
+ struct token_trans *p = is_ckey(curword, strlen(curword)) ;
+ if( p )
+ return p->token;
+ }
+
+ if (ch == '\n') continue;
+ return ch;
+ }
+
+ /* Special for quoted strings */
+ *curword = '\0';
+ ch = chget();
+ if( ch == EOF ) return ch;
+
+ *curword = ch;
+ curword[1] = '\0';
+
+ if( ch == quoted_str ) {
+ if( ch == '"' )
+ {
+ if (dialect == DI_ANSI) {
+ /* Found a terminator '"' check for ansi continuation */
+ while( (ch = pgetc()) <= ' ' && ch != EOF) ;
+ if( ch == '"' ) continue;
+ unchget(ch);
+ *curword = '"';
+ curword[1] = '\0';
+ }
+
+ quoted_str = 0;
+ return '"';
+ } else {
+ quoted_str = 0;
+ return ch;
+ }
+ }
+ if( ch == '\n' ) {
+ quoted_str = 0;
+ unchget(ch); /* Make sure error line is right */
+ return ch;
+ }
+ if( ch == '\\' ) {
+ unchget(ch);
+ ch = get_onetok(KEEP_SPACE);
+ return ch;
+ }
+ return TK_STR;
+ }
+}
+
+static int
+gettok_nosub()
+{ int rv; dont_subst++; rv=get_onetok(SKIP_SPACE); dont_subst--; return rv; }
+
+static int
+get_onetok(keep)
+int keep;
+{
+ char * p;
+ int state;
+ int ch, cc;
+
+Try_again:
+ *(p=curword) = '\0';
+ state=cc=ch=0;
+
+ /* First skip whitespace, if the arg says so then we need to keep it */
+ while( (ch = pgetc()) == ' ' || ch == '\t' )
+ {
+ if (keep == KEEP_SPACE) {
+ if( p < curword + WORDSIZE-1 ) {
+ *p++ = ch; /* Clip to WORDSIZE */
+ *p = '\0';
+ }
+ }
+ }
+
+ if( ch > 0xFF ) return ch;
+ if( p != curword ) { unchget(ch); return TK_WSPACE; }
+ if( ch == '\n') return ch;
+ if( ch == EOF ) return ch;
+ if( ch >= 0 && ch < ' ' ) goto Try_again;
+
+ for(;;)
+ {
+ switch(state)
+ {
+ case 0: if( (ch >= 'A' && ch <= 'Z')
+ || (ch >= 'a' && ch <= 'z')
+ || ch == '_' || ch == '$' )
+ state = 1;
+ else if(ch == '0')
+ state = 2;
+ else if(ch >= '1' && ch <= '9')
+ state = 5;
+ else
+ goto break_break;
+ break;
+ case 1: if( (ch >= '0' && ch <= '9')
+ || (ch >= 'A' && ch <= 'Z')
+ || (ch >= 'a' && ch <= 'z')
+ || ch == '_' || ch == '$' )
+ break;
+ else
+ goto break_break;
+ case 2: if( ch >= '0' && ch <= '7')
+ state = 3;
+ else if( ch == 'x' || ch == 'X' )
+ state = 4;
+ else
+ goto break_break;
+ break;
+ case 3: if( ch >= '0' && ch <= '7')
+ break;
+ else
+ goto break_break;
+ case 4: if( (ch >= '0' && ch <= '9')
+ || (ch >= 'A' && ch <= 'F')
+ || (ch >= 'a' && ch <= 'f') )
+ break;
+ else
+ goto break_break;
+ case 5:
+ case 6: if( ch >= '0' && ch <= '9')
+ ;
+ else if( ch == '.' && state != 6 )
+ state = 6;
+ else if( ch == 'e' || ch == 'E' )
+ state = 7;
+ else
+ goto break_break;
+ break;
+ case 7: if( ch == '+' || ch == '-' )
+ break;
+ state = 8;
+ /* FALLTHROUGH */
+ case 8: if( ch >= '0' && ch <= '9')
+ break;
+ else
+ goto break_break;
+ }
+ if( cc < WORDSIZE-1 ) *p++ = ch; /* Clip to WORDSIZE */
+ *p = '\0'; cc++;
+ ch = chget();
+ if (ch == SYN) ch = chget();
+ }
+break_break:
+ /* Numbers */
+ if( state >= 2 )
+ {
+ if( state < 6 )
+ {
+ if( ch == 'u' || ch == 'U' )
+ {
+ if( cc < WORDSIZE-1 ) *p++ = ch; /* Clip to WORDSIZE */
+ *p = '\0'; cc++;
+ ch = chget();
+ }
+ if( ch == 'l' || ch == 'L' )
+ {
+ if( cc < WORDSIZE-1 ) *p++ = ch; /* Clip to WORDSIZE */
+ *p = '\0'; cc++;
+ }
+ else unchget(ch);
+ return TK_NUM;
+ }
+ unchget(ch);
+ return TK_FLT;
+ }
+
+ /* Words */
+ if( state == 1 )
+ {
+ struct define_item * ptr;
+ unchget(ch);
+ if( !dont_subst
+ && (ptr = read_entry(0, curword)) != 0
+ && !ptr->in_use
+ )
+ {
+ if ( def_count >= MAX_DEFINE ) {
+ cwarn("Preprocessor recursion overflow");
+ return TK_WORD;
+ } else if( ptr->arg_count >= 0 )
+ {
+ /* An open bracket must follow the word */
+ int ch1 = 0;
+ while ((ch = chget()) == ' ' || ch == '\t' ) ch1 = ch;
+ if (ch != '(') {
+ unchget(ch);
+ if (ch1) unchget(ch1);
+ return TK_WORD;
+ }
+
+ /* We have arguments to process so lets do so. */
+ gen_substrings(ptr->name, ptr->value, ptr->arg_count, ptr->varargs);
+
+ /* Don't mark macros with arguments as in use, it's very
+ * difficult to say what the correct result would be so
+ * I'm letting the error happen. Also if I do block
+ * recursion then it'll also block 'pseudo' recursion
+ * where the arguments have a call to this macro.
+ *
+ def_ref = ptr;
+ ptr->in_use = 1;
+ */
+ }
+ else if (ptr->value[0])
+ {
+ /* Simple direct substitution; note the shortcut (above) for
+ * macros that are defined as null */
+ saved_ref[def_count] = def_ref;
+ saved_def[def_count] = def_ptr;
+ saved_start[def_count] = def_start;
+ saved_unputc[def_count] = unputc;
+ def_count++;
+ unputc = 0;
+ def_ref = ptr;
+ def_ptr = ptr->value;
+ def_start = 0;
+ ptr->in_use = 1;
+ }
+ goto Try_again;
+ }
+ return TK_WORD;
+ }
+
+ /* Quoted char for preprocessor expressions */
+ if(in_preproc && ch == '\'' )
+ {
+ *p++ = ch; ch = chget();
+ for(;;)
+ {
+ if( cc < WORDSIZE-1 ) *p++ = ch; /* Clip to WORDSIZE */
+ *p = '\0'; cc++;
+ if( ch == '\'' || ch == '\n' ) break;
+
+ if( ch == '\\' )
+ {
+ ch = chget();
+ if( cc < WORDSIZE-1 ) *p++ = ch; /* Clip to WORDSIZE */
+ *p = '\0'; cc++;
+ }
+ ch = chget();
+ }
+ ch = TK_QUOT;
+ }
+
+ /* Collect and translate \xyx strings, (should probably translate these
+ * all to some standard form (eg \ooo plus \N )
+ *
+ * ___________________________________________________________________
+ * | new-line NL (LF) \n| audible alert BEL \a |
+ * | horizontal tab HT \t| question mark ? \? |
+ * | vertical tab VT \v| double quote " \" |
+ * | backspace BS \b| octal escape ooo \ooo|
+ * | carriage return CR \r| hexadecimal escape hh \xhh|
+ * | formfeed FF \f| backslash \ \\ |
+ * | single quote ' \'| |
+ * |_______________________________|_________________________________|
+ */
+
+ if( ch == '\\' )
+ {
+ int i;
+
+ *p++ = ch; ch = chget();
+ if (ch >= '0' && ch <= '7' ) {
+ for(i=0; i<3; i++) {
+ if (ch >= '0' && ch <= '7' ) {
+ *p++ = ch; ch = chget();
+ }
+ }
+ unchget(ch);
+ } else if (ch == 'x' || ch == 'X') {
+ *p++ = ch; ch = chget();
+ for(i=0; i<2; i++) {
+ if ( (ch >= '0' && ch <= '9' ) ||
+ (ch >= 'A' && ch <= 'F' ) ||
+ (ch >= 'a' && ch <= 'f' ) ) {
+ *p++ = ch; ch = chget();
+ }
+ }
+ unchget(ch);
+ } else if (ch == '?') {
+ p[-1] = '?';
+ } else if (ch != '\n' && ch != EOF) {
+ *p++ = ch;
+ } else
+ unchget(ch);
+ *p = '\0';
+ return TK_STR;
+ }
+
+ /* Possible composite tokens */
+ if( ch > ' ' && ch <= '~' )
+ {
+ struct token_trans *tt;
+ *curword = cc = ch;
+
+ for(state=1; ; state++)
+ {
+ curword[state] = ch = chget();
+ if( !(tt=is_ctok(curword, state+1)) )
+ {
+ unchget(ch);
+ curword[state] = '\0';
+ return cc;
+ }
+ cc=tt->token;
+ }
+ }
+ return ch;
+}
+
+static int
+pgetc()
+{
+ int ch, ch1;
+
+ for(;;)
+ {
+ if ((ch = chget()) == EOF) return ch;
+
+ if( !in_preproc && last_char == '\n' && ch == '#' )
+ {
+ in_preproc = 1;
+ ch = do_preproc();
+ in_preproc = 0;
+ if(if_false || ch == 0) continue;
+
+ last_char = '\n';
+ return ch;
+ }
+ if( last_char != '\n' || (ch != ' ' && ch != '\t') )
+ last_char = ch;
+
+ /* Remove comments ... */
+ if( ch != '/' )
+ { if(if_false && !in_preproc) continue; return ch; }
+ ch1 = chget(); /* Allow "/\\\n*" as comment start too!? */
+
+ if( ch1 == '/' ) /* Double slash style comments */
+ {
+ do { ch = chget(); } while(ch != '\n' && ch != EOF);
+ return ch; /* Keep the return. */
+ }
+
+ if( ch1 != '*' )
+ {
+ unchget(ch1);
+ if(if_false && !in_preproc) continue;
+ return ch;
+ }
+
+ for(;;)
+ {
+ if( ch == '*' )
+ {
+ ch = chget();
+ if( ch == EOF ) return EOF;
+ if( ch == '/' ) break;
+ }
+ else ch = chget();
+ }
+ if (dialect == DI_ANSI)
+ return ' '; /* If comments become " " */
+ else return SYN; /* Comments become nulls, but we need a
+ * marker so I can do token concat properly. */
+ }
+}
+
+/* This function handles the first and second translation phases of Ansi-C */
+static int
+chget()
+{
+ int ch, ch1;
+ for(;;) {
+ ch = chget_raw();
+ if (ch == '\\') {
+ ch1 = chget_raw();
+ if (ch1 == '\n') continue;
+ unchget(ch1);
+ }
+
+ /* Ansi trigraphs -- Ewww, it needs lots of 'unchget' space too. */
+ if (dialect == DI_ANSI && ch == '?') {
+ ch1 = chget_raw();
+ if (ch1 != '?')
+ unchget(ch1);
+ else {
+ static char trig1[] = "()<>/!'-=";
+ static char trig2[] = "[]{}\\|^~#";
+ char * s;
+ ch1 = chget_raw();
+ s = strchr(trig1, ch1);
+ if (s) {
+ unchget(trig2[s-trig1]); /* Unchget so that ??/ can be used as */
+ continue; /* a real backslash at EOL. */
+ } else {
+ unchget(ch1);
+ unchget('?');
+ }
+ }
+ }
+
+ return ch;
+ }
+}
+
+static void
+unchget(ch)
+{
+#if CPP_DEBUG
+ fprintf(stderr, "\b", ch);
+#endif
+ if(ch == 0) return; /* Hummm */
+ if(ch == EOF) ch=EOT; /* EOF is pushed back as a normal character. */
+ ch &= 0xFF;
+
+ if(unputc&0xFF000000)
+ cerror("Internal character pushback stack overflow");
+ else unputc = (unputc<<8) + (ch);
+ if( ch == '\n' ) c_lineno--;
+}
+
+static int
+chget_raw()
+#if CPP_DEBUG
+{
+ int ch;
+static int last_def = 0;
+static int last_fi = 0;
+ if (last_fi != fi_count) fprintf(stderr, "<INC%d>", fi_count);
+ if (last_def != def_count) fprintf(stderr, "<DEF%d>", def_count);
+ last_def = def_count; last_fi = fi_count;
+
+ ch = realchget();
+ if (ch == EOF) fprintf(stderr, "<EOF>"); else fprintf(stderr, "%c", ch);
+
+ if (last_def != def_count) fprintf(stderr, "<DEF%d>", def_count);
+ if (last_fi != fi_count) fprintf(stderr, "<INC%d>", fi_count);
+ last_def = def_count; last_fi = fi_count;
+
+ return ch;
+}
+
+static int
+realchget()
+#endif
+{
+ int ch;
+ for(;;)
+ {
+ if( unputc )
+ {
+ if((unputc&0xFF)==EOT && in_preproc) return '\n';
+ ch=(unputc&0xFF); unputc>>=8;
+ if( ch == EOT ) ch = EOF;
+ if( ch == '\n' ) c_lineno++;
+ return ch;
+ }
+
+ if( def_ptr )
+ {
+ ch = *def_ptr++; if(ch) return (unsigned char)ch;
+ if( def_start ) free(def_start);
+ if( def_ref ) def_ref->in_use = 0;
+
+ def_count--;
+ def_ref = saved_ref[def_count];
+ def_ptr = saved_def[def_count];
+ def_start = saved_start[def_count];
+ unputc = saved_unputc[def_count];
+ continue;
+ }
+
+ ch = getc(curfile);
+ if( ch == EOF && fi_count != 0)
+ {
+ fclose(curfile);
+ fi_count--;
+ curfile = saved_files[fi_count];
+ if(c_fname) free(c_fname);
+ c_fname = saved_fname[fi_count];
+ c_lineno = saved_lines[fi_count];
+ ch = '\n'; /* Ensure end of line on end of file */
+ }
+ else if( ch == '\n' ) c_lineno++;
+
+ /* Treat all control characters, except the standard whitespace
+ * characters of TAB and NL as completely invisible.
+ */
+ if( ch >= 0 && ch < ' ' && ch!='\n' && ch!='\t' && ch!=EOF ) continue;
+
+ if( ch == EOF ) { unchget(ch); return '\n'; } /* Ensure EOL before EOF */
+ return (unsigned char)ch;
+ }
+}
+
+static int
+do_preproc()
+{
+ int val, no_match=0;
+
+ if( (val=get_onetok(SKIP_SPACE)) == TK_WORD )
+ {
+ if( strcmp(curword, "ifdef") == 0 )
+ do_proc_if(0);
+ else if( strcmp(curword, "ifndef") == 0 )
+ do_proc_if(1);
+ else if( strcmp(curword, "if") == 0 )
+ do_proc_if(2);
+ else if( strcmp(curword, "elif") == 0 )
+ do_proc_if(3);
+ else if( strcmp(curword, "else") == 0 )
+ do_proc_else();
+ else if( strcmp(curword, "endif") == 0 )
+ do_proc_endif();
+ else if(if_false)
+ no_match=1;
+ else
+ {
+ if( strcmp(curword, "include") == 0 )
+ do_proc_include();
+ else if( strcmp(curword, "define") == 0 )
+ do_proc_define();
+ else if( strcmp(curword, "undef") == 0 )
+ do_proc_undef();
+ else if( strcmp(curword, "error") == 0 ) {
+ strcpy(curword, "#error");
+ do_proc_copy_hashline(); pgetc();
+ cerror(curword);
+ } else if( strcmp(curword, "warning") == 0 ) {
+ strcpy(curword, "#warning");
+ do_proc_copy_hashline(); pgetc();
+ cwarn(curword);
+ } else if( strcmp(curword, "pragma") == 0 ) {
+ do_proc_copy_hashline(); pgetc();
+ /* Ignore #pragma ? */
+ } else if( strcmp(curword, "line") == 0 ) {
+ do_proc_copy_hashline(); pgetc();
+ /* Ignore #line for now. */
+ } else if( strcmp(curword, "asm") == 0 ) {
+ alltok |= 0x100;
+ return do_proc_copy_hashline();
+ } else if( strcmp(curword, "endasm") == 0 ) {
+ alltok &= ~0x100;
+ return do_proc_copy_hashline();
+ } else
+ no_match=1;
+ }
+ } else if (!val) {
+ /* Empty directives used to denote that a file is to be run through
+ * the preprocessor in K&R. Do not complain if we got no token. */
+ no_match=1;
+ }
+
+ if( no_match )
+ {
+ if(!if_false) cerror("Unknown preprocessor directive");
+ while( val != '\n' ) val = pgetc();
+ }
+
+ *curword = 0; /* Just in case */
+ return 0;
+}
+
+static int
+do_proc_copy_hashline()
+{
+ int off, ch;
+
+ off = strlen(curword);
+
+ while( (ch=pgetc()) != '\n' )
+ {
+ if( off < WORDSIZE ) curword[off++] = ch;
+ }
+ if( off == WORDSIZE )
+ {
+ cerror("Preprocessor directive too long");
+ curword[WORDSIZE-1] = '\0';
+ }
+ else
+ curword[off] = '\0';
+
+ unchget('\n');
+ return TK_COPY;
+}
+
+static void
+do_proc_include()
+{
+ int ch, ch1;
+ char * p;
+ FILE * fd;
+
+ ch = get_onetok(SKIP_SPACE);
+ if( ch == '<' || ch == '"' )
+ {
+ if( ch == '"' ) ch1 = ch; else ch1 = '>';
+ p = curword;
+ while(p< curword+WORDSIZE-1)
+ {
+ ch = pgetc();
+ if( ch == '\n' ) break;
+ if( ch == ch1 )
+ {
+ *p = '\0';
+ p = strdup(curword);
+
+ do { ch1 = pgetc(); } while(ch1 == ' ' || ch1 == '\t');
+ unchget(ch1);
+ do_proc_tail();
+
+ saved_files[fi_count] = curfile;
+ saved_fname[fi_count] = c_fname;
+ saved_lines[fi_count] = c_lineno;
+
+ fd = open_include(p, "r", (ch=='"'));
+ if( fd ) {
+ fi_count++;
+ curfile = fd;
+ } else
+ cerror("Cannot open include file");
+
+ return;
+ }
+ *p++ = ch;
+ }
+ }
+ cerror("Bad #include command");
+ while(ch != '\n') ch = pgetc();
+ return;
+}
+
+static void
+do_proc_define()
+{
+ int ch, ch1;
+ struct define_item * ptr, * old_value = 0;
+ int cc, len;
+ char name[WORDSIZE];
+
+ if( (ch=gettok_nosub()) == TK_WORD )
+ {
+ strcpy(name, curword);
+ ptr = read_entry(0, name);
+ if(ptr)
+ {
+ set_entry(0, name, (void*)0); /* Unset var */
+ if (ptr->in_use)
+ /* Eeeek! This shouldn't happen; so just let it leak. */
+ cwarn("macro redefined while it was in use!?");
+ else
+ old_value = ptr;
+ }
+
+ /* Skip blanks */
+ for(ch=ch1=pgetc(); ch == ' ' || ch == '\t' ; ch=pgetc()) ;
+
+ len = WORDSIZE;
+ ptr = malloc(sizeof(struct define_item) + WORDSIZE);
+ if(ptr==0) cfatal("Preprocessor out of memory");
+ ptr->value[cc=0] = '\0';
+
+ /* Add in arguments */
+ if( ch1 == '(' )
+ {
+ ptr->arg_count=0;
+ for(;;)
+ {
+ ch=gettok_nosub();
+ if( ptr->arg_count==0 && ch == ')' ) break;
+ if( ch == TK_WORD )
+ {
+ if( cc+strlen(curword)+4 >= len)
+ {
+ len = cc + WORDSIZE;
+ ptr = (struct define_item *) realloc(ptr, sizeof(struct define_item) + len);
+ if(ptr==0) cfatal("Preprocessor out of memory");
+ }
+ if( cc+strlen(curword) < len)
+ {
+ strcpy(ptr->value+cc, curword);
+ cc+=strlen(curword);
+ strcpy(ptr->value+cc, ",");
+ cc++;
+ ptr->arg_count++;
+ ch=gettok_nosub();
+ if( ch == TK_ELLIPSIS ) {
+ ptr->varargs = 1;
+ ch=gettok_nosub();
+ if (ch == ',') ch = '*'; /* Force error if not ')' */
+ }
+ if( ch == ')' ) break;
+ if( ch == ',' ) continue;
+ }
+ }
+ cerror("Bad #define command");
+ free(ptr);
+ while(ch != '\n') ch = pgetc();
+ set_entry(0, name, (void*)old_value); /* Return var to old. */
+ return;
+ }
+ while((ch=pgetc())==' ' || ch=='\t');
+ }
+ else ptr->arg_count = -1;
+
+ /* And the substitution string */
+ while(ch != '\n')
+ {
+ if( cc+4 > len )
+ {
+ len = cc + WORDSIZE;
+ ptr = (struct define_item *) realloc(ptr, sizeof(struct define_item) + len);
+ if(ptr==0) cfatal("Preprocessor out of memory");
+ }
+ ptr->value[cc++] = ch;
+ ch = pgetc();
+ }
+ if (cc)
+ ptr->value[cc++] = ' ';/* Byte of lookahead for recursive macros */
+ ptr->value[cc++] = '\0';
+
+#if CPP_DEBUG
+ if (cc == 1)
+ fprintf(stderr, "\n### Define '%s' as null\n", name);
+ else if (ptr->arg_count<0)
+ fprintf(stderr, "\n### Define '%s' as '%s'\n",
+ name, ptr->value);
+ else
+ fprintf(stderr, "\n### Define '%s' as %d args '%s'\n",
+ name, ptr->arg_count, ptr->value);
+#endif
+
+ /* Clip to correct size and save */
+ ptr = (struct define_item *) realloc(ptr, sizeof(struct define_item) + cc);
+ ptr->name = set_entry(0, name, ptr);
+ ptr->in_use = 0;
+ ptr->next = 0;
+
+ if (old_value) {
+ if (strcmp(old_value->value, ptr->value) != 0)
+ cwarn("#define redefined macro");
+ free(old_value);
+ }
+ }
+ else cerror("Bad #define command");
+ while(ch != '\n') ch = pgetc();
+}
+
+static void
+do_proc_undef()
+{
+ int ch;
+ struct define_item * ptr;
+ if( (ch=gettok_nosub()) == TK_WORD )
+ {
+ ptr = read_entry(0, curword);
+ if(ptr)
+ {
+ set_entry(0, curword, (void*)0); /* Unset var */
+ if (ptr->in_use)
+ /* Eeeek! This shouldn't happen; so just let it leak. */
+ cwarn("macro undefined while it was in use!?");
+ else
+ free(ptr);
+ }
+ do_proc_tail();
+ }
+ else
+ {
+ cerror("Bad #undef command");
+ while(ch != '\n') ch = pgetc();
+ }
+}
+
+static int
+do_proc_if(type)
+int type;
+{
+ int ch = 0;
+ if(if_false && if_hidden)
+ {
+ if( type != 3 ) if_hidden++;
+ do_proc_tail();
+ return 0;
+ }
+
+ if( type == 3 )
+ {
+ if( if_count == 0 )
+ cerror("#elif without matching #if");
+ else
+ {
+ if( if_has_else )
+ cerror("#elif following #else for one #if");
+ if( if_has_else || if_false != 1 )
+ {
+ if_false=2;
+ while(ch != '\n') ch = pgetc();
+ return 0;
+ }
+ if_false=0;
+ }
+ if_has_else = 0;
+ }
+ if(if_false)
+ {
+ if( type != 3 ) if_hidden++;
+ do_proc_tail();
+ }
+ else
+ {
+ if( type != 3 )
+ {
+ if_count++;
+ if_stack <<= 1;
+ if_stack |= if_has_else;
+ if_has_else = 0;
+ }
+ if(type > 1)
+ {
+ ch = get_if_expression();
+ if_false=!ch;
+ }
+ else
+ {
+ ch = gettok_nosub();
+ if( ch == TK_WORD )
+ {
+ do_proc_tail();
+ if_false = (read_entry(0, curword) == 0);
+ if(type == 1) if_false = !if_false;
+ }
+ else
+ {
+ cerror("Bad #if command");
+ if_false = 0;
+ while(ch != '\n') ch = pgetc();
+ }
+ }
+ }
+ return 0;
+}
+
+static void
+do_proc_else()
+{
+ if( if_hidden == 0 )
+ {
+ if( if_count == 0 )
+ cerror("#else without matching #if");
+ else
+ if_false = (if_false^1);
+ if( if_has_else )
+ cerror("Multiple #else's for one #if");
+ if_has_else = 1;
+ }
+ do_proc_tail();
+}
+
+static void
+do_proc_endif()
+{
+ if( if_hidden )
+ if_hidden--;
+ else
+ {
+ if( if_count == 0 )
+ cerror("Unmatched #endif");
+ else
+ {
+ if_count--;
+ if_false=0;
+ if_has_else = (if_stack&1);
+ if_stack >>=1;
+ }
+ }
+ do_proc_tail();
+}
+
+static void
+do_proc_tail()
+{
+ int ch, flg=1;
+ while((ch = pgetc()) != '\n') if(ch > ' ')
+ {
+ if (!if_false && flg)
+ cwarn("Unexpected text following preprocessor command");
+ flg=0;
+ }
+}
+
+static int
+get_if_expression()
+{
+ int value = get_expression(0);
+
+ if (curtok != '\n')
+ do_proc_tail();
+
+ return value;
+}
+
+static int_type
+get_expression(prio)
+int prio;
+{
+ int_type lvalue;
+ int_type rvalue;
+ int no_op = 0;
+
+ curtok = get_onetok(SKIP_SPACE);
+ lvalue = get_exp_value();
+
+ do
+ {
+ switch(curtok)
+ {
+ case '*': case '/': case '%':
+ if (prio >= 10) return lvalue;
+ break;
+ case '+': case '-':
+ if (prio >= 9) return lvalue;
+ break;
+ case TK_RIGHT_OP: case TK_LEFT_OP:
+ if (prio >= 8) return lvalue;
+ break;
+ case '<': case '>': case TK_LE_OP: case TK_GE_OP:
+ if (prio >= 7) return lvalue;
+ break;
+ case TK_EQ_OP: case TK_NE_OP:
+ if (prio >= 6) return lvalue;
+ break;
+ case '&':
+ if (prio >= 5) return lvalue;
+ break;
+ case '^':
+ if (prio >= 4) return lvalue;
+ break;
+ case '|':
+ if (prio >= 3) return lvalue;
+ break;
+ case TK_AND_OP:
+ if (prio >= 2) return lvalue;
+ break;
+ case TK_OR_OP:
+ if (prio >= 1) return lvalue;
+ break;
+ }
+ switch(curtok)
+ {
+ case '*':
+ rvalue = get_expression(10);
+ lvalue *= rvalue;
+ break;
+ case '/':
+ rvalue = get_expression(10);
+ if (rvalue)
+ lvalue /= rvalue;
+ break;
+ case '%':
+ rvalue = get_expression(10);
+ if (rvalue)
+ lvalue %= rvalue;
+ break;
+ case '+':
+ rvalue = get_expression(9);
+ lvalue += rvalue;
+ break;
+ case '-':
+ rvalue = get_expression(9);
+ lvalue -= rvalue;
+ break;
+ case TK_RIGHT_OP:
+ rvalue = get_expression(8);
+ lvalue >>= rvalue;
+ break;
+ case TK_LEFT_OP:
+ rvalue = get_expression(8);
+ lvalue <<= rvalue;
+ break;
+ case '<':
+ rvalue = get_expression(7);
+ lvalue = (lvalue < rvalue);
+ break;
+ case '>':
+ rvalue = get_expression(7);
+ lvalue = (lvalue > rvalue);
+ break;
+ case TK_LE_OP:
+ rvalue = get_expression(7);
+ lvalue = (lvalue <= rvalue);
+ break;
+ case TK_GE_OP:
+ rvalue = get_expression(7);
+ lvalue = (lvalue >= rvalue);
+ break;
+ case TK_EQ_OP:
+ rvalue = get_expression(6);
+ lvalue = (lvalue == rvalue);
+ break;
+ case TK_NE_OP:
+ rvalue = get_expression(6);
+ lvalue = (lvalue != rvalue);
+ break;
+ case '&':
+ rvalue = get_expression(5);
+ lvalue = (lvalue & rvalue);
+ break;
+ case '^':
+ rvalue = get_expression(4);
+ lvalue = (lvalue ^ rvalue);
+ break;
+ case '|':
+ rvalue = get_expression(3);
+ lvalue = (lvalue | rvalue);
+ break;
+ case TK_AND_OP:
+ rvalue = get_expression(2);
+ lvalue = (lvalue && rvalue);
+ break;
+ case TK_OR_OP:
+ rvalue = get_expression(1);
+ lvalue = (lvalue || rvalue);
+ break;
+
+ case '?': /* XXX: To add */
+
+ default:
+ no_op = 1;
+ }
+ }
+ while(prio == 0 && !no_op);
+
+ return lvalue;
+}
+
+static int_type
+get_exp_value()
+{
+ int_type value = 0;
+ int sign = 1;
+
+ if (curtok == '!') {
+ curtok = get_onetok(SKIP_SPACE);
+ return !get_exp_value();
+ }
+ if (curtok == '~') {
+ curtok = get_onetok(SKIP_SPACE);
+ return ~get_exp_value();
+ }
+
+ while (curtok == '+' || curtok == '-') {
+ if (curtok == '-') sign = -sign;
+ curtok = get_onetok(SKIP_SPACE);
+ }
+
+ if (curtok == TK_NUM) {
+ value = strtoul(curword, (void*)0, 0);
+ curtok = get_onetok(SKIP_SPACE);
+ } else if (curtok == TK_QUOT) {
+ value = curword[1];
+ if (value == '\\') {
+ if (curword[2] >= '0' && curword[2] <= '7') {
+ value = curword[2] - '0';
+ if (curword[3] >= '0' && curword[3] <= '7') {
+ value = (value<<3) + curword[3] - '0';
+ if (curword[4] >= '0' && curword[4] <= '7') {
+ value = (value<<3) + curword[4] - '0';
+ }
+ }
+ } else switch(curword[2]) {
+ case 'n': value = '\n'; break;
+ case 'f': value = '\f'; break;
+ case 't': value = '\t'; break;
+ default: value = curword[2]; break;
+ }
+ }
+#ifdef NATIVE_CPP
+ value = (char) value; /* Fix range */
+#elif SIGNED_CHAR
+ value = (signed char) value;
+#else
+ value = (unsigned char) value;
+#endif
+ curtok = get_onetok(SKIP_SPACE);
+ } else if (curtok == TK_WORD) {
+ value = 0;
+ if (strcmp("defined", curword) == 0) {
+ curtok = gettok_nosub();
+ if (curtok == '(' && gettok_nosub() != TK_WORD)
+ cerror("'defined' keyword requires argument");
+ else {
+ value = (read_entry(0, curword) != 0);
+ if (curtok == '(' && gettok_nosub() != ')')
+ cerror("'defined' keyword requires closing ')'");
+ else
+ curtok = get_onetok(SKIP_SPACE);
+ }
+ }
+ else
+ curtok = get_onetok(SKIP_SPACE);
+
+ } else if (curtok == '(') {
+ value = get_expression(0);
+ if (curtok == ')')
+ curtok = get_onetok(SKIP_SPACE);
+ else {
+ curtok = '$';
+ cerror("Expected ')'");
+ }
+ }
+
+ return sign<0 ? -value: value;
+}
+
+void
+gen_substrings(macname, data_str, arg_count, is_vararg)
+char * macname;
+char * data_str;
+int arg_count;
+int is_vararg;
+{
+ char * mac_text = 0;
+ struct arg_store *arg_list;
+ int ac, ch, cc, len;
+
+ int paren_count = 0;
+ int in_quote = 0;
+ int quote_char = 0;
+ int commas_found = 0;
+ int args_found = 0;
+
+ arg_list = malloc(sizeof(struct arg_store) * arg_count);
+ memset(arg_list, 0, sizeof(struct arg_store) * arg_count);
+
+ for(ac=0; *data_str && ac < arg_count; data_str++) {
+ if( *data_str == ',' ) { ac++; continue; }
+
+ if (arg_list[ac].name == 0) cc = len = 0;
+
+ if (cc+2 >= len) {
+ len += 20;
+ arg_list[ac].name = realloc(arg_list[ac].name, len);
+ }
+ arg_list[ac].name[cc++] = *data_str;
+ arg_list[ac].name[cc] = '\0';
+ }
+
+ for(;;) {
+ if ((ch = chget()) == EOF) break;
+ if(in_quote == 2) {
+ in_quote = 1;
+ } else if (in_quote) {
+ if ( ch == quote_char ) in_quote = 0;
+ if ( ch == '\\') in_quote = 2;
+ } else {
+ if ( ch == '(' ) paren_count++;
+ if ( ch == '"' || ch == '\'' ) { in_quote = 1; quote_char = ch; }
+ if (paren_count == 0 && ch == ',' ) {
+ commas_found++;
+ if (commas_found < arg_count)
+ continue;
+ }
+ if ( ch == ')' ) {
+ if (paren_count == 0) break;
+ paren_count--;
+ }
+ }
+ args_found = 1;
+ /* Too many args, deal with, or ignore, the rest. */
+ if (commas_found >= arg_count) {
+ if(arg_count == 0) continue;
+ ac = arg_count-1;
+ } else
+ ac = commas_found;
+
+ if (arg_list[ac].value == 0) {
+ cc = len = 0;
+ arg_list[ac].in_define = def_count;
+ }
+
+ if (cc+2 >= len) {
+ len += 20;
+ arg_list[ac].value = realloc(arg_list[ac].value, len);
+ }
+
+#if 0
+ if (ch == '\n' && cc>0 && arg_list[ac].value[cc-1] == '\n' ) {
+ ... ?
+ }
+#endif
+
+ arg_list[ac].value[cc++] = ch;
+ arg_list[ac].value[cc] = '\0';
+ }
+
+ if (commas_found || args_found) args_found = commas_found+1;
+
+ if( arg_count == 0 && args_found != 0 )
+ cerror("Arguments given to macro without them.");
+ else if( !is_vararg && arg_count != args_found )
+ cwarn("Incorrect number of macro arguments");
+
+ mac_text = insert_substrings(data_str, arg_list, arg_count);
+
+ /*
+ * At this point 'mac_text' contains the full expansion of the macro.
+ *
+ * So we could scan this for calls to this macro and if we find one
+ * that _exactly_ matches this call (including arguments) then we mark
+ * this call's in_use flag.
+ *
+ * OTOH, it would probably be best to throw away this expansion and
+ * pretend we never noticed this macro expansion in the first place.
+ *
+ * Still this is mostly academic as the error trapping works and
+ * recursive macros _with_arguments_ are both rare and unpredictable.
+ */
+
+ if (arg_list) {
+ for (ac=0; ac<arg_count; ac++) {
+ if (arg_list[ac].name) free(arg_list[ac].name);
+ if (arg_list[ac].value) free(arg_list[ac].value);
+ }
+ free(arg_list);
+ }
+
+ saved_ref[def_count] = def_ref;
+ saved_def[def_count] = def_ptr;
+ saved_start[def_count] = def_start;
+ saved_unputc[def_count] = unputc;
+ def_count++;
+ unputc = 0;
+ def_ptr = mac_text;
+ def_start = mac_text;
+ def_ref = 0;
+#if CPP_DEBUG
+ fprintf(stderr, "\n### <DEF%d='%s'>\n", def_count, mac_text);
+#endif
+}
+
+static char *
+insert_substrings(data_str, arg_list, arg_count)
+char * data_str;
+struct arg_store *arg_list;
+int arg_count;
+{
+ int ac, ch;
+ char * p, * s;
+ char * rv = 0;
+ int len = 0;
+ int cc = 0;
+ int in_quote = 0;
+ int quote_char = 0;
+ int ansi_stringize = 0;
+
+#if CPP_DEBUG
+ fprintf(stderr, "\n### Macro substitution in '%s'\n", data_str);
+ for (ac=0; ac<arg_count; ac++) {
+ fprintf(stderr, "### Argument %d (%s) = '%s'\n",
+ ac+1, arg_list[ac].name, arg_list[ac].value);
+ }
+#endif
+
+ rv = malloc(4); *rv = '\0'; len = 4;
+
+ while(*data_str) {
+ p = curword;
+
+ if (dialect == DI_ANSI) {
+ if (in_quote == 2)
+ in_quote = 1;
+ else if (in_quote) {
+ if (*data_str == quote_char) in_quote = 0;
+ if (*data_str == '\\') in_quote = 2;
+ } else {
+ if (*data_str == '"' || *data_str == '\'')
+ { in_quote = 1; quote_char = *data_str; }
+ }
+ }
+
+ if (!in_quote) for(;;) {
+ ch = *data_str;
+ if( (ch >= '0' && ch <= '9')
+ || (ch >= 'A' && ch <= 'Z')
+ || (ch >= 'a' && ch <= 'z')
+ || ch == '_' || ch == '$' )
+ *p++ = *data_str++;
+ else
+ break;
+ }
+
+ if (p == curword) {
+ /* Ansi Stringize and concat */
+ if (*data_str == '#' && dialect != DI_KNR) {
+ if (data_str[1] == '#') {
+ while(cc>0 && (rv[cc-1] == ' ' || rv[cc-1] == '\t'))
+ cc--;
+ data_str+=2;
+ while(*data_str == ' ' || *data_str == '\t')
+ data_str++;
+ if (*data_str == '\0') { /* Hummm */
+ data_str--;
+ cerror("'##' operator at end of macro");
+ }
+ continue;
+ }
+ data_str++;
+ ansi_stringize = 1;
+ continue;
+ }
+
+ if (ansi_stringize) {
+ ansi_stringize = 0;
+ cerror("'#' operator should be followed by a macro argument name");
+ }
+
+ /* Other characters ... */
+ if (cc+2 > len) { len += 20; rv = realloc(rv, len); }
+ rv[cc++] = *data_str++;
+ continue;
+ }
+ *p = '\0'; s = curword;
+ for (ac=0; ac<arg_count; ac++) {
+ if (*curword == arg_list[ac].name[0] &&
+ strcmp(curword, arg_list[ac].name) == 0)
+ {
+ s = arg_list[ac].value;
+ if (!s) s = ""; else
+
+ /* Ansi stringize operation, this is very messy! */
+ if (ansi_stringize) {
+ if (arg_list[ac].in_define) {
+ struct define_item * ptr;
+ if ((ptr = read_entry(0, s)) &&
+ ptr->arg_count == -1) {
+ s = ptr->value;
+ }
+ }
+
+ rv[cc++] = '"';
+ while(*s == ' ' || *s == '\t') s++;
+ while (*s) {
+ if (cc+4 > len) { len += 20; rv = realloc(rv, len); }
+ if (*s == '"') rv[cc++] = '\\';
+ rv[cc++] = *s++;
+ }
+ while(cc>0 && (rv[cc-1] == ' ' || rv[cc-1] == '\t'))
+ cc--;
+ rv[cc++] = '"';
+ rv[cc++] = '\0';
+ ansi_stringize = 0;
+ s = "";
+ break;
+ }
+
+ break;
+ }
+ }
+
+ if (ansi_stringize) {
+ ansi_stringize = 0;
+ cerror("'#' operator should be followed by a macro argument name");
+ }
+
+ if (cc+2+strlen(s) > len) { len += strlen(s)+20; rv = realloc(rv, len); }
+ strcpy(rv+cc, s);
+ cc = strlen(rv);
+ }
+
+ rv[cc] = '\0';
+ return rv;
+}
--- /dev/null
+
+#include <stdio.h>
+#ifdef __STDC__
+#include <stdlib.h>
+#include <string.h>
+#else
+#include <malloc.h>
+#endif
+#include "cc.h"
+
+/*
+ * Two functions:
+ * char * set_entry(int namespace, char * name, void * value);
+ * returns a pointer to the copy of the name;
+ *
+ * void * read_entry(int namespace, char * name);
+ * returns the value;
+ */
+
+struct hashentry
+{
+ struct hashentry * next;
+ void * value;
+ int namespace;
+ char word[1];
+};
+
+struct hashentry ** hashtable;
+int hashsize = 0xFF; /* 2^X -1 */
+int hashcount = 0;
+static int hashvalue P((int namespace, char * word));
+
+void *
+read_entry(namespace, word)
+int namespace;
+char * word;
+{
+ int hash_val;
+ struct hashentry * hashline;
+ if( hashtable == 0 ) return 0;
+ hash_val = hashvalue(namespace, word);
+
+ hashline = hashtable[hash_val];
+
+ for(; hashline; hashline = hashline->next)
+ {
+ if(namespace != hashline->namespace) continue;
+ if(word[0] != hashline->word[0]) continue;
+ if(strcmp(word, hashline->word) ) continue;
+ return hashline->value;
+ }
+ return 0;
+}
+
+char *
+set_entry(namespace, word, value)
+int namespace;
+char * word;
+void * value;
+{
+ int hash_val, i;
+ struct hashentry * hashline, *prev;
+ hash_val = hashvalue(namespace, word);
+
+ if( hashtable )
+ {
+ hashline = hashtable[hash_val];
+
+ for(prev=0; hashline; prev=hashline, hashline = hashline->next)
+ {
+ if(namespace != hashline->namespace) continue;
+ if(word[0] != hashline->word[0]) continue;
+ if(strcmp(word, hashline->word) ) continue;
+ if( value ) hashline->value = value;
+ else
+ {
+ if( prev == 0 ) hashtable[hash_val] = hashline->next;
+ else prev->next = hashline->next;
+ free(hashline);
+ return 0;
+ }
+ return hashline->word;
+ }
+ }
+ if( value == 0 ) return 0;
+ if( hashtable == 0 )
+ {
+ hashtable = malloc((hashsize+1)*sizeof(char*));
+ if( hashtable == 0 ) cfatal("Out of memory");
+ for(i=0; i<=hashsize; i++) hashtable[i] = 0;
+ }
+ /* Add record */
+ hashline = malloc(sizeof(struct hashentry)+strlen(word));
+ if( hashline == 0 ) cfatal("Out of memory");
+ else
+ {
+ hashline->next = hashtable[hash_val];
+ hashline->namespace = namespace;
+ hashline->value = value;
+ strcpy(hashline->word, word);
+ hashtable[hash_val] = hashline;
+ }
+ return hashline->word;
+}
+
+static int hashvalue(namespace, word)
+int namespace;
+char * word;
+{
+ int val = namespace;
+ char *p = word;
+
+ while(*p)
+ {
+ val = ((val<<4)^((val>>12)&0xF)^((*p++)&0xFF));
+ }
+ val &= hashsize;
+ return val;
+}
--- /dev/null
+
+#include <stdio.h>
+#if __STDC__
+#include <stdlib.h>
+#include <locale.h>
+#else
+#include <malloc.h>
+#endif
+#include <ctype.h>
+#include <string.h>
+#include <time.h>
+
+#include "cc.h"
+
+#define MAXINCPATH 5
+
+int main P((int argc, char ** argv));
+void undefine_macro P((char * name));
+void define_macro P((char * name));
+void print_toks_cpp P((void));
+void print_toks_raw P((void));
+void define_macro P((char *));
+void undefine_macro P((char *));
+void cmsg P((char * mtype, char * str));
+char * token_txn P((int));
+void pr_indent P((int));
+void hash_line P((void));
+
+char * include_paths[MAXINCPATH];
+
+char last_name[512] = "";
+int last_line = -1;
+int debug_mode = 0;
+int p_flag = 0;
+int exit_code = 0;
+
+char * outfile = 0;
+FILE * ofd = 0;
+
+int
+main(argc, argv)
+int argc;
+char ** argv;
+{
+ int ar, i;
+ char * p;
+static char Usage[] = "Usage: cpp -E -0 -Dxxx -Uxxx -Ixxx infile -o outfile";
+
+#ifdef LC_CTYPE
+ setlocale(LC_CTYPE, "");
+#endif
+
+ alltok = 1; /* Get all tokens from the cpp. */
+
+ for(ar=1; ar<argc; ar++) if( argv[ar][0] == '-') switch(argv[ar][1])
+ {
+ case 'd': debug_mode++; break;
+ case 'T': alltok = 0; break;
+ case 'A': dialect = DI_ANSI; break;
+ case 'K': dialect = DI_KNR; break;
+
+ /* Some options for describing the code generator. */
+ case '0': define_macro("__BCC__");
+ define_macro("__AS386_16__");
+ define_macro("__8086__");
+ break;
+ case '3': define_macro("__BCC__");
+ define_macro("__AS386_32__");
+ define_macro("__i386__");
+ break;
+ case 'c': define_macro("__CALLER_SAVES__");
+ break;
+ case 'f': define_macro("__FIRST_ARG_IN_AX__");
+ break;
+ case 'O': define_macro("__OPTIMISED__");
+ break;
+
+ case 'C': /* Keep comments. */
+ cwarn("-C not implemented");
+ break;
+ case 'P': p_flag++;
+ break;
+
+ case 'I':
+ if (argv[ar][2]) p=argv[ar]+2;
+ else {
+ ar++;
+ if (ar>=argc) cfatal(Usage);
+ p = argv[ar];
+ }
+ for(i=0; i<MAXINCPATH; i++)
+ if (!include_paths[i]) {
+ include_paths[i] = p;
+ break;
+ }
+ if (i>=MAXINCPATH)
+ cfatal("Too many items in include path for CPP");
+ break;
+ case 'D':
+ if (argv[ar][2]) p=argv[ar]+2;
+ else {
+ ar++;
+ if (ar>=argc) cfatal(Usage);
+ p = argv[ar];
+ }
+ define_macro(p);
+ break;
+ case 'U':
+ if (argv[ar][2]) p=argv[ar]+2;
+ else {
+ ar++;
+ if (ar>=argc) cfatal(Usage);
+ p = argv[ar];
+ }
+ undefine_macro(p);
+ break;
+ case 'o':
+ if (argv[ar][2]) p=argv[ar]+2;
+ else {
+ ar++;
+ if (ar>=argc) cfatal(Usage);
+ p = argv[ar];
+ }
+ if (outfile) cfatal(Usage);
+ outfile = p;
+ break;
+ default:
+ fprintf(stderr, "CPP Unknown option %s\n", argv[ar]);
+ cfatal(Usage);
+ } else if (!curfile) {
+ /* Input file */
+ curfile = fopen(argv[ar], "r");
+ c_fname = argv[ar]; c_lineno = 1;
+ if (!curfile)
+ cfatal("Cannot open input file");
+ } else
+ cfatal(Usage);
+
+ if (!curfile)
+ cfatal(Usage);
+
+ /* Define date and time macros. */
+ if (dialect != DI_KNR) {
+ time_t now;
+ char * timep;
+ char buf[128];
+ time(&now);
+ timep = ctime(&now);
+
+ /* Yes, well */
+ sprintf(buf, "__TIME__=\"%.8s\"", timep + 11);
+ define_macro(buf);
+ /* US order; Seems to be mandated by standard. */
+ sprintf(buf, "__DATE__=\"%.3s %.2s %.4s\"", timep + 4, timep + 8, timep + 20);
+ define_macro(buf);
+ }
+
+ if (outfile) ofd = fopen(outfile, "w");
+ else ofd = stdout;
+ if (!ofd)
+ cfatal("Cannot open output file");
+
+ if (debug_mode)
+ print_toks_raw();
+ else
+ print_toks_cpp();
+
+ if (outfile) fclose(ofd);
+ exit(exit_code);
+}
+
+void
+undefine_macro(name)
+char * name;
+{
+ struct define_item * ptr;
+
+ ptr = read_entry(0, name);
+ if (ptr) {
+ set_entry(0, name, (void*)0);
+ if (!ptr->in_use) free(ptr);
+ }
+}
+
+void
+define_macro(name)
+char * name;
+{
+ char * p;
+ char * value;
+ struct define_item * ptr;
+
+ if ((p=strchr(name, '=')) != 0) {
+ *p = 0;
+ value = p+1;
+ } else
+ value = "1";
+
+ undefine_macro(name);
+
+ ptr = malloc(sizeof(struct define_item) + strlen(value));
+ ptr->name = set_entry(0, name, ptr);
+ strcpy(ptr->value, value);
+ ptr->arg_count = -1;
+ ptr->in_use = 0;
+ ptr->next = 0;
+}
+
+FILE *
+open_include(fname, mode, checkrel)
+char * fname;
+char * mode;
+int checkrel;
+{
+ FILE * fd = 0;
+ int i;
+ char buf[256], *p;
+
+ if( checkrel )
+ {
+ strcpy(buf, c_fname);
+ p = strrchr(buf, '/');
+ if (p) *++p = 0; else *(p=buf) = 0;
+ strcpy(p, fname);
+
+ fd=fopen(buf, mode);
+ }
+ if (!fd) {
+ for(i=0; i<MAXINCPATH; i++)
+ if (include_paths[i]) {
+ strcpy(buf, include_paths[i]);
+ if (buf[strlen(buf)-1] != '/') strcat(buf, "/");
+ strcat(buf, fname);
+ fd=fopen(buf, mode);
+ if( fd ) break;
+ }
+ }
+ if (!fd) return fd;
+ c_fname = strdup(buf);
+ c_lineno = 1;
+
+ return fd;
+}
+
+/*----------------------------------------------------------------------*/
+
+static int outpos = 0;
+
+void
+cmsg(mtype, str)
+char * mtype;
+char * str;
+{
+ if (c_fname && (*c_fname || c_lineno))
+ fprintf(stderr, "%s:%d: ", c_fname, c_lineno);
+
+ if (mtype && *mtype)
+ fprintf(stderr, "%s: %s\n", mtype, str);
+ else
+ fprintf(stderr, "%s\n", str);
+}
+
+void
+cfatal(str)
+char * str;
+{
+ cmsg("CPP-FATAL error", str);
+ exit(255);
+}
+
+void
+cerror(str)
+char * str;
+{
+ exit_code = 1;
+ cmsg("error", str);
+}
+
+void
+cwarn(str)
+char * str;
+{
+ cmsg("warning", str);
+}
+
+void
+pr_indent(count)
+int count;
+{
+ if(count>10) count=10;
+ while(count>0) {fprintf(ofd, "\t"); count--; }
+}
+
+void
+hash_line()
+{
+ if( strcmp(last_name, c_fname) != 0 ) last_line = -1;
+ if( c_lineno != last_line || last_line <= 0 )
+ {
+ if( outpos != 0 ) {
+ fputc('\n', ofd); outpos=0;
+ if (last_line > 0) last_line++;
+ }
+ while( c_lineno > last_line &&
+ (p_flag || c_lineno < last_line+4) &&
+ last_line > 0 &&
+ !debug_mode )
+ {
+ fputc('\n', ofd); last_line++;
+ }
+
+ if( !p_flag && (c_lineno != last_line || last_line <= 0 ))
+ {
+ fprintf(ofd, "# %d", c_lineno);
+ if( last_line <= 0 ) fprintf(ofd, " \"%s\"", c_fname);
+ fprintf(ofd, "\n");
+ }
+
+ strcpy(last_name, c_fname);
+ last_line = c_lineno;
+ }
+}
+
+void
+print_toks_cpp()
+{
+ int i;
+ int indent=0;
+ int paren=0;
+
+ hash_line();
+ while( (i=gettok()) != EOF )
+ {
+ hash_line();
+ switch(i)
+ {
+ case '\n':
+ cwarn("newline received from tokeniser!");
+ break;
+
+ case TK_STR:
+ outpos += fprintf(ofd, "%s", curword);
+ break;
+
+ case TK_COPY:
+ if( outpos ) { fputc('\n', ofd); last_line++; }
+ outpos = 0; last_line++;
+ fprintf(ofd, "#%s\n", curword);
+ break;
+
+ case TK_FILE: sprintf(curword, "\"%s\"", c_fname); if(0) {
+ case TK_LINE: sprintf(curword, "%d", c_lineno);
+ }
+ /*FALLTHROUGH*/
+ default:
+ if (!alltok) {
+ if(i == '}' || i == TK_CASE || i == TK_DEFAULT ) indent--;
+ if(i ==')') paren--;
+
+ if(outpos) { fputc(' ', ofd); outpos++; }
+ else pr_indent(indent+(paren!=0));
+
+ if(i == '{' || i == TK_CASE || i == TK_DEFAULT ) indent++;
+ if(i ==';') paren=0;
+ if(i =='(') paren++;
+ }
+
+ outpos += fprintf(ofd, "%s", curword);
+
+ if ( i == '"' || i == '\'' )
+ {
+ while((i=gettok()) == TK_STR) {
+ outpos += fprintf(ofd, "%s", curword);
+ }
+ if (i != '\n')
+ outpos += fprintf(ofd, "%s", curword);
+ }
+ break;
+ }
+ }
+ if( outpos ) fputc('\n', ofd);
+ outpos = 0;
+}
+
+void
+print_toks_raw()
+{
+ int i;
+ long val;
+
+ hash_line();
+ while( (i=gettok()) != EOF )
+ {
+ hash_line();
+ switch(i)
+ {
+ case '"': case '\'':
+ if (debug_mode < 2) {
+ fprintf(ofd, "%-16s: %s", "Quoted string", curword);
+ while((i=gettok()) == TK_STR)
+ outpos+= fprintf(ofd, "%s", curword);
+ if ( i == '\n' ) fprintf(ofd, " --> EOL!!\n");
+ else outpos+= fprintf(ofd, "%s\n", curword);
+ break;
+ }
+ /*FALLTHROUGH*/
+ default: fprintf(ofd, "%-16s: '", token_txn(i));
+ {
+ char *p;
+ for(p=curword; *p; p++)
+ if(isprint(*p) && *p != '\'' && *p != '\\')
+ fputc(*p, ofd);
+ else if (*p == '\n') fprintf(ofd, "\\n");
+ else if (*p == '\t') fprintf(ofd, "\\t");
+ else if (*p == '\v') fprintf(ofd, "\\v");
+ else if (*p == '\b') fprintf(ofd, "\\b");
+ else if (*p == '\r') fprintf(ofd, "\\r");
+ else if (*p == '\f') fprintf(ofd, "\\f");
+ else if (*p == '\a') fprintf(ofd, "\\a");
+ else
+ fprintf(ofd, "\\x%02x", (unsigned char)*p);
+ }
+ fprintf(ofd, "'\n");
+ break;
+ case TK_NUM:
+ val = strtoul(curword, (void*)0, 0);
+ fprintf(ofd, "%-16s: ", token_txn(i));
+ fprintf(ofd, "%s => %ld\n", curword, val);
+ break;
+ case TK_COPY:
+ fprintf(ofd, "%-16s: ", token_txn(i));
+ fprintf(ofd, "#%s\n", curword);
+ break;
+ case '\n':
+ fprintf(ofd, "%-16s:\n", "Newline char");
+ break;
+ }
+ }
+}
+
+char *
+token_txn(token)
+int token;
+{
+ char * s = "UNKNOWN";
+ static char buf[17];
+
+ if (token> ' ' && token <= '~')
+ {
+ sprintf(buf, "TK_CHAR('%c')", token);
+ return buf;
+ }
+ if (token >= 0 && token < 0x100)
+ {
+ sprintf(buf, "TK_CHAR(%d)", token);
+ return buf;
+ }
+
+ switch(token)
+ {
+ case TK_WSPACE : s="TK_WSPACE"; break;
+ case TK_WORD : s="TK_WORD"; break;
+ case TK_NUM : s="TK_NUM"; break;
+ case TK_FLT : s="TK_FLT"; break;
+ case TK_QUOT : s="TK_QUOT"; break;
+ case TK_STR : s="TK_STR"; break;
+ case TK_FILE : s="TK_FILE"; break;
+ case TK_LINE : s="TK_LINE"; break;
+ case TK_COPY : s="TK_COPY"; break;
+ case TK_NE_OP : s="TK_NE_OP"; break;
+ case TK_MOD_ASSIGN : s="TK_MOD_ASSIGN"; break;
+ case TK_AND_OP : s="TK_AND_OP"; break;
+ case TK_AND_ASSIGN : s="TK_AND_ASSIGN"; break;
+ case TK_MUL_ASSIGN : s="TK_MUL_ASSIGN"; break;
+ case TK_INC_OP : s="TK_INC_OP"; break;
+ case TK_ADD_ASSIGN : s="TK_ADD_ASSIGN"; break;
+ case TK_DEC_OP : s="TK_DEC_OP"; break;
+ case TK_SUB_ASSIGN : s="TK_SUB_ASSIGN"; break;
+ case TK_PTR_OP : s="TK_PTR_OP"; break;
+ case TK_ELLIPSIS : s="TK_ELLIPSIS"; break;
+ case TK_DIV_ASSIGN : s="TK_DIV_ASSIGN"; break;
+ case TK_LEFT_OP : s="TK_LEFT_OP"; break;
+ case TK_LEFT_ASSIGN : s="TK_LEFT_ASSIGN"; break;
+ case TK_LE_OP : s="TK_LE_OP"; break;
+ case TK_EQ_OP : s="TK_EQ_OP"; break;
+ case TK_GE_OP : s="TK_GE_OP"; break;
+ case TK_RIGHT_OP : s="TK_RIGHT_OP"; break;
+ case TK_RIGHT_ASSIGN : s="TK_RIGHT_ASSIGN"; break;
+ case TK_XOR_ASSIGN : s="TK_XOR_ASSIGN"; break;
+ case TK_OR_ASSIGN : s="TK_OR_ASSIGN"; break;
+ case TK_OR_OP : s="TK_OR_OP"; break;
+ case TK_AUTO : s="TK_AUTO"; break;
+ case TK_BREAK : s="TK_BREAK"; break;
+ case TK_CASE : s="TK_CASE"; break;
+ case TK_CHAR : s="TK_CHAR"; break;
+ case TK_CONST : s="TK_CONST"; break;
+ case TK_CONTINUE : s="TK_CONTINUE"; break;
+ case TK_DEFAULT : s="TK_DEFAULT"; break;
+ case TK_DO : s="TK_DO"; break;
+ case TK_DOUBLE : s="TK_DOUBLE"; break;
+ case TK_ELSE : s="TK_ELSE"; break;
+ case TK_ENUM : s="TK_ENUM"; break;
+ case TK_EXTERN : s="TK_EXTERN"; break;
+ case TK_FLOAT : s="TK_FLOAT"; break;
+ case TK_FOR : s="TK_FOR"; break;
+ case TK_GOTO : s="TK_GOTO"; break;
+ case TK_IF : s="TK_IF"; break;
+ case TK_INT : s="TK_INT"; break;
+ case TK_LONG : s="TK_LONG"; break;
+ case TK_REGISTER : s="TK_REGISTER"; break;
+ case TK_RETURN : s="TK_RETURN"; break;
+ case TK_SHORT : s="TK_SHORT"; break;
+ case TK_SIGNED : s="TK_SIGNED"; break;
+ case TK_SIZEOF : s="TK_SIZEOF"; break;
+ case TK_STATIC : s="TK_STATIC"; break;
+ case TK_STRUCT : s="TK_STRUCT"; break;
+ case TK_SWITCH : s="TK_SWITCH"; break;
+ case TK_TYPEDEF : s="TK_TYPEDEF"; break;
+ case TK_UNION : s="TK_UNION"; break;
+ case TK_UNSIGNED : s="TK_UNSIGNED"; break;
+ case TK_VOID : s="TK_VOID"; break;
+ case TK_VOLATILE : s="TK_VOLATILE"; break;
+ case TK_WHILE : s="TK_WHILE"; break;
+ }
+ return s;
+}
--- /dev/null
+
+#include <stdio.h>
+#include <string.h>
+#include "cc.h"
+
+#ifdef __GNUC__
+__inline
+#endif
+static unsigned int hash1 P((register const char *, register unsigned int));
+
+#include "token1.h"
--- /dev/null
+/* C code produced by gperf version 2.7.1 (19981006 egcs) */
+/* Command-line: gperf -aptTc -N is_ctok -H hash1 token1.tok */
+
+#define TOTAL_KEYWORDS 23
+#define MIN_WORD_LENGTH 2
+#define MAX_WORD_LENGTH 3
+#define MIN_HASH_VALUE 2
+#define MAX_HASH_VALUE 63
+/* maximum key range = 62, duplicates = 0 */
+
+#ifdef __GNUC__
+__inline
+#endif
+static unsigned int
+hash1 (str, len)
+ register const char *str;
+ register unsigned int len;
+{
+ static unsigned char asso_values[] =
+ {
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 1, 64, 64, 64, 3, 25, 64,
+ 64, 64, 13, 18, 64, 8, 30, 15, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 5, 0, 20, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 30, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 23, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64
+ };
+ return len + asso_values[(unsigned char)str[len - 1]] + asso_values[(unsigned char)str[0]];
+}
+
+#ifdef __GNUC__
+__inline
+#endif
+struct token_trans *
+is_ctok (str, len)
+ register const char *str;
+ register unsigned int len;
+{
+ static struct token_trans wordlist[] =
+ {
+ {""}, {""},
+ {"==", TK_EQ_OP},
+ {"!=", TK_NE_OP},
+ {""},
+ {"%=", TK_MOD_ASSIGN},
+ {""},
+ {"<=", TK_LE_OP},
+ {"<<=", TK_LEFT_ASSIGN},
+ {""},
+ {"-=", TK_SUB_ASSIGN},
+ {""},
+ {"<<", TK_LEFT_OP},
+ {""}, {""},
+ {"*=", TK_MUL_ASSIGN},
+ {""},
+ {"/=", TK_DIV_ASSIGN},
+ {"--", TK_DEC_OP},
+ {""},
+ {"+=", TK_ADD_ASSIGN},
+ {""},
+ {">=", TK_GE_OP},
+ {">>=", TK_RIGHT_ASSIGN},
+ {""},
+ {"|=", TK_OR_ASSIGN},
+ {""},
+ {"&=", TK_AND_ASSIGN},
+ {""}, {""},
+ {"->", TK_PTR_OP},
+ {""},
+ {"^=", TK_XOR_ASSIGN},
+ {""}, {""}, {""}, {""}, {""},
+ {"++", TK_INC_OP},
+ {""}, {""}, {""},
+ {">>", TK_RIGHT_OP},
+ {""}, {""}, {""}, {""}, {""},
+ {"||", TK_OR_OP},
+ {""}, {""}, {""},
+ {"&&", TK_AND_OP},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {"..", TK_WORD},
+ {"...", TK_ELLIPSIS}
+ };
+
+ if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
+ {
+ register int key = hash1 (str, len);
+
+ if (key <= MAX_HASH_VALUE && key >= 0)
+ {
+ register const char *s = wordlist[key].name;
+
+ if (*str == *s && !strncmp (str + 1, s + 1, len - 1))
+ return &wordlist[key];
+ }
+ }
+ return 0;
+}
--- /dev/null
+struct token_trans { char * name; int token; };
+%%
+..., TK_ELLIPSIS
+>>=, TK_RIGHT_ASSIGN
+<<=, TK_LEFT_ASSIGN
++=, TK_ADD_ASSIGN
+-=, TK_SUB_ASSIGN
+*=, TK_MUL_ASSIGN
+/=, TK_DIV_ASSIGN
+%=, TK_MOD_ASSIGN
+&=, TK_AND_ASSIGN
+^=, TK_XOR_ASSIGN
+|=, TK_OR_ASSIGN
+>>, TK_RIGHT_OP
+<<, TK_LEFT_OP
+++, TK_INC_OP
+--, TK_DEC_OP
+->, TK_PTR_OP
+&&, TK_AND_OP
+||, TK_OR_OP
+<=, TK_LE_OP
+>=, TK_GE_OP
+==, TK_EQ_OP
+!=, TK_NE_OP
+.., TK_WORD
--- /dev/null
+
+#include <stdio.h>
+#include <string.h>
+#include "cc.h"
+
+#ifdef __GNUC__
+__inline
+#endif
+static unsigned int hash2 P((register const char *, register unsigned int));
+
+#include "token2.h"
--- /dev/null
+/* C code produced by gperf version 2.7.1 (19981006 egcs) */
+/* Command-line: gperf -aptTc -k1,3 -N is_ckey -H hash2 token2.tok */
+
+#define TOTAL_KEYWORDS 34
+#define MIN_WORD_LENGTH 2
+#define MAX_WORD_LENGTH 8
+#define MIN_HASH_VALUE 2
+#define MAX_HASH_VALUE 69
+/* maximum key range = 68, duplicates = 0 */
+
+#ifdef __GNUC__
+__inline
+#endif
+static unsigned int
+hash2 (str, len)
+ register const char *str;
+ register unsigned int len;
+{
+ static unsigned char asso_values[] =
+ {
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 5, 70, 70, 70, 70, 70, 0, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 0, 70, 5, 5, 10,
+ 10, 20, 20, 25, 70, 0, 70, 70, 50, 70,
+ 0, 15, 0, 70, 15, 0, 40, 20, 0, 0,
+ 70, 70, 10, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70
+ };
+ register int hval = len;
+
+ switch (hval)
+ {
+ default:
+ case 3:
+ hval += asso_values[(unsigned char)str[2]];
+ case 2:
+ case 1:
+ hval += asso_values[(unsigned char)str[0]];
+ break;
+ }
+ return hval;
+}
+
+#ifdef __GNUC__
+__inline
+#endif
+struct token_trans *
+is_ckey (str, len)
+ register const char *str;
+ register unsigned int len;
+{
+ static struct token_trans wordlist[] =
+ {
+ {""}, {""},
+ {"if", TK_IF},
+ {""},
+ {"void", TK_VOID},
+ {"while", TK_WHILE},
+ {"switch", TK_SWITCH},
+ {""},
+ {"__LINE__", TK_LINE},
+ {""}, {""},
+ {"static", TK_STATIC},
+ {"do", TK_DO},
+ {"__FILE__", TK_FILE},
+ {"case", TK_CASE},
+ {"const", TK_CONST},
+ {"sizeof", TK_SIZEOF},
+ {""},
+ {"continue", TK_CONTINUE},
+ {"char", TK_CHAR},
+ {"short", TK_SHORT},
+ {"struct", TK_STRUCT},
+ {""}, {""},
+ {"else", TK_ELSE},
+ {"union", TK_UNION},
+ {""}, {""},
+ {"unsigned", TK_UNSIGNED},
+ {""},
+ {"break", TK_BREAK},
+ {"signed", TK_SIGNED},
+ {""}, {""}, {""}, {""},
+ {"double", TK_DOUBLE},
+ {"default", TK_DEFAULT},
+ {"for", TK_FOR},
+ {""},
+ {"float", TK_FLOAT},
+ {""}, {""},
+ {"int", TK_INT},
+ {"enum", TK_ENUM},
+ {""}, {""},
+ {"typedef", TK_TYPEDEF},
+ {"register", TK_REGISTER},
+ {"auto", TK_AUTO},
+ {""}, {""}, {""}, {""},
+ {"long", TK_LONG},
+ {""}, {""}, {""},
+ {"volatile", TK_VOLATILE},
+ {""}, {""},
+ {"return", TK_RETURN},
+ {""}, {""}, {""}, {""},
+ {"extern", TK_EXTERN},
+ {""}, {""},
+ {"goto", TK_GOTO}
+ };
+
+ if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
+ {
+ register int key = hash2 (str, len);
+
+ if (key <= MAX_HASH_VALUE && key >= 0)
+ {
+ register const char *s = wordlist[key].name;
+
+ if (*str == *s && !strncmp (str + 1, s + 1, len - 1))
+ return &wordlist[key];
+ }
+ }
+ return 0;
+}
--- /dev/null
+struct token_trans { char * name; int token; };
+%%
+auto, TK_AUTO
+break, TK_BREAK
+case, TK_CASE
+char, TK_CHAR
+const, TK_CONST
+continue, TK_CONTINUE
+default, TK_DEFAULT
+do, TK_DO
+double, TK_DOUBLE
+else, TK_ELSE
+enum, TK_ENUM
+extern, TK_EXTERN
+float, TK_FLOAT
+for, TK_FOR
+goto, TK_GOTO
+if, TK_IF
+int, TK_INT
+long, TK_LONG
+register, TK_REGISTER
+return, TK_RETURN
+short, TK_SHORT
+signed, TK_SIGNED
+sizeof, TK_SIZEOF
+static, TK_STATIC
+struct, TK_STRUCT
+switch, TK_SWITCH
+typedef, TK_TYPEDEF
+union, TK_UNION
+unsigned, TK_UNSIGNED
+void, TK_VOID
+volatile, TK_VOLATILE
+while, TK_WHILE
+__FILE__, TK_FILE
+__LINE__, TK_LINE
--- /dev/null
+/\\r
+* \ This _evil_ little file is compilable Ansi C.\r
+* / There are NO extensions ... Waddya think ? \r
+\/\r
+\r
+// ***/ func() { printf("Hello /* world */ %d ???/?=\n" ??/\r
+, 1?\r
+'\\\r
+007':\r
+'??/"'/*"*/\r
+ );}\r
+\r
+ \r
+main() \r
+{\r
+ func();\r
+\r
+}\r