main.c revision 63165362
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 ];
102char		*objprefix = "";
103char		*objsuffix = OBJSUFFIX;
104static 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
117#ifdef RETSIGTYPE
118RETSIGTYPE
119#else
120# ifdef SIGNALRETURNSINT
121int
122# else
123void
124# endif
125#endif
126catch (int sig)
127{
128	fflush (stdout);
129	fatalerr ("got signal %d\n", sig);
130}
131
132#if defined(USG) || (defined(i386) && defined(SYSV)) || defined(WIN32) || defined(__UNIXOS2__) || defined(Lynx_22) || defined(__CYGWIN__)
133#define USGISH
134#endif
135
136#ifndef USGISH
137#ifdef X_NOT_POSIX
138#define sigaction sigvec
139#define sa_handler sv_handler
140#define sa_mask sv_mask
141#define sa_flags sv_flags
142#endif
143static struct sigaction sig_act;
144#endif /* USGISH */
145
146#ifndef USING_AUTOCONF
147# if !defined(USGISH) && !defined(_SEQUENT_) && !defined(MINIX)
148#  define HAVE_FCHMOD	1
149# endif
150#endif
151
152int
153main(int argc, char *argv[])
154{
155	char	**fp = filelist;
156	const char	**incp = includedirs;
157	char	*p;
158	struct inclist	*ip;
159	char	*makefile = NULL;
160	struct filepointer	*filecontent;
161	const struct symtab *psymp = predefs;
162	char *endmarker = NULL;
163	char *defincdir = NULL;
164	char **undeflist = NULL;
165	int numundefs = 0, i;
166
167	ProgramName = argv[0];
168
169	while (psymp->s_name)
170	{
171	    define2(psymp->s_name, psymp->s_value, &maininclist);
172	    psymp++;
173	}
174#ifdef __sun
175	/* Solaris predefined values that are computed, not hardcoded */
176	{
177	    struct utsname name;
178
179	    if (uname(&name) >= 0) {
180		char osrevdef[SYS_NMLN + SYS_NMLN + 5];
181		snprintf(osrevdef, sizeof(osrevdef), "__%s_%s",
182			 name.sysname, name.release);
183
184		for (p = osrevdef; *p != '\0'; p++) {
185		    if (!isalnum(*p)) {
186			*p = '_';
187		    }
188		}
189		define2(osrevdef, "1", &maininclist);
190	    }
191	}
192#endif
193	if (argc == 2 && argv[1][0] == '@') {
194	    struct stat ast;
195	    int afd;
196	    char *args;
197	    char **nargv;
198	    int nargc;
199	    char quotechar = '\0';
200
201	    nargc = 1;
202	    if ((afd = open(argv[1]+1, O_RDONLY)) < 0)
203		fatalerr("cannot open \"%s\"\n", argv[1]+1);
204	    fstat(afd, &ast);
205	    args = (char *)malloc(ast.st_size + 1);
206	    if ((ast.st_size = read(afd, args, ast.st_size)) < 0)
207		fatalerr("failed to read %s\n", argv[1]+1);
208	    args[ast.st_size] = '\0';
209	    close(afd);
210	    for (p = args; *p; p++) {
211		if (quotechar) {
212		    if (quotechar == '\\' ||
213			(*p == quotechar && p[-1] != '\\'))
214			quotechar = '\0';
215		    continue;
216		}
217		switch (*p) {
218		case '\\':
219		case '"':
220		case '\'':
221		    quotechar = *p;
222		    break;
223		case ' ':
224		case '\n':
225		    *p = '\0';
226		    if (p > args && p[-1])
227			nargc++;
228		    break;
229		}
230	    }
231	    if (p[-1])
232		nargc++;
233	    nargv = (char **)malloc(nargc * sizeof(char *));
234	    nargv[0] = argv[0];
235	    argc = 1;
236	    for (p = args; argc < nargc; p += strlen(p) + 1)
237		if (*p) nargv[argc++] = p;
238	    argv = nargv;
239	}
240	for(argc--, argv++; argc; argc--, argv++) {
241	    	/* if looking for endmarker then check before parsing */
242		if (endmarker && strcmp (endmarker, *argv) == 0) {
243		    endmarker = NULL;
244		    continue;
245		}
246		if (**argv != '-') {
247			/* treat +thing as an option for C++ */
248			if (endmarker && **argv == '+')
249				continue;
250			*fp++ = argv[0];
251			continue;
252		}
253		switch(argv[0][1]) {
254		case '-':
255			endmarker = &argv[0][2];
256			if (endmarker[0] == '\0') endmarker = "--";
257			break;
258		case 'D':
259			if (argv[0][2] == '\0') {
260				argv++;
261				argc--;
262			}
263			for (p=argv[0] + 2; *p ; p++)
264				if (*p == '=') {
265					*p = ' ';
266					break;
267				}
268			define(argv[0] + 2, &maininclist);
269			break;
270		case 'I':
271			if (incp >= includedirs + MAXDIRS)
272			    fatalerr("Too many -I flags.\n");
273			*incp++ = argv[0]+2;
274			if (**(incp-1) == '\0') {
275				*(incp-1) = *(++argv);
276				argc--;
277			}
278			break;
279		case 'U':
280			/* Undef's override all -D's so save them up */
281			numundefs++;
282			if (numundefs == 1)
283			    undeflist = malloc(sizeof(char *));
284			else
285			    undeflist = realloc(undeflist,
286						numundefs * sizeof(char *));
287			if (argv[0][2] == '\0') {
288				argv++;
289				argc--;
290			}
291			undeflist[numundefs - 1] = argv[0] + 2;
292			break;
293		case 'Y':
294			defincdir = argv[0]+2;
295			break;
296		/* do not use if endmarker processing */
297		case 'a':
298			if (endmarker) break;
299			append = TRUE;
300			break;
301		case 'w':
302			if (endmarker) break;
303			if (argv[0][2] == '\0') {
304				argv++;
305				argc--;
306				width = atoi(argv[0]);
307			} else
308				width = atoi(argv[0]+2);
309			break;
310		case 'o':
311			if (endmarker) break;
312			if (argv[0][2] == '\0') {
313				argv++;
314				argc--;
315				objsuffix = argv[0];
316			} else
317				objsuffix = argv[0]+2;
318			break;
319		case 'p':
320			if (endmarker) break;
321			if (argv[0][2] == '\0') {
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				startat = *(++argv);
341				argc--;
342			}
343			if (*startat != '#')
344				fatalerr("-s flag's value should start %s\n",
345					"with '#'.");
346			break;
347		case 'f':
348			if (endmarker) break;
349			makefile = argv[0]+2;
350			if (*makefile == '\0') {
351				makefile = *(++argv);
352				argc--;
353			}
354			break;
355
356		case 'm':
357			warn_multiple = TRUE;
358			break;
359
360		/* Ignore -O, -g so we can just pass ${CFLAGS} to
361		   makedepend
362		 */
363		case 'O':
364		case 'g':
365			break;
366		case 'i':
367			if (strcmp(&argv[0][1],"include") == 0) {
368				char *buf;
369				if (argc<2)
370					fatalerr("option -include is a "
371						 "missing its parameter\n");
372				if (cmdinc_count >= MAXINCFILES)
373					fatalerr("Too many -include flags.\n");
374				argc--;
375				argv++;
376				buf = malloc(strlen(DASH_INC_PRE) +
377					     strlen(argv[0]) +
378					     strlen(DASH_INC_POST) + 1);
379                		if(!buf)
380					fatalerr("out of memory at "
381						 "-include string\n");
382				cmdinc_list[2 * cmdinc_count + 0] = argv[0];
383				cmdinc_list[2 * cmdinc_count + 1] = buf;
384				cmdinc_count++;
385				break;
386			}
387			/* intentional fall through */
388		default:
389			if (endmarker) break;
390	/*		fatalerr("unknown opt = %s\n", argv[0]); */
391			warning("ignoring option %s\n", argv[0]);
392		}
393	}
394	/* Now do the undefs from the command line */
395	for (i = 0; i < numundefs; i++)
396	    undefine(undeflist[i], &maininclist);
397	if (numundefs > 0)
398	    free(undeflist);
399
400	if (!defincdir) {
401#ifdef PREINCDIR
402	    if (incp >= includedirs + MAXDIRS)
403		fatalerr("Too many -I flags.\n");
404	    *incp++ = PREINCDIR;
405#endif
406#ifdef __UNIXOS2__
407	    {
408		char *emxinc = getenv("C_INCLUDE_PATH");
409		/* can have more than one component */
410		if (emxinc) {
411		    char *beg, *end;
412		    beg= (char*)strdup(emxinc);
413		    for (;;) {
414			end = (char*)strchr(beg,';');
415			if (end) *end = 0;
416		    	if (incp >= includedirs + MAXDIRS)
417				fatalerr("Too many include dirs\n");
418			*incp++ = beg;
419			if (!end) break;
420			beg = end+1;
421		    }
422		}
423	    }
424#else /* !__UNIXOS2__, does not use INCLUDEDIR at all */
425	    if (incp >= includedirs + MAXDIRS)
426		fatalerr("Too many -I flags.\n");
427	    *incp++ = INCLUDEDIR;
428#endif
429
430#ifdef EXTRAINCDIR
431	    if (incp >= includedirs + MAXDIRS)
432		fatalerr("Too many -I flags.\n");
433	    *incp++ = EXTRAINCDIR;
434#endif
435
436#ifdef POSTINCDIR
437	    if (incp >= includedirs + MAXDIRS)
438		fatalerr("Too many -I flags.\n");
439	    *incp++ = POSTINCDIR;
440#endif
441	} else if (*defincdir) {
442	    if (incp >= includedirs + MAXDIRS)
443		fatalerr("Too many -I flags.\n");
444	    *incp++ = defincdir;
445	}
446
447	redirect(startat, makefile);
448
449	/*
450	 * catch signals.
451	 */
452#ifdef USGISH
453/*  should really reset SIGINT to SIG_IGN if it was.  */
454#ifdef SIGHUP
455	signal (SIGHUP, catch);
456#endif
457	signal (SIGINT, catch);
458#ifdef SIGQUIT
459	signal (SIGQUIT, catch);
460#endif
461	signal (SIGILL, catch);
462#ifdef SIGBUS
463	signal (SIGBUS, catch);
464#endif
465	signal (SIGSEGV, catch);
466#ifdef SIGSYS
467	signal (SIGSYS, catch);
468#endif
469#else
470	sig_act.sa_handler = catch;
471#if defined(_POSIX_SOURCE) || !defined(X_NOT_POSIX)
472	sigemptyset(&sig_act.sa_mask);
473	sigaddset(&sig_act.sa_mask, SIGINT);
474	sigaddset(&sig_act.sa_mask, SIGQUIT);
475#ifdef SIGBUS
476	sigaddset(&sig_act.sa_mask, SIGBUS);
477#endif
478	sigaddset(&sig_act.sa_mask, SIGILL);
479	sigaddset(&sig_act.sa_mask, SIGSEGV);
480	sigaddset(&sig_act.sa_mask, SIGHUP);
481	sigaddset(&sig_act.sa_mask, SIGPIPE);
482#ifdef SIGSYS
483	sigaddset(&sig_act.sa_mask, SIGSYS);
484#endif
485#else
486	sig_act.sa_mask = ((1<<(SIGINT -1))
487			   |(1<<(SIGQUIT-1))
488#ifdef SIGBUS
489			   |(1<<(SIGBUS-1))
490#endif
491			   |(1<<(SIGILL-1))
492			   |(1<<(SIGSEGV-1))
493			   |(1<<(SIGHUP-1))
494			   |(1<<(SIGPIPE-1))
495#ifdef SIGSYS
496			   |(1<<(SIGSYS-1))
497#endif
498			   );
499#endif /* _POSIX_SOURCE */
500	sig_act.sa_flags = 0;
501	sigaction(SIGHUP, &sig_act, (struct sigaction *)0);
502	sigaction(SIGINT, &sig_act, (struct sigaction *)0);
503	sigaction(SIGQUIT, &sig_act, (struct sigaction *)0);
504	sigaction(SIGILL, &sig_act, (struct sigaction *)0);
505#ifdef SIGBUS
506	sigaction(SIGBUS, &sig_act, (struct sigaction *)0);
507#endif
508	sigaction(SIGSEGV, &sig_act, (struct sigaction *)0);
509#ifdef SIGSYS
510	sigaction(SIGSYS, &sig_act, (struct sigaction *)0);
511#endif
512#endif /* USGISH */
513
514	/*
515	 * now peruse through the list of files.
516	 */
517	for(fp=filelist; *fp; fp++) {
518		DBG_PRINT(stderr,"file: %s\n",*fp);
519		filecontent = getfile(*fp);
520		setfile_cmdinc(filecontent, cmdinc_count, cmdinc_list);
521		ip = newinclude(*fp, (char *)NULL);
522
523		find_includes(filecontent, ip, ip, 0, FALSE);
524		freefile(filecontent);
525		recursive_pr_include(ip, ip->i_file, base_name(*fp));
526		inc_clean();
527	}
528	if (printed)
529		printf("\n");
530	return 0;
531}
532
533#ifdef __UNIXOS2__
534/*
535 * eliminate \r chars from file
536 */
537static int
538elim_cr(char *buf, int sz)
539{
540	int i,wp;
541	for (i= wp = 0; i<sz; i++) {
542		if (buf[i] != '\r')
543			buf[wp++] = buf[i];
544	}
545	return wp;
546}
547#endif
548
549struct filepointer *
550getfile(const char *file)
551{
552	int	fd;
553	struct filepointer	*content;
554	struct stat	st;
555
556	content = (struct filepointer *)malloc(sizeof(struct filepointer));
557	content->f_name = file;
558	if ((fd = open(file, O_RDONLY)) < 0) {
559		warning("cannot open \"%s\"\n", file);
560		content->f_p = content->f_base = content->f_end = (char *)malloc(1);
561		*content->f_p = '\0';
562		return(content);
563	}
564	fstat(fd, &st);
565	content->f_base = (char *)malloc(st.st_size+1);
566	if (content->f_base == NULL)
567		fatalerr("cannot allocate mem\n");
568	if ((st.st_size = read(fd, content->f_base, st.st_size)) < 0)
569		fatalerr("failed to read %s\n", file);
570#ifdef __UNIXOS2__
571	st.st_size = elim_cr(content->f_base,st.st_size);
572#endif
573	close(fd);
574	content->f_len = st.st_size+1;
575	content->f_p = content->f_base;
576	content->f_end = content->f_base + st.st_size;
577	*content->f_end = '\0';
578	content->f_line = 0;
579	content->cmdinc_count = 0;
580	content->cmdinc_list = NULL;
581	content->cmdinc_line = 0;
582	return(content);
583}
584
585void
586setfile_cmdinc(struct filepointer* filep, long count, char** list)
587{
588	filep->cmdinc_count = count;
589	filep->cmdinc_list = list;
590	filep->cmdinc_line = 0;
591}
592
593void
594freefile(struct filepointer *fp)
595{
596	free(fp->f_base);
597	free(fp);
598}
599
600int
601match(const char *str, const char * const *list)
602{
603	int	i;
604
605	for (i=0; *list; i++, list++)
606		if (strcmp(str, *list) == 0)
607			return(i);
608	return(-1);
609}
610
611/*
612 * Get the next line.  We only return lines beginning with '#' since that
613 * is all this program is ever interested in.
614 */
615char *getnextline(struct filepointer *filep)
616{
617	char	*p,	/* walking pointer */
618		*eof,	/* end of file pointer */
619		*bol;	/* beginning of line pointer */
620	int	lineno;	/* line number */
621	boolean whitespace = FALSE;
622
623	/*
624	 * Fake the "-include" line files in form of #include to the
625	 * start of each file.
626	 */
627	if (filep->cmdinc_line < filep->cmdinc_count) {
628		char *inc = filep->cmdinc_list[2 * filep->cmdinc_line + 0];
629		char *buf = filep->cmdinc_list[2 * filep->cmdinc_line + 1];
630		filep->cmdinc_line++;
631		sprintf(buf,"%s%s%s",DASH_INC_PRE,inc,DASH_INC_POST);
632		DBG_PRINT(stderr,"%s\n",buf);
633		return(buf);
634	}
635
636	p = filep->f_p;
637	eof = filep->f_end;
638	if (p >= eof)
639		return((char *)NULL);
640	lineno = filep->f_line;
641
642	for (bol = p--; ++p < eof; ) {
643		if ((bol == p) && ((*p == ' ') || (*p == '\t')))
644		{
645			/* Consume leading white-spaces for this line */
646			while (((p+1) < eof) && ((*p == ' ') || (*p == '\t')))
647			{
648				p++;
649				bol++;
650			}
651			whitespace = TRUE;
652		}
653
654		if (*p == '/' && (p+1) < eof && *(p+1) == '*') {
655			/* Consume C comments */
656			*(p++) = ' ';
657			*(p++) = ' ';
658			while (p < eof && *p) {
659				if (*p == '*' && (p+1) < eof && *(p+1) == '/') {
660					*(p++) = ' ';
661					*(p++) = ' ';
662					break;
663				}
664				if (*p == '\n')
665					lineno++;
666				*(p++) = ' ';
667			}
668			--p;
669		}
670		else if (*p == '/' && (p+1) < eof && *(p+1) == '/') {
671			/* Consume C++ comments */
672			*(p++) = ' ';
673			*(p++) = ' ';
674			while (p < eof && *p) {
675				if (*p == '\\' && (p+1) < eof &&
676				    *(p+1) == '\n') {
677					*(p++) = ' ';
678					lineno++;
679				}
680				else if (*p == '?' && (p+3) < eof &&
681					 *(p+1) == '?' &&
682					 *(p+2) == '/' &&
683					 *(p+3) == '\n') {
684					*(p++) = ' ';
685					*(p++) = ' ';
686					*(p++) = ' ';
687					lineno++;
688				}
689				else if (*p == '\n')
690					break;	/* to process end of line */
691				*(p++) = ' ';
692			}
693			--p;
694		}
695		else if (*p == '\\' && (p+1) < eof && *(p+1) == '\n') {
696			/* Consume backslash line terminations */
697			*(p++) = ' ';
698			*p = ' ';
699			lineno++;
700		}
701		else if (*p == '?' && (p+3) < eof &&
702			 *(p+1) == '?' && *(p+2) == '/' && *(p+3) == '\n') {
703			/* Consume trigraph'ed backslash line terminations */
704			*(p++) = ' ';
705			*(p++) = ' ';
706			*(p++) = ' ';
707			*p = ' ';
708			lineno++;
709		}
710		else if (*p == '\n') {
711			lineno++;
712			if (*bol == '#') {
713				char *cp;
714
715				*(p++) = '\0';
716				/* punt lines with just # (yacc generated) */
717				for (cp = bol+1;
718				     *cp && (*cp == ' ' || *cp == '\t'); cp++);
719				if (*cp) goto done;
720				--p;
721			}
722			bol = p+1;
723			whitespace = FALSE;
724		}
725	}
726	if (*bol != '#')
727		bol = NULL;
728done:
729	filep->f_p = p;
730	filep->f_line = lineno;
731#ifdef DEBUG_DUMP
732	if (bol)
733		DBG_PRINT(stderr,"%s\n",bol);
734#endif
735	return(bol);
736}
737
738/*
739 * Strip the file name down to what we want to see in the Makefile.
740 * It will have objprefix and objsuffix around it.
741 */
742char *base_name(const char *in_file)
743{
744	char	*p;
745	char	*file = copy(in_file);
746	for(p=file+strlen(file); p>file && *p != '.'; p--) ;
747
748	if (*p == '.')
749		*p = '\0';
750	return(file);
751}
752
753#ifdef USING_AUTOCONF
754# ifndef HAVE_RENAME
755#  define NEED_RENAME
756# endif
757#else /* Imake configured, check known OS'es without rename() */
758# if defined(USG) && !defined(CRAY) && !defined(SVR4) && !defined(__UNIXOS2__) && !defined(clipper) && !defined(__clipper__)
759#  define NEED_RENAME
760# endif
761#endif
762
763#ifdef NEED_RENAME
764int rename (char *from, char *to)
765{
766    (void) unlink (to);
767    if (link (from, to) == 0) {
768	unlink (from);
769	return 0;
770    } else {
771	return -1;
772    }
773}
774#endif /* NEED_RENAME */
775
776static void
777redirect(const char *line, const char *makefile)
778{
779	struct stat	st;
780	FILE	*fdin, *fdout;
781	char	backup[ BUFSIZ ],
782		buf[ BUFSIZ ];
783	boolean	found = FALSE;
784	int	len;
785
786	/*
787	 * if makefile is "-" then let it pour onto stdout.
788	 */
789	if (makefile && *makefile == '-' && *(makefile+1) == '\0') {
790		puts(line);
791		return;
792	}
793
794	/*
795	 * use a default makefile is not specified.
796	 */
797	if (!makefile) {
798		if (stat("Makefile", &st) == 0)
799			makefile = "Makefile";
800		else if (stat("makefile", &st) == 0)
801			makefile = "makefile";
802		else
803			fatalerr("[mM]akefile is not present\n");
804	}
805	else
806	    stat(makefile, &st);
807	if ((fdin = fopen(makefile, "r")) == NULL)
808		fatalerr("cannot open \"%s\"\n", makefile);
809	sprintf(backup, "%s.bak", makefile);
810	unlink(backup);
811#if defined(WIN32) || defined(__UNIXOS2__) || defined(__CYGWIN__)
812	fclose(fdin);
813#endif
814	if (rename(makefile, backup) < 0)
815		fatalerr("cannot rename %s to %s\n", makefile, backup);
816#if defined(WIN32) || defined(__UNIXOS2__) || defined(__CYGWIN__)
817	if ((fdin = fopen(backup, "r")) == NULL)
818		fatalerr("cannot open \"%s\"\n", backup);
819#endif
820	if ((fdout = freopen(makefile, "w", stdout)) == NULL)
821		fatalerr("cannot open \"%s\"\n", backup);
822	len = strlen(line);
823	while (!found && fgets(buf, BUFSIZ, fdin)) {
824		if (*buf == '#' && strncmp(line, buf, len) == 0)
825			found = TRUE;
826		fputs(buf, fdout);
827	}
828	if (!found) {
829		if (verbose)
830		warning("Adding new delimiting line \"%s\" and dependencies...\n",
831			line);
832		puts(line); /* same as fputs(fdout); but with newline */
833	} else if (append) {
834	    while (fgets(buf, BUFSIZ, fdin)) {
835		fputs(buf, fdout);
836	    }
837	}
838	fflush(fdout);
839#ifndef HAVE_FCHMOD
840	chmod(makefile, st.st_mode);
841#else
842        fchmod(fileno(fdout), st.st_mode);
843#endif /* HAVE_FCHMOD */
844}
845
846void
847fatalerr(const char *msg, ...)
848{
849	va_list args;
850	fprintf(stderr, "%s: error:  ", ProgramName);
851	va_start(args, msg);
852	vfprintf(stderr, msg, args);
853	va_end(args);
854	exit (1);
855}
856
857void
858warning(const char *msg, ...)
859{
860	va_list args;
861	fprintf(stderr, "%s: warning:  ", ProgramName);
862	va_start(args, msg);
863	vfprintf(stderr, msg, args);
864	va_end(args);
865}
866
867void
868warning1(const char *msg, ...)
869{
870	va_list args;
871	va_start(args, msg);
872	vfprintf(stderr, msg, args);
873	va_end(args);
874}
875