summaryrefslogtreecommitdiffstats
path: root/contrib/groff/src/libs
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/groff/src/libs')
-rw-r--r--contrib/groff/src/libs/libbib/Makefile.sub10
-rw-r--r--contrib/groff/src/libs/libbib/index.cc5
-rw-r--r--contrib/groff/src/libs/libbib/linear.cc6
-rw-r--r--contrib/groff/src/libs/libbib/map.c9
-rw-r--r--contrib/groff/src/libs/libbib/search.cc7
-rw-r--r--contrib/groff/src/libs/libdriver/Makefile.sub4
-rw-r--r--contrib/groff/src/libs/libdriver/input.cc2156
-rw-r--r--contrib/groff/src/libs/libdriver/printer.cc119
-rw-r--r--contrib/groff/src/libs/libgroff/Makefile.sub97
-rw-r--r--contrib/groff/src/libs/libgroff/color.cc363
-rw-r--r--contrib/groff/src/libs/libgroff/errarg.cc20
-rw-r--r--contrib/groff/src/libs/libgroff/font.cc158
-rw-r--r--contrib/groff/src/libs/libgroff/fontfile.cc9
-rw-r--r--contrib/groff/src/libs/libgroff/geometry.cc286
-rw-r--r--contrib/groff/src/libs/libgroff/getopt.c349
-rw-r--r--contrib/groff/src/libs/libgroff/getopt1.c16
-rw-r--r--contrib/groff/src/libs/libgroff/htmlhint.cc59
-rw-r--r--contrib/groff/src/libs/libgroff/invalid.cc60
-rw-r--r--contrib/groff/src/libs/libgroff/itoa.c17
-rw-r--r--contrib/groff/src/libs/libgroff/matherr.c6
-rw-r--r--contrib/groff/src/libs/libgroff/maxfilename.cc2
-rw-r--r--contrib/groff/src/libs/libgroff/mksdir.cc34
-rw-r--r--contrib/groff/src/libs/libgroff/mkstemp.cc34
-rw-r--r--contrib/groff/src/libs/libgroff/nametoindex.cc9
-rw-r--r--contrib/groff/src/libs/libgroff/new.cc5
-rw-r--r--contrib/groff/src/libs/libgroff/paper.cc84
-rw-r--r--contrib/groff/src/libs/libgroff/putenv.c6
-rw-r--r--contrib/groff/src/libs/libgroff/searchpath.cc8
-rw-r--r--contrib/groff/src/libs/libgroff/strerror.c6
-rw-r--r--contrib/groff/src/libs/libgroff/string.cc38
-rw-r--r--contrib/groff/src/libs/libgroff/strtol.c7
-rw-r--r--contrib/groff/src/libs/libgroff/tmpfile.cc157
-rw-r--r--contrib/groff/src/libs/libgroff/tmpname.cc116
33 files changed, 3484 insertions, 778 deletions
diff --git a/contrib/groff/src/libs/libbib/Makefile.sub b/contrib/groff/src/libs/libbib/Makefile.sub
index 482f01a..6e59d64 100644
--- a/contrib/groff/src/libs/libbib/Makefile.sub
+++ b/contrib/groff/src/libs/libbib/Makefile.sub
@@ -1,10 +1,10 @@
LIB=bib
OBJS=\
- common.o \
- index.o \
- linear.o \
- search.o \
- map.o
+ common.$(OBJEXT) \
+ index.$(OBJEXT) \
+ linear.$(OBJEXT) \
+ search.$(OBJEXT) \
+ map.$(OBJEXT)
CCSRCS=\
$(srcdir)/common.cc \
$(srcdir)/index.cc \
diff --git a/contrib/groff/src/libs/libbib/index.cc b/contrib/groff/src/libs/libbib/index.cc
index 4d836a0..3633df1 100644
--- a/contrib/groff/src/libs/libbib/index.cc
+++ b/contrib/groff/src/libs/libbib/index.cc
@@ -18,13 +18,12 @@ You should have received a copy of the GNU General Public License along
with groff; see the file COPYING. If not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-#include <stdio.h>
-#include <string.h>
+#include "lib.h"
+
#include <stdlib.h>
#include <errno.h>
#include "posix.h"
-#include "lib.h"
#include "cset.h"
#include "cmap.h"
#include "errarg.h"
diff --git a/contrib/groff/src/libs/libbib/linear.cc b/contrib/groff/src/libs/libbib/linear.cc
index a8c2a55..1dd902b 100644
--- a/contrib/groff/src/libs/libbib/linear.cc
+++ b/contrib/groff/src/libs/libbib/linear.cc
@@ -1,5 +1,6 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+ Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -18,14 +19,13 @@ You should have received a copy of the GNU General Public License along
with groff; see the file COPYING. If not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+#include "lib.h"
-#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include "posix.h"
-#include "lib.h"
#include "errarg.h"
#include "error.h"
#include "cset.h"
diff --git a/contrib/groff/src/libs/libbib/map.c b/contrib/groff/src/libs/libbib/map.c
index ee5d008..4d878a2 100644
--- a/contrib/groff/src/libs/libbib/map.c
+++ b/contrib/groff/src/libs/libbib/map.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+ Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -17,6 +18,12 @@ You should have received a copy of the GNU General Public License along
with groff; see the file COPYING. If not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+#include <stdlib.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#ifdef HAVE_MMAP
#include <sys/types.h>
diff --git a/contrib/groff/src/libs/libbib/search.cc b/contrib/groff/src/libs/libbib/search.cc
index 1e027c6..2223fb6 100644
--- a/contrib/groff/src/libs/libbib/search.cc
+++ b/contrib/groff/src/libs/libbib/search.cc
@@ -1,5 +1,6 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+ Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -18,13 +19,13 @@ You should have received a copy of the GNU General Public License along
with groff; see the file COPYING. If not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+#include "lib.h"
+
#include <stdlib.h>
-#include <string.h>
#include <assert.h>
#include <errno.h>
#include "posix.h"
-#include "lib.h"
#include "errarg.h"
#include "error.h"
#include "nonposix.h"
diff --git a/contrib/groff/src/libs/libdriver/Makefile.sub b/contrib/groff/src/libs/libdriver/Makefile.sub
index d50f060..547b8c0 100644
--- a/contrib/groff/src/libs/libdriver/Makefile.sub
+++ b/contrib/groff/src/libs/libdriver/Makefile.sub
@@ -1,7 +1,7 @@
LIB=driver
OBJS=\
- input.o \
- printer.o
+ input.$(OBJEXT) \
+ printer.$(OBJEXT)
CCSRCS=\
$(srcdir)/input.cc \
$(srcdir)/printer.cc
diff --git a/contrib/groff/src/libs/libdriver/input.cc b/contrib/groff/src/libs/libdriver/input.cc
index e19841c..a02c139 100644
--- a/contrib/groff/src/libs/libdriver/input.cc
+++ b/contrib/groff/src/libs/libdriver/input.cc
@@ -1,504 +1,1814 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2001 Free Software Foundation, Inc.
- Written by James Clark (jjc@jclark.com)
-This file is part of groff.
+// <groff_src_dir>/src/libs/libdriver/input.cc
-groff is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
-version.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002
+ Free Software Foundation, Inc.
-groff is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
+ Written by James Clark (jjc@jclark.com)
+ Major rewrite 2001 by Bernd Warken (bwarken@mayn.de)
-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. */
+ Last update: 12 Apr 2002
+
+ This file is part of groff, the GNU roff text processing system.
+
+ groff is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ groff is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with groff; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+*/
+
+/* Description
+
+ This file implements the parser for the intermediate groff output,
+ see groff_out(5), and does the printout for the given device.
+
+ All parsed information is processed within the function do_file() by
+ using the global object `pr' of class `printer'. So a device
+ postprocessor just needs to fill in the methods for the class
+ `printer' without having to worry about the syntax of the
+ intermediate output format. Consequently, the programming of groff
+ postprocessors is similar to the development of device-drivers.
+
+ The prototyping for this file is done in driver.h (and error.h).
+
+ Postprocessor programs must deallocate the global variables `pr' and
+ `device' using `delete', and `current_filename' using
+ `free((char *))'.
+*/
+
+/* Changes of the 2001 rewrite of this file.
+
+ The interface to the outside and the handling of the global
+ variables was not changed, but internally many necessary changes
+ were performed.
+
+ The main aim for this rewrite is to provide a first step towards
+ making groff fully compatible with classical troff without pain.
+
+ Bugs fixed
+ - Unknown subcommands of `D' and `x' are now ignored like in the
+ classical case, but a warning is issued. This was also
+ implemented for the other commands.
+ - A warning is emitted if `x stop' is missing.
+ - `DC' and `DE' commands didn't position to the right end after
+ drawing (now they do), see discussion below.
+ - So far, `x stop' was ignored. Now it terminates the processing
+ of the current intermediate output file like the classical troff.
+ - The command `c' didn't check correctly on white-space.
+ - The environment stack wasn't suitable for the color extensions
+ (replaced by a class).
+ - The old groff parser could only handle a prologue with the first
+ 3 lines having a fixed structure, while classical troff specified
+ the sequence of the first 3 commands without further
+ restrictions. Now the parser is smart about additional
+ white space, comments, and empty lines in the prologue.
+ - The old parser allowed space characters only as syntactical
+ separators, while classical troff had tab characters as well.
+ Now any sequence of tabs and/or spaces is a syntactical
+ separator between commands and/or arguments.
+ - Range checks for numbers implemented.
+
+ New and improved features
+ - The color commands `m' and `DF' are added.
+ - The old color command `Df' is now converted and delegated to `DFg'.
+ - The command `F' is implemented as `use intended file name'. It
+ checks whether its argument agrees with the file name used so far,
+ otherwise a warning is issued. Then the new name is remembered
+ and used for the following error messages.
+ - For the positioning after drawing commands, an alternative, easier
+ scheme is provided, but not yet activated; it can be chosen by
+ undefining the preprocessor macro STUPID_DRAWING_POSITIONING.
+ It extends the rule of the classical troff output language in a
+ logical way instead of the rather strange actual positioning.
+ For details, see the discussion below.
+ - For the `D' commands that only set the environment, the calling of
+ pr->send_draw() was removed because this doesn't make sense for
+ the `DF' commands; the (changed) environment is sent with the
+ next command anyway.
+ - Error handling was clearly separated into warnings and fatal.
+ - The error behavior on additional arguments for `D' and `x'
+ commands with a fixed number of arguments was changed from being
+ ignored (former groff) to issue a warning and ignore (now), see
+ skip_line_x(). No fatal was chosen because both string and
+ integer arguments can occur.
+ - The gtroff program issues a trailing dummy integer argument for
+ some drawing commands with an odd number of arguments to make the
+ number of arguments even, e.g. the DC and Dt commands; this is
+ honored now.
+ - All D commands with a variable number of args expect an even
+ number of trailing integer arguments, so fatal on error was
+ implemented.
+ - Disable environment stack and the commands `{' and `}' by making
+ them conditional on macro USE_ENV_STACK; actually, this is
+ undefined by default. There isn't any known application for these
+ features.
+
+ Cosmetics
+ - Nested `switch' commands are avoided by using more functions.
+ Dangerous 'fall-through's avoided.
+ - Commands and functions are sorted alphabetically (where possible).
+ - Dynamic arrays/buffers are now implemented as container classes.
+ - Some functions had an ugly return structure; this has been
+ streamlined by using classes.
+ - Use standard C math functions for number handling, so getting rid
+ of differences to '0'.
+ - The macro `IntArg' has been created for an easier transition
+ to guaranteed 32 bits integers (`int' is enough for GNU, while
+ ANSI only guarantees `long int' to have a length of 32 bits).
+ - The many usages of type `int' are differentiated by using `Char',
+ `bool', and `IntArg' where appropriate.
+ - To ease the calls of the local utility functions, the parser
+ variables `current_file', `npages', and `current_env'
+ (formerly env) were made global to the file (formerly they were
+ local to the do_file() function)
+ - Various comments were added.
+
+ TODO
+ - Get rid of the stupid drawing positioning.
+ - Can the `Dt' command be completely handled by setting environment
+ within do_file() instead of sending to pr?
+ - Integer arguments must be >= 32 bits, use conditional #define.
+ - Add scaling facility for classical device independence and
+ non-groff devices. Classical troff output had a quasi device
+ independence by scaling the intermediate output to the resolution
+ of the postprocessor device if different from the one specified
+ with `x T', groff have not. So implement full quasi device
+ indepedence, including the mapping of the strange classical
+ devices to the postprocessor device (seems to be reasonably
+ easy).
+ - The external, global pointer variables are not optimally handled.
+ - `pr' isn't used outside besides initialization and deletion.
+ So it could be replaced by a static local variable. For
+ example, a wrapper class `Postprocessor' for class `printer' with
+ internal make_printer() and automatic clean-up would make sense.
+ - The global variables `current_filename' and `current_lineno' are
+ only used for error reporting. So implement a static class
+ `Error' (`::' calls).
+ - The global `device' is the name used during the formatting
+ process; there should be a new variable for the device name used
+ during the postprocessing.
+ - Implement the B-spline drawing `D~' for all graphical devices.
+ - Make `environment' a class with an overflow check for its members
+ and a delete method to get rid of delete_current_env().
+ - Implement the `EnvStack' to use `new' instead of `malloc'.
+ - The class definitions of this document could go into a new file.
+ - The comments in this section should go to a `Changelog' or some
+ `README' file in this directory.
+*/
+
+/*
+ Discussion of the positioning by drawing commands
+
+ There was some confusion about the positioning of the graphical
+ pointer at the printout after having executed a `D' command.
+ The classical troff manual of Osanna & Kernighan specified,
+
+ `The position after a graphical object has been drawn is
+ at its end; for circles and ellipses, the "end" is at the
+ right side.'
+
+ From this, it follows that
+ - all open figures (args, splines, and lines) should position at their
+ final point.
+ - all circles and ellipses should position at their right-most point
+ (as if 2 halves had been drawn).
+ - all closed figures apart from circles and ellipses shouldn't change
+ the position because they return to their origin.
+ - all setting commands should not change position because they do not
+ draw any graphical object.
+
+ In the case of the open figures, this means that the horizontal
+ displacement is the sum of all odd arguments and the vertical offset
+ the sum of all even arguments, called the alternate arguments sum
+ displacement in the following.
+
+ Unfortunately, groff did not implement this simple rule. The former
+ documentation in groff_out(5) differed from the source code, and
+ neither of them is compatible with the classical rule.
+
+ The former groff_out(5) specified to use the alternative arguments
+ sum displacement for calculating the drawing positioning of
+ non-classical commands, including the `Dt' command (setting-only)
+ and closed polygons. Applying this to the new groff color commands
+ will lead to disaster. For their arguments can take large values (>
+ 65000). On low resolution devices, the displacement of such large
+ values will corrupt the display or kill the printer. So the
+ nonsense specification has come to a natural end anyway.
+
+ The groff source code, however, had no positioning for the
+ setting-only commands (esp. `Dt'), the right-end positioning for
+ outlined circles and ellipses, and the alternative argument sum
+ displacement for all other commands (including filled circles and
+ ellipses).
+
+ The reason why no one seems to have suffered from this mayhem so
+ far is that the graphical objects are usually generated by
+ preprocessors like pic that do not depend on the automatic
+ positioning. When using the low level `\D' escape sequences or `D'
+ output commands, the strange positionings can be circumvented by
+ absolute positionings or by tricks like `\Z'.
+
+ So doing an exorcism on the strange, incompatible displacements might
+ not harm any existing documents, but will make the usage of the
+ graphical escape sequences and commands natural.
+
+ That's why the rewrite of this file returned to the reasonable,
+ classical specification with its clear end-of-drawing rule that is
+ suitable for all cases. But a macro STUPID_DRAWING_POSITIONING is
+ provided for testing the funny former behavior.
+
+ The new rule implies the following behavior.
+ - Setting commands (`Dt', `Df', `DF') and polygons (`Dp' and `DP')
+ do not change position now.
+ - Filled circles and ellipses (`DC' and `DE') position at their
+ most right point (outlined ones `Dc' and `De' did this anyway).
+ - As before, all open graphical objects position to their final
+ drawing point (alternate sum of the command arguments).
+
+*/
+
+#ifndef STUPID_DRAWING_POSITIONING
+// uncomment next line if all non-classical D commands shall position
+// to the strange alternate sum of args displacement
+#define STUPID_DRAWING_POSITIONING
+#endif
+
+// Decide whether the commands `{' and `}' for different environments
+// should be used.
+#undef USE_ENV_STACK
#include "driver.h"
#include "device.h"
-#include "cset.h"
-const char *current_filename=0;
-int current_lineno;
-const char *device = 0;
-FILE *current_file;
+#include <stdlib.h>
+#include <errno.h>
+#include <ctype.h>
+#include <math.h>
+
+
+/**********************************************************************
+ local types
+ **********************************************************************/
+
+// integer type used in the fields of struct environment (see printer.h)
+typedef int EnvInt;
-int get_integer(); // don't read the newline
-int possibly_get_integer(int *);
-char *get_string(int is_long = 0);
-void skip_line();
+// integer arguments of groff_out commands, must be >= 32 bits
+typedef int IntArg;
-struct environment_list {
- environment env;
- environment_list *next;
+// color components of groff_out color commands, must be >= 32 bits
+typedef unsigned int ColorArg;
+
+// Array for IntArg values.
+class IntArray {
+ size_t num_allocated;
+ size_t num_stored;
+ IntArg *data;
+public:
+ IntArray(void);
+ IntArray(const size_t);
+ ~IntArray(void);
+ const IntArg operator[](const size_t i) const
+ {
+ if (i >= num_stored || i < 0)
+ fatal("index out of range");
+ return (const IntArg) data[i];
+ }
+ void append(IntArg);
+ const IntArg * const
+ get_data(void) const { return (const IntArg * const) data; }
+ const size_t len(void) const { return num_stored; }
+};
+
+// Characters read from the input queue.
+class Char {
+ int data;
+public:
+ Char(void) : data('\0') {}
+ Char(const int c) : data(c) {}
+ bool operator==(char c) const { return (data == c) ? true : false; }
+ bool operator==(int c) const { return (data == c) ? true : false; }
+ bool operator==(const Char c) const
+ { return (data == c.data) ? true : false; }
+ bool operator!=(char c) const { return !(*this == c); }
+ bool operator!=(int c) const { return !(*this == c); }
+ bool operator!=(const Char c) const { return !(*this == c); }
+ operator int() const { return (int) data; }
+ operator unsigned char() const { return (unsigned char) data; }
+ operator char() const { return (char) data; }
+};
+
+// Buffer for string arguments (Char, not char).
+class StringBuf {
+ size_t num_allocated;
+ size_t num_stored;
+ Char *data; // not terminated by '\0'
+public:
+ StringBuf(void); // allocate without storing
+ ~StringBuf(void);
+ void append(const Char); // append character to `data'
+ char *make_string(void); // return new copy of `data' with '\0'
+ bool is_empty(void) { // true if none stored
+ return (num_stored > 0) ? false : true;
+ }
+ void reset(void); // set `num_stored' to 0
+};
- environment_list(const environment &, environment_list *);
+#ifdef USE_ENV_STACK
+class EnvStack {
+ environment **data;
+ size_t num_allocated;
+ size_t num_stored;
+public:
+ EnvStack(void);
+ ~EnvStack(void);
+ environment *pop(void);
+ void push(environment *e);
};
+#endif // USE_ENV_STACK
+
+
+/**********************************************************************
+ external variables
+ **********************************************************************/
+
+// exported as extern by error.h (called from driver.h)
+// needed for error messages (see ../libgroff/error.cc)
+const char *current_filename = 0; // printable name of the current file
+int current_lineno = 0; // current line number of printout
+
+// exported as extern by device.h;
+const char *device = 0; // cancel former init with literal
+
+// from driver.h; pr is kept between several runs of do_file()
+// extern printer *pr;
+
+// Note:
+//
+// We rely on an implementation of the `new' operator which aborts
+// gracefully if it can't allocate memory (e.g. from libgroff/new.cc).
+
+
+/**********************************************************************
+ static local variables
+ **********************************************************************/
+
+FILE *current_file = 0; // current input stream for parser
+
+// npages: number of pages processed so far (including current page),
+// _not_ the page number in the printout (can be set with `p').
+int npages = 0;
+
+const ColorArg
+COLORARG_MAX = (ColorArg) 65536U; // == 0xFFFF + 1 == 0x10000
+
+const IntArg
+INTARG_MAX = (IntArg) 0x7FFFFFFF; // maximal signed 32 bits number
+
+// parser environment, created and deleted by each run of do_file()
+environment *current_env = 0;
-environment_list::environment_list(const environment &e, environment_list *p)
-: env(e), next(p)
+#ifdef USE_ENV_STACK
+const size_t
+envp_size = sizeof(environment *);
+#endif // USE_ENV_STACK
+
+
+/**********************************************************************
+ function declarations
+ **********************************************************************/
+
+// utility functions
+ColorArg color_from_Df_command(IntArg);
+ // transform old color into new
+void delete_current_env(void); // delete global var current_env
+void fatal_command(char); // abort for invalid command
+inline Char get_char(void); // read next character from input stream
+ColorArg get_color_arg(void); // read in argument for new color cmds
+IntArray *get_D_fixed_args(const size_t);
+ // read in fixed number of integer
+ // arguments
+IntArray *get_D_fixed_args_odd_dummy(const size_t);
+ // read in a fixed number of integer
+ // arguments plus optional dummy
+IntArray *get_D_variable_args(void);
+ // variable, even number of int args
+char *get_extended_arg(void); // argument for `x X' (several lines)
+IntArg get_integer_arg(void); // read in next integer argument
+IntArray *get_possibly_integer_args();
+ // 0 or more integer arguments
+char *get_string_arg(void); // read in next string arg, ended by WS
+inline bool is_space_or_tab(const Char);
+ // test on space/tab char
+Char next_arg_begin(void); // skip white space on current line
+Char next_command(void); // go to next command, evt. diff. line
+inline bool odd(const int); // test if integer is odd
+void position_to_end_of_args(const IntArray * const);
+ // positioning after drawing
+void remember_filename(const char *);
+ // set global current_filename
+void send_draw(const Char, const IntArray * const);
+ // call pr->draw
+void skip_line(void); // unconditionally skip to next line
+bool skip_line_checked(void); // skip line, false if args are left
+void skip_line_fatal(void); // skip line, fatal if args are left
+void skip_line_warn(void); // skip line, warn if args are left
+void skip_line_D(void); // skip line in D commands
+void skip_line_x(void); // skip line in x commands
+void skip_to_end_of_line(void); // skip to the end of the current line
+inline void unget_char(const Char);
+ // restore character onto input
+
+// parser subcommands
+void parse_color_command(color *);
+ // color sub(sub)commands m and DF
+void parse_D_command(void); // graphical subcommands
+bool parse_x_command(void); // device controller subcommands
+
+
+/**********************************************************************
+ class methods
+ **********************************************************************/
+
+#ifdef USE_ENV_STACK
+EnvStack::EnvStack(void)
{
+ num_allocated = 4;
+ // allocate pointer to array of num_allocated pointers to environment
+ data = (environment **) malloc(envp_size * num_allocated);
+ if (data == 0)
+ fatal("could not allocate environment data");
+ num_stored = 0;
}
-inline int get_char()
+EnvStack::~EnvStack(void)
{
- return getc(current_file);
+ for (size_t i = 0; i < num_stored; i++)
+ delete data[i];
+ free(data);
}
-/*
- * remember_filename - is needed as get_string might overwrite the
- * filename eventually.
- */
+// return top element from stack and decrease stack pointer
+//
+// the calling function must take care of properly deleting the result
+environment *
+EnvStack::pop(void)
+{
+ num_stored--;
+ environment *result = data[num_stored];
+ data[num_stored] = 0;
+ return result;
+}
-void remember_filename(const char *filename)
+// copy argument and push this onto the stack
+void
+EnvStack::push(environment *e)
{
- if (current_filename != 0) {
- free((char *)current_filename);
+ environment *e_copy = new environment;
+ if (num_stored >= num_allocated) {
+ environment **old_data = data;
+ num_allocated *= 2;
+ data = (environment **) malloc(envp_size * num_allocated);
+ if (data == 0)
+ fatal("could not allocate data");
+ for (size_t i = 0; i < num_stored; i++)
+ data[i] = old_data[i];
+ free(old_data);
}
- if (strcmp(filename, "-") == 0) {
- filename = "<standard input>";
+ e_copy->col = new color;
+ e_copy->fill = new color;
+ *e_copy->col = *e->col;
+ *e_copy->fill = *e->fill;
+ e_copy->fontno = e->fontno;
+ e_copy->height = e->height;
+ e_copy->hpos = e->hpos;
+ e_copy->size = e->size;
+ e_copy->slant = e->slant;
+ e_copy->vpos = e->vpos;
+ data[num_stored] = e_copy;
+ num_stored++;
+}
+#endif // USE_ENV_STACK
+
+IntArray::IntArray(void)
+{
+ num_allocated = 4;
+ data = new IntArg[num_allocated];
+ num_stored = 0;
+}
+
+IntArray::IntArray(const size_t n)
+{
+ if (n <= 0)
+ fatal("number of integers to be allocated must be > 0");
+ num_allocated = n;
+ data = new IntArg[num_allocated];
+ num_stored = 0;
+}
+
+IntArray::~IntArray(void)
+{
+ a_delete data;
+}
+
+void
+IntArray::append(IntArg x)
+{
+ if (num_stored >= num_allocated) {
+ IntArg *old_data = data;
+ num_allocated *= 2;
+ data = new IntArg[num_allocated];
+ for (size_t i = 0; i < num_stored; i++)
+ data[i] = old_data[i];
+ a_delete old_data;
}
- current_filename = (const char *)malloc(strlen(filename) + 1);
- if (current_filename == 0) {
- fatal("can't malloc space for filename");
+ data[num_stored] = x;
+ num_stored++;
+}
+
+StringBuf::StringBuf(void)
+{
+ num_stored = 0;
+ num_allocated = 128;
+ data = new Char[num_allocated];
+}
+
+StringBuf::~StringBuf(void)
+{
+ a_delete data;
+}
+
+void
+StringBuf::append(const Char c)
+{
+ if (num_stored >= num_allocated) {
+ Char *old_data = data;
+ num_allocated *= 2;
+ data = new Char[num_allocated];
+ for (size_t i = 0; i < num_stored; i++)
+ data[i] = old_data[i];
+ a_delete old_data;
}
- strcpy((char *)current_filename, (char *)filename);
+ data[num_stored] = c;
+ num_stored++;
}
-void do_file(const char *filename)
+char *
+StringBuf::make_string(void)
{
- int npages = 0;
- if (filename[0] == '-' && filename[1] == '\0') {
- remember_filename(filename);
- current_file = stdin;
+ char *result = new char[num_stored + 1];
+ for (size_t i = 0; i < num_stored; i++)
+ result[i] = (char) data[i];
+ result[num_stored] = '\0';
+ return result;
+}
+
+void
+StringBuf::reset(void)
+{
+ num_stored = 0;
+}
+
+/**********************************************************************
+ utility functions
+ **********************************************************************/
+
+//////////////////////////////////////////////////////////////////////
+/* color_from_Df_command:
+ Process the gray shade setting command Df.
+
+ Transform Df style color into DF style color.
+ Df color: 0-1000, 0 is white
+ DF color: 0-65536, 0 is black
+
+ The Df command is obsoleted by command DFg, but kept for
+ compatibility.
+
+ XXX: Add proper handling for values < 0 or > 1000 as documented in
+ groff_out(5).
+*/
+ColorArg
+color_from_Df_command(IntArg Df_gray)
+{
+ if (Df_gray <= 0)
+ return COLORARG_MAX;
+ if (Df_gray >= 1000)
+ return 0;
+ return ColorArg((1000-Df_gray) * COLORARG_MAX / 1000); // scaling
+}
+
+//////////////////////////////////////////////////////////////////////
+/* delete_current_env():
+ Delete global variable current_env and its pointer members.
+
+ This should be a class method of environment.
+*/
+void delete_current_env(void)
+{
+ delete current_env->col;
+ delete current_env->fill;
+ delete current_env;
+}
+
+//////////////////////////////////////////////////////////////////////
+/* fatal_command():
+ Emit error message about invalid command and abort.
+*/
+void
+fatal_command(char command)
+{
+ fatal("`%1' command invalid before first `p' command", command);
+}
+
+//////////////////////////////////////////////////////////////////////
+/* get_char():
+ Retrieve the next character from the input queue.
+
+ Return: The retrieved character (incl. EOF), converted to Char.
+*/
+inline Char
+get_char(void)
+{
+ return (Char) getc(current_file);
+}
+
+//////////////////////////////////////////////////////////////////////
+/* get_color_arg():
+ Retrieve an argument suitable for the color commands m and DF.
+
+ Return: The retrieved color argument.
+*/
+ColorArg
+get_color_arg(void)
+{
+ IntArg x = get_integer_arg();
+ if (x < 0 || x > (IntArg)COLORARG_MAX) {
+ error("color component argument out of range");
+ x = 0;
}
- else {
- errno = 0;
- current_file = fopen(filename, "r");
- if (current_file == 0) {
- error("can't open `%1'", filename);
- return;
+ return (ColorArg) x;
+}
+
+//////////////////////////////////////////////////////////////////////
+/* get_D_fixed_args():
+ Get a fixed number of integer arguments for D commands.
+
+ Fatal if wrong number of arguments.
+ Too many arguments on the line raise a warning.
+ A line skip is done.
+
+ number: In-parameter, the number of arguments to be retrieved.
+ ignore: In-parameter, ignore next argument -- GNU troff always emits
+ pairs of parameters for `D' extensions added by groff.
+ Default is `false'.
+
+ Return: New IntArray containing the arguments.
+*/
+IntArray *
+get_D_fixed_args(const size_t number)
+{
+ if (number <= 0)
+ fatal("requested number of arguments must be > 0");
+ IntArray *args = new IntArray(number);
+ for (size_t i = 0; i < number; i++)
+ args->append(get_integer_arg());
+ skip_line_D();
+ return args;
+}
+
+//////////////////////////////////////////////////////////////////////
+/* get_D_fixed_args_odd_dummy():
+ Get a fixed number of integer arguments for D commands and optionally
+ ignore a dummy integer argument if the requested number is odd.
+
+ The gtroff program adds a dummy argument to some commands to get
+ an even number of arguments.
+ Error if the number of arguments differs from the scheme above.
+ A line skip is done.
+
+ number: In-parameter, the number of arguments to be retrieved.
+
+ Return: New IntArray containing the arguments.
+*/
+IntArray *
+get_D_fixed_args_odd_dummy(const size_t number)
+{
+ if (number <= 0)
+ fatal("requested number of arguments must be > 0");
+ IntArray *args = new IntArray(number);
+ for (size_t i = 0; i < number; i++)
+ args->append(get_integer_arg());
+ if (odd(number)) {
+ IntArray *a = get_possibly_integer_args();
+ if (a->len() > 1)
+ error("too many arguments");
+ delete a;
+ }
+ skip_line_D();
+ return args;
+}
+
+//////////////////////////////////////////////////////////////////////
+/* get_D_variable_args():
+ Get a variable even number of integer arguments for D commands.
+
+ Get as many integer arguments as possible from the rest of the
+ current line.
+ - The arguments are separated by an arbitrary sequence of space or
+ tab characters.
+ - A comment, a newline, or EOF indicates the end of processing.
+ - Error on non-digit characters different from these.
+ - A final line skip is performed (except for EOF).
+
+ Return: New IntArray of the retrieved arguments.
+*/
+IntArray *
+get_D_variable_args()
+{
+ IntArray *args = get_possibly_integer_args();
+ size_t n = args->len();
+ if (n <= 0)
+ error("no arguments found");
+ if (odd(n))
+ error("even number of arguments expected");
+ skip_line_D();
+ return args;
+}
+
+//////////////////////////////////////////////////////////////////////
+/* get_extended_arg():
+ Retrieve extended arg for `x X' command.
+
+ - Skip leading spaces and tabs, error on EOL or newline.
+ - Return everything before the next NL or EOF ('#' is not a comment);
+ as long as the following line starts with '+' this is returned
+ as well, with the '+' replaced by a newline.
+ - Final line skip is always performed.
+
+ Return: Allocated (new) string of retrieved text argument.
+*/
+char *
+get_extended_arg(void)
+{
+ StringBuf buf = StringBuf();
+ Char c = next_arg_begin();
+ while ((int) c != EOF) {
+ if ((int) c == '\n') {
+ current_lineno++;
+ c = get_char();
+ if ((int) c == '+')
+ buf.append((Char) '\n');
+ else {
+ unget_char(c); // first character of next line
+ break;
+ }
}
- remember_filename(filename);
+ else
+ buf.append(c);
+ c = get_char();
}
- environment env;
- env.vpos = -1;
- env.hpos = -1;
- env.fontno = -1;
- env.height = 0;
- env.slant = 0;
- environment_list *env_list = 0;
- current_lineno = 1;
- int command;
- char *s;
- command = get_char();
- if (command == EOF)
- return;
- if (command != 'x')
- fatal("the first command must be `x T'");
- s = get_string();
- if (s[0] != 'T')
- fatal("the first command must be `x T'");
- char *dev = get_string();
- if (pr == 0) {
- device = strsave(dev);
- if (!font::load_desc())
- fatal("sorry, I can't continue");
+ return buf.make_string();
+}
+
+//////////////////////////////////////////////////////////////////////
+/* get_integer_arg(): Retrieve integer argument.
+
+ Skip leading spaces and tabs, collect an optional '-' and all
+ following decimal digits (at least one) up to the next non-digit,
+ which is restored onto the input queue.
+
+ Fatal error on all other situations.
+
+ Return: Retrieved integer.
+*/
+IntArg
+get_integer_arg(void)
+{
+ StringBuf buf = StringBuf();
+ Char c = next_arg_begin();
+ if ((int) c == '-') {
+ buf.append(c);
+ c = get_char();
}
- else {
- if (device == 0 || strcmp(device, dev) != 0)
- fatal("all files must use the same device");
+ if (!isdigit((int) c))
+ error("integer argument expected");
+ while (isdigit((int) c)) {
+ buf.append(c);
+ c = get_char();
}
- skip_line();
- env.size = 10*font::sizescale;
- command = get_char();
- if (command != 'x')
- fatal("the second command must be `x res'");
- s = get_string();
- if (s[0] != 'r')
- fatal("the second command must be `x res'");
- int n = get_integer();
- if (n != font::res)
- fatal("resolution does not match");
- n = get_integer();
- if (n != font::hor)
- fatal("horizontal resolution does not match");
- n = get_integer();
- if (n != font::vert)
- fatal("vertical resolution does not match");
- skip_line();
- command = get_char();
- if (command != 'x')
- fatal("the third command must be `x init'");
- s = get_string();
- if (s[0] != 'i')
- fatal("the third command must be `x init'");
- skip_line();
- if (pr == 0)
- pr = make_printer();
- while ((command = get_char()) != EOF) {
- switch (command) {
- case 's':
- env.size = get_integer();
- if (env.height == env.size)
- env.height = 0;
- break;
- case 'f':
- env.fontno = get_integer();
- break;
- case 'F':
- remember_filename(get_string());
- break;
- case 'C':
- {
- if (npages == 0)
- fatal("`C' command illegal before first `p' command");
- char *s = get_string();
- pr->set_special_char(s, &env);
+ // c is not a digit
+ unget_char(c);
+ char *s = buf.make_string();
+ errno = 0;
+ long int number = strtol(s, 0, 10);
+ if (errno != 0
+ || number > INTARG_MAX || number < -INTARG_MAX) {
+ error("integer argument too large");
+ number = 0;
+ }
+ delete s;
+ return (IntArg) number;
+}
+
+//////////////////////////////////////////////////////////////////////
+/* get_possibly_integer_args():
+ Parse the rest of the input line as a list of integer arguments.
+
+ Get as many integer arguments as possible from the rest of the
+ current line, even none.
+ - The arguments are separated by an arbitrary sequence of space or
+ tab characters.
+ - A comment, a newline, or EOF indicates the end of processing.
+ - Error on non-digit characters different from these.
+ - No line skip is performed.
+
+ Return: New IntArray of the retrieved arguments.
+*/
+IntArray *
+get_possibly_integer_args()
+{
+ bool done = false;
+ StringBuf buf = StringBuf();
+ Char c = get_char();
+ IntArray *args = new IntArray();
+ while (!done) {
+ buf.reset();
+ while (is_space_or_tab(c))
+ c = get_char();
+ if (c == '-') {
+ Char c1 = get_char();
+ if (isdigit((int) c1)) {
+ buf.append(c);
+ c = c1;
}
- break;
- case 'N':
- {
- if (npages == 0)
- fatal("`N' command illegal before first `p' command");
- pr->set_numbered_char(get_integer(), &env);
+ else
+ unget_char(c1);
+ }
+ while (isdigit((int) c)) {
+ buf.append(c);
+ c = get_char();
+ }
+ if (!buf.is_empty()) {
+ char *s = buf.make_string();
+ errno = 0;
+ long int x = strtol(s, 0, 10);
+ if (errno
+ || x > INTARG_MAX || x < -INTARG_MAX) {
+ error("invalid integer argument, set to 0");
+ x = 0;
}
+ args->append((IntArg) x);
+ delete s;
+ }
+ // Here, c is not a digit.
+ // Terminate on comment, end of line, or end of file, while
+ // space or tab indicate continuation; otherwise error.
+ switch((int) c) {
+ case '#':
+ skip_to_end_of_line();
+ done = true;
break;
- case 'H':
- env.hpos = get_integer();
+ case '\n':
+ done = true;
+ unget_char(c);
break;
- case 'h':
- env.hpos += get_integer();
+ case EOF:
+ done = true;
break;
- case 'V':
- env.vpos = get_integer();
+ case ' ':
+ case '\t':
break;
- case 'v':
- env.vpos += get_integer();
+ default:
+ error("integer argument expected");
break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- {
- int c = get_char();
- if (!csdigit(c))
- fatal("digit expected");
- env.hpos += (command - '0')*10 + (c - '0');
- }
- // fall through
- case 'c':
- {
- if (npages == 0)
- fatal("`c' command illegal before first `p' command");
- int c = get_char();
- if (c == EOF)
- fatal("missing argument to `c' command");
- pr->set_ascii_char(c, &env);
- }
+ }
+ }
+ return args;
+}
+
+//////////////////////////////////////////////////////////////////////
+/* get_string_arg():
+ Retrieve string arg.
+
+ - Skip leading spaces and tabs; error on EOL or newline.
+ - Return all following characters before the next space, tab,
+ newline, or EOF character (in-word '#' is not a comment character).
+ - The terminating space, tab, newline, or EOF character is restored
+ onto the input queue, so no line skip.
+
+ Return: Retrieved string as char *, allocated by 'new'.
+*/
+char *
+get_string_arg(void)
+{
+ StringBuf buf = StringBuf();
+ Char c = next_arg_begin();
+ while (!is_space_or_tab(c)
+ && c != Char('\n') && c != Char(EOF)) {
+ buf.append(c);
+ c = get_char();
+ }
+ unget_char(c); // restore white space
+ return buf.make_string();
+}
+
+//////////////////////////////////////////////////////////////////////
+/* is_space_or_tab():
+ Test a character if it is a space or tab.
+
+ c: In-parameter, character to be tested.
+
+ Return: True, if c is a space or tab character, false otherwise.
+*/
+inline bool
+is_space_or_tab(const Char c)
+{
+ return (c == Char(' ') || c == Char('\t')) ? true : false;
+}
+
+//////////////////////////////////////////////////////////////////////
+/* next_arg_begin():
+ Return first character of next argument.
+
+ Skip space and tab characters; error on newline or EOF.
+
+ Return: The first character different from these (including '#').
+*/
+Char
+next_arg_begin(void)
+{
+ Char c;
+ while (1) {
+ c = get_char();
+ switch ((int) c) {
+ case ' ':
+ case '\t':
break;
- case 'n':
- if (npages == 0)
- fatal("`n' command illegal before first `p' command");
- pr->end_of_line();
- (void)get_integer();
- (void)get_integer();
+ case '\n':
+ case EOF:
+ error("missing argument");
break;
- case 'w':
+ default: // first essential character
+ return c;
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////
+/* next_command():
+ Find the first character of the next command.
+
+ Skip spaces, tabs, comments (introduced by #), and newlines.
+
+ Return: The first character different from these (including EOF).
+*/
+Char
+next_command(void)
+{
+ Char c;
+ while (1) {
+ c = get_char();
+ switch ((int) c) {
case ' ':
+ case '\t':
break;
case '\n':
current_lineno++;
break;
- case 'p':
- if (npages)
- pr->end_page(env.vpos);
- npages++;
- pr->begin_page(get_integer());
- env.vpos = 0;
- break;
- case '{':
- env_list = new environment_list(env, env_list);
- break;
- case '}':
- if (!env_list) {
- fatal("can't pop");
- }
- else {
- env = env_list->env;
- environment_list *tem = env_list;
- env_list = env_list->next;
- delete tem;
- }
- break;
- case 'u':
- {
- if (npages == 0)
- fatal("`u' command illegal before first `p' command");
- int kern = get_integer();
- int c = get_char();
- while (c == ' ')
- c = get_char();
- while (c != EOF) {
- if (c == '\n') {
- current_lineno++;
- break;
- }
- int w;
- pr->set_ascii_char(c, &env, &w);
- env.hpos += w + kern;
- c = get_char();
- if (c == ' ')
- break;
- }
- }
- break;
- case 't':
- {
- if (npages == 0)
- fatal("`t' command illegal before first `p' command");
- int c;
- while ((c = get_char()) != EOF && c != ' ') {
- if (c == '\n') {
- current_lineno++;
- break;
- }
- int w;
- pr->set_ascii_char(c, &env, &w);
- env.hpos += w;
- }
- }
- break;
- case '#':
- skip_line();
- break;
- case 'D':
- {
- if (npages == 0)
- fatal("`D' command illegal before first `p' command");
- int c;
- while ((c = get_char()) == ' ')
- ;
- int n;
- int *p = 0;
- int szp = 0;
- int np;
- for (np = 0; possibly_get_integer(&n); np++) {
- if (np >= szp) {
- if (szp == 0) {
- szp = 16;
- p = new int[szp];
- }
- else {
- int *oldp = p;
- p = new int[szp*2];
- memcpy(p, oldp, szp*sizeof(int));
- szp *= 2;
- a_delete oldp;
- }
- }
- p[np] = n;
- }
- pr->draw(c, p, np, &env);
- if (c == 'e') {
- if (np > 0)
- env.hpos += p[0];
- }
- else if (c == 'f' || c == 't')
- ;
- else {
- int i;
- for (i = 0; i < np/2; i++) {
- env.hpos += p[i*2];
- env.vpos += p[i*2 + 1];
- }
- // there might be an odd number of characters
- if (i*2 < np)
- env.hpos += p[i*2];
- }
- a_delete p;
- skip_line();
- }
- break;
- case 'x':
- {
- char *s = get_string();
- int suppress_skip = 0;
- switch (s[0]) {
- case 'i':
- error("duplicate `x init' command");
- break;
- case 'T':
- error("duplicate `x T' command");
- break;
- case 'r':
- error("duplicate `x res' command");
- break;
- case 'p':
- break;
- case 's':
- break;
- case 't':
- break;
- case 'f':
- {
- int n = get_integer();
- char *name = get_string();
- pr->load_font(n, name);
- }
- break;
- case 'H':
- env.height = get_integer();
- if (env.height == env.size)
- env.height = 0;
- break;
- case 'S':
- env.slant = get_integer();
- break;
- case 'X':
- if (npages == 0)
- fatal("`x X' command illegal before first `p' command");
- pr->special(get_string(1), &env);
- suppress_skip = 1;
- break;
- case 'u':
- // .cu
- pr->special(get_string(), &env, 'u');
- break;
- default:
- error("unrecognised x command `%1'", s);
- }
- if (!suppress_skip)
- skip_line();
- }
- break;
- default:
- error("unrecognised command code %1", int(command));
+ case '#': // comment
skip_line();
break;
+ default: // EOF or first essential character
+ return c;
}
}
- if (npages)
- pr->end_page(env.vpos);
}
-int get_integer()
+//////////////////////////////////////////////////////////////////////
+/* odd():
+ Test whether argument is an odd number.
+
+ n: In-parameter, the integer to be tested.
+
+ Return: True if odd, false otherwise.
+*/
+inline bool
+odd(const int n)
+{
+ return (n & 1 == 1) ? true : false;
+}
+
+//////////////////////////////////////////////////////////////////////
+/* position_to_end_of_args():
+ Move graphical pointer to end of drawn figure.
+
+ This is used by the D commands that draw open geometrical figures.
+ The algorithm simply sums up all horizontal displacements (arguments
+ with even number) for the horizontal component. Similarly, the
+ vertical component is the sum of the odd arguments.
+
+ args: In-parameter, the arguments of a former drawing command.
+*/
+void
+position_to_end_of_args(const IntArray * const args)
{
- int c = get_char();
- while (c == ' ')
- c = get_char();
- int neg = 0;
- if (c == '-') {
- neg = 1;
+ size_t i;
+ const size_t n = args->len();
+ for (i = 0; i < n; i += 2)
+ current_env->hpos += (*args)[i];
+ for (i = 1; i < n; i += 2)
+ current_env->vpos += (*args)[i];
+}
+
+//////////////////////////////////////////////////////////////////////
+/* remember_filename():
+ Set global variable current_filename.
+
+ The actual filename is stored in current_filename. This is used by
+ the postprocessors, expecting the name "<standard input>" for stdin.
+
+ filename: In-out-parameter; is changed to the new value also.
+*/
+void
+remember_filename(const char *filename)
+{
+ char *fname;
+ if (strcmp(filename, "-") == 0)
+ fname = "<standard input>";
+ else
+ fname = (char *) filename;
+ size_t len = strlen(fname) + 1;
+ if (current_filename != 0)
+ free((char *)current_filename);
+ current_filename = (const char *) malloc(len);
+ if (current_filename == 0)
+ fatal("can't malloc space for filename");
+ strncpy((char *)current_filename, (char *)fname, len);
+}
+
+//////////////////////////////////////////////////////////////////////
+/* send_draw():
+ Call draw method of printer class.
+
+ subcmd: Letter of actual D subcommand.
+ args: Array of integer arguments of actual D subcommand.
+*/
+void
+send_draw(const Char subcmd, const IntArray * const args)
+{
+ EnvInt n = (EnvInt) args->len();
+ pr->draw((int) subcmd, (IntArg *) args->get_data(), n, current_env);
+}
+
+//////////////////////////////////////////////////////////////////////
+/* skip_line():
+ Go to next line within the input queue.
+
+ Skip the rest of the current line, including the newline character.
+ The global variable current_lineno is adjusted.
+ No errors are raised.
+*/
+void
+skip_line(void)
+{
+ Char c = get_char();
+ while (1) {
+ if (c == '\n') {
+ current_lineno++;
+ break;
+ }
+ if (c == EOF)
+ break;
c = get_char();
}
- if (!csdigit(c))
- fatal("integer expected");
- int total = 0;
- do {
- total = total*10;
- if (neg)
- total -= c - '0';
- else
- total += c - '0';
- c = get_char();
- } while (csdigit(c));
- if (c != EOF)
- ungetc(c, current_file);
- return total;
}
-int possibly_get_integer(int *res)
+//////////////////////////////////////////////////////////////////////
+/* skip_line_checked ():
+ Check that there aren't any arguments left on the rest of the line,
+ then skip line.
+
+ Spaces, tabs, and a comment are allowed before newline or EOF.
+ All other characters raise an error.
+*/
+bool
+skip_line_checked(void)
{
- int c = get_char();
- while (c == ' ')
- c = get_char();
- int neg = 0;
- if (c == '-') {
- neg = 1;
+ bool ok = true;
+ Char c = get_char();
+ while (is_space_or_tab(c))
c = get_char();
+ switch((int) c) {
+ case '#': // comment
+ skip_line();
+ break;
+ case '\n':
+ current_lineno++;
+ break;
+ case EOF:
+ break;
+ default:
+ ok = false;
+ skip_line();
+ break;
}
- if (!csdigit(c)) {
- if (c != EOF)
- ungetc(c, current_file);
- return 0;
+ return ok;
+}
+
+//////////////////////////////////////////////////////////////////////
+/* skip_line_fatal ():
+ Fatal error if arguments left, otherwise skip line.
+
+ Spaces, tabs, and a comment are allowed before newline or EOF.
+ All other characters trigger the error.
+*/
+void
+skip_line_fatal(void)
+{
+ bool ok = skip_line_checked();
+ if (!ok) {
+ current_lineno--;
+ error("too many arguments");
+ current_lineno++;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////
+/* skip_line_warn ():
+ Skip line, but warn if arguments are left on actual line.
+
+ Spaces, tabs, and a comment are allowed before newline or EOF.
+ All other characters raise a warning
+*/
+void
+skip_line_warn(void)
+{
+ bool ok = skip_line_checked();
+ if (!ok) {
+ current_lineno--;
+ warning("too many arguments on current line");
+ current_lineno++;
}
- int total = 0;
- do {
- total = total*10;
- if (neg)
- total -= c - '0';
- else
- total += c - '0';
- c = get_char();
- } while (csdigit(c));
- if (c != EOF)
- ungetc(c, current_file);
- *res = total;
- return 1;
}
+//////////////////////////////////////////////////////////////////////
+/* skip_line_D ():
+ Skip line in `D' commands.
-char *get_string(int is_long)
+ Decide whether in case of an additional argument a fatal error is
+ raised (the documented classical behavior), only a warning is
+ issued, or the line is just skipped (former groff behavior).
+ Actually decided for the warning.
+*/
+void
+skip_line_D(void)
{
- static char *buf;
- static int buf_size;
- int c = get_char();
- while (c == ' ')
+ skip_line_warn();
+ // or: skip_line_fatal();
+ // or: skip_line();
+}
+
+//////////////////////////////////////////////////////////////////////
+/* skip_line_x ():
+ Skip line in `x' commands.
+
+ Decide whether in case of an additional argument a fatal error is
+ raised (the documented classical behavior), only a warning is
+ issued, or the line is just skipped (former groff behavior).
+ Actually decided for the warning.
+*/
+void
+skip_line_x(void)
+{
+ skip_line_warn();
+ // or: skip_line_fatal();
+ // or: skip_line();
+}
+
+//////////////////////////////////////////////////////////////////////
+/* skip_to_end_of_line():
+ Go to the end of the current line.
+
+ Skip the rest of the current line, excluding the newline character.
+ The global variable current_lineno is not changed.
+ No errors are raised.
+*/
+void
+skip_to_end_of_line(void)
+{
+ Char c = get_char();
+ while (1) {
+ if (c == '\n') {
+ unget_char(c);
+ return;
+ }
+ if (c == EOF)
+ return;
c = get_char();
- for (int i = 0;; i++) {
- if (i >= buf_size) {
- if (buf_size == 0) {
- buf_size = 16;
- buf = new char[buf_size];
+ }
+}
+
+//////////////////////////////////////////////////////////////////////
+/* unget_char(c):
+ Restore character c onto input queue.
+
+ Write a character back onto the input stream.
+ EOF is gracefully handled.
+
+ c: In-parameter; character to be pushed onto the input queue.
+*/
+inline void
+unget_char(const Char c)
+{
+ if (c != EOF) {
+ int ch = (int) c;
+ if (ungetc(ch, current_file) == EOF)
+ fatal("could not unget character");
+ }
+}
+
+
+/**********************************************************************
+ parser subcommands
+ **********************************************************************/
+
+//////////////////////////////////////////////////////////////////////
+/* parse_color_command:
+ Process the commands m and DF, but not Df.
+
+ col: In-out-parameter; the color object to be set, must have
+ been initialized before.
+*/
+void
+parse_color_command(color *col)
+{
+ ColorArg gray = 0;
+ ColorArg red = 0, green = 0, blue = 0;
+ ColorArg cyan = 0, magenta = 0, yellow = 0, black = 0;
+ Char subcmd = next_arg_begin();
+ switch((int) subcmd) {
+ case 'c': // DFc or mc: CMY
+ cyan = get_color_arg();
+ magenta = get_color_arg();
+ yellow = get_color_arg();
+ col->set_cmy(cyan, magenta, yellow);
+ break;
+ case 'd': // DFd or md: set default color
+ col->set_default();
+ break;
+ case 'g': // DFg or mg: gray
+ gray = get_color_arg();
+ col->set_gray(gray);
+ break;
+ case 'k': // DFk or mk: CMYK
+ cyan = get_color_arg();
+ magenta = get_color_arg();
+ yellow = get_color_arg();
+ black = get_color_arg();
+ col->set_cmyk(cyan, magenta, yellow, black);
+ break;
+ case 'r': // DFr or mr: RGB
+ red = get_color_arg();
+ green = get_color_arg();
+ blue = get_color_arg();
+ col->set_rgb(red, green, blue);
+ break;
+ default:
+ error("invalid color scheme `%1'", (int) subcmd);
+ break;
+ } // end of color subcommands
+}
+
+//////////////////////////////////////////////////////////////////////
+/* parse_D_command():
+ Parse the subcommands of graphical command D.
+
+ This is the part of the do_file() parser that scans the graphical
+ subcommands.
+ - Error on lacking or wrong arguments.
+ - Warning on too many arguments.
+ - Line is always skipped.
+*/
+void
+parse_D_command()
+{
+ Char subcmd = next_arg_begin();
+ switch((int) subcmd) {
+ case '~': // D~: draw B-spline
+ // actually, this isn't available for some postprocessors
+ // fall through
+ default: // unknown options are passed to device
+ {
+ IntArray *args = get_D_variable_args();
+ send_draw(subcmd, args);
+ position_to_end_of_args(args);
+ delete args;
+ break;
+ }
+ case 'a': // Da: draw arc
+ {
+ IntArray *args = get_D_fixed_args(4);
+ send_draw(subcmd, args);
+ position_to_end_of_args(args);
+ delete args;
+ break;
+ }
+ case 'c': // Dc: draw circle line
+ {
+ IntArray *args = get_D_fixed_args(1);
+ send_draw(subcmd, args);
+ // move to right end
+ current_env->hpos += (*args)[0];
+ delete args;
+ break;
+ }
+ case 'C': // DC: draw solid circle
+ {
+ IntArray *args = get_D_fixed_args_odd_dummy(1);
+ send_draw(subcmd, args);
+ // move to right end
+ current_env->hpos += (*args)[0];
+ delete args;
+ break;
+ }
+ case 'e': // De: draw ellipse line
+ case 'E': // DE: draw solid ellipse
+ {
+ IntArray *args = get_D_fixed_args(2);
+ send_draw(subcmd, args);
+ // move to right end
+ current_env->hpos += (*args)[0];
+ delete args;
+ break;
+ }
+ case 'f': // Df: set fill gray; obsoleted by DFg
+ {
+ IntArg arg = get_integer_arg();
+ if ((arg >= 0) && (arg <= 1000)) {
+ // convert arg and treat it like DFg
+ ColorArg gray = color_from_Df_command(arg);
+ current_env->fill->set_gray(gray);
}
else {
- char *old_buf = buf;
- int old_size = buf_size;
- buf_size *= 2;
- buf = new char[buf_size];
- memcpy(buf, old_buf, old_size);
- a_delete old_buf;
+ // set fill color to the same value as the current outline color
+ delete current_env->fill;
+ current_env->fill = new color(current_env->col);
}
+ pr->change_fill_color(current_env);
+ // skip unused `vertical' component (\D'...' always emits pairs)
+ (void) get_integer_arg();
+ // no positioning
+ skip_line_x();
+ break;
}
- if ((!is_long && (c == ' ' || c == '\n')) || c == EOF) {
- buf[i] = '\0';
+ case 'F': // DF: set fill color, several formats
+ parse_color_command(current_env->fill);
+ pr->change_fill_color(current_env);
+ // no positioning (setting-only command)
+ skip_line_x();
+ break;
+ case 'l': // Dl: draw line
+ {
+ IntArray *args = get_D_fixed_args(2);
+ send_draw(subcmd, args);
+ position_to_end_of_args(args);
+ delete args;
break;
}
- if (is_long && c == '\n') {
- current_lineno++;
- c = get_char();
- if (c == '+')
- c = '\n';
+ case 'p': // Dp: draw closed polygon line
+ case 'P': // DP: draw solid closed polygon
+ {
+ IntArray *args = get_D_variable_args();
+ send_draw(subcmd, args);
+# ifdef STUPID_DRAWING_POSITIONING
+ // final args positioning
+ position_to_end_of_args(args);
+# endif
+ delete args;
+ break;
+ }
+ case 't': // Dt: set line thickness
+ {
+ IntArray *args = get_D_fixed_args_odd_dummy(1);
+ send_draw(subcmd, args);
+# ifdef STUPID_DRAWING_POSITIONING
+ // final args positioning
+ position_to_end_of_args(args);
+# endif
+ // no positioning?
+ delete args;
+ break;
+ }
+ } // end of D subcommands
+}
+
+//////////////////////////////////////////////////////////////////////
+/* parse_x_command():
+ Parse subcommands of the device control command x.
+
+ This is the part of the do_file() parser that scans the device
+ controlling commands.
+ - Error on duplicate prologue commands.
+ - Error on wrong or lacking arguments.
+ - Warning on too many arguments.
+ - Line is always skipped.
+
+ Globals:
+ - current_env: is set by many subcommands.
+ - npages: page counting variable
+
+ Return: boolean in the meaning of `stopped'
+ - true if parsing should be stopped (`x stop').
+ - false if parsing should continue.
+*/
+bool
+parse_x_command(void)
+{
+ bool stopped = false;
+ char *subcmd_str = get_string_arg();
+ char subcmd = subcmd_str[0];
+ switch (subcmd) {
+ case 'f': // x font: mount font
+ {
+ IntArg n = get_integer_arg();
+ char *name = get_string_arg();
+ pr->load_font(n, name);
+ delete name;
+ skip_line_x();
+ break;
+ }
+ case 'F': // x Filename: set filename for errors
+ {
+ char *str_arg = get_string_arg();
+ if (str_arg == 0)
+ warning("empty argument for `x F' command");
else {
- buf[i] = '\0';
- break;
+ remember_filename(str_arg);
+ delete str_arg;
}
- }
- buf[i] = c;
- c = get_char();
+ break;
+ }
+ case 'H': // x Height: set character height
+ current_env->height = get_integer_arg();
+ if (current_env->height == current_env->size)
+ current_env->height = 0;
+ skip_line_x();
+ break;
+ case 'i': // x init: initialize device
+ error("duplicate `x init' command");
+ skip_line_x();
+ break;
+ case 'p': // x pause: pause device
+ skip_line_x();
+ break;
+ case 'r': // x res: set resolution
+ error("duplicate `x res' command");
+ skip_line_x();
+ break;
+ case 's': // x stop: stop device
+ stopped = true;
+ skip_line_x();
+ break;
+ case 'S': // x Slant: set slant
+ current_env->slant = get_integer_arg();
+ skip_line_x();
+ break;
+ case 't': // x trailer: generate trailer info
+ skip_line_x();
+ break;
+ case 'T': // x Typesetter: set typesetter
+ error("duplicate `x T' command");
+ skip_line();
+ break;
+ case 'u': // x underline: from .cu
+ {
+ char *str_arg = get_string_arg();
+ pr->special(str_arg, current_env, 'u');
+ delete str_arg;
+ skip_line_x();
+ break;
+ }
+ case 'X': // x X: send uninterpretedly to device
+ {
+ char *str_arg = get_extended_arg(); // includes line skip
+ if (npages <= 0)
+ error("`x X' command invalid before first `p' command");
+ else
+ pr->special(str_arg, current_env);
+ delete str_arg;
+ break;
+ }
+ default: // ignore unknown x commands, but warn
+ warning("unknown command `x %1'", subcmd);
+ skip_line();
}
- if (c != EOF)
- ungetc(c, current_file);
- return buf;
+ delete subcmd_str;
+ return stopped;
}
-void skip_line()
+
+/**********************************************************************
+ exported part (by driver.h)
+ **********************************************************************/
+
+////////////////////////////////////////////////////////////////////////
+/* do_file():
+ Parse and postprocess groff intermediate output.
+
+ filename: "-" for standard input, normal file name otherwise
+*/
+void
+do_file(const char *filename)
{
- int c;
- while ((c = get_char()) != EOF)
- if (c == '\n') {
- current_lineno++;
- break;
+ Char command;
+ bool stopped = false; // terminating condition
+
+#ifdef USE_ENV_STACK
+ EnvStack env_stack = EnvStack();
+#endif // USE_ENV_STACK
+
+ // setup of global variables
+ npages = 0;
+ current_lineno = 1;
+ // `pr' is initialized after the prologue.
+ // `device' is set by the 1st prologue command.
+
+ if (filename[0] == '-' && filename[1] == '\0')
+ current_file = stdin;
+ else {
+ errno = 0;
+ current_file = fopen(filename, "r");
+ if (errno != 0 || current_file == 0) {
+ error("can't open file `%1'", filename);
+ return;
}
+ }
+ remember_filename(filename);
+
+ if (current_env != 0)
+ delete_current_env();
+ current_env = new environment;
+ current_env->col = new color;
+ current_env->fill = new color;
+ current_env->fontno = -1;
+ current_env->height = 0;
+ current_env->hpos = -1;
+ current_env->slant = 0;
+ current_env->size = 0;
+ current_env->vpos = -1;
+
+ // parsing of prologue (first 3 commands)
+ {
+ char *str_arg;
+ IntArg int_arg;
+
+ // 1st command `x T'
+ command = next_command();
+ if ((int) command == EOF)
+ return;
+ if ((int) command != 'x')
+ fatal("the first command must be `x T'");
+ str_arg = get_string_arg();
+ if (str_arg[0] != 'T')
+ fatal("the first command must be `x T'");
+ delete str_arg;
+ char *tmp_dev = get_string_arg();
+ if (pr == 0) { // note: `pr' initialized after prologue
+ device = tmp_dev;
+ if (!font::load_desc())
+ fatal("couldn't load DESC file, can't continue");
+ }
+ else {
+ if (device == 0 || strcmp(device, tmp_dev) != 0)
+ fatal("all files must use the same device");
+ delete tmp_dev;
+ }
+ skip_line_x(); // ignore further arguments
+ current_env->size = 10 * font::sizescale;
+
+ // 2nd command `x res'
+ command = next_command();
+ if ((int) command != 'x')
+ fatal("the second command must be `x res'");
+ str_arg = get_string_arg();
+ if (str_arg[0] != 'r')
+ fatal("the second command must be `x res'");
+ delete str_arg;
+ int_arg = get_integer_arg();
+ EnvInt font_res = font::res;
+ if (int_arg != font_res)
+ fatal("resolution does not match");
+ int_arg = get_integer_arg();
+ if (int_arg != font::hor)
+ fatal("minimum horizontal motion does not match");
+ int_arg = get_integer_arg();
+ if (int_arg != font::vert)
+ fatal("minimum vertical motion does not match");
+ skip_line_x(); // ignore further arguments
+
+ // 3rd command `x init'
+ command = next_command();
+ if (command != 'x')
+ fatal("the third command must be `x init'");
+ str_arg = get_string_arg();
+ if (str_arg[0] != 'i')
+ fatal("the third command must be `x init'");
+ delete str_arg;
+ skip_line_x();
+ }
+
+ // parsing of body
+ if (pr == 0)
+ pr = make_printer();
+ while (!stopped) {
+ command = next_command();
+ if (command == EOF)
+ break;
+ // spaces, tabs, comments, and newlines are skipped here
+ switch ((int) command) {
+ case '#': // #: comment, ignore up to end of line
+ skip_line();
+ break;
+#ifdef USE_ENV_STACK
+ case '{': // {: start a new environment (a copy)
+ env_stack.push(current_env);
+ break;
+ case '}': // }: pop previous env from stack
+ delete_current_env();
+ current_env = env_stack.pop();
+ break;
+#endif // USE_ENV_STACK
+ case '0': // ddc: obsolete jump and print command
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ { // expect 2 digits and a character
+ char s[3];
+ Char c = next_arg_begin();
+ if (npages <= 0)
+ fatal_command(command);
+ if (!isdigit((int) c)) {
+ error("digit expected");
+ c = 0;
+ }
+ s[0] = (char) command;
+ s[1] = (char) c;
+ s[2] = '\0';
+ errno = 0;
+ long int x = strtol(s, 0, 10);
+ if (errno != 0)
+ error("couldn't convert 2 digits");
+ EnvInt hor_pos = (EnvInt) x;
+ current_env->hpos += hor_pos;
+ c = next_arg_begin();
+ if ((int) c == '\n' || (int) c == EOF)
+ error("character argument expected");
+ else
+ pr->set_ascii_char((unsigned char) c, current_env);
+ break;
+ }
+ case 'c': // c: print ascii char without moving
+ {
+ if (npages <= 0)
+ fatal_command(command);
+ Char c = next_arg_begin();
+ if (c == '\n' || c == EOF)
+ error("missing argument to `c' command");
+ else
+ pr->set_ascii_char((unsigned char) c, current_env);
+ break;
+ }
+ case 'C': // C: print named special character
+ {
+ if (npages <= 0)
+ fatal_command(command);
+ char *str_arg = get_string_arg();
+ pr->set_special_char(str_arg, current_env);
+ delete str_arg;
+ break;
+ }
+ case 'D': // drawing commands
+ if (npages <= 0)
+ fatal_command(command);
+ parse_D_command();
+ break;
+ case 'f': // f: set font to number
+ current_env->fontno = get_integer_arg();
+ break;
+ case 'F': // F: obsolete, replaced by `x F'
+ {
+ char *str_arg = get_string_arg();
+ remember_filename(str_arg);
+ delete str_arg;
+ break;
+ }
+ case 'h': // h: relative horizontal move
+ current_env->hpos += (EnvInt) get_integer_arg();
+ break;
+ case 'H': // H: absolute horizontal positioning
+ current_env->hpos = (EnvInt) get_integer_arg();
+ break;
+ case 'm': // m: glyph color
+ parse_color_command(current_env->col);
+ pr->change_color(current_env);
+ break;
+ case 'n': // n: print end of line
+ // ignore two arguments (historically)
+ if (npages <= 0)
+ fatal_command(command);
+ pr->end_of_line();
+ (void) get_integer_arg();
+ (void) get_integer_arg();
+ break;
+ case 'N': // N: print char with given int code
+ if (npages <= 0)
+ fatal_command(command);
+ pr->set_numbered_char(get_integer_arg(), current_env);
+ break;
+ case 'p': // p: start new page with given number
+ if (npages > 0)
+ pr->end_page(current_env->vpos);
+ npages++; // increment # of processed pages
+ pr->begin_page(get_integer_arg());
+ current_env->vpos = 0;
+ break;
+ case 's': // s: set point size
+ current_env->size = get_integer_arg();
+ if (current_env->height == current_env->size)
+ current_env->height = 0;
+ break;
+ case 't': // t: print a text word
+ {
+ char c;
+ if (npages <= 0)
+ fatal_command(command);
+ char *str_arg = get_string_arg();
+ size_t i = 0;
+ while ((c = str_arg[i++]) != '\0') {
+ EnvInt w;
+ pr->set_ascii_char((unsigned char) c, current_env, &w);
+ current_env->hpos += w;
+ }
+ delete str_arg;
+ break;
+ }
+ case 'u': // u: print spaced word
+ {
+ char c;
+ if (npages <= 0)
+ fatal_command(command);
+ EnvInt kern = (EnvInt) get_integer_arg();
+ char *str_arg = get_string_arg();
+ size_t i = 0;
+ while ((c = str_arg[i++]) != '\0') {
+ EnvInt w;
+ pr->set_ascii_char((unsigned char) c, current_env, &w);
+ current_env->hpos += w + kern;
+ }
+ delete str_arg;
+ break;
+ }
+ case 'v': // v: relative vertical move
+ current_env->vpos += (EnvInt) get_integer_arg();
+ break;
+ case 'V': // V: absolute vertical positioning
+ current_env->vpos = (EnvInt) get_integer_arg();
+ break;
+ case 'w': // w: inform about paddable space
+ break;
+ case 'x': // device controlling commands
+ stopped = parse_x_command();
+ break;
+ default:
+ warning("unrecognized command `%1'", (unsigned char) command);
+ skip_line();
+ break;
+ } // end of switch
+ } // end of while
+
+ // end of file reached
+ if (npages > 0)
+ pr->end_page(current_env->vpos);
+ fclose(current_file);
+ // If `stopped' is not `true' here then there wasn't any `x stop'.
+ if (!stopped)
+ warning("no final `x stop' command");
+ delete_current_env();
}
diff --git a/contrib/groff/src/libs/libdriver/printer.cc b/contrib/groff/src/libs/libdriver/printer.cc
index 4d66f7b..c97e2ce 100644
--- a/contrib/groff/src/libs/libdriver/printer.cc
+++ b/contrib/groff/src/libs/libdriver/printer.cc
@@ -1,22 +1,30 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2001 Free Software Foundation, Inc.
- Written by James Clark (jjc@jclark.com)
-This file is part of groff.
+// <groff_src_dir>/src/libs/libdriver/printer.cc
-groff is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
-version.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002
+ Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
-groff is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
+ Last update: 12 Apr 2002
-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. */
+ This file is part of groff.
+
+ groff is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ groff is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with groff; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+*/
#include "driver.h"
@@ -105,6 +113,14 @@ void printer::draw(int, int *, int, const environment *)
{
}
+void printer::change_color(const environment *)
+{
+}
+
+void printer::change_fill_color(const environment *)
+{
+}
+
void printer::set_ascii_char(unsigned char c, const environment *env,
int *widthp)
{
@@ -126,13 +142,12 @@ void printer::set_special_char(const char *nm, const environment *env,
int *widthp)
{
font *f;
- int w;
+ int w;
int i = set_char_and_width(nm, env, &w, &f);
if (i != -1) {
set_char(i, f, env, w, nm);
- if (widthp) {
+ if (widthp)
*widthp = w;
- }
}
}
@@ -199,73 +214,3 @@ font *printer::get_font_from_index(int fontno)
else
return(0);
}
-
-// This utility function adjusts the specified center of the
-// arc so that it is equidistant between the specified start
-// and end points. (p[0], p[1]) is a vector from the current
-// point to the center; (p[2], p[3]) is a vector from the
-// center to the end point. If the center can be adjusted,
-// a vector from the current point to the adjusted center is
-// stored in c[0], c[1] and 1 is returned. Otherwise 0 is
-// returned.
-
-#if 1
-int printer::adjust_arc_center(const int *p, double *c)
-{
- // We move the center along a line parallel to the line between
- // the specified start point and end point so that the center
- // is equidistant between the start and end point.
- // It can be proved (using Lagrange multipliers) that this will
- // give the point nearest to the specified center that is equidistant
- // between the start and end point.
-
- double x = p[0] + p[2]; // (x, y) is the end point
- double y = p[1] + p[3];
- double n = x*x + y*y;
- if (n != 0) {
- c[0]= double(p[0]);
- c[1] = double(p[1]);
- double k = .5 - (c[0]*x + c[1]*y)/n;
- c[0] += k*x;
- c[1] += k*y;
- return 1;
- }
- else
- return 0;
-}
-#else
-int printer::adjust_arc_center(const int *p, double *c)
-{
- int x = p[0] + p[2]; // (x, y) is the end point
- int y = p[1] + p[3];
- // Start at the current point; go in the direction of the specified
- // center point until we reach a point that is equidistant between
- // the specified starting point and the specified end point. Place
- // the center of the arc there.
- double n = p[0]*double(x) + p[1]*double(y);
- if (n > 0) {
- double k = (double(x)*x + double(y)*y)/(2.0*n);
- // (cx, cy) is our chosen center
- c[0] = k*p[0];
- c[1] = k*p[1];
- return 1;
- }
- else {
- // We would never reach such a point. So instead start at the
- // specified end point of the arc. Go towards the specified
- // center point until we reach a point that is equidistant between
- // the specified start point and specified end point. Place
- // the center of the arc there.
- n = p[2]*double(x) + p[3]*double(y);
- if (n > 0) {
- double k = 1 - (double(x)*x + double(y)*y)/(2.0*n);
- // (c[0], c[1]) is our chosen center
- c[0] = p[0] + k*p[2];
- c[1] = p[1] + k*p[3];
- return 1;
- }
- else
- return 0;
- }
-}
-#endif
diff --git a/contrib/groff/src/libs/libgroff/Makefile.sub b/contrib/groff/src/libs/libgroff/Makefile.sub
index ff5c655..ff6bd00 100644
--- a/contrib/groff/src/libs/libgroff/Makefile.sub
+++ b/contrib/groff/src/libs/libgroff/Makefile.sub
@@ -1,42 +1,48 @@
LIB=groff
OBJS=\
- assert.o \
- change_lf.o \
- cmap.o \
- cset.o \
- device.o \
- errarg.o \
- error.o \
- fatal.o \
- filename.o \
- font.o \
- fontfile.o \
- getopt.o \
- getopt1.o \
- htmlindicate.o \
- illegal.o \
- lf.o \
- lineno.o \
- macropath.o \
- maxfilename.o \
- nametoindex.o \
- new.o \
- prime.o \
- progname.o \
- ptable.o \
- searchpath.o \
- string.o \
- strsave.o \
- tmpfile.o \
- iftoa.o \
- itoa.o \
- matherr.o \
- version.o \
+ assert.$(OBJEXT) \
+ change_lf.$(OBJEXT) \
+ cmap.$(OBJEXT) \
+ color.$(OBJEXT) \
+ cset.$(OBJEXT) \
+ device.$(OBJEXT) \
+ errarg.$(OBJEXT) \
+ error.$(OBJEXT) \
+ fatal.$(OBJEXT) \
+ filename.$(OBJEXT) \
+ font.$(OBJEXT) \
+ fontfile.$(OBJEXT) \
+ geometry.$(OBJEXT) \
+ getopt.$(OBJEXT) \
+ getopt1.$(OBJEXT) \
+ htmlhint.$(OBJEXT) \
+ invalid.$(OBJEXT) \
+ lf.$(OBJEXT) \
+ lineno.$(OBJEXT) \
+ macropath.$(OBJEXT) \
+ maxfilename.$(OBJEXT) \
+ mksdir.$(OBJEXT) \
+ nametoindex.$(OBJEXT) \
+ new.$(OBJEXT) \
+ paper.$(OBJEXT) \
+ prime.$(OBJEXT) \
+ progname.$(OBJEXT) \
+ ptable.$(OBJEXT) \
+ searchpath.$(OBJEXT) \
+ string.$(OBJEXT) \
+ strsave.$(OBJEXT) \
+ tmpfile.$(OBJEXT) \
+ tmpname.$(OBJEXT) \
+ iftoa.$(OBJEXT) \
+ itoa.$(OBJEXT) \
+ matherr.$(OBJEXT) \
+ version.$(OBJEXT) \
$(LIBOBJS)
CCSRCS=\
$(srcdir)/assert.cc \
$(srcdir)/change_lf.cc \
$(srcdir)/cmap.cc \
+ $(srcdir)/color.cc \
$(srcdir)/cset.cc \
$(srcdir)/device.cc \
$(srcdir)/errarg.cc \
@@ -45,14 +51,18 @@ CCSRCS=\
$(srcdir)/filename.cc \
$(srcdir)/font.cc \
$(srcdir)/fontfile.cc \
- $(srcdir)/htmlindicate.cc \
- $(srcdir)/illegal.cc \
+ $(srcdir)/geometry.cc \
+ $(srcdir)/htmlhint.cc \
+ $(srcdir)/invalid.cc \
$(srcdir)/lf.cc \
$(srcdir)/lineno.cc \
$(srcdir)/macropath.cc \
$(srcdir)/maxfilename.cc \
+ $(srcdir)/mksdir.cc \
+ $(srcdir)/mkstemp.cc \
$(srcdir)/nametoindex.cc \
$(srcdir)/new.cc \
+ $(srcdir)/paper.cc \
$(srcdir)/prime.cc \
$(srcdir)/progname.cc \
$(srcdir)/ptable.cc \
@@ -60,6 +70,7 @@ CCSRCS=\
$(srcdir)/string.cc \
$(srcdir)/strsave.cc \
$(srcdir)/tmpfile.cc \
+ $(srcdir)/tmpname.cc \
version.cc
CSRCS=\
$(srcdir)/fmod.c \
@@ -71,16 +82,22 @@ CSRCS=\
$(srcdir)/matherr.c \
$(srcdir)/putenv.c \
$(srcdir)/strerror.c \
- $(srcdir)/strtol.c
+ $(srcdir)/strtol.c \
+ $(srcdir)/../snprintf/snprintf.c
GENSRCS=\
version.cc
-version=`cat $(top_srcdir)/VERSION`
-revision=`cat $(top_srcdir)/REVISION`
+src_version=`cat $(top_srcdir)/VERSION`
+src_revision=`cat $(top_srcdir)/REVISION`
version.cc: $(top_srcdir)/VERSION $(top_srcdir)/REVISION
@echo Making version.cc
- @echo const char \*version_string = \"$(version)\"\; >$@
- @echo const char \*revision_string = \"$(revision)\"\; >>$@
- @echo extern \"C\" const char \*Version_string = \"$(version).$(revision)\"\; | \
+ @echo const char \*version_string = \"$(src_version)\"\; >$@
+ @echo const char \*revision_string = \"$(src_revision)\"\; >>$@
+ @echo extern \"C\" const char \*Version_string = \"$(src_version).$(src_revision)\"\; | \
sed -e 's/\.0\"/\"/' >>$@
+
+# We have to avoid $(COMPILE.c) since we must not use groff's `assert.h'
+snprintf.$(OBJEXT): $(srcdir)/../snprintf/snprintf.c
+ $(CC) -c $(CDEFINES) $(CFLAGS) $(CPPFLAGS) \
+ $(srcdir)/../snprintf/snprintf.c
diff --git a/contrib/groff/src/libs/libgroff/color.cc b/contrib/groff/src/libs/libgroff/color.cc
new file mode 100644
index 0000000..68e604c
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/color.cc
@@ -0,0 +1,363 @@
+// -*- C++ -*-
+
+/* <groff_src_dir>/src/libs/libgroff/color.cc
+
+Last update: 10 Apr 2002
+
+Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ Written by Gaius Mulley <gaius@glam.ac.uk>
+
+This file is part of groff.
+
+groff is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "color.h"
+#include "cset.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <assert.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include "errarg.h"
+#include "error.h"
+
+static inline unsigned int
+min(const unsigned int a, const unsigned int b)
+{
+ if (a < b)
+ return a;
+ else
+ return b;
+}
+
+color::color(const color * const c)
+{
+ scheme = c->scheme;
+ components[0] = c->components[0];
+ components[1] = c->components[1];
+ components[2] = c->components[2];
+ components[3] = c->components[3];
+}
+
+int color::operator==(const color & c) const
+{
+ if (scheme != c.scheme)
+ return 0;
+ switch (scheme) {
+ case DEFAULT:
+ break;
+ case RGB:
+ if (Red != c.Red || Green != c.Green || Blue != c.Blue)
+ return 0;
+ break;
+ case CMYK:
+ if (Cyan != c.Cyan || Magenta != c.Magenta
+ || Yellow != c.Yellow || Black != c.Black)
+ return 0;
+ break;
+ case GRAY:
+ if (Gray != c.Gray)
+ return 0;
+ break;
+ case CMY:
+ if (Cyan != c.Cyan || Magenta != c.Magenta || Yellow != c.Yellow)
+ return 0;
+ break;
+ }
+ return 1;
+}
+
+int color::operator!=(const color & c) const
+{
+ return !(*this == c);
+}
+
+color_scheme color::get_components(unsigned int *c) const
+{
+#if 0
+ if (sizeof (c) < sizeof (unsigned int) * 4)
+ fatal("argument is not big enough to store 4 color components");
+#endif
+ c[0] = components[0];
+ c[1] = components[1];
+ c[2] = components[2];
+ c[3] = components[3];
+ return scheme;
+}
+
+void color::set_default()
+{
+ scheme = DEFAULT;
+}
+
+// (0, 0, 0) is black
+
+void color::set_rgb(const unsigned int r, const unsigned int g,
+ const unsigned int b)
+{
+ scheme = RGB;
+ Red = min(MAX_COLOR_VAL, r);
+ Green = min(MAX_COLOR_VAL, g);
+ Blue = min(MAX_COLOR_VAL, b);
+}
+
+// (0, 0, 0) is white
+
+void color::set_cmy(const unsigned int c, const unsigned int m,
+ const unsigned int y)
+{
+ scheme = CMY;
+ Cyan = min(MAX_COLOR_VAL, c);
+ Magenta = min(MAX_COLOR_VAL, m);
+ Yellow = min(MAX_COLOR_VAL, y);
+}
+
+// (0, 0, 0, 0) is white
+
+void color::set_cmyk(const unsigned int c, const unsigned int m,
+ const unsigned int y, const unsigned int k)
+{
+ scheme = CMYK;
+ Cyan = min(MAX_COLOR_VAL, c);
+ Magenta = min(MAX_COLOR_VAL, m);
+ Yellow = min(MAX_COLOR_VAL, y);
+ Black = min(MAX_COLOR_VAL, k);
+}
+
+// (0) is black
+
+void color::set_gray(const unsigned int g)
+{
+ scheme = GRAY;
+ Gray = min(MAX_COLOR_VAL, g);
+}
+
+/*
+ * atoh - computes the decimal value of a hexadecimal number string.
+ * `length' characters of `s' are read. Returns 1 if successful.
+ */
+
+static int atoh(unsigned int *result,
+ const char * const s, const size_t length)
+{
+ size_t i = 0;
+ unsigned int val = 0;
+ while ((i < length) && csxdigit(s[i])) {
+ if (csdigit(s[i]))
+ val = val*0x10 + (s[i]-'0');
+ else if (csupper(s[i]))
+ val = val*0x10 + (s[i]-'A') + 10;
+ else
+ val = val*0x10 + (s[i]-'a') + 10;
+ i++;
+ }
+ if (i != length)
+ return 0;
+ *result = val;
+ return 1;
+}
+
+/*
+ * read_encoding - set color from a hexadecimal color string.
+ *
+ * Use color scheme `cs' to parse `n' color components from string `s'.
+ * Returns 1 if successful.
+ */
+
+int color::read_encoding(const color_scheme cs, const char * const s,
+ const size_t n)
+{
+ size_t hex_length = 2;
+ scheme = cs;
+ char *p = (char *) s;
+ p++;
+ if (*p == '#') {
+ hex_length = 4;
+ p++;
+ }
+ for (size_t i = 0; i < n; i++) {
+ if (!atoh(&(components[i]), p, hex_length))
+ return 0;
+ if (hex_length == 2)
+ components[i] *= 0x101; // scale up -- 0xff should become 0xffff
+ p += hex_length;
+ }
+ return 1;
+}
+
+int color::read_rgb(const char * const s)
+{
+ return read_encoding(RGB, s, 3);
+}
+
+int color::read_cmy(const char * const s)
+{
+ return read_encoding(CMY, s, 3);
+}
+
+int color::read_cmyk(const char * const s)
+{
+ return read_encoding(CMYK, s, 4);
+}
+
+int color::read_gray(const char * const s)
+{
+ return read_encoding(GRAY, s, 1);
+}
+
+void
+color::get_rgb(unsigned int *r, unsigned int *g, unsigned int *b) const
+{
+ switch (scheme) {
+ case RGB:
+ *r = Red;
+ *g = Green;
+ *b = Blue;
+ break;
+ case CMY:
+ *r = MAX_COLOR_VAL - Cyan;
+ *g = MAX_COLOR_VAL - Magenta;
+ *b = MAX_COLOR_VAL - Yellow;
+ break;
+ case CMYK:
+ *r = MAX_COLOR_VAL
+ - min(MAX_COLOR_VAL,
+ Cyan * (MAX_COLOR_VAL - Black) / MAX_COLOR_VAL + Black);
+ *g = MAX_COLOR_VAL
+ - min(MAX_COLOR_VAL,
+ Magenta * (MAX_COLOR_VAL - Black) / MAX_COLOR_VAL + Black);
+ *b = MAX_COLOR_VAL
+ - min(MAX_COLOR_VAL,
+ Yellow * (MAX_COLOR_VAL - Black) / MAX_COLOR_VAL + Black);
+ break;
+ case GRAY:
+ *r = *g = *b = Gray;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+}
+
+void
+color::get_cmy(unsigned int *c, unsigned int *m, unsigned int *y) const
+{
+ switch (scheme) {
+ case RGB:
+ *c = MAX_COLOR_VAL - Red;
+ *m = MAX_COLOR_VAL - Green;
+ *y = MAX_COLOR_VAL - Blue;
+ break;
+ case CMY:
+ *c = Cyan;
+ *m = Magenta;
+ *y = Yellow;
+ break;
+ case CMYK:
+ *c = min(MAX_COLOR_VAL,
+ Cyan * (MAX_COLOR_VAL - Black) / MAX_COLOR_VAL + Black);
+ *m = min(MAX_COLOR_VAL,
+ Magenta * (MAX_COLOR_VAL - Black) / MAX_COLOR_VAL + Black);
+ *y = min(MAX_COLOR_VAL,
+ Yellow * (MAX_COLOR_VAL - Black) / MAX_COLOR_VAL + Black);
+ break;
+ case GRAY:
+ *c = *m = *y = MAX_COLOR_VAL - Gray;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+}
+
+void color::get_cmyk(unsigned int *c, unsigned int *m,
+ unsigned int *y, unsigned int *k) const
+{
+ switch (scheme) {
+ case RGB:
+ *k = min(MAX_COLOR_VAL - Red,
+ min(MAX_COLOR_VAL - Green, MAX_COLOR_VAL - Blue));
+ if (MAX_COLOR_VAL == *k) {
+ *c = MAX_COLOR_VAL;
+ *m = MAX_COLOR_VAL;
+ *y = MAX_COLOR_VAL;
+ }
+ else {
+ *c = (MAX_COLOR_VAL * (MAX_COLOR_VAL - Red - *k))
+ / (MAX_COLOR_VAL - *k);
+ *m = (MAX_COLOR_VAL * (MAX_COLOR_VAL - Green - *k))
+ / (MAX_COLOR_VAL - *k);
+ *y = (MAX_COLOR_VAL * (MAX_COLOR_VAL - Blue - *k))
+ / (MAX_COLOR_VAL - *k);
+ }
+ break;
+ case CMY:
+ *k = min(Cyan, min(Magenta, Yellow));
+ if (MAX_COLOR_VAL == *k) {
+ *c = MAX_COLOR_VAL;
+ *m = MAX_COLOR_VAL;
+ *y = MAX_COLOR_VAL;
+ }
+ else {
+ *c = (MAX_COLOR_VAL * (Cyan - *k)) / (MAX_COLOR_VAL - *k);
+ *m = (MAX_COLOR_VAL * (Magenta - *k)) / (MAX_COLOR_VAL - *k);
+ *y = (MAX_COLOR_VAL * (Yellow - *k)) / (MAX_COLOR_VAL - *k);
+ }
+ break;
+ case CMYK:
+ *c = Cyan;
+ *m = Magenta;
+ *y = Yellow;
+ *k = Black;
+ break;
+ case GRAY:
+ *c = *m = *y = 0;
+ *k = MAX_COLOR_VAL - Gray;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+}
+
+// we use `0.222r + 0.707g + 0.071b' (this is the ITU standard)
+// as an approximation for gray
+
+void color::get_gray(unsigned int *g) const
+{
+ switch (scheme) {
+ case RGB:
+ *g = (222*Red + 707*Green + 71*Blue) / 1000;
+ break;
+ case CMY:
+ *g = MAX_COLOR_VAL - (222*Cyan + 707*Magenta + 71*Yellow) / 1000;
+ break;
+ case CMYK:
+ *g = (MAX_COLOR_VAL - (222*Cyan + 707*Magenta + 71*Yellow) / 1000)
+ * (MAX_COLOR_VAL - Black);
+ break;
+ case GRAY:
+ *g = Gray;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+}
+
+color default_color;
diff --git a/contrib/groff/src/libs/libgroff/errarg.cc b/contrib/groff/src/libs/libgroff/errarg.cc
index f8075ea..2ddc0cc 100644
--- a/contrib/groff/src/libs/libgroff/errarg.cc
+++ b/contrib/groff/src/libs/libgroff/errarg.cc
@@ -1,5 +1,6 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2002
+ Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -31,14 +32,14 @@ errarg::errarg() : type(EMPTY)
{
}
-errarg::errarg(unsigned char cc) : type(CHAR)
+errarg::errarg(int nn) : type(INTEGER)
{
- c = cc;
+ n = nn;
}
-errarg::errarg(int nn) : type(INTEGER)
+errarg::errarg(unsigned int uu) : type(UNSIGNED_INTEGER)
{
- n = nn;
+ u = uu;
}
errarg::errarg(char cc) : type(CHAR)
@@ -46,6 +47,11 @@ errarg::errarg(char cc) : type(CHAR)
c = cc;
}
+errarg::errarg(unsigned char cc) : type(CHAR)
+{
+ c = cc;
+}
+
errarg::errarg(double dd) : type(DOUBLE)
{
d = dd;
@@ -58,6 +64,7 @@ int errarg::empty() const
extern "C" {
const char *i_to_a(int);
+ const char *ui_to_a(unsigned int);
}
void errarg::print() const
@@ -66,6 +73,9 @@ void errarg::print() const
case INTEGER:
fputs(i_to_a(n), stderr);
break;
+ case UNSIGNED_INTEGER:
+ fputs(ui_to_a(u), stderr);
+ break;
case CHAR:
putc(c, stderr);
break;
diff --git a/contrib/groff/src/libs/libgroff/font.cc b/contrib/groff/src/libs/libgroff/font.cc
index aa602b4..69e46e1 100644
--- a/contrib/groff/src/libs/libgroff/font.cc
+++ b/contrib/groff/src/libs/libgroff/font.cc
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002
Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
@@ -19,8 +19,8 @@ You should have received a copy of the GNU General Public License along
with groff; see the file COPYING. If not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-#include <stdio.h>
-#include <string.h>
+#include "lib.h"
+
#include <ctype.h>
#include <assert.h>
#include <math.h>
@@ -29,7 +29,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "error.h"
#include "cset.h"
#include "font.h"
-#include "lib.h"
+#include "paper.h"
const char *const WS = " \t\n\r";
@@ -94,13 +94,12 @@ text_file::~text_file()
fclose(fp);
}
-
int text_file::next()
{
if (fp == 0)
return 0;
if (buf == 0) {
- buf = new char [128];
+ buf = new char[128];
size = 128;
}
for (;;) {
@@ -109,8 +108,8 @@ int text_file::next()
int c = getc(fp);
if (c == EOF)
break;
- if (illegal_input_char(c))
- error("illegal input character code `%1'", int(c));
+ if (invalid_input_char(c))
+ error("invalid input character code `%1'", int(c));
else {
if (i + 1 >= size) {
char *old_buf = buf;
@@ -161,6 +160,9 @@ font::font(const char *s)
font::~font()
{
+ for (int i = 0; i < ch_used; i++)
+ if (ch[i].special_device_coding)
+ a_delete ch[i].special_device_coding;
a_delete ch;
a_delete ch_index;
if (kern_hash_table) {
@@ -206,6 +208,34 @@ inline int font::scale(int w, int sz)
return sz == unitwidth ? w : scale_round(w, sz, unitwidth);
}
+int font::unit_scale(double *value, char unit)
+{
+ // we scale everything to inch
+ double divisor = 0;
+ switch (unit) {
+ case 'i':
+ divisor = 1;
+ break;
+ case 'p':
+ divisor = 72;
+ break;
+ case 'P':
+ divisor = 6;
+ break;
+ case 'c':
+ divisor = 2.54;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ if (divisor) {
+ *value /= divisor;
+ return 1;
+ }
+ return 0;
+}
+
int font::get_skew(int c, int point_size, int sl)
{
int h = get_height(c, point_size);
@@ -303,7 +333,7 @@ int font::get_space_width(int point_size)
}
font_kern_list::font_kern_list(int c1, int c2, int n, font_kern_list *p)
- : i1(c1), i2(c2), amount(n), next(p)
+: i1(c1), i2(c2), amount(n), next(p)
{
}
@@ -472,6 +502,58 @@ static char *trim_arg(char *p)
return p;
}
+int font::scan_papersize(const char *p,
+ const char **size, double *length, double *width)
+{
+ double l, w;
+ char lu[2], wu[2];
+ const char *pp = p;
+ int test_file = 1;
+ char line[255];
+again:
+ if (csdigit(*pp)) {
+ if (sscanf(pp, "%lf%1[ipPc],%lf%1[ipPc]", &l, lu, &w, wu) == 4
+ && l > 0 && w > 0
+ && unit_scale(&l, lu[0]) && unit_scale(&w, wu[0])) {
+ if (length)
+ *length = l;
+ if (width)
+ *width = w;
+ if (size)
+ *size = "custom";
+ return 1;
+ }
+ }
+ else {
+ int i;
+ for (i = 0; i < NUM_PAPERSIZES; i++)
+ if (strcasecmp(papersizes[i].name, pp) == 0) {
+ if (length)
+ *length = papersizes[i].length;
+ if (width)
+ *width = papersizes[i].width;
+ if (size)
+ *size = papersizes[i].name;
+ return 1;
+ }
+ if (test_file) {
+ FILE *f = fopen(p, "r");
+ if (f) {
+ fgets(line, 254, f);
+ fclose(f);
+ test_file = 0;
+ char *linep = strchr(line, '\0');
+ // skip final newline, if any
+ if (*(--linep) == '\n')
+ *linep = '\0';
+ pp = line;
+ goto again;
+ }
+ }
+ }
+ return 0;
+}
+
// If the font can't be found, then if not_found is non-NULL, it will be set
// to 1 otherwise a message will be printed.
@@ -586,12 +668,12 @@ int font::load(int *not_found)
}
int i1 = name_to_index(c1);
if (i1 < 0) {
- t.error("illegal character `%1'", c1);
+ t.error("invalid character `%1'", c1);
return 0;
}
int i2 = name_to_index(c2);
if (i2 < 0) {
- t.error("illegal character `%1'", c2);
+ t.error("invalid character `%1'", c2);
return 0;
}
add_kern(i1, i2, n);
@@ -624,7 +706,7 @@ int font::load(int *not_found)
}
int index = name_to_index(nm);
if (index < 0) {
- t.error("illegal character `%1'", nm);
+ t.error("invalid character `%1'", nm);
return 0;
}
copy_entry(index, last_index);
@@ -671,20 +753,15 @@ int font::load(int *not_found)
t.error("bad code `%1' for character `%2'", p, nm);
return 0;
}
-
p = strtok(0, WS);
if ((p == NULL) || (strcmp(p, "--") == 0)) {
metric.special_device_coding = NULL;
- } else {
- char *name=(char *)malloc(strlen(p)+1);
-
- if (name == NULL) {
- fatal("malloc failed while reading character encoding");
- }
+ }
+ else {
+ char *name = new char[strlen(p) + 1];
strcpy(name, p);
metric.special_device_coding = name;
}
-
if (strcmp(nm, "---") == 0) {
last_index = number_to_index(metric.code);
add_entry(last_index, metric);
@@ -692,7 +769,7 @@ int font::load(int *not_found)
else {
last_index = name_to_index(nm);
if (last_index < 0) {
- t.error("illegal character `%1'", nm);
+ t.error("invalid character `%1'", nm);
return 0;
}
add_entry(last_index, metric);
@@ -736,7 +813,6 @@ static struct {
{ "sizescale", &font::sizescale }
};
-
int font::load_desc()
{
int nfonts = 0;
@@ -769,15 +845,6 @@ int font::load_desc()
return 0;
}
}
- else if (strcmp("tcommand", p) == 0) {
- tcommand = 1;
- }
- else if (strcmp("pass_filenames", p) == 0) {
- pass_filenames = 1;
- }
- else if (strcmp("use_charnames_in_special", p) == 0) {
- use_charnames_in_special = 1;
- }
else if (strcmp("family", p) == 0) {
p = strtok(0, WS);
if (!p) {
@@ -815,6 +882,31 @@ int font::load_desc()
}
font_name_table[nfonts] = 0;
}
+ else if (strcmp("papersize", p) == 0) {
+ p = strtok(0, WS);
+ if (!p) {
+ t.error("papersize command requires an argument");
+ return 0;
+ }
+ int found_paper = 0;
+ while (p) {
+ double unscaled_paperwidth, unscaled_paperlength;
+ if (scan_papersize(p, &papersize, &unscaled_paperlength,
+ &unscaled_paperwidth)) {
+ paperwidth = int(unscaled_paperwidth * res + 0.5);
+ paperlength = int(unscaled_paperlength * res + 0.5);
+ found_paper = 1;
+ break;
+ }
+ p = strtok(0, WS);
+ }
+ if (!found_paper) {
+ t.error("bad paper size");
+ return 0;
+ }
+ }
+ else if (strcmp("pass_filenames", p) == 0)
+ pass_filenames = 1;
else if (strcmp("sizes", p) == 0) {
int n = 16;
sizes = new int[n];
@@ -885,6 +977,10 @@ int font::load_desc()
style_table[i++] = tem;
}
}
+ else if (strcmp("tcommand", p) == 0)
+ tcommand = 1;
+ else if (strcmp("use_charnames_in_special", p) == 0)
+ use_charnames_in_special = 1;
else if (strcmp("charset", p) == 0)
break;
else if (unknown_desc_command_handler) {
diff --git a/contrib/groff/src/libs/libgroff/fontfile.cc b/contrib/groff/src/libs/libgroff/fontfile.cc
index cc1ad2c..8502d12 100644
--- a/contrib/groff/src/libs/libgroff/fontfile.cc
+++ b/contrib/groff/src/libs/libgroff/fontfile.cc
@@ -1,5 +1,6 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002
+ Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -18,13 +19,12 @@ You should have received a copy of the GNU General Public License along
with groff; see the file COPYING. If not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-#include <stdio.h>
-#include <string.h>
+#include "lib.h"
+
#include <assert.h>
#include <stdlib.h>
#include <errno.h>
#include "font.h"
-#include "lib.h"
#include "searchpath.h"
#include "device.h"
#include "defs.h"
@@ -39,6 +39,7 @@ int font::vert = 1;
int font::unitwidth = 0;
int font::paperwidth = 0;
int font::paperlength = 0;
+const char *font::papersize = 0;
int font::biggestfont = 0;
int font::spare2 = 0;
int font::sizescale = 1;
diff --git a/contrib/groff/src/libs/libgroff/geometry.cc b/contrib/groff/src/libs/libgroff/geometry.cc
new file mode 100644
index 0000000..58a94a4
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/geometry.cc
@@ -0,0 +1,286 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002
+ Free Software Foundation, Inc.
+ Written by Gaius Mulley <gaius@glam.ac.uk>
+ using adjust_arc_center() from printer.cc, written by James Clark.
+
+This file is part of groff.
+
+groff is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#include <stdio.h>
+#include <math.h>
+
+#undef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+
+#undef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+
+// This utility function adjusts the specified center of the
+// arc so that it is equidistant between the specified start
+// and end points. (p[0], p[1]) is a vector from the current
+// point to the center; (p[2], p[3]) is a vector from the
+// center to the end point. If the center can be adjusted,
+// a vector from the current point to the adjusted center is
+// stored in c[0], c[1] and 1 is returned. Otherwise 0 is
+// returned.
+
+#if 1
+int adjust_arc_center(const int *p, double *c)
+{
+ // We move the center along a line parallel to the line between
+ // the specified start point and end point so that the center
+ // is equidistant between the start and end point.
+ // It can be proved (using Lagrange multipliers) that this will
+ // give the point nearest to the specified center that is equidistant
+ // between the start and end point.
+
+ double x = p[0] + p[2]; // (x, y) is the end point
+ double y = p[1] + p[3];
+ double n = x*x + y*y;
+ if (n != 0) {
+ c[0]= double(p[0]);
+ c[1] = double(p[1]);
+ double k = .5 - (c[0]*x + c[1]*y)/n;
+ c[0] += k*x;
+ c[1] += k*y;
+ return 1;
+ }
+ else
+ return 0;
+}
+#else
+int printer::adjust_arc_center(const int *p, double *c)
+{
+ int x = p[0] + p[2]; // (x, y) is the end point
+ int y = p[1] + p[3];
+ // Start at the current point; go in the direction of the specified
+ // center point until we reach a point that is equidistant between
+ // the specified starting point and the specified end point. Place
+ // the center of the arc there.
+ double n = p[0]*double(x) + p[1]*double(y);
+ if (n > 0) {
+ double k = (double(x)*x + double(y)*y)/(2.0*n);
+ // (cx, cy) is our chosen center
+ c[0] = k*p[0];
+ c[1] = k*p[1];
+ return 1;
+ }
+ else {
+ // We would never reach such a point. So instead start at the
+ // specified end point of the arc. Go towards the specified
+ // center point until we reach a point that is equidistant between
+ // the specified start point and specified end point. Place
+ // the center of the arc there.
+ n = p[2]*double(x) + p[3]*double(y);
+ if (n > 0) {
+ double k = 1 - (double(x)*x + double(y)*y)/(2.0*n);
+ // (c[0], c[1]) is our chosen center
+ c[0] = p[0] + k*p[2];
+ c[1] = p[1] + k*p[3];
+ return 1;
+ }
+ else
+ return 0;
+ }
+}
+#endif
+
+
+/*
+ * check_output_arc_limits - works out the smallest box that will encompass
+ * an arc defined by an origin (x, y) and two
+ * vectors (p0, p1) and (p2, p3).
+ * (x1, y1) -> start of arc
+ * (x1, y1) + (xv1, yv1) -> center of circle
+ * (x1, y1) + (xv1, yv1) + (xv2, yv2) -> end of arc
+ *
+ * Works out in which quadrant the arc starts and
+ * stops, and from this it determines the x, y
+ * max/min limits. The arc is drawn clockwise.
+ *
+ * [I'm sure there is a better way to do this, but
+ * I don't know how. Please can someone let me
+ * know or "improve" this function.]
+ */
+
+void check_output_arc_limits(int x1, int y1,
+ int xv1, int yv1,
+ int xv2, int yv2,
+ double c0, double c1,
+ int *minx, int *maxx,
+ int *miny, int *maxy)
+{
+ int radius = (int)sqrt(c0*c0 + c1*c1);
+ int x2 = x1 + xv1 + xv2; // end of arc is (x2, y2)
+ int y2 = y1 + yv1 + yv2;
+
+ // firstly lets use the `circle' limitation
+ *minx = x1 + xv1 - radius;
+ *maxx = x1 + xv1 + radius;
+ *miny = y1 + yv1 - radius;
+ *maxy = y1 + yv1 + radius;
+
+ /* now to see which min/max can be reduced and increased for the limits of
+ * the arc
+ *
+ * Q2 | Q1
+ * -----+-----
+ * Q3 | Q4
+ *
+ *
+ * NB. (x1+xv1, y1+yv1) is at the origin
+ *
+ * below we ask a nested question
+ * (i) from which quadrant does the first vector start?
+ * (ii) into which quadrant does the second vector go?
+ * from the 16 possible answers we determine the limits of the arc
+ */
+ if (xv1 > 0 && yv1 > 0) {
+ // first vector in Q3
+ if (xv2 >= 0 && yv2 >= 0 ) {
+ // second in Q1
+ *maxx = x2;
+ *miny = y1;
+ }
+ else if (xv2 < 0 && yv2 >= 0) {
+ // second in Q2
+ *maxx = x2;
+ *miny = y1;
+ }
+ else if (xv2 >= 0 && yv2 < 0) {
+ // second in Q4
+ *miny = MIN(y1, y2);
+ }
+ else if (xv2 < 0 && yv2 < 0) {
+ // second in Q3
+ if (x1 >= x2) {
+ *minx = x2;
+ *maxx = x1;
+ *miny = MIN(y1, y2);
+ *maxy = MAX(y1, y2);
+ }
+ else {
+ // xv2, yv2 could all be zero?
+ }
+ }
+ }
+ else if (xv1 > 0 && yv1 < 0) {
+ // first vector in Q2
+ if (xv2 >= 0 && yv2 >= 0) {
+ // second in Q1
+ *maxx = MAX(x1, x2);
+ *minx = MIN(x1, x2);
+ *miny = y1;
+ }
+ else if (xv2 < 0 && yv2 >= 0) {
+ // second in Q2
+ if (x1 < x2) {
+ *maxx = x2;
+ *minx = x1;
+ *miny = MIN(y1, y2);
+ *maxy = MAX(y1, y2);
+ }
+ else {
+ // otherwise almost full circle anyway
+ }
+ }
+ else if (xv2 >= 0 && yv2 < 0) {
+ // second in Q4
+ *miny = y2;
+ *minx = x1;
+ }
+ else if (xv2 < 0 && yv2 < 0) {
+ // second in Q3
+ *minx = MIN(x1, x2);
+ }
+ }
+ else if (xv1 <= 0 && yv1 <= 0) {
+ // first vector in Q1
+ if (xv2 >= 0 && yv2 >= 0) {
+ // second in Q1
+ if (x1 < x2) {
+ *minx = x1;
+ *maxx = x2;
+ *miny = MIN(y1, y2);
+ *maxy = MAX(y1, y2);
+ }
+ else {
+ // nearly full circle
+ }
+ }
+ else if (xv2 < 0 && yv2 >= 0) {
+ // second in Q2
+ *maxy = MAX(y1, y2);
+ }
+ else if (xv2 >= 0 && yv2 < 0) {
+ // second in Q4
+ *miny = MIN(y1, y2);
+ *maxy = MAX(y1, y2);
+ *minx = MIN(x1, x2);
+ }
+ else if (xv2 < 0 && yv2 < 0) {
+ // second in Q3
+ *minx = x2;
+ *maxy = y1;
+ }
+ }
+ else if (xv1 <= 0 && yv1 > 0) {
+ // first vector in Q4
+ if (xv2 >= 0 && yv2 >= 0) {
+ // second in Q1
+ *maxx = MAX(x1, x2);
+ }
+ else if (xv2 < 0 && yv2 >= 0) {
+ // second in Q2
+ *maxy = MAX(y1, y2);
+ *maxx = MAX(x1, x2);
+ }
+ else if (xv2 >= 0 && yv2 < 0) {
+ // second in Q4
+ if (x1 >= x2) {
+ *miny = MIN(y1, y2);
+ *maxy = MAX(y1, y2);
+ *minx = MIN(x1, x2);
+ *maxx = MAX(x2, x2);
+ }
+ else {
+ // nearly full circle
+ }
+ }
+ else if (xv2 < 0 && yv2 < 0) {
+ // second in Q3
+ *maxy = MAX(y1, y2);
+ *minx = MIN(x1, x2);
+ *maxx = MAX(x1, x2);
+ }
+ }
+
+ // this should *never* happen but if it does it means a case above is wrong
+ // this code is only present for safety sake
+ if (*maxx < *minx) {
+ fprintf(stderr, "assert failed *minx > *maxx\n");
+ fflush(stderr);
+ *maxx = *minx;
+ }
+ if (*maxy < *miny) {
+ fprintf(stderr, "assert failed *miny > *maxy\n");
+ fflush(stderr);
+ *maxy = *miny;
+ }
+}
diff --git a/contrib/groff/src/libs/libgroff/getopt.c b/contrib/groff/src/libs/libgroff/getopt.c
index 0ecad38..289d137 100644
--- a/contrib/groff/src/libs/libgroff/getopt.c
+++ b/contrib/groff/src/libs/libgroff/getopt.c
@@ -2,24 +2,24 @@
NOTE: getopt is now part of the C library, so if you don't know what
"Keep this file name-space clean" means, talk to drepper@gnu.org
before changing it!
-
- Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000
+ Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001,2002
Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
+ Lesser General Public License for more details.
- You should have received a copy of the GNU Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
Ditto for AIX 3.2 and <stdlib.h>. */
@@ -78,7 +78,7 @@
#ifndef _
/* This is for other GNU distributions with internationalized messages. */
-# if defined HAVE_LIBINTL_H || defined _LIBC
+# if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC
# include <libintl.h>
# ifndef _
# define _(msgid) gettext (msgid)
@@ -86,6 +86,13 @@
# else
# define _(msgid) (msgid)
# endif
+# if defined _LIBC && defined USE_IN_LIBIO
+# include <wchar.h>
+# endif
+#endif
+
+#ifndef attribute_hidden
+# define attribute_hidden
#endif
/* This version of `getopt' appears to the caller like standard Unix `getopt'
@@ -131,7 +138,7 @@ int optind = 1;
causes problems with re-calling getopt as programs generally don't
know that. */
-int __getopt_initialized;
+int __getopt_initialized attribute_hidden;
/* The next char to be scanned in the option-element
in which the last option character we returned was found.
@@ -250,41 +257,34 @@ static int first_nonopt;
static int last_nonopt;
#ifdef _LIBC
+/* Stored original parameters.
+ XXX This is no good solution. We should rather copy the args so
+ that we can compare them later. But we must not use malloc(3). */
+extern int __libc_argc;
+extern char **__libc_argv;
+
/* Bash 2.0 gives us an environment variable containing flags
indicating ARGV elements that should not be considered arguments. */
+# ifdef USE_NONOPTION_FLAGS
/* Defined in getopt_init.c */
extern char *__getopt_nonoption_flags;
static int nonoption_flags_max_len;
static int nonoption_flags_len;
+# endif
-static int original_argc;
-static char *const *original_argv;
-
-/* Make sure the environment variable bash 2.0 puts in the environment
- is valid for the getopt call we must make sure that the ARGV passed
- to getopt is that one passed to the process. */
-static void
-__attribute__ ((unused))
-store_args_and_env (int argc, char *const *argv)
-{
- /* XXX This is no good solution. We should rather copy the args so
- that we can compare them later. But we must not use malloc(3). */
- original_argc = argc;
- original_argv = argv;
-}
-# ifdef text_set_element
-text_set_element (__libc_subinit, store_args_and_env);
-# endif /* text_set_element */
-
-# define SWAP_FLAGS(ch1, ch2) \
+# ifdef USE_NONOPTION_FLAGS
+# define SWAP_FLAGS(ch1, ch2) \
if (nonoption_flags_len > 0) \
{ \
char __tmp = __getopt_nonoption_flags[ch1]; \
__getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \
__getopt_nonoption_flags[ch2] = __tmp; \
}
+# else
+# define SWAP_FLAGS(ch1, ch2)
+# endif
#else /* !_LIBC */
# define SWAP_FLAGS(ch1, ch2)
#endif /* _LIBC */
@@ -316,7 +316,7 @@ exchange (argv)
It leaves the longer segment in the right place overall,
but it consists of two parts that need to be swapped next. */
-#ifdef _LIBC
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
/* First make sure the handling of the `__getopt_nonoption_flags'
string can work normally. Our top argument must be in the range
of the string. */
@@ -420,9 +420,9 @@ _getopt_initialize (argc, argv, optstring)
else
ordering = PERMUTE;
-#ifdef _LIBC
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
if (posixly_correct == NULL
- && argc == original_argc && argv == original_argv)
+ && argc == __libc_argc && argv == __libc_argv)
{
if (nonoption_flags_max_len == 0)
{
@@ -539,7 +539,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
Either it does not have option syntax, or there is an environment flag
from the shell indicating it is not an option. The later information
is only used when the used in the GNU libc. */
-#ifdef _LIBC
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \
|| (optind < nonoption_flags_len \
&& __getopt_nonoption_flags[optind] == '1'))
@@ -685,8 +685,26 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
if (ambig && !exact)
{
if (print_errors)
- fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
- argv[0], argv[optind]);
+ {
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+
+ if (__asprintf (&buf, _("%s: option `%s' is ambiguous\n"),
+ argv[0], argv[optind]) >= 0)
+ {
+
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s", buf);
+ else
+ fputs (buf, stderr);
+
+ free (buf);
+ }
+#else
+ fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
+ argv[0], argv[optind]);
+#endif
+ }
nextchar += strlen (nextchar);
optind++;
optopt = 0;
@@ -707,16 +725,50 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
{
if (print_errors)
{
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+ int n;
+#endif
+
if (argv[optind - 1][1] == '-')
- /* --option */
- fprintf (stderr,
- _("%s: option `--%s' doesn't allow an argument\n"),
- argv[0], pfound->name);
+ {
+ /* --option */
+#if defined _LIBC && defined USE_IN_LIBIO
+ n = __asprintf (&buf, _("\
+%s: option `--%s' doesn't allow an argument\n"),
+ argv[0], pfound->name);
+#else
+ fprintf (stderr, _("\
+%s: option `--%s' doesn't allow an argument\n"),
+ argv[0], pfound->name);
+#endif
+ }
else
- /* +option or -option */
- fprintf (stderr,
- _("%s: option `%c%s' doesn't allow an argument\n"),
- argv[0], argv[optind - 1][0], pfound->name);
+ {
+ /* +option or -option */
+#if defined _LIBC && defined USE_IN_LIBIO
+ n = __asprintf (&buf, _("\
+%s: option `%c%s' doesn't allow an argument\n"),
+ argv[0], argv[optind - 1][0],
+ pfound->name);
+#else
+ fprintf (stderr, _("\
+%s: option `%c%s' doesn't allow an argument\n"),
+ argv[0], argv[optind - 1][0], pfound->name);
+#endif
+ }
+
+#if defined _LIBC && defined USE_IN_LIBIO
+ if (n >= 0)
+ {
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s", buf);
+ else
+ fputs (buf, stderr);
+
+ free (buf);
+ }
+#endif
}
nextchar += strlen (nextchar);
@@ -732,9 +784,27 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
else
{
if (print_errors)
- fprintf (stderr,
- _("%s: option `%s' requires an argument\n"),
- argv[0], argv[optind - 1]);
+ {
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+
+ if (__asprintf (&buf, _("\
+%s: option `%s' requires an argument\n"),
+ argv[0], argv[optind - 1]) >= 0)
+ {
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s", buf);
+ else
+ fputs (buf, stderr);
+
+ free (buf);
+ }
+#else
+ fprintf (stderr,
+ _("%s: option `%s' requires an argument\n"),
+ argv[0], argv[optind - 1]);
+#endif
+ }
nextchar += strlen (nextchar);
optopt = pfound->val;
return optstring[0] == ':' ? ':' : '?';
@@ -760,14 +830,45 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
{
if (print_errors)
{
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+ int n;
+#endif
+
if (argv[optind][1] == '-')
- /* --option */
- fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
- argv[0], nextchar);
+ {
+ /* --option */
+#if defined _LIBC && defined USE_IN_LIBIO
+ n = __asprintf (&buf, _("%s: unrecognized option `--%s'\n"),
+ argv[0], nextchar);
+#else
+ fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
+ argv[0], nextchar);
+#endif
+ }
else
- /* +option or -option */
- fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
- argv[0], argv[optind][0], nextchar);
+ {
+ /* +option or -option */
+#if defined _LIBC && defined USE_IN_LIBIO
+ n = __asprintf (&buf, _("%s: unrecognized option `%c%s'\n"),
+ argv[0], argv[optind][0], nextchar);
+#else
+ fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
+ argv[0], argv[optind][0], nextchar);
+#endif
+ }
+
+#if defined _LIBC && defined USE_IN_LIBIO
+ if (n >= 0)
+ {
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s", buf);
+ else
+ fputs (buf, stderr);
+
+ free (buf);
+ }
+#endif
}
nextchar = (char *) "";
optind++;
@@ -790,13 +891,42 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
{
if (print_errors)
{
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+ int n;
+#endif
+
if (posixly_correct)
- /* 1003.2 specifies the format of this message. */
- fprintf (stderr, _("%s: illegal option -- %c\n"),
- argv[0], c);
+ {
+ /* 1003.2 specifies the format of this message. */
+#if defined _LIBC && defined USE_IN_LIBIO
+ n = __asprintf (&buf, _("%s: illegal option -- %c\n"),
+ argv[0], c);
+#else
+ fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c);
+#endif
+ }
else
- fprintf (stderr, _("%s: invalid option -- %c\n"),
- argv[0], c);
+ {
+#if defined _LIBC && defined USE_IN_LIBIO
+ n = __asprintf (&buf, _("%s: invalid option -- %c\n"),
+ argv[0], c);
+#else
+ fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c);
+#endif
+ }
+
+#if defined _LIBC && defined USE_IN_LIBIO
+ if (n >= 0)
+ {
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s", buf);
+ else
+ fputs (buf, stderr);
+
+ free (buf);
+ }
+#endif
}
optopt = c;
return '?';
@@ -825,8 +955,24 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
if (print_errors)
{
/* 1003.2 specifies the format of this message. */
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+
+ if (__asprintf (&buf,
+ _("%s: option requires an argument -- %c\n"),
+ argv[0], c) >= 0)
+ {
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s", buf);
+ else
+ fputs (buf, stderr);
+
+ free (buf);
+ }
+#else
fprintf (stderr, _("%s: option requires an argument -- %c\n"),
argv[0], c);
+#endif
}
optopt = c;
if (optstring[0] == ':')
@@ -872,8 +1018,25 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
if (ambig && !exact)
{
if (print_errors)
- fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
- argv[0], argv[optind]);
+ {
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+
+ if (__asprintf (&buf, _("%s: option `-W %s' is ambiguous\n"),
+ argv[0], argv[optind]) >= 0)
+ {
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s", buf);
+ else
+ fputs (buf, stderr);
+
+ free (buf);
+ }
+#else
+ fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
+ argv[0], argv[optind]);
+#endif
+ }
nextchar += strlen (nextchar);
optind++;
return '?';
@@ -890,9 +1053,27 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
else
{
if (print_errors)
- fprintf (stderr, _("\
+ {
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+
+ if (__asprintf (&buf, _("\
+%s: option `-W %s' doesn't allow an argument\n"),
+ argv[0], pfound->name) >= 0)
+ {
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s", buf);
+ else
+ fputs (buf, stderr);
+
+ free (buf);
+ }
+#else
+ fprintf (stderr, _("\
%s: option `-W %s' doesn't allow an argument\n"),
- argv[0], pfound->name);
+ argv[0], pfound->name);
+#endif
+ }
nextchar += strlen (nextchar);
return '?';
@@ -905,9 +1086,27 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
else
{
if (print_errors)
- fprintf (stderr,
- _("%s: option `%s' requires an argument\n"),
- argv[0], argv[optind - 1]);
+ {
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+
+ if (__asprintf (&buf, _("\
+%s: option `%s' requires an argument\n"),
+ argv[0], argv[optind - 1]) >= 0)
+ {
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s", buf);
+ else
+ fputs (buf, stderr);
+
+ free (buf);
+ }
+#else
+ fprintf (stderr,
+ _("%s: option `%s' requires an argument\n"),
+ argv[0], argv[optind - 1]);
+#endif
+ }
nextchar += strlen (nextchar);
return optstring[0] == ':' ? ':' : '?';
}
@@ -954,9 +1153,25 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
if (print_errors)
{
/* 1003.2 specifies the format of this message. */
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+
+ if (__asprintf (&buf, _("\
+%s: option requires an argument -- %c\n"),
+ argv[0], c) >= 0)
+ {
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s", buf);
+ else
+ fputs (buf, stderr);
+
+ free (buf);
+ }
+#else
fprintf (stderr,
_("%s: option requires an argument -- %c\n"),
argv[0], c);
+#endif
}
optopt = c;
if (optstring[0] == ':')
diff --git a/contrib/groff/src/libs/libgroff/getopt1.c b/contrib/groff/src/libs/libgroff/getopt1.c
index 3d264f2..22a7efb 100644
--- a/contrib/groff/src/libs/libgroff/getopt1.c
+++ b/contrib/groff/src/libs/libgroff/getopt1.c
@@ -4,19 +4,19 @@
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
+ Lesser General Public License for more details.
- You should have received a copy of the GNU Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
#ifdef HAVE_CONFIG_H
#include <config.h>
diff --git a/contrib/groff/src/libs/libgroff/htmlhint.cc b/contrib/groff/src/libs/libgroff/htmlhint.cc
new file mode 100644
index 0000000..3015767
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/htmlhint.cc
@@ -0,0 +1,59 @@
+/* Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+ Written by Gaius Mulley (gaius@glam.ac.uk)
+
+This file is part of groff.
+
+groff is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "lib.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#include "nonposix.h"
+#include "stringclass.h"
+#include "html-strings.h"
+
+/*
+ * This file contains a very simple set of routines which might
+ * be shared by preprocessors. It allows a preprocessor to indicate
+ * when an inline image should be created.
+ * This string is intercepted by pre-grohtml and substituted for
+ * the image name and suppression escapes.
+ *
+ * pre-html runs troff twice, once with -Thtml and once with -Tps.
+ * troff -Thtml device driver emits a <src='image'.png> tag
+ * and the postscript device driver works out the min/max limits
+ * of the graphic region. These region limits are read by pre-html
+ * and an image is generated via troff -Tps -> gs -> png
+ */
+
+/*
+ * html_begin_suppress - emit a start of image tag which will be seen
+ * by pre-html.
+ */
+void html_begin_suppress()
+{
+ put_string(HTML_IMAGE_INLINE_BEGIN, stdout);
+}
+
+/*
+ * html_end_suppress - emit an end of image tag which will be seen
+ * by pre-html.
+ */
+void html_end_suppress()
+{
+ put_string(HTML_IMAGE_INLINE_END, stdout);
+}
diff --git a/contrib/groff/src/libs/libgroff/invalid.cc b/contrib/groff/src/libs/libgroff/invalid.cc
new file mode 100644
index 0000000..f36894a
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/invalid.cc
@@ -0,0 +1,60 @@
+/* Copyright (C) 2000, 2002 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "lib.h"
+
+// Table of invalid input characters.
+
+char invalid_char_table[256]= {
+#ifndef IS_EBCDIC_HOST
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+#else
+ 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1,
+ 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+#endif
+};
diff --git a/contrib/groff/src/libs/libgroff/itoa.c b/contrib/groff/src/libs/libgroff/itoa.c
index 72826b7..245c7df 100644
--- a/contrib/groff/src/libs/libgroff/itoa.c
+++ b/contrib/groff/src/libs/libgroff/itoa.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2002
+ Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -18,6 +19,7 @@ with groff; see the file COPYING. If not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#define INT_DIGITS 19 /* enough for 64 bit integer */
+#define UINT_DIGITS 20
char *i_to_a(i)
int i;
@@ -41,3 +43,16 @@ char *i_to_a(i)
}
return p;
}
+
+char *ui_to_a(i)
+ unsigned int i;
+{
+ /* Room for UINT_DIGITS digits and '\0' */
+ static char buf[UINT_DIGITS + 1];
+ char *p = buf + UINT_DIGITS; /* points to terminating '\0' */
+ do {
+ *--p = '0' + (i % 10);
+ i /= 10;
+ } while (i != 0);
+ return p;
+}
diff --git a/contrib/groff/src/libs/libgroff/matherr.c b/contrib/groff/src/libs/libgroff/matherr.c
index b0097b8..757a540 100644
--- a/contrib/groff/src/libs/libgroff/matherr.c
+++ b/contrib/groff/src/libs/libgroff/matherr.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2001 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -17,6 +17,10 @@ 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. */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <math.h>
#include <errno.h>
diff --git a/contrib/groff/src/libs/libgroff/maxfilename.cc b/contrib/groff/src/libs/libgroff/maxfilename.cc
index c5a03d7..341cf92 100644
--- a/contrib/groff/src/libs/libgroff/maxfilename.cc
+++ b/contrib/groff/src/libs/libgroff/maxfilename.cc
@@ -20,6 +20,8 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* file_name_max(dir) does the same as pathconf(dir, _PC_NAME_MAX) */
+#include "lib.h"
+
#include <sys/types.h>
#ifdef HAVE_UNISTD_H
diff --git a/contrib/groff/src/libs/libgroff/mksdir.cc b/contrib/groff/src/libs/libgroff/mksdir.cc
new file mode 100644
index 0000000..bf4d300
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/mksdir.cc
@@ -0,0 +1,34 @@
+/* Copyright (C) 2001 Free Software Foundation, Inc.
+ Written by Werner Lemberg (wl@gnu.org)
+
+This file is part of groff.
+
+groff is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+/* This file is heavily based on the file mkstemp.c which is part of the
+ fileutils package. */
+
+
+extern int gen_tempname(char *, int = 0);
+
+/* Generate a unique temporary directory name from TEMPLATE.
+ The last six characters of TEMPLATE must be "XXXXXX";
+ they are replaced with a string that makes the filename unique.
+ Then open the directory and return a fd. */
+int mksdir(char *tmpl)
+{
+ return gen_tempname(tmpl, 1);
+}
diff --git a/contrib/groff/src/libs/libgroff/mkstemp.cc b/contrib/groff/src/libs/libgroff/mkstemp.cc
new file mode 100644
index 0000000..cd2717c
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/mkstemp.cc
@@ -0,0 +1,34 @@
+/* Copyright (C) 2001 Free Software Foundation, Inc.
+ Written by Werner Lemberg (wl@gnu.org)
+
+This file is part of groff.
+
+groff is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+/* This file is heavily based on the file mkstemp.c which is part of the
+ fileutils package. */
+
+
+extern int gen_tempname(char *, int);
+
+/* Generate a unique temporary file name from TEMPLATE.
+ The last six characters of TEMPLATE must be "XXXXXX";
+ they are replaced with a string that makes the filename unique.
+ Then open the file and return a fd. */
+int mkstemp(char *tmpl)
+{
+ return gen_tempname(tmpl, 0);
+}
diff --git a/contrib/groff/src/libs/libgroff/nametoindex.cc b/contrib/groff/src/libs/libgroff/nametoindex.cc
index 578ff34..7c94b25 100644
--- a/contrib/groff/src/libs/libgroff/nametoindex.cc
+++ b/contrib/groff/src/libs/libgroff/nametoindex.cc
@@ -1,5 +1,6 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002
+ Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -18,12 +19,11 @@ You should have received a copy of the GNU General Public License along
with groff; see the file COPYING. If not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-#include <stdio.h>
-#include <string.h>
+#include "lib.h"
+
#include <ctype.h>
#include <assert.h>
#include <stdlib.h>
-#include "lib.h"
#include "errarg.h"
#include "error.h"
#include "font.h"
@@ -45,7 +45,6 @@ private:
int ascii_index[256];
int small_number_index[NSMALL];
PTABLE(int) table;
- int lookup_char(const char *, int);
};
character_indexer::character_indexer()
diff --git a/contrib/groff/src/libs/libgroff/new.cc b/contrib/groff/src/libs/libgroff/new.cc
index 8d98591..4975149 100644
--- a/contrib/groff/src/libs/libgroff/new.cc
+++ b/contrib/groff/src/libs/libgroff/new.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2001 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -17,9 +17,10 @@ You should have received a copy of the GNU General Public License along
with groff; see the file COPYING. If not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+#include "lib.h"
+
#include <stddef.h>
#include <stdlib.h>
-#include <string.h>
#include "posix.h"
#include "nonposix.h"
diff --git a/contrib/groff/src/libs/libgroff/paper.cc b/contrib/groff/src/libs/libgroff/paper.cc
new file mode 100644
index 0000000..d79733e
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/paper.cc
@@ -0,0 +1,84 @@
+// -*- C++ -*-
+/* Copyright (C) 2002
+ Free Software Foundation, Inc.
+ Written by Werner Lemberg (wl@gnu.org)
+
+This file is part of groff.
+
+groff is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "lib.h"
+#include "paper.h"
+
+paper papersizes[NUM_PAPERSIZES];
+
+// length and width in mm
+static void add_iso_paper(char series, int offset,
+ int start_length, int start_width)
+{
+ int length = start_length;
+ int width = start_width;
+ for (int i = 0; i < 8; i++)
+ {
+ char *p = new char[3];
+ p[0] = series;
+ p[1] = '0' + i;
+ p[2] = '\0';
+ papersizes[offset + i].name = p;
+ // convert mm to inch
+ papersizes[offset + i].length = (double)length / 25.4;
+ papersizes[offset + i].width = (double)width / 25.4;
+ // after division by two, values must be rounded down to the next
+ // integer (as specified by ISO)
+ int tmp = width;
+ width = length;
+ length = tmp / 2;
+ }
+}
+
+// length and width in inch
+static void add_american_paper(const char *name, int index,
+ double length, double width )
+{
+ char *p = new char[strlen(name) + 1];
+ strcpy(p, name);
+ papersizes[index].name = p;
+ papersizes[index].length = length;
+ papersizes[index].width = width;
+}
+
+int papersize_init::initialised = 0;
+
+papersize_init::papersize_init()
+{
+ if (initialised)
+ return;
+ initialised = 1;
+ add_iso_paper('a', 0, 1189, 841);
+ add_iso_paper('b', 8, 1414, 1000);
+ add_iso_paper('c', 16, 1297, 917);
+ add_iso_paper('d', 24, 1090, 771);
+ add_american_paper("letter", 32, 11, 8.5);
+ add_american_paper("legal", 33, 14, 8.5);
+ add_american_paper("tabloid", 34, 17, 11);
+ add_american_paper("ledger", 35, 11, 17);
+ add_american_paper("statement", 36, 8.5, 5.5);
+ add_american_paper("executive", 37, 10, 7.5);
+ // the next three entries are for grolj4
+ add_american_paper("com10", 38, 9.5, 4.125);
+ add_american_paper("monarch", 39, 7.5, 3.875);
+ // this is an ISO format, but it easier to use add_american_paper
+ add_american_paper("dl", 40, 220/25.4, 110/25.4);
+}
diff --git a/contrib/groff/src/libs/libgroff/putenv.c b/contrib/groff/src/libs/libgroff/putenv.c
index c1ca671..2091f3b 100644
--- a/contrib/groff/src/libs/libgroff/putenv.c
+++ b/contrib/groff/src/libs/libgroff/putenv.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -18,6 +18,10 @@ Cambridge, MA 02139, USA. */
/* Hacked slightly by jjc@jclark.com for groff. */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <string.h>
#ifdef __STDC__
diff --git a/contrib/groff/src/libs/libgroff/searchpath.cc b/contrib/groff/src/libs/libgroff/searchpath.cc
index f4e2b90..1f8b233 100644
--- a/contrib/groff/src/libs/libgroff/searchpath.cc
+++ b/contrib/groff/src/libs/libgroff/searchpath.cc
@@ -1,5 +1,6 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+ Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -18,12 +19,11 @@ You should have received a copy of the GNU General Public License along
with groff; see the file COPYING. If not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-#include <stdio.h>
-#include <string.h>
+#include "lib.h"
+
#include <stdlib.h>
#include <assert.h>
-#include "lib.h"
#include "searchpath.h"
#include "nonposix.h"
diff --git a/contrib/groff/src/libs/libgroff/strerror.c b/contrib/groff/src/libs/libgroff/strerror.c
index 69089f1..be2d1f3 100644
--- a/contrib/groff/src/libs/libgroff/strerror.c
+++ b/contrib/groff/src/libs/libgroff/strerror.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2001 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -17,6 +17,10 @@ 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. */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <stdio.h>
#define INT_DIGITS 19 /* enough for 64 bit integer */
diff --git a/contrib/groff/src/libs/libgroff/string.cc b/contrib/groff/src/libs/libgroff/string.cc
index 4bcd4cc..2ef547e 100644
--- a/contrib/groff/src/libs/libgroff/string.cc
+++ b/contrib/groff/src/libs/libgroff/string.cc
@@ -1,5 +1,6 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002
+ Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -18,10 +19,10 @@ You should have received a copy of the GNU General Public License along
with groff; see the file COPYING. If not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-#include <stdio.h>
-#include "stringclass.h"
#include "lib.h"
+#include "stringclass.h"
+
static char *salloc(int len, int *sizep);
static void sfree(char *ptr, int size);
static char *sfree_alloc(char *ptr, int size, int len, int *sizep);
@@ -290,10 +291,39 @@ char *string::extract() const
for (i = 0; i < n; i++)
if (p[i] != '\0')
*r++ = p[i];
- q[n] = '\0';
+ *r = '\0';
return q;
}
+void string::remove_spaces()
+{
+ int l = len - 1;
+ while (l >= 0 && ptr[l] == ' ')
+ l--;
+ char *p = ptr;
+ if (l > 0)
+ while (*p == ' ') {
+ p++;
+ l--;
+ }
+ if (len - 1 != l) {
+ if (l >= 0) {
+ len = l + 1;
+ char *tmp = new char[len];
+ memcpy(tmp, p, len);
+ a_delete ptr;
+ ptr = tmp;
+ }
+ else {
+ len = 0;
+ if (ptr) {
+ a_delete ptr;
+ ptr = 0;
+ }
+ }
+ }
+}
+
void put_string(const string &s, FILE *fp)
{
int len = s.length();
diff --git a/contrib/groff/src/libs/libgroff/strtol.c b/contrib/groff/src/libs/libgroff/strtol.c
index 61ce70e..46b1702 100644
--- a/contrib/groff/src/libs/libgroff/strtol.c
+++ b/contrib/groff/src/libs/libgroff/strtol.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+ Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -17,6 +18,10 @@ 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. */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <string.h>
#include <ctype.h>
#include <errno.h>
diff --git a/contrib/groff/src/libs/libgroff/tmpfile.cc b/contrib/groff/src/libs/libgroff/tmpfile.cc
index 8508c59..41b7f06 100644
--- a/contrib/groff/src/libs/libgroff/tmpfile.cc
+++ b/contrib/groff/src/libs/libgroff/tmpfile.cc
@@ -19,23 +19,16 @@ You should have received a copy of the GNU General Public License along
with groff; see the file COPYING. If not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-#include <stdio.h>
+#include "lib.h"
+
#include <errno.h>
-#include <string.h>
#include <stdlib.h>
#include "posix.h"
-#include "lib.h"
#include "errarg.h"
#include "error.h"
#include "nonposix.h"
-#ifndef HAVE_MKSTEMP_PROTO
-extern "C" {
- extern int mkstemp (char *);
-}
-#endif
-
// If this is set, create temporary files there
#define GROFF_TMPDIR_ENVVAR "GROFF_TMPDIR"
// otherwise if this is set, create temporary files there
@@ -48,11 +41,49 @@ extern "C" {
# define DEFAULT_TMPDIR "/tmp"
#endif
// Use this as the prefix for temporary filenames.
-#ifdef __MSDOS__
-#define TMPFILE_PREFIX ""
-#else
-#define TMPFILE_PREFIX "groff"
-#endif
+#define TMPFILE_PREFIX_SHORT ""
+#define TMPFILE_PREFIX_LONG "groff"
+
+char *tmpfile_prefix;
+size_t tmpfile_prefix_len;
+int use_short_postfix = 0;
+
+struct temp_init {
+ temp_init();
+ ~temp_init();
+} _temp_init;
+
+temp_init::temp_init()
+{
+ const char *tem = getenv(GROFF_TMPDIR_ENVVAR);
+ if (!tem) {
+ tem = getenv(TMPDIR_ENVVAR);
+ if (!tem)
+ tem = DEFAULT_TMPDIR;
+ }
+ size_t tem_len = strlen(tem);
+ const char *tem_end = tem + tem_len - 1;
+ int need_slash = strchr(DIR_SEPS, *tem_end) == NULL ? 1 : 0;
+ char *tem2 = new char[tem_len + need_slash + 1];
+ strcpy(tem2, tem);
+ if (need_slash)
+ strcat(tem2, "/");
+ const char *tem3 = TMPFILE_PREFIX_LONG;
+ if (file_name_max(tem2) <= 14) {
+ tem3 = TMPFILE_PREFIX_SHORT;
+ use_short_postfix = 1;
+ }
+ tmpfile_prefix_len = tem_len + need_slash + strlen(tem3);
+ tmpfile_prefix = new char[tmpfile_prefix_len + 1];
+ strcpy(tmpfile_prefix, tem2);
+ strcat(tmpfile_prefix, tem3);
+ a_delete tem2;
+}
+
+temp_init::~temp_init()
+{
+ a_delete tmpfile_prefix;
+}
/*
* Generate a temporary name template with a postfix
@@ -62,85 +93,67 @@ extern "C" {
* only the *template* is returned.
*/
-char *xtmptemplate(char *postfix)
+char *xtmptemplate(const char *postfix_long, const char *postfix_short)
{
- const char *dir = getenv(GROFF_TMPDIR_ENVVAR);
+ const char *postfix = use_short_postfix ? postfix_short : postfix_long;
int postlen = 0;
-
if (postfix)
postlen = strlen(postfix);
-
- if (!dir) {
- dir = getenv(TMPDIR_ENVVAR);
- if (!dir)
- dir = DEFAULT_TMPDIR;
- }
-
- size_t dir_len = strlen(dir);
- const char *dir_end = dir + dir_len - 1;
- int needs_slash = strchr(DIR_SEPS, *dir_end) == NULL;
- char *templ = new char[strlen(dir) + needs_slash
- + sizeof(TMPFILE_PREFIX) - 1 + 6 + 1 + postlen];
- strcpy(templ, dir);
- if (needs_slash)
- strcat(templ, "/");
- strcat(templ, TMPFILE_PREFIX);
+ char *templ = new char[tmpfile_prefix_len + postlen + 6 + 1];
+ strcpy(templ, tmpfile_prefix);
if (postlen > 0)
strcat(templ, postfix);
strcat(templ, "XXXXXX");
-
- return( templ );
+ return templ;
}
// The trick with unlinking the temporary file while it is still in
// use is not portable, it will fail on MS-DOS and most MS-Windows
// filesystems. So it cannot be used on non-Posix systems.
-// Instead, we maintain a list of files to be deleted on exit, and
-// register an atexit function that will remove them all in one go.
+// Instead, we maintain a list of files to be deleted on exit.
// This should be portable to all platforms.
-static struct xtmpfile_list {
- struct xtmpfile_list *next;
- char fname[1];
-} *xtmpfiles_to_delete;
+struct xtmpfile_list {
+ char *fname;
+ xtmpfile_list *next;
+ xtmpfile_list(char *fn) : fname(fn), next(0) {}
+};
+
+xtmpfile_list *xtmpfiles_to_delete = 0;
-static void remove_tmp_files()
+struct xtmpfile_list_init {
+ ~xtmpfile_list_init();
+} _xtmpfile_list_init;
+
+xtmpfile_list_init::~xtmpfile_list_init()
{
- struct xtmpfile_list *p = xtmpfiles_to_delete;
-
- while (p) {
- if (unlink(p->fname) < 0)
- error("cannot unlink `%1': %2", p->fname, strerror(errno));
- struct xtmpfile_list *old = p;
- p = p->next;
- free(old);
+ xtmpfile_list *x = xtmpfiles_to_delete;
+ while (x != 0) {
+ if (unlink(x->fname) < 0)
+ error("cannot unlink `%1': %2", x->fname, strerror(errno));
+ xtmpfile_list *tmp = x;
+ x = x->next;
+ a_delete tmp->fname;
+ delete tmp;
}
}
static void add_tmp_file(const char *name)
{
- if (xtmpfiles_to_delete == NULL)
- atexit(remove_tmp_files);
-
- struct xtmpfile_list *p
- = (struct xtmpfile_list *)malloc(sizeof(struct xtmpfile_list)
- + strlen (name));
- if (p == NULL) {
- error("cannot unlink `%1': %2", name, strerror(errno));
- return;
- }
- p->next = xtmpfiles_to_delete;
- strcpy(p->fname, name);
- xtmpfiles_to_delete = p;
+ char *s = new char[strlen(name)+1];
+ strcpy(s, name);
+ xtmpfile_list *x = new xtmpfile_list(s);
+ x->next = xtmpfiles_to_delete;
+ xtmpfiles_to_delete = x;
}
// Open a temporary file and with fatal error on failure.
-FILE *xtmpfile(char **namep, char *postfix, int do_unlink)
+FILE *xtmpfile(char **namep,
+ const char *postfix_long, const char *postfix_short,
+ int do_unlink)
{
- char *templ = xtmptemplate(postfix);
-
-#ifdef HAVE_MKSTEMP
+ char *templ = xtmptemplate(postfix_long, postfix_short);
errno = 0;
int fd = mkstemp(templ);
if (fd < 0)
@@ -149,17 +162,9 @@ FILE *xtmpfile(char **namep, char *postfix, int do_unlink)
FILE *fp = fdopen(fd, FOPEN_RWB); // many callers of xtmpfile use binary I/O
if (!fp)
fatal("fdopen: %1", strerror(errno));
-#else /* not HAVE_MKSTEMP */
- if (!mktemp(templ) || !templ[0])
- fatal("cannot create file name for temporary file");
- errno = 0;
- FILE *fp = fopen(templ, FOPEN_RWB);
- if (!fp)
- fatal("cannot open `%1': %2", templ, strerror(errno));
-#endif /* not HAVE_MKSTEMP */
if (do_unlink)
add_tmp_file(templ);
- if ((namep != 0) && ((*namep) != 0))
+ if (namep)
*namep = templ;
else
a_delete templ;
diff --git a/contrib/groff/src/libs/libgroff/tmpname.cc b/contrib/groff/src/libs/libgroff/tmpname.cc
new file mode 100644
index 0000000..213b0ee
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/tmpname.cc
@@ -0,0 +1,116 @@
+/* Copyright (C) 2001 Free Software Foundation, Inc.
+ Written by Werner Lemberg (wl@gnu.org)
+
+This file is part of groff.
+
+groff is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+/* This file is heavily based on the function __gen_tempname() in the
+ file tempname.c which is part of the fileutils package. */
+
+
+#include "lib.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <time.h>
+
+#include "posix.h"
+#include "nonposix.h"
+
+#ifndef TMP_MAX
+# define TMP_MAX 238328
+#endif
+
+#if HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+
+#ifdef HAVE_GETTIMEOFDAY
+#ifdef NEED_DECLARATION_GETTIMEOFDAY
+extern "C" {
+ int gettimeofday(struct timeval *, void *);
+}
+#endif
+#endif
+
+#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+
+/* Use the widest available unsigned type if uint64_t is not
+ available. The algorithm below extracts a number less than 62**6
+ (approximately 2**35.725) from uint64_t, so ancient hosts where
+ uintmax_t is only 32 bits lose about 3.725 bits of randomness,
+ which is better than not having mkstemp at all. */
+#if !defined UINT64_MAX && !defined uint64_t
+# define uint64_t uintmax_t
+#endif
+
+/* These are the characters used in temporary filenames. */
+static const char letters[] =
+"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+
+int gen_tempname(char *tmpl, int dir)
+{
+ static uint64_t value;
+
+ size_t len = strlen(tmpl);
+ if (len < 6 || strcmp(&tmpl[len - 6], "XXXXXX"))
+ return -1; /* EINVAL */
+
+ /* This is where the Xs start. */
+ char *XXXXXX = &tmpl[len - 6];
+
+ /* Get some more or less random data. */
+#if HAVE_GETTIMEOFDAY
+ timeval tv;
+ gettimeofday(&tv, NULL);
+ uint64_t random_time_bits = ((uint64_t)tv.tv_usec << 16) ^ tv.tv_sec;
+#else
+ uint64_t random_time_bits = time(NULL);
+#endif
+ value += random_time_bits ^ getpid();
+
+ for (int count = 0; count < TMP_MAX; value += 7777, ++count) {
+ uint64_t v = value;
+
+ /* Fill in the random bits. */
+ XXXXXX[0] = letters[v % 62];
+ v /= 62;
+ XXXXXX[1] = letters[v % 62];
+ v /= 62;
+ XXXXXX[2] = letters[v % 62];
+ v /= 62;
+ XXXXXX[3] = letters[v % 62];
+ v /= 62;
+ XXXXXX[4] = letters[v % 62];
+ v /= 62;
+ XXXXXX[5] = letters[v % 62];
+
+ int fd = dir ? mkdir(tmpl, S_IRUSR | S_IWUSR | S_IXUSR)
+ : open(tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
+
+ if (fd >= 0)
+ return fd;
+ else if (errno != EEXIST)
+ return -1;
+ }
+
+ /* We got out of the loop because we ran out of combinations to try. */
+ return -1; /* EEXIST */
+}
OpenPOWER on IntegriCloud