picking up makedepend from x11r6
authorTom Yu <tlyu@mit.edu>
Thu, 26 May 1994 03:16:05 +0000 (03:16 +0000)
committerTom Yu <tlyu@mit.edu>
Thu, 26 May 1994 03:16:05 +0000 (03:16 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@3649 dc483132-0cff-0310-8789-dd5450dbe970

src/util/makedepend/Imakefile [new file with mode: 0644]
src/util/makedepend/cpp.ed [new file with mode: 0644]
src/util/makedepend/cppsetup.c [new file with mode: 0644]
src/util/makedepend/def.h [new file with mode: 0644]
src/util/makedepend/ifparser.c [new file with mode: 0644]
src/util/makedepend/ifparser.h [new file with mode: 0644]
src/util/makedepend/include.c [new file with mode: 0644]
src/util/makedepend/main.c [new file with mode: 0644]
src/util/makedepend/mkdepend.man [new file with mode: 0644]
src/util/makedepend/parse.c [new file with mode: 0644]
src/util/makedepend/pr.c [new file with mode: 0644]

diff --git a/src/util/makedepend/Imakefile b/src/util/makedepend/Imakefile
new file mode 100644 (file)
index 0000000..bcfc523
--- /dev/null
@@ -0,0 +1,45 @@
+XCOMM $XConsortium: Imakefile,v 1.22 94/03/29 15:54:05 gildea Exp $
+
+    SRCS = include.c main.c parse.c pr.c cppsetup.c ifparser.c 
+    OBJS = include.o main.o parse.o pr.o cppsetup.o ifparser.o 
+
+#if HasGcc && !defined(PreIncDir)
+#define PreIncDir /usr/local/lib/gcc-include
+#endif
+#ifdef PreIncDir
+PREINCDIR = PreIncDir
+PREINC_DEFINES = -DPREINCDIR=\"$(PREINCDIR)\"
+#endif
+#ifndef StdIncDir
+#define StdIncDir /usr/include
+#endif
+STDINCDIR = StdIncDir
+STDINC_DEFINES = -DINCLUDEDIR=\"$(STDINCDIR)\"
+#ifdef PostIncDir
+POSTINCDIR = PostIncDir
+POSTINC_DEFINES = -DPOSTINCDIR=\"$(POSTINCDIR)\"
+#endif
+INC_DEFINES = $(PREINC_DEFINES) $(STDINC_DEFINES) $(POSTINC_DEFINES)
+OSUF = .Osuf
+OSUF_DEFINES = -DOBJSUFFIX=\"$(OSUF)\"
+MAIN_DEFINES = $(INC_DEFINES) $(SIGNAL_DEFINES) $(OSUF_DEFINES)
+INCLUDES = -I$(IMAKESRC)
+ DEPLIBS =
+
+#if defined(MacIIArchitecture) || defined(SequentArchitecture)
+ XBSDLIB = /**/
+#endif
+
+all:: makedepend
+
+#undef InstallManPage
+#define InstallManPage(file,dest) /* as nothing */
+#if CrossCompiling
+ComplexHostProgramTarget(makedepend)
+#else
+ComplexProgramTarget(makedepend)
+#endif
+
+SpecialObjectRule(main.o,$(ICONFIGFILES),$(MAIN_DEFINES))
+
+InstallManPageLong(mkdepend,$(MANDIR),makedepend)
diff --git a/src/util/makedepend/cpp.ed b/src/util/makedepend/cpp.ed
new file mode 100644 (file)
index 0000000..ffa586f
--- /dev/null
@@ -0,0 +1,75 @@
+#
+# $XConsortium: cpp.ed,v 1.3 89/12/12 12:44:18 jim Exp $
+#
+# $Locker $
+#
+/struct symtab stab/d
+/struct symtab \*defloc;/d
+/struct symtab \*udfloc;/d
+/struct symtab \*incloc;/d
+/struct symtab \*ifloc;/d
+/struct symtab \*elsloc;/d
+/struct symtab \*eifloc;/d
+/struct symtab \*ifdloc;/d
+/struct symtab \*ifnloc;/d
+/struct symtab \*ysysloc;/d
+/struct symtab \*varloc;/d
+/struct symtab \*lneloc;/d
+/struct symtab \*ulnloc;/d
+/struct symtab \*uflloc;/d
+/^sayline(/s/$/        DELETED/p
+.,/^}/d
+/^unfill(/s/$/ DELETED/p
+.-1,/^}/d
+/^doincl(/s/$/ DELETED/p
+.-1,/^}/d
+/^equfrm(/s/$/ DELETED/p
+.,/^}/d
+/^dodef(/s/$/  DELETED/p
+.-1,/^}/d
+/^control(/s/$/        DELETED/p
+.-1,/^}/d
+/^savestring(/s/$/     DELETED/p
+.-1,/^}/d
+/^stsym(/s/$/  DELETED/p
+.-1,/^}/d
+/^ppsym(/s/$/  DELETED/p
+.-1,/^}/d
+/^yyerror(/s/$/        DELETED/p
+.,/^}/d
+/^ppwarn(/s/$/ DELETED/p
+.,/^}/d
+/^lookup(/s/$/ DELETED/p
+.-1,/^}/d
+/^subst(/s/$/  DELETED/p
+.-1,/^}/d
+/^trmdir(/s/$/ DELETED/p
+.-1,/^}/d
+/^copy(/s/$/   DELETED/p
+.-1,/^}/d
+/^pperror(/s/$/        DELETED/p
+.,/^}/d
+/^main(/s/$/   CHANGED to cpp_varsetup(argc,argv)/p
+.c
+cpp_varsetup(argc,argv)
+.
+/^strdex(/s/$/ DELETED/p
+.-1,/^}/d
+/^ for(i=1; i<argc; i++)/s/$/  To the end DELETED/p
+.,$c
+}
+.
+/^dump(/s/$/   DELETED/p
+.,/^}/c
+dump() { fatal("dump\n"); }
+.
+/^refill(/s/$/ DELETED/p
+.,/^}/c
+refill() { fatal("refill\n"); }
+.
+/^slookup(/s/$/        DELETED/p
+.-1,/^}/c
+static struct symtab *slookup() { fatal("slookup\n"); }
+.
+w
+q
diff --git a/src/util/makedepend/cppsetup.c b/src/util/makedepend/cppsetup.c
new file mode 100644 (file)
index 0000000..bf1c4fc
--- /dev/null
@@ -0,0 +1,242 @@
+/* $XConsortium: cppsetup.c,v 1.13 94/04/17 20:10:32 gildea Exp $ */
+/*
+
+Copyright (c) 1993, 1994  X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+*/
+
+#include "def.h"
+
+#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;
+    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->inc->i_file;
+    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 int
+_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 atoi(var);
+}
+
+
+cppsetup(line, filep, inc)
+       register char   *line;
+       register struct filepointer     *filep;
+       register struct inclist         *inc;
+{
+    IfParser ip;
+    struct _parse_data pd;
+    int val = 0;
+
+    pd.filep = filep;
+    pd.inc = inc;
+    pd.line = line;
+    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 */
+
diff --git a/src/util/makedepend/def.h b/src/util/makedepend/def.h
new file mode 100644 (file)
index 0000000..6047741
--- /dev/null
@@ -0,0 +1,145 @@
+/* $XConsortium: def.h,v 1.25 94/04/17 20:10:33 gildea Exp $ */
+/*
+
+Copyright (c) 1993, 1994  X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+*/
+
+#include <X11/Xosdefs.h>
+#ifdef WIN32
+#include <X11/Xw32defs.h>
+#endif
+#include <X11/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       512
+#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 IFFALSE         15     /* pseudo value --- never matched */
+#define ELIFFALSE       16     /* pseudo value --- never matched */
+#define INCLUDEDOT      17     /* pseudo value --- never matched */
+#define IFGUESSFALSE    18     /* pseudo value --- never matched */
+#define ELIFGUESSFALSE  19     /* 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;
+};
+
+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 */
+       int             i_ndefs;        /* current # defines */
+       int             i_deflen;       /* amount of space in table */
+       boolean         i_defchecked;   /* whether defines have been checked */
+       boolean         i_notified;     /* whether we have revealed includes */
+       boolean         i_marked;       /* whether it's in the makefile */
+       boolean         i_searched;     /* whether we have read this */
+       boolean         i_included_sym; /* whether #include SYMBOL was found */
+                                       /* Can't use i_list if TRUE */
+};
+
+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 fatalerr(char *, ...);
+extern warning(char *, ...);
+extern warning1(char *, ...);
+#endif
diff --git a/src/util/makedepend/ifparser.c b/src/util/makedepend/ifparser.c
new file mode 100644 (file)
index 0000000..e0f171d
--- /dev/null
@@ -0,0 +1,451 @@
+/*
+ * $XConsortium: ifparser.c,v 1.7 94/01/18 21:30:50 rws 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;
+    int *valp;
+{
+    SKIPSPACE (cp);
+
+    if (!isdigit(*cp))
+       return CALLFUNC(g, handle_error) (g, cp, "number");
+
+#ifdef WIN32
+    *valp = strtol(cp, &cp, 0);
+#else
+    *valp = atoi (cp);
+    /* EMPTY */
+    for (cp++; isdigit(*cp); cp++) ;
+#endif
+    return cp;
+}
+
+
+static const char *
+parse_value (g, cp, valp)
+    IfParser *g;
+    const char *cp;
+    int *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 'd':
+       if (strncmp (cp, "defined", 7) == 0 && !isalnum(cp[7])) {
+           int paren = 0;
+           cp += 7;
+           SKIPSPACE (cp);
+           if (*cp == '(') {
+               paren = 1;
+               cp++;
+           }
+           DO (cp = parse_variable (g, cp, &var));
+           SKIPSPACE (cp);
+           if (paren && *cp != ')')
+               return CALLFUNC(g, handle_error) (g, cp, ")");
+           *valp = (*(g->funcs.eval_defined)) (g, var, cp - var);
+           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;
+    int *valp;
+{
+    int 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;
+    int *valp;
+{
+    int 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;
+    int *valp;
+{
+    int 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;
+    int *valp;
+{
+    int 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;
+    int *valp;
+{
+    int 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;
+    int *valp;
+{
+    int 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;
+    int *valp;
+{
+    int 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;
+    int *valp;
+{
+    int 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;
+    int *valp;
+{
+    int 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;
+    int *valp;
+{
+    return parse_lor (g, cp, valp);
+}
+
+
diff --git a/src/util/makedepend/ifparser.h b/src/util/makedepend/ifparser.h
new file mode 100644 (file)
index 0000000..c333798
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * $XConsortium: ifparser.h,v 1.1 92/08/22 13:05:39 rws 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 * */);
+       int (*eval_variable) (/* struct _if_parser *, const char *, int */);
+       int (*eval_defined) (/* struct _if_parser *, const char *, int */);
+    } funcs;
+    char *data;
+} IfParser;
+
+char *ParseIfExpression (/* IfParser *, const char *, int * */);
+
diff --git a/src/util/makedepend/include.c b/src/util/makedepend/include.c
new file mode 100644 (file)
index 0000000..349020a
--- /dev/null
@@ -0,0 +1,295 @@
+/* $XConsortium: include.c,v 1.16 94/04/17 20:10:34 gildea Exp $ */
+/*
+
+Copyright (c) 1993, 1994  X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+*/
+
+
+#include "def.h"
+
+extern struct  inclist inclist[ MAXFILES ],
+                       *inclistp;
+extern char    *includedirs[ ];
+extern char    *notdotdot[ ];
+extern boolean show_where_not;
+extern boolean warn_multiple;
+
+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_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);
+       }
+
+       /*
+        * See if this include file is in the directory of the
+        * file being compiled.
+        */
+       if (!found) {
+               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);
+}
+
+/*
+ * Ocaisionally, 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!!)
+ */
+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;
+
+       /*
+        * Now copy the path, removing all 'x/..' components.
+        */
+       cp = components;
+       component_copied = FALSE;
+       while(*cp) {
+               if (!isdot(*cp) && !isdotdot(*cp) && isdotdot(*(cp+1))) {
+                       if (issymbolic(newpath, *cp))
+                               goto dont_remove;
+                       cp++;
+               } else {
+               dont_remove:
+                       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);
+}
+
+isdot(p)
+       register char   *p;
+{
+       if(p && *p++ == '.' && *p++ == '\0')
+               return(TRUE);
+       return(FALSE);
+}
+
+isdotdot(p)
+       register char   *p;
+{
+       if(p && *p++ == '.' && *p++ == '.' && *p++ == '\0')
+               return(TRUE);
+       return(FALSE);
+}
+
+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 >= &notdotdot[ MAXDIRS ])
+                       fatalerr("out of .. dirs, increase MAXDIRS\n");
+               return(TRUE);
+       }
+#endif
+       return(FALSE);
+}
+
+/*
+ * 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);
+       ip->i_included_sym = FALSE;
+       if (incstring == NULL)
+               ip->i_incstring = ip->i_file;
+       else
+               ip->i_incstring = copy(incstring);
+
+       return(ip);
+}
+
+included_by(ip, newfile)
+       register struct inclist *ip, *newfile;
+{
+       register 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);
+       else {
+               for (i=0; i<ip->i_listlen; i++)
+                       if (ip->i_list[ i ] == newfile) {
+                           i = strlen(newfile->i_file);
+                           if (!ip->i_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_list[ ip->i_listlen-1 ] = newfile;
+}
+
+inc_clean ()
+{
+       register struct inclist *ip;
+
+       for (ip = inclist; ip < inclistp; ip++) {
+               ip->i_marked = FALSE;
+       }
+}
diff --git a/src/util/makedepend/main.c b/src/util/makedepend/main.c
new file mode 100644 (file)
index 0000000..6d961ba
--- /dev/null
@@ -0,0 +1,700 @@
+/* $XConsortium: main.c,v 1.83 94/04/17 20:10:36 gildea Exp $ */
+/*
+
+Copyright (c) 1993, 1994  X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+*/
+
+#include "def.h"
+#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",
+       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 */
+
+static
+#ifdef SIGNALRETURNSINT
+int
+#else
+void
+#endif
+catch (sig)
+    int sig;
+{
+       fflush (stdout);
+       fatalerr ("got signal %d\n", sig);
+}
+
+#if defined(USG) || (defined(SYSV386) && 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);
+}
+
+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        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;
+               }
+#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 */
+
+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')
+               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 */
+}
+
+#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);
+}
+
+#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
+}
+
+#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/src/util/makedepend/mkdepend.man b/src/util/makedepend/mkdepend.man
new file mode 100644 (file)
index 0000000..9c3cdcc
--- /dev/null
@@ -0,0 +1,368 @@
+.\" $XConsortium: mkdepend.man,v 1.15 94/04/17 20:10:37 gildea Exp $
+.\" Copyright (c) 1993, 1994  X Consortium
+.\" 
+.\" Permission is hereby granted, free of charge, to any person obtaining a
+.\" copy of this software and associated documentation files (the "Software"), 
+.\" to deal in the Software without restriction, including without limitation 
+.\" the rights to use, copy, modify, merge, publish, distribute, sublicense, 
+.\" and/or sell copies of the Software, and to permit persons to whom the 
+.\" Software furnished to do so, subject to the following conditions:
+.\" 
+.\" The above copyright notice and this permission notice shall be included in
+.\" all copies or substantial portions of the Software.
+.\" 
+.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+.\" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+.\" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL 
+.\" THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
+.\" WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 
+.\" OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
+.\" SOFTWARE.
+.\" 
+.\" Except as contained in this notice, the name of the X Consortium shall not 
+.\" be used in advertising or otherwise to promote the sale, use or other 
+.\" dealing in this Software without prior written authorization from the 
+.\" X Consortium.
+.TH MAKEDEPEND 1 "Release 6" "X Version 11"
+.UC 4
+.SH NAME
+makedepend \- create dependencies in makefiles
+.SH SYNOPSIS
+.B makedepend
+[
+.B \-Dname=def
+] [
+.B \-Dname
+] [
+.B \-Iincludedir
+] [
+.B \-Yincludedir
+] [
+.B \-a
+] [
+.B \-fmakefile
+] [
+.B \-oobjsuffix
+] [
+.B \-pobjprefix
+] [
+.B \-sstring
+] [
+.B \-wwidth
+] [
+.B \-v
+] [
+.B \-m
+] [
+\-\^\-
+.B otheroptions
+\-\^\-
+]
+sourcefile .\|.\|.
+.br
+.SH DESCRIPTION
+.B Makedepend
+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
+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 "dependency".
+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 "sourcefile.o" is the name from the command
+line with its suffix replaced with ".o",
+and "dfile" 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
+.B Makedepend
+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 \-Dname=def or \-Dname
+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 \-Iincludedir
+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 \-Yincludedir
+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 \-fmakefile
+Filename.
+This allows you to specify an alternate makefile in which
+.B makedepend
+can place its output.
+.TP 5
+.B \-oobjsuffix
+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 \-pobjprefix
+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 \-sstring
+Starting string delimiter.
+This option permits you to specify
+a different string for
+.B makedepend
+to look for in the makefile.
+.TP 5
+.B \-wwidth
+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 on standard output.
+.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 "\-\^\- options \-\^\-"
+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 encounter's 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
diff --git a/src/util/makedepend/parse.c b/src/util/makedepend/parse.c
new file mode 100644 (file)
index 0000000..cf557c0
--- /dev/null
@@ -0,0 +1,567 @@
+/* $XConsortium: parse.c,v 1.30 94/04/17 20:10:38 gildea Exp $ */
+/*
+
+Copyright (c) 1993, 1994  X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+*/
+
+#include "def.h"
+
+extern char    *directives[];
+extern struct inclist  maininclist;
+
+find_includes(filep, file, file_red, recursion, failOK)
+       struct filepointer      *filep;
+       struct inclist          *file, *file_red;
+       int                     recursion;
+       boolean                 failOK;
+{
+       register char   *line;
+       register int    type;
+       boolean recfailOK;
+
+       while (line = getline(filep)) {
+               switch(type = deftype(line, filep, file_red, file, TRUE)) {
+               case IF:
+               doif:
+                       type = find_includes(filep, file,
+                               file_red, recursion+1, failOK);
+                       while ((type == ELIF) || (type == ELIFFALSE) ||
+                              (type == ELIFGUESSFALSE))
+                               type = gobble(filep, file, file_red);
+                       if (type == ELSE)
+                               gobble(filep, file, file_red);
+                       break;
+               case IFFALSE:
+               case IFGUESSFALSE:
+                   doiffalse:
+                       if (type == IFGUESSFALSE || type == ELIFGUESSFALSE)
+                           recfailOK = TRUE;
+                       else
+                           recfailOK = failOK;
+                       type = gobble(filep, file, file_red);
+                       if (type == ELSE)
+                           find_includes(filep, file,
+                                         file_red, recursion+1, recfailOK);
+                       else
+                       if (type == ELIF)
+                           goto doif;
+                       else
+                       if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE))
+                           goto doiffalse;
+                       break;
+               case IFDEF:
+               case IFNDEF:
+                       if ((type == IFDEF && isdefined(line, file_red, NULL))
+                        || (type == IFNDEF && !isdefined(line, file_red, NULL))) {
+                               debug(1,(type == IFNDEF ?
+                                   "line %d: %s !def'd in %s via %s%s\n" : "",
+                                   filep->f_line, line,
+                                   file->i_file, file_red->i_file, ": doit"));
+                               type = find_includes(filep, file,
+                                       file_red, recursion+1, failOK);
+                               while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE)
+                                       type = gobble(filep, file, file_red);
+                               if (type == ELSE)
+                                       gobble(filep, file, file_red);
+                       }
+                       else {
+                               debug(1,(type == IFDEF ?
+                                   "line %d: %s !def'd in %s via %s%s\n" : "",
+                                   filep->f_line, line,
+                                   file->i_file, file_red->i_file, ": gobble"));
+                               type = gobble(filep, file, file_red);
+                               if (type == ELSE)
+                                       find_includes(filep, file,
+                                               file_red, recursion+1, failOK);
+                               else if (type == ELIF)
+                                       goto doif;
+                               else if (type == ELIFFALSE || type == ELIFGUESSFALSE)
+                                       goto doiffalse;
+                       }
+                       break;
+               case ELSE:
+               case ELIFFALSE:
+               case ELIFGUESSFALSE:
+               case ELIF:
+                       if (!recursion)
+                               gobble(filep, file, file_red);
+               case ENDIF:
+                       if (recursion)
+                               return(type);
+               case DEFINE:
+                       define(line, file);
+                       break;
+               case UNDEF:
+                       if (!*line) {
+                           warning("%s, line %d: incomplete undef == \"%s\"\n",
+                               file_red->i_file, filep->f_line, line);
+                           break;
+                       }
+                       undefine(line, file_red);
+                       break;
+               case INCLUDE:
+                       add_include(filep, file, file_red, line, FALSE, failOK);
+                       break;
+               case INCLUDEDOT:
+                       add_include(filep, file, file_red, line, TRUE, failOK);
+                       break;
+               case ERROR:
+                       warning("%s: %d: %s\n", file_red->i_file,
+                                filep->f_line, line);
+                       break;
+                   
+               case PRAGMA:
+               case IDENT:
+               case SCCS:
+               case EJECT:
+                       break;
+               case -1:
+                       warning("%s", file_red->i_file);
+                       if (file_red != file)
+                           warning1(" (reading %s)", file->i_file);
+                       warning1(", line %d: unknown directive == \"%s\"\n",
+                                filep->f_line, line);
+                       break;
+               case -2:
+                       warning("%s", file_red->i_file);
+                       if (file_red != file)
+                           warning1(" (reading %s)", file->i_file);
+                       warning1(", line %d: incomplete include == \"%s\"\n",
+                                filep->f_line, line);
+                       break;
+               }
+       }
+       return(-1);
+}
+
+gobble(filep, file, file_red)
+       register struct filepointer *filep;
+       struct inclist          *file, *file_red;
+{
+       register char   *line;
+       register int    type;
+
+       while (line = getline(filep)) {
+               switch(type = deftype(line, filep, file_red, file, FALSE)) {
+               case IF:
+               case IFFALSE:
+               case IFGUESSFALSE:
+               case IFDEF:
+               case IFNDEF:
+                       type = gobble(filep, file, file_red);
+                       while ((type == ELIF) || (type == ELIFFALSE) ||
+                              (type == ELIFGUESSFALSE))
+                           type = gobble(filep, file, file_red);
+                       if (type == ELSE)
+                               (void)gobble(filep, file, file_red);
+                       break;
+               case ELSE:
+               case ENDIF:
+                       debug(0,("%s, line %d: #%s\n",
+                               file->i_file, filep->f_line,
+                               directives[type]));
+                       return(type);
+               case DEFINE:
+               case UNDEF:
+               case INCLUDE:
+               case INCLUDEDOT:
+               case PRAGMA:
+               case ERROR:
+               case IDENT:
+               case SCCS:
+               case EJECT:
+                       break;
+               case ELIF:
+               case ELIFFALSE:
+               case ELIFGUESSFALSE:
+                       return(type);
+               case -1:
+                       warning("%s, line %d: unknown directive == \"%s\"\n",
+                               file_red->i_file, filep->f_line, line);
+                       break;
+               }
+       }
+       return(-1);
+}
+
+/*
+ * Decide what type of # directive this line is.
+ */
+int deftype (line, filep, file_red, file, parse_it)
+       register char   *line;
+       register struct filepointer *filep;
+       register struct inclist *file_red, *file;
+       int     parse_it;
+{
+       register char   *p;
+       char    *directive, savechar;
+       register int    ret;
+
+       /*
+        * Parse the directive...
+        */
+       directive=line+1;
+       while (*directive == ' ' || *directive == '\t')
+               directive++;
+
+       p = directive;
+       while (*p >= 'a' && *p <= 'z')
+               p++;
+       savechar = *p;
+       *p = '\0';
+       ret = match(directive, directives);
+       *p = savechar;
+
+       /* If we don't recognize this compiler directive or we happen to just
+        * be gobbling up text while waiting for an #endif or #elif or #else
+        * in the case of an #elif we must check the zero_value and return an
+        * ELIF or an ELIFFALSE.
+        */
+
+       if (ret == ELIF && !parse_it)
+       {
+           while (*p == ' ' || *p == '\t')
+               p++;
+           /*
+            * parse an expression.
+            */
+           debug(0,("%s, line %d: #elif %s ",
+                  file->i_file, filep->f_line, p));
+           ret = zero_value(p, filep, file_red);
+           if (ret != IF)
+           {
+               debug(0,("false...\n"));
+               if (ret == IFFALSE)
+                   return(ELIFFALSE);
+               else
+                   return(ELIFGUESSFALSE);
+           }
+           else
+           {
+               debug(0,("true...\n"));
+               return(ELIF);
+           }
+       }
+
+       if (ret < 0 || ! parse_it)
+               return(ret);
+
+       /*
+        * now decide how to parse the directive, and do it.
+        */
+       while (*p == ' ' || *p == '\t')
+               p++;
+       switch (ret) {
+       case IF:
+               /*
+                * parse an expression.
+                */
+               ret = zero_value(p, filep, file_red);
+               debug(0,("%s, line %d: %s #if %s\n",
+                        file->i_file, filep->f_line, ret?"false":"true", p));
+               break;
+       case IFDEF:
+       case IFNDEF:
+               debug(0,("%s, line %d: #%s %s\n",
+                       file->i_file, filep->f_line, directives[ret], p));
+       case UNDEF:
+               /*
+                * separate the name of a single symbol.
+                */
+               while (isalnum(*p) || *p == '_')
+                       *line++ = *p++;
+               *line = '\0';
+               break;
+       case INCLUDE:
+               debug(2,("%s, line %d: #include %s\n",
+                       file->i_file, filep->f_line, p));
+
+               /* Support ANSI macro substitution */
+               {
+                   struct symtab *sym = isdefined(p, file_red, NULL);
+                   while (sym) {
+                       p = sym->s_value;
+                       debug(3,("%s : #includes SYMBOL %s = %s\n",
+                              file->i_incstring,
+                              sym -> s_name,
+                              sym -> s_value));
+                       /* mark file as having included a 'soft include' */
+                       file->i_included_sym = TRUE; 
+                       sym = isdefined(p, file_red, NULL);
+                   }
+               }
+
+               /*
+                * Separate the name of the include file.
+                */
+               while (*p && *p != '"' && *p != '<')
+                       p++;
+               if (! *p)
+                       return(-2);
+               if (*p++ == '"') {
+                       ret = INCLUDEDOT;
+                       while (*p && *p != '"')
+                               *line++ = *p++;
+               } else
+                       while (*p && *p != '>')
+                               *line++ = *p++;
+               *line = '\0';
+               break;
+       case DEFINE:
+               /*
+                * copy the definition back to the beginning of the line.
+                */
+               strcpy (line, p);
+               break;
+       case ELSE:
+       case ENDIF:
+       case ELIF:
+       case PRAGMA:
+       case ERROR:
+       case IDENT:
+       case SCCS:
+       case EJECT:
+               debug(0,("%s, line %d: #%s\n",
+                       file->i_file, filep->f_line, directives[ret]));
+               /*
+                * nothing to do.
+                */
+               break;
+       }
+       return(ret);
+}
+
+struct symtab *isdefined(symbol, file, srcfile)
+       register char   *symbol;
+       struct inclist  *file;
+       struct inclist  **srcfile;
+{
+       register struct symtab  *val;
+
+       if (val = slookup(symbol, &maininclist)) {
+               debug(1,("%s defined on command line\n", symbol));
+               if (srcfile != NULL) *srcfile = &maininclist;
+               return(val);
+       }
+       if (val = fdefined(symbol, file, srcfile))
+               return(val);
+       debug(1,("%s not defined in %s\n", symbol, file->i_file));
+       return(NULL);
+}
+
+struct symtab *fdefined(symbol, file, srcfile)
+       register char   *symbol;
+       struct inclist  *file;
+       struct inclist  **srcfile;
+{
+       register struct inclist **ip;
+       register struct symtab  *val;
+       register int    i;
+       static int      recurse_lvl = 0;
+
+       if (file->i_defchecked)
+               return(NULL);
+       file->i_defchecked = TRUE;
+       if (val = slookup(symbol, file))
+               debug(1,("%s defined in %s as %s\n", symbol, file->i_file, val->s_value));
+       if (val == NULL && file->i_list)
+               {
+               for (ip = file->i_list, i=0; i < file->i_listlen; i++, ip++)
+                       if (val = fdefined(symbol, *ip, srcfile)) {
+                               break;
+                       }
+               }
+       else if (val != NULL && srcfile != NULL) *srcfile = file;
+       recurse_lvl--;
+       file->i_defchecked = FALSE;
+
+       return(val);
+}
+
+/*
+ * Return type based on if the #if expression evaluates to 0
+ */
+zero_value(exp, filep, file_red)
+       register char   *exp;
+       register struct filepointer *filep;
+       register struct inclist *file_red;
+{
+       if (cppsetup(exp, filep, file_red))
+           return(IFFALSE);
+       else
+           return(IF);
+}
+
+define(def, file)
+       char    *def;
+       struct inclist  *file;
+{
+    char *val;
+
+    /* Separate symbol name and its value */
+    val = def;
+    while (isalnum(*val) || *val == '_')
+       val++;
+    if (*val)
+       *val++ = '\0';
+    while (*val == ' ' || *val == '\t')
+       val++;
+
+    if (!*val)
+       val = "1";
+    define2(def, val, file);
+}
+
+define2(name, val, file)
+       char    *name, *val;
+       struct inclist  *file;
+{
+    int first, last, below;
+    register struct symtab *sp = NULL, *dest;
+
+    /* Make space if it's needed */
+    if (file->i_defs == NULL)
+    {
+       file->i_defs = (struct symtab *)
+                       malloc(sizeof (struct symtab) * SYMTABINC);
+       file->i_deflen = SYMTABINC;
+       file->i_ndefs = 0;
+    }
+    else if (file->i_ndefs == file->i_deflen)
+       file->i_defs = (struct symtab *)
+                       realloc(file->i_defs,
+                           sizeof(struct symtab)*(file->i_deflen+=SYMTABINC));
+
+    if (file->i_defs == NULL)
+       fatalerr("malloc()/realloc() failure in insert_defn()\n");
+
+    below = first = 0;
+    last = file->i_ndefs - 1;
+    while (last >= first)
+    {
+       /* Fast inline binary search */
+       register char *s1;
+       register char *s2;
+       register int middle = (first + last) / 2;
+
+       /* Fast inline strchr() */
+       s1 = name;
+       s2 = file->i_defs[middle].s_name;
+       while (*s1++ == *s2++)
+           if (s2[-1] == '\0') break;
+
+       /* If exact match, set sp and break */
+       if (*--s1 == *--s2) 
+       {
+           sp = file->i_defs + middle;
+           break;
+       }
+
+       /* If name > i_defs[middle] ... */
+       if (*s1 > *s2) 
+       {
+           below = first;
+           first = middle + 1;
+       }
+       /* else ... */
+       else
+       {
+           below = last = middle - 1;
+       }
+    }
+
+    /* Search is done.  If we found an exact match to the symbol name,
+       just replace its s_value */
+    if (sp != NULL)
+    {
+       free(sp->s_value);
+       sp->s_value = copy(val);
+       return;
+    }
+
+    sp = file->i_defs + file->i_ndefs++;
+    dest = file->i_defs + below + 1;
+    while (sp > dest)
+    {
+       *sp = sp[-1];
+       sp--;
+    }
+    sp->s_name = copy(name);
+    sp->s_value = copy(val);
+}
+
+struct symtab *slookup(symbol, file)
+       register char   *symbol;
+       register struct inclist *file;
+{
+       register int first = 0;
+       register int last = file->i_ndefs - 1;
+
+       if (file) while (last >= first)
+       {
+           /* Fast inline binary search */
+           register char *s1;
+           register char *s2;
+           register int middle = (first + last) / 2;
+
+           /* Fast inline strchr() */
+           s1 = symbol;
+           s2 = file->i_defs[middle].s_name;
+           while (*s1++ == *s2++)
+               if (s2[-1] == '\0') break;
+
+           /* If exact match, we're done */
+           if (*--s1 == *--s2) 
+           {
+               return file->i_defs + middle;
+           }
+
+           /* If symbol > i_defs[middle] ... */
+           if (*s1 > *s2) 
+           {
+               first = middle + 1;
+           }
+           /* else ... */
+           else
+           {
+               last = middle - 1;
+           }
+       }
+       return(NULL);
+}
+
+undefine(symbol, file)
+       char    *symbol;
+       register struct inclist *file;
+{
+       register struct symtab *ptr;
+       struct inclist *srcfile;
+       while ((ptr = isdefined(symbol, file, &srcfile)) != NULL)
+       {
+           srcfile->i_ndefs--;
+           for (; ptr < srcfile->i_defs + srcfile->i_ndefs; ptr++)
+               *ptr = ptr[1];
+       }
+}
diff --git a/src/util/makedepend/pr.c b/src/util/makedepend/pr.c
new file mode 100644 (file)
index 0000000..407b1ec
--- /dev/null
@@ -0,0 +1,127 @@
+/* $XConsortium: pr.c,v 1.17 94/04/17 20:10:38 gildea Exp $ */
+/*
+
+Copyright (c) 1993, 1994  X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+*/
+
+#include "def.h"
+
+extern 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;
+
+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_searched) {
+                       newfile->i_searched = TRUE;
+                       content = getfile(newfile->i_file);
+                       find_includes(content, newfile, file_red, 0, failOK);
+                       freefile(content);
+               }
+       }
+}
+
+recursive_pr_include(head, file, base)
+       register struct inclist *head;
+       register char   *file, *base;
+{
+       register int    i;
+
+       if (head->i_marked)
+               return;
+       head->i_marked = TRUE;
+       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);
+}
+
+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_notified)
+               return;
+       ip->i_notified = TRUE;
+       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);
+}