summaryrefslogtreecommitdiffstats
path: root/vncmkdepend/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'vncmkdepend/parse.c')
-rw-r--r--vncmkdepend/parse.c568
1 files changed, 568 insertions, 0 deletions
diff --git a/vncmkdepend/parse.c b/vncmkdepend/parse.c
new file mode 100644
index 00000000..3f9b2fec
--- /dev/null
+++ b/vncmkdepend/parse.c
@@ -0,0 +1,568 @@
+/* $XConsortium: parse.c,v 1.30 94/04/17 20:10:38 gildea Exp $ */
+/*
+
+Copyright (c) 1993, 1994 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+*/
+
+#include "def.h"
+
+extern char *directives[];
+extern struct inclist maininclist;
+
+find_includes(filep, file, file_red, recursion, failOK)
+ struct filepointer *filep;
+ struct inclist *file, *file_red;
+ int recursion;
+ boolean failOK;
+{
+ register char *line;
+ register int type;
+ boolean recfailOK;
+
+ while (line = getline(filep)) {
+ switch(type = deftype(line, filep, file_red, file, TRUE)) {
+ case IF:
+ doif:
+ type = find_includes(filep, file,
+ file_red, recursion+1, failOK);
+ while ((type == ELIF) || (type == ELIFFALSE) ||
+ (type == ELIFGUESSFALSE))
+ type = gobble(filep, file, file_red);
+ if (type == ELSE)
+ gobble(filep, file, file_red);
+ break;
+ case IFFALSE:
+ case IFGUESSFALSE:
+ doiffalse:
+ if (type == IFGUESSFALSE || type == ELIFGUESSFALSE)
+ recfailOK = TRUE;
+ else
+ recfailOK = failOK;
+ type = gobble(filep, file, file_red);
+ if (type == ELSE)
+ find_includes(filep, file,
+ file_red, recursion+1, recfailOK);
+ else
+ if (type == ELIF)
+ goto doif;
+ else
+ if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE))
+ goto doiffalse;
+ break;
+ case IFDEF:
+ case IFNDEF:
+ if ((type == IFDEF && isdefined(line, file_red, NULL))
+ || (type == IFNDEF && !isdefined(line, file_red, NULL))) {
+ debug(1,(type == IFNDEF ?
+ "line %d: %s !def'd in %s via %s%s\n" : "",
+ filep->f_line, line,
+ file->i_file, file_red->i_file, ": doit"));
+ type = find_includes(filep, file,
+ file_red, recursion+1, failOK);
+ while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE)
+ type = gobble(filep, file, file_red);
+ if (type == ELSE)
+ gobble(filep, file, file_red);
+ }
+ else {
+ debug(1,(type == IFDEF ?
+ "line %d: %s !def'd in %s via %s%s\n" : "",
+ filep->f_line, line,
+ file->i_file, file_red->i_file, ": gobble"));
+ type = gobble(filep, file, file_red);
+ if (type == ELSE)
+ find_includes(filep, file,
+ file_red, recursion+1, failOK);
+ else if (type == ELIF)
+ goto doif;
+ else if (type == ELIFFALSE || type == ELIFGUESSFALSE)
+ goto doiffalse;
+ }
+ break;
+ case ELSE:
+ case ELIFFALSE:
+ case ELIFGUESSFALSE:
+ case ELIF:
+ if (!recursion)
+ gobble(filep, file, file_red);
+ case ENDIF:
+ if (recursion)
+ return(type);
+ case DEFINE:
+ define(line, file);
+ break;
+ case UNDEF:
+ if (!*line) {
+ warning("%s, line %d: incomplete undef == \"%s\"\n",
+ file_red->i_file, filep->f_line, line);
+ break;
+ }
+ undefine(line, file_red);
+ break;
+ case INCLUDE:
+ add_include(filep, file, file_red, line, FALSE, failOK);
+ break;
+ case INCLUDEDOT:
+ add_include(filep, file, file_red, line, TRUE, failOK);
+ break;
+ case ERROR:
+ warning("(from %s) %s: %d: %s\n",
+ file_red->i_file, file->i_file,
+ filep->f_line, line);
+ break;
+
+ case PRAGMA:
+ case IDENT:
+ case SCCS:
+ case EJECT:
+ break;
+ case -1:
+ warning("%s", file_red->i_file);
+ if (file_red != file)
+ warning1(" (reading %s)", file->i_file);
+ warning1(", line %d: unknown directive == \"%s\"\n",
+ filep->f_line, line);
+ break;
+ case -2:
+ warning("%s", file_red->i_file);
+ if (file_red != file)
+ warning1(" (reading %s)", file->i_file);
+ warning1(", line %d: incomplete include == \"%s\"\n",
+ filep->f_line, line);
+ break;
+ }
+ }
+ return(-1);
+}
+
+gobble(filep, file, file_red)
+ register struct filepointer *filep;
+ struct inclist *file, *file_red;
+{
+ register char *line;
+ register int type;
+
+ while (line = getline(filep)) {
+ switch(type = deftype(line, filep, file_red, file, FALSE)) {
+ case IF:
+ case IFFALSE:
+ case IFGUESSFALSE:
+ case IFDEF:
+ case IFNDEF:
+ type = gobble(filep, file, file_red);
+ while ((type == ELIF) || (type == ELIFFALSE) ||
+ (type == ELIFGUESSFALSE))
+ type = gobble(filep, file, file_red);
+ if (type == ELSE)
+ (void)gobble(filep, file, file_red);
+ break;
+ case ELSE:
+ case ENDIF:
+ debug(0,("%s, line %d: #%s\n",
+ file->i_file, filep->f_line,
+ directives[type]));
+ return(type);
+ case DEFINE:
+ case UNDEF:
+ case INCLUDE:
+ case INCLUDEDOT:
+ case PRAGMA:
+ case ERROR:
+ case IDENT:
+ case SCCS:
+ case EJECT:
+ break;
+ case ELIF:
+ case ELIFFALSE:
+ case ELIFGUESSFALSE:
+ return(type);
+ case -1:
+ warning("%s, line %d: unknown directive == \"%s\"\n",
+ file_red->i_file, filep->f_line, line);
+ break;
+ }
+ }
+ return(-1);
+}
+
+/*
+ * Decide what type of # directive this line is.
+ */
+int deftype (line, filep, file_red, file, parse_it)
+ register char *line;
+ register struct filepointer *filep;
+ register struct inclist *file_red, *file;
+ int parse_it;
+{
+ register char *p;
+ char *directive, savechar;
+ register int ret;
+
+ /*
+ * Parse the directive...
+ */
+ directive=line+1;
+ while (*directive == ' ' || *directive == '\t')
+ directive++;
+
+ p = directive;
+ while (*p >= 'a' && *p <= 'z')
+ p++;
+ savechar = *p;
+ *p = '\0';
+ ret = match(directive, directives);
+ *p = savechar;
+
+ /* If we don't recognize this compiler directive or we happen to just
+ * be gobbling up text while waiting for an #endif or #elif or #else
+ * in the case of an #elif we must check the zero_value and return an
+ * ELIF or an ELIFFALSE.
+ */
+
+ if (ret == ELIF && !parse_it)
+ {
+ while (*p == ' ' || *p == '\t')
+ p++;
+ /*
+ * parse an expression.
+ */
+ debug(0,("%s, line %d: #elif %s ",
+ file->i_file, filep->f_line, p));
+ ret = zero_value(p, filep, file_red);
+ if (ret != IF)
+ {
+ debug(0,("false...\n"));
+ if (ret == IFFALSE)
+ return(ELIFFALSE);
+ else
+ return(ELIFGUESSFALSE);
+ }
+ else
+ {
+ debug(0,("true...\n"));
+ return(ELIF);
+ }
+ }
+
+ if (ret < 0 || ! parse_it)
+ return(ret);
+
+ /*
+ * now decide how to parse the directive, and do it.
+ */
+ while (*p == ' ' || *p == '\t')
+ p++;
+ switch (ret) {
+ case IF:
+ /*
+ * parse an expression.
+ */
+ ret = zero_value(p, filep, file_red);
+ debug(0,("%s, line %d: %s #if %s\n",
+ file->i_file, filep->f_line, ret?"false":"true", p));
+ break;
+ case IFDEF:
+ case IFNDEF:
+ debug(0,("%s, line %d: #%s %s\n",
+ file->i_file, filep->f_line, directives[ret], p));
+ case UNDEF:
+ /*
+ * separate the name of a single symbol.
+ */
+ while (isalnum(*p) || *p == '_')
+ *line++ = *p++;
+ *line = '\0';
+ break;
+ case INCLUDE:
+ debug(2,("%s, line %d: #include %s\n",
+ file->i_file, filep->f_line, p));
+
+ /* Support ANSI macro substitution */
+ {
+ struct symtab *sym = isdefined(p, file_red, NULL);
+ while (sym) {
+ p = sym->s_value;
+ debug(3,("%s : #includes SYMBOL %s = %s\n",
+ file->i_incstring,
+ sym -> s_name,
+ sym -> s_value));
+ /* mark file as having included a 'soft include' */
+ file->i_included_sym = TRUE;
+ sym = isdefined(p, file_red, NULL);
+ }
+ }
+
+ /*
+ * Separate the name of the include file.
+ */
+ while (*p && *p != '"' && *p != '<')
+ p++;
+ if (! *p)
+ return(-2);
+ if (*p++ == '"') {
+ ret = INCLUDEDOT;
+ while (*p && *p != '"')
+ *line++ = *p++;
+ } else
+ while (*p && *p != '>')
+ *line++ = *p++;
+ *line = '\0';
+ break;
+ case DEFINE:
+ /*
+ * copy the definition back to the beginning of the line.
+ */
+ strcpy (line, p);
+ break;
+ case ELSE:
+ case ENDIF:
+ case ELIF:
+ case PRAGMA:
+ case ERROR:
+ case IDENT:
+ case SCCS:
+ case EJECT:
+ debug(0,("%s, line %d: #%s\n",
+ file->i_file, filep->f_line, directives[ret]));
+ /*
+ * nothing to do.
+ */
+ break;
+ }
+ return(ret);
+}
+
+struct symtab *isdefined(symbol, file, srcfile)
+ register char *symbol;
+ struct inclist *file;
+ struct inclist **srcfile;
+{
+ register struct symtab *val;
+
+ if (val = slookup(symbol, &maininclist)) {
+ debug(1,("%s defined on command line\n", symbol));
+ if (srcfile != NULL) *srcfile = &maininclist;
+ return(val);
+ }
+ if (val = fdefined(symbol, file, srcfile))
+ return(val);
+ debug(1,("%s not defined in %s\n", symbol, file->i_file));
+ return(NULL);
+}
+
+struct symtab *fdefined(symbol, file, srcfile)
+ register char *symbol;
+ struct inclist *file;
+ struct inclist **srcfile;
+{
+ register struct inclist **ip;
+ register struct symtab *val;
+ register int i;
+ static int recurse_lvl = 0;
+
+ if (file->i_defchecked)
+ return(NULL);
+ file->i_defchecked = TRUE;
+ if (val = slookup(symbol, file))
+ debug(1,("%s defined in %s as %s\n", symbol, file->i_file, val->s_value));
+ if (val == NULL && file->i_list)
+ {
+ for (ip = file->i_list, i=0; i < file->i_listlen; i++, ip++)
+ if (val = fdefined(symbol, *ip, srcfile)) {
+ break;
+ }
+ }
+ else if (val != NULL && srcfile != NULL) *srcfile = file;
+ recurse_lvl--;
+ file->i_defchecked = FALSE;
+
+ return(val);
+}
+
+/*
+ * Return type based on if the #if expression evaluates to 0
+ */
+zero_value(exp, filep, file_red)
+ register char *exp;
+ register struct filepointer *filep;
+ register struct inclist *file_red;
+{
+ if (cppsetup(exp, filep, file_red))
+ return(IFFALSE);
+ else
+ return(IF);
+}
+
+define(def, file)
+ char *def;
+ struct inclist *file;
+{
+ char *val;
+
+ /* Separate symbol name and its value */
+ val = def;
+ while (isalnum(*val) || *val == '_')
+ val++;
+ if (*val)
+ *val++ = '\0';
+ while (*val == ' ' || *val == '\t')
+ val++;
+
+ if (!*val)
+ val = "1";
+ define2(def, val, file);
+}
+
+define2(name, val, file)
+ char *name, *val;
+ struct inclist *file;
+{
+ int first, last, below;
+ register struct symtab *sp = NULL, *dest;
+
+ /* Make space if it's needed */
+ if (file->i_defs == NULL)
+ {
+ file->i_defs = (struct symtab *)
+ malloc(sizeof (struct symtab) * SYMTABINC);
+ file->i_deflen = SYMTABINC;
+ file->i_ndefs = 0;
+ }
+ else if (file->i_ndefs == file->i_deflen)
+ file->i_defs = (struct symtab *)
+ realloc(file->i_defs,
+ sizeof(struct symtab)*(file->i_deflen+=SYMTABINC));
+
+ if (file->i_defs == NULL)
+ fatalerr("malloc()/realloc() failure in insert_defn()\n");
+
+ below = first = 0;
+ last = file->i_ndefs - 1;
+ while (last >= first)
+ {
+ /* Fast inline binary search */
+ register char *s1;
+ register char *s2;
+ register int middle = (first + last) / 2;
+
+ /* Fast inline strchr() */
+ s1 = name;
+ s2 = file->i_defs[middle].s_name;
+ while (*s1++ == *s2++)
+ if (s2[-1] == '\0') break;
+
+ /* If exact match, set sp and break */
+ if (*--s1 == *--s2)
+ {
+ sp = file->i_defs + middle;
+ break;
+ }
+
+ /* If name > i_defs[middle] ... */
+ if (*s1 > *s2)
+ {
+ below = first;
+ first = middle + 1;
+ }
+ /* else ... */
+ else
+ {
+ below = last = middle - 1;
+ }
+ }
+
+ /* Search is done. If we found an exact match to the symbol name,
+ just replace its s_value */
+ if (sp != NULL)
+ {
+ free(sp->s_value);
+ sp->s_value = copy(val);
+ return;
+ }
+
+ sp = file->i_defs + file->i_ndefs++;
+ dest = file->i_defs + below + 1;
+ while (sp > dest)
+ {
+ *sp = sp[-1];
+ sp--;
+ }
+ sp->s_name = copy(name);
+ sp->s_value = copy(val);
+}
+
+struct symtab *slookup(symbol, file)
+ register char *symbol;
+ register struct inclist *file;
+{
+ register int first = 0;
+ register int last = file->i_ndefs - 1;
+
+ if (file) while (last >= first)
+ {
+ /* Fast inline binary search */
+ register char *s1;
+ register char *s2;
+ register int middle = (first + last) / 2;
+
+ /* Fast inline strchr() */
+ s1 = symbol;
+ s2 = file->i_defs[middle].s_name;
+ while (*s1++ == *s2++)
+ if (s2[-1] == '\0') break;
+
+ /* If exact match, we're done */
+ if (*--s1 == *--s2)
+ {
+ return file->i_defs + middle;
+ }
+
+ /* If symbol > i_defs[middle] ... */
+ if (*s1 > *s2)
+ {
+ first = middle + 1;
+ }
+ /* else ... */
+ else
+ {
+ last = middle - 1;
+ }
+ }
+ return(NULL);
+}
+
+undefine(symbol, file)
+ char *symbol;
+ register struct inclist *file;
+{
+ register struct symtab *ptr;
+ struct inclist *srcfile;
+ while ((ptr = isdefined(symbol, file, &srcfile)) != NULL)
+ {
+ srcfile->i_ndefs--;
+ for (; ptr < srcfile->i_defs + srcfile->i_ndefs; ptr++)
+ *ptr = ptr[1];
+ }
+}