diff options
author | Ruslan Ermilov <ru@FreeBSD.org> | 2005-10-20 10:45:19 +0000 |
---|---|---|
committer | Ruslan Ermilov <ru@FreeBSD.org> | 2005-10-20 10:45:19 +0000 |
commit | 22e7cbb8744990e63e02dc3985780d932c67b1a4 (patch) | |
tree | 8a188846a3f5bd2f2b8cb869cba64e3c470a2b26 /contrib/groff/src/preproc/html | |
parent | bc33253bf821b172ef51ec51fd451c0149d9eff5 (diff) | |
download | src-22e7cbb8744990e63e02dc3985780d932c67b1a4.tar.gz src-22e7cbb8744990e63e02dc3985780d932c67b1a4.zip |
Virgin import of FSF groff v1.19.2
Notes
Notes:
svn path=/vendor/groff/dist/; revision=151497
Diffstat (limited to 'contrib/groff/src/preproc/html')
-rw-r--r-- | contrib/groff/src/preproc/html/Makefile.sub | 1 | ||||
-rw-r--r-- | contrib/groff/src/preproc/html/pre-html.cpp | 1253 | ||||
-rw-r--r-- | contrib/groff/src/preproc/html/pre-html.h | 2 | ||||
-rw-r--r-- | contrib/groff/src/preproc/html/pushback.cpp | 30 | ||||
-rw-r--r-- | contrib/groff/src/preproc/html/pushback.h | 24 |
5 files changed, 778 insertions, 532 deletions
diff --git a/contrib/groff/src/preproc/html/Makefile.sub b/contrib/groff/src/preproc/html/Makefile.sub index 6a9a75707e7e..0763537a94e6 100644 --- a/contrib/groff/src/preproc/html/Makefile.sub +++ b/contrib/groff/src/preproc/html/Makefile.sub @@ -2,5 +2,6 @@ PROG=pre-grohtml$(EXEEXT) # MAN1=pre-grohtml.n MAN1= XLIBS=$(LIBGROFF) +MLIB=$(LIBM) OBJS=pre-html.$(OBJEXT) pushback.$(OBJEXT) CCSRCS=$(srcdir)/pre-html.cpp $(srcdir)/pushback.cpp diff --git a/contrib/groff/src/preproc/html/pre-html.cpp b/contrib/groff/src/preproc/html/pre-html.cpp index 8869136a6ce7..6f8a46aee0fc 100644 --- a/contrib/groff/src/preproc/html/pre-html.cpp +++ b/contrib/groff/src/preproc/html/pre-html.cpp @@ -1,5 +1,5 @@ // -*- C++ -*- -/* Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. Written by Gaius Mulley (gaius@glam.ac.uk). This file is part of groff. @@ -16,7 +16,7 @@ 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. */ +Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ #define PREHTMLC @@ -34,39 +34,124 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "defs.h" #include "searchpath.h" #include "paper.h" +#include "device.h" #include "font.h" #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 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(_WIN32) + +// 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 _WIN32 */ + +# if defined(DEBUGGING) && !defined(DEBUG_FILE_DIR) +/* When we are building a DEBUGGING version we need to tell pre-grohtml + where to put intermediate files (the DEBUGGING version will preserve + these on exit). + + On a UNIX host, we might simply use `/tmp', but MS-DOS and Win32 will + probably not have this on all disk drives, so default to using + `c:/temp' instead. (Note that user may choose to override this by + supplying a definition such as + + -DDEBUG_FILE_DIR=d:/path/to/debug/files + + in the CPPFLAGS to `make'.) */ + +# define DEBUG_FILE_DIR c:/temp +# endif + +#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 + +# if defined(DEBUGGING) && !defined(DEBUG_FILE_DIR) +/* For a DEBUGGING version, on the UNIX host, we can also usually rely + on being able to use `/tmp' for temporary file storage. (Note that, + as in the __MSDOS__ or _WIN32 case above, the user may override this + by defining + + -DDEBUG_FILE_DIR=/path/to/debug/files + + in the CPPFLAGS.) */ + +# define DEBUG_FILE_DIR /tmp +# endif + +#endif /* not __MSDOS__ or _WIN32 */ + +#ifdef DEBUGGING +// For a DEBUGGING version, we need some additional macros, +// to direct the captured debug mode output to appropriately named files +// in the specified DEBUG_FILE_DIR. + +# define DEBUG_TEXT(text) #text +# define DEBUG_NAME(text) DEBUG_TEXT(text) +# define DEBUG_FILE(name) DEBUG_NAME(DEBUG_FILE_DIR) "/" name +#endif + 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 '\\' -#define TRANSPARENT "-background white -transparent white" -#define MIN_ALPHA_BITS 0 -#define MAX_ALPHA_BITS 4 +// 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 PAGE_TEMPLATE_SHORT "pg" #define PAGE_TEMPLATE_LONG "-page-" @@ -76,78 +161,87 @@ 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; +static const char *image_gen = NULL; // the `gs' program const char *const FONT_ENV_VAR = "GROFF_FONT_PATH"; 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; @@ -188,10 +282,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; @@ -212,7 +306,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) @@ -242,29 +336,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 (n > -1 && n < size - 1) { /* glibc 2.1 and pre-ANSI C 99 */ + if (size > n + 1) { np = strsave(p); free(p); return np; @@ -272,15 +365,13 @@ 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. */ + 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 */ } } @@ -290,15 +381,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() @@ -312,22 +403,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() @@ -336,7 +427,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() @@ -349,70 +440,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"); @@ -424,23 +514,26 @@ static void makeFileName (void) exit(1); } - if (image_dir == NULL) { - image_dir = ""; - } else if ((strlen(image_dir)>0) && (image_dir[strlen(image_dir)-1] != '/')) { + if (image_dir == NULL) + image_dir = (char *)""; + 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); @@ -448,10 +541,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(" "); @@ -465,23 +558,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 @@ -499,18 +593,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; @@ -525,7 +618,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 @@ -534,24 +628,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); @@ -561,208 +656,225 @@ 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 *str) { - int j = 0; - int l = strlen(string); - int k = *i; + int j = 0; + int l = strlen(str); + 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] == str[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] != str[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 +#define OUTPUT_STREAM(name) creat((name), S_IWUSR | S_IRUSR) +#define PS_OUTPUT_STREAM OUTPUT_STREAM(psFileName) +#define REGION_OUTPUT_STREAM OUTPUT_STREAM(regionFileName) + /* - * 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 idx = 0; + char_block *element = head; + + while (element != NULL) + write_upto_newline(&element, &idx, 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; @@ -772,10 +884,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; @@ -784,8 +896,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); @@ -813,13 +926,14 @@ int imageList::createPage (int pageno) } #endif html_system(s, 1); - + s = make_message("echo showpage | " - "gs%s -q -dBATCH -dSAFER " + "%s%s -q -dBATCH -dSAFER " "-dDEVICEHEIGHTPOINTS=792 " "-dDEVICEWIDTHPOINTS=%d -dFIXEDMEDIA=true " "-sDEVICE=%s -r%d %s " "-sOutputFile=%s %s -\n", + image_gen, EXE_EXT, (getMaxX(pageno) * image_res) / postscriptRes, image_device, @@ -842,39 +956,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) @@ -885,21 +998,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, @@ -915,12 +1037,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); @@ -930,27 +1054,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; @@ -960,72 +1087,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 *region_file_name) { - pushBackBuffer *f=new pushBackBuffer(regionFileName); + pushBackBuffer *f=new pushBackBuffer(region_file_name); 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"); @@ -1035,84 +1132,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"); + // 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"); } - 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) { + + // 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) { - argv[i] = IMAGE_DEVICE; - } + if (strcmp(argv[i], "-Thtml") == 0) + argv[i] = (char *)IMAGE_DEVICE; i++; } - argv[troff_arg] = "groff"; /* rather than troff */ - } else { + argv[troff_arg] = (char *)"groff"; /* rather than troff */ + } + else { while (i < argc) { - if (strcmp(argv[i], IMAGE_DEVICE) == 0) { - argv[i] = "-Thtml"; - } + if (strcmp(argv[i], IMAGE_DEVICE) == 0) + argv[i] = (char *)"-Thtml"; i++; } - argv[troff_arg] = "groff"; /* use groff -Z */ + argv[troff_arg] = (char *)"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"); @@ -1121,9 +1231,9 @@ char **addZ (int argc, char *argv[]) new_argv[i] = argv[i]; i++; } - new_argv[i] = "-Z"; - while (i<argc) { - new_argv[i+1] = argv[i]; + new_argv[i] = (char *)"-Z"; + while (i < argc) { + new_argv[i + 1] = argv[i]; i++; } argc++; @@ -1132,18 +1242,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++; } @@ -1154,94 +1265,213 @@ 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, since we have no use for it. + + 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, PS_OUTPUT_STREAM); + set_redirection(STDERR_FILENO, REGION_OUTPUT_STREAM); + } + + // 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, and the child will be reading it. We have no further + // use for our read handle on the pipe, and should close it. + + if (close(pipedes[0]) < 0) + sys_fatal("close"); + + // Now we redirect the `stdout' stream to the inlet end of the pipe, + // and 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 + + // We do not have `fork', (or we prefer not to use it), + // but asynchronous processes are allowed, passing data through pipes. + // 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]); + + // for the Win32 model, + // we need special provision for saving BOTH `stdout' and `stderr'. + + 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, PS_OUTPUT_STREAM); + saved_stderr = save_and_redirect(STDERR_FILENO, REGION_OUTPUT_STREAM); + } + + // 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]); + + // if we redirected `stderr', for use by the image post-processor, + // then we also need to reinstate its original assignment. + + if (filter == IMAGE_OUTPUT_FILTER) + set_redirection(STDERR_FILENO, saved_stderr); + + // Now we redirect the `stdout' stream to the inlet end of the pipe, + // and push out the appropiately formatted data to the filter. + + set_redirection(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, saved_stdout); + + // And finally, we must wait for the child process to complete. + + if (WAIT(&status, child_pid, _WAIT_CHILD) != child_pid) + sys_fatal("wait"); + +#else /* can't do asynchronous pipes! */ + + // TODO: code to support an MS-DOS style process model + // should go here + +#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(); - } +# define HTML_DEBUG_STREAM OUTPUT_STREAM(htmlFileName) + // slight security risk so only enabled if compiled with defined(DEBUGGING) + if (debug) { + int saved_stdout = save_and_redirect(STDOUT_FILENO, HTML_DEBUG_STREAM); + emit_troff_output(DEVICE_FORMAT(HTML_OUTPUT_FILTER)); + set_redirection(STDOUT_FILENO, saved_stdout); + } #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++; @@ -1256,69 +1486,52 @@ 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); +# define IMAGE_DEBUG_STREAM OUTPUT_STREAM(troffFileName) + // slight security risk so only enabled if compiled with defined(DEBUGGING) + if (debug) { + int saved_stdout = save_and_redirect(STDOUT_FILENO, IMAGE_DEBUG_STREAM); + emit_troff_output(DEVICE_FORMAT(IMAGE_OUTPUT_FILTER)); + set_redirection(STDOUT_FILENO, saved_stdout); } - 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]\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) @@ -1332,40 +1545,57 @@ 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:D:F:vbdhlrnp", long_options, NULL)) + while ((c = getopt_long(argc, argv, "+a:bdD:F:g:hi:I:j:lno:prs:S:v", + 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 'b': + // handled by post-grohtml (set background color to white) + break; + case 'd': +#if defined(DEBUGGING) + debug = TRUE; +#endif + break; + case 'D': + image_dir = optarg; + break; + case 'F': + font_path.command_line_dir(optarg); + 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); } break; - case 'b': - // handled by post-grohtml (set background color to white) + case 'h': + // handled by post-grohtml break; - case 'D': - image_dir = optarg; + case 'i': + image_res = atoi(optarg); break; case 'I': image_template = optarg; break; - case 'i': - image_res = atoi(optarg); + case 'j': + // handled by post-grohtml (set job name for multiple file output) break; - case 'F': - font_path.command_line_dir(optarg); + case 'l': + // handled by post-grohtml (no automatic section links) + break; + case 'n': + // handled by post-grohtml (generate simple heading anchors) break; case 'o': vertical_offset = atoi(optarg); @@ -1373,14 +1603,18 @@ int scanArguments (int argc, char **argv) case 'p': show_progress = TRUE; break; - case 'd': -#if defined(DEBUGGING) - debug = TRUE; -#endif + case 'r': + // handled by post-grohtml (no header and footer lines) break; - case 'h': - // handled by post-grohtml + case 's': + // handled by post-grohtml (use font size n as the html base font size) + break; + case 'S': + // handled by post-grohtml (set file split level) break; + case 'v': + printf("GNU pre-grohtml (groff) version %s\n", Version_string); + exit(0); case CHAR_MAX + 1: // --help usage(stdout); exit(0); @@ -1407,19 +1641,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 = DEBUG_FILE("prehtml-ps"); + regionFileName = DEBUG_FILE("prehtml-region"); + imagePageName = DEBUG_FILE("prehtml-page"); + psPageName = DEBUG_FILE("prehtml-psn"); + troffFileName = DEBUG_FILE("prehtml-troff"); + htmlFileName = DEBUG_FILE("prehtml-html"); +#else /* not DEBUGGING */ FILE *f; /* psPageName contains a single page of postscript */ @@ -1462,7 +1696,7 @@ static int makeTempFiles (void) } fclose(f); -#endif +#endif /* not DEBUGGING */ return 0; } @@ -1470,9 +1704,27 @@ 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(DEBUG_FILE("pre-html-data"), "wb")) != NULL) { + while((i = fgetc(stdin)) >= 0) + fputc(i, dump); + fclose(dump); + } + exit(1); +#endif /* CAPTURE_MODE */ + device = "html"; + if (!font::load_desc()) + fatal("cannot find devhtml/DESC exiting"); + image_gen = font::image_generator; + if (image_gen == NULL || (strcmp(image_gen, "") == 0)) + fatal("devhtml/DESC must set the image_generator field, exiting"); postscriptRes = get_resolution(); i = scanArguments(argc, argv); setupAntiAlias(); @@ -1482,19 +1734,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); @@ -1510,9 +1758,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)); @@ -1521,6 +1769,7 @@ static int do_file(const char *filename) } if (inputFile.read_file(fp)) { + // XXX } if (fp != stdin) diff --git a/contrib/groff/src/preproc/html/pre-html.h b/contrib/groff/src/preproc/html/pre-html.h index f9a590c17b7e..3eedb21c72bb 100644 --- a/contrib/groff/src/preproc/html/pre-html.h +++ b/contrib/groff/src/preproc/html/pre-html.h @@ -16,7 +16,7 @@ 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. */ +Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ /* * defines functions implemented within pre-html.c diff --git a/contrib/groff/src/preproc/html/pushback.cpp b/contrib/groff/src/preproc/html/pushback.cpp index 07a15e36fe87..b71558783508 100644 --- a/contrib/groff/src/preproc/html/pushback.cpp +++ b/contrib/groff/src/preproc/html/pushback.cpp @@ -1,5 +1,5 @@ // -*- C++ -*- -/* Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc. Written by Gaius Mulley (gaius@glam.ac.uk). This file is part of groff. @@ -16,7 +16,7 @@ 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. */ +Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ #include "lib.h" @@ -83,14 +83,12 @@ pushBackBuffer::pushBackBuffer (char *filename) pushBackBuffer::~pushBackBuffer () { - int old; - if (charStack != 0) { free(charStack); } close(0); /* restore stdin in file descriptor 0 */ - old = dup(stdIn); + dup(stdIn); close(stdIn); } @@ -162,10 +160,8 @@ static int isWhite (char ch) void pushBackBuffer::skipToNewline (void) { - char ch; - while ((putPB(getPB()) != '\n') && (! eofFound)) { - ch = getPB(); + getPB(); } } @@ -274,15 +270,15 @@ int pushBackBuffer::readInt (void) * convertToFloat - converts integers, a and b into a.b */ -static float convertToFloat (int a, int b) +static double convertToFloat (int a, int b) { int c=10; - float f; + double f; while (b>c) { c *= 10; } - f = ((float)a) + (((float)b)/((float)c)); + f = ((double)a) + (((double)b)/((double)c)); return( f ); } @@ -290,7 +286,7 @@ static float convertToFloat (int a, int b) * readNumber - returns a float representing the word just read. */ -float pushBackBuffer::readNumber (void) +double pushBackBuffer::readNumber (void) { int i; char ch; @@ -300,7 +296,7 @@ float pushBackBuffer::readNumber (void) return convertToFloat(i, readInt()); } putPB(ch); - return (float)i; + return (double)i; } /* @@ -312,7 +308,7 @@ float pushBackBuffer::readNumber (void) char *pushBackBuffer::readString (void) { char buffer[MAXPUSHBACKSTACK]; - char *string = 0; + char *str = 0; int i=0; char ch=getPB(); @@ -326,8 +322,8 @@ char *pushBackBuffer::readString (void) } if (i < MAXPUSHBACKSTACK) { buffer[i] = (char)0; - string = (char *)malloc(strlen(buffer)+1); - strcpy(string, buffer); + str = (char *)malloc(strlen(buffer)+1); + strcpy(str, buffer); } - return( string ); + return( str ); } diff --git a/contrib/groff/src/preproc/html/pushback.h b/contrib/groff/src/preproc/html/pushback.h index 608bac53991e..3fddad66f11d 100644 --- a/contrib/groff/src/preproc/html/pushback.h +++ b/contrib/groff/src/preproc/html/pushback.h @@ -1,5 +1,5 @@ // -*- C -*- -/* Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2000, 2001, 2003, 2004 Free Software Foundation, Inc. Written by Gaius Mulley (gaius@glam.ac.uk). This file is part of groff. @@ -16,7 +16,7 @@ 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. */ +Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ #define eof (char)-1 @@ -39,16 +39,16 @@ class pushBackBuffer 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); - char *readString (void); - int isString (const char *string); + pushBackBuffer (char *); + ~ pushBackBuffer (); + char getPB (void); + char putPB (char ch); + void skipUntilToken (void); + void skipToNewline (void); + double readNumber (void); + int readInt (void); + char *readString (void); + int isString (const char *string); }; |