summaryrefslogtreecommitdiffstats
path: root/soltools/mkdepend/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'soltools/mkdepend/parse.c')
-rw-r--r--soltools/mkdepend/parse.c402
1 files changed, 402 insertions, 0 deletions
diff --git a/soltools/mkdepend/parse.c b/soltools/mkdepend/parse.c
new file mode 100644
index 000000000..a5c8273a2
--- /dev/null
+++ b/soltools/mkdepend/parse.c
@@ -0,0 +1,402 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* $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 <ctype.h>
+
+#include "def.h"
+static char *hash_lookup( char *symbol, struct symhash *symbols );
+static int gobble( struct filepointer *filep, struct inclist *file,
+ struct inclist *file_red, struct symhash *symbols );
+static int deftype ( char *line, struct filepointer *filep, struct inclist *file,
+ int parse_it, struct symhash *symbols);
+static int zero_value(char const *exp, struct symhash *symbols);
+
+extern struct symhash *maininclist;
+
+int find_includes(struct filepointer *filep, struct inclist *file, struct inclist *file_red, int recursion, boolean failOK, struct IncludesCollection* incCollection, struct symhash *symbols)
+{
+ char *line;
+ int type;
+
+ while ((line = get_line(filep))) {
+ type = deftype(line, filep, file, TRUE, symbols);
+ switch(type) {
+ case IF:
+ doif:
+ type = find_includes(filep, file,
+ file_red, recursion+1, failOK, incCollection, symbols);
+ while ((type == ELIF) || (type == ELIFFALSE) ||
+ (type == ELIFGUESSFALSE))
+ type = gobble(filep, file, file_red, symbols);
+ break;
+ case IFFALSE:
+ doiffalse:
+ type = gobble(filep, file, file_red, symbols);
+ if (type == ELIF)
+ goto doif;
+ else if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE))
+ goto doiffalse;
+ break;
+ case ELIFFALSE:
+ case ELIFGUESSFALSE:
+ case ELIF:
+ if (!recursion)
+ gobble(filep, file, file_red, symbols);
+ if (recursion)
+ return type;
+ define(line, &symbols);
+ break;
+ case ERROR:
+ warning("%s: %d: %s\n", file_red->i_file,
+ filep->f_line, line);
+ 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;
+ }
+ }
+ // coverity[leaked_storage] - on purpose
+ return -1;
+}
+
+int gobble(struct filepointer *filep,
+ struct inclist *file,
+ struct inclist *file_red,
+ struct symhash *symbols)
+{
+ char *line;
+ int type;
+
+ while ((line = get_line(filep))) {
+ type = deftype(line, filep, file, FALSE, symbols);
+ switch(type) {
+ case IF:
+ case IFFALSE:
+ type = gobble(filep, file, file_red, symbols);
+ while ((type == ELIF) || (type == ELIFFALSE) ||
+ (type == ELIFGUESSFALSE))
+ type = gobble(filep, file, file_red, symbols);
+ break;
+ case ERROR:
+ 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 (char *line, struct filepointer *filep, struct inclist * file,
+ int parse_it, struct symhash *symbols)
+{
+ char *p;
+ char *directive, savechar;
+ int ret;
+ (void)file; // used in DEBUG mode
+ (void)filep;
+ /*
+ * 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, symbols);
+ 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, symbols);
+ debug(0,("%s, line %d: %s #if %s\n",
+ file->i_file, filep->f_line, ret?"false":"true", p));
+ break;
+ case ELIF:
+ case ERROR:
+ debug(0,("%s, line %d: #%s\n",
+ file->i_file, filep->f_line, directives[ret]));
+ /*
+ * nothing to do.
+ */
+ break;
+ }
+ return ret;
+}
+
+/*
+ * HACK! - so that we do not have to introduce 'symbols' in each cppsetup.c
+ * function... It's safe, functions from cppsetup.c don't return here.
+ */
+static struct symhash *global_symbols = NULL;
+
+char * isdefined( char *symbol )
+{
+ return hash_lookup( symbol, global_symbols );
+}
+
+/*
+ * Return type based on if the #if expression evaluates to 0
+ */
+int zero_value(char const *exp, struct symhash *symbols)
+{
+ global_symbols = symbols; /* HACK! see above */
+ if (cppsetup(exp))
+ return IFFALSE;
+ else
+ return IF;
+}
+
+void define( char *def, struct symhash **symbols )
+{
+ char *val;
+
+ /* Separate symbol name and its value */
+ val = def;
+ while (isalnum((unsigned char)*val) || *val == '_')
+ val++;
+ if (*val)
+ *val++ = '\0';
+ while (*val == ' ' || *val == '\t')
+ val++;
+
+ if (!*val)
+ val = "1";
+ hash_define( def, val, symbols );
+}
+
+static int hash( char *str )
+{
+ /* Hash (Kernighan and Ritchie) */
+ unsigned int hashval = 0;
+
+ for ( ; *str; str++ )
+ {
+ hashval = ( hashval * SYMHASHSEED ) + ( *str );
+ }
+
+ return hashval & ( SYMHASHMEMBERS - 1 );
+}
+
+struct symhash *hash_copy( struct symhash *symbols )
+{
+ int i;
+ struct symhash *newsym;
+ if ( !symbols )
+ return NULL;
+
+ newsym = (struct symhash *) malloc( sizeof( struct symhash ) );
+
+ for ( i = 0; i < SYMHASHMEMBERS; ++i )
+ {
+ if ( !symbols->s_pairs[ i ] )
+ newsym->s_pairs[ i ] = NULL;
+ else
+ {
+ struct pair *it = symbols->s_pairs[ i ];
+ struct pair *nw = newsym->s_pairs[ i ] = (struct pair*) malloc( sizeof( struct pair ) );
+ nw->p_name = it->p_name;
+ nw->p_value = it->p_value;
+ nw->p_next = NULL;
+
+ while ( it->p_next )
+ {
+ nw->p_next = (struct pair*) malloc( sizeof( struct pair ) );
+ it = it->p_next;
+ nw = nw->p_next;
+ nw->p_name = it->p_name;
+ nw->p_value = it->p_value;
+ nw->p_next = NULL;
+ }
+ }
+ }
+ return newsym;
+}
+
+void hash_free( struct symhash *symbols )
+{
+ int i;
+
+ if ( !symbols )
+ return;
+
+ for ( i = 0; i < SYMHASHMEMBERS; ++i )
+ {
+ struct pair *it = symbols->s_pairs[ i ];
+ struct pair *next;
+ while ( it )
+ {
+ next = it->p_next;
+ free( it );
+ it = next;
+ }
+ }
+ free( symbols->s_pairs );
+}
+
+void hash_define( char *name, char const *val, struct symhash **symbols )
+{
+ int hashval;
+ struct pair *it;
+
+ if ( !symbols )
+ return;
+
+ /* Make space if it's needed */
+ if ( *symbols == NULL )
+ {
+ int i;
+
+ *symbols = (struct symhash *) malloc( sizeof( struct symhash ) );
+ if ( *symbols == NULL )
+ fatalerr( "malloc()/realloc() failure in insert_defn()\n" );
+
+ for ( i = 0; i < SYMHASHMEMBERS; ++i )
+ (*symbols)->s_pairs[i] = NULL;
+ }
+
+ hashval = hash( name );
+ it = (*symbols)->s_pairs[ hashval ];
+
+ /* Replace/insert the symbol */
+ if ( it == NULL )
+ {
+ it = (*symbols)->s_pairs[ hashval ] = (struct pair*) malloc( sizeof( struct pair ) );
+ it->p_name = copy( name );
+ it->p_value = copy( val );
+ it->p_next = NULL;
+ }
+ else if ( strcmp( it->p_name, name ) == 0 )
+ {
+ it->p_value = copy( val );
+ }
+ else
+ {
+ while ( it->p_next && ( strcmp( it->p_next->p_name, name ) != 0 ) )
+ {
+ it = it->p_next;
+ }
+ if ( it->p_next )
+ it->p_next->p_name = copy( name );
+ else
+ {
+ it->p_next = (struct pair*) malloc( sizeof( struct pair ) );
+ it->p_next->p_name = copy( name );
+ it->p_next->p_value = copy( val );
+ it->p_next->p_next = NULL;
+ }
+ }
+}
+
+char *hash_lookup( char *symbol, struct symhash *symbols )
+{
+ struct pair *it;
+
+ if ( !symbols )
+ return NULL;
+
+ it = symbols->s_pairs[ hash( symbol ) ];
+
+ while ( it && ( strcmp( it->p_name, symbol ) != 0 ) )
+ {
+ it = it->p_next;
+ }
+ if ( it )
+ return it->p_value;
+
+ return NULL;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */