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