summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorwlemb <wlemb>2003-10-17 12:51:55 +0000
committerwlemb <wlemb>2003-10-17 12:51:55 +0000
commit6d49073153ac0792725d56b9e92e38c75f6ae1b3 (patch)
tree991cc7cd1894a44f89743de8d0005c46457d7e6c /src
parent48d11a2ff13f1bc894d5b56a1aee6799b8697cd0 (diff)
downloadgroff-6d49073153ac0792725d56b9e92e38c75f6ae1b3.tar.gz
* src/preproc/html/pre-html.cpp (write_upto_newline): Don't use
`(*t)->next' without testing validity of `*t'. (usage): Make it more readable. Make html device run under both MS-DOS and Win32. * src/preproc/html/pre-html.cpp (MAY_FORK_CHILD_PROCESS, MAY_SPAWN_ASYNCHRONOUS_CHILD): New macros to control whether spawn or fork+exec has to be used, and whether parent must sleep until the child process terminates. Used in `char_buffer::run_output_filter'. (copyofstdoutfd): Removed. (char_buffer): Replace `write_file_html' and `write_file_troff' member functions with `emit_troff_output' and `run_output_filter'. The latter (DEVICE_FORMAT, HTML_OUTPUT_FILTER, IMAGE_OUTPUT_FILTER): New macros. (replaceFd): Replaced with... (set_redirection): New auxiliary function. (waitForChild): Replaced with... (save_and_redirect): New auxiliary function for. (char_buffer::do_html, char_buffer::do_image): Simplified, using new functions.
Diffstat (limited to 'src')
-rw-r--r--src/preproc/html/pre-html.cpp1109
1 files changed, 633 insertions, 476 deletions
diff --git a/src/preproc/html/pre-html.cpp b/src/preproc/html/pre-html.cpp
index ee3c28e5..0fa925e5 100644
--- a/src/preproc/html/pre-html.cpp
+++ b/src/preproc/html/pre-html.cpp
@@ -39,36 +39,79 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include <errno.h>
#include <sys/types.h>
#ifdef HAVE_UNISTD_H
-#include <unistd.h>
+# include <unistd.h>
#endif
#ifdef _POSIX_VERSION
-#include <sys/wait.h>
-#define PID_T pid_t
+# include <sys/wait.h>
+# define PID_T pid_t
#else /* not _POSIX_VERSION */
-#define PID_T int
+# define PID_T int
#endif /* not _POSIX_VERSION */
#include <stdarg.h>
#include "nonposix.h"
+/* Establish some definitions to facilitate discrimination between
+ differing runtime environments. */
+
+#undef __tmpfile
+#undef MAY_FORK_CHILD_PROCESS
+#undef MAY_SPAWN_ASYNCHRONOUS_CHILD
+
+#if defined(__MSDOS__) || defined(_WIN32)
+/* Most MS-DOS and Win32 environments will be missing the `fork' capability
+ (some like Cygwin have it, but it is best avoided). */
+# define MAY_FORK_CHILD_PROCESS 0
+
+/* On these systems, we use `spawn...', instead of `fork' ... `exec...'. */
+# include <process.h> // for `spawn...'
+# include <fcntl.h> // for attributes of pipes
+
+# if defined(__CYGWIN__) || defined(_UWIN) || defined(__MINGW32__)
+/* These Win32 implementations allow parent and `spawn...'ed child to
+ multitask asynchronously. */
+# define MAY_SPAWN_ASYNCHRONOUS_CHILD 1
+# else
+/* Others may adopt MS-DOS behaviour where parent must sleep,
+ from `spawn...' until child terminates. */
+# define MAY_SPAWN_ASYNCHRONOUS_CHILD 0
+# endif /* not defined __CYGWIN__, _UWIN, or __MINGW32__ */
+
+/* MS-DOS and Win32 will probably not have `/tmp' on all disk drives,
+ but we can normally expect to be able to use `c:/temp' for temporary
+ files. */
+# define __tmpfile "c:/temp/"
+
+#else /* not __MSDOS__ or _WIN32 */
+
+/* For non-Microsoft environments assume UNIX conventions,
+ so `fork' is required and child processes are asynchronous */
+# define MAY_FORK_CHILD_PROCESS 1
+# define MAY_SPAWN_ASYNCHRONOUS_CHILD 1
+
+/* We can also usually rely on being able to use `/tmp' for temporary
+ file storage. */
+# define __tmpfile "/tmp/"
+#endif /* not __MSDOS__ or _WIN32 */
+
extern "C" const char *Version_string;
#include "pre-html.h"
#include "pushback.h"
#include "html-strings.h"
-#define DEFAULT_LINE_LENGTH 7 // inches wide
-#define DEFAULT_IMAGE_RES 100 // number of pixels per inch resolution
-#define IMAGE_BOARDER_PIXELS 0
-#define INLINE_LEADER_CHAR '\\'
+#define DEFAULT_LINE_LENGTH 7 // inches wide
+#define DEFAULT_IMAGE_RES 100 // number of pixels per inch resolution
+#define IMAGE_BOARDER_PIXELS 0
+#define INLINE_LEADER_CHAR '\\'
// Don't use colour names here! Otherwise there is a dependency on
// a file called `rgb.txt' which maps names to colours.
-#define TRANSPARENT "-background rgb:f/f/f -transparent rgb:f/f/f"
-#define MIN_ALPHA_BITS 0
-#define MAX_ALPHA_BITS 4
+#define TRANSPARENT "-background rgb:f/f/f -transparent rgb:f/f/f"
+#define MIN_ALPHA_BITS 0
+#define MAX_ALPHA_BITS 4
#define PAGE_TEMPLATE_SHORT "pg"
#define PAGE_TEMPLATE_LONG "-page-"
@@ -78,46 +121,55 @@ extern "C" const char *Version_string;
#define REGION_TEMPLATE_LONG "-regions-"
#if 0
-# define DEBUGGING
+# define DEBUGGING
#endif
#if !defined(TRUE)
-# define TRUE (1==1)
+# define TRUE (1==1)
#endif
#if !defined(FALSE)
-# define FALSE (1==0)
+# define FALSE (1==0)
#endif
-typedef enum {CENTERED, LEFT, RIGHT, INLINE} IMAGE_ALIGNMENT;
-
-static int postscriptRes =-1; // postscript resolution, dots per inch
-static int stdoutfd = 1; // output file descriptor - normally 1 but might move
- // -1 means closed
-static int copyofstdoutfd =-1; // a copy of stdout, so we can restore stdout when
- // writing to post-html
-static char *psFileName = NULL; // name of postscript file
-static char *psPageName = NULL; // name of file containing postscript current page
-static char *regionFileName = NULL; // name of file containing all image regions
-static char *imagePageName = NULL; // name of bitmap image containing current page
+typedef enum {
+ CENTERED, LEFT, RIGHT, INLINE
+} IMAGE_ALIGNMENT;
+
+static int postscriptRes = -1; // postscript resolution,
+ // dots per inch
+static int stdoutfd = 1; // output file descriptor -
+ // normally 1 but might move
+ // -1 means closed
+static char *psFileName = NULL; // name of postscript file
+static char *psPageName = NULL; // name of file containing
+ // postscript current page
+static char *regionFileName = NULL; // name of file containing all
+ // image regions
+static char *imagePageName = NULL; // name of bitmap image containing
+ // current page
static const char *image_device = "pnmraw";
-static int image_res = DEFAULT_IMAGE_RES;
-static int vertical_offset = 0;
-static char *image_template = NULL; // image template filename
-static char *macroset_template= NULL; // image template passed to troff by -D
-static int troff_arg = 0; // troff arg index
-static char *image_dir = NULL; // user specified image directory
-static int textAlphaBits = MAX_ALPHA_BITS;
-static int graphicAlphaBits = MAX_ALPHA_BITS;
-static char *antiAlias = NULL; // antialias arguments we pass to gs.
-static int show_progress = FALSE; // should we display page numbers as they are processed?
-static int currentPageNo = -1; // current image page number
+static int image_res = DEFAULT_IMAGE_RES;
+static int vertical_offset = 0;
+static char *image_template = NULL; // image template filename
+static char *macroset_template= NULL; // image template passed to troff
+ // by -D
+static int troff_arg = 0; // troff arg index
+static char *image_dir = NULL; // user specified image directory
+static int textAlphaBits = MAX_ALPHA_BITS;
+static int graphicAlphaBits = MAX_ALPHA_BITS;
+static char *antiAlias = NULL; // antialias arguments we pass to gs
+static int show_progress = FALSE; // should we display page numbers as
+ // they are processed?
+static int currentPageNo = -1; // current image page number
#if defined(DEBUGGING)
-static int debug = FALSE;
-static char *troffFileName = NULL; // output of pre-html output which is sent to troff -Tps
-static char *htmlFileName = NULL; // output of pre-html output which is sent to troff -Thtml
+static int debug = FALSE;
+static char *troffFileName = NULL; // output of pre-html output which
+ // is sent to troff -Tps
+static char *htmlFileName = NULL; // output of pre-html output which
+ // is sent to troff -Thtml
#endif
-static char *linebuf = NULL; // for scanning devps/DESC
+static char *linebuf = NULL; // for scanning devps/DESC
static int linebufsize = 0;
const char *const FONT_ENV_VAR = "GROFF_FONT_PATH";
@@ -125,31 +177,30 @@ static search_path font_path(FONT_ENV_VAR, FONTPATH, 0, 0);
/*
- * Images are generated via postscript, gs and the pnm utilities.
+ * Images are generated via postscript, gs, and the pnm utilities.
*/
+#define IMAGE_DEVICE "-Tps"
-#define IMAGE_DEVICE "-Tps"
-/*
- * prototypes
- */
static int do_file(const char *filename);
+
/*
- * sys_fatal - writes a fatal error message.
- * Taken from src/roff/groff/pipeline.c.
+ * sys_fatal - Write a fatal error message.
+ * Taken from src/roff/groff/pipeline.c.
*/
-void sys_fatal (const char *s)
+void sys_fatal(const char *s)
{
fatal("%1: %2", s, strerror(errno));
}
/*
- * get_line - copies a line (w/o newline) from a file to the global line buffer
+ * get_line - Copy a line (w/o newline) from a file to the
+ * global line buffer.
*/
-int get_line (FILE *f)
+int get_line(FILE *f)
{
if (f == 0)
return 0;
@@ -190,10 +241,10 @@ int get_line (FILE *f)
}
/*
- * get_resolution - returns the postscript resolution from devps/DESC
+ * get_resolution - Return the postscript resolution from devps/DESC.
*/
-static unsigned int get_resolution (void)
+static unsigned int get_resolution(void)
{
char *pathp;
FILE *f;
@@ -214,7 +265,7 @@ static unsigned int get_resolution (void)
}
/*
- * html_system - a wrapper for system()
+ * html_system - A wrapper for system().
*/
void html_system(const char *s, int redirect_stdout)
@@ -244,29 +295,28 @@ void html_system(const char *s, int redirect_stdout)
}
/*
- * make_message - taken from man printf(3), creates a string via malloc
- * and places the result of the va args into string.
- * Finally the new string is returned.
+ * make_message - Create a string via malloc and place the result of the
+ * va args into string. Finally the new string is returned.
+ * Taken from man page of printf(3).
*/
-char *
-make_message (const char *fmt, ...)
+char *make_message(const char *fmt, ...)
{
/* Guess we need no more than 100 bytes. */
int n, size = 100;
char *p;
char *np;
va_list ap;
- if ((p = (char *)malloc (size)) == NULL)
+ if ((p = (char *)malloc(size)) == NULL)
return NULL;
while (1) {
/* Try to print in the allocated space. */
va_start(ap, fmt);
- n = vsnprintf (p, size, fmt, ap);
+ n = vsnprintf(p, size, fmt, ap);
va_end(ap);
/* If that worked, return the string. */
if (n > -1 && n < size) {
- if (size > n+1) {
+ if (size > n + 1) {
np = strsave(p);
free(p);
return np;
@@ -274,15 +324,15 @@ make_message (const char *fmt, ...)
return p;
}
/* Else try again with more space. */
- if (n > -1) /* glibc 2.1 */
- size = n+1; /* precisely what is needed */
- else /* glibc 2.0 */
- size *= 2; /* twice the old size */
- if ((np = (char *)realloc (p, size)) == NULL) {
- free(p); /* realloc failed, free old, p. */
+ if (n > -1) /* glibc 2.1 */
+ size = n + 1; /* precisely what is needed */
+ else /* glibc 2.0 */
+ size *= 2; /* twice the old size */
+ if ((np = (char *)realloc(p, size)) == NULL) {
+ free(p); /* realloc failed, free old, p. */
return NULL;
}
- p = np; /* use realloc'ed, p */
+ p = np; /* use realloc'ed, p */
}
}
@@ -292,15 +342,15 @@ make_message (const char *fmt, ...)
struct char_block {
enum { SIZE = 256 };
- char buffer[SIZE];
- int used;
- char_block *next;
+ char buffer[SIZE];
+ int used;
+ char_block *next;
char_block();
};
/*
- * char_block - constructor, sets the, used, and, next, fields to zero.
+ * char_block - Constructor. Set the, used, and, next, fields to zero.
*/
char_block::char_block()
@@ -314,22 +364,22 @@ 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 is_html);
- int can_see(char_block **t, int *i, const char *string);
- int skip_spaces(char_block **t, int *i);
+ int read_file(FILE *fp);
+ int do_html(int argc, char *argv[]);
+ int do_image(int argc, char *argv[]);
+ void emit_troff_output(int device_format_selector);
+ void write_upto_newline(char_block **t, int *i, int is_html);
+ int can_see(char_block **t, int *i, const char *string);
+ int skip_spaces(char_block **t, int *i);
void skip_until_newline(char_block **t, int *i);
private:
char_block *head;
char_block *tail;
+ int run_output_filter(int device_format_selector, int argc, char *argv[]);
};
/*
- * char_buffer - constructor
+ * char_buffer - Constructor.
*/
char_buffer::char_buffer()
@@ -338,7 +388,7 @@ char_buffer::char_buffer()
}
/*
- * char_buffer - deconstructor, throws aways the whole buffer list.
+ * char_buffer - Destructor. Throw away the whole buffer list.
*/
char_buffer::~char_buffer()
@@ -351,70 +401,69 @@ char_buffer::~char_buffer()
}
/*
- * read_file - read in a complete file, fp, placing the contents inside char_blocks.
+ * read_file - Read in a complete file, fp, placing the contents inside
+ * char_blocks.
*/
-int char_buffer::read_file (FILE *fp)
+int char_buffer::read_file(FILE *fp)
{
int n;
-
- while (! feof(fp)) {
+ while (!feof(fp)) {
if (tail == NULL) {
tail = new char_block;
head = tail;
- } else {
+ }
+ else {
if (tail->used == char_block::SIZE) {
tail->next = new char_block;
- tail = tail->next;
+ tail = tail->next;
}
}
- // at this point we have a tail which is ready for the next SIZE bytes of the file
-
+ // 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) {
+ if (n <= 0)
// error
- return( 0 );
- } else {
- tail->used += n*sizeof(char);
- }
+ return 0;
+ else
+ tail->used += n * sizeof(char);
}
- return( 1 );
+ return 1;
}
/*
- * writeNbytes - writes n bytes to stdout.
+ * writeNbytes - Write n bytes to stdout.
*/
-static void writeNbytes (const char *s, int l)
+static void writeNbytes(const char *s, int l)
{
- int n=0;
+ int n = 0;
int r;
- while (n<l) {
- r = write(stdoutfd, s, l-n);
- if (r<0) {
+ 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.
+ * writeString - Write a string to stdout.
*/
-static void writeString (const char *s)
+static void writeString(const char *s)
{
writeNbytes(s, strlen(s));
}
/*
- * makeFileName - creates the image filename template
+ * makeFileName - Create the image filename template
* and the macroset image template.
*/
-static void makeFileName (void)
+static void makeFileName(void)
{
if ((image_dir != NULL) && (strchr(image_dir, '%') != NULL)) {
error("cannot use a `%%' within the image directory name");
@@ -426,23 +475,26 @@ static void makeFileName (void)
exit(1);
}
- if (image_dir == NULL) {
+ if (image_dir == NULL)
image_dir = "";
- } else if ((strlen(image_dir)>0) && (image_dir[strlen(image_dir)-1] != '/')) {
+ else if (strlen(image_dir) > 0
+ && image_dir[strlen(image_dir) - 1] != '/') {
image_dir = make_message("%s/", image_dir);
if (image_dir == NULL)
sys_fatal("make_message");
}
-
+
if (image_template == NULL)
- macroset_template = make_message("%sgrohtml-%d", image_dir, (int)getpid());
+ macroset_template = make_message("%sgrohtml-%d", image_dir,
+ (int)getpid());
else
macroset_template = make_message("%s%s", image_dir, image_template);
if (macroset_template == NULL)
sys_fatal("make_message");
- image_template = (char *)malloc(strlen("-%d")+strlen(macroset_template)+1);
+ image_template =
+ (char *)malloc(strlen("-%d") + strlen(macroset_template) + 1);
if (image_template == NULL)
sys_fatal("malloc");
strcpy(image_template, macroset_template);
@@ -450,10 +502,10 @@ static void makeFileName (void)
}
/*
- * setupAntiAlias - sets up the antialias string, used when we call gs.
+ * setupAntiAlias - Set up the antialias string, used when we call gs.
*/
-static void setupAntiAlias (void)
+static void setupAntiAlias(void)
{
if (textAlphaBits == 0 && graphicAlphaBits == 0)
antiAlias = make_message(" ");
@@ -467,23 +519,24 @@ static void setupAntiAlias (void)
}
/*
- * checkImageDir - checks to see whether the image directory is available.
+ * checkImageDir - Check whether the image directory is available.
*/
-static void checkImageDir (void)
+static void checkImageDir(void)
{
- if ((image_dir != NULL) && (strcmp(image_dir, "") != 0))
- if (! ((mkdir(image_dir, 0777) == 0) || (errno == EEXIST))) {
+ if (image_dir != NULL && strcmp(image_dir, "") != 0)
+ if (!(mkdir(image_dir, 0777) == 0 || errno == EEXIST)) {
error("cannot create directory `%1'", image_dir);
exit(1);
}
}
/*
- * write_end_image - ends the image. It writes out the image extents if we are using -Tps.
+ * write_end_image - End the image. Write out the image extents if we
+ * are using -Tps.
*/
-static void write_end_image (int is_html)
+static void write_end_image(int is_html)
{
/*
* if we are producing html then these
@@ -501,18 +554,17 @@ static void write_end_image (int is_html)
}
/*
- * write_start_image - writes the troff which will:
+ * write_start_image - Write troff code which will:
*
* (i) disable html output for the following image
* (ii) reset the max/min x/y registers during postscript
* rendering.
*/
-static void write_start_image (IMAGE_ALIGNMENT pos, int is_html)
+static void write_start_image(IMAGE_ALIGNMENT pos, int is_html)
{
writeString("\\O[5");
switch (pos) {
-
case INLINE:
writeString("i");
break;
@@ -527,7 +579,8 @@ static void write_start_image (IMAGE_ALIGNMENT pos, int is_html)
writeString("c");
break;
}
- writeString(image_template); writeString(".png]");
+ writeString(image_template);
+ writeString(".png]");
if (is_html)
writeString("\\O[0]\\O[3]");
else
@@ -536,24 +589,25 @@ static void write_start_image (IMAGE_ALIGNMENT pos, int is_html)
}
/*
- * write_upto_newline - writes the contents of the buffer until a newline is seen.
- * It checks for HTML_IMAGE_INLINE_BEGIN and HTML_IMAGE_INLINE_END
- * and if they are present it processes them.
+ * write_upto_newline - Write the contents of the buffer until a newline
+ * is seen. Check for HTML_IMAGE_INLINE_BEGIN and
+ * HTML_IMAGE_INLINE_END; process them if they are
+ * present.
*/
-void char_buffer::write_upto_newline (char_block **t, int *i, int is_html)
+void char_buffer::write_upto_newline(char_block **t, int *i, int is_html)
{
- int j=*i;
+ int j = *i;
if (*t) {
- while ((j < (*t)->used) && ((*t)->buffer[j] != '\n') &&
- ((*t)->buffer[j] != INLINE_LEADER_CHAR)) {
+ while (j < (*t)->used
+ && (*t)->buffer[j] != '\n'
+ && (*t)->buffer[j] != INLINE_LEADER_CHAR)
j++;
- }
- if ((j < (*t)->used) && ((*t)->buffer[j] == '\n')) {
+ if (j < (*t)->used
+ && (*t)->buffer[j] == '\n')
j++;
- }
- writeNbytes((*t)->buffer+(*i), j-(*i));
+ writeNbytes((*t)->buffer + (*i), j - (*i));
if ((*t)->buffer[j] == INLINE_LEADER_CHAR) {
if (can_see(t, &j, HTML_IMAGE_INLINE_BEGIN))
write_start_image(INLINE, is_html);
@@ -563,208 +617,222 @@ void char_buffer::write_upto_newline (char_block **t, int *i, int is_html)
if (j < (*t)->used) {
*i = j;
j++;
- writeNbytes((*t)->buffer+(*i), j-(*i));
+ writeNbytes((*t)->buffer + (*i), j - (*i));
}
}
}
if (j == (*t)->used) {
*i = 0;
- if ((*t)->buffer[j-1] == '\n') {
- *t = (*t)->next;
- } else {
- *t = (*t)->next;
+ *t = (*t)->next;
+ if (*t && (*t)->buffer[j - 1] != '\n')
write_upto_newline(t, i, is_html);
- }
- } else {
+ }
+ else
// newline was seen
*i = j;
- }
}
}
/*
- * can_see - returns TRUE if we can see string in t->buffer[i] onwards
+ * can_see - Return TRUE if we can see string in t->buffer[i] onwards.
*/
-int char_buffer::can_see (char_block **t, int *i, const char *string)
+int char_buffer::can_see(char_block **t, int *i, const char *string)
{
- int j = 0;
- int l = strlen(string);
- int k = *i;
+ 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])) {
+ 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 );
+ return TRUE;
}
+ else if (k < s->used && s->buffer[k] != string[j])
+ return( FALSE );
s = s->next;
k = 0;
}
- return( FALSE );
+ return FALSE;
}
/*
- * skip_spaces - returns TRUE if we have not run out of data.
- * It also consumes spaces.
+ * skip_spaces - Return TRUE if we have not run out of data.
+ * Consume spaces also.
*/
int char_buffer::skip_spaces(char_block **t, int *i)
{
char_block *s = *t;
- int k = *i;
+ int k = *i;
while (s) {
- while ((k<s->used) && (isspace(s->buffer[k]))) {
+ while (k < s->used && isspace(s->buffer[k]))
k++;
- }
if (k == s->used) {
k = 0;
s = s->next;
- } else {
+ }
+ else {
*i = k;
- return( TRUE );
+ return TRUE;
}
}
- return( FALSE );
+ return FALSE;
}
/*
- * skip_until_newline - skips all characters until a newline is seen.
+ * skip_until_newline - Skip all characters until a newline is seen.
* The newline is not consumed.
*/
-void char_buffer::skip_until_newline (char_block **t, int *i)
+void char_buffer::skip_until_newline(char_block **t, int *i)
{
- int j=*i;
+ int j = *i;
if (*t) {
- while ((j < (*t)->used) && ((*t)->buffer[j] != '\n')) {
+ while (j < (*t)->used && (*t)->buffer[j] != '\n')
j++;
- }
if (j == (*t)->used) {
*i = 0;
*t = (*t)->next;
skip_until_newline(t, i);
- } else {
+ }
+ else
// newline was seen
*i = j;
- }
}
}
+#define DEVICE_FORMAT(filter) (filter == HTML_OUTPUT_FILTER)
+#define HTML_OUTPUT_FILTER 0
+#define IMAGE_OUTPUT_FILTER 1
+
/*
- * write_file_troff - writes the buffer to stdout (troff).
+ * emit_troff_output - Write formatted buffer content to the troff
+ * post-processor data pipeline.
*/
-void char_buffer::write_file_troff (void)
+void char_buffer::emit_troff_output(int device_format_selector)
{
- char_block *t=head;
- int i=0;
+ // Handle output for BOTH html and image device formats
+ // if `device_format_selector' is passed as
+ //
+ // HTML_FORMAT(HTML_OUTPUT_FILTER)
+ // Buffer data is written to the output stream
+ // with template image names translated to actual image names.
+ //
+ // HTML_FORMAT(IMAGE_OUTPUT_FILTER)
+ // Buffer data is written to the output stream
+ // with no translation, for image file creation in the post-processor.
+
+ int index = 0;
+ char_block *element = head;
+
+ while (element != NULL)
+ write_upto_newline(&element, &index, device_format_selector);
- if (t != NULL) {
- do {
- write_upto_newline(&t, &i, FALSE);
- } while (t != NULL);
- }
+#if 0
if (close(stdoutfd) < 0)
- sys_fatal("close");
+ 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");
- }
+ if (dup(2) != stdoutfd)
+ sys_fatal ("dup failed to use fd=1");
}
+#endif /* 0 */
}
/*
- * the image class remembers the position of all images in the postscript file
- * and assigns names for each image.
+ * 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 maxx;
- int pageNo;
-
- imageItem (int x1, int y1, int x2, int y2, int page, int res, int max_width, char *name);
- ~imageItem ();
+ imageItem *next;
+ int X1;
+ int Y1;
+ int X2;
+ int Y2;
+ char *imageName;
+ int resolution;
+ int maxx;
+ int pageNo;
+
+ imageItem(int x1, int y1, int x2, int y2,
+ int page, int res, int max_width, char *name);
+ ~imageItem();
};
/*
- * imageItem - constructor
+ * imageItem - Constructor.
*/
-imageItem::imageItem (int x1, int y1, int x2, int y2, int page, int res, int max_width, char *name)
+imageItem::imageItem(int x1, int y1, int x2, int y2,
+ int page, int res, int max_width, char *name)
{
- X1 = x1;
- Y1 = y1;
- X2 = x2;
- Y2 = y2;
- pageNo = page;
+ X1 = x1;
+ Y1 = y1;
+ X2 = x2;
+ Y2 = y2;
+ pageNo = page;
resolution = res;
- maxx = max_width;
- imageName = name;
- next = NULL;
+ maxx = max_width;
+ imageName = name;
+ next = NULL;
}
/*
- * imageItem - deconstructor
+ * imageItem - Destructor.
*/
-imageItem::~imageItem ()
+imageItem::~imageItem()
{
if (imageName)
free(imageName);
}
/*
- * imageList - class containing a list of imageItems.
+ * imageList - A class containing a list of imageItems.
*/
class imageList {
private:
imageItem *head;
imageItem *tail;
- int count;
+ int count;
public:
imageList();
~imageList();
- void add(int x1, int y1, int x2, int y2, int page, int res, int maxx, char *name);
- void createImages (void);
- int createPage (int pageno);
- void createImage (imageItem *i);
- int getMaxX (int pageno);
+ void add(int x1, int y1, int x2, int y2,
+ int page, int res, int maxx, char *name);
+ void createImages(void);
+ int createPage(int pageno);
+ void createImage(imageItem *i);
+ int getMaxX(int pageno);
};
/*
- * imageList - constructor.
+ * imageList - Constructor.
*/
-imageList::imageList ()
- : head(0), tail(0), count(0)
+imageList::imageList()
+: head(0), tail(0), count(0)
{
}
/*
- * imageList - deconstructor.
+ * imageList - Destructor.
*/
-imageList::~imageList ()
+imageList::~imageList()
{
while (head != NULL) {
imageItem *i = head;
@@ -774,10 +842,10 @@ imageList::~imageList ()
}
/*
- * createPage - creates one image of, page pageno, from the postscript file.
+ * createPage - Create one image of, page pageno, from the postscript file.
*/
-int imageList::createPage (int pageno)
+int imageList::createPage(int pageno)
{
char *s;
@@ -786,8 +854,9 @@ int imageList::createPage (int pageno)
if (currentPageNo >= 1) {
/*
- * we need to unlink the files which change each time a new page is processed.
- * The final unlink is done by xtmpfile when pre-grohtml exits.
+ * We need to unlink the files which change each time a new page is
+ * processed. The final unlink is done by xtmpfile when pre-grohtml
+ * exits.
*/
unlink(imagePageName);
unlink(psPageName);
@@ -815,7 +884,7 @@ int imageList::createPage (int pageno)
}
#endif
html_system(s, 1);
-
+
s = make_message("echo showpage | "
"gs%s -q -dBATCH -dSAFER "
"-dDEVICEHEIGHTPOINTS=792 "
@@ -844,39 +913,38 @@ int imageList::createPage (int pageno)
}
/*
- * min - returns the minimum of two numbers.
+ * min - Return the minimum of two numbers.
*/
-int min (int x, int y)
+int min(int x, int y)
{
- if (x < y) {
- return( x );
- } else {
- return( y );
- }
+ if (x < y)
+ return x;
+ else
+ return y;
}
/*
- * max - returns the maximum of two numbers.
+ * max - Return the maximum of two numbers.
*/
-int max (int x, int y)
+int max(int x, int y)
{
- if (x > y) {
- return( x );
- } else {
- return( y );
- }
+ if (x > y)
+ return x;
+ else
+ return y;
}
/*
- * getMaxX - returns the largest right hand position for any image on, pageno
+ * getMaxX - Return the largest right-hand position for any image
+ * on, pageno.
*/
-int imageList::getMaxX (int pageno)
+int imageList::getMaxX(int pageno)
{
imageItem *h = head;
- int x = postscriptRes * DEFAULT_LINE_LENGTH;
+ int x = postscriptRes * DEFAULT_LINE_LENGTH;
while (h != NULL) {
if (h->pageNo == pageno)
@@ -887,21 +955,30 @@ int imageList::getMaxX (int pageno)
}
/*
- * createImage - generates a minimal png file from the set of page images.
+ * createImage - Generate a minimal png file from the set of page images.
*/
-void imageList::createImage (imageItem *i)
+void imageList::createImage(imageItem *i)
{
if (i->X1 != -1) {
char *s;
- int x1 = max(min(i->X1, i->X2)*image_res/postscriptRes-1*IMAGE_BOARDER_PIXELS, 0);
- int y1 = max((image_res*vertical_offset/72)+min(i->Y1, i->Y2)*image_res/postscriptRes-IMAGE_BOARDER_PIXELS, 0);
- int x2 = max(i->X1, i->X2)*image_res/postscriptRes+1*IMAGE_BOARDER_PIXELS;
- int y2 = (image_res*vertical_offset/72)+(max(i->Y1, i->Y2)*image_res/postscriptRes)+1+IMAGE_BOARDER_PIXELS;
+ int x1 = max(min(i->X1, i->X2) * image_res / postscriptRes
+ - IMAGE_BOARDER_PIXELS,
+ 0);
+ int y1 = max(image_res * vertical_offset / 72
+ + min(i->Y1, i->Y2) * image_res / postscriptRes
+ - IMAGE_BOARDER_PIXELS,
+ 0);
+ int x2 = max(i->X1, i->X2) * image_res / postscriptRes
+ + IMAGE_BOARDER_PIXELS;
+ int y2 = image_res * vertical_offset / 72
+ + max(i->Y1, i->Y2) * image_res / postscriptRes
+ + 1 + IMAGE_BOARDER_PIXELS;
if (createPage(i->pageNo) == 0) {
- s = make_message("pnmcut%s %d %d %d %d < %s | pnmcrop -quiet | pnmtopng%s %s > %s \n",
+ s = make_message("pnmcut%s %d %d %d %d < %s "
+ "| pnmcrop -quiet | pnmtopng%s %s > %s\n",
EXE_EXT,
- x1, y1, x2-x1+1, y2-y1+1,
+ x1, y1, x2 - x1 + 1, y2 - y1 + 1,
imagePageName,
EXE_EXT,
TRANSPARENT,
@@ -917,12 +994,14 @@ void imageList::createImage (imageItem *i)
#endif
html_system(s, 0);
free(s);
- } else {
+ }
+ else {
fprintf(stderr, "failed to generate image of page %d\n", i->pageNo);
fflush(stderr);
}
#if defined(DEBUGGING)
- } else {
+ }
+ else {
if (debug) {
fprintf(stderr, "ignoring image as x1 coord is -1\n");
fflush(stderr);
@@ -932,27 +1011,30 @@ void imageList::createImage (imageItem *i)
}
/*
- * add - an image description to the imageList.
+ * add - Add an image description to the imageList.
*/
-void imageList::add (int x1, int y1, int x2, int y2, int page, int res, int maxx, char *name)
+void imageList::add(int x1, int y1, int x2, int y2,
+ int page, int res, int maxx, char *name)
{
imageItem *i = new imageItem(x1, y1, x2, y2, page, res, maxx, name);
if (head == NULL) {
head = i;
tail = i;
- } else {
+ }
+ else {
tail->next = i;
tail = i;
}
}
/*
- * createImages - foreach image descriptor on the imageList, create the actual image.
+ * createImages - For each image descriptor on the imageList,
+ * create the actual image.
*/
-void imageList::createImages (void)
+void imageList::createImages(void)
{
imageItem *h = head;
@@ -962,72 +1044,42 @@ void imageList::createImages (void)
}
}
-static imageList listOfImages; // list of images defined by the region file.
-
-/*
- * write_file_html - writes the buffer to stdout (troff).
- * It writes out the file replacing template image names with
- * actual image names.
- */
-
-void char_buffer::write_file_html (void)
-{
- char_block *t=head;
- int i=0;
-
- if (t != NULL) {
- do {
- write_upto_newline(&t, &i, TRUE);
- } while (t != NULL);
- }
- 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");
- }
- }
-}
+static imageList listOfImages; // List of images defined by the region file.
/*
- * generateImages - parses the region file and generates images
- * from the postscript file. The region file
- * contains the x1,y1 x2,y2 extents of each
+ * generateImages - Parse the region file and generate images
+ * from the postscript file. The region file
+ * contains the x1,y1--x2,y2 extents of each
* image.
*/
-static void generateImages (char *regionFileName)
+static void generateImages(char *regionFileName)
{
pushBackBuffer *f=new pushBackBuffer(regionFileName);
while (f->putPB(f->getPB()) != eof) {
if (f->isString("grohtml-info:page")) {
- int page = f->readInt();
- int x1 = f->readInt();
- int y1 = f->readInt();
- int x2 = f->readInt();
- int y2 = f->readInt();
- int maxx = f->readInt();
+ int page = f->readInt();
+ int x1 = f->readInt();
+ int y1 = f->readInt();
+ int x2 = f->readInt();
+ int y2 = f->readInt();
+ int maxx = f->readInt();
char *name = f->readString();
- int res = postscriptRes;
+ int res = postscriptRes;
listOfImages.add(x1, y1, x2, y2, page, res, maxx, name);
- while ((f->putPB(f->getPB()) != '\n') &&
- (f->putPB(f->getPB()) != eof)) {
+ while (f->putPB(f->getPB()) != '\n'
+ && f->putPB(f->getPB()) != eof)
(void)f->getPB();
- }
- if (f->putPB(f->getPB()) == '\n') {
+ if (f->putPB(f->getPB()) == '\n')
(void)f->getPB();
- }
- } else {
- /*
- * write any error messages out to the user
- */
+ }
+ else {
+ /* Write any error messages out to the user. */
fputc(f->getPB(), stderr);
}
}
-
+
listOfImages.createImages();
if (show_progress) {
fprintf(stderr, "done\n");
@@ -1037,84 +1089,97 @@ static void generateImages (char *regionFileName)
}
/*
- * replaceFd - replace a file descriptor, was, with, willbe.
+ * set_redirection - Set up I/O Redirection for handle, was, to refer to
+ * stream on handle, willbe.
*/
-static void replaceFd (int was, int willbe)
+static void set_redirection(int was, int willbe)
{
- int dupres;
-
+ // Nothing to do if `was' and `willbe' already have same handle.
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);
+ // Otherwise attempt the specified redirection.
+ if (dup2 (willbe, was) < 0) {
+ // Redirection failed, so issue diagnostic and bail out.
+ fprintf(stderr, "failed to replace fd=%d with %d\n", was, willbe);
+ if (willbe == STDOUT_FILENO)
+ fprintf(stderr,
+ "likely that stdout should be opened before %d\n", was);
+ sys_fatal("dup2");
}
- if (close(willbe) < 0) {
+
+ // When redirection has been successfully completed assume redundant
+ // handle `willbe' is no longer required, so close it.
+ if (close(willbe) < 0)
+ // Issue diagnostic if `close' fails.
sys_fatal("close");
- }
}
}
/*
- * waitForChild - waits for child, pid, to exit.
+ * save_and_redirect - Get duplicate handle for stream, was, then
+ * redirect, was, to refer to, willbe.
*/
-static void waitForChild (PID_T pid)
+static int save_and_redirect(int was, int willbe)
{
- PID_T waitpd;
- int status;
+ if (was == willbe)
+ // No redirection specified so don't do anything but silently bailing out.
+ return (was);
+
+ // Proceeding with redirection so first save and verify our duplicate
+ // handle for `was'.
+ int saved = dup(was);
+ if (saved < 0) {
+ fprintf(stderr, "unable to get duplicate handle for %d\n", was);
+ sys_fatal("dup");
+ }
- waitpd = WAIT(&status, pid, _WAIT_CHILD);
- if (waitpd != pid)
- sys_fatal("wait");
+ // Duplicate handle safely established so complete redirection.
+ set_redirection(was, willbe);
+
+ // Finally return the saved duplicate descriptor for the
+ // original `was' stream.
+ return saved;
}
/*
- * alterDeviceTo - if toImage is set then the arg list is altered to include
+ * alterDeviceTo - If, toImage, is set
+ * the argument list is altered to include
* IMAGE_DEVICE and we invoke groff rather than troff.
- * else
- * set -Thtml and groff
+ * Else
+ * set -Thtml and groff.
*/
-static void alterDeviceTo (int argc, char *argv[], int toImage)
+static void alterDeviceTo(int argc, char *argv[], int toImage)
{
- int i=0;
+ int i = 0;
if (toImage) {
while (i < argc) {
- if (strcmp(argv[i], "-Thtml") == 0) {
+ if (strcmp(argv[i], "-Thtml") == 0)
argv[i] = IMAGE_DEVICE;
- }
i++;
}
- argv[troff_arg] = "groff"; /* rather than troff */
- } else {
+ argv[troff_arg] = "groff"; /* rather than troff */
+ }
+ else {
while (i < argc) {
- if (strcmp(argv[i], IMAGE_DEVICE) == 0) {
+ if (strcmp(argv[i], IMAGE_DEVICE) == 0)
argv[i] = "-Thtml";
- }
i++;
}
- argv[troff_arg] = "groff"; /* use groff -Z */
+ argv[troff_arg] = "groff"; /* use groff -Z */
}
}
/*
- * addZ - appends -Z onto the command list for groff.
+ * addZ - Append -Z onto the command list for groff.
*/
-char **addZ (int argc, char *argv[])
+char **addZ(int argc, char *argv[])
{
- char **new_argv = (char **)malloc((argc+2)*sizeof(char *));
- int i=0;
+ char **new_argv = (char **)malloc((argc + 2) * sizeof(char *));
+ int i = 0;
if (new_argv == NULL)
sys_fatal("malloc");
@@ -1124,8 +1189,8 @@ char **addZ (int argc, char *argv[])
i++;
}
new_argv[i] = "-Z";
- while (i<argc) {
- new_argv[i+1] = argv[i];
+ while (i < argc) {
+ new_argv[i + 1] = argv[i];
i++;
}
argc++;
@@ -1134,18 +1199,19 @@ char **addZ (int argc, char *argv[])
}
/*
- * addRegDef - appends a defined register or string onto the command list for troff.
+ * addRegDef - Append a defined register or string onto the command
+ * list for troff.
*/
-char **addRegDef (int argc, char *argv[], const char *numReg)
+char **addRegDef(int argc, char *argv[], const char *numReg)
{
- char **new_argv = (char **)malloc((argc+2)*sizeof(char *));
- int i=0;
+ char **new_argv = (char **)malloc((argc + 2) * sizeof(char *));
+ int i = 0;
if (new_argv == NULL)
sys_fatal("malloc");
- while (i<argc) {
+ while (i < argc) {
new_argv[i] = argv[i];
i++;
}
@@ -1156,94 +1222,192 @@ char **addRegDef (int argc, char *argv[], const char *numReg)
}
/*
- * dump_args - display the argument list.
+ * dump_args - Display the argument list.
*/
-void dump_args (int argc, char *argv[])
+void dump_args(int argc, char *argv[])
{
fprintf(stderr, " %d arguments:", argc);
- for (int i=0; i<argc; i++)
+ for (int i = 0; i < argc; i++)
fprintf(stderr, " %s", argv[i]);
fprintf(stderr, "\n");
}
+int char_buffer::run_output_filter(int filter, int argc, char **argv)
+{
+ int pipedes[2];
+ PID_T child_pid;
+ int status;
+
+ if (pipe(pipedes) < 0)
+ sys_fatal("pipe");
+
+#if MAY_FORK_CHILD_PROCESS
+ // This is the UNIX process model. To invoke our post-processor,
+ // we must `fork' the current process.
+
+ if ((child_pid = fork()) < 0)
+ sys_fatal("fork");
+
+ else if (child_pid == 0) {
+ // This is the child process fork. We redirect its `stdin' stream
+ // to read data emerging from our pipe. There is no point in saving,
+ // since we won't be able to restore later!
+
+ set_redirection(STDIN_FILENO, pipedes[0]);
+
+ // The parent process will be writing this data so we should release
+ // the child's writeable handle on the pipe.
+
+ if (close(pipedes[1]) < 0)
+ sys_fatal("close");
+
+ // The IMAGE_OUTPUT_FILTER needs special output redirection...
+
+ if (filter == IMAGE_OUTPUT_FILTER) {
+ // with BOTH `stdout' AND `stderr' diverted to files.
+
+ set_redirection(STDOUT_FILENO,
+ creat(psFileName, S_IWUSR | S_IRUSR));
+ set_redirection(STDERR_FILENO,
+ creat(regionFileName, S_IWUSR | S_IRUSR));
+ }
+
+ // Now we are ready to launch the output filter.
+
+ execvp(argv[0], argv);
+
+ // If we get to here then the `exec...' request for the output filter
+ // failed. Diagnose it and bail out.
+
+ error("couldn't exec %1: %2", argv[0], strerror(errno), ((char *)0));
+ fflush(stderr); // just in case error() didn't
+ exit(1);
+ }
+
+ else {
+ // This is the parent process fork. We will be writing data to the
+ // filter pipeline but we can close our handle on the output end of
+ // the pipe so we don't block the output data stream.
+
+ if (close(pipedes[0]) < 0)
+ sys_fatal("close");
+
+ // Now we redirect the `stdout' stream to the inlet end of the pipe.
+ // Push out the appropiately formatted data to the filter.
+
+ pipedes[1] = save_and_redirect(STDOUT_FILENO, pipedes[1]);
+ emit_troff_output(DEVICE_FORMAT(filter));
+
+ // After emitting all the data we close our connection to the inlet
+ // end of the pipe so the child process will detect end of data.
+
+ set_redirection(STDOUT_FILENO, pipedes[1]);
+
+ // Finally we must wait for the child process to complete.
+
+ if (WAIT(&status, &child_pid, _WAIT_CHILD) != child_pid)
+ sys_fatal("wait");
+ }
+
+#elif MAY_SPAWN_ASYNCHRONOUS_CHILD
+
+ // This should be ok for most Win32 systems and is preferred to `fork'
+ // for starting child processes under Cygwin.
+
+ // Before we start the post-processor we bind its inherited `stdin'
+ // stream to the readable end of our pipe, saving our own `stdin' stream
+ // in `pipedes[0]'.
+
+ pipedes[0] = save_and_redirect(STDIN_FILENO, pipedes[0]);
+
+ int saved_stdout = dup(STDOUT_FILENO);
+ int saved_stderr = STDERR_FILENO;
+
+ // The IMAGE_OUTPUT_FILTER needs special output redirection...
+
+ if (filter == IMAGE_OUTPUT_FILTER) {
+ // with BOTH `stdout' AND `stderr' diverted to files while saving a
+ // duplicate handle for `stderr'.
+
+ set_redirection(STDOUT_FILENO, creat(psFileName, S_IWUSR | S_IRUSR));
+ saved_stderr =
+ save_and_redirect(STDERR_FILENO,
+ creat(regionFileName, S_IWUSR | S_IRUSR));
+ }
+
+ // We then use an asynchronous spawn request to start the post-processor.
+
+ if ((child_pid = spawnvp(_P_NOWAIT, argv[0], argv)) < 0) {
+ // Should the spawn request fail we issue a diagnostic and bail out.
+
+ error("cannot spawn %1: %2", argv[0], strerror(errno), ((char *)0));
+ exit(1);
+ }
+
+ // Once the post-processor has been started we revert our `stdin'
+ // to its original saved source which also closes the readable handle
+ // for the pipe.
+
+ set_redirection(STDIN_FILENO, pipedes[0]);
+
+ set_redirection(STDERR_FILENO, saved_stderr);
+ set_redirection(STDOUT_FILENO, pipedes[1]);
+ emit_troff_output(DEVICE_FORMAT(filter));
+
+ set_redirection(STDOUT_FILENO, saved_stdout);
+
+ if (WAIT(&status, child_pid, _WAIT_CHILD) != child_pid)
+ sys_fatal("wait");
+
+#endif /* MAY_FORK_CHILD_PROCESS or MAY_SPAWN_ASYNCHRONOUS_CHILD */
+
+ return 0;
+}
+
/*
- * do_html - sets the troff number htmlflip and
- * writes out the buffer to troff -Thtml
+ * do_html - Set the troff number htmlflip and
+ * write out the buffer to troff -Thtml.
*/
int char_buffer::do_html(int argc, char *argv[])
{
- int pdes[2];
- PID_T pid;
string s;
alterDeviceTo(argc, argv, 0);
- argv += troff_arg; // skip all arguments up to groff
+ argv += troff_arg; // skip all arguments up to groff
argc -= troff_arg;
argv = addZ(argc, argv);
argc++;
s = "-dwww-image-template=";
- s += macroset_template; // do not combine these statements otherwise they will not work
- s += '\0'; // the trailing '\0' is ignored
+ s += macroset_template; // do not combine these statements,
+ // otherwise they will not work
+ s += '\0'; // the trailing `\0' is ignored
argv = addRegDef(argc, argv, s.contents());
argc++;
- if (pipe(pdes) < 0)
- sys_fatal("pipe");
-
- 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");
- replaceFd(1, copyofstdoutfd); // and restore stdout
-
- 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
-
#if defined(DEBUGGING)
- /*
- * slight security risk so only enabled if compiled with defined(DEBUGGING)
- */
- if (debug) {
- replaceFd(1, creat(htmlFileName, S_IWUSR|S_IRUSR));
- write_file_html();
- }
+ // slight security risk so only enabled if compiled with defined(DEBUGGING)
+ if (debug) {
+ set_redirection(STDOUT_FILENO, creat(htmlFileName, S_IWUSR | S_IRUSR));
+ emit_troff_output(DEVICE_FORMAT(HTML_OUTPUT_FILTER));
+ }
#endif
- 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;
+ return run_output_filter(HTML_OUTPUT_FILTER, argc, argv);
}
/*
- * do_image - writes out the buffer to troff -Tps
+ * do_image - Write out the buffer to troff -Tps.
*/
int char_buffer::do_image(int argc, char *argv[])
{
- PID_T pid;
- int pdes[2];
string s;
alterDeviceTo(argc, argv, 1);
- argv += troff_arg; // skip all arguments up to troff/groff
+ argv += troff_arg; // skip all arguments up to troff/groff
argc -= troff_arg;
argv = addRegDef(argc, argv, "-rps4html=1");
argc++;
@@ -1258,69 +1422,50 @@ int char_buffer::do_image(int argc, char *argv[])
argv = addRegDef(argc, argv, "-P-pletter");
argc++;
- if (pipe(pdes) < 0)
- sys_fatal("pipe");
-
- pid = fork();
- if (pid == 0) {
- // child
-
- int psFd = creat(psFileName, S_IWUSR|S_IRUSR);
- int regionFd = creat(regionFileName, S_IWUSR|S_IRUSR);
-
- 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
-
#if defined(DEBUGGING)
- /*
- * slight security risk so only enabled if compiled with defined(DEBUGGING)
- */
- if (debug) {
- replaceFd(1, creat(troffFileName, S_IWUSR|S_IRUSR));
- write_file_troff();
- }
-#endif
- replaceFd(1, pdes[1]);
- write_file_troff();
- waitForChild(pid);
+ // slight security risk so only enabled if compiled with defined(DEBUGGING)
+ if (debug) {
+ set_redirection(STDOUT_FILENO, creat(troffFileName, S_IWUSR | S_IRUSR));
+ emit_troff_output(DEVICE_FORMAT(IMAGE_OUTPUT_FILTER));
}
- return 0;
+#endif
+
+ return run_output_filter(IMAGE_OUTPUT_FILTER, argc, argv);
}
static char_buffer inputFile;
-
/*
- * usage - emit usage arguments.
+ * usage - Emit usage arguments.
*/
-void usage(FILE *stream)
+static void usage(FILE *stream)
{
- fprintf(stream, "usage: %s troffname [-Iimage_name] [-Dimage_directory] [-P-o vertical_image_offset] [-P-i image_resolution] [troff flags] [files]\n", program_name);
- fprintf(stream, " vertical_image_offset (default %d/72 of an inch)\n", vertical_offset);
- fprintf(stream, " image_resolution (default %d) pixels per inch\n", image_res);
- fprintf(stream, " image_name is the name of the stem for all images (default is grohtml-<pid>)\n");
- fprintf(stream, " place all png files into image_directory\n");
+ fprintf(stream,
+ "usage: %s troffname [-Iimage_name] [-Dimage_directory]\n"
+ " [-P-o vertical_image_offset] [-P-i image_resolution]\n"
+ " [troff flags] [files]\n",
+ program_name);
+ fprintf(stream,
+ " vertical_image_offset (default %d/72 of an inch)\n",
+ vertical_offset);
+ fprintf(stream,
+ " image_resolution (default %d) pixels per inch\n",
+ image_res);
+ fprintf(stream,
+ " image_name is the name of the stem for all images\n"
+ " (default is grohtml-<pid>)\n");
+ fprintf(stream,
+ " place all png files into image_directory\n");
}
/*
- * scanArguments - scans for all arguments including -P-i, -P-o, -P-D and -P-I. It returns
- * the argument index of the first non option.
+ * scanArguments - Scan for all arguments including -P-i, -P-o, -P-D,
+ * and -P-I. Return the argument index of the first
+ * non-option.
*/
-int scanArguments (int argc, char **argv)
+static int scanArguments(int argc, char **argv)
{
const char *command_prefix = getenv("GROFF_COMMAND_PREFIX");
if (!command_prefix)
@@ -1334,21 +1479,24 @@ int scanArguments (int argc, char **argv)
{ "version", no_argument, 0, 'v' },
{ NULL, 0, 0, 0 }
};
- while ((c = getopt_long(argc, argv, "+a:g:o:i:I:j:D:F:vbdhlrnp", long_options, NULL))
+ while ((c = getopt_long(argc, argv,
+ "+a:g:o:i:I:j:D:F:vbdhlrnp", long_options, NULL))
!= EOF)
switch(c) {
case 'v':
printf("GNU pre-grohtml (groff) version %s\n", Version_string);
exit(0);
case 'a':
- textAlphaBits = min(max(MIN_ALPHA_BITS, atoi(optarg)), MAX_ALPHA_BITS);
+ textAlphaBits = min(max(MIN_ALPHA_BITS, atoi(optarg)),
+ MAX_ALPHA_BITS);
if (textAlphaBits == 3) {
error("cannot use 3 bits of antialiasing information");
exit(1);
}
break;
case 'g':
- graphicAlphaBits = min(max(MIN_ALPHA_BITS, atoi(optarg)), MAX_ALPHA_BITS);
+ graphicAlphaBits = min(max(MIN_ALPHA_BITS, atoi(optarg)),
+ MAX_ALPHA_BITS);
if (graphicAlphaBits == 3) {
error("cannot use 3 bits of antialiasing information");
exit(1);
@@ -1412,19 +1560,19 @@ int scanArguments (int argc, char **argv)
}
/*
- * makeTempFiles - name the temporary files
+ * makeTempFiles - Name the temporary files.
*/
-static int makeTempFiles (void)
+static int makeTempFiles(void)
{
#if defined(DEBUGGING)
- psFileName = "/tmp/prehtml-ps";
- regionFileName = "/tmp/prehtml-region";
- imagePageName = "/tmp/prehtml-page";
- psPageName = "/tmp/prehtml-psn";
- troffFileName = "/tmp/prehtml-troff";
- htmlFileName = "/tmp/prehtml-html";
-#else
+ psFileName = __tmpfile"prehtml-ps";
+ regionFileName = __tmpfile"prehtml-region";
+ imagePageName = __tmpfile"prehtml-page";
+ psPageName = __tmpfile"prehtml-psn";
+ troffFileName = __tmpfile"prehtml-troff";
+ htmlFileName = __tmpfile"prehtml-html";
+#else /* not DEBUGGING */
FILE *f;
/* psPageName contains a single page of postscript */
@@ -1467,7 +1615,7 @@ static int makeTempFiles (void)
}
fclose(f);
-#endif
+#endif /* not DEBUGGING */
return 0;
}
@@ -1475,9 +1623,21 @@ int main(int argc, char **argv)
{
program_name = argv[0];
int i;
- int found=0;
- int ok=1;
-
+ int found = 0;
+ int ok = 1;
+
+#ifdef CAPTURE_MODE
+ FILE *dump;
+ fprintf(stderr, "%s: invoked with %d arguments ...\n", argv[0], argc);
+ for (i = 0; i < argc; i++)
+ fprintf(stderr, "%2d: %s\n", i, argv[i]);
+ if ((dump = fopen(__tmpfile"pre-html-data", "wb")) != NULL) {
+ while((i = fgetc(stdin)) >= 0)
+ fputc(i, dump);
+ fclose(dump);
+ }
+ exit(1);
+#endif /* CAPTURE_MODE */
postscriptRes = get_resolution();
i = scanArguments(argc, argv);
setupAntiAlias();
@@ -1487,19 +1647,15 @@ int main(int argc, char **argv)
if (argv[i][0] != '-') {
/* found source file */
ok = do_file(argv[i]);
- if (! ok) {
- return( 0 );
- }
+ if (!ok)
+ return 0;
found = 1;
}
i++;
}
- copyofstdoutfd=dup(stdoutfd);
-
- if (! found) {
+ if (!found)
do_file("-");
- }
if (makeTempFiles())
return 1;
ok = inputFile.do_image(argc, argv);
@@ -1515,9 +1671,9 @@ static int do_file(const char *filename)
FILE *fp;
current_filename = filename;
- if (strcmp(filename, "-") == 0) {
+ if (strcmp(filename, "-") == 0)
fp = stdin;
- } else {
+ else {
fp = fopen(filename, "r");
if (fp == 0) {
error("can't open `%1': %2", filename, strerror(errno));
@@ -1526,6 +1682,7 @@ static int do_file(const char *filename)
}
if (inputFile.read_file(fp)) {
+ // XXX
}
if (fp != stdin)