summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMasayuki Hatta (mhatta) <mhatta@debian.org>2008-01-03 06:38:51 -0800
committerMasayuki Hatta (mhatta) <mhatta@debian.org>2008-01-03 06:38:51 -0800
commit081c86fbe0ad77d4b596bc1c0e593a3def8a8051 (patch)
tree48c16557869e78ef16a5d9ed080c53cc14f8059a /src
Import a2ps_4.14.orig.tar.gz
[dgit import orig a2ps_4.14.orig.tar.gz]
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am56
-rw-r--r--src/Makefile.in680
-rw-r--r--src/buffer.c528
-rw-r--r--src/buffer.h107
-rw-r--r--src/delegate.c438
-rw-r--r--src/delegate.h69
-rw-r--r--src/ffaces.c120
-rw-r--r--src/ffaces.h125
-rw-r--r--src/generate.c386
-rw-r--r--src/generate.h38
-rw-r--r--src/lexps.c1782
-rw-r--r--src/lexps.h40
-rw-r--r--src/lexps.l73
-rw-r--r--src/lexssh.c3552
-rw-r--r--src/lexssh.l443
-rw-r--r--src/long-options.c90
-rw-r--r--src/long-options.h35
-rw-r--r--src/main.c1229
-rw-r--r--src/main.h79
-rw-r--r--src/parsessh.c2704
-rw-r--r--src/parsessh.h140
-rw-r--r--src/parsessh.output2153
-rw-r--r--src/parsessh.y804
-rw-r--r--src/read.c206
-rw-r--r--src/read.h38
-rw-r--r--src/regex.c5835
-rw-r--r--src/regex.h542
-rw-r--r--src/select.c283
-rw-r--r--src/select.h66
-rw-r--r--src/sheets-map.c2240
-rw-r--r--src/sheets-map.l310
-rw-r--r--src/ssheet.c1529
-rw-r--r--src/ssheet.h241
-rw-r--r--src/sshread.c517
-rw-r--r--src/sshread.h42
-rw-r--r--src/version-etc.c70
-rw-r--r--src/version-etc.h38
-rw-r--r--src/versions.c136
-rw-r--r--src/versions.h52
-rw-r--r--src/yy2ssh.h40
40 files changed, 27856 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..169acab
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,56 @@
+## Makefile for a2ps' sources. -*- Makefile -*-
+## Copyright (c) 1988-93 Miguel Santana
+## Copyright (c) 1995-99 Akim Demaille, Miguel Santana
+
+##
+## This file is part of a2ps.
+##
+## This program 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, or (at your option)
+## any later version.
+##
+## This program 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; see the file COPYING. If not, write to
+## the Free Software Foundation, 59 Temple Place - Suite 330,
+## Boston, MA 02111-1307, USA.
+##
+
+## Process this file with automake to produce Makefile.in
+
+## Since this package is written in ansi, be ready to un-ansify
+AUTOMAKE_OPTIONS = $(top_builddir)/lib/ansi2knr
+
+bin_PROGRAMS = a2ps
+
+DEFS = @DEFS@ -DLOCALEDIR=\"$(datadir)/locale\"
+
+a2ps_SOURCES = main.c \
+read.c sshread.c ssheet.c select.c generate.c \
+delegate.c regex.c buffer.c versions.c ffaces.c \
+version-etc.c long-options.c \
+parsessh.y lexssh.l lexps.l sheets-map.l
+
+noinst_HEADERS = main.h \
+read.h sshread.h ssheet.h select.h generate.h \
+delegate.h regex.h buffer.h versions.h ffaces.h \
+version-etc.h long-options.h \
+yy2ssh.h lexps.h
+
+BUILT_SOURCES = parsessh.c parsessh.h
+
+YFLAGS = -dtv
+LEX = @LEX@
+# I don't really understand why I have to put srcdir here, but
+# it is needed for yacc and lex files (seems related to #line, but
+# I really don't understand why)...
+INCLUDES = -I.. -I$(srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/intl
+
+a2ps_LDADD = $(top_builddir)/lib/liba2ps.la @LIBINTL@ -lm
+
+EXTRA_DIST = $(BUILT_SOURCES)
diff --git a/src/Makefile.in b/src/Makefile.in
new file mode 100644
index 0000000..d0fe465
--- /dev/null
+++ b/src/Makefile.in
@@ -0,0 +1,680 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+ANSI2KNR = $(top_builddir)/lib/ansi2knr
+bin_PROGRAMS = a2ps$(EXEEXT)
+subdir = src
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in lexps.c lexssh.c parsessh.c sheets-map.c
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/a2_psutils.m4 \
+ $(top_srcdir)/m4/atexit.m4 $(top_srcdir)/m4/file.m4 \
+ $(top_srcdir)/m4/fp_echo.m4 $(top_srcdir)/m4/fullpath.m4 \
+ $(top_srcdir)/m4/gccwarn.m4 $(top_srcdir)/m4/gettext.m4 \
+ $(top_srcdir)/m4/gperf-check.m4 $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/isc-posix.m4 \
+ $(top_srcdir)/m4/lex.m4 $(top_srcdir)/m4/lib-ld.m4 \
+ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
+ $(top_srcdir)/m4/libpaper.m4 $(top_srcdir)/m4/lpr.m4 \
+ $(top_srcdir)/m4/m4.m4 $(top_srcdir)/m4/malloc.m4 \
+ $(top_srcdir)/m4/mbrtowc.m4 $(top_srcdir)/m4/mbstate_t.m4 \
+ $(top_srcdir)/m4/perl.m4 $(top_srcdir)/m4/prereq.m4 \
+ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/protos.m4 \
+ $(top_srcdir)/m4/realloc.m4 $(top_srcdir)/m4/rename.m4 \
+ $(top_srcdir)/m4/stdint_h.m4 $(top_srcdir)/m4/strcasecmp.m4 \
+ $(top_srcdir)/m4/strftim.m4 $(top_srcdir)/m4/termios.m4 \
+ $(top_srcdir)/m4/tterm.m4 $(top_srcdir)/m4/uintmax_t.m4 \
+ $(top_srcdir)/m4/ulonglong.m4 $(top_srcdir)/m4/winsz.m4 \
+ $(top_srcdir)/m4/xstrtoumax.m4 $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/auxdir/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)"
+binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(bin_PROGRAMS)
+am_a2ps_OBJECTS = main$U.$(OBJEXT) read$U.$(OBJEXT) \
+ sshread$U.$(OBJEXT) ssheet$U.$(OBJEXT) select$U.$(OBJEXT) \
+ generate$U.$(OBJEXT) delegate$U.$(OBJEXT) regex$U.$(OBJEXT) \
+ buffer$U.$(OBJEXT) versions$U.$(OBJEXT) ffaces$U.$(OBJEXT) \
+ version-etc$U.$(OBJEXT) long-options$U.$(OBJEXT) \
+ parsessh$U.$(OBJEXT) lexssh$U.$(OBJEXT) lexps$U.$(OBJEXT) \
+ sheets-map$U.$(OBJEXT)
+a2ps_OBJECTS = $(am_a2ps_OBJECTS)
+a2ps_DEPENDENCIES = $(top_builddir)/lib/liba2ps.la
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/auxdir/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+LEXCOMPILE = $(LEX) $(LFLAGS) $(AM_LFLAGS)
+LTLEXCOMPILE = $(LIBTOOL) --mode=compile $(LEX) $(LFLAGS) $(AM_LFLAGS)
+YLWRAP = $(top_srcdir)/auxdir/ylwrap
+YACCCOMPILE = $(YACC) $(YFLAGS) $(AM_YFLAGS)
+LTYACCCOMPILE = $(LIBTOOL) --mode=compile $(YACC) $(YFLAGS) \
+ $(AM_YFLAGS)
+SOURCES = $(a2ps_SOURCES)
+DIST_SOURCES = $(a2ps_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+COM_DISPLAY = @COM_DISPLAY@
+COM_LATEX = @COM_LATEX@
+COM_PS2PDF = @COM_PS2PDF@
+COM_PSUTILS = @COM_PSUTILS@
+COM_TEXI = @COM_TEXI@
+COM_acroread = @COM_acroread@
+COM_acroread4 = @COM_acroread4@
+COM_bzip = @COM_bzip@
+COM_bzip2 = @COM_bzip2@
+COM_convert = @COM_convert@
+COM_distill = @COM_distill@
+COM_dvips = @COM_dvips@
+COM_ghostview = @COM_ghostview@
+COM_grog = @COM_grog@
+COM_gv = @COM_gv@
+COM_gzip = @COM_gzip@
+COM_html2ps = @COM_html2ps@
+COM_latex = @COM_latex@
+COM_makeinfo = @COM_makeinfo@
+COM_netscape = @COM_netscape@
+COM_pdf2ps = @COM_pdf2ps@
+COM_ps2pdf = @COM_ps2pdf@
+COM_psnup = @COM_psnup@
+COM_psselect = @COM_psselect@
+COM_tex = @COM_tex@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@ -DLOCALEDIR=\"$(datadir)/locale\"
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EMACS = @EMACS@
+EMACSLOADPATH = @EMACSLOADPATH@
+ENCODING = @ENCODING@
+EXEEXT = @EXEEXT@
+EXTENSIONS_FALSE = @EXTENSIONS_FALSE@
+EXTENSIONS_TRUE = @EXTENSIONS_TRUE@
+EXTRA_CFLAGS = @EXTRA_CFLAGS@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+FILE_LINK = @FILE_LINK@
+GMSGFMT = @GMSGFMT@
+GNU_PACKAGE = @GNU_PACKAGE@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBVERSION = @LIBVERSION@
+LN_S = @LN_S@
+LPR = @LPR@
+LPR_QUEUE_OPTION = @LPR_QUEUE_OPTION@
+LTALLOCA = @LTALLOCA@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+M4 = @M4@
+MAKEINFO = @MAKEINFO@
+MEDIUM = @MEDIUM@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGMERGE = @MSGMERGE@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+POSUB = @POSUB@
+PSFONT_PATH = @PSFONT_PATH@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+U = @U@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+XGETTEXT = @XGETTEXT@
+YACC = @YACC@
+YFLAGS = -dtv
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+acroread = @acroread@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+bzip = @bzip@
+bzip2 = @bzip2@
+convert = @convert@
+datadir = @datadir@
+datarootdir = @datarootdir@
+distill = @distill@
+docdir = @docdir@
+dvidir = @dvidir@
+dvips = @dvips@
+exec_prefix = @exec_prefix@
+file_prog = @file_prog@
+ghostview = @ghostview@
+grog = @grog@
+gv = @gv@
+gzip = @gzip@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+html2ps = @html2ps@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+latex = @latex@
+libdir = @libdir@
+libexecdir = @libexecdir@
+lispdir = @lispdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+makeinfo = @makeinfo@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+netscape = @netscape@
+oldincludedir = @oldincludedir@
+pdf2ps = @pdf2ps@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+ps2pdf = @ps2pdf@
+psdir = @psdir@
+psnup = @psnup@
+psselect = @psselect@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+subdirs = @subdirs@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+tex = @tex@
+AUTOMAKE_OPTIONS = $(top_builddir)/lib/ansi2knr
+a2ps_SOURCES = main.c \
+read.c sshread.c ssheet.c select.c generate.c \
+delegate.c regex.c buffer.c versions.c ffaces.c \
+version-etc.c long-options.c \
+parsessh.y lexssh.l lexps.l sheets-map.l
+
+noinst_HEADERS = main.h \
+read.h sshread.h ssheet.h select.h generate.h \
+delegate.h regex.h buffer.h versions.h ffaces.h \
+version-etc.h long-options.h \
+yy2ssh.h lexps.h
+
+BUILT_SOURCES = parsessh.c parsessh.h
+# I don't really understand why I have to put srcdir here, but
+# it is needed for yacc and lex files (seems related to #line, but
+# I really don't understand why)...
+INCLUDES = -I.. -I$(srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/intl
+a2ps_LDADD = $(top_builddir)/lib/liba2ps.la @LIBINTL@ -lm
+EXTRA_DIST = $(BUILT_SOURCES)
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .l .lo .o .obj .y
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)"
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ if test -f $$p \
+ || test -f $$p1 \
+ ; then \
+ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
+ else :; fi; \
+ done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
+ rm -f "$(DESTDIR)$(bindir)/$$f"; \
+ done
+
+clean-binPROGRAMS:
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f $$p $$f"; \
+ rm -f $$p $$f ; \
+ done
+a2ps$(EXEEXT): $(a2ps_OBJECTS) $(a2ps_DEPENDENCIES)
+ @rm -f a2ps$(EXEEXT)
+ $(LINK) $(a2ps_LDFLAGS) $(a2ps_OBJECTS) $(a2ps_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+$(top_builddir)/lib/ansi2knr:
+ cd $(top_builddir)/lib && $(MAKE) $(AM_MAKEFLAGS) ansi2knr
+
+mostlyclean-kr:
+ -test "$U" = "" || rm -f *_.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buffer$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/delegate$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ffaces$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generate$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lexps$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lexssh$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/long-options$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parsessh$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/read$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regex$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/select$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sheets-map$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ssheet$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sshread$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version-etc$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/versions$U.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+buffer_.c: buffer.c $(ANSI2KNR)
+ $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/buffer.c; then echo $(srcdir)/buffer.c; else echo buffer.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+delegate_.c: delegate.c $(ANSI2KNR)
+ $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/delegate.c; then echo $(srcdir)/delegate.c; else echo delegate.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+ffaces_.c: ffaces.c $(ANSI2KNR)
+ $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ffaces.c; then echo $(srcdir)/ffaces.c; else echo ffaces.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+generate_.c: generate.c $(ANSI2KNR)
+ $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/generate.c; then echo $(srcdir)/generate.c; else echo generate.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+lexps_.c: lexps.c $(ANSI2KNR)
+ $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/lexps.c; then echo $(srcdir)/lexps.c; else echo lexps.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+lexssh_.c: lexssh.c $(ANSI2KNR)
+ $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/lexssh.c; then echo $(srcdir)/lexssh.c; else echo lexssh.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+long-options_.c: long-options.c $(ANSI2KNR)
+ $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/long-options.c; then echo $(srcdir)/long-options.c; else echo long-options.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+main_.c: main.c $(ANSI2KNR)
+ $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/main.c; then echo $(srcdir)/main.c; else echo main.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+parsessh_.c: parsessh.c $(ANSI2KNR)
+ $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/parsessh.c; then echo $(srcdir)/parsessh.c; else echo parsessh.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+read_.c: read.c $(ANSI2KNR)
+ $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/read.c; then echo $(srcdir)/read.c; else echo read.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+regex_.c: regex.c $(ANSI2KNR)
+ $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/regex.c; then echo $(srcdir)/regex.c; else echo regex.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+select_.c: select.c $(ANSI2KNR)
+ $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/select.c; then echo $(srcdir)/select.c; else echo select.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+sheets-map_.c: sheets-map.c $(ANSI2KNR)
+ $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/sheets-map.c; then echo $(srcdir)/sheets-map.c; else echo sheets-map.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+ssheet_.c: ssheet.c $(ANSI2KNR)
+ $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ssheet.c; then echo $(srcdir)/ssheet.c; else echo ssheet.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+sshread_.c: sshread.c $(ANSI2KNR)
+ $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/sshread.c; then echo $(srcdir)/sshread.c; else echo sshread.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+version-etc_.c: version-etc.c $(ANSI2KNR)
+ $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/version-etc.c; then echo $(srcdir)/version-etc.c; else echo version-etc.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+versions_.c: versions.c $(ANSI2KNR)
+ $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/versions.c; then echo $(srcdir)/versions.c; else echo versions.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+buffer_.$(OBJEXT) buffer_.lo delegate_.$(OBJEXT) delegate_.lo \
+ffaces_.$(OBJEXT) ffaces_.lo generate_.$(OBJEXT) generate_.lo \
+lexps_.$(OBJEXT) lexps_.lo lexssh_.$(OBJEXT) lexssh_.lo \
+long-options_.$(OBJEXT) long-options_.lo main_.$(OBJEXT) main_.lo \
+parsessh_.$(OBJEXT) parsessh_.lo read_.$(OBJEXT) read_.lo \
+regex_.$(OBJEXT) regex_.lo select_.$(OBJEXT) select_.lo \
+sheets-map_.$(OBJEXT) sheets-map_.lo ssheet_.$(OBJEXT) ssheet_.lo \
+sshread_.$(OBJEXT) sshread_.lo version-etc_.$(OBJEXT) version-etc_.lo \
+versions_.$(OBJEXT) versions_.lo : $(ANSI2KNR)
+
+.l.c:
+ $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE)
+
+.y.c:
+ $(YACCCOMPILE) $<
+ if test -f y.tab.h; then \
+ to=`echo "$*_H" | sed \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \
+ -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'`; \
+ sed -e "/^#/!b" -e "s/Y_TAB_H/$$to/g" -e "s|y\.tab\.h|$*.h|" \
+ y.tab.h >$*.ht; \
+ rm -f y.tab.h; \
+ if cmp -s $*.ht $*.h; then \
+ rm -f $*.ht ;\
+ else \
+ mv $*.ht $*.h; \
+ fi; \
+ fi
+ if test -f y.output; then \
+ mv y.output $*.output; \
+ fi
+ sed '/^#/ s|y\.tab\.c|$@|' y.tab.c >$@t && mv $@t $@
+ rm -f y.tab.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(PROGRAMS) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(bindir)"; do \
+ test -z "$$dir" || $(mkdir_p) "$$dir"; \
+ done
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -rm -f lexps.c
+ -rm -f lexssh.c
+ -rm -f parsessh.c
+ -rm -f sheets-map.c
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am: install-binPROGRAMS
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic mostlyclean-kr \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-info-am
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
+ clean-generic clean-libtool ctags distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-binPROGRAMS install-data install-data-am install-exec \
+ install-exec-am install-info install-info-am install-man \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-kr \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
+ uninstall-am uninstall-binPROGRAMS uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/buffer.c b/src/buffer.c
new file mode 100644
index 0000000..bf1a5ec
--- /dev/null
+++ b/src/buffer.c
@@ -0,0 +1,528 @@
+/*
+ * buffer.c - read line by line with conversion of EOL types
+ *
+ * Copyright (c) 1988-1993 Miguel Santana
+ * Copyright (c) 1995-1999 Akim Demaille, Miguel Santana
+ */
+
+/*
+ * This file is part of a2ps.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * $Id: buffer.c,v 1.1.1.1.2.1 2007/12/29 01:58:34 mhatta Exp $
+ */
+
+/* FIXME: There is a case where the behavior is probably wrong: mixed
+ string/stream buffers. It may happen that the last char of the
+ string part be a '\n' (or '\r') and buffer wants to see the next
+ char (to see if is a '\r' (or '\n')), but the next char is in the
+ stream, not the string.
+
+ Currently it does not fetch that next char. */
+
+#include "a2ps.h"
+#include "routines.h"
+#include "argmatch.h"
+#include "buffer.h"
+#include <assert.h>
+
+/****************************************************************/
+/* Handling of the various eol styles */
+/****************************************************************/
+const char *
+eol_to_string (enum eol_e eol)
+{
+ switch (eol)
+ {
+ case eol_r:
+ return "\\r";
+
+ case eol_n:
+ return "\\n";
+
+ case eol_rn:
+ return "\\r\\n";
+
+ case eol_nr:
+ return "\\n\\r";
+
+ case eol_auto:
+ /* TRANS: the type of the end-of-line rules, is `any type', i.e.
+ lines ended by \n, or \r, or \r\n, or \n\r are OK */
+ return _ ("any type");
+
+ default:
+ abort ();
+ }
+ return NULL; /* -Wall */
+}
+
+/*
+ * What about the bools
+ */
+static const char *const eol_args[] =
+{
+ "r", "mac",
+ "n", "unix",
+ "nr",
+ "rn", "pc",
+ "auto", "any", "4x4",
+ 0
+};
+
+static const enum eol_e eol_types[] =
+{
+ eol_r, eol_r,
+ eol_n, eol_n,
+ eol_nr,
+ eol_rn, eol_rn,
+ eol_auto, eol_auto, eol_auto
+};
+
+
+enum eol_e
+option_string_to_eol (const char *option,
+ const char *arg)
+{
+ ARGMATCH_ASSERT (eol_args, eol_types);
+ return XARGCASEMATCH (option, arg, eol_args, eol_types);
+}
+
+/****************************************************************/
+/* buffer_t Service routines */
+/****************************************************************/
+static inline void
+buffer_internal_set (buffer_t * buffer,
+ FILE * stream,
+ const uchar * buf, size_t bufsize,
+ bool pipe_p, enum eol_e eol)
+{
+ buffer->buf = buf;
+ buffer->bufsize = bufsize;
+ buffer->bufoffset = 0;
+ buffer->stream = stream;
+ buffer->pipe_p = pipe_p;
+
+ buffer->content = NULL;
+ buffer->eol = eol;
+ buffer->lower_case = false; /* By default, no lower case version. */
+ buffer->value = NULL;
+ buffer->line = 0;
+ buffer->allocsize = 0;
+ buffer->len = 0;
+ buffer->curr = 0;
+ obstack_init (&buffer->obstack);
+}
+
+void
+buffer_stream_set (buffer_t * buffer, FILE * stream, enum eol_e eol)
+{
+ buffer_internal_set (buffer, stream, NULL, 0, false, eol);
+}
+
+void
+buffer_pipe_set (buffer_t * buffer, FILE * stream, enum eol_e eol)
+{
+ buffer_internal_set (buffer, stream, NULL, 0, true, eol);
+}
+
+void
+buffer_string_set (buffer_t * buffer, const uchar * string, enum eol_e eol)
+{
+ buffer_internal_set (buffer, NULL, string, strlen (string), false, eol);
+}
+
+void
+buffer_buffer_set (buffer_t * buffer, const uchar * buf, size_t bufsize,
+ enum eol_e eol)
+{
+ buffer_internal_set (buffer, NULL, buf, bufsize, false, eol);
+}
+
+/* getc and ungetc on the stream of Buf. */
+
+#define sgetc(Buf) (getc ((Buf)->stream))
+#define sungetc(Char, Buf) (ungetc (Char, (Buf)->stream))
+
+/* getc and ungetc on the buffer of Buf.
+ It is much more tricky, especially if Buf is mixed buffer/stream.
+ Even when the buffer was completely read, the oofset must be increased. */
+
+#define bgetc(Buf) \
+ (((Buf)->bufoffset < (Buf)->bufsize) \
+ ? ((Buf)->buf[(Buf)->bufoffset++]) \
+ : ((Buf)->bufoffset++, EOF))
+
+#define bungetc(Char, Buf) ((Buf)->bufoffset--)
+
+void
+buffer_self_print (buffer_t * buffer, FILE * stream)
+{
+ if (buffer->buf)
+ fprintf (stream, "A string buffer. Bufoffset %u\n",
+ buffer->bufoffset);
+ if (buffer->stream)
+ fprintf (stream, "A stream buffer (%s).\n",
+ buffer->pipe_p ? "pipe" : "file");
+ fprintf (stream, "Len = %d, Lower case = %d, Line = %d\n",
+ buffer->len, buffer->lower_case, buffer->line);
+ if (buffer->len)
+ fprintf (stream, "Content = `%s'\n", buffer->content);
+}
+
+/*
+ * It frees the content, not the pointer
+ */
+void
+buffer_release (buffer_t * buffer)
+{
+ /* VALUE is malloc'd only if BUFFER->LOWER_CASE */
+ if (buffer->lower_case)
+ free (buffer->value);
+ /* I don't know how this one should be used */
+ /* obstack_free (&buffer->obstack, NULL); */
+}
+
+void
+buffer_set_lower_case (buffer_t * buffer, bool sensitive)
+{
+ buffer->lower_case = sensitive;
+}
+
+/*
+ * Get a line from BUFFER->STREAM.
+ * Returns true if a full line has been read,
+ * false if EOF was met before
+ */
+
+static inline bool
+buffer_stream_get_line (buffer_t * buffer)
+{
+ register int c, d;
+
+ while ((c = sgetc (buffer)) != EOF)
+ switch (c)
+ {
+ case '\n':
+ switch (buffer->eol)
+ {
+ case eol_r:
+ case eol_rn:
+ /* \n plain char */
+ goto stream_plain_char;
+
+ case eol_auto:
+ /* If the next char is a \r, eat it */
+ if ((d = sgetc (buffer)) != '\r')
+ sungetc (d, buffer);
+ break;
+
+ case eol_n:
+ /* This is a good eol */
+ break;
+
+ case eol_nr:
+ if ((d = sgetc (buffer)) != '\r')
+ {
+ /* This is \n, but eol is \n\r: make it a plain char */
+ sungetc (d, buffer);
+ goto stream_plain_char;
+ }
+ /* This is eol=\n\r, just return \n */
+ break;
+ }
+ /* End it. No need to NUL-terminate */
+ obstack_1grow (&buffer->obstack, c);
+ return true;
+
+ case '\r':
+ switch (buffer->eol)
+ {
+ case eol_n:
+ case eol_nr:
+ /* \r plain char */
+ goto stream_plain_char;
+
+ case eol_r:
+ /* This is a good eol, but the lib uses \n */
+ c = '\n';
+ break;
+
+ case eol_auto:
+ /* If the next char is a \n, eat it */
+ if ((d = sgetc (buffer)) != '\n')
+ sungetc (d, buffer);
+ c = '\n';
+ break;
+
+ case eol_rn:
+ if ((d = sgetc (buffer)) != '\n')
+ {
+ /* This is \r, but eol is \r\n: make it a plain char */
+ sungetc (d, buffer);
+ goto stream_plain_char;
+ }
+ /* This is eol = \r\n: just return \n */
+ c = '\n';
+ break;
+ }
+ /* End it. No need to NUL-terminate */
+ obstack_1grow (&buffer->obstack, c);
+ return true;
+
+ default:
+ stream_plain_char:
+ obstack_1grow (&buffer->obstack, c);
+ break;
+ }
+
+ /* If we are here, it's because there is nothing more to read, and
+ the last char was not an eol: report the line is not complete. */
+ return false;
+}
+
+/*
+ * Get a line from BUFFER->BUF
+ *
+ * Note that we could have made it destuctive.
+ * But would have caused problem if some day we want to use
+ * mmap.
+ *
+ * Returns true if a full line has been read,
+ * false if EOF (i.e. offset >= bufsize) was met before
+ */
+
+static inline bool
+buffer_string_get_line (buffer_t * buffer)
+{
+ register int c, d;
+
+ while ((c = bgetc (buffer)) != EOF)
+ switch (c)
+ {
+ case '\n':
+ switch (buffer->eol)
+ {
+ case eol_r:
+ case eol_rn:
+ /* \n plain char */
+ goto string_plain_char;
+
+ case eol_auto:
+ /* If the next char is a \r, eat it */
+ if ((d = bgetc (buffer)) != '\r')
+ bungetc (d, buffer);
+ break;
+
+ case eol_n:
+ /* This is a good eol */
+ break;
+
+ case eol_nr:
+ if ((d = bgetc (buffer)) != '\r')
+ {
+ /* This is \n, but eol is \n\r: make it a plain char */
+ bungetc (d, buffer);
+ goto string_plain_char;
+ }
+ /* This is eol=\n\r, just return \n */
+ break;
+ }
+ /* End it. No need to NUL-terminate */
+ obstack_1grow (&buffer->obstack, c);
+ return true;
+
+ case '\r':
+ switch (buffer->eol)
+ {
+ case eol_n:
+ case eol_nr:
+ /* \r plain char */
+ goto string_plain_char;
+
+ case eol_r:
+ /* This is a good eol, but the lib uses \n */
+ c = '\n';
+ break;
+
+ case eol_auto:
+ /* If the next char is a \n, eat it */
+ if ((d = bgetc (buffer)) != '\n')
+ bungetc (d, buffer);
+ c = '\n';
+ break;
+
+ case eol_rn:
+ if ((d = bgetc (buffer)) != '\n')
+ {
+ /* This is \r, but eol is \r\n: make it a plain char */
+ bungetc (d, buffer);
+ goto string_plain_char;
+ }
+ /* This is eol = \r\n: just return \n */
+ c = '\n';
+ break;
+ }
+ /* End it. No need to NUL-terminate */
+ obstack_1grow (&buffer->obstack, c);
+ return true;
+
+ default:
+ string_plain_char:
+ obstack_1grow (&buffer->obstack, c);
+ break;
+ }
+
+ /* If we are here, it's because there is nothing more to read, and
+ the last char was not an eol: report the line is not complete. */
+ return false;
+}
+
+
+/* buffer_get
+ * if the language is case insensitive,
+ * build a lower case version of the buffer
+ */
+void
+buffer_get (buffer_t * buffer)
+{
+ bool line_ended_p = false; /* the line read finishes by eol */
+
+ /* If there is something to read from the buffered string, fetch it */
+ if (buffer->buf && buffer->bufoffset < buffer->bufsize)
+ line_ended_p = buffer_string_get_line (buffer);
+
+ /* If the line was not finished, continue the reading but in the
+ stream. This includes the case where there is no buf */
+ if (buffer->stream && !line_ended_p)
+ line_ended_p = buffer_stream_get_line (buffer);
+
+ /* A full line has been read. Close the obstack, get the content.
+ We NUL terminate because it helps the parsing functions such as
+ match_keyword, which looks one char after the current char. With
+ this sentinel, which is probably not in the alphabet, we save a
+ test on the length of the buffer. */
+ buffer->len = obstack_object_size (&buffer->obstack);
+ obstack_1grow (&buffer->obstack, '\0');
+ buffer->content = (uchar *) obstack_finish (&buffer->obstack);
+
+ /* One more line read */
+ buffer->line++;
+
+ /* If the eol char is preceded by a \f, then just forget the eol, so
+ that there won't be a blank line at the top of the next page */
+ if ((buffer->len >= 2)
+ && buffer->content[buffer->len - 2] == '\f')
+ {
+ buffer->content[--(buffer->len)] = '\0';
+ }
+
+ if (buffer->lower_case)
+ {
+ size_t i;
+ if (buffer->allocsize <= buffer->len)
+ buffer->allocsize = buffer->len + 1;
+
+ buffer->value =
+ XREALLOC (buffer->value, uchar, buffer->allocsize);
+
+ for (i = 0; i <= buffer->len; i++)
+ buffer->value[i] = tolower (buffer->content[i]);
+ }
+ else
+ {
+ buffer->value = buffer->content;
+ }
+
+ buffer->curr = 0;
+}
+
+/* buffer_sample_get
+ * extract a piece of a BUFFER's stream into FILENAME
+ *
+ * The piece that has been extracted is taken as buf in BUFFER, so that
+ * we still can use it.
+ */
+void
+buffer_sample_get (buffer_t * buffer, const char *filename)
+{
+ /* I think that most file(1) just use the 512 first bytes */
+#define SAMPLE_SIZE 512
+ FILE *out = xwfopen (filename);
+ size_t cur = 0;
+ int c;
+ char *sample_buffer = XMALLOC (char, SAMPLE_SIZE);
+
+ for (; (cur < SAMPLE_SIZE) && ((c = sgetc (buffer)) != EOF); cur++)
+ {
+ sample_buffer[cur] = c;
+ putc (c, out);
+ }
+
+ /* Put the sample into the buffer for later use */
+ buffer->buf = sample_buffer;
+ buffer->bufsize = cur;
+
+ fclose (out);
+}
+
+
+/* buffer_save
+ * save the content of BUFFER to the file FILENAME
+ * if BUFFER has a buf, dump it
+ * then if it has a stream, dump its content
+ *
+ * Note that the buffer is no longer usable: we don't rewind it,
+ * because it can be stdin.
+ */
+void
+buffer_save (buffer_t * buffer, const char *filename)
+{
+ FILE *out = xwfopen (filename);
+
+ if (buffer->buf)
+ {
+ size_t cur;
+ for (cur = 0; cur < buffer->bufsize; cur++)
+ putc (buffer->buf[cur], out);
+ }
+
+ if (buffer->stream)
+ streams_copy (buffer->stream, out);
+
+ fclose (out);
+}
+
+/*
+ * Check if sample + dump are OK. Only for debug purpose
+ */
+#if BUFFER_TEST
+void
+buffer_test (const char *filename)
+{
+ FILE *in = xrfopen (filename);
+ buffer_t buffer;
+
+ buffer_stream_set (&buffer, in, eol_n);
+
+ buffer_sample_get (&buffer, "/tmp/sample");
+ buffer_save (&buffer, "/tmp/dump");
+ buffer_release (&buffer);
+}
+#endif
diff --git a/src/buffer.h b/src/buffer.h
new file mode 100644
index 0000000..f882c94
--- /dev/null
+++ b/src/buffer.h
@@ -0,0 +1,107 @@
+/*
+ * buffer.h - read line by line with conversion of EOL types
+ *
+ * Copyright (c) 1988-1993 Miguel Santana
+ * Copyright (c) 1995-1999 Akim Demaille, Miguel Santana
+ */
+
+/*
+ * This file is part of a2ps.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * $Id: buffer.h,v 1.1.1.1.2.1 2007/12/29 01:58:35 mhatta Exp $
+ */
+
+#ifndef _BUFFER_H_
+#define _BUFFER_H_
+
+#include "xobstack.h"
+
+/****************************************************************/
+/* buffer_t Service routines */
+/****************************************************************/
+/*
+ * How the eol should be handled
+ */
+enum eol_e
+{
+ eol_r, /* \r only */
+ eol_n, /* \n */
+ eol_rn, /* \r\n */
+ eol_nr, /* \n\r */
+ eol_auto /* Any of the previous */
+};
+
+const char * eol_to_string PARAMS ((enum eol_e eol));
+enum eol_e option_string_to_eol PARAMS ((const char * option,
+ const char * arg));
+
+/*
+ * The buffer structure, which encloses a lower case version to
+ * speed up case insensitive parsing
+ * There are two types:
+ * - buf != NULL : input comes from stream_string, read line by line.
+ * - stream != NULL : input comes from stream, read line by line.
+ * - both non NULL : first read buf, then stream.
+ *
+ */
+typedef struct buffer_s
+{
+ const uchar * buf; /* != 0 -> buffer on a string */
+ size_t bufsize; /* size of buf */
+ size_t bufoffset; /* Used when a buffer string */
+ FILE * stream; /* != 0 -> a buffer on a stream */
+ bool pipe_p; /* true -> stream has been popened */
+
+ uchar *content; /* Exactly what is read */
+ enum eol_e eol; /* What is an end of line? */
+ bool lower_case;
+ uchar * value; /* if LOWER_CASE, then lower case of content */
+ size_t line; /* Num of the current line */
+ size_t allocsize; /* Used to know how big lower_case is */
+ size_t len;
+ size_t curr;
+ struct obstack obstack;
+} buffer_t;
+
+void buffer_stream_set PARAMS ((buffer_t * buffer,
+ FILE * stream, enum eol_e eol));
+
+void buffer_pipe_set PARAMS ((buffer_t * buffer,
+ FILE * stream, enum eol_e eol));
+
+void buffer_string_set PARAMS ((buffer_t * buffer,
+ const uchar * string, enum eol_e eol));
+
+void buffer_buffer_set PARAMS ((buffer_t * buffer,
+ const uchar * buf, size_t bufsize,
+ enum eol_e eol));
+
+void buffer_set_lower_case PARAMS ((buffer_t * buffer, bool lower_case));
+void buffer_self_print PARAMS ((buffer_t * buffer, FILE * stream));
+
+void buffer_release PARAMS ((buffer_t * buffer));
+
+void buffer_get PARAMS ((buffer_t * buffer));
+
+void buffer_sample_get PARAMS ((buffer_t * buffer, const char * filename));
+void buffer_save PARAMS ((buffer_t * buffer, const char * filename));
+
+#define buffer_is_empty(Buf) (Buf->curr >= Buf->len)
+#endif
diff --git a/src/delegate.c b/src/delegate.c
new file mode 100644
index 0000000..0363e2a
--- /dev/null
+++ b/src/delegate.c
@@ -0,0 +1,438 @@
+/*
+ * delegate.c
+ *
+ * Handling the delegations
+ * Copyright (c) 1988, 89, 90, 91, 92, 93 Miguel Santana
+ * Copyright (c) 1995, 96, 97, 98, 99 Akim Demaille, Miguel Santana
+ *
+ */
+
+/*
+ * This file is part of a2ps.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "a2ps.h"
+#include "jobs.h"
+#include "fjobs.h"
+#include "output.h"
+#include "delegate.h"
+#include "message.h"
+#include "routines.h"
+#include "metaseq.h"
+#include "dsc.h"
+#include "buffer.h"
+#include "lister.h"
+#include "quotearg.h"
+
+/* Priviledge access to job and delegations */
+extern struct a2ps_job *job;
+extern struct hash_table_s *delegation_table;
+
+/************************************************************************/
+/* Handling of the hash table of the delegations */
+/************************************************************************/
+/*
+ * The hashing is done on the contract, not the name (who
+ * cares the name of the contract!)
+ */
+static unsigned long
+delegate_hash_1 (void const *key)
+{
+ return_STRING_HASH_1 (((const struct delegation *) key)->contract);
+}
+
+static unsigned long
+delegate_hash_2 (void const *key)
+{
+ return_STRING_HASH_2 (((const struct delegation *) key)->contract);
+}
+
+static int
+delegate_hash_cmp (void const *x, void const *y)
+{
+ return_STRING_COMPARE (((const struct delegation *) x)->contract,
+ ((const struct delegation *) y)->contract);
+}
+
+static int
+delegate_hash_qcmp (const struct delegation **x,
+ const struct delegation **y)
+{
+ return_STRING_COMPARE ((*x)->name, (*y)->name);
+}
+
+static size_t
+delegate_name_len (struct delegation *delegation)
+{
+ return strlen (delegation->name);
+}
+
+static void
+delegate_name_fputs (struct delegation *delegation, FILE * stream)
+{
+ fputs (delegation->name, stream);
+}
+
+static void
+delegate_free (struct delegation *delegation)
+{
+ free (delegation->name);
+ free (delegation->contract);
+ free (delegation->command);
+ free (delegation);
+}
+
+/*
+ * Create the table handling the subcontracts
+ */
+struct hash_table_s *
+delegation_table_new (void)
+{
+ NEW (struct hash_table_s, res);
+ hash_init (res, 8,
+ delegate_hash_1, delegate_hash_2, delegate_hash_cmp);
+ return res;
+}
+
+/*
+ * Free the whole table
+ */
+void
+delegation_table_free (struct hash_table_s *table)
+{
+ hash_free (table, (hash_map_func_t) delegate_free);
+ free (table);
+}
+
+/************************************************************************/
+/* Use of the subcontracts */
+/************************************************************************/
+/*
+ * Read a (PS) file, and extract the NeededResources etc.
+ * To include in the whole file Prolog.
+ * Get the number of pages too.
+ */
+
+/*
+ * Read a line "Delegation: <CONTRACT_LINE>" in a config file
+ */
+#define error_if_null(_str_) \
+ if (_str_ == NULL) \
+ error_at_line (1, 0, filename, line, \
+ _("missing argument for `%s'"), quotearg (contract_line));
+
+void
+add_delegation (const char *filename, int line,
+ char *contract_line)
+{
+ char *cp, *cp2;
+ struct delegation *contract;
+
+ contract = XMALLOC (struct delegation, 1);
+
+ /* Structure of the line:
+ <name of contract> <source type>:<destination type> <command> */
+ cp = strtok (contract_line, " \t\n");
+ error_if_null (cp);
+ contract->name = xstrdup (cp);
+
+ cp = strtok (NULL, " \t\n:");
+ error_if_null (cp);
+ cp2 = strtok (NULL, " \t\n");
+ error_if_null (cp2);
+ contract->contract = XMALLOC (char, strlen (cp) + strlen (cp2) + 2);
+ sprintf (contract->contract, "%s:%s", cp, cp2);
+
+ cp = strtok (NULL, "\n");
+ error_if_null (cp);
+ contract->command = xstrdup (cp + strspn (cp, "\t "));
+
+ /* Put it in the table */
+ hash_insert (delegation_table, contract);
+}
+
+
+/*
+ * Return the subcontract if there is, otherwise NULL
+ */
+struct delegation *
+get_subcontract (const char *src_type, const char *dest_type)
+{
+ struct delegation token;
+
+ token.contract = ALLOCA (char, strlen (src_type) + strlen (dest_type) + 2);
+ sprintf (token.contract, "%s:%s", src_type, dest_type);
+
+ return (struct delegation *) hash_find_item (delegation_table, &token);
+}
+
+/*
+ * Return the command associated a sub contract.
+ * if EVALUATE, return the evaluated command.
+ * The result is not malloc'ed, and must be used before
+ * any other call to expand_user_string.
+ */
+char *
+get_delegate_command (struct delegation *contract,
+ struct file_job *file,
+ int evaluate)
+{
+ if (evaluate)
+ return (char *) expand_user_string (job, file,
+ (const uchar *) "delegating command",
+ (const uchar *) contract->command);
+ else
+ return contract->command;
+}
+
+/*
+ * Subcontract FILE to CONTRACTOR
+ * This should produce a tmp file, then insert in the OUTPUT struture
+ * the routine to dump and remove it.
+ * Return true open success, false otherwise
+ */
+enum continuation_e
+{
+ no_continuation, needed_resource
+};
+
+int
+subcontract (struct file_job *fjob, buffer_t * buffer,
+ struct delegation *contractor)
+{
+ char *command, *stdin_content_filename = NULL;
+ FILE *in_stream, *out_stream;
+ int lines_read = 0;
+ char buf[512];
+
+ /* Here we store the type of the last %%??Resource: tag we saw,
+ * to be ready to handle continuation (%%+ ) */
+ enum continuation_e continuation = no_continuation;
+
+ /* This is an awful kludge. I dunno how to do it nicely... The
+ problem is that a2ps can be fed by stdin, but delegations cannot.
+ So we first dump stdin into a temporary file. */
+ if (fjob->name == job->stdin_filename) /* not strcmp */
+ {
+ /* Dump the content of the buffer */
+ tempname_ensure (fjob->stdin_tmpname);
+ stdin_content_filename = fjob->stdin_tmpname;
+ buffer_save (buffer, stdin_content_filename);
+
+ /* We change the name of the file so that the correct file name
+ is used in the command (that of the temporary file containing
+ stdin). */
+ fjob->name = (uchar *) stdin_content_filename;
+ command = get_delegate_command (contractor, fjob, 1);
+ fjob->name = job->stdin_filename;
+ }
+ else
+ {
+ command = get_delegate_command (contractor, fjob, 1);
+ }
+
+ /* First, before it break :), say what you do */
+ message (msg_file,
+ (stderr, "Delegating `%s' to `%s' (%s)\n",
+ fjob->name, contractor->name, command));
+
+ /* Open a pipe from the delegation, and the temp file in which
+ * the result is stored */
+ tempname_ensure (fjob->delegation_tmpname);
+ out_stream = fopen (fjob->delegation_tmpname, "w");
+ if (!out_stream)
+ {
+ error (0, errno, _("cannot create file `%s'"),
+ quotearg (fjob->delegation_tmpname));
+ return false;
+ }
+
+ in_stream = popen (command, "r");
+ if (!in_stream)
+ {
+ fclose (out_stream);
+ error (0, errno, _("cannot open a pipe on `%s'"),
+ quotearg (command));
+ return false;
+ }
+
+ /* Make the file know its first page/sheet */
+ file_job_synchronize_sheets (job);
+ file_job_synchronize_pages (job);
+
+ /* Now, read the file, update the PS info, and store the result in
+ * out_stream */
+ while (fgets (buf, sizeof (buf), in_stream))
+ {
+ /* This is not exactely the number of lines,
+ * but anyway it is only used to be sure something was read,
+ * to track the failure of a delegation */
+ lines_read++;
+#define PAGE_TAG "%%Page: "
+ if (strprefix (PAGE_TAG, buf))
+ {
+ /* We suppose that it has respected the number of virtual
+ * pages per sheet */
+ job->pages += job->rows * job->columns;
+ job->sheets++;
+ file_job_synchronize_sheets (job);
+ file_job_synchronize_pages (job);
+ }
+#define NEEDED_RES_TAG "%%DocumentNeededResources: "
+ else if (strprefix (NEEDED_RES_TAG, buf))
+ {
+ /* The needed resources must be included too.
+ * Take care of the %%+ continuation tag */
+ char *value, *res, *buf_copy;
+
+ continuation = needed_resource;
+ astrcpy (buf_copy, buf + strlen (NEEDED_RES_TAG));
+ res = strtok (buf_copy, " \n\t");
+
+ /* This while saves us from a special case of
+ * %%DocumentNeededResources: (atend)
+ */
+ while ((value = strtok (NULL, " \n\t")))
+ add_needed_resource (job, res, value);
+ }
+#define CONTINUATION_TAG "%%+ "
+ else if (strprefix (CONTINUATION_TAG, buf))
+ {
+ char *value, *res, *buf_copy;
+
+ astrcpy (buf_copy, buf + strlen (CONTINUATION_TAG));
+ res = strtok (buf_copy, " \n\t");
+ while ((value = strtok (NULL, " \n\t")))
+ switch (continuation)
+ {
+ case needed_resource:
+ add_needed_resource (job, res, value);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* The content should be left untouched */
+ fputs (buf, out_stream);
+ }
+
+ pclose (in_stream);
+ fclose (out_stream);
+
+ /* If a temporary file was created to deal with stdin, unlink it. */
+ if (stdin_content_filename)
+ unlink (stdin_content_filename);
+
+ /* FIXME: This is a trial to see when there is an error */
+ if (lines_read == 0)
+ return false;
+
+ /* This one must not be cut by the page selection */
+ {
+ int saved_redirection_of_output;
+ saved_redirection_of_output = output_is_to_void (job->divertion);
+ output_to_void (job->divertion, false);
+
+ /* Protect the rest of the file and give sane environment */
+ output (job->divertion, "BeginInclude\n");
+ output (job->divertion, "%%%%BeginDocument: %s\n", fjob->name);
+ output_delayed_routine (job->divertion,
+ (delayed_routine_t) stream_dump,
+ (void *) fjob->delegation_tmpname);
+ /* remove the file after its use */
+ output_delayed_routine (job->divertion,
+ (delayed_routine_t) unlink2,
+ (void *) fjob->delegation_tmpname);
+ output (job->divertion, "%%%%EndDocument\n");
+ output (job->divertion, "EndInclude\n");
+
+ output_to_void (job->divertion, saved_redirection_of_output);
+ }
+
+ /* The pages are no longer ordered. Respect DSC */
+ job->status->page_are_ordered = false;
+ return true;
+}
+
+/************************************************************************/
+/* "Visible" interface of the subcontracts */
+/************************************************************************/
+/*
+ * Print a single contract on STREAM
+ */
+static void
+dump_contract (FILE * stream, struct delegation *contract)
+{
+ char *cp, *cp2;
+ cp = xstrdup (contract->contract);
+ cp = strtok (cp, ":");
+ cp2 = strtok (NULL, ":");
+
+ /* E.g.: Delegation `PsNup', from ps to ps */
+ fprintf (stream, _("Delegation `%s', from %s to %s\n"),
+ contract->name, cp, cp2);
+ fprintf (stream, "\t%s\n", contract->command);
+ free (cp);
+}
+
+/*
+ * List the subcontracts for --list-subcontracts
+ */
+void
+delegations_list_long (struct hash_table_s *contracts,
+ FILE * stream)
+{
+ int i;
+ struct delegation **ordered_contracts;
+ ordered_contracts =
+ ((struct delegation **)
+ hash_dump (contracts, NULL, (qsort_cmp_t) delegate_hash_qcmp));
+
+ fputs (_("Applications configured for delegation"), stream);
+ putc ('\n', stream);
+
+ for (i = 0; ordered_contracts[i]; i++)
+ dump_contract (stream, ordered_contracts[i]);
+ putc ('\n', stream);
+
+ free (ordered_contracts);
+}
+
+/*
+ * For --list-features
+ */
+void
+delegations_list_short (struct hash_table_s *contracts,
+ FILE * stream)
+{
+ struct delegation **ordered_contracts;
+ ordered_contracts =
+ ((struct delegation **)
+ hash_dump (contracts, NULL, (qsort_cmp_t) delegate_hash_qcmp));
+
+ fputs (_("Applications configured for delegation"), stream);
+ putc ('\n', stream);
+
+ lister_fprint_vertical (NULL, stream,
+ (void *) ordered_contracts, (size_t) -1,
+ (lister_width_t) delegate_name_len,
+ (lister_print_t) delegate_name_fputs);
+ free (ordered_contracts);
+}
diff --git a/src/delegate.h b/src/delegate.h
new file mode 100644
index 0000000..7323aa4
--- /dev/null
+++ b/src/delegate.h
@@ -0,0 +1,69 @@
+/*
+ * delegate.h
+ *
+ * Handling the delegations
+ * Copyright (c) 1988, 89, 90, 91, 92, 93 Miguel Santana
+ * Copyright (c) 1995, 96, 97, 98 Akim Demaille, Miguel Santana
+ *
+ */
+
+/*
+ * This file is part of a2ps.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * $Id: delegate.h,v 1.1.1.1.2.1 2007/12/29 01:58:35 mhatta Exp $
+ */
+
+#ifndef _DELEGATE_H_
+#define _DELEGATE_H_
+
+#include "hashtab.h"
+#include "buffer.h"
+
+struct file_job;
+
+
+struct delegation
+ {
+ char *name; /* e.g. groff */
+ char *contract; /* e.g. roff:ps */
+ char *command; /* e.g. groff -man $f */
+ };
+
+struct hash_table_s *delegation_table_new PARAMS ((void));
+void delegation_table_free PARAMS ((struct hash_table_s * table));
+
+void add_delegation PARAMS ((const char *filename, int line,
+ char *contract_line));
+struct delegation *get_subcontract PARAMS ((const char *src_type,
+ const char *dest_type));
+char *get_delegate_command PARAMS ((struct delegation * contract,
+ struct file_job * file,
+ int evaluate));
+/* Execute the sub contract */
+int subcontract PARAMS ((struct file_job * file, buffer_t * buffer,
+ struct delegation * contractor));
+/*
+ * For the command line interface
+ */
+void delegations_list_long PARAMS ((struct hash_table_s * contracts,
+ FILE * stream));
+void delegations_list_short PARAMS ((struct hash_table_s * contracts,
+ FILE * stream));
+#endif /* !defined(_DELEGATE_H_) */
diff --git a/src/ffaces.c b/src/ffaces.c
new file mode 100644
index 0000000..1492383
--- /dev/null
+++ b/src/ffaces.c
@@ -0,0 +1,120 @@
+/*
+ * ffaces.h
+ *
+ * definition of the flagged faces used by a2ps
+ * Copyright (c) 1988, 89, 90, 91, 92, 93 Miguel Santana
+ * Copyright (c) 1995, 96, 97, 98 Akim Demaille, Miguel Santana
+ * $Id: ffaces.c,v 1.1.1.1.2.1 2007/12/29 01:58:35 mhatta Exp $
+ */
+
+/*
+ * This file is part of a2ps.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "a2ps.h"
+#include "ffaces.h"
+#include "routines.h"
+#include "jobs.h"
+
+/*
+ * List of the fflags and their readable names.
+ */
+struct fflag_and_name { /* Auxialiary struct just for the following list */
+ const char * name;
+ enum fflag_e flag;
+};
+
+static const struct fflag_and_name fflag_and_name [] = {
+ { "Invisible",ff_Invisible },
+ { "Tag1", ff_Tag1 },
+ { "Tag2", ff_Tag2 },
+ { "Tag3", ff_Tag3 },
+ { "Tag4", ff_Tag4 },
+ { "Index1", ff_Index1 },
+ { "Index2", ff_Index2 },
+ { "Index3", ff_Index3 },
+ { "Index4", ff_Index4 },
+ { "Encoding", ff_Encoding },
+ { NULL, ff_No_fflag }
+};
+
+/*
+ * Some predefined ffaces.
+ */
+struct fface_s String_fface = { String, ff_No_fflag };
+struct fface_s Plain_fface = { Plain, ff_No_fflag };
+struct fface_s Symbol_fface = { Symbol, ff_No_fflag };
+struct fface_s No_fface = { No_face, ff_No_fflag };
+
+
+/*
+ * Report the flagged face (included the face)
+ */
+void
+fflag_self_print (enum fflag_e flags, FILE * stream)
+{
+ int i;
+ int first = true;
+
+ putc ('(', stream);
+
+ if (flags == ff_No_fflag)
+ fputs ("No_fflag", stream);
+ else
+ {
+ /* Report the flags: make a loop onto the bits */
+ for (i = 0 ; fflag_and_name [i].flag ; i++)
+ if (fflag_and_name [i].flag & flags) {
+ if (!first)
+ fputs (" + ", stream);
+ else
+ first = false;
+ fputs (fflag_and_name [i].name, stream);
+ }
+ }
+
+ putc (')', stream);
+}
+
+/*
+ * Report the flagged face (included the face)
+ */
+void
+fface_self_print (struct fface_s fface, FILE * stream)
+{
+ int i;
+
+ if (fface.flags) {
+ putc ('(', stream);
+
+ /* Report the base face */
+ face_self_print (fface.face, stream);
+
+ /* Report the flags: make a loop onto the bits */
+ for (i = 0 ; fflag_and_name [i].flag ; i++)
+ if (fflag_and_name [i].flag & fface.flags) {
+ fputs (" + ", stream);
+ fputs (fflag_and_name [i].name, stream);
+ }
+
+ putc (')', stream);
+ }
+ else
+ /* There is nothing but the pure face to report */
+ face_self_print (fface.face, stream);
+}
diff --git a/src/ffaces.h b/src/ffaces.h
new file mode 100644
index 0000000..7709616
--- /dev/null
+++ b/src/ffaces.h
@@ -0,0 +1,125 @@
+/*
+ * ffaces.h
+ *
+ * definition of the flagged faces used by a2ps
+ * Copyright (c) 1988, 89, 90, 91, 92, 93 Miguel Santana
+ * Copyright (c) 1995, 96, 97, 98 Akim Demaille, Miguel Santana
+ *
+ */
+
+/*
+ * This file is part of a2ps.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * $Id: ffaces.h,v 1.1.1.1.2.1 2007/12/29 01:58:35 mhatta Exp $
+ */
+
+#ifndef _FFACES_H_
+#define _FFACES_H_
+#include "faces.h"
+
+/*
+ * These flags can be seen as an extension of the faces: they
+ * offer a way to have more information about the way the text
+ * should be processed by adding special flags _not_ to be
+ * seen by liba2ps.
+ *
+ * Many things used to be implemented as pure face_e, but it is
+ * better like this, and removes from liba2ps code/defs that were
+ * ment to a2ps-prog only
+ */
+enum fflag_e {
+ ff_No_fflag = 0,
+
+ /* Make the text invisible (don't print it) */
+ ff_Invisible = 1 << 0,
+
+ /* Grabbing from the text (used for headings etc) */
+ ff_Tag1 = 1 << 1,
+ ff_Tag2 = 1 << 2,
+ ff_Tag3 = 1 << 3,
+ ff_Tag4 = 1 << 4,
+
+ /* Store in the Indexes */
+ ff_Index1 = 1 << 5,
+ ff_Index2 = 1 << 6,
+ ff_Index3 = 1 << 7,
+ ff_Index4 = 1 << 8,
+
+ /* Grab an Encoding (Dynamic encoding switches) */
+ ff_Encoding = 1 << 9
+};
+
+void fflag_self_print PARAMS ((enum fflag_e flags, FILE * stream));
+
+/************************************************************************/
+/* Flagged faces */
+/************************************************************************/
+
+struct fface_s {
+ enum face_e face; /* The part which is the face to give to liba2ps */
+ enum fflag_e flags; /* The special flags for prog-a2ps */
+};
+
+void fface_self_print PARAMS ((struct fface_s face, FILE * stream));
+
+/*
+ * Read/Set the face part
+ */
+#define fface_set_face(ff,fa) \
+ ((ff).face) = (fa)
+
+#define fface_reset_face(ff) \
+ ((ff).face) = (No_face)
+
+#define fface_get_face(ff) \
+ ((ff).face)
+
+
+/*
+ * Read/Set the flags part
+ */
+#define fface_set_flags(ff,fl) \
+ ((ff).flags) = (fl)
+
+#define fface_reset_flags(ff) \
+ ((ff).flags) = ff_No_fflag
+
+#define fface_get_flags(ff) \
+ ((ff).flags)
+
+/* Here I cast, because for MIPSpro, enum | enum => int */
+#define fface_add_flags(ff,fl) \
+ fface_set_flags (ff, ((enum fflag_e) fface_get_flags (ff) | (fl)))
+
+/*
+ * Compare two ffaces
+ */
+#define fface_squ(ff1,ff2) \
+ (((ff1).face == (ff2).face) && ((ff1).flags == (ff2).flags))
+
+/*
+ * Some predefined ffaces.
+ */
+extern struct fface_s String_fface;
+extern struct fface_s Plain_fface;
+extern struct fface_s Symbol_fface;
+extern struct fface_s No_fface;
+
+#endif /* !defined(_FFACES_H_) */
diff --git a/src/generate.c b/src/generate.c
new file mode 100644
index 0000000..18f9ef5
--- /dev/null
+++ b/src/generate.c
@@ -0,0 +1,386 @@
+/*
+ * generate.c -- Input files and pretty printing.
+ *
+ * Copyright (c) 1995-99 Akim Demaille, Miguel Santana
+ */
+
+/*
+ * This file is part of a2ps.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "main.h"
+
+extern int isdir PARAMS ((const char *path));
+
+/* Name of the file in which the tmp sample file is stored. */
+char *sample_tmpname = NULL;
+
+/*
+ * What kind of treatement should be applied
+ */
+enum style_kind_e
+{
+ no_style, binary, sshparser, unprintable, delegate
+};
+
+static enum style_kind_e
+string_to_style_kind (const char * string)
+{
+ if (strequ (string, "binary"))
+ return binary;
+ else if (strequ (string, "UNPRINTABLE"))
+ return unprintable;
+ else if (strequ (string, "plain"))
+ return no_style;
+ else if (strequ (string, "delegate"))
+ return delegate;
+ return sshparser;
+}
+/************************************************************************/
+/* The inputs */
+/************************************************************************/
+static buffer_t *
+input_new (uchar * name)
+{
+ NEW (buffer_t, res);
+ struct file_job * file_job;
+ struct stat statbuf; /* to get file modification time */
+ struct tm *tm;
+
+ a2ps_open_input_session (job, name);
+ file_job = CURRENT_FILE (job);
+
+ /* Retrieve file modification date and hour */
+ if (IS_EMPTY(name) || ustrequ (name, "-"))
+ {
+ file_job->is_stdin = true;
+ file_job->name = job->stdin_filename;
+ /* Create the buffer in charge of stdin */
+ buffer_stream_set (res, stdin, end_of_line);
+ /* Ask it to make a sample of the file. */
+ tempname_ensure (sample_tmpname);
+ buffer_sample_get (res, sample_tmpname);
+ }
+ else
+ {
+ FILE * input_stream;
+ /* This is a true file (not stdin) */
+ file_job->is_stdin = false;
+
+ /* Printing a file given by its path */
+ if (isdir ((char *) name))
+ {
+ error (0, 0, _("`%s' is a directory"), quotearg ((char *) name));
+ file_job->printable = false;
+ }
+
+ file_job->name = (uchar *) name;
+ if ((input_stream = fopen ((char *) name, "r")) == NULL)
+ {
+ error (0, errno,
+ _("cannot open file `%s'"), quotearg ((char *) name));
+ file_job->printable = false;
+ }
+ else if (stat ((char *) name, &statbuf) == -1)
+ {
+ error (0, errno, _("cannot get informations on file `%s'"),
+ quotearg ((char *) name));
+ file_job->printable = false;
+ }
+ else
+ {
+ time_t tim = statbuf.st_mtime;
+ tm = localtime (&tim);
+ memcpy (&(file_job->mod_tm), tm, sizeof (*tm));
+ }
+ /* Create the buffer in charge of the input stream */
+ buffer_stream_set (res, input_stream, end_of_line);
+ }
+
+
+ /*
+ * What should be done out of this file?
+ * Find the command associated to that file
+ * - UNPRINTABLE for unprintable
+ * - requested style sheet key
+ * - style sheet key
+ */
+ if (!file_job->printable)
+ file_job->type = "UNPRINTABLE";
+ else if (!IS_EMPTY (style_request))
+ file_job->type = style_request;
+ else
+ file_job->type = get_command (file_job->name,
+ (sample_tmpname
+ ? (uchar *) sample_tmpname
+ : file_job->name));
+
+ /* Remove the sample file */
+ if (sample_tmpname)
+ unlink (sample_tmpname);
+ return res;
+}
+
+static void
+input_end (buffer_t * buffer)
+{
+ if (buffer->stream && buffer->stream!= stdin)
+ fclose (buffer->stream);
+ buffer_release (buffer);
+ free (buffer);
+
+ a2ps_close_input_session (job);
+}
+
+/************************************************************************/
+/* The producers */
+/************************************************************************/
+/*
+ * Make on message on what we did
+ */
+static void
+msg_file_pages_printed (a2ps_job * Job, const char * stylename)
+{
+ int sheets;
+
+ sheets = CURRENT_FILE (Job)->sheets;
+ if (Job->duplex)
+ sheets = (sheets + 1) / 2;
+
+ if (CURRENT_FILE (Job)->pages == 1)
+ /* 1 page on 1 sheet */
+ message (msg_report2,
+ (stderr, _("[%s (%s): 1 page on 1 sheet]\n"),
+ CURRENT_FILE (Job)->name,
+ stylename));
+ else if (sheets == 1)
+ /* several pages on 1 sheet */
+ message (msg_report2,
+ (stderr, _("[%s (%s): %d pages on 1 sheet]\n"),
+ CURRENT_FILE (Job)->name,
+ stylename,
+ CURRENT_FILE (Job)->pages));
+ else
+ /* several sheets */
+ message (msg_report2,
+ (stderr, _("[%s (%s): %d pages on %d sheets]\n"),
+ CURRENT_FILE (Job)->name,
+ stylename,
+ CURRENT_FILE (Job)-> pages,
+ sheets));
+}
+
+/*
+ * Total printed
+ */
+void
+msg_job_pages_printed (a2ps_job * Job)
+{
+ int sheets;
+ uchar *ucp;
+
+ sheets = Job->sheets;
+ if (Job->duplex)
+ sheets = (sheets + 1) / 2;
+
+ /* Make a nice message to tell where the output is sent */
+ ucp = a2ps_destination_to_string (Job);
+
+ /* Report the pages */
+ if (Job->pages == 1)
+ /* 1 page on 1 sheet "sent to the default printer" etc. */
+ message (msg_report1,
+ (stderr, _("[Total: 1 page on 1 sheet] %s\n"), ucp));
+ else if (sheets == 1)
+ /* several pages on 1 sheet */
+ message (msg_report1,
+ (stderr, _("[Total: %d pages on 1 sheet] %s\n"),
+ Job->pages, ucp));
+ else
+ /* several sheets */
+ message (msg_report1,
+ (stderr, _("[Total: %d pages on %d sheets] %s\n"),
+ Job-> pages, sheets, ucp));
+
+ /* Report the number of lines that were too long. */
+ if (macro_meta_sequence_get (Job, "cfg.wrapped")
+ && Job->lines_folded)
+ {
+ if (Job->lines_folded == 1)
+ message (msg_report1,
+ (stderr, _("[1 line wrapped]\n")));
+ else
+ message (msg_report1,
+ (stderr, _("[%d lines wrapped]\n"),
+ Job->lines_folded));
+ }
+
+ free (ucp);
+}
+/*
+ * Total printed
+ */
+void
+msg_nothing_printed (void)
+{
+ message (msg_report1,
+ (stderr, _("[No output produced]\n")));
+}
+
+void
+print_toc (const uchar * name, const uchar * value, int * native_jobs)
+{
+ buffer_t toc_buffer;
+ uchar * toc_content;
+
+ /* Create a entry for the toc, as if it were a regular file */
+ a2ps_open_input_session (job, xustrdup (name));
+ /* But it is not a regular file: we need to be able to know
+ * that it is indeed a toc, so that --pages=toc can be honored */
+ CURRENT_FILE (job)->is_toc = true;
+
+ austrcpy (toc_content,
+ expand_user_string (job, CURRENT_FILE (job),
+ name, value));
+ buffer_string_set (&toc_buffer, toc_content, end_of_line);
+
+ /* We typeset it with PreScript */
+ ssh_print_postscript (job, &toc_buffer, get_style_sheet ("pre"));
+ (*native_jobs)++;
+
+ a2ps_close_input_session (job);
+}
+
+/*
+ * Called by the main loop.
+ * The file to print is the last of the darray job->jobs.
+ * Return true if was a success, false otherwise
+ */
+void
+print (uchar * filename, int * native_jobs, int * delegated_jobs)
+{
+ char buf[512];
+ struct delegation * contract = NULL;
+ struct style_sheet * sheet;
+ buffer_t * input_buffer;
+ enum style_kind_e style_kind;
+ struct file_job * file_job;
+
+ /*
+ * First, open that file and get info about it
+ * It may seem useless in some cases (e.g. the file will be delegated)
+ * but it ensures that readbility, and stat can be correctly done.
+ */
+ input_buffer = input_new (filename);
+
+ /* Get the file_job _after_ it has been created by input_new */
+ file_job = CURRENT_FILE (job);
+
+ if (delegate_p
+ && (contract =
+ get_subcontract (file_job->type,
+ output_format_to_key (job->output_format))))
+ style_kind = delegate;
+ else
+ style_kind = string_to_style_kind (file_job->type);
+
+ message (msg_file,
+ (stderr, "Getting ready to print file `%s', with command `%s'\n",
+ file_job->name, file_job->type));
+
+ /*
+ * Then do it
+ */
+ switch (style_kind)
+ {
+ case delegate:
+ /* In ps generation, we must begin a new page */
+ page_flush (job);
+ sprintf (buf, _("%s, delegated to %s"),
+ file_job->type, contract->name);
+ if (subcontract (file_job, input_buffer, contract))
+ {
+ (*delegated_jobs)++;
+ msg_file_pages_printed (job, buf);
+ }
+ else
+ message (msg_report2, (stderr, _("[%s (%s): failed. Ignored]\n"),
+ file_job->name, buf));
+ break;
+
+ case unprintable:
+ /* The job will not be processed correctly */
+ message (msg_report2,
+ (stderr,
+ _("[%s (unprintable): ignored]\n"), file_job->name));
+ break;
+
+ case binary:
+ if (job->print_binaries)
+ goto plain_print;
+
+ message (msg_report2,
+ (stderr,
+ _("[%s (binary): ignored]\n"), file_job->name));
+ break;
+
+ case sshparser:
+ /* If highlight_level == none, don't */
+ if (highlight_level == 0)
+ goto plain_print;
+ sheet = get_style_sheet (file_job->type);
+ if (!sheet)
+ goto plain_print;
+
+ buffer_set_lower_case (input_buffer,
+ sheet->sensitiveness == case_insensitive);
+ ssh_print_postscript (job, input_buffer, sheet);
+ msg_file_pages_printed (job, (const char *) sheet->name);
+ (*native_jobs)++;
+ break;
+
+ plain_print:
+ case no_style:
+ plain_print_postscript (job, input_buffer);
+ msg_file_pages_printed (job, _("plain"));
+ (*native_jobs)++;
+ break;
+ }
+
+ input_end (input_buffer);
+}
+
+/*
+ * Called by the main loop.
+ * Almost like the above `PRINT' function, but just reports the guesses.
+ * This is a dirty hack of sth OK in 4.11
+ */
+void
+guess (uchar * filename)
+{
+ buffer_t * buffer;
+ struct file_job * file_job;
+
+ buffer = input_new (filename);
+ file_job = CURRENT_FILE (job);
+ printf ("[%s (%s)]\n", file_job->name, file_job->type);
+
+ /* Close the files, free, and close the input session */
+ if (buffer->stream && buffer->stream != stdin)
+ fclose (buffer->stream);
+}
diff --git a/src/generate.h b/src/generate.h
new file mode 100644
index 0000000..5a0e409
--- /dev/null
+++ b/src/generate.h
@@ -0,0 +1,38 @@
+/*
+ * generate.h -- Input files and pretty printing.
+ *
+ * Copyright (c) 1995-99 Akim Demaille, Miguel Santana
+ */
+
+/*
+ * This file is part of a2ps.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef GENERATE_H_
+# define GENERATE_H_
+
+void print PARAMS ((uchar * name, int * native_jobs, int * delegated_jobs));
+void print_toc PARAMS ((const uchar * name, const uchar * value,
+ int * native_jobs));
+
+void msg_job_pages_printed PARAMS ((a2ps_job * job));
+void msg_nothing_printed PARAMS ((void));
+
+void guess PARAMS ((uchar * name));
+
+#endif /* not defined(GENERATE_H_) */
diff --git a/src/lexps.c b/src/lexps.c
new file mode 100644
index 0000000..06fe6a9
--- /dev/null
+++ b/src/lexps.c
@@ -0,0 +1,1782 @@
+#line 2 "lexps.c"
+
+#line 4 "lexps.c"
+
+#define YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 33
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#endif
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_CONST
+
+#endif /* __STDC__ */
+#endif /* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE psrestart(psin )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+extern int psleng;
+
+extern FILE *psin, *psout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+ #define YY_LESS_LINENO(n)
+
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up pstext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ *yy_cp = (yy_hold_char); \
+ YY_RESTORE_YY_MORE_OFFSET \
+ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up pstext again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr) )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef unsigned int yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ int yy_bs_lineno; /**< The line count. */
+ int yy_bs_column; /**< The column count. */
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via psrestart()), so that the user can continue scanning by
+ * just pointing psin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+
+ };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+ : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when pstext is formed. */
+static char yy_hold_char;
+static int yy_n_chars; /* number of characters read into yy_ch_buf */
+int psleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 0; /* whether we need to initialize */
+static int yy_start = 0; /* start state number */
+
+/* Flag which is used to allow pswrap()'s to do buffer switches
+ * instead of setting up a fresh psin. A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void psrestart (FILE *input_file );
+void ps_switch_to_buffer (YY_BUFFER_STATE new_buffer );
+YY_BUFFER_STATE ps_create_buffer (FILE *file,int size );
+void ps_delete_buffer (YY_BUFFER_STATE b );
+void ps_flush_buffer (YY_BUFFER_STATE b );
+void pspush_buffer_state (YY_BUFFER_STATE new_buffer );
+void pspop_buffer_state (void );
+
+static void psensure_buffer_stack (void );
+static void ps_load_buffer_state (void );
+static void ps_init_buffer (YY_BUFFER_STATE b,FILE *file );
+
+#define YY_FLUSH_BUFFER ps_flush_buffer(YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE ps_scan_buffer (char *base,yy_size_t size );
+YY_BUFFER_STATE ps_scan_string (yyconst char *yy_str );
+YY_BUFFER_STATE ps_scan_bytes (yyconst char *bytes,int len );
+
+void *psalloc (yy_size_t );
+void *psrealloc (void *,yy_size_t );
+void psfree (void * );
+
+#define yy_new_buffer ps_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){ \
+ psensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ ps_create_buffer(psin,YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){\
+ psensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ ps_create_buffer(psin,YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+typedef unsigned char YY_CHAR;
+
+FILE *psin = (FILE *) 0, *psout = (FILE *) 0;
+
+typedef int yy_state_type;
+
+extern int pslineno;
+
+int pslineno = 1;
+
+extern char *pstext;
+#define yytext_ptr pstext
+
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state );
+static int yy_get_next_buffer (void );
+static void yy_fatal_error (yyconst char msg[] );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up pstext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ (yytext_ptr) = yy_bp; \
+ psleng = (size_t) (yy_cp - yy_bp); \
+ (yy_hold_char) = *yy_cp; \
+ *yy_cp = '\0'; \
+ (yy_c_buf_p) = yy_cp;
+
+#define YY_NUM_RULES 4
+#define YY_END_OF_BUFFER 5
+/* This struct is not used in this scanner,
+ but its presence is necessary. */
+struct yy_trans_info
+ {
+ flex_int32_t yy_verify;
+ flex_int32_t yy_nxt;
+ };
+static yyconst flex_int16_t yy_accept[26] =
+ { 0,
+ 2, 2, 3, 3, 5, 2, 4, 2, 3, 2,
+ 2, 3, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 1, 0
+ } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 3, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 4, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 5, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 6, 1, 7, 1, 8, 1, 1, 1, 1, 9,
+ 1, 10, 1, 1, 1, 11, 12, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+static yyconst flex_int32_t yy_meta[13] =
+ { 0,
+ 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1
+ } ;
+
+static yyconst flex_int16_t yy_base[31] =
+ { 0,
+ 25, 0, 24, 23, 24, 0, 28, 20, 0, 0,
+ 18, 0, 15, 13, 11, 9, 12, 10, 4, 2,
+ 3, 10, 9, 28, 28, 3, 5, 9, 0, 7
+ } ;
+
+static yyconst flex_int16_t yy_def[31] =
+ { 0,
+ 26, 26, 27, 27, 25, 28, 25, 28, 29, 28,
+ 28, 29, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 30, 30, 25, 0, 25, 25, 25, 25, 25
+ } ;
+
+static yyconst flex_int16_t yy_nxt[41] =
+ { 0,
+ 12, 7, 8, 6, 6, 9, 9, 23, 23, 10,
+ 24, 24, 22, 21, 20, 19, 18, 17, 16, 15,
+ 14, 13, 11, 25, 7, 7, 7, 5, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25
+ } ;
+
+static yyconst flex_int16_t yy_chk[41] =
+ { 0,
+ 29, 2, 2, 26, 26, 27, 27, 30, 30, 28,
+ 23, 22, 21, 20, 19, 18, 17, 16, 15, 14,
+ 13, 11, 8, 5, 4, 3, 1, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25
+ } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+extern int ps_flex_debug;
+int ps_flex_debug = 0;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *pstext;
+#line 1 "lexps.l"
+#line 2 "lexps.l"
+/* A Simple Lexer for PostScript.
+
+ Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2002 Akim
+ Demaille, Miguel Santana */
+
+/*
+ * This file is part of a2ps.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "main.h"
+#include "lexps.h"
+
+int pslex PARAMS ((void));
+void yyerror PARAMS ((const char *));
+
+/* Initilizes the obstacks */
+void pslex_initialize PARAMS ((void));
+
+#line 501 "lexps.c"
+
+#define INITIAL 0
+#define FINISH 1
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals (void );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int pswrap (void );
+#else
+extern int pswrap (void );
+#endif
+#endif
+
+ static void yyunput (int c,char *buf_ptr );
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (void );
+#else
+static int input (void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( pstext, psleng, 1, psout )
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+ { \
+ int c = '*'; \
+ size_t n; \
+ for ( n = 0; n < max_size && \
+ (c = getc( psin )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+ if ( c == '\n' ) \
+ buf[n++] = (char) c; \
+ if ( c == EOF && ferror( psin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ } \
+ else \
+ { \
+ errno=0; \
+ while ( (result = fread(buf, 1, max_size, psin))==0 && ferror(psin)) \
+ { \
+ if( errno != EINTR) \
+ { \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ break; \
+ } \
+ errno=0; \
+ clearerr(psin); \
+ } \
+ }\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int pslex (void);
+
+#define YY_DECL int pslex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after pstext and psleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+ if ( psleng > 0 ) \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
+ (pstext[psleng - 1] == '\n'); \
+ YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp, *yy_bp;
+ register int yy_act;
+
+#line 42 "lexps.l"
+
+
+#line 661 "lexps.c"
+
+ if ( !(yy_init) )
+ {
+ (yy_init) = 1;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if ( ! (yy_start) )
+ (yy_start) = 1; /* first start state */
+
+ if ( ! psin )
+ psin = stdin;
+
+ if ( ! psout )
+ psout = stdout;
+
+ if ( ! YY_CURRENT_BUFFER ) {
+ psensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ ps_create_buffer(psin,YY_BUF_SIZE );
+ }
+
+ ps_load_buffer_state( );
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = (yy_c_buf_p);
+
+ /* Support of pstext. */
+ *yy_cp = (yy_hold_char);
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = (yy_start);
+ yy_current_state += YY_AT_BOL();
+yy_match:
+ do
+ {
+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 26 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ ++yy_cp;
+ }
+ while ( yy_base[yy_current_state] != 28 );
+
+yy_find_action:
+ yy_act = yy_accept[yy_current_state];
+ if ( yy_act == 0 )
+ { /* have to back up */
+ yy_cp = (yy_last_accepting_cpos);
+ yy_current_state = (yy_last_accepting_state);
+ yy_act = yy_accept[yy_current_state];
+ }
+
+ YY_DO_BEFORE_ACTION;
+
+do_action: /* This label is used only to access EOF actions. */
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+ case 0: /* must back up */
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = (yy_hold_char);
+ yy_cp = (yy_last_accepting_cpos);
+ yy_current_state = (yy_last_accepting_state);
+ goto yy_find_action;
+
+case 1:
+/* rule 1 can match eol */
+YY_RULE_SETUP
+#line 44 "lexps.l"
+{
+ ECHO;
+ pagedevice_dump (psout, job);
+ BEGIN FINISH;
+}
+ YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 50 "lexps.l"
+ECHO;
+ YY_BREAK
+
+case 3:
+YY_RULE_SETUP
+#line 53 "lexps.l"
+ECHO;
+ YY_BREAK
+
+case 4:
+YY_RULE_SETUP
+#line 55 "lexps.l"
+ECHO;
+ YY_BREAK
+#line 772 "lexps.c"
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(FINISH):
+ yyterminate();
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = (yy_hold_char);
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed psin at a new source and called
+ * pslex(). If so, then we have to assure
+ * consistency between YY_CURRENT_BUFFER and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ YY_CURRENT_BUFFER_LVALUE->yy_input_file = psin;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( );
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++(yy_c_buf_p);
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = (yy_c_buf_p);
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer( ) )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ (yy_did_buffer_switch_on_eof) = 0;
+
+ if ( pswrap( ) )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * pstext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! (yy_did_buffer_switch_on_eof) )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ (yy_c_buf_p) =
+ (yytext_ptr) + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( );
+
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ (yy_c_buf_p) =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+ yy_current_state = yy_get_previous_state( );
+
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+} /* end of pslex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (void)
+{
+ register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ register char *source = (yytext_ptr);
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+ else
+ {
+ int num_to_read =
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+ int yy_c_buf_p_offset =
+ (int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+ int new_size = b->yy_buf_size * 2;
+
+ if ( new_size <= 0 )
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ psrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = 0;
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+ (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+ number_to_move - 1;
+
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+ (yy_n_chars), (size_t) num_to_read );
+
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ if ( (yy_n_chars) == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ psrestart(psin );
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ (yy_n_chars) += number_to_move;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+ (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+ return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+ static yy_state_type yy_get_previous_state (void)
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+
+ yy_current_state = (yy_start);
+ yy_current_state += YY_AT_BOL();
+
+ for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+ {
+ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 26 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ }
+
+ return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state )
+{
+ register int yy_is_jam;
+ register char *yy_cp = (yy_c_buf_p);
+
+ register YY_CHAR yy_c = 1;
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 26 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_is_jam = (yy_current_state == 25);
+
+ return yy_is_jam ? 0 : yy_current_state;
+}
+
+ static void yyunput (int c, register char * yy_bp )
+{
+ register char *yy_cp;
+
+ yy_cp = (yy_c_buf_p);
+
+ /* undo effects of setting up pstext */
+ *yy_cp = (yy_hold_char);
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ { /* need to shift things up to make room */
+ /* +2 for EOB chars. */
+ register int number_to_move = (yy_n_chars) + 2;
+ register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+ register char *source =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+ while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ *--dest = *--source;
+
+ yy_cp += (int) (dest - source);
+ yy_bp += (int) (dest - source);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ YY_FATAL_ERROR( "flex scanner push-back overflow" );
+ }
+
+ *--yy_cp = (char) c;
+
+ (yytext_ptr) = yy_bp;
+ (yy_hold_char) = *yy_cp;
+ (yy_c_buf_p) = yy_cp;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+ static int yyinput (void)
+#else
+ static int input (void)
+#endif
+
+{
+ int c;
+
+ *(yy_c_buf_p) = (yy_hold_char);
+
+ if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+ /* This was really a NUL. */
+ *(yy_c_buf_p) = '\0';
+
+ else
+ { /* need more input */
+ int offset = (yy_c_buf_p) - (yytext_ptr);
+ ++(yy_c_buf_p);
+
+ switch ( yy_get_next_buffer( ) )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ psrestart(psin );
+
+ /*FALLTHROUGH*/
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( pswrap( ) )
+ return EOF;
+
+ if ( ! (yy_did_buffer_switch_on_eof) )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput();
+#else
+ return input();
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ (yy_c_buf_p) = (yytext_ptr) + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */
+ *(yy_c_buf_p) = '\0'; /* preserve pstext */
+ (yy_hold_char) = *++(yy_c_buf_p);
+
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
+
+ return c;
+}
+#endif /* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ *
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+ void psrestart (FILE * input_file )
+{
+
+ if ( ! YY_CURRENT_BUFFER ){
+ psensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ ps_create_buffer(psin,YY_BUF_SIZE );
+ }
+
+ ps_init_buffer(YY_CURRENT_BUFFER,input_file );
+ ps_load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ *
+ */
+ void ps_switch_to_buffer (YY_BUFFER_STATE new_buffer )
+{
+
+ /* TODO. We should be able to replace this entire function body
+ * with
+ * pspop_buffer_state();
+ * pspush_buffer_state(new_buffer);
+ */
+ psensure_buffer_stack ();
+ if ( YY_CURRENT_BUFFER == new_buffer )
+ return;
+
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+ ps_load_buffer_state( );
+
+ /* We don't actually know whether we did this switch during
+ * EOF (pswrap()) processing, but the only time this flag
+ * is looked at is after pswrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void ps_load_buffer_state (void)
+{
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+ psin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+ (yy_hold_char) = *(yy_c_buf_p);
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ *
+ * @return the allocated buffer state.
+ */
+ YY_BUFFER_STATE ps_create_buffer (FILE * file, int size )
+{
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) psalloc(sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in ps_create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) psalloc(b->yy_buf_size + 2 );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in ps_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ ps_init_buffer(b,file );
+
+ return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with ps_create_buffer()
+ *
+ */
+ void ps_delete_buffer (YY_BUFFER_STATE b )
+{
+
+ if ( ! b )
+ return;
+
+ if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ psfree((void *) b->yy_ch_buf );
+
+ psfree((void *) b );
+}
+
+#ifndef __cplusplus
+extern int isatty (int );
+#endif /* __cplusplus */
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a psrestart() or at EOF.
+ */
+ static void ps_init_buffer (YY_BUFFER_STATE b, FILE * file )
+
+{
+ int oerrno = errno;
+
+ ps_flush_buffer(b );
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+ /* If b is the current buffer, then ps_init_buffer was _probably_
+ * called from psrestart() or through yy_get_next_buffer.
+ * In that case, we don't want to reset the lineno or column.
+ */
+ if (b != YY_CURRENT_BUFFER){
+ b->yy_bs_lineno = 1;
+ b->yy_bs_column = 0;
+ }
+
+ b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+
+ errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ *
+ */
+ void ps_flush_buffer (YY_BUFFER_STATE b )
+{
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == YY_CURRENT_BUFFER )
+ ps_load_buffer_state( );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ * the current state. This function will allocate the stack
+ * if necessary.
+ * @param new_buffer The new state.
+ *
+ */
+void pspush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+ if (new_buffer == NULL)
+ return;
+
+ psensure_buffer_stack();
+
+ /* This block is copied from ps_switch_to_buffer. */
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ /* Only push if top exists. Otherwise, replace top. */
+ if (YY_CURRENT_BUFFER)
+ (yy_buffer_stack_top)++;
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+ /* copied from ps_switch_to_buffer. */
+ ps_load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ * The next element becomes the new top.
+ *
+ */
+void pspop_buffer_state (void)
+{
+ if (!YY_CURRENT_BUFFER)
+ return;
+
+ ps_delete_buffer(YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ if ((yy_buffer_stack_top) > 0)
+ --(yy_buffer_stack_top);
+
+ if (YY_CURRENT_BUFFER) {
+ ps_load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
+ }
+}
+
+/* Allocates the stack if it does not exist.
+ * Guarantees space for at least one push.
+ */
+static void psensure_buffer_stack (void)
+{
+ int num_to_alloc;
+
+ if (!(yy_buffer_stack)) {
+
+ /* First allocation is just for 2 elements, since we don't know if this
+ * scanner will even need a stack. We use 2 instead of 1 to avoid an
+ * immediate realloc on the next call.
+ */
+ num_to_alloc = 1;
+ (yy_buffer_stack) = (struct yy_buffer_state**)psalloc
+ (num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+
+ memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+
+ (yy_buffer_stack_max) = num_to_alloc;
+ (yy_buffer_stack_top) = 0;
+ return;
+ }
+
+ if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+ /* Increase the buffer to prepare for a possible push. */
+ int grow_size = 8 /* arbitrary grow size */;
+
+ num_to_alloc = (yy_buffer_stack_max) + grow_size;
+ (yy_buffer_stack) = (struct yy_buffer_state**)psrealloc
+ ((yy_buffer_stack),
+ num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+
+ /* zero only the new slots.*/
+ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+ (yy_buffer_stack_max) = num_to_alloc;
+ }
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE ps_scan_buffer (char * base, yy_size_t size )
+{
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE) psalloc(sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in ps_scan_buffer()" );
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ ps_switch_to_buffer(b );
+
+ return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to pslex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ *
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ * ps_scan_bytes() instead.
+ */
+YY_BUFFER_STATE ps_scan_string (yyconst char * yystr )
+{
+
+ return ps_scan_bytes(yystr,strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to pslex() will
+ * scan from a @e copy of @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE ps_scan_bytes (yyconst char * yybytes, int _yybytes_len )
+{
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = _yybytes_len + 2;
+ buf = (char *) psalloc(n );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in ps_scan_bytes()" );
+
+ for ( i = 0; i < _yybytes_len; ++i )
+ buf[i] = yybytes[i];
+
+ buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = ps_scan_buffer(buf,n );
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in ps_scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg )
+{
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up pstext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ pstext[psleng] = (yy_hold_char); \
+ (yy_c_buf_p) = pstext + yyless_macro_arg; \
+ (yy_hold_char) = *(yy_c_buf_p); \
+ *(yy_c_buf_p) = '\0'; \
+ psleng = yyless_macro_arg; \
+ } \
+ while ( 0 )
+
+/* Accessor methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ *
+ */
+int psget_lineno (void)
+{
+
+ return pslineno;
+}
+
+/** Get the input stream.
+ *
+ */
+FILE *psget_in (void)
+{
+ return psin;
+}
+
+/** Get the output stream.
+ *
+ */
+FILE *psget_out (void)
+{
+ return psout;
+}
+
+/** Get the length of the current token.
+ *
+ */
+int psget_leng (void)
+{
+ return psleng;
+}
+
+/** Get the current token.
+ *
+ */
+
+char *psget_text (void)
+{
+ return pstext;
+}
+
+/** Set the current line number.
+ * @param line_number
+ *
+ */
+void psset_lineno (int line_number )
+{
+
+ pslineno = line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ *
+ * @see ps_switch_to_buffer
+ */
+void psset_in (FILE * in_str )
+{
+ psin = in_str ;
+}
+
+void psset_out (FILE * out_str )
+{
+ psout = out_str ;
+}
+
+int psget_debug (void)
+{
+ return ps_flex_debug;
+}
+
+void psset_debug (int bdebug )
+{
+ ps_flex_debug = bdebug ;
+}
+
+static int yy_init_globals (void)
+{
+ /* Initialization is the same as for the non-reentrant scanner.
+ * This function is called from pslex_destroy(), so don't allocate here.
+ */
+
+ (yy_buffer_stack) = 0;
+ (yy_buffer_stack_top) = 0;
+ (yy_buffer_stack_max) = 0;
+ (yy_c_buf_p) = (char *) 0;
+ (yy_init) = 0;
+ (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+ psin = stdin;
+ psout = stdout;
+#else
+ psin = (FILE *) 0;
+ psout = (FILE *) 0;
+#endif
+
+ /* For future reference: Set errno on error, since we are called by
+ * pslex_init()
+ */
+ return 0;
+}
+
+/* pslex_destroy is for both reentrant and non-reentrant scanners. */
+int pslex_destroy (void)
+{
+
+ /* Pop the buffer stack, destroying each element. */
+ while(YY_CURRENT_BUFFER){
+ ps_delete_buffer(YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ pspop_buffer_state();
+ }
+
+ /* Destroy the stack itself. */
+ psfree((yy_buffer_stack) );
+ (yy_buffer_stack) = NULL;
+
+ /* Reset the globals. This is important in a non-reentrant scanner so the next time
+ * pslex() is called, initialization will occur. */
+ yy_init_globals( );
+
+ return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+ register int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+ register int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+}
+#endif
+
+void *psalloc (yy_size_t size )
+{
+ return (void *) malloc( size );
+}
+
+void *psrealloc (void * ptr, yy_size_t size )
+{
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+}
+
+void psfree (void * ptr )
+{
+ free( (char *) ptr ); /* see psrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 55 "lexps.l"
+
+
+
+int
+pswrap (void)
+{
+ return 1;
+}
+
+/* Dump the file FILENAME on STREAM, while inserting the special
+ pagedevice requests of JOB. */
+
+void
+pslex_dump (FILE *stream, const char *filename)
+{
+ psin = xrfopen (filename);
+ psout = stream;
+
+ pslex ();
+}
+
diff --git a/src/lexps.h b/src/lexps.h
new file mode 100644
index 0000000..5fb9487
--- /dev/null
+++ b/src/lexps.h
@@ -0,0 +1,40 @@
+/*
+ * A Simple Lexer for PostScript.
+ *
+ * Copyright (c) 1988-1993 Miguel Santana
+ * Copyright (c) 1995-1999 Akim Demaille, Miguel Santana
+ *
+ */
+
+/*
+ * This file is part of a2ps.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * $Id: lexps.h,v 1.1.1.1.2.1 2007/12/29 01:58:35 mhatta Exp $
+ */
+
+#ifndef LEXPS_H_
+# define LEXPS_H_
+
+/* Dump the file FILENAME on STREAM, while inserting the special
+ pagedevice requests of JOB. */
+
+void pslex_dump PARAMS ((FILE *stream, const char *filename));
+
+#endif
diff --git a/src/lexps.l b/src/lexps.l
new file mode 100644
index 0000000..8548264
--- /dev/null
+++ b/src/lexps.l
@@ -0,0 +1,73 @@
+%{ /* -*- c -*- */
+/* A Simple Lexer for PostScript.
+
+ Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2002 Akim
+ Demaille, Miguel Santana */
+
+/*
+ * This file is part of a2ps.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "main.h"
+#include "lexps.h"
+
+int yylex PARAMS ((void));
+void yyerror PARAMS ((const char *));
+
+/* Initilizes the obstacks */
+void pslex_initialize PARAMS ((void));
+%}
+
+%option prefix="ps"
+%option outfile="lex.yy.c"
+
+%x FINISH
+
+begin_setup ^%%BeginSetup.*\n
+%%
+
+{begin_setup} {
+ ECHO;
+ pagedevice_dump (yyout, job);
+ BEGIN FINISH;
+}
+
+.* ECHO;
+
+<FINISH>{
+ .* ECHO;
+}
+%%
+
+int
+yywrap (void)
+{
+ return 1;
+}
+
+/* Dump the file FILENAME on STREAM, while inserting the special
+ pagedevice requests of JOB. */
+
+void
+pslex_dump (FILE *stream, const char *filename)
+{
+ yyin = xrfopen (filename);
+ yyout = stream;
+
+ pslex ();
+}
diff --git a/src/lexssh.c b/src/lexssh.c
new file mode 100644
index 0000000..a08dc9c
--- /dev/null
+++ b/src/lexssh.c
@@ -0,0 +1,3552 @@
+#line 2 "lexssh.c"
+
+#line 4 "lexssh.c"
+
+#define YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 33
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#endif
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_CONST
+
+#endif /* __STDC__ */
+#endif /* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE sshrestart(sshin )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+extern int sshleng;
+
+extern FILE *sshin, *sshout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+ /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
+ * access to the local variable yy_act. Since yyless() is a macro, it would break
+ * existing scanners that call yyless() from OUTSIDE sshlex.
+ * One obvious solution it to make yy_act a global. I tried that, and saw
+ * a 5% performance hit in a non-sshlineno scanner, because yy_act is
+ * normally declared as a register variable-- so it is not worth it.
+ */
+ #define YY_LESS_LINENO(n) \
+ do { \
+ int yyl;\
+ for ( yyl = n; yyl < sshleng; ++yyl )\
+ if ( sshtext[yyl] == '\n' )\
+ --sshlineno;\
+ }while(0)
+
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up sshtext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ *yy_cp = (yy_hold_char); \
+ YY_RESTORE_YY_MORE_OFFSET \
+ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up sshtext again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr) )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef unsigned int yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ int yy_bs_lineno; /**< The line count. */
+ int yy_bs_column; /**< The column count. */
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via sshrestart()), so that the user can continue scanning by
+ * just pointing sshin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+
+ };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+ : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when sshtext is formed. */
+static char yy_hold_char;
+static int yy_n_chars; /* number of characters read into yy_ch_buf */
+int sshleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 0; /* whether we need to initialize */
+static int yy_start = 0; /* start state number */
+
+/* Flag which is used to allow sshwrap()'s to do buffer switches
+ * instead of setting up a fresh sshin. A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void sshrestart (FILE *input_file );
+void ssh_switch_to_buffer (YY_BUFFER_STATE new_buffer );
+YY_BUFFER_STATE ssh_create_buffer (FILE *file,int size );
+void ssh_delete_buffer (YY_BUFFER_STATE b );
+void ssh_flush_buffer (YY_BUFFER_STATE b );
+void sshpush_buffer_state (YY_BUFFER_STATE new_buffer );
+void sshpop_buffer_state (void );
+
+static void sshensure_buffer_stack (void );
+static void ssh_load_buffer_state (void );
+static void ssh_init_buffer (YY_BUFFER_STATE b,FILE *file );
+
+#define YY_FLUSH_BUFFER ssh_flush_buffer(YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE ssh_scan_buffer (char *base,yy_size_t size );
+YY_BUFFER_STATE ssh_scan_string (yyconst char *yy_str );
+YY_BUFFER_STATE ssh_scan_bytes (yyconst char *bytes,int len );
+
+void *sshalloc (yy_size_t );
+void *sshrealloc (void *,yy_size_t );
+void sshfree (void * );
+
+#define yy_new_buffer ssh_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){ \
+ sshensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ ssh_create_buffer(sshin,YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){\
+ sshensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ ssh_create_buffer(sshin,YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+typedef unsigned char YY_CHAR;
+
+FILE *sshin = (FILE *) 0, *sshout = (FILE *) 0;
+
+typedef int yy_state_type;
+
+extern int sshlineno;
+
+int sshlineno = 1;
+
+extern char *sshtext;
+#define yytext_ptr sshtext
+
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state );
+static int yy_get_next_buffer (void );
+static void yy_fatal_error (yyconst char msg[] );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up sshtext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ (yytext_ptr) = yy_bp; \
+ sshleng = (size_t) (yy_cp - yy_bp); \
+ (yy_hold_char) = *yy_cp; \
+ *yy_cp = '\0'; \
+ (yy_c_buf_p) = yy_cp;
+
+#define YY_NUM_RULES 217
+#define YY_END_OF_BUFFER 218
+/* This struct is not used in this scanner,
+ but its presence is necessary. */
+struct yy_trans_info
+ {
+ flex_int32_t yy_verify;
+ flex_int32_t yy_nxt;
+ };
+static yyconst flex_int16_t yy_accept[901] =
+ { 0,
+ 2, 2, 0, 0, 0, 0, 218, 185, 2, 2,
+ 3, 1, 186, 185, 4, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 201, 200, 187,
+ 217, 216, 215, 202, 217, 185, 2, 1, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
+ 137, 185, 185, 185, 185, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
+
+ 185, 185, 185, 185, 185, 185, 185, 143, 185, 185,
+ 185, 185, 185, 185, 152, 154, 185, 185, 185, 185,
+ 185, 185, 185, 201, 199, 188, 190, 191, 192, 193,
+ 194, 195, 196, 197, 198, 199, 216, 214, 203, 205,
+ 206, 207, 208, 209, 210, 211, 212, 213, 214, 91,
+ 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
+ 185, 94, 185, 185, 185, 185, 21, 22, 185, 185,
+ 24, 185, 95, 185, 185, 185, 185, 185, 185, 32,
+ 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
+
+ 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 185, 185, 107, 185, 185, 185,
+ 185, 185, 185, 185, 50, 185, 185, 185, 51, 185,
+ 185, 185, 185, 185, 185, 53, 80, 185, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 185, 185, 96, 61, 185, 185,
+ 185, 185, 142, 185, 185, 185, 149, 185, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
+ 188, 189, 203, 204, 185, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 185, 185, 175, 176, 177, 178,
+
+ 185, 185, 11, 185, 185, 185, 16, 185, 185, 185,
+ 185, 185, 185, 185, 14, 33, 26, 185, 185, 28,
+ 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
+ 100, 185, 185, 40, 185, 185, 185, 185, 101, 185,
+ 185, 86, 185, 185, 185, 185, 45, 185, 185, 185,
+ 185, 81, 185, 185, 134, 185, 185, 185, 185, 185,
+ 185, 185, 67, 185, 185, 87, 117, 185, 185, 185,
+ 185, 185, 185, 43, 185, 185, 62, 185, 185, 185,
+ 185, 185, 55, 185, 185, 64, 185, 185, 185, 130,
+ 185, 185, 57, 185, 185, 185, 185, 185, 185, 119,
+
+ 185, 185, 138, 185, 185, 144, 185, 185, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
+ 185, 188, 189, 203, 204, 185, 185, 185, 185, 168,
+ 185, 185, 185, 169, 165, 185, 185, 185, 10, 185,
+ 185, 185, 185, 17, 185, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 34, 185, 185, 185, 185, 39,
+ 185, 185, 116, 79, 185, 8, 185, 185, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 185, 185, 46,
+ 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 36, 185, 114, 185, 185, 185,
+
+ 185, 185, 185, 185, 185, 185, 185, 185, 185, 115,
+ 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 63, 185, 185, 185, 185, 185,
+ 151, 185, 185, 185, 185, 185, 185, 185, 185, 162,
+ 185, 185, 146, 185, 185, 185, 179, 180, 181, 182,
+ 185, 185, 185, 171, 172, 9, 12, 185, 185, 15,
+ 19, 185, 185, 185, 31, 185, 185, 27, 25, 185,
+ 185, 93, 38, 109, 185, 185, 185, 185, 185, 41,
+ 185, 185, 185, 185, 88, 185, 185, 185, 44, 185,
+ 68, 48, 185, 185, 131, 90, 185, 185, 185, 110,
+
+ 185, 185, 60, 185, 98, 185, 185, 66, 185, 185,
+ 185, 135, 185, 185, 185, 56, 185, 185, 185, 185,
+ 185, 54, 82, 185, 185, 185, 185, 185, 185, 185,
+ 59, 185, 185, 185, 185, 118, 185, 185, 185, 185,
+ 185, 185, 185, 185, 185, 185, 157, 185, 185, 185,
+ 185, 185, 173, 185, 185, 166, 185, 185, 185, 20,
+ 185, 185, 185, 185, 185, 185, 89, 85, 185, 185,
+ 185, 185, 185, 185, 185, 6, 69, 5, 185, 49,
+ 126, 185, 185, 132, 108, 185, 185, 97, 185, 83,
+ 185, 133, 185, 136, 185, 185, 105, 185, 102, 185,
+
+ 185, 185, 185, 185, 185, 185, 47, 185, 185, 185,
+ 185, 185, 185, 145, 185, 185, 185, 185, 185, 185,
+ 185, 185, 185, 163, 164, 147, 185, 183, 185, 185,
+ 185, 185, 13, 185, 185, 23, 185, 122, 29, 185,
+ 185, 185, 185, 185, 185, 42, 185, 185, 185, 185,
+ 52, 84, 185, 185, 185, 185, 185, 185, 185, 185,
+ 185, 76, 58, 185, 185, 185, 185, 185, 185, 185,
+ 139, 185, 185, 185, 185, 155, 185, 160, 156, 185,
+ 185, 185, 184, 185, 185, 185, 185, 185, 185, 185,
+ 70, 185, 185, 185, 99, 185, 185, 185, 185, 185,
+
+ 127, 185, 185, 106, 7, 103, 185, 185, 185, 185,
+ 185, 185, 30, 18, 185, 140, 141, 185, 185, 185,
+ 159, 158, 161, 185, 185, 185, 124, 121, 185, 185,
+ 185, 128, 185, 78, 72, 75, 185, 185, 37, 185,
+ 73, 35, 129, 185, 185, 185, 185, 185, 185, 150,
+ 185, 185, 185, 185, 185, 123, 185, 185, 185, 104,
+ 77, 65, 185, 185, 185, 185, 185, 153, 185, 185,
+ 170, 185, 185, 71, 185, 185, 185, 111, 185, 185,
+ 185, 185, 185, 185, 185, 112, 185, 113, 148, 174,
+ 167, 185, 185, 185, 185, 120, 92, 74, 125, 0
+
+ } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 1, 2, 2, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 1, 4, 5, 1, 1, 1, 1, 6,
+ 6, 1, 6, 6, 7, 1, 8, 9, 10, 11,
+ 12, 13, 9, 9, 9, 14, 14, 1, 1, 1,
+ 1, 1, 1, 1, 15, 16, 17, 18, 19, 20,
+ 21, 1, 22, 1, 23, 24, 25, 26, 27, 28,
+ 1, 29, 30, 31, 32, 1, 1, 33, 1, 34,
+ 1, 35, 1, 1, 36, 1, 37, 38, 39, 40,
+
+ 41, 42, 43, 44, 45, 1, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+static yyconst flex_int32_t yy_meta[62] =
+ { 0,
+ 1, 2, 3, 4, 2, 2, 1, 5, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 7, 1, 6, 6, 6, 6,
+ 6, 6, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1
+ } ;
+
+static yyconst flex_int16_t yy_base[913] =
+ { 0,
+ 0, 0, 59, 61, 63, 64, 1012, 0, 66, 71,
+ 1013, 0, 1013, 1004, 1013, 63, 26, 961, 968, 971,
+ 960, 21, 969, 113, 164, 945, 40, 954, 29, 958,
+ 31, 961, 950, 959, 42, 958, 945, 0, 1013, 1013,
+ 209, 0, 1013, 1013, 260, 0, 87, 0, 990, 47,
+ 948, 956, 941, 51, 933, 954, 954, 937, 941, 945,
+ 93, 940, 945, 941, 43, 60, 947, 62, 946, 80,
+ 926, 925, 932, 132, 137, 934, 72, 927, 932, 935,
+ 136, 138, 151, 139, 151, 45, 156, 934, 69, 937,
+ 186, 917, 192, 157, 237, 193, 209, 199, 921, 163,
+
+ 173, 926, 929, 918, 917, 928, 925, 0, 911, 914,
+ 924, 922, 922, 907, 905, 0, 898, 190, 905, 228,
+ 896, 902, 909, 0, 1013, 283, 1013, 1013, 1013, 1013,
+ 1013, 1013, 1013, 1013, 1013, 0, 0, 1013, 294, 1013,
+ 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 0, 0,
+ 909, 897, 903, 900, 899, 907, 902, 888, 904, 899,
+ 898, 904, 276, 890, 885, 894, 891, 879, 882, 898,
+ 886, 0, 878, 881, 883, 888, 0, 0, 212, 884,
+ 0, 883, 0, 877, 883, 882, 868, 882, 155, 0,
+ 867, 267, 878, 869, 864, 871, 188, 867, 871, 862,
+
+ 858, 210, 862, 865, 218, 853, 859, 855, 852, 870,
+ 861, 855, 851, 855, 850, 864, 221, 845, 848, 167,
+ 857, 847, 268, 849, 0, 857, 842, 838, 0, 238,
+ 845, 846, 837, 836, 843, 0, 0, 266, 842, 272,
+ 845, 842, 837, 833, 839, 279, 844, 285, 824, 838,
+ 830, 840, 277, 823, 834, 834, 0, 0, 818, 818,
+ 827, 829, 0, 828, 814, 811, 0, 825, 811, 823,
+ 805, 809, 816, 804, 809, 804, 801, 809, 801, 799,
+ 330, 0, 335, 0, 816, 799, 810, 810, 796, 789,
+ 793, 796, 798, 795, 794, 792, 0, 0, 0, 0,
+
+ 797, 803, 0, 784, 789, 792, 0, 788, 798, 783,
+ 795, 777, 788, 791, 0, 0, 0, 785, 780, 0,
+ 772, 773, 780, 787, 772, 778, 774, 767, 782, 771,
+ 0, 764, 761, 0, 776, 776, 770, 752, 0, 756,
+ 762, 0, 760, 753, 762, 761, 0, 751, 751, 766,
+ 754, 0, 748, 745, 0, 762, 747, 759, 753, 750,
+ 739, 738, 0, 742, 744, 0, 755, 746, 749, 731,
+ 738, 730, 733, 0, 735, 286, 0, 737, 738, 735,
+ 734, 728, 0, 733, 728, 0, 735, 720, 729, 0,
+ 718, 731, 0, 275, 729, 729, 715, 722, 317, 0,
+
+ 723, 728, 0, 727, 709, 0, 721, 713, 709, 704,
+ 709, 707, 719, 705, 709, 704, 707, 710, 709, 704,
+ 693, 1013, 1013, 1013, 1013, 694, 701, 696, 699, 0,
+ 340, 698, 689, 705, 0, 697, 692, 701, 0, 700,
+ 699, 688, 697, 0, 696, 692, 203, 694, 677, 674,
+ 691, 690, 673, 678, 0, 680, 686, 681, 671, 0,
+ 679, 674, 0, 0, 664, 0, 664, 679, 665, 677,
+ 653, 665, 654, 655, 664, 661, 670, 651, 645, 0,
+ 667, 663, 655, 654, 646, 321, 649, 661, 280, 660,
+ 643, 641, 653, 648, 0, 651, 0, 636, 651, 642,
+
+ 641, 633, 636, 630, 647, 642, 641, 626, 639, 0,
+ 638, 641, 623, 635, 622, 627, 622, 622, 626, 310,
+ 629, 624, 316, 627, 0, 629, 611, 612, 623, 608,
+ 0, 608, 608, 605, 610, 605, 617, 601, 606, 0,
+ 604, 612, 0, 603, 596, 601, 0, 0, 0, 0,
+ 611, 608, 593, 0, 0, 0, 0, 593, 595, 0,
+ 0, 607, 590, 597, 0, 591, 603, 0, 0, 589,
+ 588, 0, 0, 0, 578, 581, 598, 578, 588, 0,
+ 583, 578, 576, 579, 0, 574, 578, 579, 0, 571,
+ 0, 0, 587, 582, 0, 0, 569, 576, 567, 0,
+
+ 570, 562, 0, 567, 0, 562, 578, 0, 564, 576,
+ 571, 0, 556, 557, 572, 0, 554, 552, 562, 550,
+ 562, 0, 0, 555, 552, 551, 546, 548, 561, 552,
+ 0, 553, 552, 553, 556, 0, 551, 541, 536, 540,
+ 543, 542, 546, 535, 547, 542, 0, 537, 542, 531,
+ 530, 535, 541, 533, 528, 538, 518, 519, 522, 0,
+ 517, 526, 519, 514, 508, 516, 0, 0, 521, 518,
+ 519, 521, 507, 518, 509, 0, 0, 0, 501, 0,
+ 0, 503, 512, 0, 0, 516, 504, 0, 505, 0,
+ 504, 0, 509, 0, 496, 492, 506, 509, 504, 494,
+
+ 506, 484, 492, 495, 479, 490, 0, 492, 488, 480,
+ 494, 478, 479, 0, 476, 480, 474, 474, 474, 479,
+ 471, 467, 482, 0, 0, 0, 468, 0, 480, 462,
+ 459, 460, 0, 453, 454, 0, 444, 0, 0, 449,
+ 27, 56, 136, 234, 244, 0, 284, 282, 291, 305,
+ 0, 0, 320, 309, 310, 319, 313, 311, 315, 320,
+ 322, 0, 0, 329, 324, 328, 325, 343, 344, 341,
+ 329, 330, 348, 337, 342, 0, 334, 0, 0, 348,
+ 336, 336, 0, 337, 343, 336, 337, 341, 347, 345,
+ 0, 344, 344, 343, 0, 347, 345, 349, 364, 347,
+
+ 0, 357, 353, 0, 0, 0, 368, 364, 361, 367,
+ 364, 359, 0, 0, 367, 0, 0, 361, 363, 361,
+ 0, 0, 0, 366, 367, 372, 0, 0, 385, 365,
+ 383, 0, 380, 0, 0, 0, 389, 372, 0, 370,
+ 0, 0, 0, 380, 387, 391, 391, 396, 389, 0,
+ 394, 386, 387, 395, 386, 0, 385, 386, 389, 0,
+ 0, 0, 399, 390, 392, 393, 397, 0, 399, 400,
+ 0, 397, 395, 0, 399, 398, 398, 0, 409, 407,
+ 414, 415, 409, 407, 411, 0, 417, 0, 0, 0,
+ 0, 405, 415, 407, 411, 0, 0, 0, 0, 1013,
+
+ 466, 473, 480, 487, 494, 500, 507, 513, 476, 477,
+ 478, 479
+ } ;
+
+static yyconst flex_int16_t yy_def[913] =
+ { 0,
+ 900, 1, 901, 901, 902, 902, 900, 903, 900, 900,
+ 900, 904, 900, 903, 900, 903, 903, 903, 903, 903,
+ 903, 903, 903, 900, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 905, 900, 900,
+ 906, 907, 900, 900, 908, 903, 900, 904, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 905, 900, 900, 900, 900, 900, 900,
+ 900, 900, 900, 900, 900, 909, 907, 900, 900, 900,
+ 900, 900, 900, 900, 900, 900, 900, 900, 910, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 900, 911, 900, 912, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 900, 900, 900, 900, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 903,
+ 903, 903, 903, 903, 903, 903, 903, 903, 903, 0,
+
+ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900,
+ 900, 900
+ } ;
+
+static yyconst flex_int16_t yy_nxt[1075] =
+ { 0,
+ 8, 9, 10, 11, 12, 13, 14, 15, 8, 8,
+ 8, 8, 8, 8, 8, 8, 16, 8, 17, 8,
+ 8, 18, 19, 20, 8, 8, 8, 21, 8, 22,
+ 23, 8, 8, 8, 24, 8, 25, 26, 27, 28,
+ 29, 30, 8, 8, 31, 32, 8, 8, 8, 33,
+ 8, 8, 34, 35, 8, 8, 36, 37, 8, 8,
+ 8, 39, 40, 39, 40, 43, 43, 47, 47, 50,
+ 44, 44, 47, 47, 52, 58, 109, 112, 53, 115,
+ 59, 791, 120, 167, 116, 151, 110, 113, 47, 47,
+ 156, 212, 168, 41, 213, 41, 121, 45, 45, 792,
+
+ 152, 61, 61, 61, 61, 61, 61, 157, 187, 172,
+ 169, 173, 51, 46, 170, 188, 175, 217, 218, 46,
+ 176, 61, 61, 61, 61, 61, 61, 62, 63, 64,
+ 65, 66, 46, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 46, 46, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+ 92, 93, 94, 95, 46, 96, 97, 98, 99, 100,
+ 101, 102, 46, 103, 104, 180, 181, 183, 195, 204,
+ 184, 185, 192, 205, 193, 182, 194, 197, 206, 793,
+ 198, 322, 214, 196, 199, 200, 215, 201, 207, 254,
+
+ 202, 208, 209, 255, 230, 210, 203, 231, 323, 211,
+ 105, 232, 106, 256, 358, 359, 107, 126, 126, 126,
+ 126, 126, 220, 257, 221, 222, 223, 224, 226, 240,
+ 272, 241, 227, 242, 243, 249, 244, 245, 331, 563,
+ 332, 228, 250, 251, 273, 127, 128, 229, 129, 130,
+ 131, 252, 313, 246, 341, 564, 314, 132, 337, 247,
+ 338, 133, 354, 134, 248, 135, 275, 136, 139, 139,
+ 139, 139, 139, 233, 342, 355, 276, 234, 368, 277,
+ 235, 236, 369, 794, 237, 297, 298, 299, 300, 238,
+ 239, 281, 281, 281, 281, 281, 140, 141, 795, 142,
+
+ 143, 144, 283, 283, 283, 283, 283, 325, 145, 362,
+ 375, 378, 146, 397, 147, 376, 148, 326, 149, 363,
+ 379, 385, 388, 389, 601, 497, 386, 511, 796, 512,
+ 398, 797, 390, 602, 798, 391, 498, 392, 422, 422,
+ 422, 422, 422, 424, 424, 424, 424, 424, 517, 547,
+ 548, 549, 550, 630, 631, 518, 519, 597, 799, 634,
+ 800, 801, 802, 803, 804, 805, 806, 520, 635, 521,
+ 522, 523, 807, 598, 808, 809, 810, 811, 812, 813,
+ 814, 815, 816, 817, 818, 819, 820, 821, 822, 823,
+ 824, 825, 826, 827, 828, 829, 830, 831, 832, 833,
+
+ 834, 835, 836, 837, 838, 839, 840, 841, 842, 843,
+ 844, 845, 846, 847, 848, 849, 850, 851, 852, 853,
+ 854, 855, 856, 857, 858, 859, 860, 861, 862, 863,
+ 864, 865, 866, 867, 868, 869, 870, 871, 872, 873,
+ 874, 875, 876, 877, 878, 879, 880, 881, 882, 883,
+ 884, 885, 886, 887, 888, 889, 890, 891, 892, 893,
+ 894, 895, 896, 897, 898, 899, 38, 38, 38, 38,
+ 38, 38, 38, 42, 42, 42, 42, 42, 42, 42,
+ 46, 282, 284, 423, 425, 46, 46, 48, 48, 790,
+ 48, 48, 48, 48, 124, 124, 789, 788, 124, 124,
+
+ 125, 125, 787, 125, 125, 125, 125, 137, 137, 786,
+ 137, 785, 137, 138, 138, 784, 138, 138, 138, 138,
+ 783, 782, 781, 780, 779, 778, 777, 776, 775, 774,
+ 773, 772, 771, 770, 769, 768, 767, 766, 765, 764,
+ 763, 762, 761, 760, 759, 758, 757, 756, 755, 754,
+ 753, 752, 751, 750, 749, 748, 747, 746, 745, 744,
+ 743, 742, 741, 740, 739, 738, 737, 736, 735, 734,
+ 733, 732, 731, 730, 729, 728, 727, 726, 725, 724,
+ 723, 722, 721, 720, 719, 718, 717, 716, 715, 714,
+ 713, 712, 711, 710, 709, 708, 707, 706, 705, 704,
+
+ 703, 702, 701, 700, 699, 698, 697, 696, 695, 694,
+ 693, 692, 691, 690, 689, 688, 687, 686, 685, 684,
+ 683, 682, 681, 680, 679, 678, 677, 676, 675, 674,
+ 673, 672, 671, 670, 669, 668, 667, 666, 665, 664,
+ 663, 662, 661, 660, 659, 658, 657, 656, 655, 654,
+ 653, 652, 651, 650, 649, 648, 647, 646, 645, 644,
+ 643, 642, 641, 640, 639, 638, 637, 636, 633, 632,
+ 629, 628, 627, 626, 625, 624, 623, 622, 621, 620,
+ 619, 618, 617, 616, 615, 614, 613, 612, 611, 610,
+ 609, 608, 607, 606, 605, 604, 603, 600, 599, 596,
+
+ 595, 594, 593, 592, 591, 590, 589, 588, 587, 586,
+ 585, 584, 583, 582, 581, 580, 579, 578, 577, 576,
+ 575, 574, 573, 572, 571, 570, 569, 568, 567, 566,
+ 565, 562, 561, 560, 559, 558, 557, 556, 555, 554,
+ 553, 552, 551, 546, 545, 544, 543, 542, 541, 540,
+ 539, 538, 537, 536, 535, 534, 533, 532, 531, 530,
+ 529, 528, 527, 526, 525, 524, 516, 515, 514, 513,
+ 510, 509, 508, 507, 506, 505, 504, 503, 502, 501,
+ 500, 499, 496, 495, 494, 493, 492, 491, 490, 489,
+ 488, 487, 486, 485, 484, 483, 482, 481, 480, 479,
+
+ 478, 477, 476, 475, 474, 473, 472, 471, 470, 469,
+ 468, 467, 466, 465, 464, 463, 462, 461, 460, 459,
+ 458, 457, 456, 455, 454, 453, 452, 451, 450, 449,
+ 448, 447, 446, 445, 444, 443, 442, 441, 440, 439,
+ 438, 437, 436, 435, 434, 433, 432, 431, 430, 429,
+ 428, 427, 426, 421, 420, 419, 418, 417, 416, 415,
+ 414, 413, 412, 411, 410, 409, 408, 407, 406, 405,
+ 404, 403, 402, 401, 400, 399, 396, 395, 394, 393,
+ 387, 384, 383, 382, 381, 380, 377, 374, 373, 372,
+ 371, 370, 367, 366, 365, 364, 361, 360, 357, 356,
+
+ 353, 352, 351, 350, 349, 348, 347, 346, 345, 344,
+ 343, 340, 339, 336, 335, 334, 333, 330, 329, 328,
+ 327, 324, 321, 320, 319, 318, 317, 316, 315, 312,
+ 311, 310, 309, 308, 307, 306, 305, 304, 303, 302,
+ 301, 296, 295, 294, 293, 292, 291, 290, 289, 288,
+ 287, 286, 285, 280, 279, 278, 274, 271, 270, 269,
+ 268, 267, 266, 265, 264, 263, 262, 261, 260, 259,
+ 258, 253, 225, 219, 216, 191, 190, 189, 186, 179,
+ 178, 177, 174, 171, 166, 165, 164, 163, 162, 161,
+ 160, 159, 158, 155, 154, 153, 150, 123, 122, 119,
+
+ 118, 117, 114, 111, 108, 60, 57, 56, 55, 54,
+ 49, 900, 7, 900, 900, 900, 900, 900, 900, 900,
+ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900,
+ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900,
+ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900,
+ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900,
+ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900,
+ 900, 900, 900, 900
+ } ;
+
+static yyconst flex_int16_t yy_chk[1075] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 3, 3, 4, 4, 5, 6, 9, 9, 16,
+ 5, 6, 10, 10, 17, 22, 27, 29, 17, 31,
+ 22, 741, 35, 65, 31, 50, 27, 29, 47, 47,
+ 54, 86, 65, 3, 86, 4, 35, 5, 6, 742,
+
+ 50, 61, 61, 61, 61, 61, 61, 54, 77, 68,
+ 66, 68, 16, 24, 66, 77, 70, 89, 89, 24,
+ 70, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 25, 74, 74, 75, 82, 84,
+ 75, 75, 81, 84, 81, 74, 81, 83, 84, 743,
+ 83, 189, 87, 82, 83, 83, 87, 83, 85, 100,
+
+ 83, 85, 85, 100, 94, 85, 83, 94, 189, 85,
+ 25, 94, 25, 101, 220, 220, 25, 41, 41, 41,
+ 41, 41, 91, 101, 91, 91, 91, 91, 93, 96,
+ 118, 96, 93, 96, 96, 98, 96, 96, 197, 447,
+ 197, 93, 98, 98, 118, 41, 41, 93, 41, 41,
+ 41, 98, 179, 97, 205, 447, 179, 41, 202, 97,
+ 202, 41, 217, 41, 97, 41, 120, 41, 45, 45,
+ 45, 45, 45, 95, 205, 217, 120, 95, 230, 120,
+ 95, 95, 230, 744, 95, 163, 163, 163, 163, 95,
+ 95, 126, 126, 126, 126, 126, 45, 45, 745, 45,
+
+ 45, 45, 139, 139, 139, 139, 139, 192, 45, 223,
+ 238, 240, 45, 253, 45, 238, 45, 192, 45, 223,
+ 240, 246, 248, 248, 489, 376, 246, 394, 747, 394,
+ 253, 748, 248, 489, 749, 248, 376, 248, 281, 281,
+ 281, 281, 281, 283, 283, 283, 283, 283, 399, 431,
+ 431, 431, 431, 520, 520, 399, 399, 486, 750, 523,
+ 753, 754, 755, 756, 757, 758, 759, 399, 523, 399,
+ 399, 399, 760, 486, 761, 764, 765, 766, 767, 768,
+ 769, 770, 771, 772, 773, 774, 775, 777, 780, 781,
+ 782, 784, 785, 786, 787, 788, 789, 790, 792, 793,
+
+ 794, 796, 797, 798, 799, 800, 802, 803, 807, 808,
+ 809, 810, 811, 812, 815, 818, 819, 820, 824, 825,
+ 826, 829, 830, 831, 833, 837, 838, 840, 844, 845,
+ 846, 847, 848, 849, 851, 852, 853, 854, 855, 857,
+ 858, 859, 863, 864, 865, 866, 867, 869, 870, 872,
+ 873, 875, 876, 877, 879, 880, 881, 882, 883, 884,
+ 885, 887, 892, 893, 894, 895, 901, 901, 901, 901,
+ 901, 901, 901, 902, 902, 902, 902, 902, 902, 902,
+ 903, 909, 910, 911, 912, 903, 903, 904, 904, 740,
+ 904, 904, 904, 904, 905, 905, 737, 735, 905, 905,
+
+ 906, 906, 734, 906, 906, 906, 906, 907, 907, 732,
+ 907, 731, 907, 908, 908, 730, 908, 908, 908, 908,
+ 729, 727, 723, 722, 721, 720, 719, 718, 717, 716,
+ 715, 713, 712, 711, 710, 709, 708, 706, 705, 704,
+ 703, 702, 701, 700, 699, 698, 697, 696, 695, 693,
+ 691, 689, 687, 686, 683, 682, 679, 675, 674, 673,
+ 672, 671, 670, 669, 666, 665, 664, 663, 662, 661,
+ 659, 658, 657, 656, 655, 654, 653, 652, 651, 650,
+ 649, 648, 646, 645, 644, 643, 642, 641, 640, 639,
+ 638, 637, 635, 634, 633, 632, 630, 629, 628, 627,
+
+ 626, 625, 624, 621, 620, 619, 618, 617, 615, 614,
+ 613, 611, 610, 609, 607, 606, 604, 602, 601, 599,
+ 598, 597, 594, 593, 590, 588, 587, 586, 584, 583,
+ 582, 581, 579, 578, 577, 576, 575, 571, 570, 567,
+ 566, 564, 563, 562, 559, 558, 553, 552, 551, 546,
+ 545, 544, 542, 541, 539, 538, 537, 536, 535, 534,
+ 533, 532, 530, 529, 528, 527, 526, 524, 522, 521,
+ 519, 518, 517, 516, 515, 514, 513, 512, 511, 509,
+ 508, 507, 506, 505, 504, 503, 502, 501, 500, 499,
+ 498, 496, 494, 493, 492, 491, 490, 488, 487, 485,
+
+ 484, 483, 482, 481, 479, 478, 477, 476, 475, 474,
+ 473, 472, 471, 470, 469, 468, 467, 465, 462, 461,
+ 459, 458, 457, 456, 454, 453, 452, 451, 450, 449,
+ 448, 446, 445, 443, 442, 441, 440, 438, 437, 436,
+ 434, 433, 432, 429, 428, 427, 426, 421, 420, 419,
+ 418, 417, 416, 415, 414, 413, 412, 411, 410, 409,
+ 408, 407, 405, 404, 402, 401, 398, 397, 396, 395,
+ 392, 391, 389, 388, 387, 385, 384, 382, 381, 380,
+ 379, 378, 375, 373, 372, 371, 370, 369, 368, 367,
+ 365, 364, 362, 361, 360, 359, 358, 357, 356, 354,
+
+ 353, 351, 350, 349, 348, 346, 345, 344, 343, 341,
+ 340, 338, 337, 336, 335, 333, 332, 330, 329, 328,
+ 327, 326, 325, 324, 323, 322, 321, 319, 318, 314,
+ 313, 312, 311, 310, 309, 308, 306, 305, 304, 302,
+ 301, 296, 295, 294, 293, 292, 291, 290, 289, 288,
+ 287, 286, 285, 280, 279, 278, 277, 276, 275, 274,
+ 273, 272, 271, 270, 269, 268, 266, 265, 264, 262,
+ 261, 260, 259, 256, 255, 254, 252, 251, 250, 249,
+ 247, 245, 244, 243, 242, 241, 239, 235, 234, 233,
+ 232, 231, 228, 227, 226, 224, 222, 221, 219, 218,
+
+ 216, 215, 214, 213, 212, 211, 210, 209, 208, 207,
+ 206, 204, 203, 201, 200, 199, 198, 196, 195, 194,
+ 193, 191, 188, 187, 186, 185, 184, 182, 180, 176,
+ 175, 174, 173, 171, 170, 169, 168, 167, 166, 165,
+ 164, 162, 161, 160, 159, 158, 157, 156, 155, 154,
+ 153, 152, 151, 123, 122, 121, 119, 117, 115, 114,
+ 113, 112, 111, 110, 109, 107, 106, 105, 104, 103,
+ 102, 99, 92, 90, 88, 80, 79, 78, 76, 73,
+ 72, 71, 69, 67, 64, 63, 62, 60, 59, 58,
+ 57, 56, 55, 53, 52, 51, 49, 37, 36, 34,
+
+ 33, 32, 30, 28, 26, 23, 21, 20, 19, 18,
+ 14, 7, 900, 900, 900, 900, 900, 900, 900, 900,
+ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900,
+ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900,
+ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900,
+ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900,
+ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900,
+ 900, 900, 900, 900
+ } ;
+
+/* Table of booleans, true if rule could match eol. */
+static yyconst flex_int32_t yy_rule_can_match_eol[218] =
+ { 0,
+0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, };
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+extern int ssh_flex_debug;
+int ssh_flex_debug = 0;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *sshtext;
+#line 1 "lexssh.l"
+#line 2 "lexssh.l"
+/*
+ * Lexer for a2ps.
+ *
+ * Copyright (c) 1988, 89, 90, 91, 92, 93 Miguel Santana
+ * Copyright (c) 1995, 96, 97, 98 Akim Demaille, Miguel Santana
+ *
+ */
+
+/*
+ * This file is part of a2ps.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * $Id: lexssh.l,v 1.1.1.1.2.1 2007/12/29 01:58:35 mhatta Exp $
+ */
+
+#include "main.h"
+#include "yy2ssh.h"
+#include "parsessh.h"
+#include "xobstack.h"
+#include "regex.h"
+
+/* Defines if the comments are printed or not */
+extern int strip_level;
+
+/* #define YY_DECL sshlex (YYSTYPE *lvalp);*/
+
+int sshlex PARAMS ((void));
+void yyerror PARAMS ((const char *));
+
+/* Initilizes the obstacks */
+void sshlex_initialize PARAMS ((void));
+
+/* Obstack for strings reading */
+static struct obstack string_stack;
+
+/* The file we scan. */
+const char * sshfilename;
+
+#define LATEX_SYM_RETURN(Str) \
+ yylval.string = (uchar *) xstrdup (Str) ; return tLATEXSYMBOL ;
+
+#define RETURN_FACE(_f_)\
+ {yylval.face = _f_ ; return tFACE ;}
+
+#define RETURN_FFLAGS(_f_)\
+ {yylval.fflags = _f_ ; return tFFLAGS ;}
+
+
+#line 1085 "lexssh.c"
+
+#define INITIAL 0
+#define STATE_STRING 1
+#define STATE_REGEXP 2
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals (void );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int sshwrap (void );
+#else
+extern int sshwrap (void );
+#endif
+#endif
+
+ static void yyunput (int c,char *buf_ptr );
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (void );
+#else
+static int input (void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( sshtext, sshleng, 1, sshout )
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+ { \
+ int c = '*'; \
+ size_t n; \
+ for ( n = 0; n < max_size && \
+ (c = getc( sshin )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+ if ( c == '\n' ) \
+ buf[n++] = (char) c; \
+ if ( c == EOF && ferror( sshin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ } \
+ else \
+ { \
+ errno=0; \
+ while ( (result = fread(buf, 1, max_size, sshin))==0 && ferror(sshin)) \
+ { \
+ if( errno != EINTR) \
+ { \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ break; \
+ } \
+ errno=0; \
+ clearerr(sshin); \
+ } \
+ }\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int sshlex (void);
+
+#define YY_DECL int sshlex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after sshtext and sshleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+ YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp, *yy_bp;
+ register int yy_act;
+
+#line 78 "lexssh.l"
+
+
+#line 1243 "lexssh.c"
+
+ if ( !(yy_init) )
+ {
+ (yy_init) = 1;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if ( ! (yy_start) )
+ (yy_start) = 1; /* first start state */
+
+ if ( ! sshin )
+ sshin = stdin;
+
+ if ( ! sshout )
+ sshout = stdout;
+
+ if ( ! YY_CURRENT_BUFFER ) {
+ sshensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ ssh_create_buffer(sshin,YY_BUF_SIZE );
+ }
+
+ ssh_load_buffer_state( );
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = (yy_c_buf_p);
+
+ /* Support of sshtext. */
+ *yy_cp = (yy_hold_char);
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = (yy_start);
+yy_match:
+ do
+ {
+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 901 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ ++yy_cp;
+ }
+ while ( yy_base[yy_current_state] != 1013 );
+
+yy_find_action:
+ yy_act = yy_accept[yy_current_state];
+ if ( yy_act == 0 )
+ { /* have to back up */
+ yy_cp = (yy_last_accepting_cpos);
+ yy_current_state = (yy_last_accepting_state);
+ yy_act = yy_accept[yy_current_state];
+ }
+
+ YY_DO_BEFORE_ACTION;
+
+ if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
+ {
+ int yyl;
+ for ( yyl = 0; yyl < sshleng; ++yyl )
+ if ( sshtext[yyl] == '\n' )
+
+ sshlineno++;
+;
+ }
+
+do_action: /* This label is used only to access EOF actions. */
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+ case 0: /* must back up */
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = (yy_hold_char);
+ yy_cp = (yy_last_accepting_cpos);
+ yy_current_state = (yy_last_accepting_state);
+ goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 80 "lexssh.l"
+{ ; }
+ YY_BREAK
+case 2:
+/* rule 2 can match eol */
+YY_RULE_SETUP
+#line 81 "lexssh.l"
+{ ; }
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 83 "lexssh.l"
+{ BEGIN STATE_STRING; }
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 84 "lexssh.l"
+{ BEGIN STATE_REGEXP; }
+ YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 86 "lexssh.l"
+LATEX_SYM_RETURN ("\042");
+ YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 87 "lexssh.l"
+LATEX_SYM_RETURN ("\044");
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 88 "lexssh.l"
+LATEX_SYM_RETURN ("\047");
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 89 "lexssh.l"
+LATEX_SYM_RETURN ("\100");
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 90 "lexssh.l"
+LATEX_SYM_RETURN ("\101");
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 91 "lexssh.l"
+LATEX_SYM_RETURN ("\102");
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 92 "lexssh.l"
+LATEX_SYM_RETURN ("\103");
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 93 "lexssh.l"
+LATEX_SYM_RETURN ("\104");
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 94 "lexssh.l"
+LATEX_SYM_RETURN ("\105");
+ YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 95 "lexssh.l"
+LATEX_SYM_RETURN ("\106");
+ YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 96 "lexssh.l"
+LATEX_SYM_RETURN ("\107");
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 97 "lexssh.l"
+LATEX_SYM_RETURN ("\110");
+ YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 98 "lexssh.l"
+LATEX_SYM_RETURN ("\111");
+ YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 99 "lexssh.l"
+LATEX_SYM_RETURN ("\112");
+ YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 100 "lexssh.l"
+LATEX_SYM_RETURN ("\113");
+ YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 101 "lexssh.l"
+LATEX_SYM_RETURN ("\114");
+ YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 102 "lexssh.l"
+LATEX_SYM_RETURN ("\115");
+ YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 103 "lexssh.l"
+LATEX_SYM_RETURN ("\116");
+ YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 104 "lexssh.l"
+LATEX_SYM_RETURN ("\117");
+ YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 105 "lexssh.l"
+LATEX_SYM_RETURN ("\120");
+ YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 106 "lexssh.l"
+LATEX_SYM_RETURN ("\121");
+ YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 107 "lexssh.l"
+LATEX_SYM_RETURN ("\122");
+ YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 108 "lexssh.l"
+LATEX_SYM_RETURN ("\123");
+ YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 109 "lexssh.l"
+LATEX_SYM_RETURN ("\124");
+ YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 110 "lexssh.l"
+LATEX_SYM_RETURN ("\125");
+ YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 111 "lexssh.l"
+LATEX_SYM_RETURN ("\126");
+ YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 112 "lexssh.l"
+LATEX_SYM_RETURN ("\127");
+ YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 113 "lexssh.l"
+LATEX_SYM_RETURN ("\130");
+ YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 114 "lexssh.l"
+LATEX_SYM_RETURN ("\131");
+ YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 115 "lexssh.l"
+LATEX_SYM_RETURN ("\132");
+ YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 116 "lexssh.l"
+LATEX_SYM_RETURN ("\134");
+ YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 117 "lexssh.l"
+LATEX_SYM_RETURN ("\136");
+ YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 118 "lexssh.l"
+LATEX_SYM_RETURN ("\140");
+ YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 119 "lexssh.l"
+LATEX_SYM_RETURN ("\141");
+ YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 120 "lexssh.l"
+LATEX_SYM_RETURN ("\142");
+ YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 121 "lexssh.l"
+LATEX_SYM_RETURN ("\143");
+ YY_BREAK
+case 41:
+YY_RULE_SETUP
+#line 122 "lexssh.l"
+LATEX_SYM_RETURN ("\144");
+ YY_BREAK
+case 42:
+YY_RULE_SETUP
+#line 123 "lexssh.l"
+LATEX_SYM_RETURN ("\145");
+ YY_BREAK
+case 43:
+YY_RULE_SETUP
+#line 124 "lexssh.l"
+LATEX_SYM_RETURN ("\146");
+ YY_BREAK
+case 44:
+YY_RULE_SETUP
+#line 125 "lexssh.l"
+LATEX_SYM_RETURN ("\147");
+ YY_BREAK
+case 45:
+YY_RULE_SETUP
+#line 126 "lexssh.l"
+LATEX_SYM_RETURN ("\150");
+ YY_BREAK
+case 46:
+YY_RULE_SETUP
+#line 127 "lexssh.l"
+LATEX_SYM_RETURN ("\151");
+ YY_BREAK
+case 47:
+YY_RULE_SETUP
+#line 128 "lexssh.l"
+LATEX_SYM_RETURN ("\152");
+ YY_BREAK
+case 48:
+YY_RULE_SETUP
+#line 129 "lexssh.l"
+LATEX_SYM_RETURN ("\153");
+ YY_BREAK
+case 49:
+YY_RULE_SETUP
+#line 130 "lexssh.l"
+LATEX_SYM_RETURN ("\154");
+ YY_BREAK
+case 50:
+YY_RULE_SETUP
+#line 131 "lexssh.l"
+LATEX_SYM_RETURN ("\155");
+ YY_BREAK
+case 51:
+YY_RULE_SETUP
+#line 132 "lexssh.l"
+LATEX_SYM_RETURN ("\156");
+ YY_BREAK
+case 52:
+YY_RULE_SETUP
+#line 133 "lexssh.l"
+LATEX_SYM_RETURN ("\157");
+ YY_BREAK
+case 53:
+YY_RULE_SETUP
+#line 134 "lexssh.l"
+LATEX_SYM_RETURN ("\160");
+ YY_BREAK
+case 54:
+YY_RULE_SETUP
+#line 135 "lexssh.l"
+LATEX_SYM_RETURN ("\161");
+ YY_BREAK
+case 55:
+YY_RULE_SETUP
+#line 136 "lexssh.l"
+LATEX_SYM_RETURN ("\162");
+ YY_BREAK
+case 56:
+YY_RULE_SETUP
+#line 137 "lexssh.l"
+LATEX_SYM_RETURN ("\163");
+ YY_BREAK
+case 57:
+YY_RULE_SETUP
+#line 138 "lexssh.l"
+LATEX_SYM_RETURN ("\164");
+ YY_BREAK
+case 58:
+YY_RULE_SETUP
+#line 139 "lexssh.l"
+LATEX_SYM_RETURN ("\165");
+ YY_BREAK
+case 59:
+YY_RULE_SETUP
+#line 140 "lexssh.l"
+LATEX_SYM_RETURN ("\166");
+ YY_BREAK
+case 60:
+YY_RULE_SETUP
+#line 141 "lexssh.l"
+LATEX_SYM_RETURN ("\167");
+ YY_BREAK
+case 61:
+YY_RULE_SETUP
+#line 142 "lexssh.l"
+LATEX_SYM_RETURN ("\170");
+ YY_BREAK
+case 62:
+YY_RULE_SETUP
+#line 143 "lexssh.l"
+LATEX_SYM_RETURN ("\171");
+ YY_BREAK
+case 63:
+YY_RULE_SETUP
+#line 144 "lexssh.l"
+LATEX_SYM_RETURN ("\172");
+ YY_BREAK
+case 64:
+YY_RULE_SETUP
+#line 145 "lexssh.l"
+LATEX_SYM_RETURN ("\176");
+ YY_BREAK
+case 65:
+YY_RULE_SETUP
+#line 146 "lexssh.l"
+LATEX_SYM_RETURN ("\241");
+ YY_BREAK
+case 66:
+YY_RULE_SETUP
+#line 147 "lexssh.l"
+LATEX_SYM_RETURN ("\242");
+ YY_BREAK
+case 67:
+YY_RULE_SETUP
+#line 148 "lexssh.l"
+LATEX_SYM_RETURN ("\243");
+ YY_BREAK
+case 68:
+YY_RULE_SETUP
+#line 149 "lexssh.l"
+LATEX_SYM_RETURN ("\245");
+ YY_BREAK
+case 69:
+YY_RULE_SETUP
+#line 150 "lexssh.l"
+LATEX_SYM_RETURN ("\246");
+ YY_BREAK
+case 70:
+YY_RULE_SETUP
+#line 151 "lexssh.l"
+LATEX_SYM_RETURN ("\247");
+ YY_BREAK
+case 71:
+YY_RULE_SETUP
+#line 152 "lexssh.l"
+LATEX_SYM_RETURN ("\250");
+ YY_BREAK
+case 72:
+YY_RULE_SETUP
+#line 153 "lexssh.l"
+LATEX_SYM_RETURN ("\251");
+ YY_BREAK
+case 73:
+YY_RULE_SETUP
+#line 154 "lexssh.l"
+LATEX_SYM_RETURN ("\252");
+ YY_BREAK
+case 74:
+YY_RULE_SETUP
+#line 155 "lexssh.l"
+LATEX_SYM_RETURN ("\253");
+ YY_BREAK
+case 75:
+YY_RULE_SETUP
+#line 156 "lexssh.l"
+LATEX_SYM_RETURN ("\254");
+ YY_BREAK
+case 76:
+YY_RULE_SETUP
+#line 157 "lexssh.l"
+LATEX_SYM_RETURN ("\255");
+ YY_BREAK
+case 77:
+YY_RULE_SETUP
+#line 158 "lexssh.l"
+LATEX_SYM_RETURN ("\256");
+ YY_BREAK
+case 78:
+YY_RULE_SETUP
+#line 159 "lexssh.l"
+LATEX_SYM_RETURN ("\257");
+ YY_BREAK
+case 79:
+YY_RULE_SETUP
+#line 160 "lexssh.l"
+LATEX_SYM_RETURN ("\260");
+ YY_BREAK
+case 80:
+YY_RULE_SETUP
+#line 161 "lexssh.l"
+LATEX_SYM_RETURN ("\261");
+ YY_BREAK
+case 81:
+YY_RULE_SETUP
+#line 162 "lexssh.l"
+LATEX_SYM_RETURN ("\263");
+ YY_BREAK
+case 82:
+YY_RULE_SETUP
+#line 163 "lexssh.l"
+LATEX_SYM_RETURN ("\264");
+ YY_BREAK
+case 83:
+YY_RULE_SETUP
+#line 164 "lexssh.l"
+LATEX_SYM_RETURN ("\265");
+ YY_BREAK
+case 84:
+YY_RULE_SETUP
+#line 165 "lexssh.l"
+LATEX_SYM_RETURN ("\266");
+ YY_BREAK
+case 85:
+YY_RULE_SETUP
+#line 166 "lexssh.l"
+LATEX_SYM_RETURN ("\267");
+ YY_BREAK
+case 86:
+YY_RULE_SETUP
+#line 167 "lexssh.l"
+LATEX_SYM_RETURN ("\270");
+ YY_BREAK
+case 87:
+YY_RULE_SETUP
+#line 168 "lexssh.l"
+LATEX_SYM_RETURN ("\271");
+ YY_BREAK
+case 88:
+YY_RULE_SETUP
+#line 169 "lexssh.l"
+LATEX_SYM_RETURN ("\272");
+ YY_BREAK
+case 89:
+YY_RULE_SETUP
+#line 170 "lexssh.l"
+LATEX_SYM_RETURN ("\273");
+ YY_BREAK
+case 90:
+YY_RULE_SETUP
+#line 171 "lexssh.l"
+LATEX_SYM_RETURN ("\274");
+ YY_BREAK
+case 91:
+YY_RULE_SETUP
+#line 172 "lexssh.l"
+LATEX_SYM_RETURN ("\276");
+ YY_BREAK
+case 92:
+YY_RULE_SETUP
+#line 173 "lexssh.l"
+LATEX_SYM_RETURN ("\277");
+ YY_BREAK
+case 93:
+YY_RULE_SETUP
+#line 174 "lexssh.l"
+LATEX_SYM_RETURN ("\300");
+ YY_BREAK
+case 94:
+YY_RULE_SETUP
+#line 175 "lexssh.l"
+LATEX_SYM_RETURN ("\301");
+ YY_BREAK
+case 95:
+YY_RULE_SETUP
+#line 176 "lexssh.l"
+LATEX_SYM_RETURN ("\302");
+ YY_BREAK
+case 96:
+YY_RULE_SETUP
+#line 177 "lexssh.l"
+LATEX_SYM_RETURN ("\303");
+ YY_BREAK
+case 97:
+YY_RULE_SETUP
+#line 178 "lexssh.l"
+LATEX_SYM_RETURN ("\304");
+ YY_BREAK
+case 98:
+YY_RULE_SETUP
+#line 179 "lexssh.l"
+LATEX_SYM_RETURN ("\305");
+ YY_BREAK
+case 99:
+YY_RULE_SETUP
+#line 180 "lexssh.l"
+LATEX_SYM_RETURN ("\306");
+ YY_BREAK
+case 100:
+YY_RULE_SETUP
+#line 181 "lexssh.l"
+LATEX_SYM_RETURN ("\307");
+ YY_BREAK
+case 101:
+YY_RULE_SETUP
+#line 182 "lexssh.l"
+LATEX_SYM_RETURN ("\310");
+ YY_BREAK
+case 102:
+YY_RULE_SETUP
+#line 183 "lexssh.l"
+LATEX_SYM_RETURN ("\311");
+ YY_BREAK
+case 103:
+YY_RULE_SETUP
+#line 184 "lexssh.l"
+LATEX_SYM_RETURN ("\312");
+ YY_BREAK
+case 104:
+YY_RULE_SETUP
+#line 185 "lexssh.l"
+LATEX_SYM_RETURN ("\313");
+ YY_BREAK
+case 105:
+YY_RULE_SETUP
+#line 186 "lexssh.l"
+LATEX_SYM_RETURN ("\314");
+ YY_BREAK
+case 106:
+YY_RULE_SETUP
+#line 187 "lexssh.l"
+LATEX_SYM_RETURN ("\315");
+ YY_BREAK
+case 107:
+YY_RULE_SETUP
+#line 188 "lexssh.l"
+LATEX_SYM_RETURN ("\316");
+ YY_BREAK
+case 108:
+YY_RULE_SETUP
+#line 189 "lexssh.l"
+LATEX_SYM_RETURN ("\317");
+ YY_BREAK
+case 109:
+YY_RULE_SETUP
+#line 190 "lexssh.l"
+LATEX_SYM_RETURN ("\320");
+ YY_BREAK
+case 110:
+YY_RULE_SETUP
+#line 191 "lexssh.l"
+LATEX_SYM_RETURN ("\321");
+ YY_BREAK
+case 111:
+YY_RULE_SETUP
+#line 192 "lexssh.l"
+LATEX_SYM_RETURN ("\322");
+ YY_BREAK
+case 112:
+YY_RULE_SETUP
+#line 193 "lexssh.l"
+LATEX_SYM_RETURN ("\324");
+ YY_BREAK
+case 113:
+YY_RULE_SETUP
+#line 194 "lexssh.l"
+LATEX_SYM_RETURN ("\324");
+ YY_BREAK
+case 114:
+YY_RULE_SETUP
+#line 195 "lexssh.l"
+LATEX_SYM_RETURN ("\325");
+ YY_BREAK
+case 115:
+YY_RULE_SETUP
+#line 196 "lexssh.l"
+LATEX_SYM_RETURN ("\326");
+ YY_BREAK
+case 116:
+YY_RULE_SETUP
+#line 197 "lexssh.l"
+LATEX_SYM_RETURN ("\327");
+ YY_BREAK
+case 117:
+YY_RULE_SETUP
+#line 198 "lexssh.l"
+LATEX_SYM_RETURN ("\330");
+ YY_BREAK
+case 118:
+YY_RULE_SETUP
+#line 199 "lexssh.l"
+LATEX_SYM_RETURN ("\331");
+ YY_BREAK
+case 119:
+YY_RULE_SETUP
+#line 200 "lexssh.l"
+LATEX_SYM_RETURN ("\332");
+ YY_BREAK
+case 120:
+YY_RULE_SETUP
+#line 201 "lexssh.l"
+LATEX_SYM_RETURN ("\333");
+ YY_BREAK
+case 121:
+YY_RULE_SETUP
+#line 202 "lexssh.l"
+LATEX_SYM_RETURN ("\334");
+ YY_BREAK
+case 122:
+YY_RULE_SETUP
+#line 203 "lexssh.l"
+LATEX_SYM_RETURN ("\335");
+ YY_BREAK
+case 123:
+YY_RULE_SETUP
+#line 204 "lexssh.l"
+LATEX_SYM_RETURN ("\336");
+ YY_BREAK
+case 124:
+YY_RULE_SETUP
+#line 205 "lexssh.l"
+LATEX_SYM_RETURN ("\337");
+ YY_BREAK
+case 125:
+YY_RULE_SETUP
+#line 206 "lexssh.l"
+LATEX_SYM_RETURN ("\340");
+ YY_BREAK
+case 126:
+YY_RULE_SETUP
+#line 207 "lexssh.l"
+LATEX_SYM_RETURN ("\341");
+ YY_BREAK
+case 127:
+YY_RULE_SETUP
+#line 208 "lexssh.l"
+LATEX_SYM_RETURN ("\342");
+ YY_BREAK
+case 128:
+YY_RULE_SETUP
+#line 209 "lexssh.l"
+LATEX_SYM_RETURN ("\342");
+ YY_BREAK
+case 129:
+YY_RULE_SETUP
+#line 210 "lexssh.l"
+LATEX_SYM_RETURN ("\344");
+ YY_BREAK
+case 130:
+YY_RULE_SETUP
+#line 211 "lexssh.l"
+LATEX_SYM_RETURN ("\345");
+ YY_BREAK
+case 131:
+YY_RULE_SETUP
+#line 212 "lexssh.l"
+LATEX_SYM_RETURN ("\351");
+ YY_BREAK
+case 132:
+YY_RULE_SETUP
+#line 213 "lexssh.l"
+LATEX_SYM_RETURN ("\353");
+ YY_BREAK
+case 133:
+YY_RULE_SETUP
+#line 214 "lexssh.l"
+LATEX_SYM_RETURN ("\361");
+ YY_BREAK
+case 134:
+YY_RULE_SETUP
+#line 215 "lexssh.l"
+LATEX_SYM_RETURN ("\362");
+ YY_BREAK
+case 135:
+YY_RULE_SETUP
+#line 216 "lexssh.l"
+LATEX_SYM_RETURN ("\371");
+ YY_BREAK
+case 136:
+YY_RULE_SETUP
+#line 217 "lexssh.l"
+LATEX_SYM_RETURN ("\373");
+ YY_BREAK
+case 137:
+YY_RULE_SETUP
+#line 219 "lexssh.l"
+{
+ int value = sshtext[1] - '0';
+ char *cursor = sshtext + 2;
+
+ while (*cursor)
+ value = 8 * value + *cursor++ - '0';
+ yylval.integer = value;
+ return tBACK_REF;
+}
+ YY_BREAK
+case 138:
+YY_RULE_SETUP
+#line 229 "lexssh.l"
+return tA2PS;
+ YY_BREAK
+case 139:
+YY_RULE_SETUP
+#line 230 "lexssh.l"
+return tALPHABET;
+ YY_BREAK
+case 140:
+YY_RULE_SETUP
+#line 231 "lexssh.l"
+return tALPHABETS;
+ YY_BREAK
+case 141:
+YY_RULE_SETUP
+#line 232 "lexssh.l"
+return tANCESTORS;
+ YY_BREAK
+case 142:
+YY_RULE_SETUP
+#line 233 "lexssh.l"
+return tARE;
+ YY_BREAK
+case 143:
+YY_RULE_SETUP
+#line 234 "lexssh.l"
+return tBY;
+ YY_BREAK
+case 144:
+YY_RULE_SETUP
+#line 235 "lexssh.l"
+return tCASE;
+ YY_BREAK
+case 145:
+YY_RULE_SETUP
+#line 236 "lexssh.l"
+return tCLOSERS;
+ YY_BREAK
+case 146:
+YY_RULE_SETUP
+#line 237 "lexssh.l"
+return tCCHAR;
+ YY_BREAK
+case 147:
+YY_RULE_SETUP
+#line 238 "lexssh.l"
+return tCSTRING;
+ YY_BREAK
+case 148:
+YY_RULE_SETUP
+#line 239 "lexssh.l"
+return tDOCUMENTATION;
+ YY_BREAK
+case 149:
+YY_RULE_SETUP
+#line 240 "lexssh.l"
+return tEND;
+ YY_BREAK
+case 150:
+YY_RULE_SETUP
+#line 241 "lexssh.l"
+return tEXCEPTIONS;
+ YY_BREAK
+case 151:
+YY_RULE_SETUP
+#line 242 "lexssh.l"
+return tFIRST;
+ YY_BREAK
+case 152:
+YY_RULE_SETUP
+#line 243 "lexssh.l"
+return tIN;
+ YY_BREAK
+case 153:
+YY_RULE_SETUP
+#line 244 "lexssh.l"
+{ yylval.sensitiveness = case_insensitive ;
+ return tSENSITIVENESS;
+ }
+ YY_BREAK
+case 154:
+YY_RULE_SETUP
+#line 247 "lexssh.l"
+return tIS;
+ YY_BREAK
+case 155:
+YY_RULE_SETUP
+#line 248 "lexssh.l"
+return tKEYWORDS;
+ YY_BREAK
+case 156:
+YY_RULE_SETUP
+#line 249 "lexssh.l"
+return tREQUIRES;
+ YY_BREAK
+case 157:
+YY_RULE_SETUP
+#line 250 "lexssh.l"
+return tSECOND;
+ YY_BREAK
+case 158:
+YY_RULE_SETUP
+#line 251 "lexssh.l"
+{ yylval.sensitiveness = case_sensitive ;
+ return tSENSITIVENESS;
+ }
+ YY_BREAK
+case 159:
+YY_RULE_SETUP
+#line 254 "lexssh.l"
+return tOPERATORS;
+ YY_BREAK
+case 160:
+YY_RULE_SETUP
+#line 255 "lexssh.l"
+return tOPTIONAL;
+ YY_BREAK
+case 161:
+YY_RULE_SETUP
+#line 256 "lexssh.l"
+return tSEQUENCES;
+ YY_BREAK
+case 162:
+YY_RULE_SETUP
+#line 257 "lexssh.l"
+return tSTYLE;
+ YY_BREAK
+case 163:
+YY_RULE_SETUP
+#line 258 "lexssh.l"
+return tVERSION;
+ YY_BREAK
+case 164:
+YY_RULE_SETUP
+#line 259 "lexssh.l"
+return tWRITTEN;
+ YY_BREAK
+case 165:
+YY_RULE_SETUP
+#line 261 "lexssh.l"
+RETURN_FACE (Plain)
+ YY_BREAK
+case 166:
+YY_RULE_SETUP
+#line 262 "lexssh.l"
+RETURN_FACE (Keyword)
+ YY_BREAK
+case 167:
+YY_RULE_SETUP
+#line 263 "lexssh.l"
+RETURN_FACE (Keyword_strong)
+ YY_BREAK
+case 168:
+YY_RULE_SETUP
+#line 264 "lexssh.l"
+RETURN_FACE (Error)
+ YY_BREAK
+case 169:
+YY_RULE_SETUP
+#line 265 "lexssh.l"
+RETURN_FACE (Label)
+ YY_BREAK
+case 170:
+YY_RULE_SETUP
+#line 266 "lexssh.l"
+RETURN_FACE (Label_strong)
+ YY_BREAK
+case 171:
+YY_RULE_SETUP
+#line 267 "lexssh.l"
+RETURN_FACE (String)
+ YY_BREAK
+case 172:
+YY_RULE_SETUP
+#line 268 "lexssh.l"
+RETURN_FACE (Symbol)
+ YY_BREAK
+case 173:
+YY_RULE_SETUP
+#line 269 "lexssh.l"
+{ /* Strip if required */
+ if ((strip_level == 1) || (strip_level == 3))
+ RETURN_FFLAGS (ff_Invisible)
+ else
+ RETURN_FACE (Comment)
+ }
+ YY_BREAK
+case 174:
+YY_RULE_SETUP
+#line 275 "lexssh.l"
+{ /* Strip if required */
+ if ((strip_level == 2) || (strip_level == 3))
+ RETURN_FFLAGS (ff_Invisible)
+ else
+ RETURN_FACE (Comment_strong)
+ }
+ YY_BREAK
+case 175:
+YY_RULE_SETUP
+#line 282 "lexssh.l"
+RETURN_FFLAGS (ff_Tag1)
+ YY_BREAK
+case 176:
+YY_RULE_SETUP
+#line 283 "lexssh.l"
+RETURN_FFLAGS (ff_Tag2)
+ YY_BREAK
+case 177:
+YY_RULE_SETUP
+#line 284 "lexssh.l"
+RETURN_FFLAGS (ff_Tag3)
+ YY_BREAK
+case 178:
+YY_RULE_SETUP
+#line 285 "lexssh.l"
+RETURN_FFLAGS (ff_Tag4)
+ YY_BREAK
+case 179:
+YY_RULE_SETUP
+#line 286 "lexssh.l"
+RETURN_FFLAGS (ff_Index1)
+ YY_BREAK
+case 180:
+YY_RULE_SETUP
+#line 287 "lexssh.l"
+RETURN_FFLAGS (ff_Index2)
+ YY_BREAK
+case 181:
+YY_RULE_SETUP
+#line 288 "lexssh.l"
+RETURN_FFLAGS (ff_Index3)
+ YY_BREAK
+case 182:
+YY_RULE_SETUP
+#line 289 "lexssh.l"
+RETURN_FFLAGS (ff_Index4)
+ YY_BREAK
+case 183:
+YY_RULE_SETUP
+#line 290 "lexssh.l"
+RETURN_FFLAGS (ff_Encoding)
+ YY_BREAK
+case 184:
+YY_RULE_SETUP
+#line 291 "lexssh.l"
+RETURN_FFLAGS (ff_Invisible)
+ YY_BREAK
+case 185:
+YY_RULE_SETUP
+#line 293 "lexssh.l"
+{ yylval.string = xustrdup (sshtext);
+ return tSTRING;
+ }
+ YY_BREAK
+case 186:
+YY_RULE_SETUP
+#line 297 "lexssh.l"
+{ return sshtext[0]; }
+ YY_BREAK
+/* string of characters */
+case 187:
+YY_RULE_SETUP
+#line 300 "lexssh.l"
+{ /* return the string */
+ uchar * string;
+
+ obstack_1grow (&string_stack, '\0');
+ string = (uchar *) obstack_finish (&string_stack);
+
+ obstack_free (&string_stack, string);
+
+ BEGIN INITIAL; /* Return to the regular scanning */
+ yylval.string = xustrdup (string);
+ return tSTRING;
+ }
+ YY_BREAK
+case 188:
+YY_RULE_SETUP
+#line 313 "lexssh.l"
+{
+ int value = sshtext[1] - '0';
+ char *cursor = sshtext + 2;
+
+ while (*cursor)
+ value = 8 * value + *cursor++ - '0';
+ obstack_1grow (&string_stack, value);
+ }
+ YY_BREAK
+case 189:
+YY_RULE_SETUP
+#line 322 "lexssh.l"
+{
+ int value = 0;
+ char *cursor = sshtext + 2;
+
+ while (*cursor)
+ if (*cursor >= 'a' && *cursor <= 'f')
+ value = 16 * value + *cursor++ - 'a' + 10;
+ else if (*cursor >= 'A' && *cursor <= 'F')
+ value = 16 * value + *cursor++ - 'A' + 10;
+ else
+ value = 16 * value + *cursor++ - '0';
+ obstack_1grow (&string_stack, value);
+ }
+ YY_BREAK
+case 190:
+YY_RULE_SETUP
+#line 336 "lexssh.l"
+{ obstack_1grow (&string_stack, '\007'); }
+ YY_BREAK
+case 191:
+YY_RULE_SETUP
+#line 337 "lexssh.l"
+{ obstack_1grow (&string_stack, '\b'); }
+ YY_BREAK
+case 192:
+YY_RULE_SETUP
+#line 338 "lexssh.l"
+{ obstack_1grow (&string_stack, 127); }
+ YY_BREAK
+case 193:
+YY_RULE_SETUP
+#line 339 "lexssh.l"
+{ obstack_1grow (&string_stack, 27); }
+ YY_BREAK
+case 194:
+YY_RULE_SETUP
+#line 340 "lexssh.l"
+{ obstack_1grow (&string_stack, '\f'); }
+ YY_BREAK
+case 195:
+YY_RULE_SETUP
+#line 341 "lexssh.l"
+{ obstack_1grow (&string_stack, '\n'); }
+ YY_BREAK
+case 196:
+YY_RULE_SETUP
+#line 342 "lexssh.l"
+{ obstack_1grow (&string_stack, '\r'); }
+ YY_BREAK
+case 197:
+YY_RULE_SETUP
+#line 343 "lexssh.l"
+{ obstack_1grow (&string_stack, '\t'); }
+ YY_BREAK
+case 198:
+YY_RULE_SETUP
+#line 344 "lexssh.l"
+{ obstack_1grow (&string_stack, '\v'); }
+ YY_BREAK
+case 199:
+YY_RULE_SETUP
+#line 345 "lexssh.l"
+{ obstack_1grow (&string_stack, sshtext[1]); }
+ YY_BREAK
+case 200:
+/* rule 200 can match eol */
+YY_RULE_SETUP
+#line 347 "lexssh.l"
+{
+ yyerror (_("end-of-line in string constant"));
+ }
+ YY_BREAK
+case 201:
+YY_RULE_SETUP
+#line 351 "lexssh.l"
+{
+ obstack_grow (&string_stack, sshtext, sshleng);
+ }
+ YY_BREAK
+
+/* a regular expression */
+case 202:
+YY_RULE_SETUP
+#line 357 "lexssh.l"
+{ /* return the string */
+ char * pattern;
+ int pattern_len;
+
+ /* I'm not sure I got the 0 terminate the pattern */
+ obstack_1grow (&string_stack, '\0');
+ pattern_len = obstack_object_size (&string_stack);
+ pattern = (char *) obstack_finish (&string_stack);
+ obstack_free (&string_stack, pattern);
+
+ yylval.pattern = XMALLOC (struct pattern, 1);
+ /* len - 1, because the NUL must not be part of the pattern that
+ * will be compiled. We put tough, to be able to use the pattern
+ * in regular C strings manipulations. */
+ yylval.pattern->len = pattern_len - 1;
+ yylval.pattern->pattern = XMALLOC (char, pattern_len);
+ memcpy (yylval.pattern->pattern, pattern, pattern_len);
+
+ BEGIN INITIAL; /* Return to the regular scanning */
+ return tREGEX;
+ }
+ YY_BREAK
+case 203:
+YY_RULE_SETUP
+#line 379 "lexssh.l"
+{
+ int value = sshtext[1] - '0';
+ char *cursor = sshtext + 2;
+
+ while (*cursor)
+ value = 8 * value + *cursor++ - '0';
+ obstack_1grow (&string_stack, value);
+ }
+ YY_BREAK
+case 204:
+YY_RULE_SETUP
+#line 388 "lexssh.l"
+{
+ int value = 0;
+ char *cursor = sshtext + 2;
+
+ while (*cursor)
+ if (*cursor >= 'a' && *cursor <= 'f')
+ value = 16 * value + *cursor++ - 'a' + 10;
+ else if (*cursor >= 'A' && *cursor <= 'F')
+ value = 16 * value + *cursor++ - 'A' + 10;
+ else
+ value = 16 * value + *cursor++ - '0';
+ obstack_1grow (&string_stack, value);
+ }
+ YY_BREAK
+case 205:
+YY_RULE_SETUP
+#line 402 "lexssh.l"
+{ obstack_1grow (&string_stack, '\007'); }
+ YY_BREAK
+case 206:
+YY_RULE_SETUP
+#line 403 "lexssh.l"
+{ obstack_1grow (&string_stack, '\b'); }
+ YY_BREAK
+case 207:
+YY_RULE_SETUP
+#line 404 "lexssh.l"
+{ obstack_1grow (&string_stack, 127); }
+ YY_BREAK
+case 208:
+YY_RULE_SETUP
+#line 405 "lexssh.l"
+{ obstack_1grow (&string_stack, 27); }
+ YY_BREAK
+case 209:
+YY_RULE_SETUP
+#line 406 "lexssh.l"
+{ obstack_1grow (&string_stack, '\f'); }
+ YY_BREAK
+case 210:
+YY_RULE_SETUP
+#line 407 "lexssh.l"
+{ obstack_1grow (&string_stack, '\n'); }
+ YY_BREAK
+case 211:
+YY_RULE_SETUP
+#line 408 "lexssh.l"
+{ obstack_1grow (&string_stack, '\r'); }
+ YY_BREAK
+case 212:
+YY_RULE_SETUP
+#line 409 "lexssh.l"
+{ obstack_1grow (&string_stack, '\t'); }
+ YY_BREAK
+case 213:
+YY_RULE_SETUP
+#line 410 "lexssh.l"
+{ obstack_1grow (&string_stack, '\v'); }
+ YY_BREAK
+case 214:
+YY_RULE_SETUP
+#line 411 "lexssh.l"
+{ obstack_1grow (&string_stack, sshtext[1]); }
+ YY_BREAK
+case 215:
+/* rule 215 can match eol */
+YY_RULE_SETUP
+#line 413 "lexssh.l"
+{
+ error_at_line (1, 0, sshfilename, sshlineno,
+ _("end of line inside a %s"), "\"..\"");
+ }
+ YY_BREAK
+case 216:
+YY_RULE_SETUP
+#line 418 "lexssh.l"
+{
+ obstack_grow (&string_stack, sshtext, sshleng);
+ }
+ YY_BREAK
+
+case 217:
+YY_RULE_SETUP
+#line 423 "lexssh.l"
+ECHO;
+ YY_BREAK
+#line 2530 "lexssh.c"
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(STATE_STRING):
+case YY_STATE_EOF(STATE_REGEXP):
+ yyterminate();
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = (yy_hold_char);
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed sshin at a new source and called
+ * sshlex(). If so, then we have to assure
+ * consistency between YY_CURRENT_BUFFER and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ YY_CURRENT_BUFFER_LVALUE->yy_input_file = sshin;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( );
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++(yy_c_buf_p);
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = (yy_c_buf_p);
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer( ) )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ (yy_did_buffer_switch_on_eof) = 0;
+
+ if ( sshwrap( ) )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * sshtext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! (yy_did_buffer_switch_on_eof) )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ (yy_c_buf_p) =
+ (yytext_ptr) + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( );
+
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ (yy_c_buf_p) =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+ yy_current_state = yy_get_previous_state( );
+
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+} /* end of sshlex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (void)
+{
+ register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ register char *source = (yytext_ptr);
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+ else
+ {
+ int num_to_read =
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+ int yy_c_buf_p_offset =
+ (int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+ int new_size = b->yy_buf_size * 2;
+
+ if ( new_size <= 0 )
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ sshrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = 0;
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+ (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+ number_to_move - 1;
+
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+ (yy_n_chars), (size_t) num_to_read );
+
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ if ( (yy_n_chars) == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ sshrestart(sshin );
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ (yy_n_chars) += number_to_move;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+ (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+ return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+ static yy_state_type yy_get_previous_state (void)
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+
+ yy_current_state = (yy_start);
+
+ for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+ {
+ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 901 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ }
+
+ return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state )
+{
+ register int yy_is_jam;
+ register char *yy_cp = (yy_c_buf_p);
+
+ register YY_CHAR yy_c = 1;
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 901 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_is_jam = (yy_current_state == 900);
+
+ return yy_is_jam ? 0 : yy_current_state;
+}
+
+ static void yyunput (int c, register char * yy_bp )
+{
+ register char *yy_cp;
+
+ yy_cp = (yy_c_buf_p);
+
+ /* undo effects of setting up sshtext */
+ *yy_cp = (yy_hold_char);
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ { /* need to shift things up to make room */
+ /* +2 for EOB chars. */
+ register int number_to_move = (yy_n_chars) + 2;
+ register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+ register char *source =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+ while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ *--dest = *--source;
+
+ yy_cp += (int) (dest - source);
+ yy_bp += (int) (dest - source);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ YY_FATAL_ERROR( "flex scanner push-back overflow" );
+ }
+
+ *--yy_cp = (char) c;
+
+ if ( c == '\n' ){
+ --sshlineno;
+ }
+
+ (yytext_ptr) = yy_bp;
+ (yy_hold_char) = *yy_cp;
+ (yy_c_buf_p) = yy_cp;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+ static int yyinput (void)
+#else
+ static int input (void)
+#endif
+
+{
+ int c;
+
+ *(yy_c_buf_p) = (yy_hold_char);
+
+ if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+ /* This was really a NUL. */
+ *(yy_c_buf_p) = '\0';
+
+ else
+ { /* need more input */
+ int offset = (yy_c_buf_p) - (yytext_ptr);
+ ++(yy_c_buf_p);
+
+ switch ( yy_get_next_buffer( ) )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ sshrestart(sshin );
+
+ /*FALLTHROUGH*/
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( sshwrap( ) )
+ return EOF;
+
+ if ( ! (yy_did_buffer_switch_on_eof) )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput();
+#else
+ return input();
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ (yy_c_buf_p) = (yytext_ptr) + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */
+ *(yy_c_buf_p) = '\0'; /* preserve sshtext */
+ (yy_hold_char) = *++(yy_c_buf_p);
+
+ if ( c == '\n' )
+
+ sshlineno++;
+;
+
+ return c;
+}
+#endif /* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ *
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+ void sshrestart (FILE * input_file )
+{
+
+ if ( ! YY_CURRENT_BUFFER ){
+ sshensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ ssh_create_buffer(sshin,YY_BUF_SIZE );
+ }
+
+ ssh_init_buffer(YY_CURRENT_BUFFER,input_file );
+ ssh_load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ *
+ */
+ void ssh_switch_to_buffer (YY_BUFFER_STATE new_buffer )
+{
+
+ /* TODO. We should be able to replace this entire function body
+ * with
+ * sshpop_buffer_state();
+ * sshpush_buffer_state(new_buffer);
+ */
+ sshensure_buffer_stack ();
+ if ( YY_CURRENT_BUFFER == new_buffer )
+ return;
+
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+ ssh_load_buffer_state( );
+
+ /* We don't actually know whether we did this switch during
+ * EOF (sshwrap()) processing, but the only time this flag
+ * is looked at is after sshwrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void ssh_load_buffer_state (void)
+{
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+ sshin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+ (yy_hold_char) = *(yy_c_buf_p);
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ *
+ * @return the allocated buffer state.
+ */
+ YY_BUFFER_STATE ssh_create_buffer (FILE * file, int size )
+{
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) sshalloc(sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in ssh_create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) sshalloc(b->yy_buf_size + 2 );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in ssh_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ ssh_init_buffer(b,file );
+
+ return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with ssh_create_buffer()
+ *
+ */
+ void ssh_delete_buffer (YY_BUFFER_STATE b )
+{
+
+ if ( ! b )
+ return;
+
+ if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ sshfree((void *) b->yy_ch_buf );
+
+ sshfree((void *) b );
+}
+
+#ifndef __cplusplus
+extern int isatty (int );
+#endif /* __cplusplus */
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a sshrestart() or at EOF.
+ */
+ static void ssh_init_buffer (YY_BUFFER_STATE b, FILE * file )
+
+{
+ int oerrno = errno;
+
+ ssh_flush_buffer(b );
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+ /* If b is the current buffer, then ssh_init_buffer was _probably_
+ * called from sshrestart() or through yy_get_next_buffer.
+ * In that case, we don't want to reset the lineno or column.
+ */
+ if (b != YY_CURRENT_BUFFER){
+ b->yy_bs_lineno = 1;
+ b->yy_bs_column = 0;
+ }
+
+ b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+
+ errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ *
+ */
+ void ssh_flush_buffer (YY_BUFFER_STATE b )
+{
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == YY_CURRENT_BUFFER )
+ ssh_load_buffer_state( );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ * the current state. This function will allocate the stack
+ * if necessary.
+ * @param new_buffer The new state.
+ *
+ */
+void sshpush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+ if (new_buffer == NULL)
+ return;
+
+ sshensure_buffer_stack();
+
+ /* This block is copied from ssh_switch_to_buffer. */
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ /* Only push if top exists. Otherwise, replace top. */
+ if (YY_CURRENT_BUFFER)
+ (yy_buffer_stack_top)++;
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+ /* copied from ssh_switch_to_buffer. */
+ ssh_load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ * The next element becomes the new top.
+ *
+ */
+void sshpop_buffer_state (void)
+{
+ if (!YY_CURRENT_BUFFER)
+ return;
+
+ ssh_delete_buffer(YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ if ((yy_buffer_stack_top) > 0)
+ --(yy_buffer_stack_top);
+
+ if (YY_CURRENT_BUFFER) {
+ ssh_load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
+ }
+}
+
+/* Allocates the stack if it does not exist.
+ * Guarantees space for at least one push.
+ */
+static void sshensure_buffer_stack (void)
+{
+ int num_to_alloc;
+
+ if (!(yy_buffer_stack)) {
+
+ /* First allocation is just for 2 elements, since we don't know if this
+ * scanner will even need a stack. We use 2 instead of 1 to avoid an
+ * immediate realloc on the next call.
+ */
+ num_to_alloc = 1;
+ (yy_buffer_stack) = (struct yy_buffer_state**)sshalloc
+ (num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+
+ memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+
+ (yy_buffer_stack_max) = num_to_alloc;
+ (yy_buffer_stack_top) = 0;
+ return;
+ }
+
+ if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+ /* Increase the buffer to prepare for a possible push. */
+ int grow_size = 8 /* arbitrary grow size */;
+
+ num_to_alloc = (yy_buffer_stack_max) + grow_size;
+ (yy_buffer_stack) = (struct yy_buffer_state**)sshrealloc
+ ((yy_buffer_stack),
+ num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+
+ /* zero only the new slots.*/
+ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+ (yy_buffer_stack_max) = num_to_alloc;
+ }
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE ssh_scan_buffer (char * base, yy_size_t size )
+{
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE) sshalloc(sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in ssh_scan_buffer()" );
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ ssh_switch_to_buffer(b );
+
+ return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to sshlex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ *
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ * ssh_scan_bytes() instead.
+ */
+YY_BUFFER_STATE ssh_scan_string (yyconst char * yystr )
+{
+
+ return ssh_scan_bytes(yystr,strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to sshlex() will
+ * scan from a @e copy of @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE ssh_scan_bytes (yyconst char * yybytes, int _yybytes_len )
+{
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = _yybytes_len + 2;
+ buf = (char *) sshalloc(n );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in ssh_scan_bytes()" );
+
+ for ( i = 0; i < _yybytes_len; ++i )
+ buf[i] = yybytes[i];
+
+ buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = ssh_scan_buffer(buf,n );
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in ssh_scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg )
+{
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up sshtext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ sshtext[sshleng] = (yy_hold_char); \
+ (yy_c_buf_p) = sshtext + yyless_macro_arg; \
+ (yy_hold_char) = *(yy_c_buf_p); \
+ *(yy_c_buf_p) = '\0'; \
+ sshleng = yyless_macro_arg; \
+ } \
+ while ( 0 )
+
+/* Accessor methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ *
+ */
+int sshget_lineno (void)
+{
+
+ return sshlineno;
+}
+
+/** Get the input stream.
+ *
+ */
+FILE *sshget_in (void)
+{
+ return sshin;
+}
+
+/** Get the output stream.
+ *
+ */
+FILE *sshget_out (void)
+{
+ return sshout;
+}
+
+/** Get the length of the current token.
+ *
+ */
+int sshget_leng (void)
+{
+ return sshleng;
+}
+
+/** Get the current token.
+ *
+ */
+
+char *sshget_text (void)
+{
+ return sshtext;
+}
+
+/** Set the current line number.
+ * @param line_number
+ *
+ */
+void sshset_lineno (int line_number )
+{
+
+ sshlineno = line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ *
+ * @see ssh_switch_to_buffer
+ */
+void sshset_in (FILE * in_str )
+{
+ sshin = in_str ;
+}
+
+void sshset_out (FILE * out_str )
+{
+ sshout = out_str ;
+}
+
+int sshget_debug (void)
+{
+ return ssh_flex_debug;
+}
+
+void sshset_debug (int bdebug )
+{
+ ssh_flex_debug = bdebug ;
+}
+
+static int yy_init_globals (void)
+{
+ /* Initialization is the same as for the non-reentrant scanner.
+ * This function is called from sshlex_destroy(), so don't allocate here.
+ */
+
+ /* We do not touch sshlineno unless the option is enabled. */
+ sshlineno = 1;
+
+ (yy_buffer_stack) = 0;
+ (yy_buffer_stack_top) = 0;
+ (yy_buffer_stack_max) = 0;
+ (yy_c_buf_p) = (char *) 0;
+ (yy_init) = 0;
+ (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+ sshin = stdin;
+ sshout = stdout;
+#else
+ sshin = (FILE *) 0;
+ sshout = (FILE *) 0;
+#endif
+
+ /* For future reference: Set errno on error, since we are called by
+ * sshlex_init()
+ */
+ return 0;
+}
+
+/* sshlex_destroy is for both reentrant and non-reentrant scanners. */
+int sshlex_destroy (void)
+{
+
+ /* Pop the buffer stack, destroying each element. */
+ while(YY_CURRENT_BUFFER){
+ ssh_delete_buffer(YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ sshpop_buffer_state();
+ }
+
+ /* Destroy the stack itself. */
+ sshfree((yy_buffer_stack) );
+ (yy_buffer_stack) = NULL;
+
+ /* Reset the globals. This is important in a non-reentrant scanner so the next time
+ * sshlex() is called, initialization will occur. */
+ yy_init_globals( );
+
+ return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+ register int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+ register int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+}
+#endif
+
+void *sshalloc (yy_size_t size )
+{
+ return (void *) malloc( size );
+}
+
+void *sshrealloc (void * ptr, yy_size_t size )
+{
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+}
+
+void sshfree (void * ptr )
+{
+ free( (char *) ptr ); /* see sshrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 423 "lexssh.l"
+
+
+
+int
+sshwrap (void)
+{
+ return 1;
+}
+
+/*
+ * Initialize the obstacks
+ */
+void
+sshlex_initialize (void)
+{
+ static int first_time = 1;
+ if (first_time)
+ {
+ first_time = 0;
+ obstack_init (&string_stack);
+ }
+}
+
diff --git a/src/lexssh.l b/src/lexssh.l
new file mode 100644
index 0000000..947b729
--- /dev/null
+++ b/src/lexssh.l
@@ -0,0 +1,443 @@
+%{ /* -*- c -*- */
+/*
+ * Lexer for a2ps.
+ *
+ * Copyright (c) 1988, 89, 90, 91, 92, 93 Miguel Santana
+ * Copyright (c) 1995, 96, 97, 98 Akim Demaille, Miguel Santana
+ *
+ */
+
+/*
+ * This file is part of a2ps.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * $Id: lexssh.l,v 1.1.1.1.2.1 2007/12/29 01:58:35 mhatta Exp $
+ */
+
+#include "main.h"
+#include "yy2ssh.h"
+#include "parsessh.h"
+#include "xobstack.h"
+#include "regex.h"
+
+/* Defines if the comments are printed or not */
+extern int strip_level;
+
+/* #define YY_DECL yylex (YYSTYPE *lvalp);*/
+
+int yylex PARAMS ((void));
+void yyerror PARAMS ((const char *));
+
+/* Initilizes the obstacks */
+void sshlex_initialize PARAMS ((void));
+
+/* Obstack for strings reading */
+static struct obstack string_stack;
+
+/* The file we scan. */
+const char * sshfilename;
+
+#define LATEX_SYM_RETURN(Str) \
+ yylval.string = (uchar *) xstrdup (Str) ; return tLATEXSYMBOL ;
+
+#define RETURN_FACE(_f_)\
+ {yylval.face = _f_ ; return tFACE ;}
+
+#define RETURN_FFLAGS(_f_)\
+ {yylval.fflags = _f_ ; return tFFLAGS ;}
+
+%}
+
+%option yylineno
+%option prefix="ssh"
+%option outfile="lex.yy.c"
+
+
+%x STATE_STRING STATE_REGEXP
+
+comment #.*
+blank [ \t\r\f\n]*
+naked_string [^/#, \t\r\f\n\"()+]*
+
+%%
+
+{comment} { ; }
+{blank} { ; }
+
+\" { BEGIN STATE_STRING; }
+\/ { BEGIN STATE_REGEXP; }
+
+"\\forall" LATEX_SYM_RETURN ("\042");
+"\\exists" LATEX_SYM_RETURN ("\044");
+"\\suchthat" LATEX_SYM_RETURN ("\047");
+"\\cong" LATEX_SYM_RETURN ("\100");
+"\\Alpha" LATEX_SYM_RETURN ("\101");
+"\\Beta" LATEX_SYM_RETURN ("\102");
+"\\Chi" LATEX_SYM_RETURN ("\103");
+"\\Delta" LATEX_SYM_RETURN ("\104");
+"\\Epsilon" LATEX_SYM_RETURN ("\105");
+"\\Phi" LATEX_SYM_RETURN ("\106");
+"\\Gamma" LATEX_SYM_RETURN ("\107");
+"\\Eta" LATEX_SYM_RETURN ("\110");
+"\\Iota" LATEX_SYM_RETURN ("\111");
+"\\vartheta" LATEX_SYM_RETURN ("\112");
+"\\Kappa" LATEX_SYM_RETURN ("\113");
+"\\Lambda" LATEX_SYM_RETURN ("\114");
+"\\Mu" LATEX_SYM_RETURN ("\115");
+"\\Nu" LATEX_SYM_RETURN ("\116");
+"\\Omicron" LATEX_SYM_RETURN ("\117");
+"\\Pi" LATEX_SYM_RETURN ("\120");
+"\\Theta" LATEX_SYM_RETURN ("\121");
+"\\Rho" LATEX_SYM_RETURN ("\122");
+"\\Sigma" LATEX_SYM_RETURN ("\123");
+"\\Tau" LATEX_SYM_RETURN ("\124");
+"\\Upsilon" LATEX_SYM_RETURN ("\125");
+"\\varsigma" LATEX_SYM_RETURN ("\126");
+"\\Omega" LATEX_SYM_RETURN ("\127");
+"\\Xi" LATEX_SYM_RETURN ("\130");
+"\\Psi" LATEX_SYM_RETURN ("\131");
+"\\Zeta" LATEX_SYM_RETURN ("\132");
+"\\therefore" LATEX_SYM_RETURN ("\134");
+"\\perp" LATEX_SYM_RETURN ("\136");
+"\\radicalex" LATEX_SYM_RETURN ("\140");
+"\\alpha" LATEX_SYM_RETURN ("\141");
+"\\beta" LATEX_SYM_RETURN ("\142");
+"\\chi" LATEX_SYM_RETURN ("\143");
+"\\delta" LATEX_SYM_RETURN ("\144");
+"\\epsilon" LATEX_SYM_RETURN ("\145");
+"\\phi" LATEX_SYM_RETURN ("\146");
+"\\gamma" LATEX_SYM_RETURN ("\147");
+"\\eta" LATEX_SYM_RETURN ("\150");
+"\\iota" LATEX_SYM_RETURN ("\151");
+"\\varphi" LATEX_SYM_RETURN ("\152");
+"\\kappa" LATEX_SYM_RETURN ("\153");
+"\\lambda" LATEX_SYM_RETURN ("\154");
+"\\mu" LATEX_SYM_RETURN ("\155");
+"\\nu" LATEX_SYM_RETURN ("\156");
+"\\omicron" LATEX_SYM_RETURN ("\157");
+"\\pi" LATEX_SYM_RETURN ("\160");
+"\\theta" LATEX_SYM_RETURN ("\161");
+"\\rho" LATEX_SYM_RETURN ("\162");
+"\\sigma" LATEX_SYM_RETURN ("\163");
+"\\tau" LATEX_SYM_RETURN ("\164");
+"\\upsilon" LATEX_SYM_RETURN ("\165");
+"\\varpi" LATEX_SYM_RETURN ("\166");
+"\\omega" LATEX_SYM_RETURN ("\167");
+"\\xi" LATEX_SYM_RETURN ("\170");
+"\\psi" LATEX_SYM_RETURN ("\171");
+"\\zeta" LATEX_SYM_RETURN ("\172");
+"\\sim" LATEX_SYM_RETURN ("\176");
+"\\varUpsilon" LATEX_SYM_RETURN ("\241");
+"\\prime" LATEX_SYM_RETURN ("\242");
+"\\leq" LATEX_SYM_RETURN ("\243");
+"\\infty" LATEX_SYM_RETURN ("\245");
+"\\florin" LATEX_SYM_RETURN ("\246");
+"\\clubsuit" LATEX_SYM_RETURN ("\247");
+"\\diamondsuit" LATEX_SYM_RETURN ("\250");
+"\\heartsuit" LATEX_SYM_RETURN ("\251");
+"\\spadesuit" LATEX_SYM_RETURN ("\252");
+"\\leftrightarrow" LATEX_SYM_RETURN ("\253");
+"\\leftarrow" LATEX_SYM_RETURN ("\254");
+"\\uparrow" LATEX_SYM_RETURN ("\255");
+"\\rightarrow" LATEX_SYM_RETURN ("\256");
+"\\downarrow" LATEX_SYM_RETURN ("\257");
+"\\circ" LATEX_SYM_RETURN ("\260");
+"\\pm" LATEX_SYM_RETURN ("\261");
+"\\geq" LATEX_SYM_RETURN ("\263");
+"\\times" LATEX_SYM_RETURN ("\264");
+"\\propto" LATEX_SYM_RETURN ("\265");
+"\\partial" LATEX_SYM_RETURN ("\266");
+"\\bullet" LATEX_SYM_RETURN ("\267");
+"\\div" LATEX_SYM_RETURN ("\270");
+"\\neq" LATEX_SYM_RETURN ("\271");
+"\\equiv" LATEX_SYM_RETURN ("\272");
+"\\approx" LATEX_SYM_RETURN ("\273");
+"\\ldots" LATEX_SYM_RETURN ("\274");
+"---" LATEX_SYM_RETURN ("\276");
+"\\carriagereturn" LATEX_SYM_RETURN ("\277");
+"\\aleph" LATEX_SYM_RETURN ("\300");
+"\\Im" LATEX_SYM_RETURN ("\301");
+"\\Re" LATEX_SYM_RETURN ("\302");
+"\\wp" LATEX_SYM_RETURN ("\303");
+"\\otimes" LATEX_SYM_RETURN ("\304");
+"\\oplus" LATEX_SYM_RETURN ("\305");
+"\\emptyset" LATEX_SYM_RETURN ("\306");
+"\\cap" LATEX_SYM_RETURN ("\307");
+"\\cup" LATEX_SYM_RETURN ("\310");
+"\\supset" LATEX_SYM_RETURN ("\311");
+"\\supseteq" LATEX_SYM_RETURN ("\312");
+"\\not\\subset" LATEX_SYM_RETURN ("\313");
+"\\subset" LATEX_SYM_RETURN ("\314");
+"\\subseteq" LATEX_SYM_RETURN ("\315");
+"\\in" LATEX_SYM_RETURN ("\316");
+"\\not\\in" LATEX_SYM_RETURN ("\317");
+"\\angle" LATEX_SYM_RETURN ("\320");
+"\\nabla" LATEX_SYM_RETURN ("\321");
+"\\varregister" LATEX_SYM_RETURN ("\322");
+"\\varcopyright" LATEX_SYM_RETURN ("\324");
+"\\vartrademark" LATEX_SYM_RETURN ("\324");
+"\\prod" LATEX_SYM_RETURN ("\325");
+"\\surd" LATEX_SYM_RETURN ("\326");
+"\\cdot" LATEX_SYM_RETURN ("\327");
+"\\not" LATEX_SYM_RETURN ("\330");
+"\\wedge" LATEX_SYM_RETURN ("\331");
+"\\vee" LATEX_SYM_RETURN ("\332");
+"\\Leftrightarrow" LATEX_SYM_RETURN ("\333");
+"\\Leftarrow" LATEX_SYM_RETURN ("\334");
+"\\Uparrow" LATEX_SYM_RETURN ("\335");
+"\\Rightarrow" LATEX_SYM_RETURN ("\336");
+"\\Downarrow" LATEX_SYM_RETURN ("\337");
+"\\vardiamondsuit" LATEX_SYM_RETURN ("\340");
+"\\langle" LATEX_SYM_RETURN ("\341");
+"\\register" LATEX_SYM_RETURN ("\342");
+"\\copyright" LATEX_SYM_RETURN ("\342");
+"\\trademark" LATEX_SYM_RETURN ("\344");
+"\\sum" LATEX_SYM_RETURN ("\345");
+"\\lceil" LATEX_SYM_RETURN ("\351");
+"\\lfloor" LATEX_SYM_RETURN ("\353");
+"\\rangle" LATEX_SYM_RETURN ("\361");
+"\\int" LATEX_SYM_RETURN ("\362");
+"\\rceil" LATEX_SYM_RETURN ("\371");
+"\\rfloor" LATEX_SYM_RETURN ("\373");
+
+\\[0-9]+ {
+ int value = yytext[1] - '0';
+ char *cursor = yytext + 2;
+
+ while (*cursor)
+ value = 8 * value + *cursor++ - '0';
+ yylval.integer = value;
+ return tBACK_REF;
+}
+
+"a2ps" return tA2PS;
+"alphabet" return tALPHABET;
+"alphabets" return tALPHABETS;
+"ancestors" return tANCESTORS;
+"are" return tARE;
+"by" return tBY;
+"case" return tCASE;
+"closers" return tCLOSERS;
+"C-char" return tCCHAR;
+"C-string" return tCSTRING;
+"documentation" return tDOCUMENTATION;
+"end" return tEND;
+"exceptions" return tEXCEPTIONS;
+"first" return tFIRST;
+"in" return tIN;
+"insensitive" { yylval.sensitiveness = case_insensitive ;
+ return tSENSITIVENESS;
+ }
+"is" return tIS;
+"keywords" return tKEYWORDS;
+"requires" return tREQUIRES;
+"second" return tSECOND;
+"sensitive" { yylval.sensitiveness = case_sensitive ;
+ return tSENSITIVENESS;
+ }
+"operators" return tOPERATORS;
+"optional" return tOPTIONAL;
+"sequences" return tSEQUENCES;
+"style" return tSTYLE;
+"version" return tVERSION;
+"written" return tWRITTEN;
+
+"Plain" RETURN_FACE (Plain)
+"Keyword" RETURN_FACE (Keyword)
+"Keyword_strong" RETURN_FACE (Keyword_strong)
+"Error" RETURN_FACE (Error)
+"Label" RETURN_FACE (Label)
+"Label_strong" RETURN_FACE (Label_strong)
+"String" RETURN_FACE (String)
+"Symbol" RETURN_FACE (Symbol)
+"Comment" { /* Strip if required */
+ if ((strip_level == 1) || (strip_level == 3))
+ RETURN_FFLAGS (ff_Invisible)
+ else
+ RETURN_FACE (Comment)
+ }
+"Comment_strong" { /* Strip if required */
+ if ((strip_level == 2) || (strip_level == 3))
+ RETURN_FFLAGS (ff_Invisible)
+ else
+ RETURN_FACE (Comment_strong)
+ }
+
+"Tag1" RETURN_FFLAGS (ff_Tag1)
+"Tag2" RETURN_FFLAGS (ff_Tag2)
+"Tag3" RETURN_FFLAGS (ff_Tag3)
+"Tag4" RETURN_FFLAGS (ff_Tag4)
+"Index1" RETURN_FFLAGS (ff_Index1)
+"Index2" RETURN_FFLAGS (ff_Index2)
+"Index3" RETURN_FFLAGS (ff_Index3)
+"Index4" RETURN_FFLAGS (ff_Index4)
+"Encoding" RETURN_FFLAGS (ff_Encoding)
+"Invisible" RETURN_FFLAGS (ff_Invisible)
+
+{naked_string} { yylval.string = xustrdup (yytext);
+ return tSTRING;
+ }
+
+. { return yytext[0]; }
+
+<STATE_STRING>{ /* string of characters */
+ \" { /* return the string */
+ uchar * string;
+
+ obstack_1grow (&string_stack, '\0');
+ string = (uchar *) obstack_finish (&string_stack);
+
+ obstack_free (&string_stack, string);
+
+ BEGIN INITIAL; /* Return to the regular scanning */
+ yylval.string = xustrdup (string);
+ return tSTRING;
+ }
+
+ \\[0-7]{1,3} {
+ int value = yytext[1] - '0';
+ char *cursor = yytext + 2;
+
+ while (*cursor)
+ value = 8 * value + *cursor++ - '0';
+ obstack_1grow (&string_stack, value);
+ }
+
+ \\x[0-9a-fA-F]{1,2} {
+ int value = 0;
+ char *cursor = yytext + 2;
+
+ while (*cursor)
+ if (*cursor >= 'a' && *cursor <= 'f')
+ value = 16 * value + *cursor++ - 'a' + 10;
+ else if (*cursor >= 'A' && *cursor <= 'F')
+ value = 16 * value + *cursor++ - 'A' + 10;
+ else
+ value = 16 * value + *cursor++ - '0';
+ obstack_1grow (&string_stack, value);
+ }
+
+ \\a { obstack_1grow (&string_stack, '\007'); }
+ \\b { obstack_1grow (&string_stack, '\b'); }
+ \\d { obstack_1grow (&string_stack, 127); }
+ \\e { obstack_1grow (&string_stack, 27); }
+ \\f { obstack_1grow (&string_stack, '\f'); }
+ \\n { obstack_1grow (&string_stack, '\n'); }
+ \\r { obstack_1grow (&string_stack, '\r'); }
+ \\t { obstack_1grow (&string_stack, '\t'); }
+ \\v { obstack_1grow (&string_stack, '\v'); }
+ \\. { obstack_1grow (&string_stack, yytext[1]); }
+
+ \n {
+ yyerror (_("end-of-line in string constant"));
+ }
+
+ [^\"\n\\]+ {
+ obstack_grow (&string_stack, yytext, yyleng);
+ }
+}
+
+<STATE_REGEXP>{ /* a regular expression */
+ \/ { /* return the string */
+ char * pattern;
+ int pattern_len;
+
+ /* I'm not sure I got the 0 terminate the pattern */
+ obstack_1grow (&string_stack, '\0');
+ pattern_len = obstack_object_size (&string_stack);
+ pattern = (char *) obstack_finish (&string_stack);
+ obstack_free (&string_stack, pattern);
+
+ yylval.pattern = XMALLOC (struct pattern, 1);
+ /* len - 1, because the NUL must not be part of the pattern that
+ * will be compiled. We put tough, to be able to use the pattern
+ * in regular C strings manipulations. */
+ yylval.pattern->len = pattern_len - 1;
+ yylval.pattern->pattern = XMALLOC (char, pattern_len);
+ memcpy (yylval.pattern->pattern, pattern, pattern_len);
+
+ BEGIN INITIAL; /* Return to the regular scanning */
+ return tREGEX;
+ }
+
+ \\[0-7]{1,3} {
+ int value = yytext[1] - '0';
+ char *cursor = yytext + 2;
+
+ while (*cursor)
+ value = 8 * value + *cursor++ - '0';
+ obstack_1grow (&string_stack, value);
+ }
+
+ \\x[0-9a-fA-F]{1,2} {
+ int value = 0;
+ char *cursor = yytext + 2;
+
+ while (*cursor)
+ if (*cursor >= 'a' && *cursor <= 'f')
+ value = 16 * value + *cursor++ - 'a' + 10;
+ else if (*cursor >= 'A' && *cursor <= 'F')
+ value = 16 * value + *cursor++ - 'A' + 10;
+ else
+ value = 16 * value + *cursor++ - '0';
+ obstack_1grow (&string_stack, value);
+ }
+
+ \\a { obstack_1grow (&string_stack, '\007'); }
+ \\b { obstack_1grow (&string_stack, '\b'); }
+ \\d { obstack_1grow (&string_stack, 127); }
+ \\e { obstack_1grow (&string_stack, 27); }
+ \\f { obstack_1grow (&string_stack, '\f'); }
+ \\n { obstack_1grow (&string_stack, '\n'); }
+ \\r { obstack_1grow (&string_stack, '\r'); }
+ \\t { obstack_1grow (&string_stack, '\t'); }
+ \\v { obstack_1grow (&string_stack, '\v'); }
+ \\. { obstack_1grow (&string_stack, yytext[1]); }
+
+ \n {
+ error_at_line (1, 0, sshfilename, sshlineno,
+ _("end of line inside a %s"), "\"..\"");
+ }
+
+ [^\n\\\/]+ {
+ obstack_grow (&string_stack, yytext, yyleng);
+ }
+}
+
+%%
+
+int
+yywrap (void)
+{
+ return 1;
+}
+
+/*
+ * Initialize the obstacks
+ */
+void
+sshlex_initialize (void)
+{
+ static int first_time = 1;
+ if (first_time)
+ {
+ first_time = 0;
+ obstack_init (&string_stack);
+ }
+}
diff --git a/src/long-options.c b/src/long-options.c
new file mode 100644
index 0000000..fb40cd9
--- /dev/null
+++ b/src/long-options.c
@@ -0,0 +1,90 @@
+/* Utility to accept --help and --version options as unobtrusively as possible.
+ Copyright (C) 1993, 1994, 1998, 1999 Free Software Foundation, Inc.
+
+ This program 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, or (at your option)
+ any later version.
+
+ This program 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, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Jim Meyering. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <getopt.h>
+#include "closeout.h"
+#include "long-options.h"
+#include "version-etc.h"
+
+#if ENABLE_NLS
+# include <libintl.h>
+# define _(Text) gettext (Text)
+#else
+# define _(Text) Text
+#endif
+
+static struct option const long_options[] =
+{
+ {"help", no_argument, 0, 'h'},
+ {"version", no_argument, 0, 'v'},
+ {0, 0, 0, 0}
+};
+
+/* Process long options --help and --version, but only if argc == 2.
+ Be careful not to gobble up `--'. */
+
+void
+parse_long_options (int argc,
+ char **argv,
+ const char *command_name,
+ const char *package,
+ const char *version,
+ const char *authors,
+ void (*usage_func)())
+{
+ int c;
+ int saved_opterr;
+
+ saved_opterr = opterr;
+
+ /* Don't print an error message for unrecognized options. */
+ opterr = 0;
+
+ if (argc == 2
+ && (c = getopt_long (argc, argv, "+", long_options, NULL)) != -1)
+ {
+ switch (c)
+ {
+ case 'h':
+ (*usage_func) (0);
+
+ case 'v':
+ version_etc (stdout, command_name, package, version, authors);
+ close_stdout (); /* FIXME: output failure exit status
+ should be settable via an arg. */
+ exit (0);
+
+ default:
+ /* Don't process any other long-named options. */
+ break;
+ }
+ }
+
+ /* Restore previous value. */
+ opterr = saved_opterr;
+
+ /* Reset this to zero so that getopt internals get initialized from
+ the probably-new parameters when/if getopt is called later. */
+ optind = 0;
+}
diff --git a/src/long-options.h b/src/long-options.h
new file mode 100644
index 0000000..586a3ef
--- /dev/null
+++ b/src/long-options.h
@@ -0,0 +1,35 @@
+/* long-options.h -- declaration for --help- and --version-handling function.
+ Copyright (C) 1993, 1994, 1998, 1999 Free Software Foundation, Inc.
+
+ This program 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, or (at your option)
+ any later version.
+
+ This program 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, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Jim Meyering. */
+
+#ifndef PARAMS
+# if defined PROTOTYPES || (defined __STDC__ && __STDC__)
+# define PARAMS(Args) Args
+# else
+# define PARAMS(Args) ()
+# endif
+#endif
+
+void
+ parse_long_options PARAMS ((int _argc,
+ char **_argv,
+ const char *_command_name,
+ const char *_package,
+ const char *_version,
+ const char *_authors,
+ void (*_usage) (int)));
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..1f75048
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,1229 @@
+/*
+ * main.c -- main loop, and interface with user
+ *
+ * Copyright (c) 1988-1993 Miguel Santana
+ * Copyright (c) 1995-2000 Akim Demaille, Miguel Santana
+ * Copyright (c) 2007 Akim Demaille, Miguel Santana and Masayuki Hatta
+ */
+
+/*
+ * This file is part of a2ps.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+/************************************************************************/
+/* */
+/* I n c l u d e f i l e s */
+/* */
+/************************************************************************/
+#include <assert.h>
+
+#include "a2ps.h"
+#include "argmatch.h"
+#include "confg.h"
+#include "options.h"
+#include "pathwalk.h"
+#include "select.h"
+#include "generate.h"
+#include "printers.h"
+#include "delegate.h"
+#include "metaseq.h"
+#include "regex.h"
+#include "buffer.h"
+#include "psgen.h"
+#include "prolog.h"
+#include "stream.h"
+#include "getnum.h"
+#include "title.h"
+#include "useropt.h"
+#include "main.h"
+#include "lexps.h"
+#include <signal.h>
+#include "signame.h"
+#include "long-options.h"
+#include "version-etc.h"
+#include <locale.h>
+
+/* From basename.c */
+char *base_name PARAMS ((const char *path));
+
+/************************************************************************/
+/* */
+/* G l o b a l d e f i n i t i o n s */
+/* */
+/************************************************************************/
+/************************************************************************
+ * The various global behaviors
+ */
+enum behavior
+ {
+ b_ps, /* postscript generator (usual PS converter) */
+ b_guess, /* do as file(1) does: return the ssh file name */
+ b_help,
+ b_version,
+ b_expand, /* Expand the strings given as arguments. */
+ b_which, /* Look for the args in the path, and report. */
+ b_glob, /* Same, but with globbing. */
+ b_list_options,
+ b_list_features,
+ b_list_media,
+ b_list_style_sheets,
+ b_list_html_style_sheets,
+ b_list_texinfo_style_sheets,
+ b_list_printers,
+ b_list_delegations,
+ b_list_macro_meta_sequences,
+ b_list_encodings,
+ b_list_texinfo_encodings,
+ b_list_user_options,
+ b_list_prologues,
+ b_list_texinfo_prologues,
+ b_list_ppd
+ };
+
+/* Stores the task to execute. Default: a2ps. */
+
+enum behavior behavior = b_ps;
+
+/* Name under which this program is called. To understand why it is
+ defined twice, see lib/confg.gperf, handling of `Options:'. */
+
+char *program_name;
+const char *program_invocation_name;
+
+/* Stores the data of liba2ps. */
+
+a2ps_job *job = NULL;
+
+
+/* Syntax table for regex. */
+
+char *re_syntax_table = NULL;
+
+#define RE_SYNTAX_A2PS \
+ (/* Allow char classes. */ \
+ RE_CHAR_CLASSES \
+ /* Be picky. */ \
+ | RE_CONTEXT_INVALID_OPS \
+ /* Allow intervals with `{' and `}', forbid invalid ranges. */\
+ | RE_INTERVALS | RE_NO_BK_BRACES | RE_NO_EMPTY_RANGES \
+ /* `(' and `)' are the grouping operators. */ \
+ | RE_NO_BK_PARENS \
+ /* `|' is the alternation. */ \
+ | RE_NO_BK_VBAR)
+
+
+/************************************************************************/
+/* Related to the config files */
+/************************************************************************/
+/*
+ * Hash table of the delegations
+ */
+struct hash_table_s *delegation_table;
+
+/*
+ * Content of sheets.map
+ */
+struct darray *sheets_map = NULL;
+
+/*
+ * Hash table of the sheet yet read
+ */
+struct hash_table_s *style_sheets = NULL;
+
+/************************************************************************/
+/* Related to the options */
+/************************************************************************/
+/*
+ * Delegate files to other applications.
+ */
+bool delegate_p = true;
+
+/*
+ * --toc[=format], generate a table of content
+ */
+uchar *toc = NULL;
+
+/*
+ * -E: style sheet to use. NULL => automated
+ */
+char *style_request = NULL;
+
+/*
+ * -g/--highlight-level: 0, 1 or 2
+ */
+int highlight_level = 1;
+
+/*
+ * --strip=NUM, don't write the comments
+ */
+int strip_level = 0;
+
+/*
+ * --end-of-line=TYPE, specify what are the sequences of chars to
+ * interpret as end of line
+ */
+enum eol_e end_of_line = eol_auto;
+
+/************************************************************************/
+/* Service routines */
+/************************************************************************/
+/*
+ * Unlink all the used files. Used for atexit
+ */
+static void
+exit_handler (void)
+{
+ if (job)
+ a2ps_job_unlink_tmpfiles (job);
+ if (sample_tmpname)
+ unlink (sample_tmpname);
+}
+
+static RETSIGTYPE
+signal_handler (int signum)
+{
+ /* Error calls exit which calls atexit which removes the files. */
+ error (EXIT_FAILURE, 0,
+ _("received signal %d: %s"), signum, strsignal (signum));
+}
+
+/************************************************************************
+ * Read the highlighting level
+ */
+static const char *const highlight_level_args[] =
+{
+ "none", "off", "0",
+ "normal", "light", "1",
+ "heavy", "symbols", "2",
+ 0
+};
+
+static const int highlight_level_types[] =
+{
+ 0, 0, 0,
+ 1, 1, 1,
+ 2, 2, 2
+};
+
+/*
+ * Return the highlight_level value
+ */
+static int
+get_highlight_level (const char *option, const char *arg)
+{
+ ARGMATCH_ASSERT (highlight_level_args, highlight_level_types);
+ return XARGCASEMATCH (option, arg,
+ highlight_level_args, highlight_level_types);
+}
+
+static char *
+highlight_level_to_string (int level)
+{
+ switch (level)
+ {
+ case 2:
+ /* TRANS: highlighting level = heavy (2/2) */
+ return _("heavy");
+
+ case 1:
+ /* TRANS: highlighting level = normal (1/2) */
+ return _("normal");
+
+ case 0:
+ /* TRANS: highlighting level = none (0/2) */
+ return _("none");
+ }
+ return NULL; /* For -Wall */
+}
+
+/************************************************************************
+ * Read the --list argument
+ */
+static const char *const behavior_args[] =
+{
+ "defaults", "options", "settings",
+ "features", "plugins",
+ "delegations",
+ "encodings", "charsets",
+ "variables", "macro-meta-sequences",
+ "media",
+ "printers", "outputs",
+ "style-sheets", "languages",
+ "user-options", "shortcuts",
+ "prologues",
+ "texinfo-style-sheets", "ssh-texi",
+ "html-style-sheets", "ssh-html",
+ "texinfo-encodings", "edf-texi",
+ "texinfo-prologues", "pro-texi",
+ "ppd",
+ "version", "release",
+ "help", "usage",
+ "expand",
+ "which", "find",
+ "glob",
+ "ps",
+ NULL
+};
+
+static const enum behavior behavior_types[] =
+{
+ b_list_options, b_list_options, b_list_options,
+ b_list_features, b_list_features,
+ b_list_delegations,
+ b_list_encodings, b_list_encodings,
+ b_list_macro_meta_sequences, b_list_macro_meta_sequences,
+ b_list_media,
+ b_list_printers, b_list_printers,
+ b_list_style_sheets, b_list_style_sheets,
+ b_list_user_options, b_list_user_options,
+ b_list_prologues,
+ b_list_texinfo_style_sheets, b_list_texinfo_style_sheets,
+ b_list_html_style_sheets, b_list_html_style_sheets,
+ b_list_texinfo_encodings, b_list_texinfo_encodings,
+ b_list_texinfo_prologues, b_list_texinfo_prologues,
+ b_list_ppd,
+ b_version, b_version,
+ b_help, b_help,
+ b_expand,
+ b_which, b_which,
+ b_glob,
+ b_ps
+};
+
+/************************************************************************/
+/* Interface */
+/************************************************************************/
+
+/*------------------------------------------------------------------.
+| Print information depending on the installation. It is also used |
+| to store useful information in the output to help us debuging the |
+| users :). |
+`------------------------------------------------------------------*/
+
+static void
+list_options (struct a2ps_job *a_job, FILE *stream)
+{
+#if 0
+ /* This is just so that gettext knows I use those two strings. */
+ static char *yes = N_("yes");
+ static char *no = N_("no");
+#endif
+
+#define bool_to_string(bool) ((bool) ? _("yes") : _("no"))
+ uchar buf[256], buf2[256];
+ const char *cp = NULL;
+ uchar *ucp = NULL;
+
+ /* Title of --list-options (%s%s is `a2ps' `version' */
+ title (stream, '=', true,
+ _("Configuration status of %s %s\n"),
+ program_invocation_name, VERSION);
+ putc ('\n', stream);
+
+ title (stream, '-', false, _("Sheets:\n"));
+ fprintf (stream, _("\
+ medium = %s%s, %s\n\
+ page layout = %d x %d, %s\n\
+ borders = %s\n\
+ file alignment = %s\n\
+ interior margin = %d\n"),
+ a_job->medium->name,
+ (a2ps_medium_libpaper_p (job, job->medium_request)
+ ? " (libpaper)" : ""),
+ (a_job->orientation == portrait) ? _("portrait") : _("landscape"),
+ a_job->columns, a_job->rows,
+ madir_to_string (a_job->madir),
+ bool_to_string (a_job->border),
+ file_align_to_string (a_job->file_align),
+ a_job->margin);
+ putc ('\n', stream);
+
+ if (a_job->columns_requested > 0)
+ sprintf ((char *) buf, _("%d characters per line"),
+ a_job->columns_requested);
+ else if (a_job->lines_requested > 0)
+ sprintf ((char *) buf, _("%d lines per page"),
+ a_job->lines_requested);
+ else
+ sprintf ((char *) buf, _("font size is %gpt"), a_job->fontsize);
+
+ switch (a_job->numbering)
+ {
+ case 0:
+ ustrcpy (buf2, _("no"));
+ break;
+ case 1:
+ /* number line: each line */
+ ustrcpy (buf2, _("each line"));
+ break;
+ default:
+ /* number line: each %d line */
+ sprintf ((char *) buf2, _("each %d lines"), a_job->numbering);
+ }
+
+ title (stream, '-', false, _("Virtual pages:\n"));
+ fprintf (stream, _("\
+ number lines = %s\n\
+ format = %s\n\
+ tabulation size = %d\n\
+ non printable format = %s\n"),
+ buf2,
+ buf,
+ a_job->tabsize,
+ unprintable_format_to_string (a_job->unprintable_format));
+ putc ('\n', stream);
+
+ title (stream, '-', false, _("Headers:\n"));
+ fprintf (stream, _("\
+ header = %s\n\
+ left footer = %s\n\
+ footer = %s\n\
+ right footer = %s\n\
+ left title = %s\n\
+ center title = %s\n\
+ right title = %s\n\
+ under lay = %s\n"),
+ UNNULL (a_job->header),
+ UNNULL (a_job->left_footer),
+ UNNULL (a_job->footer),
+ UNNULL (a_job->right_footer),
+ UNNULL (a_job->left_title),
+ UNNULL (a_job->center_title),
+ UNNULL (a_job->right_title),
+ UNNULL (a_job->water));
+ putc ('\n', stream);
+
+ title (stream, '-', false, _("Input:\n"));
+ fprintf (stream, _("\
+ truncate lines = %s\n\
+ interpret = %s\n\
+ end of line = %s\n\
+ encoding = %s\n\
+ document title = %s\n\
+ prologue = %s\n\
+ print anyway = %s\n\
+ delegating = %s\n"),
+ bool_to_string (!a_job->folding),
+ bool_to_string (a_job->interpret),
+ eol_to_string (end_of_line),
+ encoding_get_name (a_job->requested_encoding),
+ a_job->title,
+ a_job->prolog,
+ bool_to_string (a_job->print_binaries),
+ bool_to_string (delegate_p));
+ putc ('\n', stream);
+
+ /*
+ * Pretty printing
+ */
+ if (IS_EMPTY (style_request))
+ /* TRANS: a2ps -E --list=options. Warning, this answer is also
+ used for the PPD file. Make it compatible with both. */
+ ustrcpy (buf, _("selected automatically"));
+ else
+ ustrcpy (buf, style_request);
+ title (stream, '-', false, _("Pretty-printing:\n"));
+ fprintf (stream, _("\
+ style sheet = %s\n\
+ highlight level = %s\n\
+ strip level = %d\n"),
+ buf,
+ highlight_level_to_string (highlight_level),
+ strip_level);
+ putc ('\n', stream);
+
+ /*
+ * Information on where will go the output
+ */
+
+ /* Make a nice message to tell where the output is sent */
+ ucp = a2ps_flag_destination_to_string (a_job);
+
+ /* Make a nice message to tell what version control is used */
+ switch (a_job->backup_type)
+ {
+ case none:
+ cp = _("never make backups");
+ break;
+
+ case simple:
+ cp = _("simple backups of every file");
+ break;
+
+ case numbered_existing:
+ /* appears in a2ps --version-=existing --list=defaults */
+ cp = _("numbered backups of files already numbered,\n\
+ and simple of others");
+ break;
+
+ case numbered:
+ cp = _("numbered backups of every file");
+ break;
+ }
+
+ title (stream, '-', false, _("Output:\n"));
+ fprintf (stream, _("\
+ destination = %s\n\
+ version control = %s\n\
+ backup suffix = %s\n"),
+ ucp, cp, simple_backup_suffix);
+ putc ('\n', stream);
+ free (ucp);
+
+ /*
+ * PostScript report.
+ * TRANS: to be aligned with `page prefeed ='
+ */
+ cp = a2ps_printers_request_ppdkey_get (a_job->printers);
+ title (stream, '-', false, _("PostScript:\n"));
+ fprintf (stream, _("\
+ magic number = %s\n\
+ Printer Description (PPD) = %s\n\
+ default PPD = %s\n\
+ page label format = %s\n\
+ number of copies = %d\n\
+ sides per sheet = %s\n\
+ page device definitions = "),
+ a_job->status->magic_number,
+ cp ? cp : _("selected automatically"),
+ a2ps_printers_default_ppdkey_get (a_job->printers),
+ a_job->status->page_label_format,
+ a_job->copies,
+ (a_job->duplex == simplex
+ ? "Simplex"
+ : (a_job->duplex == duplex
+ ? "Duplex"
+ : "DuplexTumble")));
+
+ list_pagedevice (a_job, stream);
+ fprintf (stream, _("\
+ statusdict definitions = "));
+ list_statusdict (a_job, stream);
+ fprintf (stream, _("\
+ page prefeed = %s\n"),
+ bool_to_string (a_job->page_prefeed));
+ putc ('\n', stream);
+
+
+ /*
+ * Internal Details
+ */
+ title (stream, '-', false, _("Internals:\n"));
+ fprintf (stream, _("\
+ verbosity level = %d\n\
+ file command = %s\n\
+ library path = \n"),
+ msg_verbosity,
+ UNNULL (a_job->file_command));
+ pw_fprintf_path (stream, "\t%s\n", a_job->common.path);
+}
+
+
+/*------------------------------------------------------------------.
+| This is used in psgen to push into the PostScript the report of |
+| the state of a2ps when it produced the file. I'm tired of |
+| fighting with users who don't really say everything on the state |
+| of their a2ps when something goes wrong. Now I can ask a ps file |
+| generated with --debug, and got everything I need. |
+`------------------------------------------------------------------*/
+
+static void
+spy_user (struct a2ps_job *a_job, FILE * stream)
+{
+#define PREFIX "% "
+ FILE *spy;
+ char *spyname;
+ char buf[BUFSIZ];
+
+ /* Use one of the temp file names so that cleanup can be correctly
+ done. */
+ tempname_ensure (job->tmp_filenames[0]);
+ spyname = job->tmp_filenames[0];
+ spy = fopen (spyname, "w");
+ if (!spy)
+ error (1, errno, _("cannot open file `%s'"), quotearg (spyname));
+
+
+ /* Well, this is the information I've been fighting with some users
+ to get them exact... I hate doing that, but I need to save part
+ of my time. */
+ fputs ("SPY-BEGIN\n", spy);
+ fputs ((char *) expand_user_string (job, CURRENT_FILE (job),
+ (const uchar *) "Debugging info",
+ (const uchar *) "%V was called with #!$|| |\n\n"),
+ spy);
+
+ list_options (a_job, spy);
+ putc ('\n', spy);
+ macro_meta_sequences_list_long (a_job, spy);
+ fputs ("SPY-END\n", spy);
+
+ /* Yes, I know, there are certainly better means. Just teach them
+ to me... */
+ fclose (spy);
+ fopen (spyname, "r");
+ if (!spy)
+ error (1, errno, _("cannot open file `%s'"), quotearg (spyname));
+
+ while (fgets (buf, sizeof (buf), spy))
+ {
+ fputs (PREFIX, stream);
+ fputs (buf, stream);
+ }
+ fputs (PREFIX, stream);
+ putc ('\n', stream);
+ fclose (spy);
+ unlink (spyname);
+}
+
+
+/*--------------------------------------------------.
+| Print information depending on the installation. |
+`--------------------------------------------------*/
+
+static void
+list_features (struct a2ps_job *a_job, FILE * stream)
+{
+ /* Known languages */
+ list_style_sheets_short (stream);
+ putc ('\n', stream);
+
+ /* Known char sets */
+ list_encodings_short (a_job, stream);
+ putc ('\n', stream);
+
+ /* Known media */
+ list_media_short (a_job, stream);
+ putc ('\n', stream);
+
+ /* Known prologues */
+ prologues_list_short (a_job, stream);
+ putc ('\n', stream);
+
+ /* Known PPD files */
+ a2ps_ppd_list_short (a_job, stream);
+ putc ('\n', stream);
+
+ /* Known "printers" */
+ a2ps_printers_list_short (a_job, stream);
+ putc ('\n', stream);
+
+ /* Known "delegates" */
+ delegations_list_short (delegation_table, stream);
+ putc ('\n', stream);
+
+ /* Known user options */
+ user_options_list_short (a_job, stream);
+ putc ('\n', stream);
+
+ /* Macro meta seq. */
+ macro_meta_sequences_list_short (a_job, stream);
+}
+
+/*------------------------.
+| Print a usage message. |
+`------------------------*/
+
+#define sfputs(String) fputs (String, stream)
+#define sputc(Char) putc (Char, stream)
+
+static void
+usage (int status)
+{
+ /* Currently, there seem to be no use in being able to use another
+ stream than STDOUT. */
+ FILE *stream = stdout;
+
+ fprintf (stream, _("\
+Usage: %s [OPTION]... [FILE]...\n\
+\n\
+Convert FILE(s) or standard input to PostScript. By default, the output\n\
+is sent to the default printer. An output file may be specified with -o.\n\
+\n\
+Mandatory arguments to long options are mandatory for short options too.\n\
+Long options marked with * require a yes/no argument, corresponding\n\
+short options stand for `yes'.\n"),
+ program_invocation_name);
+
+ /*
+ * Does not print, and exits with success
+ */
+ sputc ('\n');
+ sfputs (_("Tasks:\n"));
+ sfputs (_("\
+ --version display version\n\
+ --help display this help\n\
+ --guess report guessed types of FILES\n\
+ --which report the full path of library files named FILES\n\
+ --glob report the full path of library files matching FILES\n\
+ --list=defaults display default settings and parameters\n\
+ --list=TOPIC detailed list on TOPIC (delegations, encodings, features,\n\
+ variables, media, ppd, printers, prologues, style-sheets,\n\
+ user-options)\n"));
+ sputc ('\n');
+ sfputs (_("\
+After having performed the task, exit successfully. Detailed lists may\n\
+provide additional help on specific features.\n"));
+
+ /*
+ * Applies to the whole behavior
+ */
+ sputc ('\n');
+ sfputs (_("Global:\n"));
+ sfputs (_("\
+ -q, --quiet, --silent be really quiet\n\
+ -v, --verbose[=LEVEL] set verbosity on, or to LEVEL\n\
+ -=, --user-option=OPTION use the user defined shortcut OPTION\n\
+ --debug enable debugging features\n\
+ -D, --define=KEY[:VALUE] unset variable KEY or set to VALUE\n"));
+
+ sputc ('\n');
+ sfputs (_("Sheets:\n"));
+ sfputs (_("\
+ -M, --medium=NAME use output medium NAME\n\
+ -r, --landscape print in landscape mode\n\
+ -R, --portrait print in portrait mode\n\
+ --columns=NUM number of columns per sheet\n\
+ --rows=NUM number of rows per sheet\n\
+ --major=DIRECTION first fill (DIRECTION=) rows, or columns\n\
+ -1, -2, ..., -9 predefined font sizes and layouts for 1.. 9 virtuals\n\
+ -A, --file-align=MODE align separate files according to MODE (fill, rank\n\
+ page, sheet, or a number)\n\
+ -j, --borders* print borders around columns\n\
+ --margin[=NUM] define an interior margin of size NUM\n"));
+ sputc ('\n');
+ sfputs (_("\
+The options -1.. -9 affect several primitive parameters to set up predefined\n\
+layouts with 80 columns. Therefore the order matters: `-R -f40 -2' is\n\
+equivalent to `-2'. To modify the layout, use `-2Rf40', or compose primitive\n\
+options (`--columns', `--font-size' etc.).\n"));
+
+ sputc ('\n');
+ sfputs (_("Virtual pages:\n"));
+ sfputs (_("\
+ --line-numbers=NUM precede each NUM lines with its line number\n\
+ -C alias for --line-numbers=5\n\
+ -f, --font-size=SIZE use font SIZE (float) for the body text\n\
+ -L, --lines-per-page=NUM scale the font to print NUM lines per virtual\n\
+ -l, --chars-per-line=NUM scale the font to print NUM columns per virtual\n\
+ -m, --catman process FILE as a man page (same as -L66)\n\
+ -T, --tabsize=NUM set tabulator size to NUM\n\
+ --non-printable-format=FMT specify how non-printable chars are printed\n"));
+
+ sputc ('\n');
+ sfputs (_("Headings:\n"));
+ /* xgettext:no-c-format */
+ sfputs (_("\
+ -B, --no-header no page headers at all\n\
+ -b, --header[=TEXT] set page header\n\
+ -u, --underlay[=TEXT] print TEXT under every page\n\
+ --center-title[=TEXT] set page title to TITLE\n\
+ --left-title[=TEXT] set left and right page title to TEXT\n\
+ --right-title[=TEXT]\n\
+ --left-footer[=TEXT] set sheet footers to TEXT\n\
+ --footer[=TEXT]\n\
+ --right-footer[=TEXT]\n"));
+ sputc ('\n');
+ sfputs (_("\
+The TEXTs may use special escapes.\n"));
+
+ sputc ('\n');
+ sfputs (_("Input:\n"));
+ sfputs (_("\
+ -a, --pages[=RANGE] select the pages to print\n\
+ -c, --truncate-lines* cut long lines\n\
+ -i, --interpret* interpret tab, bs and ff chars\n\
+ --end-of-line=TYPE specify the eol char (TYPE: r, n, nr, rn, any)\n\
+ -X, --encoding=NAME use input encoding NAME\n\
+ -t, --title=NAME set the name of the job\n\
+ --stdin=NAME set the name of the input file stdin\n\
+ --print-anyway* force binary printing\n\
+ -Z, --delegate* delegate files to another application\n\
+ --toc[=TEXT] generate a table of content\n"));
+ sputc ('\n');
+ sfputs (_("\
+When delegations are enabled, a2ps may use other applications to handle the\n\
+processing of files that should not be printed as raw information, e.g., HTML\n\
+PostScript, PDF etc.\n"));
+
+ sputc ('\n');
+ sfputs (_("Pretty-printing:\n"));
+ sfputs (_("\
+ -E, --pretty-print[=LANG] enable pretty-printing (set style to LANG)\n\
+ --highlight-level=LEVEL set pretty printing highlight LEVEL\n\
+ LEVEL can be none, normal or heavy\n\
+ -g alias for --highlight-level=heavy\n\
+ --strip-level=NUM level of comments stripping\n"));
+
+ sputc ('\n');
+ sfputs (_("Output:\n"));
+ sfputs (_("\
+ -o, --output=FILE leave output to file FILE. If FILE is `-',\n\
+ leave output to stdout.\n\
+ --version-control=WORD override the usual version control\n\
+ --suffix=SUFFIX override the usual backup suffix\n\
+ -P, --printer=NAME send output to printer NAME\n\
+ -d send output to the default printer\n\
+ (this is the default behavior)\n"));
+
+ sputc ('\n');
+ sfputs (_("PostScript:\n"));
+ sfputs (_("\
+ --prologue=FILE include FILE.pro as PostScript prologue\n\
+ --ppd[=KEY] automatic PPD selection or set to KEY\n\
+ -n, --copies=NUM print NUM copies of each page\n\
+ -s, --sides=MODE set the duplex MODE (`1' or `simplex',\n\
+ `2' or `duplex', `tumble')\n\
+ -S, --setpagedevice=K[:V] pass a page device definition to output\n\
+ --statusdict=K[:[:]V] pass a statusdict definition to the output\n\
+ -k, --page-prefeed enable page prefeed\n\
+ -K, --no-page-prefeed disable page prefeed\n"));
+
+
+ /* A short documentation. */
+ sputc ('\n');
+ sfputs (_("\
+By default a2ps is tuned to do what you want to, so trust it. To pretty\n\
+print the content of the `src' directory and a table of content, and send the\n\
+result to the printer `lw',\n\
+\n\
+ $ a2ps -P lw --toc src/*\n\
+\n\
+To process the files `sample.ps' and `sample.html' and display the result,\n\
+\n\
+ $ a2ps -P display sample.ps sample.html\n\
+\n\
+To process a mailbox in 4 up,\n\
+\n\
+ $ a2ps -=mail -4 mailbox\n\
+\n\
+To print as a booklet on the default printer, which is Duplex capable,\n\
+\n\
+ $ a2ps -=book paper.dvi.gz -d\n"));
+
+ /* Finally, some addresses. */
+ sputc ('\n');
+ sfputs (_("\
+News, updates and documentation: visit http://www.gnu.org/software/a2ps/.\n"));
+ sfputs (_("Report bugs to <bug-a2ps@gnu.org>.\n"));
+
+ exit (status);
+}
+
+
+/*----------------------------------------------------------------.
+| Handle the options that a2ps understands (not liba2ps) Return 1 |
+| for success |
+`----------------------------------------------------------------*/
+
+static int
+handle_a2ps_option (int option, char *optional_arg)
+{
+ switch (option)
+ {
+ case 'E': /* --pretty-print select language */
+ xstrcpy (style_request, optional_arg);
+ break;
+
+ case 'g': /* Symbol translation */
+ highlight_level = 2;
+ break;
+
+ case 154: /* Symbol translation */
+ highlight_level =
+ a2ps_get_bool ("--graphic-symbols", optional_arg);
+ break;
+
+ case 173: /* Level of high lighting */
+ highlight_level =
+ get_highlight_level ("--highlight-level", optional_arg);
+ break;
+
+ case 'h': /* --help */
+ behavior = b_help;
+ break;
+
+ case 'V': /* version and configuration info */
+ behavior = b_version;
+ break;
+
+ case 'Z': /* --delegate */
+ delegate_p = true;
+ break;
+
+ case 138:
+ behavior = b_guess;
+ break;
+
+ case 137:
+ behavior = b_which;
+ break;
+
+ case 150:
+ behavior = b_glob;
+ break;
+
+ case 139:
+ behavior = b_list_options;
+ break;
+
+ case 145:
+ ARGMATCH_ASSERT (behavior_args, behavior_types);
+ behavior = XARGCASEMATCH ("--list", optional_arg,
+ behavior_args, behavior_types);
+ break;
+
+ case 148: /* --strip-level */
+ strip_level =
+ get_integer_in_range ("--strip-level", optional_arg,
+ 0, 3, range_min_max);
+ break;
+
+ case 160: /* --delegate=BOOL */
+ delegate_p = a2ps_get_bool ("--delegate", optional_arg);
+ break;
+
+ case 161: /* --list-media */
+ behavior = b_list_media;
+ break;
+
+ case 162: /* --list-style-sheets */
+ behavior = b_list_style_sheets;
+ break;
+
+ case 167: /* --toc[=toc format] */
+ /* If no argument is given, use #{toc}. */
+ xustrcpy (toc, optional_arg ? optional_arg : "#{toc}");
+ break;
+
+ case 169: /* --end-of-line=TYPE */
+ end_of_line = option_string_to_eol ("--end-of-line", optional_arg);
+ break;
+
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+/************************************************************************/
+/* Main routine for this program. */
+/************************************************************************/
+int
+main (int argc, char *argv[])
+{
+ int argn;
+
+ /* Architecture specific initialization. */
+#ifdef __EMX__
+ /* Wildcard expansion for OS/2 */
+ _wildcard (&argc, &argv);
+#endif
+
+ /* Name under which this program was called. */
+ program_name = base_name (argv[0]);
+ program_invocation_name = xstrdup (program_name);
+ version_etc_copyright = N_("\
+Copyright (c) 1988-1993 Miguel Santana\n\
+Copyright (c) 1995-2000 Akim Demaille, Miguel Santana\n\
+Copyright (c) 2007- Akim Demaille, Miguel Santana and Masayuki Hatta");
+
+ /* Set the NLS on */
+ setlocale (LC_TIME, "");
+#ifdef HAVE_LC_MESSAGES
+ setlocale (LC_MESSAGES, "");
+#endif
+ setlocale (LC_CTYPE, "");
+
+ bindtextdomain (PACKAGE, LOCALEDIR);
+ textdomain (PACKAGE);
+
+ /* People don't want initializations when they just request a --help
+ or --version. */
+ parse_long_options (argc, argv,
+ NULL, GNU_PACKAGE, VERSION,
+ "Akim Demaille, Miguel Santana",
+ usage);
+
+ /* Catch the exits and signals to cleanup the mess.
+
+ We do it now, though there is no tmp files before long, because I
+ find it beautiful to see `received signal blah blah' even if it
+ is even before a2ps could make a move. */
+ atexit (exit_handler);
+ signame_init ();
+#define signal_set(Sig, Handler) \
+ do { \
+ if (signal (Sig, Handler) == SIG_IGN) \
+ signal (Sig, SIG_IGN); \
+ } while (0)
+ /* There are warnings on Solaris. This is due to their definition
+ of SIG_IGN as `(void (*)())1'. Please ignore ;) */
+ signal_set (SIGINT, signal_handler);
+#ifdef SIGHUP
+ signal_set (SIGHUP, signal_handler);
+#endif
+ signal_set (SIGTERM, signal_handler);
+#ifdef SIGPIPE
+ signal (SIGPIPE, signal_handler);
+#endif
+
+ /* Hooks for reading the config files */
+ delegation_hook = add_delegation;
+
+ /* Hook when reading the options */
+ handle_option_hook = handle_a2ps_option;
+
+ /* Prepare to receive in the hash table of the delegations */
+ delegation_table = delegation_table_new ();
+
+ /* Set the syntax that has be chosen for regexp */
+ re_set_syntax (RE_SYNTAX_A2PS);
+
+ /* The spine of a2ps */
+ job = a2ps_job_new ();
+
+ /* System's config. */
+ a2_read_sys_config (job);
+
+ /* Personal config.: only when installed, because there may be
+ incompatibilities between config files versions. */
+ if (!getenv ("NO_HOME_CONF"))
+ /* Home's */
+ a2_read_config (job,
+ macro_meta_sequence_get (job, VAR_USER_HOME),
+ ".a2ps/a2psrc");
+
+ /* Local config. */
+ a2_read_config (job, ".", ".a2psrc");
+
+ /* Prepare the sheets map structure and the hash table that receives
+ yet read sheets. */
+ sheets_map = sheets_map_new ();
+ style_sheets = new_style_sheets ();
+
+ /* Process the command line options. */
+ argn = a2ps_handle_options (job, argc, argv);
+
+ /* Once a2ps.cfg is read, finish the building of a2ps_job */
+ a2ps_job_finalize (job);
+
+ /* If we are debugging, then install a hook called after having
+ generated the PostScript comments. */
+ if (job->debug)
+ ps_comment_hook = spy_user;
+
+ /* Attach the arguments to the JOB */
+ job->argv = argv;
+ job->argc = argc;
+
+ switch (behavior)
+ {
+ case b_guess:
+ /* Act like file(1) does: report guessed ssh key */
+ if (argn < argc)
+ for (; argn < argc; argn++)
+ guess ((uchar *) argv[argn]);
+ else
+ /* A guess is asked upon stdin */
+ guess (UNULL);
+ break;
+
+ /* FIXME: for expand, which, and glob, should we give an error
+ when no arguments are given? */
+
+ case b_expand:
+ /* Expand the strings given as arguments. */
+ for (; argn < argc; argn++)
+ {
+ fputs (expand_user_string (job, FIRST_FILE (job),
+ "--list=expand", (uchar *) argv[argn]),
+ stdout);
+ putc ('\n', stdout);
+ }
+ break;
+
+ case b_which:
+ /* Look for the arguments in the library, and report the full
+ paths. */
+ for (; argn < argc; argn++)
+ {
+ char *cp;
+ cp = pw_find_file (job->common.path, (uchar *) argv[argn], NULL);
+ if (cp)
+ {
+ fputs (cp, stdout);
+ putc ('\n', stdout);
+ }
+ }
+ break;
+
+ case b_glob:
+ /* Glob the arguments in the library, and report the full
+ paths. */
+ for (; argn < argc; argn++)
+ pw_glob_print (job->common.path, (uchar *) argv[argn], stdout);
+ break;
+
+ case b_version:
+ version_etc (stdout, NULL, GNU_PACKAGE, VERSION,
+ "Akim Demaille, Miguel Santana");
+ break;
+
+ case b_help:
+ usage (0);
+ break;
+
+ case b_list_options:
+ list_options (job, stdout);
+ break;
+
+ case b_list_features:
+ list_features (job, stdout);
+ break;
+
+ case b_list_media:
+ list_media_long (job, stdout);
+ break;
+
+ case b_list_style_sheets:
+ list_style_sheets_long (stdout);
+ break;
+
+ case b_list_html_style_sheets:
+ /* This is done to ease the update of a2ps' web page */
+ list_style_sheets_html (stdout);
+ break;
+
+ case b_list_texinfo_style_sheets:
+ /* This is done to ease the update of a2ps' Texinfo doc */
+ list_style_sheets_texinfo (stdout);
+ break;
+
+ case b_list_printers:
+ a2ps_printers_list_long (job, stdout);
+ break;
+
+ case b_list_delegations:
+ delegations_list_long (delegation_table, stdout);
+ break;
+
+ case b_list_macro_meta_sequences:
+ macro_meta_sequences_list_long (job, stdout);
+ break;
+
+ case b_list_encodings:
+ list_encodings_long (job, stdout);
+ break;
+
+ case b_list_texinfo_encodings:
+ list_texinfo_encodings_long (job, stdout);
+ break;
+
+ case b_list_user_options:
+ user_options_list_long (job, stdout);
+ break;
+
+ case b_list_prologues:
+ prologues_list_long (job, stdout);
+ break;
+
+ case b_list_texinfo_prologues:
+ prologues_list_texinfo (job, stdout);
+ break;
+
+ case b_list_ppd:
+ /* Report PPD files */
+ a2ps_ppd_list_long (job, stdout);
+ break;
+
+ /*
+ * Text to PostScript generator
+ */
+ case b_ps:
+ {
+ /* Count the number of jobs done */
+ int delegated_jobs = 0, native_jobs = 0;
+
+ a2ps_open_output_session (job);
+
+ if (argn == argc) /* Print stdin */
+ print (UNULL, &native_jobs, &delegated_jobs);
+ else /* Print following files */
+ for (; argn < argc; argn++)
+ print ((uchar *) argv[argn], &native_jobs, &delegated_jobs);
+
+ if (!IS_EMPTY (toc))
+ print_toc ((uchar *) _("Table of Content"), toc, &native_jobs);
+
+ if ((native_jobs == 0) && (delegated_jobs == 1))
+ {
+ /* a2ps has only been used to delegate a single job.
+ * Hence its prologue is superfluous */
+ /* FIXME: if there were other files but which failed,
+ * then there is _no_reason_ that the file we're interested
+ * in is this one!
+ * To this end, we need to put more information in file_job
+ * on how its processing went. */
+
+ struct file_job * file_job;
+ size_t len;
+
+ /* 'delegation_tmpname' is necessary not null else it is a
+ failed job and we ignore it */
+ file_job = CURRENT_FILE (job);
+ len = job->jobs->len;
+ while (!file_job->delegation_tmpname)
+ {
+ len--;
+ file_job = job->jobs->content[len - 1];
+ }
+
+ a2ps_open_output_stream (job);
+ pslex_dump (job->output_stream->fp, file_job->delegation_tmpname);
+ unlink (file_job->delegation_tmpname);
+ a2ps_close_output_stream (job);
+ msg_job_pages_printed (job);
+ }
+ else if (native_jobs || delegated_jobs)
+ {
+ /* The whole stuff is needed */
+ a2ps_close_output_session (job);
+ msg_job_pages_printed (job);
+ }
+ else
+ {
+ /* Nothing has been printed.
+ * Don't close the job, so that nothing is sent to the printer,
+ * not even the PS prologue */
+ msg_nothing_printed ();
+ }
+ }
+ break;
+
+ default:
+ /* A case has not been recognized. */
+ abort ();
+ }
+
+ a2ps_job_free (job);
+ job = NULL;
+
+ return (EXIT_SUCCESS);
+}
diff --git a/src/main.h b/src/main.h
new file mode 100644
index 0000000..8536bf4
--- /dev/null
+++ b/src/main.h
@@ -0,0 +1,79 @@
+/*
+ * main.h -- Common definitions for a2ps the program
+ *
+ * Copyright (c) 1988, 89, 90, 91, 92, 93 Miguel Santana
+ * Copyright (c) 1995, 96, 97, 98 Akim Demaille, Miguel Santana
+ *
+ */
+
+/*
+ * This file is part of a2ps.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * $Id: main.h,v 1.1.1.1.2.1 2007/12/29 01:58:35 mhatta Exp $
+ */
+
+#ifndef _MAIN_H_
+#define _MAIN_H_
+
+#include "system.h"
+#include "darray.h"
+#include "hashtab.h"
+#include "message.h"
+#include "quotearg.h"
+
+#include "jobs.h"
+#include "fjobs.h"
+#include "generate.h"
+#include "psgen.h"
+#include "sshread.h"
+#include "read.h"
+#include "routines.h"
+#include "select.h"
+#include "delegate.h"
+#include "gen.h"
+#include "printers.h"
+#include "metaseq.h"
+
+/* Defined in main.c. */
+
+extern struct hash_table_s * files;
+
+/* --stdin=NAME name of the file given by stdin */
+extern uchar * stdin_filename;
+
+extern struct a2ps_job * job;
+
+/* Shall we delegate */
+extern bool delegate_p;
+
+/* Highlighting model */
+extern int highlight_level;
+
+/* Requested style sheet */
+extern char *style_request;
+
+/* Type of eol. */
+extern enum eol_e end_of_line;
+
+/* Defined in generate.c. */
+
+/* The file in which samples of files are put. */
+extern char *sample_tmpname;
+#endif /* !defined(_MAIN_H_) */
diff --git a/src/parsessh.c b/src/parsessh.c
new file mode 100644
index 0000000..a303027
--- /dev/null
+++ b/src/parsessh.c
@@ -0,0 +1,2704 @@
+/* A Bison parser, made by GNU Bison 2.3. */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program 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, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Bison version. */
+#define YYBISON_VERSION "2.3"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 0
+
+/* Using locations. */
+#define YYLSP_NEEDED 0
+
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ tSTYLE = 258,
+ tIS = 259,
+ tEND = 260,
+ tKEYWORDS = 261,
+ tARE = 262,
+ tIN = 263,
+ tOPERATORS = 264,
+ tSEQUENCES = 265,
+ tFIRST = 266,
+ tSECOND = 267,
+ tALPHABET = 268,
+ tALPHABETS = 269,
+ tDOCUMENTATION = 270,
+ tEXCEPTIONS = 271,
+ tCASE = 272,
+ tCSTRING = 273,
+ tCCHAR = 274,
+ tOPTIONAL = 275,
+ tCLOSERS = 276,
+ tWRITTEN = 277,
+ tBY = 278,
+ tVERSION = 279,
+ tREQUIRES = 280,
+ tA2PS = 281,
+ tANCESTORS = 282,
+ tFACE = 283,
+ tFFLAGS = 284,
+ tSTRING = 285,
+ tLATEXSYMBOL = 286,
+ tREGEX = 287,
+ tSENSITIVENESS = 288,
+ tBACK_REF = 289
+ };
+#endif
+/* Tokens. */
+#define tSTYLE 258
+#define tIS 259
+#define tEND 260
+#define tKEYWORDS 261
+#define tARE 262
+#define tIN 263
+#define tOPERATORS 264
+#define tSEQUENCES 265
+#define tFIRST 266
+#define tSECOND 267
+#define tALPHABET 268
+#define tALPHABETS 269
+#define tDOCUMENTATION 270
+#define tEXCEPTIONS 271
+#define tCASE 272
+#define tCSTRING 273
+#define tCCHAR 274
+#define tOPTIONAL 275
+#define tCLOSERS 276
+#define tWRITTEN 277
+#define tBY 278
+#define tVERSION 279
+#define tREQUIRES 280
+#define tA2PS 281
+#define tANCESTORS 282
+#define tFACE 283
+#define tFFLAGS 284
+#define tSTRING 285
+#define tLATEXSYMBOL 286
+#define tREGEX 287
+#define tSENSITIVENESS 288
+#define tBACK_REF 289
+
+
+
+
+/* Copy the first part of user declarations. */
+#line 1 "parsessh.y"
+ /* -*- c -*- */
+/*
+ * Grammar for parsing the style sheets
+ *
+ * Copyright (c) 1988-1993 Miguel Santana
+ * Copyright (c) 1995-1999 Akim Demaille, Miguel Santana
+ *
+ */
+
+/*
+ * This file is part of a2ps
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * $Id: parsessh.y,v 1.1.1.1.2.2 2007/12/29 01:58:35 mhatta Exp $
+ */
+
+#include "a2ps.h"
+#include "jobs.h"
+#include "ffaces.h"
+#include "ssheet.h"
+#include "message.h"
+#include "routines.h"
+#include "yy2ssh.h"
+#include "regex.h"
+
+#define YYDEBUG 1
+#define YYERROR_VERBOSE 1
+#define YYPRINT(file, type, value) yyprint (file, type, value)
+
+/* We need to use the same `const' as bison, to avoid the following
+ prototypes to diverge from the function declarations */
+#undef const
+#ifndef __cplusplus
+# ifndef __STDC__
+# define const
+# endif
+#endif
+
+/* Comes from the parser */
+extern int sshlineno;
+
+/* Comes from the caller */
+extern FILE * sshin;
+extern struct a2ps_job * job;
+extern const char * sshfilename;
+
+/* Local prototypes */
+void yyerror PARAMS ((const char *msg));
+static void yyprint ();
+
+/* Initilizes the obstacks */
+void sshlex_initialize PARAMS ((void));
+
+/* Comes from main.c */
+extern int highlight_level;
+
+int yylex PARAMS ((void));
+struct style_sheet * parse_style_sheet PARAMS ((const char * filename));
+
+/* Defines the style sheet being loaded */
+static struct style_sheet * parsed_style_sheet = NULL;
+
+
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 1
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table. */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+#line 81 "parsessh.y"
+{
+ int integer;
+ uchar * string;
+ struct pattern * pattern;
+ struct style_sheet * sheet;
+ struct rule * rule;
+ struct sequence * sequence;
+ struct darray * array;
+ struct words * words;
+ struct faced_string * faced_string;
+ enum face_e face; /* Face */
+ enum fflag_e fflags; /* Flags for faces */
+ struct fface_s fface; /* Flagged face */
+ enum case_sensitiveness sensitiveness;
+}
+/* Line 187 of yacc.c. */
+#line 260 "parsessh.c"
+ YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+
+
+/* Copy the second part of user declarations. */
+
+
+/* Line 216 of yacc.c. */
+#line 273 "parsessh.c"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_(msgid) dgettext ("bison-runtime", msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions. */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int i)
+#else
+static int
+YYID (i)
+ int i;
+#endif
+{
+ return i;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
+# else
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+# endif
+# else
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined _STDLIB_H \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ yytype_int16 yyss;
+ YYSTYPE yyvs;
+ };
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (YYID (0))
+# endif
+# endif
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack, Stack, yysize); \
+ Stack = &yyptr->Stack; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 5
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 218
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 39
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 30
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 92
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 200
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 289
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+static const yytype_uint8 yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 36, 37, 2, 38, 35, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+ YYRHS. */
+static const yytype_uint16 yyprhs[] =
+{
+ 0, 0, 3, 5, 12, 13, 19, 24, 30, 35,
+ 39, 42, 45, 50, 56, 62, 65, 68, 71, 74,
+ 77, 81, 86, 92, 94, 97, 101, 105, 108, 114,
+ 116, 120, 123, 125, 128, 130, 133, 135, 137, 140,
+ 142, 144, 146, 150, 152, 154, 158, 160, 162, 166,
+ 170, 173, 175, 180, 186, 190, 192, 194, 198, 202,
+ 205, 207, 212, 218, 222, 224, 226, 230, 234, 237,
+ 239, 244, 250, 252, 256, 262, 269, 275, 281, 286,
+ 293, 299, 305, 310, 318, 326, 328, 330, 331, 333,
+ 335, 339, 340
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yytype_int8 yyrhs[] =
+{
+ 40, 0, -1, 41, -1, 3, 30, 4, 42, 5,
+ 3, -1, -1, 42, 20, 6, 58, 6, -1, 42,
+ 6, 58, 6, -1, 42, 20, 9, 61, 9, -1,
+ 42, 9, 61, 9, -1, 42, 20, 64, -1, 42,
+ 64, -1, 42, 48, -1, 42, 14, 7, 30, -1,
+ 42, 11, 13, 4, 30, -1, 42, 12, 13, 4,
+ 30, -1, 42, 50, -1, 42, 44, -1, 42, 46,
+ -1, 42, 47, -1, 42, 43, -1, 25, 26, 30,
+ -1, 25, 26, 24, 30, -1, 15, 4, 45, 5,
+ 15, -1, 30, -1, 45, 30, -1, 22, 23, 30,
+ -1, 24, 4, 30, -1, 24, 30, -1, 27, 7,
+ 49, 5, 27, -1, 30, -1, 49, 35, 30, -1,
+ 17, 33, -1, 32, -1, 51, 32, -1, 53, -1,
+ 30, 55, -1, 30, -1, 55, -1, 34, 55, -1,
+ 34, -1, 31, -1, 53, -1, 54, 35, 53, -1,
+ 28, -1, 29, -1, 36, 56, 37, -1, 28, -1,
+ 29, -1, 56, 38, 28, -1, 56, 38, 29, -1,
+ 30, 52, -1, 30, -1, 36, 30, 54, 37, -1,
+ 8, 55, 7, 59, 5, -1, 7, 59, 5, -1,
+ 57, -1, 60, -1, 59, 35, 57, -1, 59, 35,
+ 60, -1, 51, 52, -1, 51, -1, 36, 51, 54,
+ 37, -1, 8, 55, 7, 62, 5, -1, 7, 62,
+ 5, -1, 57, -1, 63, -1, 62, 35, 57, -1,
+ 62, 35, 63, -1, 51, 52, -1, 51, -1, 36,
+ 51, 54, 37, -1, 10, 7, 65, 5, 10, -1,
+ 66, -1, 65, 35, 66, -1, 30, 31, 55, 67,
+ 68, -1, 30, 30, 55, 55, 67, 68, -1, 30,
+ 55, 55, 67, 68, -1, 30, 30, 55, 67, 68,
+ -1, 30, 55, 67, 68, -1, 51, 30, 55, 55,
+ 67, 68, -1, 51, 55, 55, 67, 68, -1, 51,
+ 30, 55, 67, 68, -1, 51, 55, 67, 68, -1,
+ 36, 30, 54, 37, 55, 67, 68, -1, 36, 51,
+ 54, 37, 55, 67, 68, -1, 18, -1, 19, -1,
+ -1, 57, -1, 63, -1, 21, 61, 21, -1, -1,
+ 16, 61, 16, -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const yytype_uint16 yyrline[] =
+{
+ 0, 129, 129, 136, 145, 148, 157, 163, 172, 178,
+ 186, 191, 196, 204, 211, 218, 221, 224, 227, 230,
+ 245, 246, 249, 251, 252, 267, 270, 271, 276, 283,
+ 291, 298, 306, 310, 322, 330, 334, 338, 342, 346,
+ 350, 357, 363, 374, 379, 386, 396, 401, 406, 412,
+ 426, 431, 437, 449, 453, 460, 465, 470, 475, 487,
+ 492, 499, 509, 513, 520, 526, 532, 537, 549, 554,
+ 560, 570, 573, 579, 602, 610, 618, 626, 634, 642,
+ 650, 658, 666, 674, 681, 689, 693, 701, 709, 715,
+ 721, 730, 733
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "tSTYLE", "tIS", "tEND", "tKEYWORDS",
+ "tARE", "tIN", "tOPERATORS", "tSEQUENCES", "tFIRST", "tSECOND",
+ "tALPHABET", "tALPHABETS", "tDOCUMENTATION", "tEXCEPTIONS", "tCASE",
+ "tCSTRING", "tCCHAR", "tOPTIONAL", "tCLOSERS", "tWRITTEN", "tBY",
+ "tVERSION", "tREQUIRES", "tA2PS", "tANCESTORS", "tFACE", "tFFLAGS",
+ "tSTRING", "tLATEXSYMBOL", "tREGEX", "tSENSITIVENESS", "tBACK_REF",
+ "','", "'('", "')'", "'+'", "$accept", "file", "style_sheet",
+ "definition_list", "requirement", "documentation", "long_string",
+ "authors", "version", "ancestors_def", "ancestors_list", "case_def",
+ "regex", "rhs", "a_rhs", "rhs_list", "fface", "fface_sxp", "rule",
+ "keywords_def", "keywords_rule_list", "keyword_regex", "operators_def",
+ "operators_rule_list", "operator_regex", "sequence_def", "sequence_list",
+ "sequence", "closers_opt", "exception_def_opt", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+ token YYLEX-NUM. */
+static const yytype_uint16 yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
+ 285, 286, 287, 288, 289, 44, 40, 41, 43
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint8 yyr1[] =
+{
+ 0, 39, 40, 41, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 43, 43, 44, 45, 45, 46, 47, 47, 48, 49,
+ 49, 50, 51, 51, 52, 53, 53, 53, 53, 53,
+ 53, 54, 54, 55, 55, 55, 56, 56, 56, 56,
+ 57, 57, 57, 58, 58, 59, 59, 59, 59, 60,
+ 60, 60, 61, 61, 62, 62, 62, 62, 63, 63,
+ 63, 64, 65, 65, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 67, 67, 67,
+ 67, 68, 68
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 1, 6, 0, 5, 4, 5, 4, 3,
+ 2, 2, 4, 5, 5, 2, 2, 2, 2, 2,
+ 3, 4, 5, 1, 2, 3, 3, 2, 5, 1,
+ 3, 2, 1, 2, 1, 2, 1, 1, 2, 1,
+ 1, 1, 3, 1, 1, 3, 1, 1, 3, 3,
+ 2, 1, 4, 5, 3, 1, 1, 3, 3, 2,
+ 1, 4, 5, 3, 1, 1, 3, 3, 2, 1,
+ 4, 5, 1, 3, 5, 6, 5, 5, 4, 6,
+ 5, 5, 4, 7, 7, 1, 1, 0, 1, 1,
+ 3, 0, 3
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint8 yydefact[] =
+{
+ 0, 0, 0, 2, 0, 1, 4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 19, 16, 17, 18, 11, 15, 10, 3,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 31, 0, 0, 9, 0, 0, 27, 0, 0,
+ 51, 32, 0, 60, 55, 0, 56, 43, 44, 0,
+ 0, 6, 0, 69, 64, 0, 65, 0, 8, 85,
+ 86, 0, 0, 0, 0, 72, 0, 0, 12, 23,
+ 0, 0, 0, 25, 26, 0, 20, 29, 0, 36,
+ 40, 39, 50, 34, 37, 0, 0, 33, 59, 54,
+ 0, 46, 47, 0, 0, 0, 68, 63, 0, 0,
+ 0, 0, 87, 0, 0, 0, 87, 0, 0, 13,
+ 14, 0, 24, 5, 7, 21, 0, 0, 35, 38,
+ 41, 0, 0, 57, 58, 45, 0, 0, 0, 66,
+ 67, 0, 87, 87, 0, 0, 87, 88, 89, 91,
+ 0, 0, 87, 87, 91, 71, 73, 22, 28, 30,
+ 0, 52, 61, 48, 49, 53, 70, 62, 87, 91,
+ 91, 0, 91, 0, 78, 0, 0, 87, 91, 91,
+ 82, 42, 91, 77, 74, 90, 76, 0, 87, 87,
+ 91, 81, 80, 75, 92, 91, 91, 79, 83, 84
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int16 yydefgoto[] =
+{
+ -1, 2, 3, 7, 22, 23, 80, 24, 25, 26,
+ 88, 27, 63, 92, 130, 131, 94, 103, 147, 32,
+ 55, 56, 35, 65, 148, 28, 74, 75, 149, 174
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+#define YYPACT_NINF -150
+static const yytype_int16 yypact[] =
+{
+ 11, -2, 31, -150, 39, -150, -150, 98, 66, 126,
+ 183, 56, 62, 65, 75, 91, 40, 175, 77, 7,
+ 80, 109, -150, -150, -150, -150, -150, -150, -150, -150,
+ 69, 60, 132, 94, 60, 133, 35, 131, 142, 140,
+ 167, -150, 126, 183, -150, 168, 169, -150, 8, 170,
+ 129, -150, 18, 120, -150, 1, -150, -150, -150, 154,
+ 189, -150, 18, 120, -150, 4, -150, 194, -150, -150,
+ -150, 138, 34, 143, 10, -150, 172, 173, -150, -150,
+ 5, 198, 196, -150, -150, 176, -150, -150, 14, 60,
+ -150, 60, -150, -150, -150, 129, 120, -150, -150, -150,
+ 69, -150, -150, 155, 69, 120, -150, -150, 94, 94,
+ 60, 60, 111, 129, 120, 60, 111, 197, 35, -150,
+ -150, 146, -150, -150, -150, -150, 181, 179, -150, -150,
+ -150, 92, 118, -150, -150, -150, 166, 21, 127, -150,
+ -150, 22, 111, 38, 183, 148, 38, -150, -150, 195,
+ 151, 152, 111, 38, 195, -150, -150, -150, -150, -150,
+ 129, -150, -150, -150, -150, -150, -150, -150, 38, 195,
+ 195, 191, 195, 183, -150, 60, 60, 38, 195, 195,
+ -150, -150, 195, -150, -150, -150, -150, 199, 38, 38,
+ 195, -150, -150, -150, -150, 195, 195, -150, -150, -150
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const yytype_int16 yypgoto[] =
+{
+ -150, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+ -150, -150, -28, -41, -46, 23, -31, -150, -17, 171,
+ 106, 114, -42, 107, -15, 200, -150, 100, -91, -149
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule which
+ number is the opposite. If zero, do what YYDEFACT says.
+ If YYTABLE_NINF, syntax error. */
+#define YYTABLE_NINF -1
+static const yytype_uint8 yytable[] =
+{
+ 60, 82, 53, 67, 93, 180, 99, 93, 73, 107,
+ 121, 46, 98, 54, 1, 117, 64, 93, 66, 126,
+ 183, 184, 106, 186, 96, 154, 165, 167, 4, 191,
+ 192, 5, 85, 193, 105, 122, 100, 47, 86, 108,
+ 112, 197, 116, 6, 114, 118, 198, 199, 95, 127,
+ 51, 169, 170, 69, 70, 172, 100, 108, 128, 144,
+ 129, 178, 179, 36, 113, 71, 51, 51, 50, 29,
+ 51, 72, 53, 41, 62, 37, 53, 182, 38, 142,
+ 143, 146, 39, 133, 152, 153, 190, 54, 57, 58,
+ 73, 139, 64, 140, 66, 40, 59, 195, 196, 50,
+ 45, 51, 171, 8, 9, 52, 48, 10, 11, 12,
+ 13, 168, 14, 15, 181, 16, 49, 105, 17, 132,
+ 18, 177, 19, 20, 50, 21, 51, 160, 138, 161,
+ 62, 187, 144, 30, 31, 76, 150, 151, 61, 57,
+ 58, 50, 68, 51, 188, 189, 77, 145, 57, 58,
+ 89, 90, 97, 160, 91, 162, 59, 57, 58, 89,
+ 90, 157, 160, 91, 166, 59, 57, 58, 110, 111,
+ 78, 57, 58, 115, 59, 97, 101, 102, 95, 59,
+ 51, 42, 101, 102, 43, 11, 160, 160, 175, 176,
+ 33, 34, 135, 136, 163, 164, 104, 79, 83, 84,
+ 87, 109, 119, 120, 123, 124, 125, 155, 158, 159,
+ 137, 173, 185, 81, 134, 194, 141, 44, 156
+};
+
+static const yytype_uint8 yycheck[] =
+{
+ 31, 43, 30, 34, 50, 154, 5, 53, 36, 5,
+ 5, 4, 53, 30, 3, 5, 33, 63, 33, 5,
+ 169, 170, 63, 172, 52, 116, 5, 5, 30, 178,
+ 179, 0, 24, 182, 62, 30, 35, 30, 30, 35,
+ 71, 190, 73, 4, 72, 35, 195, 196, 30, 35,
+ 32, 142, 143, 18, 19, 146, 35, 35, 89, 21,
+ 91, 152, 153, 7, 30, 30, 32, 32, 30, 3,
+ 32, 36, 100, 33, 36, 13, 104, 168, 13, 110,
+ 111, 112, 7, 100, 115, 116, 177, 104, 28, 29,
+ 118, 108, 109, 108, 109, 4, 36, 188, 189, 30,
+ 23, 32, 144, 5, 6, 36, 26, 9, 10, 11,
+ 12, 142, 14, 15, 160, 17, 7, 145, 20, 96,
+ 22, 152, 24, 25, 30, 27, 32, 35, 105, 37,
+ 36, 173, 21, 7, 8, 4, 113, 114, 6, 28,
+ 29, 30, 9, 32, 175, 176, 4, 36, 28, 29,
+ 30, 31, 32, 35, 34, 37, 36, 28, 29, 30,
+ 31, 15, 35, 34, 37, 36, 28, 29, 30, 31,
+ 30, 28, 29, 30, 36, 32, 28, 29, 30, 36,
+ 32, 6, 28, 29, 9, 10, 35, 35, 37, 37,
+ 7, 8, 37, 38, 28, 29, 7, 30, 30, 30,
+ 30, 7, 30, 30, 6, 9, 30, 10, 27, 30,
+ 104, 16, 21, 42, 100, 16, 109, 17, 118
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const yytype_uint8 yystos[] =
+{
+ 0, 3, 40, 41, 30, 0, 4, 42, 5, 6,
+ 9, 10, 11, 12, 14, 15, 17, 20, 22, 24,
+ 25, 27, 43, 44, 46, 47, 48, 50, 64, 3,
+ 7, 8, 58, 7, 8, 61, 7, 13, 13, 7,
+ 4, 33, 6, 9, 64, 23, 4, 30, 26, 7,
+ 30, 32, 36, 51, 57, 59, 60, 28, 29, 36,
+ 55, 6, 36, 51, 57, 62, 63, 55, 9, 18,
+ 19, 30, 36, 51, 65, 66, 4, 4, 30, 30,
+ 45, 58, 61, 30, 30, 24, 30, 30, 49, 30,
+ 31, 34, 52, 53, 55, 30, 51, 32, 52, 5,
+ 35, 28, 29, 56, 7, 51, 52, 5, 35, 7,
+ 30, 31, 55, 30, 51, 30, 55, 5, 35, 30,
+ 30, 5, 30, 6, 9, 30, 5, 35, 55, 55,
+ 53, 54, 54, 57, 60, 37, 38, 59, 54, 57,
+ 63, 62, 55, 55, 21, 36, 55, 57, 63, 67,
+ 54, 54, 55, 55, 67, 10, 66, 15, 27, 30,
+ 35, 37, 37, 28, 29, 5, 37, 5, 55, 67,
+ 67, 61, 67, 16, 68, 37, 37, 55, 67, 67,
+ 68, 53, 67, 68, 68, 21, 68, 61, 55, 55,
+ 67, 68, 68, 68, 16, 67, 67, 68, 68, 68
+};
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror. This remains here temporarily
+ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+
+#define YYFAIL goto yyerrlab
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK (1); \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+while (YYID (0))
+
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+ If N is 0, then set CURRENT to the empty location which ends
+ the previous symbol: RHS[0] (always defined). */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (YYID (N)) \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ } \
+ while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+ This macro was not mandated originally: define only if we know
+ we won't break user code: when these are the locations we know. */
+
+#ifndef YY_LOCATION_PRINT
+# if YYLTYPE_IS_TRIVIAL
+# define YY_LOCATION_PRINT(File, Loc) \
+ fprintf (File, "%d.%d-%d.%d", \
+ (Loc).first_line, (Loc).first_column, \
+ (Loc).last_line, (Loc).last_column)
+# else
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments. */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (YYLEX_PARAM)
+#else
+# define YYLEX yylex ()
+#endif
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+#endif
+{
+ if (!yyvaluep)
+ return;
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+ YYUSE (yyoutput);
+# endif
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+#endif
+{
+ if (yytype < YYNTOKENS)
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep);
+ YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
+#else
+static void
+yy_stack_print (bottom, top)
+ yytype_int16 *bottom;
+ yytype_int16 *top;
+#endif
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (; bottom <= top; ++bottom)
+ YYFPRINTF (stderr, " %d", *bottom);
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
+#else
+static void
+yy_reduce_print (yyvsp, yyrule)
+ YYSTYPE *yyvsp;
+ int yyrule;
+#endif
+{
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+ unsigned long int yylno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ fprintf (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ );
+ fprintf (stderr, "\n");
+ }
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyvsp, Rule); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+ const char *yystr;
+#endif
+{
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
+ continue;
+ return yylen;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+ char *yydest;
+ const char *yysrc;
+#endif
+{
+ char *yyd = yydest;
+ const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+ if (*yystr == '"')
+ {
+ YYSIZE_T yyn = 0;
+ char const *yyp = yystr;
+
+ for (;;)
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ do_not_strip_quotes: ;
+ }
+
+ if (! yyres)
+ return yystrlen (yystr);
+
+ return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+ YYCHAR while in state YYSTATE. Return the number of bytes copied,
+ including the terminating null byte. If YYRESULT is null, do not
+ copy anything; just return the number of bytes that would be
+ copied. As a special case, return 0 if an ordinary "syntax error"
+ message will do. Return YYSIZE_MAXIMUM if overflow occurs during
+ size calculation. */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+ int yyn = yypact[yystate];
+
+ if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+ return 0;
+ else
+ {
+ int yytype = YYTRANSLATE (yychar);
+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+ YYSIZE_T yysize = yysize0;
+ YYSIZE_T yysize1;
+ int yysize_overflow = 0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ int yyx;
+
+# if 0
+ /* This is so xgettext sees the translatable formats that are
+ constructed on the fly. */
+ YY_("syntax error, unexpected %s");
+ YY_("syntax error, unexpected %s, expecting %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+ char *yyfmt;
+ char const *yyf;
+ static char const yyunexpected[] = "syntax error, unexpected %s";
+ static char const yyexpecting[] = ", expecting %s";
+ static char const yyor[] = " or %s";
+ char yyformat[sizeof yyunexpected
+ + sizeof yyexpecting - 1
+ + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+ * (sizeof yyor - 1))];
+ char const *yyprefix = yyexpecting;
+
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 1;
+
+ yyarg[0] = yytname[yytype];
+ yyfmt = yystpcpy (yyformat, yyunexpected);
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ yyformat[sizeof yyunexpected - 1] = '\0';
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+ yyfmt = yystpcpy (yyfmt, yyprefix);
+ yyprefix = yyor;
+ }
+
+ yyf = YY_(yyformat);
+ yysize1 = yysize + yystrlen (yyf);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+
+ if (yysize_overflow)
+ return YYSIZE_MAXIMUM;
+
+ if (yyresult)
+ {
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ char *yyp = yyresult;
+ int yyi = 0;
+ while ((*yyp = *yyf) != '\0')
+ {
+ if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyf += 2;
+ }
+ else
+ {
+ yyp++;
+ yyf++;
+ }
+ }
+ }
+ return yysize;
+ }
+}
+#endif /* YYERROR_VERBOSE */
+
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep)
+ const char *yymsg;
+ int yytype;
+ YYSTYPE *yyvaluep;
+#endif
+{
+ YYUSE (yyvaluep);
+
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+ switch (yytype)
+ {
+
+ default:
+ break;
+ }
+}
+
+
+/* Prevent warnings from -Wmissing-prototypes. */
+
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+/* The look-ahead symbol. */
+int yychar;
+
+/* The semantic value of the look-ahead symbol. */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far. */
+int yynerrs;
+
+
+
+/*----------.
+| yyparse. |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void)
+#else
+int
+yyparse ()
+
+#endif
+#endif
+{
+
+ int yystate;
+ int yyn;
+ int yyresult;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+ /* Look-ahead token as an internal (translated) token number. */
+ int yytoken = 0;
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+ /* Three stacks and their tools:
+ `yyss': related to states,
+ `yyvs': related to semantic values,
+ `yyls': related to locations.
+
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss = yyssa;
+ yytype_int16 *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs = yyvsa;
+ YYSTYPE *yyvsp;
+
+
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
+
+ YYSIZE_T yystacksize = YYINITDEPTH;
+
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+
+ yyssp = yyss;
+ yyvsp = yyvs;
+
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. So pushing a state here evens the stacks. */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;
+
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+
+ &yystacksize);
+
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyexhaustedlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss);
+ YYSTACK_RELOCATE (yyvs);
+
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+ /* Do appropriate processing given the current state. Read a
+ look-ahead token if we need one and don't already have one. */
+
+ /* First try to decide what to do without reference to look-ahead token. */
+ yyn = yypact[yystate];
+ if (yyn == YYPACT_NINF)
+ goto yydefault;
+
+ /* Not known => get a look-ahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = YYLEX;
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ /* Shift the look-ahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the shifted token unless it is eof. */
+ if (yychar != YYEOF)
+ yychar = YYEMPTY;
+
+ yystate = yyn;
+ *++yyvsp = yylval;
+
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 2:
+#line 130 "parsessh.y"
+ {
+ parsed_style_sheet = (yyvsp[(1) - (1)].sheet);
+ }
+ break;
+
+ case 3:
+#line 137 "parsessh.y"
+ {
+ (yyvsp[(4) - (6)].sheet)->name = (yyvsp[(2) - (6)].string);
+ (yyvsp[(4) - (6)].sheet)->key = "<No key yet>";
+ (yyval.sheet) = (yyvsp[(4) - (6)].sheet);
+ }
+ break;
+
+ case 4:
+#line 145 "parsessh.y"
+ {
+ (yyval.sheet) = new_style_sheet ((const uchar *) "<no name>");
+ }
+ break;
+
+ case 5:
+#line 149 "parsessh.y"
+ {
+ if (highlight_level == 2) {
+ words_set_no_face ((yyvsp[(4) - (5)].words), Plain_fface);
+ words_merge_rules_unique ((yyvsp[(1) - (5)].sheet)->keywords, (yyvsp[(4) - (5)].words));
+ } else
+ words_free ((yyvsp[(4) - (5)].words));
+ (yyval.sheet) = (yyvsp[(1) - (5)].sheet);
+ }
+ break;
+
+ case 6:
+#line 158 "parsessh.y"
+ {
+ words_set_no_face ((yyvsp[(3) - (4)].words), Plain_fface);
+ words_merge_rules_unique ((yyvsp[(1) - (4)].sheet)->keywords, (yyvsp[(3) - (4)].words));
+ (yyval.sheet) = (yyvsp[(1) - (4)].sheet);
+ }
+ break;
+
+ case 7:
+#line 164 "parsessh.y"
+ {
+ if (highlight_level == 2) {
+ words_set_no_face ((yyvsp[(4) - (5)].words), Plain_fface);
+ words_merge_rules_unique ((yyvsp[(1) - (5)].sheet)->operators, (yyvsp[(4) - (5)].words));
+ } else
+ words_free ((yyvsp[(4) - (5)].words));
+ (yyval.sheet) = (yyvsp[(1) - (5)].sheet);
+ }
+ break;
+
+ case 8:
+#line 173 "parsessh.y"
+ {
+ words_set_no_face ((yyvsp[(3) - (4)].words), Plain_fface);
+ words_merge_rules_unique ((yyvsp[(1) - (4)].sheet)->operators, (yyvsp[(3) - (4)].words));
+ (yyval.sheet) = (yyvsp[(1) - (4)].sheet);
+ }
+ break;
+
+ case 9:
+#line 178 "parsessh.y"
+ {
+ if (highlight_level == 2) {
+ da_concat ((yyvsp[(1) - (3)].sheet)->sequences, (yyvsp[(3) - (3)].array));
+ da_erase ((yyvsp[(3) - (3)].array));
+ } else
+ da_free ((yyvsp[(3) - (3)].array), (da_map_func_t) free_sequence);
+ (yyval.sheet) = (yyvsp[(1) - (3)].sheet);
+ }
+ break;
+
+ case 10:
+#line 186 "parsessh.y"
+ {
+ da_concat ((yyvsp[(1) - (2)].sheet)->sequences, (yyvsp[(2) - (2)].array));
+ da_erase ((yyvsp[(2) - (2)].array));
+ (yyval.sheet) = (yyvsp[(1) - (2)].sheet);
+ }
+ break;
+
+ case 11:
+#line 191 "parsessh.y"
+ {
+ da_concat ((yyvsp[(1) - (2)].sheet)->ancestors, (yyvsp[(2) - (2)].array));
+ da_erase ((yyvsp[(2) - (2)].array));
+ (yyval.sheet) = (yyvsp[(1) - (2)].sheet);
+ }
+ break;
+
+ case 12:
+#line 196 "parsessh.y"
+ {
+ string_to_array ((yyvsp[(1) - (4)].sheet)->alpha1, (yyvsp[(4) - (4)].string));
+ string_to_array ((yyvsp[(1) - (4)].sheet)->alpha2, (yyvsp[(4) - (4)].string));
+ /* This is the syntax table used by regex */
+ free ((yyvsp[(4) - (4)].string));
+ (yyvsp[(4) - (4)].string) = NULL;
+ (yyval.sheet) = (yyvsp[(1) - (4)].sheet);
+ }
+ break;
+
+ case 13:
+#line 204 "parsessh.y"
+ {
+ string_to_array ((yyvsp[(1) - (5)].sheet)->alpha1, (yyvsp[(5) - (5)].string));
+ /* This is the syntax table used by regex */
+ free ((yyvsp[(5) - (5)].string));
+ (yyvsp[(5) - (5)].string) = NULL;
+ (yyval.sheet) = (yyvsp[(1) - (5)].sheet);
+ }
+ break;
+
+ case 14:
+#line 211 "parsessh.y"
+ {
+ string_to_array ((yyvsp[(1) - (5)].sheet)->alpha2, (yyvsp[(5) - (5)].string));
+ /* This is the syntax table used by regex */
+ free ((yyvsp[(5) - (5)].string));
+ (yyvsp[(5) - (5)].string) = NULL;
+ (yyval.sheet) = (yyvsp[(1) - (5)].sheet);
+ }
+ break;
+
+ case 15:
+#line 218 "parsessh.y"
+ {
+ (yyvsp[(1) - (2)].sheet)->sensitiveness = (yyvsp[(2) - (2)].sensitiveness);
+ }
+ break;
+
+ case 16:
+#line 221 "parsessh.y"
+ {
+ (yyvsp[(1) - (2)].sheet)->documentation = (yyvsp[(2) - (2)].string);
+ }
+ break;
+
+ case 17:
+#line 224 "parsessh.y"
+ {
+ (yyvsp[(1) - (2)].sheet)->author = (yyvsp[(2) - (2)].string);
+ }
+ break;
+
+ case 18:
+#line 227 "parsessh.y"
+ {
+ style_sheet_set_version ((yyvsp[(1) - (2)].sheet), (const char *) (yyvsp[(2) - (2)].string));
+ }
+ break;
+
+ case 19:
+#line 230 "parsessh.y"
+ {
+ /* Make sure now that we won't encounter new tokens.
+ * This avoids nasty error messages, or worse:
+ * unexpected behavior at run time */
+ if (!style_sheet_set_requirement ((yyvsp[(1) - (2)].sheet), (const char *) (yyvsp[(2) - (2)].string)))
+ error (1, 0,
+ _("cannot process `%s' which requires a2ps version %s"),
+ sshfilename, (yyvsp[(2) - (2)].string));
+ }
+ break;
+
+ case 20:
+#line 245 "parsessh.y"
+ { (yyval.string) = (yyvsp[(3) - (3)].string) ; }
+ break;
+
+ case 21:
+#line 246 "parsessh.y"
+ { (yyval.string) = (yyvsp[(4) - (4)].string) ; }
+ break;
+
+ case 22:
+#line 249 "parsessh.y"
+ { (yyval.string) = (yyvsp[(3) - (5)].string) ; }
+ break;
+
+ case 23:
+#line 251 "parsessh.y"
+ { (yyval.string) = (yyvsp[(1) - (1)].string); }
+ break;
+
+ case 24:
+#line 253 "parsessh.y"
+ {
+ size_t len1;
+ size_t len2;
+
+ len1 = ustrlen ((yyvsp[(1) - (2)].string));
+ (yyvsp[(1) - (2)].string)[len1] = '\n';
+ len2 = ustrlen ((yyvsp[(2) - (2)].string));
+ (yyval.string) = XMALLOC (uchar, len1 + len2 + 2);
+ ustpcpy (ustpncpy ((yyval.string), (yyvsp[(1) - (2)].string), len1 + 1), (yyvsp[(2) - (2)].string));
+ free ((yyvsp[(1) - (2)].string));
+ free ((yyvsp[(2) - (2)].string));
+ }
+ break;
+
+ case 25:
+#line 267 "parsessh.y"
+ { (yyval.string) = (yyvsp[(3) - (3)].string) ; }
+ break;
+
+ case 26:
+#line 270 "parsessh.y"
+ { (yyval.string) = (yyvsp[(3) - (3)].string) ; }
+ break;
+
+ case 27:
+#line 271 "parsessh.y"
+ { (yyval.string) = (yyvsp[(2) - (2)].string) ; }
+ break;
+
+ case 28:
+#line 277 "parsessh.y"
+ {
+ /* The list of keys of style sheets from which it inherits */
+ (yyval.array) = (yyvsp[(3) - (5)].array);
+ }
+ break;
+
+ case 29:
+#line 284 "parsessh.y"
+ {
+ /* Create a list of ancestors, and drop the new one in */
+ (yyval.array) = da_new ("Ancestors tmp", 2,
+ da_linear, 2,
+ (da_print_func_t) da_str_print, NULL);
+ da_append ((yyval.array), (yyvsp[(1) - (1)].string));
+ }
+ break;
+
+ case 30:
+#line 292 "parsessh.y"
+ {
+ da_append ((yyvsp[(1) - (3)].array), (yyvsp[(3) - (3)].string));
+ (yyval.array) = (yyvsp[(1) - (3)].array);
+ }
+ break;
+
+ case 31:
+#line 298 "parsessh.y"
+ { (yyval.sensitiveness) = (yyvsp[(2) - (2)].sensitiveness) ; }
+ break;
+
+ case 32:
+#line 307 "parsessh.y"
+ {
+ (yyval.pattern) = (yyvsp[(1) - (1)].pattern);
+ }
+ break;
+
+ case 33:
+#line 311 "parsessh.y"
+ {
+ /* Concatenate $2 to $1 makes $$ */
+ (yyval.pattern) = (yyvsp[(1) - (2)].pattern);
+ (yyval.pattern)->pattern = XREALLOC ((yyval.pattern)->pattern, char, (yyvsp[(1) - (2)].pattern)->len + (yyvsp[(2) - (2)].pattern)->len + 1);
+ strncpy ((yyval.pattern)->pattern + (yyval.pattern)->len, (yyvsp[(2) - (2)].pattern)->pattern, (yyvsp[(2) - (2)].pattern)->len);
+ (yyval.pattern)->len += (yyvsp[(2) - (2)].pattern)->len;
+ free ((yyvsp[(2) - (2)].pattern)->pattern);
+ }
+ break;
+
+ case 34:
+#line 323 "parsessh.y"
+ {
+ (yyval.array) = rhs_new ();
+ rhs_add ((yyval.array), (yyvsp[(1) - (1)].faced_string));
+ }
+ break;
+
+ case 35:
+#line 331 "parsessh.y"
+ {
+ (yyval.faced_string) = faced_string_new ((yyvsp[(1) - (2)].string), 0, (yyvsp[(2) - (2)].fface));
+ }
+ break;
+
+ case 36:
+#line 335 "parsessh.y"
+ {
+ (yyval.faced_string) = faced_string_new ((yyvsp[(1) - (1)].string), 0, No_fface);
+ }
+ break;
+
+ case 37:
+#line 339 "parsessh.y"
+ {
+ (yyval.faced_string) = faced_string_new (NULL, 0, (yyvsp[(1) - (1)].fface));
+ }
+ break;
+
+ case 38:
+#line 343 "parsessh.y"
+ {
+ (yyval.faced_string) = faced_string_new (UNULL, (yyvsp[(1) - (2)].integer), (yyvsp[(2) - (2)].fface));
+ }
+ break;
+
+ case 39:
+#line 347 "parsessh.y"
+ {
+ (yyval.faced_string) = faced_string_new (UNULL, (yyvsp[(1) - (1)].integer), No_fface);
+ }
+ break;
+
+ case 40:
+#line 351 "parsessh.y"
+ {
+ (yyval.faced_string) = faced_string_new ((yyvsp[(1) - (1)].string), 0, Symbol_fface);
+ }
+ break;
+
+ case 41:
+#line 358 "parsessh.y"
+ {
+ (yyval.array) = rhs_new ();
+ rhs_add ((yyval.array), (yyvsp[(1) - (1)].faced_string));
+ }
+ break;
+
+ case 42:
+#line 364 "parsessh.y"
+ {
+ rhs_add ((yyvsp[(1) - (3)].array), (yyvsp[(3) - (3)].faced_string));
+ (yyval.array) = (yyvsp[(1) - (3)].array);
+ }
+ break;
+
+ case 43:
+#line 375 "parsessh.y"
+ {
+ fface_set_face ((yyval.fface), (yyvsp[(1) - (1)].face));
+ fface_reset_flags ((yyval.fface));
+ }
+ break;
+
+ case 44:
+#line 380 "parsessh.y"
+ {
+ fface_reset_face ((yyval.fface));
+ fface_set_flags ((yyval.fface), (yyvsp[(1) - (1)].fflags));
+ /* If there is no face, then set Invisible */
+ fface_add_flags ((yyval.fface), ff_Invisible);
+ }
+ break;
+
+ case 45:
+#line 387 "parsessh.y"
+ {
+ (yyval.fface) = (yyvsp[(2) - (3)].fface);
+ /* If there is no face, then set Invisible */
+ if (fface_get_face ((yyval.fface)) == No_face)
+ fface_add_flags ((yyval.fface), ff_Invisible);
+ }
+ break;
+
+ case 46:
+#line 397 "parsessh.y"
+ {
+ fface_set_face((yyval.fface), (yyvsp[(1) - (1)].face));
+ fface_reset_flags((yyval.fface));
+ }
+ break;
+
+ case 47:
+#line 402 "parsessh.y"
+ {
+ fface_reset_face((yyval.fface));
+ fface_set_flags((yyval.fface), (yyvsp[(1) - (1)].fflags));
+ }
+ break;
+
+ case 48:
+#line 407 "parsessh.y"
+ {
+ /* FIXME: Overloading of the face should be forbidden */
+ (yyval.fface) = (yyvsp[(1) - (3)].fface);
+ fface_set_face((yyval.fface), (yyvsp[(3) - (3)].face));
+ }
+ break;
+
+ case 49:
+#line 413 "parsessh.y"
+ {
+ (yyval.fface) = (yyvsp[(1) - (3)].fface);
+ fface_add_flags((yyval.fface), (yyvsp[(3) - (3)].fflags));
+ }
+ break;
+
+ case 50:
+#line 427 "parsessh.y"
+ {
+ (yyval.rule) = rule_new ((yyvsp[(1) - (2)].string), NULL, (yyvsp[(2) - (2)].array),
+ sshfilename, sshlineno);
+ }
+ break;
+
+ case 51:
+#line 432 "parsessh.y"
+ {
+ (yyval.rule) = rule_new ((yyvsp[(1) - (1)].string), NULL,
+ rhs_new_single (UNULL, 0, No_fface),
+ sshfilename, sshlineno);
+ }
+ break;
+
+ case 52:
+#line 438 "parsessh.y"
+ {
+ (yyval.rule) = rule_new ((yyvsp[(2) - (4)].string), NULL, (yyvsp[(3) - (4)].array),
+ sshfilename, sshlineno);
+ }
+ break;
+
+ case 53:
+#line 449 "parsessh.y"
+ {
+ words_set_no_face ((yyvsp[(4) - (5)].words), (yyvsp[(2) - (5)].fface));
+ (yyval.words) = (yyvsp[(4) - (5)].words);
+ }
+ break;
+
+ case 54:
+#line 453 "parsessh.y"
+ {
+ /* First of all, the No_face must be turned into Plain */
+ (yyval.words) = (yyvsp[(2) - (3)].words);
+ }
+ break;
+
+ case 55:
+#line 461 "parsessh.y"
+ {
+ (yyval.words) = words_new ("Keywords: Strings", "Keywords: Regexps", 100, 100);
+ words_add_string ((yyval.words), (yyvsp[(1) - (1)].rule));
+ }
+ break;
+
+ case 56:
+#line 466 "parsessh.y"
+ {
+ (yyval.words) = words_new ("Keywords: Strings", "Keywords: Regexps", 100, 100);
+ words_add_regex ((yyval.words), (yyvsp[(1) - (1)].rule));
+ }
+ break;
+
+ case 57:
+#line 471 "parsessh.y"
+ {
+ words_add_string ((yyvsp[(1) - (3)].words), (yyvsp[(3) - (3)].rule));
+ (yyval.words) = (yyvsp[(1) - (3)].words);
+ }
+ break;
+
+ case 58:
+#line 476 "parsessh.y"
+ {
+ words_add_regex ((yyvsp[(1) - (3)].words), (yyvsp[(3) - (3)].rule));
+ (yyval.words) = (yyvsp[(1) - (3)].words);
+ }
+ break;
+
+ case 59:
+#line 488 "parsessh.y"
+ {
+ (yyval.rule) = keyword_rule_new (UNULL, (yyvsp[(1) - (2)].pattern), (yyvsp[(2) - (2)].array),
+ sshfilename, sshlineno);
+ }
+ break;
+
+ case 60:
+#line 493 "parsessh.y"
+ {
+ (yyval.rule) = keyword_rule_new (UNULL, (yyvsp[(1) - (1)].pattern),
+ rhs_new_single (UNULL, 0,
+ No_fface),
+ sshfilename, sshlineno);
+ }
+ break;
+
+ case 61:
+#line 500 "parsessh.y"
+ {
+ (yyval.rule) = keyword_rule_new (UNULL, (yyvsp[(2) - (4)].pattern), (yyvsp[(3) - (4)].array),
+ sshfilename, sshlineno);
+ }
+ break;
+
+ case 62:
+#line 509 "parsessh.y"
+ {
+ words_set_no_face ((yyvsp[(4) - (5)].words), (yyvsp[(2) - (5)].fface));
+ (yyval.words) = (yyvsp[(4) - (5)].words);
+ }
+ break;
+
+ case 63:
+#line 513 "parsessh.y"
+ {
+ /* First of all, the No_face must be turned into Plain */
+ (yyval.words) = (yyvsp[(2) - (3)].words);
+ }
+ break;
+
+ case 64:
+#line 521 "parsessh.y"
+ {
+ (yyval.words) = words_new ("Operators: Strings", "Operators: Regexps",
+ 100, 100);
+ words_add_string ((yyval.words), (yyvsp[(1) - (1)].rule));
+ }
+ break;
+
+ case 65:
+#line 527 "parsessh.y"
+ {
+ (yyval.words) = words_new ("Operators: Strings", "Operators: Regexps",
+ 100, 100);
+ words_add_regex ((yyval.words), (yyvsp[(1) - (1)].rule));
+ }
+ break;
+
+ case 66:
+#line 533 "parsessh.y"
+ {
+ words_add_string ((yyvsp[(1) - (3)].words), (yyvsp[(3) - (3)].rule));
+ (yyval.words) = (yyvsp[(1) - (3)].words);
+ }
+ break;
+
+ case 67:
+#line 538 "parsessh.y"
+ {
+ words_add_regex ((yyvsp[(1) - (3)].words), (yyvsp[(3) - (3)].rule));
+ (yyval.words) = (yyvsp[(1) - (3)].words);
+ }
+ break;
+
+ case 68:
+#line 550 "parsessh.y"
+ {
+ (yyval.rule) = rule_new (UNULL, (yyvsp[(1) - (2)].pattern), (yyvsp[(2) - (2)].array),
+ sshfilename, sshlineno);
+ }
+ break;
+
+ case 69:
+#line 555 "parsessh.y"
+ {
+ (yyval.rule) = rule_new (UNULL, (yyvsp[(1) - (1)].pattern),
+ rhs_new_single (UNULL, 0, No_fface),
+ sshfilename, sshlineno);
+ }
+ break;
+
+ case 70:
+#line 561 "parsessh.y"
+ {
+ (yyval.rule) = rule_new (UNULL, (yyvsp[(2) - (4)].pattern), (yyvsp[(3) - (4)].array),
+ sshfilename, sshlineno);
+ }
+ break;
+
+ case 71:
+#line 570 "parsessh.y"
+ { (yyval.array) = (yyvsp[(3) - (5)].array); }
+ break;
+
+ case 72:
+#line 573 "parsessh.y"
+ {
+ (yyval.array) = da_new ("Sequence tmp", 100,
+ da_linear, 100,
+ (da_print_func_t) sequence_self_print, NULL);
+ da_append ((yyval.array), (yyvsp[(1) - (1)].sequence));
+ }
+ break;
+
+ case 73:
+#line 579 "parsessh.y"
+ {
+ da_append ((yyvsp[(1) - (3)].array), (yyvsp[(3) - (3)].sequence));
+ (yyval.array) = (yyvsp[(1) - (3)].array);
+ }
+ break;
+
+ case 74:
+#line 603 "parsessh.y"
+ {
+ struct rule * open_rule;
+ open_rule = rule_new ((yyvsp[(1) - (5)].string), NULL,
+ rhs_new_single ((yyvsp[(2) - (5)].string), 0, Symbol_fface),
+ sshfilename, sshlineno);
+ (yyval.sequence) = sequence_new (open_rule, (yyvsp[(3) - (5)].fface), (yyvsp[(4) - (5)].words), (yyvsp[(5) - (5)].words));
+ }
+ break;
+
+ case 75:
+#line 611 "parsessh.y"
+ {
+ struct rule * open_rule;
+ open_rule = rule_new ((yyvsp[(1) - (6)].string), NULL,
+ rhs_new_single ((yyvsp[(2) - (6)].string), 0, (yyvsp[(3) - (6)].fface)),
+ sshfilename, sshlineno);
+ (yyval.sequence) = sequence_new (open_rule, (yyvsp[(4) - (6)].fface), (yyvsp[(5) - (6)].words), (yyvsp[(6) - (6)].words));
+ }
+ break;
+
+ case 76:
+#line 619 "parsessh.y"
+ {
+ struct rule * open_rule;
+ open_rule = rule_new ((yyvsp[(1) - (5)].string), NULL,
+ rhs_new_single (UNULL, 0, (yyvsp[(2) - (5)].fface)),
+ sshfilename, sshlineno);
+ (yyval.sequence) = sequence_new (open_rule, (yyvsp[(3) - (5)].fface), (yyvsp[(4) - (5)].words), (yyvsp[(5) - (5)].words));
+ }
+ break;
+
+ case 77:
+#line 627 "parsessh.y"
+ {
+ struct rule * open_rule;
+ open_rule = rule_new ((yyvsp[(1) - (5)].string), NULL,
+ rhs_new_single ((yyvsp[(2) - (5)].string), 0, (yyvsp[(3) - (5)].fface)),
+ sshfilename, sshlineno);
+ (yyval.sequence) = sequence_new (open_rule, (yyvsp[(3) - (5)].fface), (yyvsp[(4) - (5)].words), (yyvsp[(5) - (5)].words));
+ }
+ break;
+
+ case 78:
+#line 635 "parsessh.y"
+ {
+ struct rule * open_rule;
+ open_rule = rule_new ((yyvsp[(1) - (4)].string), NULL,
+ rhs_new_single (UNULL, 0, (yyvsp[(2) - (4)].fface)),
+ sshfilename, sshlineno);
+ (yyval.sequence) = sequence_new (open_rule, (yyvsp[(2) - (4)].fface), (yyvsp[(3) - (4)].words), (yyvsp[(4) - (4)].words));
+ }
+ break;
+
+ case 79:
+#line 643 "parsessh.y"
+ {
+ struct rule * open_rule;
+ open_rule = rule_new (UNULL, (yyvsp[(1) - (6)].pattern),
+ rhs_new_single ((yyvsp[(2) - (6)].string), 0, (yyvsp[(3) - (6)].fface)),
+ sshfilename, sshlineno);
+ (yyval.sequence) = sequence_new (open_rule, (yyvsp[(4) - (6)].fface), (yyvsp[(5) - (6)].words), (yyvsp[(6) - (6)].words));
+ }
+ break;
+
+ case 80:
+#line 651 "parsessh.y"
+ {
+ struct rule * open_rule;
+ open_rule = rule_new (UNULL, (yyvsp[(1) - (5)].pattern),
+ rhs_new_single (UNULL, 0, (yyvsp[(2) - (5)].fface)),
+ sshfilename, sshlineno);
+ (yyval.sequence) = sequence_new (open_rule, (yyvsp[(3) - (5)].fface), (yyvsp[(4) - (5)].words), (yyvsp[(5) - (5)].words));
+ }
+ break;
+
+ case 81:
+#line 659 "parsessh.y"
+ {
+ struct rule * open_rule;
+ open_rule = rule_new (UNULL, (yyvsp[(1) - (5)].pattern),
+ rhs_new_single ((yyvsp[(2) - (5)].string), 0, (yyvsp[(3) - (5)].fface)),
+ sshfilename, sshlineno);
+ (yyval.sequence) = sequence_new (open_rule, (yyvsp[(3) - (5)].fface), (yyvsp[(4) - (5)].words), (yyvsp[(5) - (5)].words));
+ }
+ break;
+
+ case 82:
+#line 667 "parsessh.y"
+ {
+ struct rule * open_rule;
+ open_rule = rule_new (UNULL, (yyvsp[(1) - (4)].pattern),
+ rhs_new_single (UNULL, 0, No_fface),
+ sshfilename, sshlineno);
+ (yyval.sequence) = sequence_new (open_rule, (yyvsp[(2) - (4)].fface), (yyvsp[(3) - (4)].words), (yyvsp[(4) - (4)].words));
+ }
+ break;
+
+ case 83:
+#line 675 "parsessh.y"
+ {
+ struct rule * open_rule;
+ open_rule = rule_new ((yyvsp[(2) - (7)].string), NULL, (yyvsp[(3) - (7)].array),
+ sshfilename, sshlineno);
+ (yyval.sequence) = sequence_new (open_rule, (yyvsp[(5) - (7)].fface), (yyvsp[(6) - (7)].words), (yyvsp[(7) - (7)].words));
+ }
+ break;
+
+ case 84:
+#line 682 "parsessh.y"
+ {
+ struct rule * open_rule;
+ open_rule = rule_new (UNULL, (yyvsp[(2) - (7)].pattern), (yyvsp[(3) - (7)].array),
+ sshfilename, sshlineno);
+ (yyval.sequence) = sequence_new (open_rule, (yyvsp[(5) - (7)].fface), (yyvsp[(6) - (7)].words), (yyvsp[(7) - (7)].words));
+ }
+ break;
+
+ case 85:
+#line 690 "parsessh.y"
+ {
+ (yyval.sequence) = new_C_string_sequence ("\"");
+ }
+ break;
+
+ case 86:
+#line 694 "parsessh.y"
+ {
+ (yyval.sequence) = new_C_string_sequence ("\'");
+ }
+ break;
+
+ case 87:
+#line 701 "parsessh.y"
+ {
+ /* This is a shortcut which means "up to the end of the line". */
+ (yyval.words) = words_new ("Closing: Strings", "Closing: Regexps", 2, 2);
+ words_add_string ((yyval.words), rule_new (xustrdup ("\n"), NULL,
+ rhs_new_single (NULL, 0,
+ No_fface),
+ sshfilename, sshlineno));
+ }
+ break;
+
+ case 88:
+#line 710 "parsessh.y"
+ {
+ /* Only one */
+ (yyval.words) = words_new ("Closing: Strings", "Closing: Regexps", 2, 2);
+ words_add_string ((yyval.words), (yyvsp[(1) - (1)].rule));
+ }
+ break;
+
+ case 89:
+#line 716 "parsessh.y"
+ {
+ /* Only one */
+ (yyval.words) = words_new ("Closing: Strings", "Closing: Regexps", 2, 2);
+ words_add_regex ((yyval.words), (yyvsp[(1) - (1)].rule));
+ }
+ break;
+
+ case 90:
+#line 722 "parsessh.y"
+ {
+ /* Several, comma separated, between () */
+ (yyval.words) = (yyvsp[(2) - (3)].words);
+ }
+ break;
+
+ case 91:
+#line 730 "parsessh.y"
+ {
+ (yyval.words) = words_new ("Exceptions: Strings", "Exceptions: Regexps", 1, 1);
+ }
+ break;
+
+ case 92:
+#line 734 "parsessh.y"
+ {
+ (yyval.words) = (yyvsp[(2) - (3)].words);
+ }
+ break;
+
+
+/* Line 1267 of yacc.c. */
+#line 2423 "parsessh.c"
+ default: break;
+ }
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+
+
+ /* Now `shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if ! YYERROR_VERBOSE
+ yyerror (YY_("syntax error"));
+#else
+ {
+ YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+ if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+ {
+ YYSIZE_T yyalloc = 2 * yysize;
+ if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+ yyalloc = YYSTACK_ALLOC_MAXIMUM;
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+ if (yymsg)
+ yymsg_alloc = yyalloc;
+ else
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ }
+ }
+
+ if (0 < yysize && yysize <= yymsg_alloc)
+ {
+ (void) yysyntax_error (yymsg, yystate, yychar);
+ yyerror (yymsg);
+ }
+ else
+ {
+ yyerror (YY_("syntax error"));
+ if (yysize != 0)
+ goto yyexhaustedlab;
+ }
+ }
+#endif
+ }
+
+
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse look-ahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval);
+ yychar = YYEMPTY;
+ }
+ }
+
+ /* Else will try to reuse look-ahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+ /* Pacify compilers like GCC when the user code never invokes
+ YYERROR and the label yyerrorlab therefore never appears in user
+ code. */
+ if (/*CONSTCOND*/ 0)
+ goto yyerrorlab;
+
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (yyn != YYPACT_NINF)
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ *++yyvsp = yylval;
+
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#ifndef yyoverflow
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (YY_("memory exhausted"));
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+ if (yychar != YYEOF && yychar != YYEMPTY)
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval);
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ yystos[*yyssp], yyvsp);
+ YYPOPSTACK (1);
+ }
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
+ /* Make sure YYID is used. */
+ return YYID (yyresult);
+}
+
+
+#line 738 "parsessh.y"
+
+
+void
+yyerror (const char *msg)
+{
+ error_at_line (1, 0, sshfilename, sshlineno, msg);
+}
+
+/*
+ * FIXME: Cover the other relevant types
+ */
+static void
+yyprint (FILE *file, int type, YYSTYPE value)
+{
+ switch (type) {
+ case tBACK_REF:
+ fprintf (file, " \\%d", value.integer);
+ break;
+
+ case tFFLAGS:
+ putc (' ', file);
+ fflag_self_print (value.fflags, file);
+ break;
+
+ case tFACE:
+ fprintf (file, " %s", face_to_string (value.face));
+ break;
+
+ case tREGEX:
+ fprintf (file, " /%s/", value.pattern->pattern);
+ break;
+
+ case tSTRING:
+ fprintf (file, " \"%s\"", value.string);
+ break;
+ }
+}
+
+struct style_sheet *
+parse_style_sheet (const char * filename)
+{
+ int res;
+
+ sshfilename = filename;
+ sshlineno = 1;
+ sshin = xrfopen (sshfilename);
+
+ message (msg_file | msg_sheet | msg_parse,
+ (stderr, "Parsing file `%s'\n", sshfilename));
+
+ sshlex_initialize ();
+
+ if (msg_test (msg_parse))
+ yydebug = true;
+ res = yyparse (); /* FIXME: test the result of parsing */
+
+ if (msg_test (msg_sheet)) {
+ fprintf (stderr, "---------- Right after parsing of %s\n",
+ parsed_style_sheet->key);
+ style_sheet_self_print (parsed_style_sheet, stderr);
+ fprintf (stderr, "---------- End of after parsing of %s\n",
+ parsed_style_sheet->key);
+ }
+
+ fclose (sshin);
+ return parsed_style_sheet;
+}
+
diff --git a/src/parsessh.h b/src/parsessh.h
new file mode 100644
index 0000000..742a3b1
--- /dev/null
+++ b/src/parsessh.h
@@ -0,0 +1,140 @@
+/* A Bison parser, made by GNU Bison 2.3. */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program 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, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ tSTYLE = 258,
+ tIS = 259,
+ tEND = 260,
+ tKEYWORDS = 261,
+ tARE = 262,
+ tIN = 263,
+ tOPERATORS = 264,
+ tSEQUENCES = 265,
+ tFIRST = 266,
+ tSECOND = 267,
+ tALPHABET = 268,
+ tALPHABETS = 269,
+ tDOCUMENTATION = 270,
+ tEXCEPTIONS = 271,
+ tCASE = 272,
+ tCSTRING = 273,
+ tCCHAR = 274,
+ tOPTIONAL = 275,
+ tCLOSERS = 276,
+ tWRITTEN = 277,
+ tBY = 278,
+ tVERSION = 279,
+ tREQUIRES = 280,
+ tA2PS = 281,
+ tANCESTORS = 282,
+ tFACE = 283,
+ tFFLAGS = 284,
+ tSTRING = 285,
+ tLATEXSYMBOL = 286,
+ tREGEX = 287,
+ tSENSITIVENESS = 288,
+ tBACK_REF = 289
+ };
+#endif
+/* Tokens. */
+#define tSTYLE 258
+#define tIS 259
+#define tEND 260
+#define tKEYWORDS 261
+#define tARE 262
+#define tIN 263
+#define tOPERATORS 264
+#define tSEQUENCES 265
+#define tFIRST 266
+#define tSECOND 267
+#define tALPHABET 268
+#define tALPHABETS 269
+#define tDOCUMENTATION 270
+#define tEXCEPTIONS 271
+#define tCASE 272
+#define tCSTRING 273
+#define tCCHAR 274
+#define tOPTIONAL 275
+#define tCLOSERS 276
+#define tWRITTEN 277
+#define tBY 278
+#define tVERSION 279
+#define tREQUIRES 280
+#define tA2PS 281
+#define tANCESTORS 282
+#define tFACE 283
+#define tFFLAGS 284
+#define tSTRING 285
+#define tLATEXSYMBOL 286
+#define tREGEX 287
+#define tSENSITIVENESS 288
+#define tBACK_REF 289
+
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+#line 81 "parsessh.y"
+{
+ int integer;
+ uchar * string;
+ struct pattern * pattern;
+ struct style_sheet * sheet;
+ struct rule * rule;
+ struct sequence * sequence;
+ struct darray * array;
+ struct words * words;
+ struct faced_string * faced_string;
+ enum face_e face; /* Face */
+ enum fflag_e fflags; /* Flags for faces */
+ struct fface_s fface; /* Flagged face */
+ enum case_sensitiveness sensitiveness;
+}
+/* Line 1489 of yacc.c. */
+#line 133 "parsessh.h"
+ YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+extern YYSTYPE yylval;
+
diff --git a/src/parsessh.output b/src/parsessh.output
new file mode 100644
index 0000000..5120ba1
--- /dev/null
+++ b/src/parsessh.output
@@ -0,0 +1,2153 @@
+文法
+
+ 0 $accept: file $end
+
+ 1 file: style_sheet
+
+ 2 style_sheet: tSTYLE tSTRING tIS definition_list tEND tSTYLE
+
+ 3 definition_list: /* 空 */
+ 4 | definition_list tOPTIONAL tKEYWORDS keywords_def tKEYWORDS
+ 5 | definition_list tKEYWORDS keywords_def tKEYWORDS
+ 6 | definition_list tOPTIONAL tOPERATORS operators_def tOPERATORS
+ 7 | definition_list tOPERATORS operators_def tOPERATORS
+ 8 | definition_list tOPTIONAL sequence_def
+ 9 | definition_list sequence_def
+ 10 | definition_list ancestors_def
+ 11 | definition_list tALPHABETS tARE tSTRING
+ 12 | definition_list tFIRST tALPHABET tIS tSTRING
+ 13 | definition_list tSECOND tALPHABET tIS tSTRING
+ 14 | definition_list case_def
+ 15 | definition_list documentation
+ 16 | definition_list authors
+ 17 | definition_list version
+ 18 | definition_list requirement
+
+ 19 requirement: tREQUIRES tA2PS tSTRING
+ 20 | tREQUIRES tA2PS tVERSION tSTRING
+
+ 21 documentation: tDOCUMENTATION tIS long_string tEND tDOCUMENTATION
+
+ 22 long_string: tSTRING
+ 23 | long_string tSTRING
+
+ 24 authors: tWRITTEN tBY tSTRING
+
+ 25 version: tVERSION tIS tSTRING
+ 26 | tVERSION tSTRING
+
+ 27 ancestors_def: tANCESTORS tARE ancestors_list tEND tANCESTORS
+
+ 28 ancestors_list: tSTRING
+ 29 | ancestors_list ',' tSTRING
+
+ 30 case_def: tCASE tSENSITIVENESS
+
+ 31 regex: tREGEX
+ 32 | regex tREGEX
+
+ 33 rhs: a_rhs
+
+ 34 a_rhs: tSTRING fface
+ 35 | tSTRING
+ 36 | fface
+ 37 | tBACK_REF fface
+ 38 | tBACK_REF
+ 39 | tLATEXSYMBOL
+
+ 40 rhs_list: a_rhs
+ 41 | rhs_list ',' a_rhs
+
+ 42 fface: tFACE
+ 43 | tFFLAGS
+ 44 | '(' fface_sxp ')'
+
+ 45 fface_sxp: tFACE
+ 46 | tFFLAGS
+ 47 | fface_sxp '+' tFACE
+ 48 | fface_sxp '+' tFFLAGS
+
+ 49 rule: tSTRING rhs
+ 50 | tSTRING
+ 51 | '(' tSTRING rhs_list ')'
+
+ 52 keywords_def: tIN fface tARE keywords_rule_list tEND
+ 53 | tARE keywords_rule_list tEND
+
+ 54 keywords_rule_list: rule
+ 55 | keyword_regex
+ 56 | keywords_rule_list ',' rule
+ 57 | keywords_rule_list ',' keyword_regex
+
+ 58 keyword_regex: regex rhs
+ 59 | regex
+ 60 | '(' regex rhs_list ')'
+
+ 61 operators_def: tIN fface tARE operators_rule_list tEND
+ 62 | tARE operators_rule_list tEND
+
+ 63 operators_rule_list: rule
+ 64 | operator_regex
+ 65 | operators_rule_list ',' rule
+ 66 | operators_rule_list ',' operator_regex
+
+ 67 operator_regex: regex rhs
+ 68 | regex
+ 69 | '(' regex rhs_list ')'
+
+ 70 sequence_def: tSEQUENCES tARE sequence_list tEND tSEQUENCES
+
+ 71 sequence_list: sequence
+ 72 | sequence_list ',' sequence
+
+ 73 sequence: tSTRING tLATEXSYMBOL fface closers_opt exception_def_opt
+ 74 | tSTRING tSTRING fface fface closers_opt exception_def_opt
+ 75 | tSTRING fface fface closers_opt exception_def_opt
+ 76 | tSTRING tSTRING fface closers_opt exception_def_opt
+ 77 | tSTRING fface closers_opt exception_def_opt
+ 78 | regex tSTRING fface fface closers_opt exception_def_opt
+ 79 | regex fface fface closers_opt exception_def_opt
+ 80 | regex tSTRING fface closers_opt exception_def_opt
+ 81 | regex fface closers_opt exception_def_opt
+ 82 | '(' tSTRING rhs_list ')' fface closers_opt exception_def_opt
+ 83 | '(' regex rhs_list ')' fface closers_opt exception_def_opt
+ 84 | tCSTRING
+ 85 | tCCHAR
+
+ 86 closers_opt: /* 空 */
+ 87 | rule
+ 88 | operator_regex
+ 89 | tCLOSERS operators_def tCLOSERS
+
+ 90 exception_def_opt: /* 空 */
+ 91 | tEXCEPTIONS operators_def tEXCEPTIONS
+
+
+出ç¾ä½ç½®ã®è¦å‰‡ã«ã‚ˆã‚‹çµ‚端
+
+$end (0) 0
+'(' (40) 44 51 60 69 82 83
+')' (41) 44 51 60 69 82 83
+'+' (43) 47 48
+',' (44) 29 41 56 57 65 66 72
+error (256)
+tSTYLE (258) 2
+tIS (259) 2 12 13 21 25
+tEND (260) 2 21 27 52 53 61 62 70
+tKEYWORDS (261) 4 5
+tARE (262) 11 27 52 53 61 62 70
+tIN (263) 52 61
+tOPERATORS (264) 6 7
+tSEQUENCES (265) 70
+tFIRST (266) 12
+tSECOND (267) 13
+tALPHABET (268) 12 13
+tALPHABETS (269) 11
+tDOCUMENTATION (270) 21
+tEXCEPTIONS (271) 91
+tCASE (272) 30
+tCSTRING (273) 84
+tCCHAR (274) 85
+tOPTIONAL (275) 4 6 8
+tCLOSERS (276) 89
+tWRITTEN (277) 24
+tBY (278) 24
+tVERSION (279) 20 25 26
+tREQUIRES (280) 19 20
+tA2PS (281) 19 20
+tANCESTORS (282) 27
+tFACE (283) 42 45 47
+tFFLAGS (284) 43 46 48
+tSTRING (285) 2 11 12 13 19 20 22 23 24 25 26 28 29 34 35 49 50 51
+ 73 74 75 76 77 78 80 82
+tLATEXSYMBOL (286) 39 73
+tREGEX (287) 31 32
+tSENSITIVENESS (288) 30
+tBACK_REF (289) 37 38
+
+
+出ç¾ä½ç½®ã®è¦å‰‡ã«ã‚ˆã‚‹éžçµ‚端
+
+$accept (39)
+ 左辺: 0
+file (40)
+ 左辺: 1, å³è¾º: 0
+style_sheet (41)
+ 左辺: 2, å³è¾º: 1
+definition_list (42)
+ 左辺: 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18,
+ å³è¾º: 2 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
+requirement (43)
+ 左辺: 19 20, å³è¾º: 18
+documentation (44)
+ 左辺: 21, å³è¾º: 15
+long_string (45)
+ 左辺: 22 23, å³è¾º: 21 23
+authors (46)
+ 左辺: 24, å³è¾º: 16
+version (47)
+ 左辺: 25 26, å³è¾º: 17
+ancestors_def (48)
+ 左辺: 27, å³è¾º: 10
+ancestors_list (49)
+ 左辺: 28 29, å³è¾º: 27 29
+case_def (50)
+ 左辺: 30, å³è¾º: 14
+regex (51)
+ 左辺: 31 32, å³è¾º: 32 58 59 60 67 68 69 78 79 80 81 83
+rhs (52)
+ 左辺: 33, å³è¾º: 49 58 67
+a_rhs (53)
+ 左辺: 34 35 36 37 38 39, å³è¾º: 33 40 41
+rhs_list (54)
+ 左辺: 40 41, å³è¾º: 41 51 60 69 82 83
+fface (55)
+ 左辺: 42 43 44, å³è¾º: 34 36 37 52 61 73 74 75 76 77 78 79 80
+ 81 82 83
+fface_sxp (56)
+ 左辺: 45 46 47 48, å³è¾º: 44 47 48
+rule (57)
+ 左辺: 49 50 51, å³è¾º: 54 56 63 65 87
+keywords_def (58)
+ 左辺: 52 53, å³è¾º: 4 5
+keywords_rule_list (59)
+ 左辺: 54 55 56 57, å³è¾º: 52 53 56 57
+keyword_regex (60)
+ 左辺: 58 59 60, å³è¾º: 55 57
+operators_def (61)
+ 左辺: 61 62, å³è¾º: 6 7 89 91
+operators_rule_list (62)
+ 左辺: 63 64 65 66, å³è¾º: 61 62 65 66
+operator_regex (63)
+ 左辺: 67 68 69, å³è¾º: 64 66 88
+sequence_def (64)
+ 左辺: 70, å³è¾º: 8 9
+sequence_list (65)
+ 左辺: 71 72, å³è¾º: 70 72
+sequence (66)
+ 左辺: 73 74 75 76 77 78 79 80 81 82 83 84 85,
+ å³è¾º: 71 72
+closers_opt (67)
+ 左辺: 86 87 88 89, å³è¾º: 73 74 75 76 77 78 79 80 81 82 83
+exception_def_opt (68)
+ 左辺: 90 91, å³è¾º: 73 74 75 76 77 78 79 80 81 82 83
+
+
+状態 0
+
+ 0 $accept: . file $end
+
+ tSTYLE shift, and go to state 1
+
+ file go to state 2
+ style_sheet go to state 3
+
+
+状態 1
+
+ 2 style_sheet: tSTYLE . tSTRING tIS definition_list tEND tSTYLE
+
+ tSTRING shift, and go to state 4
+
+
+状態 2
+
+ 0 $accept: file . $end
+
+ $end shift, and go to state 5
+
+
+状態 3
+
+ 1 file: style_sheet .
+
+ $default reduce using rule 1 (file)
+
+
+状態 4
+
+ 2 style_sheet: tSTYLE tSTRING . tIS definition_list tEND tSTYLE
+
+ tIS shift, and go to state 6
+
+
+状態 5
+
+ 0 $accept: file $end .
+
+ $default accept
+
+
+状態 6
+
+ 2 style_sheet: tSTYLE tSTRING tIS . definition_list tEND tSTYLE
+
+ $default reduce using rule 3 (definition_list)
+
+ definition_list go to state 7
+
+
+状態 7
+
+ 2 style_sheet: tSTYLE tSTRING tIS definition_list . tEND tSTYLE
+ 4 definition_list: definition_list . tOPTIONAL tKEYWORDS keywords_def tKEYWORDS
+ 5 | definition_list . tKEYWORDS keywords_def tKEYWORDS
+ 6 | definition_list . tOPTIONAL tOPERATORS operators_def tOPERATORS
+ 7 | definition_list . tOPERATORS operators_def tOPERATORS
+ 8 | definition_list . tOPTIONAL sequence_def
+ 9 | definition_list . sequence_def
+ 10 | definition_list . ancestors_def
+ 11 | definition_list . tALPHABETS tARE tSTRING
+ 12 | definition_list . tFIRST tALPHABET tIS tSTRING
+ 13 | definition_list . tSECOND tALPHABET tIS tSTRING
+ 14 | definition_list . case_def
+ 15 | definition_list . documentation
+ 16 | definition_list . authors
+ 17 | definition_list . version
+ 18 | definition_list . requirement
+
+ tEND shift, and go to state 8
+ tKEYWORDS shift, and go to state 9
+ tOPERATORS shift, and go to state 10
+ tSEQUENCES shift, and go to state 11
+ tFIRST shift, and go to state 12
+ tSECOND shift, and go to state 13
+ tALPHABETS shift, and go to state 14
+ tDOCUMENTATION shift, and go to state 15
+ tCASE shift, and go to state 16
+ tOPTIONAL shift, and go to state 17
+ tWRITTEN shift, and go to state 18
+ tVERSION shift, and go to state 19
+ tREQUIRES shift, and go to state 20
+ tANCESTORS shift, and go to state 21
+
+ requirement go to state 22
+ documentation go to state 23
+ authors go to state 24
+ version go to state 25
+ ancestors_def go to state 26
+ case_def go to state 27
+ sequence_def go to state 28
+
+
+状態 8
+
+ 2 style_sheet: tSTYLE tSTRING tIS definition_list tEND . tSTYLE
+
+ tSTYLE shift, and go to state 29
+
+
+状態 9
+
+ 5 definition_list: definition_list tKEYWORDS . keywords_def tKEYWORDS
+
+ tARE shift, and go to state 30
+ tIN shift, and go to state 31
+
+ keywords_def go to state 32
+
+
+状態 10
+
+ 7 definition_list: definition_list tOPERATORS . operators_def tOPERATORS
+
+ tARE shift, and go to state 33
+ tIN shift, and go to state 34
+
+ operators_def go to state 35
+
+
+状態 11
+
+ 70 sequence_def: tSEQUENCES . tARE sequence_list tEND tSEQUENCES
+
+ tARE shift, and go to state 36
+
+
+状態 12
+
+ 12 definition_list: definition_list tFIRST . tALPHABET tIS tSTRING
+
+ tALPHABET shift, and go to state 37
+
+
+状態 13
+
+ 13 definition_list: definition_list tSECOND . tALPHABET tIS tSTRING
+
+ tALPHABET shift, and go to state 38
+
+
+状態 14
+
+ 11 definition_list: definition_list tALPHABETS . tARE tSTRING
+
+ tARE shift, and go to state 39
+
+
+状態 15
+
+ 21 documentation: tDOCUMENTATION . tIS long_string tEND tDOCUMENTATION
+
+ tIS shift, and go to state 40
+
+
+状態 16
+
+ 30 case_def: tCASE . tSENSITIVENESS
+
+ tSENSITIVENESS shift, and go to state 41
+
+
+状態 17
+
+ 4 definition_list: definition_list tOPTIONAL . tKEYWORDS keywords_def tKEYWORDS
+ 6 | definition_list tOPTIONAL . tOPERATORS operators_def tOPERATORS
+ 8 | definition_list tOPTIONAL . sequence_def
+
+ tKEYWORDS shift, and go to state 42
+ tOPERATORS shift, and go to state 43
+ tSEQUENCES shift, and go to state 11
+
+ sequence_def go to state 44
+
+
+状態 18
+
+ 24 authors: tWRITTEN . tBY tSTRING
+
+ tBY shift, and go to state 45
+
+
+状態 19
+
+ 25 version: tVERSION . tIS tSTRING
+ 26 | tVERSION . tSTRING
+
+ tIS shift, and go to state 46
+ tSTRING shift, and go to state 47
+
+
+状態 20
+
+ 19 requirement: tREQUIRES . tA2PS tSTRING
+ 20 | tREQUIRES . tA2PS tVERSION tSTRING
+
+ tA2PS shift, and go to state 48
+
+
+状態 21
+
+ 27 ancestors_def: tANCESTORS . tARE ancestors_list tEND tANCESTORS
+
+ tARE shift, and go to state 49
+
+
+状態 22
+
+ 18 definition_list: definition_list requirement .
+
+ $default reduce using rule 18 (definition_list)
+
+
+状態 23
+
+ 15 definition_list: definition_list documentation .
+
+ $default reduce using rule 15 (definition_list)
+
+
+状態 24
+
+ 16 definition_list: definition_list authors .
+
+ $default reduce using rule 16 (definition_list)
+
+
+状態 25
+
+ 17 definition_list: definition_list version .
+
+ $default reduce using rule 17 (definition_list)
+
+
+状態 26
+
+ 10 definition_list: definition_list ancestors_def .
+
+ $default reduce using rule 10 (definition_list)
+
+
+状態 27
+
+ 14 definition_list: definition_list case_def .
+
+ $default reduce using rule 14 (definition_list)
+
+
+状態 28
+
+ 9 definition_list: definition_list sequence_def .
+
+ $default reduce using rule 9 (definition_list)
+
+
+状態 29
+
+ 2 style_sheet: tSTYLE tSTRING tIS definition_list tEND tSTYLE .
+
+ $default reduce using rule 2 (style_sheet)
+
+
+状態 30
+
+ 53 keywords_def: tARE . keywords_rule_list tEND
+
+ tSTRING shift, and go to state 50
+ tREGEX shift, and go to state 51
+ '(' shift, and go to state 52
+
+ regex go to state 53
+ rule go to state 54
+ keywords_rule_list go to state 55
+ keyword_regex go to state 56
+
+
+状態 31
+
+ 52 keywords_def: tIN . fface tARE keywords_rule_list tEND
+
+ tFACE shift, and go to state 57
+ tFFLAGS shift, and go to state 58
+ '(' shift, and go to state 59
+
+ fface go to state 60
+
+
+状態 32
+
+ 5 definition_list: definition_list tKEYWORDS keywords_def . tKEYWORDS
+
+ tKEYWORDS shift, and go to state 61
+
+
+状態 33
+
+ 62 operators_def: tARE . operators_rule_list tEND
+
+ tSTRING shift, and go to state 50
+ tREGEX shift, and go to state 51
+ '(' shift, and go to state 62
+
+ regex go to state 63
+ rule go to state 64
+ operators_rule_list go to state 65
+ operator_regex go to state 66
+
+
+状態 34
+
+ 61 operators_def: tIN . fface tARE operators_rule_list tEND
+
+ tFACE shift, and go to state 57
+ tFFLAGS shift, and go to state 58
+ '(' shift, and go to state 59
+
+ fface go to state 67
+
+
+状態 35
+
+ 7 definition_list: definition_list tOPERATORS operators_def . tOPERATORS
+
+ tOPERATORS shift, and go to state 68
+
+
+状態 36
+
+ 70 sequence_def: tSEQUENCES tARE . sequence_list tEND tSEQUENCES
+
+ tCSTRING shift, and go to state 69
+ tCCHAR shift, and go to state 70
+ tSTRING shift, and go to state 71
+ tREGEX shift, and go to state 51
+ '(' shift, and go to state 72
+
+ regex go to state 73
+ sequence_list go to state 74
+ sequence go to state 75
+
+
+状態 37
+
+ 12 definition_list: definition_list tFIRST tALPHABET . tIS tSTRING
+
+ tIS shift, and go to state 76
+
+
+状態 38
+
+ 13 definition_list: definition_list tSECOND tALPHABET . tIS tSTRING
+
+ tIS shift, and go to state 77
+
+
+状態 39
+
+ 11 definition_list: definition_list tALPHABETS tARE . tSTRING
+
+ tSTRING shift, and go to state 78
+
+
+状態 40
+
+ 21 documentation: tDOCUMENTATION tIS . long_string tEND tDOCUMENTATION
+
+ tSTRING shift, and go to state 79
+
+ long_string go to state 80
+
+
+状態 41
+
+ 30 case_def: tCASE tSENSITIVENESS .
+
+ $default reduce using rule 30 (case_def)
+
+
+状態 42
+
+ 4 definition_list: definition_list tOPTIONAL tKEYWORDS . keywords_def tKEYWORDS
+
+ tARE shift, and go to state 30
+ tIN shift, and go to state 31
+
+ keywords_def go to state 81
+
+
+状態 43
+
+ 6 definition_list: definition_list tOPTIONAL tOPERATORS . operators_def tOPERATORS
+
+ tARE shift, and go to state 33
+ tIN shift, and go to state 34
+
+ operators_def go to state 82
+
+
+状態 44
+
+ 8 definition_list: definition_list tOPTIONAL sequence_def .
+
+ $default reduce using rule 8 (definition_list)
+
+
+状態 45
+
+ 24 authors: tWRITTEN tBY . tSTRING
+
+ tSTRING shift, and go to state 83
+
+
+状態 46
+
+ 25 version: tVERSION tIS . tSTRING
+
+ tSTRING shift, and go to state 84
+
+
+状態 47
+
+ 26 version: tVERSION tSTRING .
+
+ $default reduce using rule 26 (version)
+
+
+状態 48
+
+ 19 requirement: tREQUIRES tA2PS . tSTRING
+ 20 | tREQUIRES tA2PS . tVERSION tSTRING
+
+ tVERSION shift, and go to state 85
+ tSTRING shift, and go to state 86
+
+
+状態 49
+
+ 27 ancestors_def: tANCESTORS tARE . ancestors_list tEND tANCESTORS
+
+ tSTRING shift, and go to state 87
+
+ ancestors_list go to state 88
+
+
+状態 50
+
+ 49 rule: tSTRING . rhs
+ 50 | tSTRING .
+
+ tFACE shift, and go to state 57
+ tFFLAGS shift, and go to state 58
+ tSTRING shift, and go to state 89
+ tLATEXSYMBOL shift, and go to state 90
+ tBACK_REF shift, and go to state 91
+ '(' shift, and go to state 59
+
+ $default reduce using rule 50 (rule)
+
+ rhs go to state 92
+ a_rhs go to state 93
+ fface go to state 94
+
+
+状態 51
+
+ 31 regex: tREGEX .
+
+ $default reduce using rule 31 (regex)
+
+
+状態 52
+
+ 51 rule: '(' . tSTRING rhs_list ')'
+ 60 keyword_regex: '(' . regex rhs_list ')'
+
+ tSTRING shift, and go to state 95
+ tREGEX shift, and go to state 51
+
+ regex go to state 96
+
+
+状態 53
+
+ 32 regex: regex . tREGEX
+ 58 keyword_regex: regex . rhs
+ 59 | regex .
+
+ tFACE shift, and go to state 57
+ tFFLAGS shift, and go to state 58
+ tSTRING shift, and go to state 89
+ tLATEXSYMBOL shift, and go to state 90
+ tREGEX shift, and go to state 97
+ tBACK_REF shift, and go to state 91
+ '(' shift, and go to state 59
+
+ $default reduce using rule 59 (keyword_regex)
+
+ rhs go to state 98
+ a_rhs go to state 93
+ fface go to state 94
+
+
+状態 54
+
+ 54 keywords_rule_list: rule .
+
+ $default reduce using rule 54 (keywords_rule_list)
+
+
+状態 55
+
+ 53 keywords_def: tARE keywords_rule_list . tEND
+ 56 keywords_rule_list: keywords_rule_list . ',' rule
+ 57 | keywords_rule_list . ',' keyword_regex
+
+ tEND shift, and go to state 99
+ ',' shift, and go to state 100
+
+
+状態 56
+
+ 55 keywords_rule_list: keyword_regex .
+
+ $default reduce using rule 55 (keywords_rule_list)
+
+
+状態 57
+
+ 42 fface: tFACE .
+
+ $default reduce using rule 42 (fface)
+
+
+状態 58
+
+ 43 fface: tFFLAGS .
+
+ $default reduce using rule 43 (fface)
+
+
+状態 59
+
+ 44 fface: '(' . fface_sxp ')'
+
+ tFACE shift, and go to state 101
+ tFFLAGS shift, and go to state 102
+
+ fface_sxp go to state 103
+
+
+状態 60
+
+ 52 keywords_def: tIN fface . tARE keywords_rule_list tEND
+
+ tARE shift, and go to state 104
+
+
+状態 61
+
+ 5 definition_list: definition_list tKEYWORDS keywords_def tKEYWORDS .
+
+ $default reduce using rule 5 (definition_list)
+
+
+状態 62
+
+ 51 rule: '(' . tSTRING rhs_list ')'
+ 69 operator_regex: '(' . regex rhs_list ')'
+
+ tSTRING shift, and go to state 95
+ tREGEX shift, and go to state 51
+
+ regex go to state 105
+
+
+状態 63
+
+ 32 regex: regex . tREGEX
+ 67 operator_regex: regex . rhs
+ 68 | regex .
+
+ tFACE shift, and go to state 57
+ tFFLAGS shift, and go to state 58
+ tSTRING shift, and go to state 89
+ tLATEXSYMBOL shift, and go to state 90
+ tREGEX shift, and go to state 97
+ tBACK_REF shift, and go to state 91
+ '(' shift, and go to state 59
+
+ $default reduce using rule 68 (operator_regex)
+
+ rhs go to state 106
+ a_rhs go to state 93
+ fface go to state 94
+
+
+状態 64
+
+ 63 operators_rule_list: rule .
+
+ $default reduce using rule 63 (operators_rule_list)
+
+
+状態 65
+
+ 62 operators_def: tARE operators_rule_list . tEND
+ 65 operators_rule_list: operators_rule_list . ',' rule
+ 66 | operators_rule_list . ',' operator_regex
+
+ tEND shift, and go to state 107
+ ',' shift, and go to state 108
+
+
+状態 66
+
+ 64 operators_rule_list: operator_regex .
+
+ $default reduce using rule 64 (operators_rule_list)
+
+
+状態 67
+
+ 61 operators_def: tIN fface . tARE operators_rule_list tEND
+
+ tARE shift, and go to state 109
+
+
+状態 68
+
+ 7 definition_list: definition_list tOPERATORS operators_def tOPERATORS .
+
+ $default reduce using rule 7 (definition_list)
+
+
+状態 69
+
+ 84 sequence: tCSTRING .
+
+ $default reduce using rule 84 (sequence)
+
+
+状態 70
+
+ 85 sequence: tCCHAR .
+
+ $default reduce using rule 85 (sequence)
+
+
+状態 71
+
+ 73 sequence: tSTRING . tLATEXSYMBOL fface closers_opt exception_def_opt
+ 74 | tSTRING . tSTRING fface fface closers_opt exception_def_opt
+ 75 | tSTRING . fface fface closers_opt exception_def_opt
+ 76 | tSTRING . tSTRING fface closers_opt exception_def_opt
+ 77 | tSTRING . fface closers_opt exception_def_opt
+
+ tFACE shift, and go to state 57
+ tFFLAGS shift, and go to state 58
+ tSTRING shift, and go to state 110
+ tLATEXSYMBOL shift, and go to state 111
+ '(' shift, and go to state 59
+
+ fface go to state 112
+
+
+状態 72
+
+ 82 sequence: '(' . tSTRING rhs_list ')' fface closers_opt exception_def_opt
+ 83 | '(' . regex rhs_list ')' fface closers_opt exception_def_opt
+
+ tSTRING shift, and go to state 113
+ tREGEX shift, and go to state 51
+
+ regex go to state 114
+
+
+状態 73
+
+ 32 regex: regex . tREGEX
+ 78 sequence: regex . tSTRING fface fface closers_opt exception_def_opt
+ 79 | regex . fface fface closers_opt exception_def_opt
+ 80 | regex . tSTRING fface closers_opt exception_def_opt
+ 81 | regex . fface closers_opt exception_def_opt
+
+ tFACE shift, and go to state 57
+ tFFLAGS shift, and go to state 58
+ tSTRING shift, and go to state 115
+ tREGEX shift, and go to state 97
+ '(' shift, and go to state 59
+
+ fface go to state 116
+
+
+状態 74
+
+ 70 sequence_def: tSEQUENCES tARE sequence_list . tEND tSEQUENCES
+ 72 sequence_list: sequence_list . ',' sequence
+
+ tEND shift, and go to state 117
+ ',' shift, and go to state 118
+
+
+状態 75
+
+ 71 sequence_list: sequence .
+
+ $default reduce using rule 71 (sequence_list)
+
+
+状態 76
+
+ 12 definition_list: definition_list tFIRST tALPHABET tIS . tSTRING
+
+ tSTRING shift, and go to state 119
+
+
+状態 77
+
+ 13 definition_list: definition_list tSECOND tALPHABET tIS . tSTRING
+
+ tSTRING shift, and go to state 120
+
+
+状態 78
+
+ 11 definition_list: definition_list tALPHABETS tARE tSTRING .
+
+ $default reduce using rule 11 (definition_list)
+
+
+状態 79
+
+ 22 long_string: tSTRING .
+
+ $default reduce using rule 22 (long_string)
+
+
+状態 80
+
+ 21 documentation: tDOCUMENTATION tIS long_string . tEND tDOCUMENTATION
+ 23 long_string: long_string . tSTRING
+
+ tEND shift, and go to state 121
+ tSTRING shift, and go to state 122
+
+
+状態 81
+
+ 4 definition_list: definition_list tOPTIONAL tKEYWORDS keywords_def . tKEYWORDS
+
+ tKEYWORDS shift, and go to state 123
+
+
+状態 82
+
+ 6 definition_list: definition_list tOPTIONAL tOPERATORS operators_def . tOPERATORS
+
+ tOPERATORS shift, and go to state 124
+
+
+状態 83
+
+ 24 authors: tWRITTEN tBY tSTRING .
+
+ $default reduce using rule 24 (authors)
+
+
+状態 84
+
+ 25 version: tVERSION tIS tSTRING .
+
+ $default reduce using rule 25 (version)
+
+
+状態 85
+
+ 20 requirement: tREQUIRES tA2PS tVERSION . tSTRING
+
+ tSTRING shift, and go to state 125
+
+
+状態 86
+
+ 19 requirement: tREQUIRES tA2PS tSTRING .
+
+ $default reduce using rule 19 (requirement)
+
+
+状態 87
+
+ 28 ancestors_list: tSTRING .
+
+ $default reduce using rule 28 (ancestors_list)
+
+
+状態 88
+
+ 27 ancestors_def: tANCESTORS tARE ancestors_list . tEND tANCESTORS
+ 29 ancestors_list: ancestors_list . ',' tSTRING
+
+ tEND shift, and go to state 126
+ ',' shift, and go to state 127
+
+
+状態 89
+
+ 34 a_rhs: tSTRING . fface
+ 35 | tSTRING .
+
+ tFACE shift, and go to state 57
+ tFFLAGS shift, and go to state 58
+ '(' shift, and go to state 59
+
+ $default reduce using rule 35 (a_rhs)
+
+ fface go to state 128
+
+
+状態 90
+
+ 39 a_rhs: tLATEXSYMBOL .
+
+ $default reduce using rule 39 (a_rhs)
+
+
+状態 91
+
+ 37 a_rhs: tBACK_REF . fface
+ 38 | tBACK_REF .
+
+ tFACE shift, and go to state 57
+ tFFLAGS shift, and go to state 58
+ '(' shift, and go to state 59
+
+ $default reduce using rule 38 (a_rhs)
+
+ fface go to state 129
+
+
+状態 92
+
+ 49 rule: tSTRING rhs .
+
+ $default reduce using rule 49 (rule)
+
+
+状態 93
+
+ 33 rhs: a_rhs .
+
+ $default reduce using rule 33 (rhs)
+
+
+状態 94
+
+ 36 a_rhs: fface .
+
+ $default reduce using rule 36 (a_rhs)
+
+
+状態 95
+
+ 51 rule: '(' tSTRING . rhs_list ')'
+
+ tFACE shift, and go to state 57
+ tFFLAGS shift, and go to state 58
+ tSTRING shift, and go to state 89
+ tLATEXSYMBOL shift, and go to state 90
+ tBACK_REF shift, and go to state 91
+ '(' shift, and go to state 59
+
+ a_rhs go to state 130
+ rhs_list go to state 131
+ fface go to state 94
+
+
+状態 96
+
+ 32 regex: regex . tREGEX
+ 60 keyword_regex: '(' regex . rhs_list ')'
+
+ tFACE shift, and go to state 57
+ tFFLAGS shift, and go to state 58
+ tSTRING shift, and go to state 89
+ tLATEXSYMBOL shift, and go to state 90
+ tREGEX shift, and go to state 97
+ tBACK_REF shift, and go to state 91
+ '(' shift, and go to state 59
+
+ a_rhs go to state 130
+ rhs_list go to state 132
+ fface go to state 94
+
+
+状態 97
+
+ 32 regex: regex tREGEX .
+
+ $default reduce using rule 32 (regex)
+
+
+状態 98
+
+ 58 keyword_regex: regex rhs .
+
+ $default reduce using rule 58 (keyword_regex)
+
+
+状態 99
+
+ 53 keywords_def: tARE keywords_rule_list tEND .
+
+ $default reduce using rule 53 (keywords_def)
+
+
+状態 100
+
+ 56 keywords_rule_list: keywords_rule_list ',' . rule
+ 57 | keywords_rule_list ',' . keyword_regex
+
+ tSTRING shift, and go to state 50
+ tREGEX shift, and go to state 51
+ '(' shift, and go to state 52
+
+ regex go to state 53
+ rule go to state 133
+ keyword_regex go to state 134
+
+
+状態 101
+
+ 45 fface_sxp: tFACE .
+
+ $default reduce using rule 45 (fface_sxp)
+
+
+状態 102
+
+ 46 fface_sxp: tFFLAGS .
+
+ $default reduce using rule 46 (fface_sxp)
+
+
+状態 103
+
+ 44 fface: '(' fface_sxp . ')'
+ 47 fface_sxp: fface_sxp . '+' tFACE
+ 48 | fface_sxp . '+' tFFLAGS
+
+ ')' shift, and go to state 135
+ '+' shift, and go to state 136
+
+
+状態 104
+
+ 52 keywords_def: tIN fface tARE . keywords_rule_list tEND
+
+ tSTRING shift, and go to state 50
+ tREGEX shift, and go to state 51
+ '(' shift, and go to state 52
+
+ regex go to state 53
+ rule go to state 54
+ keywords_rule_list go to state 137
+ keyword_regex go to state 56
+
+
+状態 105
+
+ 32 regex: regex . tREGEX
+ 69 operator_regex: '(' regex . rhs_list ')'
+
+ tFACE shift, and go to state 57
+ tFFLAGS shift, and go to state 58
+ tSTRING shift, and go to state 89
+ tLATEXSYMBOL shift, and go to state 90
+ tREGEX shift, and go to state 97
+ tBACK_REF shift, and go to state 91
+ '(' shift, and go to state 59
+
+ a_rhs go to state 130
+ rhs_list go to state 138
+ fface go to state 94
+
+
+状態 106
+
+ 67 operator_regex: regex rhs .
+
+ $default reduce using rule 67 (operator_regex)
+
+
+状態 107
+
+ 62 operators_def: tARE operators_rule_list tEND .
+
+ $default reduce using rule 62 (operators_def)
+
+
+状態 108
+
+ 65 operators_rule_list: operators_rule_list ',' . rule
+ 66 | operators_rule_list ',' . operator_regex
+
+ tSTRING shift, and go to state 50
+ tREGEX shift, and go to state 51
+ '(' shift, and go to state 62
+
+ regex go to state 63
+ rule go to state 139
+ operator_regex go to state 140
+
+
+状態 109
+
+ 61 operators_def: tIN fface tARE . operators_rule_list tEND
+
+ tSTRING shift, and go to state 50
+ tREGEX shift, and go to state 51
+ '(' shift, and go to state 62
+
+ regex go to state 63
+ rule go to state 64
+ operators_rule_list go to state 141
+ operator_regex go to state 66
+
+
+状態 110
+
+ 74 sequence: tSTRING tSTRING . fface fface closers_opt exception_def_opt
+ 76 | tSTRING tSTRING . fface closers_opt exception_def_opt
+
+ tFACE shift, and go to state 57
+ tFFLAGS shift, and go to state 58
+ '(' shift, and go to state 59
+
+ fface go to state 142
+
+
+状態 111
+
+ 73 sequence: tSTRING tLATEXSYMBOL . fface closers_opt exception_def_opt
+
+ tFACE shift, and go to state 57
+ tFFLAGS shift, and go to state 58
+ '(' shift, and go to state 59
+
+ fface go to state 143
+
+
+状態 112
+
+ 75 sequence: tSTRING fface . fface closers_opt exception_def_opt
+ 77 | tSTRING fface . closers_opt exception_def_opt
+
+ tCLOSERS shift, and go to state 144
+ tFACE shift, and go to state 57
+ tFFLAGS shift, and go to state 58
+ tSTRING shift, and go to state 50
+ tREGEX shift, and go to state 51
+ '(' shift, and go to state 145
+
+ $default reduce using rule 86 (closers_opt)
+
+ regex go to state 63
+ fface go to state 146
+ rule go to state 147
+ operator_regex go to state 148
+ closers_opt go to state 149
+
+
+状態 113
+
+ 82 sequence: '(' tSTRING . rhs_list ')' fface closers_opt exception_def_opt
+
+ tFACE shift, and go to state 57
+ tFFLAGS shift, and go to state 58
+ tSTRING shift, and go to state 89
+ tLATEXSYMBOL shift, and go to state 90
+ tBACK_REF shift, and go to state 91
+ '(' shift, and go to state 59
+
+ a_rhs go to state 130
+ rhs_list go to state 150
+ fface go to state 94
+
+
+状態 114
+
+ 32 regex: regex . tREGEX
+ 83 sequence: '(' regex . rhs_list ')' fface closers_opt exception_def_opt
+
+ tFACE shift, and go to state 57
+ tFFLAGS shift, and go to state 58
+ tSTRING shift, and go to state 89
+ tLATEXSYMBOL shift, and go to state 90
+ tREGEX shift, and go to state 97
+ tBACK_REF shift, and go to state 91
+ '(' shift, and go to state 59
+
+ a_rhs go to state 130
+ rhs_list go to state 151
+ fface go to state 94
+
+
+状態 115
+
+ 78 sequence: regex tSTRING . fface fface closers_opt exception_def_opt
+ 80 | regex tSTRING . fface closers_opt exception_def_opt
+
+ tFACE shift, and go to state 57
+ tFFLAGS shift, and go to state 58
+ '(' shift, and go to state 59
+
+ fface go to state 152
+
+
+状態 116
+
+ 79 sequence: regex fface . fface closers_opt exception_def_opt
+ 81 | regex fface . closers_opt exception_def_opt
+
+ tCLOSERS shift, and go to state 144
+ tFACE shift, and go to state 57
+ tFFLAGS shift, and go to state 58
+ tSTRING shift, and go to state 50
+ tREGEX shift, and go to state 51
+ '(' shift, and go to state 145
+
+ $default reduce using rule 86 (closers_opt)
+
+ regex go to state 63
+ fface go to state 153
+ rule go to state 147
+ operator_regex go to state 148
+ closers_opt go to state 154
+
+
+状態 117
+
+ 70 sequence_def: tSEQUENCES tARE sequence_list tEND . tSEQUENCES
+
+ tSEQUENCES shift, and go to state 155
+
+
+状態 118
+
+ 72 sequence_list: sequence_list ',' . sequence
+
+ tCSTRING shift, and go to state 69
+ tCCHAR shift, and go to state 70
+ tSTRING shift, and go to state 71
+ tREGEX shift, and go to state 51
+ '(' shift, and go to state 72
+
+ regex go to state 73
+ sequence go to state 156
+
+
+状態 119
+
+ 12 definition_list: definition_list tFIRST tALPHABET tIS tSTRING .
+
+ $default reduce using rule 12 (definition_list)
+
+
+状態 120
+
+ 13 definition_list: definition_list tSECOND tALPHABET tIS tSTRING .
+
+ $default reduce using rule 13 (definition_list)
+
+
+状態 121
+
+ 21 documentation: tDOCUMENTATION tIS long_string tEND . tDOCUMENTATION
+
+ tDOCUMENTATION shift, and go to state 157
+
+
+状態 122
+
+ 23 long_string: long_string tSTRING .
+
+ $default reduce using rule 23 (long_string)
+
+
+状態 123
+
+ 4 definition_list: definition_list tOPTIONAL tKEYWORDS keywords_def tKEYWORDS .
+
+ $default reduce using rule 4 (definition_list)
+
+
+状態 124
+
+ 6 definition_list: definition_list tOPTIONAL tOPERATORS operators_def tOPERATORS .
+
+ $default reduce using rule 6 (definition_list)
+
+
+状態 125
+
+ 20 requirement: tREQUIRES tA2PS tVERSION tSTRING .
+
+ $default reduce using rule 20 (requirement)
+
+
+状態 126
+
+ 27 ancestors_def: tANCESTORS tARE ancestors_list tEND . tANCESTORS
+
+ tANCESTORS shift, and go to state 158
+
+
+状態 127
+
+ 29 ancestors_list: ancestors_list ',' . tSTRING
+
+ tSTRING shift, and go to state 159
+
+
+状態 128
+
+ 34 a_rhs: tSTRING fface .
+
+ $default reduce using rule 34 (a_rhs)
+
+
+状態 129
+
+ 37 a_rhs: tBACK_REF fface .
+
+ $default reduce using rule 37 (a_rhs)
+
+
+状態 130
+
+ 40 rhs_list: a_rhs .
+
+ $default reduce using rule 40 (rhs_list)
+
+
+状態 131
+
+ 41 rhs_list: rhs_list . ',' a_rhs
+ 51 rule: '(' tSTRING rhs_list . ')'
+
+ ',' shift, and go to state 160
+ ')' shift, and go to state 161
+
+
+状態 132
+
+ 41 rhs_list: rhs_list . ',' a_rhs
+ 60 keyword_regex: '(' regex rhs_list . ')'
+
+ ',' shift, and go to state 160
+ ')' shift, and go to state 162
+
+
+状態 133
+
+ 56 keywords_rule_list: keywords_rule_list ',' rule .
+
+ $default reduce using rule 56 (keywords_rule_list)
+
+
+状態 134
+
+ 57 keywords_rule_list: keywords_rule_list ',' keyword_regex .
+
+ $default reduce using rule 57 (keywords_rule_list)
+
+
+状態 135
+
+ 44 fface: '(' fface_sxp ')' .
+
+ $default reduce using rule 44 (fface)
+
+
+状態 136
+
+ 47 fface_sxp: fface_sxp '+' . tFACE
+ 48 | fface_sxp '+' . tFFLAGS
+
+ tFACE shift, and go to state 163
+ tFFLAGS shift, and go to state 164
+
+
+状態 137
+
+ 52 keywords_def: tIN fface tARE keywords_rule_list . tEND
+ 56 keywords_rule_list: keywords_rule_list . ',' rule
+ 57 | keywords_rule_list . ',' keyword_regex
+
+ tEND shift, and go to state 165
+ ',' shift, and go to state 100
+
+
+状態 138
+
+ 41 rhs_list: rhs_list . ',' a_rhs
+ 69 operator_regex: '(' regex rhs_list . ')'
+
+ ',' shift, and go to state 160
+ ')' shift, and go to state 166
+
+
+状態 139
+
+ 65 operators_rule_list: operators_rule_list ',' rule .
+
+ $default reduce using rule 65 (operators_rule_list)
+
+
+状態 140
+
+ 66 operators_rule_list: operators_rule_list ',' operator_regex .
+
+ $default reduce using rule 66 (operators_rule_list)
+
+
+状態 141
+
+ 61 operators_def: tIN fface tARE operators_rule_list . tEND
+ 65 operators_rule_list: operators_rule_list . ',' rule
+ 66 | operators_rule_list . ',' operator_regex
+
+ tEND shift, and go to state 167
+ ',' shift, and go to state 108
+
+
+状態 142
+
+ 74 sequence: tSTRING tSTRING fface . fface closers_opt exception_def_opt
+ 76 | tSTRING tSTRING fface . closers_opt exception_def_opt
+
+ tCLOSERS shift, and go to state 144
+ tFACE shift, and go to state 57
+ tFFLAGS shift, and go to state 58
+ tSTRING shift, and go to state 50
+ tREGEX shift, and go to state 51
+ '(' shift, and go to state 145
+
+ $default reduce using rule 86 (closers_opt)
+
+ regex go to state 63
+ fface go to state 168
+ rule go to state 147
+ operator_regex go to state 148
+ closers_opt go to state 169
+
+
+状態 143
+
+ 73 sequence: tSTRING tLATEXSYMBOL fface . closers_opt exception_def_opt
+
+ tCLOSERS shift, and go to state 144
+ tSTRING shift, and go to state 50
+ tREGEX shift, and go to state 51
+ '(' shift, and go to state 62
+
+ $default reduce using rule 86 (closers_opt)
+
+ regex go to state 63
+ rule go to state 147
+ operator_regex go to state 148
+ closers_opt go to state 170
+
+
+状態 144
+
+ 89 closers_opt: tCLOSERS . operators_def tCLOSERS
+
+ tARE shift, and go to state 33
+ tIN shift, and go to state 34
+
+ operators_def go to state 171
+
+
+状態 145
+
+ 44 fface: '(' . fface_sxp ')'
+ 51 rule: '(' . tSTRING rhs_list ')'
+ 69 operator_regex: '(' . regex rhs_list ')'
+
+ tFACE shift, and go to state 101
+ tFFLAGS shift, and go to state 102
+ tSTRING shift, and go to state 95
+ tREGEX shift, and go to state 51
+
+ regex go to state 105
+ fface_sxp go to state 103
+
+
+状態 146
+
+ 75 sequence: tSTRING fface fface . closers_opt exception_def_opt
+
+ tCLOSERS shift, and go to state 144
+ tSTRING shift, and go to state 50
+ tREGEX shift, and go to state 51
+ '(' shift, and go to state 62
+
+ $default reduce using rule 86 (closers_opt)
+
+ regex go to state 63
+ rule go to state 147
+ operator_regex go to state 148
+ closers_opt go to state 172
+
+
+状態 147
+
+ 87 closers_opt: rule .
+
+ $default reduce using rule 87 (closers_opt)
+
+
+状態 148
+
+ 88 closers_opt: operator_regex .
+
+ $default reduce using rule 88 (closers_opt)
+
+
+状態 149
+
+ 77 sequence: tSTRING fface closers_opt . exception_def_opt
+
+ tEXCEPTIONS shift, and go to state 173
+
+ $default reduce using rule 90 (exception_def_opt)
+
+ exception_def_opt go to state 174
+
+
+状態 150
+
+ 41 rhs_list: rhs_list . ',' a_rhs
+ 82 sequence: '(' tSTRING rhs_list . ')' fface closers_opt exception_def_opt
+
+ ',' shift, and go to state 160
+ ')' shift, and go to state 175
+
+
+状態 151
+
+ 41 rhs_list: rhs_list . ',' a_rhs
+ 83 sequence: '(' regex rhs_list . ')' fface closers_opt exception_def_opt
+
+ ',' shift, and go to state 160
+ ')' shift, and go to state 176
+
+
+状態 152
+
+ 78 sequence: regex tSTRING fface . fface closers_opt exception_def_opt
+ 80 | regex tSTRING fface . closers_opt exception_def_opt
+
+ tCLOSERS shift, and go to state 144
+ tFACE shift, and go to state 57
+ tFFLAGS shift, and go to state 58
+ tSTRING shift, and go to state 50
+ tREGEX shift, and go to state 51
+ '(' shift, and go to state 145
+
+ $default reduce using rule 86 (closers_opt)
+
+ regex go to state 63
+ fface go to state 177
+ rule go to state 147
+ operator_regex go to state 148
+ closers_opt go to state 178
+
+
+状態 153
+
+ 79 sequence: regex fface fface . closers_opt exception_def_opt
+
+ tCLOSERS shift, and go to state 144
+ tSTRING shift, and go to state 50
+ tREGEX shift, and go to state 51
+ '(' shift, and go to state 62
+
+ $default reduce using rule 86 (closers_opt)
+
+ regex go to state 63
+ rule go to state 147
+ operator_regex go to state 148
+ closers_opt go to state 179
+
+
+状態 154
+
+ 81 sequence: regex fface closers_opt . exception_def_opt
+
+ tEXCEPTIONS shift, and go to state 173
+
+ $default reduce using rule 90 (exception_def_opt)
+
+ exception_def_opt go to state 180
+
+
+状態 155
+
+ 70 sequence_def: tSEQUENCES tARE sequence_list tEND tSEQUENCES .
+
+ $default reduce using rule 70 (sequence_def)
+
+
+状態 156
+
+ 72 sequence_list: sequence_list ',' sequence .
+
+ $default reduce using rule 72 (sequence_list)
+
+
+状態 157
+
+ 21 documentation: tDOCUMENTATION tIS long_string tEND tDOCUMENTATION .
+
+ $default reduce using rule 21 (documentation)
+
+
+状態 158
+
+ 27 ancestors_def: tANCESTORS tARE ancestors_list tEND tANCESTORS .
+
+ $default reduce using rule 27 (ancestors_def)
+
+
+状態 159
+
+ 29 ancestors_list: ancestors_list ',' tSTRING .
+
+ $default reduce using rule 29 (ancestors_list)
+
+
+状態 160
+
+ 41 rhs_list: rhs_list ',' . a_rhs
+
+ tFACE shift, and go to state 57
+ tFFLAGS shift, and go to state 58
+ tSTRING shift, and go to state 89
+ tLATEXSYMBOL shift, and go to state 90
+ tBACK_REF shift, and go to state 91
+ '(' shift, and go to state 59
+
+ a_rhs go to state 181
+ fface go to state 94
+
+
+状態 161
+
+ 51 rule: '(' tSTRING rhs_list ')' .
+
+ $default reduce using rule 51 (rule)
+
+
+状態 162
+
+ 60 keyword_regex: '(' regex rhs_list ')' .
+
+ $default reduce using rule 60 (keyword_regex)
+
+
+状態 163
+
+ 47 fface_sxp: fface_sxp '+' tFACE .
+
+ $default reduce using rule 47 (fface_sxp)
+
+
+状態 164
+
+ 48 fface_sxp: fface_sxp '+' tFFLAGS .
+
+ $default reduce using rule 48 (fface_sxp)
+
+
+状態 165
+
+ 52 keywords_def: tIN fface tARE keywords_rule_list tEND .
+
+ $default reduce using rule 52 (keywords_def)
+
+
+状態 166
+
+ 69 operator_regex: '(' regex rhs_list ')' .
+
+ $default reduce using rule 69 (operator_regex)
+
+
+状態 167
+
+ 61 operators_def: tIN fface tARE operators_rule_list tEND .
+
+ $default reduce using rule 61 (operators_def)
+
+
+状態 168
+
+ 74 sequence: tSTRING tSTRING fface fface . closers_opt exception_def_opt
+
+ tCLOSERS shift, and go to state 144
+ tSTRING shift, and go to state 50
+ tREGEX shift, and go to state 51
+ '(' shift, and go to state 62
+
+ $default reduce using rule 86 (closers_opt)
+
+ regex go to state 63
+ rule go to state 147
+ operator_regex go to state 148
+ closers_opt go to state 182
+
+
+状態 169
+
+ 76 sequence: tSTRING tSTRING fface closers_opt . exception_def_opt
+
+ tEXCEPTIONS shift, and go to state 173
+
+ $default reduce using rule 90 (exception_def_opt)
+
+ exception_def_opt go to state 183
+
+
+状態 170
+
+ 73 sequence: tSTRING tLATEXSYMBOL fface closers_opt . exception_def_opt
+
+ tEXCEPTIONS shift, and go to state 173
+
+ $default reduce using rule 90 (exception_def_opt)
+
+ exception_def_opt go to state 184
+
+
+状態 171
+
+ 89 closers_opt: tCLOSERS operators_def . tCLOSERS
+
+ tCLOSERS shift, and go to state 185
+
+
+状態 172
+
+ 75 sequence: tSTRING fface fface closers_opt . exception_def_opt
+
+ tEXCEPTIONS shift, and go to state 173
+
+ $default reduce using rule 90 (exception_def_opt)
+
+ exception_def_opt go to state 186
+
+
+状態 173
+
+ 91 exception_def_opt: tEXCEPTIONS . operators_def tEXCEPTIONS
+
+ tARE shift, and go to state 33
+ tIN shift, and go to state 34
+
+ operators_def go to state 187
+
+
+状態 174
+
+ 77 sequence: tSTRING fface closers_opt exception_def_opt .
+
+ $default reduce using rule 77 (sequence)
+
+
+状態 175
+
+ 82 sequence: '(' tSTRING rhs_list ')' . fface closers_opt exception_def_opt
+
+ tFACE shift, and go to state 57
+ tFFLAGS shift, and go to state 58
+ '(' shift, and go to state 59
+
+ fface go to state 188
+
+
+状態 176
+
+ 83 sequence: '(' regex rhs_list ')' . fface closers_opt exception_def_opt
+
+ tFACE shift, and go to state 57
+ tFFLAGS shift, and go to state 58
+ '(' shift, and go to state 59
+
+ fface go to state 189
+
+
+状態 177
+
+ 78 sequence: regex tSTRING fface fface . closers_opt exception_def_opt
+
+ tCLOSERS shift, and go to state 144
+ tSTRING shift, and go to state 50
+ tREGEX shift, and go to state 51
+ '(' shift, and go to state 62
+
+ $default reduce using rule 86 (closers_opt)
+
+ regex go to state 63
+ rule go to state 147
+ operator_regex go to state 148
+ closers_opt go to state 190
+
+
+状態 178
+
+ 80 sequence: regex tSTRING fface closers_opt . exception_def_opt
+
+ tEXCEPTIONS shift, and go to state 173
+
+ $default reduce using rule 90 (exception_def_opt)
+
+ exception_def_opt go to state 191
+
+
+状態 179
+
+ 79 sequence: regex fface fface closers_opt . exception_def_opt
+
+ tEXCEPTIONS shift, and go to state 173
+
+ $default reduce using rule 90 (exception_def_opt)
+
+ exception_def_opt go to state 192
+
+
+状態 180
+
+ 81 sequence: regex fface closers_opt exception_def_opt .
+
+ $default reduce using rule 81 (sequence)
+
+
+状態 181
+
+ 41 rhs_list: rhs_list ',' a_rhs .
+
+ $default reduce using rule 41 (rhs_list)
+
+
+状態 182
+
+ 74 sequence: tSTRING tSTRING fface fface closers_opt . exception_def_opt
+
+ tEXCEPTIONS shift, and go to state 173
+
+ $default reduce using rule 90 (exception_def_opt)
+
+ exception_def_opt go to state 193
+
+
+状態 183
+
+ 76 sequence: tSTRING tSTRING fface closers_opt exception_def_opt .
+
+ $default reduce using rule 76 (sequence)
+
+
+状態 184
+
+ 73 sequence: tSTRING tLATEXSYMBOL fface closers_opt exception_def_opt .
+
+ $default reduce using rule 73 (sequence)
+
+
+状態 185
+
+ 89 closers_opt: tCLOSERS operators_def tCLOSERS .
+
+ $default reduce using rule 89 (closers_opt)
+
+
+状態 186
+
+ 75 sequence: tSTRING fface fface closers_opt exception_def_opt .
+
+ $default reduce using rule 75 (sequence)
+
+
+状態 187
+
+ 91 exception_def_opt: tEXCEPTIONS operators_def . tEXCEPTIONS
+
+ tEXCEPTIONS shift, and go to state 194
+
+
+状態 188
+
+ 82 sequence: '(' tSTRING rhs_list ')' fface . closers_opt exception_def_opt
+
+ tCLOSERS shift, and go to state 144
+ tSTRING shift, and go to state 50
+ tREGEX shift, and go to state 51
+ '(' shift, and go to state 62
+
+ $default reduce using rule 86 (closers_opt)
+
+ regex go to state 63
+ rule go to state 147
+ operator_regex go to state 148
+ closers_opt go to state 195
+
+
+状態 189
+
+ 83 sequence: '(' regex rhs_list ')' fface . closers_opt exception_def_opt
+
+ tCLOSERS shift, and go to state 144
+ tSTRING shift, and go to state 50
+ tREGEX shift, and go to state 51
+ '(' shift, and go to state 62
+
+ $default reduce using rule 86 (closers_opt)
+
+ regex go to state 63
+ rule go to state 147
+ operator_regex go to state 148
+ closers_opt go to state 196
+
+
+状態 190
+
+ 78 sequence: regex tSTRING fface fface closers_opt . exception_def_opt
+
+ tEXCEPTIONS shift, and go to state 173
+
+ $default reduce using rule 90 (exception_def_opt)
+
+ exception_def_opt go to state 197
+
+
+状態 191
+
+ 80 sequence: regex tSTRING fface closers_opt exception_def_opt .
+
+ $default reduce using rule 80 (sequence)
+
+
+状態 192
+
+ 79 sequence: regex fface fface closers_opt exception_def_opt .
+
+ $default reduce using rule 79 (sequence)
+
+
+状態 193
+
+ 74 sequence: tSTRING tSTRING fface fface closers_opt exception_def_opt .
+
+ $default reduce using rule 74 (sequence)
+
+
+状態 194
+
+ 91 exception_def_opt: tEXCEPTIONS operators_def tEXCEPTIONS .
+
+ $default reduce using rule 91 (exception_def_opt)
+
+
+状態 195
+
+ 82 sequence: '(' tSTRING rhs_list ')' fface closers_opt . exception_def_opt
+
+ tEXCEPTIONS shift, and go to state 173
+
+ $default reduce using rule 90 (exception_def_opt)
+
+ exception_def_opt go to state 198
+
+
+状態 196
+
+ 83 sequence: '(' regex rhs_list ')' fface closers_opt . exception_def_opt
+
+ tEXCEPTIONS shift, and go to state 173
+
+ $default reduce using rule 90 (exception_def_opt)
+
+ exception_def_opt go to state 199
+
+
+状態 197
+
+ 78 sequence: regex tSTRING fface fface closers_opt exception_def_opt .
+
+ $default reduce using rule 78 (sequence)
+
+
+状態 198
+
+ 82 sequence: '(' tSTRING rhs_list ')' fface closers_opt exception_def_opt .
+
+ $default reduce using rule 82 (sequence)
+
+
+状態 199
+
+ 83 sequence: '(' regex rhs_list ')' fface closers_opt exception_def_opt .
+
+ $default reduce using rule 83 (sequence)
diff --git a/src/parsessh.y b/src/parsessh.y
new file mode 100644
index 0000000..21e9559
--- /dev/null
+++ b/src/parsessh.y
@@ -0,0 +1,804 @@
+%{ /* -*- c -*- */
+/*
+ * Grammar for parsing the style sheets
+ *
+ * Copyright (c) 1988-1993 Miguel Santana
+ * Copyright (c) 1995-1999 Akim Demaille, Miguel Santana
+ *
+ */
+
+/*
+ * This file is part of a2ps
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * $Id: parsessh.y,v 1.1.1.1.2.2 2007/12/29 01:58:35 mhatta Exp $
+ */
+
+#include "a2ps.h"
+#include "jobs.h"
+#include "ffaces.h"
+#include "ssheet.h"
+#include "message.h"
+#include "routines.h"
+#include "yy2ssh.h"
+#include "regex.h"
+
+#define YYDEBUG 1
+#define YYERROR_VERBOSE 1
+#define YYPRINT(file, type, value) yyprint (file, type, value)
+
+/* We need to use the same `const' as bison, to avoid the following
+ prototypes to diverge from the function declarations */
+#undef const
+#ifndef __cplusplus
+# ifndef __STDC__
+# define const
+# endif
+#endif
+
+/* Comes from the parser */
+extern int sshlineno;
+
+/* Comes from the caller */
+extern FILE * sshin;
+extern struct a2ps_job * job;
+extern const char * sshfilename;
+
+/* Local prototypes */
+void yyerror PARAMS ((const char *msg));
+static void yyprint ();
+
+/* Initilizes the obstacks */
+void sshlex_initialize PARAMS ((void));
+
+/* Comes from main.c */
+extern int highlight_level;
+
+int yylex PARAMS ((void));
+struct style_sheet * parse_style_sheet PARAMS ((const char * filename));
+
+/* Defines the style sheet being loaded */
+static struct style_sheet * parsed_style_sheet = NULL;
+
+%}
+%union
+{
+ int integer;
+ uchar * string;
+ struct pattern * pattern;
+ struct style_sheet * sheet;
+ struct rule * rule;
+ struct sequence * sequence;
+ struct darray * array;
+ struct words * words;
+ struct faced_string * faced_string;
+ enum face_e face; /* Face */
+ enum fflag_e fflags; /* Flags for faces */
+ struct fface_s fface; /* Flagged face */
+ enum case_sensitiveness sensitiveness;
+}
+
+%token tSTYLE tIS tEND tKEYWORDS tARE tIN tOPERATORS tSEQUENCES
+%token tFIRST tSECOND tALPHABET tALPHABETS tDOCUMENTATION tEXCEPTIONS
+%token tCASE tCSTRING tCCHAR tOPTIONAL tCLOSERS
+%token tWRITTEN tBY tVERSION tREQUIRES tA2PS tANCESTORS
+%token <face> tFACE
+%token <fflags> tFFLAGS
+%token <string> tSTRING tLATEXSYMBOL
+%token <pattern> tREGEX
+%token <sensitiveness> tSENSITIVENESS
+%token <integer> tBACK_REF
+
+%type <pattern> regex
+%type <fface> fface fface_sxp
+%type <string> authors documentation version long_string requirement
+%type <faced_string> a_rhs
+%type <rule> rule keyword_regex operator_regex
+%type <sheet> style_sheet definition_list
+%type <words> keywords_def keywords_rule_list
+%type <words> operators_def operators_rule_list
+%type <array> sequence_list sequence_def
+%type <words> exception_def_opt
+%type <array> ancestors_def ancestors_list
+%type <words> closers_opt
+%type <sensitiveness> case_def
+%type <array> rhs rhs_list
+%type <sequence> sequence
+%%
+
+/************************************************************************/
+/* Top most */
+/************************************************************************/
+file :
+ style_sheet
+ {
+ parsed_style_sheet = $1;
+ }
+ ;
+
+style_sheet :
+ tSTYLE tSTRING tIS definition_list tEND tSTYLE
+ {
+ $4->name = $2;
+ $4->key = "<No key yet>";
+ $$ = $4;
+ }
+ ;
+
+definition_list :
+ /* empty */ {
+ $$ = new_style_sheet ((const uchar *) "<no name>");
+ }
+ | definition_list tOPTIONAL tKEYWORDS keywords_def tKEYWORDS
+ {
+ if (highlight_level == 2) {
+ words_set_no_face ($4, Plain_fface);
+ words_merge_rules_unique ($1->keywords, $4);
+ } else
+ words_free ($4);
+ $$ = $1;
+ }
+ | definition_list tKEYWORDS keywords_def tKEYWORDS
+ {
+ words_set_no_face ($3, Plain_fface);
+ words_merge_rules_unique ($1->keywords, $3);
+ $$ = $1;
+ }
+ | definition_list tOPTIONAL tOPERATORS operators_def tOPERATORS
+ {
+ if (highlight_level == 2) {
+ words_set_no_face ($4, Plain_fface);
+ words_merge_rules_unique ($1->operators, $4);
+ } else
+ words_free ($4);
+ $$ = $1;
+ }
+ | definition_list tOPERATORS operators_def tOPERATORS
+ {
+ words_set_no_face ($3, Plain_fface);
+ words_merge_rules_unique ($1->operators, $3);
+ $$ = $1;
+ }
+ | definition_list tOPTIONAL sequence_def {
+ if (highlight_level == 2) {
+ da_concat ($1->sequences, $3);
+ da_erase ($3);
+ } else
+ da_free ($3, (da_map_func_t) free_sequence);
+ $$ = $1;
+ }
+ | definition_list sequence_def {
+ da_concat ($1->sequences, $2);
+ da_erase ($2);
+ $$ = $1;
+ }
+ | definition_list ancestors_def {
+ da_concat ($1->ancestors, $2);
+ da_erase ($2);
+ $$ = $1;
+ }
+ | definition_list tALPHABETS tARE tSTRING {
+ string_to_array ($1->alpha1, $4);
+ string_to_array ($1->alpha2, $4);
+ /* This is the syntax table used by regex */
+ free ($4);
+ $4 = NULL;
+ $$ = $1;
+ }
+ | definition_list tFIRST tALPHABET tIS tSTRING {
+ string_to_array ($1->alpha1, $5);
+ /* This is the syntax table used by regex */
+ free ($5);
+ $5 = NULL;
+ $$ = $1;
+ }
+ | definition_list tSECOND tALPHABET tIS tSTRING {
+ string_to_array ($1->alpha2, $5);
+ /* This is the syntax table used by regex */
+ free ($5);
+ $5 = NULL;
+ $$ = $1;
+ }
+ | definition_list case_def {
+ $1->sensitiveness = $2;
+ }
+ | definition_list documentation {
+ $1->documentation = $2;
+ }
+ | definition_list authors {
+ $1->author = $2;
+ }
+ | definition_list version {
+ style_sheet_set_version ($1, (const char *) $2);
+ }
+ | definition_list requirement {
+ /* Make sure now that we won't encounter new tokens.
+ * This avoids nasty error messages, or worse:
+ * unexpected behavior at run time */
+ if (!style_sheet_set_requirement ($1, (const char *) $2))
+ error (1, 0,
+ _("cannot process `%s' which requires a2ps version %s"),
+ sshfilename, $2);
+ }
+ ;
+
+/************************************************************************/
+/* Dealing with the inessential informations */
+/************************************************************************/
+requirement :
+ tREQUIRES tA2PS tSTRING { $$ = $3 ; }
+ | tREQUIRES tA2PS tVERSION tSTRING { $$ = $4 ; } ;
+
+documentation :
+ tDOCUMENTATION tIS long_string tEND tDOCUMENTATION { $$ = $3 ; };
+
+long_string: tSTRING { $$ = $1; }
+ | long_string tSTRING
+ {
+ size_t len1;
+ size_t len2;
+
+ len1 = ustrlen ($1);
+ $1[len1] = '\n';
+ len2 = ustrlen ($2);
+ $$ = XMALLOC (uchar, len1 + len2 + 2);
+ ustpcpy (ustpncpy ($$, $1, len1 + 1), $2);
+ free ($1);
+ free ($2);
+ }
+ ;
+
+authors : tWRITTEN tBY tSTRING { $$ = $3 ; };
+
+version :
+ tVERSION tIS tSTRING { $$ = $3 ; }
+ | tVERSION tSTRING { $$ = $2 ; };
+
+/************************************************************************/
+/* Dealing with the ancestors of a style sheet */
+/************************************************************************/
+ancestors_def : tANCESTORS tARE ancestors_list tEND tANCESTORS
+ {
+ /* The list of keys of style sheets from which it inherits */
+ $$ = $3;
+ }
+ ;
+
+ancestors_list: tSTRING
+ {
+ /* Create a list of ancestors, and drop the new one in */
+ $$ = da_new ("Ancestors tmp", 2,
+ da_linear, 2,
+ (da_print_func_t) da_str_print, NULL);
+ da_append ($$, $1);
+ }
+ | ancestors_list ',' tSTRING
+ {
+ da_append ($1, $3);
+ $$ = $1;
+ }
+ ;
+
+case_def : tCASE tSENSITIVENESS { $$ = $2 ; } ;
+
+/************************************************************************/
+/* Rhs */
+/* (Lists of (strings/regexp back references, face) */
+/************************************************************************/
+/* Regex split upon several lines */
+regex:
+ tREGEX
+ {
+ $$ = $1;
+ }
+ | regex tREGEX
+ {
+ /* Concatenate $2 to $1 makes $$ */
+ $$ = $1;
+ $$->pattern = XREALLOC ($$->pattern, char, $1->len + $2->len + 1);
+ strncpy ($$->pattern + $$->len, $2->pattern, $2->len);
+ $$->len += $2->len;
+ free ($2->pattern);
+ }
+ ;
+
+rhs:
+ a_rhs
+ {
+ $$ = rhs_new ();
+ rhs_add ($$, $1);
+ }
+ ;
+
+a_rhs:
+ tSTRING fface
+ {
+ $$ = faced_string_new ($1, 0, $2);
+ }
+ | tSTRING
+ {
+ $$ = faced_string_new ($1, 0, No_fface);
+ }
+ | fface
+ {
+ $$ = faced_string_new (NULL, 0, $1);
+ }
+ | tBACK_REF fface
+ {
+ $$ = faced_string_new (UNULL, $1, $2);
+ }
+ | tBACK_REF
+ {
+ $$ = faced_string_new (UNULL, $1, No_fface);
+ }
+ | tLATEXSYMBOL
+ {
+ $$ = faced_string_new ($1, 0, Symbol_fface);
+ }
+ ;
+
+rhs_list:
+ a_rhs
+ {
+ $$ = rhs_new ();
+ rhs_add ($$, $1);
+ }
+ |
+ rhs_list ',' a_rhs
+ {
+ rhs_add ($1, $3);
+ $$ = $1;
+ }
+ ;
+
+/*
+ * The flagged faces (One (true face or Invisible) plus flags)
+ */
+fface:
+ tFACE
+ {
+ fface_set_face ($$, $1);
+ fface_reset_flags ($$);
+ }
+ | tFFLAGS
+ {
+ fface_reset_face ($$);
+ fface_set_flags ($$, $1);
+ /* If there is no face, then set Invisible */
+ fface_add_flags ($$, ff_Invisible);
+ }
+ | '(' fface_sxp ')'
+ {
+ $$ = $2;
+ /* If there is no face, then set Invisible */
+ if (fface_get_face ($$) == No_face)
+ fface_add_flags ($$, ff_Invisible);
+ }
+ ;
+
+fface_sxp:
+ tFACE
+ {
+ fface_set_face($$, $1);
+ fface_reset_flags($$);
+ }
+ | tFFLAGS
+ {
+ fface_reset_face($$);
+ fface_set_flags($$, $1);
+ }
+ | fface_sxp '+' tFACE
+ {
+ /* FIXME: Overloading of the face should be forbidden */
+ $$ = $1;
+ fface_set_face($$, $3);
+ }
+ | fface_sxp '+' tFFLAGS
+ {
+ $$ = $1;
+ fface_add_flags($$, $3);
+ }
+ ;
+
+/************************************************************************/
+/* Symbol atoms */
+/************************************************************************/
+/* A rule is the group of 1. string to match, 2. the rhs
+ *
+ * In the special shortcut where no face is given, see where
+ * rule_list appears for resolving */
+rule: tSTRING rhs
+ {
+ $$ = rule_new ($1, NULL, $2,
+ sshfilename, sshlineno);
+ }
+ | tSTRING
+ {
+ $$ = rule_new ($1, NULL,
+ rhs_new_single (UNULL, 0, No_fface),
+ sshfilename, sshlineno);
+ }
+ | '(' tSTRING rhs_list ')'
+ {
+ $$ = rule_new ($2, NULL, $3,
+ sshfilename, sshlineno);
+ }
+ ;
+
+/************************************************************************/
+/* Keywords lists */
+/* We make the difference because the regex must be compiled with a */
+/* difference (which is \\b\\(%s\\)\\b) between keywords and operators */
+/************************************************************************/
+keywords_def : tIN fface tARE keywords_rule_list tEND {
+ words_set_no_face ($4, $2);
+ $$ = $4;
+ }
+ | tARE keywords_rule_list tEND {
+ /* First of all, the No_face must be turned into Plain */
+ $$ = $2;
+ }
+ ;
+
+keywords_rule_list:
+ rule
+ {
+ $$ = words_new ("Keywords: Strings", "Keywords: Regexps", 100, 100);
+ words_add_string ($$, $1);
+ }
+ | keyword_regex
+ {
+ $$ = words_new ("Keywords: Strings", "Keywords: Regexps", 100, 100);
+ words_add_regex ($$, $1);
+ }
+ | keywords_rule_list ',' rule
+ {
+ words_add_string ($1, $3);
+ $$ = $1;
+ }
+ | keywords_rule_list ',' keyword_regex
+ {
+ words_add_regex ($1, $3);
+ $$ = $1;
+ }
+ ;
+
+/* A rule is the group of 1. string to match, 2. string to
+ * print, 3. face of the string to print. In the special
+ * shortcut where no face is given, see where rule_list appears
+ * for resolving */
+keyword_regex:
+ regex rhs
+ {
+ $$ = keyword_rule_new (UNULL, $1, $2,
+ sshfilename, sshlineno);
+ }
+ | regex
+ {
+ $$ = keyword_rule_new (UNULL, $1,
+ rhs_new_single (UNULL, 0,
+ No_fface),
+ sshfilename, sshlineno);
+ }
+ | '(' regex rhs_list ')'
+ {
+ $$ = keyword_rule_new (UNULL, $2, $3,
+ sshfilename, sshlineno);
+ }
+ ;
+
+/************************************************************************/
+/* Operators lists */
+/************************************************************************/
+operators_def: tIN fface tARE operators_rule_list tEND {
+ words_set_no_face ($4, $2);
+ $$ = $4;
+ }
+ | tARE operators_rule_list tEND {
+ /* First of all, the No_face must be turned into Plain */
+ $$ = $2;
+ }
+ ;
+
+operators_rule_list:
+ rule
+ {
+ $$ = words_new ("Operators: Strings", "Operators: Regexps",
+ 100, 100);
+ words_add_string ($$, $1);
+ }
+ | operator_regex
+ {
+ $$ = words_new ("Operators: Strings", "Operators: Regexps",
+ 100, 100);
+ words_add_regex ($$, $1);
+ }
+ | operators_rule_list ',' rule
+ {
+ words_add_string ($1, $3);
+ $$ = $1;
+ }
+ | operators_rule_list ',' operator_regex
+ {
+ words_add_regex ($1, $3);
+ $$ = $1;
+ }
+ ;
+
+/* A rule is the group of 1. string to match, 2. string to
+ * print, 3. face of the string to print. In the special
+ * shortcut where no face is given, see where rule_list appears
+ * for resolving */
+operator_regex:
+ regex rhs
+ {
+ $$ = rule_new (UNULL, $1, $2,
+ sshfilename, sshlineno);
+ }
+ | regex
+ {
+ $$ = rule_new (UNULL, $1,
+ rhs_new_single (UNULL, 0, No_fface),
+ sshfilename, sshlineno);
+ }
+ | '(' regex rhs_list ')'
+ {
+ $$ = rule_new (UNULL, $2, $3,
+ sshfilename, sshlineno);
+ }
+ ;
+
+/************************************************************************/
+/* Dealing with the sequences */
+/************************************************************************/
+sequence_def : tSEQUENCES tARE sequence_list tEND tSEQUENCES { $$ = $3; }
+ ;
+
+sequence_list: sequence {
+ $$ = da_new ("Sequence tmp", 100,
+ da_linear, 100,
+ (da_print_func_t) sequence_self_print, NULL);
+ da_append ($$, $1);
+ }
+ | sequence_list ',' sequence {
+ da_append ($1, $3);
+ $$ = $1;
+ }
+ ;
+
+/*
+ * I can understand one will get sick reading this. It hurts, indeed,
+ * but is necessary because of shift/reduce conflicts if one uses
+ *
+ * sequence: operators_rule face closers_opt exception_def_opt
+ *
+ * The problem is that when bison/yacc reads this
+ *
+ * <word> <word> . <face1> <face2>
+ *
+ * it doesn't know whether <face1> should be in $1, or in $2.
+ * So we have to inline the rule at hand...
+ */
+sequence:
+ /* Expansion of each possibility for
+ * <operators_rule> <face> <closers_opt> <exception_def_opt>
+ */
+ tSTRING tLATEXSYMBOL fface closers_opt exception_def_opt
+ {
+ struct rule * open_rule;
+ open_rule = rule_new ($1, NULL,
+ rhs_new_single ($2, 0, Symbol_fface),
+ sshfilename, sshlineno);
+ $$ = sequence_new (open_rule, $3, $4, $5);
+ }
+ | tSTRING tSTRING fface fface closers_opt exception_def_opt
+ {
+ struct rule * open_rule;
+ open_rule = rule_new ($1, NULL,
+ rhs_new_single ($2, 0, $3),
+ sshfilename, sshlineno);
+ $$ = sequence_new (open_rule, $4, $5, $6);
+ }
+ | tSTRING fface fface closers_opt exception_def_opt
+ {
+ struct rule * open_rule;
+ open_rule = rule_new ($1, NULL,
+ rhs_new_single (UNULL, 0, $2),
+ sshfilename, sshlineno);
+ $$ = sequence_new (open_rule, $3, $4, $5);
+ }
+ | tSTRING tSTRING fface closers_opt exception_def_opt
+ {
+ struct rule * open_rule;
+ open_rule = rule_new ($1, NULL,
+ rhs_new_single ($2, 0, $3),
+ sshfilename, sshlineno);
+ $$ = sequence_new (open_rule, $3, $4, $5);
+ }
+ | tSTRING fface closers_opt exception_def_opt
+ {
+ struct rule * open_rule;
+ open_rule = rule_new ($1, NULL,
+ rhs_new_single (UNULL, 0, $2),
+ sshfilename, sshlineno);
+ $$ = sequence_new (open_rule, $2, $3, $4);
+ }
+ | regex tSTRING fface fface closers_opt exception_def_opt
+ {
+ struct rule * open_rule;
+ open_rule = rule_new (UNULL, $1,
+ rhs_new_single ($2, 0, $3),
+ sshfilename, sshlineno);
+ $$ = sequence_new (open_rule, $4, $5, $6);
+ }
+ | regex fface fface closers_opt exception_def_opt
+ {
+ struct rule * open_rule;
+ open_rule = rule_new (UNULL, $1,
+ rhs_new_single (UNULL, 0, $2),
+ sshfilename, sshlineno);
+ $$ = sequence_new (open_rule, $3, $4, $5);
+ }
+ | regex tSTRING fface closers_opt exception_def_opt
+ {
+ struct rule * open_rule;
+ open_rule = rule_new (UNULL, $1,
+ rhs_new_single ($2, 0, $3),
+ sshfilename, sshlineno);
+ $$ = sequence_new (open_rule, $3, $4, $5);
+ }
+ | regex fface closers_opt exception_def_opt
+ {
+ struct rule * open_rule;
+ open_rule = rule_new (UNULL, $1,
+ rhs_new_single (UNULL, 0, No_fface),
+ sshfilename, sshlineno);
+ $$ = sequence_new (open_rule, $2, $3, $4);
+ }
+ | '(' tSTRING rhs_list ')' fface closers_opt exception_def_opt
+ {
+ struct rule * open_rule;
+ open_rule = rule_new ($2, NULL, $3,
+ sshfilename, sshlineno);
+ $$ = sequence_new (open_rule, $5, $6, $7);
+ }
+ | '(' regex rhs_list ')' fface closers_opt exception_def_opt
+ {
+ struct rule * open_rule;
+ open_rule = rule_new (UNULL, $2, $3,
+ sshfilename, sshlineno);
+ $$ = sequence_new (open_rule, $5, $6, $7);
+ }
+/* End of the brute force expansion */
+ | tCSTRING
+ {
+ $$ = new_C_string_sequence ("\"");
+ }
+ | tCCHAR
+ {
+ $$ = new_C_string_sequence ("\'");
+ }
+ ;
+
+closers_opt:
+ /* Nothing */
+ {
+ /* This is a shortcut which means "up to the end of the line". */
+ $$ = words_new ("Closing: Strings", "Closing: Regexps", 2, 2);
+ words_add_string ($$, rule_new (xustrdup ("\n"), NULL,
+ rhs_new_single (NULL, 0,
+ No_fface),
+ sshfilename, sshlineno));
+ }
+ | rule
+ {
+ /* Only one */
+ $$ = words_new ("Closing: Strings", "Closing: Regexps", 2, 2);
+ words_add_string ($$, $1);
+ }
+ | operator_regex
+ {
+ /* Only one */
+ $$ = words_new ("Closing: Strings", "Closing: Regexps", 2, 2);
+ words_add_regex ($$, $1);
+ }
+ | tCLOSERS operators_def tCLOSERS
+ {
+ /* Several, comma separated, between () */
+ $$ = $2;
+ }
+ ;
+
+exception_def_opt:
+ /* Nothing */
+ {
+ $$ = words_new ("Exceptions: Strings", "Exceptions: Regexps", 1, 1);
+ }
+ | tEXCEPTIONS operators_def tEXCEPTIONS
+ {
+ $$ = $2;
+ };
+
+%%
+
+void
+yyerror (const char *msg)
+{
+ error_at_line (1, 0, sshfilename, sshlineno, msg);
+}
+
+/*
+ * FIXME: Cover the other relevant types
+ */
+static void
+yyprint (FILE *file, int type, YYSTYPE value)
+{
+ switch (type) {
+ case tBACK_REF:
+ fprintf (file, " \\%d", value.integer);
+ break;
+
+ case tFFLAGS:
+ putc (' ', file);
+ fflag_self_print (value.fflags, file);
+ break;
+
+ case tFACE:
+ fprintf (file, " %s", face_to_string (value.face));
+ break;
+
+ case tREGEX:
+ fprintf (file, " /%s/", value.pattern->pattern);
+ break;
+
+ case tSTRING:
+ fprintf (file, " \"%s\"", value.string);
+ break;
+ }
+}
+
+struct style_sheet *
+parse_style_sheet (const char * filename)
+{
+ int res;
+
+ sshfilename = filename;
+ sshlineno = 1;
+ sshin = xrfopen (sshfilename);
+
+ message (msg_file | msg_sheet | msg_parse,
+ (stderr, "Parsing file `%s'\n", sshfilename));
+
+ sshlex_initialize ();
+
+ if (msg_test (msg_parse))
+ yydebug = true;
+ res = yyparse (); /* FIXME: test the result of parsing */
+
+ if (msg_test (msg_sheet)) {
+ fprintf (stderr, "---------- Right after parsing of %s\n",
+ parsed_style_sheet->key);
+ style_sheet_self_print (parsed_style_sheet, stderr);
+ fprintf (stderr, "---------- End of after parsing of %s\n",
+ parsed_style_sheet->key);
+ }
+
+ fclose (sshin);
+ return parsed_style_sheet;
+}
diff --git a/src/read.c b/src/read.c
new file mode 100644
index 0000000..1878867
--- /dev/null
+++ b/src/read.c
@@ -0,0 +1,206 @@
+/*
+ * read.c --- routines of input with no style sheets
+ *
+ * Copyright (c) 1988-1993 Miguel Santana
+ * Copyright (c) 1995-2000 Akim Demaille, Miguel Santana
+ *
+ */
+
+/*
+ * This file is part of a2ps.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "main.h"
+#include "buffer.h"
+
+
+/*-------------------------------------------------------.
+| Returns a single char (EOF for end-of-file). |
+| |
+| Does the nroff's replacement for underline, bold etc. |
+`-------------------------------------------------------*/
+
+static int
+plain_getc (buffer_t * buffer, enum face_e *face)
+{
+ uchar c;
+
+ if (buffer_is_empty (buffer))
+ {
+ buffer_get (buffer);
+
+ /* We don't trust liba2ps for the line numbers, because if a2ps
+ skips some lines (e.g., --strip-level, or INVISIBLE), liba2ps
+ will number upon output lines, not imput lines, which is what
+ is expected. */
+ (CURRENT_FILE (job))->lines = buffer->line;
+
+ if (buffer->len == 0)
+ return EOF;
+ }
+
+ *face = Plain;
+ c = buffer->content[(buffer->curr)++];
+
+ /* Check if it is a special nroff'ed sequence */
+ if (buffer->content[buffer->curr] == '\b')
+ {
+ /* We might be dealing with misceleanous nroff'ed pages. */
+ const uchar *input = buffer->content + buffer->curr + 1;
+
+ /* This might be a bolding sequence. The bad news is that some
+ strange systems build the bold sequences with only one
+ rewriting, not the 3 usuals.
+
+ Super strong `_', seen in Sun's mpeg_rc doc. */
+ if (c == input[0] &&
+ '\b' == input[1] &&
+ c == input[2] &&
+ '\b' == input[3] &&
+ c == input[4] &&
+ '\b' == input[5] &&
+ c == input[6])
+ {
+ *face = Label_strong;
+ buffer->curr += 8;
+ }
+ else if (c == input[0] &&
+ '\b' == input[1] &&
+ c == input[2] &&
+ '\b' == input[3] &&
+ c == input[4])
+ {
+ *face = Keyword_strong;
+ buffer->curr += 6;
+ }
+ else if (c == input[0] &&
+ '\b' == input[1] &&
+ c == input[2])
+ {
+ *face = Keyword_strong;
+ buffer->curr += 4;
+ }
+ else if (c == input[0])
+ {
+ *face = Keyword_strong;
+ buffer->curr += 2;
+ }
+ /* If C is `_', then set font to italic and move to next char.
+ */
+ else if (c == '_')
+ {
+ char c2 = input[0];
+ /* Winner of the cup: mpeg_rc, from Sun, where it tries both
+ to underline, and to boldize. */
+ if ('\b' == input[1] &&
+ c2 == input[2] &&
+ '\b' == input[3] &&
+ c2 == input[4] &&
+ '\b' == input[5] &&
+ c2 == input[6])
+ {
+ *face = Label_strong;
+ c = c2;
+ buffer->curr += 8;
+ }
+ else
+ {
+ *face = Keyword;
+ c = input[0];
+ buffer->curr += 2;
+ }
+ }
+ /* Seen in gcc.1: o;\b;+, seen in cccp.1: +;\b;o to have an
+ itemizing symbol. */
+ else if (('o' == c &&
+ '+' == input[0])
+ || ('+' == c &&
+ 'o' == input[0]))
+ {
+ *face = Symbol;
+ buffer->curr += 2;
+ c = 0305; /* \oplus in LaTeX */
+ }
+ /* Seen in groff.1 : c;\b;O, for copyright */
+ else if ('c' == c &&
+ 'O' == input[0])
+ {
+ *face = Symbol;
+ buffer->curr += 2;
+ c = 0343; /* \copyright. */
+ }
+ /* Seen in gtroff.1 : +;\b;_, for plus or minus */
+ else if ('+' == c &&
+ '_' == input[0])
+ {
+ *face = Symbol;
+ buffer->curr += 2;
+ c = 0261;
+ }
+ /* Seen in geqn.1 : ~;\b>;\b;_ for greater or equal */
+ else if ('~' == c &&
+ '>' == input[0] &&
+ '\b' == input[1] &&
+ '_' == input[2])
+ {
+ *face = Symbol;
+ buffer->curr += 4;
+ c = 0263;
+ }
+ /* Less than or equal to. */
+ else if ('~' == c &&
+ '<' == input[0] &&
+ '\b' == input[1] &&
+ '_' == input[2])
+ {
+ *face = Symbol;
+ buffer->curr += 4;
+ c = 0243;
+ }
+ /* Underlined: x;\b;_ . Note that we have a conflict here in the
+ case x == '+' (see above). This choice seems the best. */
+ else if ('_' == input[0])
+ {
+ *face = Keyword;
+ buffer->curr += 2;
+ }
+ /* (Should be last). In some case, headers or footers too big,
+ nroff backslashes so that both chars. are superimposed. We
+ decided to keep only the first one. */
+ else if (((CURRENT_FILE (job)->lines + 3) % 66 == 0)
+ || ((CURRENT_FILE (job)->lines - 4) % 66 == 0))
+ {
+ buffer->curr += 2;
+ }
+ /* else: treate the backslash as a special characters */
+ }
+ return c;
+}
+
+/*
+ * Print a file to postscript (no style)
+ */
+void
+plain_print_postscript (a2ps_job * Job, buffer_t * buffer)
+{
+ enum face_e face = Plain;
+ int c;
+
+ while ((c = plain_getc (buffer, &face)) != EOF)
+ ps_print_char (Job, c, face);
+}
diff --git a/src/read.h b/src/read.h
new file mode 100644
index 0000000..4b4e080
--- /dev/null
+++ b/src/read.h
@@ -0,0 +1,38 @@
+/*
+ * read.h
+ *
+ * routines of input with no style sheets
+ * Copyright (c) 1988, 89, 90, 91, 92, 93 Miguel Santana
+ * Copyright (c) 1995, 96, 97, 98 Akim Demaille, Miguel Santana
+ * $Id: read.h,v 1.1.1.1.2.1 2007/12/29 01:58:36 mhatta Exp $
+ */
+
+/*
+ * This file is part of a2ps.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _READ_H_
+#define _READ_H_
+#include "faces.h"
+#include "buffer.h"
+
+struct a2ps_job;
+
+void plain_print_postscript PARAMS ((struct a2ps_job * job,
+ buffer_t * buffer));
+#endif /* not defined(_READ_H_) */
diff --git a/src/regex.c b/src/regex.c
new file mode 100644
index 0000000..b0845f7
--- /dev/null
+++ b/src/regex.c
@@ -0,0 +1,5835 @@
+/* Extended regular expression matching and search library,
+ version 0.12.
+ (Implements POSIX draft P1003.2/D11.2, except for some of the
+ internationalization features.)
+ Copyright (C) 1993, 94, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 3 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* AIX requires this to be the first thing in the file. */
+#if defined _AIX && !defined REGEX_MALLOC
+ #pragma alloca
+#endif
+
+#undef _GNU_SOURCE
+#define _GNU_SOURCE
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifndef PARAMS
+# if defined __GNUC__ || (defined __STDC__ && __STDC__)
+# define PARAMS(args) args
+# else
+# define PARAMS(args) ()
+# endif /* GCC. */
+#endif /* Not PARAMS. */
+
+#if defined STDC_HEADERS && !defined emacs
+# include <stddef.h>
+#else
+/* We need this for `regex.h', and perhaps for the Emacs include files. */
+# include <sys/types.h>
+#endif
+
+#define WIDE_CHAR_SUPPORT (HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_BTOWC)
+
+/* For platform which support the ISO C amendement 1 functionality we
+ support user defined character classes. */
+#if defined _LIBC || WIDE_CHAR_SUPPORT
+/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */
+# include <wchar.h>
+# include <wctype.h>
+#endif
+
+#ifdef _LIBC
+/* We have to keep the namespace clean. */
+# define regfree(preg) __regfree (preg)
+# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef)
+# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags)
+# define regerror(errcode, preg, errbuf, errbuf_size) \
+ __regerror(errcode, preg, errbuf, errbuf_size)
+# define re_set_registers(bu, re, nu, st, en) \
+ __re_set_registers (bu, re, nu, st, en)
+# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \
+ __re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
+# define re_match(bufp, string, size, pos, regs) \
+ __re_match (bufp, string, size, pos, regs)
+# define re_search(bufp, string, size, startpos, range, regs) \
+ __re_search (bufp, string, size, startpos, range, regs)
+# define re_compile_pattern(pattern, length, bufp) \
+ __re_compile_pattern (pattern, length, bufp)
+# define re_set_syntax(syntax) __re_set_syntax (syntax)
+# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \
+ __re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop)
+# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp)
+
+#define btowc __btowc
+#endif
+
+/* This is for other GNU distributions with internationalized messages. */
+#if HAVE_LIBINTL_H || defined _LIBC
+# include <libintl.h>
+#else
+# define gettext(msgid) (msgid)
+#endif
+
+#ifndef gettext_noop
+/* This define is so xgettext can find the internationalizable
+ strings. */
+# define gettext_noop(String) String
+#endif
+
+/* The `emacs' switch turns on certain matching commands
+ that make sense only in Emacs. */
+#ifdef emacs
+
+# include "lisp.h"
+# include "buffer.h"
+# include "syntax.h"
+
+#else /* not emacs */
+
+/* If we are not linking with Emacs proper,
+ we can't use the relocating allocator
+ even if config.h says that we can. */
+# undef REL_ALLOC
+
+# if defined STDC_HEADERS || defined _LIBC
+# include <stdlib.h>
+# else
+char *malloc ();
+char *realloc ();
+# endif
+
+/* When used in Emacs's lib-src, we need to get bzero and bcopy somehow.
+ If nothing else has been done, use the method below. */
+# ifdef INHIBIT_STRING_HEADER
+# if !(defined HAVE_BZERO && defined HAVE_BCOPY)
+# if !defined bzero && !defined bcopy
+# undef INHIBIT_STRING_HEADER
+# endif
+# endif
+# endif
+
+/* This is the normal way of making sure we have a bcopy and a bzero.
+ This is used in most programs--a few other programs avoid this
+ by defining INHIBIT_STRING_HEADER. */
+# ifndef INHIBIT_STRING_HEADER
+# if defined HAVE_STRING_H || defined STDC_HEADERS || defined _LIBC
+# include <string.h>
+# ifndef bzero
+# ifndef _LIBC
+# define bzero(s, n) (memset (s, '\0', n), (s))
+# else
+# define bzero(s, n) __bzero (s, n)
+# endif
+# endif
+# else
+# include <strings.h>
+# ifndef memcmp
+# define memcmp(s1, s2, n) bcmp (s1, s2, n)
+# endif
+# ifndef memcpy
+# define memcpy(d, s, n) (bcopy (s, d, n), (d))
+# endif
+# endif
+# endif
+
+/* Define the syntax stuff for \<, \>, etc. */
+
+/* This must be nonzero for the wordchar and notwordchar pattern
+ commands in re_match_2. */
+# ifndef Sword
+# define Sword 1
+# endif
+
+# ifdef SWITCH_ENUM_BUG
+# define SWITCH_ENUM_CAST(x) ((int)(x))
+# else
+# define SWITCH_ENUM_CAST(x) (x)
+# endif
+
+/* How many characters in the character set. */
+# define CHAR_SET_SIZE 256
+
+# ifdef SYNTAX_TABLE
+
+extern char *re_syntax_table;
+
+# else /* not SYNTAX_TABLE */
+
+static char re_syntax_table[CHAR_SET_SIZE];
+
+static void
+init_syntax_once ()
+{
+ register int c;
+ static int done = 0;
+
+ if (done)
+ return;
+
+ bzero (re_syntax_table, sizeof re_syntax_table);
+
+ for (c = 'a'; c <= 'z'; c++)
+ re_syntax_table[c] = Sword;
+
+ for (c = 'A'; c <= 'Z'; c++)
+ re_syntax_table[c] = Sword;
+
+ for (c = '0'; c <= '9'; c++)
+ re_syntax_table[c] = Sword;
+
+ re_syntax_table['_'] = Sword;
+
+ done = 1;
+}
+
+# endif /* not SYNTAX_TABLE */
+
+# define SYNTAX(c) re_syntax_table[c]
+
+#endif /* not emacs */
+
+/* Get the interface, including the syntax bits. */
+#include <regex.h>
+
+/* isalpha etc. are used for the character classes. */
+#include <ctype.h>
+
+/* Jim Meyering writes:
+
+ "... Some ctype macros are valid only for character codes that
+ isascii says are ASCII (SGI's IRIX-4.0.5 is one such system --when
+ using /bin/cc or gcc but without giving an ansi option). So, all
+ ctype uses should be through macros like ISPRINT... If
+ STDC_HEADERS is defined, then autoconf has verified that the ctype
+ macros don't need to be guarded with references to isascii. ...
+ Defining isascii to 1 should let any compiler worth its salt
+ eliminate the && through constant folding."
+ Solaris defines some of these symbols so we must undefine them first. */
+
+#undef ISASCII
+#if defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII)
+# define ISASCII(c) 1
+#else
+# define ISASCII(c) isascii(c)
+#endif
+
+#ifdef isblank
+# define ISBLANK(c) (ISASCII (c) && isblank (c))
+#else
+# define ISBLANK(c) ((c) == ' ' || (c) == '\t')
+#endif
+#ifdef isgraph
+# define ISGRAPH(c) (ISASCII (c) && isgraph (c))
+#else
+# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
+#endif
+
+#undef ISPRINT
+#define ISPRINT(c) (ISASCII (c) && isprint (c))
+#define ISDIGIT(c) (ISASCII (c) && isdigit (c))
+#define ISALNUM(c) (ISASCII (c) && isalnum (c))
+#define ISALPHA(c) (ISASCII (c) && isalpha (c))
+#define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
+#define ISLOWER(c) (ISASCII (c) && islower (c))
+#define ISPUNCT(c) (ISASCII (c) && ispunct (c))
+#define ISSPACE(c) (ISASCII (c) && isspace (c))
+#define ISUPPER(c) (ISASCII (c) && isupper (c))
+#define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
+
+#ifdef _tolower
+# define TOLOWER(c) _tolower(c)
+#else
+# define TOLOWER(c) tolower(c)
+#endif
+
+#ifndef NULL
+# define NULL (void *)0
+#endif
+
+/* We remove any previous definition of `SIGN_EXTEND_CHAR',
+ since ours (we hope) works properly with all combinations of
+ machines, compilers, `char' and `unsigned char' argument types.
+ (Per Bothner suggested the basic approach.) */
+#undef SIGN_EXTEND_CHAR
+#if __STDC__
+# define SIGN_EXTEND_CHAR(c) ((signed char) (c))
+#else /* not __STDC__ */
+/* As in Harbison and Steele. */
+# define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128)
+#endif
+
+/* Should we use malloc or alloca? If REGEX_MALLOC is not defined, we
+ use `alloca' instead of `malloc'. This is because using malloc in
+ re_search* or re_match* could cause memory leaks when C-g is used in
+ Emacs; also, malloc is slower and causes storage fragmentation. On
+ the other hand, malloc is more portable, and easier to debug.
+
+ Because we sometimes use alloca, some routines have to be macros,
+ not functions -- `alloca'-allocated space disappears at the end of the
+ function it is called in. */
+
+#ifdef REGEX_MALLOC
+
+# define REGEX_ALLOCATE malloc
+# define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize)
+# define REGEX_FREE free
+
+#else /* not REGEX_MALLOC */
+
+/* Emacs already defines alloca, sometimes. */
+# ifndef alloca
+
+/* Make alloca work the best possible way. */
+# ifdef __GNUC__
+# define alloca __builtin_alloca
+# else /* not __GNUC__ */
+# if HAVE_ALLOCA_H
+# include <alloca.h>
+# endif /* HAVE_ALLOCA_H */
+# endif /* not __GNUC__ */
+
+# endif /* not alloca */
+
+# define REGEX_ALLOCATE alloca
+
+/* Assumes a `char *destination' variable. */
+# define REGEX_REALLOCATE(source, osize, nsize) \
+ (destination = (char *) alloca (nsize), \
+ memcpy (destination, source, osize))
+
+/* No need to do anything to free, after alloca. */
+# define REGEX_FREE(arg) ((void)0) /* Do nothing! But inhibit gcc warning. */
+
+#endif /* not REGEX_MALLOC */
+
+/* Define how to allocate the failure stack. */
+
+#if defined REL_ALLOC && defined REGEX_MALLOC
+
+# define REGEX_ALLOCATE_STACK(size) \
+ r_alloc (&failure_stack_ptr, (size))
+# define REGEX_REALLOCATE_STACK(source, osize, nsize) \
+ r_re_alloc (&failure_stack_ptr, (nsize))
+# define REGEX_FREE_STACK(ptr) \
+ r_alloc_free (&failure_stack_ptr)
+
+#else /* not using relocating allocator */
+
+# ifdef REGEX_MALLOC
+
+# define REGEX_ALLOCATE_STACK malloc
+# define REGEX_REALLOCATE_STACK(source, osize, nsize) realloc (source, nsize)
+# define REGEX_FREE_STACK free
+
+# else /* not REGEX_MALLOC */
+
+# define REGEX_ALLOCATE_STACK alloca
+
+# define REGEX_REALLOCATE_STACK(source, osize, nsize) \
+ REGEX_REALLOCATE (source, osize, nsize)
+/* No need to explicitly free anything. */
+# define REGEX_FREE_STACK(arg)
+
+# endif /* not REGEX_MALLOC */
+#endif /* not using relocating allocator */
+
+
+/* True if `size1' is non-NULL and PTR is pointing anywhere inside
+ `string1' or just past its end. This works if PTR is NULL, which is
+ a good thing. */
+#define FIRST_STRING_P(ptr) \
+ (size1 && string1 <= (ptr) && (ptr) <= string1 + size1)
+
+/* (Re)Allocate N items of type T using malloc, or fail. */
+#define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t)))
+#define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t)))
+#define RETALLOC_IF(addr, n, t) \
+ if (addr) RETALLOC((addr), (n), t); else (addr) = TALLOC ((n), t)
+#define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t)))
+
+#define BYTEWIDTH 8 /* In bits. */
+
+#define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
+
+#undef MAX
+#undef MIN
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+
+typedef char boolean;
+#define false 0
+#define true 1
+
+static int re_match_2_internal PARAMS ((struct re_pattern_buffer *bufp,
+ const char *string1, int size1,
+ const char *string2, int size2,
+ int pos,
+ struct re_registers *regs,
+ int stop));
+
+/* These are the command codes that appear in compiled regular
+ expressions. Some opcodes are followed by argument bytes. A
+ command code can specify any interpretation whatsoever for its
+ arguments. Zero bytes may appear in the compiled regular expression. */
+
+typedef enum
+{
+ no_op = 0,
+
+ /* Succeed right away--no more backtracking. */
+ succeed,
+
+ /* Followed by one byte giving n, then by n literal bytes. */
+ exactn,
+
+ /* Matches any (more or less) character. */
+ anychar,
+
+ /* Matches any one char belonging to specified set. First
+ following byte is number of bitmap bytes. Then come bytes
+ for a bitmap saying which chars are in. Bits in each byte
+ are ordered low-bit-first. A character is in the set if its
+ bit is 1. A character too large to have a bit in the map is
+ automatically not in the set. */
+ charset,
+
+ /* Same parameters as charset, but match any character that is
+ not one of those specified. */
+ charset_not,
+
+ /* Start remembering the text that is matched, for storing in a
+ register. Followed by one byte with the register number, in
+ the range 0 to one less than the pattern buffer's re_nsub
+ field. Then followed by one byte with the number of groups
+ inner to this one. (This last has to be part of the
+ start_memory only because we need it in the on_failure_jump
+ of re_match_2.) */
+ start_memory,
+
+ /* Stop remembering the text that is matched and store it in a
+ memory register. Followed by one byte with the register
+ number, in the range 0 to one less than `re_nsub' in the
+ pattern buffer, and one byte with the number of inner groups,
+ just like `start_memory'. (We need the number of inner
+ groups here because we don't have any easy way of finding the
+ corresponding start_memory when we're at a stop_memory.) */
+ stop_memory,
+
+ /* Match a duplicate of something remembered. Followed by one
+ byte containing the register number. */
+ duplicate,
+
+ /* Fail unless at beginning of line. */
+ begline,
+
+ /* Fail unless at end of line. */
+ endline,
+
+ /* Succeeds if at beginning of buffer (if emacs) or at beginning
+ of string to be matched (if not). */
+ begbuf,
+
+ /* Analogously, for end of buffer/string. */
+ endbuf,
+
+ /* Followed by two byte relative address to which to jump. */
+ jump,
+
+ /* Same as jump, but marks the end of an alternative. */
+ jump_past_alt,
+
+ /* Followed by two-byte relative address of place to resume at
+ in case of failure. */
+ on_failure_jump,
+
+ /* Like on_failure_jump, but pushes a placeholder instead of the
+ current string position when executed. */
+ on_failure_keep_string_jump,
+
+ /* Throw away latest failure point and then jump to following
+ two-byte relative address. */
+ pop_failure_jump,
+
+ /* Change to pop_failure_jump if know won't have to backtrack to
+ match; otherwise change to jump. This is used to jump
+ back to the beginning of a repeat. If what follows this jump
+ clearly won't match what the repeat does, such that we can be
+ sure that there is no use backtracking out of repetitions
+ already matched, then we change it to a pop_failure_jump.
+ Followed by two-byte address. */
+ maybe_pop_jump,
+
+ /* Jump to following two-byte address, and push a dummy failure
+ point. This failure point will be thrown away if an attempt
+ is made to use it for a failure. A `+' construct makes this
+ before the first repeat. Also used as an intermediary kind
+ of jump when compiling an alternative. */
+ dummy_failure_jump,
+
+ /* Push a dummy failure point and continue. Used at the end of
+ alternatives. */
+ push_dummy_failure,
+
+ /* Followed by two-byte relative address and two-byte number n.
+ After matching N times, jump to the address upon failure. */
+ succeed_n,
+
+ /* Followed by two-byte relative address, and two-byte number n.
+ Jump to the address N times, then fail. */
+ jump_n,
+
+ /* Set the following two-byte relative address to the
+ subsequent two-byte number. The address *includes* the two
+ bytes of number. */
+ set_number_at,
+
+ wordchar, /* Matches any word-constituent character. */
+ notwordchar, /* Matches any char that is not a word-constituent. */
+
+ wordbeg, /* Succeeds if at word beginning. */
+ wordend, /* Succeeds if at word end. */
+
+ wordbound, /* Succeeds if at a word boundary. */
+ notwordbound /* Succeeds if not at a word boundary. */
+
+#ifdef emacs
+ ,before_dot, /* Succeeds if before point. */
+ at_dot, /* Succeeds if at point. */
+ after_dot, /* Succeeds if after point. */
+
+ /* Matches any character whose syntax is specified. Followed by
+ a byte which contains a syntax code, e.g., Sword. */
+ syntaxspec,
+
+ /* Matches any character whose syntax is not that specified. */
+ notsyntaxspec
+#endif /* emacs */
+} re_opcode_t;
+
+/* Common operations on the compiled pattern. */
+
+/* Store NUMBER in two contiguous bytes starting at DESTINATION. */
+
+#define STORE_NUMBER(destination, number) \
+ do { \
+ (destination)[0] = (number) & 0377; \
+ (destination)[1] = (number) >> 8; \
+ } while (0)
+
+/* Same as STORE_NUMBER, except increment DESTINATION to
+ the byte after where the number is stored. Therefore, DESTINATION
+ must be an lvalue. */
+
+#define STORE_NUMBER_AND_INCR(destination, number) \
+ do { \
+ STORE_NUMBER (destination, number); \
+ (destination) += 2; \
+ } while (0)
+
+/* Put into DESTINATION a number stored in two contiguous bytes starting
+ at SOURCE. */
+
+#define EXTRACT_NUMBER(destination, source) \
+ do { \
+ (destination) = *(source) & 0377; \
+ (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8; \
+ } while (0)
+
+#ifdef DEBUG
+static void extract_number _RE_ARGS ((int *dest, unsigned char *source));
+static void
+extract_number (dest, source)
+ int *dest;
+ unsigned char *source;
+{
+ int temp = SIGN_EXTEND_CHAR (*(source + 1));
+ *dest = *source & 0377;
+ *dest += temp << 8;
+}
+
+# ifndef EXTRACT_MACROS /* To debug the macros. */
+# undef EXTRACT_NUMBER
+# define EXTRACT_NUMBER(dest, src) extract_number (&dest, src)
+# endif /* not EXTRACT_MACROS */
+
+#endif /* DEBUG */
+
+/* Same as EXTRACT_NUMBER, except increment SOURCE to after the number.
+ SOURCE must be an lvalue. */
+
+#define EXTRACT_NUMBER_AND_INCR(destination, source) \
+ do { \
+ EXTRACT_NUMBER (destination, source); \
+ (source) += 2; \
+ } while (0)
+
+#ifdef DEBUG
+static void extract_number_and_incr _RE_ARGS ((int *destination,
+ unsigned char **source));
+static void
+extract_number_and_incr (destination, source)
+ int *destination;
+ unsigned char **source;
+{
+ extract_number (destination, *source);
+ *source += 2;
+}
+
+# ifndef EXTRACT_MACROS
+# undef EXTRACT_NUMBER_AND_INCR
+# define EXTRACT_NUMBER_AND_INCR(dest, src) \
+ extract_number_and_incr (&dest, &src)
+# endif /* not EXTRACT_MACROS */
+
+#endif /* DEBUG */
+
+/* If DEBUG is defined, Regex prints many voluminous messages about what
+ it is doing (if the variable `debug' is nonzero). If linked with the
+ main program in `iregex.c', you can enter patterns and strings
+ interactively. And if linked with the main program in `main.c' and
+ the other test files, you can run the already-written tests. */
+
+#ifdef DEBUG
+
+/* We use standard I/O for debugging. */
+# include <stdio.h>
+
+/* It is useful to test things that ``must'' be true when debugging. */
+# include <assert.h>
+
+static int debug = 0;
+
+# define DEBUG_STATEMENT(e) e
+# define DEBUG_PRINT1(x) if (debug) printf (x)
+# define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2)
+# define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3)
+# define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4)
+# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \
+ if (debug) print_partial_compiled_pattern (s, e)
+# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \
+ if (debug) print_double_string (w, s1, sz1, s2, sz2)
+
+
+/* Print the fastmap in human-readable form. */
+
+void
+print_fastmap (fastmap)
+ char *fastmap;
+{
+ unsigned was_a_range = 0;
+ unsigned i = 0;
+
+ while (i < (1 << BYTEWIDTH))
+ {
+ if (fastmap[i++])
+ {
+ was_a_range = 0;
+ putchar (i - 1);
+ while (i < (1 << BYTEWIDTH) && fastmap[i])
+ {
+ was_a_range = 1;
+ i++;
+ }
+ if (was_a_range)
+ {
+ printf ("-");
+ putchar (i - 1);
+ }
+ }
+ }
+ putchar ('\n');
+}
+
+
+/* Print a compiled pattern string in human-readable form, starting at
+ the START pointer into it and ending just before the pointer END. */
+
+void
+print_partial_compiled_pattern (start, end)
+ unsigned char *start;
+ unsigned char *end;
+{
+ int mcnt, mcnt2;
+ unsigned char *p1;
+ unsigned char *p = start;
+ unsigned char *pend = end;
+
+ if (start == NULL)
+ {
+ printf ("(null)\n");
+ return;
+ }
+
+ /* Loop over pattern commands. */
+ while (p < pend)
+ {
+ printf ("%d:\t", p - start);
+
+ switch ((re_opcode_t) *p++)
+ {
+ case no_op:
+ printf ("/no_op");
+ break;
+
+ case exactn:
+ mcnt = *p++;
+ printf ("/exactn/%d", mcnt);
+ do
+ {
+ putchar ('/');
+ putchar (*p++);
+ }
+ while (--mcnt);
+ break;
+
+ case start_memory:
+ mcnt = *p++;
+ printf ("/start_memory/%d/%d", mcnt, *p++);
+ break;
+
+ case stop_memory:
+ mcnt = *p++;
+ printf ("/stop_memory/%d/%d", mcnt, *p++);
+ break;
+
+ case duplicate:
+ printf ("/duplicate/%d", *p++);
+ break;
+
+ case anychar:
+ printf ("/anychar");
+ break;
+
+ case charset:
+ case charset_not:
+ {
+ register int c, last = -100;
+ register int in_range = 0;
+
+ printf ("/charset [%s",
+ (re_opcode_t) *(p - 1) == charset_not ? "^" : "");
+
+ assert (p + *p < pend);
+
+ for (c = 0; c < 256; c++)
+ if (c / 8 < *p
+ && (p[1 + (c/8)] & (1 << (c % 8))))
+ {
+ /* Are we starting a range? */
+ if (last + 1 == c && ! in_range)
+ {
+ putchar ('-');
+ in_range = 1;
+ }
+ /* Have we broken a range? */
+ else if (last + 1 != c && in_range)
+ {
+ putchar (last);
+ in_range = 0;
+ }
+
+ if (! in_range)
+ putchar (c);
+
+ last = c;
+ }
+
+ if (in_range)
+ putchar (last);
+
+ putchar (']');
+
+ p += 1 + *p;
+ }
+ break;
+
+ case begline:
+ printf ("/begline");
+ break;
+
+ case endline:
+ printf ("/endline");
+ break;
+
+ case on_failure_jump:
+ extract_number_and_incr (&mcnt, &p);
+ printf ("/on_failure_jump to %d", p + mcnt - start);
+ break;
+
+ case on_failure_keep_string_jump:
+ extract_number_and_incr (&mcnt, &p);
+ printf ("/on_failure_keep_string_jump to %d", p + mcnt - start);
+ break;
+
+ case dummy_failure_jump:
+ extract_number_and_incr (&mcnt, &p);
+ printf ("/dummy_failure_jump to %d", p + mcnt - start);
+ break;
+
+ case push_dummy_failure:
+ printf ("/push_dummy_failure");
+ break;
+
+ case maybe_pop_jump:
+ extract_number_and_incr (&mcnt, &p);
+ printf ("/maybe_pop_jump to %d", p + mcnt - start);
+ break;
+
+ case pop_failure_jump:
+ extract_number_and_incr (&mcnt, &p);
+ printf ("/pop_failure_jump to %d", p + mcnt - start);
+ break;
+
+ case jump_past_alt:
+ extract_number_and_incr (&mcnt, &p);
+ printf ("/jump_past_alt to %d", p + mcnt - start);
+ break;
+
+ case jump:
+ extract_number_and_incr (&mcnt, &p);
+ printf ("/jump to %d", p + mcnt - start);
+ break;
+
+ case succeed_n:
+ extract_number_and_incr (&mcnt, &p);
+ p1 = p + mcnt;
+ extract_number_and_incr (&mcnt2, &p);
+ printf ("/succeed_n to %d, %d times", p1 - start, mcnt2);
+ break;
+
+ case jump_n:
+ extract_number_and_incr (&mcnt, &p);
+ p1 = p + mcnt;
+ extract_number_and_incr (&mcnt2, &p);
+ printf ("/jump_n to %d, %d times", p1 - start, mcnt2);
+ break;
+
+ case set_number_at:
+ extract_number_and_incr (&mcnt, &p);
+ p1 = p + mcnt;
+ extract_number_and_incr (&mcnt2, &p);
+ printf ("/set_number_at location %d to %d", p1 - start, mcnt2);
+ break;
+
+ case wordbound:
+ printf ("/wordbound");
+ break;
+
+ case notwordbound:
+ printf ("/notwordbound");
+ break;
+
+ case wordbeg:
+ printf ("/wordbeg");
+ break;
+
+ case wordend:
+ printf ("/wordend");
+
+# ifdef emacs
+ case before_dot:
+ printf ("/before_dot");
+ break;
+
+ case at_dot:
+ printf ("/at_dot");
+ break;
+
+ case after_dot:
+ printf ("/after_dot");
+ break;
+
+ case syntaxspec:
+ printf ("/syntaxspec");
+ mcnt = *p++;
+ printf ("/%d", mcnt);
+ break;
+
+ case notsyntaxspec:
+ printf ("/notsyntaxspec");
+ mcnt = *p++;
+ printf ("/%d", mcnt);
+ break;
+# endif /* emacs */
+
+ case wordchar:
+ printf ("/wordchar");
+ break;
+
+ case notwordchar:
+ printf ("/notwordchar");
+ break;
+
+ case begbuf:
+ printf ("/begbuf");
+ break;
+
+ case endbuf:
+ printf ("/endbuf");
+ break;
+
+ default:
+ printf ("?%d", *(p-1));
+ }
+
+ putchar ('\n');
+ }
+
+ printf ("%d:\tend of pattern.\n", p - start);
+}
+
+
+void
+print_compiled_pattern (bufp)
+ struct re_pattern_buffer *bufp;
+{
+ unsigned char *buffer = bufp->buffer;
+
+ print_partial_compiled_pattern (buffer, buffer + bufp->used);
+ printf ("%ld bytes used/%ld bytes allocated.\n",
+ bufp->used, bufp->allocated);
+
+ if (bufp->fastmap_accurate && bufp->fastmap)
+ {
+ printf ("fastmap: ");
+ print_fastmap (bufp->fastmap);
+ }
+
+ printf ("re_nsub: %d\t", bufp->re_nsub);
+ printf ("regs_alloc: %d\t", bufp->regs_allocated);
+ printf ("can_be_null: %d\t", bufp->can_be_null);
+ printf ("newline_anchor: %d\n", bufp->newline_anchor);
+ printf ("no_sub: %d\t", bufp->no_sub);
+ printf ("not_bol: %d\t", bufp->not_bol);
+ printf ("not_eol: %d\t", bufp->not_eol);
+ printf ("syntax: %lx\n", bufp->syntax);
+ /* Perhaps we should print the translate table? */
+}
+
+
+void
+print_double_string (where, string1, size1, string2, size2)
+ const char *where;
+ const char *string1;
+ const char *string2;
+ int size1;
+ int size2;
+{
+ int this_char;
+
+ if (where == NULL)
+ printf ("(null)");
+ else
+ {
+ if (FIRST_STRING_P (where))
+ {
+ for (this_char = where - string1; this_char < size1; this_char++)
+ putchar (string1[this_char]);
+
+ where = string2;
+ }
+
+ for (this_char = where - string2; this_char < size2; this_char++)
+ putchar (string2[this_char]);
+ }
+}
+
+void
+printchar (c)
+ int c;
+{
+ putc (c, stderr);
+}
+
+#else /* not DEBUG */
+
+# undef assert
+# define assert(e)
+
+# define DEBUG_STATEMENT(e)
+# define DEBUG_PRINT1(x)
+# define DEBUG_PRINT2(x1, x2)
+# define DEBUG_PRINT3(x1, x2, x3)
+# define DEBUG_PRINT4(x1, x2, x3, x4)
+# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e)
+# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)
+
+#endif /* not DEBUG */
+
+/* Set by `re_set_syntax' to the current regexp syntax to recognize. Can
+ also be assigned to arbitrarily: each pattern buffer stores its own
+ syntax, so it can be changed between regex compilations. */
+/* This has no initializer because initialized variables in Emacs
+ become read-only after dumping. */
+reg_syntax_t re_syntax_options;
+
+
+/* Specify the precise syntax of regexps for compilation. This provides
+ for compatibility for various utilities which historically have
+ different, incompatible syntaxes.
+
+ The argument SYNTAX is a bit mask comprised of the various bits
+ defined in regex.h. We return the old syntax. */
+
+reg_syntax_t
+re_set_syntax (syntax)
+ reg_syntax_t syntax;
+{
+ reg_syntax_t ret = re_syntax_options;
+
+ re_syntax_options = syntax;
+#ifdef DEBUG
+ if (syntax & RE_DEBUG)
+ debug = 1;
+ else if (debug) /* was on but now is not */
+ debug = 0;
+#endif /* DEBUG */
+ return ret;
+}
+#ifdef _LIBC
+weak_alias (__re_set_syntax, re_set_syntax)
+#endif
+
+/* This table gives an error message for each of the error codes listed
+ in regex.h. Obviously the order here has to be same as there.
+ POSIX doesn't require that we do anything for REG_NOERROR,
+ but why not be nice? */
+
+static const char *re_error_msgid[] =
+ {
+ gettext_noop ("Success"), /* REG_NOERROR */
+ gettext_noop ("No match"), /* REG_NOMATCH */
+ gettext_noop ("Invalid regular expression"), /* REG_BADPAT */
+ gettext_noop ("Invalid collation character"), /* REG_ECOLLATE */
+ gettext_noop ("Invalid character class name"), /* REG_ECTYPE */
+ gettext_noop ("Trailing backslash"), /* REG_EESCAPE */
+ gettext_noop ("Invalid back reference"), /* REG_ESUBREG */
+ gettext_noop ("Unmatched [ or [^"), /* REG_EBRACK */
+ gettext_noop ("Unmatched ( or \\("), /* REG_EPAREN */
+ gettext_noop ("Unmatched \\{"), /* REG_EBRACE */
+ gettext_noop ("Invalid content of \\{\\}"), /* REG_BADBR */
+ gettext_noop ("Invalid range end"), /* REG_ERANGE */
+ gettext_noop ("Memory exhausted"), /* REG_ESPACE */
+ gettext_noop ("Invalid preceding regular expression"), /* REG_BADRPT */
+ gettext_noop ("Premature end of regular expression"), /* REG_EEND */
+ gettext_noop ("Regular expression too big"), /* REG_ESIZE */
+ gettext_noop ("Unmatched ) or \\)"), /* REG_ERPAREN */
+ };
+
+/* Avoiding alloca during matching, to placate r_alloc. */
+
+/* Define MATCH_MAY_ALLOCATE unless we need to make sure that the
+ searching and matching functions should not call alloca. On some
+ systems, alloca is implemented in terms of malloc, and if we're
+ using the relocating allocator routines, then malloc could cause a
+ relocation, which might (if the strings being searched are in the
+ ralloc heap) shift the data out from underneath the regexp
+ routines.
+
+ Here's another reason to avoid allocation: Emacs
+ processes input from X in a signal handler; processing X input may
+ call malloc; if input arrives while a matching routine is calling
+ malloc, then we're scrod. But Emacs can't just block input while
+ calling matching routines; then we don't notice interrupts when
+ they come in. So, Emacs blocks input around all regexp calls
+ except the matching calls, which it leaves unprotected, in the
+ faith that they will not malloc. */
+
+/* Normally, this is fine. */
+#define MATCH_MAY_ALLOCATE
+
+/* When using GNU C, we are not REALLY using the C alloca, no matter
+ what config.h may say. So don't take precautions for it. */
+#ifdef __GNUC__
+# undef C_ALLOCA
+#endif
+
+/* The match routines may not allocate if (1) they would do it with malloc
+ and (2) it's not safe for them to use malloc.
+ Note that if REL_ALLOC is defined, matching would not use malloc for the
+ failure stack, but we would still use it for the register vectors;
+ so REL_ALLOC should not affect this. */
+#if (defined C_ALLOCA || defined REGEX_MALLOC) && defined emacs
+# undef MATCH_MAY_ALLOCATE
+#endif
+
+
+/* Failure stack declarations and macros; both re_compile_fastmap and
+ re_match_2 use a failure stack. These have to be macros because of
+ REGEX_ALLOCATE_STACK. */
+
+
+/* Number of failure points for which to initially allocate space
+ when matching. If this number is exceeded, we allocate more
+ space, so it is not a hard limit. */
+#ifndef INIT_FAILURE_ALLOC
+# define INIT_FAILURE_ALLOC 5
+#endif
+
+/* Roughly the maximum number of failure points on the stack. Would be
+ exactly that if always used MAX_FAILURE_ITEMS items each time we failed.
+ This is a variable only so users of regex can assign to it; we never
+ change it ourselves. */
+
+#ifdef INT_IS_16BIT
+
+# if defined MATCH_MAY_ALLOCATE
+/* 4400 was enough to cause a crash on Alpha OSF/1,
+ whose default stack limit is 2mb. */
+long int re_max_failures = 4000;
+# else
+long int re_max_failures = 2000;
+# endif
+
+union fail_stack_elt
+{
+ unsigned char *pointer;
+ long int integer;
+};
+
+typedef union fail_stack_elt fail_stack_elt_t;
+
+typedef struct
+{
+ fail_stack_elt_t *stack;
+ unsigned long int size;
+ unsigned long int avail; /* Offset of next open position. */
+} fail_stack_type;
+
+#else /* not INT_IS_16BIT */
+
+# if defined MATCH_MAY_ALLOCATE
+/* 4400 was enough to cause a crash on Alpha OSF/1,
+ whose default stack limit is 2mb. */
+int re_max_failures = 20000;
+# else
+int re_max_failures = 2000;
+# endif
+
+union fail_stack_elt
+{
+ unsigned char *pointer;
+ int integer;
+};
+
+typedef union fail_stack_elt fail_stack_elt_t;
+
+typedef struct
+{
+ fail_stack_elt_t *stack;
+ unsigned size;
+ unsigned avail; /* Offset of next open position. */
+} fail_stack_type;
+
+#endif /* INT_IS_16BIT */
+
+#define FAIL_STACK_EMPTY() (fail_stack.avail == 0)
+#define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0)
+#define FAIL_STACK_FULL() (fail_stack.avail == fail_stack.size)
+
+
+/* Define macros to initialize and free the failure stack.
+ Do `return -2' if the alloc fails. */
+
+#ifdef MATCH_MAY_ALLOCATE
+# define INIT_FAIL_STACK() \
+ do { \
+ fail_stack.stack = (fail_stack_elt_t *) \
+ REGEX_ALLOCATE_STACK (INIT_FAILURE_ALLOC * sizeof (fail_stack_elt_t)); \
+ \
+ if (fail_stack.stack == NULL) \
+ return -2; \
+ \
+ fail_stack.size = INIT_FAILURE_ALLOC; \
+ fail_stack.avail = 0; \
+ } while (0)
+
+# define RESET_FAIL_STACK() REGEX_FREE_STACK (fail_stack.stack)
+#else
+# define INIT_FAIL_STACK() \
+ do { \
+ fail_stack.avail = 0; \
+ } while (0)
+
+# define RESET_FAIL_STACK()
+#endif
+
+
+/* Double the size of FAIL_STACK, up to approximately `re_max_failures' items.
+
+ Return 1 if succeeds, and 0 if either ran out of memory
+ allocating space for it or it was already too large.
+
+ REGEX_REALLOCATE_STACK requires `destination' be declared. */
+
+#define DOUBLE_FAIL_STACK(fail_stack) \
+ ((fail_stack).size > (unsigned) (re_max_failures * MAX_FAILURE_ITEMS) \
+ ? 0 \
+ : ((fail_stack).stack = (fail_stack_elt_t *) \
+ REGEX_REALLOCATE_STACK ((fail_stack).stack, \
+ (fail_stack).size * sizeof (fail_stack_elt_t), \
+ ((fail_stack).size << 1) * sizeof (fail_stack_elt_t)), \
+ \
+ (fail_stack).stack == NULL \
+ ? 0 \
+ : ((fail_stack).size <<= 1, \
+ 1)))
+
+
+/* Push pointer POINTER on FAIL_STACK.
+ Return 1 if was able to do so and 0 if ran out of memory allocating
+ space to do so. */
+#define PUSH_PATTERN_OP(POINTER, FAIL_STACK) \
+ ((FAIL_STACK_FULL () \
+ && !DOUBLE_FAIL_STACK (FAIL_STACK)) \
+ ? 0 \
+ : ((FAIL_STACK).stack[(FAIL_STACK).avail++].pointer = POINTER, \
+ 1))
+
+/* Push a pointer value onto the failure stack.
+ Assumes the variable `fail_stack'. Probably should only
+ be called from within `PUSH_FAILURE_POINT'. */
+#define PUSH_FAILURE_POINTER(item) \
+ fail_stack.stack[fail_stack.avail++].pointer = (unsigned char *) (item)
+
+/* This pushes an integer-valued item onto the failure stack.
+ Assumes the variable `fail_stack'. Probably should only
+ be called from within `PUSH_FAILURE_POINT'. */
+#define PUSH_FAILURE_INT(item) \
+ fail_stack.stack[fail_stack.avail++].integer = (item)
+
+/* Push a fail_stack_elt_t value onto the failure stack.
+ Assumes the variable `fail_stack'. Probably should only
+ be called from within `PUSH_FAILURE_POINT'. */
+#define PUSH_FAILURE_ELT(item) \
+ fail_stack.stack[fail_stack.avail++] = (item)
+
+/* These three POP... operations complement the three PUSH... operations.
+ All assume that `fail_stack' is nonempty. */
+#define POP_FAILURE_POINTER() fail_stack.stack[--fail_stack.avail].pointer
+#define POP_FAILURE_INT() fail_stack.stack[--fail_stack.avail].integer
+#define POP_FAILURE_ELT() fail_stack.stack[--fail_stack.avail]
+
+/* Used to omit pushing failure point id's when we're not debugging. */
+#ifdef DEBUG
+# define DEBUG_PUSH PUSH_FAILURE_INT
+# define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_INT ()
+#else
+# define DEBUG_PUSH(item)
+# define DEBUG_POP(item_addr)
+#endif
+
+
+/* Push the information about the state we will need
+ if we ever fail back to it.
+
+ Requires variables fail_stack, regstart, regend, reg_info, and
+ num_regs_pushed be declared. DOUBLE_FAIL_STACK requires `destination'
+ be declared.
+
+ Does `return FAILURE_CODE' if runs out of memory. */
+
+#define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code) \
+ do { \
+ char *destination; \
+ /* Must be int, so when we don't save any registers, the arithmetic \
+ of 0 + -1 isn't done as unsigned. */ \
+ /* Can't be int, since there is not a shred of a guarantee that int \
+ is wide enough to hold a value of something to which pointer can \
+ be assigned */ \
+ active_reg_t this_reg; \
+ \
+ DEBUG_STATEMENT (failure_id++); \
+ DEBUG_STATEMENT (nfailure_points_pushed++); \
+ DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id); \
+ DEBUG_PRINT2 (" Before push, next avail: %d\n", (fail_stack).avail);\
+ DEBUG_PRINT2 (" size: %d\n", (fail_stack).size);\
+ \
+ DEBUG_PRINT2 (" slots needed: %ld\n", NUM_FAILURE_ITEMS); \
+ DEBUG_PRINT2 (" available: %d\n", REMAINING_AVAIL_SLOTS); \
+ \
+ /* Ensure we have enough space allocated for what we will push. */ \
+ while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS) \
+ { \
+ if (!DOUBLE_FAIL_STACK (fail_stack)) \
+ return failure_code; \
+ \
+ DEBUG_PRINT2 ("\n Doubled stack; size now: %d\n", \
+ (fail_stack).size); \
+ DEBUG_PRINT2 (" slots available: %d\n", REMAINING_AVAIL_SLOTS);\
+ } \
+ \
+ /* Push the info, starting with the registers. */ \
+ DEBUG_PRINT1 ("\n"); \
+ \
+ if (1) \
+ for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \
+ this_reg++) \
+ { \
+ DEBUG_PRINT2 (" Pushing reg: %lu\n", this_reg); \
+ DEBUG_STATEMENT (num_regs_pushed++); \
+ \
+ DEBUG_PRINT2 (" start: %p\n", regstart[this_reg]); \
+ PUSH_FAILURE_POINTER (regstart[this_reg]); \
+ \
+ DEBUG_PRINT2 (" end: %p\n", regend[this_reg]); \
+ PUSH_FAILURE_POINTER (regend[this_reg]); \
+ \
+ DEBUG_PRINT2 (" info: %p\n ", \
+ reg_info[this_reg].word.pointer); \
+ DEBUG_PRINT2 (" match_null=%d", \
+ REG_MATCH_NULL_STRING_P (reg_info[this_reg])); \
+ DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg])); \
+ DEBUG_PRINT2 (" matched_something=%d", \
+ MATCHED_SOMETHING (reg_info[this_reg])); \
+ DEBUG_PRINT2 (" ever_matched=%d", \
+ EVER_MATCHED_SOMETHING (reg_info[this_reg])); \
+ DEBUG_PRINT1 ("\n"); \
+ PUSH_FAILURE_ELT (reg_info[this_reg].word); \
+ } \
+ \
+ DEBUG_PRINT2 (" Pushing low active reg: %ld\n", lowest_active_reg);\
+ PUSH_FAILURE_INT (lowest_active_reg); \
+ \
+ DEBUG_PRINT2 (" Pushing high active reg: %ld\n", highest_active_reg);\
+ PUSH_FAILURE_INT (highest_active_reg); \
+ \
+ DEBUG_PRINT2 (" Pushing pattern %p:\n", pattern_place); \
+ DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend); \
+ PUSH_FAILURE_POINTER (pattern_place); \
+ \
+ DEBUG_PRINT2 (" Pushing string %p: `", string_place); \
+ DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, \
+ size2); \
+ DEBUG_PRINT1 ("'\n"); \
+ PUSH_FAILURE_POINTER (string_place); \
+ \
+ DEBUG_PRINT2 (" Pushing failure id: %u\n", failure_id); \
+ DEBUG_PUSH (failure_id); \
+ } while (0)
+
+/* This is the number of items that are pushed and popped on the stack
+ for each register. */
+#define NUM_REG_ITEMS 3
+
+/* Individual items aside from the registers. */
+#ifdef DEBUG
+# define NUM_NONREG_ITEMS 5 /* Includes failure point id. */
+#else
+# define NUM_NONREG_ITEMS 4
+#endif
+
+/* We push at most this many items on the stack. */
+/* We used to use (num_regs - 1), which is the number of registers
+ this regexp will save; but that was changed to 5
+ to avoid stack overflow for a regexp with lots of parens. */
+#define MAX_FAILURE_ITEMS (5 * NUM_REG_ITEMS + NUM_NONREG_ITEMS)
+
+/* We actually push this many items. */
+#define NUM_FAILURE_ITEMS \
+ (((0 \
+ ? 0 : highest_active_reg - lowest_active_reg + 1) \
+ * NUM_REG_ITEMS) \
+ + NUM_NONREG_ITEMS)
+
+/* How many items can still be added to the stack without overflowing it. */
+#define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail)
+
+
+/* Pops what PUSH_FAIL_STACK pushes.
+
+ We restore into the parameters, all of which should be lvalues:
+ STR -- the saved data position.
+ PAT -- the saved pattern position.
+ LOW_REG, HIGH_REG -- the highest and lowest active registers.
+ REGSTART, REGEND -- arrays of string positions.
+ REG_INFO -- array of information about each subexpression.
+
+ Also assumes the variables `fail_stack' and (if debugging), `bufp',
+ `pend', `string1', `size1', `string2', and `size2'. */
+
+#define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\
+{ \
+ DEBUG_STATEMENT (unsigned failure_id;) \
+ active_reg_t this_reg; \
+ const unsigned char *string_temp; \
+ \
+ assert (!FAIL_STACK_EMPTY ()); \
+ \
+ /* Remove failure points and point to how many regs pushed. */ \
+ DEBUG_PRINT1 ("POP_FAILURE_POINT:\n"); \
+ DEBUG_PRINT2 (" Before pop, next avail: %d\n", fail_stack.avail); \
+ DEBUG_PRINT2 (" size: %d\n", fail_stack.size); \
+ \
+ assert (fail_stack.avail >= NUM_NONREG_ITEMS); \
+ \
+ DEBUG_POP (&failure_id); \
+ DEBUG_PRINT2 (" Popping failure id: %u\n", failure_id); \
+ \
+ /* If the saved string location is NULL, it came from an \
+ on_failure_keep_string_jump opcode, and we want to throw away the \
+ saved NULL, thus retaining our current position in the string. */ \
+ string_temp = POP_FAILURE_POINTER (); \
+ if (string_temp != NULL) \
+ str = (const char *) string_temp; \
+ \
+ DEBUG_PRINT2 (" Popping string %p: `", str); \
+ DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \
+ DEBUG_PRINT1 ("'\n"); \
+ \
+ pat = (unsigned char *) POP_FAILURE_POINTER (); \
+ DEBUG_PRINT2 (" Popping pattern %p:\n", pat); \
+ DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \
+ \
+ /* Restore register info. */ \
+ high_reg = (active_reg_t) POP_FAILURE_INT (); \
+ DEBUG_PRINT2 (" Popping high active reg: %ld\n", high_reg); \
+ \
+ low_reg = (active_reg_t) POP_FAILURE_INT (); \
+ DEBUG_PRINT2 (" Popping low active reg: %ld\n", low_reg); \
+ \
+ if (1) \
+ for (this_reg = high_reg; this_reg >= low_reg; this_reg--) \
+ { \
+ DEBUG_PRINT2 (" Popping reg: %ld\n", this_reg); \
+ \
+ reg_info[this_reg].word = POP_FAILURE_ELT (); \
+ DEBUG_PRINT2 (" info: %p\n", \
+ reg_info[this_reg].word.pointer); \
+ \
+ regend[this_reg] = (const char *) POP_FAILURE_POINTER (); \
+ DEBUG_PRINT2 (" end: %p\n", regend[this_reg]); \
+ \
+ regstart[this_reg] = (const char *) POP_FAILURE_POINTER (); \
+ DEBUG_PRINT2 (" start: %p\n", regstart[this_reg]); \
+ } \
+ else \
+ { \
+ for (this_reg = highest_active_reg; this_reg > high_reg; this_reg--) \
+ { \
+ reg_info[this_reg].word.integer = 0; \
+ regend[this_reg] = 0; \
+ regstart[this_reg] = 0; \
+ } \
+ highest_active_reg = high_reg; \
+ } \
+ \
+ set_regs_matched_done = 0; \
+ DEBUG_STATEMENT (nfailure_points_popped++); \
+} /* POP_FAILURE_POINT */
+
+
+
+/* Structure for per-register (a.k.a. per-group) information.
+ Other register information, such as the
+ starting and ending positions (which are addresses), and the list of
+ inner groups (which is a bits list) are maintained in separate
+ variables.
+
+ We are making a (strictly speaking) nonportable assumption here: that
+ the compiler will pack our bit fields into something that fits into
+ the type of `word', i.e., is something that fits into one item on the
+ failure stack. */
+
+
+/* Declarations and macros for re_match_2. */
+
+typedef union
+{
+ fail_stack_elt_t word;
+ struct
+ {
+ /* This field is one if this group can match the empty string,
+ zero if not. If not yet determined, `MATCH_NULL_UNSET_VALUE'. */
+#define MATCH_NULL_UNSET_VALUE 3
+ unsigned match_null_string_p : 2;
+ unsigned is_active : 1;
+ unsigned matched_something : 1;
+ unsigned ever_matched_something : 1;
+ } bits;
+} register_info_type;
+
+#define REG_MATCH_NULL_STRING_P(R) ((R).bits.match_null_string_p)
+#define IS_ACTIVE(R) ((R).bits.is_active)
+#define MATCHED_SOMETHING(R) ((R).bits.matched_something)
+#define EVER_MATCHED_SOMETHING(R) ((R).bits.ever_matched_something)
+
+
+/* Call this when have matched a real character; it sets `matched' flags
+ for the subexpressions which we are currently inside. Also records
+ that those subexprs have matched. */
+#define SET_REGS_MATCHED() \
+ do \
+ { \
+ if (!set_regs_matched_done) \
+ { \
+ active_reg_t r; \
+ set_regs_matched_done = 1; \
+ for (r = lowest_active_reg; r <= highest_active_reg; r++) \
+ { \
+ MATCHED_SOMETHING (reg_info[r]) \
+ = EVER_MATCHED_SOMETHING (reg_info[r]) \
+ = 1; \
+ } \
+ } \
+ } \
+ while (0)
+
+/* Registers are set to a sentinel when they haven't yet matched. */
+static char reg_unset_dummy;
+#define REG_UNSET_VALUE (&reg_unset_dummy)
+#define REG_UNSET(e) ((e) == REG_UNSET_VALUE)
+
+/* Subroutine declarations and macros for regex_compile. */
+
+static reg_errcode_t regex_compile _RE_ARGS ((const char *pattern, size_t size,
+ reg_syntax_t syntax,
+ struct re_pattern_buffer *bufp));
+static void store_op1 _RE_ARGS ((re_opcode_t op, unsigned char *loc, int arg));
+static void store_op2 _RE_ARGS ((re_opcode_t op, unsigned char *loc,
+ int arg1, int arg2));
+static void insert_op1 _RE_ARGS ((re_opcode_t op, unsigned char *loc,
+ int arg, unsigned char *end));
+static void insert_op2 _RE_ARGS ((re_opcode_t op, unsigned char *loc,
+ int arg1, int arg2, unsigned char *end));
+static boolean at_begline_loc_p _RE_ARGS ((const char *pattern, const char *p,
+ reg_syntax_t syntax));
+static boolean at_endline_loc_p _RE_ARGS ((const char *p, const char *pend,
+ reg_syntax_t syntax));
+static reg_errcode_t compile_range _RE_ARGS ((const char **p_ptr,
+ const char *pend,
+ char *translate,
+ reg_syntax_t syntax,
+ unsigned char *b));
+
+/* Fetch the next character in the uncompiled pattern---translating it
+ if necessary. Also cast from a signed character in the constant
+ string passed to us by the user to an unsigned char that we can use
+ as an array index (in, e.g., `translate'). */
+#ifndef PATFETCH
+# define PATFETCH(c) \
+ do {if (p == pend) return REG_EEND; \
+ c = (unsigned char) *p++; \
+ if (translate) c = (unsigned char) translate[c]; \
+ } while (0)
+#endif
+
+/* Fetch the next character in the uncompiled pattern, with no
+ translation. */
+#define PATFETCH_RAW(c) \
+ do {if (p == pend) return REG_EEND; \
+ c = (unsigned char) *p++; \
+ } while (0)
+
+/* Go backwards one character in the pattern. */
+#define PATUNFETCH p--
+
+
+/* If `translate' is non-null, return translate[D], else just D. We
+ cast the subscript to translate because some data is declared as
+ `char *', to avoid warnings when a string constant is passed. But
+ when we use a character as a subscript we must make it unsigned. */
+#ifndef TRANSLATE
+# define TRANSLATE(d) \
+ (translate ? (char) translate[(unsigned char) (d)] : (d))
+#endif
+
+
+/* Macros for outputting the compiled pattern into `buffer'. */
+
+/* If the buffer isn't allocated when it comes in, use this. */
+#define INIT_BUF_SIZE 32
+
+/* Make sure we have at least N more bytes of space in buffer. */
+#define GET_BUFFER_SPACE(n) \
+ while ((unsigned long) (b - bufp->buffer + (n)) > bufp->allocated) \
+ EXTEND_BUFFER ()
+
+/* Make sure we have one more byte of buffer space and then add C to it. */
+#define BUF_PUSH(c) \
+ do { \
+ GET_BUFFER_SPACE (1); \
+ *b++ = (unsigned char) (c); \
+ } while (0)
+
+
+/* Ensure we have two more bytes of buffer space and then append C1 and C2. */
+#define BUF_PUSH_2(c1, c2) \
+ do { \
+ GET_BUFFER_SPACE (2); \
+ *b++ = (unsigned char) (c1); \
+ *b++ = (unsigned char) (c2); \
+ } while (0)
+
+
+/* As with BUF_PUSH_2, except for three bytes. */
+#define BUF_PUSH_3(c1, c2, c3) \
+ do { \
+ GET_BUFFER_SPACE (3); \
+ *b++ = (unsigned char) (c1); \
+ *b++ = (unsigned char) (c2); \
+ *b++ = (unsigned char) (c3); \
+ } while (0)
+
+
+/* Store a jump with opcode OP at LOC to location TO. We store a
+ relative address offset by the three bytes the jump itself occupies. */
+#define STORE_JUMP(op, loc, to) \
+ store_op1 (op, loc, (int) ((to) - (loc) - 3))
+
+/* Likewise, for a two-argument jump. */
+#define STORE_JUMP2(op, loc, to, arg) \
+ store_op2 (op, loc, (int) ((to) - (loc) - 3), arg)
+
+/* Like `STORE_JUMP', but for inserting. Assume `b' is the buffer end. */
+#define INSERT_JUMP(op, loc, to) \
+ insert_op1 (op, loc, (int) ((to) - (loc) - 3), b)
+
+/* Like `STORE_JUMP2', but for inserting. Assume `b' is the buffer end. */
+#define INSERT_JUMP2(op, loc, to, arg) \
+ insert_op2 (op, loc, (int) ((to) - (loc) - 3), arg, b)
+
+
+/* This is not an arbitrary limit: the arguments which represent offsets
+ into the pattern are two bytes long. So if 2^16 bytes turns out to
+ be too small, many things would have to change. */
+/* Any other compiler which, like MSC, has allocation limit below 2^16
+ bytes will have to use approach similar to what was done below for
+ MSC and drop MAX_BUF_SIZE a bit. Otherwise you may end up
+ reallocating to 0 bytes. Such thing is not going to work too well.
+ You have been warned!! */
+#if defined _MSC_VER && !defined WIN32
+/* Microsoft C 16-bit versions limit malloc to approx 65512 bytes.
+ The REALLOC define eliminates a flurry of conversion warnings,
+ but is not required. */
+# define MAX_BUF_SIZE 65500L
+# define REALLOC(p,s) realloc ((p), (size_t) (s))
+#else
+# define MAX_BUF_SIZE (1L << 16)
+# define REALLOC(p,s) realloc ((p), (s))
+#endif
+
+/* Extend the buffer by twice its current size via realloc and
+ reset the pointers that pointed into the old block to point to the
+ correct places in the new one. If extending the buffer results in it
+ being larger than MAX_BUF_SIZE, then flag memory exhausted. */
+#define EXTEND_BUFFER() \
+ do { \
+ unsigned char *old_buffer = bufp->buffer; \
+ if (bufp->allocated == MAX_BUF_SIZE) \
+ return REG_ESIZE; \
+ bufp->allocated <<= 1; \
+ if (bufp->allocated > MAX_BUF_SIZE) \
+ bufp->allocated = MAX_BUF_SIZE; \
+ bufp->buffer = (unsigned char *) REALLOC (bufp->buffer, bufp->allocated);\
+ if (bufp->buffer == NULL) \
+ return REG_ESPACE; \
+ /* If the buffer moved, move all the pointers into it. */ \
+ if (old_buffer != bufp->buffer) \
+ { \
+ b = (b - old_buffer) + bufp->buffer; \
+ begalt = (begalt - old_buffer) + bufp->buffer; \
+ if (fixup_alt_jump) \
+ fixup_alt_jump = (fixup_alt_jump - old_buffer) + bufp->buffer;\
+ if (laststart) \
+ laststart = (laststart - old_buffer) + bufp->buffer; \
+ if (pending_exact) \
+ pending_exact = (pending_exact - old_buffer) + bufp->buffer; \
+ } \
+ } while (0)
+
+
+/* Since we have one byte reserved for the register number argument to
+ {start,stop}_memory, the maximum number of groups we can report
+ things about is what fits in that byte. */
+#define MAX_REGNUM 255
+
+/* But patterns can have more than `MAX_REGNUM' registers. We just
+ ignore the excess. */
+typedef unsigned regnum_t;
+
+
+/* Macros for the compile stack. */
+
+/* Since offsets can go either forwards or backwards, this type needs to
+ be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1. */
+/* int may be not enough when sizeof(int) == 2. */
+typedef long pattern_offset_t;
+
+typedef struct
+{
+ pattern_offset_t begalt_offset;
+ pattern_offset_t fixup_alt_jump;
+ pattern_offset_t inner_group_offset;
+ pattern_offset_t laststart_offset;
+ regnum_t regnum;
+} compile_stack_elt_t;
+
+
+typedef struct
+{
+ compile_stack_elt_t *stack;
+ unsigned size;
+ unsigned avail; /* Offset of next open position. */
+} compile_stack_type;
+
+
+#define INIT_COMPILE_STACK_SIZE 32
+
+#define COMPILE_STACK_EMPTY (compile_stack.avail == 0)
+#define COMPILE_STACK_FULL (compile_stack.avail == compile_stack.size)
+
+/* The next available element. */
+#define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail])
+
+
+/* Set the bit for character C in a list. */
+#define SET_LIST_BIT(c) \
+ (b[((unsigned char) (c)) / BYTEWIDTH] \
+ |= 1 << (((unsigned char) c) % BYTEWIDTH))
+
+
+/* Get the next unsigned number in the uncompiled pattern. */
+#define GET_UNSIGNED_NUMBER(num) \
+ { if (p != pend) \
+ { \
+ PATFETCH (c); \
+ while (ISDIGIT (c)) \
+ { \
+ if (num < 0) \
+ num = 0; \
+ num = num * 10 + c - '0'; \
+ if (p == pend) \
+ break; \
+ PATFETCH (c); \
+ } \
+ } \
+ }
+
+#if defined _LIBC || WIDE_CHAR_SUPPORT
+/* The GNU C library provides support for user-defined character classes
+ and the functions from ISO C amendement 1. */
+# ifdef CHARCLASS_NAME_MAX
+# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
+# else
+/* This shouldn't happen but some implementation might still have this
+ problem. Use a reasonable default value. */
+# define CHAR_CLASS_MAX_LENGTH 256
+# endif
+
+# ifdef _LIBC
+# define IS_CHAR_CLASS(string) __wctype (string)
+# else
+# define IS_CHAR_CLASS(string) wctype (string)
+# endif
+#else
+# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */
+
+# define IS_CHAR_CLASS(string) \
+ (STREQ (string, "alpha") || STREQ (string, "upper") \
+ || STREQ (string, "lower") || STREQ (string, "digit") \
+ || STREQ (string, "alnum") || STREQ (string, "xdigit") \
+ || STREQ (string, "space") || STREQ (string, "print") \
+ || STREQ (string, "punct") || STREQ (string, "graph") \
+ || STREQ (string, "cntrl") || STREQ (string, "blank"))
+#endif
+
+#ifndef MATCH_MAY_ALLOCATE
+
+/* If we cannot allocate large objects within re_match_2_internal,
+ we make the fail stack and register vectors global.
+ The fail stack, we grow to the maximum size when a regexp
+ is compiled.
+ The register vectors, we adjust in size each time we
+ compile a regexp, according to the number of registers it needs. */
+
+static fail_stack_type fail_stack;
+
+/* Size with which the following vectors are currently allocated.
+ That is so we can make them bigger as needed,
+ but never make them smaller. */
+static int regs_allocated_size;
+
+static const char ** regstart, ** regend;
+static const char ** old_regstart, ** old_regend;
+static const char **best_regstart, **best_regend;
+static register_info_type *reg_info;
+static const char **reg_dummy;
+static register_info_type *reg_info_dummy;
+
+/* Make the register vectors big enough for NUM_REGS registers,
+ but don't make them smaller. */
+
+static
+regex_grow_registers (num_regs)
+ int num_regs;
+{
+ if (num_regs > regs_allocated_size)
+ {
+ RETALLOC_IF (regstart, num_regs, const char *);
+ RETALLOC_IF (regend, num_regs, const char *);
+ RETALLOC_IF (old_regstart, num_regs, const char *);
+ RETALLOC_IF (old_regend, num_regs, const char *);
+ RETALLOC_IF (best_regstart, num_regs, const char *);
+ RETALLOC_IF (best_regend, num_regs, const char *);
+ RETALLOC_IF (reg_info, num_regs, register_info_type);
+ RETALLOC_IF (reg_dummy, num_regs, const char *);
+ RETALLOC_IF (reg_info_dummy, num_regs, register_info_type);
+
+ regs_allocated_size = num_regs;
+ }
+}
+
+#endif /* not MATCH_MAY_ALLOCATE */
+
+static boolean group_in_compile_stack _RE_ARGS ((compile_stack_type
+ compile_stack,
+ regnum_t regnum));
+
+/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX.
+ Returns one of error codes defined in `regex.h', or zero for success.
+
+ Assumes the `allocated' (and perhaps `buffer') and `translate'
+ fields are set in BUFP on entry.
+
+ If it succeeds, results are put in BUFP (if it returns an error, the
+ contents of BUFP are undefined):
+ `buffer' is the compiled pattern;
+ `syntax' is set to SYNTAX;
+ `used' is set to the length of the compiled pattern;
+ `fastmap_accurate' is zero;
+ `re_nsub' is the number of subexpressions in PATTERN;
+ `not_bol' and `not_eol' are zero;
+
+ The `fastmap' and `newline_anchor' fields are neither
+ examined nor set. */
+
+/* Return, freeing storage we allocated. */
+#define FREE_STACK_RETURN(value) \
+ return (free (compile_stack.stack), value)
+
+static reg_errcode_t
+regex_compile (pattern, size, syntax, bufp)
+ const char *pattern;
+ size_t size;
+ reg_syntax_t syntax;
+ struct re_pattern_buffer *bufp;
+{
+ /* We fetch characters from PATTERN here. Even though PATTERN is
+ `char *' (i.e., signed), we declare these variables as unsigned, so
+ they can be reliably used as array indices. */
+ register unsigned char c, c1;
+
+ /* A random temporary spot in PATTERN. */
+ const char *p1;
+
+ /* Points to the end of the buffer, where we should append. */
+ register unsigned char *b;
+
+ /* Keeps track of unclosed groups. */
+ compile_stack_type compile_stack;
+
+ /* Points to the current (ending) position in the pattern. */
+ const char *p = pattern;
+ const char *pend = pattern + size;
+
+ /* How to translate the characters in the pattern. */
+ RE_TRANSLATE_TYPE translate = bufp->translate;
+
+ /* Address of the count-byte of the most recently inserted `exactn'
+ command. This makes it possible to tell if a new exact-match
+ character can be added to that command or if the character requires
+ a new `exactn' command. */
+ unsigned char *pending_exact = 0;
+
+ /* Address of start of the most recently finished expression.
+ This tells, e.g., postfix * where to find the start of its
+ operand. Reset at the beginning of groups and alternatives. */
+ unsigned char *laststart = 0;
+
+ /* Address of beginning of regexp, or inside of last group. */
+ unsigned char *begalt;
+
+ /* Place in the uncompiled pattern (i.e., the {) to
+ which to go back if the interval is invalid. */
+ const char *beg_interval;
+
+ /* Address of the place where a forward jump should go to the end of
+ the containing expression. Each alternative of an `or' -- except the
+ last -- ends with a forward jump of this sort. */
+ unsigned char *fixup_alt_jump = 0;
+
+ /* Counts open-groups as they are encountered. Remembered for the
+ matching close-group on the compile stack, so the same register
+ number is put in the stop_memory as the start_memory. */
+ regnum_t regnum = 0;
+
+#ifdef DEBUG
+ DEBUG_PRINT1 ("\nCompiling pattern: ");
+ if (debug)
+ {
+ unsigned debug_count;
+
+ for (debug_count = 0; debug_count < size; debug_count++)
+ putchar (pattern[debug_count]);
+ putchar ('\n');
+ }
+#endif /* DEBUG */
+
+ /* Initialize the compile stack. */
+ compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t);
+ if (compile_stack.stack == NULL)
+ return REG_ESPACE;
+
+ compile_stack.size = INIT_COMPILE_STACK_SIZE;
+ compile_stack.avail = 0;
+
+ /* Initialize the pattern buffer. */
+ bufp->syntax = syntax;
+ bufp->fastmap_accurate = 0;
+ bufp->not_bol = bufp->not_eol = 0;
+
+ /* Set `used' to zero, so that if we return an error, the pattern
+ printer (for debugging) will think there's no pattern. We reset it
+ at the end. */
+ bufp->used = 0;
+
+ /* Always count groups, whether or not bufp->no_sub is set. */
+ bufp->re_nsub = 0;
+
+#if !defined emacs && !defined SYNTAX_TABLE
+ /* Initialize the syntax table. */
+ init_syntax_once ();
+#endif
+
+ if (bufp->allocated == 0)
+ {
+ if (bufp->buffer)
+ { /* If zero allocated, but buffer is non-null, try to realloc
+ enough space. This loses if buffer's address is bogus, but
+ that is the user's responsibility. */
+ RETALLOC (bufp->buffer, INIT_BUF_SIZE, unsigned char);
+ }
+ else
+ { /* Caller did not allocate a buffer. Do it for them. */
+ bufp->buffer = TALLOC (INIT_BUF_SIZE, unsigned char);
+ }
+ if (!bufp->buffer) FREE_STACK_RETURN (REG_ESPACE);
+
+ bufp->allocated = INIT_BUF_SIZE;
+ }
+
+ begalt = b = bufp->buffer;
+
+ /* Loop through the uncompiled pattern until we're at the end. */
+ while (p != pend)
+ {
+ PATFETCH (c);
+
+ switch (c)
+ {
+ case '^':
+ {
+ if ( /* If at start of pattern, it's an operator. */
+ p == pattern + 1
+ /* If context independent, it's an operator. */
+ || syntax & RE_CONTEXT_INDEP_ANCHORS
+ /* Otherwise, depends on what's come before. */
+ || at_begline_loc_p (pattern, p, syntax))
+ BUF_PUSH (begline);
+ else
+ goto normal_char;
+ }
+ break;
+
+
+ case '$':
+ {
+ if ( /* If at end of pattern, it's an operator. */
+ p == pend
+ /* If context independent, it's an operator. */
+ || syntax & RE_CONTEXT_INDEP_ANCHORS
+ /* Otherwise, depends on what's next. */
+ || at_endline_loc_p (p, pend, syntax))
+ BUF_PUSH (endline);
+ else
+ goto normal_char;
+ }
+ break;
+
+
+ case '+':
+ case '?':
+ if ((syntax & RE_BK_PLUS_QM)
+ || (syntax & RE_LIMITED_OPS))
+ goto normal_char;
+ handle_plus:
+ case '*':
+ /* If there is no previous pattern... */
+ if (!laststart)
+ {
+ if (syntax & RE_CONTEXT_INVALID_OPS)
+ FREE_STACK_RETURN (REG_BADRPT);
+ else if (!(syntax & RE_CONTEXT_INDEP_OPS))
+ goto normal_char;
+ }
+
+ {
+ /* Are we optimizing this jump? */
+ boolean keep_string_p = false;
+
+ /* 1 means zero (many) matches is allowed. */
+ char zero_times_ok = 0, many_times_ok = 0;
+
+ /* If there is a sequence of repetition chars, collapse it
+ down to just one (the right one). We can't combine
+ interval operators with these because of, e.g., `a{2}*',
+ which should only match an even number of `a's. */
+
+ for (;;)
+ {
+ zero_times_ok |= c != '+';
+ many_times_ok |= c != '?';
+
+ if (p == pend)
+ break;
+
+ PATFETCH (c);
+
+ if (c == '*'
+ || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?')))
+ ;
+
+ else if (syntax & RE_BK_PLUS_QM && c == '\\')
+ {
+ if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
+
+ PATFETCH (c1);
+ if (!(c1 == '+' || c1 == '?'))
+ {
+ PATUNFETCH;
+ PATUNFETCH;
+ break;
+ }
+
+ c = c1;
+ }
+ else
+ {
+ PATUNFETCH;
+ break;
+ }
+
+ /* If we get here, we found another repeat character. */
+ }
+
+ /* Star, etc. applied to an empty pattern is equivalent
+ to an empty pattern. */
+ if (!laststart)
+ break;
+
+ /* Now we know whether or not zero matches is allowed
+ and also whether or not two or more matches is allowed. */
+ if (many_times_ok)
+ { /* More than one repetition is allowed, so put in at the
+ end a backward relative jump from `b' to before the next
+ jump we're going to put in below (which jumps from
+ laststart to after this jump).
+
+ But if we are at the `*' in the exact sequence `.*\n',
+ insert an unconditional jump backwards to the .,
+ instead of the beginning of the loop. This way we only
+ push a failure point once, instead of every time
+ through the loop. */
+ assert (p - 1 > pattern);
+
+ /* Allocate the space for the jump. */
+ GET_BUFFER_SPACE (3);
+
+ /* We know we are not at the first character of the pattern,
+ because laststart was nonzero. And we've already
+ incremented `p', by the way, to be the character after
+ the `*'. Do we have to do something analogous here
+ for null bytes, because of RE_DOT_NOT_NULL? */
+ if (TRANSLATE (*(p - 2)) == TRANSLATE ('.')
+ && zero_times_ok
+ && p < pend && TRANSLATE (*p) == TRANSLATE ('\n')
+ && !(syntax & RE_DOT_NEWLINE))
+ { /* We have .*\n. */
+ STORE_JUMP (jump, b, laststart);
+ keep_string_p = true;
+ }
+ else
+ /* Anything else. */
+ STORE_JUMP (maybe_pop_jump, b, laststart - 3);
+
+ /* We've added more stuff to the buffer. */
+ b += 3;
+ }
+
+ /* On failure, jump from laststart to b + 3, which will be the
+ end of the buffer after this jump is inserted. */
+ GET_BUFFER_SPACE (3);
+ INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump
+ : on_failure_jump,
+ laststart, b + 3);
+ pending_exact = 0;
+ b += 3;
+
+ if (!zero_times_ok)
+ {
+ /* At least one repetition is required, so insert a
+ `dummy_failure_jump' before the initial
+ `on_failure_jump' instruction of the loop. This
+ effects a skip over that instruction the first time
+ we hit that loop. */
+ GET_BUFFER_SPACE (3);
+ INSERT_JUMP (dummy_failure_jump, laststart, laststart + 6);
+ b += 3;
+ }
+ }
+ break;
+
+
+ case '.':
+ laststart = b;
+ BUF_PUSH (anychar);
+ break;
+
+
+ case '[':
+ {
+ boolean had_char_class = false;
+
+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+ /* Ensure that we have enough space to push a charset: the
+ opcode, the length count, and the bitset; 34 bytes in all. */
+ GET_BUFFER_SPACE (34);
+
+ laststart = b;
+
+ /* We test `*p == '^' twice, instead of using an if
+ statement, so we only need one BUF_PUSH. */
+ BUF_PUSH (*p == '^' ? charset_not : charset);
+ if (*p == '^')
+ p++;
+
+ /* Remember the first position in the bracket expression. */
+ p1 = p;
+
+ /* Push the number of bytes in the bitmap. */
+ BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH);
+
+ /* Clear the whole map. */
+ bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH);
+
+ /* charset_not matches newline according to a syntax bit. */
+ if ((re_opcode_t) b[-2] == charset_not
+ && (syntax & RE_HAT_LISTS_NOT_NEWLINE))
+ SET_LIST_BIT ('\n');
+
+ /* Read in characters and ranges, setting map bits. */
+ for (;;)
+ {
+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+ PATFETCH (c);
+
+ /* \ might escape characters inside [...] and [^...]. */
+ if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\')
+ {
+ if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
+
+ PATFETCH (c1);
+ SET_LIST_BIT (c1);
+ continue;
+ }
+
+ /* Could be the end of the bracket expression. If it's
+ not (i.e., when the bracket expression is `[]' so
+ far), the ']' character bit gets set way below. */
+ if (c == ']' && p != p1 + 1)
+ break;
+
+ /* Look ahead to see if it's a range when the last thing
+ was a character class. */
+ if (had_char_class && c == '-' && *p != ']')
+ FREE_STACK_RETURN (REG_ERANGE);
+
+ /* Look ahead to see if it's a range when the last thing
+ was a character: if this is a hyphen not at the
+ beginning or the end of a list, then it's the range
+ operator. */
+ if (c == '-'
+ && !(p - 2 >= pattern && p[-2] == '[')
+ && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^')
+ && *p != ']')
+ {
+ reg_errcode_t ret
+ = compile_range (&p, pend, translate, syntax, b);
+ if (ret != REG_NOERROR) FREE_STACK_RETURN (ret);
+ }
+
+ else if (p[0] == '-' && p[1] != ']')
+ { /* This handles ranges made up of characters only. */
+ reg_errcode_t ret;
+
+ /* Move past the `-'. */
+ PATFETCH (c1);
+
+ ret = compile_range (&p, pend, translate, syntax, b);
+ if (ret != REG_NOERROR) FREE_STACK_RETURN (ret);
+ }
+
+ /* See if we're at the beginning of a possible character
+ class. */
+
+ else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':')
+ { /* Leave room for the null. */
+ char str[CHAR_CLASS_MAX_LENGTH + 1];
+
+ PATFETCH (c);
+ c1 = 0;
+
+ /* If pattern is `[[:'. */
+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+ for (;;)
+ {
+ PATFETCH (c);
+ if ((c == ':' && *p == ']') || p == pend)
+ break;
+ if (c1 < CHAR_CLASS_MAX_LENGTH)
+ str[c1++] = c;
+ else
+ /* This is in any case an invalid class name. */
+ str[0] = '\0';
+ }
+ str[c1] = '\0';
+
+ /* If isn't a word bracketed by `[:' and `:]':
+ undo the ending character, the letters, and leave
+ the leading `:' and `[' (but set bits for them). */
+ if (c == ':' && *p == ']')
+ {
+#if defined _LIBC || WIDE_CHAR_SUPPORT
+ boolean is_lower = STREQ (str, "lower");
+ boolean is_upper = STREQ (str, "upper");
+ wctype_t wt;
+ int ch;
+
+ wt = IS_CHAR_CLASS (str);
+ if (wt == 0)
+ FREE_STACK_RETURN (REG_ECTYPE);
+
+ /* Throw away the ] at the end of the character
+ class. */
+ PATFETCH (c);
+
+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+ for (ch = 0; ch < 1 << BYTEWIDTH; ++ch)
+ {
+# ifdef _LIBC
+ if (__iswctype (__btowc (ch), wt))
+ SET_LIST_BIT (ch);
+# else
+ if (iswctype (btowc (ch), wt))
+ SET_LIST_BIT (ch);
+# endif
+
+ if (translate && (is_upper || is_lower)
+ && (ISUPPER (ch) || ISLOWER (ch)))
+ SET_LIST_BIT (ch);
+ }
+
+ had_char_class = true;
+#else
+ int ch;
+ boolean is_alnum = STREQ (str, "alnum");
+ boolean is_alpha = STREQ (str, "alpha");
+ boolean is_blank = STREQ (str, "blank");
+ boolean is_cntrl = STREQ (str, "cntrl");
+ boolean is_digit = STREQ (str, "digit");
+ boolean is_graph = STREQ (str, "graph");
+ boolean is_lower = STREQ (str, "lower");
+ boolean is_print = STREQ (str, "print");
+ boolean is_punct = STREQ (str, "punct");
+ boolean is_space = STREQ (str, "space");
+ boolean is_upper = STREQ (str, "upper");
+ boolean is_xdigit = STREQ (str, "xdigit");
+
+ if (!IS_CHAR_CLASS (str))
+ FREE_STACK_RETURN (REG_ECTYPE);
+
+ /* Throw away the ] at the end of the character
+ class. */
+ PATFETCH (c);
+
+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+ for (ch = 0; ch < 1 << BYTEWIDTH; ch++)
+ {
+ /* This was split into 3 if's to
+ avoid an arbitrary limit in some compiler. */
+ if ( (is_alnum && ISALNUM (ch))
+ || (is_alpha && ISALPHA (ch))
+ || (is_blank && ISBLANK (ch))
+ || (is_cntrl && ISCNTRL (ch)))
+ SET_LIST_BIT (ch);
+ if ( (is_digit && ISDIGIT (ch))
+ || (is_graph && ISGRAPH (ch))
+ || (is_lower && ISLOWER (ch))
+ || (is_print && ISPRINT (ch)))
+ SET_LIST_BIT (ch);
+ if ( (is_punct && ISPUNCT (ch))
+ || (is_space && ISSPACE (ch))
+ || (is_upper && ISUPPER (ch))
+ || (is_xdigit && ISXDIGIT (ch)))
+ SET_LIST_BIT (ch);
+ if ( translate && (is_upper || is_lower)
+ && (ISUPPER (ch) || ISLOWER (ch)))
+ SET_LIST_BIT (ch);
+ }
+ had_char_class = true;
+#endif /* libc || wctype.h */
+ }
+ else
+ {
+ c1++;
+ while (c1--)
+ PATUNFETCH;
+ SET_LIST_BIT ('[');
+ SET_LIST_BIT (':');
+ had_char_class = false;
+ }
+ }
+ else
+ {
+ had_char_class = false;
+ SET_LIST_BIT (c);
+ }
+ }
+
+ /* Discard any (non)matching list bytes that are all 0 at the
+ end of the map. Decrease the map-length byte too. */
+ while ((int) b[-1] > 0 && b[b[-1] - 1] == 0)
+ b[-1]--;
+ b += b[-1];
+ }
+ break;
+
+
+ case '(':
+ if (syntax & RE_NO_BK_PARENS)
+ goto handle_open;
+ else
+ goto normal_char;
+
+
+ case ')':
+ if (syntax & RE_NO_BK_PARENS)
+ goto handle_close;
+ else
+ goto normal_char;
+
+
+ case '\n':
+ if (syntax & RE_NEWLINE_ALT)
+ goto handle_alt;
+ else
+ goto normal_char;
+
+
+ case '|':
+ if (syntax & RE_NO_BK_VBAR)
+ goto handle_alt;
+ else
+ goto normal_char;
+
+
+ case '{':
+ if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES)
+ goto handle_interval;
+ else
+ goto normal_char;
+
+
+ case '\\':
+ if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
+
+ /* Do not translate the character after the \, so that we can
+ distinguish, e.g., \B from \b, even if we normally would
+ translate, e.g., B to b. */
+ PATFETCH_RAW (c);
+
+ switch (c)
+ {
+ case '(':
+ if (syntax & RE_NO_BK_PARENS)
+ goto normal_backslash;
+
+ handle_open:
+ bufp->re_nsub++;
+ regnum++;
+
+ if (COMPILE_STACK_FULL)
+ {
+ RETALLOC (compile_stack.stack, compile_stack.size << 1,
+ compile_stack_elt_t);
+ if (compile_stack.stack == NULL) return REG_ESPACE;
+
+ compile_stack.size <<= 1;
+ }
+
+ /* These are the values to restore when we hit end of this
+ group. They are all relative offsets, so that if the
+ whole pattern moves because of realloc, they will still
+ be valid. */
+ COMPILE_STACK_TOP.begalt_offset = begalt - bufp->buffer;
+ COMPILE_STACK_TOP.fixup_alt_jump
+ = fixup_alt_jump ? fixup_alt_jump - bufp->buffer + 1 : 0;
+ COMPILE_STACK_TOP.laststart_offset = b - bufp->buffer;
+ COMPILE_STACK_TOP.regnum = regnum;
+
+ /* We will eventually replace the 0 with the number of
+ groups inner to this one. But do not push a
+ start_memory for groups beyond the last one we can
+ represent in the compiled pattern. */
+ if (regnum <= MAX_REGNUM)
+ {
+ COMPILE_STACK_TOP.inner_group_offset = b - bufp->buffer + 2;
+ BUF_PUSH_3 (start_memory, regnum, 0);
+ }
+
+ compile_stack.avail++;
+
+ fixup_alt_jump = 0;
+ laststart = 0;
+ begalt = b;
+ /* If we've reached MAX_REGNUM groups, then this open
+ won't actually generate any code, so we'll have to
+ clear pending_exact explicitly. */
+ pending_exact = 0;
+ break;
+
+
+ case ')':
+ if (syntax & RE_NO_BK_PARENS) goto normal_backslash;
+
+ if (COMPILE_STACK_EMPTY)
+ {
+ if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
+ goto normal_backslash;
+ else
+ FREE_STACK_RETURN (REG_ERPAREN);
+ }
+
+ handle_close:
+ if (fixup_alt_jump)
+ { /* Push a dummy failure point at the end of the
+ alternative for a possible future
+ `pop_failure_jump' to pop. See comments at
+ `push_dummy_failure' in `re_match_2'. */
+ BUF_PUSH (push_dummy_failure);
+
+ /* We allocated space for this jump when we assigned
+ to `fixup_alt_jump', in the `handle_alt' case below. */
+ STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1);
+ }
+
+ /* See similar code for backslashed left paren above. */
+ if (COMPILE_STACK_EMPTY)
+ {
+ if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
+ goto normal_char;
+ else
+ FREE_STACK_RETURN (REG_ERPAREN);
+ }
+
+ /* Since we just checked for an empty stack above, this
+ ``can't happen''. */
+ assert (compile_stack.avail != 0);
+ {
+ /* We don't just want to restore into `regnum', because
+ later groups should continue to be numbered higher,
+ as in `(ab)c(de)' -- the second group is #2. */
+ regnum_t this_group_regnum;
+
+ compile_stack.avail--;
+ begalt = bufp->buffer + COMPILE_STACK_TOP.begalt_offset;
+ fixup_alt_jump
+ = COMPILE_STACK_TOP.fixup_alt_jump
+ ? bufp->buffer + COMPILE_STACK_TOP.fixup_alt_jump - 1
+ : 0;
+ laststart = bufp->buffer + COMPILE_STACK_TOP.laststart_offset;
+ this_group_regnum = COMPILE_STACK_TOP.regnum;
+ /* If we've reached MAX_REGNUM groups, then this open
+ won't actually generate any code, so we'll have to
+ clear pending_exact explicitly. */
+ pending_exact = 0;
+
+ /* We're at the end of the group, so now we know how many
+ groups were inside this one. */
+ if (this_group_regnum <= MAX_REGNUM)
+ {
+ unsigned char *inner_group_loc
+ = bufp->buffer + COMPILE_STACK_TOP.inner_group_offset;
+
+ *inner_group_loc = regnum - this_group_regnum;
+ BUF_PUSH_3 (stop_memory, this_group_regnum,
+ regnum - this_group_regnum);
+ }
+ }
+ break;
+
+
+ case '|': /* `\|'. */
+ if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR)
+ goto normal_backslash;
+ handle_alt:
+ if (syntax & RE_LIMITED_OPS)
+ goto normal_char;
+
+ /* Insert before the previous alternative a jump which
+ jumps to this alternative if the former fails. */
+ GET_BUFFER_SPACE (3);
+ INSERT_JUMP (on_failure_jump, begalt, b + 6);
+ pending_exact = 0;
+ b += 3;
+
+ /* The alternative before this one has a jump after it
+ which gets executed if it gets matched. Adjust that
+ jump so it will jump to this alternative's analogous
+ jump (put in below, which in turn will jump to the next
+ (if any) alternative's such jump, etc.). The last such
+ jump jumps to the correct final destination. A picture:
+ _____ _____
+ | | | |
+ | v | v
+ a | b | c
+
+ If we are at `b', then fixup_alt_jump right now points to a
+ three-byte space after `a'. We'll put in the jump, set
+ fixup_alt_jump to right after `b', and leave behind three
+ bytes which we'll fill in when we get to after `c'. */
+
+ if (fixup_alt_jump)
+ STORE_JUMP (jump_past_alt, fixup_alt_jump, b);
+
+ /* Mark and leave space for a jump after this alternative,
+ to be filled in later either by next alternative or
+ when know we're at the end of a series of alternatives. */
+ fixup_alt_jump = b;
+ GET_BUFFER_SPACE (3);
+ b += 3;
+
+ laststart = 0;
+ begalt = b;
+ break;
+
+
+ case '{':
+ /* If \{ is a literal. */
+ if (!(syntax & RE_INTERVALS)
+ /* If we're at `\{' and it's not the open-interval
+ operator. */
+ || ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
+ || (p - 2 == pattern && p == pend))
+ goto normal_backslash;
+
+ handle_interval:
+ {
+ /* If got here, then the syntax allows intervals. */
+
+ /* At least (most) this many matches must be made. */
+ int lower_bound = -1, upper_bound = -1;
+
+ beg_interval = p - 1;
+
+ if (p == pend)
+ {
+ if (syntax & RE_NO_BK_BRACES)
+ goto unfetch_interval;
+ else
+ FREE_STACK_RETURN (REG_EBRACE);
+ }
+
+ GET_UNSIGNED_NUMBER (lower_bound);
+
+ if (c == ',')
+ {
+ GET_UNSIGNED_NUMBER (upper_bound);
+ if (upper_bound < 0) upper_bound = RE_DUP_MAX;
+ }
+ else
+ /* Interval such as `{1}' => match exactly once. */
+ upper_bound = lower_bound;
+
+ if (lower_bound < 0 || upper_bound > RE_DUP_MAX
+ || lower_bound > upper_bound)
+ {
+ if (syntax & RE_NO_BK_BRACES)
+ goto unfetch_interval;
+ else
+ FREE_STACK_RETURN (REG_BADBR);
+ }
+
+ if (!(syntax & RE_NO_BK_BRACES))
+ {
+ if (c != '\\') FREE_STACK_RETURN (REG_EBRACE);
+
+ PATFETCH (c);
+ }
+
+ if (c != '}')
+ {
+ if (syntax & RE_NO_BK_BRACES)
+ goto unfetch_interval;
+ else
+ FREE_STACK_RETURN (REG_BADBR);
+ }
+
+ /* We just parsed a valid interval. */
+
+ /* If it's invalid to have no preceding re. */
+ if (!laststart)
+ {
+ if (syntax & RE_CONTEXT_INVALID_OPS)
+ FREE_STACK_RETURN (REG_BADRPT);
+ else if (syntax & RE_CONTEXT_INDEP_OPS)
+ laststart = b;
+ else
+ goto unfetch_interval;
+ }
+
+ /* If the upper bound is zero, don't want to succeed at
+ all; jump from `laststart' to `b + 3', which will be
+ the end of the buffer after we insert the jump. */
+ if (upper_bound == 0)
+ {
+ GET_BUFFER_SPACE (3);
+ INSERT_JUMP (jump, laststart, b + 3);
+ b += 3;
+ }
+
+ /* Otherwise, we have a nontrivial interval. When
+ we're all done, the pattern will look like:
+ set_number_at <jump count> <upper bound>
+ set_number_at <succeed_n count> <lower bound>
+ succeed_n <after jump addr> <succeed_n count>
+ <body of loop>
+ jump_n <succeed_n addr> <jump count>
+ (The upper bound and `jump_n' are omitted if
+ `upper_bound' is 1, though.) */
+ else
+ { /* If the upper bound is > 1, we need to insert
+ more at the end of the loop. */
+ unsigned nbytes = 10 + (upper_bound > 1) * 10;
+
+ GET_BUFFER_SPACE (nbytes);
+
+ /* Initialize lower bound of the `succeed_n', even
+ though it will be set during matching by its
+ attendant `set_number_at' (inserted next),
+ because `re_compile_fastmap' needs to know.
+ Jump to the `jump_n' we might insert below. */
+ INSERT_JUMP2 (succeed_n, laststart,
+ b + 5 + (upper_bound > 1) * 5,
+ lower_bound);
+ b += 5;
+
+ /* Code to initialize the lower bound. Insert
+ before the `succeed_n'. The `5' is the last two
+ bytes of this `set_number_at', plus 3 bytes of
+ the following `succeed_n'. */
+ insert_op2 (set_number_at, laststart, 5, lower_bound, b);
+ b += 5;
+
+ if (upper_bound > 1)
+ { /* More than one repetition is allowed, so
+ append a backward jump to the `succeed_n'
+ that starts this interval.
+
+ When we've reached this during matching,
+ we'll have matched the interval once, so
+ jump back only `upper_bound - 1' times. */
+ STORE_JUMP2 (jump_n, b, laststart + 5,
+ upper_bound - 1);
+ b += 5;
+
+ /* The location we want to set is the second
+ parameter of the `jump_n'; that is `b-2' as
+ an absolute address. `laststart' will be
+ the `set_number_at' we're about to insert;
+ `laststart+3' the number to set, the source
+ for the relative address. But we are
+ inserting into the middle of the pattern --
+ so everything is getting moved up by 5.
+ Conclusion: (b - 2) - (laststart + 3) + 5,
+ i.e., b - laststart.
+
+ We insert this at the beginning of the loop
+ so that if we fail during matching, we'll
+ reinitialize the bounds. */
+ insert_op2 (set_number_at, laststart, b - laststart,
+ upper_bound - 1, b);
+ b += 5;
+ }
+ }
+ pending_exact = 0;
+ beg_interval = NULL;
+ }
+ break;
+
+ unfetch_interval:
+ /* If an invalid interval, match the characters as literals. */
+ assert (beg_interval);
+ p = beg_interval;
+ beg_interval = NULL;
+
+ /* normal_char and normal_backslash need `c'. */
+ PATFETCH (c);
+
+ if (!(syntax & RE_NO_BK_BRACES))
+ {
+ if (p > pattern && p[-1] == '\\')
+ goto normal_backslash;
+ }
+ goto normal_char;
+
+#ifdef emacs
+ /* There is no way to specify the before_dot and after_dot
+ operators. rms says this is ok. --karl */
+ case '=':
+ BUF_PUSH (at_dot);
+ break;
+
+ case 's':
+ laststart = b;
+ PATFETCH (c);
+ BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]);
+ break;
+
+ case 'S':
+ laststart = b;
+ PATFETCH (c);
+ BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]);
+ break;
+#endif /* emacs */
+
+
+ case 'w':
+ if (syntax & RE_NO_GNU_OPS)
+ goto normal_char;
+ laststart = b;
+ BUF_PUSH (wordchar);
+ break;
+
+
+ case 'W':
+ if (syntax & RE_NO_GNU_OPS)
+ goto normal_char;
+ laststart = b;
+ BUF_PUSH (notwordchar);
+ break;
+
+
+ case '<':
+ if (syntax & RE_NO_GNU_OPS)
+ goto normal_char;
+ BUF_PUSH (wordbeg);
+ break;
+
+ case '>':
+ if (syntax & RE_NO_GNU_OPS)
+ goto normal_char;
+ BUF_PUSH (wordend);
+ break;
+
+ case 'b':
+ if (syntax & RE_NO_GNU_OPS)
+ goto normal_char;
+ BUF_PUSH (wordbound);
+ break;
+
+ case 'B':
+ if (syntax & RE_NO_GNU_OPS)
+ goto normal_char;
+ BUF_PUSH (notwordbound);
+ break;
+
+ case '`':
+ if (syntax & RE_NO_GNU_OPS)
+ goto normal_char;
+ BUF_PUSH (begbuf);
+ break;
+
+ case '\'':
+ if (syntax & RE_NO_GNU_OPS)
+ goto normal_char;
+ BUF_PUSH (endbuf);
+ break;
+
+ case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9':
+ if (syntax & RE_NO_BK_REFS)
+ goto normal_char;
+
+ c1 = c - '0';
+
+ if (c1 > regnum)
+ FREE_STACK_RETURN (REG_ESUBREG);
+
+ /* Can't back reference to a subexpression if inside of it. */
+ if (group_in_compile_stack (compile_stack, (regnum_t) c1))
+ goto normal_char;
+
+ laststart = b;
+ BUF_PUSH_2 (duplicate, c1);
+ break;
+
+
+ case '+':
+ case '?':
+ if (syntax & RE_BK_PLUS_QM)
+ goto handle_plus;
+ else
+ goto normal_backslash;
+
+ default:
+ normal_backslash:
+ /* You might think it would be useful for \ to mean
+ not to translate; but if we don't translate it
+ it will never match anything. */
+ c = TRANSLATE (c);
+ goto normal_char;
+ }
+ break;
+
+
+ default:
+ /* Expects the character in `c'. */
+ normal_char:
+ /* If no exactn currently being built. */
+ if (!pending_exact
+
+ /* If last exactn not at current position. */
+ || pending_exact + *pending_exact + 1 != b
+
+ /* We have only one byte following the exactn for the count. */
+ || *pending_exact == (1 << BYTEWIDTH) - 1
+
+ /* If followed by a repetition operator. */
+ || *p == '*' || *p == '^'
+ || ((syntax & RE_BK_PLUS_QM)
+ ? *p == '\\' && (p[1] == '+' || p[1] == '?')
+ : (*p == '+' || *p == '?'))
+ || ((syntax & RE_INTERVALS)
+ && ((syntax & RE_NO_BK_BRACES)
+ ? *p == '{'
+ : (p[0] == '\\' && p[1] == '{'))))
+ {
+ /* Start building a new exactn. */
+
+ laststart = b;
+
+ BUF_PUSH_2 (exactn, 0);
+ pending_exact = b - 1;
+ }
+
+ BUF_PUSH (c);
+ (*pending_exact)++;
+ break;
+ } /* switch (c) */
+ } /* while p != pend */
+
+
+ /* Through the pattern now. */
+
+ if (fixup_alt_jump)
+ STORE_JUMP (jump_past_alt, fixup_alt_jump, b);
+
+ if (!COMPILE_STACK_EMPTY)
+ FREE_STACK_RETURN (REG_EPAREN);
+
+ /* If we don't want backtracking, force success
+ the first time we reach the end of the compiled pattern. */
+ if (syntax & RE_NO_POSIX_BACKTRACKING)
+ BUF_PUSH (succeed);
+
+ free (compile_stack.stack);
+
+ /* We have succeeded; set the length of the buffer. */
+ bufp->used = b - bufp->buffer;
+
+#ifdef DEBUG
+ if (debug)
+ {
+ DEBUG_PRINT1 ("\nCompiled pattern: \n");
+ print_compiled_pattern (bufp);
+ }
+#endif /* DEBUG */
+
+#ifndef MATCH_MAY_ALLOCATE
+ /* Initialize the failure stack to the largest possible stack. This
+ isn't necessary unless we're trying to avoid calling alloca in
+ the search and match routines. */
+ {
+ int num_regs = bufp->re_nsub + 1;
+
+ /* Since DOUBLE_FAIL_STACK refuses to double only if the current size
+ is strictly greater than re_max_failures, the largest possible stack
+ is 2 * re_max_failures failure points. */
+ if (fail_stack.size < (2 * re_max_failures * MAX_FAILURE_ITEMS))
+ {
+ fail_stack.size = (2 * re_max_failures * MAX_FAILURE_ITEMS);
+
+# ifdef emacs
+ if (! fail_stack.stack)
+ fail_stack.stack
+ = (fail_stack_elt_t *) xmalloc (fail_stack.size
+ * sizeof (fail_stack_elt_t));
+ else
+ fail_stack.stack
+ = (fail_stack_elt_t *) xrealloc (fail_stack.stack,
+ (fail_stack.size
+ * sizeof (fail_stack_elt_t)));
+# else /* not emacs */
+ if (! fail_stack.stack)
+ fail_stack.stack
+ = (fail_stack_elt_t *) malloc (fail_stack.size
+ * sizeof (fail_stack_elt_t));
+ else
+ fail_stack.stack
+ = (fail_stack_elt_t *) realloc (fail_stack.stack,
+ (fail_stack.size
+ * sizeof (fail_stack_elt_t)));
+# endif /* not emacs */
+ }
+
+ regex_grow_registers (num_regs);
+ }
+#endif /* not MATCH_MAY_ALLOCATE */
+
+ return REG_NOERROR;
+} /* regex_compile */
+
+/* Subroutines for `regex_compile'. */
+
+/* Store OP at LOC followed by two-byte integer parameter ARG. */
+
+static void
+store_op1 (op, loc, arg)
+ re_opcode_t op;
+ unsigned char *loc;
+ int arg;
+{
+ *loc = (unsigned char) op;
+ STORE_NUMBER (loc + 1, arg);
+}
+
+
+/* Like `store_op1', but for two two-byte parameters ARG1 and ARG2. */
+
+static void
+store_op2 (op, loc, arg1, arg2)
+ re_opcode_t op;
+ unsigned char *loc;
+ int arg1, arg2;
+{
+ *loc = (unsigned char) op;
+ STORE_NUMBER (loc + 1, arg1);
+ STORE_NUMBER (loc + 3, arg2);
+}
+
+
+/* Copy the bytes from LOC to END to open up three bytes of space at LOC
+ for OP followed by two-byte integer parameter ARG. */
+
+static void
+insert_op1 (op, loc, arg, end)
+ re_opcode_t op;
+ unsigned char *loc;
+ int arg;
+ unsigned char *end;
+{
+ register unsigned char *pfrom = end;
+ register unsigned char *pto = end + 3;
+
+ while (pfrom != loc)
+ *--pto = *--pfrom;
+
+ store_op1 (op, loc, arg);
+}
+
+
+/* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2. */
+
+static void
+insert_op2 (op, loc, arg1, arg2, end)
+ re_opcode_t op;
+ unsigned char *loc;
+ int arg1, arg2;
+ unsigned char *end;
+{
+ register unsigned char *pfrom = end;
+ register unsigned char *pto = end + 5;
+
+ while (pfrom != loc)
+ *--pto = *--pfrom;
+
+ store_op2 (op, loc, arg1, arg2);
+}
+
+
+/* P points to just after a ^ in PATTERN. Return true if that ^ comes
+ after an alternative or a begin-subexpression. We assume there is at
+ least one character before the ^. */
+
+static boolean
+at_begline_loc_p (pattern, p, syntax)
+ const char *pattern, *p;
+ reg_syntax_t syntax;
+{
+ const char *prev = p - 2;
+ boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\';
+
+ return
+ /* After a subexpression? */
+ (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash))
+ /* After an alternative? */
+ || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash));
+}
+
+
+/* The dual of at_begline_loc_p. This one is for $. We assume there is
+ at least one character after the $, i.e., `P < PEND'. */
+
+static boolean
+at_endline_loc_p (p, pend, syntax)
+ const char *p, *pend;
+ reg_syntax_t syntax;
+{
+ const char *next = p;
+ boolean next_backslash = *next == '\\';
+ const char *next_next = p + 1 < pend ? p + 1 : 0;
+
+ return
+ /* Before a subexpression? */
+ (syntax & RE_NO_BK_PARENS ? *next == ')'
+ : next_backslash && next_next && *next_next == ')')
+ /* Before an alternative? */
+ || (syntax & RE_NO_BK_VBAR ? *next == '|'
+ : next_backslash && next_next && *next_next == '|');
+}
+
+
+/* Returns true if REGNUM is in one of COMPILE_STACK's elements and
+ false if it's not. */
+
+static boolean
+group_in_compile_stack (compile_stack, regnum)
+ compile_stack_type compile_stack;
+ regnum_t regnum;
+{
+ int this_element;
+
+ for (this_element = compile_stack.avail - 1;
+ this_element >= 0;
+ this_element--)
+ if (compile_stack.stack[this_element].regnum == regnum)
+ return true;
+
+ return false;
+}
+
+
+/* Read the ending character of a range (in a bracket expression) from the
+ uncompiled pattern *P_PTR (which ends at PEND). We assume the
+ starting character is in `P[-2]'. (`P[-1]' is the character `-'.)
+ Then we set the translation of all bits between the starting and
+ ending characters (inclusive) in the compiled pattern B.
+
+ Return an error code.
+
+ We use these short variable names so we can use the same macros as
+ `regex_compile' itself. */
+
+static reg_errcode_t
+compile_range (p_ptr, pend, translate, syntax, b)
+ const char **p_ptr, *pend;
+ RE_TRANSLATE_TYPE translate;
+ reg_syntax_t syntax;
+ unsigned char *b;
+{
+ unsigned this_char;
+
+ const char *p = *p_ptr;
+ unsigned int range_start, range_end;
+
+ if (p == pend)
+ return REG_ERANGE;
+
+ /* Even though the pattern is a signed `char *', we need to fetch
+ with unsigned char *'s; if the high bit of the pattern character
+ is set, the range endpoints will be negative if we fetch using a
+ signed char *.
+
+ We also want to fetch the endpoints without translating them; the
+ appropriate translation is done in the bit-setting loop below. */
+ /* The SVR4 compiler on the 3B2 had trouble with unsigned const char *. */
+ range_start = ((const unsigned char *) p)[-2];
+ range_end = ((const unsigned char *) p)[0];
+
+ /* Have to increment the pointer into the pattern string, so the
+ caller isn't still at the ending character. */
+ (*p_ptr)++;
+
+ /* If the start is after the end, the range is empty. */
+ if (range_start > range_end)
+ return syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR;
+
+ /* Here we see why `this_char' has to be larger than an `unsigned
+ char' -- the range is inclusive, so if `range_end' == 0xff
+ (assuming 8-bit characters), we would otherwise go into an infinite
+ loop, since all characters <= 0xff. */
+ for (this_char = range_start; this_char <= range_end; this_char++)
+ {
+ SET_LIST_BIT (TRANSLATE (this_char));
+ }
+
+ return REG_NOERROR;
+}
+
+/* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in
+ BUFP. A fastmap records which of the (1 << BYTEWIDTH) possible
+ characters can start a string that matches the pattern. This fastmap
+ is used by re_search to skip quickly over impossible starting points.
+
+ The caller must supply the address of a (1 << BYTEWIDTH)-byte data
+ area as BUFP->fastmap.
+
+ We set the `fastmap', `fastmap_accurate', and `can_be_null' fields in
+ the pattern buffer.
+
+ Returns 0 if we succeed, -2 if an internal error. */
+
+int
+re_compile_fastmap (bufp)
+ struct re_pattern_buffer *bufp;
+{
+ int j, k;
+#ifdef MATCH_MAY_ALLOCATE
+ fail_stack_type fail_stack;
+#endif
+#ifndef REGEX_MALLOC
+ char *destination;
+#endif
+
+ register char *fastmap = bufp->fastmap;
+ unsigned char *pattern = bufp->buffer;
+ unsigned char *p = pattern;
+ register unsigned char *pend = pattern + bufp->used;
+
+#ifdef REL_ALLOC
+ /* This holds the pointer to the failure stack, when
+ it is allocated relocatably. */
+ fail_stack_elt_t *failure_stack_ptr;
+#endif
+
+ /* Assume that each path through the pattern can be null until
+ proven otherwise. We set this false at the bottom of switch
+ statement, to which we get only if a particular path doesn't
+ match the empty string. */
+ boolean path_can_be_null = true;
+
+ /* We aren't doing a `succeed_n' to begin with. */
+ boolean succeed_n_p = false;
+
+ assert (fastmap != NULL && p != NULL);
+
+ INIT_FAIL_STACK ();
+ bzero (fastmap, 1 << BYTEWIDTH); /* Assume nothing's valid. */
+ bufp->fastmap_accurate = 1; /* It will be when we're done. */
+ bufp->can_be_null = 0;
+
+ while (1)
+ {
+ if (p == pend || *p == succeed)
+ {
+ /* We have reached the (effective) end of pattern. */
+ if (!FAIL_STACK_EMPTY ())
+ {
+ bufp->can_be_null |= path_can_be_null;
+
+ /* Reset for next path. */
+ path_can_be_null = true;
+
+ p = fail_stack.stack[--fail_stack.avail].pointer;
+
+ continue;
+ }
+ else
+ break;
+ }
+
+ /* We should never be about to go beyond the end of the pattern. */
+ assert (p < pend);
+
+ switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++))
+ {
+
+ /* I guess the idea here is to simply not bother with a fastmap
+ if a backreference is used, since it's too hard to figure out
+ the fastmap for the corresponding group. Setting
+ `can_be_null' stops `re_search_2' from using the fastmap, so
+ that is all we do. */
+ case duplicate:
+ bufp->can_be_null = 1;
+ goto done;
+
+
+ /* Following are the cases which match a character. These end
+ with `break'. */
+
+ case exactn:
+ fastmap[p[1]] = 1;
+ break;
+
+
+ case charset:
+ for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
+ if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))
+ fastmap[j] = 1;
+ break;
+
+
+ case charset_not:
+ /* Chars beyond end of map must be allowed. */
+ for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++)
+ fastmap[j] = 1;
+
+ for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
+ if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))))
+ fastmap[j] = 1;
+ break;
+
+
+ case wordchar:
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (SYNTAX (j) == Sword)
+ fastmap[j] = 1;
+ break;
+
+
+ case notwordchar:
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (SYNTAX (j) != Sword)
+ fastmap[j] = 1;
+ break;
+
+
+ case anychar:
+ {
+ int fastmap_newline = fastmap['\n'];
+
+ /* `.' matches anything ... */
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ fastmap[j] = 1;
+
+ /* ... except perhaps newline. */
+ if (!(bufp->syntax & RE_DOT_NEWLINE))
+ fastmap['\n'] = fastmap_newline;
+
+ /* Return if we have already set `can_be_null'; if we have,
+ then the fastmap is irrelevant. Something's wrong here. */
+ else if (bufp->can_be_null)
+ goto done;
+
+ /* Otherwise, have to check alternative paths. */
+ break;
+ }
+
+#ifdef emacs
+ case syntaxspec:
+ k = *p++;
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (SYNTAX (j) == (enum syntaxcode) k)
+ fastmap[j] = 1;
+ break;
+
+
+ case notsyntaxspec:
+ k = *p++;
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (SYNTAX (j) != (enum syntaxcode) k)
+ fastmap[j] = 1;
+ break;
+
+
+ /* All cases after this match the empty string. These end with
+ `continue'. */
+
+
+ case before_dot:
+ case at_dot:
+ case after_dot:
+ continue;
+#endif /* emacs */
+
+
+ case no_op:
+ case begline:
+ case endline:
+ case begbuf:
+ case endbuf:
+ case wordbound:
+ case notwordbound:
+ case wordbeg:
+ case wordend:
+ case push_dummy_failure:
+ continue;
+
+
+ case jump_n:
+ case pop_failure_jump:
+ case maybe_pop_jump:
+ case jump:
+ case jump_past_alt:
+ case dummy_failure_jump:
+ EXTRACT_NUMBER_AND_INCR (j, p);
+ p += j;
+ if (j > 0)
+ continue;
+
+ /* Jump backward implies we just went through the body of a
+ loop and matched nothing. Opcode jumped to should be
+ `on_failure_jump' or `succeed_n'. Just treat it like an
+ ordinary jump. For a * loop, it has pushed its failure
+ point already; if so, discard that as redundant. */
+ if ((re_opcode_t) *p != on_failure_jump
+ && (re_opcode_t) *p != succeed_n)
+ continue;
+
+ p++;
+ EXTRACT_NUMBER_AND_INCR (j, p);
+ p += j;
+
+ /* If what's on the stack is where we are now, pop it. */
+ if (!FAIL_STACK_EMPTY ()
+ && fail_stack.stack[fail_stack.avail - 1].pointer == p)
+ fail_stack.avail--;
+
+ continue;
+
+
+ case on_failure_jump:
+ case on_failure_keep_string_jump:
+ handle_on_failure_jump:
+ EXTRACT_NUMBER_AND_INCR (j, p);
+
+ /* For some patterns, e.g., `(a?)?', `p+j' here points to the
+ end of the pattern. We don't want to push such a point,
+ since when we restore it above, entering the switch will
+ increment `p' past the end of the pattern. We don't need
+ to push such a point since we obviously won't find any more
+ fastmap entries beyond `pend'. Such a pattern can match
+ the null string, though. */
+ if (p + j < pend)
+ {
+ if (!PUSH_PATTERN_OP (p + j, fail_stack))
+ {
+ RESET_FAIL_STACK ();
+ return -2;
+ }
+ }
+ else
+ bufp->can_be_null = 1;
+
+ if (succeed_n_p)
+ {
+ EXTRACT_NUMBER_AND_INCR (k, p); /* Skip the n. */
+ succeed_n_p = false;
+ }
+
+ continue;
+
+
+ case succeed_n:
+ /* Get to the number of times to succeed. */
+ p += 2;
+
+ /* Increment p past the n for when k != 0. */
+ EXTRACT_NUMBER_AND_INCR (k, p);
+ if (k == 0)
+ {
+ p -= 4;
+ succeed_n_p = true; /* Spaghetti code alert. */
+ goto handle_on_failure_jump;
+ }
+ continue;
+
+
+ case set_number_at:
+ p += 4;
+ continue;
+
+
+ case start_memory:
+ case stop_memory:
+ p += 2;
+ continue;
+
+
+ default:
+ abort (); /* We have listed all the cases. */
+ } /* switch *p++ */
+
+ /* Getting here means we have found the possible starting
+ characters for one path of the pattern -- and that the empty
+ string does not match. We need not follow this path further.
+ Instead, look at the next alternative (remembered on the
+ stack), or quit if no more. The test at the top of the loop
+ does these things. */
+ path_can_be_null = false;
+ p = pend;
+ } /* while p */
+
+ /* Set `can_be_null' for the last path (also the first path, if the
+ pattern is empty). */
+ bufp->can_be_null |= path_can_be_null;
+
+ done:
+ RESET_FAIL_STACK ();
+ return 0;
+} /* re_compile_fastmap */
+#ifdef _LIBC
+weak_alias (__re_compile_fastmap, re_compile_fastmap)
+#endif
+
+/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
+ ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use
+ this memory for recording register information. STARTS and ENDS
+ must be allocated using the malloc library routine, and must each
+ be at least NUM_REGS * sizeof (regoff_t) bytes long.
+
+ If NUM_REGS == 0, then subsequent matches should allocate their own
+ register data.
+
+ Unless this function is called, the first search or match using
+ PATTERN_BUFFER will allocate its own register data, without
+ freeing the old data. */
+
+void
+re_set_registers (bufp, regs, num_regs, starts, ends)
+ struct re_pattern_buffer *bufp;
+ struct re_registers *regs;
+ unsigned num_regs;
+ regoff_t *starts, *ends;
+{
+ if (num_regs)
+ {
+ bufp->regs_allocated = REGS_REALLOCATE;
+ regs->num_regs = num_regs;
+ regs->start = starts;
+ regs->end = ends;
+ }
+ else
+ {
+ bufp->regs_allocated = REGS_UNALLOCATED;
+ regs->num_regs = 0;
+ regs->start = regs->end = (regoff_t *) 0;
+ }
+}
+#ifdef _LIBC
+weak_alias (__re_set_registers, re_set_registers)
+#endif
+
+/* Searching routines. */
+
+/* Like re_search_2, below, but only one string is specified, and
+ doesn't let you say where to stop matching. */
+
+int
+re_search (bufp, string, size, startpos, range, regs)
+ struct re_pattern_buffer *bufp;
+ const char *string;
+ int size, startpos, range;
+ struct re_registers *regs;
+{
+ return re_search_2 (bufp, NULL, 0, string, size, startpos, range,
+ regs, size);
+}
+#ifdef _LIBC
+weak_alias (__re_search, re_search)
+#endif
+
+
+/* Using the compiled pattern in BUFP->buffer, first tries to match the
+ virtual concatenation of STRING1 and STRING2, starting first at index
+ STARTPOS, then at STARTPOS + 1, and so on.
+
+ STRING1 and STRING2 have length SIZE1 and SIZE2, respectively.
+
+ RANGE is how far to scan while trying to match. RANGE = 0 means try
+ only at STARTPOS; in general, the last start tried is STARTPOS +
+ RANGE.
+
+ In REGS, return the indices of the virtual concatenation of STRING1
+ and STRING2 that matched the entire BUFP->buffer and its contained
+ subexpressions.
+
+ Do not consider matching one past the index STOP in the virtual
+ concatenation of STRING1 and STRING2.
+
+ We return either the position in the strings at which the match was
+ found, -1 if no match, or -2 if error (such as failure
+ stack overflow). */
+
+int
+re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop)
+ struct re_pattern_buffer *bufp;
+ const char *string1, *string2;
+ int size1, size2;
+ int startpos;
+ int range;
+ struct re_registers *regs;
+ int stop;
+{
+ int val;
+ register char *fastmap = bufp->fastmap;
+ register RE_TRANSLATE_TYPE translate = bufp->translate;
+ int total_size = size1 + size2;
+ int endpos = startpos + range;
+
+ /* Check for out-of-range STARTPOS. */
+ if (startpos < 0 || startpos > total_size)
+ return -1;
+
+ /* Fix up RANGE if it might eventually take us outside
+ the virtual concatenation of STRING1 and STRING2.
+ Make sure we won't move STARTPOS below 0 or above TOTAL_SIZE. */
+ if (endpos < 0)
+ range = 0 - startpos;
+ else if (endpos > total_size)
+ range = total_size - startpos;
+
+ /* If the search isn't to be a backwards one, don't waste time in a
+ search for a pattern that must be anchored. */
+ if (bufp->used > 0 && range > 0
+ && ((re_opcode_t) bufp->buffer[0] == begbuf
+ /* `begline' is like `begbuf' if it cannot match at newlines. */
+ || ((re_opcode_t) bufp->buffer[0] == begline
+ && !bufp->newline_anchor)))
+ {
+ if (startpos > 0)
+ return -1;
+ else
+ range = 1;
+ }
+
+#ifdef emacs
+ /* In a forward search for something that starts with \=.
+ don't keep searching past point. */
+ if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == at_dot && range > 0)
+ {
+ range = PT - startpos;
+ if (range <= 0)
+ return -1;
+ }
+#endif /* emacs */
+
+ /* Update the fastmap now if not correct already. */
+ if (fastmap && !bufp->fastmap_accurate)
+ if (re_compile_fastmap (bufp) == -2)
+ return -2;
+
+ /* Loop through the string, looking for a place to start matching. */
+ for (;;)
+ {
+ /* If a fastmap is supplied, skip quickly over characters that
+ cannot be the start of a match. If the pattern can match the
+ null string, however, we don't need to skip characters; we want
+ the first null string. */
+ if (fastmap && startpos < total_size && !bufp->can_be_null)
+ {
+ if (range > 0) /* Searching forwards. */
+ {
+ register const char *d;
+ register int lim = 0;
+ int irange = range;
+
+ if (startpos < size1 && startpos + range >= size1)
+ lim = range - (size1 - startpos);
+
+ d = (startpos >= size1 ? string2 - size1 : string1) + startpos;
+
+ /* Written out as an if-else to avoid testing `translate'
+ inside the loop. */
+ if (translate)
+ while (range > lim
+ && !fastmap[(unsigned char)
+ translate[(unsigned char) *d++]])
+ range--;
+ else
+ while (range > lim && !fastmap[(unsigned char) *d++])
+ range--;
+
+ startpos += irange - range;
+ }
+ else /* Searching backwards. */
+ {
+ register char c = (size1 == 0 || startpos >= size1
+ ? string2[startpos - size1]
+ : string1[startpos]);
+
+ if (!fastmap[(unsigned char) TRANSLATE (c)])
+ goto advance;
+ }
+ }
+
+ /* If can't match the null string, and that's all we have left, fail. */
+ if (range >= 0 && startpos == total_size && fastmap
+ && !bufp->can_be_null)
+ return -1;
+
+ val = re_match_2_internal (bufp, string1, size1, string2, size2,
+ startpos, regs, stop);
+#ifndef REGEX_MALLOC
+# ifdef C_ALLOCA
+ alloca (0);
+# endif
+#endif
+
+ if (val >= 0)
+ return startpos;
+
+ if (val == -2)
+ return -2;
+
+ advance:
+ if (!range)
+ break;
+ else if (range > 0)
+ {
+ range--;
+ startpos++;
+ }
+ else
+ {
+ range++;
+ startpos--;
+ }
+ }
+ return -1;
+} /* re_search_2 */
+#ifdef _LIBC
+weak_alias (__re_search_2, re_search_2)
+#endif
+
+/* This converts PTR, a pointer into one of the search strings `string1'
+ and `string2' into an offset from the beginning of that string. */
+#define POINTER_TO_OFFSET(ptr) \
+ (FIRST_STRING_P (ptr) \
+ ? ((regoff_t) ((ptr) - string1)) \
+ : ((regoff_t) ((ptr) - string2 + size1)))
+
+/* Macros for dealing with the split strings in re_match_2. */
+
+#define MATCHING_IN_FIRST_STRING (dend == end_match_1)
+
+/* Call before fetching a character with *d. This switches over to
+ string2 if necessary. */
+#define PREFETCH() \
+ while (d == dend) \
+ { \
+ /* End of string2 => fail. */ \
+ if (dend == end_match_2) \
+ goto fail; \
+ /* End of string1 => advance to string2. */ \
+ d = string2; \
+ dend = end_match_2; \
+ }
+
+
+/* Test if at very beginning or at very end of the virtual concatenation
+ of `string1' and `string2'. If only one string, it's `string2'. */
+#define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2)
+#define AT_STRINGS_END(d) ((d) == end2)
+
+
+/* Test if D points to a character which is word-constituent. We have
+ two special cases to check for: if past the end of string1, look at
+ the first character in string2; and if before the beginning of
+ string2, look at the last character in string1. */
+#define WORDCHAR_P(d) \
+ (SYNTAX ((d) == end1 ? *string2 \
+ : (d) == string2 - 1 ? *(end1 - 1) : *(d)) \
+ == Sword)
+
+/* Disabled due to a compiler bug -- see comment at case wordbound */
+#if 0
+/* Test if the character before D and the one at D differ with respect
+ to being word-constituent. */
+#define AT_WORD_BOUNDARY(d) \
+ (AT_STRINGS_BEG (d) || AT_STRINGS_END (d) \
+ || WORDCHAR_P (d - 1) != WORDCHAR_P (d))
+#endif
+
+/* Free everything we malloc. */
+#ifdef MATCH_MAY_ALLOCATE
+# define FREE_VAR(var) if (var) REGEX_FREE (var); var = NULL
+# define FREE_VARIABLES() \
+ do { \
+ REGEX_FREE_STACK (fail_stack.stack); \
+ FREE_VAR (regstart); \
+ FREE_VAR (regend); \
+ FREE_VAR (old_regstart); \
+ FREE_VAR (old_regend); \
+ FREE_VAR (best_regstart); \
+ FREE_VAR (best_regend); \
+ FREE_VAR (reg_info); \
+ FREE_VAR (reg_dummy); \
+ FREE_VAR (reg_info_dummy); \
+ } while (0)
+#else
+# define FREE_VARIABLES() ((void)0) /* Do nothing! But inhibit gcc warning. */
+#endif /* not MATCH_MAY_ALLOCATE */
+
+/* These values must meet several constraints. They must not be valid
+ register values; since we have a limit of 255 registers (because
+ we use only one byte in the pattern for the register number), we can
+ use numbers larger than 255. They must differ by 1, because of
+ NUM_FAILURE_ITEMS above. And the value for the lowest register must
+ be larger than the value for the highest register, so we do not try
+ to actually save any registers when none are active. */
+#define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH)
+#define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1)
+
+/* Matching routines. */
+
+#ifndef emacs /* Emacs never uses this. */
+/* re_match is like re_match_2 except it takes only a single string. */
+
+int
+re_match (bufp, string, size, pos, regs)
+ struct re_pattern_buffer *bufp;
+ const char *string;
+ int size, pos;
+ struct re_registers *regs;
+{
+ int result = re_match_2_internal (bufp, NULL, 0, string, size,
+ pos, regs, size);
+# ifndef REGEX_MALLOC
+# ifdef C_ALLOCA
+ alloca (0);
+# endif
+# endif
+ return result;
+}
+# ifdef _LIBC
+weak_alias (__re_match, re_match)
+# endif
+#endif /* not emacs */
+
+static boolean group_match_null_string_p _RE_ARGS ((unsigned char **p,
+ unsigned char *end,
+ register_info_type *reg_info));
+static boolean alt_match_null_string_p _RE_ARGS ((unsigned char *p,
+ unsigned char *end,
+ register_info_type *reg_info));
+static boolean common_op_match_null_string_p _RE_ARGS ((unsigned char **p,
+ unsigned char *end,
+ register_info_type *reg_info));
+static int bcmp_translate _RE_ARGS ((const char *s1, const char *s2,
+ int len, char *translate));
+
+/* re_match_2 matches the compiled pattern in BUFP against the
+ the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1
+ and SIZE2, respectively). We start matching at POS, and stop
+ matching at STOP.
+
+ If REGS is non-null and the `no_sub' field of BUFP is nonzero, we
+ store offsets for the substring each group matched in REGS. See the
+ documentation for exactly how many groups we fill.
+
+ We return -1 if no match, -2 if an internal error (such as the
+ failure stack overflowing). Otherwise, we return the length of the
+ matched substring. */
+
+int
+re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
+ struct re_pattern_buffer *bufp;
+ const char *string1, *string2;
+ int size1, size2;
+ int pos;
+ struct re_registers *regs;
+ int stop;
+{
+ int result = re_match_2_internal (bufp, string1, size1, string2, size2,
+ pos, regs, stop);
+#ifndef REGEX_MALLOC
+# ifdef C_ALLOCA
+ alloca (0);
+# endif
+#endif
+ return result;
+}
+#ifdef _LIBC
+weak_alias (__re_match_2, re_match_2)
+#endif
+
+/* This is a separate function so that we can force an alloca cleanup
+ afterwards. */
+static int
+re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
+ struct re_pattern_buffer *bufp;
+ const char *string1, *string2;
+ int size1, size2;
+ int pos;
+ struct re_registers *regs;
+ int stop;
+{
+ /* General temporaries. */
+ int mcnt;
+ unsigned char *p1;
+
+ /* Just past the end of the corresponding string. */
+ const char *end1, *end2;
+
+ /* Pointers into string1 and string2, just past the last characters in
+ each to consider matching. */
+ const char *end_match_1, *end_match_2;
+
+ /* Where we are in the data, and the end of the current string. */
+ const char *d, *dend;
+
+ /* Where we are in the pattern, and the end of the pattern. */
+ unsigned char *p = bufp->buffer;
+ register unsigned char *pend = p + bufp->used;
+
+ /* Mark the opcode just after a start_memory, so we can test for an
+ empty subpattern when we get to the stop_memory. */
+ unsigned char *just_past_start_mem = 0;
+
+ /* We use this to map every character in the string. */
+ RE_TRANSLATE_TYPE translate = bufp->translate;
+
+ /* Failure point stack. Each place that can handle a failure further
+ down the line pushes a failure point on this stack. It consists of
+ restart, regend, and reg_info for all registers corresponding to
+ the subexpressions we're currently inside, plus the number of such
+ registers, and, finally, two char *'s. The first char * is where
+ to resume scanning the pattern; the second one is where to resume
+ scanning the strings. If the latter is zero, the failure point is
+ a ``dummy''; if a failure happens and the failure point is a dummy,
+ it gets discarded and the next next one is tried. */
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */
+ fail_stack_type fail_stack;
+#endif
+#ifdef DEBUG
+ static unsigned failure_id = 0;
+ unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0;
+#endif
+
+#ifdef REL_ALLOC
+ /* This holds the pointer to the failure stack, when
+ it is allocated relocatably. */
+ fail_stack_elt_t *failure_stack_ptr;
+#endif
+
+ /* We fill all the registers internally, independent of what we
+ return, for use in backreferences. The number here includes
+ an element for register zero. */
+ size_t num_regs = bufp->re_nsub + 1;
+
+ /* The currently active registers. */
+ active_reg_t lowest_active_reg = NO_LOWEST_ACTIVE_REG;
+ active_reg_t highest_active_reg = NO_HIGHEST_ACTIVE_REG;
+
+ /* Information on the contents of registers. These are pointers into
+ the input strings; they record just what was matched (on this
+ attempt) by a subexpression part of the pattern, that is, the
+ regnum-th regstart pointer points to where in the pattern we began
+ matching and the regnum-th regend points to right after where we
+ stopped matching the regnum-th subexpression. (The zeroth register
+ keeps track of what the whole pattern matches.) */
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */
+ const char **regstart, **regend;
+#endif
+
+ /* If a group that's operated upon by a repetition operator fails to
+ match anything, then the register for its start will need to be
+ restored because it will have been set to wherever in the string we
+ are when we last see its open-group operator. Similarly for a
+ register's end. */
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */
+ const char **old_regstart, **old_regend;
+#endif
+
+ /* The is_active field of reg_info helps us keep track of which (possibly
+ nested) subexpressions we are currently in. The matched_something
+ field of reg_info[reg_num] helps us tell whether or not we have
+ matched any of the pattern so far this time through the reg_num-th
+ subexpression. These two fields get reset each time through any
+ loop their register is in. */
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */
+ register_info_type *reg_info;
+#endif
+
+ /* The following record the register info as found in the above
+ variables when we find a match better than any we've seen before.
+ This happens as we backtrack through the failure points, which in
+ turn happens only if we have not yet matched the entire string. */
+ unsigned best_regs_set = false;
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */
+ const char **best_regstart, **best_regend;
+#endif
+
+ /* Logically, this is `best_regend[0]'. But we don't want to have to
+ allocate space for that if we're not allocating space for anything
+ else (see below). Also, we never need info about register 0 for
+ any of the other register vectors, and it seems rather a kludge to
+ treat `best_regend' differently than the rest. So we keep track of
+ the end of the best match so far in a separate variable. We
+ initialize this to NULL so that when we backtrack the first time
+ and need to test it, it's not garbage. */
+ const char *match_end = NULL;
+
+ /* This helps SET_REGS_MATCHED avoid doing redundant work. */
+ int set_regs_matched_done = 0;
+
+ /* Used when we pop values we don't care about. */
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */
+ const char **reg_dummy;
+ register_info_type *reg_info_dummy;
+#endif
+
+#ifdef DEBUG
+ /* Counts the total number of registers pushed. */
+ unsigned num_regs_pushed = 0;
+#endif
+
+ DEBUG_PRINT1 ("\n\nEntering re_match_2.\n");
+
+ INIT_FAIL_STACK ();
+
+#ifdef MATCH_MAY_ALLOCATE
+ /* Do not bother to initialize all the register variables if there are
+ no groups in the pattern, as it takes a fair amount of time. If
+ there are groups, we include space for register 0 (the whole
+ pattern), even though we never use it, since it simplifies the
+ array indexing. We should fix this. */
+ if (bufp->re_nsub)
+ {
+ regstart = REGEX_TALLOC (num_regs, const char *);
+ regend = REGEX_TALLOC (num_regs, const char *);
+ old_regstart = REGEX_TALLOC (num_regs, const char *);
+ old_regend = REGEX_TALLOC (num_regs, const char *);
+ best_regstart = REGEX_TALLOC (num_regs, const char *);
+ best_regend = REGEX_TALLOC (num_regs, const char *);
+ reg_info = REGEX_TALLOC (num_regs, register_info_type);
+ reg_dummy = REGEX_TALLOC (num_regs, const char *);
+ reg_info_dummy = REGEX_TALLOC (num_regs, register_info_type);
+
+ if (!(regstart && regend && old_regstart && old_regend && reg_info
+ && best_regstart && best_regend && reg_dummy && reg_info_dummy))
+ {
+ FREE_VARIABLES ();
+ return -2;
+ }
+ }
+ else
+ {
+ /* We must initialize all our variables to NULL, so that
+ `FREE_VARIABLES' doesn't try to free them. */
+ regstart = regend = old_regstart = old_regend = best_regstart
+ = best_regend = reg_dummy = NULL;
+ reg_info = reg_info_dummy = (register_info_type *) NULL;
+ }
+#endif /* MATCH_MAY_ALLOCATE */
+
+ /* The starting position is bogus. */
+ if (pos < 0 || pos > size1 + size2)
+ {
+ FREE_VARIABLES ();
+ return -1;
+ }
+
+ /* Initialize subexpression text positions to -1 to mark ones that no
+ start_memory/stop_memory has been seen for. Also initialize the
+ register information struct. */
+ for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++)
+ {
+ regstart[mcnt] = regend[mcnt]
+ = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE;
+
+ REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE;
+ IS_ACTIVE (reg_info[mcnt]) = 0;
+ MATCHED_SOMETHING (reg_info[mcnt]) = 0;
+ EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0;
+ }
+
+ /* We move `string1' into `string2' if the latter's empty -- but not if
+ `string1' is null. */
+ if (size2 == 0 && string1 != NULL)
+ {
+ string2 = string1;
+ size2 = size1;
+ string1 = 0;
+ size1 = 0;
+ }
+ end1 = string1 + size1;
+ end2 = string2 + size2;
+
+ /* Compute where to stop matching, within the two strings. */
+ if (stop <= size1)
+ {
+ end_match_1 = string1 + stop;
+ end_match_2 = string2;
+ }
+ else
+ {
+ end_match_1 = end1;
+ end_match_2 = string2 + stop - size1;
+ }
+
+ /* `p' scans through the pattern as `d' scans through the data.
+ `dend' is the end of the input string that `d' points within. `d'
+ is advanced into the following input string whenever necessary, but
+ this happens before fetching; therefore, at the beginning of the
+ loop, `d' can be pointing at the end of a string, but it cannot
+ equal `string2'. */
+ if (size1 > 0 && pos <= size1)
+ {
+ d = string1 + pos;
+ dend = end_match_1;
+ }
+ else
+ {
+ d = string2 + pos - size1;
+ dend = end_match_2;
+ }
+
+ DEBUG_PRINT1 ("The compiled pattern is:\n");
+ DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend);
+ DEBUG_PRINT1 ("The string to match is: `");
+ DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2);
+ DEBUG_PRINT1 ("'\n");
+
+ /* This loops over pattern commands. It exits by returning from the
+ function if the match is complete, or it drops through if the match
+ fails at this starting point in the input data. */
+ for (;;)
+ {
+#ifdef _LIBC
+ DEBUG_PRINT2 ("\n%p: ", p);
+#else
+ DEBUG_PRINT2 ("\n0x%x: ", p);
+#endif
+
+ if (p == pend)
+ { /* End of pattern means we might have succeeded. */
+ DEBUG_PRINT1 ("end of pattern ... ");
+
+ /* If we haven't matched the entire string, and we want the
+ longest match, try backtracking. */
+ if (d != end_match_2)
+ {
+ /* 1 if this match ends in the same string (string1 or string2)
+ as the best previous match. */
+ boolean same_str_p = (FIRST_STRING_P (match_end)
+ == MATCHING_IN_FIRST_STRING);
+ /* 1 if this match is the best seen so far. */
+ boolean best_match_p;
+
+ /* AIX compiler got confused when this was combined
+ with the previous declaration. */
+ if (same_str_p)
+ best_match_p = d > match_end;
+ else
+ best_match_p = !MATCHING_IN_FIRST_STRING;
+
+ DEBUG_PRINT1 ("backtracking.\n");
+
+ if (!FAIL_STACK_EMPTY ())
+ { /* More failure points to try. */
+
+ /* If exceeds best match so far, save it. */
+ if (!best_regs_set || best_match_p)
+ {
+ best_regs_set = true;
+ match_end = d;
+
+ DEBUG_PRINT1 ("\nSAVING match as best so far.\n");
+
+ for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++)
+ {
+ best_regstart[mcnt] = regstart[mcnt];
+ best_regend[mcnt] = regend[mcnt];
+ }
+ }
+ goto fail;
+ }
+
+ /* If no failure points, don't restore garbage. And if
+ last match is real best match, don't restore second
+ best one. */
+ else if (best_regs_set && !best_match_p)
+ {
+ restore_best_regs:
+ /* Restore best match. It may happen that `dend ==
+ end_match_1' while the restored d is in string2.
+ For example, the pattern `x.*y.*z' against the
+ strings `x-' and `y-z-', if the two strings are
+ not consecutive in memory. */
+ DEBUG_PRINT1 ("Restoring best registers.\n");
+
+ d = match_end;
+ dend = ((d >= string1 && d <= end1)
+ ? end_match_1 : end_match_2);
+
+ for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++)
+ {
+ regstart[mcnt] = best_regstart[mcnt];
+ regend[mcnt] = best_regend[mcnt];
+ }
+ }
+ } /* d != end_match_2 */
+
+ succeed_label:
+ DEBUG_PRINT1 ("Accepting match.\n");
+
+ /* If caller wants register contents data back, do it. */
+ if (regs && !bufp->no_sub)
+ {
+ /* Have the register data arrays been allocated? */
+ if (bufp->regs_allocated == REGS_UNALLOCATED)
+ { /* No. So allocate them with malloc. We need one
+ extra element beyond `num_regs' for the `-1' marker
+ GNU code uses. */
+ regs->num_regs = MAX (RE_NREGS, num_regs + 1);
+ regs->start = TALLOC (regs->num_regs, regoff_t);
+ regs->end = TALLOC (regs->num_regs, regoff_t);
+ if (regs->start == NULL || regs->end == NULL)
+ {
+ FREE_VARIABLES ();
+ return -2;
+ }
+ bufp->regs_allocated = REGS_REALLOCATE;
+ }
+ else if (bufp->regs_allocated == REGS_REALLOCATE)
+ { /* Yes. If we need more elements than were already
+ allocated, reallocate them. If we need fewer, just
+ leave it alone. */
+ if (regs->num_regs < num_regs + 1)
+ {
+ regs->num_regs = num_regs + 1;
+ RETALLOC (regs->start, regs->num_regs, regoff_t);
+ RETALLOC (regs->end, regs->num_regs, regoff_t);
+ if (regs->start == NULL || regs->end == NULL)
+ {
+ FREE_VARIABLES ();
+ return -2;
+ }
+ }
+ }
+ else
+ {
+ /* These braces fend off a "empty body in an else-statement"
+ warning under GCC when assert expands to nothing. */
+ assert (bufp->regs_allocated == REGS_FIXED);
+ }
+
+ /* Convert the pointer data in `regstart' and `regend' to
+ indices. Register zero has to be set differently,
+ since we haven't kept track of any info for it. */
+ if (regs->num_regs > 0)
+ {
+ regs->start[0] = pos;
+ regs->end[0] = (MATCHING_IN_FIRST_STRING
+ ? ((regoff_t) (d - string1))
+ : ((regoff_t) (d - string2 + size1)));
+ }
+
+ /* Go through the first `min (num_regs, regs->num_regs)'
+ registers, since that is all we initialized. */
+ for (mcnt = 1; (unsigned) mcnt < MIN (num_regs, regs->num_regs);
+ mcnt++)
+ {
+ if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt]))
+ regs->start[mcnt] = regs->end[mcnt] = -1;
+ else
+ {
+ regs->start[mcnt]
+ = (regoff_t) POINTER_TO_OFFSET (regstart[mcnt]);
+ regs->end[mcnt]
+ = (regoff_t) POINTER_TO_OFFSET (regend[mcnt]);
+ }
+ }
+
+ /* If the regs structure we return has more elements than
+ were in the pattern, set the extra elements to -1. If
+ we (re)allocated the registers, this is the case,
+ because we always allocate enough to have at least one
+ -1 at the end. */
+ for (mcnt = num_regs; (unsigned) mcnt < regs->num_regs; mcnt++)
+ regs->start[mcnt] = regs->end[mcnt] = -1;
+ } /* regs && !bufp->no_sub */
+
+ DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n",
+ nfailure_points_pushed, nfailure_points_popped,
+ nfailure_points_pushed - nfailure_points_popped);
+ DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed);
+
+ mcnt = d - pos - (MATCHING_IN_FIRST_STRING
+ ? string1
+ : string2 - size1);
+
+ DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt);
+
+ FREE_VARIABLES ();
+ return mcnt;
+ }
+
+ /* Otherwise match next pattern command. */
+ switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++))
+ {
+ /* Ignore these. Used to ignore the n of succeed_n's which
+ currently have n == 0. */
+ case no_op:
+ DEBUG_PRINT1 ("EXECUTING no_op.\n");
+ break;
+
+ case succeed:
+ DEBUG_PRINT1 ("EXECUTING succeed.\n");
+ goto succeed_label;
+
+ /* Match the next n pattern characters exactly. The following
+ byte in the pattern defines n, and the n bytes after that
+ are the characters to match. */
+ case exactn:
+ mcnt = *p++;
+ DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt);
+
+ /* This is written out as an if-else so we don't waste time
+ testing `translate' inside the loop. */
+ if (translate)
+ {
+ do
+ {
+ PREFETCH ();
+ if ((unsigned char) translate[(unsigned char) *d++]
+ != (unsigned char) *p++)
+ goto fail;
+ }
+ while (--mcnt);
+ }
+ else
+ {
+ do
+ {
+ PREFETCH ();
+ if (*d++ != (char) *p++) goto fail;
+ }
+ while (--mcnt);
+ }
+ SET_REGS_MATCHED ();
+ break;
+
+
+ /* Match any character except possibly a newline or a null. */
+ case anychar:
+ DEBUG_PRINT1 ("EXECUTING anychar.\n");
+
+ PREFETCH ();
+
+ if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n')
+ || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000'))
+ goto fail;
+
+ SET_REGS_MATCHED ();
+ DEBUG_PRINT2 (" Matched `%d'.\n", *d);
+ d++;
+ break;
+
+
+ case charset:
+ case charset_not:
+ {
+ register unsigned char c;
+ boolean not = (re_opcode_t) *(p - 1) == charset_not;
+
+ DEBUG_PRINT2 ("EXECUTING charset%s.\n", not ? "_not" : "");
+
+ PREFETCH ();
+ c = TRANSLATE (*d); /* The character to match. */
+
+ /* Cast to `unsigned' instead of `unsigned char' in case the
+ bit list is a full 32 bytes long. */
+ if (c < (unsigned) (*p * BYTEWIDTH)
+ && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
+ not = !not;
+
+ p += 1 + *p;
+
+ if (!not) goto fail;
+
+ SET_REGS_MATCHED ();
+ d++;
+ break;
+ }
+
+
+ /* The beginning of a group is represented by start_memory.
+ The arguments are the register number in the next byte, and the
+ number of groups inner to this one in the next. The text
+ matched within the group is recorded (in the internal
+ registers data structure) under the register number. */
+ case start_memory:
+ DEBUG_PRINT3 ("EXECUTING start_memory %d (%d):\n", *p, p[1]);
+
+ /* Find out if this group can match the empty string. */
+ p1 = p; /* To send to group_match_null_string_p. */
+
+ if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE)
+ REG_MATCH_NULL_STRING_P (reg_info[*p])
+ = group_match_null_string_p (&p1, pend, reg_info);
+
+ /* Save the position in the string where we were the last time
+ we were at this open-group operator in case the group is
+ operated upon by a repetition operator, e.g., with `(a*)*b'
+ against `ab'; then we want to ignore where we are now in
+ the string in case this attempt to match fails. */
+ old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
+ ? REG_UNSET (regstart[*p]) ? d : regstart[*p]
+ : regstart[*p];
+ DEBUG_PRINT2 (" old_regstart: %d\n",
+ POINTER_TO_OFFSET (old_regstart[*p]));
+
+ regstart[*p] = d;
+ DEBUG_PRINT2 (" regstart: %d\n", POINTER_TO_OFFSET (regstart[*p]));
+
+ IS_ACTIVE (reg_info[*p]) = 1;
+ MATCHED_SOMETHING (reg_info[*p]) = 0;
+
+ /* Clear this whenever we change the register activity status. */
+ set_regs_matched_done = 0;
+
+ /* This is the new highest active register. */
+ highest_active_reg = *p;
+
+ /* If nothing was active before, this is the new lowest active
+ register. */
+ if (lowest_active_reg == NO_LOWEST_ACTIVE_REG)
+ lowest_active_reg = *p;
+
+ /* Move past the register number and inner group count. */
+ p += 2;
+ just_past_start_mem = p;
+
+ break;
+
+
+ /* The stop_memory opcode represents the end of a group. Its
+ arguments are the same as start_memory's: the register
+ number, and the number of inner groups. */
+ case stop_memory:
+ DEBUG_PRINT3 ("EXECUTING stop_memory %d (%d):\n", *p, p[1]);
+
+ /* We need to save the string position the last time we were at
+ this close-group operator in case the group is operated
+ upon by a repetition operator, e.g., with `((a*)*(b*)*)*'
+ against `aba'; then we want to ignore where we are now in
+ the string in case this attempt to match fails. */
+ old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
+ ? REG_UNSET (regend[*p]) ? d : regend[*p]
+ : regend[*p];
+ DEBUG_PRINT2 (" old_regend: %d\n",
+ POINTER_TO_OFFSET (old_regend[*p]));
+
+ regend[*p] = d;
+ DEBUG_PRINT2 (" regend: %d\n", POINTER_TO_OFFSET (regend[*p]));
+
+ /* This register isn't active anymore. */
+ IS_ACTIVE (reg_info[*p]) = 0;
+
+ /* Clear this whenever we change the register activity status. */
+ set_regs_matched_done = 0;
+
+ /* If this was the only register active, nothing is active
+ anymore. */
+ if (lowest_active_reg == highest_active_reg)
+ {
+ lowest_active_reg = NO_LOWEST_ACTIVE_REG;
+ highest_active_reg = NO_HIGHEST_ACTIVE_REG;
+ }
+ else
+ { /* We must scan for the new highest active register, since
+ it isn't necessarily one less than now: consider
+ (a(b)c(d(e)f)g). When group 3 ends, after the f), the
+ new highest active register is 1. */
+ unsigned char r = *p - 1;
+ while (r > 0 && !IS_ACTIVE (reg_info[r]))
+ r--;
+
+ /* If we end up at register zero, that means that we saved
+ the registers as the result of an `on_failure_jump', not
+ a `start_memory', and we jumped to past the innermost
+ `stop_memory'. For example, in ((.)*) we save
+ registers 1 and 2 as a result of the *, but when we pop
+ back to the second ), we are at the stop_memory 1.
+ Thus, nothing is active. */
+ if (r == 0)
+ {
+ lowest_active_reg = NO_LOWEST_ACTIVE_REG;
+ highest_active_reg = NO_HIGHEST_ACTIVE_REG;
+ }
+ else
+ highest_active_reg = r;
+ }
+
+ /* If just failed to match something this time around with a
+ group that's operated on by a repetition operator, try to
+ force exit from the ``loop'', and restore the register
+ information for this group that we had before trying this
+ last match. */
+ if ((!MATCHED_SOMETHING (reg_info[*p])
+ || just_past_start_mem == p - 1)
+ && (p + 2) < pend)
+ {
+ boolean is_a_jump_n = false;
+
+ p1 = p + 2;
+ mcnt = 0;
+ switch ((re_opcode_t) *p1++)
+ {
+ case jump_n:
+ is_a_jump_n = true;
+ case pop_failure_jump:
+ case maybe_pop_jump:
+ case jump:
+ case dummy_failure_jump:
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+ if (is_a_jump_n)
+ p1 += 2;
+ break;
+
+ default:
+ /* do nothing */ ;
+ }
+ p1 += mcnt;
+
+ /* If the next operation is a jump backwards in the pattern
+ to an on_failure_jump right before the start_memory
+ corresponding to this stop_memory, exit from the loop
+ by forcing a failure after pushing on the stack the
+ on_failure_jump's jump in the pattern, and d. */
+ if (mcnt < 0 && (re_opcode_t) *p1 == on_failure_jump
+ && (re_opcode_t) p1[3] == start_memory && p1[4] == *p)
+ {
+ /* If this group ever matched anything, then restore
+ what its registers were before trying this last
+ failed match, e.g., with `(a*)*b' against `ab' for
+ regstart[1], and, e.g., with `((a*)*(b*)*)*'
+ against `aba' for regend[3].
+
+ Also restore the registers for inner groups for,
+ e.g., `((a*)(b*))*' against `aba' (register 3 would
+ otherwise get trashed). */
+
+ if (EVER_MATCHED_SOMETHING (reg_info[*p]))
+ {
+ unsigned r;
+
+ EVER_MATCHED_SOMETHING (reg_info[*p]) = 0;
+
+ /* Restore this and inner groups' (if any) registers. */
+ for (r = *p; r < (unsigned) *p + (unsigned) *(p + 1);
+ r++)
+ {
+ regstart[r] = old_regstart[r];
+
+ /* xx why this test? */
+ if (old_regend[r] >= regstart[r])
+ regend[r] = old_regend[r];
+ }
+ }
+ p1++;
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+ PUSH_FAILURE_POINT (p1 + mcnt, d, -2);
+
+ goto fail;
+ }
+ }
+
+ /* Move past the register number and the inner group count. */
+ p += 2;
+ break;
+
+
+ /* \<digit> has been turned into a `duplicate' command which is
+ followed by the numeric value of <digit> as the register number. */
+ case duplicate:
+ {
+ register const char *d2, *dend2;
+ int regno = *p++; /* Get which register to match against. */
+ DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno);
+
+ /* Can't back reference a group which we've never matched. */
+ if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno]))
+ goto fail;
+
+ /* Where in input to try to start matching. */
+ d2 = regstart[regno];
+
+ /* Where to stop matching; if both the place to start and
+ the place to stop matching are in the same string, then
+ set to the place to stop, otherwise, for now have to use
+ the end of the first string. */
+
+ dend2 = ((FIRST_STRING_P (regstart[regno])
+ == FIRST_STRING_P (regend[regno]))
+ ? regend[regno] : end_match_1);
+ for (;;)
+ {
+ /* If necessary, advance to next segment in register
+ contents. */
+ while (d2 == dend2)
+ {
+ if (dend2 == end_match_2) break;
+ if (dend2 == regend[regno]) break;
+
+ /* End of string1 => advance to string2. */
+ d2 = string2;
+ dend2 = regend[regno];
+ }
+ /* At end of register contents => success */
+ if (d2 == dend2) break;
+
+ /* If necessary, advance to next segment in data. */
+ PREFETCH ();
+
+ /* How many characters left in this segment to match. */
+ mcnt = dend - d;
+
+ /* Want how many consecutive characters we can match in
+ one shot, so, if necessary, adjust the count. */
+ if (mcnt > dend2 - d2)
+ mcnt = dend2 - d2;
+
+ /* Compare that many; failure if mismatch, else move
+ past them. */
+ if (translate
+ ? bcmp_translate (d, d2, mcnt, translate)
+ : memcmp (d, d2, mcnt))
+ goto fail;
+ d += mcnt, d2 += mcnt;
+
+ /* Do this because we've match some characters. */
+ SET_REGS_MATCHED ();
+ }
+ }
+ break;
+
+
+ /* begline matches the empty string at the beginning of the string
+ (unless `not_bol' is set in `bufp'), and, if
+ `newline_anchor' is set, after newlines. */
+ case begline:
+ DEBUG_PRINT1 ("EXECUTING begline.\n");
+
+ if (AT_STRINGS_BEG (d))
+ {
+ if (!bufp->not_bol) break;
+ }
+ else if (d[-1] == '\n' && bufp->newline_anchor)
+ {
+ break;
+ }
+ /* In all other cases, we fail. */
+ goto fail;
+
+
+ /* endline is the dual of begline. */
+ case endline:
+ DEBUG_PRINT1 ("EXECUTING endline.\n");
+
+ if (AT_STRINGS_END (d))
+ {
+ if (!bufp->not_eol) break;
+ }
+
+ /* We have to ``prefetch'' the next character. */
+ else if ((d == end1 ? *string2 : *d) == '\n'
+ && bufp->newline_anchor)
+ {
+ break;
+ }
+ goto fail;
+
+
+ /* Match at the very beginning of the data. */
+ case begbuf:
+ DEBUG_PRINT1 ("EXECUTING begbuf.\n");
+ if (AT_STRINGS_BEG (d))
+ break;
+ goto fail;
+
+
+ /* Match at the very end of the data. */
+ case endbuf:
+ DEBUG_PRINT1 ("EXECUTING endbuf.\n");
+ if (AT_STRINGS_END (d))
+ break;
+ goto fail;
+
+
+ /* on_failure_keep_string_jump is used to optimize `.*\n'. It
+ pushes NULL as the value for the string on the stack. Then
+ `pop_failure_point' will keep the current value for the
+ string, instead of restoring it. To see why, consider
+ matching `foo\nbar' against `.*\n'. The .* matches the foo;
+ then the . fails against the \n. But the next thing we want
+ to do is match the \n against the \n; if we restored the
+ string value, we would be back at the foo.
+
+ Because this is used only in specific cases, we don't need to
+ check all the things that `on_failure_jump' does, to make
+ sure the right things get saved on the stack. Hence we don't
+ share its code. The only reason to push anything on the
+ stack at all is that otherwise we would have to change
+ `anychar's code to do something besides goto fail in this
+ case; that seems worse than this. */
+ case on_failure_keep_string_jump:
+ DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump");
+
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+#ifdef _LIBC
+ DEBUG_PRINT3 (" %d (to %p):\n", mcnt, p + mcnt);
+#else
+ DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt);
+#endif
+
+ PUSH_FAILURE_POINT (p + mcnt, NULL, -2);
+ break;
+
+
+ /* Uses of on_failure_jump:
+
+ Each alternative starts with an on_failure_jump that points
+ to the beginning of the next alternative. Each alternative
+ except the last ends with a jump that in effect jumps past
+ the rest of the alternatives. (They really jump to the
+ ending jump of the following alternative, because tensioning
+ these jumps is a hassle.)
+
+ Repeats start with an on_failure_jump that points past both
+ the repetition text and either the following jump or
+ pop_failure_jump back to this on_failure_jump. */
+ case on_failure_jump:
+ on_failure:
+ DEBUG_PRINT1 ("EXECUTING on_failure_jump");
+
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+#ifdef _LIBC
+ DEBUG_PRINT3 (" %d (to %p)", mcnt, p + mcnt);
+#else
+ DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt);
+#endif
+
+ /* If this on_failure_jump comes right before a group (i.e.,
+ the original * applied to a group), save the information
+ for that group and all inner ones, so that if we fail back
+ to this point, the group's information will be correct.
+ For example, in \(a*\)*\1, we need the preceding group,
+ and in \(zz\(a*\)b*\)\2, we need the inner group. */
+
+ /* We can't use `p' to check ahead because we push
+ a failure point to `p + mcnt' after we do this. */
+ p1 = p;
+
+ /* We need to skip no_op's before we look for the
+ start_memory in case this on_failure_jump is happening as
+ the result of a completed succeed_n, as in \(a\)\{1,3\}b\1
+ against aba. */
+ while (p1 < pend && (re_opcode_t) *p1 == no_op)
+ p1++;
+
+ if (p1 < pend && (re_opcode_t) *p1 == start_memory)
+ {
+ /* We have a new highest active register now. This will
+ get reset at the start_memory we are about to get to,
+ but we will have saved all the registers relevant to
+ this repetition op, as described above. */
+ highest_active_reg = *(p1 + 1) + *(p1 + 2);
+ if (lowest_active_reg == NO_LOWEST_ACTIVE_REG)
+ lowest_active_reg = *(p1 + 1);
+ }
+
+ DEBUG_PRINT1 (":\n");
+ PUSH_FAILURE_POINT (p + mcnt, d, -2);
+ break;
+
+
+ /* A smart repeat ends with `maybe_pop_jump'.
+ We change it to either `pop_failure_jump' or `jump'. */
+ case maybe_pop_jump:
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+ DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt);
+ {
+ register unsigned char *p2 = p;
+
+ /* Compare the beginning of the repeat with what in the
+ pattern follows its end. If we can establish that there
+ is nothing that they would both match, i.e., that we
+ would have to backtrack because of (as in, e.g., `a*a')
+ then we can change to pop_failure_jump, because we'll
+ never have to backtrack.
+
+ This is not true in the case of alternatives: in
+ `(a|ab)*' we do need to backtrack to the `ab' alternative
+ (e.g., if the string was `ab'). But instead of trying to
+ detect that here, the alternative has put on a dummy
+ failure point which is what we will end up popping. */
+
+ /* Skip over open/close-group commands.
+ If what follows this loop is a ...+ construct,
+ look at what begins its body, since we will have to
+ match at least one of that. */
+ while (1)
+ {
+ if (p2 + 2 < pend
+ && ((re_opcode_t) *p2 == stop_memory
+ || (re_opcode_t) *p2 == start_memory))
+ p2 += 3;
+ else if (p2 + 6 < pend
+ && (re_opcode_t) *p2 == dummy_failure_jump)
+ p2 += 6;
+ else
+ break;
+ }
+
+ p1 = p + mcnt;
+ /* p1[0] ... p1[2] are the `on_failure_jump' corresponding
+ to the `maybe_finalize_jump' of this case. Examine what
+ follows. */
+
+ /* If we're at the end of the pattern, we can change. */
+ if (p2 == pend)
+ {
+ /* Consider what happens when matching ":\(.*\)"
+ against ":/". I don't really understand this code
+ yet. */
+ p[-3] = (unsigned char) pop_failure_jump;
+ DEBUG_PRINT1
+ (" End of pattern: change to `pop_failure_jump'.\n");
+ }
+
+ else if ((re_opcode_t) *p2 == exactn
+ || (bufp->newline_anchor && (re_opcode_t) *p2 == endline))
+ {
+ register unsigned char c
+ = *p2 == (unsigned char) endline ? '\n' : p2[2];
+
+ if ((re_opcode_t) p1[3] == exactn && p1[5] != c)
+ {
+ p[-3] = (unsigned char) pop_failure_jump;
+ DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n",
+ c, p1[5]);
+ }
+
+ else if ((re_opcode_t) p1[3] == charset
+ || (re_opcode_t) p1[3] == charset_not)
+ {
+ int not = (re_opcode_t) p1[3] == charset_not;
+
+ if (c < (unsigned char) (p1[4] * BYTEWIDTH)
+ && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
+ not = !not;
+
+ /* `not' is equal to 1 if c would match, which means
+ that we can't change to pop_failure_jump. */
+ if (!not)
+ {
+ p[-3] = (unsigned char) pop_failure_jump;
+ DEBUG_PRINT1 (" No match => pop_failure_jump.\n");
+ }
+ }
+ }
+ else if ((re_opcode_t) *p2 == charset)
+ {
+#ifdef DEBUG
+ register unsigned char c
+ = *p2 == (unsigned char) endline ? '\n' : p2[2];
+#endif
+
+#if 0
+ if ((re_opcode_t) p1[3] == exactn
+ && ! ((int) p2[1] * BYTEWIDTH > (int) p1[5]
+ && (p2[2 + p1[5] / BYTEWIDTH]
+ & (1 << (p1[5] % BYTEWIDTH)))))
+#else
+ if ((re_opcode_t) p1[3] == exactn
+ && ! ((int) p2[1] * BYTEWIDTH > (int) p1[4]
+ && (p2[2 + p1[4] / BYTEWIDTH]
+ & (1 << (p1[4] % BYTEWIDTH)))))
+#endif
+ {
+ p[-3] = (unsigned char) pop_failure_jump;
+ DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n",
+ c, p1[5]);
+ }
+
+ else if ((re_opcode_t) p1[3] == charset_not)
+ {
+ int idx;
+ /* We win if the charset_not inside the loop
+ lists every character listed in the charset after. */
+ for (idx = 0; idx < (int) p2[1]; idx++)
+ if (! (p2[2 + idx] == 0
+ || (idx < (int) p1[4]
+ && ((p2[2 + idx] & ~ p1[5 + idx]) == 0))))
+ break;
+
+ if (idx == p2[1])
+ {
+ p[-3] = (unsigned char) pop_failure_jump;
+ DEBUG_PRINT1 (" No match => pop_failure_jump.\n");
+ }
+ }
+ else if ((re_opcode_t) p1[3] == charset)
+ {
+ int idx;
+ /* We win if the charset inside the loop
+ has no overlap with the one after the loop. */
+ for (idx = 0;
+ idx < (int) p2[1] && idx < (int) p1[4];
+ idx++)
+ if ((p2[2 + idx] & p1[5 + idx]) != 0)
+ break;
+
+ if (idx == p2[1] || idx == p1[4])
+ {
+ p[-3] = (unsigned char) pop_failure_jump;
+ DEBUG_PRINT1 (" No match => pop_failure_jump.\n");
+ }
+ }
+ }
+ }
+ p -= 2; /* Point at relative address again. */
+ if ((re_opcode_t) p[-1] != pop_failure_jump)
+ {
+ p[-1] = (unsigned char) jump;
+ DEBUG_PRINT1 (" Match => jump.\n");
+ goto unconditional_jump;
+ }
+ /* Note fall through. */
+
+
+ /* The end of a simple repeat has a pop_failure_jump back to
+ its matching on_failure_jump, where the latter will push a
+ failure point. The pop_failure_jump takes off failure
+ points put on by this pop_failure_jump's matching
+ on_failure_jump; we got through the pattern to here from the
+ matching on_failure_jump, so didn't fail. */
+ case pop_failure_jump:
+ {
+ /* We need to pass separate storage for the lowest and
+ highest registers, even though we don't care about the
+ actual values. Otherwise, we will restore only one
+ register from the stack, since lowest will == highest in
+ `pop_failure_point'. */
+ active_reg_t dummy_low_reg, dummy_high_reg;
+ unsigned char *pdummy;
+ const char *sdummy;
+
+ DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n");
+ POP_FAILURE_POINT (sdummy, pdummy,
+ dummy_low_reg, dummy_high_reg,
+ reg_dummy, reg_dummy, reg_info_dummy);
+ }
+ /* Note fall through. */
+
+ unconditional_jump:
+#ifdef _LIBC
+ DEBUG_PRINT2 ("\n%p: ", p);
+#else
+ DEBUG_PRINT2 ("\n0x%x: ", p);
+#endif
+ /* Note fall through. */
+
+ /* Unconditionally jump (without popping any failure points). */
+ case jump:
+ EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */
+ DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt);
+ p += mcnt; /* Do the jump. */
+#ifdef _LIBC
+ DEBUG_PRINT2 ("(to %p).\n", p);
+#else
+ DEBUG_PRINT2 ("(to 0x%x).\n", p);
+#endif
+ break;
+
+
+ /* We need this opcode so we can detect where alternatives end
+ in `group_match_null_string_p' et al. */
+ case jump_past_alt:
+ DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n");
+ goto unconditional_jump;
+
+
+ /* Normally, the on_failure_jump pushes a failure point, which
+ then gets popped at pop_failure_jump. We will end up at
+ pop_failure_jump, also, and with a pattern of, say, `a+', we
+ are skipping over the on_failure_jump, so we have to push
+ something meaningless for pop_failure_jump to pop. */
+ case dummy_failure_jump:
+ DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n");
+ /* It doesn't matter what we push for the string here. What
+ the code at `fail' tests is the value for the pattern. */
+ PUSH_FAILURE_POINT (NULL, NULL, -2);
+ goto unconditional_jump;
+
+
+ /* At the end of an alternative, we need to push a dummy failure
+ point in case we are followed by a `pop_failure_jump', because
+ we don't want the failure point for the alternative to be
+ popped. For example, matching `(a|ab)*' against `aab'
+ requires that we match the `ab' alternative. */
+ case push_dummy_failure:
+ DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n");
+ /* See comments just above at `dummy_failure_jump' about the
+ two zeroes. */
+ PUSH_FAILURE_POINT (NULL, NULL, -2);
+ break;
+
+ /* Have to succeed matching what follows at least n times.
+ After that, handle like `on_failure_jump'. */
+ case succeed_n:
+ EXTRACT_NUMBER (mcnt, p + 2);
+ DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt);
+
+ assert (mcnt >= 0);
+ /* Originally, this is how many times we HAVE to succeed. */
+ if (mcnt > 0)
+ {
+ mcnt--;
+ p += 2;
+ STORE_NUMBER_AND_INCR (p, mcnt);
+#ifdef _LIBC
+ DEBUG_PRINT3 (" Setting %p to %d.\n", p - 2, mcnt);
+#else
+ DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p - 2, mcnt);
+#endif
+ }
+ else if (mcnt == 0)
+ {
+#ifdef _LIBC
+ DEBUG_PRINT2 (" Setting two bytes from %p to no_op.\n", p+2);
+#else
+ DEBUG_PRINT2 (" Setting two bytes from 0x%x to no_op.\n", p+2);
+#endif
+ p[2] = (unsigned char) no_op;
+ p[3] = (unsigned char) no_op;
+ goto on_failure;
+ }
+ break;
+
+ case jump_n:
+ EXTRACT_NUMBER (mcnt, p + 2);
+ DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt);
+
+ /* Originally, this is how many times we CAN jump. */
+ if (mcnt)
+ {
+ mcnt--;
+ STORE_NUMBER (p + 2, mcnt);
+#ifdef _LIBC
+ DEBUG_PRINT3 (" Setting %p to %d.\n", p + 2, mcnt);
+#else
+ DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p + 2, mcnt);
+#endif
+ goto unconditional_jump;
+ }
+ /* If don't have to jump any more, skip over the rest of command. */
+ else
+ p += 4;
+ break;
+
+ case set_number_at:
+ {
+ DEBUG_PRINT1 ("EXECUTING set_number_at.\n");
+
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+ p1 = p + mcnt;
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+#ifdef _LIBC
+ DEBUG_PRINT3 (" Setting %p to %d.\n", p1, mcnt);
+#else
+ DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p1, mcnt);
+#endif
+ STORE_NUMBER (p1, mcnt);
+ break;
+ }
+
+#if 0
+ /* The DEC Alpha C compiler 3.x generates incorrect code for the
+ test WORDCHAR_P (d - 1) != WORDCHAR_P (d) in the expansion of
+ AT_WORD_BOUNDARY, so this code is disabled. Expanding the
+ macro and introducing temporary variables works around the bug. */
+
+ case wordbound:
+ DEBUG_PRINT1 ("EXECUTING wordbound.\n");
+ if (AT_WORD_BOUNDARY (d))
+ break;
+ goto fail;
+
+ case notwordbound:
+ DEBUG_PRINT1 ("EXECUTING notwordbound.\n");
+ if (AT_WORD_BOUNDARY (d))
+ goto fail;
+ break;
+#else
+ case wordbound:
+ {
+ boolean prevchar, thischar;
+
+ DEBUG_PRINT1 ("EXECUTING wordbound.\n");
+ if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d))
+ break;
+
+ prevchar = WORDCHAR_P (d - 1);
+ thischar = WORDCHAR_P (d);
+ if (prevchar != thischar)
+ break;
+ goto fail;
+ }
+
+ case notwordbound:
+ {
+ boolean prevchar, thischar;
+
+ DEBUG_PRINT1 ("EXECUTING notwordbound.\n");
+ if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d))
+ goto fail;
+
+ prevchar = WORDCHAR_P (d - 1);
+ thischar = WORDCHAR_P (d);
+ if (prevchar != thischar)
+ goto fail;
+ break;
+ }
+#endif
+
+ case wordbeg:
+ DEBUG_PRINT1 ("EXECUTING wordbeg.\n");
+ if (WORDCHAR_P (d) && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1)))
+ break;
+ goto fail;
+
+ case wordend:
+ DEBUG_PRINT1 ("EXECUTING wordend.\n");
+ if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1)
+ && (!WORDCHAR_P (d) || AT_STRINGS_END (d)))
+ break;
+ goto fail;
+
+#ifdef emacs
+ case before_dot:
+ DEBUG_PRINT1 ("EXECUTING before_dot.\n");
+ if (PTR_CHAR_POS ((unsigned char *) d) >= point)
+ goto fail;
+ break;
+
+ case at_dot:
+ DEBUG_PRINT1 ("EXECUTING at_dot.\n");
+ if (PTR_CHAR_POS ((unsigned char *) d) != point)
+ goto fail;
+ break;
+
+ case after_dot:
+ DEBUG_PRINT1 ("EXECUTING after_dot.\n");
+ if (PTR_CHAR_POS ((unsigned char *) d) <= point)
+ goto fail;
+ break;
+
+ case syntaxspec:
+ DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt);
+ mcnt = *p++;
+ goto matchsyntax;
+
+ case wordchar:
+ DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n");
+ mcnt = (int) Sword;
+ matchsyntax:
+ PREFETCH ();
+ /* Can't use *d++ here; SYNTAX may be an unsafe macro. */
+ d++;
+ if (SYNTAX (d[-1]) != (enum syntaxcode) mcnt)
+ goto fail;
+ SET_REGS_MATCHED ();
+ break;
+
+ case notsyntaxspec:
+ DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt);
+ mcnt = *p++;
+ goto matchnotsyntax;
+
+ case notwordchar:
+ DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n");
+ mcnt = (int) Sword;
+ matchnotsyntax:
+ PREFETCH ();
+ /* Can't use *d++ here; SYNTAX may be an unsafe macro. */
+ d++;
+ if (SYNTAX (d[-1]) == (enum syntaxcode) mcnt)
+ goto fail;
+ SET_REGS_MATCHED ();
+ break;
+
+#else /* not emacs */
+ case wordchar:
+ DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n");
+ PREFETCH ();
+ if (!WORDCHAR_P (d))
+ goto fail;
+ SET_REGS_MATCHED ();
+ d++;
+ break;
+
+ case notwordchar:
+ DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n");
+ PREFETCH ();
+ if (WORDCHAR_P (d))
+ goto fail;
+ SET_REGS_MATCHED ();
+ d++;
+ break;
+#endif /* not emacs */
+
+ default:
+ abort ();
+ }
+ continue; /* Successfully executed one pattern command; keep going. */
+
+
+ /* We goto here if a matching operation fails. */
+ fail:
+ if (!FAIL_STACK_EMPTY ())
+ { /* A restart point is known. Restore to that state. */
+ DEBUG_PRINT1 ("\nFAIL:\n");
+ POP_FAILURE_POINT (d, p,
+ lowest_active_reg, highest_active_reg,
+ regstart, regend, reg_info);
+
+ /* If this failure point is a dummy, try the next one. */
+ if (!p)
+ goto fail;
+
+ /* If we failed to the end of the pattern, don't examine *p. */
+ assert (p <= pend);
+ if (p < pend)
+ {
+ boolean is_a_jump_n = false;
+
+ /* If failed to a backwards jump that's part of a repetition
+ loop, need to pop this failure point and use the next one. */
+ switch ((re_opcode_t) *p)
+ {
+ case jump_n:
+ is_a_jump_n = true;
+ case maybe_pop_jump:
+ case pop_failure_jump:
+ case jump:
+ p1 = p + 1;
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+ p1 += mcnt;
+
+ if ((is_a_jump_n && (re_opcode_t) *p1 == succeed_n)
+ || (!is_a_jump_n
+ && (re_opcode_t) *p1 == on_failure_jump))
+ goto fail;
+ break;
+ default:
+ /* do nothing */ ;
+ }
+ }
+
+ if (d >= string1 && d <= end1)
+ dend = end_match_1;
+ }
+ else
+ break; /* Matching at this starting point really fails. */
+ } /* for (;;) */
+
+ if (best_regs_set)
+ goto restore_best_regs;
+
+ FREE_VARIABLES ();
+
+ return -1; /* Failure to match. */
+} /* re_match_2 */
+
+/* Subroutine definitions for re_match_2. */
+
+
+/* We are passed P pointing to a register number after a start_memory.
+
+ Return true if the pattern up to the corresponding stop_memory can
+ match the empty string, and false otherwise.
+
+ If we find the matching stop_memory, sets P to point to one past its number.
+ Otherwise, sets P to an undefined byte less than or equal to END.
+
+ We don't handle duplicates properly (yet). */
+
+static boolean
+group_match_null_string_p (p, end, reg_info)
+ unsigned char **p, *end;
+ register_info_type *reg_info;
+{
+ int mcnt;
+ /* Point to after the args to the start_memory. */
+ unsigned char *p1 = *p + 2;
+
+ while (p1 < end)
+ {
+ /* Skip over opcodes that can match nothing, and return true or
+ false, as appropriate, when we get to one that can't, or to the
+ matching stop_memory. */
+
+ switch ((re_opcode_t) *p1)
+ {
+ /* Could be either a loop or a series of alternatives. */
+ case on_failure_jump:
+ p1++;
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+
+ /* If the next operation is not a jump backwards in the
+ pattern. */
+
+ if (mcnt >= 0)
+ {
+ /* Go through the on_failure_jumps of the alternatives,
+ seeing if any of the alternatives cannot match nothing.
+ The last alternative starts with only a jump,
+ whereas the rest start with on_failure_jump and end
+ with a jump, e.g., here is the pattern for `a|b|c':
+
+ /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6
+ /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3
+ /exactn/1/c
+
+ So, we have to first go through the first (n-1)
+ alternatives and then deal with the last one separately. */
+
+
+ /* Deal with the first (n-1) alternatives, which start
+ with an on_failure_jump (see above) that jumps to right
+ past a jump_past_alt. */
+
+ while ((re_opcode_t) p1[mcnt-3] == jump_past_alt)
+ {
+ /* `mcnt' holds how many bytes long the alternative
+ is, including the ending `jump_past_alt' and
+ its number. */
+
+ if (!alt_match_null_string_p (p1, p1 + mcnt - 3,
+ reg_info))
+ return false;
+
+ /* Move to right after this alternative, including the
+ jump_past_alt. */
+ p1 += mcnt;
+
+ /* Break if it's the beginning of an n-th alternative
+ that doesn't begin with an on_failure_jump. */
+ if ((re_opcode_t) *p1 != on_failure_jump)
+ break;
+
+ /* Still have to check that it's not an n-th
+ alternative that starts with an on_failure_jump. */
+ p1++;
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+ if ((re_opcode_t) p1[mcnt-3] != jump_past_alt)
+ {
+ /* Get to the beginning of the n-th alternative. */
+ p1 -= 3;
+ break;
+ }
+ }
+
+ /* Deal with the last alternative: go back and get number
+ of the `jump_past_alt' just before it. `mcnt' contains
+ the length of the alternative. */
+ EXTRACT_NUMBER (mcnt, p1 - 2);
+
+ if (!alt_match_null_string_p (p1, p1 + mcnt, reg_info))
+ return false;
+
+ p1 += mcnt; /* Get past the n-th alternative. */
+ } /* if mcnt > 0 */
+ break;
+
+
+ case stop_memory:
+ assert (p1[1] == **p);
+ *p = p1 + 2;
+ return true;
+
+
+ default:
+ if (!common_op_match_null_string_p (&p1, end, reg_info))
+ return false;
+ }
+ } /* while p1 < end */
+
+ return false;
+} /* group_match_null_string_p */
+
+
+/* Similar to group_match_null_string_p, but doesn't deal with alternatives:
+ It expects P to be the first byte of a single alternative and END one
+ byte past the last. The alternative can contain groups. */
+
+static boolean
+alt_match_null_string_p (p, end, reg_info)
+ unsigned char *p, *end;
+ register_info_type *reg_info;
+{
+ int mcnt;
+ unsigned char *p1 = p;
+
+ while (p1 < end)
+ {
+ /* Skip over opcodes that can match nothing, and break when we get
+ to one that can't. */
+
+ switch ((re_opcode_t) *p1)
+ {
+ /* It's a loop. */
+ case on_failure_jump:
+ p1++;
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+ p1 += mcnt;
+ break;
+
+ default:
+ if (!common_op_match_null_string_p (&p1, end, reg_info))
+ return false;
+ }
+ } /* while p1 < end */
+
+ return true;
+} /* alt_match_null_string_p */
+
+
+/* Deals with the ops common to group_match_null_string_p and
+ alt_match_null_string_p.
+
+ Sets P to one after the op and its arguments, if any. */
+
+static boolean
+common_op_match_null_string_p (p, end, reg_info)
+ unsigned char **p, *end;
+ register_info_type *reg_info;
+{
+ int mcnt;
+ boolean ret;
+ int reg_no;
+ unsigned char *p1 = *p;
+
+ switch ((re_opcode_t) *p1++)
+ {
+ case no_op:
+ case begline:
+ case endline:
+ case begbuf:
+ case endbuf:
+ case wordbeg:
+ case wordend:
+ case wordbound:
+ case notwordbound:
+#ifdef emacs
+ case before_dot:
+ case at_dot:
+ case after_dot:
+#endif
+ break;
+
+ case start_memory:
+ reg_no = *p1;
+ assert (reg_no > 0 && reg_no <= MAX_REGNUM);
+ ret = group_match_null_string_p (&p1, end, reg_info);
+
+ /* Have to set this here in case we're checking a group which
+ contains a group and a back reference to it. */
+
+ if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE)
+ REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret;
+
+ if (!ret)
+ return false;
+ break;
+
+ /* If this is an optimized succeed_n for zero times, make the jump. */
+ case jump:
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+ if (mcnt >= 0)
+ p1 += mcnt;
+ else
+ return false;
+ break;
+
+ case succeed_n:
+ /* Get to the number of times to succeed. */
+ p1 += 2;
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+
+ if (mcnt == 0)
+ {
+ p1 -= 4;
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+ p1 += mcnt;
+ }
+ else
+ return false;
+ break;
+
+ case duplicate:
+ if (!REG_MATCH_NULL_STRING_P (reg_info[*p1]))
+ return false;
+ break;
+
+ case set_number_at:
+ p1 += 4;
+
+ default:
+ /* All other opcodes mean we cannot match the empty string. */
+ return false;
+ }
+
+ *p = p1;
+ return true;
+} /* common_op_match_null_string_p */
+
+
+/* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN
+ bytes; nonzero otherwise. */
+
+static int
+bcmp_translate (s1, s2, len, translate)
+ const char *s1, *s2;
+ register int len;
+ RE_TRANSLATE_TYPE translate;
+{
+ register const unsigned char *p1 = (const unsigned char *) s1;
+ register const unsigned char *p2 = (const unsigned char *) s2;
+ while (len)
+ {
+ if (translate[*p1++] != translate[*p2++]) return 1;
+ len--;
+ }
+ return 0;
+}
+
+/* Entry points for GNU code. */
+
+/* re_compile_pattern is the GNU regular expression compiler: it
+ compiles PATTERN (of length SIZE) and puts the result in BUFP.
+ Returns 0 if the pattern was valid, otherwise an error string.
+
+ Assumes the `allocated' (and perhaps `buffer') and `translate' fields
+ are set in BUFP on entry.
+
+ We call regex_compile to do the actual compilation. */
+
+const char *
+re_compile_pattern (pattern, length, bufp)
+ const char *pattern;
+ size_t length;
+ struct re_pattern_buffer *bufp;
+{
+ reg_errcode_t ret;
+
+ /* GNU code is written to assume at least RE_NREGS registers will be set
+ (and at least one extra will be -1). */
+ bufp->regs_allocated = REGS_UNALLOCATED;
+
+ /* And GNU code determines whether or not to get register information
+ by passing null for the REGS argument to re_match, etc., not by
+ setting no_sub. */
+ bufp->no_sub = 0;
+
+ /* Match anchors at newline. */
+ bufp->newline_anchor = 1;
+
+ ret = regex_compile (pattern, length, re_syntax_options, bufp);
+
+ if (!ret)
+ return NULL;
+ return gettext (re_error_msgid[(int) ret]);
+}
+#ifdef _LIBC
+weak_alias (__re_compile_pattern, re_compile_pattern)
+#endif
+
+/* Entry points compatible with 4.2 BSD regex library. We don't define
+ them unless specifically requested. */
+
+#if defined _REGEX_RE_COMP || defined _LIBC
+
+/* BSD has one and only one pattern buffer. */
+static struct re_pattern_buffer re_comp_buf;
+
+char *
+#ifdef _LIBC
+/* Make these definitions weak in libc, so POSIX programs can redefine
+ these names if they don't use our functions, and still use
+ regcomp/regexec below without link errors. */
+weak_function
+#endif
+re_comp (s)
+ const char *s;
+{
+ reg_errcode_t ret;
+
+ if (!s)
+ {
+ if (!re_comp_buf.buffer)
+ return gettext ("No previous regular expression");
+ return 0;
+ }
+
+ if (!re_comp_buf.buffer)
+ {
+ re_comp_buf.buffer = (unsigned char *) malloc (200);
+ if (re_comp_buf.buffer == NULL)
+ return (char *) gettext (re_error_msgid[(int) REG_ESPACE]);
+ re_comp_buf.allocated = 200;
+
+ re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH);
+ if (re_comp_buf.fastmap == NULL)
+ return (char *) gettext (re_error_msgid[(int) REG_ESPACE]);
+ }
+
+ /* Since `re_exec' always passes NULL for the `regs' argument, we
+ don't need to initialize the pattern buffer fields which affect it. */
+
+ /* Match anchors at newlines. */
+ re_comp_buf.newline_anchor = 1;
+
+ ret = regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf);
+
+ if (!ret)
+ return NULL;
+
+ /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */
+ return (char *) gettext (re_error_msgid[(int) ret]);
+}
+
+
+int
+#ifdef _LIBC
+weak_function
+#endif
+re_exec (s)
+ const char *s;
+{
+ const int len = strlen (s);
+ return
+ 0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0);
+}
+
+#endif /* _REGEX_RE_COMP */
+
+/* POSIX.2 functions. Don't define these for Emacs. */
+
+#ifndef emacs
+
+/* regcomp takes a regular expression as a string and compiles it.
+
+ PREG is a regex_t *. We do not expect any fields to be initialized,
+ since POSIX says we shouldn't. Thus, we set
+
+ `buffer' to the compiled pattern;
+ `used' to the length of the compiled pattern;
+ `syntax' to RE_SYNTAX_POSIX_EXTENDED if the
+ REG_EXTENDED bit in CFLAGS is set; otherwise, to
+ RE_SYNTAX_POSIX_BASIC;
+ `newline_anchor' to REG_NEWLINE being set in CFLAGS;
+ `fastmap' to an allocated space for the fastmap;
+ `fastmap_accurate' to zero;
+ `re_nsub' to the number of subexpressions in PATTERN.
+
+ PATTERN is the address of the pattern string.
+
+ CFLAGS is a series of bits which affect compilation.
+
+ If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we
+ use POSIX basic syntax.
+
+ If REG_NEWLINE is set, then . and [^...] don't match newline.
+ Also, regexec will try a match beginning after every newline.
+
+ If REG_ICASE is set, then we considers upper- and lowercase
+ versions of letters to be equivalent when matching.
+
+ If REG_NOSUB is set, then when PREG is passed to regexec, that
+ routine will report only success or failure, and nothing about the
+ registers.
+
+ It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for
+ the return codes and their meanings.) */
+
+int
+regcomp (preg, pattern, cflags)
+ regex_t *preg;
+ const char *pattern;
+ int cflags;
+{
+ reg_errcode_t ret;
+ reg_syntax_t syntax
+ = (cflags & REG_EXTENDED) ?
+ RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC;
+
+ /* regex_compile will allocate the space for the compiled pattern. */
+ preg->buffer = 0;
+ preg->allocated = 0;
+ preg->used = 0;
+
+ /* Try to allocate space for the fastmap. */
+ preg->fastmap = (char *) malloc (1 << BYTEWIDTH);
+
+ if (cflags & REG_ICASE)
+ {
+ unsigned i;
+
+ preg->translate
+ = (RE_TRANSLATE_TYPE) malloc (CHAR_SET_SIZE
+ * sizeof (*(RE_TRANSLATE_TYPE)0));
+ if (preg->translate == NULL)
+ return (int) REG_ESPACE;
+
+ /* Map uppercase characters to corresponding lowercase ones. */
+ for (i = 0; i < CHAR_SET_SIZE; i++)
+ preg->translate[i] = ISUPPER (i) ? TOLOWER (i) : i;
+ }
+ else
+ preg->translate = NULL;
+
+ /* If REG_NEWLINE is set, newlines are treated differently. */
+ if (cflags & REG_NEWLINE)
+ { /* REG_NEWLINE implies neither . nor [^...] match newline. */
+ syntax &= ~RE_DOT_NEWLINE;
+ syntax |= RE_HAT_LISTS_NOT_NEWLINE;
+ /* It also changes the matching behavior. */
+ preg->newline_anchor = 1;
+ }
+ else
+ preg->newline_anchor = 0;
+
+ preg->no_sub = !!(cflags & REG_NOSUB);
+
+ /* POSIX says a null character in the pattern terminates it, so we
+ can use strlen here in compiling the pattern. */
+ ret = regex_compile (pattern, strlen (pattern), syntax, preg);
+
+ /* POSIX doesn't distinguish between an unmatched open-group and an
+ unmatched close-group: both are REG_EPAREN. */
+ if (ret == REG_ERPAREN) ret = REG_EPAREN;
+
+ if (ret == REG_NOERROR && preg->fastmap)
+ {
+ /* Compute the fastmap now, since regexec cannot modify the pattern
+ buffer. */
+ if (re_compile_fastmap (preg) == -2)
+ {
+ /* Some error occured while computing the fastmap, just forget
+ about it. */
+ free (preg->fastmap);
+ preg->fastmap = NULL;
+ }
+ }
+
+ return (int) ret;
+}
+#ifdef _LIBC
+weak_alias (__regcomp, regcomp)
+#endif
+
+
+/* regexec searches for a given pattern, specified by PREG, in the
+ string STRING.
+
+ If NMATCH is zero or REG_NOSUB was set in the cflags argument to
+ `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at
+ least NMATCH elements, and we set them to the offsets of the
+ corresponding matched substrings.
+
+ EFLAGS specifies `execution flags' which affect matching: if
+ REG_NOTBOL is set, then ^ does not match at the beginning of the
+ string; if REG_NOTEOL is set, then $ does not match at the end.
+
+ We return 0 if we find a match and REG_NOMATCH if not. */
+
+int
+regexec (preg, string, nmatch, pmatch, eflags)
+ const regex_t *preg;
+ const char *string;
+ size_t nmatch;
+ regmatch_t pmatch[];
+ int eflags;
+{
+ int ret;
+ struct re_registers regs;
+ regex_t private_preg;
+ int len = strlen (string);
+ boolean want_reg_info = !preg->no_sub && nmatch > 0;
+
+ private_preg = *preg;
+
+ private_preg.not_bol = !!(eflags & REG_NOTBOL);
+ private_preg.not_eol = !!(eflags & REG_NOTEOL);
+
+ /* The user has told us exactly how many registers to return
+ information about, via `nmatch'. We have to pass that on to the
+ matching routines. */
+ private_preg.regs_allocated = REGS_FIXED;
+
+ if (want_reg_info)
+ {
+ regs.num_regs = nmatch;
+ regs.start = TALLOC (nmatch * 2, regoff_t);
+ if (regs.start == NULL)
+ return (int) REG_NOMATCH;
+ regs.end = regs.start + nmatch;
+ }
+
+ /* Perform the searching operation. */
+ ret = re_search (&private_preg, string, len,
+ /* start: */ 0, /* range: */ len,
+ want_reg_info ? &regs : (struct re_registers *) 0);
+
+ /* Copy the register information to the POSIX structure. */
+ if (want_reg_info)
+ {
+ if (ret >= 0)
+ {
+ unsigned r;
+
+ for (r = 0; r < nmatch; r++)
+ {
+ pmatch[r].rm_so = regs.start[r];
+ pmatch[r].rm_eo = regs.end[r];
+ }
+ }
+
+ /* If we needed the temporary register info, free the space now. */
+ free (regs.start);
+ }
+
+ /* We want zero return to mean success, unlike `re_search'. */
+ return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH;
+}
+#ifdef _LIBC
+weak_alias (__regexec, regexec)
+#endif
+
+
+/* Returns a message corresponding to an error code, ERRCODE, returned
+ from either regcomp or regexec. We don't use PREG here. */
+
+size_t
+regerror (errcode, preg, errbuf, errbuf_size)
+ int errcode;
+ const regex_t *preg;
+ char *errbuf;
+ size_t errbuf_size;
+{
+ const char *msg;
+ size_t msg_size;
+
+ if (errcode < 0
+ || errcode >= (int) (sizeof (re_error_msgid)
+ / sizeof (re_error_msgid[0])))
+ /* Only error codes returned by the rest of the code should be passed
+ to this routine. If we are given anything else, or if other regex
+ code generates an invalid error code, then the program has a bug.
+ Dump core so we can fix it. */
+ abort ();
+
+ msg = gettext (re_error_msgid[errcode]);
+
+ msg_size = strlen (msg) + 1; /* Includes the null. */
+
+ if (errbuf_size != 0)
+ {
+ if (msg_size > errbuf_size)
+ {
+#if defined HAVE_MEMPCPY || defined _LIBC
+ *((char *) __mempcpy (errbuf, msg, errbuf_size - 1)) = '\0';
+#else
+ memcpy (errbuf, msg, errbuf_size - 1);
+ errbuf[errbuf_size - 1] = 0;
+#endif
+ }
+ else
+ memcpy (errbuf, msg, msg_size);
+ }
+
+ return msg_size;
+}
+#ifdef _LIBC
+weak_alias (__regerror, regerror)
+#endif
+
+
+/* Free dynamically allocated space used by PREG. */
+
+void
+regfree (preg)
+ regex_t *preg;
+{
+ if (preg->buffer != NULL)
+ free (preg->buffer);
+ preg->buffer = NULL;
+
+ preg->allocated = 0;
+ preg->used = 0;
+
+ if (preg->fastmap != NULL)
+ free (preg->fastmap);
+ preg->fastmap = NULL;
+ preg->fastmap_accurate = 0;
+
+ if (preg->translate != NULL)
+ free (preg->translate);
+ preg->translate = NULL;
+}
+#ifdef _LIBC
+weak_alias (__regfree, regfree)
+#endif
+
+#endif /* not emacs */
diff --git a/src/regex.h b/src/regex.h
new file mode 100644
index 0000000..3e93c20
--- /dev/null
+++ b/src/regex.h
@@ -0,0 +1,542 @@
+/* Definitions for data structures and routines for the regular
+ expression library, version 0.12.
+ Copyright (C) 1985,89,90,91,92,93,95,96,97,98 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library. Its master source is NOT part of
+ the C library, however. The master source lives in /gd/gnu/lib.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 3 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef _REGEX_H
+#define _REGEX_H 1
+
+/* Allow the use in C++ code. */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* POSIX says that <sys/types.h> must be included (by the caller) before
+ <regex.h>. */
+
+#if !defined _POSIX_C_SOURCE && !defined _POSIX_SOURCE && defined VMS
+/* VMS doesn't have `size_t' in <sys/types.h>, even though POSIX says it
+ should be there. */
+# include <stddef.h>
+#endif
+
+/* The following two types have to be signed and unsigned integer type
+ wide enough to hold a value of a pointer. For most ANSI compilers
+ ptrdiff_t and size_t should be likely OK. Still size of these two
+ types is 2 for Microsoft C. Ugh... */
+typedef long int s_reg_t;
+typedef unsigned long int active_reg_t;
+
+/* The following bits are used to determine the regexp syntax we
+ recognize. The set/not-set meanings are chosen so that Emacs syntax
+ remains the value 0. The bits are given in alphabetical order, and
+ the definitions shifted by one from the previous bit; thus, when we
+ add or remove a bit, only one other definition need change. */
+typedef unsigned long int reg_syntax_t;
+
+/* If this bit is not set, then \ inside a bracket expression is literal.
+ If set, then such a \ quotes the following character. */
+#define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1)
+
+/* If this bit is not set, then + and ? are operators, and \+ and \? are
+ literals.
+ If set, then \+ and \? are operators and + and ? are literals. */
+#define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1)
+
+/* If this bit is set, then character classes are supported. They are:
+ [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:],
+ [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:].
+ If not set, then character classes are not supported. */
+#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1)
+
+/* If this bit is set, then ^ and $ are always anchors (outside bracket
+ expressions, of course).
+ If this bit is not set, then it depends:
+ ^ is an anchor if it is at the beginning of a regular
+ expression or after an open-group or an alternation operator;
+ $ is an anchor if it is at the end of a regular expression, or
+ before a close-group or an alternation operator.
+
+ This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because
+ POSIX draft 11.2 says that * etc. in leading positions is undefined.
+ We already implemented a previous draft which made those constructs
+ invalid, though, so we haven't changed the code back. */
+#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1)
+
+/* If this bit is set, then special characters are always special
+ regardless of where they are in the pattern.
+ If this bit is not set, then special characters are special only in
+ some contexts; otherwise they are ordinary. Specifically,
+ * + ? and intervals are only special when not after the beginning,
+ open-group, or alternation operator. */
+#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1)
+
+/* If this bit is set, then *, +, ?, and { cannot be first in an re or
+ immediately after an alternation or begin-group operator. */
+#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1)
+
+/* If this bit is set, then . matches newline.
+ If not set, then it doesn't. */
+#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1)
+
+/* If this bit is set, then . doesn't match NUL.
+ If not set, then it does. */
+#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1)
+
+/* If this bit is set, nonmatching lists [^...] do not match newline.
+ If not set, they do. */
+#define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1)
+
+/* If this bit is set, either \{...\} or {...} defines an
+ interval, depending on RE_NO_BK_BRACES.
+ If not set, \{, \}, {, and } are literals. */
+#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1)
+
+/* If this bit is set, +, ? and | aren't recognized as operators.
+ If not set, they are. */
+#define RE_LIMITED_OPS (RE_INTERVALS << 1)
+
+/* If this bit is set, newline is an alternation operator.
+ If not set, newline is literal. */
+#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1)
+
+/* If this bit is set, then `{...}' defines an interval, and \{ and \}
+ are literals.
+ If not set, then `\{...\}' defines an interval. */
+#define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1)
+
+/* If this bit is set, (...) defines a group, and \( and \) are literals.
+ If not set, \(...\) defines a group, and ( and ) are literals. */
+#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1)
+
+/* If this bit is set, then \<digit> matches <digit>.
+ If not set, then \<digit> is a back-reference. */
+#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1)
+
+/* If this bit is set, then | is an alternation operator, and \| is literal.
+ If not set, then \| is an alternation operator, and | is literal. */
+#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1)
+
+/* If this bit is set, then an ending range point collating higher
+ than the starting range point, as in [z-a], is invalid.
+ If not set, then when ending range point collates higher than the
+ starting range point, the range is ignored. */
+#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1)
+
+/* If this bit is set, then an unmatched ) is ordinary.
+ If not set, then an unmatched ) is invalid. */
+#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1)
+
+/* If this bit is set, succeed as soon as we match the whole pattern,
+ without further backtracking. */
+#define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1)
+
+/* If this bit is set, do not process the GNU regex operators.
+ If not set, then the GNU regex operators are recognized. */
+#define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1)
+
+/* If this bit is set, turn on internal regex debugging.
+ If not set, and debugging was on, turn it off.
+ This only works if regex.c is compiled -DDEBUG.
+ We define this bit always, so that all that's needed to turn on
+ debugging is to recompile regex.c; the calling code can always have
+ this bit set, and it won't affect anything in the normal case. */
+#define RE_DEBUG (RE_NO_GNU_OPS << 1)
+
+/* This global variable defines the particular regexp syntax to use (for
+ some interfaces). When a regexp is compiled, the syntax used is
+ stored in the pattern buffer, so changing this does not affect
+ already-compiled regexps. */
+extern reg_syntax_t re_syntax_options;
+
+/* Define combinations of the above bits for the standard possibilities.
+ (The [[[ comments delimit what gets put into the Texinfo file, so
+ don't delete them!) */
+/* [[[begin syntaxes]]] */
+#define RE_SYNTAX_EMACS 0
+
+#define RE_SYNTAX_AWK \
+ (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \
+ | RE_NO_BK_PARENS | RE_NO_BK_REFS \
+ | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \
+ | RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \
+ | RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS)
+
+#define RE_SYNTAX_GNU_AWK \
+ ((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DEBUG) \
+ & ~(RE_DOT_NOT_NULL | RE_INTERVALS | RE_CONTEXT_INDEP_OPS))
+
+#define RE_SYNTAX_POSIX_AWK \
+ (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \
+ | RE_INTERVALS | RE_NO_GNU_OPS)
+
+#define RE_SYNTAX_GREP \
+ (RE_BK_PLUS_QM | RE_CHAR_CLASSES \
+ | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \
+ | RE_NEWLINE_ALT)
+
+#define RE_SYNTAX_EGREP \
+ (RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \
+ | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \
+ | RE_NEWLINE_ALT | RE_NO_BK_PARENS \
+ | RE_NO_BK_VBAR)
+
+#define RE_SYNTAX_POSIX_EGREP \
+ (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES)
+
+/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */
+#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC
+
+#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC
+
+/* Syntax bits common to both basic and extended POSIX regex syntax. */
+#define _RE_SYNTAX_POSIX_COMMON \
+ (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \
+ | RE_INTERVALS | RE_NO_EMPTY_RANGES)
+
+#define RE_SYNTAX_POSIX_BASIC \
+ (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM)
+
+/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes
+ RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this
+ isn't minimal, since other operators, such as \`, aren't disabled. */
+#define RE_SYNTAX_POSIX_MINIMAL_BASIC \
+ (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS)
+
+#define RE_SYNTAX_POSIX_EXTENDED \
+ (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
+ | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \
+ | RE_NO_BK_PARENS | RE_NO_BK_VBAR \
+ | RE_UNMATCHED_RIGHT_PAREN_ORD)
+
+/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INVALID_OPS
+ replaces RE_CONTEXT_INDEP_OPS and RE_NO_BK_REFS is added. */
+#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \
+ (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
+ | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \
+ | RE_NO_BK_PARENS | RE_NO_BK_REFS \
+ | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD)
+/* [[[end syntaxes]]] */
+
+/* Maximum number of duplicates an interval can allow. Some systems
+ (erroneously) define this in other header files, but we want our
+ value, so remove any previous define. */
+#ifdef RE_DUP_MAX
+# undef RE_DUP_MAX
+#endif
+/* If sizeof(int) == 2, then ((1 << 15) - 1) overflows. */
+#define RE_DUP_MAX (0x7fff)
+
+
+/* POSIX `cflags' bits (i.e., information for `regcomp'). */
+
+/* If this bit is set, then use extended regular expression syntax.
+ If not set, then use basic regular expression syntax. */
+#define REG_EXTENDED 1
+
+/* If this bit is set, then ignore case when matching.
+ If not set, then case is significant. */
+#define REG_ICASE (REG_EXTENDED << 1)
+
+/* If this bit is set, then anchors do not match at newline
+ characters in the string.
+ If not set, then anchors do match at newlines. */
+#define REG_NEWLINE (REG_ICASE << 1)
+
+/* If this bit is set, then report only success or fail in regexec.
+ If not set, then returns differ between not matching and errors. */
+#define REG_NOSUB (REG_NEWLINE << 1)
+
+
+/* POSIX `eflags' bits (i.e., information for regexec). */
+
+/* If this bit is set, then the beginning-of-line operator doesn't match
+ the beginning of the string (presumably because it's not the
+ beginning of a line).
+ If not set, then the beginning-of-line operator does match the
+ beginning of the string. */
+#define REG_NOTBOL 1
+
+/* Like REG_NOTBOL, except for the end-of-line. */
+#define REG_NOTEOL (1 << 1)
+
+
+/* If any error codes are removed, changed, or added, update the
+ `re_error_msg' table in regex.c. */
+typedef enum
+{
+#ifdef _XOPEN_SOURCE
+ REG_ENOSYS = -1, /* This will never happen for this implementation. */
+#endif
+
+ REG_NOERROR = 0, /* Success. */
+ REG_NOMATCH, /* Didn't find a match (for regexec). */
+
+ /* POSIX regcomp return error codes. (In the order listed in the
+ standard.) */
+ REG_BADPAT, /* Invalid pattern. */
+ REG_ECOLLATE, /* Not implemented. */
+ REG_ECTYPE, /* Invalid character class name. */
+ REG_EESCAPE, /* Trailing backslash. */
+ REG_ESUBREG, /* Invalid back reference. */
+ REG_EBRACK, /* Unmatched left bracket. */
+ REG_EPAREN, /* Parenthesis imbalance. */
+ REG_EBRACE, /* Unmatched \{. */
+ REG_BADBR, /* Invalid contents of \{\}. */
+ REG_ERANGE, /* Invalid range end. */
+ REG_ESPACE, /* Ran out of memory. */
+ REG_BADRPT, /* No preceding re for repetition op. */
+
+ /* Error codes we've added. */
+ REG_EEND, /* Premature end. */
+ REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */
+ REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */
+} reg_errcode_t;
+
+/* This data structure represents a compiled pattern. Before calling
+ the pattern compiler, the fields `buffer', `allocated', `fastmap',
+ `translate', and `no_sub' can be set. After the pattern has been
+ compiled, the `re_nsub' field is available. All other fields are
+ private to the regex routines. */
+
+#ifndef RE_TRANSLATE_TYPE
+# define RE_TRANSLATE_TYPE char *
+#endif
+
+struct re_pattern_buffer
+{
+/* [[[begin pattern_buffer]]] */
+ /* Space that holds the compiled pattern. It is declared as
+ `unsigned char *' because its elements are
+ sometimes used as array indexes. */
+ unsigned char *buffer;
+
+ /* Number of bytes to which `buffer' points. */
+ unsigned long int allocated;
+
+ /* Number of bytes actually used in `buffer'. */
+ unsigned long int used;
+
+ /* Syntax setting with which the pattern was compiled. */
+ reg_syntax_t syntax;
+
+ /* Pointer to a fastmap, if any, otherwise zero. re_search uses
+ the fastmap, if there is one, to skip over impossible
+ starting points for matches. */
+ char *fastmap;
+
+ /* Either a translate table to apply to all characters before
+ comparing them, or zero for no translation. The translation
+ is applied to a pattern when it is compiled and to a string
+ when it is matched. */
+ RE_TRANSLATE_TYPE translate;
+
+ /* Number of subexpressions found by the compiler. */
+ size_t re_nsub;
+
+ /* Zero if this pattern cannot match the empty string, one else.
+ Well, in truth it's used only in `re_search_2', to see
+ whether or not we should use the fastmap, so we don't set
+ this absolutely perfectly; see `re_compile_fastmap' (the
+ `duplicate' case). */
+ unsigned can_be_null : 1;
+
+ /* If REGS_UNALLOCATED, allocate space in the `regs' structure
+ for `max (RE_NREGS, re_nsub + 1)' groups.
+ If REGS_REALLOCATE, reallocate space if necessary.
+ If REGS_FIXED, use what's there. */
+#define REGS_UNALLOCATED 0
+#define REGS_REALLOCATE 1
+#define REGS_FIXED 2
+ unsigned regs_allocated : 2;
+
+ /* Set to zero when `regex_compile' compiles a pattern; set to one
+ by `re_compile_fastmap' if it updates the fastmap. */
+ unsigned fastmap_accurate : 1;
+
+ /* If set, `re_match_2' does not return information about
+ subexpressions. */
+ unsigned no_sub : 1;
+
+ /* If set, a beginning-of-line anchor doesn't match at the
+ beginning of the string. */
+ unsigned not_bol : 1;
+
+ /* Similarly for an end-of-line anchor. */
+ unsigned not_eol : 1;
+
+ /* If true, an anchor at a newline matches. */
+ unsigned newline_anchor : 1;
+
+/* [[[end pattern_buffer]]] */
+};
+
+typedef struct re_pattern_buffer regex_t;
+
+/* Type for byte offsets within the string. POSIX mandates this. */
+typedef int regoff_t;
+
+
+/* This is the structure we store register match data in. See
+ regex.texinfo for a full description of what registers match. */
+struct re_registers
+{
+ unsigned num_regs;
+ regoff_t *start;
+ regoff_t *end;
+};
+
+
+/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer,
+ `re_match_2' returns information about at least this many registers
+ the first time a `regs' structure is passed. */
+#ifndef RE_NREGS
+# define RE_NREGS 30
+#endif
+
+
+/* POSIX specification for registers. Aside from the different names than
+ `re_registers', POSIX uses an array of structures, instead of a
+ structure of arrays. */
+typedef struct
+{
+ regoff_t rm_so; /* Byte offset from string's start to substring's start. */
+ regoff_t rm_eo; /* Byte offset from string's start to substring's end. */
+} regmatch_t;
+
+/* Declarations for routines. */
+
+/* To avoid duplicating every routine declaration -- once with a
+ prototype (if we are ANSI), and once without (if we aren't) -- we
+ use the following macro to declare argument types. This
+ unfortunately clutters up the declarations a bit, but I think it's
+ worth it. */
+
+#if __STDC__
+
+# define _RE_ARGS(args) args
+
+#else /* not __STDC__ */
+
+# define _RE_ARGS(args) ()
+
+#endif /* not __STDC__ */
+
+/* Sets the current default syntax to SYNTAX, and return the old syntax.
+ You can also simply assign to the `re_syntax_options' variable. */
+extern reg_syntax_t re_set_syntax _RE_ARGS ((reg_syntax_t syntax));
+
+/* Compile the regular expression PATTERN, with length LENGTH
+ and syntax given by the global `re_syntax_options', into the buffer
+ BUFFER. Return NULL if successful, and an error string if not. */
+extern const char *re_compile_pattern
+ _RE_ARGS ((const char *pattern, size_t length,
+ struct re_pattern_buffer *buffer));
+
+
+/* Compile a fastmap for the compiled pattern in BUFFER; used to
+ accelerate searches. Return 0 if successful and -2 if was an
+ internal error. */
+extern int re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer));
+
+
+/* Search in the string STRING (with length LENGTH) for the pattern
+ compiled into BUFFER. Start searching at position START, for RANGE
+ characters. Return the starting position of the match, -1 for no
+ match, or -2 for an internal error. Also return register
+ information in REGS (if REGS and BUFFER->no_sub are nonzero). */
+extern int re_search
+ _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
+ int length, int start, int range, struct re_registers *regs));
+
+
+/* Like `re_search', but search in the concatenation of STRING1 and
+ STRING2. Also, stop searching at index START + STOP. */
+extern int re_search_2
+ _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
+ int length1, const char *string2, int length2,
+ int start, int range, struct re_registers *regs, int stop));
+
+
+/* Like `re_search', but return how many characters in STRING the regexp
+ in BUFFER matched, starting at position START. */
+extern int re_match
+ _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
+ int length, int start, struct re_registers *regs));
+
+
+/* Relates to `re_match' as `re_search_2' relates to `re_search'. */
+extern int re_match_2
+ _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
+ int length1, const char *string2, int length2,
+ int start, struct re_registers *regs, int stop));
+
+
+/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
+ ENDS. Subsequent matches using BUFFER and REGS will use this memory
+ for recording register information. STARTS and ENDS must be
+ allocated with malloc, and must each be at least `NUM_REGS * sizeof
+ (regoff_t)' bytes long.
+
+ If NUM_REGS == 0, then subsequent matches should allocate their own
+ register data.
+
+ Unless this function is called, the first search or match using
+ PATTERN_BUFFER will allocate its own register data, without
+ freeing the old data. */
+extern void re_set_registers
+ _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs,
+ unsigned num_regs, regoff_t *starts, regoff_t *ends));
+
+#if defined _REGEX_RE_COMP || defined _LIBC
+# ifndef _CRAY
+/* 4.2 bsd compatibility. */
+extern char *re_comp _RE_ARGS ((const char *));
+extern int re_exec _RE_ARGS ((const char *));
+# endif
+#endif
+
+/* POSIX compatibility. */
+extern int regcomp _RE_ARGS ((regex_t *__preg, const char *__pattern,
+ int __cflags));
+
+extern int regexec _RE_ARGS ((const regex_t *__preg,
+ const char *__string, size_t __nmatch,
+ regmatch_t __pmatch[], int __eflags));
+
+extern size_t regerror _RE_ARGS ((int __errcode, const regex_t *__preg,
+ char *__errbuf, size_t __errbuf_size));
+
+extern void regfree _RE_ARGS ((regex_t *__preg));
+
+
+#ifdef __cplusplus
+}
+#endif /* C++ */
+
+#endif /* regex.h */
+
+/*
+Local variables:
+make-backup-files: t
+version-control: t
+trim-versions-without-asking: nil
+End:
+*/
diff --git a/src/select.c b/src/select.c
new file mode 100644
index 0000000..c4553c3
--- /dev/null
+++ b/src/select.c
@@ -0,0 +1,283 @@
+/*
+ * select.c -- Selection of a style sheet
+ * Copyright (c) 1995-99 Akim Demaille, Miguel Santana
+ *
+ */
+
+/*
+ * This file is part of a2ps.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "a2ps.h"
+#include "select.h"
+#include "routines.h"
+#include "xfnmatch.h"
+#include "getshline.h"
+#include "path-concat.h"
+#include "pathwalk.h"
+#include "filtdir.h"
+#include "message.h"
+#include "quotearg.h"
+
+extern char * style_request;
+
+/*
+ * Take priviledged access to job :)
+ */
+extern a2ps_job * job;
+extern struct darray * sheets_map;
+
+
+/*
+ * The user has requested the style sheet him self.
+ */
+void
+set_requested_style (const char * arg)
+{
+ xstrcpy (style_request, arg);
+}
+
+/************************************************************************/
+/* sheets.map handling */
+/************************************************************************/
+/*
+ * Association of suffixes rules, and corresponding style sheet
+ */
+struct pattern_rule
+{
+ const char * pattern;
+ const char * command;
+ int on_file_verdict;
+ bool insensitive_p;
+};
+
+struct pattern_rule *
+pattern_rule_new (const char *pattern, int on_file_verdict, bool insensitive_p,
+ const char *command)
+{
+ NEW (struct pattern_rule, res);
+
+ res->pattern = pattern;
+ res->on_file_verdict = on_file_verdict;
+ res->command = command;
+ res->insensitive_p = insensitive_p;
+
+ return res;
+}
+
+static void
+pattern_rule_self_print (struct pattern_rule * item, FILE * stream)
+{
+ fprintf (stream, "%s/%s: %s/%s\n",
+ item->on_file_verdict ? "file" : "name",
+ item->pattern,
+ item->command,
+ item->insensitive_p ? "i" : "");
+}
+
+struct darray *
+sheets_map_new (void)
+{
+ return da_new ("Sheets map", 200,
+ da_linear, 20,
+ (da_print_func_t) pattern_rule_self_print, NULL);
+}
+
+void
+sheets_map_add (const char * pattern, int on_file_verdict, bool insensitive_p,
+ const char * key)
+{
+ da_append (sheets_map,
+ pattern_rule_new (pattern, on_file_verdict, insensitive_p, key));
+}
+
+
+/*
+ * Read the sheets.map file
+ */
+static int
+sheets_map_load_main (void)
+{
+ char * file;
+
+ /* System's */
+ file = pw_find_file (job->common.path, "sheets.map", NULL);
+ if (!file)
+ {
+ error (0, errno, _("cannot find file `%s'"), "sheets.map");
+ /* sheets.map can not be found: there is no automatic prettyprinting */
+ error (0, 0, _("automatic style selection cancelled"));
+ return 0;
+ }
+
+ sheets_map_load (file);
+
+ free (file);
+ return 1;
+}
+
+/* escapes the name of a file so that the shell groks it in 'single' q.marks.
+ The resulting pointer has to be free()ed when not longer used. */
+char *
+shell_escape(const char *fn)
+{
+ size_t len = 0;
+ const char *inp;
+ char *retval, *outp;
+
+ for(inp = fn; *inp; ++inp)
+ switch(*inp)
+ {
+ case '\'': len += 4; break;
+ default: len += 1; break;
+ }
+
+ outp = retval = malloc(len + 1);
+ if(!outp)
+ return NULL; /* perhaps one should do better error handling here */
+ for(inp = fn; *inp; ++inp)
+ switch(*inp)
+ {
+ case '\'': *outp++ = '\''; *outp++ = '\\'; *outp++ = '\'', *outp++ = '\''; break;
+ default: *outp++ = *inp; break;
+ }
+ *outp = 0;
+
+ return retval;
+}
+
+/* What says file about the type of a file (result is malloc'd). NULL
+ if could not be run. */
+
+static char *
+file_verdict_on (const uchar *filename)
+{
+ char *cp = NULL, * command;
+ char buf [1024];
+ FILE * file_out;
+
+ if (IS_EMPTY (job->file_command))
+ return NULL;
+
+ filename = shell_escape(filename);
+ if(filename == NULL)
+ return NULL;
+ /* Call file(1) with the correct option */
+ command = ALLOCA (char, (4
+ + strlen (job->file_command)
+ + ustrlen (filename)));
+ sprintf (command, "%s '%s'", job->file_command, (const char *) filename);
+ free(filename);
+ message (msg_tool, (stderr, "Reading pipe: `%s'\n", command));
+ file_out = popen (command, "r");
+
+ /* Check for failure */
+ if (!file_out)
+ {
+ if (msg_test(msg_tool))
+ error (0, errno, _("cannot open a pipe on `%s'"),
+ quotearg (command));
+ return NULL;
+ }
+
+ /* Get the answer */
+ fgets (buf, sizeof (buf), file_out);
+ pclose (file_out);
+ message (msg_tool, (stderr, "file(1): %s", buf));
+
+ /* File is expected to answer:
+ filename: file-answer. */
+ cp = buf;
+ while (*cp && *cp != ':')
+ cp++;
+ cp++;
+ while (*cp && ((*cp == ' ') || (*cp == '\t')))
+ cp++;
+
+ if (*cp)
+ {
+ if (cp)
+ message (msg_tool, (stderr, "File's verdict: %s", cp));
+ /* Don't return the `\n'. */
+ return xstrndup (cp, strlen (cp) - 1);
+ }
+ return NULL;
+}
+
+/*
+ * Get style name from FILENAME, using pattern rules
+ * and file(1) rules if USE_FILE.
+ */
+#define rule(_i_) ((struct pattern_rule *)sheets_map->content[_i_])
+const char *
+get_command (const uchar *name_to_match, const uchar *name_to_file)
+{
+ int i;
+ char *file_verdict;
+ uchar *name_to_match_lc;
+
+ /* We only want to read the sheets map if needed, hence,
+ * from here (not needed if the sheet name is given by the
+ * user) */
+ if (da_is_empty (sheets_map))
+ sheets_map_load_main ();
+
+
+ /* Get file(1)'s verdict, and get a lowercase version of the
+ filename. */
+ file_verdict = file_verdict_on (name_to_file);
+ if (name_to_match)
+ {
+ name_to_match_lc = ALLOCA (char, strlen (name_to_match) + 1);
+ strcpylc (name_to_match_lc, name_to_match);
+ }
+
+ /* We look from bottom up, so that most recently defined rules are
+ * honored. Make sure not to call fnmatch on an empty FILE_VERDICT
+ * (thanks to Michael Taeschner <Michael.Taeschner@dlr.de>,
+ * Christian Mondrup <scancm@biobase.dk> and Jens Henrik Leonhard
+ * Jensen recjhl@mediator.uni-c.dk) */
+ /* The loop is split to speed up */
+ for (i = sheets_map->len - 1 ; i >= 0 ; i--)
+ if (rule(i)->on_file_verdict)
+ {
+ /* Testing upon file's result */
+ if (file_verdict
+ && !fnmatch (rule(i)->pattern, file_verdict, 0))
+ {
+ free (file_verdict);
+ return rule(i)->command;
+ }
+ }
+ else
+ {
+ /* Upon file name */
+ if (name_to_match
+ && !fnmatch (rule(i)->pattern,
+ (char *) (rule(i)->insensitive_p
+ ? name_to_match_lc : name_to_match),
+ 0))
+ {
+ XFREE (file_verdict);
+ return rule(i)->command;
+ }
+ }
+ XFREE (file_verdict);
+
+ return "plain";
+}
diff --git a/src/select.h b/src/select.h
new file mode 100644
index 0000000..7b12e60
--- /dev/null
+++ b/src/select.h
@@ -0,0 +1,66 @@
+/*
+ * select.h
+ *
+ * Selection of a style
+ * Copyright (c) 1988, 89, 90, 91, 92, 93 Miguel Santana
+ * Copyright (c) 1995, 96, 97, 98 Akim Demaille, Miguel Santana
+ */
+
+/*
+ * This file is part of a2ps.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * $Id: select.h,v 1.1.1.1.2.1 2007/12/29 01:58:36 mhatta Exp $
+ */
+
+#ifndef _SELECT_H_
+#define _SELECT_H_
+#include "ssheet.h"
+#include "darray.h"
+
+/* Used as hook when reading the options */
+void set_requested_style PARAMS ((const char * arg));
+
+/************************************************************************/
+/* sheets.map handling */
+/************************************************************************/
+/*
+ * Structure in charge of remembering the sheets read
+ */
+struct darray * sheets_map_new PARAMS ((void));
+void
+sheets_map_add PARAMS ((const char *pattern, int on_file_verdict,
+ bool insenstive, const char *key));
+
+/* Pattern matching is run on NAME_TO_MATCH, and file(1)
+ * is run of NAME_TO_FILE
+ */
+const char * get_command PARAMS ((const uchar * name_to_match,
+ const uchar * name_to_file));
+
+struct pattern_rule *
+pattern_rule_new PARAMS ((const char *pattern,
+ int on_file_verdict,
+ bool insensitive_p,
+ const char *command));
+
+void
+sheets_map_load PARAMS ((const char *filename));
+
+#endif /* !defined(_SELECT_H_) */
diff --git a/src/sheets-map.c b/src/sheets-map.c
new file mode 100644
index 0000000..8c72db0
--- /dev/null
+++ b/src/sheets-map.c
@@ -0,0 +1,2240 @@
+#line 2 "sheets-map.c"
+
+#line 4 "sheets-map.c"
+
+#define YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 33
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#endif
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_CONST
+
+#endif /* __STDC__ */
+#endif /* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE smaprestart(smapin )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+extern int smapleng;
+
+extern FILE *smapin, *smapout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+ /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
+ * access to the local variable yy_act. Since yyless() is a macro, it would break
+ * existing scanners that call yyless() from OUTSIDE smaplex.
+ * One obvious solution it to make yy_act a global. I tried that, and saw
+ * a 5% performance hit in a non-smaplineno scanner, because yy_act is
+ * normally declared as a register variable-- so it is not worth it.
+ */
+ #define YY_LESS_LINENO(n) \
+ do { \
+ int yyl;\
+ for ( yyl = n; yyl < smapleng; ++yyl )\
+ if ( smaptext[yyl] == '\n' )\
+ --smaplineno;\
+ }while(0)
+
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up smaptext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ *yy_cp = (yy_hold_char); \
+ YY_RESTORE_YY_MORE_OFFSET \
+ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up smaptext again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr) )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef unsigned int yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ int yy_bs_lineno; /**< The line count. */
+ int yy_bs_column; /**< The column count. */
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via smaprestart()), so that the user can continue scanning by
+ * just pointing smapin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+
+ };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+ : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when smaptext is formed. */
+static char yy_hold_char;
+static int yy_n_chars; /* number of characters read into yy_ch_buf */
+int smapleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 0; /* whether we need to initialize */
+static int yy_start = 0; /* start state number */
+
+/* Flag which is used to allow smapwrap()'s to do buffer switches
+ * instead of setting up a fresh smapin. A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void smaprestart (FILE *input_file );
+void smap_switch_to_buffer (YY_BUFFER_STATE new_buffer );
+YY_BUFFER_STATE smap_create_buffer (FILE *file,int size );
+void smap_delete_buffer (YY_BUFFER_STATE b );
+void smap_flush_buffer (YY_BUFFER_STATE b );
+void smappush_buffer_state (YY_BUFFER_STATE new_buffer );
+void smappop_buffer_state (void );
+
+static void smapensure_buffer_stack (void );
+static void smap_load_buffer_state (void );
+static void smap_init_buffer (YY_BUFFER_STATE b,FILE *file );
+
+#define YY_FLUSH_BUFFER smap_flush_buffer(YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE smap_scan_buffer (char *base,yy_size_t size );
+YY_BUFFER_STATE smap_scan_string (yyconst char *yy_str );
+YY_BUFFER_STATE smap_scan_bytes (yyconst char *bytes,int len );
+
+void *smapalloc (yy_size_t );
+void *smaprealloc (void *,yy_size_t );
+void smapfree (void * );
+
+#define yy_new_buffer smap_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){ \
+ smapensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ smap_create_buffer(smapin,YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){\
+ smapensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ smap_create_buffer(smapin,YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+typedef unsigned char YY_CHAR;
+
+FILE *smapin = (FILE *) 0, *smapout = (FILE *) 0;
+
+typedef int yy_state_type;
+
+extern int smaplineno;
+
+int smaplineno = 1;
+
+extern char *smaptext;
+#define yytext_ptr smaptext
+
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state );
+static int yy_get_next_buffer (void );
+static void yy_fatal_error (yyconst char msg[] );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up smaptext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ (yytext_ptr) = yy_bp; \
+ smapleng = (size_t) (yy_cp - yy_bp); \
+ (yy_hold_char) = *yy_cp; \
+ *yy_cp = '\0'; \
+ (yy_c_buf_p) = yy_cp;
+
+#define YY_NUM_RULES 38
+#define YY_END_OF_BUFFER 39
+/* This struct is not used in this scanner,
+ but its presence is necessary. */
+struct yy_trans_info
+ {
+ flex_int32_t yy_verify;
+ flex_int32_t yy_nxt;
+ };
+static yyconst flex_int16_t yy_accept[74] =
+ { 0,
+ 0, 0, 0, 0, 0, 0, 39, 7, 4, 4,
+ 5, 7, 2, 3, 7, 22, 21, 8, 38, 37,
+ 36, 23, 38, 4, 5, 0, 1, 0, 22, 8,
+ 20, 9, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 37, 23, 35, 24, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 0, 9, 10, 24,
+ 25, 0, 9, 10, 24, 25, 0, 0, 0, 0,
+ 0, 6, 0
+ } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 1, 1, 4, 1, 1, 1, 1, 5,
+ 6, 1, 1, 1, 7, 1, 8, 9, 9, 9,
+ 9, 9, 9, 9, 9, 10, 10, 11, 1, 12,
+ 1, 13, 1, 1, 10, 10, 10, 10, 10, 10,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 1, 14, 1, 1, 7, 1, 15, 16, 17, 18,
+
+ 19, 20, 7, 7, 21, 7, 7, 22, 7, 23,
+ 7, 7, 7, 24, 7, 25, 26, 27, 7, 28,
+ 7, 7, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+static yyconst flex_int32_t yy_meta[29] =
+ { 0,
+ 1, 1, 2, 1, 1, 3, 4, 5, 6, 6,
+ 4, 1, 7, 8, 6, 6, 6, 6, 6, 6,
+ 4, 4, 4, 4, 4, 4, 4, 4
+ } ;
+
+static yyconst flex_int16_t yy_base[85] =
+ { 0,
+ 0, 0, 26, 27, 29, 33, 154, 174, 35, 42,
+ 0, 140, 174, 174, 28, 0, 174, 122, 51, 0,
+ 174, 103, 79, 46, 0, 112, 174, 97, 0, 174,
+ 174, 110, 174, 174, 174, 174, 174, 174, 174, 174,
+ 174, 0, 0, 174, 174, 108, 174, 174, 174, 174,
+ 174, 174, 174, 174, 174, 0, 98, 106, 0, 103,
+ 0, 99, 174, 174, 174, 174, 100, 102, 111, 0,
+ 76, 174, 174, 125, 133, 141, 146, 152, 159, 48,
+ 44, 27, 25, 165
+ } ;
+
+static yyconst flex_int16_t yy_def[85] =
+ { 0,
+ 73, 1, 74, 74, 75, 75, 73, 73, 73, 73,
+ 76, 77, 73, 73, 77, 78, 73, 73, 73, 79,
+ 73, 73, 73, 73, 76, 77, 73, 77, 78, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 80, 79, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 81, 77, 73, 82, 73,
+ 83, 77, 73, 73, 73, 73, 77, 77, 77, 84,
+ 84, 73, 0, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73
+ } ;
+
+static yyconst flex_int16_t yy_nxt[203] =
+ { 0,
+ 8, 9, 10, 11, 8, 8, 12, 13, 12, 12,
+ 8, 14, 8, 8, 12, 12, 12, 12, 12, 12,
+ 15, 12, 12, 12, 12, 12, 12, 12, 17, 17,
+ 66, 21, 64, 18, 18, 21, 24, 24, 27, 19,
+ 19, 22, 23, 24, 24, 22, 23, 24, 24, 61,
+ 28, 31, 31, 59, 31, 31, 31, 31, 31, 32,
+ 31, 31, 31, 31, 31, 33, 34, 31, 35, 36,
+ 37, 31, 31, 38, 39, 40, 31, 41, 42, 45,
+ 45, 72, 45, 45, 45, 45, 45, 46, 45, 45,
+ 45, 45, 45, 47, 48, 45, 49, 50, 51, 45,
+
+ 45, 52, 53, 54, 45, 55, 56, 27, 27, 27,
+ 27, 65, 27, 57, 63, 70, 60, 68, 58, 62,
+ 69, 27, 27, 44, 67, 16, 16, 16, 16, 16,
+ 16, 16, 16, 20, 20, 20, 20, 20, 20, 20,
+ 20, 25, 30, 25, 25, 25, 25, 25, 25, 26,
+ 27, 26, 29, 73, 29, 29, 73, 29, 29, 43,
+ 73, 43, 43, 43, 43, 71, 71, 73, 71, 71,
+ 71, 71, 71, 7, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+
+ 73, 73
+ } ;
+
+static yyconst flex_int16_t yy_chk[203] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 3, 4,
+ 83, 5, 82, 3, 4, 6, 9, 9, 15, 3,
+ 4, 5, 5, 10, 10, 6, 6, 24, 24, 81,
+ 15, 19, 19, 80, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 23,
+ 23, 71, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+
+ 23, 23, 23, 23, 23, 23, 23, 28, 57, 62,
+ 67, 60, 68, 28, 58, 69, 46, 67, 32, 57,
+ 68, 69, 26, 22, 62, 74, 74, 74, 74, 74,
+ 74, 74, 74, 75, 75, 75, 75, 75, 75, 75,
+ 75, 76, 18, 76, 76, 76, 76, 76, 76, 77,
+ 12, 77, 78, 7, 78, 78, 0, 78, 78, 79,
+ 0, 79, 79, 79, 79, 84, 84, 0, 84, 84,
+ 84, 84, 84, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+
+ 73, 73
+ } ;
+
+/* Table of booleans, true if rule could match eol. */
+static yyconst flex_int32_t yy_rule_can_match_eol[39] =
+ { 0,
+0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, };
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+extern int smap_flex_debug;
+int smap_flex_debug = 0;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *smaptext;
+#line 1 "sheets-map.l"
+#line 2 "sheets-map.l"
+/* Scanner for sheets.map files.
+ * Copyright (c) 1999-2000 Akim Demaille, Miguel Santana
+ */
+
+/*
+ * This file is part of a2ps.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "main.h"
+#include "select.h"
+#include "xobstack.h"
+
+extern struct darray * sheets_map;
+
+int smaplex PARAMS ((void));
+void yyerror PARAMS ((const char *));
+static void yy_include_push PARAMS ((char *file));
+static void yy_include_pop PARAMS ((void));
+
+/* Obstack for strings reading */
+static struct obstack string_stack;
+
+/* Stack to handle included files. */
+
+#define MAX_INCLUDE_DEPTH 10
+static YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
+static int lineno_stack[MAX_INCLUDE_DEPTH];
+static char *filename_stack[MAX_INCLUDE_DEPTH];
+static int include_stack_ptr;
+static char *yyfilename;
+
+typedef enum
+{
+ tKEY = 10,
+ tGLOB = 11,
+ tFILE = 12
+} token_t;
+
+static char *token_val;
+static bool insensitive_p;
+
+static inline void
+obstack_hexa_grow (struct obstack *o, const char *str)
+{
+ int value = 0;
+
+ /* FIXME: Requires ASCII? */
+ while (*str)
+ if (*str >= 'a' && *str <= 'f')
+ value = 16 * value + *str++ - 'a' + 10;
+ else if (*str >= 'A' && *str <= 'F')
+ value = 16 * value + *str++ - 'A' + 10;
+ else
+ value = 16 * value + *str++ - '0';
+ obstack_1grow (o, value);
+}
+
+static inline void
+obstack_octal_grow (struct obstack *o, const char *str)
+{
+ int value = *str++ - '0';
+
+ while (*str)
+ value = 8 * value + *str++ - '0';
+ obstack_1grow (o, value);
+}
+
+
+
+
+#line 628 "sheets-map.c"
+
+#define INITIAL 0
+#define STATE_GLOB 1
+#define STATE_FILE 2
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals (void );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int smapwrap (void );
+#else
+extern int smapwrap (void );
+#endif
+#endif
+
+ static void yyunput (int c,char *buf_ptr );
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (void );
+#else
+static int input (void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( smaptext, smapleng, 1, smapout )
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+ { \
+ int c = '*'; \
+ size_t n; \
+ for ( n = 0; n < max_size && \
+ (c = getc( smapin )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+ if ( c == '\n' ) \
+ buf[n++] = (char) c; \
+ if ( c == EOF && ferror( smapin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ } \
+ else \
+ { \
+ errno=0; \
+ while ( (result = fread(buf, 1, max_size, smapin))==0 && ferror(smapin)) \
+ { \
+ if( errno != EINTR) \
+ { \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ break; \
+ } \
+ errno=0; \
+ clearerr(smapin); \
+ } \
+ }\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int smaplex (void);
+
+#define YY_DECL int smaplex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after smaptext and smapleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+ YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp, *yy_bp;
+ register int yy_act;
+
+#line 98 "sheets-map.l"
+
+
+#line 786 "sheets-map.c"
+
+ if ( !(yy_init) )
+ {
+ (yy_init) = 1;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if ( ! (yy_start) )
+ (yy_start) = 1; /* first start state */
+
+ if ( ! smapin )
+ smapin = stdin;
+
+ if ( ! smapout )
+ smapout = stdout;
+
+ if ( ! YY_CURRENT_BUFFER ) {
+ smapensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ smap_create_buffer(smapin,YY_BUF_SIZE );
+ }
+
+ smap_load_buffer_state( );
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = (yy_c_buf_p);
+
+ /* Support of smaptext. */
+ *yy_cp = (yy_hold_char);
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = (yy_start);
+yy_match:
+ do
+ {
+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 74 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ ++yy_cp;
+ }
+ while ( yy_base[yy_current_state] != 174 );
+
+yy_find_action:
+ yy_act = yy_accept[yy_current_state];
+ if ( yy_act == 0 )
+ { /* have to back up */
+ yy_cp = (yy_last_accepting_cpos);
+ yy_current_state = (yy_last_accepting_state);
+ yy_act = yy_accept[yy_current_state];
+ }
+
+ YY_DO_BEFORE_ACTION;
+
+ if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
+ {
+ int yyl;
+ for ( yyl = 0; yyl < smapleng; ++yyl )
+ if ( smaptext[yyl] == '\n' )
+
+ smaplineno++;
+;
+ }
+
+do_action: /* This label is used only to access EOF actions. */
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+ case 0: /* must back up */
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = (yy_hold_char);
+ yy_cp = (yy_last_accepting_cpos);
+ yy_current_state = (yy_last_accepting_state);
+ goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 100 "sheets-map.l"
+token_val = xstrndup (smaptext, smapleng - 1); return tKEY;
+ YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 101 "sheets-map.l"
+BEGIN STATE_GLOB;
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 102 "sheets-map.l"
+BEGIN STATE_FILE;
+ YY_BREAK
+case 4:
+/* rule 4 can match eol */
+YY_RULE_SETUP
+#line 103 "sheets-map.l"
+;
+ YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 104 "sheets-map.l"
+;
+ YY_BREAK
+case 6:
+/* rule 6 can match eol */
+YY_RULE_SETUP
+#line 105 "sheets-map.l"
+{ /* Kill the closing paren and pass the file name. */
+ smaptext[smapleng - 1] = '\0';
+ yy_include_push (smaptext + strlen ("include("));
+ }
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 110 "sheets-map.l"
+{ error_at_line (1, 0, yyfilename, smaplineno,
+ _("unexpected character `%c'"), *smaptext);
+ }
+ YY_BREAK
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(STATE_GLOB):
+case YY_STATE_EOF(STATE_FILE):
+#line 113 "sheets-map.l"
+{ message (msg_file, (stderr, "End of file `%s'.\n",
+ yyfilename));
+ if (--include_stack_ptr < 0)
+ yyterminate ();
+ else
+ yy_include_pop () ;
+ }
+ YY_BREAK
+
+case 8:
+YY_RULE_SETUP
+#line 122 "sheets-map.l"
+{ /* return the string */
+ uchar *string;
+
+ obstack_1grow (&string_stack, '\0');
+ string = (uchar *) obstack_finish (&string_stack);
+ obstack_free (&string_stack, string);
+ token_val = xustrdup (string);
+
+ /* Decode the additional flags. */
+ insensitive_p = smaptext[1] == 'i';
+
+ BEGIN INITIAL; /* Return to the regular scanning */
+ return tGLOB;
+ }
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 137 "sheets-map.l"
+{ obstack_octal_grow (&string_stack, smaptext + 1); }
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 138 "sheets-map.l"
+{ obstack_hexa_grow (&string_stack, smaptext + 2); }
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 139 "sheets-map.l"
+{ obstack_1grow (&string_stack, '\007'); }
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 140 "sheets-map.l"
+{ obstack_1grow (&string_stack, '\b'); }
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 141 "sheets-map.l"
+{ obstack_1grow (&string_stack, 127); }
+ YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 142 "sheets-map.l"
+{ obstack_1grow (&string_stack, 27); }
+ YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 143 "sheets-map.l"
+{ obstack_1grow (&string_stack, '\f'); }
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 144 "sheets-map.l"
+{ obstack_1grow (&string_stack, '\n'); }
+ YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 145 "sheets-map.l"
+{ obstack_1grow (&string_stack, '\r'); }
+ YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 146 "sheets-map.l"
+{ obstack_1grow (&string_stack, '\t'); }
+ YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 147 "sheets-map.l"
+{ obstack_1grow (&string_stack, '\v'); }
+ YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 148 "sheets-map.l"
+{ obstack_1grow (&string_stack, smaptext[1]); }
+ YY_BREAK
+case 21:
+/* rule 21 can match eol */
+YY_RULE_SETUP
+#line 150 "sheets-map.l"
+{
+ error_at_line (1, 0, yyfilename, smaplineno,
+ /* TRANS: %s is ".." or <..> or /../ etc. */
+ _("end of line inside a %s"), "/../");
+ }
+ YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 156 "sheets-map.l"
+{
+ obstack_grow (&string_stack, smaptext, smapleng);
+ }
+ YY_BREAK
+
+/* string of characters */
+case 23:
+YY_RULE_SETUP
+#line 162 "sheets-map.l"
+{ /* return the string */
+ uchar *string;
+
+ obstack_1grow (&string_stack, '\0');
+ string = (uchar *) obstack_finish (&string_stack);
+ obstack_free (&string_stack, string);
+ token_val = xustrdup (string);
+
+ /* Decode the additional flags. */
+ insensitive_p = smaptext[1] == 'i';
+
+ BEGIN INITIAL; /* Return to the regular scanning */
+ return tFILE;
+ }
+ YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 177 "sheets-map.l"
+{ obstack_octal_grow (&string_stack, smaptext + 1); }
+ YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 178 "sheets-map.l"
+{ obstack_hexa_grow (&string_stack, smaptext + 2); }
+ YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 179 "sheets-map.l"
+{ obstack_1grow (&string_stack, '\007'); }
+ YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 180 "sheets-map.l"
+{ obstack_1grow (&string_stack, '\b'); }
+ YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 181 "sheets-map.l"
+{ obstack_1grow (&string_stack, 127); }
+ YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 182 "sheets-map.l"
+{ obstack_1grow (&string_stack, 27); }
+ YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 183 "sheets-map.l"
+{ obstack_1grow (&string_stack, '\f'); }
+ YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 184 "sheets-map.l"
+{ obstack_1grow (&string_stack, '\n'); }
+ YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 185 "sheets-map.l"
+{ obstack_1grow (&string_stack, '\r'); }
+ YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 186 "sheets-map.l"
+{ obstack_1grow (&string_stack, '\t'); }
+ YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 187 "sheets-map.l"
+{ obstack_1grow (&string_stack, '\v'); }
+ YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 188 "sheets-map.l"
+{ obstack_1grow (&string_stack, smaptext[1]); }
+ YY_BREAK
+case 36:
+/* rule 36 can match eol */
+YY_RULE_SETUP
+#line 190 "sheets-map.l"
+{
+ error_at_line (1, 0, yyfilename, smaplineno,
+ _("end of line inside a %s"), "<..>");
+ }
+ YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 195 "sheets-map.l"
+{
+ obstack_grow (&string_stack, smaptext, smapleng);
+ }
+ YY_BREAK
+
+case 38:
+YY_RULE_SETUP
+#line 199 "sheets-map.l"
+ECHO;
+ YY_BREAK
+#line 1131 "sheets-map.c"
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = (yy_hold_char);
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed smapin at a new source and called
+ * smaplex(). If so, then we have to assure
+ * consistency between YY_CURRENT_BUFFER and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ YY_CURRENT_BUFFER_LVALUE->yy_input_file = smapin;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( );
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++(yy_c_buf_p);
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = (yy_c_buf_p);
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer( ) )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ (yy_did_buffer_switch_on_eof) = 0;
+
+ if ( smapwrap( ) )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * smaptext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! (yy_did_buffer_switch_on_eof) )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ (yy_c_buf_p) =
+ (yytext_ptr) + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( );
+
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ (yy_c_buf_p) =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+ yy_current_state = yy_get_previous_state( );
+
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+} /* end of smaplex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (void)
+{
+ register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ register char *source = (yytext_ptr);
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+ else
+ {
+ int num_to_read =
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+ int yy_c_buf_p_offset =
+ (int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+ int new_size = b->yy_buf_size * 2;
+
+ if ( new_size <= 0 )
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ smaprealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = 0;
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+ (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+ number_to_move - 1;
+
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+ (yy_n_chars), (size_t) num_to_read );
+
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ if ( (yy_n_chars) == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ smaprestart(smapin );
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ (yy_n_chars) += number_to_move;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+ (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+ return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+ static yy_state_type yy_get_previous_state (void)
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+
+ yy_current_state = (yy_start);
+
+ for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+ {
+ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 74 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ }
+
+ return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state )
+{
+ register int yy_is_jam;
+ register char *yy_cp = (yy_c_buf_p);
+
+ register YY_CHAR yy_c = 1;
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 74 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_is_jam = (yy_current_state == 73);
+
+ return yy_is_jam ? 0 : yy_current_state;
+}
+
+ static void yyunput (int c, register char * yy_bp )
+{
+ register char *yy_cp;
+
+ yy_cp = (yy_c_buf_p);
+
+ /* undo effects of setting up smaptext */
+ *yy_cp = (yy_hold_char);
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ { /* need to shift things up to make room */
+ /* +2 for EOB chars. */
+ register int number_to_move = (yy_n_chars) + 2;
+ register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+ register char *source =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+ while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ *--dest = *--source;
+
+ yy_cp += (int) (dest - source);
+ yy_bp += (int) (dest - source);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ YY_FATAL_ERROR( "flex scanner push-back overflow" );
+ }
+
+ *--yy_cp = (char) c;
+
+ if ( c == '\n' ){
+ --smaplineno;
+ }
+
+ (yytext_ptr) = yy_bp;
+ (yy_hold_char) = *yy_cp;
+ (yy_c_buf_p) = yy_cp;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+ static int yyinput (void)
+#else
+ static int input (void)
+#endif
+
+{
+ int c;
+
+ *(yy_c_buf_p) = (yy_hold_char);
+
+ if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+ /* This was really a NUL. */
+ *(yy_c_buf_p) = '\0';
+
+ else
+ { /* need more input */
+ int offset = (yy_c_buf_p) - (yytext_ptr);
+ ++(yy_c_buf_p);
+
+ switch ( yy_get_next_buffer( ) )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ smaprestart(smapin );
+
+ /*FALLTHROUGH*/
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( smapwrap( ) )
+ return EOF;
+
+ if ( ! (yy_did_buffer_switch_on_eof) )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput();
+#else
+ return input();
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ (yy_c_buf_p) = (yytext_ptr) + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */
+ *(yy_c_buf_p) = '\0'; /* preserve smaptext */
+ (yy_hold_char) = *++(yy_c_buf_p);
+
+ if ( c == '\n' )
+
+ smaplineno++;
+;
+
+ return c;
+}
+#endif /* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ *
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+ void smaprestart (FILE * input_file )
+{
+
+ if ( ! YY_CURRENT_BUFFER ){
+ smapensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ smap_create_buffer(smapin,YY_BUF_SIZE );
+ }
+
+ smap_init_buffer(YY_CURRENT_BUFFER,input_file );
+ smap_load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ *
+ */
+ void smap_switch_to_buffer (YY_BUFFER_STATE new_buffer )
+{
+
+ /* TODO. We should be able to replace this entire function body
+ * with
+ * smappop_buffer_state();
+ * smappush_buffer_state(new_buffer);
+ */
+ smapensure_buffer_stack ();
+ if ( YY_CURRENT_BUFFER == new_buffer )
+ return;
+
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+ smap_load_buffer_state( );
+
+ /* We don't actually know whether we did this switch during
+ * EOF (smapwrap()) processing, but the only time this flag
+ * is looked at is after smapwrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void smap_load_buffer_state (void)
+{
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+ smapin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+ (yy_hold_char) = *(yy_c_buf_p);
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ *
+ * @return the allocated buffer state.
+ */
+ YY_BUFFER_STATE smap_create_buffer (FILE * file, int size )
+{
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) smapalloc(sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in smap_create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) smapalloc(b->yy_buf_size + 2 );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in smap_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ smap_init_buffer(b,file );
+
+ return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with smap_create_buffer()
+ *
+ */
+ void smap_delete_buffer (YY_BUFFER_STATE b )
+{
+
+ if ( ! b )
+ return;
+
+ if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ smapfree((void *) b->yy_ch_buf );
+
+ smapfree((void *) b );
+}
+
+#ifndef __cplusplus
+extern int isatty (int );
+#endif /* __cplusplus */
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a smaprestart() or at EOF.
+ */
+ static void smap_init_buffer (YY_BUFFER_STATE b, FILE * file )
+
+{
+ int oerrno = errno;
+
+ smap_flush_buffer(b );
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+ /* If b is the current buffer, then smap_init_buffer was _probably_
+ * called from smaprestart() or through yy_get_next_buffer.
+ * In that case, we don't want to reset the lineno or column.
+ */
+ if (b != YY_CURRENT_BUFFER){
+ b->yy_bs_lineno = 1;
+ b->yy_bs_column = 0;
+ }
+
+ b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+
+ errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ *
+ */
+ void smap_flush_buffer (YY_BUFFER_STATE b )
+{
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == YY_CURRENT_BUFFER )
+ smap_load_buffer_state( );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ * the current state. This function will allocate the stack
+ * if necessary.
+ * @param new_buffer The new state.
+ *
+ */
+void smappush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+ if (new_buffer == NULL)
+ return;
+
+ smapensure_buffer_stack();
+
+ /* This block is copied from smap_switch_to_buffer. */
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ /* Only push if top exists. Otherwise, replace top. */
+ if (YY_CURRENT_BUFFER)
+ (yy_buffer_stack_top)++;
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+ /* copied from smap_switch_to_buffer. */
+ smap_load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ * The next element becomes the new top.
+ *
+ */
+void smappop_buffer_state (void)
+{
+ if (!YY_CURRENT_BUFFER)
+ return;
+
+ smap_delete_buffer(YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ if ((yy_buffer_stack_top) > 0)
+ --(yy_buffer_stack_top);
+
+ if (YY_CURRENT_BUFFER) {
+ smap_load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
+ }
+}
+
+/* Allocates the stack if it does not exist.
+ * Guarantees space for at least one push.
+ */
+static void smapensure_buffer_stack (void)
+{
+ int num_to_alloc;
+
+ if (!(yy_buffer_stack)) {
+
+ /* First allocation is just for 2 elements, since we don't know if this
+ * scanner will even need a stack. We use 2 instead of 1 to avoid an
+ * immediate realloc on the next call.
+ */
+ num_to_alloc = 1;
+ (yy_buffer_stack) = (struct yy_buffer_state**)smapalloc
+ (num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+
+ memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+
+ (yy_buffer_stack_max) = num_to_alloc;
+ (yy_buffer_stack_top) = 0;
+ return;
+ }
+
+ if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+ /* Increase the buffer to prepare for a possible push. */
+ int grow_size = 8 /* arbitrary grow size */;
+
+ num_to_alloc = (yy_buffer_stack_max) + grow_size;
+ (yy_buffer_stack) = (struct yy_buffer_state**)smaprealloc
+ ((yy_buffer_stack),
+ num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+
+ /* zero only the new slots.*/
+ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+ (yy_buffer_stack_max) = num_to_alloc;
+ }
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE smap_scan_buffer (char * base, yy_size_t size )
+{
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE) smapalloc(sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in smap_scan_buffer()" );
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ smap_switch_to_buffer(b );
+
+ return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to smaplex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ *
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ * smap_scan_bytes() instead.
+ */
+YY_BUFFER_STATE smap_scan_string (yyconst char * yystr )
+{
+
+ return smap_scan_bytes(yystr,strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to smaplex() will
+ * scan from a @e copy of @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE smap_scan_bytes (yyconst char * yybytes, int _yybytes_len )
+{
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = _yybytes_len + 2;
+ buf = (char *) smapalloc(n );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in smap_scan_bytes()" );
+
+ for ( i = 0; i < _yybytes_len; ++i )
+ buf[i] = yybytes[i];
+
+ buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = smap_scan_buffer(buf,n );
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in smap_scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg )
+{
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up smaptext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ smaptext[smapleng] = (yy_hold_char); \
+ (yy_c_buf_p) = smaptext + yyless_macro_arg; \
+ (yy_hold_char) = *(yy_c_buf_p); \
+ *(yy_c_buf_p) = '\0'; \
+ smapleng = yyless_macro_arg; \
+ } \
+ while ( 0 )
+
+/* Accessor methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ *
+ */
+int smapget_lineno (void)
+{
+
+ return smaplineno;
+}
+
+/** Get the input stream.
+ *
+ */
+FILE *smapget_in (void)
+{
+ return smapin;
+}
+
+/** Get the output stream.
+ *
+ */
+FILE *smapget_out (void)
+{
+ return smapout;
+}
+
+/** Get the length of the current token.
+ *
+ */
+int smapget_leng (void)
+{
+ return smapleng;
+}
+
+/** Get the current token.
+ *
+ */
+
+char *smapget_text (void)
+{
+ return smaptext;
+}
+
+/** Set the current line number.
+ * @param line_number
+ *
+ */
+void smapset_lineno (int line_number )
+{
+
+ smaplineno = line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ *
+ * @see smap_switch_to_buffer
+ */
+void smapset_in (FILE * in_str )
+{
+ smapin = in_str ;
+}
+
+void smapset_out (FILE * out_str )
+{
+ smapout = out_str ;
+}
+
+int smapget_debug (void)
+{
+ return smap_flex_debug;
+}
+
+void smapset_debug (int bdebug )
+{
+ smap_flex_debug = bdebug ;
+}
+
+static int yy_init_globals (void)
+{
+ /* Initialization is the same as for the non-reentrant scanner.
+ * This function is called from smaplex_destroy(), so don't allocate here.
+ */
+
+ /* We do not touch smaplineno unless the option is enabled. */
+ smaplineno = 1;
+
+ (yy_buffer_stack) = 0;
+ (yy_buffer_stack_top) = 0;
+ (yy_buffer_stack_max) = 0;
+ (yy_c_buf_p) = (char *) 0;
+ (yy_init) = 0;
+ (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+ smapin = stdin;
+ smapout = stdout;
+#else
+ smapin = (FILE *) 0;
+ smapout = (FILE *) 0;
+#endif
+
+ /* For future reference: Set errno on error, since we are called by
+ * smaplex_init()
+ */
+ return 0;
+}
+
+/* smaplex_destroy is for both reentrant and non-reentrant scanners. */
+int smaplex_destroy (void)
+{
+
+ /* Pop the buffer stack, destroying each element. */
+ while(YY_CURRENT_BUFFER){
+ smap_delete_buffer(YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ smappop_buffer_state();
+ }
+
+ /* Destroy the stack itself. */
+ smapfree((yy_buffer_stack) );
+ (yy_buffer_stack) = NULL;
+
+ /* Reset the globals. This is important in a non-reentrant scanner so the next time
+ * smaplex() is called, initialization will occur. */
+ yy_init_globals( );
+
+ return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+ register int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+ register int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+}
+#endif
+
+void *smapalloc (yy_size_t size )
+{
+ return (void *) malloc( size );
+}
+
+void *smaprealloc (void * ptr, yy_size_t size )
+{
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+}
+
+void smapfree (void * ptr )
+{
+ free( (char *) ptr ); /* see smaprealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 199 "sheets-map.l"
+
+
+
+/*-----------------------------------------------------.
+| Handle the inclusion of files at the scanner level. |
+`-----------------------------------------------------*/
+
+/* Switch the scanning onto FILE, coming back to YYIN later. */
+
+static void
+yy_include_push (char *file)
+{
+ if (include_stack_ptr >= MAX_INCLUDE_DEPTH)
+ error (1, 0, _("too many includes"));
+
+ include_stack[include_stack_ptr] = YY_CURRENT_BUFFER;
+ lineno_stack[include_stack_ptr] = smaplineno;
+ filename_stack[include_stack_ptr++] = yyfilename;
+
+ message (msg_file, (stderr, "%s:%d: includes %s\n",
+ yyfilename, smaplineno, file));
+
+ yyfilename = file;
+ smapin = xrfopen (yyfilename);
+
+ smap_switch_to_buffer (smap_create_buffer (smapin, YY_BUF_SIZE));
+}
+
+/* Pop the inclusion stack and proceed. To be called on <<EOF>>.*/
+
+static void
+yy_include_pop (void)
+{
+ fclose (smapin);
+ smap_delete_buffer (YY_CURRENT_BUFFER);
+ yyfilename = filename_stack[include_stack_ptr];
+ smaplineno = lineno_stack[include_stack_ptr];
+ smap_switch_to_buffer (include_stack[include_stack_ptr]);
+ message (msg_file, (stderr, "Back to file `%s'.\n", yyfilename));
+}
+
+
+/*----------------------.
+| Prepare the scanner. |
+`----------------------*/
+
+/* Initialize the include stack to FILE. */
+
+static inline void
+yy_open (const char *file)
+{
+ yyfilename = xstrdup (file);
+ smapin = xrfopen (yyfilename);
+ include_stack_ptr = 0;
+}
+
+/* End of the scanning. */
+
+static inline void
+yy_close (void)
+{
+ fclose (smapin);
+ free (yyfilename);
+}
+
+int
+smapwrap (void)
+{
+ return 1;
+}
+
+
+void
+sheets_map_load (const char *filename)
+{
+ static int first_time = 1;
+ token_t token;
+ char *key = NULL;
+
+ if (first_time)
+ {
+ first_time = 0;
+ obstack_init (&string_stack);
+ }
+
+ yy_open (filename);
+
+ while ((token = smaplex ()))
+ {
+ switch (token)
+ {
+ case tKEY:
+ key = token_val;
+ break;
+
+ case tGLOB:
+ if (!key)
+ error_at_line (1, 0, yyfilename, smaplineno,
+ _("no key defined for `%s'"), quotearg (token_val));
+ sheets_map_add (token_val, false, insensitive_p, key);
+ break;
+
+ case tFILE:
+ if (!key)
+ error_at_line (1, 0, yyfilename, smaplineno,
+ _("no key defined for `%s'"), quotearg (token_val));
+ sheets_map_add (token_val, true, insensitive_p, key);
+ break;
+ }
+ }
+
+ yy_close ();
+}
+
diff --git a/src/sheets-map.l b/src/sheets-map.l
new file mode 100644
index 0000000..b14dd07
--- /dev/null
+++ b/src/sheets-map.l
@@ -0,0 +1,310 @@
+%{ /* -*- c -*- */
+/* Scanner for sheets.map files.
+ * Copyright (c) 1999-2000 Akim Demaille, Miguel Santana
+ */
+
+/*
+ * This file is part of a2ps.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "main.h"
+#include "select.h"
+#include "xobstack.h"
+
+extern struct darray * sheets_map;
+
+int yylex PARAMS ((void));
+void yyerror PARAMS ((const char *));
+static void yy_include_push PARAMS ((char *file));
+static void yy_include_pop PARAMS ((void));
+
+/* Obstack for strings reading */
+static struct obstack string_stack;
+
+/* Stack to handle included files. */
+
+#define MAX_INCLUDE_DEPTH 10
+static YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
+static int lineno_stack[MAX_INCLUDE_DEPTH];
+static char *filename_stack[MAX_INCLUDE_DEPTH];
+static int include_stack_ptr;
+static char *yyfilename;
+
+typedef enum
+{
+ tKEY = 10,
+ tGLOB = 11,
+ tFILE = 12
+} token_t;
+
+static char *token_val;
+static bool insensitive_p;
+
+static inline void
+obstack_hexa_grow (struct obstack *o, const char *str)
+{
+ int value = 0;
+
+ /* FIXME: Requires ASCII? */
+ while (*str)
+ if (*str >= 'a' && *str <= 'f')
+ value = 16 * value + *str++ - 'a' + 10;
+ else if (*str >= 'A' && *str <= 'F')
+ value = 16 * value + *str++ - 'A' + 10;
+ else
+ value = 16 * value + *str++ - '0';
+ obstack_1grow (o, value);
+}
+
+static inline void
+obstack_octal_grow (struct obstack *o, const char *str)
+{
+ int value = *str++ - '0';
+
+ while (*str)
+ value = 8 * value + *str++ - '0';
+ obstack_1grow (o, value);
+}
+
+
+%}
+
+%option yylineno
+%option prefix="smap"
+%option outfile="lex.yy.c"
+
+%x STATE_GLOB
+%x STATE_FILE
+
+white [[:space:]]+
+key [-a-zA-Z0-9_]+:
+comment #.*
+include include\([^)]+\)
+%%
+
+{key} token_val = xstrndup (yytext, yyleng - 1); return tKEY;
+\/ BEGIN STATE_GLOB;
+\< BEGIN STATE_FILE;
+{white} ;
+{comment} ;
+{include} { /* Kill the closing paren and pass the file name. */
+ yytext[yyleng - 1] = '\0';
+ yy_include_push (yytext + strlen ("include("));
+ }
+
+. { error_at_line (1, 0, yyfilename, yylineno,
+ _("unexpected character `%c'"), *yytext);
+ }
+<<EOF>> { message (msg_file, (stderr, "End of file `%s'.\n",
+ yyfilename));
+ if (--include_stack_ptr < 0)
+ yyterminate ();
+ else
+ yy_include_pop () ;
+ }
+
+<STATE_GLOB>{
+ \/i? { /* return the string */
+ uchar *string;
+
+ obstack_1grow (&string_stack, '\0');
+ string = (uchar *) obstack_finish (&string_stack);
+ obstack_free (&string_stack, string);
+ token_val = xustrdup (string);
+
+ /* Decode the additional flags. */
+ insensitive_p = yytext[1] == 'i';
+
+ BEGIN INITIAL; /* Return to the regular scanning */
+ return tGLOB;
+ }
+
+ \\[0-7]{1,3} { obstack_octal_grow (&string_stack, yytext + 1); }
+ \\x[0-9a-fA-F]{1,2} { obstack_hexa_grow (&string_stack, yytext + 2); }
+ \\a { obstack_1grow (&string_stack, '\007'); }
+ \\b { obstack_1grow (&string_stack, '\b'); }
+ \\d { obstack_1grow (&string_stack, 127); }
+ \\e { obstack_1grow (&string_stack, 27); }
+ \\f { obstack_1grow (&string_stack, '\f'); }
+ \\n { obstack_1grow (&string_stack, '\n'); }
+ \\r { obstack_1grow (&string_stack, '\r'); }
+ \\t { obstack_1grow (&string_stack, '\t'); }
+ \\v { obstack_1grow (&string_stack, '\v'); }
+ \\. { obstack_1grow (&string_stack, yytext[1]); }
+
+ \n {
+ error_at_line (1, 0, yyfilename, yylineno,
+ /* TRANS: %s is ".." or <..> or /../ etc. */
+ _("end of line inside a %s"), "/../");
+ }
+
+ [^\/\n\\]+ {
+ obstack_grow (&string_stack, yytext, yyleng);
+ }
+}
+
+<STATE_FILE>{ /* string of characters */
+ \>i? { /* return the string */
+ uchar *string;
+
+ obstack_1grow (&string_stack, '\0');
+ string = (uchar *) obstack_finish (&string_stack);
+ obstack_free (&string_stack, string);
+ token_val = xustrdup (string);
+
+ /* Decode the additional flags. */
+ insensitive_p = yytext[1] == 'i';
+
+ BEGIN INITIAL; /* Return to the regular scanning */
+ return tFILE;
+ }
+
+ \\[0-7]{1,3} { obstack_octal_grow (&string_stack, yytext + 1); }
+ \\x[0-9a-fA-F]{1,2} { obstack_hexa_grow (&string_stack, yytext + 2); }
+ \\a { obstack_1grow (&string_stack, '\007'); }
+ \\b { obstack_1grow (&string_stack, '\b'); }
+ \\d { obstack_1grow (&string_stack, 127); }
+ \\e { obstack_1grow (&string_stack, 27); }
+ \\f { obstack_1grow (&string_stack, '\f'); }
+ \\n { obstack_1grow (&string_stack, '\n'); }
+ \\r { obstack_1grow (&string_stack, '\r'); }
+ \\t { obstack_1grow (&string_stack, '\t'); }
+ \\v { obstack_1grow (&string_stack, '\v'); }
+ \\. { obstack_1grow (&string_stack, yytext[1]); }
+
+ \n {
+ error_at_line (1, 0, yyfilename, yylineno,
+ _("end of line inside a %s"), "<..>");
+ }
+
+ [^>\n\\]+ {
+ obstack_grow (&string_stack, yytext, yyleng);
+ }
+}
+%%
+
+/*-----------------------------------------------------.
+| Handle the inclusion of files at the scanner level. |
+`-----------------------------------------------------*/
+
+/* Switch the scanning onto FILE, coming back to YYIN later. */
+
+static void
+yy_include_push (char *file)
+{
+ if (include_stack_ptr >= MAX_INCLUDE_DEPTH)
+ error (1, 0, _("too many includes"));
+
+ include_stack[include_stack_ptr] = YY_CURRENT_BUFFER;
+ lineno_stack[include_stack_ptr] = yylineno;
+ filename_stack[include_stack_ptr++] = yyfilename;
+
+ message (msg_file, (stderr, "%s:%d: includes %s\n",
+ yyfilename, yylineno, file));
+
+ yyfilename = file;
+ yyin = xrfopen (yyfilename);
+
+ yy_switch_to_buffer (yy_create_buffer (yyin, YY_BUF_SIZE));
+}
+
+/* Pop the inclusion stack and proceed. To be called on <<EOF>>.*/
+
+static void
+yy_include_pop (void)
+{
+ fclose (yyin);
+ yy_delete_buffer (YY_CURRENT_BUFFER);
+ yyfilename = filename_stack[include_stack_ptr];
+ yylineno = lineno_stack[include_stack_ptr];
+ yy_switch_to_buffer (include_stack[include_stack_ptr]);
+ message (msg_file, (stderr, "Back to file `%s'.\n", yyfilename));
+}
+
+
+/*----------------------.
+| Prepare the scanner. |
+`----------------------*/
+
+/* Initialize the include stack to FILE. */
+
+static inline void
+yy_open (const char *file)
+{
+ yyfilename = xstrdup (file);
+ yyin = xrfopen (yyfilename);
+ include_stack_ptr = 0;
+}
+
+/* End of the scanning. */
+
+static inline void
+yy_close (void)
+{
+ fclose (yyin);
+ free (yyfilename);
+}
+
+int
+yywrap (void)
+{
+ return 1;
+}
+
+
+void
+sheets_map_load (const char *filename)
+{
+ static int first_time = 1;
+ token_t token;
+ char *key = NULL;
+
+ if (first_time)
+ {
+ first_time = 0;
+ obstack_init (&string_stack);
+ }
+
+ yy_open (filename);
+
+ while ((token = yylex ()))
+ {
+ switch (token)
+ {
+ case tKEY:
+ key = token_val;
+ break;
+
+ case tGLOB:
+ if (!key)
+ error_at_line (1, 0, yyfilename, yylineno,
+ _("no key defined for `%s'"), quotearg (token_val));
+ sheets_map_add (token_val, false, insensitive_p, key);
+ break;
+
+ case tFILE:
+ if (!key)
+ error_at_line (1, 0, yyfilename, yylineno,
+ _("no key defined for `%s'"), quotearg (token_val));
+ sheets_map_add (token_val, true, insensitive_p, key);
+ break;
+ }
+ }
+
+ yy_close ();
+}
diff --git a/src/ssheet.c b/src/ssheet.c
new file mode 100644
index 0000000..11a9fa3
--- /dev/null
+++ b/src/ssheet.c
@@ -0,0 +1,1529 @@
+/*
+ * ssheet.c -- definition of the languages style sheets
+ *
+ * Copyright (c) 1988-93 Miguel Santana
+ * Copyright (c) 1995-99 Akim Demaille, Miguel Santana
+ *
+ */
+
+/*
+ * This file is part of a2ps.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "a2ps.h"
+#include "routines.h"
+#include "ssheet.h"
+#include "pathwalk.h"
+#include "jobs.h"
+#include "message.h"
+#include "filtdir.h"
+#include "versions.h"
+#include "document.h"
+#include "metaseq.h"
+#include "title.h"
+#include "quotearg.h"
+
+/* Suffix of the style sheet files */
+#define SSH_SUFFIX ".ssh"
+
+/* Separator of ancestors in mixed style sheets. */
+#define MIXED_SHEET_SEP ",;+"
+
+extern a2ps_job * job;
+extern struct hash_table_s * style_sheets;
+
+/* Comes from regex */
+extern char * re_syntax_table;
+
+/* This function is defined in sshparser.y, but I don't know
+ * how to make it appear in a .h file */
+struct style_sheet * parse_style_sheet PARAMS ((const char * filename));
+
+/* Computes the sum of the versions and the highest requirement
+ * of the sheet with key in KEYS */
+static inline void style_sheets_versions PARAMS ((struct darray * keys,
+ int sum [4],
+ int requirement [4]));
+
+/* return true iff OK */
+static bool style_sheet_check PARAMS ((struct style_sheet * sheet));
+
+/* We drop in the alphabets[0] an invalid value. It allows to see if
+ * the alphabets were defined or not, so that the default alphabets
+ * can be set when finalizing the sheet. Note that we cannot set the
+ * default alphabets a priori, because we need to be able to inherit
+ * from ancestors. */
+#define ALPHABET_UNDEFINED_TAG 127
+#define ALPHABET_IS_UNDEFINED(_alpha_) \
+ ((_alpha_)[0] == ALPHABET_UNDEFINED_TAG)
+#define ALPHABET_UNDEFINE(_alpha_) \
+ ((_alpha_)[0] = ALPHABET_UNDEFINED_TAG)
+
+#define DEFAULT_ALPHA1 ((const uchar *) \
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_")
+#define DEFAULT_ALPHA2 ((const uchar *) \
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789")
+
+static void
+alphabet_self_print (char *a, FILE *s)
+{
+ if (ALPHABET_IS_UNDEFINED (a))
+ fputs ("<undefined>\n", s);
+ else
+ {
+ int c;
+
+ fputc ('\"', s);
+ for (c = 0 ; c < 256 ; c++)
+ if (a [c])
+ fputc (c, s);
+ fputs ("\"\n", s);
+ }
+}
+
+#define DEFAULT_SENSITIVENESS case_insensitive
+
+struct pattern *
+new_pattern (char * pattern, size_t len)
+{
+ struct pattern * res = XMALLOC (struct pattern, 1);
+ res->pattern = pattern;
+ res->len = len;
+ return res;
+}
+
+/*
+ * The faced_string
+ */
+struct faced_string *
+faced_string_new (uchar * string, int reg_ref, struct fface_s face)
+{
+ struct faced_string * res = XMALLOC (struct faced_string, 1);
+ res->string = string;
+ res->reg_ref = reg_ref;
+ res->face = face;
+ return res;
+}
+
+/*
+ * Report a faced_string
+ */
+static void
+faced_string_self_print (struct faced_string * faced_string, FILE * stream)
+{
+ if (faced_string->string)
+ fprintf (stream, "\"%s\": ", faced_string->string);
+ else
+ fprintf (stream, "\\%d: ", faced_string->reg_ref);
+
+ fface_self_print (faced_string->face, stream);
+}
+
+inline static void
+faced_string_free (struct faced_string * faced_string)
+{
+ XFREE (faced_string->string);
+ free (faced_string);
+}
+
+/*
+ * Replace all the No_fface's by FACE
+ */
+inline static void
+faced_string_set_no_face (struct faced_string * str, struct fface_s face)
+{
+ if (fface_squ (str->face, No_fface))
+ str->face = face;
+}
+
+/************************************************************************/
+/* The version handling */
+/************************************************************************/
+void
+style_sheet_set_version (struct style_sheet * sheet,
+ const char * version_string)
+{
+ string_to_version (version_string, sheet->version);
+}
+
+/*
+ * Set the version of a2ps required for the processing of SHEET.
+ * Return false if the requirement is higher than VERSION.
+ */
+int
+style_sheet_set_requirement (struct style_sheet * sheet,
+ const char * version_string)
+{
+ int a2ps_version [4];
+
+ string_to_version (version_string, sheet->requirement);
+ string_to_version (VERSION, a2ps_version);
+
+ if (version_cmp (sheet->requirement, a2ps_version) > 0)
+ return false;
+
+ return true;
+}
+
+/************************************************************************/
+/* Rhs darray */
+/************************************************************************/
+/*
+ * New rhs array
+ */
+struct darray *
+rhs_new (void)
+{
+ struct darray * res;
+ res = da_new ("Rhs", 2, da_geometrical, 2,
+ (da_print_func_t) faced_string_self_print, NULL);
+ return res;
+}
+
+/*
+ * New rhs array with a single argument
+ */
+struct darray *
+rhs_new_single (uchar * string, int reg_ref, struct fface_s face)
+{
+ struct darray * res;
+ res = da_new ("Rhs", 2, da_geometrical, 2,
+ (da_print_func_t) faced_string_self_print, NULL);
+ da_append (res, faced_string_new (string, reg_ref, face));
+ return res;
+}
+
+/*
+ * Replace all the No_fface's by FACE
+ */
+inline static void
+rhs_set_no_face (struct darray * dest, struct fface_s face)
+{
+ size_t i;
+
+ for (i = 0 ; i < dest->len ; i++)
+ if (fface_squ (((struct faced_string *) dest->content [i])->face,
+ No_fface))
+ ((struct faced_string *) dest->content [i])->face = face;
+}
+
+/*
+ * Add a rule in the rhs array,
+ * Don't forget to scan the string, because it may have actually
+ * regex references in it, which must be resolved
+ */
+void
+rhs_add (struct darray * dest, struct faced_string * str)
+{
+ da_append (dest, str);
+}
+
+/*
+ * Report a rhs array
+ */
+void
+rhs_self_print (struct darray * rhs, FILE * stream)
+{
+ size_t i;
+
+ putc ('(', stream);
+ for (i = 0 ; i < rhs->len ; i++)
+ faced_string_self_print ((struct faced_string *) rhs->content [i], stream);
+ putc (')', stream);
+}
+
+/************************************************************************/
+/* P-rules */
+/************************************************************************/
+/*
+ * Dealing with the rules and operators
+ */
+inline static struct rule *
+rule_new_internal_word (uchar * word,
+ struct darray * rhs)
+{
+ struct rule * res = XMALLOC (struct rule, 1);
+
+ res->word = word;
+ res->regex = NULL;
+ res->rhs = rhs;
+ return res;
+}
+
+/*
+ * Dealing with the rules and operators
+ */
+inline static struct rule *
+rule_new_internal_regexp (struct pattern *pattern,
+ char *regexp, int regexp_len,
+ struct darray *rhs,
+ const char *filename, size_t line)
+{
+ struct rule *res = XMALLOC (struct rule, 1);
+ const char *error_msg;
+
+ /* This is a regular expression. We want to keep the original
+ * pattern to ease the debugging of a style sheet */
+ res->word = (uchar *) pattern->pattern;
+
+ /* Build the regex structure, and compile the pattern */
+ res->regex = XMALLOC (struct re_pattern_buffer, 1);
+ res->regex->translate = NULL;
+ res->regex->fastmap = NULL;
+ res->regex->buffer = NULL;
+ res->regex->allocated = 0;
+
+ error_msg = re_compile_pattern (regexp, regexp_len, res->regex);
+ /* The pattern is nul terminated, no fear to have */
+ if (error_msg)
+ error_at_line (1, 0, filename, line,
+ _("cannot compile regular expression `%s': %s"),
+ regexp, error_msg);
+ free (pattern);
+ res->rhs = rhs;
+ return res;
+}
+
+/*
+ * Dealing with the rules and operators
+ */
+struct rule *
+rule_new (uchar * word, struct pattern * pattern,
+ struct darray * rhs,
+ const char *filename, size_t line)
+{
+ if (pattern)
+ return rule_new_internal_regexp (pattern,
+ pattern->pattern, pattern->len,
+ rhs,
+ filename, line);
+ else
+ return rule_new_internal_word (word,
+ rhs);
+}
+
+
+/*-------------------------------------------------------------------.
+| Dealing with the rules and operators. This is pretty much the |
+| same as the previous case, but the difference is that the regexp |
+| must be built appending a `\\b' at the end, to make sure that, for |
+| instance, as a keyword matcher `/c*f/' does not match `ccfe': the |
+| keyword is not separated. |
+`-------------------------------------------------------------------*/
+
+struct rule *
+keyword_rule_new (uchar * word, struct pattern * pattern,
+ struct darray * rhs,
+ const char *filename, size_t line)
+{
+ int pattern_len = 0;
+ char * pattern_to_compile = NULL;
+
+ if (pattern)
+ {
+ pattern_len = pattern->len + strlen ("\\b()\\b");
+ pattern_to_compile = ALLOCA (char, pattern_len + 1);
+ sprintf (pattern_to_compile, "\\b(%s)\\b", pattern->pattern);
+ return rule_new_internal_regexp (pattern,
+ pattern_to_compile, pattern_len,
+ rhs,
+ filename, line);
+ }
+ else
+ return rule_new_internal_word (word,
+ rhs);
+}
+
+
+/*--------------.
+| Free a rule. |
+`--------------*/
+
+static void
+free_rule (struct rule * rule)
+{
+ XFREE (rule->word);
+ if (rule->regex)
+ {
+ regfree (rule->regex);
+ free (rule->regex);
+ }
+ da_free (rule->rhs, (da_map_func_t) faced_string_free);
+ free (rule);
+}
+
+/*
+ * Compare two rules.
+ * Note: they should be string-rules, not regex-rule
+ */
+static int
+rule_cmp (struct rule * k1, struct rule * k2)
+{
+ return ustrcmp (k1->word, k2->word);
+}
+
+static void
+rule_self_print (struct rule * rule, FILE * stream)
+{
+ if (rule->regex)
+ fprintf (stream, "/%s/ -> ", rule->word);
+ else
+ fprintf (stream, "\"%s\" -> ", rule->word);
+ rhs_self_print (rule->rhs, stream);
+}
+
+/*
+ * Replace all the No_fface's that may be in the array of
+ * rules, to FACE
+ */
+static inline void
+rule_set_no_face (struct rule * rule, struct fface_s face)
+{
+ rhs_set_no_face (rule->rhs, face);
+}
+
+static void
+rules_set_no_faces (struct darray * arr, struct fface_s face)
+{
+ size_t i;
+
+ for (i = 0 ; i < arr->len ; i++)
+ rule_set_no_face (((struct rule *) arr->content[i]), face);
+}
+
+
+/*
+ * `words' are a specialization of darray, to capture the fact
+ * that it is faster to look for a prefix of a string taking
+ * advantage to know that it can only be in the interval
+ * of candidates that start with the same first letter
+ *
+ */
+struct words *
+words_new (/* Regular darray parameters */
+ const char * name_strings, const char * name_regexps,
+ size_t size, size_t increment)
+{
+ int c;
+ struct words * res = XMALLOC (struct words, 1);
+
+ /* Initialize the underlying darray of strings */
+ res->strings = da_new (name_strings, size,
+ da_linear, increment,
+ (da_print_func_t) rule_self_print,
+ (da_cmp_func_t) rule_cmp);
+
+ /* Initialize the underlying darray of regexps */
+ res->regexps = da_new (name_regexps, size,
+ da_linear, increment,
+ (da_print_func_t) rule_self_print,
+ (da_cmp_func_t) NULL);
+
+ /* Set min and max intervals to void values */
+ for (c = 0 ; c < 256 ; c ++)
+ res->min[c] = res->max[c] = NULL;
+
+ return res;
+}
+
+static inline void
+words_erase (struct words * words)
+{
+ /* Do not free the items, there may be pointers onto them */
+ da_erase (words->strings);
+ da_erase (words->regexps);
+
+ free (words);
+}
+
+void
+words_free (struct words * words)
+{
+ da_free (words->strings, (da_map_func_t) free_rule);
+ da_free (words->regexps, (da_map_func_t) free_rule);
+ free (words);
+}
+
+static void
+words_self_print (struct words * words, FILE * stream)
+{
+ if (words->regexps->len)
+ da_self_print (words->regexps, stream);
+ if (words->strings->len)
+ da_self_print (words->strings, stream);
+}
+
+void
+words_add_string (struct words * words, struct rule * rule)
+{
+ da_append (words->strings, rule);
+}
+
+void
+words_add_regex (struct words * words, struct rule * rule)
+{
+ da_append (words->regexps, rule);
+}
+
+void
+words_set_no_face (struct words * words, struct fface_s face)
+{
+ rules_set_no_faces (words->strings, face);
+ rules_set_no_faces (words->regexps, face);
+}
+
+/*
+ * Add the content of NEW in WORDS.
+ * If in WORDS there is yet a rule with the same string matcher
+ * than in NEW, then the one of NEW is the winner
+ * No special care is made for the regex matcher
+ * NEW is destroyed.
+ */
+void
+words_merge_rules_unique (struct words * words, struct words * new)
+{
+ /* Select those that are regexps */
+ da_concat (words->regexps, new->regexps);
+
+ /* Include the strings */
+ da_qsort (new->strings);
+ da_merge (words->strings, new->strings,
+ (da_map_func_t) free_rule, da_2_wins);
+
+ /* Empty the structure, but don't free, since words->regexps
+ * keeps a reference to them */
+ words_erase (new);
+}
+
+/*
+ * Finish setting up the keywords recognition mechanism
+ */
+static void
+words_finalize (struct words * list)
+{
+ size_t i;
+ struct rule ** content;
+
+ /* Sort in alphabetical order */
+ da_qsort (list->strings);
+
+ /* Build two arrays which contains for each letter, its first
+ * and last occurence index in (*DEST) array */
+ content = (struct rule **) list->strings->content;
+ for (i = 0 ; i < list->strings->len ; i++) {
+ if (list->min [content[i]->word[0]] == NULL)
+ list->min [content[i]->word[0]] = content + i;
+ list->max [content[i]->word[0]] = content + i;
+ }
+}
+
+/************************************************************************/
+/* Handling the ancestors of a style sheet */
+/************************************************************************/
+static struct darray *
+ancestors_new (void)
+{
+ return da_new ("Ancestors", 2,
+ da_linear, 2,
+ (da_print_func_t) da_str_print, NULL);
+}
+
+static void
+ancestors_finalize (struct style_sheet * sheet)
+{
+ int i;
+ struct style_sheet * ancestor = NULL;
+
+ if (sheet->ancestors->len == 0)
+ return; /* No inheritance */
+
+ /* The string defined rules must be read in order, so that the last
+ * definition overwrites the first (and not the converse) */
+ for (i = 0 ; i < (int) sheet->ancestors->len ; i++)
+ {
+ ancestor = get_style_sheet ((char *) sheet->ancestors->content [i]);
+ /* It is possible that the ancestors is not available */
+ if (!ancestor)
+ continue;
+
+ /* Inherit from their string keywords. The keywords we already
+ have are the oldest, hence the one to keep. This is why
+ da_1_wins. Do not free the item, coz' your being killing
+ another style sheet! */
+ da_merge (sheet->keywords->strings, ancestor->keywords->strings,
+ NULL, da_1_wins);
+ /* Inherit from their string operators */
+ da_merge (sheet->operators->strings, ancestor->operators->strings,
+ NULL, da_1_wins);
+ }
+
+ /* We want to inherit from the _last_ alphabets if it has not been
+ defined in this sheet. The problem is when there are several
+ ancestors, and some are missing. To maximize the chance to get
+ something defined last, we drop the tests for alphabets and
+ sensitiveness in the backward loop. The cost is low (in general
+ there are few ancestors), and ensures that the last existing (not
+ the last required) ancestor defines the syntactic definitions */
+ for (i = (int) sheet->ancestors->len - 1; i >= 0 ; i--)
+ {
+ ancestor = get_style_sheet ((char *) sheet->ancestors->content [i]);
+ if (!ancestor)
+ continue;
+
+ /* Inherit of the _last_ alphabets if it has not been defined in
+ * this sheet. */
+ if (ALPHABET_IS_UNDEFINED (sheet->alpha1))
+ memcpy (sheet->alpha1, ancestor->alpha1, sizeof (uchar) * 256);
+ if (ALPHABET_IS_UNDEFINED (sheet->alpha2))
+ memcpy (sheet->alpha2, ancestor->alpha2, sizeof (uchar) * 256);
+
+ /* Inherit of the _last_ case sensitivity */
+ if (sheet->sensitiveness == case_undefined)
+ sheet->sensitiveness = ancestor->sensitiveness;
+
+ /* Inherit from their regex keywords */
+ da_prefix (sheet->keywords->regexps,
+ ancestor->keywords->regexps);
+
+ /* Inherit from their regex operators */
+ da_prefix (sheet->operators->regexps,
+ ancestor->operators->regexps);
+
+ /* Inherit from their sequences */
+ /* They must be read in reverse order */
+ da_prefix (sheet->sequences, ancestor->sequences);
+ }
+}
+
+/************************************************************************/
+/* Creating, loading a style sheet */
+/************************************************************************/
+/*
+ * Create a sequence
+ */
+struct sequence *
+sequence_new (struct rule * Open,
+ struct fface_s in_face,
+ struct words * Close,
+ struct words * exceptions)
+{
+ struct sequence * res = XMALLOC (struct sequence, 1);
+
+ /* Make sure to set the face of those with No_fface */
+ rule_set_no_face (Open, in_face);
+ res->open = Open;
+
+ res->face = in_face;
+
+ words_set_no_face (exceptions, in_face);
+ words_finalize (exceptions);
+ res->exceptions = exceptions;
+
+ words_set_no_face (Close, in_face);
+ words_finalize (Close);
+ res->close = Close;
+ return res;
+}
+
+/*
+ * Release a sequence.
+ */
+void
+free_sequence (struct sequence * sequence)
+{
+ free_rule (sequence->open);
+ words_free (sequence->close);
+ words_free (sequence->exceptions);
+ free (sequence);
+}
+
+/*
+ * Build the usual C's string and char with their escapes
+ */
+#define C_add_exception(_excep_) \
+ words_add_string (res, \
+ rule_new (xustrdup (_excep_), NULL, \
+ rhs_new_single (xustrdup (_excep_), 0, String_fface),\
+ __FILE__, __LINE__));
+
+static struct words *
+new_C_exceptions (void)
+{
+ struct words * res;
+
+ res = words_new ("C usual exceptions: strings",
+ "C usual exceptions: regexps",
+ 3, 3);
+ C_add_exception ("\\\'");
+ C_add_exception ("\\\\");
+ C_add_exception ("\\\"");
+
+ words_finalize (res);
+ return res;
+}
+
+struct sequence *
+new_C_string_sequence (const char * delimitor)
+{
+ struct sequence * res = XMALLOC (struct sequence, 1);
+ res->open = rule_new (xustrdup (delimitor), NULL,
+ rhs_new_single (NULL, 0, Plain_fface),
+ __FILE__, __LINE__);
+ res->face = String_fface;
+ res->exceptions = new_C_exceptions ();
+ res->close = words_new ("C Close: strings", "C Close: regex", 5, 5);
+ words_add_string (res->close,
+ rule_new (xustrdup (delimitor), NULL,
+ rhs_new_single (NULL, 0, Plain_fface),
+ __FILE__, __LINE__));
+ words_finalize (res->close);
+ return res;
+}
+
+void
+sequence_self_print (struct sequence * tmp, FILE * stream)
+{
+ rule_self_print (tmp->open, stream);
+ fputs (" ->", stream);
+ fface_self_print (tmp->face, stream);
+ fputs (":\n", stream);
+ words_self_print (tmp->exceptions, stream);
+ words_self_print (tmp->close, stream);
+}
+
+/************************************************************************/
+/* Creating, loading a style sheet */
+/************************************************************************/
+/*
+ * Dealing with the style sheets
+ */
+struct style_sheet *
+new_style_sheet (const uchar * name)
+{
+ NEW (struct style_sheet, res);
+
+ res->name = name;
+ res->author = UNULL;
+ version_set_to_null (res->version);
+ res->documentation = UNULL;
+ version_set_to_null (res->requirement);
+ res->ancestors = ancestors_new ();
+ res->sensitiveness = case_undefined;
+
+ ALPHABET_UNDEFINE (res->alpha1);
+ ALPHABET_UNDEFINE (res->alpha2);
+
+ res->keywords = words_new ("Keywords: Strings", "Keywords: Regexps",
+ 100, 100);
+ res->operators = words_new ("Operators: Strings", "Operators: Regexps",
+ 100, 100);
+
+ res->sequences = da_new ("Sequences", 100,
+ da_linear, 100,
+ (da_print_func_t) sequence_self_print, NULL);
+
+ return res;
+}
+
+
+/*---------------------------------------------------------.
+| Build a style sheet which is only defined by ancestors. |
+`---------------------------------------------------------*/
+
+static char *
+style_sheet_mixed_new (const uchar * ancestors)
+{
+ struct style_sheet *sheet, *ancestor;
+ char *ancestor_key, *key, *cp;
+ char *ancestors_keys;
+ struct darray *ancestors_array;
+
+ /* It cannot be longer than ancestors_keys. */
+ key = ALLOCA (char, ustrlen (ancestors) + 1);
+ astrcpy (ancestors_keys, ancestors);
+
+ /* Create the darray of ancestors keys, and build the final key. */
+ ancestors_array = ancestors_new ();
+ ancestor_key = strtok (ancestors_keys, MIXED_SHEET_SEP);
+ da_append (ancestors_array, ancestor_key);
+ ancestor = get_style_sheet (ancestor_key);
+ cp = stpcpy (key, ancestor->key);
+
+ while ((ancestor_key = strtok (NULL, MIXED_SHEET_SEP)))
+ {
+ da_append (ancestors_array, ancestor_key);
+ ancestor = get_style_sheet (ancestor_key);
+ *cp++ =',';
+ cp = stpcpy (cp, ancestor->key);
+ }
+ *cp = '\0';
+ key = xstrdup (key);
+
+ /* Create the style sheet. */
+ message (msg_sheet,
+ (stderr, "Creating a mixed style sheet \"%s\"\n", key));
+ /* Its name is its key. */
+ sheet = new_style_sheet ((uchar *) key);
+ sheet->key = strdup (key);
+ da_concat (sheet->ancestors, ancestors_array);
+ da_erase (ancestors_array);
+ style_sheet_finalize (sheet);
+
+ return key;
+}
+
+/*-----------------------------------------------------------------.
+| Once a style sheet has been read, make it usable (sorts etc.). |
+| |
+| NOTE: It must _not_ be called from the parser, since it may call |
+| another time the parser, in case one of the ancestors are not |
+| known. |
+`-----------------------------------------------------------------*/
+void
+style_sheet_finalize (struct style_sheet * sheet)
+{
+ message (msg_sheet,
+ (stderr, "Finalizing style sheet \"%s\" (%s)\n",
+ sheet->name, sheet->key));
+
+ ancestors_finalize (sheet);
+
+ /* Ensure a default alphabet */
+ if (ALPHABET_IS_UNDEFINED (sheet->alpha1))
+ string_to_array (sheet->alpha1, DEFAULT_ALPHA1);
+ if (ALPHABET_IS_UNDEFINED (sheet->alpha2))
+ string_to_array (sheet->alpha2, DEFAULT_ALPHA2);
+
+ /* Ensure a default sensitivity */
+ if (sheet->sensitiveness == case_undefined)
+ sheet->sensitiveness = DEFAULT_SENSITIVENESS;
+
+ words_finalize (sheet->keywords);
+ words_finalize (sheet->operators);
+ if (msg_test (msg_sheet))
+ {
+ fprintf (stderr, "---------- After Finalization of %s\n", sheet->key);
+ style_sheet_self_print (sheet, stderr);
+
+ message (msg_sheet,
+ (stderr, "Checking coherence of \"%s\" (%s)\n",
+ sheet->name, sheet->key));
+ if (style_sheet_check (sheet))
+ message (msg_sheet, (stderr, "\"%s\" (%s) is sane.\n",
+ sheet->name, sheet->key));
+ else
+ message (msg_sheet, (stderr, "\"%s\" (%s) is corrupted.\n",
+ sheet->name, sheet->key));
+ fprintf (stderr, "---------- End of Finalization of %s\n", sheet->key);
+ }
+
+ /* Put it in the sheets' table. */
+ hash_insert (style_sheets, sheet);
+}
+
+/*
+ * Loading a style sheet either looking for its path
+ * thanks to its key, or directly from its path.
+ */
+static struct style_sheet *
+load_style_sheet (const char * pseudo_key)
+{
+ struct style_sheet * res;
+
+ /* Is the key a real key, or a path? */
+ if (strsuffix (pseudo_key, SSH_SUFFIX))
+ {
+ /* This style sheet has to have its path as key. This is used
+ to ease to allow specifying a style sheet by its real path,
+ instead of allowing key based file search. It is also used
+ to to check that an ssh file is OK, from a2ps-mode in
+ emacs.*/
+ res = parse_style_sheet (pseudo_key);
+ }
+ else
+ {
+ /* This is the regular process: find the file */
+ char * path = pw_find_file (job->common.path, pseudo_key, SSH_SUFFIX);
+ if (!path)
+ {
+ char *file;
+ astrcat2 (file, pseudo_key, SSH_SUFFIX);
+ error (0, 0, _("cannot find file `%s'"), quotearg (file));
+ return NULL;
+ }
+ res = parse_style_sheet (path);
+ free (path);
+ }
+
+ /* Now, finalize it, and store it in the hash tab */
+ res->key = strdup (pseudo_key);
+ style_sheet_finalize (res);
+
+ return res;
+}
+
+/************************************************************************/
+/* Reporting information about the style sheets */
+/************************************************************************/
+
+/* Compare the names of two style sheets */
+
+static int
+sheet_name_cmp (const char * key1, const char * key2)
+{
+ return strcasecmp ((const char *) get_style_sheet (key1) -> name,
+ (const char *) get_style_sheet (key2) -> name);
+}
+
+/*
+ * Report everything (used in -v5 at end of parsing)
+ */
+void
+style_sheet_self_print (struct style_sheet * sheet, FILE * stream)
+{
+ fprintf (stream, "Style sheet \"%s\" (%s), version ",
+ sheet->name, sheet->key);
+ version_self_print (sheet->version, stream);
+ putc ('\n', stream);
+ if (!IS_EMPTY (sheet->author))
+ fprintf (stream, "Written by %s\n", sheet->author);
+ if (sheet->ancestors->len > 0)
+ {
+ size_t i;
+ fprintf (stream, "It inherits from: ");
+ for (i = 0 ; i < sheet->ancestors->len ; i++)
+ fprintf (stream, "%s%s",
+ i ? ", " : "",
+ (char *) sheet->ancestors->content [i]);
+ fputs (".\n", stream);
+ }
+
+ fprintf (stream, "Case %ssensitive\n",
+ sheet->sensitiveness == case_insensitive ? "in" : "");
+
+ /* Alphabets */
+ fputs ("First alphabet is ", stream);
+ alphabet_self_print (sheet->alpha1, stream);
+ fputs ("Second alphabet is ", stream);
+ alphabet_self_print (sheet->alpha2, stream);
+
+ words_self_print (sheet->keywords, stream);
+ words_self_print (sheet->operators, stream);
+ if (!da_is_empty (sheet->sequences))
+ da_self_print (sheet->sequences, stream);
+}
+
+/*
+ * Print a short signature (i.e., name, author etc.)
+ */
+static void
+style_sheet_print_signature (FILE * stream, struct style_sheet * sheet)
+{
+ int i, title_bar_len;
+
+ if (!version_null_p (sheet->version))
+ {
+ title_bar_len = (strlen (" (.ssh version )")
+ + ustrlen (sheet->name)
+ + strlen (sheet->key)
+ + version_length (sheet->version));
+ fprintf (stream, "%s (%s.ssh version ",
+ sheet->name, sheet->key);
+ version_self_print (sheet->version, stream);
+ fputs (")\n", stream);
+ }
+ else
+ {
+ title_bar_len = (strlen (" (.ssh)")
+ + ustrlen (sheet->name)
+ + strlen (sheet->key));
+ fprintf (stream, "%s (%s.ssh)\n",
+ sheet->name, sheet->key);
+ }
+ for (i = 0 ; i < title_bar_len ; i++)
+ putc ('-', stream);
+ putc ('\n', stream);
+
+ authors_print_plain (sheet->author, stream, "Written by ");
+
+ documentation_print_plain (sheet->documentation, "%s\n", stream);
+ fputs ("\n", stream);
+}
+
+/*
+ * List the style sheet names (for option -E)
+ */
+void
+list_style_sheets_short (FILE * stream)
+{
+ fputs (_("Known Style Sheets"), stream);
+ putc ('\n', stream);
+ pw_lister_on_suffix (stream, job->common.path, SSH_SUFFIX);
+}
+
+/*
+ * List the style sheets
+ */
+void
+list_style_sheets_long (FILE * stream)
+{
+ struct style_sheet * sheet;
+ struct darray * entries;
+ size_t i;
+
+ entries = pw_glob_on_suffix (job->common.path, SSH_SUFFIX);
+
+ /* Sort them by name (not key) */
+ entries->cmp = (da_cmp_func_t) sheet_name_cmp;
+ da_qsort (entries);
+
+ title (stream, '=', true, _("Known Style Sheets"));
+ putc ('\n', stream);
+
+ for (i = 0 ; i < entries->len ; i++)
+ {
+ sheet = get_style_sheet ((char *) entries->content[i]);
+ style_sheet_print_signature (stream, sheet);
+ }
+ da_free (entries, (da_map_func_t) free);
+}
+
+/************************************************************************/
+/* Report in HTML format */
+/************************************************************************/
+/*
+ * Print a short signature (i.e., name, author etc.)
+ * In html format
+ */
+static void
+style_sheet_html_print_signature (FILE * stream, struct style_sheet * sheet)
+{
+ if (version_null_p (sheet->version))
+ fprintf (stream,
+ "<li><p><strong><a href=\"%s.ssh\" name=\"%s\">%s</a></strong>.</p>\n",
+ sheet->key, sheet->key, sheet->name);
+ else
+ {
+ fprintf (stream,
+ "<li><p><strong><a href=\"%s.ssh\" name=\"%s\">%s</a></strong> version ",
+ sheet->key, sheet->key, sheet->name);
+ version_self_print (sheet->version, stream);
+ fputs (".</p>\n", stream);
+ }
+
+ if (!IS_EMPTY(sheet->author)
+ || !version_null_p(sheet->requirement)
+ || (sheet->ancestors->len > 0))
+ {
+ fputs ("<p>", stream);
+ authors_print_html (sheet->author, stream, "Written by ");
+ if (!version_null_p (sheet->requirement))
+ {
+ fputs ("It requires a2ps version ", stream);
+ version_self_print (sheet->requirement, stream);
+ fputs (".\n", stream);
+ }
+ if (sheet->ancestors->len > 0)
+ {
+ size_t i;
+ fputs ("It inherits from: ", stream);
+ for (i = 0 ; i < sheet->ancestors->len ; i++)
+ fprintf (stream, "%s<a href=\"#%s\">%s.ssh</a>",
+ i ? ", " : "",
+ (char *) sheet->ancestors->content [i],
+ (char *) sheet->ancestors->content [i]);
+ fputs (".\n", stream);
+ }
+ fputs ("</p>", stream);
+ }
+
+ documentation_print_html (sheet->documentation, "<p>%s</p>\n", stream);
+ fputs ("</li>\n\n", stream);
+}
+
+/*
+ * List the style sheets in html format
+ * I have a conscience problem wrt this. This is made to ease
+ * my task, but actually it has not much to do with a2ps itself :(
+ */
+void
+list_style_sheets_html (FILE * stream)
+{
+ struct style_sheet * sheet;
+ struct darray * entries;
+ size_t i;
+ version_t version_index, requirement;
+ int rows;
+
+ entries = pw_glob_on_suffix (job->common.path, SSH_SUFFIX);
+
+ style_sheets_versions (entries, version_index, requirement);
+
+ /* Sort them by name, not key. */
+ entries->cmp = (da_cmp_func_t) sheet_name_cmp;
+ da_qsort (entries);
+
+ /*
+ * The HTML header. It should definitely be taken out of here.
+ */
+ fputs ((char *) expand_user_string (job,
+ CURRENT_FILE (job),
+ "sheets.html generation",
+"<html>\n\
+#{html.begin.hook}\n\
+<head>\n\
+ <title>#{html.title:-GNU a2ps language support}</title>\n\
+</head>\n\
+\n\
+<h1 align=\\\"CENTER\\\">\n\
+#{html.title.1:-GNU a2ps language support}\n\
+</h1>\n\
+#{html.hline:-<hline>}\n\
+<h2>Current <a href=\"sheets.mp\">sheets.map</a></h2>\n\
+<p>It is the list of rules to decide what style sheet to use.</p>\n"), stream);
+
+ /*
+ * The short list, presented as a table
+ */
+ fputs ((char *) expand_user_string (job,
+ CURRENT_FILE (job),
+ "sheets.html generation",
+"\
+#{html.hline:-<hline>}\n\
+<h2>Sumary of current style sheets</h2>\n\
+<p>There is a <a href=\"sheets.tar.gz\">package</a> which contains \
+them all. Its index (sum of the style sheets version number) is \
+<strong>"), stream);
+ version_self_print (version_index, stream);
+ fputs ("</strong>, and the highest requirement is a2ps version ", stream);
+ version_self_print (requirement, stream);
+ fputs (". Links point to their detailed exposure.</p>\n", stream);
+
+ /* How many rows? Let's make two columns */
+ rows = entries->len / 3 + 1;
+
+ fputs ("<table border=\"0\" cellpadding=\"0\"><tr>\n", stream);
+ for (i = 0 ; i < entries->len ; /* Nothing */)
+ {
+ fputs ("<td valign=\"top\"><ul>\n", stream);
+ do
+ {
+ sheet = get_style_sheet ((char *) entries->content[i]);
+ fprintf (stream, "<li><a href=\"#%s\">%s <code>",
+ sheet->key, sheet->name);
+ version_self_print (sheet->version, stream);
+ fputs ("</a></code></li>\n", stream);
+ }
+ while ((++i % rows) && (i < entries->len));
+ fputs ("</ul></td>\n", stream);
+ }
+ fputs ("</tr></table>\n", stream);
+
+ /*
+ * The real detail list
+ */
+ fputs ((char *) expand_user_string (job,
+ CURRENT_FILE (job),
+ "sheets.html generation",
+"\
+#{html.hline:-<hline>}\n\
+<h2>Detailed list of current style sheets</h2>\n"), stream);
+ fputs ("Links point to their files.</p>\n", stream);
+
+ fputs ("<ul>\n", stream);
+ for (i = 0 ; i < entries->len ; i++)
+ {
+ sheet = get_style_sheet ((char *) entries->content[i]);
+ style_sheet_html_print_signature (stream, sheet);
+ }
+ fputs ("</ul>\n", stream);
+
+ fputs ((char *) expand_user_string (job,
+ CURRENT_FILE (job),
+ "sheets.html generation",
+"\
+#{html.end.hook}\n\
+</body>\n\
+</html>\n"), stream);
+
+ da_free (entries, (da_map_func_t) free);
+}
+
+/************************************************************************/
+/* Report in Texinfo format */
+/************************************************************************/
+/*
+ * Print a short signature (i.e., name, author etc.)
+ * In texinfo format
+ */
+static void
+style_sheet_texinfo_print_signature (FILE * stream,
+ struct style_sheet * sheet)
+{
+ fprintf (stream,
+ "@deftp {Style Sheet} {%s} (@file{%s.ssh})\n",
+ sheet->name, sheet->key);
+
+ /* Report details (version numbers, ancestors...) only if
+ * verbose mode for sheets */
+ if (!IS_EMPTY(sheet->author)
+ || (msg_test (msg_sheet)
+ && (!version_null_p (sheet->requirement)
+ || (sheet->ancestors->len > 0))))
+ {
+ authors_print_texinfo (sheet->author, stream, "Written by ");
+ if (msg_test (msg_sheet))
+ {
+ if (!version_null_p (sheet->requirement))
+ {
+ fputs ("It requires @code{a2ps} version ", stream);
+ version_self_print (sheet->requirement, stream);
+ fputs (". \n", stream);
+ }
+ if (sheet->ancestors->len > 0)
+ {
+ size_t i;
+ fputs ("It inherits from: ", stream);
+ for (i = 0 ; i < sheet->ancestors->len ; i++)
+ fprintf (stream, "%s@file{%s.ssh}",
+ i ? ", " : "",
+ (char *) sheet->ancestors->content [i]);
+ fputs (". \n", stream);
+ }
+ }
+ }
+
+ documentation_print_texinfo (sheet->documentation, "%s\n", stream);
+
+ fputs ("@end deftp\n\n", stream);
+}
+
+/*
+ * List the style sheets in Texinfo format
+ */
+void
+list_style_sheets_texinfo (FILE * stream)
+{
+ struct style_sheet * sheet;
+ struct darray * entries;
+ size_t i;
+ version_t version_index, requirement;
+
+ entries = pw_glob_on_suffix (job->common.path, SSH_SUFFIX);
+
+ /* Sort them by name (not key) */
+ entries->cmp = (da_cmp_func_t) sheet_name_cmp;
+ da_qsort (entries);
+
+ style_sheets_versions (entries, version_index, requirement);
+
+ /* Report details (version numbers etc.) only if verbose
+ * mode is set for sheets */
+ if (msg_test (msg_sheet))
+ {
+ fputs ("\
+The current index (sum of all the style sheets version number) is ", stream);
+ version_self_print (version_index, stream);
+ fputs (" and the highest requirement is a2ps version ", stream);
+ version_self_print (requirement, stream);
+ fputs (".\n", stream);
+
+ }
+
+ for (i = 0 ; i < entries->len ; i++) {
+ sheet = get_style_sheet ((char *) entries->content[i]);
+ style_sheet_texinfo_print_signature (stream, sheet);
+ }
+
+ da_free (entries, (da_map_func_t) free);
+}
+
+/************************************************************************/
+/* Perform some tests on the style sheets */
+/************************************************************************/
+/*
+ * Check that a darray of rules is in lower case
+ * (true for success)
+ */
+static bool
+check_rules_lower_case (const char * name, struct darray * rules)
+{
+ size_t i;
+ bool res = true;
+
+ for (i = 0 ; i < rules->len ; i++)
+ if (!is_strlower (((struct rule *) rules->content[i])->word)) {
+ error (0, 0,
+ "%s.ssh:`%s' uses upper case characters",
+ name, ((struct rule *) rules->content[i])->word);
+ res = false;
+ }
+ return res;
+}
+
+/*
+ * Check that WORDS is all in lower case
+ */
+static bool
+check_words_lower_case (const char * name, struct words * words)
+{
+ return (check_rules_lower_case (name, words->strings)
+ && check_rules_lower_case (name, words->regexps));
+}
+
+/*
+ * Check that SEQUENCE is all in lower case
+ */
+static bool
+check_sequence_lower_case (const char * name, struct sequence * sequence)
+{
+ bool res = true;
+
+ if (!is_strlower (sequence->open->word)) {
+ error (0, 0,
+ "%s.ssh:`%s' uses upper case characters",
+ name, sequence->open->word);
+ res = false;
+ }
+
+ res &= check_words_lower_case (name, sequence->exceptions);
+ res &= check_words_lower_case (name, sequence->close);
+
+ return res;
+}
+
+static bool
+check_sequences_lower_case (const char * name, struct darray * sequences)
+{
+ size_t i;
+ bool res = true;
+
+ for (i = 0 ; i < sequences->len ; i++)
+ res &= check_sequence_lower_case (name,
+ (struct sequence *) sequences->content [i]);
+
+ return res;
+}
+
+/*
+ * Check that keywords are in lower case when lang is
+ * case insensitive (returns 0 for failure)
+ */
+static bool
+check_sensitivity (struct style_sheet * sheet)
+{
+ bool res = true;
+
+ if (sheet->sensitiveness == case_sensitive)
+ return true;
+
+ /* The language is case insensitive: there should be only
+ * lower case rules.
+ * I know \B is legal in the regex. But I prefer still
+ * making the test: those who know how to use \B will have
+ * no problems to understand that the test is wrong, not them. */
+ res &= check_words_lower_case (sheet->key, sheet->keywords);
+ res &= check_words_lower_case (sheet->key, sheet->operators);
+ res &= check_sequences_lower_case (sheet->key, sheet->sequences);
+
+ return res;
+}
+
+
+static bool
+check_rules_doubles (const char * name, struct darray * rules)
+{
+ size_t i;
+ bool res = true;
+
+ for (i = 1 ; i < rules->len ; i++)
+ if (!ustrcmp (((struct rule *) rules->content [i - 1])->word,
+ ((struct rule *) rules->content [i])->word))
+ {
+ res = false;
+ error (0, 0, "%s.ssh:`%s' is defined twice",
+ name, ((struct rule *) rules->content [i])->word);
+ }
+ return res;
+}
+
+
+static bool
+check_words_doubles (const char * name, struct words * words)
+{
+ return (check_rules_doubles (name, words->strings)
+ && check_rules_doubles (name, words->regexps));
+}
+
+/*
+ * Check that there are no doublons in the style sheets
+ */
+static bool
+check_doubles (struct style_sheet * sheet)
+{
+ bool res = true;
+
+ res &= check_words_doubles (sheet->key, sheet->keywords);
+ res &= check_words_doubles (sheet->key, sheet->operators);
+
+ return res;
+}
+
+/*
+ * Return a correctness result upon SHEET
+ * (0: failure, 1: correct)
+ */
+static bool
+style_sheet_check (struct style_sheet * sheet)
+{
+ return check_doubles (sheet) && check_sensitivity (sheet);
+}
+
+/************************************************************************/
+/* Handling of the hash table of */
+/* the style sheets */
+/************************************************************************/
+/*
+ * We want to store the yet read style sheets in an hash table
+ */
+static unsigned long
+sheet_hash_1 (void const *key)
+{
+ return_STRING_HASH_1 (((const struct style_sheet *)key)->key);
+}
+
+static unsigned long
+sheet_hash_2 (void const *key)
+{
+ return_STRING_HASH_2 (((const struct style_sheet *)key)->key);
+}
+
+static int
+sheet_hash_cmp (void const *x, void const *y)
+{
+ return_STRING_COMPARE (((const struct style_sheet *)x)->key,
+ ((const struct style_sheet *)y)->key);
+}
+
+/*
+ * Create the hash table
+ */
+struct hash_table_s *
+new_style_sheets (void)
+{
+ struct hash_table_s * res;
+ res = XMALLOC (hash_table, 1);
+ hash_init (res, 8,
+ sheet_hash_1, sheet_hash_2, sheet_hash_cmp);
+ return res;
+}
+
+/*
+ * Make sure the style sheet SHEET is in the hash table
+ */
+static void
+require_style_sheet (const char * key)
+{
+ struct style_sheet * item;
+ struct style_sheet token;
+
+ if (strequ (key, "plain"))
+ return;
+
+ token.key = (char *) key;
+ item = (struct style_sheet *) hash_find_item (style_sheets, &token);
+
+ if (item == NULL)
+ {
+ /* The style has never been seen before, then load it through a
+ correct call to yyparse, which in turn is in charge of
+ putting the newly read style in the hash table. Hence, look
+ for it again. An error at this point is really an error. */
+ item = load_style_sheet (key);
+
+ if (item == NULL)
+ error (0, 0,
+ _("cannot find style sheet `%s': using plain style"), key);
+ }
+
+ return;
+}
+
+/*
+ * return the style sheet bearing this name
+ * autoload it if not yet read.
+ * If the sheet cannot be found, return NULL
+ */
+struct style_sheet *
+get_style_sheet (const char * key)
+{
+ struct style_sheet * item;
+ struct style_sheet token;
+
+ if (strequ (key, "plain"))
+ return NULL;
+
+ /* There is some specials magic to build on the fly mixed style
+ sheets, for instance `-Email,sh' build a new style sheet which is
+ only defined by:
+ ancestors are
+ mail, sh
+ end ancestors.
+ In this case the key become `mail,sh'.
+ */
+ if (strpbrk (key, MIXED_SHEET_SEP))
+ key = style_sheet_mixed_new (key);
+ else
+ /* Make sure the hash table contains the corresponding style sheet */
+ require_style_sheet (key);
+
+ token.key = (char *) key;
+ item = (struct style_sheet *) hash_find_item (style_sheets, &token);
+
+ if (!item)
+ return NULL;
+
+ /* To me, it looks like an horror: the syntax table is not
+ * stored in the regex buffer. As a consequence, each time
+ * we change sheet, make sure to update the re_syntax_table */
+ re_syntax_table = (char *) item->alpha1;
+
+ return item;
+}
+
+/*
+ * Compute the total SUM of the all the versions of the
+ * sheets which key is in KEYS
+ */
+static inline void
+style_sheets_versions (struct darray * keys,
+ int sum [4], int requirement [4])
+{
+ size_t i;
+ struct style_sheet * sheet;
+
+ version_set_to_null (sum);
+ version_set_to_null (requirement);
+ for (i = 0 ; i < keys->len ; i++)
+ {
+ sheet = get_style_sheet ((char *) keys->content[i]);
+ version_add (sum, sheet->version);
+ if (version_cmp (sheet->requirement, requirement) > 0)
+ version_cpy (requirement, sheet->requirement);
+ }
+}
diff --git a/src/ssheet.h b/src/ssheet.h
new file mode 100644
index 0000000..e9671bc
--- /dev/null
+++ b/src/ssheet.h
@@ -0,0 +1,241 @@
+/*
+ * ssheet.h
+ *
+ * definition of the languages style sheets
+ * Copyright (c) 1988, 89, 90, 91, 92, 93 Miguel Santana
+ * Copyright (c) 1995, 96, 97, 98 Akim Demaille, Miguel Santana
+ * $Id: ssheet.h,v 1.1.1.1.2.1 2007/12/29 01:58:36 mhatta Exp $
+ */
+
+/*
+ * This file is part of a2ps.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _SSHEET_H_
+#define _SSHEET_H_
+
+#include "a2ps.h"
+#include "darray.h"
+#include "ffaces.h"
+#include "hashtab.h"
+#include "jobs.h"
+#include "regex.h"
+
+enum case_sensitiveness
+{
+ case_sensitive, case_insensitive, case_undefined
+};
+
+/*
+ * Used by the scanner and parser to return a pattern,
+ * which may enclose NUL
+ */
+struct pattern
+{
+ char * pattern;
+ size_t len;
+};
+
+/*
+ * Now, keywords, and operators share the same underlying
+ * structure, because, though keywords don't need a SYMBOL field,
+ * they are so close, that implementation should be the same.
+ * This may be a sign that OO would have been appreciated :)
+ */
+struct faced_string
+{
+ uchar * string; /* the destination string */
+ int reg_ref; /* there is no destination string,
+ * but the model is the REG_REF expression
+ * caught by the regexp (e.g. 1 for \1 */
+ struct fface_s face;
+};
+
+
+/*--------------------------------------.
+| A rule is composed of its lhs and rhs |
+`--------------------------------------*/
+
+struct rule
+{
+ uchar *word;
+ struct re_pattern_buffer *regex;
+ struct darray * rhs;
+};
+
+struct words
+{
+ /* darrays of struct rule * */
+ struct darray * strings; /* those which matchers are strings */
+ struct darray * regexps; /* those which matchers are regexps */
+ struct rule ** min [256];
+ struct rule ** max [256];
+};
+
+struct sequence
+{
+ struct rule * open;
+ struct fface_s face;
+ struct words * exceptions; /* Exception, i.e. \" between "" */
+ struct words * close; /* closing alternatives */
+} ;
+
+struct style_sheet
+{
+ /* index of the language (compare with command-line option) */
+ const char * key;
+
+ /* Nice looking name of the style */
+ const uchar * name;
+
+ /* Who wrote it, and when */
+ const uchar * author;
+ int version[4];
+
+ /* What version of a2ps is required? */
+ int requirement[4];
+
+ /* Note describing the mode or the language */
+ const uchar * documentation;
+
+ /* Does it have ancestors (i.e., this one is an extension of
+ * its ancestors). It is a list of keys, of course */
+ struct darray * ancestors;
+
+ /* case sensitiveness for keywords and rules */
+ enum case_sensitiveness sensitiveness;
+
+ /* definition of the "words" (keywords and rules):
+ * a char belonging to a first alphabet (alpha1),
+ * and any number of chars belonging to the second (alpha2). */
+ uchar alpha1 [256];
+ uchar alpha2 [256];
+
+ /* list of keywords for this language */
+ struct words * keywords;
+
+ /* same as keywords BUT there is no need to be preceded and followed
+ * by not in alpha2. In other words, these are not "words" of the
+ * alphabet, but any sequence of chars */
+ struct words * operators;
+
+ /* darray of the sequences (strings, documentations, etc.) */
+ struct darray * sequences;
+};
+
+/* Notes
+ *
+ * - global exceptions is made for languages such as tcl where, whereever the
+ * rule appears, it must not be "understood", e.g. \" and \\ are
+ * written directly.
+ *
+ * - local exception is made for àç§è! languages such as ada where "" is the
+ * empty string, but appearing in a string, "" denotes ".
+ */
+
+
+/*
+ * The faced_string
+ */
+struct faced_string *
+faced_string_new PARAMS ((uchar * string, int reg_ref, struct fface_s fface));
+
+/*
+ * The version numbers
+ */
+void style_sheet_set_version PARAMS ((struct style_sheet * sheet,
+ const char * version_string));
+int style_sheet_set_requirement PARAMS ((struct style_sheet * sheet,
+ const char * version_string));
+
+/*
+ * The destinations (part of rule)
+ */
+struct darray * rhs_new PARAMS ((void));
+struct darray *
+rhs_new_single PARAMS ((uchar * string, int reg_ref, struct fface_s fface));
+void rhs_add PARAMS ((struct darray * dest, struct faced_string * str));
+void rhs_self_print PARAMS ((struct darray * rhs, FILE * stream));
+
+/*
+ * Dealing with the keywords, rules and operators
+ */
+struct rule * rule_new PARAMS ((uchar * word,
+ struct pattern * pattern,
+ struct darray * destination,
+ const char *filename, size_t line));
+struct rule * keyword_rule_new PARAMS ((uchar * word,
+ struct pattern * pattern,
+ struct darray * destination,
+ const char *filename, size_t line));
+
+/*
+ * Dealing with the sequences
+ */
+struct pattern *
+new_pattern PARAMS ((char * pattern, size_t len));
+
+struct sequence * sequence_new
+ PARAMS ((struct rule * Open,
+ struct fface_s in_face,
+ struct words * Close,
+ struct words * exceptions));
+void free_sequence PARAMS ((struct sequence * sequence));
+struct sequence * new_C_string_sequence PARAMS ((const char * delimitor));
+void sequence_self_print PARAMS ((struct sequence * v, FILE * stream));
+
+
+/*
+ * Dealing with the struct words
+ */
+struct words *
+words_new PARAMS ((const char * name_strings, const char * name_regexps,
+ size_t size, size_t increment));
+void words_free PARAMS ((struct words * words));
+void words_add_string PARAMS ((struct words * words, struct rule * rule));
+void words_add_regex PARAMS ((struct words * words, struct rule * rule));
+void words_set_no_face PARAMS ((struct words * words, struct fface_s face));
+void words_merge_rules_unique PARAMS ((struct words * words,
+ struct words * new));
+
+/*
+ * Dealing with the style sheets
+ */
+struct style_sheet * new_style_sheet PARAMS ((const uchar * name));
+void style_sheet_finalize PARAMS ((struct style_sheet * sheet));
+void style_sheet_self_print PARAMS ((struct style_sheet * sheet,
+ FILE * stream));
+
+/*
+ * Dealing with the hash table for style sheets
+ */
+struct hash_table_s * new_style_sheets PARAMS ((void));
+struct style_sheet * get_style_sheet PARAMS ((const char * name));
+
+/************************************************************************/
+/* style selection */
+/************************************************************************/
+/*
+ * List the style sheets
+ */
+void list_style_sheets_short PARAMS ((FILE * stream));
+void list_style_sheets_long PARAMS ((FILE * strea));
+void list_style_sheets_html PARAMS ((FILE * strea));
+void list_style_sheets_texinfo PARAMS ((FILE * strea));
+
+#endif /* not defined _SSHEET_H_ */
diff --git a/src/sshread.c b/src/sshread.c
new file mode 100644
index 0000000..7abb473
--- /dev/null
+++ b/src/sshread.c
@@ -0,0 +1,517 @@
+/*
+ * sshread.c
+ *
+ * routines of input, and formatting according to the styles
+ * Copyright (c) 1988, 89, 90, 91, 92, 93 Miguel Santana
+ * Copyright (c) 1995, 96, 97, 98 Akim Demaille, Miguel Santana
+ * $Id: sshread.c,v 1.1.1.1.2.1 2007/12/29 01:58:36 mhatta Exp $
+ */
+
+/*
+ * This file is part of a2ps.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * $Id: sshread.c,v 1.1.1.1.2.1 2007/12/29 01:58:36 mhatta Exp $
+ */
+
+#include "a2ps.h"
+#include "sshread.h"
+#include "ssheet.h"
+#include "routines.h"
+#include "buffer.h"
+#include "jobs.h"
+#include "fjobs.h"
+#include "psgen.h"
+#include "assert.h"
+#include "quotearg.h"
+
+/*
+ * Use the information offered by main.c
+ */
+extern struct a2ps_job *job;
+
+/*
+ * Shortcut to call regex upon a buffer, and store in a token
+ */
+#define buffer_match(buffer,regex,token) \
+ re_match (regex, \
+ (char *) buffer->value, buffer->len, buffer->curr, \
+ token->registers)
+
+/*
+ * Structure in which is stored the result of a parsing
+ */
+struct token
+ {
+ struct re_registers *registers;
+ struct darray *rhs;
+ };
+
+#define token_dest(_i_) \
+ ((struct faced_string *) token->rhs->content[_i_])
+
+#define token_dest_fface(_i_) \
+ (token_dest(_i_)->face)
+
+#define token_dest_face(_i_) \
+ (fface_get_face(token_dest_fface(_i_)))
+
+#define token_dest_fflags(_i_) \
+ (fface_get_flags(token_dest_fface(_i_)))
+
+static inline struct token *
+token_new (void)
+{
+ struct token *res = XMALLOC (struct token, 1);
+ res->registers = XMALLOC (struct re_registers, 1);
+ res->registers->start = XMALLOC (regoff_t, 30);
+ res->registers->end = XMALLOC (regoff_t, 30);
+ return res;
+}
+
+static inline struct darray *
+rhs_plain_new (void)
+{
+ return rhs_new_single (NULL, 0, Plain_fface);
+}
+
+static inline void
+token_free (struct token *token)
+{
+ free (token);
+}
+
+/* Where the token and its attributes are stored */
+static struct token *token = NULL;
+#define token_set_registers(_start_, _len_) \
+ do { \
+ token->registers->start [0] = _start_; \
+ token->registers->end [0] = _start_ + _len_; \
+ } while (0)
+
+#define token_start(_i_) \
+ token->registers->start [token_dest(_i_)->reg_ref]
+
+#define token_end(_i_) \
+ token->registers->end [token_dest(_i_)->reg_ref]
+
+static struct darray *plain_rhs = NULL;
+
+/****************************************************************/
+/* pretty printing service routines */
+/****************************************************************/
+/*
+ * Eat characters as long as their in the 2nd alphabet
+ * and we are in the buffer.
+ */
+static inline void
+match_word (buffer_t * buffer, struct style_sheet *sheet)
+{
+ int start = buffer->curr;
+
+ do
+ buffer->curr++;
+ while (sheet->alpha2[*(buffer->content + buffer->curr)]
+ && !buffer_is_empty (buffer));
+
+ token->rhs = plain_rhs;
+ token_dest (0)->face = Plain_fface;
+ token->registers->start[0] = start;
+ token->registers->end[0] = buffer->curr;
+}
+
+/****************************************************************/
+/* lexical analysis routines */
+/****************************************************************/
+#define word_regexp(_i_) \
+ (((struct rule *) words->regexps->content[_i_]))
+/*
+ * Return true if there is a element of WORDS which keywords-match
+ * current point of BUFFER. Fill TOKEN with the matching part.
+ */
+static inline int
+match_keyword (buffer_t * buffer,
+ struct words *words,
+ uchar * alphabet)
+{
+ struct rule **key;
+ uchar *string = buffer->value + buffer->curr;
+ int i;
+ int res;
+
+ /* First try the words */
+ if (words->min[*string])
+ for (key = words->max[*string]
+ ; words->min[*string] <= key
+ ; key--)
+ {
+ if (ustrprefix ((*key)->word, string)
+ && !alphabet[string[ustrlen ((*key)->word)]])
+ {
+ token->rhs = (*key)->rhs;
+ token_set_registers (buffer->curr, ustrlen ((*key)->word));
+ buffer->curr += ustrlen ((*key)->word);
+ return 1;
+ }
+ }
+
+ /* Then the regexps, in reversed order (in order to take the
+ * _last_ definition */
+ for (i = (int) words->regexps->len - 1; i >= 0; i--)
+ {
+ res = buffer_match (buffer, word_regexp (i)->regex, token);
+ switch (res)
+ {
+ case -2:
+ fprintf (stderr, "An error occured while matching\n");
+ break;
+ case -1:
+ continue;
+ default:
+ token->rhs = word_regexp (i)->rhs;
+ buffer->curr += res;
+ return 1;
+ }
+ }
+
+ /* Report that nothing matches */
+ return 0;
+}
+
+/*
+ * Return true if there is a element of WORDS which operators-match
+ * current point of BUFFER. Fill TOKEN with the matching part.
+ */
+static inline int
+match_operator (buffer_t * buffer,
+ struct words *words)
+{
+ struct rule **key;
+ uchar *string = buffer->value + buffer->curr;
+ int i;
+ int res;
+
+ /* First the words */
+ if (words->min[*string])
+ for (key = words->max[*string]
+ ; words->min[*string] <= key
+ ; key--)
+ {
+ if (ustrprefix ((*key)->word, string))
+ {
+ token->rhs = (*key)->rhs;
+ token_set_registers (buffer->curr, ustrlen ((*key)->word));
+ buffer->curr += ustrlen ((*key)->word);
+ return 1;
+ }
+ }
+
+ /* Then the regexps, in reversed order (in order to take the
+ * _last_ definition */
+ for (i = (int) words->regexps->len - 1; i >= 0; i--)
+ {
+ res = buffer_match (buffer, word_regexp (i)->regex, token);
+ switch (res)
+ {
+ case -2:
+ fprintf (stderr, "An error occured while matching\n");
+ break;
+ case -1:
+ continue;
+ default:
+ token->rhs = word_regexp (i)->rhs;
+ buffer->curr += res;
+ return 1;
+ }
+ }
+
+ /* Report failure */
+ return 0;
+}
+
+/*
+ * If buffer+*curr begins with a sequence, return that sequence.
+ * Otherwise NULL
+ */
+#ifdef SEQ
+#undef SEQ
+#endif
+#define SEQ(_i_) \
+ ((struct sequence *) sheet->sequences->content [i])
+static inline struct sequence *
+match_sequence (buffer_t * buffer, struct style_sheet *sheet)
+{
+ int i;
+ int res;
+ uchar *string = buffer->value + buffer->curr;
+
+ /* In reversed order (in order to take the _last_ definition */
+ for (i = (int) sheet->sequences->len - 1; i >= 0; i--)
+ {
+ if (SEQ (i)->open->regex)
+ {
+ /* The regexp patterns */
+ res = buffer_match (buffer, SEQ (i)->open->regex, token);
+ switch (res)
+ {
+ case -2:
+ fprintf (stderr, "An error occured while matching\n");
+ break;
+ case -1:
+ continue;
+ default:
+ token->rhs = SEQ (i)->open->rhs;
+ buffer->curr += res;
+ return SEQ (i);
+ }
+ }
+ else
+ {
+ /* It's a string */
+ if (ustrprefix (SEQ (i)->open->word, string))
+ {
+ token_set_registers (buffer->curr, ustrlen (SEQ (i)->open->word));
+ token->rhs = SEQ (i)->open->rhs;
+ buffer->curr += ustrlen (SEQ (i)->open->word);
+ return SEQ (i);
+ }
+ }
+ }
+ return NULL;
+}
+
+/*
+ * Put in token the token recognized.
+ * The number of token read, 0 if nothing left
+ */
+static inline int
+ssh_get_token (buffer_t * buffer, struct style_sheet *sheet)
+{
+ static int return_to_plain = false;
+ /* NULL if not in a sequence currently */
+ static struct sequence *sequence = NULL;
+
+ if (buffer_is_empty (buffer))
+ {
+ buffer_get (buffer);
+
+ /* We don't trust liba2ps for the line numbers, because
+ * if a2ps skips some lines (e.g., --strip-level, or INVISIBLE),
+ * liba2ps will number upon output lines, not imput lines,
+ * which is what is expected */
+ (CURRENT_FILE (job))->lines = buffer->line;
+
+ if (buffer->len == 0)
+ {
+ /* end of file: reset values */
+ /* If this is a new file, it must not depend on the trailling
+ * parameters of the previous file */
+ sequence = NULL;
+ return_to_plain = false;
+ return 0;
+ }
+ }
+
+ if (return_to_plain)
+ {
+ return_to_plain = false;
+ token->rhs = plain_rhs;
+ token_dest (0)->face = Plain_fface;
+ }
+
+ if (sequence)
+ {
+ /* escape: not converted when in a sequence */
+ if (match_operator (buffer, sequence->exceptions))
+ return 1;
+ /* end of sequence ? */
+ if (match_operator (buffer, sequence->close))
+ {
+ return_to_plain = true;
+ sequence = NULL;
+ return 1;
+ }
+ /* We are in a sequence not to be closed yet.
+ * Advance of 1 char */
+ token->rhs = plain_rhs;
+ token_dest (0)->face = sequence->face;
+ token->registers->start[0] = buffer->curr++;
+ token->registers->end[0] = buffer->curr;
+ return 1;
+ }
+ else
+ { /* (not in sequence) */
+ if ((sequence = match_sequence (buffer, sheet)))
+ return 1;
+ else if (sheet->alpha1[buffer->content[buffer->curr]])
+ {
+ /* we are in a word since this was a char belonging to the
+ * first alphabet */
+ if (match_keyword (buffer, sheet->keywords, sheet->alpha2)
+ || match_operator (buffer, sheet->operators))
+ {
+ return_to_plain = true;
+ return 1;
+ }
+ else
+ {
+ /* since some characters may be used inside an identifier
+ * (eg, x' = x in claire) but can also be used to open
+ * a special sequence (eg, 'x' in claire), then we must read
+ * the whole word, and print in.
+ */
+ match_word (buffer, sheet);
+ return 1;
+ }
+ }
+ else if (match_operator (buffer, sheet->operators))
+ {
+ return_to_plain = true;
+ return 1;
+ }
+ }
+
+ /* We did not recognize something special */
+ token->rhs = plain_rhs;
+ token->registers->start[0] = buffer->curr++;
+ token->registers->end[0] = buffer->curr;
+ return 1;
+}
+
+#define GRAB_TAG(_tag_) \
+ do { \
+ ustrncat (_tag_, \
+ buffer->content + token_start (i), \
+ token_end (i) - token_start (i)); \
+ } while (0)
+
+/*
+ * ssh-Pretty print a file to postscript
+ */
+void
+ssh_print_postscript (struct a2ps_job *Job,
+ buffer_t * buffer,
+ struct style_sheet *sheet)
+{
+ struct fface_s fface;
+ /* To grab the encoding switching instruction */
+ uchar bufenc[512];
+ int grabbing_encoding = false;
+ size_t i;
+
+ *bufenc = '\0';
+ fface = Plain_fface;
+
+ /* I must do this because of the broken handling of the registers in
+ * regex. Until I find a way to ensure enough place in the
+ * registers, without having to trust regex. */
+ if (!token)
+ {
+ token = token_new ();
+ plain_rhs = rhs_plain_new ();
+ }
+
+ while (ssh_get_token (buffer, sheet) != 0)
+ for (i = 0; i < token->rhs->len; i++)
+ {
+ /* Is a new face ? */
+ if (!fface_squ (fface, token_dest_fface (i)))
+ {
+ /* Reset dynamic markers */
+ if (token_dest_fflags (i) & ff_Tag1)
+ *Job->tag1 = '\0';
+ if (token_dest_fflags (i) & ff_Tag2)
+ *Job->tag2 = '\0';
+ if (token_dest_fflags (i) & ff_Tag3)
+ *Job->tag3 = '\0';
+ if (token_dest_fflags (i) & ff_Tag4)
+ *Job->tag4 = '\0';
+ if (grabbing_encoding
+ && (!(token_dest_fflags (i) & ff_Encoding)))
+ {
+ /* Grabbing of the encoding name is completed */
+ struct encoding *newenc;
+ newenc = get_encoding_by_alias (job, (char *) bufenc);
+/* encoding_build_faces_wx (job, newenc); */
+ if (!newenc)
+ error (0, 0, _ ("unknown encoding `%s', ignored"),
+ quotearg ((char *) bufenc));
+ else
+ ps_switch_encoding (Job, newenc);
+ *bufenc = '\0';
+ grabbing_encoding = false;
+ }
+ fface = token_dest (i)->face;
+ }
+
+ /* See if there are some information to grab */
+ if (token_dest (i)->string)
+ {
+ if (fface_get_flags (fface) & ff_Tag1)
+ ustrcat (Job->tag1, token_dest (i)->string);
+ if (fface_get_flags (fface) & ff_Tag2)
+ ustrcat (Job->tag2, token_dest (i)->string);
+ if (fface_get_flags (fface) & ff_Tag3)
+ ustrcat (Job->tag3, token_dest (i)->string);
+ if (fface_get_flags (fface) & ff_Tag4)
+ ustrcat (Job->tag4, token_dest (i)->string);
+ /* Grab the dynamic encodings */
+ if (fface_get_flags (fface) & ff_Encoding)
+ {
+ grabbing_encoding = true;
+ ustrcat (bufenc, token_dest (i)->string);
+ }
+ }
+ else
+ {
+ if (fface_get_flags (fface) & ff_Tag1)
+ GRAB_TAG (Job->tag1);
+ if (fface_get_flags (fface) & ff_Tag2)
+ GRAB_TAG (Job->tag2);
+ if (fface_get_flags (fface) & ff_Tag3)
+ GRAB_TAG (Job->tag3);
+ if (fface_get_flags (fface) & ff_Tag4)
+ GRAB_TAG (Job->tag4);
+ /* Grab the dynamic encodings */
+ if (fface_get_flags (fface) & ff_Encoding)
+ {
+ grabbing_encoding = true;
+ GRAB_TAG (bufenc);
+ }
+ }
+
+ /*
+ * If not invisible, give it to liba2ps for printing.
+ */
+ if (!(fface_get_flags (fface) & ff_Invisible))
+ {
+ if (token_dest (i)->string)
+ ps_print_string (Job, token_dest (i)->string,
+ fface.face);
+ else
+ ps_print_buffer (Job, buffer->content,
+ token_start (i), token_end (i),
+ fface.face);
+ }
+ }
+
+ /* FIXME: Find a way to remove the token some day
+ token_free (token);
+ */
+}
diff --git a/src/sshread.h b/src/sshread.h
new file mode 100644
index 0000000..fb8b156
--- /dev/null
+++ b/src/sshread.h
@@ -0,0 +1,42 @@
+/*
+ * sshread.h
+ *
+ * routines of input, and formatting according to the styles
+ * Copyright (c) 1988, 89, 90, 91, 92, 93 Miguel Santana
+ * Copyright (c) 1995, 96, 97, 98 Akim Demaille, Miguel Santana
+ * $Id: sshread.h,v 1.1.1.1.2.1 2007/12/29 01:58:36 mhatta Exp $
+ */
+
+/*
+ * This file is part of a2ps.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _SSHREAD_H_
+#define _SSHREAD_H_
+
+#include "ssheet.h"
+#include "buffer.h"
+struct a2ps_job;
+/*
+ * Pretty print the current file of JOB
+ */
+void ssh_print_postscript PARAMS ((struct a2ps_job * job,
+ buffer_t * buffer,
+ struct style_sheet * sheet));
+
+#endif /* not defined(_SHHREAD_H_) */
diff --git a/src/version-etc.c b/src/version-etc.c
new file mode 100644
index 0000000..cdbf26a
--- /dev/null
+++ b/src/version-etc.c
@@ -0,0 +1,70 @@
+/* Utility to help print --version output in a consistent format.
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program 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, or (at your option)
+ any later version.
+
+ This program 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, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Jim Meyering. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include "version-etc.h"
+
+#if ENABLE_NLS
+# include <libintl.h>
+# define _(Text) gettext (Text)
+#else
+# define _(Text) Text
+#endif
+#define N_(Text) Text
+
+/* Default copyright goes to the FSF. */
+
+char* version_etc_copyright =
+ N_("Copyright (C) 1999 Free Software Foundation, Inc.");
+
+
+/* Display the --version information the standard way.
+
+ If COMMAND_NAME is NULL, the PACKAGE is asumed to be the name of
+ the program. The formats are therefore:
+
+ PACKAGE VERSION
+
+ or
+
+ COMMAND_NAME (PACKAGE) VERSION. */
+void
+version_etc (FILE *stream,
+ const char *command_name, const char *package,
+ const char *version, const char *authors)
+{
+ if (command_name)
+ fprintf (stream, "%s (%s) %s\n", command_name, package, version);
+ else
+ fprintf (stream, "%s %s\n", package, version);
+ fprintf (stream, _("Written by %s.\n"), authors);
+ putc ('\n', stream);
+
+ fputs (_(version_etc_copyright), stream);
+ putc ('\n', stream);
+
+ fputs (_("\
+This is free software; see the source for copying conditions. There is NO\n\
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"),
+ stream);
+}
diff --git a/src/version-etc.h b/src/version-etc.h
new file mode 100644
index 0000000..9ca6026
--- /dev/null
+++ b/src/version-etc.h
@@ -0,0 +1,38 @@
+/* Utility to help print --version output in a consistent format.
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program 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, or (at your option)
+ any later version.
+
+ This program 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, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Jim Meyering. */
+
+#ifndef VERSION_ETC_H
+# define VERSION_ETC_H 1
+
+# ifndef PARAMS
+# if defined PROTOTYPES || (defined __STDC__ && __STDC__)
+# define PARAMS(Args) Args
+# else
+# define PARAMS(Args) ()
+# endif
+# endif
+
+extern char *version_etc_copyright;
+
+void
+version_etc PARAMS ((FILE *stream,
+ const char *command_name, const char *package,
+ const char *version, const char *authors));
+
+#endif /* VERSION_ETC_H */
diff --git a/src/versions.c b/src/versions.c
new file mode 100644
index 0000000..34e495e
--- /dev/null
+++ b/src/versions.c
@@ -0,0 +1,136 @@
+/*
+ * versions.c -- Handling standard version numbers
+ * Copyright (c) 1988, 89, 90, 91, 92, 93 Miguel Santana
+ * Copyright (c) 1995, 96, 97, 98 Akim Demaille, Miguel Santana
+ *
+ */
+
+/*
+ * This file is part of a2ps.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "a2ps.h"
+#include "versions.h"
+#include "quotearg.h"
+
+/************************************************************************/
+/* The version handling */
+/************************************************************************/
+void
+version_set_to_null (version_t version)
+{
+ size_t n;
+
+ for (n = 0 ; n < VERSION_LENGTH ; n++)
+ version[n] = 0;
+}
+
+bool
+version_null_p (version_t version)
+{
+ size_t n;
+
+ for (n = 0 ; n < VERSION_LENGTH ; n++)
+ if (version[n])
+ return false;
+ return true;
+}
+
+int
+version_cmp (version_t v1, version_t v2)
+{
+ int n;
+
+ for (n = 0 ; n < VERSION_LENGTH ; n++)
+ if (v1[n] < v2[n])
+ return -1;
+ else if (v1[n] > v2[n])
+ return 1;
+
+ return 0;
+}
+
+void
+version_cpy (version_t d, version_t s)
+{
+ memcpy (d, s, VERSION_LENGTH * sizeof(s[0]));
+}
+
+void
+version_self_print (version_t version, FILE * stream)
+{
+ if (version[2])
+ fprintf (stream, "%d.%d%c",
+ version[0], version[1], version[2]);
+ else
+ fprintf (stream, "%d.%d",
+ version[0], version[1]);
+}
+
+/*
+ * Return the length occupied by this version number once printed
+ */
+int
+version_length (version_t version)
+{
+#define short_int_len(_i_) ((_i_) < 10 ? 1 : 2)
+ if (version[2])
+ return 2
+ + short_int_len(version[0])
+ + short_int_len(version[1])
+ + 1;
+ else
+ return 1
+ + short_int_len(version[0])
+ + short_int_len(version[1]);
+}
+
+void
+version_add (version_t v1, version_t v2)
+{
+ int n;
+
+ for (n = 0 ; n < VERSION_LENGTH ; n++)
+ v1[n] += v2[n];
+}
+
+/*
+ * Valid versions numbers are:
+ * digit.digit
+ * digit.digitchar
+ */
+void
+string_to_version (const char * version_string, version_t version)
+{
+ char d;
+
+ switch (sscanf (version_string, "%d.%d%c",
+ &(version[0]), &(version[1]), &d))
+ {
+ case 2:
+ version[2] = 0;
+ break;
+ case VERSION_LENGTH:
+ version[2] = d - 'a' + 1;
+ break;
+ default:
+ error (1, 0,
+ _("invalid version number `%s'"), quotearg (version_string));
+ break;
+ };
+}
diff --git a/src/versions.h b/src/versions.h
new file mode 100644
index 0000000..b596aa4
--- /dev/null
+++ b/src/versions.h
@@ -0,0 +1,52 @@
+/*
+ * versions.h -- Handling standard version numbers
+ * Copyright (c) 1988, 89, 90, 91, 92, 93 Miguel Santana
+ * Copyright (c) 1995, 96, 97, 98 Akim Demaille, Miguel Santana
+ *
+ */
+
+/*
+ * This file is part of a2ps.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef VERSIONS_H_
+# define VERSIONS_H_
+
+/* Beware that the routines are not actually ready for a meer change
+ of VERSION_LENGTH. Changes will be needed. */
+#define VERSION_LENGTH 3
+typedef int version_t[VERSION_LENGTH];
+
+void version_set_to_null PARAMS ((version_t version));
+
+bool version_null_p PARAMS ((version_t version));
+
+int version_cmp PARAMS ((version_t v1, version_t v2));
+
+void version_cpy PARAMS ((version_t d, version_t s));
+
+void version_self_print PARAMS ((version_t version , FILE *stream));
+
+/* Return the length occupied by this version number once printed */
+int version_length PARAMS ((version_t version));
+
+void version_add PARAMS ((version_t v1, version_t v2));
+
+void string_to_version PARAMS ((const char *string, version_t version));
+
+#endif /* not defined VERSIONS_H_ */
diff --git a/src/yy2ssh.h b/src/yy2ssh.h
new file mode 100644
index 0000000..3dcdc8e
--- /dev/null
+++ b/src/yy2ssh.h
@@ -0,0 +1,40 @@
+#define yymaxdepth sshmaxdepth
+#define yyparse sshparse
+#define yylex sshlex
+#define yyerror ssherror
+#define yylval sshlval
+#define yychar sshchar
+#define yydebug sshdebug
+#define yypact sshpact
+#define yyr1 sshr1
+#define yyr2 sshr2
+#define yydef sshdef
+#define yychk sshchk
+#define yypgo sshpgo
+#define yyact sshact
+#define yyexca sshexca
+#define yyerrflag ssherrflag
+#define yynerrs sshnerrs
+#define yyps sshps
+#define yypv sshpv
+#define yys sshs
+#define yy_yys sshyys
+#define yystate sshstate
+#define yytmp sshtmp
+#define yyv sshv
+#define yy_yyv sshyyv
+#define yyval sshval
+#define yylloc sshlloc
+#define yyreds sshreds
+#define yytoks sshtoks
+#define yylhs sshyylhs
+#define yylen sshyylen
+#define yydefred sshyydefred
+#define yydgoto sshyydgoto
+#define yysindex sshyysindex
+#define yyrindex sshyyrindex
+#define yygindex sshyygindex
+#define yytable sshyytable
+#define yycheck sshyycheck
+#define yyname sshyyname
+#define yyrule sshyyrule