main.c revision b2f5b1db
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			if (fp >= filelist + MAXFILES) {
236			    fatalerr("Too many source files. Limit is %i files.\n", MAXFILES);
237			}
238			*fp++ = argv[0];
239			continue;
240		}
241		switch(argv[0][1]) {
242		case '-':
243			endmarker = &argv[0][2];
244			if (endmarker[0] == '\0') endmarker = "--";
245			break;
246		case 'D':
247			if (argv[0][2] == '\0') {
248				if (argc < 2)
249					fatalerr("Missing argument for -D\n");
250				argv++;
251				argc--;
252			}
253			for (p=argv[0] + 2; *p ; p++)
254				if (*p == '=') {
255					*p = ' ';
256					break;
257				}
258			define(argv[0] + 2, &maininclist);
259			break;
260		case 'I':
261			if (incp >= includedirs + MAXDIRS)
262			    fatalerr("Too many -I flags.\n");
263			*incp++ = argv[0]+2;
264			if (**(incp-1) == '\0') {
265				if (argc < 2)
266					fatalerr("Missing argument for -I\n");
267				*(incp-1) = *(++argv);
268				argc--;
269			}
270			break;
271		case 'U':
272			/* Undef's override all -D's so save them up */
273			numundefs++;
274			if (numundefs == 1)
275			    undeflist = malloc(sizeof(char *));
276			else
277			    undeflist = realloc(undeflist,
278						numundefs * sizeof(char *));
279			if (argv[0][2] == '\0') {
280				if (argc < 2)
281					fatalerr("Missing argument for -U\n");
282				argv++;
283				argc--;
284			}
285			undeflist[numundefs - 1] = argv[0] + 2;
286			break;
287		case 'Y':
288			defincdir = argv[0]+2;
289			break;
290		/* do not use if endmarker processing */
291		case 'a':
292			if (endmarker) break;
293			append = TRUE;
294			break;
295		case 'w':
296			if (endmarker) break;
297			if (argv[0][2] == '\0') {
298				if (argc < 2)
299					fatalerr("Missing argument for -w\n");
300				argv++;
301				argc--;
302				width = atoi(argv[0]);
303			} else
304				width = atoi(argv[0]+2);
305			break;
306		case 'o':
307			if (endmarker) break;
308			if (argv[0][2] == '\0') {
309				if (argc < 2)
310					fatalerr("Missing argument for -o\n");
311				argv++;
312				argc--;
313				objsuffix = argv[0];
314			} else
315				objsuffix = argv[0]+2;
316			break;
317		case 'p':
318			if (endmarker) break;
319			if (argv[0][2] == '\0') {
320				if (argc < 2)
321					fatalerr("Missing argument for -p\n");
322				argv++;
323				argc--;
324				objprefix = argv[0];
325			} else
326				objprefix = argv[0]+2;
327			break;
328		case 'v':
329			if (endmarker) break;
330			verbose = TRUE;
331#ifdef DEBUG
332			if (argv[0][2])
333				_debugmask = atoi(argv[0]+2);
334#endif
335			break;
336		case 's':
337			if (endmarker) break;
338			startat = argv[0]+2;
339			if (*startat == '\0') {
340				if (argc < 2)
341					fatalerr("Missing argument for -s\n");
342				startat = *(++argv);
343				argc--;
344			}
345			if (*startat != '#')
346				fatalerr("-s flag's value should start %s\n",
347					"with '#'.");
348			break;
349		case 'f':
350			if (endmarker) break;
351			makefile = argv[0]+2;
352			if (*makefile == '\0') {
353				if (argc < 2)
354					fatalerr("Missing argument for -f\n");
355				makefile = *(++argv);
356				argc--;
357			}
358			break;
359
360		case 'm':
361			warn_multiple = TRUE;
362			break;
363
364		/* Ignore -O, -g so we can just pass ${CFLAGS} to
365		   makedepend
366		 */
367		case 'O':
368		case 'g':
369			break;
370		case 'i':
371			if (strcmp(&argv[0][1],"include") == 0) {
372				char *buf;
373				if (argc<2)
374					fatalerr("option -include is a "
375						 "missing its parameter\n");
376				if (cmdinc_count >= MAXINCFILES)
377					fatalerr("Too many -include flags.\n");
378				argc--;
379				argv++;
380				buf = malloc(strlen(DASH_INC_PRE) +
381					     strlen(argv[0]) +
382					     strlen(DASH_INC_POST) + 1);
383                		if(!buf)
384					fatalerr("out of memory at "
385						 "-include string\n");
386				cmdinc_list[2 * cmdinc_count + 0] = argv[0];
387				cmdinc_list[2 * cmdinc_count + 1] = buf;
388				cmdinc_count++;
389				break;
390			}
391			/* intentional fall through */
392		default:
393			if (endmarker) break;
394	/*		fatalerr("unknown opt = %s\n", argv[0]); */
395			warning("ignoring option %s\n", argv[0]);
396		}
397	}
398	/* Now do the undefs from the command line */
399	for (i = 0; i < numundefs; i++)
400	    undefine(undeflist[i], &maininclist);
401	if (numundefs > 0)
402	    free(undeflist);
403
404	if (!defincdir) {
405#ifdef PREINCDIR
406	    if (incp >= includedirs + MAXDIRS)
407		fatalerr("Too many -I flags.\n");
408	    *incp++ = PREINCDIR;
409#endif
410	    if (incp >= includedirs + MAXDIRS)
411		fatalerr("Too many -I flags.\n");
412	    *incp++ = INCLUDEDIR;
413
414#ifdef EXTRAINCDIR
415	    if (incp >= includedirs + MAXDIRS)
416		fatalerr("Too many -I flags.\n");
417	    *incp++ = EXTRAINCDIR;
418#endif
419
420#ifdef POSTINCDIR
421	    if (incp >= includedirs + MAXDIRS)
422		fatalerr("Too many -I flags.\n");
423	    *incp++ = POSTINCDIR;
424#endif
425	} else if (*defincdir) {
426	    if (incp >= includedirs + MAXDIRS)
427		fatalerr("Too many -I flags.\n");
428	    *incp++ = defincdir;
429	}
430
431	redirect(startat, makefile);
432
433	/*
434	 * catch signals.
435	 */
436#ifdef USGISH
437/*  should really reset SIGINT to SIG_IGN if it was.  */
438#ifdef SIGHUP
439	signal (SIGHUP, catch);
440#endif
441	signal (SIGINT, catch);
442#ifdef SIGQUIT
443	signal (SIGQUIT, catch);
444#endif
445	signal (SIGILL, catch);
446#ifdef SIGBUS
447	signal (SIGBUS, catch);
448#endif
449	signal (SIGSEGV, catch);
450#ifdef SIGSYS
451	signal (SIGSYS, catch);
452#endif
453#else
454	sig_act.sa_handler = catch;
455#if defined(_POSIX_SOURCE) || !defined(X_NOT_POSIX)
456	sigemptyset(&sig_act.sa_mask);
457	sigaddset(&sig_act.sa_mask, SIGINT);
458	sigaddset(&sig_act.sa_mask, SIGQUIT);
459#ifdef SIGBUS
460	sigaddset(&sig_act.sa_mask, SIGBUS);
461#endif
462	sigaddset(&sig_act.sa_mask, SIGILL);
463	sigaddset(&sig_act.sa_mask, SIGSEGV);
464	sigaddset(&sig_act.sa_mask, SIGHUP);
465	sigaddset(&sig_act.sa_mask, SIGPIPE);
466#ifdef SIGSYS
467	sigaddset(&sig_act.sa_mask, SIGSYS);
468#endif
469#else
470	sig_act.sa_mask = ((1<<(SIGINT -1))
471			   |(1<<(SIGQUIT-1))
472#ifdef SIGBUS
473			   |(1<<(SIGBUS-1))
474#endif
475			   |(1<<(SIGILL-1))
476			   |(1<<(SIGSEGV-1))
477			   |(1<<(SIGHUP-1))
478			   |(1<<(SIGPIPE-1))
479#ifdef SIGSYS
480			   |(1<<(SIGSYS-1))
481#endif
482			   );
483#endif /* _POSIX_SOURCE */
484	sig_act.sa_flags = 0;
485	sigaction(SIGHUP, &sig_act, (struct sigaction *)0);
486	sigaction(SIGINT, &sig_act, (struct sigaction *)0);
487	sigaction(SIGQUIT, &sig_act, (struct sigaction *)0);
488	sigaction(SIGILL, &sig_act, (struct sigaction *)0);
489#ifdef SIGBUS
490	sigaction(SIGBUS, &sig_act, (struct sigaction *)0);
491#endif
492	sigaction(SIGSEGV, &sig_act, (struct sigaction *)0);
493#ifdef SIGSYS
494	sigaction(SIGSYS, &sig_act, (struct sigaction *)0);
495#endif
496#endif /* USGISH */
497
498	/*
499	 * now peruse through the list of files.
500	 */
501	for(fp=filelist; *fp; fp++) {
502		DBG_PRINT(stderr,"file: %s\n",*fp);
503		filecontent = getfile(*fp);
504		setfile_cmdinc(filecontent, cmdinc_count, cmdinc_list);
505		ip = newinclude(*fp, (char *)NULL);
506
507		find_includes(filecontent, ip, ip, 0, FALSE);
508		freefile(filecontent);
509		recursive_pr_include(ip, ip->i_file, base_name(*fp));
510		inc_clean();
511	}
512	if (printed)
513		printf("\n");
514	return 0;
515}
516
517
518struct filepointer *
519getfile(const char *file)
520{
521	int	fd;
522	struct filepointer	*content;
523	struct stat	st;
524
525	content = malloc(sizeof(struct filepointer));
526	content->f_name = file;
527	if ((fd = open(file, O_RDONLY)) < 0) {
528		warning("cannot open \"%s\"\n", file);
529		content->f_p = content->f_base = content->f_end = malloc(1);
530		*content->f_p = '\0';
531		return(content);
532	}
533	fstat(fd, &st);
534	content->f_base = malloc(st.st_size+1);
535	if (content->f_base == NULL)
536		fatalerr("cannot allocate mem\n");
537	if ((st.st_size = read(fd, content->f_base, st.st_size)) < 0)
538		fatalerr("failed to read %s\n", file);
539	close(fd);
540	content->f_len = st.st_size+1;
541	content->f_p = content->f_base;
542	content->f_end = content->f_base + st.st_size;
543	*content->f_end = '\0';
544	content->f_line = 0;
545	content->cmdinc_count = 0;
546	content->cmdinc_list = NULL;
547	content->cmdinc_line = 0;
548	return(content);
549}
550
551void
552setfile_cmdinc(struct filepointer* filep, long count, char** list)
553{
554	filep->cmdinc_count = count;
555	filep->cmdinc_list = list;
556	filep->cmdinc_line = 0;
557}
558
559void
560freefile(struct filepointer *fp)
561{
562	free(fp->f_base);
563	free(fp);
564}
565
566int
567match(const char *str, const char * const *list)
568{
569	int	i;
570
571	for (i=0; *list; i++, list++)
572		if (strcmp(str, *list) == 0)
573			return(i);
574	return(-1);
575}
576
577/*
578 * Get the next line.  We only return lines beginning with '#' since that
579 * is all this program is ever interested in.
580 */
581char *getnextline(struct filepointer *filep)
582{
583	char	*p,	/* walking pointer */
584		*eof,	/* end of file pointer */
585		*bol;	/* beginning of line pointer */
586	int	lineno;	/* line number */
587
588	/*
589	 * Fake the "-include" line files in form of #include to the
590	 * start of each file.
591	 */
592	if (filep->cmdinc_line < filep->cmdinc_count) {
593		char *inc = filep->cmdinc_list[2 * filep->cmdinc_line + 0];
594		char *buf = filep->cmdinc_list[2 * filep->cmdinc_line + 1];
595		filep->cmdinc_line++;
596		sprintf(buf,"%s%s%s",DASH_INC_PRE,inc,DASH_INC_POST);
597		DBG_PRINT(stderr,"%s\n",buf);
598		return(buf);
599	}
600
601	p = filep->f_p;
602	eof = filep->f_end;
603	if (p >= eof)
604		return((char *)NULL);
605	lineno = filep->f_line;
606
607	for (bol = p--; ++p < eof; ) {
608		if ((bol == p) && ((*p == ' ') || (*p == '\t')))
609		{
610			/* Consume leading white-spaces for this line */
611			while (((p+1) < eof) && ((*p == ' ') || (*p == '\t')))
612			{
613				p++;
614				bol++;
615			}
616		}
617
618		if (*p == '/' && (p+1) < eof && *(p+1) == '*') {
619			/* Consume C comments */
620			*(p++) = ' ';
621			*(p++) = ' ';
622			while (p < eof && *p) {
623				if (*p == '*' && (p+1) < eof && *(p+1) == '/') {
624					*(p++) = ' ';
625					*(p++) = ' ';
626					break;
627				}
628				if (*p == '\n')
629					lineno++;
630				*(p++) = ' ';
631			}
632			--p;
633		}
634		else if (*p == '/' && (p+1) < eof && *(p+1) == '/') {
635			/* Consume C++ comments */
636			*(p++) = ' ';
637			*(p++) = ' ';
638			while (p < eof && *p) {
639				if (*p == '\\' && (p+1) < eof &&
640				    *(p+1) == '\n') {
641					*(p++) = ' ';
642					lineno++;
643				}
644				else if (*p == '?' && (p+3) < eof &&
645					 *(p+1) == '?' &&
646					 *(p+2) == '/' &&
647					 *(p+3) == '\n') {
648					*(p++) = ' ';
649					*(p++) = ' ';
650					*(p++) = ' ';
651					lineno++;
652				}
653				else if (*p == '\n')
654					break;	/* to process end of line */
655				*(p++) = ' ';
656			}
657			--p;
658		}
659		else if (*p == '\\' && (p+1) < eof && *(p+1) == '\n') {
660			/* Consume backslash line terminations */
661			*(p++) = ' ';
662			*p = ' ';
663			lineno++;
664		}
665		else if (*p == '?' && (p+3) < eof &&
666			 *(p+1) == '?' && *(p+2) == '/' && *(p+3) == '\n') {
667			/* Consume trigraph'ed backslash line terminations */
668			*(p++) = ' ';
669			*(p++) = ' ';
670			*(p++) = ' ';
671			*p = ' ';
672			lineno++;
673		}
674		else if (*p == '\n') {
675			lineno++;
676			if (*bol == '#') {
677				char *cp;
678
679				*(p++) = '\0';
680				/* punt lines with just # (yacc generated) */
681				for (cp = bol+1;
682				     *cp && (*cp == ' ' || *cp == '\t'); cp++);
683				if (*cp) goto done;
684				--p;
685			}
686			bol = p+1;
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