1 /*
2
3 Copyright (c) 1993, 1994, 1998 The Open Group
4
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in 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
53 int _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
66 const char *ProgramName;
67
68 const 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
91 struct inclist inclist[ MAXFILES ],
92 *inclistp = inclist,
93 *inclistnext = inclist,
94 maininclist;
95
96 static char *filelist[ MAXFILES ];
97 const char *includedirs[ MAXDIRS + 1 ],
98 **includedirsnext = includedirs;
99 char *notdotdot[ MAXDIRS ];
100 static int cmdinc_count = 0;
101 static char *cmdinc_list[ 2 * MAXINCFILES ];
102 const char *objprefix = "";
103 const char *objsuffix = OBJSUFFIX;
104 static const char *startat = "# DO NOT DELETE";
105 int width = 78;
106 static boolean append = FALSE;
107 boolean printed = FALSE;
108 boolean verbose = FALSE;
109 boolean show_where_not = FALSE;
110 /* Warn on multiple includes of same file */
111 boolean warn_multiple = FALSE;
112
113 static void setfile_cmdinc(struct filepointer *filep, long count, char **list);
114 static void redirect(const char *line, const char *makefile);
115
116 static void _X_NORETURN
catch(int sig)117 catch (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
134 static struct sigaction sig_act;
135 #endif /* USGISH */
136
137 int
main(int argc,char * argv[])138 main(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
518 struct filepointer *
getfile(const char * file)519 getfile(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
551 void
setfile_cmdinc(struct filepointer * filep,long count,char ** list)552 setfile_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
559 void
freefile(struct filepointer * fp)560 freefile(struct filepointer *fp)
561 {
562 free(fp->f_base);
563 free(fp);
564 }
565
566 int
match(const char * str,const char * const * list)567 match(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 */
getnextline(struct filepointer * filep)581 char *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;
691 done:
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 */
base_name(const char * in_file)705 char *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
rename(char * from,char * to)717 int 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
729 static void
redirect(const char * line,const char * makefile)730 redirect(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
801 void
fatalerr(const char * msg,...)802 fatalerr(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
812 void
warning(const char * msg,...)813 warning(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
822 void
warning1(const char * msg,...)823 warning1(const char *msg, ...)
824 {
825 va_list args;
826 va_start(args, msg);
827 vfprintf(stderr, msg, args);
828 va_end(args);
829 }
830