1 /* $XConsortium: imake.c,v 1.65 91/07/25 17:50:17 rws Exp $ */ 2 3 /*****************************************************************************\ 4 * * 5 * Porting Note * 6 * * 7 * Add the value of BOOTSTRAPCFLAGS to the cpp_argv table so that it will be * 8 * passed to the template file. * 9 * * 10 \*****************************************************************************/ 11 12 /* 13 * 14 * Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology 15 * 16 * Permission to use, copy, modify, and distribute this 17 * software and its documentation for any purpose and without 18 * fee is hereby granted, provided that the above copyright 19 * notice appear in all copies and that both that copyright 20 * notice and this permission notice appear in supporting 21 * documentation, and that the name of M.I.T. not be used in 22 * advertising or publicity pertaining to distribution of the 23 * software without specific, written prior permission. 24 * M.I.T. makes no representations about the suitability of 25 * this software for any purpose. It is provided "as is" 26 * without express or implied warranty. 27 * 28 * Original Author: 29 * Todd Brunhoff 30 * Tektronix, inc. 31 * While a guest engineer at Project Athena, MIT 32 * 33 * imake: the include-make program. 34 * 35 * Usage: imake [-Idir] [-Ddefine] [-T] [-f imakefile ] [-s] [-e] [-v] [make flags] 36 * 37 * Imake takes a template makefile (Imake.tmpl) and runs cpp on it 38 * producing a temporary makefile in /tmp. It then runs make on 39 * this pre-processed makefile. 40 * Options: 41 * -D define. Same as cpp -D argument. 42 * -I Include directory. Same as cpp -I argument. 43 * -T template. Designate a template other 44 * than Imake.tmpl 45 * -s[F] show. Show the produced makefile on the standard 46 * output. Make is not run is this case. If a file 47 * argument is provided, the output is placed there. 48 * -e[F] execute instead of show; optionally name Makefile F 49 * -v verbose. Show the make command line executed. 50 * 51 * Environment variables: 52 * 53 * IMAKEINCLUDE Include directory to use in addition to "." 54 * IMAKECPP Cpp to use instead of /lib/cpp 55 * IMAKEMAKE make program to use other than what is 56 * found by searching the $PATH variable. 57 * Other features: 58 * imake reads the entire cpp output into memory and then scans it 59 * for occurences of "@@". If it encounters them, it replaces it with 60 * a newline. It also trims any trailing white space on output lines 61 * (because make gets upset at them). This helps when cpp expands 62 * multi-line macros but you want them to appear on multiple lines. 63 * 64 * The macros MAKEFILE and MAKE are provided as macros 65 * to make. MAKEFILE is set to imake's makefile (not the constructed, 66 * preprocessed one) and MAKE is set to argv[0], i.e. the name of 67 * the imake program. 68 * 69 * Theory of operation: 70 * 1. Determine the name of the imakefile from the command line (-f) 71 * or from the content of the current directory (Imakefile or imakefile). 72 * Call this <imakefile>. This gets added to the arguments for 73 * make as MAKEFILE=<imakefile>. 74 * 2. Determine the name of the template from the command line (-T) 75 * or the default, Imake.tmpl. Call this <template> 76 * 3. Start up cpp an provide it with three lines of input: 77 * #define IMAKE_TEMPLATE " <template> " 78 * #define INCLUDE_IMAKEFILE < <imakefile> > 79 * #include IMAKE_TEMPLATE 80 * Note that the define for INCLUDE_IMAKEFILE is intended for 81 * use in the template file. This implies that the imake is 82 * useless unless the template file contains at least the line 83 * #include INCLUDE_IMAKEFILE 84 * 4. Gather the output from cpp, and clean it up, expanding @@ to 85 * newlines, stripping trailing white space, cpp control lines, 86 * and extra blank lines. This cleaned output is placed in a 87 * temporary file. Call this <makefile>. 88 * 5. Start up make specifying <makefile> as its input. 89 * 90 * The design of the template makefile should therefore be: 91 * <set global macros like CFLAGS, etc.> 92 * <include machine dependent additions> 93 * #include INCLUDE_IMAKEFILE 94 * <add any global targets like 'clean' and long dependencies> 95 */ 96 #include <stdio.h> 97 #if (defined(SVR4) || defined(_IBMR2) || defined(SYSV386)) && __STDC__ 98 FILE * fdopen(); 99 #endif 100 #include <ctype.h> 101 #include "Xosdefs.h" 102 #ifndef X_NOT_POSIX 103 #define _POSIX_SOURCE 104 #endif 105 #include <sys/types.h> 106 #include <fcntl.h> 107 #ifdef X_NOT_POSIX 108 #include <sys/file.h> 109 #else 110 #ifdef hp9000 111 #undef _POSIX_SOURCE 112 #endif 113 #include <unistd.h> 114 #ifdef hp9000 115 #define _POSIX_SOURCE 116 #endif 117 #endif 118 #if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE) 119 #include <signal.h> 120 #else 121 #define _POSIX_SOURCE 122 #include <signal.h> 123 #undef _POSIX_SOURCE 124 #endif 125 #include <sys/stat.h> 126 #ifndef X_NOT_POSIX 127 #ifdef _POSIX_SOURCE 128 #include <sys/wait.h> 129 #else 130 #define _POSIX_SOURCE 131 #include <sys/wait.h> 132 #undef _POSIX_SOURCE 133 #endif 134 #define waitCode(w) WEXITSTATUS(w) 135 #define waitSig(w) WTERMSIG(w) 136 typedef int waitType; 137 #else /* X_NOT_POSIX */ 138 #ifdef SYSV 139 #define waitCode(w) (((w) >> 8) & 0x7f) 140 #define waitSig(w) ((w) & 0xff) 141 typedef int waitType; 142 #else /* SYSV */ 143 #include <sys/wait.h> 144 #define waitCode(w) ((w).w_T.w_Retcode) 145 #define waitSig(w) ((w).w_T.w_Termsig) 146 typedef union wait waitType; 147 #endif 148 #ifndef WIFSIGNALED 149 #define WIFSIGNALED(w) waitSig(w) 150 #endif 151 #ifndef WIFEXITED 152 #define WIFEXITED(w) waitCode(w) 153 #endif 154 #endif /* X_NOT_POSIX */ 155 #ifndef X_NOT_STDC_ENV 156 #include <stdlib.h> 157 #else 158 char *malloc(), *realloc(); 159 void exit(); 160 #endif 161 #if defined(macII) && !defined(__STDC__) /* stdlib.h fails to define these */ 162 char *malloc(), *realloc(); 163 #endif /* macII */ 164 #ifdef X_NOT_STDC_ENV 165 extern char *getenv(); 166 #endif 167 #include <errno.h> 168 extern int errno; 169 #include "imakemdep.h" 170 171 172 #define TRUE 1 173 #define FALSE 0 174 175 #ifdef FIXUP_CPP_WHITESPACE 176 int InRule = FALSE; 177 #endif 178 179 /* 180 * Some versions of cpp reduce all tabs in macro expansion to a single 181 * space. In addition, the escaped newline may be replaced with a 182 * space instead of being deleted. Blech. 183 */ 184 #ifndef FIXUP_CPP_WHITESPACE 185 #define KludgeOutputLine(arg) 186 #define KludgeResetRule() 187 #endif 188 189 typedef unsigned char boolean; 190 191 #ifndef DEFAULT_CPP 192 #ifdef USE_CC_E 193 #define DEFAULT_CPP "/bin/cc" 194 #else 195 #ifdef CPP_PROGRAM 196 #define DEFAULT_CPP CPP_PROGRAM 197 #else 198 #define DEFAULT_CPP "/lib/cpp" 199 #endif 200 #endif 201 #endif 202 203 char *cpp = DEFAULT_CPP; 204 205 char *tmpMakefile = "/tmp/Imf.XXXXXX"; 206 char *tmpImakefile = "/tmp/IIf.XXXXXX"; 207 char *make_argv[ ARGUMENTS ] = { "make" }; 208 209 int make_argindex; 210 int cpp_argindex; 211 char *make = NULL; 212 char *Imakefile = NULL; 213 char *Makefile = "Makefile"; 214 char *Template = "Imake.tmpl"; 215 char *program; 216 char *FindImakefile(); 217 char *ReadLine(); 218 char *CleanCppInput(); 219 char *Strdup(); 220 #if defined(__STDC__) || defined(__GNUC__) 221 char *Emalloc(int); 222 #else 223 char *Emalloc(); 224 #endif 225 226 boolean verbose = FALSE; 227 boolean show = TRUE; 228 229 main(argc, argv) 230 int argc; 231 char **argv; 232 { 233 FILE *tmpfd; 234 char makeMacro[ BUFSIZ ]; 235 char makefileMacro[ BUFSIZ ]; 236 237 program = argv[0]; 238 init(); 239 SetOpts(argc, argv); 240 #ifdef USE_CC_E 241 AddCppArg("-"); 242 #endif 243 244 Imakefile = FindImakefile(Imakefile); 245 if (Makefile) 246 tmpMakefile = Makefile; 247 else { 248 tmpMakefile = Strdup(tmpMakefile); 249 (void) mktemp(tmpMakefile); 250 } 251 AddMakeArg("-f"); 252 AddMakeArg( tmpMakefile ); 253 sprintf(makeMacro, "MAKE=%s", program); 254 AddMakeArg( makeMacro ); 255 sprintf(makefileMacro, "MAKEFILE=%s", Imakefile); 256 AddMakeArg( makefileMacro ); 257 258 if ((tmpfd = fopen(tmpMakefile, "w+")) == NULL) 259 LogFatal("Cannot create temporary file %s.", tmpMakefile); 260 261 cppit(Imakefile, Template, tmpfd, tmpMakefile); 262 263 if (show) { 264 if (Makefile == NULL) 265 showit(tmpfd); 266 } else 267 makeit(); 268 wrapup(); 269 exit(0); 270 } 271 272 showit(fd) 273 FILE *fd; 274 { 275 char buf[ BUFSIZ ]; 276 int red; 277 278 fseek(fd, 0, 0); 279 while ((red = fread(buf, 1, BUFSIZ, fd)) > 0) 280 fwrite(buf, red, 1, stdout); 281 if (red < 0) 282 LogFatal("Cannot write stdout.", ""); 283 } 284 285 wrapup() 286 { 287 if (tmpMakefile != Makefile) 288 unlink(tmpMakefile); 289 unlink(tmpImakefile); 290 } 291 292 #ifdef SIGNALRETURNSINT 293 int 294 #else 295 void 296 #endif 297 catch(sig) 298 int sig; 299 { 300 errno = 0; 301 LogFatalI("Signal %d.", sig); 302 } 303 304 /* 305 * Initialize some variables. 306 */ 307 init() 308 { 309 char *p; 310 311 make_argindex=0; 312 while (make_argv[ make_argindex ] != NULL) 313 make_argindex++; 314 cpp_argindex = 0; 315 while (cpp_argv[ cpp_argindex ] != NULL) 316 cpp_argindex++; 317 318 /* 319 * See if the standard include directory is different than 320 * the default. Or if cpp is not the default. Or if the make 321 * found by the PATH variable is not the default. 322 */ 323 if (p = getenv("IMAKEINCLUDE")) { 324 if (*p != '-' || *(p+1) != 'I') 325 LogFatal("Environment var IMAKEINCLUDE %s\n", 326 "must begin with -I"); 327 AddCppArg(p); 328 for (; *p; p++) 329 if (*p == ' ') { 330 *p++ = '\0'; 331 AddCppArg(p); 332 } 333 } 334 if (p = getenv("IMAKECPP")) 335 cpp = p; 336 if (p = getenv("IMAKEMAKE")) 337 make = p; 338 339 if (signal(SIGINT, SIG_IGN) != SIG_IGN) 340 signal(SIGINT, catch); 341 } 342 343 AddMakeArg(arg) 344 char *arg; 345 { 346 errno = 0; 347 if (make_argindex >= ARGUMENTS-1) 348 LogFatal("Out of internal storage.", ""); 349 make_argv[ make_argindex++ ] = arg; 350 make_argv[ make_argindex ] = NULL; 351 } 352 353 AddCppArg(arg) 354 char *arg; 355 { 356 errno = 0; 357 if (cpp_argindex >= ARGUMENTS-1) 358 LogFatal("Out of internal storage.", ""); 359 cpp_argv[ cpp_argindex++ ] = arg; 360 cpp_argv[ cpp_argindex ] = NULL; 361 } 362 363 SetOpts(argc, argv) 364 int argc; 365 char **argv; 366 { 367 errno = 0; 368 /* 369 * Now gather the arguments for make 370 */ 371 for(argc--, argv++; argc; argc--, argv++) { 372 /* 373 * We intercept these flags. 374 */ 375 if (argv[0][0] == '-') { 376 if (argv[0][1] == 'D') { 377 AddCppArg(argv[0]); 378 } else if (argv[0][1] == 'I') { 379 AddCppArg(argv[0]); 380 } else if (argv[0][1] == 'f') { 381 if (argv[0][2]) 382 Imakefile = argv[0]+2; 383 else { 384 argc--, argv++; 385 if (! argc) 386 LogFatal("No description arg after -f flag\n", ""); 387 Imakefile = argv[0]; 388 } 389 } else if (argv[0][1] == 's') { 390 if (argv[0][2]) 391 Makefile = ((argv[0][2] == '-') && !argv[0][3]) ? 392 NULL : argv[0]+2; 393 else { 394 argc--, argv++; 395 if (!argc) 396 LogFatal("No description arg after -s flag\n", ""); 397 Makefile = ((argv[0][0] == '-') && !argv[0][1]) ? 398 NULL : argv[0]; 399 } 400 show = TRUE; 401 } else if (argv[0][1] == 'e') { 402 Makefile = (argv[0][2] ? argv[0]+2 : NULL); 403 show = FALSE; 404 } else if (argv[0][1] == 'T') { 405 if (argv[0][2]) 406 Template = argv[0]+2; 407 else { 408 argc--, argv++; 409 if (! argc) 410 LogFatal("No description arg after -T flag\n", ""); 411 Template = argv[0]; 412 } 413 } else if (argv[0][1] == 'v') { 414 verbose = TRUE; 415 } else 416 AddMakeArg(argv[0]); 417 } else 418 AddMakeArg(argv[0]); 419 } 420 } 421 422 char *FindImakefile(Imakefile) 423 char *Imakefile; 424 { 425 int fd; 426 427 if (Imakefile) { 428 if ((fd = open(Imakefile, O_RDONLY)) < 0) 429 LogFatal("Cannot open %s.", Imakefile); 430 } else { 431 if ((fd = open("Imakefile", O_RDONLY)) < 0) 432 if ((fd = open("imakefile", O_RDONLY)) < 0) 433 LogFatal("No description file.", ""); 434 else 435 Imakefile = "imakefile"; 436 else 437 Imakefile = "Imakefile"; 438 } 439 close (fd); 440 return(Imakefile); 441 } 442 443 LogFatalI(s, i) 444 char *s; 445 int i; 446 { 447 /*NOSTRICT*/ 448 LogFatal(s, (char *)i); 449 } 450 451 LogFatal(x0,x1) 452 char *x0, *x1; 453 { 454 extern char *sys_errlist[]; 455 static boolean entered = FALSE; 456 457 if (entered) 458 return; 459 entered = TRUE; 460 461 fprintf(stderr, "%s: ", program); 462 if (errno) 463 fprintf(stderr, "%s: ", sys_errlist[ errno ]); 464 fprintf(stderr, x0,x1); 465 fprintf(stderr, " Stop.\n"); 466 wrapup(); 467 exit(1); 468 } 469 470 showargs(argv) 471 char **argv; 472 { 473 for (; *argv; argv++) 474 fprintf(stderr, "%s ", *argv); 475 fprintf(stderr, "\n"); 476 } 477 478 cppit(Imakefile, template, outfd, outfname) 479 char *Imakefile; 480 char *template; 481 FILE *outfd; 482 char *outfname; 483 { 484 FILE *pipeFile; 485 int pid, pipefd[2]; 486 waitType status; 487 char *cleanedImakefile; 488 489 /* 490 * Get a pipe. 491 */ 492 if (pipe(pipefd) < 0) 493 LogFatal("Cannot make a pipe.", ""); 494 495 /* 496 * Fork and exec cpp 497 */ 498 pid = fork(); 499 if (pid < 0) 500 LogFatal("Cannot fork.", ""); 501 if (pid) { /* parent */ 502 close(pipefd[0]); 503 cleanedImakefile = CleanCppInput(Imakefile); 504 if ((pipeFile = fdopen(pipefd[1], "w")) == NULL) 505 LogFatalI("Cannot fdopen fd %d for output.", pipefd[1]); 506 fprintf(pipeFile, "#define IMAKE_TEMPLATE\t\"%s\"\n", 507 template); 508 fprintf(pipeFile, "#define INCLUDE_IMAKEFILE\t<%s>\n", 509 cleanedImakefile); 510 fprintf(pipeFile, "#include IMAKE_TEMPLATE\n"); 511 fclose(pipeFile); 512 while (wait(&status) > 0) { 513 errno = 0; 514 if (WIFSIGNALED(status)) 515 LogFatalI("Signal %d.", waitSig(status)); 516 if (WIFEXITED(status) && waitCode(status)) 517 LogFatalI("Exit code %d.", waitCode(status)); 518 } 519 CleanCppOutput(outfd, outfname); 520 } else { /* child... dup and exec cpp */ 521 if (verbose) 522 showargs(cpp_argv); 523 dup2(pipefd[0], 0); 524 dup2(fileno(outfd), 1); 525 close(pipefd[1]); 526 execv(cpp, cpp_argv); 527 LogFatal("Cannot exec %s.", cpp); 528 } 529 } 530 531 makeit() 532 { 533 int pid; 534 waitType status; 535 536 /* 537 * Fork and exec make 538 */ 539 pid = fork(); 540 if (pid < 0) 541 LogFatal("Cannot fork.", ""); 542 if (pid) { /* parent... simply wait */ 543 while (wait(&status) > 0) { 544 errno = 0; 545 if (WIFSIGNALED(status)) 546 LogFatalI("Signal %d.", waitSig(status)); 547 if (WIFEXITED(status) && waitCode(status)) 548 LogFatalI("Exit code %d.", waitCode(status)); 549 } 550 } else { /* child... dup and exec cpp */ 551 if (verbose) 552 showargs(make_argv); 553 if (make) 554 execv(make, make_argv); 555 else 556 execvp("make", make_argv); 557 LogFatal("Cannot exec %s.", make); 558 } 559 } 560 561 char *CleanCppInput(Imakefile) 562 char *Imakefile; 563 { 564 FILE *outFile = NULL; 565 int infd; 566 char *buf, /* buffer for file content */ 567 *pbuf, /* walking pointer to buf */ 568 *punwritten, /* pointer to unwritten portion of buf */ 569 *cleanedImakefile = Imakefile, /* return value */ 570 *ptoken, /* pointer to # token */ 571 *pend, /* pointer to end of # token */ 572 savec; /* temporary character holder */ 573 struct stat st; 574 575 /* 576 * grab the entire file. 577 */ 578 if ((infd = open(Imakefile, O_RDONLY)) < 0) 579 LogFatal("Cannot open %s for input.", Imakefile); 580 fstat(infd, &st); 581 buf = Emalloc(st.st_size+1); 582 if (read(infd, buf, st.st_size) != st.st_size) 583 LogFatal("Cannot read all of %s:", Imakefile); 584 close(infd); 585 buf[ st.st_size ] = '\0'; 586 587 punwritten = pbuf = buf; 588 while (*pbuf) { 589 /* pad make comments for cpp */ 590 if (*pbuf == '#' && (pbuf == buf || pbuf[-1] == '\n')) { 591 592 ptoken = pbuf+1; 593 while (*ptoken == ' ' || *ptoken == '\t') 594 ptoken++; 595 pend = ptoken; 596 while (*pend && *pend != ' ' && *pend != '\t' && *pend != '\n') 597 pend++; 598 savec = *pend; 599 *pend = '\0'; 600 if (strcmp(ptoken, "include") 601 && strcmp(ptoken, "define") 602 && strcmp(ptoken, "undef") 603 && strcmp(ptoken, "ifdef") 604 && strcmp(ptoken, "ifndef") 605 && strcmp(ptoken, "else") 606 && strcmp(ptoken, "endif") 607 && strcmp(ptoken, "if")) { 608 if (outFile == NULL) { 609 tmpImakefile = Strdup(tmpImakefile); 610 (void) mktemp(tmpImakefile); 611 cleanedImakefile = tmpImakefile; 612 outFile = fopen(tmpImakefile, "w"); 613 if (outFile == NULL) 614 LogFatal("Cannot open %s for write.\n", 615 tmpImakefile); 616 } 617 fwrite(punwritten, sizeof(char), pbuf-punwritten, outFile); 618 fputs("/**/", outFile); 619 punwritten = pbuf; 620 } 621 *pend = savec; 622 } 623 pbuf++; 624 } 625 if (outFile) { 626 fwrite(punwritten, sizeof(char), pbuf-punwritten, outFile); 627 fclose(outFile); /* also closes the pipe */ 628 } 629 630 return(cleanedImakefile); 631 } 632 633 CleanCppOutput(tmpfd, tmpfname) 634 FILE *tmpfd; 635 char *tmpfname; 636 { 637 char *input; 638 int blankline = 0; 639 640 while(input = ReadLine(tmpfd, tmpfname)) { 641 if (isempty(input)) { 642 if (blankline++) 643 continue; 644 KludgeResetRule(); 645 } else { 646 blankline = 0; 647 KludgeOutputLine(&input); 648 fputs(input, tmpfd); 649 } 650 putc('\n', tmpfd); 651 } 652 fflush(tmpfd); 653 #ifdef NFS_STDOUT_BUG 654 /* 655 * On some systems, NFS seems to leave a large number of nulls at 656 * the end of the file. Ralph Swick says that this kludge makes the 657 * problem go away. 658 */ 659 ftruncate (fileno(tmpfd), (off_t)ftell(tmpfd)); 660 #endif 661 } 662 663 /* 664 * Determine of a line has nothing in it. As a side effect, we trim white 665 * space from the end of the line. Cpp magic cookies are also thrown away. 666 */ 667 isempty(line) 668 char *line; 669 { 670 char *pend; 671 672 /* 673 * Check for lines of the form 674 * # n "... 675 * or 676 * # line n "... 677 */ 678 if (*line == '#') { 679 pend = line+1; 680 if (*pend == ' ') 681 pend++; 682 if (strncmp(pend, "line ", 5) == 0) 683 pend += 5; 684 if (isdigit(*pend)) { 685 while (isdigit(*pend)) 686 pend++; 687 if (*pend++ == ' ' && *pend == '"') 688 return(TRUE); 689 } 690 } 691 692 /* 693 * Find the end of the line and then walk back. 694 */ 695 for (pend=line; *pend; pend++) ; 696 697 pend--; 698 while (pend >= line && (*pend == ' ' || *pend == '\t')) 699 pend--; 700 *++pend = '\0'; 701 return (*line == '\0'); 702 } 703 704 /*ARGSUSED*/ 705 char *ReadLine(tmpfd, tmpfname) 706 FILE *tmpfd; 707 char *tmpfname; 708 { 709 static boolean initialized = FALSE; 710 static char *buf, *pline, *end; 711 char *p1, *p2; 712 713 if (! initialized) { 714 int total_red; 715 struct stat st; 716 717 /* 718 * Slurp it all up. 719 */ 720 fseek(tmpfd, 0, 0); 721 fstat(fileno(tmpfd), &st); 722 pline = buf = Emalloc(st.st_size+1); 723 total_red = read(fileno(tmpfd), buf, st.st_size); 724 if (total_red != st.st_size) 725 LogFatal("cannot read %s\n", tmpMakefile); 726 end = buf + st.st_size; 727 *end = '\0'; 728 lseek(fileno(tmpfd), 0, 0); 729 #ifdef SYSV 730 freopen(tmpfname, "w+", tmpfd); 731 #else /* !SYSV */ 732 ftruncate(fileno(tmpfd), 0); 733 #endif /* !SYSV */ 734 initialized = TRUE; 735 fprintf (tmpfd, "# Makefile generated by imake - do not edit!\n"); 736 fprintf (tmpfd, "# %s\n", 737 "$XConsortium: imake.c,v 1.65 91/07/25 17:50:17 rws Exp $"); 738 739 #ifdef FIXUP_CPP_WHITESPACE 740 { 741 static char *cpp_warning[] = { 742 "#", 743 "# The cpp used on this machine replaces all newlines and multiple tabs and", 744 "# spaces in a macro expansion with a single space. Imake tries to compensate", 745 "# for this, but is not always successful.", 746 "#", 747 NULL }; 748 char **cpp; 749 750 for (cpp = cpp_warning; *cpp; cpp++) { 751 fprintf (tmpfd, "%s\n", *cpp); 752 } 753 } 754 #endif /* FIXUP_CPP_WHITESPACE */ 755 } 756 757 for (p1 = pline; p1 < end; p1++) { 758 if (*p1 == '@' && *(p1+1) == '@') { /* soft EOL */ 759 *p1++ = '\0'; 760 p1++; /* skip over second @ */ 761 break; 762 } 763 else if (*p1 == '\n') { /* real EOL */ 764 *p1++ = '\0'; 765 break; 766 } 767 } 768 769 /* 770 * return NULL at the end of the file. 771 */ 772 p2 = (pline == p1 ? NULL : pline); 773 pline = p1; 774 return(p2); 775 } 776 777 writetmpfile(fd, buf, cnt) 778 FILE *fd; 779 int cnt; 780 char *buf; 781 { 782 errno = 0; 783 if (fwrite(buf, cnt, 1, fd) != 1) 784 LogFatal("Cannot write to %s.", tmpMakefile); 785 } 786 787 char *Emalloc(size) 788 int size; 789 { 790 char *p; 791 792 if ((p = malloc(size)) == NULL) 793 LogFatalI("Cannot allocate %d bytes\n", size); 794 return(p); 795 } 796 797 #ifdef FIXUP_CPP_WHITESPACE 798 KludgeOutputLine(pline) 799 char **pline; 800 { 801 char *p = *pline; 802 803 switch (*p) { 804 case '#': /*Comment - ignore*/ 805 break; 806 case '\t': /*Already tabbed - ignore it*/ 807 break; 808 case ' ': /*May need a tab*/ 809 default: 810 for (; *p; p++) if (p[0] == ':' && 811 p > *pline && p[-1] != '\\') { 812 if (**pline == ' ') 813 (*pline)++; 814 InRule = TRUE; 815 break; 816 } 817 if (InRule && **pline == ' ') 818 **pline = '\t'; 819 break; 820 } 821 } 822 823 KludgeResetRule() 824 { 825 InRule = FALSE; 826 } 827 #endif /* FIXUP_CPP_WHITESPACE */ 828 829 char *Strdup(cp) 830 register char *cp; 831 { 832 register char *new = Emalloc(strlen(cp) + 1); 833 834 strcpy(new, cp); 835 return new; 836 } 837