From a93688b17281e4b464fc59cd453cdd2d0207e47f Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Sat, 16 Sep 2006 02:22:08 +0000 Subject: [PATCH] Resurrect yapp from revision 998. svn path=/trunk/yasm/; revision=1614 --- modules/preprocs/yapp/Makefile.inc | 18 + modules/preprocs/yapp/tests/Makefile.inc | 26 + modules/preprocs/yapp/tests/comment.asm | 2 + modules/preprocs/yapp/tests/comment.pre | 2 + modules/preprocs/yapp/tests/ddefine.asm | 6 + modules/preprocs/yapp/tests/ddefine.pre | 5 + modules/preprocs/yapp/tests/define.asm | 4 + modules/preprocs/yapp/tests/define.pre | 3 + modules/preprocs/yapp/tests/ifdef.asm | 13 + modules/preprocs/yapp/tests/ifdef.pre | 5 + modules/preprocs/yapp/tests/include.asm | 5 + modules/preprocs/yapp/tests/include.pre | 10 + modules/preprocs/yapp/tests/params.asm | 2 + modules/preprocs/yapp/tests/params.pre | 2 + modules/preprocs/yapp/tests/pdefine.asm | 6 + modules/preprocs/yapp/tests/pdefine.pre | 5 + modules/preprocs/yapp/tests/raw.asm | 1 + modules/preprocs/yapp/tests/raw.pre | 2 + modules/preprocs/yapp/tests/rdefine.asm | 6 + modules/preprocs/yapp/tests/rdefine.pre | 5 + modules/preprocs/yapp/tests/rinclude.asm | 5 + modules/preprocs/yapp/tests/rinclude.pre | 3 + modules/preprocs/yapp/tests/yapp_test.sh | 60 ++ modules/preprocs/yapp/yapp-preproc.c | 952 +++++++++++++++++++++++ modules/preprocs/yapp/yapp-preproc.h | 58 ++ modules/preprocs/yapp/yapp-token.h | 64 ++ modules/preprocs/yapp/yapp-token.l | 355 +++++++++ 27 files changed, 1625 insertions(+) create mode 100644 modules/preprocs/yapp/Makefile.inc create mode 100644 modules/preprocs/yapp/tests/Makefile.inc create mode 100644 modules/preprocs/yapp/tests/comment.asm create mode 100644 modules/preprocs/yapp/tests/comment.pre create mode 100644 modules/preprocs/yapp/tests/ddefine.asm create mode 100644 modules/preprocs/yapp/tests/ddefine.pre create mode 100644 modules/preprocs/yapp/tests/define.asm create mode 100644 modules/preprocs/yapp/tests/define.pre create mode 100644 modules/preprocs/yapp/tests/ifdef.asm create mode 100644 modules/preprocs/yapp/tests/ifdef.pre create mode 100644 modules/preprocs/yapp/tests/include.asm create mode 100644 modules/preprocs/yapp/tests/include.pre create mode 100644 modules/preprocs/yapp/tests/params.asm create mode 100644 modules/preprocs/yapp/tests/params.pre create mode 100644 modules/preprocs/yapp/tests/pdefine.asm create mode 100644 modules/preprocs/yapp/tests/pdefine.pre create mode 100644 modules/preprocs/yapp/tests/raw.asm create mode 100644 modules/preprocs/yapp/tests/raw.pre create mode 100644 modules/preprocs/yapp/tests/rdefine.asm create mode 100644 modules/preprocs/yapp/tests/rdefine.pre create mode 100644 modules/preprocs/yapp/tests/rinclude.asm create mode 100644 modules/preprocs/yapp/tests/rinclude.pre create mode 100755 modules/preprocs/yapp/tests/yapp_test.sh create mode 100644 modules/preprocs/yapp/yapp-preproc.c create mode 100644 modules/preprocs/yapp/yapp-preproc.h create mode 100644 modules/preprocs/yapp/yapp-token.h create mode 100644 modules/preprocs/yapp/yapp-token.l diff --git a/modules/preprocs/yapp/Makefile.inc b/modules/preprocs/yapp/Makefile.inc new file mode 100644 index 00000000..c935c6e7 --- /dev/null +++ b/modules/preprocs/yapp/Makefile.inc @@ -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 index 00000000..7dd1285f --- /dev/null +++ b/modules/preprocs/yapp/tests/Makefile.inc @@ -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 index 00000000..e41966d4 --- /dev/null +++ b/modules/preprocs/yapp/tests/comment.asm @@ -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 index 00000000..6d0bfdd3 --- /dev/null +++ b/modules/preprocs/yapp/tests/comment.pre @@ -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 index 00000000..ae46fc6f --- /dev/null +++ b/modules/preprocs/yapp/tests/ddefine.asm @@ -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 index 00000000..5d2f788d --- /dev/null +++ b/modules/preprocs/yapp/tests/ddefine.pre @@ -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 index 00000000..f9330d39 --- /dev/null +++ b/modules/preprocs/yapp/tests/define.asm @@ -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 index 00000000..b631ba28 --- /dev/null +++ b/modules/preprocs/yapp/tests/define.pre @@ -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 index 00000000..b9d7807e --- /dev/null +++ b/modules/preprocs/yapp/tests/ifdef.asm @@ -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 index 00000000..4031163b --- /dev/null +++ b/modules/preprocs/yapp/tests/ifdef.pre @@ -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 index 00000000..08b1b487 --- /dev/null +++ b/modules/preprocs/yapp/tests/include.asm @@ -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 index 00000000..ea172aca --- /dev/null +++ b/modules/preprocs/yapp/tests/include.pre @@ -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 index 00000000..046775e8 --- /dev/null +++ b/modules/preprocs/yapp/tests/params.asm @@ -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 index 00000000..dc2cd987 --- /dev/null +++ b/modules/preprocs/yapp/tests/params.pre @@ -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 index 00000000..ebde9222 --- /dev/null +++ b/modules/preprocs/yapp/tests/pdefine.asm @@ -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 index 00000000..553799d9 --- /dev/null +++ b/modules/preprocs/yapp/tests/pdefine.pre @@ -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 index 00000000..9d5f67f6 --- /dev/null +++ b/modules/preprocs/yapp/tests/raw.asm @@ -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 index 00000000..3bf60621 --- /dev/null +++ b/modules/preprocs/yapp/tests/raw.pre @@ -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 index 00000000..c4b1644b --- /dev/null +++ b/modules/preprocs/yapp/tests/rdefine.asm @@ -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 index 00000000..dfc1bfac --- /dev/null +++ b/modules/preprocs/yapp/tests/rdefine.pre @@ -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 index 00000000..43f3efea --- /dev/null +++ b/modules/preprocs/yapp/tests/rinclude.asm @@ -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 index 00000000..63ac7fcd --- /dev/null +++ b/modules/preprocs/yapp/tests/rinclude.pre @@ -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 index 00000000..28e42ea8 --- /dev/null +++ b/modules/preprocs/yapp/tests/yapp_test.sh @@ -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 index 00000000..e8e647c0 --- /dev/null +++ b/modules/preprocs/yapp/yapp-preproc.c @@ -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 +/*@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 + +#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, ¯o_head, sizeof(macro_head)); + + SLIST_INIT(¯o_head); + macro_tail = SLIST_FIRST(¯o_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, ¯o_head, sizeof(macro_head)); + memcpy(&ym->param_head, ¶m_head, sizeof(param_head)); + + HAMT_insert(macro_table, mungename, (void *)ym, &zero, (void (*)(void *))yapp_macro_error_exists); + + SLIST_INIT(¯o_head); + SLIST_INIT(¶m_head); + + macro_tail = SLIST_FIRST(¯o_head); + param_tail = SLIST_FIRST(¶m_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(¯o_head); + SLIST_INIT(¶m_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(¯o_head); + param_tail = SLIST_FIRST(¶m_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(¯o_head, ¯o_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, ¶m_head, ¶m_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, ¯o_head, ¯o_tail); + if (append_to_return(¯o_head, ¯o_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 index 00000000..531d6b10 --- /dev/null +++ b/modules/preprocs/yapp/yapp-preproc.h @@ -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 index 00000000..43012495 --- /dev/null +++ b/modules/preprocs/yapp/yapp-token.h @@ -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 index 00000000..7889ea3f --- /dev/null +++ b/modules/preprocs/yapp/yapp-token.l @@ -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 + +#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 */ +{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 */ +[ \t"]* /* eat whitespace */ +[^ \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 at the time */ +<> { + 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; + } +} + +["]{WS}*\n BEGIN(INITIAL); + + + /* directive: % directive [args] */ +{DIR}clear[^\n] ; +{DIR}clear return CLEAR; + +{DIR}line[^\n] ; +{DIR}line BEGIN(line); +{DIGIT}+ yapp_preproc_line_number = strtoul(yytext, (char **)NULL, 10); +{DIGIT}+{WS}*\n { + yapp_preproc_line_number = strtoul(yytext, (char **)NULL, 10); + BEGIN(INITIAL); + return LINE; +} +{WS}+["] ; /* eat space before file */ +[^ \t\n"]* { /* have the filename */ + yasm_xfree(yapp_preproc_current_file); + yapp_preproc_current_file = yasm__xstrdup(yytext); +} +["]{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; +{DIR}define[^\n]* ; +{DIR}undef[^\n]* ; +{DIR}assign[^\n]* ; +{DIR}macro[^\n]* ; +{DIR}endmacro[^\n]* ; +{DIR}rotate[^\n]* ; + + /* preprocessor loops */ +{DIR}rep return REP; +{DIR}exitrep return EXITREP; +{DIR}endrep return ENDREP; +{DIR}rep[^\n]* ; +{DIR}exitrep[^\n]* ; +{DIR}endrep[^\n]* ; + +{DIR}if return IF; +{DIR}elif return ELIF; +{DIR}else return ELSE; +{DIR}endif return ENDIF; +{DIR}if { BEGIN(INITIAL); return IF; } +{DIR}elif { BEGIN(INITIAL); return ELIF; } +{DIR}else { BEGIN(INITIAL); return ELSE; } +{DIR}endif { BEGIN(INITIAL); return ENDIF; } + + /* test defines */ +{DIR}ifdef return IFDEF; +{DIR}elifdef return ELIFDEF; +{DIR}ifndef return IFNDEF; +{DIR}elifndef return ELIFNDEF; +{DIR}ifdef { BEGIN(INITIAL); return IFDEF; } +{DIR}elifdef { BEGIN(INITIAL); return ELIFDEF; } +{DIR}ifndef { BEGIN(INITIAL); return IFNDEF; } +{DIR}elifndef { BEGIN(INITIAL); return ELIFNDEF; } + + /* test context stack */ +{DIR}ifctx return IFCTX; +{DIR}elifctx return ELIFCTX; +{DIR}ifctx { BEGIN(INITIAL); return IFCTX; } +{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; +{DIR}ifidn { BEGIN(INITIAL); return IFIDN; } +{DIR}elifidn { BEGIN(INITIAL); return ELIFIDN; } +{DIR}ifidni { BEGIN(INITIAL); return IFIDNI; } +{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; +{DIR}ifid { BEGIN(INITIAL); return IFID; } +{DIR}elifid { BEGIN(INITIAL); return ELIFID; } +{DIR}ifnum { BEGIN(INITIAL); return IFNUM; } +{DIR}elifnum { BEGIN(INITIAL); return ELIFNUM; } +{DIR}ifstr { BEGIN(INITIAL); return IFSTR; } +{DIR}elifstr { BEGIN(INITIAL); return ELIFSTR; } + + /* error reporting */ +{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; +{DIR}push[^\n]* ; +{DIR}pop[^\n]* ; +{DIR}repl[^\n]* ; + +[^%\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]; } + +. { + yasm__warning(YASM_WARN_PREPROC, cur_lindex, N_("Unhandled character in `%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); +} -- 2.40.0