summaryrefslogtreecommitdiffstats
path: root/contrib/diff
diff options
context:
space:
mode:
authordelphij <delphij@FreeBSD.org>2007-06-15 07:06:13 +0000
committerdelphij <delphij@FreeBSD.org>2007-06-15 07:06:13 +0000
commit40ec4fdc9a74bfdb83f13672acdb88af5c91ab46 (patch)
treefa574500c8a91fba34c02a5fbe177ac9ef1890ea /contrib/diff
parentf75ef5d3d4da5cc670cb41c22a97279e60c6cb0c (diff)
downloadFreeBSD-src-40ec4fdc9a74bfdb83f13672acdb88af5c91ab46.zip
FreeBSD-src-40ec4fdc9a74bfdb83f13672acdb88af5c91ab46.tar.gz
Virgin import of diffutils 2.8.7.
Diffstat (limited to 'contrib/diff')
-rw-r--r--contrib/diff/ABOUT-NLS768
-rw-r--r--contrib/diff/AUTHORS112
-rw-r--r--contrib/diff/COPYING11
-rw-r--r--contrib/diff/ChangeLog2142
-rw-r--r--contrib/diff/Makefile.am23
-rw-r--r--contrib/diff/NEWS124
-rw-r--r--contrib/diff/README70
-rw-r--r--contrib/diff/THANKS22
-rw-r--r--contrib/diff/TODO1
-rwxr-xr-xcontrib/diff/bootstrap180
-rw-r--r--contrib/diff/doc/Makefile.am24
-rw-r--r--contrib/diff/doc/diagmeet.note71
-rw-r--r--contrib/diff/doc/diff.texi4649
-rw-r--r--contrib/diff/doc/fdl.texi452
-rw-r--r--contrib/diff/doc/stamp-vti4
-rw-r--r--contrib/diff/doc/version.texi4
-rwxr-xr-xcontrib/diff/exgettext115
-rw-r--r--contrib/diff/lib/Makefile.am35
-rw-r--r--contrib/diff/lib/alloca.c489
-rw-r--r--contrib/diff/lib/alloca_.h68
-rw-r--r--contrib/diff/lib/basename.c79
-rw-r--r--contrib/diff/lib/c-stack.c311
-rw-r--r--contrib/diff/lib/c-stack.h19
-rw-r--r--contrib/diff/lib/cmpbuf.c147
-rw-r--r--contrib/diff/lib/cmpbuf.h21
-rw-r--r--contrib/diff/lib/dirname.c119
-rw-r--r--contrib/diff/lib/dirname.h43
-rw-r--r--contrib/diff/lib/error.c310
-rw-r--r--contrib/diff/lib/error.h66
-rw-r--r--contrib/diff/lib/exclude.c263
-rw-r--r--contrib/diff/lib/exclude.h43
-rw-r--r--contrib/diff/lib/exit.h32
-rw-r--r--contrib/diff/lib/exitfail.c27
-rw-r--r--contrib/diff/lib/exitfail.h20
-rw-r--r--contrib/diff/lib/file-type.c75
-rw-r--r--contrib/diff/lib/file-type.h166
-rw-r--r--contrib/diff/lib/fnmatch.c403
-rw-r--r--contrib/diff/lib/fnmatch_.h63
-rw-r--r--contrib/diff/lib/fnmatch_loop.c1192
-rw-r--r--contrib/diff/lib/getopt.c1254
-rw-r--r--contrib/diff/lib/getopt.h176
-rw-r--r--contrib/diff/lib/getopt1.c191
-rw-r--r--contrib/diff/lib/getopt_int.h129
-rw-r--r--contrib/diff/lib/gettext.h68
-rw-r--r--contrib/diff/lib/gettimeofday.c121
-rw-r--r--contrib/diff/lib/gnulib.mk90
-rw-r--r--contrib/diff/lib/hard-locale.c74
-rw-r--r--contrib/diff/lib/hard-locale.h24
-rw-r--r--contrib/diff/lib/imaxtostr.c3
-rw-r--r--contrib/diff/lib/inttostr.c49
-rw-r--r--contrib/diff/lib/inttostr.h47
-rw-r--r--contrib/diff/lib/malloc.c36
-rw-r--r--contrib/diff/lib/mkstemp.c42
-rw-r--r--contrib/diff/lib/offtostr.c3
-rw-r--r--contrib/diff/lib/posixver.c59
-rw-r--r--contrib/diff/lib/posixver.h1
-rw-r--r--contrib/diff/lib/prepargs.c93
-rw-r--r--contrib/diff/lib/prepargs.h3
-rw-r--r--contrib/diff/lib/quotesys.c125
-rw-r--r--contrib/diff/lib/quotesys.h9
-rw-r--r--contrib/diff/lib/realloc.c39
-rw-r--r--contrib/diff/lib/regex.c8298
-rw-r--r--contrib/diff/lib/regex.h556
-rw-r--r--contrib/diff/lib/setmode.c67
-rw-r--r--contrib/diff/lib/setmode.h27
-rw-r--r--contrib/diff/lib/stdbool_.h93
-rw-r--r--contrib/diff/lib/strcase.h35
-rw-r--r--contrib/diff/lib/strcasecmp.c66
-rw-r--r--contrib/diff/lib/strftime.c1330
-rw-r--r--contrib/diff/lib/stripslash.c39
-rw-r--r--contrib/diff/lib/strncasecmp.c2
-rw-r--r--contrib/diff/lib/strtoimax.c80
-rw-r--r--contrib/diff/lib/strtol.c432
-rw-r--r--contrib/diff/lib/strtoll.c33
-rw-r--r--contrib/diff/lib/strtoul.c20
-rw-r--r--contrib/diff/lib/strtoull.c27
-rw-r--r--contrib/diff/lib/strtoumax.c2
-rw-r--r--contrib/diff/lib/tempname.c344
-rw-r--r--contrib/diff/lib/time_r.c69
-rw-r--r--contrib/diff/lib/time_r.h46
-rw-r--r--contrib/diff/lib/umaxtostr.c3
-rw-r--r--contrib/diff/lib/unlocked-io.h132
-rw-r--r--contrib/diff/lib/version-etc.c176
-rw-r--r--contrib/diff/lib/version-etc.h37
-rw-r--r--contrib/diff/lib/waitpid.c72
-rw-r--r--contrib/diff/lib/xalloc.h87
-rw-r--r--contrib/diff/lib/xmalloc.c255
-rw-r--r--contrib/diff/lib/xstrdup.c33
-rw-r--r--contrib/diff/lib/xstrtol.c295
-rw-r--r--contrib/diff/lib/xstrtol.h91
-rw-r--r--contrib/diff/lib/xstrtoul.c6
-rw-r--r--contrib/diff/lib/xstrtoumax.c37
-rw-r--r--contrib/diff/man/Makefile.am34
-rw-r--r--contrib/diff/man/cmp.163
-rw-r--r--contrib/diff/man/diff.1227
-rw-r--r--contrib/diff/man/diff3.178
-rw-r--r--contrib/diff/man/sdiff.190
-rw-r--r--contrib/diff/src/Makefile.am44
-rw-r--r--contrib/diff/src/analyze.c1038
-rw-r--r--contrib/diff/src/cmp.c677
-rw-r--r--contrib/diff/src/context.c478
-rw-r--r--contrib/diff/src/diff.c1353
-rw-r--r--contrib/diff/src/diff.h375
-rw-r--r--contrib/diff/src/diff3.c1744
-rw-r--r--contrib/diff/src/dir.c288
-rw-r--r--contrib/diff/src/ed.c169
-rw-r--r--contrib/diff/src/ifdef.c430
-rw-r--r--contrib/diff/src/io.c859
-rw-r--r--contrib/diff/src/normal.c71
-rw-r--r--contrib/diff/src/sdiff.c1225
-rw-r--r--contrib/diff/src/side.c281
-rw-r--r--contrib/diff/src/system.h326
-rw-r--r--contrib/diff/src/util.c775
113 files changed, 38786 insertions, 28 deletions
diff --git a/contrib/diff/ABOUT-NLS b/contrib/diff/ABOUT-NLS
new file mode 100644
index 0000000..2f50c66
--- /dev/null
+++ b/contrib/diff/ABOUT-NLS
@@ -0,0 +1,768 @@
+Notes on the Free Translation Project
+*************************************
+
+Free software is going international! The Free Translation Project is
+a way to get maintainers of free software, translators, and users all
+together, so that will gradually become able to speak many languages.
+A few packages already provide translations for their messages.
+
+ If you found this `ABOUT-NLS' file inside a distribution, you may
+assume that the distributed package does use GNU `gettext' internally,
+itself available at your nearest GNU archive site. But you do _not_
+need to install GNU `gettext' prior to configuring, installing or using
+this package with messages translated.
+
+ Installers will find here some useful hints. These notes also
+explain how users should proceed for getting the programs to use the
+available translations. They tell how people wanting to contribute and
+work at translations should contact the appropriate team.
+
+ When reporting bugs in the `intl/' directory or bugs which may be
+related to internationalization, you should tell about the version of
+`gettext' which is used. The information can be found in the
+`intl/VERSION' file, in internationalized packages.
+
+Quick configuration advice
+==========================
+
+If you want to exploit the full power of internationalization, you
+should configure it using
+
+ ./configure --with-included-gettext
+
+to force usage of internationalizing routines provided within this
+package, despite the existence of internationalizing capabilities in the
+operating system where this package is being installed. So far, only
+the `gettext' implementation in the GNU C library version 2 provides as
+many features (such as locale alias, message inheritance, automatic
+charset conversion or plural form handling) as the implementation here.
+It is also not possible to offer this additional functionality on top
+of a `catgets' implementation. Future versions of GNU `gettext' will
+very likely convey even more functionality. So it might be a good idea
+to change to GNU `gettext' as soon as possible.
+
+ So you need _not_ provide this option if you are using GNU libc 2 or
+you have installed a recent copy of the GNU gettext package with the
+included `libintl'.
+
+INSTALL Matters
+===============
+
+Some packages are "localizable" when properly installed; the programs
+they contain can be made to speak your own native language. Most such
+packages use GNU `gettext'. Other packages have their own ways to
+internationalization, predating GNU `gettext'.
+
+ By default, this package will be installed to allow translation of
+messages. It will automatically detect whether the system already
+provides the GNU `gettext' functions. If not, the GNU `gettext' own
+library will be used. This library is wholly contained within this
+package, usually in the `intl/' subdirectory, so prior installation of
+the GNU `gettext' package is _not_ required. Installers may use
+special options at configuration time for changing the default
+behaviour. The commands:
+
+ ./configure --with-included-gettext
+ ./configure --disable-nls
+
+will respectively bypass any pre-existing `gettext' to use the
+internationalizing routines provided within this package, or else,
+_totally_ disable translation of messages.
+
+ When you already have GNU `gettext' installed on your system and run
+configure without an option for your new package, `configure' will
+probably detect the previously built and installed `libintl.a' file and
+will decide to use this. This might be not what is desirable. You
+should use the more recent version of the GNU `gettext' library. I.e.
+if the file `intl/VERSION' shows that the library which comes with this
+package is more recent, you should use
+
+ ./configure --with-included-gettext
+
+to prevent auto-detection.
+
+ The configuration process will not test for the `catgets' function
+and therefore it will not be used. The reason is that even an
+emulation of `gettext' on top of `catgets' could not provide all the
+extensions of the GNU `gettext' library.
+
+ Internationalized packages have usually many `po/LL.po' files, where
+LL gives an ISO 639 two-letter code identifying the language. Unless
+translations have been forbidden at `configure' time by using the
+`--disable-nls' switch, all available translations are installed
+together with the package. However, the environment variable `LINGUAS'
+may be set, prior to configuration, to limit the installed set.
+`LINGUAS' should then contain a space separated list of two-letter
+codes, stating which languages are allowed.
+
+Using This Package
+==================
+
+As a user, if your language has been installed for this package, you
+only have to set the `LANG' environment variable to the appropriate
+`LL_CC' combination. Here `LL' is an ISO 639 two-letter language code,
+and `CC' is an ISO 3166 two-letter country code. For example, let's
+suppose that you speak German and live in Germany. At the shell
+prompt, merely execute `setenv LANG de_DE' (in `csh'),
+`export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash').
+This can be done from your `.login' or `.profile' file, once and for
+all.
+
+ You might think that the country code specification is redundant.
+But in fact, some languages have dialects in different countries. For
+example, `de_AT' is used for Austria, and `pt_BR' for Brazil. The
+country code serves to distinguish the dialects.
+
+ The locale naming convention of `LL_CC', with `LL' denoting the
+language and `CC' denoting the country, is the one use on systems based
+on GNU libc. On other systems, some variations of this scheme are
+used, such as `LL' or `LL_CC.ENCODING'. You can get the list of
+locales supported by your system for your country by running the command
+`locale -a | grep '^LL''.
+
+ Not all programs have translations for all languages. By default, an
+English message is shown in place of a nonexistent translation. If you
+understand other languages, you can set up a priority list of languages.
+This is done through a different environment variable, called
+`LANGUAGE'. GNU `gettext' gives preference to `LANGUAGE' over `LANG'
+for the purpose of message handling, but you still need to have `LANG'
+set to the primary language; this is required by other parts of the
+system libraries. For example, some Swedish users who would rather
+read translations in German than English for when Swedish is not
+available, set `LANGUAGE' to `sv:de' while leaving `LANG' to `sv_SE'.
+
+ Special advice for Norwegian users: The language code for Norwegian
+bokma*l changed from `no' to `nb' recently (in 2003). During the
+transition period, while some message catalogs for this language are
+installed under `nb' and some older ones under `no', it's recommended
+for Norwegian users to set `LANGUAGE' to `nb:no' so that both newer and
+older translations are used.
+
+ In the `LANGUAGE' environment variable, but not in the `LANG'
+environment variable, `LL_CC' combinations can be abbreviated as `LL'
+to denote the language's main dialect. For example, `de' is equivalent
+to `de_DE' (German as spoken in Germany), and `pt' to `pt_PT'
+(Portuguese as spoken in Portugal) in this context.
+
+Translating Teams
+=================
+
+For the Free Translation Project to be a success, we need interested
+people who like their own language and write it well, and who are also
+able to synergize with other translators speaking the same language.
+Each translation team has its own mailing list. The up-to-date list of
+teams can be found at the Free Translation Project's homepage,
+`http://www.iro.umontreal.ca/contrib/po/HTML/', in the "National teams"
+area.
+
+ If you'd like to volunteer to _work_ at translating messages, you
+should become a member of the translating team for your own language.
+The subscribing address is _not_ the same as the list itself, it has
+`-request' appended. For example, speakers of Swedish can send a
+message to `sv-request@li.org', having this message body:
+
+ subscribe
+
+ Keep in mind that team members are expected to participate
+_actively_ in translations, or at solving translational difficulties,
+rather than merely lurking around. If your team does not exist yet and
+you want to start one, or if you are unsure about what to do or how to
+get started, please write to `translation@iro.umontreal.ca' to reach the
+coordinator for all translator teams.
+
+ The English team is special. It works at improving and uniformizing
+the terminology in use. Proven linguistic skill are praised more than
+programming skill, here.
+
+Available Packages
+==================
+
+Languages are not equally supported in all packages. The following
+matrix shows the current state of internationalization, as of January
+2004. The matrix shows, in regard of each package, for which languages
+PO files have been submitted to translation coordination, with a
+translation percentage of at least 50%.
+
+ Ready PO files af am ar az be bg bs ca cs da de el en en_GB eo es
+ +----------------------------------------------------+
+ a2ps | [] [] [] [] |
+ aegis | () |
+ ant-phone | () |
+ anubis | |
+ ap-utils | |
+ aspell | [] |
+ bash | [] [] [] [] |
+ batchelor | |
+ bfd | [] [] |
+ binutils | [] [] |
+ bison | [] [] [] |
+ bluez-pin | [] [] [] |
+ clisp | |
+ clisp | [] [] [] |
+ console-tools | [] [] |
+ coreutils | [] [] [] [] |
+ cpio | [] [] [] |
+ darkstat | [] () [] |
+ diffutils | [] [] [] [] [] [] [] |
+ e2fsprogs | [] [] [] |
+ enscript | [] [] [] [] |
+ error | [] [] [] [] [] |
+ fetchmail | [] () [] [] [] [] |
+ fileutils | [] [] [] |
+ findutils | [] [] [] [] [] [] [] |
+ flex | [] [] [] [] |
+ fslint | |
+ gas | [] |
+ gawk | [] [] [] [] |
+ gbiff | [] |
+ gcal | [] |
+ gcc | [] [] |
+ gettext | [] [] [] [] [] |
+ gettext-examples | [] [] [] [] |
+ gettext-runtime | [] [] [] [] [] |
+ gettext-tools | [] [] [] |
+ gimp-print | [] [] [] [] [] |
+ gliv | |
+ glunarclock | [] [] |
+ gnubiff | [] |
+ gnucash | [] () [] [] |
+ gnucash-glossary | [] () [] |
+ gnupg | [] () [] [] [] [] |
+ gpe-aerial | [] |
+ gpe-beam | [] [] |
+ gpe-calendar | [] [] |
+ gpe-clock | [] [] |
+ gpe-conf | [] [] |
+ gpe-contacts | [] [] |
+ gpe-edit | [] |
+ gpe-go | [] |
+ gpe-login | [] [] |
+ gpe-ownerinfo | [] [] |
+ gpe-sketchbook | [] [] |
+ gpe-su | [] [] |
+ gpe-taskmanager | [] [] |
+ gpe-timesheet | [] |
+ gpe-today | [] [] |
+ gpe-todo | [] [] |
+ gphoto2 | [] [] [] [] |
+ gprof | [] [] [] |
+ gpsdrive | () () () |
+ gramadoir | [] |
+ grep | [] [] [] [] [] [] |
+ gretl | [] |
+ gtick | [] () |
+ hello | [] [] [] [] [] [] |
+ id-utils | [] [] |
+ indent | [] [] [] [] |
+ iso_3166 | [] [] [] [] [] [] [] [] [] [] |
+ iso_3166_1 | [] [] [] [] [] [] |
+ iso_3166_2 | |
+ iso_3166_3 | [] |
+ iso_4217 | [] [] [] [] |
+ iso_639 | |
+ jpilot | [] [] [] |
+ jtag | |
+ jwhois | [] |
+ kbd | [] [] [] [] [] |
+ latrine | () |
+ ld | [] [] |
+ libc | [] [] [] [] [] [] |
+ libgpewidget | [] [] |
+ libiconv | [] [] [] [] [] |
+ lifelines | [] () |
+ lilypond | [] |
+ lingoteach | |
+ lingoteach_lessons | () () |
+ lynx | [] [] [] [] |
+ m4 | [] [] [] [] |
+ mailutils | [] [] |
+ make | [] [] [] |
+ man-db | [] () [] [] () |
+ minicom | [] [] [] |
+ mysecretdiary | [] [] [] |
+ nano | [] () [] [] [] |
+ nano_1_0 | [] () [] [] [] |
+ opcodes | [] |
+ parted | [] [] [] [] [] |
+ ptx | [] [] [] [] [] |
+ python | |
+ radius | [] |
+ recode | [] [] [] [] [] [] [] |
+ rpm | [] [] |
+ screem | |
+ scrollkeeper | [] [] [] [] [] [] |
+ sed | [] [] [] [] [] [] |
+ sh-utils | [] [] [] |
+ shared-mime-info | |
+ sharutils | [] [] [] [] [] [] |
+ silky | () |
+ skencil | [] () [] |
+ sketch | [] () [] |
+ soundtracker | [] [] [] |
+ sp | [] |
+ tar | [] [] [] [] |
+ texinfo | [] [] [] |
+ textutils | [] [] [] [] |
+ tin | () () |
+ tp-robot | |
+ tuxpaint | [] [] [] [] [] [] [] |
+ unicode-han-tra... | |
+ unicode-transla... | |
+ util-linux | [] [] [] [] [] |
+ vorbis-tools | [] [] [] [] |
+ wastesedge | () |
+ wdiff | [] [] [] [] |
+ wget | [] [] [] [] [] [] |
+ xchat | [] [] [] [] |
+ xfree86_xkb_xml | [] [] |
+ xpad | [] |
+ +----------------------------------------------------+
+ af am ar az be bg bs ca cs da de el en en_GB eo es
+ 4 0 0 1 9 4 1 40 41 60 78 17 1 5 13 68
+
+ et eu fa fi fr ga gl he hr hu id is it ja ko lg
+ +-------------------------------------------------+
+ a2ps | [] [] [] () () |
+ aegis | |
+ ant-phone | [] |
+ anubis | [] |
+ ap-utils | [] |
+ aspell | [] [] |
+ bash | [] [] |
+ batchelor | [] [] |
+ bfd | [] |
+ binutils | [] [] |
+ bison | [] [] [] [] |
+ bluez-pin | [] [] [] [] [] |
+ clisp | |
+ clisp | [] |
+ console-tools | |
+ coreutils | [] [] [] [] [] [] |
+ cpio | [] [] [] [] |
+ darkstat | () [] [] [] |
+ diffutils | [] [] [] [] [] [] [] |
+ e2fsprogs | |
+ enscript | [] [] |
+ error | [] [] [] [] |
+ fetchmail | [] |
+ fileutils | [] [] [] [] [] [] |
+ findutils | [] [] [] [] [] [] [] [] [] [] [] |
+ flex | [] [] [] |
+ fslint | [] |
+ gas | [] |
+ gawk | [] [] [] |
+ gbiff | [] |
+ gcal | [] |
+ gcc | [] |
+ gettext | [] [] [] |
+ gettext-examples | [] [] |
+ gettext-runtime | [] [] [] [] [] |
+ gettext-tools | [] [] [] |
+ gimp-print | [] [] |
+ gliv | () |
+ glunarclock | [] [] [] [] |
+ gnubiff | [] |
+ gnucash | () [] |
+ gnucash-glossary | [] |
+ gnupg | [] [] [] [] [] [] [] |
+ gpe-aerial | [] |
+ gpe-beam | [] |
+ gpe-calendar | [] [] [] |
+ gpe-clock | [] |
+ gpe-conf | [] |
+ gpe-contacts | [] [] |
+ gpe-edit | [] [] |
+ gpe-go | [] |
+ gpe-login | [] [] |
+ gpe-ownerinfo | [] [] [] |
+ gpe-sketchbook | [] |
+ gpe-su | [] |
+ gpe-taskmanager | [] |
+ gpe-timesheet | [] [] [] |
+ gpe-today | [] [] |
+ gpe-todo | [] [] |
+ gphoto2 | [] [] [] |
+ gprof | [] [] |
+ gpsdrive | () () () |
+ gramadoir | [] [] |
+ grep | [] [] [] [] [] [] [] [] [] [] [] |
+ gretl | [] [] |
+ gtick | [] [] [] |
+ hello | [] [] [] [] [] [] [] [] [] [] [] [] [] |
+ id-utils | [] [] [] [] |
+ indent | [] [] [] [] [] [] [] [] [] |
+ iso_3166 | [] [] [] [] [] [] [] |
+ iso_3166_1 | [] [] [] [] [] |
+ iso_3166_2 | |
+ iso_3166_3 | |
+ iso_4217 | [] [] [] [] [] [] |
+ iso_639 | |
+ jpilot | [] () |
+ jtag | [] |
+ jwhois | [] [] [] [] |
+ kbd | [] |
+ latrine | [] |
+ ld | [] |
+ libc | [] [] [] [] [] [] |
+ libgpewidget | [] [] [] [] |
+ libiconv | [] [] [] [] [] [] [] [] [] |
+ lifelines | () |
+ lilypond | [] |
+ lingoteach | [] [] |
+ lingoteach_lessons | |
+ lynx | [] [] [] [] |
+ m4 | [] [] [] [] |
+ mailutils | |
+ make | [] [] [] [] [] [] |
+ man-db | () () |
+ minicom | [] [] [] [] |
+ mysecretdiary | [] [] |
+ nano | [] [] [] [] |
+ nano_1_0 | [] [] [] [] |
+ opcodes | [] |
+ parted | [] [] [] |
+ ptx | [] [] [] [] [] [] [] |
+ python | |
+ radius | [] |
+ recode | [] [] [] [] [] [] |
+ rpm | [] [] |
+ screem | |
+ scrollkeeper | [] |
+ sed | [] [] [] [] [] [] [] [] [] |
+ sh-utils | [] [] [] [] [] [] [] |
+ shared-mime-info | [] [] [] |
+ sharutils | [] [] [] [] [] |
+ silky | () [] () () |
+ skencil | [] |
+ sketch | [] |
+ soundtracker | [] [] |
+ sp | [] () |
+ tar | [] [] [] [] [] [] [] [] [] |
+ texinfo | [] [] [] [] |
+ textutils | [] [] [] [] [] [] |
+ tin | [] () |
+ tp-robot | [] |
+ tuxpaint | [] [] [] [] [] [] [] [] [] |
+ unicode-han-tra... | |
+ unicode-transla... | [] [] |
+ util-linux | [] [] [] [] () [] |
+ vorbis-tools | [] |
+ wastesedge | () |
+ wdiff | [] [] [] [] [] [] |
+ wget | [] [] [] [] [] [] [] |
+ xchat | [] [] [] |
+ xfree86_xkb_xml | [] [] |
+ xpad | [] [] |
+ +-------------------------------------------------+
+ et eu fa fi fr ga gl he hr hu id is it ja ko lg
+ 22 2 1 26 106 28 24 8 10 41 33 1 26 33 12 0
+
+ lt lv mk mn ms mt nb nl nn no nso pl pt pt_BR ro ru
+ +-----------------------------------------------------+
+ a2ps | [] [] () () [] [] [] |
+ aegis | () () () |
+ ant-phone | [] [] |
+ anubis | [] [] [] [] [] [] |
+ ap-utils | [] () [] |
+ aspell | [] |
+ bash | [] [] [] |
+ batchelor | [] |
+ bfd | [] |
+ binutils | [] |
+ bison | [] [] [] [] [] |
+ bluez-pin | [] [] [] |
+ clisp | |
+ clisp | [] |
+ console-tools | [] |
+ coreutils | [] [] |
+ cpio | [] [] [] [] [] |
+ darkstat | [] [] [] [] |
+ diffutils | [] [] [] [] [] [] |
+ e2fsprogs | [] |
+ enscript | [] [] [] [] |
+ error | [] [] [] |
+ fetchmail | [] [] () [] |
+ fileutils | [] [] [] |
+ findutils | [] [] [] [] [] |
+ flex | [] [] [] [] |
+ fslint | [] [] |
+ gas | |
+ gawk | [] [] [] |
+ gbiff | [] [] |
+ gcal | |
+ gcc | |
+ gettext | [] [] [] |
+ gettext-examples | [] [] [] |
+ gettext-runtime | [] [] [] [] |
+ gettext-tools | [] [] |
+ gimp-print | [] |
+ gliv | [] [] [] |
+ glunarclock | [] [] [] [] |
+ gnubiff | [] |
+ gnucash | [] [] () [] |
+ gnucash-glossary | [] [] |
+ gnupg | [] |
+ gpe-aerial | [] [] [] [] |
+ gpe-beam | [] [] [] [] |
+ gpe-calendar | [] [] [] [] |
+ gpe-clock | [] [] [] [] |
+ gpe-conf | [] [] [] [] |
+ gpe-contacts | [] [] [] [] |
+ gpe-edit | [] [] [] [] |
+ gpe-go | [] [] [] |
+ gpe-login | [] [] [] [] |
+ gpe-ownerinfo | [] [] [] [] |
+ gpe-sketchbook | [] [] [] [] |
+ gpe-su | [] [] [] [] |
+ gpe-taskmanager | [] [] [] [] |
+ gpe-timesheet | [] [] [] [] |
+ gpe-today | [] [] [] [] |
+ gpe-todo | [] [] [] [] |
+ gphoto2 | [] |
+ gprof | [] [] |
+ gpsdrive | () () [] |
+ gramadoir | () [] |
+ grep | [] [] [] [] [] |
+ gretl | |
+ gtick | [] [] [] |
+ hello | [] [] [] [] [] [] [] [] [] [] |
+ id-utils | [] [] [] [] |
+ indent | [] [] [] [] |
+ iso_3166 | [] [] [] |
+ iso_3166_1 | [] [] |
+ iso_3166_2 | |
+ iso_3166_3 | [] |
+ iso_4217 | [] [] [] [] [] [] [] [] |
+ iso_639 | [] |
+ jpilot | () () |
+ jtag | |
+ jwhois | [] [] [] [] () |
+ kbd | [] [] [] |
+ latrine | [] |
+ ld | |
+ libc | [] [] [] [] |
+ libgpewidget | [] [] [] |
+ libiconv | [] [] [] [] [] |
+ lifelines | |
+ lilypond | |
+ lingoteach | |
+ lingoteach_lessons | |
+ lynx | [] [] [] |
+ m4 | [] [] [] [] [] |
+ mailutils | [] [] [] |
+ make | [] [] [] [] |
+ man-db | [] |
+ minicom | [] [] [] [] |
+ mysecretdiary | [] [] [] |
+ nano | [] [] [] [] [] |
+ nano_1_0 | [] [] [] [] [] [] |
+ opcodes | [] [] |
+ parted | [] [] [] [] |
+ ptx | [] [] [] [] [] [] [] [] |
+ python | |
+ radius | [] [] |
+ recode | [] [] [] [] |
+ rpm | [] [] [] |
+ screem | |
+ scrollkeeper | [] [] [] [] [] |
+ sed | [] [] [] |
+ sh-utils | [] [] |
+ shared-mime-info | [] [] |
+ sharutils | [] [] |
+ silky | () |
+ skencil | [] [] |
+ sketch | [] [] |
+ soundtracker | |
+ sp | |
+ tar | [] [] [] [] [] [] |
+ texinfo | [] [] [] [] |
+ textutils | [] [] |
+ tin | |
+ tp-robot | [] |
+ tuxpaint | [] [] [] [] [] [] [] [] |
+ unicode-han-tra... | |
+ unicode-transla... | |
+ util-linux | [] [] [] |
+ vorbis-tools | [] [] [] |
+ wastesedge | |
+ wdiff | [] [] [] [] [] |
+ wget | [] [] [] |
+ xchat | [] [] [] |
+ xfree86_xkb_xml | [] [] |
+ xpad | [] [] |
+ +-----------------------------------------------------+
+ lt lv mk mn ms mt nb nl nn no nso pl pt pt_BR ro ru
+ 1 2 0 3 12 0 10 69 6 7 1 40 26 36 76 63
+
+ sk sl sr sv ta th tr uk ven vi wa xh zh_CN zh_TW zu
+ +-----------------------------------------------------+
+ a2ps | [] [] [] [] | 16
+ aegis | | 0
+ ant-phone | | 3
+ anubis | [] [] | 9
+ ap-utils | () | 3
+ aspell | | 4
+ bash | | 9
+ batchelor | | 3
+ bfd | [] [] | 6
+ binutils | [] [] [] | 8
+ bison | [] [] | 14
+ bluez-pin | [] [] [] | 14
+ clisp | | 0
+ clisp | | 5
+ console-tools | | 3
+ coreutils | [] [] [] [] | 16
+ cpio | [] [] | 14
+ darkstat | [] [] [] () () | 12
+ diffutils | [] [] [] | 23
+ e2fsprogs | [] [] | 6
+ enscript | [] [] | 12
+ error | [] [] [] | 15
+ fetchmail | [] [] | 11
+ fileutils | [] [] [] [] [] | 17
+ findutils | [] [] [] [] [] [] | 29
+ flex | [] [] | 13
+ fslint | | 3
+ gas | [] | 3
+ gawk | [] [] | 12
+ gbiff | | 4
+ gcal | [] [] | 4
+ gcc | [] | 4
+ gettext | [] [] [] [] [] | 16
+ gettext-examples | [] [] [] [] [] | 14
+ gettext-runtime | [] [] [] [] [] [] [] [] | 22
+ gettext-tools | [] [] [] [] [] [] | 14
+ gimp-print | [] [] | 10
+ gliv | | 3
+ glunarclock | [] [] [] | 13
+ gnubiff | | 3
+ gnucash | [] [] | 9
+ gnucash-glossary | [] [] [] | 8
+ gnupg | [] [] [] [] | 17
+ gpe-aerial | [] | 7
+ gpe-beam | [] | 8
+ gpe-calendar | [] [] [] [] | 13
+ gpe-clock | [] [] [] | 10
+ gpe-conf | [] [] | 9
+ gpe-contacts | [] [] [] | 11
+ gpe-edit | [] [] [] [] [] | 12
+ gpe-go | | 5
+ gpe-login | [] [] [] [] [] | 13
+ gpe-ownerinfo | [] [] [] [] | 13
+ gpe-sketchbook | [] [] | 9
+ gpe-su | [] [] [] | 10
+ gpe-taskmanager | [] [] [] | 10
+ gpe-timesheet | [] [] [] [] | 12
+ gpe-today | [] [] [] [] [] | 13
+ gpe-todo | [] [] [] [] | 12
+ gphoto2 | [] [] [] | 11
+ gprof | [] [] | 9
+ gpsdrive | [] [] | 3
+ gramadoir | [] | 5
+ grep | [] [] [] [] | 26
+ gretl | | 3
+ gtick | | 7
+ hello | [] [] [] [] [] | 34
+ id-utils | [] [] | 12
+ indent | [] [] [] [] | 21
+ iso_3166 | [] [] [] [] [] [] [] | 27
+ iso_3166_1 | [] [] [] | 16
+ iso_3166_2 | | 0
+ iso_3166_3 | | 2
+ iso_4217 | [] [] [] [] [] [] | 24
+ iso_639 | | 1
+ jpilot | [] [] [] [] [] | 9
+ jtag | [] | 2
+ jwhois | () [] [] | 11
+ kbd | [] [] | 11
+ latrine | | 2
+ ld | [] [] | 5
+ libc | [] [] [] [] | 20
+ libgpewidget | [] [] [] [] | 13
+ libiconv | [] [] [] [] [] [] [] [] | 27
+ lifelines | [] | 2
+ lilypond | [] | 3
+ lingoteach | | 2
+ lingoteach_lessons | () | 0
+ lynx | [] [] [] | 14
+ m4 | [] [] | 15
+ mailutils | | 5
+ make | [] [] [] | 16
+ man-db | [] | 5
+ minicom | | 11
+ mysecretdiary | [] [] | 10
+ nano | [] [] [] [] | 17
+ nano_1_0 | [] [] [] | 17
+ opcodes | [] [] | 6
+ parted | [] [] [] | 15
+ ptx | [] [] | 22
+ python | | 0
+ radius | | 4
+ recode | [] [] [] | 20
+ rpm | [] [] | 9
+ screem | [] [] | 2
+ scrollkeeper | [] [] [] | 15
+ sed | [] [] [] [] [] [] | 24
+ sh-utils | [] [] | 14
+ shared-mime-info | [] [] | 7
+ sharutils | [] [] [] [] | 17
+ silky | () | 3
+ skencil | [] | 6
+ sketch | [] | 6
+ soundtracker | [] [] | 7
+ sp | [] | 3
+ tar | [] [] [] [] [] | 24
+ texinfo | [] [] [] | 14
+ textutils | [] [] [] [] | 16
+ tin | | 1
+ tp-robot | | 2
+ tuxpaint | [] [] [] [] [] | 29
+ unicode-han-tra... | | 0
+ unicode-transla... | | 2
+ util-linux | [] [] | 15
+ vorbis-tools | | 8
+ wastesedge | | 0
+ wdiff | [] [] [] | 18
+ wget | [] [] [] [] [] [] [] [] | 24
+ xchat | [] [] [] [] [] | 15
+ xfree86_xkb_xml | [] [] [] [] [] | 11
+ xpad | | 5
+ +-----------------------------------------------------+
+ 63 teams sk sl sr sv ta th tr uk ven vi wa xh zh_CN zh_TW zu
+ 131 domains 47 19 28 83 0 0 59 13 1 1 11 0 22 22 0 1373
+
+ Some counters in the preceding matrix are higher than the number of
+visible blocks let us expect. This is because a few extra PO files are
+used for implementing regional variants of languages, or language
+dialects.
+
+ For a PO file in the matrix above to be effective, the package to
+which it applies should also have been internationalized and
+distributed as such by its maintainer. There might be an observable
+lag between the mere existence a PO file and its wide availability in a
+distribution.
+
+ If January 2004 seems to be old, you may fetch a more recent copy of
+this `ABOUT-NLS' file on most GNU archive sites. The most up-to-date
+matrix with full percentage details can be found at
+`http://www.iro.umontreal.ca/contrib/po/HTML/matrix.html'.
+
+Using `gettext' in new packages
+===============================
+
+If you are writing a freely available program and want to
+internationalize it you are welcome to use GNU `gettext' in your
+package. Of course you have to respect the GNU Library General Public
+License which covers the use of the GNU `gettext' library. This means
+in particular that even non-free programs can use `libintl' as a shared
+library, whereas only free software can use `libintl' as a static
+library or use modified versions of `libintl'.
+
+ Once the sources are changed appropriately and the setup can handle
+the use of `gettext' the only thing missing are the translations. The
+Free Translation Project is also available for packages which are not
+developed inside the GNU project. Therefore the information given above
+applies also for every other Free Software Project. Contact
+`translation@iro.umontreal.ca' to make the `.pot' files available to
+the translation teams.
+
diff --git a/contrib/diff/AUTHORS b/contrib/diff/AUTHORS
new file mode 100644
index 0000000..f5f0e90
--- /dev/null
+++ b/contrib/diff/AUTHORS
@@ -0,0 +1,112 @@
+Authors of GNU diffutils.
+
+ Copyright 2001 Free Software Foundation, Inc.
+
+ This file is part of GNU diffutils.
+
+ GNU diffutils 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.
+
+ GNU diffutils 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 GNU diffutils; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+The following contributions warranted legal paper exchanges with the
+Free Software Foundation. Also see files ChangeLog and THANKS.
+
+DIFFUTILS Leonard H. Tower Jr. US 1949 1987-03-09
+Assigns diff (diff.c, initial version).
+
+DIFFUTILS Torbjorn Granlund Sweden 1961 1988-01-11
+Assigns cmp.
+tege@matematik.su.se
+
+DIFFUTILS Mike Haertel US 1967 1988-09-16
+Assigns changes to diff.
+
+DIFFUTILS David S. Hayes US ? 1988-01-12
+Assigns changes to diff.
+
+DIFFUTILS Randall Smith US 1964 1988-09-21
+Assigns diff3.
+
+DIFFUTILS Richard Stallman US 1953 1988-01-15
+Assigns changes to GNU Diff.
+
+DIFFUTILS F. Thomas May US 1965 1989-08-22
+Assigns changes to diff (for -D).
+
+DIFFUTILS Optimal Solutions, Inc. 1989-08-14
+Disclaims changes by Thomas May to diff.
+
+DIFFUTILS Wayne Davison 1990-09-10
+Disclaims changes to diff.
+
+DIFFUTILS Digital Research Inc. 1990-09-13
+Disclaims changes by Wayne Davison to diff.
+
+DIFFUTILS Paul Eggert 1990-03-16
+Disclaims changes to diff.
+eggert@twinsun.com
+
+DIFFUTILS Paul Eggert 1990-08-14
+Disclaims changes to GNU Diff.
+eggert@twinsun.com
+
+DIFFUTILS Twin Sun Inc. 1990-03-16
+Disclaims changes to GNU Diff by Paul Eggert.
+
+DIFFUTILS Twin Sun Inc. 1990-08-14
+Disclaims changes to GNU Diff by Paul Eggert.
+
+DIFFUTILS Chip Rosenthal US 1959 1990-03-06
+Assigns changes to diff.
+chip@chinacat.Unicom.COM
+
+DIFFUTILS Unicom Systems Development 1990-03-06
+Disclaims changes by Chip Rosenthal to diff.
+
+GCC DIFFUTILS Paul Eggert and Twin Sun Inc. 1992-03-11
+Disclaims changes by Paul Eggert to gcc and diff.
+eggert@twinsun.com
+
+DIFF Wayne Davison 1993-06-20
+Disclaims diffcvt.c.
+
+DIFFUTILS Francois Pinard Canada 1949 1993-01-15
+Assigns wdiff and future changes submitted to the FSF.
+pinard@iro.umontreal.ca
+
+DIFFUTILS Patrick D'Cruze Australia 1971 1994-11-10
+Assigns changes (makefile.in, analyze.c, cmp.c, error.c, diff.c,
+diff3.c, getopt.c, getopt1.c, regex.c, sdiff.c, util.c, xmalloc.c;
+new file: language.++)
+
+DIFFUTILS Paul R. Eggert US 1954 1997-04-07
+Assigns past and future changes.
+eggert@twinsun.com
+
+DIFFUTILS Paul R. Eggert US 1954 1997-04-07
+Assigns past and future changes to manual.
+eggert@twinsun.com
+
+ANY DIFFUTILS GNATS Cyclic Software 1997-11-11
+Assigns past and future works (work for hire by Tim Pierce (diffutils) and
+Abe Feldman (GNATS)).
+kingdon@cyclic.com
+
+WEBPAGES Gregory B. Harvey Canada 1976 1998-02-14
+Assigns web pages describing GNU Diffutils and future changes.
+
+DIFFUTILS Olga Nikulin Russia 1965 2001-01-11
+Assigns changes to diff. (diffutils-2.7.2/analyze.c, context.c, diff.[ch],
+ed.c, ifdef.c, io.c, normal.c, side.c, util.c)
+onikulin@yahoo.com
diff --git a/contrib/diff/COPYING b/contrib/diff/COPYING
index a43ea21..d60c31a 100644
--- a/contrib/diff/COPYING
+++ b/contrib/diff/COPYING
@@ -2,7 +2,7 @@
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 675 Mass Ave, Cambridge, MA 02139, USA
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@@ -279,7 +279,7 @@ POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
- Appendix: How to Apply These Terms to Your New Programs
+ How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
@@ -291,7 +291,7 @@ 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 program's name and a brief idea of what it does.>
- Copyright (C) 19yy <name of author>
+ Copyright (C) <year> <name of author>
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
@@ -305,14 +305,15 @@ the "copyright" line and a pointer to where the full notice is found.
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.
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
- Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
diff --git a/contrib/diff/ChangeLog b/contrib/diff/ChangeLog
index 6cfc779..291919d 100644
--- a/contrib/diff/ChangeLog
+++ b/contrib/diff/ChangeLog
@@ -1,3 +1,2100 @@
+2004-04-13 Paul Eggert <eggert@twinsun.com>
+
+ * NEWS, configure.ac (AC_INIT): Version 2.8.7.
+ * configure.ac (AM_GNU_GETTEXT_VERSION): Add.
+ (XGETTEXT): Restore from pre-2004-04-12 version. This fixes
+ a bug that lost many msgids in doc/diffutils.pot.
+ * bootstrap: New file.
+ * exgettext: Don't generate a temporary file, as this runs afoul
+ of "make distcheck" which operates with read-only directories.
+ * Makefile.am (EXTRA_DIST): Add bootstrap.
+ Remove config/config.rpath as it is deduced automatically these days.
+
+2004-04-12 Paul Eggert <eggert@twinsun.com>
+
+ * NEWS, configure.ac (AC_INIT): Version 2.8.6.
+
+ * NEWS: Add news for 2.8.4, 2.8.6.
+
+ * README: Move copyright notice to end. Defer to "configure
+ --help" for special "configure" options. Suggest latest libiconv.
+ Update version numbers of Autoconf etc. to current.
+
+ * configure.ac: Quote various arguments better.
+ (AC_CONFIG_MACRO_DIR): Add call, specifying "m4".
+ (AC_CONFIG_HEADER): Replaces AM_CONFIG_HEADER.
+ (gl_USE_SYSTEM_EXTENSIONS): Replaces AC_GNU_SOURCE.
+ (AC_ISC_POSIX): Remove; nobody ports to ancient ISC any more.
+ (AC_PROG_CPP, AC_PROG_INSTALL, AC_C_INLINE,
+ AC_HEADER_STDBOOL, AC_HEADER_STDC, AM_GNU_GETTEXT, XGETTEXT,
+ AC_HEADER_STAT, AC_FUNC_VPRINTF, jm_FUNC_GLIBC_UNLOCKED_IO,
+ jm_FUNC_GNU_STRFTIME, jm_FUNC_MALLOC, jm_FUNC_REALLOC,
+ jm_PREREQ_C_STACK, jm_PREREQ_ERROR, jm_PREREQ_HARD_LOCALE,
+ jm_PREREQ_QUOTEARG, jm_PREREQ_REGEX, AC_FUNC_FNMATCH_GNU, jm_AC_DOS):
+ Remove; not needed here, as our files don't use them directly
+ or we rely on gnulib modules.
+ (AC_C_CONST): Remove; we assume C89 now.
+ (AC_CHECK_HEADERS): Remove libintl.h, limits.h, stdlib.h, string.h,
+ time.h.
+ (AC_CHECK_TYPE): Remove ptrdiff_t, ssize_t.
+ (AC_CHECK_FUNCS): Remove diraccess, strchr, strerror, tmpnam).
+ (AC_REPLACE_FUNCS): Remove memchr, mkstemp, strcasecmp.
+ (GNULIB_AUTOCONF_SNIPPET): Add call. This replaces much of
+ the above.
+ (AC_CONFIG_FILES): Remove lib/posix/Makefile.
+ (AC_CONFIG_COMMANDS): Remove.
+
+ * doc/diff.texi (dircategory): Change to "Text creation and
+ manipulation" from "GNU packages".
+ (Translations): New node.
+ (Overview): Improve quality of algorithm citations.
+ (Binary): -q doesn't exactly cause diff to assume files are binary.
+ (Normal): Place after Side by Side, since it's less important.
+ (Detailed Context, Detailed Unified, Detailed ed,
+ Detailed if-then-else, diff3 Hunks, Detailed diff3 Normal):
+ Place at end of menu.
+ (Detailed Unified): Mention that fractional timestamps are
+ omitted on hosts that don't support them.
+ Mention what happens when hunks contain just one line.
+ (Line Group Formats, Reject Names): Fix duplicate-word typos.
+ (Comparing Directories): Trailing white space and empty lines are
+ ignored in the -X file.
+ (diff Options): Add --strip-trailing-cr.
+ (Projects): gnu -> gvc@gnu.org.
+
+ * lib/Makefile.am (SUBDIRS): Remove.
+ (EXTRA_DIST, noinst_HEADERS): Remove most entries.
+ (libdiffutils_a_SOURCES): Now just lib_SOURCES.
+ (lib_SOURCES): New macro.
+ (DISTCLEANFILES, MOSTLYCLEANFILES): Set to empty now.
+ (gnulib.mk): Include: this does most of the work eliminated
+ by the above changes.
+
+ * lib/inttostr.c (inttostr): Protect i < 0 by compile-time
+ test intended to suppress compiler warnings.
+ * lib/inttostr.h: Include limits.h unilaterally.
+ (CHAR_BIT): Remove.
+ (PARAMS): Remove; all uses changed.
+ * lib/setmode.c (__attribute__): New macro.
+ (set_binary_mode): Define only if HAVE_SETMODE_DOS.
+ Otherwise define a dummy static char, as C89 requires
+ that we define something.
+ * lib/setmode.h (set_binary_mode): Return true, not 1.
+
+ * src/analyze.c, src/context.c, src/diff.c, src/io.c, src/util.c:
+ Do not include regex.h, as diff.h does this now.
+
+ * src/cmp.c: Sort includes. Include <exit.h>, <unlocked-io.h>.
+ (specify_comparison_type): Don't report an error if the comparison
+ type has already been specified the same way as this one.
+
+ * src/cmp.c (usage): Mention exit status.
+ * src/diff.c (option_help_msgid): Likewise.
+ * src/diff3.c (usage): Likewise.
+ * src/sdiff.c (usage): Likewise.
+
+ * src/cmp.c (main): Adjust to latest gnulib c_stack_action
+ calling conventions.
+ * src/diff.c (main): Likewise.
+ * src/diff3.c (main): Likewise.
+ * src/sdiff.c (main): Likewise.
+
+ * src/cmp.c (main): Adjust to latest version_etc calling conventions.
+ * src/diff.c (main): Likewise.
+ * src/diff3.c (main): Likewise.
+ * src/sdiff.c (main): Likewise.
+
+ * src/diff.c: Include <exit.h>.
+ (binary): Define to true if not declared.
+ (longopts): Set tabsize flag to 1.
+ (main): Don't output nanoseconds if platform lacks them.
+ Don't treat files as binary if !binary.
+ (set_mtime_to_now): Use 0, not NULL.
+ (compare_files): Mark files as nonexistent if it looks like
+ 'patch' created inaccessible regular empty files to denote
+ nonexistent backups. Don't compare such files.
+ Clear st_* members of status of nonexistent file.
+ Remove now-unnecessary tests.
+
+ * src/diff.h: Include regex.h, unlocked-io.h.
+ (struct file_data.changed): Now char *, not bool *, to save
+ space on hosts where bool takes more space than char.
+ All uses changed.
+
+ * src/diff3.c: Include unlocked-io.h.
+ (strip_trailing_cr): New var.
+ (STRIP_TRAILING_CR_OPTION): New enum.
+ (longopts, main, option_help_msgid, read_diff):
+ Add --strip-trailing-cr support.
+ (read_diff): Exit with status 126 (not 127) if errno != ENOENT
+ after failed execvp in child. Report this in parent.
+
+ * src/dir.c: Include <strcase.h>.
+ (failed_locale_specific_sorting): Renamed from failed_strcoll.
+ All uses changed.
+ (compare_names): Don't invoke strcasecmp first thing when
+ ignore_file_name_case; if locale_specific_sorting, we should
+ just use that.
+
+ * src/ifdef.c (next_line): Remove; replace with...
+ (next_line0, next_line1): New vars.
+ (print_ifdef_script, print_ifdef_hunk):
+ Use them to fix line-number computation bug.
+
+ * src/io.c (find_and_hash_each_line): Don't convert char *
+ to unsigned char *; just leave pointers as char *. This
+ lessens the number of potentially-dangerous casts.
+ * src/util.c (lines_differ): Likewise.
+
+ * src/sdiff.c: Include <unlocked-io.h>, <exit.h>.
+ (check_child_status): Renamed from ck_editor_status, and
+ accept a new arg MAX_OK_STATUS. All callers changed.
+ Handle status 126/127 as per POSIX.
+ (edit): Likewise.
+ (main): Likewise. Fix getopt typo: -E wasn't supported.
+
+ * src/system.h (S_IRWXU, S_IRWXG, S_IRWXO): Define if not defined.
+ (S_IXUSR, S_IXGRP, S_IXOTH): Remove.
+ Include <time.h> unconditionally, since we can assume C89 now.
+ Likewise for <stdlib.h>, <string.h>.
+ (getenv, EXIT_SUCCESS, EXIT_FAILURE, SSIZE_MAX, strchr, strrchr,
+ memcmp, memcpy): Remove decl; no longer needed.
+ (strcasecoll, strcasecmp): Define if not built in.
+ (CTYPE_DOMAIN, ISPRINT, ISSPACE, TOLOWER, _tolower, errno): Remove;
+ we now assume C89 or better. All uses changed.
+ Include <stdbool.h> unconditionally now, since gnulib supports it
+ if the C compiler doesn't. All boolean uses of 0 and 1 now
+ changed to false and true.
+ (lin_is_printable_as_long_int): Renamed from lin_is_printable_as_long.
+
+ * src/util.c (begin_output): Fix bug: 0 wasn't cast to char * arg,
+ which led to undefined behavior on 64-bit hosts.
+ Use more-standard test for exit status 126 versus 127.
+ (finish_output): Likewise.
+ (analyze_hunk): Do not cast bool to int.
+
+2004-03-15 Paul Eggert <eggert@twinsun.com>
+
+ * src/cmp.c (main): Don't consider two files with the same name to
+ be the same, if their initial skip values differ. This fixes a
+ bug reported by Hideki Iwamoto in
+ <http://mail.gnu.org/archive/html/bug-gnu-utils/2004-03/msg00024.html>.
+
+2004-03-11 Paul Eggert <eggert@twinsun.com>
+
+ * src/analyze.c (diag): Return void, not lin, since the return
+ value wasn't needed. All callers changed.
+ (diag, diff_2_files):
+ Use 'true' and 'false' instead of '1' and '0', when appropriate.
+ (compareseq): Use lin const * local variables instead of lin *.
+ Don't bother checking diag's return value.
+ (shift_boundaries, build_reverse_script, build_script, diff_2_files):
+ Use char arrays, not bool arrays, since
+ sizeof (bool) might be greater than 1.
+
+2004-02-09 Paul Eggert <eggert@twinsun.com>
+
+ * m4/setmode.m4 (AC_FUNC_SETMODE_DOS): AC_LIBOBJ(setmode) if
+ we would return true.
+
+2002-10-14 Paul Eggert <eggert@twinsun.com>
+
+ * src/Makefile.am (diff3.$(OBJEXT), diff.$(OBJEXT),
+ sdiff.$(OBJEXT)): Rename from (misspelled) diff3.$(OBJECT),
+ diff.$(OBJECT), sdiff.$(OBJECT). Patch by Paul D. Smith in
+ <http://mail.gnu.org/pipermail/bug-gnu-utils/2002-October/003251.html>.
+ Bug reported by Chris Bainbridge.
+
+2002-10-13 Paul Eggert <eggert@twinsun.com>
+
+ * src/Makefile.am (MOSTLYCLEANFILES): Add paths.ht.
+ (paths.h): Send output to paths.ht first, and then rename to
+ paths.h at the end. This avoids problems if the disk is full.
+ It also works around what appears to be a bug with GNU make -j
+ (3.79.1); see <http://bugs.gentoo.org/show_bug.cgi?id=8934>.
+
+2002-06-27 Paul Eggert <eggert@twinsun.com>
+
+ * NEWS, configure.ac (AC_INIT): Version 2.8.4.
+
+ * config/config.sub: Sync with latest version maintained in other
+ packages.
+
+ * lib/file-type.h: Protect against double inclusion. Detect
+ whether <sys/stat.h> has been included. Fix from Jim Meyering.
+
+ * src/analyze.c (briefly_report): Don't say "Binary files differ",
+ since one of the files may not be a binary file.
+ Bug reported by Dan Jacobson.
+
+2002-06-22 Paul Eggert <eggert@twinsun.com>
+
+ * lib/c-stack.c (segv_handler, c_stack_action) [! defined
+ SA_SIGINFO]: Do not assume SA_SIGINFO behavior.
+ Bug reported by Jim Meyering on NetBSD 1.5.2.
+
+2002-06-16 Paul Eggert <eggert@twinsun.com>
+
+ * NEWS, configure.ac (AC_INIT): Version 2.8.3.
+
+ * config/depcomp, config/missing, README: Update to automake 1.6.2.
+
+ * po/LINGUAS: Add en_US.
+ * po/en_US.po: New file.
+ * po/POTFILES.in: Remove lib/freesoft.c.
+ Add lib/file-type.c, lib/version-etc.c, lib/xmalloc.c.
+
+2002-06-15 Paul Eggert <eggert@twinsun.com>
+
+ * doc/diff.texi (Special Files): Document behavior of symlink
+ loops.
+
+ * lib/Makefile.am (noinst_HEADERS): Remove freesoft.h.
+ Add version-etc.h.
+ (libdiffutils_a_SOURCES): Remove freesoft.c. Add version-etc.c.
+ * lib/freesoft.c, lib/freesoft.h: Remove.
+ * lib/version-etc.h (PARAMS): Remove; we now assume C89 at least.
+
+ * lib/version-etc.h (version_etc): Remove package and version args.
+ (version_etc_copyright): Remove.
+ * lib/version-etc.c: Likewise.
+ Do not include unlocked-io.h; no longer needed.
+ Include gettext.h rather than libinto.h.
+ (_): Define unconditionally.
+ (version_etc): Adjust wording to match current GNU coding standards.
+ Translate "(C)" if possible.
+
+ * lib/version-etc.c, lib/version-etc.h: New files, taken from
+ fileutils.
+
+ * src/Makefile.am (cmp_SOURCES, diff3_SOURCES, sdiff_SOURCES,
+ diff_SOURCES): Remove version.c.
+ (MAINTAINERCLEANFILES, $(srcdir)/version.c): Remove.
+
+ * src/cmp.c: Include version-etc.h, not freesoft.h.
+ (copyright_notice): Remove.
+ (main): Use version_etc to print version.
+ * src/diff.c, src/diff3.c, src/sdiff.c: Likewise.
+
+ * src/cmp.c (version_string): Remove decl.
+ * src/diff.h, src/diff3.c, src/sdiff.c: Likewise.
+
+2002-06-11 Paul Eggert <eggert@twinsun.com>
+
+ * lib/fnmatch.c, lib/fnmatch_loop.c (WIDE_CHAR_SUPPORT):
+ New macro. Use it uniformly instead of
+ (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H).
+ It also uses HAVE_BTOWC, to fix a porting bug on Solaris 2.5.1
+ reported by Vin Shelton.
+ * m4/fnmatch.m4 (_AC_LIBOBJ_FNMATCH): Check for btowc.
+
+ * NEWS, configure.ac (AC_INIT): Version 2.8.2.
+
+ * ABOUT-NLS, config/config.guess, config/config.sub,
+ config/depcomp, config/texinfo.tex, lib/posix/regex.h,
+ m4/c-bs-a.m4, m4/gettext.m4, m4/gnu-source.m4, m4/lib-link.m4,
+ m4/malloc.m4:
+ Update to recent version (maintained in other packages).
+ * m4/prereq.m4 (jm_PREREQ_EXCLUSIVE): AC_FUNC_FNMATCH_GNU
+ no longer takes a lib.
+
+ * README: Incorporate contents from INSTALLME.
+ * INSTALLME: Remove.
+ * Makefile.am (EXTRA_DIST): Remove INSTALLME.
+
+ * configure.ac (AC_GNU_SOURCE): Move up, so that it affects
+ later compilations properly.
+ (DEFAULT_DIFF_PROGRAM, AC_TYPE_SIGNAL): Remove.
+ (jm_AC_TYPE_INTMAX_T): Add.
+ (AC_FUNC_FNMATCH_GNU): Use this, instead of AC_FUNC_FNMATCH.
+ (AC_CONFIG_LINKS): regex.hin renamed from regex_.h.
+
+ * doc/diff.texi: Reword "@option{-f} and @option{--foo}" to
+ "@option{-f} or @option{--foo}".
+ Use @acronym instead of @sc where appropriate.
+ (Specified Lines): Renamed from Specified Folding.
+ (Comparison, Blank Lines):
+ Clarify wordings for Blank Lines and Specified Lines nodes.
+ (Binary): Mention --verbose and --print-bytes.
+ (Tabs, sdiff Option Summary, diff Options):
+ New option --tabsize=COLUMNS.
+
+ * lib/Makefile.am (EXTRA_DIST): Add fnmatch_loop.c.
+ (noinst_HEADERS): fnmatch_.h renamed from fnmatch.hin.
+ regex_.h renamed from regex.hin.
+ Add file-type.h.
+ (libdiffutils_a_SOURCES): Add file-type.c.
+ (DISTCLEANFILES): Remove fnmatch.hno, regex.hno.
+
+ * lib/c-stack.c (__attribute__): New macro.
+ (EOVERFLOW): Define if not defined.
+ (stack_t): Define to struct sigaltstack if not defined or declared.
+ Include <sys/resource.h>, <ucontext.h> if available.
+ Include <stdio.h> if DEBUG.
+ Do not include <inttypes.h> or <stdint.h>.
+ (c_stack_die): Remove info and context args. All uses changed.
+ (segv_action): Likewise.
+ (alternate_signal_stack): Change uintmax_t to long, to ease porting.
+ (get_stack_location, min_address_from_argv, max_address_from_argv,
+ null_action): New functions.
+ (stack_base, stack_size): New vars.
+ (segv_handler): context arg may not be used.
+ Use global stack_base, stack_size if
+ ! HAVE_XSI_STACK_OVERFLOW_HEURISTIC.
+ Add debug code.
+ Invoke die (rather than segv_action) to exit.
+ (c_stack_action): Accept new argv arg, and simpler handler arg.
+ All uses changed. Move code into new functions above.
+ Allow null action.
+ [! (defined SA_ONSTACK && defined _SC_PAGESIZE)]: Assume all segvs
+ are stack overflows.
+ (main) [DEBUG]: Describe what output should be like.
+
+ * lib/c-stack.h (siginfo_t, c_stack_die): Remove decl.
+
+ * lib/file-type.c, lib/file-type.h: New files. These contain code
+ that was in src/diff.c, but is now librarified and spiffed up a
+ bit. Jim Meyering suggested this.
+
+ * lib/fnmatch.c (alloca, __builtin_expect): Define for non-GCC hosts.
+ <strings.h>: Include only if HAVE_STRINGS_H.
+ <stddef.h>: Include if we include stdlib.h.
+ Do not comment out all code if ! HAVE_FNMATCH_GNU.
+ (getenv): Do not declare if HAVE_DECL_GETENV.
+ (__strchrnul, __wcschrnul): Remove; not used.
+ (MEMPCPY): Use mempcpy if not _LIBC; use memcpy if neither _LIBC
+ nor HAVE_MEMPCPY.
+ (FOLD) [HANDLE_MULTIBYTE]: Do not pass wide char to ISUPPER.
+ (STRLEN, STRCAT, MEMPCPY) [HANDLE_MULTIBYTE && !defined _LIBC]:
+ Use wcslen rather than __wcslen, and likewise for wcscat, wmempcpy.
+ (MEMPCPY) [HANDLE_MULTIBYTE]: Use wmempcpy if not _LIBC; use wmemcpy
+ if neither _LIBC nor HAVE_WMEMPCPY.
+ * lib/fnmatch_.h (__const): Do not define to empty, as this breaks
+ Sun cc. The code doesn't work with K&R anyway.
+ * lib/fnmatch_loop.c (struct patternlist.str): Size 1, not 0,
+ as C89 requires this.
+ (NEW_PATTERN): Use offsetof, not sizeof, since str now has size 1.
+ * lib/fnmatch_.h: Import from glibc fnmatch.h.
+ * lib/fnmatch.c, lib/fnmatch_loop.c: Import from glibc.
+
+ * lib/posixver.c: Include posixver.h.
+
+ * lib/regex_.h: Renamed from lib/regex.hin.
+
+ * m4/c-stack.m4 (jm_PREREQ_C_STACK): Do not AC_REQUIRE
+ jm_AC_TYPE_UINTMAX_T and do not use uintmax_t.
+ Check for sys/resource.h, uccontext.h.
+ Check for decls and existence of getcontext, sigaltstack.
+ Check for stack_t.
+
+ * m4/codeset.m4, m4/glibc21.m4, m4/lcmessage.m4: Remove.
+
+ * m4/fnmatch.m4: Update to latest Autoconf CVS for AC_FUNC_FNMATCH_GNU.
+ * m4/gnu-source.m4: Likewise, for AC_GNU_SOURCE (renamed from
+ AC__GNU_SOURCE).
+
+ * m4/mbstate_t.m4 (AC_TYPE_MBSTATE_T): Renamed from AC_MBSTATE_T.
+ All uses changed. Upgrade to recent Autoconf CVS.
+
+ * m4/stdbool.m4 (AC_HEADER_STDBOOL): Do not cast pointer to
+ bool in integer constant expression; C99 does not allow it.
+ Reported by Bruno Haible.
+
+ * po/LINGUAS: Add hu, pt_BR.
+ * po/hu.po, po/pt_BR.po: New files.
+
+ * src/Makefile.am (noinst_HEADERS): Remove diff.h.
+ (DEFS): Remove.
+ (diff_sources): Add diff.h.
+ (MOSTLYCLEANFILES): New macro.
+ (cmp.$(OBJEXT) diff3.$(OBJECT) diff.$(OBJECT) sdiff.$(OBJECT)): Depend
+ on paths.h.
+ (paths.h): New rule.
+
+ * src/analyze.c, src/cmp.c, src/diff.c, src/diff3.c, src/io.c,
+ src/sdiff.c: Include <file-type.h>.
+
+ * src/cmp.c: Include paths.h.
+ (copyright_notice): Renamed from copyright_string.
+ Now a msgid, so that copyright symbol can be translated.
+ All uses changed.
+ * src/diff.c, src/diff3.c, src/sdiff.c: Likewise.
+
+ * src/diff.c: Include posixver.h.
+ (TABSIZE_OPTION): New constant.
+ (main): Allow widths up to SIZE_MAX.
+ (filetype): Move to lib/file-type.c and rename to file_type.
+ All uses changed.
+
+ * src/diff.c (longopts, main, usage): New option --tabsize=COLUMNS.
+ * src/io.c (find_and_hash_each_line): Likewise.
+
+ * src/diff.h (TAB_WIDTH): Remove.
+ (tabsize): New decl.
+ (sdiff_half_width, sdiff_column2_offset): Now size_t rather than
+ unsigned int.
+
+ * src/diff3.c (skipwhite, readnum): New functions.
+ (process_diff_control): Use them.
+ (SKIPWHITE, READNUM): Remove.
+ (read_diff): Don't worry about errno == ENOEXEC.
+
+ * src/sdiff.c (catchsig, signal_handler, initial_action): Signal
+ handlers return void, not RETSIGTYPE, since we no longer support
+ K&R.
+ (TABSIZE_OPTION): New constant.
+ (longopts, usage, main): New option --tabsize=COLUMNS.
+ (cleanup): New arg signo. All uses changed.
+ (ck_editor_status, main, edit): Don't worry about ENOEXEC.
+
+ * src/side.c (tab_from_to, print_half_line, print_1sdiff_line):
+ New option --tabsize=COLUMNS.
+
+ * src/system.h (S_ISBLK, S_ISCHR, S_ISDIR, S_ISFIFO, S_ISREG,
+ S_ISSOCK): Remove; now in lib/file-type.h.
+
+ * src/util.c (finish_output): Check for ENOEXEC.
+ (lines_differ, output_1_line): New option --tabsize=COLUMNS.
+ (analyze_hunk): If -b or -w is also specified, -B now considers
+ lines to be empty if they contain only white space.
+
+2002-04-05 Paul Eggert <eggert@sic.twinsun.com>
+
+ * NEWS, configure.ac (AC_INIT): Version 2.8.1.
+
+ * configure.ac (AC_HEADER_STDBOOL): Add.
+ (AC_CHECK_HEADERS): Remove stdbool.h.
+ * m4/stdbool.m4: New file.
+ * m4/prereq.m4 (jm_PREREQ_EXCLUDE):
+ Use AC_HEADER_STDBOOL rather than AC_CHECK_HEADERS(stdbool.h).
+ (jm_PREREQ_HASH): Likewise.
+
+ * src/system.h (SSIZE_MAX): Define if limits.h doesn't.
+
+ * src/analyze.c (diff_2_files): Assign PTRDIFF_MAX - 1 to a
+ size_t variable, just in case there's a problem with ptrdiff_t
+ versus size_t.
+
+ * lib/cmpbuf.c (errno): Remove decl; K&R C is no longer supported.
+ Include limits.h.
+ (SIZE_MAX, SSIZE_MAX): Define if standard headers don't.
+ (MIN): New macro.
+ (block_read): Do not attempt to read more than SSIZE_MAX bytes, as the
+ resulting behavior is implementation-defined. Work around bug in
+ Tru64 5.1, which can't read more than INT_MAX bytes at a time.
+ * src/cmp.c (cmp): Use block_read instead of read, to work
+ around Tru64 5.1 bug.
+ * src/diff3.c (read_diff): Likewise.
+ * src/diff3.c: Include cmpbuf.h.
+
+ * THANKS: Add Ulrich Drepper.
+
+ * INSTALLME: Mention GNU texinfo.
+
+ * doc/diff.texi:
+ Use new @copying directive.
+ Put @contents first, not last, since Texinfo now suggests this.
+ Fix bug in -w documentation noted by Karl Berry.
+ Mention links for speedup.
+ New node "Speedups" for future speedups.
+ Just say "Index", not "Concept Index".
+
+2002-03-26 Paul Eggert <eggert@twinsun.com>
+
+ * src/Makefile.am:
+ (INCLUDES): Remove this obsolete macro, replacing it with:
+ (AM_CPPFLAGS): New macro.
+
+2002-03-26 Albert Chin-A-Young <china@thewrittenword.com>
+
+ * src/Makefile.am (datadir): Remove, as it conflicts with --datadir.
+
+2002-03-26 Paul Eggert <eggert@twinsun.com>
+
+ * doc/diff.texi (dircategory GNU packages): Fix typo: a "* " was
+ missing before the menu entry. Bug diagnosed by Adam Heath.
+ Also, put this dircategory after the Individual utilities dircategory,
+ to work around a compatibility problem with Debian install-info.
+
+2002-03-24 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * src/io.c (sip): Do not mishandle buffered count when reverting
+ to text mode.
+
+2002-03-23 Paul Eggert <eggert@twinsun.com>
+
+ * NEWS, configure.ac (AC_INIT): Version 2.8.
+ * configure.ac (AC_PREREQ): 2.53.
+ * INSTALLME: Upgrade to gettext 0.11.1 and help2man 1.27.
+
+ * doc/diff.texi: Upgrade the description of `patch' to GNU patch
+ 2.5.4, and revamp the documentation accordingly.
+
+ * src/diff.c (main): Fix typo that prevented diff -y from working.
+ Bug reported by Mitsuru Chinen.
+
+2002-03-15 Paul Eggert <eggert@twinsun.com>
+
+ * lib/c-stack.c (c_stack_die) [!HAVE_SIGINFO_T]: Don't use info.
+ Bug reported by Eli Zaretskii.
+
+2002-03-15 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * ms/config.sed: Tweak editing of install-info-am target.
+
+2002-03-12 Paul Eggert <eggert@twinsun.com>
+
+ * NEWS, configure.ac (AC_INIT): Version 2.7.10.
+
+ * NEWS: cmp -l -s and cmp -s -l are not allowed.
+ Deprecate diff -h, -H, -L, -P, --inhibit-hunk-merge.
+
+ * configure.ac (jm_PREREQ_HARD_LOCALE): Add.
+ (AM_INIT_AUTOMAKE): Do not distribute shar file.
+
+ * doc/diff.texi (Overview): byte != character.
+ (Detailed Context, Detailed Unified, Alternate Names, diff Options):
+ Do not document diff -L.
+ (Comparing Directories, Making Patches, diff Options):
+ Do not document diff -P.
+ (diff Performance, sdiff Option Summary, diff Options, sdiff Options):
+ Do not document diff -H.
+ (diff Performance, diff Options): Do not document --horizon-lines.
+ (cmp Options): Prefer -b to -c.
+ (cmp Options, diff Options, diff3 Options, patch Options,
+ sdiff Options): Put short options next to the similar long options.
+ Document --help, and use the same wording for --verbose.
+ (diff3 Options): Fix typo in description of -E, which used wrongly used
+ "-e" instead of "-E".
+
+ * lib/hard-locale.c (alloca): Remove.
+ Include stdlib.h if available, for malloc.
+ (hard_locale): Use malloc, not alloca, so that we need not worry about
+ alloca issues. Test for storage allocation failure.
+
+ * m4/prereq.m4 (jm_PREREQ): Add jm_PREREQ_HARD_LOCALE.
+ (jm_PREREQ_HARD_LOCALE): New macro.
+
+ * src/cmp.c (specify_comparison_type): New function.
+ (check_stdout): "indices and codes" -> "byte numbers and values"
+ (main): Detect clashing options.
+ (cmp): Use "byte" rather than "char" if a translation for "byte"
+ is available, even when in the POSIX locale.
+
+ * src/diff.c (option_help_msgid): Do not document -L, -P,
+ --horizon-lines, --inhibit-hunk-merge, -H.
+ * src/diff.h: -L -> --label
+
+2002-03-11 Paul Eggert <eggert@twinsun.com>
+
+ * NEWS, configure.ac (AC_INIT): Version 2.7.9.
+
+ * INSTALLME: Update to autoconf 2.53, automake 1.6, help2man
+ 1.25 with patch.
+
+ * configure.ac (AC_INIT):
+ Change package name from diff to diffutils.
+ (AM_INIT_AUTOMAKE): Use new form, with option gnits,
+ rather than old from that duplicated AC_INIT.
+ (AM_MISSING_PROG): Add help2man.
+ (REGEX_MALLOC): Define.
+ (AC_CONFIG_FILES): Add man/Makefile.
+
+ * Makefile.am (AUTOMAKE_OPTIONS): Remove.
+ * doc/Makefile.am (AUTOMAKE_OPTIONS): Remove.
+ * lib/Makefile.am (AUTOMAKE_OPTIONS): Likewise.
+ * ms/Makefile.am (AUTOMAKE_OPTIONS): Likewise.
+ * src/Makefile.am (AUTOMAKE_OPTIONS): Likewise.
+
+ * lib/c-stack.c: Include <errno.h>
+ (ENOTSUP): Define if errno.h doesn't.
+ (SA_NODEFER, SA_ONSTACK, SA_RESETHAND, SA_SIGINFO, SIGSTKSZ,
+ _SC_PAGESIZE, ALTERNATE_STACK_SIZE, stack_t, sigaltstack):
+ Remove; we now assume them all when
+ HAVE_XSI_STACK_OVERFLOW_HEURISTIC, so we don't need
+ substitutes.
+ (<ucontext.h>): Include only if HAVE_XSI_STACK_OVERFLOW_HEURISTIC.
+ (alternate_signal_stack): Now of size SIGSTKSZ.
+ (segv_handler): Simplify, under the assumption that
+ HAVE_XSI_STACK_OVERFLOW_HEURISTIC is nonzero.
+ (c_stack_action): Likewise.
+ (exit_failure) [DEBUG]: Initialize to 0, not 1.
+ (recurse, main) [DEBUG]: Remove main args.
+
+ * m4/c-stack.m4 (AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC): Change
+ wording of message. Do not check for stdbool.h or ucontext.h,
+ or for ucontext_t or sigaction or sigaltstack.
+
+ * po/LINGUAS: Add zh_TW.
+
+ * Makefile.am (SUBDIRS): Add man.
+ * man/Makefile.am: New file.
+ * src/cmp.c (usage): Reword for help2man.
+ * src/diff.c (option_help_msgid): Likewise.
+ * src/diff3.c (option_help_msgid, usage): Likewise.
+ * src/sdiff3.c (option_help_msgid, usage): Likewise.
+ Reword for help2man.
+
+ * THANKS: Add email address for Tower.
+
+ * config/config.guess, config/config.sub, config/depcomp,
+ config/install-sh, config/mdate-sh, config/missing,
+ config/mkinstalldirs, config/texinfo.tex: Update
+ to recent version (maintained in other packages).
+
+2002-03-04 Bruno Haible <haible@ilog.fr>
+
+ * m4/gettext.m4 (AM_GNU_GETTEXT): Set LIBINTL and LTLIBINTL to empty if
+ no preinstalled GNU gettext was found.
+
+2002-03-02 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * ms/config.sed: Tweak editing of install-info-am and
+ uninstall-info-am targets, to include 8+3-butchered names of Info
+ files.
+
+2002-02-28 Paul Eggert <eggert@twinsun.com>
+
+ * NEWS, configure.ac (AC_INIT, AM_INIT_AUTOMAKE): Version 2.7.8.
+
+ * doc/diff.texi: Add vr index.
+ Update copyright to 2002.
+ (Standards conformance): New chapter.
+ (Binary): Differing binary files are trouble unless the user asked for
+ brief output.
+ (Detailed Context): Prefer ISO time stamp format in discussion.
+ (Detailed Unified, Pagination): Likewise.
+ (Less Context): Likewise. Also use short option.
+ (Alternate Names): Separate option from arg.
+ (Making Patches): Mention -U 2.
+ (diff Options): Deprecate -LINES, as POSIX 1003.1-2001 does not
+ allow it.
+
+ * INSTALLME: Update advice for Solaris installation problems.
+ We no longer use a test version of gettext.
+ Autoconf test version updated from 2.52f to 2.52h.
+ POSIX 1003.1-2001 patch for Automake.
+
+ * configure.ac (AC__GNU_SOURCE): Add this,
+ replacing AH_VERBATIM of _GNU_SOURCE.
+ (tempname): Use AC_LIBOBJS, not LIBOBJS=, as now required by autoconf.
+ (jm_PREREQ_C_STACK): Add.
+ (AC_CONFIG_FILES): Remove intl/Makefile.
+ (AM_GNU_GETTEXT): Add external arg, from gettext 0.11.
+
+ * lib/c-stack.c, lib/c-stack.h, lib/exitfail.c, lib/exitfail.h,
+ lib/posixver.c, lib/posixver.h, m4/c-stack.m4, m4/gnu-source.m4,
+ po/cs.po, po/ja.po: New files.
+
+ * intl/ChangeLog, intl/Makefile.in, intl/VERSION,
+ intl/bindtextdom.c, intl/config.charset, intl/dcgettext.c,
+ intl/dcigettext.c, intl/dcngettext.c, intl/dgettext.c,
+ intl/dngettext.c, intl/explodename.c, intl/finddomain.c,
+ intl/gettext.c, intl/gettextP.h, intl/gmo.h, intl/hash-string.h,
+ intl/intl-compat.c, intl/l10nflist.c, intl/libgnuintl.h,
+ intl/loadinfo.h, intl/loadmsgcat.c, intl/localcharset.c,
+ intl/locale.alias, intl/localealias.c, intl/localename.c,
+ intl/ngettext.c, intl/os2compat.c, intl/os2compat.h, intl/osdep.c,
+ intl/plural-eval.c, intl/plural-exp.c, intl/plural-exp.h,
+ intl/plural.c, intl/plural.y, intl/ref-add.sin, intl/ref-del.sin,
+ intl/textdomain.c, m4/isc-posix.m4, m4/libtool.m4: Remove.
+
+ * ABOUT-NLS: Update to Gettext 0.11.
+
+ * Makefile.am (SUBDIRS): Remove intl.
+
+ * config/config.guess, config/config.rpath, config/config.sub,
+ config/texinfo.tex, config/depcomp, config/texinfo.tex,
+ lib/tempname.c: Update to latest version from other packages.
+
+ * lib/xalloc.h (xalloc_exit_failure): Remove; subsumed by exit_failure.
+ * lib/xmalloc.c: Include exitfail.h.
+ (xalloc_exit_failure): Remove; subsumed by exit_failure.
+ All uses changed.
+
+ * lib/Makefile.am (noinst_HEADERS): Add c-stack.h, exitfail.h.
+ (libdiffutils_a_SOURCES): Add c-stack.c, exitfail.c, quotesys.c.
+ (INCLUDES): Remove.
+
+ * lib/cmpbuf.h (buffer_lcm): New arg LCM_MAX.
+ * lib/cmpbuf.c: Include errno.h.
+ (errno): Declare if !STDC_HEADERS.
+ Include signal.h.
+ (SA_RESTART): Define if not already defined.
+ Include <inttypes.h>.
+ (PTRDIFF_MAX): Define if not already defined.
+ (TYPE_SIGNED, TYPE_MINIMUM, TYPE_MAXIMUM): Likewise.
+ (block_read): Accommodate ancient AIX hosts that set errno to EINTR
+ after uncaught SIGCONT.
+ (buffer_lcm): Return a reasonable size if the multiple is too large.
+ New arg LCM_MAX. All callers changed.
+
+ * lib/hard-locale.c: Include "hard-locale.h".
+ (hard_locale): Ignore ENABLE_NLS, since we want to operate on
+ locales other than LC_MESSAGES.
+
+ * m4/prereq.m4 (jm_PREREQ): Add jm_PREREQ_POSIXVER.
+ (jm_PREREQ_POSIXVER): New macro.
+
+ * m4/setmode.m4 (AC_FUNC_SETMODE_DOS):
+ Check for fcntl.h and unistd.h unconditionally.
+ Suggested by Bruno Haible.
+
+ * po/LINGUAS: Add cs, ja.
+ * po/POTFILES.in: Add lib/c-stack.c, src/dir.c.
+
+ * src/Makefile.am (datadir): @DATADIRNAME@ -> share.
+ (INCLUDES): Remove intl.
+ (LDADD): Change INTLLIBS to LIBINTL.
+ No longer need to link libdiffutils.a twice.
+
+ * src/analyze.c (diff_2_files):
+ Avoid arithmetic overflow in buffer size calculation.
+
+ * src/cmp.c: Include c-stack.h, exitfail.h.
+ (hard_locale_LC_MESSAGES): Depend on ENABLE_NLS.
+ (try_help, check_stdout, main, cmp): 2 -> EXIT_TROUBLE.
+ (main): Check for stack overflow.
+ 0 -> EXIT_SUCCESS.
+ 1 -> EXIT_FAILURE.
+ (cmp): Likewise.
+ Accommodate ancient AIX hosts that set errno to
+ EINTR after uncaught SIGCONT.
+
+ * src/context.c (pr_context_hunk):
+ Do not dump core if an enormous context causes an
+ arithmetic overflow.
+ (pr_unidiff_hunk): Likewise.
+ (find_hunk): Likewise.
+
+ * src/diff.h: unsigned -> unsigned int.
+ * src/diff.c: Include c-stack.h, exitfail.h.
+ Do not include signal.h.
+ (specify_style, specify_value): Bring these routines back, as POSIX
+ requires that the order of options not matter.
+ (shortopts): New constant.
+ (group_format_option, line_format_option): New constants.
+ (main): 0 -> EXIT_SUCCESS, 1 -> EXIT_FAILURE, 2 -> EXIT_TROUBLE.
+ Ensure that order of options does not matter.
+ Check for stack overflow.
+ If contexts overflow, substitute LIN_MAX, as that's good enough.
+ If multiple contexts are specified, use their maximum.
+ -c is equivalent to -C 3 now, instead of having an implicit context;
+ likewise for -u and -U 3.
+ Use specify_style and specify_value.
+ (SIGCHLD): Do not define; now done in a header.
+ Use new style time stamp format for -u / -U.
+ Reject numeric-string options if operating in POSIX 1003.1-2001 mode.
+ Avoid overflow problems with tab width.
+ Simplify from-file and to-file code.
+ (usage): Do not mention obsolete options.
+ (filetype): Do not mention whether a file is executable.
+ Add typed memory objects.
+ (compare_files): 0 -> EXIT_SUCCESS, 1 -> EXIT_FAILURE, 2 ->
+ EXIT_TROUBLE.
+
+ * src/diff3.c: Include c-stack.h, exitfail.h.
+ (ALLOCATE): Remove. All uses changed to xmalloc, or to xmalloc plus
+ an overflow check.
+ (myread): Remove.
+ (main): Check for stack overflow.
+ 0 -> EXIT_SUCCESS, 1 -> EXIT_FAIULRE, 2 -> EXIT_TROUBLE.
+ (try_help): Likewise.
+ (process_diff): Check for integer overflow, to avoid core dumps.
+ 2 -> EXIT_TROUBLE.
+ (read_diff): Exit with status 126 if the file is not executable,
+ for compatibility with POSIX 1003.1-2001.
+ Accommodate ancient AIX hosts that set errno to EINTR after uncaught
+ SIGCONT.
+ Check for integer overflow to avoid core dumps.
+ (fatal, perror_with_exit): 2 -> EXIT_TROUBLE.
+
+ * src/dir.c (dir_read):
+ Ignore st_size of directories: POSIX says it's garbage.
+ Check for integer overflow to avoid core dumps.
+ (diff_dirs): 0 -> EXIT_SUCCESS, 2 -> EXIT_TROUBLE.
+
+ * src/ifdef.c: Include <xalloc.h>.
+ (format_group, print_ifdef_lines): Avoid core dumps with bad formats.
+ (do_printf_spec): Avoid alloca.
+
+ * src/io.c (sip):
+ Avoid integer overflow and core dumps if buffer alignments are
+ preposterously incompatible.
+ (slurp): Do not dump core if the file is growing as we read it.
+ If a regular file grows, keep reading until we catch up with its EOF.
+ (find_and_hash_each_line): Check for integer overflow to avoid cores.
+ (GUESS_LINES): Remove.
+ (guess_lines): New function. Avoid integer overflow.
+ (find_identical_ends): Use it.
+ Avoid integer overflow and possible core dumps.
+
+ * src/sdiff.c: Include c-stack.h, exitfail.h. Do not include signal.h.
+ 0 -> EXIT_SUCCESS, 1 -> EXIT_FAILURE, 2 -> EXIT_TROUBLE.
+ (ck_editor_status): New function.
+ (main): Check for stack overflow.
+ Adopt POSIX convention for subsidiary programs not found.
+ (diffarg): Check for integer overflow to avoid core dumps.
+ (trapsigs): Remove SA_INTERRUPT special case; now done by header.
+ (SIGCHLD): Likewise.
+ (edit): Adopt POSIX convention for subsidiary programs not found.
+
+ * src/side.c: unsigned -> unsigned int.
+
+ * src/system.h: Don't use alloca or include <alloca.h>.
+ unsigned -> unsigned int
+ (EXIT_SUCCESS, EXIT_FAILURE, EXIT_TROUBLE): Define if not defined.
+ Include signal.h.
+ (SA_RESTART): Define if not defined.
+ (SIGCHLD): Likewise.
+
+ * src/util.c: 2 -> EXIT_TROUBLE.
+ Adopt POSIX convention for ENOEXEC and exit status 126.
+ unsigned -> unsigned int
+
+2002-01-24 Paul Eggert <eggert@twinsun.com>
+
+ * NEWS, configure.ac (AC_INIT, AM_INIT_AUTOMAKE): Version 2.7.7.
+
+ * intl/plural.c: Regenerate with Bison 1.31.
+
+ * ABOUT-NLS, intl/*: Update to Gettext 0.11-pre5++.
+ * INSTALL: Update to Autoconf 2.52f.
+
+ * INSTALLME: New file.
+ * Makefile.am (EXTRA_DIST): Add config/config.rpath, INSTALLME.
+ (DISTCLEANFILES): Remove.
+ * NEWS: Reformat for imminent 2.8 release.
+ * README: Mention INSTALLME.
+ * README-alpha: Move most of contents to INSTALLME.
+ * THANKS: Add Bruno Haible, Jim Meyering, and Eli Zaretskii.
+
+ * config: New subdirectory, containing the following files from .:
+ config.guess, config.sub, depcomp, missing, install-sh, mkinstalldirs.
+ Move the following files here from doc: texinfo.tex, mdate-sh.
+ * config/config.guess, config/config.sub, config/texinfo.tex:
+ Update to latest version from FSF.
+ * config/config.rpath: New file, from Gettext 0.11-pre5++.
+
+ * configure.ac (AC_INIT): Use new 3-arg form.
+ (AC_CONFIG_SRCDIR): Specify src/diff.c here, not in AC_INIT.
+ (ALL_LINGUAS): Remove: now in po/LINGUAS as per Gettext 0.11.
+ (AC_CONFIG_AUX_DIR): New macro invocation.
+
+ * lib/Makefile.am (noinst_HEADERS): Add gettext.h.
+ * lib/gettext.h: New file, from Gettext 0.11-pre5++.
+ * lib/prepargs.c: Include <string.h>. Reported by Bruno Haible.
+
+ * m4/codeset.m4, m4/gettext.m4, glibc21.m4, iconv.m4, isc-posix.m4,
+ lcmessage.m4, progtest.m4: Upgrade to Gettext 0.11-pre5++.
+ * m4/lib-ld.m4, m4/lib-link.m4, m4/lib-prefix.m4: New files, from
+ Gettext 0.11-pre5++.
+
+ * po/LINGUAS: New file.
+ * po/Makefile.in.in: Upgrade to Gettext 0.11-pre5++.
+ * po/Makevars, po/Rules-quot, po/boldquot.sed: New files,
+ from Gettext 0.11-pre5++.
+
+ * src/cmp.c (copyright_string): Update to 2002.
+ * src/diff.c (copyright_string): Likewise.
+ * src/diff3.c (copyright_string): Likewise.
+ * src/sdiff.c (copyright_string): Likewise.
+
+ * src/cmp.c (specify_ignore_initial): Renamed from
+ parse_ignore_initial, with different signature, to take the
+ maximum of multiple options rather than the last one.
+ All uses changed.
+
+ * src/cmp.c (bytes, specify_ignore_initial, cmp): Use UINTMAX_MAX
+ instead of (uintmax_t) -1, to avoid warnings on some compilers.
+ * src/io.c (file_block_read): Likewise, for SIZE_MAX.
+
+ * src/cmp.c (usage): Reformat messages to ease translation.
+ * src/diff3.c (usage): Likewise.
+ * src/sdiff.c (usage): Likewise.
+
+ * src/cmp.c (main): Two files with the same name are identical
+ only if the same offset is specified.
+ (block_compare_and_count): Avoid cast to unsigned char.
+
+ * src/diff3.c (main): Remove unused variable.
+
+ * src/dir.c: Include <setjmp.h>
+ (struct dirdata): New member nnames.
+ (locale_specific_sorting, failed_strcoll): New vars.
+ (dir_read): Renamed from dir_sort. Don't sort the dir.
+ Set new nnames member of struct dirdata. All callers changed.
+ (compare_names): Don't check for errno after strcasecmp.
+ Use strcoll only if locale_specific_sorting is nonzero.
+ If strcoll fails, longjmp out rather than returning a value
+ that might result in an invalid comparison function that might
+ make qsort dump core.
+ (diff_dirs): Sort the directory ourselves. Use setjmp to recover
+ from strcoll failure, falling back on native byte comparison.
+ Make local variables volatile if they need to preserve their value
+ after setjmp/longjmp.
+
+ * src/sdiff.c (handler_index_of_SIGINT, handler_index_of_SIGPIPE):
+ New macros.
+ (main): Do not confuse signal numbers with their indices.
+ Bug reported by Bruno Haible.
+ (edit): Cat lin to long before printing with %ld, since lin might
+ be narrow than long.
+
+ * src/system.h (UINTMAX_MAX): New macro.
+ Include gettext.h, not libgettext.h.
+ (N_): Do not wrap arg in parentheses. Fix from Bruno Haible.
+
+ * src/util.c (finish_output): Ensure that werrno is initialized.
+ (lines_differ): Have an explicit do-nothing case for
+ IGNORE_NO_WHITE_SPACE, to pacify gcc -Wall.
+
+2001-12-29 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * src/sdiff.c (interact): After extracting rlen from the editor
+ command, test for a terminating null character, not for a newline.
+
+ * ms/config.bat: Allow longer source directory names without
+ overflowing the line length limits. Create the cache in the
+ build directory, not in the source directory
+ * ms/config.sed: Fix AC_CONFIG_LINKS for when symlinks are
+ unavailable.
+
+2001-12-23 Paul Eggert <eggert@twinsun.com>
+
+ * NEWS, configure.ac (AM_INIT_AUTOMAKE): Version 2.7.6.
+
+ * configure.ac (ALL_LINGUAS): Add tr.
+
+ * src/util.c (begin_output):
+ Have child exit with status 127 rather than reporting
+ failure on its own. Set errno to 0 before invoking popen.
+ (finish_output): Report errno on pclose failure.
+ Distinguish between subsidiary program not found, and failure.
+
+ * src/sdiff.c (not_found, execdiff): Remove.
+ (DIFF_PROGRAM_OPTION): New constant.
+ (longopts, option_help_msgid, main): Add --diff-program=PROGRAM.
+ (check_stdout): New function.
+ (main): Remove DIFF_PROGRAM. Check stdout after printing version.
+ Use check_stdout after printing help. Use execvp/perror_fatail rather
+ than execdiff. Set errno to 0 before invoking popen.
+ Check for pclose failure properly.
+ (main, edit): If child exec fails, exit with 127 rather than trying to
+ print diagnostic.
+ Distinguish between subsidiary program failing and not being found.
+ (edit): Handle signals the same way, regardless of whether we're using
+ system or fork+exec. Check for system returning -1.
+
+ * src/diff3.c (DIFF_PROGRAM_OPTION, HELP_OPTION): New constants.
+ (longopts, main): Use them.
+ (longopts, main, option_help_msgid): New option --diff-option=PROGRAM.
+ (main): Remove DIFF_PROGRAM support.
+ Check stdout after printing version.
+ (check_stdout): Report errno info if fclose fails.
+ (read_diff): Have child exit with status 127 when program is not found,
+ rather than trying to have the child report failure. Check for
+ pclose returning -1.
+
+ * src/diff.c (DEFAULT_WIDTH): Remove.
+ (main): Use 130 instead of DEFAULT_WIDTH, since it's not really
+ builder-settable. Do not prepend DIFF_OPTIONS.
+ (check-stdout): If fclose (stdout) fails, print errno info.
+ (option_help_msgid): Default context is 3, not 2.
+ (usage): Work even if ptrdiff_t is wider than int.
+
+ * doc/diff.texi (diff Options): Remove DIFF_OPTIONS.
+ (Invoking diff3, Invoking sdiff): Remove DIFF_PROGRAM.
+ (diff3 Options, sdiff Options): Add --diff-program.
+
+ * src/cmp.c (valid_suffixes):
+ Add '0', to support suffixes like "MB" and "MiB".
+ (check_stdout): Don't assume that the translations of "write failed"
+ and of "standard output" lack '%'.
+ (main): Check stdout after printing version.
+
+ * lib/setmode.c: [HAVE_FCNTL_H && HAVE_SETMODE_DOS]: Include <fcntl.h>.
+ [!HAVE_SETMODE_DOS]: Do not include <unistd.h>.
+ (set_binary_mode): Return mode (not 1) if fd is a tty.
+ Do not assume that O_TEXT is zero.
+
+ * doc/diff.texi (cmp Options):
+ In byte counts, a plain suffix (without any integer)
+ is assumed to modify the integer 1. Index terms like "kibibyte".
+ Document plain "k".
+
+ (Reporting Bugs): Mention bug-report archive and test version
+ location. Ask for "diff --version" in bug reports.
+
+2001-12-13 Paul Eggert <eggert@twinsun.com>
+
+ * src/diff.c (DEFAULT_WIDTH): Remove; couldn't be changed without
+ also changing option_help_msgid. All uses replaced with 130.
+
+ * lib/setmode.c: Include fcntl.h and unistd.h only if
+ HAVE_SETMODE_DOS.
+ (setmode): Assume a file is binary unless the mode is O_TEXT.
+ * ms/README: Fix minor typos.
+
+2001-12-13 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * ms/README: New file.
+
+ * lib/setmode.c (set_binary_mode) [HAVE_SETMODE_DOS]: Don't assume
+ O_TEXT has a zero value. If FD is a terminal device, do nothing
+ and return MODE, thus pretending that it was already in the
+ requested MODE.
+ [HAVE_FCNTL_H]: Include fcntl.h (needed for O_BINARY).
+
+ * ms/config.sed: Remove the split prevention of config.status.
+ Fix Sed commands for converting absolute file names into
+ top_srcdir-relative ones.
+
+ * ms/config.bat: Fix typos.
+
+2001-12-12 Neal H Walfield <neal@cs.uml.edu>
+
+ * diff.c (option_help_msgid): Correct the default context width
+ from 2 to 3.
+
+2001-12-11 Paul Eggert <eggert@twinsun.com>
+
+ * m4/Makefile.am.in: Remove jm-glibc-io.m4
+
+ * NEWS, configure.ac (AM_INIT_AUTOMAKE): Version 2.7.5.
+
+ * configure.ac (PR_PROGRAM): Use AC_DEFINE_UNQUOTED, so that
+ $PR_PROGRAM is expanded by sh.
+ (ptrdiff_t, ssize_t): Use AC_CHECK_TYPE with a default of int,
+ not AC_CHECK_TYPES.
+ (jm_AC_DOS, AC_FUNC_SETMODE_DOS): New macros.
+ (AC_CONFIG_FILES): Add ms/Makefile.
+
+ * doc/diff.texi: Add --no-ignore-file-name-case.
+ File name case sensitivity now affects file name exclusion.
+ Fix typos.
+
+ * src/util.c: Include dirname.h.
+ (dir_file_pathname): Use base_name rather than file_name_lastdirchar.
+
+ * src/system.h (S_IXUSR, S_IXGRP, S_IXOTH): New macros.
+ Include <libgettext.h> rather than rolling it ourselves.
+ (file_name_lastdirchar, HAVE_SETMODE, set_binary_mode): Remove.
+
+ * src/sdiff.c: Include <dirname.h>.
+ (expand_name): Use base_name rather than file_name_lastdirchar, for
+ portability to DOS.
+ (main): Initialize xalloc_exit_failure before possibly invoking
+ any memory allocator.
+
+ * src/io.c: Include setmode.h.
+
+ * src/diff3.c (main):
+ Initialize xalloc_exit_failure before possibly invoking any memory
+ allocator.
+
+ * src/diff.c: Include dirname.h, setmode.h.
+
+ (main): Later values and/or styles now silently override earlier.
+ (specify_value, specify_style): Likewise. All callers changed.
+ Remove.
+ (binary, main, option_help_msgid, compare_files):
+ HAVE_SETMODE -> HAVE_SETMODE_DOS.
+ (NO_IGNORE_FILE_NAME_CASE_OPTION): New constant.
+ (longopts, main, option_help_msgid): Support it.
+ (exclude_options): New function.
+ (main): Use it. Initialize xalloc_exit_failure before potentially
+ allocating memory.
+
+ (filetype): Distinguish executable files from others, as POSIX
+ suggests.
+
+ (compare_files): Use base_name instead of file_name_lastdirchar.
+
+ * src/cmp.c: Include <hard-locale.h>, <setmode.h>.
+ (hard_locale_LC_MESSAGES): New macro.
+ (sprintc): Remove int width arg; it's now the caller's responsibility
+ to pad. All callers changed.
+ (stat_buf): New static var; was formerly a local var in 'main'.
+ (valid_suffixes): Add 'K', for 'KiB'.
+ (option_help_msgid): Don't confuse bytes with characters.
+ (main): Set xalloc_exit_failure before invoking anything that might
+ allocate memory. Fix bug: -n was incorrectly ignored when optimizing
+ the case of regular files with different lengths.
+ (cmp): Use an index column wide enough to store this comparison's
+ indexes. In locales other than the POSIX locale, say "byte"
+ rather than "char".
+
+ * ms/config.bat: pc -> ms
+
+ * ms/Makefile.am, m4/setmode.m4, lib/setmode.c, lib/setmode.h:
+ New file.
+
+ * lib/Makefile.am (noinst_HEADERS): Add dirname.h, setmode.h.
+ (libdiffutils_a_SOURCES): Add basename.c, setmode.c.
+
+ * Makefile.am (SUBDIRS): Add ms.
+
+2001-12-10 Paul Eggert <eggert@twinsun.com>
+
+ * m4/fnmatch.m4: Test for FNM_CASEFOLD.
+
+2001-12-03 Paul Eggert <eggert@twinsun.com>
+
+ * lib/posix/regex.h: Fix copyright notice.
+
+2001-12-03 Paul Eggert <eggert@twinsun.com>
+
+ * NEWS, configure.ac (AM_INIT_AUTOMAKE): Version 2.7.4.
+
+ * diff.texi (direntry, Overview, Comparison, Binary, Invoking cmp):
+ Use "byte" rather than "character" when talking about cmp, since
+ it compares bytes, not character.
+ (Invoking cmp): New trailing operands FROM-SKIP and TO-SKIP.
+ -i or --ignore-initial now accepts FROM-SKIP:TO-SKIP.
+ New option -n or --bytes.
+ Count operands now may be in octal or hex, and may be followed by a
+ size multiplier.
+
+ * configure.ac (DEFAULT_DIFF_PROGRAM):
+ Define to "diff", not "$bindir/diff" (which didn't work anyway).
+ (AC_CHECK_MEMBERS): Add struct stat.st_blksize, struct stat.st_rdev.
+ (AC_STRUCT_ST_BLKSIZE, AC_STRUCT_ST_RDEV): Remove; obsolescent.
+ (AC_FUNC_FORK): Use this, instead of obsolescent AC_FUNC_VFORK.
+ (AC_CONFIG_FILES, AC_CONFIG_COMMANDS): Add.
+ (AC_OUTPUT): Remove args; they were obsolescent.
+
+ * util.c (setup_output, begin_output, finish_output):
+ HAVE_FORK -> HAVE_WORKING_FORK || HAVE_WORKING_VFORK.
+ * sdiff.c (diffpid, cleanup, main, edit): Likewise.
+ * diff3.c (read_diff): Likewise.
+
+ * system.h (STAT_BLOCKSIZE):
+ Use HAVE_STRUCT_STAT_ST_BLKSIZE, not HAVE_ST_BLKSIZE.
+ (vfork): New macro.
+ (HAVE_FORK): Remove.
+ (set_binary_mode): New macro.
+
+ * sdiff.c (main): HAVE_VFORK -> HAVE_WORKING_VFORK.
+ (edit): Reopen the temporary file after the editor has run, in case
+ the editor operates by unlinking the old file and linking a new one.
+ (P_tmpdir): Rename from PVT_tmpdir; this fixes a typo.
+ All uses changed.
+
+ * io.c (sip, read_files):
+ Remove tests for HAVE_SETMODE; use set_binary_mode
+ instead of setmode.
+ (sip): Fix typo in backward lseek when reverting to text mode.
+
+ * config.site, config.sed, config.bat: New file.
+
+ * Makefile.am (EXTRA_DIST): Add xstrtol.c.
+ (noinst_HEADERS): Add xstrtol.h.
+ (libdiffutils_a_SOURCES): Add xstrtoumax.c.
+
+ * cmp.c: <xstrtol.h>: Include.
+ (ignore_initial): Now an array with 2 elements. All uses changed.
+ (bytes): New var.
+ (HELP_OPTION): New constant.
+ (long_options, main): Use it.
+ (long_options, option_help_msgid, main, cmp):
+ Add support for -n or --bytes.
+ (parse_ignore_initial): New function.
+ (option_help_msgid, main): Add -i M:N.
+ (usage, main): Add two optional trailing operands, a la BSD.
+ (main): setmode -> set_binary_mode.
+ (cmp): Report byte number of what we've seen, not of the entire file.
+ This is to be consistent with the line number, which is always relative
+ with what we've seen.
+
+2001-12-02 Paul Eggert <eggert@twinsun.com>
+
+ * diff.c (main, compare_files): setmode -> set_binary_mode.
+
+ * xstrtol.c (__xstrtol): Don't accept 'Ki'; require 'KiB'.
+
+ * xstrtol.c (__xstrtol): Add support for IEC 60027-2.
+
+2001-11-25 Paul Eggert <eggert@twinsun.com>
+
+ * NEWS, configure.ac (AM_INIT_AUTOMAKE): Version 2.7.3.
+
+ * README-alpha: New file.
+
+ * src/Makefile.am (INCLUDES): Add -I../lib, for regex.h.
+
+ * configure.ac:
+ Don't set LIB_CLOCK_GETTIME to 'none required'; set it to
+ the empty string instead.
+
+ * lib/Makefile.am (EXTRA_DIST): Add strtoimax.c, strtol.c.
+
+ * Makefile.am (SUBDIRS): Put intl before lib, so that libintl.h exists.
+
+ * lib/Makefile.am (noinst_HEADERS): Add unlocked-io.h.
+
+ * configure.ac (__EXTENSIONS__): New define, for the unlocked macros.
+
+ * README: Add copyright notice.
+ Remove stuff that doesn't apply any more.
+
+ * doc/diff.texi: offsets -> indices for cmp
+
+ * src/cmp.c (option_help_msgid): offsets -> indices
+
+ * src/diff.c (option_help_msgid):
+ Don't mention --binary on POSIX hosts.
+
+ * src/sdiff.c (STRIP_TRAILING_CR_OPTION): New constant.
+ (longopts, option_help_msgid, main): Add -E, --ignore-tab-expansion,
+ --strip-trailing-cr.
+
+ * doc/diff.texi: Change direcategory from Utilities to GNU Packages.
+ Add individual utilities.
+ Switch to Free Documentation License.
+ @code -> @command
+ @samp -> @option
+ GNU -> @sc{gnu}
+ Expand tabs to spaces, except when in an example that actually
+ uses tabs.
+ Prefer @node with just one arg.
+ Document -E or --ignore-tab-expansion, --strip-trailing-cr,
+ --ignore-file-name-case.
+ Regular expressions are now grep style, not Emacs style.
+ cmp's -c or --print-chars option is now -b or --print-bytes.
+ Time stamps now depend on LC_TIME.
+ -p now implies ^[[:alpha:]$_].
+ Flags now include ' and 0.
+ cmp -i is an alias for --ignore-initial
+ Document --from-file, --to-file.
+ Document DIFF_OPTIONS.
+
+ * configure.ac (AC_CHECK_FUNCS): Add gettimeofday, clock_gettime.
+ (LIB_CLOCK_GETTIME): New subst.
+
+ * src/system.h: Assume C89 or better.
+ (_GNU_SOURCE): Remove; config.h now defines it.
+ (alloca): Declare like coreutils does it.
+ (verify, TYPE_SIGNED, TYPE_MINIMUM, TYPE_MAXIMUM, O_RDWR,
+ S_IRUSR, S_IWUSR): New macros.
+ (STAT_BLOCKSIZE): Parenthesize definiens.
+ <inttypes.h>: Include if HAVE_INTTYPES_H.
+ (CHAR_MAX, INT_MAX): Remove.
+ (PTRDIFF_MAX, SIZE_MAX): New macros.
+ (strtoumax): New decl.
+ Include stddef.h.
+ (bzero): Remove.
+ (bindtextdomain, textdomain, N_): New macros.
+ (ISPRINT, ISSPACE): Remove ifndef wrappers.
+ (ISUPPER, ISDIGIT): Remove.
+ (TOLOWER): New macro.
+ (MIN): Renamed from min; all callers changed.
+ (MAX): Likewise, from max.
+ (lin): New type.
+ (LIN_MAX): New macro.
+ (file_name_cmp): Renamed from filename_cmp. All callers changed.
+ (file_name_lastdirchar): Renamed from file_name_lastdirchar.
+ All callers changed.
+ (could_be_mvfs_stat_bug, could_be_nfs_stat_bug,
+ dev_may_have_duplicate_ino): Remove.
+ (HAVE_SETMODE, NULL_DEVICE): New macros.
+ (same_file): Do not check attributes.
+ (same_file_attributes): New macro.
+
+ * src/util.c: Assume C89 or better.
+ int -> bool for booleans.
+ int -> lin for line numbers.
+ int -> size_t for sizes.
+ Use angle-brackets when including quotesys.h.
+ Include error.h, regex.h, xalloc.h.
+ (message5): sizeof -> offsetof
+ (begin_output): Invoke pr without -f.
+ (lines_differ): Renamed from line_cmp, and return bool not 3-way int.
+ All callers changed.
+ Add support for IGNORE_TAB_EXPANSION.
+ (change_letter): Now an array rather than a function. All
+ callers changed.
+ (translate_range): Translate line numbers to long, not lin,
+ for convenience with printf.
+ (analyze_hunk): Return enum changes instead of a count of
+ inserts and deletes. All callers changed.
+ (zalloc): New function.
+
+ * src/side.c: Assume C89 or better.
+ int -> bool for booleans.
+ int -> lin for line numbers.
+
+ * src/sdiff.c: Assume C89 or better.
+ int -> bool for booleans.
+ int -> lin for line numbers.
+ Use angle-brackets when including getopt.h, quotesys.h.
+ Include error.h, freesoft.h, stdio.h, xalloc.h.
+ (copyright_string): Use only most recent year.
+ (authorship_msgid, option_help_msgid): Wrap in N_().
+
+ (tmpname): Now volatile.
+ (tmpmade): Remove.
+ (tmp): New var.
+ (private_tempnam, exists, letters): Remove.
+ (temporary_file): New function.
+ (edit): Use it.
+ (interact): Use strtoumax, not atoi.
+
+ * src/normal.c: Assume C89 or better.
+ int -> lin for line numbers.
+
+ * src/io.c: Assume C89 or better.
+ int -> bool for booleans.
+ int -> lin for line numbers.
+ int -> size_t for sizes.
+ Use angle-brackets when including cmpbuf.h.
+ Include regex.h, xalloc.h.
+ (word): Remove; now done in system.h.
+ (hash_value): New type; use it instead of 'unsigned' for hash values.
+ (file_block_read): New function.
+ (sip, slurp): Use it. Now static.
+ (sip): Ensure block size is a multiple of word size. Clear eof flag.
+ (slurp): Use xalloc_die to report memory exhaustion.
+ (find_and_hash_each_line): Use TOLOWER instead of _tolower.
+ Add support for IGNORE_TAB_EXPANSION.
+ (prepare_text_end): Strip trailing CR if requested.
+ (find_identical_ends): Prepare the text only once,
+ if they're duplicates.
+ Let the compiler take advantage more of the fact that the buffers are
+ word-aligned.
+ (primes): Remove.
+ (prime_offset): New var.
+ (read_var): Use prime_offset instead of primes.
+ Use zalloc instead of xmalloc + bzero.
+
+ * src/ifdef.c: Assume C89 or better.
+ int -> lin for line numbers.
+ (format_group): Use strtoumax to parse line numbers.
+ (format_group, print_ifdef_lines): Use do_printf_spec to
+ handle printf specs.
+ (groups_letter_value): Don't use _tolower; it's locale-dependent.
+ (do_printf_spec): Renamed from scan_printf_spec; now does the printing.
+
+ * src/ed.c: Assume C89 or better.
+ int -> lin for line numbers (or 'long' when that's more convenient).
+ (print_ed_hunk): Fix bug when handling double-dot inserts.
+
+ * src/dir.c: Assume C89 or better.
+ int -> bool for booleans.
+ Include error.h, exclude.h, xalloc.h.
+
+ (dir_sort): Return 0 on error, 1 on success. All callers changed.
+ compare_names -> compare_names_for_qsort.
+
+ (compare_names): Try strcasecmp if ignore_file_name_case. Then try
+ strcoll. Use file_name_cmp only as a last resort. Warn about
+ strcasecmp or strcoll failure.
+ (compare_names_for_qsort): New function.
+
+ (diff_dirs): Use compare_names rather than filename_cmp.
+
+ * src/diff3.c: Assume C89 or better.
+ int -> bool for booleans.
+ int -> lin for line numbers.
+ Use angle-brackets when including getopt.h, quotesys.h.
+ Include error.h, freesoft.h, inttostr.h, xalloc.h.
+ (copyright_string): Use only most recent year.
+ (authorship_msgid, option_help_msgid): Wrap in N_().
+
+ Rename the following variables for consistency with user-visible
+ option spellings. All uses changed.
+ (text): Renamed from always_text.
+ (initial_tab): Renamed from tab_align_flag.
+
+ (horizon_lines): Remove. Remove all uses.
+
+ (main): Invoke bindtextdomain and textdomain after setlocale.
+ Rename "DIFF" to "DIFF_PROGRAM".
+
+ Try to compare file0 to file1, because this is where changes are
+ expected to come from. Diffing between these pairs of files is more
+ likely to avoid phantom changes from file0 to file1.
+ However, use file2 as the common file if this is a 3-way diff,
+ for backward compatibility. Suggested by Karl Tomlinson.
+
+ (create_diff3_block): Use xcalloc instead of malloc + bzero.
+
+ (INT_STRLEN_BOUND): Remove; now in system.h.
+
+ (read_diff): Always use --horizon-lines=100 rather than trying
+ to guess it.
+ Do not pass --inhibit-hunk-merge.
+ Minimum chunk size is 1, not 8KiB.
+ Use xalloc_die to report memory exhaustion.
+ (undotlines): Use long for start, not int.
+
+ * src/diff.h: Assume C89 or better.
+ int -> bool for booleans.
+ int -> lin for line numbers.
+ Don't include regex.h.
+ (enum changes): New enum.
+ (enum line_class): Remove; subsumed by enum changes.
+ (enum output_style): New constant OUTPUT_UNSPECIFIED.
+
+ (ignore_space_change_flag, ignore_all_space_flag): Remove.
+ (ignore_white_space): New decl, subsuming the above two. All
+ uses changed.
+
+ Rename the following decls for consistency with user-visible
+ option spellings. All uses changed.
+ (text): Renamed from always_text_flag.
+ (ignore_blank_lines): Renamed from ignore_blank_lines_flag.
+ (ignore_case): Renamed from ignore_case_flag.
+ (brief): Renamed from no_details_flag.
+ (initial_tab): Renamed from tab_align_flag.
+ (expand_tabs): Renamed from tab_expand_flag.
+ (starting_file): Renamed from dir_start_file.
+ (paginate): Renamed from paginate_flag.
+ (sdiff_merge_assist): Renamed from sdiff_help_sdiff.
+ (left_column): Renamed from sdiff_left_only.
+ (suppress_common_lines): Renamed from sdiff_skip_common_lines.
+ (speed_large_files): Renamed from heuristic.
+ (minimal): Renamed from no_discards.
+
+ (inhibit_hunk_merge): Remove.
+
+ (strip_trailing_cr, excluded, time_format): New decls.
+
+ (files_can_be_treated_as_binary): Renamed from ignore_some_changes.
+
+ (group_format, line_format): Now char const *[], not char *[].
+
+ (struct file_data): Buffer is now word*, not char*, as it's always
+ aligned and this can help the compiler. buffered_chars -> buffered
+ (since it's a byte count, not a char count). All uses changed.
+ New member `eof'.
+
+ (FILE_BUFFER): New macro.
+
+ (excluded_filename, error, free_software_msgid): Remove decls; now in
+ other .h files.
+
+ (sip, slurp): Remove decls.
+ (file_block_read): New decl.
+ (change_letter): Now an array, not a function.
+ (lines_differ): Renamed from line_cmp.
+ (analyze_hunk): Now returns enum changes rather than two change counts.
+
+ * src/Makefile.am (diff_LDADD): New symbol.
+
+ * src/diff.c: Assume C89 or better.
+ int -> bool for booleans.
+ long -> off_t for line numbers.
+ Use angle-brackets when including getopt.h, fnmatch.h, quotesys.h.
+ Include error.h, exclude.h, freesoft.h, hard-locale.h, prepargs.h,
+ regex.h, signal.h, xalloc.h.
+ (copyright_string): Use only most recent year.
+ (authorship_msgid, option_help_msgid): Wrap in N_().
+
+ Rename the following variables for consistency with user-visible
+ option spellings. All uses changed.
+ (binary): Renamed from binary_flag.
+ (new_file): Renamed from entire_new_file_flag.
+ (unidirectional_new_file): Renamed from unidirectional_new_file_flag.
+ (report_identical_files): Renamed from print_file_same_flag.
+
+ (numeric_arg): Remove.
+
+ (exclude, exclude_alloc, exclude_count, excluded_filename, add_exclude,
+ add_exclude_file):
+ Remove; now done by exclude.h.
+
+ (BINARY_OPTION, FROM_FILE_OPTION, HELP_OPTION, HORIZON_LINES_OPTION,
+ IGNORE_FILE_NAME_CASE_OPTION, INHIBIT_HUNK_MERGE_OPTION,
+ LEFT_COLUMN_OPTION, LINE_FORMAT_OPTION, NORMAL_OPTION,
+ SDIFF_MERGE_ASSIST_OPTION, STRIP_TRAILING_CR_OPTION,
+ SUPPRESS_COMMON_LINES_OPTION, TO_FILE_OPTION,
+ UNCHANGED_LINE_FORMAT_OPTION, OLD_LINE_FORMAT_OPTION,
+ NEW_LINE_FORMAT_OPTION, UNCHANGED_GROUP_FORMAT_OPTION,
+ OLD_GROUP_FORMAT_OPTION, NEW_GROUP_FORMAT_OPTION,
+ CHANGED_GROUP_FORMAT_OPTION): New constants.
+ (longopts, main): Use them.
+
+ (longopts, main, option_help_msgid): Add -E, --from-file, --to-file.
+
+ (main): Invoke bindtextdomain and textdomain after setlocale.
+ Use grep syntax, not Emacs, for regular expressions.
+ Use exclude.h, not our own functions.
+ Use ISO 8601 time format in hard locales.
+ Prepend DIFF_OPTIONS.
+ Don't update ignore_some_changes.
+ Use strtoumax instead of numeric_arg.
+ Use specify_value when appropriate.
+ error -> try_help when appropriate.
+ -p now means ^[[:alpha:]$_], not ^[_a-zA-Z$].
+ Ignore --inhibit-hunk-merge.
+ Prefer changed group formats to unchanged ones.
+ Remove now-unnecessary casts.
+ Set files_can_be_treated_as_binary.
+
+ (specify_value): Renamed from specify_format. All uses changed.
+
+ (specify_style): Default is now unspecified, not normal. All
+ uses changed.
+
+ (set_mtime_to_now): New function.
+ (compare_files): Use it. Use memset, not bzero.
+ Set stdin mtime to current time even when stdin is not a regular file.
+ Check for same file attributes, as well as for same file.
+ Use files_can_be_treated_as_binary.
+ "write failed" -> "standard output on output failure.
+
+ * src/context.c: Assume C89 or better.
+ int -> lin for line numbers.
+ Include inttostr.h, regex.h.
+ (TIMESPEC_NS): New macro.
+ (nstrftime): New decl.
+ (print_context_label): Use nstrftime and time_format to format times.
+ Print numeric time stamp value if localtime fails.
+ (print_context_function): New function.
+ (pr_context_hunk, pr_unidiff_hunk): Use it.
+ (find_function): Use size_t for sizes, not int.
+
+ * src/cmp.c: Assume C89 or better.
+ int -> bool for booleans.
+ long -> off_t for line numbers.
+ Use angle-brackets when including cmpbuf.h, getopt.h.
+ Include error.h, freesoft.h, inttostr.h, xalloc.h.
+ (copyright_string): Use only most recent year.
+ (authorship_msgid): Wrap in N_().
+ (buffer): Now word*, not char*. All uses changed.
+ (word): Remove macro; now in system.h.
+ (long_options, option_help_msgid, main): -c --print-chars ->
+ -b --print-bytes
+ (check_stdout): "write failed" -> "standard output"
+ (option_help_msgid): Wrap in N_().
+ (main): Invoke bindtextdomain and textdomain after setlocale.
+ Use strtoumax instead of doing the work ourselves.
+ Check for same_file_attributes as well as same_file.
+ (cmp): Use ssize_t for read returns, not size_t.
+ Do not assume that size_t is not narrower than int.
+ Do not assume that line numbers fit in 'long'.
+ (block_compare_and_count, block_compare):
+ Compiler now checks that buffers are word-aligned.
+ (block_compare_and_count): Count sizes with size_t, not long.
+ (sprintc): byte arg is unsigned char, not unsigned.
+
+ * src/analyze.c: Assume C89 or better.
+ int -> lin for line numbers.
+ int -> bool for booleans.
+ unsigned int -> size_t for sizes.
+ Use angle-brackets when including cmpbuf.h.
+ Include error.h, regex.h, xalloc.h.
+ (discard_confusing_lines, diff_2_files): Use zalloc rather
+ than xalloc+bzero.
+ (discard_confusing_lines): unsigned int -> lin for values that
+ are really line numbers.
+ (shift_boundaries): Do not inhibit hunk merges.
+ (build_reverse_script, build_script, diff_2_files): Use |, not ||.
+ (diff_2_files): no_details_flag & ~ignore_some_changes ->
+ files_can_be_treated_as_binary. Esure that buffer size is a multiple
+ of sizeof (word). Use file_block_read to read buffers.
+ (diff_2_files): Abort if output style is not one of the
+ expected styles.
+
+2001-11-23 Paul Eggert <eggert@twinsun.com>
+
+ * src/Makefile.am, m4/vararrays.m4: New file.
+
+ * m4/prereq.m4 (jm_PREREQ_READUTMP):
+ Remove, as it gives autoheader the willies.
+
+ * m4/README, lib/prepargs.h, lib/prepargs.c, lib/offtostr.c,
+ lib/umaxtostr.c, lib/inttostr.c, lib/inttostr.h,
+ lib/imaxtostr.c, lib/freesoft.h: New files.
+
+ * lib/freesoft.c: Include config.h, freesoft.h rather than diff.h.
+ (free_software_msgid): Wrap contents in N_.
+
+ * lib/cmpbuf.h: Use prototypes instead of old-style functions.
+
+ * lib/cmpbuf.c:
+ Don't include system.h; instead, include config.h, unistd.h.
+ Use prototypes instead of old-style functions.
+ (block_read): Don't assume that int is no wider than size_t.
+
+ * lib/Makefile.am, po/POTFILES.in: New file.
+
+2001-11-22 Paul Eggert <eggert@twinsun.com>
+
+ * pc/config.h:
+ Define filename_cmp as an object-like macro, not as a function-like
+ macro.
+
+ * exgettext: Always operate in the C locale.
+ Set AWK using a method that works even with broken shells.
+
+ * doc/Makefile.am: New file.
+
+ * configure.ac (AC_INIT):
+ Use src/diff.c, not diff.h, as the source files got removed.
+ (AM_CONFIG_HEADER): Switch from AC_CONFIG_HEADER.
+ (AC_ARG_PROGRAM, AC_MINIX): Remove.
+
+ (AC_PREREQ, AM_INIT_AUTOMAKE, ALL_LINGUAS, AC_PROG_AWK,
+ AM_PROG_CC_STDC, AC_PROG_RANLIB, AC_C_INLINE, AC_C_VARARRAYS,
+ DEFAULT_DIFF_PROGRAM, DEFAULT_EDITOR_PROGRAM,
+ AC_STRUCT_ST_MTIM_NSEC): Add.
+
+ (PR_PROGRAM): AC_DEFINE.
+
+ (AC_SYS_LARGEFILE): Use instead of our homebrew version.
+
+ (_GNU_SOURCE): Define if not defined.
+
+ (AC_CHECK_HEADERS): Add stdbool.h, unistd.h.
+ (AC_CHECK_TYPES): Add ptrdiff_t, uintmax_t.
+ (AM_GNU_GETTEXT, XGETTEXT): Add.
+
+ (WITH_MVFS_STAT_BUG, WITH_NFS_STAT_BUG): Remove.
+ (HAVE_MEMCHR): Remove.
+ (AC_CHECK_FUNCS): Add diraccess.
+ (AC_REPLACE_FUNCS): Add memchr, waitpid.
+ (jm_FUNC_GLIBC_UNLOCKED_IO, jm_FUNC_GNU_STRFTIME, jm_FUNC_MALLOC,
+ jm_FUNC_REALLOC, jm_PREREQ_ERROR, jm_PREREQ_QUOTEARG, jm_PREREQ_REGEX,
+ jm_PREREQ_TEMPNAME, jm_AC_PREREQ_XSTRTOUMAX, AC_FUNC_FNMATCH): Add.
+ (fnmatch.h, regex.h): Do not create these files unless we're using
+ our own fnmatch and regex.
+
+ (AC_OUTPUT): Add doc/Makefile, intl/Makefile, lib/Makefile,
+ lib/posix/Makefile, m4/Makefile, po/Makefile.in, src/Makefile.
+
+ * Makefile.am: New file.
+
+ * po/en_GB.po: Don't translate "program" to "programme".
+
+2001-11-20 Paul Eggert <eggert@twinsun.com>
+
+ * m4/prereq.m4: New file.
+
+2001-03-16 Paul Eggert <eggert@twinsun.com>
+
+ * lib/tempname.c (uint64_t):
+ Define if not defined, and if UINT64_MAX is not defined.
+
+2001-02-26 Paul Eggert <eggert@twinsun.com>
+
+ * lib/tempname.c: glibc 1.32
+
+2001-02-17 Paul Eggert <eggert@twinsun.com>
+
+ * m4/Makefile.am.in: GNU fileutils 4.1
+
+2001-01-09 Paul Eggert <eggert@twinsun.com>
+
+ * lib/tempname.c (struct_stat64): New macro.
+ (direxists, __gen_tempname): Use it. This avoids a portability problem
+ with Solaris 8.
+
+ * lib/tempname.c (<config.h>): Include if HAVE_CONFIG_H.
+ (<stddef.h>, <stdint.h>, <string.h>):
+ Include only if STDC_HEADERS || _LIBC.
+ (<fcntl.h>): Include only if HAVE_FCNTL_H || _LIBC.
+ (<unistd.h>): Include only if HAVE_UNISTD_H || _LIBC.
+ (<sys/time.h>): Include only if HAVE_SYS_TIME_H || _LIBC.
+ (__set_errno): Define this macro if <errno.h> doesn't.
+ (P_tmpdir, TMP_MAX, __GT_FILE, __GT_BIGFILE, __GT_DIR, __GT_NOCREATE):
+ Define these macros if <stdio.h> doesn't.
+ (S_ISDIR, S_IRUSR, S_IWUSR, S_IXUSR):
+ Define these macros if <sys/stat.h>
+ doesn't. Ignore <sys/stat.h> S_ISDIR if STAT_MACROS_BROKEN.
+ (stat64, __getpid, __gettimeofday, __mkdir, __open, __open64, lxstat64,
+ __xstat64): Define if not _LIBC.
+ (__secure_getenv): Define if ! (HAVE___SECURE_GETENV || _LIBC).
+ (__gen_tempname): Invoke gettimeofday only if HAVE_GETTIMEOFDAY
+ || _LIBC; otherwise, fall back on plain "time".
+ Use macros like S_IRUSR | S_IWUSR rather than octal values like 0600.
+
+ * lib/mkstemp.c (__GT_FILE): Define to zero if not defined.
+
+2000-10-25 Paul Eggert <eggert@twinsun.com>
+
+ * lib/hard-locale.c: New file.
+
+2000-02-05 Paul Eggert <eggert@twinsun.com>
+
+ * exgettext: From GCC repository
+
+1999-07-06 Paul Eggert <eggert@twinsun.com>
+
+ * lib/mkstemp.c: glibc 2.2
+
+1998-12-11 Paul Eggert <eggert@twinsun.com>
+
+ * src/sdiff.c (lf_snarf):
+ Fix bug when help line wrapped around the input buffer.
+
+1998-09-15 Paul Eggert <eggert@twinsun.com>
+
+ * diff.texi: Add @dircategory and @direntry.
+
+1998-09-14 Paul Eggert <eggert@twinsun.com>
+
+ * Makefile.in (VERSION): Version 2.7.2.
+ (DEFAULT_DIFF_PROGRAM): Renamed from DIFF_PROGRAM.
+ (PR_PROGRAM): All `configure' to define it.
+ (srcs): Add $(diffutils_srcs), freesoft.c, quotearg.c instead of
+ quote.c, quotearg.h.
+ (distfiles): Add acconfig.h, message/*.
+ (all): Depend on $(destfiles), not info.
+ (version.c): Parenthesize `GNU diffutils'.
+ (common_o): Add freesoft.o
+ (diff_o): quote.o -> quotearg.o
+ (diff3_o, sdiff_o): Likewise.
+ (diff.dvi): Depend on version.texi.
+ (diff.o diff3.o quotearg.o sdiff.o util.o):
+ New dependency on quotearg.h
+ (diff3.o): DIFF_PROGRAM -> DEFAULT_DIFF_PROGRAM.
+ (sdiff.o): Likewise.
+ (messages.po): Remove.
+ (message/msgid.po, message/template.po): New rules.
+ (maintainer-clean): Renamed from realclean.
+ (install): Install from source directory, if applicable.
+ Invoke install-info if needed.
+ (install-strip): New rule.
+ (check): Set DIFF.
+ (stamp-h.in): Don't put the date into the timestamp.
+ (D_dirs): Add $D/message.
+ ($D.tar.gz): Compress with gzip -9.
+ Don't use ln to create distribution; it doesn't work with symlinks.
+ (srcs, distfiles, diff_o, diff3_o, sdiff_o): Rename quotearg.c to
+ quotesys.c and quotearg.h to quotesys.h.
+
+ * configure.in (AC_PATH_PROG): Add PR_PROGRAM.
+ If available, prefer support for large files unless the user specified
+ one of the CPPFLAGS, LDFLAGS, or LIBS variables.
+ (AC_STRUCT_ST_RDEV): Add.
+ (HAVE_ST_FSTYPE_STRING): Add.
+ (--with-mvfs-stat-bug, --with-nfs-stat-bug): New options.
+ (HAVE_MEMCHR): New macro.
+ (AC_CHECK_FUNCS): Add sicprocmask.
+
+ * diff.h (XTERN): Renamed from EXTERN.
+ (struct filedata): Remove dir_p arg.
+ (struct comparison): New type.
+ (diff_2_files, diff_dirs)" Ise ot/
+ (error): Add printf attribute if applicable.
+ (free_software_msgid): New decl.
+ (pr_program): New decl.
+ (fatal): Add noreturn attribute.
+ (pfatal_with_name): Likewise.
+
+ * system.h (__attribute__): New macro.
+ (getenv): Don't declare if HAVE_STDLIB_H.
+ (CHAR_MAX): New macro.
+ (<locale.h>): New include.
+ (<locale.h>): Include before <libintl.h>.
+ (could_be_mvfs_stat_bug, could_be_nfs_stat_bug,
+ dev_may_have_duplicate_ino, same_special_file): New macros.
+ (same_file): Use them.
+
+ * cmp.c (authorship_msgid): New var.
+ (free_software_msgid): New decl.
+ (error): Now has printf attribute.
+ (try_help): Likewise.
+ (long_options): Don't assume ASCII.
+ (try_help): Now accepts operand arg.
+ (main): Check for -1, not EOF, when calling getopt_long.
+ Report --ignore-initial value when complaining about it.
+ Output copyright and free software info with -v.
+ Don't assume ASCII.
+ Report last operand when one is missing.
+ Report text of extra operand.
+ Move block_read into cmpbuf.c.
+
+ * diff.c (authorship_msgid): New var.
+ (quotesys.h): Include.
+ (ck_atoi): Remove.
+ (function_regexp_list, ignore_regexp_list): Now static.
+ (binary_flag): Renamed from binary_I_O.
+ (entire_new_file_flag, unidirectional_new_file_flag,
+ print_file_same_flag): Now static.
+ (numeric_arg): Renamed from ck_atoi.
+ New argument specifying the argument type.
+ (longopts, main): Don't assume ASCII.
+ (longopts): Remove old aliases --file-label, --entire-new-file,
+ --ascii, --print.
+ (main): Check for -1, not EOF, when calling getopt_long.
+ Use numeric_arg to report errors.
+ Report error if -l specified but pagination is not supported.
+ Report error if -S is specified twice with conflicting values.
+ Have --version conform to the new GNU standards.
+ Add new --from-file, --to-file, --inhibit-hun,-merge options.
+ Make the horizon at least as large as the context.
+ Add casts to pacify gcc -Wall.
+ (try_help): Add operand arg.
+ (option_help_msgid): Doc fix to match above.
+ (usage): Indent option_help_msgid.
+ (compare_files): Now takes struct comparison
+ instead of two directory names and a depth.
+ (NONEXISTENT, UNOPENED, ERRNO_ENCODE, ERRNO_DECODE):
+ New macros.
+ (DIR_P): New macro.
+ Report error if fflush does.
+
+ * cmpbuf.c (block_read): Moved here from cmp.c.
+
+ * cmpbuf.h (block_read): New decl.
+
+ * io.c (cmpbuf.h): Include.
+ (slurp): Check for arithmetic overflow when computing buffer size.
+
+ * dir.c (diff_dirs): Check for recursive directory loop.
+ Arg is now struct comparison const *.
+ (dir_loop): New function
+
+ * analyze.c (no_discards): Remove.
+ (inhibit): Remove.
+ (shift_boundaries): Don't inhibit. If inhibit_hunk_merge is nonzero,
+ don't merge hunks.
+ (briefly_report): Now returns 2 if trouble, CHANGES otherwise.
+ (diff_2_files): Now takes struct comparison. If briefly_report reports
+ trouble, pass it on to caller.
+
+ * side.c (print_half_line): Add brackets to pacify GCC -Wall.
+
+ * sdiff.c (quotesys.h): Include.
+ (DIFF_PROGRAM, DEFAULT_EDITOR_PROGRAM): Remove.
+ (free_software_msgid, editor_program, not_found): New vars.
+ (diffbin, edbin): Remove.
+ (editor_program): Renamed from edbin.
+ (edit, interact): Now take extra string arg.
+ (exiterr, fatal, perror_fatal, try_help): Add noreturn attribute.
+ (sigset_t, sigemptyset, sigmask, sigaddset, SIG_BLOCK, SIG_SETMASK):
+ (sigprocmask): New macros, if !HAVE_SIGPROCMASK.
+ (error): Now has printf attribute.
+ (longopts, main): Don't assume ASCII.
+ (try_help): New operand arg.
+ (usage): Conform to new GNU standards.
+ (main): Set static vars for editor and diff program.
+ Compare getopt_long result to -1, not EOF.
+ -v conforms to new GNU standard.
+ Complain better about extra and missing operands.
+ If HAVE_VFORK, block SIGINT and SIGPIPE in the parent, since when
+ the child munges its handlers it may somp on the parent.
+ Pass rname to intract.
+ Translate not-found message before forking.
+ (give_help): Just output it all at once.
+ (edit): New args lname, lline, rname, rline.
+ (edit): New command 'd'.
+ (interact): New args lname, rname.
+
+ * util.c (quotesys.h): Include.
+ (PR_PROGRAM): New macro.
+ (pfatal_with_name): Abort if error returns.
+ (fatal): Likewise.
+ (print_message_queue): Free message chain after printing.
+ (currently_recursive): Renamed from current_depth, and now a boolean.
+ (begin_output): Report error if fflush does.
+ Avoid stdio and gettext in child.
+
+ * diff3.c (quotesys.h): Include.
+ (free_software_msgid): New decl.
+ (RANGE_START, RANGE_END): Renamed from START and END.
+ (fatal, perror_with_exit, try_help): Add noreturn attribute.
+ (error): Add printf attribute.
+ (diff_program): Now a ptr, not an array.
+ Initialize to DEFAULT_DIFF_PROGRAM instead of DIFF_PROGRAM.
+ (longopts, main): Don't assume ASCII.
+ (main): Use DIFF environment var to specify name of diff program.
+ Compare getopt_long result to -1, not EOF.
+ -v now reports version according to new GNU standard.
+ Report spelling of extra operand, or last operand before missing one.
+ (try_help): Now takes operand arg.
+ (option_help_ms): Fix typo: missing comma.
+ (usage): Update as per current GNU standards.
+ (environ): Remove decl.
+ (read_diff): Invoke diff with --inhibit-hunk-merge.
+ Translate `not found' message before forking.
+ Quote name of diff program.
+ Pass horizon lines.
+ `memory exhausted' -> `Memory exhausted'
+
+ * pc/makefile (%.exe): Remove.
+ (pc-clean): Remove *.exe
+ * pc/makefile.sed (DEFAULT_DIFF_PROGRAM): Renamed from DIFF_PROGRAM.
+ When editing mkinstalldirs rule, look for exec_prefix and prefix.
+ Add .exe when installing files.
+ * pc/emx/config.h (same_file): Add.
+ * pc/config.h (same_file): Remove.
+ * pc/djgpp/config.h: Adjust to latest patch from eliz.
+ * pc/djgpp/makefile.sed: Don't alter PROGRAMS.
+ * pc/pc.c: Update FSF address.
+ (quote_system_arg): Renamed from system_quote_arg.
+
+ * README: Add --with-mvfs-stat-bug, --with-nfs-stat-bug.
+
+ * getmsgids: Add copyright date and update FSF address.
+
+ * diff.texi: Document recent changes.
+ The patch doc still corresponds to patch 2.2, unfortunately.
+ Update GNU bug reporting address. Omit Larry Wall's address;
+ it's obsolete and he's busy with perl.
+
+ * context.c: Fix spacing.
+
+ * NEWS: Mention --from-file=FILE, --to-file=FILE, ed.
+
+ * acconfig.h, freesoft.c, message/de.po, message/en_UK.po,
+ message/es.po, message/fr.po, message/pl.po, message/sv.po:
+ New files.
+
+ * ed.c: Remove `#if 0'ed code.
+
+ * normal.c, waitpid.c: Update FSF address.
+
+1998-03-15 Paul Eggert <eggert@twinsun.com>
+
+ * quotesys.c: Renamed from quotearg.c.
+
+ * quotesys.h: Renamed from quotearg.h
+ (__QUOTESYS_P): Renamed from __QUOTEARG_P.
+
+1997-05-05 Paul Eggert <eggert@twinsun.com>
+
+ * quotesys.c, quotesys.h: New file.
+
+Mon Nov 14 05:10:56 1994 Paul Eggert <eggert@twinsun.com>
+
+ Add internationalization support.
+ Several messages have been changed slightly,
+ to make them more consistent and easier to translate.
+ All strings that are messages are passed through gettext once before
+ being used, so that they can be localized.
+ Each function and macro whose first parameter is a gettext msgid
+ has had its first parameter's name changed so it ends in `msgid'.
+ All arrays of msgids have had their names changed to end in `msgid'.
+ `getmsgids' uses this to determine which strings are msgids.
+
+ * pc/COPYING, pc/INSTALL, pc/config.h,
+ pc/djgpp/config.h, pc/djgpp/makefile.sed,
+ pc/emx/config.h, pc/emx/diff.def, pc/emx/gnuregex.def,
+ pc/emx/makefile.sed,
+ pc/makefile, pc/makefile.sed, pc/pc.c: New files, for PC support.
+
+ * getmsgids: New file.
+
+ * Makefile.in (PACKAGE, VERSION, diffutils_srcs, D): New vars.
+ (version.c, version.texi, messages.po): New files.
+ messages.po is built automatically from source files and `getmsgids'.
+ (distfiles): Add them, pc/*, and getmsgids.
+ (diff.info): Now depends on version.texi.
+ (realclean): Clean messages.po, version.*.
+ (dist): Just build $D.tar.gz.
+ ($D.tar.gz): New file, takes over old `dist' function.
+ Don't assume $(distfiles) are all in same directory.
+
+ * configure.in (AC_CHECK_HEADERS): Add libintl.h, locale.h.
+ (AC_CHECK_LIB): Check for -lintl.
+
+ * analyze.c (briefly_report): Rewrite `message (A?"B":"C")' as
+ `if (A) message ("B") : message ("C")'; this is for getmsgids.
+ (briefly_report, diff_2_files): For label, use file_label if set.
+ * diff.c (compare_files): Likewise.
+
+ * system.h (gettext): Declare; use a stub if ! HAVE_LIBINTL_H.
+ (setlocale): Declare; use a stub if ! HAVE_LOCALE_H.
+
+ * cmp.c, diff.c, diff3.c, sdiff.c (main):
+ Invoke setlocale first thing, to tell library we're internationalized.
+ (option_help_msgid): New constant.
+ (usage): Use it, so message is translated one option at a time.
+ * sdiff (help_msgid, give_help): Likewise.
+
+ * cmp.c (sprintc): Renamed from `printc'.
+ Now outputs to a buffer instead of stdout.
+ (cmp): Use new sprintc; it's easier to internationalize.
+
+ * diff.c (main): -D FOO now outputs `/* ! FOO */ instead of
+ `/* not FOO */'.
+
+ * sdiff.c (version_string): Fix decl typo: `const' was missing.
+ (trapsigs): Ignore sigaction failure, to be compatible with `signal'.
+
+ * util.c (struct msg, message5, print_message_queue):
+ Allocate just one block of memory to save a message.
+
+Wed Nov 9 17:42:44 1994 Paul Eggert <eggert@twinsun.com>
+
+ * sdiff.c (trapsigs): Don't check signal return value, since it's
+ bogus under djgpp.
+
+Mon Oct 31 07:27:27 1994 Paul Eggert <eggert@twinsun.com>
+
+ * Makefile.in (srcs, diff_o, diff3_o, sdiff_o):
+ New files quote.c, quote.o.
+
+ * diff.h (function_regexp, ignore_regexp): Replace lists of compiled
+ regexps with these single compiled regexps. All users changed.
+ (regexp_list,function_regexp_list,ignore_regexp_list): Move to diff.c.
+ * diff.c (add_regexp): Build one big regexp instead of a regexp list.
+ (summarize_regexp_list): New function.
+ (regexp_list): Redesigned struct; moved here from diff.h.
+ (function_regexp_list, ignore_regexp_list): Likewise, for vars.
+
+ * context.c (find_function): Simplify interface:
+ don't return size of function line. All callers changed.
+ (print_context_script, find_function): INT_MAX now denotes no
+ previous match; this is simpler than `- file->prefix_lines - 1'.
+
+ * diff3.c (read_diff): Quote arguments with system_quote_arg.
+ * sdiff.c (main): Use system_quote_arg to compute command.
+ * diff.c (option_list): Quote options with system_quote_arg.
+ * util.c (begin_output): Use system_quote_arg to compute command.
+
+ * util.c (pr_program): New var.
+ (analyze_hunk): Fix off-by-1 line length bug.
+ Match with one big regexp instead of a list of regexps.
+ Use new `trivial_length' local instead of comparing first byte to `\n'.
+ Help the compiler with linbuf local vars.
+
+ * system.h (system_quote_arg):
+ New function; replaces SYSTEM_QUOTE_ARG macro.
+
+Sat Oct 15 20:09:12 1994 Paul Eggert <eggert@twinsun.com>
+
+ * system.h (_tolower): Define if not already defined.
+ * io.c (find_and_hash_each_line): Change tolower to _tolower; this
+ speeds up diff -i considerably on some hosts (e.g. Solaris 2.3).
+ * util.c (line_cmp): Likewise.
+ * ifdef.c (groups_letter_value): Likewise.
+
+ * diff.h (ignore_some_line_changes): Remove. All users changed.
+ * io.c (find_and_hash_each_line): Don't invoke line_cmp if the length
+ differs and -i is in force. Don't assume ISSPACE ('\n') is nonzero.
+
+ * diff.h (xmalloc_exit_failure): New variable.
+ All `main' programs set this variable at the start.
+ xmalloc and xrealloc are now taken from GNU library.
+ * cmp.c (main): Align buffer size to word size; some mallocs care.
+ * io.c (slurp): Likewise.
+ * diff.c (add_exclude): Can now assume xrealloc (0, ...) works.
+ (add_regexp): Free storage on failure. Allocate storage all at one go.
+ * system.h (malloc, realloc): Remove unused declarations.
+ * diff3.c, sdiff.c, util.c (xmalloc, xrealloc): Remove.
+ * sdiff.c (diffarg): Take advantage of cleaner xrealloc semantics.
+
+ * io.c (ROL): Use sizeof to make it more generic.
+
+ * Makefile.in (common_o): New variable.
+ Link error.o and xmalloc.o into all programs.
+ (check): Depend on $(PROGRAMS).
+
+ * diff.h (error): Change to GNU library standard. All callers changed.
+ * diff3.c (main): Use strerror (EISDIR) instead of "Is a directory".
+ (fatal, perror_with_exit): Use `error'.
+ * util.c (perror_with_name, fatal): Use GNU `error'.
+ (error): Remove.
+
+Wed Oct 12 17:04:40 1994 David J. MacKenzie (djm@duality.gnu.ai.mit.edu)
+
+ * cmp.c (main): Set xmalloc_exit_failure.
+
Sat Oct 1 05:24:19 1994 Paul Eggert <eggert@twinsun.com>
* Version 2.7 released.
@@ -190,7 +2287,7 @@ Fri Sep 2 16:01:49 1994 Paul Eggert <eggert@twinsun.com>
* system.h (STAT_BLOCKSIZE): Don't define if already defined.
(min, max): Undef if already defined.
(filename_cmp, filename_lastdirchar, HAVE_FORK, HAVE_SETMODE,
- initialize_main O_BINARY, same_file): New macros.
+ initialize_main, O_BINARY, same_file): New macros.
Fri Jun 17 11:23:53 1994 David J. MacKenzie (djm@geech.gnu.ai.mit.edu)
@@ -580,7 +2677,7 @@ Sat Jun 5 23:10:40 1993 Paul Eggert (eggert@twinsun.com)
Wed May 26 17:16:02 1993 Paul Eggert (eggert@twinsun.com)
* diff.c (main): Cast args to compare_files, for traditional C.
- * side.c (print_sdiff_common_lines_print_sdiff_hunk): Likewise.
+ * side.c (print_sdiff_common_lines, print_sdiff_hunk): Likewise.
* analyze.c, diff3.c, sdiff.c, util.c: Don't assume NULL is defined
properly.
@@ -1407,9 +3504,9 @@ Sun Mar 25 15:58:42 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
* analyze.c (discard_confusing_lines):
`many' wasn't being used; use it.
- Cancelling provisionals near start of run must handle already
- cancelled provisionals.
- Cancelling subruns of provisionals was cancelling last nonprovisional.
+ Canceling provisionals near start of run must handle already
+ canceled provisionals.
+ Canceling subruns of provisionals was canceling last nonprovisional.
Sat Mar 24 14:02:51 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
@@ -1417,7 +3514,7 @@ Sat Mar 24 14:02:51 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
Threshold for line occurring many times scales by square root
of total lines.
Within each run, cancel any long subrun of provisionals.
- Don't update `provisional' while cancelling provisionals.
+ Don't update `provisional' while canceling provisionals.
In big outer loop, handle provisional and nonprovisional separately.
Thu Mar 22 16:35:33 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
@@ -1477,7 +3574,7 @@ Thu Feb 8 02:43:16 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
Fri Feb 2 23:21:38 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
- * analyze.c (diif_2_files): If -B or -I, don't return 1
+ * analyze.c (diff_2_files): If -B or -I, don't return 1
if all changes were ignored.
Wed Jan 24 20:43:57 1990 Richard Stallman (rms at albert.ai.mit.edu)
@@ -1496,7 +3593,7 @@ Wed Jan 10 16:06:38 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
Sun Dec 24 10:29:20 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
* io.c (find_equiv_class): Fix typo that came from changing init of B
- to an assigment.
+ to an assignment.
* version.c: New file.
* diff.c (main): -v prints version number.
@@ -1523,7 +3620,7 @@ Thu Nov 16 13:51:10 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
* analyze.c (shift_boundaries):
Test for END at end of range before indexing by it.
- Fix typo `preceeding' in var names.
+ Fix misspelling of `preceding' in var names.
Sat Nov 11 14:04:16 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
@@ -1758,9 +3855,24 @@ Thu Nov 3 16:30:24 1988 Randall Smith (randy at gluteus.ai.mit.edu)
* ed.c, analyze.c, context.c: Shortened names to 12 characters for
the sake of System V (too simple not to do).
-
-Local Variables:
-mode: indented-text
-left-margin: 8
-version-control: never
-End:
+
+
+Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1997, 1998, 1999,
+2000, 2001, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Diffutils.
+
+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 they will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
diff --git a/contrib/diff/Makefile.am b/contrib/diff/Makefile.am
new file mode 100644
index 0000000..87f7c3d
--- /dev/null
+++ b/contrib/diff/Makefile.am
@@ -0,0 +1,23 @@
+# Main Automakefile for GNU diffutils.
+
+# Copyright (C) 2001, 2002, 2004 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., 59 Temple Place - Suite 330, Boston, MA
+## 02111-1307, USA.
+
+EXTRA_DIST = bootstrap exgettext
+SUBDIRS = doc lib m4 ms src man po
+
+ACLOCAL_AMFLAGS = -I m4
diff --git a/contrib/diff/NEWS b/contrib/diff/NEWS
index dcde122..3854f8b 100644
--- a/contrib/diff/NEWS
+++ b/contrib/diff/NEWS
@@ -1,6 +1,102 @@
+Version 2.8.7 contains no user-visible changes.
+
+User-visible changes in version 2.8.6:
+
+* New diff3 option --strip-trailing-cr.
+
+* With -N and -P, inaccessible empty regular files (the kind of files
+ that 'patch' creates to indicate nonexistent backups) are now
+ treated as nonexistent when they are in the 'backup' file position.
+
+* If multiple SKIP values are given to cmp, e.g., `cmp -i 10 -i 20',
+ cmp now uses the maximal value instead of the last one.
+
+* diff now omits the ".000000000" on hosts that do not support
+ fractional time stamps.
+
+Version 2.8.5 was not publicly released.
+
+User-visible changes in version 2.8.4:
+
+* Diff now simply prints "Files A and B differ" instead of "Binary
+ files A and B differ". The message is output if either A or B
+ appears to be a binary file, and the old wording was misleading
+ because it implied that both files are binary, which is not
+ necessarily the case.
+
+User-visible changes in version 2.8.3:
+
+* New locale: en_US.
+
+User-visible changes in version 2.8.2:
+
+* New diff and sdiff option:
+ --tabsize=COLUMNS
+* If --ignore-space-change or --ignore-all-space is also specified,
+ --ignore-blank-lines now considers lines to be empty if they contain
+ only white space.
+* More platforms now handle multibyte characters correctly when
+ excluding files by name (diff -x and -X).
+* New locales: hu, pt_BR.
+
+User-visible changes in version 2.8.1:
+
+* Documentation fixes.
+
+User-visible changes in version 2.8:
+
+* cmp and diff now conform to POSIX 1003.1-2001 (IEEE Std 1003.1-2001)
+ if the underlying system conforms to POSIX and if the _POSIX2_VERSION
+ environment variable is set to 200112. Conformance removes support
+ for `diff -NUM', where NUM is a number. Use -C NUM or -U NUM instead.
+* cmp now supports trailing operands SKIP1 and SKIP2, like BSD cmp.
+* cmp -i or --ignore-initial now accepts SKIP1:SKIP2 option value.
+* New cmp option: -n or --bytes.
+* cmp's old -c or --print-chars option has been renamed;
+ use -b or --print-bytes instead.
+* cmp now outputs "byte" rather than "char" outside the POSIX locale.
+* cmp -l's index column width now adjusts to fit larger (or smaller) files.
+* cmp -l -s and cmp -s -l are not allowed. Use cmp -s or cmp -l instead.
+* diff uses ISO 8601 style time stamps for output times (e.g. "2001-11-23
+ 16:44:36.875702460 -0800") unless in the C or POSIX locale and the
+ -c style is specified.
+* diff's -I and -F options use the regexp syntax of grep, not of Emacs.
+* diff now accepts multiple context arguments, and uses their maximum value.
+* New diff and sdiff options:
+ -E --ignore-tab-expansion
+ --strip-trailing-cr
+* New diff options:
+ --from-file=FILE, --to-file=FILE
+ --ignore-file-name-case
+ --no-ignore-file-name-case
+* New diff3 and sdiff option:
+ --diff-program=PROGRAM
+* The following diff options are still accepted, but are no longer documented.
+ They may be withdrawn in future releases.
+ -h (omit; it has no effect)
+ -H (use --speed-large-files instead)
+ -L (use --label instead)
+ -P (use --unidirectional-new-file instead)
+ --inhibit-hunk-merge (omit; it has no effect)
+* Recursive diffs now sort file names according to the LC_COLLATE locale
+ category if possible, instead of using native byte comparison.
+* Recursive diffs now detect and report directory loops.
+* Diff printf specs can now use the "0" and "'" flags.
+* The new sdiff interactive command `ed' precedes each version with a header.
+* On 64-bit hosts, files larger than 2 GB can be compared.
+* Some internationalization support has been added, but multibyte locales
+ are still not completely supported yet.
+* Some diagnostics have been reworded slightly for consistency.
+ Also, `diff -D FOO' now outputs `/* ! FOO */' instead of `/* not FOO */'.
+* The `patch' part of the manual now describes `patch' version 2.5.4.
+* Man pages are now distributed and installed.
+* There is support for DJGPP; see the 'ms' subdirectory and the files
+ m4/dos.m4 and */setmode.*.
+
+
User-visible changes in version 2.7:
-* New diff option: --binary (useful only on non-Posix hosts)
+* New diff option: --binary (useful only on non-POSIX hosts)
* diff -b and -w now ignore line incompleteness; -B no longer does this.
* cmp -c now uses locale to decide which output characters to quote.
* Help and version messages are reorganized.
@@ -64,8 +160,8 @@ User-visible changes in version 2.4:
* The format spec %0 introduced in version 2.1 has been removed, since it
is incompatible with printf specs like %02d. To represent a null char,
use %c'\0' instead.
-* cmp and diff now conform to Posix.2 (ISO/IEC 9945-2:1993)
- if the underlying system conforms to Posix:
+* cmp and diff now conform to POSIX 1003.2-1992 (ISO/IEC 9945-2:1993)
+ if the underlying system conforms to POSIX:
- Some messages' wordings are changed in minor ways.
- ``White space'' is now whatever C's `isspace' says it is.
- When comparing directories, if `diff' finds a file that is not a regular
@@ -124,3 +220,25 @@ User-visible changes in version 2.0:
* Add long-named equivalents for other diff3 options.
* diff options -F (--show-function-line) and -I (--ignore-matching-lines)
can now be given more than once.
+
+
+
+Copyright (C) 1993, 1994, 1998, 2001, 2002, 2004 Free Software
+Foundation, Inc.
+
+This file is part of GNU Diffutils.
+
+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 they will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
diff --git a/contrib/diff/README b/contrib/diff/README
index bfb9965..0c37230 100644
--- a/contrib/diff/README
+++ b/contrib/diff/README
@@ -1,9 +1,69 @@
+README for GNU DIFF
+
This directory contains the GNU diff, diff3, sdiff, and cmp utilities.
Their features are a superset of the Unix features and they are
-significantly faster. cmp has been moved here from the GNU textutils.
+significantly faster.
+
+Please see the file COPYING for copying conditions.
+
+Please see the file doc/version.texi for version information.
+
+Please see the file doc/diff.texi (or doc/diff.info) for documentation
+that can be printed with TeX, or read with the `info' program or with
+Emacs's `M-x info'. Brief man pages are in man/*, but they are no
+substitute for the documentation.
+
+Please see the file ABOUT-NLS for notes about translations.
+
+Please see the file INSTALL for generic compilation and installation
+instructions. Briefly, you can run "./configure; make install". The
+command "./configure --help" lists the supported --enable and --with
+options.
+
+If you have a problem with internationalization, you might be able to
+work around it as described in ABOUT-NLS by invoking `./configure
+--disable-nls'. Many of the problems arise from dynamic linking
+issues on non-GNU platforms (e.g. with the iconv library). Such
+problems tend to be shared by other GNU applications on these
+platforms, and can usually be fixed by carefully tweaking your non-GNU
+installation. If you have an older version of libiconv, please
+upgrade to the latest one; see <ftp://ftp.gnu.org/gnu/libiconv/>. If
+the problem seems isolated to diffutils, though, please report a bug.
+
+This program requires a Standard C compiler (C89 or later). If you
+have a nonstandard compiler, please install GCC first.
+
+If you make changes to the source code, you may need appropriate
+versions of GNU build tools to regenerate the intermediate files. The
+following versions were used to generate the intermediate files in
+this distribution:
+
+* Autoconf 2.59 <ftp://ftp.gnu.org/gnu/autoconf/autoconf-2.59.tar.gz>
+* Automake 1.8.3 <ftp://ftp.gnu.org/gnu/automake/automake-1.8.3.tar.gz>
+* gettext 0.14.1 <ftp://ftp.gnu.org/gnu/gettext/gettext-0.14.1.tar.gz>
+* help2man 1.33 <ftp://ftp.gnu.org/gnu/help2man/help2man-1.33.1.tar.gz>
+* Texinfo 4.7 <ftp://ftp.gnu.org/gnu/texinfo/texinfo-4.7.tar.gz>
+
+Please report bugs to <bug-gnu-utils@gnu.org>.
+
+-----
+
+Copyright (C) 1992, 1998, 2001, 2002, 2004 Free Software Foundation,
+Inc.
+
+This file is part of GNU Diffutils.
+
+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.
-See the file COPYING for copying conditions.
-See the file diff.texi (or diff.info*) for documentation.
-See the file INSTALL for compilation and installation instructions.
+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.
-Report bugs to bug-gnu-utils@prep.ai.mit.edu
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
diff --git a/contrib/diff/THANKS b/contrib/diff/THANKS
new file mode 100644
index 0000000..4fc388c
--- /dev/null
+++ b/contrib/diff/THANKS
@@ -0,0 +1,22 @@
+Thanks to all the following for their contributions to GNU diffutils:
+
+Thomas Bushnell <tb@becket.net>
+Wayne Davison <wayned@users.sourceforge.net>
+Ulrich Drepper <drepper@redhat.com>
+Paul Eggert <eggert@twinsun.com>
+Jay Fenlason <hack@gnu.org>
+John Gilmore <gnu@cygnus.com>
+Torbjorn Granlund <tege@swox.com>
+Mike Haertel <mike@ichips.intel.com>
+Bruno Haible <haible@ilog.fr>
+Chris Hanson <cph@gnu.org>
+Jim Kingdon <kingdon@panix.com>
+Tom Lord <lord@gnu.org>
+David J. MacKenzie <djm@gnu.org>
+Roland McGrath <roland@gnu.org>
+Jim Meyering <meyering@lucent.com>
+Eugene W. Myers <gene@cs.arizona.edu>
+Randy Smith <randy@gnu.org>
+Richard Stallman <rms@gnu.org>
+Leonard H. Tower Jr. <tower@ai.mit.edu>
+Eli Zaretskii <eliz@is.elta.co.il>
diff --git a/contrib/diff/TODO b/contrib/diff/TODO
new file mode 100644
index 0000000..98211ed
--- /dev/null
+++ b/contrib/diff/TODO
@@ -0,0 +1 @@
+Add --include option (opposite of --exclude).
diff --git a/contrib/diff/bootstrap b/contrib/diff/bootstrap
new file mode 100755
index 0000000..f72f57d
--- /dev/null
+++ b/contrib/diff/bootstrap
@@ -0,0 +1,180 @@
+#! /bin/sh
+
+# Bootstrap this package from CVS.
+
+# Copyright (C) 2003, 2004 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., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+# Written by Paul Eggert.
+
+package=diffutils
+
+# Parse options.
+
+for option
+do
+ case $option in
+ --help)
+ echo "$0: usage: $0 [--gnulib-srcdir=DIR] [--cvs-auth=AUTH-METHOD] [--cvs-user=USERNAME] [--skip-po]"
+ exit;;
+ --gnulib-srcdir=*)
+ GNULIB_SRCDIR=`expr "$1" : '--gnulib-srcdir=\(.*\)'`;;
+ --cvs-auth=*)
+ CVS_AUTH=`expr "$1" : '--cvs-auth=\(.*\)'`;;
+ --cvs-user=*)
+ CVS_USER=`expr "$1" : '--cvs-user=\(.*\)'`;;
+ --skip-po)
+ SKIP_PO=t;;
+ *)
+ echo >&2 "$0: $option: unknown option"
+ exit 1;;
+ esac
+done
+
+echo "$0: Bootstrapping CVS $package..."
+
+build_cvs_prefix() {
+ CVS_PREFIX=:${1}:
+ if [ "${2}" != - ]; then
+ CVS_PREFIX=${CVS_PREFIX}${2}@
+ fi
+}
+
+# Get gnulib files.
+
+case ${GNULIB_SRCDIR--} in
+-)
+ if [ ! -d gnulib ]; then
+ echo "$0: getting gnulib files..."
+
+ trap exit 1 2 13 15
+ trap 'rm -fr gnulib; exit 1' 0
+
+ case "${CVS_AUTH--}" in
+ -) : ${CVS_RSH:?}
+ CVS_PREFIX="";;
+ pserver) build_cvs_prefix $CVS_AUTH ${CVS_USER:-anoncvs};;
+ gserver|server)
+ build_cvs_prefix $CVS_AUTH ${CVS_USER--};;
+ ext) : ${CVS_RSH:?}
+ build_cvs_prefix $CVS_AUTH ${CVS_USER--};;
+ *) echo "$0: Unknown CVS access method" >&2
+ exit 1;;
+ esac
+ if [ "${CVS_AUTH--}" = "pserver" ]; then
+ cvs -d ${CVS_PREFIX}subversions.gnu.org:/cvsroot/gnulib login || exit
+ fi
+ cvs -q -d ${CVS_PREFIX}subversions.gnu.org:/cvsroot/gnulib co gnulib || exit
+
+ trap 0
+ fi
+ GNULIB_SRCDIR=gnulib
+esac
+
+<$GNULIB_SRCDIR/gnulib-tool || exit
+
+gnulib_modules='
+c-stack
+dirname
+error
+exclude
+exit
+exitfail
+file-type
+fnmatch-gnu
+getopt
+hard-locale
+inttostr
+mkstemp
+posixver
+regex
+strcase
+strftime
+strtoumax
+unlocked-io
+version-etc
+xalloc
+xstrtoumax
+'
+
+previous_gnulib_modules=
+while [ "$gnulib_modules" != "$previous_gnulib_modules" ]; do
+ previous_gnulib_modules=$gnulib_modules
+ gnulib_modules=`
+ (echo "$gnulib_modules"
+ for gnulib_module in $gnulib_modules; do
+ $GNULIB_SRCDIR/gnulib-tool --extract-dependencies $gnulib_module
+ done) | sort -u
+ `
+done
+
+gnulib_files=`
+ (for gnulib_module in $gnulib_modules; do
+ $GNULIB_SRCDIR/gnulib-tool --extract-filelist $gnulib_module
+ done) | sort -u
+`
+
+gnulib_dirs=`echo "$gnulib_files" | sed 's,/[^/]*$,,' | sort -u`
+mkdir -p $gnulib_dirs || exit
+
+for gnulib_file in $gnulib_files; do
+ dest=$gnulib_file
+
+ case $gnulib_file in
+ m4/onceonly_2_57.m4) dest=m4/onceonly.m4;;
+ esac
+
+ rm -f $dest &&
+ echo "$0: Copying file $GNULIB_SRCDIR/$gnulib_file" &&
+ cp -p $GNULIB_SRCDIR/$gnulib_file $dest || exit
+done
+
+
+# Get translations.
+
+case $SKIP_PO in
+'')
+ echo "$0: getting translations into po..."
+ (cd po &&
+ rm -f dummy `ls | sed -n '/\.gmo$/p; /\.po/p'` &&
+ wget -nv -nd -r -l 1 -A .po -C off \
+ http://www2.iro.umontreal.ca/~gnutra/po/maint/$package/ &&
+ ls *.po | sed 's/\.po$//' >LINGUAS
+ ) || exit;;
+esac
+
+
+# Reconfigure, getting other files.
+
+echo "$0: autoreconf --verbose --install --force ..."
+autoreconf --verbose --install --force || exit
+
+
+# Generate autoconf and automake snippets.
+
+(echo '# This file is generated automatically by "bootstrap".' &&
+ echo 'AC_DEFUN([GNULIB_AUTOCONF_SNIPPET],[' &&
+ $GNULIB_SRCDIR/gnulib-tool --extract-autoconf-snippet $gnulib_modules &&
+ echo '])'
+) >m4/gnulib.m4 || exit
+
+(echo '# This file is generated automatically by "bootstrap".' &&
+ $GNULIB_SRCDIR/gnulib-tool --extract-automake-snippet $gnulib_modules
+) >lib/gnulib.mk || exit
+
+
+echo "$0: done. Now you can run './configure'."
diff --git a/contrib/diff/doc/Makefile.am b/contrib/diff/doc/Makefile.am
new file mode 100644
index 0000000..574fdab
--- /dev/null
+++ b/contrib/diff/doc/Makefile.am
@@ -0,0 +1,24 @@
+# Makefile for GNU diffutils documentation.
+
+# Copyright (C) 2001, 2002 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+AM_MAKEINFOFLAGS = --no-split
+
+info_TEXINFOS = diff.texi
+diff_TEXINFOS = fdl.texi
+
+EXTRA_DIST = diagmeet.note
diff --git a/contrib/diff/doc/diagmeet.note b/contrib/diff/doc/diagmeet.note
new file mode 100644
index 0000000..8f7242c
--- /dev/null
+++ b/contrib/diff/doc/diagmeet.note
@@ -0,0 +1,71 @@
+Here is a comparison matrix which shows a case in which
+it is possible for the forward and backward scan in `diag'
+to meet along a nonzero length of diagonal simultaneous
+(so that bdiag[d] and fdiag[d] are not equal)
+even though there is no snake on that diagonal at the meeting point.
+
+
+ 85 1 1 1 159 1 1 17
+ 1 2 3 4
+60
+ 1 2
+1
+ 2 2 3 4
+71
+ 3 3 4 5
+85
+ 4 3 4 5
+17
+ 5 4 5
+1
+ 6 4 5 6
+183
+ 7 5 6 7
+10
+ 8 6 7
+1
+ 9 6 7 8
+12
+ 7 8 9 10
+13
+ 10 8 9 10
+14
+ 10 9 10
+17
+ 10 10
+1
+ 10 9 10
+1
+ 8 10 10 10
+183
+ 8 7 9 9 9
+10
+ 7 6 8 9 8 8
+1
+ 6 5 7 7
+1
+ 5 6 6
+1
+ 5 5 5
+50
+ 5 4 4 4
+1
+ 4 3 3
+85
+ 5 4 3 2 2
+1
+ 2 1
+17
+ 5 4 3 2 1 1
+1
+ 1 0
+ 85 1 1 1 159 1 1 17
+
+
+
+
+
+
+
+
+
diff --git a/contrib/diff/doc/diff.texi b/contrib/diff/doc/diff.texi
new file mode 100644
index 0000000..a8724f4
--- /dev/null
+++ b/contrib/diff/doc/diff.texi
@@ -0,0 +1,4649 @@
+\input texinfo @c -*-texinfo-*-
+@comment $Id: diff.texi,v 1.25 2004/04/12 07:44:35 eggert Exp $
+@comment %**start of header
+@setfilename diff.info
+@include version.texi
+@settitle Comparing and Merging Files
+@syncodeindex vr cp
+@setchapternewpage odd
+@comment %**end of header
+@copying
+This manual is for GNU Diffutils
+(version @value{VERSION}, @value{UPDATED}),
+and documents the @acronym{GNU} @command{diff}, @command{diff3},
+@command{sdiff}, and @command{cmp} commands for showing the
+differences between files and the @acronym{GNU} @command{patch} command for
+using their output to update files.
+
+Copyright @copyright{} 1992, 1993, 1994, 1998, 2001, 2002, 2004 Free
+Software Foundation, Inc.
+
+@quotation
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.1 or
+any later version published by the Free Software Foundation; with no
+Invariant Sections, with the Front-Cover texts being ``A GNU Manual,''
+and with the Back-Cover Texts as in (a) below. A copy of the
+license is included in the section entitled ``GNU Free Documentation
+License.''
+
+(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify
+this GNU Manual, like GNU software. Copies published by the Free
+Software Foundation raise funds for GNU development.''
+@end quotation
+@end copying
+
+@c Debian install-info (up through at least version 1.9.20) uses only the
+@c first dircategory. Put this one first, as it is more useful in practice.
+@dircategory Individual utilities
+@direntry
+* cmp: (diff)Invoking cmp. Compare 2 files byte by byte.
+* diff: (diff)Invoking diff. Compare 2 files line by line.
+* diff3: (diff)Invoking diff3. Compare 3 files line by line.
+* patch: (diff)Invoking patch. Apply a patch to a file.
+* sdiff: (diff)Invoking sdiff. Merge 2 files side-by-side.
+@end direntry
+
+@dircategory Text creation and manipulation
+@direntry
+* Diff: (diff). Comparing and merging files.
+@end direntry
+
+@titlepage
+@title Comparing and Merging Files
+@subtitle for Diffutils @value{VERSION} and @code{patch} 2.5.4
+@subtitle @value{UPDATED}
+@author David MacKenzie, Paul Eggert, and Richard Stallman
+@page
+@vskip 0pt plus 1filll
+@insertcopying
+@end titlepage
+
+@shortcontents
+@contents
+
+@ifnottex
+@node Top
+@top Comparing and Merging Files
+
+@insertcopying
+@end ifnottex
+
+@menu
+* Overview:: Preliminary information.
+* Comparison:: What file comparison means.
+
+* Output Formats:: Formats for two-way difference reports.
+* Incomplete Lines:: Lines that lack trailing newlines.
+* Comparing Directories:: Comparing files and directories.
+* Adjusting Output:: Making @command{diff} output prettier.
+* diff Performance:: Making @command{diff} smarter or faster.
+
+* Comparing Three Files:: Formats for three-way difference reports.
+* diff3 Merging:: Merging from a common ancestor.
+
+* Interactive Merging:: Interactive merging with @command{sdiff}.
+
+* Merging with patch:: Using @command{patch} to change old files into new ones.
+* Making Patches:: Tips for making and using patch distributions.
+
+* Invoking cmp:: Compare two files byte by byte.
+* Invoking diff:: Compare two files line by line.
+* Invoking diff3:: Compare three files line by line.
+* Invoking patch:: Apply a diff file to an original.
+* Invoking sdiff:: Side-by-side merge of file differences.
+
+* Standards conformance:: Conformance to the @acronym{POSIX} standard.
+* Projects:: If you've found a bug or other shortcoming.
+
+* Copying This Manual:: How to make copies of this manual.
+* Translations:: Available translations of this manual.
+* Index:: Index.
+@end menu
+
+@node Overview
+@unnumbered Overview
+@cindex overview of @command{diff} and @command{patch}
+
+Computer users often find occasion to ask how two files differ. Perhaps
+one file is a newer version of the other file. Or maybe the two files
+started out as identical copies but were changed by different people.
+
+You can use the @command{diff} command to show differences between two
+files, or each corresponding file in two directories. @command{diff}
+outputs differences between files line by line in any of several
+formats, selectable by command line options. This set of differences is
+often called a @dfn{diff} or @dfn{patch}. For files that are identical,
+@command{diff} normally produces no output; for binary (non-text) files,
+@command{diff} normally reports only that they are different.
+
+You can use the @command{cmp} command to show the byte and line numbers
+where two files differ. @command{cmp} can also show all the bytes
+that differ between the two files, side by side. A way to compare
+two files character by character is the Emacs command @kbd{M-x
+compare-windows}. @xref{Other Window, , Other Window, emacs, The @acronym{GNU}
+Emacs Manual}, for more information on that command.
+
+You can use the @command{diff3} command to show differences among three
+files. When two people have made independent changes to a common
+original, @command{diff3} can report the differences between the original
+and the two changed versions, and can produce a merged file that
+contains both persons' changes together with warnings about conflicts.
+
+You can use the @command{sdiff} command to merge two files interactively.
+
+You can use the set of differences produced by @command{diff} to distribute
+updates to text files (such as program source code) to other people.
+This method is especially useful when the differences are small compared
+to the complete files. Given @command{diff} output, you can use the
+@command{patch} program to update, or @dfn{patch}, a copy of the file. If you
+think of @command{diff} as subtracting one file from another to produce
+their difference, you can think of @command{patch} as adding the difference
+to one file to reproduce the other.
+
+This manual first concentrates on making diffs, and later shows how to
+use diffs to update files.
+
+@acronym{GNU} @command{diff} was written by Paul Eggert, Mike Haertel,
+David Hayes, Richard Stallman, and Len Tower. Wayne Davison designed and
+implemented the unified output format. The basic algorithm is described
+by Eugene W. Myers in ``An O(ND) Difference Algorithm and its Variations'',
+@cite{Algorithmica} Vol.@: 1 No.@: 2, 1986, pp.@: 251--266; and in ``A File
+Comparison Program'', Webb Miller and Eugene W. Myers,
+@cite{Software---Practice and Experience} Vol.@: 15 No.@: 11, 1985,
+pp.@: 1025--1040.
+@c From: "Gene Myers" <gene@cs.arizona.edu>
+@c They are about the same basic algorithm; the Algorithmica
+@c paper gives a rigorous treatment and the sub-algorithm for
+@c delivering scripts and should be the primary reference, but
+@c both should be mentioned.
+The algorithm was independently discovered as described by E. Ukkonen in
+``Algorithms for Approximate String Matching'',
+@cite{Information and Control} Vol.@: 64, 1985, pp.@: 100--118.
+@c From: "Gene Myers" <gene@cs.arizona.edu>
+@c Date: Wed, 29 Sep 1993 08:27:55 MST
+@c Ukkonen should be given credit for also discovering the algorithm used
+@c in GNU diff.
+Unless the @option{--minimal} option is used, @command{diff} uses a
+heuristic by Paul Eggert that limits the cost to @math{O(N^1.5 log N)}
+at the price of producing suboptimal output for large inputs with many
+differences. Related algorithms are surveyed by Alfred V. Aho in
+section 6.3 of ``Algorithms for Finding Patterns in Strings'',
+@cite{Handbook of Theoretical Computer Science} (Jan Van Leeuwen,
+ed.), Vol.@: A, @cite{Algorithms and Complexity}, Elsevier/MIT Press,
+1990, pp.@: 255--300.
+
+@acronym{GNU} @command{diff3} was written by Randy Smith. @acronym{GNU}
+@command{sdiff} was written by Thomas Lord. @acronym{GNU} @command{cmp}
+was written by Torbj@"orn Granlund and David MacKenzie.
+
+@acronym{GNU} @command{patch} was written mainly by Larry Wall and Paul Eggert;
+several @acronym{GNU} enhancements were contributed by Wayne Davison and
+David MacKenzie. Parts of this manual are adapted from a manual page
+written by Larry Wall, with his permission.
+
+@node Comparison
+@chapter What Comparison Means
+@cindex introduction
+
+There are several ways to think about the differences between two files.
+One way to think of the differences is as a series of lines that were
+deleted from, inserted in, or changed in one file to produce the other
+file. @command{diff} compares two files line by line, finds groups of
+lines that differ, and reports each group of differing lines. It can
+report the differing lines in several formats, which have different
+purposes.
+
+@acronym{GNU} @command{diff} can show whether files are different
+without detailing the differences. It also provides ways to suppress
+certain kinds of differences that are not important to you. Most
+commonly, such differences are changes in the amount of white space
+between words or lines. @command{diff} also provides ways to suppress
+differences in alphabetic case or in lines that match a regular
+expression that you provide. These options can accumulate; for
+example, you can ignore changes in both white space and alphabetic
+case.
+
+Another way to think of the differences between two files is as a
+sequence of pairs of bytes that can be either identical or
+different. @command{cmp} reports the differences between two files
+byte by byte, instead of line by line. As a result, it is often
+more useful than @command{diff} for comparing binary files. For text
+files, @command{cmp} is useful mainly when you want to know only whether
+two files are identical, or whether one file is a prefix of the other.
+
+To illustrate the effect that considering changes byte by byte
+can have compared with considering them line by line, think of what
+happens if a single newline character is added to the beginning of a
+file. If that file is then compared with an otherwise identical file
+that lacks the newline at the beginning, @command{diff} will report that a
+blank line has been added to the file, while @command{cmp} will report that
+almost every byte of the two files differs.
+
+@command{diff3} normally compares three input files line by line, finds
+groups of lines that differ, and reports each group of differing lines.
+Its output is designed to make it easy to inspect two different sets of
+changes to the same file.
+
+@menu
+* Hunks:: Groups of differing lines.
+* White Space:: Suppressing differences in white space.
+* Blank Lines:: Suppressing differences whose lines are all blank.
+* Specified Lines:: Suppressing differences whose lines all match a pattern.
+* Case Folding:: Suppressing differences in alphabetic case.
+* Brief:: Summarizing which files are different.
+* Binary:: Comparing binary files or forcing text comparisons.
+@end menu
+
+@node Hunks
+@section Hunks
+@cindex hunks
+
+When comparing two files, @command{diff} finds sequences of lines common to
+both files, interspersed with groups of differing lines called
+@dfn{hunks}. Comparing two identical files yields one sequence of
+common lines and no hunks, because no lines differ. Comparing two
+entirely different files yields no common lines and one large hunk that
+contains all lines of both files. In general, there are many ways to
+match up lines between two given files. @command{diff} tries to minimize
+the total hunk size by finding large sequences of common lines
+interspersed with small hunks of differing lines.
+
+For example, suppose the file @file{F} contains the three lines
+@samp{a}, @samp{b}, @samp{c}, and the file @file{G} contains the same
+three lines in reverse order @samp{c}, @samp{b}, @samp{a}. If
+@command{diff} finds the line @samp{c} as common, then the command
+@samp{diff F G} produces this output:
+
+@example
+1,2d0
+< a
+< b
+3a2,3
+> b
+> a
+@end example
+
+@noindent
+But if @command{diff} notices the common line @samp{b} instead, it produces
+this output:
+
+@example
+1c1
+< a
+---
+> c
+3c3
+< c
+---
+> a
+@end example
+
+@noindent
+It is also possible to find @samp{a} as the common line. @command{diff}
+does not always find an optimal matching between the files; it takes
+shortcuts to run faster. But its output is usually close to the
+shortest possible. You can adjust this tradeoff with the
+@option{-d} or @option{--minimal} option (@pxref{diff Performance}).
+
+@node White Space
+@section Suppressing Differences in Blank and Tab Spacing
+@cindex blank and tab difference suppression
+@cindex tab and blank difference suppression
+
+The @option{-E} or @option{--ignore-tab-expansion} option ignores the
+distinction between tabs and spaces on input. A tab is considered to be
+equivalent to the number of spaces to the next tab stop (@pxref{Tabs}).
+
+The @option{-b} or @option{--ignore-space-change} option is stronger.
+It ignores white space at line end, and considers all other sequences of
+one or more white space characters within a line to be equivalent. With this
+option, @command{diff} considers the following two lines to be equivalent,
+where @samp{$} denotes the line end:
+
+@example
+Here lyeth muche rychnesse in lytell space. -- John Heywood$
+Here lyeth muche rychnesse in lytell space. -- John Heywood $
+@end example
+
+The @option{-w} or @option{--ignore-all-space} option is stronger still.
+It ignores differences even if one line has white space where
+the other line has none. @dfn{White space} characters include
+tab, newline, vertical tab, form feed, carriage return, and space;
+some locales may define additional characters to be white space.
+With this option, @command{diff} considers the
+following two lines to be equivalent, where @samp{$} denotes the line
+end and @samp{^M} denotes a carriage return:
+
+@example
+Here lyeth muche rychnesse in lytell space.-- John Heywood$
+ He relyeth much erychnes seinly tells pace. --John Heywood ^M$
+@end example
+
+@node Blank Lines
+@section Suppressing Differences Whose Lines Are All Blank
+@cindex blank line difference suppression
+
+The @option{-B} or @option{--ignore-blank-lines} option ignores changes
+that consist entirely of blank lines. With this option, for example, a
+file containing
+@example
+1. A point is that which has no part.
+
+2. A line is breadthless length.
+-- Euclid, The Elements, I
+@end example
+@noindent
+is considered identical to a file containing
+@example
+1. A point is that which has no part.
+2. A line is breadthless length.
+
+
+-- Euclid, The Elements, I
+@end example
+
+Normally this option affects only lines that are completely empty, but
+if you also specify the @option{-b} or @option{--ignore-space-change}
+option, or the @option{-w} or @option{--ignore-all-space} option,
+lines are also affected if they look empty but contain white space.
+In other words, @option{-B} is equivalent to @samp{-I '^$'} by
+default, but it is equivalent to @option{-I '^[[:space:]]*$'} if
+@option{-b} or @option{-w} is also specified.
+
+@node Specified Lines
+@section Suppressing Differences Whose Lines All Match a Regular Expression
+@cindex regular expression suppression
+
+To ignore insertions and deletions of lines that match a
+@command{grep}-style regular expression, use the @option{-I
+@var{regexp}} or @option{--ignore-matching-lines=@var{regexp}} option.
+You should escape
+regular expressions that contain shell metacharacters to prevent the
+shell from expanding them. For example, @samp{diff -I '^[[:digit:]]'} ignores
+all changes to lines beginning with a digit.
+
+However, @option{-I} only ignores the insertion or deletion of lines that
+contain the regular expression if every changed line in the hunk---every
+insertion and every deletion---matches the regular expression. In other
+words, for each nonignorable change, @command{diff} prints the complete set
+of changes in its vicinity, including the ignorable ones.
+
+You can specify more than one regular expression for lines to ignore by
+using more than one @option{-I} option. @command{diff} tries to match each
+line against each regular expression.
+
+@node Case Folding
+@section Suppressing Case Differences
+@cindex case difference suppression
+
+@acronym{GNU} @command{diff} can treat lower case letters as
+equivalent to their upper case counterparts, so that, for example, it
+considers @samp{Funky Stuff}, @samp{funky STUFF}, and @samp{fUNKy
+stuFf} to all be the same. To request this, use the @option{-i} or
+@option{--ignore-case} option.
+
+@node Brief
+@section Summarizing Which Files Differ
+@cindex summarizing which files differ
+@cindex brief difference reports
+
+When you only want to find out whether files are different, and you
+don't care what the differences are, you can use the summary output
+format. In this format, instead of showing the differences between the
+files, @command{diff} simply reports whether files differ. The @option{-q}
+or @option{--brief} option selects this output format.
+
+This format is especially useful when comparing the contents of two
+directories. It is also much faster than doing the normal line by line
+comparisons, because @command{diff} can stop analyzing the files as soon as
+it knows that there are any differences.
+
+You can also get a brief indication of whether two files differ by using
+@command{cmp}. For files that are identical, @command{cmp} produces no
+output. When the files differ, by default, @command{cmp} outputs the byte
+and line number where the first difference occurs, or reports that one
+file is a prefix of the other. You can use
+the @option{-s}, @option{--quiet}, or @option{--silent} option to
+suppress that information, so that @command{cmp}
+produces no output and reports whether the files differ using only its
+exit status (@pxref{Invoking cmp}).
+
+@c Fix this.
+Unlike @command{diff}, @command{cmp} cannot compare directories; it can only
+compare two files.
+
+@node Binary
+@section Binary Files and Forcing Text Comparisons
+@cindex binary file diff
+@cindex text versus binary diff
+
+If @command{diff} thinks that either of the two files it is comparing is
+binary (a non-text file), it normally treats that pair of files much as
+if the summary output format had been selected (@pxref{Brief}), and
+reports only that the binary files are different. This is because line
+by line comparisons are usually not meaningful for binary files.
+
+@command{diff} determines whether a file is text or binary by checking the
+first few bytes in the file; the exact number of bytes is system
+dependent, but it is typically several thousand. If every byte in
+that part of the file is non-null, @command{diff} considers the file to be
+text; otherwise it considers the file to be binary.
+
+Sometimes you might want to force @command{diff} to consider files to be
+text. For example, you might be comparing text files that contain
+null characters; @command{diff} would erroneously decide that those are
+non-text files. Or you might be comparing documents that are in a
+format used by a word processing system that uses null characters to
+indicate special formatting. You can force @command{diff} to consider all
+files to be text files, and compare them line by line, by using the
+@option{-a} or @option{--text} option. If the files you compare using this
+option do not in fact contain text, they will probably contain few
+newline characters, and the @command{diff} output will consist of hunks
+showing differences between long lines of whatever characters the files
+contain.
+
+You can also force @command{diff} to report only whether files differ
+(but not how). Use the @option{-q} or @option{--brief} option for
+this.
+
+Normally, differing binary files count as trouble because the
+resulting @command{diff} output does not capture all the differences.
+This trouble causes @command{diff} to exit with status 2. However,
+this trouble cannot occur with the @option{-a} or @option{--text}
+option, or with the @option{-q} or @option{--brief} option, as these
+options both cause @command{diff} to generate a form of output that
+represents differences as requested.
+
+In operating systems that distinguish between text and binary files,
+@command{diff} normally reads and writes all data as text. Use the
+@option{--binary} option to force @command{diff} to read and write binary
+data instead. This option has no effect on a @acronym{POSIX}-compliant system
+like @acronym{GNU} or traditional Unix. However, many personal computer
+operating systems represent the end of a line with a carriage return
+followed by a newline. On such systems, @command{diff} normally ignores
+these carriage returns on input and generates them at the end of each
+output line, but with the @option{--binary} option @command{diff} treats
+each carriage return as just another input character, and does not
+generate a carriage return at the end of each output line. This can be
+useful when dealing with non-text files that are meant to be
+interchanged with @acronym{POSIX}-compliant systems.
+
+The @option{--strip-trailing-cr} causes @command{diff} to treat input
+lines that end in carriage return followed by newline as if they end
+in plain newline. This can be useful when comparing text that is
+imperfectly imported from many personal computer operating systems.
+This option affects how lines are read, which in turn affects how they
+are compared and output.
+
+If you want to compare two files byte by byte, you can use the
+@command{cmp} program with the @option{-l} or @option{--verbose}
+option to show the values of each differing byte in the two files.
+With @acronym{GNU} @command{cmp}, you can also use the @option{-b} or
+@option{--print-bytes} option to show the @acronym{ASCII} representation of
+those bytes. @xref{Invoking cmp}, for more information.
+
+If @command{diff3} thinks that any of the files it is comparing is binary
+(a non-text file), it normally reports an error, because such
+comparisons are usually not useful. @command{diff3} uses the same test as
+@command{diff} to decide whether a file is binary. As with @command{diff}, if
+the input files contain a few non-text bytes but otherwise are like
+text files, you can force @command{diff3} to consider all files to be text
+files and compare them line by line by using the @option{-a} or
+@option{--text} option.
+
+@node Output Formats
+@chapter @command{diff} Output Formats
+@cindex output formats
+@cindex format of @command{diff} output
+
+@command{diff} has several mutually exclusive options for output format.
+The following sections describe each format, illustrating how
+@command{diff} reports the differences between two sample input files.
+
+@menu
+* Sample diff Input:: Sample @command{diff} input files for examples.
+* Context:: Showing differences with the surrounding text.
+* Side by Side:: Showing differences in two columns.
+* Normal:: Showing differences without surrounding text.
+* Scripts:: Generating scripts for other programs.
+* If-then-else:: Merging files with if-then-else.
+@end menu
+
+@node Sample diff Input
+@section Two Sample Input Files
+@cindex @command{diff} sample input
+@cindex sample input for @command{diff}
+
+Here are two sample files that we will use in numerous examples to
+illustrate the output of @command{diff} and how various options can change
+it.
+
+This is the file @file{lao}:
+
+@example
+The Way that can be told of is not the eternal Way;
+The name that can be named is not the eternal name.
+The Nameless is the origin of Heaven and Earth;
+The Named is the mother of all things.
+Therefore let there always be non-being,
+ so we may see their subtlety,
+And let there always be being,
+ so we may see their outcome.
+The two are the same,
+But after they are produced,
+ they have different names.
+@end example
+
+This is the file @file{tzu}:
+
+@example
+The Nameless is the origin of Heaven and Earth;
+The named is the mother of all things.
+
+Therefore let there always be non-being,
+ so we may see their subtlety,
+And let there always be being,
+ so we may see their outcome.
+The two are the same,
+But after they are produced,
+ they have different names.
+They both may be called deep and profound.
+Deeper and more profound,
+The door of all subtleties!
+@end example
+
+In this example, the first hunk contains just the first two lines of
+@file{lao}, the second hunk contains the fourth line of @file{lao}
+opposing the second and third lines of @file{tzu}, and the last hunk
+contains just the last three lines of @file{tzu}.
+
+@node Context
+@section Showing Differences in Their Context
+@cindex context output format
+@cindex @samp{!} output format
+
+Usually, when you are looking at the differences between files, you will
+also want to see the parts of the files near the lines that differ, to
+help you understand exactly what has changed. These nearby parts of the
+files are called the @dfn{context}.
+
+@acronym{GNU} @command{diff} provides two output formats that show context
+around the differing lines: @dfn{context format} and @dfn{unified
+format}. It can optionally show in which function or section of the
+file the differing lines are found.
+
+If you are distributing new versions of files to other people in the
+form of @command{diff} output, you should use one of the output formats
+that show context so that they can apply the diffs even if they have
+made small changes of their own to the files. @command{patch} can apply
+the diffs in this case by searching in the files for the lines of
+context around the differing lines; if those lines are actually a few
+lines away from where the diff says they are, @command{patch} can adjust
+the line numbers accordingly and still apply the diff correctly.
+@xref{Imperfect}, for more information on using @command{patch} to apply
+imperfect diffs.
+
+@menu
+* Context Format:: An output format that shows surrounding lines.
+* Unified Format:: A more compact output format that shows context.
+* Sections:: Showing which sections of the files differences are in.
+* Alternate Names:: Showing alternate file names in context headers.
+@end menu
+
+@node Context Format
+@subsection Context Format
+
+The context output format shows several lines of context around the
+lines that differ. It is the standard format for distributing updates
+to source code.
+
+To select this output format, use the @option{-C @var{lines}},
+@option{--context@r{[}=@var{lines}@r{]}}, or @option{-c} option. The
+argument @var{lines} that some of these options take is the number of
+lines of context to show. If you do not specify @var{lines}, it
+defaults to three. For proper operation, @command{patch} typically needs
+at least two lines of context.
+
+@menu
+* Example Context:: Sample output in context format.
+* Less Context:: Another sample with less context.
+* Detailed Context:: A detailed description of the context output format.
+@end menu
+
+@node Example Context
+@subsubsection An Example of Context Format
+
+Here is the output of @samp{diff -c lao tzu} (@pxref{Sample diff Input},
+for the complete contents of the two files). Notice that up to three
+lines that are not different are shown around each line that is
+different; they are the context lines. Also notice that the first two
+hunks have run together, because their contents overlap.
+
+@example
+*** lao 2002-02-21 23:30:39.942229878 -0800
+--- tzu 2002-02-21 23:30:50.442260588 -0800
+***************
+*** 1,7 ****
+- The Way that can be told of is not the eternal Way;
+- The name that can be named is not the eternal name.
+ The Nameless is the origin of Heaven and Earth;
+! The Named is the mother of all things.
+ Therefore let there always be non-being,
+ so we may see their subtlety,
+ And let there always be being,
+--- 1,6 ----
+ The Nameless is the origin of Heaven and Earth;
+! The named is the mother of all things.
+!
+ Therefore let there always be non-being,
+ so we may see their subtlety,
+ And let there always be being,
+***************
+*** 9,11 ****
+--- 8,13 ----
+ The two are the same,
+ But after they are produced,
+ they have different names.
++ They both may be called deep and profound.
++ Deeper and more profound,
++ The door of all subtleties!
+@end example
+
+@node Less Context
+@subsubsection An Example of Context Format with Less Context
+
+Here is the output of @samp{diff -C 1 lao tzu} (@pxref{Sample diff
+Input}, for the complete contents of the two files). Notice that at
+most one context line is reported here.
+
+@example
+*** lao 2002-02-21 23:30:39.942229878 -0800
+--- tzu 2002-02-21 23:30:50.442260588 -0800
+***************
+*** 1,5 ****
+- The Way that can be told of is not the eternal Way;
+- The name that can be named is not the eternal name.
+ The Nameless is the origin of Heaven and Earth;
+! The Named is the mother of all things.
+ Therefore let there always be non-being,
+--- 1,4 ----
+ The Nameless is the origin of Heaven and Earth;
+! The named is the mother of all things.
+!
+ Therefore let there always be non-being,
+***************
+*** 11 ****
+--- 10,13 ----
+ they have different names.
++ They both may be called deep and profound.
++ Deeper and more profound,
++ The door of all subtleties!
+@end example
+
+@node Detailed Context
+@subsubsection Detailed Description of Context Format
+
+The context output format starts with a two-line header, which looks
+like this:
+
+@example
+*** @var{from-file} @var{from-file-modification-time}
+--- @var{to-file} @var{to-file-modification time}
+@end example
+
+@noindent
+@vindex LC_TIME
+@cindex time stamp format, context diffs
+The time stamp normally looks like @samp{2002-02-21 23:30:39.942229878
+-0800} to indicate the date, time with fractional seconds, and time
+zone in @uref{ftp://ftp.isi.edu/in-notes/rfc2822.txt, Internet RFC
+2822 format}. (The fractional seconds are omitted on hosts that do
+not support fractional time stamps.) However, a traditional time
+stamp like @samp{Thu Feb 21 23:30:39 2002} is used if the
+@env{LC_TIME} locale category is either @samp{C} or @samp{POSIX}.
+
+You can change the header's content with the
+@option{--label=@var{label}} option; see @ref{Alternate Names}.
+
+Next come one or more hunks of differences; each hunk shows one area
+where the files differ. Context format hunks look like this:
+
+@example
+***************
+*** @var{from-file-line-numbers} ****
+ @var{from-file-line}
+ @var{from-file-line}@dots{}
+--- @var{to-file-line-numbers} ----
+ @var{to-file-line}
+ @var{to-file-line}@dots{}
+@end example
+
+If a hunk contains two or more lines, its line numbers look like
+@samp{@var{start},@var{end}}. Otherwise only its end line number
+appears. An empty hunk is considered to end at the line that precedes
+the hunk.
+
+The lines of context around the lines that differ start with two space
+characters. The lines that differ between the two files start with one
+of the following indicator characters, followed by a space character:
+
+@table @samp
+@item !
+A line that is part of a group of one or more lines that changed between
+the two files. There is a corresponding group of lines marked with
+@samp{!} in the part of this hunk for the other file.
+
+@item +
+An ``inserted'' line in the second file that corresponds to nothing in
+the first file.
+
+@item -
+A ``deleted'' line in the first file that corresponds to nothing in the
+second file.
+@end table
+
+If all of the changes in a hunk are insertions, the lines of
+@var{from-file} are omitted. If all of the changes are deletions, the
+lines of @var{to-file} are omitted.
+
+@node Unified Format
+@subsection Unified Format
+@cindex unified output format
+@cindex @samp{+-} output format
+
+The unified output format is a variation on the context format that is
+more compact because it omits redundant context lines. To select this
+output format, use the @option{-U @var{lines}},
+@option{--unified@r{[}=@var{lines}@r{]}}, or @option{-u}
+option. The argument @var{lines} is the number of lines of context to
+show. When it is not given, it defaults to three.
+
+At present, only @acronym{GNU} @command{diff} can produce this format and
+only @acronym{GNU} @command{patch} can automatically apply diffs in this
+format. For proper operation, @command{patch} typically needs at
+least three lines of context.
+
+@menu
+* Example Unified:: Sample output in unified format.
+* Detailed Unified:: A detailed description of unified format.
+@end menu
+
+@node Example Unified
+@subsubsection An Example of Unified Format
+
+Here is the output of the command @samp{diff -u lao tzu}
+(@pxref{Sample diff Input}, for the complete contents of the two files):
+
+@example
+--- lao 2002-02-21 23:30:39.942229878 -0800
++++ tzu 2002-02-21 23:30:50.442260588 -0800
+@@@@ -1,7 +1,6 @@@@
+-The Way that can be told of is not the eternal Way;
+-The name that can be named is not the eternal name.
+ The Nameless is the origin of Heaven and Earth;
+-The Named is the mother of all things.
++The named is the mother of all things.
++
+ Therefore let there always be non-being,
+ so we may see their subtlety,
+ And let there always be being,
+@@@@ -9,3 +8,6 @@@@
+ The two are the same,
+ But after they are produced,
+ they have different names.
++They both may be called deep and profound.
++Deeper and more profound,
++The door of all subtleties!
+@end example
+
+@node Detailed Unified
+@subsubsection Detailed Description of Unified Format
+
+The unified output format starts with a two-line header, which looks
+like this:
+
+@example
+--- @var{from-file} @var{from-file-modification-time}
++++ @var{to-file} @var{to-file-modification-time}
+@end example
+
+@noindent
+@cindex time stamp format, unified diffs
+The time stamp looks like @samp{2002-02-21 23:30:39.942229878 -0800}
+to indicate the date, time with fractional seconds, and time zone.
+The fractional seconds are omitted on hosts that do not support
+fractional time stamps.
+
+You can change the header's content with the
+@option{--label=@var{label}} option; see @xref{Alternate Names}.
+
+Next come one or more hunks of differences; each hunk shows one area
+where the files differ. Unified format hunks look like this:
+
+@example
+@@@@ @var{from-file-line-numbers} @var{to-file-line-numbers} @@@@
+ @var{line-from-either-file}
+ @var{line-from-either-file}@dots{}
+@end example
+
+If a hunk contains just one line, only its start line number appears.
+Otherwise its line numbers look like @samp{@var{start},@var{count}}.
+An empty hunk is considered to start at the line that follows the hunk.
+
+If a hunk and its context contain two or more lines, its
+line numbers look like @samp{@var{start},@var{count}}. Otherwise only
+its end line number appears. An empty hunk is considered to end at
+the line that precedes the hunk.
+
+The lines common to both files begin with a space character. The lines
+that actually differ between the two files have one of the following
+indicator characters in the left print column:
+
+@table @samp
+@item +
+A line was added here to the first file.
+
+@item -
+A line was removed here from the first file.
+@end table
+
+@node Sections
+@subsection Showing Which Sections Differences Are in
+@cindex headings
+@cindex section headings
+
+Sometimes you might want to know which part of the files each change
+falls in. If the files are source code, this could mean which
+function was changed. If the files are documents, it could mean which
+chapter or appendix was changed. @acronym{GNU} @command{diff} can
+show this by displaying the nearest section heading line that precedes
+the differing lines. Which lines are ``section headings'' is
+determined by a regular expression.
+
+@menu
+* Specified Headings:: Showing headings that match regular expressions.
+* C Function Headings:: Showing headings of C functions.
+@end menu
+
+@node Specified Headings
+@subsubsection Showing Lines That Match Regular Expressions
+@cindex specified headings
+@cindex regular expression matching headings
+
+To show in which sections differences occur for files that are not
+source code for C or similar languages, use the @option{-F @var{regexp}}
+or @option{--show-function-line=@var{regexp}} option. @command{diff}
+considers lines that match the @command{grep}-style regular expression
+@var{regexp} to be the beginning
+of a section of the file. Here are suggested regular expressions for
+some common languages:
+
+@c Please add to this list, e.g. Fortran, Pascal, Perl, Python.
+@table @samp
+@item ^[[:alpha:]$_]
+C, C++, Prolog
+@item ^(
+Lisp
+@item ^@@node
+Texinfo
+@end table
+
+This option does not automatically select an output format; in order to
+use it, you must select the context format (@pxref{Context Format}) or
+unified format (@pxref{Unified Format}). In other output formats it
+has no effect.
+
+The @option{-F} or @option{--show-function-line} option finds the nearest
+unchanged line that precedes each hunk of differences and matches the
+given regular expression. Then it adds that line to the end of the
+line of asterisks in the context format, or to the @samp{@@@@} line in
+unified format. If no matching line exists, this option leaves the output for
+that hunk unchanged. If that line is more than 40 characters long, it
+outputs only the first 40 characters. You can specify more than one
+regular expression for such lines; @command{diff} tries to match each line
+against each regular expression, starting with the last one given. This
+means that you can use @option{-p} and @option{-F} together, if you wish.
+
+@node C Function Headings
+@subsubsection Showing C Function Headings
+@cindex C function headings
+@cindex function headings, C
+
+To show in which functions differences occur for C and similar
+languages, you can use the @option{-p} or @option{--show-c-function} option.
+This option automatically defaults to the context output format
+(@pxref{Context Format}), with the default number of lines of context.
+You can override that number with @option{-C @var{lines}} elsewhere in the
+command line. You can override both the format and the number with
+@option{-U @var{lines}} elsewhere in the command line.
+
+The @option{-p} or @option{--show-c-function} option is equivalent to
+@option{-F '^[[:alpha:]$_]'} if the unified format is specified, otherwise
+@option{-c -F '^[[:alpha:]$_]'} (@pxref{Specified Headings}). @acronym{GNU}
+@command{diff} provides this option for the sake of convenience.
+
+@node Alternate Names
+@subsection Showing Alternate File Names
+@cindex alternate file names
+@cindex file name alternates
+
+If you are comparing two files that have meaningless or uninformative
+names, you might want @command{diff} to show alternate names in the header
+of the context and unified output formats. To do this, use the
+@option{--label=@var{label}} option. The first time
+you give this option, its argument replaces the name and date of the
+first file in the header; the second time, its argument replaces the
+name and date of the second file. If you give this option more than
+twice, @command{diff} reports an error. The @option{--label} option does not
+affect the file names in the @command{pr} header when the @option{-l} or
+@option{--paginate} option is used (@pxref{Pagination}).
+
+Here are the first two lines of the output from @samp{diff -C 2
+--label=original --label=modified lao tzu}:
+
+@example
+*** original
+--- modified
+@end example
+
+@node Side by Side
+@section Showing Differences Side by Side
+@cindex side by side
+@cindex two-column output
+@cindex columnar output
+
+@command{diff} can produce a side by side difference listing of two files.
+The files are listed in two columns with a gutter between them. The
+gutter contains one of the following markers:
+
+@table @asis
+@item white space
+The corresponding lines are in common. That is, either the lines are
+identical, or the difference is ignored because of one of the
+@option{--ignore} options (@pxref{White Space}).
+
+@item @samp{|}
+The corresponding lines differ, and they are either both complete
+or both incomplete.
+
+@item @samp{<}
+The files differ and only the first file contains the line.
+
+@item @samp{>}
+The files differ and only the second file contains the line.
+
+@item @samp{(}
+Only the first file contains the line, but the difference is ignored.
+
+@item @samp{)}
+Only the second file contains the line, but the difference is ignored.
+
+@item @samp{\}
+The corresponding lines differ, and only the first line is incomplete.
+
+@item @samp{/}
+The corresponding lines differ, and only the second line is incomplete.
+@end table
+
+Normally, an output line is incomplete if and only if the lines that it
+contains are incomplete; @xref{Incomplete Lines}. However, when an
+output line represents two differing lines, one might be incomplete
+while the other is not. In this case, the output line is complete,
+but its the gutter is marked @samp{\} if the first line is incomplete,
+@samp{/} if the second line is.
+
+Side by side format is sometimes easiest to read, but it has limitations.
+It generates much wider output than usual, and truncates lines that are
+too long to fit. Also, it relies on lining up output more heavily than
+usual, so its output looks particularly bad if you use varying
+width fonts, nonstandard tab stops, or nonprinting characters.
+
+You can use the @command{sdiff} command to interactively merge side by side
+differences. @xref{Interactive Merging}, for more information on merging files.
+
+@menu
+* Side by Side Format:: Controlling side by side output format.
+* Example Side by Side:: Sample side by side output.
+@end menu
+
+@node Side by Side Format
+@subsection Controlling Side by Side Format
+@cindex side by side format
+
+The @option{-y} or @option{--side-by-side} option selects side by side
+format. Because side by side output lines contain two input lines, the
+output is wider than usual: normally 130 print columns, which can fit
+onto a traditional printer line. You can set the width of the output
+with the @option{-W @var{columns}} or @option{--width=@var{columns}}
+option. The output is split into two halves of equal width, separated by a
+small gutter to mark differences; the right half is aligned to a tab
+stop so that tabs line up. Input lines that are too long to fit in half
+of an output line are truncated for output.
+
+The @option{--left-column} option prints only the left column of two
+common lines. The @option{--suppress-common-lines} option suppresses
+common lines entirely.
+
+@node Example Side by Side
+@subsection An Example of Side by Side Format
+
+Here is the output of the command @samp{diff -y -W 72 lao tzu}
+(@pxref{Sample diff Input}, for the complete contents of the two files).
+
+@example
+The Way that can be told of is n <
+The name that can be named is no <
+The Nameless is the origin of He The Nameless is the origin of He
+The Named is the mother of all t | The named is the mother of all t
+ >
+Therefore let there always be no Therefore let there always be no
+ so we may see their subtlety, so we may see their subtlety,
+And let there always be being, And let there always be being,
+ so we may see their outcome. so we may see their outcome.
+The two are the same, The two are the same,
+But after they are produced, But after they are produced,
+ they have different names. they have different names.
+ > They both may be called deep and
+ > Deeper and more profound,
+ > The door of all subtleties!
+@end example
+
+@node Normal
+@section Showing Differences Without Context
+@cindex normal output format
+@cindex @samp{<} output format
+
+The ``normal'' @command{diff} output format shows each hunk of differences
+without any surrounding context. Sometimes such output is the clearest
+way to see how lines have changed, without the clutter of nearby
+unchanged lines (although you can get similar results with the context
+or unified formats by using 0 lines of context). However, this format
+is no longer widely used for sending out patches; for that purpose, the
+context format (@pxref{Context Format}) and the unified format
+(@pxref{Unified Format}) are superior. Normal format is the default for
+compatibility with older versions of @command{diff} and the @acronym{POSIX}
+standard. Use the @option{--normal} option to select this output
+format explicitly.
+
+@menu
+* Example Normal:: Sample output in the normal format.
+* Detailed Normal:: A detailed description of normal output format.
+@end menu
+
+@node Example Normal
+@subsection An Example of Normal Format
+
+Here is the output of the command @samp{diff lao tzu}
+(@pxref{Sample diff Input}, for the complete contents of the two files).
+Notice that it shows only the lines that are different between the two
+files.
+
+@example
+1,2d0
+< The Way that can be told of is not the eternal Way;
+< The name that can be named is not the eternal name.
+4c2,3
+< The Named is the mother of all things.
+---
+> The named is the mother of all things.
+>
+11a11,13
+> They both may be called deep and profound.
+> Deeper and more profound,
+> The door of all subtleties!
+@end example
+
+@node Detailed Normal
+@subsection Detailed Description of Normal Format
+
+The normal output format consists of one or more hunks of differences;
+each hunk shows one area where the files differ. Normal format hunks
+look like this:
+
+@example
+@var{change-command}
+< @var{from-file-line}
+< @var{from-file-line}@dots{}
+---
+> @var{to-file-line}
+> @var{to-file-line}@dots{}
+@end example
+
+There are three types of change commands. Each consists of a line
+number or comma-separated range of lines in the first file, a single
+character indicating the kind of change to make, and a line number or
+comma-separated range of lines in the second file. All line numbers are
+the original line numbers in each file. The types of change commands
+are:
+
+@table @samp
+@item @var{l}a@var{r}
+Add the lines in range @var{r} of the second file after line @var{l} of
+the first file. For example, @samp{8a12,15} means append lines 12--15
+of file 2 after line 8 of file 1; or, if changing file 2 into file 1,
+delete lines 12--15 of file 2.
+
+@item @var{f}c@var{t}
+Replace the lines in range @var{f} of the first file with lines in range
+@var{t} of the second file. This is like a combined add and delete, but
+more compact. For example, @samp{5,7c8,10} means change lines 5--7 of
+file 1 to read as lines 8--10 of file 2; or, if changing file 2 into
+file 1, change lines 8--10 of file 2 to read as lines 5--7 of file 1.
+
+@item @var{r}d@var{l}
+Delete the lines in range @var{r} from the first file; line @var{l} is where
+they would have appeared in the second file had they not been deleted.
+For example, @samp{5,7d3} means delete lines 5--7 of file 1; or, if
+changing file 2 into file 1, append lines 5--7 of file 1 after line 3 of
+file 2.
+@end table
+
+@node Scripts
+@section Making Edit Scripts
+@cindex script output formats
+
+Several output modes produce command scripts for editing @var{from-file}
+to produce @var{to-file}.
+
+@menu
+* ed Scripts:: Using @command{diff} to produce commands for @command{ed}.
+* Forward ed:: Making forward @command{ed} scripts.
+* RCS:: A special @command{diff} output format used by @acronym{RCS}.
+@end menu
+
+@node ed Scripts
+@subsection @command{ed} Scripts
+@cindex @command{ed} script output format
+
+@command{diff} can produce commands that direct the @command{ed} text editor
+to change the first file into the second file. Long ago, this was the
+only output mode that was suitable for editing one file into another
+automatically; today, with @command{patch}, it is almost obsolete. Use the
+@option{-e} or @option{--ed} option to select this output format.
+
+Like the normal format (@pxref{Normal}), this output format does not
+show any context; unlike the normal format, it does not include the
+information necessary to apply the diff in reverse (to produce the first
+file if all you have is the second file and the diff).
+
+If the file @file{d} contains the output of @samp{diff -e old new}, then
+the command @samp{(cat d && echo w) | ed - old} edits @file{old} to make
+it a copy of @file{new}. More generally, if @file{d1}, @file{d2},
+@dots{}, @file{dN} contain the outputs of @samp{diff -e old new1},
+@samp{diff -e new1 new2}, @dots{}, @samp{diff -e newN-1 newN},
+respectively, then the command @samp{(cat d1 d2 @dots{} dN && echo w) |
+ed - old} edits @file{old} to make it a copy of @file{newN}.
+
+@menu
+* Example ed:: A sample @command{ed} script.
+* Detailed ed:: A detailed description of @command{ed} format.
+@end menu
+
+@node Example ed
+@subsubsection Example @command{ed} Script
+
+Here is the output of @samp{diff -e lao tzu} (@pxref{Sample
+diff Input}, for the complete contents of the two files):
+
+@example
+11a
+They both may be called deep and profound.
+Deeper and more profound,
+The door of all subtleties!
+.
+4c
+The named is the mother of all things.
+
+.
+1,2d
+@end example
+
+@node Detailed ed
+@subsubsection Detailed Description of @command{ed} Format
+
+The @command{ed} output format consists of one or more hunks of
+differences. The changes closest to the ends of the files come first so
+that commands that change the number of lines do not affect how
+@command{ed} interprets line numbers in succeeding commands. @command{ed}
+format hunks look like this:
+
+@example
+@var{change-command}
+@var{to-file-line}
+@var{to-file-line}@dots{}
+.
+@end example
+
+Because @command{ed} uses a single period on a line to indicate the
+end of input, @acronym{GNU} @command{diff} protects lines of changes
+that contain a single period on a line by writing two periods instead,
+then writing a subsequent @command{ed} command to change the two
+periods into one. The @command{ed} format cannot represent an
+incomplete line, so if the second file ends in a changed incomplete
+line, @command{diff} reports an error and then pretends that a newline
+was appended.
+
+There are three types of change commands. Each consists of a line
+number or comma-separated range of lines in the first file and a single
+character indicating the kind of change to make. All line numbers are
+the original line numbers in the file. The types of change commands
+are:
+
+@table @samp
+@item @var{l}a
+Add text from the second file after line @var{l} in the first file. For
+example, @samp{8a} means to add the following lines after line 8 of file
+1.
+
+@item @var{r}c
+Replace the lines in range @var{r} in the first file with the following
+lines. Like a combined add and delete, but more compact. For example,
+@samp{5,7c} means change lines 5--7 of file 1 to read as the text file
+2.
+
+@item @var{r}d
+Delete the lines in range @var{r} from the first file. For example,
+@samp{5,7d} means delete lines 5--7 of file 1.
+@end table
+
+@node Forward ed
+@subsection Forward @command{ed} Scripts
+@cindex forward @command{ed} script output format
+
+@command{diff} can produce output that is like an @command{ed} script, but
+with hunks in forward (front to back) order. The format of the commands
+is also changed slightly: command characters precede the lines they
+modify, spaces separate line numbers in ranges, and no attempt is made
+to disambiguate hunk lines consisting of a single period. Like
+@command{ed} format, forward @command{ed} format cannot represent incomplete
+lines.
+
+Forward @command{ed} format is not very useful, because neither @command{ed}
+nor @command{patch} can apply diffs in this format. It exists mainly for
+compatibility with older versions of @command{diff}. Use the @option{-f} or
+@option{--forward-ed} option to select it.
+
+@node RCS
+@subsection @acronym{RCS} Scripts
+@cindex @acronym{RCS} script output format
+
+The @acronym{RCS} output format is designed specifically for use by
+the Revision Control System, which is a set of free programs used for
+organizing different versions and systems of files. Use the
+@option{-n} or @option{--rcs} option to select this output format. It
+is like the forward @command{ed} format (@pxref{Forward ed}), but it
+can represent arbitrary changes to the contents of a file because it
+avoids the forward @command{ed} format's problems with lines
+consisting of a single period and with incomplete lines. Instead of
+ending text sections with a line consisting of a single period, each
+command specifies the number of lines it affects; a combination of the
+@samp{a} and @samp{d} commands are used instead of @samp{c}. Also, if
+the second file ends in a changed incomplete line, then the output
+also ends in an incomplete line.
+
+Here is the output of @samp{diff -n lao tzu} (@pxref{Sample
+diff Input}, for the complete contents of the two files):
+
+@example
+d1 2
+d4 1
+a4 2
+The named is the mother of all things.
+
+a11 3
+They both may be called deep and profound.
+Deeper and more profound,
+The door of all subtleties!
+@end example
+
+@node If-then-else
+@section Merging Files with If-then-else
+@cindex merged output format
+@cindex if-then-else output format
+@cindex C if-then-else output format
+@cindex @command{ifdef} output format
+
+You can use @command{diff} to merge two files of C source code. The output
+of @command{diff} in this format contains all the lines of both files.
+Lines common to both files are output just once; the differing parts are
+separated by the C preprocessor directives @code{#ifdef @var{name}} or
+@code{#ifndef @var{name}}, @code{#else}, and @code{#endif}. When
+compiling the output, you select which version to use by either defining
+or leaving undefined the macro @var{name}.
+
+To merge two files, use @command{diff} with the @option{-D @var{name}} or
+@option{--ifdef=@var{name}} option. The argument @var{name} is the C
+preprocessor identifier to use in the @code{#ifdef} and @code{#ifndef}
+directives.
+
+For example, if you change an instance of @code{wait (&s)} to
+@code{waitpid (-1, &s, 0)} and then merge the old and new files with
+the @option{--ifdef=HAVE_WAITPID} option, then the affected part of your code
+might look like this:
+
+@example
+ do @{
+#ifndef HAVE_WAITPID
+ if ((w = wait (&s)) < 0 && errno != EINTR)
+#else /* HAVE_WAITPID */
+ if ((w = waitpid (-1, &s, 0)) < 0 && errno != EINTR)
+#endif /* HAVE_WAITPID */
+ return w;
+ @} while (w != child);
+@end example
+
+You can specify formats for languages other than C by using line group
+formats and line formats, as described in the next sections.
+
+@menu
+* Line Group Formats:: Formats for general if-then-else line groups.
+* Line Formats:: Formats for each line in a line group.
+* Example If-then-else:: Sample if-then-else format output.
+* Detailed If-then-else:: A detailed description of if-then-else format.
+@end menu
+
+@node Line Group Formats
+@subsection Line Group Formats
+@cindex line group formats
+@cindex formats for if-then-else line groups
+
+Line group formats let you specify formats suitable for many
+applications that allow if-then-else input, including programming
+languages and text formatting languages. A line group format specifies
+the output format for a contiguous group of similar lines.
+
+For example, the following command compares the TeX files @file{old}
+and @file{new}, and outputs a merged file in which old regions are
+surrounded by @samp{\begin@{em@}}-@samp{\end@{em@}} lines, and new
+regions are surrounded by @samp{\begin@{bf@}}-@samp{\end@{bf@}} lines.
+
+@example
+diff \
+ --old-group-format='\begin@{em@}
+%<\end@{em@}
+' \
+ --new-group-format='\begin@{bf@}
+%>\end@{bf@}
+' \
+ old new
+@end example
+
+The following command is equivalent to the above example, but it is a
+little more verbose, because it spells out the default line group formats.
+
+@example
+diff \
+ --old-group-format='\begin@{em@}
+%<\end@{em@}
+' \
+ --new-group-format='\begin@{bf@}
+%>\end@{bf@}
+' \
+ --unchanged-group-format='%=' \
+ --changed-group-format='\begin@{em@}
+%<\end@{em@}
+\begin@{bf@}
+%>\end@{bf@}
+' \
+ old new
+@end example
+
+Here is a more advanced example, which outputs a diff listing with
+headers containing line numbers in a ``plain English'' style.
+
+@example
+diff \
+ --unchanged-group-format='' \
+ --old-group-format='-------- %dn line%(n=1?:s) deleted at %df:
+%<' \
+ --new-group-format='-------- %dN line%(N=1?:s) added after %de:
+%>' \
+ --changed-group-format='-------- %dn line%(n=1?:s) changed at %df:
+%<-------- to:
+%>' \
+ old new
+@end example
+
+To specify a line group format, use @command{diff} with one of the options
+listed below. You can specify up to four line group formats, one for
+each kind of line group. You should quote @var{format}, because it
+typically contains shell metacharacters.
+
+@table @option
+@item --old-group-format=@var{format}
+These line groups are hunks containing only lines from the first file.
+The default old group format is the same as the changed group format if
+it is specified; otherwise it is a format that outputs the line group as-is.
+
+@item --new-group-format=@var{format}
+These line groups are hunks containing only lines from the second
+file. The default new group format is same as the changed group
+format if it is specified; otherwise it is a format that outputs the
+line group as-is.
+
+@item --changed-group-format=@var{format}
+These line groups are hunks containing lines from both files. The
+default changed group format is the concatenation of the old and new
+group formats.
+
+@item --unchanged-group-format=@var{format}
+These line groups contain lines common to both files. The default
+unchanged group format is a format that outputs the line group as-is.
+@end table
+
+In a line group format, ordinary characters represent themselves;
+conversion specifications start with @samp{%} and have one of the
+following forms.
+
+@table @samp
+@item %<
+stands for the lines from the first file, including the trailing newline.
+Each line is formatted according to the old line format (@pxref{Line Formats}).
+
+@item %>
+stands for the lines from the second file, including the trailing newline.
+Each line is formatted according to the new line format.
+
+@item %=
+stands for the lines common to both files, including the trailing newline.
+Each line is formatted according to the unchanged line format.
+
+@item %%
+stands for @samp{%}.
+
+@item %c'@var{C}'
+where @var{C} is a single character, stands for @var{C}.
+@var{C} may not be a backslash or an apostrophe.
+For example, @samp{%c':'} stands for a colon, even inside
+the then-part of an if-then-else format, which a colon would
+normally terminate.
+
+@item %c'\@var{O}'
+where @var{O} is a string of 1, 2, or 3 octal digits,
+stands for the character with octal code @var{O}.
+For example, @samp{%c'\0'} stands for a null character.
+
+@item @var{F}@var{n}
+where @var{F} is a @code{printf} conversion specification and @var{n} is one
+of the following letters, stands for @var{n}'s value formatted with @var{F}.
+
+@table @samp
+@item e
+The line number of the line just before the group in the old file.
+
+@item f
+The line number of the first line in the group in the old file;
+equals @var{e} + 1.
+
+@item l
+The line number of the last line in the group in the old file.
+
+@item m
+The line number of the line just after the group in the old file;
+equals @var{l} + 1.
+
+@item n
+The number of lines in the group in the old file; equals @var{l} - @var{f} + 1.
+
+@item E, F, L, M, N
+Likewise, for lines in the new file.
+
+@end table
+
+@vindex LC_NUMERIC
+The @code{printf} conversion specification can be @samp{%d},
+@samp{%o}, @samp{%x}, or @samp{%X}, specifying decimal, octal,
+lower case hexadecimal, or upper case hexadecimal output
+respectively. After the @samp{%} the following options can appear in
+sequence: a series of zero or more flags; an integer
+specifying the minimum field width; and a period followed by an
+optional integer specifying the minimum number of digits.
+The flags are @samp{-} for left-justification, @samp{'} for separating
+the digit into groups as specified by the @env{LC_NUMERIC} locale category,
+and @samp{0} for padding with zeros instead of spaces.
+For example, @samp{%5dN} prints the number of new lines in the group
+in a field of width 5 characters, using the @code{printf} format @code{"%5d"}.
+
+@item (@var{A}=@var{B}?@var{T}:@var{E})
+If @var{A} equals @var{B} then @var{T} else @var{E}.
+@var{A} and @var{B} are each either a decimal constant
+or a single letter interpreted as above.
+This format spec is equivalent to @var{T} if
+@var{A}'s value equals @var{B}'s; otherwise it is equivalent to @var{E}.
+
+For example, @samp{%(N=0?no:%dN) line%(N=1?:s)} is equivalent to
+@samp{no lines} if @var{N} (the number of lines in the group in the
+new file) is 0, to @samp{1 line} if @var{N} is 1, and to @samp{%dN lines}
+otherwise.
+@end table
+
+@node Line Formats
+@subsection Line Formats
+@cindex line formats
+
+Line formats control how each line taken from an input file is
+output as part of a line group in if-then-else format.
+
+For example, the following command outputs text with a one-character
+change indicator to the left of the text. The first character of output
+is @samp{-} for deleted lines, @samp{|} for added lines, and a space for
+unchanged lines. The formats contain newline characters where newlines
+are desired on output.
+
+@example
+diff \
+ --old-line-format='-%l
+' \
+ --new-line-format='|%l
+' \
+ --unchanged-line-format=' %l
+' \
+ old new
+@end example
+
+To specify a line format, use one of the following options. You should
+quote @var{format}, since it often contains shell metacharacters.
+
+@table @option
+@item --old-line-format=@var{format}
+formats lines just from the first file.
+
+@item --new-line-format=@var{format}
+formats lines just from the second file.
+
+@item --unchanged-line-format=@var{format}
+formats lines common to both files.
+
+@item --line-format=@var{format}
+formats all lines; in effect, it sets all three above options simultaneously.
+@end table
+
+In a line format, ordinary characters represent themselves;
+conversion specifications start with @samp{%} and have one of the
+following forms.
+
+@table @samp
+@item %l
+stands for the contents of the line, not counting its trailing
+newline (if any). This format ignores whether the line is incomplete;
+@xref{Incomplete Lines}.
+
+@item %L
+stands for the contents of the line, including its trailing newline
+(if any). If a line is incomplete, this format preserves its
+incompleteness.
+
+@item %%
+stands for @samp{%}.
+
+@item %c'@var{C}'
+where @var{C} is a single character, stands for @var{C}.
+@var{C} may not be a backslash or an apostrophe.
+For example, @samp{%c':'} stands for a colon.
+
+@item %c'\@var{O}'
+where @var{O} is a string of 1, 2, or 3 octal digits,
+stands for the character with octal code @var{O}.
+For example, @samp{%c'\0'} stands for a null character.
+
+@item @var{F}n
+where @var{F} is a @code{printf} conversion specification,
+stands for the line number formatted with @var{F}.
+For example, @samp{%.5dn} prints the line number using the
+@code{printf} format @code{"%.5d"}. @xref{Line Group Formats}, for
+more about printf conversion specifications.
+
+@end table
+
+The default line format is @samp{%l} followed by a newline character.
+
+If the input contains tab characters and it is important that they line
+up on output, you should ensure that @samp{%l} or @samp{%L} in a line
+format is just after a tab stop (e.g.@: by preceding @samp{%l} or
+@samp{%L} with a tab character), or you should use the @option{-t} or
+@option{--expand-tabs} option.
+
+Taken together, the line and line group formats let you specify many
+different formats. For example, the following command uses a format
+similar to normal @command{diff} format. You can tailor this command
+to get fine control over @command{diff} output.
+
+@example
+diff \
+ --old-line-format='< %l
+' \
+ --new-line-format='> %l
+' \
+ --old-group-format='%df%(f=l?:,%dl)d%dE
+%<' \
+ --new-group-format='%dea%dF%(F=L?:,%dL)
+%>' \
+ --changed-group-format='%df%(f=l?:,%dl)c%dF%(F=L?:,%dL)
+%<---
+%>' \
+ --unchanged-group-format='' \
+ old new
+@end example
+
+@node Example If-then-else
+@subsection An Example of If-then-else Format
+
+Here is the output of @samp{diff -DTWO lao tzu} (@pxref{Sample
+diff Input}, for the complete contents of the two files):
+
+@example
+#ifndef TWO
+The Way that can be told of is not the eternal Way;
+The name that can be named is not the eternal name.
+#endif /* ! TWO */
+The Nameless is the origin of Heaven and Earth;
+#ifndef TWO
+The Named is the mother of all things.
+#else /* TWO */
+The named is the mother of all things.
+
+#endif /* TWO */
+Therefore let there always be non-being,
+ so we may see their subtlety,
+And let there always be being,
+ so we may see their outcome.
+The two are the same,
+But after they are produced,
+ they have different names.
+#ifdef TWO
+They both may be called deep and profound.
+Deeper and more profound,
+The door of all subtleties!
+#endif /* TWO */
+@end example
+
+@node Detailed If-then-else
+@subsection Detailed Description of If-then-else Format
+
+For lines common to both files, @command{diff} uses the unchanged line
+group format. For each hunk of differences in the merged output
+format, if the hunk contains only lines from the first file,
+@command{diff} uses the old line group format; if the hunk contains only
+lines from the second file, @command{diff} uses the new group format;
+otherwise, @command{diff} uses the changed group format.
+
+The old, new, and unchanged line formats specify the output format of
+lines from the first file, lines from the second file, and lines common
+to both files, respectively.
+
+The option @option{--ifdef=@var{name}} is equivalent to
+the following sequence of options using shell syntax:
+
+@example
+--old-group-format='#ifndef @var{name}
+%<#endif /* ! @var{name} */
+' \
+--new-group-format='#ifdef @var{name}
+%>#endif /* @var{name} */
+' \
+--unchanged-group-format='%=' \
+--changed-group-format='#ifndef @var{name}
+%<#else /* @var{name} */
+%>#endif /* @var{name} */
+'
+@end example
+
+You should carefully check the @command{diff} output for proper nesting.
+For example, when using the @option{-D @var{name}} or
+@option{--ifdef=@var{name}} option, you should check that if the
+differing lines contain any of the C preprocessor directives
+@samp{#ifdef}, @samp{#ifndef}, @samp{#else}, @samp{#elif}, or
+@samp{#endif}, they are nested properly and match. If they don't, you
+must make corrections manually. It is a good idea to carefully check
+the resulting code anyway to make sure that it really does what you
+want it to; depending on how the input files were produced, the output
+might contain duplicate or otherwise incorrect code.
+
+The @command{patch} @option{-D @var{name}} option behaves like
+the @command{diff} @option{-D @var{name}} option, except it operates on
+a file and a diff to produce a merged file; @xref{patch Options}.
+
+@node Incomplete Lines
+@chapter Incomplete Lines
+@cindex incomplete lines
+@cindex full lines
+@cindex newline treatment by @command{diff}
+
+When an input file ends in a non-newline character, its last line is
+called an @dfn{incomplete line} because its last character is not a
+newline. All other lines are called @dfn{full lines} and end in a
+newline character. Incomplete lines do not match full lines unless
+differences in white space are ignored (@pxref{White Space}).
+
+An incomplete line is normally distinguished on output from a full
+line by a following line that starts with @samp{\}. However, the
+@acronym{RCS} format (@pxref{RCS}) outputs the incomplete line as-is,
+without any trailing newline or following line. The side by side
+format normally represents incomplete lines as-is, but in some cases
+uses a @samp{\} or @samp{/} gutter marker; @xref{Side by Side}. The
+if-then-else line format preserves a line's incompleteness with
+@samp{%L}, and discards the newline with @samp{%l}; @xref{Line
+Formats}. Finally, with the @command{ed} and forward @command{ed}
+output formats (@pxref{Output Formats}) @command{diff} cannot
+represent an incomplete line, so it pretends there was a newline and
+reports an error.
+
+For example, suppose @file{F} and @file{G} are one-byte files that
+contain just @samp{f} and @samp{g}, respectively. Then @samp{diff F G}
+outputs
+
+@example
+1c1
+< f
+\ No newline at end of file
+---
+> g
+\ No newline at end of file
+@end example
+
+@noindent
+(The exact message may differ in non-English locales.)
+@samp{diff -n F G} outputs the following without a trailing newline:
+
+@example
+d1 1
+a1 1
+g
+@end example
+
+@noindent
+@samp{diff -e F G} reports two errors and outputs the following:
+
+@example
+1c
+g
+.
+@end example
+
+@node Comparing Directories
+@chapter Comparing Directories
+
+@vindex LC_COLLATE
+You can use @command{diff} to compare some or all of the files in two
+directory trees. When both file name arguments to @command{diff} are
+directories, it compares each file that is contained in both
+directories, examining file names in alphabetical order as specified by
+the @env{LC_COLLATE} locale category. Normally
+@command{diff} is silent about pairs of files that contain no differences,
+but if you use the @option{-s} or @option{--report-identical-files} option,
+it reports pairs of identical files. Normally @command{diff} reports
+subdirectories common to both directories without comparing
+subdirectories' files, but if you use the @option{-r} or
+@option{--recursive} option, it compares every corresponding pair of files
+in the directory trees, as many levels deep as they go.
+
+For file names that are in only one of the directories, @command{diff}
+normally does not show the contents of the file that exists; it reports
+only that the file exists in that directory and not in the other. You
+can make @command{diff} act as though the file existed but was empty in the
+other directory, so that it outputs the entire contents of the file that
+actually exists. (It is output as either an insertion or a
+deletion, depending on whether it is in the first or the second
+directory given.) To do this, use the @option{-N} or @option{--new-file}
+option.
+
+If the older directory contains one or more large files that are not in
+the newer directory, you can make the patch smaller by using the
+@option{--unidirectional-new-file} option instead of @option{-N}.
+This option is like @option{-N} except that it only inserts the contents
+of files that appear in the second directory but not the first (that is,
+files that were added). At the top of the patch, write instructions for
+the user applying the patch to remove the files that were deleted before
+applying the patch. @xref{Making Patches}, for more discussion of
+making patches for distribution.
+
+To ignore some files while comparing directories, use the @option{-x
+@var{pattern}} or @option{--exclude=@var{pattern}} option. This option
+ignores any files or subdirectories whose base names match the shell
+pattern @var{pattern}. Unlike in the shell, a period at the start of
+the base of a file name matches a wildcard at the start of a pattern.
+You should enclose @var{pattern} in quotes so that the shell does not
+expand it. For example, the option @option{-x '*.[ao]'} ignores any file
+whose name ends with @samp{.a} or @samp{.o}.
+
+This option accumulates if you specify it more than once. For example,
+using the options @option{-x 'RCS' -x '*,v'} ignores any file or
+subdirectory whose base name is @samp{RCS} or ends with @samp{,v}.
+
+If you need to give this option many times, you can instead put the
+patterns in a file, one pattern per line, and use the @option{-X
+@var{file}} or @option{--exclude-from=@var{file}} option. Trailing
+white space and empty lines are ignored in the pattern file.
+
+If you have been comparing two directories and stopped partway through,
+later you might want to continue where you left off. You can do this by
+using the @option{-S @var{file}} or @option{--starting-file=@var{file}}
+option. This compares only the file @var{file} and all alphabetically
+later files in the topmost directory level.
+
+If two directories differ only in that file names are lower case in
+one directory and upper case in the upper, @command{diff} normally
+reports many differences because it compares file names in a
+case sensitive way. With the @option{--ignore-file-name-case} option,
+@command{diff} ignores case differences in file names, so that for example
+the contents of the file @file{Tao} in one directory are compared to
+the contents of the file @file{TAO} in the other. The
+@option{--no-ignore-file-name-case} option cancels the effect of the
+@option{--ignore-file-name-case} option, reverting to the default
+behavior.
+
+If an @option{-x @var{pattern}} or @option{--exclude=@var{pattern}}
+option, or an @option{-X @var{file}} or
+@option{--exclude-from=@var{file}} option,
+is specified while the @option{--ignore-file-name-case} option is in
+effect, case is ignored when excluding file names matching the
+specified patterns.
+
+@node Adjusting Output
+@chapter Making @command{diff} Output Prettier
+
+@command{diff} provides several ways to adjust the appearance of its output.
+These adjustments can be applied to any output format.
+
+@menu
+* Tabs:: Preserving the alignment of tab stops.
+* Pagination:: Page numbering and time-stamping @command{diff} output.
+@end menu
+
+@node Tabs
+@section Preserving Tab Stop Alignment
+@cindex tab stop alignment
+@cindex aligning tab stops
+
+The lines of text in some of the @command{diff} output formats are
+preceded by one or two characters that indicate whether the text is
+inserted, deleted, or changed. The addition of those characters can
+cause tabs to move to the next tab stop, throwing off the alignment of
+columns in the line. @acronym{GNU} @command{diff} provides two ways
+to make tab-aligned columns line up correctly.
+
+The first way is to have @command{diff} convert all tabs into the correct
+number of spaces before outputting them; select this method with the
+@option{-t} or @option{--expand-tabs} option. To use this form of output with
+@command{patch}, you must give @command{patch} the @option{-l} or
+@option{--ignore-white-space} option (@pxref{Changed White Space}, for more
+information). @command{diff} normally assumes that tab stops are set
+every 8 print columns, but this can be altered by the
+@option{--tabsize=@var{columns}} option.
+
+The other method for making tabs line up correctly is to add a tab
+character instead of a space after the indicator character at the
+beginning of the line. This ensures that all following tab characters
+are in the same position relative to tab stops that they were in the
+original files, so that the output is aligned correctly. Its
+disadvantage is that it can make long lines too long to fit on one line
+of the screen or the paper. It also does not work with the unified
+output format, which does not have a space character after the change
+type indicator character. Select this method with the @option{-T} or
+@option{--initial-tab} option.
+
+@node Pagination
+@section Paginating @command{diff} Output
+@cindex paginating @command{diff} output
+
+It can be convenient to have long output page-numbered and time-stamped.
+The @option{-l} or @option{--paginate} option does this by sending the
+@command{diff} output through the @command{pr} program. Here is what the page
+header might look like for @samp{diff -lc lao tzu}:
+
+@example
+2002-02-22 14:20 diff -lc lao tzu Page 1
+@end example
+
+@node diff Performance
+@chapter @command{diff} Performance Tradeoffs
+@cindex performance of @command{diff}
+
+@acronym{GNU} @command{diff} runs quite efficiently; however, in some
+circumstances you can cause it to run faster or produce a more compact
+set of changes.
+
+One way to improve @command{diff} performance is to use hard or
+symbolic links to files instead of copies. This improves performance
+because @command{diff} normally does not need to read two hard or
+symbolic links to the same file, since their contents must be
+identical. For example, suppose you copy a large directory hierarchy,
+make a few changes to the copy, and then often use @samp{diff -r} to
+compare the original to the copy. If the original files are
+read-only, you can greatly improve performance by creating the copy
+using hard or symbolic links (e.g., with @acronym{GNU} @samp{cp -lR} or
+@samp{cp -sR}). Before editing a file in the copy for the first time,
+you should break the link and replace it with a regular copy.
+
+You can also affect the performance of @acronym{GNU} @command{diff} by
+giving it options that change the way it compares files.
+Performance has more than one dimension. These options improve one
+aspect of performance at the cost of another, or they improve
+performance in some cases while hurting it in others.
+
+The way that @acronym{GNU} @command{diff} determines which lines have
+changed always comes up with a near-minimal set of differences.
+Usually it is good enough for practical purposes. If the
+@command{diff} output is large, you might want @command{diff} to use a
+modified algorithm that sometimes produces a smaller set of
+differences. The @option{-d} or @option{--minimal} option does this;
+however, it can also cause @command{diff} to run more slowly than
+usual, so it is not the default behavior.
+
+When the files you are comparing are large and have small groups of
+changes scattered throughout them, you can use the
+@option{--speed-large-files} option to make a different modification to
+the algorithm that @command{diff} uses. If the input files have a constant
+small density of changes, this option speeds up the comparisons without
+changing the output. If not, @command{diff} might produce a larger set of
+differences; however, the output will still be correct.
+
+Normally @command{diff} discards the prefix and suffix that is common to
+both files before it attempts to find a minimal set of differences.
+This makes @command{diff} run faster, but occasionally it may produce
+non-minimal output. The @option{--horizon-lines=@var{lines}} option
+prevents @command{diff} from discarding the last @var{lines} lines of the
+prefix and the first @var{lines} lines of the suffix. This gives
+@command{diff} further opportunities to find a minimal output.
+
+Suppose a run of changed lines includes a sequence of lines at one end
+and there is an identical sequence of lines just outside the other end.
+The @command{diff} command is free to choose which identical sequence is
+included in the hunk. In this case, @command{diff} normally shifts the
+hunk's boundaries when this merges adjacent hunks, or shifts a hunk's
+lines towards the end of the file. Merging hunks can make the output
+look nicer in some cases.
+
+@node Comparing Three Files
+@chapter Comparing Three Files
+@cindex comparing three files
+@cindex format of @command{diff3} output
+
+Use the program @command{diff3} to compare three files and show any
+differences among them. (@command{diff3} can also merge files; see
+@ref{diff3 Merging}).
+
+The ``normal'' @command{diff3} output format shows each hunk of
+differences without surrounding context. Hunks are labeled depending
+on whether they are two-way or three-way, and lines are annotated by
+their location in the input files.
+
+@xref{Invoking diff3}, for more information on how to run @command{diff3}.
+
+@menu
+* Sample diff3 Input:: Sample @command{diff3} input for examples.
+* Example diff3 Normal:: Sample output in the normal format.
+* diff3 Hunks:: The format of normal output format.
+* Detailed diff3 Normal:: A detailed description of normal output format.
+@end menu
+
+@node Sample diff3 Input
+@section A Third Sample Input File
+@cindex @command{diff3} sample input
+@cindex sample input for @command{diff3}
+
+Here is a third sample file that will be used in examples to illustrate
+the output of @command{diff3} and how various options can change it. The
+first two files are the same that we used for @command{diff} (@pxref{Sample
+diff Input}). This is the third sample file, called @file{tao}:
+
+@example
+The Way that can be told of is not the eternal Way;
+The name that can be named is not the eternal name.
+The Nameless is the origin of Heaven and Earth;
+The named is the mother of all things.
+
+Therefore let there always be non-being,
+ so we may see their subtlety,
+And let there always be being,
+ so we may see their result.
+The two are the same,
+But after they are produced,
+ they have different names.
+
+ -- The Way of Lao-Tzu, tr. Wing-tsit Chan
+@end example
+
+@node Example diff3 Normal
+@section An Example of @command{diff3} Normal Format
+
+Here is the output of the command @samp{diff3 lao tzu tao}
+(@pxref{Sample diff3 Input}, for the complete contents of the files).
+Notice that it shows only the lines that are different among the three
+files.
+
+@example
+====2
+1:1,2c
+3:1,2c
+ The Way that can be told of is not the eternal Way;
+ The name that can be named is not the eternal name.
+2:0a
+====1
+1:4c
+ The Named is the mother of all things.
+2:2,3c
+3:4,5c
+ The named is the mother of all things.
+
+====3
+1:8c
+2:7c
+ so we may see their outcome.
+3:9c
+ so we may see their result.
+====
+1:11a
+2:11,13c
+ They both may be called deep and profound.
+ Deeper and more profound,
+ The door of all subtleties!
+3:13,14c
+
+ -- The Way of Lao-Tzu, tr. Wing-tsit Chan
+@end example
+
+@node Detailed diff3 Normal
+@section Detailed Description of @command{diff3} Normal Format
+
+Each hunk begins with a line marked @samp{====}. Three-way hunks have
+plain @samp{====} lines, and two-way hunks have @samp{1}, @samp{2}, or
+@samp{3} appended to specify which of the three input files differ in
+that hunk. The hunks contain copies of two or three sets of input
+lines each preceded by one or two commands identifying where the lines
+came from.
+
+Normally, two spaces precede each copy of an input line to distinguish
+it from the commands. But with the @option{-T} or @option{--initial-tab}
+option, @command{diff3} uses a tab instead of two spaces; this lines up
+tabs correctly. @xref{Tabs}, for more information.
+
+Commands take the following forms:
+
+@table @samp
+@item @var{file}:@var{l}a
+This hunk appears after line @var{l} of file @var{file}, and
+contains no lines in that file. To edit this file to yield the other
+files, one must append hunk lines taken from the other files. For
+example, @samp{1:11a} means that the hunk follows line 11 in the first
+file and contains no lines from that file.
+
+@item @var{file}:@var{r}c
+This hunk contains the lines in the range @var{r} of file @var{file}.
+The range @var{r} is a comma-separated pair of line numbers, or just one
+number if the range is a singleton. To edit this file to yield the
+other files, one must change the specified lines to be the lines taken
+from the other files. For example, @samp{2:11,13c} means that the hunk
+contains lines 11 through 13 from the second file.
+@end table
+
+If the last line in a set of input lines is incomplete
+(@pxref{Incomplete Lines}), it is distinguished on output from a full
+line by a following line that starts with @samp{\}.
+
+@node diff3 Hunks
+@section @command{diff3} Hunks
+@cindex hunks for @command{diff3}
+@cindex @command{diff3} hunks
+
+Groups of lines that differ in two or three of the input files are
+called @dfn{diff3 hunks}, by analogy with @command{diff} hunks
+(@pxref{Hunks}). If all three input files differ in a @command{diff3}
+hunk, the hunk is called a @dfn{three-way hunk}; if just two input files
+differ, it is a @dfn{two-way hunk}.
+
+As with @command{diff}, several solutions are possible. When comparing the
+files @samp{A}, @samp{B}, and @samp{C}, @command{diff3} normally finds
+@command{diff3} hunks by merging the two-way hunks output by the two
+commands @samp{diff A B} and @samp{diff A C}. This does not necessarily
+minimize the size of the output, but exceptions should be rare.
+
+For example, suppose @file{F} contains the three lines @samp{a},
+@samp{b}, @samp{f}, @file{G} contains the lines @samp{g}, @samp{b},
+@samp{g}, and @file{H} contains the lines @samp{a}, @samp{b},
+@samp{h}. @samp{diff3 F G H} might output the following:
+
+@example
+====2
+1:1c
+3:1c
+ a
+2:1c
+ g
+====
+1:3c
+ f
+2:3c
+ g
+3:3c
+ h
+@end example
+
+@noindent
+because it found a two-way hunk containing @samp{a} in the first and
+third files and @samp{g} in the second file, then the single line
+@samp{b} common to all three files, then a three-way hunk containing
+the last line of each file.
+
+@node diff3 Merging
+@chapter Merging From a Common Ancestor
+@cindex merging from a common ancestor
+
+When two people have made changes to copies of the same file,
+@command{diff3} can produce a merged output that contains both sets of
+changes together with warnings about conflicts.
+
+One might imagine programs with names like @command{diff4} and @command{diff5}
+to compare more than three files simultaneously, but in practice the
+need rarely arises. You can use @command{diff3} to merge three or more
+sets of changes to a file by merging two change sets at a time.
+
+@command{diff3} can incorporate changes from two modified versions into a
+common preceding version. This lets you merge the sets of changes
+represented by the two newer files. Specify the common ancestor version
+as the second argument and the two newer versions as the first and third
+arguments, like this:
+
+@example
+diff3 @var{mine} @var{older} @var{yours}
+@end example
+
+@noindent
+You can remember the order of the arguments by noting that they are in
+alphabetical order.
+
+@cindex conflict
+@cindex overlap
+You can think of this as subtracting @var{older} from @var{yours} and
+adding the result to @var{mine}, or as merging into @var{mine} the
+changes that would turn @var{older} into @var{yours}. This merging is
+well-defined as long as @var{mine} and @var{older} match in the
+neighborhood of each such change. This fails to be true when all three
+input files differ or when only @var{older} differs; we call this
+a @dfn{conflict}. When all three input files differ, we call the
+conflict an @dfn{overlap}.
+
+@command{diff3} gives you several ways to handle overlaps and conflicts.
+You can omit overlaps or conflicts, or select only overlaps,
+or mark conflicts with special @samp{<<<<<<<} and @samp{>>>>>>>} lines.
+
+@command{diff3} can output the merge results as an @command{ed} script that
+that can be applied to the first file to yield the merged output.
+However, it is usually better to have @command{diff3} generate the merged
+output directly; this bypasses some problems with @command{ed}.
+
+@menu
+* Which Changes:: Selecting changes to incorporate.
+* Marking Conflicts:: Marking conflicts.
+* Bypassing ed:: Generating merged output directly.
+* Merging Incomplete Lines:: How @command{diff3} merges incomplete lines.
+* Saving the Changed File:: Emulating System V behavior.
+@end menu
+
+@node Which Changes
+@section Selecting Which Changes to Incorporate
+@cindex overlapping change, selection of
+@cindex unmerged change
+
+You can select all unmerged changes from @var{older} to @var{yours} for merging
+into @var{mine} with the @option{-e} or @option{--ed} option. You can
+select only the nonoverlapping unmerged changes with @option{-3} or
+@option{--easy-only}, and you can select only the overlapping changes with
+@option{-x} or @option{--overlap-only}.
+
+The @option{-e}, @option{-3} and @option{-x} options select only
+@dfn{unmerged changes}, i.e.@: changes where @var{mine} and @var{yours}
+differ; they ignore changes from @var{older} to @var{yours} where
+@var{mine} and @var{yours} are identical, because they assume that such
+changes have already been merged. If this assumption is not a safe
+one, you can use the @option{-A} or @option{--show-all} option
+(@pxref{Marking Conflicts}).
+
+Here is the output of the command @command{diff3} with each of these three
+options (@pxref{Sample diff3 Input}, for the complete contents of the files).
+Notice that @option{-e} outputs the union of the disjoint sets of changes
+output by @option{-3} and @option{-x}.
+
+Output of @samp{diff3 -e lao tzu tao}:
+@example
+11a
+
+ -- The Way of Lao-Tzu, tr. Wing-tsit Chan
+.
+8c
+ so we may see their result.
+.
+@end example
+
+Output of @samp{diff3 -3 lao tzu tao}:
+@example
+8c
+ so we may see their result.
+.
+@end example
+
+Output of @samp{diff3 -x lao tzu tao}:
+@example
+11a
+
+ -- The Way of Lao-Tzu, tr. Wing-tsit Chan
+.
+@end example
+
+@node Marking Conflicts
+@section Marking Conflicts
+@cindex conflict marking
+@cindex @samp{<<<<<<<} for marking conflicts
+
+@command{diff3} can mark conflicts in the merged output by
+bracketing them with special marker lines. A conflict
+that comes from two files @var{A} and @var{B} is marked as follows:
+
+@example
+<<<<<<< @var{A}
+@r{lines from @var{A}}
+=======
+@r{lines from @var{B}}
+>>>>>>> @var{B}
+@end example
+
+A conflict that comes from three files @var{A}, @var{B} and @var{C} is
+marked as follows:
+
+@example
+<<<<<<< @var{A}
+@r{lines from @var{A}}
+||||||| @var{B}
+@r{lines from @var{B}}
+=======
+@r{lines from @var{C}}
+>>>>>>> @var{C}
+@end example
+
+The @option{-A} or @option{--show-all} option acts like the @option{-e}
+option, except that it brackets conflicts, and it outputs all changes
+from @var{older} to @var{yours}, not just the unmerged changes. Thus,
+given the sample input files (@pxref{Sample diff3 Input}), @samp{diff3
+-A lao tzu tao} puts brackets around the conflict where only @file{tzu}
+differs:
+
+@example
+<<<<<<< tzu
+=======
+The Way that can be told of is not the eternal Way;
+The name that can be named is not the eternal name.
+>>>>>>> tao
+@end example
+
+And it outputs the three-way conflict as follows:
+
+@example
+<<<<<<< lao
+||||||| tzu
+They both may be called deep and profound.
+Deeper and more profound,
+The door of all subtleties!
+=======
+
+ -- The Way of Lao-Tzu, tr. Wing-tsit Chan
+>>>>>>> tao
+@end example
+
+The @option{-E} or @option{--show-overlap} option outputs less information
+than the @option{-A} or @option{--show-all} option, because it outputs only
+unmerged changes, and it never outputs the contents of the second
+file. Thus the @option{-E} option acts like the @option{-e} option,
+except that it brackets the first and third files from three-way
+overlapping changes. Similarly, @option{-X} acts like @option{-x}, except
+it brackets all its (necessarily overlapping) changes. For example,
+for the three-way overlapping change above, the @option{-E} and @option{-X}
+options output the following:
+
+@example
+<<<<<<< lao
+=======
+
+ -- The Way of Lao-Tzu, tr. Wing-tsit Chan
+>>>>>>> tao
+@end example
+
+If you are comparing files that have meaningless or uninformative names,
+you can use the @option{--label=@var{label}}
+option to show alternate names in the @samp{<<<<<<<}, @samp{|||||||}
+and @samp{>>>>>>>} brackets. This option can be given up to three
+times, once for each input file. Thus @samp{diff3 -A --label X
+--label Y --label Z A
+B C} acts like @samp{diff3 -A A B C}, except that the output looks like
+it came from files named @samp{X}, @samp{Y} and @samp{Z} rather than
+from files named @samp{A}, @samp{B} and @samp{C}.
+
+@node Bypassing ed
+@section Generating the Merged Output Directly
+@cindex merged @command{diff3} format
+
+With the @option{-m} or @option{--merge} option, @command{diff3} outputs the
+merged file directly. This is more efficient than using @command{ed} to
+generate it, and works even with non-text files that @command{ed} would
+reject. If you specify @option{-m} without an @command{ed} script option,
+@option{-A} is assumed.
+
+For example, the command @samp{diff3 -m lao tzu tao}
+(@pxref{Sample diff3 Input} for a copy of the input files) would output
+the following:
+
+@example
+<<<<<<< tzu
+=======
+The Way that can be told of is not the eternal Way;
+The name that can be named is not the eternal name.
+>>>>>>> tao
+The Nameless is the origin of Heaven and Earth;
+The Named is the mother of all things.
+Therefore let there always be non-being,
+ so we may see their subtlety,
+And let there always be being,
+ so we may see their result.
+The two are the same,
+But after they are produced,
+ they have different names.
+<<<<<<< lao
+||||||| tzu
+They both may be called deep and profound.
+Deeper and more profound,
+The door of all subtleties!
+=======
+
+ -- The Way of Lao-Tzu, tr. Wing-tsit Chan
+>>>>>>> tao
+@end example
+
+@node Merging Incomplete Lines
+@section How @command{diff3} Merges Incomplete Lines
+@cindex incomplete line merging
+
+With @option{-m}, incomplete lines (@pxref{Incomplete Lines}) are simply
+copied to the output as they are found; if the merged output ends in an
+conflict and one of the input files ends in an incomplete
+line, succeeding @samp{|||||||}, @samp{=======} or @samp{>>>>>>>}
+brackets appear somewhere other than the start of a line because
+they are appended to the incomplete line.
+
+Without @option{-m}, if an @command{ed} script option is specified and an
+incomplete line is found, @command{diff3} generates a warning and acts as
+if a newline had been present.
+
+@node Saving the Changed File
+@section Saving the Changed File
+@cindex System V @command{diff3} compatibility
+
+Traditional Unix @command{diff3} generates an @command{ed} script without the
+trailing @samp{w} and @samp{q} commands that save the changes.
+System V @command{diff3} generates these extra commands. @acronym{GNU}
+@command{diff3} normally behaves like traditional Unix
+@command{diff3}, but with the @option{-i} option it behaves like
+System V @command{diff3} and appends the @samp{w} and @samp{q}
+commands.
+
+The @option{-i} option requires one of the @command{ed} script options
+@option{-AeExX3}, and is incompatible with the merged output option
+@option{-m}.
+
+@node Interactive Merging
+@chapter Interactive Merging with @command{sdiff}
+@cindex diff merging
+@cindex interactive merging
+
+With @command{sdiff}, you can merge two files interactively based on a
+side-by-side @option{-y} format comparison (@pxref{Side by Side}). Use
+@option{-o @var{file}} or @option{--output=@var{file}} to specify where to
+put the merged text. @xref{Invoking sdiff}, for more details on the
+options to @command{sdiff}.
+
+Another way to merge files interactively is to use the Emacs Lisp
+package @command{emerge}. @xref{emerge, , emerge, emacs, The
+@acronym{GNU} Emacs Manual}, for more information.
+
+@menu
+* sdiff Option Summary:: Summary of @command{sdiff} options.
+* Merge Commands:: Merging two files interactively.
+@end menu
+
+@node sdiff Option Summary
+@section Specifying @command{diff} Options to @command{sdiff}
+@cindex @command{sdiff} output format
+
+The following @command{sdiff} options have the same meaning as for
+@command{diff}. @xref{diff Options}, for the use of these options.
+
+@example
+-a -b -d -i -t -v
+-B -E -I @var{regexp}
+
+--expand-tabs
+--ignore-blank-lines --ignore-case
+--ignore-matching-lines=@var{regexp} --ignore-space-change
+--ignore-tab-expansion
+--left-column --minimal --speed-large-files
+--strip-trailing-cr --suppress-common-lines
+--tabsize=@var{columns} --text --version --width=@var{columns}
+@end example
+
+For historical reasons, @command{sdiff} has alternate names for some
+options. The @option{-l} option is equivalent to the
+@option{--left-column} option, and similarly @option{-s} is equivalent
+to @option{--suppress-common-lines}. The meaning of the @command{sdiff}
+@option{-w} and @option{-W} options is interchanged from that of
+@command{diff}: with @command{sdiff}, @option{-w @var{columns}} is
+equivalent to @option{--width=@var{columns}}, and @option{-W} is
+equivalent to @option{--ignore-all-space}. @command{sdiff} without the
+@option{-o} option is equivalent to @command{diff} with the @option{-y}
+or @option{--side-by-side} option (@pxref{Side by Side}).
+
+@node Merge Commands
+@section Merge Commands
+@cindex merge commands
+@cindex merging interactively
+
+Groups of common lines, with a blank gutter, are copied from the first
+file to the output. After each group of differing lines, @command{sdiff}
+prompts with @samp{%} and pauses, waiting for one of the following
+commands. Follow each command with @key{RET}.
+
+@table @samp
+@item e
+Discard both versions.
+Invoke a text editor on an empty temporary file,
+then copy the resulting file to the output.
+
+@item eb
+Concatenate the two versions, edit the result in a temporary file,
+then copy the edited result to the output.
+
+@item ed
+Like @samp{eb}, except precede each version with a header that
+shows what file and lines the version came from.
+
+@item el
+Edit a copy of the left version, then copy the result to the output.
+
+@item er
+Edit a copy of the right version, then copy the result to the output.
+
+@item l
+Copy the left version to the output.
+
+@item q
+Quit.
+
+@item r
+Copy the right version to the output.
+
+@item s
+Silently copy common lines.
+
+@item v
+Verbosely copy common lines. This is the default.
+@end table
+
+@vindex EDITOR
+The text editor invoked is specified by the @env{EDITOR} environment
+variable if it is set. The default is system-dependent.
+
+@node Merging with patch
+@chapter Merging with @command{patch}
+
+@command{patch} takes comparison output produced by @command{diff} and applies
+the differences to a copy of the original file, producing a patched
+version. With @command{patch}, you can distribute just the changes to a
+set of files instead of distributing the entire file set; your
+correspondents can apply @command{patch} to update their copy of the files
+with your changes. @command{patch} automatically determines the diff
+format, skips any leading or trailing headers, and uses the headers to
+determine which file to patch. This lets your correspondents feed a
+mail message containing a difference listing directly to
+@command{patch}.
+
+@command{patch} detects and warns about common problems like forward
+patches. It saves any patches that it could not apply. It can also maintain a
+@code{patchlevel.h} file to ensure that your correspondents apply
+diffs in the proper order.
+
+@command{patch} accepts a series of diffs in its standard input, usually
+separated by headers that specify which file to patch. It applies
+@command{diff} hunks (@pxref{Hunks}) one by one. If a hunk does not
+exactly match the original file, @command{patch} uses heuristics to try to
+patch the file as well as it can. If no approximate match can be found,
+@command{patch} rejects the hunk and skips to the next hunk. @command{patch}
+normally replaces each file @var{f} with its new version, putting reject
+hunks (if any) into @samp{@var{f}.rej}.
+
+@xref{Invoking patch}, for detailed information on the options to
+@command{patch}.
+
+@menu
+* patch Input:: Selecting the type of @command{patch} input.
+* Revision Control:: Getting files from @acronym{RCS}, @acronym{SCCS}, etc.
+* Imperfect:: Dealing with imperfect patches.
+* Creating and Removing:: Creating and removing files with a patch.
+* Patching Time Stamps:: Updating time stamps on patched files.
+* Multiple Patches:: Handling multiple patches in a file.
+* patch Directories:: Changing directory and stripping directories.
+* Backups:: Whether backup files are made.
+* Backup Names:: Backup file names.
+* Reject Names:: Reject file names.
+* patch Messages:: Messages and questions @command{patch} can produce.
+* patch and POSIX:: Conformance to the @acronym{POSIX} standard.
+* patch and Tradition:: @acronym{GNU} versus traditional @command{patch}.
+@end menu
+
+@node patch Input
+@section Selecting the @command{patch} Input Format
+@cindex @command{patch} input format
+
+@command{patch} normally determines which @command{diff} format the patch
+file uses by examining its contents. For patch files that contain
+particularly confusing leading text, you might need to use one of the
+following options to force @command{patch} to interpret the patch file as a
+certain format of diff. The output formats listed here are the only
+ones that @command{patch} can understand.
+
+@table @option
+@item -c
+@itemx --context
+context diff.
+
+@item -e
+@itemx --ed
+@command{ed} script.
+
+@item -n
+@itemx --normal
+normal diff.
+
+@item -u
+@itemx --unified
+unified diff.
+@end table
+
+@node Revision Control
+@section Revision Control
+@cindex revision control
+@cindex version control
+@cindex @acronym{RCS}
+@cindex ClearCase
+@cindex @acronym{SCCS}
+
+If a nonexistent input file is under a revision control system
+supported by @command{patch}, @command{patch} normally asks the user
+whether to get (or check out) the file from the revision control
+system. Patch currently supports @acronym{RCS}, ClearCase and
+@acronym{SCCS}. Under @acronym{RCS} and @acronym{SCCS},
+@command{patch} also asks when the input file is read-only and matches
+the default version in the revision control system.
+
+@vindex PATCH_GET
+The @option{-g @var{num}} or @option{--get=@var{num}} option affects access
+to files under supported revision control systems. If @var{num} is
+positive, @command{patch} gets the file without asking the user; if
+zero, @command{patch} neither asks the user nor gets the file; and if
+negative, @command{patch} asks the user before getting the file. The
+default value of @var{num} is given by the value of the
+@env{PATCH_GET} environment variable if it is set; if not, the default
+value is zero if @command{patch} is conforming to @acronym{POSIX}, negative
+otherwise. @xref{patch and POSIX}.
+
+@vindex VERSION_CONTROL
+The choice of revision control system is unaffected by the
+@env{VERSION_CONTROL} environment variable (@pxref{Backup Names}).
+
+@node Imperfect
+@section Applying Imperfect Patches
+@cindex imperfect patch application
+
+@command{patch} tries to skip any leading text in the patch file,
+apply the diff, and then skip any trailing text. Thus you can feed a
+mail message directly to @command{patch}, and it should work. If the
+entire diff is indented by a constant amount of white space,
+@command{patch} automatically ignores the indentation. If a context
+diff contains trailing carriage return on each line, @command{patch}
+automatically ignores the carriage return. If a context diff has been
+encapsulated by prepending @w{@samp{- }} to lines beginning with @samp{-}
+as per @uref{ftp://ftp.isi.edu/in-notes/rfc934.txt, Internet RFC 934},
+@command{patch} automatically unencapsulates the input.
+
+However, certain other types of imperfect input require user
+intervention or testing.
+
+@menu
+* Changed White Space:: When tabs and spaces don't match exactly.
+* Reversed Patches:: Applying reversed patches correctly.
+* Inexact:: Helping @command{patch} find close matches.
+* Dry Runs:: Predicting what @command{patch} will do.
+@end menu
+
+@node Changed White Space
+@subsection Applying Patches with Changed White Space
+@cindex white space in patches
+
+Sometimes mailers, editors, or other programs change spaces into tabs,
+or vice versa. If this happens to a patch file or an input file, the
+files might look the same, but @command{patch} will not be able to match
+them properly. If this problem occurs, use the @option{-l} or
+@option{--ignore-white-space} option, which makes @command{patch} compare
+blank characters (i.e.@: spaces and tabs) loosely so that any nonempty
+sequence of blanks in the patch file matches any nonempty sequence of
+blanks in the input files. Non-blank
+characters must still match exactly. Each line of the context must
+still match a line in the input file.
+
+@node Reversed Patches
+@subsection Applying Reversed Patches
+@cindex reversed patches
+
+Sometimes people run @command{diff} with the new file first instead of
+second. This creates a diff that is ``reversed''. To apply such
+patches, give @command{patch} the @option{-R} or @option{--reverse} option.
+@command{patch} then attempts to swap each hunk around before applying it.
+Rejects come out in the swapped format.
+
+Often @command{patch} can guess that the patch is reversed. If the first
+hunk of a patch fails, @command{patch} reverses the hunk to see if it can
+apply it that way. If it can, @command{patch} asks you if you want to have
+the @option{-R} option set; if it can't, @command{patch} continues to apply
+the patch normally. This method cannot detect a reversed patch if it is
+a normal diff and the first command is an append (which should have been
+a delete) since appends always succeed, because a null context matches
+anywhere. But most patches add or change lines rather than delete them,
+so most reversed normal diffs begin with a delete, which fails, and
+@command{patch} notices.
+
+If you apply a patch that you have already applied, @command{patch} thinks
+it is a reversed patch and offers to un-apply the patch. This could be
+construed as a feature. If you did this inadvertently and you don't
+want to un-apply the patch, just answer @samp{n} to this offer and to
+the subsequent ``apply anyway'' question---or type @kbd{C-c} to kill the
+@command{patch} process.
+
+@node Inexact
+@subsection Helping @command{patch} Find Inexact Matches
+@cindex inexact patches
+@cindex fuzz factor when patching
+
+For context diffs, and to a lesser extent normal diffs, @command{patch} can
+detect when the line numbers mentioned in the patch are incorrect, and
+it attempts to find the correct place to apply each hunk of the patch.
+As a first guess, it takes the line number mentioned in the hunk, plus
+or minus any offset used in applying the previous hunk. If that is not
+the correct place, @command{patch} scans both forward and backward for a
+set of lines matching the context given in the hunk.
+
+First @command{patch} looks for a place where all lines of the context
+match. If it cannot find such a place, and it is reading a context or
+unified diff, and the maximum fuzz factor is set to 1 or more, then
+@command{patch} makes another scan, ignoring the first and last line of
+context. If that fails, and the maximum fuzz factor is set to 2 or
+more, it makes another scan, ignoring the first two and last two lines
+of context are ignored. It continues similarly if the maximum fuzz
+factor is larger.
+
+The @option{-F @var{lines}} or @option{--fuzz=@var{lines}} option sets the
+maximum fuzz factor to @var{lines}. This option only applies to context
+and unified diffs; it ignores up to @var{lines} lines while looking for
+the place to install a hunk. Note that a larger fuzz factor increases
+the odds of making a faulty patch. The default fuzz factor is 2; there
+is no point to setting it to more than the number of lines of context
+in the diff, ordinarily 3.
+
+If @command{patch} cannot find a place to install a hunk of the patch, it
+writes the hunk out to a reject file (@pxref{Reject Names}, for information
+on how reject files are named). It writes out rejected hunks in context
+format no matter what form the input patch is in. If the input is a
+normal or @command{ed} diff, many of the contexts are simply null. The
+line numbers on the hunks in the reject file may be different from those
+in the patch file: they show the approximate location where @command{patch}
+thinks the failed hunks belong in the new file rather than in the old
+one.
+
+If the @option{--verbose} option is given, then
+as it completes each hunk @command{patch} tells you whether the hunk
+succeeded or failed, and if it failed, on which line (in the new file)
+@command{patch} thinks the hunk should go. If this is different from the
+line number specified in the diff, it tells you the offset. A single
+large offset @emph{may} indicate that @command{patch} installed a hunk in
+the wrong place. @command{patch} also tells you if it used a fuzz factor
+to make the match, in which case you should also be slightly suspicious.
+
+@command{patch} cannot tell if the line numbers are off in an @command{ed}
+script, and can only detect wrong line numbers in a normal diff when it
+finds a change or delete command. It may have the same problem with a
+context diff using a fuzz factor equal to or greater than the number of
+lines of context shown in the diff (typically 3). In these cases, you
+should probably look at a context diff between your original and patched
+input files to see if the changes make sense. Compiling without errors
+is a pretty good indication that the patch worked, but not a guarantee.
+
+A patch against an empty file applies to a nonexistent file, and vice
+versa. @xref{Creating and Removing}.
+
+@command{patch} usually produces the correct results, even when it must
+make many guesses. However, the results are guaranteed only when
+the patch is applied to an exact copy of the file that the patch was
+generated from.
+
+@node Dry Runs
+@subsection Predicting what @command{patch} will do
+@cindex testing @command{patch}
+@cindex dry runs for @command{patch}
+
+It may not be obvious in advance what @command{patch} will do with a
+complicated or poorly formatted patch. If you are concerned that the
+input might cause @command{patch} to modify the wrong files, you can
+use the @option{--dry-run} option, which causes @command{patch} to
+print the results of applying patches without actually changing any
+files. You can then inspect the diagnostics generated by the dry run
+to see whether @command{patch} will modify the files that you expect.
+If the patch does not do what you want, you can modify the patch (or
+the other options to @command{patch}) and try another dry run. Once
+you are satisfied with the proposed patch you can apply it by invoking
+@command{patch} as before, but this time without the
+@option{--dry-run} option.
+
+@node Creating and Removing
+@section Creating and Removing Files
+@cindex creating files
+@cindex empty files, removing
+@cindex removing empty files
+
+Sometimes when comparing two directories, a file may exist in one
+directory but not the other. If you give @command{diff} the
+@option{-N} or @option{--new-file} option, or if you supply an old or
+new file that is named @file{/dev/null} or is empty and is dated the
+Epoch (1970-01-01 00:00:00 UTC), @command{diff} outputs a patch that
+adds or deletes the contents of this file. When given such a patch,
+@command{patch} normally creates a new file or removes the old file.
+However, when conforming to @acronym{POSIX} (@pxref{patch and POSIX}),
+@command{patch} does not remove the old file, but leaves it empty.
+The @option{-E} or @option{--remove-empty-files} option causes
+@command{patch} to remove output files that are empty after applying a
+patch, even if the patch does not appear to be one that removed the
+file.
+
+If the patch appears to create a file that already exists,
+@command{patch} asks for confirmation before applying the patch.
+
+@node Patching Time Stamps
+@section Updating Time Stamps on Patched Files
+@cindex time stamps on patched files
+
+When @command{patch} updates a file, it normally sets the file's
+last-modified time stamp to the current time of day. If you are using
+@command{patch} to track a software distribution, this can cause
+@command{make} to incorrectly conclude that a patched file is out of
+date. For example, if @file{syntax.c} depends on @file{syntax.y}, and
+@command{patch} updates @file{syntax.c} and then @file{syntax.y}, then
+@file{syntax.c} will normally appear to be out of date with respect to
+@file{syntax.y} even though its contents are actually up to date.
+
+The @option{-Z} or @option{--set-utc} option causes @command{patch} to
+set a patched file's modification and access times to the time stamps
+given in context diff headers. If the context diff headers do not
+specify a time zone, they are assumed to use Coordinated Universal
+Time (@acronym{UTC}, often known as @acronym{GMT}).
+
+The @option{-T} or @option{--set-time} option acts like @option{-Z} or
+@option{--set-utc}, except that it assumes that the context diff
+headers' time stamps use local time instead of @acronym{UTC}. This option
+is not recommended, because patches using local time cannot easily be
+used by people in other time zones, and because local time stamps are
+ambiguous when local clocks move backwards during daylight-saving time
+adjustments. If the context diff headers specify a time zone, this
+option is equivalent to @option{-Z} or @option{--set-utc}.
+
+@command{patch} normally refrains from setting a file's time stamps if
+the file's original last-modified time stamp does not match the time
+given in the diff header, of if the file's contents do not exactly
+match the patch. However, if the @option{-f} or @option{--force}
+option is given, the file's time stamps are set regardless.
+
+Due to the limitations of the current @command{diff} format,
+@command{patch} cannot update the times of files whose contents have
+not changed. Also, if you set file time stamps to values other than
+the current time of day, you should also remove (e.g., with @samp{make
+clean}) all files that depend on the patched files, so that later
+invocations of @command{make} do not get confused by the patched
+files' times.
+
+@node Multiple Patches
+@section Multiple Patches in a File
+@cindex multiple patches
+@cindex intuiting file names from patches
+
+If the patch file contains more than one patch, and if you do not
+specify an input file on the command line, @command{patch} tries to
+apply each patch as if they came from separate patch files. This
+means that it determines the name of the file to patch for each patch,
+and that it examines the leading text before each patch for file names
+and prerequisite revision level (@pxref{Making Patches}, for more on
+that topic).
+
+@command{patch} uses the following rules to intuit a file name from
+the leading text before a patch. First, @command{patch} takes an
+ordered list of candidate file names as follows:
+
+@itemize @bullet
+@item
+If the header is that of a context diff, @command{patch} takes the old
+and new file names in the header. A name is ignored if it does not
+have enough slashes to satisfy the @option{-p@var{num}} or
+@option{--strip=@var{num}} option. The name @file{/dev/null} is also
+ignored.
+
+@item
+If there is an @samp{Index:} line in the leading garbage and if either
+the old and new names are both absent or if @command{patch} is
+conforming to @acronym{POSIX}, @command{patch} takes the name in the
+@samp{Index:} line.
+
+@item
+For the purpose of the following rules, the candidate file names are
+considered to be in the order (old, new, index), regardless of the
+order that they appear in the header.
+@end itemize
+
+@noindent
+Then @command{patch} selects a file name from the candidate list as
+follows:
+
+@itemize @bullet
+@item
+If some of the named files exist, @command{patch} selects the first
+name if conforming to @acronym{POSIX}, and the best name otherwise.
+
+@item
+If @command{patch} is not ignoring @acronym{RCS}, ClearCase, and @acronym{SCCS}
+(@pxref{Revision Control}), and no named files exist but an @acronym{RCS},
+ClearCase, or @acronym{SCCS} master is found, @command{patch} selects the
+first named file with an @acronym{RCS}, ClearCase, or @acronym{SCCS} master.
+
+@item
+If no named files exist, no @acronym{RCS}, ClearCase, or @acronym{SCCS} master
+was found, some names are given, @command{patch} is not conforming to
+@acronym{POSIX}, and the patch appears to create a file, @command{patch}
+selects the best name requiring the creation of the fewest
+directories.
+
+@item
+If no file name results from the above heuristics, you are asked for
+the name of the file to patch, and @command{patch} selects that name.
+@end itemize
+
+To determine the @dfn{best} of a nonempty list of file names,
+@command{patch} first takes all the names with the fewest path name
+components; of those, it then takes all the names with the shortest
+basename; of those, it then takes all the shortest names; finally, it
+takes the first remaining name.
+
+@xref{patch and POSIX}, to see whether @command{patch} is conforming
+to @acronym{POSIX}.
+
+@node patch Directories
+@section Applying Patches in Other Directories
+@cindex directories and patch
+@cindex patching directories
+
+The @option{-d @var{directory}} or @option{--directory=@var{directory}}
+option to @command{patch} makes directory @var{directory} the current
+directory for interpreting both file names in the patch file, and file
+names given as arguments to other options (such as @option{-B} and
+@option{-o}). For example, while in a mail reading program, you can patch
+a file in the @file{/usr/src/emacs} directory directly from a message
+containing the patch like this:
+
+@example
+| patch -d /usr/src/emacs
+@end example
+
+Sometimes the file names given in a patch contain leading directories,
+but you keep your files in a directory different from the one given in
+the patch. In those cases, you can use the
+@option{-p@var{number}} or @option{--strip=@var{number}}
+option to set the file name strip count to @var{number}. The strip
+count tells @command{patch} how many slashes, along with the directory
+names between them, to strip from the front of file names. A sequence
+of one or more adjacent slashes is counted as a single slash. By
+default, @command{patch} strips off all leading directories, leaving
+just the base file names.
+
+For example, suppose the file name in the patch file is
+@file{/gnu/src/emacs/etc/NEWS}. Using @option{-p0} gives the
+entire file name unmodified, @option{-p1} gives
+@file{gnu/src/emacs/etc/NEWS} (no leading slash), @option{-p4} gives
+@file{etc/NEWS}, and not specifying @option{-p} at all gives @file{NEWS}.
+
+@command{patch} looks for each file (after any slashes have been stripped)
+in the current directory, or if you used the @option{-d @var{directory}}
+option, in that directory.
+
+@node Backups
+@section Backup Files
+@cindex backup file strategy
+
+Normally, @command{patch} creates a backup file if the patch does not
+exactly match the original input file, because in that case the
+original data might not be recovered if you undo the patch with
+@samp{patch -R} (@pxref{Reversed Patches}). However, when conforming
+to @acronym{POSIX}, @command{patch} does not create backup files by
+default. @xref{patch and POSIX}.
+
+The @option{-b} or @option{--backup} option causes @command{patch} to
+make a backup file regardless of whether the patch matches the
+original input. The @option{--backup-if-mismatch} option causes
+@command{patch} to create backup files for mismatches files; this is
+the default when not conforming to @acronym{POSIX}. The
+@option{--no-backup-if-mismatch} option causes @command{patch} to not
+create backup files, even for mismatched patches; this is the default
+when conforming to @acronym{POSIX}.
+
+When backing up a file that does not exist, an empty, unreadable
+backup file is created as a placeholder to represent the nonexistent
+file.
+
+@node Backup Names
+@section Backup File Names
+@cindex backup file names
+
+Normally, @command{patch} renames an original input file into a backup
+file by appending to its name the extension @samp{.orig}, or @samp{~}
+if using @samp{.orig} would make the backup file name too
+long.@footnote{A coding error in @acronym{GNU} @command{patch} version
+2.5.4 causes it to always use @samp{~}, but this should be fixed in
+the next release.} The @option{-z @var{backup-suffix}} or
+@option{--suffix=@var{backup-suffix}} option causes @command{patch} to
+use @var{backup-suffix} as the backup extension instead.
+
+@vindex SIMPLE_BACKUP_SUFFIX
+Alternately, you can specify the extension for backup files with the
+@env{SIMPLE_BACKUP_SUFFIX} environment variable, which the options
+override.
+
+@command{patch} can also create numbered backup files the way
+@acronym{GNU} Emacs does. With this method, instead of having a
+single backup of each file, @command{patch} makes a new backup file
+name each time it patches a file. For example, the backups of a file
+named @file{sink} would be called, successively, @file{sink.~1~},
+@file{sink.~2~}, @file{sink.~3~}, etc.
+
+@vindex PATCH_VERSION_CONTROL
+@vindex VERSION_CONTROL
+The @option{-V @var{backup-style}} or
+@option{--version-control=@var{backup-style}} option takes as an
+argument a method for creating backup file names. You can alternately
+control the type of backups that @command{patch} makes with the
+@env{PATCH_VERSION_CONTROL} environment variable, which the
+@option{-V} option overrides. If @env{PATCH_VERSION_CONTROL} is not
+set, the @env{VERSION_CONTROL} environment variable is used instead.
+Please note that these options and variables control backup file
+names; they do not affect the choice of revision control system
+(@pxref{Revision Control}).
+
+The values of these environment variables and the argument to the
+@option{-V} option are like the @acronym{GNU} Emacs @code{version-control}
+variable (@pxref{Backup Names, , , emacs, The @acronym{GNU} Emacs Manual},
+for more information on backup versions in Emacs). They also
+recognize synonyms that are more descriptive. The valid values are
+listed below; unique abbreviations are acceptable.
+
+@table @option
+@item t
+@itemx numbered
+Always make numbered backups.
+
+@item nil
+@itemx existing
+Make numbered backups of files that already have them, simple backups of
+the others. This is the default.
+
+@item never
+@itemx simple
+Always make simple backups.
+@end table
+
+You can also tell @command{patch} to prepend a prefix, such as a
+directory name, to produce backup file names. The @option{-B
+@var{prefix}} or @option{--prefix=@var{prefix}} option makes backup
+files by prepending @var{prefix} to them. The @option{-Y
+@var{prefix}} or @option{--basename-prefix=@var{prefix}} prepends
+@var{prefix} to the last file name component of backup file names
+instead; for example, @option{-Y ~} causes the backup name for
+@file{dir/file.c} to be @file{dir/~file.c}. If you use either of
+these prefix options, the suffix-based options are ignored.
+
+If you specify the output file with the @option{-o} option, that file is
+the one that is backed up, not the input file.
+
+Options that affect the names of backup files do not affect whether
+backups are made. For example, if you specify the
+@option{--no-backup-if-mismatch} option, none of the options described
+in this section have any affect, because no backups are made.
+
+@node Reject Names
+@section Reject File Names
+@cindex reject file names
+
+The names for reject files (files containing patches that
+@command{patch} could not find a place to apply) are normally the name
+of the output file with @samp{.rej} appended (or @samp{#} if using
+@samp{.rej} would make the backup file name too long).
+
+Alternatively, you can tell @command{patch} to place all of the rejected
+patches in a single file. The @option{-r @var{reject-file}} or
+@option{--reject-file=@var{reject-file}} option uses @var{reject-file} as
+the reject file name.
+
+@node patch Messages
+@section Messages and Questions from @command{patch}
+@cindex @command{patch} messages and questions
+@cindex diagnostics from @command{patch}
+@cindex messages from @command{patch}
+
+@command{patch} can produce a variety of messages, especially if it
+has trouble decoding its input. In a few situations where it's not
+sure how to proceed, @command{patch} normally prompts you for more
+information from the keyboard. There are options to produce more or
+fewer messages, to have it not ask for keyboard input, and to
+affect the way that file names are quoted in messages.
+
+@menu
+* More or Fewer Messages:: Controlling the verbosity of @command{patch}.
+* patch and Keyboard Input:: Inhibiting keyboard input.
+* patch Quoting Style:: Quoting file names in diagnostics.
+@end menu
+
+@command{patch} exits with status 0 if all hunks are applied successfully,
+1 if some hunks cannot be applied, and 2 if there is more serious trouble.
+When applying a set of patches in a loop, you should check the
+exit status, so you don't apply a later patch to a partially patched
+file.
+
+@node More or Fewer Messages
+@subsection Controlling the Verbosity of @command{patch}
+@cindex verbose messages from @command{patch}
+@cindex inhibit messages from @command{patch}
+
+You can cause @command{patch} to produce more messages by using the
+@option{--verbose} option. For example, when you give this option,
+the message @samp{Hmm...} indicates that @command{patch} is reading text in
+the patch file, attempting to determine whether there is a patch in that
+text, and if so, what kind of patch it is.
+
+You can inhibit all terminal output from @command{patch}, unless an error
+occurs, by using the @option{-s}, @option{--quiet}, or @option{--silent}
+option.
+
+@node patch and Keyboard Input
+@subsection Inhibiting Keyboard Input
+@cindex keyboard input to @command{patch}
+
+There are two ways you can prevent @command{patch} from asking you any
+questions. The @option{-f} or @option{--force} option assumes that you know
+what you are doing. It causes @command{patch} to do the following:
+
+@itemize @bullet
+@item
+Skip patches that do not contain file names in their headers.
+
+@item
+Patch files even though they have the wrong version for the
+@samp{Prereq:} line in the patch;
+
+@item
+Assume that patches are not reversed even if they look like they are.
+@end itemize
+
+@noindent
+The @option{-t} or @option{--batch} option is similar to @option{-f}, in that
+it suppresses questions, but it makes somewhat different assumptions:
+
+@itemize @bullet
+@item
+Skip patches that do not contain file names in their headers
+(the same as @option{-f}).
+
+@item
+Skip patches for which the file has the wrong version for the
+@samp{Prereq:} line in the patch;
+
+@item
+Assume that patches are reversed if they look like they are.
+@end itemize
+
+@node patch Quoting Style
+@subsection @command{patch} Quoting Style
+@cindex quoting style
+
+When @command{patch} outputs a file name in a diagnostic message, it
+can format the name in any of several ways. This can be useful to
+output file names unambiguously, even if they contain punctuation or
+special characters like newlines. The
+@option{--quoting-style=@var{word}} option controls how names are
+output. The @var{word} should be one of the following:
+
+@table @samp
+@item literal
+Output names as-is.
+@item shell
+Quote names for the shell if they contain shell metacharacters or would
+cause ambiguous output.
+@item shell-always
+Quote names for the shell, even if they would normally not require quoting.
+@item c
+Quote names as for a C language string.
+@item escape
+Quote as with @samp{c} except omit the surrounding double-quote
+characters.
+@c The following are not yet implemented in patch 2.5.4.
+@c @item clocale
+@c Quote as with @samp{c} except use quotation marks appropriate for the
+@c locale.
+@c @item locale
+@c @c Use @t instead of @samp to avoid duplicate quoting in some output styles.
+@c Like @samp{clocale}, but quote @t{`like this'} instead of @t{"like
+@c this"} in the default C locale. This looks nicer on many displays.
+@end table
+
+@vindex QUOTING_STYLE
+You can specify the default value of the @option{--quoting-style}
+option with the environment variable @env{QUOTING_STYLE}. If that
+environment variable is not set, the default value is @samp{shell},
+but this default may change in a future version of @command{patch}.
+
+@node patch and POSIX
+@section @command{patch} and the @acronym{POSIX} Standard
+@cindex @acronym{POSIX}
+
+@vindex POSIXLY_CORRECT
+If you specify the @option{--posix} option, or set the
+@env{POSIXLY_CORRECT} environment variable, @command{patch} conforms
+more strictly to the @acronym{POSIX} standard, as follows:
+
+@itemize @bullet
+@item
+Take the first existing file from the list (old, new, index)
+when intuiting file names from diff headers. @xref{Multiple Patches}.
+
+@item
+Do not remove files that are removed by a diff.
+@xref{Creating and Removing}.
+
+@item
+Do not ask whether to get files from @acronym{RCS}, ClearCase, or
+@acronym{SCCS}. @xref{Revision Control}.
+
+@item
+Require that all options precede the files in the command line.
+
+@item
+Do not backup files, even when there is a mismatch. @xref{Backups}.
+
+@end itemize
+
+@node patch and Tradition
+@section @acronym{GNU} @command{patch} and Traditional @command{patch}
+@cindex traditional @command{patch}
+
+The current version of @acronym{GNU} @command{patch} normally follows the
+@acronym{POSIX} standard. @xref{patch and POSIX}, for the few exceptions
+to this general rule.
+
+Unfortunately, @acronym{POSIX} redefined the behavior of @command{patch} in
+several important ways. You should be aware of the following
+differences if you must interoperate with traditional @command{patch},
+or with @acronym{GNU} @command{patch} version 2.1 and earlier.
+
+@itemize @bullet
+@item
+In traditional @command{patch}, the @option{-p} option's operand was
+optional, and a bare @option{-p} was equivalent to @option{-p0}. The
+@option{-p} option now requires an operand, and @option{-p@ 0} is now
+equivalent to @option{-p0}. For maximum compatibility, use options
+like @option{-p0} and @option{-p1}.
+
+Also, traditional @command{patch} simply counted slashes when
+stripping path prefixes; @command{patch} now counts pathname
+components. That is, a sequence of one or more adjacent slashes now
+counts as a single slash. For maximum portability, avoid sending
+patches containing @file{//} in file names.
+
+@item
+In traditional @command{patch}, backups were enabled by default. This
+behavior is now enabled with the @option{-b} or @option{--backup}
+option.
+
+Conversely, in @acronym{POSIX} @command{patch}, backups are never made,
+even when there is a mismatch. In @acronym{GNU} @command{patch}, this
+behavior is enabled with the @option{--no-backup-if-mismatch} option,
+or by conforming to @acronym{POSIX}.
+
+The @option{-b@ @var{suffix}} option of traditional @command{patch} is
+equivalent to the @samp{-b -z@ @var{suffix}} options of @acronym{GNU}
+@command{patch}.
+
+@item
+Traditional @command{patch} used a complicated (and incompletely
+documented) method to intuit the name of the file to be patched from
+the patch header. This method did not conform to @acronym{POSIX}, and had
+a few gotchas. Now @command{patch} uses a different, equally
+complicated (but better documented) method that is optionally
+@acronym{POSIX}-conforming; we hope it has fewer gotchas. The two methods
+are compatible if the file names in the context diff header and the
+@samp{Index:} line are all identical after prefix-stripping. Your
+patch is normally compatible if each header's file names all contain
+the same number of slashes.
+
+@item
+When traditional @command{patch} asked the user a question, it sent
+the question to standard error and looked for an answer from the first
+file in the following list that was a terminal: standard error,
+standard output, @file{/dev/tty}, and standard input. Now
+@command{patch} sends questions to standard output and gets answers
+from @file{/dev/tty}. Defaults for some answers have been changed so
+that @command{patch} never goes into an infinite loop when using
+default answers.
+
+@item
+Traditional @command{patch} exited with a status value that counted
+the number of bad hunks, or with status 1 if there was real trouble.
+Now @command{patch} exits with status 1 if some hunks failed, or with
+2 if there was real trouble.
+
+@item
+Limit yourself to the following options when sending instructions
+meant to be executed by anyone running @acronym{GNU} @command{patch},
+traditional @command{patch}, or a @command{patch} that conforms to
+@acronym{POSIX}. Spaces are significant in the following list, and
+operands are required.
+
+@example
+@option{-c}
+@option{-d @var{dir}}
+@option{-D @var{define}}
+@option{-e}
+@option{-l}
+@option{-n}
+@option{-N}
+@option{-o @var{outfile}}
+@option{-p@var{num}}
+@option{-R}
+@option{-r @var{rejectfile}}
+@end example
+
+@end itemize
+
+@node Making Patches
+@chapter Tips for Making and Using Patches
+
+Use some common sense when making and using patches. For example,
+when sending bug fixes to a program's maintainer, send several small
+patches, one per independent subject, instead of one large,
+harder-to-digest patch that covers all the subjects.
+
+Here are some other things you should keep in mind if you are going to
+distribute patches for updating a software package.
+
+@menu
+* Tips for Patch Producers:: Advice for making patches.
+* Tips for Patch Consumers:: Advice for using patches.
+* Avoiding Common Mistakes:: Avoiding common mistakes when using @command{patch}.
+* Generating Smaller Patches:: How to generate smaller patches.
+@end menu
+
+@node Tips for Patch Producers
+@section Tips for Patch Producers
+@cindex patch producer tips
+
+To create a patch that changes an older version of a package into a
+newer version, first make a copy of the older and newer versions in
+adjacent subdirectories. It is common to do that by unpacking
+@command{tar} archives of the two versions.
+
+To generate the patch, use the command @samp{diff -Naur @var{old}
+@var{new}} where @var{old} and @var{new} identify the old and new
+directories. The names @var{old} and @var{new} should not contain any
+slashes. The @option{-N} option lets the patch create and remove
+files; @option{-a} lets the patch update non-text files; @option{-u}
+generates useful time stamps and enough context; and @option{-r} lets
+the patch update subdirectories. Here is an example command, using
+Bourne shell syntax:
+
+@example
+diff -Naur gcc-3.0.3 gcc-3.0.4
+@end example
+
+Tell your recipients how to apply the patches. This should include
+which working directory to use, and which @command{patch} options to
+use; the option @samp{-p1} is recommended. Test your procedure by
+pretending to be a recipient and applying your patches to a copy of
+the original files.
+
+@xref{Avoiding Common Mistakes}, for how to avoid common mistakes when
+generating a patch.
+
+@node Tips for Patch Consumers
+@section Tips for Patch Consumers
+@cindex patch consumer tips
+
+A patch producer should tell recipients how to apply the patches, so
+the first rule of thumb for a patch consumer is to follow the
+instructions supplied with the patch.
+
+@acronym{GNU} @command{diff} can analyze files with arbitrarily long lines
+and files that end in incomplete lines. However, older versions of
+@command{patch} cannot patch such files. If you are having trouble
+applying such patches, try upgrading to a recent version of @acronym{GNU}
+@command{patch}.
+
+@node Avoiding Common Mistakes
+@section Avoiding Common Mistakes
+@cindex common mistakes with patches
+@cindex patch, common mistakes
+
+When producing a patch for multiple files, apply @command{diff} to
+directories whose names do not have slashes. This reduces confusion
+when the patch consumer specifies the @option{-p@var{number}} option,
+since this option can have surprising results when the old and new
+file names have different numbers of slashes. For example, do not
+send a patch with a header that looks like this:
+
+@example
+diff -Naur v2.0.29/prog/README prog/README
+--- v2.0.29/prog/README 2002-03-10 23:30:39.942229878 -0800
++++ prog/README 2002-03-17 20:49:32.442260588 -0800
+@end example
+
+@noindent
+because the two file names have different numbers of slashes, and
+different versions of @command{patch} interpret the file names
+differently. To avoid confusion, send output that looks like this
+instead:
+
+@example
+diff -Naur v2.0.29/prog/README v2.0.30/prog/README
+--- v2.0.29/prog/README 2002-03-10 23:30:39.942229878 -0800
++++ v2.0.30/prog/README 2002-03-17 20:49:32.442260588 -0800
+@end example
+
+Make sure you have specified the file names correctly, either in a
+context diff header or with an @samp{Index:} line. Take care to not send out
+reversed patches, since these make people wonder whether they have
+already applied the patch.
+
+Avoid sending patches that compare backup file names like
+@file{README.orig} or @file{README~}, since this might confuse
+@command{patch} into patching a backup file instead of the real file.
+Instead, send patches that compare the same base file names in
+different directories, e.g.@: @file{old/README} and @file{new/README}.
+
+To save people from partially applying a patch before other patches that
+should have gone before it, you can make the first patch in the patch
+file update a file with a name like @file{patchlevel.h} or
+@file{version.c}, which contains a patch level or version number. If
+the input file contains the wrong version number, @command{patch} will
+complain immediately.
+
+An even clearer way to prevent this problem is to put a @samp{Prereq:}
+line before the patch. If the leading text in the patch file contains a
+line that starts with @samp{Prereq:}, @command{patch} takes the next word
+from that line (normally a version number) and checks whether the next
+input file contains that word, preceded and followed by either
+white space or a newline. If not, @command{patch} prompts you for
+confirmation before proceeding. This makes it difficult to accidentally
+apply patches in the wrong order.
+
+@node Generating Smaller Patches
+@section Generating Smaller Patches
+@cindex patches, shrinking
+
+The simplest way to generate a patch is to use @samp{diff -Naur}
+(@pxref{Tips for Patch Producers}), but you might be able to reduce
+the size of the patch by renaming or removing some files before making
+the patch. If the older version of the package contains any files
+that the newer version does not, or if any files have been renamed
+between the two versions, make a list of @command{rm} and @command{mv}
+commands for the user to execute in the old version directory before
+applying the patch. Then run those commands yourself in the scratch
+directory.
+
+If there are any files that you don't need to include in the patch
+because they can easily be rebuilt from other files (for example,
+@file{TAGS} and output from @command{yacc} and @command{makeinfo}),
+exclude them from the patch by giving @command{diff} the @option{-x
+@var{pattern}} option (@pxref{Comparing Directories}). If you want
+your patch to modify a derived file because your recipients lack tools
+to build it, make sure that the patch for the derived file follows any
+patches for files that it depends on, so that the recipients' time
+stamps will not confuse @command{make}.
+
+Now you can create the patch using @samp{diff -Naur}. Make sure to
+specify the scratch directory first and the newer directory second.
+
+Add to the top of the patch a note telling the user any @command{rm} and
+@command{mv} commands to run before applying the patch. Then you can
+remove the scratch directory.
+
+You can also shrink the patch size by using fewer lines of context,
+but bear in mind that @command{patch} typically needs at least two
+lines for proper operation when patches do not exactly match the input
+files.
+
+@node Invoking cmp
+@chapter Invoking @command{cmp}
+@cindex invoking @command{cmp}
+@cindex @command{cmp} invocation
+
+The @command{cmp} command compares two files, and if they differ,
+tells the first byte and line number where they differ or reports
+that one file is a prefix of the other. Bytes and
+lines are numbered starting with 1. The arguments of @command{cmp}
+are as follows:
+
+@example
+cmp @var{options}@dots{} @var{from-file} @r{[}@var{to-file} @r{[}@var{from-skip} @r{[}@var{to-skip}@r{]}@r{]}@r{]}
+@end example
+
+The file name @file{-} is always the standard input. @command{cmp}
+also uses the standard input if one file name is omitted. The
+@var{from-skip} and @var{to-skip} operands specify how many bytes to
+ignore at the start of each file; they are equivalent to the
+@option{--ignore-initial=@var{from-skip}:@var{to-skip}} option.
+
+By default, @command{cmp} outputs nothing if the two files have the
+same contents. If one file is a prefix of the other, @command{cmp}
+prints to standard error a message of the following form:
+
+@example
+cmp: EOF on @var{shorter-file}
+@end example
+
+Otherwise, @command{cmp} prints to standard output a message of the
+following form:
+
+@example
+@var{from-file} @var{to-file} differ: char @var{byte-number}, line @var{line-number}
+@end example
+
+The message formats can differ outside the @acronym{POSIX} locale.
+Also, @acronym{POSIX} allows the @acronym{EOF} message to be followed
+by a blank and some additional information.
+
+An exit status of 0 means no differences were found, 1 means some
+differences were found, and 2 means trouble.
+
+@menu
+* cmp Options:: Summary of options to @command{cmp}.
+@end menu
+
+@node cmp Options
+@section Options to @command{cmp}
+@cindex @command{cmp} options
+@cindex options for @command{cmp}
+
+Below is a summary of all of the options that @acronym{GNU}
+@command{cmp} accepts. Most options have two equivalent names, one of
+which is a single letter preceded by @samp{-}, and the other of which
+is a long name preceded by @samp{--}. Multiple single letter options
+(unless they take an argument) can be combined into a single command
+line word: @option{-bl} is equivalent to @option{-b -l}.
+
+@table @option
+@item -b
+@itemx --print-bytes
+Print the differing bytes. Display control bytes as a
+@samp{^} followed by a letter of the alphabet and precede bytes
+that have the high bit set with @samp{M-} (which stands for ``meta'').
+
+@item --help
+Output a summary of usage and then exit.
+
+@item -i @var{skip}
+@itemx --ignore-initial=@var{skip}
+Ignore any differences in the first @var{skip} bytes of the input
+files. Treat files with fewer than @var{skip} bytes as if they are
+empty. If @var{skip} is of the form
+@option{@var{from-skip}:@var{to-skip}}, skip the first @var{from-skip}
+bytes of the first input file and the first @var{to-skip} bytes of the
+second.
+
+@item -l
+@itemx --verbose
+Output the (decimal) byte numbers and (octal) values of all differing bytes,
+instead of the default standard output.
+
+@item -n @var{count}
+@itemx --bytes=@var{count}
+Compare at most @var{count} input bytes.
+
+@item -s
+@itemx --quiet
+@itemx --silent
+Do not print anything; only return an exit status indicating whether
+the files differ.
+
+@item -v
+@itemx --version
+Output version information and then exit.
+@end table
+
+In the above table, operands that are byte counts are normally
+decimal, but may be preceded by @samp{0} for octal and @samp{0x} for
+hexadecimal.
+
+A byte count can be followed by a suffix to specify a multiple of that
+count; in this case an omitted integer is understood to be 1. A bare
+size letter, or one followed by @samp{iB}, specifies a multiple using
+powers of 1024. A size letter followed by @samp{B} specifies powers
+of 1000 instead. For example, @option{-n 4M} and @option{-n 4MiB} are
+equivalent to @option{-n 4194304}, whereas @option{-n 4MB} is
+equivalent to @option{-n 4000000}. This notation is upward compatible
+with the @uref{http://www.bipm.fr/enus/3_SI/si-prefixes.html, SI
+prefixes} for decimal multiples and with the
+@uref{http://physics.nist.gov/cuu/Units/binary.html, IEC 60027-2
+prefixes for binary multiples}.
+
+The following suffixes are defined. Large sizes like @code{1Y} may be
+rejected by your computer due to limitations of its arithmetic.
+
+@table @samp
+@item kB
+@cindex kilobyte, definition of
+kilobyte: @math{10^3 = 1000}.
+@item k
+@itemx K
+@itemx KiB
+@cindex kibibyte, definition of
+kibibyte: @math{2^10 = 1024}. @samp{K} is special: the SI prefix is
+@samp{k} and the IEC 60027-2 prefix is @samp{Ki}, but tradition and
+@acronym{POSIX} use @samp{k} to mean @samp{KiB}.
+@item MB
+@cindex megabyte, definition of
+megabyte: @math{10^6 = 1,000,000}.
+@item M
+@itemx MiB
+@cindex mebibyte, definition of
+mebibyte: @math{2^20 = 1,048,576}.
+@item GB
+@cindex gigabyte, definition of
+gigabyte: @math{10^9 = 1,000,000,000}.
+@item G
+@itemx GiB
+@cindex gibibyte, definition of
+gibibyte: @math{2^30 = 1,073,741,824}.
+@item TB
+@cindex terabyte, definition of
+terabyte: @math{10^12 = 1,000,000,000,000}.
+@item T
+@itemx TiB
+@cindex tebibyte, definition of
+tebibyte: @math{2^40 = 1,099,511,627,776}.
+@item PB
+@cindex petabyte, definition of
+petabyte: @math{10^15 = 1,000,000,000,000,000}.
+@item P
+@itemx PiB
+@cindex pebibyte, definition of
+pebibyte: @math{2^50 = 1,125,899,906,842,624}.
+@item EB
+@cindex exabyte, definition of
+exabyte: @math{10^18 = 1,000,000,000,000,000,000}.
+@item E
+@itemx EiB
+@cindex exbibyte, definition of
+exbibyte: @math{2^60 = 1,152,921,504,606,846,976}.
+@item ZB
+@cindex zettabyte, definition of
+zettabyte: @math{10^21 = 1,000,000,000,000,000,000,000}
+@item Z
+@itemx ZiB
+@math{2^70 = 1,180,591,620,717,411,303,424}.
+(@samp{Zi} is a GNU extension to IEC 60027-2.)
+@item YB
+@cindex yottabyte, definition of
+yottabyte: @math{10^24 = 1,000,000,000,000,000,000,000,000}.
+@item Y
+@itemx YiB
+@math{2^80 = 1,208,925,819,614,629,174,706,176}.
+(@samp{Yi} is a GNU extension to IEC 60027-2.)
+@end table
+
+@node Invoking diff
+@chapter Invoking @command{diff}
+@cindex invoking @command{diff}
+@cindex @command{diff} invocation
+
+The format for running the @command{diff} command is:
+
+@example
+diff @var{options}@dots{} @var{files}@dots{}
+@end example
+
+In the simplest case, two file names @var{from-file} and
+@var{to-file} are given, and @command{diff} compares the contents of
+@var{from-file} and @var{to-file}. A file name of @file{-} stands for
+text read from the standard input. As a special case, @samp{diff - -}
+compares a copy of standard input to itself.
+
+If one file is a directory and the other is not, @command{diff} compares
+the file in the directory whose name is that of the non-directory.
+The non-directory file must not be @file{-}.
+
+If two file names are given and both are directories,
+@command{diff} compares corresponding files in both directories, in
+alphabetical order; this comparison is not recursive unless the
+@option{-r} or @option{--recursive} option is given. @command{diff} never
+compares the actual contents of a directory as if it were a file. The
+file that is fully specified may not be standard input, because standard
+input is nameless and the notion of ``file with the same name'' does not
+apply.
+
+If the @option{--from-file=@var{file}} option is given, the number of
+file names is arbitrary, and @var{file} is compared to each named file.
+Similarly, if the @option{--to-file=@var{file}} option is given, each
+named file is compared to @var{file}.
+
+@command{diff} options begin with @samp{-}, so normally file names
+may not begin with @samp{-}. However, @option{--} as an
+argument by itself treats the remaining arguments as file names even if
+they begin with @samp{-}.
+
+An exit status of 0 means no differences were found, 1 means some
+differences were found, and 2 means trouble. Normally, differing
+binary files count as trouble, but this can be altered by using the
+@option{-a} or @option{--text} option, or the @option{-q} or
+@option{--brief} option.
+
+@menu
+* diff Options:: Summary of options to @command{diff}.
+@end menu
+
+@node diff Options
+@section Options to @command{diff}
+@cindex @command{diff} options
+@cindex options for @command{diff}
+
+Below is a summary of all of the options that @acronym{GNU}
+@command{diff} accepts. Most options have two equivalent names, one
+of which is a single letter preceded by @samp{-}, and the other of
+which is a long name preceded by @samp{--}. Multiple single letter
+options (unless they take an argument) can be combined into a single
+command line word: @option{-ac} is equivalent to @option{-a -c}. Long
+named options can be abbreviated to any unique prefix of their name.
+Brackets ([ and ]) indicate that an option takes an optional argument.
+
+@table @option
+@item -a
+@itemx --text
+Treat all files as text and compare them line-by-line, even if they
+do not seem to be text. @xref{Binary}.
+
+@item -b
+@itemx --ignore-space-change
+Ignore changes in amount of white space. @xref{White Space}.
+
+@item -B
+@itemx --ignore-blank-lines
+Ignore changes that just insert or delete blank lines. @xref{Blank
+Lines}.
+
+@item --binary
+Read and write data in binary mode. @xref{Binary}.
+
+@item -c
+Use the context output format, showing three lines of context.
+@xref{Context Format}.
+
+@item -C @var{lines}
+@itemx --context@r{[}=@var{lines}@r{]}
+Use the context output format, showing @var{lines} (an integer) lines of
+context, or three if @var{lines} is not given. @xref{Context Format}.
+For proper operation, @command{patch} typically needs at least two lines of
+context.
+
+On older systems, @command{diff} supports an obsolete option
+@option{-@var{lines}} that has effect when combined with @option{-c}
+or @option{-p}. @acronym{POSIX} 1003.1-2001 (@pxref{Standards
+conformance}) does not allow this; use @option{-C @var{lines}}
+instead.
+
+@item --changed-group-format=@var{format}
+Use @var{format} to output a line group containing differing lines from
+both files in if-then-else format. @xref{Line Group Formats}.
+
+@item -d
+@itemx --minimal
+Change the algorithm perhaps find a smaller set of changes. This makes
+@command{diff} slower (sometimes much slower). @xref{diff Performance}.
+
+@item -D @var{name}
+@itemx --ifdef=@var{name}
+Make merged @samp{#ifdef} format output, conditional on the preprocessor
+macro @var{name}. @xref{If-then-else}.
+
+@item -e
+@itemx --ed
+Make output that is a valid @command{ed} script. @xref{ed Scripts}.
+
+@item -E
+@itemx --ignore-tab-expansion
+Ignore changes due to tab expansion.
+@xref{White Space}.
+
+@item -f
+@itemx --forward-ed
+Make output that looks vaguely like an @command{ed} script but has changes
+in the order they appear in the file. @xref{Forward ed}.
+
+@item -F @var{regexp}
+@itemx --show-function-line=@var{regexp}
+In context and unified format, for each hunk of differences, show some
+of the last preceding line that matches @var{regexp}. @xref{Specified
+Headings}.
+
+@item --from-file=@var{file}
+Compare @var{file} to each operand; @var{file} may be a directory.
+
+@item --help
+Output a summary of usage and then exit.
+
+@item --horizon-lines=@var{lines}
+Do not discard the last @var{lines} lines of the common prefix
+and the first @var{lines} lines of the common suffix.
+@xref{diff Performance}.
+
+@item -i
+@itemx --ignore-case
+Ignore changes in case; consider upper- and lower-case letters
+equivalent. @xref{Case Folding}.
+
+@item -I @var{regexp}
+@itemx --ignore-matching-lines=@var{regexp}
+Ignore changes that just insert or delete lines that match @var{regexp}.
+@xref{Specified Lines}.
+
+@item --ignore-file-name-case
+Ignore case when comparing file names during recursive comparison.
+@xref{Comparing Directories}.
+
+@item -l
+@itemx --paginate
+Pass the output through @command{pr} to paginate it. @xref{Pagination}.
+
+@item --label=@var{label}
+Use @var{label} instead of the file name in the context format
+(@pxref{Context Format}) and unified format (@pxref{Unified Format})
+headers. @xref{RCS}.
+
+@item --left-column
+Print only the left column of two common lines in side by side format.
+@xref{Side by Side Format}.
+
+@item --line-format=@var{format}
+Use @var{format} to output all input lines in if-then-else format.
+@xref{Line Formats}.
+
+@item -n
+@itemx --rcs
+Output @acronym{RCS}-format diffs; like @option{-f} except that each command
+specifies the number of lines affected. @xref{RCS}.
+
+@item -N
+@itemx --new-file
+In directory comparison, if a file is found in only one directory,
+treat it as present but empty in the other directory. @xref{Comparing
+Directories}.
+
+@item --new-group-format=@var{format}
+Use @var{format} to output a group of lines taken from just the second
+file in if-then-else format. @xref{Line Group Formats}.
+
+@item --new-line-format=@var{format}
+Use @var{format} to output a line taken from just the second file in
+if-then-else format. @xref{Line Formats}.
+
+@item --old-group-format=@var{format}
+Use @var{format} to output a group of lines taken from just the first
+file in if-then-else format. @xref{Line Group Formats}.
+
+@item --old-line-format=@var{format}
+Use @var{format} to output a line taken from just the first file in
+if-then-else format. @xref{Line Formats}.
+
+@item -p
+@itemx --show-c-function
+Show which C function each change is in. @xref{C Function Headings}.
+
+@item -q
+@itemx --brief
+Report only whether the files differ, not the details of the
+differences. @xref{Brief}.
+
+@item -r
+@itemx --recursive
+When comparing directories, recursively compare any subdirectories
+found. @xref{Comparing Directories}.
+
+@item -s
+@itemx --report-identical-files
+Report when two files are the same. @xref{Comparing Directories}.
+
+@item -S @var{file}
+@itemx --starting-file=@var{file}
+When comparing directories, start with the file @var{file}. This is
+used for resuming an aborted comparison. @xref{Comparing Directories}.
+
+@item --speed-large-files
+Use heuristics to speed handling of large files that have numerous
+scattered small changes. @xref{diff Performance}.
+
+@item --strip-trailing-cr
+Strip any trailing carriage return at the end of an input line.
+@xref{Binary}.
+
+@item --suppress-common-lines
+Do not print common lines in side by side format.
+@xref{Side by Side Format}.
+
+@item -t
+@itemx --expand-tabs
+Expand tabs to spaces in the output, to preserve the alignment of tabs
+in the input files. @xref{Tabs}.
+
+@item -T
+@itemx --initial-tab
+Output a tab rather than a space before the text of a line in normal or
+context format. This causes the alignment of tabs in the line to look
+normal. @xref{Tabs}.
+
+@item --tabsize=@var{columns}
+Assume that tab stops are set every @var{columns} (default 8) print
+columns. @xref{Tabs}.
+
+@item --to-file=@var{file}
+Compare each operand to @var{file}; @var{file} may be a directory.
+
+@item -u
+Use the unified output format, showing three lines of context.
+@xref{Unified Format}.
+
+@item --unchanged-group-format=@var{format}
+Use @var{format} to output a group of common lines taken from both files
+in if-then-else format. @xref{Line Group Formats}.
+
+@item --unchanged-line-format=@var{format}
+Use @var{format} to output a line common to both files in if-then-else
+format. @xref{Line Formats}.
+
+@item --unidirectional-new-file
+When comparing directories, if a file appears only in the second
+directory of the two, treat it as present but empty in the other.
+@xref{Comparing Directories}.
+
+@item -U @var{lines}
+@itemx --unified@r{[}=@var{lines}@r{]}
+Use the unified output format, showing @var{lines} (an integer) lines of
+context, or three if @var{lines} is not given. @xref{Unified Format}.
+For proper operation, @command{patch} typically needs at least two lines of
+context.
+
+On older systems, @command{diff} supports an obsolete option
+@option{-@var{lines}} that has effect when combined with @option{-u}.
+@acronym{POSIX} 1003.1-2001 (@pxref{Standards conformance}) does not allow
+this; use @option{-U @var{lines}} instead.
+
+@item -v
+@itemx --version
+Output version information and then exit.
+
+@item -w
+@itemx --ignore-all-space
+Ignore white space when comparing lines. @xref{White Space}.
+
+@item -W @var{columns}
+@itemx --width=@var{columns}
+Output at most @var{columns} (default 130) print columns per line in
+side by side format. @xref{Side by Side Format}.
+
+@item -x @var{pattern}
+@itemx --exclude=@var{pattern}
+When comparing directories, ignore files and subdirectories whose basenames
+match @var{pattern}. @xref{Comparing Directories}.
+
+@item -X @var{file}
+@itemx --exclude-from=@var{file}
+When comparing directories, ignore files and subdirectories whose basenames
+match any pattern contained in @var{file}. @xref{Comparing Directories}.
+
+@item -y
+@itemx --side-by-side
+Use the side by side output format. @xref{Side by Side Format}.
+@end table
+
+@node Invoking diff3
+@chapter Invoking @command{diff3}
+@cindex invoking @command{diff3}
+@cindex @command{diff3} invocation
+
+The @command{diff3} command compares three files and outputs descriptions
+of their differences. Its arguments are as follows:
+
+@example
+diff3 @var{options}@dots{} @var{mine} @var{older} @var{yours}
+@end example
+
+The files to compare are @var{mine}, @var{older}, and @var{yours}.
+At most one of these three file names may be @file{-},
+which tells @command{diff3} to read the standard input for that file.
+
+An exit status of 0 means @command{diff3} was successful, 1 means some
+conflicts were found, and 2 means trouble.
+
+@menu
+* diff3 Options:: Summary of options to @command{diff3}.
+@end menu
+
+@node diff3 Options
+@section Options to @command{diff3}
+@cindex @command{diff3} options
+@cindex options for @command{diff3}
+
+Below is a summary of all of the options that @acronym{GNU} @command{diff3}
+accepts. Multiple single letter options (unless they take an argument)
+can be combined into a single command line argument.
+
+@table @option
+@item -a
+@itemx --text
+Treat all files as text and compare them line-by-line, even if they
+do not appear to be text. @xref{Binary}.
+
+@item -A
+@itemx --show-all
+Incorporate all unmerged changes from @var{older} to @var{yours} into
+@var{mine}, surrounding conflicts with bracket lines.
+@xref{Marking Conflicts}.
+
+@item --diff-program=@var{program}
+Use the compatible comparison program @var{program} to compare files
+instead of @command{diff}.
+
+@item -e
+@itemx --ed
+Generate an @command{ed} script that incorporates all the changes from
+@var{older} to @var{yours} into @var{mine}. @xref{Which Changes}.
+
+@item -E
+@itemx --show-overlap
+Like @option{-e}, except bracket lines from overlapping changes' first
+and third files.
+@xref{Marking Conflicts}.
+With @option{-E}, an overlapping change looks like this:
+
+@example
+<<<<<<< @var{mine}
+@r{lines from @var{mine}}
+=======
+@r{lines from @var{yours}}
+>>>>>>> @var{yours}
+@end example
+
+@item --help
+Output a summary of usage and then exit.
+
+@item -i
+Generate @samp{w} and @samp{q} commands at the end of the @command{ed}
+script for System V compatibility. This option must be combined with
+one of the @option{-AeExX3} options, and may not be combined with @option{-m}.
+@xref{Saving the Changed File}.
+
+@item --label=@var{label}
+Use the label @var{label} for the brackets output by the @option{-A},
+@option{-E} and @option{-X} options. This option may be given up to three
+times, one for each input file. The default labels are the names of
+the input files. Thus @samp{diff3 --label X --label Y --label Z -m A
+B C} acts like
+@samp{diff3 -m A B C}, except that the output looks like it came from
+files named @samp{X}, @samp{Y} and @samp{Z} rather than from files
+named @samp{A}, @samp{B} and @samp{C}. @xref{Marking Conflicts}.
+
+@item -m
+@itemx --merge
+Apply the edit script to the first file and send the result to standard
+output. Unlike piping the output from @command{diff3} to @command{ed}, this
+works even for binary files and incomplete lines. @option{-A} is assumed
+if no edit script option is specified. @xref{Bypassing ed}.
+
+@item --strip-trailing-cr
+Strip any trailing carriage return at the end of an input line.
+@xref{Binary}.
+
+@item -T
+@itemx --initial-tab
+Output a tab rather than two spaces before the text of a line in normal format.
+This causes the alignment of tabs in the line to look normal. @xref{Tabs}.
+
+@item -v
+@itemx --version
+Output version information and then exit.
+
+@item -x
+@itemx --overlap-only
+Like @option{-e}, except output only the overlapping changes.
+@xref{Which Changes}.
+
+@item -X
+Like @option{-E}, except output only the overlapping changes.
+In other words, like @option{-x}, except bracket changes as in @option{-E}.
+@xref{Marking Conflicts}.
+
+@item -3
+@itemx --easy-only
+Like @option{-e}, except output only the nonoverlapping changes.
+@xref{Which Changes}.
+@end table
+
+@node Invoking patch
+@chapter Invoking @command{patch}
+@cindex invoking @command{patch}
+@cindex @command{patch} invocation
+
+Normally @command{patch} is invoked like this:
+
+@example
+patch <@var{patchfile}
+@end example
+
+The full format for invoking @command{patch} is:
+
+@example
+patch @var{options}@dots{} @r{[}@var{origfile} @r{[}@var{patchfile}@r{]}@r{]}
+@end example
+
+You can also specify where to read the patch from with the @option{-i
+@var{patchfile}} or @option{--input=@var{patchfile}} option.
+If you do not specify @var{patchfile}, or if @var{patchfile} is
+@file{-}, @command{patch} reads the patch (that is, the @command{diff} output)
+from the standard input.
+
+If you do not specify an input file on the command line, @command{patch}
+tries to intuit from the @dfn{leading text} (any text in the patch
+that comes before the @command{diff} output) which file to edit.
+@xref{Multiple Patches}.
+
+By default, @command{patch} replaces the original input file with the
+patched version, possibly after renaming the original file into a
+backup file (@pxref{Backup Names}, for a description of how
+@command{patch} names backup files). You can also specify where to
+put the output with the @option{-o @var{file}} or
+@option{--output=@var{file}} option; however, do not use this option
+if @var{file} is one of the input files.
+
+@menu
+* patch Options:: Summary table of options to @command{patch}.
+@end menu
+
+@node patch Options
+@section Options to @command{patch}
+@cindex @command{patch} options
+@cindex options for @command{patch}
+
+Here is a summary of all of the options that @acronym{GNU} @command{patch}
+accepts. @xref{patch and Tradition}, for which of these options are
+safe to use in older versions of @command{patch}.
+
+Multiple single-letter options that do not take an argument can be
+combined into a single command line argument with only one dash.
+
+@table @option
+@item -b
+@itemx --backup
+Back up the original contents of each file, even if backups would
+normally not be made. @xref{Backups}.
+
+@item -B @var{prefix}
+@itemx --prefix=@var{prefix}
+Prepend @var{prefix} to backup file names. @xref{Backup Names}.
+
+@item --backup-if-mismatch
+Back up the original contents of each file if the patch does not
+exactly match the file. This is the default behavior when not
+conforming to @acronym{POSIX}. @xref{Backups}.
+
+@item --binary
+Read and write all files in binary mode, except for standard output
+and @file{/dev/tty}. This option has no effect on
+@acronym{POSIX}-conforming systems like @acronym{GNU}/Linux. On systems where
+this option makes a difference, the patch should be generated by
+@samp{diff -a --binary}. @xref{Binary}.
+
+@item -c
+@itemx --context
+Interpret the patch file as a context diff. @xref{patch Input}.
+
+@item -d @var{directory}
+@itemx --directory=@var{directory}
+Make directory @var{directory} the current directory for interpreting
+both file names in the patch file, and file names given as arguments to
+other options. @xref{patch Directories}.
+
+@item -D @var{name}
+@itemx --ifdef=@var{name}
+Make merged if-then-else output using @var{name}. @xref{If-then-else}.
+
+@item --dry-run
+Print the results of applying the patches without actually changing
+any files. @xref{Dry Runs}.
+
+@item -e
+@itemx --ed
+Interpret the patch file as an @command{ed} script. @xref{patch Input}.
+
+@item -E
+@itemx --remove-empty-files
+Remove output files that are empty after the patches have been applied.
+@xref{Creating and Removing}.
+
+@item -f
+@itemx --force
+Assume that the user knows exactly what he or she is doing, and do not
+ask any questions. @xref{patch Messages}.
+
+@item -F @var{lines}
+@itemx --fuzz=@var{lines}
+Set the maximum fuzz factor to @var{lines}. @xref{Inexact}.
+
+@item -g @var{num}
+@itemx --get=@var{num}
+If @var{num} is positive, get input files from a revision control
+system as necessary; if zero, do not get the files; if negative, ask
+the user whether to get the files. @xref{Revision Control}.
+
+@item --help
+Output a summary of usage and then exit.
+
+@item -i @var{patchfile}
+@itemx --input=@var{patchfile}
+Read the patch from @var{patchfile} rather than from standard input.
+@xref{patch Options}.
+
+@item -l
+@itemx --ignore-white-space
+Let any sequence of blanks (spaces or tabs) in the patch file match
+any sequence of blanks in the input file. @xref{Changed White Space}.
+
+@item -n
+@itemx --normal
+Interpret the patch file as a normal diff. @xref{patch Input}.
+
+@item -N
+@itemx --forward
+Ignore patches that @command{patch} thinks are reversed or already applied.
+See also @option{-R}. @xref{Reversed Patches}.
+
+@item --no-backup-if-mismatch
+Do not back up the original contents of files. This is the default
+behavior when conforming to @acronym{POSIX}. @xref{Backups}.
+
+@item -o @var{file}
+@itemx --output=@var{file}
+Use @var{file} as the output file name. @xref{patch Options}.
+
+@item -p@var{number}
+@itemx --strip=@var{number}
+Set the file name strip count to @var{number}. @xref{patch Directories}.
+
+@item --posix
+Conform to @acronym{POSIX}, as if the @env{POSIXLY_CORRECT} environment
+variable had been set. @xref{patch and POSIX}.
+
+@item --quoting-style=@var{word}
+Use style @var{word} to quote names in diagnostics, as if the
+@env{QUOTING_STYLE} environment variable had been set to @var{word}.
+@xref{patch Quoting Style}.
+
+@item -r @var{reject-file}
+@itemx --reject-file=@var{reject-file}
+Use @var{reject-file} as the reject file name. @xref{Reject Names}.
+
+@item -R
+@itemx --reverse
+Assume that this patch was created with the old and new files swapped.
+@xref{Reversed Patches}.
+
+@item -s
+@itemx --quiet
+@itemx --silent
+Work silently unless an error occurs. @xref{patch Messages}.
+
+@item -t
+@itemx --batch
+Do not ask any questions. @xref{patch Messages}.
+
+@item -T
+@itemx --set-time
+Set the modification and access times of patched files from time
+stamps given in context diff headers, assuming that the context diff
+headers use local time. @xref{Patching Time Stamps}.
+
+@item -u
+@itemx --unified
+Interpret the patch file as a unified diff. @xref{patch Input}.
+
+@item -v
+@itemx --version
+Output version information and then exit.
+
+@item -V @var{backup-style}
+@itemx --version=control=@var{backup-style}
+Select the naming convention for backup file names. @xref{Backup Names}.
+
+@item --verbose
+Print more diagnostics than usual. @xref{patch Messages}.
+
+@item -x @var{number}
+@itemx --debug=@var{number}
+Set internal debugging flags. Of interest only to @command{patch}
+patchers.
+
+@item -Y @var{prefix}
+@itemx --basename-prefix=@var{prefix}
+Prepend @var{prefix} to base names of backup files. @xref{Backup Names}.
+
+@item -z @var{suffix}
+@itemx --suffix=@var{suffix}
+Use @var{suffix} as the backup extension instead of @samp{.orig} or
+@samp{~}. @xref{Backup Names}.
+
+@item -Z
+@itemx --set-utc
+Set the modification and access times of patched files from time
+stamps given in context diff headers, assuming that the context diff
+headers use @acronym{UTC}. @xref{Patching Time Stamps}.
+
+@end table
+
+@node Invoking sdiff
+@chapter Invoking @command{sdiff}
+@cindex invoking @command{sdiff}
+@cindex @command{sdiff} invocation
+
+The @command{sdiff} command merges two files and interactively outputs the
+results. Its arguments are as follows:
+
+@example
+sdiff -o @var{outfile} @var{options}@dots{} @var{from-file} @var{to-file}
+@end example
+
+This merges @var{from-file} with @var{to-file}, with output to @var{outfile}.
+If @var{from-file} is a directory and @var{to-file} is not, @command{sdiff}
+compares the file in @var{from-file} whose file name is that of @var{to-file},
+and vice versa. @var{from-file} and @var{to-file} may not both be
+directories.
+
+@command{sdiff} options begin with @samp{-}, so normally @var{from-file}
+and @var{to-file} may not begin with @samp{-}. However, @option{--} as an
+argument by itself treats the remaining arguments as file names even if
+they begin with @samp{-}. You may not use @file{-} as an input file.
+
+@command{sdiff} without @option{-o} (or @option{--output}) produces a
+side-by-side difference. This usage is obsolete; use the @option{-y}
+or @option{--side-by-side} option of @command{diff} instead.
+
+An exit status of 0 means no differences were found, 1 means some
+differences were found, and 2 means trouble.
+
+@menu
+* sdiff Options:: Summary of options to @command{diff}.
+@end menu
+
+@node sdiff Options
+@section Options to @command{sdiff}
+@cindex @command{sdiff} options
+@cindex options for @command{sdiff}
+
+Below is a summary of all of the options that @acronym{GNU}
+@command{sdiff} accepts. Each option has two equivalent names, one of
+which is a single letter preceded by @samp{-}, and the other of which
+is a long name preceded by @samp{--}. Multiple single letter options
+(unless they take an argument) can be combined into a single command
+line argument. Long named options can be abbreviated to any unique
+prefix of their name.
+
+@table @option
+@item -a
+@itemx --text
+Treat all files as text and compare them line-by-line, even if they
+do not appear to be text. @xref{Binary}.
+
+@item -b
+@itemx --ignore-space-change
+Ignore changes in amount of white space. @xref{White Space}.
+
+@item -B
+@itemx --ignore-blank-lines
+Ignore changes that just insert or delete blank lines. @xref{Blank
+Lines}.
+
+@item -d
+@itemx --minimal
+Change the algorithm to perhaps find a smaller set of changes. This
+makes @command{sdiff} slower (sometimes much slower). @xref{diff
+Performance}.
+
+@item --diff-program=@var{program}
+Use the compatible comparison program @var{program} to compare files
+instead of @command{diff}.
+
+@item -E
+@itemx --ignore-tab-expansion
+Ignore changes due to tab expansion.
+@xref{White Space}.
+
+@item --help
+Output a summary of usage and then exit.
+
+@item -i
+@itemx --ignore-case
+Ignore changes in case; consider upper- and lower-case to be the same.
+@xref{Case Folding}.
+
+@item -I @var{regexp}
+@itemx --ignore-matching-lines=@var{regexp}
+Ignore changes that just insert or delete lines that match @var{regexp}.
+@xref{Specified Lines}.
+
+@item -l
+@itemx --left-column
+Print only the left column of two common lines.
+@xref{Side by Side Format}.
+
+@item -o @var{file}
+@itemx --output=@var{file}
+Put merged output into @var{file}. This option is required for merging.
+
+@item -s
+@itemx --suppress-common-lines
+Do not print common lines. @xref{Side by Side Format}.
+
+@item --speed-large-files
+Use heuristics to speed handling of large files that have numerous
+scattered small changes. @xref{diff Performance}.
+
+@item --strip-trailing-cr
+Strip any trailing carriage return at the end of an input line.
+@xref{Binary}.
+
+@item -t
+@itemx --expand-tabs
+Expand tabs to spaces in the output, to preserve the alignment of tabs
+in the input files. @xref{Tabs}.
+
+@item --tabsize=@var{columns}
+Assume that tab stops are set every @var{columns} (default 8) print
+columns. @xref{Tabs}.
+
+@item -v
+@itemx --version
+Output version information and then exit.
+
+@item -w @var{columns}
+@itemx --width=@var{columns}
+Output at most @var{columns} (default 130) print columns per line.
+@xref{Side by Side Format}. Note that for historical reasons, this
+option is @option{-W} in @command{diff}, @option{-w} in @command{sdiff}.
+
+@item -W
+@itemx --ignore-all-space
+Ignore white space when comparing lines. @xref{White Space}.
+Note that for historical reasons, this option is @option{-w} in @command{diff},
+@option{-W} in @command{sdiff}.
+@end table
+
+@node Standards conformance
+@chapter Standards conformance
+@cindex @acronym{POSIX}
+
+@vindex POSIXLY_CORRECT
+In a few cases, the @acronym{GNU} utilities' default behavior is
+incompatible with the @acronym{POSIX} standard. To suppress these
+incompatibilities, define the @env{POSIXLY_CORRECT} environment
+variable. Unless you are checking for @acronym{POSIX} conformance, you
+probably do not need to define @env{POSIXLY_CORRECT}.
+
+Normally options and operands can appear in any order, and programs act
+as if all the options appear before any operands. For example,
+@samp{diff lao tzu -C 2} acts like @samp{diff -C 2 lao tzu}, since
+@samp{2} is an option-argument of @option{-C}. However, if the
+@env{POSIXLY_CORRECT} environment variable is set, options must appear
+before operands, unless otherwise specified for a particular command.
+
+Newer versions of @acronym{POSIX} are occasionally incompatible with older
+versions. For example, older versions of @acronym{POSIX} allowed the
+command @samp{diff -c -10} to have the same meaning as @samp{diff -C
+10}, but @acronym{POSIX} 1003.1-2001 @samp{diff} no longer allows
+digit-string options like @option{-10}.
+
+@vindex _POSIX2_VERSION
+The @acronym{GNU} utilities normally conform to the version of @acronym{POSIX}
+that is standard for your system. To cause them to conform to a
+different version of @acronym{POSIX}, define the @env{_POSIX2_VERSION}
+environment variable to a value of the form @var{yyyymm} specifying
+the year and month the standard was adopted. Two values are currently
+supported for @env{_POSIX2_VERSION}: @samp{199209} stands for
+@acronym{POSIX} 1003.2-1992, and @samp{200112} stands for @acronym{POSIX}
+1003.1-2001. For example, if you are running older software that
+assumes an older version of @acronym{POSIX} and uses @samp{diff -c -10},
+you can work around the compatibility problems by setting
+@samp{_POSIX2_VERSION=199209} in your environment.
+
+@node Projects
+@chapter Future Projects
+
+Here are some ideas for improving @acronym{GNU} @command{diff} and
+@command{patch}. The @acronym{GNU} project has identified some
+improvements as potential programming projects for volunteers. You
+can also help by reporting any bugs that you find.
+
+If you are a programmer and would like to contribute something to the
+@acronym{GNU} project, please consider volunteering for one of these
+projects. If you are seriously contemplating work, please write to
+@email{gvc@@gnu.org} to coordinate with other volunteers.
+
+@menu
+* Shortcomings:: Suggested projects for improvements.
+* Bugs:: Reporting bugs.
+@end menu
+
+@node Shortcomings
+@section Suggested Projects for Improving @acronym{GNU} @command{diff} and @command{patch}
+@cindex projects for directories
+
+One should be able to use @acronym{GNU} @command{diff} to generate a
+patch from any pair of directory trees, and given the patch and a copy
+of one such tree, use @command{patch} to generate a faithful copy of
+the other. Unfortunately, some changes to directory trees cannot be
+expressed using current patch formats; also, @command{patch} does not
+handle some of the existing formats. These shortcomings motivate the
+following suggested projects.
+
+@menu
+* Internationalization:: Handling multibyte and varying-width characters.
+* Changing Structure:: Handling changes to the directory structure.
+* Special Files:: Handling symbolic links, device special files, etc.
+* Unusual File Names:: Handling file names that contain unusual characters.
+* Time Stamp Order:: Outputting diffs in time stamp order.
+* Ignoring Changes:: Ignoring certain changes while showing others.
+* Speedups:: Improving performance.
+@end menu
+
+@node Internationalization
+@subsection Handling Multibyte and Varying-Width Characters
+@cindex multibyte characters
+@cindex varying-width characters
+
+@command{diff}, @command{diff3} and @command{sdiff} treat each line of
+input as a string of unibyte characters. This can mishandle multibyte
+characters in some cases. For example, when asked to ignore spaces,
+@command{diff} does not properly ignore a multibyte space character.
+
+Also, @command{diff} currently assumes that each byte is one column
+wide, and this assumption is incorrect in some locales, e.g., locales
+that use UTF-8 encoding. This causes problems with the @option{-y} or
+@option{--side-by-side} option of @command{diff}.
+
+These problems need to be fixed without unduly affecting the
+performance of the utilities in unibyte environments.
+
+The IBM GNU/Linux Technology Center Internationalization Team has
+proposed
+@uref{http://oss.software.ibm.com/developer/opensource/linux/patches/i18n/diffutils-2.7.2-i18n-0.1.patch.gz,patches
+to support internationalized @command{diff}}.
+Unfortunately, these patches are incomplete and are to an older
+version of @command{diff}, so more work needs to be done in this area.
+
+@node Changing Structure
+@subsection Handling Changes to the Directory Structure
+@cindex directory structure changes
+
+@command{diff} and @command{patch} do not handle some changes to directory
+structure. For example, suppose one directory tree contains a directory
+named @samp{D} with some subsidiary files, and another contains a file
+with the same name @samp{D}. @samp{diff -r} does not output enough
+information for @command{patch} to transform the directory subtree into
+the file.
+
+There should be a way to specify that a file has been removed without
+having to include its entire contents in the patch file. There should
+also be a way to tell @command{patch} that a file was renamed, even if
+there is no way for @command{diff} to generate such information.
+There should be a way to tell @command{patch} that a file's time stamp
+has changed, even if its contents have not changed.
+
+These problems can be fixed by extending the @command{diff} output format
+to represent changes in directory structure, and extending @command{patch}
+to understand these extensions.
+
+@node Special Files
+@subsection Files that are Neither Directories Nor Regular Files
+@cindex special files
+
+Some files are neither directories nor regular files: they are unusual
+files like symbolic links, device special files, named pipes, and
+sockets. Currently, @command{diff} treats symbolic links as if they
+were the pointed-to files, except that a recursive @command{diff}
+reports an error if it detects infinite loops of symbolic links (e.g.,
+symbolic links to @file{..}). @command{diff} treats other special
+files like regular files if they are specified at the top level, but
+simply reports their presence when comparing directories. This means
+that @command{patch} cannot represent changes to such files. For
+example, if you change which file a symbolic link points to,
+@command{diff} outputs the difference between the two files, instead
+of the change to the symbolic link.
+
+@c This might not be a good idea; is it wise for root to install devices
+@c this way?
+@command{diff} should optionally report changes to special files specially,
+and @command{patch} should be extended to understand these extensions.
+
+@node Unusual File Names
+@subsection File Names that Contain Unusual Characters
+@cindex file names with unusual characters
+
+When a file name contains an unusual character like a newline or
+white space, @samp{diff -r} generates a patch that @command{patch} cannot
+parse. The problem is with format of @command{diff} output, not just with
+@command{patch}, because with odd enough file names one can cause
+@command{diff} to generate a patch that is syntactically correct but
+patches the wrong files. The format of @command{diff} output should be
+extended to handle all possible file names.
+
+@node Time Stamp Order
+@subsection Outputting Diffs in Time Stamp Order
+
+Applying @command{patch} to a multiple-file diff can result in files
+whose time stamps are out of order. @acronym{GNU} @command{patch} has
+options to restore the time stamps of the updated files
+(@pxref{Patching Time Stamps}), but sometimes it is useful to generate
+a patch that works even if the recipient does not have @acronym{GNU} patch,
+or does not use these options. One way to do this would be to
+implement a @command{diff} option to output diffs in time stamp order.
+
+@node Ignoring Changes
+@subsection Ignoring Certain Changes
+
+It would be nice to have a feature for specifying two strings, one in
+@var{from-file} and one in @var{to-file}, which should be considered to
+match. Thus, if the two strings are @samp{foo} and @samp{bar}, then if
+two lines differ only in that @samp{foo} in file 1 corresponds to
+@samp{bar} in file 2, the lines are treated as identical.
+
+It is not clear how general this feature can or should be, or
+what syntax should be used for it.
+
+A partial substitute is to filter one or both files before comparing,
+e.g.:
+
+@example
+sed 's/foo/bar/g' file1 | diff - file2
+@end example
+
+However, this outputs the filtered text, not the original.
+
+@node Speedups
+@subsection Improving Performance
+
+When comparing two large directory structures, one of which was
+originally copied from the other with time stamps preserved (e.g.,
+with @samp{cp -pR}), it would greatly improve performance if an option
+told @command{diff} to assume that two files with the same size and
+time stamps have the same content. @xref{diff Performance}.
+
+@node Bugs
+@section Reporting Bugs
+@cindex bug reports
+@cindex reporting bugs
+
+If you think you have found a bug in @acronym{GNU} @command{cmp},
+@command{diff}, @command{diff3}, or @command{sdiff}, please report it
+by electronic mail to the
+@uref{http://mail.gnu.org/mailman/listinfo/bug-gnu-utils,GNU utilities
+bug report mailing list} @email{bug-gnu-utils@@gnu.org}. Please send
+bug reports for @acronym{GNU} @command{patch} to
+@email{bug-patch@@gnu.org}. Send as precise a description of the
+problem as you can, including the output of the @option{--version}
+option and sample input files that produce the bug, if applicable. If
+you have a nontrivial fix for the bug, please send it as well. If you
+have a patch, please send it too. It may simplify the maintainer's
+job if the patch is relative to a recent test release, which you can
+find in the directory @uref{ftp://alpha.gnu.org/gnu/diffutils/}.
+
+@node Copying This Manual
+@appendix Copying This Manual
+
+@menu
+* GNU Free Documentation License:: License for copying this manual.
+@end menu
+
+@include fdl.texi
+
+@node Translations
+@appendix Translations of This Manual
+
+Nishio Futoshi of the GNUjdoc project has prepared a Japanese
+translation of this manual. Its most recent version can be found at
+@uref{http://openlab.ring.gr.jp/gnujdoc/cvsweb/cvsweb.cgi/gnujdoc/}.
+
+@node Index
+@appendix Index
+
+@printindex cp
+
+@bye
diff --git a/contrib/diff/doc/fdl.texi b/contrib/diff/doc/fdl.texi
new file mode 100644
index 0000000..11737cc
--- /dev/null
+++ b/contrib/diff/doc/fdl.texi
@@ -0,0 +1,452 @@
+
+@node GNU Free Documentation License
+@appendixsec GNU Free Documentation License
+
+@cindex FDL, GNU Free Documentation License
+@center Version 1.2, November 2002
+
+@display
+Copyright @copyright{} 2000,2001,2002 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+@end display
+
+@enumerate 0
+@item
+PREAMBLE
+
+The purpose of this License is to make a manual, textbook, or other
+functional and useful document @dfn{free} in the sense of freedom: to
+assure everyone the effective freedom to copy and redistribute it,
+with or without modifying it, either commercially or noncommercially.
+Secondarily, this License preserves for the author and publisher a way
+to get credit for their work, while not being considered responsible
+for modifications made by others.
+
+This License is a kind of ``copyleft'', which means that derivative
+works of the document must themselves be free in the same sense. It
+complements the GNU General Public License, which is a copyleft
+license designed for free software.
+
+We have designed this License in order to use it for manuals for free
+software, because free software needs free documentation: a free
+program should come with manuals providing the same freedoms that the
+software does. But this License is not limited to software manuals;
+it can be used for any textual work, regardless of subject matter or
+whether it is published as a printed book. We recommend this License
+principally for works whose purpose is instruction or reference.
+
+@item
+APPLICABILITY AND DEFINITIONS
+
+This License applies to any manual or other work, in any medium, that
+contains a notice placed by the copyright holder saying it can be
+distributed under the terms of this License. Such a notice grants a
+world-wide, royalty-free license, unlimited in duration, to use that
+work under the conditions stated herein. The ``Document'', below,
+refers to any such manual or work. Any member of the public is a
+licensee, and is addressed as ``you''. You accept the license if you
+copy, modify or distribute the work in a way requiring permission
+under copyright law.
+
+A ``Modified Version'' of the Document means any work containing the
+Document or a portion of it, either copied verbatim, or with
+modifications and/or translated into another language.
+
+A ``Secondary Section'' is a named appendix or a front-matter section
+of the Document that deals exclusively with the relationship of the
+publishers or authors of the Document to the Document's overall
+subject (or to related matters) and contains nothing that could fall
+directly within that overall subject. (Thus, if the Document is in
+part a textbook of mathematics, a Secondary Section may not explain
+any mathematics.) The relationship could be a matter of historical
+connection with the subject or with related matters, or of legal,
+commercial, philosophical, ethical or political position regarding
+them.
+
+The ``Invariant Sections'' are certain Secondary Sections whose titles
+are designated, as being those of Invariant Sections, in the notice
+that says that the Document is released under this License. If a
+section does not fit the above definition of Secondary then it is not
+allowed to be designated as Invariant. The Document may contain zero
+Invariant Sections. If the Document does not identify any Invariant
+Sections then there are none.
+
+The ``Cover Texts'' are certain short passages of text that are listed,
+as Front-Cover Texts or Back-Cover Texts, in the notice that says that
+the Document is released under this License. A Front-Cover Text may
+be at most 5 words, and a Back-Cover Text may be at most 25 words.
+
+A ``Transparent'' copy of the Document means a machine-readable copy,
+represented in a format whose specification is available to the
+general public, that is suitable for revising the document
+straightforwardly with generic text editors or (for images composed of
+pixels) generic paint programs or (for drawings) some widely available
+drawing editor, and that is suitable for input to text formatters or
+for automatic translation to a variety of formats suitable for input
+to text formatters. A copy made in an otherwise Transparent file
+format whose markup, or absence of markup, has been arranged to thwart
+or discourage subsequent modification by readers is not Transparent.
+An image format is not Transparent if used for any substantial amount
+of text. A copy that is not ``Transparent'' is called ``Opaque''.
+
+Examples of suitable formats for Transparent copies include plain
+@sc{ascii} without markup, Texinfo input format, La@TeX{} input
+format, @acronym{SGML} or @acronym{XML} using a publicly available
+@acronym{DTD}, and standard-conforming simple @acronym{HTML},
+PostScript or @acronym{PDF} designed for human modification. Examples
+of transparent image formats include @acronym{PNG}, @acronym{XCF} and
+@acronym{JPG}. Opaque formats include proprietary formats that can be
+read and edited only by proprietary word processors, @acronym{SGML} or
+@acronym{XML} for which the @acronym{DTD} and/or processing tools are
+not generally available, and the machine-generated @acronym{HTML},
+PostScript or @acronym{PDF} produced by some word processors for
+output purposes only.
+
+The ``Title Page'' means, for a printed book, the title page itself,
+plus such following pages as are needed to hold, legibly, the material
+this License requires to appear in the title page. For works in
+formats which do not have any title page as such, ``Title Page'' means
+the text near the most prominent appearance of the work's title,
+preceding the beginning of the body of the text.
+
+A section ``Entitled XYZ'' means a named subunit of the Document whose
+title either is precisely XYZ or contains XYZ in parentheses following
+text that translates XYZ in another language. (Here XYZ stands for a
+specific section name mentioned below, such as ``Acknowledgements'',
+``Dedications'', ``Endorsements'', or ``History''.) To ``Preserve the Title''
+of such a section when you modify the Document means that it remains a
+section ``Entitled XYZ'' according to this definition.
+
+The Document may include Warranty Disclaimers next to the notice which
+states that this License applies to the Document. These Warranty
+Disclaimers are considered to be included by reference in this
+License, but only as regards disclaiming warranties: any other
+implication that these Warranty Disclaimers may have is void and has
+no effect on the meaning of this License.
+
+@item
+VERBATIM COPYING
+
+You may copy and distribute the Document in any medium, either
+commercially or noncommercially, provided that this License, the
+copyright notices, and the license notice saying this License applies
+to the Document are reproduced in all copies, and that you add no other
+conditions whatsoever to those of this License. You may not use
+technical measures to obstruct or control the reading or further
+copying of the copies you make or distribute. However, you may accept
+compensation in exchange for copies. If you distribute a large enough
+number of copies you must also follow the conditions in section 3.
+
+You may also lend copies, under the same conditions stated above, and
+you may publicly display copies.
+
+@item
+COPYING IN QUANTITY
+
+If you publish printed copies (or copies in media that commonly have
+printed covers) of the Document, numbering more than 100, and the
+Document's license notice requires Cover Texts, you must enclose the
+copies in covers that carry, clearly and legibly, all these Cover
+Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
+the back cover. Both covers must also clearly and legibly identify
+you as the publisher of these copies. The front cover must present
+the full title with all words of the title equally prominent and
+visible. You may add other material on the covers in addition.
+Copying with changes limited to the covers, as long as they preserve
+the title of the Document and satisfy these conditions, can be treated
+as verbatim copying in other respects.
+
+If the required texts for either cover are too voluminous to fit
+legibly, you should put the first ones listed (as many as fit
+reasonably) on the actual cover, and continue the rest onto adjacent
+pages.
+
+If you publish or distribute Opaque copies of the Document numbering
+more than 100, you must either include a machine-readable Transparent
+copy along with each Opaque copy, or state in or with each Opaque copy
+a computer-network location from which the general network-using
+public has access to download using public-standard network protocols
+a complete Transparent copy of the Document, free of added material.
+If you use the latter option, you must take reasonably prudent steps,
+when you begin distribution of Opaque copies in quantity, to ensure
+that this Transparent copy will remain thus accessible at the stated
+location until at least one year after the last time you distribute an
+Opaque copy (directly or through your agents or retailers) of that
+edition to the public.
+
+It is requested, but not required, that you contact the authors of the
+Document well before redistributing any large number of copies, to give
+them a chance to provide you with an updated version of the Document.
+
+@item
+MODIFICATIONS
+
+You may copy and distribute a Modified Version of the Document under
+the conditions of sections 2 and 3 above, provided that you release
+the Modified Version under precisely this License, with the Modified
+Version filling the role of the Document, thus licensing distribution
+and modification of the Modified Version to whoever possesses a copy
+of it. In addition, you must do these things in the Modified Version:
+
+@enumerate A
+@item
+Use in the Title Page (and on the covers, if any) a title distinct
+from that of the Document, and from those of previous versions
+(which should, if there were any, be listed in the History section
+of the Document). You may use the same title as a previous version
+if the original publisher of that version gives permission.
+
+@item
+List on the Title Page, as authors, one or more persons or entities
+responsible for authorship of the modifications in the Modified
+Version, together with at least five of the principal authors of the
+Document (all of its principal authors, if it has fewer than five),
+unless they release you from this requirement.
+
+@item
+State on the Title page the name of the publisher of the
+Modified Version, as the publisher.
+
+@item
+Preserve all the copyright notices of the Document.
+
+@item
+Add an appropriate copyright notice for your modifications
+adjacent to the other copyright notices.
+
+@item
+Include, immediately after the copyright notices, a license notice
+giving the public permission to use the Modified Version under the
+terms of this License, in the form shown in the Addendum below.
+
+@item
+Preserve in that license notice the full lists of Invariant Sections
+and required Cover Texts given in the Document's license notice.
+
+@item
+Include an unaltered copy of this License.
+
+@item
+Preserve the section Entitled ``History'', Preserve its Title, and add
+to it an item stating at least the title, year, new authors, and
+publisher of the Modified Version as given on the Title Page. If
+there is no section Entitled ``History'' in the Document, create one
+stating the title, year, authors, and publisher of the Document as
+given on its Title Page, then add an item describing the Modified
+Version as stated in the previous sentence.
+
+@item
+Preserve the network location, if any, given in the Document for
+public access to a Transparent copy of the Document, and likewise
+the network locations given in the Document for previous versions
+it was based on. These may be placed in the ``History'' section.
+You may omit a network location for a work that was published at
+least four years before the Document itself, or if the original
+publisher of the version it refers to gives permission.
+
+@item
+For any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve
+the Title of the section, and preserve in the section all the
+substance and tone of each of the contributor acknowledgements and/or
+dedications given therein.
+
+@item
+Preserve all the Invariant Sections of the Document,
+unaltered in their text and in their titles. Section numbers
+or the equivalent are not considered part of the section titles.
+
+@item
+Delete any section Entitled ``Endorsements''. Such a section
+may not be included in the Modified Version.
+
+@item
+Do not retitle any existing section to be Entitled ``Endorsements'' or
+to conflict in title with any Invariant Section.
+
+@item
+Preserve any Warranty Disclaimers.
+@end enumerate
+
+If the Modified Version includes new front-matter sections or
+appendices that qualify as Secondary Sections and contain no material
+copied from the Document, you may at your option designate some or all
+of these sections as invariant. To do this, add their titles to the
+list of Invariant Sections in the Modified Version's license notice.
+These titles must be distinct from any other section titles.
+
+You may add a section Entitled ``Endorsements'', provided it contains
+nothing but endorsements of your Modified Version by various
+parties---for example, statements of peer review or that the text has
+been approved by an organization as the authoritative definition of a
+standard.
+
+You may add a passage of up to five words as a Front-Cover Text, and a
+passage of up to 25 words as a Back-Cover Text, to the end of the list
+of Cover Texts in the Modified Version. Only one passage of
+Front-Cover Text and one of Back-Cover Text may be added by (or
+through arrangements made by) any one entity. If the Document already
+includes a cover text for the same cover, previously added by you or
+by arrangement made by the same entity you are acting on behalf of,
+you may not add another; but you may replace the old one, on explicit
+permission from the previous publisher that added the old one.
+
+The author(s) and publisher(s) of the Document do not by this License
+give permission to use their names for publicity for or to assert or
+imply endorsement of any Modified Version.
+
+@item
+COMBINING DOCUMENTS
+
+You may combine the Document with other documents released under this
+License, under the terms defined in section 4 above for modified
+versions, provided that you include in the combination all of the
+Invariant Sections of all of the original documents, unmodified, and
+list them all as Invariant Sections of your combined work in its
+license notice, and that you preserve all their Warranty Disclaimers.
+
+The combined work need only contain one copy of this License, and
+multiple identical Invariant Sections may be replaced with a single
+copy. If there are multiple Invariant Sections with the same name but
+different contents, make the title of each such section unique by
+adding at the end of it, in parentheses, the name of the original
+author or publisher of that section if known, or else a unique number.
+Make the same adjustment to the section titles in the list of
+Invariant Sections in the license notice of the combined work.
+
+In the combination, you must combine any sections Entitled ``History''
+in the various original documents, forming one section Entitled
+``History''; likewise combine any sections Entitled ``Acknowledgements'',
+and any sections Entitled ``Dedications''. You must delete all
+sections Entitled ``Endorsements.''
+
+@item
+COLLECTIONS OF DOCUMENTS
+
+You may make a collection consisting of the Document and other documents
+released under this License, and replace the individual copies of this
+License in the various documents with a single copy that is included in
+the collection, provided that you follow the rules of this License for
+verbatim copying of each of the documents in all other respects.
+
+You may extract a single document from such a collection, and distribute
+it individually under this License, provided you insert a copy of this
+License into the extracted document, and follow this License in all
+other respects regarding verbatim copying of that document.
+
+@item
+AGGREGATION WITH INDEPENDENT WORKS
+
+A compilation of the Document or its derivatives with other separate
+and independent documents or works, in or on a volume of a storage or
+distribution medium, is called an ``aggregate'' if the copyright
+resulting from the compilation is not used to limit the legal rights
+of the compilation's users beyond what the individual works permit.
+When the Document is included in an aggregate, this License does not
+apply to the other works in the aggregate which are not themselves
+derivative works of the Document.
+
+If the Cover Text requirement of section 3 is applicable to these
+copies of the Document, then if the Document is less than one half of
+the entire aggregate, the Document's Cover Texts may be placed on
+covers that bracket the Document within the aggregate, or the
+electronic equivalent of covers if the Document is in electronic form.
+Otherwise they must appear on printed covers that bracket the whole
+aggregate.
+
+@item
+TRANSLATION
+
+Translation is considered a kind of modification, so you may
+distribute translations of the Document under the terms of section 4.
+Replacing Invariant Sections with translations requires special
+permission from their copyright holders, but you may include
+translations of some or all Invariant Sections in addition to the
+original versions of these Invariant Sections. You may include a
+translation of this License, and all the license notices in the
+Document, and any Warranty Disclaimers, provided that you also include
+the original English version of this License and the original versions
+of those notices and disclaimers. In case of a disagreement between
+the translation and the original version of this License or a notice
+or disclaimer, the original version will prevail.
+
+If a section in the Document is Entitled ``Acknowledgements'',
+``Dedications'', or ``History'', the requirement (section 4) to Preserve
+its Title (section 1) will typically require changing the actual
+title.
+
+@item
+TERMINATION
+
+You may not copy, modify, sublicense, or distribute the Document except
+as expressly provided for under this License. Any other attempt to
+copy, modify, sublicense or distribute the Document 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.
+
+@item
+FUTURE REVISIONS OF THIS LICENSE
+
+The Free Software Foundation may publish new, revised versions
+of the GNU Free Documentation 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. See
+@uref{http://www.gnu.org/copyleft/}.
+
+Each version of the License is given a distinguishing version number.
+If the Document specifies that a particular numbered version of this
+License ``or any later version'' applies to it, you have the option of
+following the terms and conditions either of that specified version or
+of any later version that has been published (not as a draft) by the
+Free Software Foundation. If the Document does not specify a version
+number of this License, you may choose any version ever published (not
+as a draft) by the Free Software Foundation.
+@end enumerate
+
+@page
+@appendixsubsec ADDENDUM: How to use this License for your documents
+
+To use this License in a document you have written, include a copy of
+the License in the document and put the following copyright and
+license notices just after the title page:
+
+@smallexample
+@group
+ Copyright (C) @var{year} @var{your name}.
+ Permission is granted to copy, distribute and/or modify this document
+ under the terms of the GNU Free Documentation License, Version 1.2
+ or any later version published by the Free Software Foundation;
+ with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
+ Texts. A copy of the license is included in the section entitled ``GNU
+ Free Documentation License''.
+@end group
+@end smallexample
+
+If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
+replace the ``with...Texts.'' line with this:
+
+@smallexample
+@group
+ with the Invariant Sections being @var{list their titles}, with
+ the Front-Cover Texts being @var{list}, and with the Back-Cover Texts
+ being @var{list}.
+@end group
+@end smallexample
+
+If you have Invariant Sections without Cover Texts, or some other
+combination of the three, merge those two alternatives to suit the
+situation.
+
+If your document contains nontrivial examples of program code, we
+recommend releasing these examples in parallel under your choice of
+free software license, such as the GNU General Public License,
+to permit their use in free software.
+
+@c Local Variables:
+@c ispell-local-pdict: "ispell-dict"
+@c End:
+
diff --git a/contrib/diff/doc/stamp-vti b/contrib/diff/doc/stamp-vti
new file mode 100644
index 0000000..cb009ce
--- /dev/null
+++ b/contrib/diff/doc/stamp-vti
@@ -0,0 +1,4 @@
+@set UPDATED 12 April 2004
+@set UPDATED-MONTH April 2004
+@set EDITION 2.8.7
+@set VERSION 2.8.7
diff --git a/contrib/diff/doc/version.texi b/contrib/diff/doc/version.texi
new file mode 100644
index 0000000..cb009ce
--- /dev/null
+++ b/contrib/diff/doc/version.texi
@@ -0,0 +1,4 @@
+@set UPDATED 12 April 2004
+@set UPDATED-MONTH April 2004
+@set EDITION 2.8.7
+@set VERSION 2.8.7
diff --git a/contrib/diff/exgettext b/contrib/diff/exgettext
new file mode 100755
index 0000000..4fef5ed
--- /dev/null
+++ b/contrib/diff/exgettext
@@ -0,0 +1,115 @@
+#! /bin/sh
+# Wrapper around gettext for programs using the msgid convention.
+
+# Copyright (C) 1998, 2001, 2004 Free Software Foundation, Inc.
+
+# Written by Paul Eggert <eggert@twinsun.com>.
+
+# 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 GNU CC; see the file COPYING. If not, write to
+# the Free Software Foundation, 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# Always operate in the C locale.
+LANG=C
+LANGUAGE=C
+LC_ALL=C
+export LANG LANGUAGE LC_ALL
+
+# Set AWK if environment has not already set it.
+AWK=${AWK-awk}
+
+# The argument to this wrapper is the xgettext command to be executed.
+# Extract the xgettext program name from the rest of the command.
+xgettext=${1?}
+shift
+
+# Save work if we're just wrapping a no-op.
+case $xgettext in
+:) exit;;
+esac
+
+# Find the files to be scanned, and the directory to scan them from.
+directory=.
+files=
+for i
+do
+ case $i in
+ --directory=*)
+ directory=`expr " $i" : ' --directory=\(.*\)'`;;
+ --files-from=*)
+ files_from=`expr " $i" : ' --files-from=\(.*\)'`
+ files=`$AWK '/^[^#]/ { print }' $files_from`;;
+ esac
+done
+
+# Generate keyword options for xgettext,
+# by scanning for declarations of functions
+# whose parameter names end in "msgid".
+generate_keyword_options='
+ /^[A-Z_a-z].*\(.*msgid[,)]/ {
+
+ paren_index = index($0, "(")
+
+ name = substr($0, 1, paren_index - 1)
+ sub(/[^0-9A-Z_a-z]*$/, "", name)
+ sub(/[ ]+PARAMS/, "", name)
+ sub(/[ ]+VPARAMS/, "", name)
+ sub(/.*[^0-9A-Z_a-z]/, "", name)
+
+ args = substr($0, paren_index)
+ sub(/msgid[,)].*/, "", args)
+ for (n = 1; sub(/^[^,]*,/, "", args); n++) {
+ continue;
+ }
+
+ if (n == 1) {
+ keyword = name
+ } else {
+ keyword = name ":" n
+ }
+
+ if (! keyword_seen[keyword]++) {
+ print "--keyword=" keyword
+ }
+ }
+'
+keyword_options=`(
+ cd $directory &&
+ $AWK "$generate_keyword_options" $files < /dev/null
+)` || exit
+
+# Run the xgettext command, with extra input containing the extra
+# msgids that it wouldn't normally find.
+generate_emsgids='
+ /%e.*}/ {
+ line = $0
+ while ((percent_index = index(line, "%e")) != 0) {
+ line = substr(line, percent_index + 2)
+ bracket_index = index(line, "}")
+ if (bracket_index == 0) {
+ continue
+ }
+ msgid = substr(line, 1, bracket_index - 1)
+ if (index(msgid, "%") != 0) {
+ continue
+ }
+ printf "#line %d \"%s\"\n", FNR, FILENAME
+ printf "_(\"%s\")\n", msgid
+ line = substr(line, bracket_index + 1)
+ }
+ }
+'
+(cd $directory &&
+ $AWK "$generate_emsgids" $files < /dev/null
+) | "$xgettext" $keyword_options ${1+"$@"} -
diff --git a/contrib/diff/lib/Makefile.am b/contrib/diff/lib/Makefile.am
new file mode 100644
index 0000000..dbf8b0f
--- /dev/null
+++ b/contrib/diff/lib/Makefile.am
@@ -0,0 +1,35 @@
+# Automakefile for GNU Diffutils library.
+
+# Copyright (C) 2001, 2002, 2004 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., 59 Temple Place - Suite 330, Boston, MA
+## 02111-1307, USA.
+
+noinst_LIBRARIES = libdiffutils.a
+
+noinst_HEADERS = cmpbuf.h prepargs.h quotesys.h
+
+libdiffutils_a_SOURCES = $(lib_SOURCES)
+lib_SOURCES = cmpbuf.c prepargs.c quotesys.c
+
+libdiffutils_a_LIBADD = @ALLOCA@ @LIBOBJS@
+libdiffutils_a_DEPENDENCIES = $(libdiffutils_a_LIBADD)
+
+BUILT_SOURCES =
+DISTCLEANFILES =
+EXTRA_DIST = setmode.h waitpid.c
+MOSTLYCLEANFILES =
+
+include gnulib.mk
diff --git a/contrib/diff/lib/alloca.c b/contrib/diff/lib/alloca.c
new file mode 100644
index 0000000..a580078
--- /dev/null
+++ b/contrib/diff/lib/alloca.c
@@ -0,0 +1,489 @@
+/* alloca.c -- allocate automatically reclaimed memory
+ (Mostly) portable public-domain implementation -- D A Gwyn
+
+ This implementation of the PWB library alloca function,
+ which is used to allocate space off the run-time stack so
+ that it is automatically reclaimed upon procedure exit,
+ was inspired by discussions with J. Q. Johnson of Cornell.
+ J.Otto Tennant <jot@cray.com> contributed the Cray support.
+
+ There are some preprocessor constants that can
+ be defined when compiling for your specific system, for
+ improved efficiency; however, the defaults should be okay.
+
+ The general concept of this implementation is to keep
+ track of all alloca-allocated blocks, and reclaim any
+ that are found to be deeper in the stack than the current
+ invocation. This heuristic does not reclaim storage as
+ soon as it becomes invalid, but it will do so eventually.
+
+ As a special case, alloca(0) reclaims storage without
+ allocating any. It is a good idea to use alloca(0) in
+ your main control loop, etc. to force garbage collection. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef emacs
+# include "lisp.h"
+# include "blockinput.h"
+# ifdef EMACS_FREE
+# undef free
+# define free EMACS_FREE
+# endif
+#else
+# define memory_full() abort ()
+#endif
+
+/* If compiling with GCC 2, this file's not needed. */
+#if !defined (__GNUC__) || __GNUC__ < 2
+
+/* If someone has defined alloca as a macro,
+ there must be some other way alloca is supposed to work. */
+# ifndef alloca
+
+# ifdef emacs
+# ifdef static
+/* actually, only want this if static is defined as ""
+ -- this is for usg, in which emacs must undefine static
+ in order to make unexec workable
+ */
+# ifndef STACK_DIRECTION
+you
+lose
+-- must know STACK_DIRECTION at compile-time
+/* Using #error here is not wise since this file should work for
+ old and obscure compilers. */
+# endif /* STACK_DIRECTION undefined */
+# endif /* static */
+# endif /* emacs */
+
+/* If your stack is a linked list of frames, you have to
+ provide an "address metric" ADDRESS_FUNCTION macro. */
+
+# if defined (CRAY) && defined (CRAY_STACKSEG_END)
+long i00afunc ();
+# define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
+# else
+# define ADDRESS_FUNCTION(arg) &(arg)
+# endif
+
+/* Define STACK_DIRECTION if you know the direction of stack
+ growth for your system; otherwise it will be automatically
+ deduced at run-time.
+
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown */
+
+# ifndef STACK_DIRECTION
+# define STACK_DIRECTION 0 /* Direction unknown. */
+# endif
+
+# if STACK_DIRECTION != 0
+
+# define STACK_DIR STACK_DIRECTION /* Known at compile-time. */
+
+# else /* STACK_DIRECTION == 0; need run-time code. */
+
+static int stack_dir; /* 1 or -1 once known. */
+# define STACK_DIR stack_dir
+
+static void
+find_stack_direction (void)
+{
+ static char *addr = NULL; /* Address of first `dummy', once known. */
+ auto char dummy; /* To get stack address. */
+
+ if (addr == NULL)
+ { /* Initial entry. */
+ addr = ADDRESS_FUNCTION (dummy);
+
+ find_stack_direction (); /* Recurse once. */
+ }
+ else
+ {
+ /* Second entry. */
+ if (ADDRESS_FUNCTION (dummy) > addr)
+ stack_dir = 1; /* Stack grew upward. */
+ else
+ stack_dir = -1; /* Stack grew downward. */
+ }
+}
+
+# endif /* STACK_DIRECTION == 0 */
+
+/* An "alloca header" is used to:
+ (a) chain together all alloca'ed blocks;
+ (b) keep track of stack depth.
+
+ It is very important that sizeof(header) agree with malloc
+ alignment chunk size. The following default should work okay. */
+
+# ifndef ALIGN_SIZE
+# define ALIGN_SIZE sizeof(double)
+# endif
+
+typedef union hdr
+{
+ char align[ALIGN_SIZE]; /* To force sizeof(header). */
+ struct
+ {
+ union hdr *next; /* For chaining headers. */
+ char *deep; /* For stack depth measure. */
+ } h;
+} header;
+
+static header *last_alloca_header = NULL; /* -> last alloca header. */
+
+/* Return a pointer to at least SIZE bytes of storage,
+ which will be automatically reclaimed upon exit from
+ the procedure that called alloca. Originally, this space
+ was supposed to be taken from the current stack frame of the
+ caller, but that method cannot be made to work for some
+ implementations of C, for example under Gould's UTX/32. */
+
+void *
+alloca (size_t size)
+{
+ auto char probe; /* Probes stack depth: */
+ register char *depth = ADDRESS_FUNCTION (probe);
+
+# if STACK_DIRECTION == 0
+ if (STACK_DIR == 0) /* Unknown growth direction. */
+ find_stack_direction ();
+# endif
+
+ /* Reclaim garbage, defined as all alloca'd storage that
+ was allocated from deeper in the stack than currently. */
+
+ {
+ register header *hp; /* Traverses linked list. */
+
+# ifdef emacs
+ BLOCK_INPUT;
+# endif
+
+ for (hp = last_alloca_header; hp != NULL;)
+ if ((STACK_DIR > 0 && hp->h.deep > depth)
+ || (STACK_DIR < 0 && hp->h.deep < depth))
+ {
+ register header *np = hp->h.next;
+
+ free (hp); /* Collect garbage. */
+
+ hp = np; /* -> next header. */
+ }
+ else
+ break; /* Rest are not deeper. */
+
+ last_alloca_header = hp; /* -> last valid storage. */
+
+# ifdef emacs
+ UNBLOCK_INPUT;
+# endif
+ }
+
+ if (size == 0)
+ return NULL; /* No allocation required. */
+
+ /* Allocate combined header + user data storage. */
+
+ {
+ /* Address of header. */
+ register header *new;
+
+ size_t combined_size = sizeof (header) + size;
+ if (combined_size < sizeof (header))
+ memory_full ();
+
+ new = malloc (combined_size);
+
+ if (! new)
+ memory_full ();
+
+ new->h.next = last_alloca_header;
+ new->h.deep = depth;
+
+ last_alloca_header = new;
+
+ /* User storage begins just after header. */
+
+ return (void *) (new + 1);
+ }
+}
+
+# if defined (CRAY) && defined (CRAY_STACKSEG_END)
+
+# ifdef DEBUG_I00AFUNC
+# include <stdio.h>
+# endif
+
+# ifndef CRAY_STACK
+# define CRAY_STACK
+# ifndef CRAY2
+/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
+struct stack_control_header
+ {
+ long shgrow:32; /* Number of times stack has grown. */
+ long shaseg:32; /* Size of increments to stack. */
+ long shhwm:32; /* High water mark of stack. */
+ long shsize:32; /* Current size of stack (all segments). */
+ };
+
+/* The stack segment linkage control information occurs at
+ the high-address end of a stack segment. (The stack
+ grows from low addresses to high addresses.) The initial
+ part of the stack segment linkage control information is
+ 0200 (octal) words. This provides for register storage
+ for the routine which overflows the stack. */
+
+struct stack_segment_linkage
+ {
+ long ss[0200]; /* 0200 overflow words. */
+ long sssize:32; /* Number of words in this segment. */
+ long ssbase:32; /* Offset to stack base. */
+ long:32;
+ long sspseg:32; /* Offset to linkage control of previous
+ segment of stack. */
+ long:32;
+ long sstcpt:32; /* Pointer to task common address block. */
+ long sscsnm; /* Private control structure number for
+ microtasking. */
+ long ssusr1; /* Reserved for user. */
+ long ssusr2; /* Reserved for user. */
+ long sstpid; /* Process ID for pid based multi-tasking. */
+ long ssgvup; /* Pointer to multitasking thread giveup. */
+ long sscray[7]; /* Reserved for Cray Research. */
+ long ssa0;
+ long ssa1;
+ long ssa2;
+ long ssa3;
+ long ssa4;
+ long ssa5;
+ long ssa6;
+ long ssa7;
+ long sss0;
+ long sss1;
+ long sss2;
+ long sss3;
+ long sss4;
+ long sss5;
+ long sss6;
+ long sss7;
+ };
+
+# else /* CRAY2 */
+/* The following structure defines the vector of words
+ returned by the STKSTAT library routine. */
+struct stk_stat
+ {
+ long now; /* Current total stack size. */
+ long maxc; /* Amount of contiguous space which would
+ be required to satisfy the maximum
+ stack demand to date. */
+ long high_water; /* Stack high-water mark. */
+ long overflows; /* Number of stack overflow ($STKOFEN) calls. */
+ long hits; /* Number of internal buffer hits. */
+ long extends; /* Number of block extensions. */
+ long stko_mallocs; /* Block allocations by $STKOFEN. */
+ long underflows; /* Number of stack underflow calls ($STKRETN). */
+ long stko_free; /* Number of deallocations by $STKRETN. */
+ long stkm_free; /* Number of deallocations by $STKMRET. */
+ long segments; /* Current number of stack segments. */
+ long maxs; /* Maximum number of stack segments so far. */
+ long pad_size; /* Stack pad size. */
+ long current_address; /* Current stack segment address. */
+ long current_size; /* Current stack segment size. This
+ number is actually corrupted by STKSTAT to
+ include the fifteen word trailer area. */
+ long initial_address; /* Address of initial segment. */
+ long initial_size; /* Size of initial segment. */
+ };
+
+/* The following structure describes the data structure which trails
+ any stack segment. I think that the description in 'asdef' is
+ out of date. I only describe the parts that I am sure about. */
+
+struct stk_trailer
+ {
+ long this_address; /* Address of this block. */
+ long this_size; /* Size of this block (does not include
+ this trailer). */
+ long unknown2;
+ long unknown3;
+ long link; /* Address of trailer block of previous
+ segment. */
+ long unknown5;
+ long unknown6;
+ long unknown7;
+ long unknown8;
+ long unknown9;
+ long unknown10;
+ long unknown11;
+ long unknown12;
+ long unknown13;
+ long unknown14;
+ };
+
+# endif /* CRAY2 */
+# endif /* not CRAY_STACK */
+
+# ifdef CRAY2
+/* Determine a "stack measure" for an arbitrary ADDRESS.
+ I doubt that "lint" will like this much. */
+
+static long
+i00afunc (long *address)
+{
+ struct stk_stat status;
+ struct stk_trailer *trailer;
+ long *block, size;
+ long result = 0;
+
+ /* We want to iterate through all of the segments. The first
+ step is to get the stack status structure. We could do this
+ more quickly and more directly, perhaps, by referencing the
+ $LM00 common block, but I know that this works. */
+
+ STKSTAT (&status);
+
+ /* Set up the iteration. */
+
+ trailer = (struct stk_trailer *) (status.current_address
+ + status.current_size
+ - 15);
+
+ /* There must be at least one stack segment. Therefore it is
+ a fatal error if "trailer" is null. */
+
+ if (trailer == 0)
+ abort ();
+
+ /* Discard segments that do not contain our argument address. */
+
+ while (trailer != 0)
+ {
+ block = (long *) trailer->this_address;
+ size = trailer->this_size;
+ if (block == 0 || size == 0)
+ abort ();
+ trailer = (struct stk_trailer *) trailer->link;
+ if ((block <= address) && (address < (block + size)))
+ break;
+ }
+
+ /* Set the result to the offset in this segment and add the sizes
+ of all predecessor segments. */
+
+ result = address - block;
+
+ if (trailer == 0)
+ {
+ return result;
+ }
+
+ do
+ {
+ if (trailer->this_size <= 0)
+ abort ();
+ result += trailer->this_size;
+ trailer = (struct stk_trailer *) trailer->link;
+ }
+ while (trailer != 0);
+
+ /* We are done. Note that if you present a bogus address (one
+ not in any segment), you will get a different number back, formed
+ from subtracting the address of the first block. This is probably
+ not what you want. */
+
+ return (result);
+}
+
+# else /* not CRAY2 */
+/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
+ Determine the number of the cell within the stack,
+ given the address of the cell. The purpose of this
+ routine is to linearize, in some sense, stack addresses
+ for alloca. */
+
+static long
+i00afunc (long address)
+{
+ long stkl = 0;
+
+ long size, pseg, this_segment, stack;
+ long result = 0;
+
+ struct stack_segment_linkage *ssptr;
+
+ /* Register B67 contains the address of the end of the
+ current stack segment. If you (as a subprogram) store
+ your registers on the stack and find that you are past
+ the contents of B67, you have overflowed the segment.
+
+ B67 also points to the stack segment linkage control
+ area, which is what we are really interested in. */
+
+ stkl = CRAY_STACKSEG_END ();
+ ssptr = (struct stack_segment_linkage *) stkl;
+
+ /* If one subtracts 'size' from the end of the segment,
+ one has the address of the first word of the segment.
+
+ If this is not the first segment, 'pseg' will be
+ nonzero. */
+
+ pseg = ssptr->sspseg;
+ size = ssptr->sssize;
+
+ this_segment = stkl - size;
+
+ /* It is possible that calling this routine itself caused
+ a stack overflow. Discard stack segments which do not
+ contain the target address. */
+
+ while (!(this_segment <= address && address <= stkl))
+ {
+# ifdef DEBUG_I00AFUNC
+ fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl);
+# endif
+ if (pseg == 0)
+ break;
+ stkl = stkl - pseg;
+ ssptr = (struct stack_segment_linkage *) stkl;
+ size = ssptr->sssize;
+ pseg = ssptr->sspseg;
+ this_segment = stkl - size;
+ }
+
+ result = address - this_segment;
+
+ /* If you subtract pseg from the current end of the stack,
+ you get the address of the previous stack segment's end.
+ This seems a little convoluted to me, but I'll bet you save
+ a cycle somewhere. */
+
+ while (pseg != 0)
+ {
+# ifdef DEBUG_I00AFUNC
+ fprintf (stderr, "%011o %011o\n", pseg, size);
+# endif
+ stkl = stkl - pseg;
+ ssptr = (struct stack_segment_linkage *) stkl;
+ size = ssptr->sssize;
+ pseg = ssptr->sspseg;
+ result += size;
+ }
+ return (result);
+}
+
+# endif /* not CRAY2 */
+# endif /* CRAY */
+
+# endif /* no alloca */
+#endif /* not GCC version 2 */
diff --git a/contrib/diff/lib/alloca_.h b/contrib/diff/lib/alloca_.h
new file mode 100644
index 0000000..8ed34fd
--- /dev/null
+++ b/contrib/diff/lib/alloca_.h
@@ -0,0 +1,68 @@
+/* Memory allocation on the stack.
+ Copyright (C) 1995, 1999, 2001-2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+/* When this file is included, it may be preceded only by preprocessor
+ declarations. Thanks to AIX. Therefore we include it right after
+ "config.h", not later. */
+
+#ifndef _ALLOCA_H
+# define _ALLOCA_H
+
+/* alloca(N) returns a pointer (void* or char*) to N bytes of memory
+ allocated on the stack, and which will last until the function returns.
+ Use of alloca should be avoided:
+ - inside arguments of function calls - undefined behaviour,
+ - in inline functions - the allocation may actually last until the
+ calling function returns,
+ - for huge N (say, N >= 65536) - you never know how large (or small)
+ the stack is, and when the stack cannot fulfill the memory allocation
+ request, the program just crashes.
+ */
+
+# ifdef __GNUC__
+# ifndef alloca
+# define alloca __builtin_alloca
+# endif
+# else
+# ifdef _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+# else
+# if HAVE_ALLOCA_H
+# include <alloca.h>
+# else
+# ifdef _AIX
+ # pragma alloca
+# else
+# ifdef __hpux /* This section must match that of bison generated files. */
+# ifdef __cplusplus
+extern "C" void *alloca (unsigned int);
+# else /* not __cplusplus */
+extern void *alloca ();
+# endif /* not __cplusplus */
+# else /* not __hpux */
+# ifndef alloca
+extern char *alloca ();
+# endif
+# endif /* __hpux */
+# endif
+# endif
+# endif
+# endif
+
+#endif /* _ALLOCA_H */
diff --git a/contrib/diff/lib/basename.c b/contrib/diff/lib/basename.c
new file mode 100644
index 0000000..5ff2989
--- /dev/null
+++ b/contrib/diff/lib/basename.c
@@ -0,0 +1,79 @@
+/* basename.c -- return the last element in a path
+
+ Copyright (C) 1990, 1998, 1999, 2000, 2001, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "dirname.h"
+#include <string.h>
+
+/* In general, we can't use the builtin `basename' function if available,
+ since it has different meanings in different environments.
+ In some environments the builtin `basename' modifies its argument.
+
+ Return the address of the last file name component of NAME. If
+ NAME has no file name components because it is all slashes, return
+ NAME if it is empty, the address of its last slash otherwise. */
+
+char *
+base_name (char const *name)
+{
+ char const *base = name + FILESYSTEM_PREFIX_LEN (name);
+ char const *p;
+
+ for (p = base; *p; p++)
+ {
+ if (ISSLASH (*p))
+ {
+ /* Treat multiple adjacent slashes like a single slash. */
+ do p++;
+ while (ISSLASH (*p));
+
+ /* If the file name ends in slash, use the trailing slash as
+ the basename if no non-slashes have been found. */
+ if (! *p)
+ {
+ if (ISSLASH (*base))
+ base = p - 1;
+ break;
+ }
+
+ /* *P is a non-slash preceded by a slash. */
+ base = p;
+ }
+ }
+
+ return (char *) base;
+}
+
+/* Return the length of of the basename NAME. Typically NAME is the
+ value returned by base_name. Act like strlen (NAME), except omit
+ redundant trailing slashes. */
+
+size_t
+base_len (char const *name)
+{
+ size_t len;
+
+ for (len = strlen (name); 1 < len && ISSLASH (name[len - 1]); len--)
+ continue;
+
+ return len;
+}
diff --git a/contrib/diff/lib/c-stack.c b/contrib/diff/lib/c-stack.c
new file mode 100644
index 0000000..a018e51
--- /dev/null
+++ b/contrib/diff/lib/c-stack.c
@@ -0,0 +1,311 @@
+/* Stack overflow handling.
+
+ Copyright (C) 2002, 2004 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Paul Eggert. */
+
+/* NOTES:
+
+ A program that uses alloca, dynamic arrays, or large local
+ variables may extend the stack by more than a page at a time. If
+ so, when the stack overflows the operating system may not detect
+ the overflow until the program uses the array, and this module may
+ incorrectly report a program error instead of a stack overflow.
+
+ To avoid this problem, allocate only small objects on the stack; a
+ program should be OK if it limits single allocations to a page or
+ less. Allocate larger arrays in static storage, or on the heap
+ (e.g., with malloc). Yes, this is a pain, but we don't know of any
+ better solution that is portable.
+
+ No attempt has been made to deal with multithreaded applications. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifndef __attribute__
+# if __GNUC__ < 3 || __STRICT_ANSI__
+# define __attribute__(x)
+# endif
+#endif
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
+#include <errno.h>
+#ifndef ENOTSUP
+# define ENOTSUP EINVAL
+#endif
+#ifndef EOVERFLOW
+# define EOVERFLOW EINVAL
+#endif
+
+#include <signal.h>
+#if ! HAVE_STACK_T && ! defined stack_t
+typedef struct sigaltstack stack_t;
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#if HAVE_SYS_RESOURCE_H
+/* Include sys/time.h here, because...
+ SunOS-4.1.x <sys/resource.h> fails to include <sys/time.h>.
+ This gives "incomplete type" errors for ru_utime and tu_stime. */
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# endif
+# include <sys/resource.h>
+#endif
+
+#if HAVE_UCONTEXT_H
+# include <ucontext.h>
+#endif
+
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifndef STDERR_FILENO
+# define STDERR_FILENO 2
+#endif
+
+#if DEBUG
+# include <stdio.h>
+#endif
+
+#include "c-stack.h"
+#include "exitfail.h"
+
+#if (HAVE_STRUCT_SIGACTION_SA_SIGACTION && defined SA_NODEFER \
+ && defined SA_ONSTACK && defined SA_RESETHAND && defined SA_SIGINFO)
+# define SIGACTION_WORKS 1
+#else
+# define SIGACTION_WORKS 0
+#endif
+
+extern char *program_name;
+
+/* The user-specified action to take when a SEGV-related program error
+ or stack overflow occurs. */
+static void (* volatile segv_action) (int);
+
+/* Translated messages for program errors and stack overflow. Do not
+ translate them in the signal handler, since gettext is not
+ async-signal-safe. */
+static char const * volatile program_error_message;
+static char const * volatile stack_overflow_message;
+
+/* Output an error message, then exit with status EXIT_FAILURE if it
+ appears to have been a stack overflow, or with a core dump
+ otherwise. This function is async-signal-safe. */
+
+static void die (int) __attribute__ ((noreturn));
+static void
+die (int signo)
+{
+ char const *message;
+ segv_action (signo);
+ message = signo ? program_error_message : stack_overflow_message;
+ write (STDERR_FILENO, program_name, strlen (program_name));
+ write (STDERR_FILENO, ": ", 2);
+ write (STDERR_FILENO, message, strlen (message));
+ write (STDERR_FILENO, "\n", 1);
+ if (! signo)
+ _exit (exit_failure);
+ kill (getpid (), signo);
+ abort ();
+}
+
+#if HAVE_SIGALTSTACK && HAVE_DECL_SIGALTSTACK
+
+/* Direction of the C runtime stack. This function is
+ async-signal-safe. */
+
+# if STACK_DIRECTION
+# define find_stack_direction(ptr) STACK_DIRECTION
+# else
+static int
+find_stack_direction (char const *addr)
+{
+ char dummy;
+ return ! addr ? find_stack_direction (&dummy) : addr < &dummy ? 1 : -1;
+}
+# endif
+
+/* Storage for the alternate signal stack. */
+static union
+{
+ char buffer[SIGSTKSZ];
+
+ /* These other members are for proper alignment. There's no
+ standard way to guarantee stack alignment, but this seems enough
+ in practice. */
+ long double ld;
+ long l;
+ void *p;
+} alternate_signal_stack;
+
+# if SIGACTION_WORKS
+
+/* Handle a segmentation violation and exit. This function is
+ async-signal-safe. */
+
+static void segv_handler (int, siginfo_t *, void *) __attribute__((noreturn));
+static void
+segv_handler (int signo, siginfo_t *info,
+ void *context __attribute__ ((unused)))
+{
+ /* Clear SIGNO if it seems to have been a stack overflow. */
+ if (0 < info->si_code)
+ {
+# if ! HAVE_XSI_STACK_OVERFLOW_HEURISTIC
+ /* We can't easily determine whether it is a stack overflow; so
+ assume that the rest of our program is perfect (!) and that
+ this segmentation violation is a stack overflow. */
+ signo = 0;
+# else
+ /* If the faulting address is within the stack, or within one
+ page of the stack end, assume that it is a stack
+ overflow. */
+ ucontext_t const *user_context = context;
+ char const *stack_base = user_context->uc_stack.ss_sp;
+ size_t stack_size = user_context->uc_stack.ss_size;
+ char const *faulting_address = info->si_addr;
+ size_t s = faulting_address - stack_base;
+ size_t page_size = sysconf (_SC_PAGESIZE);
+ if (find_stack_direction (0) < 0)
+ s += page_size;
+ if (s < stack_size + page_size)
+ signo = 0;
+
+# if DEBUG
+ {
+ char buf[1024];
+ sprintf (buf,
+ "segv_handler fault=%p base=%p size=%lx page=%lx signo=%d\n",
+ faulting_address, stack_base, (unsigned long) stack_size,
+ (unsigned long) page_size, signo);
+ write (STDERR_FILENO, buf, strlen (buf));
+ }
+# endif
+# endif
+ }
+
+ die (signo);
+}
+# endif
+
+static void
+null_action (int signo __attribute__ ((unused)))
+{
+}
+
+/* Set up ACTION so that it is invoked on C stack overflow. Return -1
+ (setting errno) if this cannot be done.
+
+ When ACTION is called, it is passed an argument equal to SIGSEGV
+ for a segmentation violation that does not appear related to stack
+ overflow, and is passed zero otherwise. On many platforms it is
+ hard to tell; when in doubt, zero is passed.
+
+ A null ACTION acts like an action that does nothing.
+
+ ACTION must be async-signal-safe. ACTION together with its callees
+ must not require more than SIGSTKSZ bytes of stack space. */
+
+int
+c_stack_action (void (*action) (int))
+{
+ int r;
+ stack_t st;
+ st.ss_flags = 0;
+ st.ss_sp = alternate_signal_stack.buffer;
+ st.ss_size = sizeof alternate_signal_stack.buffer;
+ r = sigaltstack (&st, 0);
+ if (r != 0)
+ return r;
+
+ segv_action = action ? action : null_action;
+ program_error_message = _("program error");
+ stack_overflow_message = _("stack overflow");
+
+ {
+# if SIGACTION_WORKS
+ struct sigaction act;
+ sigemptyset (&act.sa_mask);
+
+ /* POSIX 1003.1-2001 says SA_RESETHAND implies SA_NODEFER, but
+ this is not true on Solaris 8 at least. It doesn't hurt to use
+ SA_NODEFER here, so leave it in. */
+ act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO;
+
+ act.sa_sigaction = segv_handler;
+
+ return sigaction (SIGSEGV, &act, 0);
+# else
+ return signal (SIGSEGV, die) == SIG_ERR ? -1 : 0;
+# endif
+ }
+}
+
+#else /* ! (HAVE_SIGALTSTACK && HAVE_DECL_SIGALTSTACK) */
+
+int
+c_stack_action (void (*action) (int) __attribute__ ((unused)))
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
+#endif
+
+
+
+#if DEBUG
+
+int volatile exit_failure;
+
+static long
+recurse (char *p)
+{
+ char array[500];
+ array[0] = 1;
+ return *p + recurse (array);
+}
+
+char *program_name;
+
+int
+main (int argc __attribute__ ((unused)), char **argv)
+{
+ program_name = argv[0];
+ fprintf (stderr,
+ "The last output line should contain \"stack overflow\".\n");
+ if (c_stack_action (0) == 0)
+ return recurse ("\1");
+ perror ("c_stack_action");
+ return 1;
+}
+
+#endif /* DEBUG */
+
+/*
+Local Variables:
+compile-command: "gcc -DDEBUG -DHAVE_CONFIG_H -I.. -g -O -Wall -W c-stack.c"
+End:
+*/
diff --git a/contrib/diff/lib/c-stack.h b/contrib/diff/lib/c-stack.h
new file mode 100644
index 0000000..968fd52
--- /dev/null
+++ b/contrib/diff/lib/c-stack.h
@@ -0,0 +1,19 @@
+/* Stack overflow handling.
+
+ Copyright (C) 2002, 2004 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+int c_stack_action (void (*) (int));
diff --git a/contrib/diff/lib/cmpbuf.c b/contrib/diff/lib/cmpbuf.c
new file mode 100644
index 0000000..858aa39
--- /dev/null
+++ b/contrib/diff/lib/cmpbuf.c
@@ -0,0 +1,147 @@
+/* Buffer primitives for comparison operations.
+
+ Copyright (C) 1993, 1995, 1998, 2001, 2002 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; see the file COPYING.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <limits.h>
+
+#include <signal.h>
+#ifndef SA_RESTART
+# ifdef SA_INTERRUPT /* e.g. SunOS 4.1.x */
+# define SA_RESTART SA_INTERRUPT
+# else
+# define SA_RESTART 0
+# endif
+#endif
+
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+
+#include <sys/types.h>
+#include "cmpbuf.h"
+
+/* Determine whether an integer type is signed, and its bounds.
+ This code assumes two's (or one's!) complement with no holes. */
+
+/* The extra casts work around common compiler bugs,
+ e.g. Cray C 5.0.3.0 when t == time_t. */
+#ifndef TYPE_SIGNED
+# define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+#endif
+#ifndef TYPE_MINIMUM
+# define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \
+ ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) \
+ : (t) 0))
+#endif
+#ifndef TYPE_MAXIMUM
+# define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t)))
+#endif
+
+#ifndef PTRDIFF_MAX
+# define PTRDIFF_MAX TYPE_MAXIMUM (ptrdiff_t)
+#endif
+#ifndef SIZE_MAX
+# define SIZE_MAX TYPE_MAXIMUM (size_t)
+#endif
+#ifndef SSIZE_MAX
+# define SSIZE_MAX TYPE_MAXIMUM (ssize_t)
+#endif
+
+#undef MIN
+#define MIN(a, b) ((a) <= (b) ? (a) : (b))
+
+/* Read NBYTES bytes from descriptor FD into BUF.
+ NBYTES must not be SIZE_MAX.
+ Return the number of characters successfully read.
+ On error, return SIZE_MAX, setting errno.
+ The number returned is always NBYTES unless end-of-file or error. */
+
+size_t
+block_read (int fd, char *buf, size_t nbytes)
+{
+ char *bp = buf;
+ char const *buflim = buf + nbytes;
+ size_t readlim = SSIZE_MAX;
+
+ do
+ {
+ size_t bytes_to_read = MIN (buflim - bp, readlim);
+ ssize_t nread = read (fd, bp, bytes_to_read);
+ if (nread <= 0)
+ {
+ if (nread == 0)
+ break;
+
+ /* Accommodate Tru64 5.1, which can't read more than INT_MAX
+ bytes at a time. They call that a 64-bit OS? */
+ if (errno == EINVAL && INT_MAX < bytes_to_read)
+ {
+ readlim = INT_MAX;
+ continue;
+ }
+
+ /* This is needed for programs that have signal handlers on
+ older hosts without SA_RESTART. It also accommodates
+ ancient AIX hosts that set errno to EINTR after uncaught
+ SIGCONT. See <news:1r77ojINN85n@ftp.UU.NET>
+ (1993-04-22). */
+ if (! SA_RESTART && errno == EINTR)
+ continue;
+
+ return SIZE_MAX;
+ }
+ bp += nread;
+ }
+ while (bp < buflim);
+
+ return bp - buf;
+}
+
+/* Least common multiple of two buffer sizes A and B. However, if
+ either A or B is zero, or if the multiple is greater than LCM_MAX,
+ return a reasonable buffer size. */
+
+size_t
+buffer_lcm (size_t a, size_t b, size_t lcm_max)
+{
+ size_t lcm, m, n, q, r;
+
+ /* Yield reasonable values if buffer sizes are zero. */
+ if (!a)
+ return b ? b : 8 * 1024;
+ if (!b)
+ return a;
+
+ /* n = gcd (a, b) */
+ for (m = a, n = b; (r = m % n) != 0; m = n, n = r)
+ continue;
+
+ /* Yield a if there is an overflow. */
+ q = a / n;
+ lcm = q * b;
+ return lcm <= lcm_max && lcm / b == q ? lcm : a;
+}
diff --git a/contrib/diff/lib/cmpbuf.h b/contrib/diff/lib/cmpbuf.h
new file mode 100644
index 0000000..9b29cd0
--- /dev/null
+++ b/contrib/diff/lib/cmpbuf.h
@@ -0,0 +1,21 @@
+/* Buffer primitives for comparison operations.
+
+ Copyright (C) 2002 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; see the file COPYING.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+size_t block_read (int, char *, size_t);
+size_t buffer_lcm (size_t, size_t, size_t);
diff --git a/contrib/diff/lib/dirname.c b/contrib/diff/lib/dirname.c
new file mode 100644
index 0000000..815192a
--- /dev/null
+++ b/contrib/diff/lib/dirname.c
@@ -0,0 +1,119 @@
+/* dirname.c -- return all but the last element in a path
+ Copyright (C) 1990, 1998, 2000, 2001, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "dirname.h"
+
+#include <string.h>
+#include "xalloc.h"
+
+/* Return the length of `dirname (PATH)', or zero if PATH is
+ in the working directory. Works properly even if
+ there are trailing slashes (by effectively ignoring them). */
+size_t
+dir_len (char const *path)
+{
+ size_t prefix_length = FILESYSTEM_PREFIX_LEN (path);
+ size_t length;
+
+ /* Strip the basename and any redundant slashes before it. */
+ for (length = base_name (path) - path; prefix_length < length; length--)
+ if (! ISSLASH (path[length - 1]))
+ return length;
+
+ /* But don't strip the only slash from "/". */
+ return prefix_length + ISSLASH (path[prefix_length]);
+}
+
+/* Return the leading directories part of PATH,
+ allocated with xmalloc.
+ Works properly even if there are trailing slashes
+ (by effectively ignoring them). */
+
+char *
+dir_name (char const *path)
+{
+ size_t length = dir_len (path);
+ int append_dot = (length == FILESYSTEM_PREFIX_LEN (path));
+ char *newpath = xmalloc (length + append_dot + 1);
+ memcpy (newpath, path, length);
+ if (append_dot)
+ newpath[length++] = '.';
+ newpath[length] = 0;
+ return newpath;
+}
+
+#ifdef TEST_DIRNAME
+/*
+
+Run the test like this (expect no output):
+ gcc -DHAVE_CONFIG_H -DTEST_DIRNAME -I.. -O -Wall \
+ basename.c dirname.c xmalloc.c error.c
+ sed -n '/^BEGIN-DATA$/,/^END-DATA$/p' dirname.c|grep -v DATA|./a.out
+
+If it's been built on a DOS or Windows platforms, run another test like
+this (again, expect no output):
+ sed -n '/^BEGIN-DOS-DATA$/,/^END-DOS-DATA$/p' dirname.c|grep -v DATA|./a.out
+
+BEGIN-DATA
+foo//// .
+bar/foo//// bar
+foo/ .
+/ /
+. .
+a .
+END-DATA
+
+BEGIN-DOS-DATA
+c:///// c:/
+c:/ c:/
+c:/. c:/
+c:foo c:.
+c:foo/bar c:foo
+END-DOS-DATA
+
+*/
+
+# define MAX_BUFF_LEN 1024
+# include <stdio.h>
+
+char *program_name;
+
+int
+main (int argc, char *argv[])
+{
+ char buff[MAX_BUFF_LEN + 1];
+
+ program_name = argv[0];
+
+ buff[MAX_BUFF_LEN] = 0;
+ while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0])
+ {
+ char path[MAX_BUFF_LEN];
+ char expected_result[MAX_BUFF_LEN];
+ char const *result;
+ sscanf (buff, "%s %s", path, expected_result);
+ result = dir_name (path);
+ if (strcmp (result, expected_result))
+ printf ("%s: got %s, expected %s\n", path, result, expected_result);
+ }
+ return 0;
+}
+#endif
diff --git a/contrib/diff/lib/dirname.h b/contrib/diff/lib/dirname.h
new file mode 100644
index 0000000..62da37d
--- /dev/null
+++ b/contrib/diff/lib/dirname.h
@@ -0,0 +1,43 @@
+/* Take file names apart into directory and base names.
+
+ Copyright (C) 1998, 2001, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef DIRNAME_H_
+# define DIRNAME_H_ 1
+
+# include <stddef.h>
+
+# ifndef DIRECTORY_SEPARATOR
+# define DIRECTORY_SEPARATOR '/'
+# endif
+
+# ifndef ISSLASH
+# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR)
+# endif
+
+# ifndef FILESYSTEM_PREFIX_LEN
+# define FILESYSTEM_PREFIX_LEN(Filename) 0
+# endif
+
+char *base_name (char const *path);
+char *dir_name (char const *path);
+size_t base_len (char const *path);
+size_t dir_len (char const *path);
+
+int strip_trailing_slashes (char *path);
+
+#endif /* not DIRNAME_H_ */
diff --git a/contrib/diff/lib/error.c b/contrib/diff/lib/error.c
new file mode 100644
index 0000000..1149235
--- /dev/null
+++ b/contrib/diff/lib/error.c
@@ -0,0 +1,310 @@
+/* Error handler for noninteractive utilities
+ Copyright (C) 1990-1998, 2000-2002, 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "error.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "gettext.h"
+#endif
+
+#ifdef _LIBC
+# include <wchar.h>
+# define mbsrtowcs __mbsrtowcs
+#endif
+
+#if !_LIBC
+# include "unlocked-io.h"
+#endif
+
+#ifndef _
+# define _(String) String
+#endif
+
+/* If NULL, error will flush stdout, then print on stderr the program
+ name, a colon and a space. Otherwise, error will call this
+ function without parameters instead. */
+void (*error_print_progname) (void);
+
+/* This variable is incremented each time `error' is called. */
+unsigned int error_message_count;
+
+#ifdef _LIBC
+/* In the GNU C library, there is a predefined variable for this. */
+
+# define program_name program_invocation_name
+# include <errno.h>
+# include <libio/libioP.h>
+
+/* In GNU libc we want do not want to use the common name `error' directly.
+ Instead make it a weak alias. */
+extern void __error (int status, int errnum, const char *message, ...)
+ __attribute__ ((__format__ (__printf__, 3, 4)));
+extern void __error_at_line (int status, int errnum, const char *file_name,
+ unsigned int line_number, const char *message,
+ ...)
+ __attribute__ ((__format__ (__printf__, 5, 6)));;
+# define error __error
+# define error_at_line __error_at_line
+
+# include <libio/iolibio.h>
+# define fflush(s) INTUSE(_IO_fflush) (s)
+# undef putc
+# define putc(c, fp) INTUSE(_IO_putc) (c, fp)
+
+# include <bits/libc-lock.h>
+
+#else /* not _LIBC */
+
+# if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P
+# ifndef HAVE_DECL_STRERROR_R
+"this configure-time declaration test was not run"
+# endif
+char *strerror_r ();
+# endif
+
+# ifndef SIZE_MAX
+# define SIZE_MAX ((size_t) -1)
+# endif
+
+/* The calling program should define program_name and set it to the
+ name of the executing program. */
+extern char *program_name;
+
+# if HAVE_STRERROR_R || defined strerror_r
+# define __strerror_r strerror_r
+# endif
+#endif /* not _LIBC */
+
+static void
+print_errno_message (int errnum)
+{
+ char const *s;
+
+#if defined HAVE_STRERROR_R || _LIBC
+ char errbuf[1024];
+# if STRERROR_R_CHAR_P || _LIBC
+ s = __strerror_r (errnum, errbuf, sizeof errbuf);
+# else
+ if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0)
+ s = errbuf;
+ else
+ s = 0;
+# endif
+#else
+ s = strerror (errnum);
+#endif
+
+#if !_LIBC
+ if (! s)
+ s = _("Unknown system error");
+#endif
+
+#if _LIBC
+ if (_IO_fwide (stderr, 0) > 0)
+ {
+ __fwprintf (stderr, L": %s", s);
+ return;
+ }
+#endif
+
+ fprintf (stderr, ": %s", s);
+}
+
+static void
+error_tail (int status, int errnum, const char *message, va_list args)
+{
+#if _LIBC
+ if (_IO_fwide (stderr, 0) > 0)
+ {
+# define ALLOCA_LIMIT 2000
+ size_t len = strlen (message) + 1;
+ const wchar_t *wmessage = L"out of memory";
+ wchar_t *wbuf = (len < ALLOCA_LIMIT
+ ? alloca (len * sizeof *wbuf)
+ : len <= SIZE_MAX / sizeof *wbuf
+ ? malloc (len * sizeof *wbuf)
+ : NULL);
+
+ if (wbuf)
+ {
+ size_t res;
+ mbstate_t st;
+ const char *tmp = message;
+ memset (&st, '\0', sizeof (st));
+ res = mbsrtowcs (wbuf, &tmp, len, &st);
+ wmessage = res == (size_t) -1 ? L"???" : wbuf;
+ }
+
+ __vfwprintf (stderr, wmessage, args);
+ if (! (len < ALLOCA_LIMIT))
+ free (wbuf);
+ }
+ else
+#endif
+ vfprintf (stderr, message, args);
+ va_end (args);
+
+ ++error_message_count;
+ if (errnum)
+ print_errno_message (errnum);
+#if _LIBC
+ if (_IO_fwide (stderr, 0) > 0)
+ putwc (L'\n', stderr);
+ else
+#endif
+ putc ('\n', stderr);
+ fflush (stderr);
+ if (status)
+ exit (status);
+}
+
+
+/* Print the program name and error message MESSAGE, which is a printf-style
+ format string with optional args.
+ If ERRNUM is nonzero, print its corresponding system error message.
+ Exit with status STATUS if it is nonzero. */
+void
+error (int status, int errnum, const char *message, ...)
+{
+ va_list args;
+
+#if defined _LIBC && defined __libc_ptf_call
+ /* We do not want this call to be cut short by a thread
+ cancellation. Therefore disable cancellation for now. */
+ int state = PTHREAD_CANCEL_ENABLE;
+ __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
+ 0);
+#endif
+
+ fflush (stdout);
+#ifdef _LIBC
+ _IO_flockfile (stderr);
+#endif
+ if (error_print_progname)
+ (*error_print_progname) ();
+ else
+ {
+#if _LIBC
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s: ", program_name);
+ else
+#endif
+ fprintf (stderr, "%s: ", program_name);
+ }
+
+ va_start (args, message);
+ error_tail (status, errnum, message, args);
+
+#ifdef _LIBC
+ _IO_funlockfile (stderr);
+# ifdef __libc_ptf_call
+ __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
+# endif
+#endif
+}
+
+/* Sometimes we want to have at most one error per line. This
+ variable controls whether this mode is selected or not. */
+int error_one_per_line;
+
+void
+error_at_line (int status, int errnum, const char *file_name,
+ unsigned int line_number, const char *message, ...)
+{
+ va_list args;
+
+ if (error_one_per_line)
+ {
+ static const char *old_file_name;
+ static unsigned int old_line_number;
+
+ if (old_line_number == line_number
+ && (file_name == old_file_name
+ || strcmp (old_file_name, file_name) == 0))
+ /* Simply return and print nothing. */
+ return;
+
+ old_file_name = file_name;
+ old_line_number = line_number;
+ }
+
+#if defined _LIBC && defined __libc_ptf_call
+ /* We do not want this call to be cut short by a thread
+ cancellation. Therefore disable cancellation for now. */
+ int state = PTHREAD_CANCEL_ENABLE;
+ __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
+ 0);
+#endif
+
+ fflush (stdout);
+#ifdef _LIBC
+ _IO_flockfile (stderr);
+#endif
+ if (error_print_progname)
+ (*error_print_progname) ();
+ else
+ {
+#if _LIBC
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s: ", program_name);
+ else
+#endif
+ fprintf (stderr, "%s:", program_name);
+ }
+
+ if (file_name != NULL)
+ {
+#if _LIBC
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s:%d: ", file_name, line_number);
+ else
+#endif
+ fprintf (stderr, "%s:%d: ", file_name, line_number);
+ }
+
+ va_start (args, message);
+ error_tail (status, errnum, message, args);
+
+#ifdef _LIBC
+ _IO_funlockfile (stderr);
+# ifdef __libc_ptf_call
+ __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
+# endif
+#endif
+}
+
+#ifdef _LIBC
+/* Make the weak alias. */
+# undef error
+# undef error_at_line
+weak_alias (__error, error)
+weak_alias (__error_at_line, error_at_line)
+#endif
diff --git a/contrib/diff/lib/error.h b/contrib/diff/lib/error.h
new file mode 100644
index 0000000..8ed6359
--- /dev/null
+++ b/contrib/diff/lib/error.h
@@ -0,0 +1,66 @@
+/* Declaration for error-reporting function
+ Copyright (C) 1995, 1996, 1997, 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _ERROR_H
+#define _ERROR_H 1
+
+#ifndef __attribute__
+/* This feature is available in gcc versions 2.5 and later. */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
+# define __attribute__(Spec) /* empty */
+# endif
+/* The __-protected variants of `format' and `printf' attributes
+ are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
+# define __format__ format
+# define __printf__ printf
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Print a message with `fprintf (stderr, FORMAT, ...)';
+ if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM).
+ If STATUS is nonzero, terminate the program with `exit (STATUS)'. */
+
+extern void error (int __status, int __errnum, const char *__format, ...)
+ __attribute__ ((__format__ (__printf__, 3, 4)));
+
+extern void error_at_line (int __status, int __errnum, const char *__fname,
+ unsigned int __lineno, const char *__format, ...)
+ __attribute__ ((__format__ (__printf__, 5, 6)));
+
+/* If NULL, error will flush stdout, then print on stderr the program
+ name, a colon and a space. Otherwise, error will call this
+ function without parameters instead. */
+extern void (*error_print_progname) (void);
+
+/* This variable is incremented each time `error' is called. */
+extern unsigned int error_message_count;
+
+/* Sometimes we want to have at most one error per line. This
+ variable controls whether this mode is selected or not. */
+extern int error_one_per_line;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* error.h */
diff --git a/contrib/diff/lib/exclude.c b/contrib/diff/lib/exclude.c
new file mode 100644
index 0000000..55f1a39
--- /dev/null
+++ b/contrib/diff/lib/exclude.c
@@ -0,0 +1,263 @@
+/* exclude.c -- exclude file names
+
+ Copyright (C) 1992, 1993, 1994, 1997, 1999, 2000, 2001, 2002, 2003 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; see the file COPYING.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Paul Eggert <eggert@twinsun.com> */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdbool.h>
+
+#include <ctype.h>
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "exclude.h"
+#include "fnmatch.h"
+#include "unlocked-io.h"
+#include "xalloc.h"
+
+#if STDC_HEADERS || (! defined isascii && ! HAVE_ISASCII)
+# define IN_CTYPE_DOMAIN(c) true
+#else
+# define IN_CTYPE_DOMAIN(c) isascii (c)
+#endif
+
+static inline bool
+is_space (unsigned char c)
+{
+ return IN_CTYPE_DOMAIN (c) && isspace (c);
+}
+
+/* Verify a requirement at compile-time (unlike assert, which is runtime). */
+#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; }
+
+/* Non-GNU systems lack these options, so we don't need to check them. */
+#ifndef FNM_CASEFOLD
+# define FNM_CASEFOLD 0
+#endif
+#ifndef FNM_LEADING_DIR
+# define FNM_LEADING_DIR 0
+#endif
+
+verify (EXCLUDE_macros_do_not_collide_with_FNM_macros,
+ (((EXCLUDE_ANCHORED | EXCLUDE_INCLUDE | EXCLUDE_WILDCARDS)
+ & (FNM_PATHNAME | FNM_NOESCAPE | FNM_PERIOD | FNM_LEADING_DIR
+ | FNM_CASEFOLD))
+ == 0));
+
+/* An exclude pattern-options pair. The options are fnmatch options
+ ORed with EXCLUDE_* options. */
+
+struct patopts
+ {
+ char const *pattern;
+ int options;
+ };
+
+/* An exclude list, of pattern-options pairs. */
+
+struct exclude
+ {
+ struct patopts *exclude;
+ size_t exclude_alloc;
+ size_t exclude_count;
+ };
+
+/* Return a newly allocated and empty exclude list. */
+
+struct exclude *
+new_exclude (void)
+{
+ return xzalloc (sizeof *new_exclude ());
+}
+
+/* Free the storage associated with an exclude list. */
+
+void
+free_exclude (struct exclude *ex)
+{
+ free (ex->exclude);
+ free (ex);
+}
+
+/* Return zero if PATTERN matches F, obeying OPTIONS, except that
+ (unlike fnmatch) wildcards are disabled in PATTERN. */
+
+static int
+fnmatch_no_wildcards (char const *pattern, char const *f, int options)
+{
+ if (! (options & FNM_LEADING_DIR))
+ return ((options & FNM_CASEFOLD)
+ ? strcasecmp (pattern, f)
+ : strcmp (pattern, f));
+ else
+ {
+ size_t patlen = strlen (pattern);
+ int r = ((options & FNM_CASEFOLD)
+ ? strncasecmp (pattern, f, patlen)
+ : strncmp (pattern, f, patlen));
+ if (! r)
+ {
+ r = f[patlen];
+ if (r == '/')
+ r = 0;
+ }
+ return r;
+ }
+}
+
+/* Return true if EX excludes F. */
+
+bool
+excluded_filename (struct exclude const *ex, char const *f)
+{
+ size_t exclude_count = ex->exclude_count;
+
+ /* If no options are given, the default is to include. */
+ if (exclude_count == 0)
+ return false;
+ else
+ {
+ struct patopts const *exclude = ex->exclude;
+ size_t i;
+
+ /* Otherwise, the default is the opposite of the first option. */
+ bool excluded = !! (exclude[0].options & EXCLUDE_INCLUDE);
+
+ /* Scan through the options, seeing whether they change F from
+ excluded to included or vice versa. */
+ for (i = 0; i < exclude_count; i++)
+ {
+ char const *pattern = exclude[i].pattern;
+ int options = exclude[i].options;
+ if (excluded == !! (options & EXCLUDE_INCLUDE))
+ {
+ int (*matcher) (char const *, char const *, int) =
+ (options & EXCLUDE_WILDCARDS
+ ? fnmatch
+ : fnmatch_no_wildcards);
+ bool matched = ((*matcher) (pattern, f, options) == 0);
+ char const *p;
+
+ if (! (options & EXCLUDE_ANCHORED))
+ for (p = f; *p && ! matched; p++)
+ if (*p == '/' && p[1] != '/')
+ matched = ((*matcher) (pattern, p + 1, options) == 0);
+
+ excluded ^= matched;
+ }
+ }
+
+ return excluded;
+ }
+}
+
+/* Append to EX the exclusion PATTERN with OPTIONS. */
+
+void
+add_exclude (struct exclude *ex, char const *pattern, int options)
+{
+ struct patopts *patopts;
+
+ if (ex->exclude_count == ex->exclude_alloc)
+ ex->exclude = x2nrealloc (ex->exclude, &ex->exclude_alloc,
+ sizeof *ex->exclude);
+
+ patopts = &ex->exclude[ex->exclude_count++];
+ patopts->pattern = pattern;
+ patopts->options = options;
+}
+
+/* Use ADD_FUNC to append to EX the patterns in FILENAME, each with
+ OPTIONS. LINE_END terminates each pattern in the file. If
+ LINE_END is a space character, ignore trailing spaces and empty
+ lines in FILE. Return -1 on failure, 0 on success. */
+
+int
+add_exclude_file (void (*add_func) (struct exclude *, char const *, int),
+ struct exclude *ex, char const *filename, int options,
+ char line_end)
+{
+ bool use_stdin = filename[0] == '-' && !filename[1];
+ FILE *in;
+ char *buf = NULL;
+ char *p;
+ char const *pattern;
+ char const *lim;
+ size_t buf_alloc = 0;
+ size_t buf_count = 0;
+ int c;
+ int e = 0;
+
+ if (use_stdin)
+ in = stdin;
+ else if (! (in = fopen (filename, "r")))
+ return -1;
+
+ while ((c = getc (in)) != EOF)
+ {
+ if (buf_count == buf_alloc)
+ buf = x2realloc (buf, &buf_alloc);
+ buf[buf_count++] = c;
+ }
+
+ if (ferror (in))
+ e = errno;
+
+ if (!use_stdin && fclose (in) != 0)
+ e = errno;
+
+ buf = xrealloc (buf, buf_count + 1);
+ buf[buf_count] = line_end;
+ lim = buf + buf_count + ! (buf_count == 0 || buf[buf_count - 1] == line_end);
+ pattern = buf;
+
+ for (p = buf; p < lim; p++)
+ if (*p == line_end)
+ {
+ char *pattern_end = p;
+
+ if (is_space (line_end))
+ {
+ for (; ; pattern_end--)
+ if (pattern_end == pattern)
+ goto next_pattern;
+ else if (! is_space (pattern_end[-1]))
+ break;
+ }
+
+ *pattern_end = '\0';
+ (*add_func) (ex, pattern, options);
+
+ next_pattern:
+ pattern = p + 1;
+ }
+
+ errno = e;
+ return e ? -1 : 0;
+}
diff --git a/contrib/diff/lib/exclude.h b/contrib/diff/lib/exclude.h
new file mode 100644
index 0000000..a7e2971
--- /dev/null
+++ b/contrib/diff/lib/exclude.h
@@ -0,0 +1,43 @@
+/* exclude.h -- declarations for excluding file names
+
+ Copyright (C) 1992, 1993, 1994, 1997, 1999, 2001, 2002, 2003 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; see the file COPYING.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Paul Eggert <eggert@twinsun.com> */
+
+/* Exclude options, which can be ORed with fnmatch options. */
+
+/* Patterns must match the start of file names, instead of matching
+ anywhere after a '/'. */
+#define EXCLUDE_ANCHORED (1 << 30)
+
+/* Include instead of exclude. */
+#define EXCLUDE_INCLUDE (1 << 29)
+
+/* '?', '*', '[', and '\\' are special in patterns. Without this
+ option, these characters are ordinary and fnmatch is not used. */
+#define EXCLUDE_WILDCARDS (1 << 28)
+
+struct exclude;
+
+struct exclude *new_exclude (void);
+void free_exclude (struct exclude *);
+void add_exclude (struct exclude *, char const *, int);
+int add_exclude_file (void (*) (struct exclude *, char const *, int),
+ struct exclude *, char const *, int, char);
+bool excluded_filename (struct exclude const *, char const *);
diff --git a/contrib/diff/lib/exit.h b/contrib/diff/lib/exit.h
new file mode 100644
index 0000000..4e8d465
--- /dev/null
+++ b/contrib/diff/lib/exit.h
@@ -0,0 +1,32 @@
+/* exit() function.
+ Copyright (C) 1995, 2001 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _EXIT_H
+#define _EXIT_H
+
+/* Get exit() declaration. */
+#include <stdlib.h>
+
+/* Some systems do not define EXIT_*, even with STDC_HEADERS. */
+#ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+#endif
+#ifndef EXIT_FAILURE
+# define EXIT_FAILURE 1
+#endif
+
+#endif /* _EXIT_H */
diff --git a/contrib/diff/lib/exitfail.c b/contrib/diff/lib/exitfail.c
new file mode 100644
index 0000000..2ae5f69
--- /dev/null
+++ b/contrib/diff/lib/exitfail.c
@@ -0,0 +1,27 @@
+/* Failure exit status
+
+ Copyright (C) 2002, 2003 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; see the file COPYING.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "exitfail.h"
+#include "exit.h"
+
+int volatile exit_failure = EXIT_FAILURE;
diff --git a/contrib/diff/lib/exitfail.h b/contrib/diff/lib/exitfail.h
new file mode 100644
index 0000000..cf5ab71
--- /dev/null
+++ b/contrib/diff/lib/exitfail.h
@@ -0,0 +1,20 @@
+/* Failure exit status
+
+ Copyright (C) 2002 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; see the file COPYING.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+extern int volatile exit_failure;
diff --git a/contrib/diff/lib/file-type.c b/contrib/diff/lib/file-type.c
new file mode 100644
index 0000000..3c58c7f
--- /dev/null
+++ b/contrib/diff/lib/file-type.c
@@ -0,0 +1,75 @@
+/* Return a string describing the type of a file.
+
+ Copyright (C) 1993, 1994, 2001, 2002, 2004 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Paul Eggert. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "file-type.h"
+
+#include <gettext.h>
+#define _(text) gettext (text)
+
+char const *
+file_type (struct stat const *st)
+{
+ /* See POSIX 1003.1-2001 XCU Table 4-8 lines 17093-17107 for some of
+ these formats.
+
+ To keep diagnostics grammatical in English, the returned string
+ must start with a consonant. */
+
+ if (S_ISREG (st->st_mode))
+ return st->st_size == 0 ? _("regular empty file") : _("regular file");
+
+ if (S_ISDIR (st->st_mode))
+ return _("directory");
+
+ if (S_ISBLK (st->st_mode))
+ return _("block special file");
+
+ if (S_ISCHR (st->st_mode))
+ return _("character special file");
+
+ if (S_ISFIFO (st->st_mode))
+ return _("fifo");
+
+ if (S_ISLNK (st->st_mode))
+ return _("symbolic link");
+
+ if (S_ISSOCK (st->st_mode))
+ return _("socket");
+
+ if (S_TYPEISMQ (st))
+ return _("message queue");
+
+ if (S_TYPEISSEM (st))
+ return _("semaphore");
+
+ if (S_TYPEISSHM (st))
+ return _("shared memory object");
+
+ if (S_TYPEISTMO (st))
+ return _("typed memory object");
+
+ return _("weird file");
+}
diff --git a/contrib/diff/lib/file-type.h b/contrib/diff/lib/file-type.h
new file mode 100644
index 0000000..502f091
--- /dev/null
+++ b/contrib/diff/lib/file-type.h
@@ -0,0 +1,166 @@
+/* Return a string describing the type of a file.
+
+ Copyright (C) 1993, 1994, 2001, 2002, 2004 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Paul Eggert and Jim Meyering. */
+
+#ifndef FILE_TYPE_H
+# define FILE_TYPE_H 1
+
+# if ! defined S_ISREG && ! defined S_IFREG
+you must include <sys/stat.h> before including this file
+# endif
+
+char const *file_type (struct stat const *);
+
+# ifndef S_IFMT
+# define S_IFMT 0170000
+# endif
+
+# if STAT_MACROS_BROKEN
+# undef S_ISBLK
+# undef S_ISCHR
+# undef S_ISDIR
+# undef S_ISDOOR
+# undef S_ISFIFO
+# undef S_ISLNK
+# undef S_ISNAM
+# undef S_ISMPB
+# undef S_ISMPC
+# undef S_ISNWK
+# undef S_ISREG
+# undef S_ISSOCK
+# endif
+
+
+# ifndef S_ISBLK
+# ifdef S_IFBLK
+# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
+# else
+# define S_ISBLK(m) 0
+# endif
+# endif
+
+# ifndef S_ISCHR
+# ifdef S_IFCHR
+# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+# else
+# define S_ISCHR(m) 0
+# endif
+# endif
+
+# ifndef S_ISDIR
+# ifdef S_IFDIR
+# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+# else
+# define S_ISDIR(m) 0
+# endif
+# endif
+
+# ifndef S_ISDOOR /* Solaris 2.5 and up */
+# ifdef S_IFDOOR
+# define S_ISDOOR(m) (((m) & S_IFMT) == S_IFDOOR)
+# else
+# define S_ISDOOR(m) 0
+# endif
+# endif
+
+# ifndef S_ISFIFO
+# ifdef S_IFIFO
+# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
+# else
+# define S_ISFIFO(m) 0
+# endif
+# endif
+
+# ifndef S_ISLNK
+# ifdef S_IFLNK
+# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+# else
+# define S_ISLNK(m) 0
+# endif
+# endif
+
+# ifndef S_ISMPB /* V7 */
+# ifdef S_IFMPB
+# define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
+# define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
+# else
+# define S_ISMPB(m) 0
+# define S_ISMPC(m) 0
+# endif
+# endif
+
+# ifndef S_ISNAM /* Xenix */
+# ifdef S_IFNAM
+# define S_ISNAM(m) (((m) & S_IFMT) == S_IFNAM)
+# else
+# define S_ISNAM(m) 0
+# endif
+# endif
+
+# ifndef S_ISNWK /* HP/UX */
+# ifdef S_IFNWK
+# define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
+# else
+# define S_ISNWK(m) 0
+# endif
+# endif
+
+# ifndef S_ISREG
+# ifdef S_IFREG
+# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+# else
+# define S_ISREG(m) 0
+# endif
+# endif
+
+# ifndef S_ISSOCK
+# ifdef S_IFSOCK
+# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
+# else
+# define S_ISSOCK(m) 0
+# endif
+# endif
+
+
+# ifndef S_TYPEISMQ
+# define S_TYPEISMQ(p) 0
+# endif
+
+# ifndef S_TYPEISTMO
+# define S_TYPEISTMO(p) 0
+# endif
+
+
+# ifndef S_TYPEISSEM
+# ifdef S_INSEM
+# define S_TYPEISSEM(p) (S_ISNAM ((p)->st_mode) && (p)->st_rdev == S_INSEM)
+# else
+# define S_TYPEISSEM(p) 0
+# endif
+# endif
+
+# ifndef S_TYPEISSHM
+# ifdef S_INSHD
+# define S_TYPEISSHM(p) (S_ISNAM ((p)->st_mode) && (p)->st_rdev == S_INSHD)
+# else
+# define S_TYPEISSHM(p) 0
+# endif
+# endif
+
+#endif /* FILE_TYPE_H */
diff --git a/contrib/diff/lib/fnmatch.c b/contrib/diff/lib/fnmatch.c
new file mode 100644
index 0000000..d0cd8cd
--- /dev/null
+++ b/contrib/diff/lib/fnmatch.c
@@ -0,0 +1,403 @@
+/* Copyright (C) 1991,1992,1993,1996,1997,1998,1999,2000,2001,2002,2003,2004
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Enable GNU extensions in fnmatch.h. */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+# define HAVE_ALLOCA 1
+#else
+# if defined HAVE_ALLOCA_H || defined _LIBC
+# include <alloca.h>
+# else
+# ifdef _AIX
+ # pragma alloca
+# else
+# ifndef alloca
+char *alloca ();
+# endif
+# endif
+# endif
+#endif
+
+#if ! defined __builtin_expect && __GNUC__ < 3
+# define __builtin_expect(expr, expected) (expr)
+#endif
+
+#include <fnmatch.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define WIDE_CHAR_SUPPORT (HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_BTOWC)
+
+/* For platform which support the ISO C amendement 1 functionality we
+ support user defined character classes. */
+#if defined _LIBC || WIDE_CHAR_SUPPORT
+/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */
+# include <wchar.h>
+# include <wctype.h>
+#endif
+
+/* We need some of the locale data (the collation sequence information)
+ but there is no interface to get this information in general. Therefore
+ we support a correct implementation only in glibc. */
+#ifdef _LIBC
+# include "../locale/localeinfo.h"
+# include "../locale/elem-hash.h"
+# include "../locale/coll-lookup.h"
+# include <shlib-compat.h>
+
+# define CONCAT(a,b) __CONCAT(a,b)
+# define mbsrtowcs __mbsrtowcs
+# define fnmatch __fnmatch
+extern int fnmatch (const char *pattern, const char *string, int flags);
+#endif
+
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t) -1)
+#endif
+
+/* We often have to test for FNM_FILE_NAME and FNM_PERIOD being both set. */
+#define NO_LEADING_PERIOD(flags) \
+ ((flags & (FNM_FILE_NAME | FNM_PERIOD)) == (FNM_FILE_NAME | FNM_PERIOD))
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself, and have not detected a bug
+ in the library. 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__ || !HAVE_FNMATCH_GNU
+
+
+# if defined STDC_HEADERS || !defined isascii
+# define ISASCII(c) 1
+# else
+# define ISASCII(c) isascii(c)
+# endif
+
+# ifdef isblank
+# define ISBLANK(c) (ISASCII (c) && isblank (c))
+# else
+# define ISBLANK(c) ((c) == ' ' || (c) == '\t')
+# endif
+# ifdef isgraph
+# define ISGRAPH(c) (ISASCII (c) && isgraph (c))
+# else
+# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
+# endif
+
+# 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))
+
+# define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
+
+# if defined _LIBC || WIDE_CHAR_SUPPORT
+/* The GNU C library provides support for user-defined character classes
+ and the functions from ISO C amendement 1. */
+# ifdef CHARCLASS_NAME_MAX
+# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
+# else
+/* This shouldn't happen but some implementation might still have this
+ problem. Use a reasonable default value. */
+# define CHAR_CLASS_MAX_LENGTH 256
+# endif
+
+# ifdef _LIBC
+# define IS_CHAR_CLASS(string) __wctype (string)
+# else
+# define IS_CHAR_CLASS(string) wctype (string)
+# endif
+
+# ifdef _LIBC
+# define ISWCTYPE(WC, WT) __iswctype (WC, WT)
+# else
+# define ISWCTYPE(WC, WT) iswctype (WC, WT)
+# endif
+
+# if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS) || _LIBC
+/* In this case we are implementing the multibyte character handling. */
+# define HANDLE_MULTIBYTE 1
+# endif
+
+# else
+# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */
+
+# define IS_CHAR_CLASS(string) \
+ (STREQ (string, "alpha") || STREQ (string, "upper") \
+ || STREQ (string, "lower") || STREQ (string, "digit") \
+ || STREQ (string, "alnum") || STREQ (string, "xdigit") \
+ || STREQ (string, "space") || STREQ (string, "print") \
+ || STREQ (string, "punct") || STREQ (string, "graph") \
+ || STREQ (string, "cntrl") || STREQ (string, "blank"))
+# endif
+
+/* Avoid depending on library functions or files
+ whose names are inconsistent. */
+
+# ifndef errno
+extern int errno;
+# endif
+
+/* Global variable. */
+static int posixly_correct;
+
+# ifndef internal_function
+/* Inside GNU libc we mark some function in a special way. In other
+ environments simply ignore the marking. */
+# define internal_function
+# endif
+
+/* Note that this evaluates C many times. */
+# ifdef _LIBC
+# define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
+# else
+# define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
+# endif
+# define CHAR char
+# define UCHAR unsigned char
+# define INT int
+# define FCT internal_fnmatch
+# define EXT ext_match
+# define END end_pattern
+# define L(CS) CS
+# ifdef _LIBC
+# define BTOWC(C) __btowc (C)
+# else
+# define BTOWC(C) btowc (C)
+# endif
+# define STRLEN(S) strlen (S)
+# define STRCAT(D, S) strcat (D, S)
+# ifdef _LIBC
+# define MEMPCPY(D, S, N) __mempcpy (D, S, N)
+# else
+# if HAVE_MEMPCPY
+# define MEMPCPY(D, S, N) mempcpy (D, S, N)
+# else
+# define MEMPCPY(D, S, N) ((void *) ((char *) memcpy (D, S, N) + (N)))
+# endif
+# endif
+# define MEMCHR(S, C, N) memchr (S, C, N)
+# define STRCOLL(S1, S2) strcoll (S1, S2)
+# include "fnmatch_loop.c"
+
+
+# if HANDLE_MULTIBYTE
+# define FOLD(c) ((flags & FNM_CASEFOLD) ? towlower (c) : (c))
+# define CHAR wchar_t
+# define UCHAR wint_t
+# define INT wint_t
+# define FCT internal_fnwmatch
+# define EXT ext_wmatch
+# define END end_wpattern
+# define L(CS) L##CS
+# define BTOWC(C) (C)
+# ifdef _LIBC
+# define STRLEN(S) __wcslen (S)
+# define STRCAT(D, S) __wcscat (D, S)
+# define MEMPCPY(D, S, N) __wmempcpy (D, S, N)
+# else
+# define STRLEN(S) wcslen (S)
+# define STRCAT(D, S) wcscat (D, S)
+# if HAVE_WMEMPCPY
+# define MEMPCPY(D, S, N) wmempcpy (D, S, N)
+# else
+# define MEMPCPY(D, S, N) (wmemcpy (D, S, N) + (N))
+# endif
+# endif
+# define MEMCHR(S, C, N) wmemchr (S, C, N)
+# define STRCOLL(S1, S2) wcscoll (S1, S2)
+# define WIDE_CHAR_VERSION 1
+
+# undef IS_CHAR_CLASS
+/* We have to convert the wide character string in a multibyte string. But
+ we know that the character class names consist of alphanumeric characters
+ from the portable character set, and since the wide character encoding
+ for a member of the portable character set is the same code point as
+ its single-byte encoding, we can use a simplified method to convert the
+ string to a multibyte character string. */
+static wctype_t
+is_char_class (const wchar_t *wcs)
+{
+ char s[CHAR_CLASS_MAX_LENGTH + 1];
+ char *cp = s;
+
+ do
+ {
+ /* Test for a printable character from the portable character set. */
+# ifdef _LIBC
+ if (*wcs < 0x20 || *wcs > 0x7e
+ || *wcs == 0x24 || *wcs == 0x40 || *wcs == 0x60)
+ return (wctype_t) 0;
+# else
+ switch (*wcs)
+ {
+ case L' ': case L'!': case L'"': case L'#': case L'%':
+ case L'&': case L'\'': case L'(': case L')': case L'*':
+ case L'+': case L',': case L'-': case L'.': case L'/':
+ case L'0': case L'1': case L'2': case L'3': case L'4':
+ case L'5': case L'6': case L'7': case L'8': case L'9':
+ case L':': case L';': case L'<': case L'=': case L'>':
+ case L'?':
+ case L'A': case L'B': case L'C': case L'D': case L'E':
+ case L'F': case L'G': case L'H': case L'I': case L'J':
+ case L'K': case L'L': case L'M': case L'N': case L'O':
+ case L'P': case L'Q': case L'R': case L'S': case L'T':
+ case L'U': case L'V': case L'W': case L'X': case L'Y':
+ case L'Z':
+ case L'[': case L'\\': case L']': case L'^': case L'_':
+ case L'a': case L'b': case L'c': case L'd': case L'e':
+ case L'f': case L'g': case L'h': case L'i': case L'j':
+ case L'k': case L'l': case L'm': case L'n': case L'o':
+ case L'p': case L'q': case L'r': case L's': case L't':
+ case L'u': case L'v': case L'w': case L'x': case L'y':
+ case L'z': case L'{': case L'|': case L'}': case L'~':
+ break;
+ default:
+ return (wctype_t) 0;
+ }
+# endif
+
+ /* Avoid overrunning the buffer. */
+ if (cp == s + CHAR_CLASS_MAX_LENGTH)
+ return (wctype_t) 0;
+
+ *cp++ = (char) *wcs++;
+ }
+ while (*wcs != L'\0');
+
+ *cp = '\0';
+
+# ifdef _LIBC
+ return __wctype (s);
+# else
+ return wctype (s);
+# endif
+}
+# define IS_CHAR_CLASS(string) is_char_class (string)
+
+# include "fnmatch_loop.c"
+# endif
+
+
+int
+fnmatch (const char *pattern, const char *string, int flags)
+{
+# if HANDLE_MULTIBYTE
+# define ALLOCA_LIMIT 2000
+ if (__builtin_expect (MB_CUR_MAX, 1) != 1)
+ {
+ mbstate_t ps;
+ size_t patsize;
+ size_t strsize;
+ size_t totsize;
+ wchar_t *wpattern;
+ wchar_t *wstring;
+ int res;
+
+ /* Calculate the size needed to convert the strings to
+ wide characters. */
+ memset (&ps, '\0', sizeof (ps));
+ patsize = mbsrtowcs (NULL, &pattern, 0, &ps) + 1;
+ if (__builtin_expect (patsize == 0, 0))
+ /* Something wrong.
+ XXX Do we have to set `errno' to something which mbsrtows hasn't
+ already done? */
+ return -1;
+ assert (mbsinit (&ps));
+ strsize = mbsrtowcs (NULL, &string, 0, &ps) + 1;
+ if (__builtin_expect (strsize == 0, 0))
+ /* Something wrong.
+ XXX Do we have to set `errno' to something which mbsrtows hasn't
+ already done? */
+ return -1;
+ assert (mbsinit (&ps));
+ totsize = patsize + strsize;
+ if (__builtin_expect (! (patsize <= totsize
+ && totsize <= SIZE_MAX / sizeof (wchar_t)),
+ 0))
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ /* Allocate room for the wide characters. */
+ if (__builtin_expect (totsize < ALLOCA_LIMIT, 1))
+ wpattern = (wchar_t *) alloca (totsize * sizeof (wchar_t));
+ else
+ {
+ wpattern = malloc (totsize * sizeof (wchar_t));
+ if (__builtin_expect (! wpattern, 0))
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ }
+ wstring = wpattern + patsize;
+
+ /* Convert the strings into wide characters. */
+ mbsrtowcs (wpattern, &pattern, patsize, &ps);
+ assert (mbsinit (&ps));
+ mbsrtowcs (wstring, &string, strsize, &ps);
+
+ res = internal_fnwmatch (wpattern, wstring, wstring + strsize - 1,
+ flags & FNM_PERIOD, flags);
+
+ if (__builtin_expect (! (totsize < ALLOCA_LIMIT), 0))
+ free (wpattern);
+ return res;
+ }
+# endif /* HANDLE_MULTIBYTE */
+
+ return internal_fnmatch (pattern, string, string + strlen (string),
+ flags & FNM_PERIOD, flags);
+}
+
+# ifdef _LIBC
+# undef fnmatch
+versioned_symbol (libc, __fnmatch, fnmatch, GLIBC_2_2_3);
+# if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_2_3)
+strong_alias (__fnmatch, __fnmatch_old)
+compat_symbol (libc, __fnmatch_old, fnmatch, GLIBC_2_0);
+# endif
+libc_hidden_ver (__fnmatch, fnmatch)
+# endif
+
+#endif /* _LIBC or not __GNU_LIBRARY__. */
diff --git a/contrib/diff/lib/fnmatch_.h b/contrib/diff/lib/fnmatch_.h
new file mode 100644
index 0000000..87e661f
--- /dev/null
+++ b/contrib/diff/lib/fnmatch_.h
@@ -0,0 +1,63 @@
+/* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999, 2001, 2002, 2003
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _FNMATCH_H
+# define _FNMATCH_H 1
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/* 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. */
+# define FNM_EXTMATCH (1 << 5) /* Use ksh-like extended matching. */
+# endif
+
+/* Value returned by `fnmatch' if STRING does not match PATTERN. */
+# define FNM_NOMATCH 1
+
+/* This value is returned if the implementation does not support
+ `fnmatch'. Since this is not the case here it will never be
+ returned but the conformance test suites still require the symbol
+ to be defined. */
+# ifdef _XOPEN_SOURCE
+# define FNM_NOSYS (-1)
+# endif
+
+/* Match NAME against the filename pattern PATTERN,
+ returning zero if it matches, FNM_NOMATCH if not. */
+extern int fnmatch (const char *__pattern, const char *__name,
+ int __flags);
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif /* fnmatch.h */
diff --git a/contrib/diff/lib/fnmatch_loop.c b/contrib/diff/lib/fnmatch_loop.c
new file mode 100644
index 0000000..7798b59
--- /dev/null
+++ b/contrib/diff/lib/fnmatch_loop.c
@@ -0,0 +1,1192 @@
+/* Copyright (C) 1991,1992,1993,1996,1997,1998,1999,2000,2001,2002,2003,2004
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Match STRING against the filename pattern PATTERN, returning zero if
+ it matches, nonzero if not. */
+static int EXT (INT opt, const CHAR *pattern, const CHAR *string,
+ const CHAR *string_end, int no_leading_period, int flags)
+ internal_function;
+static const CHAR *END (const CHAR *patternp) internal_function;
+
+static int
+internal_function
+FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end,
+ int no_leading_period, int flags)
+{
+ register const CHAR *p = pattern, *n = string;
+ register UCHAR c;
+#ifdef _LIBC
+# if WIDE_CHAR_VERSION
+ const char *collseq = (const char *)
+ _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC);
+# else
+ const UCHAR *collseq = (const UCHAR *)
+ _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQMB);
+# endif
+#endif
+
+ while ((c = *p++) != L('\0'))
+ {
+ int new_no_leading_period = 0;
+ c = FOLD (c);
+
+ switch (c)
+ {
+ case L('?'):
+ if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
+ {
+ int res;
+
+ res = EXT (c, p, n, string_end, no_leading_period,
+ flags);
+ if (res != -1)
+ return res;
+ }
+
+ if (n == string_end)
+ return FNM_NOMATCH;
+ else if (*n == L('/') && (flags & FNM_FILE_NAME))
+ return FNM_NOMATCH;
+ else if (*n == L('.') && no_leading_period)
+ return FNM_NOMATCH;
+ break;
+
+ case L('\\'):
+ if (!(flags & FNM_NOESCAPE))
+ {
+ c = *p++;
+ if (c == L('\0'))
+ /* Trailing \ loses. */
+ return FNM_NOMATCH;
+ c = FOLD (c);
+ }
+ if (n == string_end || FOLD ((UCHAR) *n) != c)
+ return FNM_NOMATCH;
+ break;
+
+ case L('*'):
+ if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
+ {
+ int res;
+
+ res = EXT (c, p, n, string_end, no_leading_period,
+ flags);
+ if (res != -1)
+ return res;
+ }
+
+ if (n != string_end && *n == L('.') && no_leading_period)
+ return FNM_NOMATCH;
+
+ for (c = *p++; c == L('?') || c == L('*'); c = *p++)
+ {
+ if (*p == L('(') && (flags & FNM_EXTMATCH) != 0)
+ {
+ const CHAR *endp = END (p);
+ if (endp != p)
+ {
+ /* This is a pattern. Skip over it. */
+ p = endp;
+ continue;
+ }
+ }
+
+ if (c == L('?'))
+ {
+ /* A ? needs to match one character. */
+ if (n == string_end)
+ /* There isn't another character; no match. */
+ return FNM_NOMATCH;
+ else if (*n == L('/')
+ && __builtin_expect (flags & FNM_FILE_NAME, 0))
+ /* A slash does not match a wildcard under
+ FNM_FILE_NAME. */
+ 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 == L('\0'))
+ /* The wildcard(s) is/are the last element of the pattern.
+ If the name is a file name and contains another slash
+ this means it cannot match, unless the FNM_LEADING_DIR
+ flag is set. */
+ {
+ int result = (flags & FNM_FILE_NAME) == 0 ? 0 : FNM_NOMATCH;
+
+ if (flags & FNM_FILE_NAME)
+ {
+ if (flags & FNM_LEADING_DIR)
+ result = 0;
+ else
+ {
+ if (MEMCHR (n, L('/'), string_end - n) == NULL)
+ result = 0;
+ }
+ }
+
+ return result;
+ }
+ else
+ {
+ const CHAR *endp;
+
+ endp = MEMCHR (n, (flags & FNM_FILE_NAME) ? L('/') : L('\0'),
+ string_end - n);
+ if (endp == NULL)
+ endp = string_end;
+
+ if (c == L('[')
+ || (__builtin_expect (flags & FNM_EXTMATCH, 0) != 0
+ && (c == L('@') || c == L('+') || c == L('!'))
+ && *p == L('(')))
+ {
+ int flags2 = ((flags & FNM_FILE_NAME)
+ ? flags : (flags & ~FNM_PERIOD));
+ int no_leading_period2 = no_leading_period;
+
+ for (--p; n < endp; ++n, no_leading_period2 = 0)
+ if (FCT (p, n, string_end, no_leading_period2, flags2)
+ == 0)
+ return 0;
+ }
+ else if (c == L('/') && (flags & FNM_FILE_NAME))
+ {
+ while (n < string_end && *n != L('/'))
+ ++n;
+ if (n < string_end && *n == L('/')
+ && (FCT (p, n + 1, string_end, flags & FNM_PERIOD, flags)
+ == 0))
+ return 0;
+ }
+ else
+ {
+ int flags2 = ((flags & FNM_FILE_NAME)
+ ? flags : (flags & ~FNM_PERIOD));
+ int no_leading_period2 = no_leading_period;
+
+ if (c == L('\\') && !(flags & FNM_NOESCAPE))
+ c = *p;
+ c = FOLD (c);
+ for (--p; n < endp; ++n, no_leading_period2 = 0)
+ if (FOLD ((UCHAR) *n) == c
+ && (FCT (p, n, string_end, no_leading_period2, flags2)
+ == 0))
+ return 0;
+ }
+ }
+
+ /* If we come here no match is possible with the wildcard. */
+ return FNM_NOMATCH;
+
+ case L('['):
+ {
+ /* Nonzero if the sense of the character class is inverted. */
+ register int not;
+ CHAR cold;
+ UCHAR fn;
+
+ if (posixly_correct == 0)
+ posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
+
+ if (n == string_end)
+ return FNM_NOMATCH;
+
+ if (*n == L('.') && no_leading_period)
+ return FNM_NOMATCH;
+
+ if (*n == L('/') && (flags & FNM_FILE_NAME))
+ /* `/' cannot be matched. */
+ return FNM_NOMATCH;
+
+ not = (*p == L('!') || (posixly_correct < 0 && *p == L('^')));
+ if (not)
+ ++p;
+
+ fn = FOLD ((UCHAR) *n);
+
+ c = *p++;
+ for (;;)
+ {
+ if (!(flags & FNM_NOESCAPE) && c == L('\\'))
+ {
+ if (*p == L('\0'))
+ return FNM_NOMATCH;
+ c = FOLD ((UCHAR) *p);
+ ++p;
+
+ if (c == fn)
+ goto matched;
+ }
+ else if (c == L('[') && *p == L(':'))
+ {
+ /* Leave room for the null. */
+ CHAR str[CHAR_CLASS_MAX_LENGTH + 1];
+ size_t c1 = 0;
+#if defined _LIBC || WIDE_CHAR_SUPPORT
+ wctype_t wt;
+#endif
+ const CHAR *startp = p;
+
+ for (;;)
+ {
+ if (c1 == CHAR_CLASS_MAX_LENGTH)
+ /* The name is too long and therefore the pattern
+ is ill-formed. */
+ return FNM_NOMATCH;
+
+ c = *++p;
+ if (c == L(':') && p[1] == L(']'))
+ {
+ p += 2;
+ break;
+ }
+ if (c < L('a') || c >= L('z'))
+ {
+ /* This cannot possibly be a character class name.
+ Match it as a normal range. */
+ p = startp;
+ c = L('[');
+ goto normal_bracket;
+ }
+ str[c1++] = c;
+ }
+ str[c1] = L('\0');
+
+#if defined _LIBC || WIDE_CHAR_SUPPORT
+ wt = IS_CHAR_CLASS (str);
+ if (wt == 0)
+ /* Invalid character class name. */
+ return FNM_NOMATCH;
+
+# if defined _LIBC && ! WIDE_CHAR_VERSION
+ /* The following code is glibc specific but does
+ there a good job in speeding up the code since
+ we can avoid the btowc() call. */
+ if (_ISCTYPE ((UCHAR) *n, wt))
+ goto matched;
+# else
+ if (ISWCTYPE (BTOWC ((UCHAR) *n), wt))
+ goto matched;
+# endif
+#else
+ if ((STREQ (str, L("alnum")) && ISALNUM ((UCHAR) *n))
+ || (STREQ (str, L("alpha")) && ISALPHA ((UCHAR) *n))
+ || (STREQ (str, L("blank")) && ISBLANK ((UCHAR) *n))
+ || (STREQ (str, L("cntrl")) && ISCNTRL ((UCHAR) *n))
+ || (STREQ (str, L("digit")) && ISDIGIT ((UCHAR) *n))
+ || (STREQ (str, L("graph")) && ISGRAPH ((UCHAR) *n))
+ || (STREQ (str, L("lower")) && ISLOWER ((UCHAR) *n))
+ || (STREQ (str, L("print")) && ISPRINT ((UCHAR) *n))
+ || (STREQ (str, L("punct")) && ISPUNCT ((UCHAR) *n))
+ || (STREQ (str, L("space")) && ISSPACE ((UCHAR) *n))
+ || (STREQ (str, L("upper")) && ISUPPER ((UCHAR) *n))
+ || (STREQ (str, L("xdigit")) && ISXDIGIT ((UCHAR) *n)))
+ goto matched;
+#endif
+ c = *p++;
+ }
+#ifdef _LIBC
+ else if (c == L('[') && *p == L('='))
+ {
+ UCHAR str[1];
+ uint32_t nrules =
+ _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+ const CHAR *startp = p;
+
+ c = *++p;
+ if (c == L('\0'))
+ {
+ p = startp;
+ c = L('[');
+ goto normal_bracket;
+ }
+ str[0] = c;
+
+ c = *++p;
+ if (c != L('=') || p[1] != L(']'))
+ {
+ p = startp;
+ c = L('[');
+ goto normal_bracket;
+ }
+ p += 2;
+
+ if (nrules == 0)
+ {
+ if ((UCHAR) *n == str[0])
+ goto matched;
+ }
+ else
+ {
+ const int32_t *table;
+# if WIDE_CHAR_VERSION
+ const int32_t *weights;
+ const int32_t *extra;
+# else
+ const unsigned char *weights;
+ const unsigned char *extra;
+# endif
+ const int32_t *indirect;
+ int32_t idx;
+ const UCHAR *cp = (const UCHAR *) str;
+
+ /* This #include defines a local function! */
+# if WIDE_CHAR_VERSION
+# include <locale/weightwc.h>
+# else
+# include <locale/weight.h>
+# endif
+
+# if WIDE_CHAR_VERSION
+ table = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEWC);
+ weights = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTWC);
+ extra = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAWC);
+ indirect = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTWC);
+# else
+ table = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
+ weights = (const unsigned char *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB);
+ extra = (const unsigned char *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
+ indirect = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB);
+# endif
+
+ idx = findidx (&cp);
+ if (idx != 0)
+ {
+ /* We found a table entry. Now see whether the
+ character we are currently at has the same
+ equivalance class value. */
+ int len = weights[idx];
+ int32_t idx2;
+ const UCHAR *np = (const UCHAR *) n;
+
+ idx2 = findidx (&np);
+ if (idx2 != 0 && len == weights[idx2])
+ {
+ int cnt = 0;
+
+ while (cnt < len
+ && (weights[idx + 1 + cnt]
+ == weights[idx2 + 1 + cnt]))
+ ++cnt;
+
+ if (cnt == len)
+ goto matched;
+ }
+ }
+ }
+
+ c = *p++;
+ }
+#endif
+ else if (c == L('\0'))
+ /* [ (unterminated) loses. */
+ return FNM_NOMATCH;
+ else
+ {
+ int is_range = 0;
+
+#ifdef _LIBC
+ int is_seqval = 0;
+
+ if (c == L('[') && *p == L('.'))
+ {
+ uint32_t nrules =
+ _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+ const CHAR *startp = p;
+ size_t c1 = 0;
+
+ while (1)
+ {
+ c = *++p;
+ if (c == L('.') && p[1] == L(']'))
+ {
+ p += 2;
+ break;
+ }
+ if (c == '\0')
+ return FNM_NOMATCH;
+ ++c1;
+ }
+
+ /* We have to handling the symbols differently in
+ ranges since then the collation sequence is
+ important. */
+ is_range = *p == L('-') && p[1] != L('\0');
+
+ if (nrules == 0)
+ {
+ /* There are no names defined in the collation
+ data. Therefore we only accept the trivial
+ names consisting of the character itself. */
+ if (c1 != 1)
+ return FNM_NOMATCH;
+
+ if (!is_range && *n == startp[1])
+ goto matched;
+
+ cold = startp[1];
+ c = *p++;
+ }
+ else
+ {
+ int32_t table_size;
+ const int32_t *symb_table;
+# ifdef WIDE_CHAR_VERSION
+ char str[c1];
+ unsigned int strcnt;
+# else
+# define str (startp + 1)
+# endif
+ const unsigned char *extra;
+ int32_t idx;
+ int32_t elem;
+ int32_t second;
+ int32_t hash;
+
+# ifdef WIDE_CHAR_VERSION
+ /* We have to convert the name to a single-byte
+ string. This is possible since the names
+ consist of ASCII characters and the internal
+ representation is UCS4. */
+ for (strcnt = 0; strcnt < c1; ++strcnt)
+ str[strcnt] = startp[1 + strcnt];
+# endif
+
+ table_size =
+ _NL_CURRENT_WORD (LC_COLLATE,
+ _NL_COLLATE_SYMB_HASH_SIZEMB);
+ symb_table = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE,
+ _NL_COLLATE_SYMB_TABLEMB);
+ extra = (const unsigned char *)
+ _NL_CURRENT (LC_COLLATE,
+ _NL_COLLATE_SYMB_EXTRAMB);
+
+ /* Locate the character in the hashing table. */
+ hash = elem_hash (str, c1);
+
+ idx = 0;
+ elem = hash % table_size;
+ second = hash % (table_size - 2);
+ while (symb_table[2 * elem] != 0)
+ {
+ /* First compare the hashing value. */
+ if (symb_table[2 * elem] == hash
+ && c1 == extra[symb_table[2 * elem + 1]]
+ && memcmp (str,
+ &extra[symb_table[2 * elem + 1]
+ + 1], c1) == 0)
+ {
+ /* Yep, this is the entry. */
+ idx = symb_table[2 * elem + 1];
+ idx += 1 + extra[idx];
+ break;
+ }
+
+ /* Next entry. */
+ elem += second;
+ }
+
+ if (symb_table[2 * elem] != 0)
+ {
+ /* Compare the byte sequence but only if
+ this is not part of a range. */
+# ifdef WIDE_CHAR_VERSION
+ int32_t *wextra;
+
+ idx += 1 + extra[idx];
+ /* Adjust for the alignment. */
+ idx = (idx + 3) & ~3;
+
+ wextra = (int32_t *) &extra[idx + 4];
+# endif
+
+ if (! is_range)
+ {
+# ifdef WIDE_CHAR_VERSION
+ for (c1 = 0;
+ (int32_t) c1 < wextra[idx];
+ ++c1)
+ if (n[c1] != wextra[1 + c1])
+ break;
+
+ if ((int32_t) c1 == wextra[idx])
+ goto matched;
+# else
+ for (c1 = 0; c1 < extra[idx]; ++c1)
+ if (n[c1] != extra[1 + c1])
+ break;
+
+ if (c1 == extra[idx])
+ goto matched;
+# endif
+ }
+
+ /* Get the collation sequence value. */
+ is_seqval = 1;
+# ifdef WIDE_CHAR_VERSION
+ cold = wextra[1 + wextra[idx]];
+# else
+ /* Adjust for the alignment. */
+ idx += 1 + extra[idx];
+ idx = (idx + 3) & ~4;
+ cold = *((int32_t *) &extra[idx]);
+# endif
+
+ c = *p++;
+ }
+ else if (c1 == 1)
+ {
+ /* No valid character. Match it as a
+ single byte. */
+ if (!is_range && *n == str[0])
+ goto matched;
+
+ cold = str[0];
+ c = *p++;
+ }
+ else
+ return FNM_NOMATCH;
+ }
+ }
+ else
+# undef str
+#endif
+ {
+ c = FOLD (c);
+ normal_bracket:
+
+ /* We have to handling the symbols differently in
+ ranges since then the collation sequence is
+ important. */
+ is_range = (*p == L('-') && p[1] != L('\0')
+ && p[1] != L(']'));
+
+ if (!is_range && c == fn)
+ goto matched;
+
+ cold = c;
+ c = *p++;
+ }
+
+ if (c == L('-') && *p != L(']'))
+ {
+#if _LIBC
+ /* We have to find the collation sequence
+ value for C. Collation sequence is nothing
+ we can regularly access. The sequence
+ value is defined by the order in which the
+ definitions of the collation values for the
+ various characters appear in the source
+ file. A strange concept, nowhere
+ documented. */
+ uint32_t fcollseq;
+ uint32_t lcollseq;
+ UCHAR cend = *p++;
+
+# ifdef WIDE_CHAR_VERSION
+ /* Search in the `names' array for the characters. */
+ fcollseq = __collseq_table_lookup (collseq, fn);
+ if (fcollseq == ~((uint32_t) 0))
+ /* XXX We don't know anything about the character
+ we are supposed to match. This means we are
+ failing. */
+ goto range_not_matched;
+
+ if (is_seqval)
+ lcollseq = cold;
+ else
+ lcollseq = __collseq_table_lookup (collseq, cold);
+# else
+ fcollseq = collseq[fn];
+ lcollseq = is_seqval ? cold : collseq[(UCHAR) cold];
+# endif
+
+ is_seqval = 0;
+ if (cend == L('[') && *p == L('.'))
+ {
+ uint32_t nrules =
+ _NL_CURRENT_WORD (LC_COLLATE,
+ _NL_COLLATE_NRULES);
+ const CHAR *startp = p;
+ size_t c1 = 0;
+
+ while (1)
+ {
+ c = *++p;
+ if (c == L('.') && p[1] == L(']'))
+ {
+ p += 2;
+ break;
+ }
+ if (c == '\0')
+ return FNM_NOMATCH;
+ ++c1;
+ }
+
+ if (nrules == 0)
+ {
+ /* There are no names defined in the
+ collation data. Therefore we only
+ accept the trivial names consisting
+ of the character itself. */
+ if (c1 != 1)
+ return FNM_NOMATCH;
+
+ cend = startp[1];
+ }
+ else
+ {
+ int32_t table_size;
+ const int32_t *symb_table;
+# ifdef WIDE_CHAR_VERSION
+ char str[c1];
+ unsigned int strcnt;
+# else
+# define str (startp + 1)
+# endif
+ const unsigned char *extra;
+ int32_t idx;
+ int32_t elem;
+ int32_t second;
+ int32_t hash;
+
+# ifdef WIDE_CHAR_VERSION
+ /* We have to convert the name to a single-byte
+ string. This is possible since the names
+ consist of ASCII characters and the internal
+ representation is UCS4. */
+ for (strcnt = 0; strcnt < c1; ++strcnt)
+ str[strcnt] = startp[1 + strcnt];
+# endif
+
+ table_size =
+ _NL_CURRENT_WORD (LC_COLLATE,
+ _NL_COLLATE_SYMB_HASH_SIZEMB);
+ symb_table = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE,
+ _NL_COLLATE_SYMB_TABLEMB);
+ extra = (const unsigned char *)
+ _NL_CURRENT (LC_COLLATE,
+ _NL_COLLATE_SYMB_EXTRAMB);
+
+ /* Locate the character in the hashing
+ table. */
+ hash = elem_hash (str, c1);
+
+ idx = 0;
+ elem = hash % table_size;
+ second = hash % (table_size - 2);
+ while (symb_table[2 * elem] != 0)
+ {
+ /* First compare the hashing value. */
+ if (symb_table[2 * elem] == hash
+ && (c1
+ == extra[symb_table[2 * elem + 1]])
+ && memcmp (str,
+ &extra[symb_table[2 * elem + 1]
+ + 1], c1) == 0)
+ {
+ /* Yep, this is the entry. */
+ idx = symb_table[2 * elem + 1];
+ idx += 1 + extra[idx];
+ break;
+ }
+
+ /* Next entry. */
+ elem += second;
+ }
+
+ if (symb_table[2 * elem] != 0)
+ {
+ /* Compare the byte sequence but only if
+ this is not part of a range. */
+# ifdef WIDE_CHAR_VERSION
+ int32_t *wextra;
+
+ idx += 1 + extra[idx];
+ /* Adjust for the alignment. */
+ idx = (idx + 3) & ~4;
+
+ wextra = (int32_t *) &extra[idx + 4];
+# endif
+ /* Get the collation sequence value. */
+ is_seqval = 1;
+# ifdef WIDE_CHAR_VERSION
+ cend = wextra[1 + wextra[idx]];
+# else
+ /* Adjust for the alignment. */
+ idx += 1 + extra[idx];
+ idx = (idx + 3) & ~4;
+ cend = *((int32_t *) &extra[idx]);
+# endif
+ }
+ else if (symb_table[2 * elem] != 0 && c1 == 1)
+ {
+ cend = str[0];
+ c = *p++;
+ }
+ else
+ return FNM_NOMATCH;
+ }
+# undef str
+ }
+ else
+ {
+ if (!(flags & FNM_NOESCAPE) && cend == L('\\'))
+ cend = *p++;
+ if (cend == L('\0'))
+ return FNM_NOMATCH;
+ cend = FOLD (cend);
+ }
+
+ /* XXX It is not entirely clear to me how to handle
+ characters which are not mentioned in the
+ collation specification. */
+ if (
+# ifdef WIDE_CHAR_VERSION
+ lcollseq == 0xffffffff ||
+# endif
+ lcollseq <= fcollseq)
+ {
+ /* We have to look at the upper bound. */
+ uint32_t hcollseq;
+
+ if (is_seqval)
+ hcollseq = cend;
+ else
+ {
+# ifdef WIDE_CHAR_VERSION
+ hcollseq =
+ __collseq_table_lookup (collseq, cend);
+ if (hcollseq == ~((uint32_t) 0))
+ {
+ /* Hum, no information about the upper
+ bound. The matching succeeds if the
+ lower bound is matched exactly. */
+ if (lcollseq != fcollseq)
+ goto range_not_matched;
+
+ goto matched;
+ }
+# else
+ hcollseq = collseq[cend];
+# endif
+ }
+
+ if (lcollseq <= hcollseq && fcollseq <= hcollseq)
+ goto matched;
+ }
+# ifdef WIDE_CHAR_VERSION
+ range_not_matched:
+# endif
+#else
+ /* We use a boring value comparison of the character
+ values. This is better than comparing using
+ `strcoll' since the latter would have surprising
+ and sometimes fatal consequences. */
+ UCHAR cend = *p++;
+
+ if (!(flags & FNM_NOESCAPE) && cend == L('\\'))
+ cend = *p++;
+ if (cend == L('\0'))
+ return FNM_NOMATCH;
+
+ /* It is a range. */
+ if (cold <= fn && fn <= cend)
+ goto matched;
+#endif
+
+ c = *p++;
+ }
+ }
+
+ if (c == L(']'))
+ break;
+ }
+
+ if (!not)
+ return FNM_NOMATCH;
+ break;
+
+ matched:
+ /* Skip the rest of the [...] that already matched. */
+ do
+ {
+ ignore_next:
+ c = *p++;
+
+ if (c == L('\0'))
+ /* [... (unterminated) loses. */
+ return FNM_NOMATCH;
+
+ if (!(flags & FNM_NOESCAPE) && c == L('\\'))
+ {
+ if (*p == L('\0'))
+ return FNM_NOMATCH;
+ /* XXX 1003.2d11 is unclear if this is right. */
+ ++p;
+ }
+ else if (c == L('[') && *p == L(':'))
+ {
+ int c1 = 0;
+ const CHAR *startp = p;
+
+ while (1)
+ {
+ c = *++p;
+ if (++c1 == CHAR_CLASS_MAX_LENGTH)
+ return FNM_NOMATCH;
+
+ if (*p == L(':') && p[1] == L(']'))
+ break;
+
+ if (c < L('a') || c >= L('z'))
+ {
+ p = startp;
+ goto ignore_next;
+ }
+ }
+ p += 2;
+ c = *p++;
+ }
+ else if (c == L('[') && *p == L('='))
+ {
+ c = *++p;
+ if (c == L('\0'))
+ return FNM_NOMATCH;
+ c = *++p;
+ if (c != L('=') || p[1] != L(']'))
+ return FNM_NOMATCH;
+ p += 2;
+ c = *p++;
+ }
+ else if (c == L('[') && *p == L('.'))
+ {
+ ++p;
+ while (1)
+ {
+ c = *++p;
+ if (c == '\0')
+ return FNM_NOMATCH;
+
+ if (*p == L('.') && p[1] == L(']'))
+ break;
+ }
+ p += 2;
+ c = *p++;
+ }
+ }
+ while (c != L(']'));
+ if (not)
+ return FNM_NOMATCH;
+ }
+ break;
+
+ case L('+'):
+ case L('@'):
+ case L('!'):
+ if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
+ {
+ int res;
+
+ res = EXT (c, p, n, string_end, no_leading_period, flags);
+ if (res != -1)
+ return res;
+ }
+ goto normal_match;
+
+ case L('/'):
+ if (NO_LEADING_PERIOD (flags))
+ {
+ if (n == string_end || c != (UCHAR) *n)
+ return FNM_NOMATCH;
+
+ new_no_leading_period = 1;
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ normal_match:
+ if (n == string_end || c != FOLD ((UCHAR) *n))
+ return FNM_NOMATCH;
+ }
+
+ no_leading_period = new_no_leading_period;
+ ++n;
+ }
+
+ if (n == string_end)
+ return 0;
+
+ if ((flags & FNM_LEADING_DIR) && n != string_end && *n == L('/'))
+ /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
+ return 0;
+
+ return FNM_NOMATCH;
+}
+
+
+static const CHAR *
+internal_function
+END (const CHAR *pattern)
+{
+ const CHAR *p = pattern;
+
+ while (1)
+ if (*++p == L('\0'))
+ /* This is an invalid pattern. */
+ return pattern;
+ else if (*p == L('['))
+ {
+ /* Handle brackets special. */
+ if (posixly_correct == 0)
+ posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
+
+ /* Skip the not sign. We have to recognize it because of a possibly
+ following ']'. */
+ if (*++p == L('!') || (posixly_correct < 0 && *p == L('^')))
+ ++p;
+ /* A leading ']' is recognized as such. */
+ if (*p == L(']'))
+ ++p;
+ /* Skip over all characters of the list. */
+ while (*p != L(']'))
+ if (*p++ == L('\0'))
+ /* This is no valid pattern. */
+ return pattern;
+ }
+ else if ((*p == L('?') || *p == L('*') || *p == L('+') || *p == L('@')
+ || *p == L('!')) && p[1] == L('('))
+ p = END (p + 1);
+ else if (*p == L(')'))
+ break;
+
+ return p + 1;
+}
+
+
+static int
+internal_function
+EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
+ int no_leading_period, int flags)
+{
+ const CHAR *startp;
+ int level;
+ struct patternlist
+ {
+ struct patternlist *next;
+ CHAR str[1];
+ } *list = NULL;
+ struct patternlist **lastp = &list;
+ size_t pattern_len = STRLEN (pattern);
+ const CHAR *p;
+ const CHAR *rs;
+ enum { ALLOCA_LIMIT = 8000 };
+
+ /* Parse the pattern. Store the individual parts in the list. */
+ level = 0;
+ for (startp = p = pattern + 1; level >= 0; ++p)
+ if (*p == L('\0'))
+ /* This is an invalid pattern. */
+ return -1;
+ else if (*p == L('['))
+ {
+ /* Handle brackets special. */
+ if (posixly_correct == 0)
+ posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
+
+ /* Skip the not sign. We have to recognize it because of a possibly
+ following ']'. */
+ if (*++p == L('!') || (posixly_correct < 0 && *p == L('^')))
+ ++p;
+ /* A leading ']' is recognized as such. */
+ if (*p == L(']'))
+ ++p;
+ /* Skip over all characters of the list. */
+ while (*p != L(']'))
+ if (*p++ == L('\0'))
+ /* This is no valid pattern. */
+ return -1;
+ }
+ else if ((*p == L('?') || *p == L('*') || *p == L('+') || *p == L('@')
+ || *p == L('!')) && p[1] == L('('))
+ /* Remember the nesting level. */
+ ++level;
+ else if (*p == L(')'))
+ {
+ if (level-- == 0)
+ {
+ /* This means we found the end of the pattern. */
+#define NEW_PATTERN \
+ struct patternlist *newp; \
+ size_t plen; \
+ size_t plensize; \
+ size_t newpsize; \
+ \
+ plen = (opt == L('?') || opt == L('@') \
+ ? pattern_len \
+ : p - startp + 1); \
+ plensize = plen * sizeof (CHAR); \
+ newpsize = offsetof (struct patternlist, str) + plensize; \
+ if ((size_t) -1 / sizeof (CHAR) < plen \
+ || newpsize < offsetof (struct patternlist, str) \
+ || ALLOCA_LIMIT <= newpsize) \
+ return -1; \
+ newp = (struct patternlist *) alloca (newpsize); \
+ *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L('\0'); \
+ newp->next = NULL; \
+ *lastp = newp; \
+ lastp = &newp->next
+ NEW_PATTERN;
+ }
+ }
+ else if (*p == L('|'))
+ {
+ if (level == 0)
+ {
+ NEW_PATTERN;
+ startp = p + 1;
+ }
+ }
+ assert (list != NULL);
+ assert (p[-1] == L(')'));
+#undef NEW_PATTERN
+
+ switch (opt)
+ {
+ case L('*'):
+ if (FCT (p, string, string_end, no_leading_period, flags) == 0)
+ return 0;
+ /* FALLTHROUGH */
+
+ case L('+'):
+ do
+ {
+ for (rs = string; rs <= string_end; ++rs)
+ /* First match the prefix with the current pattern with the
+ current pattern. */
+ if (FCT (list->str, string, rs, no_leading_period,
+ flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0
+ /* This was successful. Now match the rest with the rest
+ of the pattern. */
+ && (FCT (p, rs, string_end,
+ rs == string
+ ? no_leading_period
+ : rs[-1] == '/' && NO_LEADING_PERIOD (flags) ? 1 : 0,
+ flags & FNM_FILE_NAME
+ ? flags : flags & ~FNM_PERIOD) == 0
+ /* This didn't work. Try the whole pattern. */
+ || (rs != string
+ && FCT (pattern - 1, rs, string_end,
+ rs == string
+ ? no_leading_period
+ : (rs[-1] == '/' && NO_LEADING_PERIOD (flags)
+ ? 1 : 0),
+ flags & FNM_FILE_NAME
+ ? flags : flags & ~FNM_PERIOD) == 0)))
+ /* It worked. Signal success. */
+ return 0;
+ }
+ while ((list = list->next) != NULL);
+
+ /* None of the patterns lead to a match. */
+ return FNM_NOMATCH;
+
+ case L('?'):
+ if (FCT (p, string, string_end, no_leading_period, flags) == 0)
+ return 0;
+ /* FALLTHROUGH */
+
+ case L('@'):
+ do
+ /* I cannot believe it but `strcat' is actually acceptable
+ here. Match the entire string with the prefix from the
+ pattern list and the rest of the pattern following the
+ pattern list. */
+ if (FCT (STRCAT (list->str, p), string, string_end,
+ no_leading_period,
+ flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0)
+ /* It worked. Signal success. */
+ return 0;
+ while ((list = list->next) != NULL);
+
+ /* None of the patterns lead to a match. */
+ return FNM_NOMATCH;
+
+ case L('!'):
+ for (rs = string; rs <= string_end; ++rs)
+ {
+ struct patternlist *runp;
+
+ for (runp = list; runp != NULL; runp = runp->next)
+ if (FCT (runp->str, string, rs, no_leading_period,
+ flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0)
+ break;
+
+ /* If none of the patterns matched see whether the rest does. */
+ if (runp == NULL
+ && (FCT (p, rs, string_end,
+ rs == string
+ ? no_leading_period
+ : rs[-1] == '/' && NO_LEADING_PERIOD (flags) ? 1 : 0,
+ flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD)
+ == 0))
+ /* This is successful. */
+ return 0;
+ }
+
+ /* None of the patterns together with the rest of the pattern
+ lead to a match. */
+ return FNM_NOMATCH;
+
+ default:
+ assert (! "Invalid extended matching operator");
+ break;
+ }
+
+ return -1;
+}
+
+
+#undef FOLD
+#undef CHAR
+#undef UCHAR
+#undef INT
+#undef FCT
+#undef EXT
+#undef END
+#undef MEMPCPY
+#undef MEMCHR
+#undef STRCOLL
+#undef STRLEN
+#undef STRCAT
+#undef L
+#undef BTOWC
diff --git a/contrib/diff/lib/getopt.c b/contrib/diff/lib/getopt.c
new file mode 100644
index 0000000..8f017f8
--- /dev/null
+++ b/contrib/diff/lib/getopt.c
@@ -0,0 +1,1254 @@
+/* Getopt for GNU.
+ NOTE: getopt is now part of the C library, so if you don't know what
+ "Keep this file name-space clean" means, talk to drepper@gnu.org
+ before changing it!
+ Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001,2002,2003,2004
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
+ Ditto for AIX 3.2 and <stdlib.h>. */
+#ifndef _NO_PROTO
+# define _NO_PROTO
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.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 GETOPT_INTERFACE_VERSION 2
+#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
+# include <gnu-versions.h>
+# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
+# define ELIDE_CODE
+# endif
+#endif
+
+#ifndef ELIDE_CODE
+
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+/* Don't include stdlib.h for non-GNU C libraries because some of them
+ contain conflicting prototypes for getopt. */
+# include <stdlib.h>
+# include <unistd.h>
+#endif /* GNU C library. */
+
+#include <string.h>
+
+#ifdef VMS
+# include <unixlib.h>
+#endif
+
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "gettext.h"
+# define _(msgid) gettext (msgid)
+#endif
+
+#if defined _LIBC && defined USE_IN_LIBIO
+# include <wchar.h>
+#endif
+
+#ifndef attribute_hidden
+# define attribute_hidden
+#endif
+
+/* This version of `getopt' appears to the caller like standard Unix `getopt'
+ but it behaves differently for the user, since it allows the user
+ to intersperse the options with the other arguments.
+
+ As `getopt' works, it permutes the elements of ARGV so that,
+ when it is done, all the options precede everything else. Thus
+ all application programs are extended to handle flexible argument order.
+
+ Setting the environment variable POSIXLY_CORRECT disables permutation.
+ Then the behavior is completely standard.
+
+ GNU application programs can use a third alternative mode in which
+ they can distinguish the relative order of options and other arguments. */
+
+#include "getopt.h"
+#include "getopt_int.h"
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns -1, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+/* 1003.2 says this must be 1 before any call. */
+int optind = 1;
+
+/* Callers store zero here to inhibit the error message
+ for unrecognized options. */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+ This must be initialized on some systems to avoid linking in the
+ system's own getopt implementation. */
+
+int optopt = '?';
+
+/* Keep a global copy of all internal members of getopt_data. */
+
+static struct _getopt_data getopt_data;
+
+
+#ifndef __GNU_LIBRARY__
+
+/* Avoid depending on library functions or files
+ whose names are inconsistent. */
+
+#ifndef getenv
+extern char *getenv ();
+#endif
+
+#endif /* not __GNU_LIBRARY__ */
+
+#ifdef _LIBC
+/* Stored original parameters.
+ XXX This is no good solution. We should rather copy the args so
+ that we can compare them later. But we must not use malloc(3). */
+extern int __libc_argc;
+extern char **__libc_argv;
+
+/* Bash 2.0 gives us an environment variable containing flags
+ indicating ARGV elements that should not be considered arguments. */
+
+# ifdef USE_NONOPTION_FLAGS
+/* Defined in getopt_init.c */
+extern char *__getopt_nonoption_flags;
+# endif
+
+# ifdef USE_NONOPTION_FLAGS
+# define SWAP_FLAGS(ch1, ch2) \
+ if (d->__nonoption_flags_len > 0) \
+ { \
+ char __tmp = __getopt_nonoption_flags[ch1]; \
+ __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \
+ __getopt_nonoption_flags[ch2] = __tmp; \
+ }
+# else
+# define SWAP_FLAGS(ch1, ch2)
+# endif
+#else /* !_LIBC */
+# define SWAP_FLAGS(ch1, ch2)
+#endif /* _LIBC */
+
+/* Exchange two adjacent subsequences of ARGV.
+ One subsequence is elements [first_nonopt,last_nonopt)
+ which contains all the non-options that have been skipped so far.
+ The other is elements [last_nonopt,optind), which contains all
+ the options processed since those non-options were skipped.
+
+ `first_nonopt' and `last_nonopt' are relocated so that they describe
+ the new indices of the non-options in ARGV after they are moved. */
+
+static void
+exchange (char **argv, struct _getopt_data *d)
+{
+ int bottom = d->__first_nonopt;
+ int middle = d->__last_nonopt;
+ int top = d->optind;
+ char *tem;
+
+ /* Exchange the shorter segment with the far end of the longer segment.
+ That puts the shorter segment into the right place.
+ It leaves the longer segment in the right place overall,
+ but it consists of two parts that need to be swapped next. */
+
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
+ /* First make sure the handling of the `__getopt_nonoption_flags'
+ string can work normally. Our top argument must be in the range
+ of the string. */
+ if (d->__nonoption_flags_len > 0 && top >= d->__nonoption_flags_max_len)
+ {
+ /* We must extend the array. The user plays games with us and
+ presents new arguments. */
+ char *new_str = malloc (top + 1);
+ if (new_str == NULL)
+ d->__nonoption_flags_len = d->__nonoption_flags_max_len = 0;
+ else
+ {
+ memset (__mempcpy (new_str, __getopt_nonoption_flags,
+ d->__nonoption_flags_max_len),
+ '\0', top + 1 - d->__nonoption_flags_max_len);
+ d->__nonoption_flags_max_len = top + 1;
+ __getopt_nonoption_flags = new_str;
+ }
+ }
+#endif
+
+ while (top > middle && middle > bottom)
+ {
+ if (top - middle > middle - bottom)
+ {
+ /* Bottom segment is the short one. */
+ int len = middle - bottom;
+ register int i;
+
+ /* Swap it with the top part of the top segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[top - (middle - bottom) + i];
+ argv[top - (middle - bottom) + i] = tem;
+ SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
+ }
+ /* Exclude the moved bottom segment from further swapping. */
+ top -= len;
+ }
+ else
+ {
+ /* Top segment is the short one. */
+ int len = top - middle;
+ register int i;
+
+ /* Swap it with the bottom part of the bottom segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[middle + i];
+ argv[middle + i] = tem;
+ SWAP_FLAGS (bottom + i, middle + i);
+ }
+ /* Exclude the moved top segment from further swapping. */
+ bottom += len;
+ }
+ }
+
+ /* Update records for the slots the non-options now occupy. */
+
+ d->__first_nonopt += (d->optind - d->__last_nonopt);
+ d->__last_nonopt = d->optind;
+}
+
+/* Initialize the internal data when the first call is made. */
+
+static const char *
+_getopt_initialize (int argc, char *const *argv, const char *optstring,
+ struct _getopt_data *d)
+{
+ /* Start processing options with ARGV-element 1 (since ARGV-element 0
+ is the program name); the sequence of previously skipped
+ non-option ARGV-elements is empty. */
+
+ d->__first_nonopt = d->__last_nonopt = d->optind;
+
+ d->__nextchar = NULL;
+
+ d->__posixly_correct = !!getenv ("POSIXLY_CORRECT");
+
+ /* Determine how to handle the ordering of options and nonoptions. */
+
+ if (optstring[0] == '-')
+ {
+ d->__ordering = RETURN_IN_ORDER;
+ ++optstring;
+ }
+ else if (optstring[0] == '+')
+ {
+ d->__ordering = REQUIRE_ORDER;
+ ++optstring;
+ }
+ else if (d->__posixly_correct)
+ d->__ordering = REQUIRE_ORDER;
+ else
+ d->__ordering = PERMUTE;
+
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
+ if (!d->__posixly_correct
+ && argc == __libc_argc && argv == __libc_argv)
+ {
+ if (d->__nonoption_flags_max_len == 0)
+ {
+ if (__getopt_nonoption_flags == NULL
+ || __getopt_nonoption_flags[0] == '\0')
+ d->__nonoption_flags_max_len = -1;
+ else
+ {
+ const char *orig_str = __getopt_nonoption_flags;
+ int len = d->__nonoption_flags_max_len = strlen (orig_str);
+ if (d->__nonoption_flags_max_len < argc)
+ d->__nonoption_flags_max_len = argc;
+ __getopt_nonoption_flags =
+ (char *) malloc (d->__nonoption_flags_max_len);
+ if (__getopt_nonoption_flags == NULL)
+ d->__nonoption_flags_max_len = -1;
+ else
+ memset (__mempcpy (__getopt_nonoption_flags, orig_str, len),
+ '\0', d->__nonoption_flags_max_len - len);
+ }
+ }
+ d->__nonoption_flags_len = d->__nonoption_flags_max_len;
+ }
+ else
+ d->__nonoption_flags_len = 0;
+#endif
+
+ return optstring;
+}
+
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+ given in OPTSTRING.
+
+ If an element of ARGV starts with '-', and is not exactly "-" or "--",
+ then it is an option element. The characters of this element
+ (aside from the initial '-') are option characters. If `getopt'
+ is called repeatedly, it returns successively each of the option characters
+ from each of the option elements.
+
+ If `getopt' finds another option character, it returns that character,
+ updating `optind' and `nextchar' so that the next call to `getopt' can
+ resume the scan with the following option character or ARGV-element.
+
+ If there are no more option characters, `getopt' returns -1.
+ Then `optind' is the index in ARGV of the first ARGV-element
+ that is not an option. (The ARGV-elements have been permuted
+ so that those that are not options now come last.)
+
+ OPTSTRING is a string containing the legitimate option characters.
+ If an option character is seen that is not listed in OPTSTRING,
+ return '?' after printing an error message. If you set `opterr' to
+ zero, the error message is suppressed but we still return '?'.
+
+ If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+ so the following text in the same ARGV-element, or the text of the following
+ ARGV-element, is returned in `optarg'. Two colons mean an option that
+ wants an optional arg; if there is text in the current ARGV-element,
+ it is returned in `optarg', otherwise `optarg' is set to zero.
+
+ If OPTSTRING starts with `-' or `+', it requests different methods of
+ handling the non-option ARGV-elements.
+ See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+ Long-named options begin with `--' instead of `-'.
+ Their names may be abbreviated as long as the abbreviation is unique
+ or is an exact match for some defined option. If they have an
+ argument, it follows the option name in the same ARGV-element, separated
+ from the option name by a `=', or else the in next ARGV-element.
+ When `getopt' finds a long-named option, it returns 0 if that option's
+ `flag' field is nonzero, the value of the option's `val' field
+ if the `flag' field is zero.
+
+ The elements of ARGV aren't really const, because we permute them.
+ But we pretend they're const in the prototype to be compatible
+ with other systems.
+
+ LONGOPTS is a vector of `struct option' terminated by an
+ element containing a name which is zero.
+
+ LONGIND returns the index in LONGOPT of the long-named option found.
+ It is only valid when a long-named option has been found by the most
+ recent call.
+
+ If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+ long-named options. */
+
+int
+_getopt_internal_r (int argc, char *const *argv, const char *optstring,
+ const struct option *longopts, int *longind,
+ int long_only, struct _getopt_data *d)
+{
+ int print_errors = d->opterr;
+ if (optstring[0] == ':')
+ print_errors = 0;
+
+ if (argc < 1)
+ return -1;
+
+ d->optarg = NULL;
+
+ if (d->optind == 0 || !d->__initialized)
+ {
+ if (d->optind == 0)
+ d->optind = 1; /* Don't scan ARGV[0], the program name. */
+ optstring = _getopt_initialize (argc, argv, optstring, d);
+ d->__initialized = 1;
+ }
+
+ /* Test whether ARGV[optind] points to a non-option argument.
+ Either it does not have option syntax, or there is an environment flag
+ from the shell indicating it is not an option. The later information
+ is only used when the used in the GNU libc. */
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
+# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0' \
+ || (d->optind < d->__nonoption_flags_len \
+ && __getopt_nonoption_flags[d->optind] == '1'))
+#else
+# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0')
+#endif
+
+ if (d->__nextchar == NULL || *d->__nextchar == '\0')
+ {
+ /* Advance to the next ARGV-element. */
+
+ /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
+ moved back by the user (who may also have changed the arguments). */
+ if (d->__last_nonopt > d->optind)
+ d->__last_nonopt = d->optind;
+ if (d->__first_nonopt > d->optind)
+ d->__first_nonopt = d->optind;
+
+ if (d->__ordering == PERMUTE)
+ {
+ /* If we have just processed some options following some non-options,
+ exchange them so that the options come first. */
+
+ if (d->__first_nonopt != d->__last_nonopt
+ && d->__last_nonopt != d->optind)
+ exchange ((char **) argv, d);
+ else if (d->__last_nonopt != d->optind)
+ d->__first_nonopt = d->optind;
+
+ /* Skip any additional non-options
+ and extend the range of non-options previously skipped. */
+
+ while (d->optind < argc && NONOPTION_P)
+ d->optind++;
+ d->__last_nonopt = d->optind;
+ }
+
+ /* The special ARGV-element `--' means premature end of options.
+ Skip it like a null option,
+ then exchange with previous non-options as if it were an option,
+ then skip everything else like a non-option. */
+
+ if (d->optind != argc && !strcmp (argv[d->optind], "--"))
+ {
+ d->optind++;
+
+ if (d->__first_nonopt != d->__last_nonopt
+ && d->__last_nonopt != d->optind)
+ exchange ((char **) argv, d);
+ else if (d->__first_nonopt == d->__last_nonopt)
+ d->__first_nonopt = d->optind;
+ d->__last_nonopt = argc;
+
+ d->optind = argc;
+ }
+
+ /* If we have done all the ARGV-elements, stop the scan
+ and back over any non-options that we skipped and permuted. */
+
+ if (d->optind == argc)
+ {
+ /* Set the next-arg-index to point at the non-options
+ that we previously skipped, so the caller will digest them. */
+ if (d->__first_nonopt != d->__last_nonopt)
+ d->optind = d->__first_nonopt;
+ return -1;
+ }
+
+ /* If we have come to a non-option and did not permute it,
+ either stop the scan or describe it to the caller and pass it by. */
+
+ if (NONOPTION_P)
+ {
+ if (d->__ordering == REQUIRE_ORDER)
+ return -1;
+ d->optarg = argv[d->optind++];
+ return 1;
+ }
+
+ /* We have found another option-ARGV-element.
+ Skip the initial punctuation. */
+
+ d->__nextchar = (argv[d->optind] + 1
+ + (longopts != NULL && argv[d->optind][1] == '-'));
+ }
+
+ /* Decode the current option-ARGV-element. */
+
+ /* Check whether the ARGV-element is a long option.
+
+ If long_only and the ARGV-element has the form "-f", where f is
+ a valid short option, don't consider it an abbreviated form of
+ a long option that starts with f. Otherwise there would be no
+ way to give the -f short option.
+
+ On the other hand, if there's a long option "fubar" and
+ the ARGV-element is "-fu", do consider that an abbreviation of
+ the long option, just like "--fu", and not "-f" with arg "u".
+
+ This distinction seems to be the most useful approach. */
+
+ if (longopts != NULL
+ && (argv[d->optind][1] == '-'
+ || (long_only && (argv[d->optind][2]
+ || !strchr (optstring, argv[d->optind][1])))))
+ {
+ char *nameend;
+ const struct option *p;
+ const struct option *pfound = NULL;
+ int exact = 0;
+ int ambig = 0;
+ int indfound = -1;
+ int option_index;
+
+ for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++)
+ /* Do nothing. */ ;
+
+ /* Test all long options for either exact match
+ or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name; p++, option_index++)
+ if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar))
+ {
+ if ((unsigned int) (nameend - d->__nextchar)
+ == (unsigned int) strlen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ }
+ else if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else if (long_only
+ || pfound->has_arg != p->has_arg
+ || pfound->flag != p->flag
+ || pfound->val != p->val)
+ /* Second or later nonexact match found. */
+ ambig = 1;
+ }
+
+ if (ambig && !exact)
+ {
+ if (print_errors)
+ {
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+
+ if (__asprintf (&buf, _("%s: option `%s' is ambiguous\n"),
+ argv[0], argv[d->optind]) >= 0)
+ {
+ _IO_flockfile (stderr);
+
+ int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+ ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s", buf);
+ else
+ fputs (buf, stderr);
+
+ ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+ _IO_funlockfile (stderr);
+
+ free (buf);
+ }
+#else
+ fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
+ argv[0], argv[d->optind]);
+#endif
+ }
+ d->__nextchar += strlen (d->__nextchar);
+ d->optind++;
+ d->optopt = 0;
+ return '?';
+ }
+
+ if (pfound != NULL)
+ {
+ option_index = indfound;
+ d->optind++;
+ if (*nameend)
+ {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ d->optarg = nameend + 1;
+ else
+ {
+ if (print_errors)
+ {
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+ int n;
+#endif
+
+ if (argv[d->optind - 1][1] == '-')
+ {
+ /* --option */
+#if defined _LIBC && defined USE_IN_LIBIO
+ n = __asprintf (&buf, _("\
+%s: option `--%s' doesn't allow an argument\n"),
+ argv[0], pfound->name);
+#else
+ fprintf (stderr, _("\
+%s: option `--%s' doesn't allow an argument\n"),
+ argv[0], pfound->name);
+#endif
+ }
+ else
+ {
+ /* +option or -option */
+#if defined _LIBC && defined USE_IN_LIBIO
+ n = __asprintf (&buf, _("\
+%s: option `%c%s' doesn't allow an argument\n"),
+ argv[0], argv[d->optind - 1][0],
+ pfound->name);
+#else
+ fprintf (stderr, _("\
+%s: option `%c%s' doesn't allow an argument\n"),
+ argv[0], argv[d->optind - 1][0],
+ pfound->name);
+#endif
+ }
+
+#if defined _LIBC && defined USE_IN_LIBIO
+ if (n >= 0)
+ {
+ _IO_flockfile (stderr);
+
+ int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+ ((_IO_FILE *) stderr)->_flags2
+ |= _IO_FLAGS2_NOTCANCEL;
+
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s", buf);
+ else
+ fputs (buf, stderr);
+
+ ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+ _IO_funlockfile (stderr);
+
+ free (buf);
+ }
+#endif
+ }
+
+ d->__nextchar += strlen (d->__nextchar);
+
+ d->optopt = pfound->val;
+ return '?';
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (d->optind < argc)
+ d->optarg = argv[d->optind++];
+ else
+ {
+ if (print_errors)
+ {
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+
+ if (__asprintf (&buf, _("\
+%s: option `%s' requires an argument\n"),
+ argv[0], argv[d->optind - 1]) >= 0)
+ {
+ _IO_flockfile (stderr);
+
+ int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+ ((_IO_FILE *) stderr)->_flags2
+ |= _IO_FLAGS2_NOTCANCEL;
+
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s", buf);
+ else
+ fputs (buf, stderr);
+
+ ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+ _IO_funlockfile (stderr);
+
+ free (buf);
+ }
+#else
+ fprintf (stderr,
+ _("%s: option `%s' requires an argument\n"),
+ argv[0], argv[d->optind - 1]);
+#endif
+ }
+ d->__nextchar += strlen (d->__nextchar);
+ d->optopt = pfound->val;
+ return optstring[0] == ':' ? ':' : '?';
+ }
+ }
+ d->__nextchar += strlen (d->__nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+ }
+
+ /* Can't find it as a long option. If this is not getopt_long_only,
+ or the option starts with '--' or is not a valid short
+ option, then it's an error.
+ Otherwise interpret it as a short option. */
+ if (!long_only || argv[d->optind][1] == '-'
+ || strchr (optstring, *d->__nextchar) == NULL)
+ {
+ if (print_errors)
+ {
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+ int n;
+#endif
+
+ if (argv[d->optind][1] == '-')
+ {
+ /* --option */
+#if defined _LIBC && defined USE_IN_LIBIO
+ n = __asprintf (&buf, _("%s: unrecognized option `--%s'\n"),
+ argv[0], d->__nextchar);
+#else
+ fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
+ argv[0], d->__nextchar);
+#endif
+ }
+ else
+ {
+ /* +option or -option */
+#if defined _LIBC && defined USE_IN_LIBIO
+ n = __asprintf (&buf, _("%s: unrecognized option `%c%s'\n"),
+ argv[0], argv[d->optind][0], d->__nextchar);
+#else
+ fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
+ argv[0], argv[d->optind][0], d->__nextchar);
+#endif
+ }
+
+#if defined _LIBC && defined USE_IN_LIBIO
+ if (n >= 0)
+ {
+ _IO_flockfile (stderr);
+
+ int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+ ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s", buf);
+ else
+ fputs (buf, stderr);
+
+ ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+ _IO_funlockfile (stderr);
+
+ free (buf);
+ }
+#endif
+ }
+ d->__nextchar = (char *) "";
+ d->optind++;
+ d->optopt = 0;
+ return '?';
+ }
+ }
+
+ /* Look at and handle the next short option-character. */
+
+ {
+ char c = *d->__nextchar++;
+ char *temp = strchr (optstring, c);
+
+ /* Increment `optind' when we start to process its last character. */
+ if (*d->__nextchar == '\0')
+ ++d->optind;
+
+ if (temp == NULL || c == ':')
+ {
+ if (print_errors)
+ {
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+ int n;
+#endif
+
+ if (d->__posixly_correct)
+ {
+ /* 1003.2 specifies the format of this message. */
+#if defined _LIBC && defined USE_IN_LIBIO
+ n = __asprintf (&buf, _("%s: illegal option -- %c\n"),
+ argv[0], c);
+#else
+ fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c);
+#endif
+ }
+ else
+ {
+#if defined _LIBC && defined USE_IN_LIBIO
+ n = __asprintf (&buf, _("%s: invalid option -- %c\n"),
+ argv[0], c);
+#else
+ fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c);
+#endif
+ }
+
+#if defined _LIBC && defined USE_IN_LIBIO
+ if (n >= 0)
+ {
+ _IO_flockfile (stderr);
+
+ int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+ ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s", buf);
+ else
+ fputs (buf, stderr);
+
+ ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+ _IO_funlockfile (stderr);
+
+ free (buf);
+ }
+#endif
+ }
+ d->optopt = c;
+ return '?';
+ }
+ /* Convenience. Treat POSIX -W foo same as long option --foo */
+ if (temp[0] == 'W' && temp[1] == ';')
+ {
+ char *nameend;
+ const struct option *p;
+ const struct option *pfound = NULL;
+ int exact = 0;
+ int ambig = 0;
+ int indfound = 0;
+ int option_index;
+
+ /* This is an option that requires an argument. */
+ if (*d->__nextchar != '\0')
+ {
+ d->optarg = d->__nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ d->optind++;
+ }
+ else if (d->optind == argc)
+ {
+ if (print_errors)
+ {
+ /* 1003.2 specifies the format of this message. */
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+
+ if (__asprintf (&buf,
+ _("%s: option requires an argument -- %c\n"),
+ argv[0], c) >= 0)
+ {
+ _IO_flockfile (stderr);
+
+ int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+ ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s", buf);
+ else
+ fputs (buf, stderr);
+
+ ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+ _IO_funlockfile (stderr);
+
+ free (buf);
+ }
+#else
+ fprintf (stderr, _("%s: option requires an argument -- %c\n"),
+ argv[0], c);
+#endif
+ }
+ d->optopt = c;
+ if (optstring[0] == ':')
+ c = ':';
+ else
+ c = '?';
+ return c;
+ }
+ else
+ /* We already incremented `d->optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ d->optarg = argv[d->optind++];
+
+ /* optarg is now the argument, see if it's in the
+ table of longopts. */
+
+ for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '=';
+ nameend++)
+ /* Do nothing. */ ;
+
+ /* Test all long options for either exact match
+ or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name; p++, option_index++)
+ if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar))
+ {
+ if ((unsigned int) (nameend - d->__nextchar) == strlen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ }
+ else if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else
+ /* Second or later nonexact match found. */
+ ambig = 1;
+ }
+ if (ambig && !exact)
+ {
+ if (print_errors)
+ {
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+
+ if (__asprintf (&buf, _("%s: option `-W %s' is ambiguous\n"),
+ argv[0], argv[d->optind]) >= 0)
+ {
+ _IO_flockfile (stderr);
+
+ int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+ ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s", buf);
+ else
+ fputs (buf, stderr);
+
+ ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+ _IO_funlockfile (stderr);
+
+ free (buf);
+ }
+#else
+ fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
+ argv[0], argv[d->optind]);
+#endif
+ }
+ d->__nextchar += strlen (d->__nextchar);
+ d->optind++;
+ return '?';
+ }
+ if (pfound != NULL)
+ {
+ option_index = indfound;
+ if (*nameend)
+ {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ d->optarg = nameend + 1;
+ else
+ {
+ if (print_errors)
+ {
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+
+ if (__asprintf (&buf, _("\
+%s: option `-W %s' doesn't allow an argument\n"),
+ argv[0], pfound->name) >= 0)
+ {
+ _IO_flockfile (stderr);
+
+ int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+ ((_IO_FILE *) stderr)->_flags2
+ |= _IO_FLAGS2_NOTCANCEL;
+
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s", buf);
+ else
+ fputs (buf, stderr);
+
+ ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+ _IO_funlockfile (stderr);
+
+ free (buf);
+ }
+#else
+ fprintf (stderr, _("\
+%s: option `-W %s' doesn't allow an argument\n"),
+ argv[0], pfound->name);
+#endif
+ }
+
+ d->__nextchar += strlen (d->__nextchar);
+ return '?';
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (d->optind < argc)
+ d->optarg = argv[d->optind++];
+ else
+ {
+ if (print_errors)
+ {
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+
+ if (__asprintf (&buf, _("\
+%s: option `%s' requires an argument\n"),
+ argv[0], argv[d->optind - 1]) >= 0)
+ {
+ _IO_flockfile (stderr);
+
+ int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+ ((_IO_FILE *) stderr)->_flags2
+ |= _IO_FLAGS2_NOTCANCEL;
+
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s", buf);
+ else
+ fputs (buf, stderr);
+
+ ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+ _IO_funlockfile (stderr);
+
+ free (buf);
+ }
+#else
+ fprintf (stderr,
+ _("%s: option `%s' requires an argument\n"),
+ argv[0], argv[d->optind - 1]);
+#endif
+ }
+ d->__nextchar += strlen (d->__nextchar);
+ return optstring[0] == ':' ? ':' : '?';
+ }
+ }
+ d->__nextchar += strlen (d->__nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+ }
+ d->__nextchar = NULL;
+ return 'W'; /* Let the application handle it. */
+ }
+ if (temp[1] == ':')
+ {
+ if (temp[2] == ':')
+ {
+ /* This is an option that accepts an argument optionally. */
+ if (*d->__nextchar != '\0')
+ {
+ d->optarg = d->__nextchar;
+ d->optind++;
+ }
+ else
+ d->optarg = NULL;
+ d->__nextchar = NULL;
+ }
+ else
+ {
+ /* This is an option that requires an argument. */
+ if (*d->__nextchar != '\0')
+ {
+ d->optarg = d->__nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ d->optind++;
+ }
+ else if (d->optind == argc)
+ {
+ if (print_errors)
+ {
+ /* 1003.2 specifies the format of this message. */
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+
+ if (__asprintf (&buf, _("\
+%s: option requires an argument -- %c\n"),
+ argv[0], c) >= 0)
+ {
+ _IO_flockfile (stderr);
+
+ int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+ ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s", buf);
+ else
+ fputs (buf, stderr);
+
+ ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+ _IO_funlockfile (stderr);
+
+ free (buf);
+ }
+#else
+ fprintf (stderr,
+ _("%s: option requires an argument -- %c\n"),
+ argv[0], c);
+#endif
+ }
+ d->optopt = c;
+ if (optstring[0] == ':')
+ c = ':';
+ else
+ c = '?';
+ }
+ else
+ /* We already incremented `optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ d->optarg = argv[d->optind++];
+ d->__nextchar = NULL;
+ }
+ }
+ return c;
+ }
+}
+
+int
+_getopt_internal (int argc, char *const *argv, const char *optstring,
+ const struct option *longopts, int *longind, int long_only)
+{
+ int result;
+
+ getopt_data.optind = optind;
+ getopt_data.opterr = opterr;
+
+ result = _getopt_internal_r (argc, argv, optstring, longopts,
+ longind, long_only, &getopt_data);
+
+ optind = getopt_data.optind;
+ optarg = getopt_data.optarg;
+ optopt = getopt_data.optopt;
+
+ return result;
+}
+
+int
+getopt (int argc, char *const *argv, const char *optstring)
+{
+ return _getopt_internal (argc, argv, optstring,
+ (const struct option *) 0,
+ (int *) 0,
+ 0);
+}
+
+#endif /* Not ELIDE_CODE. */
+
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+ the above definition of `getopt'. */
+
+int
+main (int argc, char **argv)
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+
+ c = getopt (argc, argv, "abc:d:0123456789");
+ if (c == -1)
+ break;
+
+ switch (c)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
diff --git a/contrib/diff/lib/getopt.h b/contrib/diff/lib/getopt.h
new file mode 100644
index 0000000..c61768c
--- /dev/null
+++ b/contrib/diff/lib/getopt.h
@@ -0,0 +1,176 @@
+/* Declarations for getopt.
+ Copyright (C) 1989-1994,1996-1999,2001,2003,2004
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _GETOPT_H
+
+#ifndef __need_getopt
+# define _GETOPT_H 1
+#endif
+
+/* If __GNU_LIBRARY__ is not already defined, either we are being used
+ standalone, or this is the first header included in the source file.
+ If we are being used with glibc, we need to include <features.h>, but
+ that does not exist if we are standalone. So: if __GNU_LIBRARY__ is
+ not defined, include <ctype.h>, which will pull in <features.h> for us
+ if it's from glibc. (Why ctype.h? It's guaranteed to exist and it
+ doesn't flood the namespace with stuff the way some other headers do.) */
+#if !defined __GNU_LIBRARY__
+# include <ctype.h>
+#endif
+
+#ifndef __THROW
+# ifndef __GNUC_PREREQ
+# define __GNUC_PREREQ(maj, min) (0)
+# endif
+# if defined __cplusplus && __GNUC_PREREQ (2,8)
+# define __THROW throw ()
+# else
+# define __THROW
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns -1, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+ for unrecognized options. */
+
+extern int opterr;
+
+/* Set to an option character which was unrecognized. */
+
+extern int optopt;
+
+#ifndef __need_getopt
+/* Describe the long-named options requested by the application.
+ The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+ of `struct option' terminated by an element containing a name which is
+ zero.
+
+ The field `has_arg' is:
+ no_argument (or 0) if the option does not take an argument,
+ required_argument (or 1) if the option requires an argument,
+ optional_argument (or 2) if the option takes an optional argument.
+
+ If the field `flag' is not NULL, it points to a variable that is set
+ to the value given in the field `val' when the option is found, but
+ left unchanged if the option is not found.
+
+ To have a long-named option do something other than set an `int' to
+ a compiled-in constant, such as set a value from `optarg', set the
+ option's `flag' field to zero and its `val' field to a nonzero
+ value (the equivalent single-letter option character, if there is
+ one). For long options that have a zero `flag' field, `getopt'
+ returns the contents of the `val' field. */
+
+struct option
+{
+ const char *name;
+ /* has_arg can't be an enum because some compilers complain about
+ type mismatches in all the code that assumes it is an int. */
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'. */
+
+# define no_argument 0
+# define required_argument 1
+# define optional_argument 2
+#endif /* need getopt */
+
+
+/* Get definitions and prototypes for functions to process the
+ arguments in ARGV (ARGC of them, minus the program name) for
+ options given in OPTS.
+
+ Return the option character from OPTS just read. Return -1 when
+ there are no more options. For unrecognized options, or options
+ missing arguments, `optopt' is set to the option letter, and '?' is
+ returned.
+
+ The OPTS string is a list of characters which are recognized option
+ letters, optionally followed by colons, specifying that that letter
+ takes an argument, to be placed in `optarg'.
+
+ If a letter in OPTS is followed by two colons, its argument is
+ optional. This behavior is specific to the GNU `getopt'.
+
+ The argument `--' causes premature termination of argument
+ scanning, explicitly telling `getopt' that there are no more
+ options.
+
+ If OPTS begins with `--', then non-option arguments are treated as
+ arguments to the option '\0'. This behavior is specific to the GNU
+ `getopt'. */
+
+#ifdef __GNU_LIBRARY__
+/* Many other libraries have conflicting prototypes for getopt, with
+ differences in the consts, in stdlib.h. To avoid compilation
+ errors, only prototype getopt for the GNU C library. */
+extern int getopt (int ___argc, char *const *___argv, const char *__shortopts)
+ __THROW;
+#else /* not __GNU_LIBRARY__ */
+extern int getopt ();
+#endif /* __GNU_LIBRARY__ */
+
+#ifndef __need_getopt
+extern int getopt_long (int ___argc, char *const *___argv,
+ const char *__shortopts,
+ const struct option *__longopts, int *__longind)
+ __THROW;
+extern int getopt_long_only (int ___argc, char *const *___argv,
+ const char *__shortopts,
+ const struct option *__longopts, int *__longind)
+ __THROW;
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Make sure we later can get all the definitions and declarations. */
+#undef __need_getopt
+
+#endif /* getopt.h */
diff --git a/contrib/diff/lib/getopt1.c b/contrib/diff/lib/getopt1.c
new file mode 100644
index 0000000..7671eba
--- /dev/null
+++ b/contrib/diff/lib/getopt1.c
@@ -0,0 +1,191 @@
+/* getopt_long and getopt_long_only entry points for GNU getopt.
+ Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98,2004
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef _LIBC
+# include <getopt.h>
+#else
+# include "getopt.h"
+#endif
+#include "getopt_int.h"
+
+#include <stdio.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 GETOPT_INTERFACE_VERSION 2
+#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
+#include <gnu-versions.h>
+#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
+#define ELIDE_CODE
+#endif
+#endif
+
+#ifndef ELIDE_CODE
+
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+#include <stdlib.h>
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+int
+getopt_long (int argc, char *const *argv, const char *options,
+ const struct option *long_options, int *opt_index)
+{
+ return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
+}
+
+int
+_getopt_long_r (int argc, char *const *argv, const char *options,
+ const struct option *long_options, int *opt_index,
+ struct _getopt_data *d)
+{
+ return _getopt_internal_r (argc, argv, options, long_options, opt_index,
+ 0, d);
+}
+
+/* Like getopt_long, but '-' as well as '--' can indicate a long option.
+ If an option that starts with '-' (not '--') doesn't match a long option,
+ but does match a short option, it is parsed as a short option
+ instead. */
+
+int
+getopt_long_only (int argc, char *const *argv, const char *options,
+ const struct option *long_options, int *opt_index)
+{
+ return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
+}
+
+int
+_getopt_long_only_r (int argc, char *const *argv, const char *options,
+ const struct option *long_options, int *opt_index,
+ struct _getopt_data *d)
+{
+ return _getopt_internal_r (argc, argv, options, long_options, opt_index,
+ 1, d);
+}
+
+#endif /* Not ELIDE_CODE. */
+
+#ifdef TEST
+
+#include <stdio.h>
+
+int
+main (int argc, char **argv)
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+ int option_index = 0;
+ static struct option long_options[] =
+ {
+ {"add", 1, 0, 0},
+ {"append", 0, 0, 0},
+ {"delete", 1, 0, 0},
+ {"verbose", 0, 0, 0},
+ {"create", 0, 0, 0},
+ {"file", 1, 0, 0},
+ {0, 0, 0, 0}
+ };
+
+ c = getopt_long (argc, argv, "abc:d:0123456789",
+ long_options, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c)
+ {
+ case 0:
+ printf ("option %s", long_options[option_index].name);
+ if (optarg)
+ printf (" with arg %s", optarg);
+ printf ("\n");
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case 'd':
+ printf ("option d with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
diff --git a/contrib/diff/lib/getopt_int.h b/contrib/diff/lib/getopt_int.h
new file mode 100644
index 0000000..0c5edde
--- /dev/null
+++ b/contrib/diff/lib/getopt_int.h
@@ -0,0 +1,129 @@
+/* Internal declarations for getopt.
+ Copyright (C) 1989-1994,1996-1999,2001,2003,2004
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _GETOPT_INT_H
+#define _GETOPT_INT_H 1
+
+extern int _getopt_internal (int ___argc, char *const *___argv,
+ const char *__shortopts,
+ const struct option *__longopts, int *__longind,
+ int __long_only);
+
+
+/* Reentrant versions which can handle parsing multiple argument
+ vectors at the same time. */
+
+/* Data type for reentrant functions. */
+struct _getopt_data
+{
+ /* These have exactly the same meaning as the corresponding global
+ variables, except that they are used for the reentrant
+ versions of getopt. */
+ int optind;
+ int opterr;
+ int optopt;
+ char *optarg;
+
+ /* Internal members. */
+
+ /* True if the internal members have been initialized. */
+ int __initialized;
+
+ /* The next char to be scanned in the option-element
+ in which the last option character we returned was found.
+ This allows us to pick up the scan where we left off.
+
+ If this is zero, or a null string, it means resume the scan
+ by advancing to the next ARGV-element. */
+ char *__nextchar;
+
+ /* Describe how to deal with options that follow non-option ARGV-elements.
+
+ If the caller did not specify anything,
+ the default is REQUIRE_ORDER if the environment variable
+ POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+ REQUIRE_ORDER means don't recognize them as options;
+ stop option processing when the first non-option is seen.
+ This is what Unix does.
+ This mode of operation is selected by either setting the environment
+ variable POSIXLY_CORRECT, or using `+' as the first character
+ of the list of option characters.
+
+ PERMUTE is the default. We permute the contents of ARGV as we
+ scan, so that eventually all the non-options are at the end.
+ This allows options to be given in any order, even with programs
+ that were not written to expect this.
+
+ RETURN_IN_ORDER is an option available to programs that were
+ written to expect options and other ARGV-elements in any order
+ and that care about the ordering of the two. We describe each
+ non-option ARGV-element as if it were the argument of an option
+ with character code 1. Using `-' as the first character of the
+ list of option characters selects this mode of operation.
+
+ The special argument `--' forces an end of option-scanning regardless
+ of the value of `ordering'. In the case of RETURN_IN_ORDER, only
+ `--' can cause `getopt' to return -1 with `optind' != ARGC. */
+
+ enum
+ {
+ REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+ } __ordering;
+
+ /* If the POSIXLY_CORRECT environment variable is set. */
+ int __posixly_correct;
+
+
+ /* Handle permutation of arguments. */
+
+ /* Describe the part of ARGV that contains non-options that have
+ been skipped. `first_nonopt' is the index in ARGV of the first
+ of them; `last_nonopt' is the index after the last of them. */
+
+ int __first_nonopt;
+ int __last_nonopt;
+
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
+ int __nonoption_flags_max_len;
+ int __nonoption_flags_len;
+# endif
+};
+
+/* The initializer is necessary to set OPTIND and OPTERR to their
+ default values and to clear the initialization flag. */
+#define _GETOPT_DATA_INITIALIZER { 1, 1 }
+
+extern int _getopt_internal_r (int ___argc, char *const *___argv,
+ const char *__shortopts,
+ const struct option *__longopts, int *__longind,
+ int __long_only, struct _getopt_data *__data);
+
+extern int _getopt_long_r (int ___argc, char *const *___argv,
+ const char *__shortopts,
+ const struct option *__longopts, int *__longind,
+ struct _getopt_data *__data);
+
+extern int _getopt_long_only_r (int ___argc, char *const *___argv,
+ const char *__shortopts,
+ const struct option *__longopts,
+ int *__longind,
+ struct _getopt_data *__data);
+
+#endif /* getopt_int.h */
diff --git a/contrib/diff/lib/gettext.h b/contrib/diff/lib/gettext.h
new file mode 100644
index 0000000..835732e
--- /dev/null
+++ b/contrib/diff/lib/gettext.h
@@ -0,0 +1,68 @@
+/* Convenience header for conditional use of GNU <libintl.h>.
+ Copyright (C) 1995-1998, 2000-2002 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _LIBGETTEXT_H
+#define _LIBGETTEXT_H 1
+
+/* NLS can be disabled through the configure --disable-nls option. */
+#if ENABLE_NLS
+
+/* Get declarations of GNU message catalog functions. */
+# include <libintl.h>
+
+#else
+
+/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
+ chokes if dcgettext is defined as a macro. So include it now, to make
+ later inclusions of <locale.h> a NOP. We don't include <libintl.h>
+ as well because people using "gettext.h" will not include <libintl.h>,
+ and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
+ is OK. */
+#if defined(__sun)
+# include <locale.h>
+#endif
+
+/* Disabled NLS.
+ The casts to 'const char *' serve the purpose of producing warnings
+ for invalid uses of the value returned from these functions.
+ On pre-ANSI systems without 'const', the config.h file is supposed to
+ contain "#define const". */
+# define gettext(Msgid) ((const char *) (Msgid))
+# define dgettext(Domainname, Msgid) ((const char *) (Msgid))
+# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid))
+# define ngettext(Msgid1, Msgid2, N) \
+ ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define dngettext(Domainname, Msgid1, Msgid2, N) \
+ ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
+ ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define textdomain(Domainname) ((const char *) (Domainname))
+# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
+# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset))
+
+#endif
+
+/* A pseudo function call that serves as a marker for the automated
+ extraction of messages, but does not call gettext(). The run-time
+ translation is done at a different place in the code.
+ The argument, String, should be a literal string. Concatenated strings
+ and other string expressions won't work.
+ The macro's expansion is not parenthesized, so that it is suitable as
+ initializer for static 'char[]' or 'const char[]' variables. */
+#define gettext_noop(String) String
+
+#endif /* _LIBGETTEXT_H */
diff --git a/contrib/diff/lib/gettimeofday.c b/contrib/diff/lib/gettimeofday.c
new file mode 100644
index 0000000..1ebe4d0
--- /dev/null
+++ b/contrib/diff/lib/gettimeofday.c
@@ -0,0 +1,121 @@
+/* Work around the bug in some systems whereby gettimeofday clobbers the
+ static buffer that localtime uses for it's return value. The gettimeofday
+ function from Mac OS X 10.0.4, i.e. Darwin 1.3.7 has this problem.
+ The tzset replacement is necessary for at least Solaris 2.5, 2.5.1, and 2.6.
+ Copyright (C) 2001, 2002, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* written by Jim Meyering */
+
+#include <config.h>
+
+/* Disable the definitions of these functions (from config.h)
+ so we can use the library versions here. */
+#undef gettimeofday
+#undef gmtime
+#undef localtime
+#undef tzset
+
+#include <sys/types.h>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+
+#include <stdlib.h>
+
+static struct tm *localtime_buffer_addr;
+
+/* This is a wrapper for localtime. It is used only on systems for which
+ gettimeofday clobbers the static buffer used for localtime's result.
+
+ On the first call, record the address of the static buffer that
+ localtime uses for its result. */
+
+struct tm *
+rpl_localtime (const time_t *timep)
+{
+ struct tm *tm = localtime (timep);
+
+ if (! localtime_buffer_addr)
+ localtime_buffer_addr = tm;
+
+ return tm;
+}
+
+/* Same as above, since gmtime and localtime use the same buffer. */
+struct tm *
+rpl_gmtime (const time_t *timep)
+{
+ struct tm *tm = gmtime (timep);
+
+ if (! localtime_buffer_addr)
+ localtime_buffer_addr = tm;
+
+ return tm;
+}
+
+/* This is a wrapper for gettimeofday. It is used only on systems for which
+ gettimeofday clobbers the static buffer used for localtime's result.
+
+ Save and restore the contents of the buffer used for localtime's result
+ around the call to gettimeofday. */
+
+int
+rpl_gettimeofday (struct timeval *tv, struct timezone *tz)
+{
+ struct tm save;
+ int result;
+
+ if (! localtime_buffer_addr)
+ {
+ time_t t = 0;
+ localtime_buffer_addr = localtime (&t);
+ }
+
+ save = *localtime_buffer_addr;
+ result = gettimeofday (tv, tz);
+ *localtime_buffer_addr = save;
+
+ return result;
+}
+
+/* This is a wrapper for tzset. It is used only on systems for which
+ tzset may clobber the static buffer used for localtime's result.
+ Save and restore the contents of the buffer used for localtime's
+ result around the call to tzset. */
+void
+rpl_tzset (void)
+{
+ struct tm save;
+
+ if (! localtime_buffer_addr)
+ {
+ time_t t = 0;
+ localtime_buffer_addr = localtime (&t);
+ }
+
+ save = *localtime_buffer_addr;
+ tzset ();
+ *localtime_buffer_addr = save;
+}
diff --git a/contrib/diff/lib/gnulib.mk b/contrib/diff/lib/gnulib.mk
new file mode 100644
index 0000000..6e7f05a
--- /dev/null
+++ b/contrib/diff/lib/gnulib.mk
@@ -0,0 +1,90 @@
+# This file is generated automatically by "bootstrap".
+BUILT_SOURCES += $(ALLOCA_H)
+EXTRA_DIST += alloca_.h
+
+# We need the following in order to create an <alloca.h> when the system
+# doesn't have one that works with the given compiler.
+all-local $(lib_OBJECTS): $(ALLOCA_H)
+alloca.h: alloca_.h
+ cp $(srcdir)/alloca_.h $@-t
+ mv $@-t $@
+MOSTLYCLEANFILES += alloca.h alloca.h-t
+
+lib_SOURCES += c-stack.h c-stack.c
+
+lib_SOURCES += dirname.h dirname.c basename.c stripslash.c
+
+
+lib_SOURCES += exclude.h exclude.c
+
+lib_SOURCES += exit.h
+
+lib_SOURCES += exitfail.h exitfail.c
+
+
+lib_SOURCES += file-type.h file-type.c
+
+BUILT_SOURCES += $(FNMATCH_H)
+EXTRA_DIST += fnmatch_.h fnmatch_loop.c
+
+# We need the following in order to create an <fnmatch.h> when the system
+# doesn't have one that supports the required API.
+all-local $(lib_OBJECTS): $(FNMATCH_H)
+fnmatch.h: fnmatch_.h
+ cp $(srcdir)/fnmatch_.h $@-t
+ mv $@-t $@
+MOSTLYCLEANFILES += fnmatch.h fnmatch.h-t
+
+
+lib_SOURCES += getopt.h getopt.c getopt1.c getopt_int.h
+
+lib_SOURCES += gettext.h
+
+
+lib_SOURCES += hard-locale.h hard-locale.c
+
+EXTRA_DIST += inttostr.c
+lib_SOURCES += imaxtostr.c inttostr.h offtostr.c umaxtostr.c
+
+
+
+lib_SOURCES += posixver.h posixver.c
+
+
+lib_SOURCES += regex.h
+
+
+BUILT_SOURCES += $(STDBOOL_H)
+EXTRA_DIST += stdbool_.h
+
+# We need the following in order to create an <stdbool.h> when the system
+# doesn't have one that works.
+all-local $(lib_OBJECTS): $(STDBOOL_H)
+stdbool.h: stdbool_.h
+ sed -e 's/@''HAVE__BOOL''@/$(HAVE__BOOL)/g' < $(srcdir)/stdbool_.h > $@-t
+ mv $@-t $@
+MOSTLYCLEANFILES += stdbool.h stdbool.h-t
+
+lib_SOURCES += strcase.h
+
+lib_SOURCES += strftime.c
+
+
+
+
+
+
+
+lib_SOURCES += time_r.h
+
+
+lib_SOURCES += unlocked-io.h
+
+lib_SOURCES += version-etc.h version-etc.c
+
+lib_SOURCES += xalloc.h xmalloc.c xstrdup.c
+
+lib_SOURCES += xstrtol.h xstrtol.c xstrtoul.c
+
+lib_SOURCES += xstrtoumax.c
+
diff --git a/contrib/diff/lib/hard-locale.c b/contrib/diff/lib/hard-locale.c
new file mode 100644
index 0000000..8c0ee8c
--- /dev/null
+++ b/contrib/diff/lib/hard-locale.c
@@ -0,0 +1,74 @@
+/* hard-locale.c -- Determine whether a locale is hard.
+
+ Copyright (C) 1997, 1998, 1999, 2002, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "hard-locale.h"
+
+#if HAVE_LOCALE_H
+# include <locale.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+/* Return nonzero if the current CATEGORY locale is hard, i.e. if you
+ can't get away with assuming traditional C or POSIX behavior. */
+int
+hard_locale (int category)
+{
+#if ! HAVE_SETLOCALE
+ return 0;
+#else
+
+ int hard = 1;
+ char const *p = setlocale (category, 0);
+
+ if (p)
+ {
+# if defined __GLIBC__ && 2 <= __GLIBC__
+ if (strcmp (p, "C") == 0 || strcmp (p, "POSIX") == 0)
+ hard = 0;
+# else
+ char *locale = malloc (strlen (p) + 1);
+ if (locale)
+ {
+ strcpy (locale, p);
+
+ /* Temporarily set the locale to the "C" and "POSIX" locales
+ to find their names, so that we can determine whether one
+ or the other is the caller's locale. */
+ if (((p = setlocale (category, "C"))
+ && strcmp (p, locale) == 0)
+ || ((p = setlocale (category, "POSIX"))
+ && strcmp (p, locale) == 0))
+ hard = 0;
+
+ /* Restore the caller's locale. */
+ setlocale (category, locale);
+ free (locale);
+ }
+# endif
+ }
+
+ return hard;
+
+#endif
+}
diff --git a/contrib/diff/lib/hard-locale.h b/contrib/diff/lib/hard-locale.h
new file mode 100644
index 0000000..ddc15d0
--- /dev/null
+++ b/contrib/diff/lib/hard-locale.h
@@ -0,0 +1,24 @@
+/* Determine whether a locale is hard.
+
+ Copyright (C) 1999, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef HARD_LOCALE_H_
+# define HARD_LOCALE_H_ 1
+
+int hard_locale (int);
+
+#endif /* HARD_LOCALE_H_ */
diff --git a/contrib/diff/lib/imaxtostr.c b/contrib/diff/lib/imaxtostr.c
new file mode 100644
index 0000000..5e87ad5
--- /dev/null
+++ b/contrib/diff/lib/imaxtostr.c
@@ -0,0 +1,3 @@
+#define inttostr imaxtostr
+#define inttype intmax_t
+#include "inttostr.c"
diff --git a/contrib/diff/lib/inttostr.c b/contrib/diff/lib/inttostr.c
new file mode 100644
index 0000000..78a48af
--- /dev/null
+++ b/contrib/diff/lib/inttostr.c
@@ -0,0 +1,49 @@
+/* inttostr.c -- convert integers to printable strings
+
+ Copyright (C) 2001 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Paul Eggert */
+
+#include "inttostr.h"
+
+/* Convert I to a printable string in BUF, which must be at least
+ INT_BUFSIZE_BOUND (INTTYPE) bytes long. Return the address of the
+ printable string, which need not start at BUF. */
+
+char *
+inttostr (inttype i, char *buf)
+{
+ char *p = buf + INT_STRLEN_BOUND (inttype);
+ *p = 0;
+
+ if (i < 0)
+ {
+ do
+ *--p = '0' - i % 10;
+ while ((i /= 10) != 0);
+
+ *--p = '-';
+ }
+ else
+ {
+ do
+ *--p = '0' + i % 10;
+ while ((i /= 10) != 0);
+ }
+
+ return p;
+}
diff --git a/contrib/diff/lib/inttostr.h b/contrib/diff/lib/inttostr.h
new file mode 100644
index 0000000..6f2416b
--- /dev/null
+++ b/contrib/diff/lib/inttostr.h
@@ -0,0 +1,47 @@
+/* inttostr.h -- convert integers to printable strings
+
+ Copyright (C) 2001, 2002, 2003, 2004 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Paul Eggert */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+
+#include <limits.h>
+
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+/* Upper bound on the string length of an integer converted to string.
+ 302 / 1000 is ceil (log10 (2.0)). Subtract 1 for the sign bit;
+ add 1 for integer division truncation; add 1 more for a minus sign. */
+#define INT_STRLEN_BOUND(t) ((sizeof (t) * CHAR_BIT - 1) * 302 / 1000 + 2)
+
+#define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1)
+
+char *offtostr (off_t, char *);
+char *imaxtostr (intmax_t, char *);
+char *umaxtostr (uintmax_t, char *);
diff --git a/contrib/diff/lib/malloc.c b/contrib/diff/lib/malloc.c
new file mode 100644
index 0000000..a43d169
--- /dev/null
+++ b/contrib/diff/lib/malloc.c
@@ -0,0 +1,36 @@
+/* Work around bug on some systems where malloc (0) fails.
+ Copyright (C) 1997, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* written by Jim Meyering */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+#undef malloc
+
+#include <stdlib.h>
+
+/* Allocate an N-byte block of memory from the heap.
+ If N is zero, allocate a 1-byte block. */
+
+void *
+rpl_malloc (size_t n)
+{
+ if (n == 0)
+ n = 1;
+ return malloc (n);
+}
diff --git a/contrib/diff/lib/mkstemp.c b/contrib/diff/lib/mkstemp.c
new file mode 100644
index 0000000..f6312b6
--- /dev/null
+++ b/contrib/diff/lib/mkstemp.c
@@ -0,0 +1,42 @@
+/* Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc.
+ This file is derived from the one in the GNU C Library.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <config.h>
+
+/* Disable the definition of mkstemp to rpl_mkstemp (from config.h) in this
+ file. Otherwise, we'd get conflicting prototypes for rpl_mkstemp on
+ most systems. */
+#undef mkstemp
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef __GT_FILE
+# define __GT_FILE 0
+#endif
+
+int __gen_tempname ();
+
+/* Generate a unique temporary file name from TEMPLATE.
+ The last six characters of TEMPLATE must be "XXXXXX";
+ they are replaced with a string that makes the filename unique.
+ Then open the file and return a fd. */
+int
+rpl_mkstemp (char *template)
+{
+ return __gen_tempname (template, __GT_FILE);
+}
diff --git a/contrib/diff/lib/offtostr.c b/contrib/diff/lib/offtostr.c
new file mode 100644
index 0000000..45196e2
--- /dev/null
+++ b/contrib/diff/lib/offtostr.c
@@ -0,0 +1,3 @@
+#define inttostr offtostr
+#define inttype off_t
+#include "inttostr.c"
diff --git a/contrib/diff/lib/posixver.c b/contrib/diff/lib/posixver.c
new file mode 100644
index 0000000..754d7ac
--- /dev/null
+++ b/contrib/diff/lib/posixver.c
@@ -0,0 +1,59 @@
+/* Which POSIX version to conform to, for utilities.
+
+ Copyright (C) 2002, 2003, 2004 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Paul Eggert. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "posixver.h"
+
+#include <limits.h>
+#include <stdlib.h>
+
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifndef _POSIX2_VERSION
+# define _POSIX2_VERSION 0
+#endif
+
+#ifndef DEFAULT_POSIX2_VERSION
+# define DEFAULT_POSIX2_VERSION _POSIX2_VERSION
+#endif
+
+/* The POSIX version that utilities should conform to. The default is
+ specified by the system. */
+
+int
+posix2_version (void)
+{
+ long int v = DEFAULT_POSIX2_VERSION;
+ char const *s = getenv ("_POSIX2_VERSION");
+
+ if (s && *s)
+ {
+ char *e;
+ long int i = strtol (s, &e, 10);
+ if (! *e)
+ v = i;
+ }
+
+ return v < INT_MIN ? INT_MIN : v < INT_MAX ? v : INT_MAX;
+}
diff --git a/contrib/diff/lib/posixver.h b/contrib/diff/lib/posixver.h
new file mode 100644
index 0000000..b64f6a2
--- /dev/null
+++ b/contrib/diff/lib/posixver.h
@@ -0,0 +1 @@
+int posix2_version (void);
diff --git a/contrib/diff/lib/prepargs.c b/contrib/diff/lib/prepargs.c
new file mode 100644
index 0000000..f5735ac
--- /dev/null
+++ b/contrib/diff/lib/prepargs.c
@@ -0,0 +1,93 @@
+/* Parse arguments from a string and prepend them to an argv.
+
+ Copyright (C) 1999, 2000, 2001, 2002 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., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/* Written by Paul Eggert <eggert@twinsun.com>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include "prepargs.h"
+#include <string.h>
+#include <sys/types.h>
+#include <xalloc.h>
+
+#include <ctype.h>
+
+/* IN_CTYPE_DOMAIN (C) is nonzero if the unsigned char C can safely be given
+ as an argument to <ctype.h> macros like "isspace". */
+#ifdef STDC_HEADERS
+# define IN_CTYPE_DOMAIN(c) 1
+#else
+# define IN_CTYPE_DOMAIN(c) ((c) <= 0177)
+#endif
+
+#define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c))
+
+/* Find the white-space-separated options specified by OPTIONS, and
+ using BUF to store copies of these options, set ARGV[0], ARGV[1],
+ etc. to the option copies. Return the number N of options found.
+ Do not set ARGV[N]. If ARGV is zero, do not store ARGV[0] etc.
+ Backslash can be used to escape whitespace (and backslashes). */
+static int
+prepend_args (char const *options, char *buf, char **argv)
+{
+ char const *o = options;
+ char *b = buf;
+ int n = 0;
+
+ for (;;)
+ {
+ while (ISSPACE ((unsigned char) *o))
+ o++;
+ if (!*o)
+ return n;
+ if (argv)
+ argv[n] = b;
+ n++;
+
+ do
+ if ((*b++ = *o++) == '\\' && *o)
+ b[-1] = *o++;
+ while (*o && ! ISSPACE ((unsigned char) *o));
+
+ *b++ = '\0';
+ }
+}
+
+/* Prepend the whitespace-separated options in OPTIONS to the argument
+ vector of a main program with argument count *PARGC and argument
+ vector *PARGV. */
+void
+prepend_default_options (char const *options, int *pargc, char ***pargv)
+{
+ if (options)
+ {
+ char *buf = xmalloc (strlen (options) + 1);
+ int prepended = prepend_args (options, buf, (char **) 0);
+ int argc = *pargc;
+ char * const *argv = *pargv;
+ char **pp = (char **) xmalloc ((prepended + argc + 1) * sizeof *pp);
+ *pargc = prepended + argc;
+ *pargv = pp;
+ *pp++ = *argv++;
+ pp += prepend_args (options, buf, pp);
+ while ((*pp++ = *argv++))
+ continue;
+ }
+}
diff --git a/contrib/diff/lib/prepargs.h b/contrib/diff/lib/prepargs.h
new file mode 100644
index 0000000..ce93ea8
--- /dev/null
+++ b/contrib/diff/lib/prepargs.h
@@ -0,0 +1,3 @@
+/* Parse arguments from a string and prepend them to an argv. */
+
+void prepend_default_options (char const *, int *, char ***);
diff --git a/contrib/diff/lib/quotesys.c b/contrib/diff/lib/quotesys.c
new file mode 100644
index 0000000..528f382
--- /dev/null
+++ b/contrib/diff/lib/quotesys.c
@@ -0,0 +1,125 @@
+/* Shell command argument quoting.
+ Copyright (C) 1994, 1995, 1997 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; see the file COPYING.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Paul Eggert <eggert@twinsun.com> */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <quotesys.h>
+
+/* Place into QUOTED a quoted version of ARG suitable for `system'.
+ Return the length of the resulting string (which is not null-terminated).
+ If QUOTED is null, return the length without any side effects. */
+
+size_t
+quote_system_arg (quoted, arg)
+ char *quoted;
+ char const *arg;
+{
+ char const *a;
+ size_t len = 0;
+
+ /* Scan ARG, copying it to QUOTED if QUOTED is not null,
+ looking for shell metacharacters. */
+
+ for (a = arg; ; a++)
+ {
+ char c = *a;
+ switch (c)
+ {
+ case 0:
+ /* ARG has no shell metacharacters. */
+ return len;
+
+ case '=':
+ if (*arg == '-')
+ break;
+ /* Fall through. */
+ case '\t': case '\n': case ' ':
+ case '!': case '"': case '#': case '$': case '%': case '&': case '\'':
+ case '(': case ')': case '*': case ';':
+ case '<': case '>': case '?': case '[': case '\\':
+ case '^': case '`': case '|': case '~':
+ {
+ /* ARG has a shell metacharacter.
+ Start over, quoting it this time. */
+
+ len = 0;
+ c = *arg++;
+
+ /* If ARG is an option, quote just its argument.
+ This is not necessary, but it looks nicer. */
+ if (c == '-' && arg < a)
+ {
+ c = *arg++;
+
+ if (quoted)
+ {
+ quoted[len] = '-';
+ quoted[len + 1] = c;
+ }
+ len += 2;
+
+ if (c == '-')
+ while (arg < a)
+ {
+ c = *arg++;
+ if (quoted)
+ quoted[len] = c;
+ len++;
+ if (c == '=')
+ break;
+ }
+ c = *arg++;
+ }
+
+ if (quoted)
+ quoted[len] = '\'';
+ len++;
+
+ for (; c; c = *arg++)
+ {
+ if (c == '\'')
+ {
+ if (quoted)
+ {
+ quoted[len] = '\'';
+ quoted[len + 1] = '\\';
+ quoted[len + 2] = '\'';
+ }
+ len += 3;
+ }
+ if (quoted)
+ quoted[len] = c;
+ len++;
+ }
+
+ if (quoted)
+ quoted[len] = '\'';
+ return len + 1;
+ }
+ }
+
+ if (quoted)
+ quoted[len] = c;
+ len++;
+ }
+}
diff --git a/contrib/diff/lib/quotesys.h b/contrib/diff/lib/quotesys.h
new file mode 100644
index 0000000..0d0d825
--- /dev/null
+++ b/contrib/diff/lib/quotesys.h
@@ -0,0 +1,9 @@
+/* quotesys.h -- declarations for quoting system arguments */
+
+#if defined __STDC__ || __GNUC__
+# define __QUOTESYS_P(args) args
+#else
+# define __QUOTESYS_P(args) ()
+#endif
+
+size_t quote_system_arg __QUOTESYS_P ((char *, char const *));
diff --git a/contrib/diff/lib/realloc.c b/contrib/diff/lib/realloc.c
new file mode 100644
index 0000000..ccbf991
--- /dev/null
+++ b/contrib/diff/lib/realloc.c
@@ -0,0 +1,39 @@
+/* Work around bug on some systems where realloc (NULL, 0) fails.
+ Copyright (C) 1997, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* written by Jim Meyering */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+#undef realloc
+
+#include <stdlib.h>
+
+/* Change the size of an allocated block of memory P to N bytes,
+ with error checking. If N is zero, change it to 1. If P is NULL,
+ use malloc. */
+
+void *
+rpl_realloc (void *p, size_t n)
+{
+ if (n == 0)
+ n = 1;
+ if (p == 0)
+ return malloc (n);
+ return realloc (p, n);
+}
diff --git a/contrib/diff/lib/regex.c b/contrib/diff/lib/regex.c
new file mode 100644
index 0000000..ac70b90
--- /dev/null
+++ b/contrib/diff/lib/regex.c
@@ -0,0 +1,8298 @@
+/* Extended regular expression matching and search library,
+ version 0.12.
+ (Implements POSIX draft P1003.2/D11.2, except for some of the
+ internationalization features.)
+
+ Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+ 2002, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* AIX requires this to be the first thing in the file. */
+#if defined _AIX && !defined REGEX_MALLOC
+ #pragma alloca
+#endif
+
+#undef _GNU_SOURCE
+#define _GNU_SOURCE
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifndef INSIDE_RECURSION
+
+# include <stddef.h>
+
+# define WIDE_CHAR_SUPPORT (HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_BTOWC)
+
+/* For platform which support the ISO C amendement 1 functionality we
+ support user defined character classes. */
+# if defined _LIBC || WIDE_CHAR_SUPPORT
+/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */
+# include <wchar.h>
+# include <wctype.h>
+# endif
+
+# ifdef _LIBC
+/* We have to keep the namespace clean. */
+# define regfree(preg) __regfree (preg)
+# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef)
+# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags)
+# define regerror(errcode, preg, errbuf, errbuf_size) \
+ __regerror(errcode, preg, errbuf, errbuf_size)
+# define re_set_registers(bu, re, nu, st, en) \
+ __re_set_registers (bu, re, nu, st, en)
+# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \
+ __re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
+# define re_match(bufp, string, size, pos, regs) \
+ __re_match (bufp, string, size, pos, regs)
+# define re_search(bufp, string, size, startpos, range, regs) \
+ __re_search (bufp, string, size, startpos, range, regs)
+# define re_compile_pattern(pattern, length, bufp) \
+ __re_compile_pattern (pattern, length, bufp)
+# define re_set_syntax(syntax) __re_set_syntax (syntax)
+# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \
+ __re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop)
+# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp)
+
+# define btowc __btowc
+# define iswctype __iswctype
+# define mbrtowc __mbrtowc
+# define wcslen __wcslen
+# define wcscoll __wcscoll
+# define wcrtomb __wcrtomb
+
+/* We are also using some library internals. */
+# include <locale/localeinfo.h>
+# include <locale/elem-hash.h>
+# include <langinfo.h>
+# include <locale/coll-lookup.h>
+# endif
+
+# ifdef _LIBC
+# include <libintl.h>
+# undef gettext
+# define gettext(msgid) __dcgettext ("libc", msgid, LC_MESSAGES)
+ /* This define is so xgettext can find the internationalizable strings. */
+# define gettext_noop(msgid) msgid
+# else
+/* This is for other GNU distributions with internationalized messages. */
+# include "gettext.h"
+# endif
+
+/* Support for bounded pointers. */
+# if !defined _LIBC && !defined __BOUNDED_POINTERS__
+# define __bounded /* nothing */
+# define __unbounded /* nothing */
+# define __ptrvalue /* nothing */
+# endif
+
+/* The `emacs' switch turns on certain matching commands
+ that make sense only in Emacs. */
+# ifdef emacs
+
+# include "lisp.h"
+# include "buffer.h"
+# include "syntax.h"
+
+# else /* not emacs */
+
+/* If we are not linking with Emacs proper,
+ we can't use the relocating allocator
+ even if config.h says that we can. */
+# undef REL_ALLOC
+
+# include <stdlib.h>
+
+/* When used in Emacs's lib-src, we need to get bzero and bcopy somehow.
+ If nothing else has been done, use the method below. */
+# ifdef INHIBIT_STRING_HEADER
+# if !(defined HAVE_BZERO && defined HAVE_BCOPY)
+# if !defined bzero && !defined bcopy
+# undef INHIBIT_STRING_HEADER
+# endif
+# endif
+# endif
+
+/* This is the normal way of making sure we have a bcopy and a bzero.
+ This is used in most programs--a few other programs avoid this
+ by defining INHIBIT_STRING_HEADER. */
+# ifndef INHIBIT_STRING_HEADER
+# include <string.h>
+# ifndef bzero
+# ifndef _LIBC
+# define bzero(s, n) (memset (s, '\0', n), (s))
+# else
+# define bzero(s, n) __bzero (s, n)
+# endif
+# endif
+# endif
+
+/* Define the syntax stuff for \<, \>, etc. */
+
+/* This must be nonzero for the wordchar and notwordchar pattern
+ commands in re_match_2. */
+# ifndef Sword
+# define Sword 1
+# endif
+
+# ifdef SWITCH_ENUM_BUG
+# define SWITCH_ENUM_CAST(x) ((int)(x))
+# else
+# define SWITCH_ENUM_CAST(x) (x)
+# endif
+
+# endif /* not emacs */
+
+# include <limits.h>
+
+# ifndef MB_LEN_MAX
+# define MB_LEN_MAX 1
+# endif
+
+/* Get the interface, including the syntax bits. */
+# include <regex.h>
+
+/* isalpha etc. are used for the character classes. */
+# include <ctype.h>
+
+/* Jim Meyering writes:
+
+ "... Some ctype macros are valid only for character codes that
+ isascii says are ASCII (SGI's IRIX-4.0.5 is one such system --when
+ using /bin/cc or gcc but without giving an ansi option). So, all
+ ctype uses should be through macros like ISPRINT... If
+ STDC_HEADERS is defined, then autoconf has verified that the ctype
+ macros don't need to be guarded with references to isascii. ...
+ Defining isascii to 1 should let any compiler worth its salt
+ eliminate the && through constant folding."
+ Solaris defines some of these symbols so we must undefine them first. */
+
+# if defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII)
+# define IN_CTYPE_DOMAIN(c) 1
+# else
+# define IN_CTYPE_DOMAIN(c) isascii(c)
+# endif
+
+# ifdef isblank
+# define ISBLANK(c) (IN_CTYPE_DOMAIN (c) && isblank (c))
+# else
+# define ISBLANK(c) ((c) == ' ' || (c) == '\t')
+# endif
+# ifdef isgraph
+# define ISGRAPH(c) (IN_CTYPE_DOMAIN (c) && isgraph (c))
+# else
+# define ISGRAPH(c) (IN_CTYPE_DOMAIN (c) && isprint (c) && !isspace (c))
+# endif
+
+# undef ISPRINT
+# define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint (c))
+# define ISDIGIT(c) (IN_CTYPE_DOMAIN (c) && isdigit (c))
+# define ISALNUM(c) (IN_CTYPE_DOMAIN (c) && isalnum (c))
+# define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha (c))
+# define ISCNTRL(c) (IN_CTYPE_DOMAIN (c) && iscntrl (c))
+# define ISLOWER(c) (IN_CTYPE_DOMAIN (c) && islower (c))
+# define ISPUNCT(c) (IN_CTYPE_DOMAIN (c) && ispunct (c))
+# define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c))
+# define ISUPPER(c) (IN_CTYPE_DOMAIN (c) && isupper (c))
+# define ISXDIGIT(c) (IN_CTYPE_DOMAIN (c) && isxdigit (c))
+
+# ifdef _tolower
+# define TOLOWER(c) _tolower(c)
+# else
+# define TOLOWER(c) tolower(c)
+# endif
+
+# ifndef emacs
+/* How many characters in the character set. */
+# define CHAR_SET_SIZE 256
+
+# ifdef SYNTAX_TABLE
+
+extern char *re_syntax_table;
+
+# else /* not SYNTAX_TABLE */
+
+static char re_syntax_table[CHAR_SET_SIZE];
+
+static void
+init_syntax_once (void)
+{
+ register int c;
+ static int done = 0;
+
+ if (done)
+ return;
+ bzero (re_syntax_table, sizeof re_syntax_table);
+
+ for (c = 0; c < CHAR_SET_SIZE; ++c)
+ if (ISALNUM (c))
+ re_syntax_table[c] = Sword;
+
+ re_syntax_table['_'] = Sword;
+
+ done = 1;
+}
+
+# endif /* not SYNTAX_TABLE */
+
+# define SYNTAX(c) re_syntax_table[(unsigned char) (c)]
+
+# endif /* emacs */
+
+/* Should we use malloc or alloca? If REGEX_MALLOC is not defined, we
+ use `alloca' instead of `malloc'. This is because using malloc in
+ re_search* or re_match* could cause memory leaks when C-g is used in
+ Emacs; also, malloc is slower and causes storage fragmentation. On
+ the other hand, malloc is more portable, and easier to debug.
+
+ Because we sometimes use alloca, some routines have to be macros,
+ not functions -- `alloca'-allocated space disappears at the end of the
+ function it is called in. */
+
+# ifdef REGEX_MALLOC
+
+# define REGEX_ALLOCATE malloc
+# define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize)
+# define REGEX_FREE free
+
+# else /* not REGEX_MALLOC */
+
+/* Emacs already defines alloca, sometimes. */
+# ifndef alloca
+
+/* Make alloca work the best possible way. */
+# ifdef __GNUC__
+# define alloca __builtin_alloca
+# else /* not __GNUC__ */
+# if HAVE_ALLOCA_H
+# include <alloca.h>
+# endif /* HAVE_ALLOCA_H */
+# endif /* not __GNUC__ */
+
+# endif /* not alloca */
+
+# define REGEX_ALLOCATE alloca
+
+/* Assumes a `char *destination' variable. */
+# define REGEX_REALLOCATE(source, osize, nsize) \
+ (destination = (char *) alloca (nsize), \
+ memcpy (destination, source, osize))
+
+/* No need to do anything to free, after alloca. */
+# define REGEX_FREE(arg) ((void)0) /* Do nothing! But inhibit gcc warning. */
+
+# endif /* not REGEX_MALLOC */
+
+/* Define how to allocate the failure stack. */
+
+# if defined REL_ALLOC && defined REGEX_MALLOC
+
+# define REGEX_ALLOCATE_STACK(size) \
+ r_alloc (&failure_stack_ptr, (size))
+# define REGEX_REALLOCATE_STACK(source, osize, nsize) \
+ r_re_alloc (&failure_stack_ptr, (nsize))
+# define REGEX_FREE_STACK(ptr) \
+ r_alloc_free (&failure_stack_ptr)
+
+# else /* not using relocating allocator */
+
+# ifdef REGEX_MALLOC
+
+# define REGEX_ALLOCATE_STACK malloc
+# define REGEX_REALLOCATE_STACK(source, osize, nsize) realloc (source, nsize)
+# define REGEX_FREE_STACK free
+
+# else /* not REGEX_MALLOC */
+
+# define REGEX_ALLOCATE_STACK alloca
+
+# define REGEX_REALLOCATE_STACK(source, osize, nsize) \
+ REGEX_REALLOCATE (source, osize, nsize)
+/* No need to explicitly free anything. */
+# define REGEX_FREE_STACK(arg)
+
+# endif /* not REGEX_MALLOC */
+# endif /* not using relocating allocator */
+
+
+/* True if `size1' is non-NULL and PTR is pointing anywhere inside
+ `string1' or just past its end. This works if PTR is NULL, which is
+ a good thing. */
+# define FIRST_STRING_P(ptr) \
+ (size1 && string1 <= (ptr) && (ptr) <= string1 + size1)
+
+/* (Re)Allocate N items of type T using malloc, or fail. */
+# define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t)))
+# define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t)))
+# define RETALLOC_IF(addr, n, t) \
+ if (addr) RETALLOC((addr), (n), t); else (addr) = TALLOC ((n), t)
+# define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t)))
+
+# define BYTEWIDTH 8 /* In bits. */
+
+# define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
+
+# undef MAX
+# undef MIN
+# define MAX(a, b) ((a) > (b) ? (a) : (b))
+# define MIN(a, b) ((a) < (b) ? (a) : (b))
+
+typedef char boolean;
+# define false 0
+# define true 1
+
+static reg_errcode_t byte_regex_compile (const char *pattern, size_t size,
+ reg_syntax_t syntax,
+ struct re_pattern_buffer *bufp);
+
+static int byte_re_match_2_internal (struct re_pattern_buffer *bufp,
+ const char *string1, int size1,
+ const char *string2, int size2,
+ int pos,
+ struct re_registers *regs,
+ int stop);
+static int byte_re_search_2 (struct re_pattern_buffer *bufp,
+ const char *string1, int size1,
+ const char *string2, int size2,
+ int startpos, int range,
+ struct re_registers *regs, int stop);
+static int byte_re_compile_fastmap (struct re_pattern_buffer *bufp);
+
+#ifdef MBS_SUPPORT
+static reg_errcode_t wcs_regex_compile (const char *pattern, size_t size,
+ reg_syntax_t syntax,
+ struct re_pattern_buffer *bufp);
+
+
+static int wcs_re_match_2_internal (struct re_pattern_buffer *bufp,
+ const char *cstring1, int csize1,
+ const char *cstring2, int csize2,
+ int pos,
+ struct re_registers *regs,
+ int stop,
+ wchar_t *string1, int size1,
+ wchar_t *string2, int size2,
+ int *mbs_offset1, int *mbs_offset2);
+static int wcs_re_search_2 (struct re_pattern_buffer *bufp,
+ const char *string1, int size1,
+ const char *string2, int size2,
+ int startpos, int range,
+ struct re_registers *regs, int stop);
+static int wcs_re_compile_fastmap (struct re_pattern_buffer *bufp);
+#endif
+
+/* These are the command codes that appear in compiled regular
+ expressions. Some opcodes are followed by argument bytes. A
+ command code can specify any interpretation whatsoever for its
+ arguments. Zero bytes may appear in the compiled regular expression. */
+
+typedef enum
+{
+ no_op = 0,
+
+ /* Succeed right away--no more backtracking. */
+ succeed,
+
+ /* Followed by one byte giving n, then by n literal bytes. */
+ exactn,
+
+# ifdef MBS_SUPPORT
+ /* Same as exactn, but contains binary data. */
+ exactn_bin,
+# endif
+
+ /* 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. */
+ /* ifdef MBS_SUPPORT, following element is length of character
+ classes, length of collating symbols, length of equivalence
+ classes, length of character ranges, and length of characters.
+ Next, character class element, collating symbols elements,
+ equivalence class elements, range elements, and character
+ elements follow.
+ See regex_compile function. */
+ 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. */
+ /* ifdef MBS_SUPPORT, the size of address is 1. */
+ 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. */
+ /* ifdef MBS_SUPPORT, the size of address is 1. */
+ 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. */
+ /* ifdef MBS_SUPPORT, the size of address is 1. */
+ 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. */
+ /* ifdef MBS_SUPPORT, the size of address is 1. */
+ 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. */
+ /* ifdef MBS_SUPPORT, the size of address is 1. */
+ succeed_n,
+
+ /* Followed by two-byte relative address, and two-byte number n.
+ Jump to the address N times, then fail. */
+ /* ifdef MBS_SUPPORT, the size of address is 1. */
+ jump_n,
+
+ /* Set the following two-byte relative address to the
+ subsequent two-byte number. The address *includes* the two
+ bytes of number. */
+ /* ifdef MBS_SUPPORT, the size of address is 1. */
+ 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;
+#endif /* not INSIDE_RECURSION */
+
+
+#ifdef BYTE
+# define CHAR_T char
+# define UCHAR_T unsigned char
+# define COMPILED_BUFFER_VAR bufp->buffer
+# define OFFSET_ADDRESS_SIZE 2
+# define PREFIX(name) byte_##name
+# define ARG_PREFIX(name) name
+# define PUT_CHAR(c) putchar (c)
+#else
+# ifdef WCHAR
+# define CHAR_T wchar_t
+# define UCHAR_T wchar_t
+# define COMPILED_BUFFER_VAR wc_buffer
+# define OFFSET_ADDRESS_SIZE 1 /* the size which STORE_NUMBER macro use */
+# define CHAR_CLASS_SIZE ((__alignof__(wctype_t)+sizeof(wctype_t))/sizeof(CHAR_T)+1)
+# define PREFIX(name) wcs_##name
+# define ARG_PREFIX(name) c##name
+/* Should we use wide stream?? */
+# define PUT_CHAR(c) printf ("%C", c);
+# define TRUE 1
+# define FALSE 0
+# else
+# ifdef MBS_SUPPORT
+# define WCHAR
+# define INSIDE_RECURSION
+# include "regex.c"
+# undef INSIDE_RECURSION
+# endif
+# define BYTE
+# define INSIDE_RECURSION
+# include "regex.c"
+# undef INSIDE_RECURSION
+# endif
+#endif
+#include "unlocked-io.h"
+
+#ifdef INSIDE_RECURSION
+/* Common operations on the compiled pattern. */
+
+/* Store NUMBER in two contiguous bytes starting at DESTINATION. */
+/* ifdef MBS_SUPPORT, we store NUMBER in 1 element. */
+
+# ifdef WCHAR
+# define STORE_NUMBER(destination, number) \
+ do { \
+ *(destination) = (UCHAR_T)(number); \
+ } while (0)
+# else /* BYTE */
+# define STORE_NUMBER(destination, number) \
+ do { \
+ (destination)[0] = (number) & 0377; \
+ (destination)[1] = (number) >> 8; \
+ } while (0)
+# endif /* WCHAR */
+
+/* Same as STORE_NUMBER, except increment DESTINATION to
+ the byte after where the number is stored. Therefore, DESTINATION
+ must be an lvalue. */
+/* ifdef MBS_SUPPORT, we store NUMBER in 1 element. */
+
+# define STORE_NUMBER_AND_INCR(destination, number) \
+ do { \
+ STORE_NUMBER (destination, number); \
+ (destination) += OFFSET_ADDRESS_SIZE; \
+ } while (0)
+
+/* Put into DESTINATION a number stored in two contiguous bytes starting
+ at SOURCE. */
+/* ifdef MBS_SUPPORT, we store NUMBER in 1 element. */
+
+# ifdef WCHAR
+# define EXTRACT_NUMBER(destination, source) \
+ do { \
+ (destination) = *(source); \
+ } while (0)
+# else /* BYTE */
+# define EXTRACT_NUMBER(destination, source) \
+ do { \
+ (destination) = *(source) & 0377; \
+ (destination) += (signed char) (*((source) + 1)) << 8; \
+ } while (0)
+# endif
+
+# ifdef DEBUG
+static void
+PREFIX(extract_number) (int *dest, UCHAR_T *source)
+{
+# ifdef WCHAR
+ *dest = *source;
+# else /* BYTE */
+ signed char temp = source[1];
+ *dest = *source & 0377;
+ *dest += temp << 8;
+# endif
+}
+
+# ifndef EXTRACT_MACROS /* To debug the macros. */
+# undef EXTRACT_NUMBER
+# define EXTRACT_NUMBER(dest, src) PREFIX(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) += OFFSET_ADDRESS_SIZE; \
+ } while (0)
+
+# ifdef DEBUG
+static void
+PREFIX(extract_number_and_incr) (int *destination, UCHAR_T **source)
+{
+ PREFIX(extract_number) (destination, *source);
+ *source += OFFSET_ADDRESS_SIZE;
+}
+
+# ifndef EXTRACT_MACROS
+# undef EXTRACT_NUMBER_AND_INCR
+# define EXTRACT_NUMBER_AND_INCR(dest, src) \
+ PREFIX(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
+
+# ifndef DEFINED_ONCE
+
+/* 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;
+
+# 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)
+# endif /* not DEFINED_ONCE */
+
+# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \
+ if (debug) PREFIX(print_partial_compiled_pattern) (s, e)
+# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \
+ if (debug) PREFIX(print_double_string) (w, s1, sz1, s2, sz2)
+
+
+/* Print the fastmap in human-readable form. */
+
+# ifndef DEFINED_ONCE
+void
+print_fastmap (char *fastmap)
+{
+ unsigned was_a_range = 0;
+ unsigned i = 0;
+
+ while (i < (1 << BYTEWIDTH))
+ {
+ if (fastmap[i++])
+ {
+ was_a_range = 0;
+ putchar (i - 1);
+ while (i < (1 << BYTEWIDTH) && fastmap[i])
+ {
+ was_a_range = 1;
+ i++;
+ }
+ if (was_a_range)
+ {
+ printf ("-");
+ putchar (i - 1);
+ }
+ }
+ }
+ putchar ('\n');
+}
+# endif /* not DEFINED_ONCE */
+
+
+/* Print a compiled pattern string in human-readable form, starting at
+ the START pointer into it and ending just before the pointer END. */
+
+void
+PREFIX(print_partial_compiled_pattern) (UCHAR_T *start, UCHAR_T *end)
+{
+ int mcnt, mcnt2;
+ UCHAR_T *p1;
+ UCHAR_T *p = start;
+ UCHAR_T *pend = end;
+
+ if (start == NULL)
+ {
+ printf ("(null)\n");
+ return;
+ }
+
+ /* Loop over pattern commands. */
+ while (p < pend)
+ {
+# ifdef _LIBC
+ printf ("%td:\t", p - start);
+# else
+ printf ("%ld:\t", (long int) (p - start));
+# endif
+
+ switch ((re_opcode_t) *p++)
+ {
+ case no_op:
+ printf ("/no_op");
+ break;
+
+ case exactn:
+ mcnt = *p++;
+ printf ("/exactn/%d", mcnt);
+ do
+ {
+ putchar ('/');
+ PUT_CHAR (*p++);
+ }
+ while (--mcnt);
+ break;
+
+# ifdef MBS_SUPPORT
+ case exactn_bin:
+ mcnt = *p++;
+ printf ("/exactn_bin/%d", mcnt);
+ do
+ {
+ printf("/%lx", (long int) *p++);
+ }
+ while (--mcnt);
+ break;
+# endif /* MBS_SUPPORT */
+
+ case start_memory:
+ mcnt = *p++;
+ printf ("/start_memory/%d/%ld", mcnt, (long int) *p++);
+ break;
+
+ case stop_memory:
+ mcnt = *p++;
+ printf ("/stop_memory/%d/%ld", mcnt, (long int) *p++);
+ break;
+
+ case duplicate:
+ printf ("/duplicate/%ld", (long int) *p++);
+ break;
+
+ case anychar:
+ printf ("/anychar");
+ break;
+
+ case charset:
+ case charset_not:
+ {
+# ifdef WCHAR
+ int i, length;
+ wchar_t *workp = p;
+ printf ("/charset [%s",
+ (re_opcode_t) *(workp - 1) == charset_not ? "^" : "");
+ p += 5;
+ length = *workp++; /* the length of char_classes */
+ for (i=0 ; i<length ; i++)
+ printf("[:%lx:]", (long int) *p++);
+ length = *workp++; /* the length of collating_symbol */
+ for (i=0 ; i<length ;)
+ {
+ printf("[.");
+ while(*p != 0)
+ PUT_CHAR((i++,*p++));
+ i++,p++;
+ printf(".]");
+ }
+ length = *workp++; /* the length of equivalence_class */
+ for (i=0 ; i<length ;)
+ {
+ printf("[=");
+ while(*p != 0)
+ PUT_CHAR((i++,*p++));
+ i++,p++;
+ printf("=]");
+ }
+ length = *workp++; /* the length of char_range */
+ for (i=0 ; i<length ; i++)
+ {
+ wchar_t range_start = *p++;
+ wchar_t range_end = *p++;
+ printf("%C-%C", range_start, range_end);
+ }
+ length = *workp++; /* the length of char */
+ for (i=0 ; i<length ; i++)
+ printf("%C", *p++);
+ putchar (']');
+# else
+ register int c, last = -100;
+ register int in_range = 0;
+
+ printf ("/charset [%s",
+ (re_opcode_t) *(p - 1) == charset_not ? "^" : "");
+
+ assert (p + *p < pend);
+
+ for (c = 0; c < 256; c++)
+ if (c / 8 < *p
+ && (p[1 + (c/8)] & (1 << (c % 8))))
+ {
+ /* Are we starting a range? */
+ if (last + 1 == c && ! in_range)
+ {
+ putchar ('-');
+ in_range = 1;
+ }
+ /* Have we broken a range? */
+ else if (last + 1 != c && in_range)
+ {
+ putchar (last);
+ in_range = 0;
+ }
+
+ if (! in_range)
+ putchar (c);
+
+ last = c;
+ }
+
+ if (in_range)
+ putchar (last);
+
+ putchar (']');
+
+ p += 1 + *p;
+# endif /* WCHAR */
+ }
+ break;
+
+ case begline:
+ printf ("/begline");
+ break;
+
+ case endline:
+ printf ("/endline");
+ break;
+
+ case on_failure_jump:
+ PREFIX(extract_number_and_incr) (&mcnt, &p);
+# ifdef _LIBC
+ printf ("/on_failure_jump to %td", p + mcnt - start);
+# else
+ printf ("/on_failure_jump to %ld", (long int) (p + mcnt - start));
+# endif
+ break;
+
+ case on_failure_keep_string_jump:
+ PREFIX(extract_number_and_incr) (&mcnt, &p);
+# ifdef _LIBC
+ printf ("/on_failure_keep_string_jump to %td", p + mcnt - start);
+# else
+ printf ("/on_failure_keep_string_jump to %ld",
+ (long int) (p + mcnt - start));
+# endif
+ break;
+
+ case dummy_failure_jump:
+ PREFIX(extract_number_and_incr) (&mcnt, &p);
+# ifdef _LIBC
+ printf ("/dummy_failure_jump to %td", p + mcnt - start);
+# else
+ printf ("/dummy_failure_jump to %ld", (long int) (p + mcnt - start));
+# endif
+ break;
+
+ case push_dummy_failure:
+ printf ("/push_dummy_failure");
+ break;
+
+ case maybe_pop_jump:
+ PREFIX(extract_number_and_incr) (&mcnt, &p);
+# ifdef _LIBC
+ printf ("/maybe_pop_jump to %td", p + mcnt - start);
+# else
+ printf ("/maybe_pop_jump to %ld", (long int) (p + mcnt - start));
+# endif
+ break;
+
+ case pop_failure_jump:
+ PREFIX(extract_number_and_incr) (&mcnt, &p);
+# ifdef _LIBC
+ printf ("/pop_failure_jump to %td", p + mcnt - start);
+# else
+ printf ("/pop_failure_jump to %ld", (long int) (p + mcnt - start));
+# endif
+ break;
+
+ case jump_past_alt:
+ PREFIX(extract_number_and_incr) (&mcnt, &p);
+# ifdef _LIBC
+ printf ("/jump_past_alt to %td", p + mcnt - start);
+# else
+ printf ("/jump_past_alt to %ld", (long int) (p + mcnt - start));
+# endif
+ break;
+
+ case jump:
+ PREFIX(extract_number_and_incr) (&mcnt, &p);
+# ifdef _LIBC
+ printf ("/jump to %td", p + mcnt - start);
+# else
+ printf ("/jump to %ld", (long int) (p + mcnt - start));
+# endif
+ break;
+
+ case succeed_n:
+ PREFIX(extract_number_and_incr) (&mcnt, &p);
+ p1 = p + mcnt;
+ PREFIX(extract_number_and_incr) (&mcnt2, &p);
+# ifdef _LIBC
+ printf ("/succeed_n to %td, %d times", p1 - start, mcnt2);
+# else
+ printf ("/succeed_n to %ld, %d times",
+ (long int) (p1 - start), mcnt2);
+# endif
+ break;
+
+ case jump_n:
+ PREFIX(extract_number_and_incr) (&mcnt, &p);
+ p1 = p + mcnt;
+ PREFIX(extract_number_and_incr) (&mcnt2, &p);
+ printf ("/jump_n to %d, %d times", p1 - start, mcnt2);
+ break;
+
+ case set_number_at:
+ PREFIX(extract_number_and_incr) (&mcnt, &p);
+ p1 = p + mcnt;
+ PREFIX(extract_number_and_incr) (&mcnt2, &p);
+# ifdef _LIBC
+ printf ("/set_number_at location %td to %d", p1 - start, mcnt2);
+# else
+ printf ("/set_number_at location %ld to %d",
+ (long int) (p1 - start), mcnt2);
+# endif
+ break;
+
+ case wordbound:
+ printf ("/wordbound");
+ break;
+
+ case notwordbound:
+ printf ("/notwordbound");
+ break;
+
+ case wordbeg:
+ printf ("/wordbeg");
+ break;
+
+ case wordend:
+ printf ("/wordend");
+ break;
+
+# 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 ("?%ld", (long int) *(p-1));
+ }
+
+ putchar ('\n');
+ }
+
+# ifdef _LIBC
+ printf ("%td:\tend of pattern.\n", p - start);
+# else
+ printf ("%ld:\tend of pattern.\n", (long int) (p - start));
+# endif
+}
+
+
+void
+PREFIX(print_compiled_pattern) (struct re_pattern_buffer *bufp)
+{
+ UCHAR_T *buffer = (UCHAR_T*) bufp->buffer;
+
+ PREFIX(print_partial_compiled_pattern) (buffer, buffer
+ + bufp->used / sizeof(UCHAR_T));
+ printf ("%ld bytes used/%ld bytes allocated.\n",
+ bufp->used, bufp->allocated);
+
+ if (bufp->fastmap_accurate && bufp->fastmap)
+ {
+ printf ("fastmap: ");
+ print_fastmap (bufp->fastmap);
+ }
+
+# ifdef _LIBC
+ printf ("re_nsub: %Zd\t", bufp->re_nsub);
+# else
+ printf ("re_nsub: %ld\t", (long int) bufp->re_nsub);
+# endif
+ printf ("regs_alloc: %d\t", bufp->regs_allocated);
+ printf ("can_be_null: %d\t", bufp->can_be_null);
+ printf ("newline_anchor: %d\n", bufp->newline_anchor);
+ printf ("no_sub: %d\t", bufp->no_sub);
+ printf ("not_bol: %d\t", bufp->not_bol);
+ printf ("not_eol: %d\t", bufp->not_eol);
+ printf ("syntax: %lx\n", bufp->syntax);
+ /* Perhaps we should print the translate table? */
+}
+
+
+void
+PREFIX(print_double_string) (const CHAR_T *where,
+ const CHAR_T *string1,
+ const CHAR_T *string2,
+ int size1,
+ int size2)
+{
+ int this_char;
+
+ if (where == NULL)
+ printf ("(null)");
+ else
+ {
+ int cnt;
+
+ if (FIRST_STRING_P (where))
+ {
+ for (this_char = where - string1; this_char < size1; this_char++)
+ PUT_CHAR (string1[this_char]);
+
+ where = string2;
+ }
+
+ cnt = 0;
+ for (this_char = where - string2; this_char < size2; this_char++)
+ {
+ PUT_CHAR (string2[this_char]);
+ if (++cnt > 100)
+ {
+ fputs ("...", stdout);
+ break;
+ }
+ }
+ }
+}
+
+# ifndef DEFINED_ONCE
+void
+printchar (c)
+ int c;
+{
+ putc (c, stderr);
+}
+# endif
+
+# else /* not DEBUG */
+
+# ifndef DEFINED_ONCE
+# 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)
+# endif /* not DEFINED_ONCE */
+# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e)
+# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)
+
+# endif /* not DEBUG */
+
+
+
+# ifdef WCHAR
+/* This convert a multibyte string to a wide character string.
+ And write their correspondances to offset_buffer(see below)
+ and write whether each wchar_t is binary data to is_binary.
+ This assume invalid multibyte sequences as binary data.
+ We assume offset_buffer and is_binary is already allocated
+ enough space. */
+
+static size_t
+convert_mbs_to_wcs (CHAR_T *dest,
+ const unsigned char* src,
+
+ /* The length of multibyte string. */
+ size_t len,
+
+ /* Correspondences between src(char string) and
+ dest(wchar_t string) for optimization. E.g.:
+ src = "xxxyzz"
+ dest = {'X', 'Y', 'Z'}
+ (each "xxx", "y" and "zz" represent one
+ multibyte character corresponding to 'X',
+ 'Y' and 'Z'.)
+ offset_buffer = {0, 0+3("xxx"), 0+3+1("y"),
+ 0+3+1+2("zz")}
+ = {0, 3, 4, 6} */
+ int *offset_buffer,
+
+ char *is_binary)
+{
+ wchar_t *pdest = dest;
+ const unsigned char *psrc = src;
+ size_t wc_count = 0;
+
+ mbstate_t mbs;
+ int i, consumed;
+ size_t mb_remain = len;
+ size_t mb_count = 0;
+
+ /* Initialize the conversion state. */
+ memset (&mbs, 0, sizeof (mbstate_t));
+
+ offset_buffer[0] = 0;
+ for( ; mb_remain > 0 ; ++wc_count, ++pdest, mb_remain -= consumed,
+ psrc += consumed)
+ {
+ consumed = mbrtowc (pdest, psrc, mb_remain, &mbs);
+
+ if (consumed <= 0)
+ /* failed to convert. maybe src contains binary data.
+ So we consume 1 byte manualy. */
+ {
+ *pdest = *psrc;
+ consumed = 1;
+ is_binary[wc_count] = TRUE;
+ }
+ else
+ is_binary[wc_count] = FALSE;
+ /* In sjis encoding, we use yen sign as escape character in
+ place of reverse solidus. So we convert 0x5c(yen sign in
+ sjis) to not 0xa5(yen sign in UCS2) but 0x5c(reverse
+ solidus in UCS2). */
+ if (consumed == 1 && (int) *psrc == 0x5c && (int) *pdest == 0xa5)
+ *pdest = (wchar_t) *psrc;
+
+ offset_buffer[wc_count + 1] = mb_count += consumed;
+ }
+
+ /* Fill remain of the buffer with sentinel. */
+ for (i = wc_count + 1 ; i <= len ; i++)
+ offset_buffer[i] = mb_count + 1;
+
+ return wc_count;
+}
+
+# endif /* WCHAR */
+
+#else /* not INSIDE_RECURSION */
+
+/* Set by `re_set_syntax' to the current regexp syntax to recognize. Can
+ also be assigned to arbitrarily: each pattern buffer stores its own
+ syntax, so it can be changed between regex compilations. */
+/* This has no initializer because initialized variables in Emacs
+ become read-only after dumping. */
+reg_syntax_t re_syntax_options;
+
+
+/* Specify the precise syntax of regexps for compilation. This provides
+ for compatibility for various utilities which historically have
+ different, incompatible syntaxes.
+
+ The argument SYNTAX is a bit mask comprised of the various bits
+ defined in regex.h. We return the old syntax. */
+
+reg_syntax_t
+re_set_syntax (reg_syntax_t syntax)
+{
+ reg_syntax_t ret = re_syntax_options;
+
+ re_syntax_options = syntax;
+# ifdef DEBUG
+ if (syntax & RE_DEBUG)
+ debug = 1;
+ else if (debug) /* was on but now is not */
+ debug = 0;
+# endif /* DEBUG */
+ return ret;
+}
+# ifdef _LIBC
+weak_alias (__re_set_syntax, re_set_syntax)
+# endif
+
+/* This table gives an error message for each of the error codes listed
+ in regex.h. Obviously the order here has to be same as there.
+ POSIX doesn't require that we do anything for REG_NOERROR,
+ but why not be nice? */
+
+static const char re_error_msgid[] =
+ {
+# define REG_NOERROR_IDX 0
+ gettext_noop ("Success") /* REG_NOERROR */
+ "\0"
+# define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success")
+ gettext_noop ("No match") /* REG_NOMATCH */
+ "\0"
+# define REG_BADPAT_IDX (REG_NOMATCH_IDX + sizeof "No match")
+ gettext_noop ("Invalid regular expression") /* REG_BADPAT */
+ "\0"
+# define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression")
+ gettext_noop ("Invalid collation character") /* REG_ECOLLATE */
+ "\0"
+# define REG_ECTYPE_IDX (REG_ECOLLATE_IDX + sizeof "Invalid collation character")
+ gettext_noop ("Invalid character class name") /* REG_ECTYPE */
+ "\0"
+# define REG_EESCAPE_IDX (REG_ECTYPE_IDX + sizeof "Invalid character class name")
+ gettext_noop ("Trailing backslash") /* REG_EESCAPE */
+ "\0"
+# define REG_ESUBREG_IDX (REG_EESCAPE_IDX + sizeof "Trailing backslash")
+ gettext_noop ("Invalid back reference") /* REG_ESUBREG */
+ "\0"
+# define REG_EBRACK_IDX (REG_ESUBREG_IDX + sizeof "Invalid back reference")
+ gettext_noop ("Unmatched [ or [^") /* REG_EBRACK */
+ "\0"
+# define REG_EPAREN_IDX (REG_EBRACK_IDX + sizeof "Unmatched [ or [^")
+ gettext_noop ("Unmatched ( or \\(") /* REG_EPAREN */
+ "\0"
+# define REG_EBRACE_IDX (REG_EPAREN_IDX + sizeof "Unmatched ( or \\(")
+ gettext_noop ("Unmatched \\{") /* REG_EBRACE */
+ "\0"
+# define REG_BADBR_IDX (REG_EBRACE_IDX + sizeof "Unmatched \\{")
+ gettext_noop ("Invalid content of \\{\\}") /* REG_BADBR */
+ "\0"
+# define REG_ERANGE_IDX (REG_BADBR_IDX + sizeof "Invalid content of \\{\\}")
+ gettext_noop ("Invalid range end") /* REG_ERANGE */
+ "\0"
+# define REG_ESPACE_IDX (REG_ERANGE_IDX + sizeof "Invalid range end")
+ gettext_noop ("Memory exhausted") /* REG_ESPACE */
+ "\0"
+# define REG_BADRPT_IDX (REG_ESPACE_IDX + sizeof "Memory exhausted")
+ gettext_noop ("Invalid preceding regular expression") /* REG_BADRPT */
+ "\0"
+# define REG_EEND_IDX (REG_BADRPT_IDX + sizeof "Invalid preceding regular expression")
+ gettext_noop ("Premature end of regular expression") /* REG_EEND */
+ "\0"
+# define REG_ESIZE_IDX (REG_EEND_IDX + sizeof "Premature end of regular expression")
+ gettext_noop ("Regular expression too big") /* REG_ESIZE */
+ "\0"
+# define REG_ERPAREN_IDX (REG_ESIZE_IDX + sizeof "Regular expression too big")
+ gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */
+ };
+
+static const size_t re_error_msgid_idx[] =
+ {
+ REG_NOERROR_IDX,
+ REG_NOMATCH_IDX,
+ REG_BADPAT_IDX,
+ REG_ECOLLATE_IDX,
+ REG_ECTYPE_IDX,
+ REG_EESCAPE_IDX,
+ REG_ESUBREG_IDX,
+ REG_EBRACK_IDX,
+ REG_EPAREN_IDX,
+ REG_EBRACE_IDX,
+ REG_BADBR_IDX,
+ REG_ERANGE_IDX,
+ REG_ESPACE_IDX,
+ REG_BADRPT_IDX,
+ REG_EEND_IDX,
+ REG_ESIZE_IDX,
+ REG_ERPAREN_IDX
+ };
+
+#endif /* INSIDE_RECURSION */
+
+#ifndef DEFINED_ONCE
+/* Avoiding alloca during matching, to placate r_alloc. */
+
+/* Define MATCH_MAY_ALLOCATE unless we need to make sure that the
+ searching and matching functions should not call alloca. On some
+ systems, alloca is implemented in terms of malloc, and if we're
+ using the relocating allocator routines, then malloc could cause a
+ relocation, which might (if the strings being searched are in the
+ ralloc heap) shift the data out from underneath the regexp
+ routines.
+
+ Here's another reason to avoid allocation: Emacs
+ processes input from X in a signal handler; processing X input may
+ call malloc; if input arrives while a matching routine is calling
+ malloc, then we're scrod. But Emacs can't just block input while
+ calling matching routines; then we don't notice interrupts when
+ they come in. So, Emacs blocks input around all regexp calls
+ except the matching calls, which it leaves unprotected, in the
+ faith that they will not malloc. */
+
+/* Normally, this is fine. */
+# define MATCH_MAY_ALLOCATE
+
+/* When using GNU C, we are not REALLY using the C alloca, no matter
+ what config.h may say. So don't take precautions for it. */
+# ifdef __GNUC__
+# undef C_ALLOCA
+# endif
+
+/* The match routines may not allocate if (1) they would do it with malloc
+ and (2) it's not safe for them to use malloc.
+ Note that if REL_ALLOC is defined, matching would not use malloc for the
+ failure stack, but we would still use it for the register vectors;
+ so REL_ALLOC should not affect this. */
+# if (defined C_ALLOCA || defined REGEX_MALLOC) && defined emacs
+# undef MATCH_MAY_ALLOCATE
+# endif
+#endif /* not DEFINED_ONCE */
+
+#ifdef INSIDE_RECURSION
+/* Failure stack declarations and macros; both re_compile_fastmap and
+ re_match_2 use a failure stack. These have to be macros because of
+ REGEX_ALLOCATE_STACK. */
+
+
+/* Number of failure points for which to initially allocate space
+ when matching. If this number is exceeded, we allocate more
+ space, so it is not a hard limit. */
+# ifndef INIT_FAILURE_ALLOC
+# define INIT_FAILURE_ALLOC 5
+# endif
+
+/* Roughly the maximum number of failure points on the stack. Would be
+ exactly that if always used MAX_FAILURE_ITEMS items each time we failed.
+ This is a variable only so users of regex can assign to it; we never
+ change it ourselves. */
+
+# ifdef INT_IS_16BIT
+
+# ifndef DEFINED_ONCE
+# if defined MATCH_MAY_ALLOCATE
+/* 4400 was enough to cause a crash on Alpha OSF/1,
+ whose default stack limit is 2mb. */
+long int re_max_failures = 4000;
+# else
+long int re_max_failures = 2000;
+# endif
+# endif
+
+union PREFIX(fail_stack_elt)
+{
+ UCHAR_T *pointer;
+ long int integer;
+};
+
+typedef union PREFIX(fail_stack_elt) PREFIX(fail_stack_elt_t);
+
+typedef struct
+{
+ PREFIX(fail_stack_elt_t) *stack;
+ unsigned long int size;
+ unsigned long int avail; /* Offset of next open position. */
+} PREFIX(fail_stack_type);
+
+# else /* not INT_IS_16BIT */
+
+# ifndef DEFINED_ONCE
+# if defined MATCH_MAY_ALLOCATE
+/* 4400 was enough to cause a crash on Alpha OSF/1,
+ whose default stack limit is 2mb. */
+int re_max_failures = 4000;
+# else
+int re_max_failures = 2000;
+# endif
+# endif
+
+union PREFIX(fail_stack_elt)
+{
+ UCHAR_T *pointer;
+ int integer;
+};
+
+typedef union PREFIX(fail_stack_elt) PREFIX(fail_stack_elt_t);
+
+typedef struct
+{
+ PREFIX(fail_stack_elt_t) *stack;
+ unsigned size;
+ unsigned avail; /* Offset of next open position. */
+} PREFIX(fail_stack_type);
+
+# endif /* INT_IS_16BIT */
+
+# ifndef DEFINED_ONCE
+# 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)
+# endif
+
+
+/* Define macros to initialize and free the failure stack.
+ Do `return -2' if the alloc fails. */
+
+# ifdef MATCH_MAY_ALLOCATE
+# define INIT_FAIL_STACK() \
+ do { \
+ fail_stack.stack = (PREFIX(fail_stack_elt_t) *) \
+ REGEX_ALLOCATE_STACK (INIT_FAILURE_ALLOC * sizeof (PREFIX(fail_stack_elt_t))); \
+ \
+ if (fail_stack.stack == NULL) \
+ return -2; \
+ \
+ fail_stack.size = INIT_FAILURE_ALLOC; \
+ fail_stack.avail = 0; \
+ } while (0)
+
+# define RESET_FAIL_STACK() REGEX_FREE_STACK (fail_stack.stack)
+# else
+# define INIT_FAIL_STACK() \
+ do { \
+ fail_stack.avail = 0; \
+ } while (0)
+
+# define RESET_FAIL_STACK()
+# endif
+
+
+/* Double the size of FAIL_STACK, up to approximately `re_max_failures' items.
+
+ Return 1 if succeeds, and 0 if either ran out of memory
+ allocating space for it or it was already too large.
+
+ REGEX_REALLOCATE_STACK requires `destination' be declared. */
+
+# define DOUBLE_FAIL_STACK(fail_stack) \
+ ((fail_stack).size > (unsigned) (re_max_failures * MAX_FAILURE_ITEMS) \
+ ? 0 \
+ : ((fail_stack).stack = (PREFIX(fail_stack_elt_t) *) \
+ REGEX_REALLOCATE_STACK ((fail_stack).stack, \
+ (fail_stack).size * sizeof (PREFIX(fail_stack_elt_t)), \
+ ((fail_stack).size << 1) * sizeof (PREFIX(fail_stack_elt_t))),\
+ \
+ (fail_stack).stack == NULL \
+ ? 0 \
+ : ((fail_stack).size <<= 1, \
+ 1)))
+
+
+/* Push pointer POINTER on FAIL_STACK.
+ Return 1 if was able to do so and 0 if ran out of memory allocating
+ space to do so. */
+# define PUSH_PATTERN_OP(POINTER, FAIL_STACK) \
+ ((FAIL_STACK_FULL () \
+ && !DOUBLE_FAIL_STACK (FAIL_STACK)) \
+ ? 0 \
+ : ((FAIL_STACK).stack[(FAIL_STACK).avail++].pointer = POINTER, \
+ 1))
+
+/* Push a pointer value onto the failure stack.
+ Assumes the variable `fail_stack'. Probably should only
+ be called from within `PUSH_FAILURE_POINT'. */
+# define PUSH_FAILURE_POINTER(item) \
+ fail_stack.stack[fail_stack.avail++].pointer = (UCHAR_T *) (item)
+
+/* This pushes an integer-valued item onto the failure stack.
+ Assumes the variable `fail_stack'. Probably should only
+ be called from within `PUSH_FAILURE_POINT'. */
+# define PUSH_FAILURE_INT(item) \
+ fail_stack.stack[fail_stack.avail++].integer = (item)
+
+/* Push a fail_stack_elt_t value onto the failure stack.
+ Assumes the variable `fail_stack'. Probably should only
+ be called from within `PUSH_FAILURE_POINT'. */
+# define PUSH_FAILURE_ELT(item) \
+ fail_stack.stack[fail_stack.avail++] = (item)
+
+/* These three POP... operations complement the three PUSH... operations.
+ All assume that `fail_stack' is nonempty. */
+# define POP_FAILURE_POINTER() fail_stack.stack[--fail_stack.avail].pointer
+# define POP_FAILURE_INT() fail_stack.stack[--fail_stack.avail].integer
+# define POP_FAILURE_ELT() fail_stack.stack[--fail_stack.avail]
+
+/* Used to omit pushing failure point id's when we're not debugging. */
+# ifdef DEBUG
+# define DEBUG_PUSH PUSH_FAILURE_INT
+# define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_INT ()
+# else
+# define DEBUG_PUSH(item)
+# define DEBUG_POP(item_addr)
+# endif
+
+
+/* Push the information about the state we will need
+ if we ever fail back to it.
+
+ Requires variables fail_stack, regstart, regend, reg_info, and
+ num_regs_pushed be declared. DOUBLE_FAIL_STACK requires `destination'
+ be declared.
+
+ Does `return FAILURE_CODE' if runs out of memory. */
+
+# define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code) \
+ do { \
+ char *destination; \
+ /* Must be int, so when we don't save any registers, the arithmetic \
+ of 0 + -1 isn't done as unsigned. */ \
+ /* Can't be int, since there is not a shred of a guarantee that int \
+ is wide enough to hold a value of something to which pointer can \
+ be assigned */ \
+ active_reg_t this_reg; \
+ \
+ DEBUG_STATEMENT (failure_id++); \
+ DEBUG_STATEMENT (nfailure_points_pushed++); \
+ DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id); \
+ DEBUG_PRINT2 (" Before push, next avail: %d\n", (fail_stack).avail);\
+ DEBUG_PRINT2 (" size: %d\n", (fail_stack).size);\
+ \
+ DEBUG_PRINT2 (" slots needed: %ld\n", NUM_FAILURE_ITEMS); \
+ DEBUG_PRINT2 (" available: %d\n", REMAINING_AVAIL_SLOTS); \
+ \
+ /* Ensure we have enough space allocated for what we will push. */ \
+ while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS) \
+ { \
+ if (!DOUBLE_FAIL_STACK (fail_stack)) \
+ return failure_code; \
+ \
+ DEBUG_PRINT2 ("\n Doubled stack; size now: %d\n", \
+ (fail_stack).size); \
+ DEBUG_PRINT2 (" slots available: %d\n", REMAINING_AVAIL_SLOTS);\
+ } \
+ \
+ /* Push the info, starting with the registers. */ \
+ DEBUG_PRINT1 ("\n"); \
+ \
+ if (1) \
+ for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \
+ this_reg++) \
+ { \
+ DEBUG_PRINT2 (" Pushing reg: %lu\n", this_reg); \
+ DEBUG_STATEMENT (num_regs_pushed++); \
+ \
+ DEBUG_PRINT2 (" start: %p\n", regstart[this_reg]); \
+ PUSH_FAILURE_POINTER (regstart[this_reg]); \
+ \
+ DEBUG_PRINT2 (" end: %p\n", regend[this_reg]); \
+ PUSH_FAILURE_POINTER (regend[this_reg]); \
+ \
+ DEBUG_PRINT2 (" info: %p\n ", \
+ reg_info[this_reg].word.pointer); \
+ DEBUG_PRINT2 (" match_null=%d", \
+ REG_MATCH_NULL_STRING_P (reg_info[this_reg])); \
+ DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg])); \
+ DEBUG_PRINT2 (" matched_something=%d", \
+ MATCHED_SOMETHING (reg_info[this_reg])); \
+ DEBUG_PRINT2 (" ever_matched=%d", \
+ EVER_MATCHED_SOMETHING (reg_info[this_reg])); \
+ DEBUG_PRINT1 ("\n"); \
+ PUSH_FAILURE_ELT (reg_info[this_reg].word); \
+ } \
+ \
+ DEBUG_PRINT2 (" Pushing low active reg: %ld\n", lowest_active_reg);\
+ PUSH_FAILURE_INT (lowest_active_reg); \
+ \
+ DEBUG_PRINT2 (" Pushing high active reg: %ld\n", highest_active_reg);\
+ PUSH_FAILURE_INT (highest_active_reg); \
+ \
+ DEBUG_PRINT2 (" Pushing pattern %p:\n", pattern_place); \
+ DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend); \
+ PUSH_FAILURE_POINTER (pattern_place); \
+ \
+ DEBUG_PRINT2 (" Pushing string %p: `", string_place); \
+ DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, \
+ size2); \
+ DEBUG_PRINT1 ("'\n"); \
+ PUSH_FAILURE_POINTER (string_place); \
+ \
+ DEBUG_PRINT2 (" Pushing failure id: %u\n", failure_id); \
+ DEBUG_PUSH (failure_id); \
+ } while (0)
+
+# ifndef DEFINED_ONCE
+/* This is the number of items that are pushed and popped on the stack
+ for each register. */
+# define NUM_REG_ITEMS 3
+
+/* Individual items aside from the registers. */
+# ifdef DEBUG
+# define NUM_NONREG_ITEMS 5 /* Includes failure point id. */
+# else
+# define NUM_NONREG_ITEMS 4
+# endif
+
+/* We push at most this many items on the stack. */
+/* We used to use (num_regs - 1), which is the number of registers
+ this regexp will save; but that was changed to 5
+ to avoid stack overflow for a regexp with lots of parens. */
+# define MAX_FAILURE_ITEMS (5 * NUM_REG_ITEMS + NUM_NONREG_ITEMS)
+
+/* We actually push this many items. */
+# define NUM_FAILURE_ITEMS \
+ (((0 \
+ ? 0 : highest_active_reg - lowest_active_reg + 1) \
+ * NUM_REG_ITEMS) \
+ + NUM_NONREG_ITEMS)
+
+/* How many items can still be added to the stack without overflowing it. */
+# define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail)
+# endif /* not DEFINED_ONCE */
+
+
+/* Pops what PUSH_FAIL_STACK pushes.
+
+ We restore into the parameters, all of which should be lvalues:
+ STR -- the saved data position.
+ PAT -- the saved pattern position.
+ LOW_REG, HIGH_REG -- the highest and lowest active registers.
+ REGSTART, REGEND -- arrays of string positions.
+ REG_INFO -- array of information about each subexpression.
+
+ Also assumes the variables `fail_stack' and (if debugging), `bufp',
+ `pend', `string1', `size1', `string2', and `size2'. */
+# define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\
+{ \
+ DEBUG_STATEMENT (unsigned failure_id;) \
+ active_reg_t this_reg; \
+ const UCHAR_T *string_temp; \
+ \
+ assert (!FAIL_STACK_EMPTY ()); \
+ \
+ /* Remove failure points and point to how many regs pushed. */ \
+ DEBUG_PRINT1 ("POP_FAILURE_POINT:\n"); \
+ DEBUG_PRINT2 (" Before pop, next avail: %d\n", fail_stack.avail); \
+ DEBUG_PRINT2 (" size: %d\n", fail_stack.size); \
+ \
+ assert (fail_stack.avail >= NUM_NONREG_ITEMS); \
+ \
+ DEBUG_POP (&failure_id); \
+ DEBUG_PRINT2 (" Popping failure id: %u\n", failure_id); \
+ \
+ /* If the saved string location is NULL, it came from an \
+ on_failure_keep_string_jump opcode, and we want to throw away the \
+ saved NULL, thus retaining our current position in the string. */ \
+ string_temp = POP_FAILURE_POINTER (); \
+ if (string_temp != NULL) \
+ str = (const CHAR_T *) string_temp; \
+ \
+ DEBUG_PRINT2 (" Popping string %p: `", str); \
+ DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \
+ DEBUG_PRINT1 ("'\n"); \
+ \
+ pat = (UCHAR_T *) POP_FAILURE_POINTER (); \
+ DEBUG_PRINT2 (" Popping pattern %p:\n", pat); \
+ DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \
+ \
+ /* Restore register info. */ \
+ high_reg = (active_reg_t) POP_FAILURE_INT (); \
+ DEBUG_PRINT2 (" Popping high active reg: %ld\n", high_reg); \
+ \
+ low_reg = (active_reg_t) POP_FAILURE_INT (); \
+ DEBUG_PRINT2 (" Popping low active reg: %ld\n", low_reg); \
+ \
+ if (1) \
+ for (this_reg = high_reg; this_reg >= low_reg; this_reg--) \
+ { \
+ DEBUG_PRINT2 (" Popping reg: %ld\n", this_reg); \
+ \
+ reg_info[this_reg].word = POP_FAILURE_ELT (); \
+ DEBUG_PRINT2 (" info: %p\n", \
+ reg_info[this_reg].word.pointer); \
+ \
+ regend[this_reg] = (const CHAR_T *) POP_FAILURE_POINTER (); \
+ DEBUG_PRINT2 (" end: %p\n", regend[this_reg]); \
+ \
+ regstart[this_reg] = (const CHAR_T *) POP_FAILURE_POINTER (); \
+ DEBUG_PRINT2 (" start: %p\n", regstart[this_reg]); \
+ } \
+ else \
+ { \
+ for (this_reg = highest_active_reg; this_reg > high_reg; this_reg--) \
+ { \
+ reg_info[this_reg].word.integer = 0; \
+ regend[this_reg] = 0; \
+ regstart[this_reg] = 0; \
+ } \
+ highest_active_reg = high_reg; \
+ } \
+ \
+ set_regs_matched_done = 0; \
+ DEBUG_STATEMENT (nfailure_points_popped++); \
+} /* POP_FAILURE_POINT */
+
+/* Structure for per-register (a.k.a. per-group) information.
+ Other register information, such as the
+ starting and ending positions (which are addresses), and the list of
+ inner groups (which is a bits list) are maintained in separate
+ variables.
+
+ We are making a (strictly speaking) nonportable assumption here: that
+ the compiler will pack our bit fields into something that fits into
+ the type of `word', i.e., is something that fits into one item on the
+ failure stack. */
+
+
+/* Declarations and macros for re_match_2. */
+
+typedef union
+{
+ PREFIX(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;
+} PREFIX(register_info_type);
+
+# ifndef DEFINED_ONCE
+# define REG_MATCH_NULL_STRING_P(R) ((R).bits.match_null_string_p)
+# define IS_ACTIVE(R) ((R).bits.is_active)
+# define MATCHED_SOMETHING(R) ((R).bits.matched_something)
+# define EVER_MATCHED_SOMETHING(R) ((R).bits.ever_matched_something)
+
+
+/* Call this when have matched a real character; it sets `matched' flags
+ for the subexpressions which we are currently inside. Also records
+ that those subexprs have matched. */
+# define SET_REGS_MATCHED() \
+ do \
+ { \
+ if (!set_regs_matched_done) \
+ { \
+ active_reg_t r; \
+ set_regs_matched_done = 1; \
+ for (r = lowest_active_reg; r <= highest_active_reg; r++) \
+ { \
+ MATCHED_SOMETHING (reg_info[r]) \
+ = EVER_MATCHED_SOMETHING (reg_info[r]) \
+ = 1; \
+ } \
+ } \
+ } \
+ while (0)
+# endif /* not DEFINED_ONCE */
+
+/* Registers are set to a sentinel when they haven't yet matched. */
+static CHAR_T PREFIX(reg_unset_dummy);
+# define REG_UNSET_VALUE (&PREFIX(reg_unset_dummy))
+# define REG_UNSET(e) ((e) == REG_UNSET_VALUE)
+
+/* Subroutine declarations and macros for regex_compile. */
+static void PREFIX(store_op1) (re_opcode_t op, UCHAR_T *loc, int arg);
+static void PREFIX(store_op2) (re_opcode_t op, UCHAR_T *loc,
+ int arg1, int arg2);
+static void PREFIX(insert_op1) (re_opcode_t op, UCHAR_T *loc,
+ int arg, UCHAR_T *end);
+static void PREFIX(insert_op2) (re_opcode_t op, UCHAR_T *loc,
+ int arg1, int arg2, UCHAR_T *end);
+static boolean PREFIX(at_begline_loc_p) (const CHAR_T *pattern,
+ const CHAR_T *p,
+ reg_syntax_t syntax);
+static boolean PREFIX(at_endline_loc_p) (const CHAR_T *p,
+ const CHAR_T *pend,
+ reg_syntax_t syntax);
+# ifdef WCHAR
+static reg_errcode_t wcs_compile_range (CHAR_T range_start,
+ const CHAR_T **p_ptr,
+ const CHAR_T *pend,
+ char *translate,
+ reg_syntax_t syntax,
+ UCHAR_T *b,
+ CHAR_T *char_set);
+static void insert_space (int num, CHAR_T *loc, CHAR_T *end);
+# else /* BYTE */
+static reg_errcode_t byte_compile_range (unsigned int range_start,
+ const char **p_ptr,
+ const char *pend,
+ char *translate,
+ reg_syntax_t syntax,
+ unsigned char *b);
+# endif /* WCHAR */
+
+/* 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'). */
+/* ifdef MBS_SUPPORT, we translate only if character <= 0xff,
+ because it is impossible to allocate 4GB array for some encodings
+ which have 4 byte character_set like UCS4. */
+# ifndef PATFETCH
+# ifdef WCHAR
+# define PATFETCH(c) \
+ do {if (p == pend) return REG_EEND; \
+ c = (UCHAR_T) *p++; \
+ if (translate && (c <= 0xff)) c = (UCHAR_T) translate[c]; \
+ } while (0)
+# else /* BYTE */
+# define PATFETCH(c) \
+ do {if (p == pend) return REG_EEND; \
+ c = (unsigned char) *p++; \
+ if (translate) c = (unsigned char) translate[c]; \
+ } while (0)
+# endif /* WCHAR */
+# endif
+
+/* Fetch the next character in the uncompiled pattern, with no
+ translation. */
+# define PATFETCH_RAW(c) \
+ do {if (p == pend) return REG_EEND; \
+ c = (UCHAR_T) *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. */
+/* ifdef MBS_SUPPORT, we translate only if character <= 0xff,
+ because it is impossible to allocate 4GB array for some encodings
+ which have 4 byte character_set like UCS4. */
+
+# ifndef TRANSLATE
+# ifdef WCHAR
+# define TRANSLATE(d) \
+ ((translate && ((UCHAR_T) (d)) <= 0xff) \
+ ? (char) translate[(unsigned char) (d)] : (d))
+# else /* BYTE */
+# define TRANSLATE(d) \
+ (translate ? (char) translate[(unsigned char) (d)] : (d))
+# endif /* WCHAR */
+# endif
+
+
+/* Macros for outputting the compiled pattern into `buffer'. */
+
+/* If the buffer isn't allocated when it comes in, use this. */
+# define INIT_BUF_SIZE (32 * sizeof(UCHAR_T))
+
+/* Make sure we have at least N more bytes of space in buffer. */
+# ifdef WCHAR
+# define GET_BUFFER_SPACE(n) \
+ while (((unsigned long)b - (unsigned long)COMPILED_BUFFER_VAR \
+ + (n)*sizeof(CHAR_T)) > bufp->allocated) \
+ EXTEND_BUFFER ()
+# else /* BYTE */
+# define GET_BUFFER_SPACE(n) \
+ while ((unsigned long) (b - bufp->buffer + (n)) > bufp->allocated) \
+ EXTEND_BUFFER ()
+# endif /* WCHAR */
+
+/* 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++ = (UCHAR_T) (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++ = (UCHAR_T) (c1); \
+ *b++ = (UCHAR_T) (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++ = (UCHAR_T) (c1); \
+ *b++ = (UCHAR_T) (c2); \
+ *b++ = (UCHAR_T) (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) \
+ PREFIX(store_op1) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)))
+
+/* Likewise, for a two-argument jump. */
+# define STORE_JUMP2(op, loc, to, arg) \
+ PREFIX(store_op2) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)), arg)
+
+/* Like `STORE_JUMP', but for inserting. Assume `b' is the buffer end. */
+# define INSERT_JUMP(op, loc, to) \
+ PREFIX(insert_op1) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)), b)
+
+/* Like `STORE_JUMP2', but for inserting. Assume `b' is the buffer end. */
+# define INSERT_JUMP2(op, loc, to, arg) \
+ PREFIX(insert_op2) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)),\
+ arg, b)
+
+/* This is not an arbitrary limit: the arguments which represent offsets
+ into the pattern are two bytes long. So if 2^16 bytes turns out to
+ be too small, many things would have to change. */
+/* Any other compiler which, like MSC, has allocation limit below 2^16
+ bytes will have to use approach similar to what was done below for
+ MSC and drop MAX_BUF_SIZE a bit. Otherwise you may end up
+ reallocating to 0 bytes. Such thing is not going to work too well.
+ You have been warned!! */
+# ifndef DEFINED_ONCE
+# if defined _MSC_VER && !defined WIN32
+/* Microsoft C 16-bit versions limit malloc to approx 65512 bytes.
+ The REALLOC define eliminates a flurry of conversion warnings,
+ but is not required. */
+# define MAX_BUF_SIZE 65500L
+# define REALLOC(p,s) realloc ((p), (size_t) (s))
+# else
+# define MAX_BUF_SIZE (1L << 16)
+# define REALLOC(p,s) realloc ((p), (s))
+# endif
+
+/* Extend the buffer by twice its current size via realloc and
+ reset the pointers that pointed into the old block to point to the
+ correct places in the new one. If extending the buffer results in it
+ being larger than MAX_BUF_SIZE, then flag memory exhausted. */
+# if __BOUNDED_POINTERS__
+# define SET_HIGH_BOUND(P) (__ptrhigh (P) = __ptrlow (P) + bufp->allocated)
+# define MOVE_BUFFER_POINTER(P) \
+ (__ptrlow (P) += incr, SET_HIGH_BOUND (P), __ptrvalue (P) += incr)
+# define ELSE_EXTEND_BUFFER_HIGH_BOUND \
+ else \
+ { \
+ SET_HIGH_BOUND (b); \
+ SET_HIGH_BOUND (begalt); \
+ if (fixup_alt_jump) \
+ SET_HIGH_BOUND (fixup_alt_jump); \
+ if (laststart) \
+ SET_HIGH_BOUND (laststart); \
+ if (pending_exact) \
+ SET_HIGH_BOUND (pending_exact); \
+ }
+# else
+# define MOVE_BUFFER_POINTER(P) (P) += incr
+# define ELSE_EXTEND_BUFFER_HIGH_BOUND
+# endif
+# endif /* not DEFINED_ONCE */
+
+# ifdef WCHAR
+# define EXTEND_BUFFER() \
+ do { \
+ UCHAR_T *old_buffer = COMPILED_BUFFER_VAR; \
+ int wchar_count; \
+ if (bufp->allocated + sizeof(UCHAR_T) > MAX_BUF_SIZE) \
+ return REG_ESIZE; \
+ bufp->allocated <<= 1; \
+ if (bufp->allocated > MAX_BUF_SIZE) \
+ bufp->allocated = MAX_BUF_SIZE; \
+ /* How many characters the new buffer can have? */ \
+ wchar_count = bufp->allocated / sizeof(UCHAR_T); \
+ if (wchar_count == 0) wchar_count = 1; \
+ /* Truncate the buffer to CHAR_T align. */ \
+ bufp->allocated = wchar_count * sizeof(UCHAR_T); \
+ RETALLOC (COMPILED_BUFFER_VAR, wchar_count, UCHAR_T); \
+ bufp->buffer = (char*)COMPILED_BUFFER_VAR; \
+ if (COMPILED_BUFFER_VAR == NULL) \
+ return REG_ESPACE; \
+ /* If the buffer moved, move all the pointers into it. */ \
+ if (old_buffer != COMPILED_BUFFER_VAR) \
+ { \
+ int incr = COMPILED_BUFFER_VAR - old_buffer; \
+ MOVE_BUFFER_POINTER (b); \
+ MOVE_BUFFER_POINTER (begalt); \
+ if (fixup_alt_jump) \
+ MOVE_BUFFER_POINTER (fixup_alt_jump); \
+ if (laststart) \
+ MOVE_BUFFER_POINTER (laststart); \
+ if (pending_exact) \
+ MOVE_BUFFER_POINTER (pending_exact); \
+ } \
+ ELSE_EXTEND_BUFFER_HIGH_BOUND \
+ } while (0)
+# else /* BYTE */
+# define EXTEND_BUFFER() \
+ do { \
+ UCHAR_T *old_buffer = COMPILED_BUFFER_VAR; \
+ 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 = REALLOC (COMPILED_BUFFER_VAR, bufp->allocated); \
+ if (COMPILED_BUFFER_VAR == NULL) \
+ return REG_ESPACE; \
+ /* If the buffer moved, move all the pointers into it. */ \
+ if (old_buffer != COMPILED_BUFFER_VAR) \
+ { \
+ int incr = COMPILED_BUFFER_VAR - old_buffer; \
+ MOVE_BUFFER_POINTER (b); \
+ MOVE_BUFFER_POINTER (begalt); \
+ if (fixup_alt_jump) \
+ MOVE_BUFFER_POINTER (fixup_alt_jump); \
+ if (laststart) \
+ MOVE_BUFFER_POINTER (laststart); \
+ if (pending_exact) \
+ MOVE_BUFFER_POINTER (pending_exact); \
+ } \
+ ELSE_EXTEND_BUFFER_HIGH_BOUND \
+ } while (0)
+# endif /* WCHAR */
+
+# ifndef DEFINED_ONCE
+/* Since we have one byte reserved for the register number argument to
+ {start,stop}_memory, the maximum number of groups we can report
+ things about is what fits in that byte. */
+# define MAX_REGNUM 255
+
+/* But patterns can have more than `MAX_REGNUM' registers. We just
+ ignore the excess. */
+typedef unsigned regnum_t;
+
+
+/* Macros for the compile stack. */
+
+/* Since offsets can go either forwards or backwards, this type needs to
+ be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1. */
+/* int may be not enough when sizeof(int) == 2. */
+typedef long pattern_offset_t;
+
+typedef struct
+{
+ pattern_offset_t begalt_offset;
+ pattern_offset_t fixup_alt_jump;
+ pattern_offset_t inner_group_offset;
+ pattern_offset_t laststart_offset;
+ regnum_t regnum;
+} compile_stack_elt_t;
+
+
+typedef struct
+{
+ compile_stack_elt_t *stack;
+ unsigned size;
+ unsigned avail; /* Offset of next open position. */
+} compile_stack_type;
+
+
+# define INIT_COMPILE_STACK_SIZE 32
+
+# define COMPILE_STACK_EMPTY (compile_stack.avail == 0)
+# define COMPILE_STACK_FULL (compile_stack.avail == compile_stack.size)
+
+/* The next available element. */
+# define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail])
+
+# endif /* not DEFINED_ONCE */
+
+/* Set the bit for character C in a list. */
+# ifndef DEFINED_ONCE
+# define SET_LIST_BIT(c) \
+ (b[((unsigned char) (c)) / BYTEWIDTH] \
+ |= 1 << (((unsigned char) c) % BYTEWIDTH))
+# endif /* DEFINED_ONCE */
+
+/* Get the next unsigned number in the uncompiled pattern. */
+# define GET_UNSIGNED_NUMBER(num) \
+ { \
+ while (p != pend) \
+ { \
+ PATFETCH (c); \
+ if (c < '0' || c > '9') \
+ break; \
+ if (num <= RE_DUP_MAX) \
+ { \
+ if (num < 0) \
+ num = 0; \
+ num = num * 10 + c - '0'; \
+ } \
+ } \
+ }
+
+# ifndef DEFINED_ONCE
+# if defined _LIBC || WIDE_CHAR_SUPPORT
+/* The GNU C library provides support for user-defined character classes
+ and the functions from ISO C amendement 1. */
+# ifdef CHARCLASS_NAME_MAX
+# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
+# else
+/* This shouldn't happen but some implementation might still have this
+ problem. Use a reasonable default value. */
+# define CHAR_CLASS_MAX_LENGTH 256
+# endif
+
+# ifdef _LIBC
+# define IS_CHAR_CLASS(string) __wctype (string)
+# else
+# define IS_CHAR_CLASS(string) wctype (string)
+# endif
+# else
+# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */
+
+# define IS_CHAR_CLASS(string) \
+ (STREQ (string, "alpha") || STREQ (string, "upper") \
+ || STREQ (string, "lower") || STREQ (string, "digit") \
+ || STREQ (string, "alnum") || STREQ (string, "xdigit") \
+ || STREQ (string, "space") || STREQ (string, "print") \
+ || STREQ (string, "punct") || STREQ (string, "graph") \
+ || STREQ (string, "cntrl") || STREQ (string, "blank"))
+# endif
+# endif /* DEFINED_ONCE */
+
+# ifndef MATCH_MAY_ALLOCATE
+
+/* If we cannot allocate large objects within re_match_2_internal,
+ we make the fail stack and register vectors global.
+ The fail stack, we grow to the maximum size when a regexp
+ is compiled.
+ The register vectors, we adjust in size each time we
+ compile a regexp, according to the number of registers it needs. */
+
+static PREFIX(fail_stack_type) fail_stack;
+
+/* Size with which the following vectors are currently allocated.
+ That is so we can make them bigger as needed,
+ but never make them smaller. */
+# ifdef DEFINED_ONCE
+static int regs_allocated_size;
+
+static const char ** regstart, ** regend;
+static const char ** old_regstart, ** old_regend;
+static const char **best_regstart, **best_regend;
+static const char **reg_dummy;
+# endif /* DEFINED_ONCE */
+
+static PREFIX(register_info_type) *PREFIX(reg_info);
+static PREFIX(register_info_type) *PREFIX(reg_info_dummy);
+
+/* Make the register vectors big enough for NUM_REGS registers,
+ but don't make them smaller. */
+
+static void
+PREFIX(regex_grow_registers) (int num_regs)
+{
+ if (num_regs > regs_allocated_size)
+ {
+ RETALLOC_IF (regstart, num_regs, const char *);
+ RETALLOC_IF (regend, num_regs, const char *);
+ RETALLOC_IF (old_regstart, num_regs, const char *);
+ RETALLOC_IF (old_regend, num_regs, const char *);
+ RETALLOC_IF (best_regstart, num_regs, const char *);
+ RETALLOC_IF (best_regend, num_regs, const char *);
+ RETALLOC_IF (PREFIX(reg_info), num_regs, PREFIX(register_info_type));
+ RETALLOC_IF (reg_dummy, num_regs, const char *);
+ RETALLOC_IF (PREFIX(reg_info_dummy), num_regs, PREFIX(register_info_type));
+
+ regs_allocated_size = num_regs;
+ }
+}
+
+# endif /* not MATCH_MAY_ALLOCATE */
+
+# ifndef DEFINED_ONCE
+static boolean group_in_compile_stack (compile_stack_type
+ compile_stack,
+ regnum_t regnum);
+# endif /* not DEFINED_ONCE */
+
+/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX.
+ Returns one of error codes defined in `regex.h', or zero for success.
+
+ Assumes the `allocated' (and perhaps `buffer') and `translate'
+ fields are set in BUFP on entry.
+
+ If it succeeds, results are put in BUFP (if it returns an error, the
+ contents of BUFP are undefined):
+ `buffer' is the compiled pattern;
+ `syntax' is set to SYNTAX;
+ `used' is set to the length of the compiled pattern;
+ `fastmap_accurate' is zero;
+ `re_nsub' is the number of subexpressions in PATTERN;
+ `not_bol' and `not_eol' are zero;
+
+ The `fastmap' and `newline_anchor' fields are neither
+ examined nor set. */
+
+/* Return, freeing storage we allocated. */
+# ifdef WCHAR
+# define FREE_STACK_RETURN(value) \
+ return (free(pattern), free(mbs_offset), free(is_binary), free (compile_stack.stack), value)
+# else
+# define FREE_STACK_RETURN(value) \
+ return (free (compile_stack.stack), value)
+# endif /* WCHAR */
+
+static reg_errcode_t
+PREFIX(regex_compile) (const char *ARG_PREFIX(pattern),
+ size_t ARG_PREFIX(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 UCHAR_T c, c1;
+
+#ifdef WCHAR
+ /* A temporary space to keep wchar_t pattern and compiled pattern. */
+ CHAR_T *pattern, *COMPILED_BUFFER_VAR;
+ size_t size;
+ /* offset buffer for optimization. See convert_mbs_to_wc. */
+ int *mbs_offset = NULL;
+ /* It hold whether each wchar_t is binary data or not. */
+ char *is_binary = NULL;
+ /* A flag whether exactn is handling binary data or not. */
+ char is_exactn_bin = FALSE;
+#endif /* WCHAR */
+
+ /* A random temporary spot in PATTERN. */
+ const CHAR_T *p1;
+
+ /* Points to the end of the buffer, where we should append. */
+ register UCHAR_T *b;
+
+ /* Keeps track of unclosed groups. */
+ compile_stack_type compile_stack;
+
+ /* Points to the current (ending) position in the pattern. */
+#ifdef WCHAR
+ const CHAR_T *p;
+ const CHAR_T *pend;
+#else /* BYTE */
+ const CHAR_T *p = pattern;
+ const CHAR_T *pend = pattern + size;
+#endif /* WCHAR */
+
+ /* How to translate the characters in the pattern. */
+ RE_TRANSLATE_TYPE translate = bufp->translate;
+
+ /* Address of the count-byte of the most recently inserted `exactn'
+ command. This makes it possible to tell if a new exact-match
+ character can be added to that command or if the character requires
+ a new `exactn' command. */
+ UCHAR_T *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. */
+ UCHAR_T *laststart = 0;
+
+ /* Address of beginning of regexp, or inside of last group. */
+ UCHAR_T *begalt;
+
+ /* 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. */
+ UCHAR_T *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 WCHAR
+ /* Initialize the wchar_t PATTERN and offset_buffer. */
+ p = pend = pattern = TALLOC(csize + 1, CHAR_T);
+ mbs_offset = TALLOC(csize + 1, int);
+ is_binary = TALLOC(csize + 1, char);
+ if (pattern == NULL || mbs_offset == NULL || is_binary == NULL)
+ {
+ free(pattern);
+ free(mbs_offset);
+ free(is_binary);
+ return REG_ESPACE;
+ }
+ pattern[csize] = L'\0'; /* sentinel */
+ size = convert_mbs_to_wcs(pattern, cpattern, csize, mbs_offset, is_binary);
+ pend = p + size;
+ if (size < 0)
+ {
+ free(pattern);
+ free(mbs_offset);
+ free(is_binary);
+ return REG_BADPAT;
+ }
+#endif
+
+#ifdef DEBUG
+ DEBUG_PRINT1 ("\nCompiling pattern: ");
+ if (debug)
+ {
+ unsigned debug_count;
+
+ for (debug_count = 0; debug_count < size; debug_count++)
+ PUT_CHAR (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)
+ {
+#ifdef WCHAR
+ free(pattern);
+ free(mbs_offset);
+ free(is_binary);
+#endif
+ 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. */
+#ifdef WCHAR
+ /* Free bufp->buffer and allocate an array for wchar_t pattern
+ buffer. */
+ free(bufp->buffer);
+ COMPILED_BUFFER_VAR = TALLOC (INIT_BUF_SIZE/sizeof(UCHAR_T),
+ UCHAR_T);
+#else
+ RETALLOC (COMPILED_BUFFER_VAR, INIT_BUF_SIZE, UCHAR_T);
+#endif /* WCHAR */
+ }
+ else
+ { /* Caller did not allocate a buffer. Do it for them. */
+ COMPILED_BUFFER_VAR = TALLOC (INIT_BUF_SIZE / sizeof(UCHAR_T),
+ UCHAR_T);
+ }
+
+ if (!COMPILED_BUFFER_VAR) FREE_STACK_RETURN (REG_ESPACE);
+#ifdef WCHAR
+ bufp->buffer = (char*)COMPILED_BUFFER_VAR;
+#endif /* WCHAR */
+ bufp->allocated = INIT_BUF_SIZE;
+ }
+#ifdef WCHAR
+ else
+ COMPILED_BUFFER_VAR = (UCHAR_T*) bufp->buffer;
+#endif
+
+ begalt = b = COMPILED_BUFFER_VAR;
+
+ /* 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. */
+ || PREFIX(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. */
+ || PREFIX(at_endline_loc_p) (p, pend, syntax))
+ BUF_PUSH (endline);
+ else
+ goto normal_char;
+ }
+ break;
+
+
+ case '+':
+ case '?':
+ if ((syntax & RE_BK_PLUS_QM)
+ || (syntax & RE_LIMITED_OPS))
+ goto normal_char;
+ handle_plus:
+ case '*':
+ /* If there is no previous pattern... */
+ if (!laststart)
+ {
+ if (syntax & RE_CONTEXT_INVALID_OPS)
+ FREE_STACK_RETURN (REG_BADRPT);
+ else if (!(syntax & RE_CONTEXT_INDEP_OPS))
+ goto normal_char;
+ }
+
+ {
+ /* Are we optimizing this jump? */
+ boolean keep_string_p = false;
+
+ /* 1 means zero (many) matches is allowed. */
+ char zero_times_ok = 0, many_times_ok = 0;
+
+ /* If there is a sequence of repetition chars, collapse it
+ down to just one (the right one). We can't combine
+ interval operators with these because of, e.g., `a{2}*',
+ which should only match an even number of `a's. */
+
+ for (;;)
+ {
+ zero_times_ok |= c != '+';
+ many_times_ok |= c != '?';
+
+ if (p == pend)
+ break;
+
+ PATFETCH (c);
+
+ if (c == '*'
+ || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?')))
+ ;
+
+ else if (syntax & RE_BK_PLUS_QM && c == '\\')
+ {
+ if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
+
+ PATFETCH (c1);
+ if (!(c1 == '+' || c1 == '?'))
+ {
+ PATUNFETCH;
+ PATUNFETCH;
+ break;
+ }
+
+ c = c1;
+ }
+ else
+ {
+ PATUNFETCH;
+ break;
+ }
+
+ /* If we get here, we found another repeat character. */
+ }
+
+ /* Star, etc. applied to an empty pattern is equivalent
+ to an empty pattern. */
+ if (!laststart)
+ break;
+
+ /* Now we know whether or not zero matches is allowed
+ and also whether or not two or more matches is allowed. */
+ if (many_times_ok)
+ { /* More than one repetition is allowed, so put in at the
+ end a backward relative jump from `b' to before the next
+ jump we're going to put in below (which jumps from
+ laststart to after this jump).
+
+ But if we are at the `*' in the exact sequence `.*\n',
+ insert an unconditional jump backwards to the .,
+ instead of the beginning of the loop. This way we only
+ push a failure point once, instead of every time
+ through the loop. */
+ assert (p - 1 > pattern);
+
+ /* Allocate the space for the jump. */
+ GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE);
+
+ /* 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 -
+ (1 + OFFSET_ADDRESS_SIZE));
+
+ /* We've added more stuff to the buffer. */
+ b += 1 + OFFSET_ADDRESS_SIZE;
+ }
+
+ /* On failure, jump from laststart to b + 3, which will be the
+ end of the buffer after this jump is inserted. */
+ /* ifdef WCHAR, 'b + 1 + OFFSET_ADDRESS_SIZE' instead of
+ 'b + 3'. */
+ GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE);
+ INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump
+ : on_failure_jump,
+ laststart, b + 1 + OFFSET_ADDRESS_SIZE);
+ pending_exact = 0;
+ b += 1 + OFFSET_ADDRESS_SIZE;
+
+ 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 (1 + OFFSET_ADDRESS_SIZE);
+ INSERT_JUMP (dummy_failure_jump, laststart, laststart +
+ 2 + 2 * OFFSET_ADDRESS_SIZE);
+ b += 1 + OFFSET_ADDRESS_SIZE;
+ }
+ }
+ break;
+
+
+ case '.':
+ laststart = b;
+ BUF_PUSH (anychar);
+ break;
+
+
+ case '[':
+ {
+ boolean had_char_class = false;
+#ifdef WCHAR
+ CHAR_T range_start = 0xffffffff;
+#else
+ unsigned int range_start = 0xffffffff;
+#endif
+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+#ifdef WCHAR
+ /* We assume a charset(_not) structure as a wchar_t array.
+ charset[0] = (re_opcode_t) charset(_not)
+ charset[1] = l (= length of char_classes)
+ charset[2] = m (= length of collating_symbols)
+ charset[3] = n (= length of equivalence_classes)
+ charset[4] = o (= length of char_ranges)
+ charset[5] = p (= length of chars)
+
+ charset[6] = char_class (wctype_t)
+ charset[6+CHAR_CLASS_SIZE] = char_class (wctype_t)
+ ...
+ charset[l+5] = char_class (wctype_t)
+
+ charset[l+6] = collating_symbol (wchar_t)
+ ...
+ charset[l+m+5] = collating_symbol (wchar_t)
+ ifdef _LIBC we use the index if
+ _NL_COLLATE_SYMB_EXTRAMB instead of
+ wchar_t string.
+
+ charset[l+m+6] = equivalence_classes (wchar_t)
+ ...
+ charset[l+m+n+5] = equivalence_classes (wchar_t)
+ ifdef _LIBC we use the index in
+ _NL_COLLATE_WEIGHT instead of
+ wchar_t string.
+
+ charset[l+m+n+6] = range_start
+ charset[l+m+n+7] = range_end
+ ...
+ charset[l+m+n+2o+4] = range_start
+ charset[l+m+n+2o+5] = range_end
+ ifdef _LIBC we use the value looked up
+ in _NL_COLLATE_COLLSEQ instead of
+ wchar_t character.
+
+ charset[l+m+n+2o+6] = char
+ ...
+ charset[l+m+n+2o+p+5] = char
+
+ */
+
+ /* We need at least 6 spaces: the opcode, the length of
+ char_classes, the length of collating_symbols, the length of
+ equivalence_classes, the length of char_ranges, the length of
+ chars. */
+ GET_BUFFER_SPACE (6);
+
+ /* Save b as laststart. And We use laststart as the pointer
+ to the first element of the charset here.
+ In other words, laststart[i] indicates charset[i]. */
+ 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++;
+
+ /* Push the length of char_classes, the length of
+ collating_symbols, the length of equivalence_classes, the
+ length of char_ranges and the length of chars. */
+ BUF_PUSH_3 (0, 0, 0);
+ BUF_PUSH_2 (0, 0);
+
+ /* Remember the first position in the bracket expression. */
+ p1 = p;
+
+ /* charset_not matches newline according to a syntax bit. */
+ if ((re_opcode_t) b[-6] == charset_not
+ && (syntax & RE_HAT_LISTS_NOT_NEWLINE))
+ {
+ BUF_PUSH('\n');
+ laststart[5]++; /* Update the length of characters */
+ }
+
+ /* Read in characters and ranges, setting map bits. */
+ for (;;)
+ {
+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+ PATFETCH (c);
+
+ /* \ might escape characters inside [...] and [^...]. */
+ if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\')
+ {
+ if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
+
+ PATFETCH (c1);
+ BUF_PUSH(c1);
+ laststart[5]++; /* Update the length of chars */
+ range_start = c1;
+ continue;
+ }
+
+ /* Could be the end of the bracket expression. If it's
+ not (i.e., when the bracket expression is `[]' so
+ far), the ']' character bit gets set way below. */
+ if (c == ']' && p != p1 + 1)
+ break;
+
+ /* Look ahead to see if it's a range when the last thing
+ was a character class. */
+ if (had_char_class && c == '-' && *p != ']')
+ FREE_STACK_RETURN (REG_ERANGE);
+
+ /* Look ahead to see if it's a range when the last thing
+ was a character: if this is a hyphen not at the
+ beginning or the end of a list, then it's the range
+ operator. */
+ if (c == '-'
+ && !(p - 2 >= pattern && p[-2] == '[')
+ && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^')
+ && *p != ']')
+ {
+ reg_errcode_t ret;
+ /* Allocate the space for range_start and range_end. */
+ GET_BUFFER_SPACE (2);
+ /* Update the pointer to indicate end of buffer. */
+ b += 2;
+ ret = wcs_compile_range (range_start, &p, pend, translate,
+ syntax, b, laststart);
+ if (ret != REG_NOERROR) FREE_STACK_RETURN (ret);
+ range_start = 0xffffffff;
+ }
+ else if (p[0] == '-' && p[1] != ']')
+ { /* This handles ranges made up of characters only. */
+ reg_errcode_t ret;
+
+ /* Move past the `-'. */
+ PATFETCH (c1);
+ /* Allocate the space for range_start and range_end. */
+ GET_BUFFER_SPACE (2);
+ /* Update the pointer to indicate end of buffer. */
+ b += 2;
+ ret = wcs_compile_range (c, &p, pend, translate, syntax, b,
+ laststart);
+ if (ret != REG_NOERROR) FREE_STACK_RETURN (ret);
+ range_start = 0xffffffff;
+ }
+
+ /* See if we're at the beginning of a possible character
+ class. */
+ else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':')
+ { /* Leave room for the null. */
+ char str[CHAR_CLASS_MAX_LENGTH + 1];
+
+ PATFETCH (c);
+ c1 = 0;
+
+ /* If pattern is `[[:'. */
+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+ for (;;)
+ {
+ PATFETCH (c);
+ if ((c == ':' && *p == ']') || p == pend)
+ break;
+ if (c1 < CHAR_CLASS_MAX_LENGTH)
+ str[c1++] = c;
+ else
+ /* This is in any case an invalid class name. */
+ str[0] = '\0';
+ }
+ str[c1] = '\0';
+
+ /* If isn't a word bracketed by `[:' and `:]':
+ undo the ending character, the letters, and leave
+ the leading `:' and `[' (but store them as character). */
+ if (c == ':' && *p == ']')
+ {
+ wctype_t wt;
+ uintptr_t alignedp;
+
+ /* Query the character class as wctype_t. */
+ wt = IS_CHAR_CLASS (str);
+ if (wt == 0)
+ FREE_STACK_RETURN (REG_ECTYPE);
+
+ /* Throw away the ] at the end of the character
+ class. */
+ PATFETCH (c);
+
+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+ /* Allocate the space for character class. */
+ GET_BUFFER_SPACE(CHAR_CLASS_SIZE);
+ /* Update the pointer to indicate end of buffer. */
+ b += CHAR_CLASS_SIZE;
+ /* Move data which follow character classes
+ not to violate the data. */
+ insert_space(CHAR_CLASS_SIZE,
+ laststart + 6 + laststart[1],
+ b - 1);
+ alignedp = ((uintptr_t)(laststart + 6 + laststart[1])
+ + __alignof__(wctype_t) - 1)
+ & ~(uintptr_t)(__alignof__(wctype_t) - 1);
+ /* Store the character class. */
+ *((wctype_t*)alignedp) = wt;
+ /* Update length of char_classes */
+ laststart[1] += CHAR_CLASS_SIZE;
+
+ had_char_class = true;
+ }
+ else
+ {
+ c1++;
+ while (c1--)
+ PATUNFETCH;
+ BUF_PUSH ('[');
+ BUF_PUSH (':');
+ laststart[5] += 2; /* Update the length of characters */
+ range_start = ':';
+ had_char_class = false;
+ }
+ }
+ else if (syntax & RE_CHAR_CLASSES && c == '[' && (*p == '='
+ || *p == '.'))
+ {
+ CHAR_T str[128]; /* Should be large enough. */
+ CHAR_T delim = *p; /* '=' or '.' */
+# ifdef _LIBC
+ uint32_t nrules =
+ _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+# endif
+ PATFETCH (c);
+ c1 = 0;
+
+ /* If pattern is `[[=' or '[[.'. */
+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+ for (;;)
+ {
+ PATFETCH (c);
+ if ((c == delim && *p == ']') || p == pend)
+ break;
+ if (c1 < sizeof (str) - 1)
+ str[c1++] = c;
+ else
+ /* This is in any case an invalid class name. */
+ str[0] = '\0';
+ }
+ str[c1] = '\0';
+
+ if (c == delim && *p == ']' && str[0] != '\0')
+ {
+ unsigned int i, offset;
+ /* If we have no collation data we use the default
+ collation in which each character is in a class
+ by itself. It also means that ASCII is the
+ character set and therefore we cannot have character
+ with more than one byte in the multibyte
+ representation. */
+
+ /* If not defined _LIBC, we push the name and
+ `\0' for the sake of matching performance. */
+ int datasize = c1 + 1;
+
+# ifdef _LIBC
+ int32_t idx = 0;
+ if (nrules == 0)
+# endif
+ {
+ if (c1 != 1)
+ FREE_STACK_RETURN (REG_ECOLLATE);
+ }
+# ifdef _LIBC
+ else
+ {
+ const int32_t *table;
+ const int32_t *weights;
+ const int32_t *extra;
+ const int32_t *indirect;
+ wint_t *cp;
+
+ /* This #include defines a local function! */
+# include <locale/weightwc.h>
+
+ if(delim == '=')
+ {
+ /* We push the index for equivalence class. */
+ cp = (wint_t*)str;
+
+ table = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE,
+ _NL_COLLATE_TABLEWC);
+ weights = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE,
+ _NL_COLLATE_WEIGHTWC);
+ extra = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE,
+ _NL_COLLATE_EXTRAWC);
+ indirect = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE,
+ _NL_COLLATE_INDIRECTWC);
+
+ idx = findidx ((const wint_t**)&cp);
+ if (idx == 0 || cp < (wint_t*) str + c1)
+ /* This is no valid character. */
+ FREE_STACK_RETURN (REG_ECOLLATE);
+
+ str[0] = (wchar_t)idx;
+ }
+ else /* delim == '.' */
+ {
+ /* We push collation sequence value
+ for collating symbol. */
+ int32_t table_size;
+ const int32_t *symb_table;
+ const unsigned char *extra;
+ int32_t idx;
+ int32_t elem;
+ int32_t second;
+ int32_t hash;
+ char char_str[c1];
+
+ /* We have to convert the name to a single-byte
+ string. This is possible since the names
+ consist of ASCII characters and the internal
+ representation is UCS4. */
+ for (i = 0; i < c1; ++i)
+ char_str[i] = str[i];
+
+ table_size =
+ _NL_CURRENT_WORD (LC_COLLATE,
+ _NL_COLLATE_SYMB_HASH_SIZEMB);
+ symb_table = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE,
+ _NL_COLLATE_SYMB_TABLEMB);
+ extra = (const unsigned char *)
+ _NL_CURRENT (LC_COLLATE,
+ _NL_COLLATE_SYMB_EXTRAMB);
+
+ /* Locate the character in the hashing table. */
+ hash = elem_hash (char_str, c1);
+
+ idx = 0;
+ elem = hash % table_size;
+ second = hash % (table_size - 2);
+ while (symb_table[2 * elem] != 0)
+ {
+ /* First compare the hashing value. */
+ if (symb_table[2 * elem] == hash
+ && c1 == extra[symb_table[2 * elem + 1]]
+ && memcmp (char_str,
+ &extra[symb_table[2 * elem + 1]
+ + 1], c1) == 0)
+ {
+ /* Yep, this is the entry. */
+ idx = symb_table[2 * elem + 1];
+ idx += 1 + extra[idx];
+ break;
+ }
+
+ /* Next entry. */
+ elem += second;
+ }
+
+ if (symb_table[2 * elem] != 0)
+ {
+ /* Compute the index of the byte sequence
+ in the table. */
+ idx += 1 + extra[idx];
+ /* Adjust for the alignment. */
+ idx = (idx + 3) & ~3;
+
+ str[0] = (wchar_t) idx + 4;
+ }
+ else if (symb_table[2 * elem] == 0 && c1 == 1)
+ {
+ /* No valid character. Match it as a
+ single byte character. */
+ had_char_class = false;
+ BUF_PUSH(str[0]);
+ /* Update the length of characters */
+ laststart[5]++;
+ range_start = str[0];
+
+ /* Throw away the ] at the end of the
+ collating symbol. */
+ PATFETCH (c);
+ /* exit from the switch block. */
+ continue;
+ }
+ else
+ FREE_STACK_RETURN (REG_ECOLLATE);
+ }
+ datasize = 1;
+ }
+# endif
+ /* Throw away the ] at the end of the equivalence
+ class (or collating symbol). */
+ PATFETCH (c);
+
+ /* Allocate the space for the equivalence class
+ (or collating symbol) (and '\0' if needed). */
+ GET_BUFFER_SPACE(datasize);
+ /* Update the pointer to indicate end of buffer. */
+ b += datasize;
+
+ if (delim == '=')
+ { /* equivalence class */
+ /* Calculate the offset of char_ranges,
+ which is next to equivalence_classes. */
+ offset = laststart[1] + laststart[2]
+ + laststart[3] +6;
+ /* Insert space. */
+ insert_space(datasize, laststart + offset, b - 1);
+
+ /* Write the equivalence_class and \0. */
+ for (i = 0 ; i < datasize ; i++)
+ laststart[offset + i] = str[i];
+
+ /* Update the length of equivalence_classes. */
+ laststart[3] += datasize;
+ had_char_class = true;
+ }
+ else /* delim == '.' */
+ { /* collating symbol */
+ /* Calculate the offset of the equivalence_classes,
+ which is next to collating_symbols. */
+ offset = laststart[1] + laststart[2] + 6;
+ /* Insert space and write the collationg_symbol
+ and \0. */
+ insert_space(datasize, laststart + offset, b-1);
+ for (i = 0 ; i < datasize ; i++)
+ laststart[offset + i] = str[i];
+
+ /* In re_match_2_internal if range_start < -1, we
+ assume -range_start is the offset of the
+ collating symbol which is specified as
+ the character of the range start. So we assign
+ -(laststart[1] + laststart[2] + 6) to
+ range_start. */
+ range_start = -(laststart[1] + laststart[2] + 6);
+ /* Update the length of collating_symbol. */
+ laststart[2] += datasize;
+ had_char_class = false;
+ }
+ }
+ else
+ {
+ c1++;
+ while (c1--)
+ PATUNFETCH;
+ BUF_PUSH ('[');
+ BUF_PUSH (delim);
+ laststart[5] += 2; /* Update the length of characters */
+ range_start = delim;
+ had_char_class = false;
+ }
+ }
+ else
+ {
+ had_char_class = false;
+ BUF_PUSH(c);
+ laststart[5]++; /* Update the length of characters */
+ range_start = c;
+ }
+ }
+
+#else /* BYTE */
+ /* Ensure that we have enough space to push a charset: the
+ opcode, the length count, and the bitset; 34 bytes in all. */
+ GET_BUFFER_SPACE (34);
+
+ laststart = b;
+
+ /* We test `*p == '^' twice, instead of using an if
+ statement, so we only need one BUF_PUSH. */
+ BUF_PUSH (*p == '^' ? charset_not : charset);
+ if (*p == '^')
+ p++;
+
+ /* Remember the first position in the bracket expression. */
+ p1 = p;
+
+ /* Push the number of bytes in the bitmap. */
+ BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH);
+
+ /* Clear the whole map. */
+ bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH);
+
+ /* charset_not matches newline according to a syntax bit. */
+ if ((re_opcode_t) b[-2] == charset_not
+ && (syntax & RE_HAT_LISTS_NOT_NEWLINE))
+ SET_LIST_BIT ('\n');
+
+ /* Read in characters and ranges, setting map bits. */
+ for (;;)
+ {
+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+ PATFETCH (c);
+
+ /* \ might escape characters inside [...] and [^...]. */
+ if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\')
+ {
+ if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
+
+ PATFETCH (c1);
+ SET_LIST_BIT (c1);
+ range_start = c1;
+ continue;
+ }
+
+ /* Could be the end of the bracket expression. If it's
+ not (i.e., when the bracket expression is `[]' so
+ far), the ']' character bit gets set way below. */
+ if (c == ']' && p != p1 + 1)
+ break;
+
+ /* Look ahead to see if it's a range when the last thing
+ was a character class. */
+ if (had_char_class && c == '-' && *p != ']')
+ FREE_STACK_RETURN (REG_ERANGE);
+
+ /* Look ahead to see if it's a range when the last thing
+ was a character: if this is a hyphen not at the
+ beginning or the end of a list, then it's the range
+ operator. */
+ if (c == '-'
+ && !(p - 2 >= pattern && p[-2] == '[')
+ && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^')
+ && *p != ']')
+ {
+ reg_errcode_t ret
+ = byte_compile_range (range_start, &p, pend, translate,
+ syntax, b);
+ if (ret != REG_NOERROR) FREE_STACK_RETURN (ret);
+ range_start = 0xffffffff;
+ }
+
+ else if (p[0] == '-' && p[1] != ']')
+ { /* This handles ranges made up of characters only. */
+ reg_errcode_t ret;
+
+ /* Move past the `-'. */
+ PATFETCH (c1);
+
+ ret = byte_compile_range (c, &p, pend, translate, syntax, b);
+ if (ret != REG_NOERROR) FREE_STACK_RETURN (ret);
+ range_start = 0xffffffff;
+ }
+
+ /* See if we're at the beginning of a possible character
+ class. */
+
+ else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':')
+ { /* Leave room for the null. */
+ char str[CHAR_CLASS_MAX_LENGTH + 1];
+
+ PATFETCH (c);
+ c1 = 0;
+
+ /* If pattern is `[[:'. */
+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+ for (;;)
+ {
+ PATFETCH (c);
+ if ((c == ':' && *p == ']') || p == pend)
+ break;
+ if (c1 < CHAR_CLASS_MAX_LENGTH)
+ str[c1++] = c;
+ else
+ /* This is in any case an invalid class name. */
+ str[0] = '\0';
+ }
+ str[c1] = '\0';
+
+ /* If isn't a word bracketed by `[:' and `:]':
+ undo the ending character, the letters, and leave
+ the leading `:' and `[' (but set bits for them). */
+ if (c == ':' && *p == ']')
+ {
+# if defined _LIBC || WIDE_CHAR_SUPPORT
+ boolean is_lower = STREQ (str, "lower");
+ boolean is_upper = STREQ (str, "upper");
+ wctype_t wt;
+ int ch;
+
+ wt = IS_CHAR_CLASS (str);
+ if (wt == 0)
+ FREE_STACK_RETURN (REG_ECTYPE);
+
+ /* Throw away the ] at the end of the character
+ class. */
+ PATFETCH (c);
+
+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+ for (ch = 0; ch < 1 << BYTEWIDTH; ++ch)
+ {
+ if (iswctype (btowc (ch), wt))
+ SET_LIST_BIT (ch);
+
+ if (translate && (is_upper || is_lower)
+ && (ISUPPER (ch) || ISLOWER (ch)))
+ SET_LIST_BIT (ch);
+ }
+
+ had_char_class = true;
+# else
+ int ch;
+ boolean is_alnum = STREQ (str, "alnum");
+ boolean is_alpha = STREQ (str, "alpha");
+ boolean is_blank = STREQ (str, "blank");
+ boolean is_cntrl = STREQ (str, "cntrl");
+ boolean is_digit = STREQ (str, "digit");
+ boolean is_graph = STREQ (str, "graph");
+ boolean is_lower = STREQ (str, "lower");
+ boolean is_print = STREQ (str, "print");
+ boolean is_punct = STREQ (str, "punct");
+ boolean is_space = STREQ (str, "space");
+ boolean is_upper = STREQ (str, "upper");
+ boolean is_xdigit = STREQ (str, "xdigit");
+
+ if (!IS_CHAR_CLASS (str))
+ FREE_STACK_RETURN (REG_ECTYPE);
+
+ /* Throw away the ] at the end of the character
+ class. */
+ PATFETCH (c);
+
+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+ for (ch = 0; ch < 1 << BYTEWIDTH; ch++)
+ {
+ /* This was split into 3 if's to
+ avoid an arbitrary limit in some compiler. */
+ if ( (is_alnum && ISALNUM (ch))
+ || (is_alpha && ISALPHA (ch))
+ || (is_blank && ISBLANK (ch))
+ || (is_cntrl && ISCNTRL (ch)))
+ SET_LIST_BIT (ch);
+ if ( (is_digit && ISDIGIT (ch))
+ || (is_graph && ISGRAPH (ch))
+ || (is_lower && ISLOWER (ch))
+ || (is_print && ISPRINT (ch)))
+ SET_LIST_BIT (ch);
+ if ( (is_punct && ISPUNCT (ch))
+ || (is_space && ISSPACE (ch))
+ || (is_upper && ISUPPER (ch))
+ || (is_xdigit && ISXDIGIT (ch)))
+ SET_LIST_BIT (ch);
+ if ( translate && (is_upper || is_lower)
+ && (ISUPPER (ch) || ISLOWER (ch)))
+ SET_LIST_BIT (ch);
+ }
+ had_char_class = true;
+# endif /* libc || wctype.h */
+ }
+ else
+ {
+ c1++;
+ while (c1--)
+ PATUNFETCH;
+ SET_LIST_BIT ('[');
+ SET_LIST_BIT (':');
+ range_start = ':';
+ had_char_class = false;
+ }
+ }
+ else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == '=')
+ {
+ unsigned char str[MB_LEN_MAX + 1];
+# ifdef _LIBC
+ uint32_t nrules =
+ _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+# endif
+
+ PATFETCH (c);
+ c1 = 0;
+
+ /* If pattern is `[[='. */
+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+ for (;;)
+ {
+ PATFETCH (c);
+ if ((c == '=' && *p == ']') || p == pend)
+ break;
+ if (c1 < MB_LEN_MAX)
+ str[c1++] = c;
+ else
+ /* This is in any case an invalid class name. */
+ str[0] = '\0';
+ }
+ str[c1] = '\0';
+
+ if (c == '=' && *p == ']' && str[0] != '\0')
+ {
+ /* If we have no collation data we use the default
+ collation in which each character is in a class
+ by itself. It also means that ASCII is the
+ character set and therefore we cannot have character
+ with more than one byte in the multibyte
+ representation. */
+# ifdef _LIBC
+ if (nrules == 0)
+# endif
+ {
+ if (c1 != 1)
+ FREE_STACK_RETURN (REG_ECOLLATE);
+
+ /* Throw away the ] at the end of the equivalence
+ class. */
+ PATFETCH (c);
+
+ /* Set the bit for the character. */
+ SET_LIST_BIT (str[0]);
+ }
+# ifdef _LIBC
+ else
+ {
+ /* Try to match the byte sequence in `str' against
+ those known to the collate implementation.
+ First find out whether the bytes in `str' are
+ actually from exactly one character. */
+ const int32_t *table;
+ const unsigned char *weights;
+ const unsigned char *extra;
+ const int32_t *indirect;
+ int32_t idx;
+ const unsigned char *cp = str;
+ int ch;
+
+ /* This #include defines a local function! */
+# include <locale/weight.h>
+
+ table = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
+ weights = (const unsigned char *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB);
+ extra = (const unsigned char *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
+ indirect = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB);
+
+ idx = findidx (&cp);
+ if (idx == 0 || cp < str + c1)
+ /* This is no valid character. */
+ FREE_STACK_RETURN (REG_ECOLLATE);
+
+ /* Throw away the ] at the end of the equivalence
+ class. */
+ PATFETCH (c);
+
+ /* Now we have to go throught the whole table
+ and find all characters which have the same
+ first level weight.
+
+ XXX Note that this is not entirely correct.
+ we would have to match multibyte sequences
+ but this is not possible with the current
+ implementation. */
+ for (ch = 1; ch < 256; ++ch)
+ /* XXX This test would have to be changed if we
+ would allow matching multibyte sequences. */
+ if (table[ch] > 0)
+ {
+ int32_t idx2 = table[ch];
+ size_t len = weights[idx2];
+
+ /* Test whether the lenghts match. */
+ if (weights[idx] == len)
+ {
+ /* They do. New compare the bytes of
+ the weight. */
+ size_t cnt = 0;
+
+ while (cnt < len
+ && (weights[idx + 1 + cnt]
+ == weights[idx2 + 1 + cnt]))
+ ++cnt;
+
+ if (cnt == len)
+ /* They match. Mark the character as
+ acceptable. */
+ SET_LIST_BIT (ch);
+ }
+ }
+ }
+# endif
+ had_char_class = true;
+ }
+ else
+ {
+ c1++;
+ while (c1--)
+ PATUNFETCH;
+ SET_LIST_BIT ('[');
+ SET_LIST_BIT ('=');
+ range_start = '=';
+ had_char_class = false;
+ }
+ }
+ else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == '.')
+ {
+ unsigned char str[128]; /* Should be large enough. */
+# ifdef _LIBC
+ uint32_t nrules =
+ _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+# endif
+
+ PATFETCH (c);
+ c1 = 0;
+
+ /* If pattern is `[[.'. */
+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+ for (;;)
+ {
+ PATFETCH (c);
+ if ((c == '.' && *p == ']') || p == pend)
+ break;
+ if (c1 < sizeof (str))
+ str[c1++] = c;
+ else
+ /* This is in any case an invalid class name. */
+ str[0] = '\0';
+ }
+ str[c1] = '\0';
+
+ if (c == '.' && *p == ']' && str[0] != '\0')
+ {
+ /* If we have no collation data we use the default
+ collation in which each character is the name
+ for its own class which contains only the one
+ character. It also means that ASCII is the
+ character set and therefore we cannot have character
+ with more than one byte in the multibyte
+ representation. */
+# ifdef _LIBC
+ if (nrules == 0)
+# endif
+ {
+ if (c1 != 1)
+ FREE_STACK_RETURN (REG_ECOLLATE);
+
+ /* Throw away the ] at the end of the equivalence
+ class. */
+ PATFETCH (c);
+
+ /* Set the bit for the character. */
+ SET_LIST_BIT (str[0]);
+ range_start = ((const unsigned char *) str)[0];
+ }
+# ifdef _LIBC
+ else
+ {
+ /* Try to match the byte sequence in `str' against
+ those known to the collate implementation.
+ First find out whether the bytes in `str' are
+ actually from exactly one character. */
+ int32_t table_size;
+ const int32_t *symb_table;
+ const unsigned char *extra;
+ int32_t idx;
+ int32_t elem;
+ int32_t second;
+ int32_t hash;
+
+ table_size =
+ _NL_CURRENT_WORD (LC_COLLATE,
+ _NL_COLLATE_SYMB_HASH_SIZEMB);
+ symb_table = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE,
+ _NL_COLLATE_SYMB_TABLEMB);
+ extra = (const unsigned char *)
+ _NL_CURRENT (LC_COLLATE,
+ _NL_COLLATE_SYMB_EXTRAMB);
+
+ /* Locate the character in the hashing table. */
+ hash = elem_hash (str, c1);
+
+ idx = 0;
+ elem = hash % table_size;
+ second = hash % (table_size - 2);
+ while (symb_table[2 * elem] != 0)
+ {
+ /* First compare the hashing value. */
+ if (symb_table[2 * elem] == hash
+ && c1 == extra[symb_table[2 * elem + 1]]
+ && memcmp (str,
+ &extra[symb_table[2 * elem + 1]
+ + 1],
+ c1) == 0)
+ {
+ /* Yep, this is the entry. */
+ idx = symb_table[2 * elem + 1];
+ idx += 1 + extra[idx];
+ break;
+ }
+
+ /* Next entry. */
+ elem += second;
+ }
+
+ if (symb_table[2 * elem] == 0)
+ /* This is no valid character. */
+ FREE_STACK_RETURN (REG_ECOLLATE);
+
+ /* Throw away the ] at the end of the equivalence
+ class. */
+ PATFETCH (c);
+
+ /* Now add the multibyte character(s) we found
+ to the accept list.
+
+ XXX Note that this is not entirely correct.
+ we would have to match multibyte sequences
+ but this is not possible with the current
+ implementation. Also, we have to match
+ collating symbols, which expand to more than
+ one file, as a whole and not allow the
+ individual bytes. */
+ c1 = extra[idx++];
+ if (c1 == 1)
+ range_start = extra[idx];
+ while (c1-- > 0)
+ {
+ SET_LIST_BIT (extra[idx]);
+ ++idx;
+ }
+ }
+# endif
+ had_char_class = false;
+ }
+ else
+ {
+ c1++;
+ while (c1--)
+ PATUNFETCH;
+ SET_LIST_BIT ('[');
+ SET_LIST_BIT ('.');
+ range_start = '.';
+ had_char_class = false;
+ }
+ }
+ else
+ {
+ had_char_class = false;
+ SET_LIST_BIT (c);
+ range_start = 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];
+#endif /* WCHAR */
+ }
+ break;
+
+
+ case '(':
+ if (syntax & RE_NO_BK_PARENS)
+ goto handle_open;
+ else
+ goto normal_char;
+
+
+ case ')':
+ if (syntax & RE_NO_BK_PARENS)
+ goto handle_close;
+ else
+ goto normal_char;
+
+
+ case '\n':
+ if (syntax & RE_NEWLINE_ALT)
+ goto handle_alt;
+ else
+ goto normal_char;
+
+
+ case '|':
+ if (syntax & RE_NO_BK_VBAR)
+ goto handle_alt;
+ else
+ goto normal_char;
+
+
+ case '{':
+ if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES)
+ goto handle_interval;
+ else
+ goto normal_char;
+
+
+ case '\\':
+ if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
+
+ /* Do not translate the character after the \, so that we can
+ distinguish, e.g., \B from \b, even if we normally would
+ translate, e.g., B to b. */
+ PATFETCH_RAW (c);
+
+ switch (c)
+ {
+ case '(':
+ if (syntax & RE_NO_BK_PARENS)
+ goto normal_backslash;
+
+ handle_open:
+ bufp->re_nsub++;
+ regnum++;
+
+ if (COMPILE_STACK_FULL)
+ {
+ RETALLOC (compile_stack.stack, compile_stack.size << 1,
+ compile_stack_elt_t);
+ if (compile_stack.stack == NULL) return REG_ESPACE;
+
+ compile_stack.size <<= 1;
+ }
+
+ /* These are the values to restore when we hit end of this
+ group. They are all relative offsets, so that if the
+ whole pattern moves because of realloc, they will still
+ be valid. */
+ COMPILE_STACK_TOP.begalt_offset = begalt - COMPILED_BUFFER_VAR;
+ COMPILE_STACK_TOP.fixup_alt_jump
+ = fixup_alt_jump ? fixup_alt_jump - COMPILED_BUFFER_VAR + 1 : 0;
+ COMPILE_STACK_TOP.laststart_offset = b - COMPILED_BUFFER_VAR;
+ 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
+ - COMPILED_BUFFER_VAR + 2;
+ BUF_PUSH_3 (start_memory, regnum, 0);
+ }
+
+ compile_stack.avail++;
+
+ fixup_alt_jump = 0;
+ laststart = 0;
+ begalt = b;
+ /* If we've reached MAX_REGNUM groups, then this open
+ won't actually generate any code, so we'll have to
+ clear pending_exact explicitly. */
+ pending_exact = 0;
+ break;
+
+
+ case ')':
+ if (syntax & RE_NO_BK_PARENS) goto normal_backslash;
+
+ if (COMPILE_STACK_EMPTY)
+ {
+ if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
+ goto normal_backslash;
+ else
+ FREE_STACK_RETURN (REG_ERPAREN);
+ }
+
+ handle_close:
+ if (fixup_alt_jump)
+ { /* Push a dummy failure point at the end of the
+ alternative for a possible future
+ `pop_failure_jump' to pop. See comments at
+ `push_dummy_failure' in `re_match_2'. */
+ BUF_PUSH (push_dummy_failure);
+
+ /* We allocated space for this jump when we assigned
+ to `fixup_alt_jump', in the `handle_alt' case below. */
+ STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1);
+ }
+
+ /* See similar code for backslashed left paren above. */
+ if (COMPILE_STACK_EMPTY)
+ {
+ if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
+ goto normal_char;
+ else
+ FREE_STACK_RETURN (REG_ERPAREN);
+ }
+
+ /* Since we just checked for an empty stack above, this
+ ``can't happen''. */
+ assert (compile_stack.avail != 0);
+ {
+ /* We don't just want to restore into `regnum', because
+ later groups should continue to be numbered higher,
+ as in `(ab)c(de)' -- the second group is #2. */
+ regnum_t this_group_regnum;
+
+ compile_stack.avail--;
+ begalt = COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.begalt_offset;
+ fixup_alt_jump
+ = COMPILE_STACK_TOP.fixup_alt_jump
+ ? COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.fixup_alt_jump - 1
+ : 0;
+ laststart = COMPILED_BUFFER_VAR + 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)
+ {
+ UCHAR_T *inner_group_loc
+ = COMPILED_BUFFER_VAR + 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 (1 + OFFSET_ADDRESS_SIZE);
+ INSERT_JUMP (on_failure_jump, begalt,
+ b + 2 + 2 * OFFSET_ADDRESS_SIZE);
+ pending_exact = 0;
+ b += 1 + OFFSET_ADDRESS_SIZE;
+
+ /* 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 (1 + OFFSET_ADDRESS_SIZE);
+ b += 1 + OFFSET_ADDRESS_SIZE;
+
+ 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_NO_BK_BRACES))
+ 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;
+
+ /* Place in the uncompiled pattern (i.e., just after
+ the '{') to go back to if the interval is invalid. */
+ const CHAR_T *beg_interval = p;
+
+ if (p == pend)
+ goto invalid_interval;
+
+ 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 (! (0 <= lower_bound && lower_bound <= upper_bound))
+ goto invalid_interval;
+
+ if (!(syntax & RE_NO_BK_BRACES))
+ {
+ if (c != '\\' || p == pend)
+ goto invalid_interval;
+ PATFETCH (c);
+ }
+
+ if (c != '}')
+ goto invalid_interval;
+
+ /* If it's invalid to have no preceding re. */
+ if (!laststart)
+ {
+ if (syntax & RE_CONTEXT_INVALID_OPS
+ && !(syntax & RE_INVALID_INTERVAL_ORD))
+ FREE_STACK_RETURN (REG_BADRPT);
+ else if (syntax & RE_CONTEXT_INDEP_OPS)
+ laststart = b;
+ else
+ goto unfetch_interval;
+ }
+
+ /* We just parsed a valid interval. */
+
+ if (RE_DUP_MAX < upper_bound)
+ FREE_STACK_RETURN (REG_BADBR);
+
+ /* 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. */
+ /* ifdef WCHAR, 'b + 1 + OFFSET_ADDRESS_SIZE'
+ instead of 'b + 3'. */
+ if (upper_bound == 0)
+ {
+ GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE);
+ INSERT_JUMP (jump, laststart, b + 1
+ + OFFSET_ADDRESS_SIZE);
+ b += 1 + OFFSET_ADDRESS_SIZE;
+ }
+
+ /* Otherwise, we have a nontrivial interval. When
+ we're all done, the pattern will look like:
+ set_number_at <jump count> <upper bound>
+ set_number_at <succeed_n count> <lower bound>
+ succeed_n <after jump addr> <succeed_n count>
+ <body of loop>
+ jump_n <succeed_n addr> <jump count>
+ (The upper bound and `jump_n' are omitted if
+ `upper_bound' is 1, though.) */
+ else
+ { /* If the upper bound is > 1, we need to insert
+ more at the end of the loop. */
+ unsigned nbytes = 2 + 4 * OFFSET_ADDRESS_SIZE +
+ (upper_bound > 1) * (2 + 4 * OFFSET_ADDRESS_SIZE);
+
+ 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 + 1 + 2 * OFFSET_ADDRESS_SIZE
+ + (upper_bound > 1) * (1 + 2 * OFFSET_ADDRESS_SIZE)
+ , lower_bound);
+ b += 1 + 2 * OFFSET_ADDRESS_SIZE;
+
+ /* 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'. */
+ /* ifdef WCHAR, The '1+2*OFFSET_ADDRESS_SIZE'
+ is the 'set_number_at', plus '1+OFFSET_ADDRESS_SIZE'
+ of the following `succeed_n'. */
+ PREFIX(insert_op2) (set_number_at, laststart, 1
+ + 2 * OFFSET_ADDRESS_SIZE, lower_bound, b);
+ b += 1 + 2 * OFFSET_ADDRESS_SIZE;
+
+ 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
+ + 2 * OFFSET_ADDRESS_SIZE + 1,
+ upper_bound - 1);
+ b += 1 + 2 * OFFSET_ADDRESS_SIZE;
+
+ /* 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. */
+ PREFIX(insert_op2) (set_number_at, laststart,
+ b - laststart,
+ upper_bound - 1, b);
+ b += 1 + 2 * OFFSET_ADDRESS_SIZE;
+ }
+ }
+ pending_exact = 0;
+ break;
+
+ invalid_interval:
+ if (!(syntax & RE_INVALID_INTERVAL_ORD))
+ FREE_STACK_RETURN (p == pend ? REG_EBRACE : REG_BADBR);
+ unfetch_interval:
+ /* Match the characters as literals. */
+ p = beg_interval;
+ c = '{';
+ if (syntax & RE_NO_BK_BRACES)
+ goto normal_char;
+ else
+ goto normal_backslash;
+ }
+
+#ifdef emacs
+ /* There is no way to specify the before_dot and after_dot
+ operators. rms says this is ok. --karl */
+ case '=':
+ BUF_PUSH (at_dot);
+ break;
+
+ case 's':
+ laststart = b;
+ PATFETCH (c);
+ BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]);
+ break;
+
+ case 'S':
+ laststart = b;
+ PATFETCH (c);
+ BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]);
+ break;
+#endif /* emacs */
+
+
+ case 'w':
+ if (syntax & RE_NO_GNU_OPS)
+ goto normal_char;
+ laststart = b;
+ BUF_PUSH (wordchar);
+ break;
+
+
+ case 'W':
+ if (syntax & RE_NO_GNU_OPS)
+ goto normal_char;
+ laststart = b;
+ BUF_PUSH (notwordchar);
+ break;
+
+
+ case '<':
+ if (syntax & RE_NO_GNU_OPS)
+ goto normal_char;
+ BUF_PUSH (wordbeg);
+ break;
+
+ case '>':
+ if (syntax & RE_NO_GNU_OPS)
+ goto normal_char;
+ BUF_PUSH (wordend);
+ break;
+
+ case 'b':
+ if (syntax & RE_NO_GNU_OPS)
+ goto normal_char;
+ BUF_PUSH (wordbound);
+ break;
+
+ case 'B':
+ if (syntax & RE_NO_GNU_OPS)
+ goto normal_char;
+ BUF_PUSH (notwordbound);
+ break;
+
+ case '`':
+ if (syntax & RE_NO_GNU_OPS)
+ goto normal_char;
+ BUF_PUSH (begbuf);
+ break;
+
+ case '\'':
+ if (syntax & RE_NO_GNU_OPS)
+ goto normal_char;
+ BUF_PUSH (endbuf);
+ break;
+
+ case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9':
+ if (syntax & RE_NO_BK_REFS)
+ goto normal_char;
+
+ c1 = c - '0';
+
+ if (c1 > regnum)
+ FREE_STACK_RETURN (REG_ESUBREG);
+
+ /* Can't back reference to a subexpression if inside of it. */
+ if (group_in_compile_stack (compile_stack, (regnum_t) c1))
+ goto normal_char;
+
+ laststart = b;
+ BUF_PUSH_2 (duplicate, c1);
+ break;
+
+
+ case '+':
+ case '?':
+ if (syntax & RE_BK_PLUS_QM)
+ goto handle_plus;
+ else
+ goto normal_backslash;
+
+ default:
+ normal_backslash:
+ /* You might think it would be useful for \ to mean
+ not to translate; but if we don't translate it
+ it will never match anything. */
+ c = TRANSLATE (c);
+ goto normal_char;
+ }
+ break;
+
+
+ default:
+ /* Expects the character in `c'. */
+ normal_char:
+ /* If no exactn currently being built. */
+ if (!pending_exact
+#ifdef WCHAR
+ /* If last exactn handle binary(or character) and
+ new exactn handle character(or binary). */
+ || is_exactn_bin != is_binary[p - 1 - pattern]
+#endif /* WCHAR */
+
+ /* 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;
+
+#ifdef WCHAR
+ /* Is this exactn binary data or character? */
+ is_exactn_bin = is_binary[p - 1 - pattern];
+ if (is_exactn_bin)
+ BUF_PUSH_2 (exactn_bin, 0);
+ else
+ BUF_PUSH_2 (exactn, 0);
+#else
+ BUF_PUSH_2 (exactn, 0);
+#endif /* WCHAR */
+ pending_exact = b - 1;
+ }
+
+ BUF_PUSH (c);
+ (*pending_exact)++;
+ break;
+ } /* switch (c) */
+ } /* while p != pend */
+
+
+ /* Through the pattern now. */
+
+ if (fixup_alt_jump)
+ STORE_JUMP (jump_past_alt, fixup_alt_jump, b);
+
+ if (!COMPILE_STACK_EMPTY)
+ FREE_STACK_RETURN (REG_EPAREN);
+
+ /* If we don't want backtracking, force success
+ the first time we reach the end of the compiled pattern. */
+ if (syntax & RE_NO_POSIX_BACKTRACKING)
+ BUF_PUSH (succeed);
+
+#ifdef WCHAR
+ free (pattern);
+ free (mbs_offset);
+ free (is_binary);
+#endif
+ free (compile_stack.stack);
+
+ /* We have succeeded; set the length of the buffer. */
+#ifdef WCHAR
+ bufp->used = (uintptr_t) b - (uintptr_t) COMPILED_BUFFER_VAR;
+#else
+ bufp->used = b - bufp->buffer;
+#endif
+
+#ifdef DEBUG
+ if (debug)
+ {
+ DEBUG_PRINT1 ("\nCompiled pattern: \n");
+ PREFIX(print_compiled_pattern) (bufp);
+ }
+#endif /* DEBUG */
+
+#ifndef MATCH_MAY_ALLOCATE
+ /* Initialize the failure stack to the largest possible stack. This
+ isn't necessary unless we're trying to avoid calling alloca in
+ the search and match routines. */
+ {
+ int num_regs = bufp->re_nsub + 1;
+
+ /* Since DOUBLE_FAIL_STACK refuses to double only if the current size
+ is strictly greater than re_max_failures, the largest possible stack
+ is 2 * re_max_failures failure points. */
+ if (fail_stack.size < (2 * re_max_failures * MAX_FAILURE_ITEMS))
+ {
+ fail_stack.size = (2 * re_max_failures * MAX_FAILURE_ITEMS);
+
+# ifdef emacs
+ if (! fail_stack.stack)
+ fail_stack.stack
+ = (PREFIX(fail_stack_elt_t) *) xmalloc (fail_stack.size
+ * sizeof (PREFIX(fail_stack_elt_t)));
+ else
+ fail_stack.stack
+ = (PREFIX(fail_stack_elt_t) *) xrealloc (fail_stack.stack,
+ (fail_stack.size
+ * sizeof (PREFIX(fail_stack_elt_t))));
+# else /* not emacs */
+ if (! fail_stack.stack)
+ fail_stack.stack
+ = malloc (fail_stack.size * sizeof (PREFIX(fail_stack_elt_t)));
+ else
+ fail_stack.stack
+ = realloc (fail_stack.stack,
+ fail_stack.size * sizeof (PREFIX(fail_stack_elt_t)));
+# endif /* not emacs */
+ }
+
+ PREFIX(regex_grow_registers) (num_regs);
+ }
+#endif /* not MATCH_MAY_ALLOCATE */
+
+ return REG_NOERROR;
+} /* regex_compile */
+
+/* Subroutines for `regex_compile'. */
+
+/* Store OP at LOC followed by two-byte integer parameter ARG. */
+/* ifdef WCHAR, integer parameter is 1 wchar_t. */
+
+static void
+PREFIX(store_op1) (re_opcode_t op, UCHAR_T *loc, int arg)
+{
+ *loc = (UCHAR_T) op;
+ STORE_NUMBER (loc + 1, arg);
+}
+
+
+/* Like `store_op1', but for two two-byte parameters ARG1 and ARG2. */
+/* ifdef WCHAR, integer parameter is 1 wchar_t. */
+
+static void
+PREFIX(store_op2) (re_opcode_t op, UCHAR_T *loc, int arg1, int arg2)
+{
+ *loc = (UCHAR_T) op;
+ STORE_NUMBER (loc + 1, arg1);
+ STORE_NUMBER (loc + 1 + OFFSET_ADDRESS_SIZE, 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. */
+/* ifdef WCHAR, integer parameter is 1 wchar_t. */
+
+static void
+PREFIX(insert_op1) (re_opcode_t op, UCHAR_T *loc, int arg, UCHAR_T *end)
+{
+ register UCHAR_T *pfrom = end;
+ register UCHAR_T *pto = end + 1 + OFFSET_ADDRESS_SIZE;
+
+ while (pfrom != loc)
+ *--pto = *--pfrom;
+
+ PREFIX(store_op1) (op, loc, arg);
+}
+
+
+/* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2. */
+/* ifdef WCHAR, integer parameter is 1 wchar_t. */
+
+static void
+PREFIX(insert_op2) (re_opcode_t op, UCHAR_T *loc, int arg1, int arg2,
+ UCHAR_T *end)
+{
+ register UCHAR_T *pfrom = end;
+ register UCHAR_T *pto = end + 1 + 2 * OFFSET_ADDRESS_SIZE;
+
+ while (pfrom != loc)
+ *--pto = *--pfrom;
+
+ PREFIX(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
+PREFIX(at_begline_loc_p) (const CHAR_T *pattern, const CHAR_T *p,
+ reg_syntax_t syntax)
+{
+ const CHAR_T *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
+PREFIX(at_endline_loc_p) (const CHAR_T *p, const CHAR_T *pend,
+ reg_syntax_t syntax)
+{
+ const CHAR_T *next = p;
+ boolean next_backslash = *next == '\\';
+ const CHAR_T *next_next = p + 1 < pend ? p + 1 : 0;
+
+ return
+ /* Before a subexpression? */
+ (syntax & RE_NO_BK_PARENS ? *next == ')'
+ : next_backslash && next_next && *next_next == ')')
+ /* Before an alternative? */
+ || (syntax & RE_NO_BK_VBAR ? *next == '|'
+ : next_backslash && next_next && *next_next == '|');
+}
+
+#else /* not INSIDE_RECURSION */
+
+/* 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_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;
+}
+#endif /* not INSIDE_RECURSION */
+
+#ifdef INSIDE_RECURSION
+
+#ifdef WCHAR
+/* This insert space, which size is "num", into the pattern at "loc".
+ "end" must point the end of the allocated buffer. */
+static void
+insert_space (int num, CHAR_T *loc, CHAR_T *end)
+{
+ register CHAR_T *pto = end;
+ register CHAR_T *pfrom = end - num;
+
+ while (pfrom >= loc)
+ *pto-- = *pfrom--;
+}
+#endif /* WCHAR */
+
+#ifdef WCHAR
+static reg_errcode_t
+wcs_compile_range (CHAR_T range_start_char,
+ const CHAR_T **p_ptr, const CHAR_T *pend,
+ RE_TRANSLATE_TYPE translate, reg_syntax_t syntax,
+ CHAR_T *b, CHAR_T *char_set)
+{
+ const CHAR_T *p = *p_ptr;
+ CHAR_T range_start, range_end;
+ reg_errcode_t ret;
+# ifdef _LIBC
+ uint32_t nrules;
+ uint32_t start_val, end_val;
+# endif
+ if (p == pend)
+ return REG_ERANGE;
+
+# ifdef _LIBC
+ nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+ if (nrules != 0)
+ {
+ const char *collseq = (const char *) _NL_CURRENT(LC_COLLATE,
+ _NL_COLLATE_COLLSEQWC);
+ const unsigned char *extra = (const unsigned char *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB);
+
+ if (range_start_char < -1)
+ {
+ /* range_start is a collating symbol. */
+ int32_t *wextra;
+ /* Retreive the index and get collation sequence value. */
+ wextra = (int32_t*)(extra + char_set[-range_start_char]);
+ start_val = wextra[1 + *wextra];
+ }
+ else
+ start_val = collseq_table_lookup(collseq, TRANSLATE(range_start_char));
+
+ end_val = collseq_table_lookup (collseq, TRANSLATE (p[0]));
+
+ /* Report an error if the range is empty and the syntax prohibits
+ this. */
+ ret = ((syntax & RE_NO_EMPTY_RANGES)
+ && (start_val > end_val))? REG_ERANGE : REG_NOERROR;
+
+ /* Insert space to the end of the char_ranges. */
+ insert_space(2, b - char_set[5] - 2, b - 1);
+ *(b - char_set[5] - 2) = (wchar_t)start_val;
+ *(b - char_set[5] - 1) = (wchar_t)end_val;
+ char_set[4]++; /* ranges_index */
+ }
+ else
+# endif
+ {
+ range_start = (range_start_char >= 0)? TRANSLATE (range_start_char):
+ range_start_char;
+ range_end = TRANSLATE (p[0]);
+ /* Report an error if the range is empty and the syntax prohibits
+ this. */
+ ret = ((syntax & RE_NO_EMPTY_RANGES)
+ && (range_start > range_end))? REG_ERANGE : REG_NOERROR;
+
+ /* Insert space to the end of the char_ranges. */
+ insert_space(2, b - char_set[5] - 2, b - 1);
+ *(b - char_set[5] - 2) = range_start;
+ *(b - char_set[5] - 1) = range_end;
+ char_set[4]++; /* ranges_index */
+ }
+ /* Have to increment the pointer into the pattern string, so the
+ caller isn't still at the ending character. */
+ (*p_ptr)++;
+
+ return ret;
+}
+#else /* BYTE */
+/* 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
+byte_compile_range (unsigned int range_start_char,
+ const char **p_ptr, const char *pend,
+ RE_TRANSLATE_TYPE translate, reg_syntax_t syntax,
+ unsigned char *b)
+{
+ unsigned this_char;
+ const char *p = *p_ptr;
+ reg_errcode_t ret;
+# if _LIBC
+ const unsigned char *collseq;
+ unsigned int start_colseq;
+ unsigned int end_colseq;
+# else
+ unsigned end_char;
+# endif
+
+ if (p == pend)
+ return REG_ERANGE;
+
+ /* Have to increment the pointer into the pattern string, so the
+ caller isn't still at the ending character. */
+ (*p_ptr)++;
+
+ /* Report an error if the range is empty and the syntax prohibits this. */
+ ret = syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR;
+
+# if _LIBC
+ collseq = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
+ _NL_COLLATE_COLLSEQMB);
+
+ start_colseq = collseq[(unsigned char) TRANSLATE (range_start_char)];
+ end_colseq = collseq[(unsigned char) TRANSLATE (p[0])];
+ for (this_char = 0; this_char <= (unsigned char) -1; ++this_char)
+ {
+ unsigned int this_colseq = collseq[(unsigned char) TRANSLATE (this_char)];
+
+ if (start_colseq <= this_colseq && this_colseq <= end_colseq)
+ {
+ SET_LIST_BIT (TRANSLATE (this_char));
+ ret = REG_NOERROR;
+ }
+ }
+# else
+ /* Here we see why `this_char' has to be larger than an `unsigned
+ char' -- we would otherwise go into an infinite loop, since all
+ characters <= 0xff. */
+ range_start_char = TRANSLATE (range_start_char);
+ /* TRANSLATE(p[0]) is casted to char (not unsigned char) in TRANSLATE,
+ and some compilers cast it to int implicitly, so following for_loop
+ may fall to (almost) infinite loop.
+ e.g. If translate[p[0]] = 0xff, end_char may equals to 0xffffffff.
+ To avoid this, we cast p[0] to unsigned int and truncate it. */
+ end_char = ((unsigned)TRANSLATE(p[0]) & ((1 << BYTEWIDTH) - 1));
+
+ for (this_char = range_start_char; this_char <= end_char; ++this_char)
+ {
+ SET_LIST_BIT (TRANSLATE (this_char));
+ ret = REG_NOERROR;
+ }
+# endif
+
+ return ret;
+}
+#endif /* WCHAR */
+
+/* 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. */
+
+#ifdef WCHAR
+/* local function for re_compile_fastmap.
+ truncate wchar_t character to char. */
+
+static unsigned char
+truncate_wchar (CHAR_T c)
+{
+ unsigned char buf[MB_CUR_MAX];
+ mbstate_t state;
+ int retval;
+ memset (&state, '\0', sizeof (state));
+ retval = wcrtomb (buf, c, &state);
+ return retval > 0 ? buf[0] : (unsigned char) c;
+}
+#endif /* WCHAR */
+
+static int
+PREFIX(re_compile_fastmap) (struct re_pattern_buffer *bufp)
+{
+ int j, k;
+#ifdef MATCH_MAY_ALLOCATE
+ PREFIX(fail_stack_type) fail_stack;
+#endif
+#ifndef REGEX_MALLOC
+ char *destination;
+#endif
+
+ register char *fastmap = bufp->fastmap;
+
+#ifdef WCHAR
+ /* We need to cast pattern to (wchar_t*), because we casted this compiled
+ pattern to (char*) in regex_compile. */
+ UCHAR_T *pattern = (UCHAR_T*)bufp->buffer;
+ register UCHAR_T *pend = (UCHAR_T*) (bufp->buffer + bufp->used);
+#else /* BYTE */
+ UCHAR_T *pattern = bufp->buffer;
+ register UCHAR_T *pend = pattern + bufp->used;
+#endif /* WCHAR */
+ UCHAR_T *p = pattern;
+
+#ifdef REL_ALLOC
+ /* This holds the pointer to the failure stack, when
+ it is allocated relocatably. */
+ fail_stack_elt_t *failure_stack_ptr;
+#endif
+
+ /* Assume that each path through the pattern can be null until
+ proven otherwise. We set this false at the bottom of switch
+ statement, to which we get only if a particular path doesn't
+ match the empty string. */
+ boolean path_can_be_null = true;
+
+ /* We aren't doing a `succeed_n' to begin with. */
+ boolean succeed_n_p = false;
+
+ assert (fastmap != NULL && p != NULL);
+
+ INIT_FAIL_STACK ();
+ bzero (fastmap, 1 << BYTEWIDTH); /* Assume nothing's valid. */
+ bufp->fastmap_accurate = 1; /* It will be when we're done. */
+ bufp->can_be_null = 0;
+
+ while (1)
+ {
+ if (p == pend || *p == succeed)
+ {
+ /* We have reached the (effective) end of pattern. */
+ if (!FAIL_STACK_EMPTY ())
+ {
+ bufp->can_be_null |= path_can_be_null;
+
+ /* Reset for next path. */
+ path_can_be_null = true;
+
+ p = fail_stack.stack[--fail_stack.avail].pointer;
+
+ continue;
+ }
+ else
+ break;
+ }
+
+ /* We should never be about to go beyond the end of the pattern. */
+ assert (p < pend);
+
+ switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++))
+ {
+
+ /* I guess the idea here is to simply not bother with a fastmap
+ if a backreference is used, since it's too hard to figure out
+ the fastmap for the corresponding group. Setting
+ `can_be_null' stops `re_search_2' from using the fastmap, so
+ that is all we do. */
+ case duplicate:
+ bufp->can_be_null = 1;
+ goto done;
+
+
+ /* Following are the cases which match a character. These end
+ with `break'. */
+
+#ifdef WCHAR
+ case exactn:
+ fastmap[truncate_wchar(p[1])] = 1;
+ break;
+#else /* BYTE */
+ case exactn:
+ fastmap[p[1]] = 1;
+ break;
+#endif /* WCHAR */
+#ifdef MBS_SUPPORT
+ case exactn_bin:
+ fastmap[p[1]] = 1;
+ break;
+#endif
+
+#ifdef WCHAR
+ /* It is hard to distinguish fastmap from (multi byte) characters
+ which depends on current locale. */
+ case charset:
+ case charset_not:
+ case wordchar:
+ case notwordchar:
+ bufp->can_be_null = 1;
+ goto done;
+#else /* BYTE */
+ 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;
+#endif /* WCHAR */
+
+ case anychar:
+ {
+ int fastmap_newline = fastmap['\n'];
+
+ /* `.' matches anything ... */
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ fastmap[j] = 1;
+
+ /* ... except perhaps newline. */
+ if (!(bufp->syntax & RE_DOT_NEWLINE))
+ fastmap['\n'] = fastmap_newline;
+
+ /* Return if we have already set `can_be_null'; if we have,
+ then the fastmap is irrelevant. Something's wrong here. */
+ else if (bufp->can_be_null)
+ goto done;
+
+ /* Otherwise, have to check alternative paths. */
+ break;
+ }
+
+#ifdef emacs
+ case syntaxspec:
+ k = *p++;
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (SYNTAX (j) == (enum syntaxcode) k)
+ fastmap[j] = 1;
+ break;
+
+
+ case notsyntaxspec:
+ k = *p++;
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (SYNTAX (j) != (enum syntaxcode) k)
+ fastmap[j] = 1;
+ break;
+
+
+ /* All cases after this match the empty string. These end with
+ `continue'. */
+
+
+ case before_dot:
+ case at_dot:
+ case after_dot:
+ continue;
+#endif /* emacs */
+
+
+ case no_op:
+ case begline:
+ case endline:
+ case begbuf:
+ case endbuf:
+ case wordbound:
+ case notwordbound:
+ case wordbeg:
+ case wordend:
+ case push_dummy_failure:
+ continue;
+
+
+ case jump_n:
+ case pop_failure_jump:
+ case maybe_pop_jump:
+ case jump:
+ case jump_past_alt:
+ case dummy_failure_jump:
+ EXTRACT_NUMBER_AND_INCR (j, p);
+ p += j;
+ if (j > 0)
+ continue;
+
+ /* Jump backward implies we just went through the body of a
+ loop and matched nothing. Opcode jumped to should be
+ `on_failure_jump' or `succeed_n'. Just treat it like an
+ ordinary jump. For a * loop, it has pushed its failure
+ point already; if so, discard that as redundant. */
+ if ((re_opcode_t) *p != on_failure_jump
+ && (re_opcode_t) *p != succeed_n)
+ continue;
+
+ p++;
+ EXTRACT_NUMBER_AND_INCR (j, p);
+ p += j;
+
+ /* If what's on the stack is where we are now, pop it. */
+ if (!FAIL_STACK_EMPTY ()
+ && fail_stack.stack[fail_stack.avail - 1].pointer == p)
+ fail_stack.avail--;
+
+ continue;
+
+
+ case on_failure_jump:
+ case on_failure_keep_string_jump:
+ handle_on_failure_jump:
+ EXTRACT_NUMBER_AND_INCR (j, p);
+
+ /* For some patterns, e.g., `(a?)?', `p+j' here points to the
+ end of the pattern. We don't want to push such a point,
+ since when we restore it above, entering the switch will
+ increment `p' past the end of the pattern. We don't need
+ to push such a point since we obviously won't find any more
+ fastmap entries beyond `pend'. Such a pattern can match
+ the null string, though. */
+ if (p + j < pend)
+ {
+ if (!PUSH_PATTERN_OP (p + j, fail_stack))
+ {
+ RESET_FAIL_STACK ();
+ return -2;
+ }
+ }
+ else
+ bufp->can_be_null = 1;
+
+ if (succeed_n_p)
+ {
+ EXTRACT_NUMBER_AND_INCR (k, p); /* Skip the n. */
+ succeed_n_p = false;
+ }
+
+ continue;
+
+
+ case succeed_n:
+ /* Get to the number of times to succeed. */
+ p += OFFSET_ADDRESS_SIZE;
+
+ /* Increment p past the n for when k != 0. */
+ EXTRACT_NUMBER_AND_INCR (k, p);
+ if (k == 0)
+ {
+ p -= 2 * OFFSET_ADDRESS_SIZE;
+ succeed_n_p = true; /* Spaghetti code alert. */
+ goto handle_on_failure_jump;
+ }
+ continue;
+
+
+ case set_number_at:
+ p += 2 * OFFSET_ADDRESS_SIZE;
+ continue;
+
+
+ case start_memory:
+ case stop_memory:
+ p += 2;
+ continue;
+
+
+ default:
+ abort (); /* We have listed all the cases. */
+ } /* switch *p++ */
+
+ /* Getting here means we have found the possible starting
+ characters for one path of the pattern -- and that the empty
+ string does not match. We need not follow this path further.
+ Instead, look at the next alternative (remembered on the
+ stack), or quit if no more. The test at the top of the loop
+ does these things. */
+ path_can_be_null = false;
+ p = pend;
+ } /* while p */
+
+ /* Set `can_be_null' for the last path (also the first path, if the
+ pattern is empty). */
+ bufp->can_be_null |= path_can_be_null;
+
+ done:
+ RESET_FAIL_STACK ();
+ return 0;
+}
+
+#else /* not INSIDE_RECURSION */
+
+int
+re_compile_fastmap (struct re_pattern_buffer *bufp)
+{
+# ifdef MBS_SUPPORT
+ if (MB_CUR_MAX != 1)
+ return wcs_re_compile_fastmap(bufp);
+ else
+# endif
+ return byte_re_compile_fastmap(bufp);
+} /* re_compile_fastmap */
+#ifdef _LIBC
+weak_alias (__re_compile_fastmap, re_compile_fastmap)
+#endif
+
+
+/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
+ ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use
+ this memory for recording register information. STARTS and ENDS
+ must be allocated using the malloc library routine, and must each
+ be at least NUM_REGS * sizeof (regoff_t) bytes long.
+
+ If NUM_REGS == 0, then subsequent matches should allocate their own
+ register data.
+
+ Unless this function is called, the first search or match using
+ PATTERN_BUFFER will allocate its own register data, without
+ freeing the old data. */
+
+void
+re_set_registers (struct re_pattern_buffer *bufp,
+ struct re_registers *regs,
+ unsigned int num_regs,
+ regoff_t *starts, regoff_t *ends)
+{
+ if (num_regs)
+ {
+ bufp->regs_allocated = REGS_REALLOCATE;
+ regs->num_regs = num_regs;
+ regs->start = starts;
+ regs->end = ends;
+ }
+ else
+ {
+ bufp->regs_allocated = REGS_UNALLOCATED;
+ regs->num_regs = 0;
+ regs->start = regs->end = (regoff_t *) 0;
+ }
+}
+#ifdef _LIBC
+weak_alias (__re_set_registers, re_set_registers)
+#endif
+
+/* Searching routines. */
+
+/* Like re_search_2, below, but only one string is specified, and
+ doesn't let you say where to stop matching. */
+
+int
+re_search (struct re_pattern_buffer *bufp,
+ const char *string,
+ int size, int startpos, int range,
+ struct re_registers *regs)
+{
+ return re_search_2 (bufp, NULL, 0, string, size, startpos, range,
+ regs, size);
+}
+#ifdef _LIBC
+weak_alias (__re_search, re_search)
+#endif
+
+
+/* Using the compiled pattern in BUFP->buffer, first tries to match the
+ virtual concatenation of STRING1 and STRING2, starting first at index
+ STARTPOS, then at STARTPOS + 1, and so on.
+
+ STRING1 and STRING2 have length SIZE1 and SIZE2, respectively.
+
+ RANGE is how far to scan while trying to match. RANGE = 0 means try
+ only at STARTPOS; in general, the last start tried is STARTPOS +
+ RANGE.
+
+ In REGS, return the indices of the virtual concatenation of STRING1
+ and STRING2 that matched the entire BUFP->buffer and its contained
+ subexpressions.
+
+ Do not consider matching one past the index STOP in the virtual
+ concatenation of STRING1 and STRING2.
+
+ We return either the position in the strings at which the match was
+ found, -1 if no match, or -2 if error (such as failure
+ stack overflow). */
+
+int
+re_search_2 (struct re_pattern_buffer *bufp,
+ const char *string1, int size1,
+ const char *string2, int size2,
+ int startpos, int range,
+ struct re_registers *regs,
+ int stop)
+{
+# ifdef MBS_SUPPORT
+ if (MB_CUR_MAX != 1)
+ return wcs_re_search_2 (bufp, string1, size1, string2, size2, startpos,
+ range, regs, stop);
+ else
+# endif
+ return byte_re_search_2 (bufp, string1, size1, string2, size2, startpos,
+ range, regs, stop);
+} /* re_search_2 */
+#ifdef _LIBC
+weak_alias (__re_search_2, re_search_2)
+#endif
+
+#endif /* not INSIDE_RECURSION */
+
+#ifdef INSIDE_RECURSION
+
+#ifdef MATCH_MAY_ALLOCATE
+# define FREE_VAR(var) if (var) REGEX_FREE (var); var = NULL
+#else
+# define FREE_VAR(var) if (var) free (var); var = NULL
+#endif
+
+#ifdef WCHAR
+# define MAX_ALLOCA_SIZE 2000
+
+# define FREE_WCS_BUFFERS() \
+ do { \
+ if (size1 > MAX_ALLOCA_SIZE) \
+ { \
+ free (wcs_string1); \
+ free (mbs_offset1); \
+ } \
+ else \
+ { \
+ FREE_VAR (wcs_string1); \
+ FREE_VAR (mbs_offset1); \
+ } \
+ if (size2 > MAX_ALLOCA_SIZE) \
+ { \
+ free (wcs_string2); \
+ free (mbs_offset2); \
+ } \
+ else \
+ { \
+ FREE_VAR (wcs_string2); \
+ FREE_VAR (mbs_offset2); \
+ } \
+ } while (0)
+
+#endif
+
+
+static int
+PREFIX(re_search_2) (struct re_pattern_buffer *bufp,
+ const char *string1, int size1,
+ const char *string2, int size2,
+ int startpos, int range,
+ struct re_registers *regs,
+ int stop)
+{
+ int val;
+ register char *fastmap = bufp->fastmap;
+ register RE_TRANSLATE_TYPE translate = bufp->translate;
+ int total_size = size1 + size2;
+ int endpos = startpos + range;
+#ifdef WCHAR
+ /* We need wchar_t* buffers correspond to cstring1, cstring2. */
+ wchar_t *wcs_string1 = NULL, *wcs_string2 = NULL;
+ /* We need the size of wchar_t buffers correspond to csize1, csize2. */
+ int wcs_size1 = 0, wcs_size2 = 0;
+ /* offset buffer for optimizatoin. See convert_mbs_to_wc. */
+ int *mbs_offset1 = NULL, *mbs_offset2 = NULL;
+ /* They hold whether each wchar_t is binary data or not. */
+ char *is_binary = NULL;
+#endif /* WCHAR */
+
+ /* Check for out-of-range STARTPOS. */
+ if (startpos < 0 || startpos > total_size)
+ return -1;
+
+ /* Fix up RANGE if it might eventually take us outside
+ the virtual concatenation of STRING1 and STRING2.
+ Make sure we won't move STARTPOS below 0 or above TOTAL_SIZE. */
+ if (endpos < 0)
+ range = 0 - startpos;
+ else if (endpos > total_size)
+ range = total_size - startpos;
+
+ /* If the search isn't to be a backwards one, don't waste time in a
+ search for a pattern that must be anchored. */
+ if (bufp->used > 0 && range > 0
+ && ((re_opcode_t) bufp->buffer[0] == begbuf
+ /* `begline' is like `begbuf' if it cannot match at newlines. */
+ || ((re_opcode_t) bufp->buffer[0] == begline
+ && !bufp->newline_anchor)))
+ {
+ if (startpos > 0)
+ return -1;
+ else
+ range = 1;
+ }
+
+#ifdef emacs
+ /* In a forward search for something that starts with \=.
+ don't keep searching past point. */
+ if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == at_dot && range > 0)
+ {
+ range = PT - startpos;
+ if (range <= 0)
+ return -1;
+ }
+#endif /* emacs */
+
+ /* Update the fastmap now if not correct already. */
+ if (fastmap && !bufp->fastmap_accurate)
+ if (re_compile_fastmap (bufp) == -2)
+ return -2;
+
+#ifdef WCHAR
+ /* Allocate wchar_t array for wcs_string1 and wcs_string2 and
+ fill them with converted string. */
+ if (size1 != 0)
+ {
+ if (size1 > MAX_ALLOCA_SIZE)
+ {
+ wcs_string1 = TALLOC (size1 + 1, CHAR_T);
+ mbs_offset1 = TALLOC (size1 + 1, int);
+ is_binary = TALLOC (size1 + 1, char);
+ }
+ else
+ {
+ wcs_string1 = REGEX_TALLOC (size1 + 1, CHAR_T);
+ mbs_offset1 = REGEX_TALLOC (size1 + 1, int);
+ is_binary = REGEX_TALLOC (size1 + 1, char);
+ }
+ if (!wcs_string1 || !mbs_offset1 || !is_binary)
+ {
+ if (size1 > MAX_ALLOCA_SIZE)
+ {
+ free (wcs_string1);
+ free (mbs_offset1);
+ free (is_binary);
+ }
+ else
+ {
+ FREE_VAR (wcs_string1);
+ FREE_VAR (mbs_offset1);
+ FREE_VAR (is_binary);
+ }
+ return -2;
+ }
+ wcs_size1 = convert_mbs_to_wcs(wcs_string1, string1, size1,
+ mbs_offset1, is_binary);
+ wcs_string1[wcs_size1] = L'\0'; /* for a sentinel */
+ if (size1 > MAX_ALLOCA_SIZE)
+ free (is_binary);
+ else
+ FREE_VAR (is_binary);
+ }
+ if (size2 != 0)
+ {
+ if (size2 > MAX_ALLOCA_SIZE)
+ {
+ wcs_string2 = TALLOC (size2 + 1, CHAR_T);
+ mbs_offset2 = TALLOC (size2 + 1, int);
+ is_binary = TALLOC (size2 + 1, char);
+ }
+ else
+ {
+ wcs_string2 = REGEX_TALLOC (size2 + 1, CHAR_T);
+ mbs_offset2 = REGEX_TALLOC (size2 + 1, int);
+ is_binary = REGEX_TALLOC (size2 + 1, char);
+ }
+ if (!wcs_string2 || !mbs_offset2 || !is_binary)
+ {
+ FREE_WCS_BUFFERS ();
+ if (size2 > MAX_ALLOCA_SIZE)
+ free (is_binary);
+ else
+ FREE_VAR (is_binary);
+ return -2;
+ }
+ wcs_size2 = convert_mbs_to_wcs(wcs_string2, string2, size2,
+ mbs_offset2, is_binary);
+ wcs_string2[wcs_size2] = L'\0'; /* for a sentinel */
+ if (size2 > MAX_ALLOCA_SIZE)
+ free (is_binary);
+ else
+ FREE_VAR (is_binary);
+ }
+#endif /* WCHAR */
+
+
+ /* 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_T 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)
+ {
+#ifdef WCHAR
+ FREE_WCS_BUFFERS ();
+#endif
+ return -1;
+ }
+
+#ifdef WCHAR
+ val = wcs_re_match_2_internal (bufp, string1, size1, string2,
+ size2, startpos, regs, stop,
+ wcs_string1, wcs_size1,
+ wcs_string2, wcs_size2,
+ mbs_offset1, mbs_offset2);
+#else /* BYTE */
+ val = byte_re_match_2_internal (bufp, string1, size1, string2,
+ size2, startpos, regs, stop);
+#endif /* BYTE */
+
+#ifndef REGEX_MALLOC
+# ifdef C_ALLOCA
+ alloca (0);
+# endif
+#endif
+
+ if (val >= 0)
+ {
+#ifdef WCHAR
+ FREE_WCS_BUFFERS ();
+#endif
+ return startpos;
+ }
+
+ if (val == -2)
+ {
+#ifdef WCHAR
+ FREE_WCS_BUFFERS ();
+#endif
+ return -2;
+ }
+
+ advance:
+ if (!range)
+ break;
+ else if (range > 0)
+ {
+ range--;
+ startpos++;
+ }
+ else
+ {
+ range++;
+ startpos--;
+ }
+ }
+#ifdef WCHAR
+ FREE_WCS_BUFFERS ();
+#endif
+ return -1;
+}
+
+#ifdef WCHAR
+/* This converts PTR, a pointer into one of the search wchar_t strings
+ `string1' and `string2' into an multibyte string offset from the
+ beginning of that string. We use mbs_offset to optimize.
+ See convert_mbs_to_wcs. */
+# define POINTER_TO_OFFSET(ptr) \
+ (FIRST_STRING_P (ptr) \
+ ? ((regoff_t)(mbs_offset1 != NULL? mbs_offset1[(ptr)-string1] : 0)) \
+ : ((regoff_t)((mbs_offset2 != NULL? mbs_offset2[(ptr)-string2] : 0) \
+ + csize1)))
+#else /* BYTE */
+/* This converts PTR, a pointer into one of the search strings `string1'
+ and `string2' into an offset from the beginning of that string. */
+# define POINTER_TO_OFFSET(ptr) \
+ (FIRST_STRING_P (ptr) \
+ ? ((regoff_t) ((ptr) - string1)) \
+ : ((regoff_t) ((ptr) - string2 + size1)))
+#endif /* WCHAR */
+
+/* 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. */
+#ifdef WCHAR
+/* Use internationalized API instead of SYNTAX. */
+# define WORDCHAR_P(d) \
+ (iswalnum ((wint_t)((d) == end1 ? *string2 \
+ : (d) == string2 - 1 ? *(end1 - 1) : *(d))) != 0 \
+ || ((d) == end1 ? *string2 \
+ : (d) == string2 - 1 ? *(end1 - 1) : *(d)) == L'_')
+#else /* BYTE */
+# define WORDCHAR_P(d) \
+ (SYNTAX ((d) == end1 ? *string2 \
+ : (d) == string2 - 1 ? *(end1 - 1) : *(d)) \
+ == Sword)
+#endif /* WCHAR */
+
+/* Disabled due to a compiler bug -- see comment at case wordbound */
+#if 0
+/* Test if the character before D and the one at D differ with respect
+ to being word-constituent. */
+#define AT_WORD_BOUNDARY(d) \
+ (AT_STRINGS_BEG (d) || AT_STRINGS_END (d) \
+ || WORDCHAR_P (d - 1) != WORDCHAR_P (d))
+#endif
+
+/* Free everything we malloc. */
+#ifdef MATCH_MAY_ALLOCATE
+# ifdef WCHAR
+# define FREE_VARIABLES() \
+ do { \
+ REGEX_FREE_STACK (fail_stack.stack); \
+ FREE_VAR (regstart); \
+ FREE_VAR (regend); \
+ FREE_VAR (old_regstart); \
+ FREE_VAR (old_regend); \
+ FREE_VAR (best_regstart); \
+ FREE_VAR (best_regend); \
+ FREE_VAR (reg_info); \
+ FREE_VAR (reg_dummy); \
+ FREE_VAR (reg_info_dummy); \
+ if (!cant_free_wcs_buf) \
+ { \
+ FREE_VAR (string1); \
+ FREE_VAR (string2); \
+ FREE_VAR (mbs_offset1); \
+ FREE_VAR (mbs_offset2); \
+ } \
+ } while (0)
+# else /* BYTE */
+# define FREE_VARIABLES() \
+ do { \
+ REGEX_FREE_STACK (fail_stack.stack); \
+ FREE_VAR (regstart); \
+ FREE_VAR (regend); \
+ FREE_VAR (old_regstart); \
+ FREE_VAR (old_regend); \
+ FREE_VAR (best_regstart); \
+ FREE_VAR (best_regend); \
+ FREE_VAR (reg_info); \
+ FREE_VAR (reg_dummy); \
+ FREE_VAR (reg_info_dummy); \
+ } while (0)
+# endif /* WCHAR */
+#else
+# ifdef WCHAR
+# define FREE_VARIABLES() \
+ do { \
+ if (!cant_free_wcs_buf) \
+ { \
+ FREE_VAR (string1); \
+ FREE_VAR (string2); \
+ FREE_VAR (mbs_offset1); \
+ FREE_VAR (mbs_offset2); \
+ } \
+ } while (0)
+# else /* BYTE */
+# define FREE_VARIABLES() ((void)0) /* Do nothing! But inhibit gcc warning. */
+# endif /* WCHAR */
+#endif /* not MATCH_MAY_ALLOCATE */
+
+/* These values must meet several constraints. They must not be valid
+ register values; since we have a limit of 255 registers (because
+ we use only one byte in the pattern for the register number), we can
+ use numbers larger than 255. They must differ by 1, because of
+ NUM_FAILURE_ITEMS above. And the value for the lowest register must
+ be larger than the value for the highest register, so we do not try
+ to actually save any registers when none are active. */
+#define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH)
+#define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1)
+
+#else /* not INSIDE_RECURSION */
+/* 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 (struct re_pattern_buffer *bufp,
+ const char *string,
+ int size, int pos,
+ struct re_registers *regs)
+{
+ int result;
+# ifdef MBS_SUPPORT
+ if (MB_CUR_MAX != 1)
+ result = wcs_re_match_2_internal (bufp, NULL, 0, string, size,
+ pos, regs, size,
+ NULL, 0, NULL, 0, NULL, NULL);
+ else
+# endif
+ result = byte_re_match_2_internal (bufp, NULL, 0, string, size,
+ pos, regs, size);
+# ifndef REGEX_MALLOC
+# ifdef C_ALLOCA
+ alloca (0);
+# endif
+# endif
+ return result;
+}
+# ifdef _LIBC
+weak_alias (__re_match, re_match)
+# endif
+#endif /* not emacs */
+
+#endif /* not INSIDE_RECURSION */
+
+#ifdef INSIDE_RECURSION
+static boolean PREFIX(group_match_null_string_p) (UCHAR_T **p,
+ UCHAR_T *end,
+ PREFIX(register_info_type) *reg_info);
+static boolean PREFIX(alt_match_null_string_p) (UCHAR_T *p,
+ UCHAR_T *end,
+ PREFIX(register_info_type) *reg_info);
+static boolean PREFIX(common_op_match_null_string_p) (UCHAR_T **p,
+ UCHAR_T *end,
+ PREFIX(register_info_type) *reg_info);
+static int PREFIX(bcmp_translate) (const CHAR_T *s1, const CHAR_T *s2,
+ int len, char *translate);
+#else /* not INSIDE_RECURSION */
+
+/* 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 (struct re_pattern_buffer *bufp,
+ const char *string1, int size1,
+ const char *string2, int size2,
+ int pos, struct re_registers *regs,
+ int stop)
+{
+ int result;
+# ifdef MBS_SUPPORT
+ if (MB_CUR_MAX != 1)
+ result = wcs_re_match_2_internal (bufp, string1, size1, string2, size2,
+ pos, regs, stop,
+ NULL, 0, NULL, 0, NULL, NULL);
+ else
+# endif
+ result = byte_re_match_2_internal (bufp, string1, size1, string2, size2,
+ pos, regs, stop);
+
+#ifndef REGEX_MALLOC
+# ifdef C_ALLOCA
+ alloca (0);
+# endif
+#endif
+ return result;
+}
+#ifdef _LIBC
+weak_alias (__re_match_2, re_match_2)
+#endif
+
+#endif /* not INSIDE_RECURSION */
+
+#ifdef INSIDE_RECURSION
+
+#ifdef WCHAR
+
+/* This check the substring (from 0, to length) of the multibyte string,
+ to which offset_buffer correspond. And count how many wchar_t_characters
+ the substring occupy. We use offset_buffer to optimization.
+ See convert_mbs_to_wcs. */
+
+static int
+count_mbs_length (int *offset_buffer, int length)
+{
+ int upper, lower;
+
+ /* Check whether the size is valid. */
+ if (length < 0)
+ return -1;
+
+ if (offset_buffer == NULL)
+ return 0;
+
+ /* If there are no multibyte character, offset_buffer[i] == i.
+ Optmize for this case. */
+ if (offset_buffer[length] == length)
+ return length;
+
+ /* Set up upper with length. (because for all i, offset_buffer[i] >= i) */
+ upper = length;
+ lower = 0;
+
+ while (true)
+ {
+ int middle = (lower + upper) / 2;
+ if (middle == lower || middle == upper)
+ break;
+ if (offset_buffer[middle] > length)
+ upper = middle;
+ else if (offset_buffer[middle] < length)
+ lower = middle;
+ else
+ return middle;
+ }
+
+ return -1;
+}
+#endif /* WCHAR */
+
+/* This is a separate function so that we can force an alloca cleanup
+ afterwards. */
+#ifdef WCHAR
+static int
+wcs_re_match_2_internal (struct re_pattern_buffer *bufp,
+ const char *cstring1, int csize1,
+ const char *cstring2, int csize2,
+ int pos,
+ struct re_registers *regs,
+ int stop,
+ /* string1 == string2 == NULL means
+ string1/2, size1/2 and mbs_offset1/2 need
+ setting up in this function. */
+ /* We need wchar_t * buffers corresponding to
+ cstring1, cstring2. */
+ wchar_t *string1, int size1,
+ wchar_t *string2, int size2,
+ /* Offset buffer for optimization. See
+ convert_mbs_to_wc. */
+ int *mbs_offset1,
+ int *mbs_offset2)
+#else /* BYTE */
+static int
+byte_re_match_2_internal (struct re_pattern_buffer *bufp,
+ const char *string1, int size1,
+ const char *string2, int size2,
+ int pos,
+ struct re_registers *regs,
+ int stop)
+#endif /* BYTE */
+{
+ /* General temporaries. */
+ int mcnt;
+ UCHAR_T *p1;
+#ifdef WCHAR
+ /* They hold whether each wchar_t is binary data or not. */
+ char *is_binary = NULL;
+ /* If true, we can't free string1/2, mbs_offset1/2. */
+ int cant_free_wcs_buf = 1;
+#endif /* WCHAR */
+
+ /* Just past the end of the corresponding string. */
+ const CHAR_T *end1, *end2;
+
+ /* Pointers into string1 and string2, just past the last characters in
+ each to consider matching. */
+ const CHAR_T *end_match_1, *end_match_2;
+
+ /* Where we are in the data, and the end of the current string. */
+ const CHAR_T *d, *dend;
+
+ /* Where we are in the pattern, and the end of the pattern. */
+#ifdef WCHAR
+ UCHAR_T *pattern, *p;
+ register UCHAR_T *pend;
+#else /* BYTE */
+ UCHAR_T *p = bufp->buffer;
+ register UCHAR_T *pend = p + bufp->used;
+#endif /* WCHAR */
+
+ /* Mark the opcode just after a start_memory, so we can test for an
+ empty subpattern when we get to the stop_memory. */
+ UCHAR_T *just_past_start_mem = 0;
+
+ /* We use this to map every character in the string. */
+ RE_TRANSLATE_TYPE translate = bufp->translate;
+
+ /* Failure point stack. Each place that can handle a failure further
+ down the line pushes a failure point on this stack. It consists of
+ restart, regend, and reg_info for all registers corresponding to
+ the subexpressions we're currently inside, plus the number of such
+ registers, and, finally, two char *'s. The first char * is where
+ to resume scanning the pattern; the second one is where to resume
+ scanning the strings. If the latter is zero, the failure point is
+ a ``dummy''; if a failure happens and the failure point is a dummy,
+ it gets discarded and the next next one is tried. */
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */
+ PREFIX(fail_stack_type) fail_stack;
+#endif
+#ifdef DEBUG
+ static unsigned failure_id;
+ unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0;
+#endif
+
+#ifdef REL_ALLOC
+ /* This holds the pointer to the failure stack, when
+ it is allocated relocatably. */
+ fail_stack_elt_t *failure_stack_ptr;
+#endif
+
+ /* We fill all the registers internally, independent of what we
+ return, for use in backreferences. The number here includes
+ an element for register zero. */
+ size_t num_regs = bufp->re_nsub + 1;
+
+ /* The currently active registers. */
+ active_reg_t lowest_active_reg = NO_LOWEST_ACTIVE_REG;
+ active_reg_t highest_active_reg = NO_HIGHEST_ACTIVE_REG;
+
+ /* Information on the contents of registers. These are pointers into
+ the input strings; they record just what was matched (on this
+ attempt) by a subexpression part of the pattern, that is, the
+ regnum-th regstart pointer points to where in the pattern we began
+ matching and the regnum-th regend points to right after where we
+ stopped matching the regnum-th subexpression. (The zeroth register
+ keeps track of what the whole pattern matches.) */
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */
+ const CHAR_T **regstart, **regend;
+#endif
+
+ /* If a group that's operated upon by a repetition operator fails to
+ match anything, then the register for its start will need to be
+ restored because it will have been set to wherever in the string we
+ are when we last see its open-group operator. Similarly for a
+ register's end. */
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */
+ const CHAR_T **old_regstart, **old_regend;
+#endif
+
+ /* The is_active field of reg_info helps us keep track of which (possibly
+ nested) subexpressions we are currently in. The matched_something
+ field of reg_info[reg_num] helps us tell whether or not we have
+ matched any of the pattern so far this time through the reg_num-th
+ subexpression. These two fields get reset each time through any
+ loop their register is in. */
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */
+ PREFIX(register_info_type) *reg_info;
+#endif
+
+ /* The following record the register info as found in the above
+ variables when we find a match better than any we've seen before.
+ This happens as we backtrack through the failure points, which in
+ turn happens only if we have not yet matched the entire string. */
+ unsigned best_regs_set = false;
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */
+ const CHAR_T **best_regstart, **best_regend;
+#endif
+
+ /* Logically, this is `best_regend[0]'. But we don't want to have to
+ allocate space for that if we're not allocating space for anything
+ else (see below). Also, we never need info about register 0 for
+ any of the other register vectors, and it seems rather a kludge to
+ treat `best_regend' differently than the rest. So we keep track of
+ the end of the best match so far in a separate variable. We
+ initialize this to NULL so that when we backtrack the first time
+ and need to test it, it's not garbage. */
+ const CHAR_T *match_end = NULL;
+
+ /* This helps SET_REGS_MATCHED avoid doing redundant work. */
+ int set_regs_matched_done = 0;
+
+ /* Used when we pop values we don't care about. */
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */
+ const CHAR_T **reg_dummy;
+ PREFIX(register_info_type) *reg_info_dummy;
+#endif
+
+#ifdef DEBUG
+ /* Counts the total number of registers pushed. */
+ unsigned num_regs_pushed = 0;
+#endif
+
+ /* Definitions for state transitions. More efficiently for gcc. */
+#ifdef __GNUC__
+# if defined HAVE_SUBTRACT_LOCAL_LABELS && defined SHARED
+# define NEXT \
+ do \
+ { \
+ int offset; \
+ const void *__unbounded ptr; \
+ offset = (p == pend \
+ ? 0 : jmptable[SWITCH_ENUM_CAST ((re_opcode_t) *p++)]); \
+ ptr = &&end_of_pattern + offset; \
+ goto *ptr; \
+ } \
+ while (0)
+# define REF(x) \
+ &&label_##x - &&end_of_pattern
+# define JUMP_TABLE_TYPE const int
+# else
+# define NEXT \
+ do \
+ { \
+ const void *__unbounded ptr; \
+ ptr = (p == pend ? &&end_of_pattern \
+ : jmptable[SWITCH_ENUM_CAST ((re_opcode_t) *p++)]); \
+ goto *ptr; \
+ } \
+ while (0)
+# define REF(x) \
+ &&label_##x
+# define JUMP_TABLE_TYPE const void *const
+# endif
+# define CASE(x) label_##x
+ static JUMP_TABLE_TYPE jmptable[] =
+ {
+ REF (no_op),
+ REF (succeed),
+ REF (exactn),
+# ifdef MBS_SUPPORT
+ REF (exactn_bin),
+# endif
+ REF (anychar),
+ REF (charset),
+ REF (charset_not),
+ REF (start_memory),
+ REF (stop_memory),
+ REF (duplicate),
+ REF (begline),
+ REF (endline),
+ REF (begbuf),
+ REF (endbuf),
+ REF (jump),
+ REF (jump_past_alt),
+ REF (on_failure_jump),
+ REF (on_failure_keep_string_jump),
+ REF (pop_failure_jump),
+ REF (maybe_pop_jump),
+ REF (dummy_failure_jump),
+ REF (push_dummy_failure),
+ REF (succeed_n),
+ REF (jump_n),
+ REF (set_number_at),
+ REF (wordchar),
+ REF (notwordchar),
+ REF (wordbeg),
+ REF (wordend),
+ REF (wordbound),
+ REF (notwordbound)
+# ifdef emacs
+ ,REF (before_dot),
+ REF (at_dot),
+ REF (after_dot),
+ REF (syntaxspec),
+ REF (notsyntaxspec)
+# endif
+ };
+#else
+# define NEXT \
+ break
+# define CASE(x) \
+ case x
+#endif
+
+ DEBUG_PRINT1 ("\n\nEntering re_match_2.\n");
+
+ INIT_FAIL_STACK ();
+
+#ifdef MATCH_MAY_ALLOCATE
+ /* Do not bother to initialize all the register variables if there are
+ no groups in the pattern, as it takes a fair amount of time. If
+ there are groups, we include space for register 0 (the whole
+ pattern), even though we never use it, since it simplifies the
+ array indexing. We should fix this. */
+ if (bufp->re_nsub)
+ {
+ regstart = REGEX_TALLOC (num_regs, const CHAR_T *);
+ regend = REGEX_TALLOC (num_regs, const CHAR_T *);
+ old_regstart = REGEX_TALLOC (num_regs, const CHAR_T *);
+ old_regend = REGEX_TALLOC (num_regs, const CHAR_T *);
+ best_regstart = REGEX_TALLOC (num_regs, const CHAR_T *);
+ best_regend = REGEX_TALLOC (num_regs, const CHAR_T *);
+ reg_info = REGEX_TALLOC (num_regs, PREFIX(register_info_type));
+ reg_dummy = REGEX_TALLOC (num_regs, const CHAR_T *);
+ reg_info_dummy = REGEX_TALLOC (num_regs, PREFIX(register_info_type));
+
+ if (!(regstart && regend && old_regstart && old_regend && reg_info
+ && best_regstart && best_regend && reg_dummy && reg_info_dummy))
+ {
+ FREE_VARIABLES ();
+ return -2;
+ }
+ }
+ else
+ {
+ /* We must initialize all our variables to NULL, so that
+ `FREE_VARIABLES' doesn't try to free them. */
+ regstart = regend = old_regstart = old_regend = best_regstart
+ = best_regend = reg_dummy = NULL;
+ reg_info = reg_info_dummy = (PREFIX(register_info_type) *) NULL;
+ }
+#endif /* MATCH_MAY_ALLOCATE */
+
+ /* The starting position is bogus. */
+#ifdef WCHAR
+ if (pos < 0 || pos > csize1 + csize2)
+#else /* BYTE */
+ if (pos < 0 || pos > size1 + size2)
+#endif
+ {
+ FREE_VARIABLES ();
+ return -1;
+ }
+
+#ifdef WCHAR
+ /* Allocate wchar_t array for string1 and string2 and
+ fill them with converted string. */
+ if (string1 == NULL && string2 == NULL)
+ {
+ /* We need seting up buffers here. */
+
+ /* We must free wcs buffers in this function. */
+ cant_free_wcs_buf = 0;
+
+ if (csize1 != 0)
+ {
+ string1 = REGEX_TALLOC (csize1 + 1, CHAR_T);
+ mbs_offset1 = REGEX_TALLOC (csize1 + 1, int);
+ is_binary = REGEX_TALLOC (csize1 + 1, char);
+ if (!string1 || !mbs_offset1 || !is_binary)
+ {
+ FREE_VAR (string1);
+ FREE_VAR (mbs_offset1);
+ FREE_VAR (is_binary);
+ return -2;
+ }
+ }
+ if (csize2 != 0)
+ {
+ string2 = REGEX_TALLOC (csize2 + 1, CHAR_T);
+ mbs_offset2 = REGEX_TALLOC (csize2 + 1, int);
+ is_binary = REGEX_TALLOC (csize2 + 1, char);
+ if (!string2 || !mbs_offset2 || !is_binary)
+ {
+ FREE_VAR (string1);
+ FREE_VAR (mbs_offset1);
+ FREE_VAR (string2);
+ FREE_VAR (mbs_offset2);
+ FREE_VAR (is_binary);
+ return -2;
+ }
+ size2 = convert_mbs_to_wcs(string2, cstring2, csize2,
+ mbs_offset2, is_binary);
+ string2[size2] = L'\0'; /* for a sentinel */
+ FREE_VAR (is_binary);
+ }
+ }
+
+ /* We need to cast pattern to (wchar_t*), because we casted this compiled
+ pattern to (char*) in regex_compile. */
+ p = pattern = (CHAR_T*)bufp->buffer;
+ pend = (CHAR_T*)(bufp->buffer + bufp->used);
+
+#endif /* WCHAR */
+
+ /* Initialize subexpression text positions to -1 to mark ones that no
+ start_memory/stop_memory has been seen for. Also initialize the
+ register information struct. */
+ for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++)
+ {
+ regstart[mcnt] = regend[mcnt]
+ = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE;
+
+ REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE;
+ IS_ACTIVE (reg_info[mcnt]) = 0;
+ MATCHED_SOMETHING (reg_info[mcnt]) = 0;
+ EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0;
+ }
+
+ /* We move `string1' into `string2' if the latter's empty -- but not if
+ `string1' is null. */
+ if (size2 == 0 && string1 != NULL)
+ {
+ string2 = string1;
+ size2 = size1;
+ string1 = 0;
+ size1 = 0;
+#ifdef WCHAR
+ mbs_offset2 = mbs_offset1;
+ csize2 = csize1;
+ mbs_offset1 = NULL;
+ csize1 = 0;
+#endif
+ }
+ end1 = string1 + size1;
+ end2 = string2 + size2;
+
+ /* Compute where to stop matching, within the two strings. */
+#ifdef WCHAR
+ if (stop <= csize1)
+ {
+ mcnt = count_mbs_length(mbs_offset1, stop);
+ end_match_1 = string1 + mcnt;
+ end_match_2 = string2;
+ }
+ else
+ {
+ if (stop > csize1 + csize2)
+ stop = csize1 + csize2;
+ end_match_1 = end1;
+ mcnt = count_mbs_length(mbs_offset2, stop-csize1);
+ end_match_2 = string2 + mcnt;
+ }
+ if (mcnt < 0)
+ { /* count_mbs_length return error. */
+ FREE_VARIABLES ();
+ return -1;
+ }
+#else
+ if (stop <= size1)
+ {
+ end_match_1 = string1 + stop;
+ end_match_2 = string2;
+ }
+ else
+ {
+ end_match_1 = end1;
+ end_match_2 = string2 + stop - size1;
+ }
+#endif /* WCHAR */
+
+ /* `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'. */
+#ifdef WCHAR
+ if (size1 > 0 && pos <= csize1)
+ {
+ mcnt = count_mbs_length(mbs_offset1, pos);
+ d = string1 + mcnt;
+ dend = end_match_1;
+ }
+ else
+ {
+ mcnt = count_mbs_length(mbs_offset2, pos-csize1);
+ d = string2 + mcnt;
+ dend = end_match_2;
+ }
+
+ if (mcnt < 0)
+ { /* count_mbs_length return error. */
+ FREE_VARIABLES ();
+ return -1;
+ }
+#else
+ if (size1 > 0 && pos <= size1)
+ {
+ d = string1 + pos;
+ dend = end_match_1;
+ }
+ else
+ {
+ d = string2 + pos - size1;
+ dend = end_match_2;
+ }
+#endif /* WCHAR */
+
+ DEBUG_PRINT1 ("The compiled pattern is:\n");
+ DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend);
+ DEBUG_PRINT1 ("The string to match is: `");
+ DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2);
+ DEBUG_PRINT1 ("'\n");
+
+ /* This loops over pattern commands. It exits by returning from the
+ function if the match is complete, or it drops through if the match
+ fails at this starting point in the input data. */
+ for (;;)
+ {
+#ifdef _LIBC
+ DEBUG_PRINT2 ("\n%p: ", p);
+#else
+ DEBUG_PRINT2 ("\n0x%x: ", p);
+#endif
+
+#ifdef __GNUC__
+ NEXT;
+#else
+ if (p == pend)
+#endif
+ {
+#ifdef __GNUC__
+ end_of_pattern:
+#endif
+ /* End of pattern means we might have succeeded. */
+ DEBUG_PRINT1 ("end of pattern ... ");
+
+ /* If we haven't matched the entire string, and we want the
+ longest match, try backtracking. */
+ if (d != end_match_2)
+ {
+ /* 1 if this match ends in the same string (string1 or string2)
+ as the best previous match. */
+ boolean same_str_p = (FIRST_STRING_P (match_end)
+ == MATCHING_IN_FIRST_STRING);
+ /* 1 if this match is the best seen so far. */
+ boolean best_match_p;
+
+ /* AIX compiler got confused when this was combined
+ with the previous declaration. */
+ if (same_str_p)
+ best_match_p = d > match_end;
+ else
+ best_match_p = !MATCHING_IN_FIRST_STRING;
+
+ DEBUG_PRINT1 ("backtracking.\n");
+
+ if (!FAIL_STACK_EMPTY ())
+ { /* More failure points to try. */
+
+ /* If exceeds best match so far, save it. */
+ if (!best_regs_set || best_match_p)
+ {
+ best_regs_set = true;
+ match_end = d;
+
+ DEBUG_PRINT1 ("\nSAVING match as best so far.\n");
+
+ for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++)
+ {
+ best_regstart[mcnt] = regstart[mcnt];
+ best_regend[mcnt] = regend[mcnt];
+ }
+ }
+ goto fail;
+ }
+
+ /* If no failure points, don't restore garbage. And if
+ last match is real best match, don't restore second
+ best one. */
+ else if (best_regs_set && !best_match_p)
+ {
+ restore_best_regs:
+ /* Restore best match. It may happen that `dend ==
+ end_match_1' while the restored d is in string2.
+ For example, the pattern `x.*y.*z' against the
+ strings `x-' and `y-z-', if the two strings are
+ not consecutive in memory. */
+ DEBUG_PRINT1 ("Restoring best registers.\n");
+
+ d = match_end;
+ dend = ((d >= string1 && d <= end1)
+ ? end_match_1 : end_match_2);
+
+ for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++)
+ {
+ regstart[mcnt] = best_regstart[mcnt];
+ regend[mcnt] = best_regend[mcnt];
+ }
+ }
+ } /* d != end_match_2 */
+
+ succeed_label:
+ DEBUG_PRINT1 ("Accepting match.\n");
+ /* If caller wants register contents data back, do it. */
+ if (regs && !bufp->no_sub)
+ {
+ /* Have the register data arrays been allocated? */
+ if (bufp->regs_allocated == REGS_UNALLOCATED)
+ { /* No. So allocate them with malloc. We need one
+ extra element beyond `num_regs' for the `-1' marker
+ GNU code uses. */
+ regs->num_regs = MAX (RE_NREGS, num_regs + 1);
+ regs->start = TALLOC (regs->num_regs, regoff_t);
+ regs->end = TALLOC (regs->num_regs, regoff_t);
+ if (regs->start == NULL || regs->end == NULL)
+ {
+ FREE_VARIABLES ();
+ return -2;
+ }
+ bufp->regs_allocated = REGS_REALLOCATE;
+ }
+ else if (bufp->regs_allocated == REGS_REALLOCATE)
+ { /* Yes. If we need more elements than were already
+ allocated, reallocate them. If we need fewer, just
+ leave it alone. */
+ if (regs->num_regs < num_regs + 1)
+ {
+ regs->num_regs = num_regs + 1;
+ RETALLOC (regs->start, regs->num_regs, regoff_t);
+ RETALLOC (regs->end, regs->num_regs, regoff_t);
+ if (regs->start == NULL || regs->end == NULL)
+ {
+ FREE_VARIABLES ();
+ return -2;
+ }
+ }
+ }
+ else
+ {
+ /* These braces fend off a "empty body in an else-statement"
+ warning under GCC when assert expands to nothing. */
+ assert (bufp->regs_allocated == REGS_FIXED);
+ }
+
+ /* Convert the pointer data in `regstart' and `regend' to
+ indices. Register zero has to be set differently,
+ since we haven't kept track of any info for it. */
+ if (regs->num_regs > 0)
+ {
+ regs->start[0] = pos;
+#ifdef WCHAR
+ if (MATCHING_IN_FIRST_STRING)
+ regs->end[0] = (mbs_offset1 != NULL ?
+ mbs_offset1[d-string1] : 0);
+ else
+ regs->end[0] = csize1 + (mbs_offset2 != NULL
+ ? mbs_offset2[d-string2] : 0);
+#else
+ regs->end[0] = (MATCHING_IN_FIRST_STRING
+ ? ((regoff_t) (d - string1))
+ : ((regoff_t) (d - string2 + size1)));
+#endif /* WCHAR */
+ }
+
+ /* Go through the first `min (num_regs, regs->num_regs)'
+ registers, since that is all we initialized. */
+ for (mcnt = 1; (unsigned) mcnt < MIN (num_regs, regs->num_regs);
+ mcnt++)
+ {
+ if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt]))
+ regs->start[mcnt] = regs->end[mcnt] = -1;
+ else
+ {
+ regs->start[mcnt]
+ = (regoff_t) POINTER_TO_OFFSET (regstart[mcnt]);
+ regs->end[mcnt]
+ = (regoff_t) POINTER_TO_OFFSET (regend[mcnt]);
+ }
+ }
+
+ /* If the regs structure we return has more elements than
+ were in the pattern, set the extra elements to -1. If
+ we (re)allocated the registers, this is the case,
+ because we always allocate enough to have at least one
+ -1 at the end. */
+ for (mcnt = num_regs; (unsigned) mcnt < regs->num_regs; mcnt++)
+ regs->start[mcnt] = regs->end[mcnt] = -1;
+ } /* regs && !bufp->no_sub */
+
+ DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n",
+ nfailure_points_pushed, nfailure_points_popped,
+ nfailure_points_pushed - nfailure_points_popped);
+ DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed);
+
+#ifdef WCHAR
+ if (MATCHING_IN_FIRST_STRING)
+ mcnt = mbs_offset1 != NULL ? mbs_offset1[d-string1] : 0;
+ else
+ mcnt = (mbs_offset2 != NULL ? mbs_offset2[d-string2] : 0) +
+ csize1;
+ mcnt -= pos;
+#else
+ mcnt = d - pos - (MATCHING_IN_FIRST_STRING
+ ? string1 : string2 - size1);
+#endif /* WCHAR */
+
+ DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt);
+
+ FREE_VARIABLES ();
+ return mcnt;
+ }
+
+#ifndef __GNUC__
+ /* Otherwise match next pattern command. */
+ switch (SWITCH_ENUM_CAST ((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");
+ NEXT;
+
+ CASE (succeed):
+ DEBUG_PRINT1 ("EXECUTING succeed.\n");
+ goto succeed_label;
+
+ /* Match the next n pattern characters exactly. The following
+ byte in the pattern defines n, and the n bytes after that
+ are the characters to match. */
+ CASE (exactn):
+#ifdef MBS_SUPPORT
+ CASE (exactn_bin):
+#endif
+ 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 ();
+#ifdef WCHAR
+ if (*d <= 0xff)
+ {
+ if ((UCHAR_T) translate[(unsigned char) *d++]
+ != (UCHAR_T) *p++)
+ goto fail;
+ }
+ else
+ {
+ if (*d++ != (CHAR_T) *p++)
+ goto fail;
+ }
+#else
+ if ((UCHAR_T) translate[(unsigned char) *d++]
+ != (UCHAR_T) *p++)
+ goto fail;
+#endif /* WCHAR */
+ }
+ while (--mcnt);
+ }
+ else
+ {
+ do
+ {
+ PREFETCH ();
+ if (*d++ != (CHAR_T) *p++) goto fail;
+ }
+ while (--mcnt);
+ }
+ SET_REGS_MATCHED ();
+ NEXT;
+
+
+ /* 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 `%ld'.\n", (long int) *d);
+ d++;
+ NEXT;
+
+
+ CASE (charset):
+ CASE (charset_not):
+ {
+ register UCHAR_T c;
+#ifdef WCHAR
+ unsigned int i, char_class_length, coll_symbol_length,
+ equiv_class_length, ranges_length, chars_length, length;
+ CHAR_T *workp, *workp2, *charset_top;
+#define WORK_BUFFER_SIZE 128
+ CHAR_T str_buf[WORK_BUFFER_SIZE];
+# ifdef _LIBC
+ uint32_t nrules;
+# endif /* _LIBC */
+#endif /* WCHAR */
+ 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. */
+#ifdef WCHAR
+# ifdef _LIBC
+ nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+# endif /* _LIBC */
+ charset_top = p - 1;
+ char_class_length = *p++;
+ coll_symbol_length = *p++;
+ equiv_class_length = *p++;
+ ranges_length = *p++;
+ chars_length = *p++;
+ /* p points charset[6], so the address of the next instruction
+ (charset[l+m+n+2o+k+p']) equals p[l+m+n+2*o+p'],
+ where l=length of char_classes, m=length of collating_symbol,
+ n=equivalence_class, o=length of char_range,
+ p'=length of character. */
+ workp = p;
+ /* Update p to indicate the next instruction. */
+ p += char_class_length + coll_symbol_length+ equiv_class_length +
+ 2*ranges_length + chars_length;
+
+ /* match with char_class? */
+ for (i = 0; i < char_class_length ; i += CHAR_CLASS_SIZE)
+ {
+ wctype_t wctype;
+ uintptr_t alignedp = ((uintptr_t)workp
+ + __alignof__(wctype_t) - 1)
+ & ~(uintptr_t)(__alignof__(wctype_t) - 1);
+ wctype = *((wctype_t*)alignedp);
+ workp += CHAR_CLASS_SIZE;
+ if (iswctype((wint_t)c, wctype))
+ goto char_set_matched;
+ }
+
+ /* match with collating_symbol? */
+# ifdef _LIBC
+ if (nrules != 0)
+ {
+ const unsigned char *extra = (const unsigned char *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB);
+
+ for (workp2 = workp + coll_symbol_length ; workp < workp2 ;
+ workp++)
+ {
+ int32_t *wextra;
+ wextra = (int32_t*)(extra + *workp++);
+ for (i = 0; i < *wextra; ++i)
+ if (TRANSLATE(d[i]) != wextra[1 + i])
+ break;
+
+ if (i == *wextra)
+ {
+ /* Update d, however d will be incremented at
+ char_set_matched:, we decrement d here. */
+ d += i - 1;
+ goto char_set_matched;
+ }
+ }
+ }
+ else /* (nrules == 0) */
+# endif
+ /* If we can't look up collation data, we use wcscoll
+ instead. */
+ {
+ for (workp2 = workp + coll_symbol_length ; workp < workp2 ;)
+ {
+ const CHAR_T *backup_d = d, *backup_dend = dend;
+ length = wcslen (workp);
+
+ /* If wcscoll(the collating symbol, whole string) > 0,
+ any substring of the string never match with the
+ collating symbol. */
+ if (wcscoll (workp, d) > 0)
+ {
+ workp += length + 1;
+ continue;
+ }
+
+ /* First, we compare the collating symbol with
+ the first character of the string.
+ If it don't match, we add the next character to
+ the compare buffer in turn. */
+ for (i = 0 ; i < WORK_BUFFER_SIZE-1 ; i++, d++)
+ {
+ int match;
+ if (d == dend)
+ {
+ if (dend == end_match_2)
+ break;
+ d = string2;
+ dend = end_match_2;
+ }
+
+ /* add next character to the compare buffer. */
+ str_buf[i] = TRANSLATE(*d);
+ str_buf[i+1] = '\0';
+
+ match = wcscoll (workp, str_buf);
+ if (match == 0)
+ goto char_set_matched;
+
+ if (match < 0)
+ /* (str_buf > workp) indicate (str_buf + X > workp),
+ because for all X (str_buf + X > str_buf).
+ So we don't need continue this loop. */
+ break;
+
+ /* Otherwise(str_buf < workp),
+ (str_buf+next_character) may equals (workp).
+ So we continue this loop. */
+ }
+ /* not matched */
+ d = backup_d;
+ dend = backup_dend;
+ workp += length + 1;
+ }
+ }
+ /* match with equivalence_class? */
+# ifdef _LIBC
+ if (nrules != 0)
+ {
+ const CHAR_T *backup_d = d, *backup_dend = dend;
+ /* Try to match the equivalence class against
+ those known to the collate implementation. */
+ const int32_t *table;
+ const int32_t *weights;
+ const int32_t *extra;
+ const int32_t *indirect;
+ int32_t idx, idx2;
+ wint_t *cp;
+ size_t len;
+
+ /* This #include defines a local function! */
+# include <locale/weightwc.h>
+
+ table = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEWC);
+ weights = (const wint_t *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTWC);
+ extra = (const wint_t *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAWC);
+ indirect = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTWC);
+
+ /* Write 1 collating element to str_buf, and
+ get its index. */
+ idx2 = 0;
+
+ for (i = 0 ; idx2 == 0 && i < WORK_BUFFER_SIZE - 1; i++)
+ {
+ cp = (wint_t*)str_buf;
+ if (d == dend)
+ {
+ if (dend == end_match_2)
+ break;
+ d = string2;
+ dend = end_match_2;
+ }
+ str_buf[i] = TRANSLATE(*(d+i));
+ str_buf[i+1] = '\0'; /* sentinel */
+ idx2 = findidx ((const wint_t**)&cp);
+ }
+
+ /* Update d, however d will be incremented at
+ char_set_matched:, we decrement d here. */
+ d = backup_d + ((wchar_t*)cp - (wchar_t*)str_buf - 1);
+ if (d >= dend)
+ {
+ if (dend == end_match_2)
+ d = dend;
+ else
+ {
+ d = string2;
+ dend = end_match_2;
+ }
+ }
+
+ len = weights[idx2];
+
+ for (workp2 = workp + equiv_class_length ; workp < workp2 ;
+ workp++)
+ {
+ idx = (int32_t)*workp;
+ /* We already checked idx != 0 in regex_compile. */
+
+ if (idx2 != 0 && len == weights[idx])
+ {
+ int cnt = 0;
+ while (cnt < len && (weights[idx + 1 + cnt]
+ == weights[idx2 + 1 + cnt]))
+ ++cnt;
+
+ if (cnt == len)
+ goto char_set_matched;
+ }
+ }
+ /* not matched */
+ d = backup_d;
+ dend = backup_dend;
+ }
+ else /* (nrules == 0) */
+# endif
+ /* If we can't look up collation data, we use wcscoll
+ instead. */
+ {
+ for (workp2 = workp + equiv_class_length ; workp < workp2 ;)
+ {
+ const CHAR_T *backup_d = d, *backup_dend = dend;
+ length = wcslen (workp);
+
+ /* If wcscoll(the collating symbol, whole string) > 0,
+ any substring of the string never match with the
+ collating symbol. */
+ if (wcscoll (workp, d) > 0)
+ {
+ workp += length + 1;
+ break;
+ }
+
+ /* First, we compare the equivalence class with
+ the first character of the string.
+ If it don't match, we add the next character to
+ the compare buffer in turn. */
+ for (i = 0 ; i < WORK_BUFFER_SIZE - 1 ; i++, d++)
+ {
+ int match;
+ if (d == dend)
+ {
+ if (dend == end_match_2)
+ break;
+ d = string2;
+ dend = end_match_2;
+ }
+
+ /* add next character to the compare buffer. */
+ str_buf[i] = TRANSLATE(*d);
+ str_buf[i+1] = '\0';
+
+ match = wcscoll (workp, str_buf);
+
+ if (match == 0)
+ goto char_set_matched;
+
+ if (match < 0)
+ /* (str_buf > workp) indicate (str_buf + X > workp),
+ because for all X (str_buf + X > str_buf).
+ So we don't need continue this loop. */
+ break;
+
+ /* Otherwise(str_buf < workp),
+ (str_buf+next_character) may equals (workp).
+ So we continue this loop. */
+ }
+ /* not matched */
+ d = backup_d;
+ dend = backup_dend;
+ workp += length + 1;
+ }
+ }
+
+ /* match with char_range? */
+# ifdef _LIBC
+ if (nrules != 0)
+ {
+ uint32_t collseqval;
+ const char *collseq = (const char *)
+ _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC);
+
+ collseqval = collseq_table_lookup (collseq, c);
+
+ for (; workp < p - chars_length ;)
+ {
+ uint32_t start_val, end_val;
+
+ /* We already compute the collation sequence value
+ of the characters (or collating symbols). */
+ start_val = (uint32_t) *workp++; /* range_start */
+ end_val = (uint32_t) *workp++; /* range_end */
+
+ if (start_val <= collseqval && collseqval <= end_val)
+ goto char_set_matched;
+ }
+ }
+ else
+# endif
+ {
+ /* We set range_start_char at str_buf[0], range_end_char
+ at str_buf[4], and compared char at str_buf[2]. */
+ str_buf[1] = 0;
+ str_buf[2] = c;
+ str_buf[3] = 0;
+ str_buf[5] = 0;
+ for (; workp < p - chars_length ;)
+ {
+ wchar_t *range_start_char, *range_end_char;
+
+ /* match if (range_start_char <= c <= range_end_char). */
+
+ /* If range_start(or end) < 0, we assume -range_start(end)
+ is the offset of the collating symbol which is specified
+ as the character of the range start(end). */
+
+ /* range_start */
+ if (*workp < 0)
+ range_start_char = charset_top - (*workp++);
+ else
+ {
+ str_buf[0] = *workp++;
+ range_start_char = str_buf;
+ }
+
+ /* range_end */
+ if (*workp < 0)
+ range_end_char = charset_top - (*workp++);
+ else
+ {
+ str_buf[4] = *workp++;
+ range_end_char = str_buf + 4;
+ }
+
+ if (wcscoll (range_start_char, str_buf+2) <= 0
+ && wcscoll (str_buf+2, range_end_char) <= 0)
+ goto char_set_matched;
+ }
+ }
+
+ /* match with char? */
+ for (; workp < p ; workp++)
+ if (c == *workp)
+ goto char_set_matched;
+
+ not = !not;
+
+ char_set_matched:
+ if (not) goto fail;
+#else
+ /* 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;
+#undef WORK_BUFFER_SIZE
+#endif /* WCHAR */
+ SET_REGS_MATCHED ();
+ d++;
+ NEXT;
+ }
+
+
+ /* 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 %ld (%ld):\n",
+ (long int) *p, (long int) 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])
+ = PREFIX(group_match_null_string_p) (&p1, pend, reg_info);
+
+ /* Save the position in the string where we were the last time
+ we were at this open-group operator in case the group is
+ operated upon by a repetition operator, e.g., with `(a*)*b'
+ against `ab'; then we want to ignore where we are now in
+ the string in case this attempt to match fails. */
+ old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
+ ? REG_UNSET (regstart[*p]) ? d : regstart[*p]
+ : regstart[*p];
+ DEBUG_PRINT2 (" old_regstart: %d\n",
+ POINTER_TO_OFFSET (old_regstart[*p]));
+
+ regstart[*p] = d;
+ DEBUG_PRINT2 (" regstart: %d\n", POINTER_TO_OFFSET (regstart[*p]));
+
+ IS_ACTIVE (reg_info[*p]) = 1;
+ MATCHED_SOMETHING (reg_info[*p]) = 0;
+
+ /* Clear this whenever we change the register activity status. */
+ set_regs_matched_done = 0;
+
+ /* This is the new highest active register. */
+ highest_active_reg = *p;
+
+ /* If nothing was active before, this is the new lowest active
+ register. */
+ if (lowest_active_reg == NO_LOWEST_ACTIVE_REG)
+ lowest_active_reg = *p;
+
+ /* Move past the register number and inner group count. */
+ p += 2;
+ just_past_start_mem = p;
+
+ NEXT;
+
+
+ /* 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 %ld (%ld):\n",
+ (long int) *p, (long int) p[1]);
+
+ /* We need to save the string position the last time we were at
+ this close-group operator in case the group is operated
+ upon by a repetition operator, e.g., with `((a*)*(b*)*)*'
+ against `aba'; then we want to ignore where we are now in
+ the string in case this attempt to match fails. */
+ old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
+ ? REG_UNSET (regend[*p]) ? d : regend[*p]
+ : regend[*p];
+ DEBUG_PRINT2 (" old_regend: %d\n",
+ POINTER_TO_OFFSET (old_regend[*p]));
+
+ regend[*p] = d;
+ DEBUG_PRINT2 (" regend: %d\n", POINTER_TO_OFFSET (regend[*p]));
+
+ /* This register isn't active anymore. */
+ IS_ACTIVE (reg_info[*p]) = 0;
+
+ /* Clear this whenever we change the register activity status. */
+ set_regs_matched_done = 0;
+
+ /* If this was the only register active, nothing is active
+ anymore. */
+ if (lowest_active_reg == highest_active_reg)
+ {
+ lowest_active_reg = NO_LOWEST_ACTIVE_REG;
+ highest_active_reg = NO_HIGHEST_ACTIVE_REG;
+ }
+ else
+ { /* We must scan for the new highest active register, since
+ it isn't necessarily one less than now: consider
+ (a(b)c(d(e)f)g). When group 3 ends, after the f), the
+ new highest active register is 1. */
+ UCHAR_T r = *p - 1;
+ while (r > 0 && !IS_ACTIVE (reg_info[r]))
+ r--;
+
+ /* If we end up at register zero, that means that we saved
+ the registers as the result of an `on_failure_jump', not
+ a `start_memory', and we jumped to past the innermost
+ `stop_memory'. For example, in ((.)*) we save
+ registers 1 and 2 as a result of the *, but when we pop
+ back to the second ), we are at the stop_memory 1.
+ Thus, nothing is active. */
+ if (r == 0)
+ {
+ lowest_active_reg = NO_LOWEST_ACTIVE_REG;
+ highest_active_reg = NO_HIGHEST_ACTIVE_REG;
+ }
+ else
+ highest_active_reg = r;
+ }
+
+ /* If just failed to match something this time around with a
+ group that's operated on by a repetition operator, try to
+ force exit from the ``loop'', and restore the register
+ information for this group that we had before trying this
+ last match. */
+ if ((!MATCHED_SOMETHING (reg_info[*p])
+ || just_past_start_mem == p - 1)
+ && (p + 2) < pend)
+ {
+ boolean is_a_jump_n = false;
+
+ p1 = p + 2;
+ mcnt = 0;
+ switch ((re_opcode_t) *p1++)
+ {
+ case jump_n:
+ is_a_jump_n = true;
+ case pop_failure_jump:
+ case maybe_pop_jump:
+ case jump:
+ case dummy_failure_jump:
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+ if (is_a_jump_n)
+ p1 += OFFSET_ADDRESS_SIZE;
+ 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[1+OFFSET_ADDRESS_SIZE] == start_memory
+ && p1[2+OFFSET_ADDRESS_SIZE] == *p)
+ {
+ /* If this group ever matched anything, then restore
+ what its registers were before trying this last
+ failed match, e.g., with `(a*)*b' against `ab' for
+ regstart[1], and, e.g., with `((a*)*(b*)*)*'
+ against `aba' for regend[3].
+
+ Also restore the registers for inner groups for,
+ e.g., `((a*)(b*))*' against `aba' (register 3 would
+ otherwise get trashed). */
+
+ if (EVER_MATCHED_SOMETHING (reg_info[*p]))
+ {
+ unsigned r;
+
+ EVER_MATCHED_SOMETHING (reg_info[*p]) = 0;
+
+ /* Restore this and inner groups' (if any) registers. */
+ for (r = *p; r < (unsigned) *p + (unsigned) *(p + 1);
+ r++)
+ {
+ regstart[r] = old_regstart[r];
+
+ /* xx why this test? */
+ if (old_regend[r] >= regstart[r])
+ regend[r] = old_regend[r];
+ }
+ }
+ p1++;
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+ PUSH_FAILURE_POINT (p1 + mcnt, d, -2);
+
+ goto fail;
+ }
+ }
+
+ /* Move past the register number and the inner group count. */
+ p += 2;
+ NEXT;
+
+
+ /* \<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_T *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
+ ? PREFIX(bcmp_translate) (d, d2, mcnt, translate)
+ : memcmp (d, d2, mcnt*sizeof(UCHAR_T)))
+ goto fail;
+ d += mcnt, d2 += mcnt;
+
+ /* Do this because we've match some characters. */
+ SET_REGS_MATCHED ();
+ }
+ }
+ NEXT;
+
+
+ /* 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)
+ {
+ NEXT;
+ }
+ }
+ else if (d[-1] == '\n' && bufp->newline_anchor)
+ {
+ NEXT;
+ }
+ /* 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)
+ {
+ NEXT;
+ }
+ }
+
+ /* We have to ``prefetch'' the next character. */
+ else if ((d == end1 ? *string2 : *d) == '\n'
+ && bufp->newline_anchor)
+ {
+ NEXT;
+ }
+ goto fail;
+
+
+ /* Match at the very beginning of the data. */
+ CASE (begbuf):
+ DEBUG_PRINT1 ("EXECUTING begbuf.\n");
+ if (AT_STRINGS_BEG (d))
+ {
+ NEXT;
+ }
+ goto fail;
+
+
+ /* Match at the very end of the data. */
+ CASE (endbuf):
+ DEBUG_PRINT1 ("EXECUTING endbuf.\n");
+ if (AT_STRINGS_END (d))
+ {
+ NEXT;
+ }
+ goto fail;
+
+
+ /* on_failure_keep_string_jump is used to optimize `.*\n'. It
+ pushes NULL as the value for the string on the stack. Then
+ `pop_failure_point' will keep the current value for the
+ string, instead of restoring it. To see why, consider
+ matching `foo\nbar' against `.*\n'. The .* matches the foo;
+ then the . fails against the \n. But the next thing we want
+ to do is match the \n against the \n; if we restored the
+ string value, we would be back at the foo.
+
+ Because this is used only in specific cases, we don't need to
+ check all the things that `on_failure_jump' does, to make
+ sure the right things get saved on the stack. Hence we don't
+ share its code. The only reason to push anything on the
+ stack at all is that otherwise we would have to change
+ `anychar's code to do something besides goto fail in this
+ case; that seems worse than this. */
+ CASE (on_failure_keep_string_jump):
+ DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump");
+
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+#ifdef _LIBC
+ DEBUG_PRINT3 (" %d (to %p):\n", mcnt, p + mcnt);
+#else
+ DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt);
+#endif
+
+ PUSH_FAILURE_POINT (p + mcnt, NULL, -2);
+ NEXT;
+
+
+ /* Uses of on_failure_jump:
+
+ Each alternative starts with an on_failure_jump that points
+ to the beginning of the next alternative. Each alternative
+ except the last ends with a jump that in effect jumps past
+ the rest of the alternatives. (They really jump to the
+ ending jump of the following alternative, because tensioning
+ these jumps is a hassle.)
+
+ Repeats start with an on_failure_jump that points past both
+ the repetition text and either the following jump or
+ pop_failure_jump back to this on_failure_jump. */
+ CASE (on_failure_jump):
+ on_failure:
+ DEBUG_PRINT1 ("EXECUTING on_failure_jump");
+
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+#ifdef _LIBC
+ DEBUG_PRINT3 (" %d (to %p)", mcnt, p + mcnt);
+#else
+ DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt);
+#endif
+
+ /* If this on_failure_jump comes right before a group (i.e.,
+ the original * applied to a group), save the information
+ for that group and all inner ones, so that if we fail back
+ to this point, the group's information will be correct.
+ For example, in \(a*\)*\1, we need the preceding group,
+ and in \(zz\(a*\)b*\)\2, we need the inner group. */
+
+ /* We can't use `p' to check ahead because we push
+ a failure point to `p + mcnt' after we do this. */
+ p1 = p;
+
+ /* We need to skip no_op's before we look for the
+ start_memory in case this on_failure_jump is happening as
+ the result of a completed succeed_n, as in \(a\)\{1,3\}b\1
+ against aba. */
+ while (p1 < pend && (re_opcode_t) *p1 == no_op)
+ p1++;
+
+ if (p1 < pend && (re_opcode_t) *p1 == start_memory)
+ {
+ /* We have a new highest active register now. This will
+ get reset at the start_memory we are about to get to,
+ but we will have saved all the registers relevant to
+ this repetition op, as described above. */
+ highest_active_reg = *(p1 + 1) + *(p1 + 2);
+ if (lowest_active_reg == NO_LOWEST_ACTIVE_REG)
+ lowest_active_reg = *(p1 + 1);
+ }
+
+ DEBUG_PRINT1 (":\n");
+ PUSH_FAILURE_POINT (p + mcnt, d, -2);
+ NEXT;
+
+
+ /* 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 UCHAR_T *p2 = p;
+
+ /* Compare the beginning of the repeat with what in the
+ pattern follows its end. If we can establish that there
+ is nothing that they would both match, i.e., that we
+ would have to backtrack because of (as in, e.g., `a*a')
+ then we can change to pop_failure_jump, because we'll
+ never have to backtrack.
+
+ This is not true in the case of alternatives: in
+ `(a|ab)*' we do need to backtrack to the `ab' alternative
+ (e.g., if the string was `ab'). But instead of trying to
+ detect that here, the alternative has put on a dummy
+ failure point which is what we will end up popping. */
+
+ /* Skip over open/close-group commands.
+ If what follows this loop is a ...+ construct,
+ look at what begins its body, since we will have to
+ match at least one of that. */
+ while (1)
+ {
+ if (p2 + 2 < pend
+ && ((re_opcode_t) *p2 == stop_memory
+ || (re_opcode_t) *p2 == start_memory))
+ p2 += 3;
+ else if (p2 + 2 + 2 * OFFSET_ADDRESS_SIZE < pend
+ && (re_opcode_t) *p2 == dummy_failure_jump)
+ p2 += 2 + 2 * OFFSET_ADDRESS_SIZE;
+ else
+ break;
+ }
+
+ p1 = p + mcnt;
+ /* p1[0] ... p1[2] are the `on_failure_jump' corresponding
+ to the `maybe_finalize_jump' of this case. Examine what
+ follows. */
+
+ /* If we're at the end of the pattern, we can change. */
+ if (p2 == pend)
+ {
+ /* Consider what happens when matching ":\(.*\)"
+ against ":/". I don't really understand this code
+ yet. */
+ p[-(1+OFFSET_ADDRESS_SIZE)] = (UCHAR_T)
+ pop_failure_jump;
+ DEBUG_PRINT1
+ (" End of pattern: change to `pop_failure_jump'.\n");
+ }
+
+ else if ((re_opcode_t) *p2 == exactn
+#ifdef MBS_SUPPORT
+ || (re_opcode_t) *p2 == exactn_bin
+#endif
+ || (bufp->newline_anchor && (re_opcode_t) *p2 == endline))
+ {
+ register UCHAR_T c
+ = *p2 == (UCHAR_T) endline ? '\n' : p2[2];
+
+ if (((re_opcode_t) p1[1+OFFSET_ADDRESS_SIZE] == exactn
+#ifdef MBS_SUPPORT
+ || (re_opcode_t) p1[1+OFFSET_ADDRESS_SIZE] == exactn_bin
+#endif
+ ) && p1[3+OFFSET_ADDRESS_SIZE] != c)
+ {
+ p[-(1+OFFSET_ADDRESS_SIZE)] = (UCHAR_T)
+ pop_failure_jump;
+#ifdef WCHAR
+ DEBUG_PRINT3 (" %C != %C => pop_failure_jump.\n",
+ (wint_t) c,
+ (wint_t) p1[3+OFFSET_ADDRESS_SIZE]);
+#else
+ DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n",
+ (char) c,
+ (char) p1[3+OFFSET_ADDRESS_SIZE]);
+#endif
+ }
+
+#ifndef WCHAR
+ 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) (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");
+ }
+ }
+#endif /* not WCHAR */
+ }
+#ifndef WCHAR
+ else if ((re_opcode_t) *p2 == charset)
+ {
+ /* We win if the first character of the loop is not part
+ of the charset. */
+ if ((re_opcode_t) p1[3] == exactn
+ && ! ((int) p2[1] * BYTEWIDTH > (int) p1[5]
+ && (p2[2 + p1[5] / BYTEWIDTH]
+ & (1 << (p1[5] % BYTEWIDTH)))))
+ {
+ p[-3] = (unsigned char) pop_failure_jump;
+ DEBUG_PRINT1 (" No match => pop_failure_jump.\n");
+ }
+
+ else if ((re_opcode_t) p1[3] == charset_not)
+ {
+ int idx;
+ /* We win if the charset_not inside the loop
+ lists every character listed in the charset after. */
+ for (idx = 0; idx < (int) p2[1]; idx++)
+ if (! (p2[2 + idx] == 0
+ || (idx < (int) p1[4]
+ && ((p2[2 + idx] & ~ p1[5 + idx]) == 0))))
+ break;
+
+ if (idx == p2[1])
+ {
+ p[-3] = (unsigned char) pop_failure_jump;
+ DEBUG_PRINT1 (" No match => pop_failure_jump.\n");
+ }
+ }
+ else if ((re_opcode_t) p1[3] == charset)
+ {
+ int idx;
+ /* We win if the charset inside the loop
+ has no overlap with the one after the loop. */
+ for (idx = 0;
+ idx < (int) p2[1] && idx < (int) p1[4];
+ idx++)
+ if ((p2[2 + idx] & p1[5 + idx]) != 0)
+ break;
+
+ if (idx == p2[1] || idx == p1[4])
+ {
+ p[-3] = (unsigned char) pop_failure_jump;
+ DEBUG_PRINT1 (" No match => pop_failure_jump.\n");
+ }
+ }
+ }
+#endif /* not WCHAR */
+ }
+ p -= OFFSET_ADDRESS_SIZE; /* Point at relative address again. */
+ if ((re_opcode_t) p[-1] != pop_failure_jump)
+ {
+ p[-1] = (UCHAR_T) jump;
+ DEBUG_PRINT1 (" Match => jump.\n");
+ goto unconditional_jump;
+ }
+ /* Note fall through. */
+
+
+ /* The end of a simple repeat has a pop_failure_jump back to
+ its matching on_failure_jump, where the latter will push a
+ failure point. The pop_failure_jump takes off failure
+ points put on by this pop_failure_jump's matching
+ on_failure_jump; we got through the pattern to here from the
+ matching on_failure_jump, so didn't fail. */
+ CASE (pop_failure_jump):
+ {
+ /* We need to pass separate storage for the lowest and
+ highest registers, even though we don't care about the
+ actual values. Otherwise, we will restore only one
+ register from the stack, since lowest will == highest in
+ `pop_failure_point'. */
+ active_reg_t dummy_low_reg, dummy_high_reg;
+ UCHAR_T *pdummy = NULL;
+ const CHAR_T *sdummy = NULL;
+
+ DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n");
+ POP_FAILURE_POINT (sdummy, pdummy,
+ dummy_low_reg, dummy_high_reg,
+ reg_dummy, reg_dummy, reg_info_dummy);
+ }
+ /* Note fall through. */
+
+ unconditional_jump:
+#ifdef _LIBC
+ DEBUG_PRINT2 ("\n%p: ", p);
+#else
+ DEBUG_PRINT2 ("\n0x%x: ", p);
+#endif
+ /* Note fall through. */
+
+ /* Unconditionally jump (without popping any failure points). */
+ CASE (jump):
+ EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */
+ DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt);
+ p += mcnt; /* Do the jump. */
+#ifdef _LIBC
+ DEBUG_PRINT2 ("(to %p).\n", p);
+#else
+ DEBUG_PRINT2 ("(to 0x%x).\n", p);
+#endif
+ NEXT;
+
+
+ /* We need this opcode so we can detect where alternatives end
+ in `group_match_null_string_p' et al. */
+ CASE (jump_past_alt):
+ DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n");
+ goto unconditional_jump;
+
+
+ /* Normally, the on_failure_jump pushes a failure point, which
+ then gets popped at pop_failure_jump. We will end up at
+ pop_failure_jump, also, and with a pattern of, say, `a+', we
+ are skipping over the on_failure_jump, so we have to push
+ something meaningless for pop_failure_jump to pop. */
+ CASE (dummy_failure_jump):
+ DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n");
+ /* It doesn't matter what we push for the string here. What
+ the code at `fail' tests is the value for the pattern. */
+ PUSH_FAILURE_POINT (NULL, NULL, -2);
+ goto unconditional_jump;
+
+
+ /* At the end of an alternative, we need to push a dummy failure
+ point in case we are followed by a `pop_failure_jump', because
+ we don't want the failure point for the alternative to be
+ popped. For example, matching `(a|ab)*' against `aab'
+ requires that we match the `ab' alternative. */
+ CASE (push_dummy_failure):
+ DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n");
+ /* See comments just above at `dummy_failure_jump' about the
+ two zeroes. */
+ PUSH_FAILURE_POINT (NULL, NULL, -2);
+ NEXT;
+
+ /* Have to succeed matching what follows at least n times.
+ After that, handle like `on_failure_jump'. */
+ CASE (succeed_n):
+ EXTRACT_NUMBER (mcnt, p + OFFSET_ADDRESS_SIZE);
+ 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 += OFFSET_ADDRESS_SIZE;
+ STORE_NUMBER_AND_INCR (p, mcnt);
+#ifdef _LIBC
+ DEBUG_PRINT3 (" Setting %p to %d.\n", p - OFFSET_ADDRESS_SIZE
+ , mcnt);
+#else
+ DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p - OFFSET_ADDRESS_SIZE
+ , mcnt);
+#endif
+ }
+ else if (mcnt == 0)
+ {
+#ifdef _LIBC
+ DEBUG_PRINT2 (" Setting two bytes from %p to no_op.\n",
+ p + OFFSET_ADDRESS_SIZE);
+#else
+ DEBUG_PRINT2 (" Setting two bytes from 0x%x to no_op.\n",
+ p + OFFSET_ADDRESS_SIZE);
+#endif /* _LIBC */
+
+#ifdef WCHAR
+ p[1] = (UCHAR_T) no_op;
+#else
+ p[2] = (UCHAR_T) no_op;
+ p[3] = (UCHAR_T) no_op;
+#endif /* WCHAR */
+ goto on_failure;
+ }
+ NEXT;
+
+ CASE (jump_n):
+ EXTRACT_NUMBER (mcnt, p + OFFSET_ADDRESS_SIZE);
+ DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt);
+
+ /* Originally, this is how many times we CAN jump. */
+ if (mcnt)
+ {
+ mcnt--;
+ STORE_NUMBER (p + OFFSET_ADDRESS_SIZE, mcnt);
+
+#ifdef _LIBC
+ DEBUG_PRINT3 (" Setting %p to %d.\n", p + OFFSET_ADDRESS_SIZE,
+ mcnt);
+#else
+ DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p + OFFSET_ADDRESS_SIZE,
+ mcnt);
+#endif /* _LIBC */
+ goto unconditional_jump;
+ }
+ /* If don't have to jump any more, skip over the rest of command. */
+ else
+ p += 2 * OFFSET_ADDRESS_SIZE;
+ NEXT;
+
+ CASE (set_number_at):
+ {
+ DEBUG_PRINT1 ("EXECUTING set_number_at.\n");
+
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+ p1 = p + mcnt;
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+#ifdef _LIBC
+ DEBUG_PRINT3 (" Setting %p to %d.\n", p1, mcnt);
+#else
+ DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p1, mcnt);
+#endif
+ STORE_NUMBER (p1, mcnt);
+ NEXT;
+ }
+
+#if 0
+ /* The DEC Alpha C compiler 3.x generates incorrect code for the
+ test WORDCHAR_P (d - 1) != WORDCHAR_P (d) in the expansion of
+ AT_WORD_BOUNDARY, so this code is disabled. Expanding the
+ macro and introducing temporary variables works around the bug. */
+
+ CASE (wordbound):
+ DEBUG_PRINT1 ("EXECUTING wordbound.\n");
+ if (AT_WORD_BOUNDARY (d))
+ {
+ NEXT;
+ }
+ goto fail;
+
+ CASE (notwordbound):
+ DEBUG_PRINT1 ("EXECUTING notwordbound.\n");
+ if (AT_WORD_BOUNDARY (d))
+ goto fail;
+ NEXT;
+#else
+ CASE (wordbound):
+ {
+ boolean prevchar, thischar;
+
+ DEBUG_PRINT1 ("EXECUTING wordbound.\n");
+ if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d))
+ {
+ NEXT;
+ }
+
+ prevchar = WORDCHAR_P (d - 1);
+ thischar = WORDCHAR_P (d);
+ if (prevchar != thischar)
+ {
+ NEXT;
+ }
+ goto fail;
+ }
+
+ CASE (notwordbound):
+ {
+ boolean prevchar, thischar;
+
+ DEBUG_PRINT1 ("EXECUTING notwordbound.\n");
+ if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d))
+ goto fail;
+
+ prevchar = WORDCHAR_P (d - 1);
+ thischar = WORDCHAR_P (d);
+ if (prevchar != thischar)
+ goto fail;
+ NEXT;
+ }
+#endif
+
+ CASE (wordbeg):
+ DEBUG_PRINT1 ("EXECUTING wordbeg.\n");
+ if (!AT_STRINGS_END (d) && WORDCHAR_P (d)
+ && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1)))
+ {
+ NEXT;
+ }
+ goto fail;
+
+ CASE (wordend):
+ DEBUG_PRINT1 ("EXECUTING wordend.\n");
+ if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1)
+ && (AT_STRINGS_END (d) || !WORDCHAR_P (d)))
+ {
+ NEXT;
+ }
+ goto fail;
+
+#ifdef emacs
+ CASE (before_dot):
+ DEBUG_PRINT1 ("EXECUTING before_dot.\n");
+ if (PTR_CHAR_POS ((unsigned char *) d) >= point)
+ goto fail;
+ NEXT;
+
+ CASE (at_dot):
+ DEBUG_PRINT1 ("EXECUTING at_dot.\n");
+ if (PTR_CHAR_POS ((unsigned char *) d) != point)
+ goto fail;
+ NEXT;
+
+ CASE (after_dot):
+ DEBUG_PRINT1 ("EXECUTING after_dot.\n");
+ if (PTR_CHAR_POS ((unsigned char *) d) <= point)
+ goto fail;
+ NEXT;
+
+ CASE (syntaxspec):
+ DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt);
+ mcnt = *p++;
+ goto matchsyntax;
+
+ CASE (wordchar):
+ DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n");
+ mcnt = (int) Sword;
+ matchsyntax:
+ PREFETCH ();
+ /* Can't use *d++ here; SYNTAX may be an unsafe macro. */
+ d++;
+ if (SYNTAX (d[-1]) != (enum syntaxcode) mcnt)
+ goto fail;
+ SET_REGS_MATCHED ();
+ NEXT;
+
+ CASE (notsyntaxspec):
+ DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt);
+ mcnt = *p++;
+ goto matchnotsyntax;
+
+ CASE (notwordchar):
+ DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n");
+ mcnt = (int) Sword;
+ matchnotsyntax:
+ PREFETCH ();
+ /* Can't use *d++ here; SYNTAX may be an unsafe macro. */
+ d++;
+ if (SYNTAX (d[-1]) == (enum syntaxcode) mcnt)
+ goto fail;
+ SET_REGS_MATCHED ();
+ NEXT;
+
+#else /* not emacs */
+ CASE (wordchar):
+ DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n");
+ PREFETCH ();
+ if (!WORDCHAR_P (d))
+ goto fail;
+ SET_REGS_MATCHED ();
+ d++;
+ NEXT;
+
+ CASE (notwordchar):
+ DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n");
+ PREFETCH ();
+ if (WORDCHAR_P (d))
+ goto fail;
+ SET_REGS_MATCHED ();
+ d++;
+ NEXT;
+#endif /* not emacs */
+
+#ifndef __GNUC__
+ default:
+ abort ();
+ }
+ continue; /* Successfully executed one pattern command; keep going. */
+#endif
+
+
+ /* 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
+PREFIX(group_match_null_string_p) (UCHAR_T **p, UCHAR_T *end,
+ PREFIX(register_info_type) *reg_info)
+{
+ int mcnt;
+ /* Point to after the args to the start_memory. */
+ UCHAR_T *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-(1+OFFSET_ADDRESS_SIZE)] ==
+ jump_past_alt)
+ {
+ /* `mcnt' holds how many bytes long the alternative
+ is, including the ending `jump_past_alt' and
+ its number. */
+
+ if (!PREFIX(alt_match_null_string_p) (p1, p1 + mcnt -
+ (1 + OFFSET_ADDRESS_SIZE),
+ 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-(1+OFFSET_ADDRESS_SIZE)] !=
+ jump_past_alt)
+ {
+ /* Get to the beginning of the n-th alternative. */
+ p1 -= 1 + OFFSET_ADDRESS_SIZE;
+ 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 - OFFSET_ADDRESS_SIZE);
+
+ if (!PREFIX(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 (!PREFIX(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
+PREFIX(alt_match_null_string_p) (UCHAR_T *p, UCHAR_T *end,
+ PREFIX(register_info_type) *reg_info)
+{
+ int mcnt;
+ UCHAR_T *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 (!PREFIX(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
+PREFIX(common_op_match_null_string_p) (UCHAR_T **p, UCHAR_T *end,
+ PREFIX(register_info_type) *reg_info)
+{
+ int mcnt;
+ boolean ret;
+ int reg_no;
+ UCHAR_T *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 = PREFIX(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 += OFFSET_ADDRESS_SIZE;
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+
+ if (mcnt == 0)
+ {
+ p1 -= 2 * OFFSET_ADDRESS_SIZE;
+ 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 += 2 * OFFSET_ADDRESS_SIZE;
+
+ 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
+PREFIX(bcmp_translate) (const CHAR_T *s1, const CHAR_T *s2,
+ register int len,
+ RE_TRANSLATE_TYPE translate)
+{
+ register const UCHAR_T *p1 = (const UCHAR_T *) s1;
+ register const UCHAR_T *p2 = (const UCHAR_T *) s2;
+ while (len)
+ {
+#ifdef WCHAR
+ if (((*p1<=0xff)?translate[*p1++]:*p1++)
+ != ((*p2<=0xff)?translate[*p2++]:*p2++))
+ return 1;
+#else /* BYTE */
+ if (translate[*p1++] != translate[*p2++]) return 1;
+#endif /* WCHAR */
+ len--;
+ }
+ return 0;
+}
+
+
+#else /* not INSIDE_RECURSION */
+
+/* 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 (const char *pattern,
+ size_t length,
+ struct re_pattern_buffer *bufp)
+{
+ reg_errcode_t ret;
+
+ /* GNU code is written to assume at least RE_NREGS registers will be set
+ (and at least one extra will be -1). */
+ bufp->regs_allocated = REGS_UNALLOCATED;
+
+ /* And GNU code determines whether or not to get register information
+ by passing null for the REGS argument to re_match, etc., not by
+ setting no_sub. */
+ bufp->no_sub = 0;
+
+ /* Match anchors at newline. */
+ bufp->newline_anchor = 1;
+
+# ifdef MBS_SUPPORT
+ if (MB_CUR_MAX != 1)
+ ret = wcs_regex_compile (pattern, length, re_syntax_options, bufp);
+ else
+# endif
+ ret = byte_regex_compile (pattern, length, re_syntax_options, bufp);
+
+ if (!ret)
+ return NULL;
+ return gettext (re_error_msgid + re_error_msgid_idx[(int) ret]);
+}
+#ifdef _LIBC
+weak_alias (__re_compile_pattern, re_compile_pattern)
+#endif
+
+/* Entry points compatible with 4.2 BSD regex library. We don't define
+ them unless specifically requested. */
+
+#if defined _REGEX_RE_COMP || defined _LIBC
+
+/* BSD has one and only one pattern buffer. */
+static struct re_pattern_buffer re_comp_buf;
+
+char *
+#ifdef _LIBC
+/* Make these definitions weak in libc, so POSIX programs can redefine
+ these names if they don't use our functions, and still use
+ regcomp/regexec below without link errors. */
+weak_function
+#endif
+re_comp (const char *s)
+{
+ reg_errcode_t ret;
+
+ if (!s)
+ {
+ if (!re_comp_buf.buffer)
+ return gettext ("No previous regular expression");
+ return 0;
+ }
+
+ if (!re_comp_buf.buffer)
+ {
+ re_comp_buf.buffer = malloc (200);
+ if (re_comp_buf.buffer == NULL)
+ return (char *) gettext (re_error_msgid
+ + re_error_msgid_idx[(int) REG_ESPACE]);
+ re_comp_buf.allocated = 200;
+
+ re_comp_buf.fastmap = malloc (1 << BYTEWIDTH);
+ if (re_comp_buf.fastmap == NULL)
+ return (char *) gettext (re_error_msgid
+ + re_error_msgid_idx[(int) REG_ESPACE]);
+ }
+
+ /* Since `re_exec' always passes NULL for the `regs' argument, we
+ don't need to initialize the pattern buffer fields which affect it. */
+
+ /* Match anchors at newlines. */
+ re_comp_buf.newline_anchor = 1;
+
+# ifdef MBS_SUPPORT
+ if (MB_CUR_MAX != 1)
+ ret = wcs_regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf);
+ else
+# endif
+ ret = byte_regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf);
+
+ if (!ret)
+ return NULL;
+
+ /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */
+ return (char *) gettext (re_error_msgid + re_error_msgid_idx[(int) ret]);
+}
+
+
+int
+#ifdef _LIBC
+weak_function
+#endif
+re_exec (const char *s)
+{
+ const int len = strlen (s);
+ return
+ 0 <= re_search (&re_comp_buf, s, len, 0, len, 0);
+}
+
+#endif /* _REGEX_RE_COMP */
+
+/* POSIX.2 functions. Don't define these for Emacs. */
+
+#ifndef emacs
+
+/* regcomp takes a regular expression as a string and compiles it.
+
+ PREG is a regex_t *. We do not expect any fields to be initialized,
+ since POSIX says we shouldn't. Thus, we set
+
+ `buffer' to the compiled pattern;
+ `used' to the length of the compiled pattern;
+ `syntax' to RE_SYNTAX_POSIX_EXTENDED if the
+ REG_EXTENDED bit in CFLAGS is set; otherwise, to
+ RE_SYNTAX_POSIX_BASIC;
+ `newline_anchor' to REG_NEWLINE being set in CFLAGS;
+ `fastmap' to an allocated space for the fastmap;
+ `fastmap_accurate' to zero;
+ `re_nsub' to the number of subexpressions in PATTERN.
+
+ PATTERN is the address of the pattern string.
+
+ CFLAGS is a series of bits which affect compilation.
+
+ If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we
+ use POSIX basic syntax.
+
+ If REG_NEWLINE is set, then . and [^...] don't match newline.
+ Also, regexec will try a match beginning after every newline.
+
+ If REG_ICASE is set, then we considers upper- and lowercase
+ versions of letters to be equivalent when matching.
+
+ If REG_NOSUB is set, then when PREG is passed to regexec, that
+ routine will report only success or failure, and nothing about the
+ registers.
+
+ It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for
+ the return codes and their meanings.) */
+
+int
+regcomp (regex_t *preg, const char *pattern, int cflags)
+{
+ reg_errcode_t ret;
+ reg_syntax_t syntax
+ = (cflags & REG_EXTENDED) ?
+ RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC;
+
+ /* regex_compile will allocate the space for the compiled pattern. */
+ preg->buffer = 0;
+ preg->allocated = 0;
+ preg->used = 0;
+
+ /* Try to allocate space for the fastmap. */
+ preg->fastmap = malloc (1 << BYTEWIDTH);
+
+ if (cflags & REG_ICASE)
+ {
+ unsigned i;
+
+ preg->translate = malloc (CHAR_SET_SIZE
+ * sizeof (*(RE_TRANSLATE_TYPE)0));
+ if (preg->translate == NULL)
+ return (int) REG_ESPACE;
+
+ /* Map uppercase characters to corresponding lowercase ones. */
+ for (i = 0; i < CHAR_SET_SIZE; i++)
+ preg->translate[i] = ISUPPER (i) ? TOLOWER (i) : i;
+ }
+ else
+ preg->translate = NULL;
+
+ /* If REG_NEWLINE is set, newlines are treated differently. */
+ if (cflags & REG_NEWLINE)
+ { /* REG_NEWLINE implies neither . nor [^...] match newline. */
+ syntax &= ~RE_DOT_NEWLINE;
+ syntax |= RE_HAT_LISTS_NOT_NEWLINE;
+ /* It also changes the matching behavior. */
+ preg->newline_anchor = 1;
+ }
+ else
+ preg->newline_anchor = 0;
+
+ preg->no_sub = !!(cflags & REG_NOSUB);
+
+ /* POSIX says a null character in the pattern terminates it, so we
+ can use strlen here in compiling the pattern. */
+# ifdef MBS_SUPPORT
+ if (MB_CUR_MAX != 1)
+ ret = wcs_regex_compile (pattern, strlen (pattern), syntax, preg);
+ else
+# endif
+ ret = byte_regex_compile (pattern, strlen (pattern), syntax, preg);
+
+ /* POSIX doesn't distinguish between an unmatched open-group and an
+ unmatched close-group: both are REG_EPAREN. */
+ if (ret == REG_ERPAREN) ret = REG_EPAREN;
+
+ if (ret == REG_NOERROR && preg->fastmap)
+ {
+ /* Compute the fastmap now, since regexec cannot modify the pattern
+ buffer. */
+ if (re_compile_fastmap (preg) == -2)
+ {
+ /* Some error occurred while computing the fastmap, just forget
+ about it. */
+ free (preg->fastmap);
+ preg->fastmap = NULL;
+ }
+ }
+
+ return (int) ret;
+}
+#ifdef _LIBC
+weak_alias (__regcomp, regcomp)
+#endif
+
+
+/* regexec searches for a given pattern, specified by PREG, in the
+ string STRING.
+
+ If NMATCH is zero or REG_NOSUB was set in the cflags argument to
+ `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at
+ least NMATCH elements, and we set them to the offsets of the
+ corresponding matched substrings.
+
+ EFLAGS specifies `execution flags' which affect matching: if
+ REG_NOTBOL is set, then ^ does not match at the beginning of the
+ string; if REG_NOTEOL is set, then $ does not match at the end.
+
+ We return 0 if we find a match and REG_NOMATCH if not. */
+
+int
+regexec (const regex_t *preg, const char *string,
+ size_t nmatch, regmatch_t pmatch[], int eflags)
+{
+ int ret;
+ struct re_registers regs;
+ regex_t private_preg;
+ int len = strlen (string);
+ boolean want_reg_info = !preg->no_sub && nmatch > 0;
+
+ private_preg = *preg;
+
+ private_preg.not_bol = !!(eflags & REG_NOTBOL);
+ private_preg.not_eol = !!(eflags & REG_NOTEOL);
+
+ /* The user has told us exactly how many registers to return
+ information about, via `nmatch'. We have to pass that on to the
+ matching routines. */
+ private_preg.regs_allocated = REGS_FIXED;
+
+ if (want_reg_info)
+ {
+ regs.num_regs = nmatch;
+ regs.start = TALLOC (nmatch * 2, regoff_t);
+ if (regs.start == NULL)
+ return (int) REG_NOMATCH;
+ regs.end = regs.start + nmatch;
+ }
+
+ /* Perform the searching operation. */
+ ret = re_search (&private_preg, string, len,
+ /* start: */ 0, /* range: */ len,
+ want_reg_info ? &regs : 0);
+
+ /* Copy the register information to the POSIX structure. */
+ if (want_reg_info)
+ {
+ if (ret >= 0)
+ {
+ unsigned r;
+
+ for (r = 0; r < nmatch; r++)
+ {
+ pmatch[r].rm_so = regs.start[r];
+ pmatch[r].rm_eo = regs.end[r];
+ }
+ }
+
+ /* If we needed the temporary register info, free the space now. */
+ free (regs.start);
+ }
+
+ /* We want zero return to mean success, unlike `re_search'. */
+ return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH;
+}
+#ifdef _LIBC
+weak_alias (__regexec, regexec)
+#endif
+
+
+/* Returns a message corresponding to an error code, ERRCODE, returned
+ from either regcomp or regexec. We don't use PREG here. */
+
+size_t
+regerror (int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
+{
+ const char *msg;
+ size_t msg_size;
+
+ if (errcode < 0
+ || errcode >= (int) (sizeof (re_error_msgid_idx)
+ / sizeof (re_error_msgid_idx[0])))
+ /* Only error codes returned by the rest of the code should be passed
+ to this routine. If we are given anything else, or if other regex
+ code generates an invalid error code, then the program has a bug.
+ Dump core so we can fix it. */
+ abort ();
+
+ msg = gettext (re_error_msgid + re_error_msgid_idx[errcode]);
+
+ msg_size = strlen (msg) + 1; /* Includes the null. */
+
+ if (errbuf_size != 0)
+ {
+ if (msg_size > errbuf_size)
+ {
+#if defined HAVE_MEMPCPY || defined _LIBC
+ *((char *) __mempcpy (errbuf, msg, errbuf_size - 1)) = '\0';
+#else
+ memcpy (errbuf, msg, errbuf_size - 1);
+ errbuf[errbuf_size - 1] = 0;
+#endif
+ }
+ else
+ memcpy (errbuf, msg, msg_size);
+ }
+
+ return msg_size;
+}
+#ifdef _LIBC
+weak_alias (__regerror, regerror)
+#endif
+
+
+/* Free dynamically allocated space used by PREG. */
+
+void
+regfree (regex_t *preg)
+{
+ if (preg->buffer != NULL)
+ free (preg->buffer);
+ preg->buffer = NULL;
+
+ preg->allocated = 0;
+ preg->used = 0;
+
+ if (preg->fastmap != NULL)
+ free (preg->fastmap);
+ preg->fastmap = NULL;
+ preg->fastmap_accurate = 0;
+
+ if (preg->translate != NULL)
+ free (preg->translate);
+ preg->translate = NULL;
+}
+#ifdef _LIBC
+weak_alias (__regfree, regfree)
+#endif
+
+#endif /* not emacs */
+
+#endif /* not INSIDE_RECURSION */
+
+
+#undef STORE_NUMBER
+#undef STORE_NUMBER_AND_INCR
+#undef EXTRACT_NUMBER
+#undef EXTRACT_NUMBER_AND_INCR
+
+#undef DEBUG_PRINT_COMPILED_PATTERN
+#undef DEBUG_PRINT_DOUBLE_STRING
+
+#undef INIT_FAIL_STACK
+#undef RESET_FAIL_STACK
+#undef DOUBLE_FAIL_STACK
+#undef PUSH_PATTERN_OP
+#undef PUSH_FAILURE_POINTER
+#undef PUSH_FAILURE_INT
+#undef PUSH_FAILURE_ELT
+#undef POP_FAILURE_POINTER
+#undef POP_FAILURE_INT
+#undef POP_FAILURE_ELT
+#undef DEBUG_PUSH
+#undef DEBUG_POP
+#undef PUSH_FAILURE_POINT
+#undef POP_FAILURE_POINT
+
+#undef REG_UNSET_VALUE
+#undef REG_UNSET
+
+#undef PATFETCH
+#undef PATFETCH_RAW
+#undef PATUNFETCH
+#undef TRANSLATE
+
+#undef INIT_BUF_SIZE
+#undef GET_BUFFER_SPACE
+#undef BUF_PUSH
+#undef BUF_PUSH_2
+#undef BUF_PUSH_3
+#undef STORE_JUMP
+#undef STORE_JUMP2
+#undef INSERT_JUMP
+#undef INSERT_JUMP2
+#undef EXTEND_BUFFER
+#undef GET_UNSIGNED_NUMBER
+#undef FREE_STACK_RETURN
+
+# undef POINTER_TO_OFFSET
+# undef MATCHING_IN_FRST_STRING
+# undef PREFETCH
+# undef AT_STRINGS_BEG
+# undef AT_STRINGS_END
+# undef WORDCHAR_P
+# undef FREE_VAR
+# undef FREE_VARIABLES
+# undef NO_HIGHEST_ACTIVE_REG
+# undef NO_LOWEST_ACTIVE_REG
+
+# undef CHAR_T
+# undef UCHAR_T
+# undef COMPILED_BUFFER_VAR
+# undef OFFSET_ADDRESS_SIZE
+# undef CHAR_CLASS_SIZE
+# undef PREFIX
+# undef ARG_PREFIX
+# undef PUT_CHAR
+# undef BYTE
+# undef WCHAR
+
+# define DEFINED_ONCE
diff --git a/contrib/diff/lib/regex.h b/contrib/diff/lib/regex.h
new file mode 100644
index 0000000..b4bbc01
--- /dev/null
+++ b/contrib/diff/lib/regex.h
@@ -0,0 +1,556 @@
+/* Definitions for data structures and routines for the regular
+ expression library.
+ Copyright (C) 1985,1989-93,1995-98,2000,2001,2002,2003
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _REGEX_H
+#define _REGEX_H 1
+
+#include <sys/types.h>
+
+/* Allow the use in C++ code. */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* POSIX says that <sys/types.h> must be included (by the caller) before
+ <regex.h>. */
+
+#if !defined _POSIX_C_SOURCE && !defined _POSIX_SOURCE && defined VMS
+/* VMS doesn't have `size_t' in <sys/types.h>, even though POSIX says it
+ should be there. */
+# include <stddef.h>
+#endif
+
+/* The following two types have to be signed and unsigned integer type
+ wide enough to hold a value of a pointer. For most ANSI compilers
+ ptrdiff_t and size_t should be likely OK. Still size of these two
+ types is 2 for Microsoft C. Ugh... */
+typedef long int s_reg_t;
+typedef unsigned long int active_reg_t;
+
+/* The following bits are used to determine the regexp syntax we
+ recognize. The set/not-set meanings are chosen so that Emacs syntax
+ remains the value 0. The bits are given in alphabetical order, and
+ the definitions shifted by one from the previous bit; thus, when we
+ add or remove a bit, only one other definition need change. */
+typedef unsigned long int reg_syntax_t;
+
+/* If this bit is not set, then \ inside a bracket expression is literal.
+ If set, then such a \ quotes the following character. */
+#define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1)
+
+/* If this bit is not set, then + and ? are operators, and \+ and \? are
+ literals.
+ If set, then \+ and \? are operators and + and ? are literals. */
+#define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1)
+
+/* If this bit is set, then character classes are supported. They are:
+ [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:],
+ [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:].
+ If not set, then character classes are not supported. */
+#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1)
+
+/* If this bit is set, then ^ and $ are always anchors (outside bracket
+ expressions, of course).
+ If this bit is not set, then it depends:
+ ^ is an anchor if it is at the beginning of a regular
+ expression or after an open-group or an alternation operator;
+ $ is an anchor if it is at the end of a regular expression, or
+ before a close-group or an alternation operator.
+
+ This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because
+ POSIX draft 11.2 says that * etc. in leading positions is undefined.
+ We already implemented a previous draft which made those constructs
+ invalid, though, so we haven't changed the code back. */
+#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1)
+
+/* If this bit is set, then special characters are always special
+ regardless of where they are in the pattern.
+ If this bit is not set, then special characters are special only in
+ some contexts; otherwise they are ordinary. Specifically,
+ * + ? and intervals are only special when not after the beginning,
+ open-group, or alternation operator. */
+#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1)
+
+/* If this bit is set, then *, +, ?, and { cannot be first in an re or
+ immediately after an alternation or begin-group operator. */
+#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1)
+
+/* If this bit is set, then . matches newline.
+ If not set, then it doesn't. */
+#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1)
+
+/* If this bit is set, then . doesn't match NUL.
+ If not set, then it does. */
+#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1)
+
+/* If this bit is set, nonmatching lists [^...] do not match newline.
+ If not set, they do. */
+#define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1)
+
+/* If this bit is set, either \{...\} or {...} defines an
+ interval, depending on RE_NO_BK_BRACES.
+ If not set, \{, \}, {, and } are literals. */
+#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1)
+
+/* If this bit is set, +, ? and | aren't recognized as operators.
+ If not set, they are. */
+#define RE_LIMITED_OPS (RE_INTERVALS << 1)
+
+/* If this bit is set, newline is an alternation operator.
+ If not set, newline is literal. */
+#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1)
+
+/* If this bit is set, then `{...}' defines an interval, and \{ and \}
+ are literals.
+ If not set, then `\{...\}' defines an interval. */
+#define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1)
+
+/* If this bit is set, (...) defines a group, and \( and \) are literals.
+ If not set, \(...\) defines a group, and ( and ) are literals. */
+#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1)
+
+/* If this bit is set, then \<digit> matches <digit>.
+ If not set, then \<digit> is a back-reference. */
+#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1)
+
+/* If this bit is set, then | is an alternation operator, and \| is literal.
+ If not set, then \| is an alternation operator, and | is literal. */
+#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1)
+
+/* If this bit is set, then an ending range point collating higher
+ than the starting range point, as in [z-a], is invalid.
+ If not set, then when ending range point collates higher than the
+ starting range point, the range is ignored. */
+#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1)
+
+/* If this bit is set, then an unmatched ) is ordinary.
+ If not set, then an unmatched ) is invalid. */
+#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1)
+
+/* If this bit is set, succeed as soon as we match the whole pattern,
+ without further backtracking. */
+#define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1)
+
+/* If this bit is set, do not process the GNU regex operators.
+ If not set, then the GNU regex operators are recognized. */
+#define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1)
+
+/* If this bit is set, turn on internal regex debugging.
+ If not set, and debugging was on, turn it off.
+ This only works if regex.c is compiled -DDEBUG.
+ We define this bit always, so that all that's needed to turn on
+ debugging is to recompile regex.c; the calling code can always have
+ this bit set, and it won't affect anything in the normal case. */
+#define RE_DEBUG (RE_NO_GNU_OPS << 1)
+
+/* If this bit is set, a syntactically invalid interval is treated as
+ a string of ordinary characters. For example, the ERE 'a{1' is
+ treated as 'a\{1'. */
+#define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1)
+
+/* If this bit is set, then ignore case when matching.
+ If not set, then case is significant. */
+#define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1)
+
+/* This global variable defines the particular regexp syntax to use (for
+ some interfaces). When a regexp is compiled, the syntax used is
+ stored in the pattern buffer, so changing this does not affect
+ already-compiled regexps. */
+extern reg_syntax_t re_syntax_options;
+
+/* Define combinations of the above bits for the standard possibilities.
+ (The [[[ comments delimit what gets put into the Texinfo file, so
+ don't delete them!) */
+/* [[[begin syntaxes]]] */
+#define RE_SYNTAX_EMACS 0
+
+#define RE_SYNTAX_AWK \
+ (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \
+ | RE_NO_BK_PARENS | RE_NO_BK_REFS \
+ | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \
+ | RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \
+ | RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS)
+
+#define RE_SYNTAX_GNU_AWK \
+ ((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DEBUG) \
+ & ~(RE_DOT_NOT_NULL | RE_INTERVALS | RE_CONTEXT_INDEP_OPS \
+ | RE_CONTEXT_INVALID_OPS ))
+
+#define RE_SYNTAX_POSIX_AWK \
+ (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \
+ | RE_INTERVALS | RE_NO_GNU_OPS)
+
+#define RE_SYNTAX_GREP \
+ (RE_BK_PLUS_QM | RE_CHAR_CLASSES \
+ | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \
+ | RE_NEWLINE_ALT)
+
+#define RE_SYNTAX_EGREP \
+ (RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \
+ | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \
+ | RE_NEWLINE_ALT | RE_NO_BK_PARENS \
+ | RE_NO_BK_VBAR)
+
+#define RE_SYNTAX_POSIX_EGREP \
+ (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES \
+ | RE_INVALID_INTERVAL_ORD)
+
+/* 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_CONTEXT_INVALID_OPS | RE_UNMATCHED_RIGHT_PAREN_ORD)
+
+/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INDEP_OPS is
+ removed and RE_NO_BK_REFS is added. */
+#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \
+ (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
+ | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \
+ | RE_NO_BK_PARENS | RE_NO_BK_REFS \
+ | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD)
+/* [[[end syntaxes]]] */
+
+/* Maximum number of duplicates an interval can allow. Some systems
+ (erroneously) define this in other header files, but we want our
+ value, so remove any previous define. */
+#ifdef RE_DUP_MAX
+# undef RE_DUP_MAX
+#endif
+/* If sizeof(int) == 2, then ((1 << 15) - 1) overflows. */
+#define RE_DUP_MAX (0x7fff)
+
+
+/* POSIX `cflags' bits (i.e., information for `regcomp'). */
+
+/* If this bit is set, then use extended regular expression syntax.
+ If not set, then use basic regular expression syntax. */
+#define REG_EXTENDED 1
+
+/* If this bit is set, then ignore case when matching.
+ If not set, then case is significant. */
+#define REG_ICASE (REG_EXTENDED << 1)
+
+/* If this bit is set, then anchors do not match at newline
+ characters in the string.
+ If not set, then anchors do match at newlines. */
+#define REG_NEWLINE (REG_ICASE << 1)
+
+/* If this bit is set, then report only success or fail in regexec.
+ If not set, then returns differ between not matching and errors. */
+#define REG_NOSUB (REG_NEWLINE << 1)
+
+
+/* POSIX `eflags' bits (i.e., information for regexec). */
+
+/* If this bit is set, then the beginning-of-line operator doesn't match
+ the beginning of the string (presumably because it's not the
+ beginning of a line).
+ If not set, then the beginning-of-line operator does match the
+ beginning of the string. */
+#define REG_NOTBOL 1
+
+/* Like REG_NOTBOL, except for the end-of-line. */
+#define REG_NOTEOL (1 << 1)
+
+
+/* If any error codes are removed, changed, or added, update the
+ `re_error_msg' table in regex.c. */
+typedef enum
+{
+#ifdef _XOPEN_SOURCE
+ REG_ENOSYS = -1, /* This will never happen for this implementation. */
+#endif
+
+ REG_NOERROR = 0, /* Success. */
+ REG_NOMATCH, /* Didn't find a match (for regexec). */
+
+ /* POSIX regcomp return error codes. (In the order listed in the
+ standard.) */
+ REG_BADPAT, /* Invalid pattern. */
+ REG_ECOLLATE, /* Not implemented. */
+ REG_ECTYPE, /* Invalid character class name. */
+ REG_EESCAPE, /* Trailing backslash. */
+ REG_ESUBREG, /* Invalid back reference. */
+ REG_EBRACK, /* Unmatched left bracket. */
+ REG_EPAREN, /* Parenthesis imbalance. */
+ REG_EBRACE, /* Unmatched \{. */
+ REG_BADBR, /* Invalid contents of \{\}. */
+ REG_ERANGE, /* Invalid range end. */
+ REG_ESPACE, /* Ran out of memory. */
+ REG_BADRPT, /* No preceding re for repetition op. */
+
+ /* Error codes we've added. */
+ REG_EEND, /* Premature end. */
+ REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */
+ REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */
+} reg_errcode_t;
+
+/* This data structure represents a compiled pattern. Before calling
+ the pattern compiler, the fields `buffer', `allocated', `fastmap',
+ `translate', and `no_sub' can be set. After the pattern has been
+ compiled, the `re_nsub' field is available. All other fields are
+ private to the regex routines. */
+
+#ifndef RE_TRANSLATE_TYPE
+# define RE_TRANSLATE_TYPE char *
+#endif
+
+struct re_pattern_buffer
+{
+/* [[[begin pattern_buffer]]] */
+ /* Space that holds the compiled pattern. It is declared as
+ `unsigned char *' because its elements are
+ sometimes used as array indexes. */
+ unsigned char *buffer;
+
+ /* Number of bytes to which `buffer' points. */
+ unsigned long int allocated;
+
+ /* Number of bytes actually used in `buffer'. */
+ unsigned long int used;
+
+ /* Syntax setting with which the pattern was compiled. */
+ reg_syntax_t syntax;
+
+ /* Pointer to a fastmap, if any, otherwise zero. re_search uses
+ the fastmap, if there is one, to skip over impossible
+ starting points for matches. */
+ char *fastmap;
+
+ /* Either a translate table to apply to all characters before
+ comparing them, or zero for no translation. The translation
+ is applied to a pattern when it is compiled and to a string
+ when it is matched. */
+ RE_TRANSLATE_TYPE translate;
+
+ /* Number of subexpressions found by the compiler. */
+ size_t re_nsub;
+
+ /* Zero if this pattern cannot match the empty string, one else.
+ Well, in truth it's used only in `re_search_2', to see
+ whether or not we should use the fastmap, so we don't set
+ this absolutely perfectly; see `re_compile_fastmap' (the
+ `duplicate' case). */
+ unsigned can_be_null : 1;
+
+ /* If REGS_UNALLOCATED, allocate space in the `regs' structure
+ for `max (RE_NREGS, re_nsub + 1)' groups.
+ If REGS_REALLOCATE, reallocate space if necessary.
+ If REGS_FIXED, use what's there. */
+#define REGS_UNALLOCATED 0
+#define REGS_REALLOCATE 1
+#define REGS_FIXED 2
+ unsigned regs_allocated : 2;
+
+ /* Set to zero when `regex_compile' compiles a pattern; set to one
+ by `re_compile_fastmap' if it updates the fastmap. */
+ unsigned fastmap_accurate : 1;
+
+ /* If set, `re_match_2' does not return information about
+ subexpressions. */
+ unsigned no_sub : 1;
+
+ /* If set, a beginning-of-line anchor doesn't match at the
+ beginning of the string. */
+ unsigned not_bol : 1;
+
+ /* Similarly for an end-of-line anchor. */
+ unsigned not_eol : 1;
+
+ /* If true, an anchor at a newline matches. */
+ unsigned newline_anchor : 1;
+
+/* [[[end pattern_buffer]]] */
+};
+
+typedef struct re_pattern_buffer regex_t;
+
+/* Type for byte offsets within the string. POSIX mandates this. */
+typedef int regoff_t;
+
+
+/* This is the structure we store register match data in. See
+ regex.texinfo for a full description of what registers match. */
+struct re_registers
+{
+ unsigned num_regs;
+ regoff_t *start;
+ regoff_t *end;
+};
+
+
+/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer,
+ `re_match_2' returns information about at least this many registers
+ the first time a `regs' structure is passed. */
+#ifndef RE_NREGS
+# define RE_NREGS 30
+#endif
+
+
+/* POSIX specification for registers. Aside from the different names than
+ `re_registers', POSIX uses an array of structures, instead of a
+ structure of arrays. */
+typedef struct
+{
+ regoff_t rm_so; /* Byte offset from string's start to substring's start. */
+ regoff_t rm_eo; /* Byte offset from string's start to substring's end. */
+} regmatch_t;
+
+/* Declarations for routines. */
+
+/* Sets the current default syntax to SYNTAX, and return the old syntax.
+ You can also simply assign to the `re_syntax_options' variable. */
+extern reg_syntax_t re_set_syntax (reg_syntax_t syntax);
+
+/* Compile the regular expression PATTERN, with length LENGTH
+ and syntax given by the global `re_syntax_options', into the buffer
+ BUFFER. Return NULL if successful, and an error string if not. */
+extern const char *re_compile_pattern (const char *pattern, size_t length,
+ struct re_pattern_buffer *buffer);
+
+
+/* Compile a fastmap for the compiled pattern in BUFFER; used to
+ accelerate searches. Return 0 if successful and -2 if was an
+ internal error. */
+extern int re_compile_fastmap (struct re_pattern_buffer *buffer);
+
+
+/* Search in the string STRING (with length LENGTH) for the pattern
+ compiled into BUFFER. Start searching at position START, for RANGE
+ characters. Return the starting position of the match, -1 for no
+ match, or -2 for an internal error. Also return register
+ information in REGS (if REGS and BUFFER->no_sub are nonzero). */
+extern int re_search (struct re_pattern_buffer *buffer, const char *string,
+ int length, int start, int range,
+ struct re_registers *regs);
+
+
+/* Like `re_search', but search in the concatenation of STRING1 and
+ STRING2. Also, stop searching at index START + STOP. */
+extern int re_search_2 (struct re_pattern_buffer *buffer, const char *string1,
+ int length1, const char *string2, int length2,
+ int start, int range, struct re_registers *regs,
+ int stop);
+
+
+/* Like `re_search', but return how many characters in STRING the regexp
+ in BUFFER matched, starting at position START. */
+extern int re_match (struct re_pattern_buffer *buffer, const char *string,
+ int length, int start, struct re_registers *regs);
+
+
+/* Relates to `re_match' as `re_search_2' relates to `re_search'. */
+extern int re_match_2 (struct re_pattern_buffer *buffer, const char *string1,
+ int length1, const char *string2, int length2,
+ int start, struct re_registers *regs, int stop);
+
+
+/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
+ ENDS. Subsequent matches using BUFFER and REGS will use this memory
+ for recording register information. STARTS and ENDS must be
+ allocated with malloc, and must each be at least `NUM_REGS * sizeof
+ (regoff_t)' bytes long.
+
+ If NUM_REGS == 0, then subsequent matches should allocate their own
+ register data.
+
+ Unless this function is called, the first search or match using
+ PATTERN_BUFFER will allocate its own register data, without
+ freeing the old data. */
+extern void re_set_registers (struct re_pattern_buffer *buffer,
+ struct re_registers *regs, unsigned num_regs,
+ regoff_t *starts, regoff_t *ends);
+
+#if defined _REGEX_RE_COMP || defined _LIBC
+# ifndef _CRAY
+/* 4.2 bsd compatibility. */
+extern char *re_comp (const char *);
+extern int re_exec (const char *);
+# endif
+#endif
+
+/* GCC 2.95 and later have "__restrict"; C99 compilers have
+ "restrict", and "configure" may have defined "restrict". */
+#ifndef __restrict
+# if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__))
+# if defined restrict || 199901L <= __STDC_VERSION__
+# define __restrict restrict
+# else
+# define __restrict
+# endif
+# endif
+#endif
+/* gcc 3.1 and up support the [restrict] syntax. */
+#ifndef __restrict_arr
+# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+# define __restrict_arr __restrict
+# else
+# define __restrict_arr
+# endif
+#endif
+
+/* POSIX compatibility. */
+extern int regcomp (regex_t *__restrict __preg,
+ const char *__restrict __pattern,
+ int __cflags);
+
+extern int regexec (const regex_t *__restrict __preg,
+ const char *__restrict __string, size_t __nmatch,
+ regmatch_t __pmatch[__restrict_arr],
+ int __eflags);
+
+extern size_t regerror (int __errcode, const regex_t *__preg,
+ char *__errbuf, size_t __errbuf_size);
+
+extern void regfree (regex_t *__preg);
+
+
+#ifdef __cplusplus
+}
+#endif /* C++ */
+
+#endif /* regex.h */
+
+/*
+Local variables:
+make-backup-files: t
+version-control: t
+trim-versions-without-asking: nil
+End:
+*/
diff --git a/contrib/diff/lib/setmode.c b/contrib/diff/lib/setmode.c
new file mode 100644
index 0000000..b2b93a6
--- /dev/null
+++ b/contrib/diff/lib/setmode.c
@@ -0,0 +1,67 @@
+/* Set a file descriptor's mode to binary or to text.
+
+ Copyright (C) 2001, 2004 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; see the file COPYING.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Paul Eggert <eggert@twinsun.com> */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+typedef enum {false = 0, true = 1} bool;
+#endif
+
+#if HAVE_SETMODE_DOS
+# include <io.h>
+# if HAVE_FCNTL_H
+# include <fcntl.h>
+# endif
+# if HAVE_UNISTD_H
+# include <unistd.h>
+# endif
+#endif
+
+#include "setmode.h"
+#undef set_binary_mode
+
+#ifndef __attribute__
+# if __GNUC__ < 3 || __STRICT_ANSI__
+# define __attribute__(x)
+# endif
+#endif
+
+/* Set the binary mode of FD to MODE, returning its previous mode.
+ MODE is 1 for binary and 0 for text. If setting the mode might
+ cause problems, ignore the request and return MODE. Always return
+ 1 on POSIX platforms, which do not distinguish between text and
+ binary. */
+
+#if HAVE_SETMODE_DOS
+bool
+set_binary_mode (int fd, bool mode)
+{
+ if (isatty (fd))
+ return mode;
+ return setmode (fd, mode ? O_BINARY : O_TEXT) != O_TEXT;
+}
+#else
+static char dummy;
+#endif
diff --git a/contrib/diff/lib/setmode.h b/contrib/diff/lib/setmode.h
new file mode 100644
index 0000000..8381d12
--- /dev/null
+++ b/contrib/diff/lib/setmode.h
@@ -0,0 +1,27 @@
+/* Set a file descriptor's mode to binary or to text.
+
+ Copyright (C) 2001, 2004 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; see the file COPYING.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Paul Eggert <eggert@twinsun.com> */
+
+#ifndef set_binary_mode
+bool set_binary_mode (int, bool);
+# if ! HAVE_SETMODE_DOS
+# define set_binary_mode(fd, mode) true
+# endif
+#endif
diff --git a/contrib/diff/lib/stdbool_.h b/contrib/diff/lib/stdbool_.h
new file mode 100644
index 0000000..e33715a
--- /dev/null
+++ b/contrib/diff/lib/stdbool_.h
@@ -0,0 +1,93 @@
+/* Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+ Written by Bruno Haible <haible@clisp.cons.org>, 2001.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _STDBOOL_H
+#define _STDBOOL_H
+
+/* ISO C 99 <stdbool.h> for platforms that lack it. */
+
+/* Usage suggestions:
+
+ Programs that use <stdbool.h> should be aware of some limitations
+ and standards compliance issues.
+
+ Standards compliance:
+
+ - <stdbool.h> must be #included before 'bool', 'false', 'true'
+ can be used.
+
+ - You cannot assume that sizeof (bool) == 1.
+
+ - Programs should not undefine the macros bool, true, and false,
+ as C99 lists that as an "obsolescent feature".
+
+ Limitations of this substitute, when used in a C89 environment:
+
+ - <stdbool.h> must be #included before the '_Bool' type can be used.
+
+ - You cannot assume that _Bool is a typedef; it might be a macro.
+
+ - In C99, casts and automatic conversions to '_Bool' or 'bool' are
+ performed in such a way that every nonzero value gets converted
+ to 'true', and zero gets converted to 'false'. This doesn't work
+ with this substitute. With this substitute, only the values 0 and 1
+ give the expected result when converted to _Bool' or 'bool'.
+
+ Also, it is suggested that programs use 'bool' rather than '_Bool';
+ this isn't required, but 'bool' is more common. */
+
+
+/* 7.16. Boolean type and values */
+
+/* BeOS <sys/socket.h> already #defines false 0, true 1. We use the same
+ definitions below, but temporarily we have to #undef them. */
+#ifdef __BEOS__
+# include <OS.h> /* defines bool but not _Bool */
+# undef false
+# undef true
+#endif
+
+/* For the sake of symbolic names in gdb, we define true and false as
+ enum constants, not only as macros.
+ It is tempting to write
+ typedef enum { false = 0, true = 1 } _Bool;
+ so that gdb prints values of type 'bool' symbolically. But if we do
+ this, values of type '_Bool' may promote to 'int' or 'unsigned int'
+ (see ISO C 99 6.7.2.2.(4)); however, '_Bool' must promote to 'int'
+ (see ISO C 99 6.3.1.1.(2)). So we add a negative value to the
+ enum; this ensures that '_Bool' promotes to 'int'. */
+#if !(defined __cplusplus || defined __BEOS__)
+# if !@HAVE__BOOL@
+# if defined __SUNPRO_C && (__SUNPRO_C < 0x550 || __STDC__ == 1)
+ /* Avoid stupid "warning: _Bool is a keyword in ISO C99". */
+# define _Bool signed char
+enum { false = 0, true = 1 };
+# else
+typedef enum { _Bool_must_promote_to_int = -1, false = 0, true = 1 } _Bool;
+# endif
+# endif
+#else
+typedef bool _Bool;
+#endif
+#define bool _Bool
+
+/* The other macros must be usable in preprocessor directives. */
+#define false 0
+#define true 1
+#define __bool_true_false_are_defined 1
+
+#endif /* _STDBOOL_H */
diff --git a/contrib/diff/lib/strcase.h b/contrib/diff/lib/strcase.h
new file mode 100644
index 0000000..f17e648
--- /dev/null
+++ b/contrib/diff/lib/strcase.h
@@ -0,0 +1,35 @@
+/* Case-insensitive string comparison functions.
+ Copyright (C) 1995-1996, 2001, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _STRCASE_H
+#define _STRCASE_H
+
+#include <stddef.h>
+
+/* Compare strings S1 and S2, ignoring case, returning less than, equal to or
+ greater than zero if S1 is lexicographically less than, equal to or greater
+ than S2.
+ Note: This function does not work correctly in multibyte locales. */
+extern int strcasecmp (const char *s1, const char *s2);
+
+/* Compare no more than N characters of strings S1 and S2, ignoring case,
+ returning less than, equal to or greater than zero if S1 is
+ lexicographically less than, equal to or greater than S2.
+ Note: This function can not work correctly in multibyte locales. */
+extern int strncasecmp (const char *s1, const char *s2, size_t n);
+
+#endif /* _STRCASE_H */
diff --git a/contrib/diff/lib/strcasecmp.c b/contrib/diff/lib/strcasecmp.c
new file mode 100644
index 0000000..cf4ab88
--- /dev/null
+++ b/contrib/diff/lib/strcasecmp.c
@@ -0,0 +1,66 @@
+/* strcasecmp.c -- case insensitive string comparator
+ Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef LENGTH_LIMIT
+# define STRXCASECMP_FUNCTION strncasecmp
+# define STRXCASECMP_DECLARE_N , size_t n
+# define LENGTH_LIMIT_EXPR(Expr) Expr
+#else
+# define STRXCASECMP_FUNCTION strcasecmp
+# define STRXCASECMP_DECLARE_N /* empty */
+# define LENGTH_LIMIT_EXPR(Expr) 0
+#endif
+
+#include <stddef.h>
+#include <ctype.h>
+
+#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
+
+/* Compare {{no more than N characters of }}strings S1 and S2,
+ ignoring case, returning less than, equal to or
+ greater than zero if S1 is lexicographically less
+ than, equal to or greater than S2. */
+
+int
+STRXCASECMP_FUNCTION (const char *s1, const char *s2 STRXCASECMP_DECLARE_N)
+{
+ register const unsigned char *p1 = (const unsigned char *) s1;
+ register const unsigned char *p2 = (const unsigned char *) s2;
+ unsigned char c1, c2;
+
+ if (p1 == p2 || LENGTH_LIMIT_EXPR (n == 0))
+ return 0;
+
+ do
+ {
+ c1 = TOLOWER (*p1);
+ c2 = TOLOWER (*p2);
+
+ if (LENGTH_LIMIT_EXPR (--n == 0) || c1 == '\0')
+ break;
+
+ ++p1;
+ ++p2;
+ }
+ while (c1 == c2);
+
+ return c1 - c2;
+}
diff --git a/contrib/diff/lib/strftime.c b/contrib/diff/lib/strftime.c
new file mode 100644
index 0000000..dccbaf7
--- /dev/null
+++ b/contrib/diff/lib/strftime.c
@@ -0,0 +1,1330 @@
+/* Copyright (C) 1991-1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+
+ NOTE: The canonical source of this file is maintained with the GNU C Library.
+ Bugs can be reported to bug-glibc@prep.ai.mit.edu.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef _LIBC
+# define HAVE_MBLEN 1
+# define HAVE_MBRLEN 1
+# define HAVE_STRUCT_ERA_ENTRY 1
+# define HAVE_TM_GMTOFF 1
+# define HAVE_TM_ZONE 1
+# define HAVE_TZNAME 1
+# define HAVE_TZSET 1
+# define MULTIBYTE_IS_FORMAT_SAFE 1
+# include "../locale/localeinfo.h"
+#endif
+
+#include <ctype.h>
+#include <sys/types.h> /* Some systems define `time_t' here. */
+
+#ifdef TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+#if HAVE_TZNAME
+extern char *tzname[];
+#endif
+
+/* Do multibyte processing if multibytes are supported, unless
+ multibyte sequences are safe in formats. Multibyte sequences are
+ safe if they cannot contain byte sequences that look like format
+ conversion specifications. The GNU C Library uses UTF8 multibyte
+ encoding, which is safe for formats, but strftime.c can be used
+ with other C libraries that use unsafe encodings. */
+#define DO_MULTIBYTE (HAVE_MBLEN && ! MULTIBYTE_IS_FORMAT_SAFE)
+
+#if DO_MULTIBYTE
+# if HAVE_MBRLEN
+# include <wchar.h>
+# else
+ /* Simulate mbrlen with mblen as best we can. */
+# define mbstate_t int
+# define mbrlen(s, n, ps) mblen (s, n)
+# define mbsinit(ps) (*(ps) == 0)
+# endif
+ static const mbstate_t mbstate_zero;
+#endif
+
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef COMPILE_WIDE
+# include <endian.h>
+# define CHAR_T wchar_t
+# define UCHAR_T unsigned int
+# define L_(Str) L##Str
+# define NLW(Sym) _NL_W##Sym
+
+# define MEMCPY(d, s, n) __wmemcpy (d, s, n)
+# define STRLEN(s) __wcslen (s)
+
+#else
+# define CHAR_T char
+# define UCHAR_T unsigned char
+# define L_(Str) Str
+# define NLW(Sym) Sym
+
+# define MEMCPY(d, s, n) memcpy (d, s, n)
+# define STRLEN(s) strlen (s)
+
+# ifdef _LIBC
+# define MEMPCPY(d, s, n) __mempcpy (d, s, n)
+# else
+# ifndef HAVE_MEMPCPY
+# define MEMPCPY(d, s, n) ((void *) ((char *) memcpy (d, s, n) + (n)))
+# endif
+# endif
+#endif
+
+#define TYPE_SIGNED(t) ((t) -1 < 0)
+
+/* Bound on length of the string representing an integer value of type t.
+ Subtract one for the sign bit if t is signed;
+ 302 / 1000 is log10 (2) rounded up;
+ add one for integer division truncation;
+ add one more for a minus sign if t is signed. */
+#define INT_STRLEN_BOUND(t) \
+ ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 + 1 + TYPE_SIGNED (t))
+
+#define TM_YEAR_BASE 1900
+
+#ifndef __isleap
+/* Nonzero if YEAR is a leap year (every 4 years,
+ except every 100th isn't, and every 400th is). */
+# define __isleap(year) \
+ ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
+#endif
+
+
+#ifdef _LIBC
+# define tzname __tzname
+# define tzset __tzset
+#endif
+
+#if !HAVE_TM_GMTOFF
+/* Portable standalone applications should supply a "time_r.h" that
+ declares a POSIX-compliant localtime_r, for the benefit of older
+ implementations that lack localtime_r or have a nonstandard one.
+ See the gnulib time_r module for one way to implement this. */
+# include "time_r.h"
+# undef __gmtime_r
+# undef __localtime_r
+# define __gmtime_r gmtime_r
+# define __localtime_r localtime_r
+#endif
+
+
+#ifdef COMPILE_WIDE
+# define memset_space(P, Len) (wmemset (P, L' ', Len), (P) += (Len))
+# define memset_zero(P, Len) (wmemset (P, L'0', Len), (P) += (Len))
+#else
+# define memset_space(P, Len) (memset (P, ' ', Len), (P) += (Len))
+# define memset_zero(P, Len) (memset (P, '0', Len), (P) += (Len))
+#endif
+
+#define add(n, f) \
+ do \
+ { \
+ int _n = (n); \
+ int _delta = width - _n; \
+ int _incr = _n + (_delta > 0 ? _delta : 0); \
+ if ((size_t) _incr >= maxsize - i) \
+ return 0; \
+ if (p) \
+ { \
+ if (_delta > 0) \
+ { \
+ if (pad == L_('0')) \
+ memset_zero (p, _delta); \
+ else \
+ memset_space (p, _delta); \
+ } \
+ f; \
+ p += _n; \
+ } \
+ i += _incr; \
+ } while (0)
+
+#define cpy(n, s) \
+ add ((n), \
+ if (to_lowcase) \
+ memcpy_lowcase (p, (s), _n LOCALE_ARG); \
+ else if (to_uppcase) \
+ memcpy_uppcase (p, (s), _n LOCALE_ARG); \
+ else \
+ MEMCPY ((void *) p, (void const *) (s), _n))
+
+#ifdef COMPILE_WIDE
+# ifndef USE_IN_EXTENDED_LOCALE_MODEL
+# undef __mbsrtowcs_l
+# define __mbsrtowcs_l(d, s, l, st, loc) __mbsrtowcs (d, s, l, st)
+# endif
+# define widen(os, ws, l) \
+ { \
+ mbstate_t __st; \
+ const char *__s = os; \
+ memset (&__st, '\0', sizeof (__st)); \
+ l = __mbsrtowcs_l (NULL, &__s, 0, &__st, loc); \
+ ws = (wchar_t *) alloca ((l + 1) * sizeof (wchar_t)); \
+ (void) __mbsrtowcs_l (ws, &__s, l, &__st, loc); \
+ }
+#endif
+
+
+#if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
+/* We use this code also for the extended locale handling where the
+ function gets as an additional argument the locale which has to be
+ used. To access the values we have to redefine the _NL_CURRENT
+ macro. */
+# define strftime __strftime_l
+# define wcsftime __wcsftime_l
+# undef _NL_CURRENT
+# define _NL_CURRENT(category, item) \
+ (current->values[_NL_ITEM_INDEX (item)].string)
+# define LOCALE_ARG , loc
+# define LOCALE_PARAM_PROTO , __locale_t loc
+# define HELPER_LOCALE_ARG , current
+#else
+# define LOCALE_PARAM_PROTO
+# define LOCALE_ARG
+# ifdef _LIBC
+# define HELPER_LOCALE_ARG , _NL_CURRENT_DATA (LC_TIME)
+# else
+# define HELPER_LOCALE_ARG
+# endif
+#endif
+
+#ifdef COMPILE_WIDE
+# ifdef USE_IN_EXTENDED_LOCALE_MODEL
+# define TOUPPER(Ch, L) __towupper_l (Ch, L)
+# define TOLOWER(Ch, L) __towlower_l (Ch, L)
+# else
+# define TOUPPER(Ch, L) towupper (Ch)
+# define TOLOWER(Ch, L) towlower (Ch)
+# endif
+#else
+# ifdef _LIBC
+# ifdef USE_IN_EXTENDED_LOCALE_MODEL
+# define TOUPPER(Ch, L) __toupper_l (Ch, L)
+# define TOLOWER(Ch, L) __tolower_l (Ch, L)
+# else
+# define TOUPPER(Ch, L) toupper (Ch)
+# define TOLOWER(Ch, L) tolower (Ch)
+# endif
+# else
+# define TOUPPER(Ch, L) (islower (Ch) ? toupper (Ch) : (Ch))
+# define TOLOWER(Ch, L) (isupper (Ch) ? tolower (Ch) : (Ch))
+# endif
+#endif
+/* We don't use `isdigit' here since the locale dependent
+ interpretation is not what we want here. We only need to accept
+ the arabic digits in the ASCII range. One day there is perhaps a
+ more reliable way to accept other sets of digits. */
+#define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9)
+
+static CHAR_T *
+memcpy_lowcase (CHAR_T *dest, const CHAR_T *src,
+ size_t len LOCALE_PARAM_PROTO)
+{
+ while (len-- > 0)
+ dest[len] = TOLOWER ((UCHAR_T) src[len], loc);
+ return dest;
+}
+
+static CHAR_T *
+memcpy_uppcase (CHAR_T *dest, const CHAR_T *src,
+ size_t len LOCALE_PARAM_PROTO)
+{
+ while (len-- > 0)
+ dest[len] = TOUPPER ((UCHAR_T) src[len], loc);
+ return dest;
+}
+
+
+#if ! HAVE_TM_GMTOFF
+/* Yield the difference between *A and *B,
+ measured in seconds, ignoring leap seconds. */
+# define tm_diff ftime_tm_diff
+static int
+tm_diff (const struct tm *a, const struct tm *b)
+{
+ /* Compute intervening leap days correctly even if year is negative.
+ Take care to avoid int overflow in leap day calculations,
+ but it's OK to assume that A and B are close to each other. */
+ int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3);
+ int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3);
+ int a100 = a4 / 25 - (a4 % 25 < 0);
+ int b100 = b4 / 25 - (b4 % 25 < 0);
+ int a400 = a100 >> 2;
+ int b400 = b100 >> 2;
+ int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
+ int years = a->tm_year - b->tm_year;
+ int days = (365 * years + intervening_leap_days
+ + (a->tm_yday - b->tm_yday));
+ return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
+ + (a->tm_min - b->tm_min))
+ + (a->tm_sec - b->tm_sec));
+}
+#endif /* ! HAVE_TM_GMTOFF */
+
+
+
+/* The number of days from the first day of the first ISO week of this
+ year to the year day YDAY with week day WDAY. ISO weeks start on
+ Monday; the first ISO week has the year's first Thursday. YDAY may
+ be as small as YDAY_MINIMUM. */
+#define ISO_WEEK_START_WDAY 1 /* Monday */
+#define ISO_WEEK1_WDAY 4 /* Thursday */
+#define YDAY_MINIMUM (-366)
+#ifdef __GNUC__
+__inline__
+#endif
+static int
+iso_week_days (int yday, int wday)
+{
+ /* Add enough to the first operand of % to make it nonnegative. */
+ int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
+ return (yday
+ - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
+ + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
+}
+
+
+#if !(defined _NL_CURRENT || HAVE_STRFTIME)
+static CHAR_T const weekday_name[][10] =
+ {
+ L_("Sunday"), L_("Monday"), L_("Tuesday"), L_("Wednesday"),
+ L_("Thursday"), L_("Friday"), L_("Saturday")
+ };
+static CHAR_T const month_name[][10] =
+ {
+ L_("January"), L_("February"), L_("March"), L_("April"), L_("May"),
+ L_("June"), L_("July"), L_("August"), L_("September"), L_("October"),
+ L_("November"), L_("December")
+ };
+#endif
+
+
+/* When compiling this file, GNU applications can #define my_strftime
+ to a symbol (typically nstrftime) to get an extended strftime with
+ extra arguments UT and NS. Emacs is a special case for now, but
+ this Emacs-specific code can be removed once Emacs's config.h
+ defines my_strftime. */
+#if defined emacs && !defined my_strftime
+# define my_strftime nstrftime
+#endif
+
+#ifdef my_strftime
+# define extra_args , ut, ns
+# define extra_args_spec , int ut, int ns
+#else
+# ifdef COMPILE_WIDE
+# define my_strftime wcsftime
+# define nl_get_alt_digit _nl_get_walt_digit
+# else
+# define my_strftime strftime
+# define nl_get_alt_digit _nl_get_alt_digit
+# endif
+# define extra_args
+# define extra_args_spec
+/* We don't have this information in general. */
+# define ut 0
+# define ns 0
+#endif
+
+#if ! defined _LIBC && ! HAVE_RUN_TZSET_TEST
+/* Solaris 2.5.x and 2.6 tzset sometimes modify the storage returned
+ by localtime. On such systems, we must use the tzset and localtime
+ wrappers to work around the bug. */
+"you must run the autoconf test for a working tzset function"
+#endif
+
+
+/* Write information from TP into S according to the format
+ string FORMAT, writing no more that MAXSIZE characters
+ (including the terminating '\0') and returning number of
+ characters written. If S is NULL, nothing will be written
+ anywhere, so to determine how many characters would be
+ written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */
+size_t
+my_strftime (CHAR_T *s, size_t maxsize, const CHAR_T *format,
+ const struct tm *tp extra_args_spec LOCALE_PARAM_PROTO)
+{
+#if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
+ struct locale_data *const current = loc->__locales[LC_TIME];
+#endif
+
+ int hour12 = tp->tm_hour;
+#ifdef _NL_CURRENT
+ /* We cannot make the following values variables since we must delay
+ the evaluation of these values until really needed since some
+ expressions might not be valid in every situation. The `struct tm'
+ might be generated by a strptime() call that initialized
+ only a few elements. Dereference the pointers only if the format
+ requires this. Then it is ok to fail if the pointers are invalid. */
+# define a_wkday \
+ ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday))
+# define f_wkday \
+ ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday))
+# define a_month \
+ ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon))
+# define f_month \
+ ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon))
+# define ampm \
+ ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \
+ ? NLW(PM_STR) : NLW(AM_STR)))
+
+# define aw_len STRLEN (a_wkday)
+# define am_len STRLEN (a_month)
+# define ap_len STRLEN (ampm)
+#else
+# if !HAVE_STRFTIME
+# define f_wkday (weekday_name[tp->tm_wday])
+# define f_month (month_name[tp->tm_mon])
+# define a_wkday f_wkday
+# define a_month f_month
+# define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11))
+
+ size_t aw_len = 3;
+ size_t am_len = 3;
+ size_t ap_len = 2;
+# endif
+#endif
+ const char *zone;
+ size_t i = 0;
+ CHAR_T *p = s;
+ const CHAR_T *f;
+#if DO_MULTIBYTE && !defined COMPILE_WIDE
+ const char *format_end = NULL;
+#endif
+
+ zone = NULL;
+#if HAVE_TM_ZONE
+ /* The POSIX test suite assumes that setting
+ the environment variable TZ to a new value before calling strftime()
+ will influence the result (the %Z format) even if the information in
+ TP is computed with a totally different time zone.
+ This is bogus: though POSIX allows bad behavior like this,
+ POSIX does not require it. Do the right thing instead. */
+ zone = (const char *) tp->tm_zone;
+#endif
+#if HAVE_TZNAME
+ if (ut)
+ {
+ if (! (zone && *zone))
+ zone = "GMT";
+ }
+ else
+ {
+ /* POSIX.1 requires that local time zone information be used as
+ though strftime called tzset. */
+# if HAVE_TZSET
+ tzset ();
+# endif
+ }
+#endif
+
+ if (hour12 > 12)
+ hour12 -= 12;
+ else
+ if (hour12 == 0)
+ hour12 = 12;
+
+ for (f = format; *f != '\0'; ++f)
+ {
+ int pad = 0; /* Padding for number ('-', '_', or 0). */
+ int modifier; /* Field modifier ('E', 'O', or 0). */
+ int digits; /* Max digits for numeric format. */
+ int number_value; /* Numeric value to be printed. */
+ int negative_number; /* 1 if the number is negative. */
+ const CHAR_T *subfmt;
+ CHAR_T *bufp;
+ CHAR_T buf[1 + (sizeof (int) < sizeof (time_t)
+ ? INT_STRLEN_BOUND (time_t)
+ : INT_STRLEN_BOUND (int))];
+ int width = -1;
+ int to_lowcase = 0;
+ int to_uppcase = 0;
+ int change_case = 0;
+ int format_char;
+
+#if DO_MULTIBYTE && !defined COMPILE_WIDE
+ switch (*f)
+ {
+ case L_('%'):
+ break;
+
+ case L_('\b'): case L_('\t'): case L_('\n'):
+ case L_('\v'): case L_('\f'): case L_('\r'):
+ case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'):
+ case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'):
+ case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'):
+ case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'):
+ case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'):
+ case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'):
+ case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'):
+ case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'):
+ case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'):
+ case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'):
+ case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'):
+ case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'):
+ case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'):
+ case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'):
+ case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'):
+ case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'):
+ case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'):
+ case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'):
+ case L_('~'):
+ /* The C Standard requires these 98 characters (plus '%') to
+ be in the basic execution character set. None of these
+ characters can start a multibyte sequence, so they need
+ not be analyzed further. */
+ add (1, *p = *f);
+ continue;
+
+ default:
+ /* Copy this multibyte sequence until we reach its end, find
+ an error, or come back to the initial shift state. */
+ {
+ mbstate_t mbstate = mbstate_zero;
+ size_t len = 0;
+ size_t fsize;
+
+ if (! format_end)
+ format_end = f + strlen (f) + 1;
+ fsize = format_end - f;
+
+ do
+ {
+ size_t bytes = mbrlen (f + len, fsize - len, &mbstate);
+
+ if (bytes == 0)
+ break;
+
+ if (bytes == (size_t) -2)
+ {
+ len += strlen (f + len);
+ break;
+ }
+
+ if (bytes == (size_t) -1)
+ {
+ len++;
+ break;
+ }
+
+ len += bytes;
+ }
+ while (! mbsinit (&mbstate));
+
+ cpy (len, f);
+ f += len - 1;
+ continue;
+ }
+ }
+
+#else /* ! DO_MULTIBYTE */
+
+ /* Either multibyte encodings are not supported, they are
+ safe for formats, so any non-'%' byte can be copied through,
+ or this is the wide character version. */
+ if (*f != L_('%'))
+ {
+ add (1, *p = *f);
+ continue;
+ }
+
+#endif /* ! DO_MULTIBYTE */
+
+ /* Check for flags that can modify a format. */
+ while (1)
+ {
+ switch (*++f)
+ {
+ /* This influences the number formats. */
+ case L_('_'):
+ case L_('-'):
+ case L_('0'):
+ pad = *f;
+ continue;
+
+ /* This changes textual output. */
+ case L_('^'):
+ to_uppcase = 1;
+ continue;
+ case L_('#'):
+ change_case = 1;
+ continue;
+
+ default:
+ break;
+ }
+ break;
+ }
+
+ /* As a GNU extension we allow to specify the field width. */
+ if (ISDIGIT (*f))
+ {
+ width = 0;
+ do
+ {
+ if (width > INT_MAX / 10
+ || (width == INT_MAX / 10 && *f - L_('0') > INT_MAX % 10))
+ /* Avoid overflow. */
+ width = INT_MAX;
+ else
+ {
+ width *= 10;
+ width += *f - L_('0');
+ }
+ ++f;
+ }
+ while (ISDIGIT (*f));
+ }
+
+ /* Check for modifiers. */
+ switch (*f)
+ {
+ case L_('E'):
+ case L_('O'):
+ modifier = *f++;
+ break;
+
+ default:
+ modifier = 0;
+ break;
+ }
+
+ /* Now do the specified format. */
+ format_char = *f;
+ switch (format_char)
+ {
+#define DO_NUMBER(d, v) \
+ digits = d > width ? d : width; \
+ number_value = v; goto do_number
+#define DO_NUMBER_SPACEPAD(d, v) \
+ digits = d > width ? d : width; \
+ number_value = v; goto do_number_spacepad
+
+ case L_('%'):
+ if (modifier != 0)
+ goto bad_format;
+ add (1, *p = *f);
+ break;
+
+ case L_('a'):
+ if (modifier != 0)
+ goto bad_format;
+ if (change_case)
+ {
+ to_uppcase = 1;
+ to_lowcase = 0;
+ }
+#if defined _NL_CURRENT || !HAVE_STRFTIME
+ cpy (aw_len, a_wkday);
+ break;
+#else
+ goto underlying_strftime;
+#endif
+
+ case 'A':
+ if (modifier != 0)
+ goto bad_format;
+ if (change_case)
+ {
+ to_uppcase = 1;
+ to_lowcase = 0;
+ }
+#if defined _NL_CURRENT || !HAVE_STRFTIME
+ cpy (STRLEN (f_wkday), f_wkday);
+ break;
+#else
+ goto underlying_strftime;
+#endif
+
+ case L_('b'):
+ case L_('h'):
+ if (change_case)
+ {
+ to_uppcase = 1;
+ to_lowcase = 0;
+ }
+ if (modifier != 0)
+ goto bad_format;
+#if defined _NL_CURRENT || !HAVE_STRFTIME
+ cpy (am_len, a_month);
+ break;
+#else
+ goto underlying_strftime;
+#endif
+
+ case L_('B'):
+ if (modifier != 0)
+ goto bad_format;
+ if (change_case)
+ {
+ to_uppcase = 1;
+ to_lowcase = 0;
+ }
+#if defined _NL_CURRENT || !HAVE_STRFTIME
+ cpy (STRLEN (f_month), f_month);
+ break;
+#else
+ goto underlying_strftime;
+#endif
+
+ case L_('c'):
+ if (modifier == L_('O'))
+ goto bad_format;
+#ifdef _NL_CURRENT
+ if (! (modifier == 'E'
+ && (*(subfmt =
+ (const CHAR_T *) _NL_CURRENT (LC_TIME,
+ NLW(ERA_D_T_FMT)))
+ != '\0')))
+ subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT));
+#else
+# if HAVE_STRFTIME
+ goto underlying_strftime;
+# else
+ subfmt = L_("%a %b %e %H:%M:%S %Y");
+# endif
+#endif
+
+ subformat:
+ {
+ CHAR_T *old_start = p;
+ size_t len = my_strftime (NULL, (size_t) -1, subfmt,
+ tp extra_args LOCALE_ARG);
+ add (len, my_strftime (p, maxsize - i, subfmt,
+ tp extra_args LOCALE_ARG));
+
+ if (to_uppcase)
+ while (old_start < p)
+ {
+ *old_start = TOUPPER ((UCHAR_T) *old_start, loc);
+ ++old_start;
+ }
+ }
+ break;
+
+#if HAVE_STRFTIME && ! (defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
+ underlying_strftime:
+ {
+ /* The relevant information is available only via the
+ underlying strftime implementation, so use that. */
+ char ufmt[4];
+ char *u = ufmt;
+ char ubuf[1024]; /* enough for any single format in practice */
+ size_t len;
+ /* Make sure we're calling the actual underlying strftime.
+ In some cases, config.h contains something like
+ "#define strftime rpl_strftime". */
+# ifdef strftime
+# undef strftime
+ size_t strftime ();
+# endif
+
+ *u++ = '%';
+ if (modifier != 0)
+ *u++ = modifier;
+ *u++ = format_char;
+ *u = '\0';
+ len = strftime (ubuf, sizeof ubuf, ufmt, tp);
+ if (len == 0 && ubuf[0] != '\0')
+ return 0;
+ cpy (len, ubuf);
+ }
+ break;
+#endif
+
+ case L_('C'):
+ if (modifier == L_('O'))
+ goto bad_format;
+ if (modifier == L_('E'))
+ {
+#if HAVE_STRUCT_ERA_ENTRY
+ struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
+ if (era)
+ {
+# ifdef COMPILE_WIDE
+ size_t len = __wcslen (era->era_wname);
+ cpy (len, era->era_wname);
+# else
+ size_t len = strlen (era->era_name);
+ cpy (len, era->era_name);
+# endif
+ break;
+ }
+#else
+# if HAVE_STRFTIME
+ goto underlying_strftime;
+# endif
+#endif
+ }
+
+ {
+ int year = tp->tm_year + TM_YEAR_BASE;
+ DO_NUMBER (1, year / 100 - (year % 100 < 0));
+ }
+
+ case L_('x'):
+ if (modifier == L_('O'))
+ goto bad_format;
+#ifdef _NL_CURRENT
+ if (! (modifier == L_('E')
+ && (*(subfmt =
+ (const CHAR_T *)_NL_CURRENT (LC_TIME, NLW(ERA_D_FMT)))
+ != L_('\0'))))
+ subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
+ goto subformat;
+#else
+# if HAVE_STRFTIME
+ goto underlying_strftime;
+# else
+ /* Fall through. */
+# endif
+#endif
+ case L_('D'):
+ if (modifier != 0)
+ goto bad_format;
+ subfmt = L_("%m/%d/%y");
+ goto subformat;
+
+ case L_('d'):
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER (2, tp->tm_mday);
+
+ case L_('e'):
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER_SPACEPAD (2, tp->tm_mday);
+
+ /* All numeric formats set DIGITS and NUMBER_VALUE and then
+ jump to one of these two labels. */
+
+ do_number_spacepad:
+ /* Force `_' flag unless overridden by `0' or `-' flag. */
+ if (pad != L_('0') && pad != L_('-'))
+ pad = L_('_');
+
+ do_number:
+ /* Format the number according to the MODIFIER flag. */
+
+ if (modifier == L_('O') && 0 <= number_value)
+ {
+#ifdef _NL_CURRENT
+ /* Get the locale specific alternate representation of
+ the number NUMBER_VALUE. If none exist NULL is returned. */
+ const CHAR_T *cp = nl_get_alt_digit (number_value
+ HELPER_LOCALE_ARG);
+
+ if (cp != NULL)
+ {
+ size_t digitlen = STRLEN (cp);
+ if (digitlen != 0)
+ {
+ cpy (digitlen, cp);
+ break;
+ }
+ }
+#else
+# if HAVE_STRFTIME
+ goto underlying_strftime;
+# endif
+#endif
+ }
+ {
+ unsigned int u = number_value;
+
+ bufp = buf + sizeof (buf) / sizeof (buf[0]);
+ negative_number = number_value < 0;
+
+ if (negative_number)
+ u = -u;
+
+ do
+ *--bufp = u % 10 + L_('0');
+ while ((u /= 10) != 0);
+ }
+
+ do_number_sign_and_padding:
+ if (negative_number)
+ *--bufp = L_('-');
+
+ if (pad != L_('-'))
+ {
+ int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0]))
+ - bufp);
+
+ if (padding > 0)
+ {
+ if (pad == L_('_'))
+ {
+ if ((size_t) padding >= maxsize - i)
+ return 0;
+
+ if (p)
+ memset_space (p, padding);
+ i += padding;
+ width = width > padding ? width - padding : 0;
+ }
+ else
+ {
+ if ((size_t) digits >= maxsize - i)
+ return 0;
+
+ if (negative_number)
+ {
+ ++bufp;
+
+ if (p)
+ *p++ = L_('-');
+ ++i;
+ }
+
+ if (p)
+ memset_zero (p, padding);
+ i += padding;
+ width = 0;
+ }
+ }
+ }
+
+ cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
+ break;
+
+ case L_('F'):
+ if (modifier != 0)
+ goto bad_format;
+ subfmt = L_("%Y-%m-%d");
+ goto subformat;
+
+ case L_('H'):
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER (2, tp->tm_hour);
+
+ case L_('I'):
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER (2, hour12);
+
+ case L_('k'): /* GNU extension. */
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER_SPACEPAD (2, tp->tm_hour);
+
+ case L_('l'): /* GNU extension. */
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER_SPACEPAD (2, hour12);
+
+ case L_('j'):
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER (3, 1 + tp->tm_yday);
+
+ case L_('M'):
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER (2, tp->tm_min);
+
+ case L_('m'):
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER (2, tp->tm_mon + 1);
+
+#ifndef _LIBC
+ case L_('N'): /* GNU extension. */
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ number_value = ns;
+ if (width != -1)
+ {
+ /* Take an explicit width less than 9 as a precision. */
+ int j;
+ for (j = width; j < 9; j++)
+ number_value /= 10;
+ }
+
+ DO_NUMBER (9, number_value);
+#endif
+
+ case L_('n'):
+ add (1, *p = L_('\n'));
+ break;
+
+ case L_('P'):
+ to_lowcase = 1;
+#if !defined _NL_CURRENT && HAVE_STRFTIME
+ format_char = L_('p');
+#endif
+ /* FALLTHROUGH */
+
+ case L_('p'):
+ if (change_case)
+ {
+ to_uppcase = 0;
+ to_lowcase = 1;
+ }
+#if defined _NL_CURRENT || !HAVE_STRFTIME
+ cpy (ap_len, ampm);
+ break;
+#else
+ goto underlying_strftime;
+#endif
+
+ case L_('R'):
+ subfmt = L_("%H:%M");
+ goto subformat;
+
+ case L_('r'):
+#if !defined _NL_CURRENT && HAVE_STRFTIME
+ goto underlying_strftime;
+#else
+# ifdef _NL_CURRENT
+ if (*(subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME,
+ NLW(T_FMT_AMPM)))
+ == L_('\0'))
+# endif
+ subfmt = L_("%I:%M:%S %p");
+ goto subformat;
+#endif
+
+ case L_('S'):
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER (2, tp->tm_sec);
+
+ case L_('s'): /* GNU extension. */
+ {
+ struct tm ltm;
+ time_t t;
+
+ ltm = *tp;
+ t = mktime (&ltm);
+
+ /* Generate string value for T using time_t arithmetic;
+ this works even if sizeof (long) < sizeof (time_t). */
+
+ bufp = buf + sizeof (buf) / sizeof (buf[0]);
+ negative_number = t < 0;
+
+ do
+ {
+ int d = t % 10;
+ t /= 10;
+
+ if (negative_number)
+ {
+ d = -d;
+
+ /* Adjust if division truncates to minus infinity. */
+ if (0 < -1 % 10 && d < 0)
+ {
+ t++;
+ d += 10;
+ }
+ }
+
+ *--bufp = d + L_('0');
+ }
+ while (t != 0);
+
+ digits = 1;
+ goto do_number_sign_and_padding;
+ }
+
+ case L_('X'):
+ if (modifier == L_('O'))
+ goto bad_format;
+#ifdef _NL_CURRENT
+ if (! (modifier == L_('E')
+ && (*(subfmt =
+ (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_T_FMT)))
+ != L_('\0'))))
+ subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
+ goto subformat;
+#else
+# if HAVE_STRFTIME
+ goto underlying_strftime;
+# else
+ /* Fall through. */
+# endif
+#endif
+ case L_('T'):
+ subfmt = L_("%H:%M:%S");
+ goto subformat;
+
+ case L_('t'):
+ add (1, *p = L_('\t'));
+ break;
+
+ case L_('u'):
+ DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
+
+ case L_('U'):
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
+
+ case L_('V'):
+ case L_('g'):
+ case L_('G'):
+ if (modifier == L_('E'))
+ goto bad_format;
+ {
+ int year = tp->tm_year + TM_YEAR_BASE;
+ int days = iso_week_days (tp->tm_yday, tp->tm_wday);
+
+ if (days < 0)
+ {
+ /* This ISO week belongs to the previous year. */
+ year--;
+ days = iso_week_days (tp->tm_yday + (365 + __isleap (year)),
+ tp->tm_wday);
+ }
+ else
+ {
+ int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
+ tp->tm_wday);
+ if (0 <= d)
+ {
+ /* This ISO week belongs to the next year. */
+ year++;
+ days = d;
+ }
+ }
+
+ switch (*f)
+ {
+ case L_('g'):
+ DO_NUMBER (2, (year % 100 + 100) % 100);
+
+ case L_('G'):
+ DO_NUMBER (1, year);
+
+ default:
+ DO_NUMBER (2, days / 7 + 1);
+ }
+ }
+
+ case L_('W'):
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
+
+ case L_('w'):
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER (1, tp->tm_wday);
+
+ case L_('Y'):
+ if (modifier == 'E')
+ {
+#if HAVE_STRUCT_ERA_ENTRY
+ struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
+ if (era)
+ {
+# ifdef COMPILE_WIDE
+ subfmt = era->era_wformat;
+# else
+ subfmt = era->era_format;
+# endif
+ goto subformat;
+ }
+#else
+# if HAVE_STRFTIME
+ goto underlying_strftime;
+# endif
+#endif
+ }
+ if (modifier == L_('O'))
+ goto bad_format;
+ else
+ DO_NUMBER (1, tp->tm_year + TM_YEAR_BASE);
+
+ case L_('y'):
+ if (modifier == L_('E'))
+ {
+#if HAVE_STRUCT_ERA_ENTRY
+ struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
+ if (era)
+ {
+ int delta = tp->tm_year - era->start_date[0];
+ DO_NUMBER (1, (era->offset
+ + delta * era->absolute_direction));
+ }
+#else
+# if HAVE_STRFTIME
+ goto underlying_strftime;
+# endif
+#endif
+ }
+ DO_NUMBER (2, (tp->tm_year % 100 + 100) % 100);
+
+ case L_('Z'):
+ if (change_case)
+ {
+ to_uppcase = 0;
+ to_lowcase = 1;
+ }
+
+#if HAVE_TZNAME
+ /* The tzset() call might have changed the value. */
+ if (!(zone && *zone) && tp->tm_isdst >= 0)
+ zone = tzname[tp->tm_isdst];
+#endif
+ if (! zone)
+ zone = "";
+
+#ifdef COMPILE_WIDE
+ {
+ /* The zone string is always given in multibyte form. We have
+ to transform it first. */
+ wchar_t *wczone;
+ size_t len;
+ widen (zone, wczone, len);
+ cpy (len, wczone);
+ }
+#else
+ cpy (strlen (zone), zone);
+#endif
+ break;
+
+ case L_('z'):
+ if (tp->tm_isdst < 0)
+ break;
+
+ {
+ int diff;
+#if HAVE_TM_GMTOFF
+ diff = tp->tm_gmtoff;
+#else
+ if (ut)
+ diff = 0;
+ else
+ {
+ struct tm gtm;
+ struct tm ltm;
+ time_t lt;
+
+ ltm = *tp;
+ lt = mktime (&ltm);
+
+ if (lt == (time_t) -1)
+ {
+ /* mktime returns -1 for errors, but -1 is also a
+ valid time_t value. Check whether an error really
+ occurred. */
+ struct tm tm;
+
+ if (! __localtime_r (&lt, &tm)
+ || ((ltm.tm_sec ^ tm.tm_sec)
+ | (ltm.tm_min ^ tm.tm_min)
+ | (ltm.tm_hour ^ tm.tm_hour)
+ | (ltm.tm_mday ^ tm.tm_mday)
+ | (ltm.tm_mon ^ tm.tm_mon)
+ | (ltm.tm_year ^ tm.tm_year)))
+ break;
+ }
+
+ if (! __gmtime_r (&lt, &gtm))
+ break;
+
+ diff = tm_diff (&ltm, &gtm);
+ }
+#endif
+
+ if (diff < 0)
+ {
+ add (1, *p = L_('-'));
+ diff = -diff;
+ }
+ else
+ add (1, *p = L_('+'));
+
+ diff /= 60;
+ DO_NUMBER (4, (diff / 60) * 100 + diff % 60);
+ }
+
+ case L_('\0'): /* GNU extension: % at end of format. */
+ --f;
+ /* Fall through. */
+ default:
+ /* Unknown format; output the format, including the '%',
+ since this is most likely the right thing to do if a
+ multibyte string has been misparsed. */
+ bad_format:
+ {
+ int flen;
+ for (flen = 1; f[1 - flen] != L_('%'); flen++)
+ continue;
+ cpy (flen, &f[1 - flen]);
+ }
+ break;
+ }
+ }
+
+ if (p && maxsize != 0)
+ *p = L_('\0');
+ return i;
+}
+#ifdef _LIBC
+libc_hidden_def (my_strftime)
+#endif
+
+
+#ifdef emacs
+/* For Emacs we have a separate interface which corresponds to the normal
+ strftime function plus the ut argument, but without the ns argument. */
+size_t
+emacs_strftimeu (char *s, size_t maxsize, const char *format,
+ const struct tm *tp, int ut)
+{
+ return my_strftime (s, maxsize, format, tp, ut, 0);
+}
+#endif
diff --git a/contrib/diff/lib/stripslash.c b/contrib/diff/lib/stripslash.c
new file mode 100644
index 0000000..c6b319e
--- /dev/null
+++ b/contrib/diff/lib/stripslash.c
@@ -0,0 +1,39 @@
+/* stripslash.c -- remove redundant trailing slashes from a file name
+ Copyright (C) 1990, 2001, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "dirname.h"
+
+/* Remove trailing slashes from PATH.
+ Return nonzero if a trailing slash was removed.
+ This is useful when using filename completion from a shell that
+ adds a "/" after directory names (such as tcsh and bash), because
+ the Unix rename and rmdir system calls return an "Invalid argument" error
+ when given a path that ends in "/" (except for the root directory). */
+
+int
+strip_trailing_slashes (char *path)
+{
+ char *base = base_name (path);
+ char *base_lim = base + base_len (base);
+ int had_slash = *base_lim;
+ *base_lim = '\0';
+ return had_slash;
+}
diff --git a/contrib/diff/lib/strncasecmp.c b/contrib/diff/lib/strncasecmp.c
new file mode 100644
index 0000000..68d95aa
--- /dev/null
+++ b/contrib/diff/lib/strncasecmp.c
@@ -0,0 +1,2 @@
+#define LENGTH_LIMIT
+#include "strcasecmp.c"
diff --git a/contrib/diff/lib/strtoimax.c b/contrib/diff/lib/strtoimax.c
new file mode 100644
index 0000000..4ce741c
--- /dev/null
+++ b/contrib/diff/lib/strtoimax.c
@@ -0,0 +1,80 @@
+/* Convert string representation of a number into an intmax_t value.
+ Copyright (C) 1999, 2001, 2002, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Paul Eggert. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#elif HAVE_STDINT_H
+# include <stdint.h>
+#endif
+
+#include <stdlib.h>
+
+/* Verify a requirement at compile-time (unlike assert, which is runtime). */
+#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; }
+
+#ifdef UNSIGNED
+# ifndef HAVE_DECL_STRTOULL
+"this configure-time declaration test was not run"
+# endif
+# if !HAVE_DECL_STRTOULL && HAVE_UNSIGNED_LONG_LONG
+unsigned long long strtoull (char const *, char **, int);
+# endif
+
+#else
+
+# ifndef HAVE_DECL_STRTOLL
+"this configure-time declaration test was not run"
+# endif
+# if !HAVE_DECL_STRTOLL && HAVE_UNSIGNED_LONG_LONG
+long long strtoll (char const *, char **, int);
+# endif
+#endif
+
+#ifdef UNSIGNED
+# undef HAVE_LONG_LONG
+# define HAVE_LONG_LONG HAVE_UNSIGNED_LONG_LONG
+# define INT uintmax_t
+# define strtoimax strtoumax
+# define strtol strtoul
+# define strtoll strtoull
+#else
+# define INT intmax_t
+#endif
+
+INT
+strtoimax (char const *ptr, char **endptr, int base)
+{
+#if HAVE_LONG_LONG
+ verify (size_is_that_of_long_or_long_long,
+ (sizeof (INT) == sizeof (long)
+ || sizeof (INT) == sizeof (long long)));
+
+ if (sizeof (INT) != sizeof (long))
+ return strtoll (ptr, endptr, base);
+#else
+ verify (size_is_that_of_long,
+ sizeof (INT) == sizeof (long));
+#endif
+
+ return strtol (ptr, endptr, base);
+}
diff --git a/contrib/diff/lib/strtol.c b/contrib/diff/lib/strtol.c
new file mode 100644
index 0000000..e2b1589
--- /dev/null
+++ b/contrib/diff/lib/strtol.c
@@ -0,0 +1,432 @@
+/* Convert string representation of a number into an integer value.
+
+ Copyright (C) 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2003
+ Free Software Foundation, Inc.
+
+ NOTE: The canonical source of this file is maintained with the GNU C
+ Library. Bugs can be reported to bug-glibc@gnu.org.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef _LIBC
+# define USE_NUMBER_GROUPING
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+#ifndef __set_errno
+# define __set_errno(Val) errno = (Val)
+#endif
+
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef USE_NUMBER_GROUPING
+# include "../locale/localeinfo.h"
+#endif
+
+/* Nonzero if we are defining `strtoul' or `strtoull', operating on
+ unsigned integers. */
+#ifndef UNSIGNED
+# define UNSIGNED 0
+# define INT LONG int
+#else
+# define INT unsigned LONG int
+#endif
+
+/* Determine the name. */
+#ifdef USE_IN_EXTENDED_LOCALE_MODEL
+# if UNSIGNED
+# ifdef USE_WIDE_CHAR
+# ifdef QUAD
+# define strtol __wcstoull_l
+# else
+# define strtol __wcstoul_l
+# endif
+# else
+# ifdef QUAD
+# define strtol __strtoull_l
+# else
+# define strtol __strtoul_l
+# endif
+# endif
+# else
+# ifdef USE_WIDE_CHAR
+# ifdef QUAD
+# define strtol __wcstoll_l
+# else
+# define strtol __wcstol_l
+# endif
+# else
+# ifdef QUAD
+# define strtol __strtoll_l
+# else
+# define strtol __strtol_l
+# endif
+# endif
+# endif
+#else
+# if UNSIGNED
+# ifdef USE_WIDE_CHAR
+# ifdef QUAD
+# define strtol wcstoull
+# else
+# define strtol wcstoul
+# endif
+# else
+# ifdef QUAD
+# define strtol strtoull
+# else
+# define strtol strtoul
+# endif
+# endif
+# else
+# ifdef USE_WIDE_CHAR
+# ifdef QUAD
+# define strtol wcstoll
+# else
+# define strtol wcstol
+# endif
+# else
+# ifdef QUAD
+# define strtol strtoll
+# endif
+# endif
+# endif
+#endif
+
+/* If QUAD is defined, we are defining `strtoll' or `strtoull',
+ operating on `long long int's. */
+#ifdef QUAD
+# define LONG long long
+# define STRTOL_LONG_MIN LONG_LONG_MIN
+# define STRTOL_LONG_MAX LONG_LONG_MAX
+# define STRTOL_ULONG_MAX ULONG_LONG_MAX
+
+/* The extra casts work around common compiler bugs,
+ e.g. Cray C 5.0.3.0 when t == time_t. */
+# ifndef TYPE_SIGNED
+# define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+# endif
+# ifndef TYPE_MINIMUM
+# define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \
+ ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) \
+ : (t) 0))
+# endif
+# ifndef TYPE_MAXIMUM
+# define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t)))
+# endif
+
+# ifndef ULONG_LONG_MAX
+# define ULONG_LONG_MAX TYPE_MAXIMUM (unsigned long long)
+# endif
+# ifndef LONG_LONG_MAX
+# define LONG_LONG_MAX TYPE_MAXIMUM (long long int)
+# endif
+# ifndef LONG_LONG_MIN
+# define LONG_LONG_MIN TYPE_MINIMUM (long long int)
+# endif
+
+# if __GNUC__ == 2 && __GNUC_MINOR__ < 7
+ /* Work around gcc bug with using this constant. */
+ static const unsigned long long int maxquad = ULONG_LONG_MAX;
+# undef STRTOL_ULONG_MAX
+# define STRTOL_ULONG_MAX maxquad
+# endif
+#else
+# define LONG long
+# define STRTOL_LONG_MIN LONG_MIN
+# define STRTOL_LONG_MAX LONG_MAX
+# define STRTOL_ULONG_MAX ULONG_MAX
+#endif
+
+
+/* We use this code also for the extended locale handling where the
+ function gets as an additional argument the locale which has to be
+ used. To access the values we have to redefine the _NL_CURRENT
+ macro. */
+#ifdef USE_IN_EXTENDED_LOCALE_MODEL
+# undef _NL_CURRENT
+# define _NL_CURRENT(category, item) \
+ (current->values[_NL_ITEM_INDEX (item)].string)
+# define LOCALE_PARAM , loc
+# define LOCALE_PARAM_PROTO , __locale_t loc
+#else
+# define LOCALE_PARAM
+# define LOCALE_PARAM_PROTO
+#endif
+
+#if defined _LIBC || defined HAVE_WCHAR_H
+# include <wchar.h>
+#endif
+
+#ifdef USE_WIDE_CHAR
+# include <wctype.h>
+# define L_(Ch) L##Ch
+# define UCHAR_TYPE wint_t
+# define STRING_TYPE wchar_t
+# ifdef USE_IN_EXTENDED_LOCALE_MODEL
+# define ISSPACE(Ch) __iswspace_l ((Ch), loc)
+# define ISALPHA(Ch) __iswalpha_l ((Ch), loc)
+# define TOUPPER(Ch) __towupper_l ((Ch), loc)
+# else
+# define ISSPACE(Ch) iswspace (Ch)
+# define ISALPHA(Ch) iswalpha (Ch)
+# define TOUPPER(Ch) towupper (Ch)
+# endif
+#else
+# if defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII)
+# define IN_CTYPE_DOMAIN(c) 1
+# else
+# define IN_CTYPE_DOMAIN(c) isascii(c)
+# endif
+# define L_(Ch) Ch
+# define UCHAR_TYPE unsigned char
+# define STRING_TYPE char
+# ifdef USE_IN_EXTENDED_LOCALE_MODEL
+# define ISSPACE(Ch) __isspace_l ((Ch), loc)
+# define ISALPHA(Ch) __isalpha_l ((Ch), loc)
+# define TOUPPER(Ch) __toupper_l ((Ch), loc)
+# else
+# define ISSPACE(Ch) (IN_CTYPE_DOMAIN (Ch) && isspace (Ch))
+# define ISALPHA(Ch) (IN_CTYPE_DOMAIN (Ch) && isalpha (Ch))
+# define TOUPPER(Ch) (IN_CTYPE_DOMAIN (Ch) ? toupper (Ch) : (Ch))
+# endif
+#endif
+
+#define INTERNAL(X) INTERNAL1(X)
+#define INTERNAL1(X) __##X##_internal
+#define WEAKNAME(X) WEAKNAME1(X)
+
+#ifdef USE_NUMBER_GROUPING
+/* This file defines a function to check for correct grouping. */
+# include "grouping.h"
+#endif
+
+
+
+/* Convert NPTR to an `unsigned long int' or `long int' in base BASE.
+ If BASE is 0 the base is determined by the presence of a leading
+ zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
+ If BASE is < 2 or > 36, it is reset to 10.
+ If ENDPTR is not NULL, a pointer to the character after the last
+ one converted is stored in *ENDPTR. */
+
+INT
+INTERNAL (strtol) (const STRING_TYPE *nptr, STRING_TYPE **endptr,
+ int base, int group LOCALE_PARAM_PROTO)
+{
+ int negative;
+ register unsigned LONG int cutoff;
+ register unsigned int cutlim;
+ register unsigned LONG int i;
+ register const STRING_TYPE *s;
+ register UCHAR_TYPE c;
+ const STRING_TYPE *save, *end;
+ int overflow;
+
+#ifdef USE_NUMBER_GROUPING
+# ifdef USE_IN_EXTENDED_LOCALE_MODEL
+ struct locale_data *current = loc->__locales[LC_NUMERIC];
+# endif
+ /* The thousands character of the current locale. */
+ wchar_t thousands = L'\0';
+ /* The numeric grouping specification of the current locale,
+ in the format described in <locale.h>. */
+ const char *grouping;
+
+ if (group)
+ {
+ grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
+ if (*grouping <= 0 || *grouping == CHAR_MAX)
+ grouping = NULL;
+ else
+ {
+ /* Figure out the thousands separator character. */
+# if defined _LIBC || defined _HAVE_BTOWC
+ thousands = __btowc (*_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP));
+ if (thousands == WEOF)
+ thousands = L'\0';
+# endif
+ if (thousands == L'\0')
+ grouping = NULL;
+ }
+ }
+ else
+ grouping = NULL;
+#endif
+
+ if (base < 0 || base == 1 || base > 36)
+ {
+ __set_errno (EINVAL);
+ return 0;
+ }
+
+ save = s = nptr;
+
+ /* Skip white space. */
+ while (ISSPACE (*s))
+ ++s;
+ if (*s == L_('\0'))
+ goto noconv;
+
+ /* Check for a sign. */
+ if (*s == L_('-'))
+ {
+ negative = 1;
+ ++s;
+ }
+ else if (*s == L_('+'))
+ {
+ negative = 0;
+ ++s;
+ }
+ else
+ negative = 0;
+
+ /* Recognize number prefix and if BASE is zero, figure it out ourselves. */
+ if (*s == L_('0'))
+ {
+ if ((base == 0 || base == 16) && TOUPPER (s[1]) == L_('X'))
+ {
+ s += 2;
+ base = 16;
+ }
+ else if (base == 0)
+ base = 8;
+ }
+ else if (base == 0)
+ base = 10;
+
+ /* Save the pointer so we can check later if anything happened. */
+ save = s;
+
+#ifdef USE_NUMBER_GROUPING
+ if (group)
+ {
+ /* Find the end of the digit string and check its grouping. */
+ end = s;
+ for (c = *end; c != L_('\0'); c = *++end)
+ if ((wchar_t) c != thousands
+ && ((wchar_t) c < L_('0') || (wchar_t) c > L_('9'))
+ && (!ISALPHA (c) || (int) (TOUPPER (c) - L_('A') + 10) >= base))
+ break;
+ if (*s == thousands)
+ end = s;
+ else
+ end = correctly_grouped_prefix (s, end, thousands, grouping);
+ }
+ else
+#endif
+ end = NULL;
+
+ cutoff = STRTOL_ULONG_MAX / (unsigned LONG int) base;
+ cutlim = STRTOL_ULONG_MAX % (unsigned LONG int) base;
+
+ overflow = 0;
+ i = 0;
+ for (c = *s; c != L_('\0'); c = *++s)
+ {
+ if (s == end)
+ break;
+ if (c >= L_('0') && c <= L_('9'))
+ c -= L_('0');
+ else if (ISALPHA (c))
+ c = TOUPPER (c) - L_('A') + 10;
+ else
+ break;
+ if ((int) c >= base)
+ break;
+ /* Check for overflow. */
+ if (i > cutoff || (i == cutoff && c > cutlim))
+ overflow = 1;
+ else
+ {
+ i *= (unsigned LONG int) base;
+ i += c;
+ }
+ }
+
+ /* Check if anything actually happened. */
+ if (s == save)
+ goto noconv;
+
+ /* Store in ENDPTR the address of one character
+ past the last character we converted. */
+ if (endptr != NULL)
+ *endptr = (STRING_TYPE *) s;
+
+#if !UNSIGNED
+ /* Check for a value that is within the range of
+ `unsigned LONG int', but outside the range of `LONG int'. */
+ if (overflow == 0
+ && i > (negative
+ ? -((unsigned LONG int) (STRTOL_LONG_MIN + 1)) + 1
+ : (unsigned LONG int) STRTOL_LONG_MAX))
+ overflow = 1;
+#endif
+
+ if (overflow)
+ {
+ __set_errno (ERANGE);
+#if UNSIGNED
+ return STRTOL_ULONG_MAX;
+#else
+ return negative ? STRTOL_LONG_MIN : STRTOL_LONG_MAX;
+#endif
+ }
+
+ /* Return the result of the appropriate sign. */
+ return negative ? -i : i;
+
+noconv:
+ /* We must handle a special case here: the base is 0 or 16 and the
+ first two characters are '0' and 'x', but the rest are no
+ hexadecimal digits. This is no error case. We return 0 and
+ ENDPTR points to the `x`. */
+ if (endptr != NULL)
+ {
+ if (save - nptr >= 2 && TOUPPER (save[-1]) == L_('X')
+ && save[-2] == L_('0'))
+ *endptr = (STRING_TYPE *) &save[-1];
+ else
+ /* There was no number to convert. */
+ *endptr = (STRING_TYPE *) nptr;
+ }
+
+ return 0L;
+}
+
+/* External user entry point. */
+
+
+INT
+#ifdef weak_function
+weak_function
+#endif
+strtol (const STRING_TYPE *nptr, STRING_TYPE **endptr,
+ int base LOCALE_PARAM_PROTO)
+{
+ return INTERNAL (strtol) (nptr, endptr, base, 0 LOCALE_PARAM);
+}
diff --git a/contrib/diff/lib/strtoll.c b/contrib/diff/lib/strtoll.c
new file mode 100644
index 0000000..8e9b261
--- /dev/null
+++ b/contrib/diff/lib/strtoll.c
@@ -0,0 +1,33 @@
+/* Function to parse a `long long int' from text.
+ Copyright (C) 1995, 1996, 1997, 1999, 2001 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define QUAD 1
+
+#include <strtol.c>
+
+#ifdef _LIBC
+# ifdef SHARED
+# include <shlib-compat.h>
+
+# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2)
+compat_symbol (libc, __strtoll_internal, __strtoq_internal, GLIBC_2_0);
+# endif
+
+# endif
+weak_alias (strtoll, strtoq)
+#endif
diff --git a/contrib/diff/lib/strtoul.c b/contrib/diff/lib/strtoul.c
new file mode 100644
index 0000000..bb62f9b
--- /dev/null
+++ b/contrib/diff/lib/strtoul.c
@@ -0,0 +1,20 @@
+/* Copyright (C) 1991, 1997 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define UNSIGNED 1
+
+#include "strtol.c"
diff --git a/contrib/diff/lib/strtoull.c b/contrib/diff/lib/strtoull.c
new file mode 100644
index 0000000..d6aa1f8
--- /dev/null
+++ b/contrib/diff/lib/strtoull.c
@@ -0,0 +1,27 @@
+/* Function to parse an `unsigned long long int' from text.
+ Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc.
+ NOTE: The canonical source of this file is maintained with the GNU C
+ Library. Bugs can be reported to bug-glibc@gnu.org.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define QUAD 1
+
+#include "strtoul.c"
+
+#ifdef _LIBC
+strong_alias (__strtoull_internal, __strtouq_internal)
+weak_alias (strtoull, strtouq)
+#endif
diff --git a/contrib/diff/lib/strtoumax.c b/contrib/diff/lib/strtoumax.c
new file mode 100644
index 0000000..dc395d6
--- /dev/null
+++ b/contrib/diff/lib/strtoumax.c
@@ -0,0 +1,2 @@
+#define UNSIGNED 1
+#include "strtoimax.c"
diff --git a/contrib/diff/lib/tempname.c b/contrib/diff/lib/tempname.c
new file mode 100644
index 0000000..b3d0874
--- /dev/null
+++ b/contrib/diff/lib/tempname.c
@@ -0,0 +1,344 @@
+/* tempname.c - generate the name of a temporary file.
+
+ Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ 2000, 2001, 2002, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <assert.h>
+
+#include <errno.h>
+#ifndef __set_errno
+# define __set_errno(Val) errno = (Val)
+#endif
+
+#include <stdio.h>
+#ifndef P_tmpdir
+# define P_tmpdir "/tmp"
+#endif
+#ifndef TMP_MAX
+# define TMP_MAX 238328
+#endif
+#ifndef __GT_FILE
+# define __GT_FILE 0
+# define __GT_BIGFILE 1
+# define __GT_DIR 2
+# define __GT_NOCREATE 3
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if HAVE_FCNTL_H || _LIBC
+# include <fcntl.h>
+#endif
+
+#if HAVE_SYS_TIME_H || _LIBC
+# include <sys/time.h>
+#endif
+
+#if HAVE_STDINT_H || _LIBC
+# include <stdint.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+
+#if HAVE_UNISTD_H || _LIBC
+# include <unistd.h>
+#endif
+
+#include <sys/stat.h>
+#if STAT_MACROS_BROKEN
+# undef S_ISDIR
+#endif
+#if !defined S_ISDIR && defined S_IFDIR
+# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
+#endif
+#if !S_IRUSR && S_IREAD
+# define S_IRUSR S_IREAD
+#endif
+#if !S_IRUSR
+# define S_IRUSR 00400
+#endif
+#if !S_IWUSR && S_IWRITE
+# define S_IWUSR S_IWRITE
+#endif
+#if !S_IWUSR
+# define S_IWUSR 00200
+#endif
+#if !S_IXUSR && S_IEXEC
+# define S_IXUSR S_IEXEC
+#endif
+#if !S_IXUSR
+# define S_IXUSR 00100
+#endif
+
+#if _LIBC
+# define struct_stat64 struct stat64
+#else
+# define struct_stat64 struct stat
+# define __getpid getpid
+# define __gettimeofday gettimeofday
+# define __mkdir mkdir
+# define __open open
+# define __open64 open
+# define __lxstat64(version, path, buf) lstat (path, buf)
+# define __xstat64(version, path, buf) stat (path, buf)
+#endif
+
+#if ! (HAVE___SECURE_GETENV || _LIBC)
+# define __secure_getenv getenv
+#endif
+
+#ifdef _LIBC
+# include <hp-timing.h>
+# if HP_TIMING_AVAIL
+# define RANDOM_BITS(Var) \
+ if (__builtin_expect (value == UINT64_C (0), 0)) \
+ { \
+ /* If this is the first time this function is used initialize \
+ the variable we accumulate the value in to some somewhat \
+ random value. If we'd not do this programs at startup time \
+ might have a reduced set of possible names, at least on slow \
+ machines. */ \
+ struct timeval tv; \
+ __gettimeofday (&tv, NULL); \
+ value = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; \
+ } \
+ HP_TIMING_NOW (Var)
+# endif
+#endif
+
+/* Use the widest available unsigned type if uint64_t is not
+ available. The algorithm below extracts a number less than 62**6
+ (approximately 2**35.725) from uint64_t, so ancient hosts where
+ uintmax_t is only 32 bits lose about 3.725 bits of randomness,
+ which is better than not having mkstemp at all. */
+#if !defined UINT64_MAX && !defined uint64_t
+# define uint64_t uintmax_t
+#endif
+
+/* Return nonzero if DIR is an existent directory. */
+static int
+direxists (const char *dir)
+{
+ struct_stat64 buf;
+ return __xstat64 (_STAT_VER, dir, &buf) == 0 && S_ISDIR (buf.st_mode);
+}
+
+/* Path search algorithm, for tmpnam, tmpfile, etc. If DIR is
+ non-null and exists, uses it; otherwise uses the first of $TMPDIR,
+ P_tmpdir, /tmp that exists. Copies into TMPL a template suitable
+ for use with mk[s]temp. Will fail (-1) if DIR is non-null and
+ doesn't exist, none of the searched dirs exists, or there's not
+ enough space in TMPL. */
+int
+__path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx,
+ int try_tmpdir)
+{
+ const char *d;
+ size_t dlen, plen;
+
+ if (!pfx || !pfx[0])
+ {
+ pfx = "file";
+ plen = 4;
+ }
+ else
+ {
+ plen = strlen (pfx);
+ if (plen > 5)
+ plen = 5;
+ }
+
+ if (try_tmpdir)
+ {
+ d = __secure_getenv ("TMPDIR");
+ if (d != NULL && direxists (d))
+ dir = d;
+ else if (dir != NULL && direxists (dir))
+ /* nothing */ ;
+ else
+ dir = NULL;
+ }
+ if (dir == NULL)
+ {
+ if (direxists (P_tmpdir))
+ dir = P_tmpdir;
+ else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp"))
+ dir = "/tmp";
+ else
+ {
+ __set_errno (ENOENT);
+ return -1;
+ }
+ }
+
+ dlen = strlen (dir);
+ while (dlen > 1 && dir[dlen - 1] == '/')
+ dlen--; /* remove trailing slashes */
+
+ /* check we have room for "${dir}/${pfx}XXXXXX\0" */
+ if (tmpl_len < dlen + 1 + plen + 6 + 1)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ sprintf (tmpl, "%.*s/%.*sXXXXXX", (int) dlen, dir, (int) plen, pfx);
+ return 0;
+}
+
+/* These are the characters used in temporary filenames. */
+static const char letters[] =
+"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+
+/* Generate a temporary file name based on TMPL. TMPL must match the
+ rules for mk[s]temp (i.e. end in "XXXXXX"). The name constructed
+ does not exist at the time of the call to __gen_tempname. TMPL is
+ overwritten with the result.
+
+ KIND may be one of:
+ __GT_NOCREATE: simply verify that the name does not exist
+ at the time of the call.
+ __GT_FILE: create the file using open(O_CREAT|O_EXCL)
+ and return a read-write fd. The file is mode 0600.
+ __GT_BIGFILE: same as __GT_FILE but use open64().
+ __GT_DIR: create a directory, which will be mode 0700.
+
+ We use a clever algorithm to get hard-to-predict names. */
+int
+__gen_tempname (char *tmpl, int kind)
+{
+ int len;
+ char *XXXXXX;
+ static uint64_t value;
+ uint64_t random_time_bits;
+ unsigned int count;
+ int fd = -1;
+ int save_errno = errno;
+ struct_stat64 st;
+
+ /* A lower bound on the number of temporary files to attempt to
+ generate. The maximum total number of temporary file names that
+ can exist for a given template is 62**6. It should never be
+ necessary to try all these combinations. Instead if a reasonable
+ number of names is tried (we define reasonable as 62**3) fail to
+ give the system administrator the chance to remove the problems. */
+ unsigned int attempts_min = 62 * 62 * 62;
+
+ /* The number of times to attempt to generate a temporary file. To
+ conform to POSIX, this must be no smaller than TMP_MAX. */
+ unsigned int attempts = attempts_min < TMP_MAX ? TMP_MAX : attempts_min;
+
+ len = strlen (tmpl);
+ if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ /* This is where the Xs start. */
+ XXXXXX = &tmpl[len - 6];
+
+ /* Get some more or less random data. */
+#ifdef RANDOM_BITS
+ RANDOM_BITS (random_time_bits);
+#else
+# if HAVE_GETTIMEOFDAY || _LIBC
+ {
+ struct timeval tv;
+ __gettimeofday (&tv, NULL);
+ random_time_bits = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec;
+ }
+# else
+ random_time_bits = time (NULL);
+# endif
+#endif
+ value += random_time_bits ^ __getpid ();
+
+ for (count = 0; count < attempts; value += 7777, ++count)
+ {
+ uint64_t v = value;
+
+ /* Fill in the random bits. */
+ XXXXXX[0] = letters[v % 62];
+ v /= 62;
+ XXXXXX[1] = letters[v % 62];
+ v /= 62;
+ XXXXXX[2] = letters[v % 62];
+ v /= 62;
+ XXXXXX[3] = letters[v % 62];
+ v /= 62;
+ XXXXXX[4] = letters[v % 62];
+ v /= 62;
+ XXXXXX[5] = letters[v % 62];
+
+ switch (kind)
+ {
+ case __GT_FILE:
+ fd = __open (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
+ break;
+
+ case __GT_BIGFILE:
+ fd = __open64 (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
+ break;
+
+ case __GT_DIR:
+ fd = __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR);
+ break;
+
+ case __GT_NOCREATE:
+ /* This case is backward from the other three. __gen_tempname
+ succeeds if __xstat fails because the name does not exist.
+ Note the continue to bypass the common logic at the bottom
+ of the loop. */
+ if (__lxstat64 (_STAT_VER, tmpl, &st) < 0)
+ {
+ if (errno == ENOENT)
+ {
+ __set_errno (save_errno);
+ return 0;
+ }
+ else
+ /* Give up now. */
+ return -1;
+ }
+ continue;
+
+ default:
+ assert (! "invalid KIND in __gen_tempname");
+ }
+
+ if (fd >= 0)
+ {
+ __set_errno (save_errno);
+ return fd;
+ }
+ else if (errno != EEXIST)
+ return -1;
+ }
+
+ /* We got out of the loop because we ran out of combinations to try. */
+ __set_errno (EEXIST);
+ return -1;
+}
diff --git a/contrib/diff/lib/time_r.c b/contrib/diff/lib/time_r.c
new file mode 100644
index 0000000..6c42504
--- /dev/null
+++ b/contrib/diff/lib/time_r.c
@@ -0,0 +1,69 @@
+/* Reentrant time functions like localtime_r.
+
+ Copyright (C) 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Paul Eggert. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "time_r.h"
+
+#include <string.h>
+
+static char *
+copy_string_result (char *dest, char const *src)
+{
+ if (! src)
+ return 0;
+ return strcpy (dest, src);
+}
+
+static struct tm *
+copy_tm_result (struct tm *dest, struct tm const *src)
+{
+ if (! src)
+ return 0;
+ *dest = *src;
+ return dest;
+}
+
+
+char *
+asctime_r (struct tm const * restrict tm, char * restrict buf)
+{
+ return copy_string_result (buf, asctime (tm));
+}
+
+char *
+ctime_r (time_t const *t, char *buf)
+{
+ return copy_string_result (buf, ctime (t));
+}
+
+struct tm *
+gmtime_r (time_t const * restrict t, struct tm * restrict tp)
+{
+ return copy_tm_result (tp, gmtime (t));
+}
+
+struct tm *
+localtime_r (time_t const * restrict t, struct tm * restrict tp)
+{
+ return copy_tm_result (tp, localtime (t));
+}
diff --git a/contrib/diff/lib/time_r.h b/contrib/diff/lib/time_r.h
new file mode 100644
index 0000000..fbd3375
--- /dev/null
+++ b/contrib/diff/lib/time_r.h
@@ -0,0 +1,46 @@
+/* Reentrant time functions like localtime_r.
+
+ Copyright (C) 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Paul Eggert. */
+
+#ifndef _TIME_R_H
+#define _TIME_R_H
+
+/* Include <time.h> first, since it may declare these functions with
+ signatures that disagree with POSIX, and we don't want to rename
+ those declarations. */
+#include <time.h>
+
+#if !HAVE_TIME_R_POSIX
+# undef asctime_r
+# undef ctime_r
+# undef gmtime_r
+# undef localtime_r
+
+# define asctime_r rpl_asctime_r
+# define ctime_r rpl_ctime_r
+# define gmtime_r rpl_gmtime_r
+# define localtime_r rpl_localtime_r
+
+char *asctime_r (struct tm const * restrict, char * restrict);
+char *ctime_r (time_t const *, char *);
+struct tm *gmtime_r (time_t const * restrict, struct tm * restrict);
+struct tm *localtime_r (time_t const * restrict, struct tm * restrict);
+#endif
+
+#endif
diff --git a/contrib/diff/lib/umaxtostr.c b/contrib/diff/lib/umaxtostr.c
new file mode 100644
index 0000000..4f49a7f
--- /dev/null
+++ b/contrib/diff/lib/umaxtostr.c
@@ -0,0 +1,3 @@
+#define inttostr umaxtostr
+#define inttype uintmax_t
+#include "inttostr.c"
diff --git a/contrib/diff/lib/unlocked-io.h b/contrib/diff/lib/unlocked-io.h
new file mode 100644
index 0000000..36a7a48
--- /dev/null
+++ b/contrib/diff/lib/unlocked-io.h
@@ -0,0 +1,132 @@
+/* Prefer faster, non-thread-safe stdio functions if available.
+
+ Copyright (C) 2001, 2002, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Jim Meyering. */
+
+#ifndef UNLOCKED_IO_H
+# define UNLOCKED_IO_H 1
+
+# ifndef USE_UNLOCKED_IO
+# define USE_UNLOCKED_IO 1
+# endif
+
+# if USE_UNLOCKED_IO
+
+/* These are wrappers for functions/macros from the GNU C library, and
+ from other C libraries supporting POSIX's optional thread-safe functions.
+
+ The standard I/O functions are thread-safe. These *_unlocked ones are
+ more efficient but not thread-safe. That they're not thread-safe is
+ fine since all of the applications in this package are single threaded.
+
+ Also, some code that is shared with the GNU C library may invoke
+ the *_unlocked functions directly. On hosts that lack those
+ functions, invoke the non-thread-safe versions instead. */
+
+# include <stdio.h>
+
+# if HAVE_DECL_CLEARERR_UNLOCKED
+# undef clearerr
+# define clearerr(x) clearerr_unlocked (x)
+# else
+# define clearerr_unlocked(x) clearerr (x)
+# endif
+# if HAVE_DECL_FEOF_UNLOCKED
+# undef feof
+# define feof(x) feof_unlocked (x)
+# else
+# define feof_unlocked(x) feof (x)
+# endif
+# if HAVE_DECL_FERROR_UNLOCKED
+# undef ferror
+# define ferror(x) ferror_unlocked (x)
+# else
+# define ferror_unlocked(x) ferror (x)
+# endif
+# if HAVE_DECL_FFLUSH_UNLOCKED
+# undef fflush
+# define fflush(x) fflush_unlocked (x)
+# else
+# define fflush_unlocked(x) fflush (x)
+# endif
+# if HAVE_DECL_FGETS_UNLOCKED
+# undef fgets
+# define fgets(x,y,z) fgets_unlocked (x,y,z)
+# else
+# define fgets_unlocked(x,y,z) fgets (x,y,z)
+# endif
+# if HAVE_DECL_FPUTC_UNLOCKED
+# undef fputc
+# define fputc(x,y) fputc_unlocked (x,y)
+# else
+# define fputc_unlocked(x,y) fputc (x,y)
+# endif
+# if HAVE_DECL_FPUTS_UNLOCKED
+# undef fputs
+# define fputs(x,y) fputs_unlocked (x,y)
+# else
+# define fputs_unlocked(x,y) fputs (x,y)
+# endif
+# if HAVE_DECL_FREAD_UNLOCKED
+# undef fread
+# define fread(w,x,y,z) fread_unlocked (w,x,y,z)
+# else
+# define fread_unlocked(w,x,y,z) fread (w,x,y,z)
+# endif
+# if HAVE_DECL_FWRITE_UNLOCKED
+# undef fwrite
+# define fwrite(w,x,y,z) fwrite_unlocked (w,x,y,z)
+# else
+# define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z)
+# endif
+# if HAVE_DECL_GETC_UNLOCKED
+# undef getc
+# define getc(x) getc_unlocked (x)
+# else
+# define getc_unlocked(x) getc (x)
+# endif
+# if HAVE_DECL_GETCHAR_UNLOCKED
+# undef getchar
+# define getchar() getchar_unlocked ()
+# else
+# define getchar_unlocked() getchar ()
+# endif
+# if HAVE_DECL_PUTC_UNLOCKED
+# undef putc
+# define putc(x,y) putc_unlocked (x,y)
+# else
+# define putc_unlocked(x,y) putc (x,y)
+# endif
+# if HAVE_DECL_PUTCHAR_UNLOCKED
+# undef putchar
+# define putchar(x) putchar_unlocked (x)
+# else
+# define putchar_unlocked(x) putchar (x)
+# endif
+
+# undef flockfile
+# define flockfile(x) ((void) 0)
+
+# undef ftrylockfile
+# define ftrylockfile(x) 0
+
+# undef funlockfile
+# define funlockfile(x) ((void) 0)
+
+# endif /* USE_UNLOCKED_IO */
+#endif /* UNLOCKED_IO_H */
diff --git a/contrib/diff/lib/version-etc.c b/contrib/diff/lib/version-etc.c
new file mode 100644
index 0000000..7523b08
--- /dev/null
+++ b/contrib/diff/lib/version-etc.c
@@ -0,0 +1,176 @@
+/* Utility to help print --version output in a consistent format.
+ Copyright (C) 1999-2004 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Jim Meyering. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Specification. */
+#include "version-etc.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "unlocked-io.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
+/* Default copyright goes to the FSF. */
+
+const char* version_etc_copyright =
+ /* Do *not* mark this string for translation. */
+ "Copyright (C) 2004 Free Software Foundation, Inc.";
+
+
+/* Like version_etc, below, but with the NULL-terminated author list
+ provided via a variable of type va_list. */
+void
+version_etc_va (FILE *stream,
+ const char *command_name, const char *package,
+ const char *version, va_list authors)
+{
+ unsigned int n_authors;
+
+ /* Count the number of authors. */
+ {
+ va_list tmp_authors;
+
+#ifdef __va_copy
+ __va_copy (tmp_authors, authors);
+#else
+ tmp_authors = authors;
+#endif
+
+ n_authors = 0;
+ while (va_arg (tmp_authors, const char *) != NULL)
+ ++n_authors;
+ }
+
+ if (command_name)
+ fprintf (stream, "%s (%s) %s\n", command_name, package, version);
+ else
+ fprintf (stream, "%s %s\n", package, version);
+
+ switch (n_authors)
+ {
+ case 0:
+ /* The caller must provide at least one author name. */
+ abort ();
+ case 1:
+ /* TRANSLATORS: %s denotes an author name. */
+ vfprintf (stream, _("Written by %s.\n"), authors);
+ break;
+ case 2:
+ /* TRANSLATORS: Each %s denotes an author name. */
+ vfprintf (stream, _("Written by %s and %s.\n"), authors);
+ break;
+ case 3:
+ /* TRANSLATORS: Each %s denotes an author name. */
+ vfprintf (stream, _("Written by %s, %s, and %s.\n"), authors);
+ break;
+ case 4:
+ /* TRANSLATORS: Each %s denotes an author name.
+ You can use line breaks, estimating that each author name occupies
+ ca. 16 screen columns and that a screen line has ca. 80 columns. */
+ vfprintf (stream, _("Written by %s, %s, %s,\nand %s.\n"), authors);
+ break;
+ case 5:
+ /* TRANSLATORS: Each %s denotes an author name.
+ You can use line breaks, estimating that each author name occupies
+ ca. 16 screen columns and that a screen line has ca. 80 columns. */
+ vfprintf (stream, _("Written by %s, %s, %s,\n%s, and %s.\n"), authors);
+ break;
+ case 6:
+ /* TRANSLATORS: Each %s denotes an author name.
+ You can use line breaks, estimating that each author name occupies
+ ca. 16 screen columns and that a screen line has ca. 80 columns. */
+ vfprintf (stream, _("Written by %s, %s, %s,\n%s, %s, and %s.\n"),
+ authors);
+ break;
+ case 7:
+ /* TRANSLATORS: Each %s denotes an author name.
+ You can use line breaks, estimating that each author name occupies
+ ca. 16 screen columns and that a screen line has ca. 80 columns. */
+ vfprintf (stream, _("Written by %s, %s, %s,\n%s, %s, %s, and %s.\n"),
+ authors);
+ break;
+ case 8:
+ /* TRANSLATORS: Each %s denotes an author name.
+ You can use line breaks, estimating that each author name occupies
+ ca. 16 screen columns and that a screen line has ca. 80 columns. */
+ vfprintf (stream, _("\
+Written by %s, %s, %s,\n%s, %s, %s, %s,\nand %s.\n"),
+ authors);
+ break;
+ case 9:
+ /* TRANSLATORS: Each %s denotes an author name.
+ You can use line breaks, estimating that each author name occupies
+ ca. 16 screen columns and that a screen line has ca. 80 columns. */
+ vfprintf (stream, _("\
+Written by %s, %s, %s,\n%s, %s, %s, %s,\n%s, and %s.\n"),
+ authors);
+ break;
+ default:
+ /* 10 or more authors. Use an abbreviation, since the human reader
+ will probably not want to read the entire list anyway. */
+ /* TRANSLATORS: Each %s denotes an author name.
+ You can use line breaks, estimating that each author name occupies
+ ca. 16 screen columns and that a screen line has ca. 80 columns. */
+ vfprintf (stream, _("\
+Written by %s, %s, %s,\n%s, %s, %s, %s,\n%s, %s, and others.\n"),
+ authors);
+ break;
+ }
+ va_end (authors);
+ putc ('\n', stream);
+
+ fputs (version_etc_copyright, stream);
+ putc ('\n', stream);
+
+ fputs (_("\
+This is free software; see the source for copying conditions. There is NO\n\
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"),
+ stream);
+}
+
+
+/* Display the --version information the standard way.
+
+ If COMMAND_NAME is NULL, the PACKAGE is asumed to be the name of
+ the program. The formats are therefore:
+
+ PACKAGE VERSION
+
+ or
+
+ COMMAND_NAME (PACKAGE) VERSION.
+
+ The author names are passed as separate arguments, with an additional
+ NULL argument at the end. */
+void
+version_etc (FILE *stream,
+ const char *command_name, const char *package,
+ const char *version, /* const char *author1, ...*/ ...)
+{
+ va_list authors;
+
+ va_start (authors, version);
+ version_etc_va (stream, command_name, package, version, authors);
+}
diff --git a/contrib/diff/lib/version-etc.h b/contrib/diff/lib/version-etc.h
new file mode 100644
index 0000000..d505e75
--- /dev/null
+++ b/contrib/diff/lib/version-etc.h
@@ -0,0 +1,37 @@
+/* Utility to help print --version output in a consistent format.
+ Copyright (C) 1999, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Jim Meyering. */
+
+#ifndef VERSION_ETC_H
+# define VERSION_ETC_H 1
+
+# include <stdarg.h>
+# include <stdio.h>
+
+extern const char *version_etc_copyright;
+
+extern void version_etc_va (FILE *stream,
+ const char *command_name, const char *package,
+ const char *version, va_list authors);
+
+extern void version_etc (FILE *stream,
+ const char *command_name, const char *package,
+ const char *version,
+ /* const char *author1, ...*/ ...);
+
+#endif /* VERSION_ETC_H */
diff --git a/contrib/diff/lib/waitpid.c b/contrib/diff/lib/waitpid.c
new file mode 100644
index 0000000..bc07898
--- /dev/null
+++ b/contrib/diff/lib/waitpid.c
@@ -0,0 +1,72 @@
+/* Emulate waitpid on systems that just have wait.
+ Copyright (C) 1994, 1995, 1998, 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 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; see the file COPYING.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+
+#define WAITPID_CHILDREN 8
+static pid_t waited_pid[WAITPID_CHILDREN];
+static int waited_status[WAITPID_CHILDREN];
+
+pid_t
+waitpid (pid_t pid, int *stat_loc, int options)
+{
+ int i;
+ pid_t p;
+
+ if (!options && (pid == -1 || 0 < pid))
+ {
+ /* If we have already waited for this child, return it immediately. */
+ for (i = 0; i < WAITPID_CHILDREN; i++)
+ {
+ p = waited_pid[i];
+ if (p && (p == pid || pid == -1))
+ {
+ waited_pid[i] = 0;
+ goto success;
+ }
+ }
+
+ /* The child has not returned yet; wait for it, accumulating status. */
+ for (i = 0; i < WAITPID_CHILDREN; i++)
+ if (! waited_pid[i])
+ {
+ p = wait (&waited_status[i]);
+ if (p < 0)
+ return p;
+ if (p == pid || pid == -1)
+ goto success;
+ waited_pid[i] = p;
+ }
+ }
+
+ /* We cannot emulate this wait call, e.g. because of too many children. */
+ errno = EINVAL;
+ return -1;
+
+success:
+ if (stat_loc)
+ *stat_loc = waited_status[i];
+ return p;
+}
diff --git a/contrib/diff/lib/xalloc.h b/contrib/diff/lib/xalloc.h
new file mode 100644
index 0000000..4b65858
--- /dev/null
+++ b/contrib/diff/lib/xalloc.h
@@ -0,0 +1,87 @@
+/* xalloc.h -- malloc with out-of-memory checking
+
+ Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+ 1999, 2000, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef XALLOC_H_
+# define XALLOC_H_
+
+# include <stddef.h>
+
+# ifndef __attribute__
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
+# define __attribute__(x)
+# endif
+# endif
+
+# ifndef ATTRIBUTE_NORETURN
+# define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
+# endif
+
+/* If this pointer is non-zero, run the specified function upon each
+ allocation failure. It is initialized to zero. */
+extern void (*xalloc_fail_func) (void);
+
+/* If XALLOC_FAIL_FUNC is undefined or a function that returns, this
+ message is output. It is translated via gettext.
+ Its value is "memory exhausted". */
+extern char const xalloc_msg_memory_exhausted[];
+
+/* This function is always triggered when memory is exhausted. It is
+ in charge of honoring the two previous items. It exits with status
+ exit_failure (defined in exitfail.h). This is the
+ function to call when one wants the program to die because of a
+ memory allocation failure. */
+extern void xalloc_die (void) ATTRIBUTE_NORETURN;
+
+void *xmalloc (size_t s);
+void *xnmalloc (size_t n, size_t s);
+void *xzalloc (size_t s);
+void *xcalloc (size_t n, size_t s);
+void *xrealloc (void *p, size_t s);
+void *xnrealloc (void *p, size_t n, size_t s);
+void *x2realloc (void *p, size_t *pn);
+void *x2nrealloc (void *p, size_t *pn, size_t s);
+void *xclone (void const *p, size_t s);
+char *xstrdup (const char *str);
+
+/* Return 1 if an array of N objects, each of size S, cannot exist due
+ to size arithmetic overflow. S must be positive and N must be
+ nonnegative. This is a macro, not an inline function, so that it
+ works correctly even when SIZE_MAX < N.
+
+ By gnulib convention, SIZE_MAX represents overflow in size
+ calculations, so the conservative dividend to use here is
+ SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value.
+ However, malloc (SIZE_MAX) fails on all known hosts where
+ sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for
+ exactly-SIZE_MAX allocations on such hosts; this avoids a test and
+ branch when S is known to be 1. */
+# define xalloc_oversized(n, s) \
+ ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n))
+
+/* These macros are deprecated; they will go away soon, and are retained
+ temporarily only to ease conversion to the functions described above. */
+# define CCLONE(p, n) xclone (p, (n) * sizeof *(p))
+# define CLONE(p) xclone (p, sizeof *(p))
+# define NEW(type, var) type *var = xmalloc (sizeof (type))
+# define XCALLOC(type, n) xcalloc (n, sizeof (type))
+# define XMALLOC(type, n) xnmalloc (n, sizeof (type))
+# define XREALLOC(p, type, n) xnrealloc (p, n, sizeof (type))
+# define XFREE(p) free (p)
+
+#endif /* !XALLOC_H_ */
diff --git a/contrib/diff/lib/xmalloc.c b/contrib/diff/lib/xmalloc.c
new file mode 100644
index 0000000..181006b
--- /dev/null
+++ b/contrib/diff/lib/xmalloc.c
@@ -0,0 +1,255 @@
+/* xmalloc.c -- malloc with out of memory checking
+
+ Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2003,
+ 1999, 2000, 2002, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "xalloc.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+#define N_(msgid) msgid
+
+#include "error.h"
+#include "exitfail.h"
+
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t) -1)
+#endif
+
+#ifndef HAVE_MALLOC
+"you must run the autoconf test for a GNU libc compatible malloc"
+#endif
+
+#ifndef HAVE_REALLOC
+"you must run the autoconf test for a GNU libc compatible realloc"
+#endif
+
+/* If non NULL, call this function when memory is exhausted. */
+void (*xalloc_fail_func) (void) = 0;
+
+/* If XALLOC_FAIL_FUNC is NULL, or does return, display this message
+ before exiting when memory is exhausted. Goes through gettext. */
+char const xalloc_msg_memory_exhausted[] = N_("memory exhausted");
+
+void
+xalloc_die (void)
+{
+ if (xalloc_fail_func)
+ (*xalloc_fail_func) ();
+ error (exit_failure, 0, "%s", _(xalloc_msg_memory_exhausted));
+ /* The `noreturn' cannot be given to error, since it may return if
+ its first argument is 0. To help compilers understand the
+ xalloc_die does terminate, call abort. */
+ abort ();
+}
+
+/* Allocate an array of N objects, each with S bytes of memory,
+ dynamically, with error checking. S must be nonzero. */
+
+static inline void *
+xnmalloc_inline (size_t n, size_t s)
+{
+ void *p;
+ if (xalloc_oversized (n, s) || ! (p = malloc (n * s)))
+ xalloc_die ();
+ return p;
+}
+
+void *
+xnmalloc (size_t n, size_t s)
+{
+ return xnmalloc_inline (n, s);
+}
+
+/* Allocate N bytes of memory dynamically, with error checking. */
+
+void *
+xmalloc (size_t n)
+{
+ return xnmalloc_inline (n, 1);
+}
+
+/* Change the size of an allocated block of memory P to an array of N
+ objects each of S bytes, with error checking. S must be nonzero. */
+
+static inline void *
+xnrealloc_inline (void *p, size_t n, size_t s)
+{
+ if (xalloc_oversized (n, s) || ! (p = realloc (p, n * s)))
+ xalloc_die ();
+ return p;
+}
+
+void *
+xnrealloc (void *p, size_t n, size_t s)
+{
+ return xnrealloc_inline (p, n, s);
+}
+
+/* Change the size of an allocated block of memory P to N bytes,
+ with error checking. */
+
+void *
+xrealloc (void *p, size_t n)
+{
+ return xnrealloc_inline (p, n, 1);
+}
+
+
+/* If P is null, allocate a block of at least *PN such objects;
+ otherwise, reallocate P so that it contains more than *PN objects
+ each of S bytes. *PN must be nonzero unless P is null, and S must
+ be nonzero. Set *PN to the new number of objects, and return the
+ pointer to the new block. *PN is never set to zero, and the
+ returned pointer is never null.
+
+ Repeated reallocations are guaranteed to make progress, either by
+ allocating an initial block with a nonzero size, or by allocating a
+ larger block.
+
+ In the following implementation, nonzero sizes are doubled so that
+ repeated reallocations have O(N log N) overall cost rather than
+ O(N**2) cost, but the specification for this function does not
+ guarantee that sizes are doubled.
+
+ Here is an example of use:
+
+ int *p = NULL;
+ size_t used = 0;
+ size_t allocated = 0;
+
+ void
+ append_int (int value)
+ {
+ if (used == allocated)
+ p = x2nrealloc (p, &allocated, sizeof *p);
+ p[used++] = value;
+ }
+
+ This causes x2nrealloc to allocate a block of some nonzero size the
+ first time it is called.
+
+ To have finer-grained control over the initial size, set *PN to a
+ nonzero value before calling this function with P == NULL. For
+ example:
+
+ int *p = NULL;
+ size_t used = 0;
+ size_t allocated = 0;
+ size_t allocated1 = 1000;
+
+ void
+ append_int (int value)
+ {
+ if (used == allocated)
+ {
+ p = x2nrealloc (p, &allocated1, sizeof *p);
+ allocated = allocated1;
+ }
+ p[used++] = value;
+ }
+
+ */
+
+static inline void *
+x2nrealloc_inline (void *p, size_t *pn, size_t s)
+{
+ size_t n = *pn;
+
+ if (! p)
+ {
+ if (! n)
+ {
+ /* The approximate size to use for initial small allocation
+ requests, when the invoking code specifies an old size of
+ zero. 64 bytes is the largest "small" request for the
+ GNU C library malloc. */
+ enum { DEFAULT_MXFAST = 64 };
+
+ n = DEFAULT_MXFAST / s;
+ n += !n;
+ }
+ }
+ else
+ {
+ if (SIZE_MAX / 2 / s < n)
+ xalloc_die ();
+ n *= 2;
+ }
+
+ *pn = n;
+ return xrealloc (p, n * s);
+}
+
+void *
+x2nrealloc (void *p, size_t *pn, size_t s)
+{
+ return x2nrealloc_inline (p, pn, s);
+}
+
+/* If P is null, allocate a block of at least *PN bytes; otherwise,
+ reallocate P so that it contains more than *PN bytes. *PN must be
+ nonzero unless P is null. Set *PN to the new block's size, and
+ return the pointer to the new block. *PN is never set to zero, and
+ the returned pointer is never null. */
+
+void *
+x2realloc (void *p, size_t *pn)
+{
+ return x2nrealloc_inline (p, pn, 1);
+}
+
+/* Allocate S bytes of zeroed memory dynamically, with error checking.
+ There's no need for xnzalloc (N, S), since it would be equivalent
+ to xcalloc (N, S). */
+
+void *
+xzalloc (size_t s)
+{
+ return memset (xmalloc (s), 0, s);
+}
+
+/* Allocate zeroed memory for N elements of S bytes, with error
+ checking. S must be nonzero. */
+
+void *
+xcalloc (size_t n, size_t s)
+{
+ void *p;
+ /* Test for overflow, since some calloc implementations don't have
+ proper overflow checks. */
+ if (xalloc_oversized (n, s) || ! (p = calloc (n, s)))
+ xalloc_die ();
+ return p;
+}
+
+/* Clone an object P of size S, with error checking. There's no need
+ for xnclone (P, N, S), since xclone (P, N * S) works without any
+ need for an arithmetic overflow check. */
+
+void *
+xclone (void const *p, size_t s)
+{
+ return memcpy (xmalloc (s), p, s);
+}
diff --git a/contrib/diff/lib/xstrdup.c b/contrib/diff/lib/xstrdup.c
new file mode 100644
index 0000000..58f18be
--- /dev/null
+++ b/contrib/diff/lib/xstrdup.c
@@ -0,0 +1,33 @@
+/* xstrdup.c -- copy a string with out of memory checking
+ Copyright (C) 1990, 1996, 1998, 2001, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Specification. */
+#include "xalloc.h"
+
+#include <string.h>
+
+/* Return a newly allocated copy of STRING. */
+
+char *
+xstrdup (const char *string)
+{
+ return xclone (string, strlen (string) + 1);
+}
diff --git a/contrib/diff/lib/xstrtol.c b/contrib/diff/lib/xstrtol.c
new file mode 100644
index 0000000..d0aa0a9
--- /dev/null
+++ b/contrib/diff/lib/xstrtol.c
@@ -0,0 +1,295 @@
+/* A more useful interface to strtol.
+
+ Copyright (C) 1995, 1996, 1998, 1999, 2000, 2001, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Jim Meyering. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifndef __strtol
+# define __strtol strtol
+# define __strtol_t long int
+# define __xstrtol xstrtol
+# define STRTOL_T_MINIMUM LONG_MIN
+# define STRTOL_T_MAXIMUM LONG_MAX
+#endif
+
+/* Some pre-ANSI implementations (e.g. SunOS 4)
+ need stderr defined if assertion checking is enabled. */
+#include <stdio.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+
+#include <limits.h>
+
+/* The extra casts work around common compiler bugs. */
+#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+#define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \
+ ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) \
+ : (t) 0))
+#define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t)))
+
+#ifndef STRTOL_T_MINIMUM
+# define STRTOL_T_MINIMUM TYPE_MINIMUM (__strtol_t)
+# define STRTOL_T_MAXIMUM TYPE_MAXIMUM (__strtol_t)
+#endif
+
+#if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
+# define IN_CTYPE_DOMAIN(c) 1
+#else
+# define IN_CTYPE_DOMAIN(c) isascii(c)
+#endif
+
+#define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c))
+
+#include "xstrtol.h"
+
+#if !HAVE_DECL_STRTOIMAX && !defined strtoimax
+intmax_t strtoimax ();
+#endif
+
+#if !HAVE_DECL_STRTOUMAX && !defined strtoumax
+uintmax_t strtoumax ();
+#endif
+
+static strtol_error
+bkm_scale (__strtol_t *x, int scale_factor)
+{
+ if (TYPE_SIGNED (__strtol_t) && *x < STRTOL_T_MINIMUM / scale_factor)
+ {
+ *x = STRTOL_T_MINIMUM;
+ return LONGINT_OVERFLOW;
+ }
+ if (STRTOL_T_MAXIMUM / scale_factor < *x)
+ {
+ *x = STRTOL_T_MAXIMUM;
+ return LONGINT_OVERFLOW;
+ }
+ *x *= scale_factor;
+ return LONGINT_OK;
+}
+
+static strtol_error
+bkm_scale_by_power (__strtol_t *x, int base, int power)
+{
+ strtol_error err = LONGINT_OK;
+ while (power--)
+ err |= bkm_scale (x, base);
+ return err;
+}
+
+/* FIXME: comment. */
+
+strtol_error
+__xstrtol (const char *s, char **ptr, int strtol_base,
+ __strtol_t *val, const char *valid_suffixes)
+{
+ char *t_ptr;
+ char **p;
+ __strtol_t tmp;
+ strtol_error err = LONGINT_OK;
+
+ assert (0 <= strtol_base && strtol_base <= 36);
+
+ p = (ptr ? ptr : &t_ptr);
+
+ if (! TYPE_SIGNED (__strtol_t))
+ {
+ const char *q = s;
+ while (ISSPACE ((unsigned char) *q))
+ ++q;
+ if (*q == '-')
+ return LONGINT_INVALID;
+ }
+
+ errno = 0;
+ tmp = __strtol (s, p, strtol_base);
+
+ if (*p == s)
+ {
+ /* If there is no number but there is a valid suffix, assume the
+ number is 1. The string is invalid otherwise. */
+ if (valid_suffixes && **p && strchr (valid_suffixes, **p))
+ tmp = 1;
+ else
+ return LONGINT_INVALID;
+ }
+ else if (errno != 0)
+ {
+ if (errno != ERANGE)
+ return LONGINT_INVALID;
+ err = LONGINT_OVERFLOW;
+ }
+
+ /* Let valid_suffixes == NULL mean `allow any suffix'. */
+ /* FIXME: update all callers except the ones that allow suffixes
+ after the number, changing last parameter NULL to `""'. */
+ if (!valid_suffixes)
+ {
+ *val = tmp;
+ return err;
+ }
+
+ if (**p != '\0')
+ {
+ int base = 1024;
+ int suffixes = 1;
+ strtol_error overflow;
+
+ if (!strchr (valid_suffixes, **p))
+ {
+ *val = tmp;
+ return err | LONGINT_INVALID_SUFFIX_CHAR;
+ }
+
+ if (strchr (valid_suffixes, '0'))
+ {
+ /* The ``valid suffix'' '0' is a special flag meaning that
+ an optional second suffix is allowed, which can change
+ the base. A suffix "B" (e.g. "100MB") stands for a power
+ of 1000, whereas a suffix "iB" (e.g. "100MiB") stands for
+ a power of 1024. If no suffix (e.g. "100M"), assume
+ power-of-1024. */
+
+ switch (p[0][1])
+ {
+ case 'i':
+ if (p[0][2] == 'B')
+ suffixes += 2;
+ break;
+
+ case 'B':
+ case 'D': /* 'D' is obsolescent */
+ base = 1000;
+ suffixes++;
+ break;
+ }
+ }
+
+ switch (**p)
+ {
+ case 'b':
+ overflow = bkm_scale (&tmp, 512);
+ break;
+
+ case 'B':
+ overflow = bkm_scale (&tmp, 1024);
+ break;
+
+ case 'c':
+ overflow = 0;
+ break;
+
+ case 'E': /* exa or exbi */
+ overflow = bkm_scale_by_power (&tmp, base, 6);
+ break;
+
+ case 'G': /* giga or gibi */
+ case 'g': /* 'g' is undocumented; for compatibility only */
+ overflow = bkm_scale_by_power (&tmp, base, 3);
+ break;
+
+ case 'k': /* kilo */
+ case 'K': /* kibi */
+ overflow = bkm_scale_by_power (&tmp, base, 1);
+ break;
+
+ case 'M': /* mega or mebi */
+ case 'm': /* 'm' is undocumented; for compatibility only */
+ overflow = bkm_scale_by_power (&tmp, base, 2);
+ break;
+
+ case 'P': /* peta or pebi */
+ overflow = bkm_scale_by_power (&tmp, base, 5);
+ break;
+
+ case 'T': /* tera or tebi */
+ case 't': /* 't' is undocumented; for compatibility only */
+ overflow = bkm_scale_by_power (&tmp, base, 4);
+ break;
+
+ case 'w':
+ overflow = bkm_scale (&tmp, 2);
+ break;
+
+ case 'Y': /* yotta or 2**80 */
+ overflow = bkm_scale_by_power (&tmp, base, 8);
+ break;
+
+ case 'Z': /* zetta or 2**70 */
+ overflow = bkm_scale_by_power (&tmp, base, 7);
+ break;
+
+ default:
+ *val = tmp;
+ return err | LONGINT_INVALID_SUFFIX_CHAR;
+ }
+
+ err |= overflow;
+ *p += suffixes;
+ if (**p)
+ err |= LONGINT_INVALID_SUFFIX_CHAR;
+ }
+
+ *val = tmp;
+ return err;
+}
+
+#ifdef TESTING_XSTRTO
+
+# include <stdio.h>
+# include "error.h"
+
+char *program_name;
+
+int
+main (int argc, char **argv)
+{
+ strtol_error s_err;
+ int i;
+
+ program_name = argv[0];
+ for (i=1; i<argc; i++)
+ {
+ char *p;
+ __strtol_t val;
+
+ s_err = __xstrtol (argv[i], &p, 0, &val, "bckmw");
+ if (s_err == LONGINT_OK)
+ {
+ printf ("%s->%lu (%s)\n", argv[i], val, p);
+ }
+ else
+ {
+ STRTOL_FATAL_ERROR (argv[i], "arg", s_err);
+ }
+ }
+ exit (0);
+}
+
+#endif /* TESTING_XSTRTO */
diff --git a/contrib/diff/lib/xstrtol.h b/contrib/diff/lib/xstrtol.h
new file mode 100644
index 0000000..5765c88
--- /dev/null
+++ b/contrib/diff/lib/xstrtol.h
@@ -0,0 +1,91 @@
+/* A more useful interface to strtol.
+
+ Copyright (C) 1995, 1996, 1998, 1999, 2001, 2002, 2003, 2004 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef XSTRTOL_H_
+# define XSTRTOL_H_ 1
+
+# include "exitfail.h"
+
+/* Get uintmax_t. */
+# if HAVE_INTTYPES_H
+# include <inttypes.h>
+# else
+# if HAVE_STDINT_H
+# include <stdint.h>
+# endif
+# endif
+
+# ifndef _STRTOL_ERROR
+enum strtol_error
+ {
+ LONGINT_OK = 0,
+
+ /* These two values can be ORed together, to indicate that both
+ errors occurred. */
+ LONGINT_OVERFLOW = 1,
+ LONGINT_INVALID_SUFFIX_CHAR = 2,
+
+ LONGINT_INVALID_SUFFIX_CHAR_WITH_OVERFLOW = (LONGINT_INVALID_SUFFIX_CHAR
+ | LONGINT_OVERFLOW),
+ LONGINT_INVALID = 4
+ };
+typedef enum strtol_error strtol_error;
+# endif
+
+# define _DECLARE_XSTRTOL(name, type) \
+ strtol_error name (const char *, char **, int, type *, const char *);
+_DECLARE_XSTRTOL (xstrtol, long int)
+_DECLARE_XSTRTOL (xstrtoul, unsigned long int)
+_DECLARE_XSTRTOL (xstrtoimax, intmax_t)
+_DECLARE_XSTRTOL (xstrtoumax, uintmax_t)
+
+# define _STRTOL_ERROR(Exit_code, Str, Argument_type_string, Err) \
+ do \
+ { \
+ switch ((Err)) \
+ { \
+ default: \
+ abort (); \
+ \
+ case LONGINT_INVALID: \
+ error ((Exit_code), 0, "invalid %s `%s'", \
+ (Argument_type_string), (Str)); \
+ break; \
+ \
+ case LONGINT_INVALID_SUFFIX_CHAR: \
+ case LONGINT_INVALID_SUFFIX_CHAR | LONGINT_OVERFLOW: \
+ error ((Exit_code), 0, "invalid character following %s in `%s'", \
+ (Argument_type_string), (Str)); \
+ break; \
+ \
+ case LONGINT_OVERFLOW: \
+ error ((Exit_code), 0, "%s `%s' too large", \
+ (Argument_type_string), (Str)); \
+ break; \
+ } \
+ } \
+ while (0)
+
+# define STRTOL_FATAL_ERROR(Str, Argument_type_string, Err) \
+ _STRTOL_ERROR (exit_failure, Str, Argument_type_string, Err)
+
+# define STRTOL_FAIL_WARN(Str, Argument_type_string, Err) \
+ _STRTOL_ERROR (0, Str, Argument_type_string, Err)
+
+#endif /* not XSTRTOL_H_ */
diff --git a/contrib/diff/lib/xstrtoul.c b/contrib/diff/lib/xstrtoul.c
new file mode 100644
index 0000000..285f7b9
--- /dev/null
+++ b/contrib/diff/lib/xstrtoul.c
@@ -0,0 +1,6 @@
+#define __strtol strtoul
+#define __strtol_t unsigned long int
+#define __xstrtol xstrtoul
+#define STRTOL_T_MINIMUM 0
+#define STRTOL_T_MAXIMUM ULONG_MAX
+#include "xstrtol.c"
diff --git a/contrib/diff/lib/xstrtoumax.c b/contrib/diff/lib/xstrtoumax.c
new file mode 100644
index 0000000..a8858bf
--- /dev/null
+++ b/contrib/diff/lib/xstrtoumax.c
@@ -0,0 +1,37 @@
+/* xstrtoumax.c -- A more useful interface to strtoumax.
+ Copyright (C) 1999, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Paul Eggert. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#elif HAVE_STDINT_H
+# include <stdint.h>
+#endif
+
+#define __strtol strtoumax
+#define __strtol_t uintmax_t
+#define __xstrtol xstrtoumax
+#ifdef UINTMAX_MAX
+# define STRTOL_T_MINIMUM 0
+# define STRTOL_T_MAXIMUM UINTMAX_MAX
+#endif
+#include "xstrtol.c"
diff --git a/contrib/diff/man/Makefile.am b/contrib/diff/man/Makefile.am
new file mode 100644
index 0000000..d3a1ee2
--- /dev/null
+++ b/contrib/diff/man/Makefile.am
@@ -0,0 +1,34 @@
+# Automakefile for GNU diffutils man pages
+
+# Copyright (C) 2002 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., 59 Temple Place - Suite 330, Boston, MA
+## 02111-1307, USA.
+
+dist_man_MANS = cmp.1 diff.1 diff3.1 sdiff.1
+MAINTAINERCLEANFILES = $(dist_man_MANS)
+
+S = $(top_srcdir)/src
+cmp.1: $S/cmp.c
+diff.1: $S/diff.c
+diff3.1: $S/diff3.c
+sdiff.1: $S/sdiff.c
+
+# Depend on configure.ac to get version number changes.
+$(dist_man_MANS): $(top_srcdir)/configure.ac
+ base=`expr $@ : '\(.*\).1'` && \
+ (echo '[NAME]' && sed 's@/\* *@@; s/-/\\-/; q' $S/$$base.c) | \
+ $(HELP2MAN) -i - -S '$(PACKAGE) $(VERSION)' ../src/$$base | \
+ sed 's/^\.B info .*/.B info diff/' >$@
diff --git a/contrib/diff/man/cmp.1 b/contrib/diff/man/cmp.1
new file mode 100644
index 0000000..ffc664e
--- /dev/null
+++ b/contrib/diff/man/cmp.1
@@ -0,0 +1,63 @@
+.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.33.
+.TH CMP "1" "April 2004" "diffutils 2.8.7" "User Commands"
+.SH NAME
+cmp \- compare two files byte by byte
+.SH SYNOPSIS
+.B cmp
+[\fIOPTION\fR]... \fIFILE1 \fR[\fIFILE2 \fR[\fISKIP1 \fR[\fISKIP2\fR]]]
+.SH DESCRIPTION
+Compare two files byte by byte.
+.TP
+\fB\-b\fR \fB\-\-print\-bytes\fR
+Print differing bytes.
+.TP
+\fB\-i\fR SKIP \fB\-\-ignore\-initial\fR=\fISKIP\fR
+Skip the first SKIP bytes of input.
+.HP
+\fB\-i\fR SKIP1:SKIP2 \fB\-\-ignore\-initial\fR=\fISKIP1\fR:SKIP2
+.IP
+Skip the first SKIP1 bytes of FILE1 and the first SKIP2 bytes of FILE2.
+.TP
+\fB\-l\fR \fB\-\-verbose\fR
+Output byte numbers and values of all differing bytes.
+.TP
+\fB\-n\fR LIMIT \fB\-\-bytes\fR=\fILIMIT\fR
+Compare at most LIMIT bytes.
+.TP
+\fB\-s\fR \fB\-\-quiet\fR \fB\-\-silent\fR
+Output nothing; yield exit status only.
+.TP
+\fB\-v\fR \fB\-\-version\fR
+Output version info.
+.TP
+\fB\-\-help\fR
+Output this help.
+.PP
+SKIP1 and SKIP2 are the number of bytes to skip in each file.
+SKIP values may be followed by the following multiplicative suffixes:
+kB 1000, K 1024, MB 1,000,000, M 1,048,576,
+GB 1,000,000,000, G 1,073,741,824, and so on for T, P, E, Z, Y.
+.PP
+If a FILE is `-' or missing, read standard input.
+Exit status is 0 if inputs are the same, 1 if different, 2 if trouble.
+.SH AUTHOR
+Written by Torbjorn Granlund and David MacKenzie.
+.SH "REPORTING BUGS"
+Report bugs to <bug-gnu-utils@gnu.org>.
+.SH COPYRIGHT
+Copyright \(co 2004 Free Software Foundation, Inc.
+.br
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+.SH "SEE ALSO"
+The full documentation for
+.B cmp
+is maintained as a Texinfo manual. If the
+.B info
+and
+.B cmp
+programs are properly installed at your site, the command
+.IP
+.B info diff
+.PP
+should give you access to the complete manual.
diff --git a/contrib/diff/man/diff.1 b/contrib/diff/man/diff.1
new file mode 100644
index 0000000..cef8e1a
--- /dev/null
+++ b/contrib/diff/man/diff.1
@@ -0,0 +1,227 @@
+.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.33.
+.TH DIFF "1" "April 2004" "diffutils 2.8.7" "User Commands"
+.SH NAME
+diff \- compare files line by line
+.SH SYNOPSIS
+.B diff
+[\fIOPTION\fR]... \fIFILES\fR
+.SH DESCRIPTION
+Compare files line by line.
+.TP
+\fB\-i\fR \fB\-\-ignore\-case\fR
+Ignore case differences in file contents.
+.TP
+\fB\-\-ignore\-file\-name\-case\fR
+Ignore case when comparing file names.
+.TP
+\fB\-\-no\-ignore\-file\-name\-case\fR
+Consider case when comparing file names.
+.TP
+\fB\-E\fR \fB\-\-ignore\-tab\-expansion\fR
+Ignore changes due to tab expansion.
+.TP
+\fB\-b\fR \fB\-\-ignore\-space\-change\fR
+Ignore changes in the amount of white space.
+.TP
+\fB\-w\fR \fB\-\-ignore\-all\-space\fR
+Ignore all white space.
+.TP
+\fB\-B\fR \fB\-\-ignore\-blank\-lines\fR
+Ignore changes whose lines are all blank.
+.TP
+\fB\-I\fR RE \fB\-\-ignore\-matching\-lines\fR=\fIRE\fR
+Ignore changes whose lines all match RE.
+.TP
+\fB\-\-strip\-trailing\-cr\fR
+Strip trailing carriage return on input.
+.TP
+\fB\-a\fR \fB\-\-text\fR
+Treat all files as text.
+.TP
+\fB\-c\fR \fB\-C\fR NUM \fB\-\-context\fR[=\fINUM\fR]
+Output NUM (default 3) lines of copied context.
+.TP
+\fB\-u\fR \fB\-U\fR NUM \fB\-\-unified\fR[=\fINUM\fR]
+Output NUM (default 3) lines of unified context.
+.TP
+\fB\-\-label\fR LABEL
+Use LABEL instead of file name.
+.TP
+\fB\-p\fR \fB\-\-show\-c\-function\fR
+Show which C function each change is in.
+.TP
+\fB\-F\fR RE \fB\-\-show\-function\-line\fR=\fIRE\fR
+Show the most recent line matching RE.
+.TP
+\fB\-q\fR \fB\-\-brief\fR
+Output only whether files differ.
+.TP
+\fB\-e\fR \fB\-\-ed\fR
+Output an ed script.
+.TP
+\fB\-\-normal\fR
+Output a normal diff.
+.TP
+\fB\-n\fR \fB\-\-rcs\fR
+Output an RCS format diff.
+.TP
+\fB\-y\fR \fB\-\-side\-by\-side\fR
+Output in two columns.
+.TP
+\fB\-W\fR NUM \fB\-\-width\fR=\fINUM\fR
+Output at most NUM (default 130) print columns.
+.TP
+\fB\-\-left\-column\fR
+Output only the left column of common lines.
+.TP
+\fB\-\-suppress\-common\-lines\fR
+Do not output common lines.
+.TP
+\fB\-D\fR NAME \fB\-\-ifdef\fR=\fINAME\fR
+Output merged file to show `#ifdef NAME' diffs.
+.TP
+\fB\-\-GTYPE\-group\-format\fR=\fIGFMT\fR
+Similar, but format GTYPE input groups with GFMT.
+.TP
+\fB\-\-line\-format\fR=\fILFMT\fR
+Similar, but format all input lines with LFMT.
+.TP
+\fB\-\-LTYPE\-line\-format\fR=\fILFMT\fR
+Similar, but format LTYPE input lines with LFMT.
+.TP
+LTYPE is `old', `new', or `unchanged'.
+GTYPE is LTYPE or `changed'.
+.IP
+GFMT may contain:
+.TP
+%<
+lines from FILE1
+.TP
+%>
+lines from FILE2
+.TP
+%=
+lines common to FILE1 and FILE2
+.TP
+%[-][WIDTH][.[PREC]]{doxX}LETTER
+printf-style spec for LETTER
+.IP
+LETTERs are as follows for new group, lower case for old group:
+.TP
+F
+first line number
+.TP
+L
+last line number
+.TP
+N
+number of lines = L-F+1
+.TP
+E
+F-1
+.TP
+M
+L+1
+.IP
+LFMT may contain:
+.TP
+%L
+contents of line
+.TP
+%l
+contents of line, excluding any trailing newline
+.TP
+%[-][WIDTH][.[PREC]]{doxX}n
+printf-style spec for input line number
+.IP
+Either GFMT or LFMT may contain:
+.TP
+%%
+%
+.TP
+%c'C'
+the single character C
+.TP
+%c'\eOOO'
+the character with octal code OOO
+.TP
+\fB\-l\fR \fB\-\-paginate\fR
+Pass the output through `pr' to paginate it.
+.TP
+\fB\-t\fR \fB\-\-expand\-tabs\fR
+Expand tabs to spaces in output.
+.TP
+\fB\-T\fR \fB\-\-initial\-tab\fR
+Make tabs line up by prepending a tab.
+.TP
+\fB\-\-tabsize\fR=\fINUM\fR
+Tab stops are every NUM (default 8) print columns.
+.TP
+\fB\-r\fR \fB\-\-recursive\fR
+Recursively compare any subdirectories found.
+.TP
+\fB\-N\fR \fB\-\-new\-file\fR
+Treat absent files as empty.
+.TP
+\fB\-\-unidirectional\-new\-file\fR
+Treat absent first files as empty.
+.TP
+\fB\-s\fR \fB\-\-report\-identical\-files\fR
+Report when two files are the same.
+.TP
+\fB\-x\fR PAT \fB\-\-exclude\fR=\fIPAT\fR
+Exclude files that match PAT.
+.TP
+\fB\-X\fR FILE \fB\-\-exclude\-from\fR=\fIFILE\fR
+Exclude files that match any pattern in FILE.
+.TP
+\fB\-S\fR FILE \fB\-\-starting\-file\fR=\fIFILE\fR
+Start with FILE when comparing directories.
+.TP
+\fB\-\-from\-file\fR=\fIFILE1\fR
+Compare FILE1 to all operands. FILE1 can be a directory.
+.TP
+\fB\-\-to\-file\fR=\fIFILE2\fR
+Compare all operands to FILE2. FILE2 can be a directory.
+.TP
+\fB\-\-horizon\-lines\fR=\fINUM\fR
+Keep NUM lines of the common prefix and suffix.
+.TP
+\fB\-d\fR \fB\-\-minimal\fR
+Try hard to find a smaller set of changes.
+.TP
+\fB\-\-speed\-large\-files\fR
+Assume large files and many scattered small changes.
+.TP
+\fB\-v\fR \fB\-\-version\fR
+Output version info.
+.TP
+\fB\-\-help\fR
+Output this help.
+.PP
+FILES are `FILE1 FILE2' or `DIR1 DIR2' or `DIR FILE...' or `FILE... DIR'.
+If \fB\-\-from\-file\fR or \fB\-\-to\-file\fR is given, there are no restrictions on FILES.
+If a FILE is `-', read standard input.
+Exit status is 0 if inputs are the same, 1 if different, 2 if trouble.
+.SH AUTHOR
+Written by Paul Eggert, Mike Haertel, David Hayes,
+Richard Stallman, and Len Tower.
+.SH "REPORTING BUGS"
+Report bugs to <bug-gnu-utils@gnu.org>.
+.SH COPYRIGHT
+Copyright \(co 2004 Free Software Foundation, Inc.
+.br
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+.SH "SEE ALSO"
+The full documentation for
+.B diff
+is maintained as a Texinfo manual. If the
+.B info
+and
+.B diff
+programs are properly installed at your site, the command
+.IP
+.B info diff
+.PP
+should give you access to the complete manual.
diff --git a/contrib/diff/man/diff3.1 b/contrib/diff/man/diff3.1
new file mode 100644
index 0000000..f7daee2
--- /dev/null
+++ b/contrib/diff/man/diff3.1
@@ -0,0 +1,78 @@
+.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.33.
+.TH DIFF3 "1" "April 2004" "diffutils 2.8.7" "User Commands"
+.SH NAME
+diff3 \- compare three files line by line
+.SH SYNOPSIS
+.B diff3
+[\fIOPTION\fR]... \fIMYFILE OLDFILE YOURFILE\fR
+.SH DESCRIPTION
+Compare three files line by line.
+.TP
+\fB\-e\fR \fB\-\-ed\fR
+Output unmerged changes from OLDFILE to YOURFILE into MYFILE.
+.TP
+\fB\-E\fR \fB\-\-show\-overlap\fR
+Output unmerged changes, bracketing conflicts.
+.TP
+\fB\-A\fR \fB\-\-show\-all\fR
+Output all changes, bracketing conflicts.
+.TP
+\fB\-x\fR \fB\-\-overlap\-only\fR
+Output overlapping changes.
+.TP
+\fB\-X\fR
+Output overlapping changes, bracketing them.
+.TP
+\fB\-3\fR \fB\-\-easy\-only\fR
+Output unmerged nonoverlapping changes.
+.TP
+\fB\-m\fR \fB\-\-merge\fR
+Output merged file instead of ed script (default \fB\-A\fR).
+.TP
+\fB\-L\fR LABEL \fB\-\-label\fR=\fILABEL\fR
+Use LABEL instead of file name.
+.TP
+\fB\-i\fR
+Append `w' and `q' commands to ed scripts.
+.TP
+\fB\-a\fR \fB\-\-text\fR
+Treat all files as text.
+.TP
+\fB\-\-strip\-trailing\-cr\fR
+Strip trailing carriage return on input.
+.TP
+\fB\-T\fR \fB\-\-initial\-tab\fR
+Make tabs line up by prepending a tab.
+.TP
+\fB\-\-diff\-program\fR=\fIPROGRAM\fR
+Use PROGRAM to compare files.
+.TP
+\fB\-v\fR \fB\-\-version\fR
+Output version info.
+.TP
+\fB\-\-help\fR
+Output this help.
+.PP
+If a FILE is `-', read standard input.
+Exit status is 0 if successful, 1 if conflicts, 2 if trouble.
+.SH AUTHOR
+Written by Randy Smith.
+.SH "REPORTING BUGS"
+Report bugs to <bug-gnu-utils@gnu.org>.
+.SH COPYRIGHT
+Copyright \(co 2004 Free Software Foundation, Inc.
+.br
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+.SH "SEE ALSO"
+The full documentation for
+.B diff3
+is maintained as a Texinfo manual. If the
+.B info
+and
+.B diff3
+programs are properly installed at your site, the command
+.IP
+.B info diff
+.PP
+should give you access to the complete manual.
diff --git a/contrib/diff/man/sdiff.1 b/contrib/diff/man/sdiff.1
new file mode 100644
index 0000000..ab64c7e
--- /dev/null
+++ b/contrib/diff/man/sdiff.1
@@ -0,0 +1,90 @@
+.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.33.
+.TH SDIFF "1" "April 2004" "diffutils 2.8.7" "User Commands"
+.SH NAME
+sdiff \- side-by-side merge of file differences
+.SH SYNOPSIS
+.B sdiff
+[\fIOPTION\fR]... \fIFILE1 FILE2\fR
+.SH DESCRIPTION
+Side-by-side merge of file differences.
+.TP
+\fB\-o\fR FILE \fB\-\-output\fR=\fIFILE\fR
+Operate interactively, sending output to FILE.
+.TP
+\fB\-i\fR \fB\-\-ignore\-case\fR
+Consider upper- and lower-case to be the same.
+.TP
+\fB\-E\fR \fB\-\-ignore\-tab\-expansion\fR
+Ignore changes due to tab expansion.
+.TP
+\fB\-b\fR \fB\-\-ignore\-space\-change\fR
+Ignore changes in the amount of white space.
+.TP
+\fB\-W\fR \fB\-\-ignore\-all\-space\fR
+Ignore all white space.
+.TP
+\fB\-B\fR \fB\-\-ignore\-blank\-lines\fR
+Ignore changes whose lines are all blank.
+.TP
+\fB\-I\fR RE \fB\-\-ignore\-matching\-lines\fR=\fIRE\fR
+Ignore changes whose lines all match RE.
+.TP
+\fB\-\-strip\-trailing\-cr\fR
+Strip trailing carriage return on input.
+.TP
+\fB\-a\fR \fB\-\-text\fR
+Treat all files as text.
+.TP
+\fB\-w\fR NUM \fB\-\-width\fR=\fINUM\fR
+Output at most NUM (default 130) print columns.
+.TP
+\fB\-l\fR \fB\-\-left\-column\fR
+Output only the left column of common lines.
+.TP
+\fB\-s\fR \fB\-\-suppress\-common\-lines\fR
+Do not output common lines.
+.TP
+\fB\-t\fR \fB\-\-expand\-tabs\fR
+Expand tabs to spaces in output.
+.TP
+\fB\-\-tabsize\fR=\fINUM\fR
+Tab stops are every NUM (default 8) print columns.
+.TP
+\fB\-d\fR \fB\-\-minimal\fR
+Try hard to find a smaller set of changes.
+.TP
+\fB\-H\fR \fB\-\-speed\-large\-files\fR
+Assume large files and many scattered small changes.
+.TP
+\fB\-\-diff\-program\fR=\fIPROGRAM\fR
+Use PROGRAM to compare files.
+.TP
+\fB\-v\fR \fB\-\-version\fR
+Output version info.
+.TP
+\fB\-\-help\fR
+Output this help.
+.PP
+If a FILE is `-', read standard input.
+Exit status is 0 if inputs are the same, 1 if different, 2 if trouble.
+.SH AUTHOR
+Written by Thomas Lord.
+.SH "REPORTING BUGS"
+Report bugs to <bug-gnu-utils@gnu.org>.
+.SH COPYRIGHT
+Copyright \(co 2004 Free Software Foundation, Inc.
+.br
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+.SH "SEE ALSO"
+The full documentation for
+.B sdiff
+is maintained as a Texinfo manual. If the
+.B info
+and
+.B sdiff
+programs are properly installed at your site, the command
+.IP
+.B info diff
+.PP
+should give you access to the complete manual.
diff --git a/contrib/diff/src/Makefile.am b/contrib/diff/src/Makefile.am
new file mode 100644
index 0000000..14ff6ec
--- /dev/null
+++ b/contrib/diff/src/Makefile.am
@@ -0,0 +1,44 @@
+# Automakefile for GNU diffutils programs.
+
+# Copyright (C) 2001, 2002 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., 59 Temple Place - Suite 330, Boston, MA
+## 02111-1307, USA.
+
+bin_PROGRAMS = cmp diff diff3 sdiff
+
+noinst_HEADERS = system.h
+
+localedir = $(datadir)/locale
+
+AM_CPPFLAGS = -I../lib -I$(top_srcdir)/lib
+
+LDADD = ../lib/libdiffutils.a @LIBINTL@
+diff_LDADD = $(LDADD) @LIB_CLOCK_GETTIME@
+
+cmp_SOURCES = cmp.c
+diff3_SOURCES = diff3.c
+sdiff_SOURCES = sdiff.c
+diff_SOURCES = \
+ analyze.c context.c diff.c diff.h dir.c ed.c ifdef.c io.c \
+ normal.c side.c util.c
+
+MOSTLYCLEANFILES = paths.h paths.ht
+
+cmp.$(OBJEXT) diff3.$(OBJEXT) diff.$(OBJEXT) sdiff.$(OBJEXT): paths.h
+paths.h:
+ (echo '#define DEFAULT_DIFF_PROGRAM "$(bindir)/'`echo diff|sed '$(transform)'`'"' && \
+ echo '#define LOCALEDIR "$(localedir)"') >$@t
+ mv $@t $@
diff --git a/contrib/diff/src/analyze.c b/contrib/diff/src/analyze.c
new file mode 100644
index 0000000..7d6750a
--- /dev/null
+++ b/contrib/diff/src/analyze.c
@@ -0,0 +1,1038 @@
+/* Analyze file differences for GNU DIFF.
+
+ Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1998, 2001, 2002,
+ 2004 Free Software Foundation, Inc.
+
+ This file is part of GNU DIFF.
+
+ GNU DIFF 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.
+
+ GNU DIFF is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* The basic algorithm is described in:
+ "An O(ND) Difference Algorithm and its Variations", Eugene Myers,
+ Algorithmica Vol. 1 No. 2, 1986, pp. 251-266;
+ see especially section 4.2, which describes the variation used below.
+ Unless the --minimal option is specified, this code uses the TOO_EXPENSIVE
+ heuristic, by Paul Eggert, to limit the cost to O(N**1.5 log N)
+ at the price of producing suboptimal output for large inputs with
+ many differences.
+
+ The basic algorithm was independently discovered as described in:
+ "Algorithms for Approximate String Matching", E. Ukkonen,
+ Information and Control Vol. 64, 1985, pp. 100-118. */
+
+#include "diff.h"
+#include <cmpbuf.h>
+#include <error.h>
+#include <file-type.h>
+#include <xalloc.h>
+
+static lin *xvec, *yvec; /* Vectors being compared. */
+static lin *fdiag; /* Vector, indexed by diagonal, containing
+ 1 + the X coordinate of the point furthest
+ along the given diagonal in the forward
+ search of the edit matrix. */
+static lin *bdiag; /* Vector, indexed by diagonal, containing
+ the X coordinate of the point furthest
+ along the given diagonal in the backward
+ search of the edit matrix. */
+static lin too_expensive; /* Edit scripts longer than this are too
+ expensive to compute. */
+
+#define SNAKE_LIMIT 20 /* Snakes bigger than this are considered `big'. */
+
+struct partition
+{
+ lin xmid, ymid; /* Midpoints of this partition. */
+ bool lo_minimal; /* Nonzero if low half will be analyzed minimally. */
+ bool hi_minimal; /* Likewise for high half. */
+};
+
+/* Find the midpoint of the shortest edit script for a specified
+ portion of the two files.
+
+ Scan from the beginnings of the files, and simultaneously from the ends,
+ doing a breadth-first search through the space of edit-sequence.
+ When the two searches meet, we have found the midpoint of the shortest
+ edit sequence.
+
+ If FIND_MINIMAL is nonzero, find the minimal edit script regardless
+ of expense. Otherwise, if the search is too expensive, use
+ heuristics to stop the search and report a suboptimal answer.
+
+ Set PART->(xmid,ymid) to the midpoint (XMID,YMID). The diagonal number
+ XMID - YMID equals the number of inserted lines minus the number
+ of deleted lines (counting only lines before the midpoint).
+
+ Set PART->lo_minimal to true iff the minimal edit script for the
+ left half of the partition is known; similarly for PART->hi_minimal.
+
+ This function assumes that the first lines of the specified portions
+ of the two files do not match, and likewise that the last lines do not
+ match. The caller must trim matching lines from the beginning and end
+ of the portions it is going to specify.
+
+ If we return the "wrong" partitions,
+ the worst this can do is cause suboptimal diff output.
+ It cannot cause incorrect diff output. */
+
+static void
+diag (lin xoff, lin xlim, lin yoff, lin ylim, bool find_minimal,
+ struct partition *part)
+{
+ lin *const fd = fdiag; /* Give the compiler a chance. */
+ lin *const bd = bdiag; /* Additional help for the compiler. */
+ lin const *const xv = xvec; /* Still more help for the compiler. */
+ lin const *const yv = yvec; /* And more and more . . . */
+ lin const dmin = xoff - ylim; /* Minimum valid diagonal. */
+ lin const dmax = xlim - yoff; /* Maximum valid diagonal. */
+ lin const fmid = xoff - yoff; /* Center diagonal of top-down search. */
+ lin const bmid = xlim - ylim; /* Center diagonal of bottom-up search. */
+ lin fmin = fmid, fmax = fmid; /* Limits of top-down search. */
+ lin bmin = bmid, bmax = bmid; /* Limits of bottom-up search. */
+ lin c; /* Cost. */
+ bool odd = (fmid - bmid) & 1; /* True if southeast corner is on an odd
+ diagonal with respect to the northwest. */
+
+ fd[fmid] = xoff;
+ bd[bmid] = xlim;
+
+ for (c = 1;; ++c)
+ {
+ lin d; /* Active diagonal. */
+ bool big_snake = false;
+
+ /* Extend the top-down search by an edit step in each diagonal. */
+ fmin > dmin ? fd[--fmin - 1] = -1 : ++fmin;
+ fmax < dmax ? fd[++fmax + 1] = -1 : --fmax;
+ for (d = fmax; d >= fmin; d -= 2)
+ {
+ lin x, y, oldx, tlo = fd[d - 1], thi = fd[d + 1];
+
+ if (tlo >= thi)
+ x = tlo + 1;
+ else
+ x = thi;
+ oldx = x;
+ y = x - d;
+ while (x < xlim && y < ylim && xv[x] == yv[y])
+ ++x, ++y;
+ if (x - oldx > SNAKE_LIMIT)
+ big_snake = true;
+ fd[d] = x;
+ if (odd && bmin <= d && d <= bmax && bd[d] <= x)
+ {
+ part->xmid = x;
+ part->ymid = y;
+ part->lo_minimal = part->hi_minimal = true;
+ return;
+ }
+ }
+
+ /* Similarly extend the bottom-up search. */
+ bmin > dmin ? bd[--bmin - 1] = LIN_MAX : ++bmin;
+ bmax < dmax ? bd[++bmax + 1] = LIN_MAX : --bmax;
+ for (d = bmax; d >= bmin; d -= 2)
+ {
+ lin x, y, oldx, tlo = bd[d - 1], thi = bd[d + 1];
+
+ if (tlo < thi)
+ x = tlo;
+ else
+ x = thi - 1;
+ oldx = x;
+ y = x - d;
+ while (x > xoff && y > yoff && xv[x - 1] == yv[y - 1])
+ --x, --y;
+ if (oldx - x > SNAKE_LIMIT)
+ big_snake = true;
+ bd[d] = x;
+ if (!odd && fmin <= d && d <= fmax && x <= fd[d])
+ {
+ part->xmid = x;
+ part->ymid = y;
+ part->lo_minimal = part->hi_minimal = true;
+ return;
+ }
+ }
+
+ if (find_minimal)
+ continue;
+
+ /* Heuristic: check occasionally for a diagonal that has made
+ lots of progress compared with the edit distance.
+ If we have any such, find the one that has made the most
+ progress and return it as if it had succeeded.
+
+ With this heuristic, for files with a constant small density
+ of changes, the algorithm is linear in the file size. */
+
+ if (200 < c && big_snake && speed_large_files)
+ {
+ lin best = 0;
+
+ for (d = fmax; d >= fmin; d -= 2)
+ {
+ lin dd = d - fmid;
+ lin x = fd[d];
+ lin y = x - d;
+ lin v = (x - xoff) * 2 - dd;
+ if (v > 12 * (c + (dd < 0 ? -dd : dd)))
+ {
+ if (v > best
+ && xoff + SNAKE_LIMIT <= x && x < xlim
+ && yoff + SNAKE_LIMIT <= y && y < ylim)
+ {
+ /* We have a good enough best diagonal;
+ now insist that it end with a significant snake. */
+ int k;
+
+ for (k = 1; xv[x - k] == yv[y - k]; k++)
+ if (k == SNAKE_LIMIT)
+ {
+ best = v;
+ part->xmid = x;
+ part->ymid = y;
+ break;
+ }
+ }
+ }
+ }
+ if (best > 0)
+ {
+ part->lo_minimal = true;
+ part->hi_minimal = false;
+ return;
+ }
+
+ best = 0;
+ for (d = bmax; d >= bmin; d -= 2)
+ {
+ lin dd = d - bmid;
+ lin x = bd[d];
+ lin y = x - d;
+ lin v = (xlim - x) * 2 + dd;
+ if (v > 12 * (c + (dd < 0 ? -dd : dd)))
+ {
+ if (v > best
+ && xoff < x && x <= xlim - SNAKE_LIMIT
+ && yoff < y && y <= ylim - SNAKE_LIMIT)
+ {
+ /* We have a good enough best diagonal;
+ now insist that it end with a significant snake. */
+ int k;
+
+ for (k = 0; xv[x + k] == yv[y + k]; k++)
+ if (k == SNAKE_LIMIT - 1)
+ {
+ best = v;
+ part->xmid = x;
+ part->ymid = y;
+ break;
+ }
+ }
+ }
+ }
+ if (best > 0)
+ {
+ part->lo_minimal = false;
+ part->hi_minimal = true;
+ return;
+ }
+ }
+
+ /* Heuristic: if we've gone well beyond the call of duty,
+ give up and report halfway between our best results so far. */
+ if (c >= too_expensive)
+ {
+ lin fxybest, fxbest;
+ lin bxybest, bxbest;
+
+ fxbest = bxbest = 0; /* Pacify `gcc -Wall'. */
+
+ /* Find forward diagonal that maximizes X + Y. */
+ fxybest = -1;
+ for (d = fmax; d >= fmin; d -= 2)
+ {
+ lin x = MIN (fd[d], xlim);
+ lin y = x - d;
+ if (ylim < y)
+ x = ylim + d, y = ylim;
+ if (fxybest < x + y)
+ {
+ fxybest = x + y;
+ fxbest = x;
+ }
+ }
+
+ /* Find backward diagonal that minimizes X + Y. */
+ bxybest = LIN_MAX;
+ for (d = bmax; d >= bmin; d -= 2)
+ {
+ lin x = MAX (xoff, bd[d]);
+ lin y = x - d;
+ if (y < yoff)
+ x = yoff + d, y = yoff;
+ if (x + y < bxybest)
+ {
+ bxybest = x + y;
+ bxbest = x;
+ }
+ }
+
+ /* Use the better of the two diagonals. */
+ if ((xlim + ylim) - bxybest < fxybest - (xoff + yoff))
+ {
+ part->xmid = fxbest;
+ part->ymid = fxybest - fxbest;
+ part->lo_minimal = true;
+ part->hi_minimal = false;
+ }
+ else
+ {
+ part->xmid = bxbest;
+ part->ymid = bxybest - bxbest;
+ part->lo_minimal = false;
+ part->hi_minimal = true;
+ }
+ return;
+ }
+ }
+}
+
+/* Compare in detail contiguous subsequences of the two files
+ which are known, as a whole, to match each other.
+
+ The results are recorded in the vectors files[N].changed, by
+ storing 1 in the element for each line that is an insertion or deletion.
+
+ The subsequence of file 0 is [XOFF, XLIM) and likewise for file 1.
+
+ Note that XLIM, YLIM are exclusive bounds.
+ All line numbers are origin-0 and discarded lines are not counted.
+
+ If FIND_MINIMAL, find a minimal difference no matter how
+ expensive it is. */
+
+static void
+compareseq (lin xoff, lin xlim, lin yoff, lin ylim, bool find_minimal)
+{
+ lin const *xv = xvec; /* Help the compiler. */
+ lin const *yv = yvec;
+
+ /* Slide down the bottom initial diagonal. */
+ while (xoff < xlim && yoff < ylim && xv[xoff] == yv[yoff])
+ ++xoff, ++yoff;
+ /* Slide up the top initial diagonal. */
+ while (xlim > xoff && ylim > yoff && xv[xlim - 1] == yv[ylim - 1])
+ --xlim, --ylim;
+
+ /* Handle simple cases. */
+ if (xoff == xlim)
+ while (yoff < ylim)
+ files[1].changed[files[1].realindexes[yoff++]] = 1;
+ else if (yoff == ylim)
+ while (xoff < xlim)
+ files[0].changed[files[0].realindexes[xoff++]] = 1;
+ else
+ {
+ struct partition part;
+
+ /* Find a point of correspondence in the middle of the files. */
+ diag (xoff, xlim, yoff, ylim, find_minimal, &part);
+
+ /* Use the partitions to split this problem into subproblems. */
+ compareseq (xoff, part.xmid, yoff, part.ymid, part.lo_minimal);
+ compareseq (part.xmid, xlim, part.ymid, ylim, part.hi_minimal);
+ }
+}
+
+/* Discard lines from one file that have no matches in the other file.
+
+ A line which is discarded will not be considered by the actual
+ comparison algorithm; it will be as if that line were not in the file.
+ The file's `realindexes' table maps virtual line numbers
+ (which don't count the discarded lines) into real line numbers;
+ this is how the actual comparison algorithm produces results
+ that are comprehensible when the discarded lines are counted.
+
+ When we discard a line, we also mark it as a deletion or insertion
+ so that it will be printed in the output. */
+
+static void
+discard_confusing_lines (struct file_data filevec[])
+{
+ int f;
+ lin i;
+ char *discarded[2];
+ lin *equiv_count[2];
+ lin *p;
+
+ /* Allocate our results. */
+ p = xmalloc ((filevec[0].buffered_lines + filevec[1].buffered_lines)
+ * (2 * sizeof *p));
+ for (f = 0; f < 2; f++)
+ {
+ filevec[f].undiscarded = p; p += filevec[f].buffered_lines;
+ filevec[f].realindexes = p; p += filevec[f].buffered_lines;
+ }
+
+ /* Set up equiv_count[F][I] as the number of lines in file F
+ that fall in equivalence class I. */
+
+ p = zalloc (filevec[0].equiv_max * (2 * sizeof *p));
+ equiv_count[0] = p;
+ equiv_count[1] = p + filevec[0].equiv_max;
+
+ for (i = 0; i < filevec[0].buffered_lines; ++i)
+ ++equiv_count[0][filevec[0].equivs[i]];
+ for (i = 0; i < filevec[1].buffered_lines; ++i)
+ ++equiv_count[1][filevec[1].equivs[i]];
+
+ /* Set up tables of which lines are going to be discarded. */
+
+ discarded[0] = zalloc (filevec[0].buffered_lines
+ + filevec[1].buffered_lines);
+ discarded[1] = discarded[0] + filevec[0].buffered_lines;
+
+ /* Mark to be discarded each line that matches no line of the other file.
+ If a line matches many lines, mark it as provisionally discardable. */
+
+ for (f = 0; f < 2; f++)
+ {
+ size_t end = filevec[f].buffered_lines;
+ char *discards = discarded[f];
+ lin *counts = equiv_count[1 - f];
+ lin *equivs = filevec[f].equivs;
+ size_t many = 5;
+ size_t tem = end / 64;
+
+ /* Multiply MANY by approximate square root of number of lines.
+ That is the threshold for provisionally discardable lines. */
+ while ((tem = tem >> 2) > 0)
+ many *= 2;
+
+ for (i = 0; i < end; i++)
+ {
+ lin nmatch;
+ if (equivs[i] == 0)
+ continue;
+ nmatch = counts[equivs[i]];
+ if (nmatch == 0)
+ discards[i] = 1;
+ else if (nmatch > many)
+ discards[i] = 2;
+ }
+ }
+
+ /* Don't really discard the provisional lines except when they occur
+ in a run of discardables, with nonprovisionals at the beginning
+ and end. */
+
+ for (f = 0; f < 2; f++)
+ {
+ lin end = filevec[f].buffered_lines;
+ register char *discards = discarded[f];
+
+ for (i = 0; i < end; i++)
+ {
+ /* Cancel provisional discards not in middle of run of discards. */
+ if (discards[i] == 2)
+ discards[i] = 0;
+ else if (discards[i] != 0)
+ {
+ /* We have found a nonprovisional discard. */
+ register lin j;
+ lin length;
+ lin provisional = 0;
+
+ /* Find end of this run of discardable lines.
+ Count how many are provisionally discardable. */
+ for (j = i; j < end; j++)
+ {
+ if (discards[j] == 0)
+ break;
+ if (discards[j] == 2)
+ ++provisional;
+ }
+
+ /* Cancel provisional discards at end, and shrink the run. */
+ while (j > i && discards[j - 1] == 2)
+ discards[--j] = 0, --provisional;
+
+ /* Now we have the length of a run of discardable lines
+ whose first and last are not provisional. */
+ length = j - i;
+
+ /* If 1/4 of the lines in the run are provisional,
+ cancel discarding of all provisional lines in the run. */
+ if (provisional * 4 > length)
+ {
+ while (j > i)
+ if (discards[--j] == 2)
+ discards[j] = 0;
+ }
+ else
+ {
+ register lin consec;
+ lin minimum = 1;
+ lin tem = length >> 2;
+
+ /* MINIMUM is approximate square root of LENGTH/4.
+ A subrun of two or more provisionals can stand
+ when LENGTH is at least 16.
+ A subrun of 4 or more can stand when LENGTH >= 64. */
+ while (0 < (tem >>= 2))
+ minimum <<= 1;
+ minimum++;
+
+ /* Cancel any subrun of MINIMUM or more provisionals
+ within the larger run. */
+ for (j = 0, consec = 0; j < length; j++)
+ if (discards[i + j] != 2)
+ consec = 0;
+ else if (minimum == ++consec)
+ /* Back up to start of subrun, to cancel it all. */
+ j -= consec;
+ else if (minimum < consec)
+ discards[i + j] = 0;
+
+ /* Scan from beginning of run
+ until we find 3 or more nonprovisionals in a row
+ or until the first nonprovisional at least 8 lines in.
+ Until that point, cancel any provisionals. */
+ for (j = 0, consec = 0; j < length; j++)
+ {
+ if (j >= 8 && discards[i + j] == 1)
+ break;
+ if (discards[i + j] == 2)
+ consec = 0, discards[i + j] = 0;
+ else if (discards[i + j] == 0)
+ consec = 0;
+ else
+ consec++;
+ if (consec == 3)
+ break;
+ }
+
+ /* I advances to the last line of the run. */
+ i += length - 1;
+
+ /* Same thing, from end. */
+ for (j = 0, consec = 0; j < length; j++)
+ {
+ if (j >= 8 && discards[i - j] == 1)
+ break;
+ if (discards[i - j] == 2)
+ consec = 0, discards[i - j] = 0;
+ else if (discards[i - j] == 0)
+ consec = 0;
+ else
+ consec++;
+ if (consec == 3)
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ /* Actually discard the lines. */
+ for (f = 0; f < 2; f++)
+ {
+ char *discards = discarded[f];
+ lin end = filevec[f].buffered_lines;
+ lin j = 0;
+ for (i = 0; i < end; ++i)
+ if (minimal || discards[i] == 0)
+ {
+ filevec[f].undiscarded[j] = filevec[f].equivs[i];
+ filevec[f].realindexes[j++] = i;
+ }
+ else
+ filevec[f].changed[i] = 1;
+ filevec[f].nondiscarded_lines = j;
+ }
+
+ free (discarded[0]);
+ free (equiv_count[0]);
+}
+
+/* Adjust inserts/deletes of identical lines to join changes
+ as much as possible.
+
+ We do something when a run of changed lines include a
+ line at one end and have an excluded, identical line at the other.
+ We are free to choose which identical line is included.
+ `compareseq' usually chooses the one at the beginning,
+ but usually it is cleaner to consider the following identical line
+ to be the "change". */
+
+static void
+shift_boundaries (struct file_data filevec[])
+{
+ int f;
+
+ for (f = 0; f < 2; f++)
+ {
+ char *changed = filevec[f].changed;
+ char *other_changed = filevec[1 - f].changed;
+ lin const *equivs = filevec[f].equivs;
+ lin i = 0;
+ lin j = 0;
+ lin i_end = filevec[f].buffered_lines;
+
+ while (1)
+ {
+ lin runlength, start, corresponding;
+
+ /* Scan forwards to find beginning of another run of changes.
+ Also keep track of the corresponding point in the other file. */
+
+ while (i < i_end && !changed[i])
+ {
+ while (other_changed[j++])
+ continue;
+ i++;
+ }
+
+ if (i == i_end)
+ break;
+
+ start = i;
+
+ /* Find the end of this run of changes. */
+
+ while (changed[++i])
+ continue;
+ while (other_changed[j])
+ j++;
+
+ do
+ {
+ /* Record the length of this run of changes, so that
+ we can later determine whether the run has grown. */
+ runlength = i - start;
+
+ /* Move the changed region back, so long as the
+ previous unchanged line matches the last changed one.
+ This merges with previous changed regions. */
+
+ while (start && equivs[start - 1] == equivs[i - 1])
+ {
+ changed[--start] = 1;
+ changed[--i] = 0;
+ while (changed[start - 1])
+ start--;
+ while (other_changed[--j])
+ continue;
+ }
+
+ /* Set CORRESPONDING to the end of the changed run, at the last
+ point where it corresponds to a changed run in the other file.
+ CORRESPONDING == I_END means no such point has been found. */
+ corresponding = other_changed[j - 1] ? i : i_end;
+
+ /* Move the changed region forward, so long as the
+ first changed line matches the following unchanged one.
+ This merges with following changed regions.
+ Do this second, so that if there are no merges,
+ the changed region is moved forward as far as possible. */
+
+ while (i != i_end && equivs[start] == equivs[i])
+ {
+ changed[start++] = 0;
+ changed[i++] = 1;
+ while (changed[i])
+ i++;
+ while (other_changed[++j])
+ corresponding = i;
+ }
+ }
+ while (runlength != i - start);
+
+ /* If possible, move the fully-merged run of changes
+ back to a corresponding run in the other file. */
+
+ while (corresponding < i)
+ {
+ changed[--start] = 1;
+ changed[--i] = 0;
+ while (other_changed[--j])
+ continue;
+ }
+ }
+ }
+}
+
+/* Cons an additional entry onto the front of an edit script OLD.
+ LINE0 and LINE1 are the first affected lines in the two files (origin 0).
+ DELETED is the number of lines deleted here from file 0.
+ INSERTED is the number of lines inserted here in file 1.
+
+ If DELETED is 0 then LINE0 is the number of the line before
+ which the insertion was done; vice versa for INSERTED and LINE1. */
+
+static struct change *
+add_change (lin line0, lin line1, lin deleted, lin inserted,
+ struct change *old)
+{
+ struct change *new = xmalloc (sizeof *new);
+
+ new->line0 = line0;
+ new->line1 = line1;
+ new->inserted = inserted;
+ new->deleted = deleted;
+ new->link = old;
+ return new;
+}
+
+/* Scan the tables of which lines are inserted and deleted,
+ producing an edit script in reverse order. */
+
+static struct change *
+build_reverse_script (struct file_data const filevec[])
+{
+ struct change *script = 0;
+ char *changed0 = filevec[0].changed;
+ char *changed1 = filevec[1].changed;
+ lin len0 = filevec[0].buffered_lines;
+ lin len1 = filevec[1].buffered_lines;
+
+ /* Note that changedN[len0] does exist, and is 0. */
+
+ lin i0 = 0, i1 = 0;
+
+ while (i0 < len0 || i1 < len1)
+ {
+ if (changed0[i0] | changed1[i1])
+ {
+ lin line0 = i0, line1 = i1;
+
+ /* Find # lines changed here in each file. */
+ while (changed0[i0]) ++i0;
+ while (changed1[i1]) ++i1;
+
+ /* Record this change. */
+ script = add_change (line0, line1, i0 - line0, i1 - line1, script);
+ }
+
+ /* We have reached lines in the two files that match each other. */
+ i0++, i1++;
+ }
+
+ return script;
+}
+
+/* Scan the tables of which lines are inserted and deleted,
+ producing an edit script in forward order. */
+
+static struct change *
+build_script (struct file_data const filevec[])
+{
+ struct change *script = 0;
+ char *changed0 = filevec[0].changed;
+ char *changed1 = filevec[1].changed;
+ lin i0 = filevec[0].buffered_lines, i1 = filevec[1].buffered_lines;
+
+ /* Note that changedN[-1] does exist, and is 0. */
+
+ while (i0 >= 0 || i1 >= 0)
+ {
+ if (changed0[i0 - 1] | changed1[i1 - 1])
+ {
+ lin line0 = i0, line1 = i1;
+
+ /* Find # lines changed here in each file. */
+ while (changed0[i0 - 1]) --i0;
+ while (changed1[i1 - 1]) --i1;
+
+ /* Record this change. */
+ script = add_change (i0, i1, line0 - i0, line1 - i1, script);
+ }
+
+ /* We have reached lines in the two files that match each other. */
+ i0--, i1--;
+ }
+
+ return script;
+}
+
+/* If CHANGES, briefly report that two files differed.
+ Return 2 if trouble, CHANGES otherwise. */
+static int
+briefly_report (int changes, struct file_data const filevec[])
+{
+ if (changes)
+ {
+ char const *label0 = file_label[0] ? file_label[0] : filevec[0].name;
+ char const *label1 = file_label[1] ? file_label[1] : filevec[1].name;
+ message ("Files %s and %s differ\n", label0, label1);
+ if (! brief)
+ changes = 2;
+ }
+
+ return changes;
+}
+
+/* Report the differences of two files. */
+int
+diff_2_files (struct comparison *cmp)
+{
+ lin diags;
+ int f;
+ struct change *e, *p;
+ struct change *script;
+ int changes;
+
+
+ /* If we have detected that either file is binary,
+ compare the two files as binary. This can happen
+ only when the first chunk is read.
+ Also, --brief without any --ignore-* options means
+ we can speed things up by treating the files as binary. */
+
+ if (read_files (cmp->file, files_can_be_treated_as_binary))
+ {
+ /* Files with different lengths must be different. */
+ if (cmp->file[0].stat.st_size != cmp->file[1].stat.st_size
+ && (cmp->file[0].desc < 0 || S_ISREG (cmp->file[0].stat.st_mode))
+ && (cmp->file[1].desc < 0 || S_ISREG (cmp->file[1].stat.st_mode)))
+ changes = 1;
+
+ /* Standard input equals itself. */
+ else if (cmp->file[0].desc == cmp->file[1].desc)
+ changes = 0;
+
+ else
+ /* Scan both files, a buffer at a time, looking for a difference. */
+ {
+ /* Allocate same-sized buffers for both files. */
+ size_t lcm_max = PTRDIFF_MAX - 1;
+ size_t buffer_size =
+ buffer_lcm (sizeof (word),
+ buffer_lcm (STAT_BLOCKSIZE (cmp->file[0].stat),
+ STAT_BLOCKSIZE (cmp->file[1].stat),
+ lcm_max),
+ lcm_max);
+ for (f = 0; f < 2; f++)
+ cmp->file[f].buffer = xrealloc (cmp->file[f].buffer, buffer_size);
+
+ for (;; cmp->file[0].buffered = cmp->file[1].buffered = 0)
+ {
+ /* Read a buffer's worth from both files. */
+ for (f = 0; f < 2; f++)
+ if (0 <= cmp->file[f].desc)
+ file_block_read (&cmp->file[f],
+ buffer_size - cmp->file[f].buffered);
+
+ /* If the buffers differ, the files differ. */
+ if (cmp->file[0].buffered != cmp->file[1].buffered
+ || memcmp (cmp->file[0].buffer,
+ cmp->file[1].buffer,
+ cmp->file[0].buffered))
+ {
+ changes = 1;
+ break;
+ }
+
+ /* If we reach end of file, the files are the same. */
+ if (cmp->file[0].buffered != buffer_size)
+ {
+ changes = 0;
+ break;
+ }
+ }
+ }
+
+ changes = briefly_report (changes, cmp->file);
+ }
+ else
+ {
+ /* Allocate vectors for the results of comparison:
+ a flag for each line of each file, saying whether that line
+ is an insertion or deletion.
+ Allocate an extra element, always 0, at each end of each vector. */
+
+ size_t s = cmp->file[0].buffered_lines + cmp->file[1].buffered_lines + 4;
+ char *flag_space = zalloc (s);
+ cmp->file[0].changed = flag_space + 1;
+ cmp->file[1].changed = flag_space + cmp->file[0].buffered_lines + 3;
+
+ /* Some lines are obviously insertions or deletions
+ because they don't match anything. Detect them now, and
+ avoid even thinking about them in the main comparison algorithm. */
+
+ discard_confusing_lines (cmp->file);
+
+ /* Now do the main comparison algorithm, considering just the
+ undiscarded lines. */
+
+ xvec = cmp->file[0].undiscarded;
+ yvec = cmp->file[1].undiscarded;
+ diags = (cmp->file[0].nondiscarded_lines
+ + cmp->file[1].nondiscarded_lines + 3);
+ fdiag = xmalloc (diags * (2 * sizeof *fdiag));
+ bdiag = fdiag + diags;
+ fdiag += cmp->file[1].nondiscarded_lines + 1;
+ bdiag += cmp->file[1].nondiscarded_lines + 1;
+
+ /* Set TOO_EXPENSIVE to be approximate square root of input size,
+ bounded below by 256. */
+ too_expensive = 1;
+ for (; diags != 0; diags >>= 2)
+ too_expensive <<= 1;
+ too_expensive = MAX (256, too_expensive);
+
+ files[0] = cmp->file[0];
+ files[1] = cmp->file[1];
+
+ compareseq (0, cmp->file[0].nondiscarded_lines,
+ 0, cmp->file[1].nondiscarded_lines, minimal);
+
+ free (fdiag - (cmp->file[1].nondiscarded_lines + 1));
+
+ /* Modify the results slightly to make them prettier
+ in cases where that can validly be done. */
+
+ shift_boundaries (cmp->file);
+
+ /* Get the results of comparison in the form of a chain
+ of `struct change's -- an edit script. */
+
+ if (output_style == OUTPUT_ED)
+ script = build_reverse_script (cmp->file);
+ else
+ script = build_script (cmp->file);
+
+ /* Set CHANGES if we had any diffs.
+ If some changes are ignored, we must scan the script to decide. */
+ if (ignore_blank_lines || ignore_regexp.fastmap)
+ {
+ struct change *next = script;
+ changes = 0;
+
+ while (next && changes == 0)
+ {
+ struct change *this, *end;
+ lin first0, last0, first1, last1;
+
+ /* Find a set of changes that belong together. */
+ this = next;
+ end = find_change (next);
+
+ /* Disconnect them from the rest of the changes, making them
+ a hunk, and remember the rest for next iteration. */
+ next = end->link;
+ end->link = 0;
+
+ /* Determine whether this hunk is really a difference. */
+ if (analyze_hunk (this, &first0, &last0, &first1, &last1))
+ changes = 1;
+
+ /* Reconnect the script so it will all be freed properly. */
+ end->link = next;
+ }
+ }
+ else
+ changes = (script != 0);
+
+ if (brief)
+ changes = briefly_report (changes, cmp->file);
+ else
+ {
+ if (changes | !no_diff_means_no_output)
+ {
+ /* Record info for starting up output,
+ to be used if and when we have some output to print. */
+ setup_output (file_label[0] ? file_label[0] : cmp->file[0].name,
+ file_label[1] ? file_label[1] : cmp->file[1].name,
+ cmp->parent != 0);
+
+ switch (output_style)
+ {
+ case OUTPUT_CONTEXT:
+ print_context_script (script, false);
+ break;
+
+ case OUTPUT_UNIFIED:
+ print_context_script (script, true);
+ break;
+
+ case OUTPUT_ED:
+ print_ed_script (script);
+ break;
+
+ case OUTPUT_FORWARD_ED:
+ pr_forward_ed_script (script);
+ break;
+
+ case OUTPUT_RCS:
+ print_rcs_script (script);
+ break;
+
+ case OUTPUT_NORMAL:
+ print_normal_script (script);
+ break;
+
+ case OUTPUT_IFDEF:
+ print_ifdef_script (script);
+ break;
+
+ case OUTPUT_SDIFF:
+ print_sdiff_script (script);
+ break;
+
+ default:
+ abort ();
+ }
+
+ finish_output ();
+ }
+ }
+
+ free (cmp->file[0].undiscarded);
+
+ free (flag_space);
+
+ for (f = 0; f < 2; f++)
+ {
+ free (cmp->file[f].equivs);
+ free (cmp->file[f].linbuf + cmp->file[f].linbuf_base);
+ }
+
+ for (e = script; e; e = p)
+ {
+ p = e->link;
+ free (e);
+ }
+
+ if (! ROBUST_OUTPUT_STYLE (output_style))
+ for (f = 0; f < 2; ++f)
+ if (cmp->file[f].missing_newline)
+ {
+ error (0, 0, "%s: %s\n",
+ file_label[f] ? file_label[f] : cmp->file[f].name,
+ _("No newline at end of file"));
+ changes = 2;
+ }
+ }
+
+ if (cmp->file[0].buffer != cmp->file[1].buffer)
+ free (cmp->file[0].buffer);
+ free (cmp->file[1].buffer);
+
+ return changes;
+}
diff --git a/contrib/diff/src/cmp.c b/contrib/diff/src/cmp.c
new file mode 100644
index 0000000..1f965e5
--- /dev/null
+++ b/contrib/diff/src/cmp.c
@@ -0,0 +1,677 @@
+/* cmp - compare two files byte by byte
+
+ Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 2001,
+ 2002, 2004 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; see the file COPYING.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "system.h"
+#include "paths.h"
+
+#include <stdio.h>
+
+#include <c-stack.h>
+#include <cmpbuf.h>
+#include <error.h>
+#include <exit.h>
+#include <exitfail.h>
+#include <file-type.h>
+#include <getopt.h>
+#include <hard-locale.h>
+#include <inttostr.h>
+#include <setmode.h>
+#include <unlocked-io.h>
+#include <version-etc.h>
+#include <xalloc.h>
+#include <xstrtol.h>
+
+#if defined LC_MESSAGES && ENABLE_NLS
+# define hard_locale_LC_MESSAGES hard_locale (LC_MESSAGES)
+#else
+# define hard_locale_LC_MESSAGES 0
+#endif
+
+static int cmp (void);
+static off_t file_position (int);
+static size_t block_compare (word const *, word const *);
+static size_t block_compare_and_count (word const *, word const *, off_t *);
+static void sprintc (char *, unsigned char);
+
+/* Name under which this program was invoked. */
+char *program_name;
+
+/* Filenames of the compared files. */
+static char const *file[2];
+
+/* File descriptors of the files. */
+static int file_desc[2];
+
+/* Status of the files. */
+static struct stat stat_buf[2];
+
+/* Read buffers for the files. */
+static word *buffer[2];
+
+/* Optimal block size for the files. */
+static size_t buf_size;
+
+/* Initial prefix to ignore for each file. */
+static off_t ignore_initial[2];
+
+/* Number of bytes to compare. */
+static uintmax_t bytes = UINTMAX_MAX;
+
+/* Output format. */
+static enum comparison_type
+ {
+ type_first_diff, /* Print the first difference. */
+ type_all_diffs, /* Print all differences. */
+ type_status /* Exit status only. */
+ } comparison_type;
+
+/* If nonzero, print values of bytes quoted like cat -t does. */
+static bool opt_print_bytes;
+
+/* Values for long options that do not have single-letter equivalents. */
+enum
+{
+ HELP_OPTION = CHAR_MAX + 1
+};
+
+static struct option const long_options[] =
+{
+ {"print-bytes", 0, 0, 'b'},
+ {"print-chars", 0, 0, 'c'}, /* obsolescent as of diffutils 2.7.3 */
+ {"ignore-initial", 1, 0, 'i'},
+ {"verbose", 0, 0, 'l'},
+ {"bytes", 1, 0, 'n'},
+ {"silent", 0, 0, 's'},
+ {"quiet", 0, 0, 's'},
+ {"version", 0, 0, 'v'},
+ {"help", 0, 0, HELP_OPTION},
+ {0, 0, 0, 0}
+};
+
+static void try_help (char const *, char const *) __attribute__((noreturn));
+static void
+try_help (char const *reason_msgid, char const *operand)
+{
+ if (reason_msgid)
+ error (0, 0, _(reason_msgid), operand);
+ error (EXIT_TROUBLE, 0,
+ _("Try `%s --help' for more information."), program_name);
+ abort ();
+}
+
+static char const valid_suffixes[] = "kKMGTPEZY0";
+
+/* Update ignore_initial[F] according to the result of parsing an
+ *operand ARGPTR of --ignore-initial, updating *ARGPTR to point
+ *after the operand. If DELIMITER is nonzero, the operand may be
+ *followed by DELIMITER; otherwise it must be null-terminated. */
+static void
+specify_ignore_initial (int f, char **argptr, char delimiter)
+{
+ uintmax_t val;
+ off_t o;
+ char const *arg = *argptr;
+ strtol_error e = xstrtoumax (arg, argptr, 0, &val, valid_suffixes);
+ if (! (e == LONGINT_OK
+ || (e == LONGINT_INVALID_SUFFIX_CHAR && **argptr == delimiter))
+ || (o = val) < 0 || o != val || val == UINTMAX_MAX)
+ try_help ("invalid --ignore-initial value `%s'", arg);
+ if (ignore_initial[f] < o)
+ ignore_initial[f] = o;
+}
+
+/* Specify the output format. */
+static void
+specify_comparison_type (enum comparison_type t)
+{
+ if (comparison_type && comparison_type != t)
+ try_help ("options -l and -s are incompatible", 0);
+ comparison_type = t;
+}
+
+static void
+check_stdout (void)
+{
+ if (ferror (stdout))
+ error (EXIT_TROUBLE, 0, "%s", _("write failed"));
+ else if (fclose (stdout) != 0)
+ error (EXIT_TROUBLE, errno, "%s", _("standard output"));
+}
+
+static char const * const option_help_msgid[] = {
+ N_("-b --print-bytes Print differing bytes."),
+ N_("-i SKIP --ignore-initial=SKIP Skip the first SKIP bytes of input."),
+ N_("-i SKIP1:SKIP2 --ignore-initial=SKIP1:SKIP2"),
+ N_(" Skip the first SKIP1 bytes of FILE1 and the first SKIP2 bytes of FILE2."),
+ N_("-l --verbose Output byte numbers and values of all differing bytes."),
+ N_("-n LIMIT --bytes=LIMIT Compare at most LIMIT bytes."),
+ N_("-s --quiet --silent Output nothing; yield exit status only."),
+ N_("-v --version Output version info."),
+ N_("--help Output this help."),
+ 0
+};
+
+static void
+usage (void)
+{
+ char const * const *p;
+
+ printf (_("Usage: %s [OPTION]... FILE1 [FILE2 [SKIP1 [SKIP2]]]\n"),
+ program_name);
+ printf ("%s\n\n", _("Compare two files byte by byte."));
+ for (p = option_help_msgid; *p; p++)
+ printf (" %s\n", _(*p));
+ printf ("\n%s\n%s\n\n%s\n%s\n\n%s\n",
+ _("SKIP1 and SKIP2 are the number of bytes to skip in each file."),
+ _("SKIP values may be followed by the following multiplicative suffixes:\n\
+kB 1000, K 1024, MB 1,000,000, M 1,048,576,\n\
+GB 1,000,000,000, G 1,073,741,824, and so on for T, P, E, Z, Y."),
+ _("If a FILE is `-' or missing, read standard input."),
+ _("Exit status is 0 if inputs are the same, 1 if different, 2 if trouble."),
+ _("Report bugs to <bug-gnu-utils@gnu.org>."));
+}
+
+int
+main (int argc, char **argv)
+{
+ int c, f, exit_status;
+ size_t words_per_buffer;
+
+ exit_failure = EXIT_TROUBLE;
+ initialize_main (&argc, &argv);
+ program_name = argv[0];
+ setlocale (LC_ALL, "");
+ bindtextdomain (PACKAGE, LOCALEDIR);
+ textdomain (PACKAGE);
+ c_stack_action (0);
+
+ /* Parse command line options. */
+
+ while ((c = getopt_long (argc, argv, "bci:ln:sv", long_options, 0))
+ != -1)
+ switch (c)
+ {
+ case 'b':
+ case 'c': /* 'c' is obsolescent as of diffutils 2.7.3 */
+ opt_print_bytes = true;
+ break;
+
+ case 'i':
+ specify_ignore_initial (0, &optarg, ':');
+ if (*optarg++ == ':')
+ specify_ignore_initial (1, &optarg, 0);
+ else if (ignore_initial[1] < ignore_initial[0])
+ ignore_initial[1] = ignore_initial[0];
+ break;
+
+ case 'l':
+ specify_comparison_type (type_all_diffs);
+ break;
+
+ case 'n':
+ {
+ uintmax_t n;
+ if (xstrtoumax (optarg, 0, 0, &n, valid_suffixes) != LONGINT_OK)
+ try_help ("invalid --bytes value `%s'", optarg);
+ if (n < bytes)
+ bytes = n;
+ }
+ break;
+
+ case 's':
+ specify_comparison_type (type_status);
+ break;
+
+ case 'v':
+ /* TRANSLATORS: Please translate the second "o" in "Torbjorn
+ Granlund" to an o-with-umlaut (U+00F6, LATIN SMALL LETTER O
+ WITH DIAERESIS) if possible. */
+ version_etc (stdout, "cmp", PACKAGE_NAME, PACKAGE_VERSION,
+ _("Torbjorn Granlund"), "David MacKenzie", (char *) 0);
+ check_stdout ();
+ return EXIT_SUCCESS;
+
+ case HELP_OPTION:
+ usage ();
+ check_stdout ();
+ return EXIT_SUCCESS;
+
+ default:
+ try_help (0, 0);
+ }
+
+ if (optind == argc)
+ try_help ("missing operand after `%s'", argv[argc - 1]);
+
+ file[0] = argv[optind++];
+ file[1] = optind < argc ? argv[optind++] : "-";
+
+ for (f = 0; f < 2 && optind < argc; f++)
+ {
+ char *arg = argv[optind++];
+ specify_ignore_initial (f, &arg, 0);
+ }
+
+ if (optind < argc)
+ try_help ("extra operand `%s'", argv[optind]);
+
+ for (f = 0; f < 2; f++)
+ {
+ /* If file[1] is "-", treat it first; this avoids a misdiagnostic if
+ stdin is closed and opening file[0] yields file descriptor 0. */
+ int f1 = f ^ (strcmp (file[1], "-") == 0);
+
+ /* Two files with the same name and offset are identical.
+ But wait until we open the file once, for proper diagnostics. */
+ if (f && ignore_initial[0] == ignore_initial[1]
+ && file_name_cmp (file[0], file[1]) == 0)
+ return EXIT_SUCCESS;
+
+ file_desc[f1] = (strcmp (file[f1], "-") == 0
+ ? STDIN_FILENO
+ : open (file[f1], O_RDONLY, 0));
+ if (file_desc[f1] < 0 || fstat (file_desc[f1], stat_buf + f1) != 0)
+ {
+ if (file_desc[f1] < 0 && comparison_type == type_status)
+ exit (EXIT_TROUBLE);
+ else
+ error (EXIT_TROUBLE, errno, "%s", file[f1]);
+ }
+
+ set_binary_mode (file_desc[f1], true);
+ }
+
+ /* If the files are links to the same inode and have the same file position,
+ they are identical. */
+
+ if (0 < same_file (&stat_buf[0], &stat_buf[1])
+ && same_file_attributes (&stat_buf[0], &stat_buf[1])
+ && file_position (0) == file_position (1))
+ return EXIT_SUCCESS;
+
+ /* If output is redirected to the null device, we may assume `-s'. */
+
+ if (comparison_type != type_status)
+ {
+ struct stat outstat, nullstat;
+
+ if (fstat (STDOUT_FILENO, &outstat) == 0
+ && stat (NULL_DEVICE, &nullstat) == 0
+ && 0 < same_file (&outstat, &nullstat))
+ comparison_type = type_status;
+ }
+
+ /* If only a return code is needed,
+ and if both input descriptors are associated with plain files,
+ conclude that the files differ if they have different sizes
+ and if more bytes will be compared than are in the smaller file. */
+
+ if (comparison_type == type_status
+ && S_ISREG (stat_buf[0].st_mode)
+ && S_ISREG (stat_buf[1].st_mode))
+ {
+ off_t s0 = stat_buf[0].st_size - file_position (0);
+ off_t s1 = stat_buf[1].st_size - file_position (1);
+ if (s0 < 0)
+ s0 = 0;
+ if (s1 < 0)
+ s1 = 0;
+ if (s0 != s1 && MIN (s0, s1) < bytes)
+ exit (EXIT_FAILURE);
+ }
+
+ /* Get the optimal block size of the files. */
+
+ buf_size = buffer_lcm (STAT_BLOCKSIZE (stat_buf[0]),
+ STAT_BLOCKSIZE (stat_buf[1]),
+ PTRDIFF_MAX - sizeof (word));
+
+ /* Allocate word-aligned buffers, with space for sentinels at the end. */
+
+ words_per_buffer = (buf_size + 2 * sizeof (word) - 1) / sizeof (word);
+ buffer[0] = xmalloc (2 * sizeof (word) * words_per_buffer);
+ buffer[1] = buffer[0] + words_per_buffer;
+
+ exit_status = cmp ();
+
+ for (f = 0; f < 2; f++)
+ if (close (file_desc[f]) != 0)
+ error (EXIT_TROUBLE, errno, "%s", file[f]);
+ if (exit_status != 0 && comparison_type != type_status)
+ check_stdout ();
+ exit (exit_status);
+ return exit_status;
+}
+
+/* Compare the two files already open on `file_desc[0]' and `file_desc[1]',
+ using `buffer[0]' and `buffer[1]'.
+ Return EXIT_SUCCESS if identical, EXIT_FAILURE if different,
+ >1 if error. */
+
+static int
+cmp (void)
+{
+ off_t line_number = 1; /* Line number (1...) of difference. */
+ off_t byte_number = 1; /* Byte number (1...) of difference. */
+ uintmax_t remaining = bytes; /* Remaining number of bytes to compare. */
+ size_t read0, read1; /* Number of bytes read from each file. */
+ size_t first_diff; /* Offset (0...) in buffers of 1st diff. */
+ size_t smaller; /* The lesser of `read0' and `read1'. */
+ word *buffer0 = buffer[0];
+ word *buffer1 = buffer[1];
+ char *buf0 = (char *) buffer0;
+ char *buf1 = (char *) buffer1;
+ int ret = EXIT_SUCCESS;
+ int f;
+ int offset_width;
+
+ if (comparison_type == type_all_diffs)
+ {
+ off_t byte_number_max = MIN (bytes, TYPE_MAXIMUM (off_t));
+
+ for (f = 0; f < 2; f++)
+ if (S_ISREG (stat_buf[f].st_mode))
+ {
+ off_t file_bytes = stat_buf[f].st_size - file_position (f);
+ if (file_bytes < byte_number_max)
+ byte_number_max = file_bytes;
+ }
+
+ for (offset_width = 1; (byte_number_max /= 10) != 0; offset_width++)
+ continue;
+ }
+
+ for (f = 0; f < 2; f++)
+ {
+ off_t ig = ignore_initial[f];
+ if (ig && file_position (f) == -1)
+ {
+ /* lseek failed; read and discard the ignored initial prefix. */
+ do
+ {
+ size_t bytes_to_read = MIN (ig, buf_size);
+ size_t r = block_read (file_desc[f], buf0, bytes_to_read);
+ if (r != bytes_to_read)
+ {
+ if (r == SIZE_MAX)
+ error (EXIT_TROUBLE, errno, "%s", file[f]);
+ break;
+ }
+ ig -= r;
+ }
+ while (ig);
+ }
+ }
+
+ do
+ {
+ size_t bytes_to_read = buf_size;
+
+ if (remaining != UINTMAX_MAX)
+ {
+ if (remaining < bytes_to_read)
+ bytes_to_read = remaining;
+ remaining -= bytes_to_read;
+ }
+
+ read0 = block_read (file_desc[0], buf0, bytes_to_read);
+ if (read0 == SIZE_MAX)
+ error (EXIT_TROUBLE, errno, "%s", file[0]);
+ read1 = block_read (file_desc[1], buf1, bytes_to_read);
+ if (read1 == SIZE_MAX)
+ error (EXIT_TROUBLE, errno, "%s", file[1]);
+
+ /* Insert sentinels for the block compare. */
+
+ buf0[read0] = ~buf1[read0];
+ buf1[read1] = ~buf0[read1];
+
+ /* If the line number should be written for differing files,
+ compare the blocks and count the number of newlines
+ simultaneously. */
+ first_diff = (comparison_type == type_first_diff
+ ? block_compare_and_count (buffer0, buffer1, &line_number)
+ : block_compare (buffer0, buffer1));
+
+ byte_number += first_diff;
+ smaller = MIN (read0, read1);
+
+ if (first_diff < smaller)
+ {
+ switch (comparison_type)
+ {
+ case type_first_diff:
+ {
+ char byte_buf[INT_BUFSIZE_BOUND (off_t)];
+ char line_buf[INT_BUFSIZE_BOUND (off_t)];
+ char const *byte_num = offtostr (byte_number, byte_buf);
+ char const *line_num = offtostr (line_number, line_buf);
+ if (!opt_print_bytes)
+ {
+ /* See POSIX 1003.1-2001 for this format. This
+ message is used only in the POSIX locale, so it
+ need not be translated. */
+ static char const char_message[] =
+ "%s %s differ: char %s, line %s\n";
+
+ /* The POSIX rationale recommends using the word
+ "byte" outside the POSIX locale. Some gettext
+ implementations translate even in the POSIX
+ locale if certain other environment variables
+ are set, so use "byte" if a translation is
+ available, or if outside the POSIX locale. */
+ static char const byte_msgid[] =
+ N_("%s %s differ: byte %s, line %s\n");
+ char const *byte_message = _(byte_msgid);
+ bool use_byte_message = (byte_message != byte_msgid
+ || hard_locale_LC_MESSAGES);
+
+ printf (use_byte_message ? byte_message : char_message,
+ file[0], file[1], byte_num, line_num);
+ }
+ else
+ {
+ unsigned char c0 = buf0[first_diff];
+ unsigned char c1 = buf1[first_diff];
+ char s0[5];
+ char s1[5];
+ sprintc (s0, c0);
+ sprintc (s1, c1);
+ printf (_("%s %s differ: byte %s, line %s is %3o %s %3o %s\n"),
+ file[0], file[1], byte_num, line_num,
+ c0, s0, c1, s1);
+ }
+ }
+ /* Fall through. */
+ case type_status:
+ return EXIT_FAILURE;
+
+ case type_all_diffs:
+ do
+ {
+ unsigned char c0 = buf0[first_diff];
+ unsigned char c1 = buf1[first_diff];
+ if (c0 != c1)
+ {
+ char byte_buf[INT_BUFSIZE_BOUND (off_t)];
+ char const *byte_num = offtostr (byte_number, byte_buf);
+ if (!opt_print_bytes)
+ {
+ /* See POSIX 1003.1-2001 for this format. */
+ printf ("%*s %3o %3o\n",
+ offset_width, byte_num, c0, c1);
+ }
+ else
+ {
+ char s0[5];
+ char s1[5];
+ sprintc (s0, c0);
+ sprintc (s1, c1);
+ printf ("%*s %3o %-4s %3o %s\n",
+ offset_width, byte_num, c0, s0, c1, s1);
+ }
+ }
+ byte_number++;
+ first_diff++;
+ }
+ while (first_diff < smaller);
+ ret = EXIT_FAILURE;
+ break;
+ }
+ }
+
+ if (read0 != read1)
+ {
+ if (comparison_type != type_status)
+ {
+ /* See POSIX 1003.1-2001 for this format. */
+ fprintf (stderr, _("cmp: EOF on %s\n"), file[read1 < read0]);
+ }
+
+ return EXIT_FAILURE;
+ }
+ }
+ while (read0 == buf_size);
+
+ return ret;
+}
+
+/* Compare two blocks of memory P0 and P1 until they differ,
+ and count the number of '\n' occurrences in the common
+ part of P0 and P1.
+ If the blocks are not guaranteed to be different, put sentinels at the ends
+ of the blocks before calling this function.
+
+ Return the offset of the first byte that differs.
+ Increment *COUNT by the count of '\n' occurrences. */
+
+static size_t
+block_compare_and_count (word const *p0, word const *p1, off_t *count)
+{
+ word l; /* One word from first buffer. */
+ word const *l0, *l1; /* Pointers into each buffer. */
+ char const *c0, *c1; /* Pointers for finding exact address. */
+ size_t cnt = 0; /* Number of '\n' occurrences. */
+ word nnnn; /* Newline, sizeof (word) times. */
+ int i;
+
+ nnnn = 0;
+ for (i = 0; i < sizeof nnnn; i++)
+ nnnn = (nnnn << CHAR_BIT) | '\n';
+
+ /* Find the rough position of the first difference by reading words,
+ not bytes. */
+
+ for (l0 = p0, l1 = p1; (l = *l0) == *l1; l0++, l1++)
+ {
+ l ^= nnnn;
+ for (i = 0; i < sizeof l; i++)
+ {
+ unsigned char uc = l;
+ cnt += ! uc;
+ l >>= CHAR_BIT;
+ }
+ }
+
+ /* Find the exact differing position (endianness independent). */
+
+ for (c0 = (char const *) l0, c1 = (char const *) l1;
+ *c0 == *c1;
+ c0++, c1++)
+ cnt += *c0 == '\n';
+
+ *count += cnt;
+ return c0 - (char const *) p0;
+}
+
+/* Compare two blocks of memory P0 and P1 until they differ.
+ If the blocks are not guaranteed to be different, put sentinels at the ends
+ of the blocks before calling this function.
+
+ Return the offset of the first byte that differs. */
+
+static size_t
+block_compare (word const *p0, word const *p1)
+{
+ word const *l0, *l1;
+ char const *c0, *c1;
+
+ /* Find the rough position of the first difference by reading words,
+ not bytes. */
+
+ for (l0 = p0, l1 = p1; *l0 == *l1; l0++, l1++)
+ continue;
+
+ /* Find the exact differing position (endianness independent). */
+
+ for (c0 = (char const *) l0, c1 = (char const *) l1;
+ *c0 == *c1;
+ c0++, c1++)
+ continue;
+
+ return c0 - (char const *) p0;
+}
+
+/* Put into BUF the unsigned char C, making unprintable bytes
+ visible by quoting like cat -t does. */
+
+static void
+sprintc (char *buf, unsigned char c)
+{
+ if (! isprint (c))
+ {
+ if (c >= 128)
+ {
+ *buf++ = 'M';
+ *buf++ = '-';
+ c -= 128;
+ }
+ if (c < 32)
+ {
+ *buf++ = '^';
+ c += 64;
+ }
+ else if (c == 127)
+ {
+ *buf++ = '^';
+ c = '?';
+ }
+ }
+
+ *buf++ = c;
+ *buf = 0;
+}
+
+/* Position file F to ignore_initial[F] bytes from its initial position,
+ and yield its new position. Don't try more than once. */
+
+static off_t
+file_position (int f)
+{
+ static bool positioned[2];
+ static off_t position[2];
+
+ if (! positioned[f])
+ {
+ positioned[f] = true;
+ position[f] = lseek (file_desc[f], ignore_initial[f], SEEK_CUR);
+ }
+ return position[f];
+}
diff --git a/contrib/diff/src/context.c b/contrib/diff/src/context.c
new file mode 100644
index 0000000..2055ff1
--- /dev/null
+++ b/contrib/diff/src/context.c
@@ -0,0 +1,478 @@
+/* Context-format output routines for GNU DIFF.
+
+ Copyright (C) 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1998, 2001,
+ 2002, 2004 Free Software Foundation, Inc.
+
+ This file is part of GNU DIFF.
+
+ GNU DIFF 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.
+
+ GNU DIFF is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "diff.h"
+#include <inttostr.h>
+
+#ifdef ST_MTIM_NSEC
+# define TIMESPEC_NS(timespec) ((timespec).ST_MTIM_NSEC)
+#else
+# define TIMESPEC_NS(timespec) 0
+#endif
+
+size_t nstrftime (char *, size_t, char const *, struct tm const *, int, int);
+
+static char const *find_function (char const * const *, lin);
+static struct change *find_hunk (struct change *);
+static void mark_ignorable (struct change *);
+static void pr_context_hunk (struct change *);
+static void pr_unidiff_hunk (struct change *);
+
+/* Last place find_function started searching from. */
+static lin find_function_last_search;
+
+/* The value find_function returned when it started searching there. */
+static lin find_function_last_match;
+
+/* Print a label for a context diff, with a file name and date or a label. */
+
+static void
+print_context_label (char const *mark,
+ struct file_data *inf,
+ char const *label)
+{
+ if (label)
+ fprintf (outfile, "%s %s\n", mark, label);
+ else
+ {
+ char buf[MAX (INT_STRLEN_BOUND (int) + 32,
+ INT_STRLEN_BOUND (time_t) + 11)];
+ struct tm const *tm = localtime (&inf->stat.st_mtime);
+ int nsec = TIMESPEC_NS (inf->stat.st_mtim);
+ if (! (tm && nstrftime (buf, sizeof buf, time_format, tm, 0, nsec)))
+ {
+ long int sec = inf->stat.st_mtime;
+ verify (info_preserved, sizeof inf->stat.st_mtime <= sizeof sec);
+ sprintf (buf, "%ld.%.9d", sec, nsec);
+ }
+ fprintf (outfile, "%s %s\t%s\n", mark, inf->name, buf);
+ }
+}
+
+/* Print a header for a context diff, with the file names and dates. */
+
+void
+print_context_header (struct file_data inf[], bool unidiff)
+{
+ if (unidiff)
+ {
+ print_context_label ("---", &inf[0], file_label[0]);
+ print_context_label ("+++", &inf[1], file_label[1]);
+ }
+ else
+ {
+ print_context_label ("***", &inf[0], file_label[0]);
+ print_context_label ("---", &inf[1], file_label[1]);
+ }
+}
+
+/* Print an edit script in context format. */
+
+void
+print_context_script (struct change *script, bool unidiff)
+{
+ if (ignore_blank_lines || ignore_regexp.fastmap)
+ mark_ignorable (script);
+ else
+ {
+ struct change *e;
+ for (e = script; e; e = e->link)
+ e->ignore = false;
+ }
+
+ find_function_last_search = - files[0].prefix_lines;
+ find_function_last_match = LIN_MAX;
+
+ if (unidiff)
+ print_script (script, find_hunk, pr_unidiff_hunk);
+ else
+ print_script (script, find_hunk, pr_context_hunk);
+}
+
+/* Print a pair of line numbers with a comma, translated for file FILE.
+ If the second number is not greater, use the first in place of it.
+
+ Args A and B are internal line numbers.
+ We print the translated (real) line numbers. */
+
+static void
+print_context_number_range (struct file_data const *file, lin a, lin b)
+{
+ long int trans_a, trans_b;
+ translate_range (file, a, b, &trans_a, &trans_b);
+
+ /* We can have B <= A in the case of a range of no lines.
+ In this case, we should print the line number before the range,
+ which is B.
+
+ POSIX 1003.1-2001 requires two line numbers separated by a comma
+ even if the line numbers are the same. However, this does not
+ match existing practice and is surely an error in the
+ specification. */
+
+ if (trans_b <= trans_a)
+ fprintf (outfile, "%ld", trans_b);
+ else
+ fprintf (outfile, "%ld,%ld", trans_a, trans_b);
+}
+
+/* Print FUNCTION in a context header. */
+static void
+print_context_function (FILE *out, char const *function)
+{
+ int i;
+ putc (' ', out);
+ for (i = 0; i < 40 && function[i] != '\n'; i++)
+ continue;
+ fwrite (function, sizeof (char), i, out);
+}
+
+/* Print a portion of an edit script in context format.
+ HUNK is the beginning of the portion to be printed.
+ The end is marked by a `link' that has been nulled out.
+
+ Prints out lines from both files, and precedes each
+ line with the appropriate flag-character. */
+
+static void
+pr_context_hunk (struct change *hunk)
+{
+ lin first0, last0, first1, last1, i;
+ char const *prefix;
+ char const *function;
+ FILE *out;
+
+ /* Determine range of line numbers involved in each file. */
+
+ enum changes changes = analyze_hunk (hunk, &first0, &last0, &first1, &last1);
+ if (! changes)
+ return;
+
+ /* Include a context's width before and after. */
+
+ i = - files[0].prefix_lines;
+ first0 = MAX (first0 - context, i);
+ first1 = MAX (first1 - context, i);
+ if (last0 < files[0].valid_lines - context)
+ last0 += context;
+ else
+ last0 = files[0].valid_lines - 1;
+ if (last1 < files[1].valid_lines - context)
+ last1 += context;
+ else
+ last1 = files[1].valid_lines - 1;
+
+ /* If desired, find the preceding function definition line in file 0. */
+ function = 0;
+ if (function_regexp.fastmap)
+ function = find_function (files[0].linbuf, first0);
+
+ begin_output ();
+ out = outfile;
+
+ fprintf (out, "***************");
+
+ if (function)
+ print_context_function (out, function);
+
+ fprintf (out, "\n*** ");
+ print_context_number_range (&files[0], first0, last0);
+ fprintf (out, " ****\n");
+
+ if (changes & OLD)
+ {
+ struct change *next = hunk;
+
+ for (i = first0; i <= last0; i++)
+ {
+ /* Skip past changes that apply (in file 0)
+ only to lines before line I. */
+
+ while (next && next->line0 + next->deleted <= i)
+ next = next->link;
+
+ /* Compute the marking for line I. */
+
+ prefix = " ";
+ if (next && next->line0 <= i)
+ /* The change NEXT covers this line.
+ If lines were inserted here in file 1, this is "changed".
+ Otherwise it is "deleted". */
+ prefix = (next->inserted > 0 ? "!" : "-");
+
+ print_1_line (prefix, &files[0].linbuf[i]);
+ }
+ }
+
+ fprintf (out, "--- ");
+ print_context_number_range (&files[1], first1, last1);
+ fprintf (out, " ----\n");
+
+ if (changes & NEW)
+ {
+ struct change *next = hunk;
+
+ for (i = first1; i <= last1; i++)
+ {
+ /* Skip past changes that apply (in file 1)
+ only to lines before line I. */
+
+ while (next && next->line1 + next->inserted <= i)
+ next = next->link;
+
+ /* Compute the marking for line I. */
+
+ prefix = " ";
+ if (next && next->line1 <= i)
+ /* The change NEXT covers this line.
+ If lines were deleted here in file 0, this is "changed".
+ Otherwise it is "inserted". */
+ prefix = (next->deleted > 0 ? "!" : "+");
+
+ print_1_line (prefix, &files[1].linbuf[i]);
+ }
+ }
+}
+
+/* Print a pair of line numbers with a comma, translated for file FILE.
+ If the second number is smaller, use the first in place of it.
+ If the numbers are equal, print just one number.
+
+ Args A and B are internal line numbers.
+ We print the translated (real) line numbers. */
+
+static void
+print_unidiff_number_range (struct file_data const *file, lin a, lin b)
+{
+ long int trans_a, trans_b;
+ translate_range (file, a, b, &trans_a, &trans_b);
+
+ /* We can have B < A in the case of a range of no lines.
+ In this case, we print the line number before the range,
+ which is B. It would be more logical to print A, but
+ 'patch' expects B in order to detect diffs against empty files. */
+ if (trans_b <= trans_a)
+ fprintf (outfile, trans_b < trans_a ? "%ld,0" : "%ld", trans_b);
+ else
+ fprintf (outfile, "%ld,%ld", trans_a, trans_b - trans_a + 1);
+}
+
+/* Print a portion of an edit script in unidiff format.
+ HUNK is the beginning of the portion to be printed.
+ The end is marked by a `link' that has been nulled out.
+
+ Prints out lines from both files, and precedes each
+ line with the appropriate flag-character. */
+
+static void
+pr_unidiff_hunk (struct change *hunk)
+{
+ lin first0, last0, first1, last1;
+ lin i, j, k;
+ struct change *next;
+ char const *function;
+ FILE *out;
+
+ /* Determine range of line numbers involved in each file. */
+
+ if (! analyze_hunk (hunk, &first0, &last0, &first1, &last1))
+ return;
+
+ /* Include a context's width before and after. */
+
+ i = - files[0].prefix_lines;
+ first0 = MAX (first0 - context, i);
+ first1 = MAX (first1 - context, i);
+ if (last0 < files[0].valid_lines - context)
+ last0 += context;
+ else
+ last0 = files[0].valid_lines - 1;
+ if (last1 < files[1].valid_lines - context)
+ last1 += context;
+ else
+ last1 = files[1].valid_lines - 1;
+
+ /* If desired, find the preceding function definition line in file 0. */
+ function = 0;
+ if (function_regexp.fastmap)
+ function = find_function (files[0].linbuf, first0);
+
+ begin_output ();
+ out = outfile;
+
+ fprintf (out, "@@ -");
+ print_unidiff_number_range (&files[0], first0, last0);
+ fprintf (out, " +");
+ print_unidiff_number_range (&files[1], first1, last1);
+ fprintf (out, " @@");
+
+ if (function)
+ print_context_function (out, function);
+
+ putc ('\n', out);
+
+ next = hunk;
+ i = first0;
+ j = first1;
+
+ while (i <= last0 || j <= last1)
+ {
+
+ /* If the line isn't a difference, output the context from file 0. */
+
+ if (!next || i < next->line0)
+ {
+ putc (initial_tab ? '\t' : ' ', out);
+ print_1_line (0, &files[0].linbuf[i++]);
+ j++;
+ }
+ else
+ {
+ /* For each difference, first output the deleted part. */
+
+ k = next->deleted;
+ while (k--)
+ {
+ putc ('-', out);
+ if (initial_tab)
+ putc ('\t', out);
+ print_1_line (0, &files[0].linbuf[i++]);
+ }
+
+ /* Then output the inserted part. */
+
+ k = next->inserted;
+ while (k--)
+ {
+ putc ('+', out);
+ if (initial_tab)
+ putc ('\t', out);
+ print_1_line (0, &files[1].linbuf[j++]);
+ }
+
+ /* We're done with this hunk, so on to the next! */
+
+ next = next->link;
+ }
+ }
+}
+
+/* Scan a (forward-ordered) edit script for the first place that more than
+ 2*CONTEXT unchanged lines appear, and return a pointer
+ to the `struct change' for the last change before those lines. */
+
+static struct change *
+find_hunk (struct change *start)
+{
+ struct change *prev;
+ lin top0, top1;
+ lin thresh;
+
+ /* Threshold distance is 2 * CONTEXT + 1 between two non-ignorable
+ changes, but only CONTEXT if one is ignorable. Watch out for
+ integer overflow, though. */
+ lin non_ignorable_threshold =
+ (LIN_MAX - 1) / 2 < context ? LIN_MAX : 2 * context + 1;
+ lin ignorable_threshold = context;
+
+ do
+ {
+ /* Compute number of first line in each file beyond this changed. */
+ top0 = start->line0 + start->deleted;
+ top1 = start->line1 + start->inserted;
+ prev = start;
+ start = start->link;
+ thresh = (prev->ignore || (start && start->ignore)
+ ? ignorable_threshold
+ : non_ignorable_threshold);
+ /* It is not supposed to matter which file we check in the end-test.
+ If it would matter, crash. */
+ if (start && start->line0 - top0 != start->line1 - top1)
+ abort ();
+ } while (start
+ /* Keep going if less than THRESH lines
+ elapse before the affected line. */
+ && start->line0 - top0 < thresh);
+
+ return prev;
+}
+
+/* Set the `ignore' flag properly in each change in SCRIPT.
+ It should be 1 if all the lines inserted or deleted in that change
+ are ignorable lines. */
+
+static void
+mark_ignorable (struct change *script)
+{
+ while (script)
+ {
+ struct change *next = script->link;
+ lin first0, last0, first1, last1;
+
+ /* Turn this change into a hunk: detach it from the others. */
+ script->link = 0;
+
+ /* Determine whether this change is ignorable. */
+ script->ignore = ! analyze_hunk (script,
+ &first0, &last0, &first1, &last1);
+
+ /* Reconnect the chain as before. */
+ script->link = next;
+
+ /* Advance to the following change. */
+ script = next;
+ }
+}
+
+/* Find the last function-header line in LINBUF prior to line number LINENUM.
+ This is a line containing a match for the regexp in `function_regexp'.
+ Return the address of the text, or 0 if no function-header is found. */
+
+static char const *
+find_function (char const * const *linbuf, lin linenum)
+{
+ lin i = linenum;
+ lin last = find_function_last_search;
+ find_function_last_search = i;
+
+ while (last <= --i)
+ {
+ /* See if this line is what we want. */
+ char const *line = linbuf[i];
+ size_t linelen = linbuf[i + 1] - line - 1;
+
+ /* FIXME: re_search's size args should be size_t, not int. */
+ int len = MIN (linelen, INT_MAX);
+
+ if (0 <= re_search (&function_regexp, line, len, 0, len, 0))
+ {
+ find_function_last_match = i;
+ return line;
+ }
+ }
+ /* If we search back to where we started searching the previous time,
+ find the line we found last time. */
+ if (find_function_last_match != LIN_MAX)
+ return linbuf[find_function_last_match];
+
+ return 0;
+}
diff --git a/contrib/diff/src/diff.c b/contrib/diff/src/diff.c
new file mode 100644
index 0000000..a975107
--- /dev/null
+++ b/contrib/diff/src/diff.c
@@ -0,0 +1,1353 @@
+/* diff - compare files line by line
+
+ Copyright (C) 1988, 1989, 1992, 1993, 1994, 1996, 1998, 2001, 2002,
+ 2004 Free Software Foundation, Inc.
+
+ This file is part of GNU DIFF.
+
+ GNU DIFF 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.
+
+ GNU DIFF 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 GNU DIFF; see the file COPYING.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define GDIFF_MAIN
+#include "diff.h"
+#include "paths.h"
+#include <c-stack.h>
+#include <dirname.h>
+#include <error.h>
+#include <exclude.h>
+#include <exit.h>
+#include <exitfail.h>
+#include <file-type.h>
+#include <fnmatch.h>
+#include <getopt.h>
+#include <hard-locale.h>
+#include <posixver.h>
+#include <prepargs.h>
+#include <quotesys.h>
+#include <setmode.h>
+#include <version-etc.h>
+#include <xalloc.h>
+
+#ifndef GUTTER_WIDTH_MINIMUM
+# define GUTTER_WIDTH_MINIMUM 3
+#endif
+
+struct regexp_list
+{
+ char *regexps; /* chars representing disjunction of the regexps */
+ size_t len; /* chars used in `regexps' */
+ size_t size; /* size malloc'ed for `regexps'; 0 if not malloc'ed */
+ bool multiple_regexps;/* Does `regexps' represent a disjunction? */
+ struct re_pattern_buffer *buf;
+};
+
+static int compare_files (struct comparison const *, char const *, char const *);
+static void add_regexp (struct regexp_list *, char const *);
+static void summarize_regexp_list (struct regexp_list *);
+static void specify_style (enum output_style);
+static void specify_value (char const **, char const *, char const *);
+static void try_help (char const *, char const *) __attribute__((noreturn));
+static void check_stdout (void);
+static void usage (void);
+
+/* If comparing directories, compare their common subdirectories
+ recursively. */
+static bool recursive;
+
+/* In context diffs, show previous lines that match these regexps. */
+static struct regexp_list function_regexp_list;
+
+/* Ignore changes affecting only lines that match these regexps. */
+static struct regexp_list ignore_regexp_list;
+
+#if HAVE_SETMODE_DOS
+/* Use binary I/O when reading and writing data (--binary).
+ On POSIX hosts, this has no effect. */
+static bool binary;
+#else
+enum { binary = true };
+#endif
+
+/* When comparing directories, if a file appears only in one
+ directory, treat it as present but empty in the other (-N).
+ Then `patch' would create the file with appropriate contents. */
+static bool new_file;
+
+/* When comparing directories, if a file appears only in the second
+ directory of the two, treat it as present but empty in the other
+ (--unidirectional-new-file).
+ Then `patch' would create the file with appropriate contents. */
+static bool unidirectional_new_file;
+
+/* Report files compared that are the same (-s).
+ Normally nothing is output when that happens. */
+static bool report_identical_files;
+
+
+/* Return a string containing the command options with which diff was invoked.
+ Spaces appear between what were separate ARGV-elements.
+ There is a space at the beginning but none at the end.
+ If there were no options, the result is an empty string.
+
+ Arguments: OPTIONVEC, a vector containing separate ARGV-elements, and COUNT,
+ the length of that vector. */
+
+static char *
+option_list (char **optionvec, int count)
+{
+ int i;
+ size_t size = 1;
+ char *result;
+ char *p;
+
+ for (i = 0; i < count; i++)
+ size += 1 + quote_system_arg ((char *) 0, optionvec[i]);
+
+ p = result = xmalloc (size);
+
+ for (i = 0; i < count; i++)
+ {
+ *p++ = ' ';
+ p += quote_system_arg (p, optionvec[i]);
+ }
+
+ *p = 0;
+ return result;
+}
+
+
+/* Return an option value suitable for add_exclude. */
+
+static int
+exclude_options (void)
+{
+ return EXCLUDE_WILDCARDS | (ignore_file_name_case ? FNM_CASEFOLD : 0);
+}
+
+static char const shortopts[] =
+"0123456789abBcC:dD:eEfF:hHiI:lL:nNpPqrsS:tTuU:vwW:x:X:y";
+
+/* Values for long options that do not have single-letter equivalents. */
+enum
+{
+ BINARY_OPTION = CHAR_MAX + 1,
+ FROM_FILE_OPTION,
+ HELP_OPTION,
+ HORIZON_LINES_OPTION,
+ IGNORE_FILE_NAME_CASE_OPTION,
+ INHIBIT_HUNK_MERGE_OPTION,
+ LEFT_COLUMN_OPTION,
+ LINE_FORMAT_OPTION,
+ NO_IGNORE_FILE_NAME_CASE_OPTION,
+ NORMAL_OPTION,
+ SDIFF_MERGE_ASSIST_OPTION,
+ STRIP_TRAILING_CR_OPTION,
+ SUPPRESS_COMMON_LINES_OPTION,
+ TABSIZE_OPTION,
+ TO_FILE_OPTION,
+
+ /* These options must be in sequence. */
+ UNCHANGED_LINE_FORMAT_OPTION,
+ OLD_LINE_FORMAT_OPTION,
+ NEW_LINE_FORMAT_OPTION,
+
+ /* These options must be in sequence. */
+ UNCHANGED_GROUP_FORMAT_OPTION,
+ OLD_GROUP_FORMAT_OPTION,
+ NEW_GROUP_FORMAT_OPTION,
+ CHANGED_GROUP_FORMAT_OPTION
+};
+
+static char const group_format_option[][sizeof "--unchanged-group-format"] =
+ {
+ "--unchanged-group-format",
+ "--old-group-format",
+ "--new-group-format",
+ "--changed-group-format"
+ };
+
+static char const line_format_option[][sizeof "--unchanged-line-format"] =
+ {
+ "--unchanged-line-format",
+ "--old-line-format",
+ "--new-line-format"
+ };
+
+static struct option const longopts[] =
+{
+ {"binary", 0, 0, BINARY_OPTION},
+ {"brief", 0, 0, 'q'},
+ {"changed-group-format", 1, 0, CHANGED_GROUP_FORMAT_OPTION},
+ {"context", 2, 0, 'C'},
+ {"ed", 0, 0, 'e'},
+ {"exclude", 1, 0, 'x'},
+ {"exclude-from", 1, 0, 'X'},
+ {"expand-tabs", 0, 0, 't'},
+ {"forward-ed", 0, 0, 'f'},
+ {"from-file", 1, 0, FROM_FILE_OPTION},
+ {"help", 0, 0, HELP_OPTION},
+ {"horizon-lines", 1, 0, HORIZON_LINES_OPTION},
+ {"ifdef", 1, 0, 'D'},
+ {"ignore-all-space", 0, 0, 'w'},
+ {"ignore-blank-lines", 0, 0, 'B'},
+ {"ignore-case", 0, 0, 'i'},
+ {"ignore-file-name-case", 0, 0, IGNORE_FILE_NAME_CASE_OPTION},
+ {"ignore-matching-lines", 1, 0, 'I'},
+ {"ignore-space-change", 0, 0, 'b'},
+ {"ignore-tab-expansion", 0, 0, 'E'},
+ {"inhibit-hunk-merge", 0, 0, INHIBIT_HUNK_MERGE_OPTION},
+ {"initial-tab", 0, 0, 'T'},
+ {"label", 1, 0, 'L'},
+ {"left-column", 0, 0, LEFT_COLUMN_OPTION},
+ {"line-format", 1, 0, LINE_FORMAT_OPTION},
+ {"minimal", 0, 0, 'd'},
+ {"new-file", 0, 0, 'N'},
+ {"new-group-format", 1, 0, NEW_GROUP_FORMAT_OPTION},
+ {"new-line-format", 1, 0, NEW_LINE_FORMAT_OPTION},
+ {"no-ignore-file-name-case", 0, 0, NO_IGNORE_FILE_NAME_CASE_OPTION},
+ {"normal", 0, 0, NORMAL_OPTION},
+ {"old-group-format", 1, 0, OLD_GROUP_FORMAT_OPTION},
+ {"old-line-format", 1, 0, OLD_LINE_FORMAT_OPTION},
+ {"paginate", 0, 0, 'l'},
+ {"rcs", 0, 0, 'n'},
+ {"recursive", 0, 0, 'r'},
+ {"report-identical-files", 0, 0, 's'},
+ {"sdiff-merge-assist", 0, 0, SDIFF_MERGE_ASSIST_OPTION},
+ {"show-c-function", 0, 0, 'p'},
+ {"show-function-line", 1, 0, 'F'},
+ {"side-by-side", 0, 0, 'y'},
+ {"speed-large-files", 0, 0, 'H'},
+ {"starting-file", 1, 0, 'S'},
+ {"strip-trailing-cr", 0, 0, STRIP_TRAILING_CR_OPTION},
+ {"suppress-common-lines", 0, 0, SUPPRESS_COMMON_LINES_OPTION},
+ {"tabsize", 1, 0, TABSIZE_OPTION},
+ {"text", 0, 0, 'a'},
+ {"to-file", 1, 0, TO_FILE_OPTION},
+ {"unchanged-group-format", 1, 0, UNCHANGED_GROUP_FORMAT_OPTION},
+ {"unchanged-line-format", 1, 0, UNCHANGED_LINE_FORMAT_OPTION},
+ {"unidirectional-new-file", 0, 0, 'P'},
+ {"unified", 2, 0, 'U'},
+ {"version", 0, 0, 'v'},
+ {"width", 1, 0, 'W'},
+ {0, 0, 0, 0}
+};
+
+int
+main (int argc, char **argv)
+{
+ int exit_status = EXIT_SUCCESS;
+ int c;
+ int i;
+ int prev = -1;
+ lin ocontext = -1;
+ bool explicit_context = false;
+ size_t width = 0;
+ bool show_c_function = false;
+ char const *from_file = 0;
+ char const *to_file = 0;
+ uintmax_t numval;
+ char *numend;
+
+ /* Do our initializations. */
+ exit_failure = 2;
+ initialize_main (&argc, &argv);
+ program_name = argv[0];
+ setlocale (LC_ALL, "");
+ bindtextdomain (PACKAGE, LOCALEDIR);
+ textdomain (PACKAGE);
+ c_stack_action (0);
+ function_regexp_list.buf = &function_regexp;
+ ignore_regexp_list.buf = &ignore_regexp;
+ re_set_syntax (RE_SYNTAX_GREP | RE_NO_POSIX_BACKTRACKING);
+ excluded = new_exclude ();
+
+ /* Decode the options. */
+
+ while ((c = getopt_long (argc, argv, shortopts, longopts, 0)) != -1)
+ {
+ switch (c)
+ {
+ case 0:
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (! ISDIGIT (prev))
+ ocontext = c - '0';
+ else if (LIN_MAX / 10 < ocontext
+ || ((ocontext = 10 * ocontext + c - '0') < 0))
+ ocontext = LIN_MAX;
+ break;
+
+ case 'a':
+ text = true;
+ break;
+
+ case 'b':
+ if (ignore_white_space < IGNORE_SPACE_CHANGE)
+ ignore_white_space = IGNORE_SPACE_CHANGE;
+ break;
+
+ case 'B':
+ ignore_blank_lines = true;
+ break;
+
+ case 'C':
+ case 'U':
+ {
+ if (optarg)
+ {
+ numval = strtoumax (optarg, &numend, 10);
+ if (*numend)
+ try_help ("invalid context length `%s'", optarg);
+ if (LIN_MAX < numval)
+ numval = LIN_MAX;
+ }
+ else
+ numval = 3;
+
+ specify_style (c == 'U' ? OUTPUT_UNIFIED : OUTPUT_CONTEXT);
+ if (context < numval)
+ context = numval;
+ explicit_context = true;
+ }
+ break;
+
+ case 'c':
+ specify_style (OUTPUT_CONTEXT);
+ if (context < 3)
+ context = 3;
+ break;
+
+ case 'd':
+ minimal = true;
+ break;
+
+ case 'D':
+ specify_style (OUTPUT_IFDEF);
+ {
+ static char const C_ifdef_group_formats[] =
+ "%%=%c#ifndef %s\n%%<#endif /* ! %s */\n%c#ifdef %s\n%%>#endif /* %s */\n%c#ifndef %s\n%%<#else /* %s */\n%%>#endif /* %s */\n";
+ char *b = xmalloc (sizeof C_ifdef_group_formats
+ + 7 * strlen (optarg) - 14 /* 7*"%s" */
+ - 8 /* 5*"%%" + 3*"%c" */);
+ sprintf (b, C_ifdef_group_formats,
+ 0,
+ optarg, optarg, 0,
+ optarg, optarg, 0,
+ optarg, optarg, optarg);
+ for (i = 0; i < sizeof group_format / sizeof *group_format; i++)
+ {
+ specify_value (&group_format[i], b, "-D");
+ b += strlen (b) + 1;
+ }
+ }
+ break;
+
+ case 'e':
+ specify_style (OUTPUT_ED);
+ break;
+
+ case 'E':
+ if (ignore_white_space < IGNORE_TAB_EXPANSION)
+ ignore_white_space = IGNORE_TAB_EXPANSION;
+ break;
+
+ case 'f':
+ specify_style (OUTPUT_FORWARD_ED);
+ break;
+
+ case 'F':
+ add_regexp (&function_regexp_list, optarg);
+ break;
+
+ case 'h':
+ /* Split the files into chunks for faster processing.
+ Usually does not change the result.
+
+ This currently has no effect. */
+ break;
+
+ case 'H':
+ speed_large_files = true;
+ break;
+
+ case 'i':
+ ignore_case = true;
+ break;
+
+ case 'I':
+ add_regexp (&ignore_regexp_list, optarg);
+ break;
+
+ case 'l':
+ if (!pr_program[0])
+ try_help ("pagination not supported on this host", 0);
+ paginate = true;
+#ifdef SIGCHLD
+ /* Pagination requires forking and waiting, and
+ System V fork+wait does not work if SIGCHLD is ignored. */
+ signal (SIGCHLD, SIG_DFL);
+#endif
+ break;
+
+ case 'L':
+ if (!file_label[0])
+ file_label[0] = optarg;
+ else if (!file_label[1])
+ file_label[1] = optarg;
+ else
+ fatal ("too many file label options");
+ break;
+
+ case 'n':
+ specify_style (OUTPUT_RCS);
+ break;
+
+ case 'N':
+ new_file = true;
+ break;
+
+ case 'p':
+ show_c_function = true;
+ add_regexp (&function_regexp_list, "^[[:alpha:]$_]");
+ break;
+
+ case 'P':
+ unidirectional_new_file = true;
+ break;
+
+ case 'q':
+ brief = true;
+ break;
+
+ case 'r':
+ recursive = true;
+ break;
+
+ case 's':
+ report_identical_files = true;
+ break;
+
+ case 'S':
+ specify_value (&starting_file, optarg, "-S");
+ break;
+
+ case 't':
+ expand_tabs = true;
+ break;
+
+ case 'T':
+ initial_tab = true;
+ break;
+
+ case 'u':
+ specify_style (OUTPUT_UNIFIED);
+ if (context < 3)
+ context = 3;
+ break;
+
+ case 'v':
+ version_etc (stdout, "diff", PACKAGE_NAME, PACKAGE_VERSION,
+ "Paul Eggert", "Mike Haertel", "David Hayes",
+ "Richard Stallman", "Len Tower", (char *) 0);
+ check_stdout ();
+ return EXIT_SUCCESS;
+
+ case 'w':
+ ignore_white_space = IGNORE_ALL_SPACE;
+ break;
+
+ case 'x':
+ add_exclude (excluded, optarg, exclude_options ());
+ break;
+
+ case 'X':
+ if (add_exclude_file (add_exclude, excluded, optarg,
+ exclude_options (), '\n'))
+ pfatal_with_name (optarg);
+ break;
+
+ case 'y':
+ specify_style (OUTPUT_SDIFF);
+ break;
+
+ case 'W':
+ numval = strtoumax (optarg, &numend, 10);
+ if (! (0 < numval && numval <= SIZE_MAX) || *numend)
+ try_help ("invalid width `%s'", optarg);
+ if (width != numval)
+ {
+ if (width)
+ fatal ("conflicting width options");
+ width = numval;
+ }
+ break;
+
+ case BINARY_OPTION:
+#if HAVE_SETMODE_DOS
+ binary = true;
+ set_binary_mode (STDOUT_FILENO, true);
+#endif
+ break;
+
+ case FROM_FILE_OPTION:
+ specify_value (&from_file, optarg, "--from-file");
+ break;
+
+ case HELP_OPTION:
+ usage ();
+ check_stdout ();
+ return EXIT_SUCCESS;
+
+ case HORIZON_LINES_OPTION:
+ numval = strtoumax (optarg, &numend, 10);
+ if (*numend)
+ try_help ("invalid horizon length `%s'", optarg);
+ horizon_lines = MAX (horizon_lines, MIN (numval, LIN_MAX));
+ break;
+
+ case IGNORE_FILE_NAME_CASE_OPTION:
+ ignore_file_name_case = true;
+ break;
+
+ case INHIBIT_HUNK_MERGE_OPTION:
+ /* This option is obsolete, but accept it for backward
+ compatibility. */
+ break;
+
+ case LEFT_COLUMN_OPTION:
+ left_column = true;
+ break;
+
+ case LINE_FORMAT_OPTION:
+ specify_style (OUTPUT_IFDEF);
+ for (i = 0; i < sizeof line_format / sizeof *line_format; i++)
+ specify_value (&line_format[i], optarg, "--line-format");
+ break;
+
+ case NO_IGNORE_FILE_NAME_CASE_OPTION:
+ ignore_file_name_case = false;
+ break;
+
+ case NORMAL_OPTION:
+ specify_style (OUTPUT_NORMAL);
+ break;
+
+ case SDIFF_MERGE_ASSIST_OPTION:
+ specify_style (OUTPUT_SDIFF);
+ sdiff_merge_assist = true;
+ break;
+
+ case STRIP_TRAILING_CR_OPTION:
+ strip_trailing_cr = true;
+ break;
+
+ case SUPPRESS_COMMON_LINES_OPTION:
+ suppress_common_lines = true;
+ break;
+
+ case TABSIZE_OPTION:
+ numval = strtoumax (optarg, &numend, 10);
+ if (! (0 < numval && numval <= SIZE_MAX) || *numend)
+ try_help ("invalid tabsize `%s'", optarg);
+ if (tabsize != numval)
+ {
+ if (tabsize)
+ fatal ("conflicting tabsize options");
+ tabsize = numval;
+ }
+ break;
+
+ case TO_FILE_OPTION:
+ specify_value (&to_file, optarg, "--to-file");
+ break;
+
+ case UNCHANGED_LINE_FORMAT_OPTION:
+ case OLD_LINE_FORMAT_OPTION:
+ case NEW_LINE_FORMAT_OPTION:
+ specify_style (OUTPUT_IFDEF);
+ c -= UNCHANGED_LINE_FORMAT_OPTION;
+ specify_value (&line_format[c], optarg, line_format_option[c]);
+ break;
+
+ case UNCHANGED_GROUP_FORMAT_OPTION:
+ case OLD_GROUP_FORMAT_OPTION:
+ case NEW_GROUP_FORMAT_OPTION:
+ case CHANGED_GROUP_FORMAT_OPTION:
+ specify_style (OUTPUT_IFDEF);
+ c -= UNCHANGED_GROUP_FORMAT_OPTION;
+ specify_value (&group_format[c], optarg, group_format_option[c]);
+ break;
+
+ default:
+ try_help (0, 0);
+ }
+ prev = c;
+ }
+
+ if (output_style == OUTPUT_UNSPECIFIED)
+ {
+ if (show_c_function)
+ {
+ specify_style (OUTPUT_CONTEXT);
+ if (ocontext < 0)
+ context = 3;
+ }
+ else
+ specify_style (OUTPUT_NORMAL);
+ }
+
+ if (output_style != OUTPUT_CONTEXT || hard_locale (LC_TIME))
+ {
+#ifdef ST_MTIM_NSEC
+ time_format = "%Y-%m-%d %H:%M:%S.%N %z";
+#else
+ time_format = "%Y-%m-%d %H:%M:%S %z";
+#endif
+ }
+ else
+ {
+ /* See POSIX 1003.1-2001 for this format. */
+ time_format = "%a %b %e %T %Y";
+ }
+
+ if (0 <= ocontext)
+ {
+ bool modern_usage = 200112 <= posix2_version ();
+
+ if ((output_style == OUTPUT_CONTEXT
+ || output_style == OUTPUT_UNIFIED)
+ && (context < ocontext
+ || (ocontext < context && ! explicit_context)))
+ {
+ if (modern_usage)
+ {
+ error (0, 0,
+ _("`-%ld' option is obsolete; use `-%c %ld'"),
+ (long int) ocontext,
+ output_style == OUTPUT_CONTEXT ? 'C' : 'U',
+ (long int) ocontext);
+ try_help (0, 0);
+ }
+ context = ocontext;
+ }
+ else
+ {
+ if (modern_usage)
+ {
+ error (0, 0, _("`-%ld' option is obsolete; omit it"),
+ (long int) ocontext);
+ try_help (0, 0);
+ }
+ }
+ }
+
+ if (! tabsize)
+ tabsize = 8;
+ if (! width)
+ width = 130;
+
+ {
+ /* Maximize first the half line width, and then the gutter width,
+ according to the following constraints:
+
+ 1. Two half lines plus a gutter must fit in a line.
+ 2. If the half line width is nonzero:
+ a. The gutter width is at least GUTTER_WIDTH_MINIMUM.
+ b. If tabs are not expanded to spaces,
+ a half line plus a gutter is an integral number of tabs,
+ so that tabs in the right column line up. */
+
+ intmax_t t = expand_tabs ? 1 : tabsize;
+ intmax_t w = width;
+ intmax_t off = (w + t + GUTTER_WIDTH_MINIMUM) / (2 * t) * t;
+ sdiff_half_width = MAX (0, MIN (off - GUTTER_WIDTH_MINIMUM, w - off)),
+ sdiff_column2_offset = sdiff_half_width ? off : w;
+ }
+
+ /* Make the horizon at least as large as the context, so that
+ shift_boundaries has more freedom to shift the first and last hunks. */
+ if (horizon_lines < context)
+ horizon_lines = context;
+
+ summarize_regexp_list (&function_regexp_list);
+ summarize_regexp_list (&ignore_regexp_list);
+
+ if (output_style == OUTPUT_IFDEF)
+ {
+ for (i = 0; i < sizeof line_format / sizeof *line_format; i++)
+ if (!line_format[i])
+ line_format[i] = "%l\n";
+ if (!group_format[OLD])
+ group_format[OLD]
+ = group_format[CHANGED] ? group_format[CHANGED] : "%<";
+ if (!group_format[NEW])
+ group_format[NEW]
+ = group_format[CHANGED] ? group_format[CHANGED] : "%>";
+ if (!group_format[UNCHANGED])
+ group_format[UNCHANGED] = "%=";
+ if (!group_format[CHANGED])
+ group_format[CHANGED] = concat (group_format[OLD],
+ group_format[NEW], "");
+ }
+
+ no_diff_means_no_output =
+ (output_style == OUTPUT_IFDEF ?
+ (!*group_format[UNCHANGED]
+ || (strcmp (group_format[UNCHANGED], "%=") == 0
+ && !*line_format[UNCHANGED]))
+ : (output_style != OUTPUT_SDIFF) | suppress_common_lines);
+
+ files_can_be_treated_as_binary =
+ (brief & binary
+ & ~ (ignore_blank_lines | ignore_case | strip_trailing_cr
+ | (ignore_regexp_list.regexps || ignore_white_space)));
+
+ switch_string = option_list (argv + 1, optind - 1);
+
+ if (from_file)
+ {
+ if (to_file)
+ fatal ("--from-file and --to-file both specified");
+ else
+ for (; optind < argc; optind++)
+ {
+ int status = compare_files ((struct comparison *) 0,
+ from_file, argv[optind]);
+ if (exit_status < status)
+ exit_status = status;
+ }
+ }
+ else
+ {
+ if (to_file)
+ for (; optind < argc; optind++)
+ {
+ int status = compare_files ((struct comparison *) 0,
+ argv[optind], to_file);
+ if (exit_status < status)
+ exit_status = status;
+ }
+ else
+ {
+ if (argc - optind != 2)
+ {
+ if (argc - optind < 2)
+ try_help ("missing operand after `%s'", argv[argc - 1]);
+ else
+ try_help ("extra operand `%s'", argv[optind + 2]);
+ }
+
+ exit_status = compare_files ((struct comparison *) 0,
+ argv[optind], argv[optind + 1]);
+ }
+ }
+
+ /* Print any messages that were saved up for last. */
+ print_message_queue ();
+
+ check_stdout ();
+ exit (exit_status);
+ return exit_status;
+}
+
+/* Append to REGLIST the regexp PATTERN. */
+
+static void
+add_regexp (struct regexp_list *reglist, char const *pattern)
+{
+ size_t patlen = strlen (pattern);
+ char const *m = re_compile_pattern (pattern, patlen, reglist->buf);
+
+ if (m != 0)
+ error (0, 0, "%s: %s", pattern, m);
+ else
+ {
+ char *regexps = reglist->regexps;
+ size_t len = reglist->len;
+ bool multiple_regexps = reglist->multiple_regexps = regexps != 0;
+ size_t newlen = reglist->len = len + 2 * multiple_regexps + patlen;
+ size_t size = reglist->size;
+
+ if (size <= newlen)
+ {
+ if (!size)
+ size = 1;
+
+ do size *= 2;
+ while (size <= newlen);
+
+ reglist->size = size;
+ reglist->regexps = regexps = xrealloc (regexps, size);
+ }
+ if (multiple_regexps)
+ {
+ regexps[len++] = '\\';
+ regexps[len++] = '|';
+ }
+ memcpy (regexps + len, pattern, patlen + 1);
+ }
+}
+
+/* Ensure that REGLIST represents the disjunction of its regexps.
+ This is done here, rather than earlier, to avoid O(N^2) behavior. */
+
+static void
+summarize_regexp_list (struct regexp_list *reglist)
+{
+ if (reglist->regexps)
+ {
+ /* At least one regexp was specified. Allocate a fastmap for it. */
+ reglist->buf->fastmap = xmalloc (1 << CHAR_BIT);
+ if (reglist->multiple_regexps)
+ {
+ /* Compile the disjunction of the regexps.
+ (If just one regexp was specified, it is already compiled.) */
+ char const *m = re_compile_pattern (reglist->regexps, reglist->len,
+ reglist->buf);
+ if (m != 0)
+ error (EXIT_TROUBLE, 0, "%s: %s", reglist->regexps, m);
+ }
+ }
+}
+
+static void
+try_help (char const *reason_msgid, char const *operand)
+{
+ if (reason_msgid)
+ error (0, 0, _(reason_msgid), operand);
+ error (EXIT_TROUBLE, 0, _("Try `%s --help' for more information."),
+ program_name);
+ abort ();
+}
+
+static void
+check_stdout (void)
+{
+ if (ferror (stdout))
+ fatal ("write failed");
+ else if (fclose (stdout) != 0)
+ pfatal_with_name (_("standard output"));
+}
+
+static char const * const option_help_msgid[] = {
+ N_("Compare files line by line."),
+ "",
+ N_("-i --ignore-case Ignore case differences in file contents."),
+ N_("--ignore-file-name-case Ignore case when comparing file names."),
+ N_("--no-ignore-file-name-case Consider case when comparing file names."),
+ N_("-E --ignore-tab-expansion Ignore changes due to tab expansion."),
+ N_("-b --ignore-space-change Ignore changes in the amount of white space."),
+ N_("-w --ignore-all-space Ignore all white space."),
+ N_("-B --ignore-blank-lines Ignore changes whose lines are all blank."),
+ N_("-I RE --ignore-matching-lines=RE Ignore changes whose lines all match RE."),
+ N_("--strip-trailing-cr Strip trailing carriage return on input."),
+#if HAVE_SETMODE_DOS
+ N_("--binary Read and write data in binary mode."),
+#endif
+ N_("-a --text Treat all files as text."),
+ "",
+ N_("-c -C NUM --context[=NUM] Output NUM (default 3) lines of copied context.\n\
+-u -U NUM --unified[=NUM] Output NUM (default 3) lines of unified context.\n\
+ --label LABEL Use LABEL instead of file name.\n\
+ -p --show-c-function Show which C function each change is in.\n\
+ -F RE --show-function-line=RE Show the most recent line matching RE."),
+ N_("-q --brief Output only whether files differ."),
+ N_("-e --ed Output an ed script."),
+ N_("--normal Output a normal diff."),
+ N_("-n --rcs Output an RCS format diff."),
+ N_("-y --side-by-side Output in two columns.\n\
+ -W NUM --width=NUM Output at most NUM (default 130) print columns.\n\
+ --left-column Output only the left column of common lines.\n\
+ --suppress-common-lines Do not output common lines."),
+ N_("-D NAME --ifdef=NAME Output merged file to show `#ifdef NAME' diffs."),
+ N_("--GTYPE-group-format=GFMT Similar, but format GTYPE input groups with GFMT."),
+ N_("--line-format=LFMT Similar, but format all input lines with LFMT."),
+ N_("--LTYPE-line-format=LFMT Similar, but format LTYPE input lines with LFMT."),
+ N_(" LTYPE is `old', `new', or `unchanged'. GTYPE is LTYPE or `changed'."),
+ N_(" GFMT may contain:\n\
+ %< lines from FILE1\n\
+ %> lines from FILE2\n\
+ %= lines common to FILE1 and FILE2\n\
+ %[-][WIDTH][.[PREC]]{doxX}LETTER printf-style spec for LETTER\n\
+ LETTERs are as follows for new group, lower case for old group:\n\
+ F first line number\n\
+ L last line number\n\
+ N number of lines = L-F+1\n\
+ E F-1\n\
+ M L+1"),
+ N_(" LFMT may contain:\n\
+ %L contents of line\n\
+ %l contents of line, excluding any trailing newline\n\
+ %[-][WIDTH][.[PREC]]{doxX}n printf-style spec for input line number"),
+ N_(" Either GFMT or LFMT may contain:\n\
+ %% %\n\
+ %c'C' the single character C\n\
+ %c'\\OOO' the character with octal code OOO"),
+ "",
+ N_("-l --paginate Pass the output through `pr' to paginate it."),
+ N_("-t --expand-tabs Expand tabs to spaces in output."),
+ N_("-T --initial-tab Make tabs line up by prepending a tab."),
+ N_("--tabsize=NUM Tab stops are every NUM (default 8) print columns."),
+ "",
+ N_("-r --recursive Recursively compare any subdirectories found."),
+ N_("-N --new-file Treat absent files as empty."),
+ N_("--unidirectional-new-file Treat absent first files as empty."),
+ N_("-s --report-identical-files Report when two files are the same."),
+ N_("-x PAT --exclude=PAT Exclude files that match PAT."),
+ N_("-X FILE --exclude-from=FILE Exclude files that match any pattern in FILE."),
+ N_("-S FILE --starting-file=FILE Start with FILE when comparing directories."),
+ N_("--from-file=FILE1 Compare FILE1 to all operands. FILE1 can be a directory."),
+ N_("--to-file=FILE2 Compare all operands to FILE2. FILE2 can be a directory."),
+ "",
+ N_("--horizon-lines=NUM Keep NUM lines of the common prefix and suffix."),
+ N_("-d --minimal Try hard to find a smaller set of changes."),
+ N_("--speed-large-files Assume large files and many scattered small changes."),
+ "",
+ N_("-v --version Output version info."),
+ N_("--help Output this help."),
+ "",
+ N_("FILES are `FILE1 FILE2' or `DIR1 DIR2' or `DIR FILE...' or `FILE... DIR'."),
+ N_("If --from-file or --to-file is given, there are no restrictions on FILES."),
+ N_("If a FILE is `-', read standard input."),
+ N_("Exit status is 0 if inputs are the same, 1 if different, 2 if trouble."),
+ "",
+ N_("Report bugs to <bug-gnu-utils@gnu.org>."),
+ 0
+};
+
+static void
+usage (void)
+{
+ char const * const *p;
+
+ printf (_("Usage: %s [OPTION]... FILES\n"), program_name);
+
+ for (p = option_help_msgid; *p; p++)
+ {
+ if (!**p)
+ putchar ('\n');
+ else
+ {
+ char const *msg = _(*p);
+ char const *nl;
+ while ((nl = strchr (msg, '\n')))
+ {
+ int msglen = nl + 1 - msg;
+ printf (" %.*s", msglen, msg);
+ msg = nl + 1;
+ }
+
+ printf (" %s\n" + 2 * (*msg != ' ' && *msg != '-'), msg);
+ }
+ }
+}
+
+/* Set VAR to VALUE, reporting an OPTION error if this is a
+ conflict. */
+static void
+specify_value (char const **var, char const *value, char const *option)
+{
+ if (*var && strcmp (*var, value) != 0)
+ {
+ error (0, 0, _("conflicting %s option value `%s'"), option, value);
+ try_help (0, 0);
+ }
+ *var = value;
+}
+
+/* Set the output style to STYLE, diagnosing conflicts. */
+static void
+specify_style (enum output_style style)
+{
+ if (output_style != style)
+ {
+ if (output_style != OUTPUT_UNSPECIFIED)
+ try_help ("conflicting output style options", 0);
+ output_style = style;
+ }
+}
+
+/* Set the last-modified time of *ST to be the current time. */
+
+static void
+set_mtime_to_now (struct stat *st)
+{
+#ifdef ST_MTIM_NSEC
+
+# if HAVE_CLOCK_GETTIME && defined CLOCK_REALTIME
+ if (clock_gettime (CLOCK_REALTIME, &st->st_mtim) == 0)
+ return;
+# endif
+
+# if HAVE_GETTIMEOFDAY
+ {
+ struct timeval timeval;
+ if (gettimeofday (&timeval, 0) == 0)
+ {
+ st->st_mtime = timeval.tv_sec;
+ st->st_mtim.ST_MTIM_NSEC = timeval.tv_usec * 1000;
+ return;
+ }
+ }
+# endif
+
+#endif /* ST_MTIM_NSEC */
+
+ time (&st->st_mtime);
+}
+
+/* Compare two files (or dirs) with parent comparison PARENT
+ and names NAME0 and NAME1.
+ (If PARENT is 0, then the first name is just NAME0, etc.)
+ This is self-contained; it opens the files and closes them.
+
+ Value is EXIT_SUCCESS if files are the same, EXIT_FAILURE if
+ different, EXIT_TROUBLE if there is a problem opening them. */
+
+static int
+compare_files (struct comparison const *parent,
+ char const *name0,
+ char const *name1)
+{
+ struct comparison cmp;
+#define DIR_P(f) (S_ISDIR (cmp.file[f].stat.st_mode) != 0)
+ register int f;
+ int status = EXIT_SUCCESS;
+ bool same_files;
+ char *free0, *free1;
+
+ /* If this is directory comparison, perhaps we have a file
+ that exists only in one of the directories.
+ If so, just print a message to that effect. */
+
+ if (! ((name0 && name1)
+ || (unidirectional_new_file && name1)
+ || new_file))
+ {
+ char const *name = name0 == 0 ? name1 : name0;
+ char const *dir = parent->file[name0 == 0].name;
+
+ /* See POSIX 1003.1-2001 for this format. */
+ message ("Only in %s: %s\n", dir, name);
+
+ /* Return EXIT_FAILURE so that diff_dirs will return
+ EXIT_FAILURE ("some files differ"). */
+ return EXIT_FAILURE;
+ }
+
+ memset (cmp.file, 0, sizeof cmp.file);
+ cmp.parent = parent;
+
+ /* cmp.file[f].desc markers */
+#define NONEXISTENT (-1) /* nonexistent file */
+#define UNOPENED (-2) /* unopened file (e.g. directory) */
+#define ERRNO_ENCODE(errno) (-3 - (errno)) /* encoded errno value */
+
+#define ERRNO_DECODE(desc) (-3 - (desc)) /* inverse of ERRNO_ENCODE */
+
+ cmp.file[0].desc = name0 == 0 ? NONEXISTENT : UNOPENED;
+ cmp.file[1].desc = name1 == 0 ? NONEXISTENT : UNOPENED;
+
+ /* Now record the full name of each file, including nonexistent ones. */
+
+ if (name0 == 0)
+ name0 = name1;
+ if (name1 == 0)
+ name1 = name0;
+
+ if (!parent)
+ {
+ free0 = 0;
+ free1 = 0;
+ cmp.file[0].name = name0;
+ cmp.file[1].name = name1;
+ }
+ else
+ {
+ cmp.file[0].name = free0
+ = dir_file_pathname (parent->file[0].name, name0);
+ cmp.file[1].name = free1
+ = dir_file_pathname (parent->file[1].name, name1);
+ }
+
+ /* Stat the files. */
+
+ for (f = 0; f < 2; f++)
+ {
+ if (cmp.file[f].desc != NONEXISTENT)
+ {
+ if (f && file_name_cmp (cmp.file[f].name, cmp.file[0].name) == 0)
+ {
+ cmp.file[f].desc = cmp.file[0].desc;
+ cmp.file[f].stat = cmp.file[0].stat;
+ }
+ else if (strcmp (cmp.file[f].name, "-") == 0)
+ {
+ cmp.file[f].desc = STDIN_FILENO;
+ if (fstat (STDIN_FILENO, &cmp.file[f].stat) != 0)
+ cmp.file[f].desc = ERRNO_ENCODE (errno);
+ else
+ {
+ if (S_ISREG (cmp.file[f].stat.st_mode))
+ {
+ off_t pos = lseek (STDIN_FILENO, (off_t) 0, SEEK_CUR);
+ if (pos < 0)
+ cmp.file[f].desc = ERRNO_ENCODE (errno);
+ else
+ cmp.file[f].stat.st_size =
+ MAX (0, cmp.file[f].stat.st_size - pos);
+ }
+
+ /* POSIX 1003.1-2001 requires current time for
+ stdin. */
+ set_mtime_to_now (&cmp.file[f].stat);
+ }
+ }
+ else if (stat (cmp.file[f].name, &cmp.file[f].stat) != 0)
+ cmp.file[f].desc = ERRNO_ENCODE (errno);
+ }
+ }
+
+ /* Mark files as nonexistent as needed for -N and -P, if they are
+ inaccessible empty regular files (the kind of files that 'patch'
+ creates to indicate nonexistent backups), or if they are
+ top-level files that do not exist but their counterparts do
+ exist. */
+ for (f = 0; f < 2; f++)
+ if ((new_file || (f == 0 && unidirectional_new_file))
+ && (cmp.file[f].desc == UNOPENED
+ ? (S_ISREG (cmp.file[f].stat.st_mode)
+ && ! (cmp.file[f].stat.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO))
+ && cmp.file[f].stat.st_size == 0)
+ : (cmp.file[f].desc == ERRNO_ENCODE (ENOENT)
+ && ! parent
+ && cmp.file[1 - f].desc == UNOPENED)))
+ cmp.file[f].desc = NONEXISTENT;
+
+ for (f = 0; f < 2; f++)
+ if (cmp.file[f].desc == NONEXISTENT)
+ {
+ memset (&cmp.file[f].stat, 0, sizeof cmp.file[f].stat);
+ cmp.file[f].stat.st_mode = cmp.file[1 - f].stat.st_mode;
+ }
+
+ for (f = 0; f < 2; f++)
+ {
+ int e = ERRNO_DECODE (cmp.file[f].desc);
+ if (0 <= e)
+ {
+ errno = e;
+ perror_with_name (cmp.file[f].name);
+ status = EXIT_TROUBLE;
+ }
+ }
+
+ if (status == EXIT_SUCCESS && ! parent && DIR_P (0) != DIR_P (1))
+ {
+ /* If one is a directory, and it was specified in the command line,
+ use the file in that dir with the other file's basename. */
+
+ int fnm_arg = DIR_P (0);
+ int dir_arg = 1 - fnm_arg;
+ char const *fnm = cmp.file[fnm_arg].name;
+ char const *dir = cmp.file[dir_arg].name;
+ char const *filename = cmp.file[dir_arg].name = free0
+ = dir_file_pathname (dir, base_name (fnm));
+
+ if (strcmp (fnm, "-") == 0)
+ fatal ("cannot compare `-' to a directory");
+
+ if (stat (filename, &cmp.file[dir_arg].stat) != 0)
+ {
+ perror_with_name (filename);
+ status = EXIT_TROUBLE;
+ }
+ }
+
+ if (status != EXIT_SUCCESS)
+ {
+ /* One of the files should exist but does not. */
+ }
+ else if (cmp.file[0].desc == NONEXISTENT
+ && cmp.file[1].desc == NONEXISTENT)
+ {
+ /* Neither file "exists", so there's nothing to compare. */
+ }
+ else if ((same_files
+ = (cmp.file[0].desc != NONEXISTENT
+ && cmp.file[1].desc != NONEXISTENT
+ && 0 < same_file (&cmp.file[0].stat, &cmp.file[1].stat)
+ && same_file_attributes (&cmp.file[0].stat,
+ &cmp.file[1].stat)))
+ && no_diff_means_no_output)
+ {
+ /* The two named files are actually the same physical file.
+ We know they are identical without actually reading them. */
+ }
+ else if (DIR_P (0) & DIR_P (1))
+ {
+ if (output_style == OUTPUT_IFDEF)
+ fatal ("-D option not supported with directories");
+
+ /* If both are directories, compare the files in them. */
+
+ if (parent && !recursive)
+ {
+ /* But don't compare dir contents one level down
+ unless -r was specified.
+ See POSIX 1003.1-2001 for this format. */
+ message ("Common subdirectories: %s and %s\n",
+ cmp.file[0].name, cmp.file[1].name);
+ }
+ else
+ status = diff_dirs (&cmp, compare_files);
+ }
+ else if ((DIR_P (0) | DIR_P (1))
+ || (parent
+ && (! S_ISREG (cmp.file[0].stat.st_mode)
+ || ! S_ISREG (cmp.file[1].stat.st_mode))))
+ {
+ if (cmp.file[0].desc == NONEXISTENT || cmp.file[1].desc == NONEXISTENT)
+ {
+ /* We have a subdirectory that exists only in one directory. */
+
+ if ((DIR_P (0) | DIR_P (1))
+ && recursive
+ && (new_file
+ || (unidirectional_new_file
+ && cmp.file[0].desc == NONEXISTENT)))
+ status = diff_dirs (&cmp, compare_files);
+ else
+ {
+ char const *dir
+ = parent->file[cmp.file[0].desc == NONEXISTENT].name;
+
+ /* See POSIX 1003.1-2001 for this format. */
+ message ("Only in %s: %s\n", dir, name0);
+
+ status = EXIT_FAILURE;
+ }
+ }
+ else
+ {
+ /* We have two files that are not to be compared. */
+
+ /* See POSIX 1003.1-2001 for this format. */
+ message5 ("File %s is a %s while file %s is a %s\n",
+ file_label[0] ? file_label[0] : cmp.file[0].name,
+ file_type (&cmp.file[0].stat),
+ file_label[1] ? file_label[1] : cmp.file[1].name,
+ file_type (&cmp.file[1].stat));
+
+ /* This is a difference. */
+ status = EXIT_FAILURE;
+ }
+ }
+ else if (files_can_be_treated_as_binary
+ && S_ISREG (cmp.file[0].stat.st_mode)
+ && S_ISREG (cmp.file[1].stat.st_mode)
+ && cmp.file[0].stat.st_size != cmp.file[1].stat.st_size)
+ {
+ message ("Files %s and %s differ\n",
+ file_label[0] ? file_label[0] : cmp.file[0].name,
+ file_label[1] ? file_label[1] : cmp.file[1].name);
+ status = EXIT_FAILURE;
+ }
+ else
+ {
+ /* Both exist and neither is a directory. */
+
+ /* Open the files and record their descriptors. */
+
+ if (cmp.file[0].desc == UNOPENED)
+ if ((cmp.file[0].desc = open (cmp.file[0].name, O_RDONLY, 0)) < 0)
+ {
+ perror_with_name (cmp.file[0].name);
+ status = EXIT_TROUBLE;
+ }
+ if (cmp.file[1].desc == UNOPENED)
+ {
+ if (same_files)
+ cmp.file[1].desc = cmp.file[0].desc;
+ else if ((cmp.file[1].desc = open (cmp.file[1].name, O_RDONLY, 0))
+ < 0)
+ {
+ perror_with_name (cmp.file[1].name);
+ status = EXIT_TROUBLE;
+ }
+ }
+
+#if HAVE_SETMODE_DOS
+ if (binary)
+ for (f = 0; f < 2; f++)
+ if (0 <= cmp.file[f].desc)
+ set_binary_mode (cmp.file[f].desc, true);
+#endif
+
+ /* Compare the files, if no error was found. */
+
+ if (status == EXIT_SUCCESS)
+ status = diff_2_files (&cmp);
+
+ /* Close the file descriptors. */
+
+ if (0 <= cmp.file[0].desc && close (cmp.file[0].desc) != 0)
+ {
+ perror_with_name (cmp.file[0].name);
+ status = EXIT_TROUBLE;
+ }
+ if (0 <= cmp.file[1].desc && cmp.file[0].desc != cmp.file[1].desc
+ && close (cmp.file[1].desc) != 0)
+ {
+ perror_with_name (cmp.file[1].name);
+ status = EXIT_TROUBLE;
+ }
+ }
+
+ /* Now the comparison has been done, if no error prevented it,
+ and STATUS is the value this function will return. */
+
+ if (status == EXIT_SUCCESS)
+ {
+ if (report_identical_files && !DIR_P (0))
+ message ("Files %s and %s are identical\n",
+ file_label[0] ? file_label[0] : cmp.file[0].name,
+ file_label[1] ? file_label[1] : cmp.file[1].name);
+ }
+ else
+ {
+ /* Flush stdout so that the user sees differences immediately.
+ This can hurt performance, unfortunately. */
+ if (fflush (stdout) != 0)
+ pfatal_with_name (_("standard output"));
+ }
+
+ if (free0)
+ free (free0);
+ if (free1)
+ free (free1);
+
+ return status;
+}
diff --git a/contrib/diff/src/diff.h b/contrib/diff/src/diff.h
new file mode 100644
index 0000000..e7a4b2d
--- /dev/null
+++ b/contrib/diff/src/diff.h
@@ -0,0 +1,375 @@
+/* Shared definitions for GNU DIFF
+
+ Copyright (C) 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1998, 2001,
+ 2002, 2004 Free Software Foundation, Inc.
+
+ This file is part of GNU DIFF.
+
+ GNU DIFF 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.
+
+ GNU DIFF is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "system.h"
+#include <regex.h>
+#include <stdio.h>
+#include <unlocked-io.h>
+
+/* What kind of changes a hunk contains. */
+enum changes
+{
+ /* No changes: lines common to both files. */
+ UNCHANGED,
+
+ /* Deletes only: lines taken from just the first file. */
+ OLD,
+
+ /* Inserts only: lines taken from just the second file. */
+ NEW,
+
+ /* Both deletes and inserts: a hunk containing both old and new lines. */
+ CHANGED
+};
+
+/* Variables for command line options */
+
+#ifndef GDIFF_MAIN
+# define XTERN extern
+#else
+# define XTERN
+#endif
+
+enum output_style
+{
+ /* No output style specified. */
+ OUTPUT_UNSPECIFIED,
+
+ /* Default output style. */
+ OUTPUT_NORMAL,
+
+ /* Output the differences with lines of context before and after (-c). */
+ OUTPUT_CONTEXT,
+
+ /* Output the differences in a unified context diff format (-u). */
+ OUTPUT_UNIFIED,
+
+ /* Output the differences as commands suitable for `ed' (-e). */
+ OUTPUT_ED,
+
+ /* Output the diff as a forward ed script (-f). */
+ OUTPUT_FORWARD_ED,
+
+ /* Like -f, but output a count of changed lines in each "command" (-n). */
+ OUTPUT_RCS,
+
+ /* Output merged #ifdef'd file (-D). */
+ OUTPUT_IFDEF,
+
+ /* Output sdiff style (-y). */
+ OUTPUT_SDIFF
+};
+
+/* True for output styles that are robust,
+ i.e. can handle a file that ends in a non-newline. */
+#define ROBUST_OUTPUT_STYLE(S) ((S) != OUTPUT_ED && (S) != OUTPUT_FORWARD_ED)
+
+XTERN enum output_style output_style;
+
+/* Nonzero if output cannot be generated for identical files. */
+XTERN bool no_diff_means_no_output;
+
+/* Number of lines of context to show in each set of diffs.
+ This is zero when context is not to be shown. */
+XTERN lin context;
+
+/* Consider all files as text files (-a).
+ Don't interpret codes over 0177 as implying a "binary file". */
+XTERN bool text;
+
+/* Number of lines to keep in identical prefix and suffix. */
+XTERN lin horizon_lines;
+
+/* The significance of white space during comparisons. */
+XTERN enum
+{
+ /* All white space is significant (the default). */
+ IGNORE_NO_WHITE_SPACE,
+
+ /* Ignore changes due to tab expansion (-E). */
+ IGNORE_TAB_EXPANSION,
+
+ /* Ignore changes in horizontal white space (-b). */
+ IGNORE_SPACE_CHANGE,
+
+ /* Ignore all horizontal white space (-w). */
+ IGNORE_ALL_SPACE
+} ignore_white_space;
+
+/* Ignore changes that affect only blank lines (-B). */
+XTERN bool ignore_blank_lines;
+
+/* Files can be compared byte-by-byte, as if they were binary.
+ This depends on various options. */
+XTERN bool files_can_be_treated_as_binary;
+
+/* Ignore differences in case of letters (-i). */
+XTERN bool ignore_case;
+
+/* Ignore differences in case of letters in file names. */
+XTERN bool ignore_file_name_case;
+
+/* File labels for `-c' output headers (--label). */
+XTERN char *file_label[2];
+
+/* Regexp to identify function-header lines (-F). */
+XTERN struct re_pattern_buffer function_regexp;
+
+/* Ignore changes that affect only lines matching this regexp (-I). */
+XTERN struct re_pattern_buffer ignore_regexp;
+
+/* Say only whether files differ, not how (-q). */
+XTERN bool brief;
+
+/* Expand tabs in the output so the text lines up properly
+ despite the characters added to the front of each line (-t). */
+XTERN bool expand_tabs;
+
+/* Number of columns between tab stops. */
+XTERN size_t tabsize;
+
+/* Use a tab in the output, rather than a space, before the text of an
+ input line, so as to keep the proper alignment in the input line
+ without changing the characters in it (-T). */
+XTERN bool initial_tab;
+
+/* Remove trailing carriage returns from input. */
+XTERN bool strip_trailing_cr;
+
+/* In directory comparison, specify file to start with (-S).
+ This is used for resuming an aborted comparison.
+ All file names less than this name are ignored. */
+XTERN char const *starting_file;
+
+/* Pipe each file's output through pr (-l). */
+XTERN bool paginate;
+
+/* Line group formats for unchanged, old, new, and changed groups. */
+XTERN char const *group_format[CHANGED + 1];
+
+/* Line formats for unchanged, old, and new lines. */
+XTERN char const *line_format[NEW + 1];
+
+/* If using OUTPUT_SDIFF print extra information to help the sdiff filter. */
+XTERN bool sdiff_merge_assist;
+
+/* Tell OUTPUT_SDIFF to show only the left version of common lines. */
+XTERN bool left_column;
+
+/* Tell OUTPUT_SDIFF to not show common lines. */
+XTERN bool suppress_common_lines;
+
+/* The half line width and column 2 offset for OUTPUT_SDIFF. */
+XTERN size_t sdiff_half_width;
+XTERN size_t sdiff_column2_offset;
+
+/* String containing all the command options diff received,
+ with spaces between and at the beginning but none at the end.
+ If there were no options given, this string is empty. */
+XTERN char *switch_string;
+
+/* Use heuristics for better speed with large files with a small
+ density of changes. */
+XTERN bool speed_large_files;
+
+/* Patterns that match file names to be excluded. */
+XTERN struct exclude *excluded;
+
+/* Don't discard lines. This makes things slower (sometimes much
+ slower) but will find a guaranteed minimal set of changes. */
+XTERN bool minimal;
+
+/* Name of program the user invoked (for error messages). */
+XTERN char *program_name;
+
+/* The strftime format to use for time strings. */
+XTERN char const *time_format;
+
+/* The result of comparison is an "edit script": a chain of `struct change'.
+ Each `struct change' represents one place where some lines are deleted
+ and some are inserted.
+
+ LINE0 and LINE1 are the first affected lines in the two files (origin 0).
+ DELETED is the number of lines deleted here from file 0.
+ INSERTED is the number of lines inserted here in file 1.
+
+ If DELETED is 0 then LINE0 is the number of the line before
+ which the insertion was done; vice versa for INSERTED and LINE1. */
+
+struct change
+{
+ struct change *link; /* Previous or next edit command */
+ lin inserted; /* # lines of file 1 changed here. */
+ lin deleted; /* # lines of file 0 changed here. */
+ lin line0; /* Line number of 1st deleted line. */
+ lin line1; /* Line number of 1st inserted line. */
+ bool ignore; /* Flag used in context.c. */
+};
+
+/* Structures that describe the input files. */
+
+/* Data on one input file being compared. */
+
+struct file_data {
+ int desc; /* File descriptor */
+ char const *name; /* File name */
+ struct stat stat; /* File status */
+
+ /* Buffer in which text of file is read. */
+ word *buffer;
+
+ /* Allocated size of buffer, in bytes. Always a multiple of
+ sizeof *buffer. */
+ size_t bufsize;
+
+ /* Number of valid bytes now in the buffer. */
+ size_t buffered;
+
+ /* Array of pointers to lines in the file. */
+ char const **linbuf;
+
+ /* linbuf_base <= buffered_lines <= valid_lines <= alloc_lines.
+ linebuf[linbuf_base ... buffered_lines - 1] are possibly differing.
+ linebuf[linbuf_base ... valid_lines - 1] contain valid data.
+ linebuf[linbuf_base ... alloc_lines - 1] are allocated. */
+ lin linbuf_base, buffered_lines, valid_lines, alloc_lines;
+
+ /* Pointer to end of prefix of this file to ignore when hashing. */
+ char const *prefix_end;
+
+ /* Count of lines in the prefix.
+ There are this many lines in the file before linbuf[0]. */
+ lin prefix_lines;
+
+ /* Pointer to start of suffix of this file to ignore when hashing. */
+ char const *suffix_begin;
+
+ /* Vector, indexed by line number, containing an equivalence code for
+ each line. It is this vector that is actually compared with that
+ of another file to generate differences. */
+ lin *equivs;
+
+ /* Vector, like the previous one except that
+ the elements for discarded lines have been squeezed out. */
+ lin *undiscarded;
+
+ /* Vector mapping virtual line numbers (not counting discarded lines)
+ to real ones (counting those lines). Both are origin-0. */
+ lin *realindexes;
+
+ /* Total number of nondiscarded lines. */
+ lin nondiscarded_lines;
+
+ /* Vector, indexed by real origin-0 line number,
+ containing 1 for a line that is an insertion or a deletion.
+ The results of comparison are stored here. */
+ char *changed;
+
+ /* 1 if file ends in a line with no final newline. */
+ bool missing_newline;
+
+ /* 1 if at end of file. */
+ bool eof;
+
+ /* 1 more than the maximum equivalence value used for this or its
+ sibling file. */
+ lin equiv_max;
+};
+
+/* The file buffer, considered as an array of bytes rather than
+ as an array of words. */
+#define FILE_BUFFER(f) ((char *) (f)->buffer)
+
+/* Data on two input files being compared. */
+
+struct comparison
+ {
+ struct file_data file[2];
+ struct comparison const *parent; /* parent, if a recursive comparison */
+ };
+
+/* Describe the two files currently being compared. */
+
+XTERN struct file_data files[2];
+
+/* Stdio stream to output diffs to. */
+
+XTERN FILE *outfile;
+
+/* Declare various functions. */
+
+/* analyze.c */
+int diff_2_files (struct comparison *);
+
+/* context.c */
+void print_context_header (struct file_data[], bool);
+void print_context_script (struct change *, bool);
+
+/* dir.c */
+int diff_dirs (struct comparison const *, int (*) (struct comparison const *, char const *, char const *));
+
+/* ed.c */
+void print_ed_script (struct change *);
+void pr_forward_ed_script (struct change *);
+
+/* ifdef.c */
+void print_ifdef_script (struct change *);
+
+/* io.c */
+void file_block_read (struct file_data *, size_t);
+bool read_files (struct file_data[], bool);
+
+/* normal.c */
+void print_normal_script (struct change *);
+
+/* rcs.c */
+void print_rcs_script (struct change *);
+
+/* side.c */
+void print_sdiff_script (struct change *);
+
+/* util.c */
+extern char const change_letter[4];
+extern char const pr_program[];
+char *concat (char const *, char const *, char const *);
+char *dir_file_pathname (char const *, char const *);
+bool lines_differ (char const *, char const *);
+lin translate_line_number (struct file_data const *, lin);
+struct change *find_change (struct change *);
+struct change *find_reverse_change (struct change *);
+void *zalloc (size_t);
+enum changes analyze_hunk (struct change *, lin *, lin *, lin *, lin *);
+void begin_output (void);
+void debug_script (struct change *);
+void fatal (char const *) __attribute__((noreturn));
+void finish_output (void);
+void message (char const *, char const *, char const *);
+void message5 (char const *, char const *, char const *, char const *, char const *);
+void output_1_line (char const *, char const *, char const *, char const *);
+void perror_with_name (char const *);
+void pfatal_with_name (char const *) __attribute__((noreturn));
+void print_1_line (char const *, char const * const *);
+void print_message_queue (void);
+void print_number_range (char, struct file_data *, lin, lin);
+void print_script (struct change *, struct change * (*) (struct change *), void (*) (struct change *));
+void setup_output (char const *, char const *, bool);
+void translate_range (struct file_data const *, lin, lin, long int *, long int *);
diff --git a/contrib/diff/src/diff3.c b/contrib/diff/src/diff3.c
new file mode 100644
index 0000000..261eeab
--- /dev/null
+++ b/contrib/diff/src/diff3.c
@@ -0,0 +1,1744 @@
+/* diff3 - compare three files line by line
+
+ Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1998, 2001,
+ 2002, 2004 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; see the file COPYING.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "system.h"
+#include "paths.h"
+
+#include <stdio.h>
+#include <unlocked-io.h>
+
+#include <c-stack.h>
+#include <cmpbuf.h>
+#include <error.h>
+#include <exitfail.h>
+#include <file-type.h>
+#include <getopt.h>
+#include <inttostr.h>
+#include <quotesys.h>
+#include <version-etc.h>
+#include <xalloc.h>
+
+/* Internal data structures and macros for the diff3 program; includes
+ data structures for both diff3 diffs and normal diffs. */
+
+/* Different files within a three way diff. */
+#define FILE0 0
+#define FILE1 1
+#define FILE2 2
+
+/* A three way diff is built from two two-way diffs; the file which
+ the two two-way diffs share is: */
+#define FILEC FILE2
+
+/* Different files within a two way diff.
+ FC is the common file, FO the other file. */
+#define FO 0
+#define FC 1
+
+/* The ranges are indexed by */
+#define RANGE_START 0
+#define RANGE_END 1
+
+enum diff_type {
+ ERROR, /* Should not be used */
+ ADD, /* Two way diff add */
+ CHANGE, /* Two way diff change */
+ DELETE, /* Two way diff delete */
+ DIFF_ALL, /* All three are different */
+ DIFF_1ST, /* Only the first is different */
+ DIFF_2ND, /* Only the second */
+ DIFF_3RD /* Only the third */
+};
+
+/* Two way diff */
+struct diff_block {
+ lin ranges[2][2]; /* Ranges are inclusive */
+ char **lines[2]; /* The actual lines (may contain nulls) */
+ size_t *lengths[2]; /* Line lengths (including newlines, if any) */
+ struct diff_block *next;
+};
+
+/* Three way diff */
+
+struct diff3_block {
+ enum diff_type correspond; /* Type of diff */
+ lin ranges[3][2]; /* Ranges are inclusive */
+ char **lines[3]; /* The actual lines (may contain nulls) */
+ size_t *lengths[3]; /* Line lengths (including newlines, if any) */
+ struct diff3_block *next;
+};
+
+/* Access the ranges on a diff block. */
+#define D_LOWLINE(diff, filenum) \
+ ((diff)->ranges[filenum][RANGE_START])
+#define D_HIGHLINE(diff, filenum) \
+ ((diff)->ranges[filenum][RANGE_END])
+#define D_NUMLINES(diff, filenum) \
+ (D_HIGHLINE (diff, filenum) - D_LOWLINE (diff, filenum) + 1)
+
+/* Access the line numbers in a file in a diff by relative line
+ numbers (i.e. line number within the diff itself). Note that these
+ are lvalues and can be used for assignment. */
+#define D_RELNUM(diff, filenum, linenum) \
+ ((diff)->lines[filenum][linenum])
+#define D_RELLEN(diff, filenum, linenum) \
+ ((diff)->lengths[filenum][linenum])
+
+/* And get at them directly, when that should be necessary. */
+#define D_LINEARRAY(diff, filenum) \
+ ((diff)->lines[filenum])
+#define D_LENARRAY(diff, filenum) \
+ ((diff)->lengths[filenum])
+
+/* Next block. */
+#define D_NEXT(diff) ((diff)->next)
+
+/* Access the type of a diff3 block. */
+#define D3_TYPE(diff) ((diff)->correspond)
+
+/* Line mappings based on diffs. The first maps off the top of the
+ diff, the second off of the bottom. */
+#define D_HIGH_MAPLINE(diff, fromfile, tofile, linenum) \
+ ((linenum) \
+ - D_HIGHLINE ((diff), (fromfile)) \
+ + D_HIGHLINE ((diff), (tofile)))
+
+#define D_LOW_MAPLINE(diff, fromfile, tofile, linenum) \
+ ((linenum) \
+ - D_LOWLINE ((diff), (fromfile)) \
+ + D_LOWLINE ((diff), (tofile)))
+
+/* Options variables for flags set on command line. */
+
+/* If nonzero, treat all files as text files, never as binary. */
+static bool text;
+
+/* Remove trailing carriage returns from input. */
+static bool strip_trailing_cr;
+
+/* If nonzero, write out an ed script instead of the standard diff3 format. */
+static bool edscript;
+
+/* If nonzero, in the case of overlapping diffs (type DIFF_ALL),
+ preserve the lines which would normally be deleted from
+ file 1 with a special flagging mechanism. */
+static bool flagging;
+
+/* Use a tab to align output lines (-T). */
+static bool initial_tab;
+
+/* If nonzero, do not output information for overlapping diffs. */
+static bool simple_only;
+
+/* If nonzero, do not output information for non-overlapping diffs. */
+static bool overlap_only;
+
+/* If nonzero, show information for DIFF_2ND diffs. */
+static bool show_2nd;
+
+/* If nonzero, include `:wq' at the end of the script
+ to write out the file being edited. */
+static bool finalwrite;
+
+/* If nonzero, output a merged file. */
+static bool merge;
+
+char *program_name;
+
+static char *read_diff (char const *, char const *, char **);
+static char *scan_diff_line (char *, char **, size_t *, char *, char);
+static enum diff_type process_diff_control (char **, struct diff_block *);
+static bool compare_line_list (char * const[], size_t const[], char * const[], size_t const[], lin);
+static bool copy_stringlist (char * const[], size_t const[], char *[], size_t[], lin);
+static bool output_diff3_edscript (FILE *, struct diff3_block *, int const[3], int const[3], char const *, char const *, char const *);
+static bool output_diff3_merge (FILE *, FILE *, struct diff3_block *, int const[3], int const[3], char const *, char const *, char const *);
+static struct diff3_block *create_diff3_block (lin, lin, lin, lin, lin, lin);
+static struct diff3_block *make_3way_diff (struct diff_block *, struct diff_block *);
+static struct diff3_block *reverse_diff3_blocklist (struct diff3_block *);
+static struct diff3_block *using_to_diff3_block (struct diff_block *[2], struct diff_block *[2], int, int, struct diff3_block const *);
+static struct diff_block *process_diff (char const *, char const *, struct diff_block **);
+static void check_stdout (void);
+static void fatal (char const *) __attribute__((noreturn));
+static void output_diff3 (FILE *, struct diff3_block *, int const[3], int const[3]);
+static void perror_with_exit (char const *) __attribute__((noreturn));
+static void try_help (char const *, char const *) __attribute__((noreturn));
+static void usage (void);
+
+static char const *diff_program = DEFAULT_DIFF_PROGRAM;
+
+/* Values for long options that do not have single-letter equivalents. */
+enum
+{
+ DIFF_PROGRAM_OPTION = CHAR_MAX + 1,
+ HELP_OPTION,
+ STRIP_TRAILING_CR_OPTION
+};
+
+static struct option const longopts[] =
+{
+ {"diff-program", 1, 0, DIFF_PROGRAM_OPTION},
+ {"easy-only", 0, 0, '3'},
+ {"ed", 0, 0, 'e'},
+ {"help", 0, 0, HELP_OPTION},
+ {"initial-tab", 0, 0, 'T'},
+ {"label", 1, 0, 'L'},
+ {"merge", 0, 0, 'm'},
+ {"overlap-only", 0, 0, 'x'},
+ {"show-all", 0, 0, 'A'},
+ {"show-overlap", 0, 0, 'E'},
+ {"strip-trailing-cr", 0, 0, STRIP_TRAILING_CR_OPTION},
+ {"text", 0, 0, 'a'},
+ {"version", 0, 0, 'v'},
+ {0, 0, 0, 0}
+};
+
+int
+main (int argc, char **argv)
+{
+ int c, i;
+ int common;
+ int mapping[3];
+ int rev_mapping[3];
+ int incompat = 0;
+ bool conflicts_found;
+ struct diff_block *thread0, *thread1, *last_block;
+ struct diff3_block *diff3;
+ int tag_count = 0;
+ char *tag_strings[3];
+ char *commonname;
+ char **file;
+ struct stat statb;
+
+ exit_failure = 2;
+ initialize_main (&argc, &argv);
+ program_name = argv[0];
+ setlocale (LC_ALL, "");
+ bindtextdomain (PACKAGE, LOCALEDIR);
+ textdomain (PACKAGE);
+ c_stack_action (0);
+
+ while ((c = getopt_long (argc, argv, "aeimvx3AEL:TX", longopts, 0)) != -1)
+ {
+ switch (c)
+ {
+ case 'a':
+ text = true;
+ break;
+ case 'A':
+ show_2nd = true;
+ flagging = true;
+ incompat++;
+ break;
+ case 'x':
+ overlap_only = true;
+ incompat++;
+ break;
+ case '3':
+ simple_only = true;
+ incompat++;
+ break;
+ case 'i':
+ finalwrite = true;
+ break;
+ case 'm':
+ merge = true;
+ break;
+ case 'X':
+ overlap_only = true;
+ /* Fall through. */
+ case 'E':
+ flagging = true;
+ /* Fall through. */
+ case 'e':
+ incompat++;
+ break;
+ case 'T':
+ initial_tab = true;
+ break;
+ case STRIP_TRAILING_CR_OPTION:
+ strip_trailing_cr = true;
+ break;
+ case 'v':
+ version_etc (stdout, "diff3", PACKAGE_NAME, PACKAGE_VERSION,
+ "Randy Smith", (char *) 0);
+ check_stdout ();
+ return EXIT_SUCCESS;
+ case DIFF_PROGRAM_OPTION:
+ diff_program = optarg;
+ break;
+ case HELP_OPTION:
+ usage ();
+ check_stdout ();
+ return EXIT_SUCCESS;
+ case 'L':
+ /* Handle up to three -L options. */
+ if (tag_count < 3)
+ {
+ tag_strings[tag_count++] = optarg;
+ break;
+ }
+ try_help ("too many file label options", 0);
+ default:
+ try_help (0, 0);
+ }
+ }
+
+ edscript = incompat & ~merge; /* -AeExX3 without -m implies ed script. */
+ show_2nd |= ~incompat & merge; /* -m without -AeExX3 implies -A. */
+ flagging |= ~incompat & merge;
+
+ if (incompat > 1 /* Ensure at most one of -AeExX3. */
+ || finalwrite & merge /* -i -m would rewrite input file. */
+ || (tag_count && ! flagging)) /* -L requires one of -AEX. */
+ try_help ("incompatible options", 0);
+
+ if (argc - optind != 3)
+ {
+ if (argc - optind < 3)
+ try_help ("missing operand after `%s'", argv[argc - 1]);
+ else
+ try_help ("extra operand `%s'", argv[optind + 3]);
+ }
+
+ file = &argv[optind];
+
+ for (i = tag_count; i < 3; i++)
+ tag_strings[i] = file[i];
+
+ /* Always compare file1 to file2, even if file2 is "-".
+ This is needed for -mAeExX3. Using the file0 as
+ the common file would produce wrong results, because if the
+ file0-file1 diffs didn't line up with the file0-file2 diffs
+ (which is entirely possible since we don't use diff's -n option),
+ diff3 might report phantom changes from file1 to file2.
+
+ Also, try to compare file0 to file1, because this is where
+ changes are expected to come from. Diffing between these pairs
+ of files is more likely to avoid phantom changes from file0 to file1.
+
+ Historically, the default common file was file2, so some older
+ applications (e.g. Emacs ediff) used file2 as the ancestor. So,
+ for compatibility, if this is a 3-way diff (not a merge or
+ edscript), prefer file2 as the common file. */
+
+ common = 2 - (edscript | merge);
+
+ if (strcmp (file[common], "-") == 0)
+ {
+ /* Sigh. We've got standard input as the common file. We can't
+ call diff twice on stdin. Use the other arg as the common
+ file instead. */
+ common = 3 - common;
+ if (strcmp (file[0], "-") == 0 || strcmp (file[common], "-") == 0)
+ fatal ("`-' specified for more than one input file");
+ }
+
+ mapping[0] = 0;
+ mapping[1] = 3 - common;
+ mapping[2] = common;
+
+ for (i = 0; i < 3; i++)
+ rev_mapping[mapping[i]] = i;
+
+ for (i = 0; i < 3; i++)
+ if (strcmp (file[i], "-") != 0)
+ {
+ if (stat (file[i], &statb) < 0)
+ perror_with_exit (file[i]);
+ else if (S_ISDIR (statb.st_mode))
+ error (EXIT_TROUBLE, EISDIR, "%s", file[i]);
+ }
+
+#ifdef SIGCHLD
+ /* System V fork+wait does not work if SIGCHLD is ignored. */
+ signal (SIGCHLD, SIG_DFL);
+#endif
+
+ /* Invoke diff twice on two pairs of input files, combine the two
+ diffs, and output them. */
+
+ commonname = file[rev_mapping[FILEC]];
+ thread1 = process_diff (file[rev_mapping[FILE1]], commonname, &last_block);
+ thread0 = process_diff (file[rev_mapping[FILE0]], commonname, &last_block);
+ diff3 = make_3way_diff (thread0, thread1);
+ if (edscript)
+ conflicts_found
+ = output_diff3_edscript (stdout, diff3, mapping, rev_mapping,
+ tag_strings[0], tag_strings[1], tag_strings[2]);
+ else if (merge)
+ {
+ if (! freopen (file[rev_mapping[FILE0]], "r", stdin))
+ perror_with_exit (file[rev_mapping[FILE0]]);
+ conflicts_found
+ = output_diff3_merge (stdin, stdout, diff3, mapping, rev_mapping,
+ tag_strings[0], tag_strings[1], tag_strings[2]);
+ if (ferror (stdin))
+ fatal ("read failed");
+ }
+ else
+ {
+ output_diff3 (stdout, diff3, mapping, rev_mapping);
+ conflicts_found = false;
+ }
+
+ check_stdout ();
+ exit (conflicts_found);
+ return conflicts_found;
+}
+
+static void
+try_help (char const *reason_msgid, char const *operand)
+{
+ if (reason_msgid)
+ error (0, 0, _(reason_msgid), operand);
+ error (EXIT_TROUBLE, 0,
+ _("Try `%s --help' for more information."), program_name);
+ abort ();
+}
+
+static void
+check_stdout (void)
+{
+ if (ferror (stdout))
+ fatal ("write failed");
+ else if (fclose (stdout) != 0)
+ perror_with_exit (_("standard output"));
+}
+
+static char const * const option_help_msgid[] = {
+ N_("-e --ed Output unmerged changes from OLDFILE to YOURFILE into MYFILE."),
+ N_("-E --show-overlap Output unmerged changes, bracketing conflicts."),
+ N_("-A --show-all Output all changes, bracketing conflicts."),
+ N_("-x --overlap-only Output overlapping changes."),
+ N_("-X Output overlapping changes, bracketing them."),
+ N_("-3 --easy-only Output unmerged nonoverlapping changes."),
+ "",
+ N_("-m --merge Output merged file instead of ed script (default -A)."),
+ N_("-L LABEL --label=LABEL Use LABEL instead of file name."),
+ N_("-i Append `w' and `q' commands to ed scripts."),
+ N_("-a --text Treat all files as text."),
+ N_("--strip-trailing-cr Strip trailing carriage return on input."),
+ N_("-T --initial-tab Make tabs line up by prepending a tab."),
+ N_("--diff-program=PROGRAM Use PROGRAM to compare files."),
+ "",
+ N_("-v --version Output version info."),
+ N_("--help Output this help."),
+ 0
+};
+
+static void
+usage (void)
+{
+ char const * const *p;
+
+ printf (_("Usage: %s [OPTION]... MYFILE OLDFILE YOURFILE\n"),
+ program_name);
+ printf ("%s\n\n", _("Compare three files line by line."));
+ for (p = option_help_msgid; *p; p++)
+ if (**p)
+ printf (" %s\n", _(*p));
+ else
+ putchar ('\n');
+ printf ("\n%s\n%s\n\n%s\n",
+ _("If a FILE is `-', read standard input."),
+ _("Exit status is 0 if successful, 1 if conflicts, 2 if trouble."),
+ _("Report bugs to <bug-gnu-utils@gnu.org>."));
+}
+
+/* Combine the two diffs together into one.
+ Here is the algorithm:
+
+ File2 is shared in common between the two diffs.
+ Diff02 is the diff between 0 and 2.
+ Diff12 is the diff between 1 and 2.
+
+ 1) Find the range for the first block in File2.
+ a) Take the lowest of the two ranges (in File2) in the two
+ current blocks (one from each diff) as being the low
+ water mark. Assign the upper end of this block as
+ being the high water mark and move the current block up
+ one. Mark the block just moved over as to be used.
+ b) Check the next block in the diff that the high water
+ mark is *not* from.
+
+ *If* the high water mark is above
+ the low end of the range in that block,
+
+ mark that block as to be used and move the current
+ block up. Set the high water mark to the max of
+ the high end of this block and the current. Repeat b.
+
+ 2) Find the corresponding ranges in File0 (from the blocks
+ in diff02; line per line outside of diffs) and in File1.
+ Create a diff3_block, reserving space as indicated by the ranges.
+
+ 3) Copy all of the pointers for file2 in. At least for now,
+ do memcmp's between corresponding strings in the two diffs.
+
+ 4) Copy all of the pointers for file0 and 1 in. Get what is
+ needed from file2 (when there isn't a diff block, it's
+ identical to file2 within the range between diff blocks).
+
+ 5) If the diff blocks used came from only one of the two
+ strings of diffs, then that file (i.e. the one other than
+ the common file in that diff) is the odd person out. If
+ diff blocks are used from both sets, check to see if files
+ 0 and 1 match:
+
+ Same number of lines? If so, do a set of memcmp's (if
+ a memcmp matches; copy the pointer over; it'll be easier
+ later during comparisons). If they match, 0 & 1 are the
+ same. If not, all three different.
+
+ Then do it again, until the blocks are exhausted. */
+
+
+/* Make a three way diff (chain of diff3_block's) from two two way
+ diffs (chains of diff_block's). Assume that each of the two diffs
+ passed are onto the same file (i.e. that each of the diffs were
+ made "to" the same file). Return a three way diff pointer with
+ numbering FILE0 = the other file in diff02, FILE1 = the other file
+ in diff12, and FILEC = the common file. */
+
+static struct diff3_block *
+make_3way_diff (struct diff_block *thread0, struct diff_block *thread1)
+{
+ /* Work on the two diffs passed to it as threads. Thread number 0
+ is diff02, thread number 1 is diff12. USING is the base of the
+ list of blocks to be used to construct each block of the three
+ way diff; if no blocks from a particular thread are to be used,
+ that element of USING is 0. LAST_USING contains the last
+ elements on each of the using lists.
+
+ HIGH_WATER_MARK is the highest line number in the common file
+ described in any of the diffs in either of the USING lists.
+ HIGH_WATER_THREAD names the thread. Similarly BASE_WATER_MARK
+ and BASE_WATER_THREAD describe the lowest line number in the
+ common file described in any of the diffs in either of the USING
+ lists. HIGH_WATER_DIFF is the diff from which the
+ HIGH_WATER_MARK was taken.
+
+ HIGH_WATER_DIFF should always be equal to
+ LAST_USING[HIGH_WATER_THREAD]. OTHER_DIFF is the next diff to
+ check for higher water, and should always be equal to
+ CURRENT[HIGH_WATER_THREAD ^ 1]. OTHER_THREAD is the thread in
+ which the OTHER_DIFF is, and hence should always be equal to
+ HIGH_WATER_THREAD ^ 1.
+
+ LAST_DIFF is the last diff block produced by this routine, for
+ line correspondence purposes between that diff and the one
+ currently being worked on. It is ZERO_DIFF before any blocks
+ have been created. */
+
+ struct diff_block *using[2];
+ struct diff_block *last_using[2];
+ struct diff_block *current[2];
+
+ lin high_water_mark;
+
+ int high_water_thread;
+ int base_water_thread;
+ int other_thread;
+
+ struct diff_block *high_water_diff;
+ struct diff_block *other_diff;
+
+ struct diff3_block *result;
+ struct diff3_block *tmpblock;
+ struct diff3_block **result_end;
+
+ struct diff3_block const *last_diff3;
+
+ static struct diff3_block const zero_diff3;
+
+ /* Initialization */
+ result = 0;
+ result_end = &result;
+ current[0] = thread0; current[1] = thread1;
+ last_diff3 = &zero_diff3;
+
+ /* Sniff up the threads until we reach the end */
+
+ while (current[0] || current[1])
+ {
+ using[0] = using[1] = last_using[0] = last_using[1] = 0;
+
+ /* Setup low and high water threads, diffs, and marks. */
+ if (!current[0])
+ base_water_thread = 1;
+ else if (!current[1])
+ base_water_thread = 0;
+ else
+ base_water_thread =
+ (D_LOWLINE (current[0], FC) > D_LOWLINE (current[1], FC));
+
+ high_water_thread = base_water_thread;
+
+ high_water_diff = current[high_water_thread];
+
+ high_water_mark = D_HIGHLINE (high_water_diff, FC);
+
+ /* Make the diff you just got info from into the using class */
+ using[high_water_thread]
+ = last_using[high_water_thread]
+ = high_water_diff;
+ current[high_water_thread] = high_water_diff->next;
+ last_using[high_water_thread]->next = 0;
+
+ /* And mark the other diff */
+ other_thread = high_water_thread ^ 0x1;
+ other_diff = current[other_thread];
+
+ /* Shuffle up the ladder, checking the other diff to see if it
+ needs to be incorporated. */
+ while (other_diff
+ && D_LOWLINE (other_diff, FC) <= high_water_mark + 1)
+ {
+
+ /* Incorporate this diff into the using list. Note that
+ this doesn't take it off the current list */
+ if (using[other_thread])
+ last_using[other_thread]->next = other_diff;
+ else
+ using[other_thread] = other_diff;
+ last_using[other_thread] = other_diff;
+
+ /* Take it off the current list. Note that this following
+ code assumes that other_diff enters it equal to
+ current[high_water_thread ^ 0x1] */
+ current[other_thread] = current[other_thread]->next;
+ other_diff->next = 0;
+
+ /* Set the high_water stuff
+ If this comparison is equal, then this is the last pass
+ through this loop; since diff blocks within a given
+ thread cannot overlap, the high_water_mark will be
+ *below* the range_start of either of the next diffs. */
+
+ if (high_water_mark < D_HIGHLINE (other_diff, FC))
+ {
+ high_water_thread ^= 1;
+ high_water_diff = other_diff;
+ high_water_mark = D_HIGHLINE (other_diff, FC);
+ }
+
+ /* Set the other diff */
+ other_thread = high_water_thread ^ 0x1;
+ other_diff = current[other_thread];
+ }
+
+ /* The using lists contain a list of all of the blocks to be
+ included in this diff3_block. Create it. */
+
+ tmpblock = using_to_diff3_block (using, last_using,
+ base_water_thread, high_water_thread,
+ last_diff3);
+
+ if (!tmpblock)
+ fatal ("internal error: screwup in format of diff blocks");
+
+ /* Put it on the list. */
+ *result_end = tmpblock;
+ result_end = &tmpblock->next;
+
+ /* Set up corresponding lines correctly. */
+ last_diff3 = tmpblock;
+ }
+ return result;
+}
+
+/* Take two lists of blocks (from two separate diff threads) and put
+ them together into one diff3 block. Return a pointer to this diff3
+ block or 0 for failure.
+
+ All arguments besides using are for the convenience of the routine;
+ they could be derived from the using array. LAST_USING is a pair
+ of pointers to the last blocks in the using structure. LOW_THREAD
+ and HIGH_THREAD tell which threads contain the lowest and highest
+ line numbers for File0. LAST_DIFF3 contains the last diff produced
+ in the calling routine. This is used for lines mappings that
+ would still be identical to the state that diff ended in.
+
+ A distinction should be made in this routine between the two diffs
+ that are part of a normal two diff block, and the three diffs that
+ are part of a diff3_block. */
+
+static struct diff3_block *
+using_to_diff3_block (struct diff_block *using[2],
+ struct diff_block *last_using[2],
+ int low_thread, int high_thread,
+ struct diff3_block const *last_diff3)
+{
+ lin low[2], high[2];
+ struct diff3_block *result;
+ struct diff_block *ptr;
+ int d;
+ lin i;
+
+ /* Find the range in the common file. */
+ lin lowc = D_LOWLINE (using[low_thread], FC);
+ lin highc = D_HIGHLINE (last_using[high_thread], FC);
+
+ /* Find the ranges in the other files.
+ If using[d] is null, that means that the file to which that diff
+ refers is equivalent to the common file over this range. */
+
+ for (d = 0; d < 2; d++)
+ if (using[d])
+ {
+ low[d] = D_LOW_MAPLINE (using[d], FC, FO, lowc);
+ high[d] = D_HIGH_MAPLINE (last_using[d], FC, FO, highc);
+ }
+ else
+ {
+ low[d] = D_HIGH_MAPLINE (last_diff3, FILEC, FILE0 + d, lowc);
+ high[d] = D_HIGH_MAPLINE (last_diff3, FILEC, FILE0 + d, highc);
+ }
+
+ /* Create a block with the appropriate sizes */
+ result = create_diff3_block (low[0], high[0], low[1], high[1], lowc, highc);
+
+ /* Copy information for the common file.
+ Return with a zero if any of the compares failed. */
+
+ for (d = 0; d < 2; d++)
+ for (ptr = using[d]; ptr; ptr = D_NEXT (ptr))
+ {
+ lin result_offset = D_LOWLINE (ptr, FC) - lowc;
+
+ if (!copy_stringlist (D_LINEARRAY (ptr, FC),
+ D_LENARRAY (ptr, FC),
+ D_LINEARRAY (result, FILEC) + result_offset,
+ D_LENARRAY (result, FILEC) + result_offset,
+ D_NUMLINES (ptr, FC)))
+ return 0;
+ }
+
+ /* Copy information for file d. First deal with anything that might be
+ before the first diff. */
+
+ for (d = 0; d < 2; d++)
+ {
+ struct diff_block *u = using[d];
+ lin lo = low[d], hi = high[d];
+
+ for (i = 0;
+ i + lo < (u ? D_LOWLINE (u, FO) : hi + 1);
+ i++)
+ {
+ D_RELNUM (result, FILE0 + d, i) = D_RELNUM (result, FILEC, i);
+ D_RELLEN (result, FILE0 + d, i) = D_RELLEN (result, FILEC, i);
+ }
+
+ for (ptr = u; ptr; ptr = D_NEXT (ptr))
+ {
+ lin result_offset = D_LOWLINE (ptr, FO) - lo;
+ lin linec;
+
+ if (!copy_stringlist (D_LINEARRAY (ptr, FO),
+ D_LENARRAY (ptr, FO),
+ D_LINEARRAY (result, FILE0 + d) + result_offset,
+ D_LENARRAY (result, FILE0 + d) + result_offset,
+ D_NUMLINES (ptr, FO)))
+ return 0;
+
+ /* Catch the lines between here and the next diff */
+ linec = D_HIGHLINE (ptr, FC) + 1 - lowc;
+ for (i = D_HIGHLINE (ptr, FO) + 1 - lo;
+ i < (D_NEXT (ptr) ? D_LOWLINE (D_NEXT (ptr), FO) : hi + 1) - lo;
+ i++)
+ {
+ D_RELNUM (result, FILE0 + d, i) = D_RELNUM (result, FILEC, linec);
+ D_RELLEN (result, FILE0 + d, i) = D_RELLEN (result, FILEC, linec);
+ linec++;
+ }
+ }
+ }
+
+ /* Set correspond */
+ if (!using[0])
+ D3_TYPE (result) = DIFF_2ND;
+ else if (!using[1])
+ D3_TYPE (result) = DIFF_1ST;
+ else
+ {
+ lin nl0 = D_NUMLINES (result, FILE0);
+ lin nl1 = D_NUMLINES (result, FILE1);
+
+ if (nl0 != nl1
+ || !compare_line_list (D_LINEARRAY (result, FILE0),
+ D_LENARRAY (result, FILE0),
+ D_LINEARRAY (result, FILE1),
+ D_LENARRAY (result, FILE1),
+ nl0))
+ D3_TYPE (result) = DIFF_ALL;
+ else
+ D3_TYPE (result) = DIFF_3RD;
+ }
+
+ return result;
+}
+
+/* Copy pointers from a list of strings to a different list of
+ strings. If a spot in the second list is already filled, make sure
+ that it is filled with the same string; if not, return false, the copy
+ incomplete. Upon successful completion of the copy, return true. */
+
+static bool
+copy_stringlist (char * const fromptrs[], size_t const fromlengths[],
+ char *toptrs[], size_t tolengths[],
+ lin copynum)
+{
+ register char * const *f = fromptrs;
+ register char **t = toptrs;
+ register size_t const *fl = fromlengths;
+ register size_t *tl = tolengths;
+
+ while (copynum--)
+ {
+ if (*t)
+ {
+ if (*fl != *tl || memcmp (*f, *t, *fl) != 0)
+ return false;
+ }
+ else
+ {
+ *t = *f;
+ *tl = *fl;
+ }
+
+ t++; f++; tl++; fl++;
+ }
+
+ return true;
+}
+
+/* Create a diff3_block, with ranges as specified in the arguments.
+ Allocate the arrays for the various pointers (and zero them) based
+ on the arguments passed. Return the block as a result. */
+
+static struct diff3_block *
+create_diff3_block (lin low0, lin high0,
+ lin low1, lin high1,
+ lin low2, lin high2)
+{
+ struct diff3_block *result = xmalloc (sizeof *result);
+ lin numlines;
+
+ D3_TYPE (result) = ERROR;
+ D_NEXT (result) = 0;
+
+ /* Assign ranges */
+ D_LOWLINE (result, FILE0) = low0;
+ D_HIGHLINE (result, FILE0) = high0;
+ D_LOWLINE (result, FILE1) = low1;
+ D_HIGHLINE (result, FILE1) = high1;
+ D_LOWLINE (result, FILE2) = low2;
+ D_HIGHLINE (result, FILE2) = high2;
+
+ /* Allocate and zero space */
+ numlines = D_NUMLINES (result, FILE0);
+ if (numlines)
+ {
+ D_LINEARRAY (result, FILE0) = xcalloc (numlines, sizeof (char *));
+ D_LENARRAY (result, FILE0) = xcalloc (numlines, sizeof (size_t));
+ }
+ else
+ {
+ D_LINEARRAY (result, FILE0) = 0;
+ D_LENARRAY (result, FILE0) = 0;
+ }
+
+ numlines = D_NUMLINES (result, FILE1);
+ if (numlines)
+ {
+ D_LINEARRAY (result, FILE1) = xcalloc (numlines, sizeof (char *));
+ D_LENARRAY (result, FILE1) = xcalloc (numlines, sizeof (size_t));
+ }
+ else
+ {
+ D_LINEARRAY (result, FILE1) = 0;
+ D_LENARRAY (result, FILE1) = 0;
+ }
+
+ numlines = D_NUMLINES (result, FILE2);
+ if (numlines)
+ {
+ D_LINEARRAY (result, FILE2) = xcalloc (numlines, sizeof (char *));
+ D_LENARRAY (result, FILE2) = xcalloc (numlines, sizeof (size_t));
+ }
+ else
+ {
+ D_LINEARRAY (result, FILE2) = 0;
+ D_LENARRAY (result, FILE2) = 0;
+ }
+
+ /* Return */
+ return result;
+}
+
+/* Compare two lists of lines of text.
+ Return 1 if they are equivalent, 0 if not. */
+
+static bool
+compare_line_list (char * const list1[], size_t const lengths1[],
+ char * const list2[], size_t const lengths2[],
+ lin nl)
+{
+ char * const *l1 = list1;
+ char * const *l2 = list2;
+ size_t const *lgths1 = lengths1;
+ size_t const *lgths2 = lengths2;
+
+ while (nl--)
+ if (!*l1 || !*l2 || *lgths1 != *lgths2++
+ || memcmp (*l1++, *l2++, *lgths1++) != 0)
+ return false;
+ return true;
+}
+
+/* Input and parse two way diffs. */
+
+static struct diff_block *
+process_diff (char const *filea,
+ char const *fileb,
+ struct diff_block **last_block)
+{
+ char *diff_contents;
+ char *diff_limit;
+ char *scan_diff;
+ enum diff_type dt;
+ lin i;
+ struct diff_block *block_list, **block_list_end, *bptr;
+ size_t too_many_lines = (PTRDIFF_MAX
+ / MIN (sizeof *bptr->lines[1],
+ sizeof *bptr->lengths[1]));
+
+ diff_limit = read_diff (filea, fileb, &diff_contents);
+ scan_diff = diff_contents;
+ block_list_end = &block_list;
+ bptr = 0; /* Pacify `gcc -W'. */
+
+ while (scan_diff < diff_limit)
+ {
+ bptr = xmalloc (sizeof *bptr);
+ bptr->lines[0] = bptr->lines[1] = 0;
+ bptr->lengths[0] = bptr->lengths[1] = 0;
+
+ dt = process_diff_control (&scan_diff, bptr);
+ if (dt == ERROR || *scan_diff != '\n')
+ {
+ fprintf (stderr, _("%s: diff failed: "), program_name);
+ do
+ {
+ putc (*scan_diff, stderr);
+ }
+ while (*scan_diff++ != '\n');
+ exit (EXIT_TROUBLE);
+ }
+ scan_diff++;
+
+ /* Force appropriate ranges to be null, if necessary */
+ switch (dt)
+ {
+ case ADD:
+ bptr->ranges[0][0]++;
+ break;
+ case DELETE:
+ bptr->ranges[1][0]++;
+ break;
+ case CHANGE:
+ break;
+ default:
+ fatal ("internal error: invalid diff type in process_diff");
+ break;
+ }
+
+ /* Allocate space for the pointers for the lines from filea, and
+ parcel them out among these pointers */
+ if (dt != ADD)
+ {
+ lin numlines = D_NUMLINES (bptr, 0);
+ if (too_many_lines <= numlines)
+ xalloc_die ();
+ bptr->lines[0] = xmalloc (numlines * sizeof *bptr->lines[0]);
+ bptr->lengths[0] = xmalloc (numlines * sizeof *bptr->lengths[0]);
+ for (i = 0; i < numlines; i++)
+ scan_diff = scan_diff_line (scan_diff,
+ &(bptr->lines[0][i]),
+ &(bptr->lengths[0][i]),
+ diff_limit,
+ '<');
+ }
+
+ /* Get past the separator for changes */
+ if (dt == CHANGE)
+ {
+ if (strncmp (scan_diff, "---\n", 4))
+ fatal ("invalid diff format; invalid change separator");
+ scan_diff += 4;
+ }
+
+ /* Allocate space for the pointers for the lines from fileb, and
+ parcel them out among these pointers */
+ if (dt != DELETE)
+ {
+ lin numlines = D_NUMLINES (bptr, 1);
+ if (too_many_lines <= numlines)
+ xalloc_die ();
+ bptr->lines[1] = xmalloc (numlines * sizeof *bptr->lines[1]);
+ bptr->lengths[1] = xmalloc (numlines * sizeof *bptr->lengths[1]);
+ for (i = 0; i < numlines; i++)
+ scan_diff = scan_diff_line (scan_diff,
+ &(bptr->lines[1][i]),
+ &(bptr->lengths[1][i]),
+ diff_limit,
+ '>');
+ }
+
+ /* Place this block on the blocklist. */
+ *block_list_end = bptr;
+ block_list_end = &bptr->next;
+ }
+
+ *block_list_end = 0;
+ *last_block = bptr;
+ return block_list;
+}
+
+/* Skip tabs and spaces, and return the first character after them. */
+
+static char *
+skipwhite (char *s)
+{
+ while (*s == ' ' || *s == '\t')
+ s++;
+ return s;
+}
+
+/* Read a nonnegative line number from S, returning the address of the
+ first character after the line number, and storing the number into
+ *PNUM. Return 0 if S does not point to a valid line number. */
+
+static char *
+readnum (char *s, lin *pnum)
+{
+ unsigned char c = *s;
+ lin num = 0;
+
+ if (! ISDIGIT (c))
+ return 0;
+
+ do
+ {
+ num = c - '0' + num * 10;
+ c = *++s;
+ }
+ while (ISDIGIT (c));
+
+ *pnum = num;
+ return s;
+}
+
+/* Parse a normal format diff control string. Return the type of the
+ diff (ERROR if the format is bad). All of the other important
+ information is filled into to the structure pointed to by db, and
+ the string pointer (whose location is passed to this routine) is
+ updated to point beyond the end of the string parsed. Note that
+ only the ranges in the diff_block will be set by this routine.
+
+ If some specific pair of numbers has been reduced to a single
+ number, then both corresponding numbers in the diff block are set
+ to that number. In general these numbers are interpreted as ranges
+ inclusive, unless being used by the ADD or DELETE commands. It is
+ assumed that these will be special cased in a superior routine. */
+
+static enum diff_type
+process_diff_control (char **string, struct diff_block *db)
+{
+ char *s = *string;
+ enum diff_type type;
+
+ /* Read first set of digits */
+ s = readnum (skipwhite (s), &db->ranges[0][RANGE_START]);
+ if (! s)
+ return ERROR;
+
+ /* Was that the only digit? */
+ s = skipwhite (s);
+ if (*s == ',')
+ {
+ s = readnum (s + 1, &db->ranges[0][RANGE_END]);
+ if (! s)
+ return ERROR;
+ }
+ else
+ db->ranges[0][RANGE_END] = db->ranges[0][RANGE_START];
+
+ /* Get the letter */
+ s = skipwhite (s);
+ switch (*s)
+ {
+ case 'a':
+ type = ADD;
+ break;
+ case 'c':
+ type = CHANGE;
+ break;
+ case 'd':
+ type = DELETE;
+ break;
+ default:
+ return ERROR; /* Bad format */
+ }
+ s++; /* Past letter */
+
+ /* Read second set of digits */
+ s = readnum (skipwhite (s), &db->ranges[1][RANGE_START]);
+ if (! s)
+ return ERROR;
+
+ /* Was that the only digit? */
+ s = skipwhite (s);
+ if (*s == ',')
+ {
+ s = readnum (s + 1, &db->ranges[1][RANGE_END]);
+ if (! s)
+ return ERROR;
+ s = skipwhite (s); /* To move to end */
+ }
+ else
+ db->ranges[1][RANGE_END] = db->ranges[1][RANGE_START];
+
+ *string = s;
+ return type;
+}
+
+static char *
+read_diff (char const *filea,
+ char const *fileb,
+ char **output_placement)
+{
+ char *diff_result;
+ size_t current_chunk_size, total;
+ int fd, wstatus, status;
+ int werrno = 0;
+ struct stat pipestat;
+
+#if HAVE_WORKING_FORK || HAVE_WORKING_VFORK
+
+ char const *argv[9];
+ char const **ap;
+ int fds[2];
+ pid_t pid;
+
+ ap = argv;
+ *ap++ = diff_program;
+ if (text)
+ *ap++ = "-a";
+ if (strip_trailing_cr)
+ *ap++ = "--strip-trailing-cr";
+ *ap++ = "--horizon-lines=100";
+ *ap++ = "--";
+ *ap++ = filea;
+ *ap++ = fileb;
+ *ap = 0;
+
+ if (pipe (fds) != 0)
+ perror_with_exit ("pipe");
+
+ pid = vfork ();
+ if (pid == 0)
+ {
+ /* Child */
+ close (fds[0]);
+ if (fds[1] != STDOUT_FILENO)
+ {
+ dup2 (fds[1], STDOUT_FILENO);
+ close (fds[1]);
+ }
+
+ /* The cast to (char **) is needed for portability to older
+ hosts with a nonstandard prototype for execvp. */
+ execvp (diff_program, (char **) argv);
+
+ _exit (errno == ENOENT ? 127 : 126);
+ }
+
+ if (pid == -1)
+ perror_with_exit ("fork");
+
+ close (fds[1]); /* Prevent erroneous lack of EOF */
+ fd = fds[0];
+
+#else
+
+ FILE *fpipe;
+ char const args[] = " --horizon-lines=100 -- ";
+ char *command = xmalloc (quote_system_arg (0, diff_program)
+ + sizeof "-a"
+ + sizeof "--strip-trailing-cr"
+ + sizeof args - 1
+ + quote_system_arg (0, filea) + 1
+ + quote_system_arg (0, fileb) + 1);
+ char *p = command;
+ p += quote_system_arg (p, diff_program);
+ if (text)
+ {
+ strcpy (p, " -a");
+ p += 3;
+ }
+ if (strip_trailing_cr)
+ {
+ strcpy (p, " --strip-trailing-cr");
+ p += 20;
+ }
+ strcpy (p, args);
+ p += sizeof args - 1;
+ p += quote_system_arg (p, filea);
+ *p++ = ' ';
+ p += quote_system_arg (p, fileb);
+ *p = 0;
+ errno = 0;
+ fpipe = popen (command, "r");
+ if (!fpipe)
+ perror_with_exit (command);
+ free (command);
+ fd = fileno (fpipe);
+
+#endif
+
+ if (fstat (fd, &pipestat) != 0)
+ perror_with_exit ("fstat");
+ current_chunk_size = MAX (1, STAT_BLOCKSIZE (pipestat));
+ diff_result = xmalloc (current_chunk_size);
+ total = 0;
+
+ for (;;)
+ {
+ size_t bytes_to_read = current_chunk_size - total;
+ size_t bytes = block_read (fd, diff_result + total, bytes_to_read);
+ total += bytes;
+ if (bytes != bytes_to_read)
+ {
+ if (bytes == SIZE_MAX)
+ perror_with_exit (_("read failed"));
+ break;
+ }
+ if (PTRDIFF_MAX / 2 <= current_chunk_size)
+ xalloc_die ();
+ current_chunk_size *= 2;
+ diff_result = xrealloc (diff_result, current_chunk_size);
+ }
+
+ if (total != 0 && diff_result[total-1] != '\n')
+ fatal ("invalid diff format; incomplete last line");
+
+ *output_placement = diff_result;
+
+#if ! (HAVE_WORKING_FORK || HAVE_WORKING_VFORK)
+
+ wstatus = pclose (fpipe);
+ if (wstatus == -1)
+ werrno = errno;
+
+#else
+
+ if (close (fd) != 0)
+ perror_with_exit ("close");
+ if (waitpid (pid, &wstatus, 0) < 0)
+ perror_with_exit ("waitpid");
+
+#endif
+
+ status = ! werrno && WIFEXITED (wstatus) ? WEXITSTATUS (wstatus) : INT_MAX;
+
+ if (EXIT_TROUBLE <= status)
+ error (EXIT_TROUBLE, werrno,
+ _(status == 126
+ ? "subsidiary program `%s' could not be invoked"
+ : status == 127
+ ? "subsidiary program `%s' not found"
+ : status == INT_MAX
+ ? "subsidiary program `%s' failed"
+ : "subsidiary program `%s' failed (exit status %d)"),
+ diff_program, status);
+
+ return diff_result + total;
+}
+
+
+/* Scan a regular diff line (consisting of > or <, followed by a
+ space, followed by text (including nulls) up to a newline.
+
+ This next routine began life as a macro and many parameters in it
+ are used as call-by-reference values. */
+static char *
+scan_diff_line (char *scan_ptr, char **set_start, size_t *set_length,
+ char *limit, char leadingchar)
+{
+ char *line_ptr;
+
+ if (!(scan_ptr[0] == leadingchar
+ && scan_ptr[1] == ' '))
+ fatal ("invalid diff format; incorrect leading line chars");
+
+ *set_start = line_ptr = scan_ptr + 2;
+ while (*line_ptr++ != '\n')
+ continue;
+
+ /* Include newline if the original line ended in a newline,
+ or if an edit script is being generated.
+ Copy any missing newline message to stderr if an edit script is being
+ generated, because edit scripts cannot handle missing newlines.
+ Return the beginning of the next line. */
+ *set_length = line_ptr - *set_start;
+ if (line_ptr < limit && *line_ptr == '\\')
+ {
+ if (edscript)
+ fprintf (stderr, "%s:", program_name);
+ else
+ --*set_length;
+ line_ptr++;
+ do
+ {
+ if (edscript)
+ putc (*line_ptr, stderr);
+ }
+ while (*line_ptr++ != '\n');
+ }
+
+ return line_ptr;
+}
+
+/* Output a three way diff passed as a list of diff3_block's. The
+ argument MAPPING is indexed by external file number (in the
+ argument list) and contains the internal file number (from the diff
+ passed). This is important because the user expects outputs in
+ terms of the argument list number, and the diff passed may have
+ been done slightly differently (if the last argument was "-", for
+ example). REV_MAPPING is the inverse of MAPPING. */
+
+static void
+output_diff3 (FILE *outputfile, struct diff3_block *diff,
+ int const mapping[3], int const rev_mapping[3])
+{
+ int i;
+ int oddoneout;
+ char *cp;
+ struct diff3_block *ptr;
+ lin line;
+ size_t length;
+ int dontprint;
+ static int skew_increment[3] = { 2, 3, 1 }; /* 0==>2==>1==>3 */
+ char const *line_prefix = initial_tab ? "\t" : " ";
+
+ for (ptr = diff; ptr; ptr = D_NEXT (ptr))
+ {
+ char x[2];
+
+ switch (ptr->correspond)
+ {
+ case DIFF_ALL:
+ x[0] = 0;
+ dontprint = 3; /* Print them all */
+ oddoneout = 3; /* Nobody's odder than anyone else */
+ break;
+ case DIFF_1ST:
+ case DIFF_2ND:
+ case DIFF_3RD:
+ oddoneout = rev_mapping[ptr->correspond - DIFF_1ST];
+
+ x[0] = oddoneout + '1';
+ x[1] = 0;
+ dontprint = oddoneout == 0;
+ break;
+ default:
+ fatal ("internal error: invalid diff type passed to output");
+ }
+ fprintf (outputfile, "====%s\n", x);
+
+ /* Go 0, 2, 1 if the first and third outputs are equivalent. */
+ for (i = 0; i < 3;
+ i = (oddoneout == 1 ? skew_increment[i] : i + 1))
+ {
+ int realfile = mapping[i];
+ lin lowt = D_LOWLINE (ptr, realfile);
+ lin hight = D_HIGHLINE (ptr, realfile);
+ long int llowt = lowt;
+ long int lhight = hight;
+
+ fprintf (outputfile, "%d:", i + 1);
+ switch (lowt - hight)
+ {
+ case 1:
+ fprintf (outputfile, "%lda\n", llowt - 1);
+ break;
+ case 0:
+ fprintf (outputfile, "%ldc\n", llowt);
+ break;
+ default:
+ fprintf (outputfile, "%ld,%ldc\n", llowt, lhight);
+ break;
+ }
+
+ if (i == dontprint) continue;
+
+ if (lowt <= hight)
+ {
+ line = 0;
+ do
+ {
+ fprintf (outputfile, line_prefix);
+ cp = D_RELNUM (ptr, realfile, line);
+ length = D_RELLEN (ptr, realfile, line);
+ fwrite (cp, sizeof (char), length, outputfile);
+ }
+ while (++line < hight - lowt + 1);
+ if (cp[length - 1] != '\n')
+ fprintf (outputfile, "\n\\ %s\n",
+ _("No newline at end of file"));
+ }
+ }
+ }
+}
+
+
+/* Output to OUTPUTFILE the lines of B taken from FILENUM. Double any
+ initial '.'s; yield nonzero if any initial '.'s were doubled. */
+
+static bool
+dotlines (FILE *outputfile, struct diff3_block *b, int filenum)
+{
+ lin i;
+ bool leading_dot = false;
+
+ for (i = 0;
+ i < D_NUMLINES (b, filenum);
+ i++)
+ {
+ char *line = D_RELNUM (b, filenum, i);
+ if (line[0] == '.')
+ {
+ leading_dot = true;
+ fprintf (outputfile, ".");
+ }
+ fwrite (line, sizeof (char),
+ D_RELLEN (b, filenum, i), outputfile);
+ }
+
+ return leading_dot;
+}
+
+/* Output to OUTPUTFILE a '.' line. If LEADING_DOT is true, also
+ output a command that removes initial '.'s starting with line START
+ and continuing for NUM lines. (START is long int, not lin, for
+ convenience with printf %ld formats.) */
+
+static void
+undotlines (FILE *outputfile, bool leading_dot, long int start, lin num)
+{
+ fprintf (outputfile, ".\n");
+ if (leading_dot)
+ {
+ if (num == 1)
+ fprintf (outputfile, "%lds/^\\.//\n", start);
+ else
+ fprintf (outputfile, "%ld,%lds/^\\.//\n", start, start + num - 1);
+ }
+}
+
+/* Output a diff3 set of blocks as an ed script. This script applies
+ the changes between file's 2 & 3 to file 1. Take the precise
+ format of the ed script to be output from global variables set
+ during options processing. Reverse the order of
+ the set of diff3 blocks in DIFF; this gets
+ around the problems involved with changing line numbers in an ed
+ script.
+
+ As in `output_diff3', the variable MAPPING maps from file number
+ according to the argument list to file number according to the diff
+ passed. All files listed below are in terms of the argument list.
+ REV_MAPPING is the inverse of MAPPING.
+
+ FILE0, FILE1 and FILE2 are the strings to print as the names of the
+ three files. These may be the actual names, or may be the
+ arguments specified with -L.
+
+ Return 1 if conflicts were found. */
+
+static bool
+output_diff3_edscript (FILE *outputfile, struct diff3_block *diff,
+ int const mapping[3], int const rev_mapping[3],
+ char const *file0, char const *file1, char const *file2)
+{
+ bool leading_dot;
+ bool conflicts_found = false;
+ bool conflict;
+ struct diff3_block *b;
+
+ for (b = reverse_diff3_blocklist (diff); b; b = b->next)
+ {
+ /* Must do mapping correctly. */
+ enum diff_type type
+ = (b->correspond == DIFF_ALL
+ ? DIFF_ALL
+ : DIFF_1ST + rev_mapping[b->correspond - DIFF_1ST]);
+
+ long int low0, high0;
+
+ /* If we aren't supposed to do this output block, skip it. */
+ switch (type)
+ {
+ default: continue;
+ case DIFF_2ND: if (!show_2nd) continue; conflict = true; break;
+ case DIFF_3RD: if (overlap_only) continue; conflict = false; break;
+ case DIFF_ALL: if (simple_only) continue; conflict = flagging; break;
+ }
+
+ low0 = D_LOWLINE (b, mapping[FILE0]);
+ high0 = D_HIGHLINE (b, mapping[FILE0]);
+
+ if (conflict)
+ {
+ conflicts_found = true;
+
+
+ /* Mark end of conflict. */
+
+ fprintf (outputfile, "%lda\n", high0);
+ leading_dot = false;
+ if (type == DIFF_ALL)
+ {
+ if (show_2nd)
+ {
+ /* Append lines from FILE1. */
+ fprintf (outputfile, "||||||| %s\n", file1);
+ leading_dot = dotlines (outputfile, b, mapping[FILE1]);
+ }
+ /* Append lines from FILE2. */
+ fprintf (outputfile, "=======\n");
+ leading_dot |= dotlines (outputfile, b, mapping[FILE2]);
+ }
+ fprintf (outputfile, ">>>>>>> %s\n", file2);
+ undotlines (outputfile, leading_dot, high0 + 2,
+ (D_NUMLINES (b, mapping[FILE1])
+ + D_NUMLINES (b, mapping[FILE2]) + 1));
+
+
+ /* Mark start of conflict. */
+
+ fprintf (outputfile, "%lda\n<<<<<<< %s\n", low0 - 1,
+ type == DIFF_ALL ? file0 : file1);
+ leading_dot = false;
+ if (type == DIFF_2ND)
+ {
+ /* Prepend lines from FILE1. */
+ leading_dot = dotlines (outputfile, b, mapping[FILE1]);
+ fprintf (outputfile, "=======\n");
+ }
+ undotlines (outputfile, leading_dot, low0 + 1,
+ D_NUMLINES (b, mapping[FILE1]));
+ }
+ else if (D_NUMLINES (b, mapping[FILE2]) == 0)
+ /* Write out a delete */
+ {
+ if (low0 == high0)
+ fprintf (outputfile, "%ldd\n", low0);
+ else
+ fprintf (outputfile, "%ld,%ldd\n", low0, high0);
+ }
+ else
+ /* Write out an add or change */
+ {
+ switch (high0 - low0)
+ {
+ case -1:
+ fprintf (outputfile, "%lda\n", high0);
+ break;
+ case 0:
+ fprintf (outputfile, "%ldc\n", high0);
+ break;
+ default:
+ fprintf (outputfile, "%ld,%ldc\n", low0, high0);
+ break;
+ }
+
+ undotlines (outputfile, dotlines (outputfile, b, mapping[FILE2]),
+ low0, D_NUMLINES (b, mapping[FILE2]));
+ }
+ }
+ if (finalwrite) fprintf (outputfile, "w\nq\n");
+ return conflicts_found;
+}
+
+/* Read from INFILE and output to OUTPUTFILE a set of diff3_blocks
+ DIFF as a merged file. This acts like 'ed file0
+ <[output_diff3_edscript]', except that it works even for binary
+ data or incomplete lines.
+
+ As before, MAPPING maps from arg list file number to diff file
+ number, REV_MAPPING is its inverse, and FILE0, FILE1, and FILE2 are
+ the names of the files.
+
+ Return 1 if conflicts were found. */
+
+static bool
+output_diff3_merge (FILE *infile, FILE *outputfile, struct diff3_block *diff,
+ int const mapping[3], int const rev_mapping[3],
+ char const *file0, char const *file1, char const *file2)
+{
+ int c;
+ lin i;
+ bool conflicts_found = false;
+ bool conflict;
+ struct diff3_block *b;
+ lin linesread = 0;
+
+ for (b = diff; b; b = b->next)
+ {
+ /* Must do mapping correctly. */
+ enum diff_type type
+ = ((b->correspond == DIFF_ALL)
+ ? DIFF_ALL
+ : DIFF_1ST + rev_mapping[b->correspond - DIFF_1ST]);
+ char const *format_2nd = "<<<<<<< %s\n";
+
+ /* If we aren't supposed to do this output block, skip it. */
+ switch (type)
+ {
+ default: continue;
+ case DIFF_2ND: if (!show_2nd) continue; conflict = true; break;
+ case DIFF_3RD: if (overlap_only) continue; conflict = false; break;
+ case DIFF_ALL: if (simple_only) continue; conflict = flagging;
+ format_2nd = "||||||| %s\n";
+ break;
+ }
+
+ /* Copy I lines from file 0. */
+ i = D_LOWLINE (b, FILE0) - linesread - 1;
+ linesread += i;
+ while (0 <= --i)
+ do
+ {
+ c = getc (infile);
+ if (c == EOF)
+ {
+ if (ferror (infile))
+ perror_with_exit (_("read failed"));
+ else if (feof (infile))
+ fatal ("input file shrank");
+ }
+ putc (c, outputfile);
+ }
+ while (c != '\n');
+
+ if (conflict)
+ {
+ conflicts_found = true;
+
+ if (type == DIFF_ALL)
+ {
+ /* Put in lines from FILE0 with bracket. */
+ fprintf (outputfile, "<<<<<<< %s\n", file0);
+ for (i = 0;
+ i < D_NUMLINES (b, mapping[FILE0]);
+ i++)
+ fwrite (D_RELNUM (b, mapping[FILE0], i), sizeof (char),
+ D_RELLEN (b, mapping[FILE0], i), outputfile);
+ }
+
+ if (show_2nd)
+ {
+ /* Put in lines from FILE1 with bracket. */
+ fprintf (outputfile, format_2nd, file1);
+ for (i = 0;
+ i < D_NUMLINES (b, mapping[FILE1]);
+ i++)
+ fwrite (D_RELNUM (b, mapping[FILE1], i), sizeof (char),
+ D_RELLEN (b, mapping[FILE1], i), outputfile);
+ }
+
+ fprintf (outputfile, "=======\n");
+ }
+
+ /* Put in lines from FILE2. */
+ for (i = 0;
+ i < D_NUMLINES (b, mapping[FILE2]);
+ i++)
+ fwrite (D_RELNUM (b, mapping[FILE2], i), sizeof (char),
+ D_RELLEN (b, mapping[FILE2], i), outputfile);
+
+ if (conflict)
+ fprintf (outputfile, ">>>>>>> %s\n", file2);
+
+ /* Skip I lines in file 0. */
+ i = D_NUMLINES (b, FILE0);
+ linesread += i;
+ while (0 <= --i)
+ while ((c = getc (infile)) != '\n')
+ if (c == EOF)
+ {
+ if (ferror (infile))
+ perror_with_exit (_("read failed"));
+ else if (feof (infile))
+ {
+ if (i || b->next)
+ fatal ("input file shrank");
+ return conflicts_found;
+ }
+ }
+ }
+ /* Copy rest of common file. */
+ while ((c = getc (infile)) != EOF || !(ferror (infile) | feof (infile)))
+ putc (c, outputfile);
+ return conflicts_found;
+}
+
+/* Reverse the order of the list of diff3 blocks. */
+
+static struct diff3_block *
+reverse_diff3_blocklist (struct diff3_block *diff)
+{
+ register struct diff3_block *tmp, *next, *prev;
+
+ for (tmp = diff, prev = 0; tmp; tmp = next)
+ {
+ next = tmp->next;
+ tmp->next = prev;
+ prev = tmp;
+ }
+
+ return prev;
+}
+
+static void
+fatal (char const *msgid)
+{
+ error (EXIT_TROUBLE, 0, "%s", _(msgid));
+ abort ();
+}
+
+static void
+perror_with_exit (char const *string)
+{
+ error (EXIT_TROUBLE, errno, "%s", string);
+ abort ();
+}
diff --git a/contrib/diff/src/dir.c b/contrib/diff/src/dir.c
new file mode 100644
index 0000000..cc0c8793
--- /dev/null
+++ b/contrib/diff/src/dir.c
@@ -0,0 +1,288 @@
+/* Read, sort and compare two directories. Used for GNU DIFF.
+
+ Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1998, 2001, 2002,
+ 2004 Free Software Foundation, Inc.
+
+ This file is part of GNU DIFF.
+
+ GNU DIFF 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.
+
+ GNU DIFF is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "diff.h"
+#include <error.h>
+#include <exclude.h>
+#include <setjmp.h>
+#include <strcase.h>
+#include <xalloc.h>
+
+/* Read the directory named by DIR and store into DIRDATA a sorted vector
+ of filenames for its contents. DIR->desc == -1 means this directory is
+ known to be nonexistent, so set DIRDATA to an empty vector.
+ Return -1 (setting errno) if error, 0 otherwise. */
+
+struct dirdata
+{
+ size_t nnames; /* Number of names. */
+ char const **names; /* Sorted names of files in dir, followed by 0. */
+ char *data; /* Allocated storage for file names. */
+};
+
+/* Whether file names in directories should be compared with
+ locale-specific sorting. */
+static bool locale_specific_sorting;
+
+/* Where to go if locale-specific sorting fails. */
+static jmp_buf failed_locale_specific_sorting;
+
+static bool dir_loop (struct comparison const *, int);
+static int compare_names_for_qsort (void const *, void const *);
+
+
+/* Read a directory and get its vector of names. */
+
+static bool
+dir_read (struct file_data const *dir, struct dirdata *dirdata)
+{
+ register struct dirent *next;
+ register size_t i;
+
+ /* Address of block containing the files that are described. */
+ char const **names;
+
+ /* Number of files in directory. */
+ size_t nnames;
+
+ /* Allocated and used storage for file name data. */
+ char *data;
+ size_t data_alloc, data_used;
+
+ dirdata->names = 0;
+ dirdata->data = 0;
+ nnames = 0;
+ data = 0;
+
+ if (dir->desc != -1)
+ {
+ /* Open the directory and check for errors. */
+ register DIR *reading = opendir (dir->name);
+ if (!reading)
+ return false;
+
+ /* Initialize the table of filenames. */
+
+ data_alloc = 512;
+ data_used = 0;
+ dirdata->data = data = xmalloc (data_alloc);
+
+ /* Read the directory entries, and insert the subfiles
+ into the `data' table. */
+
+ while ((errno = 0, (next = readdir (reading)) != 0))
+ {
+ char *d_name = next->d_name;
+ size_t d_size = NAMLEN (next) + 1;
+
+ /* Ignore "." and "..". */
+ if (d_name[0] == '.'
+ && (d_name[1] == 0 || (d_name[1] == '.' && d_name[2] == 0)))
+ continue;
+
+ if (excluded_filename (excluded, d_name))
+ continue;
+
+ while (data_alloc < data_used + d_size)
+ {
+ if (PTRDIFF_MAX / 2 <= data_alloc)
+ xalloc_die ();
+ dirdata->data = data = xrealloc (data, data_alloc *= 2);
+ }
+
+ memcpy (data + data_used, d_name, d_size);
+ data_used += d_size;
+ nnames++;
+ }
+ if (errno)
+ {
+ int e = errno;
+ closedir (reading);
+ errno = e;
+ return false;
+ }
+#if CLOSEDIR_VOID
+ closedir (reading);
+#else
+ if (closedir (reading) != 0)
+ return false;
+#endif
+ }
+
+ /* Create the `names' table from the `data' table. */
+ if (PTRDIFF_MAX / sizeof *names - 1 <= nnames)
+ xalloc_die ();
+ dirdata->names = names = xmalloc ((nnames + 1) * sizeof *names);
+ dirdata->nnames = nnames;
+ for (i = 0; i < nnames; i++)
+ {
+ names[i] = data;
+ data += strlen (data) + 1;
+ }
+ names[nnames] = 0;
+ return true;
+}
+
+/* Compare file names, returning a value compatible with strcmp. */
+
+static int
+compare_names (char const *name1, char const *name2)
+{
+ if (locale_specific_sorting)
+ {
+ int r;
+ errno = 0;
+ if (ignore_file_name_case)
+ r = strcasecoll (name1, name2);
+ else
+ r = strcoll (name1, name2);
+ if (errno)
+ {
+ error (0, errno, _("cannot compare file names `%s' and `%s'"),
+ name1, name2);
+ longjmp (failed_locale_specific_sorting, 1);
+ }
+ return r;
+ }
+
+ return (ignore_file_name_case
+ ? strcasecmp (name1, name2)
+ : file_name_cmp (name1, name2));
+}
+
+/* A wrapper for compare_names suitable as an argument for qsort. */
+
+static int
+compare_names_for_qsort (void const *file1, void const *file2)
+{
+ char const *const *f1 = file1;
+ char const *const *f2 = file2;
+ return compare_names (*f1, *f2);
+}
+
+/* Compare the contents of two directories named in CMP.
+ This is a top-level routine; it does everything necessary for diff
+ on two directories.
+
+ CMP->file[0].desc == -1 says directory CMP->file[0] doesn't exist,
+ but pretend it is empty. Likewise for CMP->file[1].
+
+ HANDLE_FILE is a caller-provided subroutine called to handle each file.
+ It gets three operands: CMP, name of file in dir 0, name of file in dir 1.
+ These names are relative to the original working directory.
+
+ For a file that appears in only one of the dirs, one of the name-args
+ to HANDLE_FILE is zero.
+
+ Returns the maximum of all the values returned by HANDLE_FILE,
+ or EXIT_TROUBLE if trouble is encountered in opening files. */
+
+int
+diff_dirs (struct comparison const *cmp,
+ int (*handle_file) (struct comparison const *,
+ char const *, char const *))
+{
+ struct dirdata dirdata[2];
+ int volatile val = EXIT_SUCCESS;
+ int i;
+
+ if ((cmp->file[0].desc == -1 || dir_loop (cmp, 0))
+ && (cmp->file[1].desc == -1 || dir_loop (cmp, 1)))
+ {
+ error (0, 0, "%s: recursive directory loop",
+ cmp->file[cmp->file[0].desc == -1].name);
+ return EXIT_TROUBLE;
+ }
+
+ /* Get contents of both dirs. */
+ for (i = 0; i < 2; i++)
+ if (! dir_read (&cmp->file[i], &dirdata[i]))
+ {
+ perror_with_name (cmp->file[i].name);
+ val = EXIT_TROUBLE;
+ }
+
+ if (val == EXIT_SUCCESS)
+ {
+ char const **volatile names[2];
+ names[0] = dirdata[0].names;
+ names[1] = dirdata[1].names;
+
+ /* Use locale-specific sorting if possible, else native byte order. */
+ locale_specific_sorting = true;
+ if (setjmp (failed_locale_specific_sorting))
+ locale_specific_sorting = false;
+
+ /* Sort the directories. */
+ for (i = 0; i < 2; i++)
+ qsort (names[i], dirdata[i].nnames, sizeof *dirdata[i].names,
+ compare_names_for_qsort);
+
+ /* If `-S name' was given, and this is the topmost level of comparison,
+ ignore all file names less than the specified starting name. */
+
+ if (starting_file && ! cmp->parent)
+ {
+ while (*names[0] && compare_names (*names[0], starting_file) < 0)
+ names[0]++;
+ while (*names[1] && compare_names (*names[1], starting_file) < 0)
+ names[1]++;
+ }
+
+ /* Loop while files remain in one or both dirs. */
+ while (*names[0] || *names[1])
+ {
+ /* Compare next name in dir 0 with next name in dir 1.
+ At the end of a dir,
+ pretend the "next name" in that dir is very large. */
+ int nameorder = (!*names[0] ? 1 : !*names[1] ? -1
+ : compare_names (*names[0], *names[1]));
+ int v1 = (*handle_file) (cmp,
+ 0 < nameorder ? 0 : *names[0]++,
+ nameorder < 0 ? 0 : *names[1]++);
+ if (val < v1)
+ val = v1;
+ }
+ }
+
+ for (i = 0; i < 2; i++)
+ {
+ if (dirdata[i].names)
+ free (dirdata[i].names);
+ if (dirdata[i].data)
+ free (dirdata[i].data);
+ }
+
+ return val;
+}
+
+/* Return nonzero if CMP is looping recursively in argument I. */
+
+static bool
+dir_loop (struct comparison const *cmp, int i)
+{
+ struct comparison const *p = cmp;
+ while ((p = p->parent))
+ if (0 < same_file (&p->file[i].stat, &cmp->file[i].stat))
+ return true;
+ return false;
+}
diff --git a/contrib/diff/src/ed.c b/contrib/diff/src/ed.c
new file mode 100644
index 0000000..c90ed78
--- /dev/null
+++ b/contrib/diff/src/ed.c
@@ -0,0 +1,169 @@
+/* Output routines for ed-script format.
+
+ Copyright (C) 1988, 1989, 1991, 1992, 1993, 1995, 1998, 2001, 2004
+ Free Software Foundation, Inc.
+
+ This file is part of GNU DIFF.
+
+ GNU DIFF 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.
+
+ GNU DIFF is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "diff.h"
+
+static void print_ed_hunk (struct change *);
+static void print_rcs_hunk (struct change *);
+static void pr_forward_ed_hunk (struct change *);
+
+/* Print our script as ed commands. */
+
+void
+print_ed_script (struct change *script)
+{
+ print_script (script, find_reverse_change, print_ed_hunk);
+}
+
+/* Print a hunk of an ed diff */
+
+static void
+print_ed_hunk (struct change *hunk)
+{
+ lin f0, l0, f1, l1;
+ enum changes changes;
+
+#ifdef DEBUG
+ debug_script (hunk);
+#endif
+
+ /* Determine range of line numbers involved in each file. */
+ changes = analyze_hunk (hunk, &f0, &l0, &f1, &l1);
+ if (!changes)
+ return;
+
+ begin_output ();
+
+ /* Print out the line number header for this hunk */
+ print_number_range (',', &files[0], f0, l0);
+ fprintf (outfile, "%c\n", change_letter[changes]);
+
+ /* Print new/changed lines from second file, if needed */
+ if (changes != OLD)
+ {
+ lin i;
+ for (i = f1; i <= l1; i++)
+ {
+ if (files[1].linbuf[i][0] == '.' && files[1].linbuf[i][1] == '\n')
+ {
+ /* The file's line is just a dot, and it would exit
+ insert mode. Precede the dot with another dot, exit
+ insert mode, remove the extra dot, and then resume
+ insert mode. */
+ fprintf (outfile, "..\n.\ns/.//\na\n");
+ }
+ else
+ print_1_line ("", &files[1].linbuf[i]);
+ }
+
+ fprintf (outfile, ".\n");
+ }
+}
+
+/* Print change script in the style of ed commands,
+ but print the changes in the order they appear in the input files,
+ which means that the commands are not truly useful with ed. */
+
+void
+pr_forward_ed_script (struct change *script)
+{
+ print_script (script, find_change, pr_forward_ed_hunk);
+}
+
+static void
+pr_forward_ed_hunk (struct change *hunk)
+{
+ lin i, f0, l0, f1, l1;
+
+ /* Determine range of line numbers involved in each file. */
+ enum changes changes = analyze_hunk (hunk, &f0, &l0, &f1, &l1);
+ if (!changes)
+ return;
+
+ begin_output ();
+
+ fprintf (outfile, "%c", change_letter[changes]);
+ print_number_range (' ', files, f0, l0);
+ fprintf (outfile, "\n");
+
+ /* If deletion only, print just the number range. */
+
+ if (changes == OLD)
+ return;
+
+ /* For insertion (with or without deletion), print the number range
+ and the lines from file 2. */
+
+ for (i = f1; i <= l1; i++)
+ print_1_line ("", &files[1].linbuf[i]);
+
+ fprintf (outfile, ".\n");
+}
+
+/* Print in a format somewhat like ed commands
+ except that each insert command states the number of lines it inserts.
+ This format is used for RCS. */
+
+void
+print_rcs_script (struct change *script)
+{
+ print_script (script, find_change, print_rcs_hunk);
+}
+
+/* Print a hunk of an RCS diff */
+
+static void
+print_rcs_hunk (struct change *hunk)
+{
+ lin i, f0, l0, f1, l1;
+ long int tf0, tl0, tf1, tl1;
+
+ /* Determine range of line numbers involved in each file. */
+ enum changes changes = analyze_hunk (hunk, &f0, &l0, &f1, &l1);
+ if (!changes)
+ return;
+
+ begin_output ();
+
+ translate_range (&files[0], f0, l0, &tf0, &tl0);
+
+ if (changes & OLD)
+ {
+ fprintf (outfile, "d");
+ /* For deletion, print just the starting line number from file 0
+ and the number of lines deleted. */
+ fprintf (outfile, "%ld %ld\n", tf0, tf0 <= tl0 ? tl0 - tf0 + 1 : 1);
+ }
+
+ if (changes & NEW)
+ {
+ fprintf (outfile, "a");
+
+ /* Take last-line-number from file 0 and # lines from file 1. */
+ translate_range (&files[1], f1, l1, &tf1, &tl1);
+ fprintf (outfile, "%ld %ld\n", tl0, tf1 <= tl1 ? tl1 - tf1 + 1 : 1);
+
+ /* Print the inserted lines. */
+ for (i = f1; i <= l1; i++)
+ print_1_line ("", &files[1].linbuf[i]);
+ }
+}
diff --git a/contrib/diff/src/ifdef.c b/contrib/diff/src/ifdef.c
new file mode 100644
index 0000000..22f1cb1
--- /dev/null
+++ b/contrib/diff/src/ifdef.c
@@ -0,0 +1,430 @@
+/* #ifdef-format output routines for GNU DIFF.
+
+ Copyright (C) 1989, 1991, 1992, 1993, 1994, 2001, 2002, 2004 Free
+ Software Foundation, Inc.
+
+ This file is part of GNU DIFF.
+
+ GNU DIFF is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY. No author or distributor
+ accepts responsibility to anyone for the consequences of using it
+ or for whether it serves any particular purpose or works at all,
+ unless he says so in writing. Refer to the GNU DIFF General Public
+ License for full details.
+
+ Everyone is granted permission to copy, modify and redistribute
+ GNU DIFF, but only under the conditions described in the
+ GNU DIFF General Public License. A copy of this license is
+ supposed to have been given to you along with GNU DIFF so you
+ can know your rights and responsibilities. It should be in a
+ file named COPYING. Among other things, the copyright notice
+ and this notice must be preserved on all copies. */
+
+#include "diff.h"
+
+#include <xalloc.h>
+
+struct group
+{
+ struct file_data const *file;
+ lin from, upto; /* start and limit lines for this group of lines */
+};
+
+static char const *format_group (FILE *, char const *, char,
+ struct group const *);
+static char const *do_printf_spec (FILE *, char const *,
+ struct file_data const *, lin,
+ struct group const *);
+static char const *scan_char_literal (char const *, char *);
+static lin groups_letter_value (struct group const *, char);
+static void format_ifdef (char const *, lin, lin, lin, lin);
+static void print_ifdef_hunk (struct change *);
+static void print_ifdef_lines (FILE *, char const *, struct group const *);
+
+static lin next_line0;
+static lin next_line1;
+
+/* Print the edit-script SCRIPT as a merged #ifdef file. */
+
+void
+print_ifdef_script (struct change *script)
+{
+ next_line0 = next_line1 = - files[0].prefix_lines;
+ print_script (script, find_change, print_ifdef_hunk);
+ if (next_line0 < files[0].valid_lines
+ || next_line1 < files[1].valid_lines)
+ {
+ begin_output ();
+ format_ifdef (group_format[UNCHANGED],
+ next_line0, files[0].valid_lines,
+ next_line1, files[1].valid_lines);
+ }
+}
+
+/* Print a hunk of an ifdef diff.
+ This is a contiguous portion of a complete edit script,
+ describing changes in consecutive lines. */
+
+static void
+print_ifdef_hunk (struct change *hunk)
+{
+ lin first0, last0, first1, last1;
+
+ /* Determine range of line numbers involved in each file. */
+ enum changes changes = analyze_hunk (hunk, &first0, &last0, &first1, &last1);
+ if (!changes)
+ return;
+
+ begin_output ();
+
+ /* Print lines up to this change. */
+ if (next_line0 < first0 || next_line1 < first1)
+ format_ifdef (group_format[UNCHANGED],
+ next_line0, first0,
+ next_line1, first1);
+
+ /* Print this change. */
+ next_line0 = last0 + 1;
+ next_line1 = last1 + 1;
+ format_ifdef (group_format[changes],
+ first0, next_line0,
+ first1, next_line1);
+}
+
+/* Print a set of lines according to FORMAT.
+ Lines BEG0 up to END0 are from the first file;
+ lines BEG1 up to END1 are from the second file. */
+
+static void
+format_ifdef (char const *format, lin beg0, lin end0, lin beg1, lin end1)
+{
+ struct group groups[2];
+
+ groups[0].file = &files[0];
+ groups[0].from = beg0;
+ groups[0].upto = end0;
+ groups[1].file = &files[1];
+ groups[1].from = beg1;
+ groups[1].upto = end1;
+ format_group (outfile, format, 0, groups);
+}
+
+/* Print to file OUT a set of lines according to FORMAT.
+ The format ends at the first free instance of ENDCHAR.
+ Yield the address of the terminating character.
+ GROUPS specifies which lines to print.
+ If OUT is zero, do not actually print anything; just scan the format. */
+
+static char const *
+format_group (register FILE *out, char const *format, char endchar,
+ struct group const *groups)
+{
+ register char c;
+ register char const *f = format;
+
+ while ((c = *f) != endchar && c != 0)
+ {
+ char const *f1 = ++f;
+ if (c == '%')
+ switch ((c = *f++))
+ {
+ case '%':
+ break;
+
+ case '(':
+ /* Print if-then-else format e.g. `%(n=1?thenpart:elsepart)'. */
+ {
+ int i;
+ uintmax_t value[2];
+ FILE *thenout, *elseout;
+
+ for (i = 0; i < 2; i++)
+ {
+ if (ISDIGIT (*f))
+ {
+ char *fend;
+ errno = 0;
+ value[i] = strtoumax (f, &fend, 10);
+ if (errno)
+ goto bad_format;
+ f = fend;
+ }
+ else
+ {
+ value[i] = groups_letter_value (groups, *f);
+ if (value[i] == -1)
+ goto bad_format;
+ f++;
+ }
+ if (*f++ != "=?"[i])
+ goto bad_format;
+ }
+ if (value[0] == value[1])
+ thenout = out, elseout = 0;
+ else
+ thenout = 0, elseout = out;
+ f = format_group (thenout, f, ':', groups);
+ if (*f)
+ {
+ f = format_group (elseout, f + 1, ')', groups);
+ if (*f)
+ f++;
+ }
+ }
+ continue;
+
+ case '<':
+ /* Print lines deleted from first file. */
+ print_ifdef_lines (out, line_format[OLD], &groups[0]);
+ continue;
+
+ case '=':
+ /* Print common lines. */
+ print_ifdef_lines (out, line_format[UNCHANGED], &groups[0]);
+ continue;
+
+ case '>':
+ /* Print lines inserted from second file. */
+ print_ifdef_lines (out, line_format[NEW], &groups[1]);
+ continue;
+
+ default:
+ f = do_printf_spec (out, f - 2, 0, 0, groups);
+ if (f)
+ continue;
+ /* Fall through. */
+ bad_format:
+ c = '%';
+ f = f1;
+ break;
+ }
+
+ if (out)
+ putc (c, out);
+ }
+
+ return f;
+}
+
+/* For the line group pair G, return the number corresponding to LETTER.
+ Return -1 if LETTER is not a group format letter. */
+static lin
+groups_letter_value (struct group const *g, char letter)
+{
+ switch (letter)
+ {
+ case 'E': letter = 'e'; g++; break;
+ case 'F': letter = 'f'; g++; break;
+ case 'L': letter = 'l'; g++; break;
+ case 'M': letter = 'm'; g++; break;
+ case 'N': letter = 'n'; g++; break;
+ }
+
+ switch (letter)
+ {
+ case 'e': return translate_line_number (g->file, g->from) - 1;
+ case 'f': return translate_line_number (g->file, g->from);
+ case 'l': return translate_line_number (g->file, g->upto) - 1;
+ case 'm': return translate_line_number (g->file, g->upto);
+ case 'n': return g->upto - g->from;
+ default: return -1;
+ }
+}
+
+/* Print to file OUT, using FORMAT to print the line group GROUP.
+ But do nothing if OUT is zero. */
+static void
+print_ifdef_lines (register FILE *out, char const *format,
+ struct group const *group)
+{
+ struct file_data const *file = group->file;
+ char const * const *linbuf = file->linbuf;
+ lin from = group->from, upto = group->upto;
+
+ if (!out)
+ return;
+
+ /* If possible, use a single fwrite; it's faster. */
+ if (!expand_tabs && format[0] == '%')
+ {
+ if (format[1] == 'l' && format[2] == '\n' && !format[3] && from < upto)
+ {
+ fwrite (linbuf[from], sizeof (char),
+ linbuf[upto] + (linbuf[upto][-1] != '\n') - linbuf[from],
+ out);
+ return;
+ }
+ if (format[1] == 'L' && !format[2])
+ {
+ fwrite (linbuf[from], sizeof (char),
+ linbuf[upto] - linbuf[from], out);
+ return;
+ }
+ }
+
+ for (; from < upto; from++)
+ {
+ register char c;
+ register char const *f = format;
+
+ while ((c = *f++) != 0)
+ {
+ char const *f1 = f;
+ if (c == '%')
+ switch ((c = *f++))
+ {
+ case '%':
+ break;
+
+ case 'l':
+ output_1_line (linbuf[from],
+ (linbuf[from + 1]
+ - (linbuf[from + 1][-1] == '\n')),
+ 0, 0);
+ continue;
+
+ case 'L':
+ output_1_line (linbuf[from], linbuf[from + 1], 0, 0);
+ continue;
+
+ default:
+ f = do_printf_spec (out, f - 2, file, from, 0);
+ if (f)
+ continue;
+ c = '%';
+ f = f1;
+ break;
+ }
+
+ putc (c, out);
+ }
+ }
+}
+
+static char const *
+do_printf_spec (FILE *out, char const *spec,
+ struct file_data const *file, lin n,
+ struct group const *groups)
+{
+ char const *f = spec;
+ char c;
+ char c1;
+
+ /* Scan printf-style SPEC of the form %[-'0]*[0-9]*(.[0-9]*)?[cdoxX]. */
+ /* assert (*f == '%'); */
+ f++;
+ while ((c = *f++) == '-' || c == '\'' || c == '0')
+ continue;
+ while (ISDIGIT (c))
+ c = *f++;
+ if (c == '.')
+ while (ISDIGIT (c = *f++))
+ continue;
+ c1 = *f++;
+
+ switch (c)
+ {
+ case 'c':
+ if (c1 != '\'')
+ return 0;
+ else
+ {
+ char value;
+ f = scan_char_literal (f, &value);
+ if (!f)
+ return 0;
+ if (out)
+ putc (value, out);
+ }
+ break;
+
+ case 'd': case 'o': case 'x': case 'X':
+ {
+ lin value;
+
+ if (file)
+ {
+ if (c1 != 'n')
+ return 0;
+ value = translate_line_number (file, n);
+ }
+ else
+ {
+ value = groups_letter_value (groups, c1);
+ if (value < 0)
+ return 0;
+ }
+
+ if (out)
+ {
+ /* For example, if the spec is "%3xn", use the printf
+ format spec "%3lx". Here the spec prefix is "%3". */
+ long int long_value = value;
+ size_t spec_prefix_len = f - spec - 2;
+#if HAVE_C_VARARRAYS
+ char format[spec_prefix_len + 3];
+#else
+ char *format = xmalloc (spec_prefix_len + 3);
+#endif
+ char *p = format + spec_prefix_len;
+ memcpy (format, spec, spec_prefix_len);
+ *p++ = 'l';
+ *p++ = c;
+ *p = '\0';
+ fprintf (out, format, long_value);
+#if ! HAVE_C_VARARRAYS
+ free (format);
+#endif
+ }
+ }
+ break;
+
+ default:
+ return 0;
+ }
+
+ return f;
+}
+
+/* Scan the character literal represented in the string LIT; LIT points just
+ after the initial apostrophe. Put the literal's value into *VALPTR.
+ Yield the address of the first character after the closing apostrophe,
+ or zero if the literal is ill-formed. */
+static char const *
+scan_char_literal (char const *lit, char *valptr)
+{
+ register char const *p = lit;
+ char value;
+ ptrdiff_t digits;
+ char c = *p++;
+
+ switch (c)
+ {
+ case 0:
+ case '\'':
+ return 0;
+
+ case '\\':
+ value = 0;
+ while ((c = *p++) != '\'')
+ {
+ unsigned int digit = c - '0';
+ if (8 <= digit)
+ return 0;
+ value = 8 * value + digit;
+ }
+ digits = p - lit - 2;
+ if (! (1 <= digits && digits <= 3))
+ return 0;
+ break;
+
+ default:
+ value = c;
+ if (*p++ != '\'')
+ return 0;
+ break;
+ }
+
+ *valptr = value;
+ return p;
+}
diff --git a/contrib/diff/src/io.c b/contrib/diff/src/io.c
new file mode 100644
index 0000000..3ddc1f8
--- /dev/null
+++ b/contrib/diff/src/io.c
@@ -0,0 +1,859 @@
+/* File I/O for GNU DIFF.
+
+ Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1998, 2001, 2002,
+ 2004 Free Software Foundation, Inc.
+
+ This file is part of GNU DIFF.
+
+ GNU DIFF 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.
+
+ GNU DIFF is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "diff.h"
+#include <cmpbuf.h>
+#include <file-type.h>
+#include <setmode.h>
+#include <xalloc.h>
+
+/* Rotate an unsigned value to the left. */
+#define ROL(v, n) ((v) << (n) | (v) >> (sizeof (v) * CHAR_BIT - (n)))
+
+/* Given a hash value and a new character, return a new hash value. */
+#define HASH(h, c) ((c) + ROL (h, 7))
+
+/* The type of a hash value. */
+typedef size_t hash_value;
+verify (hash_value_is_unsigned, ! TYPE_SIGNED (hash_value));
+
+/* Lines are put into equivalence classes of lines that match in lines_differ.
+ Each equivalence class is represented by one of these structures,
+ but only while the classes are being computed.
+ Afterward, each class is represented by a number. */
+struct equivclass
+{
+ lin next; /* Next item in this bucket. */
+ hash_value hash; /* Hash of lines in this class. */
+ char const *line; /* A line that fits this class. */
+ size_t length; /* That line's length, not counting its newline. */
+};
+
+/* Hash-table: array of buckets, each being a chain of equivalence classes.
+ buckets[-1] is reserved for incomplete lines. */
+static lin *buckets;
+
+/* Number of buckets in the hash table array, not counting buckets[-1]. */
+static size_t nbuckets;
+
+/* Array in which the equivalence classes are allocated.
+ The bucket-chains go through the elements in this array.
+ The number of an equivalence class is its index in this array. */
+static struct equivclass *equivs;
+
+/* Index of first free element in the array `equivs'. */
+static lin equivs_index;
+
+/* Number of elements allocated in the array `equivs'. */
+static lin equivs_alloc;
+
+/* Read a block of data into a file buffer, checking for EOF and error. */
+
+void
+file_block_read (struct file_data *current, size_t size)
+{
+ if (size && ! current->eof)
+ {
+ size_t s = block_read (current->desc,
+ FILE_BUFFER (current) + current->buffered, size);
+ if (s == SIZE_MAX)
+ pfatal_with_name (current->name);
+ current->buffered += s;
+ current->eof = s < size;
+ }
+}
+
+/* Check for binary files and compare them for exact identity. */
+
+/* Return 1 if BUF contains a non text character.
+ SIZE is the number of characters in BUF. */
+
+#define binary_file_p(buf, size) (memchr (buf, 0, size) != 0)
+
+/* Get ready to read the current file.
+ Return nonzero if SKIP_TEST is zero,
+ and if it appears to be a binary file. */
+
+static bool
+sip (struct file_data *current, bool skip_test)
+{
+ /* If we have a nonexistent file at this stage, treat it as empty. */
+ if (current->desc < 0)
+ {
+ /* Leave room for a sentinel. */
+ current->bufsize = sizeof (word);
+ current->buffer = xmalloc (current->bufsize);
+ }
+ else
+ {
+ current->bufsize = buffer_lcm (sizeof (word),
+ STAT_BLOCKSIZE (current->stat),
+ PTRDIFF_MAX - 2 * sizeof (word));
+ current->buffer = xmalloc (current->bufsize);
+
+ if (! skip_test)
+ {
+ /* Check first part of file to see if it's a binary file. */
+
+ bool was_binary = set_binary_mode (current->desc, true);
+ off_t buffered;
+ file_block_read (current, current->bufsize);
+ buffered = current->buffered;
+
+ if (! was_binary)
+ {
+ /* Revert to text mode and seek back to the beginning to
+ reread the file. Use relative seek, since file
+ descriptors like stdin might not start at offset
+ zero. */
+
+ if (lseek (current->desc, - buffered, SEEK_CUR) == -1)
+ pfatal_with_name (current->name);
+ set_binary_mode (current->desc, false);
+ current->buffered = 0;
+ current->eof = false;
+ }
+
+ return binary_file_p (current->buffer, buffered);
+ }
+ }
+
+ current->buffered = 0;
+ current->eof = false;
+ return false;
+}
+
+/* Slurp the rest of the current file completely into memory. */
+
+static void
+slurp (struct file_data *current)
+{
+ size_t cc;
+
+ if (current->desc < 0)
+ {
+ /* The file is nonexistent. */
+ return;
+ }
+
+ if (S_ISREG (current->stat.st_mode))
+ {
+ /* It's a regular file; slurp in the rest all at once. */
+
+ /* Get the size out of the stat block.
+ Allocate just enough room for appended newline plus word sentinel,
+ plus word-alignment since we want the buffer word-aligned. */
+ size_t file_size = current->stat.st_size;
+ cc = file_size + 2 * sizeof (word) - file_size % sizeof (word);
+ if (file_size != current->stat.st_size || cc < file_size
+ || PTRDIFF_MAX <= cc)
+ xalloc_die ();
+
+ if (current->bufsize < cc)
+ {
+ current->bufsize = cc;
+ current->buffer = xrealloc (current->buffer, cc);
+ }
+
+ /* Try to read at least 1 more byte than the size indicates, to
+ detect whether the file is growing. This is a nicety for
+ users who run 'diff' on files while they are changing. */
+
+ if (current->buffered <= file_size)
+ {
+ file_block_read (current, file_size + 1 - current->buffered);
+ if (current->buffered <= file_size)
+ return;
+ }
+ }
+
+ /* It's not a regular file, or it's a growing regular file; read it,
+ growing the buffer as needed. */
+
+ file_block_read (current, current->bufsize - current->buffered);
+
+ if (current->buffered)
+ {
+ while (current->buffered == current->bufsize)
+ {
+ if (PTRDIFF_MAX / 2 - sizeof (word) < current->bufsize)
+ xalloc_die ();
+ current->bufsize *= 2;
+ current->buffer = xrealloc (current->buffer, current->bufsize);
+ file_block_read (current, current->bufsize - current->buffered);
+ }
+
+ /* Allocate just enough room for appended newline plus word
+ sentinel, plus word-alignment. */
+ cc = current->buffered + 2 * sizeof (word);
+ current->bufsize = cc - cc % sizeof (word);
+ current->buffer = xrealloc (current->buffer, current->bufsize);
+ }
+}
+
+/* Split the file into lines, simultaneously computing the equivalence
+ class for each line. */
+
+static void
+find_and_hash_each_line (struct file_data *current)
+{
+ hash_value h;
+ char const *p = current->prefix_end;
+ unsigned char c;
+ lin i, *bucket;
+ size_t length;
+
+ /* Cache often-used quantities in local variables to help the compiler. */
+ char const **linbuf = current->linbuf;
+ lin alloc_lines = current->alloc_lines;
+ lin line = 0;
+ lin linbuf_base = current->linbuf_base;
+ lin *cureqs = xmalloc (alloc_lines * sizeof *cureqs);
+ struct equivclass *eqs = equivs;
+ lin eqs_index = equivs_index;
+ lin eqs_alloc = equivs_alloc;
+ char const *suffix_begin = current->suffix_begin;
+ char const *bufend = FILE_BUFFER (current) + current->buffered;
+ bool diff_length_compare_anyway =
+ ignore_white_space != IGNORE_NO_WHITE_SPACE;
+ bool same_length_diff_contents_compare_anyway =
+ diff_length_compare_anyway | ignore_case;
+
+ while (p < suffix_begin)
+ {
+ char const *ip = p;
+
+ h = 0;
+
+ /* Hash this line until we find a newline. */
+ if (ignore_case)
+ switch (ignore_white_space)
+ {
+ case IGNORE_ALL_SPACE:
+ while ((c = *p++) != '\n')
+ if (! isspace (c))
+ h = HASH (h, tolower (c));
+ break;
+
+ case IGNORE_SPACE_CHANGE:
+ while ((c = *p++) != '\n')
+ {
+ if (isspace (c))
+ {
+ do
+ if ((c = *p++) == '\n')
+ goto hashing_done;
+ while (isspace (c));
+
+ h = HASH (h, ' ');
+ }
+
+ /* C is now the first non-space. */
+ h = HASH (h, tolower (c));
+ }
+ break;
+
+ case IGNORE_TAB_EXPANSION:
+ {
+ size_t column = 0;
+ while ((c = *p++) != '\n')
+ {
+ size_t repetitions = 1;
+
+ switch (c)
+ {
+ case '\b':
+ column -= 0 < column;
+ break;
+
+ case '\t':
+ c = ' ';
+ repetitions = tabsize - column % tabsize;
+ column = (column + repetitions < column
+ ? 0
+ : column + repetitions);
+ break;
+
+ case '\r':
+ column = 0;
+ break;
+
+ default:
+ c = tolower (c);
+ column++;
+ break;
+ }
+
+ do
+ h = HASH (h, c);
+ while (--repetitions != 0);
+ }
+ }
+ break;
+
+ default:
+ while ((c = *p++) != '\n')
+ h = HASH (h, tolower (c));
+ break;
+ }
+ else
+ switch (ignore_white_space)
+ {
+ case IGNORE_ALL_SPACE:
+ while ((c = *p++) != '\n')
+ if (! isspace (c))
+ h = HASH (h, c);
+ break;
+
+ case IGNORE_SPACE_CHANGE:
+ while ((c = *p++) != '\n')
+ {
+ if (isspace (c))
+ {
+ do
+ if ((c = *p++) == '\n')
+ goto hashing_done;
+ while (isspace (c));
+
+ h = HASH (h, ' ');
+ }
+
+ /* C is now the first non-space. */
+ h = HASH (h, c);
+ }
+ break;
+
+ case IGNORE_TAB_EXPANSION:
+ {
+ size_t column = 0;
+ while ((c = *p++) != '\n')
+ {
+ size_t repetitions = 1;
+
+ switch (c)
+ {
+ case '\b':
+ column -= 0 < column;
+ break;
+
+ case '\t':
+ c = ' ';
+ repetitions = tabsize - column % tabsize;
+ column = (column + repetitions < column
+ ? 0
+ : column + repetitions);
+ break;
+
+ case '\r':
+ column = 0;
+ break;
+
+ default:
+ column++;
+ break;
+ }
+
+ do
+ h = HASH (h, c);
+ while (--repetitions != 0);
+ }
+ }
+ break;
+
+ default:
+ while ((c = *p++) != '\n')
+ h = HASH (h, c);
+ break;
+ }
+
+ hashing_done:;
+
+ bucket = &buckets[h % nbuckets];
+ length = p - ip - 1;
+
+ if (p == bufend
+ && current->missing_newline
+ && ROBUST_OUTPUT_STYLE (output_style))
+ {
+ /* This line is incomplete. If this is significant,
+ put the line into buckets[-1]. */
+ if (ignore_white_space < IGNORE_SPACE_CHANGE)
+ bucket = &buckets[-1];
+
+ /* Omit the inserted newline when computing linbuf later. */
+ p--;
+ bufend = suffix_begin = p;
+ }
+
+ for (i = *bucket; ; i = eqs[i].next)
+ if (!i)
+ {
+ /* Create a new equivalence class in this bucket. */
+ i = eqs_index++;
+ if (i == eqs_alloc)
+ {
+ if (PTRDIFF_MAX / (2 * sizeof *eqs) <= eqs_alloc)
+ xalloc_die ();
+ eqs_alloc *= 2;
+ eqs = xrealloc (eqs, eqs_alloc * sizeof *eqs);
+ }
+ eqs[i].next = *bucket;
+ eqs[i].hash = h;
+ eqs[i].line = ip;
+ eqs[i].length = length;
+ *bucket = i;
+ break;
+ }
+ else if (eqs[i].hash == h)
+ {
+ char const *eqline = eqs[i].line;
+
+ /* Reuse existing class if lines_differ reports the lines
+ equal. */
+ if (eqs[i].length == length)
+ {
+ /* Reuse existing equivalence class if the lines are identical.
+ This detects the common case of exact identity
+ faster than lines_differ would. */
+ if (memcmp (eqline, ip, length) == 0)
+ break;
+ if (!same_length_diff_contents_compare_anyway)
+ continue;
+ }
+ else if (!diff_length_compare_anyway)
+ continue;
+
+ if (! lines_differ (eqline, ip))
+ break;
+ }
+
+ /* Maybe increase the size of the line table. */
+ if (line == alloc_lines)
+ {
+ /* Double (alloc_lines - linbuf_base) by adding to alloc_lines. */
+ if (PTRDIFF_MAX / 3 <= alloc_lines
+ || PTRDIFF_MAX / sizeof *cureqs <= 2 * alloc_lines - linbuf_base
+ || PTRDIFF_MAX / sizeof *linbuf <= alloc_lines - linbuf_base)
+ xalloc_die ();
+ alloc_lines = 2 * alloc_lines - linbuf_base;
+ cureqs = xrealloc (cureqs, alloc_lines * sizeof *cureqs);
+ linbuf += linbuf_base;
+ linbuf = xrealloc (linbuf,
+ (alloc_lines - linbuf_base) * sizeof *linbuf);
+ linbuf -= linbuf_base;
+ }
+ linbuf[line] = ip;
+ cureqs[line] = i;
+ ++line;
+ }
+
+ current->buffered_lines = line;
+
+ for (i = 0; ; i++)
+ {
+ /* Record the line start for lines in the suffix that we care about.
+ Record one more line start than lines,
+ so that we can compute the length of any buffered line. */
+ if (line == alloc_lines)
+ {
+ /* Double (alloc_lines - linbuf_base) by adding to alloc_lines. */
+ if (PTRDIFF_MAX / 3 <= alloc_lines
+ || PTRDIFF_MAX / sizeof *cureqs <= 2 * alloc_lines - linbuf_base
+ || PTRDIFF_MAX / sizeof *linbuf <= alloc_lines - linbuf_base)
+ xalloc_die ();
+ alloc_lines = 2 * alloc_lines - linbuf_base;
+ linbuf += linbuf_base;
+ linbuf = xrealloc (linbuf,
+ (alloc_lines - linbuf_base) * sizeof *linbuf);
+ linbuf -= linbuf_base;
+ }
+ linbuf[line] = p;
+
+ if (p == bufend)
+ break;
+
+ if (context <= i && no_diff_means_no_output)
+ break;
+
+ line++;
+
+ while (*p++ != '\n')
+ continue;
+ }
+
+ /* Done with cache in local variables. */
+ current->linbuf = linbuf;
+ current->valid_lines = line;
+ current->alloc_lines = alloc_lines;
+ current->equivs = cureqs;
+ equivs = eqs;
+ equivs_alloc = eqs_alloc;
+ equivs_index = eqs_index;
+}
+
+/* Prepare the text. Make sure the text end is initialized.
+ Make sure text ends in a newline,
+ but remember that we had to add one.
+ Strip trailing CRs, if that was requested. */
+
+static void
+prepare_text (struct file_data *current)
+{
+ size_t buffered = current->buffered;
+ char *p = FILE_BUFFER (current);
+ char *dst;
+
+ if (buffered == 0 || p[buffered - 1] == '\n')
+ current->missing_newline = false;
+ else
+ {
+ p[buffered++] = '\n';
+ current->missing_newline = true;
+ }
+
+ if (!p)
+ return;
+
+ /* Don't use uninitialized storage when planting or using sentinels. */
+ memset (p + buffered, 0, sizeof (word));
+
+ if (strip_trailing_cr && (dst = memchr (p, '\r', buffered)))
+ {
+ char const *src = dst;
+ char const *srclim = p + buffered;
+
+ do
+ dst += ! ((*dst = *src++) == '\r' && *src == '\n');
+ while (src < srclim);
+
+ buffered -= src - dst;
+ }
+
+ current->buffered = buffered;
+}
+
+/* We have found N lines in a buffer of size S; guess the
+ proportionate number of lines that will be found in a buffer of
+ size T. However, do not guess a number of lines so large that the
+ resulting line table might cause overflow in size calculations. */
+static lin
+guess_lines (lin n, size_t s, size_t t)
+{
+ size_t guessed_bytes_per_line = n < 10 ? 32 : s / (n - 1);
+ lin guessed_lines = MAX (1, t / guessed_bytes_per_line);
+ return MIN (guessed_lines, PTRDIFF_MAX / (2 * sizeof (char *) + 1) - 5) + 5;
+}
+
+/* Given a vector of two file_data objects, find the identical
+ prefixes and suffixes of each object. */
+
+static void
+find_identical_ends (struct file_data filevec[])
+{
+ word *w0, *w1;
+ char *p0, *p1, *buffer0, *buffer1;
+ char const *end0, *beg0;
+ char const **linbuf0, **linbuf1;
+ lin i, lines;
+ size_t n0, n1;
+ lin alloc_lines0, alloc_lines1;
+ lin buffered_prefix, prefix_count, prefix_mask;
+ lin middle_guess, suffix_guess;
+
+ slurp (&filevec[0]);
+ prepare_text (&filevec[0]);
+ if (filevec[0].desc != filevec[1].desc)
+ {
+ slurp (&filevec[1]);
+ prepare_text (&filevec[1]);
+ }
+ else
+ {
+ filevec[1].buffer = filevec[0].buffer;
+ filevec[1].bufsize = filevec[0].bufsize;
+ filevec[1].buffered = filevec[0].buffered;
+ filevec[1].missing_newline = filevec[0].missing_newline;
+ }
+
+ /* Find identical prefix. */
+
+ w0 = filevec[0].buffer;
+ w1 = filevec[1].buffer;
+ p0 = buffer0 = (char *) w0;
+ p1 = buffer1 = (char *) w1;
+ n0 = filevec[0].buffered;
+ n1 = filevec[1].buffered;
+
+ if (p0 == p1)
+ /* The buffers are the same; sentinels won't work. */
+ p0 = p1 += n1;
+ else
+ {
+ /* Insert end sentinels, in this case characters that are guaranteed
+ to make the equality test false, and thus terminate the loop. */
+
+ if (n0 < n1)
+ p0[n0] = ~p1[n0];
+ else
+ p1[n1] = ~p0[n1];
+
+ /* Loop until first mismatch, or to the sentinel characters. */
+
+ /* Compare a word at a time for speed. */
+ while (*w0 == *w1)
+ w0++, w1++;
+
+ /* Do the last few bytes of comparison a byte at a time. */
+ p0 = (char *) w0;
+ p1 = (char *) w1;
+ while (*p0 == *p1)
+ p0++, p1++;
+
+ /* Don't mistakenly count missing newline as part of prefix. */
+ if (ROBUST_OUTPUT_STYLE (output_style)
+ && ((buffer0 + n0 - filevec[0].missing_newline < p0)
+ !=
+ (buffer1 + n1 - filevec[1].missing_newline < p1)))
+ p0--, p1--;
+ }
+
+ /* Now P0 and P1 point at the first nonmatching characters. */
+
+ /* Skip back to last line-beginning in the prefix,
+ and then discard up to HORIZON_LINES lines from the prefix. */
+ i = horizon_lines;
+ while (p0 != buffer0 && (p0[-1] != '\n' || i--))
+ p0--, p1--;
+
+ /* Record the prefix. */
+ filevec[0].prefix_end = p0;
+ filevec[1].prefix_end = p1;
+
+ /* Find identical suffix. */
+
+ /* P0 and P1 point beyond the last chars not yet compared. */
+ p0 = buffer0 + n0;
+ p1 = buffer1 + n1;
+
+ if (! ROBUST_OUTPUT_STYLE (output_style)
+ || filevec[0].missing_newline == filevec[1].missing_newline)
+ {
+ end0 = p0; /* Addr of last char in file 0. */
+
+ /* Get value of P0 at which we should stop scanning backward:
+ this is when either P0 or P1 points just past the last char
+ of the identical prefix. */
+ beg0 = filevec[0].prefix_end + (n0 < n1 ? 0 : n0 - n1);
+
+ /* Scan back until chars don't match or we reach that point. */
+ for (; p0 != beg0; p0--, p1--)
+ if (*p0 != *p1)
+ {
+ /* Point at the first char of the matching suffix. */
+ beg0 = p0;
+ break;
+ }
+
+ /* Are we at a line-beginning in both files? If not, add the rest of
+ this line to the main body. Discard up to HORIZON_LINES lines from
+ the identical suffix. Also, discard one extra line,
+ because shift_boundaries may need it. */
+ i = horizon_lines + !((buffer0 == p0 || p0[-1] == '\n')
+ &&
+ (buffer1 == p1 || p1[-1] == '\n'));
+ while (i-- && p0 != end0)
+ while (*p0++ != '\n')
+ continue;
+
+ p1 += p0 - beg0;
+ }
+
+ /* Record the suffix. */
+ filevec[0].suffix_begin = p0;
+ filevec[1].suffix_begin = p1;
+
+ /* Calculate number of lines of prefix to save.
+
+ prefix_count == 0 means save the whole prefix;
+ we need this for options like -D that output the whole file,
+ or for enormous contexts (to avoid worrying about arithmetic overflow).
+ We also need it for options like -F that output some preceding line;
+ at least we will need to find the last few lines,
+ but since we don't know how many, it's easiest to find them all.
+
+ Otherwise, prefix_count != 0. Save just prefix_count lines at start
+ of the line buffer; they'll be moved to the proper location later.
+ Handle 1 more line than the context says (because we count 1 too many),
+ rounded up to the next power of 2 to speed index computation. */
+
+ if (no_diff_means_no_output && ! function_regexp.fastmap
+ && context < LIN_MAX / 4 && context < n0)
+ {
+ middle_guess = guess_lines (0, 0, p0 - filevec[0].prefix_end);
+ suffix_guess = guess_lines (0, 0, buffer0 + n0 - p0);
+ for (prefix_count = 1; prefix_count <= context; prefix_count *= 2)
+ continue;
+ alloc_lines0 = (prefix_count + middle_guess
+ + MIN (context, suffix_guess));
+ }
+ else
+ {
+ prefix_count = 0;
+ alloc_lines0 = guess_lines (0, 0, n0);
+ }
+
+ prefix_mask = prefix_count - 1;
+ lines = 0;
+ linbuf0 = xmalloc (alloc_lines0 * sizeof *linbuf0);
+ p0 = buffer0;
+
+ /* If the prefix is needed, find the prefix lines. */
+ if (! (no_diff_means_no_output
+ && filevec[0].prefix_end == p0
+ && filevec[1].prefix_end == p1))
+ {
+ end0 = filevec[0].prefix_end;
+ while (p0 != end0)
+ {
+ lin l = lines++ & prefix_mask;
+ if (l == alloc_lines0)
+ {
+ if (PTRDIFF_MAX / (2 * sizeof *linbuf0) <= alloc_lines0)
+ xalloc_die ();
+ alloc_lines0 *= 2;
+ linbuf0 = xrealloc (linbuf0, alloc_lines0 * sizeof *linbuf0);
+ }
+ linbuf0[l] = p0;
+ while (*p0++ != '\n')
+ continue;
+ }
+ }
+ buffered_prefix = prefix_count && context < lines ? context : lines;
+
+ /* Allocate line buffer 1. */
+
+ middle_guess = guess_lines (lines, p0 - buffer0, p1 - filevec[1].prefix_end);
+ suffix_guess = guess_lines (lines, p0 - buffer0, buffer1 + n1 - p1);
+ alloc_lines1 = buffered_prefix + middle_guess + MIN (context, suffix_guess);
+ if (alloc_lines1 < buffered_prefix
+ || PTRDIFF_MAX / sizeof *linbuf1 <= alloc_lines1)
+ xalloc_die ();
+ linbuf1 = xmalloc (alloc_lines1 * sizeof *linbuf1);
+
+ if (buffered_prefix != lines)
+ {
+ /* Rotate prefix lines to proper location. */
+ for (i = 0; i < buffered_prefix; i++)
+ linbuf1[i] = linbuf0[(lines - context + i) & prefix_mask];
+ for (i = 0; i < buffered_prefix; i++)
+ linbuf0[i] = linbuf1[i];
+ }
+
+ /* Initialize line buffer 1 from line buffer 0. */
+ for (i = 0; i < buffered_prefix; i++)
+ linbuf1[i] = linbuf0[i] - buffer0 + buffer1;
+
+ /* Record the line buffer, adjusted so that
+ linbuf[0] points at the first differing line. */
+ filevec[0].linbuf = linbuf0 + buffered_prefix;
+ filevec[1].linbuf = linbuf1 + buffered_prefix;
+ filevec[0].linbuf_base = filevec[1].linbuf_base = - buffered_prefix;
+ filevec[0].alloc_lines = alloc_lines0 - buffered_prefix;
+ filevec[1].alloc_lines = alloc_lines1 - buffered_prefix;
+ filevec[0].prefix_lines = filevec[1].prefix_lines = lines;
+}
+
+/* If 1 < k, then (2**k - prime_offset[k]) is the largest prime less
+ than 2**k. This table is derived from Chris K. Caldwell's list
+ <http://www.utm.edu/research/primes/lists/2small/>. */
+
+static unsigned char const prime_offset[] =
+{
+ 0, 0, 1, 1, 3, 1, 3, 1, 5, 3, 3, 9, 3, 1, 3, 19, 15, 1, 5, 1, 3, 9, 3,
+ 15, 3, 39, 5, 39, 57, 3, 35, 1, 5, 9, 41, 31, 5, 25, 45, 7, 87, 21,
+ 11, 57, 17, 55, 21, 115, 59, 81, 27, 129, 47, 111, 33, 55, 5, 13, 27,
+ 55, 93, 1, 57, 25
+};
+
+/* Verify that this host's size_t is not too wide for the above table. */
+
+verify (enough_prime_offsets,
+ sizeof (size_t) * CHAR_BIT <= sizeof prime_offset);
+
+/* Given a vector of two file_data objects, read the file associated
+ with each one, and build the table of equivalence classes.
+ Return nonzero if either file appears to be a binary file.
+ If PRETEND_BINARY is nonzero, pretend they are binary regardless. */
+
+bool
+read_files (struct file_data filevec[], bool pretend_binary)
+{
+ int i;
+ bool skip_test = text | pretend_binary;
+ bool appears_binary = pretend_binary | sip (&filevec[0], skip_test);
+
+ if (filevec[0].desc != filevec[1].desc)
+ appears_binary |= sip (&filevec[1], skip_test | appears_binary);
+ else
+ {
+ filevec[1].buffer = filevec[0].buffer;
+ filevec[1].bufsize = filevec[0].bufsize;
+ filevec[1].buffered = filevec[0].buffered;
+ }
+ if (appears_binary)
+ {
+ set_binary_mode (filevec[0].desc, true);
+ set_binary_mode (filevec[1].desc, true);
+ return true;
+ }
+
+ find_identical_ends (filevec);
+
+ equivs_alloc = filevec[0].alloc_lines + filevec[1].alloc_lines + 1;
+ if (PTRDIFF_MAX / sizeof *equivs <= equivs_alloc)
+ xalloc_die ();
+ equivs = xmalloc (equivs_alloc * sizeof *equivs);
+ /* Equivalence class 0 is permanently safe for lines that were not
+ hashed. Real equivalence classes start at 1. */
+ equivs_index = 1;
+
+ /* Allocate (one plus) a prime number of hash buckets. Use a prime
+ number between 1/3 and 2/3 of the value of equiv_allocs,
+ approximately. */
+ for (i = 9; (size_t) 1 << i < equivs_alloc / 3; i++)
+ continue;
+ nbuckets = ((size_t) 1 << i) - prime_offset[i];
+ if (PTRDIFF_MAX / sizeof *buckets <= nbuckets)
+ xalloc_die ();
+ buckets = zalloc ((nbuckets + 1) * sizeof *buckets);
+ buckets++;
+
+ for (i = 0; i < 2; i++)
+ find_and_hash_each_line (&filevec[i]);
+
+ filevec[0].equiv_max = filevec[1].equiv_max = equivs_index;
+
+ free (equivs);
+ free (buckets - 1);
+
+ return false;
+}
diff --git a/contrib/diff/src/normal.c b/contrib/diff/src/normal.c
new file mode 100644
index 0000000..4a01596
--- /dev/null
+++ b/contrib/diff/src/normal.c
@@ -0,0 +1,71 @@
+/* Normal-format output routines for GNU DIFF.
+
+ Copyright (C) 1988, 1989, 1993, 1995, 1998, 2001 Free Software
+ Foundation, Inc.
+
+ This file is part of GNU DIFF.
+
+ GNU DIFF 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.
+
+ GNU DIFF is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "diff.h"
+
+static void print_normal_hunk (struct change *);
+
+/* Print the edit-script SCRIPT as a normal diff.
+ INF points to an array of descriptions of the two files. */
+
+void
+print_normal_script (struct change *script)
+{
+ print_script (script, find_change, print_normal_hunk);
+}
+
+/* Print a hunk of a normal diff.
+ This is a contiguous portion of a complete edit script,
+ describing changes in consecutive lines. */
+
+static void
+print_normal_hunk (struct change *hunk)
+{
+ lin first0, last0, first1, last1;
+ register lin i;
+
+ /* Determine range of line numbers involved in each file. */
+ enum changes changes = analyze_hunk (hunk, &first0, &last0, &first1, &last1);
+ if (!changes)
+ return;
+
+ begin_output ();
+
+ /* Print out the line number header for this hunk */
+ print_number_range (',', &files[0], first0, last0);
+ fprintf (outfile, "%c", change_letter[changes]);
+ print_number_range (',', &files[1], first1, last1);
+ fprintf (outfile, "\n");
+
+ /* Print the lines that the first file has. */
+ if (changes & OLD)
+ for (i = first0; i <= last0; i++)
+ print_1_line ("<", &files[0].linbuf[i]);
+
+ if (changes == CHANGED)
+ fprintf (outfile, "---\n");
+
+ /* Print the lines that the second file has. */
+ if (changes & NEW)
+ for (i = first1; i <= last1; i++)
+ print_1_line (">", &files[1].linbuf[i]);
+}
diff --git a/contrib/diff/src/sdiff.c b/contrib/diff/src/sdiff.c
new file mode 100644
index 0000000..2b0a2ae
--- /dev/null
+++ b/contrib/diff/src/sdiff.c
@@ -0,0 +1,1225 @@
+/* sdiff - side-by-side merge of file differences
+
+ Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 2001, 2002, 2004
+ Free Software Foundation, Inc.
+
+ This file is part of GNU DIFF.
+
+ GNU DIFF 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.
+
+ GNU DIFF is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "system.h"
+#include "paths.h"
+
+#include <stdio.h>
+#include <unlocked-io.h>
+
+#include <c-stack.h>
+#include <dirname.h>
+#include <error.h>
+#include <exit.h>
+#include <exitfail.h>
+#include <file-type.h>
+#include <getopt.h>
+#include <quotesys.h>
+#include <version-etc.h>
+#include <xalloc.h>
+
+/* Size of chunks read from files which must be parsed into lines. */
+#define SDIFF_BUFSIZE ((size_t) 65536)
+
+char *program_name;
+
+static char const *editor_program = DEFAULT_EDITOR_PROGRAM;
+static char const **diffargv;
+
+static char * volatile tmpname;
+static FILE *tmp;
+
+#if HAVE_WORKING_FORK || HAVE_WORKING_VFORK
+static pid_t volatile diffpid;
+#endif
+
+struct line_filter;
+
+static void catchsig (int);
+static bool edit (struct line_filter *, char const *, lin, lin, struct line_filter *, char const *, lin, lin, FILE *);
+static bool interact (struct line_filter *, struct line_filter *, char const *, struct line_filter *, char const *, FILE *);
+static void checksigs (void);
+static void diffarg (char const *);
+static void fatal (char const *) __attribute__((noreturn));
+static void perror_fatal (char const *) __attribute__((noreturn));
+static void trapsigs (void);
+static void untrapsig (int);
+
+#define NUM_SIGS (sizeof sigs / sizeof *sigs)
+static int const sigs[] = {
+#ifdef SIGHUP
+ SIGHUP,
+#endif
+#ifdef SIGQUIT
+ SIGQUIT,
+#endif
+#ifdef SIGTERM
+ SIGTERM,
+#endif
+#ifdef SIGXCPU
+ SIGXCPU,
+#endif
+#ifdef SIGXFSZ
+ SIGXFSZ,
+#endif
+ SIGINT,
+ SIGPIPE
+};
+#define handler_index_of_SIGINT (NUM_SIGS - 2)
+#define handler_index_of_SIGPIPE (NUM_SIGS - 1)
+
+#if HAVE_SIGACTION
+ /* Prefer `sigaction' if available, since `signal' can lose signals. */
+ static struct sigaction initial_action[NUM_SIGS];
+# define initial_handler(i) (initial_action[i].sa_handler)
+ static void signal_handler (int, void (*) (int));
+#else
+ static void (*initial_action[NUM_SIGS]) ();
+# define initial_handler(i) (initial_action[i])
+# define signal_handler(sig, handler) signal (sig, handler)
+#endif
+
+#if ! HAVE_SIGPROCMASK
+# define sigset_t int
+# define sigemptyset(s) (*(s) = 0)
+# ifndef sigmask
+# define sigmask(sig) (1 << ((sig) - 1))
+# endif
+# define sigaddset(s, sig) (*(s) |= sigmask (sig))
+# ifndef SIG_BLOCK
+# define SIG_BLOCK 0
+# endif
+# ifndef SIG_SETMASK
+# define SIG_SETMASK (! SIG_BLOCK)
+# endif
+# define sigprocmask(how, n, o) \
+ ((how) == SIG_BLOCK ? *(o) = sigblock (*(n)) : sigsetmask (*(n)))
+#endif
+
+static bool diraccess (char const *);
+static int temporary_file (void);
+
+/* Options: */
+
+/* Name of output file if -o specified. */
+static char const *output;
+
+/* Do not print common lines. */
+static bool suppress_common_lines;
+
+/* Value for the long option that does not have single-letter equivalents. */
+enum
+{
+ DIFF_PROGRAM_OPTION = CHAR_MAX + 1,
+ HELP_OPTION,
+ STRIP_TRAILING_CR_OPTION,
+ TABSIZE_OPTION
+};
+
+static struct option const longopts[] =
+{
+ {"diff-program", 1, 0, DIFF_PROGRAM_OPTION},
+ {"expand-tabs", 0, 0, 't'},
+ {"help", 0, 0, HELP_OPTION},
+ {"ignore-all-space", 0, 0, 'W'}, /* swap W and w for historical reasons */
+ {"ignore-blank-lines", 0, 0, 'B'},
+ {"ignore-case", 0, 0, 'i'},
+ {"ignore-matching-lines", 1, 0, 'I'},
+ {"ignore-space-change", 0, 0, 'b'},
+ {"ignore-tab-expansion", 0, 0, 'E'},
+ {"left-column", 0, 0, 'l'},
+ {"minimal", 0, 0, 'd'},
+ {"output", 1, 0, 'o'},
+ {"speed-large-files", 0, 0, 'H'},
+ {"strip-trailing-cr", 0, 0, STRIP_TRAILING_CR_OPTION},
+ {"suppress-common-lines", 0, 0, 's'},
+ {"tabsize", 1, 0, TABSIZE_OPTION},
+ {"text", 0, 0, 'a'},
+ {"version", 0, 0, 'v'},
+ {"width", 1, 0, 'w'},
+ {0, 0, 0, 0}
+};
+
+static void try_help (char const *, char const *) __attribute__((noreturn));
+static void
+try_help (char const *reason_msgid, char const *operand)
+{
+ if (reason_msgid)
+ error (0, 0, _(reason_msgid), operand);
+ error (EXIT_TROUBLE, 0, _("Try `%s --help' for more information."),
+ program_name);
+ abort ();
+}
+
+static void
+check_stdout (void)
+{
+ if (ferror (stdout))
+ fatal ("write failed");
+ else if (fclose (stdout) != 0)
+ perror_fatal (_("standard output"));
+}
+
+static char const * const option_help_msgid[] = {
+ N_("-o FILE --output=FILE Operate interactively, sending output to FILE."),
+ "",
+ N_("-i --ignore-case Consider upper- and lower-case to be the same."),
+ N_("-E --ignore-tab-expansion Ignore changes due to tab expansion."),
+ N_("-b --ignore-space-change Ignore changes in the amount of white space."),
+ N_("-W --ignore-all-space Ignore all white space."),
+ N_("-B --ignore-blank-lines Ignore changes whose lines are all blank."),
+ N_("-I RE --ignore-matching-lines=RE Ignore changes whose lines all match RE."),
+ N_("--strip-trailing-cr Strip trailing carriage return on input."),
+ N_("-a --text Treat all files as text."),
+ "",
+ N_("-w NUM --width=NUM Output at most NUM (default 130) print columns."),
+ N_("-l --left-column Output only the left column of common lines."),
+ N_("-s --suppress-common-lines Do not output common lines."),
+ "",
+ N_("-t --expand-tabs Expand tabs to spaces in output."),
+ N_("--tabsize=NUM Tab stops are every NUM (default 8) print columns."),
+ "",
+ N_("-d --minimal Try hard to find a smaller set of changes."),
+ N_("-H --speed-large-files Assume large files and many scattered small changes."),
+ N_("--diff-program=PROGRAM Use PROGRAM to compare files."),
+ "",
+ N_("-v --version Output version info."),
+ N_("--help Output this help."),
+ 0
+};
+
+static void
+usage (void)
+{
+ char const * const *p;
+
+ printf (_("Usage: %s [OPTION]... FILE1 FILE2\n"), program_name);
+ printf ("%s\n\n", _("Side-by-side merge of file differences."));
+ for (p = option_help_msgid; *p; p++)
+ if (**p)
+ printf (" %s\n", _(*p));
+ else
+ putchar ('\n');
+ printf ("\n%s\n%s\n\n%s\n",
+ _("If a FILE is `-', read standard input."),
+ _("Exit status is 0 if inputs are the same, 1 if different, 2 if trouble."),
+ _("Report bugs to <bug-gnu-utils@gnu.org>."));
+}
+
+/* Clean up after a signal or other failure. This function is
+ async-signal-safe. */
+static void
+cleanup (int signo __attribute__((unused)))
+{
+#if HAVE_WORKING_FORK || HAVE_WORKING_VFORK
+ if (0 < diffpid)
+ kill (diffpid, SIGPIPE);
+#endif
+ if (tmpname)
+ unlink (tmpname);
+}
+
+static void exiterr (void) __attribute__((noreturn));
+static void
+exiterr (void)
+{
+ cleanup (0);
+ untrapsig (0);
+ checksigs ();
+ exit (EXIT_TROUBLE);
+}
+
+static void
+fatal (char const *msgid)
+{
+ error (0, 0, "%s", _(msgid));
+ exiterr ();
+}
+
+static void
+perror_fatal (char const *msg)
+{
+ int e = errno;
+ checksigs ();
+ error (0, e, "%s", msg);
+ exiterr ();
+}
+
+static void
+check_child_status (int werrno, int wstatus, int max_ok_status,
+ char const *subsidiary_program)
+{
+ int status = (! werrno && WIFEXITED (wstatus)
+ ? WEXITSTATUS (wstatus)
+ : INT_MAX);
+
+ if (max_ok_status < status)
+ {
+ error (0, werrno,
+ _(status == 126
+ ? "subsidiary program `%s' could not be invoked"
+ : status == 127
+ ? "subsidiary program `%s' not found"
+ : status == INT_MAX
+ ? "subsidiary program `%s' failed"
+ : "subsidiary program `%s' failed (exit status %d)"),
+ subsidiary_program, status);
+ exiterr ();
+ }
+}
+
+static FILE *
+ck_fopen (char const *fname, char const *type)
+{
+ FILE *r = fopen (fname, type);
+ if (! r)
+ perror_fatal (fname);
+ return r;
+}
+
+static void
+ck_fclose (FILE *f)
+{
+ if (fclose (f))
+ perror_fatal ("fclose");
+}
+
+static size_t
+ck_fread (char *buf, size_t size, FILE *f)
+{
+ size_t r = fread (buf, sizeof (char), size, f);
+ if (r == 0 && ferror (f))
+ perror_fatal (_("read failed"));
+ return r;
+}
+
+static void
+ck_fwrite (char const *buf, size_t size, FILE *f)
+{
+ if (fwrite (buf, sizeof (char), size, f) != size)
+ perror_fatal (_("write failed"));
+}
+
+static void
+ck_fflush (FILE *f)
+{
+ if (fflush (f) != 0)
+ perror_fatal (_("write failed"));
+}
+
+static char const *
+expand_name (char *name, bool is_dir, char const *other_name)
+{
+ if (strcmp (name, "-") == 0)
+ fatal ("cannot interactively merge standard input");
+ if (! is_dir)
+ return name;
+ else
+ {
+ /* Yield NAME/BASE, where BASE is OTHER_NAME's basename. */
+ char const *base = base_name (other_name);
+ size_t namelen = strlen (name), baselen = strlen (base);
+ bool insert_slash = *base_name (name) && name[namelen - 1] != '/';
+ char *r = xmalloc (namelen + insert_slash + baselen + 1);
+ memcpy (r, name, namelen);
+ r[namelen] = '/';
+ memcpy (r + namelen + insert_slash, base, baselen + 1);
+ return r;
+ }
+}
+
+struct line_filter {
+ FILE *infile;
+ char *bufpos;
+ char *buffer;
+ char *buflim;
+};
+
+static void
+lf_init (struct line_filter *lf, FILE *infile)
+{
+ lf->infile = infile;
+ lf->bufpos = lf->buffer = lf->buflim = xmalloc (SDIFF_BUFSIZE + 1);
+ lf->buflim[0] = '\n';
+}
+
+/* Fill an exhausted line_filter buffer from its INFILE */
+static size_t
+lf_refill (struct line_filter *lf)
+{
+ size_t s = ck_fread (lf->buffer, SDIFF_BUFSIZE, lf->infile);
+ lf->bufpos = lf->buffer;
+ lf->buflim = lf->buffer + s;
+ lf->buflim[0] = '\n';
+ checksigs ();
+ return s;
+}
+
+/* Advance LINES on LF's infile, copying lines to OUTFILE */
+static void
+lf_copy (struct line_filter *lf, lin lines, FILE *outfile)
+{
+ char *start = lf->bufpos;
+
+ while (lines)
+ {
+ lf->bufpos = (char *) memchr (lf->bufpos, '\n', lf->buflim - lf->bufpos);
+ if (! lf->bufpos)
+ {
+ ck_fwrite (start, lf->buflim - start, outfile);
+ if (! lf_refill (lf))
+ return;
+ start = lf->bufpos;
+ }
+ else
+ {
+ --lines;
+ ++lf->bufpos;
+ }
+ }
+
+ ck_fwrite (start, lf->bufpos - start, outfile);
+}
+
+/* Advance LINES on LF's infile without doing output */
+static void
+lf_skip (struct line_filter *lf, lin lines)
+{
+ while (lines)
+ {
+ lf->bufpos = (char *) memchr (lf->bufpos, '\n', lf->buflim - lf->bufpos);
+ if (! lf->bufpos)
+ {
+ if (! lf_refill (lf))
+ break;
+ }
+ else
+ {
+ --lines;
+ ++lf->bufpos;
+ }
+ }
+}
+
+/* Snarf a line into a buffer. Return EOF if EOF, 0 if error, 1 if OK. */
+static int
+lf_snarf (struct line_filter *lf, char *buffer, size_t bufsize)
+{
+ for (;;)
+ {
+ char *start = lf->bufpos;
+ char *next = (char *) memchr (start, '\n', lf->buflim + 1 - start);
+ size_t s = next - start;
+ if (bufsize <= s)
+ return 0;
+ memcpy (buffer, start, s);
+ if (next < lf->buflim)
+ {
+ buffer[s] = 0;
+ lf->bufpos = next + 1;
+ return 1;
+ }
+ if (! lf_refill (lf))
+ return s ? 0 : EOF;
+ buffer += s;
+ bufsize -= s;
+ }
+}
+
+int
+main (int argc, char *argv[])
+{
+ int opt;
+ char const *prog;
+
+ exit_failure = EXIT_TROUBLE;
+ initialize_main (&argc, &argv);
+ program_name = argv[0];
+ setlocale (LC_ALL, "");
+ bindtextdomain (PACKAGE, LOCALEDIR);
+ textdomain (PACKAGE);
+ c_stack_action (cleanup);
+
+ prog = getenv ("EDITOR");
+ if (prog)
+ editor_program = prog;
+
+ diffarg (DEFAULT_DIFF_PROGRAM);
+
+ /* parse command line args */
+ while ((opt = getopt_long (argc, argv, "abBdEHiI:lo:stvw:W", longopts, 0))
+ != -1)
+ {
+ switch (opt)
+ {
+ case 'a':
+ diffarg ("-a");
+ break;
+
+ case 'b':
+ diffarg ("-b");
+ break;
+
+ case 'B':
+ diffarg ("-B");
+ break;
+
+ case 'd':
+ diffarg ("-d");
+ break;
+
+ case 'E':
+ diffarg ("-E");
+ break;
+
+ case 'H':
+ diffarg ("-H");
+ break;
+
+ case 'i':
+ diffarg ("-i");
+ break;
+
+ case 'I':
+ diffarg ("-I");
+ diffarg (optarg);
+ break;
+
+ case 'l':
+ diffarg ("--left-column");
+ break;
+
+ case 'o':
+ output = optarg;
+ break;
+
+ case 's':
+ suppress_common_lines = true;
+ break;
+
+ case 't':
+ diffarg ("-t");
+ break;
+
+ case 'v':
+ version_etc (stdout, "sdiff", PACKAGE_NAME, PACKAGE_VERSION,
+ "Thomas Lord", (char *) 0);
+ check_stdout ();
+ return EXIT_SUCCESS;
+
+ case 'w':
+ diffarg ("-W");
+ diffarg (optarg);
+ break;
+
+ case 'W':
+ diffarg ("-w");
+ break;
+
+ case DIFF_PROGRAM_OPTION:
+ diffargv[0] = optarg;
+ break;
+
+ case HELP_OPTION:
+ usage ();
+ check_stdout ();
+ return EXIT_SUCCESS;
+
+ case STRIP_TRAILING_CR_OPTION:
+ diffarg ("--strip-trailing-cr");
+ break;
+
+ case TABSIZE_OPTION:
+ diffarg ("--tabsize");
+ diffarg (optarg);
+ break;
+
+ default:
+ try_help (0, 0);
+ }
+ }
+
+ if (argc - optind != 2)
+ {
+ if (argc - optind < 2)
+ try_help ("missing operand after `%s'", argv[argc - 1]);
+ else
+ try_help ("extra operand `%s'", argv[optind + 2]);
+ }
+
+ if (! output)
+ {
+ /* easy case: diff does everything for us */
+ if (suppress_common_lines)
+ diffarg ("--suppress-common-lines");
+ diffarg ("-y");
+ diffarg ("--");
+ diffarg (argv[optind]);
+ diffarg (argv[optind + 1]);
+ diffarg (0);
+ execvp (diffargv[0], (char **) diffargv);
+ perror_fatal (diffargv[0]);
+ }
+ else
+ {
+ char const *lname, *rname;
+ FILE *left, *right, *out, *diffout;
+ bool interact_ok;
+ struct line_filter lfilt;
+ struct line_filter rfilt;
+ struct line_filter diff_filt;
+ bool leftdir = diraccess (argv[optind]);
+ bool rightdir = diraccess (argv[optind + 1]);
+
+ if (leftdir & rightdir)
+ fatal ("both files to be compared are directories");
+
+ lname = expand_name (argv[optind], leftdir, argv[optind + 1]);
+ left = ck_fopen (lname, "r");
+ rname = expand_name (argv[optind + 1], rightdir, argv[optind]);
+ right = ck_fopen (rname, "r");
+ out = ck_fopen (output, "w");
+
+ diffarg ("--sdiff-merge-assist");
+ diffarg ("--");
+ diffarg (argv[optind]);
+ diffarg (argv[optind + 1]);
+ diffarg (0);
+
+ trapsigs ();
+
+#if ! (HAVE_WORKING_FORK || HAVE_WORKING_VFORK)
+ {
+ size_t cmdsize = 1;
+ char *p, *command;
+ int i;
+
+ for (i = 0; diffargv[i]; i++)
+ cmdsize += quote_system_arg (0, diffargv[i]) + 1;
+ command = p = xmalloc (cmdsize);
+ for (i = 0; diffargv[i]; i++)
+ {
+ p += quote_system_arg (p, diffargv[i]);
+ *p++ = ' ';
+ }
+ p[-1] = 0;
+ errno = 0;
+ diffout = popen (command, "r");
+ if (! diffout)
+ perror_fatal (command);
+ free (command);
+ }
+#else
+ {
+ int diff_fds[2];
+# if HAVE_WORKING_VFORK
+ sigset_t procmask;
+ sigset_t blocked;
+# endif
+
+ if (pipe (diff_fds) != 0)
+ perror_fatal ("pipe");
+
+# if HAVE_WORKING_VFORK
+ /* Block SIGINT and SIGPIPE. */
+ sigemptyset (&blocked);
+ sigaddset (&blocked, SIGINT);
+ sigaddset (&blocked, SIGPIPE);
+ sigprocmask (SIG_BLOCK, &blocked, &procmask);
+# endif
+ diffpid = vfork ();
+ if (diffpid < 0)
+ perror_fatal ("fork");
+ if (! diffpid)
+ {
+ /* Alter the child's SIGINT and SIGPIPE handlers;
+ this may munge the parent.
+ The child ignores SIGINT in case the user interrupts the editor.
+ The child does not ignore SIGPIPE, even if the parent does. */
+ if (initial_handler (handler_index_of_SIGINT) != SIG_IGN)
+ signal_handler (SIGINT, SIG_IGN);
+ signal_handler (SIGPIPE, SIG_DFL);
+# if HAVE_WORKING_VFORK
+ /* Stop blocking SIGINT and SIGPIPE in the child. */
+ sigprocmask (SIG_SETMASK, &procmask, 0);
+# endif
+ close (diff_fds[0]);
+ if (diff_fds[1] != STDOUT_FILENO)
+ {
+ dup2 (diff_fds[1], STDOUT_FILENO);
+ close (diff_fds[1]);
+ }
+
+ execvp (diffargv[0], (char **) diffargv);
+ _exit (errno == ENOENT ? 127 : 126);
+ }
+
+# if HAVE_WORKING_VFORK
+ /* Restore the parent's SIGINT and SIGPIPE behavior. */
+ if (initial_handler (handler_index_of_SIGINT) != SIG_IGN)
+ signal_handler (SIGINT, catchsig);
+ if (initial_handler (handler_index_of_SIGPIPE) != SIG_IGN)
+ signal_handler (SIGPIPE, catchsig);
+ else
+ signal_handler (SIGPIPE, SIG_IGN);
+
+ /* Stop blocking SIGINT and SIGPIPE in the parent. */
+ sigprocmask (SIG_SETMASK, &procmask, 0);
+# endif
+
+ close (diff_fds[1]);
+ diffout = fdopen (diff_fds[0], "r");
+ if (! diffout)
+ perror_fatal ("fdopen");
+ }
+#endif
+
+ lf_init (&diff_filt, diffout);
+ lf_init (&lfilt, left);
+ lf_init (&rfilt, right);
+
+ interact_ok = interact (&diff_filt, &lfilt, lname, &rfilt, rname, out);
+
+ ck_fclose (left);
+ ck_fclose (right);
+ ck_fclose (out);
+
+ {
+ int wstatus;
+ int werrno = 0;
+
+#if ! (HAVE_WORKING_FORK || HAVE_WORKING_VFORK)
+ wstatus = pclose (diffout);
+ if (wstatus == -1)
+ werrno = errno;
+#else
+ ck_fclose (diffout);
+ while (waitpid (diffpid, &wstatus, 0) < 0)
+ if (errno == EINTR)
+ checksigs ();
+ else
+ perror_fatal ("waitpid");
+ diffpid = 0;
+#endif
+
+ if (tmpname)
+ {
+ unlink (tmpname);
+ tmpname = 0;
+ }
+
+ if (! interact_ok)
+ exiterr ();
+
+ check_child_status (werrno, wstatus, EXIT_FAILURE, diffargv[0]);
+ untrapsig (0);
+ checksigs ();
+ exit (WEXITSTATUS (wstatus));
+ }
+ }
+ return EXIT_SUCCESS; /* Fool `-Wall'. */
+}
+
+static void
+diffarg (char const *a)
+{
+ static size_t diffargs, diffarglim;
+
+ if (diffargs == diffarglim)
+ {
+ if (! diffarglim)
+ diffarglim = 16;
+ else if (PTRDIFF_MAX / (2 * sizeof *diffargv) <= diffarglim)
+ xalloc_die ();
+ else
+ diffarglim *= 2;
+ diffargv = xrealloc (diffargv, diffarglim * sizeof *diffargv);
+ }
+ diffargv[diffargs++] = a;
+}
+
+/* Signal handling */
+
+static bool volatile ignore_SIGINT;
+static int volatile signal_received;
+static bool sigs_trapped;
+
+static void
+catchsig (int s)
+{
+#if ! HAVE_SIGACTION
+ signal (s, SIG_IGN);
+#endif
+ if (! (s == SIGINT && ignore_SIGINT))
+ signal_received = s;
+}
+
+#if HAVE_SIGACTION
+static struct sigaction catchaction;
+
+static void
+signal_handler (int sig, void (*handler) (int))
+{
+ catchaction.sa_handler = handler;
+ sigaction (sig, &catchaction, 0);
+}
+#endif
+
+static void
+trapsigs (void)
+{
+ int i;
+
+#if HAVE_SIGACTION
+ catchaction.sa_flags = SA_RESTART;
+ sigemptyset (&catchaction.sa_mask);
+ for (i = 0; i < NUM_SIGS; i++)
+ sigaddset (&catchaction.sa_mask, sigs[i]);
+#endif
+
+ for (i = 0; i < NUM_SIGS; i++)
+ {
+#if HAVE_SIGACTION
+ sigaction (sigs[i], 0, &initial_action[i]);
+#else
+ initial_action[i] = signal (sigs[i], SIG_IGN);
+#endif
+ if (initial_handler (i) != SIG_IGN)
+ signal_handler (sigs[i], catchsig);
+ }
+
+#ifdef SIGCHLD
+ /* System V fork+wait does not work if SIGCHLD is ignored. */
+ signal (SIGCHLD, SIG_DFL);
+#endif
+
+ sigs_trapped = true;
+}
+
+/* Untrap signal S, or all trapped signals if S is zero. */
+static void
+untrapsig (int s)
+{
+ int i;
+
+ if (sigs_trapped)
+ for (i = 0; i < NUM_SIGS; i++)
+ if ((! s || sigs[i] == s) && initial_handler (i) != SIG_IGN)
+ {
+#if HAVE_SIGACTION
+ sigaction (sigs[i], &initial_action[i], 0);
+#else
+ signal (sigs[i], initial_action[i]);
+#endif
+ }
+}
+
+/* Exit if a signal has been received. */
+static void
+checksigs (void)
+{
+ int s = signal_received;
+ if (s)
+ {
+ cleanup (0);
+
+ /* Yield an exit status indicating that a signal was received. */
+ untrapsig (s);
+ kill (getpid (), s);
+
+ /* That didn't work, so exit with error status. */
+ exit (EXIT_TROUBLE);
+ }
+}
+
+static void
+give_help (void)
+{
+ fprintf (stderr, "%s", _("\
+ed:\tEdit then use both versions, each decorated with a header.\n\
+eb:\tEdit then use both versions.\n\
+el:\tEdit then use the left version.\n\
+er:\tEdit then use the right version.\n\
+e:\tEdit a new version.\n\
+l:\tUse the left version.\n\
+r:\tUse the right version.\n\
+s:\tSilently include common lines.\n\
+v:\tVerbosely include common lines.\n\
+q:\tQuit.\n\
+"));
+}
+
+static int
+skip_white (void)
+{
+ int c;
+ for (;;)
+ {
+ c = getchar ();
+ if (! isspace (c) || c == '\n')
+ break;
+ checksigs ();
+ }
+ if (ferror (stdin))
+ perror_fatal (_("read failed"));
+ return c;
+}
+
+static void
+flush_line (void)
+{
+ int c;
+ while ((c = getchar ()) != '\n' && c != EOF)
+ continue;
+ if (ferror (stdin))
+ perror_fatal (_("read failed"));
+}
+
+
+/* interpret an edit command */
+static bool
+edit (struct line_filter *left, char const *lname, lin lline, lin llen,
+ struct line_filter *right, char const *rname, lin rline, lin rlen,
+ FILE *outfile)
+{
+ for (;;)
+ {
+ int cmd0, cmd1;
+ bool gotcmd = false;
+
+ cmd1 = 0; /* Pacify `gcc -W'. */
+
+ while (! gotcmd)
+ {
+ if (putchar ('%') != '%')
+ perror_fatal (_("write failed"));
+ ck_fflush (stdout);
+
+ cmd0 = skip_white ();
+ switch (cmd0)
+ {
+ case 'l': case 'r': case 's': case 'v': case 'q':
+ if (skip_white () != '\n')
+ {
+ give_help ();
+ flush_line ();
+ continue;
+ }
+ gotcmd = true;
+ break;
+
+ case 'e':
+ cmd1 = skip_white ();
+ switch (cmd1)
+ {
+ case 'b': case 'd': case 'l': case 'r':
+ if (skip_white () != '\n')
+ {
+ give_help ();
+ flush_line ();
+ continue;
+ }
+ gotcmd = true;
+ break;
+ case '\n':
+ gotcmd = true;
+ break;
+ default:
+ give_help ();
+ flush_line ();
+ continue;
+ }
+ break;
+
+ case EOF:
+ if (feof (stdin))
+ {
+ gotcmd = true;
+ cmd0 = 'q';
+ break;
+ }
+ /* Fall through. */
+ default:
+ flush_line ();
+ /* Fall through. */
+ case '\n':
+ give_help ();
+ continue;
+ }
+ }
+
+ switch (cmd0)
+ {
+ case 'l':
+ lf_copy (left, llen, outfile);
+ lf_skip (right, rlen);
+ return true;
+ case 'r':
+ lf_copy (right, rlen, outfile);
+ lf_skip (left, llen);
+ return true;
+ case 's':
+ suppress_common_lines = true;
+ break;
+ case 'v':
+ suppress_common_lines = false;
+ break;
+ case 'q':
+ return false;
+ case 'e':
+ {
+ int fd;
+
+ if (tmpname)
+ tmp = fopen (tmpname, "w");
+ else
+ {
+ if ((fd = temporary_file ()) < 0)
+ perror_fatal ("mkstemp");
+ tmp = fdopen (fd, "w");
+ }
+
+ if (! tmp)
+ perror_fatal (tmpname);
+
+ switch (cmd1)
+ {
+ case 'd':
+ if (llen)
+ {
+ if (llen == 1)
+ fprintf (tmp, "--- %s %ld\n", lname, (long int) lline);
+ else
+ fprintf (tmp, "--- %s %ld,%ld\n", lname,
+ (long int) lline,
+ (long int) (lline + llen - 1));
+ }
+ /* Fall through. */
+ case 'b': case 'l':
+ lf_copy (left, llen, tmp);
+ break;
+
+ default:
+ lf_skip (left, llen);
+ break;
+ }
+
+ switch (cmd1)
+ {
+ case 'd':
+ if (rlen)
+ {
+ if (rlen == 1)
+ fprintf (tmp, "+++ %s %ld\n", rname, (long int) rline);
+ else
+ fprintf (tmp, "+++ %s %ld,%ld\n", rname,
+ (long int) rline,
+ (long int) (rline + rlen - 1));
+ }
+ /* Fall through. */
+ case 'b': case 'r':
+ lf_copy (right, rlen, tmp);
+ break;
+
+ default:
+ lf_skip (right, rlen);
+ break;
+ }
+
+ ck_fclose (tmp);
+
+ {
+ int wstatus;
+ int werrno = 0;
+ ignore_SIGINT = true;
+ checksigs ();
+
+ {
+#if ! (HAVE_WORKING_FORK || HAVE_WORKING_VFORK)
+ char *command =
+ xmalloc (quote_system_arg (0, editor_program)
+ + 1 + strlen (tmpname) + 1);
+ sprintf (command + quote_system_arg (command, editor_program),
+ " %s", tmpname);
+ wstatus = system (command);
+ if (wstatus == -1)
+ werrno = errno;
+ free (command);
+#else
+ pid_t pid;
+
+ pid = vfork ();
+ if (pid == 0)
+ {
+ char const *argv[3];
+ int i = 0;
+
+ argv[i++] = editor_program;
+ argv[i++] = tmpname;
+ argv[i] = 0;
+
+ execvp (editor_program, (char **) argv);
+ _exit (errno == ENOENT ? 127 : 126);
+ }
+
+ if (pid < 0)
+ perror_fatal ("fork");
+
+ while (waitpid (pid, &wstatus, 0) < 0)
+ if (errno == EINTR)
+ checksigs ();
+ else
+ perror_fatal ("waitpid");
+#endif
+ }
+
+ ignore_SIGINT = false;
+ check_child_status (werrno, wstatus, EXIT_SUCCESS,
+ editor_program);
+ }
+
+ {
+ char buf[SDIFF_BUFSIZE];
+ size_t size;
+ tmp = ck_fopen (tmpname, "r");
+ while ((size = ck_fread (buf, SDIFF_BUFSIZE, tmp)) != 0)
+ {
+ checksigs ();
+ ck_fwrite (buf, size, outfile);
+ }
+ ck_fclose (tmp);
+ }
+ return true;
+ }
+ default:
+ give_help ();
+ break;
+ }
+ }
+}
+
+/* Alternately reveal bursts of diff output and handle user commands. */
+static bool
+interact (struct line_filter *diff,
+ struct line_filter *left, char const *lname,
+ struct line_filter *right, char const *rname,
+ FILE *outfile)
+{
+ lin lline = 1, rline = 1;
+
+ for (;;)
+ {
+ char diff_help[256];
+ int snarfed = lf_snarf (diff, diff_help, sizeof diff_help);
+
+ if (snarfed <= 0)
+ return snarfed != 0;
+
+ checksigs ();
+
+ if (diff_help[0] == ' ')
+ puts (diff_help + 1);
+ else
+ {
+ char *numend;
+ uintmax_t val;
+ lin llen, rlen, lenmax;
+ errno = 0;
+ llen = val = strtoumax (diff_help + 1, &numend, 10);
+ if (llen < 0 || llen != val || errno || *numend != ',')
+ fatal (diff_help);
+ rlen = val = strtoumax (numend + 1, &numend, 10);
+ if (rlen < 0 || rlen != val || errno || *numend)
+ fatal (diff_help);
+
+ lenmax = MAX (llen, rlen);
+
+ switch (diff_help[0])
+ {
+ case 'i':
+ if (suppress_common_lines)
+ lf_skip (diff, lenmax);
+ else
+ lf_copy (diff, lenmax, stdout);
+
+ lf_copy (left, llen, outfile);
+ lf_skip (right, rlen);
+ break;
+
+ case 'c':
+ lf_copy (diff, lenmax, stdout);
+ if (! edit (left, lname, lline, llen,
+ right, rname, rline, rlen,
+ outfile))
+ return false;
+ break;
+
+ default:
+ fatal (diff_help);
+ }
+
+ lline += llen;
+ rline += rlen;
+ }
+ }
+}
+
+/* Return true if DIR is an existing directory. */
+static bool
+diraccess (char const *dir)
+{
+ struct stat buf;
+ return stat (dir, &buf) == 0 && S_ISDIR (buf.st_mode);
+}
+
+#ifndef P_tmpdir
+# define P_tmpdir "/tmp"
+#endif
+#ifndef TMPDIR_ENV
+# define TMPDIR_ENV "TMPDIR"
+#endif
+
+/* Open a temporary file and return its file descriptor. Put into
+ tmpname the address of a newly allocated buffer that holds the
+ file's name. Use the prefix "sdiff". */
+static int
+temporary_file (void)
+{
+ char const *tmpdir = getenv (TMPDIR_ENV);
+ char const *dir = tmpdir ? tmpdir : P_tmpdir;
+ char *buf = xmalloc (strlen (dir) + 1 + 5 + 6 + 1);
+ int fd;
+ int e;
+ sigset_t procmask;
+ sigset_t blocked;
+ sprintf (buf, "%s/sdiffXXXXXX", dir);
+ sigemptyset (&blocked);
+ sigaddset (&blocked, SIGINT);
+ sigprocmask (SIG_BLOCK, &blocked, &procmask);
+ fd = mkstemp (buf);
+ e = errno;
+ if (0 <= fd)
+ tmpname = buf;
+ sigprocmask (SIG_SETMASK, &procmask, 0);
+ errno = e;
+ return fd;
+}
diff --git a/contrib/diff/src/side.c b/contrib/diff/src/side.c
new file mode 100644
index 0000000..3eaef4d
--- /dev/null
+++ b/contrib/diff/src/side.c
@@ -0,0 +1,281 @@
+/* sdiff-format output routines for GNU DIFF.
+
+ Copyright (C) 1991, 1992, 1993, 1998, 2001, 2002, 2004 Free
+ Software Foundation, Inc.
+
+ This file is part of GNU DIFF.
+
+ GNU DIFF is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY. No author or distributor
+ accepts responsibility to anyone for the consequences of using it
+ or for whether it serves any particular purpose or works at all,
+ unless he says so in writing. Refer to the GNU DIFF General Public
+ License for full details.
+
+ Everyone is granted permission to copy, modify and redistribute
+ GNU DIFF, but only under the conditions described in the
+ GNU DIFF General Public License. A copy of this license is
+ supposed to have been given to you along with GNU DIFF so you
+ can know your rights and responsibilities. It should be in a
+ file named COPYING. Among other things, the copyright notice
+ and this notice must be preserved on all copies. */
+
+#include "diff.h"
+
+static void print_sdiff_common_lines (lin, lin);
+static void print_sdiff_hunk (struct change *);
+
+/* Next line number to be printed in the two input files. */
+static lin next0, next1;
+
+/* Print the edit-script SCRIPT as a sdiff style output. */
+
+void
+print_sdiff_script (struct change *script)
+{
+ begin_output ();
+
+ next0 = next1 = - files[0].prefix_lines;
+ print_script (script, find_change, print_sdiff_hunk);
+
+ print_sdiff_common_lines (files[0].valid_lines, files[1].valid_lines);
+}
+
+/* Tab from column FROM to column TO, where FROM <= TO. Yield TO. */
+
+static size_t
+tab_from_to (size_t from, size_t to)
+{
+ FILE *out = outfile;
+ size_t tab;
+ size_t tab_size = tabsize;
+
+ if (!expand_tabs)
+ for (tab = from + tab_size - from % tab_size; tab <= to; tab += tab_size)
+ {
+ putc ('\t', out);
+ from = tab;
+ }
+ while (from++ < to)
+ putc (' ', out);
+ return to;
+}
+
+/* Print the text for half an sdiff line. This means truncate to
+ width observing tabs, and trim a trailing newline. Return the
+ last column written (not the number of chars). */
+
+static size_t
+print_half_line (char const *const *line, size_t indent, size_t out_bound)
+{
+ FILE *out = outfile;
+ register size_t in_position = 0;
+ register size_t out_position = 0;
+ register char const *text_pointer = line[0];
+ register char const *text_limit = line[1];
+
+ while (text_pointer < text_limit)
+ {
+ register unsigned char c = *text_pointer++;
+
+ switch (c)
+ {
+ case '\t':
+ {
+ size_t spaces = tabsize - in_position % tabsize;
+ if (in_position == out_position)
+ {
+ size_t tabstop = out_position + spaces;
+ if (expand_tabs)
+ {
+ if (out_bound < tabstop)
+ tabstop = out_bound;
+ for (; out_position < tabstop; out_position++)
+ putc (' ', out);
+ }
+ else
+ if (tabstop < out_bound)
+ {
+ out_position = tabstop;
+ putc (c, out);
+ }
+ }
+ in_position += spaces;
+ }
+ break;
+
+ case '\r':
+ {
+ putc (c, out);
+ tab_from_to (0, indent);
+ in_position = out_position = 0;
+ }
+ break;
+
+ case '\b':
+ if (in_position != 0 && --in_position < out_bound)
+ {
+ if (out_position <= in_position)
+ /* Add spaces to make up for suppressed tab past out_bound. */
+ for (; out_position < in_position; out_position++)
+ putc (' ', out);
+ else
+ {
+ out_position = in_position;
+ putc (c, out);
+ }
+ }
+ break;
+
+ case '\f':
+ case '\v':
+ control_char:
+ if (in_position < out_bound)
+ putc (c, out);
+ break;
+
+ default:
+ if (! isprint (c))
+ goto control_char;
+ /* falls through */
+ case ' ':
+ if (in_position++ < out_bound)
+ {
+ out_position = in_position;
+ putc (c, out);
+ }
+ break;
+
+ case '\n':
+ return out_position;
+ }
+ }
+
+ return out_position;
+}
+
+/* Print side by side lines with a separator in the middle.
+ 0 parameters are taken to indicate white space text.
+ Blank lines that can easily be caught are reduced to a single newline. */
+
+static void
+print_1sdiff_line (char const *const *left, char sep,
+ char const *const *right)
+{
+ FILE *out = outfile;
+ size_t hw = sdiff_half_width;
+ size_t c2o = sdiff_column2_offset;
+ size_t col = 0;
+ bool put_newline = false;
+
+ if (left)
+ {
+ put_newline |= left[1][-1] == '\n';
+ col = print_half_line (left, 0, hw);
+ }
+
+ if (sep != ' ')
+ {
+ col = tab_from_to (col, (hw + c2o - 1) / 2) + 1;
+ if (sep == '|' && put_newline != (right[1][-1] == '\n'))
+ sep = put_newline ? '/' : '\\';
+ putc (sep, out);
+ }
+
+ if (right)
+ {
+ put_newline |= right[1][-1] == '\n';
+ if (**right != '\n')
+ {
+ col = tab_from_to (col, c2o);
+ print_half_line (right, col, hw);
+ }
+ }
+
+ if (put_newline)
+ putc ('\n', out);
+}
+
+/* Print lines common to both files in side-by-side format. */
+static void
+print_sdiff_common_lines (lin limit0, lin limit1)
+{
+ lin i0 = next0, i1 = next1;
+
+ if (!suppress_common_lines && (i0 != limit0 || i1 != limit1))
+ {
+ if (sdiff_merge_assist)
+ {
+ long int len0 = limit0 - i0;
+ long int len1 = limit1 - i1;
+ fprintf (outfile, "i%ld,%ld\n", len0, len1);
+ }
+
+ if (!left_column)
+ {
+ while (i0 != limit0 && i1 != limit1)
+ print_1sdiff_line (&files[0].linbuf[i0++], ' ',
+ &files[1].linbuf[i1++]);
+ while (i1 != limit1)
+ print_1sdiff_line (0, ')', &files[1].linbuf[i1++]);
+ }
+ while (i0 != limit0)
+ print_1sdiff_line (&files[0].linbuf[i0++], '(', 0);
+ }
+
+ next0 = limit0;
+ next1 = limit1;
+}
+
+/* Print a hunk of an sdiff diff.
+ This is a contiguous portion of a complete edit script,
+ describing changes in consecutive lines. */
+
+static void
+print_sdiff_hunk (struct change *hunk)
+{
+ lin first0, last0, first1, last1;
+ register lin i, j;
+
+ /* Determine range of line numbers involved in each file. */
+ enum changes changes =
+ analyze_hunk (hunk, &first0, &last0, &first1, &last1);
+ if (!changes)
+ return;
+
+ /* Print out lines up to this change. */
+ print_sdiff_common_lines (first0, first1);
+
+ if (sdiff_merge_assist)
+ {
+ long int len0 = last0 - first0 + 1;
+ long int len1 = last1 - first1 + 1;
+ fprintf (outfile, "c%ld,%ld\n", len0, len1);
+ }
+
+ /* Print ``xxx | xxx '' lines */
+ if (changes == CHANGED)
+ {
+ for (i = first0, j = first1; i <= last0 && j <= last1; i++, j++)
+ print_1sdiff_line (&files[0].linbuf[i], '|', &files[1].linbuf[j]);
+ changes = (i <= last0 ? OLD : 0) + (j <= last1 ? NEW : 0);
+ next0 = first0 = i;
+ next1 = first1 = j;
+ }
+
+ /* Print `` > xxx '' lines */
+ if (changes & NEW)
+ {
+ for (j = first1; j <= last1; ++j)
+ print_1sdiff_line (0, '>', &files[1].linbuf[j]);
+ next1 = j;
+ }
+
+ /* Print ``xxx < '' lines */
+ if (changes & OLD)
+ {
+ for (i = first0; i <= last0; ++i)
+ print_1sdiff_line (&files[0].linbuf[i], '<', 0);
+ next0 = i;
+ }
+}
diff --git a/contrib/diff/src/system.h b/contrib/diff/src/system.h
new file mode 100644
index 0000000..e480cc5
--- /dev/null
+++ b/contrib/diff/src/system.h
@@ -0,0 +1,326 @@
+/* System dependent declarations.
+
+ Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1998, 2001, 2002,
+ 2004 Free Software Foundation, Inc.
+
+ This file is part of GNU DIFF.
+
+ GNU DIFF 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.
+
+ GNU DIFF is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <config.h>
+
+/* Don't bother to support K&R C compilers any more; it's not worth
+ the trouble. These macros prevent some library modules from being
+ compiled in K&R C mode. */
+#define PARAMS(Args) Args
+#define PROTOTYPES 1
+
+/* Define `__attribute__' and `volatile' first
+ so that they're used consistently in all system includes. */
+#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 6) || __STRICT_ANSI__
+# define __attribute__(x)
+#endif
+#if defined const && !defined volatile
+# define volatile
+#endif
+
+/* Verify a requirement at compile-time (unlike assert, which is runtime). */
+#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; }
+
+
+/* Determine whether an integer type is signed, and its bounds.
+ This code assumes two's (or one's!) complement with no holes. */
+
+/* The extra casts work around common compiler bugs,
+ e.g. Cray C 5.0.3.0 when t == time_t. */
+#ifndef TYPE_SIGNED
+# define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+#endif
+#ifndef TYPE_MINIMUM
+# define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \
+ ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) \
+ : (t) 0))
+#endif
+#ifndef TYPE_MAXIMUM
+# define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t)))
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifndef S_IRWXU
+# define S_IRWXU 0700
+#endif
+#ifndef S_IRWXG
+# define S_IRWXG 0070
+#endif
+#ifndef S_IRWXO
+# define S_IRWXO 0007
+#endif
+
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#ifndef SEEK_SET
+# define SEEK_SET 0
+#endif
+#ifndef SEEK_CUR
+# define SEEK_CUR 1
+#endif
+
+#ifndef STDIN_FILENO
+# define STDIN_FILENO 0
+#endif
+#ifndef STDOUT_FILENO
+# define STDOUT_FILENO 1
+#endif
+#ifndef STDERR_FILENO
+# define STDERR_FILENO 2
+#endif
+
+#include <time.h>
+
+#if HAVE_FCNTL_H
+# include <fcntl.h>
+#else
+# if HAVE_SYS_FILE_H
+# include <sys/file.h>
+# endif
+#endif
+
+#if !HAVE_DUP2
+# define dup2(f, t) (close (t), fcntl (f, F_DUPFD, t))
+#endif
+
+#ifndef O_RDONLY
+# define O_RDONLY 0
+#endif
+#ifndef O_RDWR
+# define O_RDWR 2
+#endif
+#ifndef S_IRUSR
+# define S_IRUSR 0400
+#endif
+#ifndef S_IWUSR
+# define S_IWUSR 0200
+#endif
+
+#if HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+#endif
+#ifndef WEXITSTATUS
+# define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8)
+#endif
+#ifndef WIFEXITED
+# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+#endif
+
+#ifndef STAT_BLOCKSIZE
+# if HAVE_STRUCT_STAT_ST_BLKSIZE
+# define STAT_BLOCKSIZE(s) ((s).st_blksize)
+# else
+# define STAT_BLOCKSIZE(s) (8 * 1024)
+# endif
+#endif
+
+#if HAVE_DIRENT_H
+# include <dirent.h>
+# define NAMLEN(dirent) strlen ((dirent)->d_name)
+#else
+# define dirent direct
+# define NAMLEN(dirent) ((dirent)->d_namlen)
+# if HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# endif
+# if HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif
+# if HAVE_NDIR_H
+# include <ndir.h>
+# endif
+#endif
+
+#include <stdlib.h>
+#define EXIT_TROUBLE 2
+
+#include <limits.h>
+
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifndef PTRDIFF_MAX
+# define PTRDIFF_MAX TYPE_MAXIMUM (ptrdiff_t)
+#endif
+#ifndef SIZE_MAX
+# define SIZE_MAX TYPE_MAXIMUM (size_t)
+#endif
+#ifndef UINTMAX_MAX
+# define UINTMAX_MAX TYPE_MAXIMUM (uintmax_t)
+#endif
+#if ! HAVE_STRTOUMAX && ! defined strtoumax
+uintmax_t strtoumax (char const *, char **, int);
+#endif
+
+#include <stddef.h>
+
+#include <string.h>
+#if ! HAVE_STRCASECOLL
+# if HAVE_STRICOLL || defined stricoll
+# define strcasecoll(a, b) stricoll (a, b)
+# else
+# define strcasecoll(a, b) strcasecmp (a, b) /* best we can do */
+# endif
+#endif
+#if ! (HAVE_STRCASECMP || defined strcasecmp)
+int strcasecmp (char const *, char const *);
+#endif
+
+#if HAVE_LOCALE_H
+# include <locale.h>
+#else
+# define setlocale(category, locale)
+#endif
+
+#include <gettext.h>
+
+#define _(msgid) gettext (msgid)
+#define N_(msgid) msgid
+
+#include <ctype.h>
+
+/* ISDIGIT differs from isdigit, as follows:
+ - Its arg may be any int or unsigned int; it need not be an unsigned char.
+ - It's guaranteed to evaluate its argument exactly once.
+ - It's typically faster.
+ POSIX 1003.1-2001 says that only '0' through '9' are digits.
+ Prefer ISDIGIT to isdigit unless it's important to use the locale's
+ definition of `digit' even when the host does not conform to POSIX. */
+#define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9)
+
+#include <errno.h>
+
+#include <signal.h>
+#ifndef SA_RESTART
+# ifdef SA_INTERRUPT /* e.g. SunOS 4.1.x */
+# define SA_RESTART SA_INTERRUPT
+# else
+# define SA_RESTART 0
+# endif
+#endif
+#if !defined SIGCHLD && defined SIGCLD
+# define SIGCHLD SIGCLD
+#endif
+
+#undef MIN
+#undef MAX
+#define MIN(a, b) ((a) <= (b) ? (a) : (b))
+#define MAX(a, b) ((a) >= (b) ? (a) : (b))
+
+#include <stdbool.h>
+
+#if HAVE_VFORK_H
+# include <vfork.h>
+#endif
+
+#if ! HAVE_WORKING_VFORK
+# define vfork fork
+#endif
+
+/* Type used for fast comparison of several bytes at a time. */
+
+#ifndef word
+# define word uintmax_t
+#endif
+
+/* The integer type of a line number. Since files are read into main
+ memory, ptrdiff_t should be wide enough. */
+
+typedef ptrdiff_t lin;
+#define LIN_MAX PTRDIFF_MAX
+verify (lin_is_signed, TYPE_SIGNED (lin));
+verify (lin_is_wide_enough, sizeof (ptrdiff_t) <= sizeof (lin));
+verify (lin_is_printable_as_long_int, sizeof (lin) <= sizeof (long int));
+
+/* This section contains POSIX-compliant defaults for macros
+ that are meant to be overridden by hand in config.h as needed. */
+
+#ifndef file_name_cmp
+# define file_name_cmp strcmp
+#endif
+
+#ifndef initialize_main
+# define initialize_main(argcp, argvp)
+#endif
+
+#ifndef NULL_DEVICE
+# define NULL_DEVICE "/dev/null"
+#endif
+
+/* Do struct stat *S, *T describe the same special file? */
+#ifndef same_special_file
+# if HAVE_ST_RDEV && defined S_ISBLK && defined S_ISCHR
+# define same_special_file(s, t) \
+ (((S_ISBLK ((s)->st_mode) && S_ISBLK ((t)->st_mode)) \
+ || (S_ISCHR ((s)->st_mode) && S_ISCHR ((t)->st_mode))) \
+ && (s)->st_rdev == (t)->st_rdev)
+# else
+# define same_special_file(s, t) 0
+# endif
+#endif
+
+/* Do struct stat *S, *T describe the same file? Answer -1 if unknown. */
+#ifndef same_file
+# define same_file(s, t) \
+ ((((s)->st_ino == (t)->st_ino) && ((s)->st_dev == (t)->st_dev)) \
+ || same_special_file (s, t))
+#endif
+
+/* Do struct stat *S, *T have the same file attributes?
+
+ POSIX says that two files are identical if st_ino and st_dev are
+ the same, but many filesystems incorrectly assign the same (device,
+ inode) pair to two distinct files, including:
+
+ - GNU/Linux NFS servers that export all local filesystems as a
+ single NFS filesystem, if a local device number (st_dev) exceeds
+ 255, or if a local inode number (st_ino) exceeds 16777215.
+
+ - Network Appliance NFS servers in snapshot directories; see
+ Network Appliance bug #195.
+
+ - ClearCase MVFS; see bug id ATRia04618.
+
+ Check whether two files that purport to be the same have the same
+ attributes, to work around instances of this common bug. Do not
+ inspect all attributes, only attributes useful in checking for this
+ bug.
+
+ It's possible for two distinct files on a buggy filesystem to have
+ the same attributes, but it's not worth slowing down all
+ implementations (or complicating the configuration) to cater to
+ these rare cases in buggy implementations. */
+
+#ifndef same_file_attributes
+# define same_file_attributes(s, t) \
+ ((s)->st_mode == (t)->st_mode \
+ && (s)->st_nlink == (t)->st_nlink \
+ && (s)->st_uid == (t)->st_uid \
+ && (s)->st_gid == (t)->st_gid \
+ && (s)->st_size == (t)->st_size \
+ && (s)->st_mtime == (t)->st_mtime \
+ && (s)->st_ctime == (t)->st_ctime)
+#endif
diff --git a/contrib/diff/src/util.c b/contrib/diff/src/util.c
new file mode 100644
index 0000000..809f125
--- /dev/null
+++ b/contrib/diff/src/util.c
@@ -0,0 +1,775 @@
+/* Support routines for GNU DIFF.
+
+ Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1998, 2001, 2002,
+ 2004 Free Software Foundation, Inc.
+
+ This file is part of GNU DIFF.
+
+ GNU DIFF 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.
+
+ GNU DIFF is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "diff.h"
+#include <dirname.h>
+#include <error.h>
+#include <quotesys.h>
+#include <xalloc.h>
+
+char const pr_program[] = PR_PROGRAM;
+
+/* Queue up one-line messages to be printed at the end,
+ when -l is specified. Each message is recorded with a `struct msg'. */
+
+struct msg
+{
+ struct msg *next;
+ char args[1]; /* Format + 4 args, each '\0' terminated, concatenated. */
+};
+
+/* Head of the chain of queues messages. */
+
+static struct msg *msg_chain;
+
+/* Tail of the chain of queues messages. */
+
+static struct msg **msg_chain_end = &msg_chain;
+
+/* Use when a system call returns non-zero status.
+ NAME should normally be the file name. */
+
+void
+perror_with_name (char const *name)
+{
+ error (0, errno, "%s", name);
+}
+
+/* Use when a system call returns non-zero status and that is fatal. */
+
+void
+pfatal_with_name (char const *name)
+{
+ int e = errno;
+ print_message_queue ();
+ error (EXIT_TROUBLE, e, "%s", name);
+ abort ();
+}
+
+/* Print an error message containing MSGID, then exit. */
+
+void
+fatal (char const *msgid)
+{
+ print_message_queue ();
+ error (EXIT_TROUBLE, 0, "%s", _(msgid));
+ abort ();
+}
+
+/* Like printf, except if -l in effect then save the message and print later.
+ This is used for things like "Only in ...". */
+
+void
+message (char const *format_msgid, char const *arg1, char const *arg2)
+{
+ message5 (format_msgid, arg1, arg2, 0, 0);
+}
+
+void
+message5 (char const *format_msgid, char const *arg1, char const *arg2,
+ char const *arg3, char const *arg4)
+{
+ if (paginate)
+ {
+ char *p;
+ char const *arg[5];
+ int i;
+ size_t size[5];
+ size_t total_size = offsetof (struct msg, args);
+ struct msg *new;
+
+ arg[0] = format_msgid;
+ arg[1] = arg1;
+ arg[2] = arg2;
+ arg[3] = arg3 ? arg3 : "";
+ arg[4] = arg4 ? arg4 : "";
+
+ for (i = 0; i < 5; i++)
+ total_size += size[i] = strlen (arg[i]) + 1;
+
+ new = xmalloc (total_size);
+
+ for (i = 0, p = new->args; i < 5; p += size[i++])
+ memcpy (p, arg[i], size[i]);
+
+ *msg_chain_end = new;
+ new->next = 0;
+ msg_chain_end = &new->next;
+ }
+ else
+ {
+ if (sdiff_merge_assist)
+ putchar (' ');
+ printf (_(format_msgid), arg1, arg2, arg3, arg4);
+ }
+}
+
+/* Output all the messages that were saved up by calls to `message'. */
+
+void
+print_message_queue (void)
+{
+ char const *arg[5];
+ int i;
+ struct msg *m = msg_chain;
+
+ while (m)
+ {
+ struct msg *next = m->next;
+ arg[0] = m->args;
+ for (i = 0; i < 4; i++)
+ arg[i + 1] = arg[i] + strlen (arg[i]) + 1;
+ printf (_(arg[0]), arg[1], arg[2], arg[3], arg[4]);
+ free (m);
+ m = next;
+ }
+}
+
+/* Call before outputting the results of comparing files NAME0 and NAME1
+ to set up OUTFILE, the stdio stream for the output to go to.
+
+ Usually, OUTFILE is just stdout. But when -l was specified
+ we fork off a `pr' and make OUTFILE a pipe to it.
+ `pr' then outputs to our stdout. */
+
+static char const *current_name0;
+static char const *current_name1;
+static bool currently_recursive;
+
+void
+setup_output (char const *name0, char const *name1, bool recursive)
+{
+ current_name0 = name0;
+ current_name1 = name1;
+ currently_recursive = recursive;
+ outfile = 0;
+}
+
+#if HAVE_WORKING_FORK || HAVE_WORKING_VFORK
+static pid_t pr_pid;
+#endif
+
+void
+begin_output (void)
+{
+ char *name;
+
+ if (outfile != 0)
+ return;
+
+ /* Construct the header of this piece of diff. */
+ name = xmalloc (strlen (current_name0) + strlen (current_name1)
+ + strlen (switch_string) + 7);
+
+ /* POSIX 1003.1-2001 specifies this format. But there are some bugs in
+ the standard: it says that we must print only the last component
+ of the pathnames, and it requires two spaces after "diff" if
+ there are no options. These requirements are silly and do not
+ match historical practice. */
+ sprintf (name, "diff%s %s %s", switch_string, current_name0, current_name1);
+
+ if (paginate)
+ {
+ if (fflush (stdout) != 0)
+ pfatal_with_name (_("write failed"));
+
+ /* Make OUTFILE a pipe to a subsidiary `pr'. */
+ {
+#if HAVE_WORKING_FORK || HAVE_WORKING_VFORK
+ int pipes[2];
+
+ if (pipe (pipes) != 0)
+ pfatal_with_name ("pipe");
+
+ pr_pid = vfork ();
+ if (pr_pid < 0)
+ pfatal_with_name ("fork");
+
+ if (pr_pid == 0)
+ {
+ close (pipes[1]);
+ if (pipes[0] != STDIN_FILENO)
+ {
+ if (dup2 (pipes[0], STDIN_FILENO) < 0)
+ pfatal_with_name ("dup2");
+ close (pipes[0]);
+ }
+
+ execl (pr_program, pr_program, "-h", name, (char *) 0);
+ _exit (errno == ENOENT ? 127 : 126);
+ }
+ else
+ {
+ close (pipes[0]);
+ outfile = fdopen (pipes[1], "w");
+ if (!outfile)
+ pfatal_with_name ("fdopen");
+ }
+#else
+ char *command = xmalloc (sizeof pr_program - 1 + 7
+ + quote_system_arg ((char *) 0, name) + 1);
+ char *p;
+ sprintf (command, "%s -f -h ", pr_program);
+ p = command + sizeof pr_program - 1 + 7;
+ p += quote_system_arg (p, name);
+ *p = 0;
+ errno = 0;
+ outfile = popen (command, "w");
+ if (!outfile)
+ pfatal_with_name (command);
+ free (command);
+#endif
+ }
+ }
+ else
+ {
+
+ /* If -l was not specified, output the diff straight to `stdout'. */
+
+ outfile = stdout;
+
+ /* If handling multiple files (because scanning a directory),
+ print which files the following output is about. */
+ if (currently_recursive)
+ printf ("%s\n", name);
+ }
+
+ free (name);
+
+ /* A special header is needed at the beginning of context output. */
+ switch (output_style)
+ {
+ case OUTPUT_CONTEXT:
+ print_context_header (files, false);
+ break;
+
+ case OUTPUT_UNIFIED:
+ print_context_header (files, true);
+ break;
+
+ default:
+ break;
+ }
+}
+
+/* Call after the end of output of diffs for one file.
+ Close OUTFILE and get rid of the `pr' subfork. */
+
+void
+finish_output (void)
+{
+ if (outfile != 0 && outfile != stdout)
+ {
+ int status;
+ int wstatus;
+ int werrno = 0;
+ if (ferror (outfile))
+ fatal ("write failed");
+#if ! (HAVE_WORKING_FORK || HAVE_WORKING_VFORK)
+ wstatus = pclose (outfile);
+ if (wstatus == -1)
+ werrno = errno;
+#else
+ if (fclose (outfile) != 0)
+ pfatal_with_name (_("write failed"));
+ if (waitpid (pr_pid, &wstatus, 0) < 0)
+ pfatal_with_name ("waitpid");
+#endif
+ status = (! werrno && WIFEXITED (wstatus)
+ ? WEXITSTATUS (wstatus)
+ : INT_MAX);
+ if (status)
+ error (EXIT_TROUBLE, werrno,
+ _(status == 126
+ ? "subsidiary program `%s' could not be invoked"
+ : status == 127
+ ? "subsidiary program `%s' not found"
+ : status == INT_MAX
+ ? "subsidiary program `%s' failed"
+ : "subsidiary program `%s' failed (exit status %d)"),
+ pr_program, status);
+ }
+
+ outfile = 0;
+}
+
+/* Compare two lines (typically one from each input file)
+ according to the command line options.
+ For efficiency, this is invoked only when the lines do not match exactly
+ but an option like -i might cause us to ignore the difference.
+ Return nonzero if the lines differ. */
+
+bool
+lines_differ (char const *s1, char const *s2)
+{
+ register char const *t1 = s1;
+ register char const *t2 = s2;
+ size_t column = 0;
+
+ while (1)
+ {
+ register unsigned char c1 = *t1++;
+ register unsigned char c2 = *t2++;
+
+ /* Test for exact char equality first, since it's a common case. */
+ if (c1 != c2)
+ {
+ switch (ignore_white_space)
+ {
+ case IGNORE_ALL_SPACE:
+ /* For -w, just skip past any white space. */
+ while (isspace (c1) && c1 != '\n') c1 = *t1++;
+ while (isspace (c2) && c2 != '\n') c2 = *t2++;
+ break;
+
+ case IGNORE_SPACE_CHANGE:
+ /* For -b, advance past any sequence of white space in
+ line 1 and consider it just one space, or nothing at
+ all if it is at the end of the line. */
+ if (isspace (c1))
+ {
+ while (c1 != '\n')
+ {
+ c1 = *t1++;
+ if (! isspace (c1))
+ {
+ --t1;
+ c1 = ' ';
+ break;
+ }
+ }
+ }
+
+ /* Likewise for line 2. */
+ if (isspace (c2))
+ {
+ while (c2 != '\n')
+ {
+ c2 = *t2++;
+ if (! isspace (c2))
+ {
+ --t2;
+ c2 = ' ';
+ break;
+ }
+ }
+ }
+
+ if (c1 != c2)
+ {
+ /* If we went too far when doing the simple test
+ for equality, go back to the first non-white-space
+ character in both sides and try again. */
+ if (c2 == ' ' && c1 != '\n'
+ && s1 + 1 < t1
+ && isspace ((unsigned char) t1[-2]))
+ {
+ --t1;
+ continue;
+ }
+ if (c1 == ' ' && c2 != '\n'
+ && s2 + 1 < t2
+ && isspace ((unsigned char) t2[-2]))
+ {
+ --t2;
+ continue;
+ }
+ }
+
+ break;
+
+ case IGNORE_TAB_EXPANSION:
+ if ((c1 == ' ' && c2 == '\t')
+ || (c1 == '\t' && c2 == ' '))
+ {
+ size_t column2 = column;
+ for (;; c1 = *t1++)
+ {
+ if (c1 == ' ')
+ column++;
+ else if (c1 == '\t')
+ column += tabsize - column % tabsize;
+ else
+ break;
+ }
+ for (;; c2 = *t2++)
+ {
+ if (c2 == ' ')
+ column2++;
+ else if (c2 == '\t')
+ column2 += tabsize - column2 % tabsize;
+ else
+ break;
+ }
+ if (column != column2)
+ return true;
+ }
+ break;
+
+ case IGNORE_NO_WHITE_SPACE:
+ break;
+ }
+
+ /* Lowercase all letters if -i is specified. */
+
+ if (ignore_case)
+ {
+ c1 = tolower (c1);
+ c2 = tolower (c2);
+ }
+
+ if (c1 != c2)
+ break;
+ }
+ if (c1 == '\n')
+ return false;
+
+ column += c1 == '\t' ? tabsize - column % tabsize : 1;
+ }
+
+ return true;
+}
+
+/* Find the consecutive changes at the start of the script START.
+ Return the last link before the first gap. */
+
+struct change *
+find_change (struct change *start)
+{
+ return start;
+}
+
+struct change *
+find_reverse_change (struct change *start)
+{
+ return start;
+}
+
+/* Divide SCRIPT into pieces by calling HUNKFUN and
+ print each piece with PRINTFUN.
+ Both functions take one arg, an edit script.
+
+ HUNKFUN is called with the tail of the script
+ and returns the last link that belongs together with the start
+ of the tail.
+
+ PRINTFUN takes a subscript which belongs together (with a null
+ link at the end) and prints it. */
+
+void
+print_script (struct change *script,
+ struct change * (*hunkfun) (struct change *),
+ void (*printfun) (struct change *))
+{
+ struct change *next = script;
+
+ while (next)
+ {
+ struct change *this, *end;
+
+ /* Find a set of changes that belong together. */
+ this = next;
+ end = (*hunkfun) (next);
+
+ /* Disconnect them from the rest of the changes,
+ making them a hunk, and remember the rest for next iteration. */
+ next = end->link;
+ end->link = 0;
+#ifdef DEBUG
+ debug_script (this);
+#endif
+
+ /* Print this hunk. */
+ (*printfun) (this);
+
+ /* Reconnect the script so it will all be freed properly. */
+ end->link = next;
+ }
+}
+
+/* Print the text of a single line LINE,
+ flagging it with the characters in LINE_FLAG (which say whether
+ the line is inserted, deleted, changed, etc.). */
+
+void
+print_1_line (char const *line_flag, char const *const *line)
+{
+ char const *base = line[0], *limit = line[1]; /* Help the compiler. */
+ FILE *out = outfile; /* Help the compiler some more. */
+ char const *flag_format = 0;
+
+ /* If -T was specified, use a Tab between the line-flag and the text.
+ Otherwise use a Space (as Unix diff does).
+ Print neither space nor tab if line-flags are empty. */
+
+ if (line_flag && *line_flag)
+ {
+ flag_format = initial_tab ? "%s\t" : "%s ";
+ fprintf (out, flag_format, line_flag);
+ }
+
+ output_1_line (base, limit, flag_format, line_flag);
+
+ if ((!line_flag || line_flag[0]) && limit[-1] != '\n')
+ fprintf (out, "\n\\ %s\n", _("No newline at end of file"));
+}
+
+/* Output a line from BASE up to LIMIT.
+ With -t, expand white space characters to spaces, and if FLAG_FORMAT
+ is nonzero, output it with argument LINE_FLAG after every
+ internal carriage return, so that tab stops continue to line up. */
+
+void
+output_1_line (char const *base, char const *limit, char const *flag_format,
+ char const *line_flag)
+{
+ if (!expand_tabs)
+ fwrite (base, sizeof (char), limit - base, outfile);
+ else
+ {
+ register FILE *out = outfile;
+ register unsigned char c;
+ register char const *t = base;
+ register size_t column = 0;
+ size_t tab_size = tabsize;
+
+ while (t < limit)
+ switch ((c = *t++))
+ {
+ case '\t':
+ {
+ size_t spaces = tab_size - column % tab_size;
+ column += spaces;
+ do
+ putc (' ', out);
+ while (--spaces);
+ }
+ break;
+
+ case '\r':
+ putc (c, out);
+ if (flag_format && t < limit && *t != '\n')
+ fprintf (out, flag_format, line_flag);
+ column = 0;
+ break;
+
+ case '\b':
+ if (column == 0)
+ continue;
+ column--;
+ putc (c, out);
+ break;
+
+ default:
+ column += isprint (c) != 0;
+ putc (c, out);
+ break;
+ }
+ }
+}
+
+char const change_letter[] = { 0, 'd', 'a', 'c' };
+
+/* Translate an internal line number (an index into diff's table of lines)
+ into an actual line number in the input file.
+ The internal line number is I. FILE points to the data on the file.
+
+ Internal line numbers count from 0 starting after the prefix.
+ Actual line numbers count from 1 within the entire file. */
+
+lin
+translate_line_number (struct file_data const *file, lin i)
+{
+ return i + file->prefix_lines + 1;
+}
+
+/* Translate a line number range. This is always done for printing,
+ so for convenience translate to long int rather than lin, so that the
+ caller can use printf with "%ld" without casting. */
+
+void
+translate_range (struct file_data const *file,
+ lin a, lin b,
+ long int *aptr, long int *bptr)
+{
+ *aptr = translate_line_number (file, a - 1) + 1;
+ *bptr = translate_line_number (file, b + 1) - 1;
+}
+
+/* Print a pair of line numbers with SEPCHAR, translated for file FILE.
+ If the two numbers are identical, print just one number.
+
+ Args A and B are internal line numbers.
+ We print the translated (real) line numbers. */
+
+void
+print_number_range (char sepchar, struct file_data *file, lin a, lin b)
+{
+ long int trans_a, trans_b;
+ translate_range (file, a, b, &trans_a, &trans_b);
+
+ /* Note: we can have B < A in the case of a range of no lines.
+ In this case, we should print the line number before the range,
+ which is B. */
+ if (trans_b > trans_a)
+ fprintf (outfile, "%ld%c%ld", trans_a, sepchar, trans_b);
+ else
+ fprintf (outfile, "%ld", trans_b);
+}
+
+/* Look at a hunk of edit script and report the range of lines in each file
+ that it applies to. HUNK is the start of the hunk, which is a chain
+ of `struct change'. The first and last line numbers of file 0 are stored in
+ *FIRST0 and *LAST0, and likewise for file 1 in *FIRST1 and *LAST1.
+ Note that these are internal line numbers that count from 0.
+
+ If no lines from file 0 are deleted, then FIRST0 is LAST0+1.
+
+ Return UNCHANGED if only ignorable lines are inserted or deleted,
+ OLD if lines of file 0 are deleted,
+ NEW if lines of file 1 are inserted,
+ and CHANGED if both kinds of changes are found. */
+
+enum changes
+analyze_hunk (struct change *hunk,
+ lin *first0, lin *last0,
+ lin *first1, lin *last1)
+{
+ struct change *next;
+ lin l0, l1;
+ lin show_from, show_to;
+ lin i;
+ bool trivial = ignore_blank_lines || ignore_regexp.fastmap;
+ size_t trivial_length = ignore_blank_lines - 1;
+ /* If 0, ignore zero-length lines;
+ if SIZE_MAX, do not ignore lines just because of their length. */
+ bool skip_leading_white_space =
+ (ignore_blank_lines && IGNORE_SPACE_CHANGE <= ignore_white_space);
+
+ char const * const *linbuf0 = files[0].linbuf; /* Help the compiler. */
+ char const * const *linbuf1 = files[1].linbuf;
+
+ show_from = show_to = 0;
+
+ *first0 = hunk->line0;
+ *first1 = hunk->line1;
+
+ next = hunk;
+ do
+ {
+ l0 = next->line0 + next->deleted - 1;
+ l1 = next->line1 + next->inserted - 1;
+ show_from += next->deleted;
+ show_to += next->inserted;
+
+ for (i = next->line0; i <= l0 && trivial; i++)
+ {
+ char const *line = linbuf0[i];
+ char const *newline = linbuf0[i + 1] - 1;
+ size_t len = newline - line;
+ char const *p = line;
+ if (skip_leading_white_space)
+ while (isspace ((unsigned char) *p) && *p != '\n')
+ p++;
+ if (newline - p != trivial_length
+ && (! ignore_regexp.fastmap
+ || re_search (&ignore_regexp, line, len, 0, len, 0) < 0))
+ trivial = 0;
+ }
+
+ for (i = next->line1; i <= l1 && trivial; i++)
+ {
+ char const *line = linbuf1[i];
+ char const *newline = linbuf1[i + 1] - 1;
+ size_t len = newline - line;
+ char const *p = line;
+ if (skip_leading_white_space)
+ while (isspace ((unsigned char) *p) && *p != '\n')
+ p++;
+ if (newline - p != trivial_length
+ && (! ignore_regexp.fastmap
+ || re_search (&ignore_regexp, line, len, 0, len, 0) < 0))
+ trivial = 0;
+ }
+ }
+ while ((next = next->link) != 0);
+
+ *last0 = l0;
+ *last1 = l1;
+
+ /* If all inserted or deleted lines are ignorable,
+ tell the caller to ignore this hunk. */
+
+ if (trivial)
+ return UNCHANGED;
+
+ return (show_from ? OLD : UNCHANGED) | (show_to ? NEW : UNCHANGED);
+}
+
+/* Concatenate three strings, returning a newly malloc'd string. */
+
+char *
+concat (char const *s1, char const *s2, char const *s3)
+{
+ char *new = xmalloc (strlen (s1) + strlen (s2) + strlen (s3) + 1);
+ sprintf (new, "%s%s%s", s1, s2, s3);
+ return new;
+}
+
+/* Yield a new block of SIZE bytes, initialized to zero. */
+
+void *
+zalloc (size_t size)
+{
+ void *p = xmalloc (size);
+ memset (p, 0, size);
+ return p;
+}
+
+/* Yield the newly malloc'd pathname
+ of the file in DIR whose filename is FILE. */
+
+char *
+dir_file_pathname (char const *dir, char const *file)
+{
+ char const *base = base_name (dir);
+ bool omit_slash = !*base || base[strlen (base) - 1] == '/';
+ return concat (dir, "/" + omit_slash, file);
+}
+
+void
+debug_script (struct change *sp)
+{
+ fflush (stdout);
+
+ for (; sp; sp = sp->link)
+ {
+ long int line0 = sp->line0;
+ long int line1 = sp->line1;
+ long int deleted = sp->deleted;
+ long int inserted = sp->inserted;
+ fprintf (stderr, "%3ld %3ld delete %ld insert %ld\n",
+ line0, line1, deleted, inserted);
+ }
+
+ fflush (stderr);
+}
OpenPOWER on IntegriCloud