summaryrefslogtreecommitdiff
path: root/src/preproc/pinit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/preproc/pinit.c')
-rw-r--r--src/preproc/pinit.c251
1 files changed, 251 insertions, 0 deletions
diff --git a/src/preproc/pinit.c b/src/preproc/pinit.c
new file mode 100644
index 0000000..9f64cb0
--- /dev/null
+++ b/src/preproc/pinit.c
@@ -0,0 +1,251 @@
+/*
+ * This file contains functions used to initialize the preprocessor,
+ * particularly those for establishing implementation-dependent standard
+ * macro definitions.
+ */
+#include "../preproc/preproc.h"
+#include "../preproc/ptoken.h"
+#include "../preproc/pproto.h"
+
+static void define_opt (char *s, int len, struct token *dflt);
+static void do_directive (char *s);
+static void mac_opts (char *opt_lst, char **opt_args);
+static void undef_opt (char *s, int len);
+
+struct src dummy;
+
+/*
+ * init_preproc - initialize all parts of the preprocessor, establishing
+ * the primary file as the current source of tokens.
+ */
+void init_preproc(fname, opt_lst, opt_args)
+char *fname;
+char *opt_lst;
+char **opt_args;
+ {
+
+ init_str(); /* initialize string table */
+ init_tok(); /* initialize tokenizer */
+ init_macro(); /* initialize macro table */
+ init_files(opt_lst, opt_args); /* initialize standard header locations */
+ dummy.flag = DummySrc; /* marker at bottom of source stack */
+ dummy.ntoks = 0;
+ src_stack = &dummy;
+ mac_opts(opt_lst, opt_args); /* process options for predefined macros */
+ source(fname); /* establish primary source file */
+ }
+
+/*
+ * mac_opts - handle options which affect what predefined macros are in
+ * effect when preprocessing starts. The options may be on the command
+ * line. Also establish predefined macros.
+ */
+static void mac_opts(opt_lst, opt_args)
+char *opt_lst;
+char **opt_args;
+ {
+ int i;
+
+ /*
+ * Establish predefined macros.
+ */
+ #if CYGWIN
+ do_directive("#define __CYGWIN32__\n");
+ do_directive("#define __CYGWIN__\n");
+ do_directive("#define __unix__\n");
+ do_directive("#define __unix\n");
+ do_directive("#define _WIN32\n");
+ do_directive("#define __WIN32\n");
+ do_directive("#define __WIN32__\n");
+ #else /* CYGWIN */
+ do_directive("#define unix 1\n");
+ do_directive(PPInit); /* defines that vary between Unix systems */
+ #endif /* CYGWIN*/
+
+ /*
+ * look for options that affect macro definitions (-U, -D, etc).
+ */
+ for (i = 0; opt_lst[i] != '\0'; ++i)
+ switch(opt_lst[i]) {
+ case 'U':
+ /*
+ * Undefine and predefined identifier.
+ */
+ undef_opt(opt_args[i], (int)strlen(opt_args[i]));
+ break;
+
+ case 'D':
+ /*
+ * Define an identifier. Use "1" if no defining string is given.
+ */
+ define_opt(opt_args[i], (int)strlen(opt_args[i]), one_tok);
+ break;
+ }
+ }
+
+/*
+ * str_src - establish a string, given by a character pointer and a length,
+ * as the current source of tokens.
+ */
+void str_src(src_name, s, len)
+char *src_name;
+char *s;
+int len;
+ {
+ union src_ref ref;
+ int *ip1, *ip2;
+
+ /*
+ * Create a character source with a large enought buffer for the string.
+ */
+ ref.cs = new_cs(src_name, NULL, len + 1);
+ push_src(CharSrc, &ref);
+ ip1 = ref.cs->char_buf;
+ ip2 = ref.cs->line_buf;
+ while (len-- > 0) {
+ *ip1++ = *s++; /* copy string to source buffer */
+ *ip2++ = 0; /* characters are from "line 0" */
+ }
+ *ip1 = EOF;
+ *ip2 = 0;
+ ref.cs->next_char = ref.cs->char_buf;
+ ref.cs->last_char = ip1;
+ first_char = ref.cs->char_buf;
+ next_char = first_char;
+ last_char = ref.cs->last_char;
+ }
+
+/*
+ * do_directive - take a character string containing preprocessor
+ * directives separated by new-lines and execute them. This done
+ * by preprocessing the string.
+ */
+static void do_directive(s)
+char *s;
+ {
+ str_src("<initialization>", s, (int)strlen(s));
+ while (interp_dir() != NULL)
+ ;
+ }
+
+/*
+ * undef_opt - take the argument to a -U option and, if it is valid,
+ * undefine it.
+ */
+static void undef_opt(s, len)
+char *s;
+int len;
+ {
+ struct token *mname;
+ int i;
+
+ /*
+ * The name is needed in the form of a token. Use the preprocessor
+ * to tokenize it.
+ */
+ str_src("<options>", s, len);
+ mname = next_tok();
+ if (mname == NULL || mname->tok_id != Identifier ||
+ next_tok() != NULL) {
+ fprintf(stderr, "invalid argument to -U option: ");
+ for (i = 0; i < len; ++i)
+ putc(s[i], stderr); /* show offending argument */
+ putc('\n', stderr);
+ show_usage();
+ }
+ m_delete(mname);
+ }
+
+/*
+ * define_opt - take an argument to a -D option and, if it is valid, perform
+ * the requested definition.
+ */
+static void define_opt(s, len, dflt)
+char *s;
+int len;
+struct token *dflt;
+ {
+ struct token *mname;
+ struct token *t;
+ struct tok_lst *body;
+ struct tok_lst **ptlst, **trail_whsp;
+ int i;
+
+ /*
+ * The argument to -D must be tokenized.
+ */
+ str_src("<options>", s, len);
+
+ /*
+ * Find the macro name.
+ */
+ mname = next_tok();
+ if (mname == NULL || mname->tok_id != Identifier) {
+ fprintf(stderr, "invalid argument to -D option: ");
+ for (i = 0; i < len; ++i)
+ putc(s[i], stderr);
+ putc('\n', stderr);
+ show_usage();
+ }
+
+ /*
+ * Determine if the name is followed by '='.
+ */
+ if (chk_eq_sign()) {
+ /*
+ * Macro body is given, strip leading white space
+ */
+ t = next_tok();
+ if (t != NULL && t->tok_id == WhiteSpace) {
+ free_t(t);
+ t = next_tok();
+ }
+
+
+ /*
+ * Construct the token list for body of macro. Keep track of trailing
+ * white space so it can be deleted.
+ */
+ body = NULL;
+ ptlst = &body;
+ trail_whsp = NULL;
+ while (t != NULL) {
+ t->flag &= ~LineChk;
+ (*ptlst) = new_t_lst(t);
+ if (t->tok_id == WhiteSpace)
+ trail_whsp = ptlst;
+ else
+ trail_whsp = NULL;
+ ptlst = &(*ptlst)->next;
+ t = next_tok();
+ }
+
+ /*
+ * strip trailing white space
+ */
+ if (trail_whsp != NULL) {
+ free_t_lst(*trail_whsp);
+ *trail_whsp = NULL;
+ }
+ }
+ else {
+ /*
+ * There is no '=' after the macro name; use the supplied
+ * default value for the macro definition.
+ */
+ if (next_tok() == NULL)
+ if (dflt == NULL)
+ body = NULL;
+ else
+ body = new_t_lst(copy_t(dflt));
+ else {
+ fprintf(stderr, "invalid argument to -D option: ");
+ for (i = 0; i < len; ++i)
+ putc(s[i], stderr);
+ putc('\n', stderr);
+ show_usage();
+ }
+ }
+
+ m_install(mname, NoArgs, 0, NULL, body); /* install macro definition */
+ }