]> granicus.if.org Git - yasm/commitdiff
Resurrect yapp from revision 998.
authorPeter Johnson <peter@tortall.net>
Sat, 16 Sep 2006 02:22:08 +0000 (02:22 -0000)
committerPeter Johnson <peter@tortall.net>
Sat, 16 Sep 2006 02:22:08 +0000 (02:22 -0000)
svn path=/trunk/yasm/; revision=1614

27 files changed:
modules/preprocs/yapp/Makefile.inc [new file with mode: 0644]
modules/preprocs/yapp/tests/Makefile.inc [new file with mode: 0644]
modules/preprocs/yapp/tests/comment.asm [new file with mode: 0644]
modules/preprocs/yapp/tests/comment.pre [new file with mode: 0644]
modules/preprocs/yapp/tests/ddefine.asm [new file with mode: 0644]
modules/preprocs/yapp/tests/ddefine.pre [new file with mode: 0644]
modules/preprocs/yapp/tests/define.asm [new file with mode: 0644]
modules/preprocs/yapp/tests/define.pre [new file with mode: 0644]
modules/preprocs/yapp/tests/ifdef.asm [new file with mode: 0644]
modules/preprocs/yapp/tests/ifdef.pre [new file with mode: 0644]
modules/preprocs/yapp/tests/include.asm [new file with mode: 0644]
modules/preprocs/yapp/tests/include.pre [new file with mode: 0644]
modules/preprocs/yapp/tests/params.asm [new file with mode: 0644]
modules/preprocs/yapp/tests/params.pre [new file with mode: 0644]
modules/preprocs/yapp/tests/pdefine.asm [new file with mode: 0644]
modules/preprocs/yapp/tests/pdefine.pre [new file with mode: 0644]
modules/preprocs/yapp/tests/raw.asm [new file with mode: 0644]
modules/preprocs/yapp/tests/raw.pre [new file with mode: 0644]
modules/preprocs/yapp/tests/rdefine.asm [new file with mode: 0644]
modules/preprocs/yapp/tests/rdefine.pre [new file with mode: 0644]
modules/preprocs/yapp/tests/rinclude.asm [new file with mode: 0644]
modules/preprocs/yapp/tests/rinclude.pre [new file with mode: 0644]
modules/preprocs/yapp/tests/yapp_test.sh [new file with mode: 0755]
modules/preprocs/yapp/yapp-preproc.c [new file with mode: 0644]
modules/preprocs/yapp/yapp-preproc.h [new file with mode: 0644]
modules/preprocs/yapp/yapp-token.h [new file with mode: 0644]
modules/preprocs/yapp/yapp-token.l [new file with mode: 0644]

