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
-/* $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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-
-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;
{
FILE *in;
- yydebug = 1;
-
if(argc==2) {
in = fopen(argv[1], "rt");
if(!in) {
return EXIT_FAILURE;
}
filename = strdup(argv[1]);
- yyin = in;
- } else
- filename = strdup("<UNKNOWN>");
+ } else {
+ in = stdin;
+ filename = strdup("<STDIN>");
+ }
- yyparse();
+ nasm_parser.doparse(&raw_preproc, &dbg_outfmt, in);
if(filename)
free(filename);
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
-/* $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
enum type { SECTION, ABSOLUTE };
+ char *name;
+ unsigned int id;
+
union {
/* SECTION data */
- char *name;
/* ABSOLUTE data */
unsigned long start;
} data;
--- /dev/null
+.*.sw?
+Makefile.in
+Makefile
--- /dev/null
+SUBDIRS = dbg
--- /dev/null
+.*.sw?
+Makefile.in
+Makefile
+.deps
+liboutfmt.a
--- /dev/null
+noinst_LIBRARIES = liboutfmt.a
+
+liboutfmt_a_SOURCES = \
+ outfmt.c
+
+INCLUDES=-I$(top_srcdir)/src
+
+if DEV
+CFLAGS = -ansi -pedantic -Wall -g
+endif
--- /dev/null
+/* $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"
+};
--- /dev/null
+/* $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"
+};
--- /dev/null
+/* $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"
+};
--- /dev/null
+.*.sw?
+Makefile.in
+Makefile
--- /dev/null
+SUBDIRS = nasm
--- /dev/null
+.*.sw?
+bison.c
+bison.h
+token.c
+bison.y
+token.l
+Makefile.in
+Makefile
+.deps
+libparser.a
--- /dev/null
+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
-/* $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
#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 *);
%}
return retval;
}
+void
+nasm_parser_error(char *s)
+{
+ yyerror(s);
+}
+
-/* $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
#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 *);
%}
return retval;
}
+void
+nasm_parser_error(char *s)
+{
+ yyerror(s);
+}
+
--- /dev/null
+/* $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 <stdio.h>
+#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
+};
--- /dev/null
+/* $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 <stdio.h>
+#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
+};
-/* $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
#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
--- /dev/null
+.*.sw?
+Makefile.in
+Makefile
--- /dev/null
+SUBDIRS = raw
--- /dev/null
+.*.sw?
+Makefile.in
+Makefile
+.deps
+libpreproc.a
--- /dev/null
+noinst_LIBRARIES = libpreproc.a
+
+libpreproc_a_SOURCES = \
+ preproc.c
+
+INCLUDES=-I$(top_srcdir)/src
+
+if DEV
+CFLAGS = -ansi -pedantic -Wall -g
+endif
--- /dev/null
+/* $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 <stdio.h>
+#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
+};
--- /dev/null
+/* $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 <stdio.h>
+#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
+};
.*.sw?
-bison.c
-bison.h
-token.c
-bison.y
-token.l
Makefile.in
Makefile
.deps
+SUBDIRS = parsers preprocs outfmts
+
bin_PROGRAMS = yasm
yasm_SOURCES = \
- bison.y \
- token.l \
bytecode.c \
bytecode.h \
errwarn.c \
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
+++ /dev/null
-/* $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 <math.h>
-#include <stdlib.h>
-#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 <int_val> INTNUM
-%token <double_val> FLTNUM
-%token <str_val> DIRECTIVE_NAME DIRECTIVE_VAL STRING
-%token <int_val> BYTE WORD DWORD QWORD TWORD DQWORD
-%token <int_val> DECLARE_DATA
-%token <int_val> 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 <int_val> OPERSIZE ADDRSIZE
-%token <int_val> CR4 CRREG_NOTCR4 DRREG TRREG ST0 FPUREG_NOTST0 MMXREG XMMREG
-%token <int_val> REG_EAX REG_ECX REG_EDX REG_EBX REG_ESP REG_EBP REG_ESI REG_EDI
-%token <int_val> REG_AX REG_CX REG_DX REG_BX REG_SP REG_BP REG_SI REG_DI
-%token <int_val> REG_AL REG_CL REG_DL REG_BL REG_AH REG_CH REG_DH REG_BH
-%token <int_val> REG_ES REG_CS REG_SS REG_DS REG_FS REG_GS
-%token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD
-%token <syminfo> ID LOCAL_ID SPECIAL_ID
-
-/* instruction tokens (dynamically generated) */
-/* @TOKENS@ */
-
-/* @TYPES@ */
-
-%type <bc> line exp instr instrbase label
-
-%type <int_val> fpureg reg32 reg16 reg8 segreg
-%type <ea_val> mem memaddr memexp memfar
-%type <ea_val> mem8x mem16x mem32x mem64x mem80x mem128x
-%type <ea_val> mem8 mem16 mem32 mem64 mem80 mem128 mem1632
-%type <ea_val> rm8x rm16x rm32x /*rm64x rm128x*/
-%type <ea_val> rm8 rm16 rm32 rm64 rm128
-%type <im_val> imm imm8x imm16x imm32x imm8 imm16 imm32
-%type <exp> expr expr_no_string
-%type <syminfo> explabel
-%type <sym> label_id
-%type <tgt_val> target
-%type <data> 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;
-}
-
+++ /dev/null
-#!/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 (<INPUT>)
- {
- 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 <groupdata> 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 (<IN>)
- {
- # 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 (<IN>)
- {
- if (m{/[*]\s*[@]TOKENS[@]\s*[*]/})
- {
- my $len = length("%token <groupdata>");
- print GRAMMAR "%token <groupdata>";
- 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 <groupdata> GRP_\U$group\E";
- $len = length("%token <groupdata> GRP_$group");
- }
- }
- print GRAMMAR "\n";
- }
- elsif (m{/[*]\s*[@]TYPES[@]\s*[*]/})
- {
- my $len = length("%type <bc>");
- print GRAMMAR "%type <bc>";
- foreach my $group (sort keys %$groups)
- {
- if ($len + length($group) < 76)
- {
- print GRAMMAR " $group";
- $len += length(" $group");
- }
- else
- {
- print GRAMMAR "\n%type <bc> $group";
- $len = length("%type <bc> $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;
-}
-/* $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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-
-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;
{
FILE *in;
- yydebug = 1;
-
if(argc==2) {
in = fopen(argv[1], "rt");
if(!in) {
return EXIT_FAILURE;
}
filename = strdup(argv[1]);
- yyin = in;
- } else
- filename = strdup("<UNKNOWN>");
+ } else {
+ in = stdin;
+ filename = strdup("<STDIN>");
+ }
- yyparse();
+ nasm_parser.doparse(&raw_preproc, &dbg_outfmt, in);
if(filename)
free(filename);
--- /dev/null
+/* $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
--- /dev/null
+.*.sw?
+Makefile.in
+Makefile
--- /dev/null
+SUBDIRS = dbg
--- /dev/null
+.*.sw?
+Makefile.in
+Makefile
+.deps
+liboutfmt.a
--- /dev/null
+noinst_LIBRARIES = liboutfmt.a
+
+liboutfmt_a_SOURCES = \
+ outfmt.c
+
+INCLUDES=-I$(top_srcdir)/src
+
+if DEV
+CFLAGS = -ansi -pedantic -Wall -g
+endif
--- /dev/null
+/* $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"
+};
--- /dev/null
+/* $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"
+};
--- /dev/null
+/* $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"
+};
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+.*.sw?
+Makefile.in
+Makefile
--- /dev/null
+SUBDIRS = nasm
--- /dev/null
+.*.sw?
+bison.c
+bison.h
+token.c
+bison.y
+token.l
+Makefile.in
+Makefile
+.deps
+libparser.a
--- /dev/null
+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
-/* $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
#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 *);
%}
return retval;
}
+void
+nasm_parser_error(char *s)
+{
+ yyerror(s);
+}
+
-/* $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
#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 *);
%}
return retval;
}
+void
+nasm_parser_error(char *s)
+{
+ yyerror(s);
+}
+
--- /dev/null
+/* $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 <stdio.h>
+#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
+};
--- /dev/null
+/* $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 <stdio.h>
+#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
+};
-/* $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
#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
--- /dev/null
+/* $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
--- /dev/null
+.*.sw?
+Makefile.in
+Makefile
--- /dev/null
+SUBDIRS = raw
--- /dev/null
+.*.sw?
+Makefile.in
+Makefile
+.deps
+libpreproc.a
--- /dev/null
+noinst_LIBRARIES = libpreproc.a
+
+libpreproc_a_SOURCES = \
+ preproc.c
+
+INCLUDES=-I$(top_srcdir)/src
+
+if DEV
+CFLAGS = -ansi -pedantic -Wall -g
+endif
--- /dev/null
+/* $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 <stdio.h>
+#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
+};
--- /dev/null
+/* $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 <stdio.h>
+#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
+};
-/* $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
enum type { SECTION, ABSOLUTE };
+ char *name;
+ unsigned int id;
+
union {
/* SECTION data */
- char *name;
/* ABSOLUTE data */
unsigned long start;
} data;
+++ /dev/null
-/* $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 <stdlib.h>
-# include <string.h>
-#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 '['; }
-<DIRECTIVE>"]" { BEGIN INITIAL; return ']'; }
-<DIRECTIVE2>"]" { BEGIN INITIAL; return ']'; }
-<DIRECTIVE>\n { BEGIN INITIAL; return '\n'; }
-<DIRECTIVE2>\n { BEGIN INITIAL; return '\n'; }
-<DIRECTIVE>{WS}+ ;
-<DIRECTIVE2>{WS}+ ;
-<DIRECTIVE>[a-z]+ {
- BEGIN DIRECTIVE2;
- yylval.str_val = strdup(yytext);
- if(!yylval.str_val)
- Fatal(FATAL_NOMEM);
- return DIRECTIVE_NAME;
-}
- /* everything printable except for ' ', '[' and ']'. */
-<DIRECTIVE2>[!-@a-z\\^-`{|}~]+ {
- yylval.str_val = strdup(yytext);
- if(!yylval.str_val)
- Fatal(FATAL_NOMEM);
- return DIRECTIVE_VAL;
-}
-<DIRECTIVE>. {
- Warning(WARN_UNREC_CHAR, (char *)NULL, conv_unprint(yytext[0]));
-}
-<DIRECTIVE2>. {
- 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])); }
-