summaryrefslogtreecommitdiff
path: root/Build/source/texk/contrib
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/contrib')
-rw-r--r--Build/source/texk/contrib/ChangeLog290
-rw-r--r--Build/source/texk/contrib/INSTALL12
-rw-r--r--Build/source/texk/contrib/README22
-rw-r--r--Build/source/texk/contrib/config.h11
-rw-r--r--Build/source/texk/contrib/depend.mak559
-rw-r--r--Build/source/texk/contrib/depend.mk155
-rw-r--r--Build/source/texk/contrib/dvihp.c433
-rw-r--r--Build/source/texk/contrib/dvihp.rc35
-rw-r--r--Build/source/texk/contrib/fileutils.c561
-rw-r--r--Build/source/texk/contrib/fileutils.h26
-rw-r--r--Build/source/texk/contrib/fmtutil.c1312
-rw-r--r--Build/source/texk/contrib/fmtutil.h43
-rw-r--r--Build/source/texk/contrib/glob/COPYING.LIB481
-rw-r--r--Build/source/texk/contrib/glob/Makefile.ami69
-rw-r--r--Build/source/texk/contrib/glob/Makefile.in66
-rw-r--r--Build/source/texk/contrib/glob/SCOPTIONS13
-rw-r--r--Build/source/texk/contrib/glob/SMakefile69
-rwxr-xr-xBuild/source/texk/contrib/glob/configure2139
-rw-r--r--Build/source/texk/contrib/glob/configure.bat26
-rw-r--r--Build/source/texk/contrib/glob/configure.in20
-rw-r--r--Build/source/texk/contrib/glob/fnmatch.c230
-rw-r--r--Build/source/texk/contrib/glob/fnmatch.h68
-rw-r--r--Build/source/texk/contrib/glob/glob.c906
-rw-r--r--Build/source/texk/contrib/glob/glob.h108
-rw-r--r--Build/source/texk/contrib/irun.c569
-rw-r--r--Build/source/texk/contrib/irun.h1
-rw-r--r--Build/source/texk/contrib/irun.rc34
-rw-r--r--Build/source/texk/contrib/libmktex.rc36
-rw-r--r--Build/source/texk/contrib/main.c91
-rw-r--r--Build/source/texk/contrib/makempx.c630
-rw-r--r--Build/source/texk/contrib/makempx.rc34
-rw-r--r--Build/source/texk/contrib/mkloctex.bat48
-rw-r--r--Build/source/texk/contrib/mkocp.c46
-rw-r--r--Build/source/texk/contrib/mkofm.c83
-rw-r--r--Build/source/texk/contrib/mktex.c2610
-rw-r--r--Build/source/texk/contrib/mktex.h58
-rw-r--r--Build/source/texk/contrib/mktexlib.h61
-rw-r--r--Build/source/texk/contrib/pdfdde.c564
-rw-r--r--Build/source/texk/contrib/regex/regex.c4948
-rw-r--r--Build/source/texk/contrib/regex/regex.h505
-rw-r--r--Build/source/texk/contrib/stackenv.c343
-rw-r--r--Build/source/texk/contrib/stackenv.h46
-rw-r--r--Build/source/texk/contrib/variables.c472
-rw-r--r--Build/source/texk/contrib/variables.h23
-rw-r--r--Build/source/texk/contrib/win32.mak166
45 files changed, 19022 insertions, 0 deletions
diff --git a/Build/source/texk/contrib/ChangeLog b/Build/source/texk/contrib/ChangeLog
new file mode 100644
index 00000000000..f0462901d4b
--- /dev/null
+++ b/Build/source/texk/contrib/ChangeLog
@@ -0,0 +1,290 @@
+2003-01-08 Olaf Weber <olaf@infovore.xs4all.nl>
+
+ * mktex.h: Update from Fabrice.
+
+ * mktex.c: Update from Fabrice.
+
+2002-12-14 Olaf Weber <olaf@infovore.xs4all.nl>
+
+ * fmtutil.c: Sync with TeXlive tree.
+
+ * glob/configure.bat: sync with TeXlive tree.
+
+2002-10-06 Olaf Weber <olaf@infovore.xs4all.nl>
+
+ * variables.c: TeXlive merge.
+
+ * stackenv.h: TeXlive merge.
+
+ * stackenv.c: TeXlive merge.
+
+ * mktexlib.h: TeXlive merge.
+
+ * mktex.h: TeXlive merge.
+
+ * mktex.c: TeXlive merge.
+
+ * makempx.c: TeXlive merge.
+
+ * main.c: TeXlive merge.
+
+ * fmtutil.h: TeXlive merge.
+
+ * fmtutil.c: TeXlive merge.
+
+ * fileutils.c: TeXlive merge.
+
+ * dvihp.c: TeXlive merge.
+
+2000-04-21 Olaf Weber <olaf@infovore.xs4all.nl>
+
+ * makempx.c, stackenv.c, fmtutil.c: Update from Fabrice.
+
+2000-04-03 Olaf Weber <olaf@infovore.xs4all.nl>
+
+ * All files: Update from Fabrice Popineau
+ <popineau@esemetz.ese-metz.fr>.
+
+1999-03-17 Olaf Weber <olaf@infovore.xs4all.nl>
+
+ * fmtutil.c: TEXMF_CNF -> VARTEXMF. From Thomas.
+
+1999-03-15 Olaf Weber <olaf@infovore.xs4all.nl>
+
+ * mktex.c (do_mktexmf): Correction for 11 point fonts, addition
+ for the CB font family. From Kimon Kontovasilis
+ <kimon@cyclades.nrcps.ariadne-t.gr>.
+
+1999-02-06 Olaf Weber <olaf@infovore.xs4all.nl>
+
+ * mktex.c (do_mktexmf): Special-case 30 and 36 points, as with the
+ mktexmf script. From Fabrice.
+
+1999-02-04 Olaf Weber <olaf@infovore.xs4all.nl>
+
+ * stackenv.h (oops): Removed __cdecl, from Fabrice.
+
+ * stackenv.c (oops): Removed __cdecl, from Fabrice.
+
+ * mktexlib.h [!WIN32]: Removed define of __cdecl. From Fabrice.
+
+ * mktex.c (main): Removed __cdecl, from Fabrice.
+
+ * makempx.c (main): Removed __cdecl, from Fabrice.
+
+ * main.c (main): Removed __cdecl, from Fabrice.
+
+ * fmtutil.c (main): Removed __cdecl, from Fabrice.
+
+ * dvihp.c (main): Removed __cdecl, from Fabrice.
+
+1999-01-27 Olaf Weber <olaf@infovore.xs4all.nl>
+
+ * fileutils.h: New file from Fabrice Popineau.
+
+ * fileutils.c: New file from Fabrice Popineau.
+
+ * Makefile: Update for new files from Fabrice Popineau.
+
+ * General updates of the other files from Fabrice.
+
+Fri Jun 12 11:39:22 1998 Fabrice POPINEAU <popineau@ese-metz.fr>
+
+ * variables.c (normalize): added UNC names handling.
+ * mktex.c (do_makedir): same thing.
+
+Tue Apr 14 21:52:37 1998 Fabrice POPINEAU <popineau@ese-metz.fr>
+
+ * mktex.c: split mktex.c into (mktex.c, main.c). The goal is to
+ build a mktex dll, directly callable from other programs. The
+ command line programs are kept through main.c .
+
+1998-03-10 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * mktex.c (main): Diagnose empty or bogus $TEXMFMAIN setting.
+ (read_mktexcnf): Don't free mtsite, as it is recorded in the hash
+ table.
+
+1998-03-09 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * mktex.c (do_mktexupdate): Call `mktexlsr', not `do_mktexlr', as
+ the latter doesn't redirect its output to the `ls-R' file.
+ (get_mode_from_mf): Fix the METAFONT command line.
+ (mktexlsr): Record the name of the temporary db_file_tmp.
+ (is_db_file_tmp): New function.
+ (print_path): Call it to check whether a file is the temporary
+ database itself, and if so, don't record it.
+
+1998-03-08 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * mktex.c (mktex_opt): Reinstate the sanity check of
+ $MT_VARTEXFONTS, like the script does.
+
+ * mktex.c (mktexpk): Revert to calling `system' instead of
+ `execute_command'.
+
+1998-03-04 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * mktex.c (do_mktexnames): Changes in the $VARTEXFONTS logic, to
+ track the shell script.
+
+ * variables.c (subst): If no match, return a copy of the original
+ string. From Fabrice Popineau.
+
+ * stackenv.c (execute_command): New function, from Fabrice
+ Popineau.
+
+ * mktex.c (string_to_lower): New function, from Fabrice Popineau.
+ (do_mktexnames): Fold case when matching relfmt with stdfontpath,
+ on case-insensitive systems. From Fabrice Popineau.
+ (do_mktextfm, mktexpk): Call `execute_command' instead of
+ `system'. From Fabrice Popineau.
+
+1998-03-03 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * mktex.c (is_casesensitive): Use the CASE_SENSITIVE flag, not
+ CASE_PRESERVED, as the latter doesn't imply the former. From
+ Fabrice Popineau.
+
+1998-03-02 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * stackenv.c (test_file): Let 'w' check stat mod bits, in addition
+ to `access', to make it more like "test -w foo".
+
+ * mktex.c (findmap): Fix the case where $SUPPLIER is shorter than
+ 3 characters.
+ (do_mktexnames): Expand stdfontpath _after_ concatenation.
+ (path_included): Fold case only for case-insensitive filesystems.
+ (do_mktexnames): Fix comparison of $MT_DESTROOT and $SYSTEMXF.
+
+1998-02-23 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * stackenv.c (is_writable): Remove temporary file we created.
+
+ * mktex.c (mktexnam_opt): When dosnames is in effect, set
+ MT_PKBASE, not MT_PKNAME.
+
+1998-02-17 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * dvihp.c (main): Catch SIGINT, SIGQUIT, SIGHUP and SIGTERM
+ signals, so we have a chance to clean up. Create temporary
+ directory which is writeable only by owner.
+
+ * makempx.c (main): Catch SIGQUIT, SIGHUP and SIGTERM signals as
+ well, like the script does.
+
+ * mktex.c: Update the usage strings according to latest scripts.
+ (mktex_opt): Catch SIGHUP and SIGTERM signals as well, like the
+ scripts do.
+
+1998-02-16 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * mktex.c (main): Compute $MT_TEXMFMAIN, like all the scripts do
+ now.
+ (do_mktexmf): Compute $MT_MFNAME.
+ (do_mktexnames): Changes in $MT_xxx variables.
+ (mktexpk): Handle non-positional options, like the script does.
+ Mask off write access bits to the temporary file for group/other.
+ (mktextfm): Handle non-positional options, like the script does.
+ Mask off write access bits to the temporary files for
+ group/other.
+ (chmod_as_dir): Mask off some access bits as given by an
+ additional parameter MASK.
+ (do_makedir): Set permissions for created directories by calling
+ `chmod'.
+
+ * dvihp.c (main): Make `main' be __cdecl for the Win32 port.
+
+ * makempx.c (main): Ditto.
+
+ * mktex.c (mktexpk): Move $NAME.${DPI}pk to $PKNAME if the latter
+ isn't produced by `gftopk'.
+ (mktex_opt): Remove computation of $TEXMFMAIN. Support exported
+ cached $MT_xxx variables, like the scripts do.
+ (read_mktexcnf): Set $MT_MKTEX_CNF if unset.
+
+1998-02-15 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * mktex.c (do_mktexmf): Free unused strings. Make division by 100
+ be in sync with the script.
+ (mktexmf): Remove redundant print-out before exiting.
+ (do_mktextfm): Free unused strings. Move $NAME.log only if
+ non-empty, like the script does; fix the second argument to
+ `mvfile' when moving $NAME.log.
+ (get_mode_from_mf): Remove redundant backslashes.
+ (mktexpk): Free unused strings. Move $NAME.log only if non-empty,
+ like the script does; fix the second argument to `mvfile' when
+ moving $NAME.log.
+
+1998-02-12 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * mktex.c (mktexnam_opt): Fix error messages.
+ (mktexnames): Print names separated by ENV_SEP_STRING, as the
+ script now does. Remove redundant calls to `expand_var'.
+
+1998-02-11 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * mktex.c [!S_ISLNK] (readlink): New function, a dummy version for
+ systems which don't support symlinks and therefore don't have
+ `readlink' in their libraries.
+ (mktexlsr): Follow symlinks, like the script does. Set access
+ permissions for db_file_tmp before moving it to db_file.
+ (do_mktexnames): Use `setval' instead of `setval_default', to
+ track changes in the script. Delete MT_xxPART variables, for the
+ same reason. New way of computing the destination directory,
+ after the script. Free `vars' and its elements.
+
+1998-02-10 +02 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * mktex.c (mktex_opt): Changes to track modifications in
+ kpathsea/mktex.opt.
+ (read_mktexcnf): Call kpse_find_file to find mktex.cnf.
+
+ * variables.c (setval_default): Only assign to unset variables,
+ leave set but empty ones unchanged. Do not put the variable into
+ the environment.
+ (setval): Do not put the variable into the environment.
+ (expand_var): Remove leading "!!" from path elements. Return NULL
+ for NULL argument.
+
+Tue Feb 10 18:06:31 1998 Olaf Weber <infovore@xs4all.nl>
+
+ * Makefile: Add check target.
+
+ * dvihp.c: Patches from Eli Zaretskii.
+
+ * makempx.c: Patches from Eli Zaretskii.
+
+ * mktex.c: Patches from Eli Zaretskii.
+
+1998-02-09 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * stackenv.c (is_writable): Handle null or empty argument without
+ crashing.
+
+Fri Feb 6 18:04:36 1998 Olaf Weber <infovore@xs4all.nl>
+
+ * Makefile: Add distclean target.
+
+Tue Feb 3 17:09:18 1998 Olaf Weber <infovore@xs4all.nl>
+
+ * Makefile (clean): Add makempx and dvihp to list of programs to
+ be removed.
+
+Sun Feb 1 16:22:59 1998 Olaf Weber <infovore@xs4all.nl>
+
+ * dvihp.c: Patch from Eli Zaretskii; replace D_OK with R_OK|W_OK.
+
+ * makempx.c: Patch from Eli Zaretskii.
+
+ * mktex.c: Patch from Eli Zaretskii; replace the kpathsea include
+ with kpathsea.h.
+
+ * stackenv.c: Patch from Eli Zaretskii.
+
+Wed Jan 28 20:19:07 1998 Olaf Weber <infovore@xs4all.nl>
+
+ * C replacements for the mktex scripts. Written by Fabrice
+ Popineau with help from Eli Zaretskii. May not work on your
+ system.
+
diff --git a/Build/source/texk/contrib/INSTALL b/Build/source/texk/contrib/INSTALL
new file mode 100644
index 00000000000..4def5256c28
--- /dev/null
+++ b/Build/source/texk/contrib/INSTALL
@@ -0,0 +1,12 @@
+To build the replacement programs, chdir to this directory and type
+"make". This builds the main programs mktex, makempx and dvihp, and
+the mktex... programs which are really symlinks to mktex.
+
+To install the compiled programs, copy them all into the same directory
+where you install the other binaries ($prefix/bin, which is usually
+/usr/local/bin).
+
+The supplied Makefile was tested with DJGPP, but it should also work
+with any reasonable Unix setup. For platforms other than these two,
+you might need to tweak the Makefile a bit; the macros $EXE, $O, $LN_S
+and $RM are provided to make this easier.
diff --git a/Build/source/texk/contrib/README b/Build/source/texk/contrib/README
new file mode 100644
index 00000000000..546ba53bc32
--- /dev/null
+++ b/Build/source/texk/contrib/README
@@ -0,0 +1,22 @@
+This directory contains: replacement mktex... programs which emulate
+the mktex... shell scripts in ../kpathsea directory; a replacement for
+the makempx script from ../web2c/mpware; and a replacement for the
+dvihp script from ../dviljk. These C programs are primarily for use
+in those environments where the standard Unix shell and utilities
+invoked by the scripts are not readily available. However, they can
+also be used on Unix platforms, although they were tested almost
+exclusively on MS-DOS and MS-Windows systems.
+
+Caveats: currently, the emulation programs don't support edited *.opt
+files, they emulate internally the effect of the original *.opt files
+distributed with Web2c sources. Variables set from the mktex.cnf file
+*are* supported.
+
+All of the programs except dvihp.c were written by Fabrice Popineau
+<popineau@esemetz.ese-metz.fr>. dvihp.c was written by Eli Zaretskii
+<eliz@is.elta.co.il>.
+
+See `INSTALL' for instructions to build and install.
+
+This is free software. See the files COPYING* for copying permissions.
+
diff --git a/Build/source/texk/contrib/config.h b/Build/source/texk/contrib/config.h
new file mode 100644
index 00000000000..aa4a7474013
--- /dev/null
+++ b/Build/source/texk/contrib/config.h
@@ -0,0 +1,11 @@
+/* config.h: master configuration file, included first by all compilable
+ source files (not headers). */
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#ifdef WIN32
+# include <win32lib.h>
+#endif
+
+#endif /* CONFIG_H */
diff --git a/Build/source/texk/contrib/depend.mak b/Build/source/texk/contrib/depend.mak
new file mode 100644
index 00000000000..642d55552f2
--- /dev/null
+++ b/Build/source/texk/contrib/depend.mak
@@ -0,0 +1,559 @@
+$(objdir)/mktex.obj: \
+ stackenv.h \
+ mktexlib.h \
+ $(kpathseadir)/config.h \
+ $(kpathseadir)/c-auto.h \
+ $(kpathseadir)/c-std.h \
+ $(kpathseadir)/c-unistd.h \
+ $(kpathseadir)/systypes.h \
+ $(kpathseadir)/c-memstr.h \
+ $(kpathseadir)/c-errno.h \
+ $(kpathseadir)/c-minmax.h \
+ $(kpathseadir)/c-limits.h \
+ $(kpathseadir)/c-proto.h \
+ $(gnuw32dir)/win32lib.h \
+ $(kpathseadir)/debug.h \
+ $(kpathseadir)/types.h \
+ $(kpathseadir)/lib.h \
+ $(kpathseadir)/progname.h \
+ $(kpathseadir)/kpathsea.h \
+ $(kpathseadir)/absolute.h \
+ $(kpathseadir)/c-ctype.h \
+ $(gnuw32dir)/oldnames.h \
+ $(kpathseadir)/c-dir.h \
+ $(kpathseadir)/c-fopen.h \
+ $(kpathseadir)/c-namemx.h \
+ $(kpathseadir)/c-pathch.h \
+ $(kpathseadir)/c-pathmx.h \
+ $(kpathseadir)/c-stat.h \
+ $(kpathseadir)/c-vararg.h \
+ $(kpathseadir)/cnf.h \
+ $(kpathseadir)/concatn.h \
+ $(kpathseadir)/db.h \
+ $(kpathseadir)/str-list.h \
+ $(kpathseadir)/default.h \
+ $(kpathseadir)/expand.h \
+ $(kpathseadir)/fn.h \
+ $(kpathseadir)/fontmap.h \
+ $(kpathseadir)/hash.h \
+ $(kpathseadir)/getopt.h \
+ $(kpathseadir)/line.h \
+ $(kpathseadir)/magstep.h \
+ $(kpathseadir)/paths.h \
+ $(kpathseadir)/pathsearch.h \
+ $(kpathseadir)/str-llist.h \
+ $(kpathseadir)/proginit.h \
+ $(kpathseadir)/readable.h \
+ $(kpathseadir)/remote.h \
+ $(kpathseadir)/tex-file.h \
+ $(kpathseadir)/tex-glyph.h \
+ $(kpathseadir)/tex-hush.h \
+ $(kpathseadir)/tex-make.h \
+ $(kpathseadir)/tilde.h \
+ $(kpathseadir)/truncate.h \
+ $(kpathseadir)/variable.h \
+ $(kpathseadir)/xopendir.h \
+ $(kpathseadir)/xstat.h \
+ variables.h \
+ fileutils.h \
+ mktex.h
+
+$(objdir)/irun.obj: \
+ $(kpathseadir)/config.h \
+ $(kpathseadir)/c-auto.h \
+ $(kpathseadir)/c-std.h \
+ $(kpathseadir)/c-unistd.h \
+ $(kpathseadir)/systypes.h \
+ $(kpathseadir)/c-memstr.h \
+ $(kpathseadir)/c-errno.h \
+ $(kpathseadir)/c-minmax.h \
+ $(kpathseadir)/c-limits.h \
+ $(kpathseadir)/c-proto.h \
+ $(gnuw32dir)/win32lib.h \
+ $(kpathseadir)/debug.h \
+ $(kpathseadir)/types.h \
+ $(kpathseadir)/lib.h \
+ $(kpathseadir)/progname.h \
+ $(kpathseadir)/proginit.h \
+ $(kpathseadir)/tex-file.h \
+ $(kpathseadir)/c-vararg.h \
+ irun.h
+
+$(objdir)/pdfdde.obj: \
+ $(gnuw32dir)/win32lib.h \
+ $(kpathseadir)/getopt.h
+
+$(objdir)/fmtutil.obj: \
+ $(kpathseadir)/kpathsea.h \
+ $(kpathseadir)/config.h \
+ $(kpathseadir)/c-auto.h \
+ $(kpathseadir)/c-std.h \
+ $(kpathseadir)/c-unistd.h \
+ $(kpathseadir)/systypes.h \
+ $(kpathseadir)/c-memstr.h \
+ $(kpathseadir)/c-errno.h \
+ $(kpathseadir)/c-minmax.h \
+ $(kpathseadir)/c-limits.h \
+ $(kpathseadir)/c-proto.h \
+ $(gnuw32dir)/win32lib.h \
+ $(kpathseadir)/debug.h \
+ $(kpathseadir)/types.h \
+ $(kpathseadir)/lib.h \
+ $(kpathseadir)/progname.h \
+ $(kpathseadir)/absolute.h \
+ $(kpathseadir)/c-ctype.h \
+ $(gnuw32dir)/oldnames.h \
+ $(kpathseadir)/c-dir.h \
+ $(kpathseadir)/c-fopen.h \
+ $(kpathseadir)/c-namemx.h \
+ $(kpathseadir)/c-pathch.h \
+ $(kpathseadir)/c-pathmx.h \
+ $(kpathseadir)/c-stat.h \
+ $(kpathseadir)/c-vararg.h \
+ $(kpathseadir)/cnf.h \
+ $(kpathseadir)/concatn.h \
+ $(kpathseadir)/db.h \
+ $(kpathseadir)/str-list.h \
+ $(kpathseadir)/default.h \
+ $(kpathseadir)/expand.h \
+ $(kpathseadir)/fn.h \
+ $(kpathseadir)/fontmap.h \
+ $(kpathseadir)/hash.h \
+ $(kpathseadir)/getopt.h \
+ $(kpathseadir)/line.h \
+ $(kpathseadir)/magstep.h \
+ $(kpathseadir)/paths.h \
+ $(kpathseadir)/pathsearch.h \
+ $(kpathseadir)/str-llist.h \
+ $(kpathseadir)/proginit.h \
+ $(kpathseadir)/readable.h \
+ $(kpathseadir)/remote.h \
+ $(kpathseadir)/tex-file.h \
+ $(kpathseadir)/tex-glyph.h \
+ $(kpathseadir)/tex-hush.h \
+ $(kpathseadir)/tex-make.h \
+ $(kpathseadir)/tilde.h \
+ $(kpathseadir)/truncate.h \
+ $(kpathseadir)/variable.h \
+ $(kpathseadir)/xopendir.h \
+ $(kpathseadir)/xstat.h \
+ mktex.h \
+ mktexlib.h \
+ fileutils.h \
+ stackenv.h \
+ variables.h \
+ fmtutil.h
+
+$(objdir)/fileutils.obj: \
+ fileutils.h \
+ mktexlib.h \
+ $(kpathseadir)/config.h \
+ $(kpathseadir)/c-auto.h \
+ $(kpathseadir)/c-std.h \
+ $(kpathseadir)/c-unistd.h \
+ $(kpathseadir)/systypes.h \
+ $(kpathseadir)/c-memstr.h \
+ $(kpathseadir)/c-errno.h \
+ $(kpathseadir)/c-minmax.h \
+ $(kpathseadir)/c-limits.h \
+ $(kpathseadir)/c-proto.h \
+ $(gnuw32dir)/win32lib.h \
+ $(kpathseadir)/debug.h \
+ $(kpathseadir)/types.h \
+ $(kpathseadir)/lib.h \
+ $(kpathseadir)/progname.h \
+ $(kpathseadir)/kpathsea.h \
+ $(kpathseadir)/absolute.h \
+ $(kpathseadir)/c-ctype.h \
+ $(gnuw32dir)/oldnames.h \
+ $(kpathseadir)/c-dir.h \
+ $(kpathseadir)/c-fopen.h \
+ $(kpathseadir)/c-namemx.h \
+ $(kpathseadir)/c-pathch.h \
+ $(kpathseadir)/c-pathmx.h \
+ $(kpathseadir)/c-stat.h \
+ $(kpathseadir)/c-vararg.h \
+ $(kpathseadir)/cnf.h \
+ $(kpathseadir)/concatn.h \
+ $(kpathseadir)/db.h \
+ $(kpathseadir)/str-list.h \
+ $(kpathseadir)/default.h \
+ $(kpathseadir)/expand.h \
+ $(kpathseadir)/fn.h \
+ $(kpathseadir)/fontmap.h \
+ $(kpathseadir)/hash.h \
+ $(kpathseadir)/getopt.h \
+ $(kpathseadir)/line.h \
+ $(kpathseadir)/magstep.h \
+ $(kpathseadir)/paths.h \
+ $(kpathseadir)/pathsearch.h \
+ $(kpathseadir)/str-llist.h \
+ $(kpathseadir)/proginit.h \
+ $(kpathseadir)/readable.h \
+ $(kpathseadir)/remote.h \
+ $(kpathseadir)/tex-file.h \
+ $(kpathseadir)/tex-glyph.h \
+ $(kpathseadir)/tex-hush.h \
+ $(kpathseadir)/tex-make.h \
+ $(kpathseadir)/tilde.h \
+ $(kpathseadir)/truncate.h \
+ $(kpathseadir)/variable.h \
+ $(kpathseadir)/xopendir.h \
+ $(kpathseadir)/xstat.h \
+ stackenv.h
+
+$(objdir)/makempx.obj: \
+ mktex.h \
+ mktexlib.h \
+ $(kpathseadir)/config.h \
+ $(kpathseadir)/c-auto.h \
+ $(kpathseadir)/c-std.h \
+ $(kpathseadir)/c-unistd.h \
+ $(kpathseadir)/systypes.h \
+ $(kpathseadir)/c-memstr.h \
+ $(kpathseadir)/c-errno.h \
+ $(kpathseadir)/c-minmax.h \
+ $(kpathseadir)/c-limits.h \
+ $(kpathseadir)/c-proto.h \
+ $(gnuw32dir)/win32lib.h \
+ $(kpathseadir)/debug.h \
+ $(kpathseadir)/types.h \
+ $(kpathseadir)/lib.h \
+ $(kpathseadir)/progname.h \
+ $(kpathseadir)/kpathsea.h \
+ $(kpathseadir)/absolute.h \
+ $(kpathseadir)/c-ctype.h \
+ $(gnuw32dir)/oldnames.h \
+ $(kpathseadir)/c-dir.h \
+ $(kpathseadir)/c-fopen.h \
+ $(kpathseadir)/c-namemx.h \
+ $(kpathseadir)/c-pathch.h \
+ $(kpathseadir)/c-pathmx.h \
+ $(kpathseadir)/c-stat.h \
+ $(kpathseadir)/c-vararg.h \
+ $(kpathseadir)/cnf.h \
+ $(kpathseadir)/concatn.h \
+ $(kpathseadir)/db.h \
+ $(kpathseadir)/str-list.h \
+ $(kpathseadir)/default.h \
+ $(kpathseadir)/expand.h \
+ $(kpathseadir)/fn.h \
+ $(kpathseadir)/fontmap.h \
+ $(kpathseadir)/hash.h \
+ $(kpathseadir)/getopt.h \
+ $(kpathseadir)/line.h \
+ $(kpathseadir)/magstep.h \
+ $(kpathseadir)/paths.h \
+ $(kpathseadir)/pathsearch.h \
+ $(kpathseadir)/str-llist.h \
+ $(kpathseadir)/proginit.h \
+ $(kpathseadir)/readable.h \
+ $(kpathseadir)/remote.h \
+ $(kpathseadir)/tex-file.h \
+ $(kpathseadir)/tex-glyph.h \
+ $(kpathseadir)/tex-hush.h \
+ $(kpathseadir)/tex-make.h \
+ $(kpathseadir)/tilde.h \
+ $(kpathseadir)/truncate.h \
+ $(kpathseadir)/variable.h \
+ $(kpathseadir)/xopendir.h \
+ $(kpathseadir)/xstat.h \
+ stackenv.h \
+ fileutils.h
+
+$(objdir)/stackenv.obj: \
+ stackenv.h \
+ mktexlib.h \
+ $(kpathseadir)/config.h \
+ $(kpathseadir)/c-auto.h \
+ $(kpathseadir)/c-std.h \
+ $(kpathseadir)/c-unistd.h \
+ $(kpathseadir)/systypes.h \
+ $(kpathseadir)/c-memstr.h \
+ $(kpathseadir)/c-errno.h \
+ $(kpathseadir)/c-minmax.h \
+ $(kpathseadir)/c-limits.h \
+ $(kpathseadir)/c-proto.h \
+ $(gnuw32dir)/win32lib.h \
+ $(kpathseadir)/debug.h \
+ $(kpathseadir)/types.h \
+ $(kpathseadir)/lib.h \
+ $(kpathseadir)/progname.h \
+ $(kpathseadir)/kpathsea.h \
+ $(kpathseadir)/absolute.h \
+ $(kpathseadir)/c-ctype.h \
+ $(gnuw32dir)/oldnames.h \
+ $(kpathseadir)/c-dir.h \
+ $(kpathseadir)/c-fopen.h \
+ $(kpathseadir)/c-namemx.h \
+ $(kpathseadir)/c-pathch.h \
+ $(kpathseadir)/c-pathmx.h \
+ $(kpathseadir)/c-stat.h \
+ $(kpathseadir)/c-vararg.h \
+ $(kpathseadir)/cnf.h \
+ $(kpathseadir)/concatn.h \
+ $(kpathseadir)/db.h \
+ $(kpathseadir)/str-list.h \
+ $(kpathseadir)/default.h \
+ $(kpathseadir)/expand.h \
+ $(kpathseadir)/fn.h \
+ $(kpathseadir)/fontmap.h \
+ $(kpathseadir)/hash.h \
+ $(kpathseadir)/getopt.h \
+ $(kpathseadir)/line.h \
+ $(kpathseadir)/magstep.h \
+ $(kpathseadir)/paths.h \
+ $(kpathseadir)/pathsearch.h \
+ $(kpathseadir)/str-llist.h \
+ $(kpathseadir)/proginit.h \
+ $(kpathseadir)/readable.h \
+ $(kpathseadir)/remote.h \
+ $(kpathseadir)/tex-file.h \
+ $(kpathseadir)/tex-glyph.h \
+ $(kpathseadir)/tex-hush.h \
+ $(kpathseadir)/tex-make.h \
+ $(kpathseadir)/tilde.h \
+ $(kpathseadir)/truncate.h \
+ $(kpathseadir)/variable.h \
+ $(kpathseadir)/xopendir.h \
+ $(kpathseadir)/xstat.h \
+ variables.h
+
+$(objdir)/mkofm.obj: \
+ $(gnuw32dir)/win32lib.h
+
+$(objdir)/dvihp.obj: \
+ mktex.h \
+ mktexlib.h \
+ $(kpathseadir)/config.h \
+ $(kpathseadir)/c-auto.h \
+ $(kpathseadir)/c-std.h \
+ $(kpathseadir)/c-unistd.h \
+ $(kpathseadir)/systypes.h \
+ $(kpathseadir)/c-memstr.h \
+ $(kpathseadir)/c-errno.h \
+ $(kpathseadir)/c-minmax.h \
+ $(kpathseadir)/c-limits.h \
+ $(kpathseadir)/c-proto.h \
+ $(gnuw32dir)/win32lib.h \
+ $(kpathseadir)/debug.h \
+ $(kpathseadir)/types.h \
+ $(kpathseadir)/lib.h \
+ $(kpathseadir)/progname.h \
+ $(kpathseadir)/kpathsea.h \
+ $(kpathseadir)/absolute.h \
+ $(kpathseadir)/c-ctype.h \
+ $(gnuw32dir)/oldnames.h \
+ $(kpathseadir)/c-dir.h \
+ $(kpathseadir)/c-fopen.h \
+ $(kpathseadir)/c-namemx.h \
+ $(kpathseadir)/c-pathch.h \
+ $(kpathseadir)/c-pathmx.h \
+ $(kpathseadir)/c-stat.h \
+ $(kpathseadir)/c-vararg.h \
+ $(kpathseadir)/cnf.h \
+ $(kpathseadir)/concatn.h \
+ $(kpathseadir)/db.h \
+ $(kpathseadir)/str-list.h \
+ $(kpathseadir)/default.h \
+ $(kpathseadir)/expand.h \
+ $(kpathseadir)/fn.h \
+ $(kpathseadir)/fontmap.h \
+ $(kpathseadir)/hash.h \
+ $(kpathseadir)/getopt.h \
+ $(kpathseadir)/line.h \
+ $(kpathseadir)/magstep.h \
+ $(kpathseadir)/paths.h \
+ $(kpathseadir)/pathsearch.h \
+ $(kpathseadir)/str-llist.h \
+ $(kpathseadir)/proginit.h \
+ $(kpathseadir)/readable.h \
+ $(kpathseadir)/remote.h \
+ $(kpathseadir)/tex-file.h \
+ $(kpathseadir)/tex-glyph.h \
+ $(kpathseadir)/tex-hush.h \
+ $(kpathseadir)/tex-make.h \
+ $(kpathseadir)/tilde.h \
+ $(kpathseadir)/truncate.h \
+ $(kpathseadir)/variable.h \
+ $(kpathseadir)/xopendir.h \
+ $(kpathseadir)/xstat.h \
+ stackenv.h
+
+$(objdir)/variables.obj: \
+ stackenv.h \
+ mktexlib.h \
+ $(kpathseadir)/config.h \
+ $(kpathseadir)/c-auto.h \
+ $(kpathseadir)/c-std.h \
+ $(kpathseadir)/c-unistd.h \
+ $(kpathseadir)/systypes.h \
+ $(kpathseadir)/c-memstr.h \
+ $(kpathseadir)/c-errno.h \
+ $(kpathseadir)/c-minmax.h \
+ $(kpathseadir)/c-limits.h \
+ $(kpathseadir)/c-proto.h \
+ $(gnuw32dir)/win32lib.h \
+ $(kpathseadir)/debug.h \
+ $(kpathseadir)/types.h \
+ $(kpathseadir)/lib.h \
+ $(kpathseadir)/progname.h \
+ $(kpathseadir)/kpathsea.h \
+ $(kpathseadir)/absolute.h \
+ $(kpathseadir)/c-ctype.h \
+ $(gnuw32dir)/oldnames.h \
+ $(kpathseadir)/c-dir.h \
+ $(kpathseadir)/c-fopen.h \
+ $(kpathseadir)/c-namemx.h \
+ $(kpathseadir)/c-pathch.h \
+ $(kpathseadir)/c-pathmx.h \
+ $(kpathseadir)/c-stat.h \
+ $(kpathseadir)/c-vararg.h \
+ $(kpathseadir)/cnf.h \
+ $(kpathseadir)/concatn.h \
+ $(kpathseadir)/db.h \
+ $(kpathseadir)/str-list.h \
+ $(kpathseadir)/default.h \
+ $(kpathseadir)/expand.h \
+ $(kpathseadir)/fn.h \
+ $(kpathseadir)/fontmap.h \
+ $(kpathseadir)/hash.h \
+ $(kpathseadir)/getopt.h \
+ $(kpathseadir)/line.h \
+ $(kpathseadir)/magstep.h \
+ $(kpathseadir)/paths.h \
+ $(kpathseadir)/pathsearch.h \
+ $(kpathseadir)/str-llist.h \
+ $(kpathseadir)/proginit.h \
+ $(kpathseadir)/readable.h \
+ $(kpathseadir)/remote.h \
+ $(kpathseadir)/tex-file.h \
+ $(kpathseadir)/tex-glyph.h \
+ $(kpathseadir)/tex-hush.h \
+ $(kpathseadir)/tex-make.h \
+ $(kpathseadir)/tilde.h \
+ $(kpathseadir)/truncate.h \
+ $(kpathseadir)/variable.h \
+ $(kpathseadir)/xopendir.h \
+ $(kpathseadir)/xstat.h \
+ fileutils.h \
+ variables.h \
+ $(regexdir)/regex.h
+
+$(objdir)/main.obj: \
+ mktex.h \
+ mktexlib.h \
+ $(kpathseadir)/config.h \
+ $(kpathseadir)/c-auto.h \
+ $(kpathseadir)/c-std.h \
+ $(kpathseadir)/c-unistd.h \
+ $(kpathseadir)/systypes.h \
+ $(kpathseadir)/c-memstr.h \
+ $(kpathseadir)/c-errno.h \
+ $(kpathseadir)/c-minmax.h \
+ $(kpathseadir)/c-limits.h \
+ $(kpathseadir)/c-proto.h \
+ $(gnuw32dir)/win32lib.h \
+ $(kpathseadir)/debug.h \
+ $(kpathseadir)/types.h \
+ $(kpathseadir)/lib.h \
+ $(kpathseadir)/progname.h \
+ $(kpathseadir)/kpathsea.h \
+ $(kpathseadir)/absolute.h \
+ $(kpathseadir)/c-ctype.h \
+ $(gnuw32dir)/oldnames.h \
+ $(kpathseadir)/c-dir.h \
+ $(kpathseadir)/c-fopen.h \
+ $(kpathseadir)/c-namemx.h \
+ $(kpathseadir)/c-pathch.h \
+ $(kpathseadir)/c-pathmx.h \
+ $(kpathseadir)/c-stat.h \
+ $(kpathseadir)/c-vararg.h \
+ $(kpathseadir)/cnf.h \
+ $(kpathseadir)/concatn.h \
+ $(kpathseadir)/db.h \
+ $(kpathseadir)/str-list.h \
+ $(kpathseadir)/default.h \
+ $(kpathseadir)/expand.h \
+ $(kpathseadir)/fn.h \
+ $(kpathseadir)/fontmap.h \
+ $(kpathseadir)/hash.h \
+ $(kpathseadir)/getopt.h \
+ $(kpathseadir)/line.h \
+ $(kpathseadir)/magstep.h \
+ $(kpathseadir)/paths.h \
+ $(kpathseadir)/pathsearch.h \
+ $(kpathseadir)/str-llist.h \
+ $(kpathseadir)/proginit.h \
+ $(kpathseadir)/readable.h \
+ $(kpathseadir)/remote.h \
+ $(kpathseadir)/tex-file.h \
+ $(kpathseadir)/tex-glyph.h \
+ $(kpathseadir)/tex-hush.h \
+ $(kpathseadir)/tex-make.h \
+ $(kpathseadir)/tilde.h \
+ $(kpathseadir)/truncate.h \
+ $(kpathseadir)/variable.h \
+ $(kpathseadir)/xopendir.h \
+ $(kpathseadir)/xstat.h \
+ stackenv.h \
+ variables.h \
+ fileutils.h
+
+$(objdir)/mkocp.obj: \
+ $(kpathseadir)/kpathsea.h \
+ $(kpathseadir)/config.h \
+ $(kpathseadir)/c-auto.h \
+ $(kpathseadir)/c-std.h \
+ $(kpathseadir)/c-unistd.h \
+ $(kpathseadir)/systypes.h \
+ $(kpathseadir)/c-memstr.h \
+ $(kpathseadir)/c-errno.h \
+ $(kpathseadir)/c-minmax.h \
+ $(kpathseadir)/c-limits.h \
+ $(kpathseadir)/c-proto.h \
+ $(gnuw32dir)/win32lib.h \
+ $(kpathseadir)/debug.h \
+ $(kpathseadir)/types.h \
+ $(kpathseadir)/lib.h \
+ $(kpathseadir)/progname.h \
+ $(kpathseadir)/absolute.h \
+ $(kpathseadir)/c-ctype.h \
+ $(gnuw32dir)/oldnames.h \
+ $(kpathseadir)/c-dir.h \
+ $(kpathseadir)/c-fopen.h \
+ $(kpathseadir)/c-namemx.h \
+ $(kpathseadir)/c-pathch.h \
+ $(kpathseadir)/c-pathmx.h \
+ $(kpathseadir)/c-stat.h \
+ $(kpathseadir)/c-vararg.h \
+ $(kpathseadir)/cnf.h \
+ $(kpathseadir)/concatn.h \
+ $(kpathseadir)/db.h \
+ $(kpathseadir)/str-list.h \
+ $(kpathseadir)/default.h \
+ $(kpathseadir)/expand.h \
+ $(kpathseadir)/fn.h \
+ $(kpathseadir)/fontmap.h \
+ $(kpathseadir)/hash.h \
+ $(kpathseadir)/getopt.h \
+ $(kpathseadir)/line.h \
+ $(kpathseadir)/magstep.h \
+ $(kpathseadir)/paths.h \
+ $(kpathseadir)/pathsearch.h \
+ $(kpathseadir)/str-llist.h \
+ $(kpathseadir)/proginit.h \
+ $(kpathseadir)/readable.h \
+ $(kpathseadir)/remote.h \
+ $(kpathseadir)/tex-file.h \
+ $(kpathseadir)/tex-glyph.h \
+ $(kpathseadir)/tex-hush.h \
+ $(kpathseadir)/tex-make.h \
+ $(kpathseadir)/tilde.h \
+ $(kpathseadir)/truncate.h \
+ $(kpathseadir)/variable.h \
+ $(kpathseadir)/xopendir.h \
+ $(kpathseadir)/xstat.h \
+ stackenv.h \
+ mktexlib.h
+
diff --git a/Build/source/texk/contrib/depend.mk b/Build/source/texk/contrib/depend.mk
new file mode 100644
index 00000000000..d34121b3e2e
--- /dev/null
+++ b/Build/source/texk/contrib/depend.mk
@@ -0,0 +1,155 @@
+# DO NOT DELETE
+
+$(objdir)/dvihp.obj: dvihp.c stackenv.h mktexlib.h $(kpathsea_srcdir)/config.h \
+ $(kpathsea_dir)/c-auto.h $(kpathsea_srcdir)/win32lib.h $(kpathsea_dir)/c-auto.h \
+ $(kpathsea_srcdir)/c-proto.h $(kpathsea_srcdir)/c-std.h $(kpathsea_srcdir)/c-unistd.h \
+ $(kpathsea_srcdir)/systypes.h $(kpathsea_srcdir)/c-memstr.h $(kpathsea_srcdir)/c-errno.h \
+ $(kpathsea_srcdir)/c-minmax.h $(kpathsea_srcdir)/c-limits.h $(kpathsea_srcdir)/debug.h \
+ $(kpathsea_srcdir)/types.h $(kpathsea_srcdir)/lib.h $(kpathsea_srcdir)/progname.h \
+ $(kpathsea_srcdir)/kpathsea.h $(kpathsea_srcdir)/absolute.h $(kpathsea_srcdir)/c-ctype.h \
+ $(kpathsea_srcdir)/c-dir.h $(kpathsea_srcdir)/c-fopen.h $(kpathsea_srcdir)/c-namemx.h \
+ $(kpathsea_srcdir)/c-pathch.h $(kpathsea_srcdir)/c-pathmx.h $(kpathsea_srcdir)/c-stat.h \
+ $(kpathsea_srcdir)/c-vararg.h $(kpathsea_srcdir)/cnf.h $(kpathsea_srcdir)/concatn.h \
+ $(kpathsea_srcdir)/db.h $(kpathsea_srcdir)/str-list.h $(kpathsea_srcdir)/default.h \
+ $(kpathsea_srcdir)/expand.h $(kpathsea_srcdir)/fn.h $(kpathsea_srcdir)/fontmap.h \
+ $(kpathsea_srcdir)/hash.h $(kpathsea_srcdir)/getopt.h $(kpathsea_srcdir)/line.h \
+ $(kpathsea_srcdir)/magstep.h $(kpathsea_dir)/paths.h $(kpathsea_srcdir)/pathsearch.h \
+ $(kpathsea_srcdir)/str-llist.h $(kpathsea_srcdir)/proginit.h $(kpathsea_srcdir)/readable.h \
+ $(kpathsea_srcdir)/tex-file.h $(kpathsea_srcdir)/tex-glyph.h $(kpathsea_srcdir)/tex-hush.h \
+ $(kpathsea_srcdir)/tex-make.h $(kpathsea_srcdir)/tilde.h $(kpathsea_srcdir)/truncate.h \
+ $(kpathsea_srcdir)/variable.h $(kpathsea_srcdir)/xopendir.h $(kpathsea_srcdir)/xstat.h \
+ fileutils.h
+$(objdir)/fileutils.obj: fileutils.c mktexlib.h $(kpathsea_srcdir)/config.h \
+ $(kpathsea_dir)/c-auto.h $(kpathsea_srcdir)/win32lib.h $(kpathsea_dir)/c-auto.h \
+ $(kpathsea_srcdir)/c-proto.h $(kpathsea_srcdir)/c-std.h $(kpathsea_srcdir)/c-unistd.h \
+ $(kpathsea_srcdir)/systypes.h $(kpathsea_srcdir)/c-memstr.h $(kpathsea_srcdir)/c-errno.h \
+ $(kpathsea_srcdir)/c-minmax.h $(kpathsea_srcdir)/c-limits.h $(kpathsea_srcdir)/debug.h \
+ $(kpathsea_srcdir)/types.h $(kpathsea_srcdir)/lib.h $(kpathsea_srcdir)/progname.h \
+ $(kpathsea_srcdir)/kpathsea.h $(kpathsea_srcdir)/absolute.h $(kpathsea_srcdir)/c-ctype.h \
+ $(kpathsea_srcdir)/c-dir.h $(kpathsea_srcdir)/c-fopen.h $(kpathsea_srcdir)/c-namemx.h \
+ $(kpathsea_srcdir)/c-pathch.h $(kpathsea_srcdir)/c-pathmx.h $(kpathsea_srcdir)/c-stat.h \
+ $(kpathsea_srcdir)/c-vararg.h $(kpathsea_srcdir)/cnf.h $(kpathsea_srcdir)/concatn.h \
+ $(kpathsea_srcdir)/db.h $(kpathsea_srcdir)/str-list.h $(kpathsea_srcdir)/default.h \
+ $(kpathsea_srcdir)/expand.h $(kpathsea_srcdir)/fn.h $(kpathsea_srcdir)/fontmap.h \
+ $(kpathsea_srcdir)/hash.h $(kpathsea_srcdir)/getopt.h $(kpathsea_srcdir)/line.h \
+ $(kpathsea_srcdir)/magstep.h $(kpathsea_dir)/paths.h $(kpathsea_srcdir)/pathsearch.h \
+ $(kpathsea_srcdir)/str-llist.h $(kpathsea_srcdir)/proginit.h $(kpathsea_srcdir)/readable.h \
+ $(kpathsea_srcdir)/tex-file.h $(kpathsea_srcdir)/tex-glyph.h $(kpathsea_srcdir)/tex-hush.h \
+ $(kpathsea_srcdir)/tex-make.h $(kpathsea_srcdir)/tilde.h $(kpathsea_srcdir)/truncate.h \
+ $(kpathsea_srcdir)/variable.h $(kpathsea_srcdir)/xopendir.h $(kpathsea_srcdir)/xstat.h \
+ stackenv.h
+$(objdir)/fmtutil.obj: fmtutil.c $(kpathsea_srcdir)/kpathsea.h $(kpathsea_srcdir)/config.h \
+ $(kpathsea_dir)/c-auto.h $(kpathsea_srcdir)/win32lib.h $(kpathsea_dir)/c-auto.h \
+ $(kpathsea_srcdir)/c-proto.h $(kpathsea_srcdir)/c-std.h $(kpathsea_srcdir)/c-unistd.h \
+ $(kpathsea_srcdir)/systypes.h $(kpathsea_srcdir)/c-memstr.h $(kpathsea_srcdir)/c-errno.h \
+ $(kpathsea_srcdir)/c-minmax.h $(kpathsea_srcdir)/c-limits.h $(kpathsea_srcdir)/debug.h \
+ $(kpathsea_srcdir)/types.h $(kpathsea_srcdir)/lib.h $(kpathsea_srcdir)/progname.h \
+ $(kpathsea_srcdir)/absolute.h $(kpathsea_srcdir)/c-ctype.h $(kpathsea_srcdir)/c-dir.h \
+ $(kpathsea_srcdir)/c-fopen.h $(kpathsea_srcdir)/c-namemx.h $(kpathsea_srcdir)/c-pathch.h \
+ $(kpathsea_srcdir)/c-pathmx.h $(kpathsea_srcdir)/c-stat.h $(kpathsea_srcdir)/c-vararg.h \
+ $(kpathsea_srcdir)/cnf.h $(kpathsea_srcdir)/concatn.h $(kpathsea_srcdir)/db.h \
+ $(kpathsea_srcdir)/str-list.h $(kpathsea_srcdir)/default.h $(kpathsea_srcdir)/expand.h \
+ $(kpathsea_srcdir)/fn.h $(kpathsea_srcdir)/fontmap.h $(kpathsea_srcdir)/hash.h \
+ $(kpathsea_srcdir)/getopt.h $(kpathsea_srcdir)/line.h $(kpathsea_srcdir)/magstep.h \
+ $(kpathsea_dir)/paths.h $(kpathsea_srcdir)/pathsearch.h $(kpathsea_srcdir)/str-llist.h \
+ $(kpathsea_srcdir)/proginit.h $(kpathsea_srcdir)/readable.h $(kpathsea_srcdir)/tex-file.h \
+ $(kpathsea_srcdir)/tex-glyph.h $(kpathsea_srcdir)/tex-hush.h $(kpathsea_srcdir)/tex-make.h \
+ $(kpathsea_srcdir)/tilde.h $(kpathsea_srcdir)/truncate.h $(kpathsea_srcdir)/variable.h \
+ $(kpathsea_srcdir)/xopendir.h $(kpathsea_srcdir)/xstat.h fileutils.h mktexlib.h \
+ stackenv.h variables.h fmtutil.h
+$(objdir)/main.obj: main.c stackenv.h mktexlib.h $(kpathsea_srcdir)/config.h \
+ $(kpathsea_dir)/c-auto.h $(kpathsea_srcdir)/win32lib.h $(kpathsea_dir)/c-auto.h \
+ $(kpathsea_srcdir)/c-proto.h $(kpathsea_srcdir)/c-std.h $(kpathsea_srcdir)/c-unistd.h \
+ $(kpathsea_srcdir)/systypes.h $(kpathsea_srcdir)/c-memstr.h $(kpathsea_srcdir)/c-errno.h \
+ $(kpathsea_srcdir)/c-minmax.h $(kpathsea_srcdir)/c-limits.h $(kpathsea_srcdir)/debug.h \
+ $(kpathsea_srcdir)/types.h $(kpathsea_srcdir)/lib.h $(kpathsea_srcdir)/progname.h \
+ $(kpathsea_srcdir)/kpathsea.h $(kpathsea_srcdir)/absolute.h $(kpathsea_srcdir)/c-ctype.h \
+ $(kpathsea_srcdir)/c-dir.h $(kpathsea_srcdir)/c-fopen.h $(kpathsea_srcdir)/c-namemx.h \
+ $(kpathsea_srcdir)/c-pathch.h $(kpathsea_srcdir)/c-pathmx.h $(kpathsea_srcdir)/c-stat.h \
+ $(kpathsea_srcdir)/c-vararg.h $(kpathsea_srcdir)/cnf.h $(kpathsea_srcdir)/concatn.h \
+ $(kpathsea_srcdir)/db.h $(kpathsea_srcdir)/str-list.h $(kpathsea_srcdir)/default.h \
+ $(kpathsea_srcdir)/expand.h $(kpathsea_srcdir)/fn.h $(kpathsea_srcdir)/fontmap.h \
+ $(kpathsea_srcdir)/hash.h $(kpathsea_srcdir)/getopt.h $(kpathsea_srcdir)/line.h \
+ $(kpathsea_srcdir)/magstep.h $(kpathsea_dir)/paths.h $(kpathsea_srcdir)/pathsearch.h \
+ $(kpathsea_srcdir)/str-llist.h $(kpathsea_srcdir)/proginit.h $(kpathsea_srcdir)/readable.h \
+ $(kpathsea_srcdir)/tex-file.h $(kpathsea_srcdir)/tex-glyph.h $(kpathsea_srcdir)/tex-hush.h \
+ $(kpathsea_srcdir)/tex-make.h $(kpathsea_srcdir)/tilde.h $(kpathsea_srcdir)/truncate.h \
+ $(kpathsea_srcdir)/variable.h $(kpathsea_srcdir)/xopendir.h $(kpathsea_srcdir)/xstat.h mktex.h \
+ stackenv.h
+$(objdir)/makempx.obj: makempx.c mktexlib.h $(kpathsea_srcdir)/config.h \
+ $(kpathsea_dir)/c-auto.h $(kpathsea_srcdir)/win32lib.h $(kpathsea_dir)/c-auto.h \
+ $(kpathsea_srcdir)/c-proto.h $(kpathsea_srcdir)/c-std.h $(kpathsea_srcdir)/c-unistd.h \
+ $(kpathsea_srcdir)/systypes.h $(kpathsea_srcdir)/c-memstr.h $(kpathsea_srcdir)/c-errno.h \
+ $(kpathsea_srcdir)/c-minmax.h $(kpathsea_srcdir)/c-limits.h $(kpathsea_srcdir)/debug.h \
+ $(kpathsea_srcdir)/types.h $(kpathsea_srcdir)/lib.h $(kpathsea_srcdir)/progname.h \
+ $(kpathsea_srcdir)/kpathsea.h $(kpathsea_srcdir)/absolute.h $(kpathsea_srcdir)/c-ctype.h \
+ $(kpathsea_srcdir)/c-dir.h $(kpathsea_srcdir)/c-fopen.h $(kpathsea_srcdir)/c-namemx.h \
+ $(kpathsea_srcdir)/c-pathch.h $(kpathsea_srcdir)/c-pathmx.h $(kpathsea_srcdir)/c-stat.h \
+ $(kpathsea_srcdir)/c-vararg.h $(kpathsea_srcdir)/cnf.h $(kpathsea_srcdir)/concatn.h \
+ $(kpathsea_srcdir)/db.h $(kpathsea_srcdir)/str-list.h $(kpathsea_srcdir)/default.h \
+ $(kpathsea_srcdir)/expand.h $(kpathsea_srcdir)/fn.h $(kpathsea_srcdir)/fontmap.h \
+ $(kpathsea_srcdir)/hash.h $(kpathsea_srcdir)/getopt.h $(kpathsea_srcdir)/line.h \
+ $(kpathsea_srcdir)/magstep.h $(kpathsea_dir)/paths.h $(kpathsea_srcdir)/pathsearch.h \
+ $(kpathsea_srcdir)/str-llist.h $(kpathsea_srcdir)/proginit.h $(kpathsea_srcdir)/readable.h \
+ $(kpathsea_srcdir)/tex-file.h $(kpathsea_srcdir)/tex-glyph.h $(kpathsea_srcdir)/tex-hush.h \
+ $(kpathsea_srcdir)/tex-make.h $(kpathsea_srcdir)/tilde.h $(kpathsea_srcdir)/truncate.h \
+ $(kpathsea_srcdir)/variable.h $(kpathsea_srcdir)/xopendir.h $(kpathsea_srcdir)/xstat.h \
+ fileutils.h
+$(objdir)/mktex.obj: mktex.c stackenv.h mktexlib.h $(kpathsea_srcdir)/config.h \
+ $(kpathsea_dir)/c-auto.h $(kpathsea_srcdir)/win32lib.h $(kpathsea_dir)/c-auto.h \
+ $(kpathsea_srcdir)/c-proto.h $(kpathsea_srcdir)/c-std.h $(kpathsea_srcdir)/c-unistd.h \
+ $(kpathsea_srcdir)/systypes.h $(kpathsea_srcdir)/c-memstr.h $(kpathsea_srcdir)/c-errno.h \
+ $(kpathsea_srcdir)/c-minmax.h $(kpathsea_srcdir)/c-limits.h $(kpathsea_srcdir)/debug.h \
+ $(kpathsea_srcdir)/types.h $(kpathsea_srcdir)/lib.h $(kpathsea_srcdir)/progname.h \
+ $(kpathsea_srcdir)/kpathsea.h $(kpathsea_srcdir)/absolute.h $(kpathsea_srcdir)/c-ctype.h \
+ $(kpathsea_srcdir)/c-dir.h $(kpathsea_srcdir)/c-fopen.h $(kpathsea_srcdir)/c-namemx.h \
+ $(kpathsea_srcdir)/c-pathch.h $(kpathsea_srcdir)/c-pathmx.h $(kpathsea_srcdir)/c-stat.h \
+ $(kpathsea_srcdir)/c-vararg.h $(kpathsea_srcdir)/cnf.h $(kpathsea_srcdir)/concatn.h \
+ $(kpathsea_srcdir)/db.h $(kpathsea_srcdir)/str-list.h $(kpathsea_srcdir)/default.h \
+ $(kpathsea_srcdir)/expand.h $(kpathsea_srcdir)/fn.h $(kpathsea_srcdir)/fontmap.h \
+ $(kpathsea_srcdir)/hash.h $(kpathsea_srcdir)/getopt.h $(kpathsea_srcdir)/line.h \
+ $(kpathsea_srcdir)/magstep.h $(kpathsea_dir)/paths.h $(kpathsea_srcdir)/pathsearch.h \
+ $(kpathsea_srcdir)/str-llist.h $(kpathsea_srcdir)/proginit.h $(kpathsea_srcdir)/readable.h \
+ $(kpathsea_srcdir)/tex-file.h $(kpathsea_srcdir)/tex-glyph.h $(kpathsea_srcdir)/tex-hush.h \
+ $(kpathsea_srcdir)/tex-make.h $(kpathsea_srcdir)/tilde.h $(kpathsea_srcdir)/truncate.h \
+ $(kpathsea_srcdir)/variable.h $(kpathsea_srcdir)/xopendir.h $(kpathsea_srcdir)/xstat.h \
+ variables.h fileutils.h mktex.h
+$(objdir)/stackenv.obj: stackenv.c stackenv.h mktexlib.h $(kpathsea_srcdir)/config.h \
+ $(kpathsea_dir)/c-auto.h $(kpathsea_srcdir)/win32lib.h $(kpathsea_dir)/c-auto.h \
+ $(kpathsea_srcdir)/c-proto.h $(kpathsea_srcdir)/c-std.h $(kpathsea_srcdir)/c-unistd.h \
+ $(kpathsea_srcdir)/systypes.h $(kpathsea_srcdir)/c-memstr.h $(kpathsea_srcdir)/c-errno.h \
+ $(kpathsea_srcdir)/c-minmax.h $(kpathsea_srcdir)/c-limits.h $(kpathsea_srcdir)/debug.h \
+ $(kpathsea_srcdir)/types.h $(kpathsea_srcdir)/lib.h $(kpathsea_srcdir)/progname.h \
+ $(kpathsea_srcdir)/kpathsea.h $(kpathsea_srcdir)/absolute.h $(kpathsea_srcdir)/c-ctype.h \
+ $(kpathsea_srcdir)/c-dir.h $(kpathsea_srcdir)/c-fopen.h $(kpathsea_srcdir)/c-namemx.h \
+ $(kpathsea_srcdir)/c-pathch.h $(kpathsea_srcdir)/c-pathmx.h $(kpathsea_srcdir)/c-stat.h \
+ $(kpathsea_srcdir)/c-vararg.h $(kpathsea_srcdir)/cnf.h $(kpathsea_srcdir)/concatn.h \
+ $(kpathsea_srcdir)/db.h $(kpathsea_srcdir)/str-list.h $(kpathsea_srcdir)/default.h \
+ $(kpathsea_srcdir)/expand.h $(kpathsea_srcdir)/fn.h $(kpathsea_srcdir)/fontmap.h \
+ $(kpathsea_srcdir)/hash.h $(kpathsea_srcdir)/getopt.h $(kpathsea_srcdir)/line.h \
+ $(kpathsea_srcdir)/magstep.h $(kpathsea_dir)/paths.h $(kpathsea_srcdir)/pathsearch.h \
+ $(kpathsea_srcdir)/str-llist.h $(kpathsea_srcdir)/proginit.h $(kpathsea_srcdir)/readable.h \
+ $(kpathsea_srcdir)/tex-file.h $(kpathsea_srcdir)/tex-glyph.h $(kpathsea_srcdir)/tex-hush.h \
+ $(kpathsea_srcdir)/tex-make.h $(kpathsea_srcdir)/tilde.h $(kpathsea_srcdir)/truncate.h \
+ $(kpathsea_srcdir)/variable.h $(kpathsea_srcdir)/xopendir.h $(kpathsea_srcdir)/xstat.h \
+ variables.h
+$(objdir)/variables.obj: variables.c stackenv.h mktexlib.h \
+ $(kpathsea_srcdir)/config.h $(kpathsea_dir)/c-auto.h $(kpathsea_srcdir)/win32lib.h \
+ $(kpathsea_dir)/c-auto.h $(kpathsea_srcdir)/c-proto.h $(kpathsea_srcdir)/c-std.h \
+ $(kpathsea_srcdir)/c-unistd.h $(kpathsea_srcdir)/systypes.h $(kpathsea_srcdir)/c-memstr.h \
+ $(kpathsea_srcdir)/c-errno.h $(kpathsea_srcdir)/c-minmax.h $(kpathsea_srcdir)/c-limits.h \
+ $(kpathsea_srcdir)/debug.h $(kpathsea_srcdir)/types.h $(kpathsea_srcdir)/lib.h \
+ $(kpathsea_srcdir)/progname.h $(kpathsea_srcdir)/kpathsea.h $(kpathsea_srcdir)/absolute.h \
+ $(kpathsea_srcdir)/c-ctype.h $(kpathsea_srcdir)/c-dir.h $(kpathsea_srcdir)/c-fopen.h \
+ $(kpathsea_srcdir)/c-namemx.h $(kpathsea_srcdir)/c-pathch.h $(kpathsea_srcdir)/c-pathmx.h \
+ $(kpathsea_srcdir)/c-stat.h $(kpathsea_srcdir)/c-vararg.h $(kpathsea_srcdir)/cnf.h \
+ $(kpathsea_srcdir)/concatn.h $(kpathsea_srcdir)/db.h $(kpathsea_srcdir)/str-list.h \
+ $(kpathsea_srcdir)/default.h $(kpathsea_srcdir)/expand.h $(kpathsea_srcdir)/fn.h \
+ $(kpathsea_srcdir)/fontmap.h $(kpathsea_srcdir)/hash.h $(kpathsea_srcdir)/getopt.h \
+ $(kpathsea_srcdir)/line.h $(kpathsea_srcdir)/magstep.h $(kpathsea_dir)/paths.h \
+ $(kpathsea_srcdir)/pathsearch.h $(kpathsea_srcdir)/str-llist.h $(kpathsea_srcdir)/proginit.h \
+ $(kpathsea_srcdir)/readable.h $(kpathsea_srcdir)/tex-file.h $(kpathsea_srcdir)/tex-glyph.h \
+ $(kpathsea_srcdir)/tex-hush.h $(kpathsea_srcdir)/tex-make.h $(kpathsea_srcdir)/tilde.h \
+ $(kpathsea_srcdir)/truncate.h $(kpathsea_srcdir)/variable.h $(kpathsea_srcdir)/xopendir.h \
+ $(kpathsea_srcdir)/xstat.h fileutils.h variables.h \
+ $(root_srcdir)/libs/regex-0.12/regex.h
diff --git a/Build/source/texk/contrib/dvihp.c b/Build/source/texk/contrib/dvihp.c
new file mode 100644
index 00000000000..e595f734d16
--- /dev/null
+++ b/Build/source/texk/contrib/dvihp.c
@@ -0,0 +1,433 @@
+/* dvihp.c: emulate the dvihp shell script
+
+ Converted to C by Eli Zaretskii <eliz@is.elta.co.il>
+ Adapted to Win32 by Fabrice POPINEAU
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This 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 this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "mktex.h"
+#include "stackenv.h"
+
+static const char rcs_id[] =
+ "$Id: dvihp.c,v 1.7 2002/10/06 14:02:09 olaf Exp $";
+static char rcs_revision[] = "$Revision: 1.7 $";
+
+static void usage (void)
+{
+ printf ("Usage: %s [OPTIONS] [DVIFILE[.dvi]].\n\
+ Translate the given DVIFILE to Hewlett-Packard PCL by calling dvicopy\n\
+ and then $DVILJ (dvilj4 by default).\n\
+ In the absence of other options, pipe the PCL to $SPOOL (lpr by default).\n\
+\n\
+ Options are recognized from dvips where possible:\n\
+-A print odd pages\n\
+-B print even pages\n\
+-d # set debug bits to # (see documentation)\n\
+-D # set resolution to #\n\
+-f run as filter\n\
+-l # don't print pages after #\n\
+-m manual feed\n\
+-n # print # pages\n\
+-O #,# set/change paper offset to #,# mm\n\
+-o s output to s instead of spooling\n\
+-p # don't print pages before #\n\
+-Ps pass directly to lpr\n\
+-v verbose operation\n\
+-x # set magnification to #\n\
+\n\
+Other options are passed to the dvilj program.\n\
+\n\
+Email bug reports to tex-k@mail.tug.org.\n", program_invocation_short_name);
+ fflush (stdout);
+}
+
+/* Emulate `rm -f prefix*' */
+
+void rmfiles (const_string prefix)
+{
+#ifdef _WIN32
+ /* Win32 doesn't have POSIX dirent functions. */
+ WIN32_FIND_DATA ffd;
+ HANDLE hnd;
+ boolean go_on;
+ string temp = concat (prefix, "*");
+ string directory = xdirname (prefix);
+
+ pushd (directory);
+ hnd = FindFirstFile(temp, &ffd);
+ go_on = (hnd != INVALID_HANDLE_VALUE);
+ while (go_on) {
+ /* FIXME: can this remove read-only files also, like rm -f does? */
+ DeleteFile(ffd.cFileName);
+ go_on = (FindNextFile(hnd, &ffd) == TRUE);
+ }
+ FindClose(hnd);
+ free(temp);
+ popd ();
+#else /* not _WIN32 */
+ DIR *dp;
+ struct dirent *de;
+ int temp_len = strlen (prefix);
+ string directory = "./";
+ const_string base = xbasename (prefix);
+
+ /* Copy the directory part of PREFIX with the trailing slash, if any. */
+ if (base != prefix)
+ {
+ directory = (string) xmalloc (base - prefix + 1);
+ directory[0] = '\0';
+ strncat (directory, prefix, base - prefix);
+ }
+
+ /* Find matching files and delete them. */
+ if ((dp = opendir (directory)) != 0) {
+ while ((de = readdir (dp)) != 0)
+ {
+ string found = concat (directory, de->d_name);
+
+ if (FILESTRNCASEEQ (found, prefix, temp_len))
+ /* On POSIX-compliant systems, including DJGPP, this will also
+ remove read-only files and empty directories, like rm -f does. */
+ if (remove (found))
+ perror (found);
+ free (found);
+ }
+ }
+#endif /* not _WIN32 */
+}
+
+void __cdecl output_and_cleanup(int code)
+{
+ /* FIXME : what cleanup should be done ? */
+}
+
+int
+main (int argc, char *argv[])
+{
+ string opt = (string) xmalloc (1);
+ string output = "", infile = "";
+ string output_opt = " -e";
+ string dvilj;
+ string spool;
+ string tmpdir;
+ string spool_opt = "";
+ char template[PATH_MAX];
+ string vfless_dvi, dvicopy_log, dvilj_log;
+ int verbose = 0;
+ string cmdline, maybe_spool_cmd = "";
+ const_string space = " ";
+
+ output_and_cleanup_function = output_and_cleanup;
+
+ progname = argv[0];
+ kpse_set_progname (progname);
+
+#ifdef _WIN32
+ SetConsoleCtrlHandler((PHANDLER_ROUTINE)mt_exit, TRUE);
+#else
+# ifdef SIGINT
+ signal (SIGINT, sigint_handler);
+# endif
+# ifdef SIGQUIT
+ signal (SIGQUIT, sigint_handler);
+# endif
+# ifdef SIGHUP
+ signal (SIGHUP, sigint_handler);
+# endif
+# ifdef SIGTERM
+ signal (SIGTERM, sigint_handler);
+# endif
+#endif
+
+ dvilj = kpse_var_value ("DVILJ");
+ spool = kpse_var_value ("SPOOL");
+ tmpdir = kpse_var_value ("TMPDIR");
+ opt[0] = '\0';
+
+ /* Set default values for variables:
+
+ ${DVILJ=dvilj4} the dvilj variant to run
+ ${SPOOL=lpr} used to print an LJ file
+ ${TMPDIR=/tmp} for the dvicopy output */
+ if (!dvilj || !*dvilj)
+ dvilj = "dvilj4";
+ if (!spool || !*spool)
+ {
+#ifdef __DJGPP__
+ /* Feature: if they don't have LPR installed, make the
+ default be to print to the local printer device. */
+ char lpr_path[PATH_MAX];
+ extern char *__dosexec_find_on_path (const char *, char **, char *);
+ extern char **environ;
+
+ if (!__dosexec_find_on_path ("lpr", (char **)0, lpr_path)
+ && !__dosexec_find_on_path ("lpr", environ, lpr_path))
+ spool = "> PRN";
+ else
+#endif
+ spool = "| lpr";
+ }
+
+ if (!tmpdir || !*tmpdir)
+ {
+ tmpdir = "/tmp";
+ if (access (tmpdir, R_OK|W_OK) != 0)
+ {
+ mkdir (tmpdir, 0755);
+#ifdef DOSISH
+ if (access (tmpdir, R_OK|W_OK) != 0)
+ {
+ /* Maybe this is a read-only filesystem (CD-ROM)? */
+ tmpdir = "c:/tmp";
+ mkdir (tmpdir, 0755); /* in case they don't have it */
+ }
+#endif
+ }
+ }
+
+ if (argc <= 1)
+ {
+ fprintf (stderr, "%s: Missing argument(s).\nTry `%s --help' for more information.\n",
+ program_invocation_short_name, program_invocation_short_name);
+ return 0;
+ }
+
+ while (--argc)
+ {
+ char *arg = *++argv;
+
+ if (STREQ (arg, "-help") || STREQ (arg, "--help"))
+ {
+ usage ();
+ return 0;
+ }
+ else if (STREQ (arg, "-version") || STREQ (arg, "--version"))
+ {
+ printf ("%s: (Dviljk 2.6) %s\nThere is NO warranty. This program is public domain.\n",
+ program_invocation_short_name, rcs_revision);
+ return 0;
+ }
+ else if (arg[0] == '-')
+ {
+ string newopt = NULL;
+
+ switch (arg[1])
+ {
+ case 'A': /* -A => -D1 (odd pages) */
+ newopt = concat (opt, " -D1");
+ break;
+ case 'B': /* -B -> -D2 (even pages) */
+ newopt = concat (opt, " -D2");
+ break;
+ case 'd': /* -d => --D (debug) */
+ if (arg[2] == '\0')
+ {
+ argc--;
+ newopt = concat3 (opt, " --D", *++argv);
+ }
+ else
+ newopt = concat3 (opt, " --D", arg + 2);
+ break;
+ case 'D': /* -D => -R (resolution) */
+ argc--;
+ newopt = concat3 (opt, " -R", *++argv);
+ break;
+ case 'f': /* -f (run as filter) */
+ infile = "";
+ output = "-";
+ break;
+ case 'l': /* -l => -t (ending page) */
+ if (arg[2] == '\0')
+ {
+ argc--;
+ newopt = concat3 (opt, " -t", *++argv);
+ }
+ else
+ newopt = concat3 (opt, " -t", arg + 2);
+ break;
+ case 'm': /* -m => -A (manual feed) */
+ newopt = concat (opt, " -A");
+ break;
+ case 'n': /* -n => -p (page count) */
+ if (arg[2] == '\0')
+ {
+ argc--;
+ newopt = concat3 (opt, " -t", *++argv);
+ }
+ else
+ newopt = concat3 (opt, " -t", arg + 2);
+ break;
+ case 'o': /* -o (output file) */
+ {
+ string inbase = xstrdup (xbasename (infile));
+ if (argc == 1 && *inbase)
+ {
+ /* No remaining args, output to foo.lj. */
+ int inbaselen = strlen (inbase);
+
+ if (FILESTRCASEEQ (inbase + inbaselen - 4, ".dvi"))
+ output = strcpy (inbase + inbaselen - 4, ".lj");
+ else
+ {
+#if defined (MSDOS) && defined _PC_NAME_MAX
+ if (pathconf (infile, _PC_NAME_MAX) <= 12)
+ {
+ /* Plain MS-DOS (not Windows 95), can't have
+ more than a single dot in a filename. */
+ char *dot = strchr (inbase, '.');
+
+ if (dot)
+ *dot = '\0';
+ }
+#endif
+ output = concat (inbase, ".lj");
+ free (inbase);
+ }
+ }
+ else if (arg[2] == '\0')
+ {
+ argc--;
+ output = *++argv;
+ }
+ else
+ output = arg + 2;
+ break;
+ }
+ case 'O': /* -O => -x, -y (page offsets) */
+ {
+ int x_len;
+ char *params = arg + 2;
+ char *x;
+
+ if (arg[2] == '\0')
+ {
+ argc--;
+ params = *++argv;
+ }
+
+ x_len = strcspn (params, ",");
+ x = (char *)xmalloc (x_len + 1);
+ x[0] = '\0';
+ strncat (x, params, x_len);
+ if (params[x_len] == ',')
+ x_len++; /* get past the comma, if any */
+ newopt = concatn (opt, " -x", x, " y", params + x_len, NULL);
+ break;
+ }
+ case 'p': /* -p => -f (starting page) */
+ if (arg[2] == '\0')
+ {
+ argc--;
+ newopt = concat3 (opt, " -f", *++argv);
+ }
+ else
+ newopt = concat3 (opt, " -f", arg + 2);
+ break;
+ case 'P': /* -Pprinter */
+ output = "";
+ if (spool[0] == '>') /* direct printing: replace device */
+ spool = concat ("> ", arg[2] ? arg + 2 : *++argv);
+ else
+ spool_opt = concat ("-P", arg[2] ? arg + 2 : *++argv);
+ if (arg[2] == '\0')
+ argc--;
+ break;
+ case 'v': /* verbose */
+ verbose = 1;
+ newopt = concat (opt, " -v");
+ break;
+ case 'x': /* -x => -m (magnification) */
+ if (arg[2] == '\0')
+ {
+ argc--;
+ newopt = concat3 (opt, " -m", *++argv);
+ }
+ else
+ newopt = concat3 (opt, " -m", arg + 2);
+ break;
+ case '-': /* -- => end of options */
+ argc--;
+ infile = *++argv;
+ break;
+ default: /* pass other options through */
+ newopt = concat3 (opt, space, arg);
+ break;
+ }
+
+ if (newopt)
+ {
+ free (opt);
+ opt = newopt;
+ }
+ }
+ else
+ infile = arg;
+ }
+
+ /* Generate temporary filenames. Assumes PID is 5 digits. */
+ sprintf (template, "%s/dvi%5.5d.", tmpdir, getpid ());
+ vfless_dvi = concat (template, "-vf");
+ /* FIXME: where are these two used? */
+ dvicopy_log = concat (template, "copy");
+ dvilj_log = concat (template, "lj");
+
+ /* Expand VF references.
+ If INFILE is null, this will read standard input.
+ dvilj can't read from a pipe, so always write to a file. */
+ if (verbose)
+ fprintf (stderr, "Running dvicopy %s >%s\n", infile, vfless_dvi);
+
+ /* FIXME: special characters in filenames aren't protected from the shell. */
+ cmdline = concatn ("dvicopy ", infile, " >", vfless_dvi, NULL);
+ if (system (cmdline))
+ {
+ fprintf (stderr, "%s: dvicopy %s failed.\n", progname, infile);
+ return 1;
+ }
+ free (cmdline);
+
+ if (verbose)
+ {
+ struct stat st_buf;
+
+ if (stat (vfless_dvi, &st_buf))
+ perror (vfless_dvi);
+ else /* assume they only want to see the size and timestamp */
+ fprintf (stderr, " %ld %s %s\n",
+ (long)st_buf.st_size, ctime (&st_buf.st_mtime), vfless_dvi);
+ }
+ if (!*output)
+ {
+ output = "-"; /* output to stdout */
+ maybe_spool_cmd = concat (spool, spool_opt);
+ }
+
+ /* Translate DVI to LJ. */
+ cmdline = concatn (dvilj, space, opt, output_opt, output,
+ space, vfless_dvi, space, maybe_spool_cmd, NULL);
+ if (verbose)
+ fprintf (stderr, "Running %s\n", cmdline);
+ if (system (cmdline))
+ {
+ fprintf (stderr, "%s: %s failed.\n", progname, dvilj);
+ return 2;
+ }
+
+ /* rm -f $TMPDIR/dvi$$.* */
+ rmfiles (template);
+
+ return 0;
+}
diff --git a/Build/source/texk/contrib/dvihp.rc b/Build/source/texk/contrib/dvihp.rc
new file mode 100644
index 00000000000..1ad4f54943b
--- /dev/null
+++ b/Build/source/texk/contrib/dvihp.rc
@@ -0,0 +1,35 @@
+/* dvihp.rc: dvihp resources -*- C++ -*-
+
+ Copyright (C) 1996-2003 Fabrice Popineau <fabrice.popineau@supelec.fr>
+
+ This file 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 file 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 file; if not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+
+#include <texlive-version.h>
+
+#define VER_FILEVERSION TEXLIVE_MAJOR_VERSION,TEXLIVE_MINOR_VERSION,TEXLIVE_BETA_NUMBER,TEXLIVE_ALPHA_NUMBER
+#define VER_FILEVERSION_STR TEXLIVE_PRODUCTVERSION_STR " dvihp 1.7"
+
+#define VER_INTERNALNAME_STR "Dvihp"
+#define VER_ORIGINALFILENAME_STR "dvihp.exe"
+
+#define VER_LEGALCOPYRIGHT_STR " Copyright (c) 1996-1997 by Eli Zaretskii."
+
+#define VER_FILEDESCRIPTION_STR "Driver for DviLJ programs"
+
+#include <texlive.version>
+
+/* dvihp.rc ends here */
diff --git a/Build/source/texk/contrib/fileutils.c b/Build/source/texk/contrib/fileutils.c
new file mode 100644
index 00000000000..cfd9e3b0db2
--- /dev/null
+++ b/Build/source/texk/contrib/fileutils.c
@@ -0,0 +1,561 @@
+/* stackenv.c: routines that help to deal with files and directories.
+
+Copyright (C) 1997 Fabrice POPINEAU.
+
+Adapted to DJGPP by Eli Zaretskii.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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 this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "fileutils.h"
+
+/* A few utility functions shared by both mktex and makempx. */
+
+int mt_append_mask = 0;
+
+/* Execute a command, much like system() but using popen() */
+int
+execute_command(string cmd)
+{
+ int retcode = 0;
+ FILE *fcmd = NULL;
+ if ((fcmd = popen(cmd, "r")) == NULL)
+ return -1;
+ retcode = pclose(fcmd);
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG)) {
+ fprintf(stderr, "executing %s => %d\n", cmd, retcode);
+ }
+ return retcode;
+}
+
+/* Copy a file, appending if required. */
+
+int catfile (const char *from, const char *to, int append)
+{
+ FILE *finp, *fout;
+ unsigned char buf[16*1024];
+ int rbytes;
+
+ finp = fopen (from, "rb");
+ if (!finp)
+ return FALSE;
+ fout = fopen (to, append ? "ab" : "wb");
+ if (!fout) {
+ fclose (finp);
+ return FALSE;
+ }
+
+ while ((rbytes = fread (buf, 1, sizeof buf, finp)) > 0) {
+ int wbytes = fwrite (buf, 1, rbytes, fout);
+
+ if (wbytes < rbytes) {
+ if (wbytes >= 0)
+ fprintf (stderr, "%s: disk full\n", to);
+ fclose (finp);
+ fclose (fout);
+ unlink (to);
+ return FALSE;
+ }
+ }
+
+ fclose (finp);
+ fclose (fout);
+ return TRUE;
+}
+
+/* Move a file using rename if possible, copy if necessary. */
+
+int mvfile (const char *from, const char *to)
+{
+ int e = errno;
+ int retval = TRUE;
+ char errstring[PATH_MAX*4];
+
+ errno = 0;
+ if (rename (from, to) == 0) {
+ errno = e;
+ return TRUE;
+ }
+
+#ifndef DOSISH
+ /* I don't want to rely on this on DOSISH systems. First, not all
+ of them know about EXDEV. And second, DOS will fail `rename'
+ with EACCES when the target is more than 8 directory levels deep. */
+ if (errno != EXDEV)
+ retval = FALSE;
+ else
+#endif
+
+ /* `rename' failed on cross-filesystem move. Copy, then delete. */
+ if (catfile (from, to, 0) == FALSE)
+ retval = FALSE;
+ else
+ unlink (from); /* ignore possible errors */
+
+ /* Simulate error message from `mv'. */
+ if (retval == FALSE) {
+ sprintf(errstring, "%s: can't move %s to %s", kpse_program_name, from, to);
+ perror(errstring);
+ }
+
+ if (!errno)
+ errno = e;
+ return retval;
+}
+
+/* Like the test function from Unix */
+
+boolean test_file(int c, string path)
+{
+ struct stat stat_buf;
+ boolean file_exists;
+
+ if (c == 'z')
+ return (path == NULL || *path == '\0');
+
+ if (c == 'n')
+ return (path != NULL && *path != '\0');
+
+#ifdef WIN32
+ /* Bug under W95 */
+ if (c == 'd')
+ return dir_p(path);
+#endif
+
+ file_exists = (stat(path, &stat_buf) != -1);
+
+#ifdef DOSISH
+ /* When they say "test -x foo", make so we find "foo.exe" etc. */
+ if (c == 'x' && !file_exists)
+ {
+ static string try_ext[] = {
+ ".exe",
+ ".bat",
+ ".cmd",
+ ".btm",
+ 0
+ };
+ string *p = try_ext;
+
+ while (p)
+ {
+ string try = concat(path, *p++);
+ if (stat(try, &stat_buf) != -1)
+ {
+ file_exists = 1;
+ free(try);
+ break;
+ }
+ free(try);
+ }
+ }
+#endif
+
+ if (!file_exists) return FALSE;
+ switch (c) {
+ case 'd':
+ return ((stat_buf.st_mode & S_IFMT) == S_IFDIR);
+ case 'e':
+ case 'r':
+ return TRUE;
+ case 'f':
+ return ((stat_buf.st_mode & S_IFMT) == S_IFREG);
+ case 's':
+ return (stat_buf.st_size > 0);
+ case 'x':
+ return ((stat_buf.st_mode & S_IFMT) == S_IFREG
+ && (stat_buf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)));
+ case 'w':
+ {
+ return (
+#ifdef DOSISH
+ /* DOSISH systems allow to create files in read-only
+ directories, and `is_writable' knows about that. So we
+ artificially look at the write bit returned by `stat'
+ and refuse to write in read-only directories. */
+ (stat_buf.st_mode & S_IWUSR) != 0 &&
+#endif
+ is_writable(path));
+ }
+ default:
+ return FALSE;
+ }
+}
+
+#ifdef _WIN32
+
+boolean is_writable(string path)
+{
+ DWORD dw;
+ char tmppath[PATH_MAX*2];
+ int writable;
+
+ /* Test 2 cases: directory or file */
+ if ((dw = GetFileAttributes(path)) == 0xFFFFFFFF) {
+ /* Invalid Path, not writable */
+ writable = false;
+ errno = ENOENT; /* like `access' does */
+ }
+ else if (dw & FILE_ATTRIBUTE_READONLY) {
+ writable = false;
+ }
+ else if (dw & FILE_ATTRIBUTE_DIRECTORY) {
+ /* Trying to open a file */
+ if (GetTempFileName(path, "foo", 0, tmppath) == 0) {
+ writable = false;
+ }
+ else {
+ writable = true;
+ }
+ DeleteFile(tmppath);
+ }
+ else {
+ writable = true;
+ }
+ return writable;
+}
+
+#else /* !_WIN32 */
+
+boolean is_writable(string path)
+{
+ if (!path || !*path) /* like `access' called with empty variable as arg */
+ return false;
+#ifdef MSDOS
+ /* Directories always return as writable, even on read-only filesystems
+ such as CD-ROMs or write-protected floppies. Need to try harder... */
+ if (access(path, D_OK) == 0) {
+ /* Use a unique file name. */
+ string template = concat3(path, "/", "wrXXXXXX");
+ int fd;
+
+ if (mktemp(template) && (fd = creat(template, S_IRUSR | S_IWUSR)) >= 0) {
+ close(fd);
+ unlink(template);
+ free(template);
+ return true;
+ }
+
+ free(template);
+
+ /* Simulate errno from `access'. */
+#ifdef EROFS
+ errno = EROFS; /* POSIX platforms should have this */
+#else
+ errno = EACCES;
+#endif
+ return false;
+ }
+ else
+#endif /* MSDOS */
+ return access(path, W_OK) == 0 ? true : false;
+}
+
+#endif /* !_WIN32 */
+
+/*
+ Recursive walk through the directory tree. Depth-first order.
+*/
+void recurse_dir(string path, execfn before, execfn after)
+{
+ /* In depth traversal of the subdir tree */
+#if defined(_WIN32)
+ WIN32_FIND_DATA find_file_data;
+ HANDLE hnd;
+#else
+ DIR *dp;
+ struct dirent *ep;
+#endif
+ struct stat stat_buf; /* We have to have one local because
+ of after */
+
+ int path_len = strlen(path);
+
+ /* current node */
+ if (stat(path, &stat_buf))
+ perror(path);
+
+ /* execute before for the current node */
+ if (before)
+ (*before)(path, &stat_buf);
+
+ /* if it is a directory, recurse through all sons */
+ if ((stat_buf.st_mode & S_IFMT) == S_IFDIR) {
+#if defined(_WIN32)
+ strcat(path, "/*");
+ hnd = FindFirstFile(path, &find_file_data);
+ while (hnd != INVALID_HANDLE_VALUE &&
+ FindNextFile(hnd, &find_file_data) != FALSE) {
+ if(!strcmp(find_file_data.cFileName, ".")
+ || !strcmp(find_file_data.cFileName, ".."))
+ continue;
+ path[path_len+1] = '\0';
+ strcat(path, find_file_data.cFileName);
+ recurse_dir(path, before, after);
+ }
+ path[path_len] = '\0';
+ FindClose(hnd);
+#else
+ if ((dp = opendir(path))) {
+ while ((ep = readdir(dp)))
+ if (strcmp(ep->d_name, ".") &&
+ strcmp(ep->d_name, "..")) {
+ path[path_len] = '/';
+ strcpy(path+path_len+1, ep->d_name);
+ recurse_dir(path, before, after);
+ }
+ path[path_len] = '\0';
+ closedir(dp);
+ }
+ else
+ perror(path);
+#endif
+ }
+ /* execute after for the current node */
+ if (after)
+ (*after)(path, &stat_buf);
+}
+
+void do_rmdir(string path)
+{
+ static char name[PATH_MAX];
+ strcpy(name,path);
+
+ if (test_file('d', path)) {
+ recurse_dir(name, NULL, remove_path);
+ }
+ else
+ unlink(path);
+}
+
+/* Recursively destructs files & directories from path. */
+void rec_rmdir(string path)
+{
+ string p;
+
+ for(p=path+strlen(path)-1; IS_DIR_SEP(*p) && (p > path) ; p--) {
+ *p = '\0';
+ }
+ do_rmdir(path);
+}
+
+/* Creates path, and all intermediate directories if necessary. */
+
+int do_makedir(string path)
+{
+ struct stat stat_buf;
+ string p = path;
+ mode_t dir_perms = 0777 & ~umask (0); /* default permissions for `mkdir' */
+ mode_t parent_perms = 0;
+
+ /* We can't authorize multiple slashes here */
+ normalize(path);
+
+ if (KPSE_DEBUG_P(MKTEX_DEBUG)) {
+ fprintf(stderr, "Creating directory: %s\n", path);
+ }
+
+ if (stat(path, &stat_buf) == 0 &&
+ (stat_buf.st_mode & S_IFMT) == S_IFDIR)
+ return 0; /* The path already exists */
+
+#ifdef WIN32
+ /* Handling of UNC names */
+ if (IS_UNC_NAME(path)) {
+ /* UNC pathname : \\server\dir\...
+ We must begin at the third component.
+ Name is normalized, so only '/' as dir sep.
+ */
+ p = strchr(path+3, '/');
+ if (!p) {
+ /* invalid pathname */
+ return ENOTDIR;
+ }
+ p = strchr(p+1, '/');
+ if (!p) {
+ /* invalid pathname */
+ return ENOTDIR;
+ }
+ p++;
+ }
+ else {
+ if (NAME_BEGINS_WITH_DEVICE(path)) {
+ p = path+2;
+ }
+ if (IS_DIR_SEP(*p))
+ p++;
+ }
+#else
+ /* Finding the [drive letter][:] */
+ if (IS_DEVICE_SEP(*(p+1)))
+ p +=2;
+
+ if (IS_DIR_SEP(*p))
+ p++;
+#endif
+ for ( ; *p ; p++) {
+ if (IS_DIR_SEP(*p)) {
+ *p = '\0';
+ errno = 0;
+ if (!test_file('d', path)) {
+ if ((mkdir(path, dir_perms) == -1)) {
+ return errno;
+ } else if (parent_perms == 0 && errno == 0) {
+ /* The first time we actually create a directory, remember the
+ permission bits of its parent. */
+ string parent = concat(path, "/..");
+
+ if (stat(parent, &stat_buf) == 0) {
+ parent_perms = stat_buf.st_mode;
+ /* Use the correct bits from now on. */
+ dir_perms = parent_perms | mt_append_mask;
+ }
+ free(parent);
+ }
+ /* chmod the directory we just created. */
+ chmod(path, dir_perms);
+ }
+ *p = DIR_SEP;
+ }
+ }
+ /* and for the whole path */
+ if (mkdir(path, dir_perms) == -1) {
+ return errno;
+ }
+ chmod(path, dir_perms);
+
+ return 0;
+}
+
+/* remove something which already exists */
+void remove_path(string path, struct stat* st)
+{
+ int e = errno;
+
+ if ((st->st_mode & S_IFMT) == S_IFDIR) {
+ errno = 0;
+ if (rmdir(path) == -1 && errno == EBUSY) {
+ /* `rmdir' will fail (at least on MS-DOS) if PATH is the current
+ working directory on another drive, or the parent of the
+ working directory. To work around that, we chdir to the root
+ of that drive, then try to rmdir again. */
+ char drv_root[4], *p = drv_root;
+
+ if (path[0] && path[1] == ':') {
+ *p++ = path[0];
+ *p++ = path[1];
+ }
+ *p++ = '/';
+ *p = '\0';
+ pushd(drv_root);
+ if (rmdir(path) == 0) {
+ errno = e;
+ popd();
+ return;
+ }
+ }
+ else if (errno)
+ perror(path);
+ else
+ errno = e;
+ }
+ else {
+ if (unlink(path) == -1)
+ perror(path);
+ }
+}
+
+/*
+ Rewrite path with the same DIR_SEP and deleting multiple ones
+ FIXME: does this eliminates the trailing ones ? W95 doesn't grok
+ stat() on pathes that end up in PATH_SEP.
+ */
+char *normalize(string path)
+{
+ string p, q;
+ int offset = 0;
+
+ /* Be safe */
+ if (path == NULL) return path;
+
+ /* Delete any multiple slashes, except leading ones on WIN32 (UNC names) */
+#ifdef WIN32
+ if (IS_UNC_NAME(path)) {
+ path[0] = path[1] = DIR_SEP;
+ offset = 2;
+ }
+#endif
+ for ( p = q = path+offset; *p != '\0'; p++, q++) {
+ *q = (IS_DIR_SEP(*p) ? DIR_SEP : *p);
+ if (IS_DIR_SEP(*p))
+ while (*(p+1) && IS_DIR_SEP(*(p+1))) p++;
+ }
+ *q = '\0';
+
+ return path;
+}
+
+
+/* Smart concatenation of 2 pathes: add the separator only
+ when needed. Allocates a new path. */
+string concat_pathes(const_string p1, const_string p2)
+{
+ string res;
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG)) {
+ fprintf(stderr, "Concat pathes %s and %s\n", p1, p2);
+ }
+
+ assert (p1 && p2);
+
+ res = normalize(concat3(p1, DIR_SEP_STRING, p2));
+
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG)) {
+ fprintf(stderr, "\t=> %s\n", res);
+ }
+
+ return res;
+}
+
+/*
+ Kpathsea's basename does not strip suffixes
+ */
+string my_basename(string name, string suffix)
+{
+ string res = (string)xbasename(name);
+ if (suffix) {
+ int suffix_len = strlen(suffix);
+ if (FILESTRCASEEQ(res+strlen(res)-suffix_len, suffix))
+ *(res+strlen(res)-suffix_len) = '\0';
+ }
+ return xstrdup(res);
+}
+
+#if 0
+/*
+ Kpathsea's kpse_find_file() is not parametrized by '--progname'.
+ This is an attempt to do that.
+ */
+
+/* The path spec we are defining, one element of the global array. */
+#define FMT_INFO kpse_format_info[format]
+/* Call add_suffixes. */
+#define SUFFIXES(args) add_suffixes(&FMT_INFO.suffix, args, NULL)
+#define ALT_SUFFIXES(args) add_suffixes (&FMT_INFO.alt_suffix, args, NULL)
+
+/* Call `init_path', including appending the trailing NULL to the envvar
+ list. Also initialize the fields not needed in setting the path. */
+#define INIT_FORMAT(text, default_path, envs) \
+ FMT_INFO.type = text; \
+ init_path (&FMT_INFO, default_path, envs, NULL)
+#endif
diff --git a/Build/source/texk/contrib/fileutils.h b/Build/source/texk/contrib/fileutils.h
new file mode 100644
index 00000000000..a09eeb569db
--- /dev/null
+++ b/Build/source/texk/contrib/fileutils.h
@@ -0,0 +1,26 @@
+#ifndef _FILEUTILS_H_
+
+#define _FILEUTILS_H_
+
+#include "mktexlib.h"
+#include "stackenv.h"
+
+
+/* Type of function to execute */
+typedef void (*execfn)(string, struct stat*);
+
+extern MKTEXDLL void recurse_dir(string, execfn, execfn);
+extern MKTEXDLL void do_rmdir(string);
+extern MKTEXDLL void rec_rmdir(string);
+extern MKTEXDLL int do_makedir(string);
+extern MKTEXDLL void remove_path(string, struct stat*);
+extern MKTEXDLL int mvfile(const char *, const char *);
+extern MKTEXDLL int catfile(const char *, const char *, int);
+extern MKTEXDLL boolean test_file(int, string);
+extern MKTEXDLL boolean is_writable(string);
+extern MKTEXDLL int execute_command(string);
+extern MKTEXDLL char *normalize(char *path);
+extern MKTEXDLL char *my_basename(char *name,char *suffix);
+extern MKTEXDLL char *concat_pathes(const char *p1,const char *p2);
+
+#endif /* _FILEUTILS_H_ */
diff --git a/Build/source/texk/contrib/fmtutil.c b/Build/source/texk/contrib/fmtutil.c
new file mode 100644
index 00000000000..0012d754ef2
--- /dev/null
+++ b/Build/source/texk/contrib/fmtutil.c
@@ -0,0 +1,1312 @@
+/* fmtutil.c: this program emulates the fmtutil shell script from tetex.
+
+Copyright (C) 1998 Fabrice POPINEAU.
+
+Time-stamp: <04/03/20 16:03:00 popineau>
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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 this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Maximum number of lines per usage message. */
+#define MAX_LINES 32
+
+#define SEPARATORS " \t\n\""
+
+#include <signal.h>
+
+#include <kpathsea/kpathsea.h>
+extern KPSEDLL char* kpathsea_version_string;
+
+#include "mktex.h"
+#include "fileutils.h"
+#include "stackenv.h"
+#include "variables.h"
+#include "fmtutil.h"
+
+#ifdef _WIN32
+#define isatty _isatty
+#else
+#include <glob.h>
+#endif
+
+extern string fmtutil_version_string;
+
+/*
+ Global Variables found in the fmtutil script
+*/
+
+static string texmfmain;
+static string tempenv;
+static string cwd;
+
+static string mode, bdpi;
+
+/* fmtutil.cnf */
+
+static boolean downcase_names;
+char cmd_buf[1024]; /* Hope it is enough for handling command */
+char cmd_sys[1024]; /* system() calls */
+char msg_buf[1024];
+
+static int errstatus;
+static string log_failure_msg = NULL;
+
+static void usage(void);
+
+/* Test whether getopt found an option ``A''.
+ Assumes the option index is in the variable `option_index', and the
+ option table in a variable `long_options'. */
+#define ARGUMENT_IS(a) STREQ (long_options[option_index].name, a)
+
+static struct option long_options [] = {
+ { "all", 0, 0, 0},
+ { "quiet", 0, 0, 0},
+ { "test", 0, 0, 0},
+ { "force", 0, 0, 0},
+ { "dolinks", 0, 0, 0},
+ { "missing", 0, 0, 0},
+ { "byfmt", 1, 0, 0},
+ { "byhyphen", 1, 0, 0},
+ { "enablefmt", 1, 0, 0},
+ { "disablefmt", 1, 0, 0},
+ { "listcfg", 1, 0, 0},
+ { "showhyphen", 1, 0, 0},
+ { "edit", 0, 0, 0},
+ { "help", 0, 0, 0},
+ { "cnffile", 1, 0, 0},
+ { "fmtdir", 1, 0, 0},
+ { "debug", 1, 0, 0},
+ {0, 0, 0, 0}
+};
+
+enum {
+ NONE, ALL, MISSING, BYFMT, BYHYPHEN,
+ ENABLEFMT, DISABLEFMT, LISTCFG, SHOWHYPHEN, EDIT
+};
+
+#define MAX_FMTS 128
+
+typedef struct fmtdesc {
+ string format; /* e.g.: latex.fmt */
+ string shortformat; /* e.g.: latex */
+ string engine; /* e.g.: tex */
+ string progname; /* e.g.: latex */
+ string hyphenation; /* e.g.: - */
+ string texargs;
+ string inifile;
+ string inifile_short; /* remember it */
+ string pool;
+ string poolbase;
+ string tcx;
+ string tcxoption;
+} fmtdesc;
+
+static fmtdesc fmts[MAX_FMTS];
+static int nb_formats = 0;
+
+string unrmable_engines[] = {
+ "tex", "pdftex", "etex", "pdfetex", "omega", "eomega", "aleph", "mf", "mpost", NULL
+};
+
+/*
+ First argument takes progname;
+ Other arguments take no arguments.
+ */
+static string usage_msg[][MAX_LINES] = {
+ {
+ "Usage: fmtutil [option] ... command\n\n",
+ "Valid options:\n",
+ " --cnffile file\n",
+ " --fmtdir directory\n",
+ " --debug=<n> set debug level to n\n",
+ " --quiet no output except error messages\n",
+ " --test only print what would be done\n",
+ " --dolinks link engine to format\n\n",
+ " --force force links even if target exists\n\n",
+ "Valid commands:\n",
+ " --all recreate all format files\n",
+ " --missing create all missing format files\n",
+ " --byfmt formatname (re)create format for `formatname'\n",
+ " --byhyphen hyphenfile (re)create formats that depend on `hyphenfile'\n",
+ " --enablefmt formatname enable `formatname' in config file\n",
+ " --disablefmt formatname disable formatname in config file\n",
+ " --listcfg list (enabled and disabled) configurations\n",
+ " --showhyphen formatname print name of hyphenfile for format `formatname'\n",
+ " --edit edit fmtutil.cnf file\n",
+ " --version display version information\n",
+ " --help show this message\n",
+ 0
+ },
+ {
+ "Usage: mktexfmt [[option] format.ext | command]\n\n",
+ "Valid options:\n",
+ " --debug=<n> set debug level to n\n",
+ " --quiet no output except error messages\n",
+ " --test only print what would be done\n",
+ " --dolinks link engine to format\n\n",
+ " --force force links even if target exists\n\n",
+ "Valid commands:\n",
+ " --version display version information\n",
+ " --help show this message\n",
+ 0
+ }
+};
+
+static string fmtutil_version_string = "Revision: 0.40";
+
+static string cnf_default = "fmtutil.cnf";
+static string cnf_file = NULL;
+static string arg = NULL;
+static string destdir = NULL;
+static int cmd= NONE;
+static boolean quiet = false;
+static boolean norebuild = false;
+static boolean dolinks = false;
+static boolean force = false;
+static enum { FMTUTIL, MKTEXFMT, LAST_PROGRAM } incarnation = FMTUTIL;
+
+#define MAX_LINKS 128
+
+struct _links {
+ string src;
+ string dst;
+} to_link[MAX_LINKS];
+int nb_links = 0;
+
+void link_formats();
+
+void log_failure(string msg)
+{
+ if (log_failure_msg == NULL) {
+ log_failure_msg = xstrdup(msg);
+ }
+ else {
+ string tmp = log_failure_msg;
+ log_failure_msg = concat(log_failure_msg, msg);
+ free(tmp);
+ }
+}
+
+/*
+ First part: fmtutil.opt
+ */
+int fmtutil_opt(int argc, char *argv[])
+{
+ int g; /* getopt return code */
+ int i;
+ int option_index;
+
+ for(;;) {
+ g = getopt_long_only (argc, argv, "", long_options, &option_index);
+
+ if (g == EOF)
+ break;
+
+ if (g == '?')
+ return 1; /* Unknown option. */
+
+ /* assert (g == 0); */ /* We have no short option names. */
+
+ if (ARGUMENT_IS ("debug")) {
+ kpathsea_debug |= atoi (optarg);
+ }
+ else if (ARGUMENT_IS ("quiet")) {
+ quiet = true;
+ }
+ else if (ARGUMENT_IS ("test")) {
+ norebuild = true;
+ }
+ else if (ARGUMENT_IS ("dolinks")) {
+ dolinks = true;
+ }
+ else if (ARGUMENT_IS ("force")) {
+ force = true;
+ }
+ else if (ARGUMENT_IS ("help")) {
+ usage();
+ exit(0);
+ }
+ else if (ARGUMENT_IS ("version")) {
+ fprintf(stderr, "%s (version %s) of %s.\n", progname,
+ fmtutil_version_string,
+ kpathsea_version_string);
+ exit(0);
+ }
+ else if (incarnation == MKTEXFMT) {
+ /* no othe options */
+ }
+ else if (incarnation == FMTUTIL) {
+ if (ARGUMENT_IS("all")) {
+ cmd = ALL;
+ }
+ else if (ARGUMENT_IS("missing")) {
+ cmd = MISSING;
+ }
+ else if (ARGUMENT_IS("byfmt")) {
+ cmd = BYFMT;
+ arg = xstrdup(optarg);
+ }
+ else if (ARGUMENT_IS("byhyphen")) {
+ cmd = BYHYPHEN;
+ arg = xstrdup(optarg);
+ }
+ else if (ARGUMENT_IS("enablefmt")) {
+ cmd = ENABLEFMT;
+ arg = xstrdup(optarg);
+ }
+ else if (ARGUMENT_IS("disablefmt")) {
+ cmd = DISABLEFMT;
+ arg = xstrdup(optarg);
+ }
+ else if (ARGUMENT_IS("listcfg")) {
+ cmd = LISTCFG;
+ arg = xstrdup(optarg);
+ }
+ else if (ARGUMENT_IS("showhyphen")) {
+ cmd = SHOWHYPHEN;
+ arg = xstrdup(optarg);
+ }
+ else if (ARGUMENT_IS("edit")) {
+ cmd = EDIT;
+ }
+ else if (ARGUMENT_IS("cnffile")) {
+ cnf_file = xstrdup(optarg);
+ }
+ else if (ARGUMENT_IS("fmtdir")) {
+ destdir = xstrdup(optarg);
+ }
+ }
+ }
+
+ if (incarnation == MKTEXFMT) {
+ cmd = BYFMT;
+ if (optind < argc) {
+ string ext = NULL;
+ /* Make `mktexfmt <format.ext>' equivalent to `fmtutil --byfmt=<format>' */
+ cmd = BYFMT;
+ arg = xstrdup(xbasename(argv[optind++]));
+ /* remove any extension */
+ ext = strrchr(arg, '.');
+ if (ext) *ext = '\0';
+ }
+ }
+
+ /* shifting options from argv[] list */
+ for (i = 1; optind < argc; i++, optind++)
+ argv[i] = argv[optind];
+ argv[i] = NULL;
+
+ argc = i;
+
+ if (argc > 1) {
+ fprintf(stderr, "%s: Extra arguments", progname);
+ fprintf (stderr, "\nTry `%s --help' for more information.\n",
+ kpse_program_name);
+ exit(1);
+ }
+
+ if (argc == 0 || cmd == NONE) {
+ fprintf(stderr, "%s: Missing arguments", progname);
+ fprintf (stderr, "\nTry `%s --help' for more information.\n",
+ kpse_program_name);
+ exit(1);
+ }
+
+ return argc;
+}
+
+/* Reading fmtutil.cnf */
+boolean parse_line(string line)
+{
+ string format = NULL,
+ engine = NULL,
+ hyphenation = NULL,
+ texargs = NULL,
+ inifile = NULL,
+ pool = NULL,
+ tcx = NULL;
+ string p, end;
+
+ end = line + strlen(line);
+
+ format = strtok(line, "\t ");
+ if (!format || !*format)
+ return false;
+ engine = strtok(NULL, "\t ");
+ if (!engine || !*engine)
+ return false;
+ hyphenation = strtok(NULL, "\t ");
+ if (!hyphenation || !*hyphenation)
+ return false;
+ texargs = strtok(NULL, " \t");
+ if (!texargs || !*texargs)
+ return false;
+ if (strncasecmp(texargs, "nls=", 4) == 0) {
+ pool = texargs+4;
+ if (tcx = strchr(pool, ',')) {
+ *tcx = '\0';
+ }
+ texargs = strtok(NULL, " \t");
+ }
+
+ p = texargs + strlen(texargs);
+ if (p < end && *p == '\0')
+ *p = ' ';
+
+ /* Get last argument */
+ for (inifile = texargs + strlen(texargs) - 1;
+ isspace(*inifile) && inifile > texargs;
+ inifile--)
+ *inifile = '\0';
+ for ( ; !isspace(*(inifile - 1)) && inifile > texargs; inifile--);
+
+ inifile = (*inifile == '*' ? inifile+1 : inifile);
+
+ fmts[nb_formats].inifile_short = (inifile ? xstrdup(inifile) : NULL);
+
+#if 0
+ fprintf(stderr, "parse_line : pool = %s, hyphen = %s, tcx = %s, inifile = %s\n", pool, hyphenation, tcx, inifile);
+#endif
+ kpse_reset_program_name(format);
+ if (STREQ(engine, "mf") || STREQ(engine, "mf-nowin")) {
+ if (!kpse_find_file(inifile, kpse_mf_format, false)) {
+ /* Do not log it : we don't know if it has been requested or not ! */
+ /* sprintf(msg_buf, "%s: ini file %s not found\n", cnf_file, inifile); */
+ /* log_failure(msg_buf); */
+ inifile = NULL;
+ }
+ fmts[nb_formats].progname = xstrdup(engine);
+ fmts[nb_formats].shortformat = xstrdup(format);
+ fmts[nb_formats].format = concat(format, ".base");
+ }
+ else if (STREQ(engine, "mpost")) {
+ if (!kpse_find_file(inifile, kpse_mp_format, false)) {
+/* sprintf(msg_buf, "%s: ini file %s not found\n", cnf_file, inifile); */
+/* log_failure(msg_buf); */
+ inifile = NULL;
+ }
+ fmts[nb_formats].progname = xstrdup(engine);
+ fmts[nb_formats].shortformat = xstrdup(format);
+ fmts[nb_formats].format = concat(format, ".mem");
+ }
+ else {
+ if (!kpse_find_file(inifile, kpse_tex_format, false)) {
+/* sprintf(msg_buf, "%s: ini file %s not found\n", cnf_file, inifile); */
+/* log_failure(msg_buf); */
+ inifile = NULL;
+ }
+ fmts[nb_formats].progname = xstrdup(format);
+ fmts[nb_formats].shortformat = xstrdup(format);
+
+ if (STREQ(engine, "etex")
+ || STREQ(engine, "pdfetex")) {
+ fmts[nb_formats].format = concat(format, ".efmt");
+ }
+ else if (STREQ(engine, "aleph")
+ || STREQ(engine, "pdfaleph")) {
+ fmts[nb_formats].format = concat(format, ".afmt");
+ }
+ else if (STREQ(engine, "eomega")
+ || STREQ(engine, "pdfeomega")) {
+ fmts[nb_formats].format = concat(format, ".eoft");
+ }
+ else if (STREQ(engine, "omega")) {
+ fmts[nb_formats].format = concat(format, ".oft");
+ }
+ else {
+ fmts[nb_formats].format = concat(format, ".fmt");
+ }
+ }
+ kpse_reset_program_name(progname);
+ fmts[nb_formats].engine = xstrdup(engine);
+ fmts[nb_formats].hyphenation = xstrdup(hyphenation);
+ fmts[nb_formats].texargs = xstrdup(texargs);
+ fmts[nb_formats].inifile = (inifile ? xstrdup(inifile) : NULL);
+ if (pool == NULL) {
+ fmts[nb_formats].poolbase = NULL;
+ fmts[nb_formats].pool = NULL;
+ }
+ else {
+ fmts[nb_formats].poolbase = xstrdup(pool);
+ fmts[nb_formats].pool = concat(pool, ".pool");
+ }
+ if (tcx == NULL) {
+ fmts[nb_formats].tcx = xstrdup("");
+ fmts[nb_formats].tcxoption = xstrdup("");
+ }
+ else {
+ fmts[nb_formats].tcx = xstrdup(tcx);
+ fmts[nb_formats].tcxoption = concat("-translate-file=",tcx);
+ }
+ nb_formats++;
+
+ return true;
+}
+
+void read_fmtutilcnf()
+{
+ FILE *f;
+ string line;
+
+ if (test_file('n', cnf_file) && test_file('r', cnf_file)) {
+ f = fopen(cnf_file, "r");
+ if (KPSE_DEBUG_P(FMTUTIL_DEBUG)) {
+ fprintf(stderr, "Reading fmtutil_cnf file: %s\n", cnf_file);
+ }
+ while ((line = read_line(f)) != NULL) {
+ /* skip comments */
+ if (*line == '#' || *line == '%' || isspace(*line)
+ || *line == '\0' || *line == '\n')
+ continue;
+
+ if (!parse_line(line))
+ fprintf(stderr, "%s: syntax error: %s\n", cnf_file, line);
+ free(line);
+ }
+ fclose(f);
+ if (KPSE_DEBUG_P(FMTUTIL_DEBUG)) {
+ int i;
+ for (i = 0; i < nb_formats; i++) {
+ fprintf(stderr, "Line %d: fmt = %s engine = %s progname = %s hyph = %s tex = %s ini = %s\n",
+ i, fmts[i].format, fmts[i].engine, fmts[i].progname,
+ fmts[i].hyphenation, fmts[i].texargs, fmts[i].inifile);
+ }
+ }
+
+ }
+}
+
+void __cdecl output_and_cleanup(int code)
+{
+ /* FIXME : what cleanup ? */
+ int count = 0;
+
+ if (test_file('d', tmpdir))
+ rec_rmdir(tmpdir);
+
+ if (code != 0 && log_failure_msg && *log_failure_msg) {
+ fprintf(stderr, "\
+###############################################################################\n\
+%s: Error! Not all formats have been built successfully.\n\
+Visit the log files in directory\n\
+ %s\n\
+for details.\n\
+###############################################################################\n\
+\n\
+This is a summary of all `failed' messages and warnings:\n\
+%s\n",
+ kpse_program_name, destdir, log_failure_msg);
+ }
+}
+
+static void usage()
+{
+ int i;
+ fprintf(stderr, "%s of %s\n", progname, kpathsea_version_string);
+ fprintf(stderr, "Fmtutil version %s\n", fmtutil_version_string);
+ fprintf(stderr,usage_msg[incarnation][0], progname );
+ fputs("\n", stderr);
+ for(i = 1; usage_msg[incarnation][i] != NULL; ++i)
+ fputs(usage_msg[incarnation][i], stderr);
+}
+
+
+int main(int argc, char* argv[])
+{
+ string texinputs, texformats;
+
+#if defined(WIN32)
+ /* if _DEBUG is not defined, these macros will result in nothing. */
+ SETUP_CRTDBG;
+ /* Set the debug-heap flag so that freed blocks are kept on the
+ linked list, to catch any inadvertent use of freed memory */
+ SET_CRT_DEBUG_FIELD( _CRTDBG_DELAY_FREE_MEM_DF );
+#endif
+ output_and_cleanup_function = output_and_cleanup;
+
+ if (!progname)
+ progname = argv[0];
+ kpse_set_program_name (progname, NULL);
+
+ if (FILESTRCASEEQ(kpse_program_name, "fmtutil")) {
+ incarnation = FMTUTIL;
+ progname = "fmtutil";
+ }
+ else if (FILESTRCASEEQ(kpse_program_name, "mktexfmt")) {
+ incarnation = MKTEXFMT;
+ progname = "mktexfmt";
+ }
+ else {
+ fprintf(stderr, "This program was incorrectly copied to the name %s\n",
+ argv[0]);
+ return 1;
+ }
+
+ /* initialize the symbol table */
+ init_vars();
+
+ /* `kpse_init_prog' will put MODE and DPI into environment as values of
+ the two variables below. We need to leave these variables as they are. */
+ mode = getval("MAKETEX_MODE");
+ bdpi = getval("MAKETEX_BASE_DPI");
+
+ /* NULL for no fallback font. */
+ kpse_init_prog (uppercasify (progname),
+ bdpi && atoi(bdpi) ? atoi(bdpi) : 600, mode, NULL);
+
+ /* fmtutil_opt may modify argc and shift argv */
+ argc = fmtutil_opt(argc, argv);
+
+ setval_default("DPI", getval("BDPI"));
+ setval_default("MAG", "1.0");
+
+ /* if no cnf_file from command-line, look it up with kpsewhich: */
+ if (test_file('z', cnf_file)) {
+ cnf_file = kpse_find_file(cnf_default, kpse_web2c_format, true);
+ if (test_file('z', cnf_file)) {
+ fprintf(stderr, "%s: fatal error, configuration file not found.\n",
+ progname);
+ exit(1);
+ }
+ }
+ if (!test_file('f', cnf_file)) {
+ fprintf(stderr, "%s: config file `%s' not found.\n", progname, cnf_file);
+ exit(1);
+ }
+
+ /* read the fmtutil.cnf file */
+ read_fmtutilcnf();
+
+ if (cmd == SHOWHYPHEN) {
+ exit(show_hyphen_file(arg));
+ }
+ else if (cmd == EDIT) {
+ exit(edit_fmtutil_cnf());
+ }
+
+ cache_vars();
+
+ texmfmain = getval("MT_TEXMFMAIN");
+ if (test_file('z', texmfmain) || !test_file('d', texmfmain)) {
+ fprintf(stderr, "%s: $TEXMFMAIN is undefined or points to a non-existent directory;\n%s: check your installation.\n", progname, progname);
+ exit(1); /* not mt_exit, since temporary files were not created yet */
+ }
+
+ /* setup dest dir */
+ if (test_file('z', destdir)) {
+ setval_default("VARTEXMF", expand_var("$VARTEXMF"));
+ if (test_file('z', getval("VARTEXMF")))
+ setval("VARTEXMF", expand_var("$MT_TEXMFMAIN"));
+ destdir = concat(getval("VARTEXMF"), "/web2c");
+ }
+ if (!test_file('d', destdir)) {
+ do_makedir(destdir);
+ if (!test_file('d', destdir)) {
+ fprintf(stderr, "%s: format directory `%s' does not exist.\n",
+ progname, destdir);
+ exit(1);
+ }
+ }
+
+ cwd = xgetcwd();
+ if (test_file('n', cwd)) {
+ /* Fixme : is it enough ? */
+ if (getenv("KPSE_DOT") == NULL) {
+ xputenv("KPSE_DOT", cwd);
+ }
+ texinputs = getval("TEXINPUTS");
+ if (test_file('z', texinputs)) {
+ xputenv("TEXINPUTS", concat(cwd, ENV_SEP_STRING));
+ }
+ else {
+ xputenv("TEXINPUTS", concatn(cwd, ENV_SEP_STRING,
+ texinputs, ENV_SEP_STRING, NULL));
+ }
+ }
+
+ /* Catch signals, so we clean up if the child is interrupted.
+ This emulates "trap 'whatever' 1 2 15". */
+#ifdef _WIN32
+ SetConsoleCtrlHandler((PHANDLER_ROUTINE)sigint_handler, TRUE);
+#else
+# ifdef SIGINT
+ signal (SIGINT, sigint_handler);
+# endif
+# ifdef SIGHUP
+ signal (SIGHUP, sigint_handler);
+# endif
+# ifdef SIGTERM
+ signal (SIGTERM, sigint_handler);
+# endif
+#endif
+
+ tempenv = getval("TMPDIR");
+ if (test_file ('z', tempenv))
+ tempenv = getval("TEMP");
+ if (test_file ('z', tempenv))
+ tempenv = getval("TMP");
+#ifdef DOSISH
+ if (test_file ('z', tempenv))
+ tempenv = "c:/tmp"; /* "/tmp" is not good if we are on a CD-ROM */
+#else
+ if (test_file ('z', tempenv))
+ tempenv = "/tmp";
+#endif
+ sprintf(tmpdir, "%s/fmXXXXXX", tempenv);
+ mktemp(tmpdir);
+ if (do_makedir(tmpdir)) {
+ perror(tmpdir);
+ exit(1);
+ }
+ setval("TEMPDIR", tmpdir);
+ setval("STDOUT", concat_pathes(tmpdir, "astdout"));
+ pushd(tmpdir);
+
+ /* Kludge to get dependency between formats working
+ in one pass : formats are build in tmpdir before
+ being sent to their final destination. */
+ texformats = concatn(tmpdir,
+ ENV_SEP_STRING,
+ kpse_var_expand("$TEXFORMATS"),
+ ENV_SEP_STRING,
+ NULL);
+ xputenv("TEXFORMATS", texformats);
+
+
+#if 0
+ if ((fout = fopen(getval("STDOUT"), "w")) == NULL) {
+ perror(output);
+ mt_exit(1);
+ }
+#endif
+
+ /* make local pathes absolute */
+ if (! kpse_absolute_p(destdir, FALSE) ) {
+ destdir = concat3(cwd, DIR_SEP_STRING, destdir);
+ }
+ if (! kpse_absolute_p(cnf_file, FALSE) ) {
+ cnf_file = concat3(cwd, DIR_SEP_STRING, cnf_file);
+ }
+
+
+ /* umask = 0 */
+ umask(0); /* for those platforms who support it */
+
+ errstatus = 0;
+
+ switch (cmd) {
+ case ALL:
+ errstatus = recreate_all();
+ break;
+ case MISSING:
+ errstatus = create_missing();
+ break;
+ case BYFMT:
+ errstatus = create_one_format(arg);
+ break;
+ case BYHYPHEN:
+ errstatus = recreate_by_hyphenfile(arg);
+ break;
+ }
+
+ /* Install the log files and format files */
+ process_multiple_files("*.log", move_log);
+ process_multiple_files("*.base", move_fmt);
+ process_multiple_files("*.mem", move_fmt);
+ process_multiple_files("*.fmt", move_fmt);
+ process_multiple_files("*.efmt", move_fmt);
+ process_multiple_files("*.oft", move_fmt);
+ process_multiple_files("*.eoft", move_fmt);
+ process_multiple_files("*.afmt", move_fmt);
+
+ if (dolinks)
+ link_formats();
+
+ mt_exit(errstatus != true);
+
+}
+
+/*
+###############################################################################
+# cache_vars()
+# locate files / kpathsea variables and export variables to environment
+# this speeds up future calls to e.g. mktexupd
+###############################################################################
+*/
+void cache_vars()
+{
+ setval_default("MT_VARTEXFONTS", expand_var("$VARTEXFONTS"));
+ setval_default("MT_TEXMFMAIN", kpse_path_expand("$TEXMFMAIN"));
+ setval_default("MT_MKTEX_CNF", kpse_find_file("mktex.cnf", kpse_web2c_format, false));
+ setval_default("MT_MKTEX_OPT", kpse_find_file("mktex.opt", kpse_web2c_format, false));
+ /* This should give us the ls-R default path */
+ if (!kpse_format_info[kpse_db_format].type) /* needed if arg was numeric */
+ kpse_init_format (kpse_db_format);
+ setval_default("MT_LSR_PATH", kpse_format_info[kpse_db_format].path);
+}
+
+int do_format(int f)
+{
+ string cmdfmt = "%s -ini %s %s=%s -progname=%s %s <nul";
+ string fmtswitch;
+ string prgswitch;
+ int ret = 0;
+
+ /* Do nothing if inifile has not been found */
+ if (fmts[f].inifile == NULL) {
+ sprintf(msg_buf, "%s: ini file %s not found\n", cnf_file, fmts[f].inifile_short);
+ log_failure(msg_buf);
+ return -1;
+ }
+
+ fmtswitch = "-jobname";
+
+ prgswitch = fmts[f].progname;
+ /* Kludge for context : avoid to set texmf.cnf parameters for
+ every cont-?? format. */
+ if (strlen(prgswitch) == strlen("cont-??")
+ && FILESTRNCASEEQ(prgswitch, "cont-", 5)) {
+ prgswitch = "context";
+ }
+ else if (strlen(prgswitch) == strlen("mptopdf")
+ && FILESTRCASEEQ(prgswitch, "mptopdf")) {
+ prgswitch = "context";
+ }
+ else if (strlen(prgswitch) == strlen("metafun")
+ && FILESTRCASEEQ(prgswitch, "metafun")) {
+ prgswitch = "mpost";
+ }
+
+ if (sprintf(cmd_sys, cmdfmt, fmts[f].engine, fmts[f].tcxoption, fmtswitch, fmts[f].shortformat,
+ prgswitch, fmts[f].texargs) > 1023) {
+ fprintf(stderr, "Warning: do_format buffer overrun!\n");
+ fprintf(stderr, "no command run.\n");
+ return -1;
+ }
+
+ if (fmts[f].pool != NULL) {
+ string poolfile;
+ string local_poolfile = concat(fmts[f].engine, ".pool");
+
+ kpse_reset_program_name(fmts[f].engine);
+
+ if (STREQ(fmts[f].engine, "mf") || STREQ(fmts[f].engine, "mf-nowin")) {
+ poolfile = kpse_find_file(fmts[f].pool, kpse_mfpool_format, true);
+ }
+ else if (STREQ(fmts[f].engine, "mpost")) {
+ poolfile = kpse_find_file(fmts[f].pool, kpse_mppool_format, true);
+ }
+ else {
+ poolfile = kpse_find_file(fmts[f].pool, kpse_texpool_format, true);
+ }
+
+ process_multiple_files("*.pool", remove_file);
+ if (test_file('n', poolfile) && test_file('f', poolfile)) {
+ fprintf(stderr, "%s: attempting to create localized format using pool=$pool and tcx=$tcx.\n",
+ kpse_program_name, fmts[f].poolbase, fmts[f].tcx);
+ catfile(poolfile, local_poolfile, false);
+ xputenv("TEXPOOL", ".");
+ }
+ kpse_reset_program_name(progname);
+ }
+
+ /* run discarding stdout */
+ start_redirection(quiet);
+
+ if (!quiet)
+ fprintf(stdout, "running `%s' ...\n", cmd_sys);
+
+ if (!norebuild) {
+ unlink(fmts[f].format);
+ ret = system(cmd_sys);
+ if (ret == -1 || !test_file('f', fmts[f].format)) {
+ sprintf(msg_buf, "%s: command `%s' failed (ret = %d, %s).\n", progname, cmd_sys, ret, fmts[f].format);
+ log_failure(msg_buf);
+ unlink(fmts[f].format);
+ }
+ }
+
+ pop_fd();
+
+ if (dolinks) {
+ to_link[nb_links].src = fmts[f].engine;
+ to_link[nb_links].dst = fmts[f].progname;
+ nb_links++;
+ }
+ return ret;
+}
+
+int recreate_all()
+{
+ int i, ret = true;
+
+ for (i = 0; i < nb_formats; i++) {
+ if (do_format(i) != 0)
+ ret = false;
+ }
+
+ return ret;
+}
+
+int create_missing()
+{
+ int i, ret = true;
+ string destfmt;
+
+ for (i = 0; i < nb_formats; i++) {
+ destfmt = concat_pathes(destdir, fmts[i].format);
+ if (! test_file('f', destfmt)) {
+ if (do_format(i) != 0)
+ ret = false;
+ }
+ free(destfmt);
+ }
+ return ret;
+}
+
+int create_one_format(string fmtname)
+{
+ int i, ret = true;
+ boolean created = false;
+
+ for (i = 0; i < nb_formats; i++) {
+ if (FILESTRCASEEQ(fmtname, fmts[i].shortformat)) {
+ if (do_format(i) != 0)
+ ret = false;
+ created = true;
+ break;
+ }
+ }
+
+ if (! created) {
+ fprintf(stderr, "%s: format file %s not found in fmtutil.cnf.\n",
+ progname, fmtname);
+ ret = false;
+ }
+
+ return ret;
+}
+
+int recreate_by_hyphenfile(string hyphenfile)
+{
+ int i, ret = true;
+ boolean created = false;
+
+ for (i = 0; i < nb_formats; i++) {
+ if (FILESTRCASEEQ(hyphenfile, fmts[i].hyphenation)) {
+ if (do_format(i) != 0)
+ ret = false;
+ created = true;
+ break;
+ }
+ }
+
+ if (! created) {
+ fprintf(stderr, "%s: hyphen file %s not found in fmtutil.cnf.\n",
+ progname, hyphenfile);
+ ret = false;
+ }
+
+ return ret;
+}
+
+int enable_format_file(string format)
+{
+ FILE *fin, *fout;
+ char line[256];
+ string bak_file = concat(cnf_file, ".bak");
+
+ fin = fopen(cnf_file, "r");
+ if (! fin) {
+ perror(cnf_file);
+ return false;
+ }
+ fout = fopen (bak_file, "w");
+ if (! fout) {
+ perror(bak_file);
+ return false;
+ }
+ while (fgets(line, sizeof(line), fin)) {
+ if (strncmp(line, "#! ", 3) == 0
+ && strncmp(line+3, format, strlen(format)) == 0
+ && isspace(line+3+strlen(format))) {
+ fputs(line + 3, fout);
+ }
+ else {
+ fputs(line, fout);
+ }
+ }
+ fclose(fin);
+ fclose(fout);
+ mvfile(bak_file, cnf_file);
+ free(bak_file);
+ return true;
+}
+
+int disable_format_file(string format)
+{
+ FILE *fin, *fout;
+ char line[256];
+ string bak_file = concat(cnf_file, ".bak");
+
+ fin = fopen(cnf_file, "r");
+ if (! fin) {
+ perror(cnf_file);
+ return false;
+ }
+ fout = fopen (bak_file, "w");
+ if (! fout) {
+ perror(bak_file);
+ return false;
+ }
+ while (fgets(line, sizeof(line), fin)) {
+ if (strncmp(line, format, strlen(format)) == 0
+ && isspace(line + strlen(format))) {
+ fputs("#! ", fout);
+ }
+ fputs(line, fout);
+ }
+ fclose(fin);
+ fclose(fout);
+ mvfile(bak_file, cnf_file);
+ free(bak_file);
+ return true;
+}
+
+int list_config_file()
+{
+ FILE *fin;
+ char line[256];
+
+ fin = fopen(cnf_file, "r");
+ if (! fin) {
+ perror(cnf_file);
+ return false;
+ }
+ while (fgets(line, sizeof(line), fin)) {
+ if (isalpha(line[0])
+ || strncmp(line, "#! ", 3) == 0)
+ fputs(line, stdout);
+ }
+ fclose(fin);
+ return true;
+}
+
+int show_hyphen_file(string format)
+{
+ int i, ret;
+ string hyphenfile;
+
+ for (i = 0; i < nb_formats; i++) {
+ if (FILESTRCASEEQ(format, fmts[i].shortformat)) {
+ if (STREQ(fmts[i].hyphenation, "-")) {
+ printf("%s\n", fmts[i].hyphenation);
+ return 0;
+ }
+ kpse_reset_program_name(format);
+ kpse_format_info[kpse_tex_format].cnf_path = kpse_cnf_get("TEXINPUTS");
+ if (!(hyphenfile
+ = kpse_find_file(fmts[i].hyphenation, kpse_tex_format, false))) {
+ fprintf(stderr, "%s: hyphen file %s not found\n", progname,
+ fmts[i].hyphenation);
+ ret = -1;
+ }
+ else {
+ printf("%s\n", hyphenfile);
+ free(hyphenfile);
+ ret = 0;
+ }
+ kpse_reset_program_name(progname);
+ return ret;
+ }
+ }
+ fprintf(stderr, "no info for format %s\n", format);
+ return 0;
+}
+
+int edit_fmtutil_cnf()
+{
+ string editor = kpse_var_expand("$EDITOR");
+ string command, p;
+ int ret;
+
+ if (test_file('z', editor)) {
+ editor = kpse_var_expand("$VISUAL");
+ if (test_file('z', editor)) {
+ editor = kpse_var_expand("$TEXEDIT");
+ if (test_file('z', editor)) {
+ editor = "wordpad";
+ }
+ }
+ }
+
+ p = editor;
+
+ while (isspace(*p++));
+ if (*p == '\"') {
+ do {
+ p++;
+ } while (*p != '\"' && *p != '\0');
+ if (*p == '\"') {
+ *(p+1) = '\0';
+ }
+ else {
+ fprintf(stderr, "%s: unterminated quoted string for editor specification.\n",
+ progname);
+ exit(1);
+ }
+ }
+ else {
+ do {
+ p++;
+ } while (!isspace(*p) && *p != '\0');
+ *p = '\0';
+ }
+
+ command = concat3(editor, " ", cnf_file);
+#ifdef WIN32
+ ret = win32_system(command, true);
+#else
+ ret = system (command);
+#endif
+ if (ret != 0)
+ fprintf (stderr, "! Trouble executing `%s'.\n", command);
+
+ return ret;
+}
+
+/*
+ This function expects a globbing file specification.
+ There is no recursive call here.
+*/
+void process_multiple_files(string filespec, process_fn fn)
+{
+
+ char path[PATH_MAX];
+ int path_len;
+#if defined(_WIN32)
+ WIN32_FIND_DATA find_file_data;
+ HANDLE hnd;
+#else
+ glob_t gl;
+#endif
+
+ strcpy(path, filespec);
+
+ /* If it is a directory, then get all the files there */
+ if (!(strrchr(path, '*') || strrchr(path, '?'))
+ && test_file('d', path)) {
+ path_len = strlen(path);
+ strcat(path, "/*");
+ }
+ else {
+ path_len = strlen(path) - strlen(xbasename(path)) -1;
+ }
+
+#if defined(_WIN32)
+ hnd = FindFirstFile(path, &find_file_data);
+ while (hnd != INVALID_HANDLE_VALUE) {
+ if(!strcmp(find_file_data.cFileName, ".")
+ || !strcmp(find_file_data.cFileName, ".."))
+ continue;
+ path[path_len+1] = '\0';
+ strcat(path, find_file_data.cFileName);
+ if (KPSE_DEBUG_P(FMTUTIL_DEBUG)) {
+ fprintf(stderr, "Processing %s\n", path);
+ }
+ (*fn)(path);
+ if (FindNextFile(hnd, &find_file_data) == FALSE)
+ break;
+ }
+ path[path_len+1] = '\0';
+ FindClose(hnd);
+
+#else /* ! WIN32 */
+
+ switch (glob(path, GLOB_NOCHECK, NULL, &gl)) {
+ case 0: /* success */
+ for (i = 0; i < gl.gl_pathc; i++) {
+ (*fn)(gl.gl_pathv[i]);
+ }
+ globfree(&gl);
+ break;
+
+ case GLOB_NOSPACE:
+ fprintf(stderr, "%s: Out of memory while globbing %s.\n",
+ kpse_program_name, filespec);
+ mt_exit(1);
+ break;
+
+ default:
+ break;
+ }
+#endif
+
+}
+
+void remove_file(string filename)
+{
+ unlink(filename);
+}
+
+void move_log(string logname)
+{
+ string logdest;
+ logdest = concat3(destdir, DIR_SEP_STRING, logname);
+ unlink(logdest);
+ mvfile(logname, logdest);
+ free(logdest);
+}
+
+void move_fmt(string fmtname)
+{
+ string fmtdest;
+ string texfmt, plainfmt;
+ char cmd[4096];
+ string cmdfmt = "mktexupd \"%s\" %s";
+
+ fmtdest = concat3(destdir, DIR_SEP_STRING, fmtname);
+ unlink(fmtdest);
+ if (KPSE_DEBUG_P(FMTUTIL_DEBUG)) {
+ fprintf(stderr, "Moving %s to %s\n", fmtname, fmtdest);
+ }
+ mvfile(fmtname, fmtdest);
+ fprintf(stderr, "%s: %s successfully generated.\n", progname, fmtdest);
+ sprintf(cmd, cmdfmt, destdir, fmtname);
+#if 1
+ if (KPSE_DEBUG_P(FMTUTIL_DEBUG)) {
+ fprintf(stderr, "Calling system(%s)\n", cmd);
+ }
+#endif
+ system(cmd);
+ /* if we have been called to build a format at runtime */
+ if (incarnation == MKTEXFMT) {
+ fputs(fmtdest, stdout);
+ }
+ free(fmtdest);
+
+ texfmt = concat3(destdir, DIR_SEP_STRING, "tex.fmt");
+ plainfmt = concat3(destdir, DIR_SEP_STRING, "plain.fmt");
+ if (test_file('f', texfmt) && !test_file('f', plainfmt)) {
+ catfile(texfmt, plainfmt, FALSE);
+ sprintf(cmd, cmdfmt, destdir, "plain.fmt");
+ system(cmd);
+ }
+ free(texfmt);
+ free(plainfmt);
+
+ texfmt = concat3(destdir, DIR_SEP_STRING, "tex.efmt");
+ plainfmt = concat3(destdir, DIR_SEP_STRING, "plain.efmt");
+ if (test_file('f', texfmt) && !test_file('f', plainfmt)) {
+ catfile(texfmt, plainfmt, FALSE);
+ sprintf(cmd, cmdfmt, destdir, "plain.efmt");
+ system(cmd);
+ }
+ free(texfmt);
+ free(plainfmt);
+
+ texfmt = concat3(destdir, DIR_SEP_STRING, "mf.base");
+ plainfmt = concat3(destdir, DIR_SEP_STRING, "plain.base");
+ if (test_file('f', texfmt) && !test_file('f', plainfmt)) {
+ catfile(texfmt, plainfmt, FALSE);
+ sprintf(cmd, cmdfmt, destdir, "plain.base");
+ system(cmd);
+ }
+ free(texfmt);
+ free(plainfmt);
+
+ texfmt = concat3(destdir, DIR_SEP_STRING, "mpost.mem");
+ plainfmt = concat3(destdir, DIR_SEP_STRING, "plain.mem");
+ if (test_file('f', texfmt) && !test_file('f', plainfmt)) {
+ catfile(texfmt, plainfmt, FALSE);
+ sprintf(cmd, cmdfmt, destdir, "plain.mem");
+ system(cmd);
+ }
+ free(texfmt);
+ free(plainfmt);
+}
+
+void link_formats()
+{
+ int i, j;
+ boolean skip;
+ string src, srcdll, srcexe, dstexe;
+
+ for (i = 0; i < nb_links; i++) {
+ src = expand_var(concat("$SELFAUTOLOC/", to_link[i].src));
+ /* Check that the destination is not among the ones that should
+ *never* be removed */
+ skip = false;
+ for (j = 0; unrmable_engines[j] != NULL; j++) {
+ if (FILESTRCASEEQ(to_link[i].dst, unrmable_engines[j])) {
+ fprintf(stderr,
+ "%s: %s is a basic engine, won't remove it... skipping.\n",
+ kpse_program_name, unrmable_engines[j]);
+ skip = true;
+ break;
+ }
+ }
+ /* Any smarter way to do that ? */
+ if (skip)
+ continue;
+
+ dstexe = expand_var(concatn("$SELFAUTOLOC/", to_link[i].dst, ".exe", NULL));
+ if (test_file('f', dstexe) && force == false) {
+ fprintf(stderr, "%s: destination %s already exists, skipping.\n", kpse_program_name, dstexe);
+ free(dstexe);
+ continue;
+ }
+#if 0
+ srcexe = concat(src, ".exe");
+ srcdll = concat(src, ".dll");
+ if (FILESTRCASEEQ(srcexe, dstexe)) {
+ printf("same files: %s and %s, doing nothing\n", srcexe, dstexe);
+ }
+ else if (test_file('f', srcdll)) {
+ if (norebuild) {
+ printf("copy %s to %s\n", srcexe, dstexe);
+ }
+ else if (catfile(srcexe, dstexe, false) == false) {
+ fprintf(stderr, "%s: failed to copy %s to %s\n",
+ kpse_program_name, srcexe, dstexe);
+ }
+ }
+ else {
+ sprintf(cmd_sys,"lnexe %s %s", srcexe, dstexe);
+ if (norebuild) {
+ printf("lnexe %s to %s\n", srcexe, dstexe);
+ }
+ else if (system(cmd_sys) == -1) {
+ fprintf(stderr, "%s: failed to lnexe %s to %s\n",
+ kpse_program_name, srcexe, dstexe);
+ }
+ }
+ free(srcdll);
+#else
+ srcexe = concat(src, ".exe");
+ if (FILESTRCASEEQ(srcexe, dstexe)) {
+ printf("same files: %s and %s, doing nothing\n", srcexe, dstexe);
+ }
+ else if (norebuild) {
+ printf("copy %s to %s\n", srcexe, dstexe);
+ }
+ else if (catfile(srcexe, dstexe, false) == false) {
+ fprintf(stderr, "%s: failed to copy %s to %s\n",
+ kpse_program_name, srcexe, dstexe);
+ }
+#endif
+ free(srcexe);
+ free(dstexe);
+ }
+}
diff --git a/Build/source/texk/contrib/fmtutil.h b/Build/source/texk/contrib/fmtutil.h
new file mode 100644
index 00000000000..9d35b8a24dd
--- /dev/null
+++ b/Build/source/texk/contrib/fmtutil.h
@@ -0,0 +1,43 @@
+/* fmtutil.h: definitions for fmtutil lib exports.
+
+Copyright (C) 1998 Fabrice POPINEAU.
+
+Time-stamp: <02/04/03 15:15:00 popineau>
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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 this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _FMTUTIL_H_
+#define _FMTUTIL_H_
+
+#include <kpathsea/c-proto.h>
+#include <kpathsea/debug.h>
+
+#define FMTUTIL_DEBUG (KPSE_LAST_DEBUG+5)
+
+typedef void (* process_fn )(string);
+
+void move_log(string fname);
+void move_fmt(string fname);
+void remove_file(string fname);
+void process_multiple_files(string pattern, process_fn);
+void cache_vars();
+int recreate_all();
+int create_missing();
+int create_one_format(string);
+int recreate_by_hyphenfile(string);
+int show_hyphen_file(string);
+int edit_fmtutil_cnf();
+
+#endif /* _FMTUTIL_H_ */
diff --git a/Build/source/texk/contrib/glob/COPYING.LIB b/Build/source/texk/contrib/glob/COPYING.LIB
new file mode 100644
index 00000000000..eb685a5ec98
--- /dev/null
+++ b/Build/source/texk/contrib/glob/COPYING.LIB
@@ -0,0 +1,481 @@
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This 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 this library; if not, write to the Free
+ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/Build/source/texk/contrib/glob/Makefile.ami b/Build/source/texk/contrib/glob/Makefile.ami
new file mode 100644
index 00000000000..3666d3ef3a3
--- /dev/null
+++ b/Build/source/texk/contrib/glob/Makefile.ami
@@ -0,0 +1,69 @@
+# Makefile for standalone distribution of libglob.a (fnmatch, glob).
+
+# Copyright (C) 1991, 92, 93, 94, 95 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public License
+# as published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+
+# This 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 this library; see the file COPYING.LIB. If
+# not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+# Cambridge, MA 02139, USA.
+
+# Ultrix 2.2 make doesn't expand the value of VPATH.
+VPATH = /glob/
+# This must repeat the value, because configure will remove `VPATH = .'.
+srcdir = /glob/
+
+CC = sc
+RM = delete
+CPPFLAGS =
+CFLAGS =
+
+# Information determined by configure.
+DEFS = Define HAVE_HEADER_STDC Define HAVE_UNISTD_H Define HAVE_STRING_H \
+ Define HAVE_DIRENT_H
+
+# How to invoke ar.
+AR = join
+ARFLAGS = as
+
+# How to invoke ranlib.
+RANLIB = ;
+
+.PHONY: all
+all: glob.lib
+
+glob.lib : glob.o fnmatch.o
+ $(AR) $(ARFLAGS) $@ glob.o fnmatch.o
+ $(RANLIB) $@
+
+# For some reason, Unix make wants the dependencies on the source files.
+# Otherwise it refuses to use an implicit rule!
+# And, get this: it doesn't work to use $(srcdir)foo.c!!
+glob.o: $(srcdir)glob.h $(srcdir)fnmatch.h glob.c
+fnmatch.o: $(srcdir)fnmatch.h fnmatch.c
+
+OUTPUT_OPTION =
+.c.o:
+ $(CC) IDir "" \
+ $(DEFS) $(CPPFLAGS) $(CFLAGS) $< $(OUTPUT_OPTION)
+
+.PHONY: clean realclean glob-clean glob-realclean distclean
+clean glob-clean:
+ -$(RM) glob.lib "#?.o" core
+distclean glob-realclean: clean
+ -$(RM) TAGS tags Makefile config.status config.h config.log
+realcean: distclean
+
+# For inside the C library.
+glob.tar glob.tar.Z:
+ $(MAKE) -C .. $@
diff --git a/Build/source/texk/contrib/glob/Makefile.in b/Build/source/texk/contrib/glob/Makefile.in
new file mode 100644
index 00000000000..8c091b33ac9
--- /dev/null
+++ b/Build/source/texk/contrib/glob/Makefile.in
@@ -0,0 +1,66 @@
+# Makefile for standalone distribution of libglob.a (fnmatch, glob).
+
+# Copyright (C) 1991, 92, 93, 94, 95 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public License
+# as published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+
+# This 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 this library; see the file COPYING.LIB. If
+# not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+# Cambridge, MA 02139, USA.
+
+# Ultrix 2.2 make doesn't expand the value of VPATH.
+VPATH = @srcdir@
+# This must repeat the value, because configure will remove `VPATH = .'.
+srcdir = @srcdir@
+
+CC = @CC@
+CPPFLAGS = @CPPFLAGS@
+CFLAGS = @CFLAGS@
+
+# Information determined by configure.
+DEFS = @DEFS@
+
+# How to invoke ar.
+AR = @AR@
+ARFLAGS = rv
+
+# How to invoke ranlib.
+RANLIB = @RANLIB@
+
+.PHONY: all
+all: libglob.a
+
+libglob.a: glob.o fnmatch.o
+ $(AR) $(ARFLAGS) $@ glob.o fnmatch.o
+ $(RANLIB) $@
+
+# For some reason, Unix make wants the dependencies on the source files.
+# Otherwise it refuses to use an implicit rule!
+# And, get this: it doesn't work to use $(srcdir)/foo.c!!
+glob.o: $(srcdir)/glob.h $(srcdir)/fnmatch.h glob.c
+fnmatch.o: $(srcdir)/fnmatch.h fnmatch.c
+
+.c.o:
+ $(CC) -I. -I$(srcdir) -c \
+ $(DEFS) $(CPPFLAGS) $(CFLAGS) $< $(OUTPUT_OPTION)
+
+.PHONY: clean realclean glob-clean glob-realclean distclean
+clean glob-clean:
+ -rm -f libglob.a *.o core
+distclean glob-realclean: clean
+ -rm -f TAGS tags Makefile config.status config.h config.log
+realcean: distclean
+
+# For inside the C library.
+glob.tar glob.tar.Z:
+ $(MAKE) -C .. $@
diff --git a/Build/source/texk/contrib/glob/SCOPTIONS b/Build/source/texk/contrib/glob/SCOPTIONS
new file mode 100644
index 00000000000..f89daae12f7
--- /dev/null
+++ b/Build/source/texk/contrib/glob/SCOPTIONS
@@ -0,0 +1,13 @@
+ERRORREXX
+OPTIMIZE
+NOVERSION
+OPTIMIZERTIME
+OPTIMIZERALIAS
+DEFINE INCLUDEDIR="include:"
+DEFINE LIBDIR="lib:"
+DEFINE NO_ALLOCA
+DEFINE NO_FLOAT
+DEFINE NO_ARCHIVES
+IGNORE=161
+IGNORE=100
+STARTUP=cres
diff --git a/Build/source/texk/contrib/glob/SMakefile b/Build/source/texk/contrib/glob/SMakefile
new file mode 100644
index 00000000000..1c82e0a076a
--- /dev/null
+++ b/Build/source/texk/contrib/glob/SMakefile
@@ -0,0 +1,69 @@
+# Makefile for standalone distribution of libglob.a (fnmatch, glob).
+
+# Copyright (C) 1991, 92, 93, 94, 95 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public License
+# as published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+
+# This 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 this library; see the file COPYING.LIB. If
+# not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+# Cambridge, MA 02139, USA.
+
+# Ultrix 2.2 make doesn't expand the value of VPATH.
+VPATH = /glob/
+# This must repeat the value, because configure will remove `VPATH = .'.
+srcdir = /glob/
+
+CC = sc
+CPPFLAGS =
+CFLAGS =
+MAKE = smake
+RM = delete
+
+# Information determined by configure.
+DEFS = Define HAVE_HEADER_STDC Define HAVE_UNISTD_H Define HAVE_STRING_H \
+ Define HAVE_DIRENT_H
+
+# How to invoke ar.
+AR = join
+ARFLAGS = as
+
+# How to invoke ranlib.
+RANLIB = ;
+
+.PHONY: all
+all: glob.lib
+
+glob.lib : glob.o fnmatch.o
+ $(AR) $(ARFLAGS) $@ glob.o fnmatch.o
+ $(RANLIB) $@
+
+# For some reason, Unix make wants the dependencies on the source files.
+# Otherwise it refuses to use an implicit rule!
+# And, get this: it doesn't work to use $(srcdir)foo.c!!
+glob.o: $(srcdir)glob.h $(srcdir)fnmatch.h glob.c
+fnmatch.o: $(srcdir)fnmatch.h fnmatch.c
+
+.c.o:
+ $(CC) IDir "" \
+ $(DEFS) $(CPPFLAGS) $(CFLAGS) $< $(OUTPUT_OPTION)
+
+.PHONY: clean realclean glob-clean glob-realclean distclean
+clean glob-clean:
+ -$(RM) -f glob.lib *.o core
+distclean glob-realclean: clean
+ -$(RM) -f TAGS tags Makefile config.status config.h config.log
+realcean: distclean
+
+# For inside the C library.
+glob.tar glob.tar.Z:
+ $(MAKE) -C .. $@
diff --git a/Build/source/texk/contrib/glob/configure b/Build/source/texk/contrib/glob/configure
new file mode 100755
index 00000000000..d946ae36162
--- /dev/null
+++ b/Build/source/texk/contrib/glob/configure
@@ -0,0 +1,2139 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+ac_config_files=
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.13"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_envvar| sed 's/[_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: invalid variable name: $ac_envvar" 1>&2; exit 1; }
+ fi
+ ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+ eval "$ac_envvar='$ac_optarg'"
+ export $ac_envvar ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=fnmatch.c
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:538: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ if test -z "$COMSPEC"; then ac_x=-f; else ac_x=-x; fi
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test $ac_x $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:569: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_prog_rejected=no
+ if test -z "$COMSPEC"; then ac_x=-f; else ac_x=-x; fi
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test $ac_x $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test -z "$CC"; then
+ case "`uname -s`" in
+ *win32* | *WIN32*)
+ # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:621: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ if test -z "$COMSPEC"; then ac_x=-f; else ac_x=-x; fi
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test $ac_x $ac_dir/$ac_word; then
+ ac_cv_prog_CC="cl"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ ;;
+ esac
+ fi
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:654: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 665 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:670: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cc_cross=no
+ else
+ ac_cv_prog_cc_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:696: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:701: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:710: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:729: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+
+# Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:763: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ if test -z "$COMSPEC"; then ac_x=-f; else ac_x=-x; fi
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test $ac_x $ac_dir/$ac_word; then
+ ac_cv_prog_AR="ar"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_AR" && ac_cv_prog_AR="ar"
+fi
+fi
+AR="$ac_cv_prog_AR"
+if test -n "$AR"; then
+ echo "$ac_t""$AR" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+# Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:794: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ if test -z "$COMSPEC"; then ac_x=-f; else ac_x=-x; fi
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test $ac_x $ac_dir/$ac_word; then
+ ac_cv_prog_RANLIB="ranlib"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+ echo "$ac_t""$RANLIB" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:823: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # This must be in double quotes, not single quotes, because CPP may get
+ # substituted into the Makefile and "${CC-cc}" will confuse make.
+ CPP="${CC-cc} -E"
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+#line 838 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:844: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+#line 855 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:861: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -nologo -E"
+ cat > conftest.$ac_ext <<EOF
+#line 872 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:878: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ ac_cv_prog_CPP="$CPP"
+fi
+ CPP="$ac_cv_prog_CPP"
+else
+ ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+ echo $ac_n "checking for AIX""... $ac_c" 1>&6
+echo "configure:902: checking for AIX" >&5
+cat > conftest.$ac_ext <<EOF
+#line 904 "configure"
+#include "confdefs.h"
+#ifdef _AIX
+ yes
+#endif
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "yes" >/dev/null 2>&1; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF
+#define _ALL_SOURCE 1
+EOF
+
+else
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+
+
+ac_safe=`echo "minix/config.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for minix/config.h""... $ac_c" 1>&6
+echo "configure:927: checking for minix/config.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 932 "configure"
+#include "confdefs.h"
+#include <minix/config.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:937: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ MINIX=yes
+else
+ echo "$ac_t""no" 1>&6
+MINIX=
+fi
+
+if test "$MINIX" = yes; then
+ cat >> confdefs.h <<\EOF
+#define _POSIX_SOURCE 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _POSIX_1_SOURCE 2
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _MINIX 1
+EOF
+
+fi
+
+echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&6
+echo "configure:975: checking for POSIXized ISC" >&5
+if test -d /etc/conf/kconfig.d &&
+ grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1
+then
+ echo "$ac_t""yes" 1>&6
+ ISC=yes # If later tests want to check for ISC.
+ cat >> confdefs.h <<\EOF
+#define _POSIX_SOURCE 1
+EOF
+
+ if test "$GCC" = yes; then
+ CC="$CC -posix"
+ else
+ CC="$CC -Xp"
+ fi
+else
+ echo "$ac_t""no" 1>&6
+ ISC=
+fi
+
+echo $ac_n "checking for working const""... $ac_c" 1>&6
+echo "configure:996: checking for working const" >&5
+if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1001 "configure"
+#include "confdefs.h"
+
+int main() {
+
+/* Ultrix mips cc rejects this. */
+typedef int charset[2]; const charset x;
+/* SunOS 4.1.1 cc rejects this. */
+char const *const *ccp;
+char **p;
+/* NEC SVR4.0.2 mips cc rejects this. */
+struct point {int x, y;};
+static struct point const zero = {0,0};
+/* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in an arm
+ of an if-expression whose if-part is not a constant expression */
+const char *g = "string";
+ccp = &g + (g ? g-g : 0);
+/* HPUX 7.0 cc rejects these. */
+++ccp;
+p = (char**) ccp;
+ccp = (char const *const *) p;
+{ /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+}
+{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+}
+{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+}
+{ /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+}
+{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+}
+
+; return 0; }
+EOF
+if { (eval echo configure:1050: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_const=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_c_const=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_const" 1>&6
+if test $ac_cv_c_const = no; then
+ cat >> confdefs.h <<\EOF
+#define const
+EOF
+
+fi
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:1071: checking for ANSI C header files" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1076 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1084: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ ac_cv_header_stdc=yes
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1101 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "memchr" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1119 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "free" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+ :
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1140 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+if { (eval echo configure:1151: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_header_stdc=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+ cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+for ac_hdr in memory.h unistd.h string.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:1178: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1183 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1188: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ac_header_dirent=no
+for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6
+echo "configure:1219: checking for $ac_hdr that defines DIR" >&5
+if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1224 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <$ac_hdr>
+int main() {
+DIR *dirp = 0;
+; return 0; }
+EOF
+if { (eval echo configure:1232: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_header_dirent_$ac_safe=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_dirent_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_dirent_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+ ac_header_dirent=$ac_hdr; break
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
+if test $ac_header_dirent = dirent.h; then
+echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6
+echo "configure:1257: checking for opendir in -ldir" >&5
+ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ldir $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1265 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char opendir();
+
+int main() {
+opendir()
+; return 0; }
+EOF
+if { (eval echo configure:1276: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ LIBS="$LIBS -ldir"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6
+echo "configure:1298: checking for opendir in -lx" >&5
+ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lx $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1306 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char opendir();
+
+int main() {
+opendir()
+; return 0; }
+EOF
+if { (eval echo configure:1317: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ LIBS="$LIBS -lx"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+echo $ac_n "checking whether closedir returns void""... $ac_c" 1>&6
+echo "configure:1340: checking whether closedir returns void" >&5
+if eval "test \"`echo '$''{'ac_cv_func_closedir_void'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_closedir_void=yes
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1348 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <$ac_header_dirent>
+int closedir(); main() { exit(closedir(opendir(".")) != 0); }
+EOF
+if { (eval echo configure:1354: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_func_closedir_void=no
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_func_closedir_void=yes
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_func_closedir_void" 1>&6
+if test $ac_cv_func_closedir_void = yes; then
+ cat >> confdefs.h <<\EOF
+#define CLOSEDIR_VOID 1
+EOF
+
+fi
+
+# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
+# for constant arguments. Useless!
+echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6
+echo "configure:1379: checking for working alloca.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1384 "configure"
+#include "confdefs.h"
+#include <alloca.h>
+int main() {
+char *p = alloca(2 * sizeof(int));
+; return 0; }
+EOF
+if { (eval echo configure:1391: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ac_cv_header_alloca_h=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_alloca_h=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_alloca_h" 1>&6
+if test $ac_cv_header_alloca_h = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ALLOCA_H 1
+EOF
+
+fi
+
+echo $ac_n "checking for alloca""... $ac_c" 1>&6
+echo "configure:1412: checking for alloca" >&5
+if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1417 "configure"
+#include "confdefs.h"
+
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#else
+# ifdef _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+# else
+# if HAVE_ALLOCA_H
+# include <alloca.h>
+# else
+# ifdef _AIX
+ #pragma alloca
+# else
+# ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+# endif
+# endif
+# endif
+# endif
+#endif
+
+int main() {
+char *p = (char *) alloca(1);
+; return 0; }
+EOF
+if { (eval echo configure:1445: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ac_cv_func_alloca_works=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_func_alloca_works=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_func_alloca_works" 1>&6
+if test $ac_cv_func_alloca_works = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ALLOCA 1
+EOF
+
+fi
+
+if test $ac_cv_func_alloca_works = no; then
+ # The SVR3 libPW and SVR4 libucb both contain incompatible functions
+ # that cause trouble. Some versions do not even contain alloca or
+ # contain a buggy version. If you still want to use their alloca,
+ # use ar to extract alloca.o from them instead of compiling alloca.c.
+ ALLOCA=alloca.${ac_objext}
+ cat >> confdefs.h <<\EOF
+#define C_ALLOCA 1
+EOF
+
+
+echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6
+echo "configure:1477: checking whether alloca needs Cray hooks" >&5
+if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1482 "configure"
+#include "confdefs.h"
+#if defined(CRAY) && ! defined(CRAY2)
+webecray
+#else
+wenotbecray
+#endif
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "webecray" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_os_cray=yes
+else
+ rm -rf conftest*
+ ac_cv_os_cray=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_os_cray" 1>&6
+if test $ac_cv_os_cray = yes; then
+for ac_func in _getb67 GETB67 getb67; do
+ echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:1507: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1512 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1535: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<EOF
+#define CRAY_STACKSEG_END $ac_func
+EOF
+
+ break
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+done
+fi
+
+echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6
+echo "configure:1562: checking stack direction for C alloca" >&5
+if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_c_stack_direction=0
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1570 "configure"
+#include "confdefs.h"
+find_stack_direction ()
+{
+ static char *addr = 0;
+ auto char dummy;
+ if (addr == 0)
+ {
+ addr = &dummy;
+ return find_stack_direction ();
+ }
+ else
+ return (&dummy > addr) ? 1 : -1;
+}
+main ()
+{
+ exit (find_stack_direction() < 0);
+}
+EOF
+if { (eval echo configure:1589: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_c_stack_direction=1
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_c_stack_direction=-1
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_c_stack_direction" 1>&6
+cat >> confdefs.h <<EOF
+#define STACK_DIRECTION $ac_cv_c_stack_direction
+EOF
+
+fi
+
+echo $ac_n "checking for working strcoll""... $ac_c" 1>&6
+echo "configure:1611: checking for working strcoll" >&5
+if eval "test \"`echo '$''{'ac_cv_func_strcoll_works'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_strcoll_works=no
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1619 "configure"
+#include "confdefs.h"
+#include <string.h>
+main ()
+{
+ exit (strcoll ("abc", "def") >= 0 ||
+ strcoll ("ABC", "DEF") >= 0 ||
+ strcoll ("123", "456") >= 0);
+}
+EOF
+if { (eval echo configure:1629: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_func_strcoll_works=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_func_strcoll_works=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_func_strcoll_works" 1>&6
+if test $ac_cv_func_strcoll_works = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_STRCOLL 1
+EOF
+
+fi
+
+ac_config_files="$ac_config_files Makefile"
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+DEFS=-DHAVE_CONFIG_H
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.13"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+
+
+trap 'rm -fr `echo "$ac_config_files " | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@CC@%$CC%g
+s%@AR@%$AR%g
+s%@RANLIB@%$RANLIB%g
+s%@CPP@%$CPP%g
+s%@ALLOCA@%$ALLOCA%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"$ac_config_files"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*|[A-z]:/*) # Absolute path.
+ srcdir="$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ rm -f conftest.in
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%:% $ac_given_srcdir/%g" -e "s%^%$ac_given_srcdir/%"`
+ cat $ac_file_inputs > conftest.in
+ #
+ # Replace lines of the form ac_include foo with the contents of foo:
+ # first, from the ac_include lines construct a list of file names.
+ # From that list, we construct a second list of those files that exist.
+ # Then we construct lists of sed commands for including those files,
+ # and a sed command that removes the ac_include lines. We don't attempt
+ # to read non-existent files because some (buggy) versions of sed choke
+ # on this. Have to use sed because old (Ultrix, SunOS) awk does not support
+ # getline or system. (Anyway, configure scripts aren't supposed to use awk.)
+ # Can't use only one -e and commands {dr foo} because foo has to be last.
+ # Be careful, because the filename may contain /. Be careful with
+ # whitespace; we need to use echo.
+ #
+ file_substs=`sed -n '/^ac_include/s%ac_include[ ]*\(.*\)%\1%p' conftest.in`
+ # Create the sed command line ...
+ if test -n "$file_substs"; then
+ echo "configure: warning: ac_include is obsolete; instead use kpse_include" 1>&2
+ file_subst_cmd="sed -e 's/^ac_include/kpse_include/'"
+ else
+ file_subst_cmd='sed'
+ fi
+ kpse_substs=`sed -n '/^kpse_include/s%kpse_include[ ]*\(.*\)%\1%p' conftest.in`
+ for ac_inc in $file_substs $kpse_substs; do
+ if test -f "$ac_given_srcdir/$ac_inc"; then
+ ac_mung=`echo $ac_inc | sed 's,/,%,g'`
+ file_subst_cmd="$file_subst_cmd -e '/^kpse_include $ac_mung$/r $ac_given_srcdir/$ac_inc'"
+ fi
+ done
+ file_subst_cmd="$file_subst_cmd -e '/^kpse_include/d'"
+ # ... and fix the whitespace and escaped slashes.
+ file_subst_cmd=`echo "$file_subst_cmd" | sed -e 's,%,\\\/,g' \
+-e 's/kpse_include /kpse_include[ ]*/g'`
+ # I can't find any way to do variable substitution in the sed commands
+ # (so the user could have, e.g., $top_srcdir in their ac_include line).
+ (eval $file_subst_cmd conftest.in) \
+ | sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+" | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s* conftest.in
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)'
+ac_dB='\([ ][ ]*\)[^ ].*$%\1#\2'
+ac_dC='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_uB='\([ ]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+if test "${CONFIG_HEADERS+set}" != set; then
+EOF
+cat >> $CONFIG_STATUS <<EOF
+ CONFIG_HEADERS=""
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+fi
+for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ echo creating $ac_file
+
+ rm -f conftest.frag conftest.in conftest.out
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%:% $ac_given_srcdir/%g" -e "s%^%$ac_given_srcdir/%"`
+ cat $ac_file_inputs > conftest.in
+
+EOF
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h. And first:
+# Protect against being on the right side of a sed subst in config.status.
+# Protect against being in an unquoted here document in config.status.
+rm -f conftest.vals
+cat > conftest.hdr <<\EOF
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# This sed command replaces #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >> conftest.vals <<\EOF
+s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+EOF
+
+# Break up conftest.vals because some shells have a limit on
+# the size of here documents, and old seds have small limits too.
+
+rm -f conftest.tail
+while :
+do
+ ac_lines=`grep -c . conftest.vals`
+ # grep -c gives empty output for an empty file on some AIX systems.
+ if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+ # Write a limited-size here document to conftest.frag.
+ echo ' cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+ echo 'CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+ rm -f conftest.vals
+ mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+cat >> $CONFIG_STATUS <<\EOF
+ rm -f conftest.frag conftest.h
+ echo "/* $ac_file. Generated automatically by configure. */" > conftest.h
+ cat conftest.in >> conftest.h
+ rm -f conftest.in
+ if cmp -s $ac_file conftest.h 2>/dev/null; then
+ echo "$ac_file is unchanged"
+ rm -f conftest.h
+ else
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ fi
+ rm -f $ac_file
+ mv conftest.h $ac_file
+ fi
+fi; done
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
+if test "$no_recursion" != yes; then
+
+ # Remove --cache-file and --srcdir arguments so they do not pile up.
+ ac_sub_configure_args=
+ ac_prev=
+ for ac_arg in $ac_configure_args; do
+ if test -n "$ac_prev"; then
+ ac_prev=
+ continue
+ fi
+ case "$ac_arg" in
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ ;;
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ ;;
+ *) ac_sub_configure_args="$ac_sub_configure_args $ac_arg" ;;
+ esac
+ done
+
+ for ac_config_dir in : $subdirs; do
+
+ # Do not complain, so a configure script can configure whichever
+ # parts of a large source tree are present.
+ if test ! -d $srcdir/$ac_config_dir; then
+ continue
+ fi
+
+ echo configuring in $ac_config_dir
+
+ case "$srcdir" in
+ .) ;;
+ *)
+ if test -d ./$ac_config_dir || mkdir ./$ac_config_dir; then :;
+ else
+ { echo "configure: error: can not create `pwd`/$ac_config_dir" 1>&2; exit 1; }
+ fi
+ ;;
+ esac
+
+ ac_popdir=`pwd`
+ cd $ac_config_dir
+
+ # A "../" for each directory in /$ac_config_dir.
+ ac_dots=`echo $ac_config_dir|sed -e 's%^\./%%' -e 's%[^/]$%&/%' -e 's%[^/]*/%../%g'`
+
+ case "$srcdir" in
+ .) # No --srcdir option. We are building in place.
+ ac_sub_srcdir=$srcdir ;;
+ /*|[A-z]:/*) # Absolute path.
+ ac_sub_srcdir=$srcdir/$ac_config_dir ;;
+ *) # Relative path.
+ ac_sub_srcdir=$ac_dots$srcdir/$ac_config_dir ;;
+ esac
+
+ # Check for guested configure; otherwise get Cygnus style configure.
+ if test -f ./configure; then
+ ac_sub_configure=./configure
+ elif test -f $ac_sub_srcdir/configure; then
+ ac_sub_configure=$ac_sub_srcdir/configure
+ elif test -f $ac_sub_srcdir/configure.in; then
+ ac_sub_configure=$ac_configure
+ else
+ echo "configure: warning: no configuration information is in $ac_config_dir" 1>&2
+ ac_sub_configure=
+ fi
+
+ # The recursion is here.
+ if test -n "$ac_sub_configure"; then
+
+ # Make the cache file name correct relative to the subdirectory.
+ case "$cache_file" in
+ /*|[A-z]:/*) ac_sub_cache_file=$cache_file ;;
+ *) # Relative path.
+ ac_sub_cache_file="$ac_dots$cache_file" ;;
+ esac
+
+ echo "running ${CONFIG_SHELL-/bin/sh} $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_sub_srcdir"
+ # The eval makes quoting arguments work.
+ if eval ${CONFIG_SHELL-/bin/sh} $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_sub_srcdir
+ then :
+ else
+ { echo "configure: error: $ac_sub_configure failed for $ac_config_dir" 1>&2; exit 1; }
+ fi
+ fi
+
+ cd $ac_popdir
+ done
+fi
+
diff --git a/Build/source/texk/contrib/glob/configure.bat b/Build/source/texk/contrib/glob/configure.bat
new file mode 100644
index 00000000000..f3a0f5db681
--- /dev/null
+++ b/Build/source/texk/contrib/glob/configure.bat
@@ -0,0 +1,26 @@
+@echo off
+echo Configuring glob for GO32
+rem This batch file assumes a unix-type "sed" program
+
+echo # Makefile generated by "configure.bat"> Makefile
+
+if exist config.sed del config.sed
+
+echo "s/@srcdir@/./ ">> config.sed
+echo "s/@CC@/gcc/ ">> config.sed
+echo "s/@CFLAGS@/-O2 -g/ ">> config.sed
+echo "s/@CPPFLAGS@/-DHAVE_CONFIG_H -I../ ">> config.sed
+echo "s/@AR@/ar/ ">> config.sed
+echo "s/@RANLIB@/ranlib/ ">> config.sed
+echo "s/@LDFLAGS@// ">> config.sed
+echo "s/@DEFS@// ">> config.sed
+echo "s/@ALLOCA@// ">> config.sed
+echo "s/@LIBS@// ">> config.sed
+echo "s/@LIBOBJS@// ">> config.sed
+echo "s/^Makefile *:/_Makefile:/ ">> config.sed
+echo "s/^config.h *:/_config.h:/ ">> config.sed
+
+sed -e "s/^\"//" -e "s/\"$//" -e "s/[ ]*$//" config.sed > config2.sed
+sed -f config2.sed Makefile.in >> Makefile
+del config.sed
+del config2.sed
diff --git a/Build/source/texk/contrib/glob/configure.in b/Build/source/texk/contrib/glob/configure.in
new file mode 100644
index 00000000000..ff35fcf660f
--- /dev/null
+++ b/Build/source/texk/contrib/glob/configure.in
@@ -0,0 +1,20 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(fnmatch.c) dnl A distinctive file to look for in srcdir.
+AC_PREREQ(2.1) dnl Minimum Autoconf version required.
+AC_PROG_CC
+AC_CHECK_PROG(AR, ar, ar, ar)
+AC_PROG_RANLIB
+AC_PROG_CPP dnl Later checks need this.
+dnl These two want to come early.
+AC_AIX
+AC_MINIX
+AC_ISC_POSIX
+AC_CONST
+AC_HEADER_STDC
+AC_CHECK_HEADERS(memory.h unistd.h string.h)
+AC_HEADER_DIRENT
+AC_FUNC_CLOSEDIR_VOID
+AC_FUNC_ALLOCA
+AC_FUNC_STRCOLL
+KPSE_CONFIG_FILES([Makefile])
+AC_OUTPUT
diff --git a/Build/source/texk/contrib/glob/fnmatch.c b/Build/source/texk/contrib/glob/fnmatch.c
new file mode 100644
index 00000000000..de45941f8f9
--- /dev/null
+++ b/Build/source/texk/contrib/glob/fnmatch.c
@@ -0,0 +1,230 @@
+/* Copyright (C) 1991, 1992, 1993, 1996 Free Software Foundation, Inc.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This 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 this library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/* Enable GNU extensions in fnmatch.h. */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#include <errno.h>
+#include <fnmatch.h>
+#include <ctype.h>
+
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself. This code is part of the GNU C
+ Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ program understand `configure --with-gnu-libc' and omit the object files,
+ it is simpler to just do this in the source for each such file. */
+
+#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+
+
+#ifndef errno
+extern int errno;
+#endif
+
+/* Match STRING against the filename pattern PATTERN, returning zero if
+ it matches, nonzero if not. */
+int
+fnmatch (pattern, string, flags)
+ const char *pattern;
+ const char *string;
+ int flags;
+{
+ register const char *p = pattern, *n = string;
+ register char c;
+
+/* Note that this evalutes C many times. */
+#define FOLD(c) ((flags & FNM_CASEFOLD) && isupper (c) ? tolower (c) : (c))
+
+ while ((c = *p++) != '\0')
+ {
+ c = FOLD (c);
+
+ switch (c)
+ {
+ case '?':
+ if (*n == '\0')
+ return FNM_NOMATCH;
+ else if ((flags & FNM_FILE_NAME) && *n == '/')
+ return FNM_NOMATCH;
+ else if ((flags & FNM_PERIOD) && *n == '.' &&
+ (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
+ return FNM_NOMATCH;
+ break;
+
+ case '\\':
+ if (!(flags & FNM_NOESCAPE))
+ {
+ c = *p++;
+ if (c == '\0')
+ /* Trailing \ loses. */
+ return FNM_NOMATCH;
+ c = FOLD (c);
+ }
+ if (FOLD (*n) != c)
+ return FNM_NOMATCH;
+ break;
+
+ case '*':
+ if ((flags & FNM_PERIOD) && *n == '.' &&
+ (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
+ return FNM_NOMATCH;
+
+ for (c = *p++; c == '?' || c == '*'; c = *p++)
+ {
+ if ((flags & FNM_FILE_NAME) && *n == '/')
+ /* A slash does not match a wildcard under FNM_FILE_NAME. */
+ return FNM_NOMATCH;
+ else if (c == '?')
+ {
+ /* A ? needs to match one character. */
+ if (*n == '\0')
+ /* There isn't another character; no match. */
+ return FNM_NOMATCH;
+ else
+ /* One character of the string is consumed in matching
+ this ? wildcard, so *??? won't match if there are
+ less than three characters. */
+ ++n;
+ }
+ }
+
+ if (c == '\0')
+ return 0;
+
+ {
+ char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
+ c1 = FOLD (c1);
+ for (--p; *n != '\0'; ++n)
+ if ((c == '[' || FOLD (*n) == c1) &&
+ fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
+ return 0;
+ return FNM_NOMATCH;
+ }
+
+ case '[':
+ {
+ /* Nonzero if the sense of the character class is inverted. */
+ register int not;
+
+ if (*n == '\0')
+ return FNM_NOMATCH;
+
+ if ((flags & FNM_PERIOD) && *n == '.' &&
+ (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
+ return FNM_NOMATCH;
+
+ not = (*p == '!' || *p == '^');
+ if (not)
+ ++p;
+
+ c = *p++;
+ for (;;)
+ {
+ register char cstart = c, cend = c;
+
+ if (!(flags & FNM_NOESCAPE) && c == '\\')
+ {
+ if (*p == '\0')
+ return FNM_NOMATCH;
+ cstart = cend = *p++;
+ }
+
+ cstart = cend = FOLD (cstart);
+
+ if (c == '\0')
+ /* [ (unterminated) loses. */
+ return FNM_NOMATCH;
+
+ c = *p++;
+ c = FOLD (c);
+
+ if ((flags & FNM_FILE_NAME) && c == '/')
+ /* [/] can never match. */
+ return FNM_NOMATCH;
+
+ if (c == '-' && *p != ']')
+ {
+ cend = *p++;
+ if (!(flags & FNM_NOESCAPE) && cend == '\\')
+ cend = *p++;
+ if (cend == '\0')
+ return FNM_NOMATCH;
+ cend = FOLD (cend);
+
+ c = *p++;
+ }
+
+ if (FOLD (*n) >= cstart && FOLD (*n) <= cend)
+ goto matched;
+
+ if (c == ']')
+ break;
+ }
+ if (!not)
+ return FNM_NOMATCH;
+ break;
+
+ matched:;
+ /* Skip the rest of the [...] that already matched. */
+ while (c != ']')
+ {
+ if (c == '\0')
+ /* [... (unterminated) loses. */
+ return FNM_NOMATCH;
+
+ c = *p++;
+ if (!(flags & FNM_NOESCAPE) && c == '\\')
+ {
+ if (*p == '\0')
+ return FNM_NOMATCH;
+ /* XXX 1003.2d11 is unclear if this is right. */
+ ++p;
+ }
+ }
+ if (not)
+ return FNM_NOMATCH;
+ }
+ break;
+
+ default:
+ if (c != FOLD (*n))
+ return FNM_NOMATCH;
+ }
+
+ ++n;
+ }
+
+ if (*n == '\0')
+ return 0;
+
+ if ((flags & FNM_LEADING_DIR) && *n == '/')
+ /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
+ return 0;
+
+ return FNM_NOMATCH;
+}
+
+#endif /* _LIBC or not __GNU_LIBRARY__. */
diff --git a/Build/source/texk/contrib/glob/fnmatch.h b/Build/source/texk/contrib/glob/fnmatch.h
new file mode 100644
index 00000000000..9a0036e53aa
--- /dev/null
+++ b/Build/source/texk/contrib/glob/fnmatch.h
@@ -0,0 +1,68 @@
+/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This 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 this library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#ifndef _FNMATCH_H
+
+#define _FNMATCH_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if (defined (__cplusplus) || (defined (__STDC__) && __STDC__) \
+ || defined (WIN32))
+#undef __P
+#define __P(protos) protos
+#else /* Not C++ or ANSI C. */
+#undef __P
+#define __P(protos) ()
+/* We can get away without defining `const' here only because in this file
+ it is used only inside the prototype for `fnmatch', which is elided in
+ non-ANSI C where `const' is problematical. */
+#endif /* C++ or ANSI C. */
+
+
+/* We #undef these before defining them because some losing systems
+ (HP-UX A.08.07 for example) define these in <unistd.h>. */
+#undef FNM_PATHNAME
+#undef FNM_NOESCAPE
+#undef FNM_PERIOD
+
+/* Bits set in the FLAGS argument to `fnmatch'. */
+#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */
+#define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */
+#define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */
+
+#if !defined (_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 2 || defined (_GNU_SOURCE)
+#define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */
+#define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */
+#define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */
+#endif
+
+/* Value returned by `fnmatch' if STRING does not match PATTERN. */
+#define FNM_NOMATCH 1
+
+/* Match STRING against the filename pattern PATTERN,
+ returning zero if it matches, FNM_NOMATCH if not. */
+extern int fnmatch __P ((const char *__pattern, const char *__string,
+ int __flags));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* fnmatch.h */
diff --git a/Build/source/texk/contrib/glob/glob.c b/Build/source/texk/contrib/glob/glob.c
new file mode 100644
index 00000000000..76060e14259
--- /dev/null
+++ b/Build/source/texk/contrib/glob/glob.c
@@ -0,0 +1,906 @@
+/* Copyright (C) 1991, 92, 93, 94, 95, 96 Free Software Foundation, Inc.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This 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 this library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+/* AIX requires this to be the first thing in the file. */
+#if defined (_AIX) && !defined (__GNUC__)
+ #pragma alloca
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/* Enable GNU extensions in glob.h. */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself. This code is part of the GNU C
+ Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ program understand `configure --with-gnu-libc' and omit the object files,
+ it is simpler to just do this in the source for each such file. */
+
+#define GLOB_INTERFACE_VERSION 1
+#if !defined (_LIBC) && defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1
+#include <gnu-versions.h>
+#if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION
+#define ELIDE_CODE
+#endif
+#endif
+
+#ifndef ELIDE_CODE
+
+#ifdef STDC_HEADERS
+#include <stddef.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#ifndef POSIX
+#ifdef _POSIX_VERSION
+#define POSIX
+#endif
+#endif
+#endif
+
+#if !defined (_AMIGA) && !defined (VMS) && !defined(WIN32)
+#include <pwd.h>
+#endif
+
+#if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
+extern int errno;
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+
+#if defined (HAVE_DIRENT_H) || defined (__GNU_LIBRARY__)
+# include <dirent.h>
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+#else
+# define dirent direct
+# define NAMLEN(dirent) (dirent)->d_namlen
+# ifdef HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# endif
+# ifdef HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif
+# ifdef HAVE_NDIR_H
+# include <ndir.h>
+# endif
+# ifdef HAVE_VMSDIR_H
+# include "vmsdir.h"
+# endif /* HAVE_VMSDIR_H */
+#endif
+
+
+/* In GNU systems, <dirent.h> defines this macro for us. */
+#ifdef _D_NAMLEN
+#undef NAMLEN
+#define NAMLEN(d) _D_NAMLEN(d)
+#endif
+
+
+#if (defined (POSIX) || defined (WIN32)) && !defined (__GNU_LIBRARY__)
+/* Posix does not require that the d_ino field be present, and some
+ systems do not provide it. */
+#define REAL_DIR_ENTRY(dp) 1
+#else
+#define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
+#endif /* POSIX */
+
+#if (defined (STDC_HEADERS) || defined (__GNU_LIBRARY__))
+#include <stdlib.h>
+#include <string.h>
+#define ANSI_STRING
+#else /* No standard headers. */
+
+extern char *getenv ();
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#define ANSI_STRING
+#else
+#include <strings.h>
+#endif
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+
+extern char *malloc (), *realloc ();
+extern void free ();
+
+extern void qsort ();
+extern void abort (), exit ();
+
+#endif /* Standard headers. */
+
+#ifndef ANSI_STRING
+
+#ifndef bzero
+extern void bzero ();
+#endif
+#ifndef bcopy
+extern void bcopy ();
+#endif
+
+#define memcpy(d, s, n) bcopy ((s), (d), (n))
+#define strrchr rindex
+/* memset is only used for zero here, but let's be paranoid. */
+#define memset(s, better_be_zero, n) \
+ ((void) ((better_be_zero) == 0 ? (bzero((s), (n)), 0) : (abort(), 0)))
+#endif /* Not ANSI_STRING. */
+
+#ifndef HAVE_STRCOLL
+#define strcoll strcmp
+#endif
+
+
+#ifndef __GNU_LIBRARY__
+#ifdef __GNUC__
+__inline
+#endif
+#ifndef __SASC
+#ifdef WIN32
+static void *
+#else
+static char *
+#endif
+my_realloc (p, n)
+ char *p;
+ unsigned int n;
+{
+ /* These casts are the for sake of the broken Ultrix compiler,
+ which warns of illegal pointer combinations otherwise. */
+ if (p == NULL)
+ return (char *) malloc (n);
+ return (char *) realloc (p, n);
+}
+#define realloc my_realloc
+#endif /* __SASC */
+#endif /* __GNU_LIBRARY__ */
+
+
+#if !defined(__alloca) && !defined(__GNU_LIBRARY__)
+
+#ifdef __GNUC__
+#undef alloca
+#define alloca(n) __builtin_alloca (n)
+#else /* Not GCC. */
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#else /* Not HAVE_ALLOCA_H. */
+#ifndef _AIX
+#ifdef WIN32
+#include <malloc.h>
+#else
+extern char *alloca ();
+#endif /* WIN32 */
+#endif /* Not _AIX. */
+#endif /* sparc or HAVE_ALLOCA_H. */
+#endif /* GCC. */
+
+#define __alloca alloca
+
+#endif
+
+#ifndef __GNU_LIBRARY__
+#define __stat stat
+#ifdef STAT_MACROS_BROKEN
+#undef S_ISDIR
+#endif
+#ifndef S_ISDIR
+#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
+#endif
+#endif
+
+#ifndef STDC_HEADERS
+#undef size_t
+#define size_t unsigned int
+#endif
+
+/* Some system header files erroneously define these.
+ We want our own definitions from <fnmatch.h> to take precedence. */
+#undef FNM_PATHNAME
+#undef FNM_NOESCAPE
+#undef FNM_PERIOD
+#include <fnmatch.h>
+
+/* Some system header files erroneously define these.
+ We want our own definitions from <glob.h> to take precedence. */
+#undef GLOB_ERR
+#undef GLOB_MARK
+#undef GLOB_NOSORT
+#undef GLOB_DOOFFS
+#undef GLOB_NOCHECK
+#undef GLOB_APPEND
+#undef GLOB_NOESCAPE
+#undef GLOB_PERIOD
+#include <glob.h>
+
+static int glob_pattern_p __P ((const char *pattern, int quote));
+static int glob_in_dir __P ((const char *pattern, const char *directory,
+ int flags,
+ int (*errfunc) __P ((const char *, int)),
+ glob_t *pglob));
+static int prefix_array __P ((const char *prefix, char **array, size_t n));
+static int collated_compare __P ((const __ptr_t, const __ptr_t));
+
+/* Do glob searching for PATTERN, placing results in PGLOB.
+ The bits defined above may be set in FLAGS.
+ If a directory cannot be opened or read and ERRFUNC is not nil,
+ it is called with the pathname that caused the error, and the
+ `errno' value from the failing call; if it returns non-zero
+ `glob' returns GLOB_ABEND; if it returns zero, the error is ignored.
+ If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
+ Otherwise, `glob' returns zero. */
+int
+glob (pattern, flags, errfunc, pglob)
+ const char *pattern;
+ int flags;
+ int (*errfunc) __P ((const char *, int));
+ glob_t *pglob;
+{
+ const char *filename;
+ char *dirname;
+ size_t dirlen;
+ int status;
+ int oldcount;
+
+ if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (flags & GLOB_BRACE)
+ {
+ const char *begin = strchr (pattern, '{');
+ if (begin != NULL)
+ {
+ int firstc;
+ size_t restlen;
+ const char *p, *end, *next;
+ unsigned int depth = 0;
+
+ /* Find the end of the brace expression, by counting braces.
+ While we're at it, notice the first comma at top brace level. */
+ end = begin + 1;
+ next = NULL;
+ while (1)
+ {
+ switch (*end++)
+ {
+ case ',':
+ if (depth == 0 && next == NULL)
+ next = end;
+ continue;
+ case '{':
+ ++depth;
+ continue;
+ case '}':
+ if (depth-- == 0)
+ break;
+ continue;
+ case '\0':
+ return glob (pattern, flags &~ GLOB_BRACE, errfunc, pglob);
+ }
+ break;
+ }
+ restlen = strlen (end) + 1;
+ if (next == NULL)
+ next = end;
+
+ /* We have a brace expression. BEGIN points to the opening {,
+ NEXT points past the terminator of the first element, and END
+ points past the final }. We will accumulate result names from
+ recursive runs for each brace alternative in the buffer using
+ GLOB_APPEND. */
+
+ if (!(flags & GLOB_APPEND))
+ {
+ /* This call is to set a new vector, so clear out the
+ vector so we can append to it. */
+ pglob->gl_pathc = 0;
+ pglob->gl_pathv = NULL;
+ }
+ firstc = pglob->gl_pathc;
+
+ /* In this loop P points to the beginning of the current element
+ and NEXT points past its terminator. */
+ p = begin + 1;
+ while (1)
+ {
+ /* Construct a whole name that is one of the brace
+ alternatives in a temporary buffer. */
+ int result;
+ size_t bufsz = (begin - pattern) + (next - 1 - p) + restlen;
+#ifdef __GNUC__
+ char onealt[bufsz];
+#else
+ char *onealt = malloc (bufsz);
+ if (onealt == NULL)
+ {
+ if (!(flags & GLOB_APPEND))
+ globfree (pglob);
+ return GLOB_NOSPACE;
+ }
+#endif
+ memcpy (onealt, pattern, begin - pattern);
+ memcpy (&onealt[begin - pattern], p, next - 1 - p);
+ memcpy (&onealt[(begin - pattern) + (next - 1 - p)],
+ end, restlen);
+ result = glob (onealt,
+ ((flags & ~(GLOB_NOCHECK|GLOB_NOMAGIC)) |
+ GLOB_APPEND), errfunc, pglob);
+#ifndef __GNUC__
+ free (onealt);
+#endif
+
+ /* If we got an error, return it. */
+ if (result && result != GLOB_NOMATCH)
+ {
+ if (!(flags & GLOB_APPEND))
+ globfree (pglob);
+ return result;
+ }
+
+ /* Advance past this alternative and process the next. */
+ p = next;
+ depth = 0;
+ scan:
+ switch (*p++)
+ {
+ case ',':
+ if (depth == 0)
+ {
+ /* Found the next alternative. Loop to glob it. */
+ next = p;
+ continue;
+ }
+ goto scan;
+ case '{':
+ ++depth;
+ goto scan;
+ case '}':
+ if (depth-- == 0)
+ /* End of the brace expression. Break out of the loop. */
+ break;
+ goto scan;
+ }
+ }
+
+ if (pglob->gl_pathc == firstc &&
+ !(flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
+ return GLOB_NOMATCH;
+ }
+ }
+
+ /* Find the filename. */
+ filename = strrchr (pattern, '/');
+ if (filename == NULL)
+ {
+ filename = pattern;
+#ifdef _AMIGA
+ dirname = (char *) "";
+#else
+ dirname = (char *) ".";
+#endif
+ dirlen = 0;
+ }
+ else if (filename == pattern)
+ {
+ /* "/pattern". */
+ dirname = (char *) "/";
+ dirlen = 1;
+ ++filename;
+ }
+ else
+ {
+ dirlen = filename - pattern;
+ dirname = (char *) __alloca (dirlen + 1);
+ memcpy (dirname, pattern, dirlen);
+ dirname[dirlen] = '\0';
+ ++filename;
+ }
+
+ if (filename[0] == '\0' && dirlen > 1)
+ /* "pattern/". Expand "pattern", appending slashes. */
+ {
+ int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob);
+ if (val == 0)
+ pglob->gl_flags = (pglob->gl_flags & ~GLOB_MARK) | (flags & GLOB_MARK);
+ return val;
+ }
+
+ if (!(flags & GLOB_APPEND))
+ {
+ pglob->gl_pathc = 0;
+ pglob->gl_pathv = NULL;
+ }
+
+ oldcount = pglob->gl_pathc;
+
+#ifndef VMS
+ if ((flags & GLOB_TILDE) && dirname[0] == '~')
+ {
+ if (dirname[1] == '\0')
+ {
+ /* Look up home directory. */
+ dirname = getenv ("HOME");
+#ifdef _AMIGA
+ if (dirname == NULL || dirname[0] == '\0')
+ dirname = "SYS:";
+#else
+#ifdef WIN32
+ if (dirname == NULL || dirname[0] == '\0')
+ dirname = "c:/users/default"; /* poor default */
+#else
+ if (dirname == NULL || dirname[0] == '\0')
+ {
+ extern char *getlogin __P ((void));
+ char *name = getlogin ();
+ if (name != NULL)
+ {
+ struct passwd *p = getpwnam (name);
+ if (p != NULL)
+ dirname = p->pw_dir;
+ }
+ }
+ if (dirname == NULL || dirname[0] == '\0')
+ dirname = (char *) "~"; /* No luck. */
+#endif /* WIN32 */
+#endif
+ }
+ else
+ {
+#ifdef _AMIGA
+ if (dirname == NULL || dirname[0] == '\0')
+ dirname = "SYS:";
+#else
+#ifdef WIN32
+ if (dirname == NULL || dirname[0] == '\0')
+ dirname = "c:/users/default"; /* poor default */
+#else
+ /* Look up specific user's home directory. */
+ struct passwd *p = getpwnam (dirname + 1);
+ if (p != NULL)
+ dirname = p->pw_dir;
+#endif /* WIN32 */
+#endif
+ }
+ }
+#endif /* Not VMS. */
+
+ if (glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE)))
+ {
+ /* The directory name contains metacharacters, so we
+ have to glob for the directory, and then glob for
+ the pattern in each directory found. */
+ glob_t dirs;
+ register int i;
+
+ status = glob (dirname,
+ ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE)) |
+ GLOB_NOSORT),
+ errfunc, &dirs);
+ if (status != 0)
+ return status;
+
+ /* We have successfully globbed the preceding directory name.
+ For each name we found, call glob_in_dir on it and FILENAME,
+ appending the results to PGLOB. */
+ for (i = 0; i < dirs.gl_pathc; ++i)
+ {
+ int oldcount;
+
+#ifdef SHELL
+ {
+ /* Make globbing interruptible in the bash shell. */
+ extern int interrupt_state;
+
+ if (interrupt_state)
+ {
+ globfree (&dirs);
+ globfree (&files);
+ return GLOB_ABEND;
+ }
+ }
+#endif /* SHELL. */
+
+ oldcount = pglob->gl_pathc;
+ status = glob_in_dir (filename, dirs.gl_pathv[i],
+ (flags | GLOB_APPEND) & ~GLOB_NOCHECK,
+ errfunc, pglob);
+ if (status == GLOB_NOMATCH)
+ /* No matches in this directory. Try the next. */
+ continue;
+
+ if (status != 0)
+ {
+ globfree (&dirs);
+ globfree (pglob);
+ return status;
+ }
+
+ /* Stick the directory on the front of each name. */
+ if (prefix_array (dirs.gl_pathv[i],
+ &pglob->gl_pathv[oldcount],
+ pglob->gl_pathc - oldcount))
+ {
+ globfree (&dirs);
+ globfree (pglob);
+ return GLOB_NOSPACE;
+ }
+ }
+
+ flags |= GLOB_MAGCHAR;
+
+ if (pglob->gl_pathc == oldcount)
+ /* No matches. */
+ if (flags & GLOB_NOCHECK)
+ {
+ size_t len = strlen (pattern) + 1;
+ char *patcopy = (char *) malloc (len);
+ if (patcopy == NULL)
+ return GLOB_NOSPACE;
+ memcpy (patcopy, pattern, len);
+
+ pglob->gl_pathv
+ = (char **) realloc (pglob->gl_pathv,
+ (pglob->gl_pathc +
+ ((flags & GLOB_DOOFFS) ?
+ pglob->gl_offs : 0) +
+ 1 + 1) *
+ sizeof (char *));
+ if (pglob->gl_pathv == NULL)
+ {
+ free (patcopy);
+ return GLOB_NOSPACE;
+ }
+
+ if (flags & GLOB_DOOFFS)
+ while (pglob->gl_pathc < pglob->gl_offs)
+ pglob->gl_pathv[pglob->gl_pathc++] = NULL;
+
+ pglob->gl_pathv[pglob->gl_pathc++] = patcopy;
+ pglob->gl_pathv[pglob->gl_pathc] = NULL;
+ pglob->gl_flags = flags;
+ }
+ else
+ return GLOB_NOMATCH;
+ }
+ else
+ {
+ status = glob_in_dir (filename, dirname, flags, errfunc, pglob);
+ if (status != 0)
+ return status;
+
+ if (dirlen > 0)
+ {
+ /* Stick the directory on the front of each name. */
+ if (prefix_array (dirname,
+ &pglob->gl_pathv[oldcount],
+ pglob->gl_pathc - oldcount))
+ {
+ globfree (pglob);
+ return GLOB_NOSPACE;
+ }
+ }
+ }
+
+ if (flags & GLOB_MARK)
+ {
+ /* Append slashes to directory names. */
+ int i;
+ struct stat st;
+ for (i = oldcount; i < pglob->gl_pathc; ++i)
+ if (((flags & GLOB_ALTDIRFUNC) ?
+ (*pglob->gl_stat) (pglob->gl_pathv[i], &st) :
+ __stat (pglob->gl_pathv[i], &st)) == 0 &&
+ S_ISDIR (st.st_mode))
+ {
+ size_t len = strlen (pglob->gl_pathv[i]) + 2;
+ char *new = realloc (pglob->gl_pathv[i], len);
+ if (new == NULL)
+ {
+ globfree (pglob);
+ return GLOB_NOSPACE;
+ }
+ strcpy (&new[len - 2], "/");
+ pglob->gl_pathv[i] = new;
+ }
+ }
+
+ if (!(flags & GLOB_NOSORT))
+ /* Sort the vector. */
+ qsort ((__ptr_t) &pglob->gl_pathv[oldcount],
+ pglob->gl_pathc - oldcount,
+ sizeof (char *), collated_compare);
+
+ return 0;
+}
+
+
+/* Free storage allocated in PGLOB by a previous `glob' call. */
+void
+globfree (pglob)
+ register glob_t *pglob;
+{
+ if (pglob->gl_pathv != NULL)
+ {
+ register int i;
+ for (i = 0; i < pglob->gl_pathc; ++i)
+ if (pglob->gl_pathv[i] != NULL)
+ free ((__ptr_t) pglob->gl_pathv[i]);
+ free ((__ptr_t) pglob->gl_pathv);
+ }
+}
+
+
+/* Do a collated comparison of A and B. */
+static int
+collated_compare (a, b)
+ const __ptr_t a;
+ const __ptr_t b;
+{
+ const char *const s1 = *(const char *const * const) a;
+ const char *const s2 = *(const char *const * const) b;
+
+ if (s1 == s2)
+ return 0;
+ if (s1 == NULL)
+ return 1;
+ if (s2 == NULL)
+ return -1;
+ return strcoll (s1, s2);
+}
+
+
+/* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's
+ elements in place. Return nonzero if out of memory, zero if successful.
+ A slash is inserted between DIRNAME and each elt of ARRAY,
+ unless DIRNAME is just "/". Each old element of ARRAY is freed. */
+static int
+prefix_array (dirname, array, n)
+ const char *dirname;
+ char **array;
+ size_t n;
+{
+ register size_t i;
+ size_t dirlen = strlen (dirname);
+
+ if (dirlen == 1 && dirname[0] == '/')
+ /* DIRNAME is just "/", so normal prepending would get us "//foo".
+ We want "/foo" instead, so don't prepend any chars from DIRNAME. */
+ dirlen = 0;
+
+ for (i = 0; i < n; ++i)
+ {
+ size_t eltlen = strlen (array[i]) + 1;
+ char *new = (char *) malloc (dirlen + 1 + eltlen);
+ if (new == NULL)
+ {
+ while (i > 0)
+ free ((__ptr_t) array[--i]);
+ return 1;
+ }
+
+ memcpy (new, dirname, dirlen);
+ new[dirlen] = '/';
+ memcpy (&new[dirlen + 1], array[i], eltlen);
+ free ((__ptr_t) array[i]);
+ array[i] = new;
+ }
+
+ return 0;
+}
+
+
+/* Return nonzero if PATTERN contains any metacharacters.
+ Metacharacters can be quoted with backslashes if QUOTE is nonzero. */
+static int
+glob_pattern_p (pattern, quote)
+ const char *pattern;
+ int quote;
+{
+ register const char *p;
+ int open = 0;
+
+ for (p = pattern; *p != '\0'; ++p)
+ switch (*p)
+ {
+ case '?':
+ case '*':
+ return 1;
+
+ case '\\':
+ if (quote && p[1] != '\0')
+ ++p;
+ break;
+
+ case '[':
+ open = 1;
+ break;
+
+ case ']':
+ if (open)
+ return 1;
+ break;
+ }
+
+ return 0;
+}
+
+
+/* Like `glob', but PATTERN is a final pathname component,
+ and matches are searched for in DIRECTORY.
+ The GLOB_NOSORT bit in FLAGS is ignored. No sorting is ever done.
+ The GLOB_APPEND flag is assumed to be set (always appends). */
+static int
+glob_in_dir (pattern, directory, flags, errfunc, pglob)
+ const char *pattern;
+ const char *directory;
+ int flags;
+ int (*errfunc) __P ((const char *, int));
+ glob_t *pglob;
+{
+ __ptr_t stream;
+
+ struct globlink
+ {
+ struct globlink *next;
+ char *name;
+ };
+ struct globlink *names = NULL;
+ size_t nfound = 0;
+
+ if (!glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE)))
+ {
+ stream = NULL;
+ flags |= GLOB_NOCHECK;
+ }
+ else
+ {
+ flags |= GLOB_MAGCHAR;
+
+ stream = ((flags & GLOB_ALTDIRFUNC) ?
+ (*pglob->gl_opendir) (directory) :
+ (__ptr_t) opendir (directory));
+ if (stream == NULL)
+ {
+ if ((errfunc != NULL && (*errfunc) (directory, errno)) ||
+ (flags & GLOB_ERR))
+ return GLOB_ABEND;
+ }
+ else
+ while (1)
+ {
+ const char *name;
+ size_t len;
+ struct dirent *d = ((flags & GLOB_ALTDIRFUNC) ?
+ (*pglob->gl_readdir) (stream) :
+ readdir ((DIR *) stream));
+ if (d == NULL)
+ break;
+ if (! REAL_DIR_ENTRY (d))
+ continue;
+
+ name = d->d_name;
+
+ if (fnmatch (pattern, name,
+ (!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) |
+ ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
+#ifdef _AMIGA
+ | FNM_CASEFOLD
+#endif
+ ) == 0)
+ {
+ struct globlink *new
+ = (struct globlink *) __alloca (sizeof (struct globlink));
+ len = NAMLEN (d);
+ new->name
+ = (char *) malloc (len + 1);
+ if (new->name == NULL)
+ goto memory_error;
+ memcpy ((__ptr_t) new->name, name, len);
+ new->name[len] = '\0';
+ new->next = names;
+ names = new;
+ ++nfound;
+ }
+ }
+ }
+
+ if (nfound == 0 && (flags & GLOB_NOMAGIC) &&
+ ! glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE)))
+ flags |= GLOB_NOCHECK;
+
+ if (nfound == 0 && (flags & GLOB_NOCHECK))
+ {
+ size_t len = strlen (pattern);
+ nfound = 1;
+ names = (struct globlink *) __alloca (sizeof (struct globlink));
+ names->next = NULL;
+ names->name = (char *) malloc (len + 1);
+ if (names->name == NULL)
+ goto memory_error;
+ memcpy (names->name, pattern, len);
+ names->name[len] = '\0';
+ }
+
+ pglob->gl_pathv
+ = (char **) realloc (pglob->gl_pathv,
+ (pglob->gl_pathc +
+ ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) +
+ nfound + 1) *
+ sizeof (char *));
+ if (pglob->gl_pathv == NULL)
+ goto memory_error;
+
+ if (flags & GLOB_DOOFFS)
+ while (pglob->gl_pathc < pglob->gl_offs)
+ pglob->gl_pathv[pglob->gl_pathc++] = NULL;
+
+ for (; names != NULL; names = names->next)
+ pglob->gl_pathv[pglob->gl_pathc++] = names->name;
+ pglob->gl_pathv[pglob->gl_pathc] = NULL;
+
+ pglob->gl_flags = flags;
+
+ if (stream != NULL)
+ {
+ int save = errno;
+ if (flags & GLOB_ALTDIRFUNC)
+ (*pglob->gl_closedir) (stream);
+ else
+ closedir ((DIR *) stream);
+ errno = save;
+ }
+ return nfound == 0 ? GLOB_NOMATCH : 0;
+
+ memory_error:
+ {
+ int save = errno;
+ if (flags & GLOB_ALTDIRFUNC)
+ (*pglob->gl_closedir) (stream);
+ else
+ closedir ((DIR *) stream);
+ errno = save;
+ }
+ while (names != NULL)
+ {
+ if (names->name != NULL)
+ free ((__ptr_t) names->name);
+ names = names->next;
+ }
+ return GLOB_NOSPACE;
+}
+
+#endif /* Not ELIDE_CODE. */
+
diff --git a/Build/source/texk/contrib/glob/glob.h b/Build/source/texk/contrib/glob/glob.h
new file mode 100644
index 00000000000..571bd5e4053
--- /dev/null
+++ b/Build/source/texk/contrib/glob/glob.h
@@ -0,0 +1,108 @@
+/* Copyright (C) 1991, 1992, 1995, 1996 Free Software Foundation, Inc.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This 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 this library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#ifndef _GLOB_H
+
+#define _GLOB_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#undef __ptr_t
+#if (defined (__cplusplus) || (defined (__STDC__) && __STDC__) \
+ || defined (WIN32))
+#undef __P
+#define __P(protos) protos
+#define __ptr_t void *
+#else /* Not C++ or ANSI C. */
+#undef __P
+#define __P(protos) ()
+#undef const
+#define const
+#define __ptr_t char *
+#endif /* C++ or ANSI C. */
+
+/* Bits set in the FLAGS argument to `glob'. */
+#define GLOB_ERR (1 << 0)/* Return on read errors. */
+#define GLOB_MARK (1 << 1)/* Append a slash to each name. */
+#define GLOB_NOSORT (1 << 2)/* Don't sort the names. */
+#define GLOB_DOOFFS (1 << 3)/* Insert PGLOB->gl_offs NULLs. */
+#define GLOB_NOCHECK (1 << 4)/* If nothing matches, return the pattern. */
+#define GLOB_APPEND (1 << 5)/* Append to results of a previous call. */
+#define GLOB_NOESCAPE (1 << 6)/* Backslashes don't quote metacharacters. */
+#define GLOB_PERIOD (1 << 7)/* Leading `.' can be matched by metachars. */
+#define __GLOB_FLAGS (GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \
+ GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND| \
+ GLOB_PERIOD|GLOB_ALTDIRFUNC|GLOB_BRACE| \
+ GLOB_NOMAGIC|GLOB_TILDE)
+
+#if !defined (_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 2 || defined (_BSD_SOURCE)
+#define GLOB_MAGCHAR (1 << 8)/* Set in gl_flags if any metachars seen. */
+#define GLOB_ALTDIRFUNC (1 << 9)/* Use gl_opendir et al functions. */
+#define GLOB_BRACE (1 << 10)/* Expand "{a,b}" to "a" "b". */
+#define GLOB_NOMAGIC (1 << 11)/* If no magic chars, return the pattern. */
+#define GLOB_TILDE (1 <<12)/* Expand ~user and ~ to home directories. */
+#endif
+
+/* Error returns from `glob'. */
+#define GLOB_NOSPACE 1 /* Ran out of memory. */
+#define GLOB_ABEND 2 /* Read error. */
+#define GLOB_NOMATCH 3 /* No matches found. */
+
+/* Structure describing a globbing run. */
+#if !defined (_AMIGA) && !defined (VMS) /* Buggy compiler. */
+struct stat;
+#endif
+typedef struct
+ {
+ int gl_pathc; /* Count of paths matched by the pattern. */
+ char **gl_pathv; /* List of matched pathnames. */
+ int gl_offs; /* Slots to reserve in `gl_pathv'. */
+ int gl_flags; /* Set to FLAGS, maybe | GLOB_MAGCHAR. */
+
+ /* If the GLOB_ALTDIRFUNC flag is set, the following functions
+ are used instead of the normal file access functions. */
+ void (*gl_closedir) __P ((void *));
+ struct dirent *(*gl_readdir) __P ((void *));
+ __ptr_t (*gl_opendir) __P ((const char *));
+ int (*gl_lstat) __P ((const char *, struct stat *));
+ int (*gl_stat) __P ((const char *, struct stat *));
+ } glob_t;
+
+/* Do glob searching for PATTERN, placing results in PGLOB.
+ The bits defined above may be set in FLAGS.
+ If a directory cannot be opened or read and ERRFUNC is not nil,
+ it is called with the pathname that caused the error, and the
+ `errno' value from the failing call; if it returns non-zero
+ `glob' returns GLOB_ABEND; if it returns zero, the error is ignored.
+ If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
+ Otherwise, `glob' returns zero. */
+extern int glob __P ((const char *__pattern, int __flags,
+ int (*__errfunc) __P ((const char *, int)),
+ glob_t *__pglob));
+
+/* Free storage allocated in PGLOB by a previous `glob' call. */
+extern void globfree __P ((glob_t *__pglob));
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* glob.h */
diff --git a/Build/source/texk/contrib/irun.c b/Build/source/texk/contrib/irun.c
new file mode 100644
index 00000000000..48eac01d9bb
--- /dev/null
+++ b/Build/source/texk/contrib/irun.c
@@ -0,0 +1,569 @@
+/* link.c
+
+Copyright (C) 1997 - 2003
+Fabrice Popineau <Fabrice.Popineau@supelec.fr>
+
+This file is part of Web2c for Win32.
+
+Web2c For Win32 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.
+
+Web2c For Win32 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 Web2c For Win32; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+USA. */
+
+/*
+ the goal of this file is to mimic Unix's ln command. This is a quick
+ hack, in that it will only allow to remap to predefined .exe files.
+*/
+
+#include <kpathsea/config.h>
+#include <kpathsea/lib.h>
+#include <kpathsea/proginit.h>
+#include <kpathsea/progname.h>
+#include <kpathsea/tex-file.h>
+
+#define IS_DIRSEP(c) ((c) == '/' || (c) == '\\')
+
+/* To be determined by 'dumpbin /symbols irun.exe'
+ web2c/Makefile automagically determines this value by making two passes
+ when compiling irun.exe
+*/
+
+typedef void (* PFN_kpse_set_program_name)(const_string, const_string);
+typedef void (* PFN_kpse_init_prog)(const_string, unsigned, const_string, const_string);
+typedef string (* PFN_kpse_find_file)(const_string, kpse_file_format_type, boolean);
+
+#ifndef RDATA
+#include "irun.h"
+#endif
+
+#pragma section("FOOBAR", read)
+
+#define marker "foobar"
+
+#undef DEBUG
+
+/* Initialized with marker string */
+ __declspec(allocate("FOOBAR")) const char newargv0[MAX_PATH] = marker;
+
+/*
+ This programme should emulate Unix's ln for .exe files under Win32.
+
+ Usage: irun <src> <dest>
+
+ Method used: this .exe file is located, copied to the destination
+ using the new name for the destination, while changing the newargv0
+ constant to the src file name.
+
+ Caveat: to be portable, the src file name should not be absolute.
+ It should be either a pathname relative to the current executable file,
+ either a simple name which may be looked for along the PATH, or only
+ in the same directory as the current executable file.
+
+ Adopted strategy: relative pathes are ok, absolute one will give a
+ warning when doing the link.
+
+*/
+
+#define DIR_SEP '/'
+#define DIR_SEP_STRING "/"
+#define IS_DEVICE_SEP(ch) ((ch) == ':')
+#define NAME_BEGINS_WITH_DEVICE(name) (*(name) && IS_DEVICE_SEP((name)[1]))
+/* On DOS, it's good to allow both \ and / between directories. */
+#define IS_DIR_SEP(ch) ((ch) == '/' || (ch) == '\\')
+/* On win32, UNC names are authorized */
+#define IS_UNC_NAME(name) (strlen(name)>=3 && IS_DIR_SEP(*name) \
+ && IS_DIR_SEP(*(name+1)) && isalnum(*(name+2)))
+
+char cmdline[MAX_PATH];
+char autoloc[MAX_PATH];
+char *progname;
+
+BOOL WINAPI catch_interrupt(DWORD arg)
+{
+ switch (arg) {
+ case CTRL_C_EVENT:
+ case CTRL_BREAK_EVENT:
+ return TRUE;
+ default:
+ /* No need to set interrupt as we are exiting anyway */
+ return FALSE;
+ }
+}
+
+#if 0
+static BOOL
+is_absolute(const char *filename)
+{
+ BOOL absolute = IS_DIR_SEP (*filename)
+ /* Novell allows non-alphanumeric drive letters. */
+ || (*filename && IS_DEVICE_SEP (filename[1]))
+ /* UNC names */
+ || IS_UNC_NAME(filename)
+ ;
+ BOOL explicit_relative = (*filename == '.' && (IS_DIR_SEP (filename[1])
+ || (filename[1] == '.' && IS_DIR_SEP (filename[2]))));
+ /* FIXME: On UNIX an IS_DIR_SEP of any but the last character in the name
+ implies relative. */
+ return absolute || explicit_relative;
+}
+#else
+is_absolute(const char *path)
+{
+ return IS_DIRSEP(*path)
+ || ( isalpha(*path) && *(path+1) == ':' && IS_DIRSEP(*path) );
+}
+#endif
+
+is_relative(const char *path)
+{
+ return (*path == '.' &&
+ (IS_DIRSEP(*(path+1))
+ || (*(path+1) == '.' && IS_DIRSEP(*(path+2)))));
+}
+
+char *look_for_target(char *name, char *cmdline)
+{
+ char name_drive[_MAX_DRIVE], name_dir[_MAX_DIR], name_fname[_MAX_FNAME], name_ext[_MAX_EXT];
+ char *cmd = NULL, *script = NULL, *exepath;
+ char *cmdarg = NULL;
+
+ _splitpath(name, 0, 0, name_fname, name_ext);
+#ifdef DEBUG
+ fprintf(stderr, "name = %s\n", name);
+#endif
+ if (_stricmp(name_ext, ".exe") == 0) {
+ if (is_relative(name)) {
+ /* In this case, catenate the directory of the invoked program
+ with the relative name stored in the link */
+ char *unquoted_cmd;
+ _splitpath(_pgmptr, name_drive, name_dir, 0, 0);
+ unquoted_cmd = concatn(name_drive, name_dir, name, NULL);
+ cmd = quote_filename(unquoted_cmd);
+ free(unquoted_cmd);
+ /* Do not forget to se the new name to the result, used below */
+ name = xdirsimplify(cmd);
+ }
+ else {
+ cmd = name;
+ }
+ }
+ else {
+ if (_stricmp(name_ext, ".pl") == 0) {
+ cmd = "perl.exe";
+ }
+ else if (_stricmp(name_ext, ".py") == 0) {
+ cmd = "python.exe";
+ }
+ else if (_stricmp(name_ext, ".rb") == 0) {
+ cmd = "ruby.exe";
+ }
+ else if (_stricmp(name_ext, ".java") == 0) {
+ cmd = "java.exe";
+ }
+ else if (_stricmp(name_ext, ".jar") == 0) {
+ cmd = "java.exe";
+ cmdarg = " -cp ";
+ }
+ else {
+ fprintf (stderr, "Unknown file type: %s%s\n", name_fname, name_ext);
+ return NULL;
+ }
+ }
+
+ if (look_for_cmd(cmd, &exepath) == FALSE) {
+ fprintf (stderr, "File not found: %s\n", cmd);
+ return NULL;
+ }
+
+ {
+ char *quoted_exepath = quote_filename(exepath);
+ strcpy(cmdline, quoted_exepath);
+#ifdef DEBUG
+ fprintf(stderr, "quoted_exepath = %s\n", quoted_exepath);
+#endif
+ free(exepath);
+ free(quoted_exepath);
+ }
+
+ if (cmd != name) {
+ /* This is a script, need to find it */
+ if (is_absolute(name)) {
+ script = name;
+ }
+ else {
+ /* Let's try kpathsea if available ! */
+ HMODULE hKPSEDll = 0;
+ PFN_kpse_set_program_name pkpsedll_set_program_name = NULL;
+ PFN_kpse_init_prog pkpsedll_init_prog = NULL;
+ PFN_kpse_find_file pkpsedll_find_file = NULL;
+ char *progname = xstrdup(cmd);
+ unsigned int dpi = 600;
+ char *p = strrchr(progname, '.');
+ if (p) *p = '\0';
+#ifdef DEBUG
+ fprintf(stderr, "progname = %s\n", progname);
+#endif
+ if ((hKPSEDll = LoadLibrary(KPATHSEA_DLL)) != NULL) {
+
+ pkpsedll_set_program_name = (PFN_kpse_set_program_name)GetProcAddress(hKPSEDll, "@kpse_set_program_name@8");
+ pkpsedll_init_prog = (PFN_kpse_init_prog)GetProcAddress(hKPSEDll, "@kpse_init_prog@16");
+ pkpsedll_find_file = (PFN_kpse_find_file)GetProcAddress(hKPSEDll, "@kpse_find_file@12");
+ if (pkpsedll_set_program_name && pkpsedll_init_prog && pkpsedll_find_file) {
+ (*pkpsedll_set_program_name)("irun", progname);
+ (*pkpsedll_init_prog)(uppercasify (kpse_program_name), dpi, NULL, NULL);
+ script = (*pkpsedll_find_file)(name, kpse_texmfscripts_format, TRUE);
+ }
+ FreeLibrary(hKPSEDll);
+ }
+ if (! script) {
+ fprintf(stderr, "irun: no %s script\nof name %s can be found.\nAborting.\n",
+ cmd, name);
+ *cmdline = '\0';
+ }
+ free(progname);
+ }
+ }
+
+ if (script) {
+ char *quoted_script = quote_filename(script);
+ if (cmdarg)
+ strcat(cmdline, cmdarg);
+ else
+ strcat(cmdline, " ");
+ strcat(cmdline, quoted_script);
+ strcat(cmdline, " ");
+ free (quoted_script);
+ free (script);
+ }
+
+#ifdef DEBUG
+ fprintf(stderr, "cmdline = %s\n", cmdline);
+#endif
+ return cmdline;
+}
+
+int link(char *src, char *dest, int force, int verbose, char *args[], int argc)
+{
+ int fdest;
+ int cmdlen;
+
+#ifdef DEBUG
+ if (1)
+#else
+ if (verbose)
+#endif
+ fprintf(stdout, "Linking %s to %s.\n", src, dest);
+
+ if (is_absolute(src))
+ fprintf(stderr, "Warning: source file %s is absolute!\n", src);
+
+ /* Looking for the source. */
+ if (SearchPath(NULL, "irun", ".exe", MAX_PATH, autoloc,
+ NULL) == 0) {
+ fprintf(stderr, "irun: can't find the program.\n");
+ exit(1);
+ }
+
+#ifdef DEBUG
+ fprintf(stderr, "Autoloc = %s\n", autoloc);
+#endif
+
+ if (CopyFile(autoloc, dest, !force) == 0) {
+ fprintf(stderr, "Can't copy to %s (file may already exist).\n",
+ dest);
+ exit(1);
+ }
+
+ /* Don't look for target now: it will be looked for at run time */
+ strcpy(cmdline, src);
+ cmdlen = strlen(cmdline);
+
+ /* if there are arguments left on the command line, catenate them */
+ while (argc--) {
+ strcpy(cmdline+cmdlen+1, *args);
+ cmdlen += strlen(*args) + 1;
+#ifdef DEBUG
+ fprintf(stderr, "argc = %d, cmdlen = %d, args = %s\n", argc, cmdlen, *args);
+#endif
+ args++;
+ }
+ cmdline[cmdlen+1] = '\0';
+
+#ifdef DEBUG
+ fprintf(stderr, "Cmdline = %s\n", cmdline);
+#endif
+
+ /* Now we need to put cmdline into the newargv0 variable in dest
+ file.
+ We could use the PE file format specfication to locate the .rdata
+ section , but is it actually needed :-)
+ In fact, we need to find the marker string "foobarbaz" and store
+ the name here.
+ */
+ /* Open the file */
+ if ((fdest = _open(dest, _O_RDWR | _O_BINARY)) == 0) {
+ perror("Can't open target file");
+ exit(1);
+ }
+ /* Look for the marker string */
+ if (_lseek(fdest, RDATA, SEEK_SET) < 0) {
+ perror("Can't seek to .rdata");
+ exit(1);
+ }
+
+ if (_read(fdest, autoloc, MAX_PATH) < 0) {
+ perror("Can't read into dest file");
+ exit(1);
+ }
+ if (strcmp(autoloc, newargv0) != 0) {
+ fprintf(stderr, "irun: marker string not found in %s.\n", dest);
+ exit(1);
+ }
+
+ if (_lseek(fdest, RDATA, SEEK_SET) < 0) {
+ perror("Can't seek (2) to .rdata");
+ exit(1);
+ }
+
+ if (_write(fdest, cmdline, cmdlen+1) < 1) {
+ perror("Can't write into dest file");
+ exit(1);
+ }
+
+ /* Close the file */
+ _close(fdest);
+
+ return 0;
+}
+
+char *usage_msg =
+ "Usage: %s [-f] [-v] <src> <dest>\nwill link <src> to <dest>\n"
+ "Option -f will force the link, -v is verbose.\n"
+ " If src is absolute, a warning is emitted because the hard link\n"
+ " is not portable.\n"
+ " If src is a relative path, it is relative to the dest path.\n"
+ " If src has one of the .java, .jar, .pl, .py or .rb extension,\n"
+ " it is assumed to be a script, and the executable linked to is\n"
+ " java.exe (for .java and .jar), perl.exe, python.exe and ruby.exe.\n"
+ " Those programs must be in accessible through your PATH.\n"
+ " If the script is not found, kpathsea is used to locate it through\n"
+ " the $JAVAINPUTS, $PERLINPUTS, $PYTHONINPUTS and $RUBYINPUTS variables.\n";
+
+void usage()
+{
+ fprintf(stderr, usage_msg, progname);
+ exit(1);
+}
+
+int
+main (int argc, char *argv[])
+
+{
+ int rc;
+ size_t j = 0;
+ int force = 0, verbose = 0;
+
+ for (progname = argv[0] + strlen(argv[0]) -1;
+ progname > argv[0] && *(progname-1) != '/' && *(progname-1) != '\\';
+ progname--);
+#ifdef DEBUG
+ fprintf(stderr, "progname = %s\n", progname);
+#endif
+
+#ifdef DEBUG
+ fprintf(stderr, "argc = %d, argv[0] = %s\n", argc, argv[0]);
+#endif
+
+ if (strcasecmp(progname, "irun.exe") == 0
+ || strcasecmp(progname, "irun") == 0) {
+ /* Doing the link */
+
+ if (argc == 1)
+ usage();
+
+ /* First, parse arguments */
+ while (--argc > 0 && *(++argv)[0] == '-') {
+#ifdef DEBUG
+ fprintf(stderr, "arg: %s\n", argv[0]);
+#endif
+ switch (*(argv[0]+1) == '-' ? *(argv[0]+2) : *(argv[0]+1)) {
+ case 'f':
+ force = 1;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case 'h':
+ usage();
+ exit(0);
+ }
+ }
+
+ if (argc < 2)
+ usage();
+
+ link(argv[0], argv[1], force, verbose, argv+2, argc - 2);
+ }
+ else {
+ /* Calling the target program. Unfortunately, exec does not seem
+ to work under NT as expected. */
+
+ char *newargv[256];
+ boolean quoted = false;
+ char *p, *q, *newcmd, *new_line, *new_argv_i;
+ int i, newargc = 0;
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+
+ SetConsoleCtrlHandler(catch_interrupt, TRUE);
+
+ /* Looking for the target. */
+ /* Either it is an executable or a (Perl|Python|Ruby|Java) script */
+ /* If it is a script and kpathsea is available, then it should be
+ searched for */
+ if (look_for_target(newargv0, autoloc) == NULL) {
+ fprintf(stderr, "%s: can't find the target %s.\n",
+ progname, newargv0);
+ exit(1);
+ }
+
+ p = q = autoloc;
+#ifdef DEBUG
+ fprintf(stderr, "autoloc = %s\n", autoloc);
+#endif
+ /* Fix up in the case of a script */
+ do {
+ if (*p == '"') {
+ quoted = !quoted;
+ p++;
+ }
+
+ if (*p == ' ' && !quoted) {
+ *p = '\0';
+ newargv[newargc++] = unquote_filename(q);
+ q = ++p;
+ }
+ else if (*p == '\0') {
+ newargv[newargc++] = unquote_filename(q);
+ break;
+ }
+ else {
+ p++;
+ }
+ } while (1);
+#ifdef DEBUG
+ fprintf(stderr, "stage1\n");
+ for (i = 0; i < newargc; i++) {
+ fprintf(stderr, "newargv[%d] = %s\n", i, newargv[i]);
+ }
+#endif
+
+ /* Add any argument */
+ p = newargv0 + strlen(newargv0) + 1;
+ while (*p) {
+ newargv[newargc++] = p;
+ p += strlen(p) + 1;
+ }
+#ifdef DEBUG
+ fprintf(stderr, "stage2\n");
+ for (i = 0; i < newargc; i++) {
+ fprintf(stderr, "newargv[%d] = %s\n", i, newargv[i]);
+ }
+#endif
+
+ if (*p) {
+ newargv[newargc++] = unquote_filename(p);
+ }
+#ifdef DEBUG
+ fprintf(stderr, "stage3\n");
+ for (i = 0; i < newargc; i++) {
+ fprintf(stderr, "newargv[%d] = %s\n", i, newargv[i]);
+ }
+#endif
+
+ for (i = 1; i < argc; i++) {
+ newargv[newargc++] = argv[i];
+ }
+ newargv[newargc] = NULL;
+#ifdef DEBUG
+ fprintf(stderr, "stage4\n");
+ for (i = 0; i < newargc; i++) {
+ fprintf(stderr, "newargv[%d] = %s\n", i, newargv[i]);
+ }
+#endif
+
+#if 1
+ newcmd = quote_filename(_pgmptr);
+ for (i = 1; newargv[i]; i++) {
+ new_argv_i = quote_filename(newargv[i]);
+ new_line = concat3(newcmd, " ", new_argv_i);
+ free(newcmd);
+ free(new_argv_i);
+ newcmd = new_line;
+ }
+
+ ZeroMemory( &si, sizeof(STARTUPINFO) );
+ si.cb = sizeof(STARTUPINFO);
+ si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW ;
+ si.wShowWindow = 0 ;
+ si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
+ si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
+ si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+
+#ifdef DEBUG
+ fprintf(stderr, "argv0 = %s, newargv0 = %s\n", _pgmptr, newargv[0]);
+#endif
+ /* creating child process */
+ if (CreateProcess(newargv[0], /* pointer to name of executable module */
+ newcmd, /* pointer to command line string */
+ NULL, /* pointer to process security attributes */
+ NULL, /* pointer to thread security attributes */
+ TRUE, /* handle inheritance flag */
+ 0, /* creation flags */
+ NULL, /* pointer to environment */
+ NULL, /* pointer to current directory */
+ &si, /* pointer to STARTUPINFO */
+ &pi /* pointer to PROCESS_INFORMATION */
+ ) == FALSE) {
+ fprintf(stderr, "irun: CreateProcess %x\n", GetLastError());
+ return NULL;
+ }
+
+ /* Only the process handle is needed, ignore errors */
+ CloseHandle(pi.hThread);
+
+ /* Waiting for the process to terminate */
+ if (WaitForSingleObject(pi.hProcess, INFINITE) != WAIT_OBJECT_0) {
+ fprintf(stderr, "irun: error, process still active\n");
+ rc = -1;
+ }
+
+ /* retrieving the exit code */
+ if (GetExitCodeProcess(pi.hProcess, &rc) == 0) {
+ fprintf(stderr, "irun: can't get process exit code\n");
+ rc = -1;
+ }
+#else
+
+ rc = _spawnvp (_P_WAIT, newargv[0], newargv);
+#endif
+ if (rc < 0) {
+ perror (cmdline);
+ return (1);
+ }
+ return (rc);
+ }
+ return 0;
+}
+
+/* link.c ends here */
diff --git a/Build/source/texk/contrib/irun.h b/Build/source/texk/contrib/irun.h
new file mode 100644
index 00000000000..fa0a72e0ec0
--- /dev/null
+++ b/Build/source/texk/contrib/irun.h
@@ -0,0 +1 @@
+#define RDATA 0x2000
diff --git a/Build/source/texk/contrib/irun.rc b/Build/source/texk/contrib/irun.rc
new file mode 100644
index 00000000000..2c005745d38
--- /dev/null
+++ b/Build/source/texk/contrib/irun.rc
@@ -0,0 +1,34 @@
+/* irun.rc: irun resources -*- C++ -*-
+
+ Copyright (C) 1996-2003 Fabrice Popineau <fabrice.popineau@supelec.fr>
+
+ This file 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 file 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 file; if not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+#include <texlive-version.h>
+
+#define VER_FILEVERSION TEXLIVE_MAJOR_VERSION,TEXLIVE_MINOR_VERSION,TEXLIVE_BETA_NUMBER,TEXLIVE_ALPHA_NUMBER
+#define VER_FILEVERSION_STR TEXLIVE_PRODUCTVERSION_STR " irun 1.0"
+
+#define VER_INTERNALNAME_STR "irun"
+#define VER_ORIGINALFILENAME_STR "irun.exe"
+
+#define VER_FILEDESCRIPTION_STR "Emulate Unix's ln -s for .exe|.pl|.py|.rb files"
+
+#define VER_LEGALCOPYRIGHT_STR " Copyright (c) 1997-2003 by Fabrice Popineau."
+
+#include <texlive.version>
+
+/* irun.rc ends here */
diff --git a/Build/source/texk/contrib/libmktex.rc b/Build/source/texk/contrib/libmktex.rc
new file mode 100644
index 00000000000..0724ec5ccd8
--- /dev/null
+++ b/Build/source/texk/contrib/libmktex.rc
@@ -0,0 +1,36 @@
+/* libmktex.rc: libmktex resources -*- C++ -*-
+
+ Copyright (C) 1996-2003 Fabrice Popineau <fabrice.popineau@supelec.fr>
+
+ This file 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 file 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 file; if not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+#include <texlive-version.h>
+
+#define VER_FILEVERSION TEXLIVE_MAJOR_VERSION,TEXLIVE_MINOR_VERSION,TEXLIVE_BETA_NUMBER,TEXLIVE_ALPHA_NUMBER
+#define VER_FILEVERSION_STR TEXLIVE_PRODUCTVERSION_STR " mktex library 2.0"
+
+#define VER_INTERNALNAME_STR TEXLIVE_LIBRARYPREFIX_STR "mktx"
+#define VER_ORIGINALFILENAME_STR TEXLIVE_LIBRARYPREFIX_STR "mktx.dll"
+
+#define VER_FILEDESCRIPTION_STR "MkTeX all-purpose build TeX files"
+
+#define VER_LEGALCOPYRIGHT_STR "(C) 1997-2003 Fabrice Popineau & Eli Zaretskii\0"
+
+#define VER_FILETYPE VFT_DLL
+
+#include <texlive.version>
+
+/* libmktex.rc ends here */
diff --git a/Build/source/texk/contrib/main.c b/Build/source/texk/contrib/main.c
new file mode 100644
index 00000000000..650c9cc682b
--- /dev/null
+++ b/Build/source/texk/contrib/main.c
@@ -0,0 +1,91 @@
+
+#include "mktex.h"
+#include "stackenv.h"
+#include "variables.h"
+#include "fileutils.h"
+
+void __cdecl output_and_cleanup(int code)
+{
+ FILE *f;
+ string line;
+
+ if (code == 0) {
+ /* output result if any */
+ if ((f = fopen(getval("STDOUT"), "r")) != NULL) {
+ if (redirect_stdout >= 0) {
+ int fds[3];
+
+ fds[0] = 0;
+ fds[1] = redirect_stdout;
+ fds[2] = 2;
+ push_fd(fds);
+ }
+ while((line = read_line(f)) != NULL) {
+ fputs(line, stdout);
+ free (line);
+ }
+ fclose(f);
+ if (redirect_stdout >= 0) {
+ pop_fd();
+ redirect_stdout = -1;
+ }
+ }
+ }
+
+ if (test_file('d', tmpdir))
+ rec_rmdir(tmpdir);
+
+ {
+ int count = 0;
+ /* Give more than one chance to remove the files */
+ while ((count++ < 20) && test_file('d', tmpdir)) {
+ Sleep(250);
+ rec_rmdir(tmpdir);
+ }
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ program_description * program = 0;
+ int i, errstatus;
+#if defined(WIN32)
+ /* if _DEBUG is not defined, these macros will result in nothing. */
+ SETUP_CRTDBG;
+ /* Set the debug-heap flag so that freed blocks are kept on the
+ linked list, to catch any inadvertent use of freed memory */
+ SET_CRT_DEBUG_FIELD( _CRTDBG_DELAY_FREE_MEM_DF );
+#endif
+
+ redirect_stdout = -1;
+ output_and_cleanup_function = output_and_cleanup;
+
+#if 0
+ extern MKTEXDLL string (* var_lookup)(const_string);
+ var_lookup = getval;
+#endif
+
+ mktexinit(argc, argv);
+
+ for(i = 0; makedesc[i].name; ++i) {
+ if (FILESTRCASEEQ(kpse_program_name, makedesc[i].name)) {
+ program_number = i;
+ progname = makedesc[i].name;
+ program = makedesc+i;
+ break;
+ }
+ }
+ if (!makedesc[i].name) {
+ fprintf(stderr, "This program was incorrectly copied to the name %s\n",
+ argv[0]);
+ return 1;
+ }
+
+ /* mktex_opt may modify argc and shift argv */
+ argc = mktex_opt(argc, argv, program);
+
+ errstatus = program->prog(argc, argv);
+
+ mt_exit(errstatus);
+ return 0; /* Not reached !!! */
+}
diff --git a/Build/source/texk/contrib/makempx.c b/Build/source/texk/contrib/makempx.c
new file mode 100644
index 00000000000..d6c2fda5dfb
--- /dev/null
+++ b/Build/source/texk/contrib/makempx.c
@@ -0,0 +1,630 @@
+/* makempx.c: this program emulates the makempx shell script from Metapost.
+
+Copyright (C) 1997 Fabrice POPINEAU.
+
+Adapted to DJGPP by Eli Zaretskii.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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 this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* #!/bin/sh */
+/* # '$Id: makempx.c,v 1.10 2002/10/06 14:03:14 olaf Exp $' */
+/* # Make an MPX file from the labels in a MetaPost source file, */
+/* # using mpto and either dvitomp (TeX) or dmp (troff). */
+/* # From John Hobby's original (though there's not much of it left by now). */
+/* # Public domain. */
+
+/* rcs_revision='$Revision: 1.10 $' */
+/* version=`set - $rcs_revision; echo $2` */
+
+/* : ${DMP=dmp} */
+/* : ${DVITOMP=dvitomp} */
+/* : ${MAKEMPX_BINDIR="j:\\TeX\\bin"} */
+/* : ${MPTEXPRE=mptexpre.tex} */
+/* : ${MPTOTEX="mpto -tex"} */
+/* : ${MPTOTR="mpto -troff"} */
+/* : ${NEWER=newer} */
+/* : ${TEX=tex} */
+/* : ${TROFF='eqn -d\$\$ | troff -Tpost'} */
+
+/* PATH=$MAKEMPX_BINDIR:/bin:/usr/bin:$PATH */
+
+/* # These names are documented in the MetaPost manual, so it's */
+/* # unwise to change them. */
+/* ERRLOG=mpxerr.log # file for an error log if necessary */
+/* TEXERR=mpxerr.tex # file for erroneous TeX if any */
+/* DVIERR=mpxerr.dvi # troublesome dvi file if any */
+/* TROFF_INERR=mpxerr # file for erroneous troff input, if any */
+/* TROFF_OUTERR=mpxerr.t # file for troublesome troff output, if any */
+
+
+/* usage="Usage: $0 [-tex|-troff] MPFILE MPXFILE. */
+/* If MPXFILE is older than MPFILE, translate the labels from the MetaPost */
+/* input file MPFIle to low-level commands in MPXFILE, by running */
+/* $MPTOTEX, $TEX, and $DVITOMP */
+/* by default; or, if -troff is specified, */
+/* $MPTOTR, $TROFF, and $DMP. */
+
+/* The current directory is used for writing temporary files. Errors are */
+/* left in mpxerr.{tex,log,dvi}. */
+
+/* If the file named in \$MPTEXPRE (mptexpre.tex by default) exists, it is */
+/* prepended to the output in tex mode. */
+
+/* Email bug reports to tex-k@mail.tug.org." */
+
+
+/* mode=tex */
+
+/* while test $# -gt 0; do */
+/* case "$1" in */
+/* -help|--help) */
+/* echo "$usage"; exit 0;; */
+/* -version|--version) */
+/* echo "`basename $0` (Web2c 6.98) $version" */
+/* echo "There is NO warranty. This script is public domain. */
+/* Primary author: John Hobby; Web2c maintainer: K. Berry." */
+/* exit 0;; */
+/* -troff|--troff) mode=troff;; */
+/* -tex|--tex) mode=tex;; */
+/* -*) */
+/* echo "$0: Invalid option: $1." >&2 */
+/* echo "Try \``basename $0` --help' for more information." >&2 */
+/* exit 1;; */
+/* *) */
+/* if test -z "$MPFILE"; then */
+/* MPFILE=$1 # input file */
+/* elif test -z "$MPXFILE"; then */
+/* MPXFILE=$1 # output file */
+/* else */
+/* echo "$0: Extra argument $1." >&2 */
+/* echo "Try \``basename $0` --help' for more information." >&2 */
+/* exit 1 */
+/* fi;; */
+/* esac */
+/* shift */
+/* done */
+
+/* if test -z "$MPFILE" || test -z "$MPXFILE"; then */
+/* echo "$0: Need exactly two file arguments." >&2 */
+/* echo "Try \``basename $0` --help' for more information." >&2 */
+/* exit 1 */
+/* fi */
+
+/* trap "rm -f mpx$$.* $ERRLOG; exit 4" 1 2 3 15 */
+
+/* # If MPX file is up-to-date, do nothing. */
+/* if $NEWER $MPFILE $MPXFILE; then */
+
+/* # Have to remake. */
+/* # Step 0: Check typesetter mode for consistency. */
+/* case "$mode" in */
+/* tex) MPTO="$MPTOTEX";; */
+/* troff) MPTO="$MPTOTR";; */
+/* *) echo "$0: Unknown typesetter mode: $mode" >&2 */
+/* exit 1;; */
+/* esac */
+
+/* # Step 1: Extract typesetter source from MetaPost source. */
+/* if $MPTO $MPFILE >mpx$$.tex 2>$ERRLOG; then :; */
+/* # success */
+/* else */
+/* # failure */
+/* echo "$0: Command failed: $MPTO $MPFILE" >&2 */
+/* cat $ERRLOG >&2 */
+/* rm -f mpx$$.tex */
+/* exit 1 */
+/* fi */
+/* if test "$mode" = troff; then */
+/* mv -f mpx$$.tex mpx$$.i */
+/* fi */
+
+/* # Step 2: Run typesetter. */
+/* if test "$mode" = tex; then */
+/* if test -r $MPTEXPRE; then */
+/* # Prepend user file. */
+/* cat $MPTEXPRE mpx$$.tex >mpx$$.tmp */
+/* mv mpx$$.tmp mpx$$.tex */
+/* fi */
+
+/* if $TEX '\batchmode\input 'mpx$$.tex </dev/null >/dev/null; then */
+/* WHATEVER_TO_MPX="$DVITOMP" */
+/* INFILE=mpx$$.dvi */
+/* INERROR=$DVIERR */
+/* else */
+/* # failure */
+/* mv -f mpx$$.tex $TEXERR */
+/* mv -f mpx$$.log $ERRLOG */
+/* echo "$0: Command failed: $TEX $TEXERR; see $ERRLOG" >&2 */
+/* exit 2 */
+/* fi */
+/* elif test "$mode" = troff; then */
+/* if cat mpx$$.i | eval $TROFF >mpx$$.t; then */
+/* # success, prepare for step 3. */
+/* WHATEVER_TO_MPX="$DMP" */
+/* INFILE=mpx$$.t */
+/* INERROR=$TROFF_OUTERR */
+/* else */
+/* # failure */
+/* mv -f mpx$$.i $TROFF_INERR */
+/* echo "$0: Command failed: cat $TROFFERR | $TROFF" >&2 */
+/* rm -f mpx$$.t */
+/* exit 2 */
+/* fi */
+/* else */
+/* echo "$0: Unknown typesetter mode: $mode; how did this happen?" >&2 */
+/* exit 2 */
+/* fi */
+
+/* # Step 3: Translate typesetter output to a MetaPost MPX. */
+/* if $WHATEVER_TO_MPX $INFILE $MPXFILE >$ERRLOG; then */
+/* : # success */
+/* else */
+/* # failure */
+/* mv -f $INFILE $INERROR */
+/* test $mode = troff && mv -f mpx$$.i $TROFF_INERR */
+/* echo "$0: Command failed: $WHATEVER_TO_MPX $INERROR $MPXFILE" >&2 */
+/* # Better to remove $MPXFILE if something went wrong rather than */
+/* # leaving behind an unfinished or unusable version since $NEWER */
+/* # might think that all is fine if $MPXFILE exists. */
+/* rm -f $MPXFILE */
+/* cat $ERRLOG >&2 */
+/* exit 3 */
+/* fi */
+
+/* rm -f $ERRLOG mpx$$.* */
+/* fi */
+
+/* exit 0 */
+
+/*
+ Global Variables
+ */
+/* #include <assert.h> */
+#include "mktex.h"
+#include "stackenv.h"
+#include "fileutils.h"
+
+static char *DMP;
+static char *DVITOMP;
+static char *MAKEMPX_BINDIR;
+static char *MPTEXPRE;
+static char *MPTOTEX;
+static char *MPTOTR;
+static char *NEWER;
+static char *TEX;
+static char *TROFF;
+
+static struct alist {
+ char *key;
+ char **var;
+ char *val;
+} vardef[] = {
+ {"DMP", &DMP, "dmp"},
+ {"DVITOMP", &DVITOMP, "dvitomp"},
+#ifdef _WIN32
+ {"MAKEMPX_BINDIR", &MAKEMPX_BINDIR, "c:\\TeX\\bin"},
+#else
+#ifdef __DJGPP__
+ {"MAKEMPX_BINDIR", &MAKEMPX_BINDIR, "c:/djgpp/bin"},
+#else
+ {"MAKEMPX_BINDIR", &MAKEMPX_BINDIR, "/usr/local/bin"},
+#endif
+#endif
+ {"MPTEXPRE", &MPTEXPRE, "mptexpre.tex"},
+ {"MPTOTEX", &MPTOTEX, "mpto -tex"},
+ {"MPTOTR", &MPTOTR, "mpto -troff"},
+ {"NEWER", &NEWER, "newer"},
+ {"TEX", &TEX, "tex --parse-first-line"},
+#ifdef _WIN32
+ {"TROFF", &TROFF, "eqn -d$$ | troff -Tpost"},
+#else
+#ifdef __DJGPP__
+ /* DJGPP users are likely to have Groff whose PostScript device is `ps'. */
+ {"TROFF", &TROFF, "eqn -d'$$' | troff -Tps"},
+#else
+ {"TROFF", &TROFF, "eqn -d'$$' | troff -Tpost"},
+#endif
+#endif
+ {NULL, NULL, NULL}
+};
+
+static char *MPTO, *INFILE, *INERROR, *WHATEVER_TO_MPX;
+static char mptemplate[FILENAME_MAX];
+
+/* These names are documented in the MetaPost manual, so it's */
+/* unwise to change them. */
+char *ERRLOG="mpxerr.log"; /* file for an error log if necessary */
+char *TEXERR="mpxerr.tex"; /* file for erroneous TeX if any */
+char *DVIERR="mpxerr.dvi"; /* troublesome dvi file if any */
+char *TROFF_INERR="mpxerr"; /* file for erroneous troff input, if any */
+char *TROFF_OUTERR="mpxerr.t";; /* file for troublesome troff output, if any */
+char *MPFILE = NULL;
+char *MPXFILE = NULL;
+
+char *version = "Revision: 1.7";
+extern MKTEXDLL string mktex_version_string;
+
+typedef enum { TEXMODE = 0, TROFFMODE} typeset_mode;
+
+#ifdef __GNUC__
+void __attribute__((noreturn)) usage(int exit_code)
+#else
+void usage(int exit_code)
+#endif
+{
+ fprintf(stderr, "Usage: %s [-tex|-tex=<program>|-troff] MPFILE MPXFILE.\n\
+ If MPXFILE is older than MPFILE, translate the labels from the MetaPost\n\
+ input file MPFILE to low-level commands in MPXFILE, by running\n\
+ %s, %s, and %s\n\
+ by default; or, if -troff is specified,\n\
+ %s, %s, and %s.\n\
+\n\
+ If the TeX mode is choosen, the TeX <program> used to typeset the labels\n\
+ can be specified and is `tex' by default.\n\
+\n\
+ The current directory is used for writing temporary files. Errors are\n\
+ left in mpxerr.{tex,log,dvi}.\n\
+\n\
+ If the file named in $MPTEXPRE (mptexpre.tex by default) exists, it is\n\
+ prepended to the output in tex mode.\n\
+\n\
+ Email bug reports to tex-k@mail.tug.org.\n",
+ progname, MPTOTEX, TEX, DVITOMP, MPTOTR, TROFF, DMP);
+ mt_exit(exit_code);
+}
+
+void printversion(void)
+{
+ fprintf(stderr, "%s: (Web2c 7.0) %s\n", progname, version);
+ fprintf(stderr, "%s: C replacement version %s\n", progname, mktex_version_string);
+ fprintf(stderr, "There is NO warranty. This program is public domain.\n\
+Primary author: John Hobby; Web2c maintainer: K. Berry;\n\
+C version: F. Popineau and Eli Zaretskii.");
+ mt_exit(0);
+}
+
+void output_file(FILE *f, const_string name)
+{
+ FILE *fp;
+ string line;
+
+ if ((fp = fopen(name, "r")) == NULL) {
+ perror(name);
+ }
+ else {
+ while((line = read_line(fp)) != NULL) {
+ fputs(line, f);
+ free(line);
+ }
+ fclose(fp);
+ }
+}
+
+void __cdecl output_and_cleanup(int code)
+{
+#ifdef _WIN32
+ WIN32_FIND_DATA ffd;
+ HANDLE hnd;
+ boolean go_on;
+
+ if (mptemplate && *mptemplate) {
+ string temp = concat(mptemplate, ".*");
+ /* rm -f mpxXXXXX.* */
+ hnd = FindFirstFile(temp, &ffd);
+ go_on = (hnd != INVALID_HANDLE_VALUE);
+ while (go_on) {
+ if (! (ffd.cFileName[0] == '.'
+ && (ffd.cFileName[1] == '\0'
+ || (ffd.cFileName[1] == '.'
+ && ffd.cFileName[2] == '\0')))) {
+ DeleteFile(ffd.cFileName);
+ }
+ go_on = (FindNextFile(hnd, &ffd) == TRUE);
+ }
+ FindClose(hnd);
+ free(temp);
+ }
+#else
+ DIR *dp;
+ struct dirent *de;
+ int temp_len = strlen(mptemplate) + 1; /* +1 for the dot */
+
+ if ((dp = opendir(".")) != 0) {
+ while ((de = readdir(dp)) != 0)
+ if (FILESTRNCASEEQ(de->d_name, mptemplate, temp_len))
+ remove(de->d_name);
+ }
+#endif
+
+ /* ERRLOG is removed only on normal exit. */
+ if (code == 0)
+ remove(ERRLOG);
+
+}
+
+char *change_suffix(char *old, char *suf)
+{
+ char *p, *new;
+ new = xstrdup(old);
+ p = strrchr(new, '.'); /* assumes there are no slashes in OLD */
+ if (p)
+ strcpy(p, suf);
+ else
+ strcat(new, suf);
+ return new;
+}
+
+/* This does what `newer' does, but avoids forking a child. */
+int newer(const char *first, const char *second)
+{
+ struct stat x, y;
+
+ /* does the first file exist? */
+ if (stat(first, &x) < 0)
+ return 0;
+
+ /* does the second file exist? */
+ if (stat(second, &y) < 0)
+ return 1;
+
+ /* is the first file older than the second? */
+ if (x.st_mtime < y.st_mtime)
+ return 0;
+
+ return 1;
+}
+
+int main(int argc, char *argv[])
+{
+ struct alist *p;
+ char buf[1024];
+ char cmd[512];
+ typeset_mode mode = TEXMODE;
+ int i, newfd[3];
+ FILE *ferr, *fmpx, *ftroff;
+ char mpxtex[32];
+ char *mpxi = NULL, *mpxt, *mpxtmp, *mpxlog, *mpxdvi;
+ string path;
+ string mpto_cmd;
+ char errbuf[PATH_MAX*2];
+ int mpto_status;
+
+ output_and_cleanup_function = output_and_cleanup;
+ mptemplate[0] = '\0';
+
+ if (!progname)
+ progname = argv[0];
+ kpse_set_progname (progname);
+
+ /* initialize the symbol table */
+ init_vars();
+
+#ifdef WIN32
+ SetConsoleCtrlHandler((PHANDLER_ROUTINE)mt_exit, TRUE);
+#else
+# ifdef SIGINT
+ signal (SIGINT, sigint_handler);
+# endif
+# ifdef SIGQUIT
+ signal (SIGQUIT, sigint_handler);
+# endif
+# ifdef SIGHUP
+ signal (SIGHUP, sigint_handler);
+# endif
+# ifdef SIGTERM
+ signal (SIGTERM, sigint_handler);
+# endif
+#endif
+
+ /* First assigning default values to all variables. */
+ for(p = vardef; p->key != NULL; p++) {
+ /* testing if there is an env var */
+ strcpy(buf, "$"); strcat(buf, p->key);
+ *(p->var) = kpse_var_expand(buf);
+ if (*(p->var) == NULL || **(p->var) == '\0')
+ *(p->var) = p->val;
+ }
+
+ /* Modifying $PATH */
+
+ /* The SELFAUTOLOC stuff is NOT in the original makempx script.
+ However, it is a handy way to get the installation directory
+ without modifying the source at compile time.
+
+ Also note that if $PATH is undefined, the null pointer returned
+ by `getenv' will serve as the trailing NULL to `concatn'. */
+ path = concatn(MAKEMPX_BINDIR, ENV_SEP_STRING,
+ kpse_var_value("SELFAUTOLOC"), ENV_SEP_STRING,
+ getenv("PATH"), NULL);
+ xputenv("PATH", path);
+ free(path);
+
+ for (i = 1; i <argc; i++) {
+ if (!strcmp(argv[i], "-help") || !strcmp(argv[i], "--help")
+ || !strcmp(argv[i], "-h")) {
+ usage(0);
+ }
+ if (!strcmp(argv[i], "-version") || !strcmp(argv[i], "--version")
+ || !strcmp(argv[i], "-v")) {
+ printversion();
+ }
+ if (!strcmp(argv[i], "-troff") || !strcmp(argv[i], "--troff")) {
+ mode = TROFFMODE;
+ }
+ else if (!strcmp(argv[i], "-tex") || !strcmp(argv[i], "--tex")) {
+ mode = TEXMODE;
+ }
+ else if (!strncmp(argv[i], "-tex=", 5) || !strncmp(argv[i], "--tex=", 6)) {
+ TEX = strchr(argv[i], '=') + 1;
+ mode = TEXMODE;
+ }
+ /* FIXME: this disallows arguments with a leading dash, but
+ that's how the original shell script works. */
+ else if (*argv[i] == '-') {
+ fprintf(stderr, "%s: Invalid option: %s.\nTry `%s --help' for more information.\n",
+ progname, argv[i], program_invocation_short_name);
+ mt_exit(1);
+ }
+ else if (!MPFILE || !*MPFILE)
+ MPFILE = argv[i];
+ else if (!MPXFILE || !*MPXFILE)
+ MPXFILE = argv[i];
+ else {
+ fprintf(stderr, "%s: Extra argument %s.\nTry `%s --help' for more information.\n",
+ progname, argv[i], program_invocation_short_name);
+ mt_exit(1);
+ }
+ }
+
+ if (!MPXFILE || !*MPXFILE || !MPFILE || !*MPFILE) {
+ fprintf(stderr, "%s: Need exactly two file arguments.\nTry `%s --help' for more information.",
+ progname, program_invocation_short_name);
+ mt_exit(1);
+ }
+
+ /* If MPX file is up-to-date, do nothing. */
+ if (!newer (MPFILE, MPXFILE))
+ mt_exit(0);
+
+ /* Have to remake. */
+
+ /* Step 0: Check typesetter mode for consistency. */
+ *cmd = '\0';
+ switch(mode) {
+ case TEXMODE:
+ MPTO = MPTOTEX;
+ break;
+ case TROFFMODE:
+ MPTO = MPTOTR;
+ break;
+ default:
+ fprintf(stderr, "%s: Unknown typesetter mode\n", progname);
+ mt_exit(1);
+ }
+
+ /* Step 1: Extract typesetter source from MetaPost source. */
+
+ sprintf(mptemplate, "mpx%d", getpid());
+ strcpy(mpxtex, mptemplate); strcat(mpxtex, ".tex");
+ /* redirecting 1 -> mpx$$.tex 2 -> ERRLOG */
+ if (!(fmpx = fopen(mpxtex, "w"))) {
+ perror(mpxtex);
+ mt_exit(1);
+ }
+ if (!(ferr = fopen(ERRLOG, "w"))) {
+ perror(ERRLOG);
+ mt_exit(1);
+ }
+
+ newfd[0] = 0; newfd[1] = fileno(fmpx); newfd[2] = fileno(ferr);
+ push_fd(newfd);
+
+ mpto_cmd = concat3(MPTO, " ", MPFILE);
+ mpto_status = system(mpto_cmd);
+ free(mpto_cmd);
+ pop_fd();
+ fclose(fmpx);
+ fclose(ferr);
+ if (mpto_status != 0) {
+ fprintf(stderr, "%s: Command failed: %s %s\n", progname, MPTO, MPFILE);
+
+ output_file(stderr, ERRLOG);
+ /* rm -f mpx$$.tex -- this is done by the wrap-up code */
+ mt_exit(1);
+ }
+
+ /* Step 2: Run typesetter. */
+
+ switch(mode) {
+ case TEXMODE:
+ mpxdvi = change_suffix(mpxtex, ".dvi");
+ mpxtmp = change_suffix(mpxtex, ".tmp");
+ mpxlog = change_suffix(mpxtex, ".log");
+
+ if (test_file('r', MPTEXPRE)) {
+ if (catfile(MPTEXPRE, mpxtmp, 0) == FALSE
+ || catfile(mpxtex, mpxtmp, 1) == FALSE) {
+ sprintf(errbuf, "%s: cat %s %s > %s",
+ program_invocation_short_name, MPTEXPRE, mpxtex, mpxtmp);
+ perror(errbuf);
+ mt_exit(1);
+ }
+ mvfile(mpxtmp, mpxtex);
+ }
+#ifdef _WIN32
+ sprintf(cmd, "%s --interaction=batchmode %s < nul > nul", TEX, mpxtex);
+#else
+ sprintf(cmd, "%s --interaction=batchmode %s </dev/null >/dev/null",
+ TEX, mpxtex);
+#endif
+ if (system(cmd)) {
+ fprintf(stderr, "%s: Command failed: %s %s; see %s\n",
+ progname, TEX, TEXERR, ERRLOG);
+ mvfile(mpxtex, TEXERR);
+ mvfile(mpxlog, ERRLOG);
+ mt_exit(2);
+ }
+ WHATEVER_TO_MPX = DVITOMP;
+ INFILE = mpxdvi;
+ INERROR = DVIERR;
+ break;
+ case TROFFMODE:
+ mpxi = change_suffix(mpxtex, ".i");
+ mpxt = change_suffix(mpxtex, ".t");
+ mvfile(mpxtex, mpxi);
+ sprintf(cmd, "%s > %s", TROFF, mpxt);
+ if ((ftroff = popen(cmd, "w")) == NULL) {
+ perror(cmd);
+ mt_exit(1);
+ }
+ if (!(fmpx = fopen(mpxi, "r"))) {
+ perror(mpxi);
+ mt_exit(1);
+ }
+ while (fgets(buf, 1024, fmpx))
+ fputs(buf, ftroff);
+ if (pclose(ftroff) != 0) {
+ fprintf(stderr, "%s: Command failed: cat %s | %s\n", progname,
+ TROFF_INERR, TROFF);
+ mvfile(mpxi, TROFF_INERR);
+ /* rm -f mpx$$.t : this is done in wrap-up code */
+ mt_exit(2);
+ }
+ fclose(fmpx);
+ WHATEVER_TO_MPX = DMP;
+ INFILE = mpxt;
+ INERROR = TROFF_OUTERR;
+ break;
+ default:
+ fprintf(stderr, "%s: Unknown typesetter mode; how did this happen?\n",
+ progname);
+ mt_exit(2);
+ }
+
+ /* Step 3: Translate typesetter output to a MetaPost MPX. */
+
+ sprintf(cmd, "%s %s %s > %s", WHATEVER_TO_MPX, INFILE, MPXFILE, ERRLOG);
+ if (system(cmd)) {
+ fprintf(stderr, "%s: Command failed: %s %s %s\n", progname,
+ WHATEVER_TO_MPX, INERROR, MPXFILE);
+ mvfile(INFILE, INERROR);
+ if (mode == TROFFMODE)
+ mvfile(mpxi, TROFF_INERR);
+ /* rm -f $MPXFILE : done in our exit code */
+ output_file(stderr, ERRLOG);
+ mt_exit(3);
+ }
+ mt_exit(0);
+}
diff --git a/Build/source/texk/contrib/makempx.rc b/Build/source/texk/contrib/makempx.rc
new file mode 100644
index 00000000000..f93b9e930da
--- /dev/null
+++ b/Build/source/texk/contrib/makempx.rc
@@ -0,0 +1,34 @@
+/* makempx.rc: makempx resources -*- C++ -*-
+
+ Copyright (C) 1996-2003 Fabrice Popineau <fabrice.popineau@supelec.fr>
+
+ This file 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 file 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 file; if not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+#include <texlive-version.h>
+
+#define VER_FILEVERSION TEXLIVE_MAJOR_VERSION,TEXLIVE_MINOR_VERSION,TEXLIVE_BETA_NUMBER,TEXLIVE_ALPHA_NUMBER
+#define VER_FILEVERSION_STR TEXLIVE_PRODUCTVERSION_STR " makempx 1.7"
+
+#define VER_INTERNALNAME_STR "makempx"
+#define VER_ORIGINALFILENAME_STR "makempx.exe"
+
+#define VER_FILEDESCRIPTION_STR "MetaPost label processor"
+
+#define VER_LEGALCOPYRIGHT_STR "This program is public domain"
+
+#include <texlive.version>
+
+/* makempx.rc ends here */
diff --git a/Build/source/texk/contrib/mkloctex.bat b/Build/source/texk/contrib/mkloctex.bat
new file mode 100644
index 00000000000..c91f1d102d5
--- /dev/null
+++ b/Build/source/texk/contrib/mkloctex.bat
@@ -0,0 +1,48 @@
+@echo off
+REM Staszek Wawrykiewicz (staw@gust.org.pl). March 2000
+REM This batch file installs the local TeX tree for running
+REM programs directly from the CD TeX Live 5 (Windows 9x/2000/NT)
+REM It allows changing some parameters (MF mode for dvips and windvi, etc.)
+REM and building local format files.
+REM Run: mkloctex g c
+REM where: %1 - CD ROM drive letter; %2 - HD drive letter for local tree
+if "%1"=="" goto HELPA
+if "%2"=="" goto HELPB
+%2:
+cd \
+md TeX
+md TeX\texmf
+md TeX\texmf\dvips
+md TeX\texmf\dvips\config
+md TeX\texmf\tex
+md TeX\texmf\tex\generic
+md TeX\texmf\tex\generic\config
+md TeX\texmf\web2c
+copy %1:\texmf\dvips\config\config.ps %2:\TeX\texmf\dvips\config\*.*
+copy %1:\texmf\tex\generic\config\language.dat %2:\TeX\texmf\tex\generic\config\*.*
+copy %1:\texmf\web2c\fmtutil.cnf %2:\TeX\texmf\web2c\*.*
+copy %1:\texmf\web2c\mktex.cnf %2:\TeX\texmf\web2c\*.*
+copy %1:\texmf\web2c\texmf.cnf %2:\TeX\texmf\web2c\*.*
+
+goto OKOK
+:HELPA
+echo Missing parameter: should be the letter of your CD-ROM drive
+
+goto FINIS
+:HELPB
+echo Missing parameter: should be the letter of HD drive for local TeX tree
+
+goto FINIS
+:OKOK
+echo.
+echo 1. Add %1:\bin\win32 directory to your environment PATH,
+echo 2. Add: set TEXMFCNF=%2:/TeX/texmf/web2c to your environment
+echo 3. Modify %2:\TeX\texmf\web2c\texmf.cnf accordingly, e.g.,
+echo TEXMFMAIN = %1:/texmf
+echo VARTEXMF = %2:/TeX/texmf
+echo.
+echo 4. Remember to run `mktexlsr' after any changes.
+
+:FINIS
+mktexlsr
+pause
diff --git a/Build/source/texk/contrib/mkocp.c b/Build/source/texk/contrib/mkocp.c
new file mode 100644
index 00000000000..f009c2b76de
--- /dev/null
+++ b/Build/source/texk/contrib/mkocp.c
@@ -0,0 +1,46 @@
+#include <kpathsea/kpathsea.h>
+#include "stackenv.h"
+
+char *progname = NULL;
+
+void
+usage()
+{
+ fprintf(stderr, "usage: %s ocp_filename\n", progname);
+ exit(1);
+}
+
+int
+main (int argc, char *argv[])
+{
+ char cmd[4096];
+ int newfd[3], ret;
+ FILE *f = fopen("nul", "r");
+ char *basename;
+
+ progname = xbasename(argv[0]);
+
+ if (argc != 2) {
+ usage();
+ }
+
+ SetConsoleCtrlHandler((PHANDLER_ROUTINE)mt_exit, TRUE);
+
+ basename = xbasename(argv[1]);
+ if (strlen(basename) > strlen(".ocp")
+ && _stricmp(basename + strlen(basename) - strlen(".ocp"), ".ocp") == 0) {
+ basename[strlen(basename) - strlen(".ocp")] = '\0';
+ }
+ newfd[0] = fileno(f);
+ newfd[1] = fileno(stderr);
+ newfd[2] = fileno(stderr);
+ push_fd(newfd);
+ sprintf(cmd, "otp2ocp %s", basename);
+ ret = system(cmd);
+ pop_fd();
+ fclose(f);
+ if (ret == 0) {
+ printf("%s.ocp\n", basename);
+ }
+ return ret;
+}
diff --git a/Build/source/texk/contrib/mkofm.c b/Build/source/texk/contrib/mkofm.c
new file mode 100644
index 00000000000..d133a5bd9f8
--- /dev/null
+++ b/Build/source/texk/contrib/mkofm.c
@@ -0,0 +1,83 @@
+#include <win32lib.h>
+
+#undef _DEBUG
+
+#ifdef _DEBUG
+#define TRACE(x) x
+#else
+#define TRACE(x)
+#endif
+
+/*
+ Return a quoted string if space is found
+ New string is allocated
+*/
+static char *
+quote_elt(char *elt)
+{
+ int len = 2*strlen(elt)*sizeof(char) + 2;
+ char *to = xmalloc(len);
+ char *p = to;
+ BOOL need_quote = FALSE;
+
+ if (strchr(elt, ' ')) {
+ *to++ = '"';
+ need_quote = TRUE;
+ }
+
+ while (*elt) {
+ switch (*elt) {
+ case '"':
+ case '\'':
+ /* case '\\': */
+ *to++ = '\\';
+ default:
+ *to++ = *elt++;
+ }
+ }
+ if (need_quote) {
+ *to++ = '"';
+ }
+
+ *to = *elt;
+ to = xstrdup(p);
+ free(p);
+
+ return to;
+}
+
+/*
+ Process an array of strings, quote them
+ an return their catenation
+*/
+static char *
+quote_args(char **argv)
+{
+ int i;
+ char *line = NULL, *new_line;
+ char *new_argv_i;
+
+ if (!argv)
+ return line;
+
+ line = quote_elt(argv[0]);
+ for (i = 1; argv[i]; i++) {
+ new_argv_i = quote_elt(argv[i]);
+ new_line = concat3(line, " ", new_argv_i);
+ TRACE(fprintf(stderr, "quote_args: new_line = %s\n", new_line));
+ free(line);
+ free(new_argv_i);
+ line = new_line;
+ }
+
+ return line;
+}
+
+int
+main (int argc, char *argv[])
+{
+ char *cmd_line;
+ argv[0] = "mktextfm";
+ cmd_line = quote_args(argv);
+ return system(cmd_line);
+}
diff --git a/Build/source/texk/contrib/mktex.c b/Build/source/texk/contrib/mktex.c
new file mode 100644
index 00000000000..9675ecbfa47
--- /dev/null
+++ b/Build/source/texk/contrib/mktex.c
@@ -0,0 +1,2610 @@
+/* mktex.c: this program emulates the mktex* shell scripts from web2c.
+
+Copyright (C) 1997 Fabrice POPINEAU.
+Adapted to MS-DOS/DJGPP by Eli Zaretskii <eliz@is.elta.co.il>.
+
+Time-stamp: <04/03/14 00:12:09 popineau>
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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 this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Maximum number of lines per usage message. */
+#define MAX_LINES 16
+
+#define SEPARATORS " \t\n\""
+
+#include <signal.h>
+
+#include "stackenv.h"
+#include "variables.h"
+#include "fileutils.h"
+#include "mktex.h"
+
+#ifdef _WIN32
+#define isatty _isatty
+#endif
+
+/*
+ Global Variables found in the mktex* scripts
+*/
+
+/* mktex.opt */
+int program_number = -1;
+string progname = NULL;
+
+/* mktex.cnf */
+
+char tmpdir[PATH_MAX]; /* Working temporary directory */
+string output = "astdout";
+FILE *fout = NULL;
+static boolean downcase_names;
+
+char empty_str[] = "(empty)";
+
+static int errstatus;
+extern int mt_append_mask;
+void delmulslash(string );
+void read_mktexcnf(void);
+void usage(void);
+
+/* Description of functionality : long name, short name, min args,
+ max args and pointer to a function to execute. */
+program_description makedesc [] = {
+ {"mktexpk", 2, 4, mktexpk }, /* 4,7 */
+ {"mktextfm", 2, 2, mktextfm }, /* 1,2 */
+ {"mktextex", 4, 6, mktextex }, /* ?? */
+ {"mktexmf", 2, 2, mktexmf }, /* 1,1 */
+ {"mktexlsr", 1, 255, mktexlsr }, /* 0,MANY */
+ {"texhash", 1, 255, mktexlsr }, /* 0,MANY */
+ {"mktexupd", 3, 3, mktexupdate }, /* 2,2 */
+ {"mktexdir", 2, 255, mktexmkdir }, /* 0,MANY */
+ {"mktexrmd", 2, 255, mktexrmdir }, /* ?? */
+ {"mktexnam", 2, 5, mktexnames }, /* 1,4 */
+#if 0
+ {"mktexfmt", 2, 5, mktexfmt }, /* 1,4 */
+#endif
+ {0, 0, 0}
+};
+
+#define PROGRAM_IS(p) STREQ (p, makedesc[program_number].name)
+
+/* Test whether getopt found an option ``A''.
+ Assumes the option index is in the variable `option_index', and the
+ option table in a variable `long_options'. */
+#define ARGUMENT_IS(a) STREQ (long_options[option_index].name, a)
+
+static struct option long_options [] = {
+ { "debug", 1, 0, 0},
+ { "help", 0, 0, 0},
+ { "version", 0, 0, 0},
+ { "dpi", 1, 0, 0},
+ { "bdpi", 1, 0, 0},
+ { "mag", 1, 0, 0},
+ { "mfmode", 1, 0, 0},
+ { "destdir", 1, 0, 0},
+ {0, 0, 0, 0}
+};
+
+/*
+ First argument takes progname;
+ Other arguments take no arguments.
+ */
+static string usage_msg[][MAX_LINES] = {
+ /* MktexPK */
+ {
+ "Usage: %s [OPTIONS] NAME [REDIRECT],\n",
+ "Create a PK font.\n\n",
+
+ "--dpi DPI use resolution DPI.\n",
+ "--bdpi BDPI use base resolution BDPI.\n",
+ "--mag MAG use magnificiation MAG.\n",
+ "--mfmode MODE use MODE as the METAFONT mode.\n",
+ "--destdir DESTDIR write fonts in DESTDIR.\n\n",
+
+ "Try to create a PK file for NAME at resolution DPI, with an assumed\n",
+ "device base resolution of BDPI, and a Metafont `mag' of MAG. Use MODE\n",
+ "for the METAFONT mode. Use DESTDIR for the root of where to install\n",
+ "into, either the absolute directory name to use (if it starts with a\n",
+ "/) or relative to the default DESTDIR (if not). REDIRECT, if supplied,\n",
+ "is a string of the form '>&n', where n is the number of the file\n",
+ "descriptor which is to receive, instead of stdout, the name of the\n",
+ "newly created pk file.\n",
+ 0
+ },
+ /* MktexTFM */
+ {
+ "Usage: %s [--destdir DESTDIR] FONT.\n\n",
+ "Makes a TFM file for FONT, if possible. Use DESTDIR for the root of where\n",
+ "to install into, either the absolute directory name to use (if it starts\n",
+ "with a /) or relative to the default DESTDIR (if not).\n",
+ 0
+ },
+ /* MktexTeX */
+ {
+ 0
+ },
+ /* MktexMF */
+ {
+ "Usage : %s FONT.\n\n",
+ "Makes the Metafont source file for FONT, if possible. For example,\n",
+ "`ecr12' or `cmr11'.\n",
+ 0
+ },
+ /* MktexlsR */
+ {
+ "Usage: %s [DIRS ...]\n\n",
+ "Rebuild all necessary ls-R filename databases completely. If one or\n",
+ "more arguments DIRS are given, these are used as texmf directories to\n",
+ "build ls-R for. Else all directories in the search path for ls-R files\n",
+ "($TEXMFDBS) are used.\n",
+ 0
+ },
+ /* TeXHash */
+ {
+ "Usage: %s [DIRS ...]\n\n",
+ "Rebuild all necessary ls-R filename databases completely. If one or\n",
+ "more arguments DIRS are given, these are used as texmf directories to\n",
+ "build ls-R for. Else all directories in the search path for ls-R files\n",
+ "($TEXMFDBS) are used.\n",
+ 0
+ },
+ /* Mktexupd */
+ {
+ "Usage : %s DIR FILE.\n",
+ " Update the ls-R file with an entry for FILE in DIR.\n",
+ 0
+ },
+ /* Mktexdir */
+ {
+ "Usage : %s DIRS...\n",
+ " Create each DIR, including any missing leading directories.\n",
+ 0
+ },
+ /* Mktexrmd */
+ {
+ "Usage : %s DIRS ...\n",
+ " Recursively remove each DIR.\n",
+ 0
+ },
+ /* Mktexnam */
+ {
+ "Usage : %s NAME [DPI MODE] [DESTDIR].\n",
+ " Output the PK, TFM and MF names for a font NAME.\n",
+ 0
+ },
+#if 0
+ /* Mktexfmt */
+ {
+ "Usage : %s [-all] [FORMAT].\n",
+ " Rebuild all or specified format.\n",
+ 0
+ }
+#endif
+};
+
+/*
+ First part: mktex.opt
+ */
+int mktex_opt(int argc, char *argv[],
+ program_description * program)
+{
+ int g; /* getopt return code */
+ int i;
+ int option_index;
+ string tempenv, cwd, vartexmf;
+
+ for(;;) {
+ g = getopt_long_only (argc, argv, "", long_options, &option_index);
+
+ if (g == EOF)
+ break;
+
+ if (g == '?') {
+ usage(); /* Unknown option. */
+ exit(1);
+ }
+
+ /* assert (g == 0); */ /* We have no short option names. */
+ /*
+ FIXME : try 'mktexpk --mfmode --bdpi 600 ...'
+ */
+ if (ARGUMENT_IS ("debug")) {
+ kpathsea_debug |= atoi (optarg);
+ }
+ else if (ARGUMENT_IS ("help")) {
+ usage();
+ exit(0);
+ }
+ else if (ARGUMENT_IS ("version")) {
+ fprintf(stderr, "%s of %s.\n", progname, kpathsea_version_string);
+ exit(0);
+ }
+ else if (PROGRAM_IS("mktexpk")) {
+ if (ARGUMENT_IS("dpi")) {
+ setval("DPI", optarg);
+ }
+ else if (ARGUMENT_IS("bdpi")) {
+ setval("BDPI", optarg);
+ }
+ else if (ARGUMENT_IS("mag")) {
+ setval("MAG", optarg);
+ }
+ else if (ARGUMENT_IS("mfmode")) {
+ if (!STREQ(optarg, DIR_SEP_STRING))
+ setval("MODE", optarg);
+ }
+ else if (ARGUMENT_IS("destdir")) {
+ setval("DEST", optarg);
+ }
+ }
+ else if (PROGRAM_IS("mkextfm")) {
+ if (ARGUMENT_IS("destdir")) {
+ setval("DEST", optarg);
+ }
+ }
+ }
+
+ /* shifting options from argv[] list */
+ for (i = 1; optind < argc; i++, optind++)
+ argv[i] = argv[optind];
+ argv[i] = NULL;
+
+ argc = i;
+ if (argc < program->arg_min) {
+ fprintf (stderr, "%s: Missing argument(s).\nTry `%s --help' for more information.\n", progname, kpse_program_name);
+ exit(1);
+ }
+ if (argc > program->arg_max) {
+ fprintf(stderr, "%s: Extra arguments", progname);
+ for (i = program->arg_max - 1; i < argc; i++)
+ fprintf (stderr, " \"%s\"", argv[i]);
+ fprintf (stderr, "\nTry `%s --help' for more information.\n",
+ kpse_program_name);
+ exit(1);
+ }
+
+ /* Catch signals, so we clean up if the child is interrupted.
+ This emulates "trap 'whatever' 1 2 15". */
+#ifdef _WIN32
+ SetConsoleCtrlHandler((PHANDLER_ROUTINE)sigint_handler, TRUE);
+#else
+# ifdef SIGHUP
+ signal (SIGHUP, sigint_handler);
+# endif
+# ifdef SIGINT
+ signal (SIGINT, sigint_handler);
+# endif
+# ifdef SIGQUIT
+ signal (SIGQUIT, sigint_handler);
+# endif
+# ifdef SIGEMT
+ signal (SIGEMT, sigint_handler);
+# endif
+# ifdef SIGPIPE
+ signal (SIGPIPE, sigint_handler);
+# endif
+# ifdef SIGTERM
+ signal (SIGTERM, sigint_handler);
+# endif
+#endif
+
+ tempenv = getval("TMPDIR");
+ if (test_file ('z', tempenv))
+ tempenv = getval("TEMP");
+ if (test_file ('z', tempenv))
+ tempenv = getval("TMP");
+#ifdef DOSISH
+ if (test_file ('z', tempenv))
+ tempenv = "c:/tmp"; /* "/tmp" is not good if we are on a CD-ROM */
+#else
+ if (test_file ('z', tempenv))
+ tempenv = "/tmp";
+#endif
+ sprintf(tmpdir, "%s/mtXXXXXX", tempenv);
+ mktemp(tmpdir);
+ if (do_makedir(tmpdir)) {
+ perror(tmpdir);
+ exit(1);
+ }
+ setval("TEMPDIR", tmpdir);
+ setval("STDOUT", concat_pathes(tmpdir, "astdout"));
+ setval("KPSE_DOT", cwd = xgetcwd());
+ /* export KPSE_DOT */
+ xputenv("KPSE_DOT", cwd);
+
+ /*: ${MT_VARTEXFONTS=`kpsewhich --expand-var='$VARTEXFONTS' | sed 's%^!!%%'`} */
+ vartexmf = setval_default("MT_VARTEXFONTS", expand_var("$VARTEXFONTS"));
+
+ /* A sanity check. */
+ if (test_file('z', vartexmf)) {
+ fprintf(stderr,
+ "%s: VARTEXFONTS is not defined. Defaulting to `%s'.\n",
+ progname, expand_var("$KPSE_DOT"));
+ setval("MT_VARTEXFONTS", "$KPSE_DOT");
+ }
+
+ /* mktex.opt sets the $MT_MKTEX... variables here to point to the supporting
+ scripts. But we don't need this, since we just call ourselves. */
+ setval("ls_R_magic",
+ "% ls-R -- filename database for kpathsea; do not change this line.");
+ setval("old_ls_R_magic",
+ "% ls-R -- maintained by MakeTeXls-R; do not change this line.");
+
+ pushd(tmpdir);
+
+ if ((fout = fopen(getval("STDOUT"), "w")) == NULL) {
+ perror(output);
+ mt_exit(1);
+ }
+
+ read_mktexcnf();
+
+ /* features by default */
+#ifdef MSDOS
+ setval_default("MT_FEATURES", "appendonlydir:dosnames");
+#else
+ setval_default("MT_FEATURES", "appendonlydir");
+#endif
+ setval_default("MODE", "ljfour");
+ setval_default("BDPI", "600");
+ setval_default("ps_to_pk", "gsftopk");
+
+ /* umask = 0 */
+ umask(0); /* for those platforms who support it */
+
+ /* Cache values that may be useful for recursive calls. */
+ xputenv("MT_MKTEX_CNF", getval("MT_MKTEX_CNF"));
+ xputenv("MT_TEXMFMAIN", getval("MT_TEXMFMAIN"));
+ xputenv("MT_VARTEXFONTS", getval("MT_VARTEXFONTS"));
+
+ return argc;
+}
+
+/* Reading mktex.cnf */
+
+void read_mktexcnf()
+{
+ FILE *f;
+ string line;
+ string mtsite;
+
+ mtsite = kpse_find_file ("mktex.cnf", kpse_web2c_format, false);
+ mtsite = setval_default("MT_MKTEX_CNF", mtsite);
+ if (test_file('n', mtsite) && test_file('r', mtsite)) {
+ f = fopen(mtsite, "r");
+ if (KPSE_DEBUG_P(MKTEX_DEBUG)) {
+ fprintf(stderr, "Reading mktex_cnf file: %s\n", mtsite);
+ }
+ while ((line = read_line(f)) != NULL) {
+ /* skip comments */
+ if (*line == '#' || *line == '%' || isspace(*line)
+ || *line == '\0' || *line == '\n') {
+ free(line);
+ continue;
+ }
+
+ if (!parse_variable(line))
+ fprintf(stderr, "%s: unsupported keyword: %s\n", mtsite, line);
+ free(line);
+ }
+ fclose(f);
+ }
+
+}
+
+/* If non-negative, records the handle to redirect STDOUT
+ in `output_and_cleanup'. */
+int redirect_stdout;
+
+/* Record the handle where STDOUT is to be redirected
+ for printing the names of the generated files before we exit. */
+void record_output_handle(int fd)
+{
+ redirect_stdout = fd; /* FIXME: cannot be nested! */
+}
+
+void usage()
+{
+ int i;
+ fprintf(stderr, "%s of %s\n", progname, kpathsea_version_string);
+ fprintf(stderr, "Mktex version %s\n", mktex_version_string);
+ fprintf(stderr,usage_msg[program_number][0], progname );
+ fputs("\n", stderr);
+ for(i = 1; usage_msg[program_number][i]; ++i)
+ fputs(usage_msg[program_number][i], stderr);
+}
+
+void mktexinit(int argc, char **argv)
+{
+ string mode, bdpi;
+ string texmfmain;
+
+ program_number = -1;
+
+ if (!progname)
+ progname = argv[0];
+
+ kpse_set_program_name (progname, NULL);
+
+ /* initialize the symbol table */
+ init_vars();
+ /* `kpse_init_prog' will put MODE and DPI into environment as values of
+ the two variables below. We need to leave these variables as they are. */
+ mode = getval("MAKETEX_MODE");
+ bdpi = getval("MAKETEX_BASE_DPI");
+
+ /* NULL for no fallback font. */
+ kpse_init_prog (uppercasify (progname),
+ bdpi && atoi(bdpi) ? atoi(bdpi) : 600, mode, NULL);
+
+ /* Common code for all scripts.
+
+ : ${MT_TEXMFMAIN=`kpsewhich -expand-path='$TEXMFMAIN'`} */
+ texmfmain = setval_default("MT_TEXMFMAIN", kpse_path_expand("$TEXMFMAIN"));
+
+ /* FIXME: we don't support edited mktex.opt files, and don't look for
+ that file along the TEXMF trees. But at least we should fake the
+ safeguard in case $TEXMFMAIN is not defined at all. */
+ if (test_file('z', texmfmain) || !test_file('d', texmfmain)) {
+ fprintf(stderr, "%s: $TEXMFMAIN is undefined or points to a non-existent directory;\n%s: check your installation.\n$TEXMFMAIN = %s\n", progname, progname, kpse_var_expand("$TEXMFMAIN"));
+ exit(1); /* not mt_exit, since temporary files were not created yet */
+ }
+
+}
+
+/* Output the string in lower case or without modification according
+ to downcase_names. */
+void output_name(string name, FILE *f)
+{
+ string p;
+ if (downcase_names) {
+ for(p = name; *p; p++)
+ *p = TOLOWER(*p);
+ }
+ fputs(name, f);
+}
+
+/* lower casify the string */
+string string_to_lower(string s)
+{
+ string p = NULL, q;
+ if (s) {
+ q = p = xstrdup(s);
+ while (*q) {
+ *q = TOLOWER(*q);
+ q++;
+ }
+ }
+ return p;
+}
+
+/* Info about the temporary file to which we redirect print_path's
+ stdout. */
+static struct tem_file {
+ const char *tem_dir;
+ const char *tem_base;
+ const char *lsr_base;
+} tem_file_info;
+
+/* Return 1 if DIR is the directory and BASE is the basename of the
+ temporary file whose info is in tem_file structure.
+ FIXME: this will break if mktexlsr invokes itself recirsively. */
+int is_db_file_tmp(string dir, int dir_len, char *base)
+{
+ if (!tem_file_info.tem_dir || !tem_file_info.tem_base)
+ return 0;
+ return ((dir_len >= 0 ? FILESTRNCASEEQ(dir, tem_file_info.tem_dir, dir_len)
+ : FILESTRCASEEQ(dir, tem_file_info.tem_dir))
+ && FILESTRCASEEQ(base, tem_file_info.tem_base));
+}
+
+/* Updates ls-R db for directory pointed to by path. */
+void print_path(string path, struct stat* st)
+{
+ if ((st->st_mode & S_IFMT) == S_IFDIR) {
+#ifdef _WIN32
+ WIN32_FIND_DATA ffd;
+ HANDLE hnd;
+ string fulldir;
+ int offset = 0;
+ int ind = strlen(path);
+#else
+ DIR *dp;
+ struct dirent *ep;
+#endif
+
+ putchar('\n'); /* extra blank line before new directory */
+ output_name(path, stdout);
+ if (path[0] == '.' && path[1] == '\0')
+ putchar('/');
+ putchar(':'); putchar('\n');
+
+ /* Note that we actually read each directory twice: once
+ here, to print all its entries, and once in `recurse_dir',
+ to recurse into its subdirectories. This is so that
+ `ls-R' file is written in breadth-first manner, like
+ `ls -R' does in the original script. Caching the entries
+ from the first read would make this code run faster, but
+ since it is faster than the script already, why bother? */
+
+#ifdef _WIN32
+ if (path[0] == '.' && IS_DIR_SEP(path[1])) {
+ offset = 2;
+ }
+ fulldir = concat_pathes(tem_file_info.lsr_base, path + offset);
+
+ strcat(path, "/*"); /* ok since the caller says path[PATH_MAX] */
+ hnd = FindFirstFile(path, &ffd);
+ while (hnd && FindNextFile(hnd, &ffd)) {
+ if (ffd.cFileName[0] == '.'
+ && ((ffd.cFileName[1] == '\0')
+ || (ffd.cFileName[1] == '.' && ffd.cFileName[2] == '\0')))
+ continue;
+ if (!is_db_file_tmp(path, ind, ffd.cFileName)
+ /* We don't want to report directories ! */
+ && !(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
+ output_name(ffd.cFileName, stdout);
+ putchar('\n');/* We do want a \n */
+ {
+ string fullname;
+ fullname = concat_pathes(fulldir, ffd.cFileName);
+ kpse_db_insert(fullname);
+ free(fullname);
+ }
+ }
+ }
+ path[ind] = '\0';
+ FindClose(hnd);
+ free(fulldir);
+#else /* not _WIN32 */
+ if ((dp = opendir(path))) {
+ while ((ep = readdir(dp)))
+ if (strcmp(ep->d_name, ".")
+ && strcmp(ep->d_name, "..")
+ && !is_db_file_tmp(path, -1, ep->d_name)) {
+ output_name(ep->d_name, stdout);
+ putchar('\n');
+ }
+ closedir(dp);
+ }
+ else
+ perror(path);
+#endif /* not _WIN32 */
+
+ }
+}
+
+/* return true if the fs on which path lies is case sensitive.
+ Insufficient. Some people may have copied the complete tree in
+ upper case from a case insensitive fs.
+ Second test : look at the texmf name. If GetShortName !=
+ GetLongName it is ok.
+*/
+boolean is_casesensitive(string path)
+{
+ boolean retval = TRUE; /* default for non-DOSISH systems */
+
+#ifdef MONOCASE_FILENAMES
+ char name[PATH_MAX];
+#ifdef _WIN32
+ char volname[PATH_MAX];
+ DWORD sernum;
+ DWORD maxcomplen;
+#endif
+#ifdef __DJGPP__
+ int maxnamelen;
+ DWORD maxpathlen;
+#endif
+ DWORD fsflags;
+ char fsname[PATH_MAX];
+
+ /* How should the db be output ? Preserve case or lower case ?
+ First, determine the root volume : if path has the drive, ok. If
+ not, get current drive. */
+#ifdef WIN32
+ if (IS_UNC_NAME(path)) {
+ /* UNC pathname : \\server\dir\...
+ We must find the first 2 components.
+ */
+ char *p;
+ strcpy(name, path);
+ name[0] = name[1] = '\\';
+ p = strchr(name+2, '/');
+ if (p)
+ *p = '\\';
+ else {
+ p = strchr(name+2, '\\');
+ if (!p) {
+ fprintf(stderr, "Error getting volume info on %s.\n", name);
+ mt_exit(1);
+ }
+ }
+ p = strchr(p+1, '/');
+ if (p)
+ *p = '\\';
+ else {
+ p = strchr(p+1, '\\');
+ if (!p) {
+ fprintf(stderr, "Error getting volume info on %s.\n", name);
+ mt_exit(1);
+ }
+ }
+ *(p+1) = '\0';
+ }
+ else {
+ if (IS_DEVICE_SEP(path[1])) { /* the shortest path is "." and has 2 chars */
+ name[0] = path[0];
+ }
+ else
+ name[0] = _getdrive() + 'A' - 1;
+
+ strcpy(name+1, ":\\");
+ }
+
+ if (GetVolumeInformation(name, volname, 256, &sernum, &maxcomplen,
+ &fsflags, fsname, 256) == FALSE) {
+ fprintf(stderr, "Error getting volume info on %s (code %d).\n", name, GetLastError());
+ mt_exit(1);
+ }
+
+#else /* ! WIN32 */
+ if (IS_DEVICE_SEP(path[1])) { /* the shortest path is "." and has 2 chars */
+ name[0] = path[0];
+ }
+ else
+ name[0] = _getdrive() + 'A' - 1;
+
+ strcpy(name+1, ":\\");
+
+#ifdef __DJGPP__
+ fsflags = _get_volume_info(name, &maxnamelen, &maxpathlen, fsname);
+#endif
+
+#endif /* ! WIN32 */
+
+ /* FIXME: FS_CASE_IS_PRESERVED does not seem sufficient. People
+ manage to get share/texmf/FONTS/TFM/... under W95. Too bad.
+ After all, this flag distinguishes NTFS from all FATs */
+ retval = (fsflags & FS_CASE_SENSITIVE) != 0;
+
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG)) {
+ fprintf(stderr, "FS %s %s case-sensitive\n", name,
+ (retval ? "is" : "is not"));
+ }
+#endif /* MONOCASE_FILENAMES */
+
+ return retval;
+}
+
+/* Set FILE to have the same permissions as directory DIR, minus the bits
+ masked off by MASK.
+ This emulates "chmod `kpsestat -xst,go-w $DIR` FILE". */
+
+int chmod_as_dir(string file, const string dir, mode_t mask)
+{
+ struct stat st_buf;
+
+ if (stat (dir, &st_buf) == 0)
+ return chmod (file, st_buf.st_mode & mask);
+ return -1;
+}
+
+void do_mktexlsr(string path)
+{
+ static char name[PATH_MAX];
+#ifdef __DJGPP__
+ /* `stat' can be very expensive on MS-DOS, and `recurse_dir'
+ uses it a lot. Make it work as fast as we possibly can afford. */
+ unsigned short save_stat_bits = _djstat_flags;
+ _djstat_flags = (_STAT_WRITEBIT | _STAT_ROOT_TIME | _STAT_DIRSIZE |
+ _STAT_EXEC_MAGIC | _STAT_EXEC_EXT);
+#endif
+
+ if (KPSE_DEBUG_P(MKTEX_DEBUG)) {
+ fprintf(stderr, "Building ls-R database in: %s\n", path);
+ }
+
+ downcase_names = ! is_casesensitive(path);
+
+ strcpy(name,path);
+ recurse_dir(name, print_path, NULL);
+#ifdef __DJGPP__
+ _djstat_flags = save_stat_bits;
+#endif
+}
+
+#if !defined(S_IFLNK) && !defined(S_ISLNK)
+
+/* Dummy version of `readlink' for systems which don't support links. */
+int readlink(const char *path, char *buf, int bufsize)
+{
+ return -1;
+}
+
+#endif
+
+int mktexlsr(int argc, char **argv)
+{
+ /* We have to take multiple root trees into account. */
+
+ string db_dir, db_file, lsrdir;
+ char db_dir_tmp[PATH_MAX];
+ char db_file_tmp[PATH_MAX];
+ FILE* lsrfile;
+ int newfd[3];
+ char **newargv;
+ int i;
+
+ if (argc == 1) {
+ newargv = (char **) malloc(2 * sizeof(char *));
+ newargv[0] = argv[0];
+ /* This should give us the ls-R default path */
+ if (!kpse_format_info[kpse_db_format].type) /* needed if arg was numeric */
+ kpse_init_format (kpse_db_format);
+ newargv[1] = xstrdup(kpse_format_info[kpse_db_format].path);
+ argc = 2;
+ }
+ else {
+ newargv = (char **) malloc(argc * sizeof(char *));
+ for (i = 0; i < argc; i++)
+ newargv[i] = argv[i];
+ }
+
+ /* For each argument in the list */
+ for (i = 1; i < argc; i++) {
+ for (lsrdir = kpse_path_element(newargv[i]);
+ lsrdir;
+ lsrdir = kpse_path_element(NULL)) {
+ char symlink[PATH_MAX];
+ int symlink_len;
+
+ /* We need to skip !! */
+ if (lsrdir && *lsrdir == '!' && *(lsrdir+1) == '!')
+ lsrdir +=2;
+ /* Skip empty path components. */
+ if (*lsrdir == 0)
+ continue;
+ /* FIXME : /local/tex is absolute under win32, but should it really be ? */
+ if (!kpse_absolute_p(lsrdir, FALSE))
+ lsrdir = concat_pathes(getval("KPSE_DOT"), lsrdir);
+
+ /* Follow a possible symlink to get the right filesystem. */
+ db_file = concat_pathes(lsrdir, "ls-R");
+ if ((symlink_len = readlink(db_file, symlink, PATH_MAX)) != -1) {
+ string new_db_file = xmalloc(symlink_len + 1);
+
+ strncpy(new_db_file, symlink, symlink_len);
+ new_db_file[symlink_len] = '\0';
+ if (!kpse_absolute_p(new_db_file, false)) {
+ string tem = concat_pathes(lsrdir, new_db_file);
+ free(new_db_file);
+ new_db_file = tem;
+ }
+ }
+ db_dir = xdirname(db_file);
+
+ if (!test_file('d', db_dir)) {
+ fprintf(stderr, "%s: %s is not a directory. Skipping...\n",
+ progname, db_dir);
+ continue;
+ }
+
+ if (!test_file('w', db_dir)) {
+ fprintf(stderr, "%s: %s: directory not writable. Skipping...\n",
+ progname, db_dir);
+ continue;
+ }
+
+ sprintf(db_dir_tmp, "%s/lsXXXXXX", db_dir);
+ if (mktemp(db_dir_tmp) == NULL) {
+ perror(db_dir_tmp);
+ mt_exit(1);
+ }
+ if (mkdir(db_dir_tmp, 0777 & ~umask(0)) == -1) {
+ fprintf(stderr, "%s: could not create directory '%s'. Skipping...\n");
+ continue;
+ }
+
+ sprintf(db_file_tmp, "%s/lsXXXXXX", db_dir_tmp);
+ if (mktemp(db_file_tmp) == NULL) {
+ perror(db_file_tmp);
+ mt_exit(1);
+ }
+
+ if ((lsrfile = fopen(db_file_tmp, "wb")) == NULL) {
+ fprintf(stderr, "%s: %s: no write permission. Skipping...\n",
+ progname, db_file_tmp);
+ continue;
+ }
+ if (!is_writable(db_file) && errno != ENOENT) {
+ fprintf(stderr, "%s: %s: no write permission. Skipping...\n",
+ progname, db_file);
+ continue;
+ }
+
+ if (isatty(fileno(stdout)))
+ fprintf(stderr, "%s: Updating %s...\n", progname, db_file);
+
+ newfd[0] = 0;
+ newfd[1] = fileno(lsrfile);
+ newfd[2] = 2;
+ push_fd(newfd);
+
+ puts(getval("ls_R_magic"));
+ fputs("/dev/null", stdout); /* like `ls -R' does */
+ putchar('\n');
+
+ /* Record the info about the temporary file, so we don't enter
+ it into the database. */
+ tem_file_info.tem_dir = ".";
+ tem_file_info.tem_base = xbasename(db_file_tmp);
+ tem_file_info.lsr_base = db_dir;
+
+ pushd(db_dir);
+ do_mktexlsr(".");
+
+ popd(); /* back to tmpdir */
+ /* Restore original stdout */
+ pop_fd();
+
+ fflush(stdout);
+ fclose(lsrfile);
+
+ /* Use same permissions as parent directory, minus x, s, or t bits,
+ but plus writeable bits for those who can read it. */
+ {
+ struct stat stbuf;
+
+ if (stat(db_dir, &stbuf) == 0) {
+ if ((stbuf.st_mode & S_IRUSR) != 0)
+ stbuf.st_mode |= S_IWUSR;
+ if ((stbuf.st_mode & S_IRGRP) != 0)
+ stbuf.st_mode |= S_IWGRP;
+ if ((stbuf.st_mode & S_IROTH) != 0)
+ stbuf.st_mode |= S_IWOTH;
+ chmod (db_file_tmp, stbuf.st_mode & 00666);
+ }
+ }
+
+ /* Forget about this temporary file. */
+ tem_file_info.tem_dir = 0;
+ tem_file_info.tem_base = 0;
+
+ if (mvfile(db_file_tmp, db_file) == FALSE) {
+ mt_exit(1);
+ }
+
+ do_rmdir(db_dir_tmp);
+
+ free(db_file);
+ }
+ }
+ free(newargv);
+
+ hash_reinit();
+
+ if (isatty(fileno(stdout)))
+ fprintf(stderr, "%s: Done.\n", progname);
+ return 0;
+}
+
+/* Find namepart for font name in the TDS structure. */
+void findmap()
+{
+ FILE *f;
+ string line;
+ string token;
+ string filename;
+ string name = getval("NAME"), noraw_name;
+
+ /* Raw font */
+ if (name && *name == 'r')
+ name = name+1;
+
+ filename = getval("MT_SPECIALMAP");
+ if (!test_file('r', filename))
+ return;
+
+ f = fopen(filename, FOPEN_R_MODE);
+ if (f == NULL) {
+ perror(filename);
+ return;
+ }
+
+ /* FIXME : there is a seg fault if the font is not found here */
+ /* Is it ok ? 03/02/97 ;.. */
+ while((line = read_line(f)) != NULL) {
+ token = strtok(line, SEPARATORS);
+ if (!token || !*token)
+ continue;
+
+ if (FILESTRCASEEQ(token, name)
+ || (FILESTRNCASEEQ(token, name, strlen(token))
+ && isdigit(name[strlen(name)-1])
+ && !isdigit(token[strlen(token)-1]))) {
+ setval("SUPPLIER", xstrdup(strtok(NULL, SEPARATORS)));
+ setval("TYPEFACE", xstrdup(strtok(NULL, SEPARATORS)));
+ free(line);
+ break;
+ }
+ else
+ free(line);
+ }
+
+ if (test_file('z', getval("SUPPLIER"))) {
+ string s_abbrev = xstrdup(" ");
+ /* $NAME might be raw */
+ noraw_name = (name[0] == 'r' ? name + 1 : name);
+ s_abbrev[0] = noraw_name[0];
+ setval("s_abbrev", s_abbrev);
+ filename = getval("MT_SUPPLIERMAP");
+ if (test_file('z', filename)) {
+ fprintf(stderr, "%s: %s: No such file or directory\n",
+ progname, filename ? filename : empty_str);
+ return;
+ }
+ f = freopen(filename, FOPEN_R_MODE, f);
+ if (f == NULL) {
+ perror(filename);
+ return ;
+ }
+
+ while((line = read_line(f)) != NULL) {
+ token = strtok(line, SEPARATORS);
+ if (FILECHARCASEEQ(*token, *s_abbrev) && token[1] == '\0') {
+ setval("SUPPLIER", xstrdup(strtok(NULL, SEPARATORS)));
+ free(line);
+ break;
+ }
+ else
+ free(line);
+ }
+
+ if (test_file('n', getval("SUPPLIER"))) {
+ string t_abbrev = xmalloc (3);
+
+ t_abbrev[0] = '\0';
+ strncat (t_abbrev, noraw_name + 1, 2);
+ setval("t_abbrev", t_abbrev);
+ filename = getval("MT_TYPEFACEMAP");
+ if (test_file('z', filename)) {
+ fprintf(stderr, "%s: %s: No such file or directory\n",
+ progname, filename ? filename : empty_str);
+ return;
+ }
+ f = freopen(filename, FOPEN_R_MODE, f);
+ if (f == NULL) {
+ perror(filename);
+ return;
+ }
+
+ while((line = read_line(f)) != NULL) {
+ token = strtok(line, SEPARATORS);
+ if ((strlen(token) == 2)
+ && (t_abbrev[1] == token[0]) && (t_abbrev[2] == token[1])) {
+ setval("TYPEFACE", xstrdup(strtok(NULL, SEPARATORS)));
+ free(line);
+ break;
+ }
+ else
+ free(line);
+ }
+ }
+ }
+
+ free(filename);
+ fclose(f);
+
+ if (KPSE_DEBUG_P(MKTEX_DEBUG)) {
+ fprintf(stderr, "Font %s has supplier %s and typeface %s.\n",
+ getval("NAME"),
+ getval("SUPPLIER") ? getval("SUPPLIER") : empty_str,
+ getval("TYPEFACE") ? getval("TYPEFACE") : empty_str);
+ }
+
+}
+
+
+/* Test if two pathes are equal. Up to the shortest one. */
+boolean path_included(const_string p1, const_string p2)
+{
+ boolean ret = true;
+
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG)) {
+ fprintf(stderr, "Path %s included in %s: ",
+ p1, p2);
+ }
+
+ for( ; *p1 && *p2 && ret; p1++, p2++)
+ ret = ret && (IS_DIR_SEP(*p1) ? IS_DIR_SEP(*p2) :
+ FILECHARCASEEQ(*p1, *p2));
+
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG)) {
+ fprintf(stderr, "%s\n", (ret ? "true": "false"));
+ }
+
+ return ret;
+}
+
+/* return the path element in path which can match dir else NULL */
+string path_in_pathes(const_string dir, const_string path)
+{
+ string ret = NULL;
+ string elt;
+ string pathcpy = xstrdup(path);
+ /* FIXME : why is it necessary to dup it ? */
+ string dircpy = xstrdup(dir);
+
+ for (elt = kpse_path_element (pathcpy);
+ elt && !ret;
+ elt = kpse_path_element (NULL)) {
+ /* Not sufficient to have both equal, there should be a DIR_SEP
+ on the next char of dir */
+ if (path_included(elt, dircpy) &&
+ (IS_DIR_SEP(*(dir+strlen(elt)))
+ || (strlen(dircpy) == strlen(elt))))
+ ret = xstrdup(elt);
+ }
+
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG)) {
+ fprintf(stderr, "Path %s searched for %s => %s.\n",
+ path, dircpy, ret);
+ }
+ free(pathcpy);
+ free(dircpy);
+ return ret;
+
+}
+
+
+/*
+ Split a .mf name into root part and point size part.
+ Root and point size are optional (may be NULL).
+ */
+void split_mf_name(string name, string *base, string *root, string *ptsize)
+{
+ string p, q;
+ /* name = basename $1 .mf */
+ p = my_basename(name, ".mf");
+ if (base)
+ *base = xstrdup(p);
+ /* rootname = `echo $name | sed 's/[0-9]*$//'` */
+ for (q = p + strlen(p); q > p && isdigit(q[-1]); q--);
+ /* ptsize = `echo $name | sed 's/^$rootname//'` */
+ if (ptsize)
+ *ptsize = xstrdup(q);
+ *q = '\0';
+ if (root)
+ *root = p;
+ else
+ free(p);
+}
+
+string find_sauter(string name, string *rootname)
+{
+ string root, sauter_name, res;
+ split_mf_name(name, NULL, &root, NULL);
+ sauter_name = concat("b-", root);
+ res = kpse_find_file(sauter_name, kpse_mf_format, false);
+ if (rootname)
+ *rootname = root;
+ else
+ free(root);
+ free(sauter_name);
+ return res;
+}
+
+/* Return non-zero iff FEATURE is included in $MT_FEATURES. */
+int feature_p(const char *feature)
+{
+ string mt_features = getval("MT_FEATURES");
+ char *p = strstr(mt_features, feature);
+ int next_char = p ? p[strlen(feature)] : 0;
+
+ if (p && (p == mt_features || p[-1] == ':')
+ && (next_char == ':' || next_char == '\0'))
+ return 1;
+ return 0;
+}
+
+void mktexnam_opt()
+{
+ string mtn_opt;
+
+ /* FIXME: we don't support edited mktexnam.opt files. */
+ if (feature_p("dosnames"))
+ setval("MT_PKBASE", "dpi$DPI/${NAME}.pk");
+
+ if (feature_p("nomode"))
+ setval("MODE", "");
+
+ /* This is to avoid running the code below if $TEXMF and/or
+ $TEXMFMAIN are set incorrectly. The code below cannot
+ cope with that situation. (The scripts do not call
+ mktexnam.opt in such a case, either.) */
+ mtn_opt = kpse_find_file ("mktexnam.opt", kpse_web2c_format, false);
+ if (!mtn_opt || !*mtn_opt)
+ return;
+
+ if (feature_p("fontmaps")) {
+ setval("MT_NAMEPART", "$MT_SUPPLIER/$MT_TYPEFACE");
+ setval("MT_PKDESTREL", "pk/$MT_MODE/$MT_NAMEPART");
+ setval("MT_TFMDESTREL", "tfm/$MT_NAMEPART");
+ setval("MT_MFDESTREL", "source/$MT_NAMEPART");
+ setval_default("MT_SPECIALMAP",
+ kpse_find_file("special.map", kpse_fontmap_format, false));
+ setval_default("MT_TYPEFACEMAP",
+ kpse_find_file("typeface.map", kpse_fontmap_format, false));
+ setval_default("MT_SUPPLIERMAP",
+ kpse_find_file("supplier.map", kpse_fontmap_format, false));
+
+ if (test_file('z', getval("MT_SUPPLIER"))
+ || test_file('z', getval("MT_TYPEFACE"))
+ || STREQ(getval("MT_SUPPLIER"), "unknown")
+ || STREQ(getval("MT_SUPPLIER"), "unknown")) {
+
+ findmap();
+
+ if (test_file('z', getval("SUPPLIER"))) {
+ fprintf(stderr, "%s: Could not map source abbreviation %s for %s.\n",
+ progname,
+ getval("s_abbrev") ? getval("s_abbrev") : empty_str,
+ getval("NAME"));
+ if (test_file('n', getval("MT_SPECIALMAP")))
+ fprintf(stderr, "%s: Need to update %s?\n",
+ progname, getval("MT_SPECIALMAP"));
+ else
+ fprintf(stderr, "%s: $MT_SPECIALMAP not found!\n", progname);
+ /* setval("MT_SUPPLIER", getval("MT_DEFAULT_SUPPLIER")); */
+ /* setval("MT_TYPEFACE", getval("MT_DEFAULT_TYPEFACE")); */
+ }
+ else {
+ setval("MT_SUPPLIER", getval("SUPPLIER"));
+ if (test_file('z', getval("TYPEFACE"))) {
+ fprintf(stderr, "%s: Could not map typeface abbreviation %s for %s.\n",
+ progname,
+ getval("t_abbrev") ? getval("t_abbrev") : empty_str,
+ getval("NAME"));
+ if (test_file('n', getval("MT_SPECIALMAP")))
+ fprintf(stderr, "%s: Need to update %s?\n",
+ progname, getval("MT_SPECIALMAP"));
+ else
+ fprintf(stderr, "%s: $MT_SPECIALMAP not found!\n", progname);
+ /* setval("MT_TYPEFACE", getval("MT_DEFAULT_TYPEFACE")); */
+ }
+ else
+ setval("MT_TYPEFACE", getval("TYPEFACE"));
+ }
+ }
+ }
+
+ if (feature_p("stripsupplier"))
+ setval("MT_SUPPLIER", "");
+
+ if (feature_p("striptypeface"))
+ setval("MT_TYPEFACE", "");
+
+ if (feature_p("varfonts"))
+ /* atoi is undefined for empty arguments, so test explicitly. */
+ if (test_file('z', (getval("USE_VARTEXFONTS")))
+ || atoi(getval("USE_VARTEXFONTS")) != 0)
+ setval("USE_VARTEXFONTS", "1");
+}
+
+void do_mktexnames(string name)
+{
+ string fullname, rootname, i;
+ string stdfontpath, relfmt, namepart;
+ string *vars;
+ string s_dest;
+ int use_alternate = 0;
+
+ setval("NAME", name);
+ setval_default("MT_PKDESTDIR", "$MT_DESTROOT/$MT_PKDESTREL");
+ setval_default("MT_TFMDESTDIR", "$MT_DESTROOT/$MT_TFMDESTREL");
+ setval_default("MT_MFDESTDIR", "$MT_DESTROOT/$MT_MFDESTREL");
+ setval_default("MT_PKBASE", "$NAME.${DPI}pk");
+ setval_default("MT_TFMBASE", "$NAME.tfm");
+ setval_default("MT_MFBASE", "$NAME.mf");
+ setval_default("MT_DEFAULT_SUPPLIER", "unknown");
+ setval_default("MT_DEFAULT_TYPEFACE", "unknown");
+ setval_default("MT_DEFAULT_NAMEPART", "$MT_SUPPLIER/$MT_TYPEFACE");
+ setval_default("MT_DEFAULT_PKDESTREL", "pk/modeless/$MT_NAMEPART");
+ setval_default("MT_DEFAULT_TFMDESTREL", "tfm/$MT_NAMEPART");
+ setval_default("MT_DEFAULT_MFDESTREL", "source/$MT_NAMEPART");
+ setval_default("MT_DEFAULT_DESTROOT", getval("KPSE_DOT"));
+
+ /* Looking for $name.tfm */
+ fullname = kpse_find_file(name, kpse_tfm_format, false);
+ if (test_file('z', fullname)) {
+ /* If tfm not found, looking for $name.mf */
+ fullname = kpse_find_file(name, kpse_mf_format, false);
+ if (test_file('z', fullname)) {
+ /* Try Sauter font */
+ fullname = find_sauter(name, &rootname);
+ if (test_file('z', fullname)) {
+ if (FILESTRNCASEEQ(rootname, "cs", 2)
+ || FILESTRNCASEEQ(rootname, "lcsss", 5)
+ || FILESTRNCASEEQ(rootname, "icscsc", 6)
+ || FILESTRNCASEEQ(rootname, "icstt", 5)
+ || FILESTRNCASEEQ(rootname, "ilcsss", 6)
+ ) {
+ fullname = kpse_find_file("cscode.mf", kpse_mf_format, false);
+ }
+ else if (strlen(rootname) >= 3
+ && ((FILESTRNCASEEQ(rootname, "wn", 2)
+ && strchr("bBcCdDfFiIrRsStTuUvV", rootname[2]))
+ || (FILESTRNCASEEQ(rootname, "rx", 2)
+ && strchr("bBcCdDfFiIoOrRsStTuUvVxX", rootname[2])
+ && strlen(rootname) >= 4
+ && strchr("bBcCfFhHiIlLmMoOsStTxX", rootname[3]))
+ || ((rootname[0] == 'l' || rootname[0] == 'L')
+ && strchr("aAbBcCdDhHlL", rootname[1])
+ && strchr("bBcCdDfFiIoOrRsStTuUvVxX", rootname[2])))) {
+ char lhname[64];
+ strcpy(lhname, "xxcodes.mf");
+ strncpy(lhname, name, 2);
+ fullname = kpse_find_file(lhname, kpse_mf_format, false);
+ }
+ else {
+ fullname = kpse_find_file(rootname, kpse_mf_format, false);
+ }
+ }
+ }
+ }
+
+ if (test_file('z', fullname)) {
+ /* Moved on 99/04/29
+ setval("MT_FEATURES", concat(getval("MT_FEATURES"), ":fontmaps")); */
+ setval_default("MT_DESTROOT", getval("MT_VARTEXFONTS"));
+ }
+ else {
+ /* Normalize fullname */
+ normalize(fullname);
+ stdfontpath = kpse_path_expand(concat3(("$TEXMF/fonts"),
+ ENV_SEP_STRING,
+ "$MT_VARTEXFONTS"));
+ /* FIXME : what about if fullname is not in stdfontpath ?
+ For example: fullname is absolute ... */
+ if (test_file('n', i = path_in_pathes(fullname, stdfontpath))) {
+ /* We now have a preliminary value for the destination root.
+ MT_DESTROOT="$i"
+ */
+ setval_default("MT_DESTROOT", i);
+ /*
+ # When we're done, relfmt contains one of these:
+ # "/source/$MT_NAMEPART/"
+ # "/$MT_NAMEPART/source/"
+ # while namepart contains the actual namepart.
+ */
+ relfmt = xstrdup(fullname);
+ /* should match in lower cases letters if fs is case insensitive */
+ if (!is_casesensitive(relfmt)) {
+ string p = string_to_lower(relfmt);
+ string q = string_to_lower(i);
+ /* remove the 'i' part and the name */
+ vars = grep(concatn("^", q, "(/.*/)[^/]*$", NULL), p, 1);
+ }
+ else {
+ /* remove the 'i' part and the name */
+ vars = grep(concatn("^", i, "(/.*/)[^/]*$", NULL), relfmt, 1);
+ }
+ if (vars) {
+ free(relfmt);
+ relfmt = xstrdup(vars[1]);
+ free(vars);
+ }
+ else {
+ /* grep failed. Shouldn't happen. */
+ relfmt = xstrdup("");
+ }
+
+ {
+ string res = "";
+ size_t l_relfmt = strlen(relfmt);
+
+ namepart = NULL;
+
+ /* sed -e 's%^/tfm/%/source/%' */
+ if (FILESTRNCASEEQ(relfmt, "/tfm/", 5)) {
+ res = concat("/source/", relfmt + 5);
+ namepart = concat ("/", relfmt+5);
+ free(relfmt);
+ relfmt = res;
+ }
+ /* sed -e 's%/tfm/$%/source/%' */
+ else if (l_relfmt >= 5
+ && FILESTRCASEEQ(relfmt + l_relfmt - 5, "/tfm/")) {
+ relfmt[l_relfmt - 4] = '\0';
+ res = concat(relfmt, "/source/");
+ namepart = concat(relfmt, "/");
+ free(relfmt);
+ relfmt = res;
+ }
+ /* namepart=`echo "$relfmt" | sed -e 's%/source/%/%'` */
+ /*
+ This should be almost done by now. I assume the scripts not
+ to be strict enough. IE: /tfm/ can occur only once in the name.
+ That's why the 'else if' instead of 'if'.
+ */
+ else {
+ /* namepart is unset by now */
+ namepart = subst(relfmt, "/source/", "/");
+ }
+
+ /* See if namepart is empty. */
+ if (test_file('n', namepart) && strcmp(namepart, "/") != 0) {
+ res = subst(relfmt, namepart, "/$MT_NAMEPART/");
+ free(relfmt);
+ relfmt = res;
+ }
+ else {
+ /* Assume TDS */
+ free(relfmt);
+ relfmt = xstrdup("/source/$MT_NAMEPART/");
+ namepart = "";
+ }
+ }
+
+ /* Determine supplier and typeface from namepart. If there is
+ only one part in the name part, we take it to be the typeface.
+ */
+ vars = grep("^/([^/]*)/([^/]*)[/]?$", namepart, 2);
+ if (vars) {
+ if (vars[2] == NULL || *vars[2] == '\0') {
+ setval("MT_TYPEFACE", xstrdup(vars[1]));
+ setval("MT_SUPPLIER", "");
+ }
+ else {
+ setval("MT_TYPEFACE", xstrdup(vars[2]));
+ setval("MT_SUPPLIER", xstrdup(vars[1]));
+ }
+ free(vars[1]);
+ if (vars[2]) free(vars[2]);
+ free(vars);
+ }
+ else {
+ setval("MT_TYPEFACE", namepart);
+ setval("MT_SUPPLIER", namepart);
+ }
+ /*
+ Phew. Now we create the relative paths for pk, tfm and source.
+ */
+ setval_default("MT_NAMEPART", "$MT_SUPPLIER/$MT_TYPEFACE");
+ setval_default("MT_PKDESTREL", subst(relfmt, "/source/", "/pk/$MT_MODE/"));
+ setval_default("MT_TFMDESTREL", subst(relfmt, "/source/", "/tfm/"));
+ setval_default("MT_MFDESTREL", relfmt);
+ }
+ } /* FIXME: if fullname is absolute, path_in_pathes will fail */
+ /*
+ In case some variables remain unset
+ */
+ /* setval_default("MT_DESTROOT", getval("MT_DEFAULT_DESTROOT")); */
+ setval_default("MT_SUPPLIER", getval("MT_DEFAULT_SUPPLIER"));
+ setval_default("MT_TYPEFACE", getval("MT_DEFAULT_TYPEFACE"));
+ setval_default("MT_NAMEPART", getval("MT_DEFAULT_NAMEPART"));
+ setval_default("MT_PKDESTREL", getval("MT_DEFAULT_PKDESTREL"));
+ setval_default("MT_TFMDESTREL", getval("MT_DEFAULT_TFMDESTREL"));
+ setval_default("MT_MFDESTREL", getval("MT_DEFAULT_MFDESTREL"));
+
+ /* We have found nothing, so force using the fontmaps as a last resort.
+ This also means mktexnam can be queried for advice on where to
+ place fonts. */
+ if (STREQ(getval("MT_SUPPLIER"), "unknown")
+ || STREQ(getval("MT_TYPEFACE"), "unknown")) {
+ setval_default("MT_FEATURES", concat(getval("MT_FEATURES"), ":fontmaps"));
+ }
+
+ /* Handle the options */
+ mktexnam_opt();
+
+ /* # Adjust MT_DESTROOT, if necessary. */
+ if (test_file('n', expand_var("$MT_DESTROOT"))) {
+ string systexmf;
+ /* # Do we have write access and permission? */
+ if (!test_file('w', expand_var("$MT_DESTROOT")))
+ use_alternate = 1;
+ /* # We distinguish system trees from the rest. */
+ systexmf = concat3(kpse_path_expand("{$SYSTEXMF}/fonts"),
+ ENV_SEP_STRING,
+ getval("MT_VARTEXFONTS"));
+ i = path_in_pathes(expand_var("$MT_DESTROOT"), systexmf);
+
+ if (test_file('n', i) && FILESTRCASEEQ(expand_var("$MT_DESTROOT"), i)) {
+ if ((test_file('n', (getval("USE_VARTEXFONTS")))
+ && STREQ(getval("USE_VARTEXFONTS"),"1"))
+ || use_alternate) {
+ setval("MT_DESTROOT", getval("MT_VARTEXFONTS"));
+ }
+ }
+ /* else $MT_DESTROOT stays put. */
+ else if (use_alternate)
+ setval("MT_DESTROOT", "");
+ }
+
+ if (test_file('z', expand_var("$MT_DESTROOT"))) {
+ string default_dest_root = expand_var("$MT_DEFAULT_DESTROOT");
+ setval("MT_DESTROOT", default_dest_root);
+ setval("MT_PKDESTDIR", default_dest_root);
+ setval("MT_TFMDESTDIR", default_dest_root);
+ setval("MT_MFDESTDIR", default_dest_root);
+ }
+
+ s_dest = expand_var("$DEST");
+ if (test_file('n', s_dest))
+ if (kpse_absolute_p(s_dest, false)) {
+ setval("MT_PKDESTDIR", s_dest);
+ setval("MT_TFMDESTDIR", s_dest);
+ setval("MT_MFDESTDIR", s_dest);
+ setval("MT_NAMEPART", "");
+ }
+ else
+ setval("MT_NAMEPART", s_dest);
+
+ setval ("MT_MODE", expand_var("$MODE"));
+ setval ("MT_NAMEPART", expand_var("$MT_NAMEPART"));
+ setval ("MT_DESTROOT", expand_var("$MT_DESTROOT"));
+ setval ("MT_PKDESTREL", expand_var("$MT_PKDESTREL"));
+ setval ("MT_TFMDESTREL", expand_var("$MT_TFMDESTREL"));
+ setval ("MT_MFDESTREL", expand_var("$MT_MFDESTREL"));
+ setval ("MT_PKDESTDIR", expand_var("$MT_PKDESTDIR"));
+ setval ("MT_TFMDESTDIR", expand_var("$MT_TFMDESTDIR"));
+ setval ("MT_MFDESTDIR", expand_var("$MT_MFDESTDIR"));
+ s_dest = setval ("MT_PKNAME", expand_var(concat_pathes(getval("MT_PKDESTDIR"),
+ getval("MT_PKBASE"))));
+ /* When "dosnames" is in effect, MT_PKDESTDIR should include "/dpiNNN". */
+ if (feature_p("dosnames")) {
+ string p = xdirname(s_dest);
+
+ setval ("MT_PKDESTDIR", p);
+ }
+ setval ("MT_TFMNAME", expand_var(concat_pathes(getval("MT_TFMDESTDIR"),
+ getval("MT_TFMBASE"))));
+ setval ("MT_MFNAME", expand_var(concat_pathes(getval("MT_MFDESTDIR"),
+ getval("MT_MFBASE"))));
+}
+
+int mktexnames(int argc, char **argv)
+{
+ string name = argv[1];
+
+ argc--; argv++; /* We are eliminating argv[0] */
+ if (argc <= 2) {
+ setval("DPI", getval("BDPI"));
+ if (argc == 2)
+ setval("DEST", argv[1]);
+ }
+ else if (argc < 5) {
+ setval("DPI", argv[1]);
+ setval("MODE", argv[2]);
+ if (argc == 4)
+ setval("DEST", argv[3]);
+ }
+
+ do_mktexnames(name);
+
+ printf("%s%s%s%s%s\n", normalize(getval("MT_PKNAME")), ENV_SEP_STRING,
+ normalize(getval("MT_TFMNAME")), ENV_SEP_STRING,
+ normalize(getval("MT_MFNAME")));
+ return 0;
+}
+
+int mktexmkdir(int argc, char **argv)
+{
+ int i;
+ string path;
+
+ mt_append_mask = 0;
+
+ /* FIXME: we don't support edited mktexdir.opt files! */
+ if (feature_p("appendonlydir"))
+ /* Set append-only bit on created directories. */
+ mt_append_mask = 01000; /* MT_APPEND_MASK=+t;; */
+
+ for(i = 1; i < argc; i++) {
+ /* We have to concat the original wd if argv[i] is not absolute */
+ if (kpse_absolute_p(argv[i], false))
+ errstatus = do_makedir(argv[i]) != 0;
+ else {
+ /* original dir is the zeroth directory in the env stack */
+ path = concat_pathes(peek_dir(0), argv[i]);
+ errstatus = do_makedir(path) != 0;
+ free(path);
+ }
+ }
+ return errstatus;
+}
+int mktexrmdir(int argc, char **argv)
+{
+ int i;
+
+ for(i = 1; i < argc; i++) {
+ do_rmdir(argv[i]);
+ }
+ return 0;
+}
+
+void do_mktexupdate(string dir, char *name)
+{
+ string lsrdir, relative_dir, dirname;
+ string elt, db_file, line;
+ FILE *f;
+
+ if (KPSE_DEBUG_P(MKTEX_DEBUG)) {
+ fprintf(stderr, "Mktexupd adds %s in %s\n", name, dir);
+ }
+
+ normalize(dir);
+
+ if (!test_file('d', dir)) {
+ fprintf(stderr, "%s: %s not a directory.\n", progname,
+ test_file('n', dir) ? dir : empty_str);
+ mt_exit(1);
+ }
+ if (!test_file('f', lsrdir = concat_pathes(dir, name))) {
+ fprintf(stderr, "%s: %s not a file.\n", progname,
+ test_file('n', lsrdir) ? lsrdir : empty_str);
+ mt_exit(1);
+ }
+
+ /* update the current db too ! */
+ dirname = concat_pathes(dir, name);
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG)) {
+ fprintf(stderr, "Inserting `%s' into current db\n", dirname);
+ }
+ kpse_db_insert(dirname);
+ free(dirname);
+
+ /* This should give us the ls-R default path */
+ if (!kpse_format_info[kpse_db_format].type) /* needed if arg was numeric */
+ kpse_init_format (kpse_db_format);
+
+ lsrdir = normalize(xstrdup(kpse_format_info[kpse_db_format].path));
+
+ setval("TEXMFLS_R", "");
+ /* For each argument in the list */
+ for (elt = kpse_path_element(lsrdir);
+ elt;
+ elt = kpse_path_element(NULL)) {
+ if (*elt
+ && FILESTRNCASEEQ(dir, elt, strlen(elt))) {
+ free(lsrdir);
+ setval("TEXMFLS_R", lsrdir = xstrdup(elt));
+ break;
+ }
+ }
+ if (!test_file('n', getval("TEXMFLS_R")))
+ /* just return, it is call by other functions than mktexupd() */
+ return;
+ db_file = concat_pathes(lsrdir, "ls-R");
+
+ if (!test_file('f', db_file)) {
+ char *mtlsr_argv[3];
+
+ mtlsr_argv[0] = "mktexlsr";
+ mtlsr_argv[1] = lsrdir;
+ mtlsr_argv[2] = NULL;
+ mktexlsr(2, mtlsr_argv);
+ }
+ if(!test_file('w', db_file)) {
+ fprintf(stderr, "%s: %s unwritable.\n", progname, db_file);
+ mt_exit(1);
+ }
+ if ((f = fopen(db_file, "r+b")) == NULL) {
+ fprintf(stderr, "%s: can't open %s.\n", progname, db_file);
+ mt_exit(1);
+ }
+ if ((line = read_line(f)) == NULL
+ || (strcmp(line, getval("ls_R_magic"))
+ && strcmp(line, getval("old_ls_R_magic")))) {
+ fprintf(stderr, "%s: %s lacks magic string `%s'.\n", progname, db_file,
+ getval("ls_R_magic"));
+ mt_exit(1);
+ }
+ free(line);
+
+ /* does the fs preserve case ? */
+ if (!is_casesensitive(dir)) {
+ string p;
+ for(p = dir; *p; p++)
+ *p = TOLOWER(*p);
+ for(p = name; *p; p++)
+ *p = TOLOWER(*p);
+ }
+ /* Change `$TEXMFLS_R/' to `./'. */
+ if (FILESTRNCASEEQ(dir, lsrdir, strlen(lsrdir)))
+ relative_dir = concat_pathes("./", dir + strlen(lsrdir));
+ else
+ relative_dir = xstrdup(dir);
+ fseek(f, 0L, SEEK_END);
+ fprintf(f, "%s:\n%s\n", relative_dir, name);
+ /* fputs(dir, f); fputs(":\n", f);
+ fputs(name, f); fputc('\n', f); */
+ fclose(f);
+ free(relative_dir);
+}
+
+int mktexupdate(int argc, char **argv)
+{
+ do_mktexupdate(argv[1], argv[2]);
+ return 0;
+}
+
+/* if dirname is a path that can expand into multiple directories,
+ return the first directory that exists. */
+string expand(const_string dirname)
+{
+ string path = kpse_path_expand(dirname);
+ string elt;
+
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG)) {
+ fprintf(stderr, "MktexMF (expand) <= %s\n\t <= %s\n", dirname, path);
+ }
+
+ for(elt = kpse_path_element(path);
+ elt && !test_file('d', elt);
+ elt = kpse_path_element(NULL)) {
+
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG)) {
+ fprintf(stderr, "MktexMF (expand) => %s\n", elt);
+ }
+ }
+ return (elt != NULL ? xstrdup(elt) : NULL);
+}
+
+void do_mktexmf(string font)
+{
+ string rootname, pointsize, realsize;
+ string name;
+ string mfname;
+ string gen, tmpmf, fullname;
+ string sauterroot, rootfile, destdir;
+ FILE *f;
+ size_t ptsz_len;
+
+ if (KPSE_DEBUG_P(MKTEX_DEBUG)) {
+ fprintf(stderr, "MktexMF:\n\tFONT: %s\n", font);
+ }
+
+ split_mf_name(font, &name, &rootname, &pointsize);
+
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG)) {
+ fprintf(stderr, "name = %s, rootname = %s, pointsize = %s\n",
+ name, rootname, pointsize);
+ }
+
+ sauterroot = kpse_find_file(concat3("b-", rootname, ".mf"),
+ kpse_mf_format, false);
+
+ if (test_file('n', sauterroot)) {
+ rootfile = sauterroot;
+ rootname = concat("b-", rootname);
+ }
+ else if (strlen(rootname) == 8
+ && FILESTRNCASEEQ(rootname, "csso12", 6)
+ && isdigit(rootname[6]) /* FIXME: Should be [0-5] actually */
+ && isdigit(rootname[7])) {
+ rootfile = xstrdup("");
+ }
+ else if (FILESTRNCASEEQ(rootname, "cs", 2)
+ || FILESTRNCASEEQ(rootname, "lcsss", 5)
+ || FILESTRNCASEEQ(rootname, "icscsc", 6)
+ || FILESTRNCASEEQ(rootname, "icstt", 5)
+ || FILESTRNCASEEQ(rootname, "ilcsss", 6)
+ ) {
+ rootfile = kpse_find_file("cscode.mf",
+ kpse_mf_format, false);
+ }
+ else if (strlen(rootname) >= 3
+ && ((FILESTRNCASEEQ(rootname, "wn", 2)
+ && strchr("bBcCdDfFiIrRsStTuUvV", rootname[2]))
+ || (FILESTRNCASEEQ(rootname, "rx", 2)
+ && strchr("bBcCdDfFiIoOrRsStTuUvVxX", rootname[2])
+ && strlen(rootname) >= 4
+ && strchr("bBcCfFhHiIlLmMoOsStTxX", rootname[3]))
+ || ((rootname[0] == 'l' || rootname[0] == 'L')
+ && strchr("aAbBcCdDhHlL", rootname[1])
+ && strchr("bBcCdDfFiIoOrRsStTuUvVxX", rootname[2])))) {
+ char lhprefix[64];
+ strcpy(lhprefix, "xxcodes.mf");
+ strncpy(lhprefix, name, 2);
+ rootfile = kpse_find_file(lhprefix,
+ kpse_mf_format, false);
+ }
+ else {
+ string tem;
+ rootfile = kpse_find_file(tem = concat(rootname, ".mf"),
+ kpse_mf_format, false);
+ free(tem);
+ }
+
+ if (test_file('z', rootfile)) {
+ fprintf (stderr, "%s: empty or non-existent rootfile!\n", progname);
+ mt_exit(1);
+ }
+ if (!test_file('f', rootfile)) {
+ fprintf (stderr, "%s: rootfile %s does not exist!\n", progname, rootfile);
+ mt_exit(1);
+ }
+
+ do_mktexnames(name);
+ destdir = xdirname(getval("MT_MFNAME"));
+ if (!test_file('d', destdir))
+ if (do_makedir(destdir))
+ mt_exit(1);
+
+ /* Changing directory */
+ pushd(destdir);
+
+ ptsz_len = strlen(pointsize);
+ if (ptsz_len == 0) {
+ fprintf(stderr, "%s: no pointsize.\n", progname);
+ mt_exit(1);
+ } else if (ptsz_len == 2) {
+ if (pointsize[0] == '1' && pointsize[1] == '1')
+ realsize = "10.95"; /* \magstephalf */
+ else if (pointsize[0] == '1' && pointsize[1] == '4')
+ realsize = "14.4"; /* \magstep2 */
+ else if (pointsize[0] == '1' && pointsize[1] == '7')
+ realsize = "17.28"; /* \magstep3 */
+ else if (pointsize[0] == '2' && pointsize[1] == '0')
+ realsize = "20.74"; /* \magstep4 */
+ else if (pointsize[0] == '2' && pointsize[1] == '5')
+ realsize = "24.88"; /* \magstep5 */
+ else if (pointsize[0] == '3' && pointsize[1] == '0')
+ realsize = "29.86"; /* \magstep6 */
+ else if (pointsize[0] == '3' && pointsize[1] == '6')
+ realsize = "35.83"; /* \magstep7 */
+ else
+ realsize = pointsize;
+ }
+ /* The new convention is to have three or four letters for the
+ font name and four digits for the pointsize. The number is
+ pointsize * 100. We effectively divide by 100 by inserting a
+ dot before the last two digits. */
+ else if (ptsz_len == 4 || ptsz_len == 5) {
+ /* realsize=`echo "$pointsize" | sed 's/\(..\)$/.\1/'` */
+ realsize = (string)xmalloc(ptsz_len + 2);
+ strcpy(realsize, pointsize);
+ /* The script doesn't check for last chars being digits, but we do! */
+ if (isdigit(realsize[ptsz_len-1])
+ && isdigit(realsize[ptsz_len-2])) {
+ realsize[ptsz_len+1] = '\0';
+ realsize[ptsz_len] = realsize[ptsz_len-1];
+ realsize[ptsz_len-1] = realsize[ptsz_len-2];
+ realsize[ptsz_len-2] = '.';
+ free(pointsize);
+ }
+ } else realsize = pointsize;
+
+ mfname = concat(name, ".mf");
+ if (test_file('r', mfname)) {
+ gen = normalize(concat_pathes(destdir, mfname));
+ fprintf(stderr, "%s: %s already exists.\n", progname, gen);
+ fprintf(fout, "%s\n", gen);
+ free(gen);
+ do_mktexupdate(destdir, mfname);
+ return; /* in case called by others */
+ }
+
+ /* FIXME: We have to expand fontdir and restrain it to the first
+ valid directory. */
+ tmpmf = xstrdup("mfXXXXXX");
+ if( mktemp(tmpmf) == NULL ) {
+ fprintf(stderr, "%s: can't create temp filename in %s.\n", progname,
+ destdir);
+ mt_exit(1);
+ }
+ if ((f = fopen(tmpmf, "w")) == NULL) {
+ fprintf(stderr, "%s: can't write into temp filename %s/%s.\n",
+ progname, destdir, tmpmf);
+ mt_exit(1);
+ }
+
+ if (FILESTRNCASEEQ(name, "ec", 2)
+ || FILESTRNCASEEQ(name, "tc", 2)) {
+ fprintf(f, "if unknown exbase: input exbase fi;\n");
+ fprintf(f, "gensize:=%s;\ngenerate %s;\n", realsize, rootname);
+ }
+ else if (FILESTRNCASEEQ(name, "dc", 2)) {
+ fprintf(f, "if unknown dxbase: input dxbase fi;\n");
+ fprintf(f, "gensize:=%s;\ngenerate %s;\n", realsize, rootname);
+
+ }
+ else if (FILESTRNCASEEQ(name, "cs", 2)
+ || FILESTRNCASEEQ(name, "lcsss", 5)
+ || FILESTRNCASEEQ(name, "icscsc", 6)
+ || FILESTRNCASEEQ(name, "icstt", 5)
+ || FILESTRNCASEEQ(name, "ilcsss", 6)
+ ) {
+ fprintf(f, "input cscode\nuse_driver;\n");
+ }
+ else if (strlen(name) >= 3
+ && ((FILESTRNCASEEQ(name, "wn", 2)
+ && strchr("bBcCdDfFiIrRsStTuUvV", name[2]))
+ || (FILESTRNCASEEQ(name, "rx", 2)
+ && strchr("bBcCdDfFiIoOrRsStTuUvVxX", name[2])
+ && strlen(name) >= 4
+ && strchr("bBcCfFhHiIlLmMoOsStTxX", name[3]))
+ || ((name[0] == 'l' || name[0] == 'L')
+ && strchr("aAbBcCdDhHlL", name[1])
+ && strchr("bBcCdDfFiIoOrRsStTuUvVxX", name[2])))) {
+ fprintf(f, "input fikparm;\n");
+ }
+ else if (strlen(name) >= 4 && strchr("gG", name[0])
+ && strchr("oOrRsStTlL", name[1])
+ && strchr("iIjJmMtTwWxX", name[2])
+ && strchr("cCiInNoOuU", name[3])) {
+ /* The CB font family; the test matches (case insensitively) the
+ pattern `g[lorst][ijmtwx][cinou]*'.
+ This is only slightly more general than the exact set of patterns. */
+ fprintf(f, "gensize:=%s;\ninput %s;\n", realsize, rootname);
+ }
+ else {
+ /* FIXME: this was in the previous versions */
+ /* fprintf(tmpfile, "if unknown %s: input %s fi;\n", base, base); */
+ fprintf(f, "design_size := %s;\ninput %s;\n",
+ realsize, rootname);
+ }
+ fclose(f);
+ chmod_as_dir(tmpmf, ".", 00644);
+ unlink(mfname);
+ if (mvfile(tmpmf, mfname) == FALSE) {
+ mt_exit(1);
+ }
+ setval("destdir", destdir);
+ setval("mfname", mfname);
+ fullname = normalize(concat_pathes(destdir, mfname));
+ fprintf(fout, "%s\n", fullname);
+ fprintf(stderr, "%s: %s: successfully generated.\n", progname, fullname);
+ free(fullname);
+ do_mktexupdate(destdir, mfname);
+}
+
+int mktexmf(int argc, char **argv)
+{
+ start_redirection(false);
+ do_mktexmf(argv[1]);
+ return 0;
+}
+
+void do_mktextex(const_string texname)
+{
+ string fullname, destdir;
+
+ /*
+ We may try to get this file directly from a remote repository.
+ */
+#if 0
+ fprintf(fout, "%s\n",
+ fullname = normalize(concat_pathes(destdir, texname)));
+ fprintf(stderr, "%s: %s: successfully generated.\n", progname, fullname);
+#endif
+}
+
+int mktextex(int argc, char **argv)
+{
+ start_redirection(false);
+ do_mktextex(argv[1]);
+ return 0;
+}
+
+boolean check_for_strange_path(string name)
+{
+ FILE *f;
+ string line;
+ string strange1 = "! Strange path";
+ string strange2 = "! bad pos";
+ string strange3 = "! angle(0,0) is taken as zero.";
+ boolean res = false; /* in case there are no lines which begin with `!' */
+
+ if ((f = fopen(name, "r")) == NULL) {
+ fprintf(stderr, "%s: warning: can't open log file %s.\n", progname, name);
+ return false;
+ }
+ while ((line = read_line(f)) != NULL) {
+ if (*line == '!') {
+ if (strncmp(line, strange1, strlen(strange1))
+ && strncmp(line, strange2, strlen(strange2))
+ && strncmp(line, strange3, strlen(strange3))
+ ) {
+ res = false;
+ break;
+ }
+ else if (res == false)
+ res = true; /* seen at least one ``Strange path'' message */
+ }
+ }
+ fclose(f);
+ return res;
+}
+
+
+void do_mktextfm(string font, string destdir)
+{
+ string fullname, name;
+ char tfmtempname[PATH_MAX];
+ char pktempname[PATH_MAX];
+ char cmd[256];
+ int retcode;
+
+ setval("NAME", name = my_basename(font, ".tfm"));
+ setval("MAG", "1");
+ setval("DEST", destdir);
+ setval("DPI", getval("BDPI"));
+
+ do_mktexnames(name);
+
+ setval("PKDEST", getval("MT_PKNAME"));
+ setval("TFMDEST", getval("MT_TFMNAME"));
+ setval("PKDESTDIR", getval("MT_PKDESTDIR"));
+ setval("TFMDESTDIR", getval("MT_TFMDESTDIR"));
+ setval("PKNAME", (string)xbasename(getval("MT_PKNAME")));
+ setval("TFMNAME", concat(name, ".tfm"));
+ /* FIXME: can e.g. cmr10.600gf clash with e.g. cmr10.600whatever on DOS? */
+ setval("GFNAME", concatn(name, ".", getval("DPI"), "gf", NULL));
+
+ fullname = expand_var("$TFMDESTDIR/$TFMNAME");
+ if (test_file('r', fullname)) {
+ fprintf(stderr, "%s: %s already exists.\n", progname, fullname);
+ fprintf(fout, "%s\n", fullname);
+ free(fullname);
+ do_mktexupdate(getval("TFMDESTDIR"), getval("TFMNAME"));
+ return;
+ }
+ free(fullname);
+
+ do_makedir(getval("TFMDESTDIR"));
+ if (!test_file('d', getval("TFMDESTDIR"))) {
+ fprintf(stderr, "%s: mktexdir %s failed.\n",
+ progname, getval("TFMDESTDIR"));
+ mt_exit(1);
+ }
+
+ /* Protect the semi-colons from being interpreted by the shell.
+ (Use double quotes since they are supported on non-Unix platforms.) */
+ sprintf(cmd, "mf \"\\mode:=%s; mag:=%s; nonstopmode; input %s\"",
+ getval("MODE"), getval("MAG"), getval("NAME"));
+
+ fprintf(stderr, "%s: Running %s\n", progname, cmd);
+
+ /* Now run metafont.
+ Note that stdin has been redirected to "/dev/null" by `main'. */
+ retcode = system(cmd);
+
+ if (retcode != 0) {
+ if (retcode == -1) {
+ perror(cmd);
+ mt_exit(1);
+ }
+ else if (check_for_strange_path(expand_var("$NAME.log")) == true) {
+ fprintf(stderr, "%s: warning: `%s' caused strange path errors.\n",
+ progname, cmd);
+ }
+ else {
+ struct stat statbuf;
+ fprintf(stderr, "%s: `%s' failed.\n", progname, cmd);
+ if (stat(expand_var("$NAME.log"), &statbuf) == 0
+ && statbuf.st_size > 0)
+ mvfile(expand_var("$NAME.log"),
+ concat_pathes(getval("KPSE_DOT"), expand_var("$NAME.log")));
+ mt_exit(1);
+ }
+ }
+
+ if (!test_file('r', getval("TFMNAME"))) {
+ fprintf(stderr, "%s: `%s' failed to make %s.\n",
+ progname, cmd, getval("TFMNAME"));
+ mt_exit(1);
+ }
+
+ /* Install the TFM file carefully, since others
+ may be working simultaneously. */
+ sprintf(tfmtempname, "%s/tfXXXXXX", getval("TFMDESTDIR"));
+ mktemp(tfmtempname);
+ if (mvfile(getval("TFMNAME"), tfmtempname) == FALSE) {
+ mt_exit(1);
+ }
+
+ pushd(getval("TFMDESTDIR"));
+ chmod_as_dir(tfmtempname, ".", 00644);
+ if (!test_file('r', getval("TFMNAME"))) {
+ char *tfmtmp_base = tfmtempname + strlen(getval("TFMDESTDIR")) + 1;
+
+ if (mvfile(tfmtmp_base, getval("TFMNAME")) == FALSE) {
+ mt_exit(1);
+ }
+ }
+
+ /* OK, success with the TFM. */
+ do_mktexupdate(getval("TFMDESTDIR"), getval("TFMNAME"));
+ fullname = normalize(concat_pathes(getval("TFMDESTDIR"), getval("TFMNAME")));
+ fprintf(fout, "%s\n", fullname);
+
+ fprintf(stderr, "%s: %s: successfully generated.\n", progname,
+ fullname);
+
+ /* Since we probably made a GF(->PK) file, too, may as well install
+ it if it's needed. */
+ popd(); /* Back to $TEMPDIR */
+ if (test_file('r', getval("GFNAME"))
+ && !test_file('f', concat_pathes(getval("PKDESTDIR"),
+ getval("PKNAME")))) {
+ char *pktmp_base;
+
+ sprintf(cmd, "gftopk ./%s %s", getval("GFNAME"), getval("PKNAME"));
+ if (KPSE_DEBUG_P(MKTEX_DEBUG)) {
+ fprintf(stderr, "Running: %s\n", cmd);
+ }
+ retcode = system(cmd);
+ if (retcode != 0) {
+ if (retcode == -1)
+ perror("gftopk");
+ else
+ fprintf(stderr, "%s: gftopk failed to make %s.\n",
+ progname, getval("PKNAME"));
+ mt_exit(1);
+ }
+
+ do_makedir(getval("PKDESTDIR"));
+ sprintf(pktempname, "%s/pkXXXXXX", getval("PKDESTDIR"));
+ mktemp(pktempname);
+ if (mvfile(getval("PKNAME"), pktempname) == FALSE) {
+ mt_exit(1);
+ }
+ pushd(getval("PKDESTDIR"));
+ pktmp_base = pktempname + strlen(getval("PKDESTDIR")) + 1;
+ if (test_file('f', getval("PKNAME")))
+ remove(pktmp_base);
+ else {
+ chmod_as_dir(pktmp_base, ".", 00644);
+ if (mvfile(pktmp_base, getval("PKNAME")) == FALSE) {
+ mt_exit(1);
+ }
+ do_mktexupdate(getval("PKDESTDIR"), getval("PKNAME"));
+ }
+ popd();
+ }
+}
+
+/* this is similar to mktexpk ... */
+int mktextfm(int argc, char **argv)
+{
+ string dest = getval("DEST");
+ string font = argv[1];
+
+ /* Where do potential driver files belong?
+ case "$MT_FEATURES" in
+ *nomfdrivers*)
+ : ${MT_MFDESTDIR=`pwd`}
+ export MT_MFDESTDIR;;
+ esac
+ */
+ if (feature_p("nomfdrivers")) {
+ setval_default("MT_MFDESTDIR", xgetcwd());
+ }
+
+ start_redirection(false);
+ do_mktextfm(font, dest);
+ return 0;
+}
+
+int get_mode_from_mf(string mode)
+{
+ FILE *fpipe;
+ char buf[1024];
+ int result = 0;
+
+ sprintf(buf, "mf \"\\mode:=%s;mode_setup;message\\\"BDPI= \\\"&decimal round pixels_per_inch;end.\"", mode);
+
+ /* METAFONT's stdin was redirected to /dev/null by `main'. */
+ fpipe = popen(buf, "r");
+ if (fpipe == NULL) {
+ perror("pipe to mf");
+ return 0;
+ }
+
+ /* awk '/DPI=/ {print $2}' */
+ while (fgets(buf, sizeof buf, fpipe)) {
+ char *p = strstr(buf, "DPI= ");
+ if (p)
+ result = atoi(p + 5); /* could break here, but AWK script doesn't */
+ }
+ if (pclose(fpipe))
+ perror("running mf");
+ return result;
+}
+
+/* A common lossage with stock DOS/Windows shells is that `system("foo")'
+ returns zero even though `foo' doesn't exist as an executable. A better
+ way is to say `system("foo.exe")', but that is non-portable to Unix.
+
+ Thus the need for this function. It is a no-op (always returning TRUE)
+ on Unix, but on DOS/Windows actually looks for its argument along the
+ PATH. It is assumed that on Unix, the call to `system' will fail as God
+ intended if the program is not accessible via PATH. */
+boolean find_exe(char *progname)
+{
+ char path[PATH_MAX];
+#ifdef _WIN32
+ char *fp;
+ return (SearchPath(NULL, progname, ".exe", PATH_MAX, path, &fp) != 0);
+#else
+# ifdef __DJGPP__
+ extern char * __dosexec_find_on_path (const char *, char **, char *);
+ extern char **environ;
+ return __dosexec_find_on_path (progname, environ, path) != NULL;
+# else
+ return true;
+# endif
+#endif
+}
+
+/*
+ We will read the `modes.mf' and gather the various modes.
+*/
+#define MAX_MODES 64
+
+struct mf_mode
+{
+ string mnemonic;
+ string description;
+ int hor_res;
+ int vert_res;
+};
+
+static struct mf_mode *modes;
+static int nb_modes;
+
+#define SKIP_NON_DIGIT(p) while(!isdigit(*p)) p++
+#define SKIP_ALPHA(p) while(isalpha(*p)) p++;
+#define SKIP_SPACE(p) while(isspace(*p)) p++;
+#define SKIP_LINE(p) while(*p && *p != '\n') p++;
+
+static boolean __cdecl
+cmp_mf_mode(const struct mf_mode *m1, const struct mf_mode *m2) {
+ return (strcmp(m1->description, m2->description) < 0);
+}
+
+static boolean
+read_modes()
+{
+ string modes_file_name = kpse_find_file("modes.mf", kpse_mf_format, true);
+ FILE *f;
+ string line;
+ boolean in_mode_def = false;
+ int size_modes = MAX_MODES;
+
+ /* modes will keep this value if modes.mf can't be found or read. */
+ modes = (struct mf_mode *)-1;
+ if (modes_file_name == NULL)
+ return false;
+ if((f = fopen(modes_file_name, "r")) == NULL) {
+ free(modes_file_name);
+ return false;
+ }
+
+ modes = xmalloc(size_modes * sizeof(struct mf_mode));
+
+ while((line = read_line(f)) != NULL) {
+ if (in_mode_def) {
+ char * cp;
+ if (strncmp(line, "enddef;", 7) == 0) {
+ nb_modes++;
+ if (nb_modes == MAX_MODES) {
+ size_modes *= 2;
+ modes = xrealloc(modes, size_modes * sizeof(struct mf_mode));
+ }
+ in_mode_def = false;
+ }
+ else if (modes[nb_modes].hor_res == 0
+ && (cp = strstr(line, "pixels_per_inch"))) {
+ SKIP_NON_DIGIT (cp);
+ modes[nb_modes].hor_res = atoi(cp);
+ modes[nb_modes].vert_res = atoi(cp);
+ }
+ else if (cp = strstr(line, "aspect_ratio")) {
+ SKIP_NON_DIGIT (cp);
+ modes[nb_modes].vert_res = atoi(cp);
+ }
+ }
+ else if (strncmp(line, "mode_def", 8) == 0) {
+ char *mode_name, *printer_name;
+ char *cp = line + 8;
+ while (! isalpha(*cp) && *cp != '\n')
+ cp++;
+ if (! isalpha (*cp))
+ goto line_done;
+ mode_name = cp;
+ SKIP_ALPHA (cp);
+ if (*cp == 0)
+ goto line_done;
+ *cp++ = 0;
+ if (strcmp(mode_name, "help") == 0)
+ goto line_done;
+ cp = strstr(cp, "%\\[");
+ if (cp == 0)
+ goto line_done;
+ cp += 3;
+ SKIP_SPACE (cp);
+ if (cp == 0)
+ goto line_done;
+ printer_name = cp;
+ SKIP_LINE (cp);
+ *cp = 0;
+ in_mode_def = true;
+
+ modes[nb_modes].mnemonic = xstrdup(mode_name);
+ modes[nb_modes].description = xstrdup(printer_name);
+ modes[nb_modes].hor_res = 0;
+ }
+ line_done:
+ free(line);
+ }
+ qsort(modes, nb_modes, sizeof(struct mf_mode), cmp_mf_mode);
+ return true;
+}
+
+string
+get_mf_mode(int dpi)
+{
+ int i;
+
+ if ((modes == NULL && !read_modes())
+ || (modes == (struct mf_mode *)-1))
+ return NULL;
+
+ for (i = 0; i < nb_modes; i++) {
+ if (modes[i].hor_res == dpi)
+ return modes[i].mnemonic;
+ }
+ return NULL;
+}
+
+int mktexpk(int argc, char **argv)
+{
+ FILE *psmapfile;
+ string psmapfilename, fullname;
+ string line = NULL, pktempname;
+ string cmd = "", gfcmd;
+ string aname, mfname;
+ string *vars;
+ int mf_bdpi, ibdpi, retcode;
+ boolean has_ttf2pk = false, has_hbf2gf = false;
+
+ /* Where do potential driver files belong?
+ case "$MT_FEATURES" in
+ *nomfdrivers*)
+ : ${MT_MFDESTDIR=`pwd`}
+ export MT_MFDESTDIR;;
+ esac
+ */
+ if (feature_p("nomfdrivers")) {
+ setval_default("MT_FEATURES", xgetcwd());
+ }
+
+ if (argc == 3) {
+ char *ep = NULL;
+ int fd = - 1;
+
+ if (argv[1][0] == '>' && argv[1][1] == '&' && isdigit(argv[1][2]))
+ fd = strtoul(argv[1] + 2, &ep, 0);
+ if (!ep || *ep || fd > 255 || fd < 0)
+ fprintf(stderr, "%s: argument '%s' ignored - bad file number\n",
+ progname, argv[2]);
+ else if (fd != 1)
+ /* The actual redirection happens before we print the names
+ of generated file(s). */
+ record_output_handle(fd);
+ }
+
+ start_redirection(false);
+
+ setval("NAME", argv[1]);
+
+ has_ttf2pk = find_exe("ttf2pk");
+ has_hbf2gf = find_exe("hbf2gf");
+
+ if (KPSE_DEBUG_P(MKTEX_DEBUG)) {
+ fprintf(stderr, "MktexPK:\n\tName: %s\n\tDpi: %s\n\tBdpi: %s\n\tMag: %s\n\tMode: %s\n\tDest: %s\n", getval("NAME"), getval("DPI"), getval("BDPI"),
+ getval("MAG"), getval("MODE"), getval("DEST"));
+ }
+
+ mfname = concat(getval("NAME"), ".mf");
+ cmd = expand_var("mktexmf $NAME");
+
+ if ((kpse_find_file(mfname, kpse_mf_format, false) != NULL)
+ || (system(cmd) == 0)) {
+
+ cmd = NULL; /* reset cmd */
+ if (test_file('n', getval("MODE"))) {
+ if ((mf_bdpi = get_mode_from_mf(getval("MODE")))
+ != atoi(getval("BDPI"))) {
+ fprintf(stderr, "%s: Mismatched mode %s and resolution %s; ignoring mode.\n", progname, getval("MODE"), getval("BDPI"));
+ setval("MODE", "");
+ }
+ }
+
+ if (test_file('z', getval("MODE"))
+ || strcmp(getval("MODE"), "default") == 0) {
+ ibdpi = atoi(getval("BDPI"));
+ switch (ibdpi) {
+ case 85:
+ setval("MODE", "sun");
+ break;
+ case 100:
+ setval("MODE", "nextscrn");
+ break;
+ case 180:
+ setval("MODE", "toshiba");
+ break;
+ case 300:
+ setval("MODE", "cx");
+ break;
+ case 400:
+ setval("MODE", "nexthi");
+ break;
+ case 600:
+ setval("MODE", "ljfour");
+ break;
+ case 720:
+ setval("MODE", "epshi");
+ break;
+ case 1270:
+ setval("MODE", "linoone");
+ break;
+ default: {
+ string mode = get_mf_mode(ibdpi);
+ if (mode) {
+ setval("MODE", mode);
+ }
+ else {
+ fprintf (stderr, "%s: Can't guess mode for %s dpi devices.\n",
+ progname, getval("BDPI"));
+ fprintf (stderr, "%s: Use a config file, or update me.\n",
+ progname);
+ mt_exit(1);
+ }
+ }
+ }
+ }
+ /* Run Metafont. Always use plain Metafont, since reading cmbase.mf */
+ /* does not noticeably slow things down. */
+ cmd=expand_var("mf \"\\mode:=$MODE; mag:=$MAG; nonstopmode; input $NAME\"");
+ }
+ else {
+ cmd = NULL; /* reset cmd */
+ setval("MODE", "modeless");
+ if (FILESTRCASEEQ(getval("ps_to_pk"), "gsftopk")) {
+#if 0
+ if (KPSE_DEBUG_P(MKTEX_DEBUG)) {
+ printf("Test: system -> %d win32_system -> %d\n",
+ system(expand_var("$ps_to_pk -t $NAME")),
+ win32_system(expand_var("$ps_to_pk -t $NAME")));
+ }
+#endif
+ if (system(expand_var("$ps_to_pk -t $NAME"))==0) {
+ cmd = expand_var("$ps_to_pk $NAME $DPI");
+ }
+ }
+ else if (FILESTRCASEEQ(getval("ps_to_pk"), "ps2pk")) {
+ string pstmp;
+ /* look for name in psfont.map.
+ Can't use `kpse_open_file' because it exits if the file doesn't
+ exits, and we have a special exit procedure which cleans up. */
+ pstmp = kpse_find_file("ps2pk.map", kpse_fontmap_format, false);
+ if (test_file('z', pstmp))
+ pstmp = kpse_find_file("psfonts.map", kpse_fontmap_format, false);
+ psmapfilename = setval_default("PSMAPFILE", pstmp);
+ if (test_file('n', pstmp)) free(pstmp);
+
+ if (test_file('n', psmapfilename)) {
+ string pattern = concat3("^", getval("NAME"), "([ \t]|$)");
+
+ psmapfile = fopen(psmapfilename, "r");
+ if (psmapfile == NULL) oops("Cannot open file %s.", psmapfilename);
+ while ((line = read_line(psmapfile)) != NULL) {
+ if ((vars = grep(pattern, line, 1)) != NULL)
+ break;
+ free(line);
+ line = NULL;
+ }
+ free(pattern);
+ fclose(psmapfile);
+ }
+ else
+ fprintf(stderr, "%s: no `psfonts.map' file.\n", progname);
+
+ if (line != NULL) {
+ /* ps_to_pk is set in mktex.opt */
+ string encoding, psname, slant, extend;
+ encoding = psname = slant = extend = "";
+ /* FIXME: mktexpk script has a loop here which effectively
+ looks for the LAST matching string. Is it important? */
+ if ((vars = grep("([^ \t<[\"]*.enc)", line, 1)))
+ encoding = concat ("-e", vars[1]);
+ if ((vars = grep("([^ \t<[\"]*.pf[ab])", line, 1)))
+ psname = vars[1];
+ if ((vars = grep("\" ([^ \t]+)SlantFont\"", line, 1)))
+ slant = concat ("-S ", vars[1]);
+ if ((vars = grep("\" ([^ \t]+)ExtendFont\"", line, 1)))
+ extend = concat ("-E", vars[1]);
+ /* This is looking for .pfa *and* .pfb with the 7.2 kpathsea. */
+ if (test_file('z', psname)) {
+ psname = kpse_find_file(getval("NAME"), kpse_type1_format, false);
+ }
+ if (test_file('z', psname)) {
+ aname = xstrdup(getval("NAME"));
+ if (strlen(aname) >= 2
+ && aname[strlen(aname)-2] == '8'
+ && aname[strlen(aname)-1] == 'r')
+ /* Guessing the name of the type1 font file as fallback: */
+ aname[strlen(aname)-1] = 'a';
+ psname = kpse_find_file(aname, kpse_type1_format, false);
+ free(aname);
+ }
+ if (test_file('n', psname)) {
+ /* In fact, ps2pk can't cope with the full pathname, so : */
+ psname = xbasename(psname);
+ cmd = concatn( expand_var("ps2pk -v -X$DPI -R$BDPI"),
+ slant, " ", extend, " ", encoding,
+ " ", psname, " ", expand_var("$NAME.${DPI}pk"), NULL);
+ }
+ else {
+ cmd = expand_var("gsftopk -t $NAME");
+ if (system(cmd) == 0) {
+ cmd = NULL; /* reset cmd */
+ fprintf(stderr,
+ "%s: cannot find %s.pfa or %s.pfb. Trying gsftopk.\n",
+ progname, getval("NAME"), getval("NAME"));
+ cmd = expand_var("gsftopk $NAME $DPI");
+#if 0
+ /* make sure that gsftopk uses the psline from our mapfile: */
+ {
+ FILE *f;
+ if ((f = fopen("./psfonts.map", "w")) != NULL) {
+ fprintf(f, "%s\n", line);
+ fclose(f);
+ setval("TEXFONTMAP", expand_var(".;$TEXFONTMAP"));
+ }
+ else {
+ /* Can't write in the current directory ? Strange ...
+ Anyway, let's go on and home we will find the right
+ psfonts.map ... */
+ }
+ }
+#endif
+ }
+ else {
+ cmd = NULL; /* reset cmd */
+ }
+ }
+ }
+ }
+
+ /* unsupported by $ps_to_pk, try other conversions: */
+ if (test_file('z', cmd)) {
+ if (has_ttf2pk && system(expand_var("ttf2pk -t -q $NAME")) == 0) {
+ cmd = expand_var("ttf2pk -q $NAME $DPI");
+ }
+ else if (has_hbf2gf && system(expand_var("hbf2gf -q -t $NAME")) == 0) {
+ cmd = expand_var("hbf2gf -g $NAME $DPI");
+ }
+ else {
+ fprintf(stderr, "%s: don't know how to create bitmap font for %s.",
+ progname, getval("NAME"));
+ mt_exit(1);
+ }
+ }
+ }
+
+ /* Put files into proper place */
+ do_mktexnames(getval("NAME"));
+
+ setval("PKDEST", getval("MT_PKNAME"));
+ setval("PKDESTDIR", getval("MT_PKDESTDIR"));
+ setval("PKNAME", (string)xbasename(getval("PKDEST")));
+ setval("GFNAME", expand_var("${NAME}.${DPI}gf"));
+
+ if (test_file('r', fullname = expand_var("$PKDESTDIR/$PKNAME"))) {
+ fprintf(stderr, "%s: %s already exists.\n",
+ progname, fullname);
+ fprintf(fout, "%s\n", fullname);
+ free(fullname);
+ do_mktexupdate(getval("PKDESTDIR"), getval("PKNAME"));
+ return 0;
+ }
+
+ do_makedir(getval("PKDESTDIR"));
+ if (!test_file('d', getval("PKDESTDIR"))) {
+ fprintf(stderr, "%s: mktexdir %s failed.\n",
+ progname, getval("PKDESTDIR"));
+ mt_exit(1);
+ }
+
+ printf("%s: Running %s\n", progname, cmd);
+
+ /* Now run metafont.
+ Note that stdin has been redirected to "/dev/null" by `main'. */
+ retcode = system(cmd);
+ if (retcode != 0) {
+ fprintf(stderr, "command %s return %d\n", cmd, retcode);
+ if (retcode == -1) {
+ perror("mf");
+ mt_exit(1);
+ }
+ else if (check_for_strange_path(expand_var("$NAME.log")) == true) {
+ fprintf(stderr, "%s: warning: `%s' caused strange path errors.\n",
+ progname, cmd);
+ }
+ else {
+ struct stat statbuf;
+ fprintf(stderr, "%s: `%s' failed.\n", progname, cmd);
+ if (stat(expand_var("$NAME.log"), &statbuf) == 0
+ && statbuf.st_size > 0)
+ mvfile(expand_var("$NAME.log"),
+ concat_pathes(getval("KPSE_DOT"), expand_var("$NAME.log")));
+ mt_exit(1);
+ }
+ }
+
+ if (test_file('r', getval("GFNAME"))) {
+ gfcmd = expand_var("gftopk ./$GFNAME $PKNAME");
+ retcode = system(gfcmd);
+ if (retcode == -1) {
+ perror("gftopk");
+ mt_exit(1);
+ }
+ else if (retcode != 0) {
+ fprintf(stderr, "%s: `%s' failed.\n", progname, gfcmd);
+ mt_exit(1);
+ }
+ }
+
+ /* FIXME : What about the file is created in the current directory ? */
+ if (!test_file('f', getval("PKNAME"))
+ && test_file('f', expand_var("$NAME.${DPI}pk")))
+ mvfile(expand_var("$NAME.${DPI}pk"), getval("PKNAME"));
+
+ if (!test_file('s', getval("PKNAME"))) {
+ fprintf(stderr, "%s: `%s' failed to make %s.\n",
+ progname, cmd, getval("PKNAME"));
+ mt_exit(1);
+ }
+
+ pktempname = concat_pathes(getval("PKDESTDIR"), "pkXXXXXX");
+ mktemp(pktempname);
+ if (mvfile(getval("PKNAME"), pktempname) == FALSE) {
+ mt_exit(1);
+ }
+
+ pushd(getval("PKDESTDIR"));
+ chmod_as_dir(pktempname, ".", 00644);
+ if (!test_file('r', getval("PKNAME")))
+ if (mvfile(pktempname, getval("PKNAME")) == FALSE) {
+ mt_exit(1);
+ }
+
+ /* OK, success with the PK. */
+ do_mktexupdate(getval("PKDESTDIR"), getval("PKNAME"));
+ fullname = normalize(concat_pathes(getval("PKDESTDIR"),
+ getval("PKNAME")));
+ fprintf(fout, "%s\n", fullname);
+ fprintf(stderr, "%s: %s: successfully generated.\n", progname,
+ fullname);
+ free(fullname);
+
+ popd();
+ return 0;
+}
diff --git a/Build/source/texk/contrib/mktex.h b/Build/source/texk/contrib/mktex.h
new file mode 100644
index 00000000000..153598086fe
--- /dev/null
+++ b/Build/source/texk/contrib/mktex.h
@@ -0,0 +1,58 @@
+/* mktex.h: definitions for mktex lib exports.
+
+Copyright (C) 1997 Fabrice POPINEAU.
+Adapted to MS-DOS/DJGPP by Eli Zaretskii <eliz@is.elta.co.il>.
+
+Time-stamp: <02/12/23 00:33:08 popineau>
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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 this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _MKTEX_H_
+#define _MKTEX_H_
+
+#include "mktexlib.h"
+
+/* Pointer to functions that accept argc and argv[] */
+typedef int (*fp)(int, string*);
+
+typedef struct _program_description {
+ string name;
+ int arg_min;
+ int arg_max;
+ fp prog;
+} program_description;
+
+extern MKTEXDLL int program_number;
+extern MKTEXDLL string progname;
+extern MKTEXDLL char empty_str[];
+extern MKTEXDLL FILE *fout;
+extern MKTEXDLL FILE *fnul;
+extern MKTEXDLL string output;
+extern MKTEXDLL string progname;
+extern MKTEXDLL char tmpdir[];
+extern MKTEXDLL void mktexinit(int, char**);
+extern MKTEXDLL int mktexpk(int, char**);
+extern MKTEXDLL int mktextfm(int, char**);
+extern MKTEXDLL int mktextex(int, char**);
+extern MKTEXDLL int mktexmf(int, char**);
+extern MKTEXDLL int mktexlsr(int, char**);
+extern MKTEXDLL int mktexupdate(int, char**);
+extern MKTEXDLL int mktexmkdir(int, char**);
+extern MKTEXDLL int mktexrmdir(int, char**);
+extern MKTEXDLL int mktexnames(int, char**);
+extern MKTEXDLL int mktex_opt(int, char**, program_description *);
+extern MKTEXDLL program_description makedesc[];
+#endif /* _MKTEX_H_ */
+
diff --git a/Build/source/texk/contrib/mktexlib.h b/Build/source/texk/contrib/mktexlib.h
new file mode 100644
index 00000000000..14391ccc18a
--- /dev/null
+++ b/Build/source/texk/contrib/mktexlib.h
@@ -0,0 +1,61 @@
+#ifndef _MKTEXLIB_H_
+#define _MKTEXLIB_H_
+
+#if defined(WIN32)
+# ifdef MKTEX_DLL
+# ifdef MAKE_MKTEX_DLL
+# define MKTEXDLL __declspec( dllexport)
+# else
+# define MKTEXDLL __declspec( dllimport)
+# endif
+# else
+# define MKTEXDLL
+# endif
+#else /* ! WIN32 */
+# define MKTEXDLL
+# define __cdecl
+#endif
+
+#include <assert.h>
+#ifdef _WIN32
+#include <direct.h>
+#else
+#include <unistd.h>
+#include <signal.h>
+#endif
+#include <stdio.h>
+#include <signal.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/stat.h>
+
+#include <kpathsea/config.h>
+#include <kpathsea/kpathsea.h>
+extern KPSEDLL char* kpathsea_version_string;
+
+#ifndef _WIN32
+#include <sys/param.h>
+#endif
+
+#ifdef WIN32
+# ifdef mkdir
+# undef mkdir
+# endif
+# define mkdir(p,m) _mkdir(p)
+typedef unsigned long mode_t;
+#else
+# define _getdrive() (getdisk() + 1)
+# define FS_CASE_SENSITIVE _FILESYS_CASE_SENSITIVE
+typedef unsigned int DWORD;
+#endif
+
+/* gsftopk defines KPSE_LAST_DEBUG+2, so avoid clashes */
+#define MKTEX_DEBUG (KPSE_LAST_DEBUG + 3)
+#define MKTEX_FINE_DEBUG (KPSE_LAST_DEBUG + 4)
+
+
+#define LAST_CHAR(s) (*((s)+strlen(s)-1))
+
+extern MKTEXDLL string mktex_version_string;
+
+#endif /* _MKTEXLIB_H_ */
diff --git a/Build/source/texk/contrib/pdfdde.c b/Build/source/texk/contrib/pdfdde.c
new file mode 100644
index 00000000000..b6736e7fd28
--- /dev/null
+++ b/Build/source/texk/contrib/pdfdde.c
@@ -0,0 +1,564 @@
+/* pdfdde.c -- control Adobe Acrobat under Windows. Written by Fabrice
+ Popineau many years ago, based on Adobe documentation. Public
+ domain. */
+
+// #include <afx.h>
+#include <win32lib.h>
+#include <ddeml.h>
+#include <dde.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <shellapi.h>
+
+#include <getopt.h>
+
+#define ACROBAT_EXE "acrobat.exe"
+#define ACROBAT "acroview"
+#define EVAL_TOPIC "control"
+#define RESULT_ITEM "Result"
+#define ERROR_ITEM "Error"
+
+/* Timeouts & delays */
+#define CONNECT_DELAY 500 /* ms */
+#define TRANSACTION_TIMEOUT 5000 /* ms */
+#define MAX_INPUT_IDLE_WAIT INFINITE /* ms */
+
+static DWORD DDEsession;
+static HCONV DDEconversation;
+
+/* The raw base name */
+static char *argv0 = NULL;
+static int nPage = 0;
+static char *sFileName = NULL;
+static int bAll = 0;
+static int bServer = 0;
+static int iDebug = 0;
+static char *sGoto = NULL;
+static char sLongFileName[MAXPATHLEN];
+
+const char *pdfdde_version_string = "0.2";
+
+/* Test whether getopt found an option ``A''.
+ Assumes the option index is in the variable `option_index', and the
+ option table in a variable `long_options'. */
+#define ARGUMENT_IS(a) (_stricmp(long_options[option_index].name, a) == 0)
+#define PROGRAM_IS(a) (_stricmp(a, argv0) == 0)
+
+static struct option long_options [] = {
+ { "debug", 0, 0, 0},
+ { "help", 0, 0, 0},
+ { "version", 0, 0, 0},
+ { "file", 1, 0, 0},
+ { "page", 1, 0, 0},
+ { "goto", 1, 0, 0},
+ { "all", 0, 0, 0},
+ {0, 0, 0, 0}
+};
+
+
+char *FindAcrobatModule()
+{
+ char buf[260];
+ char path[260];
+ char *program;
+ HANDLE hFile;
+ HINSTANCE hInst;
+
+ program = (char *)malloc(MAX_PATH*sizeof(char));
+ if (program == NULL) goto exit_1;
+
+ buf[0] = path[0] = program[0] = '\0';
+
+ if (GetTempPath(sizeof(path), path) != 0) {
+ strcpy(buf, path);
+ }
+
+
+ strcat(buf, "dummy.pdf");
+
+ hFile = CreateFile(buf,
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ CloseHandle(hFile);
+
+ hInst = FindExecutable("dummy.pdf", path, program);
+
+ DeleteFile(buf);
+
+#if 0
+ switch ((int)hInst) {
+ case SE_ERR_FNF:
+ fprintf(stdout, "File not found: %s\n", argv[1]);
+ break;
+ case SE_ERR_NOASSOC:
+ fprintf(stdout, "No association for %s\n", argv[1]);
+ break;
+ default:
+ fprintf(stdout, "File .pdf is opened by %s\n", program);
+ break;
+ }
+#endif
+
+ if (*program == '\0' || (GetFileAttributes(program) == 0xFFFFFFFF)) {
+ program = NULL;
+ }
+
+exit_1:
+ return program;
+
+}
+
+void CloseConversation (void)
+{
+ if (DDEconversation)
+ DdeDisconnect(DDEconversation);
+ if (DDEsession)
+ DdeUninitialize(DDEsession);
+}
+
+void error(LPCTSTR fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fputc('\n', stderr);
+
+ /* Tidy up */
+ CloseConversation();
+ exit(1);
+}
+
+void *emalloc(size_t len)
+{
+ void *p = malloc(len);
+
+ if (p == NULL)
+ error("Out of memory - cannot allocate %d bytes", len);
+
+ return p;
+}
+
+int outstanding_requests;
+
+HDDEDATA CALLBACK
+Callback (UINT uType, UINT uFmt, HCONV hconv, HSZ hsz1, HSZ hsz2,
+ HDDEDATA hdata, DWORD dwData1, DWORD dwData2)
+{
+ if (uType == XTYP_ADVDATA) {
+ DWORD len = DdeGetData(hdata, NULL, 0, 0);
+ char *buf = _alloca(len + 1);
+ DdeGetData(hdata, (LPBYTE)buf, len + 1, 0);
+
+ if (--outstanding_requests == 0)
+ PostQuitMessage(0);
+
+ return (HDDEDATA) DDE_FACK;
+ }
+
+ return (HDDEDATA) NULL;
+}
+
+int StartServer(LPCTSTR prog)
+{
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+
+ /* To be sure ... */
+ if (! prog)
+ return 1;
+
+ ZeroMemory (&si, sizeof (si));
+ si.cb = sizeof (si);
+ if (!CreateProcess (NULL, (LPTSTR)prog, NULL, NULL, FALSE, 0,
+ NULL, NULL, &si, &pi))
+ {
+ error("Could not start process %s", prog);
+ return 1;
+ }
+
+ /* Wait for the process to enter an idle state */
+ WaitForInputIdle (pi.hProcess, MAX_INPUT_IDLE_WAIT);
+
+ /* Close the handles */
+ CloseHandle (pi.hThread);
+ CloseHandle (pi.hProcess);
+ return 0;
+}
+
+HSZ DDEString(LPCTSTR str)
+{
+ HSZ hsz = DdeCreateStringHandle(DDEsession, str, CP_WINANSI);
+ if (hsz == 0)
+ error("Cannot create string for %s", str);
+ return hsz;
+}
+
+FreeString(HSZ hsz)
+{
+ DdeFreeStringHandle(DDEsession, hsz);
+}
+
+void OpenConversation(LPCTSTR topic_name)
+{
+ UINT ret;
+ HSZ service;
+ HSZ topic;
+ int n;
+
+ ret = DdeInitialize(&DDEsession, Callback, APPCMD_CLIENTONLY, 0);
+ if (ret != DMLERR_NO_ERROR)
+ error("Cannot start DDE");
+
+ service = DDEString(ACROBAT);
+ topic = DDEString(topic_name);
+ DDEconversation = DdeConnect(DDEsession, service, topic, 0);
+
+ if (DDEconversation == 0)
+ {
+ if (StartServer(FindAcrobatModule()) == 0)
+ {
+ /* Try to connect */
+ for (n = 0; n < 5; n++)
+ {
+ Sleep (CONNECT_DELAY);
+ DDEconversation = DdeConnect(DDEsession, service, topic, 0);
+ if (DDEconversation)
+ break;
+ }
+ if (DDEconversation == 0)
+ error("Cannot contact server %s", ACROBAT);
+ }
+ }
+ FreeString(service);
+ FreeString(topic);
+}
+
+void __cdecl ExecuteCommand(LPCTSTR command, ...)
+{
+ HDDEDATA ret;
+ va_list args;
+ int len;
+ char *buffer;
+
+ va_start( args, command );
+ len = _vscprintf(command, args) // _vscprintf doesn't count
+ + 1; // terminating '\0'
+ buffer = malloc( len * sizeof(char) );
+ vsprintf( buffer, command, args );
+
+ ret = DdeClientTransaction((LPBYTE)buffer, strlen(buffer) + 1,
+ DDEconversation, 0, 0, XTYP_EXECUTE,
+ TRANSACTION_TIMEOUT, 0);
+ if (ret == 0)
+ error("Cannot execute command \"%s\" (error %ld)", command, DdeGetLastError(DDEsession));
+}
+
+void StartHotLink(LPCTSTR item_name)
+{
+ HSZ item = DDEString(item_name);
+ DdeClientTransaction(0, 0, DDEconversation, item, CF_TEXT, XTYP_ADVSTART,
+ TRANSACTION_TIMEOUT, 0);
+ FreeString(item);
+}
+
+LPTSTR RequestData (LPCTSTR item_name)
+{
+ HSZ item = DDEString(item_name);
+ DWORD len;
+ char *buf;
+ HDDEDATA result;
+ result = DdeClientTransaction (NULL, 0, DDEconversation, item, CF_TEXT,
+ XTYP_REQUEST, TRANSACTION_TIMEOUT, 0);
+ FreeString(item);
+ if (result == 0)
+ error("Cannot request item %s\n", item_name);
+
+ len = DdeGetData(result, NULL, 0, 0);
+ buf = emalloc(len + 1);
+ DdeGetData(result, (LPBYTE)buf, len + 1, 0);
+ return buf;
+}
+
+void usage()
+{
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, "\tpdfopen --file <filename> [--page <page>]\n");
+ fprintf(stderr, "\t\t Opens <filename> (at page <page> if available)\n");
+ fprintf(stderr, "\t\t in Acrobat or Acrobat Reader.\n");
+ fprintf(stderr, "\tpdfclose --file <filename>\n");
+ fprintf(stderr, "\t Closes <filename> in Acrobat or Acrobat Reader.\n");
+ fprintf(stderr, "\tpdfclose --all\n");
+ fprintf(stderr, "\t Closes all documents in Acrobat or Acrobat Reader.\n");
+ fprintf(stderr, "\tpdfdde\n");
+ fprintf(stderr, "\t\t Read commands on stdin\n");
+ fprintf(stderr, "Beware: only documents opened by `pdfopen' can be closed\n");
+ fprintf(stderr, " by `pdfclose'.\n");
+ exit(0);
+}
+
+char *CheckFileName(char *p)
+{
+ char sTmp[MAXPATHLEN];
+ char *fp;
+
+ sLongFileName[0] = '\0';
+
+ if (GetFileAttributes(p) == -1) {
+ fprintf(stderr, "%s: non existent file %s\n", argv0, p);
+ return NULL;
+ }
+ if (GetFullPathName(p, sizeof(sTmp), sTmp, &fp) == 0) {
+ fprintf(stderr, "%s: failed to get full path name for %s (Error %d)\n", argv0, p, GetLastError());
+ return NULL;
+ }
+ if (GetLongPathName(sTmp, sLongFileName, sizeof(sLongFileName)) == 0) {
+ fprintf(stderr, "%s: failed to get long path name for %s (Error %d)\n", argv0, sTmp, GetLastError());
+ return NULL;
+ }
+ return sLongFileName;
+}
+
+int pdfopen()
+{
+ if (sLongFileName[0] == '\0') {
+ fprintf(stderr, "%s: mandatory `--file' argument not found.\n", argv0);
+ return EXIT_FAILURE;
+ }
+
+ OpenConversation(EVAL_TOPIC);
+
+ ExecuteCommand("[DocOpen(\"%s\")]", sLongFileName);
+ ExecuteCommand("[FileOpen(\"%s\")]", sLongFileName);
+
+ if (nPage > 0) {
+ ExecuteCommand("[DocGoTo(\"%s\", %d)]", sLongFileName, nPage);
+ }
+
+ if (sGoto != NULL) {
+ ExecuteCommand("[DocGoToNameDest(\"%s\", %s)]", sLongFileName, sGoto);
+ }
+
+ CloseConversation();
+#if 0
+ /* Problem : it seems that these calls can put AR into a strange state.
+ It would have been simpler if Adobe had simply iconified their application. */
+ if (stricmp(argv0, "pdfclose") == 0) {
+ sprintf(buf, "[AppHide()]");
+ }
+ else if (stricmp(argv0, "pdfopen") == 0) {
+ sprintf(buf, "[AppShow()]");
+ }
+ bRetVal = DdeClientTransaction((unsigned char *)buf, (DWORD)strlen(buf),
+ (HCONV)hConversation, NULL,
+ (UINT)CF_TEXT, (UINT)XTYP_EXECUTE, (DWORD)1000, &dwResult);
+#endif
+
+ return EXIT_SUCCESS;
+}
+
+int pdfclose()
+{
+ OpenConversation(EVAL_TOPIC);
+
+ if (bAll) {
+ ExecuteCommand("[CloseAllDocs()]");
+ }
+ else if (sLongFileName[0] != '\0') {
+ ExecuteCommand("[DocClose(\"%s\")]", sLongFileName);
+ }
+
+#if 0
+ fprintf(stderr, "cmd : %s\n", buf);
+#endif
+
+ CloseConversation();
+
+ return EXIT_SUCCESS;
+}
+
+int pdfserver()
+{
+ char line[1024];
+
+ OpenConversation(EVAL_TOPIC);
+
+ fprintf(stdout, "Type Ctrl-Z to quit.\n");
+
+ while (fgets(line, sizeof(line), stdin)) {
+#define WHITE_DELIM " \t\n"
+ char *p = strtok(line, WHITE_DELIM);
+ if (stricmp(p, "open") == 0) {
+ p = strtok(NULL, WHITE_DELIM);
+ if (CheckFileName(p) == NULL) goto next;
+
+ ExecuteCommand("[DocOpen(\"%s\")]", sLongFileName);
+ }
+ else if (stricmp(p, "close") == 0) {
+ p = strtok(NULL, WHITE_DELIM);
+ if (CheckFileName(p) == NULL) goto next;
+ ExecuteCommand("[DocClose(\"%s\")]", sLongFileName);
+ }
+ else if (stricmp(p, "closeall") == 0) {
+ ExecuteCommand("[CloseAllDocs()]");
+ }
+ else if (stricmp(p, "goto") == 0) {
+ p = strtok(NULL, WHITE_DELIM);
+ if (p == NULL) goto next;
+ if (CheckFileName(p) == NULL) goto next;
+ p = strtok(NULL, WHITE_DELIM);
+ if (p == NULL) goto next;
+ nPage = atoi(p) - 1;
+ ExecuteCommand("[DocGoTo(\"%s\", %d)]", sLongFileName, nPage);
+ }
+ else if (stricmp(p, "gotoname") == 0) {
+ p = strtok(NULL, WHITE_DELIM);
+ if (p == NULL) goto next;
+ if (CheckFileName(p) == NULL) goto next;
+ p = strtok(NULL, WHITE_DELIM);
+ if (p == NULL) goto next;
+ sGoto = p;
+ ExecuteCommand("[DocGoToNameDest(\"%s\", %s)]", sLongFileName, sGoto);
+ }
+ else if (stricmp(p, "show") == 0) {
+ ExecuteCommand("[AppShow()]");
+
+ }
+ else if (stricmp(p, "hide") == 0) {
+ ExecuteCommand("[AppHide()]");
+
+ }
+ else if (stricmp(p, "exit") == 0) {
+ ExecuteCommand("[AppExit()]");
+ goto exit;
+ }
+ else if (stricmp(p, "list") == 0) {
+ fprintf(stdout, "open <file> open the file\n");
+ fprintf(stdout, "close <file> close the file\n");
+ fprintf(stdout, "closeall close all files\n");
+ fprintf(stdout, "goto <file> <page> goto the given <page> in <file>\n");
+ fprintf(stdout, "gotoname <file> <dest> goto the <dest> named destination in <file>\n");
+ fprintf(stdout, "show show acroview\n");
+ fprintf(stdout, "hide hide acroview\n");
+ fprintf(stdout, "exit exit acroview and %s\n", argv0);
+ }
+ next: ;
+ }
+
+#if 0
+ fprintf(stderr, "cmd : %s\n", buf);
+#endif
+exit:
+ CloseConversation();
+
+ return EXIT_SUCCESS;
+}
+
+int main (int argc, char *argv[])
+{
+ BOOL bRet = FALSE;
+ char *p;
+ int argv0len = 0;
+ int g; /* getopt return code */
+ int option_index;
+
+ /* Make argv0 to point to the raw base name */
+ argv0 = argv[0];
+ if ((p = strrchr(argv0, '/'))
+ || (p = strrchr(argv0, '\\'))) {
+ argv0 = _strdup(p+1);
+ }
+ if ((argv0len = strlen(argv0)) > 4
+ && _strnicmp(argv0 + argv0len - 4, ".exe", 4) == 0)
+ argv0[argv0len - 4] = '\0';
+
+ for(;;) {
+ g = getopt_long_only (argc, argv, "", long_options, &option_index);
+
+ if (g == EOF)
+ break;
+
+ if (g == '?') {
+ usage(); /* Unknown option. */
+ exit(EXIT_FAILURE);
+ }
+
+ /* assert (g == 0); */ /* We have no short option names. */
+ /*
+ FIXME : try 'mktexpk --mfmode --bdpi 600 ...'
+ */
+
+ if (ARGUMENT_IS ("debug")) {
+#if 0
+ if (! isalnum(*optarg)) {
+ fprintf(stderr, "%s: warning, `%s' bad debug argument.\n", argv0, optarg);
+ }
+ iDebug |= atoi (optarg);
+#endif
+ iDebug = TRUE;
+ }
+ else if (ARGUMENT_IS ("help")) {
+ usage();
+ exit(EXIT_SUCCESS);
+ }
+ else if (ARGUMENT_IS ("version")) {
+ fprintf(stderr, "%s of %s.\n", argv0, pdfdde_version_string);
+ exit(EXIT_SUCCESS);
+ }
+ else if (PROGRAM_IS("pdfopen")) {
+ if (ARGUMENT_IS("file")) {
+ CheckFileName(optarg);
+ }
+ else if (ARGUMENT_IS("page")) {
+ nPage = atoi(optarg) - 1;
+ }
+ else if (ARGUMENT_IS("goto")) {
+ sGoto = optarg;
+ }
+ }
+ else if (PROGRAM_IS("pdfclose")) {
+ if (ARGUMENT_IS("file")) {
+ CheckFileName(optarg);
+ }
+ else if (ARGUMENT_IS("all")) {
+ bAll = TRUE;
+ }
+ }
+ }
+
+#if 0
+ /* shifting options from argv[] list */
+ for (i = 0; i < argc - optind; i++)
+ argv[i] = argv[optind+i];
+ argv[i] = NULL;
+
+ argc = i;
+#endif
+
+ if (PROGRAM_IS("pdfopen")) {
+ bRet = pdfopen();
+ }
+ else if (PROGRAM_IS("pdfclose")) {
+ bRet = pdfclose();
+ }
+ else if (PROGRAM_IS("pdfdde")) {
+ bRet = pdfserver();
+ }
+ else {
+ fprintf(stderr, "This program has been incorrectly copied to the name %s.\n", argv[0]);
+ bRet = EXIT_FAILURE;
+ }
+ return bRet;
+}
+
+
+
+
+
+
diff --git a/Build/source/texk/contrib/regex/regex.c b/Build/source/texk/contrib/regex/regex.c
new file mode 100644
index 00000000000..8169880d7e4
--- /dev/null
+++ b/Build/source/texk/contrib/regex/regex.c
@@ -0,0 +1,4948 @@
+/* Extended regular expression matching and search library,
+ version 0.12.
+ (Implements POSIX draft P10003.2/D11.2, except for
+ internationalization features.)
+
+ Copyright (C) 1993 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* AIX requires this to be the first thing in the file. */
+#if defined (_AIX) && !defined (REGEX_MALLOC)
+ #pragma alloca
+#endif
+
+#define _GNU_SOURCE
+
+/* We need this for `regex.h', and perhaps for the Emacs include files. */
+#include <sys/types.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#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"
+
+/* Emacs uses `NULL' as a predicate. */
+#undef NULL
+
+#else /* not emacs */
+
+/* We used to test for `BSTRING' here, but only GCC and Emacs define
+ `BSTRING', as far as I know, and neither of them use this code. */
+#if HAVE_STRING_H || STDC_HEADERS
+#include <string.h>
+#ifndef bcmp
+#define bcmp(s1, s2, n) memcmp ((s1), (s2), (n))
+#endif
+#ifndef bcopy
+#define bcopy(s, d, n) memcpy ((d), (s), (n))
+#endif
+#ifndef bzero
+#define bzero(s, n) memset ((s), 0, (n))
+#endif
+#else
+#include <strings.h>
+#endif
+
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#else
+char *malloc ();
+char *realloc ();
+#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 SYNTAX_TABLE
+
+extern char *re_syntax_table;
+
+#else /* not SYNTAX_TABLE */
+
+/* How many characters in the character set. */
+#define CHAR_SET_SIZE 256
+
+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>
+
+#ifndef isascii
+#define isascii(c) 1
+#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
+
+#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))
+
+#ifndef NULL
+#define NULL 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)
+
+#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>
+#else /* not __GNUC__ or HAVE_ALLOCA_H */
+#ifndef _AIX /* Already did AIX, up at the top. */
+char *alloca ();
+#endif /* not _AIX */
+#endif /* not 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), \
+ bcopy (source, destination, osize), \
+ destination)
+
+#endif /* not REGEX_MALLOC */
+
+
+/* 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 REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t)))
+
+#define BYTEWIDTH 8 /* In bits. */
+
+#define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
+
+#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
+
+/* 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.
+
+ The value of `exactn' is needed in search.c (search_buffer) in Emacs.
+ So regex.h defines a symbol `RE_EXACTN_VALUE' to be 1; the value of
+ `exactn' we use here must also be 1. */
+
+typedef enum
+{
+ no_op = 0,
+
+ /* Followed by one byte giving n, then by n literal bytes. */
+ exactn = 1,
+
+ /* 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 (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 (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)
+
+
+extern void printchar ();
+
+/* 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;
+ printchar (i - 1);
+ while (i < (1 << BYTEWIDTH) && fastmap[i])
+ {
+ was_a_range = 1;
+ i++;
+ }
+ if (was_a_range)
+ {
+ printf ("-");
+ printchar (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 *p = start;
+ unsigned char *pend = end;
+
+ if (start == NULL)
+ {
+ printf ("(null)\n");
+ return;
+ }
+
+ /* Loop over pattern commands. */
+ while (p < pend)
+ {
+ switch ((re_opcode_t) *p++)
+ {
+ case no_op:
+ printf ("/no_op");
+ break;
+
+ case exactn:
+ mcnt = *p++;
+ printf ("/exactn/%d", mcnt);
+ do
+ {
+ putchar ('/');
+ printchar (*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;
+
+ printf ("/charset%s",
+ (re_opcode_t) *(p - 1) == charset_not ? "_not" : "");
+
+ assert (p + *p < pend);
+
+ for (c = 0; c < *p; c++)
+ {
+ unsigned bit;
+ unsigned char map_byte = p[1 + c];
+
+ putchar ('/');
+
+ for (bit = 0; bit < BYTEWIDTH; bit++)
+ if (map_byte & (1 << bit))
+ printchar (c * BYTEWIDTH + bit);
+ }
+ 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/0/%d", mcnt);
+ break;
+
+ case on_failure_keep_string_jump:
+ extract_number_and_incr (&mcnt, &p);
+ printf ("/on_failure_keep_string_jump/0/%d", mcnt);
+ break;
+
+ case dummy_failure_jump:
+ extract_number_and_incr (&mcnt, &p);
+ printf ("/dummy_failure_jump/0/%d", mcnt);
+ break;
+
+ case push_dummy_failure:
+ printf ("/push_dummy_failure");
+ break;
+
+ case maybe_pop_jump:
+ extract_number_and_incr (&mcnt, &p);
+ printf ("/maybe_pop_jump/0/%d", mcnt);
+ break;
+
+ case pop_failure_jump:
+ extract_number_and_incr (&mcnt, &p);
+ printf ("/pop_failure_jump/0/%d", mcnt);
+ break;
+
+ case jump_past_alt:
+ extract_number_and_incr (&mcnt, &p);
+ printf ("/jump_past_alt/0/%d", mcnt);
+ break;
+
+ case jump:
+ extract_number_and_incr (&mcnt, &p);
+ printf ("/jump/0/%d", mcnt);
+ break;
+
+ case succeed_n:
+ extract_number_and_incr (&mcnt, &p);
+ extract_number_and_incr (&mcnt2, &p);
+ printf ("/succeed_n/0/%d/0/%d", mcnt, mcnt2);
+ break;
+
+ case jump_n:
+ extract_number_and_incr (&mcnt, &p);
+ extract_number_and_incr (&mcnt2, &p);
+ printf ("/jump_n/0/%d/0/%d", mcnt, mcnt2);
+ break;
+
+ case set_number_at:
+ extract_number_and_incr (&mcnt, &p);
+ extract_number_and_incr (&mcnt2, &p);
+ printf ("/set_number_at/0/%d/0/%d", mcnt, 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));
+ }
+ }
+ printf ("/\n");
+}
+
+
+void
+print_compiled_pattern (bufp)
+ struct re_pattern_buffer *bufp;
+{
+ unsigned char *buffer = bufp->buffer;
+
+ print_partial_compiled_pattern (buffer, buffer + bufp->used);
+ printf ("%d bytes used/%d 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: %d\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;
+{
+ unsigned this_char;
+
+ if (where == NULL)
+ printf ("(null)");
+ else
+ {
+ if (FIRST_STRING_P (where))
+ {
+ for (this_char = where - string1; this_char < size1; this_char++)
+ printchar (string1[this_char]);
+
+ where = string2;
+ }
+
+ for (this_char = where - string2; this_char < size2; this_char++)
+ printchar (string2[this_char]);
+ }
+}
+
+#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. */
+reg_syntax_t re_syntax_options = RE_SYNTAX_EMACS;
+
+
+/* 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;
+ return ret;
+}
+
+/* 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. */
+
+static const char *re_error_msg[] =
+ { NULL, /* REG_NOERROR */
+ "No match", /* REG_NOMATCH */
+ "Invalid regular expression", /* REG_BADPAT */
+ "Invalid collation character", /* REG_ECOLLATE */
+ "Invalid character class name", /* REG_ECTYPE */
+ "Trailing backslash", /* REG_EESCAPE */
+ "Invalid back reference", /* REG_ESUBREG */
+ "Unmatched [ or [^", /* REG_EBRACK */
+ "Unmatched ( or \\(", /* REG_EPAREN */
+ "Unmatched \\{", /* REG_EBRACE */
+ "Invalid content of \\{\\}", /* REG_BADBR */
+ "Invalid range end", /* REG_ERANGE */
+ "Memory exhausted", /* REG_ESPACE */
+ "Invalid preceding regular expression", /* REG_BADRPT */
+ "Premature end of regular expression", /* REG_EEND */
+ "Regular expression too big", /* REG_ESIZE */
+ "Unmatched ) or \\)", /* REG_ERPAREN */
+ };
+
+/* Subroutine declarations and macros for regex_compile. */
+
+static void store_op1 (), store_op2 ();
+static void insert_op1 (), insert_op2 ();
+static boolean at_begline_loc_p (), at_endline_loc_p ();
+static boolean group_in_compile_stack ();
+static reg_errcode_t compile_range ();
+
+/* 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'). */
+#define PATFETCH(c) \
+ do {if (p == pend) return REG_EEND; \
+ c = (unsigned char) *p++; \
+ if (translate) c = translate[c]; \
+ } while (0)
+
+/* 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. */
+#define TRANSLATE(d) (translate ? translate[(unsigned char) (d)] : (d))
+
+
+/* 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 (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, (to) - (loc) - 3)
+
+/* Likewise, for a two-argument jump. */
+#define STORE_JUMP2(op, loc, to, arg) \
+ store_op2 (op, loc, (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, (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, (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. */
+#define MAX_BUF_SIZE (1L << 16)
+
+
+/* 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. */
+typedef int 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); \
+ } \
+ } \
+ }
+
+#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"))
+
+/* `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. */
+
+static reg_errcode_t
+regex_compile (pattern, size, syntax, bufp)
+ const char *pattern;
+ int 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 tempory 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. */
+ char *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++)
+ printchar (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) 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)
+ 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) 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) 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) return REG_EBRACK;
+
+ PATFETCH (c);
+
+ /* \ might escape characters inside [...] and [^...]. */
+ if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\')
+ {
+ if (p == pend) 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 != ']')
+ 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) 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) 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) return REG_EBRACK;
+
+ for (;;)
+ {
+ PATFETCH (c);
+ if (c == ':' || c == ']' || p == pend
+ || c1 == CHAR_CLASS_MAX_LENGTH)
+ break;
+ str[c1++] = c;
+ }
+ 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 == ']')
+ {
+ 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)) return REG_ECTYPE;
+
+ /* Throw away the ] at the end of the character
+ class. */
+ PATFETCH (c);
+
+ if (p == pend) return REG_EBRACK;
+
+ for (ch = 0; ch < 1 << BYTEWIDTH; ch++)
+ {
+ if ( (is_alnum && ISALNUM (ch))
+ || (is_alpha && ISALPHA (ch))
+ || (is_blank && ISBLANK (ch))
+ || (is_cntrl && ISCNTRL (ch))
+ || (is_digit && ISDIGIT (ch))
+ || (is_graph && ISGRAPH (ch))
+ || (is_lower && ISLOWER (ch))
+ || (is_print && ISPRINT (ch))
+ || (is_punct && ISPUNCT (ch))
+ || (is_space && ISSPACE (ch))
+ || (is_upper && ISUPPER (ch))
+ || (is_xdigit && ISXDIGIT (ch)))
+ SET_LIST_BIT (ch);
+ }
+ had_char_class = true;
+ }
+ 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) 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
+ 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
+ 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
+ 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
+ return REG_BADBR;
+ }
+
+ if (!(syntax & RE_NO_BK_BRACES))
+ {
+ if (c != '\\') return REG_EBRACE;
+
+ PATFETCH (c);
+ }
+
+ if (c != '}')
+ {
+ if (syntax & RE_NO_BK_BRACES)
+ goto unfetch_interval;
+ else
+ 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)
+ 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> <succed_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':
+ laststart = b;
+ BUF_PUSH (wordchar);
+ break;
+
+
+ case 'W':
+ laststart = b;
+ BUF_PUSH (notwordchar);
+ break;
+
+
+ case '<':
+ BUF_PUSH (wordbeg);
+ break;
+
+ case '>':
+ BUF_PUSH (wordend);
+ break;
+
+ case 'b':
+ BUF_PUSH (wordbound);
+ break;
+
+ case 'B':
+ BUF_PUSH (notwordbound);
+ break;
+
+ case '`':
+ BUF_PUSH (begbuf);
+ break;
+
+ case '\'':
+ 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)
+ return REG_ESUBREG;
+
+ /* Can't back reference to a subexpression if inside of it. */
+ if (group_in_compile_stack (compile_stack, 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)
+ return REG_EPAREN;
+
+ 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: ");
+ print_compiled_pattern (bufp);
+ }
+#endif /* DEBUG */
+
+ 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;
+ int syntax;
+{
+ const char *next = p;
+ boolean next_backslash = *next == '\\';
+ const char *next_next = p + 1 < pend ? p + 1 : NULL;
+
+ 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;
+ char *translate;
+ reg_syntax_t syntax;
+ unsigned char *b;
+{
+ unsigned this_char;
+
+ const char *p = *p_ptr;
+ 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. */
+ range_start = ((unsigned char *) p)[-2];
+ range_end = ((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;
+}
+
+/* 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. */
+
+
+/* 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_SPACE each time we failed.
+ This is a variable only so users of regex can assign to it; we never
+ change it ourselves. */
+int re_max_failures = 2000;
+
+typedef const unsigned char *fail_stack_elt_t;
+
+typedef struct
+{
+ fail_stack_elt_t *stack;
+ unsigned size;
+ unsigned avail; /* Offset of next open position. */
+} fail_stack_type;
+
+#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 FAIL_STACK_TOP() (fail_stack.stack[fail_stack.avail])
+
+
+/* Initialize `fail_stack'. Do `return -2' if the alloc fails. */
+
+#define INIT_FAIL_STACK() \
+ do { \
+ fail_stack.stack = (fail_stack_elt_t *) \
+ REGEX_ALLOCATE (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)
+
+
+/* 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 requires `destination' be declared. */
+
+#define DOUBLE_FAIL_STACK(fail_stack) \
+ ((fail_stack).size > re_max_failures * MAX_FAILURE_ITEMS \
+ ? 0 \
+ : ((fail_stack).stack = (fail_stack_elt_t *) \
+ REGEX_REALLOCATE ((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 PATTERN_OP 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(pattern_op, fail_stack) \
+ ((FAIL_STACK_FULL () \
+ && !DOUBLE_FAIL_STACK (fail_stack)) \
+ ? 0 \
+ : ((fail_stack).stack[(fail_stack).avail++] = pattern_op, \
+ 1))
+
+/* This pushes an item onto the failure stack. Must be a four-byte
+ value. Assumes the variable `fail_stack'. Probably should only
+ be called from within `PUSH_FAILURE_POINT'. */
+#define PUSH_FAILURE_ITEM(item) \
+ fail_stack.stack[fail_stack.avail++] = (fail_stack_elt_t) item
+
+/* The complement operation. Assumes `fail_stack' is nonempty. */
+#define POP_FAILURE_ITEM() 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_ITEM
+#define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_ITEM ()
+#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 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. */ \
+ int 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: %d\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"); \
+ \
+ for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \
+ this_reg++) \
+ { \
+ DEBUG_PRINT2 (" Pushing reg: %d\n", this_reg); \
+ DEBUG_STATEMENT (num_regs_pushed++); \
+ \
+ DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \
+ PUSH_FAILURE_ITEM (regstart[this_reg]); \
+ \
+ DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \
+ PUSH_FAILURE_ITEM (regend[this_reg]); \
+ \
+ DEBUG_PRINT2 (" info: 0x%x\n ", reg_info[this_reg]); \
+ 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_ITEM (reg_info[this_reg].word); \
+ } \
+ \
+ DEBUG_PRINT2 (" Pushing low active reg: %d\n", lowest_active_reg);\
+ PUSH_FAILURE_ITEM (lowest_active_reg); \
+ \
+ DEBUG_PRINT2 (" Pushing high active reg: %d\n", highest_active_reg);\
+ PUSH_FAILURE_ITEM (highest_active_reg); \
+ \
+ DEBUG_PRINT2 (" Pushing pattern 0x%x: ", pattern_place); \
+ DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend); \
+ PUSH_FAILURE_ITEM (pattern_place); \
+ \
+ DEBUG_PRINT2 (" Pushing string 0x%x: `", string_place); \
+ DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, \
+ size2); \
+ DEBUG_PRINT1 ("'\n"); \
+ PUSH_FAILURE_ITEM (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. */
+#define MAX_FAILURE_ITEMS ((num_regs - 1) * NUM_REG_ITEMS + NUM_NONREG_ITEMS)
+
+/* We actually push this many items. */
+#define NUM_FAILURE_ITEMS \
+ ((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 (fail_stack_elt_t failure_id;) \
+ int 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_ITEM (); \
+ if (string_temp != NULL) \
+ str = (const char *) string_temp; \
+ \
+ DEBUG_PRINT2 (" Popping string 0x%x: `", str); \
+ DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \
+ DEBUG_PRINT1 ("'\n"); \
+ \
+ pat = (unsigned char *) POP_FAILURE_ITEM (); \
+ DEBUG_PRINT2 (" Popping pattern 0x%x: ", pat); \
+ DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \
+ \
+ /* Restore register info. */ \
+ high_reg = (unsigned) POP_FAILURE_ITEM (); \
+ DEBUG_PRINT2 (" Popping high active reg: %d\n", high_reg); \
+ \
+ low_reg = (unsigned) POP_FAILURE_ITEM (); \
+ DEBUG_PRINT2 (" Popping low active reg: %d\n", low_reg); \
+ \
+ for (this_reg = high_reg; this_reg >= low_reg; this_reg--) \
+ { \
+ DEBUG_PRINT2 (" Popping reg: %d\n", this_reg); \
+ \
+ reg_info[this_reg].word = POP_FAILURE_ITEM (); \
+ DEBUG_PRINT2 (" info: 0x%x\n", reg_info[this_reg]); \
+ \
+ regend[this_reg] = (const char *) POP_FAILURE_ITEM (); \
+ DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \
+ \
+ regstart[this_reg] = (const char *) POP_FAILURE_ITEM (); \
+ DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \
+ } \
+ \
+ DEBUG_STATEMENT (nfailure_points_popped++); \
+} /* POP_FAILURE_POINT */
+
+/* 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;
+ fail_stack_type fail_stack;
+#ifndef REGEX_MALLOC
+ char *destination;
+#endif
+ /* We don't push any register information onto the failure stack. */
+ unsigned num_regs = 0;
+
+ register char *fastmap = bufp->fastmap;
+ unsigned char *pattern = bufp->buffer;
+ unsigned long size = bufp->used;
+ const unsigned char *p = pattern;
+ register unsigned char *pend = pattern + size;
+
+ /* 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 (p != pend || !FAIL_STACK_EMPTY ())
+ {
+ if (p == pend)
+ {
+ bufp->can_be_null |= path_can_be_null;
+
+ /* Reset for next path. */
+ path_can_be_null = true;
+
+ p = fail_stack.stack[--fail_stack.avail];
+ }
+
+ /* We should never be about to go beyond the end of the pattern. */
+ assert (p < pend);
+
+#ifdef SWITCH_ENUM_BUG
+ switch ((int) ((re_opcode_t) *p++))
+#else
+ switch ((re_opcode_t) *p++)
+#endif
+ {
+
+ /* 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;
+ return 0;
+
+
+ /* 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:
+ /* `.' matches anything ... */
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ fastmap[j] = 1;
+
+ /* ... except perhaps newline. */
+ if (!(bufp->syntax & RE_DOT_NEWLINE))
+ fastmap['\n'] = 0;
+
+ /* 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)
+ return 0;
+
+ /* 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 /* not 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] == 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))
+ 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;
+ return 0;
+} /* re_compile_fastmap */
+
+/* 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;
+ }
+}
+
+/* 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);
+}
+
+
+/* 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 char *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. */
+ if (endpos < -1)
+ range = -1 - 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 && (re_opcode_t) bufp->buffer[0] == begbuf && range > 0)
+ {
+ if (startpos > 0)
+ return -1;
+ else
+ range = 1;
+ }
+
+ /* 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 (bufp, string1, size1, string2, size2,
+ startpos, regs, stop);
+ 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 */
+
+/* Declarations and macros for re_match_2. */
+
+static int bcmp_translate ();
+static boolean alt_match_null_string_p (),
+ common_op_match_null_string_p (),
+ group_match_null_string_p ();
+
+/* Structure for per-register (a.k.a. per-group) information.
+ This must not be longer than one word, because we push this value
+ onto the failure stack. 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. */
+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 \
+ { \
+ unsigned r; \
+ for (r = lowest_active_reg; r <= highest_active_reg; r++) \
+ { \
+ MATCHED_SOMETHING (reg_info[r]) \
+ = EVER_MATCHED_SOMETHING (reg_info[r]) \
+ = 1; \
+ } \
+ } \
+ while (0)
+
+
+/* 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) ? (ptr) - string1 : (ptr) - string2 + size1)
+
+/* Registers are set to a sentinel when they haven't yet matched. */
+#define REG_UNSET_VALUE ((char *) -1)
+#define REG_UNSET(e) ((e) == REG_UNSET_VALUE)
+
+
+/* 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)
+
+/* 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))
+
+
+/* Free everything we malloc. */
+#ifdef REGEX_MALLOC
+#define FREE_VAR(var) if (var) free (var); var = NULL
+#define FREE_VARIABLES() \
+ do { \
+ FREE_VAR (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 /* not REGEX_MALLOC */
+/* Some MIPS systems (at least) want this to free alloca'd storage. */
+#define FREE_VARIABLES() alloca (0)
+#endif /* not REGEX_MALLOC */
+
+
+/* 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;
+ {
+ return re_match_2 (bufp, NULL, 0, string, size, pos, regs, size);
+}
+#endif /* not emacs */
+
+
+/* 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;
+{
+ /* 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;
+
+ /* We use this to map every character in the string. */
+ char *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. */
+ fail_stack_type fail_stack;
+#ifdef DEBUG
+ static unsigned failure_id = 0;
+ unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0;
+#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. */
+ unsigned num_regs = bufp->re_nsub + 1;
+
+ /* The currently active registers. */
+ unsigned lowest_active_reg = NO_LOWEST_ACTIVE_REG;
+ unsigned 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.) */
+ const char **regstart, **regend;
+
+ /* 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. */
+ const char **old_regstart, **old_regend;
+
+ /* 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. */
+ register_info_type *reg_info;
+
+ /* 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;
+ const char **best_regstart, **best_regend;
+
+ /* 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;
+
+ /* Used when we pop values we don't care about. */
+ const char **reg_dummy;
+ register_info_type *reg_info_dummy;
+
+#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 ();
+
+ /* 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;
+ }
+ }
+#ifdef REGEX_MALLOC
+ 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 /* REGEX_MALLOC */
+
+ /* 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; 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: ");
+ 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 (;;)
+ {
+ DEBUG_PRINT2 ("\n0x%x: ", p);
+
+ 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)
+ {
+ DEBUG_PRINT1 ("backtracking.\n");
+
+ if (!FAIL_STACK_EMPTY ())
+ { /* More failure points to try. */
+ boolean same_str_p = (FIRST_STRING_P (match_end)
+ == MATCHING_IN_FIRST_STRING);
+
+ /* If exceeds best match so far, save it. */
+ if (!best_regs_set
+ || (same_str_p && d > match_end)
+ || (!same_str_p && !MATCHING_IN_FIRST_STRING))
+ {
+ best_regs_set = true;
+ match_end = d;
+
+ DEBUG_PRINT1 ("\nSAVING match as best so far.\n");
+
+ for (mcnt = 1; mcnt < num_regs; mcnt++)
+ {
+ best_regstart[mcnt] = regstart[mcnt];
+ best_regend[mcnt] = regend[mcnt];
+ }
+ }
+ goto fail;
+ }
+
+ /* If no failure points, don't restore garbage. */
+ else if (best_regs_set)
+ {
+ 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; mcnt < num_regs; mcnt++)
+ {
+ regstart[mcnt] = best_regstart[mcnt];
+ regend[mcnt] = best_regend[mcnt];
+ }
+ }
+ } /* d != end_match_2 */
+
+ 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)
+ 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)
+ return -2;
+ }
+ }
+ else
+ 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 ? d - string1
+ : d - string2 + size1);
+ }
+
+ /* Go through the first `min (num_regs, regs->num_regs)'
+ registers, since that is all we initialized. */
+ for (mcnt = 1; 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] = POINTER_TO_OFFSET (regstart[mcnt]);
+ regs->end[mcnt] = 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; mcnt < regs->num_regs; mcnt++)
+ regs->start[mcnt] = regs->end[mcnt] = -1;
+ } /* regs && !bufp->no_sub */
+
+ FREE_VARIABLES ();
+ 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);
+
+ return mcnt;
+ }
+
+ /* Otherwise match next pattern command. */
+#ifdef SWITCH_ENUM_BUG
+ switch ((int) ((re_opcode_t) *p++))
+#else
+ switch ((re_opcode_t) *p++)
+#endif
+ {
+ /* 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;
+
+
+ /* 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 (translate[(unsigned char) *d++] != (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;
+
+ /* 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;
+ 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;
+
+ /* 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])
+ || (re_opcode_t) p[-3] == start_memory)
+ && (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 < *p + *(p + 1); r++)
+ {
+ regstart[r] = old_regstart[r];
+
+ /* xx why this test? */
+ if ((int) old_regend[r] >= (int) 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)
+ : bcmp (d, d2, mcnt))
+ goto fail;
+ d += mcnt, d2 += mcnt;
+ }
+ }
+ 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);
+ DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt);
+
+ 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);
+ DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt);
+
+ /* 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 \(\(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. */
+ while (p2 + 2 < pend
+ && ((re_opcode_t) *p2 == stop_memory
+ || (re_opcode_t) *p2 == start_memory))
+ p2 += 3; /* Skip over args, too. */
+
+ /* 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];
+ 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 ((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");
+ }
+ }
+ }
+ }
+ 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'. */
+ unsigned 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. */
+
+
+ /* Unconditionally jump (without popping any failure points). */
+ case jump:
+ unconditional_jump:
+ EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */
+ DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt);
+ p += mcnt; /* Do the jump. */
+ DEBUG_PRINT2 ("(to 0x%x).\n", p);
+ 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 (0, 0, -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 (0, 0, -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);
+ DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p, mcnt);
+ }
+ else if (mcnt == 0)
+ {
+ DEBUG_PRINT2 (" Setting two bytes from 0x%x to no_op.\n", p+2);
+ 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);
+ 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);
+ DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p1, mcnt);
+ STORE_NUMBER (p1, mcnt);
+ break;
+ }
+
+ 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;
+
+ 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
+#ifdef emacs19
+ 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;
+#else /* not emacs19 */
+ case at_dot:
+ DEBUG_PRINT1 ("EXECUTING at_dot.\n");
+ if (PTR_CHAR_POS ((unsigned char *) d) + 1 != point)
+ goto fail;
+ break;
+#endif /* not emacs19 */
+
+ 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 ();
+ if (SYNTAX (*d++) != (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 ();
+ if (SYNTAX (*d++) == (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)
+ unsigned char *s1, *s2;
+ register int len;
+ char *translate;
+{
+ register unsigned char *p1 = s1, *p2 = 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;
+ int 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);
+
+ return re_error_msg[(int) ret];
+}
+
+/* Entry points compatible with 4.2 BSD regex library. We don't define
+ them if this is an Emacs or POSIX compilation. */
+
+#if !defined (emacs) && !defined (_POSIX_SOURCE)
+
+/* BSD has one and only one pattern buffer. */
+static struct re_pattern_buffer re_comp_buf;
+
+char *
+re_comp (s)
+ const char *s;
+{
+ reg_errcode_t ret;
+
+ if (!s)
+ {
+ if (!re_comp_buf.buffer)
+ return "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 "Memory exhausted";
+ re_comp_buf.allocated = 200;
+
+ re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH);
+ if (re_comp_buf.fastmap == NULL)
+ return "Memory exhausted";
+ }
+
+ /* 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);
+
+ /* Yes, we're discarding `const' here. */
+ return (char *) re_error_msg[(int) ret];
+}
+
+
+int
+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 /* not emacs and not _POSIX_SOURCE */
+
+/* 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' and `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;
+ unsigned 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;
+
+ /* Don't bother to use a fastmap when searching. This simplifies the
+ REG_NEWLINE case: if we used a fastmap, we'd have to put all the
+ characters after newlines into the fastmap. This way, we just try
+ every character. */
+ preg->fastmap = 0;
+
+ if (cflags & REG_ICASE)
+ {
+ unsigned i;
+
+ preg->translate = (char *) malloc (CHAR_SET_SIZE);
+ 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;
+
+ return (int) ret;
+}
+
+
+/* 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, regoff_t);
+ regs.end = TALLOC (nmatch, regoff_t);
+ if (regs.start == NULL || regs.end == NULL)
+ return (int) REG_NOMATCH;
+ }
+
+ /* 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);
+ free (regs.end);
+ }
+
+ /* We want zero return to mean success, unlike `re_search'. */
+ return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH;
+}
+
+
+/* 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 >= (sizeof (re_error_msg) / sizeof (re_error_msg[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 = re_error_msg[errcode];
+
+ /* POSIX doesn't require that we do anything in this case, but why
+ not be nice. */
+ if (! msg)
+ msg = "Success";
+
+ msg_size = strlen (msg) + 1; /* Includes the null. */
+
+ if (errbuf_size != 0)
+ {
+ if (msg_size > errbuf_size)
+ {
+ strncpy (errbuf, msg, errbuf_size - 1);
+ errbuf[errbuf_size - 1] = 0;
+ }
+ else
+ strcpy (errbuf, msg);
+ }
+
+ return msg_size;
+}
+
+
+/* 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;
+}
+
+#endif /* not emacs */
+
+/*
+Local variables:
+make-backup-files: t
+version-control: t
+trim-versions-without-asking: nil
+End:
+*/
diff --git a/Build/source/texk/contrib/regex/regex.h b/Build/source/texk/contrib/regex/regex.h
new file mode 100644
index 00000000000..7aa88be9f18
--- /dev/null
+++ b/Build/source/texk/contrib/regex/regex.h
@@ -0,0 +1,505 @@
+/* Definitions for data structures and routines for the regular
+ expression library, version 0.12.
+
+ Copyright (C) 1985, 1989, 1990, 1991, 1992, 1993 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef __REGEXP_LIBRARY_H__
+#define __REGEXP_LIBRARY_H__
+
+/* POSIX says that <sys/types.h> must be included (by the caller) before
+ <regex.h>. */
+
+#ifdef VMS
+/* VMS doesn't have `size_t' in <sys/types.h>, even though POSIX says it
+ should be there. */
+#include <stddef.h>
+#endif
+
+#if defined(WIN32)
+#pragma warning(disable : 4018)
+#include <malloc.h>
+#ifdef _DLL
+#ifdef MAKE_REGEX_DLL
+#define REGEXDLL __declspec( dllexport)
+#else
+#define REGEXDLL __declspec( dllimport)
+#endif
+#else
+#define REGEXDLL
+#endif
+#else /* ! WIN32 */
+#define REGEXDLL
+#endif
+
+/* 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 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 (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)
+
+/* 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 REGEXDLL 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_UNMATCHED_RIGHT_PAREN_ORD)
+
+#define RE_SYNTAX_POSIX_AWK \
+ (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS)
+
+#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
+#define RE_DUP_MAX ((1 << 15) - 1)
+
+
+/* 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
+{
+ 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. */
+
+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 allocated;
+
+ /* Number of bytes actually used in `buffer'. */
+ unsigned long 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. */
+ char *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;
+
+
+/* search.c (search_buffer) in Emacs needs this one opcode value. It is
+ defined both in `regex.c' and here. */
+#define RE_EXACTN_VALUE 1
+
+/* 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 REGEXDLL 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 REGEXDLL const char *re_compile_pattern
+ _RE_ARGS ((const char *pattern, int 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 REGEXDLL 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 REGEXDLL 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 REGEXDLL 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 REGEXDLL 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 REGEXDLL 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 REGEXDLL void re_set_registers
+ _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs,
+ unsigned num_regs, regoff_t *starts, regoff_t *ends));
+
+/* 4.2 bsd compatibility. */
+extern REGEXDLL char *re_comp _RE_ARGS ((const char *));
+extern REGEXDLL int re_exec _RE_ARGS ((const char *));
+
+/* POSIX compatibility. */
+extern REGEXDLL int regcomp _RE_ARGS ((regex_t *preg, const char *pattern, int cflags));
+extern REGEXDLL int regexec
+ _RE_ARGS ((const regex_t *preg, const char *string, size_t nmatch,
+ regmatch_t pmatch[], int eflags));
+extern REGEXDLL size_t regerror
+ _RE_ARGS ((int errcode, const regex_t *preg, char *errbuf,
+ size_t errbuf_size));
+extern REGEXDLL void regfree _RE_ARGS ((regex_t *preg));
+
+#endif /* not __REGEXP_LIBRARY_H__ */
+
+/*
+Local variables:
+make-backup-files: t
+version-control: t
+trim-versions-without-asking: nil
+End:
+*/
diff --git a/Build/source/texk/contrib/stackenv.c b/Build/source/texk/contrib/stackenv.c
new file mode 100644
index 00000000000..a4a831e5f5d
--- /dev/null
+++ b/Build/source/texk/contrib/stackenv.c
@@ -0,0 +1,343 @@
+/* stackenv.c: routines that help to mimic shell scripts.
+
+Copyright (C) 1997 Fabrice POPINEAU.
+
+Adapted to DJGPP by Eli Zaretskii.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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 this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "stackenv.h"
+#include "variables.h"
+
+string mktex_version_string = "2.0";
+
+extern char *output;
+extern char tmpdir[];
+extern char *progname;
+
+/* The global stack. */
+static mod_env stack_env[256];
+static int index_env = 0;
+
+void mt_exit(int);
+
+static FILE *fnul = NULL;
+
+pfnOutputAndCleanup output_and_cleanup_function;
+
+#ifndef _WIN32
+#include <unistd.h>
+
+void flushall (void)
+{
+ /* Simulate `flushall' by only flushing standard streams.
+ This should be enough, since the non-standard are going
+ to be closed in a moment, and will be flushed then. */
+ fflush (stdout);
+ fsync (fileno (stdout));
+ fflush (stderr);
+ fsync (fileno (stderr));
+}
+#endif
+
+#ifndef _WIN32
+#ifdef __DJGPP__
+
+/* DJGPP-specific emulation of functions which aren't in the library
+ and aren't ANSI/POSIX. */
+
+#include <errno.h>
+#include <libc/file.h>
+
+static void fcloseall_func (FILE *f)
+{
+ fflush (f);
+ if (fileno (f) > 2)
+ fclose(f);
+ else
+ fsync (fileno (f));
+}
+
+void fcloseall (void)
+{
+ _fwalk (fcloseall_func);
+}
+
+#else /* not __DJGPP__ */
+
+/* FIXME: is this enough on Unix? */
+static void fcloseall (void)
+{
+ flushall ();
+}
+
+#endif /* not __DJGPP__ */
+#endif /* not _WIN32 */
+
+void
+oops(const char *message, ...)
+{
+ va_list args;
+
+ va_start(args, message);
+ vfprintf(stderr, message, args);
+ va_end(args);
+ fputc('\n', stderr);
+ mt_exit(1);
+}
+
+/* pushd */
+void pushd(char *p)
+{
+ if (index_env >= sizeof(stack_env)/sizeof(stack_env[0])) {
+ fprintf(stderr, "%s: stack overflow in pushd\n", progname);
+ mt_exit(1);
+ }
+ if ((stack_env[index_env].data.path = malloc(MAXPATHLEN)) == NULL
+ || getcwd(stack_env[index_env].data.path, MAXPATHLEN) == NULL) {
+ fprintf(stderr, "pushd error!\n");
+ mt_exit(1);
+ }
+ stack_env[index_env].op = CHDIR;
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG)) {
+ fprintf(stderr, "At %d, pushing from %s to %s\n", index_env,
+ stack_env[index_env].data.path, p);
+ }
+
+ index_env++;
+ if (chdir(p) == -1) {
+ perror(p);
+ mt_exit(1);
+ }
+}
+/* popd */
+void popd()
+{
+ if (index_env == 0)
+ return;
+ index_env--;
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG)) {
+ fprintf(stderr, "At %d, popping %s\n", index_env, stack_env[index_env].data.path);
+ }
+ assert(stack_env[index_env].op == CHDIR);
+ if (chdir(stack_env[index_env].data.path) == -1) {
+ perror(stack_env[index_env].data.path);
+ mt_exit(1);
+ }
+ free(stack_env[index_env].data.path);
+ return;
+}
+
+/* random access to directories' stack */
+char *peek_dir(int n)
+{
+ int i;
+ int level = n;
+
+ /* The stack holds both directories pushed by `pushd' and file
+ handles pushed by `push_fd'. When they say "peek_dir(n)", they
+ mean the n'th DIRECTORY entry, not the n'th entry counting from
+ the stack bottom.
+
+ For example, if the stack looks like this:
+
+ idx type
+
+ 0 handles
+ 1 handles
+ 2 directory
+ 3 handles <--- top of the stack
+ 4 <empty> <--- index_env
+
+ then "peek_dir(0)" should return the entry with the index 2, not
+ the one with the index 0.
+
+ The following loop looks for the index i of a stack slot which
+ holds the n'th directory pushed on to the stack. */
+
+ do {
+ for (i = 0; i < index_env && stack_env[i].op != CHDIR; i++)
+ ;
+ } while (i < index_env && n--);
+
+ if (i < index_env)
+ return stack_env[i].data.path;
+ else {
+ fprintf (stderr, "%s: attempt to peek at invalid stack level %d\n",
+ progname, level);
+ mt_exit(1);
+ }
+}
+
+/* redirect */
+void push_fd(int newfd[3])
+{
+ int i;
+
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG)) {
+ fprintf(stderr, "At %d, pushing fds %d %d %d\n", index_env, newfd[0],
+ newfd[1], newfd[2]);
+ }
+ flushall();
+ if (index_env >= sizeof(stack_env)/sizeof(stack_env[0])) {
+ fprintf(stderr, "%s: stack overflow in push_fd\n", progname);
+ mt_exit(1);
+ }
+ stack_env[index_env].op = REDIRECT;
+ for(i = 0; i < 3; i++) {
+ if (i == newfd[i])
+ stack_env[index_env].data.oldfd[i] = i;
+ else {
+ if ((stack_env[index_env].data.oldfd[i] = dup(i)) == -1) {
+ perror("push_fd: dup");
+ mt_exit(1);
+ }
+ if (dup2(newfd[i], i) == -1) {
+ perror("push_fd : dup2");
+ mt_exit(1);
+ }
+ }
+ }
+ index_env++;
+}
+
+void pop_fd()
+{
+ int i;
+ index_env--;
+ assert(stack_env[index_env].op == REDIRECT);
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG)) {
+ fprintf(stderr, "At %d; popping fds %d %d %d\n",
+ index_env,
+ stack_env[index_env].data.oldfd[0],
+ stack_env[index_env].data.oldfd[1],
+ stack_env[index_env].data.oldfd[2]);
+ }
+ flushall();
+ for(i = 0; i < 3; i++)
+ if (i != stack_env[index_env].data.oldfd[i]) {
+ if (fnul && i != fileno(fnul)) close(i);
+ if (dup2(stack_env[index_env].data.oldfd[i], i) == -1) {
+ perror("pop_fd : dup2");
+ mt_exit(1);
+ }
+ if (fnul && stack_env[index_env].data.oldfd[i] != fileno(fnul))
+ close(stack_env[index_env].data.oldfd[i]);
+ }
+}
+
+/* popenv */
+void popenv()
+{
+ if (index_env <= 0) {
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG))
+ fprintf(stderr, "Trying to popenv() from empty stack!\n");
+ return;
+ }
+
+ switch(stack_env[index_env-1].op) {
+ case CHDIR:
+ popd();
+ break;
+ case REDIRECT:
+ pop_fd();
+ break;
+ default:
+ fprintf(stderr, "popenv : unknown op %d.\n", stack_env[index_env-1].op);
+ break;
+ }
+}
+
+#ifdef _WIN32
+BOOL sigint_handler(DWORD dwCtrlType)
+{
+ /* Fix me : there is a problem if a system() command is running.
+ We should wait for the son process to be interrupted.
+ Only way I can think of to do that : rewrite system() based on
+ spawn() with parsing of the command line and set a global pid
+ Next cwait(pid) in the HandlerRoutine.
+ */
+
+ /* This is not that good, but else we would need to wait for
+ the child processes to finish ! */
+ Sleep(250);
+
+ mt_exit(3);
+ return FALSE; /* return value obligatory */
+}
+#else
+void sigint_handler (int sig)
+{
+ mt_exit(3);
+}
+#endif
+
+void mt_exit(int code)
+{
+ /* rétablir les 0, 1 et 2 d'origine avant de tenter quoi que ce soit ! */
+ fcloseall();
+
+ /* unstack all env from main) */
+ for( ; index_env > 0; popenv());
+
+ /* output the result and rm any unneeded file */
+ if (output_and_cleanup_function != 0)
+ (*output_and_cleanup_function)(code);
+
+ exit(code);
+}
+
+void
+dump_stack()
+{
+ int i;
+ for (i = 0; i < index_env; i++)
+ switch (stack_env[i].op) {
+ case CHDIR:
+ fprintf(stderr, "Env %d : chdir %s\n", i, stack_env[i].data.path);
+ break;
+ case REDIRECT:
+ fprintf(stderr, "Env %d : redirect %d %d %d\n", i,
+ stack_env[i].data.oldfd[0],
+ stack_env[i].data.oldfd[1],
+ stack_env[i].data.oldfd[2]);
+ break;
+ }
+
+}
+
+/*
+ This is used by mktex{mf,tfm,pk}
+ if the argument is true, stdout is redirected to fnul
+ else to stderr.
+ */
+void start_redirection(boolean discard_stdout)
+{
+ int newfd[3];
+ if (fnul == NULL)
+#ifdef _WIN32
+ fnul = fopen("nul", "r"); /* fopen /dev/null */
+#else
+ fnul = fopen("/dev/null", "r");
+#endif
+
+ newfd[0] = fileno(fnul);
+ newfd[1] = (discard_stdout ? fileno(fnul) : fileno(stderr));
+ newfd[2] = fileno(stderr);
+
+ push_fd(newfd);
+}
+
+
diff --git a/Build/source/texk/contrib/stackenv.h b/Build/source/texk/contrib/stackenv.h
new file mode 100644
index 00000000000..58df686b3eb
--- /dev/null
+++ b/Build/source/texk/contrib/stackenv.h
@@ -0,0 +1,46 @@
+#ifndef _STACKENV_H_
+
+#define _STACKENV_H_
+
+#include "mktexlib.h"
+
+/*
+ We are keeping trace of the environment (ie: cwd, file redirections)
+ with the help of these ops and structures. There is a global stack
+ inidcating wich actions have been taken.
+ */
+typedef enum { CHDIR = 1, REDIRECT } op_env;
+typedef struct mod_env {
+ op_env op;
+ union {
+ char *path;
+ int oldfd[3];
+ } data;
+} mod_env;
+
+/* from stackenv.c */
+extern void oops(const char *, ...);
+#ifdef __GNUC__
+extern void mt_exit(int) __attribute__((noreturn));
+#else
+extern MKTEXDLL void mt_exit(int);
+#endif
+extern MKTEXDLL void pushd(char *);
+extern MKTEXDLL void popd(void);
+extern MKTEXDLL void popenv(void);
+extern char *peek_dir(int);
+extern MKTEXDLL void push_fd(int [3]);
+extern MKTEXDLL void pop_fd(void);
+extern MKTEXDLL void start_redirection(boolean);
+#ifdef _WIN32
+/* extern void mt_exit(int); */
+extern MKTEXDLL BOOL sigint_handler(DWORD);
+#else
+extern void sigint_handler(int);
+#endif
+
+typedef void (__cdecl * pfnOutputAndCleanup)(int);
+extern MKTEXDLL pfnOutputAndCleanup output_and_cleanup_function;
+
+extern MKTEXDLL int redirect_stdout;
+#endif /* _STACKENV_H_ */
diff --git a/Build/source/texk/contrib/variables.c b/Build/source/texk/contrib/variables.c
new file mode 100644
index 00000000000..d1837bd6b4b
--- /dev/null
+++ b/Build/source/texk/contrib/variables.c
@@ -0,0 +1,472 @@
+/* variables.c: this package provides symbols and dynamic strings
+
+Copyright (C) 1997 Fabrice POPINEAU.
+
+Time-stamp: <03/02/21 11:54:23 popineau>
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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 this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "stackenv.h"
+#include "fileutils.h"
+#include "variables.h"
+#include <regex.h>
+
+/*
+ We will use kpathsea's hash tables
+ */
+
+/* The symbol table */
+hash_table_type *symtab = NULL;
+
+/* Initialize a symbol table to store all the vars used by
+ the various shell scripts. */
+void init_vars()
+{
+
+ symtab = hash_create(719, hashtable_symtab);
+
+}
+
+void
+hash_remove_all (hash_table_type *table, string key)
+{
+ string *val;
+ while ((val = hash_lookup(table, key))) {
+ hash_remove(table, key, *val);
+ free (val);
+ }
+}
+
+string getval(string name)
+{
+ string *lookup = NULL;
+ string res = NULL;
+
+ /*
+ Either the name is already in the symbol table ...
+ */
+ if ((lookup = hash_lookup(symtab, name)) != NULL) {
+ /* FIXME: we return the first value ... */
+ res = lookup[0];
+ free(lookup);
+ }
+#if 0
+ else if ((lookup = hash_lookup(symtab, vname)) != NULL) {
+ /* FIXME: we return the first value ... */
+ res = lookup[0];
+ free(lookup);
+ }
+ else {
+ string dollar_name = concat("$", vname);
+ res = kpse_cnf_get(vname);
+ free(dollar_name);
+ }
+#endif
+ if (!res) {
+#if 0
+ /*
+ ... Either it is known from kpathsea, in which case we put it
+ in the symbol table.
+ */
+ string dollar_name = concat("$", vname);
+ res = expand_var(dollar_name);
+
+ if (test_file('n', res)) {
+ setval(vname, res);
+ }
+ else {
+ /* res = "", so return NULL */
+ res = NULL;
+ }
+ free (dollar_name);
+#endif
+ res = getenv(name);
+ }
+
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG)) {
+ fprintf(stderr, "GetVal %s => %s\n", name, res);
+ }
+
+ /* In any case ... */
+ return res;
+}
+
+string setval(string name, string value)
+{
+ /* Be safe ... */
+ if (!value) value = "";
+ hash_remove_all(symtab, name);
+ hash_insert(symtab, name, value);
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG)) {
+ fprintf(stderr, "SetVal %s <= %s\n", name, value);
+ }
+
+ return value;
+}
+
+string setval_default(string name, string value)
+{
+ string old_value;
+ /* Be safe ... */
+ if (!value) {
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG)) {
+ fprintf(stderr, "setval_default: inserting NULL value for %s!\n", name);
+ }
+ value = "";
+ }
+
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG)) {
+ fprintf(stderr, "SetVal default %s ... ", name);
+ }
+
+ /* The mktex... scripts NEVER use ${foo:=bar}, always ${foo=bar}.
+ So we only need to set NAME=VALUE if $NAME is unset. */
+ if ((old_value = getval(name)) == NULL) {
+ hash_insert(symtab, name, value);
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG)) {
+ fprintf(stderr, "SetVal %s <= %s\n", name, value);
+ }
+ }
+ else
+ value = old_value;
+
+ return value;
+}
+
+string *grep(char *regexp, char *line, int num_vars)
+{
+ struct re_pattern_buffer *rc;
+ struct re_registers *p;
+ const_string ok;
+ string *vars = NULL;
+ string *lookup;
+ int i;
+
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG)) {
+ fprintf(stderr, "Grep\n\t%s\n\tin\n\t%s\n", regexp, line);
+ }
+
+ if (test_file('z', line))
+ return NULL;
+
+ /* This will retrieve the precompiled regexp or compile it and
+ remember it. vars contains the strings matched, num_vars the number
+ of these strings. */
+#if 0
+ if ((lookup = hash_lookup(symtab, regexp)))
+ rc = (struct re_pattern_buffer *)lookup[0];
+ else
+ rc = NULL;
+ if (rc == NULL) {
+#endif
+ /* Compile the regexp and stores the result */
+
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG)) {
+ fprintf(stderr, "\tCompiling the regexp\n");
+ }
+
+ re_syntax_options = RE_SYNTAX_POSIX_EGREP;
+ rc = (struct re_pattern_buffer *) calloc(1, sizeof(struct re_pattern_buffer));
+ rc->regs_allocated = REGS_UNALLOCATED;
+ if ((ok = re_compile_pattern(regexp, strlen(regexp), rc)) != 0)
+ FATAL1("Can't compile regex %s\n", regexp);
+#if 0
+ hash_remove_all(symtab, regexp);
+ hash_insert(symtab, regexp, (char *)rc);
+ }
+ else if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG)) {
+ fprintf(stderr, "\tAlready compiled\n");
+ }
+#endif
+
+ p = (struct re_registers *) calloc(1, sizeof(struct re_registers));
+ p->num_regs = num_vars;
+ if ((re_match(rc, line, strlen(line), 0, p)) > 0) {
+ vars = (char **) xmalloc ((num_vars+1) * sizeof(char *));
+ for (i = 0; i <= num_vars; i++) {
+ vars[i] = malloc((p->end[i] - p->start[i] + 1)*sizeof(char));
+ strncpy(vars[i], line+p->start[i], p->end[i] - p->start[i]);
+ vars[i][p->end[i] - p->start[i]] = '\0';
+ }
+ }
+ free (p);
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG)) {
+ if (vars)
+ for(i = 0; i <= num_vars; i++)
+ fprintf(stderr, "String %d matches %s\n", i, vars[i]);
+ }
+ return vars;
+}
+
+/* read a line, trying to find 'variable = value'
+ Currently groks two constructs:
+ VAR=value
+ : {VAR=value}
+ using regex to analyze them.
+ The variable is added to the symbol table. In the first case, it
+ overrides an old value, not in the second case.
+ */
+boolean parse_variable(string line)
+{
+ char **vars;
+
+ static char *r1 = "^[[:space:]]*([[:alnum:]_]+)=[[:space:]]*([^[:space:]]*)[[:space:]]*.*$";
+ static char *r2 = "^:[[:space:]]+\\$\\{([[:alnum:]_]+)=([^\\}]*)\\}[[:space:]]*.*$";
+
+ if ((vars = grep(r1, line, 2))) {
+ setval(vars[1], vars[2]);
+ return true;
+ }
+ else if ((vars = grep(r2, line, 2))) {
+ setval_default(vars[1], vars[2]);
+ return true;
+ }
+ else
+ WARNING1("The following line has not been parsed:\n%s\n", line);
+ return false;
+}
+
+/* Substitute from by to in line */
+string subst(string line, string from, string to)
+{
+ string before, after, p;
+
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG)) {
+ fprintf(stderr, "Substituting %s by %s in %s\n", from, to, line);
+ }
+
+ if ((p = strstr(line, from))) {
+ before = xstrdup(line);
+ before[p-line] = '\0';
+ after = p+strlen(from);
+ p = concat3(before, to , after);
+ free (before);
+ }
+ else
+ p = xstrdup(line);
+
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG)) {
+ fprintf(stderr, "=> gives %s\n", p);
+ }
+
+ return p;
+}
+
+/* kpse_expand_var does not remove leading !!, but we do not need
+ them in mktex*
+ (Parts of code shamelessly stolen from remove_dbonly on tex-file.c.)
+ */
+string expand_var(const_string s)
+{
+ string p, q;
+ string res = NULL;
+
+ if (s) {
+ boolean new_elt = true;
+
+ res = mktex_var_expand(s);
+
+ for (p = q = res; *p; ) {
+ if (new_elt && *p == '!' && p[1] == '!')
+ p += 2;
+ else {
+ new_elt = *p == ENV_SEP;
+ *q++ = *p++;
+ }
+ }
+ *q = '\0';
+
+ if (KPSE_DEBUG_P(MKTEX_FINE_DEBUG)) {
+ fprintf(stderr, "Expanding variable %s into %s\n", s, res);
+ }
+ }
+
+ return res;
+}
+
+/*
+ This is shamelessly stolen from kpathsea/variable.c .
+ We want to do expansion without having to put variables in the
+ environment.
+ */
+
+/* We have to keep track of variables being expanded, otherwise
+ constructs like TEXINPUTS = $TEXINPUTS result in an infinite loop.
+ (Or indirectly recursive variables, etc.) Our simple solution is to
+ add to a list each time an expansion is started, and check the list
+ before expanding. */
+
+typedef struct {
+ const_string var;
+ boolean expanding;
+} expansion_type;
+static expansion_type *expansions; /* The sole variable of this type. */
+static unsigned expansion_len = 0;
+
+static void
+expanding P2C(const_string, var, boolean, xp)
+{
+ unsigned e;
+ for (e = 0; e < expansion_len; e++) {
+ if (STREQ (expansions[e].var, var)) {
+ expansions[e].expanding = xp;
+ return;
+ }
+ }
+
+ /* New variable, add it to the list. */
+ expansion_len++;
+ XRETALLOC (expansions, expansion_len, expansion_type);
+ expansions[expansion_len - 1].var = xstrdup (var);
+ expansions[expansion_len - 1].expanding = xp;
+}
+
+
+/* Return whether VAR is currently being expanding. */
+
+static boolean
+expanding_p P1C(const_string, var)
+{
+ unsigned e;
+ for (e = 0; e < expansion_len; e++) {
+ if (STREQ (expansions[e].var, var))
+ return expansions[e].expanding;
+ }
+
+ return false;
+}
+
+/* Append the result of value of `var' to EXPANSION, where `var' begins
+ at START and ends at END. If `var' is not set, do not complain.
+ This is a subroutine for the more complicated expansion function. */
+
+static void
+expand P3C(fn_type *, expansion, const_string, start, const_string, end)
+{
+ string value;
+ unsigned len = end - start + 1;
+ string var = xmalloc (len + 1);
+ strncpy (var, start, len);
+ var[len] = 0;
+
+ if (expanding_p (var)) {
+ WARNING1 ("kpathsea: variable `%s' references itself (eventually)", var);
+ } else {
+#if 1
+ /* The mktex.c replacement for shell scripts needs a more sophisticated
+ lookup for variables */
+ value = getval(var);
+#else
+ /* Check for an environment variable. */
+ value = getenv (var);
+#endif
+ /* If no envvar, check the config files. */
+ if (!value)
+ value = kpse_cnf_get (var);
+
+ if (value) {
+ expanding (var, true);
+ value = mktex_var_expand (value);
+ expanding (var, false);
+ fn_grow (expansion, value, strlen (value));
+ free (value);
+ }
+
+ free (var);
+ }
+}
+
+/* Can't think of when it would be useful to change these (and the
+ diagnostic messages assume them), but ... */
+#ifndef IS_VAR_START /* starts all variable references */
+#define IS_VAR_START(c) ((c) == '$')
+#endif
+#ifndef IS_VAR_CHAR /* variable name constituent */
+#define IS_VAR_CHAR(c) (ISALNUM (c) || (c) == '_')
+#endif
+#ifndef IS_VAR_BEGIN_DELIMITER /* start delimited variable name (after $) */
+#define IS_VAR_BEGIN_DELIMITER(c) ((c) == '{')
+#endif
+#ifndef IS_VAR_END_DELIMITER
+#define IS_VAR_END_DELIMITER(c) ((c) == '}')
+#endif
+
+
+/* Maybe we should support some or all of the various shell ${...}
+ constructs, especially ${var-value}. */
+
+string
+mktex_var_expand P1C(const_string, src)
+{
+ const_string s;
+ string ret;
+ fn_type expansion;
+ expansion = fn_init ();
+
+ /* Copy everything but variable constructs. */
+ for (s = src; *s; s++) {
+ if (IS_VAR_START (*s)) {
+ s++;
+
+ /* Three cases: `$VAR', `${VAR}', `$<anything-else>'. */
+ if (IS_VAR_CHAR (*s)) {
+ /* $V: collect name constituents, then expand. */
+ const_string var_end = s;
+
+ do {
+ var_end++;
+ } while (IS_VAR_CHAR (*var_end));
+
+ var_end--; /* had to go one past */
+ expand (&expansion, s, var_end);
+ s = var_end;
+
+ } else if (IS_VAR_BEGIN_DELIMITER (*s)) {
+ /* ${: scan ahead for matching delimiter, then expand. */
+ const_string var_end = ++s;
+
+ while (*var_end && !IS_VAR_END_DELIMITER (*var_end))
+ var_end++;
+
+ if (! *var_end) {
+ WARNING1 ("%s: No matching } for ${", src);
+ s = var_end - 1; /* will incr to null at top of loop */
+ } else {
+ expand (&expansion, s, var_end - 1);
+ s = var_end; /* will incr past } at top of loop*/
+ }
+
+ } else {
+ /* $<something-else>: error. */
+ WARNING2 ("%s: Unrecognized variable construct `$%c'", src, *s);
+ /* Just ignore those chars and keep going. */
+ }
+ } else
+ fn_1grow (&expansion, *s);
+ }
+ fn_1grow (&expansion, 0);
+
+ ret = FN_STRING (expansion);
+ return ret;
+}
+
+#ifdef TEST
+
+main()
+{
+ char buf[256];
+ while (gets(buf)) parse_variable(buf);
+}
+#endif
diff --git a/Build/source/texk/contrib/variables.h b/Build/source/texk/contrib/variables.h
new file mode 100644
index 00000000000..2488866c6f4
--- /dev/null
+++ b/Build/source/texk/contrib/variables.h
@@ -0,0 +1,23 @@
+#ifndef _MKTEX_VARIABLES_H_
+
+#define _MKTEX_VARIABLES_H_
+
+#include <kpathsea/cnf.h>
+#include <kpathsea/db.h>
+#include <kpathsea/fn.h>
+#include <kpathsea/hash.h>
+
+extern MKTEXDLL void init_vars(void);
+extern MKTEXDLL char *getval(char *name);
+extern MKTEXDLL char *setval(char *name,char *value);
+extern MKTEXDLL char *setval_default(char *name,char *value);
+extern MKTEXDLL char **grep(char *regexp,char *line,int num_vars) ;
+
+extern MKTEXDLL boolean parse_variable(char *line);
+
+extern char *strcasestr(char *s1,char *s2);
+
+extern char *subst(char *line, char *from, char *to);
+extern MKTEXDLL string expand_var(const_string);
+extern MKTEXDLL string mktex_var_expand (const_string src);
+#endif /* _MKTEX_VARIABLES_H_ */
diff --git a/Build/source/texk/contrib/win32.mak b/Build/source/texk/contrib/win32.mak
new file mode 100644
index 00000000000..65f9f633e8b
--- /dev/null
+++ b/Build/source/texk/contrib/win32.mak
@@ -0,0 +1,166 @@
+################################################################################
+#
+# Makefile : TeXk / contrib
+# Author : Fabrice Popineau <Fabrice.Popineau@supelec.fr>
+# Platform : Win32, Microsoft VC++ 6.0, depends upon fpTeX 0.5 sources
+# Time-stamp: <03/09/18 11:26:01 popineau>
+#
+################################################################################
+root_srcdir=..\..
+!ifdef DEVELOPMENT
+INCLUDE=$(INCLUDE);$(root_srcdir)\texk.development
+!else
+INCLUDE=$(INCLUDE);$(root_srcdir)\texk
+!endif
+
+USE_KPATHSEA=1
+USE_MKTEX=1
+MAKE_MKTEX = 1
+USE_REGEX=1
+USE_GNUW32=1
+
+# FIXME: delay load kpathsea for irun !!!
+
+!include <msvc/common.mak>
+
+DEFS = $(DEFS) -DHAVE_CONFIG_H -DKPATHSEA_DLL=\"$(kpathseaname).dll\"
+
+mktex_objs = $(objdir)\fileutils.obj \
+ $(objdir)\mktex.obj \
+ $(objdir)\variables.obj \
+ $(objdir)\stackenv.obj
+
+mktex_progs = $(objdir)\mktexlsr.exe \
+ $(objdir)\mktexnam.exe \
+ $(objdir)\mktexupd.exe \
+ $(objdir)\mktexpk.exe \
+ $(objdir)\mktexdir.exe \
+ $(objdir)\mktexmf.exe \
+ $(objdir)\mktextfm.exe \
+# $(objdir)\mkofm.exe \
+# $(objdir)\mktextex.exe
+
+programs = \
+ $(mktexdll) \
+ $(objdir)\dvihp.exe \
+ $(objdir)\makempx.exe \
+ $(objdir)\mktex.exe \
+ $(objdir)\fmtutil.exe \
+ $(objdir)\mkocp.exe \
+ $(objdir)\mkofm.exe \
+ $(objdir)\irun.exe \
+ $(objdir)\pdfdde.exe
+
+pdfddechilds = $(objdir)\pdfopen.exe $(objdir)\pdfclose.exe
+
+libfiles = $(mktexlib)
+
+default: all
+
+all: $(objdir) $(mktex) $(programs)
+
+lib: $(objdir) $(mktexlib)
+
+!ifdef MKTEX_DLL
+DEFS = -DMAKE_MKTEX_DLL $(DEFS)
+
+$(mktexlib): $(mktex_objs)
+ $(archive) /DEF $(mktex_objs)
+
+$(mktexdll): $(mktex_objs) $(objdir)\libmktex.res $(regexlib) $(kpathsealib)
+ $(link_dll) $(**) $(mktexlib:.lib=.exp) $(conlibs)
+!else
+$(mktexlib): $(mktex_objs) $(regexlib)
+ $(archive) $(**)
+!endif
+
+mktex_progs: $(objdir)\mktex.exe
+ for %%i in ($(mktex_progs)) \
+ do $(copy) $(objdir)\mktex.exe $(objdir)\%%~nxi
+
+$(objdir)\makempx.exe: $(objdir)\makempx.obj $(mktexlib) $(objdir)\makempx.res $(kpathsealib)
+ $(link) $(**) $(conlibs)
+
+$(objdir)\fmtutil.exe: $(objdir)\fmtutil.obj $(mktexlib) $(kpathsealib)
+ $(link) $(**) $(conlibs)
+
+$(objdir)\dvihp.exe: $(objdir)\dvihp.obj $(mktexlib) $(objdir)\dvihp.res $(kpathsealib)
+ $(link) $(**) $(conlibs)
+
+$(objdir)\mktex.exe: $(objdir)\main.obj $(mktexlib) $(kpathsealib)
+ $(link) $(**) $(conlibs)
+
+$(objdir)\mkocp.exe: $(objdir)\mkocp.obj $(mktexlib) $(kpathsealib)
+ $(link) $(**) $(conlibs)
+
+$(objdir)\mkofm.exe: $(objdir)\mkofm.obj $(gnuw32lib)
+ $(link) $(**) $(conlibs)
+
+$(objdir)\makempx.obj: makempx.c
+ $(compile) -UMAKE_MKTEX_DLL makempx.c
+
+$(objdir)\fmtutil.obj: fmtutil.c
+ $(compile) -UMAKE_MKTEX_DLL fmtutil.c
+
+$(objdir)\main.obj: main.c
+ $(compile) -UMAKE_MKTEX_DLL main.c
+
+$(objdir)\dvihp.obj: dvihp.c
+ $(compile) -UMAKE_MKTEX_DLL dvihp.c
+
+$(objdir)\mkocp.obj: mkocp.c
+ $(compile) -UMAKE_MKTEX_DLL mkocp.c
+
+$(objdir)\mkofm.obj: mkofm.c
+ $(compile) -UKPSE_DLL -UMAKE_MKTEX_DLL mkofm.c
+
+$(objdir)\irun-tmp.obj: $(srcdir)\irun.c
+ echo define RDATA 0x3D000 | sed "s/define/#define/" > $(srcdir)\irun.h
+ $(compile) $(srcdir)\irun.c
+
+$(objdir)\irun-tmp.exe: $(objdir)\irun-tmp.obj $(kpathsealib)
+ $(link) $(**) $(conlibs)
+
+$(objdir)\irun.obj: $(srcdir)\irun.c $(objdir)\irun-tmp.exe
+ dumpbin /headers $(objdir)\irun-tmp.exe \
+ | sed -n -e "/^[ \t]*FOOBAR/,/^[ \t]*FOOBAR/p" \
+ | sed -n -e "/file pointer/p" \
+ | sed -e "/raw data/s/^[ \t]*\([0-9A-Z]*\).*$$/#define RDATA 0x\1/" \
+ | sed -e "/file pointer/d" \
+ > $(srcdir)\irun.h
+ $(compile) $(srcdir)\irun.c
+# -$(RM) $(objdir)\irun-tmp.*
+
+$(objdir)\irun.exe: $(objdir)\irun.obj $(objdir)\irun.res $(kpathsealib)
+ $(link) $(**) $(conlibs) $(kpathsealib)
+
+$(objdir)\pdfdde.exe: $(objdir)\pdfdde.obj $(gnuw32lib)
+ $(link) $(**) $(conlibs) shell32.lib
+
+$(objdir)\pdfdde.obj: pdfdde.c
+ $(compile) -UKPSE_DLL pdfdde.c
+
+!include <msvc/config.mak>
+!include <msvc/install.mak>
+
+install:: install-exec
+
+install-exec::
+ -@echo $(verbose) & ( \
+ echo "Installing mktex program files in $(MAKEDIR)" & \
+ ( for %%i in ($(mktex_progs)) do \
+ $(copy) $(objdir)\mktex.exe $(bindir)\%%~nxi $(redir_stdout) ) & \
+ $(copy) $(objdir)\fmtutil.exe $(bindir)\mktexfmt.exe $(redir_stdout) \
+ )
+ -@echo $(verbose) & ( \
+ for %%i in ($(pdfddechilds)) \
+ do $(copy) $(objdir)\pdfdde.exe $(bindir)\%%~nxi $(redir_stdout) )
+
+!include <msvc/clean.mak>
+
+!include <msvc/rdepend.mak>
+!include "./depend.mak"
+
+#Local Variables:
+#mode: Makefile
+#End: