summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/devices/grohtml2/Makefile.in9
-rwxr-xr-xsrc/devices/grohtml2/Makefile.sub9
-rwxr-xr-xsrc/devices/grohtml2/post-html.cc93
-rwxr-xr-xsrc/preproc/html2/Makefile.sub7
-rwxr-xr-xsrc/preproc/html2/image.cc452
-rwxr-xr-xsrc/preproc/html2/pre-html.cc774
-rwxr-xr-xsrc/preproc/html2/pre-html.h37
-rwxr-xr-xsrc/preproc/html2/pushbackbuffer.cc312
-rwxr-xr-xsrc/preproc/html2/pushbackbuffer.h53
9 files changed, 1746 insertions, 0 deletions
diff --git a/src/devices/grohtml2/Makefile.in b/src/devices/grohtml2/Makefile.in
new file mode 100755
index 00000000..bca59ad7
--- /dev/null
+++ b/src/devices/grohtml2/Makefile.in
@@ -0,0 +1,9 @@
+PROG=post-grohtml
+MAN1=
+XLIBS=$(LIBDRIVER) $(LIBGROFF)
+MLIB=$(LIBM)
+OBJS=\
+ post-html.o
+CCSRCS=\
+ $(srcdir)/post-html.cc
+
diff --git a/src/devices/grohtml2/Makefile.sub b/src/devices/grohtml2/Makefile.sub
new file mode 100755
index 00000000..f43a276d
--- /dev/null
+++ b/src/devices/grohtml2/Makefile.sub
@@ -0,0 +1,9 @@
+PROG=post-grohtml
+MAN1=
+# MAN1=grohtml.n
+XLIBS=$(LIBDRIVER) $(LIBGROFF)
+MLIB=$(LIBM)
+OBJS=\
+ post-html.o
+CCSRCS=\
+ $(srcdir)/post-html.cc
diff --git a/src/devices/grohtml2/post-html.cc b/src/devices/grohtml2/post-html.cc
new file mode 100755
index 00000000..1693f106
--- /dev/null
+++ b/src/devices/grohtml2/post-html.cc
@@ -0,0 +1,93 @@
+// -*- C++ -*-
+/* Copyright (C) 1999 Free Software Foundation, Inc.
+ *
+ * Gaius Mulley (gaius@glam.ac.uk) wrote post-html.cc
+ * but it owes a huge amount of ideas and raw code from
+ * James Clark (jjc@jclark.com) grops/ps.cc.
+ */
+
+/*
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "driver.h"
+#include "stringclass.h"
+#include "cset.h"
+
+#include <time.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include <fcntl.h>
+
+#if !defined(TRUE)
+# define TRUE (1==1)
+#endif
+#if !defined(FALSE)
+# define FALSE (1==0)
+#endif
+
+printer *make_printer()
+{
+ // return new html_printer;
+ return( 0 );
+}
+
+static void usage();
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ int c;
+ while ((c = getopt(argc, argv, "F:atTvdgmx?I:r:")) != EOF)
+ switch(c) {
+ case 'v':
+ {
+ extern const char *Version_string;
+ fprintf(stderr, "post-grohtml version %s\n", Version_string);
+ fflush(stderr);
+ break;
+ }
+ case 'F':
+ font::command_line_font_dir(optarg);
+ break;
+ case '?':
+ usage();
+ break;
+ default:
+ assert(0);
+ }
+ if (optind >= argc) {
+ do_file("-");
+ } else {
+ for (int i = optind; i < argc; i++)
+ do_file(argv[i]);
+ }
+ delete pr;
+ return 0;
+}
+
+static void usage()
+{
+ fprintf(stderr, "usage: %s [-avdgmt?] [-r resolution] [-F dir] [-I imagetype] [files ...]\n",
+ program_name);
+ exit(1);
+}
diff --git a/src/preproc/html2/Makefile.sub b/src/preproc/html2/Makefile.sub
new file mode 100755
index 00000000..9d5045a9
--- /dev/null
+++ b/src/preproc/html2/Makefile.sub
@@ -0,0 +1,7 @@
+PROG=pre-grohtml
+# MAN1=pre-grohtml.n
+MAN1=
+XLIBS=$(LIBGROFF)
+OBJS=pre-html.o pushbackbuffer.o
+CCSRCS=$(srcdir)/pre-html.cc $(srcdir)/pushbackbuffer.cc
+NAMEPREFIX=$(g)
diff --git a/src/preproc/html2/image.cc b/src/preproc/html2/image.cc
new file mode 100755
index 00000000..23708b64
--- /dev/null
+++ b/src/preproc/html2/image.cc
@@ -0,0 +1,452 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by Gaius Mulley (gaius@glam.ac.uk) but owes much
+ of the code from James Clark (jjc@jclark.com).
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <signal.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "lib.h"
+#include "errarg.h"
+#include "error.h"
+#include "stringclass.h"
+#include "posix.h"
+
+#include <errno.h>
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifndef errno
+extern int errno;
+#endif
+
+#ifdef _POSIX_VERSION
+#include <sys/wait.h>
+#define PID_T pid_t
+#else /* not _POSIX_VERSION */
+#define PID_T int
+#endif /* not _POSIX_VERSION */
+
+extern char *strerror();
+
+static char *file_contents;
+static int stdoutfd =1; // output file descriptor - normally 1 but might move
+ // -1 means closed
+
+#define DEBUGGING
+
+/*
+ * eventually it would be nice to have the choice of image devices.
+ * This could be implemented once we have a -Tpng or -Tpdf device driver.
+ * For now we use what is available.. postscript, ghostscript + png utils.
+ */
+
+#define IMAGEDEVICE "-Tps"
+
+
+static int do_file(const char *filename);
+
+/*
+ * sys_fatal - writes a fatal error message. Taken from src/roff/groff/pipeline.c
+ */
+
+static void sys_fatal(const char *s)
+{
+ fprintf(stderr, "%s: %s: %s", program_name, s, strerror(errno));
+}
+
+ sprintf(buffer,
+ "echo showpage | gs -q -dSAFER -sDEVICE=%s -r%d -g%dx%d -sOutputFile=- %s - 2> /dev/null > %s.png \n",
+ image_device,
+ image_res,
+ (end_region_hpos-start_region_hpos)*image_res/font::res+IMAGE_BOARDER_PIXELS,
+ (end_region_vpos-start_region_vpos)*image_res/font::res+IMAGE_BOARDER_PIXELS,
+ ps_src, image_name);
+
+
+/*
+ * the class and methods for retaining ascii text
+ */
+
+struct char_block {
+ enum { SIZE = 256 };
+ char buffer[SIZE];
+ int used;
+ char_block *next;
+
+ char_block();
+};
+
+char_block::char_block()
+: used(0), next(0)
+{
+}
+
+class char_buffer {
+public:
+ char_buffer();
+ ~char_buffer();
+ int read_file(FILE *fp);
+ int do_html(int argc, char *argv[]);
+ int do_image(int argc, char *argv[]);
+ int write_file(int is_html);
+private:
+ char_block *head;
+ char_block *tail;
+};
+
+char_buffer::char_buffer()
+: head(0), tail(0)
+{
+}
+
+char_buffer::~char_buffer()
+{
+ while (head != 0) {
+ char_block *temp = head;
+ head = head->next;
+ delete temp;
+ }
+}
+
+int char_buffer::read_file (FILE *fp)
+{
+ int i=0;
+ unsigned int old_used;
+ int n;
+
+ while (! feof(fp)) {
+ if (tail == 0) {
+ tail = new char_block;
+ head = tail;
+ } else {
+ if (tail->used == char_block::SIZE) {
+ tail->next = new char_block;
+ tail = tail->next;
+ }
+ }
+ // at this point we have a tail which is ready for the the next SIZE bytes of the file
+
+ n = fread(tail->buffer, sizeof(char), char_block::SIZE-tail->used, fp);
+ if (n <= 0) {
+ // error
+ return( 0 );
+ } else {
+ tail->used += n*sizeof(char);
+ }
+ }
+ return( 1 );
+}
+
+/*
+ * writeNbytes - writes n bytes to stdout.
+ */
+
+static void writeNbytes (char *s, int l)
+{
+ int n=0;
+ int r;
+
+ while (n<l) {
+ r = write(stdoutfd, s, l-n);
+ if (r<0) {
+ sys_fatal("write");
+ }
+ n += r;
+ s += r;
+ }
+}
+
+/*
+ * writeString - writes a string to stdout.
+ */
+
+static void writeString (char *s)
+{
+ writeNbytes(s, strlen(s));
+}
+
+/*
+ * write_file - writes the buffer to stdout (troff).
+ * It prepends the number register set to 1 if stdout is
+ * connected to troff -Thtml and 0 if connected to troff -Tps
+ */
+
+int char_buffer::write_file (int is_html)
+{
+ char_block *t=head;
+ int r;
+
+ fprintf(stderr, "output to pipeline\n");
+ if (is_html) {
+ writeString(".nr htmlflip 1\n");
+ } else {
+ writeString(".nr htmlflip 0\n");
+ fprintf(stderr, ".nr htmlflip 0\n");
+ }
+ if (t != 0) {
+ do {
+ writeNbytes(t->buffer, t->used);
+ fprintf(stderr, "hunk..\n");
+ t = t->next;
+ } while ((t != head) && (t != 0));
+ }
+ if (close(stdoutfd) < 0)
+ sys_fatal("close");
+
+ // now we grab fd=1 so that the next pipe cannot use fd=1
+ if (stdoutfd == 1) {
+ if (dup(2) != stdoutfd) {
+ sys_fatal("dup failed to use fd=1");
+ }
+ }
+
+ return( 1 );
+}
+
+/*
+ * replaceFd - replace a file descriptor, was, with, willbe.
+ */
+
+static void replaceFd (int was, int willbe)
+{
+ int dupres;
+
+ if (was != willbe) {
+ if (close(was)<0) {
+ sys_fatal("close");
+ }
+ dupres = dup(willbe);
+ if (dupres != was) {
+ sys_fatal("dup");
+ fprintf(stderr, "trying to replace fd=%d with %d dup used %d\n", was, willbe, dupres);
+ if (willbe == 1) {
+ fprintf(stderr, "likely that stdout should be opened before %d\n", was);
+ }
+ exit(1);
+ }
+ if (close(willbe) < 0) {
+ sys_fatal("close");
+ }
+ }
+}
+
+/*
+ * waitForChild - waits for child, pid, to exit.
+ */
+
+static void waitForChild (PID_T pid)
+{
+ PID_T waitpd;
+ int status;
+
+ waitpd = wait(&status);
+ if (waitpd != pid)
+ sys_fatal("wait");
+}
+
+/*
+ * do_html - sets the troff number htmlflip and
+ * writes out the buffer to troff -Thtml
+ */
+
+int char_buffer::do_html(int argc, char *argv[])
+{
+ int pdes[2];
+ PID_T pid;
+
+ if (pipe(pdes) < 0)
+ sys_fatal("pipe");
+
+ argv++; // skip pre-grohtml argv[0]
+ pid = fork();
+ if (pid < 0)
+ sys_fatal("fork");
+
+ if (pid == 0) {
+ // child
+ replaceFd(0, pdes[0]);
+ // close end we are not using
+ if (close(pdes[1])<0)
+ sys_fatal("close");
+
+ execvp(argv[0], argv);
+ error("couldn't exec %1: %2", argv[0], strerror(errno), (char *)0);
+ fflush(stderr); /* just in case error() doesn't */
+ exit(1);
+ } else {
+ // parent
+
+ replaceFd(1, pdes[1]);
+ // close end we are not using
+ if (close(pdes[0])<0)
+ sys_fatal("close");
+
+ write_file(1);
+ waitForChild(pid);
+ }
+ return( 0 );
+}
+
+/*
+ * alterToDeviceImage - manipulates the argv to include IMAGEDEVICE rather than -Thtml2
+ */
+
+static void alterToDeviceImage (int argc, char *argv[])
+{
+ int i=0;
+
+ while (i < argc) {
+ if (strcmp(argv[i], "-Thtml2") == 0) {
+ argv[i] = IMAGEDEVICE;
+ }
+ i++;
+ }
+ argv[1] = "groff"; /* rather than troff */
+}
+
+/*
+ * do_image - sets the troff number htmlflip and
+ * writes out the buffer to troff -Tps
+ */
+
+int char_buffer::do_image(int argc, char *argv[])
+{
+ PID_T pid;
+ int pdes[2];
+
+ if (pipe(pdes) < 0)
+ sys_fatal("pipe");
+
+ alterToDeviceImage(argc, argv);
+ argv++; // skip pre-grohtml argv[0]
+
+ pid = fork();
+ if (pid == 0) {
+ // child
+
+#if defined(DEBUGGING)
+ int psFd = creat("/tmp/prehtml-ps", S_IWUSR|S_IRUSR);
+ int regionFd = creat("/tmp/prehtml-region", S_IWUSR|S_IRUSR);
+#else
+ int psFd = mkstemp(xtmptemplate("-ps-"));
+ int regionFd = mkstemp(xtmptemplate("-regions-"));
+#endif
+
+ fprintf(stderr, "about to exec %s\n", argv[0]);
+ replaceFd(1, psFd);
+ replaceFd(0, pdes[0]);
+ replaceFd(2, regionFd);
+
+ // close end we are not using
+ if (close(pdes[1])<0)
+ sys_fatal("close");
+
+ execvp(argv[0], argv);
+ error("couldn't exec %1: %2", argv[0], strerror(errno), (char *)0);
+ fflush(stderr); /* just in case error() doesn't */
+ exit(1);
+ } else {
+ // parent
+
+ replaceFd(1, pdes[1]);
+ write_file(0);
+ waitForChild(pid);
+ }
+ return( 0 );
+}
+
+static char_buffer inputFile;
+
+
+/*
+ * usage - emit usage arguments and exit.
+ */
+
+void usage()
+{
+ fprintf(stderr, "usage: %s troffname [ troff flags ] [ files ]\n", program_name);
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ int i; // skip over troff name
+ int found=0;
+ int ok=1;
+
+ for (i = 2; i < argc; i++) {
+ if (argv[i][0] == '-') {
+ if (argv[i][1] == 'v') {
+ extern const char *Version_string;
+ fprintf(stderr, "GNU pre-grohtml version %s\n", Version_string);
+ fflush(stderr);
+ }
+ } else {
+ ok = do_file(argv[i]);
+ if (! ok) {
+ return( 0 );
+ }
+ found = 1;
+ }
+ }
+
+ if (! found) {
+ do_file("-");
+ }
+ ok = inputFile.do_html(argc, argv);
+ if (ok == 0) {
+ ok = inputFile.do_image(argc, argv);
+ if (ok == 0) {
+ // generateImages();
+ }
+ }
+ return ok;
+}
+
+static int do_file(const char *filename)
+{
+ FILE *fp;
+
+ current_filename = filename;
+ if (strcmp(filename, "-") == 0) {
+ fp = stdin;
+ } else {
+ fp = fopen(filename, "r");
+ if (fp == 0) {
+ error("can't open `%1': %2", filename, strerror(errno));
+ return 0;
+ }
+ }
+
+ if (inputFile.read_file(fp)) {
+ }
+
+ if (fp != stdin)
+ fclose(fp);
+ current_filename = 0;
+ return 1;
+}
diff --git a/src/preproc/html2/pre-html.cc b/src/preproc/html2/pre-html.cc
new file mode 100755
index 00000000..8824f3ac
--- /dev/null
+++ b/src/preproc/html2/pre-html.cc
@@ -0,0 +1,774 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by Gaius Mulley (gaius@glam.ac.uk).
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define PREHTMLC
+
+#include <stdio.h>
+#include <signal.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "lib.h"
+#include "errarg.h"
+#include "error.h"
+#include "stringclass.h"
+#include "posix.h"
+
+#include <errno.h>
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifndef errno
+extern int errno;
+#endif
+
+#ifdef _POSIX_VERSION
+#include <sys/wait.h>
+#define PID_T pid_t
+#else /* not _POSIX_VERSION */
+#define PID_T int
+#endif /* not _POSIX_VERSION */
+
+extern char *strerror();
+
+#include "pre-html.h"
+#include "pushbackbuffer.h"
+
+#define POSTSCRIPTRES 72000 // maybe there is a better way to find this? --fixme--
+#define DEFAULT_IMAGE_RES 80
+#define IMAGE_BOARDER_PIXELS 10
+
+// #define TRANSPARENT "-background \"#FFF\" -transparent \"#FFF\""
+#define TRANSPARENT ""
+
+#define DEBUGGING
+
+#if !defined(TRUE)
+# define TRUE (1==1)
+#endif
+#if !defined(FALSE)
+# define FALSE (1==0)
+#endif
+
+void stop() {}
+
+
+static int stdoutfd =1; // output file descriptor - normally 1 but might move
+ // -1 means closed
+static char *psFileName =0; // name of postscript file
+static char *regionFileName=0; // name of file containing all image regions
+static char *image_device = "pnmraw";
+static int image_res = DEFAULT_IMAGE_RES;
+
+
+/*
+ * Images are generated via postscript, gs and the pnm utilities.
+ */
+
+#define IMAGEDEVICE "-Tps"
+
+
+static int do_file(const char *filename);
+
+/*
+ * sys_fatal - writes a fatal error message. Taken from src/roff/groff/pipeline.c
+ */
+
+void sys_fatal (const char *s)
+{
+ fprintf(stderr, "%s: %s: %s", program_name, s, strerror(errno));
+}
+
+/*
+ * the class and methods for retaining ascii text
+ */
+
+struct char_block {
+ enum { SIZE = 256 };
+ char buffer[SIZE];
+ int used;
+ char_block *next;
+
+ char_block();
+};
+
+char_block::char_block()
+: used(0), next(0)
+{
+}
+
+class char_buffer {
+public:
+ char_buffer();
+ ~char_buffer();
+ int read_file(FILE *fp);
+ int do_html(int argc, char *argv[]);
+ int do_image(int argc, char *argv[]);
+ void write_file_html(void);
+ void write_file_troff(void);
+ void write_upto_newline (char_block **t, int *i);
+ int can_see(char_block **t, int *i, char *string);
+private:
+ char_block *head;
+ char_block *tail;
+};
+
+char_buffer::char_buffer()
+: head(0), tail(0)
+{
+}
+
+char_buffer::~char_buffer()
+{
+ while (head != 0) {
+ char_block *temp = head;
+ head = head->next;
+ delete temp;
+ }
+}
+
+int char_buffer::read_file (FILE *fp)
+{
+ int i=0;
+ unsigned int old_used;
+ int n;
+
+ while (! feof(fp)) {
+ if (tail == 0) {
+ tail = new char_block;
+ head = tail;
+ } else {
+ if (tail->used == char_block::SIZE) {
+ tail->next = new char_block;
+ tail = tail->next;
+ }
+ }
+ // at this point we have a tail which is ready for the next SIZE bytes of the file
+
+ n = fread(tail->buffer, sizeof(char), char_block::SIZE-tail->used, fp);
+ if (n <= 0) {
+ // error
+ return( 0 );
+ } else {
+ tail->used += n*sizeof(char);
+ }
+ }
+ return( 1 );
+}
+
+/*
+ * writeNbytes - writes n bytes to stdout.
+ */
+
+static void writeNbytes (char *s, int l)
+{
+ int n=0;
+ int r;
+
+ while (n<l) {
+ r = write(stdoutfd, s, l-n);
+ if (r<0) {
+ sys_fatal("write");
+ }
+ n += r;
+ s += r;
+ }
+}
+
+/*
+ * writeString - writes a string to stdout.
+ */
+
+static void writeString (char *s)
+{
+ writeNbytes(s, strlen(s));
+}
+
+/*
+ * write_upto_newline - writes the contents of the buffer until a newline is seen.
+ */
+
+void char_buffer::write_upto_newline (char_block **t, int *i)
+{
+ int j=*i;
+
+ if (*t) {
+ while ((j < (*t)->used) && ((*t)->buffer[j] != '\n')) {
+ j++;
+ }
+ if ((j < (*t)->used) && ((*t)->buffer[j] == '\n')) {
+ j++;
+ }
+ writeNbytes((*t)->buffer+(*i), j-(*i));
+ if (j == (*t)->used) {
+ *i = 0;
+ *t = (*t)->next;
+ write_upto_newline(t, i);
+ } else {
+ // newline was seen
+ *i = j;
+ }
+ }
+}
+
+/*
+ * can_see - returns TRUE if we can see string in t->buffer[i] onwards
+ */
+
+int char_buffer::can_see(char_block **t, int *i, char *string)
+{
+ int j = 0;
+ int l = strlen(string);
+ int k = *i;
+ char_block *s = *t;
+
+ while (s) {
+ while ((k<s->used) && (j<l) && (s->buffer[k] == string[j])) {
+ j++;
+ k++;
+ }
+ if (j == l) {
+ *i = k;
+ *t = s;
+ return( TRUE );
+ } else if ((k<s->used) && (s->buffer[k] != string[j])) {
+ return( FALSE );
+ }
+ s = s->next;
+ k = 0;
+ }
+ return( FALSE );
+}
+
+/*
+ * write_file_troff - writes the buffer to stdout (troff).
+ * It prepends the number register set to 0.
+ */
+
+void char_buffer::write_file_troff (void)
+{
+ char_block *t=head;
+ int r;
+
+ writeString(".nr html2enable 1\n");
+ writeString(".nr htmlflip 0\n");
+ if (t != 0) {
+ do {
+ writeNbytes(t->buffer, t->used);
+ t = t->next;
+ } while ((t != head) && (t != 0));
+ }
+ if (close(stdoutfd) < 0)
+ sys_fatal("close");
+
+ // now we grab fd=1 so that the next pipe cannot use fd=1
+ if (stdoutfd == 1) {
+ if (dup(2) != stdoutfd) {
+ sys_fatal("dup failed to use fd=1");
+ }
+ }
+}
+
+/*
+ * the image class remembers the position of all images in the postscript file
+ * and assigns names for each image.
+ */
+
+struct imageItem {
+ imageItem *next;
+ int X1;
+ int Y1;
+ int X2;
+ int Y2;
+ char *imageName;
+ int resolution;
+ int pageNo;
+
+ imageItem (int x1, int y1, int x2, int y2, int page, int res, char *name);
+ ~imageItem ();
+};
+
+/*
+ * imageItem - constructor
+ */
+
+imageItem::imageItem (int x1, int y1, int x2, int y2, int page, int res, char *name)
+{
+ X1 = x1;
+ Y1 = y1;
+ X2 = x2;
+ Y2 = y2;
+ pageNo = page;
+ resolution = res;
+ imageName = name;
+ next = 0;
+}
+
+/*
+ * imageItem - deconstructor
+ */
+
+imageItem::~imageItem ()
+{
+}
+
+/*
+ * imageList - class containing a list of imageItems.
+ */
+
+class imageList {
+private:
+ imageItem *head;
+ imageItem *tail;
+ int count;
+public:
+ imageList();
+ ~imageList();
+ void add(int x1, int y1, int x2, int y2, int page, int res);
+ char *get(int i);
+};
+
+/*
+ * imageList - constructor.
+ */
+
+imageList::imageList ()
+ : head(0), tail(0), count(0)
+{
+}
+
+/*
+ * imageList - deconstructor.
+ */
+
+imageList::~imageList ()
+{
+ while (head != 0) {
+ imageItem *i = head;
+ head = head->next;
+ delete i;
+ }
+}
+
+/*
+ * createImage - generates a png file from the information held in, i, and
+ * the postscript file.
+ */
+
+static void createImage (imageItem *i)
+{
+ if (i->X1 != -1) {
+ char buffer[4096];
+
+ sprintf(buffer,
+ "echo showpage | gs -q -dFirstPage=%d -dLastPage=%d -dSAFER -sDEVICE=%s -r%d -sOutputFile=- %s - 2> /dev/null | pnmcut %d %d %d %d | pnmtopng %s > %s.png \n",
+ i->pageNo, i->pageNo,
+ image_device,
+ image_res,
+ psFileName,
+ i->X1*image_res/POSTSCRIPTRES,
+ i->Y1*image_res/POSTSCRIPTRES-IMAGE_BOARDER_PIXELS,
+ (i->X2-i->X1)*image_res/POSTSCRIPTRES+IMAGE_BOARDER_PIXELS,
+ (i->Y2-i->Y1)*image_res/POSTSCRIPTRES+IMAGE_BOARDER_PIXELS,
+ TRANSPARENT,
+ i->imageName);
+ fprintf(stderr, buffer);
+ system(buffer);
+ }
+}
+
+/*
+ * add - an image description to the imageList.
+ */
+
+void imageList::add (int x1, int y1, int x2, int y2, int page, int res)
+{
+ char *name = (char *)malloc(50);
+
+ if (name == 0)
+ sys_fatal("malloc");
+
+ if (x1 == -1) {
+ name[0] = (char)0;
+ } else {
+ count++;
+ sprintf(name, "grohtml-%d", count);
+ }
+ imageItem *i = new imageItem(x1, y1, x2, y2, page, res, name);
+
+ if (head == 0) {
+ head = i;
+ tail = i;
+ } else {
+ tail->next = i;
+ tail = i;
+ }
+ createImage(i);
+}
+
+/*
+ * get - returns the name for image number, i.
+ */
+
+char *imageList::get(int i)
+{
+ imageItem *t=head;
+
+ while (i>0) {
+ if (i == 1) {
+ if (t->X1 == -1) {
+ return( NULL );
+ } else {
+ return( t->imageName );
+ }
+ }
+ t = t->next;
+ i--;
+ }
+}
+
+static imageList listOfImages; // list of images defined by the region file.
+
+/*
+ * write_file_html - writes the buffer to stdout (troff).
+ * It prepends the number register set to 1 and writes
+ * out the file replacing template image names with
+ * actual image names.
+ */
+
+void char_buffer::write_file_html (void)
+{
+ char_block *t =head;
+ int imageNo=0;
+ char *name;
+ int i=0;
+
+ writeString(".nr html2enable 1\n");
+ writeString(".nr htmlflip 1\n");
+ if (t != 0) {
+ stop();
+ do {
+ if (can_see(&t, &i, ".if '\\*(.T'html2' .IMAGE <pre-html-image>\n")) {
+ imageNo++;
+ name = listOfImages.get(imageNo);
+ if (name != 0) {
+ writeString(".if '\\*(.T'html2' .IMAGE \"");
+ writeString(name);
+ writeString(".png\"\n");
+ }
+ } else {
+ write_upto_newline(&t, &i);
+ }
+ } while (t != 0);
+ }
+ if (close(stdoutfd) < 0)
+ sys_fatal("close");
+
+ // now we grab fd=1 so that the next pipe cannot use fd=1
+ if (stdoutfd == 1) {
+ if (dup(2) != stdoutfd) {
+ sys_fatal("dup failed to use fd=1");
+ }
+ }
+}
+
+/*
+ * generateImages - parses the region file and generates images
+ * from the postscript file. The region file
+ * contains the x1,y1 x2,y2 extents of each
+ * image.
+ */
+
+static void generateImages (char *regionFileName)
+{
+ pushBackBuffer *f=new pushBackBuffer(regionFileName);
+ char ch;
+
+ if (f->putPB('\n') == '\n') {
+ }
+ while (f->putPB(f->getPB()) != eof) {
+ if (f->isString("\ngrohtml-info:page")) {
+ int page= f->readInt();
+ int x1 = f->readInt();
+ int y1 = f->readInt();
+ int x2 = f->readInt();
+ int y2 = f->readInt();
+ int res = POSTSCRIPTRES; // --fixme-- prefer (f->readInt()) providing that troff can discover the value
+ listOfImages.add(x1, y1, x2, y2, page, res);
+ }
+ ch = f->getPB();
+ }
+}
+
+/*
+ * replaceFd - replace a file descriptor, was, with, willbe.
+ */
+
+static void replaceFd (int was, int willbe)
+{
+ int dupres;
+
+ if (was != willbe) {
+ if (close(was)<0) {
+ sys_fatal("close");
+ }
+ dupres = dup(willbe);
+ if (dupres != was) {
+ sys_fatal("dup");
+ fprintf(stderr, "trying to replace fd=%d with %d dup used %d\n", was, willbe, dupres);
+ if (willbe == 1) {
+ fprintf(stderr, "likely that stdout should be opened before %d\n", was);
+ }
+ exit(1);
+ }
+ if (close(willbe) < 0) {
+ sys_fatal("close");
+ }
+ }
+}
+
+/*
+ * waitForChild - waits for child, pid, to exit.
+ */
+
+static void waitForChild (PID_T pid)
+{
+ PID_T waitpd;
+ int status;
+
+ waitpd = wait(&status);
+ if (waitpd != pid)
+ sys_fatal("wait");
+}
+
+/*
+ * alterDeviceTo - if toImage is set then the arg list is altered to include
+ * IMAGEDEVICE and we invoke groff rather than troff.
+ * else
+ * set -Thtml2 and troff
+ */
+
+static void alterDeviceTo (int argc, char *argv[], int toImage)
+{
+ int i=0;
+
+ if (toImage) {
+ while (i < argc) {
+ if (strcmp(argv[i], "-Thtml2") == 0) {
+ argv[i] = IMAGEDEVICE;
+ }
+ i++;
+ }
+ argv[1] = "groff"; /* rather than troff */
+ } else {
+ while (i < argc) {
+ if (strcmp(argv[i], IMAGEDEVICE) == 0) {
+ argv[i] = "-Thtml2";
+ }
+ i++;
+ }
+ argv[1] = "troff"; /* use troff */
+ }
+}
+
+/*
+ * do_html - sets the troff number htmlflip and
+ * writes out the buffer to troff -Thtml
+ */
+
+int char_buffer::do_html(int argc, char *argv[])
+{
+ int pdes[2];
+ PID_T pid;
+
+ if (pipe(pdes) < 0)
+ sys_fatal("pipe");
+
+ alterDeviceTo(argc, argv, 0);
+ argv++; // skip pre-grohtml argv[0]
+ pid = fork();
+ if (pid < 0)
+ sys_fatal("fork");
+
+ if (pid == 0) {
+ // child
+ replaceFd(0, pdes[0]);
+ // close end we are not using
+ if (close(pdes[1])<0)
+ sys_fatal("close");
+
+ execvp(argv[0], argv);
+ error("couldn't exec %1: %2", argv[0], strerror(errno), (char *)0);
+ fflush(stderr); /* just in case error() doesn't */
+ exit(1);
+ } else {
+ // parent
+
+ replaceFd(1, pdes[1]);
+ // close end we are not using
+ if (close(pdes[0])<0)
+ sys_fatal("close");
+
+ write_file_html();
+ waitForChild(pid);
+ }
+ return( 0 );
+}
+
+/*
+ * do_image - sets the troff number htmlflip and
+ * writes out the buffer to troff -Tps
+ */
+
+int char_buffer::do_image(int argc, char *argv[])
+{
+ PID_T pid;
+ int pdes[2];
+
+ if (pipe(pdes) < 0)
+ sys_fatal("pipe");
+
+ alterDeviceTo(argc, argv, 1);
+ argv++; // skip pre-grohtml argv[0]
+
+ pid = fork();
+ if (pid == 0) {
+ // child
+
+#if defined(DEBUGGING)
+ int psFd = creat(psFileName, S_IWUSR|S_IRUSR);
+ int regionFd = creat(regionFileName, S_IWUSR|S_IRUSR);
+#else
+ int psFd = mkstemp(psFileName);
+ int regionFd = mkstemp(regionFileName);
+#endif
+
+ replaceFd(1, psFd);
+ replaceFd(0, pdes[0]);
+ replaceFd(2, regionFd);
+
+ // close end we are not using
+ if (close(pdes[1])<0)
+ sys_fatal("close");
+
+ execvp(argv[0], argv);
+ error("couldn't exec %1: %2", argv[0], strerror(errno), (char *)0);
+ fflush(stderr); /* just in case error() doesn't */
+ exit(1);
+ } else {
+ // parent
+
+ replaceFd(1, pdes[1]);
+ write_file_troff();
+ waitForChild(pid);
+ }
+ return( 0 );
+}
+
+static char_buffer inputFile;
+
+
+/*
+ * usage - emit usage arguments and exit.
+ */
+
+void usage()
+{
+ fprintf(stderr, "usage: %s troffname [ troff flags ] [ files ]\n", program_name);
+ exit(1);
+}
+
+/*
+ * makeTempFiles - name the temporary files
+ */
+
+static void makeTempFiles (void)
+{
+#if defined(DEBUGGING)
+ psFileName = "/tmp/prehtml-ps";
+ regionFileName = "/tmp/prehtml-region";
+#else
+ psFileName = xtmptemplate("-ps-");
+ regionFileName = xtmptemplate("-regions-");
+#endif
+}
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ int i; // skip over troff name
+ int found=0;
+ int ok=1;
+
+ for (i = 2; i < argc; i++) {
+ if (argv[i][0] == '-') {
+ if (argv[i][1] == 'v') {
+ extern const char *Version_string;
+ fprintf(stderr, "GNU pre-grohtml version %s\n", Version_string);
+ fflush(stderr);
+ }
+ } else {
+ ok = do_file(argv[i]);
+ if (! ok) {
+ return( 0 );
+ }
+ found = 1;
+ }
+ }
+
+ if (! found) {
+ do_file("-");
+ }
+ makeTempFiles();
+ ok = inputFile.do_image(argc, argv);
+ if (ok == 0) {
+ generateImages(regionFileName);
+ ok = inputFile.do_html(argc, argv);
+ }
+ return ok;
+}
+
+static int do_file(const char *filename)
+{
+ FILE *fp;
+
+ current_filename = filename;
+ if (strcmp(filename, "-") == 0) {
+ fp = stdin;
+ } else {
+ fp = fopen(filename, "r");
+ if (fp == 0) {
+ error("can't open `%1': %2", filename, strerror(errno));
+ return 0;
+ }
+ }
+
+ if (inputFile.read_file(fp)) {
+ }
+
+ if (fp != stdin)
+ fclose(fp);
+ current_filename = 0;
+ return 1;
+}
diff --git a/src/preproc/html2/pre-html.h b/src/preproc/html2/pre-html.h
new file mode 100755
index 00000000..739ab4cb
--- /dev/null
+++ b/src/preproc/html2/pre-html.h
@@ -0,0 +1,37 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by Gaius Mulley (gaius@glam.ac.uk).
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ * defines functions implemented within pre-html.c
+ */
+
+#if !defined(PREHTMLH)
+# define PREHTMLH
+# if defined(PREHTMLC)
+# define EXTERN
+# else
+# define EXTERN extern
+# endif
+
+
+extern void sys_fatal (const char *s);
+
+#undef EXTERN
+#endif
diff --git a/src/preproc/html2/pushbackbuffer.cc b/src/preproc/html2/pushbackbuffer.cc
new file mode 100755
index 00000000..d556c748
--- /dev/null
+++ b/src/preproc/html2/pushbackbuffer.cc
@@ -0,0 +1,312 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by Gaius Mulley (gaius@glam.ac.uk).
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <signal.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "lib.h"
+#include "errarg.h"
+#include "error.h"
+#include "stringclass.h"
+#include "posix.h"
+
+#include <errno.h>
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifndef errno
+extern int errno;
+#endif
+
+#include "pushbackbuffer.h"
+#include "pre-html.h"
+
+#if !defined(TRUE)
+# define TRUE (1==1)
+#endif
+
+#if !defined(FALSE)
+# define FALSE (1==0)
+#endif
+
+# define ERROR(X) (fprintf(stderr, "%s:%d error %s\n", __FILE__, __LINE__, X) && \
+ (fflush(stderr)) && localexit(1))
+
+
+#define MAXPUSHBACKSTACK 4096 /* maximum number of character that can be pushed back */
+
+
+/*
+ * constructor for pushBackBuffer
+ */
+
+pushBackBuffer::pushBackBuffer (char *filename)
+{
+ charStack = (char *)malloc(MAXPUSHBACKSTACK);
+ if (charStack == 0) {
+ sys_fatal("malloc");
+ }
+ stackPtr = 0; /* index to push back stack */
+ debug = 0;
+ verbose = 0;
+ eofFound = FALSE;
+ lineNo = 1;
+ if (strcmp(filename, "") != 0) {
+ stdIn = dup(0);
+ close(0);
+ if (open(filename, O_RDONLY) != 0) {
+ sys_fatal("when tring to read graph file");
+ } else {
+ fileName = filename;
+ }
+ }
+}
+
+pushBackBuffer::~pushBackBuffer ()
+{
+ int old;
+
+ if (charStack != 0) {
+ free(charStack);
+ }
+ close(0);
+ /* restore stdin in file descriptor 0 */
+ old = dup(stdIn);
+ close(stdIn);
+}
+
+/*
+ * localexit - wraps exit with a return code to aid the ERROR macro.
+ */
+
+int localexit (int i)
+{
+ exit(i);
+ return( 1 );
+}
+
+/*
+ * getPB - returns a character, possibly a pushed back character.
+ */
+
+char pushBackBuffer::getPB (void)
+{
+ if (stackPtr>0) {
+ stackPtr--;
+ return( charStack[stackPtr] );
+ } else {
+ char ch;
+
+ if (read(0, &ch, 1) == 1) {
+ if (verbose) {
+ printf("%c", ch);
+ }
+ if (ch == '\n') {
+ lineNo++;
+ }
+ return( ch );
+ } else {
+ eofFound = TRUE;
+ return( eof );
+ }
+ }
+}
+
+/*
+ * putPB - pushes a character onto the push back stack.
+ * The same character is returned.
+ */
+
+char pushBackBuffer::putPB (char ch)
+{
+ if (stackPtr<MAXPUSHBACKSTACK) {
+ charStack[stackPtr] = ch ;
+ stackPtr++;
+ } else {
+ ERROR("max push back stack exceeded, increase MAXPUSHBACKSTACK constant");
+ }
+ return( ch );
+}
+
+/*
+ * isWhite - returns TRUE if a white character is found. This character is NOT consumed.
+ */
+
+static int isWhite (char ch)
+{
+ return( (ch==' ') || (ch == '\t') || (ch == '\n') );
+}
+
+/*
+ * skipToNewline - skips characters until a newline is seen.
+ */
+
+void pushBackBuffer::skipToNewline (void)
+{
+ char ch;
+
+ while ((putPB(getPB()) != '\n') && (! eofFound)) {
+ ch = getPB();
+ }
+}
+
+/*
+ * skipUntilToken - skips until a token is seen
+ */
+
+void pushBackBuffer::skipUntilToken (void)
+{
+ char ch;
+
+ while ((isWhite(putPB(getPB())) || (putPB(getPB()) == '#')) && (! eofFound)) {
+ ch = getPB();
+ if (ch == '#') {
+ skipToNewline();
+ }
+ }
+}
+
+/*
+ * isString - returns TRUE if the string, s, matches the pushed back string.
+ * if TRUE is returned then this string is consumed, otherwise it is
+ * left alone.
+ */
+
+int pushBackBuffer::isString (char *s)
+{
+ int length=strlen(s);
+ int i=0;
+ int j;
+
+ while ((i<length) && (putPB(getPB())==s[i])) {
+ if (getPB() != s[i]) {
+ ERROR("assert failed");
+ }
+ i++;
+ }
+ if (i==length) {
+ return( TRUE );
+ } else {
+ i--;
+ while (i>=0) {
+ if (putPB(s[i]) != s[i]) {
+ ERROR("assert failed");
+ }
+ i--;
+ }
+ }
+ return( FALSE );
+}
+
+/*
+ * isDigit - returns TRUE if the character, ch, is a digit.
+ */
+
+static int isDigit (char ch)
+{
+ return( ((ch>='0') && (ch<='9')) );
+}
+
+/*
+ * isHexDigit - returns TRUE if the character, ch, is a hex digit.
+ */
+
+static int isHexDigit (char ch)
+{
+ return( (isDigit(ch)) || ((ch>='a') && (ch<='f')) );
+}
+
+/*
+ * readInt - returns an integer from the input stream.
+ */
+
+int pushBackBuffer::readInt (void)
+{
+ int c =0;
+ int i =0;
+ int s =1;
+ char ch=getPB();
+
+ while (isWhite(ch)) {
+ ch=getPB();
+ }
+ // now read integer
+
+ if (ch == '-') {
+ s = -1;
+ ch = getPB();
+ }
+ while (isDigit(ch)) {
+ i *= 10;
+ if ((ch>='0') && (ch<='9')) {
+ i += (int)(ch-'0');
+ }
+ ch = getPB();
+ c++;
+ }
+ if (ch != putPB(ch)) {
+ ERROR("assert failed");
+ }
+ return( i*s );
+}
+
+/*
+ * convertToFloat - converts integers, a and b into a.b
+ */
+
+static float convertToFloat (int a, int b)
+{
+ int c=10;
+ float f;
+
+ while (b>c) {
+ c *= 10;
+ }
+ f = ((float)a) + (((float)b)/((float)c));
+ return( f );
+}
+
+/*
+ * readNumber - returns a float representing the word just read.
+ */
+
+float pushBackBuffer::readNumber (void)
+{
+ int integer;
+ int fraction;
+ char ch;
+ float f;
+
+ integer = readInt();
+ if (putPB(getPB()) == '.') {
+ ch = getPB();
+ fraction = readInt();
+ f = convertToFloat(integer, fraction);
+ return( f );
+ } else {
+ return( (float)integer );
+ }
+}
diff --git a/src/preproc/html2/pushbackbuffer.h b/src/preproc/html2/pushbackbuffer.h
new file mode 100755
index 00000000..569f4050
--- /dev/null
+++ b/src/preproc/html2/pushbackbuffer.h
@@ -0,0 +1,53 @@
+// -*- C -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by Gaius Mulley (gaius@glam.ac.uk).
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#define eof (char)-1
+
+
+/*
+ * defines the class and methods implemented within pbbuffer.cc
+ */
+
+class pushBackBuffer
+{
+ private:
+ char *charStack;
+ int stackPtr; /* index to push back stack */
+ int debug;
+ int verbose;
+ int eofFound;
+ char *fileName;
+ int lineNo;
+ int stdIn;
+
+ public:
+ pushBackBuffer (char *);
+ ~ pushBackBuffer ();
+ char getPB (void);
+ char putPB (char ch);
+ void skipUntilToken (void);
+ void skipToNewline (void);
+ float readNumber (void);
+ int readInt (void);
+ int isString (char *string);
+};
+
+