home *** CD-ROM | disk | FTP | other *** search
- /*
- * GNU m4 -- A simple macro processor
- * Copyright (C) 1989, 1990 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 1, 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.
- */
-
- /*
- * MS-DOS port (c) 1990 by Thorsten Ohl, ohl@gnu.ai.mit.edu
- * This port is also distributed under the terms of the
- * GNU General Public License as published by the
- * Free Software Foundation.
- *
- * Please note that this file is not identical to the
- * original GNU release, you should have received this
- * code as patch to the official release.
- *
- * $Header: e:/gnu/m4/RCS/output.c 0.5.1.0 90/09/28 18:36:42 tho Exp $
- */
-
- #include "m4.h"
-
- #ifdef MSDOS
- #include <io.h>
- #include <malloc.h>
- int mkstemp (char *tmpl);
- #endif /* MSDOS */
-
- /*
- * 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 output lines for current input line */
- int output_lines;
-
- /* 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;
-
- /* number of diversions allocated */
- static int ndivertion;
-
-
- /*
- * Output initialisation. It handles allocation of memory for
- * diversions. This is done dynamically, in case we want to expand it
- * later.
- */
- void
- output_init()
- {
- int i;
-
- output = stdout;
-
- ndivertion = 10;
- divtab = (FILE **)xmalloc(ndivertion * sizeof(FILE *));
- for (i = 0; i < ndivertion; i++)
- divtab[i] = nil;
- divtab[0] = stdout;
- }
-
-
- /*
- * Output a sync line for line number LINE, with an optional file name
- * FILE specified.
- */
-
- void
- sync_line(line, file)
- int line;
- char *file;
- {
- if (output == nil)
- return;
-
- fprintf(output, "#line %d", line);
- if (file != nil)
- fprintf(output, " \"%s\"", file);
- putc('\n', output);
- }
-
- /*
- * Output TEXT to either an obstack or a file. If OBS is nil, 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(obs, text)
- struct obstack *obs;
- char *text;
- {
- static boolean start_of_output_line = true;
-
- if (obs != nil) { /* output to obstack OBS */
- obstack_grow(obs, text, strlen(text));
- return;
- }
- if (output == nil) /* discard TEXT */
- return;
-
- if (!sync_output)
- fputs(text, output);
- else {
- for (; *text != '\0'; text++) {
- if (start_of_output_line) {
- start_of_output_line = false;
-
- #ifdef DEBUG_OUTPUT
- printf("DEBUG: cur %d, cur out %d, out %d\n",
- current_line, output_current_line, output_lines);
- #endif
-
- if (current_line - output_current_line > 1 || output_lines > 1)
- sync_line(current_line, nil);
-
- output_current_line = current_line;
- }
- putc(*text, output);
- if (*text == '\n') {
- output_lines++;
- start_of_output_line = true;
- }
- }
- }
- }
-
- /*
- * Functions for use by diversions.
- */
-
- #if defined(USG) || defined(ultrix)
- /*
- * This does not avoid any races, but its there. Poor bastards.
- */
- #include <fcntl.h>
-
- int
- mkstemp(tmpl)
- char *tmpl;
- {
- mktemp(tmpl);
- return open(tmpl, O_RDWR|O_TRUNC|O_CREAT, 0600);
- }
- #endif /* USG */
-
-
- #ifdef MSDOS
- char template_base[] = "/m4%02dXXXXXX";
- char *template;
- #endif /* MSDOS */
-
- /*
- * 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_divertion(divnum)
- int divnum;
- {
- char buf[256];
- int fd;
-
- if (output != nil)
- fflush(output);
-
- if (divnum < 0 || divnum > ndivertion) {
- output = nil;
- return;
- }
-
- if (divtab[divnum] == nil) {
- #ifdef MSDOS
- {
- char *p;
-
- if ((p = getenv ("TMP")) || (p = getenv ("TEMP")))
- {
- int len = strlen (p);
- template = (char *) alloca (sizeof (template_base) + len + 1);
- strcpy (template, p);
- p = template + len - 1;
- if (*p == '/' || *p == '\\') /* strip trailing slash */
- *p = '\0';
- }
- else
- {
- template = (char *) alloca (sizeof (template_base) + 2);
- strcpy (template, ".");
- }
- strcat (template, template_base);
- }
- sprintf(buf, template, divnum);
- #else /* not MSDOS */
- sprintf(buf, "/tmp/m4.%02d.XXXXXX", divnum);
- #endif /* not MSDOS */
- fd = mkstemp(buf);
- if (fd < 0)
- fatal("can't create file for diversion: %s", syserr());
- divtab[divnum] = fdopen(fd, "w+");
- unlink(buf);
- }
- output = divtab[divnum];
-
- if (sync_output)
- sync_line(current_line, current_file);
- }
-
- /*
- * 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_divertion(divnum)
- int divnum;
- {
- FILE *div;
- int ch;
-
- if (divnum < 0 || divnum > ndivertion)
- return;
-
- div = divtab[divnum];
- if (div == nil || div == output)
- return;
-
- if (output != nil) {
- rewind(div);
- while ((ch = getc(div)) != EOF)
- putc(ch, output);
-
- if (sync_output)
- sync_line(current_line, current_file); /* BUG HERE -- undivert in the middle of line*/
- }
- fclose(div);
- }
-
-
- /*
- * Get back all diversions. This is done just before exiting from
- * main(), and from m4_undivert(), if called without arguments.
- */
- void
- undivert_all()
- {
- int divnum;
-
- for (divnum = 1; divnum < ndivertion; divnum++)
- insert_divertion(divnum);
- }
-