From: Peter Johnson Date: Sun, 19 Aug 2001 02:15:18 +0000 (-0000) Subject: New modular directory structure: parsers, preprocs, and outfmts. X-Git-Tag: v0.1.0~378 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7ba343f3468d77f80d67a5b037c222f6d479f078;p=yasm New modular directory structure: parsers, preprocs, and outfmts. Moved token.l.in, bison.y.in, and gen_instr.pl to parsers/nasm/. New parser, preproc, and outfmt structures. None are complete; outfmt needs the most work. The raw preprocessor added (for no preprocessing). Currently the default for the nasm parser is to use the raw preproc; this should be changed to nasm_preproc once the nasm preprocessor is finished. A dbg output format is also new; because outfmt isn't done yet, there's not much implementation. What structures still need creating: listfmt, debugfmt. svn path=/trunk/yasm/; revision=133 --- diff --git a/frontends/yasm/yasm.c b/frontends/yasm/yasm.c index d7db7939..35f30bdd 100644 --- a/frontends/yasm/yasm.c +++ b/frontends/yasm/yasm.c @@ -1,4 +1,4 @@ -/* $Id: yasm.c,v 1.5 2001/08/18 22:15:12 peter Exp $ +/* $Id: yasm.c,v 1.6 2001/08/19 02:15:18 peter Exp $ * Program entry point, command line parsing * * Copyright (C) 2001 Peter Johnson @@ -22,11 +22,11 @@ #include #include #include - -extern int yydebug; -extern FILE *yyin; - -extern int yyparse(void); +#include "bytecode.h" +#include "section.h" +#include "outfmt.h" +#include "preproc.h" +#include "parser.h" char *filename = (char *)NULL; unsigned int line_number = 1; @@ -37,8 +37,6 @@ main (int argc, char *argv[]) { FILE *in; - yydebug = 1; - if(argc==2) { in = fopen(argv[1], "rt"); if(!in) { @@ -46,11 +44,12 @@ main (int argc, char *argv[]) return EXIT_FAILURE; } filename = strdup(argv[1]); - yyin = in; - } else - filename = strdup(""); + } else { + in = stdin; + filename = strdup(""); + } - yyparse(); + nasm_parser.doparse(&raw_preproc, &dbg_outfmt, in); if(filename) free(filename); diff --git a/libyasm/objfmt.h b/libyasm/objfmt.h new file mode 100644 index 00000000..ab73f0ca --- /dev/null +++ b/libyasm/objfmt.h @@ -0,0 +1,44 @@ +/* $Id: objfmt.h,v 1.1 2001/08/19 02:15:18 peter Exp $ + * Output format module interface header file + * + * Copyright (C) 2001 Peter Johnson + * + * 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 + */ +#ifndef YASM_OUTFMT_H +#define YASM_OUTFMT_H + +/* Interface to the output format module(s) */ +typedef struct outfmt_s { + char *name; /* one-line description of the format */ + char *keyword; /* keyword used to select format on the command line */ + + /* NULL-terminated list of debugging formats that are valid to use with + * this output format. + */ +/* struct debugfmt_s **debugfmts;*/ + + /* Default debugging format (set even if there's only one available to + * use) + */ +/* struct debugfmt_s *default_df;*/ +} outfmt; + +/* Available output formats */ +extern outfmt dbg_outfmt; + +#endif diff --git a/libyasm/parser.h b/libyasm/parser.h new file mode 100644 index 00000000..3416173c --- /dev/null +++ b/libyasm/parser.h @@ -0,0 +1,61 @@ +/* $Id: parser.h,v 1.1 2001/08/19 02:15:18 peter Exp $ + * Parser module interface header file + * + * Copyright (C) 2001 Peter Johnson + * + * 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 + */ +#ifndef YASM_PARSER_H +#define YASM_PARSER_H + +/* Interface to the parser module(s) -- the "front end" of the assembler */ +typedef struct parser_s { + char *name; /* one-line description of the parser */ + char *keyword; /* keyword used to select parser on the command line */ + + /* NULL-terminated list of preprocessors that are valid to use with this + * parser. The raw preprocessor (raw_preproc) should always be in this + * list so it's always possible to have no preprocessing done. + */ + preproc **preprocs; + + /* Default preprocessor (set even if there's only one available to use) */ + preproc *default_pp; + + /* Main entrance point for the parser. + * + * The parser needs access to both the output format module (for format- + * specific directives and segment names), and the selected preprocessor + * (which should naturally be in the preprocs list above). + * + * This function also takes the FILE * to the initial starting file, but + * not the filename (which is in a global variable and is not + * parser-specific). + * + * This function returns the starting section of a linked list of sections + * (whatever was in the file). + * + * Note that calling this has many side effects in the output format + * module: sections and variables are declared, etc. + */ + section * (*doparse) (preproc *pp, outfmt *of, FILE *f); +} parser; + +/* Available parsers */ +extern parser nasm_parser; + +#endif diff --git a/libyasm/preproc.h b/libyasm/preproc.h new file mode 100644 index 00000000..a239dcf6 --- /dev/null +++ b/libyasm/preproc.h @@ -0,0 +1,51 @@ +/* $Id: preproc.h,v 1.1 2001/08/19 02:15:18 peter Exp $ + * Preprocessor module interface header file + * + * Copyright (C) 2001 Peter Johnson + * + * 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 + */ +#ifndef YASM_PREPROC_H +#define YASM_PREPROC_H + +/* Interface to the preprocesor module(s) */ +typedef struct preproc_s { + char *name; /* one-line description of the preprocessor */ + + /* keyword used to select preprocessor on the command line */ + char *keyword; + + /* Initializes preprocessor. + * + * The preprocessor needs access to the output format module to find out + * any output format specific macros. + * + * This function also takes the FILE * to the initial starting file, but + * not the filename (which is in a global variable and is not + * preprocessor-specific). + */ + void (*initialize) (outfmt *of, FILE *f); + + /* Gets more preprocessed source code (up to max_size bytes) into buf. + * Note that more than a single line may be returned in buf. */ + int (*input) (char *buf, int max_size); +} preproc; + +/* Available preprocessors */ +extern preproc raw_preproc; + +#endif diff --git a/libyasm/section.h b/libyasm/section.h index cf6e057d..a29e0892 100644 --- a/libyasm/section.h +++ b/libyasm/section.h @@ -1,4 +1,4 @@ -/* $Id: section.h,v 1.2 2001/06/28 21:22:01 peter Exp $ +/* $Id: section.h,v 1.3 2001/08/19 02:15:18 peter Exp $ * Section header file * * Copyright (C) 2001 Peter Johnson @@ -27,9 +27,11 @@ typedef struct section_s { enum type { SECTION, ABSOLUTE }; + char *name; + unsigned int id; + union { /* SECTION data */ - char *name; /* ABSOLUTE data */ unsigned long start; } data; diff --git a/modules/objfmts/.cvsignore b/modules/objfmts/.cvsignore new file mode 100644 index 00000000..c8286623 --- /dev/null +++ b/modules/objfmts/.cvsignore @@ -0,0 +1,3 @@ +.*.sw? +Makefile.in +Makefile diff --git a/modules/objfmts/Makefile.am b/modules/objfmts/Makefile.am new file mode 100644 index 00000000..e26d28c0 --- /dev/null +++ b/modules/objfmts/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = dbg diff --git a/modules/objfmts/dbg/.cvsignore b/modules/objfmts/dbg/.cvsignore new file mode 100644 index 00000000..ac76d46f --- /dev/null +++ b/modules/objfmts/dbg/.cvsignore @@ -0,0 +1,5 @@ +.*.sw? +Makefile.in +Makefile +.deps +liboutfmt.a diff --git a/modules/objfmts/dbg/Makefile.am b/modules/objfmts/dbg/Makefile.am new file mode 100644 index 00000000..43e24e63 --- /dev/null +++ b/modules/objfmts/dbg/Makefile.am @@ -0,0 +1,10 @@ +noinst_LIBRARIES = liboutfmt.a + +liboutfmt_a_SOURCES = \ + outfmt.c + +INCLUDES=-I$(top_srcdir)/src + +if DEV +CFLAGS = -ansi -pedantic -Wall -g +endif diff --git a/modules/objfmts/dbg/dbg-objfmt.c b/modules/objfmts/dbg/dbg-objfmt.c new file mode 100644 index 00000000..179c233e --- /dev/null +++ b/modules/objfmts/dbg/dbg-objfmt.c @@ -0,0 +1,28 @@ +/* $Id: dbg-objfmt.c,v 1.1 2001/08/19 02:15:18 peter Exp $ + * Debugging output format (used to debug output format module interface) + * + * Copyright (C) 2001 Peter Johnson + * + * 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 "outfmt.h" + +/* Define outfmt structure -- see outfmt.h for details */ +outfmt dbg_outfmt = { + "Trace of all info passed to output format module", + "dbg" +}; diff --git a/modules/objfmts/dbg/objfmt.c b/modules/objfmts/dbg/objfmt.c new file mode 100644 index 00000000..870f6e95 --- /dev/null +++ b/modules/objfmts/dbg/objfmt.c @@ -0,0 +1,28 @@ +/* $Id: objfmt.c,v 1.1 2001/08/19 02:15:18 peter Exp $ + * Debugging output format (used to debug output format module interface) + * + * Copyright (C) 2001 Peter Johnson + * + * 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 "outfmt.h" + +/* Define outfmt structure -- see outfmt.h for details */ +outfmt dbg_outfmt = { + "Trace of all info passed to output format module", + "dbg" +}; diff --git a/modules/objfmts/dbg/outfmt.c b/modules/objfmts/dbg/outfmt.c new file mode 100644 index 00000000..900d148a --- /dev/null +++ b/modules/objfmts/dbg/outfmt.c @@ -0,0 +1,28 @@ +/* $Id: outfmt.c,v 1.1 2001/08/19 02:15:18 peter Exp $ + * Debugging output format (used to debug output format module interface) + * + * Copyright (C) 2001 Peter Johnson + * + * 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 "outfmt.h" + +/* Define outfmt structure -- see outfmt.h for details */ +outfmt dbg_outfmt = { + "Trace of all info passed to output format module", + "dbg" +}; diff --git a/modules/parsers/.cvsignore b/modules/parsers/.cvsignore new file mode 100644 index 00000000..c8286623 --- /dev/null +++ b/modules/parsers/.cvsignore @@ -0,0 +1,3 @@ +.*.sw? +Makefile.in +Makefile diff --git a/modules/parsers/Makefile.am b/modules/parsers/Makefile.am new file mode 100644 index 00000000..d09dc025 --- /dev/null +++ b/modules/parsers/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = nasm diff --git a/modules/parsers/nasm/.cvsignore b/modules/parsers/nasm/.cvsignore new file mode 100644 index 00000000..b8e37e49 --- /dev/null +++ b/modules/parsers/nasm/.cvsignore @@ -0,0 +1,10 @@ +.*.sw? +bison.c +bison.h +token.c +bison.y +token.l +Makefile.in +Makefile +.deps +libparser.a diff --git a/modules/parsers/nasm/Makefile.am b/modules/parsers/nasm/Makefile.am new file mode 100644 index 00000000..77519bc8 --- /dev/null +++ b/modules/parsers/nasm/Makefile.am @@ -0,0 +1,28 @@ +noinst_LIBRARIES = libparser.a + +libparser_a_SOURCES = \ + parser.c \ + bison.y \ + token.l + +noinst_SCRIPTS = gen_instr.pl + +AM_YFLAGS = -d --name-prefix=nasm_parser_ +AM_LFLAGS = -Pnasm_parser_ -olex.yy.c + +INCLUDES=-I$(top_srcdir)/src + +if DEV +CFLAGS = -ansi -pedantic -Wall -g +endif + +token.l bison.y: $(top_srcdir)/src/instrs.dat token.l.in bison.y.in gen_instr.pl + $(PERL) gen_instr.pl -i $(top_srcdir)/src/instrs.dat -t token.l -g bison.y + +BUILT_SOURCES = token.l bison.y + +EXTRA_DIST = \ + token.l.in \ + bison.y.in \ + bison.h \ + gen_instr.pl diff --git a/modules/parsers/nasm/bison.y.in b/modules/parsers/nasm/bison.y.in index d0e1af44..d0903e66 100644 --- a/modules/parsers/nasm/bison.y.in +++ b/modules/parsers/nasm/bison.y.in @@ -1,4 +1,4 @@ -/* $Id: bison.y.in,v 1.22 2001/07/25 00:33:10 peter Exp $ +/* $Id: bison.y.in,v 1.23 2001/08/19 02:15:18 peter Exp $ * Main bison parser * * Copyright (C) 2001 Peter Johnson, Michael Urman @@ -31,9 +31,10 @@ #define YYDEBUG 1 void init_table(void); -extern int yylex(void); +extern int nasm_parser_lex(void); extern void yyerror(char *); static unsigned long ConvertCharConstToInt(char *); +void nasm_parser_error(char *); %} @@ -413,3 +414,9 @@ ConvertCharConstToInt(char *cc) return retval; } +void +nasm_parser_error(char *s) +{ + yyerror(s); +} + diff --git a/modules/parsers/nasm/nasm-bison.y b/modules/parsers/nasm/nasm-bison.y index 94f11f12..d5ff200a 100644 --- a/modules/parsers/nasm/nasm-bison.y +++ b/modules/parsers/nasm/nasm-bison.y @@ -1,4 +1,4 @@ -/* $Id: nasm-bison.y,v 1.22 2001/07/25 00:33:10 peter Exp $ +/* $Id: nasm-bison.y,v 1.23 2001/08/19 02:15:18 peter Exp $ * Main bison parser * * Copyright (C) 2001 Peter Johnson, Michael Urman @@ -31,9 +31,10 @@ #define YYDEBUG 1 void init_table(void); -extern int yylex(void); +extern int nasm_parser_lex(void); extern void yyerror(char *); static unsigned long ConvertCharConstToInt(char *); +void nasm_parser_error(char *); %} @@ -413,3 +414,9 @@ ConvertCharConstToInt(char *cc) return retval; } +void +nasm_parser_error(char *s) +{ + yyerror(s); +} + diff --git a/modules/parsers/nasm/nasm-parser.c b/modules/parsers/nasm/nasm-parser.c new file mode 100644 index 00000000..167b173d --- /dev/null +++ b/modules/parsers/nasm/nasm-parser.c @@ -0,0 +1,62 @@ +/* $Id: nasm-parser.c,v 1.1 2001/08/19 02:15:18 peter Exp $ + * NASM-compatible parser + * + * Copyright (C) 2001 Peter Johnson + * + * 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 +#include "bytecode.h" +#include "section.h" +#include "outfmt.h" +#include "preproc.h" +#include "parser.h" + +extern FILE *nasm_parser_in; +extern int nasm_parser_debug; + +int (*nasm_parser_yyinput) (char *buf, int max_size); + +static section * +doparse(preproc *pp, outfmt *of, FILE *f) +{ + pp->initialize(of, f); + nasm_parser_in = f; + nasm_parser_yyinput = pp->input; + + /* only temporary */ + nasm_parser_debug = 1; + + nasm_parser_parse(); + + return NULL; +} + +/* Define valid preprocessors to use with this parser */ +static preproc *preprocs[] = { + &raw_preproc, + NULL +}; + +/* Define parser structure -- see parser.h for details */ +parser nasm_parser = { + "NASM-compatible parser", + "nasm", + preprocs, + &raw_preproc, + &doparse +}; diff --git a/modules/parsers/nasm/parser.c b/modules/parsers/nasm/parser.c new file mode 100644 index 00000000..d8873b3d --- /dev/null +++ b/modules/parsers/nasm/parser.c @@ -0,0 +1,62 @@ +/* $Id: parser.c,v 1.1 2001/08/19 02:15:18 peter Exp $ + * NASM-compatible parser + * + * Copyright (C) 2001 Peter Johnson + * + * 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 +#include "bytecode.h" +#include "section.h" +#include "outfmt.h" +#include "preproc.h" +#include "parser.h" + +extern FILE *nasm_parser_in; +extern int nasm_parser_debug; + +int (*nasm_parser_yyinput) (char *buf, int max_size); + +static section * +doparse(preproc *pp, outfmt *of, FILE *f) +{ + pp->initialize(of, f); + nasm_parser_in = f; + nasm_parser_yyinput = pp->input; + + /* only temporary */ + nasm_parser_debug = 1; + + nasm_parser_parse(); + + return NULL; +} + +/* Define valid preprocessors to use with this parser */ +static preproc *preprocs[] = { + &raw_preproc, + NULL +}; + +/* Define parser structure -- see parser.h for details */ +parser nasm_parser = { + "NASM-compatible parser", + "nasm", + preprocs, + &raw_preproc, + &doparse +}; diff --git a/modules/parsers/nasm/token.l.in b/modules/parsers/nasm/token.l.in index 0cde489f..bbcb1449 100644 --- a/modules/parsers/nasm/token.l.in +++ b/modules/parsers/nasm/token.l.in @@ -1,4 +1,4 @@ -/* $Id: token.l.in,v 1.12 2001/07/25 00:33:10 peter Exp $ +/* $Id: token.l.in,v 1.13 2001/08/19 02:15:18 peter Exp $ * Main lexer * * Copyright (C) 2001 Peter Johnson @@ -37,6 +37,12 @@ #include "expr.h" #include "bison.h" +#define yylval nasm_parser_lval + +extern int (*nasm_parser_yyinput) (char *buf, int max_size); +#undef YY_INPUT +#define YY_INPUT(b, r, ms) (r = nasm_parser_yyinput(b, ms)) + /* starting size of string buffer */ #define STRBUF_ALLOC_SIZE 128 diff --git a/modules/preprocs/.cvsignore b/modules/preprocs/.cvsignore new file mode 100644 index 00000000..c8286623 --- /dev/null +++ b/modules/preprocs/.cvsignore @@ -0,0 +1,3 @@ +.*.sw? +Makefile.in +Makefile diff --git a/modules/preprocs/Makefile.am b/modules/preprocs/Makefile.am new file mode 100644 index 00000000..78728bf5 --- /dev/null +++ b/modules/preprocs/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = raw diff --git a/modules/preprocs/raw/.cvsignore b/modules/preprocs/raw/.cvsignore new file mode 100644 index 00000000..a8f02df7 --- /dev/null +++ b/modules/preprocs/raw/.cvsignore @@ -0,0 +1,5 @@ +.*.sw? +Makefile.in +Makefile +.deps +libpreproc.a diff --git a/modules/preprocs/raw/Makefile.am b/modules/preprocs/raw/Makefile.am new file mode 100644 index 00000000..9e956333 --- /dev/null +++ b/modules/preprocs/raw/Makefile.am @@ -0,0 +1,10 @@ +noinst_LIBRARIES = libpreproc.a + +libpreproc_a_SOURCES = \ + preproc.c + +INCLUDES=-I$(top_srcdir)/src + +if DEV +CFLAGS = -ansi -pedantic -Wall -g +endif diff --git a/modules/preprocs/raw/preproc.c b/modules/preprocs/raw/preproc.c new file mode 100644 index 00000000..e2f81fb1 --- /dev/null +++ b/modules/preprocs/raw/preproc.c @@ -0,0 +1,63 @@ +/* $Id: preproc.c,v 1.1 2001/08/19 02:15:18 peter Exp $ + * Raw preprocessor (preforms NO preprocessing) + * + * Copyright (C) 2001 Peter Johnson + * + * 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 +#include "outfmt.h" +#include "preproc.h" +#include "errwarn.h" + +static int is_interactive; +static FILE *in; + +int isatty(int); + +static void +initialize(outfmt *of, FILE *f) +{ + in = f; + is_interactive = f ? (isatty(fileno(f)) > 0) : 0; +} + +static int +input(char *buf, int max_size) +{ + int c = '*', n; + + if(is_interactive) { + for(n = 0; n < max_size && (c = getc(in)) != EOF && c != '\n'; n++) + buf[n] = (char) c; + if(c == '\n') + buf[n++] = (char) c; + if(c == EOF && ferror(in)) + Error(ERR_FILE_READ, (char *)NULL); + } else if(((n = fread(buf, 1, max_size, in)) == 0) && ferror(in)) + Error(ERR_FILE_READ, (char *)NULL); + + return n; +} + +/* Define preproc structure -- see preproc.h for details */ +preproc raw_preproc = { + "Disable preprocessing", + "raw", + &initialize, + &input +}; diff --git a/modules/preprocs/raw/raw-preproc.c b/modules/preprocs/raw/raw-preproc.c new file mode 100644 index 00000000..f50aff82 --- /dev/null +++ b/modules/preprocs/raw/raw-preproc.c @@ -0,0 +1,63 @@ +/* $Id: raw-preproc.c,v 1.1 2001/08/19 02:15:18 peter Exp $ + * Raw preprocessor (preforms NO preprocessing) + * + * Copyright (C) 2001 Peter Johnson + * + * 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 +#include "outfmt.h" +#include "preproc.h" +#include "errwarn.h" + +static int is_interactive; +static FILE *in; + +int isatty(int); + +static void +initialize(outfmt *of, FILE *f) +{ + in = f; + is_interactive = f ? (isatty(fileno(f)) > 0) : 0; +} + +static int +input(char *buf, int max_size) +{ + int c = '*', n; + + if(is_interactive) { + for(n = 0; n < max_size && (c = getc(in)) != EOF && c != '\n'; n++) + buf[n] = (char) c; + if(c == '\n') + buf[n++] = (char) c; + if(c == EOF && ferror(in)) + Error(ERR_FILE_READ, (char *)NULL); + } else if(((n = fread(buf, 1, max_size, in)) == 0) && ferror(in)) + Error(ERR_FILE_READ, (char *)NULL); + + return n; +} + +/* Define preproc structure -- see preproc.h for details */ +preproc raw_preproc = { + "Disable preprocessing", + "raw", + &initialize, + &input +}; diff --git a/src/.cvsignore b/src/.cvsignore index a78da82e..dc8b3f41 100644 --- a/src/.cvsignore +++ b/src/.cvsignore @@ -1,9 +1,4 @@ .*.sw? -bison.c -bison.h -token.c -bison.y -token.l Makefile.in Makefile .deps diff --git a/src/Makefile.am b/src/Makefile.am index 2fd7e2d3..54886725 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,8 +1,8 @@ +SUBDIRS = parsers preprocs outfmts + bin_PROGRAMS = yasm yasm_SOURCES = \ - bison.y \ - token.l \ bytecode.c \ bytecode.h \ errwarn.c \ @@ -13,26 +13,22 @@ yasm_SOURCES = \ symrec.c \ symrec.h \ globals.h \ - util.h - -noinst_SCRIPTS = gen_instr.pl + util.h \ + section.h \ + outfmt.h \ + preproc.h \ + parser.h -AM_YFLAGS = -d +yasm_LDADD = \ + parsers/nasm/libparser.a \ + preprocs/raw/libpreproc.a \ + outfmts/dbg/liboutfmt.a if DEV CFLAGS = -ansi -pedantic -Wall -g endif -token.l bison.y: instrs.dat token.l.in bison.y.in gen_instr.pl - $(PERL) $(srcdir)/gen_instr.pl -i $(srcdir)/instrs.dat -t $(srcdir)/token.l -g $(srcdir)/bison.y - -BUILT_SOURCES = token.l bison.y - EXTRA_DIST = \ instrs.dat \ - token.l.in \ - bison.y.in \ - bison.h \ - gen_instr.pl \ strdup.c \ strtoul.c diff --git a/src/bison.y.in b/src/bison.y.in deleted file mode 100644 index d0e1af44..00000000 --- a/src/bison.y.in +++ /dev/null @@ -1,415 +0,0 @@ -/* $Id: bison.y.in,v 1.22 2001/07/25 00:33:10 peter Exp $ - * Main bison parser - * - * Copyright (C) 2001 Peter Johnson, 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 -#include -#include "symrec.h" -#include "globals.h" -#include "bytecode.h" -#include "errwarn.h" -#include "expr.h" - -#define YYDEBUG 1 - -void init_table(void); -extern int yylex(void); -extern void yyerror(char *); -static unsigned long ConvertCharConstToInt(char *); - -%} - -%union { - unsigned long int_val; - char *str_val; - double double_val; - symrec *sym; - struct { - char *name; - int line; - } syminfo; - unsigned char groupdata[4]; - effaddr ea_val; - expr *exp; - immval im_val; - targetval tgt_val; - dataval *data; - bytecode bc; -} - -%token INTNUM -%token FLTNUM -%token DIRECTIVE_NAME DIRECTIVE_VAL STRING -%token BYTE WORD DWORD QWORD TWORD DQWORD -%token DECLARE_DATA -%token RESERVE_SPACE -%token INCBIN EQU TIMES -%token SEG WRT NEAR SHORT FAR NOSPLIT ORG -%token TO -%token O16 O32 A16 A32 LOCK REPNZ REP REPZ -%token OPERSIZE ADDRSIZE -%token CR4 CRREG_NOTCR4 DRREG TRREG ST0 FPUREG_NOTST0 MMXREG XMMREG -%token REG_EAX REG_ECX REG_EDX REG_EBX REG_ESP REG_EBP REG_ESI REG_EDI -%token REG_AX REG_CX REG_DX REG_BX REG_SP REG_BP REG_SI REG_DI -%token REG_AL REG_CL REG_DL REG_BL REG_AH REG_CH REG_DH REG_BH -%token REG_ES REG_CS REG_SS REG_DS REG_FS REG_GS -%token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD -%token ID LOCAL_ID SPECIAL_ID - -/* instruction tokens (dynamically generated) */ -/* @TOKENS@ */ - -/* @TYPES@ */ - -%type line exp instr instrbase label - -%type fpureg reg32 reg16 reg8 segreg -%type mem memaddr memexp memfar -%type mem8x mem16x mem32x mem64x mem80x mem128x -%type mem8 mem16 mem32 mem64 mem80 mem128 mem1632 -%type rm8x rm16x rm32x /*rm64x rm128x*/ -%type rm8 rm16 rm32 rm64 rm128 -%type imm imm8x imm16x imm32x imm8 imm16 imm32 -%type expr expr_no_string -%type explabel -%type label_id -%type target -%type dataval datavals - -%left '|' -%left '^' -%left '&' -%left LEFT_OP RIGHT_OP -%left '-' '+' -%left '*' '/' SIGNDIV '%' SIGNMOD -%nonassoc UNARYOP - -%% -input: /* empty */ - | input line { OutputError(); OutputWarning(); line_number++; } -; - -line: '\n' { $$.type = BC_EMPTY; } - | exp '\n' { DebugPrintBC(&$1); $$ = $1; } - | label exp '\n' { DebugPrintBC(&$2); $$ = $2; } - | label '\n' - | directive '\n' { $$.type = BC_EMPTY; } - | error '\n' { - Error(ERR_INVALID_LINE, (char *)NULL); - $$.type = BC_EMPTY; - yyerrok; - } -; - -exp: instr - | DECLARE_DATA datavals { BuildBC_Data(&$$, $2, $1); } - | RESERVE_SPACE expr { BuildBC_Reserve(&$$, $2, $1); } -; - -datavals: dataval - | datavals ',' dataval { $$ = dataval_append($1, $3); } -; - -dataval: expr_no_string { $$ = dataval_new_expr($1); } - | FLTNUM { $$ = dataval_new_float($1); } - | STRING { $$ = dataval_new_string($1); } - | error { - Error(ERR_EXPR_SYNTAX, (char *)NULL); - $$ = (dataval *)NULL; - } -; - -label: label_id { $1->value = 0; } /* TODO: calculate offset */ - | label_id ':' { $1->value = 0; } /* TODO: calculate offset */ -; - -label_id: ID { $$ = locallabel_base = sym_def_get ($1.name, SYM_LABEL); } - | SPECIAL_ID { $$ = sym_def_get ($1.name, SYM_LABEL); } - | LOCAL_ID { $$ = sym_def_get ($1.name, SYM_LABEL); } -; - -/* directives */ -directive: '[' DIRECTIVE_NAME DIRECTIVE_VAL ']' { - printf("Directive: Name='%s' Value='%s'\n", $2, $3); - } - | '[' DIRECTIVE_NAME DIRECTIVE_VAL error { - Error(ERR_MISSING, "%c", ']'); - } - | '[' DIRECTIVE_NAME error { - Error(ERR_MISSING_ARG, (char *)NULL, $2); - } -; - -/* register groupings */ -fpureg: ST0 - | FPUREG_NOTST0 -; - -reg32: REG_EAX - | REG_ECX - | REG_EDX - | REG_EBX - | REG_ESP - | REG_EBP - | REG_ESI - | REG_EDI - | DWORD reg32 -; - -reg16: REG_AX - | REG_CX - | REG_DX - | REG_BX - | REG_SP - | REG_BP - | REG_SI - | REG_DI - | WORD reg16 -; - -reg8: REG_AL - | REG_CL - | REG_DL - | REG_BL - | REG_AH - | REG_CH - | REG_DH - | REG_BH - | BYTE reg8 -; - -segreg: REG_ES - | REG_SS - | REG_DS - | REG_FS - | REG_GS - | REG_CS - | WORD segreg -; - -/* memory addresses */ -memexp: expr { expr_simplify ($1); ConvertExprToEA (&$$, $1); } -; - -memaddr: memexp { $$ = $1; $$.segment = 0; } - | REG_CS ':' memaddr { $$ = $3; SetEASegment(&$$, 0x2E); } - | REG_SS ':' memaddr { $$ = $3; SetEASegment(&$$, 0x36); } - | REG_DS ':' memaddr { $$ = $3; SetEASegment(&$$, 0x3E); } - | REG_ES ':' memaddr { $$ = $3; SetEASegment(&$$, 0x26); } - | REG_FS ':' memaddr { $$ = $3; SetEASegment(&$$, 0x64); } - | REG_GS ':' memaddr { $$ = $3; SetEASegment(&$$, 0x65); } - | BYTE memaddr { $$ = $2; SetEALen(&$$, 1); } - | WORD memaddr { $$ = $2; SetEALen(&$$, 2); } - | DWORD memaddr { $$ = $2; SetEALen(&$$, 4); } -; - -mem: '[' memaddr ']' { $$ = $2; } -; - -/* explicit memory */ -mem8x: BYTE mem { $$ = $2; } -; -mem16x: WORD mem { $$ = $2; } -; -mem32x: DWORD mem { $$ = $2; } -; -mem64x: QWORD mem { $$ = $2; } -; -mem80x: TWORD mem { $$ = $2; } -; -mem128x: DQWORD mem { $$ = $2; } -; - -/* FAR memory, for jmp and call */ -memfar: FAR mem { $$ = $2; } -; - -/* implicit memory */ -mem8: mem - | mem8x -; -mem16: mem - | mem16x -; -mem32: mem - | mem32x -; -mem64: mem - | mem64x -; -mem80: mem - | mem80x -; -mem128: mem - | mem128x -; - -/* both 16 and 32 bit memory */ -mem1632: mem - | mem16x - | mem32x -; - -/* explicit register or memory */ -rm8x: reg8 { (void)ConvertRegToEA(&$$, $1); } - | mem8x -; -rm16x: reg16 { (void)ConvertRegToEA(&$$, $1); } - | mem16x -; -rm32x: reg32 { (void)ConvertRegToEA(&$$, $1); } - | mem32x -; -/* not needed: -rm64x: MMXREG { (void)ConvertRegToEA(&$$, $1); } - | mem64x -; -rm128x: XMMREG { (void)ConvertRegToEA(&$$, $1); } - | mem128x -; -*/ - -/* implicit register or memory */ -rm8: reg8 { (void)ConvertRegToEA(&$$, $1); } - | mem8 -; -rm16: reg16 { (void)ConvertRegToEA(&$$, $1); } - | mem16 -; -rm32: reg32 { (void)ConvertRegToEA(&$$, $1); } - | mem32 -; -rm64: MMXREG { (void)ConvertRegToEA(&$$, $1); } - | mem64 -; -rm128: XMMREG { (void)ConvertRegToEA(&$$, $1); } - | mem128 -; - -/* immediate values */ -imm: expr { expr_simplify ($1); ConvertExprToImm (&$$, $1); } -; - -/* explicit immediates */ -imm8x: BYTE imm { $$ = $2; } -; -imm16x: WORD imm { $$ = $2; } -; -imm32x: DWORD imm { $$ = $2; } -; - -/* implicit immediates */ -imm8: imm - | imm8x -; -imm16: imm - | imm16x -; -imm32: imm - | imm32x -; - -/* jump targets */ -target: expr { $$.val = $1; $$.op_sel = JR_NONE; } - | SHORT target { $$ = $2; SetOpcodeSel(&$$.op_sel, JR_SHORT_FORCED); } - | NEAR target { $$ = $2; SetOpcodeSel(&$$.op_sel, JR_NEAR_FORCED); } -; - -/* expression trees */ -expr_no_string: INTNUM { $$ = expr_new_ident (EXPR_NUM, ExprNum($1)); } - | explabel { $$ = expr_new_ident (EXPR_SYM, ExprSym(sym_use_get ($1.name, SYM_LABEL))); } - /*| expr '||' expr { $$ = expr_new_tree ($1, EXPR_LOR, $3); }*/ - | expr '|' expr { $$ = expr_new_tree ($1, EXPR_OR, $3); } - | expr '^' expr { $$ = expr_new_tree ($1, EXPR_XOR, $3); } - /*| expr '&&' expr { $$ = expr_new_tree ($1, EXPR_LAND, $3); }*/ - | expr '&' expr { $$ = expr_new_tree ($1, EXPR_AND, $3); } - /*| expr '==' expr { $$ = expr_new_tree ($1, EXPR_EQUALS, $3); }*/ - /*| expr '>' expr { $$ = expr_new_tree ($1, EXPR_GT, $3); }*/ - /*| expr '<' expr { $$ = expr_new_tree ($1, EXPR_GT, $3); }*/ - /*| expr '>=' expr { $$ = expr_new_tree ($1, EXPR_GE, $3); }*/ - /*| expr '<=' expr { $$ = expr_new_tree ($1, EXPR_GE, $3); }*/ - /*| expr '!=' expr { $$ = expr_new_tree ($1, EXPR_NE, $3); }*/ - | expr LEFT_OP expr { $$ = expr_new_tree ($1, EXPR_SHL, $3); } - | expr RIGHT_OP expr { $$ = expr_new_tree ($1, EXPR_SHR, $3); } - | expr '+' expr { $$ = expr_new_tree ($1, EXPR_ADD, $3); } - | expr '-' expr { $$ = expr_new_tree ($1, EXPR_SUB, $3); } - | expr '*' expr { $$ = expr_new_tree ($1, EXPR_MUL, $3); } - | expr '/' expr { $$ = expr_new_tree ($1, EXPR_DIV, $3); } - | expr '%' expr { $$ = expr_new_tree ($1, EXPR_MOD, $3); } - | '+' expr %prec UNARYOP { $$ = $2; } - | '-' expr %prec UNARYOP { $$ = expr_new_branch (EXPR_NEG, $2); } - /*| '!' expr { $$ = expr_new_branch (EXPR_LNOT, $2); }*/ - | '~' expr %prec UNARYOP { $$ = expr_new_branch (EXPR_NOT, $2); } - | '(' expr ')' { $$ = $2; } -; - -expr: expr_no_string - | STRING { $$ = expr_new_ident (EXPR_NUM, ExprNum(ConvertCharConstToInt($1))); } -; - -explabel: ID | SPECIAL_ID | LOCAL_ID ; - -instr: instrbase - | OPERSIZE instr { $$ = $2; SetInsnOperSizeOverride(&$$, $1); } - | ADDRSIZE instr { $$ = $2; SetInsnAddrSizeOverride(&$$, $1); } - | REG_CS instr { $$ = $2; SetEASegment(&$$.data.insn.ea, 0x2E); } - | REG_SS instr { $$ = $2; SetEASegment(&$$.data.insn.ea, 0x36); } - | REG_DS instr { $$ = $2; SetEASegment(&$$.data.insn.ea, 0x3E); } - | REG_ES instr { $$ = $2; SetEASegment(&$$.data.insn.ea, 0x26); } - | REG_FS instr { $$ = $2; SetEASegment(&$$.data.insn.ea, 0x64); } - | REG_GS instr { $$ = $2; SetEASegment(&$$.data.insn.ea, 0x65); } - | LOCK instr { $$ = $2; SetInsnLockRepPrefix(&$$, 0xF0); } - | REPNZ instr { $$ = $2; SetInsnLockRepPrefix(&$$, 0xF2); } - | REP instr { $$ = $2; SetInsnLockRepPrefix(&$$, 0xF3); } - | REPZ instr { $$ = $2; SetInsnLockRepPrefix(&$$, 0xF4); } -; - -/* instruction grammars (dynamically generated) */ -/* @INSTRUCTIONS@ */ - -%% - -static unsigned long -ConvertCharConstToInt(char *cc) -{ - unsigned long retval = 0; - size_t len = strlen(cc); - - if(len > 4) - Warning(WARN_CHAR_CONST_TOO_BIG, (char *)NULL); - - switch(len) { - case 4: - retval |= (unsigned long)cc[3]; - retval <<= 8; - case 3: - retval |= (unsigned long)cc[2]; - retval <<= 8; - case 2: - retval |= (unsigned long)cc[1]; - retval <<= 8; - case 1: - retval |= (unsigned long)cc[0]; - } - - return retval; -} - diff --git a/src/gen_instr.pl b/src/gen_instr.pl deleted file mode 100755 index a122e084..00000000 --- a/src/gen_instr.pl +++ /dev/null @@ -1,819 +0,0 @@ -#!/usr/bin/perl -w -# $Id: gen_instr.pl,v 1.18 2001/07/11 04:07:11 peter Exp $ -# Generates bison.y and token.l from instrs.dat for YASM -# -# 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 -# - -use strict; -use Getopt::Long; -my $VERSION = "0.0.1"; - -# useful constants for instruction arrays -# common -use constant INST => 0; -use constant OPERANDS => 1; -# general format -use constant OPSIZE => 2; -use constant OPCODE => 3; -use constant EFFADDR => 4; -use constant IMM => 5; -use constant CPU => 6; -# relative target format -use constant ADSIZE => 2; -use constant SHORTOPCODE => 3; -use constant NEAROPCODE => 4; -use constant SHORTCPU => 5; -use constant NEARCPU => 6; - -use constant TOO_MANY_ERRORS => 20; - -# default options -my $instrfile = 'instrs.dat'; -my $tokenfile = 'token.l'; -my $tokensource; -my $grammarfile = 'bison.y'; -my $grammarsource; -my $showversion; -my $showusage; -my $dry_run; - -# allow overrides -my $gotopts = GetOptions ( 'input=s' => \$instrfile, - 'token=s' => \$tokenfile, - 'sourcetoken=s' => \$tokensource, - 'grammar=s' => \$grammarfile, - 'sourcegrammar=s' => \$grammarsource, - 'version' => \$showversion, - 'n|dry-run' => \$dry_run, - 'help|usage' => \$showusage, - ); - -&showusage and exit 1 unless $gotopts; -&showversion if $showversion; -&showusage if $showusage; -exit 0 if $showversion or $showusage; - -# valid values for instrs.dat fields -my $valid_regs = join '|', qw( - REG_AL REG_AH REG_AX REG_EAX - REG_BL REG_BH REG_BX REG_EBX - REG_CL REG_CH REG_CX REG_ECX - REG_DL REG_DH REG_DX REG_EDX - REG_SI REG_ESI REG_DI REG_EDI - REG_BP REG_EBP - REG_CS REG_DS REG_ES REG_FS REG_GS REG_SS - ONE XMMREG MMXREG segreg CRREG_NOTCR4 CR4 DRREG - fpureg FPUREG_NOTST0 ST0 ST1 ST2 ST3 ST4 ST5 ST6 ST7 mem imm - imm8 imm16 imm32 imm64 imm80 imm128 - imm8x imm16x imm32x imm64x imm80x imm128x - rm8 rm16 rm32 rm1632 rm64 rm80 rm128 - rm8x rm16x rm32x rm1632x rm64x rm80x rm128x - reg8 reg16 reg32 reg1632 reg64 reg80 reg128 - reg8x reg16x reg32x reg1632x reg64x reg80x reg128x - mem8 mem16 mem32 mem1632 mem64 mem80 mem128 - mem8x mem16x mem32x mem1632x mem64x mem80x mem128x - target memfar -); -my $valid_opcodes = join '|', qw( - [0-9A-F]{2} - \\$0\\.\\d -); -my $valid_cpus = join '|', qw( - 8086 186 286 386 486 P4 P5 P6 - FPU MMX KATMAI SSE SSE2 - AMD ATHLON 3DNOW - SMM - CYRIX - UNDOC OBS PRIV PROT - @0 @1 -); - -# track errors and warnings rather than die'ing on the first. -my (@messages, $errcount, $warncount); -sub die_with_errors (@) -{ - foreach (@_) { print; }; - if ($errcount) - { - print "Dying with errors\n"; - exit -1; - } -} - -my ($groups) = &read_instructions ($instrfile); - -die_with_errors @messages; - -exit 0 if $dry_run; # done with simple verification, so exit - -unless ($dry_run) -{ - &output_lex ($tokenfile, $tokensource, $groups); - &output_yacc ($grammarfile, $grammarsource, $groups); -} - -# print version for --version, etc. -sub showversion -{ - print "YASM gen_instr.pl $VERSION\n"; -} - -# print usage information for --help, etc. -sub showusage -{ - print <<"EOF"; -Usage: gen_instrs.pl [-i input] [-t tokenfile] [-g grammarfile] - -i, --input instructions file (default: $instrfile) - -t, --token token output file (default: $tokenfile) - -st, --sourcetoken token input file (default: $tokenfile.in) - -g, --grammar grammar output file (default: $grammarfile) - -sg, --sourcegrammar grammar input file (default: $grammarfile.in) - -v, --version show version and exit - -h, --help, --usage show this message and exit - -n, --dry-run verify input file without writing output files -EOF -} - -# read in instructions, and verify they're valid (well, mostly) -sub read_instructions ($) -{ - my $instrfile = shift || die; - open INPUT, "< $instrfile" or die "Cannot open '$instrfile' for reading: $!\n"; - my %instr; - my %groups; - - sub add_group_rule ($$$$) - { - my ($inst, $args, $groups, $instrfile) = splice @_; - - # slide $0.\d down by one. - # i still say changing instrs.dat would be better ;) - $args =~ s/\$0\.([1-4])/ '$0.' . ($1-1) /eg; - - # detect relative target format by looking for "target" in args - if($args =~ m/target/oi) - { - my ($op, $size, $shortopcode, $nearopcode, $shortcpu, $nearcpu) = - split /\t+/, $args; - eval { - die "Invalid group name\n" - if $inst !~ m/^!\w+$/o; - die "Invalid Operands\n" - if $op !~ m/^(nil|((TO|WORD|DWORD)\s)?(?:$valid_regs)([,:](?:$valid_regs)){0,2})$/oi; - die "Invalid Address Size\n" - if $size !~ m/^(nil|16|32|\$0\.\d)$/oi; - die "Invalid Short Opcode\n" - if $shortopcode !~ m/^(nil|(?:$valid_opcodes)(,(?:$valid_opcodes)){0,2}(\+(\$\d|\$0\.\d|\d))?)$/oi; - die "Invalid Near Opcode\n" - if $nearopcode !~ m/^(nil|(?:$valid_opcodes)(,(?:$valid_opcodes)){0,2}(\+(\$\d|\$0\.\d|\d))?)$/oi; - die "Invalid Short CPU\n" - if $shortcpu !~ m/^(?:$valid_cpus)(?:,(?:$valid_cpus))*$/o; - die "Invalid Near CPU\n" - if $nearcpu !~ m/^(?:$valid_cpus)(?:,(?:$valid_cpus))*$/o; - }; - push @messages, "Malformed Instruction at $instrfile line $.: $@" and $errcount++ if $@; - die_with_errors @messages if $errcount and @messages>=TOO_MANY_ERRORS; - # knock the ! off of $inst for the groupname - $inst = substr $inst, 1; - push @{$groups->{$inst}{rules}}, [$inst, $op, $size, $shortopcode, $nearopcode, $shortcpu, $nearcpu]; - } else { - my ($op, $size, $opcode, $eff, $imm, $cpu) = split /\t+/, $args; - eval { - die "Invalid group name\n" - if $inst !~ m/^!\w+$/o; - die "Invalid Operands\n" - if $op !~ m/^(nil|((TO|WORD|DWORD)\s)?(?:$valid_regs)([,:](?:$valid_regs)){0,2})$/oi; - die "Invalid Operation Size\n" - if $size !~ m/^(nil|16|32|\$0\.\d)$/oi; - die "Invalid Opcode\n" - if $opcode !~ m/^(?:$valid_opcodes)(,(?:$valid_opcodes)){0,2}(\+(\$\d|\$0\.\d|\d))?$/oi; - die "Invalid Effective Address\n" - if $eff !~ m/^(nil|\$?\d(r?,(\$?\d|\$0.\d)(\+\d)?|i,(nil|16|32)))$/oi; - die "Invalid Immediate Operand\n" - if $imm !~ m/^(nil|((\$\d|[0-9A-F]{2}|\$0\.\d),(((8|16|32)s?))?))$/oi; - die "Invalid CPU\n" - if $cpu !~ m/^(?:$valid_cpus)(?:,(?:$valid_cpus))*$/o; - }; - push @messages, "Malformed Instruction at $instrfile line $.: $@" and $errcount++ if $@; - die_with_errors @messages if $errcount and @messages>=TOO_MANY_ERRORS; - # knock the ! off of $inst for the groupname - $inst = substr $inst, 1; - push @{$groups->{$inst}{rules}}, [$inst, $op, $size, $opcode, $eff, $imm, $cpu]; - } - } - - sub add_group_member ($$$$$) - { - my ($handle, $fullargs, $groups, $instr, $instrfile) = splice @_; - - my ($inst, $group) = split /!/, $handle; - my ($args, $cpu) = split /\t+/, $fullargs; - eval { - die "Invalid instruction name\n" - if $inst !~ m/^\w+$/o; - die "Invalid group name\n" - if $group !~ m/^\w+$/o; - die "Invalid CPU\n" - if $cpu and $cpu !~ m/^(?:$valid_cpus)(?:,(?:$valid_cpus))*$/o; - push @messages, "Malformed Instruction at $instrfile line $.: Group $group not yet defined\n" - unless exists $groups->{$group}; - $warncount++; - }; - push @messages, "Malformed Instruction at $instrfile line $.: $@" and $errcount++ if $@; - # only allow multiple instances of instructions that aren't of a group - push @messages, "Multiple Definiton for instruction $inst at $instrfile line $.\n" and $errcount++ - if exists $instr->{$inst} and not exists $groups->{$inst}; - die_with_errors @messages if $errcount and @messages>=TOO_MANY_ERRORS; - push @{$groups->{$group}{members}}, [$inst, $group, $args, $cpu]; - $instr->{$inst} = 1; - } - - while () - { - chomp; - next if /^\s*(?:;.*)$/; - - my ($handle, $args) = split /\t+/, $_, 2; - - # pseudo hack to handle original style instructions (no group) - if ($handle =~ m/^\w+$/) - { - # TODO: this has some long ranging effects, as the eventual - # bison rules get tagged when they don't need - # to, etc. Fix this sometime. - add_group_rule ("!$handle", $args, \%groups, $instrfile); - add_group_member ("$handle!$handle", "", \%groups, \%instr, - $instrfile); - } - elsif ($handle =~ m/^!\w+$/) - { - add_group_rule ($handle, $args, \%groups, $instrfile); - } - elsif ($handle =~ m/^\w+!\w+$/) - { - add_group_member ($handle, $args, \%groups, \%instr, - $instrfile); - } - # TODO: consider if this is necessary: Pete? - # (add_group_member_synonym is -not- implemented) - #elsif ($handle =~ m/^:\w+$/) - #{ - # add_group_member_synonym ($handle, $args); - #} - } - close INPUT; - return (\%groups); -} - -sub output_lex ($@) -{ - my $tokenfile = shift or die; - my $tokensource = shift; - $tokensource ||= "$tokenfile.in"; - my $groups = shift or die; - - open IN, "< $tokensource" or die "Cannot open '$tokensource' for reading: $!\n"; - open TOKEN, "> $tokenfile" or die "Cannot open '$tokenfile' for writing: $!\n"; - while () - { - # Replace token.l.in /* @INSTRUCTIONS@ */ with generated content - if (m{/[*]\s*[@]INSTRUCTIONS[@]\s*[*]/}) - { - foreach my $grp (sort keys %$groups) - { - my %printed; - my $group = $grp; $group =~ s/^!//; - - foreach my $grp (@{$groups->{$grp}{members}}) - { - unless (exists $printed{$grp->[0]}) - { - $printed{$grp->[0]} = 1; - my @groupdata; - if ($grp->[2]) - { - @groupdata = split ",", $grp->[2]; - for (my $i=0; $i < @groupdata; ++$i) - { - $groupdata[$i] =~ s/nil/0/; - $groupdata[$i] = " yylval.groupdata[$i] = 0x$groupdata[$i];"; - } - $groupdata[-1] .= "\n\t "; - } - printf TOKEN "%-12s{%s return %-20s }\n", - $grp->[0], - (join "\n\t ", @groupdata), - "\Ugrp_$group;\E"; - # TODO: change appropriate GRP_FOO back to - # INS_FOO's. not functionally important; - # just pedantically so. - } - } - } - } - else - { - print TOKEN $_; - } - } - close IN; - close TOKEN; -} - -# helper functions for yacc output -sub rule_header ($ $ $) -{ - my ($rule, $tokens, $count) = splice (@_); - $count ? " | $tokens {\n" : "$rule: $tokens {\n"; -} -sub rule_footer () -{ - return " }\n"; -} - -sub cond_action_if ( $ $ $ $ $ $ $ ) -{ - my ($rule, $tokens, $count, $regarg, $val, $func, $a_eax) = splice (@_); - return rule_header ($rule, $tokens, $count) . <<"EOF"; - if (\$$regarg == $val) { - $func(@$a_eax); - } -EOF -} -sub cond_action_elsif ( $ $ $ $ ) -{ - my ($regarg, $val, $func, $a_eax) = splice (@_); - return <<"EOF"; - else if (\$$regarg == $val) { - $func(@$a_eax); - } -EOF -} -sub cond_action_else ( $ $ ) -{ - my ($func, $a_args) = splice (@_); - return <<"EOF" . rule_footer; - else { - $func (@$a_args); - } -EOF -} -sub cond_action ( $ $ $ $ $ $ $ $ ) -{ - my ($rule, $tokens, $count, $regarg, $val, $func, $a_eax, $a_args) - = splice (@_); - return cond_action_if ($rule, $tokens, $count, $regarg, $val, $func, - $a_eax) . cond_action_else ($func, $a_args); -} - -#sub action ( $ $ $ $ $ ) -sub action ( @ $ ) -{ - my ($rule, $tokens, $func, $a_args, $count) = splice @_; - return rule_header ($rule, $tokens, $count) - . " $func (@$a_args);\n" - . rule_footer; -} - -sub get_token_number ( $ $ ) -{ - my ($tokens, $str) = splice @_; - $tokens =~ s/$str.*/x/; # hold its place - my @f = split /\s+/, $tokens; - return scalar @f; -} - -sub output_yacc ($@) -{ - my $grammarfile = shift or die; - my $grammarsource = shift; - $grammarsource ||= "$grammarfile.in"; - my $groups = shift or die; - - open IN, "< $grammarsource" or die "Cannot open '$grammarsource' for reading: $!\n"; - open GRAMMAR, "> $grammarfile" or die "Cannot open '$grammarfile' for writing: $!\n"; - - while () - { - if (m{/[*]\s*[@]TOKENS[@]\s*[*]/}) - { - my $len = length("%token "); - print GRAMMAR "%token "; - foreach my $group (sort keys %$groups) - { - if ($len + length("GRP_$group") < 76) - { - print GRAMMAR " GRP_\U$group\E"; - $len += length(" GRP_$group"); - } - else - { - print GRAMMAR "\n%token GRP_\U$group\E"; - $len = length("%token GRP_$group"); - } - } - print GRAMMAR "\n"; - } - elsif (m{/[*]\s*[@]TYPES[@]\s*[*]/}) - { - my $len = length("%type "); - print GRAMMAR "%type "; - foreach my $group (sort keys %$groups) - { - if ($len + length($group) < 76) - { - print GRAMMAR " $group"; - $len += length(" $group"); - } - else - { - print GRAMMAR "\n%type $group"; - $len = length("%type $group"); - } - } - print GRAMMAR "\n"; - } - elsif (m{/[*]\s*[@]INSTRUCTIONS[@]\s*[*]/}) - { - # list every kind of instruction that instrbase can be - print GRAMMAR "instrbase: ", - join( "\n | ", sort keys %$groups), "\n;\n"; - - my ($ONE, $AL, $AX, $EAX); # need the outer scope - my (@XCHG_AX, @XCHG_EAX); - - # list the arguments and actions (buildbc) - #foreach my $instrname (sort keys %$instrlist) - foreach my $group (sort keys %$groups) - { - # I'm still convinced this is a hack. The idea is if - # within an instruction we see certain versions of the - # opcodes with ONE, or REG_E?A[LX],imm(8|16|32). If we - # do, defer generation of the action, as we may need to - # fold it into another version with a conditional to - # generate the more efficient variant of the opcode - # BUT, if we don't fold it in, we have to generate the - # original version we would have otherwise. - ($ONE, $AL, $AX, $EAX) = (0, 0, 0, 0); - # Folding for xchg (REG_E?AX,reg16 and reg16,REG_E?AX). - (@XCHG_AX, @XCHG_EAX) = ((0, 0), (0, 0)); - my $count = 0; - foreach my $inst (@{$groups->{$group}{rules}}) { - if($inst->[OPERANDS] =~ m/target/oi) - { - # relative target format - # build the instruction in pieces. - - # rulename = instruction - my $rule = "$inst->[INST]"; - - # tokens it eats: instruction and arguments - # nil => no arguments - my $tokens = "\Ugrp_$rule\E"; - $tokens .= " $inst->[OPERANDS]" - if $inst->[OPERANDS] ne 'nil'; - $tokens =~ s/,/ ',' /g; - $tokens =~ s/:/ ':' /g; - my $func = "BuildBC_JmpRel"; - - # Create the argument list for BuildBC - my @args; - - # First argument is always &$$ - push @args, '&$$,'; - - # Target argument: HACK: Always assumed to be arg 1. - push @args, '&$2,'; - - # test for short opcode "nil" - if($inst->[SHORTOPCODE] =~ m/nil/) - { - push @args, '0, 0, 0, 0, 0,'; - } - else - { - # opcode is valid - push @args, '1,'; - - # number of bytes of short opcode - push @args, (scalar(()=$inst->[SHORTOPCODE] =~ m/(,)/)+1) . ","; - - # opcode piece 1 (and 2 and 3 if attached) - push @args, $inst->[SHORTOPCODE]; - $args[-1] =~ s/,/, /; - $args[-1] =~ s/([0-9A-Fa-f]{2})/0x$1/g; - # don't match $0.\d in the following rule. - $args[-1] =~ s/\$(\d+)(?!\.)/"\$" . ($1*2)/eg; - $args[-1] .= ','; - - # opcode piece 2 (if not attached) - push @args, "0," if $inst->[SHORTOPCODE] !~ m/,/o; - # opcode piece 3 (if not attached) - push @args, "0," if $inst->[SHORTOPCODE] !~ m/,.*,/o; - } - - # test for near opcode "nil" - if($inst->[NEAROPCODE] =~ m/nil/) - { - push @args, '0, 0, 0, 0, 0,'; - } - else - { - # opcode is valid - push @args, '1,'; - - # number of bytes of near opcode - push @args, (scalar(()=$inst->[NEAROPCODE] =~ m/(,)/)+1) . ","; - - # opcode piece 1 (and 2 and 3 if attached) - push @args, $inst->[NEAROPCODE]; - $args[-1] =~ s/,/, /; - $args[-1] =~ s/([0-9A-Fa-f]{2})/0x$1/g; - # don't match $0.\d in the following rule. - $args[-1] =~ s/\$(\d+)(?!\.)/"\$" . ($1*2)/eg; - $args[-1] .= ','; - - # opcode piece 2 (if not attached) - push @args, "0," if $inst->[NEAROPCODE] !~ m/,/o; - # opcode piece 3 (if not attached) - push @args, "0," if $inst->[NEAROPCODE] !~ m/,.*,/o; - } - - # address size - push @args, "$inst->[ADSIZE]"; - $args[-1] =~ s/nil/0/; - - # now that we've constructed the arglist, subst $0.\d - s/\$0\.(\d+)/\$1\[$1\]/g foreach (@args); - - # generate the grammar - print GRAMMAR action ($rule, $tokens, $func, \@args, $count++); - } - else - { - # general instruction format - # build the instruction in pieces. - - # rulename = instruction - my $rule = "$inst->[INST]"; - - # tokens it eats: instruction and arguments - # nil => no arguments - my $tokens = "\Ugrp_$rule\E"; - $tokens .= " $inst->[OPERANDS]" - if $inst->[OPERANDS] ne 'nil'; - $tokens =~ s/,/ ',' /g; - $tokens =~ s/:/ ':' /g; - # offset args - my $to = $tokens =~ m/\b(TO|WORD|DWORD)\b/ ? 1 : 0; - my $func = "BuildBC_Insn"; - - # Create the argument list for BuildBC - my @args; - - # First argument is always &$$ - push @args, '&$$,'; - - # operand size - push @args, "$inst->[OPSIZE],"; - $args[-1] =~ s/nil/0/; - - # number of bytes of opcodes - push @args, (scalar(()=$inst->[OPCODE] =~ m/(,)/)+1) . ","; - - # opcode piece 1 (and 2 and 3 if attached) - push @args, $inst->[OPCODE]; - $args[-1] =~ s/,/, /; - $args[-1] =~ s/([0-9A-Fa-f]{2})/0x$1/g; - # don't match $0.\d in the following rule. - $args[-1] =~ s/\$(\d+)(?!\.)/"\$" . ($1*2+$to)/eg; - $args[-1] .= ','; - - # opcode piece 2 (if not attached) - push @args, "0," if $inst->[OPCODE] !~ m/,/o; - # opcode piece 3 (if not attached) - push @args, "0," if $inst->[OPCODE] !~ m/,.*,/o; - - # effective addresses - push @args, $inst->[EFFADDR]; - $args[-1] =~ s/,/, /; - $args[-1] =~ s/^nil$/(effaddr *)NULL, 0/; - $args[-1] =~ s/nil/0/; - # don't let a $0.\d match slip into the following rules. - $args[-1] =~ s/\$(\d+)([ri])?(?!\.)/"\$".($1*2+$to).($2||'')/eg; - $args[-1] =~ s/(\$\d+[ri]?)(?!\.)/\&$1/; # Just the first! - $args[-1] =~ s/\&(\$\d+)r/ConvertRegToEA((effaddr *)NULL, $1)/; - $args[-1] =~ s[\&(\$\d+)i,\s*(\d+)] - ["ConvertImmToEA((effaddr *)NULL, \&$1, ".($2/8)."), 0"]e; - $args[-1] .= ','; - - die $args[-1] if $args[-1] =~ m/\d+[ri]/; - - # immediate sources - push @args, $inst->[IMM]; - $args[-1] =~ s/,/, /; - $args[-1] =~ s/nil/(immval *)NULL, 0/; - # don't match $0.\d in the following rules. - $args[-1] =~ s/\$(\d+)(?!\.)/"\$".($1*2+$to).($2||'')/eg; - $args[-1] =~ s/(\$\d+)(?!\.)/\&$1/; # Just the first! - $args[-1] =~ s[^([0-9A-Fa-f]+),] - [ConvertIntToImm((immval *)NULL, 0x$1),]; - $args[-1] =~ s[^\$0.(\d+),] - [ConvertIntToImm((immval *)NULL, \$1\[$1\]),]; - - # divide the second, and only the second, by 8 bits/byte - $args[-1] =~ s#(,\s*)(\d+)(s)?#$1 . ($2/8)#eg; - $args[-1] .= ($3||'') eq 's' ? ', 1' : ', 0'; - - die $args[-1] if $args[-1] =~ m/\d+s/; - - # now that we've constructed the arglist, subst $0.\d - s/\$0\.(\d+)/\$1\[$1\]/g foreach (@args); - - # see if we match one of the cases to defer - if (($inst->[OPERANDS]||"") =~ m/,ONE/) - { - $ONE = [ $rule, $tokens, $func, \@args]; - } - elsif (($inst->[OPERANDS]||"") =~ m/REG_AL,imm8/) - { - $AL = [ $rule, $tokens, $func, \@args]; - } - elsif (($inst->[OPERANDS]||"") =~ m/REG_AX,imm16/) - { - $AX = [ $rule, $tokens, $func, \@args]; - } - elsif (($inst->[OPERANDS]||"") =~ m/REG_EAX,imm32/) - { - $EAX = [ $rule, $tokens, $func, \@args]; - } - elsif (($inst->[OPERANDS]||"") =~ m/REG_AX,reg16/) - { - $XCHG_AX[0] = [ $rule, $tokens, $func, \@args]; - } - elsif (($inst->[OPERANDS]||"") =~ m/reg16,REG_AX/) - { - $XCHG_AX[1] = [ $rule, $tokens, $func, \@args]; - } - elsif (($inst->[OPERANDS]||"") =~ m/REG_EAX,reg32/) - { - $XCHG_EAX[0] = [ $rule, $tokens, $func, \@args]; - } - elsif (($inst->[OPERANDS]||"") =~ m/reg32,REG_EAX/) - { - $XCHG_EAX[1] = [ $rule, $tokens, $func, \@args]; - } - - # or if we've deferred and we match the folding version - elsif ($ONE and ($inst->[OPERANDS]||"") =~ m/imm8/) - { - my $immarg = get_token_number ($tokens, "imm8"); - - $ONE->[4] = 1; - print GRAMMAR cond_action ($rule, $tokens, $count++, "$immarg.val", 1, $func, $ONE->[3], \@args); - } - elsif ($AL and ($inst->[OPERANDS]||"") =~ m/reg8,imm/) - { - $AL->[4] = 1; - my $regarg = get_token_number ($tokens, "reg8"); - - print GRAMMAR cond_action ($rule, $tokens, $count++, $regarg, 0, $func, $AL->[3], \@args); - } - elsif ($AX and ($inst->[OPERANDS]||"") =~ m/reg16,imm/) - { - $AX->[4] = 1; - my $regarg = get_token_number ($tokens, "reg16"); - - print GRAMMAR cond_action ($rule, $tokens, $count++, $regarg, 0, $func, $AX->[3], \@args); - } - elsif ($EAX and ($inst->[OPERANDS]||"") =~ m/reg32,imm/) - { - $EAX->[4] = 1; - my $regarg = get_token_number ($tokens, "reg32"); - - print GRAMMAR cond_action ($rule, $tokens, $count++, $regarg, 0, $func, $EAX->[3], \@args); - } - elsif (($XCHG_AX[0] or $XCHG_AX[1]) and - ($inst->[OPERANDS]||"") =~ m/reg16,reg16/) - { - my $first = 1; - for (my $i=0; $i < @XCHG_AX; ++$i) - { - if($XCHG_AX[$i]) - { - $XCHG_AX[$i]->[4] = 1; - # This is definitely a hack. The "right" - # way to do this would be to enhance - # get_token_number to get the nth reg16 - # instead of always getting the first. - my $regarg = - get_token_number ($tokens, "reg16") - + $i*2; - - if ($first) - { - print GRAMMAR cond_action_if ($rule, $tokens, $count++, $regarg, 0, $func, $XCHG_AX[$i]->[3]); - $first = 0; - } - else - { - $count++; - print GRAMMAR cond_action_elsif ($regarg, 0, $func, $XCHG_AX[$i]->[3]); - } - } - } - print GRAMMAR cond_action_else ($func, \@args); - } - elsif (($XCHG_EAX[0] or $XCHG_EAX[1]) and - ($inst->[OPERANDS]||"") =~ m/reg32,reg32/) - { - my $first = 1; - for (my $i=0; $i < @XCHG_EAX; ++$i) - { - if($XCHG_EAX[$i]) - { - $XCHG_EAX[$i]->[4] = 1; - # This is definitely a hack. The "right" - # way to do this would be to enhance - # get_token_number to get the nth reg32 - # instead of always getting the first. - my $regarg = - get_token_number ($tokens, "reg32") - + $i*2; - - if ($first) - { - print GRAMMAR cond_action_if ($rule, $tokens, $count++, $regarg, 0, $func, $XCHG_EAX[$i]->[3]); - $first = 0; - } - else - { - $count++; - print GRAMMAR cond_action_elsif ($regarg, 0, $func, $XCHG_EAX[$i]->[3]); - } - } - } - print GRAMMAR cond_action_else ($func, \@args); - } - - # otherwise, generate the normal version - else - { - print GRAMMAR action ($rule, $tokens, $func, \@args, $count++); - } - } - } - - # catch deferreds that haven't been folded in. - if ($ONE and not $ONE->[4]) - { - print GRAMMAR action (@$ONE, $count++); - } - if ($AL and not $AL->[4]) - { - print GRAMMAR action (@$AL, $count++); - } - if ($AX and not $AL->[4]) - { - print GRAMMAR action (@$AX, $count++); - } - if ($EAX and not $AL->[4]) - { - print GRAMMAR action (@$EAX, $count++); - } - - # print error action - # ASSUMES: at least one previous action exists - print GRAMMAR " | \Ugrp_$group\E error {\n"; - print GRAMMAR " Error (ERR_EXP_SYNTAX, (char *)NULL);\n"; - print GRAMMAR " }\n"; - - # terminate the rule - print GRAMMAR ";\n"; - } - } - else - { - print GRAMMAR $_; - } - } - close IN; - close GRAMMAR; -} diff --git a/src/main.c b/src/main.c index 68cbcaea..20cd55e3 100644 --- a/src/main.c +++ b/src/main.c @@ -1,4 +1,4 @@ -/* $Id: main.c,v 1.5 2001/08/18 22:15:12 peter Exp $ +/* $Id: main.c,v 1.6 2001/08/19 02:15:18 peter Exp $ * Program entry point, command line parsing * * Copyright (C) 2001 Peter Johnson @@ -22,11 +22,11 @@ #include #include #include - -extern int yydebug; -extern FILE *yyin; - -extern int yyparse(void); +#include "bytecode.h" +#include "section.h" +#include "outfmt.h" +#include "preproc.h" +#include "parser.h" char *filename = (char *)NULL; unsigned int line_number = 1; @@ -37,8 +37,6 @@ main (int argc, char *argv[]) { FILE *in; - yydebug = 1; - if(argc==2) { in = fopen(argv[1], "rt"); if(!in) { @@ -46,11 +44,12 @@ main (int argc, char *argv[]) return EXIT_FAILURE; } filename = strdup(argv[1]); - yyin = in; - } else - filename = strdup(""); + } else { + in = stdin; + filename = strdup(""); + } - yyparse(); + nasm_parser.doparse(&raw_preproc, &dbg_outfmt, in); if(filename) free(filename); diff --git a/src/objfmt.h b/src/objfmt.h new file mode 100644 index 00000000..ab73f0ca --- /dev/null +++ b/src/objfmt.h @@ -0,0 +1,44 @@ +/* $Id: objfmt.h,v 1.1 2001/08/19 02:15:18 peter Exp $ + * Output format module interface header file + * + * Copyright (C) 2001 Peter Johnson + * + * 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 + */ +#ifndef YASM_OUTFMT_H +#define YASM_OUTFMT_H + +/* Interface to the output format module(s) */ +typedef struct outfmt_s { + char *name; /* one-line description of the format */ + char *keyword; /* keyword used to select format on the command line */ + + /* NULL-terminated list of debugging formats that are valid to use with + * this output format. + */ +/* struct debugfmt_s **debugfmts;*/ + + /* Default debugging format (set even if there's only one available to + * use) + */ +/* struct debugfmt_s *default_df;*/ +} outfmt; + +/* Available output formats */ +extern outfmt dbg_outfmt; + +#endif diff --git a/src/objfmts/.cvsignore b/src/objfmts/.cvsignore new file mode 100644 index 00000000..c8286623 --- /dev/null +++ b/src/objfmts/.cvsignore @@ -0,0 +1,3 @@ +.*.sw? +Makefile.in +Makefile diff --git a/src/objfmts/Makefile.am b/src/objfmts/Makefile.am new file mode 100644 index 00000000..e26d28c0 --- /dev/null +++ b/src/objfmts/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = dbg diff --git a/src/objfmts/dbg/.cvsignore b/src/objfmts/dbg/.cvsignore new file mode 100644 index 00000000..ac76d46f --- /dev/null +++ b/src/objfmts/dbg/.cvsignore @@ -0,0 +1,5 @@ +.*.sw? +Makefile.in +Makefile +.deps +liboutfmt.a diff --git a/src/objfmts/dbg/Makefile.am b/src/objfmts/dbg/Makefile.am new file mode 100644 index 00000000..43e24e63 --- /dev/null +++ b/src/objfmts/dbg/Makefile.am @@ -0,0 +1,10 @@ +noinst_LIBRARIES = liboutfmt.a + +liboutfmt_a_SOURCES = \ + outfmt.c + +INCLUDES=-I$(top_srcdir)/src + +if DEV +CFLAGS = -ansi -pedantic -Wall -g +endif diff --git a/src/objfmts/dbg/dbg-objfmt.c b/src/objfmts/dbg/dbg-objfmt.c new file mode 100644 index 00000000..179c233e --- /dev/null +++ b/src/objfmts/dbg/dbg-objfmt.c @@ -0,0 +1,28 @@ +/* $Id: dbg-objfmt.c,v 1.1 2001/08/19 02:15:18 peter Exp $ + * Debugging output format (used to debug output format module interface) + * + * Copyright (C) 2001 Peter Johnson + * + * 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 "outfmt.h" + +/* Define outfmt structure -- see outfmt.h for details */ +outfmt dbg_outfmt = { + "Trace of all info passed to output format module", + "dbg" +}; diff --git a/src/objfmts/dbg/objfmt.c b/src/objfmts/dbg/objfmt.c new file mode 100644 index 00000000..870f6e95 --- /dev/null +++ b/src/objfmts/dbg/objfmt.c @@ -0,0 +1,28 @@ +/* $Id: objfmt.c,v 1.1 2001/08/19 02:15:18 peter Exp $ + * Debugging output format (used to debug output format module interface) + * + * Copyright (C) 2001 Peter Johnson + * + * 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 "outfmt.h" + +/* Define outfmt structure -- see outfmt.h for details */ +outfmt dbg_outfmt = { + "Trace of all info passed to output format module", + "dbg" +}; diff --git a/src/objfmts/dbg/outfmt.c b/src/objfmts/dbg/outfmt.c new file mode 100644 index 00000000..900d148a --- /dev/null +++ b/src/objfmts/dbg/outfmt.c @@ -0,0 +1,28 @@ +/* $Id: outfmt.c,v 1.1 2001/08/19 02:15:18 peter Exp $ + * Debugging output format (used to debug output format module interface) + * + * Copyright (C) 2001 Peter Johnson + * + * 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 "outfmt.h" + +/* Define outfmt structure -- see outfmt.h for details */ +outfmt dbg_outfmt = { + "Trace of all info passed to output format module", + "dbg" +}; diff --git a/src/outfmt.h b/src/outfmt.h new file mode 100644 index 00000000..eab7f6bd --- /dev/null +++ b/src/outfmt.h @@ -0,0 +1,44 @@ +/* $Id: outfmt.h,v 1.1 2001/08/19 02:15:18 peter Exp $ + * Output format module interface header file + * + * Copyright (C) 2001 Peter Johnson + * + * 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 + */ +#ifndef YASM_OUTFMT_H +#define YASM_OUTFMT_H + +/* Interface to the output format module(s) */ +typedef struct outfmt_s { + char *name; /* one-line description of the format */ + char *keyword; /* keyword used to select format on the command line */ + + /* NULL-terminated list of debugging formats that are valid to use with + * this output format. + */ +/* struct debugfmt_s **debugfmts;*/ + + /* Default debugging format (set even if there's only one available to + * use) + */ +/* struct debugfmt_s *default_df;*/ +} outfmt; + +/* Available output formats */ +extern outfmt dbg_outfmt; + +#endif diff --git a/src/parser.h b/src/parser.h new file mode 100644 index 00000000..3416173c --- /dev/null +++ b/src/parser.h @@ -0,0 +1,61 @@ +/* $Id: parser.h,v 1.1 2001/08/19 02:15:18 peter Exp $ + * Parser module interface header file + * + * Copyright (C) 2001 Peter Johnson + * + * 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 + */ +#ifndef YASM_PARSER_H +#define YASM_PARSER_H + +/* Interface to the parser module(s) -- the "front end" of the assembler */ +typedef struct parser_s { + char *name; /* one-line description of the parser */ + char *keyword; /* keyword used to select parser on the command line */ + + /* NULL-terminated list of preprocessors that are valid to use with this + * parser. The raw preprocessor (raw_preproc) should always be in this + * list so it's always possible to have no preprocessing done. + */ + preproc **preprocs; + + /* Default preprocessor (set even if there's only one available to use) */ + preproc *default_pp; + + /* Main entrance point for the parser. + * + * The parser needs access to both the output format module (for format- + * specific directives and segment names), and the selected preprocessor + * (which should naturally be in the preprocs list above). + * + * This function also takes the FILE * to the initial starting file, but + * not the filename (which is in a global variable and is not + * parser-specific). + * + * This function returns the starting section of a linked list of sections + * (whatever was in the file). + * + * Note that calling this has many side effects in the output format + * module: sections and variables are declared, etc. + */ + section * (*doparse) (preproc *pp, outfmt *of, FILE *f); +} parser; + +/* Available parsers */ +extern parser nasm_parser; + +#endif diff --git a/src/parsers/.cvsignore b/src/parsers/.cvsignore new file mode 100644 index 00000000..c8286623 --- /dev/null +++ b/src/parsers/.cvsignore @@ -0,0 +1,3 @@ +.*.sw? +Makefile.in +Makefile diff --git a/src/parsers/Makefile.am b/src/parsers/Makefile.am new file mode 100644 index 00000000..d09dc025 --- /dev/null +++ b/src/parsers/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = nasm diff --git a/src/parsers/nasm/.cvsignore b/src/parsers/nasm/.cvsignore new file mode 100644 index 00000000..b8e37e49 --- /dev/null +++ b/src/parsers/nasm/.cvsignore @@ -0,0 +1,10 @@ +.*.sw? +bison.c +bison.h +token.c +bison.y +token.l +Makefile.in +Makefile +.deps +libparser.a diff --git a/src/parsers/nasm/Makefile.am b/src/parsers/nasm/Makefile.am new file mode 100644 index 00000000..77519bc8 --- /dev/null +++ b/src/parsers/nasm/Makefile.am @@ -0,0 +1,28 @@ +noinst_LIBRARIES = libparser.a + +libparser_a_SOURCES = \ + parser.c \ + bison.y \ + token.l + +noinst_SCRIPTS = gen_instr.pl + +AM_YFLAGS = -d --name-prefix=nasm_parser_ +AM_LFLAGS = -Pnasm_parser_ -olex.yy.c + +INCLUDES=-I$(top_srcdir)/src + +if DEV +CFLAGS = -ansi -pedantic -Wall -g +endif + +token.l bison.y: $(top_srcdir)/src/instrs.dat token.l.in bison.y.in gen_instr.pl + $(PERL) gen_instr.pl -i $(top_srcdir)/src/instrs.dat -t token.l -g bison.y + +BUILT_SOURCES = token.l bison.y + +EXTRA_DIST = \ + token.l.in \ + bison.y.in \ + bison.h \ + gen_instr.pl diff --git a/src/parsers/nasm/bison.y.in b/src/parsers/nasm/bison.y.in index d0e1af44..d0903e66 100644 --- a/src/parsers/nasm/bison.y.in +++ b/src/parsers/nasm/bison.y.in @@ -1,4 +1,4 @@ -/* $Id: bison.y.in,v 1.22 2001/07/25 00:33:10 peter Exp $ +/* $Id: bison.y.in,v 1.23 2001/08/19 02:15:18 peter Exp $ * Main bison parser * * Copyright (C) 2001 Peter Johnson, Michael Urman @@ -31,9 +31,10 @@ #define YYDEBUG 1 void init_table(void); -extern int yylex(void); +extern int nasm_parser_lex(void); extern void yyerror(char *); static unsigned long ConvertCharConstToInt(char *); +void nasm_parser_error(char *); %} @@ -413,3 +414,9 @@ ConvertCharConstToInt(char *cc) return retval; } +void +nasm_parser_error(char *s) +{ + yyerror(s); +} + diff --git a/src/parsers/nasm/nasm-bison.y b/src/parsers/nasm/nasm-bison.y index 94f11f12..d5ff200a 100644 --- a/src/parsers/nasm/nasm-bison.y +++ b/src/parsers/nasm/nasm-bison.y @@ -1,4 +1,4 @@ -/* $Id: nasm-bison.y,v 1.22 2001/07/25 00:33:10 peter Exp $ +/* $Id: nasm-bison.y,v 1.23 2001/08/19 02:15:18 peter Exp $ * Main bison parser * * Copyright (C) 2001 Peter Johnson, Michael Urman @@ -31,9 +31,10 @@ #define YYDEBUG 1 void init_table(void); -extern int yylex(void); +extern int nasm_parser_lex(void); extern void yyerror(char *); static unsigned long ConvertCharConstToInt(char *); +void nasm_parser_error(char *); %} @@ -413,3 +414,9 @@ ConvertCharConstToInt(char *cc) return retval; } +void +nasm_parser_error(char *s) +{ + yyerror(s); +} + diff --git a/src/parsers/nasm/nasm-parser.c b/src/parsers/nasm/nasm-parser.c new file mode 100644 index 00000000..167b173d --- /dev/null +++ b/src/parsers/nasm/nasm-parser.c @@ -0,0 +1,62 @@ +/* $Id: nasm-parser.c,v 1.1 2001/08/19 02:15:18 peter Exp $ + * NASM-compatible parser + * + * Copyright (C) 2001 Peter Johnson + * + * 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 +#include "bytecode.h" +#include "section.h" +#include "outfmt.h" +#include "preproc.h" +#include "parser.h" + +extern FILE *nasm_parser_in; +extern int nasm_parser_debug; + +int (*nasm_parser_yyinput) (char *buf, int max_size); + +static section * +doparse(preproc *pp, outfmt *of, FILE *f) +{ + pp->initialize(of, f); + nasm_parser_in = f; + nasm_parser_yyinput = pp->input; + + /* only temporary */ + nasm_parser_debug = 1; + + nasm_parser_parse(); + + return NULL; +} + +/* Define valid preprocessors to use with this parser */ +static preproc *preprocs[] = { + &raw_preproc, + NULL +}; + +/* Define parser structure -- see parser.h for details */ +parser nasm_parser = { + "NASM-compatible parser", + "nasm", + preprocs, + &raw_preproc, + &doparse +}; diff --git a/src/parsers/nasm/parser.c b/src/parsers/nasm/parser.c new file mode 100644 index 00000000..d8873b3d --- /dev/null +++ b/src/parsers/nasm/parser.c @@ -0,0 +1,62 @@ +/* $Id: parser.c,v 1.1 2001/08/19 02:15:18 peter Exp $ + * NASM-compatible parser + * + * Copyright (C) 2001 Peter Johnson + * + * 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 +#include "bytecode.h" +#include "section.h" +#include "outfmt.h" +#include "preproc.h" +#include "parser.h" + +extern FILE *nasm_parser_in; +extern int nasm_parser_debug; + +int (*nasm_parser_yyinput) (char *buf, int max_size); + +static section * +doparse(preproc *pp, outfmt *of, FILE *f) +{ + pp->initialize(of, f); + nasm_parser_in = f; + nasm_parser_yyinput = pp->input; + + /* only temporary */ + nasm_parser_debug = 1; + + nasm_parser_parse(); + + return NULL; +} + +/* Define valid preprocessors to use with this parser */ +static preproc *preprocs[] = { + &raw_preproc, + NULL +}; + +/* Define parser structure -- see parser.h for details */ +parser nasm_parser = { + "NASM-compatible parser", + "nasm", + preprocs, + &raw_preproc, + &doparse +}; diff --git a/src/parsers/nasm/token.l.in b/src/parsers/nasm/token.l.in index 0cde489f..bbcb1449 100644 --- a/src/parsers/nasm/token.l.in +++ b/src/parsers/nasm/token.l.in @@ -1,4 +1,4 @@ -/* $Id: token.l.in,v 1.12 2001/07/25 00:33:10 peter Exp $ +/* $Id: token.l.in,v 1.13 2001/08/19 02:15:18 peter Exp $ * Main lexer * * Copyright (C) 2001 Peter Johnson @@ -37,6 +37,12 @@ #include "expr.h" #include "bison.h" +#define yylval nasm_parser_lval + +extern int (*nasm_parser_yyinput) (char *buf, int max_size); +#undef YY_INPUT +#define YY_INPUT(b, r, ms) (r = nasm_parser_yyinput(b, ms)) + /* starting size of string buffer */ #define STRBUF_ALLOC_SIZE 128 diff --git a/src/preproc.h b/src/preproc.h new file mode 100644 index 00000000..a239dcf6 --- /dev/null +++ b/src/preproc.h @@ -0,0 +1,51 @@ +/* $Id: preproc.h,v 1.1 2001/08/19 02:15:18 peter Exp $ + * Preprocessor module interface header file + * + * Copyright (C) 2001 Peter Johnson + * + * 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 + */ +#ifndef YASM_PREPROC_H +#define YASM_PREPROC_H + +/* Interface to the preprocesor module(s) */ +typedef struct preproc_s { + char *name; /* one-line description of the preprocessor */ + + /* keyword used to select preprocessor on the command line */ + char *keyword; + + /* Initializes preprocessor. + * + * The preprocessor needs access to the output format module to find out + * any output format specific macros. + * + * This function also takes the FILE * to the initial starting file, but + * not the filename (which is in a global variable and is not + * preprocessor-specific). + */ + void (*initialize) (outfmt *of, FILE *f); + + /* Gets more preprocessed source code (up to max_size bytes) into buf. + * Note that more than a single line may be returned in buf. */ + int (*input) (char *buf, int max_size); +} preproc; + +/* Available preprocessors */ +extern preproc raw_preproc; + +#endif diff --git a/src/preprocs/.cvsignore b/src/preprocs/.cvsignore new file mode 100644 index 00000000..c8286623 --- /dev/null +++ b/src/preprocs/.cvsignore @@ -0,0 +1,3 @@ +.*.sw? +Makefile.in +Makefile diff --git a/src/preprocs/Makefile.am b/src/preprocs/Makefile.am new file mode 100644 index 00000000..78728bf5 --- /dev/null +++ b/src/preprocs/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = raw diff --git a/src/preprocs/raw/.cvsignore b/src/preprocs/raw/.cvsignore new file mode 100644 index 00000000..a8f02df7 --- /dev/null +++ b/src/preprocs/raw/.cvsignore @@ -0,0 +1,5 @@ +.*.sw? +Makefile.in +Makefile +.deps +libpreproc.a diff --git a/src/preprocs/raw/Makefile.am b/src/preprocs/raw/Makefile.am new file mode 100644 index 00000000..9e956333 --- /dev/null +++ b/src/preprocs/raw/Makefile.am @@ -0,0 +1,10 @@ +noinst_LIBRARIES = libpreproc.a + +libpreproc_a_SOURCES = \ + preproc.c + +INCLUDES=-I$(top_srcdir)/src + +if DEV +CFLAGS = -ansi -pedantic -Wall -g +endif diff --git a/src/preprocs/raw/preproc.c b/src/preprocs/raw/preproc.c new file mode 100644 index 00000000..e2f81fb1 --- /dev/null +++ b/src/preprocs/raw/preproc.c @@ -0,0 +1,63 @@ +/* $Id: preproc.c,v 1.1 2001/08/19 02:15:18 peter Exp $ + * Raw preprocessor (preforms NO preprocessing) + * + * Copyright (C) 2001 Peter Johnson + * + * 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 +#include "outfmt.h" +#include "preproc.h" +#include "errwarn.h" + +static int is_interactive; +static FILE *in; + +int isatty(int); + +static void +initialize(outfmt *of, FILE *f) +{ + in = f; + is_interactive = f ? (isatty(fileno(f)) > 0) : 0; +} + +static int +input(char *buf, int max_size) +{ + int c = '*', n; + + if(is_interactive) { + for(n = 0; n < max_size && (c = getc(in)) != EOF && c != '\n'; n++) + buf[n] = (char) c; + if(c == '\n') + buf[n++] = (char) c; + if(c == EOF && ferror(in)) + Error(ERR_FILE_READ, (char *)NULL); + } else if(((n = fread(buf, 1, max_size, in)) == 0) && ferror(in)) + Error(ERR_FILE_READ, (char *)NULL); + + return n; +} + +/* Define preproc structure -- see preproc.h for details */ +preproc raw_preproc = { + "Disable preprocessing", + "raw", + &initialize, + &input +}; diff --git a/src/preprocs/raw/raw-preproc.c b/src/preprocs/raw/raw-preproc.c new file mode 100644 index 00000000..f50aff82 --- /dev/null +++ b/src/preprocs/raw/raw-preproc.c @@ -0,0 +1,63 @@ +/* $Id: raw-preproc.c,v 1.1 2001/08/19 02:15:18 peter Exp $ + * Raw preprocessor (preforms NO preprocessing) + * + * Copyright (C) 2001 Peter Johnson + * + * 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 +#include "outfmt.h" +#include "preproc.h" +#include "errwarn.h" + +static int is_interactive; +static FILE *in; + +int isatty(int); + +static void +initialize(outfmt *of, FILE *f) +{ + in = f; + is_interactive = f ? (isatty(fileno(f)) > 0) : 0; +} + +static int +input(char *buf, int max_size) +{ + int c = '*', n; + + if(is_interactive) { + for(n = 0; n < max_size && (c = getc(in)) != EOF && c != '\n'; n++) + buf[n] = (char) c; + if(c == '\n') + buf[n++] = (char) c; + if(c == EOF && ferror(in)) + Error(ERR_FILE_READ, (char *)NULL); + } else if(((n = fread(buf, 1, max_size, in)) == 0) && ferror(in)) + Error(ERR_FILE_READ, (char *)NULL); + + return n; +} + +/* Define preproc structure -- see preproc.h for details */ +preproc raw_preproc = { + "Disable preprocessing", + "raw", + &initialize, + &input +}; diff --git a/src/section.h b/src/section.h index cf6e057d..a29e0892 100644 --- a/src/section.h +++ b/src/section.h @@ -1,4 +1,4 @@ -/* $Id: section.h,v 1.2 2001/06/28 21:22:01 peter Exp $ +/* $Id: section.h,v 1.3 2001/08/19 02:15:18 peter Exp $ * Section header file * * Copyright (C) 2001 Peter Johnson @@ -27,9 +27,11 @@ typedef struct section_s { enum type { SECTION, ABSOLUTE }; + char *name; + unsigned int id; + union { /* SECTION data */ - char *name; /* ABSOLUTE data */ unsigned long start; } data; diff --git a/src/token.l.in b/src/token.l.in deleted file mode 100644 index 0cde489f..00000000 --- a/src/token.l.in +++ /dev/null @@ -1,323 +0,0 @@ -/* $Id: token.l.in,v 1.12 2001/07/25 00:33:10 peter Exp $ - * Main lexer - * - * Copyright (C) 2001 Peter Johnson - * - * 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 - */ -%{ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#ifdef STDC_HEADERS -# include -# include -#endif - -#include "util.h" - -#include "symrec.h" -#include "bytecode.h" -#include "errwarn.h" -#include "expr.h" -#include "bison.h" - -/* 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; - -%} -%option noyywrap -%option nounput -%option case-insensitive - symrec *locallabel_base = (symrec *)NULL; - int line_number; - -%x DIRECTIVE DIRECTIVE2 - -DIGIT [0-9] -BINDIGIT [01] -OCTDIGIT [0-7] -HEXDIGIT [0-9a-f] -WS [ \t\r] - -%% - - /* standard decimal integer */ -{DIGIT}+ { - yylval.int_val = strtoul(yytext, (char **)NULL, 10); - return INTNUM; -} - - /* 10010011b - binary number */ -{BINDIGIT}+b { - yylval.int_val = strtoul(yytext, (char **)NULL, 2); - return INTNUM; -} - - /* 777q - octal number */ -{OCTDIGIT}+q { - yylval.int_val = strtoul(yytext, (char **)NULL, 8); - return INTNUM; -} - - /* 0AAh form of hexidecimal number */ -0{HEXDIGIT}+h { - yylval.int_val = strtoul(yytext+1, (char **)NULL, 16); - return INTNUM; -} - - /* $0AA and 0xAA forms of hexidecimal number */ -(\$0|0x){HEXDIGIT}+ { - yylval.int_val = strtoul(yytext+2, (char **)NULL, 16); - return INTNUM; -} - - /* floating point value */ -{DIGIT}+\.{DIGIT}*(e[-+]?{DIGIT}+)? { - yylval.double_val = strtod(yytext, (char **)NULL); - return FLTNUM; -} - - /* string/character constant values */ -["'] { - int inch, count; - char endch = yytext[0]; - - strbuf = malloc(STRBUF_ALLOC_SIZE); - if(!strbuf) - Fatal(FATAL_NOMEM); - - strbuf_size = STRBUF_ALLOC_SIZE; - inch = input(); - count = 0; - while(inch != EOF && inch != endch && inch != '\n') { - strbuf[count++] = inch; - if(count >= strbuf_size) { - strbuf = realloc(strbuf, strbuf_size + STRBUF_ALLOC_SIZE); - if(!strbuf) - Fatal(FATAL_NOMEM); - strbuf_size += STRBUF_ALLOC_SIZE; - } - inch = input(); - } - - if(inch == '\n') - Error(ERR_STRING_UNTERM, (char *)NULL); - else if(inch == EOF) - Error(ERR_STRING_EOF, (char *)NULL); - - strbuf[count] = '\0'; - - yylval.str_val = strbuf; - return STRING; -} - - /* directive: [name value] */ -^"[" { BEGIN DIRECTIVE; return '['; } -"]" { BEGIN INITIAL; return ']'; } -"]" { BEGIN INITIAL; return ']'; } -\n { BEGIN INITIAL; return '\n'; } -\n { BEGIN INITIAL; return '\n'; } -{WS}+ ; -{WS}+ ; -[a-z]+ { - BEGIN DIRECTIVE2; - yylval.str_val = strdup(yytext); - if(!yylval.str_val) - Fatal(FATAL_NOMEM); - return DIRECTIVE_NAME; -} - /* everything printable except for ' ', '[' and ']'. */ -[!-@a-z\\^-`{|}~]+ { - yylval.str_val = strdup(yytext); - if(!yylval.str_val) - Fatal(FATAL_NOMEM); - return DIRECTIVE_VAL; -} -. { - Warning(WARN_UNREC_CHAR, (char *)NULL, conv_unprint(yytext[0])); -} -. { - Warning(WARN_UNREC_CHAR, (char *)NULL, conv_unprint(yytext[0])); -} - - /* size specifiers */ -byte { yylval.int_val = 1; return BYTE; } -word { yylval.int_val = 2; return WORD; } -dword { yylval.int_val = 4; return DWORD; } -qword { yylval.int_val = 8; return QWORD; } -tword { yylval.int_val = 10; return TWORD; } -dqword { yylval.int_val = 16; return DQWORD; } - - /* pseudo-instructions */ -db { yylval.int_val = 1; return DECLARE_DATA; } -dw { yylval.int_val = 2; return DECLARE_DATA; } -dd { yylval.int_val = 4; return DECLARE_DATA; } -dq { yylval.int_val = 8; return DECLARE_DATA; } -dt { yylval.int_val = 10; return DECLARE_DATA; } - -resb { yylval.int_val = 1; return RESERVE_SPACE; } -resw { yylval.int_val = 2; return RESERVE_SPACE; } -resd { yylval.int_val = 4; return RESERVE_SPACE; } -resq { yylval.int_val = 8; return RESERVE_SPACE; } -rest { yylval.int_val = 10; return RESERVE_SPACE; } - -incbin { return INCBIN; } - -equ { return EQU; } - -times { return TIMES; } - -seg { return SEG; } -wrt { return WRT; } -near { return NEAR; } -short { return SHORT; } -far { return FAR; } - -nosplit { return NOSPLIT; } - -org { return ORG; } - -to { return TO; } - - /* operand size overrides */ -o16 { yylval.int_val = 16; return OPERSIZE; } -o32 { yylval.int_val = 32; return OPERSIZE; } - /* address size overrides */ -a16 { yylval.int_val = 16; return ADDRSIZE; } -a32 { yylval.int_val = 32; return ADDRSIZE; } - - /* instruction prefixes */ -lock { return LOCK; } -repne { return REPNZ; } -repnz { return REPNZ; } -rep { return REP; } -repe { return REPZ; } -repz { return REPZ; } - - /* control, debug, and test registers */ -cr4 { yylval.int_val = 4; return CR4; } -cr[023] { yylval.int_val = yytext[2]-'0'; return CRREG_NOTCR4; } -dr[0-367] { yylval.int_val = yytext[2]-'0'; return DRREG; } -tr[3-7] { yylval.int_val = yytext[2]-'0'; return TRREG; } - - /* floating point, MMX, and SSE registers */ -st0 { yylval.int_val = 0; return ST0; } -st[1-7] { yylval.int_val = yytext[2]-'0'; return FPUREG_NOTST0; } -mm[0-7] { yylval.int_val = yytext[2]-'0'; return MMXREG; } -xmm[0-7] { yylval.int_val = yytext[3]-'0'; return XMMREG; } - - /* integer registers */ -eax { yylval.int_val = 0; return REG_EAX; } -ecx { yylval.int_val = 1; return REG_ECX; } -edx { yylval.int_val = 2; return REG_EDX; } -ebx { yylval.int_val = 3; return REG_EBX; } -esp { yylval.int_val = 4; return REG_ESP; } -ebp { yylval.int_val = 5; return REG_EBP; } -esi { yylval.int_val = 6; return REG_ESI; } -edi { yylval.int_val = 7; return REG_EDI; } - -ax { yylval.int_val = 0; return REG_AX; } -cx { yylval.int_val = 1; return REG_CX; } -dx { yylval.int_val = 2; return REG_DX; } -bx { yylval.int_val = 3; return REG_BX; } -sp { yylval.int_val = 4; return REG_SP; } -bp { yylval.int_val = 5; return REG_BP; } -si { yylval.int_val = 6; return REG_SI; } -di { yylval.int_val = 7; return REG_DI; } - -al { yylval.int_val = 0; return REG_AL; } -cl { yylval.int_val = 1; return REG_CL; } -dl { yylval.int_val = 2; return REG_DL; } -bl { yylval.int_val = 3; return REG_BL; } -ah { yylval.int_val = 4; return REG_AH; } -ch { yylval.int_val = 5; return REG_CH; } -dh { yylval.int_val = 6; return REG_DH; } -bh { yylval.int_val = 7; return REG_BH; } - - /* segment registers */ -es { yylval.int_val = 0; return REG_ES; } -cs { yylval.int_val = 1; return REG_CS; } -ss { yylval.int_val = 2; return REG_SS; } -ds { yylval.int_val = 3; return REG_DS; } -fs { yylval.int_val = 4; return REG_FS; } -gs { yylval.int_val = 5; return REG_GS; } - -"<<" { return LEFT_OP; } -">>" { return RIGHT_OP; } -"//" { return SIGNDIV; } -"%%" { return SIGNMOD; } -[-+|^&*/%~():[\],] { return yytext[0]; } - - /* special non-local ..@label and labels like ..start */ -$$|$|\.\.[a-z0-9_$#@~.?]+ { - yylval.syminfo.name = strdup (yytext); - if (yylval.syminfo.name == NULL) Fatal (FATAL_NOMEM); - yylval.syminfo.line = line_number; - - return SPECIAL_ID; -} - - /* local label (.label) */ -\.[a-z0-9_$#@~?][a-z0-9_$#@~.?]* { - if (locallabel_base == NULL) - { - Warning (WARN_NO_BASE_LABEL, (char *)NULL, yytext); - yylval.syminfo.name = strdup (yytext); - if (yylval.syminfo.name == NULL) Fatal (FATAL_NOMEM); - } - else - { - yylval.syminfo.name = malloc (strlen (yytext) - + strlen (locallabel_base->name) - + 1); - if (yylval.syminfo.name == NULL) Fatal (FATAL_NOMEM); - strcpy (yylval.syminfo.name, locallabel_base->name); - strcat (yylval.syminfo.name, yytext); - } - yylval.syminfo.line = line_number; - - return LOCAL_ID; -} - - /* instructions */ - /* @INSTRUCTIONS@ */ - - /* label */ -[a-z_?][a-z0-9_$#@~.?]* { - yylval.syminfo.name = strdup (yytext); - if (yylval.syminfo.name == NULL) Fatal (FATAL_NOMEM); - yylval.syminfo.line = line_number; - - return ID; -} - -;.* ; - -{WS}+ ; - -\n return '\n'; - -. { Warning(WARN_UNREC_CHAR, (char *)NULL, conv_unprint(yytext[0])); } -