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