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
main(argc,argv)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
showit(fd)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
wrapup()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
catch(sig)297 catch(sig)
298 int sig;
299 {
300 errno = 0;
301 LogFatalI("Signal %d.", sig);
302 }
303
304 /*
305 * Initialize some variables.
306 */
init()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
AddMakeArg(arg)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
AddCppArg(arg)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
SetOpts(argc,argv)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
FindImakefile(Imakefile)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
LogFatalI(s,i)443 LogFatalI(s, i)
444 char *s;
445 int i;
446 {
447 /*NOSTRICT*/
448 LogFatal(s, (char *)i);
449 }
450
LogFatal(x0,x1)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
showargs(argv)470 showargs(argv)
471 char **argv;
472 {
473 for (; *argv; argv++)
474 fprintf(stderr, "%s ", *argv);
475 fprintf(stderr, "\n");
476 }
477
cppit(Imakefile,template,outfd,outfname)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
makeit()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
CleanCppInput(Imakefile)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, (size_t) 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
CleanCppOutput(tmpfd,tmpfname)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 */
isempty(line)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*/
ReadLine(tmpfd,tmpfname)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
writetmpfile(fd,buf,cnt)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
Emalloc(size)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
KludgeOutputLine(pline)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
KludgeResetRule()823 KludgeResetRule()
824 {
825 InRule = FALSE;
826 }
827 #endif /* FIXUP_CPP_WHITESPACE */
828
Strdup(cp)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