home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-387-Vol-3of3.iso
/
m
/
m4v05as.zip
/
OUTPUT.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-02-22
|
7KB
|
280 lines
/*
* 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);
}