From 075e75fbeb2096f4faf6816fd8aaf064eff27161 Mon Sep 17 00:00:00 2001
Message-Id:
From: Steffen Nurpmeso
Date: Wed, 16 Jul 2014 15:27:27 +0200
Subject: [PATCH 01/20] contrib/gideal/Makefile.sub: fix Bernd (Public Domain)
---
contrib/gideal/Makefile.sub | 56 +++++++++++++++++++--------------------------
1 file changed, 23 insertions(+), 33 deletions(-)
diff --git a/contrib/gideal/Makefile.sub b/contrib/gideal/Makefile.sub
index b59a757..2d25731 100644
--- a/contrib/gideal/Makefile.sub
+++ b/contrib/gideal/Makefile.sub
@@ -32,9 +32,6 @@ MAN7=ideal.n
MOSTLYCLEANADD=gideal $(MAN1) $(MAN7)
-# not all make programs have $(RM) predefined.
-RM=rm -f
-
all: gideal
gideal: gideal.pl
@@ -46,21 +43,23 @@ gideal: gideal.pl
$(srcdir)/gideal.pl >$@; \
chmod +x $@
-.PHONY: install_data
-install_data: gideal
+install_data: install_always $(make_install_examples)
+install_always: gideal
-test -d $(DESTDIR)$(bindir) || $(mkinstalldirs) $(DESTDIR)$(bindir)
- $(RM) $(DESTDIR)$(bindir)/gideal
+ rm -f $(DESTDIR)$(bindir)/gideal
$(INSTALL_SCRIPT) gideal $(DESTDIR)$(bindir)/gideal
- -test -d $(DESTDIR)$(datasubdir) \
- || $(mkinstalldirs) $(DESTDIR)$(datasubdir)
- -test -d $(DESTDIR)$(datasubdir)/ideal \
- || $(mkinstalldirs) $(DESTDIR)$(datasubdir)/ideal
- -test -d $(DESTDIR)$(datasubdir)/ideal/libfiles \
- || $(mkinstalldirs) $(DESTDIR)$(datasubdir)/ideal/libfiles
- $(RM) $(DESTDIR)$(datasubdir)/ideal/libfiles/*
+
+install_examples: install_always
+ -test -d $(DESTDIR)$(exampledir) \
+ || $(mkinstalldirs) $(DESTDIR)$(exampledir)
+ -test -d $(DESTDIR)$(exampledir)/ideal \
+ || $(mkinstalldirs) $(DESTDIR)$(exampledir)/ideal
+ -test -d $(DESTDIR)$(exampledir)/ideal/libfiles \
+ || $(mkinstalldirs) $(DESTDIR)$(exampledir)/ideal/libfiles
+ rm -f $(DESTDIR)$(exampledir)/ideal/libfiles/*
for i in $(srcdir)/libfiles/*; do \
n=`echo $$i | sed 's|$(srcdir)/libfiles/||g'`; \
- $(INSTALL_DATA) $$i $(DESTDIR)$(datasubdir)/ideal/libfiles/$$n; \
+ $(INSTALL_DATA) $$i $(DESTDIR)$(exampledir)/ideal/libfiles/$$n; \
done
-test -d $(DESTDIR)$(exampledir) \
|| $(mkinstalldirs) $(DESTDIR)$(exampledir)
@@ -68,28 +67,19 @@ install_data: gideal
|| $(mkinstalldirs) $(DESTDIR)$(exampledir)/ideal
-test -d $(DESTDIR)$(exampledir)/ideal/files \
|| $(mkinstalldirs) $(DESTDIR)$(exampledir)/ideal/files
- $(RM) $(DESTDIR)$(exampledir)/ideal/files/*
+ rm -f $(DESTDIR)$(exampledir)/ideal/files/*
for i in $(srcdir)/files/*; do \
n=`echo $$i | sed 's|$(srcdir)/files/||g'`; \
$(INSTALL_DATA) $$i $(DESTDIR)$(exampledir)/ideal/files/$$n; \
done
+uninstall_sub: uninstall_always $(make_uninstall_examples)
+uninstall_always:
+ rm -f $(DESTDIR)$(bindir)/gideal
-.PHONY: uninstall_sub
-uninstall_sub:
- $(RM) $(DESTDIR)$(bindir)/gideal
- -rmdir $(DESTDIR)$(bindir)
- $(RM) $(DESTDIR)$(datasubdir)/ideal/files/*
- -rmdir $(DESTDIR)$(datasubdir)/ideal/files
- $(RM) $(DESTDIR)$(datasubdir)/ideal/libfiles/*
- -rmdir $(DESTDIR)$(datasubdir)/ideal/libfiles
- -rmdir $(DESTDIR)$(datasubdir)/ideal
-
-
-########################################################################
-# Emacs settings
-########################################################################
-#
-# Local Variables:
-# mode: makefile
-# End:
+uninstall_examples: uninstall_always
+ rm -f $(DESTDIR)$(exampledir)/ideal/files/*
+ -rmdir $(DESTDIR)$(exampledir)/ideal/files
+ rm -f $(DESTDIR)$(exampledir)/ideal/libfiles/*
+ -rmdir $(DESTDIR)$(exampledir)/ideal/libfiles
+ -rmdir $(DESTDIR)$(exampledir)/ideal
--
2.0.0
From 61e9cd271622a7ad0e7577434973297fe07a6bf6 Mon Sep 17 00:00:00 2001
Message-Id:
In-Reply-To:
References:
From: Steffen Nurpmeso
Date: Sat, 26 Jul 2014 16:14:56 +0200
Subject: [PATCH 02/20] src/include/lib.h: add some infrastructure (Public
Domain)
---
src/include/lib.h | 37 ++++++++++++++++++++++++++++++++++++-
1 file changed, 36 insertions(+), 1 deletion(-)
diff --git a/src/include/lib.h b/src/include/lib.h
index 7f05f2d..3928277 100644
--- a/src/include/lib.h
+++ b/src/include/lib.h
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989-2000, 2001, 2002, 2003, 2005, 2006, 2009
+/* Copyright (C) 1989-2000, 2001, 2002, 2003, 2005, 2006, 2009, 2014
Free Software Foundation, Inc.
Written by James Clark (address@hidden)
@@ -17,6 +17,8 @@ for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see . */
+#ifndef _LIB_H
+#define _LIB_H
#ifdef HAVE_CONFIG_H
#include
@@ -175,3 +177,36 @@ const double PI = 3.14159265358979323846;
#define ad_delete(size) delete []
#define a_delete delete []
#endif /* !ARRAY_DELETE_NEEDS_SIZE */
+
+#ifdef HAVE_CC_INTTYPES_H
+# include
+#endif
+#if !defined UINT8_MAX && !defined uint8_t
+# undef int8_t
+typedef unsigned char uint8_t;
+typedef signed char int8_t;
+#endif
+#if !defined UINT32_MAX && !defined uint32_t
+# undef int32_t
+# if INT_MAX == 2147483647
+typedef unsigned int uint32_t;
+typedef signed int int32_t;
+# else
+typedef unsigned long int uint32_t;
+typedef signed long int int32_t;
+# endif
+#endif
+
+#ifndef NELEM
+# define NELEM(X) (sizeof(X) / sizeof((X)[0]))
+#endif
+
+#define CLASS_DISABLE_COPY(C) private: C(C const &); C &operator=(C const &)
+
+#ifndef NDEBUG
+# define INJECT(X) X
+#else
+# define INJECT(X)
+#endif
+
+#endif /* _LIB_H */
--
2.0.0
From d154f86f67c567fdf982ee5b86784d292f705bb5 Mon Sep 17 00:00:00 2001
Message-Id:
In-Reply-To:
References:
From: Steffen Nurpmeso
Date: Sat, 26 Jul 2014 22:52:26 +0200
Subject: [PATCH 03/20] Encapsulate searchpath:: FILE*'s in new class file_case
(Public Domain)
---
src/devices/grops/ps.cpp | 23 ++--
src/devices/grops/psrm.cpp | 113 +++++++++----------
src/include/file_case.h | 100 +++++++++++++++++
src/include/font.h | 16 +--
src/include/searchpath.h | 16 +--
src/libs/libgroff/Makefile.sub | 3 +-
src/libs/libgroff/file_case.cpp | 77 +++++++++++++
src/libs/libgroff/font.cpp | 48 ++++-----
src/libs/libgroff/fontfile.cpp | 15 +--
src/libs/libgroff/searchpath.cpp | 179 ++++++++++++------------------
src/preproc/eqn/main.cpp | 14 +--
src/preproc/grn/main.cpp | 16 +--
src/preproc/html/pre-html.cpp | 22 ++--
src/preproc/soelim/soelim.cpp | 39 +++----
src/roff/troff/env.cpp | 52 ++++-----
src/roff/troff/input.cpp | 227 ++++++++++++++++++---------------------
src/roff/troff/node.cpp | 20 ++--
17 files changed, 553 insertions(+), 427 deletions(-)
create mode 100644 src/include/file_case.h
create mode 100644 src/libs/libgroff/file_case.cpp
diff --git a/src/devices/grops/ps.cpp b/src/devices/grops/ps.cpp
index ab1b080..b4306a8 100644
--- a/src/devices/grops/ps.cpp
+++ b/src/devices/grops/ps.cpp
@@ -1,6 +1,6 @@
// -*- C++ -*-
/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002, 2003, 2004, 2005,
- 2006, 2007, 2009
+ 2006, 2007, 2009, 2014
Free Software Foundation, Inc.
Written by James Clark (address@hidden)
@@ -26,6 +26,7 @@ along with this program. If not, see . */
*/
#include "driver.h"
+#include "file_case.h"
#include "stringclass.h"
#include "cset.h"
#include "nonposix.h"
@@ -784,28 +785,27 @@ void ps_printer::define_encoding(const char *encoding, int encoding_index)
int i;
for (i = 0; i < 256; i++)
vec[i] = 0;
- char *path;
- FILE *fp = font::open_file(encoding, &path);
- if (fp == 0)
+
+ file_case *fcp = font::open_file(encoding);
+ if (fcp == NULL)
fatal("can't open encoding file `%1'", encoding);
- int lineno = 1;
+
const int BUFFER_SIZE = 512;
char buf[BUFFER_SIZE];
- while (fgets(buf, BUFFER_SIZE, fp) != 0) {
+ for (int lineno = 1; fgets(buf, BUFFER_SIZE, fcp->file()) != NULL; ++lineno) {
char *p = buf;
while (csspace(*p))
p++;
if (*p != '#' && *p != '\0' && (p = strtok(buf, WS)) != 0) {
char *q = strtok(0, WS);
- int n = 0; // pacify compiler
+ int n = 0; // pacify compiler
if (q == 0 || sscanf(q, "%d", &n) != 1 || n < 0 || n >= 256)
- fatal_with_file_and_line(path, lineno, "bad second field");
+ fatal_with_file_and_line(fcp->path(), lineno, "bad second field");
vec[n] = new char[strlen(p) + 1];
strcpy(vec[n], p);
}
- lineno++;
}
- a_delete path;
+
out.put_literal_symbol(make_encoding_name(encoding_index))
.put_delimiter('[');
for (i = 0; i < 256; i++) {
@@ -818,7 +818,8 @@ void ps_printer::define_encoding(const char *encoding, int encoding_index)
}
out.put_delimiter(']')
.put_symbol("def");
- fclose(fp);
+
+ delete fcp;
}
void ps_printer::reencode_font(ps_font *f)
diff --git a/src/devices/grops/psrm.cpp b/src/devices/grops/psrm.cpp
index a3787cb..fae2176 100644
--- a/src/devices/grops/psrm.cpp
+++ b/src/devices/grops/psrm.cpp
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989-1992, 2000-2004, 2009, 2013
+/* Copyright (C) 1989-1992, 2000-2004, 2009, 2013, 2014
Free Software Foundation, Inc.
Written by James Clark (address@hidden)
@@ -19,6 +19,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see . */
#include "driver.h"
+#include "file_case.h"
#include "stringclass.h"
#include "cset.h"
@@ -306,7 +307,6 @@ void resource_manager::output_prolog(ps_output &out)
{
FILE *outfp = out.get_file();
out.end_line();
- char *path;
if (!getenv("GROPS_PROLOGUE")) {
string e = "GROPS_PROLOGUE";
e += '=';
@@ -316,16 +316,18 @@ void resource_manager::output_prolog(ps_output &out)
fatal("putenv failed");
}
char *prologue = getenv("GROPS_PROLOGUE");
- FILE *fp = font::open_file(prologue, &path);
- if (!fp)
+
+ file_case *fcp = font::open_file(prologue);
+ if (fcp == NULL)
fatal("can't find `%1'", prologue);
+
fputs("%%BeginResource: ", outfp);
procset_resource->print_type_and_name(outfp);
putc('\n', outfp);
- process_file(-1, fp, path, outfp);
- fclose(fp);
- a_delete path;
+ process_file(-1, fcp->file(), fcp->path(), outfp);
fputs("%%EndResource\n", outfp);
+
+ delete fcp;
}
void resource_manager::import_file(const char *filename, ps_output &out)
@@ -348,65 +350,54 @@ void resource_manager::supply_resource(resource *r, int rank, FILE *outfp,
r->flags |= resource::BUSY;
if (rank > r->rank)
r->rank = rank;
- char *path = 0; // pacify compiler
- FILE *fp = 0;
- if (r->filename != 0) {
+
+ file_case *fcp = NULL;
+ if (r->filename != NULL) {
if (r->type == RESOURCE_FONT) {
- fp = font::open_file(r->filename, &path);
- if (!fp) {
- error("can't find `%1'", r->filename);
- a_delete r->filename;
- r->filename = 0;
- }
+ if ((fcp = font::open_file(r->filename)) == NULL)
+ error("can't find `%1'", r->filename);
+ } else {
+ if ((fcp = include_search_path.open_file_cautious(r->filename)) == NULL)
+ error("can't open `%1': %2", r->filename, strerror(errno));
}
- else {
- errno = 0;
- fp = include_search_path.open_file_cautious(r->filename);
- if (!fp) {
- error("can't open `%1': %2", r->filename, strerror(errno));
- a_delete r->filename;
- r->filename = 0;
- }
- else
- path = r->filename;
+ if (fcp == NULL) {
+ a_delete r->filename;
+ r->filename = NULL;
}
}
- if (fp) {
+
+ if (fcp != NULL) {
if (outfp) {
if (r->type == RESOURCE_FILE && is_document) {
- fputs("%%BeginDocument: ", outfp);
- print_ps_string(r->name, outfp);
- putc('\n', outfp);
- }
- else {
- fputs("%%BeginResource: ", outfp);
- r->print_type_and_name(outfp);
- putc('\n', outfp);
+ fputs("%%BeginDocument: ", outfp);
+ print_ps_string(r->name, outfp);
+ putc('\n', outfp);
+ } else {
+ fputs("%%BeginResource: ", outfp);
+ r->print_type_and_name(outfp);
+ putc('\n', outfp);
}
}
- process_file(rank, fp, path, outfp);
- fclose(fp);
- if (r->type == RESOURCE_FONT)
- a_delete path;
+ process_file(rank, fcp->file(), fcp->path(), outfp);
+ delete fcp;
+
if (outfp) {
if (r->type == RESOURCE_FILE && is_document)
- fputs("%%EndDocument\n", outfp);
+ fputs("%%EndDocument\n", outfp);
else
- fputs("%%EndResource\n", outfp);
+ fputs("%%EndResource\n", outfp);
}
r->flags |= resource::SUPPLIED;
- }
- else {
+ } else {
if (outfp) {
if (r->type == RESOURCE_FILE && is_document) {
- fputs("%%IncludeDocument: ", outfp);
- print_ps_string(r->name, outfp);
- putc('\n', outfp);
- }
- else {
- fputs("%%IncludeResource: ", outfp);
- r->print_type_and_name(outfp);
- putc('\n', outfp);
+ fputs("%%IncludeDocument: ", outfp);
+ print_ps_string(r->name, outfp);
+ putc('\n', outfp);
+ } else {
+ fputs("%%IncludeResource: ", outfp);
+ r->print_type_and_name(outfp);
+ putc('\n', outfp);
}
}
r->flags |= resource::NEEDED;
@@ -1075,24 +1066,22 @@ void resource_manager::process_file(int rank, FILE *fp, const char *filename,
void resource_manager::read_download_file()
{
- char *path = 0;
- FILE *fp = font::open_file("download", &path);
- if (!fp)
+ file_case *fcp = font::open_file("download");
+ if (fcp == NULL)
fatal("can't find `download'");
+
char buf[512];
- int lineno = 0;
- while (fgets(buf, sizeof(buf), fp)) {
- lineno++;
+ for (int lineno = 1; fgets(buf, sizeof(buf), fcp->file()) != NULL; ++lineno) {
char *p = strtok(buf, " \t\r\n");
- if (p == 0 || *p == '#')
+ if (p == NULL || *p == '#')
continue;
char *q = strtok(0, " \t\r\n");
- if (!q)
- fatal_with_file_and_line(path, lineno, "missing filename");
+ if (q == NULL)
+ fatal_with_file_and_line(fcp->path(), lineno, "missing filename");
lookup_font(p)->filename = strsave(q);
}
- a_delete path;
- fclose(fp);
+
+ delete fcp;
}
// XXX Can we share some code with ps_output::put_string()?
diff --git a/src/include/file_case.h b/src/include/file_case.h
new file mode 100644
index 0000000..a52d121
--- /dev/null
+++ b/src/include/file_case.h
@@ -0,0 +1,100 @@
+/*@ file_case: input file encapsulator
+ * Copyright (C) 2014 Free Software Foundation, Inc.
+ * Written by Steffen Nurpmeso (address@hidden) for groff (Public Domain)
+ *
+ * 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 3 of the License, 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 this program. If not, see . */
+#ifndef _FILE_CASE_H
+#define _FILE_CASE_H
+
+#include "lib.h"
+
+#include
+#include
+
+class file_case
+{
+ char const *_path;
+ FILE *_file;
+ uint32_t _flags;
+public:
+ // Flags for ctor / muxer()
+ enum {
+ fc_none = 0,
+ fc_dont_close = 1<<0, // Don't close the file, if any
+ fc_pipe = 1<<1, // _file is not seekable
+ fc_const_path = 1<<2, // Don't dup path, and don't a_delete it
+ fc_take_path = 1<<3, // Don't dup path, but a_delete it
+ _fc_freebit = 4,
+ fc_mask = (1<<_fc_freebit) - 1
+ };
+
+ // Flags only for muxer()
+ enum {
+ mux_need_seek = 1<<(_fc_freebit+0), // File must be seekable
+ mux_need_binary = 1<<(_fc_freebit+1), // Need binary I/O
+ mux_default = fc_none,
+ mux_mask = ~fc_mask
+ };
+
+ file_case(FILE *fp, char const *path, uint32_t flags=fc_none);
+ ~file_case(void);
+
+ bool close(void);
+ char const * path(void) const;
+ FILE * file(void) const;
+ bool is_pipe(void) const;
+
+ // Factory muxer; note that fc_take_path will be honoured even on failure
+ static file_case * muxer(char const *path, uint32_t flags=mux_default);
+
+ CLASS_DISABLE_COPY(file_case);
+};
+
+inline
+file_case::file_case(FILE *fp, char const *path, uint32_t flags)
+:
+ _path(path), _file(fp), _flags(flags)
+{
+ assert(!(flags & (fc_const_path | fc_take_path)) ||
+ !(flags & fc_const_path) != !(flags & fc_take_path));
+ assert(!(flags & ~fc_mask));
+}
+
+inline
+file_case::~file_case(void)
+{
+ if (_file != NULL)
+ close();
+}
+
+inline char const *
+file_case::path(void) const
+{
+ return _path;
+}
+
+inline FILE *
+file_case::file(void) const
+{
+ return _file;
+}
+
+inline bool
+file_case::is_pipe(void) const
+{
+ return ((_flags & fc_pipe) != 0);
+}
+#endif /* _FILE_CASE_H */
diff --git a/src/include/font.h b/src/include/font.h
index 75d2ef1..2088c87 100644
--- a/src/include/font.h
+++ b/src/include/font.h
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2002, 2004, 2006, 2009, 2010
+/* Copyright (C) 1989, 1990, 1991, 1992, 2002, 2004, 2006, 2009, 2010, 2014
Free Software Foundation, Inc.
Written by James Clark (address@hidden)
@@ -18,6 +18,8 @@ for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see . */
+#include "file_case.h"
+
// A function of this type can be registered to define the semantics of
// arbitrary commands in a font DESC file.
typedef void (*FONT_COMMAND_HANDLER)(const char *, // command
@@ -215,13 +217,11 @@ public:
static void command_line_font_dir(const char *); // Prepend given
// path (arg1) to the list of directories in which
// to look up fonts.
- static FILE *open_file(const char *, char **); // Open a font file
- // with the given name (arg1), searching along the
- // current font path. If arg2 points to a string
- // pointer, set it to the found file name (this
- // depends on the device also). Return the opened
- // file. If not found, arg2 is unchanged, and NULL
- // is returned.
+
+ // Open a font file with the given name, searching along the current font
+ // path. Return the opened file or NULL.
+ static file_case * open_file(const char *name,
+ uint32_t flags=file_case::mux_default);
static int load_desc(); // Open the DESC file (depending on the
// device) and initialize some static variables with
// info from there.
diff --git a/src/include/searchpath.h b/src/include/searchpath.h
index 5f2334c..43d4773 100644
--- a/src/include/searchpath.h
+++ b/src/include/searchpath.h
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2003, 2009
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2003, 2009, 2014
Free Software Foundation, Inc.
Written by James Clark (address@hidden)
@@ -18,14 +18,18 @@ for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see . */
+#include "file_case.h"
+
class search_path {
char *dirs;
unsigned init_len;
public:
- search_path(const char *envvar, const char *standard,
- int add_home, int add_current);
+ search_path(const char *envvar, const char *standard, int add_home,
+ int add_current);
~search_path();
- void command_line_dir(const char *);
- FILE *open_file(const char *, char **);
- FILE *open_file_cautious(const char *, char ** = 0, const char * = 0);
+
+ void command_line_dir(char const *);
+ file_case * open_file(char const *name, uint32_t f=file_case::mux_default);
+ file_case * open_file_cautious(char const *name,
+ uint32_t f=file_case::mux_default);
};
diff --git a/src/libs/libgroff/Makefile.sub b/src/libs/libgroff/Makefile.sub
index 80fd87c..ae5a5b5 100644
--- a/src/libs/libgroff/Makefile.sub
+++ b/src/libs/libgroff/Makefile.sub
@@ -12,6 +12,7 @@ OBJS=\
errarg.$(OBJEXT) \
error.$(OBJEXT) \
fatal.$(OBJEXT) \
+ file_case.$(OBJEXT) \
filename.$(OBJEXT) \
font.$(OBJEXT) \
fontfile.$(OBJEXT) \
@@ -62,7 +63,7 @@ CCSRCS=\
$(srcdir)/errarg.cpp \
$(srcdir)/error.cpp \
$(srcdir)/fatal.cpp \
- $(srcdir)/filename.cpp \
+ $(srcdir)/file_case.cpp \
$(srcdir)/font.cpp \
$(srcdir)/fontfile.cpp \
$(srcdir)/geometry.cpp \
diff --git a/src/libs/libgroff/file_case.cpp b/src/libs/libgroff/file_case.cpp
new file mode 100644
index 0000000..51bc2f2
--- /dev/null
+++ b/src/libs/libgroff/file_case.cpp
@@ -0,0 +1,77 @@
+/*@ file_case: input file encapsulator
+ * Copyright (C) 2014 Free Software Foundation, Inc.
+ * Written by Steffen Nurpmeso (address@hidden) for groff (Public Domain)
+ *
+ * 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 3 of the License, 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 this program. If not, see . */
+
+#include "lib.h"
+
+#include
+#include
+#include
+
+#include "file_case.h"
+
+bool
+file_case::close(void)
+{
+ assert(_file != NULL);
+
+ if (!(_flags & fc_const_path))
+ a_delete _path;
+
+ bool rv;
+ if (_flags & fc_dont_close)
+ rv = true;
+ else
+ rv = (fclose(_file) == 0);
+
+#ifndef NDEBUG
+ _file = NULL;
+ _path = NULL;
+ _flags = fc_none;
+#endif
+ return rv;
+}
+
+/*static*/ file_case *
+file_case::muxer(char const *path, uint32_t flags)
+{
+ assert(!(flags & (fc_dont_close | fc_pipe)));
+ assert(!(flags & (fc_const_path | fc_take_path)) ||
+ !(flags & fc_const_path) != !(flags & fc_take_path));
+
+ if (!(flags & (fc_const_path | fc_take_path))) {
+ path = strsave(path);
+ flags |= fc_take_path;
+ }
+
+ errno = 0;
+ FILE *fp = fopen(path, ((flags & mux_need_binary) ? "rb" : "r"));
+ int save_err = errno;
+
+ flags &= ~mux_mask;
+ file_case *fcp;
+ if (fp != NULL)
+ fcp = new file_case(fp, path, flags);
+ else {
+ if (!(flags & fc_const_path))
+ a_delete path;
+ errno = save_err;
+ fcp = NULL;
+ }
+ return fcp;
+}
diff --git a/src/libs/libgroff/font.cpp b/src/libs/libgroff/font.cpp
index fe23fdd..b5a1990 100644
--- a/src/libs/libgroff/font.cpp
+++ b/src/libs/libgroff/font.cpp
@@ -1,6 +1,6 @@
// -*- C++ -*-
/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002, 2003, 2004, 2005,
- 2006, 2008, 2009, 2010
+ 2006, 2008, 2009, 2010, 2014
Free Software Foundation, Inc.
Written by James Clark (address@hidden)
@@ -29,7 +29,9 @@ along with this program. If not, see . */
#include "errarg.h"
#include "error.h"
#include "cset.h"
+#include "file_case.h"
#include "font.h"
+#include "searchpath.h"
#include "unicode.h"
#include "paper.h"
@@ -68,38 +70,36 @@ struct font_widths_cache {
/* text_file */
struct text_file {
- FILE *fp;
- char *path;
+ file_case *fcp;
int lineno;
int size;
int skip_comments;
int silent;
char *buf;
- text_file(FILE *fp, char *p);
+ text_file(file_case *fcp);
~text_file();
int next();
- void error(const char *format,
+ void error(const char *format,
const errarg &arg1 = empty_errarg,
const errarg &arg2 = empty_errarg,
const errarg &arg3 = empty_errarg);
};
-text_file::text_file(FILE *p, char *s)
-: fp(p), path(s), lineno(0), size(0), skip_comments(1), silent(0), buf(0)
+text_file::text_file(file_case *fcp)
+: fcp(fcp), lineno(0), size(0), skip_comments(1), silent(0), buf(0)
{
}
text_file::~text_file()
{
a_delete buf;
- a_delete path;
- if (fp)
- fclose(fp);
+ if (fcp != NULL)
+ delete fcp;
}
int text_file::next()
{
- if (fp == 0)
+ if (fcp == NULL)
return 0;
if (buf == 0) {
buf = new char[128];
@@ -108,7 +108,7 @@ int text_file::next()
for (;;) {
int i = 0;
for (;;) {
- int c = getc(fp);
+ int c = getc(fcp->file());
if (c == EOF)
break;
if (invalid_input_char(c))
@@ -139,13 +139,13 @@ int text_file::next()
return 0;
}
-void text_file::error(const char *format,
+void text_file::error(const char *format,
const errarg &arg1,
const errarg &arg2,
const errarg &arg3)
{
if (!silent)
- error_with_file_and_line(path, lineno, format, arg1, arg2, arg3);
+ error_with_file_and_line(fcp->path(), lineno, format, arg1, arg2, arg3);
}
int glyph_to_unicode(glyph *g)
@@ -769,16 +769,15 @@ int font::load(int *not_found, int head_only)
error("`DESC' is not a valid font file name");
return 0;
}
- char *path;
- FILE *fp;
- if ((fp = open_file(name, &path)) == NULL) {
+ file_case *fcp;
+ if ((fcp = open_file(name)) == NULL) {
if (not_found)
*not_found = 1;
else
error("can't find font file `%1'", name);
return 0;
}
- text_file t(fp, path);
+ text_file t(fcp);
t.skip_comments = 1;
t.silent = head_only;
char *p;
@@ -844,7 +843,8 @@ int font::load(int *not_found, int head_only)
else if (strcmp(p, "kernpairs") != 0 && strcmp(p, "charset") != 0) {
char *command = p;
p = strtok(0, "\n");
- handle_unknown_font_command(command, trim_arg(p), t.path, t.lineno);
+ handle_unknown_font_command(command, trim_arg(p), t.fcp->path(),
+ t.lineno);
}
else
break;
@@ -1033,13 +1033,12 @@ static struct {
int font::load_desc()
{
int nfonts = 0;
- FILE *fp;
- char *path;
- if ((fp = open_file("DESC", &path)) == 0) {
+ file_case *fcp;
+ if ((fcp = open_file("DESC")) == NULL) {
error("can't find `DESC' file");
return 0;
}
- text_file t(fp, path);
+ text_file t(fcp);
t.skip_comments = 1;
res = 0;
while (t.next()) {
@@ -1215,7 +1214,8 @@ int font::load_desc()
else if (unknown_desc_command_handler) {
char *command = p;
p = strtok(0, "\n");
- (*unknown_desc_command_handler)(command, trim_arg(p), t.path, t.lineno);
+ (*unknown_desc_command_handler)(command, trim_arg(p), t.fcp->path(),
+ t.lineno);
}
}
if (res == 0) {
diff --git a/src/libs/libgroff/fontfile.cpp b/src/libs/libgroff/fontfile.cpp
index 543f406..a731cf8 100644
--- a/src/libs/libgroff/fontfile.cpp
+++ b/src/libs/libgroff/fontfile.cpp
@@ -1,6 +1,6 @@
// -*- C++ -*-
/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002, 2004, 2006,
- 2009
+ 2009, 2014
Free Software Foundation, Inc.
Written by James Clark (address@hidden)
@@ -24,6 +24,7 @@ along with this program. If not, see . */
#include
#include
#include
+#include "file_case.h"
#include "font.h"
#include "searchpath.h"
#include "device.h"
@@ -60,11 +61,11 @@ void font::command_line_font_dir(const char *dir)
font_path.command_line_dir(dir);
}
-FILE *font::open_file(const char *nm, char **pathp)
+file_case *font::open_file(const char *name, uint32_t flags)
{
- char *filename = new char[strlen(nm) + strlen(device) + 5];
- sprintf(filename, "dev%s/%s", device, nm);
- FILE *fp = font_path.open_file(filename, pathp);
- a_delete filename;
- return fp;
+ assert(!(flags & ~file_case::mux_mask));
+
+ char *filename = new char[strlen(name) + strlen(device) + 5];
+ sprintf(filename, "dev%s/%s", device, name);
+ return font_path.open_file(filename, flags | file_case::fc_take_path);
}
diff --git a/src/libs/libgroff/searchpath.cpp b/src/libs/libgroff/searchpath.cpp
index 105dfdf..b0520d6 100644
--- a/src/libs/libgroff/searchpath.cpp
+++ b/src/libs/libgroff/searchpath.cpp
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2003, 2005, 2009
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2003, 2005, 2009, 2014
Free Software Foundation, Inc.
Written by James Clark (address@hidden)
@@ -24,6 +24,7 @@ along with this program. If not, see . */
#include
#include
+#include "file_case.h"
#include "searchpath.h"
#include "nonposix.h"
@@ -33,6 +34,51 @@ along with this program. If not, see . */
# define relocate(path) strsave(path)
#endif
+static file_case * _try_iter(char const *dirs, char const *name,
+ uint32_t flags);
+
+static file_case *
+_try_iter(char const *dirs, char const *name, uint32_t flags)
+{
+ file_case *fcp;
+ bool delname = ((flags & fcp->fc_take_path) != 0);
+ flags = (flags & ~(fcp->fc_const_path)) | fcp->fc_take_path;
+ unsigned namelen = strlen(name);
+ char const *p = dirs;
+
+ for (;;) {
+ char *end = strchr(p, PATH_SEP_CHAR);
+ if (end == NULL)
+ end = strchr(p, '\0');
+ int need_slash = (end > p && strchr(DIR_SEPS, end[-1]) == NULL);
+ char *origpath = new char[(end - p) + need_slash + namelen + 1];
+ memcpy(origpath, p, end - p);
+ if (need_slash)
+ origpath[end - p] = '/';
+ strcpy(origpath + (end - p) + need_slash, name);
+#if 0
+ fprintf(stderr, "origpath `%s'\n", origpath);
+#endif
+ char *path = relocate(origpath);
+ a_delete origpath;
+#if 0
+ fprintf(stderr, "trying `%s'\n", path);
+#endif
+ if ((fcp = file_case::muxer(path, flags)) != NULL)
+ goto jleave;
+ if (errno != ENOENT)
+ goto jleave;
+ if (*end == '\0')
+ break;
+ p = end + 1;
+ }
+ errno = ENOENT;
+jleave:
+ if (delname)
+ a_delete name;
+ return fcp;
+}
+
search_path::search_path(const char *envvar, const char *standard,
int add_home, int add_current)
{
@@ -93,115 +139,32 @@ void search_path::command_line_dir(const char *s)
a_delete old;
}
-FILE *search_path::open_file(const char *name, char **pathp)
+file_case *search_path::open_file(char const *name, uint32_t flags)
{
- assert(name != 0);
- if (IS_ABSOLUTE(name) || *dirs == '\0') {
- FILE *fp = fopen(name, "r");
- if (fp) {
- if (pathp)
- *pathp = strsave(name);
- return fp;
- }
- else
- return 0;
- }
- unsigned namelen = strlen(name);
- char *p = dirs;
- for (;;) {
- char *end = strchr(p, PATH_SEP_CHAR);
- if (!end)
- end = strchr(p, '\0');
- int need_slash = end > p && strchr(DIR_SEPS, end[-1]) == 0;
- char *origpath = new char[(end - p) + need_slash + namelen + 1];
- memcpy(origpath, p, end - p);
- if (need_slash)
- origpath[end - p] = '/';
- strcpy(origpath + (end - p) + need_slash, name);
-#if 0
- fprintf(stderr, "origpath `%s'\n", origpath);
-#endif
- char *path = relocate(origpath);
- a_delete origpath;
-#if 0
- fprintf(stderr, "trying `%s'\n", path);
-#endif
- FILE *fp = fopen(path, "r");
- if (fp) {
- if (pathp)
- *pathp = path;
- else
- a_delete path;
- return fp;
- }
- a_delete path;
- if (*end == '\0')
- break;
- p = end + 1;
- }
- return 0;
+ assert(name != NULL);
+
+ file_case *fcp;
+ if (IS_ABSOLUTE(name) || *dirs == '\0')
+ fcp = file_case::muxer(name, flags);
+ else
+ fcp = _try_iter(dirs, name, flags);
+ return fcp;
}
-FILE *search_path::open_file_cautious(const char *name, char **pathp,
- const char *mode)
+file_case *search_path::open_file_cautious(char const *name, uint32_t flags)
{
- if (!mode)
- mode = "r";
- bool reading = (strchr(mode, 'r') != 0);
- if (name == 0 || strcmp(name, "-") == 0) {
- if (pathp)
- *pathp = strsave(reading ? "stdin" : "stdout");
- return (reading ? stdin : stdout);
- }
- if (!reading || IS_ABSOLUTE(name) || *dirs == '\0') {
- FILE *fp = fopen(name, mode);
- if (fp) {
- if (pathp)
- *pathp = strsave(name);
- return fp;
- }
- else
- return 0;
- }
- unsigned namelen = strlen(name);
- char *p = dirs;
- for (;;) {
- char *end = strchr(p, PATH_SEP_CHAR);
- if (!end)
- end = strchr(p, '\0');
- int need_slash = end > p && strchr(DIR_SEPS, end[-1]) == 0;
- char *origpath = new char[(end - p) + need_slash + namelen + 1];
- memcpy(origpath, p, end - p);
- if (need_slash)
- origpath[end - p] = '/';
- strcpy(origpath + (end - p) + need_slash, name);
-#if 0
- fprintf(stderr, "origpath `%s'\n", origpath);
-#endif
- char *path = relocate(origpath);
- a_delete origpath;
-#if 0
- fprintf(stderr, "trying `%s'\n", path);
-#endif
- FILE *fp = fopen(path, mode);
- if (fp) {
- if (pathp)
- *pathp = path;
- else
- a_delete path;
- return fp;
- }
- int err = errno;
- a_delete path;
- if (err != ENOENT)
- {
- errno = err;
- return 0;
- }
- if (*end == '\0')
- break;
- p = end + 1;
- }
- errno = ENOENT;
- return 0;
+ assert(name != NULL);
+
+ file_case *fcp;
+ if (name == NULL || strcmp(name, "-") == 0) {
+ flags &= ~(fcp->fc_take_path);
+ flags |= fcp->fc_dont_close | fcp->fc_const_path;
+ if (flags & fcp->mux_need_binary)
+ SET_BINARY(fileno(stdin));
+ fcp = new file_case(stdin, "stdin", flags);
+ } else if (IS_ABSOLUTE(name) || *dirs == '\0')
+ fcp = file_case::muxer(name, flags);
+ else
+ fcp = _try_iter(dirs, name, flags);
+ return fcp;
}
diff --git a/src/preproc/eqn/main.cpp b/src/preproc/eqn/main.cpp
index 167fb4e..672bc50 100644
--- a/src/preproc/eqn/main.cpp
+++ b/src/preproc/eqn/main.cpp
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989-1992, 2000-2002, 2005, 2007, 2009, 2011
+/* Copyright (C) 1989-1992, 2000-2002, 2005, 2007, 2009, 2011, 2014
Free Software Foundation, Inc.
Written by James Clark (address@hidden)
@@ -21,6 +21,7 @@ along with this program. If not, see . */
#include "eqn.h"
#include "stringclass.h"
#include "device.h"
+#include "file_case.h"
#include "searchpath.h"
#include "macropath.h"
#include "htmlhint.h"
@@ -390,12 +391,11 @@ int main(int argc, char **argv)
device);
}
if (load_startup_file) {
- char *path;
- FILE *fp = config_macro_path.open_file(STARTUP_FILE, &path);
- if (fp) {
- do_file(fp, path);
- fclose(fp);
- a_delete path;
+ file_case *fcp;
+ if ((fcp = config_macro_path.open_file(STARTUP_FILE, fcp->fc_const_path)
+ ) != NULL) {
+ do_file(fcp->file(), fcp->path());
+ delete fcp;
}
}
if (optind >= argc)
diff --git a/src/preproc/grn/main.cpp b/src/preproc/grn/main.cpp
index 55fc27a..b5bcc79 100644
--- a/src/preproc/grn/main.cpp
+++ b/src/preproc/grn/main.cpp
@@ -74,6 +74,7 @@
#include "gprint.h"
#include "device.h"
+#include "file_case.h"
#include "font.h"
#include "searchpath.h"
#include "macropath.h"
@@ -514,7 +515,6 @@ void
conv(register FILE *fp,
int baseline)
{
- register FILE *gfp = NULL; /* input file pointer */
register int done = 0; /* flag to remember if finished */
register ELT *e; /* current element pointer */
ELT *PICTURE; /* whole picture data base pointer */
@@ -546,13 +546,13 @@ conv(register FILE *fp,
error("at line %1: no picture filename.\n", baseline);
return;
}
- char *path;
- gfp = macro_path.open_file(gremlinfile, &path);
- if (!gfp)
- return;
- PICTURE = DBRead(gfp); /* read picture file */
- fclose(gfp);
- a_delete path;
+ {
+ file_case *fcp;
+ if ((fcp = macro_path.open_file(gremlinfile, fcp->fc_const_path)) == NULL)
+ return;
+ PICTURE = DBRead(fcp->file()); /* read picture file */
+ delete fcp;
+ }
if (DBNullelt(PICTURE))
return; /* If a request is made to make the */
/* picture fit into a specific area, */
diff --git a/src/preproc/html/pre-html.cpp b/src/preproc/html/pre-html.cpp
index fae164c..8c115ec 100644
--- a/src/preproc/html/pre-html.cpp
+++ b/src/preproc/html/pre-html.cpp
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 2000-2004, 2007-2009, 2012
+/* Copyright (C) 2000-2004, 2007-2009, 2012, 2014
* Free Software Foundation, Inc.
* Written by Gaius Mulley (address@hidden).
*
@@ -31,6 +31,7 @@
#include
#include "errarg.h"
#include "error.h"
+#include "file_case.h"
#include "stringclass.h"
#include "posix.h"
#include "defs.h"
@@ -293,22 +294,19 @@ int get_line(FILE *f)
static unsigned int get_resolution(void)
{
- char *pathp;
- FILE *f;
unsigned int res;
- f = font_path.open_file("devps/DESC", &pathp);
- a_delete pathp;
- if (f == 0)
+ file_case *fcp;
+ if ((fcp = font_path.open_file("devps/DESC", fcp->fc_const_path)) == NULL)
fatal("can't open devps/DESC");
- while (get_line(f)) {
+ while (get_line(fcp->file())) {
int n = sscanf(linebuf, "res %u", &res);
- if (n >= 1) {
- fclose(f);
- return res;
- }
+ if (n >= 1)
+ goto jleave;
}
fatal("can't find `res' keyword in devps/DESC");
- return 0;
+jleave:
+ delete fcp;
+ return res;
}
/*
diff --git a/src/preproc/soelim/soelim.cpp b/src/preproc/soelim/soelim.cpp
index 57732fd..0c0654d 100644
--- a/src/preproc/soelim/soelim.cpp
+++ b/src/preproc/soelim/soelim.cpp
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989-1992, 2000, 2001, 2003, 2004, 2005, 2009
+/* Copyright (C) 1989-1992, 2000, 2001, 2003, 2004, 2005, 2009, 2014
Free Software Foundation, Inc.
Written by James Clark (address@hidden)
@@ -26,6 +26,7 @@ along with this program. If not, see . */
#include
#include "errarg.h"
#include "error.h"
+#include "file_case.h"
#include "stringclass.h"
#include "nonposix.h"
#include "searchpath.h"
@@ -151,23 +152,20 @@ void do_so(const char *line)
int do_file(const char *filename)
{
- char *file_name_in_path = 0;
- FILE *fp = include_search_path.open_file_cautious(filename,
- &file_name_in_path);
- int err = errno;
- string whole_filename(file_name_in_path ? file_name_in_path : filename);
- whole_filename += '\0';
- a_delete file_name_in_path;
- if (fp == 0) {
- error("can't open `%1': %2", whole_filename.contents(), strerror(err));
- return 0;
+ int rv = 0;
+ enum { START, MIDDLE, HAD_DOT, HAD_s, HAD_so, HAD_l, HAD_lf } state = START;
+
+ file_case *fcp;
+ if ((fcp = include_search_path.open_file_cautious(filename)) == NULL) {
+ error("can't open `%1': %2", filename, strerror(errno));
+ goto jleave;
}
- current_filename = whole_filename.contents();
+
+ current_filename = fcp->path();
current_lineno = 1;
set_location();
- enum { START, MIDDLE, HAD_DOT, HAD_s, HAD_so, HAD_l, HAD_lf } state = START;
for (;;) {
- int c = getc(fp);
+ int c = getc(fcp->file());
if (c == EOF)
break;
switch (state) {
@@ -225,7 +223,7 @@ int do_file(const char *filename)
case HAD_so:
if (c == ' ' || c == '\n' || compatible_flag) {
string line;
- for (; c != EOF && c != '\n'; c = getc(fp))
+ for (; c != EOF && c != '\n'; c = getc(fcp->file()))
line += c;
current_lineno++;
line += '\n';
@@ -257,7 +255,7 @@ int do_file(const char *filename)
case HAD_lf:
if (c == ' ' || c == '\n' || compatible_flag) {
string line;
- for (; c != EOF && c != '\n'; c = getc(fp))
+ for (; c != EOF && c != '\n'; c = getc(fcp->file()))
line += c;
current_lineno++;
line += '\n';
@@ -276,6 +274,7 @@ int do_file(const char *filename)
assert(0);
}
}
+
switch (state) {
case HAD_DOT:
fputs(".\n", stdout);
@@ -298,8 +297,10 @@ int do_file(const char *filename)
case START:
break;
}
- if (fp != stdin)
- fclose(fp);
+
+ delete fcp;
current_filename = 0;
- return 1;
+ rv = 1;
+jleave:
+ return rv;
}
diff --git a/src/roff/troff/env.cpp b/src/roff/troff/env.cpp
index 6d722f5..f8d2ce3 100644
--- a/src/roff/troff/env.cpp
+++ b/src/roff/troff/env.cpp
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989-1992, 2000-2006, 2009, 2011
+/* Copyright (C) 1989-1992, 2000-2006, 2009, 2011, 2014
Free Software Foundation, Inc.
Written by James Clark (address@hidden)
@@ -24,6 +24,7 @@ along with this program. If not, see . */
#include "stringclass.h"
#include "mtsm.h"
#include "env.h"
+#include "file_case.h"
#include "request.h"
#include "node.h"
#include "token.h"
@@ -3827,42 +3828,42 @@ void hyphen_trie::read_patterns_file(const char *name, int append,
{
if (!append)
clear();
+
char buf[WORD_MAX];
for (int i = 0; i < WORD_MAX; i++)
buf[i] = 0;
int num[WORD_MAX+1];
- errno = 0;
- char *path = 0;
- FILE *fp = mac_path->open_file(name, &path);
- if (fp == 0) {
- error("can't find hyphenation patterns file `%1'", name);
- return;
- }
- int c = hpf_getc(fp);
int have_patterns = 0; // we've seen \patterns
int final_pattern = 0; // 1 if we have a trailing closing brace
int have_hyphenation = 0; // we've seen \hyphenation
int final_hyphenation = 0; // 1 if we have a trailing closing brace
int have_keyword = 0; // we've seen either \patterns or \hyphenation
int traditional = 0; // don't handle \patterns
- for (;;) {
+ int c;
+ file_case *fcp;
+ if ((fcp = mac_path->open_file(name, fcp->fc_const_path)) == NULL) {
+ error("can't find hyphenation patterns file `%1'", name);
+ goto jleave;
+ }
+
+ for (c = hpf_getc(fcp->file());;) {
for (;;) {
if (c == '%') { // skip comments
do {
- c = getc(fp);
+ c = getc(fcp->file());
} while (c != EOF && c != '\n');
}
if (c == EOF || !csspace(c))
break;
- c = hpf_getc(fp);
+ c = hpf_getc(fcp->file());
}
if (c == EOF) {
if (have_keyword || traditional) // we are done
break;
else { // rescan file in `traditional' mode
- rewind(fp);
+ rewind(fcp->file());
traditional = 1;
- c = hpf_getc(fp);
+ c = hpf_getc(fcp->file());
continue;
}
}
@@ -3876,14 +3877,14 @@ void hyphen_trie::read_patterns_file(const char *name, int append,
buf[i++] = c;
num[i] = 0;
}
- c = hpf_getc(fp);
+ c = hpf_getc(fcp->file());
} while (i < WORD_MAX && c != EOF && !csspace(c)
&& c != '%' && c != '{' && c != '}');
}
if (!traditional) {
if (i >= 9 && !strncmp(buf + i - 9, "\\patterns", 9)) {
while (csspace(c))
- c = hpf_getc(fp);
+ c = hpf_getc(fcp->file());
if (c == '{') {
if (have_patterns || have_hyphenation)
error("\\patterns not allowed inside of %1 group",
@@ -3892,13 +3893,13 @@ void hyphen_trie::read_patterns_file(const char *name, int append,
have_patterns = 1;
have_keyword = 1;
}
- c = hpf_getc(fp);
+ c = hpf_getc(fcp->file());
continue;
}
}
else if (i >= 12 && !strncmp(buf + i - 12, "\\hyphenation", 12)) {
while (csspace(c))
- c = hpf_getc(fp);
+ c = hpf_getc(fcp->file());
if (c == '{') {
if (have_patterns || have_hyphenation)
error("\\hyphenation not allowed inside of %1 group",
@@ -3907,7 +3908,7 @@ void hyphen_trie::read_patterns_file(const char *name, int append,
have_hyphenation = 1;
have_keyword = 1;
}
- c = hpf_getc(fp);
+ c = hpf_getc(fcp->file());
continue;
}
}
@@ -3928,19 +3929,19 @@ void hyphen_trie::read_patterns_file(const char *name, int append,
if (i > 0)
final_hyphenation = 1;
}
- c = hpf_getc(fp);
+ c = hpf_getc(fcp->file());
}
else if (c == '{') {
if (have_patterns || have_hyphenation)
error("`{' not allowed within %1 group",
have_patterns ? "\\patterns" : "\\hyphenation");
- c = hpf_getc(fp); // skipped if not starting \patterns
- // or \hyphenation
+ c = hpf_getc(fcp->file()); // skipped if not starting \patterns
+ // or \hyphenation
}
}
else {
if (c == '{' || c == '}')
- c = hpf_getc(fp);
+ c = hpf_getc(fcp->file());
}
if (i > 0) {
if (have_patterns || final_pattern || traditional) {
@@ -3955,8 +3956,9 @@ void hyphen_trie::read_patterns_file(const char *name, int append,
}
}
}
- fclose(fp);
- a_delete path;
+
+ delete fcp;
+jleave:
return;
}
diff --git a/src/roff/troff/input.cpp b/src/roff/troff/input.cpp
index b71f27e..932eecb 100644
--- a/src/roff/troff/input.cpp
+++ b/src/roff/troff/input.cpp
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989-1992, 2000-2011
+/* Copyright (C) 1989-1992, 2000-2011, 2014
Free Software Foundation, Inc.
Written by James Clark (address@hidden)
@@ -26,6 +26,7 @@ along with this program. If not, see . */
#include "stringclass.h"
#include "mtsm.h"
#include "env.h"
+#include "file_case.h"
#include "request.h"
#include "node.h"
#include "token.h"
@@ -229,7 +230,7 @@ private:
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(file_case *, const char *) { return 0; }
virtual void shift(int) {}
virtual int is_boundary() {return 0; }
virtual int is_file() { return 0; }
@@ -274,53 +275,48 @@ public:
};
class file_iterator : public input_iterator {
- FILE *fp;
+ file_case *_fcp;
int lineno;
const char *filename;
- int popened;
int newline_flag;
int seen_escape;
enum { BUF_SIZE = 512 };
unsigned char buf[BUF_SIZE];
void close();
public:
- file_iterator(FILE *, const char *, int = 0);
+ file_iterator(file_case *, const char *);
~file_iterator();
int fill(node **);
int peek();
int get_location(int, const char **, int *);
void backtrace();
int set_location(const char *, int);
- int next_file(FILE *, const char *);
+ int next_file(file_case *, const char *);
int is_file();
};
-file_iterator::file_iterator(FILE *f, const char *fn, int po)
-: fp(f), lineno(1), filename(fn), popened(po),
- newline_flag(0), seen_escape(0)
+file_iterator::file_iterator(file_case *fcp, const char *fn)
+: _fcp(fcp), lineno(1), filename(fn), newline_flag(0), seen_escape(0)
{
if ((font::use_charnames_in_special) && (fn != 0)) {
if (!the_output)
init_output();
- the_output->put_filename(fn, po);
+ the_output->put_filename(fn, _fcp->is_pipe());
}
}
file_iterator::~file_iterator()
{
- close();
+ if (_fcp != NULL)
+ delete _fcp;
}
void file_iterator::close()
{
- if (fp == stdin)
- clearerr(stdin);
-#ifndef POPEN_MISSING
- else if (popened)
- pclose(fp);
-#endif /* not POPEN_MISSING */
- else
- fclose(fp);
+ if (_fcp != NULL) {
+ delete _fcp;
+ _fcp = NULL;
+ }
}
int file_iterator::is_file()
@@ -328,15 +324,14 @@ int file_iterator::is_file()
return 1;
}
-int file_iterator::next_file(FILE *f, const char *s)
+int file_iterator::next_file(file_case *fcp, const char *s)
{
close();
+ _fcp = fcp;
filename = s;
- fp = f;
lineno = 1;
newline_flag = 0;
seen_escape = 0;
- popened = 0;
ptr = 0;
eptr = 0;
return 1;
@@ -351,7 +346,7 @@ int file_iterator::fill(node **)
ptr = p;
unsigned char *e = p + BUF_SIZE;
while (p < e) {
- int c = getc(fp);
+ int c = getc(_fcp->file());
if (c == EOF)
break;
if (invalid_input_char(c))
@@ -378,13 +373,13 @@ int file_iterator::fill(node **)
int file_iterator::peek()
{
- int c = getc(fp);
+ int c = getc(_fcp->file());
while (invalid_input_char(c)) {
warning(WARN_INPUT, "invalid input character code %1", int(c));
- c = getc(fp);
+ c = getc(_fcp->file());
}
if (c != EOF)
- ungetc(c, fp);
+ ungetc(c, _fcp->file());
return c;
}
@@ -402,7 +397,7 @@ int file_iterator::get_location(int /*allow_macro*/,
void file_iterator::backtrace()
{
errprint("%1:%2: backtrace: %3 `%1'\n", filename, lineno,
- popened ? "process" : "file");
+ _fcp->is_pipe() ? "process" : "file");
}
int file_iterator::set_location(const char *f, int ln)
@@ -434,7 +429,7 @@ public:
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(file_case *, const char *);
static void end_file();
static void shift(int n);
static void add_boundary();
@@ -719,15 +714,15 @@ int input_stack::set_location(const char *filename, int lineno)
return 0;
}
-void input_stack::next_file(FILE *fp, const char *s)
+void input_stack::next_file(file_case *fcp, const char *s)
{
input_iterator **pp;
for (pp = ⊤ *pp != &nil_iterator; pp = &(*pp)->next)
- if ((*pp)->next_file(fp, s))
+ if ((*pp)->next_file(fcp, s))
return;
if (++level > limit && limit > 0)
fatal("input stack limit exceeded");
- *pp = new file_iterator(fp, s);
+ *pp = new file_iterator(fcp, s);
(*pp)->next = &nil_iterator;
}
@@ -807,12 +802,13 @@ void next_file()
if (nm.is_null())
input_stack::end_file();
else {
- errno = 0;
- FILE *fp = include_search_path.open_file_cautious(nm.contents());
- if (!fp)
+ file_case *fcp = include_search_path.open_file_cautious(nm.contents(),
+ fcp->fc_const_path);
+ if (fcp != NULL) {
+ input_stack::next_file(fcp, nm.contents());
+ delete fcp;
+ } else
error("can't open `%1': %2", nm.contents(), strerror(errno));
- else
- input_stack::next_file(fp, nm.contents());
}
tok.next();
}
@@ -5940,10 +5936,9 @@ void source()
else {
while (!tok.newline() && !tok.eof())
tok.next();
- errno = 0;
- FILE *fp = include_search_path.open_file_cautious(nm.contents());
- if (fp)
- input_stack::push(new file_iterator(fp, nm.contents()));
+ file_case *fcp = include_search_path.open_file_cautious(nm.contents());
+ if (fcp != NULL)
+ input_stack::push(new file_iterator(fcp, nm.contents()));
else
error("can't open `%1': %2", nm.contents(), strerror(errno));
tok.next();
@@ -5989,11 +5984,14 @@ void pipe_source()
buf[buf_used] = '\0';
errno = 0;
FILE *fp = popen(buf, POPEN_RT);
- if (fp)
- input_stack::push(new file_iterator(fp, symbol(buf).contents(), 1));
- else
- error("can't open pipe to process `%1': %2", buf, strerror(errno));
- a_delete buf;
+ if (fp != NULL)
+ input_stack::push(new file_iterator(
+ new file_case(fp, buf, file_case::fc_pipe | file_case::fc_take_path),
+ symbol(buf).contents()));
+ else {
+ error("can't open pipe to process `%1': %2", buf, strerror(errno));
+ a_delete buf;
+ }
}
tok.next();
#endif /* not POPEN_MISSING */
@@ -6184,16 +6182,14 @@ void ps_bbox_request()
else {
while (!tok.newline() && !tok.eof())
tok.next();
- errno = 0;
// PS files might contain non-printable characters, such as ^Z
// and CRs not followed by an LF, so open them in binary mode.
- FILE *fp = include_search_path.open_file_cautious(nm.contents(),
- 0, FOPEN_RB);
- if (fp) {
- do_ps_file(fp, nm.contents());
- fclose(fp);
- }
- else
+ file_case *fcp = include_search_path.open_file_cautious(nm.contents(),
+ fcp->mux_need_seek | fcp->mux_need_binary);
+ if (fcp != NULL) {
+ do_ps_file(fcp->file(), nm.contents());
+ delete fcp;
+ } else
error("can't open `%1': %2", nm.contents(), strerror(errno));
tok.next();
}
@@ -7324,26 +7320,26 @@ void transparent_file()
if (break_flag)
curenv->do_break();
if (!filename.is_null()) {
- errno = 0;
- FILE *fp = include_search_path.open_file_cautious(filename.contents());
- if (!fp)
+ file_case *fcp = include_search_path
+ .open_file_cautious(filename.contents());
+ if (fcp == NULL)
error("can't open `%1': %2", filename.contents(), strerror(errno));
else {
int bol = 1;
for (;;) {
- int c = getc(fp);
- if (c == EOF)
- break;
- if (invalid_input_char(c))
- warning(WARN_INPUT, "invalid input character code %1", int(c));
- else {
- curdiv->transparent_output(c);
- bol = c == '\n';
- }
+ int c = getc(fcp->file());
+ if (c == EOF)
+ break;
+ if (invalid_input_char(c))
+ warning(WARN_INPUT, "invalid input character code %1", int(c));
+ else {
+ curdiv->transparent_output(c);
+ bol = c == '\n';
+ }
}
if (!bol)
- curdiv->transparent_output('\n');
- fclose(fp);
+ curdiv->transparent_output('\n');
+ delete fcp;
}
}
tok.next();
@@ -7421,46 +7417,41 @@ static void parse_output_page_list(char *p)
}
}
-static FILE *open_mac_file(const char *mac, char **path)
+static file_case *open_mac_file(const char *mac)
{
// Try first FOOBAR.tmac, then tmac.FOOBAR
- char *s1 = new char[strlen(mac)+strlen(MACRO_POSTFIX)+1];
- strcpy(s1, mac);
- strcat(s1, MACRO_POSTFIX);
- FILE *fp = mac_path->open_file(s1, path);
- a_delete s1;
- if (!fp) {
- char *s2 = new char[strlen(mac)+strlen(MACRO_PREFIX)+1];
- strcpy(s2, MACRO_PREFIX);
- strcat(s2, mac);
- fp = mac_path->open_file(s2, path);
- a_delete s2;
+ char *s = new char[strlen(mac) + strlen(MACRO_POSTFIX) +1];
+ strcpy(s, mac);
+ strcat(s, MACRO_POSTFIX);
+
+ file_case *fcp;
+ if ((fcp = mac_path->open_file(s, fcp->fc_take_path)) == NULL) {
+ s = new char[strlen(mac) + strlen(MACRO_PREFIX) +1];
+ strcpy(s, MACRO_PREFIX);
+ strcat(s, mac);
+ fcp = mac_path->open_file(s, fcp->fc_take_path);
}
- return fp;
+ return fcp;
}
static void process_macro_file(const char *mac)
{
- char *path;
- FILE *fp = open_mac_file(mac, &path);
- if (!fp)
+ file_case *fcp = open_mac_file(mac);
+ if (fcp == NULL)
fatal("can't find macro file %1", mac);
- const char *s = symbol(path).contents();
- a_delete path;
- input_stack::push(new file_iterator(fp, s));
+ const char *s = symbol(fcp->path()).contents();
+ input_stack::push(new file_iterator(fcp, s));
tok.next();
process_input_stack();
}
static void process_startup_file(const char *filename)
{
- char *path;
search_path *orig_mac_path = mac_path;
mac_path = &config_macro_path;
- FILE *fp = mac_path->open_file(filename, &path);
- if (fp) {
- input_stack::push(new file_iterator(fp, symbol(path).contents()));
- a_delete path;
+ file_case *fcp;
+ if ((fcp = mac_path->open_file(filename)) != NULL) {
+ input_stack::push(new file_iterator(fcp, symbol(fcp->path()).contents()));
tok.next();
process_input_stack();
}
@@ -7475,35 +7466,33 @@ void macro_source()
else {
while (!tok.newline() && !tok.eof())
tok.next();
- char *path;
- FILE *fp = mac_path->open_file(nm.contents(), &path);
// .mso doesn't (and cannot) go through open_mac_file, so we
// need to do it here manually: If we have tmac.FOOBAR, try
// FOOBAR.tmac and vice versa
- if (!fp) {
+ file_case *fcp;
+ if ((fcp = mac_path->open_file(nm.contents())) == NULL) {
const char *fn = nm.contents();
+
if (strncasecmp(fn, MACRO_PREFIX, sizeof(MACRO_PREFIX) - 1) == 0) {
- char *s = new char[strlen(fn) + sizeof(MACRO_POSTFIX)];
- strcpy(s, fn + sizeof(MACRO_PREFIX) - 1);
- strcat(s, MACRO_POSTFIX);
- fp = mac_path->open_file(s, &path);
- a_delete s;
+ char *s = new char[strlen(fn) + sizeof(MACRO_POSTFIX)];
+ strcpy(s, fn + sizeof(MACRO_PREFIX) - 1);
+ strcat(s, MACRO_POSTFIX);
+ fcp = mac_path->open_file(s, fcp->fc_take_path);
}
- if (!fp) {
- if (strncasecmp(fn + strlen(fn) - sizeof(MACRO_POSTFIX) + 1,
- MACRO_POSTFIX, sizeof(MACRO_POSTFIX) - 1) == 0) {
- char *s = new char[strlen(fn) + sizeof(MACRO_PREFIX)];
- strcpy(s, MACRO_PREFIX);
- strncat(s, fn, strlen(fn) - sizeof(MACRO_POSTFIX) + 1);
- fp = mac_path->open_file(s, &path);
- a_delete s;
- }
+
+ if (fcp == NULL) {
+ if (strncasecmp(fn + strlen(fn) - sizeof(MACRO_POSTFIX) + 1,
+ MACRO_POSTFIX, sizeof(MACRO_POSTFIX) - 1) == 0) {
+ char *s = new char[strlen(fn) + sizeof(MACRO_PREFIX)];
+ strcpy(s, MACRO_PREFIX);
+ strncat(s, fn, strlen(fn) - sizeof(MACRO_POSTFIX) + 1);
+ fcp = mac_path->open_file(s, fcp->fc_take_path);
+ }
}
}
- if (fp) {
- input_stack::push(new file_iterator(fp, symbol(path).contents()));
- a_delete path;
- }
+
+ if (fcp != NULL)
+ input_stack::push(new file_iterator(fcp, symbol(fcp->path()).contents()));
else
warning(WARN_FILE, "can't find macro file `%1'", nm.contents());
tok.next();
@@ -7512,18 +7501,16 @@ void macro_source()
static void process_input_file(const char *name)
{
- FILE *fp;
+ file_case *fcp;
if (strcmp(name, "-") == 0) {
clearerr(stdin);
- fp = stdin;
- }
- else {
- errno = 0;
- fp = include_search_path.open_file_cautious(name);
- if (!fp)
+ fcp = new file_case(stdin, "stdin",
+ fcp->fc_dont_close | fcp->fc_const_path);
+ } else {
+ if ((fcp = include_search_path.open_file_cautious(name)) == NULL)
fatal("can't open `%1': %2", name, strerror(errno));
}
- input_stack::push(new file_iterator(fp, name));
+ input_stack::push(new file_iterator(fcp, name));
tok.next();
process_input_stack();
}
diff --git a/src/roff/troff/node.cpp b/src/roff/troff/node.cpp
index 311a5cd..9b27f12 100644
--- a/src/roff/troff/node.cpp
+++ b/src/roff/troff/node.cpp
@@ -1,6 +1,6 @@
// -*- C++ -*-
/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002, 2003, 2004, 2005,
- 2006, 2008, 2009, 2010
+ 2006, 2008, 2009, 2010, 2014
Free Software Foundation, Inc.
Written by James Clark (address@hidden)
@@ -32,6 +32,7 @@ extern int debug_state;
#include "stringclass.h"
#include "mtsm.h"
#include "env.h"
+#include "file_case.h"
#include "request.h"
#include "node.h"
#include "token.h"
@@ -1551,16 +1552,17 @@ void troff_output_file::really_copy_file(hunits x, vunits y,
moveto(x, y);
flush_tbuf();
do_motion();
- errno = 0;
- FILE *ifp = include_search_path.open_file_cautious(filename);
- if (ifp == 0)
- error("can't open `%1': %2", filename, strerror(errno));
- else {
+
+ file_case *fcp = include_search_path.open_file_cautious(filename,
+ fcp->fc_const_path);
+ if (fcp != NULL) {
int c;
- while ((c = getc(ifp)) != EOF)
+ while ((c = getc(fcp->file())) != EOF)
put(char(c));
- fclose(ifp);
- }
+ delete fcp;
+ } else
+ error("can't open `%1': %2", filename, strerror(errno));
+
force_motion = 1;
current_size = 0;
current_tfont = 0;
--
2.0.0
From ea111b9221aff011f2f57aad2da74f8f1936026e Mon Sep 17 00:00:00 2001
Message-Id:
In-Reply-To:
References:
From: Steffen Nurpmeso
Date: Fri, 25 Jul 2014 15:53:27 +0200
Subject: [PATCH 04/20] Add GROFF_UNPACK_CHECK m4++ / --with-unpack=XY (Public
Domain)
---
Makefile.in | 14 ++++++++++++++
configure.ac | 1 +
m4/groff.m4 | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
3 files changed, 68 insertions(+), 3 deletions(-)
diff --git a/Makefile.in b/Makefile.in
index 0abc86e..d76c57d 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -406,6 +406,10 @@ address@hidden@
# -DGHOSTSCRIPT=gs the name (and directory if required) of the
# ghostscript program
#
+# -DHAVE_UNPACK_BZ2 if unpacking via bzip2(1) is supported
+# -DHAVE_UNPACK_GZ if unpacking via gzip(1) is supported
+# -DHAVE_UNPACK_XZ if unpacking via xz(1) is supported
+#
address@hidden@
# Include
@@ -469,6 +473,12 @@ address@hidden@
# Sed script to deal with OS dependencies in sh scripts.
SH_DEPS_SED_SCRIPT=$(top_builddir)/arch/misc/shdeps.sed
+# Unpacker support
address@hidden@
address@hidden@
address@hidden@
address@hidden@
+
# The program to create directory hierarchies.
mkinstalldirs= $(SHELL) $(top_srcdir)/mkinstalldirs
@@ -501,6 +511,10 @@ MDEFINES=\
"EXEEXT=$(EXEEXT)" \
"GLIBC21=$(GLIBC21)" \
"GREP=$(GREP)" \
+ "HAVE_UNPACK=$(HAVE_UNPACK)" \
+ "HAVE_UNPACK_BZ2=$(HAVE_UNPACK_BZ2)" \
+ "HAVE_UNPACK_GZ=$(HAVE_UNPACK_GZ)" \
+ "HAVE_UNPACK_XZ=$(HAVE_UNPACK_XZ)" \
"HOST=$(HOST)" \
"INSTALL_DATA=$(INSTALL_DATA)" \
"INSTALL_INFO=$(INSTALL_INFO)" \
diff --git a/configure.ac b/configure.ac
index a11f879..b918d6e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -65,6 +65,7 @@ GROFF_GROFFERDIR_OPTION
GROFF_GROFFERDIR_DEFAULT
GROFF_GLILYPONDDIR_DEFAULT
GROFF_GROGDIR_DEFAULT
+GROFF_UNPACK_CHECK
GROFF_PERL
GROFF_PRINT
AC_PROG_EGREP
diff --git a/m4/groff.m4 b/m4/groff.m4
index 6021c22..ffc2f3c 100644
--- a/m4/groff.m4
+++ b/m4/groff.m4
@@ -71,14 +71,64 @@ AC_DEFUN([GROFF_PERL],
AC_MSG_ERROR([perl version is too old], 1))])
+# It is possible to directly use compressed files
+AC_DEFUN([GROFF_UNPACK_CHECK],
+ [AC_ARG_WITH([unpack],
+ [AS_HELP_STRING([--with-unpack[[=TYPE]]],
+ [choose wether support for unpacking of compressed files is desirable.
+ TYPE can be `yes' or `no', or a comma-separated list of one or
+ multiple of `bz2', `gz' and `xz', to restrict what can be unpacked])],
+ [unpack="$withval"],
+ [unpack=yes])
+ test "x$unpack" = xno && unpack=''
+
+ if test "x$unpack" = xyes; then
+ HAVE_UNPACK=1
+ HAVE_UNPACK_BZ2=1
+ HAVE_UNPACK_GZ=1
+ HAVE_UNPACK_XZ=1
+ else
+ # Don't use case/esac, verify input.
+ HAVE_UNPACK=0
+ HAVE_UNPACK_BZ2=0
+ HAVE_UNPACK_GZ=0
+ HAVE_UNPACK_XZ=0
+ OFS=$IFS
+ IFS=','
+ set -- $unpack
+ IFS=$OFS
+ for i
+ do
+ test "x$i" = xbz2 && { HAVE_UNPACK=1; HAVE_UNPACK_BZ2=1; continue; }
+ test "x$i" = xgz && { HAVE_UNPACK=1; HAVE_UNPACK_GZ=1; continue; }
+ test "x$i" = xxz && { HAVE_UNPACK=1; HAVE_UNPACK_XZ=1; continue; }
+ AC_MSG_WARN([Invalid `--with-unpack' argument:] $i)
+ done
+ fi
+
+ AC_SUBST([HAVE_UNPACK])
+ test $HAVE_UNPACK -eq 1 &&
+ AC_DEFINE([HAVE_UNPACK], [1], [Define if you have any unpacker support.])
+ AC_SUBST([HAVE_UNPACK_BZ2])
+ test $HAVE_UNPACK_BZ2 -eq 1 &&
+ AC_DEFINE([HAVE_UNPACK_BZ2], [1], [Define if you have bzip2 support.])
+ AC_SUBST([HAVE_UNPACK_GZ])
+ test $HAVE_UNPACK_GZ -eq 1 &&
+ AC_DEFINE([HAVE_UNPACK_GZ], [1], [Define if you have gzip support.])
+ AC_SUBST([HAVE_UNPACK_XZ])
+ test $HAVE_UNPACK_XZ &&
+ AC_DEFINE([HAVE_UNPACK_XZ], [1], [Define if you have xz support.])
+])
+
+
# It is possible to fine-tune generation of documenation.
AC_DEFUN([GROFF_DOC_CHECK],
[AC_ARG_WITH([doc],
[AS_HELP_STRING([--with-doc[[=TYPE]]],
- [choose which manuals (beside man pages) are desirable. \
- TYPE can be `yes' or `no', or a comma-separated list of \
- one or multiple of `html', `info', `other', `pdf', and \
+ [choose which manuals (beside man pages) are desirable.
+ TYPE can be `yes' or `no', or a comma-separated list of
+ one or multiple of `html', `info', `other', `pdf', and
`examples', to restrict what is produced])],
[doc="$withval"],
[doc=yes])
--
2.0.0
From 6ed7720614630f1f70a229ed150fd3975e0bc138 Mon Sep 17 00:00:00 2001
Message-Id:
In-Reply-To:
References:
From: Steffen Nurpmeso
Date: Sat, 26 Jul 2014 22:04:38 +0200
Subject: [PATCH 05/20] file_case: support transparent file decompression
(Public Domain)..
Since now file decompression can optionally be supported for all
files which get opened via file_case{,::muxer()} this changeset in
effect adds support for GNU troff(1) installations where each file
is compressed. (It depends on file_case::_mux_unpack_default if
this is actually true -- it is mux_unpack now, but changing it to
::mux_no_unpack will reduce compression support to those
facilities which *explicitly* specify mux_unpack, which this
changeset only uses for the `.so' request.)
Inspired by a commit from Matthew Dillon (dillon AT apollo DOT
backplane DOT com) of DragonFly BSD ([84d7c06], 2014-05-20).
---
src/devices/gropdf/Makefile.sub | 4 +
src/devices/gropdf/gropdf.pl | 56 ++++++---
src/include/file_case.h | 7 +-
src/libs/libgroff/file_case.cpp | 243 ++++++++++++++++++++++++++++++++++++++--
src/roff/troff/input.cpp | 3 +-
5 files changed, 283 insertions(+), 30 deletions(-)
diff --git a/src/devices/gropdf/Makefile.sub b/src/devices/gropdf/Makefile.sub
index c587dc5..57c3c70 100644
--- a/src/devices/gropdf/Makefile.sub
+++ b/src/devices/gropdf/Makefile.sub
@@ -39,6 +39,10 @@ gropdf: gropdf.pl $(SH_DEPS_SED_SCRIPT)
-e "s|@VERSION@|$(version)$(revision)|" \
-e "s|@PERL@|$(PERL)|" \
-e "s|@GROFF_FONT_DIR@|$(fontpath)|" \
+ -e "s|@HAVE_UNPACK@|$(HAVE_UNPACK)|" \
+ -e "s|@HAVE_UNPACK_BZ2@|$(HAVE_UNPACK_BZ2)|" \
+ -e "s|@HAVE_UNPACK_GZ@|$(HAVE_UNPACK_GZ)|" \
+ -e "s|@HAVE_UNPACK_XZ@|$(HAVE_UNPACK_XZ)|" \
-e "s|@RT_SEP@|$(RT_SEP)|" $(srcdir)/gropdf.pl >$@
chmod +x $@
diff --git a/src/devices/gropdf/gropdf.pl b/src/devices/gropdf/gropdf.pl
index f18bac8..1b6d256 100644
--- a/src/devices/gropdf/gropdf.pl
+++ b/src/devices/gropdf/gropdf.pl
@@ -3,7 +3,7 @@
# gropdf : PDF post processor for groff
# Last update : 15 Apr 2013
#
-# Copyright (C) 2011-2013
+# Copyright (C) 2011-2014
# Free Software Foundation, Inc.
# Written by Deri James
#
@@ -547,21 +547,45 @@ sub LoadDownload
sub OpenFile
{
- my $f=shift;
- my $dirs=shift;
- my $fnm=shift;
-
- if (substr($fnm,0,1) eq '/' or substr($fnm,1,1) eq ':') # dos
- {
- return if -r "$fnm" and open($$f,"<$fnm");
- }
-
- my (@dirs)=split($cfg{RT_SEP},$dirs);
-
- foreach my $dir (@dirs)
- {
- last if -r "$dir/$devnm/$fnm" and open($$f,"<$dir/$devnm/$fnm");
- }
+ sub __open {
+ my $fh = shift;
+ my $p = shift;
+
+ if ($p =~ /.*\.(gz|bz2|xz)$/) {
+ if (@HAVE_UNPACK@) {
+ return open($$fh, "bzip2 -cdf $p|")
+ if @HAVE_UNPACK_BZ2@ && $1 eq 'bz2' && -r $p;
+ return open($$fh, "gzip -cdf $p|")
+ if @HAVE_UNPACK_GZ@ && $1 eq 'gz' && -r $p;
+ return open($$fh, "xz -cdf $p|")
+ if @HAVE_UNPACK_XZ@ && $1 eq 'xz' && -r $p;
+ }
+ } else {
+ return open($$fh, "$p") if -r $p;
+ if (@HAVE_UNPACK@) {
+ return open($$fh, "bzip2 -cdf $p.bz2|")
+ if @HAVE_UNPACK_BZ2@ && -r "$p.bz2";
+ return open($$fh, "gzip -cdf $p.gz|")
+ if @HAVE_UNPACK_GZ@ && -r "$p.gz";
+ return open($$fh, "xz -cdf $p.xz|")
+ if @HAVE_UNPACK_XZ@ && -r "$p.xz";
+ }
+ }
+ return undef;
+ }
+
+ my $f = shift;
+ my $dirs = shift;
+ my $fnm = shift;
+
+ if (substr($fnm,0,1) eq '/' || substr($fnm,1,1) eq ':') { # dos
+ return if __open($f, $fnm);
+ }
+
+ my (@dirs) = split($cfg{RT_SEP},$dirs);
+ foreach my $dir (@dirs) {
+ return if __open($f, "$dir/$devnm/$fnm");
+ }
}
sub LoadDesc
diff --git a/src/include/file_case.h b/src/include/file_case.h
index a52d121..7ea3f86 100644
--- a/src/include/file_case.h
+++ b/src/include/file_case.h
@@ -45,8 +45,13 @@ public:
enum {
mux_need_seek = 1<<(_fc_freebit+0), // File must be seekable
mux_need_binary = 1<<(_fc_freebit+1), // Need binary I/O
+ mux_unpack = 1<<(_fc_freebit+2), // Do auto-check for FILE{.gz,.bz2..}
+ mux_no_unpack = 1<<(_fc_freebit+3), // Do NOT auto-check
+ mux_mask = ~fc_mask,
mux_default = fc_none,
- mux_mask = ~fc_mask
+ // Defines the global default strategy for dealing with packed files in case
+ // none of the above has been given explicitly by a callee
+ _mux_unpack_default = mux_unpack
};
file_case(FILE *fp, char const *path, uint32_t flags=fc_none);
diff --git a/src/libs/libgroff/file_case.cpp b/src/libs/libgroff/file_case.cpp
index 51bc2f2..5fdbd1f 100644
--- a/src/libs/libgroff/file_case.cpp
+++ b/src/libs/libgroff/file_case.cpp
@@ -23,8 +23,190 @@
#include
#include
+#include "errarg.h"
+#include "error.h"
+#include "posix.h"
+#include "nonposix.h"
+
#include "file_case.h"
+// Support decompression XXX configure should say `no popen() - no unpacking'
+#ifdef POPEN_MISSING
+# undef HAVE_UNPACK
+#endif
+
+struct args {
+ FILE *a_fp;
+ char const *a_path;
+ size_t a_path_len;
+ char const *a_mode; // Mode for fopen(3), if used
+ uint32_t a_flags;
+ int32_t a_errno;
+};
+
+#ifdef HAVE_UNPACK
+struct zproc {
+ uint8_t zp_popen;
+ uint8_t zp_ext_len; // Extension including `.' ()
+ uint8_t zp_cmd_len;
+ char zp_ext[5];
+ char zp_cmd[16];
+};
+
+static zproc const _zprocs[] = {
+# define __X(C,E) {true, sizeof(E) -1, sizeof(C) -1, E, C}
+# ifdef HAVE_UNPACK_BZ2
+ __X("bzip2 -cdf", ".bz2"),
+# endif
+# ifdef HAVE_UNPACK_GZ
+ __X("gzip -cdf", ".gz"),
+# endif
+# ifdef HAVE_UNPACK_XZ
+ __X("xz -cdf", ".xz")
+# endif
+# undef __X
+};
+#endif // HAVE_UNPACK
+
+#ifdef HAVE_UNPACK
+// Check wether path was explicitly specified with a packer extension.
+// This returns a ternary: false only if we knew the extension, applied the
+// zproc and that failed to perform, true otherwise (ap->a_fp is 2nd indicator)
+static bool _is_ext(args *ap);
+
+// Plain file didn't exist, iterate over the supported packer extensions
+// and see if a matching file exists instead; NULL if not / on error.
+// Note that ap->a_errno is ENOENT on entry and only overwritten if we run
+// a zproc and that fails XXX ENOENT is blindly used in codebase, but not ISO C
+static bool _try_all_ext(args *ap);
+
+// Create a FILE* according to zp, return NULL on error
+static args * __run_zproc(args *ap, zproc const *zp);
+
+// Callee needs seek()ing, unpack into temporary file, return NULL on error
+static args * __unpack(args *ap);
+#endif // HAVE_UNPACK
+
+#ifdef HAVE_UNPACK
+static bool
+_is_ext(args *ap)
+{
+ for (zproc const *zp = _zprocs; zp < _zprocs + NELEM(_zprocs); ++zp) {
+ size_t el = zp->zp_ext_len;
+
+ if (ap->a_path_len <= el)
+ continue;
+ if (memcmp(ap->a_path + ap->a_path_len - el, zp->zp_ext, el))
+ continue;
+
+ ap = __run_zproc(ap, zp);
+ break;
+ }
+ return (ap != NULL);
+}
+
+static bool
+_try_all_ext(args *ap)
+{
+ for (zproc const *zp = _zprocs; zp < _zprocs + NELEM(_zprocs); ++zp) {
+ char *np = new char[zp->zp_cmd_len +1+ ap->a_path_len + zp->zp_ext_len +1];
+
+ memcpy(np, ap->a_path, ap->a_path_len);
+
+ struct ::stat sb;
+ memcpy(np + ap->a_path_len, zp->zp_ext, zp->zp_ext_len +1);
+ if (stat(np, &sb)) {
+ a_delete np;
+ continue;
+ }
+
+ // That's our zproc, let it make the deal
+ char const *pb_save = ap->a_path;
+ size_t pl_save = ap->a_path_len;
+ ap->a_path = np;
+ ap->a_path_len = pl_save + zp->zp_ext_len;
+ if ((ap = __run_zproc(ap, zp)) != NULL) {
+ ap->a_path = pb_save;
+ ap->a_path_len = pl_save;
+ }
+ a_delete np;
+ goto jleave;
+ }
+ ap = NULL;
+jleave:
+ return (ap != NULL);
+}
+
+static args *
+__run_zproc(args *ap, zproc const *zp)
+{
+ char *np = new char[zp->zp_cmd_len + 1 + ap->a_path_len +1];
+
+ size_t l;
+ memcpy(np, zp->zp_cmd, l = zp->zp_cmd_len);
+ np[l++] = ' ';
+ memcpy(np + l, ap->a_path, ap->a_path_len +1);
+
+ if ((ap->a_fp = popen(np, "r")) == NULL) {
+ ap->a_errno = errno;
+ ap = NULL;
+ } else if (ap->a_flags & file_case::mux_need_seek)
+ ap = __unpack(ap);
+ else
+ ap->a_flags |= file_case::fc_pipe;
+
+ a_delete np;
+ return ap;
+}
+
+static args *
+__unpack(args *ap)
+{
+ size_t const buf_len = (BUFSIZ + 0) > 1 << 15 ? BUFSIZ : 1 << 15;
+ uint8_t *buf = new uint8_t[buf_len];
+
+ // xtmpfile uses binary mode and fatal()s on error
+ FILE *decomp = xtmpfile(NULL, "groff_unpack"), *decomp_save = decomp;
+ for (;;) {
+ size_t oc = fread(buf, sizeof *buf, buf_len, ap->a_fp);
+ if (oc == 0) {
+ if (!feof(ap->a_fp)) {
+ ap->a_errno = errno;
+ decomp = NULL;
+ }
+ break;
+ }
+
+ if (decomp != NULL) {
+ for (uint8_t *target = buf; oc > 0;) {
+ size_t i = fwrite(target, sizeof *buf, oc, decomp);
+ if (i == 0)
+ break;
+ oc -= i;
+ target += i;
+ }
+ if (oc > 0) {
+ ap->a_errno = errno;
+ decomp = NULL;
+ }
+ }
+ }
+ if (pclose(ap->a_fp) != 0)
+ error("decompressor pipe pclose(3) didn't exit cleanly");
+
+ if (decomp != NULL)
+ rewind(ap->a_fp = decomp);
+ else {
+ fclose(decomp_save);
+ ap->a_fp = NULL;
+ ap = NULL;
+ }
+
+ a_delete buf;
+ return ap;
+}
+#endif // HAVE_UNPACK
+
bool
file_case::close(void)
{
@@ -36,6 +218,10 @@ file_case::close(void)
bool rv;
if (_flags & fc_dont_close)
rv = true;
+#ifdef HAVE_UNPACK
+ else if (_flags & fc_pipe)
+ rv = (pclose(_file) == 0);
+#endif
else
rv = (fclose(_file) == 0);
@@ -53,25 +239,58 @@ file_case::muxer(char const *path, uint32_t flags)
assert(!(flags & (fc_dont_close | fc_pipe)));
assert(!(flags & (fc_const_path | fc_take_path)) ||
!(flags & fc_const_path) != !(flags & fc_take_path));
+ assert(!(flags & (mux_unpack | mux_no_unpack)) ||
+ !(flags & mux_unpack) != !(flags & mux_no_unpack));
if (!(flags & (fc_const_path | fc_take_path))) {
path = strsave(path);
flags |= fc_take_path;
}
+ if (!(flags & (mux_unpack | mux_no_unpack)))
+ flags |= _mux_unpack_default;
- errno = 0;
- FILE *fp = fopen(path, ((flags & mux_need_binary) ? "rb" : "r"));
- int save_err = errno;
-
- flags &= ~mux_mask;
file_case *fcp;
- if (fp != NULL)
- fcp = new file_case(fp, path, flags);
- else {
- if (!(flags & fc_const_path))
- a_delete path;
- errno = save_err;
- fcp = NULL;
+ args a;
+ a.a_fp = NULL;
+ a.a_path_len = strlen(a.a_path = path);
+ a.a_mode = (flags & mux_need_binary) ? "rb" : "r";
+ a.a_flags = flags;
+ a.a_errno = 0;
+
+ // If we support unpacking then check wether the path already includes
+ // a packer's extension, i.e., explicitly. Anyway unpack then, despite flags
+#ifdef HAVE_UNPACK
+ if (!_is_ext(&a)) {
+ assert(a.a_fp == NULL);
+ goto jerror;
}
+ if (a.a_fp != NULL)
+ goto jnew;
+#endif
+
+ // Try a plain open
+ errno = 0;
+ if ((a.a_fp = fopen(a.a_path, a.a_mode)) != NULL) {
+#ifdef HAVE_UNPACK
+jnew:
+#endif
+ assert(a.a_fp != NULL);
+ fcp = new file_case(a.a_fp, path, a.a_flags & ~mux_mask); // XXX real path?
+ goto jleave;
+ }
+ a.a_errno = errno;
+
+ // Then auto-expand the given path if so desired
+#ifdef HAVE_UNPACK
+ if (a.a_errno == ENOENT && (a.a_flags & mux_unpack) && _try_all_ext(&a))
+ goto jnew;
+
+jerror:
+#endif
+ if (!(a.a_flags & fc_const_path))
+ a_delete a.a_path;
+ errno = a.a_errno;
+ fcp = NULL;
+jleave:
return fcp;
}
diff --git a/src/roff/troff/input.cpp b/src/roff/troff/input.cpp
index 932eecb..9458682 100644
--- a/src/roff/troff/input.cpp
+++ b/src/roff/troff/input.cpp
@@ -5936,7 +5936,8 @@ void source()
else {
while (!tok.newline() && !tok.eof())
tok.next();
- file_case *fcp = include_search_path.open_file_cautious(nm.contents());
+ file_case *fcp = include_search_path.open_file_cautious(nm.contents(),
+ fcp->mux_unpack);
if (fcp != NULL)
input_stack::push(new file_iterator(fcp, nm.contents()));
else
--
2.0.0
From f605d82bb09f5ee04b470b81e8038f4cf09b2094 Mon Sep 17 00:00:00 2001
Message-Id:
In-Reply-To:
References:
From: Steffen Nurpmeso
Date: Sat, 26 Jul 2014 23:12:55 +0200
Subject: [PATCH 06/20] file_case: add read interface, extend abstraction
(Public Domain)..
Encapsulate I/O reads under the file_case surface in order to
implement a decompression layer that doesn't use external unpack
programs but instead directly uses and links against the libraries
which implement the decompression algorithms.
Add new file_case::mux_need_stdio (and ::fc_have_stdio) flags
which henceforth will be required in order to access the .file()
a.k.a STD I/O FILE* of an object, for those rare cases (only the
grn(1) gremlin preprocessor) where the file_case user needs a
FILE* for extended operations which we don't support in file_case,
e.g. fscanf(3).
---
src/devices/grops/ps.cpp | 2 +-
src/devices/grops/ps.h | 42 +++++++-------
src/devices/grops/psrm.cpp | 118 +++++++++++++++++++--------------------
src/include/file_case.h | 27 +++++++--
src/libs/libgroff/file_case.cpp | 54 ++++++++++++++++++
src/libs/libgroff/font.cpp | 2 +-
src/libs/libgroff/searchpath.cpp | 2 +-
src/preproc/eqn/main.cpp | 56 ++++++++++---------
src/preproc/grn/main.cpp | 7 ++-
src/preproc/html/pre-html.cpp | 12 ++--
src/preproc/soelim/soelim.cpp | 6 +-
src/roff/troff/env.cpp | 42 +++++++-------
src/roff/troff/input.cpp | 34 +++++------
src/roff/troff/node.cpp | 2 +-
14 files changed, 241 insertions(+), 165 deletions(-)
diff --git a/src/devices/grops/ps.cpp b/src/devices/grops/ps.cpp
index b4306a8..c34b7cd 100644
--- a/src/devices/grops/ps.cpp
+++ b/src/devices/grops/ps.cpp
@@ -792,7 +792,7 @@ void ps_printer::define_encoding(const char *encoding, int encoding_index)
const int BUFFER_SIZE = 512;
char buf[BUFFER_SIZE];
- for (int lineno = 1; fgets(buf, BUFFER_SIZE, fcp->file()) != NULL; ++lineno) {
+ for (int lineno = 1; fcp->get_line(buf, BUFFER_SIZE) != NULL; ++lineno) {
char *p = buf;
while (csspace(*p))
p++;
diff --git a/src/devices/grops/ps.h b/src/devices/grops/ps.h
index 9e592ae..15d5b3e 100644
--- a/src/devices/grops/ps.h
+++ b/src/devices/grops/ps.h
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989-1992, 2002, 2003, 2009, 2013
+/* Copyright (C) 1989-1992, 2002, 2003, 2009, 2013, 2014
Free Software Foundation, Inc.
Written by James Clark (address@hidden)
@@ -87,30 +87,30 @@ private:
unsigned revision = 0);
resource *lookup_font(const char *name);
void read_download_file();
- void supply_resource(resource *r, int rank, FILE *outfp,
- int is_document = 0);
- void process_file(int rank, FILE *fp, const char *filename, FILE *outfp);
+ void supply_resource(resource *r, int rank, FILE *ofp, int is_document = 0);
+ void process_file(int rank, file_case *fcp, FILE *ofp);
resource *read_file_arg(const char **);
resource *read_procset_arg(const char **);
resource *read_font_arg(const char **);
resource *read_resource_arg(const char **);
- void print_resources_comment(unsigned flag, FILE *outfp);
- void print_extensions_comment(FILE *outfp);
- void print_language_level_comment(FILE *outfp);
- int do_begin_resource(const char *ptr, int rank, FILE *fp, FILE *outfp);
- int do_include_resource(const char *ptr, int rank, FILE *fp, FILE *outfp);
- int do_begin_document(const char *ptr, int rank, FILE *fp, FILE *outfp);
- int do_include_document(const char *ptr, int rank, FILE *fp, FILE *outfp);
- int do_begin_procset(const char *ptr, int rank, FILE *fp, FILE *outfp);
- int do_include_procset(const char *ptr, int rank, FILE *fp, FILE *outfp);
- int do_begin_font(const char *ptr, int rank, FILE *fp, FILE *outfp);
- int do_include_font(const char *ptr, int rank, FILE *fp, FILE *outfp);
- int do_begin_file(const char *ptr, int rank, FILE *fp, FILE *outfp);
- int do_include_file(const char *ptr, int rank, FILE *fp, FILE *outfp);
- int change_to_end_resource(const char *ptr, int rank, FILE *fp, FILE *outfp);
- int do_begin_preview(const char *ptr, int rank, FILE *fp, FILE *outfp);
- int do_begin_data(const char *ptr, int rank, FILE *fp, FILE *outfp);
- int do_begin_binary(const char *ptr, int rank, FILE *fp, FILE *outfp);
+ void print_resources_comment(unsigned flag, FILE *ofp);
+ void print_extensions_comment(FILE *ofp);
+ void print_language_level_comment(FILE *ofp);
+ int do_begin_resource(const char *ptr, int rank, file_case *fcp, FILE *ofp);
+ int do_include_resource(const char *ptr, int rank, file_case *fcp, FILE *ofp);
+ int do_begin_document(const char *ptr, int rank, file_case *fcp, FILE *ofp);
+ int do_include_document(const char *ptr, int rank, file_case *fcp, FILE *ofp);
+ int do_begin_procset(const char *ptr, int rank, file_case *fcp, FILE *ofp);
+ int do_include_procset(const char *ptr, int rank, file_case *fcp, FILE *ofp);
+ int do_begin_font(const char *ptr, int rank, file_case *fcp, FILE *ofp);
+ int do_include_font(const char *ptr, int rank, file_case *fcp, FILE *ofp);
+ int do_begin_file(const char *ptr, int rank, file_case *fcp, FILE *ofp);
+ int do_include_file(const char *ptr, int rank, file_case *fp, FILE *ofp);
+ int change_to_end_resource(const char *ptr, int rank, file_case *fp,
+ FILE *ofp);
+ int do_begin_preview(const char *ptr, int rank, file_case *fcp, FILE *ofp);
+ int do_begin_data(const char *ptr, int rank, file_case *fcp, FILE *ofp);
+ int do_begin_binary(const char *ptr, int rank, file_case *fcp, FILE *ofp);
};
extern unsigned broken_flags;
diff --git a/src/devices/grops/psrm.cpp b/src/devices/grops/psrm.cpp
index fae2176..e02a1f8 100644
--- a/src/devices/grops/psrm.cpp
+++ b/src/devices/grops/psrm.cpp
@@ -324,7 +324,7 @@ void resource_manager::output_prolog(ps_output &out)
fputs("%%BeginResource: ", outfp);
procset_resource->print_type_and_name(outfp);
putc('\n', outfp);
- process_file(-1, fcp->file(), fcp->path(), outfp);
+ process_file(-1, fcp, outfp);
fputs("%%EndResource\n", outfp);
delete fcp;
@@ -378,7 +378,7 @@ void resource_manager::supply_resource(resource *r, int rank, FILE *outfp,
putc('\n', outfp);
}
}
- process_file(rank, fcp->file(), fcp->path(), outfp);
+ process_file(rank, fcp, outfp);
delete fcp;
if (outfp) {
@@ -407,10 +407,10 @@ void resource_manager::supply_resource(resource *r, int rank, FILE *outfp,
#define PS_MAGIC "%!PS-Adobe-"
-static int ps_get_line(string &buf, FILE *fp)
+static int ps_get_line(string &buf, file_case *fcp)
{
buf.clear();
- int c = getc(fp);
+ int c = fcp->get_c();
if (c == EOF)
return 0;
current_lineno++;
@@ -418,14 +418,14 @@ static int ps_get_line(string &buf, FILE *fp)
if (!valid_input_table[c])
error("invalid input character code %1", int(c));
buf += c;
- c = getc(fp);
+ c = fcp->get_c();
}
buf += '\n';
buf += '\0';
if (c == '\r') {
- c = getc(fp);
+ c = fcp->get_c();
if (c != EOF && c != '\n')
- ungetc(c, fp);
+ fcp->unget_c(c);
}
return 1;
}
@@ -591,8 +591,8 @@ static const char *matches_comment(string &buf, const char *comment)
// Return 1 if the line should be copied out.
-int resource_manager::do_begin_resource(const char *ptr, int, FILE *,
- FILE *)
+int resource_manager::do_begin_resource(const char *ptr, int, file_case *,
+ FILE *)
{
resource *r = read_resource_arg(&ptr);
if (r)
@@ -600,8 +600,8 @@ int resource_manager::do_begin_resource(const char *ptr, int, FILE *,
return 1;
}
-int resource_manager::do_include_resource(const char *ptr, int rank, FILE *,
- FILE *outfp)
+int resource_manager::do_include_resource(const char *ptr, int rank,
+ file_case *, FILE *outfp)
{
resource *r = read_resource_arg(&ptr);
if (r) {
@@ -617,8 +617,8 @@ int resource_manager::do_include_resource(const char *ptr, int rank, FILE *,
return 0;
}
-int resource_manager::do_begin_document(const char *ptr, int, FILE *,
- FILE *)
+int resource_manager::do_begin_document(const char *ptr, int, file_case *,
+ FILE *)
{
resource *r = read_file_arg(&ptr);
if (r)
@@ -626,8 +626,8 @@ int resource_manager::do_begin_document(const char *ptr, int, FILE *,
return 1;
}
-int resource_manager::do_include_document(const char *ptr, int rank, FILE *,
- FILE *outfp)
+int resource_manager::do_include_document(const char *ptr, int rank,
+ file_case *, FILE *outfp)
{
resource *r = read_file_arg(&ptr);
if (r)
@@ -635,8 +635,8 @@ int resource_manager::do_include_document(const char *ptr, int rank, FILE *,
return 0;
}
-int resource_manager::do_begin_procset(const char *ptr, int, FILE *,
- FILE *outfp)
+int resource_manager::do_begin_procset(const char *ptr, int, file_case *,
+ FILE *outfp)
{
resource *r = read_procset_arg(&ptr);
if (r) {
@@ -650,8 +650,8 @@ int resource_manager::do_begin_procset(const char *ptr, int, FILE *,
return 0;
}
-int resource_manager::do_include_procset(const char *ptr, int rank, FILE *,
- FILE *outfp)
+int resource_manager::do_include_procset(const char *ptr, int rank,
+ file_case *, FILE *outfp)
{
resource *r = read_procset_arg(&ptr);
if (r)
@@ -659,8 +659,8 @@ int resource_manager::do_include_procset(const char *ptr, int rank, FILE *,
return 0;
}
-int resource_manager::do_begin_file(const char *ptr, int, FILE *,
- FILE *outfp)
+int resource_manager::do_begin_file(const char *ptr, int, file_case *,
+ FILE *outfp)
{
resource *r = read_file_arg(&ptr);
if (r) {
@@ -674,8 +674,8 @@ int resource_manager::do_begin_file(const char *ptr, int, FILE *,
return 0;
}
-int resource_manager::do_include_file(const char *ptr, int rank, FILE *,
- FILE *outfp)
+int resource_manager::do_include_file(const char *ptr, int rank, file_case *,
+ FILE *outfp)
{
resource *r = read_file_arg(&ptr);
if (r)
@@ -683,8 +683,8 @@ int resource_manager::do_include_file(const char *ptr, int rank, FILE *,
return 0;
}
-int resource_manager::do_begin_font(const char *ptr, int, FILE *,
- FILE *outfp)
+int resource_manager::do_begin_font(const char *ptr, int, file_case *,
+ FILE *outfp)
{
resource *r = read_font_arg(&ptr);
if (r) {
@@ -698,8 +698,8 @@ int resource_manager::do_begin_font(const char *ptr, int, FILE *,
return 0;
}
-int resource_manager::do_include_font(const char *ptr, int rank, FILE *,
- FILE *outfp)
+int resource_manager::do_include_font(const char *ptr, int rank, file_case *,
+ FILE *outfp)
{
resource *r = read_font_arg(&ptr);
if (r) {
@@ -711,19 +711,20 @@ int resource_manager::do_include_font(const char *ptr, int rank, FILE *,
return 0;
}
-int resource_manager::change_to_end_resource(const char *, int, FILE *,
- FILE *outfp)
+int resource_manager::change_to_end_resource(const char *, int, file_case *,
+ FILE *outfp)
{
if (outfp)
fputs("%%EndResource\n", outfp);
return 0;
}
-int resource_manager::do_begin_preview(const char *, int, FILE *fp, FILE *)
+int resource_manager::do_begin_preview(const char *, int, file_case *fcp,
+ FILE *)
{
string buf;
do {
- if (!ps_get_line(buf, fp)) {
+ if (!ps_get_line(buf, fcp)) {
error("end of file in preview section");
break;
}
@@ -748,17 +749,17 @@ int read_one_of(const char **ptr, const char **s, int n)
return -1;
}
-void skip_possible_newline(FILE *fp, FILE *outfp)
+void skip_possible_newline(file_case *fcp, FILE *outfp)
{
- int c = getc(fp);
+ int c = fcp->get_c();
if (c == '\r') {
current_lineno++;
if (outfp)
putc(c, outfp);
- int cc = getc(fp);
+ int cc = fcp->get_c();
if (cc != '\n') {
if (cc != EOF)
- ungetc(cc, fp);
+ fcp->unget_c(cc);
}
else {
if (outfp)
@@ -771,11 +772,11 @@ void skip_possible_newline(FILE *fp, FILE *outfp)
putc(c, outfp);
}
else if (c != EOF)
- ungetc(c, fp);
+ fcp->unget_c(c);
}
-int resource_manager::do_begin_data(const char *ptr, int, FILE *fp,
- FILE *outfp)
+int resource_manager::do_begin_data(const char *ptr, int, file_case *fcp,
+ FILE *outfp)
{
while (white_space(*ptr))
ptr++;
@@ -817,7 +818,7 @@ int resource_manager::do_begin_data(const char *ptr, int, FILE *fp,
unsigned bytecount = 0;
unsigned linecount = 0;
do {
- int c = getc(fp);
+ int c = fcp->get_c();
if (c == EOF) {
error("end of file within data section");
return 0;
@@ -826,13 +827,13 @@ int resource_manager::do_begin_data(const char *ptr, int, FILE *fp,
putc(c, outfp);
bytecount++;
if (c == '\r') {
- int cc = getc(fp);
+ int cc = fcp->get_c();
if (cc != '\n') {
linecount++;
current_lineno++;
}
if (cc != EOF)
- ungetc(cc, fp);
+ fcp->unget_c(cc);
}
else if (c == '\n') {
linecount++;
@@ -840,9 +841,9 @@ int resource_manager::do_begin_data(const char *ptr, int, FILE *fp,
}
} while ((unit == Bytes ? bytecount : linecount) < numberof);
}
- skip_possible_newline(fp, outfp);
+ skip_possible_newline(fcp, outfp);
string buf;
- if (!ps_get_line(buf, fp)) {
+ if (!ps_get_line(buf, fcp)) {
error("missing %%%%EndData line");
return 0;
}
@@ -853,8 +854,8 @@ int resource_manager::do_begin_data(const char *ptr, int, FILE *fp,
return 0;
}
-int resource_manager::do_begin_binary(const char *ptr, int, FILE *fp,
- FILE *outfp)
+int resource_manager::do_begin_binary(const char *ptr, int, file_case *fcp,
+ FILE *outfp)
{
if (!outfp)
return 0;
@@ -864,7 +865,7 @@ int resource_manager::do_begin_binary(const char *ptr, int, FILE *fp,
if (outfp)
fprintf(outfp, "%%%%BeginData: %u Binary Bytes\n", count);
while (count != 0) {
- int c = getc(fp);
+ int c = fcp->get_c();
if (c == EOF) {
error("end of file within binary section");
return 0;
@@ -873,18 +874,18 @@ int resource_manager::do_begin_binary(const char *ptr, int, FILE *fp,
putc(c, outfp);
--count;
if (c == '\r') {
- int cc = getc(fp);
+ int cc = fcp->get_c();
if (cc != '\n')
current_lineno++;
if (cc != EOF)
- ungetc(cc, fp);
+ fcp->unget_c(cc);
}
else if (c == '\n')
current_lineno++;
}
- skip_possible_newline(fp, outfp);
+ skip_possible_newline(fcp, outfp);
string buf;
- if (!ps_get_line(buf, fp)) {
+ if (!ps_get_line(buf, fcp)) {
error("missing %%%%EndBinary line");
return 0;
}
@@ -933,8 +934,7 @@ static unsigned parse_extensions(const char *ptr)
// BeginResource: file should be postponed till we have seen
// the first line of the file.
-void resource_manager::process_file(int rank, FILE *fp, const char *filename,
- FILE *outfp)
+void resource_manager::process_file(int rank, file_case *fcp, FILE *outfp)
{
// If none of these comments appear in the header section, and we are
// just analyzing the file (ie outfp is 0), then we can return immediately.
@@ -953,7 +953,7 @@ void resource_manager::process_file(int rank, FILE *fp, const char *filename,
/ sizeof(header_comment_table[0]);
struct comment_info {
const char *name;
- int (resource_manager::*proc)(const char *, int, FILE *, FILE *);
+ int (resource_manager::*proc)(const char *, int, file_case *, FILE *);
};
static comment_info comment_table[] = {
@@ -979,9 +979,9 @@ void resource_manager::process_file(int rank, FILE *fp, const char *filename,
string buf;
int saved_lineno = current_lineno;
const char *saved_filename = current_filename;
- current_filename = filename;
+ current_filename = fcp->path();
current_lineno = 0;
- if (!ps_get_line(buf, fp)) {
+ if (!ps_get_line(buf, fcp)) {
current_filename = saved_filename;
current_lineno = saved_lineno;
return;
@@ -993,7 +993,7 @@ void resource_manager::process_file(int rank, FILE *fp, const char *filename,
if (!(broken_flags & STRIP_PERCENT_BANG)
|| buf[0] != '%' || buf[1] != '!')
fputs(buf.contents(), outfp);
- } while (ps_get_line(buf, fp));
+ } while (ps_get_line(buf, fcp));
}
}
else {
@@ -1004,7 +1004,7 @@ void resource_manager::process_file(int rank, FILE *fp, const char *filename,
int had_extensions_comment = 0;
int had_language_level_comment = 0;
for (;;) {
- if (!ps_get_line(buf, fp))
+ if (!ps_get_line(buf, fcp))
break;
int copy_this_line = 1;
if (buf[0] == '%') {
@@ -1014,7 +1014,7 @@ void resource_manager::process_file(int rank, FILE *fp, const char *filename,
for (i = 0; i < NCOMMENTS; i++)
if ((ptr = matches_comment(buf, comment_table[i].name))) {
copy_this_line
- = (this->*(comment_table[i].proc))(ptr, rank, fp, outfp);
+ = (this->*(comment_table[i].proc))(ptr, rank, fcp, outfp);
break;
}
if (i >= NCOMMENTS && in_header) {
@@ -1071,7 +1071,7 @@ void resource_manager::read_download_file()
fatal("can't find `download'");
char buf[512];
- for (int lineno = 1; fgets(buf, sizeof(buf), fcp->file()) != NULL; ++lineno) {
+ for (int lineno = 1; fcp->get_line(buf, sizeof(buf)) != NULL; ++lineno) {
char *p = strtok(buf, " \t\r\n");
if (p == NULL || *p == '#')
continue;
diff --git a/src/include/file_case.h b/src/include/file_case.h
index 7ea3f86..07f21d7 100644
--- a/src/include/file_case.h
+++ b/src/include/file_case.h
@@ -27,8 +27,10 @@
class file_case
{
char const *_path;
- FILE *_file;
+ FILE *_file; // fc_have_stdio
+ void *_layer; // E.g., gzFile
uint32_t _flags;
+ uint8_t _dummy[4];
public:
// Flags for ctor / muxer()
enum {
@@ -37,7 +39,8 @@ public:
fc_pipe = 1<<1, // _file is not seekable
fc_const_path = 1<<2, // Don't dup path, and don't a_delete it
fc_take_path = 1<<3, // Don't dup path, but a_delete it
- _fc_freebit = 4,
+ fc_have_stdio = 1<<4, // .file() may be used
+ _fc_freebit = 5,
fc_mask = (1<<_fc_freebit) - 1
};
@@ -47,6 +50,7 @@ public:
mux_need_binary = 1<<(_fc_freebit+1), // Need binary I/O
mux_unpack = 1<<(_fc_freebit+2), // Do auto-check for FILE{.gz,.bz2..}
mux_no_unpack = 1<<(_fc_freebit+3), // Do NOT auto-check
+ mux_need_stdio = 1<<(_fc_freebit+4), // Only then may .file() be used
mux_mask = ~fc_mask,
mux_default = fc_none,
// Defines the global default strategy for dealing with packed files in case
@@ -54,6 +58,12 @@ public:
_mux_unpack_default = mux_unpack
};
+ enum seek_whence {
+ seek_set,
+ seek_cur,
+ seek_end
+ };
+
file_case(FILE *fp, char const *path, uint32_t flags=fc_none);
~file_case(void);
@@ -62,6 +72,14 @@ public:
FILE * file(void) const;
bool is_pipe(void) const;
+ bool is_eof(void) const;
+ int get_c(void);
+ int unget_c(int c);
+ char * get_line(char *buf, size_t buf_size);
+ size_t get_buf(void *buf, size_t buf_size);
+ void rewind(void);
+ int seek(long offset, seek_whence whence=seek_set);
+
// Factory muxer; note that fc_take_path will be honoured even on failure
static file_case * muxer(char const *path, uint32_t flags=mux_default);
@@ -71,7 +89,7 @@ public:
inline
file_case::file_case(FILE *fp, char const *path, uint32_t flags)
:
- _path(path), _file(fp), _flags(flags)
+ _path(path), _file(fp), _layer(NULL), _flags(flags)
{
assert(!(flags & (fc_const_path | fc_take_path)) ||
!(flags & fc_const_path) != !(flags & fc_take_path));
@@ -81,7 +99,7 @@ file_case::file_case(FILE *fp, char const *path, uint32_t flags)
inline
file_case::~file_case(void)
{
- if (_file != NULL)
+ if (_file != NULL || _layer != NULL) // xxx (uintptr_t)a|(uintptr_t)b
close();
}
@@ -94,6 +112,7 @@ file_case::path(void) const
inline FILE *
file_case::file(void) const
{
+ assert(_flags & fc_have_stdio);
return _file;
}
diff --git a/src/libs/libgroff/file_case.cpp b/src/libs/libgroff/file_case.cpp
index 5fdbd1f..362098b 100644
--- a/src/libs/libgroff/file_case.cpp
+++ b/src/libs/libgroff/file_case.cpp
@@ -30,6 +30,14 @@
#include "file_case.h"
+#undef getc
+#undef _getc
+#ifdef HAVE_DECL_GETC_UNLOCKED
+# define _getc getc_unlocked
+#else
+# define _getc fgetc
+#endif
+
// Support decompression XXX configure should say `no popen() - no unpacking'
#ifdef POPEN_MISSING
# undef HAVE_UNPACK
@@ -233,6 +241,51 @@ file_case::close(void)
return rv;
}
+bool
+file_case::is_eof(void) const
+{
+ return (feof(_file) != 0);
+}
+
+int
+file_case::get_c(void)
+{
+ return _getc(_file);
+}
+
+int
+file_case::unget_c(int c)
+{
+ return ungetc(c, _file);
+}
+
+char *
+file_case::get_line(char *buf, size_t buf_size)
+{
+ buf = fgets(buf, (int)buf_size, _file);
+ return buf;
+}
+
+size_t
+file_case::get_buf(void *buf, size_t buf_size)
+{
+ return fread(buf, 1, buf_size, _file);
+}
+
+void
+file_case::rewind(void)
+{
+ ::rewind(_file);
+}
+
+int
+file_case::seek(long offset, seek_whence whence)
+{
+ int w = (whence == seek_set ? SEEK_SET :
+ (whence == seek_cur ? SEEK_CUR : SEEK_END));
+ return fseek(_file, offset, w);
+}
+
/*static*/ file_case *
file_case::muxer(char const *path, uint32_t flags)
{
@@ -271,6 +324,7 @@ file_case::muxer(char const *path, uint32_t flags)
// Try a plain open
errno = 0;
if ((a.a_fp = fopen(a.a_path, a.a_mode)) != NULL) {
+ a.a_flags |= fc_have_stdio;
#ifdef HAVE_UNPACK
jnew:
#endif
diff --git a/src/libs/libgroff/font.cpp b/src/libs/libgroff/font.cpp
index b5a1990..e5908a5 100644
--- a/src/libs/libgroff/font.cpp
+++ b/src/libs/libgroff/font.cpp
@@ -108,7 +108,7 @@ int text_file::next()
for (;;) {
int i = 0;
for (;;) {
- int c = getc(fcp->file());
+ int c = fcp->get_c();
if (c == EOF)
break;
if (invalid_input_char(c))
diff --git a/src/libs/libgroff/searchpath.cpp b/src/libs/libgroff/searchpath.cpp
index b0520d6..4a0561d 100644
--- a/src/libs/libgroff/searchpath.cpp
+++ b/src/libs/libgroff/searchpath.cpp
@@ -158,7 +158,7 @@ file_case *search_path::open_file_cautious(char const *name, uint32_t flags)
file_case *fcp;
if (name == NULL || strcmp(name, "-") == 0) {
flags &= ~(fcp->fc_take_path);
- flags |= fcp->fc_dont_close | fcp->fc_const_path;
+ flags |= fcp->fc_dont_close | fcp->fc_const_path | fcp->fc_have_stdio;
if (flags & fcp->mux_need_binary)
SET_BINARY(fileno(stdin));
fcp = new file_case(stdin, "stdin", flags);
diff --git a/src/preproc/eqn/main.cpp b/src/preproc/eqn/main.cpp
index 672bc50..b2a3ba1 100644
--- a/src/preproc/eqn/main.cpp
+++ b/src/preproc/eqn/main.cpp
@@ -34,7 +34,7 @@ extern int yyparse();
extern "C" const char *Version_string;
static char *delim_search (char *, int);
-static int inline_equation (FILE *, string &, string &);
+static int inline_equation (file_case *, string &, string &);
char start_delim = '\0';
char end_delim = '\0';
@@ -48,11 +48,11 @@ int html = 0;
int xhtml = 0;
eqnmode_t output_format;
-int read_line(FILE *fp, string *p)
+int read_line(file_case *fcp, string *p)
{
p->clear();
int c = -1;
- while ((c = getc(fp)) != EOF) {
+ while ((c = fcp->get_c()) != EOF) {
if (!invalid_input_char(c))
*p += char(c);
else
@@ -64,7 +64,7 @@ int read_line(FILE *fp, string *p)
return p->length() > 0;
}
-void do_file(FILE *fp, const char *filename)
+void do_file(file_case *fcp, const char *filename)
{
string linebuf;
string str;
@@ -72,7 +72,7 @@ void do_file(FILE *fp, const char *filename)
printf(".lf 1 %s\n", filename);
current_filename = filename;
current_lineno = 0;
- while (read_line(fp, &linebuf)) {
+ while (read_line(fcp, &linebuf)) {
if (linebuf.length() >= 4
&& linebuf[0] == '.' && linebuf[1] == 'l' && linebuf[2] == 'f'
&& (linebuf[3] == ' ' || linebuf[3] == '\n' || compatible_flag)) {
@@ -91,7 +91,7 @@ void do_file(FILE *fp, const char *filename)
int start_lineno = current_lineno + 1;
str.clear();
for (;;) {
- if (!read_line(fp, &linebuf))
+ if (!read_line(fcp, &linebuf))
fatal("end of file before .EN");
if (linebuf.length() >= 3 && linebuf[0] == '.' && linebuf[1] == 'E') {
if (linebuf[2] == 'N'
@@ -125,7 +125,7 @@ void do_file(FILE *fp, const char *filename)
put_string(linebuf, stdout);
}
else if (start_delim != '\0' && linebuf.search(start_delim) >= 0
- && inline_equation(fp, linebuf, str))
+ && inline_equation(fcp, linebuf, str))
;
else
put_string(linebuf, stdout);
@@ -136,7 +136,7 @@ void do_file(FILE *fp, const char *filename)
// Handle an inline equation. Return 1 if it was an inline equation,
// otherwise.
-static int inline_equation(FILE *fp, string &linebuf, string &str)
+static int inline_equation(file_case *fcp, string &linebuf, string &str)
{
linebuf += '\0';
char *ptr = &linebuf[0];
@@ -171,7 +171,7 @@ static int inline_equation(FILE *fp, string &linebuf, string &str)
break;
}
str += ptr;
- if (!read_line(fp, &linebuf))
+ if (!read_line(fcp, &linebuf))
fatal("unterminated `%1' at line %2, looking for `%3'",
start_delim, start_lineno, end_delim);
linebuf += '\0';
@@ -390,30 +390,32 @@ int main(int argc, char **argv)
".tm warning: (it is advisable to invoke groff via: groff -Thtml -e)\n",
device);
}
+
+ file_case *fcp;
if (load_startup_file) {
- file_case *fcp;
if ((fcp = config_macro_path.open_file(STARTUP_FILE, fcp->fc_const_path)
) != NULL) {
- do_file(fcp->file(), fcp->path());
+ do_file(fcp, fcp->path());
delete fcp;
}
}
- if (optind >= argc)
- do_file(stdin, "-");
- else
- for (int i = optind; i < argc; i++)
- if (strcmp(argv[i], "-") == 0)
- do_file(stdin, "-");
- else {
- errno = 0;
- FILE *fp = fopen(argv[i], "r");
- if (!fp)
- fatal("can't open `%1': %2", argv[i], strerror(errno));
- else {
- do_file(fp, argv[i]);
- fclose(fp);
- }
- }
+ int i = optind;
+ if (i >= argc)
+ goto jstdin;
+ for (; i < argc; ++i) {
+ if (!strcmp(argv[i], "-")) {
+jstdin:
+ fcp = new file_case(stdin, "stdin",
+ fcp->fc_dont_close | fcp->fc_const_path /*| fcp->fc_have_stdio*/);
+ do_file(fcp, "-");
+ } else {
+ fcp = file_case::muxer(argv[i]);
+ if (fcp == NULL)
+ fatal("can't open `%1': %2", argv[i], strerror(errno));
+ do_file(fcp, argv[i]);
+ }
+ delete fcp;
+ }
if (ferror(stdout) || fflush(stdout) < 0)
fatal("output error");
return 0;
diff --git a/src/preproc/grn/main.cpp b/src/preproc/grn/main.cpp
index b5bcc79..ee17002 100644
--- a/src/preproc/grn/main.cpp
+++ b/src/preproc/grn/main.cpp
@@ -547,10 +547,11 @@ conv(register FILE *fp,
return;
}
{
- file_case *fcp;
- if ((fcp = macro_path.open_file(gremlinfile, fcp->fc_const_path)) == NULL)
+ file_case *fcp = macro_path.open_file(gremlinfile,
+ fcp->fc_const_path | fcp->mux_need_stdio); /* TODO _need_stdio! */
+ if (fcp == NULL)
return;
- PICTURE = DBRead(fcp->file()); /* read picture file */
+ PICTURE = DBRead(fcp->file()); /* read picture file TODO _need_stdio! */
delete fcp;
}
if (DBNullelt(PICTURE))
diff --git a/src/preproc/html/pre-html.cpp b/src/preproc/html/pre-html.cpp
index 8c115ec..bbc2331 100644
--- a/src/preproc/html/pre-html.cpp
+++ b/src/preproc/html/pre-html.cpp
@@ -248,9 +248,9 @@ void sys_fatal(const char *s)
* global line buffer.
*/
-int get_line(FILE *f)
+int get_line(file_case *fcp)
{
- if (f == 0)
+ if (fcp == NULL)
return 0;
if (linebuf == 0) {
linebuf = new char[128];
@@ -259,16 +259,16 @@ int get_line(FILE *f)
int i = 0;
// skip leading whitespace
for (;;) {
- int c = getc(f);
+ int c = fcp->get_c();
if (c == EOF)
return 0;
if (c != ' ' && c != '\t') {
- ungetc(c, f);
+ fcp->unget_c(c);
break;
}
}
for (;;) {
- int c = getc(f);
+ int c = fcp->get_c();
if (c == EOF)
break;
if (i + 1 >= linebufsize) {
@@ -298,7 +298,7 @@ static unsigned int get_resolution(void)
file_case *fcp;
if ((fcp = font_path.open_file("devps/DESC", fcp->fc_const_path)) == NULL)
fatal("can't open devps/DESC");
- while (get_line(fcp->file())) {
+ while (get_line(fcp)) {
int n = sscanf(linebuf, "res %u", &res);
if (n >= 1)
goto jleave;
diff --git a/src/preproc/soelim/soelim.cpp b/src/preproc/soelim/soelim.cpp
index 0c0654d..da8a675 100644
--- a/src/preproc/soelim/soelim.cpp
+++ b/src/preproc/soelim/soelim.cpp
@@ -165,7 +165,7 @@ int do_file(const char *filename)
current_lineno = 1;
set_location();
for (;;) {
- int c = getc(fcp->file());
+ int c = fcp->get_c();
if (c == EOF)
break;
switch (state) {
@@ -223,7 +223,7 @@ int do_file(const char *filename)
case HAD_so:
if (c == ' ' || c == '\n' || compatible_flag) {
string line;
- for (; c != EOF && c != '\n'; c = getc(fcp->file()))
+ for (; c != EOF && c != '\n'; c = fcp->get_c())
line += c;
current_lineno++;
line += '\n';
@@ -255,7 +255,7 @@ int do_file(const char *filename)
case HAD_lf:
if (c == ' ' || c == '\n' || compatible_flag) {
string line;
- for (; c != EOF && c != '\n'; c = getc(fcp->file()))
+ for (; c != EOF && c != '\n'; c = fcp->get_c())
line += c;
current_lineno++;
line += '\n';
diff --git a/src/roff/troff/env.cpp b/src/roff/troff/env.cpp
index f8d2ce3..66ec813 100644
--- a/src/roff/troff/env.cpp
+++ b/src/roff/troff/env.cpp
@@ -3522,7 +3522,7 @@ class hyphen_trie : private trie {
void do_delete(void *v);
void insert_pattern(const char *pat, int patlen, int *num);
void insert_hyphenation(dictionary *ex, const char *pat, int patlen);
- int hpf_getc(FILE *f);
+ int hpf_getc(file_case *fcp);
public:
hyphen_trie() {}
~hyphen_trie() {}
@@ -3784,18 +3784,18 @@ void hyphen_trie::do_delete(void *v)
*/
-int hyphen_trie::hpf_getc(FILE *f)
+int hyphen_trie::hpf_getc(file_case *fcp)
{
- int c = getc(f);
+ int c = fcp->get_c();
int c1;
int cc = 0;
if (c != '^')
return c;
- c = getc(f);
+ c = fcp->get_c();
if (c != '^')
goto fail;
- c = getc(f);
- c1 = getc(f);
+ c = fcp->get_c();
+ c1 = fcp->get_c();
if (((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'))
&& ((c1 >= '0' && c1 <= '9') || (c1 >= 'a' && c1 <= 'f'))) {
if (c >= '0' && c <= '9')
@@ -3809,7 +3809,7 @@ int hyphen_trie::hpf_getc(FILE *f)
cc = c * 16 + c1;
}
else {
- ungetc(c1, f);
+ fcp->unget_c(c1);
if (c >= 0 && c <= 63)
cc = c + 64;
else if (c >= 64 && c <= 127)
@@ -3846,24 +3846,24 @@ void hyphen_trie::read_patterns_file(const char *name, int append,
goto jleave;
}
- for (c = hpf_getc(fcp->file());;) {
+ for (c = hpf_getc(fcp);;) {
for (;;) {
if (c == '%') { // skip comments
do {
- c = getc(fcp->file());
+ c = fcp->get_c();
} while (c != EOF && c != '\n');
}
if (c == EOF || !csspace(c))
break;
- c = hpf_getc(fcp->file());
+ c = hpf_getc(fcp);
}
if (c == EOF) {
if (have_keyword || traditional) // we are done
break;
else { // rescan file in `traditional' mode
- rewind(fcp->file());
+ fcp->rewind();
traditional = 1;
- c = hpf_getc(fcp->file());
+ c = hpf_getc(fcp);
continue;
}
}
@@ -3877,14 +3877,14 @@ void hyphen_trie::read_patterns_file(const char *name, int append,
buf[i++] = c;
num[i] = 0;
}
- c = hpf_getc(fcp->file());
+ c = hpf_getc(fcp);
} while (i < WORD_MAX && c != EOF && !csspace(c)
&& c != '%' && c != '{' && c != '}');
}
if (!traditional) {
if (i >= 9 && !strncmp(buf + i - 9, "\\patterns", 9)) {
while (csspace(c))
- c = hpf_getc(fcp->file());
+ c = hpf_getc(fcp);
if (c == '{') {
if (have_patterns || have_hyphenation)
error("\\patterns not allowed inside of %1 group",
@@ -3893,13 +3893,13 @@ void hyphen_trie::read_patterns_file(const char *name, int append,
have_patterns = 1;
have_keyword = 1;
}
- c = hpf_getc(fcp->file());
+ c = hpf_getc(fcp);
continue;
}
}
else if (i >= 12 && !strncmp(buf + i - 12, "\\hyphenation", 12)) {
while (csspace(c))
- c = hpf_getc(fcp->file());
+ c = hpf_getc(fcp);
if (c == '{') {
if (have_patterns || have_hyphenation)
error("\\hyphenation not allowed inside of %1 group",
@@ -3908,7 +3908,7 @@ void hyphen_trie::read_patterns_file(const char *name, int append,
have_hyphenation = 1;
have_keyword = 1;
}
- c = hpf_getc(fcp->file());
+ c = hpf_getc(fcp);
continue;
}
}
@@ -3929,19 +3929,19 @@ void hyphen_trie::read_patterns_file(const char *name, int append,
if (i > 0)
final_hyphenation = 1;
}
- c = hpf_getc(fcp->file());
+ c = hpf_getc(fcp);
}
else if (c == '{') {
if (have_patterns || have_hyphenation)
error("`{' not allowed within %1 group",
have_patterns ? "\\patterns" : "\\hyphenation");
- c = hpf_getc(fcp->file()); // skipped if not starting \patterns
- // or \hyphenation
+ c = hpf_getc(fcp); // skipped if not starting \patterns
+ // or \hyphenation
}
}
else {
if (c == '{' || c == '}')
- c = hpf_getc(fcp->file());
+ c = hpf_getc(fcp);
}
if (i > 0) {
if (have_patterns || final_pattern || traditional) {
diff --git a/src/roff/troff/input.cpp b/src/roff/troff/input.cpp
index 9458682..fa2c8bd 100644
--- a/src/roff/troff/input.cpp
+++ b/src/roff/troff/input.cpp
@@ -346,7 +346,7 @@ int file_iterator::fill(node **)
ptr = p;
unsigned char *e = p + BUF_SIZE;
while (p < e) {
- int c = getc(_fcp->file());
+ int c = _fcp->get_c();
if (c == EOF)
break;
if (invalid_input_char(c))
@@ -373,13 +373,13 @@ int file_iterator::fill(node **)
int file_iterator::peek()
{
- int c = getc(_fcp->file());
+ int c = _fcp->get_c();
while (invalid_input_char(c)) {
warning(WARN_INPUT, "invalid input character code %1", int(c));
- c = getc(_fcp->file());
+ c = _fcp->get_c();
}
if (c != EOF)
- ungetc(c, _fcp->file());
+ _fcp->unget_c(c);
return c;
}
@@ -6047,9 +6047,9 @@ int parse_bounding_box(char *p, bounding_box *bb)
#define PS_LINE_MAX 255
cset white_space("\n\r \t");
-int ps_get_line(char *buf, FILE *fp, const char* filename)
+int ps_get_line(char *buf, file_case *fcp, const char* filename)
{
- int c = getc(fp);
+ int c = fcp->get_c();
if (c == EOF) {
buf[0] = '\0';
return 0;
@@ -6066,14 +6066,14 @@ int ps_get_line(char *buf, FILE *fp, const char* filename)
error("PostScript file `%1' is non-conforming "
"because length of line exceeds 255", filename);
}
- c = getc(fp);
+ c = fcp->get_c();
}
buf[i++] = '\n';
buf[i] = '\0';
if (c == '\r') {
- c = getc(fp);
+ c = fcp->get_c();
if (c != EOF && c != '\n')
- ungetc(c, fp);
+ fcp->unget_c(c);
}
return 1;
}
@@ -6086,14 +6086,14 @@ inline void assign_registers(int llx, int lly, int urx, int ury)
ury_reg_contents = ury;
}
-void do_ps_file(FILE *fp, const char* filename)
+void do_ps_file(file_case *fcp, const char* filename)
{
bounding_box bb;
int bb_at_end = 0;
char buf[PS_LINE_MAX];
llx_reg_contents = lly_reg_contents =
urx_reg_contents = ury_reg_contents = 0;
- if (!ps_get_line(buf, fp, filename)) {
+ if (!ps_get_line(buf, fcp, filename)) {
error("`%1' is empty", filename);
return;
}
@@ -6102,7 +6102,7 @@ void do_ps_file(FILE *fp, const char* filename)
filename);
return;
}
- while (ps_get_line(buf, fp, filename) != 0) {
+ while (ps_get_line(buf, fcp, filename) != 0) {
// in header comments, `%X' (`X' any printable character except
// whitespace) is possible too
if (buf[0] == '%') {
@@ -6137,12 +6137,12 @@ void do_ps_file(FILE *fp, const char* filename)
for (offset = 512; !last_try; offset *= 2) {
int had_trailer = 0;
int got_bb = 0;
- if (offset > 32768 || fseek(fp, -offset, 2) == -1) {
+ if (offset > 32768 || fcp->seek(-offset, fcp->seek_end) == -1) {
last_try = 1;
- if (fseek(fp, 0L, 0) == -1)
+ if (fcp->seek(0L, fcp->seek_set) == -1)
break;
}
- while (ps_get_line(buf, fp, filename) != 0) {
+ while (ps_get_line(buf, fcp, filename) != 0) {
if (buf[0] == '%' && buf[1] == '%') {
if (!had_trailer) {
if (strncmp(buf + 2, "Trailer", 7) == 0)
@@ -6188,7 +6188,7 @@ void ps_bbox_request()
file_case *fcp = include_search_path.open_file_cautious(nm.contents(),
fcp->mux_need_seek | fcp->mux_need_binary);
if (fcp != NULL) {
- do_ps_file(fcp->file(), nm.contents());
+ do_ps_file(fcp, nm.contents());
delete fcp;
} else
error("can't open `%1': %2", nm.contents(), strerror(errno));
@@ -7328,7 +7328,7 @@ void transparent_file()
else {
int bol = 1;
for (;;) {
- int c = getc(fcp->file());
+ int c = fcp->get_c();
if (c == EOF)
break;
if (invalid_input_char(c))
diff --git a/src/roff/troff/node.cpp b/src/roff/troff/node.cpp
index 9b27f12..2f2306f 100644
--- a/src/roff/troff/node.cpp
+++ b/src/roff/troff/node.cpp
@@ -1557,7 +1557,7 @@ void troff_output_file::really_copy_file(hunits x, vunits y,
fcp->fc_const_path);
if (fcp != NULL) {
int c;
- while ((c = getc(fcp->file())) != EOF)
+ while ((c = fcp->get_c()) != EOF)
put(char(c));
delete fcp;
} else
--
2.0.0
From 5c2bf98e6843b43242ee99d8a13577c8059b6e90 Mon Sep 17 00:00:00 2001
Message-Id:
In-Reply-To:
References:
From: Steffen Nurpmeso
Date: Fri, 25 Jul 2014 15:53:31 +0200
Subject: [PATCH 07/20] Add GROFF_ZLIB_CHECK m4++ / --with-zlib=DIR (Public
Domain)
---
configure.ac | 1 +
m4/groff.m4 | 35 +++++++++++++++++++++++++++++++++++
2 files changed, 36 insertions(+)
diff --git a/configure.ac b/configure.ac
index b918d6e..619f579 100644
--- a/configure.ac
+++ b/configure.ac
@@ -66,6 +66,7 @@ GROFF_GROFFERDIR_DEFAULT
GROFF_GLILYPONDDIR_DEFAULT
GROFF_GROGDIR_DEFAULT
GROFF_UNPACK_CHECK
+GROFF_ZLIB_CHECK
GROFF_PERL
GROFF_PRINT
AC_PROG_EGREP
diff --git a/m4/groff.m4 b/m4/groff.m4
index ffc2f3c..7078bde 100644
--- a/m4/groff.m4
+++ b/m4/groff.m4
@@ -121,6 +121,41 @@ AC_DEFUN([GROFF_UNPACK_CHECK],
])
+# Check for zlib
+AC_DEFUN([GROFF_ZLIB_CHECK],
+ [user=0
+ AC_ARG_WITH([zlib],
+ [AS_HELP_STRING([--with-zlib[[=DIR]]],
+ [choose wether support of `gz' decompression through the zlib library
+ is desirable (requires --with-unpack to include `gz')])],
+ [user=1; ZLIB="$withval"],
+ [ZLIB=yes])
+
+ if test $HAVE_UNPACK_GZ -ne 1; then
+ if test $user -ne 0 && test "x$ZLIB" != xno; then
+ AC_MSG_ERROR([--with-zlib needs --with-unpack= (to include `gz')])
+ fi
+ else
+ DIR=/usr/local
+ test -f "$DIR/include/zlib.h" || DIR=/usr
+ if test "x$ZLIB" != xyes; then
+ DIR=$ZLIB
+ CPPFLAGS="-I$DIR/include $CPPFLAGS"
+ LDFLAGS="-L$DIR/lib $LDFLAGS"
+ fi
+ AC_CHECK_HEADER([zlib.h], [ZLIB=1],
+ [AC_MSG_ERROR([Cannot find zlib.h; either specify a valid zlib
+ installation with --with-zlib=DIR or disable zlib usage with
+ --without-zlib])])
+ AC_CHECK_LIB([z], [gzopen], [LIBS="-lz $LIBS"],
+ [AC_MSG_ERROR([cannot link against -lz; either specify a valid zlib
+ installation with --with-zlib=DIR or disable zlib usage with
+ --without-zlib])])
+ AC_DEFINE([HAVE_ZLIB], [1], [Define if you have the zlib library.])
+ fi
+])
+
+
# It is possible to fine-tune generation of documenation.
AC_DEFUN([GROFF_DOC_CHECK],
--
2.0.0
From f6ad3b78d17ee6a7d2d066fe93b47617f3235af7 Mon Sep 17 00:00:00 2001
Message-Id:
In-Reply-To:
References:
From: Steffen Nurpmeso
Date: Sat, 26 Jul 2014 22:24:24 +0200
Subject: [PATCH 08/20] file_case: implement direct HAVE_ZLIB layer (Public
Domain)
---
src/libs/libgroff/file_case.cpp | 182 ++++++++++++++++++++++++++++++++--------
1 file changed, 146 insertions(+), 36 deletions(-)
diff --git a/src/libs/libgroff/file_case.cpp b/src/libs/libgroff/file_case.cpp
index 362098b..f47c4f2 100644
--- a/src/libs/libgroff/file_case.cpp
+++ b/src/libs/libgroff/file_case.cpp
@@ -23,6 +23,10 @@
#include
#include
+#ifdef HAVE_ZLIB
+# include
+#endif
+
#include "errarg.h"
#include "error.h"
#include "posix.h"
@@ -43,8 +47,23 @@
# undef HAVE_UNPACK
#endif
+// (Enclosed by HAVE_UNPACK) Directly support decompression library layer?
+// XXX We yet only support a zlib _LAYER, which is why we directly address zlib
+// XXX functions instead of furtherly abstracting into a struct iolayer or sth.
+// XXX If we would, that can only have read_buf() and close() and we should
+// XXX deal with buffer handling entirely ourselfs, in which case even the
+// XXX popen(3) code path could be enwrapped into struct iolayer; i.e., then
+// XXX the entire public read interface could internally be driven by iolayer
+#ifndef HAVE_ZLIB
+# define HAVE_ZLIB 0
+#endif
+#if HAVE_ZLIB
+# define _LAYER
+#endif
+
struct args {
FILE *a_fp;
+ void *a_layer;
char const *a_path;
size_t a_path_len;
char const *a_mode; // Mode for fopen(3), if used
@@ -57,20 +76,21 @@ struct zproc {
uint8_t zp_popen;
uint8_t zp_ext_len; // Extension including `.' ()
uint8_t zp_cmd_len;
+ uint8_t zp_layer; // Uses I/O layer (zlib)
char zp_ext[5];
- char zp_cmd[16];
+ char zp_cmd[15];
};
static zproc const _zprocs[] = {
-# define __X(C,E) {true, sizeof(E) -1, sizeof(C) -1, E, C}
+# define __X(L,C,E) {true, sizeof(E) -1, sizeof(C) -1, L, E, C}
# ifdef HAVE_UNPACK_BZ2
- __X("bzip2 -cdf", ".bz2"),
+ __X(0, "bzip2 -cdf", ".bz2"),
# endif
# ifdef HAVE_UNPACK_GZ
- __X("gzip -cdf", ".gz"),
+ __X(HAVE_ZLIB, "gzip -cdf", ".gz"),
# endif
# ifdef HAVE_UNPACK_XZ
- __X("xz -cdf", ".xz")
+ __X(0, "xz -cdf", ".xz")
# endif
# undef __X
};
@@ -91,7 +111,7 @@ static bool _try_all_ext(args *ap);
// Create a FILE* according to zp, return NULL on error
static args * __run_zproc(args *ap, zproc const *zp);
-// Callee needs seek()ing, unpack into temporary file, return NULL on error
+// Callee needs seek()ing or STD I/O, unpack into temporary file, NULL on error
static args * __unpack(args *ap);
#endif // HAVE_UNPACK
@@ -148,22 +168,36 @@ jleave:
static args *
__run_zproc(args *ap, zproc const *zp)
{
- char *np = new char[zp->zp_cmd_len + 1 + ap->a_path_len +1];
+# ifdef _LAYER
+ if (zp->zp_layer) {
+ if ((ap->a_layer = gzopen(ap->a_path, "rb")) == NULL) {
+ ap->a_errno = errno;
+ ap = NULL;
+ } else if (ap->a_flags &
+ (file_case::mux_need_seek | file_case::mux_need_stdio))
+ ap = __unpack(ap);
+ } else {
+# endif
+ char *np = new char[zp->zp_cmd_len + 1 + ap->a_path_len +1];
- size_t l;
- memcpy(np, zp->zp_cmd, l = zp->zp_cmd_len);
- np[l++] = ' ';
- memcpy(np + l, ap->a_path, ap->a_path_len +1);
+ size_t l;
+ memcpy(np, zp->zp_cmd, l = zp->zp_cmd_len);
+ np[l++] = ' ';
+ memcpy(np + l, ap->a_path, ap->a_path_len +1);
- if ((ap->a_fp = popen(np, "r")) == NULL) {
- ap->a_errno = errno;
- ap = NULL;
- } else if (ap->a_flags & file_case::mux_need_seek)
- ap = __unpack(ap);
- else
- ap->a_flags |= file_case::fc_pipe;
+ if ((ap->a_fp = popen(np, "r")) == NULL) {
+ ap->a_errno = errno;
+ ap = NULL;
+ } else if (ap->a_flags & file_case::mux_need_seek)
+ ap = __unpack(ap);
+ else
+ ap->a_flags |= file_case::fc_pipe | file_case::fc_have_stdio;
+
+ a_delete np;
+# ifdef _LAYER
+ }
+# endif
- a_delete np;
return ap;
}
@@ -176,8 +210,21 @@ __unpack(args *ap)
// xtmpfile uses binary mode and fatal()s on error
FILE *decomp = xtmpfile(NULL, "groff_unpack"), *decomp_save = decomp;
for (;;) {
- size_t oc = fread(buf, sizeof *buf, buf_len, ap->a_fp);
- if (oc == 0) {
+ size_t oc;
+
+# ifdef _LAYER
+ if (ap->a_layer != NULL) {
+ int i = gzread((gzFile)ap->a_layer, buf, buf_len);
+ if (i == -1) {
+ ap->a_errno = errno;
+ decomp = NULL;
+ break;
+ } else if (i == 0)
+ break;
+ oc = (size_t)i;
+ } else
+# endif
+ if ((oc = fread(buf, sizeof *buf, buf_len, ap->a_fp)) == 0) {
if (!feof(ap->a_fp)) {
ap->a_errno = errno;
decomp = NULL;
@@ -199,12 +246,21 @@ __unpack(args *ap)
}
}
}
+
+# ifdef _LAYER
+ if (ap->a_layer != NULL) {
+ if (gzclose((gzFile)ap->a_layer) != Z_OK)
+ error("decompressor gzclose(3) failed");
+ ap->a_layer = NULL;
+ } else
+# endif
if (pclose(ap->a_fp) != 0)
error("decompressor pipe pclose(3) didn't exit cleanly");
- if (decomp != NULL)
+ if (decomp != NULL) {
+ ap->a_flags |= file_case::fc_have_stdio;
rewind(ap->a_fp = decomp);
- else {
+ } else {
fclose(decomp_save);
ap->a_fp = NULL;
ap = NULL;
@@ -218,7 +274,8 @@ __unpack(args *ap)
bool
file_case::close(void)
{
- assert(_file != NULL);
+ assert((_file != NULL && _layer == NULL) ||
+ (_file == NULL && _layer != NULL));
if (!(_flags & fc_const_path))
a_delete _path;
@@ -226,6 +283,10 @@ file_case::close(void)
bool rv;
if (_flags & fc_dont_close)
rv = true;
+#ifdef _LAYER
+ else if (_layer != NULL)
+ rv = (gzclose((gzFile)_layer) == Z_OK);
+#endif
#ifdef HAVE_UNPACK
else if (_flags & fc_pipe)
rv = (pclose(_file) == 0);
@@ -234,8 +295,9 @@ file_case::close(void)
rv = (fclose(_file) == 0);
#ifndef NDEBUG
- _file = NULL;
_path = NULL;
+ _file = NULL;
+ _layer = NULL;
_flags = fc_none;
#endif
return rv;
@@ -244,46 +306,91 @@ file_case::close(void)
bool
file_case::is_eof(void) const
{
- return (feof(_file) != 0);
+ bool rv;
+#ifdef _LAYER
+ if (_layer != NULL)
+ rv = (gzeof((gzFile)_layer) != 0);
+ else
+#endif
+ rv = (feof(_file) != 0);
+ return rv;
}
int
file_case::get_c(void)
{
- return _getc(_file);
+ int rv;
+#ifdef _LAYER
+ if (_layer != NULL)
+ rv = gzgetc((gzFile)_layer);
+ else
+#endif
+ rv = _getc(_file);
+ return rv;
}
int
file_case::unget_c(int c)
{
- return ungetc(c, _file);
+ int rv;
+#ifdef _LAYER
+ if (_layer != NULL)
+ rv = gzungetc(c, (gzFile)_layer);
+ else
+#endif
+ rv = ungetc(c, _file);
+ return rv;
}
char *
file_case::get_line(char *buf, size_t buf_size)
{
- buf = fgets(buf, (int)buf_size, _file);
+#ifdef _LAYER
+ if (_layer != NULL)
+ buf = gzgets((gzFile)_layer, buf, (int)buf_size);
+ else
+#endif
+ buf = fgets(buf, (int)buf_size, _file);
return buf;
}
size_t
file_case::get_buf(void *buf, size_t buf_size)
{
- return fread(buf, 1, buf_size, _file);
+ size_t rv;
+#ifdef _LAYER
+ if (_layer != NULL) {
+ int i = gzread((gzFile)_layer, buf, (unsigned int)buf_size);
+ rv = (i <= 0) ? 0 : (size_t)i;
+ } else
+#endif
+ rv = fread(buf, 1, buf_size, _file);
+ return rv;
}
void
file_case::rewind(void)
{
- ::rewind(_file);
+#ifdef _LAYER
+ if (_layer != NULL)
+ gzrewind((gzFile)_layer);
+ else
+#endif
+ ::rewind(_file);
}
int
file_case::seek(long offset, seek_whence whence)
{
- int w = (whence == seek_set ? SEEK_SET :
+ int x = (whence == seek_set ? SEEK_SET :
(whence == seek_cur ? SEEK_CUR : SEEK_END));
- return fseek(_file, offset, w);
+#ifdef _LAYER
+ if (_layer != NULL)
+ x = gzseek((gzFile)_layer, (z_off_t)offset, x);
+ else
+#endif
+ x = fseek(_file, offset, x);
+ return x;
}
/*static*/ file_case *
@@ -305,6 +412,7 @@ file_case::muxer(char const *path, uint32_t flags)
file_case *fcp;
args a;
a.a_fp = NULL;
+ a.a_layer = NULL;
a.a_path_len = strlen(a.a_path = path);
a.a_mode = (flags & mux_need_binary) ? "rb" : "r";
a.a_flags = flags;
@@ -314,10 +422,10 @@ file_case::muxer(char const *path, uint32_t flags)
// a packer's extension, i.e., explicitly. Anyway unpack then, despite flags
#ifdef HAVE_UNPACK
if (!_is_ext(&a)) {
- assert(a.a_fp == NULL);
+ assert(a.a_fp == NULL && a.a_layer == NULL);
goto jerror;
}
- if (a.a_fp != NULL)
+ if (a.a_fp != NULL || a.a_layer != NULL)
goto jnew;
#endif
@@ -328,8 +436,10 @@ file_case::muxer(char const *path, uint32_t flags)
#ifdef HAVE_UNPACK
jnew:
#endif
- assert(a.a_fp != NULL);
+ assert((a.a_fp != NULL && a.a_layer == NULL) ||
+ (a.a_fp == NULL && a.a_layer != NULL));
fcp = new file_case(a.a_fp, path, a.a_flags & ~mux_mask); // XXX real path?
+ fcp->_layer = a.a_layer;
goto jleave;
}
a.a_errno = errno;
--
2.0.0
From 3f3f721712242f86137494bf3d66861a063accdc Mon Sep 17 00:00:00 2001
Message-Id:
In-Reply-To:
References:
From: Steffen Nurpmeso
Date: Sat, 26 Jul 2014 16:22:57 +0200
Subject: [PATCH 09/20] CXX peace: src/preproc/eqn/pile.cpp (Public Domain)
---
src/preproc/eqn/pile.cpp | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/src/preproc/eqn/pile.cpp b/src/preproc/eqn/pile.cpp
index 79982d0..e35f6a9 100644
--- a/src/preproc/eqn/pile.cpp
+++ b/src/preproc/eqn/pile.cpp
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989-1992, 2004, 2007, 2009, 2013
+/* Copyright (C) 1989-1992, 2004, 2007, 2009, 2013, 2014
Free Software Foundation, Inc.
Written by James Clark (address@hidden)
@@ -106,11 +106,12 @@ void pile_box::output()
case RIGHT_ALIGN:
av = "right";
break;
+ default:
+ assert(0);
+ // FALLTHRU (pacify compiler)
case CENTER_ALIGN:
av = "center";
break;
- default:
- assert(0);
}
printf("", av);
for (int i = 0; i < col.len; i++) {
@@ -249,11 +250,12 @@ void matrix_box::output()
case RIGHT_ALIGN:
av = "right";
break;
+ default:
+ assert(0);
+ // FALLTHRU (pacify compiler)
case CENTER_ALIGN:
av = "center";
break;
- default:
- assert(0);
}
printf("", av);
p[j]->p[i]->output();
--
2.0.0
From d73d2159ee80afe7b14ecbb4d1f3b51e6038ec53 Mon Sep 17 00:00:00 2001
Message-Id:
In-Reply-To:
References:
From: Steffen Nurpmeso
Date: Sat, 26 Jul 2014 14:38:13 +0200
Subject: [PATCH 10/20] CXX peace: src/roff/troff/input.cpp (Public Domain)
---
src/roff/troff/input.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/roff/troff/input.cpp b/src/roff/troff/input.cpp
index fa2c8bd..e914413 100644
--- a/src/roff/troff/input.cpp
+++ b/src/roff/troff/input.cpp
@@ -3256,7 +3256,7 @@ macro::macro()
}
macro::macro(const macro &m)
-: filename(m.filename), lineno(m.lineno), len(m.len),
+: request_or_macro(), filename(m.filename), lineno(m.lineno), len(m.len),
empty_macro(m.empty_macro), is_a_diversion(m.is_a_diversion),
is_a_string(m.is_a_string), p(m.p)
{
--
2.0.0
From 2668aebb375cb0e236ad41776f63386a75172eb3 Mon Sep 17 00:00:00 2001
Message-Id:
In-Reply-To:
References:
From: Steffen Nurpmeso
Date: Sat, 26 Jul 2014 14:39:17 +0200
Subject: [PATCH 11/20] CXX peace: src/preproc/grn/hgraph.cpp (Public Domain)
---
src/preproc/grn/hgraph.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/preproc/grn/hgraph.cpp b/src/preproc/grn/hgraph.cpp
index 0120895..2a05b1f 100644
--- a/src/preproc/grn/hgraph.cpp
+++ b/src/preproc/grn/hgraph.cpp
@@ -597,7 +597,7 @@ HGArc(register int cx,
resolution = (1.0 + groff_hypot(xs, ys) / res) * PointsPerInterval;
/* mask = (1 << (int) log10(resolution + 1.0)) - 1; */
(void) frexp(resolution, &m); /* A bit more elegant than log10 */
- for (mask = 1; mask < m; mask = mask << 1);
+ for (mask = 1; mask < m; mask <<= 1) {;}
mask -= 1;
epsilon = 1.0 / resolution;
--
2.0.0
From 1226fbbc01136cf9753baad83d70cb01eae34b34 Mon Sep 17 00:00:00 2001
Message-Id:
In-Reply-To:
References:
From: Steffen Nurpmeso
Date: Sat, 26 Jul 2014 17:50:02 +0200
Subject: [PATCH 12/20] Preproc: use file_case::muxer() for ARGV: eqn/ (Public
Domain)
---
src/preproc/eqn/lex.cpp | 23 +++++++++++------------
1 file changed, 11 insertions(+), 12 deletions(-)
diff --git a/src/preproc/eqn/lex.cpp b/src/preproc/eqn/lex.cpp
index 899ecae..0ac8f0d 100644
--- a/src/preproc/eqn/lex.cpp
+++ b/src/preproc/eqn/lex.cpp
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989-1992, 2000-2003, 2005, 2007-2009, 2013
+/* Copyright (C) 1989-1992, 2000-2003, 2005, 2007-2009, 2013, 2014
Free Software Foundation, Inc.
Written by James Clark (address@hidden)
@@ -22,6 +22,7 @@ along with this program. If not, see . */
#include "eqn_tab.h"
#include "stringclass.h"
#include "ptable.h"
+#include "file_case.h"
// declarations to avoid friend name injection problems
@@ -333,14 +334,14 @@ public:
};
class file_input : public input {
- FILE *fp;
+ file_case *_fcp;
char *filename;
int lineno;
string line;
const char *ptr;
int read_line();
public:
- file_input(FILE *, const char *, input *);
+ file_input(file_case *, const char *, input *);
~file_input();
int get();
int peek();
@@ -394,17 +395,16 @@ int input::get_location(char **, int *)
return 0;
}
-file_input::file_input(FILE *f, const char *fn, input *p)
-: input(p), lineno(0), ptr("")
+file_input::file_input(file_case *fcp, const char *fn, input *p)
+: input(p), _fcp(fcp), lineno(0), ptr("")
{
- fp = f;
filename = strsave(fn);
}
file_input::~file_input()
{
a_delete filename;
- fclose(fp);
+ delete _fcp;
}
int file_input::read_line()
@@ -413,7 +413,7 @@ int file_input::read_line()
line.clear();
lineno++;
for (;;) {
- int c = getc(fp);
+ int c = _fcp->get_c();
if (c == EOF)
break;
else if (invalid_input_char(c))
@@ -925,13 +925,12 @@ void do_include()
}
token_buffer += '\0';
const char *filename = token_buffer.contents();
- errno = 0;
- FILE *fp = fopen(filename, "r");
- if (fp == 0) {
+ file_case *fcp = file_case::muxer(filename);
+ if (fcp == NULL) {
lex_error("can't open included file `%1'", filename);
return;
}
- current_input = new file_input(fp, filename, current_input);
+ current_input = new file_input(fcp, filename, current_input);
}
void ignore_definition()
--
2.0.0
From 34099883bc674832ebfa6e29346503a64a031dd8 Mon Sep 17 00:00:00 2001
Message-Id:
In-Reply-To:
References:
From: Steffen Nurpmeso
Date: Sat, 26 Jul 2014 22:04:46 +0200
Subject: [PATCH 13/20] Preproc: use file_case::muxer() for ARGV: grn/ (Public
Domain)
---
src/preproc/grn/main.cpp | 27 +++++++++++++++------------
1 file changed, 15 insertions(+), 12 deletions(-)
diff --git a/src/preproc/grn/main.cpp b/src/preproc/grn/main.cpp
index ee17002..f5e3b8a 100644
--- a/src/preproc/grn/main.cpp
+++ b/src/preproc/grn/main.cpp
@@ -231,8 +231,8 @@ int compatibility_flag = FALSE; /* TRUE if in compatibility mode */
void getres();
-int doinput(FILE *fp);
-void conv(register FILE *fp, int baseline);
+int doinput(file_case *fcp);
+void conv(file_case *fcp, int baseline);
void savestate();
int has_polygon(register ELT *elist);
void interpret(char *line);
@@ -284,7 +284,6 @@ main(int argc,
{
setlocale(LC_NUMERIC, "C");
program_name = argv[0];
- register FILE *fp;
register int k;
register char c;
int gfil = 0;
@@ -354,22 +353,26 @@ main(int argc,
}
for (k = 0; k < gfil; k++) {
+ file_case *fcp;
if (file[k] != NULL) {
- if ((fp = fopen(file[k], "r")) == NULL)
- fatal("can't open %1", file[k]);
+ if ((fcp = file_case::muxer(file[k])) == NULL)
+ fatal("can't open %1", file[k]);
} else
- fp = stdin;
+ fcp = new file_case(stdin, "stdin",
+ fcp->fc_dont_close | fcp->fc_const_path /*| fcp->fc_have_stdio*/);
- while (doinput(fp)) {
+ while (doinput(fcp)) {
if (*c1 == '.' && *c2 == 'G' && *c3 == 'S') {
if (compatibility_flag ||
*c4 == '\n' || *c4 == ' ' || *c4 == '\0')
- conv(fp, linenum);
+ conv(fcp, linenum);
else
fputs(inputline, stdout);
} else
fputs(inputline, stdout);
}
+
+ delete fcp;
}
return 0;
@@ -445,9 +448,9 @@ getres()
*----------------------------------------------------------------------------*/
int
-doinput(FILE *fp)
+doinput(file_case *fcp)
{
- if (fgets(inputline, MAXINLINE, fp) == NULL)
+ if (fcp->get_line(inputline, MAXINLINE) == NULL)
return 0;
if (strchr(inputline, '\n')) /* ++ only if it's a complete line */
linenum++;
@@ -512,7 +515,7 @@ initpic()
*----------------------------------------------------------------------------*/
void
-conv(register FILE *fp,
+conv(file_case *fcp,
int baseline)
{
register int done = 0; /* flag to remember if finished */
@@ -530,7 +533,7 @@ conv(register FILE *fp,
strcpy(GScommand, inputline); /* save `.GS' line for later */
do {
- done = !doinput(fp); /* test for EOF */
+ done = !doinput(fcp); /* test for EOF */
flyback = (*c3 == 'F'); /* and .GE or .GF */
compat = (compatibility_flag ||
*c4 == '\n' || *c4 == ' ' || *c4 == '\0');
--
2.0.0
From 906e29b3ab9e18e71a768fdcf058ef62ba82de71 Mon Sep 17 00:00:00 2001
Message-Id:
In-Reply-To:
References:
From: Steffen Nurpmeso
Date: Sat, 26 Jul 2014 22:04:48 +0200
Subject: [PATCH 14/20] Preproc: use file_case::muxer() for ARGV: html/ (Public
Domain)
---
src/preproc/html/pre-html.cpp | 35 +++++++++++++++++++----------------
1 file changed, 19 insertions(+), 16 deletions(-)
diff --git a/src/preproc/html/pre-html.cpp b/src/preproc/html/pre-html.cpp
index bbc2331..d5a5e49 100644
--- a/src/preproc/html/pre-html.cpp
+++ b/src/preproc/html/pre-html.cpp
@@ -416,7 +416,7 @@ class char_buffer {
public:
char_buffer();
~char_buffer();
- int read_file(FILE *fp);
+ int read_file(file_case *fcp);
int do_html(int argc, char *argv[]);
int do_image(int argc, char *argv[]);
void emit_troff_output(int device_format_selector);
@@ -457,10 +457,10 @@ char_buffer::~char_buffer()
* char_blocks.
*/
-int char_buffer::read_file(FILE *fp)
+int char_buffer::read_file(file_case *fcp)
{
int n;
- while (!feof(fp)) {
+ while (!fcp->is_eof()) {
if (tail == NULL) {
tail = new char_block;
head = tail;
@@ -473,14 +473,17 @@ int char_buffer::read_file(FILE *fp)
}
// at this point we have a tail which is ready for the next SIZE
// bytes of the file
- n = fread(tail->buffer, sizeof(char), char_block::SIZE-tail->used, fp);
- if (n <= 0)
- // error
- return 0;
- else
+ n = fcp->get_buf(tail->buffer, char_block::SIZE - tail->used);
+ if (n != 0)
tail->used += n * sizeof(char);
+ else {
+ n = fcp->is_eof();
+ goto jleave;
+ }
}
- return 1;
+ n = 1;
+jleave:
+ return n;
}
/*
@@ -1809,25 +1812,25 @@ int main(int argc, char **argv)
static int do_file(const char *filename)
{
- FILE *fp;
+ file_case *fcp;
current_filename = filename;
if (strcmp(filename, "-") == 0)
- fp = stdin;
+ fcp = new file_case(stdin, "stdin",
+ fcp->fc_dont_close | fcp->fc_const_path /*| fcp->fc_have_stdio*/);
else {
- fp = fopen(filename, "r");
- if (fp == 0) {
+ fcp = file_case::muxer(filename);
+ if (fcp == NULL) {
error("can't open `%1': %2", filename, strerror(errno));
return 0;
}
}
- if (inputFile.read_file(fp)) {
+ if (inputFile.read_file(fcp)) {
// XXX
}
- if (fp != stdin)
- fclose(fp);
+ delete fcp;
current_filename = NULL;
return 1;
}
--
2.0.0
From deff27cf7941a3a5f295735f25ba4d503ebeba1a Mon Sep 17 00:00:00 2001
Message-Id:
In-Reply-To:
References:
From: Steffen Nurpmeso
Date: Sat, 26 Jul 2014 22:04:51 +0200
Subject: [PATCH 15/20] Preproc: use file_case::muxer() for ARGV: pic/ (Public
Domain)
---
src/preproc/pic/lex.cpp | 44 +++++++++---------
src/preproc/pic/main.cpp | 118 +++++++++++++++++++++++------------------------
src/preproc/pic/pic.h | 8 ++--
3 files changed, 85 insertions(+), 85 deletions(-)
diff --git a/src/preproc/pic/lex.cpp b/src/preproc/pic/lex.cpp
index 73ef9a1..9c6df58 100644
--- a/src/preproc/pic/lex.cpp
+++ b/src/preproc/pic/lex.cpp
@@ -1,6 +1,6 @@
// -*- C++ -*-
/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2002, 2003, 2004, 2006,
- 2007, 2009
+ 2007, 2009, 2014
Free Software Foundation, Inc.
Written by James Clark (address@hidden)
@@ -75,14 +75,14 @@ int input::get_location(const char **, int *)
return 0;
}
-file_input::file_input(FILE *f, const char *fn)
-: fp(f), filename(fn), lineno(0), ptr("")
+file_input::file_input(file_case *fcp, const char *fn)
+: _fcp(fcp), filename(fn), lineno(0), ptr("")
{
}
file_input::~file_input()
{
- fclose(fp);
+ delete _fcp;
}
int file_input::read_line()
@@ -91,7 +91,7 @@ int file_input::read_line()
line.clear();
lineno++;
for (;;) {
- int c = getc(fp);
+ int c = _fcp->get_c();
if (c == EOF)
break;
else if (invalid_input_char(c))
@@ -1459,13 +1459,12 @@ void do_for(char *var, double from, double to, int by_is_multiplicative,
void do_copy(const char *filename)
{
- errno = 0;
- FILE *fp = fopen(filename, "r");
- if (fp == 0) {
+ file_case *fcp = file_case::muxer(filename);
+ if (fcp == NULL) {
lex_error("can't open `%1': %2", filename, strerror(errno));
return;
}
- input_stack::push(new file_input(fp, filename));
+ input_stack::push(new file_input(fcp, filename));
}
class copy_thru_input : public input {
@@ -1651,32 +1650,32 @@ int copy_thru_input::get_line()
class simple_file_input : public input {
const char *filename;
int lineno;
- FILE *fp;
+ file_case *_fcp;
public:
- simple_file_input(FILE *, const char *);
+ simple_file_input(file_case *, const char *);
~simple_file_input();
int get();
int peek();
int get_location(const char **, int *);
};
-simple_file_input::simple_file_input(FILE *p, const char *s)
-: filename(s), lineno(1), fp(p)
+simple_file_input::simple_file_input(file_case *fcp, const char *s)
+: filename(s), lineno(1), _fcp(fcp)
{
}
simple_file_input::~simple_file_input()
{
// don't delete the filename
- fclose(fp);
+ delete _fcp;
}
int simple_file_input::get()
{
- int c = getc(fp);
+ int c = _fcp->get_c();
while (invalid_input_char(c)) {
error("invalid input character code %1", c);
- c = getc(fp);
+ c = _fcp->get_c();
}
if (c == '\n')
lineno++;
@@ -1685,13 +1684,13 @@ int simple_file_input::get()
int simple_file_input::peek()
{
- int c = getc(fp);
+ int c = _fcp->get_c();
while (invalid_input_char(c)) {
error("invalid input character code %1", c);
- c = getc(fp);
+ c = _fcp->get_c();
}
if (c != EOF)
- ungetc(c, fp);
+ _fcp->unget_c(c);
return c;
}
@@ -1705,13 +1704,12 @@ int simple_file_input::get_location(const char **fnp, int *lnp)
void copy_file_thru(const char *filename, const char *body, const char *until)
{
- errno = 0;
- FILE *fp = fopen(filename, "r");
- if (fp == 0) {
+ file_case *fcp = file_case::muxer(filename);
+ if (fcp == NULL) {
lex_error("can't open `%1': %2", filename, strerror(errno));
return;
}
- input *in = new copy_file_thru_input(new simple_file_input(fp, filename),
+ input *in = new copy_file_thru_input(new simple_file_input(fcp, filename),
body, until);
input_stack::push(in);
}
diff --git a/src/preproc/pic/main.cpp b/src/preproc/pic/main.cpp
index f242da0..8173c5e 100644
--- a/src/preproc/pic/main.cpp
+++ b/src/preproc/pic/main.cpp
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989-1992, 2000, 2001, 2002, 2003, 2006, 2009, 2012
+/* Copyright (C) 1989-1992, 2000, 2001, 2002, 2003, 2006, 2009, 2012, 2014
Free Software Foundation, Inc.
Written by James Clark (address@hidden)
@@ -18,6 +18,8 @@ for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see . */
+#include "file_case.h"
+
#include "pic.h"
extern int yyparse();
@@ -43,19 +45,19 @@ static int had_parse_error = 0;
void do_file(const char *filename);
class top_input : public input {
- FILE *fp;
+ file_case *_fcp;
int bol;
int eof;
int push_back[3];
int start_lineno;
public:
- top_input(FILE *);
+ top_input(file_case *);
int get();
int peek();
int get_location(const char **, int *);
};
-top_input::top_input(FILE *p) : fp(p), bol(1), eof(0)
+top_input::top_input(file_case *fcp) : _fcp(fcp), bol(1), eof(0)
{
push_back[0] = push_back[1] = push_back[2] = EOF;
start_lineno = current_lineno;
@@ -80,20 +82,20 @@ int top_input::get()
push_back[0] = EOF;
return c;
}
- int c = getc(fp);
+ int c = _fcp->get_c();
while (invalid_input_char(c)) {
error("invalid input character code %1", int(c));
- c = getc(fp);
+ c = _fcp->get_c();
bol = 0;
}
if (bol && c == '.') {
- c = getc(fp);
+ c = _fcp->get_c();
if (c == 'P') {
- c = getc(fp);
+ c = _fcp->get_c();
if (c == 'F' || c == 'E') {
- int d = getc(fp);
+ int d = _fcp->get_c();
if (d != EOF)
- ungetc(d, fp);
+ _fcp->unget_c(d);
if (d == EOF || d == ' ' || d == '\n' || compatible_flag) {
eof = 1;
flyback_flag = c == 'F';
@@ -104,9 +106,9 @@ int top_input::get()
return '.';
}
if (c == 'S') {
- c = getc(fp);
- if (c != EOF)
- ungetc(c, fp);
+ c = _fcp->get_c();
+ if (c != EOF)
+ _fcp->unget_c(c);
if (c == EOF || c == ' ' || c == '\n' || compatible_flag) {
error("nested .PS");
eof = 1;
@@ -117,13 +119,13 @@ int top_input::get()
return '.';
}
if (c != EOF)
- ungetc(c, fp);
+ _fcp->unget_c(c);
push_back[0] = 'P';
return '.';
}
else {
if (c != EOF)
- ungetc(c, fp);
+ _fcp->unget_c(c);
return '.';
}
}
@@ -152,20 +154,20 @@ int top_input::peek()
return push_back[1];
if (push_back[0] != EOF)
return push_back[0];
- int c = getc(fp);
+ int c = _fcp->get_c();
while (invalid_input_char(c)) {
error("invalid input character code %1", int(c));
- c = getc(fp);
+ c = _fcp->get_c();
bol = 0;
}
if (bol && c == '.') {
- c = getc(fp);
+ c = _fcp->get_c();
if (c == 'P') {
- c = getc(fp);
+ c = _fcp->get_c();
if (c == 'F' || c == 'E') {
- int d = getc(fp);
+ int d = _fcp->get_c();
if (d != EOF)
- ungetc(d, fp);
+ _fcp->unget_c(d);
if (d == EOF || d == ' ' || d == '\n' || compatible_flag) {
eof = 1;
flyback_flag = c == 'F';
@@ -177,9 +179,9 @@ int top_input::peek()
return '.';
}
if (c == 'S') {
- c = getc(fp);
+ c = _fcp->get_c();
if (c != EOF)
- ungetc(c, fp);
+ _fcp->unget_c(c);
if (c == EOF || c == ' ' || c == '\n' || compatible_flag) {
error("nested .PS");
eof = 1;
@@ -191,20 +193,20 @@ int top_input::peek()
return '.';
}
if (c != EOF)
- ungetc(c, fp);
+ _fcp->unget_c(c);
push_back[0] = 'P';
push_back[1] = '.';
return '.';
}
else {
if (c != EOF)
- ungetc(c, fp);
+ _fcp->unget_c(c);
push_back[0] = '.';
return '.';
}
}
if (c != EOF)
- ungetc(c, fp);
+ _fcp->unget_c(c);
if (c == '\n')
return '\n';
return c;
@@ -217,25 +219,25 @@ int top_input::get_location(const char **filenamep, int *linenop)
return 1;
}
-void do_picture(FILE *fp)
+void do_picture(file_case *fcp)
{
flyback_flag = 0;
int c;
a_delete graphname;
graphname = strsave("graph"); // default picture name in TeX mode
- while ((c = getc(fp)) == ' ')
+ while ((c = fcp->get_c()) == ' ')
;
if (c == '<') {
string filename;
- while ((c = getc(fp)) == ' ')
+ while ((c = fcp->get_c()) == ' ')
;
while (c != EOF && c != ' ' && c != '\n') {
filename += char(c);
- c = getc(fp);
+ c = fcp->get_c();
}
if (c == ' ') {
do {
- c = getc(fp);
+ c = fcp->get_c();
} while (c != EOF && c != '\n');
}
if (c == '\n')
@@ -262,7 +264,7 @@ void do_picture(FILE *fp)
break;
}
start_line += c;
- c = getc(fp);
+ c = fcp->get_c();
}
if (c == EOF)
return;
@@ -280,7 +282,7 @@ void do_picture(FILE *fp)
}
out->set_desired_width_height(wid, ht);
out->set_args(start_line.contents());
- lex_init(new top_input(fp));
+ lex_init(new top_input(fcp));
if (yyparse()) {
had_parse_error = 1;
lex_error("giving up on this picture");
@@ -289,7 +291,7 @@ void do_picture(FILE *fp)
lex_cleanup();
// skip the rest of the .PF/.PE line
- while ((c = getc(fp)) != EOF && c != '\n')
+ while ((c = fcp->get_c()) != EOF && c != '\n')
;
if (c == '\n')
current_lineno++;
@@ -299,26 +301,24 @@ void do_picture(FILE *fp)
void do_file(const char *filename)
{
- FILE *fp;
+ file_case *fcp;
if (strcmp(filename, "-") == 0)
- fp = stdin;
- else {
- errno = 0;
- fp = fopen(filename, "r");
- if (fp == 0) {
- delete out;
- fatal("can't open `%1': %2", filename, strerror(errno));
- }
+ fcp = new file_case(stdin, "stdin",
+ fcp->fc_dont_close | fcp->fc_const_path /*| fcp->fc_have_stdio*/);
+ else if ((fcp = file_case::muxer(filename)) == NULL) {
+ delete out;
+ fatal("can't open `%1': %2", filename, strerror(errno));
}
+
out->set_location(filename, 1);
current_filename = filename;
current_lineno = 1;
enum { START, MIDDLE, HAD_DOT, HAD_P, HAD_PS, HAD_l, HAD_lf } state = START;
for (;;) {
- int c = getc(fp);
+ int c = fcp->get_c();
while (invalid_input_char(c)) {
error("invalid input character code %1", int(c));
- c = getc(fp);
+ c = fcp->get_c();
}
if (c == EOF)
break;
@@ -376,8 +376,8 @@ void do_file(const char *filename)
break;
case HAD_PS:
if (c == ' ' || c == '\n' || compatible_flag) {
- ungetc(c, fp);
- do_picture(fp);
+ fcp->unget_c(c);
+ do_picture(fcp);
state = START;
}
else {
@@ -410,7 +410,7 @@ void do_file(const char *filename)
current_lineno++;
break;
}
- c = getc(fp);
+ c = fcp->get_c();
}
line += '\0';
interpret_lf_args(line.contents());
@@ -449,28 +449,28 @@ void do_file(const char *filename)
fputs(".lf\n", stdout);
break;
}
- if (fp != stdin)
- fclose(fp);
+
+ delete fcp;
}
#ifdef FIG_SUPPORT
void do_whole_file(const char *filename)
{
// Do not set current_filename.
- FILE *fp;
+ file_case *fcp;
if (strcmp(filename, "-") == 0)
- fp = stdin;
- else {
- errno = 0;
- fp = fopen(filename, "r");
- if (fp == 0)
- fatal("can't open `%1': %2", filename, strerror(errno));
- }
- lex_init(new file_input(fp, filename));
+ fcp = new file_case(stdin, "stdin",
+ fcp->fc_dont_close | fcp->fc_const_path /*| fcp->fc_have_stdio*/);
+ else if ((fcp = file_case::muxer(filename)) == NULL)
+ fatal("can't open `%1': %2", filename, strerror(errno));
+
+ lex_init(new file_input(fcp, filename));
if (yyparse())
had_parse_error = 1;
parse_cleanup();
lex_cleanup();
+
+ delete fcp;
}
#endif
diff --git a/src/preproc/pic/pic.h b/src/preproc/pic/pic.h
index b32b7d6..1ca726f 100644
--- a/src/preproc/pic/pic.h
+++ b/src/preproc/pic/pic.h
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2003, 2005, 2009
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2003, 2005, 2009, 2014
Free Software Foundation, Inc.
Written by James Clark (address@hidden)
@@ -24,6 +24,8 @@ along with this program. If not, see . */
#include
#include
+#include "file_case.h"
+
#ifdef NEED_DECLARATION_RAND
#undef rand
extern "C" {
@@ -78,14 +80,14 @@ public:
};
class file_input : public input {
- FILE *fp;
+ file_case *_fcp;
const char *filename;
int lineno;
string line;
const char *ptr;
int read_line();
public:
- file_input(FILE *, const char *);
+ file_input(file_case *, const char *);
~file_input();
int get();
int peek();
--
2.0.0
From b62209ee131f879259575150b389a32a54f86565 Mon Sep 17 00:00:00 2001
Message-Id:
In-Reply-To:
References:
From: Steffen Nurpmeso
Date: Sat, 26 Jul 2014 23:39:34 +0200
Subject: [PATCH 16/20] Preproc: use file_case::muxer() for ARGV: preconv/
(Public Domain)
---
src/preproc/preconv/preconv.cpp | 77 ++++++++++++++++++++---------------------
1 file changed, 38 insertions(+), 39 deletions(-)
diff --git a/src/preproc/preconv/preconv.cpp b/src/preproc/preconv/preconv.cpp
index d09fc1c..ed770c3 100644
--- a/src/preproc/preconv/preconv.cpp
+++ b/src/preproc/preconv/preconv.cpp
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 2005, 2006, 2008, 2009
+/* Copyright (C) 2005, 2006, 2008, 2009, 2014
Free Software Foundation, Inc.
Written by Werner Lemberg (address@hidden)
@@ -25,6 +25,7 @@ along with this program. If not, see . */
#include
#include "errarg.h"
#include "error.h"
+#include "file_case.h"
#include "localcharset.h"
#include "nonposix.h"
#include "stringclass.h"
@@ -419,14 +420,14 @@ unicode_entity(int u)
// Conversion from ISO-8859-1 (aka Latin-1) to Unicode.
void
-conversion_latin1(FILE *fp, const string &data)
+conversion_latin1(file_case *fcp, const string &data)
{
int len = data.length();
const unsigned char *ptr = (const unsigned char *)data.contents();
for (int i = 0; i < len; i++)
unicode_entity(ptr[i]);
int c = -1;
- while ((c = getc(fp)) != EOF)
+ while ((c = fcp->get_c()) != EOF)
unicode_entity(c);
}
@@ -435,7 +436,7 @@ conversion_latin1(FILE *fp, const string &data)
// moved to the troff program.
struct utf8 {
- FILE *fp;
+ file_case *_fcp;
unsigned char s[6];
enum {
FIRST = 0,
@@ -448,14 +449,14 @@ struct utf8 {
int expected_bytes;
int invalid_warning;
int incomplete_warning;
- utf8(FILE *);
+ utf8(file_case *);
~utf8();
void add(unsigned char);
void invalid();
void incomplete();
};
-utf8::utf8(FILE *f) : fp(f), byte(FIRST), expected_bytes(1),
+utf8::utf8(file_case *fcp) : _fcp(fcp), byte(FIRST), expected_bytes(1),
invalid_warning(1), incomplete_warning(1)
{
// empty
@@ -591,22 +592,22 @@ utf8::incomplete()
// Conversion from UTF-8 to Unicode.
void
-conversion_utf8(FILE *fp, const string &data)
+conversion_utf8(file_case *fcp, const string &data)
{
- utf8 u(fp);
+ utf8 u(fcp);
int len = data.length();
const unsigned char *ptr = (const unsigned char *)data.contents();
for (int i = 0; i < len; i++)
u.add(ptr[i]);
int c = -1;
- while ((c = getc(fp)) != EOF)
+ while ((c = fcp->get_c()) != EOF)
u.add(c);
return;
}
// Conversion from cp1047 (EBCDIC) to UTF-8.
void
-conversion_cp1047(FILE *fp, const string &data)
+conversion_cp1047(file_case *fcp, const string &data)
{
static unsigned char cp1047[] = {
0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F, // 0x00
@@ -647,14 +648,14 @@ conversion_cp1047(FILE *fp, const string &data)
for (int i = 0; i < len; i++)
unicode_entity(cp1047[ptr[i]]);
int c = -1;
- while ((c = getc(fp)) != EOF)
+ while ((c = fcp->get_c()) != EOF)
unicode_entity(cp1047[c]);
}
// Locale-sensible conversion.
#if HAVE_ICONV
void
-conversion_iconv(FILE *fp, const string &data, char *enc)
+conversion_iconv(file_case *fcp, const string &data, char *enc)
{
iconv_t handle = iconv_open(UNICODE, enc);
if (handle == (iconv_t)-1) {
@@ -701,7 +702,7 @@ conversion_iconv(FILE *fp, const string &data, char *enc)
// Handle `fp' and switch to `inbuf'.
size_t read_bytes;
char *read_start = inbuf + inbytes_left;
- while ((read_bytes = fread(read_start, 1, BUFSIZ - inbytes_left, fp)) > 0) {
+ while ((read_bytes = fcp->get_buf(read_start, BUFSIZ - inbytes_left)) > 0) {
inptr = inbuf;
inbytes_left += read_bytes;
while (inbytes_left > 0) {
@@ -756,7 +757,7 @@ conversion_iconv(FILE *fp, const string &data, char *enc)
// Return encoding if a BOM is found, NULL otherwise.
// ---------------------------------------------------------
const char *
-get_BOM(FILE *fp, string &BOM, string &data)
+get_BOM(file_case *fcp, string &BOM, string &data)
{
// The BOM is U+FEFF. We have thus the following possible
// representations.
@@ -780,7 +781,7 @@ get_BOM(FILE *fp, string &BOM, string &data)
const char *retval = NULL;
int len;
for (len = 0; len < 4; len++) {
- int c = getc(fp);
+ int c = fcp->get_c();
if (c == EOF)
break;
BOM_string[len] = char(c);
@@ -810,7 +811,7 @@ get_BOM(FILE *fp, string &BOM, string &data)
// (which is stored unmodified in `data').
// ---------------------------------------------------------
char *
-get_tag_lines(FILE *fp, string &data)
+get_tag_lines(file_case *fcp, string &data)
{
int newline_count = 0;
int c, prev = -1;
@@ -827,7 +828,7 @@ get_tag_lines(FILE *fp, string &data)
return NULL;
int emit_warning = 1;
for (int lines = newline_count; lines < 2; lines++) {
- while ((c = getc(fp)) != EOF) {
+ while ((c = fcp->get_c()) != EOF) {
if (c == '\0' && debug_flag && emit_warning) {
fprintf(stderr,
" null byte(s) found in input stream --\n"
@@ -840,9 +841,9 @@ get_tag_lines(FILE *fp, string &data)
}
// Handle CR, LF, and CRLF as line separators.
if (c == '\r') {
- c = getc(fp);
+ c = fcp->get_c();
if (c != EOF && c != '\n')
- ungetc(c, fp);
+ fcp->unget_c(c);
else
data += char(c);
}
@@ -965,9 +966,9 @@ get_variable_value_pair(char *d1, char **variable, char **value)
// XXX Add support for tag at the end of buffer.
// ---------------------------------------------------------
char *
-check_coding_tag(FILE *fp, string &data)
+check_coding_tag(file_case *fcp, string &data)
{
- char *inbuf = get_tag_lines(fp, data);
+ char *inbuf = get_tag_lines(fcp, data);
char *lineend;
for (char *p = inbuf; is_comment_line(p); p = lineend + 1) {
if ((lineend = strchr(p, '\n')) == NULL)
@@ -1005,24 +1006,22 @@ check_coding_tag(FILE *fp, string &data)
int
do_file(const char *filename)
{
- FILE *fp;
+ file_case *fcp;
string BOM, data;
+ if (debug_flag)
+ fprintf(stderr, "file `%s':\n", filename);
if (strcmp(filename, "-")) {
- if (debug_flag)
- fprintf(stderr, "file `%s':\n", filename);
- fp = fopen(filename, FOPEN_RB);
- if (!fp) {
+ if ((fcp = file_case::muxer(filename, fcp->mux_need_binary)) == NULL) {
error("can't open `%1': %2", filename, strerror(errno));
return 0;
}
- }
- else {
- if (debug_flag)
- fprintf(stderr, "standard input:\n");
+ } else {
SET_BINARY(fileno(stdin));
- fp = stdin;
+ fcp = new file_case(stdin, "stdin",
+ fcp->fc_dont_close | fcp->fc_const_path /*| fcp->fc_have_stdio*/);
}
- const char *BOM_encoding = get_BOM(fp, BOM, data);
+
+ const char *BOM_encoding = get_BOM(fcp, BOM, data);
// Determine the encoding.
char *encoding;
if (user_encoding[0]) {
@@ -1043,7 +1042,7 @@ do_file(const char *filename)
}
else {
// `check_coding_tag' returns a pointer to a static array (or NULL).
- char *file_encoding = check_coding_tag(fp, data);
+ char *file_encoding = check_coding_tag(fcp, data);
if (!file_encoding) {
if (debug_flag)
fprintf(stderr, " no file encoding\n");
@@ -1071,21 +1070,21 @@ do_file(const char *filename)
int success = 1;
// Call converter (converters write to stdout).
if (!strcasecmp(encoding, "ISO-8859-1"))
- conversion_latin1(fp, BOM + data);
+ conversion_latin1(fcp, BOM + data);
else if (!strcasecmp(encoding, "UTF-8"))
- conversion_utf8(fp, data);
+ conversion_utf8(fcp, data);
else if (!strcasecmp(encoding, "cp1047"))
- conversion_cp1047(fp, BOM + data);
+ conversion_cp1047(fcp, BOM + data);
else {
#if HAVE_ICONV
- conversion_iconv(fp, BOM + data, encoding);
+ conversion_iconv(fcp, BOM + data, encoding);
#else
error("encoding system `%1' not supported", encoding);
success = 0;
#endif /* HAVE_ICONV */
}
- if (fp != stdin)
- fclose(fp);
+
+ delete fcp;
return success;
}
--
2.0.0
From 09565d1eca8b0bd5b2d9630d2e8e20463ff89b51 Mon Sep 17 00:00:00 2001
Message-Id:
In-Reply-To:
References:
From: Steffen Nurpmeso
Date: Sun, 27 Jul 2014 01:01:28 +0200
Subject: [PATCH 17/20] Preproc: use file_case::muxer() for ARGV: refer/
(Public Domain)
---
src/preproc/refer/command.cpp | 32 ++++++++++++------------
src/preproc/refer/refer.cpp | 57 ++++++++++++++++++++-----------------------
2 files changed, 43 insertions(+), 46 deletions(-)
diff --git a/src/preproc/refer/command.cpp b/src/preproc/refer/command.cpp
index 33bc9c2..cd10c26 100644
--- a/src/preproc/refer/command.cpp
+++ b/src/preproc/refer/command.cpp
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002, 2004, 2006, 2009
+/* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002, 2004, 2006, 2009, 2014
Free Software Foundation, Inc.
Written by James Clark (address@hidden)
@@ -21,6 +21,7 @@ along with this program. If not, see . */
#include "refer.h"
#include "refid.h"
#include "search.h"
+#include "file_case.h"
#include "command.h"
cset cs_field_name = csalpha;
@@ -147,35 +148,35 @@ int input_stack::peek_char()
void input_stack::push_file(const char *fn)
{
- FILE *fp;
+ file_case *fcp;
if (strcmp(fn, "-") == 0) {
- fp = stdin;
+ fcp = new file_case(stdin, "stdin",
+ fcp->fc_dont_close | fcp->fc_const_path /*| fcp->fc_have_stdio*/);
fn = "";
- }
- else {
- errno = 0;
- fp = fopen(fn, "r");
- if (fp == 0) {
+ } else {
+ fcp = file_case::muxer(fn);
+ if (fcp == NULL) {
error("can't open `%1': %2", fn, strerror(errno));
return;
}
}
+
string buf;
int bol = 1;
int lineno = 1;
for (;;) {
- int c = getc(fp);
+ int c = fcp->get_c();
if (bol && c == '.') {
// replace lines beginning with .R1 or .R2 with a blank line
- c = getc(fp);
+ c = fcp->get_c();
if (c == 'R') {
- c = getc(fp);
+ c = fcp->get_c();
if (c == '1' || c == '2') {
int cc = c;
- c = getc(fp);
+ c = fcp->get_c();
if (compatible_flag || c == ' ' || c == '\n' || c == EOF) {
while (c != '\n' && c != EOF)
- c = getc(fp);
+ c = fcp->get_c();
}
else {
buf += '.';
@@ -206,8 +207,9 @@ void input_stack::push_file(const char *fn)
bol = 0;
}
}
- if (fp != stdin)
- fclose(fp);
+
+ delete fcp;
+
if (buf.length() > 0 && buf[buf.length() - 1] != '\n')
buf += '\n';
input_item *it = new input_item(buf, fn);
diff --git a/src/preproc/refer/refer.cpp b/src/preproc/refer/refer.cpp
index 292d0e7..2395bb8 100644
--- a/src/preproc/refer/refer.cpp
+++ b/src/preproc/refer/refer.cpp
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989-1992, 2000, 2001, 2002, 2004, 2006, 2009
+/* Copyright (C) 1989-1992, 2000, 2001, 2002, 2004, 2006, 2009, 2014
Free Software Foundation, Inc.
Written by James Clark (address@hidden)
@@ -23,6 +23,7 @@ along with this program. If not, see . */
#include "ref.h"
#include "token.h"
#include "search.h"
+#include "file_case.h"
#include "command.h"
extern "C" const char *Version_string;
@@ -421,18 +422,13 @@ static int is_list(const string &str)
static void do_file(const char *filename)
{
- FILE *fp;
- if (strcmp(filename, "-") == 0) {
- fp = stdin;
- }
- else {
- errno = 0;
- fp = fopen(filename, "r");
- if (fp == 0) {
- error("can't open `%1': %2", filename, strerror(errno));
- return;
- }
+ file_case *fcp;
+ if ((fcp = file_case::muxer(filename)) == NULL) {
+ assert(strcmp(filename, "-"));
+ error("can't open `%1': %2", filename, strerror(errno));
+ return;
}
+
current_filename = filename;
fprintf(outfp, ".lf 1 %s\n", filename);
string line;
@@ -440,7 +436,7 @@ static void do_file(const char *filename)
for (;;) {
line.clear();
for (;;) {
- int c = getc(fp);
+ int c = fcp->get_c();
if (c == EOF) {
if (line.length() > 0)
line += '\n';
@@ -465,7 +461,7 @@ static void do_file(const char *filename)
string post;
string pre(line.contents() + 2, line.length() - 3);
for (;;) {
- int c = getc(fp);
+ int c = fcp->get_c();
if (c == EOF) {
error_with_file_and_line(current_filename, start_lineno,
"missing `.]' line");
@@ -474,9 +470,9 @@ static void do_file(const char *filename)
if (start_of_line)
current_lineno++;
if (start_of_line && c == '.') {
- int d = getc(fp);
+ int d = fcp->get_c();
if (d == ']') {
- while ((d = getc(fp)) != '\n' && d != EOF) {
+ while ((d = fcp->get_c()) != '\n' && d != EOF) {
if (invalid_input_char(d))
error("invalid input character code %1", d);
else
@@ -485,7 +481,7 @@ static void do_file(const char *filename)
break;
}
if (d != EOF)
- ungetc(d, fp);
+ fcp->unget_c(d);
}
if (invalid_input_char(c))
error("invalid input character code %1", c);
@@ -548,21 +544,20 @@ static void do_file(const char *filename)
int start_of_line = 1;
int start_lineno = current_lineno;
for (;;) {
- int c = getc(fp);
+ int c = fcp->get_c();
if (c != EOF && start_of_line)
current_lineno++;
if (start_of_line && c == '.') {
- c = getc(fp);
- if (c == 'R') {
- c = getc(fp);
- if (c == '2') {
- c = getc(fp);
- if (compatible_flag || c == ' ' || c == '\n' || c == EOF) {
- while (c != EOF && c != '\n')
- c = getc(fp);
- break;
- }
- else {
+ c = fcp->get_c();
+ if (c == 'R') {
+ c = fcp->get_c();
+ if (c == '2') {
+ c = fcp->get_c();
+ if (compatible_flag || c == ' ' || c == '\n' || c == EOF) {
+ while (c != EOF && c != '\n')
+ c = fcp->get_c();
+ break;
+ } else {
line += '.';
line += 'R';
line += '2';
@@ -603,8 +598,8 @@ static void do_file(const char *filename)
}
need_syncing = 0;
output_pending_line();
- if (fp != stdin)
- fclose(fp);
+
+ delete fcp;
}
class label_processing_state {
--
2.0.0
From 69ea78919fbe3141022b1891ef89d056a11bd462 Mon Sep 17 00:00:00 2001
Message-Id:
In-Reply-To:
References:
From: Steffen Nurpmeso
Date: Sat, 26 Jul 2014 22:04:57 +0200
Subject: [PATCH 18/20] Preproc: use file_case::muxer() for ARGV: tbl/ (Public
Domain)
---
src/preproc/tbl/main.cpp | 100 ++++++++++++++++++++++-------------------------
1 file changed, 47 insertions(+), 53 deletions(-)
diff --git a/src/preproc/tbl/main.cpp b/src/preproc/tbl/main.cpp
index 8732db9..38195de 100644
--- a/src/preproc/tbl/main.cpp
+++ b/src/preproc/tbl/main.cpp
@@ -1,6 +1,6 @@
// -*- C++ -*-
/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002, 2003, 2004, 2005,
- 2007, 2008, 2009, 2010
+ 2007, 2008, 2009, 2010, 2014
Free Software Foundation, Inc.
Written by James Clark (address@hidden)
@@ -19,6 +19,8 @@ for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see . */
+#include "file_case.h"
+
#include "table.h"
#define MAX_POINT_SIZE 99
@@ -29,21 +31,21 @@ extern "C" const char *Version_string;
int compatible_flag = 0;
class table_input {
- FILE *fp;
+ file_case *_fcp;
enum { START, MIDDLE,
REREAD_T, REREAD_TE, REREAD_E,
LEADER_1, LEADER_2, LEADER_3, LEADER_4,
END, ERROR } state;
string unget_stack;
public:
- table_input(FILE *);
+ table_input(file_case *);
int get();
int ended() { return unget_stack.empty() && state == END; }
void unget(char);
};
-table_input::table_input(FILE *p)
-: fp(p), state(START)
+table_input::table_input(file_case *fcp)
+: _fcp(fcp), state(START)
{
}
@@ -69,17 +71,17 @@ int table_input::get()
for (;;) {
switch (state) {
case START:
- if ((c = getc(fp)) == '.') {
- if ((c = getc(fp)) == 'T') {
- if ((c = getc(fp)) == 'E') {
+ if ((c = _fcp->get_c()) == '.') {
+ if ((c = _fcp->get_c()) == 'T') {
+ if ((c = _fcp->get_c()) == 'E') {
if (compatible_flag) {
state = END;
return EOF;
}
else {
- c = getc(fp);
+ c = _fcp->get_c();
if (c != EOF)
- ungetc(c, fp);
+ _fcp->unget_c(c);
if (c == EOF || c == ' ' || c == '\n') {
state = END;
return EOF;
@@ -90,14 +92,14 @@ int table_input::get()
}
else {
if (c != EOF)
- ungetc(c, fp);
+ _fcp->unget_c(c);
state = REREAD_T;
return '.';
}
}
else {
if (c != EOF)
- ungetc(c, fp);
+ _fcp->unget_c(c);
state = MIDDLE;
return '.';
}
@@ -121,18 +123,18 @@ int table_input::get()
break;
case MIDDLE:
// handle line continuation and uninterpreted leader character
- if ((c = getc(fp)) == '\\') {
- c = getc(fp);
- if (c == '\n')
- c = getc(fp); // perhaps state ought to be START now
+ if ((c = _fcp->get_c()) == '\\') {
+ c = _fcp->get_c();
+ if (c == '\n')
+ c = _fcp->get_c(); // perhaps state ought to be START now
else if (c == 'a' && compatible_flag) {
state = LEADER_1;
return '\\';
}
else {
- if (c != EOF)
- ungetc(c, fp);
- c = '\\';
+ if (c != EOF)
+ _fcp->unget_c(c);
+ c = '\\';
}
}
if (c == EOF) {
@@ -178,15 +180,15 @@ int table_input::get()
}
}
-void process_input_file(FILE *);
+void process_input_file(file_case *);
void process_table(table_input &in);
-void process_input_file(FILE *fp)
+void process_input_file(file_case *fcp)
{
enum { START, MIDDLE, HAD_DOT, HAD_T, HAD_TS, HAD_l, HAD_lf } state;
state = START;
int c;
- while ((c = getc(fp)) != EOF)
+ while ((c = fcp->get_c()) != EOF)
switch (state) {
case START:
if (c == '.')
@@ -248,17 +250,17 @@ void process_input_file(FILE *fp)
return;
}
putchar(c);
- c = getc(fp);
+ c = fcp->get_c();
}
putchar('\n');
current_lineno++;
{
- table_input input(fp);
+ table_input input(fcp);
process_table(input);
set_troff_location(current_filename, current_lineno);
if (input.ended()) {
fputs(".TE", stdout);
- while ((c = getc(fp)) != '\n') {
+ while ((c = fcp->get_c()) != '\n') {
if (c == EOF) {
putchar('\n');
return;
@@ -301,7 +303,7 @@ void process_input_file(FILE *fp)
current_lineno++;
break;
}
- c = getc(fp);
+ c = fcp->get_c();
}
line += '\0';
interpret_lf_args(line.contents());
@@ -339,8 +341,6 @@ void process_input_file(FILE *fp)
fputs(".TS\n", stdout);
break;
}
- if (fp != stdin)
- fclose(fp);
}
struct options {
@@ -1602,33 +1602,27 @@ int main(int argc, char **argv)
printf(".if !\\n(.g .ab GNU tbl requires GNU troff.\n"
".if !dTS .ds TS\n"
".if !dTE .ds TE\n");
- if (argc > optind) {
- for (int i = optind; i < argc; i++)
- if (argv[i][0] == '-' && argv[i][1] == '\0') {
- current_filename = "-";
- current_lineno = 1;
- printf(".lf 1 -\n");
- process_input_file(stdin);
- }
- else {
- errno = 0;
- FILE *fp = fopen(argv[i], "r");
- if (fp == 0)
- fatal("can't open `%1': %2", argv[i], strerror(errno));
- else {
- current_lineno = 1;
- current_filename = argv[i];
- printf(".lf 1 %s\n", current_filename);
- process_input_file(fp);
- }
- }
- }
- else {
- current_filename = "-";
+
+ file_case *fcp;
+ int i = optind;
+ if (i >= argc)
+ goto jstdin;
+ for (; i < argc; ++i) {
+ if (!strcmp(argv[i], "-")) {
+jstdin:
+ fcp = new file_case(stdin, "stdin",
+ fcp->fc_dont_close | fcp->fc_const_path /*| fcp->fc_have_stdio*/);
+ current_filename = "-";
+ } else if ((fcp = file_case::muxer(current_filename = argv[i])) == NULL)
+ fatal("can't open `%1': %2", argv[i], strerror(errno));
+
current_lineno = 1;
- printf(".lf 1 -\n");
- process_input_file(stdin);
+ printf(".lf 1 %s\n", current_filename);
+ process_input_file(fcp);
+
+ delete fcp;
}
+
if (ferror(stdout) || fflush(stdout) < 0)
fatal("output error");
return 0;
--
2.0.0
From a3daa945f1c9bc7ad7e7762f0122440000820e62 Mon Sep 17 00:00:00 2001
Message-Id:
In-Reply-To:
References:
From: Steffen Nurpmeso
Date: Sun, 27 Jul 2014 00:14:32 +0200
Subject: [PATCH 19/20] file_case: add support for "-" a.k.a. stdin (Public
Domain)
---
src/include/file_case.h | 4 +++-
src/libs/libgroff/file_case.cpp | 22 ++++++++++++++++++----
2 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/src/include/file_case.h b/src/include/file_case.h
index 07f21d7..ab64e2e 100644
--- a/src/include/file_case.h
+++ b/src/include/file_case.h
@@ -51,6 +51,7 @@ public:
mux_unpack = 1<<(_fc_freebit+2), // Do auto-check for FILE{.gz,.bz2..}
mux_no_unpack = 1<<(_fc_freebit+3), // Do NOT auto-check
mux_need_stdio = 1<<(_fc_freebit+4), // Only then may .file() be used
+ _mux_freebit = _fc_freebit + 5,
mux_mask = ~fc_mask,
mux_default = fc_none,
// Defines the global default strategy for dealing with packed files in case
@@ -81,7 +82,8 @@ public:
int seek(long offset, seek_whence whence=seek_set);
// Factory muxer; note that fc_take_path will be honoured even on failure
- static file_case * muxer(char const *path, uint32_t flags=mux_default);
+ // If path is NULL or "-" we'll go for stdin
+ static file_case * muxer(char const *path=NULL, uint32_t flags=mux_default);
CLASS_DISABLE_COPY(file_case);
};
diff --git a/src/libs/libgroff/file_case.cpp b/src/libs/libgroff/file_case.cpp
index f47c4f2..0b85a79 100644
--- a/src/libs/libgroff/file_case.cpp
+++ b/src/libs/libgroff/file_case.cpp
@@ -396,13 +396,19 @@ file_case::seek(long offset, seek_whence whence)
/*static*/ file_case *
file_case::muxer(char const *path, uint32_t flags)
{
+ enum {tmpbit = 1<<(_mux_freebit+0)};
+
assert(!(flags & (fc_dont_close | fc_pipe)));
assert(!(flags & (fc_const_path | fc_take_path)) ||
!(flags & fc_const_path) != !(flags & fc_take_path));
assert(!(flags & (mux_unpack | mux_no_unpack)) ||
!(flags & mux_unpack) != !(flags & mux_no_unpack));
- if (!(flags & (fc_const_path | fc_take_path))) {
+ if (path == NULL || (path[0] == '-' && path[1] == '\0')) {
+ path = "-";
+ flags &= ~fc_take_path;
+ flags |= fc_const_path | tmpbit;
+ } else if (!(flags & (fc_const_path | fc_take_path))) {
path = strsave(path);
flags |= fc_take_path;
}
@@ -418,6 +424,16 @@ file_case::muxer(char const *path, uint32_t flags)
a.a_flags = flags;
a.a_errno = 0;
+ // Shorthand: support "-" to mean stdin
+ if (flags & tmpbit) {
+ clearerr(stdin);
+ if (flags & mux_need_binary)
+ SET_BINARY(fileno(stdin));
+ a.a_fp = stdin;
+ a.a_flags |= fc_dont_close | fc_const_path | fc_have_stdio;
+ goto jnew;
+ }
+
// If we support unpacking then check wether the path already includes
// a packer's extension, i.e., explicitly. Anyway unpack then, despite flags
#ifdef HAVE_UNPACK
@@ -433,12 +449,10 @@ file_case::muxer(char const *path, uint32_t flags)
errno = 0;
if ((a.a_fp = fopen(a.a_path, a.a_mode)) != NULL) {
a.a_flags |= fc_have_stdio;
-#ifdef HAVE_UNPACK
jnew:
-#endif
assert((a.a_fp != NULL && a.a_layer == NULL) ||
(a.a_fp == NULL && a.a_layer != NULL));
- fcp = new file_case(a.a_fp, path, a.a_flags & ~mux_mask); // XXX real path?
+ fcp = new file_case(a.a_fp, path, a.a_flags & fc_mask); // XXX real path?
fcp->_layer = a.a_layer;
goto jleave;
}
--
2.0.0
From 66f424fcf8ec2929112e74bd7d415847547c14be Mon Sep 17 00:00:00 2001
Message-Id:
In-Reply-To:
References:
From: Steffen Nurpmeso
Date: Sun, 27 Jul 2014 00:20:27 +0200
Subject: [PATCH 20/20] Many: use stdin support of file_case::muxer() (Public
Domain)
---
src/libs/libgroff/searchpath.cpp | 13 +++++--------
src/preproc/eqn/main.cpp | 27 +++++++++++----------------
src/preproc/grn/main.cpp | 10 ++++------
src/preproc/html/pre-html.cpp | 14 +++++---------
src/preproc/pic/main.cpp | 13 +++++--------
src/preproc/preconv/preconv.cpp | 17 ++++++-----------
src/preproc/refer/command.cpp | 18 +++++++-----------
src/preproc/tbl/main.cpp | 17 ++++++-----------
src/roff/troff/input.cpp | 10 +++-------
9 files changed, 52 insertions(+), 87 deletions(-)
diff --git a/src/libs/libgroff/searchpath.cpp b/src/libs/libgroff/searchpath.cpp
index 4a0561d..d84b1f7 100644
--- a/src/libs/libgroff/searchpath.cpp
+++ b/src/libs/libgroff/searchpath.cpp
@@ -153,16 +153,13 @@ file_case *search_path::open_file(char const *name, uint32_t flags)
file_case *search_path::open_file_cautious(char const *name, uint32_t flags)
{
- assert(name != NULL);
-
file_case *fcp;
if (name == NULL || strcmp(name, "-") == 0) {
- flags &= ~(fcp->fc_take_path);
- flags |= fcp->fc_dont_close | fcp->fc_const_path | fcp->fc_have_stdio;
- if (flags & fcp->mux_need_binary)
- SET_BINARY(fileno(stdin));
- fcp = new file_case(stdin, "stdin", flags);
- } else if (IS_ABSOLUTE(name) || *dirs == '\0')
+ name = NULL;
+ goto jmuxer;
+ }
+ if (IS_ABSOLUTE(name) || *dirs == '\0')
+jmuxer:
fcp = file_case::muxer(name, flags);
else
fcp = _try_iter(dirs, name, flags);
diff --git a/src/preproc/eqn/main.cpp b/src/preproc/eqn/main.cpp
index b2a3ba1..12b22a6 100644
--- a/src/preproc/eqn/main.cpp
+++ b/src/preproc/eqn/main.cpp
@@ -399,23 +399,18 @@ int main(int argc, char **argv)
delete fcp;
}
}
- int i = optind;
- if (i >= argc)
- goto jstdin;
- for (; i < argc; ++i) {
- if (!strcmp(argv[i], "-")) {
-jstdin:
- fcp = new file_case(stdin, "stdin",
- fcp->fc_dont_close | fcp->fc_const_path /*| fcp->fc_have_stdio*/);
- do_file(fcp, "-");
- } else {
- fcp = file_case::muxer(argv[i]);
- if (fcp == NULL)
- fatal("can't open `%1': %2", argv[i], strerror(errno));
- do_file(fcp, argv[i]);
- }
+
+ do /*while (optind < argc)*/ {
+ char const *name = argv[optind++];
+ fcp = file_case::muxer(name);
+ if (name == NULL)
+ name = "-";
+ if (fcp == NULL)
+ fatal("can't open `%1': %2", name, strerror(errno));
+ do_file(fcp, name);
delete fcp;
- }
+ } while (optind < argc);
+
if (ferror(stdout) || fflush(stdout) < 0)
fatal("output error");
return 0;
diff --git a/src/preproc/grn/main.cpp b/src/preproc/grn/main.cpp
index f5e3b8a..c61642f 100644
--- a/src/preproc/grn/main.cpp
+++ b/src/preproc/grn/main.cpp
@@ -354,12 +354,10 @@ main(int argc,
for (k = 0; k < gfil; k++) {
file_case *fcp;
- if (file[k] != NULL) {
- if ((fcp = file_case::muxer(file[k])) == NULL)
- fatal("can't open %1", file[k]);
- } else
- fcp = new file_case(stdin, "stdin",
- fcp->fc_dont_close | fcp->fc_const_path /*| fcp->fc_have_stdio*/);
+ if ((fcp = file_case::muxer(file[k])) == NULL) {
+ assert(file[k] != NULL);
+ fatal("can't open %1", file[k]);
+ }
while (doinput(fcp)) {
if (*c1 == '.' && *c2 == 'G' && *c3 == 'S') {
diff --git a/src/preproc/html/pre-html.cpp b/src/preproc/html/pre-html.cpp
index d5a5e49..f4482a6 100644
--- a/src/preproc/html/pre-html.cpp
+++ b/src/preproc/html/pre-html.cpp
@@ -1815,15 +1815,11 @@ static int do_file(const char *filename)
file_case *fcp;
current_filename = filename;
- if (strcmp(filename, "-") == 0)
- fcp = new file_case(stdin, "stdin",
- fcp->fc_dont_close | fcp->fc_const_path /*| fcp->fc_have_stdio*/);
- else {
- fcp = file_case::muxer(filename);
- if (fcp == NULL) {
- error("can't open `%1': %2", filename, strerror(errno));
- return 0;
- }
+ fcp = file_case::muxer(filename);
+ if (fcp == NULL) {
+ assert(strcmp(filename, "-"));
+ error("can't open `%1': %2", filename, strerror(errno));
+ return 0;
}
if (inputFile.read_file(fcp)) {
diff --git a/src/preproc/pic/main.cpp b/src/preproc/pic/main.cpp
index 8173c5e..988744e 100644
--- a/src/preproc/pic/main.cpp
+++ b/src/preproc/pic/main.cpp
@@ -302,10 +302,8 @@ void do_picture(file_case *fcp)
void do_file(const char *filename)
{
file_case *fcp;
- if (strcmp(filename, "-") == 0)
- fcp = new file_case(stdin, "stdin",
- fcp->fc_dont_close | fcp->fc_const_path /*| fcp->fc_have_stdio*/);
- else if ((fcp = file_case::muxer(filename)) == NULL) {
+ if ((fcp = file_case::muxer(filename)) == NULL) {
+ assert(strcmp(filename, "-"));
delete out;
fatal("can't open `%1': %2", filename, strerror(errno));
}
@@ -458,11 +456,10 @@ void do_whole_file(const char *filename)
{
// Do not set current_filename.
file_case *fcp;
- if (strcmp(filename, "-") == 0)
- fcp = new file_case(stdin, "stdin",
- fcp->fc_dont_close | fcp->fc_const_path /*| fcp->fc_have_stdio*/);
- else if ((fcp = file_case::muxer(filename)) == NULL)
+ if ((fcp = file_case::muxer(filename)) == NULL) {
+ assert(strcmp(filename, "-"));
fatal("can't open `%1': %2", filename, strerror(errno));
+ }
lex_init(new file_input(fcp, filename));
if (yyparse())
diff --git a/src/preproc/preconv/preconv.cpp b/src/preproc/preconv/preconv.cpp
index ed770c3..c087af0 100644
--- a/src/preproc/preconv/preconv.cpp
+++ b/src/preproc/preconv/preconv.cpp
@@ -1006,21 +1006,16 @@ check_coding_tag(file_case *fcp, string &data)
int
do_file(const char *filename)
{
- file_case *fcp;
- string BOM, data;
if (debug_flag)
fprintf(stderr, "file `%s':\n", filename);
- if (strcmp(filename, "-")) {
- if ((fcp = file_case::muxer(filename, fcp->mux_need_binary)) == NULL) {
- error("can't open `%1': %2", filename, strerror(errno));
- return 0;
- }
- } else {
- SET_BINARY(fileno(stdin));
- fcp = new file_case(stdin, "stdin",
- fcp->fc_dont_close | fcp->fc_const_path /*| fcp->fc_have_stdio*/);
+ file_case *fcp;
+ if ((fcp = file_case::muxer(filename, fcp->mux_need_binary)) == NULL) {
+ assert(strcmp(filename, "-"));
+ error("can't open `%1': %2", filename, strerror(errno));
+ return 0;
}
+ string BOM, data;
const char *BOM_encoding = get_BOM(fcp, BOM, data);
// Determine the encoding.
char *encoding;
diff --git a/src/preproc/refer/command.cpp b/src/preproc/refer/command.cpp
index cd10c26..ba52a57 100644
--- a/src/preproc/refer/command.cpp
+++ b/src/preproc/refer/command.cpp
@@ -148,18 +148,14 @@ int input_stack::peek_char()
void input_stack::push_file(const char *fn)
{
- file_case *fcp;
- if (strcmp(fn, "-") == 0) {
- fcp = new file_case(stdin, "stdin",
- fcp->fc_dont_close | fcp->fc_const_path /*| fcp->fc_have_stdio*/);
- fn = "";
- } else {
- fcp = file_case::muxer(fn);
- if (fcp == NULL) {
- error("can't open `%1': %2", fn, strerror(errno));
- return;
- }
+ file_case *fcp = file_case::muxer(fn);
+ if (fcp == NULL) {
+ assert(strcmp(fn, "-"));
+ error("can't open `%1': %2", fn, strerror(errno));
+ return;
}
+ if (fn[0] == '-' && fn[1] == '\0')
+ fn = "";
string buf;
int bol = 1;
diff --git a/src/preproc/tbl/main.cpp b/src/preproc/tbl/main.cpp
index 38195de..345f266 100644
--- a/src/preproc/tbl/main.cpp
+++ b/src/preproc/tbl/main.cpp
@@ -1604,24 +1604,19 @@ int main(int argc, char **argv)
".if !dTE .ds TE\n");
file_case *fcp;
- int i = optind;
- if (i >= argc)
- goto jstdin;
- for (; i < argc; ++i) {
- if (!strcmp(argv[i], "-")) {
-jstdin:
- fcp = new file_case(stdin, "stdin",
- fcp->fc_dont_close | fcp->fc_const_path /*| fcp->fc_have_stdio*/);
+ do /*while (optind < argc)*/ {
+ if ((current_filename = argv[optind++]) == NULL)
current_filename = "-";
- } else if ((fcp = file_case::muxer(current_filename = argv[i])) == NULL)
- fatal("can't open `%1': %2", argv[i], strerror(errno));
+ fcp = file_case::muxer(current_filename);
+ if (fcp == NULL)
+ fatal("can't open `%1': %2", current_filename, strerror(errno));
current_lineno = 1;
printf(".lf 1 %s\n", current_filename);
process_input_file(fcp);
delete fcp;
- }
+ } while (optind < argc);
if (ferror(stdout) || fflush(stdout) < 0)
fatal("output error");
diff --git a/src/roff/troff/input.cpp b/src/roff/troff/input.cpp
index e914413..16ca390 100644
--- a/src/roff/troff/input.cpp
+++ b/src/roff/troff/input.cpp
@@ -7503,13 +7503,9 @@ void macro_source()
static void process_input_file(const char *name)
{
file_case *fcp;
- if (strcmp(name, "-") == 0) {
- clearerr(stdin);
- fcp = new file_case(stdin, "stdin",
- fcp->fc_dont_close | fcp->fc_const_path);
- } else {
- if ((fcp = include_search_path.open_file_cautious(name)) == NULL)
- fatal("can't open `%1': %2", name, strerror(errno));
+ if ((fcp = include_search_path.open_file_cautious(name)) == NULL) {
+ assert(strcmp(name, "-"));
+ fatal("can't open `%1': %2", name, strerror(errno));
}
input_stack::push(new file_iterator(fcp, name));
tok.next();
--
2.0.0