main.c revision 079e7944
1/*
2
3Copyright (c) 1993, 1994, 1998 The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25*/
26
27#include "def.h"
28#ifdef hpux
29#define sigvec sigvector
30#endif /* hpux */
31
32#ifdef X_POSIX_C_SOURCE
33#define _POSIX_C_SOURCE X_POSIX_C_SOURCE
34#include <signal.h>
35#undef _POSIX_C_SOURCE
36#else
37#if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE)
38#include <signal.h>
39#else
40#define _POSIX_SOURCE
41#include <signal.h>
42#undef _POSIX_SOURCE
43#endif
44#endif
45
46#include <stdarg.h>
47
48#ifdef __sun
49# include <sys/utsname.h>
50#endif
51
52#ifdef DEBUG
53int	_debugmask;
54#endif
55
56/* #define DEBUG_DUMP */
57#ifdef DEBUG_DUMP
58#define DBG_PRINT(file, fmt, args)   fprintf(file, fmt, args)
59#else
60#define DBG_PRINT(file, fmt, args)   /* empty */
61#endif
62
63#define DASH_INC_PRE    "#include \""
64#define DASH_INC_POST   "\""
65
66const char *ProgramName;
67
68const char * const directives[] = {
69	"if",
70	"ifdef",
71	"ifndef",
72	"else",
73	"endif",
74	"define",
75	"undef",
76	"include",
77	"line",
78	"pragma",
79	"error",
80	"ident",
81	"sccs",
82	"elif",
83	"eject",
84	"warning",
85	"include_next",
86	NULL
87};
88
89#include "imakemdep.h"
90
91struct	inclist inclist[ MAXFILES ],
92		*inclistp = inclist,
93		*inclistnext = inclist,
94		maininclist;
95
96static char	*filelist[ MAXFILES ];
97const char	*includedirs[ MAXDIRS + 1 ],
98		**includedirsnext = includedirs;
99char		*notdotdot[ MAXDIRS ];
100static int	cmdinc_count = 0;
101static char	*cmdinc_list[ 2 * MAXINCFILES ];
102const char	*objprefix = "";
103const char	*objsuffix = OBJSUFFIX;
104static const char	*startat = "# DO NOT DELETE";
105int		width = 78;
106static boolean	append = FALSE;
107boolean		printed = FALSE;
108boolean		verbose = FALSE;
109boolean		show_where_not = FALSE;
110/* Warn on multiple includes of same file */
111boolean 	warn_multiple = FALSE;
112
113static void setfile_cmdinc(struct filepointer *filep, long count, char **list);
114static void redirect(const char *line, const char *makefile);
115
116static void _X_NORETURN
117catch (int sig)
118{
119	fflush (stdout);
120	fatalerr ("got signal %d\n", sig);
121}
122
123#if defined(USG) || (defined(i386) && defined(SYSV)) || defined(WIN32) || defined(Lynx_22) || defined(__CYGWIN__)
124#define USGISH
125#endif
126
127#ifndef USGISH
128#ifdef X_NOT_POSIX
129#define sigaction sigvec
130#define sa_handler sv_handler
131#define sa_mask sv_mask
132#define sa_flags sv_flags
133#endif
134static struct sigaction sig_act;
135#endif /* USGISH */
136
137int
138main(int argc, char *argv[])
139{
140	char	**fp = filelist;
141	const char	**incp = includedirs;
142	char	*p;
143	struct inclist	*ip;
144	char	*makefile = NULL;
145	struct filepointer	*filecontent;
146	const struct symtab *psymp = predefs;
147	const char *endmarker = NULL;
148	char *defincdir = NULL;
149	char **undeflist = NULL;
150	int numundefs = 0, i;
151
152	ProgramName = argv[0];
153
154	while (psymp->s_name)
155	{
156	    define2(psymp->s_name, psymp->s_value, &maininclist);
157	    psymp++;
158	}
159#ifdef __sun
160	/* Solaris predefined values that are computed, not hardcoded */
161	{
162	    struct utsname name;
163
164	    if (uname(&name) >= 0) {
165		char osrevdef[SYS_NMLN + SYS_NMLN + 5];
166		snprintf(osrevdef, sizeof(osrevdef), "__%s_%s",
167			 name.sysname, name.release);
168
169		for (p = osrevdef; *p != '\0'; p++) {
170		    if (!isalnum(*p)) {
171			*p = '_';
172		    }
173		}
174		define2(osrevdef, "1", &maininclist);
175	    }
176	}
177#endif
178	if (argc == 2 && argv[1][0] == '@') {
179	    struct stat ast;
180	    int afd;
181	    char *args;
182	    char **nargv;
183	    int nargc;
184	    char quotechar = '\0';
185
186	    nargc = 1;
187	    if ((afd = open(argv[1]+1, O_RDONLY)) < 0)
188		fatalerr("cannot open \"%s\"\n", argv[1]+1);
189	    fstat(afd, &ast);
190	    args = malloc(ast.st_size + 1);
191	    if ((ast.st_size = read(afd, args, ast.st_size)) < 0)
192		fatalerr("failed to read %s\n", argv[1]+1);
193	    args[ast.st_size] = '\0';
194	    close(afd);
195	    for (p = args; *p; p++) {
196		if (quotechar) {
197		    if (quotechar == '\\' ||
198			(*p == quotechar && p[-1] != '\\'))
199			quotechar = '\0';
200		    continue;
201		}
202		switch (*p) {
203		case '\\':
204		case '"':
205		case '\'':
206		    quotechar = *p;
207		    break;
208		case ' ':
209		case '\n':
210		    *p = '\0';
211		    if (p > args && p[-1])
212			nargc++;
213		    break;
214		}
215	    }
216	    if (p[-1])
217		nargc++;
218	    nargv = malloc(nargc * sizeof(char *));
219	    nargv[0] = argv[0];
220	    argc = 1;
221	    for (p = args; argc < nargc; p += strlen(p) + 1)
222		if (*p) nargv[argc++] = p;
223	    argv = nargv;
224	}
225	for(argc--, argv++; argc; argc--, argv++) {
226	    	/* if looking for endmarker then check before parsing */
227		if (endmarker && strcmp (endmarker, *argv) == 0) {
228		    endmarker = NULL;
229		    continue;
230		}
231		if (**argv != '-') {
232			/* treat +thing as an option for C++ */
233			if (endmarker && **argv == '+')
234				continue;
235			*fp++ = argv[0];
236			continue;
237		}
238		switch(argv[0][1]) {
239		case '-':
240			endmarker = &argv[0][2];
241			if (endmarker[0] == '\0') endmarker = "--";
242			break;
243		case 'D':
244			if (argv[0][2] == '\0') {
245				if (argc < 2)
246					fatalerr("Missing argument for -D\n");
247				argv++;
248				argc--;
249			}
250			for (p=argv[0] + 2; *p ; p++)
251				if (*p == '=') {
252					*p = ' ';
253					break;
254				}
255			define(argv[0] + 2, &maininclist);
256			break;
257		case 'I':
258			if (incp >= includedirs + MAXDIRS)
259			    fatalerr("Too many -I flags.\n");
260			*incp++ = argv[0]+2;
261			if (**(incp-1) == '\0') {
262				if (argc < 2)
263					fatalerr("Missing argument for -I\n");
264				*(incp-1) = *(++argv);
265				argc--;
266			}
267			break;
268		case 'U':
269			/* Undef's override all -D's so save them up */
270			numundefs++;
271			if (numundefs == 1)
272			    undeflist = malloc(sizeof(char *));
273			else
274			    undeflist = realloc(undeflist,
275						numundefs * sizeof(char *));
276			if (argv[0][2] == '\0') {
277				if (argc < 2)
278					fatalerr("Missing argument for -U\n");
279				argv++;
280				argc--;
281			}
282			undeflist[numundefs - 1] = argv[0] + 2;
283			break;
284		case 'Y':
285			defincdir = argv[0]+2;
286			break;
287		/* do not use if endmarker processing */
288		case 'a':
289			if (endmarker) break;
290			append = TRUE;
291			break;
292		case 'w':
293			if (endmarker) break;
294			if (argv[0][2] == '\0') {
295				if (argc < 2)
296					fatalerr("Missing argument for -w\n");
297				argv++;
298				argc--;
299				width = atoi(argv[0]);
300			} else
301				width = atoi(argv[0]+2);
302			break;
303		case 'o':
304			if (endmarker) break;
305			if (argv[0][2] == '\0') {
306				if (argc < 2)
307					fatalerr("Missing argument for -o\n");
308				argv++;
309				argc--;
310				objsuffix = argv[0];
311			} else
312				objsuffix = argv[0]+2;
313			break;
314		case 'p':
315			if (endmarker) break;
316			if (argv[0][2] == '\0') {
317				if (argc < 2)
318					fatalerr("Missing argument for -p\n");
319				argv++;
320				argc--;
321				objprefix = argv[0];
322			} else
323				objprefix = argv[0]+2;
324			break;
325		case 'v':
326			if (endmarker) break;
327			verbose = TRUE;
328#ifdef DEBUG
329			if (argv[0][2])
330				_debugmask = atoi(argv[0]+2);
331#endif
332			break;
333		case 's':
334			if (endmarker) break;
335			startat = argv[0]+2;
336			if (*startat == '\0') {
337				if (argc < 2)
338					fatalerr("Missing argument for -s\n");
339				startat = *(++argv);
340				argc--;
341			}
342			if (*startat != '#')
343				fatalerr("-s flag's value should start %s\n",
344					"with '#'.");
345			break;
346		case 'f':
347			if (endmarker) break;
348			makefile = argv[0]+2;
349			if (*makefile == '\0') {
350				if (argc < 2)
351					fatalerr("Missing argument for -f\n");
352				makefile = *(++argv);
353				argc--;
354			}
355			break;
356
357		case 'm':
358			warn_multiple = TRUE;
359			break;
360
361		/* Ignore -O, -g so we can just pass ${CFLAGS} to
362		   makedepend
363		 */
364		case 'O':
365		case 'g':
366			break;
367		case 'i':
368			if (strcmp(&argv[0][1],"include") == 0) {
369				char *buf;
370				if (argc<2)
371					fatalerr("option -include is a "
372						 "missing its parameter\n");
373				if (cmdinc_count >= MAXINCFILES)
374					fatalerr("Too many -include flags.\n");
375				argc--;
376				argv++;
377				buf = malloc(strlen(DASH_INC_PRE) +
378					     strlen(argv[0]) +
379					     strlen(DASH_INC_POST) + 1);
380                		if(!buf)
381					fatalerr("out of memory at "
382						 "-include string\n");
383				cmdinc_list[2 * cmdinc_count + 0] = argv[0];
384				cmdinc_list[2 * cmdinc_count + 1] = buf;
385				cmdinc_count++;
386				break;
387			}
388			/* intentional fall through */
389		default:
390			if (endmarker) break;
391	/*		fatalerr("unknown opt = %s\n", argv[0]); */
392			warning("ignoring option %s\n", argv[0]);
393		}
394	}
395	/* Now do the undefs from the command line */
396	for (i = 0; i < numundefs; i++)
397	    undefine(undeflist[i], &maininclist);
398	if (numundefs > 0)
399	    free(undeflist);
400
401	if (!defincdir) {
402#ifdef PREINCDIR
403	    if (incp >= includedirs + MAXDIRS)
404		fatalerr("Too many -I flags.\n");
405	    *incp++ = PREINCDIR;
406#endif
407	    if (incp >= includedirs + MAXDIRS)
408		fatalerr("Too many -I flags.\n");
409	    *incp++ = INCLUDEDIR;
410
411#ifdef EXTRAINCDIR
412	    if (incp >= includedirs + MAXDIRS)
413		fatalerr("Too many -I flags.\n");
414	    *incp++ = EXTRAINCDIR;
415#endif
416
417#ifdef POSTINCDIR
418	    if (incp >= includedirs + MAXDIRS)
419		fatalerr("Too many -I flags.\n");
420	    *incp++ = POSTINCDIR;
421#endif
422	} else if (*defincdir) {
423	    if (incp >= includedirs + MAXDIRS)
424		fatalerr("Too many -I flags.\n");
425	    *incp++ = defincdir;
426	}
427
428	redirect(startat, makefile);
429
430	/*
431	 * catch signals.
432	 */
433#ifdef USGISH
434/*  should really reset SIGINT to SIG_IGN if it was.  */
435#ifdef SIGHUP
436	signal (SIGHUP, catch);
437#endif
438	signal (SIGINT, catch);
439#ifdef SIGQUIT
440	signal (SIGQUIT, catch);
441#endif
442	signal (SIGILL, catch);
443#ifdef SIGBUS
444	signal (SIGBUS, catch);
445#endif
446	signal (SIGSEGV, catch);
447#ifdef SIGSYS
448	signal (SIGSYS, catch);
449#endif
450#else
451	sig_act.sa_handler = catch;
452#if defined(_POSIX_SOURCE) || !defined(X_NOT_POSIX)
453	sigemptyset(&sig_act.sa_mask);
454	sigaddset(&sig_act.sa_mask, SIGINT);
455	sigaddset(&sig_act.sa_mask, SIGQUIT);
456#ifdef SIGBUS
457	sigaddset(&sig_act.sa_mask, SIGBUS);
458#endif
459	sigaddset(&sig_act.sa_mask, SIGILL);
460	sigaddset(&sig_act.sa_mask, SIGSEGV);
461	sigaddset(&sig_act.sa_mask, SIGHUP);
462	sigaddset(&sig_act.sa_mask, SIGPIPE);
463#ifdef SIGSYS
464	sigaddset(&sig_act.sa_mask, SIGSYS);
465#endif
466#else
467	sig_act.sa_mask = ((1<<(SIGINT -1))
468			   |(1<<(SIGQUIT-1))
469#ifdef SIGBUS
470			   |(1<<(SIGBUS-1))
471#endif
472			   |(1<<(SIGILL-1))
473			   |(1<<(SIGSEGV-1))
474			   |(1<<(SIGHUP-1))
475			   |(1<<(SIGPIPE-1))
476#ifdef SIGSYS
477			   |(1<<(SIGSYS-1))
478#endif
479			   );
480#endif /* _POSIX_SOURCE */
481	sig_act.sa_flags = 0;
482	sigaction(SIGHUP, &sig_act, (struct sigaction *)0);
483	sigaction(SIGINT, &sig_act, (struct sigaction *)0);
484	sigaction(SIGQUIT, &sig_act, (struct sigaction *)0);
485	sigaction(SIGILL, &sig_act, (struct sigaction *)0);
486#ifdef SIGBUS
487	sigaction(SIGBUS, &sig_act, (struct sigaction *)0);
488#endif
489	sigaction(SIGSEGV, &sig_act, (struct sigaction *)0);
490#ifdef SIGSYS
491	sigaction(SIGSYS, &sig_act, (struct sigaction *)0);
492#endif
493#endif /* USGISH */
494
495	/*
496	 * now peruse through the list of files.
497	 */
498	for(fp=filelist; *fp; fp++) {
499		DBG_PRINT(stderr,"file: %s\n",*fp);
500		filecontent = getfile(*fp);
501		setfile_cmdinc(filecontent, cmdinc_count, cmdinc_list);
502		ip = newinclude(*fp, (char *)NULL);
503
504		find_includes(filecontent, ip, ip, 0, FALSE);
505		freefile(filecontent);
506		recursive_pr_include(ip, ip->i_file, base_name(*fp));
507		inc_clean();
508	}
509	if (printed)
510		printf("\n");
511	return 0;
512}
513
514
515struct filepointer *
516getfile(const char *file)
517{
518	int	fd;
519	struct filepointer	*content;
520	struct stat	st;
521
522	content = malloc(sizeof(struct filepointer));
523	content->f_name = file;
524	if ((fd = open(file, O_RDONLY)) < 0) {
525		warning("cannot open \"%s\"\n", file);
526		content->f_p = content->f_base = content->f_end = malloc(1);
527		*content->f_p = '\0';
528		return(content);
529	}
530	fstat(fd, &st);
531	content->f_base = malloc(st.st_size+1);
532	if (content->f_base == NULL)
533		fatalerr("cannot allocate mem\n");
534	if ((st.st_size = read(fd, content->f_base, st.st_size)) < 0)
535		fatalerr("failed to read %s\n", file);
536	close(fd);
537	content->f_len = st.st_size+1;
538	content->f_p = content->f_base;
539	content->f_end = content->f_base + st.st_size;
540	*content->f_end = '\0';
541	content->f_line = 0;
542	content->cmdinc_count = 0;
543	content->cmdinc_list = NULL;
544	content->cmdinc_line = 0;
545	return(content);
546}
547
548void
549setfile_cmdinc(struct filepointer* filep, long count, char** list)
550{
551	filep->cmdinc_count = count;
552	filep->cmdinc_list = list;
553	filep->cmdinc_line = 0;
554}
555
556void
557freefile(struct filepointer *fp)
558{
559	free(fp->f_base);
560	free(fp);
561}
562
563int
564match(const char *str, const char * const *list)
565{
566	int	i;
567
568	for (i=0; *list; i++, list++)
569		if (strcmp(str, *list) == 0)
570			return(i);
571	return(-1);
572}
573
574/*
575 * Get the next line.  We only return lines beginning with '#' since that
576 * is all this program is ever interested in.
577 */
578char *getnextline(struct filepointer *filep)
579{
580	char	*p,	/* walking pointer */
581		*eof,	/* end of file pointer */
582		*bol;	/* beginning of line pointer */
583	int	lineno;	/* line number */
584	boolean whitespace = FALSE;
585
586	/*
587	 * Fake the "-include" line files in form of #include to the
588	 * start of each file.
589	 */
590	if (filep->cmdinc_line < filep->cmdinc_count) {
591		char *inc = filep->cmdinc_list[2 * filep->cmdinc_line + 0];
592		char *buf = filep->cmdinc_list[2 * filep->cmdinc_line + 1];
593		filep->cmdinc_line++;
594		sprintf(buf,"%s%s%s",DASH_INC_PRE,inc,DASH_INC_POST);
595		DBG_PRINT(stderr,"%s\n",buf);
596		return(buf);
597	}
598
599	p = filep->f_p;
600	eof = filep->f_end;
601	if (p >= eof)
602		return((char *)NULL);
603	lineno = filep->f_line;
604
605	for (bol = p--; ++p < eof; ) {
606		if ((bol == p) && ((*p == ' ') || (*p == '\t')))
607		{
608			/* Consume leading white-spaces for this line */
609			while (((p+1) < eof) && ((*p == ' ') || (*p == '\t')))
610			{
611				p++;
612				bol++;
613			}
614			whitespace = TRUE;
615		}
616
617		if (*p == '/' && (p+1) < eof && *(p+1) == '*') {
618			/* Consume C comments */
619			*(p++) = ' ';
620			*(p++) = ' ';
621			while (p < eof && *p) {
622				if (*p == '*' && (p+1) < eof && *(p+1) == '/') {
623					*(p++) = ' ';
624					*(p++) = ' ';
625					break;
626				}
627				if (*p == '\n')
628					lineno++;
629				*(p++) = ' ';
630			}
631			--p;
632		}
633		else if (*p == '/' && (p+1) < eof && *(p+1) == '/') {
634			/* Consume C++ comments */
635			*(p++) = ' ';
636			*(p++) = ' ';
637			while (p < eof && *p) {
638				if (*p == '\\' && (p+1) < eof &&
639				    *(p+1) == '\n') {
640					*(p++) = ' ';
641					lineno++;
642				}
643				else if (*p == '?' && (p+3) < eof &&
644					 *(p+1) == '?' &&
645					 *(p+2) == '/' &&
646					 *(p+3) == '\n') {
647					*(p++) = ' ';
648					*(p++) = ' ';
649					*(p++) = ' ';
650					lineno++;
651				}
652				else if (*p == '\n')
653					break;	/* to process end of line */
654				*(p++) = ' ';
655			}
656			--p;
657		}
658		else if (*p == '\\' && (p+1) < eof && *(p+1) == '\n') {
659			/* Consume backslash line terminations */
660			*(p++) = ' ';
661			*p = ' ';
662			lineno++;
663		}
664		else if (*p == '?' && (p+3) < eof &&
665			 *(p+1) == '?' && *(p+2) == '/' && *(p+3) == '\n') {
666			/* Consume trigraph'ed backslash line terminations */
667			*(p++) = ' ';
668			*(p++) = ' ';
669			*(p++) = ' ';
670			*p = ' ';
671			lineno++;
672		}
673		else if (*p == '\n') {
674			lineno++;
675			if (*bol == '#') {
676				char *cp;
677
678				*(p++) = '\0';
679				/* punt lines with just # (yacc generated) */
680				for (cp = bol+1;
681				     *cp && (*cp == ' ' || *cp == '\t'); cp++);
682				if (*cp) goto done;
683				--p;
684			}
685			bol = p+1;
686			whitespace = FALSE;
687		}
688	}
689	if (*bol != '#')
690		bol = NULL;
691done:
692	filep->f_p = p;
693	filep->f_line = lineno;
694#ifdef DEBUG_DUMP
695	if (bol)
696		DBG_PRINT(stderr,"%s\n",bol);
697#endif
698	return(bol);
699}
700
701/*
702 * Strip the file name down to what we want to see in the Makefile.
703 * It will have objprefix and objsuffix around it.
704 */
705char *base_name(const char *in_file)
706{
707	char	*p;
708	char	*file = strdup(in_file);
709	for(p=file+strlen(file); p>file && *p != '.'; p--) ;
710
711	if (*p == '.')
712		*p = '\0';
713	return(file);
714}
715
716#ifndef HAVE_RENAME
717int rename (char *from, char *to)
718{
719    (void) unlink (to);
720    if (link (from, to) == 0) {
721	unlink (from);
722	return 0;
723    } else {
724	return -1;
725    }
726}
727#endif /* !HAVE_RENAME */
728
729static void
730redirect(const char *line, const char *makefile)
731{
732	struct stat	st;
733	FILE	*fdin, *fdout;
734	char	backup[ BUFSIZ ],
735		buf[ BUFSIZ ];
736	boolean	found = FALSE;
737	size_t	len;
738
739	/*
740	 * if makefile is "-" then let it pour onto stdout.
741	 */
742	if (makefile && *makefile == '-' && *(makefile+1) == '\0') {
743		puts(line);
744		return;
745	}
746
747	/*
748	 * use a default if makefile is not specified.
749	 */
750	if (!makefile) {
751		if (stat("Makefile", &st) == 0)
752			makefile = "Makefile";
753		else if (stat("makefile", &st) == 0)
754			makefile = "makefile";
755		else
756			fatalerr("[mM]akefile is not present\n");
757	}
758	else {
759		if (stat(makefile, &st) != 0)
760			fatalerr("\"%s\" is not present\n", makefile);
761	}
762
763	snprintf(backup, sizeof(backup), "%s.bak", makefile);
764	unlink(backup);
765
766	/* rename() won't work on WIN32, CYGWIN, or CIFS if src file is open */
767	if (rename(makefile, backup) < 0)
768		fatalerr("cannot rename %s to %s\n", makefile, backup);
769	if ((fdin = fopen(backup, "r")) == NULL) {
770		if (rename(backup, makefile) < 0)
771			warning("renamed %s to %s, but can't move it back\n",
772				makefile, backup);
773		fatalerr("cannot open \"%s\"\n", makefile);
774	}
775	if ((fdout = freopen(makefile, "w", stdout)) == NULL)
776		fatalerr("cannot open \"%s\"\n", backup);
777	len = strlen(line);
778	while (!found && fgets(buf, BUFSIZ, fdin)) {
779		if (*buf == '#' && strncmp(line, buf, len) == 0)
780			found = TRUE;
781		fputs(buf, fdout);
782	}
783	if (!found) {
784		if (verbose)
785		warning("Adding new delimiting line \"%s\" and dependencies...\n",
786			line);
787		puts(line); /* same as fputs(fdout); but with newline */
788	} else if (append) {
789	    while (fgets(buf, BUFSIZ, fdin)) {
790		fputs(buf, fdout);
791	    }
792	}
793	fflush(fdout);
794#ifndef HAVE_FCHMOD
795	chmod(makefile, st.st_mode);
796#else
797        fchmod(fileno(fdout), st.st_mode);
798#endif /* HAVE_FCHMOD */
799}
800
801void
802fatalerr(const char *msg, ...)
803{
804	va_list args;
805	fprintf(stderr, "%s: error:  ", ProgramName);
806	va_start(args, msg);
807	vfprintf(stderr, msg, args);
808	va_end(args);
809	exit (1);
810}
811
812void
813warning(const char *msg, ...)
814{
815	va_list args;
816	fprintf(stderr, "%s: warning:  ", ProgramName);
817	va_start(args, msg);
818	vfprintf(stderr, msg, args);
819	va_end(args);
820}
821
822void
823warning1(const char *msg, ...)
824{
825	va_list args;
826	va_start(args, msg);
827	vfprintf(stderr, msg, args);
828	va_end(args);
829}
830