diff options
-rw-r--r-- | cppsetup.c | 244 | ||||
-rw-r--r-- | def.h | 147 | ||||
-rw-r--r-- | ifparser.c | 492 | ||||
-rw-r--r-- | ifparser.h | 82 | ||||
-rw-r--r-- | imakemdep.h | 815 | ||||
-rw-r--r-- | include.c | 319 | ||||
-rw-r--r-- | main.c | 746 | ||||
-rw-r--r-- | makedepend.man | 372 | ||||
-rw-r--r-- | parse.c | 653 | ||||
-rw-r--r-- | pr.c | 129 |
10 files changed, 3999 insertions, 0 deletions
diff --git a/cppsetup.c b/cppsetup.c new file mode 100644 index 0000000..b25d2ce --- /dev/null +++ b/cppsetup.c @@ -0,0 +1,244 @@ +/* $Xorg: cppsetup.c,v 1.5 2001/02/09 02:03:16 xorgcvs Exp $ */ +/* + +Copyright (c) 1993, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +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 +OPEN GROUP 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 Open Group 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 Open Group. + +*/ + +#include "def.h" + +#ifdef CPP +/* + * This file is strictly for the sake of cpy.y and yylex.c (if + * you indeed have the source for cpp). + */ +#define IB 1 +#define SB 2 +#define NB 4 +#define CB 8 +#define QB 16 +#define WB 32 +#define SALT '#' +#if pdp11 | vax | ns16000 | mc68000 | ibm032 +#define COFF 128 +#else +#define COFF 0 +#endif +/* + * These variables used by cpy.y and yylex.c + */ +extern char *outp, *inp, *newp, *pend; +extern char *ptrtab; +extern char fastab[]; +extern char slotab[]; + +/* + * cppsetup + */ +struct filepointer *currentfile; +struct inclist *currentinc; + +cppsetup(line, filep, inc) + register char *line; + register struct filepointer *filep; + register struct inclist *inc; +{ + register char *p, savec; + static boolean setupdone = FALSE; + boolean value; + + if (!setupdone) { + cpp_varsetup(); + setupdone = TRUE; + } + + currentfile = filep; + currentinc = inc; + inp = newp = line; + for (p=newp; *p; p++) + ; + + /* + * put a newline back on the end, and set up pend, etc. + */ + *p++ = '\n'; + savec = *p; + *p = '\0'; + pend = p; + + ptrtab = slotab+COFF; + *--inp = SALT; + outp=inp; + value = yyparse(); + *p = savec; + return(value); +} + +struct symtab **lookup(symbol) + char *symbol; +{ + static struct symtab *undefined; + struct symtab **sp; + + sp = isdefined(symbol, currentinc, NULL); + if (sp == NULL) { + sp = &undefined; + (*sp)->s_value = NULL; + } + return (sp); +} + +pperror(tag, x0,x1,x2,x3,x4) + int tag,x0,x1,x2,x3,x4; +{ + warning("\"%s\", line %d: ", currentinc->i_file, currentfile->f_line); + warning(x0,x1,x2,x3,x4); +} + + +yyerror(s) + register char *s; +{ + fatalerr("Fatal error: %s\n", s); +} +#else /* not CPP */ + +#include "ifparser.h" +struct _parse_data { + struct filepointer *filep; + struct inclist *inc; + char *filename; + const char *line; +}; + +static const char * +my_if_errors (ip, cp, expecting) + IfParser *ip; + const char *cp; + const char *expecting; +{ + struct _parse_data *pd = (struct _parse_data *) ip->data; + int lineno = pd->filep->f_line; + char *filename = pd->filename; + char prefix[300]; + int prefixlen; + int i; + + sprintf (prefix, "\"%s\":%d", filename, lineno); + prefixlen = strlen(prefix); + fprintf (stderr, "%s: %s", prefix, pd->line); + i = cp - pd->line; + if (i > 0 && pd->line[i-1] != '\n') { + putc ('\n', stderr); + } + for (i += prefixlen + 3; i > 0; i--) { + putc (' ', stderr); + } + fprintf (stderr, "^--- expecting %s\n", expecting); + return NULL; +} + + +#define MAXNAMELEN 256 + +static struct symtab ** +lookup_variable (ip, var, len) + IfParser *ip; + const char *var; + int len; +{ + char tmpbuf[MAXNAMELEN + 1]; + struct _parse_data *pd = (struct _parse_data *) ip->data; + + if (len > MAXNAMELEN) + return 0; + + strncpy (tmpbuf, var, len); + tmpbuf[len] = '\0'; + return isdefined (tmpbuf, pd->inc, NULL); +} + + +static int +my_eval_defined (ip, var, len) + IfParser *ip; + const char *var; + int len; +{ + if (lookup_variable (ip, var, len)) + return 1; + else + return 0; +} + +#define isvarfirstletter(ccc) (isalpha(ccc) || (ccc) == '_') + +static long +my_eval_variable (ip, var, len) + IfParser *ip; + const char *var; + int len; +{ + struct symtab **s; + + s = lookup_variable (ip, var, len); + if (!s) + return 0; + do { + var = (*s)->s_value; + if (!isvarfirstletter(*var)) + break; + s = lookup_variable (ip, var, strlen(var)); + } while (s); + + return strtol(var, NULL, 0); +} + + +cppsetup(filename, line, filep, inc) + register char *filename; + register char *line; + register struct filepointer *filep; + register struct inclist *inc; +{ + IfParser ip; + struct _parse_data pd; + long val = 0; + + pd.filep = filep; + pd.inc = inc; + pd.line = line; + pd.filename = filename; + ip.funcs.handle_error = my_if_errors; + ip.funcs.eval_defined = my_eval_defined; + ip.funcs.eval_variable = my_eval_variable; + ip.data = (char *) &pd; + + (void) ParseIfExpression (&ip, line, &val); + if (val) + return IF; + else + return IFFALSE; +} +#endif /* CPP */ + @@ -0,0 +1,147 @@ +/* $Xorg: def.h,v 1.4 2001/02/09 02:03:16 xorgcvs Exp $ */ +/* + +Copyright (c) 1993, 1994, 1998 The Open Group. + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +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 +OPEN GROUP 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 Open Group 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 Open Group. + +*/ + +#include "Xos.h" +#include "Xfuncproto.h" +#include <stdio.h> +#include <ctype.h> +#ifndef X_NOT_POSIX +#ifndef _POSIX_SOURCE +#define _POSIX_SOURCE +#endif +#endif +#include <sys/types.h> +#include <fcntl.h> +#include <sys/stat.h> + +#define MAXDEFINES 512 +#define MAXFILES 1024 +#define MAXDIRS 64 +#define SYMTABINC 10 /* must be > 1 for define() to work right */ +#define TRUE 1 +#define FALSE 0 + +/* the following must match the directives table in main.c */ +#define IF 0 +#define IFDEF 1 +#define IFNDEF 2 +#define ELSE 3 +#define ENDIF 4 +#define DEFINE 5 +#define UNDEF 6 +#define INCLUDE 7 +#define LINE 8 +#define PRAGMA 9 +#define ERROR 10 +#define IDENT 11 +#define SCCS 12 +#define ELIF 13 +#define EJECT 14 +#define WARNING 15 +#define IFFALSE 16 /* pseudo value --- never matched */ +#define ELIFFALSE 17 /* pseudo value --- never matched */ +#define INCLUDEDOT 18 /* pseudo value --- never matched */ +#define IFGUESSFALSE 19 /* pseudo value --- never matched */ +#define ELIFGUESSFALSE 20 /* pseudo value --- never matched */ + +#ifdef DEBUG +extern int _debugmask; +/* + * debug levels are: + * + * 0 show ifn*(def)*,endif + * 1 trace defined/!defined + * 2 show #include + * 3 show #include SYMBOL + * 4-6 unused + */ +#define debug(level,arg) { if (_debugmask & (1 << level)) warning arg; } +#else +#define debug(level,arg) /**/ +#endif /* DEBUG */ + +typedef unsigned char boolean; + +struct symtab { + char *s_name; + char *s_value; +}; + +/* possible i_flag */ +#define DEFCHECKED (1<<0) /* whether defines have been checked */ +#define NOTIFIED (1<<1) /* whether we have revealed includes */ +#define MARKED (1<<2) /* whether it's in the makefile */ +#define SEARCHED (1<<3) /* whether we have read this */ +#define FINISHED (1<<4) /* whether we are done reading this */ +#define INCLUDED_SYM (1<<5) /* whether #include SYMBOL was found + Can't use i_list if TRUE */ +struct inclist { + char *i_incstring; /* string from #include line */ + char *i_file; /* path name of the include file */ + struct inclist **i_list; /* list of files it itself includes */ + int i_listlen; /* length of i_list */ + struct symtab **i_defs; /* symbol table for this file and its + children when merged */ + int i_ndefs; /* current # defines */ + boolean *i_merged; /* whether we have merged child + defines */ + unsigned char i_flags; +}; + +struct filepointer { + char *f_p; + char *f_base; + char *f_end; + long f_len; + long f_line; +}; + +#ifndef X_NOT_STDC_ENV +#include <stdlib.h> +#if defined(macII) && !defined(__STDC__) /* stdlib.h fails to define these */ +char *malloc(), *realloc(); +#endif /* macII */ +#else +char *malloc(); +char *realloc(); +#endif + +char *copy(); +char *base_name(); +char *getline(); +struct symtab **slookup(); +struct symtab **isdefined(); +struct symtab **fdefined(); +struct filepointer *getfile(); +struct inclist *newinclude(); +struct inclist *inc_path(); + +#if NeedVarargsPrototypes +extern void fatalerr(char *, ...); +extern void warning(char *, ...); +extern void warning1(char *, ...); +#endif diff --git a/ifparser.c b/ifparser.c new file mode 100644 index 0000000..c91c236 --- /dev/null +++ b/ifparser.c @@ -0,0 +1,492 @@ +/* + * $Xorg: ifparser.c,v 1.3 2000/08/17 19:41:50 cpqbld Exp $ + * + * Copyright 1992 Network Computing Devices, Inc. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Network Computing Devices may not be + * used in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Network Computing Devices makes + * no representations about the suitability of this software for any purpose. + * It is provided ``as is'' without express or implied warranty. + * + * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, + * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Author: Jim Fulton + * Network Computing Devices, Inc. + * + * Simple if statement processor + * + * This module can be used to evaluate string representations of C language + * if constructs. It accepts the following grammar: + * + * EXPRESSION := VALUE + * | VALUE BINOP EXPRESSION + * + * VALUE := '(' EXPRESSION ')' + * | '!' VALUE + * | '-' VALUE + * | 'defined' '(' variable ')' + * | 'defined' variable + * | # variable '(' variable-list ')' + * | variable + * | number + * + * BINOP := '*' | '/' | '%' + * | '+' | '-' + * | '<<' | '>>' + * | '<' | '>' | '<=' | '>=' + * | '==' | '!=' + * | '&' | '|' + * | '&&' | '||' + * + * The normal C order of precidence is supported. + * + * + * External Entry Points: + * + * ParseIfExpression parse a string for #if + */ + +#include "ifparser.h" +#include <ctype.h> + +/**************************************************************************** + Internal Macros and Utilities for Parser + ****************************************************************************/ + +#define DO(val) if (!(val)) return NULL +#define CALLFUNC(ggg,fff) (*((ggg)->funcs.fff)) +#define SKIPSPACE(ccc) while (isspace(*ccc)) ccc++ +#define isvarfirstletter(ccc) (isalpha(ccc) || (ccc) == '_') + + +static const char * +parse_variable (g, cp, varp) + IfParser *g; + const char *cp; + const char **varp; +{ + SKIPSPACE (cp); + + if (!isvarfirstletter (*cp)) + return CALLFUNC(g, handle_error) (g, cp, "variable name"); + + *varp = cp; + /* EMPTY */ + for (cp++; isalnum(*cp) || *cp == '_'; cp++) ; + return cp; +} + + +static const char * +parse_number (g, cp, valp) + IfParser *g; + const char *cp; + long *valp; +{ + SKIPSPACE (cp); + + if (!isdigit(*cp)) + return CALLFUNC(g, handle_error) (g, cp, "number"); + + *valp = strtol(cp, &cp, 0); + /* skip trailing qualifiers */ + while (*cp == 'U' || *cp == 'u' || *cp == 'L' || *cp == 'l') cp++; +#if 0 + *valp = atoi (cp); + /* EMPTY */ + for (cp++; isdigit(*cp); cp++) ; +#endif + return cp; +} + +static const char * +parse_character (g, cp, valp) + IfParser *g; + const char *cp; + long *valp; +{ + char val; + + SKIPSPACE (cp); + if (*cp == '\\') + switch (cp[1]) { + case 'n': val = '\n'; break; + case 't': val = '\t'; break; + case 'v': val = '\v'; break; + case 'b': val = '\b'; break; + case 'r': val = '\r'; break; + case 'f': val = '\f'; break; + case 'a': val = '\a'; break; + case '\\': val = '\\'; break; + case '?': val = '\?'; break; + case '\'': val = '\''; break; + case '\"': val = '\"'; break; + case 'x': val = (char) strtol (cp + 2, NULL, 16); break; + default: val = (char) strtol (cp + 1, NULL, 8); break; + } + else + val = *cp; + while (*cp != '\'') cp++; + *valp = (long) val; + return cp; +} + +static const char * +parse_value (g, cp, valp) + IfParser *g; + const char *cp; + long *valp; +{ + const char *var; + + *valp = 0; + + SKIPSPACE (cp); + if (!*cp) + return cp; + + switch (*cp) { + case '(': + DO (cp = ParseIfExpression (g, cp + 1, valp)); + SKIPSPACE (cp); + if (*cp != ')') + return CALLFUNC(g, handle_error) (g, cp, ")"); + + return cp + 1; /* skip the right paren */ + + case '!': + DO (cp = parse_value (g, cp + 1, valp)); + *valp = !(*valp); + return cp; + + case '-': + DO (cp = parse_value (g, cp + 1, valp)); + *valp = -(*valp); + return cp; + + case '#': + DO (cp = parse_variable (g, cp + 1, &var)); + SKIPSPACE (cp); + if (*cp != '(') + return CALLFUNC(g, handle_error) (g, cp, "("); + do { + DO (cp = parse_variable (g, cp + 1, &var)); + SKIPSPACE (cp); + } while (*cp && *cp != ')'); + if (*cp != ')') + return CALLFUNC(g, handle_error) (g, cp, ")"); + *valp = 1; /* XXX */ + return cp + 1; + + case '\'': + DO (cp = parse_character (g, cp + 1, valp)); + if (*cp != '\'') + return CALLFUNC(g, handle_error) (g, cp, "'"); + return cp + 1; + + case 'd': + if (strncmp (cp, "defined", 7) == 0 && !isalnum(cp[7])) { + int paren = 0; + int len; + + cp += 7; + SKIPSPACE (cp); + if (*cp == '(') { + paren = 1; + cp++; + } + DO (cp = parse_variable (g, cp, &var)); + len = cp - var; + SKIPSPACE (cp); + if (paren && *cp != ')') + return CALLFUNC(g, handle_error) (g, cp, ")"); + *valp = (*(g->funcs.eval_defined)) (g, var, len); + return cp + paren; /* skip the right paren */ + } + /* fall out */ + } + + if (isdigit(*cp)) { + DO (cp = parse_number (g, cp, valp)); + } else if (!isvarfirstletter(*cp)) + return CALLFUNC(g, handle_error) (g, cp, "variable or number"); + else { + DO (cp = parse_variable (g, cp, &var)); + *valp = (*(g->funcs.eval_variable)) (g, var, cp - var); + } + + return cp; +} + + + +static const char * +parse_product (g, cp, valp) + IfParser *g; + const char *cp; + long *valp; +{ + long rightval; + + DO (cp = parse_value (g, cp, valp)); + SKIPSPACE (cp); + + switch (*cp) { + case '*': + DO (cp = parse_product (g, cp + 1, &rightval)); + *valp = (*valp * rightval); + break; + + case '/': + DO (cp = parse_product (g, cp + 1, &rightval)); + *valp = (*valp / rightval); + break; + + case '%': + DO (cp = parse_product (g, cp + 1, &rightval)); + *valp = (*valp % rightval); + break; + } + return cp; +} + + +static const char * +parse_sum (g, cp, valp) + IfParser *g; + const char *cp; + long *valp; +{ + long rightval; + + DO (cp = parse_product (g, cp, valp)); + SKIPSPACE (cp); + + switch (*cp) { + case '+': + DO (cp = parse_sum (g, cp + 1, &rightval)); + *valp = (*valp + rightval); + break; + + case '-': + DO (cp = parse_sum (g, cp + 1, &rightval)); + *valp = (*valp - rightval); + break; + } + return cp; +} + + +static const char * +parse_shift (g, cp, valp) + IfParser *g; + const char *cp; + long *valp; +{ + long rightval; + + DO (cp = parse_sum (g, cp, valp)); + SKIPSPACE (cp); + + switch (*cp) { + case '<': + if (cp[1] == '<') { + DO (cp = parse_shift (g, cp + 2, &rightval)); + *valp = (*valp << rightval); + } + break; + + case '>': + if (cp[1] == '>') { + DO (cp = parse_shift (g, cp + 2, &rightval)); + *valp = (*valp >> rightval); + } + break; + } + return cp; +} + + +static const char * +parse_inequality (g, cp, valp) + IfParser *g; + const char *cp; + long *valp; +{ + long rightval; + + DO (cp = parse_shift (g, cp, valp)); + SKIPSPACE (cp); + + switch (*cp) { + case '<': + if (cp[1] == '=') { + DO (cp = parse_inequality (g, cp + 2, &rightval)); + *valp = (*valp <= rightval); + } else { + DO (cp = parse_inequality (g, cp + 1, &rightval)); + *valp = (*valp < rightval); + } + break; + + case '>': + if (cp[1] == '=') { + DO (cp = parse_inequality (g, cp + 2, &rightval)); + *valp = (*valp >= rightval); + } else { + DO (cp = parse_inequality (g, cp + 1, &rightval)); + *valp = (*valp > rightval); + } + break; + } + return cp; +} + + +static const char * +parse_equality (g, cp, valp) + IfParser *g; + const char *cp; + long *valp; +{ + long rightval; + + DO (cp = parse_inequality (g, cp, valp)); + SKIPSPACE (cp); + + switch (*cp) { + case '=': + if (cp[1] == '=') + cp++; + DO (cp = parse_equality (g, cp + 1, &rightval)); + *valp = (*valp == rightval); + break; + + case '!': + if (cp[1] != '=') + break; + DO (cp = parse_equality (g, cp + 2, &rightval)); + *valp = (*valp != rightval); + break; + } + return cp; +} + + +static const char * +parse_band (g, cp, valp) + IfParser *g; + const char *cp; + long *valp; +{ + long rightval; + + DO (cp = parse_equality (g, cp, valp)); + SKIPSPACE (cp); + + switch (*cp) { + case '&': + if (cp[1] != '&') { + DO (cp = parse_band (g, cp + 1, &rightval)); + *valp = (*valp & rightval); + } + break; + } + return cp; +} + + +static const char * +parse_bor (g, cp, valp) + IfParser *g; + const char *cp; + long *valp; +{ + long rightval; + + DO (cp = parse_band (g, cp, valp)); + SKIPSPACE (cp); + + switch (*cp) { + case '|': + if (cp[1] != '|') { + DO (cp = parse_bor (g, cp + 1, &rightval)); + *valp = (*valp | rightval); + } + break; + } + return cp; +} + + +static const char * +parse_land (g, cp, valp) + IfParser *g; + const char *cp; + long *valp; +{ + long rightval; + + DO (cp = parse_bor (g, cp, valp)); + SKIPSPACE (cp); + + switch (*cp) { + case '&': + if (cp[1] != '&') + return CALLFUNC(g, handle_error) (g, cp, "&&"); + DO (cp = parse_land (g, cp + 2, &rightval)); + *valp = (*valp && rightval); + break; + } + return cp; +} + + +static const char * +parse_lor (g, cp, valp) + IfParser *g; + const char *cp; + long *valp; +{ + long rightval; + + DO (cp = parse_land (g, cp, valp)); + SKIPSPACE (cp); + + switch (*cp) { + case '|': + if (cp[1] != '|') + return CALLFUNC(g, handle_error) (g, cp, "||"); + DO (cp = parse_lor (g, cp + 2, &rightval)); + *valp = (*valp || rightval); + break; + } + return cp; +} + + +/**************************************************************************** + External Entry Points + ****************************************************************************/ + +const char * +ParseIfExpression (g, cp, valp) + IfParser *g; + const char *cp; + long *valp; +{ + return parse_lor (g, cp, valp); +} + + diff --git a/ifparser.h b/ifparser.h new file mode 100644 index 0000000..2b10266 --- /dev/null +++ b/ifparser.h @@ -0,0 +1,82 @@ +/* + * $Xorg: ifparser.h,v 1.3 2000/08/17 19:41:51 cpqbld Exp $ + * + * Copyright 1992 Network Computing Devices, Inc. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Network Computing Devices may not be + * used in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Network Computing Devices makes + * no representations about the suitability of this software for any purpose. + * It is provided ``as is'' without express or implied warranty. + * + * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, + * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Author: Jim Fulton + * Network Computing Devices, Inc. + * + * Simple if statement processor + * + * This module can be used to evaluate string representations of C language + * if constructs. It accepts the following grammar: + * + * EXPRESSION := VALUE + * | VALUE BINOP EXPRESSION + * + * VALUE := '(' EXPRESSION ')' + * | '!' VALUE + * | '-' VALUE + * | 'defined' '(' variable ')' + * | variable + * | number + * + * BINOP := '*' | '/' | '%' + * | '+' | '-' + * | '<<' | '>>' + * | '<' | '>' | '<=' | '>=' + * | '==' | '!=' + * | '&' | '|' + * | '&&' | '||' + * + * The normal C order of precidence is supported. + * + * + * External Entry Points: + * + * ParseIfExpression parse a string for #if + */ + +#include <stdio.h> + +#define const /**/ +typedef int Bool; +#define False 0 +#define True 1 + +typedef struct _if_parser { + struct { /* functions */ + char *(*handle_error) (/* struct _if_parser *, const char *, + const char * */); + long (*eval_variable) (/* struct _if_parser *, const char *, int */); + int (*eval_defined) (/* struct _if_parser *, const char *, int */); + } funcs; + char *data; +} IfParser; + +char *ParseIfExpression ( +#ifdef __STDC__ + IfParser *, + const char *, + long * +#endif +); + diff --git a/imakemdep.h b/imakemdep.h new file mode 100644 index 0000000..b6ebd42 --- /dev/null +++ b/imakemdep.h @@ -0,0 +1,815 @@ +/* $Xorg: imakemdep.h,v 1.6 2001/02/09 02:03:16 xorgcvs Exp $ */ +/* + +Copyright (c) 1993, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +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 +OPEN GROUP 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 Open Group 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 Open Group. + +*/ + + +/* + * This file contains machine-dependent constants for the imake utility. + * When porting imake, read each of the steps below and add in any necessary + * definitions. In general you should *not* edit ccimake.c or imake.c! + */ + +#ifdef CCIMAKE +/* + * Step 1: imake_ccflags + * Define any special flags that will be needed to get imake.c to compile. + * These will be passed to the compile along with the contents of the + * make variable BOOTSTRAPCFLAGS. + */ +#ifdef hpux +#ifdef hp9000s800 +#define imake_ccflags "-DSYSV" +#else +#define imake_ccflags "-Wc,-Nd4000,-Ns3000 -DSYSV" +#endif +#endif + +#if defined(macII) || defined(_AUX_SOURCE) +#define imake_ccflags "-DmacII -DSYSV" +#endif + +#ifdef stellar +#define imake_ccflags "-DSYSV" +#endif + +#if defined(USL) || defined(__USLC__) || defined(Oki) || defined(NCR) +#define imake_ccflags "-Xa -DSVR4" +#endif + +/* SCO may define __USLC__ so put this after the USL check */ +#if defined(M_UNIX) || defined(_SCO_DS) +#ifdef imake_ccflags +#undef imake_ccflags +#endif +#define imake_ccflags "-Dsco" +#endif + +#ifdef sony +#if defined(SYSTYPE_SYSV) || defined(_SYSTYPE_SYSV) +#define imake_ccflags "-DSVR4" +#else +#include <sys/param.h> +#if NEWSOS < 41 +#define imake_ccflags "-Dbsd43 -DNOSTDHDRS" +#else +#if NEWSOS < 42 +#define imake_ccflags "-Dbsd43" +#endif +#endif +#endif +#endif + +#ifdef _CRAY +#define imake_ccflags "-DSYSV -DUSG" +#endif + +#if defined(_IBMR2) || defined(aix) +#define imake_ccflags "-Daix -DSYSV" +#endif + +#ifdef Mips +# if defined(SYSTYPE_BSD) || defined(BSD) || defined(BSD43) +# define imake_ccflags "-DBSD43" +# else +# define imake_ccflags "-DSYSV" +# endif +#endif + +#ifdef is68k +#define imake_ccflags "-Dluna -Duniosb" +#endif + +#ifdef SYSV386 +# ifdef SVR4 +# define imake_ccflags "-Xa -DSVR4" +# else +# define imake_ccflags "-DSYSV" +# endif +#endif + +#ifdef SVR4 +# ifdef i386 +# define imake_ccflags "-Xa -DSVR4" +# endif +#endif + +#ifdef SYSV +# ifdef i386 +# define imake_ccflags "-DSYSV" +# endif +#endif + +#ifdef __convex__ +#define imake_ccflags "-fn -tm c1" +#endif + +#ifdef apollo +#define imake_ccflags "-DX_NOT_POSIX" +#endif + +#ifdef WIN32 +#if _MSC_VER < 1000 +#define imake_ccflags "-nologo -batch -D__STDC__" +#else +#define imake_ccflags "-nologo -D__STDC__" +#endif +#endif + +#ifdef __uxp__ +#define imake_ccflags "-DSVR4 -DANSICPP" +#endif + +#ifdef __sxg__ +#define imake_ccflags "-DSYSV -DUSG -DNOSTDHDRS" +#endif + +#ifdef _SEQUENT_ +#define imake_ccflags "-Xa -DSVR4" +#endif + +#if defined(SX) || defined(PC_UX) +#define imake_ccflags "-DSYSV" +#endif + +#ifdef nec_ews_svr2 +#define imake_ccflags "-DUSG" +#endif + +#if defined(nec_ews_svr4) || defined(_nec_ews_svr4) || defined(_nec_up) || defined(_nec_ft) +#define imake_ccflags "-DSVR4" +#endif + +#ifdef MACH +#define imake_ccflags "-DNOSTDHDRS" +#endif + +/* this is for OS/2 under EMX. This won't work with DOS */ +#if defined(__EMX__) +#define imake_ccflags "-DBSD43" +#endif + +#else /* not CCIMAKE */ +#ifndef MAKEDEPEND +/* + * Step 2: dup2 + * If your OS doesn't have a dup2() system call to duplicate one file + * descriptor onto another, define such a mechanism here (if you don't + * already fall under the existing category(ies). + */ +#if defined(SYSV) && !defined(_CRAY) && !defined(Mips) && !defined(_SEQUENT_) && !defined(sco) +#define dup2(fd1,fd2) ((fd1 == fd2) ? fd1 : (close(fd2), \ + fcntl(fd1, F_DUPFD, fd2))) +#endif + + +/* + * Step 3: FIXUP_CPP_WHITESPACE + * If your cpp collapses tabs macro expansions into a single space and + * replaces escaped newlines with a space, define this symbol. This will + * cause imake to attempt to patch up the generated Makefile by looking + * for lines that have colons in them (this is why the rules file escapes + * all colons). One way to tell if you need this is to see whether or not + * your Makefiles have no tabs in them and lots of @@ strings. + */ +#if defined(sun) || defined(SYSV) || defined(SVR4) || defined(hcx) || defined(WIN32) || defined(sco) || (defined(AMOEBA) && defined(CROSS_COMPILE)) +#define FIXUP_CPP_WHITESPACE +#endif +#ifdef WIN32 +#define REMOVE_CPP_LEADSPACE +#define INLINE_SYNTAX +#define MAGIC_MAKE_VARS +#endif + +/* + * Step 4: USE_CC_E, DEFAULT_CC, DEFAULT_CPP + * If you want to use cc -E instead of cpp, define USE_CC_E. + * If use cc -E but want a different compiler, define DEFAULT_CC. + * If the cpp you need is not in /lib/cpp, define DEFAULT_CPP. + */ +#ifdef hpux +#define USE_CC_E +#endif +#ifdef WIN32 +#define USE_CC_E +#define DEFAULT_CC "cl" +#endif +#ifdef apollo +#define DEFAULT_CPP "/usr/lib/cpp" +#endif +#if defined(_IBMR2) && !defined(DEFAULT_CPP) +#define DEFAULT_CPP "/usr/ccs/lib/cpp" +#endif +#if defined(sun) && (defined(SVR4) || defined(__svr4__) || defined(__SVR4) || defined(__sol__)) +#define DEFAULT_CPP "/usr/ccs/lib/cpp" +#endif +#ifdef __bsdi__ +#define DEFAULT_CPP "/usr/bin/cpp" +#endif +#ifdef __uxp__ +#define DEFAULT_CPP "/usr/ccs/lib/cpp" +#endif +#ifdef __sxg__ +#define DEFAULT_CPP "/usr/lib/cpp" +#endif +#ifdef _CRAY +#define DEFAULT_CPP "/lib/pcpp" +#endif +#if defined(__386BSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) +#define DEFAULT_CPP "/usr/libexec/cpp" +#endif +#if defined(__sgi) && defined(__ANSI_CPP__) +#define USE_CC_E +#endif +#ifdef MACH +#define USE_CC_E +#endif +#ifdef __minix_vmd +#define DEFAULT_CPP "/usr/lib/cpp" +#endif +#if defined(__EMX__) +/* expects cpp in PATH */ +#define DEFAULT_CPP "cpp" +#endif + +/* + * Step 5: cpp_argv + * The following table contains the flags that should be passed + * whenever a Makefile is being generated. If your preprocessor + * doesn't predefine any unique symbols, choose one and add it to the + * end of this table. Then, do the following: + * + * a. Use this symbol in Imake.tmpl when setting MacroFile. + * b. Put this symbol in the definition of BootstrapCFlags in your + * <platform>.cf file. + * c. When doing a make World, always add "BOOTSTRAPCFLAGS=-Dsymbol" + * to the end of the command line. + * + * Note that you may define more than one symbol (useful for platforms + * that support multiple operating systems). + */ + +#define ARGUMENTS 50 /* number of arguments in various arrays */ +char *cpp_argv[ARGUMENTS] = { + "cc", /* replaced by the actual program to exec */ + "-I.", /* add current directory to include path */ +#ifdef unix + "-Uunix", /* remove unix symbol so that filename unix.c okay */ +#endif +#if defined(__386BSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(MACH) +# ifdef __i386__ + "-D__i386__", +# endif +# ifdef __GNUC__ + "-traditional", +# endif +#endif +#ifdef M4330 + "-DM4330", /* Tektronix */ +#endif +#ifdef M4310 + "-DM4310", /* Tektronix */ +#endif +#if defined(macII) || defined(_AUX_SOURCE) + "-DmacII", /* Apple A/UX */ +#endif +#if defined(USL) || defined(__USLC__) + "-DUSL", /* USL */ +#endif +#ifdef sony + "-Dsony", /* Sony */ +#if !defined(SYSTYPE_SYSV) && !defined(_SYSTYPE_SYSV) && NEWSOS < 42 + "-Dbsd43", +#endif +#endif +#ifdef _IBMR2 + "-D_IBMR2", /* IBM RS-6000 (we ensured that aix is defined above */ +#ifndef aix +#define aix /* allow BOOTSTRAPCFLAGS="-D_IBMR2" */ +#endif +#endif /* _IBMR2 */ +#ifdef aix + "-Daix", /* AIX instead of AOS */ +#ifndef ibm +#define ibm /* allow BOOTSTRAPCFLAGS="-Daix" */ +#endif +#endif /* aix */ +#ifdef ibm + "-Dibm", /* IBM PS/2 and RT under both AOS and AIX */ +#endif +#ifdef luna + "-Dluna", /* OMRON luna 68K and 88K */ +#ifdef luna1 + "-Dluna1", +#endif +#ifdef luna88k /* need not on UniOS-Mach Vers. 1.13 */ + "-traditional", /* for some older version */ +#endif /* instead of "-DXCOMM=\\#" */ +#ifdef uniosb + "-Duniosb", +#endif +#ifdef uniosu + "-Duniosu", +#endif +#endif /* luna */ +#ifdef _CRAY /* Cray */ + "-Ucray", +#endif +#ifdef Mips + "-DMips", /* Define and use Mips for Mips Co. OS/mach. */ +# if defined(SYSTYPE_BSD) || defined(BSD) || defined(BSD43) + "-DBSD43", /* Mips RISCOS supports two environments */ +# else + "-DSYSV", /* System V environment is the default */ +# endif +#endif /* Mips */ +#ifdef MOTOROLA + "-DMOTOROLA", /* Motorola Delta Systems */ +# ifdef SYSV + "-DSYSV", +# endif +# ifdef SVR4 + "-DSVR4", +# endif +#endif /* MOTOROLA */ +#if defined(M_UNIX) || defined(sco) + "-Dsco", +# if defined(sco324) + "-Dsco324", +# endif +#endif +#ifdef i386 + "-Di386", +# ifdef SVR4 + "-DSVR4", +# endif +# ifdef SYSV + "-DSYSV", +# ifdef ISC + "-DISC", +# ifdef ISC40 + "-DISC40", /* ISC 4.0 */ +# else +# ifdef ISC202 + "-DISC202", /* ISC 2.0.2 */ +# else +# ifdef ISC30 + "-DISC30", /* ISC 3.0 */ +# else + "-DISC22", /* ISC 2.2.1 */ +# endif +# endif +# endif +# endif +# ifdef SCO + "-DSCO", +# ifdef SCO324 + "-DSCO324", +# endif +# endif +# ifdef ESIX + "-DESIX", +# endif +# ifdef ATT + "-DATT", +# endif +# ifdef DELL + "-DDELL", +# endif +# endif +#endif +#ifdef SYSV386 /* System V/386 folks, obsolete */ + "-Di386", +# ifdef SVR4 + "-DSVR4", +# endif +# ifdef SYSV + "-DSYSV", +# ifdef ISC + "-DISC", +# ifdef ISC40 + "-DISC40", /* ISC 4.0 */ +# else +# ifdef ISC202 + "-DISC202", /* ISC 2.0.2 */ +# else +# ifdef ISC30 + "-DISC30", /* ISC 3.0 */ +# else + "-DISC22", /* ISC 2.2.1 */ +# endif +# endif +# endif +# endif +# ifdef SCO + "-DSCO", +# ifdef SCO324 + "-DSCO324", +# endif +# endif +# ifdef ESIX + "-DESIX", +# endif +# ifdef ATT + "-DATT", +# endif +# ifdef DELL + "-DDELL", +# endif +# endif +#endif +#ifdef __osf__ + "-D__osf__", +# ifdef __mips__ + "-D__mips__", +# endif +# ifdef __alpha + "-D__alpha", +# endif +# ifdef __i386__ + "-D__i386__", +# endif +# ifdef __GNUC__ + "-traditional", +# endif +#endif +#ifdef Oki + "-DOki", +#endif +#ifdef sun +#if defined(SVR4) || defined(__svr4__) || defined(__SVR4) || defined(__sol__) + "-DSVR4", +#endif +#endif +#ifdef WIN32 + "-DWIN32", + "-nologo", +#if _MSC_VER < 1000 + "-batch", +#endif + "-D__STDC__", +#endif +#ifdef NCR + "-DNCR", /* NCR */ +#endif +#ifdef linux + "-traditional", + "-Dlinux", +#endif +#ifdef __uxp__ + "-D__uxp__", +#endif +#ifdef __sxg__ + "-D__sxg__", +#endif +#ifdef nec_ews_svr2 + "-Dnec_ews_svr2", +#endif +#ifdef AMOEBA + "-DAMOEBA", +# ifdef CROSS_COMPILE + "-DCROSS_COMPILE", +# ifdef CROSS_i80386 + "-DCROSS_i80386", +# endif +# ifdef CROSS_sparc + "-DCROSS_sparc", +# endif +# ifdef CROSS_mc68000 + "-DCROSS_mc68000", +# endif +# else +# ifdef i80386 + "-Di80386", +# endif +# ifdef sparc + "-Dsparc", +# endif +# ifdef mc68000 + "-Dmc68000", +# endif +# endif +#endif +#if defined(__sgi) && defined(__ANSI_CPP__) + "-cckr", +#endif +#ifdef __minix_vmd + "-Dminix", +#endif + +#if defined(__EMX__) + "-traditional", + "-Demxos2", +#endif + +}; + + +/* + * Step 6: DEFAULT_OS_MAJOR_REV, DEFAULT_OS_MINOR_REV, DEFAULT_OS_TEENY_REV, + * and DEFAULT_OS_NAME. + * If your systems provides a way to generate the default major, + * minor, teeny, or system names at runtime add commands below. + * The syntax of the _REV strings is 'f fmt' where 'f' is an argument + * you would give to uname, and "fmt" is a scanf() format string. + * Supported uname arguments are "snrvm", and if you specify multiple + * arguments they will be separated by spaces. No more than 5 arguments + * may be given. Unlike uname() order of arguments matters. + */ +#if defined(aix) +/* uname -v returns "x" (e.g. "4"), and uname -r returns "y" (e.g. "1") */ +# define DEFAULT_OS_MAJOR_REV "v %[0-9]" +# define DEFAULT_OS_MINOR_REV "r %[0-9]" +/* No information available to generate default OSTeenyVersion value. */ +# define DEFAULT_OS_NAME "srvm %[^\n]" +#elif defined(sun) || defined(sgi) || defined(ultrix) || defined(__uxp__) || defined(linux) || defined(sony) +/* uname -r returns "x.y[.z]", e.g. "5.4" or "4.1.3" */ +# define DEFAULT_OS_MAJOR_REV "r %[0-9]" +# define DEFAULT_OS_MINOR_REV "r %*d.%[0-9]" +# define DEFAULT_OS_TEENY_REV "r %*d.%*d.%[0-9]" +# define DEFAULT_OS_NAME "srvm %[^\n]" +#elif defined(hpux) +/* uname -r returns "W.x.yz", e.g. "B.10.01" */ +# define DEFAULT_OS_MAJOR_REV "r %*[^.].%[0-9]" +# define DEFAULT_OS_MINOR_REV "r %*[^.].%*d.%1s" +# define DEFAULT_OS_TEENY_REV "r %*[^.].%*d.%*c%[0-9]" +# define DEFAULT_OS_NAME "srvm %[^\n]" +#elif defined(USL) || defined(__USLC__) +/* uname -v returns "x.yz" or "x.y.z", e.g. "2.02" or "2.1.2". */ +# define DEFAULT_OS_MAJOR_REV "v %[0-9]" +# define DEFAULT_OS_MINOR_REV "v %*d.%1s" +# define DEFAULT_OS_TEENY_REV "v %*d.%*c%[.0-9]" +# define DEFAULT_OS_NAME "srvm %[^\n]" +#elif defined(__osf__) +/* uname -r returns "Wx.y", e.g. "V3.2" or "T4.0" */ +# define DEFAULT_OS_MAJOR_REV "r %*[^0-9]%[0-9]" +# define DEFAULT_OS_MINOR_REV "r %*[^.].%[0-9]" +# define DEFAULT_OS_NAME "srvm %[^\n]" +#elif defined(__uxp__) +/* NOTE: "x.y[.z]" above handles UXP/DF. This is a sample alternative. */ +/* uname -v returns "VxLy Yzzzzz ....", e.g. "V20L10 Y95021 Increment 5 ..." */ +# define DEFAULT_OS_MAJOR_REV "v V%[0-9]" +# define DEFAULT_OS_MINOR_REV "v V%*dL%[0-9]" +# define DEFAULT_OS_NAME "srvm %[^\n]" +#elif defined(__FreeBSD__) +/* NetBSD, OpenBSD, 386BSD, and BSD/OS too? */ +/* uname -r returns "x.y[.z]-mumble", e.g. "2.1.5-RELEASE" or "2.2-0801SNAP" */ +# define DEFAULT_OS_MAJOR_REV "r %[0-9]" +# define DEFAULT_OS_MINOR_REV "r %*d.%[0-9]" +# define DEFAULT_OS_TEENY_REV "r %*d.%*d.%[0-9]" +# define DEFAULT_OS_NAME "srm %[^\n]" +#elif defined(_SEQUENT_) +/* uname -v returns 'Vx.y.z', e.g. 'V4.4.2' */ +# define DEFAULT_OS_MAJOR_REV "v V%[0-9]" +# define DEFAULT_OS_MINOR_REV "v V%*d.%[0-9]" +# define DEFAULT_OS_TEENY_REV "v V%*d.%*d.%[0-9]" +# define DEFAULT_OS_NAME "s %[^\n]" +#endif + +#else /* else MAKEDEPEND */ +/* + * Step 7: predefs + * If your compiler and/or preprocessor define any specific symbols, add + * them to the the following table. The definition of struct symtab is + * in util/makedepend/def.h. + */ +struct symtab predefs[] = { +#ifdef apollo + {"apollo", "1"}, +#endif +#ifdef ibm032 + {"ibm032", "1"}, +#endif +#ifdef ibm + {"ibm", "1"}, +#endif +#ifdef aix + {"aix", "1"}, +#endif +#ifdef sun + {"sun", "1"}, +#endif +#ifdef sun2 + {"sun2", "1"}, +#endif +#ifdef sun3 + {"sun3", "1"}, +#endif +#ifdef sun4 + {"sun4", "1"}, +#endif +#ifdef sparc + {"sparc", "1"}, +#endif +#ifdef __sparc__ + {"__sparc__", "1"}, +#endif +#ifdef hpux + {"hpux", "1"}, +#endif +#ifdef __hpux + {"__hpux", "1"}, +#endif +#ifdef __hp9000s800 + {"__hp9000s800", "1"}, +#endif +#ifdef __hp9000s700 + {"__hp9000s700", "1"}, +#endif +#ifdef vax + {"vax", "1"}, +#endif +#ifdef VMS + {"VMS", "1"}, +#endif +#ifdef cray + {"cray", "1"}, +#endif +#ifdef CRAY + {"CRAY", "1"}, +#endif +#ifdef _CRAY + {"_CRAY", "1"}, +#endif +#ifdef att + {"att", "1"}, +#endif +#ifdef mips + {"mips", "1"}, +#endif +#ifdef __mips__ + {"__mips__", "1"}, +#endif +#ifdef ultrix + {"ultrix", "1"}, +#endif +#ifdef stellar + {"stellar", "1"}, +#endif +#ifdef mc68000 + {"mc68000", "1"}, +#endif +#ifdef mc68020 + {"mc68020", "1"}, +#endif +#ifdef __GNUC__ + {"__GNUC__", "1"}, +#endif +#if __STDC__ + {"__STDC__", "1"}, +#endif +#ifdef __HIGHC__ + {"__HIGHC__", "1"}, +#endif +#ifdef CMU + {"CMU", "1"}, +#endif +#ifdef luna + {"luna", "1"}, +#ifdef luna1 + {"luna1", "1"}, +#endif +#ifdef luna2 + {"luna2", "1"}, +#endif +#ifdef luna88k + {"luna88k", "1"}, +#endif +#ifdef uniosb + {"uniosb", "1"}, +#endif +#ifdef uniosu + {"uniosu", "1"}, +#endif +#endif +#ifdef ieeep754 + {"ieeep754", "1"}, +#endif +#ifdef is68k + {"is68k", "1"}, +#endif +#ifdef m68k + {"m68k", "1"}, +#endif +#ifdef m88k + {"m88k", "1"}, +#endif +#ifdef __m88k__ + {"__m88k__", "1"}, +#endif +#ifdef bsd43 + {"bsd43", "1"}, +#endif +#ifdef hcx + {"hcx", "1"}, +#endif +#ifdef sony + {"sony", "1"}, +#ifdef SYSTYPE_SYSV + {"SYSTYPE_SYSV", "1"}, +#endif +#ifdef _SYSTYPE_SYSV + {"_SYSTYPE_SYSV", "1"}, +#endif +#endif +#ifdef __OSF__ + {"__OSF__", "1"}, +#endif +#ifdef __osf__ + {"__osf__", "1"}, +#endif +#ifdef __alpha + {"__alpha", "1"}, +#endif +#ifdef __DECC + {"__DECC", "1"}, +#endif +#ifdef __decc + {"__decc", "1"}, +#endif +#ifdef __unix__ + {"__unix__", "1"}, +#endif +#ifdef __uxp__ + {"__uxp__", "1"}, +#endif +#ifdef __sxg__ + {"__sxg__", "1"}, +#endif +#ifdef _SEQUENT_ + {"_SEQUENT_", "1"}, + {"__STDC__", "1"}, +#endif +#ifdef __bsdi__ + {"__bsdi__", "1"}, +#endif +#ifdef nec_ews_svr2 + {"nec_ews_svr2", "1"}, +#endif +#ifdef nec_ews_svr4 + {"nec_ews_svr4", "1"}, +#endif +#ifdef _nec_ews_svr4 + {"_nec_ews_svr4", "1"}, +#endif +#ifdef _nec_up + {"_nec_up", "1"}, +#endif +#ifdef SX + {"SX", "1"}, +#endif +#ifdef nec + {"nec", "1"}, +#endif +#ifdef _nec_ft + {"_nec_ft", "1"}, +#endif +#ifdef PC_UX + {"PC_UX", "1"}, +#endif +#ifdef sgi + {"sgi", "1"}, +#endif +#ifdef __sgi + {"__sgi", "1"}, +#endif +#ifdef __FreeBSD__ + {"__FreeBSD__", "1"}, +#endif +#ifdef __OpenBSD__ + {"__OpenBSD__", "1"}, +#endif +#ifdef __NetBSD__ + {"__NetBSD__", "1"}, +#endif +#ifdef __EMX__ + {"__EMX__", "1"}, +#endif + /* add any additional symbols before this line */ + {NULL, NULL} +}; + +#endif /* MAKEDEPEND */ +#endif /* CCIMAKE */ diff --git a/include.c b/include.c new file mode 100644 index 0000000..4b74341 --- /dev/null +++ b/include.c @@ -0,0 +1,319 @@ +/* $Xorg: include.c,v 1.4 2001/02/09 02:03:16 xorgcvs Exp $ */ +/* + +Copyright (c) 1993, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +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 +OPEN GROUP 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 Open Group 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 Open Group. + +*/ + + +#include "def.h" + +extern struct inclist inclist[ MAXFILES ], + *inclistp; +extern char *includedirs[ ]; +extern char *notdotdot[ ]; +extern boolean show_where_not; +extern boolean warn_multiple; + +boolean +isdot(p) + register char *p; +{ + if(p && *p++ == '.' && *p++ == '\0') + return(TRUE); + return(FALSE); +} + +boolean +isdotdot(p) + register char *p; +{ + if(p && *p++ == '.' && *p++ == '.' && *p++ == '\0') + return(TRUE); + return(FALSE); +} + +boolean +issymbolic(dir, component) + register char *dir, *component; +{ +#ifdef S_IFLNK + struct stat st; + char buf[ BUFSIZ ], **pp; + + sprintf(buf, "%s%s%s", dir, *dir ? "/" : "", component); + for (pp=notdotdot; *pp; pp++) + if (strcmp(*pp, buf) == 0) + return (TRUE); + if (lstat(buf, &st) == 0 + && (st.st_mode & S_IFMT) == S_IFLNK) { + *pp++ = copy(buf); + if (pp >= ¬dotdot[ MAXDIRS ]) + fatalerr("out of .. dirs, increase MAXDIRS\n"); + return(TRUE); + } +#endif + return(FALSE); +} + +/* + * Occasionally, pathnames are created that look like .../x/../y + * Any of the 'x/..' sequences within the name can be eliminated. + * (but only if 'x' is not a symbolic link!!) + */ +void +remove_dotdot(path) + char *path; +{ + register char *end, *from, *to, **cp; + char *components[ MAXFILES ], + newpath[ BUFSIZ ]; + boolean component_copied; + + /* + * slice path up into components. + */ + to = newpath; + if (*path == '/') + *to++ = '/'; + *to = '\0'; + cp = components; + for (from=end=path; *end; end++) + if (*end == '/') { + while (*end == '/') + *end++ = '\0'; + if (*from) + *cp++ = from; + from = end; + } + *cp++ = from; + *cp = NULL; + + /* + * Recursively remove all 'x/..' component pairs. + */ + cp = components; + while(*cp) { + if (!isdot(*cp) && !isdotdot(*cp) && isdotdot(*(cp+1)) + && !issymbolic(newpath, *cp)) + { + char **fp = cp + 2; + char **tp = cp; + + do + *tp++ = *fp; /* move all the pointers down */ + while (*fp++); + if (cp != components) + cp--; /* go back and check for nested ".." */ + } else { + cp++; + } + } + /* + * Concatenate the remaining path elements. + */ + cp = components; + component_copied = FALSE; + while(*cp) { + if (component_copied) + *to++ = '/'; + component_copied = TRUE; + for (from = *cp; *from; ) + *to++ = *from++; + *to = '\0'; + cp++; + } + *to++ = '\0'; + + /* + * copy the reconstituted path back to our pointer. + */ + strcpy(path, newpath); +} + +/* + * Add an include file to the list of those included by 'file'. + */ +struct inclist *newinclude(newfile, incstring) + register char *newfile, *incstring; +{ + register struct inclist *ip; + + /* + * First, put this file on the global list of include files. + */ + ip = inclistp++; + if (inclistp == inclist + MAXFILES - 1) + fatalerr("out of space: increase MAXFILES\n"); + ip->i_file = copy(newfile); + + if (incstring == NULL) + ip->i_incstring = ip->i_file; + else + ip->i_incstring = copy(incstring); + + return(ip); +} + +void +included_by(ip, newfile) + register struct inclist *ip, *newfile; +{ + register int i; + + if (ip == NULL) + return; + /* + * Put this include file (newfile) on the list of files included + * by 'file'. If 'file' is NULL, then it is not an include + * file itself (i.e. was probably mentioned on the command line). + * If it is already on the list, don't stick it on again. + */ + if (ip->i_list == NULL) { + ip->i_list = (struct inclist **) + malloc(sizeof(struct inclist *) * ++ip->i_listlen); + ip->i_merged = (boolean *) + malloc(sizeof(boolean) * ip->i_listlen); + } else { + for (i=0; i<ip->i_listlen; i++) + if (ip->i_list[ i ] == newfile) { + i = strlen(newfile->i_file); + if (!(ip->i_flags & INCLUDED_SYM) && + !(i > 2 && + newfile->i_file[i-1] == 'c' && + newfile->i_file[i-2] == '.')) + { + /* only bitch if ip has */ + /* no #include SYMBOL lines */ + /* and is not a .c file */ + if (warn_multiple) + { + warning("%s includes %s more than once!\n", + ip->i_file, newfile->i_file); + warning1("Already have\n"); + for (i=0; i<ip->i_listlen; i++) + warning1("\t%s\n", ip->i_list[i]->i_file); + } + } + return; + } + ip->i_list = (struct inclist **) realloc(ip->i_list, + sizeof(struct inclist *) * ++ip->i_listlen); + ip->i_merged = (boolean *) + realloc(ip->i_merged, sizeof(boolean) * ip->i_listlen); + } + ip->i_list[ ip->i_listlen-1 ] = newfile; + ip->i_merged[ ip->i_listlen-1 ] = FALSE; +} + +void +inc_clean () +{ + register struct inclist *ip; + + for (ip = inclist; ip < inclistp; ip++) { + ip->i_flags &= ~MARKED; + } +} + +struct inclist *inc_path(file, include, dot) + register char *file, + *include; + boolean dot; +{ + static char path[ BUFSIZ ]; + register char **pp, *p; + register struct inclist *ip; + struct stat st; + boolean found = FALSE; + + /* + * Check all previously found include files for a path that + * has already been expanded. + */ + for (ip = inclist; ip->i_file; ip++) + if ((strcmp(ip->i_incstring, include) == 0) && + !(ip->i_flags & INCLUDED_SYM)) + { + found = TRUE; + break; + } + + /* + * If the path was surrounded by "" or is an absolute path, + * then check the exact path provided. + */ + if (!found && (dot || *include == '/')) { + if (stat(include, &st) == 0) { + ip = newinclude(include, include); + found = TRUE; + } + else if (show_where_not) + warning1("\tnot in %s\n", include); + } + + /* + * If the path was surrounded by "" see if this include file is in the + * directory of the file being parsed. + */ + if (!found && dot) { + for (p=file+strlen(file); p>file; p--) + if (*p == '/') + break; + if (p == file) + strcpy(path, include); + else { + strncpy(path, file, (p-file) + 1); + path[ (p-file) + 1 ] = '\0'; + strcpy(path + (p-file) + 1, include); + } + remove_dotdot(path); + if (stat(path, &st) == 0) { + ip = newinclude(path, include); + found = TRUE; + } + else if (show_where_not) + warning1("\tnot in %s\n", path); + } + + /* + * Check the include directories specified. (standard include dir + * should be at the end.) + */ + if (!found) + for (pp = includedirs; *pp; pp++) { + sprintf(path, "%s/%s", *pp, include); + remove_dotdot(path); + if (stat(path, &st) == 0) { + ip = newinclude(path, include); + found = TRUE; + break; + } + else if (show_where_not) + warning1("\tnot in %s\n", path); + } + + if (!found) + ip = NULL; + return(ip); +} @@ -0,0 +1,746 @@ +/* $Xorg: main.c,v 1.5 2001/02/09 02:03:16 xorgcvs Exp $ */ +/* + +Copyright (c) 1993, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +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 +THE OPEN GROUP 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 Open Group 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 Open Group. + +*/ + +#include "def.h" +#ifdef hpux +#define sigvec sigvector +#endif /* hpux */ + +#ifdef X_POSIX_C_SOURCE +#define _POSIX_C_SOURCE X_POSIX_C_SOURCE +#include <signal.h> +#undef _POSIX_C_SOURCE +#else +#if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE) +#include <signal.h> +#else +#define _POSIX_SOURCE +#include <signal.h> +#undef _POSIX_SOURCE +#endif +#endif + +#if NeedVarargsPrototypes +#include <stdarg.h> +#endif + +#ifdef DEBUG +int _debugmask; +#endif + +char *ProgramName; + +char *directives[] = { + "if", + "ifdef", + "ifndef", + "else", + "endif", + "define", + "undef", + "include", + "line", + "pragma", + "error", + "ident", + "sccs", + "elif", + "eject", + "warning", + NULL +}; + +#define MAKEDEPEND +#include "imakemdep.h" /* from config sources */ +#undef MAKEDEPEND + +struct inclist inclist[ MAXFILES ], + *inclistp = inclist, + maininclist; + +char *filelist[ MAXFILES ]; +char *includedirs[ MAXDIRS + 1 ]; +char *notdotdot[ MAXDIRS ]; +char *objprefix = ""; +char *objsuffix = OBJSUFFIX; +char *startat = "# DO NOT DELETE"; +int width = 78; +boolean append = FALSE; +boolean printed = FALSE; +boolean verbose = FALSE; +boolean show_where_not = FALSE; +boolean warn_multiple = FALSE; /* Warn on multiple includes of same file */ + +void freefile(); +void redirect(); +#if !NeedVarargsPrototypes +void fatalerr(); +void warning(); +void warning1(); +#endif + +static +#ifdef SIGNALRETURNSINT +int +#else +void +#endif +catch (sig) + int sig; +{ + fflush (stdout); + fatalerr ("got signal %d\n", sig); +} + +#if defined(USG) || (defined(i386) && defined(SYSV)) || defined(WIN32) +#define USGISH +#endif + +#ifndef USGISH +#ifndef _POSIX_SOURCE +#define sigaction sigvec +#define sa_handler sv_handler +#define sa_mask sv_mask +#define sa_flags sv_flags +#endif +struct sigaction sig_act; +#endif /* USGISH */ + +main(argc, argv) + int argc; + char **argv; +{ + register char **fp = filelist; + register char **incp = includedirs; + register char *p; + register struct inclist *ip; + char *makefile = NULL; + struct filepointer *filecontent; + struct symtab *psymp = predefs; + char *endmarker = NULL; + char *defincdir = NULL; + + ProgramName = argv[0]; + + while (psymp->s_name) + { + define2(psymp->s_name, psymp->s_value, &maininclist); + psymp++; + } + if (argc == 2 && argv[1][0] == '@') { + struct stat ast; + int afd; + char *args; + char **nargv; + int nargc; + char quotechar = '\0'; + + nargc = 1; + if ((afd = open(argv[1]+1, O_RDONLY)) < 0) + fatalerr("cannot open \"%s\"\n", argv[1]+1); + fstat(afd, &ast); + args = (char *)malloc(ast.st_size + 1); + if ((ast.st_size = read(afd, args, ast.st_size)) < 0) + fatalerr("failed to read %s\n", argv[1]+1); + args[ast.st_size] = '\0'; + close(afd); + for (p = args; *p; p++) { + if (quotechar) { + if (quotechar == '\\' || + (*p == quotechar && p[-1] != '\\')) + quotechar = '\0'; + continue; + } + switch (*p) { + case '\\': + case '"': + case '\'': + quotechar = *p; + break; + case ' ': + case '\n': + *p = '\0'; + if (p > args && p[-1]) + nargc++; + break; + } + } + if (p[-1]) + nargc++; + nargv = (char **)malloc(nargc * sizeof(char *)); + nargv[0] = argv[0]; + argc = 1; + for (p = args; argc < nargc; p += strlen(p) + 1) + if (*p) nargv[argc++] = p; + argv = nargv; + } + for(argc--, argv++; argc; argc--, argv++) { + /* if looking for endmarker then check before parsing */ + if (endmarker && strcmp (endmarker, *argv) == 0) { + endmarker = NULL; + continue; + } + if (**argv != '-') { + /* treat +thing as an option for C++ */ + if (endmarker && **argv == '+') + continue; + *fp++ = argv[0]; + continue; + } + switch(argv[0][1]) { + case '-': + endmarker = &argv[0][2]; + if (endmarker[0] == '\0') endmarker = "--"; + break; + case 'D': + if (argv[0][2] == '\0') { + argv++; + argc--; + } + for (p=argv[0] + 2; *p ; p++) + if (*p == '=') { + *p = ' '; + break; + } + define(argv[0] + 2, &maininclist); + break; + case 'I': + if (incp >= includedirs + MAXDIRS) + fatalerr("Too many -I flags.\n"); + *incp++ = argv[0]+2; + if (**(incp-1) == '\0') { + *(incp-1) = *(++argv); + argc--; + } + break; + case 'Y': + defincdir = argv[0]+2; + break; + /* do not use if endmarker processing */ + case 'a': + if (endmarker) break; + append = TRUE; + break; + case 'w': + if (endmarker) break; + if (argv[0][2] == '\0') { + argv++; + argc--; + width = atoi(argv[0]); + } else + width = atoi(argv[0]+2); + break; + case 'o': + if (endmarker) break; + if (argv[0][2] == '\0') { + argv++; + argc--; + objsuffix = argv[0]; + } else + objsuffix = argv[0]+2; + break; + case 'p': + if (endmarker) break; + if (argv[0][2] == '\0') { + argv++; + argc--; + objprefix = argv[0]; + } else + objprefix = argv[0]+2; + break; + case 'v': + if (endmarker) break; + verbose = TRUE; +#ifdef DEBUG + if (argv[0][2]) + _debugmask = atoi(argv[0]+2); +#endif + break; + case 's': + if (endmarker) break; + startat = argv[0]+2; + if (*startat == '\0') { + startat = *(++argv); + argc--; + } + if (*startat != '#') + fatalerr("-s flag's value should start %s\n", + "with '#'."); + break; + case 'f': + if (endmarker) break; + makefile = argv[0]+2; + if (*makefile == '\0') { + makefile = *(++argv); + argc--; + } + break; + + case 'm': + warn_multiple = TRUE; + break; + + /* Ignore -O, -g so we can just pass ${CFLAGS} to + makedepend + */ + case 'O': + case 'g': + break; + default: + if (endmarker) break; + /* fatalerr("unknown opt = %s\n", argv[0]); */ + warning("ignoring option %s\n", argv[0]); + } + } + if (!defincdir) { +#ifdef PREINCDIR + if (incp >= includedirs + MAXDIRS) + fatalerr("Too many -I flags.\n"); + *incp++ = PREINCDIR; +#endif + if (incp >= includedirs + MAXDIRS) + fatalerr("Too many -I flags.\n"); + *incp++ = INCLUDEDIR; +#ifdef POSTINCDIR + if (incp >= includedirs + MAXDIRS) + fatalerr("Too many -I flags.\n"); + *incp++ = POSTINCDIR; +#endif + } else if (*defincdir) { + if (incp >= includedirs + MAXDIRS) + fatalerr("Too many -I flags.\n"); + *incp++ = defincdir; + } + + redirect(startat, makefile); + + /* + * catch signals. + */ +#ifdef USGISH +/* should really reset SIGINT to SIG_IGN if it was. */ +#ifdef SIGHUP + signal (SIGHUP, catch); +#endif + signal (SIGINT, catch); +#ifdef SIGQUIT + signal (SIGQUIT, catch); +#endif + signal (SIGILL, catch); +#ifdef SIGBUS + signal (SIGBUS, catch); +#endif + signal (SIGSEGV, catch); +#ifdef SIGSYS + signal (SIGSYS, catch); +#endif +#else + sig_act.sa_handler = catch; +#ifdef _POSIX_SOURCE + sigemptyset(&sig_act.sa_mask); + sigaddset(&sig_act.sa_mask, SIGINT); + sigaddset(&sig_act.sa_mask, SIGQUIT); +#ifdef SIGBUS + sigaddset(&sig_act.sa_mask, SIGBUS); +#endif + sigaddset(&sig_act.sa_mask, SIGILL); + sigaddset(&sig_act.sa_mask, SIGSEGV); + sigaddset(&sig_act.sa_mask, SIGHUP); + sigaddset(&sig_act.sa_mask, SIGPIPE); +#ifdef SIGSYS + sigaddset(&sig_act.sa_mask, SIGSYS); +#endif +#else + sig_act.sa_mask = ((1<<(SIGINT -1)) + |(1<<(SIGQUIT-1)) +#ifdef SIGBUS + |(1<<(SIGBUS-1)) +#endif + |(1<<(SIGILL-1)) + |(1<<(SIGSEGV-1)) + |(1<<(SIGHUP-1)) + |(1<<(SIGPIPE-1)) +#ifdef SIGSYS + |(1<<(SIGSYS-1)) +#endif + ); +#endif /* _POSIX_SOURCE */ + sig_act.sa_flags = 0; + sigaction(SIGHUP, &sig_act, (struct sigaction *)0); + sigaction(SIGINT, &sig_act, (struct sigaction *)0); + sigaction(SIGQUIT, &sig_act, (struct sigaction *)0); + sigaction(SIGILL, &sig_act, (struct sigaction *)0); +#ifdef SIGBUS + sigaction(SIGBUS, &sig_act, (struct sigaction *)0); +#endif + sigaction(SIGSEGV, &sig_act, (struct sigaction *)0); +#ifdef SIGSYS + sigaction(SIGSYS, &sig_act, (struct sigaction *)0); +#endif +#endif /* USGISH */ + + /* + * now peruse through the list of files. + */ + for(fp=filelist; *fp; fp++) { + filecontent = getfile(*fp); + ip = newinclude(*fp, (char *)NULL); + + find_includes(filecontent, ip, ip, 0, FALSE); + freefile(filecontent); + recursive_pr_include(ip, ip->i_file, base_name(*fp)); + inc_clean(); + } + if (printed) + printf("\n"); + exit(0); +} + +struct filepointer *getfile(file) + char *file; +{ + register int fd; + struct filepointer *content; + struct stat st; + + content = (struct filepointer *)malloc(sizeof(struct filepointer)); + if ((fd = open(file, O_RDONLY)) < 0) { + warning("cannot open \"%s\"\n", file); + content->f_p = content->f_base = content->f_end = (char *)malloc(1); + *content->f_p = '\0'; + return(content); + } + fstat(fd, &st); + content->f_base = (char *)malloc(st.st_size+1); + if (content->f_base == NULL) + fatalerr("cannot allocate mem\n"); + if ((st.st_size = read(fd, content->f_base, st.st_size)) < 0) + fatalerr("failed to read %s\n", file); + close(fd); + content->f_len = st.st_size+1; + content->f_p = content->f_base; + content->f_end = content->f_base + st.st_size; + *content->f_end = '\0'; + content->f_line = 0; + return(content); +} + +void +freefile(fp) + struct filepointer *fp; +{ + free(fp->f_base); + free(fp); +} + +char *copy(str) + register char *str; +{ + register char *p = (char *)malloc(strlen(str) + 1); + + strcpy(p, str); + return(p); +} + +match(str, list) + register char *str, **list; +{ + register int i; + + for (i=0; *list; i++, list++) + if (strcmp(str, *list) == 0) + return(i); + return(-1); +} + +/* + * Get the next line. We only return lines beginning with '#' since that + * is all this program is ever interested in. + */ +char *getline(filep) + register struct filepointer *filep; +{ + register char *p, /* walking pointer */ + *eof, /* end of file pointer */ + *bol; /* beginning of line pointer */ + register int lineno; /* line number */ + + p = filep->f_p; + eof = filep->f_end; + if (p >= eof) + return((char *)NULL); + lineno = filep->f_line; + + for(bol = p--; ++p < eof; ) { + if (*p == '/' && *(p+1) == '*') { /* consume comments */ + *p++ = ' ', *p++ = ' '; + while (*p) { + if (*p == '*' && *(p+1) == '/') { + *p++ = ' ', *p = ' '; + break; + } + else if (*p == '\n') + lineno++; + *p++ = ' '; + } + continue; + } + else if (*p == '/' && *(p+1) == '/') { /* consume comments */ + *p++ = ' ', *p++ = ' '; + + while (*p) + { + /* Comment continues on next line. */ + if (*p == '\\' && *(p+1) == '\n') + { + *(p++) = ' '; + *(p++) = ' '; + lineno++; + } + else + if (*p == '\n') + { + /* + * Decrement so that the next iteration + * of the outter "for loop" will handle + * the case of "*p == '\n'". + */ + --p; + break; + } + else + { + *p++ = ' '; + } + } + + continue; + } +#ifdef WIN32 + else if (*p == '/' && *(p+1) == '/') { /* consume comments */ + *p++ = ' ', *p++ = ' '; + while (*p && *p != '\n') + *p++ = ' '; + lineno++; + continue; + } +#endif + else if (*p == '\\') { + if (*(p+1) == '\n') { + *p = ' '; + *(p+1) = ' '; + lineno++; + } + } + else if (*p == '\n') { + lineno++; + if (*bol == '#') { + register char *cp; + + *p++ = '\0'; + /* punt lines with just # (yacc generated) */ + for (cp = bol+1; + *cp && (*cp == ' ' || *cp == '\t'); cp++); + if (*cp) goto done; + } + bol = p+1; + } + } + if (*bol != '#') + bol = NULL; +done: + filep->f_p = p; + filep->f_line = lineno; + return(bol); +} + +/* + * Strip the file name down to what we want to see in the Makefile. + * It will have objprefix and objsuffix around it. + */ +char *base_name(file) + register char *file; +{ + register char *p; + + file = copy(file); + for(p=file+strlen(file); p>file && *p != '.'; p--) ; + + if (*p == '.') + *p = '\0'; + return(file); +} + +#if defined(USG) && !defined(CRAY) && !defined(SVR4) +int rename (from, to) + char *from, *to; +{ + (void) unlink (to); + if (link (from, to) == 0) { + unlink (from); + return 0; + } else { + return -1; + } +} +#endif /* USGISH */ + +void +redirect(line, makefile) + char *line, + *makefile; +{ + struct stat st; + FILE *fdin, *fdout; + char backup[ BUFSIZ ], + buf[ BUFSIZ ]; + boolean found = FALSE; + int len; + + /* + * if makefile is "-" then let it pour onto stdout. + */ + if (makefile && *makefile == '-' && *(makefile+1) == '\0') { + puts(line); + return; + } + + /* + * use a default makefile is not specified. + */ + if (!makefile) { + if (stat("Makefile", &st) == 0) + makefile = "Makefile"; + else if (stat("makefile", &st) == 0) + makefile = "makefile"; + else + fatalerr("[mM]akefile is not present\n"); + } + else + stat(makefile, &st); + if ((fdin = fopen(makefile, "r")) == NULL) + fatalerr("cannot open \"%s\"\n", makefile); + sprintf(backup, "%s.bak", makefile); + unlink(backup); +#ifdef WIN32 + fclose(fdin); +#endif + if (rename(makefile, backup) < 0) + fatalerr("cannot rename %s to %s\n", makefile, backup); +#ifdef WIN32 + if ((fdin = fopen(backup, "r")) == NULL) + fatalerr("cannot open \"%s\"\n", backup); +#endif + if ((fdout = freopen(makefile, "w", stdout)) == NULL) + fatalerr("cannot open \"%s\"\n", backup); + len = strlen(line); + while (!found && fgets(buf, BUFSIZ, fdin)) { + if (*buf == '#' && strncmp(line, buf, len) == 0) + found = TRUE; + fputs(buf, fdout); + } + if (!found) { + if (verbose) + warning("Adding new delimiting line \"%s\" and dependencies...\n", + line); + puts(line); /* same as fputs(fdout); but with newline */ + } else if (append) { + while (fgets(buf, BUFSIZ, fdin)) { + fputs(buf, fdout); + } + } + fflush(fdout); +#if defined(USGISH) || defined(_SEQUENT_) + chmod(makefile, st.st_mode); +#else + fchmod(fileno(fdout), st.st_mode); +#endif /* USGISH */ +} + +void +#if NeedVarargsPrototypes +fatalerr(char *msg, ...) +#else +/*VARARGS*/ +fatalerr(msg,x1,x2,x3,x4,x5,x6,x7,x8,x9) + char *msg; +#endif +{ +#if NeedVarargsPrototypes + va_list args; +#endif + fprintf(stderr, "%s: error: ", ProgramName); +#if NeedVarargsPrototypes + va_start(args, msg); + vfprintf(stderr, msg, args); + va_end(args); +#else + fprintf(stderr, msg,x1,x2,x3,x4,x5,x6,x7,x8,x9); +#endif + exit (1); +} + +void +#if NeedVarargsPrototypes +warning(char *msg, ...) +#else +/*VARARGS0*/ +warning(msg,x1,x2,x3,x4,x5,x6,x7,x8,x9) + char *msg; +#endif +{ +#if NeedVarargsPrototypes + va_list args; +#endif + fprintf(stderr, "%s: warning: ", ProgramName); +#if NeedVarargsPrototypes + va_start(args, msg); + vfprintf(stderr, msg, args); + va_end(args); +#else + fprintf(stderr, msg,x1,x2,x3,x4,x5,x6,x7,x8,x9); +#endif +} + +void +#if NeedVarargsPrototypes +warning1(char *msg, ...) +#else +/*VARARGS0*/ +warning1(msg,x1,x2,x3,x4,x5,x6,x7,x8,x9) + char *msg; +#endif +{ +#if NeedVarargsPrototypes + va_list args; + va_start(args, msg); + vfprintf(stderr, msg, args); + va_end(args); +#else + fprintf(stderr, msg,x1,x2,x3,x4,x5,x6,x7,x8,x9); +#endif +} diff --git a/makedepend.man b/makedepend.man new file mode 100644 index 0000000..21a3faa --- /dev/null +++ b/makedepend.man @@ -0,0 +1,372 @@ +.\" $Xorg: mkdepend.man,v 1.5 2001/02/09 02:03:16 xorgcvs Exp $ +.\" Copyright (c) 1993, 1994, 1998 The Open Group +.\" +.\" Permission to use, copy, modify, distribute, and sell this software and its +.\" documentation for any purpose is hereby granted without fee, provided that +.\" the above copyright notice appear in all copies and that both that +.\" copyright notice and this permission notice appear in supporting +.\" documentation. +.\" +.\" 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 OPEN GROUP 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 Open Group shall not +.\" be used in advertising or otherwise to promote the sale, use or other +.\" dealing in this Software without prior written authorization from The +.\" Open Group. +.TH MAKEDEPEND 1 "Release 6.4" "X Version 11" +.UC 4 +.SH NAME +makedepend \- create dependencies in makefiles +.SH SYNOPSIS +.B makedepend +[ +.BI \-D name\fB=\fPdef +] [ +.BI \-D name +] [ +.BI \-I includedir +] [ +.BI \-Y includedir +] [ +.B \-a +] [ +.BI \-f makefile +] [ +.BI \-o objsuffix +] [ +.BI \-p objprefix +] [ +.BI \-s string +] [ +.BI \-w width +] [ +.B \-v +] [ +.B \-m +] [ +\-\^\- +.I otheroptions +\-\^\- +] +.I sourcefile +\&.\|.\|. +.br +.SH DESCRIPTION +The +.B makedepend +program reads each +.I sourcefile +in sequence and parses it like a C-preprocessor, +processing all +.I #include, +.I #define, +.I #undef, +.I #ifdef, +.I #ifndef, +.I #endif, +.I #if, +.I #elif +and +.I #else +directives so that it can correctly tell which +.I #include, +directives would be used in a compilation. +Any +.I #include, +directives can reference files having other +.I #include +directives, and parsing will occur in these files as well. +.PP +Every file that a +.I sourcefile +includes, +directly or indirectly, +is what +.B makedepend +calls a \fIdependency.\fP +These dependencies are then written to a +.I makefile +in such a way that +.B make(1) +will know which object files must be recompiled when a dependency has changed. +.PP +By default, +.B makedepend +places its output in the file named +.I makefile +if it exists, otherwise +.I Makefile. +An alternate makefile may be specified with the +.B \-f +option. +It first searches the makefile for +the line +.sp + # DO NOT DELETE THIS LINE \-\^\- make depend depends on it. +.sp +or one provided with the +.B \-s +option, +as a delimiter for the dependency output. +If it finds it, it will delete everything +following this to the end of the makefile +and put the output after this line. +If it doesn't find it, the program +will append the string to the end of the makefile +and place the output following that. +For each +.I sourcefile +appearing on the command line, +.B makedepend +puts lines in the makefile of the form +.sp + sourcefile.o:\0dfile .\|.\|. +.sp +Where \fIsourcefile.o\fP is the name from the command +line with its suffix replaced with ``.o'', +and \fIdfile\fP is a dependency discovered in a +.I #include +directive while parsing +.I sourcefile +or one of the files it included. +.SH EXAMPLE +Normally, +.B makedepend +will be used in a makefile target so that typing ``make depend'' will +bring the dependencies up to date for the makefile. +For example, +.nf + SRCS\0=\0file1.c\0file2.c\0.\|.\|. + CFLAGS\0=\0\-O\0\-DHACK\0\-I\^.\^.\^/foobar\0\-xyz + depend: + makedepend\0\-\^\-\0$(CFLAGS)\0\-\^\-\0$(SRCS) +.fi +.SH OPTIONS +The program +will ignore any option that it does not understand so that you may use +the same arguments that you would for +.B cc(1). +.TP 5 +.B \-D\fIname\fP=\fIdef\fP \fRor\fP \-D\fIname\fP +Define. +This places a definition for +.I name +in +.B makedepend's +symbol table. +Without +.I =def\| +the symbol becomes defined as ``1''. +.TP 5 +.B \-I\fIincludedir\fP +Include directory. +This option tells +.B makedepend +to prepend +.I includedir +to its list of directories to search when it encounters +a +.I #include +directive. +By default, +.B makedepend +only searches the standard include directories (usually /usr/include +and possibly a compiler-dependent directory). +.TP 5 +.B \-Y\fIincludedir\fP +Replace all of the standard include directories with the single specified +include directory; you can omit the +.I includedir +to simply prevent searching the standard include directories. +.TP 5 +.B \-a +Append the dependencies to the end of the file instead of replacing them. +.TP 5 +.B \-f\fImakefile\fP +Filename. +This allows you to specify an alternate makefile in which +.B makedepend +can place its output. +Specifying ``\-'' as the file name (i.e., \fB\-f\-\fP) sends the +output to standard output instead of modifying an existing file. +.TP 5 +.B \-o\fIobjsuffix\fP +Object file suffix. +Some systems may have object files whose suffix is something other +than ``.o''. +This option allows you to specify another suffix, such as +``.b'' with +.I \-o.b +or ``:obj'' +with +.I \-o:obj +and so forth. +.TP 5 +.B \-p\fIobjprefix\fP +Object file prefix. +The prefix is prepended to the name of the object file. This is +usually used to designate a different directory for the object file. +The default is the empty string. +.TP 5 +.B \-s\fIstring\fP +Starting string delimiter. +This option permits you to specify +a different string for +.B makedepend +to look for in the makefile. +.TP 5 +.B \-w\fIwidth\fP +Line width. +Normally, +.B makedepend +will ensure that every output line that it writes will be no wider than +78 characters for the sake of readability. +This option enables you to change this width. +.TP 5 +.B \-v +Verbose operation. +This option causes +.B makedepend +to emit the list of files included by each input file. +.TP 5 +.B \-m +Warn about multiple inclusion. +This option causes +.B makedepend +to produce a warning if any input file includes another file more than +once. In previous versions of +.B makedepend +this was the default behavior; the default has been changed to better +match the behavior of the C compiler, which does not consider multiple +inclusion to be an error. This option is provided for backward +compatibility, and to aid in debugging problems related to multiple +inclusion. +.TP 5 +.B "\-\^\- \fIoptions\fP \-\^\-" +If +.B makedepend +encounters a double hyphen (\-\^\-) in the argument list, +then any unrecognized argument following it +will be silently ignored; a second double hyphen terminates this +special treatment. +In this way, +.B makedepend +can be made to safely ignore esoteric compiler arguments that might +normally be found in a CFLAGS +.B make +macro (see the +.B EXAMPLE +section above). +All options that +.B makedepend +recognizes and appear between the pair of double hyphens +are processed normally. +.SH ALGORITHM +The approach used in this program enables it to run an order of magnitude +faster than any other ``dependency generator'' I have ever seen. +Central to this performance are two assumptions: +that all files compiled by a single +makefile will be compiled with roughly the same +.I \-I +and +.I \-D +options; +and that most files in a single directory will include largely the +same files. +.PP +Given these assumptions, +.B makedepend +expects to be called once for each makefile, with +all source files that are maintained by the +makefile appearing on the command line. +It parses each source and include +file exactly once, maintaining an internal symbol table +for each. +Thus, the first file on the command line will take an amount of time +proportional to the amount of time that a normal C preprocessor takes. +But on subsequent files, if it encounters an include file +that it has already parsed, it does not parse it again. +.PP +For example, +imagine you are compiling two files, +.I file1.c +and +.I file2.c, +they each include the header file +.I header.h, +and the file +.I header.h +in turn includes the files +.I def1.h +and +.I def2.h. +When you run the command +.sp + makedepend\0file1.c\0file2.c +.sp +.B makedepend +will parse +.I file1.c +and consequently, +.I header.h +and then +.I def1.h +and +.I def2.h. +It then decides that the dependencies for this file are +.sp + file1.o:\0header.h\0def1.h\0def2.h +.sp +But when the program parses +.I file2.c +and discovers that it, too, includes +.I header.h, +it does not parse the file, +but simply adds +.I header.h, +.I def1.h +and +.I def2.h +to the list of dependencies for +.I file2.o. +.SH "SEE ALSO" +cc(1), make(1) +.SH BUGS +.B makedepend +parses, but does not currently evaluate, the SVR4 +#predicate(token-list) preprocessor expression; +such expressions are simply assumed to be true. +This may cause the wrong +.I #include +directives to be evaluated. +.PP +Imagine you are parsing two files, +say +.I file1.c +and +.I file2.c, +each includes the file +.I def.h. +The list of files that +.I def.h +includes might truly be different when +.I def.h +is included by +.I file1.c +than when it is included by +.I file2.c. +But once +.B makedepend +arrives at a list of dependencies for a file, +it is cast in concrete. +.SH AUTHOR +Todd Brunhoff, Tektronix, Inc. and MIT Project Athena @@ -0,0 +1,653 @@ +/* $Xorg: parse.c,v 1.6 2001/02/09 02:03:16 xorgcvs Exp $ */ +/* + +Copyright (c) 1993, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +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 +OPEN GROUP 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 Open Group 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 Open Group. + +*/ + +#include "def.h" + +extern char *directives[]; +extern struct inclist maininclist; + +int +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: + case WARNING: + break; + case ELIF: + case ELIFFALSE: + case ELIFGUESSFALSE: + return(type); + 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; + } + } + 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(file->i_file, 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(file->i_file, 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_flags |= INCLUDED_SYM; + 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 **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_flags & DEFCHECKED) + return(NULL); + file->i_flags |= DEFCHECKED; + 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 (file->i_merged[i]==FALSE) { + val = fdefined(symbol, *ip, srcfile); + if ((*ip)->i_flags & FINISHED) { + merge2defines(file,*ip); + file->i_merged[i]=TRUE; + } + if (val!=NULL) break; + } + } + else if (val != NULL && srcfile != NULL) *srcfile = file; + recurse_lvl--; + file->i_flags &= ~DEFCHECKED; + + return(val); +} + +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); +} + +/* + * Return type based on if the #if expression evaluates to 0 + */ +int +zero_value(filename, exp, filep, file_red) + register char *filename; + register char *exp; + register struct filepointer *filep; + register struct inclist *file_red; +{ + if (cppsetup(filename, exp, filep, file_red)) + return(IFFALSE); + else + return(IF); +} + +void +define2(name, val, file) + char *name, *val; + struct inclist *file; +{ + int first, last, below; + register struct symtab **sp = NULL, **dest; + struct symtab *stab; + + /* Make space if it's needed */ + if (file->i_defs == NULL) + { + file->i_defs = (struct symtab **) + malloc(sizeof (struct symtab*) * SYMTABINC); + file->i_ndefs = 0; + } + else if (!(file->i_ndefs % SYMTABINC)) + file->i_defs = (struct symtab **) + realloc(file->i_defs, + sizeof(struct symtab*)*(file->i_ndefs+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--; + } + stab = (struct symtab *) malloc(sizeof (struct symtab)); + if (stab == NULL) + fatalerr("malloc()/realloc() failure in insert_defn()\n"); + + stab->s_name = copy(name); + stab->s_value = copy(val); + *sp = stab; +} + +void +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); +} + +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); +} + +int merge2defines(file1, file2) + struct inclist *file1; + struct inclist *file2; +{ + if ((file1!=NULL) && (file2!=NULL)) + { + int first1 = 0; + int last1 = file1->i_ndefs - 1; + + int first2 = 0; + int last2 = file2->i_ndefs - 1; + + int first=0; + struct symtab** i_defs = NULL; + int deflen=file1->i_ndefs+file2->i_ndefs; + + if (deflen>0) + { + /* make sure deflen % SYMTABINC == 0 is still true */ + deflen += (SYMTABINC - deflen % SYMTABINC) % SYMTABINC; + i_defs=(struct symtab**) + malloc(deflen*sizeof(struct symtab*)); + if (i_defs==NULL) return 0; + } + + while ((last1 >= first1) && (last2 >= first2)) + { + char *s1=file1->i_defs[first1]->s_name; + char *s2=file2->i_defs[first2]->s_name; + + if (strcmp(s1,s2) < 0) + i_defs[first++]=file1->i_defs[first1++]; + else if (strcmp(s1,s2) > 0) + i_defs[first++]=file2->i_defs[first2++]; + else /* equal */ + { + i_defs[first++]=file2->i_defs[first2++]; + first1++; + } + } + while (last1 >= first1) + { + i_defs[first++]=file1->i_defs[first1++]; + } + while (last2 >= first2) + { + i_defs[first++]=file2->i_defs[first2++]; + } + + if (file1->i_defs) free(file1->i_defs); + file1->i_defs=i_defs; + file1->i_ndefs=first; + + return 1; + } + return 0; +} + +void +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]; + } +} + +int +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", file_red->i_file); + if (file_red != file) + warning1(" (reading %s)", file->i_file); + warning1(", line %d: incomplete undef == \"%s\"\n", + 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("%s", file_red->i_file); + if (file_red != file) + warning1(" (reading %s)", file->i_file); + warning1(", line %d: %s\n", + 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; + } + } + file->i_flags |= FINISHED; + return(-1); +} @@ -0,0 +1,129 @@ +/* $Xorg: pr.c,v 1.4 2001/02/09 02:03:16 xorgcvs Exp $ */ +/* + +Copyright (c) 1993, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +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 +OPEN GROUP 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 Open Group 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 Open Group. + +*/ + +#include "def.h" + +extern struct inclist inclist[ MAXFILES ], + *inclistp; +extern char *objprefix; +extern char *objsuffix; +extern int width; +extern boolean printed; +extern boolean verbose; +extern boolean show_where_not; + +void +add_include(filep, file, file_red, include, dot, failOK) + struct filepointer *filep; + struct inclist *file, *file_red; + char *include; + boolean dot; +{ + register struct inclist *newfile; + register struct filepointer *content; + + /* + * First decide what the pathname of this include file really is. + */ + newfile = inc_path(file->i_file, include, dot); + if (newfile == NULL) { + if (failOK) + return; + if (file != file_red) + warning("%s (reading %s, line %d): ", + file_red->i_file, file->i_file, filep->f_line); + else + warning("%s, line %d: ", file->i_file, filep->f_line); + warning1("cannot find include file \"%s\"\n", include); + show_where_not = TRUE; + newfile = inc_path(file->i_file, include, dot); + show_where_not = FALSE; + } + + if (newfile) { + included_by(file, newfile); + if (!(newfile->i_flags & SEARCHED)) { + newfile->i_flags |= SEARCHED; + content = getfile(newfile->i_file); + find_includes(content, newfile, file_red, 0, failOK); + freefile(content); + } + } +} + +void +pr(ip, file, base) + register struct inclist *ip; + char *file, *base; +{ + static char *lastfile; + static int current_len; + register int len, i; + char buf[ BUFSIZ ]; + + printed = TRUE; + len = strlen(ip->i_file)+1; + if (current_len + len > width || file != lastfile) { + lastfile = file; + sprintf(buf, "\n%s%s%s: %s", objprefix, base, objsuffix, + ip->i_file); + len = current_len = strlen(buf); + } + else { + buf[0] = ' '; + strcpy(buf+1, ip->i_file); + current_len += len; + } + fwrite(buf, len, 1, stdout); + + /* + * If verbose is set, then print out what this file includes. + */ + if (! verbose || ip->i_list == NULL || ip->i_flags & NOTIFIED) + return; + ip->i_flags |= NOTIFIED; + lastfile = NULL; + printf("\n# %s includes:", ip->i_file); + for (i=0; i<ip->i_listlen; i++) + printf("\n#\t%s", ip->i_list[ i ]->i_incstring); +} + +void +recursive_pr_include(head, file, base) + register struct inclist *head; + register char *file, *base; +{ + register int i; + + if (head->i_flags & MARKED) + return; + head->i_flags |= MARKED; + if (head->i_file != file) + pr(head, file, base); + for (i=0; i<head->i_listlen; i++) + recursive_pr_include(head->i_list[ i ], file, base); +} |