2006-01-05 14:49:14 +00:00
|
|
|
--- groff-1.18/src/roff/troff/Makefile.sub.hugo 2002-05-03 00:33:21.000000000 +0200
|
|
|
|
+++ groff-1.18/src/roff/troff/Makefile.sub 2002-11-04 21:30:09.000000000 +0100
|
2004-09-09 05:54:44 +00:00
|
|
|
@@ -1,6 +1,6 @@
|
|
|
|
PROG=troff$(EXEEXT)
|
|
|
|
MAN1=troff.n
|
|
|
|
-XLIBS=$(LIBGROFF)
|
|
|
|
+XLIBS=-lz $(LIBGROFF)
|
|
|
|
MLIB=$(LIBM)
|
|
|
|
OBJS=\
|
2006-01-05 14:49:14 +00:00
|
|
|
env.o \
|
|
|
|
--- groff-1.18/src/roff/troff/input.cc.hugo 2002-11-04 21:30:09.000000000 +0100
|
|
|
|
+++ groff-1.18/src/roff/troff/input.cc 2002-11-04 21:36:13.000000000 +0100
|
|
|
|
@@ -42,6 +42,8 @@
|
2004-09-09 05:54:44 +00:00
|
|
|
|
|
|
|
#include "nonposix.h"
|
|
|
|
|
|
|
|
+#include <zlib.h>
|
|
|
|
+
|
|
|
|
#ifdef NEED_DECLARATION_PUTENV
|
|
|
|
extern "C" {
|
|
|
|
int putenv(const char *);
|
2006-01-05 14:49:14 +00:00
|
|
|
@@ -217,6 +219,130 @@
|
2004-09-09 05:54:44 +00:00
|
|
|
skip_line();
|
|
|
|
}
|
|
|
|
|
|
|
|
+enum opq_fp_zmode { OPQ_FP_STDIO, OPQ_FP_ZLIB, OPQ_FP_GUESS };
|
|
|
|
+
|
|
|
|
+class opaque_fp {
|
|
|
|
+ private:
|
|
|
|
+ FILE * stdio_fp;
|
|
|
|
+ gzFile zlib_fp;
|
|
|
|
+ int is_zipped;
|
|
|
|
+ // We need this because zlib has no ungetc.
|
|
|
|
+ int char_pending;
|
|
|
|
+ char saved_char;
|
|
|
|
+ int popened;
|
|
|
|
+ public:
|
|
|
|
+ opaque_fp(const char *,
|
|
|
|
+ const char *,
|
|
|
|
+ enum opq_fp_zmode = OPQ_FP_STDIO);
|
|
|
|
+ opaque_fp(FILE *, int = 0);
|
|
|
|
+ ~opaque_fp();
|
|
|
|
+ int active();
|
|
|
|
+ int xgetc();
|
|
|
|
+ int unxgetc(int);
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+int opaque_fp::active()
|
|
|
|
+{
|
|
|
|
+ if (is_zipped) {
|
|
|
|
+ return zlib_fp!=NULL;
|
|
|
|
+ } else {
|
|
|
|
+ return stdio_fp!=NULL;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// This constructor is guaranteed to set is_zipped to 0 or 1, and set the
|
|
|
|
+// corresponding fp to something non-rubbish.
|
|
|
|
+opaque_fp::opaque_fp(const char * fn, const char * mode, enum opq_fp_zmode z)
|
|
|
|
+{
|
|
|
|
+ switch (z) {
|
|
|
|
+ case OPQ_FP_STDIO :
|
|
|
|
+ stdio_fp=fopen(fn,mode);
|
|
|
|
+ is_zipped=0;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case OPQ_FP_ZLIB :
|
|
|
|
+ zlib_fp=gzopen(fn,mode);
|
|
|
|
+ is_zipped=1;
|
|
|
|
+ char_pending=0;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case OPQ_FP_GUESS :
|
|
|
|
+ stdio_fp=fopen(fn,mode);
|
|
|
|
+ is_zipped=0;
|
|
|
|
+ if (active()) {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Yes, I'm a C addict
|
|
|
|
+ char * s;
|
|
|
|
+ s=(char*)malloc(strlen(fn)+4);
|
|
|
|
+ sprintf(s,"%s.gz",fn);
|
|
|
|
+ zlib_fp=gzopen(s,mode);
|
|
|
|
+ char_pending=0;
|
|
|
|
+ is_zipped=1;
|
|
|
|
+ free(s);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+opaque_fp::opaque_fp(FILE *fp, int p)
|
|
|
|
+{
|
|
|
|
+ stdio_fp=fp;
|
|
|
|
+ is_zipped=0;
|
|
|
|
+ popened=p;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+opaque_fp::~opaque_fp()
|
|
|
|
+{
|
|
|
|
+ if (is_zipped) {
|
|
|
|
+ if (zlib_fp!=NULL) {
|
|
|
|
+ gzclose(zlib_fp);
|
|
|
|
+ zlib_fp=NULL;
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ if (stdio_fp!=NULL) {
|
|
|
|
+ if (popened) {
|
|
|
|
+ pclose(stdio_fp);
|
|
|
|
+ } else if (stdio_fp!=stdin) {
|
|
|
|
+ fclose(stdio_fp);
|
|
|
|
+ } else {
|
|
|
|
+ clearerr(stdin);
|
|
|
|
+ }
|
|
|
|
+ stdio_fp=NULL;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// These routines must be called only if active() is true
|
|
|
|
+int opaque_fp::xgetc()
|
|
|
|
+{
|
|
|
|
+ if (is_zipped) {
|
|
|
|
+ if (char_pending) {
|
|
|
|
+ char_pending--;
|
|
|
|
+ return saved_char;
|
|
|
|
+ } else {
|
|
|
|
+ return gzgetc(zlib_fp);
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ return getc(stdio_fp);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int opaque_fp::unxgetc(int c)
|
|
|
|
+{
|
|
|
|
+ if (is_zipped) {
|
|
|
|
+ if (char_pending) {
|
|
|
|
+ return EOF;
|
|
|
|
+ } else {
|
|
|
|
+ char_pending++;
|
|
|
|
+ saved_char=c;
|
|
|
|
+ return c;
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ return ungetc(c,stdio_fp);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
class input_iterator {
|
|
|
|
public:
|
|
|
|
input_iterator();
|
2006-01-05 14:49:14 +00:00
|
|
|
@@ -236,7 +362,7 @@
|
2004-09-09 05:54:44 +00:00
|
|
|
virtual int get_location(int, const char **, int *) { return 0; }
|
|
|
|
virtual void backtrace() {}
|
|
|
|
virtual int set_location(const char *, int) { return 0; }
|
|
|
|
- virtual int next_file(FILE *, const char *) { return 0; }
|
|
|
|
+ virtual int next_file(opaque_fp *, const char *) { return 0; }
|
|
|
|
virtual void shift(int) {}
|
|
|
|
virtual int is_boundary() {return 0; }
|
|
|
|
virtual int internal_level() { return 0; }
|
2006-01-05 14:49:14 +00:00
|
|
|
@@ -277,7 +403,7 @@
|
2004-09-09 05:54:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class file_iterator : public input_iterator {
|
|
|
|
- FILE *fp;
|
|
|
|
+ opaque_fp *fp;
|
|
|
|
int lineno;
|
|
|
|
const char *filename;
|
|
|
|
int popened;
|
2006-01-05 14:49:14 +00:00
|
|
|
@@ -286,7 +412,9 @@
|
2004-09-09 05:54:44 +00:00
|
|
|
enum { BUF_SIZE = 512 };
|
|
|
|
unsigned char buf[BUF_SIZE];
|
|
|
|
void close();
|
|
|
|
+ void ctor_end(void);
|
|
|
|
public:
|
|
|
|
+ file_iterator(opaque_fp *, const char *, int = 0);
|
|
|
|
file_iterator(FILE *, const char *, int = 0);
|
|
|
|
~file_iterator();
|
|
|
|
int fill(node **);
|
2006-01-05 14:49:14 +00:00
|
|
|
@@ -294,18 +422,30 @@
|
2004-09-09 05:54:44 +00:00
|
|
|
int get_location(int, const char **, int *);
|
|
|
|
void backtrace();
|
|
|
|
int set_location(const char *, int);
|
|
|
|
- int next_file(FILE *, const char *);
|
|
|
|
+ int next_file(opaque_fp *, const char *);
|
|
|
|
int is_file();
|
|
|
|
};
|
|
|
|
|
|
|
|
-file_iterator::file_iterator(FILE *f, const char *fn, int po)
|
|
|
|
+file_iterator::file_iterator(opaque_fp *f, const char *fn, int po)
|
|
|
|
: fp(f), lineno(1), filename(fn), popened(po),
|
|
|
|
newline_flag(0), seen_escape(0)
|
|
|
|
{
|
|
|
|
- if ((font::use_charnames_in_special) && (fn != 0)) {
|
|
|
|
+ ctor_end();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+file_iterator::file_iterator(FILE * f, const char * fn, int po)
|
|
|
|
+: fp(new opaque_fp(f,po)), lineno(1), filename(fn), popened(po),
|
|
|
|
+ newline_flag(0), seen_escape(0)
|
|
|
|
+{
|
|
|
|
+ ctor_end();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void file_iterator::ctor_end(void)
|
|
|
|
+{
|
|
|
|
+ if ((font::use_charnames_in_special) && (filename != 0)) {
|
|
|
|
if (!the_output)
|
|
|
|
init_output();
|
|
|
|
- the_output->put_filename(fn);
|
|
|
|
+ the_output->put_filename(filename);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-01-05 14:49:14 +00:00
|
|
|
@@ -316,6 +456,8 @@
|
2004-09-09 05:54:44 +00:00
|
|
|
|
|
|
|
void file_iterator::close()
|
|
|
|
{
|
|
|
|
+ delete fp;
|
|
|
|
+#if 0
|
|
|
|
if (fp == stdin)
|
|
|
|
clearerr(stdin);
|
|
|
|
#ifndef POPEN_MISSING
|
2006-01-05 14:49:14 +00:00
|
|
|
@@ -324,6 +466,7 @@
|
2004-09-09 05:54:44 +00:00
|
|
|
#endif /* not POPEN_MISSING */
|
|
|
|
else
|
|
|
|
fclose(fp);
|
|
|
|
+#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
int file_iterator::is_file()
|
2006-01-05 14:49:14 +00:00
|
|
|
@@ -331,7 +474,7 @@
|
2004-09-09 05:54:44 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
-int file_iterator::next_file(FILE *f, const char *s)
|
|
|
|
+int file_iterator::next_file(opaque_fp *f, const char *s)
|
|
|
|
{
|
|
|
|
close();
|
|
|
|
filename = s;
|
2006-01-05 14:49:14 +00:00
|
|
|
@@ -354,7 +497,7 @@
|
2004-09-09 05:54:44 +00:00
|
|
|
ptr = p;
|
|
|
|
unsigned char *e = p + BUF_SIZE;
|
|
|
|
while (p < e) {
|
|
|
|
- int c = getc(fp);
|
|
|
|
+ int c = fp->xgetc();
|
|
|
|
if (c == EOF)
|
|
|
|
break;
|
|
|
|
if (invalid_input_char(c))
|
2006-01-05 14:49:14 +00:00
|
|
|
@@ -381,13 +524,13 @@
|
2004-09-09 05:54:44 +00:00
|
|
|
|
|
|
|
int file_iterator::peek()
|
|
|
|
{
|
|
|
|
- int c = getc(fp);
|
|
|
|
+ int c = fp->xgetc();
|
|
|
|
while (invalid_input_char(c)) {
|
|
|
|
warning(WARN_INPUT, "invalid input character code %1", int(c));
|
|
|
|
- c = getc(fp);
|
|
|
|
+ c = fp->xgetc();
|
|
|
|
}
|
|
|
|
if (c != EOF)
|
|
|
|
- ungetc(c, fp);
|
|
|
|
+ fp->unxgetc(c);
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
2006-01-05 14:49:14 +00:00
|
|
|
@@ -433,7 +576,7 @@
|
2004-09-09 05:54:44 +00:00
|
|
|
static int set_location(const char *, int);
|
|
|
|
static void backtrace();
|
|
|
|
static void backtrace_all();
|
|
|
|
- static void next_file(FILE *, const char *);
|
|
|
|
+ static void next_file(opaque_fp *, const char *);
|
|
|
|
static void end_file();
|
|
|
|
static void shift(int n);
|
|
|
|
static void add_boundary();
|
2006-01-05 14:49:14 +00:00
|
|
|
@@ -605,7 +748,7 @@
|
2004-09-09 05:54:44 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
-void input_stack::next_file(FILE *fp, const char *s)
|
|
|
|
+void input_stack::next_file(opaque_fp *fp, const char *s)
|
|
|
|
{
|
|
|
|
input_iterator **pp;
|
|
|
|
for (pp = ⊤ *pp != &nil_iterator; pp = &(*pp)->next)
|
2006-01-05 14:49:14 +00:00
|
|
|
@@ -691,10 +834,11 @@
|
2004-09-09 05:54:44 +00:00
|
|
|
input_stack::end_file();
|
|
|
|
else {
|
|
|
|
errno = 0;
|
2006-01-05 14:49:14 +00:00
|
|
|
- FILE *fp = fopen(nm.contents(), "r");
|
2004-09-09 05:54:44 +00:00
|
|
|
- if (!fp)
|
|
|
|
+ opaque_fp *fp = new opaque_fp(nm.contents(), "r");
|
|
|
|
+ if (!fp->active()) {
|
2006-01-05 14:49:14 +00:00
|
|
|
+ delete fp;
|
2004-09-09 05:54:44 +00:00
|
|
|
error("can't open `%1': %2", nm.contents(), strerror(errno));
|
|
|
|
- else
|
|
|
|
+ } else
|
|
|
|
input_stack::next_file(fp, nm.contents());
|
|
|
|
}
|
|
|
|
tok.next();
|
2006-01-05 14:49:14 +00:00
|
|
|
@@ -5372,11 +5516,12 @@
|
2004-09-09 05:54:44 +00:00
|
|
|
error("won't source non-file `%1' without -U flag", path);
|
|
|
|
else {
|
|
|
|
errno = 0;
|
|
|
|
- FILE *fp = fopen(path, "r");
|
|
|
|
- if (fp)
|
|
|
|
+ opaque_fp *fp = new opaque_fp(nm.contents(), "r",OPQ_FP_GUESS);
|
|
|
|
+ if (fp->active()) {
|
|
|
|
input_stack::push(new file_iterator(fp, nm.contents()));
|
|
|
|
- else
|
|
|
|
- error("can't open `%1': %2", path, strerror(errno));
|
|
|
|
+ } else {
|
|
|
|
+ delete fp;
|
|
|
|
+ }
|
|
|
|
}
|
|
|
|
tok.next();
|
|
|
|
}
|
2006-01-05 14:49:14 +00:00
|
|
|
@@ -6822,16 +6967,18 @@
|
2004-09-09 05:54:44 +00:00
|
|
|
|
|
|
|
static void process_input_file(const char *name)
|
|
|
|
{
|
|
|
|
- FILE *fp;
|
|
|
|
+ opaque_fp *fp;
|
|
|
|
if (strcmp(name, "-") == 0) {
|
|
|
|
clearerr(stdin);
|
|
|
|
- fp = stdin;
|
|
|
|
+ fp = new opaque_fp(stdin);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
errno = 0;
|
2006-01-05 14:49:14 +00:00
|
|
|
- fp = fopen(name, "r");
|
2004-09-09 05:54:44 +00:00
|
|
|
- if (!fp)
|
|
|
|
+ fp = new opaque_fp(name, "r", OPQ_FP_GUESS);
|
|
|
|
+ if (!fp->active()) {
|
2006-01-05 14:49:14 +00:00
|
|
|
+ delete fp;
|
2004-09-09 05:54:44 +00:00
|
|
|
fatal("can't open `%1': %2", name, strerror(errno));
|
|
|
|
+ }
|
|
|
|
}
|
|
|
|
input_stack::push(new file_iterator(fp, name));
|
|
|
|
tok.next();
|