summaryrefslogtreecommitdiff
path: root/Build/extra/djgpp
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2018-01-23 23:56:59 +0000
committerKarl Berry <karl@freefriends.org>2018-01-23 23:56:59 +0000
commit6372ddbab3389d1e44cb013fd178b6e4b2a10763 (patch)
treea6e7be6f92da154a893e5581294fea27a2029982 /Build/extra/djgpp
parent8294cc19d41a8405e05ec257dd5111b8c18ed4e8 (diff)
move source/extra up a level to Build/extra, to clarify that they are not part of TL
git-svn-id: svn://tug.org/texlive/trunk@46418 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/extra/djgpp')
-rw-r--r--Build/extra/djgpp/ChangeLog69
-rw-r--r--Build/extra/djgpp/README.djgpp207
-rw-r--r--Build/extra/djgpp/cfgdtl.pat19
-rw-r--r--Build/extra/djgpp/cfgdvidv.pat19
-rw-r--r--Build/extra/djgpp/cfgdvilj.pat29
-rw-r--r--Build/extra/djgpp/cfgdvips.pat31
-rw-r--r--Build/extra/djgpp/cfgdvpdf.pat19
-rw-r--r--Build/extra/djgpp/cfggsfpk.pat19
-rw-r--r--Build/extra/djgpp/cfgkpath.pat30
-rw-r--r--Build/extra/djgpp/cfglachk.pat19
-rw-r--r--Build/extra/djgpp/cfgmain.pat29
-rw-r--r--Build/extra/djgpp/cfgmkind.pat19
-rw-r--r--Build/extra/djgpp/cfgmusix.pat19
-rw-r--r--Build/extra/djgpp/cfgpspkm.pat19
-rw-r--r--Build/extra/djgpp/cfgseetx.pat19
-rw-r--r--Build/extra/djgpp/cfgtexht.pat19
-rw-r--r--Build/extra/djgpp/cfgweb2c.pat38
-rwxr-xr-xBuild/extra/djgpp/config.bat272
-rw-r--r--Build/extra/djgpp/pathconf.c47
-rw-r--r--Build/extra/djgpp/popen.c218
-rw-r--r--Build/extra/djgpp/putenv.c143
-rw-r--r--Build/extra/djgpp/stat.c935
-rw-r--r--Build/extra/djgpp/xstat.h71
23 files changed, 2309 insertions, 0 deletions
diff --git a/Build/extra/djgpp/ChangeLog b/Build/extra/djgpp/ChangeLog
new file mode 100644
index 00000000000..53a911e5f32
--- /dev/null
+++ b/Build/extra/djgpp/ChangeLog
@@ -0,0 +1,69 @@
+1999-01-27 Olaf Weber <olaf@infovore.xs4all.nl>
+
+ * config.bat: Update from Eli Zaretskii.
+
+1999-01-10 Olaf Weber <olaf@infovore.xs4all.nl>
+
+ * pathconf.c, xstat.h, putenv.c, stat.c, popen.c: New files from
+ Eli, updates of other files.
+
+1998-10-22 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * config.bat: Support build of additional packages: dtl, dvidvi,
+ gsftopk, lacheck, makeindexk, musixflx, odvipsk, ps2pkm, seetexk,
+ tex4htk.
+ * cfgdtl.pat, cfgdvidv.pat, cfglachk.pat, cfgseetx.pat,
+ cfgmkind.pat, cfggsfpk.pat, cfgpspkm.pat, cfgtexht.pat,
+ cfgmusix.pat: New files.
+
+1998-03-18 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * README.djgpp: Minor updates and cleanup.
+
+ * cfgmain.pat, cfgkpath.pat, cfgweb2c.pat, cfgdvilj.pat,
+ cfgdvips.pat: New versions.
+
+1998-03-04 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * cfgdvips.pat: New version, fixes problems with "make check" in
+ the dvipsk directory.
+
+1998-02-16 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * config.bat: Configure with EPSFWIN pseudo-window support.
+
+1998-02-09 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * config.bat: Fail if patches to some of the configure scripts
+ fail to apply. Use response file when invoking the shell, to
+ avoid exceeding the 126-character limit of DOS command lines. Use
+ ${DJDIR}/share as the location of the texmf tree.
+
+ * cfgmain.pat, cfgkpath.pat, cfgweb2c.pat, cfgdvilj.pat,
+ cfgdvips.pat: New versions.
+
+Wed Jan 28 20:16:14 1998 Olaf Weber <infovore@xs4all.nl>
+
+ * A new set of files from Eli, including cfgdvips.pat and
+ cfgdvilj.pat which are new.
+
+Tue Jan 13 12:23:50 1998 Olaf Weber <infovore@xs4all.nl>
+
+ * cfgmain.pat, cfgweb2c.pat, config.bat: New version from Eli.
+
+Tue Dec 30 17:54:29 1997 Olaf Weber <infovore@xs4all.nl>
+
+ * cfgweb2c.pat: New version from Eli.
+
+Thu Dec 18 20:43:39 1997 Olaf Weber <infovore@xs4all.nl>
+
+ * cfgkpath.pat, cfgweb2c.pat, cfgmain.pat, config.bat: New
+ versions from Eli.
+
+Tue Dec 16 18:56:03 1997 Olaf Weber <infovore@xs4all.nl>
+
+ * config.bat: New file from Eli Zaretskii.
+
+ * cfgweb2c.pat, cfgkpath.pat, cfgmain.pat: New file from Eli
+ Zaretskii, edited to remove obsolete patches.
+
diff --git a/Build/extra/djgpp/README.djgpp b/Build/extra/djgpp/README.djgpp
new file mode 100644
index 00000000000..8579633b28e
--- /dev/null
+++ b/Build/extra/djgpp/README.djgpp
@@ -0,0 +1,207 @@
+This directory includes files required to build TeX and related
+programs with the DJGPP port of GNU tools for MS-DOS and MS-Windows.
+DJGPP produces 32-bit protected-mode programs which run on all
+Microsoft platforms. On plain MS-DOS they need a DPMI server (a free
+server is available as v2misc/csdpmiNb.zip that can be downloaded from
+DJGPP archives on SimTel.NET mirrors). MS-Windows have DPMI services
+built into them. When run on Windows 9X, the DJGPP-compiled programs
+support long file names.
+
+
+ Building the package from sources
+ ---------------------------------
+
+ - The following tools are REQUIRED to build and install Web2c
+ programs (the parentheses list filenames of binary distributions
+ you can download from DJGPP archives if you don't have a
+ particular package):
+
+ Bash (bsh1147b.zip)
+ Fileutils (fil316b.zip)
+ Textutils (txt122b.zip)
+ Grep (grep22b.zip)
+ Patch (pat25b.zip)
+ Sh-utils (shl112b.zip)
+ Sed (sed302b.zip)
+ Diffutils (dif2721b.zip)
+ Findutils (find41b.zip)
+ Ed (ed-02b.zip)
+ Gawk (gwk303b.zip)
+ Bison (bsn125b.zip)
+ Flex (flx254b.zip)
+
+ All of these are available from the v2gnu directory on the usual
+ DJGPP sites, e.g. ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/.
+
+ The above tools are IN ADDITION to the basic DJGPP development
+ environment that is required to compile and link C programs.
+ Consult the file v2/readme.1st and the DJGPP FAQ list in
+ v2/faqNNNb.zip, for details about the basic package.
+
+ - Unzip the downloaded Web2c and Texmflib distributions from the
+ root of your DJGPP installation tree. If you are doing this on
+ Windows 9x, use an unzip program that supports long filenames.
+
+ This will create the top directory and unpack the sources
+ into the relevant subdirectories. It will also create the
+ `share/texmf' directory and unpack the contents of Texmflib
+ library there.
+
+ - At this point, I suggest you to read the file
+ `kpathsea/INSTALL.txt'. It includes a detailed yet very
+ readable description of the various options available to you at
+ build and installation time.
+
+ - Make sure your TMPDIR environment variable points to a drive
+ with enough free space. Many DJGPP installations set this
+ variable to a RAM disk for performance reasons. Since RAM disks
+ tend to be small (a few Megabytes), a complex shell script may
+ fill it with temporary files, typically from pipes and `command`
+ expansions, after which point programs run by that shell will
+ start to fail. The TeX build process runs some very long and
+ complicated shell scripts which require around 4MB of free space
+ on TMPDIR filesystem (it failed for me when I had only 2.5MB).
+ If you cannot enlarge your RAM disk, point TMPDIR to a real disk
+ (the effect on the overall build time is insignificant, since
+ GCC will have hard time compiling some of the larger programs
+ with -O2 switch). TMPDIR is usually set on the DJGPP.ENV file,
+ but you can override it by setting TMPDIR from the DOS prompt.
+
+ - The default 256KB stack size limit of DJGPP programs is too
+ small for compiling some of the TeX programs. Make sure your
+ cc1.exe program has at least 768KB of stack. Here's how:
+
+ stubedit cc1.exe minstack=768k
+
+ (`stubedit' is part of the basic DJGPP development
+ environment).
+
+ - To configure the package for DJGPP, run the `config.bat' batch
+ file in the djgpp subdirectory. This sets some environment
+ variables and then invokes Bash to run the configuration script
+ with necessary arguments. (You can edit the batch file if you
+ want to run the script with different arguments.) The command
+ is this:
+
+ djgpp\config
+
+ - It is possible to configure and build Web2c from a directory
+ other than where the sources reside (useful when you cannot
+ write to that directory, like if it's on a CD-ROM). In that
+ case, you need to invoke `config.bat' with a single argument
+ which is the full pathname of the source directory. For
+ example:
+
+ f:\gnu\web2c-7.2\djgpp\config f:/gnu/web2c-7.2
+
+ Note that you MUST use Unix-style forward slashes in the
+ argument you pass to `config.bat', or else it will fail.
+
+ - The configure script will run for a while and recursively
+ configure the programs in subdirectories.
+
+ - After running `config', just say "make".
+
+ Building the full Web2c package takes a while (about 2 hours
+ on a 486/DX2-66, 35 minutes on a Pentium-166), so you might go
+ for a cup of coffee while it compiles.
+
+ - To build the emulation programs in the `contrib' directory,
+ chdir into that directory and say "make". Compiling `regex.c'
+ triggers several warning messages about variables that ``might
+ be used uninitialized''; you can safely disregard these
+ warnings.
+
+ - If you are building Texk more than 18 months since it was
+ released, you might see a warning message while LaTeX is built
+ which complains about old sources. In general, you can press
+ [Enter] in response to that message and let the build continue,
+ since the message is just a precaution. However, if you do care
+ to have the latest stuff, you will need to download the
+ latex/base directory from one of the CTAN mirrors and replace
+ with it the files in latex/base which come with tmflib74.zip.
+
+ - If you have changed some of the programs in the package, it is a
+ good idea to run tests on them. The Makefile in the web2c
+ directory has a large number of xxx-check targets, where xxx is
+ the name of a program; you can run these one by one by going
+ into web2c and saying like so:
+
+ make gftopk-check
+
+ You can also run all of them together by saying "make check" in
+ the top-level directory.
+
+ Some of the tests appear to fail (`diff' prints some actual
+ differences between the test results and the reference files
+ that come with the package. In most cases, this is normal
+ behavior (the programs were changed since the canonical results
+ were computed); the file `web2c/tests/check.log' includes the
+ output you should see for each test. If your results coincide
+ with `check.log' (except for the version of the package that the
+ programs print), you are doing fine.
+
+ - Before installing, if you already have a previous version of
+ Texk installed, review your `texmf.cnf' configuration file (in
+ %TEXMF%/web2c directory). If you have changed it from the
+ original, you might want the installation process to leave it
+ alone and not overwrite it with the fresh copy from the
+ distribution. In that case, edit `texmf.cnf' and remove the
+ word "original" from its first line. This tells the
+ installation process to refrain from replacing that file.
+
+ - To install the programs, say "make install" in the top
+ directory. This will create missing directories and copy the
+ programs and auxiliary files to their places. The programs
+ inside `contrib' need to be installed manually (typically, into
+ the same directory where the executable programs go).
+
+
+ Troubleshooting
+ ---------------
+
+ I do NOT intend here to replace the various chapters in the docs
+ which explain how to solve problems and report bugs. Please read
+ the docs whenever you see any seemingly abnormal behavior. What's
+ below is intended to mention a few DOS- and DJGPP-specific
+ problems that you might see, and how to get around them.
+
+ First, a word of warning. Web2c is a tremendously large and
+ complex package, with dozens of different programs, some of them
+ with many different options. While porting it, I've made a good-
+ faith effort to test everything I could, including using it to
+ generate printed versions of various TeX and Texinfo documents.
+ However, some bugs might still be there. Please treat this port
+ accordingly and report possible bugs to the DJGPP news group
+ (comp.os.msdos.djgpp) first.
+
+ One possible problem you could see is due to insufficient number
+ of available file handles. `Dvilj' is particularly prone to this
+ problem. If you ever see an error message to the effect that a
+ program has no more handles, edit your CONFIG.SYS and enlarge the
+ FILES= setting there. (Don't forget to reboot so the new setting
+ is in effect.)
+
+ Another related problem manifests itself by an error message like
+ so:
+
+ c:\djgpp\bin/mf.exe: cannot open
+
+ This usually happens when a DVI driver finds a missing font and
+ invokes the MetaFont program to generate them on the fly. Due to
+ peculiarities of file handles inheritance from parent to child
+ processes, the child process can sometimes fail to start because
+ the stub cannot open the .exe file. I think I've fixed these
+ problems, so you shouldn't see such messages, but if you do,
+ please report the details.
+
+ If the font-creation fails, a file named `missfont.log' is created
+ in the current directory, with the commands you should issue to
+ make these fonts. Many times, invoking that file as a batch file
+ will create the missing fonts, so you could then invoke the DVI
+ driver again and it will work.
+
+
+ Happy TeXing!
+
+ Eli Zaretskii <eliz@is.elta.co.il>
diff --git a/Build/extra/djgpp/cfgdtl.pat b/Build/extra/djgpp/cfgdtl.pat
new file mode 100644
index 00000000000..23f01392623
--- /dev/null
+++ b/Build/extra/djgpp/cfgdtl.pat
@@ -0,0 +1,19 @@
+*** dtl/configure.orig Tue Mar 17 12:51:52 1998
+--- dtl/configure Thu Mar 19 18:28:22 1998
+***************
+*** 2273,2279 ****
+ s%@srcdir@%$srcdir%g
+ s%@top_srcdir@%$top_srcdir%g
+ s%@INSTALL@%$INSTALL%g
+! " | (eval "$ac_sed_cmds") > $ac_file
+ fi; done
+ rm -f conftest.s*
+
+--- 2273,2279 ----
+ s%@srcdir@%$srcdir%g
+ s%@top_srcdir@%$top_srcdir%g
+ s%@INSTALL@%$INSTALL%g
+! " | (eval "$ac_sed_cmds") | sed -e '/^default_texsizes/s,:,;,' > $ac_file
+ fi; done
+ rm -f conftest.s*
+
diff --git a/Build/extra/djgpp/cfgdvidv.pat b/Build/extra/djgpp/cfgdvidv.pat
new file mode 100644
index 00000000000..e03cbf55b43
--- /dev/null
+++ b/Build/extra/djgpp/cfgdvidv.pat
@@ -0,0 +1,19 @@
+*** dvidvi/configure.orig Tue Mar 17 12:51:54 1998
+--- dvidvi/configure Thu Mar 19 17:55:50 1998
+***************
+*** 2273,2279 ****
+ s%@srcdir@%$srcdir%g
+ s%@top_srcdir@%$top_srcdir%g
+ s%@INSTALL@%$INSTALL%g
+! " | (eval "$ac_sed_cmds") > $ac_file
+ fi; done
+ rm -f conftest.s*
+
+--- 2273,2279 ----
+ s%@srcdir@%$srcdir%g
+ s%@top_srcdir@%$top_srcdir%g
+ s%@INSTALL@%$INSTALL%g
+! " | (eval "$ac_sed_cmds") | sed -e '/^default_texsizes/s,:,;,' > $ac_file
+ fi; done
+ rm -f conftest.s*
+
diff --git a/Build/extra/djgpp/cfgdvilj.pat b/Build/extra/djgpp/cfgdvilj.pat
new file mode 100644
index 00000000000..9300c9a5a8b
--- /dev/null
+++ b/Build/extra/djgpp/cfgdvilj.pat
@@ -0,0 +1,29 @@
+*** dviljk/configure.orig Thu Mar 12 13:20:20 1998
+--- dviljk/configure Tue Mar 17 11:38:20 1998
+***************
+*** 2140,2145 ****
+--- 2140,2146 ----
+ s%@LTLIBOBJS@%$LTLIBOBJS%g
+ s%@MAINT@%$MAINT%g
+ s%@texmfmain@%$texmfmain%g
++ s, ln -s , cp -pr ,
+
+ CEOF
+ EOF
+***************
+*** 2273,2279 ****
+ s%@srcdir@%$srcdir%g
+ s%@top_srcdir@%$top_srcdir%g
+ s%@INSTALL@%$INSTALL%g
+! " | (eval "$ac_sed_cmds") > $ac_file
+ fi; done
+ rm -f conftest.s*
+
+--- 2274,2280 ----
+ s%@srcdir@%$srcdir%g
+ s%@top_srcdir@%$top_srcdir%g
+ s%@INSTALL@%$INSTALL%g
+! " | (eval "$ac_sed_cmds") | sed -e '/^default_texsizes/s,:,;,' > $ac_file
+ fi; done
+ rm -f conftest.s*
+
diff --git a/Build/extra/djgpp/cfgdvips.pat b/Build/extra/djgpp/cfgdvips.pat
new file mode 100644
index 00000000000..5e252a48fe3
--- /dev/null
+++ b/Build/extra/djgpp/cfgdvips.pat
@@ -0,0 +1,31 @@
+*** dvipsk/configure.orig Thu Mar 12 13:20:44 1998
+--- dvipsk/configure Tue Mar 17 11:38:22 1998
+***************
+*** 2077,2082 ****
+--- 2077,2085 ----
+ s%@LTLIBOBJS@%$LTLIBOBJS%g
+ s%@MAINT@%$MAINT%g
+ s%@texmfmain@%$texmfmain%g
++ s, ln -s , cp -rp ,
++ /^ -PATH=/s,^ -,&PATH_SEPARATOR=: PATH_EXPAND=y ,
++ /^ .*testdata:/s,testdata:,testdata\\\;,g
+
+ CEOF
+ EOF
+***************
+*** 2210,2216 ****
+ s%@srcdir@%$srcdir%g
+ s%@top_srcdir@%$top_srcdir%g
+ s%@INSTALL@%$INSTALL%g
+! " | (eval "$ac_sed_cmds") > $ac_file
+ fi; done
+ rm -f conftest.s*
+
+--- 2213,2219 ----
+ s%@srcdir@%$srcdir%g
+ s%@top_srcdir@%$top_srcdir%g
+ s%@INSTALL@%$INSTALL%g
+! " | (eval "$ac_sed_cmds") | sed -e '/^default_texsizes/s,:,;,' > $ac_file
+ fi; done
+ rm -f conftest.s*
+
diff --git a/Build/extra/djgpp/cfgdvpdf.pat b/Build/extra/djgpp/cfgdvpdf.pat
new file mode 100644
index 00000000000..58c716166b7
--- /dev/null
+++ b/Build/extra/djgpp/cfgdvpdf.pat
@@ -0,0 +1,19 @@
+*** dvipdfm/configure.orig Sun Jan 10 17:06:32 1999
+--- dvipdfm/configure Mon Jan 11 10:19:58 1999
+***************
+*** 3320,3326 ****
+ s%@srcdir@%$srcdir%g
+ s%@top_srcdir@%$top_srcdir%g
+ s%@INSTALL@%$INSTALL%g
+! " | (eval "$ac_sed_cmds") > $ac_file
+ fi; done
+ rm -f conftest.s*
+
+--- 3320,3326 ----
+ s%@srcdir@%$srcdir%g
+ s%@top_srcdir@%$top_srcdir%g
+ s%@INSTALL@%$INSTALL%g
+! " | (eval "$ac_sed_cmds") | sed -e '/^default_texsizes/s,:,;,' > $ac_file
+ fi; done
+ rm -f conftest.s*
+
diff --git a/Build/extra/djgpp/cfggsfpk.pat b/Build/extra/djgpp/cfggsfpk.pat
new file mode 100644
index 00000000000..2d24a48dce7
--- /dev/null
+++ b/Build/extra/djgpp/cfggsfpk.pat
@@ -0,0 +1,19 @@
+*** gsftopk/configure.orig Tue Mar 17 12:51:56 1998
+--- gsftopk/configure Tue Sep 15 15:47:08 1998
+***************
+*** 2266,2272 ****
+ s%@srcdir@%$srcdir%g
+ s%@top_srcdir@%$top_srcdir%g
+ s%@INSTALL@%$INSTALL%g
+! " | (eval "$ac_sed_cmds") > $ac_file
+ fi; done
+ rm -f conftest.s*
+
+--- 2266,2272 ----
+ s%@srcdir@%$srcdir%g
+ s%@top_srcdir@%$top_srcdir%g
+ s%@INSTALL@%$INSTALL%g
+! " | (eval "$ac_sed_cmds") | sed -e '/^default_texsizes/s,:,;,' > $ac_file
+ fi; done
+ rm -f conftest.s*
+
diff --git a/Build/extra/djgpp/cfgkpath.pat b/Build/extra/djgpp/cfgkpath.pat
new file mode 100644
index 00000000000..c86f1f95474
--- /dev/null
+++ b/Build/extra/djgpp/cfgkpath.pat
@@ -0,0 +1,30 @@
+*** kpathsea/configure.orig Mon Mar 9 08:23:38 1998
+--- kpathsea/configure Tue Mar 17 11:38:20 1998
+***************
+*** 2045,2050 ****
+--- 2045,2052 ----
+ s%@LTLIBOBJS@%$LTLIBOBJS%g
+ s%@MAINT@%$MAINT%g
+ s%@texmfmain@%$texmfmain%g
++ /^ sed -f texmf.sed/c\\
++ sed -e '/^[^%]/s/:/;/g' \\\$(srcdir)/texmf.in | sed -f texmf.sed >\\\$@
+
+ CEOF
+ EOF
+***************
+*** 2178,2184 ****
+ s%@srcdir@%$srcdir%g
+ s%@top_srcdir@%$top_srcdir%g
+ s%@INSTALL@%$INSTALL%g
+! " | (eval "$ac_sed_cmds") > $ac_file
+ fi; done
+ rm -f conftest.s*
+
+--- 2180,2186 ----
+ s%@srcdir@%$srcdir%g
+ s%@top_srcdir@%$top_srcdir%g
+ s%@INSTALL@%$INSTALL%g
+! " | (eval "$ac_sed_cmds") | sed -e '/^default_texsizes/s,:,;,' > $ac_file
+ fi; done
+ rm -f conftest.s*
+
diff --git a/Build/extra/djgpp/cfglachk.pat b/Build/extra/djgpp/cfglachk.pat
new file mode 100644
index 00000000000..8820034379c
--- /dev/null
+++ b/Build/extra/djgpp/cfglachk.pat
@@ -0,0 +1,19 @@
+*** lacheck/configure.orig Tue Mar 17 12:51:58 1998
+--- lacheck/configure Mon Mar 23 18:07:46 1998
+***************
+*** 2564,2570 ****
+ s%@srcdir@%$srcdir%g
+ s%@top_srcdir@%$top_srcdir%g
+ s%@INSTALL@%$INSTALL%g
+! " | (eval "$ac_sed_cmds") > $ac_file
+ fi; done
+ rm -f conftest.s*
+
+--- 2564,2570 ----
+ s%@srcdir@%$srcdir%g
+ s%@top_srcdir@%$top_srcdir%g
+ s%@INSTALL@%$INSTALL%g
+! " | (eval "$ac_sed_cmds") | sed -e '/^default_texsizes/s,:,;,' > $ac_file
+ fi; done
+ rm -f conftest.s*
+
diff --git a/Build/extra/djgpp/cfgmain.pat b/Build/extra/djgpp/cfgmain.pat
new file mode 100644
index 00000000000..2c05e06246e
--- /dev/null
+++ b/Build/extra/djgpp/cfgmain.pat
@@ -0,0 +1,29 @@
+*** configure.orig Wed Mar 11 00:38:40 1998
+--- configure Tue Mar 17 11:38:18 1998
+***************
+*** 973,978 ****
+--- 973,979 ----
+
+ fi
+ if test "${ac_cv_path_install+set}" = set; then
++ ac_cv_path_install=`echo.exe "$ac_cv_path_install"`
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+***************
+*** 1986,1992 ****
+ s%@srcdir@%$srcdir%g
+ s%@top_srcdir@%$top_srcdir%g
+ s%@INSTALL@%$INSTALL%g
+! " | (eval "$ac_sed_cmds") > $ac_file
+ fi; done
+ rm -f conftest.s*
+
+--- 1987,1993 ----
+ s%@srcdir@%$srcdir%g
+ s%@top_srcdir@%$top_srcdir%g
+ s%@INSTALL@%$INSTALL%g
+! " | (eval "$ac_sed_cmds") | sed -e '/^default_texsizes/s,:,;,' > $ac_file
+ fi; done
+ rm -f conftest.s*
+
diff --git a/Build/extra/djgpp/cfgmkind.pat b/Build/extra/djgpp/cfgmkind.pat
new file mode 100644
index 00000000000..12d931d012f
--- /dev/null
+++ b/Build/extra/djgpp/cfgmkind.pat
@@ -0,0 +1,19 @@
+*** makeindexk/configure.orig Tue Mar 17 12:52:06 1998
+--- makeindexk/configure Tue Sep 15 10:43:52 1998
+***************
+*** 2285,2291 ****
+ s%@srcdir@%$srcdir%g
+ s%@top_srcdir@%$top_srcdir%g
+ s%@INSTALL@%$INSTALL%g
+! " | (eval "$ac_sed_cmds") > $ac_file
+ fi; done
+ rm -f conftest.s*
+
+--- 2285,2291 ----
+ s%@srcdir@%$srcdir%g
+ s%@top_srcdir@%$top_srcdir%g
+ s%@INSTALL@%$INSTALL%g
+! " | (eval "$ac_sed_cmds") | sed -e '/^default_texsizes/s,:,;,' > $ac_file
+ fi; done
+ rm -f conftest.s*
+
diff --git a/Build/extra/djgpp/cfgmusix.pat b/Build/extra/djgpp/cfgmusix.pat
new file mode 100644
index 00000000000..a038f612f39
--- /dev/null
+++ b/Build/extra/djgpp/cfgmusix.pat
@@ -0,0 +1,19 @@
+*** musixflx/configure.orig Tue Mar 17 12:52:08 1998
+--- musixflx/configure Wed Oct 21 09:42:44 1998
+***************
+*** 2273,2279 ****
+ s%@srcdir@%$srcdir%g
+ s%@top_srcdir@%$top_srcdir%g
+ s%@INSTALL@%$INSTALL%g
+! " | (eval "$ac_sed_cmds") > $ac_file
+ fi; done
+ rm -f conftest.s*
+
+--- 2273,2279 ----
+ s%@srcdir@%$srcdir%g
+ s%@top_srcdir@%$top_srcdir%g
+ s%@INSTALL@%$INSTALL%g
+! " | (eval "$ac_sed_cmds") | sed -e '/^default_texsizes/s,:,;,' > $ac_file
+ fi; done
+ rm -f conftest.s*
+
diff --git a/Build/extra/djgpp/cfgpspkm.pat b/Build/extra/djgpp/cfgpspkm.pat
new file mode 100644
index 00000000000..7614f4bc046
--- /dev/null
+++ b/Build/extra/djgpp/cfgpspkm.pat
@@ -0,0 +1,19 @@
+*** ps2pkm/configure.orig Tue Mar 17 12:52:14 1998
+--- ps2pkm/configure Tue Sep 15 15:59:48 1998
+***************
+*** 2476,2482 ****
+ s%@srcdir@%$srcdir%g
+ s%@top_srcdir@%$top_srcdir%g
+ s%@INSTALL@%$INSTALL%g
+! " | (eval "$ac_sed_cmds") > $ac_file
+ fi; done
+ rm -f conftest.s*
+
+--- 2476,2482 ----
+ s%@srcdir@%$srcdir%g
+ s%@top_srcdir@%$top_srcdir%g
+ s%@INSTALL@%$INSTALL%g
+! " | (eval "$ac_sed_cmds") | sed -e '/^default_texsizes/s,:,;,' > $ac_file
+ fi; done
+ rm -f conftest.s*
+
diff --git a/Build/extra/djgpp/cfgseetx.pat b/Build/extra/djgpp/cfgseetx.pat
new file mode 100644
index 00000000000..adb42fbb7ed
--- /dev/null
+++ b/Build/extra/djgpp/cfgseetx.pat
@@ -0,0 +1,19 @@
+*** seetexk/configure.orig Tue Mar 17 12:52:16 1998
+--- seetexk/configure Thu Mar 26 14:37:20 1998
+***************
+*** 2305,2311 ****
+ s%@srcdir@%$srcdir%g
+ s%@top_srcdir@%$top_srcdir%g
+ s%@INSTALL@%$INSTALL%g
+! " | (eval "$ac_sed_cmds") > $ac_file
+ fi; done
+ rm -f conftest.s*
+
+--- 2305,2311 ----
+ s%@srcdir@%$srcdir%g
+ s%@top_srcdir@%$top_srcdir%g
+ s%@INSTALL@%$INSTALL%g
+! " | (eval "$ac_sed_cmds") | sed -e '/^default_texsizes/s,:,;,' > $ac_file
+ fi; done
+ rm -f conftest.s*
+
diff --git a/Build/extra/djgpp/cfgtexht.pat b/Build/extra/djgpp/cfgtexht.pat
new file mode 100644
index 00000000000..570de8147a9
--- /dev/null
+++ b/Build/extra/djgpp/cfgtexht.pat
@@ -0,0 +1,19 @@
+*** tex4htk/configure.orig Tue Mar 17 12:52:20 1998
+--- tex4htk/configure Wed Sep 16 19:06:00 1998
+***************
+*** 2210,2216 ****
+ s%@srcdir@%$srcdir%g
+ s%@top_srcdir@%$top_srcdir%g
+ s%@INSTALL@%$INSTALL%g
+! " | (eval "$ac_sed_cmds") > $ac_file
+ fi; done
+ rm -f conftest.s*
+
+--- 2210,2216 ----
+ s%@srcdir@%$srcdir%g
+ s%@top_srcdir@%$top_srcdir%g
+ s%@INSTALL@%$INSTALL%g
+! " | (eval "$ac_sed_cmds") | sed -e '/^default_texsizes/s,:,;,' > $ac_file
+ fi; done
+ rm -f conftest.s*
+
diff --git a/Build/extra/djgpp/cfgweb2c.pat b/Build/extra/djgpp/cfgweb2c.pat
new file mode 100644
index 00000000000..e74d341f91e
--- /dev/null
+++ b/Build/extra/djgpp/cfgweb2c.pat
@@ -0,0 +1,38 @@
+*** web2c/configure.orig Mon Mar 9 08:23:40 1998
+--- web2c/configure Tue Mar 17 11:38:24 1998
+***************
+*** 4271,4276 ****
+--- 4271,4286 ----
+ s%@zlib@%$zlib%g
+ s%@pdftexlibsdep@%$pdftexlibsdep%g
+ s%@zlibinc@%$zlibinc%g
++ s,\.gft,.gf,g
++ /^ MAKEMPX_BINDIR/s,^ ,&PATH_SEPARATOR=: PATH_EXPAND=y ,g
++ /^ -PATH=/s,^ -,&PATH_SEPARATOR=: PATH_EXPAND=y ,g
++ /\\\$(LN).*initex/s,\\\$(LN),ln -s,g
++ /\\\$(LN).*iniomega/s,\\\$(LN),ln -s,g
++ /\\\$(LN).*inimf/s,\\\$(LN),ln -s,g
++ /\\\$(LN).*inimpost/s,\\\$(LN),ln -s,g
++ /\\\$\\\$base/s,\\\$(LN),ln -s,g
++ s,pooltype-check,poolt-check,
++ /TFMFONTS=/s,tests:,tests\\\;,
+
+ CEOF
+ EOF
+***************
+*** 4406,4412 ****
+ s%@srcdir@%$srcdir%g
+ s%@top_srcdir@%$top_srcdir%g
+ s%@INSTALL@%$INSTALL%g
+! " | (eval "$ac_sed_cmds") > $ac_file
+ fi; done
+ rm -f conftest.s*
+
+--- 4416,4422 ----
+ s%@srcdir@%$srcdir%g
+ s%@top_srcdir@%$top_srcdir%g
+ s%@INSTALL@%$INSTALL%g
+! " | (eval "$ac_sed_cmds") | sed -e '/^default_texsizes/s,:,;,' > $ac_file
+ fi; done
+ rm -f conftest.s*
+
diff --git a/Build/extra/djgpp/config.bat b/Build/extra/djgpp/config.bat
new file mode 100755
index 00000000000..d016366692c
--- /dev/null
+++ b/Build/extra/djgpp/config.bat
@@ -0,0 +1,272 @@
+@echo off
+Rem
+Rem The SmallEnv gorp is for those who have too small environment
+Rem size which will cause the variables we set to be truncated
+Rem but who cannot be bothered to read the Out Of Environment Space
+Rem error messages spitted by the stock DOS shell
+set XSRC=.
+if not "%XSRC%" == "." goto SmallEnv
+if "%1" == "" goto inplace
+set XSRC=%1
+if not "%XSRC%" == "%1" goto SmallEnv
+:inplace
+if exist .\kpathsea\INSTALL ren .\kpathsea\INSTALL INSTALL.txt
+if exist .\web2c\INSTALL ren .\web2c\INSTALL INSTALL.txt
+if exist .\dvipsk\INSTALL ren .\dvipsk\INSTALL INSTALL.txt
+if exist .\dviljk\INSTALL ren .\dviljk\INSTALL INSTALL.txt
+if exist .\gsftopk\INSTALL ren .\gsftopk\INSTALL INSTALL.txt
+if exist .\makeindexk\INSTALL ren .\makeindexk\INSTALL INSTALL.txt
+if exist .\makeindexk\INSTALL ren .\makeindexk\INSTALL INSTALL.txt
+if exist .\dvipdfm\INSTALL ren .\dvipdfm\INSTALL INSTALL.txt
+test -d %XSRC%
+if not errorlevel 1 goto chkdir
+echo %XSRC% is not a directory
+goto end
+:chkdir
+test -f %XSRC%/configure
+if not errorlevel 1 goto argsok
+echo I cannot find the configure script in directory %XSRC%
+goto end
+:argsok
+rem set SYSROOT=c:
+set PATH_SEPARATOR=:
+if not "%PATH_SEPARATOR%" == ":" goto SmallEnv
+set PATH_EXPAND=y
+if not "%PATH_EXPAND%" == "y" goto SmallEnv
+if not "%HOSTNAME%" == "" goto hostdone
+if "%windir%" == "" goto msdos
+set OS=MS-Windows
+if not "%OS%" == "MS-Windows" goto SmallEnv
+goto haveos
+:msdos
+set OS=MS-DOS
+if not "%OS%" == "MS-DOS" goto SmallEnv
+:haveos
+if not "%USERNAME%" == "" goto haveuname
+if not "%USER%" == "" goto haveuser
+echo No USERNAME and no USER found in the environment, using default values
+set HOSTNAME=Unknown PC
+if not "%HOSTNAME%" == "Unknown PC" goto SmallEnv
+:haveuser
+set HOSTNAME=%USER%'s PC
+if not "%HOSTNAME%" == "%USER%'s PC" goto SmallEnv
+goto userdone
+:haveuname
+set HOSTNAME=%USERNAME%'s PC
+if not "%HOSTNAME%" == "%USERNAME%'s PC" goto SmallEnv
+:userdone
+set HOSTNAME=%HOSTNAME%, %OS%
+:hostdone
+set OS=
+echo Updating configure scripts for DJGPP...
+test -f %XSRC%/configure.orig
+if not errorlevel 1 goto orig1
+cp -p %XSRC%/configure configure.orig
+goto patchmain
+:orig1
+if not exist configure.orig cp -p %XSRC%/configure.orig configure.orig
+:patchmain
+patch -o configure configure.orig %XSRC%/djgpp/cfgmain.pat
+if errorlevel 1 goto PatchError
+test -d %XSRC%/kpathsea
+if errorlevel 1 goto DviLJk
+if not exist kpathsea\nul mkdir kpathsea
+if exist kpathsea\configure.orig goto orig2
+test -f %XSRC%/kpathsea/configure.orig
+if not errorlevel 1 cp -p %XSRC%/kpathsea/configure.orig kpathsea/configure.orig
+if not exist kpathsea\configure.orig cp -p %XSRC%/kpathsea/configure kpathsea/configure.orig
+:orig2
+patch -o kpathsea/configure kpathsea/configure.orig %XSRC%/djgpp/cfgkpath.pat
+if errorlevel 1 goto PatchError
+:DviLJk
+test -d %XSRC%/dviljk
+if errorlevel 1 goto DviPSk
+if not exist dviljk\nul mkdir dviljk
+if exist dviljk\configure.orig goto orig3
+test -f %XSRC%/dviljk/configure.orig
+if not errorlevel 1 cp -p %XSRC%/dviljk/configure.orig dviljk/configure.orig
+if not exist dviljk\configure.orig cp -p %XSRC%/dviljk/configure dviljk/configure.orig
+:orig3
+patch -o dviljk/configure dviljk/configure.orig %XSRC%/djgpp/cfgdvilj.pat
+if errorlevel 1 goto PatchError
+:DviPSk
+test -d %XSRC%/dvipsk
+if errorlevel 1 goto DTL
+if not exist dvipsk\nul mkdir dvipsk
+if exist dvipsk\configure.orig goto orig4
+test -f %XSRC%/dvipsk/configure.orig
+if not errorlevel 1 cp -p %XSRC%/dvipsk/configure.orig dvipsk/configure.orig
+if not exist dvipsk\configure.orig cp -p %XSRC%/dvipsk/configure dvipsk/configure.orig
+:orig4
+patch -o dvipsk/configure dvipsk/configure.orig %XSRC%/djgpp/cfgdvips.pat
+if errorlevel 1 goto PatchError
+:ODviPSk
+test -d %XSRC%/odvipsk
+if errorlevel 1 goto DTL
+if not exist odvipsk\nul mkdir odvipsk
+if exist odvipsk\configure.orig goto orig40
+test -f %XSRC%/odvipsk/configure.orig
+if not errorlevel 1 cp -p %XSRC%/odvipsk/configure.orig odvipsk/configure.orig
+if not exist odvipsk\configure.orig cp -p %XSRC%/odvipsk/configure odvipsk/configure.orig
+:orig40
+patch -o odvipsk/configure odvipsk/configure.orig %XSRC%/djgpp/cfgdvips.pat
+if errorlevel 1 goto PatchError
+:DTL
+test -d %XSRC%/dtl
+if errorlevel 1 goto DviDvi
+if not exist dtl\nul mkdir dtl
+if exist dtl\configure.orig goto orig5
+test -f %XSRC%/dtl/configure.orig
+if not errorlevel 1 cp -p %XSRC%/dtl/configure.orig dtl/configure.orig
+if not exist dtl\configure.orig cp -p %XSRC%/dtl/configure dtl/configure.orig
+:orig5
+patch -o dtl/configure dtl/configure.orig %XSRC%/djgpp/cfgdtl.pat
+if errorlevel 1 goto PatchError
+:DViDvi
+test -d %XSRC%/dvidvi
+if errorlevel 1 goto LaCheck
+if not exist dvidvi\nul mkdir dvidvi
+if exist dvidvi\configure.orig goto orig6
+test -f %XSRC%/dvidvi/configure.orig
+if not errorlevel 1 cp -p %XSRC%/dvidvi/configure.orig dvidvi/configure.orig
+if not exist dvidvi\configure.orig cp -p %XSRC%/dvidvi/configure dvidvi/configure.orig
+:orig6
+patch -o dvidvi/configure dvidvi/configure.orig %XSRC%/djgpp/cfgdvidv.pat
+if errorlevel 1 goto PatchError
+:LaCheck
+test -d %XSRC%/lacheck
+if errorlevel 1 goto SeeTeXk
+if not exist lacheck\nul mkdir lacheck
+if exist lacheck\configure.orig goto orig7
+test -f %XSRC%/lacheck/configure.orig
+if not errorlevel 1 cp -p %XSRC%/lacheck/configure.orig lacheck/configure.orig
+if not exist lacheck\configure.orig cp -p %XSRC%/lacheck/configure lacheck/configure.orig
+:orig7
+patch -o lacheck/configure lacheck/configure.orig %XSRC%/djgpp/cfglachk.pat
+if errorlevel 1 goto PatchError
+:SeeTeXk
+test -d %XSRC%/seetexk
+if errorlevel 1 goto MakeIndexk
+if not exist seetexk\nul mkdir seetexk
+if exist seetexk\configure.orig goto orig8
+test -f %XSRC%/seetexk/configure.orig
+if not errorlevel 1 cp -p %XSRC%/seetexk/configure.orig seetexk/configure.orig
+if not exist seetexk\configure.orig cp -p %XSRC%/seetexk/configure seetexk/configure.orig
+:orig8
+patch -o seetexk/configure seetexk/configure.orig %XSRC%/djgpp/cfgseetx.pat
+if errorlevel 1 goto PatchError
+:MakeIndexk
+test -d %XSRC%/makeindexk
+if errorlevel 1 goto GsfToPk
+if not exist makeindexk\nul mkdir makeindexk
+if exist makeindexk\configure.orig goto orig9
+test -f %XSRC%/makeindexk/configure.orig
+if not errorlevel 1 cp -p %XSRC%/makeindexk/configure.orig makeindexk/configure.orig
+if not exist makeindexk\configure.orig cp -p %XSRC%/makeindexk/configure makeindexk/configure.orig
+:orig9
+patch -o makeindexk/configure makeindexk/configure.orig %XSRC%/djgpp/cfgmkind.pat
+if errorlevel 1 goto PatchError
+:GsfToPk
+test -d %XSRC%/gsftopk
+if errorlevel 1 goto Ps2Pkm
+if not exist gsftopk\nul mkdir gsftopk
+if exist gsftopk\configure.orig goto orig10
+test -f %XSRC%/gsftopk/configure.orig
+if not errorlevel 1 cp -p %XSRC%/gsftopk/configure.orig gsftopk/configure.orig
+if not exist gsftopk\configure.orig cp -p %XSRC%/gsftopk/configure gsftopk/configure.orig
+:orig10
+patch -o gsftopk/configure gsftopk/configure.orig %XSRC%/djgpp/cfggsfpk.pat
+if errorlevel 1 goto PatchError
+:Ps2Pkm
+test -d %XSRC%/ps2pkm
+if errorlevel 1 goto Tex4HTk
+if not exist ps2pkm\nul mkdir ps2pkm
+if exist ps2pkm\configure.orig goto orig11
+test -f %XSRC%/ps2pkm/configure.orig
+if not errorlevel 1 cp -p %XSRC%/ps2pkm/configure.orig ps2pkm/configure.orig
+if not exist ps2pkm\configure.orig cp -p %XSRC%/ps2pkm/configure ps2pkm/configure.orig
+:orig11
+patch -o ps2pkm/configure ps2pkm/configure.orig %XSRC%/djgpp/cfgpspkm.pat
+if errorlevel 1 goto PatchError
+:Tex4HTk
+test -d %XSRC%/tex4htk
+if errorlevel 1 goto MusixFlx
+if not exist tex4htk\nul mkdir tex4htk
+if exist tex4htk\configure.orig goto orig12
+test -f %XSRC%/tex4htk/configure.orig
+if not errorlevel 1 cp -p %XSRC%/tex4htk/configure.orig tex4htk/configure.orig
+if not exist tex4htk\configure.orig cp -p %XSRC%/tex4htk/configure tex4htk/configure.orig
+:orig12
+patch -o tex4htk/configure tex4htk/configure.orig %XSRC%/djgpp/cfgtexht.pat
+if errorlevel 1 goto PatchError
+:MusixFlx
+test -d %XSRC%/musixflx
+if errorlevel 1 goto DviPDFm
+if not exist musixflx\nul mkdir musixflx
+if exist musixflx\configure.orig goto orig13
+test -f %XSRC%/musixflx/configure.orig
+if not errorlevel 1 cp -p %XSRC%/musixflx/configure.orig musixflx/configure.orig
+if not exist musixflx\configure.orig cp -p %XSRC%/musixflx/configure musixflx/configure.orig
+:orig13
+patch -o musixflx/configure musixflx/configure.orig %XSRC%/djgpp/cfgmusix.pat
+if errorlevel 1 goto PatchError
+:DviPDFm
+test -d %XSRC%/dvipdfm
+if errorlevel 1 goto Web2C
+if not exist dvipdfm\nul mkdir dvipdfm
+if exist dvipdfm\configure.orig goto orig14
+test -f %XSRC%/dvipdfm/configure.orig
+if not errorlevel 1 cp -p %XSRC%/dvipdfm/configure.orig dvipdfm/configure.orig
+if not exist dvipdfm\configure.orig cp -p %XSRC%/dvipdfm/configure dvipdfm/configure.orig
+:orig14
+patch -o dvipdfm/configure dvipdfm/configure.orig %XSRC%/djgpp/cfgdvpdf.pat
+if errorlevel 1 goto PatchError
+:Web2C
+test -d %XSRC%/web2c
+if errorlevel 1 goto skipXDVI
+if not exist web2c\nul mkdir web2c
+if exist web2c\configure.orig goto orig100
+test -f %XSRC%/web2c/configure.orig
+if not errorlevel 1 cp -p %XSRC%/web2c/configure.orig web2c/configure.orig
+if not exist web2c\configure.orig cp -p %XSRC%/web2c/configure web2c/configure.orig
+:orig100
+patch -o web2c/configure web2c/configure.orig %XSRC%/djgpp/cfgweb2c.pat
+if errorlevel 1 goto PatchError
+Rem
+Rem XDvi is not supported on MS-DOS
+GoTo skipXDVI
+if not exist xdvik\nul mkdir xdvik
+if not exist xdvik\configure.orig cp -p %XSRC%/xdvik/configure xdvik/configure.orig
+patch -o xdvik/configure xdvik/configure.orig %XSRC%/djgpp/cfgxdvik.pat
+if errorlevel 1 goto PatchError
+:skipXDVI
+set CONFIG_SHELL=bash.exe
+set INSTALL=${DJDIR}/bin/ginstall -c
+set YACC=bison -y
+set LEX=flex
+set RANLIB=ranlib
+if not "%RANLIB%" == "ranlib" goto SmallEnv
+Rem Use a response file to avoid exceeding the 126-character limit
+echo --prefix=${DJDIR} --datadir=${DJDIR}/share --srcdir=%XSRC% > cfg.rf
+echo --without-x --with-editor='emacs +%%d %%s' --with-epsfwin >> cfg.rf
+echo Configuring...
+sh ./configure i386-pc-msdos.djgppv2 @cfg.rf
+echo Done.
+goto CleanUp
+:SmallEnv
+echo Your environment size is too small. Please enlarge it and run me again.
+set HOSTNAME=
+set OS=
+:CleanUp
+set XSRC=
+set CONFIG_SHELL=
+set INSTALL=
+set YACC=
+set LEX=
+set RANLIB=
+set HOSTNAME=
+if exist cfg.rf del cfg.rf
+goto end
+:PatchError
+echo Failed to patch one or more configure scripts. Configure NOT done.
+:end
diff --git a/Build/extra/djgpp/pathconf.c b/Build/extra/djgpp/pathconf.c
new file mode 100644
index 00000000000..71483684e04
--- /dev/null
+++ b/Build/extra/djgpp/pathconf.c
@@ -0,0 +1,47 @@
+/* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */
+/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
+#include <errno.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <limits.h>
+
+#define TOLOWER(c) (isascii(c) && isupper(c) ? tolower (c) : (c))
+
+long
+pathconf(const char *path, int name)
+{
+ switch (name)
+ {
+ case _PC_LINK_MAX: return LINK_MAX;
+ case _PC_MAX_CANON: return MAX_CANON;
+ case _PC_MAX_INPUT: return MAX_INPUT;
+ case _PC_NAME_MAX: case _PC_PATH_MAX:
+ {
+ int name_max, path_max;
+ int e = errno;
+ char *lfnenv = getenv ("LFN");
+
+ if (!lfnenv || TOLOWER (*lfnenv) != 'n')
+ {
+ errno = 0;
+ _get_volume_info (path, &name_max, &path_max, 0);
+ if (!errno)
+ {
+ errno = e;
+ return (name == _PC_NAME_MAX) ? name_max : path_max;
+ }
+ }
+ return (name == _PC_NAME_MAX) ? NAME_MAX : PATH_MAX;
+ }
+ case _PC_PIPE_BUF: return PIPE_BUF;
+ case _PC_CHOWN_RESTRICTED: return _POSIX_CHOWN_RESTRICTED;
+ case _PC_NO_TRUNC: return _POSIX_NO_TRUNC;
+ case _PC_VDISABLE: return _POSIX_VDISABLE;
+
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+}
diff --git a/Build/extra/djgpp/popen.c b/Build/extra/djgpp/popen.c
new file mode 100644
index 00000000000..67250d6ed7c
--- /dev/null
+++ b/Build/extra/djgpp/popen.c
@@ -0,0 +1,218 @@
+/* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */
+/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
+/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
+/*
+ This is popen() and pclose() for MSDOS. They were developed using
+ Microsoft C, but should port easily to DOS C any compiler.
+
+ Original author: pacetti@fl-ngnet.army.mil
+
+ These routines are hacks, that is they SIMULATE thier UNIX
+ counterparts. Since MSDOS and won't allow concurrent process spawning,
+ you can't really pipe. I came up with this nearly stupid way around
+ piping because I wanted to have some portability between UNIX and MSDOS.
+ I'm probably not the first person to have this idea or implement it, but
+ I think I'm the first to give it away for free (no points?!).
+
+ The functions simulate popen() and pclose() by redirecting stdin or
+ stdout, then spawning a child processes via system().
+
+ If you popen() for read, the stdout is redirected to a temporary
+ file, and the child is spawned. The stdout is reopened via dup2(), the
+ temporary file is opened for read and a file pointer to it is returned.
+
+ If you popen() for write, a temporary file is opened for write, and
+ a file pointer to it is returned. When you pclose(), the stdin is
+ redirected to the temporary file and the child is spawned.
+
+ In both cases, pclose() closes and unlinks the temporary file.
+
+ A static linked list of C structures is built to store necessary
+ info for all popen()ed files so you can popen() more than one file at
+ a time.
+
+ The popen() function will return NULL on an error, or a valid FILE
+ *pointer on a successful open. The pclose() function will return
+ negative one (-1) on an error or zero (0) on a successful close.
+
+ The function prototypes are:
+
+ FILE *popen(command, mode)
+ char *command, char *mode;
+
+ int pclose(pp)
+ FILE *pp;
+
+ Where command is a character string equivilant to a MSDOS command
+ line, mode is "r" for read or "w" for write, and pp is a pointer to a
+ file opened through popen().
+
+ A main() function has been included for testing purposes, to compile
+ it define the preprocessor token TEST at compile time.
+ */
+
+#include <libc/stubs.h>
+#include <io.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <libc/file.h>
+
+/* hold file pointer, descriptor, command, mode, temporary file name,
+ and the status of the command */
+struct pipe_list {
+ FILE *fp;
+ int fd;
+ int exit_status;
+ char *command, mode[10], temp_name[L_tmpnam];
+ struct pipe_list *next;
+};
+
+/* static, global list pointer */
+static struct pipe_list *pl = NULL;
+
+FILE *
+popen (const char *cm, const char *md) /* program name, pipe mode */
+{
+ struct pipe_list *l1, *l2;
+
+ /* make new node */
+ if ((l1 = (struct pipe_list *) malloc (sizeof (struct pipe_list))) == NULL)
+ return NULL;
+
+ /* zero out elements to we'll get here */
+ l1->fd = 0;
+ l1->fp = NULL;
+ l1->next = NULL;
+
+ /* if empty list - just grab new node */
+ if (!pl)
+ pl = l1;
+ else
+ {
+ /* otherwise, find last node in list */
+ ++(l1->fd);
+ l2 = pl;
+ while (l2->next)
+ {
+ ++(l1->fd);
+ l2 = l2->next;
+ };
+ /* add new node to list */
+ l2->next = l1;
+ }
+
+ /* stick in elements we know already */
+ l1->exit_status = -1;
+ strcpy (l1->mode, md);
+ if (tmpnam (l1->temp_name) == NULL)
+ return NULL;
+
+ /* if can save the program name, build temp file */
+ if ((l1->command = malloc(strlen(cm)+1)))
+ {
+ strcpy(l1->command, cm);
+ /* if caller wants to read */
+ if (l1->mode[0] == 'r')
+ {
+ /* dup stdout */
+ if ((l1->fd = dup (fileno (stdout))) == EOF)
+ l1->fp = NULL;
+ else if (!(l1->fp = freopen (l1->temp_name, "wb", stdout)))
+ l1->fp = NULL;
+ else
+ /* exec cmd */
+ if ((l1->exit_status = system (cm)) == EOF)
+ l1->fp = NULL;
+ /* reopen real stdout */
+ if (dup2 (l1->fd, fileno (stdout)) == EOF)
+ l1->fp = NULL;
+ /* if cmd couldn't be run, make sure we return NULL */
+ else if (l1->exit_status != EOF)
+ /* open file for reader */
+ l1->fp = fopen (l1->temp_name, l1->mode);
+ close(l1->fd);
+ }
+ else
+ /* if caller wants to write */
+ if (l1->mode[0] == 'w')
+ /* open temp file */
+ l1->fp = fopen (l1->temp_name, l1->mode);
+ else
+ /* unknown mode */
+ l1->fp = NULL;
+ }
+ return l1->fp; /* return == NULL ? ERROR : OK */
+}
+
+int
+pclose (FILE *pp)
+{
+ struct pipe_list *l1, *l2; /* list pointers */
+ int retval=0; /* function return value */
+
+ /* if pointer is first node */
+ if (pl->fp == pp)
+ {
+ /* save node and take it out the list */
+ l1 = pl;
+ pl = l1->next;
+ }
+ else
+ /* if more than one node in list */
+ if (pl->next)
+ {
+ /* find right node */
+ for (l2 = pl, l1 = pl->next; l1; l2 = l1, l1 = l2->next)
+ if (l1->fp == pp)
+ break;
+
+ /* take node out of list */
+ l2->next = l1->next;
+ }
+ else
+ return -1;
+
+ /* if FILE not in list - return error */
+ if (l1->fp == pp)
+ {
+ /* close the (hopefully) popen()ed file */
+ fclose (l1->fp);
+
+ /* if pipe was opened to write */
+ if (l1->mode[0] == 'w')
+ {
+ /* dup stdin */
+ if ((l1->fd = dup (fileno (stdin))) == EOF)
+ retval = -1;
+ else
+ /* open temp stdin */
+ if (!(l1->fp = freopen (l1->temp_name, "rb", stdin)))
+ retval = -1;
+ else
+ /* exec cmd */
+ if ((retval = system (l1->command)) != EOF)
+ {
+ /* reopen stdin */
+ if (dup2 (l1->fd, fileno (stdin)) == EOF)
+ retval = -1;
+ }
+ close(l1->fd);
+ }
+ else
+ /* if pipe was opened to read, return the exit status we saved */
+ if (l1->mode[0] == 'r')
+ retval = l1->exit_status;
+ else
+ /* invalid mode */
+ retval = -1;
+ }
+ remove (l1->temp_name); /* remove temporary file */
+ free (l1->command); /* dealloc memory */
+ free (l1); /* dealloc memory */
+ l1 = NULL; /* make pointer bogus */
+
+ return retval; /* retval==0 ? OK : ERROR */
+}
diff --git a/Build/extra/djgpp/putenv.c b/Build/extra/djgpp/putenv.c
new file mode 100644
index 00000000000..efc0241ff07
--- /dev/null
+++ b/Build/extra/djgpp/putenv.c
@@ -0,0 +1,143 @@
+/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
+/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
+#include <libc/stubs.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libc/bss.h>
+#include <libc/environ.h>
+
+/*
+
+ This routine assumes that the environ array and all strings it
+ points to were malloc'd. Nobody else should modify the environment
+ except crt1.c
+
+*/
+
+extern char **environ;
+static char **prev_environ = NULL; /* to know when it's safe to call `free' */
+static int ecount = -1;
+static int emax = -1;
+static int putenv_bss_count = -1;
+
+
+/* This gets incremented every time some variable in the
+ environment is added, deleted, or changes its value.
+ It is meant to be used by functions that depend on values
+ of environment variables, but don't want to call `getenv'
+ unnecessarily (example: `__use_lfn').
+
+ Users should compare this variable with their static
+ variable whose value is initialized to zero; thus this
+ variable begins with 1 so first time users look they will
+ call `getenv'. */
+unsigned __environ_changed = 1;
+
+int
+putenv(const char *val)
+{
+ int vlen = strlen(val);
+ char *epos = strchr(val, '=');
+ /* Feature: VAL without a `=' means delete the entry. GNU `putenv'
+ works that way, and `env' from GNU Sh-utils counts on this behavior. */
+ int nlen = epos ? epos - val + 1 : vlen;
+ int eindex;
+
+ /* Force recomputation of the static counters.
+
+ The second condition of the next if clause covers the case that
+ somebody pointed environ to another array, which invalidates
+ `ecount' and `emax'. This can be used to change the environment
+ to something entirely different, or to effectively discard it
+ altogether. GNU `env' from Sh-utils does just that. */
+ if (putenv_bss_count != __bss_count
+ || environ != prev_environ)
+ {
+ for (ecount=0; environ[ecount]; ecount++);
+ emax = ecount;
+ /* Bump the count to a value no function has yet seen,
+ even if they were dumped with us. */
+ __environ_changed++;
+ if (putenv_bss_count != __bss_count)
+ {
+ putenv_bss_count = __bss_count;
+ prev_environ = environ; /* it's malloced by crt1.c */
+ }
+ }
+
+ for (eindex=0; environ[eindex]; eindex++)
+ if (strncmp(environ[eindex], val, nlen) == 0
+ && (epos || environ[eindex][nlen] == '='))
+ {
+ char *oval = environ[eindex];
+ int olen = strlen(oval);
+
+ if (val[nlen] == 0 && !epos) /* delete the entry */
+ {
+ free(oval);
+ environ[eindex] = environ[ecount-1];
+ environ[ecount-1] = 0;
+ ecount--;
+ __environ_changed++;
+ return 0;
+ }
+
+ /* change existing entry */
+ if (strcmp(environ[eindex]+nlen, val+nlen) == 0)
+ return 0; /* they're the same */
+
+ /* If new is the same length as old, reuse the same
+ storage. If new is shorter, call realloc to shrink the
+ allocated block: this causes less memory fragmentation. */
+ if (vlen != olen)
+ {
+ if (vlen > olen)
+ environ[eindex] = (char *)malloc(vlen+1);
+ else /* vlen < olen */
+ environ[eindex] = (char *)realloc(oval, vlen+1);
+ if (environ[eindex] == 0)
+ {
+ environ[eindex] = oval;
+ return -1;
+ }
+ if (vlen > olen)
+ free(oval);
+ }
+ strcpy(environ[eindex], val);
+ __environ_changed++;
+ return 0;
+ }
+
+ /* delete nonexisting entry? */
+ if (val[nlen] == 0 && !epos)
+ return 0;
+
+ /* create new entry */
+ if (ecount >= emax)
+ {
+ char **enew;
+ emax += 10;
+ enew = (char **)malloc((emax+1) * sizeof(char *));
+ if (enew == 0)
+ return -1;
+ memcpy(enew, environ, ecount * sizeof(char *));
+ /* If somebody set environ to another array, we can't
+ safely free it. Better leak memory than crash. */
+ if (environ == prev_environ)
+ free(environ);
+ environ = enew;
+ prev_environ = environ;
+ }
+
+ environ[ecount] = (char *)malloc(vlen+1);
+ if (environ[ecount] == 0)
+ return -1;
+ strcpy(environ[ecount], val);
+
+ ecount++;
+ environ[ecount] = 0;
+
+ __environ_changed++;
+
+ return 0;
+}
diff --git a/Build/extra/djgpp/stat.c b/Build/extra/djgpp/stat.c
new file mode 100644
index 00000000000..69fe270b848
--- /dev/null
+++ b/Build/extra/djgpp/stat.c
@@ -0,0 +1,935 @@
+/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
+/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
+/* This is file STAT.C */
+/*
+ * Almost a 100% U**X-compatible stat() substitute.
+ *
+ * Usage:
+ *
+ * That's easy: put this into libc.a, then just call stat() as usual.
+ *
+ * Rationale:
+ *
+ * Many Unix-born programs make heavy use of stat() library
+ * function to make decisions on files' equality, size, access
+ * attributes etc. In the MS-DOS environment, many implementations
+ * of stat() are crippled, because DOS makes it very hard to get to
+ * certain pieces of information about files and directories. Thus
+ * porting a program to DOS is usually an exercise in #ifdef'ing.
+ * This implementation facilitates porting Unix programs to MS-DOS
+ * by providing stat() which is much more Unix-compatible than those
+ * of most DOS-based C compilers (e.g., Borland's).
+ * Specifically, the following issues are taken care of:
+ *
+ * 1. This stat() doesn't fail for root directories, returning
+ * valid information.
+ * 2. Directory size is not reported zero; the number of used
+ * directory entries multiplied by entry size is returned instead.
+ * 3. Mode bits are set for all 3 groups (user, group, other).
+ * 4. Directories are NOT reported read-only, unless one of R, H or S
+ * attributes is set.
+ * 5. Directories have their execute bit set, as they do under Unix.
+ * 6. Device names (such as /dev/con, lpt1, aux etc.) are treated as
+ * if they were on a special drive called `@:' (st_dev = -1).
+ * The "character special" mode bit is set for these devices.
+ * 7. The inode number (st_ino) is taken from the starting cluster
+ * number of the file. If the cluster number is unavailable, it
+ * is invented using the file's name in a manner that minimizes
+ * the possibility of inventing an inode which already belongs
+ * to another file. See below for details.
+ * 8. Executable files are found based on files' extensions and
+ * magic numbers present at their beginning, and their execute
+ * bits are set.
+ *
+ * Lossage:
+ *
+ * Beautiful as the above sounds, this implementation does fail
+ * under certain circumstances. The following is a list of known
+ * problems:
+ *
+ * 1. The time fields for a root directory cannot be obtained, so
+ * they are set to the beginning of the Epoch.
+ * 2. For files which reside on networked drives, the inode number
+ * is invented, because network redirectors usually do not
+ * bring that info with them. This is not a total lossage, but
+ * it could get us a different inode for each program run.
+ * 3. Empty files do not have a starting cluster number, because
+ * DOS doesn't allocate one until you actually write something
+ * to a file. For these the inode is also invented.
+ * 4. If the st_ino field is a 16 bit number, the invented inode
+ * numbers are from 65535 and down, assuming that most disks have
+ * unused portions near their end. Valid cluster numbers are 16-bit
+ * unsigned integers, so a possibility of a clash exists, although
+ * the last 80 or more cluster numbers are unused on all drives
+ * I've seen. If the st_ino is 32 bit, then invented inodes are
+ * all greater than 64k, which totally eliminates a possibility
+ * of a clash with an actual cluster number.
+ * 5. The method of computing directory size is an approximation:
+ * a directory might consume much more space, if it has many
+ * deleted entries. Still, this is a close approximation, and
+ * it does follow the logic of reporting size for a regular file:
+ * only the actually used space is returned.
+ * 6. As this implementation relies heavily on undocumented DOS
+ * features, it will fail to get actual file info in environments
+ * other than native DOS, such as DR-DOS, OS/2 etc. For these,
+ * the function will return whatever info is available with
+ * conventional DOS calls, which is no less than any other
+ * implementation could do. This stat() might also fail for
+ * future DOS versions, if the layout of internal DOS data
+ * area is changed; however, this seems unlikely.
+ *
+ * Copyright (c) 1994-96 Eli Zaretskii <eliz@is.elta.co.il>
+ *
+ * This software may be used freely so long as this copyright notice is
+ * left intact. There is no warranty on this software.
+ *
+ */
+
+/*
+ * Tested with DJGPP port of GNU C compiler, versions 1.11maint5 and 1.12,
+ * under MS-DOS 3.3, 4.01, 5.0, 6.20 (with and without DoubleSpace) and
+ * with networked drives under XFS 1.86, Novell Netware 3.22, and
+ * TSoft NFS 0.24Beta.
+ *
+ */
+
+#include <libc/stubs.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <time.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dos.h>
+#include <dir.h>
+
+#include <dpmi.h>
+#include <go32.h>
+#include <libc/farptrgs.h>
+#include <libc/bss.h>
+#include <libc/dosio.h>
+
+#include "xstat.h"
+
+int __getdisk(void);
+int __findfirst(const char *, struct ffblk *, int);
+int __findnext(struct ffblk *);
+
+#define ALL_FILES (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_DIREC|FA_ARCH)
+
+#define _STAT_INODE 1 /* should we bother getting inode numbers? */
+#define _STAT_EXEC_EXT 2 /* get execute bits from file extension? */
+#define _STAT_EXEC_MAGIC 4 /* get execute bits from magic signature? */
+#define _STAT_DIRSIZE 8 /* compute directory size? */
+#define _STAT_ROOT_TIME 0x10 /* try to get root dir time stamp? */
+#define _STAT_WRITEBIT 0x20 /* fstat() needs write bit? */
+
+/* Should we bother about executables at all? */
+#define _STAT_EXECBIT (_STAT_EXEC_EXT | _STAT_EXEC_MAGIC)
+
+/* The structure of the full directory entry. This is the 32-byte
+ record present for each file/subdirectory in a DOS directory.
+ Although the ``packed'' attribute seems to be unnecessary, I use
+ it to be sure it will still work for future versions of GCC. */
+
+struct full_dirent {
+ char fname[8] __attribute__ ((packed));
+ char fext[3] __attribute__ ((packed));
+ unsigned char fattr __attribute__ ((packed));
+ unsigned char freserved[10] __attribute__ ((packed));
+ unsigned short ftime __attribute__ ((packed));
+ unsigned short fdate __attribute__ ((packed));
+ unsigned short fcluster __attribute__ ((packed));
+ unsigned int fsize __attribute__ ((packed));
+};
+
+
+/* Static variables to speed up SDA DOS Swappable Data Area access on
+ subsequent calls. */
+
+/* The count of number of SDA's we have. It is more than 1 for DOS
+ 4.x only. If it has a value of 0, the function init_dirent_table()
+ will be called to compute the addresses where we are to look for
+ directory entry of our file. A value of -1 means this method is
+ unsupported for this version of DOS. */
+static int dirent_count;
+
+/* The table of places to look for our directory entry.
+ Each entry in the table is a linear offset from the beginning of
+ conventional memory which points to a particular location within
+ one of the SDA's, where the entry of a file being stat()'ed could
+ appear. The offsets are computed once (when the routine is first
+ called) and then reused for other calls. The actual storage for
+ the table is malloc()'ed when this function is first called. */
+static unsigned int * dirent_table;
+
+/* When we have only one SDA, this is where its only place to look for
+ directory entry is stored. */
+static unsigned int dirent_place;
+
+/* This holds the fail bits from the last call to init_dirent_table(),
+ so we can return them every time get_inode_from_sda() is called. */
+static unsigned short init_dirent_table_bits;
+
+/* Holds the last seen value of __bss_count, to be safe for
+ restarted programs (emacs). */
+static int stat_count = -1;
+
+/*
+ * Parts of the following code is derived from file DOSSWAP.C,
+ * which came with ``Undocumented DOS'', 1st edition.
+ */
+
+/* Compute table of pointers to look for directory entry of a file. */
+static int
+init_dirent_table (void)
+{
+ short get_sda_func;
+ unsigned short dirent_offset;
+ unsigned short true_dos_version;
+ unsigned short dos_major, dos_minor;
+ __dpmi_regs regs;
+
+ if (dirent_count == -1) /* we already tried and found we can't */
+ return 0;
+
+ /* Compute INT 21h function number and offset of directory entry
+ from start of SDA. These depend on the DOS version.
+ We need exact knowledge about DOS internals, so we need the
+ TRUE DOS version (not the simulated one by SETVER), if that's
+ available. */
+ true_dos_version = _get_dos_version(1);
+ dos_major = true_dos_version >> 8;
+ dos_minor = true_dos_version & 0xff;
+
+ if ((dos_major == 3) && (dos_minor >= 10))
+ {
+ get_sda_func = 0x5d06;
+ dirent_offset = 0x1a7;
+ }
+ else if (dos_major == 4)
+ {
+ /* According to ``Undocumented DOS, 2nd edition'', I could have
+ used 5d06 here, as for DOS 5 and above, but I like to be
+ defensive. In fact, the above book itself uses 5d0b, contrary
+ to its own recommendation. */
+ get_sda_func = 0x5d0b;
+ dirent_offset = 0x1b3;
+ }
+ else if (dos_major >= 5)
+ {
+ get_sda_func = 0x5d06;
+ dirent_offset = 0x1b3;
+ }
+ else
+ {
+ _djstat_fail_bits |= _STFAIL_OSVER;
+ dirent_count = -1;
+ return 0;
+ }
+
+ _djstat_fail_bits &= ~_STFAIL_OSVER; /* version is OK */
+
+ /* Get the pointer to SDA by calling undocumented function 5dh of INT 21. */
+ regs.x.ax = get_sda_func;
+ __dpmi_int(0x21, &regs);
+ if (regs.x.flags & 1)
+ {
+ _djstat_fail_bits |= _STFAIL_SDA;
+ dirent_count = -1; /* if the call failed, never try this later */
+ return 0;
+ }
+
+ _djstat_fail_bits &= ~_STFAIL_SDA; /* Get SDA succeeded */
+
+ /* DOS 4.x might have several SDA's, which means we might have more
+ than one place to look into. (It is typical of DOS 4 to complicate
+ things.)
+ Compute all the possible addresses where we will have to look. */
+ if (dos_major == 4)
+ {
+ /* The pointer returned by INT 21h, AX=5D0b points to a header
+ which holds a number of SDA's and then an array of that number
+ of records each one of which includes address of an SDA (DWORD)
+ and its length and type (encoded in a WORD).
+ While walking this list of SDA's, we add to each pointer the
+ offset of directory entry and stash the resulting address in
+ our table for later use. */
+
+ int sda_list_walker = MK_FOFF(regs.x.ds, regs.x.si);
+ int i;
+ int *tbl;
+
+ dirent_count = _farpeekw(_dos_ds, sda_list_walker); /* number of SDA's */
+
+ /* Allocate storage for table. */
+ tbl = dirent_table = (int *)malloc(dirent_count*sizeof(int));
+ if (!dirent_table)
+ {
+ /* If malloc() failed, maybe later it will succeed, so don't
+ store -1 in dirent_count. */
+ dirent_count = 0;
+ _djstat_fail_bits |= _STFAIL_DCOUNT;
+ return 0;
+ }
+
+ memset(dirent_table, 0, dirent_count*sizeof(int));
+ _djstat_fail_bits &= ~_STFAIL_DCOUNT; /* dirent_count seems OK */
+
+ /* Walk the array of pointers, computing addresses of directory
+ entries and stashing them in our table. */
+ _farsetsel(_dos_ds);
+ for (i = dirent_count, sda_list_walker += 2; i--; sda_list_walker += 6)
+ {
+ int sda_start = _farnspeekl(sda_list_walker);
+ unsigned short sda_len = _farnspeekw(sda_list_walker + 4) & 0x7fff;
+
+ /* Let's be defensive here: if this SDA is too short to have
+ place for directory entry, we won't use it. */
+ if (sda_len > dirent_offset)
+ *tbl++ = sda_start + dirent_offset;
+ else
+ dirent_count--;
+ }
+ }
+
+ /* DOS 3.1 and 5.0 or later. We have only one SDA pointed to by
+ whatever INT 21h, AH=5d returns. */
+ else
+ {
+ dirent_count = 1;
+ dirent_place = MK_FOFF(regs.x.ds, regs.x.si) + dirent_offset;
+ dirent_table = &dirent_place;
+ }
+
+ return 1;
+}
+
+/* Get inode number by searching DOS Swappable Data Area.
+ The entire directory entry for a file found by FindFirst/FindNext
+ appears at a certain (version-dependent) offset in the SDA after
+ one of those function is called.
+ Should be called immediately after calling DOS FindFirst function,
+ before the info is overwritten by somebody who calls it again. */
+static unsigned int
+get_inode_from_sda(const char *basename)
+{
+ int count = dirent_count;
+ unsigned int * dirent_p = dirent_table;
+ unsigned short dos_mem_base = _dos_ds;
+ unsigned short our_mem_base = _my_ds();
+ char * dot = strchr(basename, '.');
+ size_t total_len = strlen(basename);
+ int name_len = dot ? dot - basename : total_len;
+ int ext_len = dot ? total_len - name_len - 1 : 0;
+ int cluster_offset = offsetof(struct full_dirent, fcluster);
+
+ /* Restore failure bits set by last call to init_dirent_table(), so
+ they will be reported as if it were called now. */
+ _djstat_fail_bits |= init_dirent_table_bits;
+
+ /* Force reinitialization in restarted programs (emacs). */
+ if (stat_count != __bss_count)
+ {
+ stat_count = __bss_count;
+ dirent_count = 0;
+ }
+
+ /* Initialize the table of SDA entries where we are to look for
+ our file. */
+ if (!dirent_count && !init_dirent_table())
+ {
+ /* Don't save the truename failure bit. */
+ init_dirent_table_bits = (_djstat_fail_bits & ~_STFAIL_TRUENAME);
+ return 0;
+ }
+ init_dirent_table_bits = (_djstat_fail_bits & ~_STFAIL_TRUENAME);
+ if (dirent_count == -1)
+ return 0;
+
+ count = dirent_count;
+ dirent_p = dirent_table;
+
+ _farsetsel(dos_mem_base);
+
+ /* This is DOS 4.x lossage: this loop might execute many times.
+ For other DOS versions it is executed exactly once. */
+ while (count--)
+ {
+ unsigned int src_address = *dirent_p & 0x000fffff;
+ char cmp_buf[sizeof(struct full_dirent)];
+
+ /* Copy the directory entry from the SDA to local storage.
+ The filename is stored there in infamous DOS format: name and
+ extension blank-padded to 8/3 characters, no dot between them. */
+ movedata(dos_mem_base, src_address, our_mem_base, (unsigned int)cmp_buf,
+ sizeof(struct full_dirent));
+
+ /* If this is the filename we are looking for, return
+ its starting cluster. */
+ if (!strncmp(cmp_buf, basename, name_len) &&
+ (ext_len == 0 || !strncmp(cmp_buf + 8, dot + 1, ext_len)))
+ return (unsigned int)_farnspeekw(*dirent_p + cluster_offset);
+
+ /* This is not our file. Search more, if more addresses left. */
+ dirent_p++;
+ }
+
+ /* If not found, give up. */
+ _djstat_fail_bits |= _STFAIL_BADSDA;
+ return 0;
+}
+
+int _ioctl_get_first_cluster(const char *);
+
+/* Get the number of the first cluster of PATHNAME using
+ the IOCTL call Int 21h/AX=440Dh/CX=0871h, if that call
+ is supported by the OS. Return the cluster number, or
+ a negative number if this service isn't supported. */
+
+int
+_ioctl_get_first_cluster(const char *pathname)
+{
+ __dpmi_regs r;
+
+ /* See if the IOCTL GetFirstCluster call is supported. */
+ r.x.ax = 0x4411; /* query generic IOCTL capability by drive */
+ r.h.bl = pathname[0] & 0x1f; /* drive number (1=A:) */
+ r.x.cx = 0x871;
+ __dpmi_int(0x21, &r);
+ if ((r.x.flags & 1) == 0 && r.x.ax == 0)
+ {
+ r.x.ax = 0x440d; /* Generic IOCTL */
+ r.x.cx = 0x0871; /* category code 08h, minor code 71h */
+ r.x.bx = 1; /* pathname uses current OEM character set */
+ r.x.ds = __tb >> 4;
+ r.x.dx = __tb & 0x0f;
+ _put_path(pathname);
+ __dpmi_int(0x21, &r);
+ if ((r.x.flags & 1) == 0)
+ return ( ((int)r.x.dx << 16) + r.x.ax );
+ }
+ return -1;
+}
+
+static char blanks_8[] = " ";
+
+static int
+stat_assist(const char *path, struct stat *statbuf)
+{
+ struct ffblk ff_blk;
+ char canon_path[MAX_TRUE_NAME];
+ char pathname[MAX_TRUE_NAME];
+ short drv_no;
+ unsigned dos_ftime;
+
+ _djstat_fail_bits = 0;
+
+ memset(statbuf, 0, sizeof(struct stat));
+ memset(&dos_ftime, 0, sizeof(dos_ftime));
+
+ /* Fields which are constant under DOS. */
+ statbuf->st_uid = getuid();
+ statbuf->st_gid = getgid();
+ statbuf->st_nlink = 1;
+#ifndef NO_ST_BLKSIZE
+ statbuf->st_blksize = _go32_info_block.size_of_transfer_buffer;
+#endif
+
+ /* Make the path explicit. This makes the rest of our job much
+ easier by getting rid of some constructs which, if present,
+ confuse `_truename' and/or `findfirst'. In particular, it
+ deletes trailing slashes, makes "d:" explicit, and allows us
+ to make an illusion of having a ".." entry in root directories. */
+ _fixpath (path, pathname);
+
+ /* Get the drive number. It is always explicit, since we
+ called `_fixpath' on the original pathname. */
+ drv_no = toupper(pathname[0]) - 'A';
+
+ /* Produce canonical pathname, with all the defaults resolved and
+ all redundant parts removed. This calls undocumented DOS
+ function 60h. */
+ if (_truename(path, canon_path) || _truename(pathname, canon_path))
+ {
+ /* Detect character device names which must be treated specially.
+ We could simply call FindFirst and test the 6th bit, but some
+ versions of DOS have trouble with this (see Ralph Brown's
+ Interrupt List, ``214E'', under `Bugs'). Instead we use
+ truename() which calls INT 21/AX=6000H. For character devices
+ it returns X:/DEVNAME, where ``X'' is the current drive letter
+ (note the FORWARD slash!). E.g., for CON or \dev\con it will
+ return C:/CON.
+ We will pretend that devices all reside on a special drive
+ called `@', which corresponds to st_dev = -1. This is because
+ these devices have no files, and we must invent inode numbers
+ for them; this scheme allows to lower a risk of clash between
+ invented inode and one which belongs to a real file. This is
+ also compatible with what our fstat() does.
+ */
+ char_dev:
+ if (canon_path[2] == '/')
+ {
+ char dev_name[9]; /* devices are at most 8 characters long */
+
+ strncpy(dev_name, canon_path + 3, 8); /* the name without `X:/' */
+ dev_name[8] = '\0';
+ strcpy(canon_path, "@:\\dev\\");
+ strcat(canon_path, dev_name);
+ strncat(canon_path, blanks_8, 8 - strlen(dev_name)); /* blank-pad */
+ canon_path[15] = '\0'; /* ensure zero-termination */
+
+ /* Invent inode */
+ statbuf->st_ino = _invent_inode(canon_path, 0, 0);
+
+ /* Device code. */
+ statbuf->st_dev = -1;
+#ifdef HAVE_ST_RDEV
+ statbuf->st_rdev = -1;
+#endif
+
+ /* Set mode bits, including character special bit.
+ Should we treat printer devices as write-only? */
+ statbuf->st_mode |= (S_IFCHR | READ_ACCESS | WRITE_ACCESS);
+
+ /* We will arrange things so that devices have current time in
+ the access-time and modified-time fields of struct stat, and
+ zero (the beginning of times) in creation-time field. This
+ is consistent with what DOS FindFirst function returns for
+ character device names (if it succeeds--see above). */
+ statbuf->st_atime = statbuf->st_mtime = time(0);
+ statbuf->st_ctime = _file_time_stamp(dos_ftime);
+
+ return 0;
+ }
+ else if (canon_path[0] >= 'A' && canon_path[0] <= 'z' &&
+ canon_path[1] == ':' && canon_path[2] == '\\')
+ {
+ /* _truename() returned a name with a drive letter. (This is
+ always so for local drives, but some network redirectors
+ also do this.) We will take this to be the TRUE drive
+ letter, because _truename() knows about SUBST and JOIN.
+ If the canonicalized path returns in the UNC form (which
+ means the drive is remote), it cannot be SUBSTed or JOINed,
+ because SUBST.EXE and JOIN.EXE won't let you do it; so, for
+ these cases, there is no problem in believing the drive
+ number we've got from the original path (or is there?). */
+ drv_no = toupper(canon_path[0]) - 'A';
+ }
+ }
+ else
+ {
+ /* _truename() failed. (This really shouldn't happen, but who knows?)
+ At least uppercase all letters, convert forward slashes to backward
+ ones, and pray... */
+ register const char *src = pathname;
+ register char *dst = canon_path;
+
+ while ( (*dst = (*src > 'a' && *src < 'z'
+ ? *src++ - ('a' - 'A')
+ : *src++)) != '\0')
+ {
+ if (*dst == '/')
+ *dst = '\\';
+ dst++;
+ }
+
+ _djstat_fail_bits |= _STFAIL_TRUENAME;
+ }
+
+ /* Call DOS FindFirst function, which will bring us most of the info. */
+ if (!__findfirst(pathname, &ff_blk, ALL_FILES))
+ {
+ /* Time fields. */
+ dos_ftime =
+ ( (unsigned short)ff_blk.ff_fdate << 16 ) +
+ (unsigned short)ff_blk.ff_ftime;
+
+ /* If the IOCTL GetFirstCluster call is available, try it first. */
+ if ( (_djstat_flags & _STAT_INODE) == 0
+ && (statbuf->st_ino = _ioctl_get_first_cluster(pathname)) <= 0)
+ {
+
+ /* For networked drives, don't believe the starting cluster
+ that the network redirector feeds us; always invent inode.
+ This is because network redirectors leave bogus values there,
+ and we don't have enough info to decide if the starting
+ cluster value is real or just a left-over from previous call.
+ For local files, try first using DOS SDA to get the inode from
+ the file's starting cluster number; if that fails, invent inode.
+ Note that the if clause below tests for non-zero value returned
+ by is_remote_drive(), which includes possible failure (-1).
+ This is because findfirst() already succeeded for our pathname,
+ and therefore the drive is a legal one; the only possibility that
+ is_remote_drive() fails is that some network redirector takes
+ over IOCTL functions in an incompatible way, which means the
+ drive is remote. QED. */
+ if (statbuf->st_ino == 0 /* don't try SDA if IOCTL call succeeded */
+ || _is_remote_drive(drv_no)
+ || (statbuf->st_ino = get_inode_from_sda(ff_blk.ff_name)) == 0)
+ {
+ _djstat_fail_bits |= _STFAIL_HASH;
+ statbuf->st_ino =
+ _invent_inode(canon_path, dos_ftime, ff_blk.ff_fsize);
+ }
+ else if (toupper (canon_path[0]) != toupper (pathname[0])
+ && canon_path[1] == ':'
+ && canon_path[2] == '\\'
+ && canon_path[3] == '\0')
+ /* The starting cluster in SDA for the root of JOINed drive
+ actually belongs to the directory where that drive is
+ ``mounted''. This can potentially be the cluster of
+ another file on the JOINed drive. We cannot allow this. */
+ statbuf->st_ino = 1;
+ }
+
+ /* File size. */
+ statbuf->st_size = ff_blk.ff_fsize;
+
+ /* Mode bits. */
+ statbuf->st_mode |= READ_ACCESS;
+ if ( !(ff_blk.ff_attrib & 0x07) ) /* no R, H or S bits set */
+ statbuf->st_mode |= WRITE_ACCESS;
+
+ /* Sometimes `_truename' doesn't return X:/FOO for character
+ devices. However, FindFirst returns attribute 40h for them. */
+ if (ff_blk.ff_attrib == 0x40)
+ {
+ size_t cplen = strlen (canon_path);
+ char *pslash = canon_path + cplen - 1;
+
+ while (pslash > canon_path + 2 && *pslash != '\\')
+ pslash--;
+
+ /* Force it into X:/FOO form. */
+ if (canon_path[1] == ':')
+ {
+ if (pslash > canon_path + 2)
+ memmove (canon_path + 2, pslash,
+ cplen - (pslash - canon_path) + 1);
+ canon_path[2] = '/';
+ goto char_dev;
+ }
+ }
+
+ /* Directories should have Execute bits set. */
+ if (ff_blk.ff_attrib & 0x10)
+ statbuf->st_mode |= (S_IFDIR | EXEC_ACCESS);
+
+ else
+ {
+ /* This is a regular file. */
+ char *extension = strrchr(ff_blk.ff_name, '.');
+
+ /* Set regular file bit. */
+ statbuf->st_mode |= S_IFREG;
+
+ if ((_djstat_flags & _STAT_EXECBIT) != _STAT_EXECBIT)
+ {
+ /* Set execute bits based on file's extension and
+ first 2 bytes. */
+ if (extension)
+ extension++; /* get past the dot */
+ if (_is_executable(pathname, -1, extension))
+ statbuf->st_mode |= EXEC_ACCESS;
+ }
+ }
+ }
+ else if ((_djstat_fail_bits & _STFAIL_TRUENAME))
+ {
+ /* If both `findfirst' and `_truename' failed, this must
+ be a non-existent file or an illegal/inaccessible drive. */
+ if (errno == ENMFILE)
+ errno = ENODEV;
+ return -1;
+ }
+ else if (pathname[3] == '\0')
+ {
+ /* Detect root directories. These are special because, unlike
+ subdirectories, FindFirst fails for them. We look at PATHNAME
+ because a network redirector could tweak what `_truename'
+ returns to be utterly unrecognizable as root directory. PATHNAME
+ always begins with "d:/", so it is root if PATHNAME[3] = 0. */
+
+ /* Mode bits. */
+ statbuf->st_mode |= (S_IFDIR|READ_ACCESS|WRITE_ACCESS|EXEC_ACCESS);
+
+ /* Root directory will have an inode = 1. Valid cluster numbers
+ for real files under DOS start with 2. */
+ statbuf->st_ino = 1;
+
+ /* Simulate zero size. This is what FindFirst returns for every
+ sub-directory. Later we might compute a better approximation
+ (see below). */
+ ff_blk.ff_fsize = 0L;
+
+ /* The time fields are left to be zero, unless the user wants us
+ to try harder. In the latter case, we check if the root has
+ a volume label entry, and use its time if it has. */
+
+ if ( (_djstat_flags & _STAT_ROOT_TIME) == 0 )
+ {
+ char buf[7];
+
+ strcpy(buf, pathname);
+ strcat(buf, "*.*");
+ if (!__findfirst(buf, &ff_blk, FA_LABEL))
+ dos_ftime = ( (unsigned)ff_blk.ff_fdate << 16 ) + ff_blk.ff_ftime;
+ else
+ _djstat_fail_bits |= _STFAIL_LABEL;
+ }
+ }
+ else
+ {
+ int e = errno; /* errno value from original FindFirst on PATHNAME */
+ int i = 0;
+ int j = strlen (pathname) - 1;
+
+ /* Check for volume labels. We did not mix FA_LABEL with
+ other attributes in the call to `__findfirst' above,
+ because some environments will return bogus info in
+ that case. For instance, Win95 and WinNT seem to
+ ignore `pathname' and return the volume label even if it
+ doesn't fit the name in `pathname'. This fools us to
+ think that a non-existent file exists and is a volume
+ label. Hence we test the returned name to be PATHNAME. */
+ if (!__findfirst(pathname, &ff_blk, FA_LABEL))
+ {
+ i = strlen (ff_blk.ff_name) - 1;
+
+ if (j >= i)
+ {
+ for ( ; i >= 0 && j >= 0; i--, j--)
+ if (toupper (ff_blk.ff_name[i]) != toupper (pathname[j]))
+ break;
+ }
+ }
+
+ if (i < 0 && pathname[j] == '/')
+ {
+ /* Indeed a label. */
+ statbuf->st_mode = READ_ACCESS;
+#ifdef S_IFLABEL
+ statbuf->st_mode |= S_IFLABEL;
+#endif
+ statbuf->st_ino = 1;
+ statbuf->st_size = 0;
+ dos_ftime = ( (unsigned)ff_blk.ff_fdate << 16 ) + ff_blk.ff_ftime;
+ }
+ else
+ {
+ /* FindFirst on volume labels might set errno to ENMFILE or even
+ to something more strange like EINVAl; correct that. */
+ errno = e; /* restore errno from the original FindFirst */
+ if (errno == ENMFILE)
+ errno = ENOENT;
+ return -1;
+ }
+ }
+
+ /* Device code. */
+ statbuf->st_dev = drv_no;
+#ifdef HAVE_ST_RDEV
+ statbuf->st_rdev = drv_no;
+#endif
+
+ /* Time fields. */
+ statbuf->st_atime = statbuf->st_mtime = statbuf->st_ctime =
+ _file_time_stamp(dos_ftime);
+
+ if ( ! strcmp(ff_blk.lfn_magic,"LFN32") )
+ {
+ unsigned xtime;
+ xtime = *(unsigned *)&ff_blk.lfn_ctime;
+ if(xtime) /* May be zero if file written w/o lfn active */
+ statbuf->st_ctime = _file_time_stamp(xtime);
+ xtime = *(unsigned *)&ff_blk.lfn_atime;
+ if(xtime > dos_ftime) /* Accessed time is date only, no time */
+ statbuf->st_atime = _file_time_stamp(xtime);
+ }
+
+ if ( (statbuf->st_mode & S_IFMT) == S_IFDIR
+ && (_djstat_flags & _STAT_DIRSIZE) == 0 )
+ {
+ /* Under DOS, directory entries for subdirectories have
+ zero size. Therefore, FindFirst brings us zero size
+ when called on a directory. (Some network redirectors
+ might do a better job, thus below we also test for zero size
+ actually being returned.) If we have zero-size directory,
+ we compute here the actual directory size by reading its
+ entries, then multiply their number by 32 (the size of a
+ directory entry under DOS). This might lose in the case
+ that many files were deleted from a once huge directory,
+ because AFAIK, directories don't return unused clusters to
+ the disk pool. Still, it is a good approximation of the
+ actual directory size.
+
+ We also take this opportunity to return the number of links
+ for directories as Unix programs expect it to be: the number
+ of subdirectories, plus 2 (the directory itself and the ``.''
+ entry).
+
+ The (max) size of the root directory could also be taken from
+ the disk BIOS Parameter Block (BPB) which can be obtained
+ by calling IOCTL (INT 21/AH=44H), subfunction 0DH, minor
+ function 60H. But we will treat all directories the same,
+ even at performance cost, because it's more robust for
+ networked drives. */
+
+ size_t pathlen = strlen (pathname);
+ char lastc = pathname[pathlen - 1];
+ char *search_spec = (char *)alloca (pathlen + 10); /* need only +5 */
+ int nfiles = 0, nsubdirs = 0, done;
+ size_t extra = 0;
+ int add_extra = 0;
+
+ strcpy(search_spec, pathname);
+ if (lastc == '/')
+ strcat(search_spec, "*.*");
+ else
+ strcat(search_spec, "/*.*");
+
+ if (statbuf->st_size == 0 && _USE_LFN)
+ {
+ /* VFAT filesystems use additional directory entries to
+ store the long filenames. */
+ char fstype[40];
+
+ if ((_get_volume_info(pathname,0,0,fstype) & _FILESYS_LFN_SUPPORTED)
+ && strncmp(fstype, "FAT", 4) == 0)
+ add_extra = 1;
+ }
+
+ /* Count files and subdirectories. */
+ for (done = __findfirst(search_spec, &ff_blk, ALL_FILES);
+ !done;
+ done = __findnext(&ff_blk))
+ {
+ register char *fname = ff_blk.ff_name;
+
+ /* Don't count "." and ".." entries. This will show empty
+ directories as size 0. */
+ if (! (fname[0] == '.'
+ && (fname[1] == '\0'
+ || (fname[1] == '.'
+ && fname[2] == '\0'))))
+ {
+ char fn[13];
+
+ nfiles++;
+ if (ff_blk.ff_attrib & 0x10)
+ nsubdirs++;
+ /* For each 13 characters of the long filename, a
+ 32-byte directory entry is used. */
+ if (add_extra && strcmp(_lfn_gen_short_fname(fname, fn), fname))
+ extra += (strlen(fname) + 12) / 13;
+ }
+ }
+
+ statbuf->st_nlink = nsubdirs + 2;
+ if (statbuf->st_size == 0)
+ statbuf->st_size = (nfiles + extra) * sizeof(struct full_dirent);
+ }
+
+ return 0;
+}
+
+/* Main entry point. This is library stat() function.
+ */
+
+int
+stat(const char *path, struct stat *statbuf)
+{
+ int e = errno;
+ int pathlen;
+
+ if (!path || !statbuf)
+ {
+ errno = EFAULT;
+ return -1;
+ }
+
+ if ((pathlen = strlen (path)) >= MAX_TRUE_NAME)
+ {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+
+ /* Fail if PATH includes wildcard characters supported by FindFirst. */
+ if (memchr(path, '*', pathlen) || memchr(path, '?', pathlen))
+ {
+ errno = ENOENT; /* since no such filename is possible */
+ return -1;
+ }
+
+ if (stat_assist(path, statbuf) == -1)
+ {
+ return -1; /* errno set by stat_assist() */
+ }
+ else
+ {
+ errno = e;
+ return 0;
+ }
+}
+
+#ifdef TEST
+
+unsigned short _djstat_flags = 0;
+
+void
+main(int argc, char *argv[])
+{
+ struct stat stat_buf;
+ char *endp;
+
+ if (argc < 2)
+ {
+ fprintf (stderr, "Usage: %s <_djstat_flags> <file...>\n", argv[0]);
+ exit(0);
+ }
+
+ if (stat(*argv, &stat_buf) != 0)
+ perror ("stat failed on argv[0]");
+ else
+ fprintf(stderr, "DOS %d.%d (%s)\n", _osmajor, _osminor, _os_flavor);
+ argc--; argv++;
+
+ _djstat_flags = (unsigned short)strtoul(*argv, &endp, 0);
+ argc--; argv++;
+
+ while (argc--)
+ {
+ if (!stat(*argv, &stat_buf))
+ {
+ fprintf(stderr, "%s: %d %6u %o %d %d %ld %lu %s", *argv,
+ stat_buf.st_dev,
+ (unsigned)stat_buf.st_ino,
+ stat_buf.st_mode,
+ stat_buf.st_nlink,
+ stat_buf.st_uid,
+ (long)stat_buf.st_size,
+ (unsigned long)stat_buf.st_mtime,
+ ctime(&stat_buf.st_mtime));
+ _djstat_describe_lossage(stderr);
+ }
+ else
+ {
+ fprintf(stderr, "%s: lossage", *argv);
+ perror(" ");
+ _djstat_describe_lossage(stderr);
+ }
+
+ ++argv;
+ }
+
+ exit (0);
+}
+
+#endif
+
diff --git a/Build/extra/djgpp/xstat.h b/Build/extra/djgpp/xstat.h
new file mode 100644
index 00000000000..5e10bb8ca1f
--- /dev/null
+++ b/Build/extra/djgpp/xstat.h
@@ -0,0 +1,71 @@
+/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
+/*
+ * Header for internal stat()/fstat() assist functions.
+ *
+ */
+
+#ifndef __XSTAT_H
+#define __XSTAT_H
+
+#include <stdio.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dpmi.h>
+
+/* Some errno.h headers do not define EFAULT. Here the value is
+ taken from POSIX IEEE 1003.1. */
+#include <errno.h>
+#ifndef EFAULT
+#define EFAULT 14
+#endif
+
+/* Under MS-DOS, file access permissions are shared by all, except for
+ Write permission. */
+#define READ_ACCESS (S_IRUSR | S_IRGRP | S_IROTH)
+#define WRITE_ACCESS S_IWUSR
+#define EXEC_ACCESS (S_IXUSR | S_IXGRP | S_IXOTH)
+
+/* Macro to convert a segment and an offset to a "far offset" suitable
+ for _farxxx() functions of DJGPP. */
+#ifndef MK_FOFF
+#define MK_FOFF(s,o) ((int)((((unsigned long)(s)) << 4) + (unsigned short)(o)))
+#endif
+
+#define MAX_TRUE_NAME FILENAME_MAX
+
+extern unsigned short _osmajor, _osminor;
+extern const char * _os_flavor;
+
+/* Bits to flag f?stat() failed to use individual undocumented features. */
+#define _STFAIL_SDA 1 /* Get SDA call failed */
+#define _STFAIL_OSVER 2 /* Unsupported DOS version */
+#define _STFAIL_BADSDA 4 /* Bad pointer to SDA */
+#define _STFAIL_TRUENAME 8 /* _truename() failed */
+#define _STFAIL_HASH 0x10 /* inode defaults to hashing */
+#define _STFAIL_LABEL 0x20 /* Root dir, but no volume label */
+#define _STFAIL_DCOUNT 0x40 /* dirent_count ridiculously large */
+#define _STFAIL_WRITEBIT 0x80 /* fstat() failed to get write access bit */
+#define _STFAIL_DEVNO 0x100 /* fstat() failed to get device number */
+#define _STFAIL_BADSFT 0x200 /* SFT entry found, but can't be trusted */
+#define _STFAIL_SFTIDX 0x400 /* bad SFT index in JFT */
+#define _STFAIL_SFTNF 0x800 /* file entry not found in SFT array */
+
+extern unsigned short _djstat_fail_bits;
+
+extern unsigned short _djstat_flags;
+
+extern time_t _file_time_stamp(unsigned int);
+extern ino_t _invent_inode(const char *, unsigned, unsigned long);
+extern unsigned short _get_magic(const char *, int);
+extern unsigned short _get_dos_version(int);
+extern char * _truename(const char *, char *);
+extern int _is_remote_drive(int);
+extern int _is_executable(const char *, int, const char *);
+extern short _get_dev_info(int);
+extern long __filelength(int);
+extern int _is_remote_handle(int);
+extern void _djstat_describe_lossage(FILE *);
+extern int _getftime(int, unsigned int *);
+
+#endif /* __XSTAT_H */