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