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