st_size is a quad and must be cast to an int in read() call.
[unix-history] / usr / src / local / X11R5 / mit / config / imake.c
CommitLineData
8558199a
EA
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__
98FILE * 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)
136typedef int waitType;
137#else /* X_NOT_POSIX */
138#ifdef SYSV
139#define waitCode(w) (((w) >> 8) & 0x7f)
140#define waitSig(w) ((w) & 0xff)
141typedef 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)
146typedef 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
158char *malloc(), *realloc();
159void exit();
160#endif
161#if defined(macII) && !defined(__STDC__) /* stdlib.h fails to define these */
162char *malloc(), *realloc();
163#endif /* macII */
164#ifdef X_NOT_STDC_ENV
165extern char *getenv();
166#endif
167#include <errno.h>
168extern int errno;
169#include "imakemdep.h"
170
171
172#define TRUE 1
173#define FALSE 0
174
175#ifdef FIXUP_CPP_WHITESPACE
176int 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
189typedef 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
203char *cpp = DEFAULT_CPP;
204
205char *tmpMakefile = "/tmp/Imf.XXXXXX";
206char *tmpImakefile = "/tmp/IIf.XXXXXX";
207char *make_argv[ ARGUMENTS ] = { "make" };
208
209int make_argindex;
210int cpp_argindex;
211char *make = NULL;
212char *Imakefile = NULL;
213char *Makefile = "Makefile";
214char *Template = "Imake.tmpl";
215char *program;
216char *FindImakefile();
217char *ReadLine();
218char *CleanCppInput();
219char *Strdup();
220#if defined(__STDC__) || defined(__GNUC__)
221char *Emalloc(int);
222#else
223char *Emalloc();
224#endif
225
226boolean verbose = FALSE;
227boolean show = TRUE;
228
229main(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
272showit(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
285wrapup()
286{
287 if (tmpMakefile != Makefile)
288 unlink(tmpMakefile);
289 unlink(tmpImakefile);
290}
291
292#ifdef SIGNALRETURNSINT
293int
294#else
295void
296#endif
297catch(sig)
298 int sig;
299{
300 errno = 0;
301 LogFatalI("Signal %d.", sig);
302}
303
304/*
305 * Initialize some variables.
306 */
307init()
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
343AddMakeArg(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
353AddCppArg(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
363SetOpts(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
422char *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
443LogFatalI(s, i)
444 char *s;
445 int i;
446{
447 /*NOSTRICT*/
448 LogFatal(s, (char *)i);
449}
450
451LogFatal(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
470showargs(argv)
471 char **argv;
472{
473 for (; *argv; argv++)
474 fprintf(stderr, "%s ", *argv);
475 fprintf(stderr, "\n");
476}
477
478cppit(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
531makeit()
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
561char *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);
cfbe8f42 582 if (read(infd, buf, (size_t) st.st_size) != st.st_size)
8558199a
EA
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
633CleanCppOutput(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 */
667isempty(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*/
705char *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"#",
747NULL };
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
777writetmpfile(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
787char *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
798KludgeOutputLine(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
823KludgeResetRule()
824{
825 InRule = FALSE;
826}
827#endif /* FIXUP_CPP_WHITESPACE */
828
829char *Strdup(cp)
830 register char *cp;
831{
832 register char *new = Emalloc(strlen(cp) + 1);
833
834 strcpy(new, cp);
835 return new;
836}