home *** CD-ROM | disk | FTP | other *** search
- /* GNU m4 -- A simple macro processor
- Copyright (C) 1989, 90, 91, 92, 93 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- #include "m4.h"
-
- #ifdef HAVE_TMPFILE
- extern FILE *tmpfile ();
- #endif
-
- /* Output functions. Most of the complexity is for handling cpp like
- sync lines.
-
- This code is fairly entangled with the code in input.c, and maybe it
- belongs there? */
-
- /* Number of input line we are generating output for. */
- int output_current_line;
-
- /* Current output stream. */
- static FILE *output;
-
- /* Table of diversion files. */
- static FILE **divtab;
-
-
- /*-------------------------------------------------------------------------.
- | Output initialisation. It handles allocation of memory for diversions. |
- | This is done dynamically, to allow customisation of the number of |
- | available diversions. |
- `-------------------------------------------------------------------------*/
-
- void
- output_init (void)
- {
- int i;
-
- output = stdout;
-
- divtab = (FILE **) xmalloc (ndiversion * sizeof (FILE *));
- for (i = 0; i < ndiversion; i++)
- divtab[i] = NULL;
- divtab[0] = stdout;
- }
-
-
- /*-------------------------------------------------------------------------.
- | Output TEXT to either an obstack or a file. If OBS is NULL, and there |
- | is no output file, the text is discarded. |
- | |
- | If we are generating sync lines, the output have to be examined, because |
- | we need to know how much output each input line generates. In general, |
- | sync lines are output whenever a single input lines generates several |
- | output lines, or when several input lines does not generate any output. |
- `-------------------------------------------------------------------------*/
-
- void
- shipout_text (struct obstack *obs, char *text)
- {
- static boolean start_of_output_line = TRUE;
-
- if (obs != NULL)
- { /* output to obstack OBS */
- obstack_grow (obs, text, strlen (text));
- return;
- }
- if (output == NULL) /* discard TEXT */
- return;
-
- if (!sync_output)
- fputs (text, output);
- else
- for (; *text; text++)
- {
- if (start_of_output_line)
- {
- start_of_output_line = FALSE;
- output_current_line++;
-
- #ifdef DEBUG_OUTPUT
- printf ("DEBUG: cur %d, cur out %d\n",
- current_line, output_current_line);
- #endif
-
- /* Output a `#line NUM' synchronisation directive if needed.
- If output_current_line was previously given a negative
- value (invalidated), rather output `#line NUM "FILE"'. */
-
- if (output_current_line != current_line)
- {
- if (output != NULL)
- {
- fprintf (output, "#line %d", current_line);
- if (output_current_line < 1)
- fprintf (output, " \"%s\"", current_file);
- putc ('\n', output);
- }
- output_current_line = current_line;
- }
- }
- putc (*text, output);
- if (*text == '\n')
- start_of_output_line = TRUE;
- }
- }
-
- /* Functions for use by diversions. */
-
- #ifndef HAVE_TMPFILE
-
- /* Implement tmpfile(3) for non-USG systems. */
- static int mkstemp ();
- extern int unlink ();
-
- static FILE *
- tmpfile (void)
- {
- char buf[32];
- int fd;
-
- strcpy (buf, "/tmp/m4XXXXXX");
- fd = mkstemp (buf);
- if (fd < 0)
- return NULL;
-
- unlink (buf);
- return fdopen (fd, "w+");
- }
-
- #ifndef HAVE_MKSTEMP
-
- /* This implementation of mkstemp(3) does not avoid any races, but its
- there. */
-
- #include <sys/types.h>
- #include <fcntl.h>
-
- static int
- mkstemp (char *tmpl)
- {
- mktemp (tmpl);
- return open (tmpl, O_RDWR | O_TRUNC | O_CREAT, 0600);
- }
-
- #endif /* not HAVE_MKSTEMP */
-
- #endif /* not HAVE_TMPFILE */
-
- /*------------------------------------------------------------------------.
- | Make a file for diversion DIVNUM, and install it in the diversion table |
- | "divtab". The file is opened read-write, so we can unlink it |
- | immediately. |
- `------------------------------------------------------------------------*/
-
- void
- make_diversion (int divnum)
- {
- if (output != NULL)
- fflush (output);
-
- if (divnum < 0 || divnum >= ndiversion)
- {
- output = NULL;
- return;
- }
-
- if (divtab[divnum] == NULL)
- {
- divtab[divnum] = tmpfile ();
- if (divtab[divnum] == NULL)
- fatal ("can't create file for diversion: %s", syserr ());
- }
- output = divtab[divnum];
- output_current_line = -1;
- }
-
- /*-------------------------------------------------------------------.
- | Insert a FILE into the current output file, in tha same manner |
- | diversions are handled. This allows files to be included, without |
- | having them rescanned by m4. |
- `-------------------------------------------------------------------*/
-
- void
- insert_file (FILE *file)
- {
- int ch;
-
- while ((ch = getc (file)) != EOF)
- putc (ch, output);
- }
-
- /*-------------------------------------------------------------------------.
- | Insert diversion number DIVNUM into the current output file. The |
- | diversion is NOT placed on the expansion obstack, because it must not be |
- | rescanned. When the file is closed, it is deleted by the system. |
- `-------------------------------------------------------------------------*/
-
- void
- insert_diversion (int divnum)
- {
- FILE *div;
-
- if (divnum < 0 || divnum >= ndiversion)
- return;
-
- div = divtab[divnum];
- if (div == NULL || div == output)
- return;
-
- if (output != NULL)
- {
- rewind (div);
- insert_file (div);
- output_current_line = -1;
- }
- fclose (div);
- divtab[divnum] = NULL;
- }
-
- /*-------------------------------------------------------------------------.
- | Get back all diversions. This is done just before exiting from main (), |
- | and from m4_undivert (), if called without arguments. |
- `-------------------------------------------------------------------------*/
-
- void
- undivert_all (void)
- {
- int divnum;
-
- for (divnum = 1; divnum < ndiversion; divnum++)
- insert_diversion (divnum);
- }
-