diff --git a/modules/preprocs/yapp/Makefile.inc b/modules/preprocs/yapp/Makefile.inc
new file mode 100644 (file)
index 0000000..c935c6e
--- /dev/null
@@ -0,0 +1,18 @@
+# $IdPath$
+
+pkglib_LTLIBRARIES += preproc_yapp.la
+
+preproc_yapp_la_SOURCES  = modules/preprocs/yapp/yapp-preproc.c
+preproc_yapp_la_SOURCES += modules/preprocs/yapp/yapp-preproc.h
+preproc_yapp_la_SOURCES += modules/preprocs/yapp/yapp-token.h
+preproc_yapp_la_SOURCES += modules/preprocs/yapp/yapp-token.l
+
+preproc_yapp_la_LDFLAGS = -module -avoid-version -no-undefined
+preproc_yapp_la_LIBADD = libyasm.la
+YASM_MODULES += -dlopen preproc_yapp.la
+
+BUILT_SOURCES += yapp-token.c
+
+CLEANFILES += yapp-token.c
+
+include modules/preprocs/yapp/tests/Makefile.inc
diff --git a/modules/preprocs/yapp/tests/Makefile.inc b/modules/preprocs/yapp/tests/Makefile.inc
new file mode 100644 (file)
index 0000000..7dd1285
--- /dev/null
@@ -0,0 +1,26 @@
+# $IdPath$
+
+TESTS += modules/preprocs/yapp/tests/yapp_test.sh
+
+EXTRA_DIST += modules/preprocs/yapp/tests/Makefile.inc
+EXTRA_DIST += modules/preprocs/yapp/tests/yapp_test.sh
+EXTRA_DIST += modules/preprocs/yapp/tests/raw.asm
+EXTRA_DIST += modules/preprocs/yapp/tests/raw.pre
+EXTRA_DIST += modules/preprocs/yapp/tests/comment.asm
+EXTRA_DIST += modules/preprocs/yapp/tests/comment.pre
+EXTRA_DIST += modules/preprocs/yapp/tests/define.asm
+EXTRA_DIST += modules/preprocs/yapp/tests/define.pre
+EXTRA_DIST += modules/preprocs/yapp/tests/ddefine.asm
+EXTRA_DIST += modules/preprocs/yapp/tests/ddefine.pre
+EXTRA_DIST += modules/preprocs/yapp/tests/rdefine.asm
+EXTRA_DIST += modules/preprocs/yapp/tests/rdefine.pre
+EXTRA_DIST += modules/preprocs/yapp/tests/pdefine.asm
+EXTRA_DIST += modules/preprocs/yapp/tests/pdefine.pre
+EXTRA_DIST += modules/preprocs/yapp/tests/ifdef.asm
+EXTRA_DIST += modules/preprocs/yapp/tests/ifdef.pre
+EXTRA_DIST += modules/preprocs/yapp/tests/include.asm
+EXTRA_DIST += modules/preprocs/yapp/tests/include.pre
+EXTRA_DIST += modules/preprocs/yapp/tests/rinclude.asm
+EXTRA_DIST += modules/preprocs/yapp/tests/rinclude.pre
+EXTRA_DIST += modules/preprocs/yapp/tests/params.asm
+EXTRA_DIST += modules/preprocs/yapp/tests/params.pre
diff --git a/modules/preprocs/yapp/tests/comment.asm b/modules/preprocs/yapp/tests/comment.asm
new file mode 100644 (file)
index 0000000..e41966d
--- /dev/null
@@ -0,0 +1,2 @@
+;      mov     ax, 4 ; asdfasdf
+       mov     ax, 4 ; asdfasdf
diff --git a/modules/preprocs/yapp/tests/comment.pre b/modules/preprocs/yapp/tests/comment.pre
new file mode 100644 (file)
index 0000000..6d0bfdd
--- /dev/null
@@ -0,0 +1,2 @@
+%line 2+1 -
+       mov     ax, 4 
diff --git a/modules/preprocs/yapp/tests/ddefine.asm b/modules/preprocs/yapp/tests/ddefine.asm
new file mode 100644 (file)
index 0000000..ae46fc6
--- /dev/null
@@ -0,0 +1,6 @@
+%define foo 5
+%define bar baz
+       mov     ax, [foo+bar]
+%define baz bzzt
+%define bzzt 9
+       mov     ax, baz+bar
diff --git a/modules/preprocs/yapp/tests/ddefine.pre b/modules/preprocs/yapp/tests/ddefine.pre
new file mode 100644 (file)
index 0000000..5d2f788
--- /dev/null
@@ -0,0 +1,5 @@
+%line 3+1 -
+       mov     ax, [5+baz]
+
+
+       mov     ax, 9+9
diff --git a/modules/preprocs/yapp/tests/define.asm b/modules/preprocs/yapp/tests/define.asm
new file mode 100644 (file)
index 0000000..f9330d3
--- /dev/null
@@ -0,0 +1,4 @@
+%define foo 5
+%define bar baz
+       mov     ax, [foo+bar]
+%define baz bzzt
diff --git a/modules/preprocs/yapp/tests/define.pre b/modules/preprocs/yapp/tests/define.pre
new file mode 100644 (file)
index 0000000..b631ba2
--- /dev/null
@@ -0,0 +1,3 @@
+%line 3+1 -
+       mov     ax, [5+baz]
+
diff --git a/modules/preprocs/yapp/tests/ifdef.asm b/modules/preprocs/yapp/tests/ifdef.asm
new file mode 100644 (file)
index 0000000..b9d7807
--- /dev/null
@@ -0,0 +1,13 @@
+%ifdef foo
+       mov     ax, foo
+%endif
+%ifdef bar
+       mov     ax, bar
+%endif
+%define foo 5
+%ifdef foo
+       mov     ax, foo
+%endif
+%ifdef bar
+       mov     ax, bar
+%endif
diff --git a/modules/preprocs/yapp/tests/ifdef.pre b/modules/preprocs/yapp/tests/ifdef.pre
new file mode 100644 (file)
index 0000000..4031163
--- /dev/null
@@ -0,0 +1,5 @@
+%line 9+1 -
+       mov     ax, 5
+
+
+%line 14+1 -
diff --git a/modules/preprocs/yapp/tests/include.asm b/modules/preprocs/yapp/tests/include.asm
new file mode 100644 (file)
index 0000000..08b1b48
--- /dev/null
@@ -0,0 +1,5 @@
+       mov     ax, 5
+%include "./modules/preprocs/yapp/tests/raw.asm"
+       mov     ax, 6
+%include "./modules/preprocs/yapp/tests/raw.asm"
+       mov     ax, 7
diff --git a/modules/preprocs/yapp/tests/include.pre b/modules/preprocs/yapp/tests/include.pre
new file mode 100644 (file)
index 0000000..ea172ac
--- /dev/null
@@ -0,0 +1,10 @@
+%line 1+1 -
+       mov     ax, 5
+%line 1+1 ./modules/preprocs/yapp/tests/raw.asm
+       mov     ax, raw
+%line 3+1 -
+       mov     ax, 6
+%line 1+1 ./modules/preprocs/yapp/tests/raw.asm
+       mov     ax, raw
+%line 5+1 -
+       mov     ax, 7
diff --git a/modules/preprocs/yapp/tests/params.asm b/modules/preprocs/yapp/tests/params.asm
new file mode 100644 (file)
index 0000000..046775e
--- /dev/null
@@ -0,0 +1,2 @@
+%define foo(a, b) (a)+(b)
+    foo((a+b,c),(d*e,f))
diff --git a/modules/preprocs/yapp/tests/params.pre b/modules/preprocs/yapp/tests/params.pre
new file mode 100644 (file)
index 0000000..dc2cd98
--- /dev/null
@@ -0,0 +1,2 @@
+%line 2+1 -
+    ((a+b,c))+((d*e,f))
diff --git a/modules/preprocs/yapp/tests/pdefine.asm b/modules/preprocs/yapp/tests/pdefine.asm
new file mode 100644 (file)
index 0000000..ebde922
--- /dev/null
@@ -0,0 +1,6 @@
+%define foo(bar) bar+1
+%define foo(bar, baz) bar-baz
+       mov     ax, foo
+       mov     ax, foo(5)
+       mov     ax, foo(5, 3)
+       mov     ax, foo(5, 6, 7)
diff --git a/modules/preprocs/yapp/tests/pdefine.pre b/modules/preprocs/yapp/tests/pdefine.pre
new file mode 100644 (file)
index 0000000..553799d
--- /dev/null
@@ -0,0 +1,5 @@
+%line 3+1 -
+       mov     ax, foo
+       mov     ax, 5+1
+       mov     ax, 5-3
+       mov     ax, foo(5, 6, 7)
diff --git a/modules/preprocs/yapp/tests/raw.asm b/modules/preprocs/yapp/tests/raw.asm
new file mode 100644 (file)
index 0000000..9d5f67f
--- /dev/null
@@ -0,0 +1 @@
+       mov     ax, raw
diff --git a/modules/preprocs/yapp/tests/raw.pre b/modules/preprocs/yapp/tests/raw.pre
new file mode 100644 (file)
index 0000000..3bf6062
--- /dev/null
@@ -0,0 +1,2 @@
+%line 1+1 -
+       mov     ax, raw
diff --git a/modules/preprocs/yapp/tests/rdefine.asm b/modules/preprocs/yapp/tests/rdefine.asm
new file mode 100644 (file)
index 0000000..c4b1644
--- /dev/null
@@ -0,0 +1,6 @@
+%define recursion endless
+%define endless recursion
+       mov     ax, 5
+       mov     ax, endless
+%define recurse recurse
+       mov     ax, recurse
diff --git a/modules/preprocs/yapp/tests/rdefine.pre b/modules/preprocs/yapp/tests/rdefine.pre
new file mode 100644 (file)
index 0000000..dfc1bfa
--- /dev/null
@@ -0,0 +1,5 @@
+%line 3+1 -
+       mov     ax, 5
+       mov     ax, endless
+
+       mov     ax, recurse
diff --git a/modules/preprocs/yapp/tests/rinclude.asm b/modules/preprocs/yapp/tests/rinclude.asm
new file mode 100644 (file)
index 0000000..43f3efe
--- /dev/null
@@ -0,0 +1,5 @@
+%ifndef recurse
+%define recurse
+%include "./modules/preprocs/yapp/tests/rinclude.asm"
+       mov     ax, 5
+%endif
diff --git a/modules/preprocs/yapp/tests/rinclude.pre b/modules/preprocs/yapp/tests/rinclude.pre
new file mode 100644 (file)
index 0000000..63ac7fc
--- /dev/null
@@ -0,0 +1,3 @@
+%line 4+1 -
+       mov ax, 5 
+
diff --git a/modules/preprocs/yapp/tests/yapp_test.sh b/modules/preprocs/yapp/tests/yapp_test.sh
new file mode 100755 (executable)
index 0000000..28e42ea
--- /dev/null
@@ -0,0 +1,60 @@
+#! /bin/sh
+# $IdPath$
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='     ' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+mkdir results >/dev/null 2>&1
+
+#
+# Verify that all test cases match
+# (aside from whitespace for now)
+#
+
+passedct=0
+passedlist=''
+failedct=0
+failedlist=''
+errorct=0
+errorlist=''
+
+YT="yapp_test"
+
+
+for asm in ${srcdir}/modules/preprocs/yapp/tests/*.asm
+do
+    a=`echo ${asm} | sed 's,^.*/,,;s,.asm$,,'`
+    y=${a}.yp
+    p=`echo ${asm} | sed 's,.asm$,.pre,'`
+
+    echo $ECHO_N "$YT: Testing yapp for ${a} ... $ECHO_C"
+    if sed "s,\./,${srcdir}/," ${asm} | ./yasm -e -r yapp |
+       sed "s,${srcdir}/,./," > results/${y}; then
+       if diff -w ${p} results/${y} > /dev/null; then
+           echo "PASS."
+           passedct=`expr $passedct + 1`
+           passedlist="${passedlist}${a} "
+       else
+           echo "FAIL."
+           failedct=`expr $failedct + 1`
+           failedlist="${failedlist}${a} "
+       fi
+    else
+       errorct=`expr $errorct + 1`
+       errorlist="${errorlist}${a} "
+    fi
+done
+
+ct=`expr $failedct + $passedct + $errorct`
+per=`expr 100 \* $passedct / $ct`
+
+echo "$YT: $per%: Checks: $ct, Failures $failedct, Errors: $errorct"
+#test $passedct -gt 0 && echo "$YT: PASSED $passedct: $passedlist"
+#test $failedct -gt 0 && echo "$YT: FAILED $failedct: $failedlist"
+#test $errorct -gt 0 && echo "$YT: ERRORED $errorct: $errorlist"
+
+exit `expr $failedct + $errorct`
diff --git a/modules/preprocs/yapp/yapp-preproc.c b/modules/preprocs/yapp/yapp-preproc.c
new file mode 100644 (file)
index 0000000..e8e647c
--- /dev/null
@@ -0,0 +1,952 @@
+/* $IdPath: yasm/modules/preprocs/yapp/yapp-preproc.c,v 1.23 2003/03/17 00:03:02 peter Exp $
+ * YAPP preprocessor (mimics NASM's preprocessor)
+ *
+ *  Copyright (C) 2001  Michael Urman
+ *
+ *  This file is part of YASM.
+ *
+ *  YASM 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 of the License, or
+ *  (at your option) any later version.
+ *
+ *  YASM 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <util.h>
+/*@unused@*/ RCSID("$IdPath: yasm/modules/preprocs/yapp/yapp-preproc.c,v 1.23 2003/03/17 00:03:02 peter Exp $");
+
+#define YASM_LIB_INTERNAL
+#include <libyasm.h>
+
+#include "yapp-preproc.h"
+#include "yapp-token.h"
+
+#define ydebug(x) /* printf x */
+
+static int is_interactive;
+static int saved_length;
+
+static HAMT *macro_table;
+
+static YAPP_Output current_output;
+YYSTYPE yapp_preproc_lval;
+
+/*@dependent@*/ yasm_linemgr *yapp_preproc_linemgr;
+
+int isatty(int);
+
+/* Build source and macro representations */
+static SLIST_HEAD(source_head, source_s) source_head, macro_head, param_head;
+static struct source_s {
+    SLIST_ENTRY(source_s) next;
+    YAPP_Token token;
+} *src, *source_tail, *macro_tail, *param_tail;
+typedef struct source_s source;
+
+/* don't forget what the nesting level says */
+static SLIST_HEAD(output_head, output_s) output_head;
+static struct output_s {
+    SLIST_ENTRY(output_s) next;
+    YAPP_Output out;
+} output, *out;
+
+/*****************************************************************************/
+/* macro support - to be moved to a separate file later (?)                  */
+/*****************************************************************************/
+typedef struct YAPP_Macro_s {
+    struct source_head macro_head;
+    struct source_head param_head;
+    enum {
+       YAPP_MACRO = 0,
+       YAPP_DEFINE
+    } type;
+    int args;
+    int fillargs;
+    int expanding;
+} YAPP_Macro;
+
+YAPP_Macro *
+yapp_macro_insert (char *name, int argc, int fillargs);
+
+void
+yapp_macro_error_exists (YAPP_Macro *v);
+
+void
+yapp_macro_error_sameargname (YAPP_Macro *v);
+
+YAPP_Macro *
+yapp_define_insert (char *name, int argc, int fillargs);
+
+void
+yapp_macro_delete (YAPP_Macro *ym);
+
+static YAPP_Macro *
+yapp_macro_get (const char *key);
+
+struct source_head *
+yapp_define_param_get (HAMT *hamt, const char *key);
+
+static void
+replay_saved_tokens(char *ident,
+                   struct source_head *from_head,
+                   struct source_head *to_head,
+                   source **to_tail);
+
+YAPP_Macro *
+yapp_macro_insert (char *name, int argc, int fillargs)
+{
+    YAPP_Macro *ym = yasm_xmalloc(sizeof(YAPP_Macro));
+    ym->type = YAPP_MACRO;
+    ym->args = argc;
+    ym->fillargs = fillargs;
+
+    memcpy(&ym->macro_head, &macro_head, sizeof(macro_head));
+
+    SLIST_INIT(&macro_head);
+    macro_tail = SLIST_FIRST(&macro_head);
+    return ym;
+}
+
+void
+yapp_macro_error_exists (YAPP_Macro *v)
+{
+    if (v) yasm__error(cur_lindex, N_("Redefining macro of the same name %d:%d"), v->type, v->args);
+}
+
+void
+yapp_macro_error_sameargname (YAPP_Macro *v)
+{
+    if (v) yasm__error(cur_lindex, N_("Duplicate argument names in macro"));
+}
+
+YAPP_Macro *
+yapp_define_insert (char *name, int argc, int fillargs)
+{
+    int zero = 0;
+    char *mungename = name;
+    YAPP_Macro *ym;
+
+    ym = yapp_macro_get(name);
+    if (ym) {
+       if ((argc >= 0 && ym->args < 0)
+           || (argc < 0 && ym->args >= 0))
+       {
+           yasm__warning(YASM_WARN_PREPROC, cur_lindex, N_("Attempted %%define both with and without parameters"));
+           return NULL;
+       }
+    }
+    else if (argc >= 0)
+    {
+       /* insert placeholder for paramlisted defines */
+       ym = yasm_xmalloc(sizeof(YAPP_Macro));
+       ym->type = YAPP_DEFINE;
+       ym->args = argc;
+       ym->fillargs = fillargs;
+       ym->expanding = 0;
+       HAMT_insert(macro_table, name, (void *)ym, &zero, (void (*)(void *))yapp_macro_error_exists);
+    }
+
+    /* now for the real one */
+    ym = yasm_xmalloc(sizeof(YAPP_Macro));
+    ym->type = YAPP_DEFINE;
+    ym->args = argc;
+    ym->fillargs = fillargs;
+    ym->expanding = 0;
+
+    if (argc>=0) {
+       mungename = yasm_xmalloc(strlen(name)+8);
+       sprintf(mungename, "%s(%d)", name, argc);
+    }
+
+    ydebug(("YAPP: +Inserting macro %s\n", mungename));
+
+    memcpy(&ym->macro_head, &macro_head, sizeof(macro_head));
+    memcpy(&ym->param_head, &param_head, sizeof(param_head));
+
+    HAMT_insert(macro_table, mungename, (void *)ym, &zero, (void (*)(void *))yapp_macro_error_exists);
+
+    SLIST_INIT(&macro_head);
+    SLIST_INIT(&param_head);
+
+    macro_tail = SLIST_FIRST(&macro_head);
+    param_tail = SLIST_FIRST(&param_head);
+
+    return ym;
+}
+
+void
+yapp_macro_delete (YAPP_Macro *ym)
+{
+    while (!SLIST_EMPTY(&ym->macro_head)) {
+       source *s = SLIST_FIRST(&ym->macro_head);
+       yasm_xfree(s);
+       SLIST_REMOVE_HEAD(&ym->macro_head, next);
+    }
+    yasm_xfree(ym);
+}
+
+static YAPP_Macro *
+yapp_macro_get (const char *key)
+{
+    return (YAPP_Macro *)HAMT_search(macro_table, key);
+}
+
+struct source_head *
+yapp_define_param_get (HAMT *hamt, const char *key)
+{
+    return (struct source_head *)HAMT_search(hamt, key);
+}
+
+/*****************************************************************************/
+
+void
+append_processed_token(source *tok, struct source_head *to_head, source **to_tail);
+
+void
+append_token(int token, struct source_head *to_head, source **to_tail);
+
+int
+append_to_return(struct source_head *to_head, source **to_tail);
+
+int
+eat_through_return(struct source_head *to_head, source **to_tail);
+
+int
+yapp_get_ident(const char *synlvl);
+
+void
+copy_token(YAPP_Token *tok, struct source_head *to_head, source **to_tail);
+
+void
+expand_macro(char *name,
+            struct source_head *from_head,
+            struct source_head *to_head,
+            source **to_tail);
+
+void
+expand_token_list(struct source_head *paramexp, struct source_head *to_head, source **to_tail);
+
+static void
+yapp_preproc_initialize(FILE *f, const char *in_filename, yasm_linemgr *lm)
+{
+    is_interactive = f ? (isatty(fileno(f)) > 0) : 0;
+    yapp_preproc_linemgr = lm;
+    yapp_preproc_current_file = yasm__xstrdup(in_filename);
+    yapp_preproc_line_number = 1;
+    yapp_lex_initialize(f);
+    SLIST_INIT(&output_head);
+    SLIST_INIT(&source_head);
+    SLIST_INIT(&macro_head);
+    SLIST_INIT(&param_head);
+    out = yasm_xmalloc(sizeof(output));
+    out->out = current_output = YAPP_OUTPUT;
+    SLIST_INSERT_HEAD(&output_head, out, next);
+
+    macro_table = HAMT_new(yasm_internal_error_);
+
+    source_tail = SLIST_FIRST(&source_head);
+    macro_tail = SLIST_FIRST(&macro_head);
+    param_tail = SLIST_FIRST(&param_head);
+
+    append_token(LINE, &source_head, &source_tail);
+}
+
+static void
+yapp_preproc_cleanup(void)
+{
+    /* TODO: clean up */
+}
+
+/* Generate a new level of if* context
+ * if val is true, this module of the current level will be output IFF the
+ * surrounding one is.
+ */
+static void
+push_if(int val)
+{
+    out = yasm_xmalloc(sizeof(output));
+    out->out = current_output;
+    SLIST_INSERT_HEAD(&output_head, out, next);
+
+    switch (current_output)
+    {
+       case YAPP_OUTPUT:
+           current_output = val ? YAPP_OUTPUT : YAPP_NO_OUTPUT;
+           break;
+
+       case YAPP_NO_OUTPUT:
+       case YAPP_OLD_OUTPUT:
+       case YAPP_BLOCKED_OUTPUT:
+           current_output = YAPP_BLOCKED_OUTPUT;
+           break;
+    }
+    if (current_output != YAPP_OUTPUT) set_inhibit();
+
+}
+
+/* Generate a new module in the current if* context
+ * if val is true and this level hasn't had a true, it will be output if the
+ * surrounding level is.
+ */
+static void
+push_else(int val)
+{
+    switch (current_output)
+    {
+       /* if it was NO, turn to output IFF val is true */
+       case YAPP_NO_OUTPUT:
+           current_output = val ? YAPP_OUTPUT : YAPP_NO_OUTPUT;
+           break;
+
+       /* if it was yes, make it OLD */
+       case YAPP_OUTPUT:
+           current_output = YAPP_OLD_OUTPUT;
+           break;
+
+       /* leave OLD as OLD, BLOCKED as BLOCKED */
+       case YAPP_OLD_OUTPUT:
+       case YAPP_BLOCKED_OUTPUT:
+           break;
+    }
+    if (current_output != YAPP_OUTPUT) set_inhibit();
+}
+
+/* Clear the curent if* context level */
+static void
+pop_if(void)
+{
+    out = SLIST_FIRST(&output_head);
+    current_output = out->out;
+    SLIST_REMOVE_HEAD(&output_head, next);
+    yasm_xfree(out);
+    if (current_output != YAPP_OUTPUT) set_inhibit();
+}
+
+/* undefine a symbol */
+static void
+yapp_undef(const char *key)
+{
+    int zero = 0;
+    HAMT_insert(macro_table, key, NULL, &zero, (void (*)(void *))yapp_macro_delete);
+}
+
+/* Is a symbol known to YAPP? */
+static int
+yapp_defined(const char *key)
+{
+    return yapp_macro_get(key) != NULL;
+}
+
+void
+append_processed_token(source *tok, struct source_head *to_head, source **to_tail)
+{
+    ydebug(("YAPP: appended token \"%s\"\n", tok->token.str));
+    if (*to_tail) {
+       SLIST_INSERT_AFTER(*to_tail, tok, next);
+    }
+    else {
+       SLIST_INSERT_HEAD(to_head, tok, next);
+    }
+    *to_tail = tok;
+    if (to_head == &source_head)
+       saved_length += strlen(tok->token.str);
+}
+
+void
+append_token(int token, struct source_head *to_head, source **to_tail)
+{
+    if (current_output != YAPP_OUTPUT) {
+       ydebug(("YAPP: append_token while not YAPP_OUTPUT\n"));
+       return;
+    }
+
+    /* attempt to condense LINES together or newlines onto LINES */
+    if ((*to_tail) && (*to_tail)->token.type == LINE
+       && (token == '\n' || token == LINE))
+    {
+       yasm_xfree ((*to_tail)->token.str);
+       (*to_tail)->token.str = yasm_xmalloc(23+strlen(yapp_preproc_current_file));
+       sprintf((*to_tail)->token.str, "%%line %d+1 %s\n", yapp_preproc_line_number, yapp_preproc_current_file);
+    }
+    else {
+       src = yasm_xmalloc(sizeof(source));
+       src->token.type = token;
+       switch (token)
+       {
+           case INTNUM:
+               src->token.str = yasm__xstrdup(yapp_preproc_lval.int_str_val.str);
+               src->token.val.int_val = yapp_preproc_lval.int_str_val.val;
+               break;
+
+           case FLTNUM:
+               src->token.str = yasm__xstrdup(yapp_preproc_lval.double_str_val.str);
+               src->token.val.double_val = yapp_preproc_lval.double_str_val.val;
+               break;
+
+           case STRING:
+           case WHITESPACE:
+               src->token.str = yasm__xstrdup(yapp_preproc_lval.str_val);
+               break;
+
+           case IDENT:
+               src->token.str = yasm__xstrdup(yapp_preproc_lval.str_val);
+               break;
+
+           case '+': case '-': case '*': case '/': case '%': case ',': case '\n':
+           case '[': case ']': case '(': case ')':
+               src->token.str = yasm_xmalloc(2);
+               src->token.str[0] = (char)token;
+               src->token.str[1] = '\0';
+               break;
+
+           case LINE:
+               /* TODO: consider removing any trailing newline or LINE tokens */
+               src->token.str = yasm_xmalloc(23+strlen(yapp_preproc_current_file));
+               sprintf(src->token.str, "%%line %d+1 %s\n", yapp_preproc_line_number, yapp_preproc_current_file);
+               break;
+
+           default:
+               yasm_xfree(src);
+               return;
+       }
+       append_processed_token(src, to_head, to_tail);
+    }
+}
+
+static void
+replay_saved_tokens(char *ident,
+                   struct source_head *from_head,
+                   struct source_head *to_head,
+                   source **to_tail)
+{
+    source *item, *after;
+    ydebug(("-No, %s didn't match any macro we have\n", ident));
+    /* this means a macro expansion failed.  stick its name and all the saved
+     * tokens into the output stream */
+    yapp_preproc_lval.str_val = ident;
+    append_token(IDENT, to_head, to_tail);
+
+    item = SLIST_FIRST(from_head);
+    while (item) {
+       after = SLIST_NEXT(item, next);
+       SLIST_INSERT_AFTER(*to_tail, item, next);
+       *to_tail = item;
+       saved_length += strlen(item->token.str);
+       item = after;
+    }
+    SLIST_INIT(from_head);
+}
+
+int
+append_to_return(struct source_head *to_head, source **to_tail)
+{
+    int token = yapp_preproc_lex();
+    while (token != '\n') {
+       ydebug(("YAPP: ATR: '%c' \"%s\"\n", token, yapp_preproc_lval.str_val));
+       if (token == 0)
+           return 0;
+       append_token(token, to_head, to_tail);
+       token = yapp_preproc_lex();
+    } 
+    return '\n';
+}
+
+int
+eat_through_return(struct source_head *to_head, source **to_tail)
+{
+    int token;
+    while ((token = yapp_preproc_lex()) != '\n') {
+       if (token == 0)
+           return 0;
+       yasm__error(cur_lindex, N_("Skipping possibly valid %%define stuff"));
+    }
+    append_token('\n', to_head, to_tail);
+    return '\n';
+}
+
+int
+yapp_get_ident(const char *synlvl)
+{
+    int token = yapp_preproc_lex();
+    if (token == WHITESPACE)
+       token = yapp_preproc_lex();
+    if (token != IDENT) {
+       yasm__error(cur_lindex, N_("Identifier expected after %%%s"), synlvl);
+    }
+    return token;
+}
+
+void
+copy_token(YAPP_Token *tok, struct source_head *to_head, source **to_tail)
+{
+    src = yasm_xmalloc(sizeof(source));
+    src->token.type = tok->type;
+    src->token.str = yasm__xstrdup(tok->str);
+
+    append_processed_token(src, to_head, to_tail);
+}
+
+void
+expand_macro(char *name,
+            struct source_head *from_head,
+            struct source_head *to_head,
+            source **to_tail)
+{
+    struct source_head replay_head, arg_head;
+    source *replay_tail, *arg_tail;
+
+    YAPP_Macro *ym = yapp_macro_get(name);
+
+    ydebug(("YAPP: +Expand macro %s...\n", name));
+
+    if (ym->expanding) yasm_internal_error(N_("Recursively expanding a macro!"));
+
+    if (ym->type == YAPP_DEFINE) {
+       if (ym->args == -1) {
+           /* no parens to deal with */
+           ym->expanding = 1;
+           expand_token_list(&ym->macro_head, to_head, to_tail);
+           ym->expanding = 0;
+       }
+       else
+       {
+           char *mungename;
+           int token;
+           int argc=0;
+           int parennest=0;
+           HAMT *param_table;
+           source *replay, *param;
+
+           ydebug(("YAPP: +Expanding multi-arg macro %s...\n", name));
+
+           /* Build up both a parameter reference list and a token buffer,
+            * because we won't know until we've reached the closing paren if
+            * we can actuall expand the macro or not.  bleah. */
+           /* worse, we can't build the parameter list until we know the
+            * parameter names, which we can't look up until we know the
+            * number of arguments.  sigh */
+           /* HMM */
+           SLIST_INIT(&replay_head);
+           replay_tail = SLIST_FIRST(&replay_head);
+
+           /* find out what we got */
+           if (from_head) {
+               yasm_internal_error(N_("Expanding macro with non-null from_head ugh\n"));
+           }
+           token = yapp_preproc_lex();
+           append_token(token, &replay_head, &replay_tail);
+           /* allow one whitespace */
+           if (token == WHITESPACE) {
+               ydebug(("Ignoring WS between macro and paren\n"));
+               token = yapp_preproc_lex();
+               append_token(token, &replay_head, &replay_tail);
+           }
+           if (token != '(') {
+               ydebug(("YAPP: -Didn't get to left paren; instead got '%c' \"%s\"\n", token, yapp_preproc_lval.str_val));
+               replay_saved_tokens(name, &replay_head, to_head, to_tail);
+               return;
+           }
+
+           /* at this point, we've got the left paren.  time to get annoyed */
+           while (token != ')') {
+               token = yapp_preproc_lex();
+               append_token(token, &replay_head, &replay_tail);
+               /* TODO: handle { } for commas?  or is that just macros? */
+               switch (token) {
+                   case '(':
+                       parennest++;
+                       break;
+
+                   case ')':
+                       if (parennest) {
+                           parennest--;
+                           token = ',';
+                       }
+                       else {
+                           argc++;
+                       }
+                       break;
+
+                   case ',':
+                       if (!parennest)
+                           argc++;
+                       break;
+
+                   case WHITESPACE: case IDENT: case INTNUM: case FLTNUM: case STRING:
+                   case '+': case '-': case '*': case '/':
+                       break;
+
+                   default:
+                       if (token < 256)
+                           yasm_internal_error(N_("Unexpected character token in parameter expansion"));
+                       else
+                           yasm__error(cur_lindex, N_("Cannot handle preprocessor items inside possible macro invocation"));
+               }
+           }
+
+           /* Now we have the argument count; let's see if it exists */
+           mungename = yasm_xmalloc(strlen(name)+8);
+           sprintf(mungename, "%s(%d)", name, argc);
+           ym = yapp_macro_get(mungename);
+           if (!ym)
+           {
+               ydebug(("YAPP: -Didn't find macro %s\n", mungename));
+               replay_saved_tokens(name, &replay_head, to_head, to_tail);
+               yasm_xfree(mungename);
+               return;
+           }
+           ydebug(("YAPP: +Found macro %s\n", mungename));
+
+           ym->expanding = 1;
+
+           /* so the macro exists. build a HAMT parameter table */
+           param_table = HAMT_new(yasm_internal_error_);
+           /* fill the entries by walking the replay buffer and create
+            * "macros".  coincidentally, clear the replay buffer. */
+
+           /* get to the opening paren */
+           replay = SLIST_FIRST(&replay_head);
+           while (replay->token.type != '(') {
+               ydebug(("YAPP: Ignoring replay token '%c' \"%s\"\n", replay->token.type, replay->token.str));
+               SLIST_REMOVE_HEAD(&replay_head, next);
+               yasm_xfree(replay->token.str);
+               yasm_xfree(replay);
+               replay = SLIST_FIRST(&replay_head);
+           }
+           ydebug(("YAPP: Ignoring replay token '%c' \"%s\"\n", replay->token.type, replay->token.str));
+
+           /* free the open paren */
+           SLIST_REMOVE_HEAD(&replay_head, next);
+           yasm_xfree(replay->token.str);
+           yasm_xfree(replay);
+
+           param = SLIST_FIRST(&ym->param_head);
+
+           SLIST_INIT(&arg_head);
+           arg_tail = SLIST_FIRST(&arg_head);
+
+           replay = SLIST_FIRST(&replay_head);
+           SLIST_REMOVE_HEAD(&replay_head, next);
+           while (parennest || replay) {
+               if (replay->token.type == '(') {
+                   parennest++;
+                   append_processed_token(replay, &arg_head, &arg_tail);
+                   ydebug(("YAPP: +add arg token '%c'\n", replay->token.type));
+               }
+               else if (parennest && replay->token.type == ')') {
+                   parennest--;
+                   append_processed_token(replay, &arg_head, &arg_tail);
+                   ydebug(("YAPP: +add arg token '%c'\n", replay->token.type));
+               }
+               else if ((!parennest) && (replay->token.type == ','
+                                         || replay->token.type == ')'))
+               {
+                   int zero=0;
+                   struct source_head *argmacro = yasm_xmalloc(sizeof(struct source_head));
+                   memcpy(argmacro, &arg_head, sizeof(struct source_head));
+                   SLIST_INIT(&arg_head);
+                   arg_tail = SLIST_FIRST(&arg_head);
+
+                   /* don't save the comma */
+                   yasm_xfree(replay->token.str);
+                   yasm_xfree(replay);
+
+                   HAMT_insert(param_table,
+                               param->token.str,
+                               (void *)argmacro,
+                               &zero,
+                               (void (*)(void *))yapp_macro_error_sameargname);
+                   param = SLIST_NEXT(param, next);
+               }
+               else if (replay->token.type == IDENT
+                        && yapp_defined(replay->token.str))
+               {
+                   ydebug(("YAPP: +add arg macro '%c' \"%s\"\n", replay->token.type, replay->token.str));
+                   expand_macro(replay->token.str, &replay_head, &arg_head, &arg_tail);
+               }
+               else if (arg_tail || replay->token.type != WHITESPACE) {
+                   ydebug(("YAPP: +else add arg token '%c' \"%s\"\n", replay->token.type, replay->token.str));
+                   append_processed_token(replay, &arg_head, &arg_tail);
+               }
+               replay = SLIST_FIRST(&replay_head);
+               if (replay) SLIST_REMOVE_HEAD(&replay_head, next);
+           }
+           if (replay) {
+               yasm_xfree(replay->token.str);
+               yasm_xfree(replay);
+           }
+           else if (param) {
+                 yasm_internal_error(N_("Got to end of arglist before end of replay!"));
+           }
+           replay = SLIST_FIRST(&replay_head);
+           if (replay || param)
+               yasm_internal_error(N_("Count and distribution of define args mismatched!"));
+
+           /* the param_table is set up without errors, so expansion is ready
+            * to go */
+           SLIST_FOREACH (replay, &ym->macro_head, next) {
+               if (replay->token.type == IDENT) {
+
+                   /* check local args first */
+                   struct source_head *paramexp =
+                       yapp_define_param_get(param_table, replay->token.str);
+
+                   if (paramexp) {
+                       expand_token_list(paramexp, to_head, to_tail);
+                   }
+                   else {
+                       /* otherwise, check macros */
+                       YAPP_Macro *imacro = yapp_macro_get(replay->token.str);
+                       if (imacro != NULL && !imacro->expanding) {
+                           expand_macro(replay->token.str, NULL, to_head, to_tail);
+                       }
+                       else {
+                           /* otherwise it's just a vanilla ident */
+                           copy_token(&replay->token, to_head, to_tail);
+                       }
+                   }
+               }
+               else {
+                   copy_token(&replay->token, to_head, to_tail);
+               }
+           }
+           ym->expanding = 0;
+       }
+    }
+    else
+       yasm_internal_error(N_("Invoking Macros not yet supported"));
+
+    ym->expanding = 0;
+}
+
+void
+expand_token_list(struct source_head *paramexp, struct source_head *to_head, source **to_tail)
+{
+    source *item;
+    SLIST_FOREACH (item, paramexp, next) {
+       if (item->token.type == IDENT) {
+           YAPP_Macro *imacro = yapp_macro_get(item->token.str);
+           if (imacro != NULL && !imacro->expanding) {
+               expand_macro(item->token.str, NULL, to_head, to_tail);
+           }
+           else {
+               copy_token(&item->token, to_head, to_tail);
+           }
+       }
+       else {
+           copy_token(&item->token, to_head, to_tail);
+       }
+    }
+}
+
+static size_t
+yapp_preproc_input(char *buf, size_t max_size)
+{
+    static YAPP_State state = YAPP_STATE_INITIAL;
+    size_t n = 0;
+    int token;
+    int need_line_directive = 0;
+
+    while ((size_t)saved_length < max_size && state != YAPP_STATE_EOF)
+    {
+       token = yapp_preproc_lex();
+
+       switch (state) {
+           case YAPP_STATE_INITIAL:
+               switch (token)
+               {
+                   char *s;
+                   default:
+                       append_token(token, &source_head, &source_tail);
+                       /*if (append_to_return()==0) state=YAPP_STATE_EOF;*/
+                       ydebug(("YAPP: default: '%c' \"%s\"\n", token, yapp_preproc_lval.str_val));
+                       /*yasm__error(cur_lindex, N_("YAPP got an unhandled token."));*/
+                       break;
+
+                   case IDENT:
+                       ydebug(("YAPP: ident: \"%s\"\n", yapp_preproc_lval.str_val));
+                       if (yapp_defined(yapp_preproc_lval.str_val)) {
+                           expand_macro(yapp_preproc_lval.str_val, NULL, &source_head, &source_tail);
+                       }
+                       else {
+                           append_token(token, &source_head, &source_tail);
+                       }
+                       break;
+
+                   case 0:
+                       state = YAPP_STATE_EOF;
+                       break;
+
+                   case '\n':
+                       append_token(token, &source_head, &source_tail);
+                       break;
+
+                   case CLEAR:
+                       HAMT_delete(macro_table, (void (*)(void *))yapp_macro_delete);
+                       macro_table = HAMT_new(yasm_internal_error_);
+                       break;
+
+                   case DEFINE:
+                       ydebug(("YAPP: define: "));
+                       token = yapp_get_ident("define");
+                           ydebug((" \"%s\"\n", yapp_preproc_lval.str_val));
+                       s = yasm__xstrdup(yapp_preproc_lval.str_val);
+
+                       /* three cases: newline or stuff or left paren */
+                       token = yapp_preproc_lex();
+                       if (token == '\n') {
+                           /* no args or content - just insert it */
+                           yapp_define_insert(s, -1, 0);
+                           append_token('\n', &source_head, &source_tail);
+                       }
+                       else if (token == WHITESPACE) {
+                           /* no parens */
+                           if(append_to_return(&macro_head, &macro_tail)==0) state=YAPP_STATE_EOF;
+                           else {
+                               yapp_define_insert(s, -1, 0);
+                           }
+                           append_token('\n', &source_head, &source_tail);
+                       }
+                       else if (token == '(') {
+                           /* get all params of the parameter list */
+                           /* ensure they alternate IDENT and ',' */
+                           int param_count = 0;
+                           int last_token = ',';
+
+                           ydebug((" *Getting arglist for define %s\n", s));
+
+                           while ((token = yapp_preproc_lex())!=')') {
+                               ydebug(("YAPP: +read token '%c' \"%s\" for macro %s\n", token, yapp_preproc_lval.str_val, s));
+                               if (token == WHITESPACE) {
+                                   token = last_token;
+                               }
+                               else if (last_token == ',' && token == IDENT) {
+                                   append_token(token, &param_head, &param_tail);
+                                   param_count++;
+                               }
+                               else if (token == 0) {
+                                   state = YAPP_STATE_EOF;
+                                   break;
+                               }
+                               else if (last_token == ',' || token != ',')
+                                   yasm__error(cur_lindex, N_("Unexpected token in %%define parameters"));
+                               last_token = token;
+                           }
+                           if (token == ')') {
+                               /* after paramlist and ')' */
+                               /* everything is what it's defined to be */
+                               token = yapp_preproc_lex();
+                               if (token != WHITESPACE) append_token(token, &macro_head, &macro_tail);
+                               if (append_to_return(&macro_head, &macro_tail)==0) state=YAPP_STATE_EOF;
+                               else {
+                                   ydebug(("YAPP: Inserting define macro %s (%d)\n", s, param_count));
+                                   yapp_define_insert(s, param_count, 0);
+                               }
+                           }
+                           append_token('\n', &source_head, &source_tail);
+                       }
+                       else {
+                           yasm_internal_error(N_("%%define ... failed miserably - neither \\n, WS, or ( followed ident"));
+                       }
+                       break;
+
+                   case UNDEF:
+                       token = yapp_get_ident("undef");
+                       yapp_undef(yapp_preproc_lval.str_val);
+                       state = YAPP_STATE_NEED_EOL;
+                       break;
+
+                   case IFDEF:
+                       token = yapp_get_ident("ifdef");
+                       push_if(yapp_defined(yapp_preproc_lval.str_val));
+                       state = YAPP_STATE_NEED_EOL;
+                       break;
+
+                   case IFNDEF:
+                       token = yapp_get_ident("ifndef");
+                       push_if(!yapp_defined(yapp_preproc_lval.str_val));
+                       state = YAPP_STATE_NEED_EOL;
+                       break;
+
+                   case ELSE:
+                       push_else(1);
+                       if (current_output == YAPP_OUTPUT) need_line_directive = 1;
+                       state = YAPP_STATE_NEED_EOL;
+                       break;
+
+                   case ELIFDEF:
+                       token = yapp_get_ident("elifdef");
+                       push_else(yapp_defined(yapp_preproc_lval.str_val));
+                       if (current_output == YAPP_OUTPUT) need_line_directive = 1;
+                       state = YAPP_STATE_NEED_EOL;
+                       break;
+
+                   case ELIFNDEF:
+                       token = yapp_get_ident("elifndef");
+                       push_else(!yapp_defined(yapp_preproc_lval.str_val));
+                       if (current_output == YAPP_OUTPUT) need_line_directive = 1;
+                       state = YAPP_STATE_NEED_EOL;
+                       break;
+
+                   case ENDIF:
+                       /* there's got to be another way to do this:   */
+                       /* only set if going from non-output to output */
+                       if (current_output != YAPP_OUTPUT) need_line_directive = 1;
+                       pop_if();
+                       if (current_output != YAPP_OUTPUT) need_line_directive = 0;
+                       state = YAPP_STATE_NEED_EOL;
+                       break;
+
+                   case INCLUDE:
+                   case LINE:
+                       need_line_directive = 1;
+                       break;
+               }
+               if (state == YAPP_STATE_NEED_EOL)
+               {
+                   if (eat_through_return(&source_head, &source_tail)==0) state=YAPP_STATE_EOF;
+                   else state=YAPP_STATE_INITIAL;
+               }
+               break;
+           default:
+               yasm__error(cur_lindex, N_("YAPP got into a bad state"));
+       }
+       if (need_line_directive) {
+           append_token(LINE, &source_head, &source_tail);
+           need_line_directive = 0;
+       }
+    }
+
+    /* convert saved stuff into output.  we either have enough, or are EOF */
+    while (n < max_size && saved_length)
+    {
+       src = SLIST_FIRST(&source_head);
+       if (max_size - n >= strlen(src->token.str)) {
+           strcpy(buf+n, src->token.str);
+           n += strlen(src->token.str);
+
+           saved_length -= strlen(src->token.str);
+           SLIST_REMOVE_HEAD(&source_head, next);
+           yasm_xfree(src->token.str);
+           yasm_xfree(src);
+       }
+    }
+
+    return n;
+}
+
+/* Define preproc structure -- see preproc.h for details */
+yasm_preproc yasm_yapp_LTX_preproc = {
+    "YAPP preprocessing (NASM style)",
+    "yapp",
+    yapp_preproc_initialize,
+    yapp_preproc_cleanup,
+    yapp_preproc_input
+};
diff --git a/modules/preprocs/yapp/yapp-preproc.h b/modules/preprocs/yapp/yapp-preproc.h
new file mode 100644 (file)
index 0000000..531d6b1
--- /dev/null
@@ -0,0 +1,58 @@
+/* $IdPath$
+ * YAPP preprocessor (mimics NASM's preprocessor) header file
+ *
+ *   Copyright (C) 2001  Michael Urman
+ *
+ *   This file is part of YASM.
+ *
+ *   YASM 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 of the License, or
+ *   (at your option) any later version.
+ *
+ *   YASM 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/* Representation of tokenized file, both for straight source, and macros */
+typedef struct YAPP_Token_s {
+    unsigned int type;
+    char *str;
+    union {
+       unsigned int int_val;
+       double double_val;
+       char *str_val;
+    } val;
+} YAPP_Token;
+
+/* internal state of preprocessor's parser */
+typedef enum {
+    YAPP_STATE_INITIAL = 0,
+    YAPP_STATE_ASSIGN,
+    YAPP_STATE_DEFINING_MACRO,
+    YAPP_STATE_BUILDING_MACRO,
+    YAPP_STATE_NEED_EOL,
+    YAPP_STATE_EOF
+} YAPP_State;
+
+/* tracks nested %if* %elif* %else %endif structures */
+typedef enum {
+    YAPP_OUTPUT,       /* this level+module outputs */
+    YAPP_NO_OUTPUT,    /* this would never output */
+    YAPP_OLD_OUTPUT,   /* this level has already output */
+    YAPP_BLOCKED_OUTPUT /* the surrounding level is not outputting */
+} YAPP_Output;
+
+void yapp_lex_initialize(FILE *f);
+void set_inhibit(void);
+
+extern /*@dependent@*/ yasm_linemgr *yapp_preproc_linemgr;
+#define cur_lindex     (yapp_preproc_linemgr->get_current())
+
diff --git a/modules/preprocs/yapp/yapp-token.h b/modules/preprocs/yapp/yapp-token.h
new file mode 100644 (file)
index 0000000..4301249
--- /dev/null
@@ -0,0 +1,64 @@
+typedef union {
+    char *str_val;
+    struct {
+       char *str;
+       unsigned long val;
+    } int_str_val;
+    struct {
+       char *str;
+       double val;
+    } double_str_val;
+} YYSTYPE;
+#define        INTNUM  257
+#define        FLTNUM  258
+#define        STRING  259
+#define        IDENT   260
+#define        CLEAR   261
+#define        INCLUDE 262
+#define        LINE    263
+#define        DEFINE  264
+#define        UNDEF   265
+#define        ASSIGN  266
+#define        MACRO   267
+#define        ENDMACRO        268
+#define        ROTATE  269
+#define        REP     270
+#define        EXITREP 271
+#define        ENDREP  272
+#define        IF      273
+#define        ELIF    274
+#define        ELSE    275
+#define        ENDIF   276
+#define        IFDEF   277
+#define        ELIFDEF 278
+#define        IFNDEF  279
+#define        ELIFNDEF        280
+#define        IFCTX   281
+#define        ELIFCTX 282
+#define        IFIDN   283
+#define        ELIFIDN 284
+#define        IFIDNI  285
+#define        ELIFIDNI        286
+#define        IFID    287
+#define        ELIFID  288
+#define        IFNUM   289
+#define        ELIFNUM 290
+#define        IFSTR   291
+#define        ELIFSTR 292
+#define        ERROR   293
+#define        PUSH    294
+#define        POP     295
+#define        REPL    296
+#define        LEFT_OP 297
+#define        RIGHT_OP        298
+#define        SIGNDIV 299
+#define        SIGNMOD 300
+#define        UNARYOP 301
+#define        WHITESPACE      302
+
+
+extern YYSTYPE yapp_preproc_lval;
+extern char *yapp_preproc_current_file;
+extern int yapp_preproc_line_number;
+
+int yapp_preproc_lex(void);
diff --git a/modules/preprocs/yapp/yapp-token.l b/modules/preprocs/yapp/yapp-token.l
new file mode 100644 (file)
index 0000000..7889ea3
--- /dev/null
@@ -0,0 +1,355 @@
+/* $IdPath$
+ * YAPP lexer
+ *
+ *  Copyright (C) 2001  Michael Urman
+ *
+ *  This file is part of YASM.
+ *
+ *  YASM 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 of the License, or
+ *  (at your option) any later version.
+ *
+ *  YASM 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+%{
+#define YASM_LIB_INTERNAL
+#include "libyasm.h"
+/*@unused@*/ RCSID("$IdPath$");
+
+#include <errno.h>
+
+#include "modules/preprocs/yapp/yapp-preproc.h"
+#include "modules/preprocs/yapp/yapp-token.h"
+
+
+#define yylval yapp_preproc_lval
+
+#define malloc yasm_xmalloc
+#define realloc yasm_xrealloc
+
+/* starting size of string buffer */
+#define STRBUF_ALLOC_SIZE      128
+
+/* string buffer used when parsing strings/character constants */
+static char *strbuf = (char *)NULL;
+
+/* length of strbuf (including terminating NULL character) */
+static size_t strbuf_size = 0;
+
+/* include file mumbo jumbo */
+static SLIST_HEAD(include_head, include_s) includes_head;
+struct include_s {
+    SLIST_ENTRY(include_s) next;
+    YY_BUFFER_STATE include_state;
+    char *filename;
+    int line_number;
+};
+typedef struct include_s include;
+
+char *yapp_preproc_current_file;
+int yapp_preproc_line_number;
+
+%}
+%option noyywrap
+%option nounput
+%option case-insensitive
+%option prefix="yapp_preproc_"
+%option outfile="lex.yy.c"
+
+%x D
+%x incl
+%x line
+%x inhibit
+
+DIGIT    [0-9]
+BINDIGIT [01]
+OCTDIGIT [0-7]
+HEXDIGIT [0-9a-f]
+WS       [ \t]
+DIR     %[ \t]*
+
+%%
+
+    /* standard decimal integer */
+{DIGIT}+ {
+    yylval.int_str_val.val = strtoul(yytext, (char **)NULL, 10);
+    yylval.int_str_val.str = yytext;
+    return INTNUM;
+}
+
+    /* 10010011b - binary number */
+{BINDIGIT}+b {
+    yylval.int_str_val.val = strtoul(yytext, (char **)NULL, 2);
+    yylval.int_str_val.str = yytext;
+    return INTNUM;
+}
+
+    /* 777q - octal number */
+{OCTDIGIT}+q {
+    yylval.int_str_val.val = strtoul(yytext, (char **)NULL, 8);
+    yylval.int_str_val.str = yytext;
+    return INTNUM;
+}
+
+    /* 0AAh form of hexidecimal number */
+0{HEXDIGIT}+h {
+    yylval.int_str_val.val = strtoul(yytext+1, (char **)NULL, 16);
+    yylval.int_str_val.str = yytext;
+    return INTNUM;
+}
+
+    /* $0AA and 0xAA forms of hexidecimal number */
+(\$0|0x){HEXDIGIT}+ {
+    yylval.int_str_val.val = strtoul(yytext+2, (char **)NULL, 16);
+    yylval.int_str_val.str = yytext;
+    return INTNUM;
+}
+
+    /* floating point value */
+{DIGIT}+\.{DIGIT}*(e[-+]?{DIGIT}+)? {
+    yylval.double_str_val.val = strtod(yytext, (char **)NULL);
+    yylval.double_str_val.str = yytext;
+    return FLTNUM;
+}
+
+    /* string/character constant values */
+["']   {
+    int inch;
+    size_t count;
+    char endch = yytext[0];
+
+    strbuf = yasm_xmalloc(STRBUF_ALLOC_SIZE);
+
+    strbuf_size = STRBUF_ALLOC_SIZE;
+    inch = input();
+    count = 0;
+    while(inch != EOF && inch != endch && inch != '\n') {
+       strbuf[count++] = inch;
+       if(count >= strbuf_size) {
+           strbuf = yasm_xrealloc(strbuf, strbuf_size + STRBUF_ALLOC_SIZE);
+           strbuf_size += STRBUF_ALLOC_SIZE;
+       }
+       inch = input();
+    }
+
+    if(inch == '\n')
+       yasm__error(cur_lindex, N_("unterminated string"));
+    else if(inch == EOF)
+       yasm__error(cur_lindex, N_("unexpected end of file in string"));
+
+    strbuf[count] = '\0';
+
+    yylval.str_val = strbuf;
+    return STRING;
+}
+
+    /* identifiers */
+\.\.[a-z0-9_$#@~.?]+ |
+\.[a-z0-9_$#@~?][a-z0-9_$#@~.?]* | 
+[a-z_?][a-z0-9_$#@~.?]* {
+    yylval.str_val = yasm__xstrdup(yytext);
+    return IDENT;
+}
+
+    /* includes - based on flex manual handling of include files */
+<inhibit>{DIR}include[^\n]* ;
+{DIR}include  BEGIN(incl);
+    /* note the " handling here is a hack that doesn't accept useful
+     * things (like spaces, or quotes).  fix it later */
+<incl>[ \t"]*  /* eat whitespace */
+<incl>[^ \t\n"]* { /* have the filename */
+    include *inc;
+    FILE *incfile;
+    inc = yasm_xmalloc(sizeof(include));
+    inc->include_state = YY_CURRENT_BUFFER;
+
+    /* FIXME: handle includes that aren't relative */
+    incfile = fopen (yytext, "r");
+    if(!incfile) {
+       yasm__error(cur_lindex, N_("include file `%s': %s"),
+                   yytext, strerror(errno));
+       yasm_xfree(inc);
+    }
+    else {
+       yyin = incfile;
+       inc->filename = yapp_preproc_current_file;
+       inc->line_number = yapp_preproc_line_number;
+       SLIST_INSERT_HEAD(&includes_head, inc, next);
+
+       yapp_preproc_line_number = 1;
+       yapp_preproc_current_file = yasm__xstrdup(yytext);
+       BEGIN(INITIAL);
+       yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
+    }
+    return INCLUDE;
+}
+
+    /* end includes - note that it's not in <incl> at the time */
+<<EOF>> {
+    if(SLIST_EMPTY(&includes_head)) {
+       yyterminate();
+    }
+    else {
+       include *inc;
+       inc = SLIST_FIRST(&includes_head);
+       yy_delete_buffer (YY_CURRENT_BUFFER);
+       yy_switch_to_buffer (inc->include_state);
+       yasm_xfree(yapp_preproc_current_file);
+       yapp_preproc_current_file = inc->filename;
+       yapp_preproc_line_number = inc->line_number + 1;
+       SLIST_REMOVE_HEAD(&includes_head, next);
+       yasm_xfree(inc);
+
+       BEGIN(incl);
+       return INCLUDE;
+    }
+}
+
+<incl>["]{WS}*\n    BEGIN(INITIAL);
+
+
+    /* directive: % directive [args] */
+<inhibit>{DIR}clear[^\n]    ;
+{DIR}clear    return CLEAR;
+
+<inhibit>{DIR}line[^\n]    ;
+{DIR}line     BEGIN(line);
+<line>{DIGIT}+     yapp_preproc_line_number = strtoul(yytext, (char **)NULL, 10);
+<line>{DIGIT}+{WS}*\n  {
+    yapp_preproc_line_number = strtoul(yytext, (char **)NULL, 10);
+    BEGIN(INITIAL);
+    return LINE;
+}
+<line>{WS}+["]     ;   /* eat space before file */
+<line>[^ \t\n"]*    { /* have the filename */
+    yasm_xfree(yapp_preproc_current_file);
+    yapp_preproc_current_file = yasm__xstrdup(yytext);
+}
+<line>["]{WS}*\n    {
+    BEGIN(INITIAL);
+    return LINE;
+}
+
+{DIR}define   return DEFINE;
+{DIR}undef    return UNDEF;
+{DIR}assign   return ASSIGN;
+{DIR}macro    return MACRO;
+{DIR}endmacro return ENDMACRO;
+{DIR}rotate   return ROTATE;
+<inhibit>{DIR}define[^\n]*     ;
+<inhibit>{DIR}undef[^\n]*      ;
+<inhibit>{DIR}assign[^\n]*     ;
+<inhibit>{DIR}macro[^\n]*      ;
+<inhibit>{DIR}endmacro[^\n]*   ;
+<inhibit>{DIR}rotate[^\n]*     ;
+
+    /* preprocessor loops */
+{DIR}rep      return REP;
+{DIR}exitrep  return EXITREP;
+{DIR}endrep   return ENDREP;
+<inhibit>{DIR}rep[^\n]*        ;
+<inhibit>{DIR}exitrep[^\n]*    ;
+<inhibit>{DIR}endrep[^\n]*     ;
+
+{DIR}if       return IF;
+{DIR}elif     return ELIF;
+{DIR}else     return ELSE;
+{DIR}endif    return ENDIF;
+<inhibit>{DIR}if       { BEGIN(INITIAL); return IF; }
+<inhibit>{DIR}elif     { BEGIN(INITIAL); return ELIF; }
+<inhibit>{DIR}else     { BEGIN(INITIAL); return ELSE; }
+<inhibit>{DIR}endif    { BEGIN(INITIAL); return ENDIF; }
+
+    /* test defines */
+{DIR}ifdef    return IFDEF;
+{DIR}elifdef  return ELIFDEF;
+{DIR}ifndef   return IFNDEF;
+{DIR}elifndef return ELIFNDEF;
+<inhibit>{DIR}ifdef    { BEGIN(INITIAL); return IFDEF; }
+<inhibit>{DIR}elifdef  { BEGIN(INITIAL); return ELIFDEF; }
+<inhibit>{DIR}ifndef   { BEGIN(INITIAL); return IFNDEF; }
+<inhibit>{DIR}elifndef { BEGIN(INITIAL); return ELIFNDEF; }
+
+    /* test context stack */
+{DIR}ifctx    return IFCTX;
+{DIR}elifctx  return ELIFCTX;
+<inhibit>{DIR}ifctx    { BEGIN(INITIAL); return IFCTX; }
+<inhibit>{DIR}elifctx  { BEGIN(INITIAL); return ELIFCTX; }
+
+    /* test exact identity */
+{DIR}ifidn    return IFIDN;
+{DIR}elifidn  return ELIFIDN;
+{DIR}ifidni   return IFIDNI;
+{DIR}elifidni return ELIFIDNI;
+<inhibit>{DIR}ifidn    { BEGIN(INITIAL); return IFIDN; }
+<inhibit>{DIR}elifidn  { BEGIN(INITIAL); return ELIFIDN; }
+<inhibit>{DIR}ifidni   { BEGIN(INITIAL); return IFIDNI; }
+<inhibit>{DIR}elifidni { BEGIN(INITIAL); return ELIFIDNI; }
+
+    /* test token types */
+{DIR}ifid     return IFID;
+{DIR}elifid   return ELIFID;
+{DIR}ifnum    return IFNUM;
+{DIR}elifnum  return ELIFNUM;
+{DIR}ifstr    return IFSTR;
+{DIR}elifstr  return ELIFSTR;
+<inhibit>{DIR}ifid     { BEGIN(INITIAL); return IFID; }
+<inhibit>{DIR}elifid   { BEGIN(INITIAL); return ELIFID; }
+<inhibit>{DIR}ifnum    { BEGIN(INITIAL); return IFNUM; }
+<inhibit>{DIR}elifnum  { BEGIN(INITIAL); return ELIFNUM; }
+<inhibit>{DIR}ifstr    { BEGIN(INITIAL); return IFSTR; }
+<inhibit>{DIR}elifstr  { BEGIN(INITIAL); return ELIFSTR; }
+
+    /* error reporting */
+<inhibit>{DIR}error[^\n]*  ;
+{DIR}error[ ]+.*    { yylval.str_val = yytext; return ERROR; }
+
+    /* context stack management */
+{DIR}push     return PUSH;
+{DIR}pop      return POP;
+{DIR}repl     return REPL;
+<inhibit>{DIR}push[^\n]*  ;
+<inhibit>{DIR}pop[^\n]*  ;
+<inhibit>{DIR}repl[^\n]*  ;
+
+<inhibit>[^%\n]*\n { yapp_preproc_line_number++; return '\n'; }
+
+;.*\n  { yapp_preproc_line_number++; return '\n'; }
+
+{WS}+  { yylval.str_val = yytext; return WHITESPACE; }
+
+{WS}*\n        { yapp_preproc_line_number++; return '\n'; }
+
+
+[][+*/,()-] { return yytext[0]; }
+
+<inhibit>.  {
+    yasm__warning(YASM_WARN_PREPROC, cur_lindex, N_("Unhandled character in <inhibit> `%s'"), yasm__conv_unprint(yytext[0]));
+}
+
+.      {
+    yasm__warning(YASM_WARN_PREPROC, cur_lindex, N_("ignoring unrecognized character `%s'"),
+                   yasm__conv_unprint(yytext[0]));
+}
+
+%%
+
+void
+yapp_lex_initialize(FILE *f)
+{
+    SLIST_INIT(&includes_head);
+    yyin = f;
+}
+
+void set_inhibit(void)
+{
+    BEGIN(inhibit);
+}