10eb10989Smrg/*
20eb10989Smrg
30eb10989SmrgCopyright (c) 1993, 1994, 1998 The Open Group
40eb10989Smrg
50eb10989SmrgPermission to use, copy, modify, distribute, and sell this software and its
60eb10989Smrgdocumentation for any purpose is hereby granted without fee, provided that
70eb10989Smrgthe above copyright notice appear in all copies and that both that
80eb10989Smrgcopyright notice and this permission notice appear in supporting
90eb10989Smrgdocumentation.
100eb10989Smrg
110eb10989SmrgThe above copyright notice and this permission notice shall be included in
120eb10989Smrgall copies or substantial portions of the Software.
130eb10989Smrg
140eb10989SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
150eb10989SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
160eb10989SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
170eb10989SmrgTHE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
180eb10989SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
190eb10989SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
200eb10989Smrg
210eb10989SmrgExcept as contained in this notice, the name of The Open Group shall not be
220eb10989Smrgused in advertising or otherwise to promote the sale, use or other dealings
230eb10989Smrgin this Software without prior written authorization from The Open Group.
240eb10989Smrg
250eb10989Smrg*/
260eb10989Smrg
270eb10989Smrg#include "def.h"
280eb10989Smrg#ifdef hpux
290eb10989Smrg#define sigvec sigvector
300eb10989Smrg#endif /* hpux */
310eb10989Smrg
320eb10989Smrg#include <signal.h>
330eb10989Smrg#include <stdarg.h>
34fadff096Smrg#include <unistd.h>
350eb10989Smrg
3663165362Smrg#ifdef __sun
37fadff096Smrg#include <sys/utsname.h>
3863165362Smrg#endif
3963165362Smrg
400eb10989Smrg#ifdef DEBUG
41fadff096Smrgint _debugmask;
420eb10989Smrg#endif
430eb10989Smrg
440eb10989Smrg/* #define DEBUG_DUMP */
450eb10989Smrg#ifdef DEBUG_DUMP
460eb10989Smrg#define DBG_PRINT(file, fmt, args)   fprintf(file, fmt, args)
470eb10989Smrg#else
480eb10989Smrg#define DBG_PRINT(file, fmt, args)   /* empty */
490eb10989Smrg#endif
500eb10989Smrg
510eb10989Smrg#define DASH_INC_PRE    "#include \""
520eb10989Smrg#define DASH_INC_POST   "\""
530eb10989Smrg
54fadff096Smrgstatic const char *ProgramName;
550eb10989Smrg
5663165362Smrg#include "imakemdep.h"
570eb10989Smrg
58fadff096Smrgstruct inclist  inclist[MAXFILES],
59fadff096Smrg                *inclistp = inclist,
60fadff096Smrg                *inclistnext = inclist,
61fadff096Smrg                maininclist;
62fadff096Smrg
63fadff096Smrgstatic char     *filelist[MAXFILES];
64fadff096Smrgconst char      *includedirs[MAXDIRS + 1],
65fadff096Smrg                **includedirsnext = includedirs;
66fadff096Smrgchar            *notdotdot[MAXDIRS];
67fadff096Smrgstatic int      cmdinc_count = 0;
68fadff096Smrgstatic char     *cmdinc_list[2 * MAXINCFILES];
69fadff096Smrgconst char      *objprefix = "";
70fadff096Smrgconst char      *objsuffix = OBJSUFFIX;
71fadff096Smrgstatic const char *startat = "# DO NOT DELETE";
72fadff096Smrgint             width = 78;
73fadff096Smrgstatic boolean  append = FALSE;
74fadff096Smrgboolean         printed = FALSE;
75fadff096Smrgboolean         verbose = FALSE;
76fadff096Smrgboolean         show_where_not = FALSE;
77fadff096Smrg
780eb10989Smrg/* Warn on multiple includes of same file */
79fadff096Smrgboolean         warn_multiple = FALSE;
800eb10989Smrg
810eb10989Smrgstatic void setfile_cmdinc(struct filepointer *filep, long count, char **list);
82fadff096Smrgstatic char *base_name(const char *file);
8363165362Smrgstatic void redirect(const char *line, const char *makefile);
840eb10989Smrg
85079e7944Smrgstatic void _X_NORETURN
86fadff096Smrgcatch(int sig)
870eb10989Smrg{
88fadff096Smrg    fflush(stdout);
89fadff096Smrg    fatalerr("got signal %d\n", sig);
900eb10989Smrg}
910eb10989Smrg
92079e7944Smrg#if defined(USG) || (defined(i386) && defined(SYSV)) || defined(WIN32) || defined(Lynx_22) || defined(__CYGWIN__)
930eb10989Smrg#define USGISH
940eb10989Smrg#endif
950eb10989Smrg
960eb10989Smrg#ifndef USGISH
970eb10989Smrg#ifdef X_NOT_POSIX
980eb10989Smrg#define sigaction sigvec
990eb10989Smrg#define sa_handler sv_handler
1000eb10989Smrg#define sa_mask sv_mask
1010eb10989Smrg#define sa_flags sv_flags
1020eb10989Smrg#endif
10363165362Smrgstatic struct sigaction sig_act;
1040eb10989Smrg#endif /* USGISH */
1050eb10989Smrg
1060eb10989Smrgint
1070eb10989Smrgmain(int argc, char *argv[])
1080eb10989Smrg{
109fadff096Smrg    char **fp = filelist;
110fadff096Smrg    const char **incp = includedirs;
111fadff096Smrg    char *p;
112fadff096Smrg    struct inclist *ip;
113fadff096Smrg    char *makefile = NULL;
114fadff096Smrg    struct filepointer *filecontent;
115fadff096Smrg    const char *endmarker = NULL;
116fadff096Smrg    char *defincdir = NULL;
117fadff096Smrg    char **undeflist = NULL;
118fadff096Smrg    int numundefs = 0, i;
119fadff096Smrg
120fadff096Smrg    ProgramName = argv[0];
121fadff096Smrg
122fadff096Smrg    for (const struct predef_symtab *psymp = predefs ;
123fadff096Smrg         psymp->s_name != NULL ; psymp++) {
124fadff096Smrg        define2(psymp->s_name, psymp->s_value, &maininclist);
125fadff096Smrg    }
12663165362Smrg#ifdef __sun
127fadff096Smrg    /* Solaris predefined values that are computed, not hardcoded */
128fadff096Smrg    {
129fadff096Smrg        struct utsname name;
130fadff096Smrg
131fadff096Smrg        if (uname(&name) >= 0) {
132fadff096Smrg            char osrevdef[SYS_NMLN + SYS_NMLN + 5];
133fadff096Smrg
134fadff096Smrg            snprintf(osrevdef, sizeof(osrevdef), "__%s_%s",
135fadff096Smrg                     name.sysname, name.release);
136fadff096Smrg
137fadff096Smrg            for (p = osrevdef; *p != '\0'; p++) {
138fadff096Smrg                if (!isalnum(*p)) {
139fadff096Smrg                    *p = '_';
140fadff096Smrg                }
141fadff096Smrg            }
142fadff096Smrg            define2(osrevdef, "1", &maininclist);
143fadff096Smrg        }
144fadff096Smrg    }
14563165362Smrg#endif
146fadff096Smrg    if (argc == 2 && argv[1][0] == '@') {
147fadff096Smrg        struct stat ast;
148fadff096Smrg        int afd;
149fadff096Smrg        char *args;
150fadff096Smrg        char **nargv;
151fadff096Smrg        int nargc;
152fadff096Smrg        char quotechar = '\0';
153fadff096Smrg
154fadff096Smrg        nargc = 1;
155fadff096Smrg        if ((afd = open(argv[1] + 1, O_RDONLY)) < 0)
156fadff096Smrg            fatalerr("cannot open \"%s\"\n", argv[1] + 1);
157fadff096Smrg        fstat(afd, &ast);
158fadff096Smrg        args = malloc(ast.st_size + 1);
159fadff096Smrg        if (args == NULL)
160fadff096Smrg            fatalerr("malloc()/realloc() failure in %s()\n", __func__);
161fadff096Smrg        if ((ast.st_size = read(afd, args, ast.st_size)) < 0)
162fadff096Smrg            fatalerr("failed to read %s\n", argv[1] + 1);
163fadff096Smrg        args[ast.st_size] = '\0';
164fadff096Smrg        close(afd);
165fadff096Smrg        for (p = args; *p; p++) {
166fadff096Smrg            if (quotechar) {
167fadff096Smrg                if (quotechar == '\\' || (*p == quotechar && p[-1] != '\\'))
168fadff096Smrg                    quotechar = '\0';
169fadff096Smrg                continue;
170fadff096Smrg            }
171fadff096Smrg            switch (*p) {
172fadff096Smrg            case '\\':
173fadff096Smrg            case '"':
174fadff096Smrg            case '\'':
175fadff096Smrg                quotechar = *p;
176fadff096Smrg                break;
177fadff096Smrg            case ' ':
178fadff096Smrg            case '\n':
179fadff096Smrg                *p = '\0';
180fadff096Smrg                if (p > args && p[-1])
181fadff096Smrg                    nargc++;
182fadff096Smrg                break;
183fadff096Smrg            }
184fadff096Smrg        }
185fadff096Smrg        if (p[-1])
186fadff096Smrg            nargc++;
187fadff096Smrg        nargv = mallocarray(nargc, sizeof(char *));
188fadff096Smrg        if (nargv == NULL)
189fadff096Smrg            fatalerr("malloc()/realloc() failure in %s()\n", __func__);
190fadff096Smrg        nargv[0] = argv[0];
191fadff096Smrg        argc = 1;
192fadff096Smrg        for (p = args; argc < nargc; p += strlen(p) + 1)
193fadff096Smrg            if (*p)
194fadff096Smrg                nargv[argc++] = p;
195fadff096Smrg        argv = nargv;
196fadff096Smrg    }
197fadff096Smrg    for (argc--, argv++; argc; argc--, argv++) {
198fadff096Smrg        /* if looking for endmarker then check before parsing */
199fadff096Smrg        if (endmarker && strcmp(endmarker, *argv) == 0) {
200fadff096Smrg            endmarker = NULL;
201fadff096Smrg            continue;
202fadff096Smrg        }
203fadff096Smrg        if (**argv != '-') {
204fadff096Smrg            /* treat +thing as an option for C++ */
205fadff096Smrg            if (endmarker && **argv == '+')
206fadff096Smrg                continue;
207fadff096Smrg            if (fp >= filelist + MAXFILES) {
208fadff096Smrg                fatalerr("Too many source files. Limit is %i files.\n",
209fadff096Smrg                         MAXFILES);
210fadff096Smrg            }
211fadff096Smrg            *fp++ = argv[0];
212fadff096Smrg            continue;
213fadff096Smrg        }
214fadff096Smrg        switch (argv[0][1]) {
215fadff096Smrg        case '-':
216fadff096Smrg            endmarker = &argv[0][2];
217fadff096Smrg            if (endmarker[0] == '\0')
218fadff096Smrg                endmarker = "--";
219fadff096Smrg            break;
220fadff096Smrg        case 'D':
221fadff096Smrg            if (argv[0][2] == '\0') {
222fadff096Smrg                if (argc < 2)
223fadff096Smrg                    fatalerr("Missing argument for -D\n");
224fadff096Smrg                argv++;
225fadff096Smrg                argc--;
226fadff096Smrg            }
227fadff096Smrg            for (p = argv[0] + 2; *p; p++)
228fadff096Smrg                if (*p == '=') {
229fadff096Smrg                    *p = ' ';
230fadff096Smrg                    break;
231fadff096Smrg                }
232fadff096Smrg            define(argv[0] + 2, &maininclist);
233fadff096Smrg            break;
234fadff096Smrg        case 'I':
235fadff096Smrg            if (incp >= includedirs + MAXDIRS)
236fadff096Smrg                fatalerr("Too many -I flags.\n");
237fadff096Smrg            *incp++ = argv[0] + 2;
238fadff096Smrg            if (**(incp - 1) == '\0') {
239fadff096Smrg                if (argc < 2)
240fadff096Smrg                    fatalerr("Missing argument for -I\n");
241fadff096Smrg                *(incp - 1) = *(++argv);
242fadff096Smrg                argc--;
243fadff096Smrg            }
244fadff096Smrg            break;
245fadff096Smrg        case 'U':
246fadff096Smrg            /* Undef's override all -D's so save them up */
247fadff096Smrg            numundefs++;
248fadff096Smrg            if (numundefs == 1)
249fadff096Smrg                undeflist = malloc(sizeof(char *));
250fadff096Smrg            else
251fadff096Smrg                undeflist = reallocarray(undeflist, numundefs, sizeof(char *));
252fadff096Smrg            if (undeflist == NULL)
253fadff096Smrg                fatalerr("malloc()/realloc() failure in %s()\n", __func__);
254fadff096Smrg            if (argv[0][2] == '\0') {
255fadff096Smrg                if (argc < 2)
256fadff096Smrg                    fatalerr("Missing argument for -U\n");
257fadff096Smrg                argv++;
258fadff096Smrg                argc--;
259fadff096Smrg            }
260fadff096Smrg            undeflist[numundefs - 1] = argv[0] + 2;
261fadff096Smrg            break;
262fadff096Smrg        case 'Y':
263fadff096Smrg            defincdir = argv[0] + 2;
264fadff096Smrg            break;
265fadff096Smrg            /* do not use if endmarker processing */
266fadff096Smrg        case 'a':
267fadff096Smrg            if (endmarker)
268fadff096Smrg                break;
269fadff096Smrg            append = TRUE;
270fadff096Smrg            break;
271fadff096Smrg        case 'w':
272fadff096Smrg            if (endmarker)
273fadff096Smrg                break;
274fadff096Smrg            if (argv[0][2] == '\0') {
275fadff096Smrg                if (argc < 2)
276fadff096Smrg                    fatalerr("Missing argument for -w\n");
277fadff096Smrg                argv++;
278fadff096Smrg                argc--;
279fadff096Smrg                width = atoi(argv[0]);
280fadff096Smrg            }
281fadff096Smrg            else
282fadff096Smrg                width = atoi(argv[0] + 2);
283fadff096Smrg            break;
284fadff096Smrg        case 'o':
285fadff096Smrg            if (endmarker)
286fadff096Smrg                break;
287fadff096Smrg            if (argv[0][2] == '\0') {
288fadff096Smrg                if (argc < 2)
289fadff096Smrg                    fatalerr("Missing argument for -o\n");
290fadff096Smrg                argv++;
291fadff096Smrg                argc--;
292fadff096Smrg                objsuffix = argv[0];
293fadff096Smrg            }
294fadff096Smrg            else
295fadff096Smrg                objsuffix = argv[0] + 2;
296fadff096Smrg            break;
297fadff096Smrg        case 'p':
298fadff096Smrg            if (endmarker)
299fadff096Smrg                break;
300fadff096Smrg            if (argv[0][2] == '\0') {
301fadff096Smrg                if (argc < 2)
302fadff096Smrg                    fatalerr("Missing argument for -p\n");
303fadff096Smrg                argv++;
304fadff096Smrg                argc--;
305fadff096Smrg                objprefix = argv[0];
306fadff096Smrg            }
307fadff096Smrg            else
308fadff096Smrg                objprefix = argv[0] + 2;
309fadff096Smrg            break;
310fadff096Smrg        case 'v':
311fadff096Smrg            if (endmarker)
312fadff096Smrg                break;
313fadff096Smrg            verbose = TRUE;
3140eb10989Smrg#ifdef DEBUG
315fadff096Smrg            if (argv[0][2])
316fadff096Smrg                _debugmask = atoi(argv[0] + 2);
3170eb10989Smrg#endif
318fadff096Smrg            break;
319fadff096Smrg        case 's':
320fadff096Smrg            if (endmarker)
321fadff096Smrg                break;
322fadff096Smrg            startat = argv[0] + 2;
323fadff096Smrg            if (*startat == '\0') {
324fadff096Smrg                if (argc < 2)
325fadff096Smrg                    fatalerr("Missing argument for -s\n");
326fadff096Smrg                startat = *(++argv);
327fadff096Smrg                argc--;
328fadff096Smrg            }
329fadff096Smrg            if (*startat != '#')
330fadff096Smrg                fatalerr("-s flag's value should start %s\n", "with '#'.");
331fadff096Smrg            break;
332fadff096Smrg        case 'f':
333fadff096Smrg            if (endmarker)
334fadff096Smrg                break;
335fadff096Smrg            makefile = argv[0] + 2;
336fadff096Smrg            if (*makefile == '\0') {
337fadff096Smrg                if (argc < 2)
338fadff096Smrg                    fatalerr("Missing argument for -f\n");
339fadff096Smrg                makefile = *(++argv);
340fadff096Smrg                argc--;
341fadff096Smrg            }
342fadff096Smrg            break;
343fadff096Smrg
344fadff096Smrg        case 'm':
345fadff096Smrg            warn_multiple = TRUE;
346fadff096Smrg            break;
347fadff096Smrg
348fadff096Smrg            /* Ignore -O, -g so we can just pass ${CFLAGS} to
349fadff096Smrg               makedepend
350fadff096Smrg             */
351fadff096Smrg        case 'O':
352fadff096Smrg        case 'g':
353fadff096Smrg            break;
354fadff096Smrg        case 'i':
355fadff096Smrg            if (strcmp(&argv[0][1], "include") == 0) {
356fadff096Smrg                char *buf;
357fadff096Smrg
358fadff096Smrg                if (argc < 2)
359fadff096Smrg                    fatalerr("option -include is missing its parameter\n");
360fadff096Smrg                if (cmdinc_count >= MAXINCFILES)
361fadff096Smrg                    fatalerr("Too many -include flags.\n");
362fadff096Smrg                argc--;
363fadff096Smrg                argv++;
364fadff096Smrg                buf = malloc(strlen(DASH_INC_PRE) +
365fadff096Smrg                             strlen(argv[0]) + strlen(DASH_INC_POST) + 1);
366fadff096Smrg                if (!buf)
367fadff096Smrg                    fatalerr("out of memory at -include string\n");
368fadff096Smrg                cmdinc_list[2 * cmdinc_count + 0] = argv[0];
369fadff096Smrg                cmdinc_list[2 * cmdinc_count + 1] = buf;
370fadff096Smrg                cmdinc_count++;
371fadff096Smrg                break;
372fadff096Smrg            }
373fadff096Smrg            /* intentional fall through */
374fadff096Smrg        default:
375fadff096Smrg            if (endmarker)
376fadff096Smrg                break;
377fadff096Smrg            /*              fatalerr("unknown opt = %s\n", argv[0]); */
378fadff096Smrg            warning("ignoring option %s\n", argv[0]);
379fadff096Smrg        }
380fadff096Smrg    }
381fadff096Smrg    /* Now do the undefs from the command line */
382fadff096Smrg    for (i = 0; i < numundefs; i++)
383fadff096Smrg        undefine(undeflist[i], &maininclist);
384fadff096Smrg    if (numundefs > 0)
385fadff096Smrg        free(undeflist);
386fadff096Smrg
387fadff096Smrg    if (!defincdir) {
3880eb10989Smrg#ifdef PREINCDIR
389fadff096Smrg        if (incp >= includedirs + MAXDIRS)
390fadff096Smrg            fatalerr("Too many -I flags.\n");
391fadff096Smrg        *incp++ = PREINCDIR;
3920eb10989Smrg#endif
393fadff096Smrg        if (incp >= includedirs + MAXDIRS)
394fadff096Smrg            fatalerr("Too many -I flags.\n");
395fadff096Smrg        *incp++ = INCLUDEDIR;
3960eb10989Smrg
3970eb10989Smrg#ifdef EXTRAINCDIR
398fadff096Smrg        if (incp >= includedirs + MAXDIRS)
399fadff096Smrg            fatalerr("Too many -I flags.\n");
400fadff096Smrg        *incp++ = EXTRAINCDIR;
4010eb10989Smrg#endif
4020eb10989Smrg
4030eb10989Smrg#ifdef POSTINCDIR
404fadff096Smrg        if (incp >= includedirs + MAXDIRS)
405fadff096Smrg            fatalerr("Too many -I flags.\n");
406fadff096Smrg        *incp++ = POSTINCDIR;
4070eb10989Smrg#endif
408fadff096Smrg    }
409fadff096Smrg    else if (*defincdir) {
410fadff096Smrg        if (incp >= includedirs + MAXDIRS)
411fadff096Smrg            fatalerr("Too many -I flags.\n");
412fadff096Smrg        *incp++ = defincdir;
413fadff096Smrg    }
4140eb10989Smrg
415fadff096Smrg    redirect(startat, makefile);
4160eb10989Smrg
417fadff096Smrg    /*
418fadff096Smrg     * catch signals.
419fadff096Smrg     */
4200eb10989Smrg#ifdef USGISH
4210eb10989Smrg/*  should really reset SIGINT to SIG_IGN if it was.  */
4220eb10989Smrg#ifdef SIGHUP
423fadff096Smrg    signal(SIGHUP, catch);
4240eb10989Smrg#endif
425fadff096Smrg    signal(SIGINT, catch);
4260eb10989Smrg#ifdef SIGQUIT
427fadff096Smrg    signal(SIGQUIT, catch);
4280eb10989Smrg#endif
429fadff096Smrg    signal(SIGILL, catch);
4300eb10989Smrg#ifdef SIGBUS
431fadff096Smrg    signal(SIGBUS, catch);
4320eb10989Smrg#endif
433fadff096Smrg    signal(SIGSEGV, catch);
4340eb10989Smrg#ifdef SIGSYS
435fadff096Smrg    signal(SIGSYS, catch);
4360eb10989Smrg#endif
4370eb10989Smrg#else
438fadff096Smrg    sig_act.sa_handler = catch;
4390eb10989Smrg#if defined(_POSIX_SOURCE) || !defined(X_NOT_POSIX)
440fadff096Smrg    sigemptyset(&sig_act.sa_mask);
441fadff096Smrg    sigaddset(&sig_act.sa_mask, SIGINT);
442fadff096Smrg    sigaddset(&sig_act.sa_mask, SIGQUIT);
4430eb10989Smrg#ifdef SIGBUS
444fadff096Smrg    sigaddset(&sig_act.sa_mask, SIGBUS);
4450eb10989Smrg#endif
446fadff096Smrg    sigaddset(&sig_act.sa_mask, SIGILL);
447fadff096Smrg    sigaddset(&sig_act.sa_mask, SIGSEGV);
448fadff096Smrg    sigaddset(&sig_act.sa_mask, SIGHUP);
449fadff096Smrg    sigaddset(&sig_act.sa_mask, SIGPIPE);
4500eb10989Smrg#ifdef SIGSYS
451fadff096Smrg    sigaddset(&sig_act.sa_mask, SIGSYS);
4520eb10989Smrg#endif
4530eb10989Smrg#else
454fadff096Smrg    sig_act.sa_mask = ((1 << (SIGINT - 1))
455fadff096Smrg                       | (1 << (SIGQUIT - 1))
4560eb10989Smrg#ifdef SIGBUS
457fadff096Smrg                       | (1 << (SIGBUS - 1))
4580eb10989Smrg#endif
459fadff096Smrg                       | (1 << (SIGILL - 1))
460fadff096Smrg                       | (1 << (SIGSEGV - 1))
461fadff096Smrg                       | (1 << (SIGHUP - 1))
462fadff096Smrg                       | (1 << (SIGPIPE - 1))
4630eb10989Smrg#ifdef SIGSYS
464fadff096Smrg                       | (1 << (SIGSYS - 1))
4650eb10989Smrg#endif
466fadff096Smrg        );
467fadff096Smrg#endif                          /* _POSIX_SOURCE */
468fadff096Smrg    sig_act.sa_flags = 0;
469fadff096Smrg    sigaction(SIGHUP, &sig_act, (struct sigaction *) 0);
470fadff096Smrg    sigaction(SIGINT, &sig_act, (struct sigaction *) 0);
471fadff096Smrg    sigaction(SIGQUIT, &sig_act, (struct sigaction *) 0);
472fadff096Smrg    sigaction(SIGILL, &sig_act, (struct sigaction *) 0);
4730eb10989Smrg#ifdef SIGBUS
474fadff096Smrg    sigaction(SIGBUS, &sig_act, (struct sigaction *) 0);
4750eb10989Smrg#endif
476fadff096Smrg    sigaction(SIGSEGV, &sig_act, (struct sigaction *) 0);
4770eb10989Smrg#ifdef SIGSYS
478fadff096Smrg    sigaction(SIGSYS, &sig_act, (struct sigaction *) 0);
4790eb10989Smrg#endif
480fadff096Smrg#endif                          /* USGISH */
481fadff096Smrg
482fadff096Smrg    /*
483fadff096Smrg     * now peruse through the list of files.
484fadff096Smrg     */
485fadff096Smrg    for (fp = filelist; *fp; fp++) {
486fadff096Smrg        DBG_PRINT(stderr, "file: %s\n", *fp);
487fadff096Smrg        filecontent = getfile(*fp);
488fadff096Smrg        setfile_cmdinc(filecontent, cmdinc_count, cmdinc_list);
489fadff096Smrg        ip = newinclude(*fp, NULL, NULL);
490fadff096Smrg
491fadff096Smrg        find_includes(filecontent, ip, ip, 0, FALSE);
492fadff096Smrg        freefile(filecontent);
493fadff096Smrg        recursive_pr_include(ip, ip->i_file, base_name(*fp));
494fadff096Smrg        inc_clean();
495fadff096Smrg    }
496fadff096Smrg    if (printed)
497fadff096Smrg        printf("\n");
498fadff096Smrg    return 0;
4990eb10989Smrg}
5000eb10989Smrg
5010eb10989Smrgstruct filepointer *
50263165362Smrggetfile(const char *file)
5030eb10989Smrg{
504fadff096Smrg    int fd;
505fadff096Smrg    struct filepointer *content;
506fadff096Smrg    struct stat st;
507fadff096Smrg
508fadff096Smrg    content = malloc(sizeof(struct filepointer));
509fadff096Smrg    if (content == NULL)
510fadff096Smrg        fatalerr("malloc()/realloc() failure in %s()\n", __func__);
511fadff096Smrg    content->f_name = file;
512fadff096Smrg    if ((fd = open(file, O_RDONLY)) < 0) {
513fadff096Smrg        warning("cannot open \"%s\"\n", file);
514fadff096Smrg        content->f_p = content->f_base = content->f_end = malloc(1);
515fadff096Smrg        if (content->f_p == NULL)
516fadff096Smrg            fatalerr("malloc()/realloc() failure in %s()\n", __func__);
517fadff096Smrg        *content->f_p = '\0';
518fadff096Smrg        return (content);
519fadff096Smrg    }
520fadff096Smrg    fstat(fd, &st);
521fadff096Smrg    content->f_base = malloc(st.st_size + 1);
522fadff096Smrg    if (content->f_base == NULL)
523fadff096Smrg        fatalerr("malloc()/realloc() failure in %s()\n", __func__);
524fadff096Smrg    if ((st.st_size = read(fd, content->f_base, st.st_size)) < 0)
525fadff096Smrg        fatalerr("failed to read %s\n", file);
526fadff096Smrg    close(fd);
527fadff096Smrg    content->f_len = st.st_size + 1;
528fadff096Smrg    content->f_p = content->f_base;
529fadff096Smrg    content->f_end = content->f_base + st.st_size;
530fadff096Smrg    *content->f_end = '\0';
531fadff096Smrg    content->f_line = 0;
532fadff096Smrg    content->cmdinc_count = 0;
533fadff096Smrg    content->cmdinc_list = NULL;
534fadff096Smrg    content->cmdinc_line = 0;
535fadff096Smrg    return (content);
5360eb10989Smrg}
5370eb10989Smrg
5380eb10989Smrgvoid
539fadff096Smrgsetfile_cmdinc(struct filepointer *filep, long count, char **list)
5400eb10989Smrg{
541fadff096Smrg    filep->cmdinc_count = count;
542fadff096Smrg    filep->cmdinc_list = list;
543fadff096Smrg    filep->cmdinc_line = 0;
5440eb10989Smrg}
5450eb10989Smrg
5460eb10989Smrgvoid
5470eb10989Smrgfreefile(struct filepointer *fp)
5480eb10989Smrg{
549fadff096Smrg    free(fp->f_base);
550fadff096Smrg    free(fp);
5510eb10989Smrg}
5520eb10989Smrg
5530eb10989Smrgint
554fadff096Smrgmatch(const char *str, const char *const *list)
5550eb10989Smrg{
556fadff096Smrg    int i;
5570eb10989Smrg
558fadff096Smrg    for (i = 0; *list; i++, list++)
559fadff096Smrg        if (strcmp(str, *list) == 0)
560fadff096Smrg            return (i);
561fadff096Smrg    return (-1);
5620eb10989Smrg}
5630eb10989Smrg
5640eb10989Smrg/*
5650eb10989Smrg * Get the next line.  We only return lines beginning with '#' since that
5660eb10989Smrg * is all this program is ever interested in.
5670eb10989Smrg */
568fadff096Smrgchar *
569fadff096Smrggetnextline(struct filepointer *filep)
5700eb10989Smrg{
571fadff096Smrg    char *p,                    /* walking pointer */
572fadff096Smrg         *eof,                  /* end of file pointer */
573fadff096Smrg         *bol;                  /* beginning of line pointer */
574fadff096Smrg    long  lineno;               /* line number */
575fadff096Smrg
576fadff096Smrg    /*
577fadff096Smrg     * Fake the "-include" line files in form of #include to the
578fadff096Smrg     * start of each file.
579fadff096Smrg     */
580fadff096Smrg    if (filep->cmdinc_line < filep->cmdinc_count) {
581fadff096Smrg        char *inc = filep->cmdinc_list[2 * filep->cmdinc_line + 0];
582fadff096Smrg        char *buf = filep->cmdinc_list[2 * filep->cmdinc_line + 1];
583fadff096Smrg
584fadff096Smrg        filep->cmdinc_line++;
585fadff096Smrg        sprintf(buf, "%s%s%s", DASH_INC_PRE, inc, DASH_INC_POST);
586fadff096Smrg        DBG_PRINT(stderr, "%s\n", buf);
587fadff096Smrg        return (buf);
588fadff096Smrg    }
589fadff096Smrg
590fadff096Smrg    p = filep->f_p;
591fadff096Smrg    eof = filep->f_end;
592fadff096Smrg    if (p >= eof)
593fadff096Smrg        return ((char *) NULL);
594fadff096Smrg    lineno = filep->f_line;
595fadff096Smrg
596fadff096Smrg    for (bol = p--; ++p < eof;) {
597fadff096Smrg        if ((bol == p) && ((*p == ' ') || (*p == '\t'))) {
598fadff096Smrg            /* Consume leading white-spaces for this line */
599fadff096Smrg            while (((p + 1) < eof) && ((*p == ' ') || (*p == '\t'))) {
600fadff096Smrg                p++;
601fadff096Smrg                bol++;
602fadff096Smrg            }
603fadff096Smrg        }
604fadff096Smrg
605fadff096Smrg        if (*p == '/' && (p + 1) < eof && *(p + 1) == '*') {
606fadff096Smrg            /* Consume C comments */
607fadff096Smrg            *(p++) = ' ';
608fadff096Smrg            *(p++) = ' ';
609fadff096Smrg            while (p < eof && *p) {
610fadff096Smrg                if (*p == '*' && (p + 1) < eof && *(p + 1) == '/') {
611fadff096Smrg                    *(p++) = ' ';
612fadff096Smrg                    *(p++) = ' ';
613fadff096Smrg                    break;
614fadff096Smrg                }
615fadff096Smrg                if (*p == '\n')
616fadff096Smrg                    lineno++;
617fadff096Smrg                *(p++) = ' ';
618fadff096Smrg            }
619fadff096Smrg            --p;
620fadff096Smrg        }
621fadff096Smrg        else if (*p == '/' && (p + 1) < eof && *(p + 1) == '/') {
622fadff096Smrg            /* Consume C++ comments */
623fadff096Smrg            *(p++) = ' ';
624fadff096Smrg            *(p++) = ' ';
625fadff096Smrg            while (p < eof && *p) {
626fadff096Smrg                if (*p == '\\' && (p + 1) < eof && *(p + 1) == '\n') {
627fadff096Smrg                    *(p++) = ' ';
628fadff096Smrg                    lineno++;
629fadff096Smrg                }
630fadff096Smrg                else if (*p == '?' && (p + 3) < eof &&
631fadff096Smrg                         *(p + 1) == '?' &&
632fadff096Smrg                         *(p + 2) == '/' && *(p + 3) == '\n') {
633fadff096Smrg                    *(p++) = ' ';
634fadff096Smrg                    *(p++) = ' ';
635fadff096Smrg                    *(p++) = ' ';
636fadff096Smrg                    lineno++;
637fadff096Smrg                }
638fadff096Smrg                else if (*p == '\n')
639fadff096Smrg                    break;      /* to process end of line */
640fadff096Smrg                *(p++) = ' ';
641fadff096Smrg            }
642fadff096Smrg            --p;
643fadff096Smrg        }
644fadff096Smrg        else if (*p == '\\' && (p + 1) < eof && *(p + 1) == '\n') {
645fadff096Smrg            /* Consume backslash line terminations */
646fadff096Smrg            *(p++) = ' ';
647fadff096Smrg            *p = ' ';
648fadff096Smrg            lineno++;
649fadff096Smrg        }
650fadff096Smrg        else if (*p == '?' && (p + 3) < eof &&
651fadff096Smrg                 *(p + 1) == '?' && *(p + 2) == '/' && *(p + 3) == '\n') {
652fadff096Smrg            /* Consume trigraph'ed backslash line terminations */
653fadff096Smrg            *(p++) = ' ';
654fadff096Smrg            *(p++) = ' ';
655fadff096Smrg            *(p++) = ' ';
656fadff096Smrg            *p = ' ';
657fadff096Smrg            lineno++;
658fadff096Smrg        }
659fadff096Smrg        else if (*p == '\n') {
660fadff096Smrg            lineno++;
661fadff096Smrg            if (*bol == '#') {
662fadff096Smrg                char *cp;
663fadff096Smrg
664fadff096Smrg                *(p++) = '\0';
665fadff096Smrg                /* punt lines with just # (yacc generated) */
666fadff096Smrg                for (cp = bol + 1; *cp && (*cp == ' ' || *cp == '\t'); cp++);
667fadff096Smrg                if (*cp)
668fadff096Smrg                    goto done;
669fadff096Smrg                --p;
670fadff096Smrg            }
671fadff096Smrg            bol = p + 1;
672fadff096Smrg        }
673fadff096Smrg    }
674fadff096Smrg    if (*bol != '#')
675fadff096Smrg        bol = NULL;
676fadff096Smrg done:
677fadff096Smrg    filep->f_p = p;
678fadff096Smrg    filep->f_line = lineno;
6790eb10989Smrg#ifdef DEBUG_DUMP
680fadff096Smrg    if (bol)
681fadff096Smrg        DBG_PRINT(stderr, "%s\n", bol);
6820eb10989Smrg#endif
683fadff096Smrg    return (bol);
6840eb10989Smrg}
6850eb10989Smrg
6860eb10989Smrg/*
6870eb10989Smrg * Strip the file name down to what we want to see in the Makefile.
6880eb10989Smrg * It will have objprefix and objsuffix around it.
6890eb10989Smrg */
690fadff096Smrgchar *
691fadff096Smrgbase_name(const char *in_file)
6920eb10989Smrg{
693fadff096Smrg    char *p;
694fadff096Smrg    char *file = strdup(in_file);
695fadff096Smrg
696fadff096Smrg    if (file == NULL)
697fadff096Smrg        fatalerr("strdup() failure in %s()\n", __func__);
698fadff096Smrg
699fadff096Smrg    p = strrchr(file, '.');
7000eb10989Smrg
701fadff096Smrg    if (p != NULL)
702fadff096Smrg        *p = '\0';
703fadff096Smrg    return (file);
7040eb10989Smrg}
7050eb10989Smrg
706079e7944Smrg#ifndef HAVE_RENAME
707fadff096Smrgint
708fadff096Smrgrename(char *from, char *to)
7090eb10989Smrg{
710fadff096Smrg    (void) unlink(to);
711fadff096Smrg    if (link(from, to) == 0) {
712fadff096Smrg        unlink(from);
713fadff096Smrg        return 0;
714fadff096Smrg    }
715fadff096Smrg    else {
716fadff096Smrg        return -1;
7170eb10989Smrg    }
7180eb10989Smrg}
719fadff096Smrg#endif                          /* !HAVE_RENAME */
7200eb10989Smrg
72163165362Smrgstatic void
72263165362Smrgredirect(const char *line, const char *makefile)
7230eb10989Smrg{
724fadff096Smrg    struct stat st;
725fadff096Smrg    FILE        *fdin, *fdout;
726fadff096Smrg    char        backup[BUFSIZ],
727fadff096Smrg                buf[BUFSIZ];
728fadff096Smrg    boolean     found = FALSE;
729fadff096Smrg    size_t      len;
730fadff096Smrg
731fadff096Smrg    /*
732fadff096Smrg     * if makefile is "-" then let it pour onto stdout.
733fadff096Smrg     */
734fadff096Smrg    if (makefile && *makefile == '-' && *(makefile + 1) == '\0') {
735fadff096Smrg        puts(line);
736fadff096Smrg        return;
737fadff096Smrg    }
738fadff096Smrg
739fadff096Smrg    /*
740fadff096Smrg     * use a default if makefile is not specified.
741fadff096Smrg     */
742fadff096Smrg    if (!makefile) {
743fadff096Smrg        if (stat("Makefile", &st) == 0)
744fadff096Smrg            makefile = "Makefile";
745fadff096Smrg        else if (stat("makefile", &st) == 0)
746fadff096Smrg            makefile = "makefile";
747fadff096Smrg        else
748fadff096Smrg            fatalerr("[mM]akefile is not present\n");
749fadff096Smrg    }
750fadff096Smrg    else {
751fadff096Smrg        if (stat(makefile, &st) != 0)
752fadff096Smrg            fatalerr("\"%s\" is not present\n", makefile);
753fadff096Smrg    }
754fadff096Smrg
755fadff096Smrg    snprintf(backup, sizeof(backup), "%s.bak", makefile);
756fadff096Smrg    unlink(backup);
757fadff096Smrg
758fadff096Smrg    /* rename() won't work on WIN32, CYGWIN, or CIFS if src file is open */
759fadff096Smrg    if (rename(makefile, backup) < 0)
760fadff096Smrg        fatalerr("cannot rename %s to %s\n", makefile, backup);
761fadff096Smrg    if ((fdin = fopen(backup, "r")) == NULL) {
762fadff096Smrg        if (rename(backup, makefile) < 0)
763fadff096Smrg            warning("renamed %s to %s, but can't move it back\n",
764fadff096Smrg                    makefile, backup);
765fadff096Smrg        fatalerr("cannot open \"%s\"\n", makefile);
766fadff096Smrg    }
767fadff096Smrg    if ((fdout = freopen(makefile, "w", stdout)) == NULL)
768fadff096Smrg        fatalerr("cannot open \"%s\"\n", backup);
769fadff096Smrg    len = strlen(line);
770fadff096Smrg    while (!found && fgets(buf, BUFSIZ, fdin)) {
771fadff096Smrg        if (*buf == '#' && strncmp(line, buf, len) == 0)
772fadff096Smrg            found = TRUE;
773fadff096Smrg        fputs(buf, fdout);
774fadff096Smrg    }
775fadff096Smrg    if (!found) {
776fadff096Smrg        if (verbose)
777fadff096Smrg            warning("Adding new delimiting line \"%s\" and dependencies...\n",
778fadff096Smrg                    line);
779fadff096Smrg        puts(line);             /* same as fputs(fdout); but with newline */
780fadff096Smrg    }
781fadff096Smrg    else if (append) {
782fadff096Smrg        while (fgets(buf, BUFSIZ, fdin)) {
783fadff096Smrg            fputs(buf, fdout);
784fadff096Smrg        }
785fadff096Smrg    }
786fadff096Smrg    fclose(fdin);
787fadff096Smrg    fflush(fdout);
7880eb10989Smrg#ifndef HAVE_FCHMOD
789fadff096Smrg    chmod(makefile, st.st_mode);
7900eb10989Smrg#else
791fadff096Smrg    fchmod(fileno(fdout), st.st_mode);
792fadff096Smrg#endif                          /* HAVE_FCHMOD */
7930eb10989Smrg}
7940eb10989Smrg
7950eb10989Smrgvoid
79663165362Smrgfatalerr(const char *msg, ...)
7970eb10989Smrg{
798fadff096Smrg    va_list args;
799fadff096Smrg
800fadff096Smrg    fprintf(stderr, "%s: error:  ", ProgramName);
801fadff096Smrg    va_start(args, msg);
802fadff096Smrg    vfprintf(stderr, msg, args);
803fadff096Smrg    va_end(args);
804fadff096Smrg    exit(1);
8050eb10989Smrg}
8060eb10989Smrg
8070eb10989Smrgvoid
80863165362Smrgwarning(const char *msg, ...)
8090eb10989Smrg{
810fadff096Smrg    va_list args;
811fadff096Smrg
812fadff096Smrg    fprintf(stderr, "%s: warning:  ", ProgramName);
813fadff096Smrg    va_start(args, msg);
814fadff096Smrg    vfprintf(stderr, msg, args);
815fadff096Smrg    va_end(args);
8160eb10989Smrg}
8170eb10989Smrg
8180eb10989Smrgvoid
81963165362Smrgwarning1(const char *msg, ...)
8200eb10989Smrg{
821fadff096Smrg    va_list args;
822fadff096Smrg
823fadff096Smrg    va_start(args, msg);
824fadff096Smrg    vfprintf(stderr, msg, args);
825fadff096Smrg    va_end(args);
8260eb10989Smrg}
827