functions to be a bit more clean.
svn path=/trunk/yasm/; revision=479
src/arch.h \
src/objfmt.c \
src/objfmt.h \
+ src/preproc.c \
src/preproc.h \
src/parser.c \
src/parser.h \
#define countof(x,y) (sizeof(x)/sizeof(y))
#endif
-static int files_open = 0;
+/* Preprocess-only buffer size */
+#define PREPROC_BUF_SIZE 16384
+
/*@null@*/ /*@only@*/ static char *obj_filename = NULL, *in_filename = NULL;
-/*@null@*/ static FILE *in = NULL, *obj = NULL;
static int special_options = 0;
+static preproc *cur_preproc = NULL;
+static int preproc_only = 0;
-static int open_obj(void);
+static FILE *open_obj(void);
static void cleanup(sectionhead *sections);
/* Forward declarations: cmd line parser handlers */
static int opt_special_handler(char *cmd, /*@null@*/ char *param, int extra);
-static int opt_format_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_parser_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_preproc_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_objfmt_handler(char *cmd, /*@null@*/ char *param, int extra);
static int opt_objfile_handler(char *cmd, /*@null@*/ char *param, int extra);
static int opt_warning_handler(char *cmd, /*@null@*/ char *param, int extra);
-/* Fake handlers: remove them */
-static int boo_boo_handler(char *cmd, /*@null@*/ char *param, int extra);
-static int b_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int preproc_only_handler(char *cmd, /*@null@*/ char *param, int extra);
/* values for special_options */
#define SPECIAL_SHOW_HELP 0x01
{
{ 0, "version", 0, opt_special_handler, SPECIAL_SHOW_VERSION, N_("show version text"), NULL },
{ 'h', "help", 0, opt_special_handler, SPECIAL_SHOW_HELP, N_("show help text"), NULL },
- { 'f', "oformat", 1, opt_format_handler, 0, N_("select output format"), N_("<format>") },
- { 'o', "objfile", 1, opt_objfile_handler, 0, N_("name of object-file output"), N_("<filename>") },
+ { 'p', "parser", 1, opt_parser_handler, 0, N_("select parser"), N_("parser") },
+ { 'r', "preproc", 1, opt_preproc_handler, 0, N_("select preprocessor"), N_("preproc") },
+ { 'f', "oformat", 1, opt_objfmt_handler, 0, N_("select object format"), N_("format") },
+ { 'o', "objfile", 1, opt_objfile_handler, 0, N_("name of object-file output"), N_("filename") },
{ 'w', NULL, 0, opt_warning_handler, 1, N_("inhibits warning messages"), NULL },
{ 'W', NULL, 0, opt_warning_handler, 0, N_("enables/disables warning"), NULL },
- /* Fake handlers: remove them */
- { 'b', NULL, 0, b_handler, 0, "says boom!", NULL },
- { 0, "boo-boo", 0, boo_boo_handler, 0, "says boo-boo!", NULL },
+ { 'e', "preproc-only", 0, preproc_only_handler, 0, N_("preprocess only (writes output to stdout by default)"), NULL },
};
/* version message */
/* help messages */
static const char help_head[] = N_(
- "usage: yasm [options|files]+\n"
+ "usage: yasm [option]* file\n"
"Options:\n");
static const char help_tail[] = N_(
"\n"
int
main(int argc, char *argv[])
{
+ /*@null@*/ FILE *in = NULL, *obj = NULL;
sectionhead *sections;
#if defined(HAVE_SETLOCALE) && defined(HAVE_LC_MESSAGES)
return EXIT_FAILURE;
}
- /* if no files were specified, fallback to reading stdin */
- if (!in || !in_filename) {
+ if (in_filename && strcmp(in_filename, "-") != 0) {
+ /* Open the input file (if not standard input) */
+ in = fopen(in_filename, "rt");
+ if (!in) {
+ ErrorNow(_("could not open file `%s'"), in_filename);
+ return EXIT_FAILURE;
+ }
+ } else {
+ /* If no files were specified, fallback to reading stdin */
in = stdin;
- if (in_filename)
- xfree(in_filename);
- in_filename = xstrdup("<STDIN>");
- if (!obj)
- obj = stdout;
+ if (!in_filename)
+ in_filename = xstrdup("-");
+ /* Default to stdout if no obj filename specified */
+ if (!obj_filename)
+ obj_filename = xstrdup("-");
}
/* Initialize line info */
cur_objfmt = find_objfmt("dbg");
assert(cur_objfmt != NULL);
- /* open the object file if not specified */
- if (!obj) {
- /* build the object filename */
- if (obj_filename)
- xfree(obj_filename);
- assert(in_filename != NULL);
+ /* handle preproc-only case here */
+ if (preproc_only) {
+ char *preproc_buf = xmalloc(PREPROC_BUF_SIZE);
+ size_t got;
+
+ /* Default output to stdout if not specified */
+ if (!obj_filename)
+ obj_filename = xstrdup("-");
+
+ /* Open output (object) file */
+ obj = open_obj();
+ if (!obj)
+ return EXIT_FAILURE;
+
+ /* If not already specified, default to raw preproc. */
+ if (!cur_preproc)
+ cur_preproc = find_preproc("raw");
+ assert(cur_preproc != NULL);
+
+ /* Pre-process until done */
+ cur_preproc->initialize(in);
+ while ((got = cur_preproc->input(preproc_buf, PREPROC_BUF_SIZE)) != 0)
+ fwrite(preproc_buf, got, 1, obj);
+
+ if (in != stdin)
+ fclose(in);
+ xfree(in_filename);
+
+ if (obj != stdout)
+ fclose(obj);
+
+ if (OutputAllErrorWarning() > 0) {
+ if (obj != stdout)
+ remove(obj_filename);
+ return EXIT_FAILURE;
+ }
+ xfree(obj_filename);
+
+ return EXIT_SUCCESS;
+ }
+
+ /* determine the object filename if not specified or stdout defaulted */
+ if (!obj_filename)
/* replace (or add) extension */
obj_filename = replace_extension(in_filename, cur_objfmt->extension,
"yasm.out");
- }
/* Pre-open the object file as debug_file if we're using a debug-type
* format. (This is so the format can output ALL function call info).
*/
if (strcmp(cur_objfmt->keyword, "dbg") == 0) {
- if (!open_obj())
+ obj = open_obj();
+ if (!obj)
return EXIT_FAILURE;
debug_file = obj;
}
return EXIT_FAILURE;
}
+ /* (Try to) set a preprocessor, if requested */
+ if (cur_preproc) {
+ if (parser_setpp(cur_parser, cur_preproc->keyword)) {
+ if (in != stdin)
+ fclose(in);
+ xfree(in_filename);
+ return EXIT_FAILURE;
+ }
+ }
+
/* Get initial BITS setting from object format */
x86_mode_bits = cur_objfmt->default_mode_bits;
+ /* Parse! */
sections = cur_parser->do_parse(cur_parser, in);
+ /* Close input file */
if (in != stdin)
fclose(in);
- if (in_filename)
- xfree(in_filename);
+ xfree(in_filename);
if (OutputAllErrorWarning() > 0) {
cleanup(sections);
}
/* open the object file for output (if not already opened above) */
- if (!debug_file) {
- if (!open_obj())
+ if (!obj) {
+ obj = open_obj();
+ if (!obj) {
+ cleanup(sections);
return EXIT_FAILURE;
+ }
}
/* Write the object file */
cur_objfmt->output(obj, sections);
- /* Finalize the object output */
- cur_objfmt->cleanup();
-
+ /* Close object file */
if (obj != stdout)
fclose(obj);
return EXIT_FAILURE;
}
- if (obj_filename)
- xfree(obj_filename);
+ xfree(obj_filename);
cleanup(sections);
return EXIT_SUCCESS;
/*@=globstate =unrecog@*/
/* Open the object file. Returns 0 on failure. */
-static int
+static FILE *
open_obj(void)
{
- if (obj != stdout) {
+ FILE *obj;
+
+ assert(obj_filename != NULL);
+
+ if (strcmp(obj_filename, "-") == 0)
+ obj = stdout;
+ else {
obj = fopen(obj_filename, "wb");
- if (!obj) {
+ if (!obj)
ErrorNow(_("could not open file `%s'"), obj_filename);
- return 0;
- }
}
- return 1;
+ return obj;
}
/* Cleans up all allocated structures. */
{
sections_delete(sections);
symrec_delete_all();
+ if (cur_objfmt)
+ cur_objfmt->cleanup();
line_shutdown();
floatnum_shutdown();
int
not_an_option_handler(char *param)
{
- if (in) {
- WarningNow("can open only one input file, only latest file will be processed");
- if (fclose(in))
- ErrorNow("could not close old input file");
+ if (in_filename) {
+ WarningNow("can open only one input file, only the last file will be processed");
+ xfree(in_filename);
}
- in = fopen(param, "rt");
- if (!in) {
- ErrorNow(_("could not open file `%s'"), param);
- return 1;
- }
- if (in_filename)
- xfree(in_filename);
in_filename = xstrdup(param);
- files_open++;
return 0;
}
}
static int
-opt_format_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
+opt_parser_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
+{
+ assert(param != NULL);
+ cur_parser = find_parser(param);
+ if (!cur_parser) {
+ ErrorNow(_("unrecognized parser `%s'"), param);
+ return 1;
+ }
+ return 0;
+}
+
+static int
+opt_preproc_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
+{
+ assert(param != NULL);
+ cur_preproc = find_preproc(param);
+ if (!cur_preproc) {
+ ErrorNow(_("unrecognized preprocessor `%s'"), param);
+ return 1;
+ }
+ return 0;
+}
+
+static int
+opt_objfmt_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
{
assert(param != NULL);
cur_objfmt = find_objfmt(param);
opt_objfile_handler(/*@unused@*/ char *cmd, char *param,
/*@unused@*/ int extra)
{
- assert(param != NULL);
- if (strcmp(param, "-") == 0)
- obj = stdout;
- else {
- if (obj) {
- WarningNow("can open only one output file, last specified used");
- if (obj != stdout && fclose(obj))
- ErrorNow("could not close old output file");
- }
- }
-
- if (obj != stdout) {
- obj = fopen(param, "wb");
- if (!obj) {
- ErrorNow(_("could not open file `%s'"), param);
- return 1;
- }
+ if (obj_filename) {
+ WarningNow(_("can output to only one object file, last specified used"));
+ xfree(obj_filename);
}
- if (obj_filename)
- xfree(obj_filename);
+ assert(param != NULL);
obj_filename = xstrdup(param);
return 0;
return 0;
}
-/* Fake handlers: remove them */
-static int
-boo_boo_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param,
- /*@unused@*/ int extra)
-{
- printf("boo-boo!\n");
- return 0;
-}
-
static int
-b_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param,
- /*@unused@*/ int extra)
+preproc_only_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param,
+ /*@unused@*/ int extra)
{
- fprintf(stdout, "boom!\n");
+ preproc_only = 1;
return 0;
}
src/arch.h \
src/objfmt.c \
src/objfmt.h \
+ src/preproc.c \
src/preproc.h \
src/parser.c \
src/parser.h \
/* Available preprocessors */
extern preproc raw_preproc;
+/* Finds a preproc based on its keyword. Returns NULL if no match was found.
+ */
+/*@null@*/ preproc *find_preproc(const char *keyword);
+
+/* Lists all available preprocs. Calls printfunc with the name and keyword
+ * of each available preprocessor.
+ */
+void list_preprocs(void (*printfunc) (const char *name, const char *keyword));
+
#endif
src/arch.h \
src/objfmt.c \
src/objfmt.h \
+ src/preproc.c \
src/preproc.h \
src/parser.c \
src/parser.h \
src/arch.h \
src/objfmt.c \
src/objfmt.h \
+ src/preproc.c \
src/preproc.h \
src/parser.c \
src/parser.h \
#define countof(x,y) (sizeof(x)/sizeof(y))
#endif
-static int files_open = 0;
+/* Preprocess-only buffer size */
+#define PREPROC_BUF_SIZE 16384
+
/*@null@*/ /*@only@*/ static char *obj_filename = NULL, *in_filename = NULL;
-/*@null@*/ static FILE *in = NULL, *obj = NULL;
static int special_options = 0;
+static preproc *cur_preproc = NULL;
+static int preproc_only = 0;
-static int open_obj(void);
+static FILE *open_obj(void);
static void cleanup(sectionhead *sections);
/* Forward declarations: cmd line parser handlers */
static int opt_special_handler(char *cmd, /*@null@*/ char *param, int extra);
-static int opt_format_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_parser_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_preproc_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_objfmt_handler(char *cmd, /*@null@*/ char *param, int extra);
static int opt_objfile_handler(char *cmd, /*@null@*/ char *param, int extra);
static int opt_warning_handler(char *cmd, /*@null@*/ char *param, int extra);
-/* Fake handlers: remove them */
-static int boo_boo_handler(char *cmd, /*@null@*/ char *param, int extra);
-static int b_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int preproc_only_handler(char *cmd, /*@null@*/ char *param, int extra);
/* values for special_options */
#define SPECIAL_SHOW_HELP 0x01
{
{ 0, "version", 0, opt_special_handler, SPECIAL_SHOW_VERSION, N_("show version text"), NULL },
{ 'h', "help", 0, opt_special_handler, SPECIAL_SHOW_HELP, N_("show help text"), NULL },
- { 'f', "oformat", 1, opt_format_handler, 0, N_("select output format"), N_("<format>") },
- { 'o', "objfile", 1, opt_objfile_handler, 0, N_("name of object-file output"), N_("<filename>") },
+ { 'p', "parser", 1, opt_parser_handler, 0, N_("select parser"), N_("parser") },
+ { 'r', "preproc", 1, opt_preproc_handler, 0, N_("select preprocessor"), N_("preproc") },
+ { 'f', "oformat", 1, opt_objfmt_handler, 0, N_("select object format"), N_("format") },
+ { 'o', "objfile", 1, opt_objfile_handler, 0, N_("name of object-file output"), N_("filename") },
{ 'w', NULL, 0, opt_warning_handler, 1, N_("inhibits warning messages"), NULL },
{ 'W', NULL, 0, opt_warning_handler, 0, N_("enables/disables warning"), NULL },
- /* Fake handlers: remove them */
- { 'b', NULL, 0, b_handler, 0, "says boom!", NULL },
- { 0, "boo-boo", 0, boo_boo_handler, 0, "says boo-boo!", NULL },
+ { 'e', "preproc-only", 0, preproc_only_handler, 0, N_("preprocess only (writes output to stdout by default)"), NULL },
};
/* version message */
/* help messages */
static const char help_head[] = N_(
- "usage: yasm [options|files]+\n"
+ "usage: yasm [option]* file\n"
"Options:\n");
static const char help_tail[] = N_(
"\n"
int
main(int argc, char *argv[])
{
+ /*@null@*/ FILE *in = NULL, *obj = NULL;
sectionhead *sections;
#if defined(HAVE_SETLOCALE) && defined(HAVE_LC_MESSAGES)
return EXIT_FAILURE;
}
- /* if no files were specified, fallback to reading stdin */
- if (!in || !in_filename) {
+ if (in_filename && strcmp(in_filename, "-") != 0) {
+ /* Open the input file (if not standard input) */
+ in = fopen(in_filename, "rt");
+ if (!in) {
+ ErrorNow(_("could not open file `%s'"), in_filename);
+ return EXIT_FAILURE;
+ }
+ } else {
+ /* If no files were specified, fallback to reading stdin */
in = stdin;
- if (in_filename)
- xfree(in_filename);
- in_filename = xstrdup("<STDIN>");
- if (!obj)
- obj = stdout;
+ if (!in_filename)
+ in_filename = xstrdup("-");
+ /* Default to stdout if no obj filename specified */
+ if (!obj_filename)
+ obj_filename = xstrdup("-");
}
/* Initialize line info */
cur_objfmt = find_objfmt("dbg");
assert(cur_objfmt != NULL);
- /* open the object file if not specified */
- if (!obj) {
- /* build the object filename */
- if (obj_filename)
- xfree(obj_filename);
- assert(in_filename != NULL);
+ /* handle preproc-only case here */
+ if (preproc_only) {
+ char *preproc_buf = xmalloc(PREPROC_BUF_SIZE);
+ size_t got;
+
+ /* Default output to stdout if not specified */
+ if (!obj_filename)
+ obj_filename = xstrdup("-");
+
+ /* Open output (object) file */
+ obj = open_obj();
+ if (!obj)
+ return EXIT_FAILURE;
+
+ /* If not already specified, default to raw preproc. */
+ if (!cur_preproc)
+ cur_preproc = find_preproc("raw");
+ assert(cur_preproc != NULL);
+
+ /* Pre-process until done */
+ cur_preproc->initialize(in);
+ while ((got = cur_preproc->input(preproc_buf, PREPROC_BUF_SIZE)) != 0)
+ fwrite(preproc_buf, got, 1, obj);
+
+ if (in != stdin)
+ fclose(in);
+ xfree(in_filename);
+
+ if (obj != stdout)
+ fclose(obj);
+
+ if (OutputAllErrorWarning() > 0) {
+ if (obj != stdout)
+ remove(obj_filename);
+ return EXIT_FAILURE;
+ }
+ xfree(obj_filename);
+
+ return EXIT_SUCCESS;
+ }
+
+ /* determine the object filename if not specified or stdout defaulted */
+ if (!obj_filename)
/* replace (or add) extension */
obj_filename = replace_extension(in_filename, cur_objfmt->extension,
"yasm.out");
- }
/* Pre-open the object file as debug_file if we're using a debug-type
* format. (This is so the format can output ALL function call info).
*/
if (strcmp(cur_objfmt->keyword, "dbg") == 0) {
- if (!open_obj())
+ obj = open_obj();
+ if (!obj)
return EXIT_FAILURE;
debug_file = obj;
}
return EXIT_FAILURE;
}
+ /* (Try to) set a preprocessor, if requested */
+ if (cur_preproc) {
+ if (parser_setpp(cur_parser, cur_preproc->keyword)) {
+ if (in != stdin)
+ fclose(in);
+ xfree(in_filename);
+ return EXIT_FAILURE;
+ }
+ }
+
/* Get initial BITS setting from object format */
x86_mode_bits = cur_objfmt->default_mode_bits;
+ /* Parse! */
sections = cur_parser->do_parse(cur_parser, in);
+ /* Close input file */
if (in != stdin)
fclose(in);
- if (in_filename)
- xfree(in_filename);
+ xfree(in_filename);
if (OutputAllErrorWarning() > 0) {
cleanup(sections);
}
/* open the object file for output (if not already opened above) */
- if (!debug_file) {
- if (!open_obj())
+ if (!obj) {
+ obj = open_obj();
+ if (!obj) {
+ cleanup(sections);
return EXIT_FAILURE;
+ }
}
/* Write the object file */
cur_objfmt->output(obj, sections);
- /* Finalize the object output */
- cur_objfmt->cleanup();
-
+ /* Close object file */
if (obj != stdout)
fclose(obj);
return EXIT_FAILURE;
}
- if (obj_filename)
- xfree(obj_filename);
+ xfree(obj_filename);
cleanup(sections);
return EXIT_SUCCESS;
/*@=globstate =unrecog@*/
/* Open the object file. Returns 0 on failure. */
-static int
+static FILE *
open_obj(void)
{
- if (obj != stdout) {
+ FILE *obj;
+
+ assert(obj_filename != NULL);
+
+ if (strcmp(obj_filename, "-") == 0)
+ obj = stdout;
+ else {
obj = fopen(obj_filename, "wb");
- if (!obj) {
+ if (!obj)
ErrorNow(_("could not open file `%s'"), obj_filename);
- return 0;
- }
}
- return 1;
+ return obj;
}
/* Cleans up all allocated structures. */
{
sections_delete(sections);
symrec_delete_all();
+ if (cur_objfmt)
+ cur_objfmt->cleanup();
line_shutdown();
floatnum_shutdown();
int
not_an_option_handler(char *param)
{
- if (in) {
- WarningNow("can open only one input file, only latest file will be processed");
- if (fclose(in))
- ErrorNow("could not close old input file");
+ if (in_filename) {
+ WarningNow("can open only one input file, only the last file will be processed");
+ xfree(in_filename);
}
- in = fopen(param, "rt");
- if (!in) {
- ErrorNow(_("could not open file `%s'"), param);
- return 1;
- }
- if (in_filename)
- xfree(in_filename);
in_filename = xstrdup(param);
- files_open++;
return 0;
}
}
static int
-opt_format_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
+opt_parser_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
+{
+ assert(param != NULL);
+ cur_parser = find_parser(param);
+ if (!cur_parser) {
+ ErrorNow(_("unrecognized parser `%s'"), param);
+ return 1;
+ }
+ return 0;
+}
+
+static int
+opt_preproc_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
+{
+ assert(param != NULL);
+ cur_preproc = find_preproc(param);
+ if (!cur_preproc) {
+ ErrorNow(_("unrecognized preprocessor `%s'"), param);
+ return 1;
+ }
+ return 0;
+}
+
+static int
+opt_objfmt_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
{
assert(param != NULL);
cur_objfmt = find_objfmt(param);
opt_objfile_handler(/*@unused@*/ char *cmd, char *param,
/*@unused@*/ int extra)
{
- assert(param != NULL);
- if (strcmp(param, "-") == 0)
- obj = stdout;
- else {
- if (obj) {
- WarningNow("can open only one output file, last specified used");
- if (obj != stdout && fclose(obj))
- ErrorNow("could not close old output file");
- }
- }
-
- if (obj != stdout) {
- obj = fopen(param, "wb");
- if (!obj) {
- ErrorNow(_("could not open file `%s'"), param);
- return 1;
- }
+ if (obj_filename) {
+ WarningNow(_("can output to only one object file, last specified used"));
+ xfree(obj_filename);
}
- if (obj_filename)
- xfree(obj_filename);
+ assert(param != NULL);
obj_filename = xstrdup(param);
return 0;
return 0;
}
-/* Fake handlers: remove them */
-static int
-boo_boo_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param,
- /*@unused@*/ int extra)
-{
- printf("boo-boo!\n");
- return 0;
-}
-
static int
-b_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param,
- /*@unused@*/ int extra)
+preproc_only_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param,
+ /*@unused@*/ int extra)
{
- fprintf(stdout, "boom!\n");
+ preproc_only = 1;
return 0;
}
--- /dev/null
+/*
+ * Generic functions for all preprocessors
+ *
+ * Copyright (C) 2002 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 "util.h"
+/*@unused@*/ RCSID("$IdPath$");
+
+#include "globals.h"
+
+#include "preproc.h"
+
+
+/* NULL-terminated list of all available preprocessors.
+ * Someday change this if we dynamically load preprocessors at runtime.
+ * Could improve this a little by generating automatically at build-time.
+ */
+/*@-nullassign@*/
+static preproc *preprocs[] = {
+ &raw_preproc,
+ NULL
+};
+/*@=nullassign@*/
+
+preproc *
+find_preproc(const char *keyword)
+{
+ int i;
+
+ /* We're just doing a linear search, as there aren't many preprocs */
+ for (i = 0; preprocs[i]; i++) {
+ if (strcasecmp(preprocs[i]->keyword, keyword) == 0)
+ /*@-unqualifiedtrans@*/
+ return preprocs[i];
+ /*@=unqualifiedtrans@*/
+ }
+
+ /* no match found */
+ return NULL;
+}
+
+void
+list_preprocs(void (*printfunc) (const char *name, const char *keyword))
+{
+ int i;
+
+ for (i = 0; preprocs[i]; i++) {
+ printfunc(preprocs[i]->name, preprocs[i]->keyword);
+ }
+}
/* Available preprocessors */
extern preproc raw_preproc;
+/* Finds a preproc based on its keyword. Returns NULL if no match was found.
+ */
+/*@null@*/ preproc *find_preproc(const char *keyword);
+
+/* Lists all available preprocs. Calls printfunc with the name and keyword
+ * of each available preprocessor.
+ */
+void list_preprocs(void (*printfunc) (const char *name, const char *keyword));
+
#endif