diff options
Diffstat (limited to 'z40.c')
-rw-r--r-- | z40.c | 255 |
1 files changed, 255 insertions, 0 deletions
@@ -0,0 +1,255 @@ +/*@z40.c:Filter Handler:FilterInit()@*****************************************/ +/* */ +/* THE LOUT DOCUMENT FORMATTING SYSTEM (VERSION 3.17) */ +/* COPYRIGHT (C) 1991, 1999 Jeffrey H. Kingston */ +/* */ +/* Jeffrey H. Kingston (jeff@cs.usyd.edu.au) */ +/* Basser Department of Computer Science */ +/* The University of Sydney 2006 */ +/* AUSTRALIA */ +/* */ +/* 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., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA */ +/* */ +/* FILE: z40.c */ +/* MODULE: Filter Handler */ +/* EXTERNS: FilterInit(), FilterCreate(), FilterSetFileNames(), */ +/* FilterExecute(), FilterWrite(), FilterScavenge() */ +/* */ +/*****************************************************************************/ +#include "externs.h" + + +static int filter_count; /* number of filter files */ +static OBJECT filter_active; /* the active filter file records */ +static OBJECT filter_in_filename; /* initial name of filter input file */ +static OBJECT filter_out_filename; /* initial name of filter ouput file */ + + +/*****************************************************************************/ +/* */ +/* FilterInit() */ +/* */ +/* Initialize this module. */ +/* */ +/*****************************************************************************/ + +void FilterInit(void) +{ filter_count = 0; + New(filter_active, ACAT); + sym_body(FilterInSym) = MakeWord(WORD, FILTER_IN, no_fpos); + sym_body(FilterOutSym) = MakeWord(WORD, FILTER_OUT, no_fpos); + sym_body(FilterErrSym) = MakeWord(WORD, FILTER_ERR, no_fpos); + filter_in_filename = sym_body(FilterInSym); + filter_out_filename = sym_body(FilterOutSym); +} /* end FilterInit */ + + +/*@::FilterCreate(), FilterSetFileNames()@************************************/ +/* */ +/* OBJECT FilterCreate(use_begin, act, xfpos) */ +/* */ +/* Create and return a new FILTERED object. Open the corresponding file */ +/* for writing and dump the parameter text to be filtered into it. */ +/* */ +/*****************************************************************************/ + +OBJECT FilterCreate(BOOLEAN use_begin, OBJECT act, FILE_POS *xfpos) +{ FULL_CHAR buff[MAX_LINE]; FILE *fp; OBJECT x, res, junk; + debug3(DFH, D, "FilterCreate(%s, %s, %s)", bool(use_begin), + SymName(act), EchoFilePos(xfpos)); + New(res, FILTERED); + FposCopy(fpos(res), *xfpos); + ++filter_count; + sprintf( (char *) buff, "%s%d", FILTER_IN, filter_count); + fp = StringFOpen(buff, WRITE_TEXT); + if( fp == NULL ) + Error(40, 1, "cannot open temporary filter file %s", FATAL, xfpos, buff); + x = MakeWord(WORD, buff, xfpos); + filter_use_begin(x) = use_begin; + filter_actual(x) = act; + Link(res, x); + Link(filter_active, x); + junk = LexScanVerbatim(fp, use_begin, xfpos, FALSE); + fclose(fp); + sprintf( (char *) buff, "%s%d", FILTER_OUT, filter_count); + x = MakeWord(WORD, buff, xfpos); + Link(res, x); + debug2(DFH, D, "FilterCreate returning %d %s", (int) res, EchoObject(res)); + return res; +} /* end FilterCreate */ + + +/*****************************************************************************/ +/* */ +/* FilterSetFileNames(x) */ +/* */ +/* Set @FilterIn, @FilterOut, and @FilterErr to suitable values for the */ +/* manifesting of the command which runs filter x. */ +/* */ +/*****************************************************************************/ + +void FilterSetFileNames(OBJECT x) +{ OBJECT y; + assert( type(x) == FILTERED, "FilterSetFileNames: type(x)!" ); + assert( Down(x) != x, "FilterSetFileNames: x has no children!" ); + debug2(DFH, D, "FilterSetFileNames(%d %s)", (int) x, EchoObject(x)); + Child(y, Down(x)); + assert( type(y) == WORD, "FilterSetFileNames: type(y)!" ); + sym_body(FilterInSym) = y; + Child(y, NextDown(Down(x))); + assert( type(y) == WORD, "FilterSetFileNames: type(y) (2)!" ); + sym_body(FilterOutSym) = y; + debug0(DFH, D, "FilterSetFileNames returning."); +} /* end FilterSetFileNames */ + + +/*@::FilterExecute()@*********************************************************/ +/* */ +/* OBJECT FilterExecute(x, command, env) */ +/* */ +/* Execute the filter command on FILTERED object x, and return the result. */ +/* */ +/*****************************************************************************/ + +OBJECT FilterExecute(OBJECT x, FULL_CHAR *command, OBJECT env) +{ int i, count, status; OBJECT t, res; char line[MAX_LINE]; + FILE *err_fp; FILE_NUM filter_out_file; + + assert( type(x) == FILTERED, "FilterExecute: type(x)!" ); + assert( type(env) == ENV, "FilterExecute: type(env)!" ); + debug4(DFH, D, "FilterExecute(%d %s, \"%s\", %s)", (int) x, EchoObject(x), + command, EchoObject(env)); + + /* reset FilterInSym since Manifest of @Filter is now complete */ + sym_body(FilterInSym) = filter_in_filename; + + if( SafeExecution ) + { + /* if safe execution, print error message and return empty object */ + Error(40, 2, "safe execution prohibiting command: %s", WARN, &fpos(x), + command); + res = MakeWord(WORD, STR_EMPTY, &fpos(x)); + } + else + { + /* execute the command, echo error messages, and exit if status problem */ + status = system( (char *) command); + err_fp = StringFOpen(FILTER_ERR, READ_TEXT); + if( err_fp != NULL ) + { while( fgets(line, MAX_LINE, err_fp) != NULL ) + { if( line[strlen(line)-1] == '\n' ) + line[strlen(line)-1] = '\0'; + Error(40, 3, "%s", WARN, &fpos(x), line); + } + fclose(err_fp); + StringRemove(FILTER_ERR); + } + if( status != 0 ) + Error(40, 4, "failure (non-zero status) of filter: %s", + FATAL, &fpos(x), command); + + /* read in output of system command as a Lout object */ + SwitchScope(nilobj); + count = 0; + SetScope(env, &count, TRUE); + debug0(DFS, D, " calling DefineFile from FilterExecute"); + filter_out_file = + DefineFile(string(sym_body(FilterOutSym)), STR_EMPTY, &fpos(x), + FILTER_FILE, SOURCE_PATH); + LexPush(filter_out_file, 0, FILTER_FILE, 1, FALSE); + t = NewToken(BEGIN, &fpos(x), 0, 0, BEGIN_PREC, FilterOutSym); + res = Parse(&t, nilobj, FALSE, FALSE); + LexPop(); + for( i = 1; i <= count; i++ ) PopScope(); + UnSwitchScope(nilobj); + StringRemove(string(sym_body(FilterOutSym))); + sym_body(FilterOutSym) = filter_out_filename; + } + + debug1(DFH, D, "FilterExecute returning %s", EchoObject(res)); + return res; +} /* end FilterExecute */ + + +/*@::FilterWrite(), FilterScavenge()@*****************************************/ +/* */ +/* FilterWrite(x, fp, linecount) */ +/* */ +/* Write out the active FILTERED object x by copying the file. */ +/* Increment *linecount by the number of lines written. */ +/* */ +/*****************************************************************************/ + +void FilterWrite(OBJECT x, FILE *fp, int *linecount) +{ FILE *in_fp; OBJECT y; int ch; + assert( type(x) == FILTERED, "FilterWrite: type(x)!" ); + debug2(DFH, D, "[ FilterWrite(%d %s, fp)", (int) x, EchoObject(x)); + Child(y, Down(x)); + in_fp = StringFOpen(string(y), READ_TEXT); + if( in_fp == NULL ) + Error(40, 5, "cannot read filter temporary file %s", + FATAL, &fpos(x), string(y)); + if( filter_use_begin(y) ) + { StringFPuts(KW_BEGIN, fp); + StringFPuts("\n", fp); + *linecount += 1; + while( (ch = getc(in_fp)) != EOF ) + { putc(ch, fp); + if( ch == '\n' ) *linecount += 1; + } + StringFPuts(KW_END, fp); + StringFPuts(" ", fp); + StringFPuts(SymName(filter_actual(y)), fp); + } + else + { StringFPuts(KW_LBR, fp); + StringFPuts("\n", fp); + *linecount += 1; + while( (ch = getc(in_fp)) != EOF ) + { putc(ch, fp); + ifdebug(DFH, D, putc(ch, stderr)); + if( ch == '\n' ) *linecount += 1; + } + StringFPuts(KW_RBR, fp); + } + StringFPuts("\n", fp); + *linecount += 1; + fclose(in_fp); + debug0(DFH, D, "] FilterWrite returning."); +} /* end FilterWrite */ + + +/*****************************************************************************/ +/* */ +/* FilterScavenge(all) */ +/* */ +/* Unlink unneeded filter files, or all remaining filter files if all. */ +/* */ +/*****************************************************************************/ + +void FilterScavenge(BOOLEAN all) +{ OBJECT y, link, nextlink; + debug1(DFH, D, "FilterScavenge(%s)", bool(all)); + for( link = Down(filter_active); link != filter_active; link = nextlink ) + { Child(y, link); + nextlink = NextDown(link); + if( all || Up(y) == LastUp(y) ) + { debug1(DFH, D, "FilterScavenge scavenging %s", string(y)); + StringRemove(string(y)); + DisposeChild(link); + } + } + debug0(DFH, D, "FilterScavenge returning."); +} /* end FilterScavenge */ |