aboutsummaryrefslogtreecommitdiffstats
path: root/z40.c
diff options
context:
space:
mode:
Diffstat (limited to 'z40.c')
-rw-r--r--z40.c255
1 files changed, 255 insertions, 0 deletions
diff --git a/z40.c b/z40.c
new file mode 100644
index 0000000..4998849
--- /dev/null
+++ b/z40.c
@@ -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 */