# This is a shell archive. Save it in a file, remove anything before # this line, and then unpack it by entering "sh file". Note, it may # create directories; files and directories will be owned by you and # have default permissions. # # This archive contains: # # contrib/diff/ # contrib/diff/README # contrib/diff/ABOUT-NLS # contrib/diff/AUTHORS # contrib/diff/COPYING # contrib/diff/ChangeLog # contrib/diff/Makefile.am # contrib/diff/NEWS # contrib/diff/THANKS # contrib/diff/exgettext # contrib/diff/INSTALLME # contrib/diff/doc # contrib/diff/doc/fdl.texi # contrib/diff/doc/Makefile.am # contrib/diff/doc/stamp-vti # contrib/diff/doc/version.texi # contrib/diff/doc/diff.texi # contrib/diff/doc/diagmeet.note # contrib/diff/doc/diff.info # contrib/diff/lib # contrib/diff/lib/c-stack.h # contrib/diff/lib/cmpbuf.h # contrib/diff/lib/dirname.h # contrib/diff/lib/error.h # contrib/diff/lib/exclude.h # contrib/diff/lib/exitfail.h # contrib/diff/lib/fnmatch.hin # contrib/diff/lib/freesoft.h # contrib/diff/lib/getopt.h # contrib/diff/lib/gettext.h # contrib/diff/lib/hard-locale.h # contrib/diff/lib/inttostr.h # contrib/diff/lib/prepargs.h # contrib/diff/lib/posixver.h # contrib/diff/lib/quotesys.h # contrib/diff/lib/regex.hin # contrib/diff/lib/setmode.h # contrib/diff/lib/unlocked-io.h # contrib/diff/lib/xalloc.h # contrib/diff/lib/xstrtol.h # contrib/diff/lib/Makefile.am # contrib/diff/lib/alloca.c # contrib/diff/lib/fnmatch.c # contrib/diff/lib/malloc.c # contrib/diff/lib/memchr.c # contrib/diff/lib/mkstemp.c # contrib/diff/lib/realloc.c # contrib/diff/lib/regex.c # contrib/diff/lib/strcasecmp.c # contrib/diff/lib/strtoul.c # contrib/diff/lib/strtoull.c # contrib/diff/lib/strtoumax.c # contrib/diff/lib/tempname.c # contrib/diff/lib/waitpid.c # contrib/diff/lib/basename.c # contrib/diff/lib/c-stack.c # contrib/diff/lib/cmpbuf.c # contrib/diff/lib/error.c # contrib/diff/lib/exclude.c # contrib/diff/lib/exitfail.c # contrib/diff/lib/freesoft.c # contrib/diff/lib/getopt.c # contrib/diff/lib/getopt1.c # contrib/diff/lib/hard-locale.c # contrib/diff/lib/imaxtostr.c # contrib/diff/lib/offtostr.c # contrib/diff/lib/prepargs.c # contrib/diff/lib/posixver.c # contrib/diff/lib/quotesys.c # contrib/diff/lib/setmode.c # contrib/diff/lib/strftime.c # contrib/diff/lib/umaxtostr.c # contrib/diff/lib/xmalloc.c # contrib/diff/lib/xstrtoumax.c # contrib/diff/lib/inttostr.c # contrib/diff/lib/strtoimax.c # contrib/diff/lib/strtol.c # contrib/diff/lib/xstrtol.c # contrib/diff/lib/posix # contrib/diff/lib/posix/Makefile.am # contrib/diff/lib/posix/regex.h # contrib/diff/src # contrib/diff/src/diff.h # contrib/diff/src/system.h # contrib/diff/src/Makefile.am # contrib/diff/src/cmp.c # contrib/diff/src/version.c # contrib/diff/src/analyze.c # contrib/diff/src/context.c # contrib/diff/src/diff.c # contrib/diff/src/dir.c # contrib/diff/src/ed.c # contrib/diff/src/ifdef.c # contrib/diff/src/io.c # contrib/diff/src/normal.c # contrib/diff/src/side.c # contrib/diff/src/util.c # contrib/diff/src/diff3.c # contrib/diff/src/sdiff.c # contrib/diff/man # contrib/diff/man/cmp.1 # contrib/diff/man/diff.1 # contrib/diff/man/diff3.1 # contrib/diff/man/sdiff.1 # contrib/diff/man/Makefile.am # echo c - contrib/diff/ mkdir -p contrib/diff/ > /dev/null 2>&1 echo x - contrib/diff/README sed 's/^X//' >contrib/diff/README << 'END-of-contrib/diff/README' XREADME for GNU DIFF X X Copyright (C) 1992, 1998, 2001, 2002 Free Software Foundation, Inc. X X This file is part of GNU Diffutils. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; see the file COPYING. If not, write to X the Free Software Foundation, Inc., 59 Temple Place - Suite 330, X Boston, MA 02111-1307, USA. X X XThis directory contains the GNU diff, diff3, sdiff, and cmp utilities. XTheir features are a superset of the Unix features and they are Xsignificantly faster. X XPlease see the file COPYING for copying conditions. X XPlease see the file doc/diff.texi (or doc/diff.info) for documentation Xthat can be printed with TeX, or read with the `info' program or with XEmacs's `M-x info'. There are no man pages. X XSee the file INSTALL for generic compilation and installation instructions, Xand the file INSTALLME for instructions specific to GNU diff. X XSee the file ABOUT-NLS for notes about translations. X XPlease report bugs to . END-of-contrib/diff/README echo x - contrib/diff/ABOUT-NLS sed 's/^X//' >contrib/diff/ABOUT-NLS << 'END-of-contrib/diff/ABOUT-NLS' XNotes on the Free Translation Project X************************************* X X Free software is going international! The Free Translation Project Xis a way to get maintainers of free software, translators, and users all Xtogether, so that will gradually become able to speak many languages. XA few packages already provide translations for their messages. X X If you found this `ABOUT-NLS' file inside a distribution, you may Xassume that the distributed package does use GNU `gettext' internally, Xitself available at your nearest GNU archive site. But you do _not_ Xneed to install GNU `gettext' prior to configuring, installing or using Xthis package with messages translated. X X Installers will find here some useful hints. These notes also Xexplain how users should proceed for getting the programs to use the Xavailable translations. They tell how people wanting to contribute and Xwork at translations should contact the appropriate team. X X When reporting bugs in the `intl/' directory or bugs which may be Xrelated to internationalization, you should tell about the version of X`gettext' which is used. The information can be found in the X`intl/VERSION' file, in internationalized packages. X XQuick configuration advice X========================== X X If you want to exploit the full power of internationalization, you Xshould configure it using X X ./configure --with-included-gettext X Xto force usage of internationalizing routines provided within this Xpackage, despite the existence of internationalizing capabilities in the Xoperating system where this package is being installed. So far, only Xthe `gettext' implementation in the GNU C library version 2 provides as Xmany features (such as locale alias, message inheritance, automatic Xcharset conversion or plural form handling) as the implementation here. XIt is also not possible to offer this additional functionality on top Xof a `catgets' implementation. Future versions of GNU `gettext' will Xvery likely convey even more functionality. So it might be a good idea Xto change to GNU `gettext' as soon as possible. X X So you need _not_ provide this option if you are using GNU libc 2 or Xyou have installed a recent copy of the GNU gettext package with the Xincluded `libintl'. X XINSTALL Matters X=============== X X Some packages are "localizable" when properly installed; the Xprograms they contain can be made to speak your own native language. XMost such packages use GNU `gettext'. Other packages have their own Xways to internationalization, predating GNU `gettext'. X X By default, this package will be installed to allow translation of Xmessages. It will automatically detect whether the system already Xprovides the GNU `gettext' functions. If not, the GNU `gettext' own Xlibrary will be used. This library is wholly contained within this Xpackage, usually in the `intl/' subdirectory, so prior installation of Xthe GNU `gettext' package is _not_ required. Installers may use Xspecial options at configuration time for changing the default Xbehaviour. The commands: X X ./configure --with-included-gettext X ./configure --disable-nls X Xwill respectively bypass any pre-existing `gettext' to use the Xinternationalizing routines provided within this package, or else, X_totally_ disable translation of messages. X X When you already have GNU `gettext' installed on your system and run Xconfigure without an option for your new package, `configure' will Xprobably detect the previously built and installed `libintl.a' file and Xwill decide to use this. This might be not what is desirable. You Xshould use the more recent version of the GNU `gettext' library. I.e. Xif the file `intl/VERSION' shows that the library which comes with this Xpackage is more recent, you should use X X ./configure --with-included-gettext X Xto prevent auto-detection. X X The configuration process will not test for the `catgets' function Xand therefore it will not be used. The reason is that even an Xemulation of `gettext' on top of `catgets' could not provide all the Xextensions of the GNU `gettext' library. X X Internationalized packages have usually many `po/LL.po' files, where XLL gives an ISO 639 two-letter code identifying the language. Unless Xtranslations have been forbidden at `configure' time by using the X`--disable-nls' switch, all available translations are installed Xtogether with the package. However, the environment variable `LINGUAS' Xmay be set, prior to configuration, to limit the installed set. X`LINGUAS' should then contain a space separated list of two-letter Xcodes, stating which languages are allowed. X XUsing This Package X================== X X As a user, if your language has been installed for this package, you Xonly have to set the `LANG' environment variable to the appropriate X`LL_CC' combination. Here `LL' is an ISO 639 two-letter language code, Xand `CC' is an ISO 3166 two-letter country code. For example, let's Xsuppose that you speak German and live in Germany. At the shell Xprompt, merely execute `setenv LANG de_DE' (in `csh'), X`export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash'). XThis can be done from your `.login' or `.profile' file, once and for Xall. X X You might think that the country code specification is redundant. XBut in fact, some languages have dialects in different countries. For Xexample, `de_AT' is used for Austria, and `pt_BR' for Brazil. The Xcountry code serves to distinguish the dialects. X X The locale naming convention of `LL_CC', with `LL' denoting the Xlanguage and `CC' denoting the country, is the one use on systems based Xon GNU libc. On other systems, some variations of this scheme are Xused, such as `LL' or `LL_CC.ENCODING'. You can get the list of Xlocales supported by your system for your country by running the command X`locale -a | grep '^LL''. X X Not all programs have translations for all languages. By default, an XEnglish message is shown in place of a nonexistent translation. If you Xunderstand other languages, you can set up a priority list of languages. XThis is done through a different environment variable, called X`LANGUAGE'. GNU `gettext' gives preference to `LANGUAGE' over `LANG' Xfor the purpose of message handling, but you still need to have `LANG' Xset to the primary language; this is required by other parts of the Xsystem libraries. For example, some Swedish users who would rather Xread translations in German than English for when Swedish is not Xavailable, set `LANGUAGE' to `sv:de' while leaving `LANG' to `sv_SE'. X X In the `LANGUAGE' environment variable, but not in the `LANG' Xenvironment variable, `LL_CC' combinations can be abbreviated as `LL' Xto denote the language's main dialect. For example, `de' is equivalent Xto `de_DE' (German as spoken in Germany), and `pt' to `pt_PT' X(Portuguese as spoken in Portugal) in this context. X XTranslating Teams X================= X X For the Free Translation Project to be a success, we need interested Xpeople who like their own language and write it well, and who are also Xable to synergize with other translators speaking the same language. XEach translation team has its own mailing list. The up-to-date list of Xteams can be found at the Free Translation Project's homepage, X`http://www.iro.umontreal.ca/contrib/po/HTML/', in the "National teams" Xarea. X X If you'd like to volunteer to _work_ at translating messages, you Xshould become a member of the translating team for your own language. XThe subscribing address is _not_ the same as the list itself, it has X`-request' appended. For example, speakers of Swedish can send a Xmessage to `sv-request@li.org', having this message body: X X subscribe X X Keep in mind that team members are expected to participate X_actively_ in translations, or at solving translational difficulties, Xrather than merely lurking around. If your team does not exist yet and Xyou want to start one, or if you are unsure about what to do or how to Xget started, please write to `translation@iro.umontreal.ca' to reach the Xcoordinator for all translator teams. X X The English team is special. It works at improving and uniformizing Xthe terminology in use. Proven linguistic skill are praised more than Xprogramming skill, here. X XAvailable Packages X================== X X Languages are not equally supported in all packages. The following Xmatrix shows the current state of internationalization, as of March X2002. The matrix shows, in regard of each package, for which languages XPO files have been submitted to translation coordination, with a Xtranslation percentage of at least 50%. X X Ready PO files bg ca cs da de el en eo es et fi fr X +-------------------------------------+ X a2ps | [] [] [] [] | X bash | [] [] [] [] | X bfd | [] [] | X binutils | [] [] | X bison | [] [] [] | X clisp | [] [] [] [] | X cpio | [] [] [] [] | X diffutils | [] [] [] [] [] [] | X enscript | [] [] | X error | [] [] | X fetchmail | () [] [] [] () | X fileutils | [] [] [] [] [] | X findutils | [] [] [] [] [] | X flex | [] [] [] [] | X gas | [] [] | X gawk | [] [] | X gcal | [] [] | X gcc | [] [] | X gettext | [] [] [] [] [] | X gnupg | [] [] [] [] [] [] | X gprof | [] [] | X grep | [] [] [] [] [] [] | X hello | [] [] [] [] [] [] [] [] | X id-utils | [] [] [] | X indent | [] [] [] [] [] | X jpilot | () [] [] [] | X jwhois | [] [] | X kbd | [] [] | X ld | [] [] | X libc | [] [] [] [] [] [] [] | X lilypond | [] [] | X lynx | [] [] [] [] | X m4 | [] [] [] [] [] | X make | [] [] [] [] | X mysecretdiary | [] [] | X nano | [] () [] [] [] [] | X nano_1_0 | [] () [] [] [] [] | X opcodes | [] [] [] | X parted | [] [] [] [] | X ptx | [] [] [] [] [] | X python | | X recode | [] [] [] [] [] [] | X sed | [] [] [] [] [] [] [] [] | X sh-utils | [] [] [] [] [] [] [] [] | X sharutils | [] [] [] [] [] [] | X sketch | () [] () | X soundtracker | [] [] [] | X sp | | X tar | [] [] [] [] [] [] | X texinfo | [] [] [] [] [] | X textutils | [] [] [] [] [] | X util-linux | [] [] [] [] | X vorbis-tools | | X wdiff | [] [] [] [] [] | X wget | [] [] [] [] [] [] [] [] | X +-------------------------------------+ X bg ca cs da de el en eo es et fi fr X 1 12 11 31 36 9 1 8 39 15 1 50 X X gl he hr hu id it ja ko lv nb nl nn X +-------------------------------------+ X a2ps | () () [] | X bash | | X bfd | [] | X binutils | [] | X bison | [] [] | X clisp | [] | X cpio | [] [] [] | X diffutils | [] [] [] | X enscript | [] | X error | [] | X fetchmail | | X fileutils | [] [] [] | X findutils | [] [] [] [] [] [] | X flex | [] | X gas | | X gawk | [] | X gcal | | X gcc | | X gettext | [] | X gnupg | [] [] [] | X gprof | | X grep | [] | X hello | [] [] [] [] [] [] [] [] [] [] | X id-utils | [] | X indent | [] [] [] | X jpilot | () () | X jwhois | | X kbd | | X ld | | X libc | [] [] [] [] | X lilypond | [] [] | X lynx | [] [] | X m4 | [] [] [] [] | X make | [] [] [] [] | X mysecretdiary | | X nano | [] [] [] () [] () [] | X nano_1_0 | [] [] [] () [] () [] | X opcodes | [] | X parted | [] [] [] | X ptx | [] [] [] [] | X python | | X recode | [] [] [] | X sed | [] [] [] [] [] [] [] | X sh-utils | [] [] [] [] [] | X sharutils | [] [] [] | X sketch | () | X soundtracker | [] | X sp | | X tar | [] [] [] | X texinfo | [] [] | X textutils | [] [] | X util-linux | () [] | X vorbis-tools | | X wdiff | | X wget | [] [] [] [] [] | X +-------------------------------------+ X gl he hr hu id it ja ko lv nb nl nn X 19 7 0 4 6 11 22 9 1 8 19 4 X X no pl pt pt_BR ru sk sl sv tr uk zh_TW X +----------------------------------------+ X a2ps | () () () [] [] [] () | 8 X bash | | 4 X bfd | [] [] | 5 X binutils | [] | 4 X bison | [] [] [] | 8 X clisp | | 5 X cpio | [] [] [] [] | 11 X diffutils | [] [] [] [] [] | 14 X enscript | [] [] [] | 6 X error | [] [] [] | 6 X fetchmail | () () [] | 4 X fileutils | [] [] [] [] | 12 X findutils | [] [] [] [] [] [] [] | 18 X flex | [] [] [] | 8 X gas | [] | 3 X gawk | [] [] | 5 X gcal | [] [] | 4 X gcc | [] | 3 X gettext | [] [] [] [] | 10 X gnupg | [] [] [] | 12 X gprof | [] [] | 4 X grep | [] [] [] | 10 X hello | [] [] [] [] [] [] [] | 25 X id-utils | [] [] | 6 X indent | [] [] [] [] | 12 X jpilot | () () | 3 X jwhois | () () [] | 3 X kbd | [] [] | 4 X ld | [] [] | 4 X libc | [] [] [] [] [] [] | 17 X lilypond | [] | 5 X lynx | [] [] [] | 9 X m4 | [] [] [] | 12 X make | [] [] [] [] | 12 X mysecretdiary | [] [] | 4 X nano | () [] [] [] [] | 14 X nano_1_0 | () [] [] [] | 13 X opcodes | [] [] | 6 X parted | [] [] [] | 10 X ptx | [] [] [] [] [] [] | 15 X python | | 0 X recode | [] [] [] [] | 13 X sed | [] [] [] [] [] [] | 21 X sh-utils | [] [] [] [] [] [] [] [] [] | 22 X sharutils | [] [] [] | 12 X sketch | [] () | 3 X soundtracker | [] | 5 X sp | | 0 X tar | [] [] [] [] [] [] [] | 16 X texinfo | [] [] [] | 10 X textutils | [] [] [] [] | 11 X util-linux | [] [] [] | 8 X vorbis-tools | [] | 1 X wdiff | [] [] [] [] | 9 X wget | [] [] [] [] [] [] [] | 20 X +----------------------------------------+ X 35 teams no pl pt pt_BR ru sk sl sv tr uk zh_TW X 55 domains 5 13 2 12 25 11 11 41 34 4 7 489 X X Some counters in the preceding matrix are higher than the number of Xvisible blocks let us expect. This is because a few extra PO files are Xused for implementing regional variants of languages, or language Xdialects. X X For a PO file in the matrix above to be effective, the package to Xwhich it applies should also have been internationalized and Xdistributed as such by its maintainer. There might be an observable Xlag between the mere existence a PO file and its wide availability in a Xdistribution. X X If March 2002 seems to be old, you may fetch a more recent copy of Xthis `ABOUT-NLS' file on most GNU archive sites. The most up-to-date Xmatrix with full percentage details can be found at X`http://www.iro.umontreal.ca/contrib/po/HTML/matrix.html'. X XUsing `gettext' in new packages X=============================== X X If you are writing a freely available program and want to Xinternationalize it you are welcome to use GNU `gettext' in your Xpackage. Of course you have to respect the GNU Library General Public XLicense which covers the use of the GNU `gettext' library. This means Xin particular that even non-free programs can use `libintl' as a shared Xlibrary, whereas only free software can use `libintl' as a static Xlibrary or use modified versions of `libintl'. X X Once the sources are changed appropriately and the setup can handle Xto use of `gettext' the only thing missing are the translations. The XFree Translation Project is also available for packages which are not Xdeveloped inside the GNU project. Therefore the information given above Xapplies also for every other Free Software Project. Contact X`translation@iro.umontreal.ca' to make the `.pot' files available to Xthe translation teams. X END-of-contrib/diff/ABOUT-NLS echo x - contrib/diff/AUTHORS sed 's/^X//' >contrib/diff/AUTHORS << 'END-of-contrib/diff/AUTHORS' XAuthors of GNU diffutils. X X Copyright 2001 Free Software Foundation, Inc. X X This file is part of GNU diffutils. X X GNU diffutils is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X GNU diffutils is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with GNU diffutils; see the file COPYING. If not, write to X the Free Software Foundation, Inc., 59 Temple Place - Suite 330, X Boston, MA 02111-1307, USA. X XThe following contributions warranted legal paper exchanges with the XFree Software Foundation. Also see files ChangeLog and THANKS. X XDIFFUTILS Leonard H. Tower Jr. US 1949 1987-03-09 XAssigns diff (diff.c, initial version). X XDIFFUTILS Torbjorn Granlund Sweden 1961 1988-01-11 XAssigns cmp. Xtege@matematik.su.se X XDIFFUTILS Mike Haertel US 1967 1988-09-16 XAssigns changes to diff. X XDIFFUTILS David S. Hayes US ? 1988-01-12 XAssigns changes to diff. X XDIFFUTILS Randall Smith US 1964 1988-09-21 XAssigns diff3. X XDIFFUTILS Richard Stallman US 1953 1988-01-15 XAssigns changes to GNU Diff. X XDIFFUTILS F. Thomas May US 1965 1989-08-22 XAssigns changes to diff (for -D). X XDIFFUTILS Optimal Solutions, Inc. 1989-08-14 XDisclaims changes by Thomas May to diff. X XDIFFUTILS Wayne Davison 1990-09-10 XDisclaims changes to diff. X XDIFFUTILS Digital Research Inc. 1990-09-13 XDisclaims changes by Wayne Davison to diff. X XDIFFUTILS Paul Eggert 1990-03-16 XDisclaims changes to diff. Xeggert@twinsun.com X XDIFFUTILS Paul Eggert 1990-08-14 XDisclaims changes to GNU Diff. Xeggert@twinsun.com X XDIFFUTILS Twin Sun Inc. 1990-03-16 XDisclaims changes to GNU Diff by Paul Eggert. X XDIFFUTILS Twin Sun Inc. 1990-08-14 XDisclaims changes to GNU Diff by Paul Eggert. X XDIFFUTILS Chip Rosenthal US 1959 1990-03-06 XAssigns changes to diff. Xchip@chinacat.Unicom.COM X XDIFFUTILS Unicom Systems Development 1990-03-06 XDisclaims changes by Chip Rosenthal to diff. X XGCC DIFFUTILS Paul Eggert and Twin Sun Inc. 1992-03-11 XDisclaims changes by Paul Eggert to gcc and diff. Xeggert@twinsun.com X XDIFF Wayne Davison 1993-06-20 XDisclaims diffcvt.c. X XDIFFUTILS Francois Pinard Canada 1949 1993-01-15 XAssigns wdiff and future changes submitted to the FSF. Xpinard@iro.umontreal.ca X XDIFFUTILS Patrick D'Cruze Australia 1971 1994-11-10 XAssigns changes (makefile.in, analyze.c, cmp.c, error.c, diff.c, Xdiff3.c, getopt.c, getopt1.c, regex.c, sdiff.c, util.c, xmalloc.c; Xnew file: language.++) X XDIFFUTILS Paul R. Eggert US 1954 1997-04-07 XAssigns past and future changes. Xeggert@twinsun.com X XDIFFUTILS Paul R. Eggert US 1954 1997-04-07 XAssigns past and future changes to manual. Xeggert@twinsun.com X XANY DIFFUTILS GNATS Cyclic Software 1997-11-11 XAssigns past and future works (work for hire by Tim Pierce (diffutils) and XAbe Feldman (GNATS)). Xkingdon@cyclic.com X XWEBPAGES Gregory B. Harvey Canada 1976 1998-02-14 XAssigns web pages describing GNU Diffutils and future changes. X XDIFFUTILS Olga Nikulin Russia 1965 2001-01-11 XAssigns changes to diff. (diffutils-2.7.2/analyze.c, context.c, diff.[ch], Xed.c, ifdef.c, io.c, normal.c, side.c, util.c) Xonikulin@yahoo.com END-of-contrib/diff/AUTHORS echo x - contrib/diff/COPYING sed 's/^X//' >contrib/diff/COPYING << 'END-of-contrib/diff/COPYING' X GNU GENERAL PUBLIC LICENSE X Version 2, June 1991 X X Copyright (C) 1989, 1991 Free Software Foundation, Inc. X 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA X Everyone is permitted to copy and distribute verbatim copies X of this license document, but changing it is not allowed. X X Preamble X X The licenses for most software are designed to take away your Xfreedom to share and change it. By contrast, the GNU General Public XLicense is intended to guarantee your freedom to share and change free Xsoftware--to make sure the software is free for all its users. This XGeneral Public License applies to most of the Free Software XFoundation's software and to any other program whose authors commit to Xusing it. (Some other Free Software Foundation software is covered by Xthe GNU Library General Public License instead.) You can apply it to Xyour programs, too. X X When we speak of free software, we are referring to freedom, not Xprice. Our General Public Licenses are designed to make sure that you Xhave the freedom to distribute copies of free software (and charge for Xthis service if you wish), that you receive source code or can get it Xif you want it, that you can change the software or use pieces of it Xin new free programs; and that you know you can do these things. X X To protect your rights, we need to make restrictions that forbid Xanyone to deny you these rights or to ask you to surrender the rights. XThese restrictions translate to certain responsibilities for you if you Xdistribute copies of the software, or if you modify it. X X For example, if you distribute copies of such a program, whether Xgratis or for a fee, you must give the recipients all the rights that Xyou have. You must make sure that they, too, receive or can get the Xsource code. And you must show them these terms so they know their Xrights. X X We protect your rights with two steps: (1) copyright the software, and X(2) offer you this license which gives you legal permission to copy, Xdistribute and/or modify the software. X X Also, for each author's protection and ours, we want to make certain Xthat everyone understands that there is no warranty for this free Xsoftware. If the software is modified by someone else and passed on, we Xwant its recipients to know that what they have is not the original, so Xthat any problems introduced by others will not reflect on the original Xauthors' reputations. X X Finally, any free program is threatened constantly by software Xpatents. We wish to avoid the danger that redistributors of a free Xprogram will individually obtain patent licenses, in effect making the Xprogram proprietary. To prevent this, we have made it clear that any Xpatent must be licensed for everyone's free use or not licensed at all. X X The precise terms and conditions for copying, distribution and Xmodification follow. X X GNU GENERAL PUBLIC LICENSE X TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION X X 0. This License applies to any program or other work which contains Xa notice placed by the copyright holder saying it may be distributed Xunder the terms of this General Public License. The "Program", below, Xrefers to any such program or work, and a "work based on the Program" Xmeans either the Program or any derivative work under copyright law: Xthat is to say, a work containing the Program or a portion of it, Xeither verbatim or with modifications and/or translated into another Xlanguage. (Hereinafter, translation is included without limitation in Xthe term "modification".) Each licensee is addressed as "you". X XActivities other than copying, distribution and modification are not Xcovered by this License; they are outside its scope. The act of Xrunning the Program is not restricted, and the output from the Program Xis covered only if its contents constitute a work based on the XProgram (independent of having been made by running the Program). XWhether that is true depends on what the Program does. X X 1. You may copy and distribute verbatim copies of the Program's Xsource code as you receive it, in any medium, provided that you Xconspicuously and appropriately publish on each copy an appropriate Xcopyright notice and disclaimer of warranty; keep intact all the Xnotices that refer to this License and to the absence of any warranty; Xand give any other recipients of the Program a copy of this License Xalong with the Program. X XYou may charge a fee for the physical act of transferring a copy, and Xyou may at your option offer warranty protection in exchange for a fee. X X 2. You may modify your copy or copies of the Program or any portion Xof it, thus forming a work based on the Program, and copy and Xdistribute such modifications or work under the terms of Section 1 Xabove, provided that you also meet all of these conditions: X X a) You must cause the modified files to carry prominent notices X stating that you changed the files and the date of any change. X X b) You must cause any work that you distribute or publish, that in X whole or in part contains or is derived from the Program or any X part thereof, to be licensed as a whole at no charge to all third X parties under the terms of this License. X X c) If the modified program normally reads commands interactively X when run, you must cause it, when started running for such X interactive use in the most ordinary way, to print or display an X announcement including an appropriate copyright notice and a X notice that there is no warranty (or else, saying that you provide X a warranty) and that users may redistribute the program under X these conditions, and telling the user how to view a copy of this X License. (Exception: if the Program itself is interactive but X does not normally print such an announcement, your work based on X the Program is not required to print an announcement.) X XThese requirements apply to the modified work as a whole. If Xidentifiable sections of that work are not derived from the Program, Xand can be reasonably considered independent and separate works in Xthemselves, then this License, and its terms, do not apply to those Xsections when you distribute them as separate works. But when you Xdistribute the same sections as part of a whole which is a work based Xon the Program, the distribution of the whole must be on the terms of Xthis License, whose permissions for other licensees extend to the Xentire whole, and thus to each and every part regardless of who wrote it. X XThus, it is not the intent of this section to claim rights or contest Xyour rights to work written entirely by you; rather, the intent is to Xexercise the right to control the distribution of derivative or Xcollective works based on the Program. X XIn addition, mere aggregation of another work not based on the Program Xwith the Program (or with a work based on the Program) on a volume of Xa storage or distribution medium does not bring the other work under Xthe scope of this License. X X 3. You may copy and distribute the Program (or a work based on it, Xunder Section 2) in object code or executable form under the terms of XSections 1 and 2 above provided that you also do one of the following: X X a) Accompany it with the complete corresponding machine-readable X source code, which must be distributed under the terms of Sections X 1 and 2 above on a medium customarily used for software interchange; or, X X b) Accompany it with a written offer, valid for at least three X years, to give any third party, for a charge no more than your X cost of physically performing source distribution, a complete X machine-readable copy of the corresponding source code, to be X distributed under the terms of Sections 1 and 2 above on a medium X customarily used for software interchange; or, X X c) Accompany it with the information you received as to the offer X to distribute corresponding source code. (This alternative is X allowed only for noncommercial distribution and only if you X received the program in object code or executable form with such X an offer, in accord with Subsection b above.) X XThe source code for a work means the preferred form of the work for Xmaking modifications to it. For an executable work, complete source Xcode means all the source code for all modules it contains, plus any Xassociated interface definition files, plus the scripts used to Xcontrol compilation and installation of the executable. However, as a Xspecial exception, the source code distributed need not include Xanything that is normally distributed (in either source or binary Xform) with the major components (compiler, kernel, and so on) of the Xoperating system on which the executable runs, unless that component Xitself accompanies the executable. X XIf distribution of executable or object code is made by offering Xaccess to copy from a designated place, then offering equivalent Xaccess to copy the source code from the same place counts as Xdistribution of the source code, even though third parties are not Xcompelled to copy the source along with the object code. X X 4. You may not copy, modify, sublicense, or distribute the Program Xexcept as expressly provided under this License. Any attempt Xotherwise to copy, modify, sublicense or distribute the Program is Xvoid, and will automatically terminate your rights under this License. XHowever, parties who have received copies, or rights, from you under Xthis License will not have their licenses terminated so long as such Xparties remain in full compliance. X X 5. You are not required to accept this License, since you have not Xsigned it. However, nothing else grants you permission to modify or Xdistribute the Program or its derivative works. These actions are Xprohibited by law if you do not accept this License. Therefore, by Xmodifying or distributing the Program (or any work based on the XProgram), you indicate your acceptance of this License to do so, and Xall its terms and conditions for copying, distributing or modifying Xthe Program or works based on it. X X 6. Each time you redistribute the Program (or any work based on the XProgram), the recipient automatically receives a license from the Xoriginal licensor to copy, distribute or modify the Program subject to Xthese terms and conditions. You may not impose any further Xrestrictions on the recipients' exercise of the rights granted herein. XYou are not responsible for enforcing compliance by third parties to Xthis License. X X 7. If, as a consequence of a court judgment or allegation of patent Xinfringement or for any other reason (not limited to patent issues), Xconditions are imposed on you (whether by court order, agreement or Xotherwise) that contradict the conditions of this License, they do not Xexcuse you from the conditions of this License. If you cannot Xdistribute so as to satisfy simultaneously your obligations under this XLicense and any other pertinent obligations, then as a consequence you Xmay not distribute the Program at all. For example, if a patent Xlicense would not permit royalty-free redistribution of the Program by Xall those who receive copies directly or indirectly through you, then Xthe only way you could satisfy both it and this License would be to Xrefrain entirely from distribution of the Program. X XIf any portion of this section is held invalid or unenforceable under Xany particular circumstance, the balance of the section is intended to Xapply and the section as a whole is intended to apply in other Xcircumstances. X XIt is not the purpose of this section to induce you to infringe any Xpatents or other property right claims or to contest validity of any Xsuch claims; this section has the sole purpose of protecting the Xintegrity of the free software distribution system, which is Ximplemented by public license practices. Many people have made Xgenerous contributions to the wide range of software distributed Xthrough that system in reliance on consistent application of that Xsystem; it is up to the author/donor to decide if he or she is willing Xto distribute software through any other system and a licensee cannot Ximpose that choice. X XThis section is intended to make thoroughly clear what is believed to Xbe a consequence of the rest of this License. X X 8. If the distribution and/or use of the Program is restricted in Xcertain countries either by patents or by copyrighted interfaces, the Xoriginal copyright holder who places the Program under this License Xmay add an explicit geographical distribution limitation excluding Xthose countries, so that distribution is permitted only in or among Xcountries not thus excluded. In such case, this License incorporates Xthe limitation as if written in the body of this License. X X 9. The Free Software Foundation may publish revised and/or new versions Xof the General Public License from time to time. Such new versions will Xbe similar in spirit to the present version, but may differ in detail to Xaddress new problems or concerns. X XEach version is given a distinguishing version number. If the Program Xspecifies a version number of this License which applies to it and "any Xlater version", you have the option of following the terms and conditions Xeither of that version or of any later version published by the Free XSoftware Foundation. If the Program does not specify a version number of Xthis License, you may choose any version ever published by the Free Software XFoundation. X X 10. If you wish to incorporate parts of the Program into other free Xprograms whose distribution conditions are different, write to the author Xto ask for permission. For software which is copyrighted by the Free XSoftware Foundation, write to the Free Software Foundation; we sometimes Xmake exceptions for this. Our decision will be guided by the two goals Xof preserving the free status of all derivatives of our free software and Xof promoting the sharing and reuse of software generally. X X NO WARRANTY X X 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY XFOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN XOTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES XPROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED XOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF XMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS XTO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE XPROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, XREPAIR OR CORRECTION. X X 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING XWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR XREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, XINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING XOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED XTO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY XYOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER XPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE XPOSSIBILITY OF SUCH DAMAGES. X X END OF TERMS AND CONDITIONS X X How to Apply These Terms to Your New Programs X X If you develop a new program, and you want it to be of the greatest Xpossible use to the public, the best way to achieve this is to make it Xfree software which everyone can redistribute and change under these terms. X X To do so, attach the following notices to the program. It is safest Xto attach them to the start of each source file to most effectively Xconvey the exclusion of warranty; and each file should have at least Xthe "copyright" line and a pointer to where the full notice is found. X X X Copyright (C) X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2 of the License, or X (at your option) any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software X Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA X X XAlso add information on how to contact you by electronic and paper mail. X XIf the program is interactive, make it output a short notice like this Xwhen it starts in an interactive mode: X X Gnomovision version 69, Copyright (C) year name of author X Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. X This is free software, and you are welcome to redistribute it X under certain conditions; type `show c' for details. X XThe hypothetical commands `show w' and `show c' should show the appropriate Xparts of the General Public License. Of course, the commands you use may Xbe called something other than `show w' and `show c'; they could even be Xmouse-clicks or menu items--whatever suits your program. X XYou should also get your employer (if you work as a programmer) or your Xschool, if any, to sign a "copyright disclaimer" for the program, if Xnecessary. Here is a sample; alter the names: X X Yoyodyne, Inc., hereby disclaims all copyright interest in the program X `Gnomovision' (which makes passes at compilers) written by James Hacker. X X , 1 April 1989 X Ty Coon, President of Vice X XThis General Public License does not permit incorporating your program into Xproprietary programs. If your program is a subroutine library, you may Xconsider it more useful to permit linking proprietary applications with the Xlibrary. If this is what you want to do, use the GNU Library General XPublic License instead of this License. END-of-contrib/diff/COPYING echo x - contrib/diff/ChangeLog sed 's/^X//' >contrib/diff/ChangeLog << 'END-of-contrib/diff/ChangeLog' X2002-04-05 Paul Eggert X X * NEWS, configure.ac (AC_INIT): Version 2.8.1. X X * configure.ac (AC_HEADER_STDBOOL): Add. X (AC_CHECK_HEADERS): Remove stdbool.h. X * m4/stdbool.m4: New file. X * m4/prereq.m4 (jm_PREREQ_EXCLUDE): X Use AC_HEADER_STDBOOL rather than AC_CHECK_HEADERS(stdbool.h). X (jm_PREREQ_HASH): Likewise. X X * src/system.h (SSIZE_MAX): Define if limits.h doesn't. X X * src/analyze.c (diff_2_files): Assign PTRDIFF_MAX - 1 to a X size_t variable, just in case there's a problem with ptrdiff_t X versus size_t. X X * lib/cmpbuf.c (errno): Remove decl; K&R C is no longer supported. X Include limits.h. X (SIZE_MAX, SSIZE_MAX): Define if standard headers don't. X (MIN): New macro. X (block_read): Do not attempt to read more than SSIZE_MAX bytes, as the X resulting behavior is implementation-defined. Work around bug in X Tru64 5.1, which can't read more than INT_MAX bytes at a time. X * src/cmp.c (cmp): Use block_read instead of read, to work X around Tru64 5.1 bug. X * src/diff3.c (read_diff): Likewise. X * src/diff3.c: Include cmpbuf.h. X X * THANKS: Add Ulrich Drepper. X X * INSTALLME: Mention GNU texinfo. X X * doc/diff.texi: X Use new @copying directive. X Put @contents first, not last, since Texinfo now suggests this. X Fix bug in -w documentation noted by Karl Berry. X Mention links for speedup. X New node "Speedups" for future speedups. X Just say "Index", not "Concept Index". X X2002-03-26 Paul Eggert X X * src/Makefile.am: X (INCLUDES): Remove this obsolete macro, replacing it with: X (AM_CPPFLAGS): New macro. X X2002-03-26 Albert Chin-A-Young X X * src/Makefile.am (datadir): Remove, as it conflicts with --datadir. X X2002-03-26 Paul Eggert X X * doc/diff.texi (dircategory GNU packages): Fix typo: a "* " was X missing before the menu entry. Bug diagnosed by Adam Heath. X Also, put this dircategory after the Individual utilities dircategory, X to work around a compatibility problem with Debian install-info. X X2002-03-24 Eli Zaretskii X X * src/io.c (sip): Do not mishandle buffered count when reverting X to text mode. X X2002-03-23 Paul Eggert X X * NEWS, configure.ac (AC_INIT): Version 2.8. X * configure.ac (AC_PREREQ): 2.53. X * INSTALLME: Upgrade to gettext 0.11.1 and help2man 1.27. X X * doc/diff.texi: Upgrade the description of `patch' to GNU patch X 2.5.4, and revamp the documentation accordingly. X X * src/diff.c (main): Fix typo that prevented diff -y from working. X Bug reported by Mitsuru Chinen. X X2002-03-15 Paul Eggert X X * lib/c-stack.c (c_stack_die) [!HAVE_SIGINFO_T]: Don't use info. X Bug reported by Eli Zaretskii. X X2002-03-15 Eli Zaretskii X X * ms/config.sed: Tweak editing of install-info-am target. X X2002-03-12 Paul Eggert X X * NEWS, configure.ac (AC_INIT): Version 2.7.10. X X * NEWS: cmp -l -s and cmp -s -l are not allowed. X Deprecate diff -h, -H, -L, -P, --inhibit-hunk-merge. X X * configure.ac (jm_PREREQ_HARD_LOCALE): Add. X (AM_INIT_AUTOMAKE): Do not distribute shar file. X X * doc/diff.texi (Overview): byte != character. X (Detailed Context, Detailed Unified, Alternate Names, diff Options): X Do not document diff -L. X (Comparing Directories, Making Patches, diff Options): X Do not document diff -P. X (diff Performance, sdiff Option Summary, diff Options, sdiff Options): X Do not document diff -H. X (diff Performance, diff Options): Do not document --horizon-lines. X (cmp Options): Prefer -b to -c. X (cmp Options, diff Options, diff3 Options, patch Options, X sdiff Options): Put short options next to the similar long options. X Document --help, and use the same wording for --verbose. X (diff3 Options): Fix typo in description of -E, which used wrongly used X "-e" instead of "-E". X X * lib/hard-locale.c (alloca): Remove. X Include stdlib.h if available, for malloc. X (hard_locale): Use malloc, not alloca, so that we need not worry about X alloca issues. Test for storage allocation failure. X X * m4/prereq.m4 (jm_PREREQ): Add jm_PREREQ_HARD_LOCALE. X (jm_PREREQ_HARD_LOCALE): New macro. X X * src/cmp.c (specify_comparison_type): New function. X (check_stdout): "indices and codes" -> "byte numbers and values" X (main): Detect clashing options. X (cmp): Use "byte" rather than "char" if a translation for "byte" X is available, even when in the POSIX locale. X X * src/diff.c (option_help_msgid): Do not document -L, -P, X --horizon-lines, --inhibit-hunk-merge, -H. X * src/diff.h: -L -> --label X X2002-03-11 Paul Eggert X X * NEWS, configure.ac (AC_INIT): Version 2.7.9. X X * INSTALLME: Update to autoconf 2.53, automake 1.6, help2man X 1.25 with patch. X X * configure.ac (AC_INIT): X Change package name from diff to diffutils. X (AM_INIT_AUTOMAKE): Use new form, with option gnits, X rather than old from that duplicated AC_INIT. X (AM_MISSING_PROG): Add help2man. X (REGEX_MALLOC): Define. X (AC_CONFIG_FILES): Add man/Makefile. X X * Makefile.am (AUTOMAKE_OPTIONS): Remove. X * doc/Makefile.am (AUTOMAKE_OPTIONS): Remove. X * lib/Makefile.am (AUTOMAKE_OPTIONS): Likewise. X * ms/Makefile.am (AUTOMAKE_OPTIONS): Likewise. X * src/Makefile.am (AUTOMAKE_OPTIONS): Likewise. X X * lib/c-stack.c: Include X (ENOTSUP): Define if errno.h doesn't. X (SA_NODEFER, SA_ONSTACK, SA_RESETHAND, SA_SIGINFO, SIGSTKSZ, X _SC_PAGESIZE, ALTERNATE_STACK_SIZE, stack_t, sigaltstack): X Remove; we now assume them all when X HAVE_XSI_STACK_OVERFLOW_HEURISTIC, so we don't need X substitutes. X (): Include only if HAVE_XSI_STACK_OVERFLOW_HEURISTIC. X (alternate_signal_stack): Now of size SIGSTKSZ. X (segv_handler): Simplify, under the assumption that X HAVE_XSI_STACK_OVERFLOW_HEURISTIC is nonzero. X (c_stack_action): Likewise. X (exit_failure) [DEBUG]: Initialize to 0, not 1. X (recurse, main) [DEBUG]: Remove main args. X X * m4/c-stack.m4 (AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC): Change X wording of message. Do not check for stdbool.h or ucontext.h, X or for ucontext_t or sigaction or sigaltstack. X X * po/LINGUAS: Add zh_TW. X X * Makefile.am (SUBDIRS): Add man. X * man/Makefile.am: New file. X * src/cmp.c (usage): Reword for help2man. X * src/diff.c (option_help_msgid): Likewise. X * src/diff3.c (option_help_msgid, usage): Likewise. X * src/sdiff3.c (option_help_msgid, usage): Likewise. X Reword for help2man. X X * THANKS: Add email address for Tower. X X * config/config.guess, config/config.sub, config/depcomp, X config/install-sh, config/mdate-sh, config/missing, X config/mkinstalldirs, config/texinfo.texi: Update X to recent version (maintained in other packages). X X2002-03-04 Bruno Haible X X * m4/gettext.m4 (AM_GNU_GETTEXT): Set LIBINTL and LTLIBINTL to empty if X no preinstalled GNU gettext was found. X X2002-03-02 Eli Zaretskii X X * ms/config.sed: Tweak editing of install-info-am and X uninstall-info-am targets, to include 8+3-butchered names of Info X files. X X2002-02-28 Paul Eggert X X * NEWS, configure.ac (AC_INIT, AM_INIT_AUTOMAKE): Version 2.7.8. X X * doc/diff.texi: Add vr index. X Update copyright to 2002. X (Standards conformance): New chapter. X (Binary): Differing binary files are trouble unless the user asked for X brief output. X (Detailed Context): Prefer ISO time stamp format in discussion. X (Detailed Unified, Pagination): Likewise. X (Less Context): Likewise. Also use short option. X (Alternate Names): Separate option from arg. X (Making Patches): Mention -U 2. X (diff Options): Deprecate -LINES, as POSIX 1003.1-2001 does not X allow it. X X * INSTALLME: Update advice for Solaris installation problems. X We no longer use a test version of gettext. X Autoconf test version updated from 2.52f to 2.52h. X POSIX 1003.1-2001 patch for Automake. X X * configure.ac (AC__GNU_SOURCE): Add this, X replacing AH_VERBATIM of _GNU_SOURCE. X (tempname): Use AC_LIBOBJS, not LIBOBJS=, as now required by autoconf. X (jm_PREREQ_C_STACK): Add. X (AC_CONFIG_FILES): Remove intl/Makefile. X (AM_GNU_GETTEXT): Add external arg, from gettext 0.11. X X * lib/c-stack.c, lib/c-stack.h, lib/exitfail.c, lib/exitfail.h, X lib/posixver.c, lib/posixver.h, m4/c-stack.m4, m4/gnu-source.m4, X po/cs.po, po/ja.po: New files. X X * intl/ChangeLog, intl/Makefile.in, intl/VERSION, X intl/bindtextdom.c, intl/config.charset, intl/dcgettext.c, X intl/dcigettext.c, intl/dcngettext.c, intl/dgettext.c, X intl/dngettext.c, intl/explodename.c, intl/finddomain.c, X intl/gettext.c, intl/gettextP.h, intl/gmo.h, intl/hash-string.h, X intl/intl-compat.c, intl/l10nflist.c, intl/libgnuintl.h, X intl/loadinfo.h, intl/loadmsgcat.c, intl/localcharset.c, X intl/locale.alias, intl/localealias.c, intl/localename.c, X intl/ngettext.c, intl/os2compat.c, intl/os2compat.h, intl/osdep.c, X intl/plural-eval.c, intl/plural-exp.c, intl/plural-exp.h, X intl/plural.c, intl/plural.y, intl/ref-add.sin, intl/ref-del.sin, X intl/textdomain.c, m4/isc-posix.m4, m4/libtool.m4: Remove. X X * ABOUT-NLS: Update to Gettext 0.11. X X * Makefile.am (SUBDIRS): Remove intl. X X * config/config.guess, config/config.rpath, config/config.sub, X config/texinfo.tex, config/depcomp, config/texinfo.tex, X lib/tempname.c: Update to latest version from other packages. X X * lib/xalloc.h (xalloc_exit_failure): Remove; subsumed by exit_failure. X * lib/xmalloc.c: Include exitfail.h. X (xalloc_exit_failure): Remove; subsumed by exit_failure. X All uses changed. X X * lib/Makefile.am (noinst_HEADERS): Add c-stack.h, exitfail.h. X (libdiffutils_a_SOURCES): Add c-stack.c, exitfail.c, quotesys.c. X (INCLUDES): Remove. X X * lib/cmpbuf.h (buffer_lcm): New arg LCM_MAX. X * lib/cmpbuf.c: Include errno.h. X (errno): Declare if !STDC_HEADERS. X Include signal.h. X (SA_RESTART): Define if not already defined. X Include . X (PTRDIFF_MAX): Define if not already defined. X (TYPE_SIGNED, TYPE_MINIMUM, TYPE_MAXIMUM): Likewise. X (block_read): Accommodate ancient AIX hosts that set errno to EINTR X after uncaught SIGCONT. X (buffer_lcm): Return a reasonable size if the multiple is too large. X New arg LCM_MAX. All callers changed. X X * lib/hard-locale.c: Include "hard-locale.h". X (hard_locale): Ignore ENABLE_NLS, since we want to operate on X locales other than LC_MESSAGES. X X * m4/prereq.m4 (jm_PREREQ): Add jm_PREREQ_POSIXVER. X (jm_PREREQ_POSIXVER): New macro. X X * m4/setmode.m4 (AC_FUNC_SETMODE_DOS): X Check for fcntl.h and unistd.h unconditionally. X Suggested by Bruno Haible. X X * po/LINGUAS: Add cs, ja. X * po/POTFILES.in: Add lib/c-stack.c, src/dir.c. X X * src/Makefile.am (datadir): @DATADIRNAME@ -> share. X (INCLUDES): Remove intl. X (LDADD): Change INTLLIBS to LIBINTL. X No longer need to link libdiffutils.a twice. X X * src/analyze.c (diff_2_files): X Avoid arithmetic overflow in buffer size calculation. X X * src/cmp.c: Include c-stack.h, exitfail.h. X (hard_locale_LC_MESSAGES): Depend on ENABLE_NLS. X (try_help, check_stdout, main, cmp): 2 -> EXIT_TROUBLE. X (main): Check for stack overflow. X 0 -> EXIT_SUCCESS. X 1 -> EXIT_FAILURE. X (cmp): Likewise. X Accommodate ancient AIX hosts that set errno to X EINTR after uncaught SIGCONT. X X * src/context.c (pr_context_hunk): X Do not dump core if an enormous context causes an X arithmetic overflow. X (pr_unidiff_hunk): Likewise. X (find_hunk): Likewise. X X * src/diff.h: unsigned -> unsigned int. X * src/diff.c: Include c-stack.h, exitfail.h. X Do not include signal.h. X (specify_style, specify_value): Bring these routines back, as POSIX X requires that the order of options not matter. X (shortopts): New constant. X (group_format_option, line_format_option): New constants. X (main): 0 -> EXIT_SUCCESS, 1 -> EXIT_FAILURE, 2 -> EXIT_TROUBLE. X Ensure that order of options does not matter. X Check for stack overflow. X If contexts overflow, substitute LIN_MAX, as that's good enough. X If multiple contexts are specified, use their maximum. X -c is equivalent to -C 3 now, instead of having an implicit context; X likewise for -u and -U 3. X Use specify_style and specify_value. X (SIGCHLD): Do not define; now done in a header. X Use new style time stamp format for -u / -U. X Reject numeric-string options if operating in POSIX 1003.1-2001 mode. X Avoid overflow problems with tab width. X Simplify from-file and to-file code. X (usage): Do not mention obsolete options. X (filetype): Do not mention whether a file is executable. X Add typed memory objects. X (compare_files): 0 -> EXIT_SUCCESS, 1 -> EXIT_FAILURE, 2 -> X EXIT_TROUBLE. X X * src/diff3.c: Include c-stack.h, exitfail.h. X (ALLOCATE): Remove. All uses changed to xmalloc, or to xmalloc plus X an overflow check. X (myread): Remove. X (main): Check for stack overflow. X 0 -> EXIT_SUCCESS, 1 -> EXIT_FAIULRE, 2 -> EXIT_TROUBLE. X (try_help): Likewise. X (process_diff): Check for integer overflow, to avoid core dumps. X 2 -> EXIT_TROUBLE. X (read_diff): Exit with status 126 if the file is not executable, X for compatibility with POSIX 1003.1-2001. X Accommodate ancient AIX hosts that set errno to EINTR after uncaught X SIGCONT. X Check for integer overflow to avoid core dumps. X (fatal, perror_with_exit): 2 -> EXIT_TROUBLE. X X * src/dir.c (dir_read): X Ignore st_size of directories: POSIX says it's garbage. X Check for integer overflow to avoid core dumps. X (diff_dirs): 0 -> EXIT_SUCCESS, 2 -> EXIT_TROUBLE. X X * src/ifdef.c: Include . X (format_group, print_ifdef_lines): Avoid core dumps with bad formats. X (do_printf_spec): Avoid alloca. X X * src/io.c (sip): X Avoid integer overflow and core dumps if buffer alignments are X preposterously incompatible. X (slurp): Do not dump core if the file is growing as we read it. X If a regular file grows, keep reading until we catch up with its EOF. X (find_and_hash_each_line): Check for integer overflow to avoid cores. X (GUESS_LINES): Remove. X (guess_lines): New function. Avoid integer overflow. X (find_identical_ends): Use it. X Avoid integer overflow and possible core dumps. X X * src/sdiff.c: Include c-stack.h, exitfail.h. Do not include signal.h. X 0 -> EXIT_SUCCESS, 1 -> EXIT_FAILURE, 2 -> EXIT_TROUBLE. X (ck_editor_status): New function. X (main): Check for stack overflow. X Adopt POSIX convention for subsidiary programs not found. X (diffarg): Check for integer overflow to avoid core dumps. X (trapsigs): Remove SA_INTERRUPT special case; now done by header. X (SIGCHLD): Likewise. X (edit): Adopt POSIX convention for subsidiary programs not found. X X * src/side.c: unsigned -> unsigned int. X X * src/system.h: Don't use alloca or include . X unsigned -> unsigned int X (EXIT_SUCCESS, EXIT_FAILURE, EXIT_TROUBLE): Define if not defined. X Include signal.h. X (SA_RESTART): Define if not defined. X (SIGCHLD): Likewise. X X * src/util.c: 2 -> EXIT_TROUBLE. X Adopt POSIX convention for ENOEXEC and exit status 126. X unsigned -> unsigned int X X2002-01-24 Paul Eggert X X * NEWS, configure.ac (AC_INIT, AM_INIT_AUTOMAKE): Version 2.7.7. X X * intl/plural.c: Regenerate with Bison 1.31. X X * ABOUT-NLS, intl/*: Update to Gettext 0.11-pre5++. X * INSTALL: Update to Autoconf 2.52f. X X * INSTALLME: New file. X * Makefile.am (EXTRA_DIST): Add config/config.rpath, INSTALLME. X (DISTCLEANFILES): Remove. X * NEWS: Reformat for imminent 2.8 release. X * README: Mention INSTALLME. X * README-alpha: Move most of contents to INSTALLME. X * THANKS: Add Bruno Haible, Jim Meyering, and Eli Zaretskii. X X * config: New subdirectory, containing the following files from .: X config.guess, config.sub, depcomp, missing, install-sh, mkinstalldirs. X Move the following files here from doc: texinfo.tex, mdate-sh. X * config/config.guess, config/config.sub, config/texinfo.tex: X Update to latest version from FSF. X * config/config.rpath: New file, from Gettext 0.11-pre5++. X X * configure.ac (AC_INIT): Use new 3-arg form. X (AC_CONFIG_SRCDIR): Specify src/diff.c here, not in AC_INIT. X (ALL_LINGUAS): Remove: now in po/LINGUAS as per Gettext 0.11. X (AC_CONFIG_AUX_DIR): New macro invocation. X X * lib/Makefile.am (noinst_HEADERS): Add gettext.h. X * lib/gettext.h: New file, from Gettext 0.11-pre5++. X * lib/prepargs.c: Include . Reported by Bruno Haible. X X * m4/codeset.m4, m4/gettext.m4, glibc21.m4, iconv.m4, isc-posix.m4, X lcmessage.m4, progtest.m4: Upgrade to Gettext 0.11-pre5++. X * m4/lib-ld.m4, m4/lib-link.m4, m4/lib-prefix.m4: New files, from X Gettext 0.11-pre5++. X X * po/LINGUAS: New file. X * po/Makefile.in.in: Upgrade to Gettext 0.11-pre5++. X * po/Makevars, po/Rules-quot, po/boldquot.sed: New files, X from Gettext 0.11-pre5++. X X * src/cmp.c (copyright_string): Update to 2002. X * src/diff.c (copyright_string): Likewise. X * src/diff3.c (copyright_string): Likewise. X * src/sdiff.c (copyright_string): Likewise. X X * src/cmp.c (bytes, parse_ignore_initial, cmp): Use UINTMAX_MAX X instead of (uintmax_t) -1, to avoid warnings on some compilers. X * src/io.c (file_block_read): Likewise, for SIZE_MAX. X X * src/cmp.c (usage): Reformat messages to ease translation. X * src/diff3.c (usage): Likewise. X * src/sdiff.c (usage): Likewise. X X * src/diff3.c (main): Remove unused variable. X X * src/dir.c: Include X (struct dirdata): New member nnames. X (locale_specific_sorting, failed_strcoll): New vars. X (dir_read): Renamed from dir_sort. Don't sort the dir. X Set new nnames member of struct dirdata. All callers changed. X (compare_names): Don't check for errno after strcasecmp. X Use strcoll only if locale_specific_sorting is nonzero. X If strcoll fails, longjmp out rather than returning a value X that might result in an invalid comparison function that might X make qsort dump core. X (diff_dirs): Sort the directory ourselves. Use setjmp to recover X from strcoll failure, falling back on native byte comparison. X Make local variables volatile if they need to preserve their value X after setjmp/longjmp. X X * src/sdiff.c (handler_index_of_SIGINT, handler_index_of_SIGPIPE): X New macros. X (main): Do not confuse signal numbers with their indices. X Bug reported by Bruno Haible. X (edit): Cat lin to long before printing with %ld, since lin might X be narrow than long. X X * src/system.h (UINTMAX_MAX): New macro. X Include gettext.h, not libgettext.h. X (N_): Do not wrap arg in parentheses. Fix from Bruno Haible. X X * src/util.c (finish_output): Ensure that werrno is initialized. X (lines_differ): Have an explicit do-nothing case for X IGNORE_NO_WHITE_SPACE, to pacify gcc -Wall. X X2001-12-29 Eli Zaretskii X X * src/sdiff.c (interact): After extracting rlen from the editor X command, test for a terminating null character, not for a newline. X X * ms/config.bat: Allow longer source directory names without X overflowing the line length limits. Create the cache in the X build directory, not in the source directory X * ms/config.sed: Fix AC_CONFIG_LINKS for when symlinks are X unavailable. X X2001-12-23 Paul Eggert X X * NEWS, configure.ac (AM_INIT_AUTOMAKE): Version 2.7.6. X X * configure.ac (ALL_LINGUAS): Add tr. X X * src/util.c (begin_output): X Have child exit with status 127 rather than reporting X failure on its own. Set errno to 0 before invoking popen. X (finish_output): Report errno on pclose failure. X Distinguish between subsidiary program not found, and failure. X X * src/sdiff.c (not_found, execdiff): Remove. X (DIFF_PROGRAM_OPTION): New constant. X (longopts, option_help_msgid, main): Add --diff-program=PROGRAM. X (check_stdout): New function. X (main): Remove DIFF_PROGRAM. Check stdout after printing version. X Use check_stdout after printing help. Use execvp/perror_fatail rather X than execdiff. Set errno to 0 before invoking popen. X Check for pclose failure properly. X (main, edit): If child exec fails, exit with 127 rather than trying to X print diagnostic. X Distinguish between subsidiary program failing and not being found. X (edit): Handle signals the same way, regardless of whether we're using X system or fork+exec. Check for system returning -1. X X * src/diff3.c (DIFF_PROGRAM_OPTION, HELP_OPTION): New constants. X (longopts, main): Use them. X (longopts, main, option_help_msgid): New option --diff-option=PROGRAM. X (main): Remove DIFF_PROGRAM support. X Check stdout after printing version. X (check_stdout): Report errno info if fclose fails. X (read_diff): Have child exit with status 127 when program is not found, X rather than trying to have the child report failure. Check for X pclose returning -1. X X * src/diff.c (DEFAULT_WIDTH): Remove. X (main): Use 130 instead of DEFAULT_WIDTH, since it's not really X builder-settable. Do not prepend DIFF_OPTIONS. X (check-stdout): If fclose (stdout) fails, print errno info. X (option_help_msgid): Default context is 3, not 2. X (usage): Work even if ptrdiff_t is wider than int. X X * doc/diff.texi (diff Options): Remove DIFF_OPTIONS. X (Invoking diff3, Invoking sdiff): Remove DIFF_PROGRAM. X (diff3 Options, sdiff Options): Add --diff-program. X X * src/cmp.c (valid_suffixes): X Add '0', to support suffixes like "MB" and "MiB". X (check_stdout): Don't assume that the translations of "write failed" X and of "standard output" lack '%'. X (main): Check stdout after printing version. X X * lib/setmode.c: [HAVE_FCNTL_H && HAVE_SETMODE_DOS]: Include . X [!HAVE_SETMODE_DOS]: Do not include . X (set_binary_mode): Return mode (not 1) if fd is a tty. X Do not assume that O_TEXT is zero. X X * doc/diff.texi (cmp Options): X In byte counts, a plain suffix (without any integer) X is assumed to modify the integer 1. Index terms like "kibibyte". X Document plain "k". X X (Reporting Bugs): Mention bug-report archive and test version X location. Ask for "diff --version" in bug reports. X X2001-12-13 Paul Eggert X X * src/diff.c (DEFAULT_WIDTH): Remove; couldn't be changed without X also changing option_help_msgid. All uses replaced with 130. X X * lib/setmode.c: Include fcntl.h and unistd.h only if X HAVE_SETMODE_DOS. X (setmode): Assume a file is binary unless the mode is O_TEXT. X * ms/README: Fix minor typos. X X2001-12-13 Eli Zaretskii X X * ms/README: New file. X X * lib/setmode.c (set_binary_mode) [HAVE_SETMODE_DOS]: Don't assume X O_TEXT has a zero value. If FD is a terminal device, do nothing X and return MODE, thus pretending that it was already in the X requested MODE. X [HAVE_FCNTL_H]: Include fcntl.h (needed for O_BINARY). X X * ms/config.sed: Remove the split prevention of config.status. X Fix Sed commands for converting absolute file names into X top_srcdir-relative ones. X X * ms/config.bat: Fix typos. X X2001-12-12 Neal H Walfield X X * diff.c (option_help_msgid): Correct the default context width X from 2 to 3. X X2001-12-11 Paul Eggert X X * m4/Makefile.am.in: Remove jm-glibc-io.m4 X X * NEWS, configure.ac (AM_INIT_AUTOMAKE): Version 2.7.5. X X * configure.ac (PR_PROGRAM): Use AC_DEFINE_UNQUOTED, so that X $PR_PROGRAM is expanded by sh. X (ptrdiff_t, ssize_t): Use AC_CHECK_TYPE with a default of int, X not AC_CHECK_TYPES. X (jm_AC_DOS, AC_FUNC_SETMODE_DOS): New macros. X (AC_CONFIG_FILES): Add ms/Makefile. X X * doc/diff.texi: Add --no-ignore-file-name-case. X File name case sensitivity now affects file name exclusion. X Fix typos. X X * src/util.c: Include dirname.h. X (dir_file_pathname): Use base_name rather than file_name_lastdirchar. X X * src/system.h (S_IXUSR, S_IXGRP, S_IXOTH): New macros. X Include rather than rolling it ourselves. X (file_name_lastdirchar, HAVE_SETMODE, set_binary_mode): Remove. X X * src/sdiff.c: Include . X (expand_name): Use base_name rather than file_name_lastdirchar, for X portability to DOS. X (main): Initialize xalloc_exit_failure before possibly invoking X any memory allocator. X X * src/io.c: Include setmode.h. X X * src/diff3.c (main): X Initialize xalloc_exit_failure before possibly invoking any memory X allocator. X X * src/diff.c: Include dirname.h, setmode.h. X X (main): Later values and/or styles now silently override earlier. X (specify_value, specify_style): Likewise. All callers changed. X Remove. X (binary, main, option_help_msgid, compare_files): X HAVE_SETMODE -> HAVE_SETMODE_DOS. X (NO_IGNORE_FILE_NAME_CASE_OPTION): New constant. X (longopts, main, option_help_msgid): Support it. X (exclude_options): New function. X (main): Use it. Initialize xalloc_exit_failure before potentially X allocating memory. X X (filetype): Distinguish executable files from others, as POSIX X suggests. X X (compare_files): Use base_name instead of file_name_lastdirchar. X X * src/cmp.c: Include , . X (hard_locale_LC_MESSAGES): New macro. X (sprintc): Remove int width arg; it's now the caller's responsibility X to pad. All callers changed. X (stat_buf): New static var; was formerly a local var in 'main'. X (valid_suffixes): Add 'K', for 'KiB'. X (option_help_msgid): Don't confuse bytes with characters. X (main): Set xalloc_exit_failure before invoking anything that might X allocate memory. Fix bug: -n was incorrectly ignored when optimizing X the case of regular files with different lengths. X (cmp): Use an index column wide enough to store this comparison's X indexes. In locales other than the POSIX locale, say "byte" X rather than "char". X X * ms/config.bat: pc -> ms X X * ms/Makefile.am, m4/setmode.m4, lib/setmode.c, lib/setmode.h: X New file. X X * lib/Makefile.am (noinst_HEADERS): Add dirname.h, setmode.h. X (libdiffutils_a_SOURCES): Add basename.c, setmode.c. X X * Makefile.am (SUBDIRS): Add ms. X X2001-12-10 Paul Eggert X X * m4/fnmatch.m4: Test for FNM_CASEFOLD. X X2001-12-03 Paul Eggert X X * lib/posix/regex.h: Fix copyright notice. X X2001-12-03 Paul Eggert X X * NEWS, configure.ac (AM_INIT_AUTOMAKE): Version 2.7.4. X X * diff.texi (direntry, Overview, Comparison, Binary, Invoking cmp): X Use "byte" rather than "character" when talking about cmp, since X it compares bytes, not character. X (Invoking cmp): New trailing operands FROM-SKIP and TO-SKIP. X -i or --ignore-initial now accepts FROM-SKIP:TO-SKIP. X New option -n or --bytes. X Count operands now may be in octal or hex, and may be followed by a X size multiplier. X X * configure.ac (DEFAULT_DIFF_PROGRAM): X Define to "diff", not "$bindir/diff" (which didn't work anyway). X (AC_CHECK_MEMBERS): Add struct stat.st_blksize, struct stat.st_rdev. X (AC_STRUCT_ST_BLKSIZE, AC_STRUCT_ST_RDEV): Remove; obsolescent. X (AC_FUNC_FORK): Use this, instead of obsolescent AC_FUNC_VFORK. X (AC_CONFIG_FILES, AC_CONFIG_COMMANDS): Add. X (AC_OUTPUT): Remove args; they were obsolescent. X X * util.c (setup_output, begin_output, finish_output): X HAVE_FORK -> HAVE_WORKING_FORK || HAVE_WORKING_VFORK. X * sdiff.c (diffpid, cleanup, main, edit): Likewise. X * diff3.c (read_diff): Likewise. X X * system.h (STAT_BLOCKSIZE): X Use HAVE_STRUCT_STAT_ST_BLKSIZE, not HAVE_ST_BLKSIZE. X (vfork): New macro. X (HAVE_FORK): Remove. X (set_binary_mode): New macro. X X * sdiff.c (main): HAVE_VFORK -> HAVE_WORKING_VFORK. X (edit): Reopen the temporary file after the editor has run, in case X the editor operates by unlinking the old file and linking a new one. X (P_tmpdir): Rename from PVT_tmpdir; this fixes a typo. X All uses changed. X X * io.c (sip, read_files): X Remove tests for HAVE_SETMODE; use set_binary_mode X instead of setmode. X (sip): Fix typo in backward lseek when reverting to text mode. X X * config.site, config.sed, config.bat: New file. X X * Makefile.am (EXTRA_DIST): Add xstrtol.c. X (noinst_HEADERS): Add xstrtol.h. X (libdiffutils_a_SOURCES): Add xstrtoumax.c. X X * cmp.c: : Include. X (ignore_initial): Now an array with 2 elements. All uses changed. X (bytes): New var. X (HELP_OPTION): New constant. X (long_options, main): Use it. X (long_options, option_help_msgid, main, cmp): X Add support for -n or --bytes. X (parse_ignore_initial): New function. X (option_help_msgid, main): Add -i M:N. X (usage, main): Add two optional trailing operands, a la BSD. X (main): setmode -> set_binary_mode. X (cmp): Report byte number of what we've seen, not of the entire file. X This is to be consistent with the line number, which is always relative X with what we've seen. X X2001-12-02 Paul Eggert X X * diff.c (main, compare_files): setmode -> set_binary_mode. X X * xstrtol.c (__xstrtol): Don't accept 'Ki'; require 'KiB'. X X * xstrtol.c (__xstrtol): Add support for IEC 60027-2. X X2001-11-25 Paul Eggert X X * NEWS, configure.ac (AM_INIT_AUTOMAKE): Version 2.7.3. X X * README-alpha: New file. X X * src/Makefile.am (INCLUDES): Add -I../lib, for regex.h. X X * configure.ac: X Don't set LIB_CLOCK_GETTIME to 'none required'; set it to X the empty string instead. X X * lib/Makefile.am (EXTRA_DIST): Add strtoimax.c, strtol.c. X X * Makefile.am (SUBDIRS): Put intl before lib, so that libintl.h exists. X X * lib/Makefile.am (noinst_HEADERS): Add unlocked-io.h. X X * configure.ac (__EXTENSIONS__): New define, for the unlocked macros. X X * README: Add copyright notice. X Remove stuff that doesn't apply any more. X X * doc/diff.texi: offsets -> indices for cmp X X * src/cmp.c (option_help_msgid): offsets -> indices X X * src/diff.c (option_help_msgid): X Don't mention --binary on POSIX hosts. X X * src/sdiff.c (STRIP_TRAILING_CR_OPTION): New constant. X (longopts, option_help_msgid, main): Add -E, --ignore-tab-expansion, X --strip-trailing-cr. X X * doc/diff.texi: Change direcategory from Utilities to GNU Packages. X Add individual utilities. X Switch to Free Documentation License. X @code -> @command X @samp -> @option X GNU -> @sc{gnu} X Expand tabs to spaces, except when in an example that actually X uses tabs. X Prefer @node with just one arg. X Document -E or --ignore-tab-expansion, --strip-trailing-cr, X --ignore-file-name-case. X Regular expressions are now grep style, not Emacs style. X cmp's -c or --print-chars option is now -b or --print-bytes. X Time stamps now depend on LC_TIME. X -p now implies ^[[:alpha:]$_]. X Flags now include ' and 0. X cmp -i is an alias for --ignore-initial X Document --from-file, --to-file. X Document DIFF_OPTIONS. X X * configure.ac (AC_CHECK_FUNCS): Add gettimeofday, clock_gettime. X (LIB_CLOCK_GETTIME): New subst. X X * src/system.h: Assume C89 or better. X (_GNU_SOURCE): Remove; config.h now defines it. X (alloca): Declare like coreutils does it. X (verify, TYPE_SIGNED, TYPE_MINIMUM, TYPE_MAXIMUM, O_RDWR, X S_IRUSR, S_IWUSR): New macros. X (STAT_BLOCKSIZE): Parenthesize definiens. X : Include if HAVE_INTTYPES_H. X (CHAR_MAX, INT_MAX): Remove. X (PTRDIFF_MAX, SIZE_MAX): New macros. X (strtoumax): New decl. X Include stddef.h. X (bzero): Remove. X (bindtextdomain, textdomain, N_): New macros. X (ISPRINT, ISSPACE): Remove ifndef wrappers. X (ISUPPER, ISDIGIT): Remove. X (TOLOWER): New macro. X (MIN): Renamed from min; all callers changed. X (MAX): Likewise, from max. X (lin): New type. X (LIN_MAX): New macro. X (file_name_cmp): Renamed from filename_cmp. All callers changed. X (file_name_lastdirchar): Renamed from file_name_lastdirchar. X All callers changed. X (could_be_mvfs_stat_bug, could_be_nfs_stat_bug, X dev_may_have_duplicate_ino): Remove. X (HAVE_SETMODE, NULL_DEVICE): New macros. X (same_file): Do not check attributes. X (same_file_attributes): New macro. X X * src/util.c: Assume C89 or better. X int -> bool for booleans. X int -> lin for line numbers. X int -> size_t for sizes. X Use angle-brackets when including quotesys.h. X Include error.h, regex.h, xalloc.h. X (message5): sizeof -> offsetof X (begin_output): Invoke pr without -f. X (lines_differ): Renamed from line_cmp, and return bool not 3-way int. X All callers changed. X Add support for IGNORE_TAB_EXPANSION. X (change_letter): Now an array rather than a function. All X callers changed. X (translate_range): Translate line numbers to long, not lin, X for convenience with printf. X (analyze_hunk): Return enum changes instead of a count of X inserts and deletes. All callers changed. X (zalloc): New function. X X * src/side.c: Assume C89 or better. X int -> bool for booleans. X int -> lin for line numbers. X X * src/sdiff.c: Assume C89 or better. X int -> bool for booleans. X int -> lin for line numbers. X Use angle-brackets when including getopt.h, quotesys.h. X Include error.h, freesoft.h, stdio.h, xalloc.h. X (copyright_string): Use only most recent year. X (authorship_msgid, option_help_msgid): Wrap in N_(). X X (tmpname): Now volatile. X (tmpmade): Remove. X (tmp): New var. X (private_tempnam, exists, letters): Remove. X (temporary_file): New function. X (edit): Use it. X (interact): Use strtoumax, not atoi. X X * src/normal.c: Assume C89 or better. X int -> lin for line numbers. X X * src/io.c: Assume C89 or better. X int -> bool for booleans. X int -> lin for line numbers. X int -> size_t for sizes. X Use angle-brackets when including cmpbuf.h. X Include regex.h, xalloc.h. X (word): Remove; now done in system.h. X (hash_value): New type; use it instead of 'unsigned' for hash values. X (file_block_read): New function. X (sip, slurp): Use it. Now static. X (sip): Ensure block size is a multiple of word size. Clear eof flag. X (slurp): Use xalloc_die to report memory exhaustion. X (find_and_hash_each_line): Use TOLOWER instead of _tolower. X Add support for IGNORE_TAB_EXPANSION. X (prepare_text_end): Strip trailing CR if requested. X (find_identical_ends): Prepare the text only once, X if they're duplicates. X Let the compiler take advantage more of the fact that the buffers are X word-aligned. X (primes): Remove. X (prime_offset): New var. X (read_var): Use prime_offset instead of primes. X Use zalloc instead of xmalloc + bzero. X X * src/ifdef.c: Assume C89 or better. X int -> lin for line numbers. X (format_group): Use strtoumax to parse line numbers. X (format_group, print_ifdef_lines): Use do_printf_spec to X handle printf specs. X (groups_letter_value): Don't use _tolower; it's locale-dependent. X (do_printf_spec): Renamed from scan_printf_spec; now does the printing. X X * src/ed.c: Assume C89 or better. X int -> lin for line numbers (or 'long' when that's more convenient). X (print_ed_hunk): Fix bug when handling double-dot inserts. X X * src/dir.c: Assume C89 or better. X int -> bool for booleans. X Include error.h, exclude.h, xalloc.h. X X (dir_sort): Return 0 on error, 1 on success. All callers changed. X compare_names -> compare_names_for_qsort. X X (compare_names): Try strcasecmp if ignore_file_name_case. Then try X strcoll. Use file_name_cmp only as a last resort. Warn about X strcasecmp or strcoll failure. X (compare_names_for_qsort): New function. X X (diff_dirs): Use compare_names rather than filename_cmp. X X * src/diff3.c: Assume C89 or better. X int -> bool for booleans. X int -> lin for line numbers. X Use angle-brackets when including getopt.h, quotesys.h. X Include error.h, freesoft.h, inttostr.h, xalloc.h. X (copyright_string): Use only most recent year. X (authorship_msgid, option_help_msgid): Wrap in N_(). X X Rename the following variables for consistency with user-visible X option spellings. All uses changed. X (text): Renamed from always_text. X (initial_tab): Renamed from tab_align_flag. X X (horizon_lines): Remove. Remove all uses. X X (main): Invoke bindtextdomain and textdomain after setlocale. X Rename "DIFF" to "DIFF_PROGRAM". X X Try to compare file0 to file1, because this is where changes are X expected to come from. Diffing between these pairs of files is more X likely to avoid phantom changes from file0 to file1. X However, use file2 as the common file if this is a 3-way diff, X for backward compatibility. Suggested by Karl Tomlinson. X X (create_diff3_block): Use xcalloc instead of malloc + bzero. X X (INT_STRLEN_BOUND): Remove; now in system.h. X X (read_diff): Always use --horizon-lines=100 rather than trying X to guess it. X Do not pass --inhibit-hunk-merge. X Minimum chunk size is 1, not 8KiB. X Use xalloc_die to report memory exhaustion. X (undotlines): Use long for start, not int. X X * src/diff.h: Assume C89 or better. X int -> bool for booleans. X int -> lin for line numbers. X Don't include regex.h. X (enum changes): New enum. X (enum line_class): Remove; subsumed by enum changes. X (enum output_style): New constant OUTPUT_UNSPECIFIED. X X (ignore_space_change_flag, ignore_all_space_flag): Remove. X (ignore_white_space): New decl, subsuming the above two. All X uses changed. X X Rename the following decls for consistency with user-visible X option spellings. All uses changed. X (text): Renamed from always_text_flag. X (ignore_blank_lines): Renamed from ignore_blank_lines_flag. X (ignore_case): Renamed from ignore_case_flag. X (brief): Renamed from no_details_flag. X (initial_tab): Renamed from tab_align_flag. X (expand_tabs): Renamed from tab_expand_flag. X (starting_file): Renamed from dir_start_file. X (paginate): Renamed from paginate_flag. X (sdiff_merge_assist): Renamed from sdiff_help_sdiff. X (left_column): Renamed from sdiff_left_only. X (suppress_common_lines): Renamed from sdiff_skip_common_lines. X (speed_large_files): Renamed from heuristic. X (minimal): Renamed from no_discards. X X (inhibit_hunk_merge): Remove. X X (strip_trailing_cr, excluded, time_format): New decls. X X (files_can_be_treated_as_binary): Renamed from ignore_some_changes. X X (group_format, line_format): Now char const *[], not char *[]. X X (struct file_data): Buffer is now word*, not char*, as it's always X aligned and this can help the compiler. buffered_chars -> buffered X (since it's a byte count, not a char count). All uses changed. X New member `eof'. X X (FILE_BUFFER): New macro. X X (excluded_filename, error, free_software_msgid): Remove decls; now in X other .h files. X X (sip, slurp): Remove decls. X (file_block_read): New decl. X (change_letter): Now an array, not a function. X (lines_differ): Renamed from line_cmp. X (analyze_hunk): Now returns enum changes rather than two change counts. X X * src/Makefile.am (diff_LDADD): New symbol. X X * src/diff.c: Assume C89 or better. X int -> bool for booleans. X long -> off_t for line numbers. X Use angle-brackets when including getopt.h, fnmatch.h, quotesys.h. X Include error.h, exclude.h, freesoft.h, hard-locale.h, prepargs.h, X regex.h, signal.h, xalloc.h. X (copyright_string): Use only most recent year. X (authorship_msgid, option_help_msgid): Wrap in N_(). X X Rename the following variables for consistency with user-visible X option spellings. All uses changed. X (binary): Renamed from binary_flag. X (new_file): Renamed from entire_new_file_flag. X (unidirectional_new_file): Renamed from unidirectional_new_file_flag. X (report_identical_files): Renamed from print_file_same_flag. X X (numeric_arg): Remove. X X (exclude, exclude_alloc, exclude_count, excluded_filename, add_exclude, X add_exclude_file): X Remove; now done by exclude.h. X X (BINARY_OPTION, FROM_FILE_OPTION, HELP_OPTION, HORIZON_LINES_OPTION, X IGNORE_FILE_NAME_CASE_OPTION, INHIBIT_HUNK_MERGE_OPTION, X LEFT_COLUMN_OPTION, LINE_FORMAT_OPTION, NORMAL_OPTION, X SDIFF_MERGE_ASSIST_OPTION, STRIP_TRAILING_CR_OPTION, X SUPPRESS_COMMON_LINES_OPTION, TO_FILE_OPTION, X UNCHANGED_LINE_FORMAT_OPTION, OLD_LINE_FORMAT_OPTION, X NEW_LINE_FORMAT_OPTION, UNCHANGED_GROUP_FORMAT_OPTION, X OLD_GROUP_FORMAT_OPTION, NEW_GROUP_FORMAT_OPTION, X CHANGED_GROUP_FORMAT_OPTION): New constants. X (longopts, main): Use them. X X (longopts, main, option_help_msgid): Add -E, --from-file, --to-file. X X (main): Invoke bindtextdomain and textdomain after setlocale. X Use grep syntax, not Emacs, for regular expressions. X Use exclude.h, not our own functions. X Use ISO 8601 time format in hard locales. X Prepend DIFF_OPTIONS. X Don't update ignore_some_changes. X Use strtoumax instead of numeric_arg. X Use specify_value when appropriate. X error -> try_help when appropriate. X -p now means ^[[:alpha:]$_], not ^[_a-zA-Z$]. X Ignore --inhibit-hunk-merge. X Prefer changed group formats to unchanged ones. X Remove now-unnecessary casts. X Set files_can_be_treated_as_binary. X X (specify_value): Renamed from specify_format. All uses changed. X X (specify_style): Default is now unspecified, not normal. All X uses changed. X X (set_mtime_to_now): New function. X (compare_files): Use it. Use memset, not bzero. X Set stdin mtime to current time even when stdin is not a regular file. X Check for same file attributes, as well as for same file. X Use files_can_be_treated_as_binary. X "write failed" -> "standard output on output failure. X X * src/context.c: Assume C89 or better. X int -> lin for line numbers. X Include inttostr.h, regex.h. X (TIMESPEC_NS): New macro. X (nstrftime): New decl. X (print_context_label): Use nstrftime and time_format to format times. X Print numeric time stamp value if localtime fails. X (print_context_function): New function. X (pr_context_hunk, pr_unidiff_hunk): Use it. X (find_function): Use size_t for sizes, not int. X X * src/cmp.c: Assume C89 or better. X int -> bool for booleans. X long -> off_t for line numbers. X Use angle-brackets when including cmpbuf.h, getopt.h. X Include error.h, freesoft.h, inttostr.h, xalloc.h. X (copyright_string): Use only most recent year. X (authorship_msgid): Wrap in N_(). X (buffer): Now word*, not char*. All uses changed. X (word): Remove macro; now in system.h. X (long_options, option_help_msgid, main): -c --print-chars -> X -b --print-bytes X (check_stdout): "write failed" -> "standard output" X (option_help_msgid): Wrap in N_(). X (main): Invoke bindtextdomain and textdomain after setlocale. X Use strtoumax instead of doing the work ourselves. X Check for same_file_attributes as well as same_file. X (cmp): Use ssize_t for read returns, not size_t. X Do not assume that size_t is not narrower than int. X Do not assume that line numbers fit in 'long'. X (block_compare_and_count, block_compare): X Compiler now checks that buffers are word-aligned. X (block_compare_and_count): Count sizes with size_t, not long. X (sprintc): byte arg is unsigned char, not unsigned. X X * src/analyze.c: Assume C89 or better. X int -> lin for line numbers. X int -> bool for booleans. X unsigned int -> size_t for sizes. X Use angle-brackets when including cmpbuf.h. X Include error.h, regex.h, xalloc.h. X (discard_confusing_lines, diff_2_files): Use zalloc rather X than xalloc+bzero. X (discard_confusing_lines): unsigned int -> lin for values that X are really line numbers. X (shift_boundaries): Do not inhibit hunk merges. X (build_reverse_script, build_script, diff_2_files): Use |, not ||. X (diff_2_files): no_details_flag & ~ignore_some_changes -> X files_can_be_treated_as_binary. Esure that buffer size is a multiple X of sizeof (word). Use file_block_read to read buffers. X (diff_2_files): Abort if output style is not one of the X expected styles. X X2001-11-23 Paul Eggert X X * src/Makefile.am, m4/vararrays.m4: New file. X X * m4/prereq.m4 (jm_PREREQ_READUTMP): X Remove, as it gives autoheader the willies. X X * m4/README, lib/prepargs.h, lib/prepargs.c, lib/offtostr.c, X lib/umaxtostr.c, lib/inttostr.c, lib/inttostr.h, X lib/imaxtostr.c, lib/freesoft.h: New files. X X * lib/freesoft.c: Include config.h, freesoft.h rather than diff.h. X (free_software_msgid): Wrap contents in N_. X X * lib/cmpbuf.h: Use prototypes instead of old-style functions. X X * lib/cmpbuf.c: X Don't include system.h; instead, include config.h, unistd.h. X Use prototypes instead of old-style functions. X (block_read): Don't assume that int is no wider than size_t. X X * lib/Makefile.am, po/POTFILES.in: New file. X X2001-11-22 Paul Eggert X X * pc/config.h: X Define filename_cmp as an object-like macro, not as a function-like X macro. X X * exgettext: Always operate in the C locale. X Set AWK using a method that works even with broken shells. X X * doc/Makefile.am: New file. X X * configure.ac (AC_INIT): X Use src/diff.c, not diff.h, as the source files got removed. X (AM_CONFIG_HEADER): Switch from AC_CONFIG_HEADER. X (AC_ARG_PROGRAM, AC_MINIX): Remove. X X (AC_PREREQ, AM_INIT_AUTOMAKE, ALL_LINGUAS, AC_PROG_AWK, X AM_PROG_CC_STDC, AC_PROG_RANLIB, AC_C_INLINE, AC_C_VARARRAYS, X DEFAULT_DIFF_PROGRAM, DEFAULT_EDITOR_PROGRAM, X AC_STRUCT_ST_MTIM_NSEC): Add. X X (PR_PROGRAM): AC_DEFINE. X X (AC_SYS_LARGEFILE): Use instead of our homebrew version. X X (_GNU_SOURCE): Define if not defined. X X (AC_CHECK_HEADERS): Add stdbool.h, unistd.h. X (AC_CHECK_TYPES): Add ptrdiff_t, uintmax_t. X (AM_GNU_GETTEXT, XGETTEXT): Add. X X (WITH_MVFS_STAT_BUG, WITH_NFS_STAT_BUG): Remove. X (HAVE_MEMCHR): Remove. X (AC_CHECK_FUNCS): Add diraccess. X (AC_REPLACE_FUNCS): Add memchr, waitpid. X (jm_FUNC_GLIBC_UNLOCKED_IO, jm_FUNC_GNU_STRFTIME, jm_FUNC_MALLOC, X jm_FUNC_REALLOC, jm_PREREQ_ERROR, jm_PREREQ_QUOTEARG, jm_PREREQ_REGEX, X jm_PREREQ_TEMPNAME, jm_AC_PREREQ_XSTRTOUMAX, AC_FUNC_FNMATCH): Add. X (fnmatch.h, regex.h): Do not create these files unless we're using X our own fnmatch and regex. X X (AC_OUTPUT): Add doc/Makefile, intl/Makefile, lib/Makefile, X lib/posix/Makefile, m4/Makefile, po/Makefile.in, src/Makefile. X X * Makefile.am: New file. X X * po/en_GB.po: Don't translate "program" to "programme". X X2001-11-20 Paul Eggert X X * m4/prereq.m4: New file. X X2001-03-16 Paul Eggert X X * lib/tempname.c (uint64_t): X Define if not defined, and if UINT64_MAX is not defined. X X2001-02-26 Paul Eggert X X * lib/tempname.c: glibc 1.32 X X2001-02-17 Paul Eggert X X * m4/Makefile.am.in: GNU fileutils 4.1 X X2001-01-09 Paul Eggert X X * lib/tempname.c (struct_stat64): New macro. X (direxists, __gen_tempname): Use it. This avoids a portability problem X with Solaris 8. X X * lib/tempname.c (): Include if HAVE_CONFIG_H. X (, , ): X Include only if STDC_HEADERS || _LIBC. X (): Include only if HAVE_FCNTL_H || _LIBC. X (): Include only if HAVE_UNISTD_H || _LIBC. X (): Include only if HAVE_SYS_TIME_H || _LIBC. X (__set_errno): Define this macro if doesn't. X (P_tmpdir, TMP_MAX, __GT_FILE, __GT_BIGFILE, __GT_DIR, __GT_NOCREATE): X Define these macros if doesn't. X (S_ISDIR, S_IRUSR, S_IWUSR, S_IXUSR): X Define these macros if X doesn't. Ignore S_ISDIR if STAT_MACROS_BROKEN. X (stat64, __getpid, __gettimeofday, __mkdir, __open, __open64, lxstat64, X __xstat64): Define if not _LIBC. X (__secure_getenv): Define if ! (HAVE___SECURE_GETENV || _LIBC). X (__gen_tempname): Invoke gettimeofday only if HAVE_GETTIMEOFDAY X || _LIBC; otherwise, fall back on plain "time". X Use macros like S_IRUSR | S_IWUSR rather than octal values like 0600. X X * lib/mkstemp.c (__GT_FILE): Define to zero if not defined. X X2000-10-25 Paul Eggert X X * lib/hard-locale.c: New file. X X2000-02-05 Paul Eggert X X * exgettext: From GCC repository X X1999-07-06 Paul Eggert X X * lib/mkstemp.c: glibc 2.2 X X1998-12-11 Paul Eggert X X * src/sdiff.c (lf_snarf): X Fix bug when help line wrapped around the input buffer. X X1998-09-15 Paul Eggert X X * diff.texi: Add @dircategory and @direntry. X X1998-09-14 Paul Eggert X X * Makefile.in (VERSION): Version 2.7.2. X (DEFAULT_DIFF_PROGRAM): Renamed from DIFF_PROGRAM. X (PR_PROGRAM): All `configure' to define it. X (srcs): Add $(diffutils_srcs), freesoft.c, quotearg.c instead of X quote.c, quotearg.h. X (distfiles): Add acconfig.h, message/*. X (all): Depend on $(destfiles), not info. X (version.c): Parenthesize `GNU diffutils'. X (common_o): Add freesoft.o X (diff_o): quote.o -> quotearg.o X (diff3_o, sdiff_o): Likewise. X (diff.dvi): Depend on version.texi. X (diff.o diff3.o quotearg.o sdiff.o util.o): X New dependency on quotearg.h X (diff3.o): DIFF_PROGRAM -> DEFAULT_DIFF_PROGRAM. X (sdiff.o): Likewise. X (messages.po): Remove. X (message/msgid.po, message/template.po): New rules. X (maintainer-clean): Renamed from realclean. X (install): Install from source directory, if applicable. X Invoke install-info if needed. X (install-strip): New rule. X (check): Set DIFF. X (stamp-h.in): Don't put the date into the timestamp. X (D_dirs): Add $D/message. X ($D.tar.gz): Compress with gzip -9. X Don't use ln to create distribution; it doesn't work with symlinks. X (srcs, distfiles, diff_o, diff3_o, sdiff_o): Rename quotearg.c to X quotesys.c and quotearg.h to quotesys.h. X X * configure.in (AC_PATH_PROG): Add PR_PROGRAM. X If available, prefer support for large files unless the user specified X one of the CPPFLAGS, LDFLAGS, or LIBS variables. X (AC_STRUCT_ST_RDEV): Add. X (HAVE_ST_FSTYPE_STRING): Add. X (--with-mvfs-stat-bug, --with-nfs-stat-bug): New options. X (HAVE_MEMCHR): New macro. X (AC_CHECK_FUNCS): Add sicprocmask. X X * diff.h (XTERN): Renamed from EXTERN. X (struct filedata): Remove dir_p arg. X (struct comparison): New type. X (diff_2_files, diff_dirs)" Ise ot/ X (error): Add printf attribute if applicable. X (free_software_msgid): New decl. X (pr_program): New decl. X (fatal): Add noreturn attribute. X (pfatal_with_name): Likewise. X X * system.h (__attribute__): New macro. X (getenv): Don't declare if HAVE_STDLIB_H. X (CHAR_MAX): New macro. X (): New include. X (): Include before . X (could_be_mvfs_stat_bug, could_be_nfs_stat_bug, X dev_may_have_duplicate_ino, same_special_file): New macros. X (same_file): Use them. X X * cmp.c (authorship_msgid): New var. X (free_software_msgid): New decl. X (error): Now has printf attribute. X (try_help): Likewise. X (long_options): Don't assume ASCII. X (try_help): Now accepts operand arg. X (main): Check for -1, not EOF, when calling getopt_long. X Report --ignore-initial value when complaining about it. X Output copyright and free software info with -v. X Don't assume ASCII. X Report last operand when one is missing. X Report text of extra operand. X Move block_read into cmpbuf.c. X X * diff.c (authorship_msgid): New var. X (quotesys.h): Include. X (ck_atoi): Remove. X (function_regexp_list, ignore_regexp_list): Now static. X (binary_flag): Renamed from binary_I_O. X (entire_new_file_flag, unidirectional_new_file_flag, X print_file_same_flag): Now static. X (numeric_arg): Renamed from ck_atoi. X New argument specifying the argument type. X (longopts, main): Don't assume ASCII. X (longopts): Remove old aliases --file-label, --entire-new-file, X --ascii, --print. X (main): Check for -1, not EOF, when calling getopt_long. X Use numeric_arg to report errors. X Report error if -l specified but pagination is not supported. X Report error if -S is specified twice with conflicting values. X Have --version conform to the new GNU standards. X Add new --from-file, --to-file, --inhibit-hun,-merge options. X Make the horizon at least as large as the context. X Add casts to pacify gcc -Wall. X (try_help): Add operand arg. X (option_help_msgid): Doc fix to match above. X (usage): Indent option_help_msgid. X (compare_files): Now takes struct comparison X instead of two directory names and a depth. X (NONEXISTENT, UNOPENED, ERRNO_ENCODE, ERRNO_DECODE): X New macros. X (DIR_P): New macro. X Report error if fflush does. X X * cmpbuf.c (block_read): Moved here from cmp.c. X X * cmpbuf.h (block_read): New decl. X X * io.c (cmpbuf.h): Include. X (slurp): Check for arithmetic overflow when computing buffer size. X X * dir.c (diff_dirs): Check for recursive directory loop. X Arg is now struct comparison const *. X (dir_loop): New function X X * analyze.c (no_discards): Remove. X (inhibit): Remove. X (shift_boundaries): Don't inhibit. If inhibit_hunk_merge is nonzero, X don't merge hunks. X (briefly_report): Now returns 2 if trouble, CHANGES otherwise. X (diff_2_files): Now takes struct comparison. If briefly_report reports X trouble, pass it on to caller. X X * side.c (print_half_line): Add brackets to pacify GCC -Wall. X X * sdiff.c (quotesys.h): Include. X (DIFF_PROGRAM, DEFAULT_EDITOR_PROGRAM): Remove. X (free_software_msgid, editor_program, not_found): New vars. X (diffbin, edbin): Remove. X (editor_program): Renamed from edbin. X (edit, interact): Now take extra string arg. X (exiterr, fatal, perror_fatal, try_help): Add noreturn attribute. X (sigset_t, sigemptyset, sigmask, sigaddset, SIG_BLOCK, SIG_SETMASK): X (sigprocmask): New macros, if !HAVE_SIGPROCMASK. X (error): Now has printf attribute. X (longopts, main): Don't assume ASCII. X (try_help): New operand arg. X (usage): Conform to new GNU standards. X (main): Set static vars for editor and diff program. X Compare getopt_long result to -1, not EOF. X -v conforms to new GNU standard. X Complain better about extra and missing operands. X If HAVE_VFORK, block SIGINT and SIGPIPE in the parent, since when X the child munges its handlers it may somp on the parent. X Pass rname to intract. X Translate not-found message before forking. X (give_help): Just output it all at once. X (edit): New args lname, lline, rname, rline. X (edit): New command 'd'. X (interact): New args lname, rname. X X * util.c (quotesys.h): Include. X (PR_PROGRAM): New macro. X (pfatal_with_name): Abort if error returns. X (fatal): Likewise. X (print_message_queue): Free message chain after printing. X (currently_recursive): Renamed from current_depth, and now a boolean. X (begin_output): Report error if fflush does. X Avoid stdio and gettext in child. X X * diff3.c (quotesys.h): Include. X (free_software_msgid): New decl. X (RANGE_START, RANGE_END): Renamed from START and END. X (fatal, perror_with_exit, try_help): Add noreturn attribute. X (error): Add printf attribute. X (diff_program): Now a ptr, not an array. X Initialize to DEFAULT_DIFF_PROGRAM instead of DIFF_PROGRAM. X (longopts, main): Don't assume ASCII. X (main): Use DIFF environment var to specify name of diff program. X Compare getopt_long result to -1, not EOF. X -v now reports version according to new GNU standard. X Report spelling of extra operand, or last operand before missing one. X (try_help): Now takes operand arg. X (option_help_ms): Fix typo: missing comma. X (usage): Update as per current GNU standards. X (environ): Remove decl. X (read_diff): Invoke diff with --inhibit-hunk-merge. X Translate `not found' message before forking. X Quote name of diff program. X Pass horizon lines. X `memory exhausted' -> `Memory exhausted' X X * pc/makefile (%.exe): Remove. X (pc-clean): Remove *.exe X * pc/makefile.sed (DEFAULT_DIFF_PROGRAM): Renamed from DIFF_PROGRAM. X When editing mkinstalldirs rule, look for exec_prefix and prefix. X Add .exe when installing files. X * pc/emx/config.h (same_file): Add. X * pc/config.h (same_file): Remove. X * pc/djgpp/config.h: Adjust to latest patch from eliz. X * pc/djgpp/makefile.sed: Don't alter PROGRAMS. X * pc/pc.c: Update FSF address. X (quote_system_arg): Renamed from system_quote_arg. X X * README: Add --with-mvfs-stat-bug, --with-nfs-stat-bug. X X * getmsgids: Add copyright date and update FSF address. X X * diff.texi: Document recent changes. X The patch doc still corresponds to patch 2.2, unfortunately. X Update GNU bug reporting address. Omit Larry Wall's address; X it's obsolete and he's busy with perl. X X * context.c: Fix spacing. X X * NEWS: Mention --from-file=FILE, --to-file=FILE, ed. X X * acconfig.h, freesoft.c, message/de.po, message/en_UK.po, X message/es.po, message/fr.po, message/pl.po, message/sv.po: X New files. X X * ed.c: Remove `#if 0'ed code. X X * normal.c, waitpid.c: Update FSF address. X X1998-03-15 Paul Eggert X X * quotesys.c: Renamed from quotearg.c. X X * quotesys.h: Renamed from quotearg.h X (__QUOTESYS_P): Renamed from __QUOTEARG_P. X X1997-05-05 Paul Eggert X X * quotesys.c, quotesys.h: New file. X XMon Nov 14 05:10:56 1994 Paul Eggert X X Add internationalization support. X Several messages have been changed slightly, X to make them more consistent and easier to translate. X All strings that are messages are passed through gettext once before X being used, so that they can be localized. X Each function and macro whose first parameter is a gettext msgid X has had its first parameter's name changed so it ends in `msgid'. X All arrays of msgids have had their names changed to end in `msgid'. X `getmsgids' uses this to determine which strings are msgids. X X * pc/COPYING, pc/INSTALL, pc/config.h, X pc/djgpp/config.h, pc/djgpp/makefile.sed, X pc/emx/config.h, pc/emx/diff.def, pc/emx/gnuregex.def, X pc/emx/makefile.sed, X pc/makefile, pc/makefile.sed, pc/pc.c: New files, for PC support. X X * getmsgids: New file. X X * Makefile.in (PACKAGE, VERSION, diffutils_srcs, D): New vars. X (version.c, version.texi, messages.po): New files. X messages.po is built automatically from source files and `getmsgids'. X (distfiles): Add them, pc/*, and getmsgids. X (diff.info): Now depends on version.texi. X (realclean): Clean messages.po, version.*. X (dist): Just build $D.tar.gz. X ($D.tar.gz): New file, takes over old `dist' function. X Don't assume $(distfiles) are all in same directory. X X * configure.in (AC_CHECK_HEADERS): Add libintl.h, locale.h. X (AC_CHECK_LIB): Check for -lintl. X X * analyze.c (briefly_report): Rewrite `message (A?"B":"C")' as X `if (A) message ("B") : message ("C")'; this is for getmsgids. X (briefly_report, diff_2_files): For label, use file_label if set. X * diff.c (compare_files): Likewise. X X * system.h (gettext): Declare; use a stub if ! HAVE_LIBINTL_H. X (setlocale): Declare; use a stub if ! HAVE_LOCALE_H. X X * cmp.c, diff.c, diff3.c, sdiff.c (main): X Invoke setlocale first thing, to tell library we're internationalized. X (option_help_msgid): New constant. X (usage): Use it, so message is translated one option at a time. X * sdiff (help_msgid, give_help): Likewise. X X * cmp.c (sprintc): Renamed from `printc'. X Now outputs to a buffer instead of stdout. X (cmp): Use new sprintc; it's easier to internationalize. X X * diff.c (main): -D FOO now outputs `/* ! FOO */ instead of X `/* not FOO */'. X X * sdiff.c (version_string): Fix decl typo: `const' was missing. X (trapsigs): Ignore sigaction failure, to be compatible with `signal'. X X * util.c (struct msg, message5, print_message_queue): X Allocate just one block of memory to save a message. X XWed Nov 9 17:42:44 1994 Paul Eggert X X * sdiff.c (trapsigs): Don't check signal return value, since it's X bogus under djgpp. X XMon Oct 31 07:27:27 1994 Paul Eggert X X * Makefile.in (srcs, diff_o, diff3_o, sdiff_o): X New files quote.c, quote.o. X X * diff.h (function_regexp, ignore_regexp): Replace lists of compiled X regexps with these single compiled regexps. All users changed. X (regexp_list,function_regexp_list,ignore_regexp_list): Move to diff.c. X * diff.c (add_regexp): Build one big regexp instead of a regexp list. X (summarize_regexp_list): New function. X (regexp_list): Redesigned struct; moved here from diff.h. X (function_regexp_list, ignore_regexp_list): Likewise, for vars. X X * context.c (find_function): Simplify interface: X don't return size of function line. All callers changed. X (print_context_script, find_function): INT_MAX now denotes no X previous match; this is simpler than `- file->prefix_lines - 1'. X X * diff3.c (read_diff): Quote arguments with system_quote_arg. X * sdiff.c (main): Use system_quote_arg to compute command. X * diff.c (option_list): Quote options with system_quote_arg. X * util.c (begin_output): Use system_quote_arg to compute command. X X * util.c (pr_program): New var. X (analyze_hunk): Fix off-by-1 line length bug. X Match with one big regexp instead of a list of regexps. X Use new `trivial_length' local instead of comparing first byte to `\n'. X Help the compiler with linbuf local vars. X X * system.h (system_quote_arg): X New function; replaces SYSTEM_QUOTE_ARG macro. X XSat Oct 15 20:09:12 1994 Paul Eggert X X * system.h (_tolower): Define if not already defined. X * io.c (find_and_hash_each_line): Change tolower to _tolower; this X speeds up diff -i considerably on some hosts (e.g. Solaris 2.3). X * util.c (line_cmp): Likewise. X * ifdef.c (groups_letter_value): Likewise. X X * diff.h (ignore_some_line_changes): Remove. All users changed. X * io.c (find_and_hash_each_line): Don't invoke line_cmp if the length X differs and -i is in force. Don't assume ISSPACE ('\n') is nonzero. X X * diff.h (xmalloc_exit_failure): New variable. X All `main' programs set this variable at the start. X xmalloc and xrealloc are now taken from GNU library. X * cmp.c (main): Align buffer size to word size; some mallocs care. X * io.c (slurp): Likewise. X * diff.c (add_exclude): Can now assume xrealloc (0, ...) works. X (add_regexp): Free storage on failure. Allocate storage all at one go. X * system.h (malloc, realloc): Remove unused declarations. X * diff3.c, sdiff.c, util.c (xmalloc, xrealloc): Remove. X * sdiff.c (diffarg): Take advantage of cleaner xrealloc semantics. X X * io.c (ROL): Use sizeof to make it more generic. X X * Makefile.in (common_o): New variable. X Link error.o and xmalloc.o into all programs. X (check): Depend on $(PROGRAMS). X X * diff.h (error): Change to GNU library standard. All callers changed. X * diff3.c (main): Use strerror (EISDIR) instead of "Is a directory". X (fatal, perror_with_exit): Use `error'. X * util.c (perror_with_name, fatal): Use GNU `error'. X (error): Remove. X XWed Oct 12 17:04:40 1994 David J. MacKenzie (djm@duality.gnu.ai.mit.edu) X X * cmp.c (main): Set xmalloc_exit_failure. X XSat Oct 1 05:24:19 1994 Paul Eggert X X * Version 2.7 released. X X * configure.in (AC_HEADER_SYS_WAIT): Add. X (AC_CHECK_HEADERS): Remove sys/wait.h. X (AC_CHECK_FUNCS): Add tmpnam. X * system.h (, WEXITSTATUS): Use simpler scheme X now that HAVE_SYS_WAIT_H is not set on hosts X that are incompatible with Posix applications. X X * util.c (dir_file_pathname): Use filename_lastdirchar not strrchr. X * sdiff.c (expand_name): Likewise. X (private_tempnam): Use tmpnam if HAVE_TMPNAM; this simplifies porting. X (exists, letters): Omit if HAVE_TMPNAM. X X * diff3.c (read_diff): If STAT_BLOCKSIZE yields zero, X adjust it to a more reasonable value. X XSat Sep 24 20:36:40 1994 Paul Eggert X X * sdiff.c (exists, private_tempname): Adopt latest GNU libc algorithm. X (private_tempnam): Specialize for sdiff to avoid portability problems. X XThu Sep 22 16:47:00 1994 Paul Eggert X X * configure.in (AC_ARG_PROGRAM): Added. X (AC_OUTPUT): Add [date > stamp-h]. X X * Makefile.in (DEFAULT_EDITOR_PROGRAM, DIFF_PROGRAM, LIBOBJS, X NULL_DEVICE, PR_PROGRAM, PROGRAMS): New variables. X (check, stamp-h.in, cmp.o, util.o): New targets. X (edit_program_name): New variable; replaces old binprefix method. X (install, uninstall): Use it. X (binprefix): Removed. X (distfiles): Add stamp-h.in. X (clean): Clean stamp-h. X (config.hin, config.h): Use time stamp files. X (cmp_o): Add $(LIBOBJS). X (install): Install info files from srcdir if they're not in `.'. X X * cmp.c, io.c (word): Don't define if already defined. X X * comp.c (main): Use setmode, not open(..., O_BINARY); this gets stdin. X Use NULL_DEVICE instead of "/dev/null". X (cmp): Use %lu instead of %ld when it is more likely to be right. X X * diff.h (PR_FILE_NAME): Rename to PR_PROGRAM and move to Makefile.in, X util.c. X X * diff3.c (main): Give proper diagnostic if too many labels were given. X (read_diff): Use SYSTEM_QUOTE_ARG. X X * system.h: : Include if HAVE_STRING_H, too. X : Include here. All includers changed. X (CTYPE_DOMAIN, ISDIGIT, ISPRINT, ISSPACE, ISUPPER): New macros that X work around common problems. X (O_BINARY): Remove. X (SYSTEM_QUOTE_ARG): New macros. X X * diff.c: Add comment. X X * util.c (PR_PROGRAM): Moved here from diff.h. X (begin_output): Use SYSTEM_QUOTE_ARG. X X * io.c (read_files): Set mode to binary before returning 1. X X * sdiff.c (TMPDIR_ENV): New macro. X (DEFAULT_EDITOR_PROGRAM): Renamed from DEFAULT_EDITOR for consistency. X (expand_name): Change `isdir' to `is_dir' to avoid theoretical ctype X namespace contamination. X (main): Use SYSTEM_QUOTE_ARG. X (private_tempnam): Don't access "/tmp" directly; use PVT_tmpdir. X XTue Sep 13 18:46:43 1994 Paul Eggert X X * configure.in (AC_FUNC_MEMCHR): Remove. Autoconf didn't adopt this, X since we need not worry about an old experimental library X where memchr didn't work. X (AC_FUNC_MEMCMP): Not needed, since we only test for equality. X (AC_REPLACE_FUNCS): Add test for memchr. X (AC_CHECK_FUNCS): Check for memchr, not memcpy, since it'll be cached. X (AC_CHECK_HEADERS): Add string.h; regex.c uses on some old hosts. X X * system.h (memcmp): Define in terms of bcmp. X Use HAVE_MEMCHR to test for all mem* routines. X X * Makefile.in (srcs): Remove memcmp.c. X We use bcmp if memcmp doesn't work, since we only test for equality. X XMon Sep 12 15:52:22 1994 Paul Eggert X X * configure.in (AC_CONFIG_HEADER): Rename config.h.in to config.hin. X (AC_ISC_POSIX, AC_MINIX): Go back to these old names for Autoconf 2. X (AC_CHECK_HEADERS): Remove now-redundant check for . X (AC_CHECK_FUNCS): Check for strchr. X (AC_FUNC_MEMCHR, AC_FUNC_MEMCMP, AC_CHECK_FUNCS): Use special-purpose X macros when suitable. X * memcmp.c: New file. X * Makefile.in (CPPFLAGS, DEFS, CFLAGS, LDFLAGS, prefix, exec_prefix): X Default to autoconf-specified strings. X (COMPILE): Use the defaults. X (srcs): Add memcmp.c. X (distfiles): Rename config.h.in->config.hin, install.sh->install-sh. X (Makefile, config.h, config.hin, config.status): Rework for X compatibility with Autoconf 2. X * io.c (binary_file_p): Assume non-broken memchr. X * memchr.c: Assume compiler understands void *; otherwise X we don't match GCC's internal declaration of memchr. X * system.h: Use more modern autoconf approach to standard C headers. X * version.c: Include , not "config.h". X X * diff.c, diff.h (ignore_some_line_changes): X New variable; replaces `length_varies'. X (line_end_char): Replace with '\n'; it wasn't being used consistently. X X * io.c (find_and_hash_each_line): Fix inconsistencies with -b -w -i and X incomplete lines. Put incomplete lines into their own bucket. X This means line_cmp no longer needs line length arguments, X and equivalence classes' line lengths no longer need to include \n. X Invoke line_cmp only if ignore_some_line_changes. X (prepare_text_end): -B no longer ignores missing newlines. X (read_files): Allocate another bucket for incomplete lines. X X * util.c (line_cmp): Now takes just two arguments. No longer X optimizes for common case of exact equality; the caller does that X optimization now. The caller is changed accordingly. X Optimize for the common case of mostly equality. X Use isupper+tolower instead of islower+toupper, for consistency. X X * waitpid.c (waitpid): Fix typo with internal scoping. X XThu Sep 8 08:23:15 1994 Paul Eggert X X * configure.in: Revamp for Autoconf 2. X * memchr.c, waitpid.c: New source files for substitute functions. X * Makefile.in (diff_o, diff3_o, sdiff_o): Add $(LIBOBJS). X (srcs): Add memchr.c, waitpid.c. X (distfiles): Add install.sh, memchr.c, waitpid.c, install.sh. X * system.h: Use Autoconf 2 style HAVE_DIRENT_H etc. macros for dirs. X * dir.c (dir_sort): Prefer NAMLEN (p) to strlen (p->d_name). X Change VOID_CLOSEDIR to CLOSEDIR_VOID for Autoconf 2. X * sdiff.c, util.c (memchr, waitpid): Remove; use new substitutes. X * diff3.c (read_diff): Use new waitpid substitute. X X * cmp.c, diff.c, diff3.c, sdiff.c (check_stdout, try_help): New fns. X (usage): Just print more detailed usage message; let caller exit. X * diff.c (option_help): New variable. X (filetype): Add Posix.1b file types. X XFri Sep 2 16:01:49 1994 Paul Eggert X X * configure.in: Switch to new autoconf names. Add sys/file.h test. X * Makefile.in (distclean): Clean config.cache, config.log X (used by new autoconf). X X * diff.c, diff3.c, (main), sdiff.c (trapsigs): If we'll have children, X make sure SIGCHLD isn't ignored. X X * diff3.c (DIFF_CHUNK_SIZE): Removed. Get size from STAT_BLOCKSIZE. X (INT_STRLEN_BOUND): New macro. X X * ifdef.c (format_group, groups_letter_value): X Use * instead of [] in prototypes. X X * system.h: Include only if HAVE_SYS_FILE_H. X (S_IXGRP, S_IXOTH, S_IXUSR): Remove unused macros. X X * util.c (begin_output): Check fdopen result. X X The following changes simplify porting to non-Posix environments. X * cmp.c, diff.c, diff3.c, sdiff.c, (main): Call initialize_main first. X * diff.c (binary_I_O): New variable for --binary option. X (main, usage, compare_files): Support --binary option. X (compare_files): Use filename_lastdirchar to find last X directory char in a file name. X * cmp.c (main), diff.c (compare_files), dir.c (compare_names, X diff_dirs): Use filename_cmp to compare file names. X Use same_file to determine whether two files are the same. X * context.c (print_context_label): Check whether ctime yields 0. X * diff3.c (read_diff), sdiff.c (cleanup, main, waitpid), X util.c (begin_output): Use popen+pclose if !HAVE_FORK. X * io.c (sip): If HAVE_SETMODE, test for binary files in O_BINARY mode. X * sdiff.c (ck_fdopen): Function removed. X (edit): Use system if !HAVE_FORK. X (execdiff): Now assumes caller has pushed all args, plus trailing 0. X All callers changed. X (private_tempnam): Try TMP if TMPDIR isn't defined. X Fit temporary filenames into 8.3 limit. X * system.h (STAT_BLOCKSIZE): Don't define if already defined. X (min, max): Undef if already defined. X (filename_cmp, filename_lastdirchar, HAVE_FORK, HAVE_SETMODE, X initialize_main, O_BINARY, same_file): New macros. X XFri Jun 17 11:23:53 1994 David J. MacKenzie (djm@geech.gnu.ai.mit.edu) X X * Makefile.in (info, dvi, diff.dvi): New targets. X (clean): Remove TeX output files. X XFri Jun 17 05:37:52 1994 Paul Eggert (eggert@twinsun.com) X X * cmp.c, io.c (word): Change from typedef to #define, to avoid X collision with Unicos 8.0 , which also typedefs `word'. X XThu Apr 15 00:53:01 1994 Paul Eggert (eggert@twinsun.com) X X * diff3.c (scan_diff_line), util.c (print_number_range): Don't X rely on promotion to make the old-style parameter type agree X with the prototype parameter type; this doesn't work on X Apollos running bsd4.3. X XMon Jan 3 02:05:51 1994 Paul Eggert (eggert@twinsun.com) X X * Makefile.in (LDFLAGS): Remove -g. Change all link commands X to use both $(CFLAGS) and $(LDFLAGS). X XMon Dec 13 12:23:27 1993 Paul Eggert (eggert@twinsun.com) X X * system.h: Don't assume dirent.h exists just because X _POSIX_VERSION is defined. X XFri Dec 3 18:39:39 1993 Paul Eggert (eggert@twinsun.com) X X * diff.c (main): allow -pu. X XTue Nov 23 03:51:08 1993 Paul Eggert (eggert@twinsun.com) X X * Makefile.in (distclean): Remove config.h. X XWed Nov 10 00:28:27 1993 Paul Eggert (eggert@twinsun.com) X X * Version 2.6 released. X X * analyze.c (too_expensive): New variable, for heuristic to X limit the worst-case cost to O(N**1.5 log N) at the price of X producing suboptimal output for large inputs with many differences. X (diff_2_files): Initialize it. X (struct partition): New type. X (SNAKE_LIMIT): New macro; merely documents already-used number 20. X (diag): New `minimal' arg; all callers changed. Put results into X struct partition. Apply `too_expensive' heuristic. Tune. X (compareseq): New `minimal' arg; all callers changed. Tune. X (shift_boundaries): Improve heuristic to also coalesce adjacent runs X of changes more often. X X * diff.c (long_options, main, usage): Add `--help'. X (main): Send version number to stdout, not stderr. X (usage): Send usage to stdout, not stderr. X (compare_files): Initialize `inf' properly. X X * io.c (word): Change to `int'; it makes a big difference on x86. X (sip, slurp): Put off allocating room to hold the whole file until we X have to read the whole file. This wins if the file turns out X to be binary. X X * util.c (xmalloc, xrealloc): "virtual memory" -> "memory" X (primes): Omit large primes if INT_MAX is small. X X * sdiff.c (usage): Send usage to stdout, not stderr. X (long_options, main, usage): Add `--help'. X (main): Send version number to stdout, not stderr. Exit afterwards. X X * diff3.c (usage): Send usage to stdout, not stderr. X (long_options, main, usage): Add `--help'. X (read_diff): Detect integer overflow in buffer size calculations. X X * cmp.c (word): New type. All uses of `long' for X word-at-a-time comparisons changed to `word'. X (long_options, main, usage): Add `--help'. X (usage): Send usage to stdout, not stderr. X (main): Add `-v'. Send version number to stdout, not stderr. X X * configure.in (AC_HAVE_HEADERS): Add unistd.h; remove AC_UNISTD_H. X XMon Sep 27 07:20:24 1993 Paul Eggert (eggert@twinsun.com) X X * diff.c (add_exclude_file): Cast memchr to (char *) X to suppress bogus warnings on some nonstandard hosts. X X * Makefile.in (cmp): Add version.o. X X * analyze.c (diff_2_files): Work around memcmp bug with size=0. X X * cmp.c (main, usage, version_string): Add --version option. X X * system.h (malloc, realloc): Declare only if !HAVE_STDLIB_H. X (memchr): Declare only if !HAVE_MEMCHR. These changes are X needed to keep some nonstandard hosts happy. X X * util.c (memchr): Make first arg char const * X to match standard. X (xmalloc, xrealloc): Cast malloc, realloc X to (VOID *) to suppress bogus warnings on some nonstandard hosts. X X * diff3.c (xmalloc, xrealloc): Cast malloc, realloc X to (VOID *) to suppress bogus warnings on some nonstandard hosts. X X * sdiff.c (xmalloc, xrealloc): Cast malloc, realloc X to (VOID *) to suppress bogus warnings on some nonstandard hosts. X (lf_copy, lf_skip, lf_snarf): Cast memchr to (char *) X to suppress bogus warnings on some nonstandard hosts. X (memchr): Make first arg char const * X to match standard. X XMon Sep 27 00:23:37 1993 Paul Eggert (eggert@twinsun.com) X X * Version 2.5 released. X X * analyze.c (diff_2_files): Work around memcmp bug with size=0. X X * cmp.c (main, usage, version_string): Add --version option. X * Makefile.in (cmp): Add version.o. X X * diff.c (add_exclude_file): Cast memchr to (char *) X to suppress bogus warnings on some nonstandard hosts. X * sdiff.c (lf_copy, lf_skip, lf_snarf): Likewise. X X * diff3.c, sdiff.c, util.c (xmalloc, xrealloc): Cast malloc, realloc X to (VOID *) to suppress bogus warnings on some nonstandard hosts. X X * sdiff.c, util.c (memchr): Make first arg char const * X to match standard. X X * system.h (malloc, realloc): Declare only if !HAVE_STDLIB_H. X (memchr): Declare only if !HAVE_MEMCHR. These changes are X needed to keep some nonstandard hosts happy. X X * xmalloc.c: Include always; some nonstandard hosts X need it for size_t even if STDC_HEADERS. X XSat Sep 18 01:33:07 1993 Paul Eggert (eggert@twinsun.com) X X * configure.in (AC_STAT_MACROS_BROKEN): Add. X * system.h (S_IS{BLK,CHR,DIR,FIFO,REG,SOCK}): Fix defns if X STAT_MACROS_BROKEN. X X * Makefile.in (diff3, sdiff, cmp): Do not link $(ALLOCA). X X * analyze.c (discard_confusing_lines): Make defn static, like decl. X * sdiff.c (xmalloc): Likewise. X X * ifdef.c (format_group): Ensure isdigit argument isn't < 0. X X * side.c (print_half_line): Use isprint, since some hosts lack isgraph. X * util.c (output_1_line): Likewise. Ensure its argument isn't < 0. X (xmalloc, xrealloc): Remove needless casts. X X * system.h (volatile, const): X Define these before including any system headers, X so that they're used consistently in all system includes. X (getenv, malloc, realloc): Declare even if HAVE_STDLIB_H, since some X s don't declare them. X (memchr): Likewise for . X X * cmp.c, diff3.c, diff.h, sdiff.c: Include "system.h" first. X * diff.c: Remove redundant "system.h" inclusion. X X * diff3.c (xmalloc): Now static. X (xmalloc, realloc): Remove needless casts. X (READNUM): Ensure isdigit argument isn't negative. X XWed Sep 14 07:14:15 1993 Paul Eggert (eggert@twinsun.com) X X * Version 2.4 released. X X * ifdef.c (scan_char_literal): New function, for new %c'x' and X %c'\ooo' format specs. X (format_group, print_ifdef_lines): Use it. Remove %0 format spec. X X * cmp.c (cmp): Don't try to read past end of file; this doesn't X work on ttys. X X * system.h, version.c: #include , not "config.h", to allow X configuring in a separate directory when the source directory has X already been configured. X * Makefile.in (COMPILE): New defn, with proper -I options so that X `#include ' works. X (.c.o, diff3.o, sdiff.o): Use it. X XMon Sep 13 06:45:43 1993 Paul Eggert (eggert@twinsun.com) X X * diff.c (main, longopts): Add --line-format=FORMAT option. X (specify_format): Args no longer const pointers. All callers changed. X X * ifdef.c: Add support for %?c, %(A=B?T:E), PRINTF_SPECn formats. X (struct group): New struct. X (print_ifdef_lines): Use it to simplify argument passing. X Remove the convention that last arg -1 signifies that the lines X from file 2 are the same as the lines from file 1; this X convention no longer works, now that line numbers might be X printed out, since the line numbers may differ. X Add first FILE * argument to output to. All callers changed. X Use a faster test for the single-fwrite optimization. X (format_group, scan_printf_spec, groups_letter_value): New functions. X X * diff.h (group_format, line_format): No longer const pointers. X (format_ifdef): 1st arg is no longer const pointer. X X * configure.in: Configure HAVE_LIMITS_H, HAVE_STDLIB_H. X * system.h , , : X Include only if HAVE_LIMITS_H etc. X X * system.h (memcmp, memcpy, strchr, strrchr, struct dirent): Prefer X these standard names to the traditional names (bcmp, bcpy, index, X rindex, struct direct). All callers changed. X X * system.h (PARAMS, VOID): X Define earlier so that malloc decl can use VOID. X (STAT_BLOCKSIZE): Simplify ersatz defn; just use 8K. X XFri Sep 3 00:21:02 1993 Paul Eggert (eggert@twinsun.com) X X * diff.c (compare_files): Two files with the same name must be X the same file; avoid a needless `stat' in that case. X XFri Aug 27 06:59:03 1993 Paul Eggert (eggert@twinsun.com) X X * Pervasive changes for portability to 64-bit hosts: X Add prototypes to function declarations. X Use size_t, not int, when needed. X X * Other pervasive changes: X Use `const' more often. X Use STD{IN,OUT,ERR}_FILENO instead of [012]. X Use 0, not NULL, for portability to broken hosts. X X * Makefile.in: (srcs, objs, distfiles, cmp): New files cmpbuf.[ch]. X (distfiles): New files config.h.in, mkinstalldirs. X (.c.o): Add -DHAVE_CONFIG_H. X X * analyze.c: (diag): Pacify `gcc -Wall' with a useless assignment. X (diff_2_files): Use l.c.m., not max, of files' buffer sizes. X X * cmp.c: Make globals static when possible. X X (file): Now a 2-element array; replaces `file1' and `file2'. X (file_desc, buffer): Likewise, for file[12]_desc and buf[12]. X (main): Likewise, for stat_buf[12]. Index these variables with `i'. X X (ignore_initial): New var. X (long_options): Now const. Add `--ignore-initial'. X (usage): Sort options and add `--ignore-initial'. X (main, cmp): Add `--ignore-initial' support. X X (main): `cmp - -' now succeeds. X When comparing standard input to a file, and using a shortcut (e.g. X looking at file sizes or inode numbers), take the lseek offset into X account before deciding whether the files are identical. X Avoid mentioning `dev_t', `ino_t' for portability to nonstandard hosts. X Use l.c.m. of files' buffer sizes, not 8 * 1024. X ferror (stdout) does not imply errno has a useful value. X If 2nd file is "-", treat it first, in case stdin is closed. X X (cmp): Always compute `char_number', `smaller' for speed and simplicity. X Say `cmp: EOF on input', not `/usr/gnu/bin/cmp: EOF on input', X as per Posix.2. X X (block_compare_and_count): Increment line_number argument. X Remove end_char argument; it's always '\n'. All callers changed. X Do not assume sizeof(long) == 4; this isn't true on some 64-bit hosts. X (block_compare): Minimize differences with block_compare_and_count. X X (block_read): Coalesce `bp += nread's. X X (printc): Remove `FILE *' arg; output to stdout. All callers changed. X X * configure.in: Configure HAVE_SIGACTION, RETSIGTYPE, HAVE_VPRINTF. X Configure into config.h. X X * context.c (print_context_label): X Standard input's st_mtime is no longer a special case X here, since `compare_files' now sets it to the current time. X X * diff.c (usage): Sort options. X (filetype): New function. X (compare_files): Set stdin's st_mtime to be the current time. X Leave its name "-" instead of changing it to "Standard Input"; X to test whether a file is stdin, we must compare its name to "-" instead X of its desc to 0, since if it's closed other file descs may be 0. X When comparing standard input to a file, and using a shortcut (e.g. X looking at file sizes or inode numbers), take the lseek offset into X account before deciding whether the files are identical. X Pretend that nonexistent files have the same filetype as existing files. X Rename `errorcount' to `failed', since it's boolean. X In directory comparisons, if a file is neither a regular file nor a X directory, just print its type and the other file's type. X X * diff.h (Is_space, textchar): Remove. X (struct msg, msg_chain, msg_chain_end): Move to util.c. X (VOID): Move to system.h. X (line_cmp, version_string, change_letter, print_number_range, X find_change): New decls. X X * diff.texi: X whitespace -> white space. It now stands for whatever isspace yields. X Add --ignore-initial. X X * diff3.c (VOID): Move to system.h. X (version_string): Now char[]. X (usage): Sort options. X (process_diff): Pacify `gcc -Wall' with a useless assignment. X (read_diff): pid is of type pid_t, not int. Use waitpid if available. X (output_diff3): Simplify test for `\ No newline at end of file' message. X X * dir.c (struct dirdata): Rename `files' to `names' to avoid confusion X with external struct file_data `files'. X X * io.c (line_cmp): Move declaration to diff.h. X (textchar): Remove. X (find_and_hash_each_line): Use locale's definition of white space X instead of using one hardwired defn for -b and another for -w. X X * normal.c (change_letter, print_number_range, find_change): X Move decls to diff.h. X (print_normal_hunk): Now static. X X * sdiff.c (SEEK_SET): Move to system.h. X (version_string): Now char[], not char*. X (private_tempnam): Remove hardcoded limit on temporary file names. X (exiterr, perror_fatal, main): When exiting because of a signal, X exit with that signal's status. X (lf_refill, main, skip_white, edit, interact): Check for signal. X (ignore_SIGINT): Renamed from `ignore_signals'. X (NUM_SIGS, initial_handler): New macros. X (initial_action, signal_received, sigs_trapped): New vars. X (catchsig, trapsigs): Use sigaction if possible, since this closes the X windows of vulnerability that `signal' has. Use RETSIGTYPE not void. X When a signal comes in, just set a global variable; this is safer. X (checksigs, untrapsig): New functions. X (edit): Pacify `gcc -Wall' with a useless assignment. X Respond to each empty line with help, not to every other empty line. X (private_tempnam): Remove hardcoded limit on temporary file name length. X Don't assume sizeof (pid_t) <= sizeof (int). X X * system.h: (S_IXOTH, S_IXGRP, S_IXUSR, X SEEK_SET, SEEK_CUR, X STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO): X New macros, if system doesn't define them. X (volatile): Don't define if already defined. X (PARAMS): New macro. X (VOID): Move here from diff.h. X X * util.c (struct msg, msg_chain, msg_chain_end): Moved here from diff.h. X (message5): New function. X (pr_pid): New var. X (begin_output): Allocate `name' more precisely. X Put child pid into pr_pid, so that we can wait for it later. X Don't check execl's return value, since any return must be an error. X (finish_output): Detect and report output errors. X Use waitpid if available. Check pr exit status. X (line_cmp): Use locale's definition of white space X instead of using one hardwired defn for -b and another for -w. X (analyze_cmp): Avoid double negation with `! nontrivial'. X Pacify `gcc -Wall' be rewriting for-loop into do-while-loop. X (dir_file_pathname): New function. X X * version.c (version_string): Now char[], not char*. X XThu Jul 29 20:44:30 1993 David J. MacKenzie (djm@wookumz.gnu.ai.mit.edu) X X * Makefile.in (config.status): Run config.status --recheck, not X configure, to get the right args passed. X XThu Jul 22 10:46:30 1993 Paul Eggert (eggert@twinsun.com) X X * Makefile.in (dist): Replace `if [ ! TEST ]; then ACTION; fi' X with `[ TEST ] || ACTION || exit' so that the containing for-loop exits X with proper status for `make'. X XThu Jul 8 19:47:22 1993 David J. MacKenzie (djm@goldman.gnu.ai.mit.edu) X X * Makefile.in (installdirs): New target. X (install): Use it. X (Makefile, config.status, configure): New targets. X XSat Jun 5 23:10:40 1993 Paul Eggert (eggert@twinsun.com) X X * Makefile.in (dist): Switch from .z to .gz. X XWed May 26 17:16:02 1993 Paul Eggert (eggert@twinsun.com) X X * diff.c (main): Cast args to compare_files, for traditional C. X * side.c (print_sdiff_common_lines_print_sdiff_hunk): Likewise. X * analyze.c, diff3.c, sdiff.c, util.c: Don't assume NULL is defined X properly. X XTue May 25 14:54:05 1993 Paul Eggert (eggert@twinsun.com) X X * analyze.c (diff_2_files): With -q, do not report that files differ X if all their differences are ignored. X (briefly_report): New function. X * diff.h (ignore_some_changes): New variable. X * diff.c (compare_files): Don't use the file size shortcut if X ignore_some_changes is nonzero, since the file size may differ X merely due to ignored changes. X (main): Set ignore_some_changes if we might ignore some changes. X Remove unsystematic assignment of 0 to static vars. X * io.c (read_files): New argument PRETEND_BINARY says whether to X pretend the files are binary. X X * diff3.c (tab_align_flag): New variable, for new -T option. X (main, usage, output_diff3): Add support for -T. X XSun May 23 15:25:29 1993 Richard Stallman (rms@mole.gnu.ai.mit.edu) X X * dir.c (dir_sort): Always init `data' to avoid GCC warning. X XSat May 22 15:35:02 1993 Paul Eggert (eggert@twinsun.com) X X * Makefile.in (dist): Change name of package from diff to diffutils. X Don't bother to build .Z dist; .z suffices. X XFri May 21 16:35:22 1993 Paul Eggert (eggert@twinsun.com) X X * diff.c: Include "system.h" to get memchr declaration. X * system.h (memchr): Declare if !HAVE_MEMCHR, not if X !HAVE_MEMCHR && !STDC_HEADERS. X XWed May 19 17:43:55 1993 Paul Eggert (eggert@twinsun.com) X X * Version 2.3 released. X XFri Apr 23 17:18:44 1993 Paul Eggert (eggert@twinsun.com) X X * io.c (find_identical_ends): Do not discard the last HORIZON_LINES X lines of the prefix, or the first HORIZON_LINES lines of the suffix. X * diff.c (main, longopts, usage): Add --horizon-lines option. X * diff3.c (main, process_diff, read_diff): Invoke second diff X with --horizon-lines determined by the first diff. X * diff.h, diff3.c (horizon_lines): New variable. X XMon Mar 22 16:16:00 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) X X * system.h [HAVE_STRING_H || STDC_HEADERS] (bcopy, bcmp, bzero): X Don't define if already defined. X XFri Mar 5 00:20:16 1993 Richard Stallman (rms@mole.gnu.ai.mit.edu) X X * diff.c (main): Use NULL in arg to compare_files. X XThu Feb 25 15:26:01 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) X X * system.h: Declare memchr #if !HAVE_MEMCHR && !STDC_HEADERS, X not #if !HAVE_MEMCHR || !STDC_HEADERS. X XMon Feb 22 15:04:46 1993 Richard Stallman (rms@geech.gnu.ai.mit.edu) X X * io.c (find_identical_ends): Move complicated arg outside GUESS_LINES. X XMon Feb 22 12:56:12 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) X X * Makefile.in (.c.o): Add -I$(srcdir); put $(CFLAGS) last before $<. X XSat Feb 20 19:18:56 1993 Richard Stallman (rms@mole.gnu.ai.mit.edu) X X * io.c (binary_file_p): Return zero if file size is zero. X XFri Feb 19 17:31:32 1993 Roland McGrath (roland@geech.gnu.ai.mit.edu) X X * Version 2.2 released. X X * system.h [HAVE_STRING_H || STDC_HEADERS] (index, rindex): Don't X define if already defined. X XWed Feb 17 17:08:00 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) X X * Makefile.in (srcs): Remove limits.h. X XThu Feb 11 03:36:00 1993 Richard Stallman (rms@mole.gnu.ai.mit.edu) X X * diff3.c (xmalloc): No longer static. X X * sdiff.c (edit): Allocate buf dynamically. X X * dir.c (dir_sort): Handle VOID_CLOSEDIR. X XWed Feb 10 00:15:54 1993 Richard Stallman (rms@mole.gnu.ai.mit.edu) X X * limits.h: File deleted (should never have been there). X XTue Feb 9 03:53:22 1993 Richard Stallman (rms@mole.gnu.ai.mit.edu) X X * Makefile.in (.c.o, diff3.o, sdiff.o): Put $(CFLAGS) last. X XWed Feb 3 15:42:10 1993 David J. MacKenzie (djm@goldman.gnu.ai.mit.edu) X X * system.h: Don't #define const; let configure do it. X XMon Feb 1 02:13:23 1993 Paul Eggert (eggert@hal.gnu.ai.mit.edu) X X * Version 2.1 released. X X * Makefile.in (dist): Survive ln failures. Create .tar.z X (gzipped tar) file as well as .tar.Z (compressed tar) file. X XFri Jan 8 22:31:41 1993 Paul Eggert (eggert@twinsun.com) X X * side.c (print_half_line): When the input position falls X outside the column, do not output a tab even if the output X position still falls within the column. X XMon Dec 21 13:54:36 1992 David J. MacKenzie (djm@kropotkin.gnu.ai.mit.edu) X X * Makefile.in (.c.o): Add -I. X XFri Dec 18 14:08:20 1992 Paul Eggert (eggert@twinsun.com) X X * configure.in: Add HAVE_FCNTL_H, since system.h uses it. X XTue Nov 24 10:06:48 1992 David J. MacKenzie (djm@goldman.gnu.ai.mit.edu) X X * Makefile.in: Note change from USG to HAVE_STRING_H. X XMon Nov 23 18:44:00 1992 Paul Eggert (eggert@twinsun.com) X X * io.c (find_and_hash_each_line): When running out of lines, X double the number of allocated lines, instead of just doubling X that number minus the prefix lines. This is more likely to X avoid the need for further memory allocation. X XWed Nov 18 20:40:28 1992 Paul Eggert (eggert@twinsun.com) X X * dir.c (dir_sort): Plug memory leak: space holding directory X contents was not being reclaimed. Get directory size from X struct file_data for initial guess at memory needed. X Detect errors when reading and closing directory. X (diff_dirs): Pass struct file_data to dir_sort. Finish plugging leak. X * diff.c (compare_files): Pass struct file_data to diff_dirs. X X * io.c (find_and_hash_each_line): Don't assume alloc_lines is X nonzero when allocating more lines. X XThu Nov 12 16:02:18 1992 Paul Eggert (eggert@twinsun.com) X X * diff.c (main): Add `-U lines' as an alias for `--unified=lines'. X X * diff3.c (usage): Add third --label option in example. X X * util.c (analyze_hunk): Fix test for ignoring blank lines. X X * configure.in, system.h: Avoid USG; use HAVE_TIME_H etc. instead. X XMon Nov 9 05:13:25 1992 Paul Eggert (eggert@twinsun.com) X X * diff3.c (main, usage): Add -A or --show-all. X -m now defaults to -A, not -E. Allow up to three -L options. X (output_diff3_edscript, output_diff3_merge): X Remove spurious differences between these two functions. X Output ||||||| for -A. Distinguish between conflicts and overlaps. X (dotlines, undotlines): New functions that output `Ns', not `N,Ns'. X (output_diff3_edscript, output_diff3_merge): Use them. X X * io.c (find_identical_ends): shift_boundaries needs an extra X identical line at the end, not at the beginning. X X * sdiff.c (edit): execvp wants char **, not const char **. X XMon Oct 19 04:39:32 1992 Paul Eggert (eggert@twinsun.com) X X * context.c (print_context_script, find_function): Context X line numbers start with - file->prefix_lines, not 0. X X * io.c (binary_file_p): Undo last change; it was a library bug. X XSun Oct 18 00:17:29 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) X X * io.c (binary_file_p): Consider empty file as non-binary. X XMon Oct 5 05:18:46 1992 Paul Eggert (eggert@twinsun.com) X X * diff3.c (main, make_3way_diff, using_to_diff3_block): Don't X report bogus differences (for one of -mexEX3) just because the X file0-file1 diffs don't line up with the file0-file2 diffs. X (This is entirely possible since we don't use diff's -n X option.) Always compare file1 to file2, so that diff3 sees X those changes directly. Typically, file2 is now the common X file, not file0. X (output_diff3_merge): The input file is file 0, not the common file. X X (FC, FO): New macros; they replace FILE1, FILE0 for two-way diffs, X to distinguish them from three-way diffs. X X * diff3.c (using_to_diff3_block): Fold repeated code into loops. X X * diff3.c (make_3way_diff, process_diff): Have the *_end X variable point to the next field to be changed, not to the last X object allocated; this saves an if-then-else. X X * diff3.c (process_diff): Use D_NUMLINES instead of its definiens. X X * diff3.c: Make fns and vars static unless they must be external. X XWed Sep 30 09:21:59 1992 Paul Eggert (eggert@twinsun.com) X X * analyze.c (diff_2_files): OUTPUT_IFDEF is now robust. X * diff.h (ROBUST_OUTPUT_STYLE): Likewise. X (default_line_format): Remove. All refs removed. X X * ifdef.c (print_ifdef_lines): Add %L. Optimize %l\n even if user X specified it, as opposed to its being the default. X XTue Sep 29 19:01:28 1992 Paul Eggert (eggert@twinsun.com) X X * diff.c (longopts, main): --{old,new,unchanged,changed}--group-format X are new options, so that -D is no longer overloaded. Set X no_diff_means_no_output if --unchanged-{line,group}-format allows it. X * diff.h (enum line_class): New type. X (group_format, line_format): Use it to regularize option flags. X All refs changed. X X * ifdef.c (format_ifdef, print_ifdef_lines): %n is no longer a format. X XMon Sep 28 04:51:42 1992 Paul Eggert (eggert@twinsun.com) X X * diff.c (main, usage): Replace --line-prefix with the more general X --{old,new,unchanged}-line-format options. X * ifdef.c (format_ifdef, print_ifdef_lines): Likewise. X * diff.h (line_format): Renamed from line_prefix. All refs changed. X * diff.h, ifdef.c (default_line_format): New variable. X * util.c (output_1_line): New function. X (print_1_line): Use it. X X * ifdef.c: (format_ifdef, print_ifdef_lines): Add %0 format. X XSun Sep 27 05:38:13 1992 Paul Eggert (eggert@twinsun.com) X X * diff.c (main): Add -E or --line-prefix option. Add -D'=xxx' X for common lines. Change default -D< format from copy of -D> X format to to -D<%<; similarly for default -D> format. X * diff.h (common_format, line_prefix): New variables. X * ifdef.c (format_ifdef): New function. X (print_ifdef_script, print_ifdef_hunk, print_ifdef_lines): X Use it for -D'=xxx', -E. X X * context.c (find_hunk): Glue together two non-ignorable changes that X are exactly CONTEXT * 2 lines apart. This shortens output, removes X a behavioral discontinuity at CONTEXT = 0, and is more compatible X with traditional diff. X X * io.c (find_identical_ends): Slurp stdin at most once. X X * util.c (print_line_line): line_flag is const char *. X XThu Sep 24 15:18:07 1992 Paul Eggert (eggert@twinsun.com) X X * ifdef.c (print_ifdef_lines): New function, which fwrites a sequence X of lines all at once for speed. X (print_ifdef_script, print_ifdef_hunk): Use it. X XThu Sep 24 05:54:14 1992 Paul Eggert (eggert@twinsun.com) X X * diff.c (main): Support new -D options for if-then-else formats. X (specify_format): New function. X * diff.h (ifndef_format, ifdef_format, ifnelse_format): New variables. X * ifdef.c (print_ifdef_hunk): Use the new variables instead of X a hardwired format. X X * side.c (print_1sdiff_line): Represent incomplete lines on output. X (print_sdiff_script): Likewise. Don't print 'q' at end, X since that doesn't work with incomplete lines. X * sdiff.c (interact): Don't assume diff output ends with 'q' line. X * diff.h (ROBUST_OUTPUT_STYLE): OUTPUT_SDIFF is now robust. X X * sdiff.c (lf_copy, lf_snarf): Use memchr instead of index, X to avoid dumping core when files contain null characters. X (memchr): New function (if memchr is missing). X X * io.c (sip): New arg SKIP_TEST to skip test for binary file. X (read_files): Don't bother testing second file if first is binary. X XThu Sep 17 21:17:49 1992 David J. MacKenzie (djm@nutrimat.gnu.ai.mit.edu) X X * system.h [!USG && !_POSIX_VERSION]: Protect from conflicting X prototype for wait in sys/wait.h. X XWed Sep 16 12:32:18 1992 David J. MacKenzie (djm@nutrimat.gnu.ai.mit.edu) X X * Makefile.in: Include binprefix in -DDIFF_PROGRAM. X XTue Sep 15 14:27:25 1992 David J. MacKenzie (djm@nutrimat.gnu.ai.mit.edu) X X * Version 2.0. X XSat Sep 12 01:31:19 1992 David J. MacKenzie (djm@nutrimat.gnu.ai.mit.edu) X X * util.c, diff.h, system.h [!HAVE_MEMCHR]: Don't use void * X and const when declaring memchr replacement. Declare memchr X if !STDC_HEADERS && !USG. X XThu Sep 10 15:17:32 1992 David J. MacKenzie (djm@nutrimat.gnu.ai.mit.edu) X X * Makefile.in (uninstall): New target. X X * diff.c (excluded_filename): Use fnmatch, not wildmat. X (usage): Document -x, -X, --exclude, --exclude-from. X Makefile.in: Use fnmatch.c, not wildmat.c. X XSun Sep 6 23:46:25 1992 Paul Eggert (eggert@twinsun.com) X X * configure.in: Add HAVE_MEMCHR. X * diff.h, util.c: Use it instead of MEMCHR_MISSING. X XSun Sep 6 07:25:49 1992 Paul Eggert (eggert@twinsun.com) X X * diff.h: (struct line_def): Replace this 3-word struct with char *. X This uses less memory, particularly for large files with short lines. X (struct file_data): New member linbuf_base counts number of lines X in common prefix that are not recorded in linbuf; X this uses less memory if files are identical or differ only at end. X New member buffered_lines counts possibly differing lines. X New member valid_lines counts valid data. X New member alloc_lines - linbuf_base replaces old linbufsize. X linbuf[0] now always points at first differing line. X Remove unused members ltran, suffix_lines. X Add const where appropriate. X (Is_space): New macro, for consistent definition of `white space'. X (excluded_filename, memchr, sip, slurp): New declarations. X * ed.c (print_ed_hunk): Adjust to diff.h's struct changes. X * context.c (pr_context_hunk): Likewise. X * ifdef.c (print_ifdef_script): Likewise. X * side.c (print_sdiff_script, print_half_line): Likewise. X * util.c (analyze_hunk, line_cmp, print_1_line): Likewise. X X * analyze.c (shift_boundaries): Remove unneeded variable `end' and X unnecessary comparisons of `preceding' and `other_preceding' against 0. X (diff_2_files): When comparing files byte-by-byte for equality, X don't slurp them all in at once; just compare them a buffer at a time. X This can win big if they differ early on. X Move some code to compare_files to enable this change. X Use only one buffer for stdin with `diff - -'. X (discard_confusing_lines, diff_2_files): Coalesce malloc/free calls. X (build_script): Remove obsolete OUTPUT_RCS code. X X * diff.c (add_exclude, add_exclude_file, excluded_filename): New fns. X (main): Use them for the new --exclude and --exclude-from options. X (compare_files): Don't open a file unless it must be read. X Treat `diff file file' and `diff file dir' similarly. X Move some code here from diff_2_files to enable this. X Simplify file vs dir warning. X X * dir.c (dir_sort): Support new --exclude* options. X X * io.c (struct equivclass): Put hash code and line length here instead X of struct line_def, so that they can be shared. X (find_and_hash_each_line): Compute equivalence class as we go, X instead of doing it in a separate pass; this thrashes memory less. X Make buckets realloc-able, since we can't preallocate them. X Record one more line start than there are lines, so that we can compute X any line's length by subtracting its start from the next line's, X instead of storing the length explicitly. This saves memory. X Move prefix-handling code to find_identical_ends; X this wins with large prefixes. X Use Is_space, not is_space, for consistent treatment of white space. X (prepare_text_end): New function. X (find_identical_ends): Move slurping here, so it's only done when X needed. Work even if the buffers are the same (because of `diff - -'). X Compare prefixes a word at a time for speed. X (find_equiv_class): Delete; now done by find_and_hash_each_line. X (read_files): Don't slurp unless needed. X find_equiv_class's work is now folded into find_and_hash_each_line. X Don't copy stdin buffer if `diff - -'. X Check for running out of primes. X (sip, slurp): Split first part of `slurp' into another function `sip'. X `sip' sets things up and perhaps reads the first ST_BLKSIZE buffer to X see whether the file is binary; `slurp' now just finishes the job. X This lets diff_2_files compare binary files lazily. X Allocate a one-word sentinel to allow word-at-a-time prefix comparison. X Count prefix lines only if needed, only count the first file's prefix. X Don't bother to count suffix lines; it's never needed. X Set up linbuf[0] to point at first differing line. X (binary_file_p): Change test for binary files: X if it has a null byte in its first buffer, it's binary. X (primes): Add more primes. X X * util.c (line_cmp): Use bcmp for speed. X Use Is_space, not is_space, for consistent treatment of white space. X (translate_line_number): Internal line numbers now count from 0 X starting after the prefix. X (memchr): New function (if memchr is missing). X X * Makefile.in: Document HAVE_ST_BLKSIZE. Link with wildmat.o. X * system.h (STAT_BLOCKSIZE): New macro based on HAVE_ST_BLKSIZE. X * configure.in: Add AC_ST_BLKSIZE. X * wildmat.c: New file. X XFri Sep 4 01:28:51 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) X X * sdiff.c (xmalloc): Renamed from ck_malloc. Callers changed. X XThu Sep 3 15:28:59 1992 David J. MacKenzie (djm@nutrimat.gnu.ai.mit.edu) X X * diff.h: Don't declare free, index, rindex. X XTue Aug 11 22:18:06 1992 John Gilmore (gnu at cygnus.com) X X * io.c (binary_file_p): Use heuristic to avoid declaring info X files as binary files. Allow about 1.5% non-printing X characters (in info's case, ^_). X XTue Jul 7 01:09:26 1992 David J. MacKenzie (djm@nutrimat.gnu.ai.mit.edu) X X * diff.h: Replace function_regexp and ignore_regexp with lists X of compiled regexps. X * analyze.c, context.c, util.c: Test whether the lists, not X the old variables, are empty. X * util.c (analyze_hunk), context.c (find_function): Compare X lines with the lists of regexps. X * diff.c (add_regexp): New function. X (main): Use it. X X * diff3: Add -v --version option. X * Makefile.in: Link with version.o. X X * system.h: New file. X * diff.h, cmp.c, diff3.c, sdiff.c: Use it. X X * diff.h, diff3.c: Include string.h or strings.h, as appropriate. X Declare malloc and realloc. X X * diff3.c (perror_with_exit): Include program name in message. X X * diff3.c: Lowercase error messages for GNU standards. X X * sdiff.c [USG || STDC_HEADERS]: Define bcopy in terms of memcpy. X X * sdiff.c: Use the version number from version.c. X * Makefile.in: Link with version.o. X X * cmp.c error.c xmalloc.c: New files from textutils. X * Makefile.in: Add rules for them. X X * diff.c (longopts): --unidirectional-new-file is like -P, not -N. X Rename --file-label to --label (leave old name, but undocumented). X X * sdiff.c, diff.c (usage): Condense messages and fix some errors. X X * diff3.c (main, usage): Add long-named options. X XFri Jul 3 14:31:18 1992 David J. MacKenzie (djm@nutrimat.gnu.ai.mit.edu) X X * diff.h, diff3.c, sdiff.c: Change FOO_MISSING macros to HAVE_FOO. X XThu Jun 25 16:59:47 1992 David J. MacKenzie (djm@apple-gunkies.gnu.ai.mit.edu) X X * diff.c: --reversed-ed -> --forward-ed. X XWed Feb 26 12:17:32 1992 Paul Eggert (eggert@yata.uucp) X X * analyze.c, diff.c, diff.h, io.c: For -y, compare even if same file. X XFri Feb 14 22:46:38 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) X X * io.c, diff3.c, analyze.c: Add extra parentheses. X XSun Feb 9 00:22:42 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) X X * diff.h (unidirectional_new_file_flag): New variable. X * diff.c (main): Set that for -P. X (compare_files): Support -P, somewhat like -N. X (longopts): Support long name for -P. X XSat Jan 4 20:10:34 1992 Paul Eggert (eggert at yata.uucp) X X * Makefile.in: Distribute diff.info-* too. X X * README, sdiff.c: version number now matches version.c. X X * configure: Fix and document vfork test. X X * ifdef.c: Don't dump core if `diff -Dx f f'. X XMon Dec 23 23:36:08 1991 David J. MacKenzie (djm at wookumz.gnu.ai.mit.edu) X X * diff.h, diff3.c, sdiff.c: Change POSIX ifdefs to X HAVE_UNISTD_H and _POSIX_VERSION. X XWed Dec 18 17:00:31 1991 David J. MacKenzie (djm at wookumz.gnu.ai.mit.edu) X X * Makefile.in (srcs): Add sdiff.c. X (tapefiles): Add diff.texi and diff.info. X X * diff.h, diff3.c, sdiff.c: Use HAVE_VFORK_H instead of X VFORK_HEADER and VFORK_WORKS. X XTue Dec 17 00:02:59 1991 Paul Eggert (eggert at yata.uucp) X X * Makefile.in (all): Add diff.info, sdiff. X X * configure, diff.c, sdiff.c: X Prefix long options with `--', not `+'. X * diff.c: Regularize option names. X X * configure: Fix check for vfork. X * configure, diff.c, diff.h, diff3.c, sdiff.c: X Use Posix definitions when possible. X X * context.c: Align context with tab if -T is given. Tune. X * diff.c, diff.h, side.c: Calculate column widths so that tabs line up. X * io.c: Add distinction between white space and printing chars. X * side.c: Don't expand tabs unless -t is given. X * side.c, util.c: Tab expansion now knows about '\b', '\f', '\r', '\v'. X * util.c: -w skips all white space. Remove lint. Tune. X X * sdiff.c: Support many more diff options, e.g. `-', `sdiff file dir'. X Ignore interrupts while the subsidiary editor is in control. X Clean up temporary file and kill subsidiary diff if interrupted. X Ensure subsidiary diff doesn't ignore SIGPIPE. X Don't get confused while waiting for two subprocesses. X Don't let buffers overflow. Check for I/O errors. X Convert to GNU style. Tune. X X * sdiff.c, util.c: Don't lose errno. X Don't confuse sdiff with messages like `Binary files differ'. X * sdiff.c, side.c: Don't assume that common lines are identical. X Simplify --sdiff-merge-assist format. X XMon Sep 16 16:42:01 1991 Tom Lord (lord at churchy.gnu.ai.mit.edu) X X * Makefile.in, sdiff.c: introduced sdiff front end to diff. X X * Makefile.in, analyze.c, diff.c, diff.h, io.c, side.c: Added X sdiff-style output format to diff. X XMon Aug 26 16:44:55 1991 David J. MacKenzie (djm at pogo.gnu.ai.mit.edu) X X * Makefile.in, configure: Only put $< in Makefile if using VPATH, X because older makes don't understand it. X XFri Aug 2 12:22:30 1991 David J. MacKenzie (djm at apple-gunkies) X X * configure: Create config.status. Remove it and Makefile if X interrupted while creating them. X XThu Aug 1 22:24:31 1991 David J. MacKenzie (djm at apple-gunkies) X X * configure: Check for +srcdir etc. arg and look for X Makefile.in in that directory. Set VPATH if srcdir is not `.'. X * Makefile.in: Get rid of $(archpfx). X XTue Jul 30 21:28:44 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu) X X * Makefile.in (prefix): Renamed from DESTDIR. X XWed Jul 24 23:08:56 1991 David J. MacKenzie (djm at wookumz.gnu.ai.mit.edu) X X * diff.h, diff3.c: Rearrange ifdefs to use POSIX, X STDC_HEADERS, VFORK_MISSING, DIRENT. This way it works on X more systems that aren't pure USG or BSD. X Don't not define const if __GNUC__ is defined -- that would X break with -traditional. X * configure: Check for those features. X XWed Jul 10 01:39:23 1991 David J. MacKenzie (djm at wookumz.gnu.ai.mit.edu) X X * configure, Makefile.in: $(INSTALLPROG) -> $(INSTALL). X XSat Jul 6 16:39:04 1991 David J. MacKenzie (djm at geech.gnu.ai.mit.edu) X X * Replace Makefile with configure and Makefile.in. X Update README with current compilation instructions. X XSat Jul 6 14:03:29 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu) X X * util.c (setup_output): Just save the args for later use. X (begin_output): Do the real work, with the values that were saved. X It's safe to call begin_output more than once. X Print the special headers for context format here. X * analyze.c (diff_2_files): Don't print special headers here. X * context.c (pr_context_hunk, pr_unidiff_hunk): Call begin_output. X * ed.c (print_ed_hunk, print_forward_ed_hunk, print_rcs_hunk): X * normal.c (print_normal_hunk): Likewise. X * ifdef.c (print_ifdef_hunk): Likewise. X * util.c (finish_output): Don't die if begin_output was not called. X XThu Jun 20 23:10:01 1991 David J. MacKenzie (djm at geech.gnu.ai.mit.edu) X X * Makefile: Add TAGS, distclean, and realclean targets. X Set SHELL. X XTue Apr 30 13:54:36 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu) X X * diff.h (TRUE, FALSE): Undefine these before defining. X XThu Mar 14 18:27:27 1991 Richard Stallman (rms@mole.ai.mit.edu) X X * Makefile (objs): Include $(ALLOCA). X XSat Mar 9 22:34:03 1991 Richard Stallman (rms at mole.ai.mit.edu) X X * diff.h: Include regex.h. X XThu Feb 28 18:59:53 1991 Richard Stallman (rms at mole.ai.mit.edu) X X * Makefile (diff3): Link with GNU getopt. X XSat Feb 23 12:49:43 1991 Richard Stallman (rms at mole.ai.mit.edu) X X * io.c (find_equiv_class): Make hash code unsigned before mod. X X * diff.h (files): Add EXTERN. X XSun Jan 13 21:33:01 1991 Richard Stallman (rms at mole.ai.mit.edu) X X * diff.c: +print option renamed +paginate. Remove +all-text. X XMon Jan 7 06:18:01 1991 David J. MacKenzie (djm at geech.ai.mit.edu) X X * Makefile (dist): New target, replacing diff.tar and X diff.tar.Z, to encode version number in distribution directory X and tar file names. X XSun Jan 6 18:42:23 1991 Michael I Bushnell (mib at geech.ai.mit.edu) X X * Version 1.15 released. X X * version.c: Updated from 1.15 alpha to 1.15 X X * context.c (print_context_number_range, X print_unidiff_number_range): Don't print N,M when N=M, print X just N instead. X X * README: Updated for version 1.15. X Makefile: Updated for version 1.15. X X * diff3.c (main): Don't get confused if one of the arguments X is a directory. X X * diff.c (compare_files): Don't get confused if comparing X standard input to a directory; print error instead. X X * analyze.c (diff_2_files), context.c (print_context_header, X print_context_script), diff.c (main), diff.h (enum X output_style): Tread unidiff as an output style in its own X right. This also generates an error when both -u and -c are X given. X X * diff.c (main): Better error messages when regexps are bad. X X * diff.c (compare_files): Don't assume stdin is opened. X X * diff3.c (read_diff): Don't assume things about the order of X descriptor assignment and closes. X X * util.c (setup_output): Don't assume things about the order X of descriptor assignment and closes. X X * diff.c (compare_files): Set a flag so that closes don't X happen more than once. X X * diff.c (main): Don't just flush stdout, do a close. That X way on broken systems we can still get errors. X XMon Dec 24 16:24:17 1990 Richard Stallman (rms at mole.ai.mit.edu) X X * diff.c (usage): Use = for args of long options. X XMon Dec 17 18:19:20 1990 Michael I Bushnell (mib at geech.ai.mit.edu) X X * context.c (print_context_label): Labels were interchanged badly. X X * context.c (pr_unidiff_hunk): Changes to deal with files X ending in incomplete lines. X * util.c (print_1_line): Other half of the changes. X XMon Dec 3 14:23:55 1990 Richard Stallman (rms at mole.ai.mit.edu) X X * diff.c (longopts, usage): unidiff => unified. X XWed Nov 7 17:13:08 1990 Richard Stallman (rms at mole.ai.mit.edu) X X * analyze.c (diff_2_files): No warnings about newlines for -D. X X * diff.c (pr_unidiff_hunk): Remove ref to output_patch_flag. X XTue Oct 23 23:19:18 1990 Richard Stallman (rms at mole.ai.mit.edu) X X * diff.c (compare_files): For -D, compare even args are same file. X * analyze.c (diff_2_files): Likewise. X Also, output even if files have no differences. X X * analyze.c (diff_2_files): Print missing newline messages last. X Return 2 if a newline is missing. X Print them even if files end with identical text. X XMon Oct 22 19:40:09 1990 Richard Stallman (rms at mole.ai.mit.edu) X X * diff.c (usage): Return 2. X XWed Oct 10 20:54:04 1990 Richard Stallman (rms at mole.ai.mit.edu) X X * diff.c (longopts): Add +new-files. X XSun Sep 23 22:49:29 1990 Richard Stallman (rms at mole.ai.mit.edu) X X * context.c (print_context_script): Handle unidiff_flag. X (print_context_header): Likewise. X (print_unidiff_number_range, pr_unidiff_hunk): New functions. X * diff.c (longopts): Add element for +unidiff. X (main): Handle +unidiff and -u. X (usage): Mention them. X XWed Sep 5 16:33:22 1990 Richard Stallman (rms at mole.ai.mit.edu) X X * io.c (find_and_hash_each_line): Deal with missing final newline X after buffering necessary context lines. X XSat Sep 1 16:32:32 1990 Richard Stallman (rms at mole.ai.mit.edu) X X * io.c (find_identical_ends): ROBUST_OUTPUT_FORMAT test was backward. X XThu Aug 23 17:17:20 1990 Richard Stallman (rms at mole.ai.mit.edu) X X * diff3.c (WIFEXITED): Undef it if WEXITSTATUS is not defined. X * context.c (find_function): Don't try to return values. X XWed Aug 22 11:54:39 1990 Richard Stallman (rms at mole.ai.mit.edu) X X * diff.h (O_RDONLY): Define if not defined. X XTue Aug 21 13:49:26 1990 Richard Stallman (rms at mole.ai.mit.edu) X X * Handle -L option. X * context.c (print_context_label): New function. X (print_context_header): Use that. X * diff.c (main): Recognize the option. X (usage): Updated. X * diff.h (file_label): New variable. X * diff3.c (main): Recognize -L instead of -t. X X * diff3.c (main): Support -m without other option. X X * diff3.c (WEXITSTATUS, WIFEXITED): Define whenever not defined. X X * diff3.c (bcopy, index, rindex): Delete definitions; not used. X (D_LINENUM, D_LINELEN): Likewise. X (struct diff_block): lengths includes newlines. X (struct diff3_block): Likewise. X (always_text, merge): New variables. X (read_diff): Return address of end, not size read. Calls changed. X Pass -a to diff if given to diff3. X current_chunk_size now an int. Detect error in `pipe'. X Check for incomplete line of output here. X (scan_diff_line): Don't make scan_ptr + 2 before knowing it is valid. X No need to check validity of diff output here. X Include newline in length of line. X (main): Compute rev_mapping here. Handle -a and -m. X Error message if excess -t operands. Error for incompatible options. X Error if `-' given more than once. X Fix error storing in tag_strings. X (output_diff3): REV_MAPPING is now an arg. Call changed. X Change syntax of "missing newline" message. X Expect length of line to include newline. X (output_diff3_edscript): Return just 0 or 1. X REV_MAPPING is now an arg. Call changed. X (output_diff3_merge): New function. X (process_diff): Better error message for bad diff format. X (fatal, perror_with_exit): Return status 2. X X * analyze.c (diff_2_files): Report missing newline in either X or both files, if not robust output style. X X * util.c (setup_output): Detect error from pipe. X No need to close stdin. X X * util.c (print_1_line): Change format of missing-newline msg. X Change if statements to switch. X X * io.c (slurp): Don't mention differences in final newline if -B. X X * io.c (binary_file_p): Use ISO char set as criterion, not ASCII. X X * io.c (find_identical_ends): Increase value of BEG0 by 1. X Other changes in backwards scan to avoid decrementing pointers X before start of array, and set LINES properly. X X * diff.h (ROBUST_OUTPUT_STYLE): New macro. X * io.c (find_identical_ends, find_and_hash_each_line): Use that macro. X X * diff.h (dup2): Don't define if XENIX. X X * diff.c (main): Check for write error at end. X X * context.c (find_function): Don't return a value. X Use argument FILE rather than global files. X X * analyze.c: Add external function declarations. X * analyze.c (build_script): Turn off explicit check for final newline. X X * analyze.c (discard_confusing_lines): Make integers unsigned. X XTue Jul 31 21:37:16 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * io.c (find_and_hash_each_line): Correct the criterion X for leaving out the newline from the end of the line. X XTue May 29 21:28:16 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * dir.c (diff_dirs): Free things only if nonzero. X XMon Apr 16 18:31:05 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * diff.h (NDIR_IN_SYS): New macro controls location of ndir.h. X X * diff3.c (xmalloc, xrealloc): Don't die if size == 0 returns 0. X XSun Mar 25 15:58:42 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * analyze.c (discard_confusing_lines): X `many' wasn't being used; use it. X Canceling provisionals near start of run must handle already X canceled provisionals. X Canceling subruns of provisionals was canceling last nonprovisional. X XSat Mar 24 14:02:51 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * analyze.c (discard_confusing_lines): X Threshold for line occurring many times scales by square root X of total lines. X Within each run, cancel any long subrun of provisionals. X Don't update `provisional' while canceling provisionals. X In big outer loop, handle provisional and nonprovisional separately. X XThu Mar 22 16:35:33 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * analyze.c (discard_confusing_lines): X The first loops to discard provisionals from ends failed to step. X In second such loops, keep discarding all consecutive provisionals. X Increase threshold for stopping discarding, and also check for X consecutive nondiscardables as separate threshold. X XFri Mar 16 00:33:08 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * diff3.c (read_diff): Pass -- as first arg to diff. X X * diff3.c: Include wait.h or define equivalent macros. X (read_diff): Don't use stdio printing error in the inferior. X Remember the pid and wait for it. Report failing status. X Report failure of vfork. X XSun Mar 11 17:10:32 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * diff3.c (main): Accept -t options and pass to output_diff3_edscript. X (usage): Mention -t. X (read_diff): Use vfork. X (vfork): Don't use it on Sparc. X X * diff.h (vfork): Don't use it on Sparc. X XTue Mar 6 22:37:20 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * diff3.c (dup2): Don't define on Xenix. X X * Makefile: Comments for Xenix. X XThu Mar 1 17:19:23 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * analyze.c (diff_2_files): `message' requires three args. X XFri Feb 23 10:56:50 1990 David J. MacKenzie (djm at albert.ai.mit.edu) X X * diff.h, util.c, diff3.c: Change 'void *' to 'VOID *', with X VOID defined as void if __STDC__, char if not. X XSun Feb 18 20:31:58 1990 David J. MacKenzie (djm at albert.ai.mit.edu) X X * Makefile: Add rules for getopt.c, getopt1.c, getopt.h. X X * getopt.c, getopt.h, getopt1.c: New files. X X * main.c (main, usage): Add long options. X X * analyze.c (shift_boundaries): Remove unused var 'j_end'. X XThu Feb 8 02:43:16 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu) X X * GNUmakefile: include ../Makerules before Makefile. X XFri Feb 2 23:21:38 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * analyze.c (diff_2_files): If -B or -I, don't return 1 X if all changes were ignored. X XWed Jan 24 20:43:57 1990 Richard Stallman (rms at albert.ai.mit.edu) X X * diff3.c (fatal): Output to stderr. X XThu Jan 11 00:25:56 1990 David J. MacKenzie (djm at hobbes.ai.mit.edu) X X * diff.c (usage): Mention -v. X XWed Jan 10 16:06:38 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * diff3.c (output_diff3_edscript): Return number of overlaps. X (main): If have overlaps, exit with status 1. X XSun Dec 24 10:29:20 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * io.c (find_equiv_class): Fix typo that came from changing init of B X to an assignment. X X * version.c: New file. X * diff.c (main): -v prints version number. X X * io.c (binary_file_p): Null char implies binary file. X XFri Nov 17 23:44:55 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * util.c (print_1_line): Fix off by 1 error. X XThu Nov 16 13:51:10 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * util.c (xcalloc): Function deleted. X X * io.c (slurp): Null-terminate the buffer. X X * io.c (read_files): Delete unused vars. X X * io.c (find_equiv_class): Don't index by N if too low. X X * dir.c (dir_sort): Delete the extra declaration of compare_names. X X * diff.h: Don't declare xcalloc. Declare some other functions. X X * analyze.c (shift_boundaries): X Test for END at end of range before indexing by it. X Fix misspelling of `preceding' in var names. X XSat Nov 11 14:04:16 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * diff3.c (using_to_diff3_block): Delete unused vars. X (make_3way_diff, process_diff_control, read_diff, output_diff3): Likewise. X XMon Nov 6 18:15:50 EST 1989 Jay Fenlason (hack@ai.mit.edu) X X * README Fix typo. X XFri Nov 3 15:27:47 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * diff.c (usage): Mention -D. X X * ifdef.c (print_ifdef_hunk): Write comments on #else and #endif. X XSun Oct 29 16:41:07 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * diff.c (compare_files): Don't fflush for identical files. X XWed Oct 25 17:57:12 1989 Randy Smith (randy at apple-gunkies.ai.mit.edu) X X * diff3.c (using_to_diff3_block): When defaulting lines from X FILE0, only copy up to just under the *lowest* line mentioned X in the next diff. X X * diff3.c (fatal): Add \n to error messages. X XWed Oct 25 15:05:49 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * Makefile (tapefiles): Add ChangeLog. X XTue Oct 3 00:51:17 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * diff3.c (process_diff, create_diff3_block): Init ->next field. X XFri Sep 29 08:16:45 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * util.c (line_cmp): Alter end char of line 2, not line 1. X XWed Sep 20 00:12:37 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * Makefile (diff.tar): Expect ln to fail on some files; X copy them with cp. X XMon Sep 18 02:54:29 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * Handle -D option: X * io.c (find_and_hash_each_line): Keep all lines of 1st file. X * diff.c (main): Handle -D option. X (compare_files): Reject -D if files spec'd are directories. X * analyze.c (diff_2_files): Handle OUTPUT_IFDEF case. X XFri Sep 1 20:15:50 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * diff.c (option_list): Rename arg VECTOR as OPTIONVEC. X XMon Aug 28 17:58:27 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * diff.c (compare_files): Clear entire inf[i].stat. X XWed Aug 23 17:48:47 1989 Richard Stallman (rms at apple-gunkies.ai.mit.edu) X X * io.c (find_identical_ends): Sign was backward X determining where to bound the scan for the suffix. X XWed Aug 16 12:49:16 1989 Richard Stallman (rms at hobbes.ai.mit.edu) X X * analyze.c (diff_2_files): If -q, treat all files as binary. X * diff.c (main): Detect -q, record in no_details_flag. X XSun Jul 30 23:12:00 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * diff.c (usage): New function. X (main): Call it. X XWed Jul 26 02:02:19 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * diff.c (main): Make -C imply -c. X XThu Jul 20 17:57:51 1989 Chris Hanson (cph at kleph) X X * io.c (find_and_hash_each_line): Bug fix in context handling, X introduced by last change. X XFri Jul 14 17:39:20 1989 Chris Hanson (cph at kleph) X X * analyze.c: To make RCS work correctly on files that don't X necessarily end in newline, introduce some changes that cause X diffs to be sensitive to missing final newline. Because X non-RCS modes don't want to be affected by these changes, they X are conditional on `output_style == OUTPUT_RCS'. X (diff_2_files) [OUTPUT_RCS]: Suppress the "File X missing X newline" message. X (build_script) [OUTPUT_RCS]: Cause the last line to compare as X different if exactly one of the files is missing its final X newline. X X * io.c (find_and_hash_each_line): Bug fix in X ignore_space_change mode. Change line's length to include the X newline. For OUTPUT_RCS, decrement last line's length if X there is no final newline. X (find_identical_ends) [OUTPUT_RCS]: If one of the files is X missing a final newline, make sure it's not included in either X the prefix or suffix. X X * util.c (print_1_line): Change line output routine to account X for line length including the newline. X XTue Jun 27 02:35:28 1989 Roland McGrath (roland at hobbes.ai.mit.edu) X X * Makefile: Inserted $(archpfx) where appropriate. X XWed May 17 20:18:43 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * diff3.c [USG]: Include fcntl.h. X X * diff.h [USG]: New compilation flags HAVE_NDIR, HAVE_DIRECT. X XWed Apr 26 15:35:57 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * dir.c (diff_dirs): Two new args, NONEX1 and NONEX2, say to pretend X nonex dirs are empty. X (dir_sort): New arg NONEX, likewise. X * diff.c (compare_files): Pass those args. X Sometimes call diff_dirs if subdir exists in just one place. X XWed Apr 12 01:10:27 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * io.c (find_identical_ends): Set END0 *after* last char X during backward scan for suffix. X XSat Apr 8 15:49:49 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) X X * diff3.c (using_to_diff3_block): Now find high marks in files 1 X and 2 through mapping off of the last difference instead of the X first. X X * diff3.c: Many trivial changes to spelling inside comments. X XFri Feb 24 12:38:03 1989 Randall Smith (randy at gluteus.ai.mit.edu) X X * util.c, normal.c, io.c, ed.c, dir.c, diff.h, diff.c, context.c, X analyze.c, Makefile: Changed copyright header to conform with new X GNU General Public license. X * diff3.c: Changed copyright header to conform with new GNU X General Public license. X * COPYING: Made a hard link to /gp/rms/COPYING. X XFri Feb 24 10:01:58 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * io.c (slurp): Leave 2 chars space at end of buffer, not one. X (find_identical_ends): Special case if either file is empty; X don't try to make a sentinel since could crash. X XWed Feb 15 14:24:48 1989 Jay Fenlason (hack at apple-gunkies.ai.mit.edu) X X * diff3.c (message) Re-wrote routine to avoid using alloca() X XWed Feb 15 06:19:14 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * io.c (find_identical_ends): Delete the variable `bytes'. X XSun Feb 12 11:50:36 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * io.c (slurp): ->bufsize is nominal amount we have room for; X add room for sentinel when calling xmalloc or xrealloc. X X * io.c (find_identical_ends): Do need overrun check in finding suffix. X XFri Feb 10 01:28:15 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * diff.c (main): -C now takes arg to specify context length. X Now -p to show C function name--Damned IEEE! X Fatal error if context length spec'd twice. X X * ed.c (print_ed_hunk): Now special treatment only for lines containing X precisely a dot and nothing else. Output `..', end the insert, X substitute that one line, then resume the insert if nec. X X * io.c (find_and_hash_lines): When backing up over starting context, X don't move past buffer-beg. X X * io.c (find_identical_ends): Use sentinels to make the loops faster. X If files are identical, skip the 2nd loop and return quickly. X (slurp): Leave 1 char extra space after each buffer. X X * analyze.c (diff_2_files): Mention difference in final newlines. X XWed Jan 25 22:44:44 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * dir.c (diff_dirs): Use * when calling fcn ptr variable. X XSat Dec 17 14:12:06 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * Makefile: New vars INSTALL and LIBS used in some rules; X provide default defns plus commented-put defns for sysV. X XThu Nov 17 16:42:53 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * dir.c (dir_sort): Open-trouble not fatal; just say # files is -1. X (diff_dirs): If dir_sort does that, give up and return 2. X X * diff.c (compare_files): Don't open directories. X Don't close them specially either. X Cross-propagate inf[i].dir_p sooner. X XSun Nov 13 11:19:36 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu) X X * diff.h: Declare index, rindex. X X * diff.c (compare_files): If comparing foodir with b/f, X use foodir/f, not foodir/b/f. X X * diff.c (compare_files): Don't print "are identical" msg for 2 dirs. X Status now 1 if one file is a dir and the other isn't, etc. X XThu Nov 3 16:30:24 1988 Randall Smith (randy at gluteus.ai.mit.edu) X X * Makefile: Added a define for diff3 to define DIFF_PROGRAM. X X * util.c: Added hack to make sure that perror was not called with X a null pointer. X X * diff.c: Changed S_IFDIR to S_IFMT in masking type of file bits X out. X X * diff3.c: Included USG compatibility defines. X X * diff.h: Moved sys/file.h into #else USG section (not needed or X wanted on System V). X X * ed.c, analyze.c, context.c: Shortened names to 12 characters for X the sake of System V (too simple not to do). X X XCopyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1997, 1998, 1999, X2000, 2001, 2002 Free Software Foundation, Inc. X XThis file is part of GNU Diffutils. X XThis program is free software; you can redistribute it and/or modify Xit under the terms of the GNU General Public License as published by Xthe Free Software Foundation; either version 2, or (at your option) Xany later version. X XThis program is distributed in the hope that they will be useful, Xbut WITHOUT ANY WARRANTY; without even the implied warranty of XMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the XGNU General Public License for more details. X XYou should have received a copy of the GNU General Public License Xalong with this program; see the file COPYING. If not, write to Xthe Free Software Foundation, Inc., 59 Temple Place - Suite 330, XBoston, MA 02111-1307, USA. END-of-contrib/diff/ChangeLog echo x - contrib/diff/Makefile.am sed 's/^X//' >contrib/diff/Makefile.am << 'END-of-contrib/diff/Makefile.am' X# Main Automakefile for GNU diffutils. X X# Copyright (C) 2001, 2002 Free Software Foundation, Inc. X X## This program is free software; you can redistribute it and/or modify X## it under the terms of the GNU General Public License as published by X## the Free Software Foundation; either version 2, or (at your option) X## any later version. X X## This program is distributed in the hope that it will be useful, X## but WITHOUT ANY WARRANTY; without even the implied warranty of X## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X## GNU General Public License for more details. X X## You should have received a copy of the GNU General Public License X## along with this program; if not, write to the Free Software X## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA X## 02111-1307, USA. X XEXTRA_DIST = config/config.rpath exgettext INSTALLME XSUBDIRS = doc lib m4 ms src man po X XACLOCAL_AMFLAGS = -I m4 END-of-contrib/diff/Makefile.am echo x - contrib/diff/NEWS sed 's/^X//' >contrib/diff/NEWS << 'END-of-contrib/diff/NEWS' XUser-visible changes in version 2.8.1: X X* Documentation fixes. X XUser-visible changes in version 2.8: X X* cmp and diff now conform to POSIX 1003.1-2001 (IEEE Std 1003.1-2001) X if the underlying system conforms to POSIX and if the _POSIX2_VERSION X environment variable is set to 200112. Conformance removes support X for `diff -NUM', where NUM is a number. Use -C NUM or -U NUM instead. X* cmp now supports trailing operands SKIP1 and SKIP2, like BSD cmp. X* cmp -i or --ignore-initial now accepts SKIP1:SKIP2 option value. X* New cmp option: -n or --bytes. X* cmp's old -c or --print-chars option has been renamed; X use -b or --print-bytes instead. X* cmp now outputs "byte" rather than "char" outside the POSIX locale. X* cmp -l's index column width now adjusts to fit larger (or smaller) files. X* cmp -l -s and cmp -s -l are not allowed. Use cmp -s or cmp -l instead. X* diff uses ISO 8601 style time stamps for output times (e.g. "2001-11-23 X 16:44:36.875702460 -0800") unless in the C or POSIX locale and the X -c style is specified. X* diff's -I and -F options use the regexp syntax of grep, not of Emacs. X* diff now accepts multiple context arguments, and uses their maximum value. X* New diff and sdiff options: X -E --ignore-tab-expansion X --strip-trailing-cr X* New diff options: X --from-file=FILE, --to-file=FILE X --ignore-file-name-case X --no-ignore-file-name-case X* New diff3 and sdiff option: X --diff-program=PROGRAM X* The following diff options are still accepted, but are no longer documented. X They may be withdrawn in future releases. X -h (omit; it has no effect) X -H (use --speed-large-files instead) X -L (use --label instead) X -P (use --unidirectional-new-file instead) X --inhibit-hunk-merge (omit; it has no effect) X* Recursive diffs now sort file names according to the LC_COLLATE locale X category if possible, instead of using native byte comparison. X* Diff printf specs can now use the "0" and "'" flags. X* The new sdiff interactive command `ed' precedes each version with a header. X* On 64-bit hosts, files larger than 2 GB can be compared. X* Some internationalization support has been added, but multibyte locales X are still not completely supported yet. X* Some diagnostics have been reworded slightly for consistency. X Also, `diff -D FOO' now outputs `/* ! FOO */' instead of `/* not FOO */'. X* The `patch' part of the manual now describes `patch' version 2.5.4. X* Man pages are now distributed and installed. X* There is support for DJGPP; see the 'ms' subdirectory and the files X m4/dos.m4 and */setmode.*. X X XUser-visible changes in version 2.7: X X* New diff option: --binary (useful only on non-POSIX hosts) X* diff -b and -w now ignore line incompleteness; -B no longer does this. X* cmp -c now uses locale to decide which output characters to quote. X* Help and version messages are reorganized. X X XUser-visible changes in version 2.6: X X* New cmp, diff, diff3, sdiff option: --help X* A new heuristic for diff greatly reduces the time needed to compare X large input files that contain many differences. X* Partly as a result, GNU diff's output is not exactly the same as before. X Usually it is a bit smaller, but sometimes it is a bit larger. X X XUser-visible changes in version 2.5: X X* New cmp option: -v --version X X XUser-visible changes in version 2.4: X X* New cmp option: --ignore-initial=BYTES X* New diff3 option: -T --initial-tab X* New diff option: --line-format=FORMAT X* New diff group format specifications: X [eflmnEFLMN] X A printf spec followed by one of the following letters X causes the integer corresponding to that letter to be X printed according to the printf specification. X E.g. `%5df' prints the number of the first line in the X group in the old file using the "%5d" format. X e: line number just before the group in old file; equals f - 1 X f: first line number in group in the old file X l: last line number in group in the old file X m: line number just after the group in old file; equals l + 1 X n: number of lines in group in the old file; equals l - f + 1 X E, F, L, M, N: likewise, for lines in the new file X %(A=B?T:E) X If A equals B then T else E. A and B are each either a decimal X constant or a single letter interpreted as above. T and E are X arbitrary format strings. This format spec is equivalent to T if X A's value equals B's; otherwise it is equivalent to E. For X example, `%(N=0?no:%dN) line%(N=1?:s)' is equivalent to `no lines' X if N (the number of lines in the group in the the new file) is 0, X to `1 line' if N is 1, and to `%dN lines' otherwise. X %c'C' X where C is a single character, stands for the character C. C may not X be a backslash or an apostrophe. E.g. %c':' stands for a colon. X %c'\O' X where O is a string of 1, 2, or 3 octal digits, stands for the X character with octal code O. E.g. %c'\0' stands for a null character. X* New diff line format specifications: X n X The line number, printed with . X E.g. `%5dn' prints the line number with a "%5d" format. X %c'C' X %c'\O' X The character C, or with octal code O, as above. X* Supported s have the same meaning as with printf, but must X match the extended regular expression %-*[0-9]*(\.[0-9]*)?[doxX]. X* The format spec %0 introduced in version 2.1 has been removed, since it X is incompatible with printf specs like %02d. To represent a null char, X use %c'\0' instead. X* cmp and diff now conform to POSIX 1003.2-1992 (ISO/IEC 9945-2:1993) X if the underlying system conforms to POSIX: X - Some messages' wordings are changed in minor ways. X - ``White space'' is now whatever C's `isspace' says it is. X - When comparing directories, if `diff' finds a file that is not a regular X file or a directory, it reports the file's type instead of diffing it. X (As usual, it follows symbolic links first.) X - When signaled, sdiff exits with the signal's status, not with status 2. X* Now portable to hosts where int, long, pointer, etc. are not all the same X size. X* `cmp - -' now works like `diff - -'. X X XUser-visible changes in version 2.3: X X* New diff option: --horizon-lines=lines X X XUser-visible changes in version 2.1: X X* New diff options: X --{old,new,unchanged}-line-format='format' X --{old,new,unchanged,changed}-group-format='format' X -U X* New diff3 option: X -A --show-all X* diff3 -m now defaults to -A, not -E. X* diff3 now takes up to three -L or --label options, not just two. X If just two options are given, they refer to the first two input files, X not the first and third input files. X* sdiff and diff -y handle incomplete lines. X X XUser-visible changes in version 2.0: X X* Add sdiff and cmp programs. X* Add Texinfo documentation. X* Add configure script. X* Improve diff performance. X* New diff options: X-x --exclude X-X --exclude-from X-P --unidirectional-new-file X-W --width X-y --side-by-side X--left-column X--sdiff-merge-assist X--suppress-common-lines X* diff options renamed: X--label renamed from --file-label X--forward-ed renamed from --reversed-ed X--paginate renamed from --print X--entire-new-file renamed from --entire-new-files X--new-file renamed from --new-files X--all-text removed X* New diff3 options: X-v --version X* Add long-named equivalents for other diff3 options. X* diff options -F (--show-function-line) and -I (--ignore-matching-lines) X can now be given more than once. X X X XCopyright (C) 1993, 1994, 1998, 2001, 2002 Free Software Foundation, XInc. X XThis file is part of GNU Diffutils. X XThis program is free software; you can redistribute it and/or modify Xit under the terms of the GNU General Public License as published by Xthe Free Software Foundation; either version 2, or (at your option) Xany later version. X XThis program is distributed in the hope that they will be useful, Xbut WITHOUT ANY WARRANTY; without even the implied warranty of XMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the XGNU General Public License for more details. X XYou should have received a copy of the GNU General Public License Xalong with this program; see the file COPYING. If not, write to Xthe Free Software Foundation, Inc., 59 Temple Place - Suite 330, XBoston, MA 02111-1307, USA. END-of-contrib/diff/NEWS echo x - contrib/diff/THANKS sed 's/^X//' >contrib/diff/THANKS << 'END-of-contrib/diff/THANKS' XThanks to all the following for their contributions to GNU diffutils: X XThomas Bushnell XWayne Davison XUlrich Drepper XPaul Eggert XJay Fenlason XJohn Gilmore XTorbjorn Granlund XMike Haertel XBruno Haible XChris Hanson XJim Kingdon XTom Lord XDavid J. MacKenzie XRoland McGrath XJim Meyering XEugene W. Myers XRandy Smith XRichard Stallman XLeonard H. Tower Jr. XEli Zaretskii END-of-contrib/diff/THANKS echo x - contrib/diff/exgettext sed 's/^X//' >contrib/diff/exgettext << 'END-of-contrib/diff/exgettext' X#! /bin/sh X# Wrapper around gettext for programs using the msgid convention. X X# Copyright (C) 1998, 2001 Free Software Foundation, Inc. X X# Written by Paul Eggert . X X# This program is free software; you can redistribute it and/or modify X# it under the terms of the GNU General Public License as published by X# the Free Software Foundation; either version 2, or (at your option) X# any later version. X X# This program is distributed in the hope that it will be useful, X# but WITHOUT ANY WARRANTY; without even the implied warranty of X# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X# GNU General Public License for more details. X X# You should have received a copy of the GNU General Public License X# along with GNU CC; see the file COPYING. If not, write to X# the Free Software Foundation, 59 Temple Place - Suite 330, X# Boston, MA 02111-1307, USA. X X# Always operate in the C locale. XLANG=C XLANGUAGE=C XLC_ALL=C Xexport LANG LANGUAGE LC_ALL X X# Set AWK if environment has not already set it. XAWK=${AWK-awk} X X# The argument to this wrapper is the xgettext command to be executed. X# Extract the xgettext program name from the rest of the command. Xxgettext=${1?} Xshift X X# Save work if we're just wrapping a no-op. Xcase $xgettext in X:) exit;; Xesac X X# Find the files to be scanned, and the directory to scan them from. Xdirectory=. Xfiles= Xfor i Xdo X case $i in X --directory=*) X directory=`expr " $i" : ' --directory=\(.*\)'`;; X --files-from=*) X files_from=`expr " $i" : ' --files-from=\(.*\)'` X files=`$AWK '/^[^#]/ { print }' $files_from`;; X esac Xdone X X# Generate keyword options for xgettext, X# by scanning for declarations of functions X# whose parameter names end in "msgid". Xgenerate_keyword_options=' X /^[A-Z_a-z].*\(.*msgid[,)]/ { X X paren_index = index($0, "(") X X name = substr($0, 1, paren_index - 1) X sub(/[^0-9A-Z_a-z]*$/, "", name) X sub(/[ ]+PARAMS/, "", name) X sub(/[ ]+VPARAMS/, "", name) X sub(/.*[^0-9A-Z_a-z]/, "", name) X X args = substr($0, paren_index) X sub(/msgid[,)].*/, "", args) X for (n = 1; sub(/^[^,]*,/, "", args); n++) { X continue; X } X X if (n == 1) { X keyword = name X } else { X keyword = name ":" n X } X X if (! keyword_seen[keyword]++) { X print "--keyword=" keyword X } X } X' Xkeyword_options=`( X cd $directory && X $AWK "$generate_keyword_options" $files < /dev/null X)` || exit X X# Generate temporary file reflecting the %e strings in the scanned files. Xtmp=tmp-emsgids.c X Xgenerate_emsgids=' X /%e.*}/ { X line = $0 X while ((percent_index = index(line, "%e")) != 0) { X line = substr(line, percent_index + 2) X bracket_index = index(line, "}") X if (bracket_index == 0) { X continue X } X msgid = substr(line, 1, bracket_index - 1) X if (index(msgid, "%") != 0) { X continue X } X printf "#line %d \"%s\"\n", FNR, FILENAME X printf "_(\"%s\")\n", msgid X line = substr(line, bracket_index + 1) X } X } X' X(cd $directory && X $AWK "$generate_emsgids" $files < /dev/null X) > $directory/$tmp || exit X X# Run the xgettext command, with temporary added as a file to scan. X"$xgettext" $keyword_options ${1+"$@"} $tmp || exit X X# Clean up. X# If we don't get here, `make clean' will remove this file later. Xrm -f $directory/$tmp END-of-contrib/diff/exgettext echo x - contrib/diff/INSTALLME sed 's/^X//' >contrib/diff/INSTALLME << 'END-of-contrib/diff/INSTALLME' XInstallation instructions specific to GNU Diffutils X X Copyright (C) 2001, 2002 Free Software Foundation, Inc. X X This file is part of GNU Diffutils. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; see the file COPYING. If not, write to X the Free Software Foundation, Inc., 59 Temple Place - Suite 330, X Boston, MA 02111-1307, USA. X X XPlease send comments and problem reports to . X XIf you have a problem with internationalization, you might be able to Xwork around it as described in ABOUT-NLS by invoking `./configure X--disable-nls'. Many of the problems arise from dynamic linking Xissues on non-GNU platforms (e.g. with the iconv library). Such Xproblems tend to be shared by other GNU applications on these Xplatforms, and can usually be fixed by carefully tweaking your non-GNU Xinstallation. If you have an older version of libiconv, please Xupgrade to the latest one, preferably libiconv-1.8 or newer. X(libiconv-1.8 is not yet available as of this writing, but it should Xbe out soon.) If the problem seems isolated to diffutils, though, Xplease report a bug. X XThis program requires a Standard C compiler (C89 or later); if you Xhave an older K&R compiler, please install GCC first. X XIf you make changes to the source code, you may need recent test Xversions of GNU build tools to regenerate the intermediate files. The Xfollowing versions were used to generate the intermediate files in Xthis distribution: X X* GNU Autoconf 2.53 X X* GNU Automake 1.6 X X* GNU gettext 0.11.1 X X* GNU help2man 1.27 X X* GNU texinfo 4.2 END-of-contrib/diff/INSTALLME echo c - contrib/diff/doc mkdir -p contrib/diff/doc > /dev/null 2>&1 echo x - contrib/diff/doc/fdl.texi sed 's/^X//' >contrib/diff/doc/fdl.texi << 'END-of-contrib/diff/doc/fdl.texi' X X@node GNU Free Documentation License X@appendixsec GNU Free Documentation License X X@cindex FDL, GNU Free Documentation License X@center Version 1.1, March 2000 X X@display XCopyright @copyright{} 2000 Free Software Foundation, Inc. X59 Temple Place, Suite 330, Boston, MA 02111-1307, USA X XEveryone is permitted to copy and distribute verbatim copies Xof this license document, but changing it is not allowed. X@end display X X@enumerate 0 X@item XPREAMBLE X XThe purpose of this License is to make a manual, textbook, or other Xwritten document @dfn{free} in the sense of freedom: to assure everyone Xthe effective freedom to copy and redistribute it, with or without Xmodifying it, either commercially or noncommercially. Secondarily, Xthis License preserves for the author and publisher a way to get Xcredit for their work, while not being considered responsible for Xmodifications made by others. X XThis License is a kind of ``copyleft'', which means that derivative Xworks of the document must themselves be free in the same sense. It Xcomplements the GNU General Public License, which is a copyleft Xlicense designed for free software. X XWe have designed this License in order to use it for manuals for free Xsoftware, because free software needs free documentation: a free Xprogram should come with manuals providing the same freedoms that the Xsoftware does. But this License is not limited to software manuals; Xit can be used for any textual work, regardless of subject matter or Xwhether it is published as a printed book. We recommend this License Xprincipally for works whose purpose is instruction or reference. X X@item XAPPLICABILITY AND DEFINITIONS X XThis License applies to any manual or other work that contains a Xnotice placed by the copyright holder saying it can be distributed Xunder the terms of this License. The ``Document'', below, refers to any Xsuch manual or work. Any member of the public is a licensee, and is Xaddressed as ``you''. X XA ``Modified Version'' of the Document means any work containing the XDocument or a portion of it, either copied verbatim, or with Xmodifications and/or translated into another language. X XA ``Secondary Section'' is a named appendix or a front-matter section of Xthe Document that deals exclusively with the relationship of the Xpublishers or authors of the Document to the Document's overall subject X(or to related matters) and contains nothing that could fall directly Xwithin that overall subject. (For example, if the Document is in part a Xtextbook of mathematics, a Secondary Section may not explain any Xmathematics.) The relationship could be a matter of historical Xconnection with the subject or with related matters, or of legal, Xcommercial, philosophical, ethical or political position regarding Xthem. X XThe ``Invariant Sections'' are certain Secondary Sections whose titles Xare designated, as being those of Invariant Sections, in the notice Xthat says that the Document is released under this License. X XThe ``Cover Texts'' are certain short passages of text that are listed, Xas Front-Cover Texts or Back-Cover Texts, in the notice that says that Xthe Document is released under this License. X XA ``Transparent'' copy of the Document means a machine-readable copy, Xrepresented in a format whose specification is available to the Xgeneral public, whose contents can be viewed and edited directly and Xstraightforwardly with generic text editors or (for images composed of Xpixels) generic paint programs or (for drawings) some widely available Xdrawing editor, and that is suitable for input to text formatters or Xfor automatic translation to a variety of formats suitable for input Xto text formatters. A copy made in an otherwise Transparent file Xformat whose markup has been designed to thwart or discourage Xsubsequent modification by readers is not Transparent. A copy that is Xnot ``Transparent'' is called ``Opaque''. X XExamples of suitable formats for Transparent copies include plain X@sc{ascii} without markup, Texinfo input format, La@TeX{} input format, X@acronym{SGML} or @acronym{XML} using a publicly available X@acronym{DTD}, and standard-conforming simple @acronym{HTML} designed Xfor human modification. Opaque formats include PostScript, X@acronym{PDF}, proprietary formats that can be read and edited only by Xproprietary word processors, @acronym{SGML} or @acronym{XML} for which Xthe @acronym{DTD} and/or processing tools are not generally available, Xand the machine-generated @acronym{HTML} produced by some word Xprocessors for output purposes only. X XThe ``Title Page'' means, for a printed book, the title page itself, Xplus such following pages as are needed to hold, legibly, the material Xthis License requires to appear in the title page. For works in Xformats which do not have any title page as such, ``Title Page'' means Xthe text near the most prominent appearance of the work's title, Xpreceding the beginning of the body of the text. X X@item XVERBATIM COPYING X XYou may copy and distribute the Document in any medium, either Xcommercially or noncommercially, provided that this License, the Xcopyright notices, and the license notice saying this License applies Xto the Document are reproduced in all copies, and that you add no other Xconditions whatsoever to those of this License. You may not use Xtechnical measures to obstruct or control the reading or further Xcopying of the copies you make or distribute. However, you may accept Xcompensation in exchange for copies. If you distribute a large enough Xnumber of copies you must also follow the conditions in section 3. X XYou may also lend copies, under the same conditions stated above, and Xyou may publicly display copies. X X@item XCOPYING IN QUANTITY X XIf you publish printed copies of the Document numbering more than 100, Xand the Document's license notice requires Cover Texts, you must enclose Xthe copies in covers that carry, clearly and legibly, all these Cover XTexts: Front-Cover Texts on the front cover, and Back-Cover Texts on Xthe back cover. Both covers must also clearly and legibly identify Xyou as the publisher of these copies. The front cover must present Xthe full title with all words of the title equally prominent and Xvisible. You may add other material on the covers in addition. XCopying with changes limited to the covers, as long as they preserve Xthe title of the Document and satisfy these conditions, can be treated Xas verbatim copying in other respects. X XIf the required texts for either cover are too voluminous to fit Xlegibly, you should put the first ones listed (as many as fit Xreasonably) on the actual cover, and continue the rest onto adjacent Xpages. X XIf you publish or distribute Opaque copies of the Document numbering Xmore than 100, you must either include a machine-readable Transparent Xcopy along with each Opaque copy, or state in or with each Opaque copy Xa publicly-accessible computer-network location containing a complete XTransparent copy of the Document, free of added material, which the Xgeneral network-using public has access to download anonymously at no Xcharge using public-standard network protocols. If you use the latter Xoption, you must take reasonably prudent steps, when you begin Xdistribution of Opaque copies in quantity, to ensure that this XTransparent copy will remain thus accessible at the stated location Xuntil at least one year after the last time you distribute an Opaque Xcopy (directly or through your agents or retailers) of that edition to Xthe public. X XIt is requested, but not required, that you contact the authors of the XDocument well before redistributing any large number of copies, to give Xthem a chance to provide you with an updated version of the Document. X X@item XMODIFICATIONS X XYou may copy and distribute a Modified Version of the Document under Xthe conditions of sections 2 and 3 above, provided that you release Xthe Modified Version under precisely this License, with the Modified XVersion filling the role of the Document, thus licensing distribution Xand modification of the Modified Version to whoever possesses a copy Xof it. In addition, you must do these things in the Modified Version: X X@enumerate A X@item XUse in the Title Page (and on the covers, if any) a title distinct Xfrom that of the Document, and from those of previous versions X(which should, if there were any, be listed in the History section Xof the Document). You may use the same title as a previous version Xif the original publisher of that version gives permission. X X@item XList on the Title Page, as authors, one or more persons or entities Xresponsible for authorship of the modifications in the Modified XVersion, together with at least five of the principal authors of the XDocument (all of its principal authors, if it has less than five). X X@item XState on the Title page the name of the publisher of the XModified Version, as the publisher. X X@item XPreserve all the copyright notices of the Document. X X@item XAdd an appropriate copyright notice for your modifications Xadjacent to the other copyright notices. X X@item XInclude, immediately after the copyright notices, a license notice Xgiving the public permission to use the Modified Version under the Xterms of this License, in the form shown in the Addendum below. X X@item XPreserve in that license notice the full lists of Invariant Sections Xand required Cover Texts given in the Document's license notice. X X@item XInclude an unaltered copy of this License. X X@item XPreserve the section entitled ``History'', and its title, and add to Xit an item stating at least the title, year, new authors, and Xpublisher of the Modified Version as given on the Title Page. If Xthere is no section entitled ``History'' in the Document, create one Xstating the title, year, authors, and publisher of the Document as Xgiven on its Title Page, then add an item describing the Modified XVersion as stated in the previous sentence. X X@item XPreserve the network location, if any, given in the Document for Xpublic access to a Transparent copy of the Document, and likewise Xthe network locations given in the Document for previous versions Xit was based on. These may be placed in the ``History'' section. XYou may omit a network location for a work that was published at Xleast four years before the Document itself, or if the original Xpublisher of the version it refers to gives permission. X X@item XIn any section entitled ``Acknowledgments'' or ``Dedications'', Xpreserve the section's title, and preserve in the section all the Xsubstance and tone of each of the contributor acknowledgments Xand/or dedications given therein. X X@item XPreserve all the Invariant Sections of the Document, Xunaltered in their text and in their titles. Section numbers Xor the equivalent are not considered part of the section titles. X X@item XDelete any section entitled ``Endorsements''. Such a section Xmay not be included in the Modified Version. X X@item XDo not retitle any existing section as ``Endorsements'' Xor to conflict in title with any Invariant Section. X@end enumerate X XIf the Modified Version includes new front-matter sections or Xappendices that qualify as Secondary Sections and contain no material Xcopied from the Document, you may at your option designate some or all Xof these sections as invariant. To do this, add their titles to the Xlist of Invariant Sections in the Modified Version's license notice. XThese titles must be distinct from any other section titles. X XYou may add a section entitled ``Endorsements'', provided it contains Xnothing but endorsements of your Modified Version by various Xparties---for example, statements of peer review or that the text has Xbeen approved by an organization as the authoritative definition of a Xstandard. X XYou may add a passage of up to five words as a Front-Cover Text, and a Xpassage of up to 25 words as a Back-Cover Text, to the end of the list Xof Cover Texts in the Modified Version. Only one passage of XFront-Cover Text and one of Back-Cover Text may be added by (or Xthrough arrangements made by) any one entity. If the Document already Xincludes a cover text for the same cover, previously added by you or Xby arrangement made by the same entity you are acting on behalf of, Xyou may not add another; but you may replace the old one, on explicit Xpermission from the previous publisher that added the old one. X XThe author(s) and publisher(s) of the Document do not by this License Xgive permission to use their names for publicity for or to assert or Ximply endorsement of any Modified Version. X X@item XCOMBINING DOCUMENTS X XYou may combine the Document with other documents released under this XLicense, under the terms defined in section 4 above for modified Xversions, provided that you include in the combination all of the XInvariant Sections of all of the original documents, unmodified, and Xlist them all as Invariant Sections of your combined work in its Xlicense notice. X XThe combined work need only contain one copy of this License, and Xmultiple identical Invariant Sections may be replaced with a single Xcopy. If there are multiple Invariant Sections with the same name but Xdifferent contents, make the title of each such section unique by Xadding at the end of it, in parentheses, the name of the original Xauthor or publisher of that section if known, or else a unique number. XMake the same adjustment to the section titles in the list of XInvariant Sections in the license notice of the combined work. X XIn the combination, you must combine any sections entitled ``History'' Xin the various original documents, forming one section entitled X``History''; likewise combine any sections entitled ``Acknowledgments'', Xand any sections entitled ``Dedications''. You must delete all sections Xentitled ``Endorsements.'' X X@item XCOLLECTIONS OF DOCUMENTS X XYou may make a collection consisting of the Document and other documents Xreleased under this License, and replace the individual copies of this XLicense in the various documents with a single copy that is included in Xthe collection, provided that you follow the rules of this License for Xverbatim copying of each of the documents in all other respects. X XYou may extract a single document from such a collection, and distribute Xit individually under this License, provided you insert a copy of this XLicense into the extracted document, and follow this License in all Xother respects regarding verbatim copying of that document. X X@item XAGGREGATION WITH INDEPENDENT WORKS X XA compilation of the Document or its derivatives with other separate Xand independent documents or works, in or on a volume of a storage or Xdistribution medium, does not as a whole count as a Modified Version Xof the Document, provided no compilation copyright is claimed for the Xcompilation. Such a compilation is called an ``aggregate'', and this XLicense does not apply to the other self-contained works thus compiled Xwith the Document, on account of their being thus compiled, if they Xare not themselves derivative works of the Document. X XIf the Cover Text requirement of section 3 is applicable to these Xcopies of the Document, then if the Document is less than one quarter Xof the entire aggregate, the Document's Cover Texts may be placed on Xcovers that surround only the Document within the aggregate. XOtherwise they must appear on covers around the whole aggregate. X X@item XTRANSLATION X XTranslation is considered a kind of modification, so you may Xdistribute translations of the Document under the terms of section 4. XReplacing Invariant Sections with translations requires special Xpermission from their copyright holders, but you may include Xtranslations of some or all Invariant Sections in addition to the Xoriginal versions of these Invariant Sections. You may include a Xtranslation of this License provided that you also include the Xoriginal English version of this License. In case of a disagreement Xbetween the translation and the original English version of this XLicense, the original English version will prevail. X X@item XTERMINATION X XYou may not copy, modify, sublicense, or distribute the Document except Xas expressly provided for under this License. Any other attempt to Xcopy, modify, sublicense or distribute the Document is void, and will Xautomatically terminate your rights under this License. However, Xparties who have received copies, or rights, from you under this XLicense will not have their licenses terminated so long as such Xparties remain in full compliance. X X@item XFUTURE REVISIONS OF THIS LICENSE X XThe Free Software Foundation may publish new, revised versions Xof the GNU Free Documentation License from time to time. Such new Xversions will be similar in spirit to the present version, but may Xdiffer in detail to address new problems or concerns. See X@uref{http://www.gnu.org/copyleft/}. X XEach version of the License is given a distinguishing version number. XIf the Document specifies that a particular numbered version of this XLicense ``or any later version'' applies to it, you have the option of Xfollowing the terms and conditions either of that specified version or Xof any later version that has been published (not as a draft) by the XFree Software Foundation. If the Document does not specify a version Xnumber of this License, you may choose any version ever published (not Xas a draft) by the Free Software Foundation. X@end enumerate X X@page X@appendixsubsec ADDENDUM: How to use this License for your documents X XTo use this License in a document you have written, include a copy of Xthe License in the document and put the following copyright and Xlicense notices just after the title page: X X@smallexample X@group X Copyright (C) @var{year} @var{your name}. X Permission is granted to copy, distribute and/or modify this document X under the terms of the GNU Free Documentation License, Version 1.1 X or any later version published by the Free Software Foundation; X with the Invariant Sections being @var{list their titles}, with the X Front-Cover Texts being @var{list}, and with the Back-Cover Texts being @var{list}. X A copy of the license is included in the section entitled ``GNU X Free Documentation License''. X@end group X@end smallexample X XIf you have no Invariant Sections, write ``with no Invariant Sections'' Xinstead of saying which ones are invariant. If you have no XFront-Cover Texts, write ``no Front-Cover Texts'' instead of X``Front-Cover Texts being @var{list}''; likewise for Back-Cover Texts. X XIf your document contains nontrivial examples of program code, we Xrecommend releasing these examples in parallel under your choice of Xfree software license, such as the GNU General Public License, Xto permit their use in free software. X X@c Local Variables: X@c ispell-local-pdict: "ispell-dict" X@c End: X END-of-contrib/diff/doc/fdl.texi echo x - contrib/diff/doc/Makefile.am sed 's/^X//' >contrib/diff/doc/Makefile.am << 'END-of-contrib/diff/doc/Makefile.am' X# Makefile for GNU diffutils documentation. X X# Copyright (C) 2001, 2002 Free Software Foundation, Inc. X X## This program is free software; you can redistribute it and/or modify X## it under the terms of the GNU General Public License as published by X## the Free Software Foundation; either version 2, or (at your option) X## any later version. X X## This program is distributed in the hope that it will be useful, X## but WITHOUT ANY WARRANTY; without even the implied warranty of X## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X## GNU General Public License for more details. X X## You should have received a copy of the GNU General Public License X## along with this program; if not, write to the Free Software Foundation, X## Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. X XAM_MAKEINFOFLAGS = --no-split X Xinfo_TEXINFOS = diff.texi Xdiff_TEXINFOS = fdl.texi X XEXTRA_DIST = diagmeet.note END-of-contrib/diff/doc/Makefile.am echo x - contrib/diff/doc/stamp-vti sed 's/^X//' >contrib/diff/doc/stamp-vti << 'END-of-contrib/diff/doc/stamp-vti' X@set UPDATED 5 April 2002 X@set UPDATED-MONTH April 2002 X@set EDITION 2.8.1 X@set VERSION 2.8.1 END-of-contrib/diff/doc/stamp-vti echo x - contrib/diff/doc/version.texi sed 's/^X//' >contrib/diff/doc/version.texi << 'END-of-contrib/diff/doc/version.texi' X@set UPDATED 5 April 2002 X@set UPDATED-MONTH April 2002 X@set EDITION 2.8.1 X@set VERSION 2.8.1 END-of-contrib/diff/doc/version.texi echo x - contrib/diff/doc/diff.texi sed 's/^X//' >contrib/diff/doc/diff.texi << 'END-of-contrib/diff/doc/diff.texi' X\input texinfo @c -*-texinfo-*- X@comment $Id$ X@comment %**start of header X@setfilename diff.info X@include version.texi X@settitle Comparing and Merging Files X@syncodeindex vr cp X@setchapternewpage odd X@comment %**end of header X@copying XThis manual is for GNU Diffutils X(version @value{VERSION}, @value{UPDATED}), Xand documents the @sc{gnu} @command{diff}, @command{diff3}, X@command{sdiff}, and @command{cmp} commands for showing the Xdifferences between files and the @sc{gnu} @command{patch} command for Xusing their output to update files. X XCopyright @copyright{} 1992, 1993, 1994, 1998, 2001, 2002 Free XSoftware Foundation, Inc. X X@quotation XPermission is granted to copy, distribute and/or modify this document Xunder the terms of the GNU Free Documentation License, Version 1.1 or Xany later version published by the Free Software Foundation; with no XInvariant Sections, with the Front-Cover texts being ``A GNU Manual,'' Xand with the Back-Cover Texts as in (a) below. A copy of the Xlicense is included in the section entitled ``GNU Free Documentation XLicense.'' X X(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify Xthis GNU Manual, like GNU software. Copies published by the Free XSoftware Foundation raise funds for GNU development.'' X@end quotation X@end copying X X@c Debian install-info (up through at least version 1.9.20) uses only the X@c first dircategory. Put this one first, as it is more useful in practice. X@dircategory Individual utilities X@direntry X* cmp: (diff)Invoking cmp. Compare 2 files byte by byte. X* diff: (diff)Invoking diff. Compare 2 files line by line. X* diff3: (diff)Invoking diff3. Compare 3 files line by line. X* patch: (diff)Invoking patch. Apply a patch to a file. X* sdiff: (diff)Invoking sdiff. Merge 2 files side-by-side. X@end direntry X X@dircategory GNU packages X@direntry X* Diff: (diff). Comparing and merging files. X@end direntry X X@titlepage X@title Comparing and Merging Files X@subtitle for Diffutils @value{VERSION} and @code{patch} 2.5.4 X@subtitle @value{UPDATED} X@author David MacKenzie, Paul Eggert, and Richard Stallman X@page X@vskip 0pt plus 1filll X@insertcopying X@end titlepage X X@shortcontents X@contents X X@ifnottex X@node Top X@top Comparing and Merging Files X X@insertcopying X@end ifnottex X X@menu X* Overview:: Preliminary information. X* Comparison:: What file comparison means. X X* Output Formats:: Formats for two-way difference reports. X* Incomplete Lines:: Lines that lack trailing newlines. X* Comparing Directories:: Comparing files and directories. X* Adjusting Output:: Making @command{diff} output prettier. X* diff Performance:: Making @command{diff} smarter or faster. X X* Comparing Three Files:: Formats for three-way difference reports. X* diff3 Merging:: Merging from a common ancestor. X X* Interactive Merging:: Interactive merging with @command{sdiff}. X X* Merging with patch:: Using @command{patch} to change old files into new ones. X* Making Patches:: Tips for making and using patch distributions. X X* Invoking cmp:: Compare two files byte by byte. X* Invoking diff:: Compare two files line by line. X* Invoking diff3:: Compare three files line by line. X* Invoking patch:: Apply a diff file to an original. X* Invoking sdiff:: Side-by-side merge of file differences. X X* Standards conformance:: Conformance to the @sc{posix} standard. X* Projects:: If you've found a bug or other shortcoming. X X* Copying This Manual:: How to make copies of this manual. X* Index:: Index. X@end menu X X@node Overview X@unnumbered Overview X@cindex overview of @command{diff} and @command{patch} X XComputer users often find occasion to ask how two files differ. Perhaps Xone file is a newer version of the other file. Or maybe the two files Xstarted out as identical copies but were changed by different people. X XYou can use the @command{diff} command to show differences between two Xfiles, or each corresponding file in two directories. @command{diff} Xoutputs differences between files line by line in any of several Xformats, selectable by command line options. This set of differences is Xoften called a @dfn{diff} or @dfn{patch}. For files that are identical, X@command{diff} normally produces no output; for binary (non-text) files, X@command{diff} normally reports only that they are different. X XYou can use the @command{cmp} command to show the byte and line numbers Xwhere two files differ. @command{cmp} can also show all the bytes Xthat differ between the two files, side by side. A way to compare Xtwo files character by character is the Emacs command @kbd{M-x Xcompare-windows}. @xref{Other Window, , Other Window, emacs, The @sc{gnu} XEmacs Manual}, for more information on that command. X XYou can use the @command{diff3} command to show differences among three Xfiles. When two people have made independent changes to a common Xoriginal, @command{diff3} can report the differences between the original Xand the two changed versions, and can produce a merged file that Xcontains both persons' changes together with warnings about conflicts. X XYou can use the @command{sdiff} command to merge two files interactively. X XYou can use the set of differences produced by @command{diff} to distribute Xupdates to text files (such as program source code) to other people. XThis method is especially useful when the differences are small compared Xto the complete files. Given @command{diff} output, you can use the X@command{patch} program to update, or @dfn{patch}, a copy of the file. If you Xthink of @command{diff} as subtracting one file from another to produce Xtheir difference, you can think of @command{patch} as adding the difference Xto one file to reproduce the other. X XThis manual first concentrates on making diffs, and later shows how to Xuse diffs to update files. X X@sc{gnu} @command{diff} was written by Paul Eggert, Mike Haertel, XDavid Hayes, Richard Stallman, and Len Tower. Wayne Davison designed and Ximplemented the unified output format. The basic algorithm is described Xin ``An O(ND) Difference Algorithm and its Variations'', Eugene W. Myers, X@cite{Algorithmica} Vol.@: 1 No.@: 2, 1986, pp.@: 251--266; and in ``A File XComparison Program'', Webb Miller and Eugene W. Myers, X@cite{Software---Practice and Experience} Vol.@: 15 No.@: 11, 1985, Xpp.@: 1025--1040. X@c From: "Gene Myers" X@c They are about the same basic algorithm; the Algorithmica X@c paper gives a rigorous treatment and the sub-algorithm for X@c delivering scripts and should be the primary reference, but X@c both should be mentioned. XThe algorithm was independently discovered as described in X``Algorithms for Approximate String Matching'', XE. Ukkonen, @cite{Information and Control} Vol.@: 64, 1985, pp.@: 100--118. X@c From: "Gene Myers" X@c Date: Wed, 29 Sep 1993 08:27:55 MST X@c Ukkonen should be given credit for also discovering the algorithm used X@c in GNU diff. X X@sc{gnu} @command{diff3} was written by Randy Smith. @sc{gnu} X@command{sdiff} was written by Thomas Lord. @sc{gnu} @command{cmp} Xwas written by Torbjorn Granlund and David MacKenzie. X X@command{patch} was written mainly by Larry Wall and Paul Eggert; Xseveral @sc{gnu} enhancements were contributed by Wayne Davison and XDavid MacKenzie. Parts of this manual are adapted from a manual page Xwritten by Larry Wall, with his permission. X X@node Comparison X@chapter What Comparison Means X@cindex introduction X XThere are several ways to think about the differences between two files. XOne way to think of the differences is as a series of lines that were Xdeleted from, inserted in, or changed in one file to produce the other Xfile. @command{diff} compares two files line by line, finds groups of Xlines that differ, and reports each group of differing lines. It can Xreport the differing lines in several formats, which have different Xpurposes. X X@sc{gnu} @command{diff} can show whether files are different without detailing Xthe differences. It also provides ways to suppress certain kinds of Xdifferences that are not important to you. Most commonly, such Xdifferences are changes in the amount of white space between words or Xlines. @command{diff} also provides ways to suppress differences in Xalphabetic case or in lines that match a regular expression that you Xprovide. These options can accumulate; for example, you can ignore Xchanges in both white space and alphabetic case. X XAnother way to think of the differences between two files is as a Xsequence of pairs of bytes that can be either identical or Xdifferent. @command{cmp} reports the differences between two files Xbyte by byte, instead of line by line. As a result, it is often Xmore useful than @command{diff} for comparing binary files. For text Xfiles, @command{cmp} is useful mainly when you want to know only whether Xtwo files are identical, or whether one file is a prefix of the other. X XTo illustrate the effect that considering changes byte by byte Xcan have compared with considering them line by line, think of what Xhappens if a single newline character is added to the beginning of a Xfile. If that file is then compared with an otherwise identical file Xthat lacks the newline at the beginning, @command{diff} will report that a Xblank line has been added to the file, while @command{cmp} will report that Xalmost every byte of the two files differs. X X@command{diff3} normally compares three input files line by line, finds Xgroups of lines that differ, and reports each group of differing lines. XIts output is designed to make it easy to inspect two different sets of Xchanges to the same file. X X@menu X* Hunks:: Groups of differing lines. X* White Space:: Suppressing differences in white space. X* Blank Lines:: Suppressing differences in blank lines. X* Case Folding:: Suppressing differences in alphabetic case. X* Specified Folding:: Suppressing differences that match regular expressions. X* Brief:: Summarizing which files are different. X* Binary:: Comparing binary files or forcing text comparisons. X@end menu X X@node Hunks X@section Hunks X@cindex hunks X XWhen comparing two files, @command{diff} finds sequences of lines common to Xboth files, interspersed with groups of differing lines called X@dfn{hunks}. Comparing two identical files yields one sequence of Xcommon lines and no hunks, because no lines differ. Comparing two Xentirely different files yields no common lines and one large hunk that Xcontains all lines of both files. In general, there are many ways to Xmatch up lines between two given files. @command{diff} tries to minimize Xthe total hunk size by finding large sequences of common lines Xinterspersed with small hunks of differing lines. X XFor example, suppose the file @file{F} contains the three lines X@samp{a}, @samp{b}, @samp{c}, and the file @file{G} contains the same Xthree lines in reverse order @samp{c}, @samp{b}, @samp{a}. If X@command{diff} finds the line @samp{c} as common, then the command X@samp{diff F G} produces this output: X X@example X1,2d0 X< a X< b X3a2,3 X> b X> a X@end example X X@noindent XBut if @command{diff} notices the common line @samp{b} instead, it produces Xthis output: X X@example X1c1 X< a X--- X> c X3c3 X< c X--- X> a X@end example X X@noindent XIt is also possible to find @samp{a} as the common line. @command{diff} Xdoes not always find an optimal matching between the files; it takes Xshortcuts to run faster. But its output is usually close to the Xshortest possible. You can adjust this tradeoff with the X@option{--minimal} option (@pxref{diff Performance}). X X@node White Space X@section Suppressing Differences in Blank and Tab Spacing X@cindex blank and tab difference suppression X@cindex tab and blank difference suppression X XThe @option{-E} and @option{--ignore-tab-expansion} options ignore the Xdistinction between tabs and spaces on input. A tab is considered to be Xequivalent to the number of spaces to the next tab stop. @command{diff} Xassumes that tab stops are set every 8 print columns. X XThe @option{-b} and @option{--ignore-space-change} options are stronger. XThey ignore white space at line end, and consider all other sequences of Xone or more white space characters to be equivalent. With these Xoptions, @command{diff} considers the following two lines to be equivalent, Xwhere @samp{$} denotes the line end: X X@example XHere lyeth muche rychnesse in lytell space. -- John Heywood$ XHere lyeth muche rychnesse in lytell space. -- John Heywood $ X@end example X XThe @option{-w} and @option{--ignore-all-space} options are stronger still. XThey ignore difference even if one line has white space where Xthe other line has none. @dfn{White space} characters include Xtab, newline, vertical tab, form feed, carriage return, and space; Xsome locales may define additional characters to be white space. XWith these options, @command{diff} considers the Xfollowing two lines to be equivalent, where @samp{$} denotes the line Xend and @samp{^M} denotes a carriage return: X X@example XHere lyeth muche rychnesse in lytell space.-- John Heywood$ X He relyeth much erychnes seinly tells pace. --John Heywood ^M$ X@end example X X@node Blank Lines X@section Suppressing Differences in Blank Lines X@cindex blank line difference suppression X XThe @option{-B} and @option{--ignore-blank-lines} options ignore insertions Xor deletions of blank lines. These options affect only lines Xthat are completely empty; they do not affect lines that look empty but Xcontain space or tab characters. With these options, for example, a Xfile containing X@example X1. A point is that which has no part. X X2. A line is breadthless length. X-- Euclid, The Elements, I X@end example X@noindent Xis considered identical to a file containing X@example X1. A point is that which has no part. X2. A line is breadthless length. X X X-- Euclid, The Elements, I X@end example X X@node Case Folding X@section Suppressing Case Differences X@cindex case difference suppression X X@sc{gnu} @command{diff} can treat lower case letters as equivalent to their Xupper case counterparts, so that, for example, it considers @samp{Funky XStuff}, @samp{funky STUFF}, and @samp{fUNKy stuFf} to all be the same. XTo request this, use the @option{-i} or @option{--ignore-case} option. X X@node Specified Folding X@section Suppressing Lines Matching a Regular Expression X@cindex regular expression suppression X XTo ignore insertions and deletions of lines that match a X@command{grep}-style regular expression, use the @option{-I X@var{regexp}} or @option{--ignore-matching-lines=@var{regexp}} option. XYou should escape Xregular expressions that contain shell metacharacters to prevent the Xshell from expanding them. For example, @samp{diff -I '^[[:digit:]]'} ignores Xall changes to lines beginning with a digit. X XHowever, @option{-I} only ignores the insertion or deletion of lines that Xcontain the regular expression if every changed line in the hunk---every Xinsertion and every deletion---matches the regular expression. In other Xwords, for each nonignorable change, @command{diff} prints the complete set Xof changes in its vicinity, including the ignorable ones. X XYou can specify more than one regular expression for lines to ignore by Xusing more than one @option{-I} option. @command{diff} tries to match each Xline against each regular expression. X X@node Brief X@section Summarizing Which Files Differ X@cindex summarizing which files differ X@cindex brief difference reports X XWhen you only want to find out whether files are different, and you Xdon't care what the differences are, you can use the summary output Xformat. In this format, instead of showing the differences between the Xfiles, @command{diff} simply reports whether files differ. The @option{-q} Xand @option{--brief} options select this output format. X XThis format is especially useful when comparing the contents of two Xdirectories. It is also much faster than doing the normal line by line Xcomparisons, because @command{diff} can stop analyzing the files as soon as Xit knows that there are any differences. X XYou can also get a brief indication of whether two files differ by using X@command{cmp}. For files that are identical, @command{cmp} produces no Xoutput. When the files differ, by default, @command{cmp} outputs the byte Xand line number where the first difference occurs. You can use Xthe @option{-s} option to suppress that information, so that @command{cmp} Xproduces no output and reports whether the files differ using only its Xexit status (@pxref{Invoking cmp}). X X@c Fix this. XUnlike @command{diff}, @command{cmp} cannot compare directories; it can only Xcompare two files. X X@node Binary X@section Binary Files and Forcing Text Comparisons X@cindex binary file diff X@cindex text versus binary diff X XIf @command{diff} thinks that either of the two files it is comparing is Xbinary (a non-text file), it normally treats that pair of files much as Xif the summary output format had been selected (@pxref{Brief}), and Xreports only that the binary files are different. This is because line Xby line comparisons are usually not meaningful for binary files. X X@command{diff} determines whether a file is text or binary by checking the Xfirst few bytes in the file; the exact number of bytes is system Xdependent, but it is typically several thousand. If every byte in Xthat part of the file is non-null, @command{diff} considers the file to be Xtext; otherwise it considers the file to be binary. X XSometimes you might want to force @command{diff} to consider files to be Xtext. For example, you might be comparing text files that contain Xnull characters; @command{diff} would erroneously decide that those are Xnon-text files. Or you might be comparing documents that are in a Xformat used by a word processing system that uses null characters to Xindicate special formatting. You can force @command{diff} to consider all Xfiles to be text files, and compare them line by line, by using the X@option{-a} or @option{--text} option. If the files you compare using this Xoption do not in fact contain text, they will probably contain few Xnewline characters, and the @command{diff} output will consist of hunks Xshowing differences between long lines of whatever characters the files Xcontain. X XYou can also force @command{diff} to consider all files to be binary files, Xand report only whether they differ (but not how). Use the X@option{-q} or @option{--brief} option for this. X XDiffering binary files are considered to cause trouble because the Xresulting @command{diff} output does not capture all the differences. XThis trouble causes @command{diff} to exit with status 2. However, Xthis trouble cannot occur with the @option{--a} or @option{--text} Xoption, or with the @option{-q} or @option{--brief} option, as these Xoptions both cause @command{diff} to treat binary files like text Xfiles. X XIn operating systems that distinguish between text and binary files, X@command{diff} normally reads and writes all data as text. Use the X@option{--binary} option to force @command{diff} to read and write binary Xdata instead. This option has no effect on a @sc{posix}-compliant system Xlike @sc{gnu} or traditional Unix. However, many personal computer Xoperating systems represent the end of a line with a carriage return Xfollowed by a newline. On such systems, @command{diff} normally ignores Xthese carriage returns on input and generates them at the end of each Xoutput line, but with the @option{--binary} option @command{diff} treats Xeach carriage return as just another input character, and does not Xgenerate a carriage return at the end of each output line. This can be Xuseful when dealing with non-text files that are meant to be Xinterchanged with @sc{posix}-compliant systems. X XThe @option{--strip-trailing-cr} causes @command{diff} to treat input Xlines that end in carriage return followed by newline as if they end Xin plain newline. This can be useful when comparing text that is Ximperfectly imported from many personal computer operating systems. XThis option affects how lines are read, which in turn affects how they Xare compared and output. X XIf you want to compare two files byte by byte, you can use the X@command{cmp} program with the @option{-l} option to show the values Xof each differing byte in the two files. With @sc{gnu} @command{cmp}, Xyou can also use the @option{-b} option to show the @sc{ascii} Xrepresentation of those bytes. @xref{Invoking cmp}, for more Xinformation. X XIf @command{diff3} thinks that any of the files it is comparing is binary X(a non-text file), it normally reports an error, because such Xcomparisons are usually not useful. @command{diff3} uses the same test as X@command{diff} to decide whether a file is binary. As with @command{diff}, if Xthe input files contain a few non-text bytes but otherwise are like Xtext files, you can force @command{diff3} to consider all files to be text Xfiles and compare them line by line by using the @option{-a} or X@option{--text} options. X X@node Output Formats X@chapter @command{diff} Output Formats X@cindex output formats X@cindex format of @command{diff} output X X@command{diff} has several mutually exclusive options for output format. XThe following sections describe each format, illustrating how X@command{diff} reports the differences between two sample input files. X X@menu X* Sample diff Input:: Sample @command{diff} input files for examples. X* Normal:: Showing differences without surrounding text. X* Context:: Showing differences with the surrounding text. X* Side by Side:: Showing differences in two columns. X* Scripts:: Generating scripts for other programs. X* If-then-else:: Merging files with if-then-else. X@end menu X X@node Sample diff Input X@section Two Sample Input Files X@cindex @command{diff} sample input X@cindex sample input for @command{diff} X XHere are two sample files that we will use in numerous examples to Xillustrate the output of @command{diff} and how various options can change Xit. X XThis is the file @file{lao}: X X@example XThe Way that can be told of is not the eternal Way; XThe name that can be named is not the eternal name. XThe Nameless is the origin of Heaven and Earth; XThe Named is the mother of all things. XTherefore let there always be non-being, X so we may see their subtlety, XAnd let there always be being, X so we may see their outcome. XThe two are the same, XBut after they are produced, X they have different names. X@end example X XThis is the file @file{tzu}: X X@example XThe Nameless is the origin of Heaven and Earth; XThe named is the mother of all things. X XTherefore let there always be non-being, X so we may see their subtlety, XAnd let there always be being, X so we may see their outcome. XThe two are the same, XBut after they are produced, X they have different names. XThey both may be called deep and profound. XDeeper and more profound, XThe door of all subtleties! X@end example X XIn this example, the first hunk contains just the first two lines of X@file{lao}, the second hunk contains the fourth line of @file{lao} Xopposing the second and third lines of @file{tzu}, and the last hunk Xcontains just the last three lines of @file{tzu}. X X@node Normal X@section Showing Differences Without Context X@cindex normal output format X@cindex @samp{<} output format X XThe ``normal'' @command{diff} output format shows each hunk of differences Xwithout any surrounding context. Sometimes such output is the clearest Xway to see how lines have changed, without the clutter of nearby Xunchanged lines (although you can get similar results with the context Xor unified formats by using 0 lines of context). However, this format Xis no longer widely used for sending out patches; for that purpose, the Xcontext format (@pxref{Context Format}) and the unified format X(@pxref{Unified Format}) are superior. Normal format is the default for Xcompatibility with older versions of @command{diff} and the @sc{posix} Xstandard. Use the @option{--normal} option to select this output Xformat explicitly. X X@menu X* Detailed Normal:: A detailed description of normal output format. X* Example Normal:: Sample output in the normal format. X@end menu X X@node Detailed Normal X@subsection Detailed Description of Normal Format X XThe normal output format consists of one or more hunks of differences; Xeach hunk shows one area where the files differ. Normal format hunks Xlook like this: X X@example X@var{change-command} X< @var{from-file-line} X< @var{from-file-line}@dots{} X--- X> @var{to-file-line} X> @var{to-file-line}@dots{} X@end example X XThere are three types of change commands. Each consists of a line Xnumber or comma-separated range of lines in the first file, a single Xcharacter indicating the kind of change to make, and a line number or Xcomma-separated range of lines in the second file. All line numbers are Xthe original line numbers in each file. The types of change commands Xare: X X@table @samp X@item @var{l}a@var{r} XAdd the lines in range @var{r} of the second file after line @var{l} of Xthe first file. For example, @samp{8a12,15} means append lines 12--15 Xof file 2 after line 8 of file 1; or, if changing file 2 into file 1, Xdelete lines 12--15 of file 2. X X@item @var{f}c@var{t} XReplace the lines in range @var{f} of the first file with lines in range X@var{t} of the second file. This is like a combined add and delete, but Xmore compact. For example, @samp{5,7c8,10} means change lines 5--7 of Xfile 1 to read as lines 8--10 of file 2; or, if changing file 2 into Xfile 1, change lines 8--10 of file 2 to read as lines 5--7 of file 1. X X@item @var{r}d@var{l} XDelete the lines in range @var{r} from the first file; line @var{l} is where Xthey would have appeared in the second file had they not been deleted. XFor example, @samp{5,7d3} means delete lines 5--7 of file 1; or, if Xchanging file 2 into file 1, append lines 5--7 of file 1 after line 3 of Xfile 2. X@end table X X@node Example Normal X@subsection An Example of Normal Format X XHere is the output of the command @samp{diff lao tzu} X(@pxref{Sample diff Input}, for the complete contents of the two files). XNotice that it shows only the lines that are different between the two Xfiles. X X@example X1,2d0 X< The Way that can be told of is not the eternal Way; X< The name that can be named is not the eternal name. X4c2,3 X< The Named is the mother of all things. X--- X> The named is the mother of all things. X> X11a11,13 X> They both may be called deep and profound. X> Deeper and more profound, X> The door of all subtleties! X@end example X X@node Context X@section Showing Differences in Their Context X@cindex context output format X@cindex @samp{!} output format X XUsually, when you are looking at the differences between files, you will Xalso want to see the parts of the files near the lines that differ, to Xhelp you understand exactly what has changed. These nearby parts of the Xfiles are called the @dfn{context}. X X@sc{gnu} @command{diff} provides two output formats that show context Xaround the differing lines: @dfn{context format} and @dfn{unified Xformat}. It can optionally show in which function or section of the Xfile the differing lines are found. X XIf you are distributing new versions of files to other people in the Xform of @command{diff} output, you should use one of the output formats Xthat show context so that they can apply the diffs even if they have Xmade small changes of their own to the files. @command{patch} can apply Xthe diffs in this case by searching in the files for the lines of Xcontext around the differing lines; if those lines are actually a few Xlines away from where the diff says they are, @command{patch} can adjust Xthe line numbers accordingly and still apply the diff correctly. X@xref{Imperfect}, for more information on using @command{patch} to apply Ximperfect diffs. X X@menu X* Context Format:: An output format that shows surrounding lines. X* Unified Format:: A more compact output format that shows context. X* Sections:: Showing which sections of the files differences are in. X* Alternate Names:: Showing alternate file names in context headers. X@end menu X X@node Context Format X@subsection Context Format X XThe context output format shows several lines of context around the Xlines that differ. It is the standard format for distributing updates Xto source code. X XTo select this output format, use the @option{-C @var{lines}}, X@option{--context@r{[}=@var{lines}@r{]}}, or @option{-c} option. The Xargument @var{lines} that some of these options take is the number of Xlines of context to show. If you do not specify @var{lines}, it Xdefaults to three. For proper operation, @command{patch} typically needs Xat least two lines of context. X X@menu X* Detailed Context:: A detailed description of the context output format. X* Example Context:: Sample output in context format. X* Less Context:: Another sample with less context. X@end menu X X@node Detailed Context X@subsubsection Detailed Description of Context Format X XThe context output format starts with a two-line header, which looks Xlike this: X X@example X*** @var{from-file} @var{from-file-modification-time} X--- @var{to-file} @var{to-file-modification time} X@end example X X@noindent X@vindex LC_TIME X@cindex time stamp format, context diffs XThe time stamp normally looks like @samp{2002-02-21 23:30:39.942229878 X-0800} to indicate the date, time with fractional seconds, and time Xzone in @uref{ftp://ftp.isi.edu/in-notes/rfc2822.txt, Internet RFC X2822 format}. However, a traditional time stamp like @samp{Thu Feb 21 X23:30:39 2002} is used if the @env{LC_TIME} locale category is either X@samp{C} or @samp{POSIX}. X XYou can change the header's content with the X@option{--label=@var{label}} option; see @ref{Alternate Names}. X XNext come one or more hunks of differences; each hunk shows one area Xwhere the files differ. Context format hunks look like this: X X@example X*************** X*** @var{from-file-line-range} **** X @var{from-file-line} X @var{from-file-line}@dots{} X--- @var{to-file-line-range} ---- X @var{to-file-line} X @var{to-file-line}@dots{} X@end example X XThe lines of context around the lines that differ start with two space Xcharacters. The lines that differ between the two files start with one Xof the following indicator characters, followed by a space character: X X@table @samp X@item ! XA line that is part of a group of one or more lines that changed between Xthe two files. There is a corresponding group of lines marked with X@samp{!} in the part of this hunk for the other file. X X@item + XAn ``inserted'' line in the second file that corresponds to nothing in Xthe first file. X X@item - XA ``deleted'' line in the first file that corresponds to nothing in the Xsecond file. X@end table X XIf all of the changes in a hunk are insertions, the lines of X@var{from-file} are omitted. If all of the changes are deletions, the Xlines of @var{to-file} are omitted. X X@node Example Context X@subsubsection An Example of Context Format X XHere is the output of @samp{diff -c lao tzu} (@pxref{Sample diff Input}, Xfor the complete contents of the two files). Notice that up to three Xlines that are not different are shown around each line that is Xdifferent; they are the context lines. Also notice that the first two Xhunks have run together, because their contents overlap. X X@example X*** lao 2002-02-21 23:30:39.942229878 -0800 X--- tzu 2002-02-21 23:30:50.442260588 -0800 X*************** X*** 1,7 **** X- The Way that can be told of is not the eternal Way; X- The name that can be named is not the eternal name. X The Nameless is the origin of Heaven and Earth; X! The Named is the mother of all things. X Therefore let there always be non-being, X so we may see their subtlety, X And let there always be being, X--- 1,6 ---- X The Nameless is the origin of Heaven and Earth; X! The named is the mother of all things. X! X Therefore let there always be non-being, X so we may see their subtlety, X And let there always be being, X*************** X*** 9,11 **** X--- 8,13 ---- X The two are the same, X But after they are produced, X they have different names. X+ They both may be called deep and profound. X+ Deeper and more profound, X+ The door of all subtleties! X@end example X X@node Less Context X@subsubsection An Example of Context Format with Less Context X XHere is the output of @samp{diff -C 1 lao tzu} (@pxref{Sample diff XInput}, for the complete contents of the two files). Notice that at Xmost one context line is reported here. X X@example X*** lao 2002-02-21 23:30:39.942229878 -0800 X--- tzu 2002-02-21 23:30:50.442260588 -0800 X*************** X*** 1,5 **** X- The Way that can be told of is not the eternal Way; X- The name that can be named is not the eternal name. X The Nameless is the origin of Heaven and Earth; X! The Named is the mother of all things. X Therefore let there always be non-being, X--- 1,4 ---- X The Nameless is the origin of Heaven and Earth; X! The named is the mother of all things. X! X Therefore let there always be non-being, X*************** X*** 11 **** X--- 10,13 ---- X they have different names. X+ They both may be called deep and profound. X+ Deeper and more profound, X+ The door of all subtleties! X@end example X X@node Unified Format X@subsection Unified Format X@cindex unified output format X@cindex @samp{+-} output format X XThe unified output format is a variation on the context format that is Xmore compact because it omits redundant context lines. To select this Xoutput format, use the @option{-U @var{lines}}, X@option{--unified@r{[}=@var{lines}@r{]}}, or @option{-u} Xoption. The argument @var{lines} is the number of lines of context to Xshow. When it is not given, it defaults to three. X XAt present, only @sc{gnu} @command{diff} can produce this format and Xonly @sc{gnu} @command{patch} can automatically apply diffs in this Xformat. For proper operation, @command{patch} typically needs at Xleast three lines of context. X X@menu X* Detailed Unified:: A detailed description of unified format. X* Example Unified:: Sample output in unified format. X@end menu X X@node Detailed Unified X@subsubsection Detailed Description of Unified Format X XThe unified output format starts with a two-line header, which looks Xlike this: X X@example X--- @var{from-file} @var{from-file-modification-time} X+++ @var{to-file} @var{to-file-modification-time} X@end example X X@noindent X@cindex time stamp format, unified diffs XThe time stamp looks like @samp{2002-02-21 23:30:39.942229878 -0800} Xto indicate the date, time with fractional seconds, and time zone. X XYou can change the header's content with the X@option{--label=@var{label}} option; see @xref{Alternate Names}. X XNext come one or more hunks of differences; each hunk shows one area Xwhere the files differ. Unified format hunks look like this: X X@example X@@@@ @var{from-file-range} @var{to-file-range} @@@@ X @var{line-from-either-file} X @var{line-from-either-file}@dots{} X@end example X XThe lines common to both files begin with a space character. The lines Xthat actually differ between the two files have one of the following Xindicator characters in the left print column: X X@table @samp X@item + XA line was added here to the first file. X X@item - XA line was removed here from the first file. X@end table X X@node Example Unified X@subsubsection An Example of Unified Format X XHere is the output of the command @samp{diff -u lao tzu} X(@pxref{Sample diff Input}, for the complete contents of the two files): X X@example X--- lao 2002-02-21 23:30:39.942229878 -0800 X+++ tzu 2002-02-21 23:30:50.442260588 -0800 X@@@@ -1,7 +1,6 @@@@ X-The Way that can be told of is not the eternal Way; X-The name that can be named is not the eternal name. X The Nameless is the origin of Heaven and Earth; X-The Named is the mother of all things. X+The named is the mother of all things. X+ X Therefore let there always be non-being, X so we may see their subtlety, X And let there always be being, X@@@@ -9,3 +8,6 @@@@ X The two are the same, X But after they are produced, X they have different names. X+They both may be called deep and profound. X+Deeper and more profound, X+The door of all subtleties! X@end example X X@node Sections X@subsection Showing Which Sections Differences Are in X@cindex headings X@cindex section headings X XSometimes you might want to know which part of the files each change Xfalls in. If the files are source code, this could mean which function Xwas changed. If the files are documents, it could mean which chapter or Xappendix was changed. @sc{gnu} @command{diff} can show this by displaying the Xnearest section heading line that precedes the differing lines. Which Xlines are ``section headings'' is determined by a regular expression. X X@menu X* Specified Headings:: Showing headings that match regular expressions. X* C Function Headings:: Showing headings of C functions. X@end menu X X@node Specified Headings X@subsubsection Showing Lines That Match Regular Expressions X@cindex specified headings X@cindex regular expression matching headings X XTo show in which sections differences occur for files that are not Xsource code for C or similar languages, use the @option{-F @var{regexp}} Xor @option{--show-function-line=@var{regexp}} option. @command{diff} Xconsiders lines that match the @command{grep}-style regular expression X@var{regexp} to be the beginning Xof a section of the file. Here are suggested regular expressions for Xsome common languages: X X@c Please add to this list, e.g. Fortran, Pascal, Perl, Python. X@table @samp X@item ^[[:alpha:]$_] XC, C++, Prolog X@item ^( XLisp X@item ^@@node XTexinfo X@end table X XThis option does not automatically select an output format; in order to Xuse it, you must select the context format (@pxref{Context Format}) or Xunified format (@pxref{Unified Format}). In other output formats it Xhas no effect. X XThe @option{-F} and @option{--show-function-line} options find the nearest Xunchanged line that precedes each hunk of differences and matches the Xgiven regular expression. Then they add that line to the end of the Xline of asterisks in the context format, or to the @samp{@@@@} line in Xunified format. If no matching line exists, they leave the output for Xthat hunk unchanged. If that line is more than 40 characters long, they Xoutput only the first 40 characters. You can specify more than one Xregular expression for such lines; @command{diff} tries to match each line Xagainst each regular expression, starting with the last one given. This Xmeans that you can use @option{-p} and @option{-F} together, if you wish. X X@node C Function Headings X@subsubsection Showing C Function Headings X@cindex C function headings X@cindex function headings, C X XTo show in which functions differences occur for C and similar Xlanguages, you can use the @option{-p} or @option{--show-c-function} option. XThis option automatically defaults to the context output format X(@pxref{Context Format}), with the default number of lines of context. XYou can override that number with @option{-C @var{lines}} elsewhere in the Xcommand line. You can override both the format and the number with X@option{-U @var{lines}} elsewhere in the command line. X XThe @option{-p} and @option{--show-c-function} options are equivalent to X@option{-F '^[[:alpha:]$_]'} if the unified format is specified, otherwise X@option{-c -F '^[[:alpha:]$_]'} (@pxref{Specified Headings}). @sc{gnu} X@command{diff} provides them for the sake of convenience. X X@node Alternate Names X@subsection Showing Alternate File Names X@cindex alternate file names X@cindex file name alternates X XIf you are comparing two files that have meaningless or uninformative Xnames, you might want @command{diff} to show alternate names in the header Xof the context and unified output formats. To do this, use the X@option{--label=@var{label}} option. The first time Xyou give this option, its argument replaces the name and date of the Xfirst file in the header; the second time, its argument replaces the Xname and date of the second file. If you give this option more than Xtwice, @command{diff} reports an error. The @option{--label} option does not Xaffect the file names in the @command{pr} header when the @option{-l} or X@option{--paginate} option is used (@pxref{Pagination}). X XHere are the first two lines of the output from @samp{diff -C 2 X--label=original --label=modified lao tzu}: X X@example X*** original X--- modified X@end example X X@node Side by Side X@section Showing Differences Side by Side X@cindex side by side X@cindex two-column output X@cindex columnar output X X@command{diff} can produce a side by side difference listing of two files. XThe files are listed in two columns with a gutter between them. The Xgutter contains one of the following markers: X X@table @asis X@item white space XThe corresponding lines are in common. That is, either the lines are Xidentical, or the difference is ignored because of one of the X@option{--ignore} options (@pxref{White Space}). X X@item @samp{|} XThe corresponding lines differ, and they are either both complete Xor both incomplete. X X@item @samp{<} XThe files differ and only the first file contains the line. X X@item @samp{>} XThe files differ and only the second file contains the line. X X@item @samp{(} XOnly the first file contains the line, but the difference is ignored. X X@item @samp{)} XOnly the second file contains the line, but the difference is ignored. X X@item @samp{\} XThe corresponding lines differ, and only the first line is incomplete. X X@item @samp{/} XThe corresponding lines differ, and only the second line is incomplete. X@end table X XNormally, an output line is incomplete if and only if the lines that it Xcontains are incomplete; @xref{Incomplete Lines}. However, when an Xoutput line represents two differing lines, one might be incomplete Xwhile the other is not. In this case, the output line is complete, Xbut its the gutter is marked @samp{\} if the first line is incomplete, X@samp{/} if the second line is. X XSide by side format is sometimes easiest to read, but it has limitations. XIt generates much wider output than usual, and truncates lines that are Xtoo long to fit. Also, it relies on lining up output more heavily than Xusual, so its output looks particularly bad if you use varying Xwidth fonts, nonstandard tab stops, or nonprinting characters. X XYou can use the @command{sdiff} command to interactively merge side by side Xdifferences. @xref{Interactive Merging}, for more information on merging files. X X@menu X* Side by Side Format:: Controlling side by side output format. X* Example Side by Side:: Sample side by side output. X@end menu X X@node Side by Side Format X@subsection Controlling Side by Side Format X@cindex side by side format X XThe @option{-y} or @option{--side-by-side} option selects side by side Xformat. Because side by side output lines contain two input lines, the Xoutput is wider than usual: normally 130 print columns, which can fit Xonto a traditional printer line. You can set the width of the output Xwith the @option{-W @var{columns}} or @option{--width=@var{columns}} Xoption. The output is split into two halves of equal width, separated by a Xsmall gutter to mark differences; the right half is aligned to a tab Xstop so that tabs line up. Input lines that are too long to fit in half Xof an output line are truncated for output. X XThe @option{--left-column} option prints only the left column of two Xcommon lines. The @option{--suppress-common-lines} option suppresses Xcommon lines entirely. X X@node Example Side by Side X@subsection An Example of Side by Side Format X XHere is the output of the command @samp{diff -y -W 72 lao tzu} X(@pxref{Sample diff Input}, for the complete contents of the two files). X X@example XThe Way that can be told of is n < XThe name that can be named is no < XThe Nameless is the origin of He The Nameless is the origin of He XThe Named is the mother of all t | The named is the mother of all t X > XTherefore let there always be no Therefore let there always be no X so we may see their subtlety, so we may see their subtlety, XAnd let there always be being, And let there always be being, X so we may see their outcome. so we may see their outcome. XThe two are the same, The two are the same, XBut after they are produced, But after they are produced, X they have different names. they have different names. X > They both may be called deep and X > Deeper and more profound, X > The door of all subtleties! X@end example X X@node Scripts X@section Making Edit Scripts X@cindex script output formats X XSeveral output modes produce command scripts for editing @var{from-file} Xto produce @var{to-file}. X X@menu X* ed Scripts:: Using @command{diff} to produce commands for @command{ed}. X* Forward ed:: Making forward @command{ed} scripts. X* RCS:: A special @command{diff} output format used by @sc{rcs}. X@end menu X X@node ed Scripts X@subsection @command{ed} Scripts X@cindex @command{ed} script output format X X@command{diff} can produce commands that direct the @command{ed} text editor Xto change the first file into the second file. Long ago, this was the Xonly output mode that was suitable for editing one file into another Xautomatically; today, with @command{patch}, it is almost obsolete. Use the X@option{-e} or @option{--ed} option to select this output format. X XLike the normal format (@pxref{Normal}), this output format does not Xshow any context; unlike the normal format, it does not include the Xinformation necessary to apply the diff in reverse (to produce the first Xfile if all you have is the second file and the diff). X XIf the file @file{d} contains the output of @samp{diff -e old new}, then Xthe command @samp{(cat d && echo w) | ed - old} edits @file{old} to make Xit a copy of @file{new}. More generally, if @file{d1}, @file{d2}, X@dots{}, @file{dN} contain the outputs of @samp{diff -e old new1}, X@samp{diff -e new1 new2}, @dots{}, @samp{diff -e newN-1 newN}, Xrespectively, then the command @samp{(cat d1 d2 @dots{} dN && echo w) | Xed - old} edits @file{old} to make it a copy of @file{newN}. X X@menu X* Detailed ed:: A detailed description of @command{ed} format. X* Example ed:: A sample @command{ed} script. X@end menu X X@node Detailed ed X@subsubsection Detailed Description of @command{ed} Format X XThe @command{ed} output format consists of one or more hunks of Xdifferences. The changes closest to the ends of the files come first so Xthat commands that change the number of lines do not affect how X@command{ed} interprets line numbers in succeeding commands. @command{ed} Xformat hunks look like this: X X@example X@var{change-command} X@var{to-file-line} X@var{to-file-line}@dots{} X. X@end example X XBecause @command{ed} uses a single period on a line to indicate the end of Xinput, @sc{gnu} @command{diff} protects lines of changes that contain a single Xperiod on a line by writing two periods instead, then writing a Xsubsequent @command{ed} command to change the two periods into one. The X@command{ed} format cannot represent an incomplete line, so if the second Xfile ends in a changed incomplete line, @command{diff} reports an error and Xthen pretends that a newline was appended. X XThere are three types of change commands. Each consists of a line Xnumber or comma-separated range of lines in the first file and a single Xcharacter indicating the kind of change to make. All line numbers are Xthe original line numbers in the file. The types of change commands Xare: X X@table @samp X@item @var{l}a XAdd text from the second file after line @var{l} in the first file. For Xexample, @samp{8a} means to add the following lines after line 8 of file X1. X X@item @var{r}c XReplace the lines in range @var{r} in the first file with the following Xlines. Like a combined add and delete, but more compact. For example, X@samp{5,7c} means change lines 5--7 of file 1 to read as the text file X2. X X@item @var{r}d XDelete the lines in range @var{r} from the first file. For example, X@samp{5,7d} means delete lines 5--7 of file 1. X@end table X X@node Example ed X@subsubsection Example @command{ed} Script X XHere is the output of @samp{diff -e lao tzu} (@pxref{Sample Xdiff Input}, for the complete contents of the two files): X X@example X11a XThey both may be called deep and profound. XDeeper and more profound, XThe door of all subtleties! X. X4c XThe named is the mother of all things. X X. X1,2d X@end example X X@node Forward ed X@subsection Forward @command{ed} Scripts X@cindex forward @command{ed} script output format X X@command{diff} can produce output that is like an @command{ed} script, but Xwith hunks in forward (front to back) order. The format of the commands Xis also changed slightly: command characters precede the lines they Xmodify, spaces separate line numbers in ranges, and no attempt is made Xto disambiguate hunk lines consisting of a single period. Like X@command{ed} format, forward @command{ed} format cannot represent incomplete Xlines. X XForward @command{ed} format is not very useful, because neither @command{ed} Xnor @command{patch} can apply diffs in this format. It exists mainly for Xcompatibility with older versions of @command{diff}. Use the @option{-f} or X@option{--forward-ed} option to select it. X X@node RCS X@subsection @sc{rcs} Scripts X@cindex @sc{rcs} script output format X XThe @sc{rcs} output format is designed specifically for use by the Revision XControl System, which is a set of free programs used for organizing Xdifferent versions and systems of files. Use the @option{-n} or X@option{--rcs} option to select this output format. It is like the Xforward @command{ed} format (@pxref{Forward ed}), but it can represent Xarbitrary changes to the contents of a file because it avoids the Xforward @command{ed} format's problems with lines consisting of a single Xperiod and with incomplete lines. Instead of ending text sections with Xa line consisting of a single period, each command specifies the number Xof lines it affects; a combination of the @samp{a} and @samp{d} Xcommands are used instead of @samp{c}. Also, if the second file ends Xin a changed incomplete line, then the output also ends in an Xincomplete line. X XHere is the output of @samp{diff -n lao tzu} (@pxref{Sample Xdiff Input}, for the complete contents of the two files): X X@example Xd1 2 Xd4 1 Xa4 2 XThe named is the mother of all things. X Xa11 3 XThey both may be called deep and profound. XDeeper and more profound, XThe door of all subtleties! X@end example X X@node If-then-else X@section Merging Files with If-then-else X@cindex merged output format X@cindex if-then-else output format X@cindex C if-then-else output format X@cindex @command{ifdef} output format X XYou can use @command{diff} to merge two files of C source code. The output Xof @command{diff} in this format contains all the lines of both files. XLines common to both files are output just once; the differing parts are Xseparated by the C preprocessor directives @code{#ifdef @var{name}} or X@code{#ifndef @var{name}}, @code{#else}, and @code{#endif}. When Xcompiling the output, you select which version to use by either defining Xor leaving undefined the macro @var{name}. X XTo merge two files, use @command{diff} with the @option{-D @var{name}} or X@option{--ifdef=@var{name}} option. The argument @var{name} is the C Xpreprocessor identifier to use in the @code{#ifdef} and @code{#ifndef} Xdirectives. X XFor example, if you change an instance of @code{wait (&s)} to X@code{waitpid (-1, &s, 0)} and then merge the old and new files with Xthe @option{--ifdef=HAVE_WAITPID} option, then the affected part of your code Xmight look like this: X X@example X do @{ X#ifndef HAVE_WAITPID X if ((w = wait (&s)) < 0 && errno != EINTR) X#else /* HAVE_WAITPID */ X if ((w = waitpid (-1, &s, 0)) < 0 && errno != EINTR) X#endif /* HAVE_WAITPID */ X return w; X @} while (w != child); X@end example X XYou can specify formats for languages other than C by using line group Xformats and line formats, as described in the next sections. X X@menu X* Line Group Formats:: Formats for general if-then-else line groups. X* Line Formats:: Formats for each line in a line group. X* Detailed If-then-else:: A detailed description of if-then-else format. X* Example If-then-else:: Sample if-then-else format output. X@end menu X X@node Line Group Formats X@subsection Line Group Formats X@cindex line group formats X@cindex formats for if-then-else line groups X XLine group formats let you specify formats suitable for many Xapplications that allow if-then-else input, including programming Xlanguages and text formatting languages. A line group format specifies Xthe output format for a contiguous group of similar lines. X XFor example, the following command compares the TeX files @file{old} Xand @file{new}, and outputs a merged file in which old regions are Xsurrounded by @samp{\begin@{em@}}-@samp{\end@{em@}} lines, and new Xregions are surrounded by @samp{\begin@{bf@}}-@samp{\end@{bf@}} lines. X X@example Xdiff \ X --old-group-format='\begin@{em@} X%<\end@{em@} X' \ X --new-group-format='\begin@{bf@} X%>\end@{bf@} X' \ X old new X@end example X XThe following command is equivalent to the above example, but it is a Xlittle more verbose, because it spells out the default line group formats. X X@example Xdiff \ X --old-group-format='\begin@{em@} X%<\end@{em@} X' \ X --new-group-format='\begin@{bf@} X%>\end@{bf@} X' \ X --unchanged-group-format='%=' \ X --changed-group-format='\begin@{em@} X%<\end@{em@} X\begin@{bf@} X%>\end@{bf@} X' \ X old new X@end example X XHere is a more advanced example, which outputs a diff listing with Xheaders containing line numbers in a ``plain English'' style. X X@example Xdiff \ X --unchanged-group-format='' \ X --old-group-format='-------- %dn line%(n=1?:s) deleted at %df: X%<' \ X --new-group-format='-------- %dN line%(N=1?:s) added after %de: X%>' \ X --changed-group-format='-------- %dn line%(n=1?:s) changed at %df: X%<-------- to: X%>' \ X old new X@end example X XTo specify a line group format, use @command{diff} with one of the options Xlisted below. You can specify up to four line group formats, one for Xeach kind of line group. You should quote @var{format}, because it Xtypically contains shell metacharacters. X X@table @option X@item --old-group-format=@var{format} XThese line groups are hunks containing only lines from the first file. XThe default old group format is the same as the changed group format if Xit is specified; otherwise it is a format that outputs the line group as-is. X X@item --new-group-format=@var{format} XThese line groups are hunks containing only lines from the second Xfile. The default new group format is same as the changed group Xformat if it is specified; otherwise it is a format that outputs the Xline group as-is. X X@item --changed-group-format=@var{format} XThese line groups are hunks containing lines from both files. The Xdefault changed group format is the concatenation of the old and new Xgroup formats. X X@item --unchanged-group-format=@var{format} XThese line groups contain lines common to both files. The default Xunchanged group format is a format that outputs the line group as-is. X@end table X XIn a line group format, ordinary characters represent themselves; Xconversion specifications start with @samp{%} and have one of the Xfollowing forms. X X@table @samp X@item %< Xstands for the lines from the first file, including the trailing newline. XEach line is formatted according to the old line format (@pxref{Line Formats}). X X@item %> Xstands for the lines from the second file, including the trailing newline. XEach line is formatted according to the new line format. X X@item %= Xstands for the lines common to both files, including the trailing newline. XEach line is formatted according to the unchanged line format. X X@item %% Xstands for @samp{%}. X X@item %c'@var{C}' Xwhere @var{C} is a single character, stands for @var{C}. X@var{C} may not be a backslash or an apostrophe. XFor example, @samp{%c':'} stands for a colon, even inside Xthe then-part of an if-then-else format, which a colon would Xnormally terminate. X X@item %c'\@var{O}' Xwhere @var{O} is a string of 1, 2, or 3 octal digits, Xstands for the character with octal code @var{O}. XFor example, @samp{%c'\0'} stands for a null character. X X@item @var{F}@var{n} Xwhere @var{F} is a @code{printf} conversion specification and @var{n} is one Xof the following letters, stands for @var{n}'s value formatted with @var{F}. X X@table @samp X@item e XThe line number of the line just before the group in the old file. X X@item f XThe line number of the first line in the group in the old file; Xequals @var{e} + 1. X X@item l XThe line number of the last line in the group in the old file. X X@item m XThe line number of the line just after the group in the old file; Xequals @var{l} + 1. X X@item n XThe number of lines in the group in the old file; equals @var{l} - @var{f} + 1. X X@item E, F, L, M, N XLikewise, for lines in the new file. X X@end table X X@vindex LC_NUMERIC XThe @code{printf} conversion specification can be @samp{%d}, X@samp{%o}, @samp{%x}, or @samp{%X}, specifying decimal, octal, Xlower case hexadecimal, or upper case hexadecimal output Xrespectively. After the @samp{%} the following options can appear in Xsequence: a series of zero or more flags; an integer Xspecifying the minimum field width; and a period followed by an Xoptional integer specifying the minimum number of digits. XThe flags are @samp{-} for left-justification, @samp{'} for separating Xthe digit into groups as specified by the @env{LC_NUMERIC} locale category, Xand @samp{0} for padding with zeros instead of spaces. XFor example, @samp{%5dN} prints the number of new lines in the group Xin a field of width 5 characters, using the @code{printf} format @code{"%5d"}. X X@item (@var{A}=@var{B}?@var{T}:@var{E}) XIf @var{A} equals @var{B} then @var{T} else @var{E}. X@var{A} and @var{B} are each either a decimal constant Xor a single letter interpreted as above. XThis format spec is equivalent to @var{T} if X@var{A}'s value equals @var{B}'s; otherwise it is equivalent to @var{E}. X XFor example, @samp{%(N=0?no:%dN) line%(N=1?:s)} is equivalent to X@samp{no lines} if @var{N} (the number of lines in the group in the the Xnew file) is 0, to @samp{1 line} if @var{N} is 1, and to @samp{%dN lines} Xotherwise. X@end table X X@node Line Formats X@subsection Line Formats X@cindex line formats X XLine formats control how each line taken from an input file is Xoutput as part of a line group in if-then-else format. X XFor example, the following command outputs text with a one-character Xchange indicator to the left of the text. The first character of output Xis @samp{-} for deleted lines, @samp{|} for added lines, and a space for Xunchanged lines. The formats contain newline characters where newlines Xare desired on output. X X@example Xdiff \ X --old-line-format='-%l X' \ X --new-line-format='|%l X' \ X --unchanged-line-format=' %l X' \ X old new X@end example X XTo specify a line format, use one of the following options. You should Xquote @var{format}, since it often contains shell metacharacters. X X@table @option X@item --old-line-format=@var{format} Xformats lines just from the first file. X X@item --new-line-format=@var{format} Xformats lines just from the second file. X X@item --unchanged-line-format=@var{format} Xformats lines common to both files. X X@item --line-format=@var{format} Xformats all lines; in effect, it sets all three above options simultaneously. X@end table X XIn a line format, ordinary characters represent themselves; Xconversion specifications start with @samp{%} and have one of the Xfollowing forms. X X@table @samp X@item %l Xstands for the contents of the line, not counting its trailing Xnewline (if any). This format ignores whether the line is incomplete; X@xref{Incomplete Lines}. X X@item %L Xstands for the contents of the line, including its trailing newline X(if any). If a line is incomplete, this format preserves its Xincompleteness. X X@item %% Xstands for @samp{%}. X X@item %c'@var{C}' Xwhere @var{C} is a single character, stands for @var{C}. X@var{C} may not be a backslash or an apostrophe. XFor example, @samp{%c':'} stands for a colon. X X@item %c'\@var{O}' Xwhere @var{O} is a string of 1, 2, or 3 octal digits, Xstands for the character with octal code @var{O}. XFor example, @samp{%c'\0'} stands for a null character. X X@item @var{F}n Xwhere @var{F} is a @code{printf} conversion specification, Xstands for the line number formatted with @var{F}. XFor example, @samp{%.5dn} prints the line number using the X@code{printf} format @code{"%.5d"}. @xref{Line Group Formats}, for Xmore about printf conversion specifications. X X@end table X XThe default line format is @samp{%l} followed by a newline character. X XIf the input contains tab characters and it is important that they line Xup on output, you should ensure that @samp{%l} or @samp{%L} in a line Xformat is just after a tab stop (e.g.@: by preceding @samp{%l} or X@samp{%L} with a tab character), or you should use the @option{-t} or X@option{--expand-tabs} option. X XTaken together, the line and line group formats let you specify many Xdifferent formats. For example, the following command uses a format Xsimilar to normal @command{diff} format. You can tailor this command Xto get fine control over @command{diff} output. X X@example Xdiff \ X --old-line-format='< %l X' \ X --new-line-format='> %l X' \ X --old-group-format='%df%(f=l?:,%dl)d%dE X%<' \ X --new-group-format='%dea%dF%(F=L?:,%dL) X%>' \ X --changed-group-format='%df%(f=l?:,%dl)c%dF%(F=L?:,%dL) X%<--- X%>' \ X --unchanged-group-format='' \ X old new X@end example X X@node Detailed If-then-else X@subsection Detailed Description of If-then-else Format X XFor lines common to both files, @command{diff} uses the unchanged line Xgroup format. For each hunk of differences in the merged output Xformat, if the hunk contains only lines from the first file, X@command{diff} uses the old line group format; if the hunk contains only Xlines from the second file, @command{diff} uses the new group format; Xotherwise, @command{diff} uses the changed group format. X XThe old, new, and unchanged line formats specify the output format of Xlines from the first file, lines from the second file, and lines common Xto both files, respectively. X XThe option @option{--ifdef=@var{name}} is equivalent to Xthe following sequence of options using shell syntax: X X@example X--old-group-format='#ifndef @var{name} X%<#endif /* ! @var{name} */ X' \ X--new-group-format='#ifdef @var{name} X%>#endif /* @var{name} */ X' \ X--unchanged-group-format='%=' \ X--changed-group-format='#ifndef @var{name} X%<#else /* @var{name} */ X%>#endif /* @var{name} */ X' X@end example X XYou should carefully check the @command{diff} output for proper nesting. XFor example, when using the @option{-D @var{name}} or X@option{--ifdef=@var{name}} option, you should check that if the Xdiffering lines contain any of the C preprocessor directives X@samp{#ifdef}, @samp{#ifndef}, @samp{#else}, @samp{#elif}, or X@samp{#endif}, they are nested properly and match. If they don't, you Xmust make corrections manually. It is a good idea to carefully check Xthe resulting code anyway to make sure that it really does what you Xwant it to; depending on how the input files were produced, the output Xmight contain duplicate or otherwise incorrect code. X XThe @command{patch} @option{-D @var{name}} option behaves like Xthe @command{diff} @option{-D @var{name}} option, except it operates on Xa file and a diff to produce a merged file; @xref{patch Options}. X X@node Example If-then-else X@subsection An Example of If-then-else Format X XHere is the output of @samp{diff -DTWO lao tzu} (@pxref{Sample Xdiff Input}, for the complete contents of the two files): X X@example X#ifndef TWO XThe Way that can be told of is not the eternal Way; XThe name that can be named is not the eternal name. X#endif /* ! TWO */ XThe Nameless is the origin of Heaven and Earth; X#ifndef TWO XThe Named is the mother of all things. X#else /* TWO */ XThe named is the mother of all things. X X#endif /* TWO */ XTherefore let there always be non-being, X so we may see their subtlety, XAnd let there always be being, X so we may see their outcome. XThe two are the same, XBut after they are produced, X they have different names. X#ifdef TWO XThey both may be called deep and profound. XDeeper and more profound, XThe door of all subtleties! X#endif /* TWO */ X@end example X X@node Incomplete Lines X@chapter Incomplete Lines X@cindex incomplete lines X@cindex full lines X@cindex newline treatment by @command{diff} X XWhen an input file ends in a non-newline character, its last line is Xcalled an @dfn{incomplete line} because its last character is not a Xnewline. All other lines are called @dfn{full lines} and end in a Xnewline character. Incomplete lines do not match full lines unless Xdifferences in white space are ignored (@pxref{White Space}). X XAn incomplete line is normally distinguished on output from a full line Xby a following line that starts with @samp{\}. However, the @sc{rcs} format X(@pxref{RCS}) outputs the incomplete line as-is, without any trailing Xnewline or following line. The side by side format normally represents Xincomplete lines as-is, but in some cases uses a @samp{\} or @samp{/} Xgutter marker; @xref{Side by Side}. The if-then-else line format Xpreserves a line's incompleteness with @samp{%L}, and discards the Xnewline with @samp{%l}; @xref{Line Formats}. Finally, with the X@command{ed} and forward @command{ed} output formats (@pxref{Output Formats}) X@command{diff} cannot represent an incomplete line, so it pretends there Xwas a newline and reports an error. X XFor example, suppose @file{F} and @file{G} are one-byte files that Xcontain just @samp{f} and @samp{g}, respectively. Then @samp{diff F G} Xoutputs X X@example X1c1 X< f X\ No newline at end of file X--- X> g X\ No newline at end of file X@end example X X@noindent X(The exact message may differ in non-English locales.) X@samp{diff -n F G} outputs the following without a trailing newline: X X@example Xd1 1 Xa1 1 Xg X@end example X X@noindent X@samp{diff -e F G} reports two errors and outputs the following: X X@example X1c Xg X. X@end example X X@node Comparing Directories X@chapter Comparing Directories X X@vindex LC_COLLATE XYou can use @command{diff} to compare some or all of the files in two Xdirectory trees. When both file name arguments to @command{diff} are Xdirectories, it compares each file that is contained in both Xdirectories, examining file names in alphabetical order as specified by Xthe @env{LC_COLLATE} locale category. Normally X@command{diff} is silent about pairs of files that contain no differences, Xbut if you use the @option{-s} or @option{--report-identical-files} option, Xit reports pairs of identical files. Normally @command{diff} reports Xsubdirectories common to both directories without comparing Xsubdirectories' files, but if you use the @option{-r} or X@option{--recursive} option, it compares every corresponding pair of files Xin the directory trees, as many levels deep as they go. X XFor file names that are in only one of the directories, @command{diff} Xnormally does not show the contents of the file that exists; it reports Xonly that the file exists in that directory and not in the other. You Xcan make @command{diff} act as though the file existed but was empty in the Xother directory, so that it outputs the entire contents of the file that Xactually exists. (It is output as either an insertion or a Xdeletion, depending on whether it is in the first or the second Xdirectory given.) To do this, use the @option{-N} or @option{--new-file} Xoption. X XIf the older directory contains one or more large files that are not in Xthe newer directory, you can make the patch smaller by using the X@option{--unidirectional-new-file} option instead of @option{-N}. XThis option is like @option{-N} except that it only inserts the contents Xof files that appear in the second directory but not the first (that is, Xfiles that were added). At the top of the patch, write instructions for Xthe user applying the patch to remove the files that were deleted before Xapplying the patch. @xref{Making Patches}, for more discussion of Xmaking patches for distribution. X XTo ignore some files while comparing directories, use the @option{-x X@var{pattern}} or @option{--exclude=@var{pattern}} option. This option Xignores any files or subdirectories whose base names match the shell Xpattern @var{pattern}. Unlike in the shell, a period at the start of Xthe base of a file name matches a wildcard at the start of a pattern. XYou should enclose @var{pattern} in quotes so that the shell does not Xexpand it. For example, the option @option{-x '*.[ao]'} ignores any file Xwhose name ends with @samp{.a} or @samp{.o}. X XThis option accumulates if you specify it more than once. For example, Xusing the options @option{-x 'RCS' -x '*,v'} ignores any file or Xsubdirectory whose base name is @samp{RCS} or ends with @samp{,v}. X XIf you need to give this option many times, you can instead put the Xpatterns in a file, one pattern per line, and use the @option{-X X@var{file}} or @option{--exclude-from=@var{file}} option. X XIf you have been comparing two directories and stopped partway through, Xlater you might want to continue where you left off. You can do this by Xusing the @option{-S @var{file}} or @option{--starting-file=@var{file}} Xoption. This compares only the file @var{file} and all alphabetically Xlater files in the topmost directory level. X XIf two directories differ only in that file names are lower case in Xone directory and upper case in the upper, @command{diff} normally Xreports many differences because it compares file names in a Xcase sensitive way. With the @option{--ignore-file-name-case} option, X@command{diff} ignores case differences in file names, so that for example Xthe contents of the file @file{Tao} in one directory are compared to Xthe contents of the file @file{TAO} in the other. The X@option{--no-ignore-file-name-case} option cancels the effect of the X@option{--ignore-file-name-case} option, reverting to the default Xbehavior. X XIf an @option{-x @var{pattern}}, @option{--exclude=@var{pattern}}, X@option{-X @var{file}}, or @option{--exclude-from=@var{file}} option Xis specified while the @option{--ignore-file-name-case} option is in Xeffect, case is ignored when excluding file names matching the Xspecified patterns. X X@node Adjusting Output X@chapter Making @command{diff} Output Prettier X X@command{diff} provides several ways to adjust the appearance of its output. XThese adjustments can be applied to any output format. X X@menu X* Tabs:: Preserving the alignment of tab stops. X* Pagination:: Page numbering and time-stamping @command{diff} output. X@end menu X X@node Tabs X@section Preserving Tab Stop Alignment X@cindex tab stop alignment X@cindex aligning tab stops X XThe lines of text in some of the @command{diff} output formats are preceded Xby one or two characters that indicate whether the text is inserted, Xdeleted, or changed. The addition of those characters can cause tabs to Xmove to the next tab stop, throwing off the alignment of columns in the Xline. @sc{gnu} @command{diff} provides two ways to make tab-aligned columns Xline up correctly. X XThe first way is to have @command{diff} convert all tabs into the correct Xnumber of spaces before outputting them; select this method with the X@option{-t} or @option{--expand-tabs} option. @command{diff} assumes that Xtab stops are set every 8 print columns. To use this form of output with X@command{patch}, you must give @command{patch} the @option{-l} or X@option{--ignore-white-space} option (@pxref{Changed White Space}, for more Xinformation). X XThe other method for making tabs line up correctly is to add a tab Xcharacter instead of a space after the indicator character at the Xbeginning of the line. This ensures that all following tab characters Xare in the same position relative to tab stops that they were in the Xoriginal files, so that the output is aligned correctly. Its Xdisadvantage is that it can make long lines too long to fit on one line Xof the screen or the paper. It also does not work with the unified Xoutput format, which does not have a space character after the change Xtype indicator character. Select this method with the @option{-T} or X@option{--initial-tab} option. X X@node Pagination X@section Paginating @command{diff} Output X@cindex paginating @command{diff} output X XIt can be convenient to have long output page-numbered and time-stamped. XThe @option{-l} and @option{--paginate} options do this by sending the X@command{diff} output through the @command{pr} program. Here is what the page Xheader might look like for @samp{diff -lc lao tzu}: X X@example X2002-02-22 14:20 diff -lc lao tzu Page 1 X@end example X X@node diff Performance X@chapter @command{diff} Performance Tradeoffs X@cindex performance of @command{diff} X X@sc{gnu} @command{diff} runs quite efficiently; however, in some circumstances Xyou can cause it to run faster or produce a more compact set of changes. X XOne way to improve @command{diff} performance is to use hard or Xsymbolic links to files instead of copies. This improves performance Xbecause @command{diff} normally does not need to read two hard or Xsymbolic links to the same file, since their contents must be Xidentical. For example, suppose you copy a large directory hierarchy, Xmake a few changes to the copy, and then often use @samp{diff -r} to Xcompare the original to the copy. If the original files are Xread-only, you can greatly improve performance by creating the copy Xusing hard or symbolic links (e.g., with @sc{gnu} @samp{cp -lR} or X@samp{cp -sR}). Before editing a file in the copy for the first time, Xyou should break the link and replace it with a regular copy. X XYou can also affect the performance of @sc{gnu} @command{diff} by Xgiving it options that change the way it compares files. XPerformance has more than one dimension. These options improve one Xaspect of performance at the cost of another, or they improve Xperformance in some cases while hurting it in others. X XThe way that @sc{gnu} @command{diff} determines which lines have changed always Xcomes up with a near-minimal set of differences. Usually it is good Xenough for practical purposes. If the @command{diff} output is large, you Xmight want @command{diff} to use a modified algorithm that sometimes Xproduces a smaller set of differences. The @option{-d} or X@option{--minimal} option does this; however, it can also cause X@command{diff} to run more slowly than usual, so it is not the default Xbehavior. X XWhen the files you are comparing are large and have small groups of Xchanges scattered throughout them, you can use the X@option{--speed-large-files} option to make a different modification to Xthe algorithm that @command{diff} uses. If the input files have a constant Xsmall density of changes, this option speeds up the comparisons without Xchanging the output. If not, @command{diff} might produce a larger set of Xdifferences; however, the output will still be correct. X XNormally @command{diff} discards the prefix and suffix that is common to Xboth files before it attempts to find a minimal set of differences. XThis makes @command{diff} run faster, but occasionally it may produce Xnon-minimal output. The @option{--horizon-lines=@var{lines}} option Xprevents @command{diff} from discarding the last @var{lines} lines of the Xprefix and the first @var{lines} lines of the suffix. This gives X@command{diff} further opportunities to find a minimal output. X XSuppose a run of changed lines includes a sequence of lines at one end Xand there is an identical sequence of lines just outside the other end. XThe @command{diff} command is free to choose which identical sequence is Xincluded in the hunk. In this case, @command{diff} normally shifts the Xhunk's boundaries when this merges adjacent hunks, or shifts a hunk's Xlines towards the end of the file. Merging hunks can make the output Xlook nicer in some cases. X X@node Comparing Three Files X@chapter Comparing Three Files X@cindex comparing three files X@cindex format of @command{diff3} output X XUse the program @command{diff3} to compare three files and show any Xdifferences among them. (@command{diff3} can also merge files; see X@ref{diff3 Merging}). X XThe ``normal'' @command{diff3} output format shows each hunk of Xdifferences without surrounding context. Hunks are labeled depending Xon whether they are two-way or three-way, and lines are annotated by Xtheir location in the input files. X X@xref{Invoking diff3}, for more information on how to run @command{diff3}. X X@menu X* Sample diff3 Input:: Sample @command{diff3} input for examples. X* Detailed diff3 Normal:: A detailed description of normal output format. X* diff3 Hunks:: The format of normal output format. X* Example diff3 Normal:: Sample output in the normal format. X@end menu X X@node Sample diff3 Input X@section A Third Sample Input File X@cindex @command{diff3} sample input X@cindex sample input for @command{diff3} X XHere is a third sample file that will be used in examples to illustrate Xthe output of @command{diff3} and how various options can change it. The Xfirst two files are the same that we used for @command{diff} (@pxref{Sample Xdiff Input}). This is the third sample file, called @file{tao}: X X@example XThe Way that can be told of is not the eternal Way; XThe name that can be named is not the eternal name. XThe Nameless is the origin of Heaven and Earth; XThe named is the mother of all things. X XTherefore let there always be non-being, X so we may see their subtlety, XAnd let there always be being, X so we may see their result. XThe two are the same, XBut after they are produced, X they have different names. X X -- The Way of Lao-Tzu, tr. Wing-tsit Chan X@end example X X@node Detailed diff3 Normal X@section Detailed Description of @command{diff3} Normal Format X XEach hunk begins with a line marked @samp{====}. Three-way hunks have Xplain @samp{====} lines, and two-way hunks have @samp{1}, @samp{2}, or X@samp{3} appended to specify which of the three input files differ in Xthat hunk. The hunks contain copies of two or three sets of input Xlines each preceded by one or two commands identifying where the lines Xcame from. X XNormally, two spaces precede each copy of an input line to distinguish Xit from the commands. But with the @option{-T} or @option{--initial-tab} Xoption, @command{diff3} uses a tab instead of two spaces; this lines up Xtabs correctly. @xref{Tabs}, for more information. X XCommands take the following forms: X X@table @samp X@item @var{file}:@var{l}a XThis hunk appears after line @var{l} of file @var{file}, and Xcontains no lines in that file. To edit this file to yield the other Xfiles, one must append hunk lines taken from the other files. For Xexample, @samp{1:11a} means that the hunk follows line 11 in the first Xfile and contains no lines from that file. X X@item @var{file}:@var{r}c XThis hunk contains the lines in the range @var{r} of file @var{file}. XThe range @var{r} is a comma-separated pair of line numbers, or just one Xnumber if the range is a singleton. To edit this file to yield the Xother files, one must change the specified lines to be the lines taken Xfrom the other files. For example, @samp{2:11,13c} means that the hunk Xcontains lines 11 through 13 from the second file. X@end table X XIf the last line in a set of input lines is incomplete X(@pxref{Incomplete Lines}), it is distinguished on output from a full Xline by a following line that starts with @samp{\}. X X@node diff3 Hunks X@section @command{diff3} Hunks X@cindex hunks for @command{diff3} X@cindex @command{diff3} hunks X XGroups of lines that differ in two or three of the input files are Xcalled @dfn{diff3 hunks}, by analogy with @command{diff} hunks X(@pxref{Hunks}). If all three input files differ in a @command{diff3} Xhunk, the hunk is called a @dfn{three-way hunk}; if just two input files Xdiffer, it is a @dfn{two-way hunk}. X XAs with @command{diff}, several solutions are possible. When comparing the Xfiles @samp{A}, @samp{B}, and @samp{C}, @command{diff3} normally finds X@command{diff3} hunks by merging the two-way hunks output by the two Xcommands @samp{diff A B} and @samp{diff A C}. This does not necessarily Xminimize the size of the output, but exceptions should be rare. X XFor example, suppose @file{F} contains the three lines @samp{a}, X@samp{b}, @samp{f}, @file{G} contains the lines @samp{g}, @samp{b}, X@samp{g}, and @file{H} contains the lines @samp{a}, @samp{b}, X@samp{h}. @samp{diff3 F G H} might output the following: X X@example X====2 X1:1c X3:1c X a X2:1c X g X==== X1:3c X f X2:3c X g X3:3c X h X@end example X X@noindent Xbecause it found a two-way hunk containing @samp{a} in the first and Xthird files and @samp{g} in the second file, then the single line X@samp{b} common to all three files, then a three-way hunk containing Xthe last line of each file. X X@node Example diff3 Normal X@section An Example of @command{diff3} Normal Format X XHere is the output of the command @samp{diff3 lao tzu tao} X(@pxref{Sample diff3 Input}, for the complete contents of the files). XNotice that it shows only the lines that are different among the three Xfiles. X X@example X====2 X1:1,2c X3:1,2c X The Way that can be told of is not the eternal Way; X The name that can be named is not the eternal name. X2:0a X====1 X1:4c X The Named is the mother of all things. X2:2,3c X3:4,5c X The named is the mother of all things. X X====3 X1:8c X2:7c X so we may see their outcome. X3:9c X so we may see their result. X==== X1:11a X2:11,13c X They both may be called deep and profound. X Deeper and more profound, X The door of all subtleties! X3:13,14c X X -- The Way of Lao-Tzu, tr. Wing-tsit Chan X@end example X X@node diff3 Merging X@chapter Merging From a Common Ancestor X@cindex merging from a common ancestor X XWhen two people have made changes to copies of the same file, X@command{diff3} can produce a merged output that contains both sets of Xchanges together with warnings about conflicts. X XOne might imagine programs with names like @command{diff4} and @command{diff5} Xto compare more than three files simultaneously, but in practice the Xneed rarely arises. You can use @command{diff3} to merge three or more Xsets of changes to a file by merging two change sets at a time. X X@command{diff3} can incorporate changes from two modified versions into a Xcommon preceding version. This lets you merge the sets of changes Xrepresented by the two newer files. Specify the common ancestor version Xas the second argument and the two newer versions as the first and third Xarguments, like this: X X@example Xdiff3 @var{mine} @var{older} @var{yours} X@end example X X@noindent XYou can remember the order of the arguments by noting that they are in Xalphabetical order. X X@cindex conflict X@cindex overlap XYou can think of this as subtracting @var{older} from @var{yours} and Xadding the result to @var{mine}, or as merging into @var{mine} the Xchanges that would turn @var{older} into @var{yours}. This merging is Xwell-defined as long as @var{mine} and @var{older} match in the Xneighborhood of each such change. This fails to be true when all three Xinput files differ or when only @var{older} differs; we call this Xa @dfn{conflict}. When all three input files differ, we call the Xconflict an @dfn{overlap}. X X@command{diff3} gives you several ways to handle overlaps and conflicts. XYou can omit overlaps or conflicts, or select only overlaps, Xor mark conflicts with special @samp{<<<<<<<} and @samp{>>>>>>>} lines. X X@command{diff3} can output the merge results as an @command{ed} script that Xthat can be applied to the first file to yield the merged output. XHowever, it is usually better to have @command{diff3} generate the merged Xoutput directly; this bypasses some problems with @command{ed}. X X@menu X* Which Changes:: Selecting changes to incorporate. X* Marking Conflicts:: Marking conflicts. X* Bypassing ed:: Generating merged output directly. X* Merging Incomplete Lines:: How @command{diff3} merges incomplete lines. X* Saving the Changed File:: Emulating System V behavior. X@end menu X X@node Which Changes X@section Selecting Which Changes to Incorporate X@cindex overlapping change, selection of X@cindex unmerged change X XYou can select all unmerged changes from @var{older} to @var{yours} for merging Xinto @var{mine} with the @option{-e} or @option{--ed} option. You can Xselect only the nonoverlapping unmerged changes with @option{-3} or X@option{--easy-only}, and you can select only the overlapping changes with X@option{-x} or @option{--overlap-only}. X XThe @option{-e}, @option{-3} and @option{-x} options select only X@dfn{unmerged changes}, i.e.@: changes where @var{mine} and @var{yours} Xdiffer; they ignore changes from @var{older} to @var{yours} where X@var{mine} and @var{yours} are identical, because they assume that such Xchanges have already been merged. If this assumption is not a safe Xone, you can use the @option{-A} or @option{--show-all} option X(@pxref{Marking Conflicts}). X XHere is the output of the command @command{diff3} with each of these three Xoptions (@pxref{Sample diff3 Input}, for the complete contents of the files). XNotice that @option{-e} outputs the union of the disjoint sets of changes Xoutput by @option{-3} and @option{-x}. X XOutput of @samp{diff3 -e lao tzu tao}: X@example X11a X X -- The Way of Lao-Tzu, tr. Wing-tsit Chan X. X8c X so we may see their result. X. X@end example X XOutput of @samp{diff3 -3 lao tzu tao}: X@example X8c X so we may see their result. X. X@end example X XOutput of @samp{diff3 -x lao tzu tao}: X@example X11a X X -- The Way of Lao-Tzu, tr. Wing-tsit Chan X. X@end example X X@node Marking Conflicts X@section Marking Conflicts X@cindex conflict marking X@cindex @samp{<<<<<<<} for marking conflicts X X@command{diff3} can mark conflicts in the merged output by Xbracketing them with special marker lines. A conflict Xthat comes from two files @var{A} and @var{B} is marked as follows: X X@example X<<<<<<< @var{A} X@r{lines from @var{A}} X======= X@r{lines from @var{B}} X>>>>>>> @var{B} X@end example X XA conflict that comes from three files @var{A}, @var{B} and @var{C} is Xmarked as follows: X X@example X<<<<<<< @var{A} X@r{lines from @var{A}} X||||||| @var{B} X@r{lines from @var{B}} X======= X@r{lines from @var{C}} X>>>>>>> @var{C} X@end example X XThe @option{-A} or @option{--show-all} option acts like the @option{-e} Xoption, except that it brackets conflicts, and it outputs all changes Xfrom @var{older} to @var{yours}, not just the unmerged changes. Thus, Xgiven the sample input files (@pxref{Sample diff3 Input}), @samp{diff3 X-A lao tzu tao} puts brackets around the conflict where only @file{tzu} Xdiffers: X X@example X<<<<<<< tzu X======= XThe Way that can be told of is not the eternal Way; XThe name that can be named is not the eternal name. X>>>>>>> tao X@end example X XAnd it outputs the three-way conflict as follows: X X@example X<<<<<<< lao X||||||| tzu XThey both may be called deep and profound. XDeeper and more profound, XThe door of all subtleties! X======= X X -- The Way of Lao-Tzu, tr. Wing-tsit Chan X>>>>>>> tao X@end example X XThe @option{-E} or @option{--show-overlap} option outputs less information Xthan the @option{-A} or @option{--show-all} option, because it outputs only Xunmerged changes, and it never outputs the contents of the second Xfile. Thus the @option{-E} option acts like the @option{-e} option, Xexcept that it brackets the first and third files from three-way Xoverlapping changes. Similarly, @option{-X} acts like @option{-x}, except Xit brackets all its (necessarily overlapping) changes. For example, Xfor the three-way overlapping change above, the @option{-E} and @option{-X} Xoptions output the following: X X@example X<<<<<<< lao X======= X X -- The Way of Lao-Tzu, tr. Wing-tsit Chan X>>>>>>> tao X@end example X XIf you are comparing files that have meaningless or uninformative names, Xyou can use the @option{-L @var{label}} or @option{--label=@var{label}} Xoption to show alternate names in the @samp{<<<<<<<}, @samp{|||||||} Xand @samp{>>>>>>>} brackets. This option can be given up to three Xtimes, once for each input file. Thus @samp{diff3 -A -L X -L Y -L Z A XB C} acts like @samp{diff3 -A A B C}, except that the output looks like Xit came from files named @samp{X}, @samp{Y} and @samp{Z} rather than Xfrom files named @samp{A}, @samp{B} and @samp{C}. X X@node Bypassing ed X@section Generating the Merged Output Directly X@cindex merged @command{diff3} format X XWith the @option{-m} or @option{--merge} option, @command{diff3} outputs the Xmerged file directly. This is more efficient than using @command{ed} to Xgenerate it, and works even with non-text files that @command{ed} would Xreject. If you specify @option{-m} without an @command{ed} script option, X@option{-A} (@option{--show-all}) is assumed. X XFor example, the command @samp{diff3 -m lao tzu tao} X(@pxref{Sample diff3 Input} for a copy of the input files) would output Xthe following: X X@example X<<<<<<< tzu X======= XThe Way that can be told of is not the eternal Way; XThe name that can be named is not the eternal name. X>>>>>>> tao XThe Nameless is the origin of Heaven and Earth; XThe Named is the mother of all things. XTherefore let there always be non-being, X so we may see their subtlety, XAnd let there always be being, X so we may see their result. XThe two are the same, XBut after they are produced, X they have different names. X<<<<<<< lao X||||||| tzu XThey both may be called deep and profound. XDeeper and more profound, XThe door of all subtleties! X======= X X -- The Way of Lao-Tzu, tr. Wing-tsit Chan X>>>>>>> tao X@end example X X@node Merging Incomplete Lines X@section How @command{diff3} Merges Incomplete Lines X@cindex incomplete line merging X XWith @option{-m}, incomplete lines (@pxref{Incomplete Lines}) are simply Xcopied to the output as they are found; if the merged output ends in an Xconflict and one of the input files ends in an incomplete Xline, succeeding @samp{|||||||}, @samp{=======} or @samp{>>>>>>>} Xbrackets appear somewhere other than the start of a line because Xthey are appended to the incomplete line. X XWithout @option{-m}, if an @command{ed} script option is specified and an Xincomplete line is found, @command{diff3} generates a warning and acts as Xif a newline had been present. X X@node Saving the Changed File X@section Saving the Changed File X@cindex System V @command{diff3} compatibility X XTraditional Unix @command{diff3} generates an @command{ed} script without the Xtrailing @samp{w} and @samp{q} commands that save the changes. XSystem V @command{diff3} generates these extra commands. @sc{gnu} X@command{diff3} normally behaves like traditional Unix X@command{diff3}, but with the @option{-i} option it behaves like XSystem V @command{diff3} and appends the @samp{w} and @samp{q} Xcommands. X XThe @option{-i} option requires one of the @command{ed} script options X@option{-AeExX3}, and is incompatible with the merged output option X@option{-m}. X X@node Interactive Merging X@chapter Interactive Merging with @command{sdiff} X@cindex diff merging X@cindex interactive merging X XWith @command{sdiff}, you can merge two files interactively based on a Xside-by-side @option{-y} format comparison (@pxref{Side by Side}). Use X@option{-o @var{file}} or @option{--output=@var{file}} to specify where to Xput the merged text. @xref{Invoking sdiff}, for more details on the Xoptions to @command{sdiff}. X XAnother way to merge files interactively is to use the Emacs Lisp Xpackage @command{emerge}. @xref{emerge, , emerge, emacs, The @sc{gnu} Emacs XManual}, for more information. X X@menu X* sdiff Option Summary:: Summary of @command{sdiff} options. X* Merge Commands:: Merging two files interactively. X@end menu X X@node sdiff Option Summary X@section Specifying @command{diff} Options to @command{sdiff} X@cindex @command{sdiff} output format X XThe following @command{sdiff} options have the same meaning as for X@command{diff}. @xref{diff Options}, for the use of these options. X X@example X-a -b -d -i -t -v X-B -E -I @var{regexp} X X--ignore-blank-lines --ignore-case X--ignore-matching-lines=@var{regexp} --ignore-space-change X--ignore-tab-expansion X--left-column --minimal --speed-large-files X--strip-trailing-cr --suppress-common-lines --expand-tabs X--text --version --width=@var{columns} X@end example X XFor historical reasons, @command{sdiff} has alternate names for some Xoptions. The @option{-l} option is equivalent to the X@option{--left-column} option, and similarly @option{-s} is equivalent Xto @option{--suppress-common-lines}. The meaning of the @command{sdiff} X@option{-w} and @option{-W} options is interchanged from that of X@command{diff}: with @command{sdiff}, @option{-w @var{columns}} is Xequivalent to @option{--width=@var{columns}}, and @option{-W} is Xequivalent to @option{--ignore-all-space}. @command{sdiff} without the X@option{-o} option is equivalent to @command{diff} with the @option{-y} Xor @option{--side-by-side} option (@pxref{Side by Side}). X X@node Merge Commands X@section Merge Commands X@cindex merge commands X@cindex merging interactively X XGroups of common lines, with a blank gutter, are copied from the first Xfile to the output. After each group of differing lines, @command{sdiff} Xprompts with @samp{%} and pauses, waiting for one of the following Xcommands. Follow each command with @key{RET}. X X@table @samp X@item e XDiscard both versions. XInvoke a text editor on an empty temporary file, Xthen copy the resulting file to the output. X X@item eb XConcatenate the two versions, edit the result in a temporary file, Xthen copy the edited result to the output. X X@item ed XLike @samp{eb}, except precede each version with a header that Xshows what file and lines the version came from. X X@item el XEdit a copy of the left version, then copy the result to the output. X X@item er XEdit a copy of the right version, then copy the result to the output. X X@item l XCopy the left version to the output. X X@item q XQuit. X X@item r XCopy the right version to the output. X X@item s XSilently copy common lines. X X@item v XVerbosely copy common lines. This is the default. X@end table X X@vindex EDITOR XThe text editor invoked is specified by the @env{EDITOR} environment Xvariable if it is set. The default is system-dependent. X X@node Merging with patch X@chapter Merging with @command{patch} X X@command{patch} takes comparison output produced by @command{diff} and applies Xthe differences to a copy of the original file, producing a patched Xversion. With @command{patch}, you can distribute just the changes to a Xset of files instead of distributing the entire file set; your Xcorrespondents can apply @command{patch} to update their copy of the files Xwith your changes. @command{patch} automatically determines the diff Xformat, skips any leading or trailing headers, and uses the headers to Xdetermine which file to patch. This lets your correspondents feed a Xmail message containing a difference listing directly to X@command{patch}. X X@command{patch} detects and warns about common problems like forward Xpatches. It saves any patches that it could not apply. It can also maintain a X@code{patchlevel.h} file to ensure that your correspondents apply Xdiffs in the proper order. X X@command{patch} accepts a series of diffs in its standard input, usually Xseparated by headers that specify which file to patch. It applies X@command{diff} hunks (@pxref{Hunks}) one by one. If a hunk does not Xexactly match the original file, @command{patch} uses heuristics to try to Xpatch the file as well as it can. If no approximate match can be found, X@command{patch} rejects the hunk and skips to the next hunk. @command{patch} Xnormally replaces each file @var{f} with its new version, putting reject Xhunks (if any) into @samp{@var{f}.rej}. X X@xref{Invoking patch}, for detailed information on the options to X@command{patch}. X X@menu X* patch Input:: Selecting the type of @command{patch} input. X* Revision Control:: Getting files from @sc{rcs}, @sc{sccs}, etc. X* Imperfect:: Dealing with imperfect patches. X* Creating and Removing:: Creating and removing files with a patch. X* Patching Time Stamps:: Updating time stamps on patched files. X* Multiple Patches:: Handling multiple patches in a file. X* patch Directories:: Changing directory and stripping directories. X* Backups:: Whether backup files are made. X* Backup Names:: Backup file names. X* Reject Names:: Reject file names. X* patch Messages:: Messages and questions @command{patch} can produce. X* patch and POSIX:: Conformance to the @sc{posix} standard. X* patch and Tradition:: @sc{gnu} versus traditional @command{patch}. X@end menu X X@node patch Input X@section Selecting the @command{patch} Input Format X@cindex @command{patch} input format X X@command{patch} normally determines which @command{diff} format the patch Xfile uses by examining its contents. For patch files that contain Xparticularly confusing leading text, you might need to use one of the Xfollowing options to force @command{patch} to interpret the patch file as a Xcertain format of diff. The output formats listed here are the only Xones that @command{patch} can understand. X X@table @option X@item -c X@itemx --context Xcontext diff. X X@item -e X@itemx --ed X@command{ed} script. X X@item -n X@itemx --normal Xnormal diff. X X@item -u X@itemx --unified Xunified diff. X@end table X X@node Revision Control X@section Revision Control X@cindex revision control X@cindex version control X@cindex @sc{rcs} X@cindex ClearCase X@cindex @sc{sccs} X XIf a nonexistent input file is under a revision control system Xsupported by @command{patch}, @command{patch} normally asks the user Xwhether to get (or check out) the file from the revision control Xsystem. Patch currently supports @sc{rcs}, ClearCase and @sc{sccs}. XUnder @sc{rcs} and @sc{sccs}, @command{patch} also asks when the input Xfile is read-only and matches the default version in the revision Xcontrol system. X X@vindex PATCH_GET XThe @option{-g @var{num}} or @option{--get=@var{num}} affects access Xto files under supported revision control systems. If @var{num} is Xpositive, @command{patch} gets the file without asking the user; if Xzero, @command{patch} neither asks the user nor gets the file; and if Xnegative, @command{patch} asks the user before getting the file. The Xdefault value of @var{num} is given by the value of the X@env{PATCH_GET} environment variable if it is set; if not, the default Xvalue is zero if @command{patch} is conforming to @sc{posix}, negative Xotherwise. @xref{patch and POSIX}. X X@vindex VERSION_CONTROL XThe choice of revision control system is unaffected by the X@env{VERSION_CONTROL} environment variable (@pxref{Backup Names}). X X@node Imperfect X@section Applying Imperfect Patches X@cindex imperfect patch application X X@command{patch} tries to skip any leading text in the patch file, Xapply the diff, and then skip any trailing text. Thus you can feed a Xmail message directly to @command{patch}, and it should work. If the Xentire diff is indented by a constant amount of white space, X@command{patch} automatically ignores the indentation. If a context Xdiff contains trailing carriage return on each line, @command{patch} Xautomatically ignores the carriage return. If a context diff has been Xencapsulated by prepending @w{@samp{- }} to lines beginning with @samp{-} Xas per @uref{ftp://ftp.isi.edu/in-notes/rfc934.txt, Internet RFC 934}, X@command{patch} automatically unencapsulates the input. X XHowever, certain other types of imperfect input require user Xintervention or testing. X X@menu X* Changed White Space:: When tabs and spaces don't match exactly. X* Reversed Patches:: Applying reversed patches correctly. X* Inexact:: Helping @command{patch} find close matches. X* Dry Runs:: Predicting what @command{patch} will do. X@end menu X X@node Changed White Space X@subsection Applying Patches with Changed White Space X@cindex white space in patches X XSometimes mailers, editors, or other programs change spaces into tabs, Xor vice versa. If this happens to a patch file or an input file, the Xfiles might look the same, but @command{patch} will not be able to match Xthem properly. If this problem occurs, use the @option{-l} or X@option{--ignore-white-space} option, which makes @command{patch} compare Xblank characters (i.e.@: spaces and tabs) loosely so that any nonempty Xsequence of blanks in the patch file matches any nonempty sequence of Xblanks in the input files. Non-blank Xcharacters must still match exactly. Each line of the context must Xstill match a line in the input file. X X@node Reversed Patches X@subsection Applying Reversed Patches X@cindex reversed patches X XSometimes people run @command{diff} with the new file first instead of Xsecond. This creates a diff that is ``reversed''. To apply such Xpatches, give @command{patch} the @option{-R} or @option{--reverse} option. X@command{patch} then attempts to swap each hunk around before applying it. XRejects come out in the swapped format. X XOften @command{patch} can guess that the patch is reversed. If the first Xhunk of a patch fails, @command{patch} reverses the hunk to see if it can Xapply it that way. If it can, @command{patch} asks you if you want to have Xthe @option{-R} option set; if it can't, @command{patch} continues to apply Xthe patch normally. This method cannot detect a reversed patch if it is Xa normal diff and the first command is an append (which should have been Xa delete) since appends always succeed, because a null context matches Xanywhere. But most patches add or change lines rather than delete them, Xso most reversed normal diffs begin with a delete, which fails, and X@command{patch} notices. X XIf you apply a patch that you have already applied, @command{patch} thinks Xit is a reversed patch and offers to un-apply the patch. This could be Xconstrued as a feature. If you did this inadvertently and you don't Xwant to un-apply the patch, just answer @samp{n} to this offer and to Xthe subsequent ``apply anyway'' question---or type @kbd{C-c} to kill the X@command{patch} process. X X@node Inexact X@subsection Helping @command{patch} Find Inexact Matches X@cindex inexact patches X@cindex fuzz factor when patching X XFor context diffs, and to a lesser extent normal diffs, @command{patch} can Xdetect when the line numbers mentioned in the patch are incorrect, and Xit attempts to find the correct place to apply each hunk of the patch. XAs a first guess, it takes the line number mentioned in the hunk, plus Xor minus any offset used in applying the previous hunk. If that is not Xthe correct place, @command{patch} scans both forward and backward for a Xset of lines matching the context given in the hunk. X XFirst @command{patch} looks for a place where all lines of the context Xmatch. If it cannot find such a place, and it is reading a context or Xunified diff, and the maximum fuzz factor is set to 1 or more, then X@command{patch} makes another scan, ignoring the first and last line of Xcontext. If that fails, and the maximum fuzz factor is set to 2 or Xmore, it makes another scan, ignoring the first two and last two lines Xof context are ignored. It continues similarly if the maximum fuzz Xfactor is larger. X XThe @option{-F @var{lines}} or @option{--fuzz=@var{lines}} option sets the Xmaximum fuzz factor to @var{lines}. This option only applies to context Xand unified diffs; it ignores up to @var{lines} lines while looking for Xthe place to install a hunk. Note that a larger fuzz factor increases Xthe odds of making a faulty patch. The default fuzz factor is 2; there Xis no point to setting it to more than the number of lines of context Xin the diff, ordinarily 3. X XIf @command{patch} cannot find a place to install a hunk of the patch, it Xwrites the hunk out to a reject file (@pxref{Reject Names}, for information Xon how reject files are named). It writes out rejected hunks in context Xformat no matter what form the input patch is in. If the input is a Xnormal or @command{ed} diff, many of the contexts are simply null. The Xline numbers on the hunks in the reject file may be different from those Xin the patch file: they show the approximate location where @command{patch} Xthinks the failed hunks belong in the new file rather than in the old Xone. X XIf the @option{--verbose} option is given, then Xas it completes each hunk @command{patch} tells you whether the hunk Xsucceeded or failed, and if it failed, on which line (in the new file) X@command{patch} thinks the hunk should go. If this is different from the Xline number specified in the diff, it tells you the offset. A single Xlarge offset @emph{may} indicate that @command{patch} installed a hunk in Xthe wrong place. @command{patch} also tells you if it used a fuzz factor Xto make the match, in which case you should also be slightly suspicious. X X@command{patch} cannot tell if the line numbers are off in an @command{ed} Xscript, and can only detect wrong line numbers in a normal diff when it Xfinds a change or delete command. It may have the same problem with a Xcontext diff using a fuzz factor equal to or greater than the number of Xlines of context shown in the diff (typically 3). In these cases, you Xshould probably look at a context diff between your original and patched Xinput files to see if the changes make sense. Compiling without errors Xis a pretty good indication that the patch worked, but not a guarantee. X XA patch against an empty file applies to a nonexistent file, and vice Xversa. @xref{Creating and Removing}. X X@command{patch} usually produces the correct results, even when it must Xmake many guesses. However, the results are guaranteed only when Xthe patch is applied to an exact copy of the file that the patch was Xgenerated from. X X@node Dry Runs X@subsection Predicting what @command{patch} will do X@cindex testing @command{patch} X@cindex dry runs for @command{patch} X XIt may not be obvious in advance what @command{patch} will do with a Xcomplicated or poorly formatted patch. If you are concerned that the Xinput might cause @command{patch} to modify the wrong files, you can Xuse the @option{--dry-run} option, which causes @command{patch} to Xprint the results of applying patches without actually changing any Xfiles. You can then inspect the diagnostics generated by the dry run Xto see whether @command{patch} will modify the files that you expect. XIf the patch does not do what you want, you can modify the patch (or Xthe other options to @command{patch}) and try another dry run. Once Xyou are satisfied with the proposed patch you can apply it by invoking X@command{patch} as before, but this time without the X@option{--dry-run} option. X X@node Creating and Removing X@section Creating and Removing Files X@cindex creating files X@cindex empty files, removing X@cindex removing empty files X XSometimes when comparing two directories, a file may exist in one Xdirectory but not the other. If you give @command{diff} the X@option{-N} or @option{--new-file} option, or if you supply an old or Xnew file that is named @file{/dev/null} or is empty and is dated the XEpoch (1970-01-01 00:00:00 UTC), @command{diff} outputs a patch that Xadds or deletes the contents of this file. When given such a patch, X@command{patch} normally creates a new file or removes the old file. XHowever, when conforming to @sc{posix} (@pxref{patch and POSIX}), X@command{patch} does not remove the old file, but leaves it empty. XThe @option{-E} or @option{--remove-empty-files} option causes X@command{patch} to remove output files that are empty after applying a Xpatch, even if the patch does not appear to be one that removed the Xfile. X XIf the patch appears to create a file that already exists, X@command{patch} asks for confirmation before applying the patch. X X@node Patching Time Stamps X@section Updating Time Stamps on Patched Files X@cindex time stamps on patched files X XWhen @command{patch} updates a file, it normally sets the file's Xlast-modified time stamp to the current time of day. If you are using X@command{patch} to track a software distribution, this can cause X@command{make} to incorrectly conclude that a patched file is out of Xdate. For example, if @file{syntax.c} depends on @file{syntax.y}, and X@command{patch} updates @file{syntax.c} and then @file{syntax.y}, then X@file{syntax.c} will normally appear to be out of date with respect to X@file{syntax.y} even though its contents are actually up to date. X XThe @option{-Z} or @option{--set-utc} option causes @command{patch} to Xset a patched file's modification and access times to the time stamps Xgiven in context diff headers. If the context diff headers do not Xspecify a time zone, they are assumed to use Coordinated Universal XTime (@sc{utc}, often known as @sc{gmt}). X XThe @option{-T} or @option{--set-time} option acts like @option{-Z} or X@option{--set-utc}, except that it assumes that the context diff Xheaders' time stamps use local time instead of @sc{utc}. This option Xis not recommended, because patches using local time cannot easily be Xused by people in other time zones, and because local time stamps are Xambiguous when local clocks move backwards during daylight-saving time Xadjustments. If the context diff headers specify a time zone, this Xoption is equivalent to @option{-Z} or @option{--set-utc}. X X@command{patch} normally refrains from setting a file's time stamps if Xthe file's original last-modified time stamp does not match the time Xgiven in the diff header, of if the file's contents do not exactly Xmatch the patch. However, if the @option{-f} or @option{--force} Xoption is given, the file's time stamps are set regardless. X XDue to the limitations of the current @command{diff} format, X@command{patch} cannot update the times of files whose contents have Xnot changed. Also, if you set file time stamps to values other than Xthe current time of day, you should also remove (e.g., with @samp{make Xclean}) all files that depend on the patched files, so that later Xinvocations of @command{make} do not get confused by the patched Xfiles' times. X X@node Multiple Patches X@section Multiple Patches in a File X@cindex multiple patches X@cindex intuiting file names from patches X XIf the patch file contains more than one patch, and if you do not Xspecify an input file on the command line, @command{patch} tries to Xapply each patch as if they came from separate patch files. This Xmeans that it determines the name of the file to patch for each patch, Xand that it examines the leading text before each patch for file names Xand prerequisite revision level (@pxref{Making Patches}, for more on Xthat topic). X X@command{patch} uses the following rules to intuit a file name from Xthe leading text before a patch. First, @command{patch} takes an Xordered list of candidate file names as follows: X X@itemize @bullet X@item XIf the header is that of a context diff, @command{patch} takes the old Xand new file names in the header. A name is ignored if it does not Xhave enough slashes to satisfy the @option{-p@var{num}} or X@option{--strip=@var{num}} option. The name @file{/dev/null} is also Xignored. X X@item XIf there is an @samp{Index:} line in the leading garbage and if either Xthe old and new names are both absent or if @command{patch} is Xconforming to @sc{posix}, @command{patch} takes the name in the X@samp{Index:} line. X X@item XFor the purpose of the following rules, the candidate file names are Xconsidered to be in the order (old, new, index), regardless of the Xorder that they appear in the header. X@end itemize X X@noindent XThen @command{patch} selects a file name from the candidate list as Xfollows: X X@itemize @bullet X@item XIf some of the named files exist, @command{patch} selects the first Xname if conforming to @sc{posix}, and the best name otherwise. X X@item XIf @command{patch} is not ignoring @sc{rcs}, ClearCase, and @sc{sccs} X(@pxref{Revision Control}), and no named files exist but an @sc{rcs}, XClearCase, or @sc{sccs} master is found, @command{patch} selects the Xfirst named file with an @sc{rcs}, ClearCase, or @sc{sccs} master. X X@item XIf no named files exist, no @sc{rcs}, ClearCase, or @sc{sccs} master Xwas found, some names are given, @command{patch} is not conforming to X@sc{posix}, and the patch appears to create a file, @command{patch} Xselects the best name requiring the creation of the fewest Xdirectories. X X@item XIf no file name results from the above heuristics, you are asked for Xthe name of the file to patch, and @command{patch} selects that name. X@end itemize X XTo determine the @dfn{best} of a nonempty list of file names, X@command{patch} first takes all the names with the fewest path name Xcomponents; of those, it then takes all the names with the shortest Xbasename; of those, it then takes all the shortest names; finally, it Xtakes the first remaining name. X X@xref{patch and POSIX}, to see whether @command{patch} is conforming Xto @sc{posix}. X X@node patch Directories X@section Applying Patches in Other Directories X@cindex directories and patch X@cindex patching directories X XThe @option{-d @var{directory}} or @option{--directory=@var{directory}} Xoption to @command{patch} makes directory @var{directory} the current Xdirectory for interpreting both file names in the patch file, and file Xnames given as arguments to other options (such as @option{-B} and X@option{-o}). For example, while in a mail reading program, you can patch Xa file in the @file{/usr/src/emacs} directory directly from a message Xcontaining the patch like this: X X@example X| patch -d /usr/src/emacs X@end example X XSometimes the file names given in a patch contain leading directories, Xbut you keep your files in a directory different from the one given in Xthe patch. In those cases, you can use the X@option{-p@var{number}} or @option{--strip=@var{number}} Xoption to set the file name strip count to @var{number}. The strip Xcount tells @command{patch} how many slashes, along with the directory Xnames between them, to strip from the front of file names. A sequence Xof one or more adjacent slashes is counted as a single slash. By Xdefault, @command{patch} strips off all leading directories, leaving Xjust the base file names. X XFor example, suppose the file name in the patch file is X@file{/gnu/src/emacs/etc/NEWS}. Using @option{-p0} gives the Xentire file name unmodified, @option{-p1} gives X@file{gnu/src/emacs/etc/NEWS} (no leading slash), @option{-p4} gives X@file{etc/NEWS}, and not specifying @option{-p} at all gives @file{NEWS}. X X@command{patch} looks for each file (after any slashes have been stripped) Xin the current directory, or if you used the @option{-d @var{directory}} Xoption, in that directory. X X@node Backups X@section Backup Files X@cindex backup file strategy X XNormally, @command{patch} creates a backup file if the patch does not Xexactly match the original input file, because in that case the Xoriginal data might not be recovered if you undo the patch with X@samp{patch -R} (@pxref{Reversed Patches}). However, when conforming Xto @sc{posix}, @command{patch} does not create backup files by Xdefault. @xref{patch and POSIX}. X XThe @option{-b} or @option{--backup} option causes @command{patch} to Xmake a backup file regardless of whether the patch matches the Xoriginal input. The @option{--backup-if-mismatch} option causes X@command{patch} to create backup files for mismatches files; this is Xthe default when not conforming to @sc{posix}. The X@option{--no-backup-if-mismatch} option causes @command{patch} to not Xcreate backup files, even for mismatched patches; this is the default Xwhen conforming to @sc{posix}. X XWhen backing up a file that does not exist, an empty, unreadable Xbackup file is created as a placeholder to represent the nonexistent Xfile. X X@node Backup Names X@section Backup File Names X@cindex backup file names X XNormally, @command{patch} renames an original input file into a backup Xfile by appending to its name the extension @samp{.orig}, or @samp{~} Xif using @samp{.orig} would make the backup file name too Xlong.@footnote{A coding error in @sc{gnu} @command{patch} version X2.5.4 causes it to always use @samp{~}, but this should be fixed in Xthe next release.} The @option{-z @var{backup-suffix}} or X@option{--suffix=@var{backup-suffix}} option causes @command{patch} to Xuse @var{backup-suffix} as the backup extension instead. X X@vindex SIMPLE_BACKUP_SUFFIX XAlternately, you can specify the extension for backup files with the X@env{SIMPLE_BACKUP_SUFFIX} environment variable, which the options Xoverride. X X@command{patch} can also create numbered backup files the way @sc{gnu} Emacs Xdoes. With this method, instead of having a single backup of each file, X@command{patch} makes a new backup file name each time it patches a file. XFor example, the backups of a file named @file{sink} would be called, Xsuccessively, @file{sink.~1~}, @file{sink.~2~}, @file{sink.~3~}, etc. X X@vindex PATCH_VERSION_CONTROL X@vindex VERSION_CONTROL XThe @option{-V @var{backup-style}} or X@option{--version-control=@var{backup-style}} option takes as an Xargument a method for creating backup file names. You can alternately Xcontrol the type of backups that @command{patch} makes with the X@env{PATCH_VERSION_CONTROL} environment variable, which the X@option{-V} option overrides. If @env{PATCH_VERSION_CONTROL} is not Xset, the @env{VERSION_CONTROL} environment variable is used instead. XPlease note that these options and variables control backup file Xnames; they do not affect the choice of revision control system X(@pxref{Revision Control}). X XThe values of these environment variables and the argument to the X@option{-V} option are like the @sc{gnu} Emacs @code{version-control} Xvariable (@pxref{Backup Names, , , emacs, The @sc{gnu} Emacs Manual}, Xfor more information on backup versions in Emacs). They also Xrecognize synonyms that are more descriptive. The valid values are Xlisted below; unique abbreviations are acceptable. X X@table @option X@item t X@itemx numbered XAlways make numbered backups. X X@item nil X@itemx existing XMake numbered backups of files that already have them, simple backups of Xthe others. This is the default. X X@item never X@itemx simple XAlways make simple backups. X@end table X XYou can also tell @command{patch} to prepend a prefix, such as a Xdirectory name, to produce backup file names. The @option{-B X@var{prefix}} or @option{--prefix=@var{prefix}} option makes backup Xfiles by prepending @var{prefix} to them. The @option{-Y X@var{prefix}} or @option{--basename-prefix=@var{prefix}} prepends X@var{prefix} to the last file name component of backup file names Xinstead; for example, @option{-Y ~} causes the backup name for X@file{dir/file.c} to be @file{dir/~file.c}. If you use either of Xthese prefix options, the suffix-based options are ignored. X XIf you specify the output file with the @option{-o} option, that file is Xthe one that is backed up, not the input file. X XOptions that affect the names of backup files do not affect whether Xbackups are made. For example, if you specify the X@option{--no-backup-if-mismatch} option, none of the options described Xin this section have any affect, because no backups are made. X X@node Reject Names X@section Reject File Names X@cindex reject file names X XThe names for reject files (files containing patches that X@command{patch} could not find a place to apply) are normally the name Xof the output file with @samp{.rej} appended (or @samp{#} if if using X@samp{.rej} would make the backup file name too long). X XAlternatively, you can tell @command{patch} to place all of the rejected Xpatches in a single file. The @option{-r @var{reject-file}} or X@option{--reject-file=@var{reject-file}} option uses @var{reject-file} as Xthe reject file name. X X@node patch Messages X@section Messages and Questions from @command{patch} X@cindex @command{patch} messages and questions X@cindex diagnostics from @command{patch} X@cindex messages from @command{patch} X X@command{patch} can produce a variety of messages, especially if it Xhas trouble decoding its input. In a few situations where it's not Xsure how to proceed, @command{patch} normally prompts you for more Xinformation from the keyboard. There are options to produce more or Xfewer messages, to have it not ask for keyboard input, and to Xaffect the way that file names are quoted in messages. X X@menu X* More or Fewer Messages:: Controlling the verbosity of @command{patch}. X* patch and Keyboard Input:: Inhibiting keyboard input. X* patch Quoting Style:: Quoting file names in diagnostics. X@end menu X X@command{patch} exits with status 0 if all hunks are applied successfully, X1 if some hunks cannot be applied, and 2 if there is more serious trouble. XWhen applying a set of patches in a loop, you should check the Xexit status, so you don't apply a later patch to a partially patched Xfile. X X@node More or Fewer Messages X@subsection Controlling the Verbosity of @command{patch} X@cindex verbose messages from @command{patch} X@cindex inhibit messages from @command{patch} X XYou can cause @command{patch} to produce more messages by using the X@option{--verbose} option. For example, when you give this option, Xthe message @samp{Hmm...} indicates that @command{patch} is reading text in Xthe patch file, attempting to determine whether there is a patch in that Xtext, and if so, what kind of patch it is. X XYou can inhibit all terminal output from @command{patch}, unless an error Xoccurs, by using the @option{-s}, @option{--quiet}, or @option{--silent} Xoption. X X@node patch and Keyboard Input X@subsection Inhibiting Keyboard Input X@cindex keyboard input to @command{patch} X XThere are two ways you can prevent @command{patch} from asking you any Xquestions. The @option{-f} or @option{--force} option assumes that you know Xwhat you are doing. It causes @command{patch} to do the following: X X@itemize @bullet X@item XSkip patches that do not contain file names in their headers. X X@item XPatch files even though they have the wrong version for the X@samp{Prereq:} line in the patch; X X@item XAssume that patches are not reversed even if they look like they are. X@end itemize X X@noindent XThe @option{-t} or @option{--batch} option is similar to @option{-f}, in that Xit suppresses questions, but it makes somewhat different assumptions: X X@itemize @bullet X@item XSkip patches that do not contain file names in their headers X(the same as @option{-f}). X X@item XSkip patches for which the file has the wrong version for the X@samp{Prereq:} line in the patch; X X@item XAssume that patches are reversed if they look like they are. X@end itemize X X@node patch Quoting Style X@subsection @command{patch} Quoting Style X@cindex quoting style X XWhen @command{patch} outputs a file name in a diagnostic message, it Xcan format the name in any of several ways. This can be useful to Xoutput file names unambiguously, even if they contain punctuation or Xspecial characters like newlines. The X@option{--quoting-style=@var{word}} option controls how names are Xoutput. The @var{word} should be one of the following: X X@table @samp X@item literal XOutput names as-is. X@item shell XQuote names for the shell if they contain shell metacharacters or would Xcause ambiguous output. X@item shell-always XQuote names for the shell, even if they would normally not require quoting. X@item c XQuote names as for a C language string. X@item escape XQuote as with @samp{c} except omit the surrounding double-quote Xcharacters. X@c The following are not yet implemented in patch 2.5.4. X@c @item clocale X@c Quote as with @samp{c} except use quotation marks appropriate for the X@c locale. X@c @item locale X@c @c Use @t instead of @samp to avoid duplicate quoting in some output styles. X@c Like @samp{clocale}, but quote @t{`like this'} instead of @t{"like X@c this"} in the default C locale. This looks nicer on many displays. X@end table X X@vindex QUOTING_STYLE XYou can specify the default value of the @option{--quoting-style} Xoption with the environment variable @env{QUOTING_STYLE}. If that Xenvironment variable is not set, the default value is @samp{shell}, Xbut this default may change in a future version of @command{patch}. X X@node patch and POSIX X@section @command{patch} and the @sc{posix} Standard X@cindex @sc{posix} X X@vindex POSIXLY_CORRECT XIf you specify the @option{--posix} option, or set the X@env{POSIXLY_CORRECT} environment variable, @command{patch} conforms Xmore strictly to the @sc{posix} standard, as follows: X X@itemize @bullet X@item XTake the first existing file from the list (old, new, index) Xwhen intuiting file names from diff headers. @xref{Multiple Patches}. X X@item XDo not remove files that are removed by a diff. X@xref{Creating and Removing}. X X@item XDo not ask whether to get files from @sc{rcs}, ClearCase, or X@sc{sccs}. @xref{Revision Control}. X X@item XRequire that all options precede the files in the command line. X X@item XDo not backup files, even when there is a mismatch. @xref{Backups}. X X@end itemize X X@node patch and Tradition X@section @sc{gnu} @command{patch} and Traditional @command{patch} X@cindex traditional @command{patch} X XThe current version of @sc{gnu} @command{patch} normally follows the X@sc{posix} standard. @xref{patch and POSIX}, for the few exceptions Xto this general rule. X XUnfortunately, @sc{posix} redefined the behavior of @command{patch} in Xseveral important ways. You should be aware of the following Xdifferences if you must interoperate with traditional @command{patch}, Xor with @sc{gnu} @command{patch} version 2.1 and earlier. X X@itemize @bullet X@item XIn traditional @command{patch}, the @option{-p} option's operand was Xoptional, and a bare @option{-p} was equivalent to @option{-p0}. The X@option{-p} option now requires an operand, and @option{-p@ 0} is now Xequivalent to @option{-p0}. For maximum compatibility, use options Xlike @option{-p0} and @option{-p1}. X XAlso, traditional @command{patch} simply counted slashes when Xstripping path prefixes; @command{patch} now counts pathname Xcomponents. That is, a sequence of one or more adjacent slashes now Xcounts as a single slash. For maximum portability, avoid sending Xpatches containing @file{//} in file names. X X@item XIn traditional @command{patch}, backups were enabled by default. This Xbehavior is now enabled with the @option{-b} or @option{--backup} Xoption. X XConversely, in @sc{posix} @command{patch}, backups are never made, Xeven when there is a mismatch. In @sc{gnu} @command{patch}, this Xbehavior is enabled with the @option{--no-backup-if-mismatch} option, Xor by conforming to @sc{posix}. X XThe @option{-b@ @var{suffix}} option of traditional @command{patch} is Xequivalent to the @samp{-b -z@ @var{suffix}} options of @sc{gnu} X@command{patch}. X X@item XTraditional @command{patch} used a complicated (and incompletely Xdocumented) method to intuit the name of the file to be patched from Xthe patch header. This method did not conform to @sc{posix}, and had Xa few gotchas. Now @command{patch} uses a different, equally Xcomplicated (but better documented) method that is optionally X@sc{posix}-conforming; we hope it has fewer gotchas. The two methods Xare compatible if the file names in the context diff header and the X@samp{Index:} line are all identical after prefix-stripping. Your Xpatch is normally compatible if each header's file names all contain Xthe same number of slashes. X X@item XWhen traditional @command{patch} asked the user a question, it sent Xthe question to standard error and looked for an answer from the first Xfile in the following list that was a terminal: standard error, Xstandard output, @file{/dev/tty}, and standard input. Now X@command{patch} sends questions to standard output and gets answers Xfrom @file{/dev/tty}. Defaults for some answers have been changed so Xthat @command{patch} never goes into an infinite loop when using Xdefault answers. X X@item XTraditional @command{patch} exited with a status value that counted Xthe number of bad hunks, or with status 1 if there was real trouble. XNow @command{patch} exits with status 1 if some hunks failed, or with X2 if there was real trouble. X X@item XLimit yourself to the following options when sending instructions Xmeant to be executed by anyone running @sc{gnu} @command{patch}, Xtraditional @command{patch}, or a @command{patch} that conforms to X@sc{posix}. Spaces are significant in the following list, and Xoperands are required. X X@example X@option{-c} X@option{-d @var{dir}} X@option{-D @var{define}} X@option{-e} X@option{-l} X@option{-n} X@option{-N} X@option{-o @var{outfile}} X@option{-p@var{num}} X@option{-R} X@option{-r @var{rejectfile}} X@end example X X@end itemize X X@node Making Patches X@chapter Tips for Making and Using Patches X XUse some common sense when making and using patches. For example, Xwhen sending bug fixes to a program's maintainer, send several small Xpatches, one per independent subject, instead of one large, Xharder-to-digest patch that covers all the subjects. X XHere are some other things you should keep in mind if you are going to Xdistribute patches for updating a software package. X X@menu X* Tips for Patch Producers:: Advice for making patches. X* Tips for Patch Consumers:: Advice for using patches. X* Avoiding Common Mistakes:: Avoiding common mistakes when using @command{patch}. X* Generating Smaller Patches:: How to generate smaller patches. X@end menu X X@node Tips for Patch Producers X@section Tips for Patch Producers X@cindex patch producer tips X XTo create a patch that changes an older version of a package into a Xnewer version, first make a copy of the older and newer versions in Xadjacent subdirectories. It is common to do that by unpacking X@command{tar} archives of the two versions. X XTo generate the patch, use the command @samp{diff -Naur @var{old} X@var{new}} where @var{old} and @var{new} identify the old and new Xdirectories. The names @var{old} and @var{new} should not contain any Xslashes. The @option{-N} option lets the patch create and remove Xfiles; @option{-a} lets the patch update non-text files; @option{-u} Xgenerates useful time stamps and enough context; and @option{-r} lets Xthe patch update subdirectories. Here is an example command, using XBourne shell syntax: X X@example Xdiff -Naur gcc-3.0.3 gcc-3.0.4 X@end example X XTell your recipients how to apply the patches. This should include Xwhich working directory to use, and which @command{patch} options to Xuse; the option @samp{-p1} is recommended. Test your procedure by Xpretending to be a recipient and applying your patches to a copy of Xthe original files. X X@xref{Avoiding Common Mistakes}, for how to avoid common mistakes when Xgenerating a patch. X X@node Tips for Patch Consumers X@section Tips for Patch Consumers X@cindex patch consumer tips X XA patch producer should tell recipients how to apply the patches, so Xthe first rule of thumb for a patch consumer is to follow the Xinstructions supplied with the patch. X X@sc{gnu} @command{diff} can analyze files with arbitrarily long lines Xand files that end in incomplete lines. However, older versions of X@command{patch} cannot patch such files. If you are having trouble Xapplying such patches, try upgrading to a recent version of @sc{gnu} X@command{patch}. X X@node Avoiding Common Mistakes X@section Avoiding Common Mistakes X@cindex common mistakes with patches X@cindex patch, common mistakes X XWhen producing a patch for multiple files, apply @command{diff} to Xdirectories whose names do not have slashes. This reduces confusion Xwhen the patch consumer specifies the @option{-p@var{number}} option, Xsince this option can have surprising results when the old and new Xfile names have different numbers of slashes. For example, do not Xsend a patch with a header that looks like this: X X@example Xdiff -Naur v2.0.29/prog/README prog/README X--- v2.0.29/prog/README 2002-03-10 23:30:39.942229878 -0800 X+++ prog/README 2002-03-17 20:49:32.442260588 -0800 X@end example X X@noindent Xbecause the two file names have different numbers of slashes, and Xdifferent versions of @command{patch} interpret the file names Xdifferently. To avoid confusion, send output that looks like this Xinstead: X X@example Xdiff -Naur v2.0.29/prog/README v2.0.30/prog/README X--- v2.0.29/prog/README 2002-03-10 23:30:39.942229878 -0800 X+++ v2.0.30/prog/README 2002-03-17 20:49:32.442260588 -0800 X@end example X XMake sure you have specified the file names correctly, either in a Xcontext diff header or with an @samp{Index:} line. Take care to not send out Xreversed patches, since these make people wonder whether they have Xalready applied the patch. X XAvoid sending patches that compare backup file names like X@file{README.orig} or @file{README~}, since this might confuse X@command{patch} into patching a backup file instead of the real file. XInstead, send patches that compare the same base file names in Xdifferent directories, e.g.@: @file{old/README} and @file{new/README}. X XTo save people from partially applying a patch before other patches that Xshould have gone before it, you can make the first patch in the patch Xfile update a file with a name like @file{patchlevel.h} or X@file{version.c}, which contains a patch level or version number. If Xthe input file contains the wrong version number, @command{patch} will Xcomplain immediately. X XAn even clearer way to prevent this problem is to put a @samp{Prereq:} Xline before the patch. If the leading text in the patch file contains a Xline that starts with @samp{Prereq:}, @command{patch} takes the next word Xfrom that line (normally a version number) and checks whether the next Xinput file contains that word, preceded and followed by either Xwhite space or a newline. If not, @command{patch} prompts you for Xconfirmation before proceeding. This makes it difficult to accidentally Xapply patches in the wrong order. X X@node Generating Smaller Patches X@section Generating Smaller Patches X@cindex patches, shrinking X XThe simplest way to generate a patch is to use @samp{diff -Naur} X(@pxref{Tips for Patch Producers}), but you might be able to reduce Xthe size of the patch by renaming or removing some files before making Xthe patch. If the older version of the package contains any files Xthat the newer version does not, or if any files have been renamed Xbetween the two versions, make a list of @command{rm} and @command{mv} Xcommands for the user to execute in the old version directory before Xapplying the patch. Then run those commands yourself in the scratch Xdirectory. X XIf there are any files that you don't need to include in the patch Xbecause they can easily be rebuilt from other files (for example, X@file{TAGS} and output from @command{yacc} and @command{makeinfo}), Xexclude them from the patch by giving @command{diff} the @option{-x X@var{pattern}} option (@pxref{Comparing Directories}). If you want Xyour patch to modify a derived file because your recipients lack tools Xto build it, make sure that the patch for the derived file follows any Xpatches for files that it depends on, so that the recipients' time Xstamps will not confuse @command{make}. X XNow you can create the patch using @samp{diff -Naur}. Make sure to Xspecify the scratch directory first and the newer directory second. X XAdd to the top of the patch a note telling the user any @command{rm} and X@command{mv} commands to run before applying the patch. Then you can Xremove the scratch directory. X XYou can also shrink the patch size by using fewer lines of context, Xbut bear in mind that @command{patch} typically needs at least two Xlines for proper operation when patches do not exactly match the input Xfiles. X X@node Invoking cmp X@chapter Invoking @command{cmp} X@cindex invoking @command{cmp} X@cindex @command{cmp} invocation X XThe @command{cmp} command compares two files, and if they differ, Xtells the first byte and line number where they differ. Bytes and Xlines are numbered starting with 1. The arguments of @command{cmp} Xare as follows: X X@example Xcmp @var{options}@dots{} @var{from-file} @r{[}@var{to-file} @r{[}@var{from-skip} @r{[}@var{to-skip}@r{]}@r{]}@r{]} X@end example X XThe file name @file{-} is always the standard input. @command{cmp} Xalso uses the standard input if one file name is omitted. The X@var{from-skip} and @var{to-skip} operands specify how many bytes to Xignore at the start of each file; they are equivalent to the X@option{--ignore-initial=@var{from-skip}:@var{to-skip}} option. X XAn exit status of 0 means no differences were found, 1 means some Xdifferences were found, and 2 means trouble. X X@menu X* cmp Options:: Summary of options to @command{cmp}. X@end menu X X@node cmp Options X@section Options to @command{cmp} X@cindex @command{cmp} options X@cindex options for @command{cmp} X XBelow is a summary of all of the options that @sc{gnu} @command{cmp} accepts. XMost options have two equivalent names, one of which is a single letter Xpreceded by @samp{-}, and the other of which is a long name preceded by X@samp{--}. Multiple single letter options (unless they take an Xargument) can be combined into a single command line word: @option{-bl} is Xequivalent to @option{-b -l}. X X@table @option X@item -b X@itemx --print-bytes XPrint the differing bytes. Display control bytes as a X@samp{^} followed by a letter of the alphabet and precede bytes Xthat have the high bit set with @samp{M-} (which stands for ``meta''). X X@item --help XOutput a summary of usage and then exit. X X@item -i @var{skip} X@itemx --ignore-initial=@var{skip} XIgnore any differences in the first @var{skip} bytes of the input Xfiles. Treat files with fewer than @var{skip} bytes as if they are Xempty. If @var{skip} is of the form X@option{@var{from-skip}:@var{to-skip}}, skip the first @var{from-skip} Xbytes of the first input file and the first @var{to-skip} bytes of the Xsecond. X X@item -l X@itemx --verbose XPrint the (decimal) byte numbers and (octal) values of all differing bytes. X X@item -n @var{count} X@itemx --bytes=@var{count} XCompare at most @var{count} input bytes. X X@item -s X@itemx --quiet X@itemx --silent XDo not print anything; only return an exit status indicating whether Xthe files differ. X X@item -v X@itemx --version XOutput version information and then exit. X@end table X XIn the above table, operands that are byte counts are normally Xdecimal, but may be preceded by @samp{0} for octal and @samp{0x} for Xhexadecimal. X XA byte count can be followed by a suffix to specify a multiple of that Xcount; in this case an omitted integer is understood to be 1. A bare Xsize letter, or one followed by @samp{iB}, specifies a multiple using Xpowers of 1024. A size letter followed by @samp{B} specifies powers Xof 1000 instead. For example, @option{-n 4M} and @option{-n 4MiB} are Xequivalent to @option{-n 4194304}, whereas @option{-n 4MB} is Xequivalent to @option{-n 4000000}. This notation is upward compatible Xwith the @uref{http://www.bipm.fr/enus/3_SI/si-prefixes.html, SI Xprefixes} for decimal multiples and with the X@uref{http://physics.nist.gov/cuu/Units/binary.html, IEC 60027-2 Xprefixes for binary multiples}. X XThe following suffixes are defined. Large sizes like @code{1Y} may be Xrejected by your computer due to limitations of its arithmetic. X X@table @samp X@item kB X@cindex kilobyte, definition of Xkilobyte: @math{10^3 = 1000}. X@item k X@itemx K X@itemx KiB X@cindex kibibyte, definition of Xkibibyte: @math{2^10 = 1024}. @samp{K} is special: the SI prefix is X@samp{k} and the IEC 60027-2 prefix is @samp{Ki}, but tradition and X@sc{posix} use @samp{k} to mean @samp{KiB}. X@item MB X@cindex megabyte, definition of Xmegabyte: @math{10^6 = 1,000,000}. X@item M X@itemx MiB X@cindex mebibyte, definition of Xmebibyte: @math{2^20 = 1,048,576}. X@item GB X@cindex gigabyte, definition of Xgigabyte: @math{10^9 = 1,000,000,000}. X@item G X@itemx GiB X@cindex gibibyte, definition of Xgibibyte: @math{2^30 = 1,073,741,824}. X@item TB X@cindex terabyte, definition of Xterabyte: @math{10^12 = 1,000,000,000,000}. X@item T X@itemx TiB X@cindex tebibyte, definition of Xtebibyte: @math{2^40 = 1,099,511,627,776}. X@item PB X@cindex petabyte, definition of Xpetabyte: @math{10^15 = 1,000,000,000,000,000}. X@item P X@itemx PiB X@cindex pebibyte, definition of Xpebibyte: @math{2^50 = 1,125,899,906,842,624}. X@item EB X@cindex exabyte, definition of Xexabyte: @math{10^18 = 1,000,000,000,000,000,000}. X@item E X@itemx EiB X@cindex exbibyte, definition of Xexbibyte: @math{2^60 = 1,152,921,504,606,846,976}. X@item ZB X@cindex zettabyte, definition of Xzettabyte: @math{10^21 = 1,000,000,000,000,000,000,000} X@item Z X@itemx ZiB X@math{2^70 = 1,180,591,620,717,411,303,424}. X(@samp{Zi} is a GNU extension to IEC 60027-2.) X@item YB X@cindex yottabyte, definition of Xyottabyte: @math{10^24 = 1,000,000,000,000,000,000,000,000}. X@item Y X@itemx YiB X@math{2^80 = 1,208,925,819,614,629,174,706,176}. X(@samp{Yi} is a GNU extension to IEC 60027-2.) X@end table X X@node Invoking diff X@chapter Invoking @command{diff} X@cindex invoking @command{diff} X@cindex @command{diff} invocation X XThe format for running the @command{diff} command is: X X@example Xdiff @var{options}@dots{} @var{files}@dots{} X@end example X XIn the simplest case, two file names @var{from-file} and X@var{to-file} are given, and @command{diff} compares the contents of X@var{from-file} and @var{to-file}. A file name of @file{-} stands for Xtext read from the standard input. As a special case, @samp{diff - -} Xcompares a copy of standard input to itself. X XIf one file is a directory and the other is not, @command{diff} compares Xthe file in the directory whose name is that of the non-directory. XThe non-directory file must not be @file{-}. X XIf two file names are given and both are directories, X@command{diff} compares corresponding files in both directories, in Xalphabetical order; this comparison is not recursive unless the X@option{-r} or @option{--recursive} option is given. @command{diff} never Xcompares the actual contents of a directory as if it were a file. The Xfile that is fully specified may not be standard input, because standard Xinput is nameless and the notion of ``file with the same name'' does not Xapply. X XIf the @option{--from-file=@var{file}} option is given, the number of Xfile names is arbitrary, and @var{file} is compared to each named file. XSimilarly, if the @option{--to-file=@var{file}} option is given, each Xnamed file is compared to @var{file}. X X@command{diff} options begin with @samp{-}, so normally file names Xmay not begin with @samp{-}. However, @option{--} as an Xargument by itself treats the remaining arguments as file names even if Xthey begin with @samp{-}. X XAn exit status of 0 means no differences were found, 1 means some Xdifferences were found, and 2 means trouble. X X@menu X* diff Options:: Summary of options to @command{diff}. X@end menu X X@node diff Options X@section Options to @command{diff} X@cindex @command{diff} options X@cindex options for @command{diff} X XBelow is a summary of all of the options that @sc{gnu} @command{diff} accepts. XMost options have two equivalent names, one of which is a single letter Xpreceded by @samp{-}, and the other of which is a long name preceded by X@samp{--}. Multiple single letter options (unless they take an Xargument) can be combined into a single command line word: @option{-ac} is Xequivalent to @option{-a -c}. Long named options can be abbreviated to Xany unique prefix of their name. Brackets ([ and ]) indicate that an Xoption takes an optional argument. X X@table @option X@item -a X@itemx --text XTreat all files as text and compare them line-by-line, even if they Xdo not seem to be text. @xref{Binary}. X X@item -b X@itemx --ignore-space-change XIgnore changes in amount of white space. @xref{White Space}. X X@item -B X@itemx --ignore-blank-lines XIgnore changes that just insert or delete blank lines. @xref{Blank XLines}. X X@item --binary XRead and write data in binary mode. @xref{Binary}. X X@item -c XUse the context output format, showing three lines of context. X@xref{Context Format}. X X@item -C @var{lines} X@itemx --context@r{[}=@var{lines}@r{]} XUse the context output format, showing @var{lines} (an integer) lines of Xcontext, or three if @var{lines} is not given. @xref{Context Format}. XFor proper operation, @command{patch} typically needs at least two lines of Xcontext. X XOn older systems, @command{diff} supports an obsolete option X@option{-@var{lines}} that has effect when combined with @option{-c} Xor @option{-p}. @sc{posix} 1003.1-2001 (@pxref{Standards Xconformance}) does not allow this; use @option{-C @var{lines}} Xinstead. X X@item --changed-group-format=@var{format} XUse @var{format} to output a line group containing differing lines from Xboth files in if-then-else format. @xref{Line Group Formats}. X X@item -d X@itemx --minimal XChange the algorithm perhaps find a smaller set of changes. This makes X@command{diff} slower (sometimes much slower). @xref{diff Performance}. X X@item -D @var{name} X@itemx --ifdef=@var{name} XMake merged @samp{#ifdef} format output, conditional on the preprocessor Xmacro @var{name}. @xref{If-then-else}. X X@item -e X@itemx --ed XMake output that is a valid @command{ed} script. @xref{ed Scripts}. X X@item -E X@itemx --ignore-tab-expansion XIgnore changes due to tab expansion. X@xref{White Space}. X X@item -f X@itemx --forward-ed XMake output that looks vaguely like an @command{ed} script but has changes Xin the order they appear in the file. @xref{Forward ed}. X X@item -F @var{regexp} X@itemx --show-function-line=@var{regexp} XIn context and unified format, for each hunk of differences, show some Xof the last preceding line that matches @var{regexp}. @xref{Specified XHeadings}. X X@item --from-file=@var{file} XCompare @var{file} to each operand; @var{file} may be a directory. X X@item --help XOutput a summary of usage and then exit. X X@item --horizon-lines=@var{lines} XDo not discard the last @var{lines} lines of the common prefix Xand the first @var{lines} lines of the common suffix. X@xref{diff Performance}. X X@item -i X@itemx --ignore-case XIgnore changes in case; consider upper- and lower-case letters Xequivalent. @xref{Case Folding}. X X@item -I @var{regexp} X@itemx --ignore-matching-lines=@var{regexp} XIgnore changes that just insert or delete lines that match @var{regexp}. X@xref{Specified Folding}. X X@item --ignore-file-name-case XIgnore case when comparing file names during recursive comparison. X@xref{Comparing Directories}. X X@item -l X@itemx --paginate XPass the output through @command{pr} to paginate it. @xref{Pagination}. X X@item --label=@var{label} XUse @var{label} instead of the file name in the context format X(@pxref{Context Format}) and unified format (@pxref{Unified Format}) Xheaders. @xref{RCS}. X X@item --left-column XPrint only the left column of two common lines in side by side format. X@xref{Side by Side Format}. X X@item --line-format=@var{format} XUse @var{format} to output all input lines in if-then-else format. X@xref{Line Formats}. X X@item -n X@itemx --rcs XOutput @sc{rcs}-format diffs; like @option{-f} except that each command Xspecifies the number of lines affected. @xref{RCS}. X X@item -N X@itemx --new-file XIn directory comparison, if a file is found in only one directory, Xtreat it as present but empty in the other directory. @xref{Comparing XDirectories}. X X@item --new-group-format=@var{format} XUse @var{format} to output a group of lines taken from just the second Xfile in if-then-else format. @xref{Line Group Formats}. X X@item --new-line-format=@var{format} XUse @var{format} to output a line taken from just the second file in Xif-then-else format. @xref{Line Formats}. X X@item --old-group-format=@var{format} XUse @var{format} to output a group of lines taken from just the first Xfile in if-then-else format. @xref{Line Group Formats}. X X@item --old-line-format=@var{format} XUse @var{format} to output a line taken from just the first file in Xif-then-else format. @xref{Line Formats}. X X@item -p X@itemx --show-c-function XShow which C function each change is in. @xref{C Function Headings}. X X@item -q X@itemx --brief XReport only whether the files differ, not the details of the Xdifferences. @xref{Brief}. X X@item -r X@itemx --recursive XWhen comparing directories, recursively compare any subdirectories Xfound. @xref{Comparing Directories}. X X@item -s X@itemx --report-identical-files XReport when two files are the same. @xref{Comparing Directories}. X X@item -S @var{file} X@itemx --starting-file=@var{file} XWhen comparing directories, start with the file @var{file}. This is Xused for resuming an aborted comparison. @xref{Comparing Directories}. X X@item --speed-large-files XUse heuristics to speed handling of large files that have numerous Xscattered small changes. @xref{diff Performance}. X X@item --strip-trailing-cr XStrip any trailing carriage return at the end of an input line. X@xref{Binary}. X X@item --suppress-common-lines XDo not print common lines in side by side format. X@xref{Side by Side Format}. X X@item -t X@itemx --expand-tabs XExpand tabs to spaces in the output, to preserve the alignment of tabs Xin the input files. @xref{Tabs}. X X@item -T X@itemx --initial-tab XOutput a tab rather than a space before the text of a line in normal or Xcontext format. This causes the alignment of tabs in the line to look Xnormal. @xref{Tabs}. X X@item --to-file=@var{file} XCompare each operand to @var{file}; @var{file} may be a directory. X X@item -u XUse the unified output format, showing three lines of context. X@xref{Unified Format}. X X@item --unchanged-group-format=@var{format} XUse @var{format} to output a group of common lines taken from both files Xin if-then-else format. @xref{Line Group Formats}. X X@item --unchanged-line-format=@var{format} XUse @var{format} to output a line common to both files in if-then-else Xformat. @xref{Line Formats}. X X@item --unidirectional-new-file XWhen comparing directories, if a file appears only in the second Xdirectory of the two, treat it as present but empty in the other. X@xref{Comparing Directories}. X X@item -U @var{lines} X@itemx --unified@r{[}=@var{lines}@r{]} XUse the unified output format, showing @var{lines} (an integer) lines of Xcontext, or three if @var{lines} is not given. @xref{Unified Format}. XFor proper operation, @command{patch} typically needs at least two lines of Xcontext. X XOn older systems, @command{diff} supports an obsolete option X@option{-@var{lines}} that has effect when combined with @option{-u}. X@sc{posix} 1003.1-2001 (@pxref{Standards conformance}) does not allow Xthis; use @option{-U @var{lines}} instead. X X@item -v X@itemx --version XOutput version information and then exit. X X@item -w X@itemx --ignore-all-space XIgnore white space when comparing lines. @xref{White Space}. X X@item -W @var{columns} X@itemx --width=@var{columns} XOutput at most @var{columns} (default 130) print columns per line in Xside by side format. @xref{Side by Side Format}. X X@item -x @var{pattern} X@itemx --exclude=@var{pattern} XWhen comparing directories, ignore files and subdirectories whose basenames Xmatch @var{pattern}. @xref{Comparing Directories}. X X@item -X @var{file} X@itemx --exclude-from=@var{file} XWhen comparing directories, ignore files and subdirectories whose basenames Xmatch any pattern contained in @var{file}. @xref{Comparing Directories}. X X@item -y X@itemx --side-by-side XUse the side by side output format. @xref{Side by Side Format}. X@end table X X@node Invoking diff3 X@chapter Invoking @command{diff3} X@cindex invoking @command{diff3} X@cindex @command{diff3} invocation X XThe @command{diff3} command compares three files and outputs descriptions Xof their differences. Its arguments are as follows: X X@example Xdiff3 @var{options}@dots{} @var{mine} @var{older} @var{yours} X@end example X XThe files to compare are @var{mine}, @var{older}, and @var{yours}. XAt most one of these three file names may be @file{-}, Xwhich tells @command{diff3} to read the standard input for that file. X XAn exit status of 0 means @command{diff3} was successful, 1 means some Xconflicts were found, and 2 means trouble. X X@menu X* diff3 Options:: Summary of options to @command{diff3}. X@end menu X X@node diff3 Options X@section Options to @command{diff3} X@cindex @command{diff3} options X@cindex options for @command{diff3} X XBelow is a summary of all of the options that @sc{gnu} @command{diff3} Xaccepts. Multiple single letter options (unless they take an argument) Xcan be combined into a single command line argument. X X@table @option X@item -a X@itemx --text XTreat all files as text and compare them line-by-line, even if they Xdo not appear to be text. @xref{Binary}. X X@item -A X@itemx --show-all XIncorporate all unmerged changes from @var{older} to @var{yours} into X@var{mine}, surrounding conflicts with bracket lines. X@xref{Marking Conflicts}. X X@item --diff-program=@var{program} XUse the compatible comparison program @var{program} to compare files Xinstead of @command{diff}. X X@item -e X@itemx --ed XGenerate an @command{ed} script that incorporates all the changes from X@var{older} to @var{yours} into @var{mine}. @xref{Which Changes}. X X@item -E X@itemx --show-overlap XLike @option{-e}, except bracket lines from overlapping changes' first Xand third files. X@xref{Marking Conflicts}. XWith @option{-E}, an overlapping change looks like this: X X@example X<<<<<<< @var{mine} X@r{lines from @var{mine}} X======= X@r{lines from @var{yours}} X>>>>>>> @var{yours} X@end example X X@item --help XOutput a summary of usage and then exit. X X@item -i XGenerate @samp{w} and @samp{q} commands at the end of the @command{ed} Xscript for System V compatibility. This option must be combined with Xone of the @option{-AeExX3} options, and may not be combined with @option{-m}. X@xref{Saving the Changed File}. X X@item -L @var{label} X@itemx --label=@var{label} XUse the label @var{label} for the brackets output by the @option{-A}, X@option{-E} and @option{-X} options. This option may be given up to three Xtimes, one for each input file. The default labels are the names of Xthe input files. Thus @samp{diff3 -L X -L Y -L Z -m A B C} acts like X@samp{diff3 -m A B C}, except that the output looks like it came from Xfiles named @samp{X}, @samp{Y} and @samp{Z} rather than from files Xnamed @samp{A}, @samp{B} and @samp{C}. @xref{Marking Conflicts}. X X@item -m X@itemx --merge XApply the edit script to the first file and send the result to standard Xoutput. Unlike piping the output from @command{diff3} to @command{ed}, this Xworks even for binary files and incomplete lines. @option{-A} is assumed Xif no edit script option is specified. @xref{Bypassing ed}. X X@item -T X@itemx --initial-tab XOutput a tab rather than two spaces before the text of a line in normal format. XThis causes the alignment of tabs in the line to look normal. @xref{Tabs}. X X@item -v X@itemx --version XOutput version information and then exit. X X@item -x X@itemx --overlap-only XLike @option{-e}, except output only the overlapping changes. X@xref{Which Changes}. X X@item -X XLike @option{-E}, except output only the overlapping changes. XIn other words, like @option{-x}, except bracket changes as in @option{-E}. X@xref{Marking Conflicts}. X X@item -3 X@itemx --easy-only XLike @option{-e}, except output only the nonoverlapping changes. X@xref{Which Changes}. X@end table X X@node Invoking patch X@chapter Invoking @command{patch} X@cindex invoking @command{patch} X@cindex @command{patch} invocation X XNormally @command{patch} is invoked like this: X X@example Xpatch <@var{patchfile} X@end example X XThe full format for invoking @command{patch} is: X X@example Xpatch @var{options}@dots{} @r{[}@var{origfile} @r{[}@var{patchfile}@r{]}@r{]} X@end example X XYou can also specify where to read the patch from with the @option{-i X@var{patchfile}} or @option{--input=@var{patchfile}} option. XIf you do not specify @var{patchfile}, or if @var{patchfile} is X@file{-}, @command{patch} reads the patch (that is, the @command{diff} output) Xfrom the standard input. X XIf you do not specify an input file on the command line, @command{patch} Xtries to intuit from the @dfn{leading text} (any text in the patch Xthat comes before the @command{diff} output) which file to edit. X@xref{Multiple Patches}. X XBy default, @command{patch} replaces the original input file with the Xpatched version, possibly after renaming the original file into a Xbackup file (@pxref{Backup Names}, for a description of how X@command{patch} names backup files). You can also specify where to Xput the output with the @option{-o @var{file}} or X@option{--output=@var{file}} option; however, do not use this option Xif @var{file} is one of the input files. X X@menu X* patch Options:: Summary table of options to @command{patch}. X@end menu X X@node patch Options X@section Options to @command{patch} X@cindex @command{patch} options X@cindex options for @command{patch} X XHere is a summary of all of the options that @sc{gnu} @command{patch} Xaccepts. @xref{patch and Tradition}, for which of these options are Xsafe to use in older versions of @command{patch}. X XMultiple single-letter options that do not take an argument can be Xcombined into a single command line argument with only one dash. X X@table @option X@item -b X@itemx --backup XBack up the original contents of each file, even if backups would Xnormally not be made. @xref{Backups}. X X@item -B @var{prefix} X@itemx --prefix=@var{prefix} XPrepend @var{prefix} to backup file names. @xref{Backup Names}. X X@item --backup-if-mismatch XBack up the original contents of each file if the patch does not Xexactly match the file. This is the default behavior when not Xconforming to @sc{posix}. @xref{Backups}. X X@item --binary XRead and write all files in binary mode, except for standard output Xand @file{/dev/tty}. This option has no effect on X@sc{posix}-conforming systems like @sc{gnu}/Linux. On systems where Xthis option makes a difference, the patch should be generated by X@samp{diff -a --binary}. @xref{Binary}. X X@item -c X@itemx --context XInterpret the patch file as a context diff. @xref{patch Input}. X X@item -d @var{directory} X@itemx --directory=@var{directory} XMake directory @var{directory} the current directory for interpreting Xboth file names in the patch file, and file names given as arguments to Xother options. @xref{patch Directories}. X X@item -D @var{name} X@itemx --ifdef=@var{name} XMake merged if-then-else output using @var{name}. @xref{If-then-else}. X X@item --dry-run XPrint the results of applying the patches without actually changing Xany files. @xref{Dry Runs}. X X@item -e X@itemx --ed XInterpret the patch file as an @command{ed} script. @xref{patch Input}. X X@item -E X@itemx --remove-empty-files XRemove output files that are empty after the patches have been applied. X@xref{Creating and Removing}. X X@item -f X@itemx --force XAssume that the user knows exactly what he or she is doing, and do not Xask any questions. @xref{patch Messages}. X X@item -F @var{lines} X@itemx --fuzz=@var{lines} XSet the maximum fuzz factor to @var{lines}. @xref{Inexact}. X X@item -g @var{num} X@itemx --get=@var{num} XIf @var{num} is positive, get input files from a revision control Xsystem as necessary; if zero, do not get the files; if negative, ask Xthe user whether to get the files. @xref{Revision Control}. X X@item --help XOutput a summary of usage and then exit. X X@item -i @var{patchfile} X@itemx --input=@var{patchfile} XRead the patch from @var{patchfile} rather than from standard input. X@xref{patch Options}. X X@item -l X@itemx --ignore-white-space XLet any sequence of blanks (spaces or tabs) in the patch file match Xany sequence of blanks in the input file. @xref{Changed White Space}. X X@item -n X@itemx --normal XInterpret the patch file as a normal diff. @xref{patch Input}. X X@item -N X@itemx --forward XIgnore patches that @command{patch} thinks are reversed or already applied. XSee also @option{-R}. @xref{Reversed Patches}. X X@item --no-backup-if-mismatch XDo not back up the original contents of files. This is the default Xbehavior when conforming to @sc{posix}. @xref{Backups}. X X@item -o @var{file} X@itemx --output=@var{file} XUse @var{file} as the output file name. @xref{patch Options}. X X@item -p@var{number} X@itemx --strip=@var{number} XSet the file name strip count to @var{number}. @xref{patch Directories}. X X@item --posix XConform to @sc{posix}, as if the @env{POSIXLY_CORRECT} environment Xvariable had been set. @xref{patch and POSIX}. X X@item --quoting-style=@var{word} XUse style @var{word} to quote names in diagnostics, as if the X@env{QUOTING_STYLE} environment variable had been set to @var{word}. X@xref{patch Quoting Style}. X X@item -r @var{reject-file} X@itemx --reject-file=@var{reject-file} XUse @var{reject-file} as the reject file name. @xref{Reject Names}. X X@item -R X@itemx --reverse XAssume that this patch was created with the old and new files swapped. X@xref{Reversed Patches}. X X@item -s X@itemx --quiet X@itemx --silent XWork silently unless an error occurs. @xref{patch Messages}. X X@item -t X@itemx --batch XDo not ask any questions. @xref{patch Messages}. X X@item -T X@itemx --set-time XSet the modification and access times of patched files from time Xstamps given in context diff headers, assuming that the context diff Xheaders use local time. @xref{Patching Time Stamps}. X X@item -u X@itemx --unified XInterpret the patch file as a unified diff. @xref{patch Input}. X X@item -v X@itemx --version XOutput version information and then exit. X X@item -V @var{backup-style} X@itemx --version=control=@var{backup-style} XSelect the naming convention for backup file names. @xref{Backup Names}. X X@item --verbose XPrint more diagnostics than usual. @xref{patch Messages}. X X@item -x @var{number} X@itemx --debug=@var{number} XSet internal debugging flags. Of interest only to @command{patch} Xpatchers. X X@item -Y @var{prefix} X@itemx --basename-prefix=@var{prefix} XPrepend @var{prefix} to base names of backup files. @xref{Backup Names}. X X@item -z @var{suffix} X@itemx --suffix=@var{suffix} XUse @var{suffix} as the backup extension instead of @samp{.orig} or X@samp{~}. @xref{Backup Names}. X X@item -Z X@itemx --set-utc XSet the modification and access times of patched files from time Xstamps given in context diff headers, assuming that the context diff Xheaders use @sc{utc}. @xref{Patching Time Stamps}. X X@end table X X@node Invoking sdiff X@chapter Invoking @command{sdiff} X@cindex invoking @command{sdiff} X@cindex @command{sdiff} invocation X XThe @command{sdiff} command merges two files and interactively outputs the Xresults. Its arguments are as follows: X X@example Xsdiff -o @var{outfile} @var{options}@dots{} @var{from-file} @var{to-file} X@end example X XThis merges @var{from-file} with @var{to-file}, with output to @var{outfile}. XIf @var{from-file} is a directory and @var{to-file} is not, @command{sdiff} Xcompares the file in @var{from-file} whose file name is that of @var{to-file}, Xand vice versa. @var{from-file} and @var{to-file} may not both be Xdirectories. X X@command{sdiff} options begin with @samp{-}, so normally @var{from-file} Xand @var{to-file} may not begin with @samp{-}. However, @option{--} as an Xargument by itself treats the remaining arguments as file names even if Xthey begin with @samp{-}. You may not use @file{-} as an input file. X X@command{sdiff} without @option{-o} (or @option{--output}) produces a Xside-by-side difference. This usage is obsolete; use the @option{-y} Xor @option{--side-by-side} option of @command{diff} instead. X XAn exit status of 0 means no differences were found, 1 means some Xdifferences were found, and 2 means trouble. X X@menu X* sdiff Options:: Summary of options to @command{diff}. X@end menu X X@node sdiff Options X@section Options to @command{sdiff} X@cindex @command{sdiff} options X@cindex options for @command{sdiff} X XBelow is a summary of all of the options that @sc{gnu} @command{sdiff} accepts. XEach option has two equivalent names, one of which is a single Xletter preceded by @samp{-}, and the other of which is a long name Xpreceded by @samp{--}. Multiple single letter options (unless they take Xan argument) can be combined into a single command line argument. Long Xnamed options can be abbreviated to any unique prefix of their name. X X@table @option X@item -a X@itemx --text XTreat all files as text and compare them line-by-line, even if they Xdo not appear to be text. @xref{Binary}. X X@item -b X@itemx --ignore-space-change XIgnore changes in amount of white space. @xref{White Space}. X X@item -B X@itemx --ignore-blank-lines XIgnore changes that just insert or delete blank lines. @xref{Blank XLines}. X X@item -d X@itemx --minimal XChange the algorithm to perhaps find a smaller set of changes. This Xmakes @command{sdiff} slower (sometimes much slower). @xref{diff XPerformance}. X X@item --diff-program=@var{program} XUse the compatible comparison program @var{program} to compare files Xinstead of @command{diff}. X X@item -E X@itemx --ignore-tab-expansion XIgnore changes due to tab expansion. X@xref{White Space}. X X@item --help XOutput a summary of usage and then exit. X X@item -i X@itemx --ignore-case XIgnore changes in case; consider upper- and lower-case to be the same. X@xref{Case Folding}. X X@item -I @var{regexp} X@itemx --ignore-matching-lines=@var{regexp} XIgnore changes that just insert or delete lines that match @var{regexp}. X@xref{Specified Folding}. X X@item -l X@itemx --left-column XPrint only the left column of two common lines. X@xref{Side by Side Format}. X X@item -o @var{file} X@itemx --output=@var{file} XPut merged output into @var{file}. This option is required for merging. X X@item -s X@itemx --suppress-common-lines XDo not print common lines. @xref{Side by Side Format}. X X@item --speed-large-files XUse heuristics to speed handling of large files that have numerous Xscattered small changes. @xref{diff Performance}. X X@item --strip-trailing-cr XStrip any trailing carriage return at the end of an input line. X@xref{Binary}. X X@item -t X@itemx --expand-tabs XExpand tabs to spaces in the output, to preserve the alignment of tabs Xin the input files. @xref{Tabs}. X X@item -v X@itemx --version XOutput version information and then exit. X X@item -w @var{columns} X@itemx --width=@var{columns} XOutput at most @var{columns} (default 130) print columns per line. X@xref{Side by Side Format}. Note that for historical reasons, this Xoption is @option{-W} in @command{diff}, @option{-w} in @command{sdiff}. X X@item -W X@itemx --ignore-all-space XIgnore white space when comparing lines. @xref{White Space}. XNote that for historical reasons, this option is @option{-w} in @command{diff}, X@option{-W} in @command{sdiff}. X@end table X X@node Standards conformance X@chapter Standards conformance X@cindex @sc{posix} X X@vindex POSIXLY_CORRECT XIn a few cases, the @sc{gnu} utilities' default behavior is Xincompatible with the @sc{posix} standard. To suppress these Xincompatibilities, define the @env{POSIXLY_CORRECT} environment Xvariable. Unless you are checking for @sc{posix} conformance, you Xprobably do not need to define @env{POSIXLY_CORRECT}. X XNormally options and operands can appear in any order, and programs act Xas if all the options appear before any operands. For example, X@samp{diff lao tzu -C 2} acts like @samp{diff -C 2 lao tzu}, since X@samp{2} is an option-argument of @option{-C}. However, if the X@env{POSIXLY_CORRECT} environment variable is set, options must appear Xbefore operands, unless otherwise specified for a particular command. X XNewer versions of @sc{posix} are occasionally incompatible with older Xversions. For example, older versions of @sc{posix} allowed the Xcommand @samp{diff -c -10} to have the same meaning as @samp{diff -C X10}, but @sc{posix} 1003.1-2001 @samp{diff} no longer allows Xdigit-string options like @option{-10}. X X@vindex _POSIX2_VERSION XThe @sc{gnu} utilities normally conform to the version of @sc{posix} Xthat is standard for your system. To cause them to conform to a Xdifferent version of @sc{posix}, define the @env{_POSIX2_VERSION} Xenvironment variable to a value of the form @var{yyyymm} specifying Xthe year and month the standard was adopted. Two values are currently Xsupported for @env{_POSIX2_VERSION}: @samp{199209} stands for X@sc{posix} 1003.2-1992, and @samp{200112} stands for @sc{posix} X1003.1-2001. For example, if you are running older software that Xassumes an older version of @sc{posix} and uses @samp{diff -c -10}, Xyou can work around the compatibility problems by setting X@samp{_POSIX2_VERSION=199209} in your environment. X X@node Projects X@chapter Future Projects X XHere are some ideas for improving @sc{gnu} @command{diff} and X@command{patch}. The @sc{gnu} project has identified some Ximprovements as potential programming projects for volunteers. You Xcan also help by reporting any bugs that you find. X XIf you are a programmer and would like to contribute something to the X@sc{gnu} project, please consider volunteering for one of these Xprojects. If you are seriously contemplating work, please write to X@email{gnu@@gnu.org} to coordinate with other volunteers. X X@menu X* Shortcomings:: Suggested projects for improvements. X* Bugs:: Reporting bugs. X@end menu X X@node Shortcomings X@section Suggested Projects for Improving @sc{gnu} @command{diff} and @command{patch} X@cindex projects for directories X XOne should be able to use @sc{gnu} @command{diff} to generate a patch from any Xpair of directory trees, and given the patch and a copy of one such Xtree, use @command{patch} to generate a faithful copy of the other. XUnfortunately, some changes to directory trees cannot be expressed using Xcurrent patch formats; also, @command{patch} does not handle some of the Xexisting formats. These shortcomings motivate the following suggested Xprojects. X X@menu X* Internationalization:: Handling multibyte and varying-width characters. X* Changing Structure:: Handling changes to the directory structure. X* Special Files:: Handling symbolic links, device special files, etc. X* Unusual File Names:: Handling file names that contain unusual characters. X* Time Stamp Order:: Outputting diffs in time stamp order. X* Ignoring Changes:: Ignoring certain changes while showing others. X* Speedups:: Improving performance. X@end menu X X@node Internationalization X@subsection Handling Multibyte and Varying-Width Characters X@cindex multibyte characters X@cindex varying-width characters X X@command{diff}, @command{diff3} and @command{sdiff} treat each line of Xinput as a string of unibyte characters. This can mishandle multibyte Xcharacters in some cases. For example, when asked to ignore spaces, X@command{diff} does not properly ignore a multibyte space character. X XAlso, @command{diff} currently assumes that each byte is one column Xwide, and this assumption is incorrect in some locales, e.g., locales Xthat use UTF-8 encoding. This causes problems with the @option{-y} or X@option{--side-by-side} option of @command{diff}. X XThese problems need to be fixed without unduly affecting the Xperformance of the utilities in unibyte environments. X XThe IBM GNU/Linux Technology Center Internationalization Team has Xproposed some patches to support internationalized @command{diff} X@uref{http://oss.software.ibm.com/developer/opensource/linux/patches/i18n/diffutils-2.7.2-i18n-0.1.patch.gz}. XUnfortunately, these patches are incomplete and are to an older Xversion of @command{diff}, so more work needs to be done in this area. X X@node Changing Structure X@subsection Handling Changes to the Directory Structure X@cindex directory structure changes X X@command{diff} and @command{patch} do not handle some changes to directory Xstructure. For example, suppose one directory tree contains a directory Xnamed @samp{D} with some subsidiary files, and another contains a file Xwith the same name @samp{D}. @samp{diff -r} does not output enough Xinformation for @command{patch} to transform the directory subtree into Xthe file. X XThere should be a way to specify that a file has been removed without Xhaving to include its entire contents in the patch file. There should Xalso be a way to tell @command{patch} that a file was renamed, even if Xthere is no way for @command{diff} to generate such information. XThere should be a way to tell @command{patch} that a file's time stamp Xhas changed, even if its contents have not changed. X XThese problems can be fixed by extending the @command{diff} output format Xto represent changes in directory structure, and extending @command{patch} Xto understand these extensions. X X@node Special Files X@subsection Files that are Neither Directories Nor Regular Files X@cindex special files X XSome files are neither directories nor regular files: they are unusual Xfiles like symbolic links, device special files, named pipes, and Xsockets. Currently, @command{diff} treats symbolic links like regular files; Xit treats other special files like regular files if they are specified Xat the top level, but simply reports their presence when comparing Xdirectories. This means that @command{patch} cannot represent changes Xto such files. For example, if you change which file a symbolic link Xpoints to, @command{diff} outputs the difference between the two files, Xinstead of the change to the symbolic link. X X@c This might not be a good idea; is it wise for root to install devices X@c this way? X@command{diff} should optionally report changes to special files specially, Xand @command{patch} should be extended to understand these extensions. X X@node Unusual File Names X@subsection File Names that Contain Unusual Characters X@cindex file names with unusual characters X XWhen a file name contains an unusual character like a newline or Xwhite space, @samp{diff -r} generates a patch that @command{patch} cannot Xparse. The problem is with format of @command{diff} output, not just with X@command{patch}, because with odd enough file names one can cause X@command{diff} to generate a patch that is syntactically correct but Xpatches the wrong files. The format of @command{diff} output should be Xextended to handle all possible file names. X X@node Time Stamp Order X@subsection Outputting Diffs in Time Stamp Order X XApplying @command{patch} to a multiple-file diff can result in files Xwhose time stamps are out of order. @sc{gnu} @command{patch} has Xoptions to restore the time stamps of the updated files X(@pxref{Patching Time Stamps}), but sometimes it is useful to generate Xa patch that works even if the recipient does not have @sc{gnu} patch, Xor does not use these options. One way to do this would be to Ximplement a @command{diff} option to output diffs in time stamp order. X X@node Ignoring Changes X@subsection Ignoring Certain Changes X XIt would be nice to have a feature for specifying two strings, one in X@var{from-file} and one in @var{to-file}, which should be considered to Xmatch. Thus, if the two strings are @samp{foo} and @samp{bar}, then if Xtwo lines differ only in that @samp{foo} in file 1 corresponds to X@samp{bar} in file 2, the lines are treated as identical. X XIt is not clear how general this feature can or should be, or Xwhat syntax should be used for it. X XA partial substitute is to filter one or both files before comparing, Xe.g.: X X@example Xsed 's/foo/bar/g' file1 | diff - file2 X@end example X XHowever, this outputs the filtered text, not the original. X X@node Speedups X@subsection Improving Performance X XWhen comparing two large directory structures, one of which was Xoriginally copied from the other with time stamps preserved (e.g., Xwith @samp{cp -pR}), it would greatly improve performance if an option Xtold @command{diff} to assume that two files with the same size and Xtime stamps have the same content. @xref{diff Performance}. X X@node Bugs X@section Reporting Bugs X@cindex bug reports X@cindex reporting bugs X XIf you think you have found a bug in @sc{gnu} @command{cmp}, X@command{diff}, @command{diff3}, or @command{sdiff}, please report it Xby electronic mail to the X@uref{http://mail.gnu.org/mailman/listinfo/bug-gnu-utils,GNU utilities Xbug report mailing list} @email{bug-gnu-utils@@gnu.org}. Please send Xbug reports for @sc{gnu} @command{patch} to X@email{bug-patch@@gnu.org}. Send as precise a description of the Xproblem as you can, including the output of the @option{--version} Xoption and sample input files that produce the bug, if applicable. If Xyou have a nontrivial fix for the bug, please send it as well. If you Xhave a patch, please send it too. It may simplify the maintainer's Xjob if the patch is relative to a recent test release, which you can Xfind in the directory @uref{ftp://alpha.gnu.org/gnu/diffutils/}. X X@node Copying This Manual X@appendix Copying This Manual X X@menu X* GNU Free Documentation License:: License for copying this manual. X@end menu X X@include fdl.texi X X@node Index X@appendix Index X X@printindex cp X X@bye END-of-contrib/diff/doc/diff.texi echo x - contrib/diff/doc/diagmeet.note sed 's/^X//' >contrib/diff/doc/diagmeet.note << 'END-of-contrib/diff/doc/diagmeet.note' XHere is a comparison matrix which shows a case in which Xit is possible for the forward and backward scan in `diag' Xto meet along a nonzero length of diagonal simultaneous X(so that bdiag[d] and fdiag[d] are not equal) Xeven though there is no snake on that diagonal at the meeting point. X X X 85 1 1 1 159 1 1 17 X 1 2 3 4 X60 X 1 2 X1 X 2 2 3 4 X71 X 3 3 4 5 X85 X 4 3 4 5 X17 X 5 4 5 X1 X 6 4 5 6 X183 X 7 5 6 7 X10 X 8 6 7 X1 X 9 6 7 8 X12 X 7 8 9 10 X13 X 10 8 9 10 X14 X 10 9 10 X17 X 10 10 X1 X 10 9 10 X1 X 8 10 10 10 X183 X 8 7 9 9 9 X10 X 7 6 8 9 8 8 X1 X 6 5 7 7 X1 X 5 6 6 X1 X 5 5 5 X50 X 5 4 4 4 X1 X 4 3 3 X85 X 5 4 3 2 2 X1 X 2 1 X17 X 5 4 3 2 1 1 X1 X 1 0 X 85 1 1 1 159 1 1 17 X X X X X X X X X END-of-contrib/diff/doc/diagmeet.note echo x - contrib/diff/doc/diff.info sed 's/^X//' >contrib/diff/doc/diff.info << 'END-of-contrib/diff/doc/diff.info' XThis is diff.info, produced by makeinfo version 4.2 from diff.texi. X XThis manual is for GNU Diffutils (version 2.8.1, 5 April 2002), and Xdocuments the GNU `diff', `diff3', `sdiff', and `cmp' commands for Xshowing the differences between files and the GNU `patch' command for Xusing their output to update files. X X Copyright (C) 1992, 1993, 1994, 1998, 2001, 2002 Free Software XFoundation, Inc. X X Permission is granted to copy, distribute and/or modify this X document under the terms of the GNU Free Documentation License, X Version 1.1 or any later version published by the Free Software X Foundation; with no Invariant Sections, with the Front-Cover texts X being "A GNU Manual," and with the Back-Cover Texts as in (a) X below. A copy of the license is included in the section entitled X "GNU Free Documentation License." X X (a) The FSF's Back-Cover Text is: "You have freedom to copy and X modify this GNU Manual, like GNU software. Copies published by X the Free Software Foundation raise funds for GNU development." X XINFO-DIR-SECTION Individual utilities XSTART-INFO-DIR-ENTRY X* cmp: (diff)Invoking cmp. Compare 2 files byte by byte. X* diff: (diff)Invoking diff. Compare 2 files line by line. X* diff3: (diff)Invoking diff3. Compare 3 files line by line. X* patch: (diff)Invoking patch. Apply a patch to a file. X* sdiff: (diff)Invoking sdiff. Merge 2 files side-by-side. XEND-INFO-DIR-ENTRY X XINFO-DIR-SECTION GNU packages XSTART-INFO-DIR-ENTRY X* Diff: (diff). Comparing and merging files. XEND-INFO-DIR-ENTRY X X XFile: diff.info, Node: Top, Next: Overview, Up: (dir) X XComparing and Merging Files X*************************** X XThis manual is for GNU Diffutils (version 2.8.1, 5 April 2002), and Xdocuments the GNU `diff', `diff3', `sdiff', and `cmp' commands for Xshowing the differences between files and the GNU `patch' command for Xusing their output to update files. X X Copyright (C) 1992, 1993, 1994, 1998, 2001, 2002 Free Software XFoundation, Inc. X X Permission is granted to copy, distribute and/or modify this X document under the terms of the GNU Free Documentation License, X Version 1.1 or any later version published by the Free Software X Foundation; with no Invariant Sections, with the Front-Cover texts X being "A GNU Manual," and with the Back-Cover Texts as in (a) X below. A copy of the license is included in the section entitled X "GNU Free Documentation License." X X (a) The FSF's Back-Cover Text is: "You have freedom to copy and X modify this GNU Manual, like GNU software. Copies published by X the Free Software Foundation raise funds for GNU development." X X* Menu: X X* Overview:: Preliminary information. X* Comparison:: What file comparison means. X X* Output Formats:: Formats for two-way difference reports. X* Incomplete Lines:: Lines that lack trailing newlines. X* Comparing Directories:: Comparing files and directories. X* Adjusting Output:: Making `diff' output prettier. X* diff Performance:: Making `diff' smarter or faster. X X* Comparing Three Files:: Formats for three-way difference reports. X* diff3 Merging:: Merging from a common ancestor. X X* Interactive Merging:: Interactive merging with `sdiff'. X X* Merging with patch:: Using `patch' to change old files into new ones. X* Making Patches:: Tips for making and using patch distributions. X X* Invoking cmp:: Compare two files byte by byte. X* Invoking diff:: Compare two files line by line. X* Invoking diff3:: Compare three files line by line. X* Invoking patch:: Apply a diff file to an original. X* Invoking sdiff:: Side-by-side merge of file differences. X X* Standards conformance:: Conformance to the POSIX standard. X* Projects:: If you've found a bug or other shortcoming. X X* Copying This Manual:: How to make copies of this manual. X* Index:: Index. X X XFile: diff.info, Node: Overview, Next: Comparison, Prev: Top, Up: Top X XOverview X******** X X Computer users often find occasion to ask how two files differ. XPerhaps one file is a newer version of the other file. Or maybe the Xtwo files started out as identical copies but were changed by different Xpeople. X X You can use the `diff' command to show differences between two Xfiles, or each corresponding file in two directories. `diff' outputs Xdifferences between files line by line in any of several formats, Xselectable by command line options. This set of differences is often Xcalled a "diff" or "patch". For files that are identical, `diff' Xnormally produces no output; for binary (non-text) files, `diff' Xnormally reports only that they are different. X X You can use the `cmp' command to show the byte and line numbers Xwhere two files differ. `cmp' can also show all the bytes that differ Xbetween the two files, side by side. A way to compare two files Xcharacter by character is the Emacs command `M-x compare-windows'. X*Note Other Window: (emacs)Other Window, for more information on that Xcommand. X X You can use the `diff3' command to show differences among three Xfiles. When two people have made independent changes to a common Xoriginal, `diff3' can report the differences between the original and Xthe two changed versions, and can produce a merged file that contains Xboth persons' changes together with warnings about conflicts. X X You can use the `sdiff' command to merge two files interactively. X X You can use the set of differences produced by `diff' to distribute Xupdates to text files (such as program source code) to other people. XThis method is especially useful when the differences are small compared Xto the complete files. Given `diff' output, you can use the `patch' Xprogram to update, or "patch", a copy of the file. If you think of X`diff' as subtracting one file from another to produce their Xdifference, you can think of `patch' as adding the difference to one Xfile to reproduce the other. X X This manual first concentrates on making diffs, and later shows how Xto use diffs to update files. X X GNU `diff' was written by Paul Eggert, Mike Haertel, David Hayes, XRichard Stallman, and Len Tower. Wayne Davison designed and Ximplemented the unified output format. The basic algorithm is described Xin "An O(ND) Difference Algorithm and its Variations", Eugene W. Myers, X`Algorithmica' Vol. 1 No. 2, 1986, pp. 251-266; and in "A File XComparison Program", Webb Miller and Eugene W. Myers, X`Software--Practice and Experience' Vol. 15 No. 11, 1985, pp. 1025-1040. XThe algorithm was independently discovered as described in "Algorithms Xfor Approximate String Matching", E. Ukkonen, `Information and Control' XVol. 64, 1985, pp. 100-118. X X GNU `diff3' was written by Randy Smith. GNU `sdiff' was written by XThomas Lord. GNU `cmp' was written by Torbjorn Granlund and David XMacKenzie. X X `patch' was written mainly by Larry Wall and Paul Eggert; several XGNU enhancements were contributed by Wayne Davison and David MacKenzie. XParts of this manual are adapted from a manual page written by Larry XWall, with his permission. X X XFile: diff.info, Node: Comparison, Next: Output Formats, Prev: Overview, Up: Top X XWhat Comparison Means X********************* X X There are several ways to think about the differences between two Xfiles. One way to think of the differences is as a series of lines Xthat were deleted from, inserted in, or changed in one file to produce Xthe other file. `diff' compares two files line by line, finds groups of Xlines that differ, and reports each group of differing lines. It can Xreport the differing lines in several formats, which have different Xpurposes. X X GNU `diff' can show whether files are different without detailing Xthe differences. It also provides ways to suppress certain kinds of Xdifferences that are not important to you. Most commonly, such Xdifferences are changes in the amount of white space between words or Xlines. `diff' also provides ways to suppress differences in alphabetic Xcase or in lines that match a regular expression that you provide. XThese options can accumulate; for example, you can ignore changes in Xboth white space and alphabetic case. X X Another way to think of the differences between two files is as a Xsequence of pairs of bytes that can be either identical or different. X`cmp' reports the differences between two files byte by byte, instead Xof line by line. As a result, it is often more useful than `diff' for Xcomparing binary files. For text files, `cmp' is useful mainly when Xyou want to know only whether two files are identical, or whether one Xfile is a prefix of the other. X X To illustrate the effect that considering changes byte by byte can Xhave compared with considering them line by line, think of what happens Xif a single newline character is added to the beginning of a file. If Xthat file is then compared with an otherwise identical file that lacks Xthe newline at the beginning, `diff' will report that a blank line has Xbeen added to the file, while `cmp' will report that almost every byte Xof the two files differs. X X `diff3' normally compares three input files line by line, finds Xgroups of lines that differ, and reports each group of differing lines. XIts output is designed to make it easy to inspect two different sets of Xchanges to the same file. X X* Menu: X X* Hunks:: Groups of differing lines. X* White Space:: Suppressing differences in white space. X* Blank Lines:: Suppressing differences in blank lines. X* Case Folding:: Suppressing differences in alphabetic case. X* Specified Folding:: Suppressing differences that match regular expressions. X* Brief:: Summarizing which files are different. X* Binary:: Comparing binary files or forcing text comparisons. X X XFile: diff.info, Node: Hunks, Next: White Space, Up: Comparison X XHunks X===== X X When comparing two files, `diff' finds sequences of lines common to Xboth files, interspersed with groups of differing lines called "hunks". XComparing two identical files yields one sequence of common lines and Xno hunks, because no lines differ. Comparing two entirely different Xfiles yields no common lines and one large hunk that contains all lines Xof both files. In general, there are many ways to match up lines Xbetween two given files. `diff' tries to minimize the total hunk size Xby finding large sequences of common lines interspersed with small Xhunks of differing lines. X X For example, suppose the file `F' contains the three lines `a', `b', X`c', and the file `G' contains the same three lines in reverse order X`c', `b', `a'. If `diff' finds the line `c' as common, then the command X`diff F G' produces this output: X X 1,2d0 X < a X < b X 3a2,3 X > b X > a X XBut if `diff' notices the common line `b' instead, it produces this Xoutput: X X 1c1 X < a X --- X > c X 3c3 X < c X --- X > a X XIt is also possible to find `a' as the common line. `diff' does not Xalways find an optimal matching between the files; it takes shortcuts Xto run faster. But its output is usually close to the shortest Xpossible. You can adjust this tradeoff with the `--minimal' option X(*note diff Performance::). X X XFile: diff.info, Node: White Space, Next: Blank Lines, Prev: Hunks, Up: Comparison X XSuppressing Differences in Blank and Tab Spacing X================================================ X X The `-E' and `--ignore-tab-expansion' options ignore the distinction Xbetween tabs and spaces on input. A tab is considered to be equivalent Xto the number of spaces to the next tab stop. `diff' assumes that tab Xstops are set every 8 print columns. X X The `-b' and `--ignore-space-change' options are stronger. They Xignore white space at line end, and consider all other sequences of one Xor more white space characters to be equivalent. With these options, X`diff' considers the following two lines to be equivalent, where `$' Xdenotes the line end: X X Here lyeth muche rychnesse in lytell space. -- John Heywood$ X Here lyeth muche rychnesse in lytell space. -- John Heywood $ X X The `-w' and `--ignore-all-space' options are stronger still. They Xignore difference even if one line has white space where the other line Xhas none. "White space" characters include tab, newline, vertical tab, Xform feed, carriage return, and space; some locales may define Xadditional characters to be white space. With these options, `diff' Xconsiders the following two lines to be equivalent, where `$' denotes Xthe line end and `^M' denotes a carriage return: X X Here lyeth muche rychnesse in lytell space.-- John Heywood$ X He relyeth much erychnes seinly tells pace. --John Heywood ^M$ X X XFile: diff.info, Node: Blank Lines, Next: Case Folding, Prev: White Space, Up: Comparison X XSuppressing Differences in Blank Lines X====================================== X X The `-B' and `--ignore-blank-lines' options ignore insertions or Xdeletions of blank lines. These options affect only lines that are Xcompletely empty; they do not affect lines that look empty but contain Xspace or tab characters. With these options, for example, a file Xcontaining X 1. A point is that which has no part. X X 2. A line is breadthless length. X -- Euclid, The Elements, I X Xis considered identical to a file containing X 1. A point is that which has no part. X 2. A line is breadthless length. X X X -- Euclid, The Elements, I X X XFile: diff.info, Node: Case Folding, Next: Specified Folding, Prev: Blank Lines, Up: Comparison X XSuppressing Case Differences X============================ X X GNU `diff' can treat lower case letters as equivalent to their upper Xcase counterparts, so that, for example, it considers `Funky Stuff', X`funky STUFF', and `fUNKy stuFf' to all be the same. To request this, Xuse the `-i' or `--ignore-case' option. X X XFile: diff.info, Node: Specified Folding, Next: Brief, Prev: Case Folding, Up: Comparison X XSuppressing Lines Matching a Regular Expression X=============================================== X X To ignore insertions and deletions of lines that match a X`grep'-style regular expression, use the `-I REGEXP' or X`--ignore-matching-lines=REGEXP' option. You should escape regular Xexpressions that contain shell metacharacters to prevent the shell from Xexpanding them. For example, `diff -I '^[[:digit:]]'' ignores all Xchanges to lines beginning with a digit. X X However, `-I' only ignores the insertion or deletion of lines that Xcontain the regular expression if every changed line in the hunk--every Xinsertion and every deletion--matches the regular expression. In other Xwords, for each nonignorable change, `diff' prints the complete set of Xchanges in its vicinity, including the ignorable ones. X X You can specify more than one regular expression for lines to ignore Xby using more than one `-I' option. `diff' tries to match each line Xagainst each regular expression. X X XFile: diff.info, Node: Brief, Next: Binary, Prev: Specified Folding, Up: Comparison X XSummarizing Which Files Differ X============================== X X When you only want to find out whether files are different, and you Xdon't care what the differences are, you can use the summary output Xformat. In this format, instead of showing the differences between the Xfiles, `diff' simply reports whether files differ. The `-q' and X`--brief' options select this output format. X X This format is especially useful when comparing the contents of two Xdirectories. It is also much faster than doing the normal line by line Xcomparisons, because `diff' can stop analyzing the files as soon as it Xknows that there are any differences. X X You can also get a brief indication of whether two files differ by Xusing `cmp'. For files that are identical, `cmp' produces no output. XWhen the files differ, by default, `cmp' outputs the byte and line Xnumber where the first difference occurs. You can use the `-s' option Xto suppress that information, so that `cmp' produces no output and Xreports whether the files differ using only its exit status (*note XInvoking cmp::). X X Unlike `diff', `cmp' cannot compare directories; it can only compare Xtwo files. X X XFile: diff.info, Node: Binary, Prev: Brief, Up: Comparison X XBinary Files and Forcing Text Comparisons X========================================= X X If `diff' thinks that either of the two files it is comparing is Xbinary (a non-text file), it normally treats that pair of files much as Xif the summary output format had been selected (*note Brief::), and Xreports only that the binary files are different. This is because line Xby line comparisons are usually not meaningful for binary files. X X `diff' determines whether a file is text or binary by checking the Xfirst few bytes in the file; the exact number of bytes is system Xdependent, but it is typically several thousand. If every byte in that Xpart of the file is non-null, `diff' considers the file to be text; Xotherwise it considers the file to be binary. X X Sometimes you might want to force `diff' to consider files to be Xtext. For example, you might be comparing text files that contain null Xcharacters; `diff' would erroneously decide that those are non-text Xfiles. Or you might be comparing documents that are in a format used Xby a word processing system that uses null characters to indicate Xspecial formatting. You can force `diff' to consider all files to be Xtext files, and compare them line by line, by using the `-a' or X`--text' option. If the files you compare using this option do not in Xfact contain text, they will probably contain few newline characters, Xand the `diff' output will consist of hunks showing differences between Xlong lines of whatever characters the files contain. X X You can also force `diff' to consider all files to be binary files, Xand report only whether they differ (but not how). Use the `-q' or X`--brief' option for this. X X Differing binary files are considered to cause trouble because the Xresulting `diff' output does not capture all the differences. This Xtrouble causes `diff' to exit with status 2. However, this trouble Xcannot occur with the `--a' or `--text' option, or with the `-q' or X`--brief' option, as these options both cause `diff' to treat binary Xfiles like text files. X X In operating systems that distinguish between text and binary files, X`diff' normally reads and writes all data as text. Use the `--binary' Xoption to force `diff' to read and write binary data instead. This Xoption has no effect on a POSIX-compliant system like GNU or Xtraditional Unix. However, many personal computer operating systems Xrepresent the end of a line with a carriage return followed by a Xnewline. On such systems, `diff' normally ignores these carriage Xreturns on input and generates them at the end of each output line, but Xwith the `--binary' option `diff' treats each carriage return as just Xanother input character, and does not generate a carriage return at the Xend of each output line. This can be useful when dealing with non-text Xfiles that are meant to be interchanged with POSIX-compliant systems. X X The `--strip-trailing-cr' causes `diff' to treat input lines that Xend in carriage return followed by newline as if they end in plain Xnewline. This can be useful when comparing text that is imperfectly Ximported from many personal computer operating systems. This option Xaffects how lines are read, which in turn affects how they are compared Xand output. X X If you want to compare two files byte by byte, you can use the `cmp' Xprogram with the `-l' option to show the values of each differing byte Xin the two files. With GNU `cmp', you can also use the `-b' option to Xshow the ASCII representation of those bytes. *Note Invoking cmp::, Xfor more information. X X If `diff3' thinks that any of the files it is comparing is binary (a Xnon-text file), it normally reports an error, because such comparisons Xare usually not useful. `diff3' uses the same test as `diff' to decide Xwhether a file is binary. As with `diff', if the input files contain a Xfew non-text bytes but otherwise are like text files, you can force X`diff3' to consider all files to be text files and compare them line by Xline by using the `-a' or `--text' options. X X XFile: diff.info, Node: Output Formats, Next: Incomplete Lines, Prev: Comparison, Up: Top X X`diff' Output Formats X********************* X X `diff' has several mutually exclusive options for output format. XThe following sections describe each format, illustrating how `diff' Xreports the differences between two sample input files. X X* Menu: X X* Sample diff Input:: Sample `diff' input files for examples. X* Normal:: Showing differences without surrounding text. X* Context:: Showing differences with the surrounding text. X* Side by Side:: Showing differences in two columns. X* Scripts:: Generating scripts for other programs. X* If-then-else:: Merging files with if-then-else. X X XFile: diff.info, Node: Sample diff Input, Next: Normal, Up: Output Formats X XTwo Sample Input Files X====================== X X Here are two sample files that we will use in numerous examples to Xillustrate the output of `diff' and how various options can change it. X X This is the file `lao': X X The Way that can be told of is not the eternal Way; X The name that can be named is not the eternal name. X The Nameless is the origin of Heaven and Earth; X The Named is the mother of all things. X Therefore let there always be non-being, X so we may see their subtlety, X And let there always be being, X so we may see their outcome. X The two are the same, X But after they are produced, X they have different names. X X This is the file `tzu': X X The Nameless is the origin of Heaven and Earth; X The named is the mother of all things. X X Therefore let there always be non-being, X so we may see their subtlety, X And let there always be being, X so we may see their outcome. X The two are the same, X But after they are produced, X they have different names. X They both may be called deep and profound. X Deeper and more profound, X The door of all subtleties! X X In this example, the first hunk contains just the first two lines of X`lao', the second hunk contains the fourth line of `lao' opposing the Xsecond and third lines of `tzu', and the last hunk contains just the Xlast three lines of `tzu'. X X XFile: diff.info, Node: Normal, Next: Context, Prev: Sample diff Input, Up: Output Formats X XShowing Differences Without Context X=================================== X X The "normal" `diff' output format shows each hunk of differences Xwithout any surrounding context. Sometimes such output is the clearest Xway to see how lines have changed, without the clutter of nearby Xunchanged lines (although you can get similar results with the context Xor unified formats by using 0 lines of context). However, this format Xis no longer widely used for sending out patches; for that purpose, the Xcontext format (*note Context Format::) and the unified format (*note XUnified Format::) are superior. Normal format is the default for Xcompatibility with older versions of `diff' and the POSIX standard. XUse the `--normal' option to select this output format explicitly. X X* Menu: X X* Detailed Normal:: A detailed description of normal output format. X* Example Normal:: Sample output in the normal format. X X XFile: diff.info, Node: Detailed Normal, Next: Example Normal, Up: Normal X XDetailed Description of Normal Format X------------------------------------- X X The normal output format consists of one or more hunks of Xdifferences; each hunk shows one area where the files differ. Normal Xformat hunks look like this: X X CHANGE-COMMAND X < FROM-FILE-LINE X < FROM-FILE-LINE... X --- X > TO-FILE-LINE X > TO-FILE-LINE... X X There are three types of change commands. Each consists of a line Xnumber or comma-separated range of lines in the first file, a single Xcharacter indicating the kind of change to make, and a line number or Xcomma-separated range of lines in the second file. All line numbers are Xthe original line numbers in each file. The types of change commands Xare: X X`LaR' X Add the lines in range R of the second file after line L of the X first file. For example, `8a12,15' means append lines 12-15 of X file 2 after line 8 of file 1; or, if changing file 2 into file 1, X delete lines 12-15 of file 2. X X`FcT' X Replace the lines in range F of the first file with lines in range X T of the second file. This is like a combined add and delete, but X more compact. For example, `5,7c8,10' means change lines 5-7 of X file 1 to read as lines 8-10 of file 2; or, if changing file 2 into X file 1, change lines 8-10 of file 2 to read as lines 5-7 of file 1. X X`RdL' X Delete the lines in range R from the first file; line L is where X they would have appeared in the second file had they not been X deleted. For example, `5,7d3' means delete lines 5-7 of file 1; X or, if changing file 2 into file 1, append lines 5-7 of file 1 X after line 3 of file 2. X X XFile: diff.info, Node: Example Normal, Prev: Detailed Normal, Up: Normal X XAn Example of Normal Format X--------------------------- X X Here is the output of the command `diff lao tzu' (*note Sample diff XInput::, for the complete contents of the two files). Notice that it Xshows only the lines that are different between the two files. X X 1,2d0 X < The Way that can be told of is not the eternal Way; X < The name that can be named is not the eternal name. X 4c2,3 X < The Named is the mother of all things. X --- X > The named is the mother of all things. X > X 11a11,13 X > They both may be called deep and profound. X > Deeper and more profound, X > The door of all subtleties! X X XFile: diff.info, Node: Context, Next: Side by Side, Prev: Normal, Up: Output Formats X XShowing Differences in Their Context X==================================== X X Usually, when you are looking at the differences between files, you Xwill also want to see the parts of the files near the lines that Xdiffer, to help you understand exactly what has changed. These nearby Xparts of the files are called the "context". X X GNU `diff' provides two output formats that show context around the Xdiffering lines: "context format" and "unified format". It can Xoptionally show in which function or section of the file the differing Xlines are found. X X If you are distributing new versions of files to other people in the Xform of `diff' output, you should use one of the output formats that Xshow context so that they can apply the diffs even if they have made Xsmall changes of their own to the files. `patch' can apply the diffs Xin this case by searching in the files for the lines of context around Xthe differing lines; if those lines are actually a few lines away from Xwhere the diff says they are, `patch' can adjust the line numbers Xaccordingly and still apply the diff correctly. *Note Imperfect::, for Xmore information on using `patch' to apply imperfect diffs. X X* Menu: X X* Context Format:: An output format that shows surrounding lines. X* Unified Format:: A more compact output format that shows context. X* Sections:: Showing which sections of the files differences are in. X* Alternate Names:: Showing alternate file names in context headers. X X XFile: diff.info, Node: Context Format, Next: Unified Format, Up: Context X XContext Format X-------------- X X The context output format shows several lines of context around the Xlines that differ. It is the standard format for distributing updates Xto source code. X X To select this output format, use the `-C LINES', X`--context[=LINES]', or `-c' option. The argument LINES that some of Xthese options take is the number of lines of context to show. If you Xdo not specify LINES, it defaults to three. For proper operation, X`patch' typically needs at least two lines of context. X X* Menu: X X* Detailed Context:: A detailed description of the context output format. X* Example Context:: Sample output in context format. X* Less Context:: Another sample with less context. X X XFile: diff.info, Node: Detailed Context, Next: Example Context, Up: Context Format X XDetailed Description of Context Format X...................................... X X The context output format starts with a two-line header, which looks Xlike this: X X *** FROM-FILE FROM-FILE-MODIFICATION-TIME X --- TO-FILE TO-FILE-MODIFICATION TIME X XThe time stamp normally looks like `2002-02-21 23:30:39.942229878 X-0800' to indicate the date, time with fractional seconds, and time Xzone in Internet RFC 2822 format X(ftp://ftp.isi.edu/in-notes/rfc2822.txt). However, a traditional time Xstamp like `Thu Feb 21 23:30:39 2002' is used if the `LC_TIME' locale Xcategory is either `C' or `POSIX'. X X You can change the header's content with the `--label=LABEL' option; Xsee *Note Alternate Names::. X X Next come one or more hunks of differences; each hunk shows one area Xwhere the files differ. Context format hunks look like this: X X *************** X *** FROM-FILE-LINE-RANGE **** X FROM-FILE-LINE X FROM-FILE-LINE... X --- TO-FILE-LINE-RANGE ---- X TO-FILE-LINE X TO-FILE-LINE... X X The lines of context around the lines that differ start with two Xspace characters. The lines that differ between the two files start Xwith one of the following indicator characters, followed by a space Xcharacter: X X`!' X A line that is part of a group of one or more lines that changed X between the two files. There is a corresponding group of lines X marked with `!' in the part of this hunk for the other file. X X`+' X An "inserted" line in the second file that corresponds to nothing X in the first file. X X`-' X A "deleted" line in the first file that corresponds to nothing in X the second file. X X If all of the changes in a hunk are insertions, the lines of XFROM-FILE are omitted. If all of the changes are deletions, the lines Xof TO-FILE are omitted. X X XFile: diff.info, Node: Example Context, Next: Less Context, Prev: Detailed Context, Up: Context Format X XAn Example of Context Format X............................ X X Here is the output of `diff -c lao tzu' (*note Sample diff Input::, Xfor the complete contents of the two files). Notice that up to three Xlines that are not different are shown around each line that is Xdifferent; they are the context lines. Also notice that the first two Xhunks have run together, because their contents overlap. X X *** lao 2002-02-21 23:30:39.942229878 -0800 X --- tzu 2002-02-21 23:30:50.442260588 -0800 X *************** X *** 1,7 **** X - The Way that can be told of is not the eternal Way; X - The name that can be named is not the eternal name. X The Nameless is the origin of Heaven and Earth; X ! The Named is the mother of all things. X Therefore let there always be non-being, X so we may see their subtlety, X And let there always be being, X --- 1,6 ---- X The Nameless is the origin of Heaven and Earth; X ! The named is the mother of all things. X ! X Therefore let there always be non-being, X so we may see their subtlety, X And let there always be being, X *************** X *** 9,11 **** X --- 8,13 ---- X The two are the same, X But after they are produced, X they have different names. X + They both may be called deep and profound. X + Deeper and more profound, X + The door of all subtleties! X X XFile: diff.info, Node: Less Context, Prev: Example Context, Up: Context Format X XAn Example of Context Format with Less Context X.............................................. X X Here is the output of `diff -C 1 lao tzu' (*note Sample diff XInput::, for the complete contents of the two files). Notice that at Xmost one context line is reported here. X X *** lao 2002-02-21 23:30:39.942229878 -0800 X --- tzu 2002-02-21 23:30:50.442260588 -0800 X *************** X *** 1,5 **** X - The Way that can be told of is not the eternal Way; X - The name that can be named is not the eternal name. X The Nameless is the origin of Heaven and Earth; X ! The Named is the mother of all things. X Therefore let there always be non-being, X --- 1,4 ---- X The Nameless is the origin of Heaven and Earth; X ! The named is the mother of all things. X ! X Therefore let there always be non-being, X *************** X *** 11 **** X --- 10,13 ---- X they have different names. X + They both may be called deep and profound. X + Deeper and more profound, X + The door of all subtleties! X X XFile: diff.info, Node: Unified Format, Next: Sections, Prev: Context Format, Up: Context X XUnified Format X-------------- X X The unified output format is a variation on the context format that Xis more compact because it omits redundant context lines. To select Xthis output format, use the `-U LINES', `--unified[=LINES]', or `-u' Xoption. The argument LINES is the number of lines of context to show. XWhen it is not given, it defaults to three. X X At present, only GNU `diff' can produce this format and only GNU X`patch' can automatically apply diffs in this format. For proper Xoperation, `patch' typically needs at least three lines of context. X X* Menu: X X* Detailed Unified:: A detailed description of unified format. X* Example Unified:: Sample output in unified format. X X XFile: diff.info, Node: Detailed Unified, Next: Example Unified, Up: Unified Format X XDetailed Description of Unified Format X...................................... X X The unified output format starts with a two-line header, which looks Xlike this: X X --- FROM-FILE FROM-FILE-MODIFICATION-TIME X +++ TO-FILE TO-FILE-MODIFICATION-TIME X XThe time stamp looks like `2002-02-21 23:30:39.942229878 -0800' to Xindicate the date, time with fractional seconds, and time zone. X X You can change the header's content with the `--label=LABEL' option; Xsee *Note Alternate Names::. X X Next come one or more hunks of differences; each hunk shows one area Xwhere the files differ. Unified format hunks look like this: X X @@ FROM-FILE-RANGE TO-FILE-RANGE @@ X LINE-FROM-EITHER-FILE X LINE-FROM-EITHER-FILE... X X The lines common to both files begin with a space character. The Xlines that actually differ between the two files have one of the Xfollowing indicator characters in the left print column: X X`+' X A line was added here to the first file. X X`-' X A line was removed here from the first file. X X XFile: diff.info, Node: Example Unified, Prev: Detailed Unified, Up: Unified Format X XAn Example of Unified Format X............................ X X Here is the output of the command `diff -u lao tzu' (*note Sample Xdiff Input::, for the complete contents of the two files): X X --- lao 2002-02-21 23:30:39.942229878 -0800 X +++ tzu 2002-02-21 23:30:50.442260588 -0800 X @@ -1,7 +1,6 @@ X -The Way that can be told of is not the eternal Way; X -The name that can be named is not the eternal name. X The Nameless is the origin of Heaven and Earth; X -The Named is the mother of all things. X +The named is the mother of all things. X + X Therefore let there always be non-being, X so we may see their subtlety, X And let there always be being, X @@ -9,3 +8,6 @@ X The two are the same, X But after they are produced, X they have different names. X +They both may be called deep and profound. X +Deeper and more profound, X +The door of all subtleties! X X XFile: diff.info, Node: Sections, Next: Alternate Names, Prev: Unified Format, Up: Context X XShowing Which Sections Differences Are in X----------------------------------------- X X Sometimes you might want to know which part of the files each change Xfalls in. If the files are source code, this could mean which function Xwas changed. If the files are documents, it could mean which chapter or Xappendix was changed. GNU `diff' can show this by displaying the Xnearest section heading line that precedes the differing lines. Which Xlines are "section headings" is determined by a regular expression. X X* Menu: X X* Specified Headings:: Showing headings that match regular expressions. X* C Function Headings:: Showing headings of C functions. X X XFile: diff.info, Node: Specified Headings, Next: C Function Headings, Up: Sections X XShowing Lines That Match Regular Expressions X............................................ X X To show in which sections differences occur for files that are not Xsource code for C or similar languages, use the `-F REGEXP' or X`--show-function-line=REGEXP' option. `diff' considers lines that Xmatch the `grep'-style regular expression REGEXP to be the beginning of Xa section of the file. Here are suggested regular expressions for some Xcommon languages: X X`^[[:alpha:]$_]' X C, C++, Prolog X X`^(' X Lisp X X`^@node' X Texinfo X X This option does not automatically select an output format; in order Xto use it, you must select the context format (*note Context Format::) Xor unified format (*note Unified Format::). In other output formats it Xhas no effect. X X The `-F' and `--show-function-line' options find the nearest Xunchanged line that precedes each hunk of differences and matches the Xgiven regular expression. Then they add that line to the end of the Xline of asterisks in the context format, or to the `@@' line in unified Xformat. If no matching line exists, they leave the output for that Xhunk unchanged. If that line is more than 40 characters long, they Xoutput only the first 40 characters. You can specify more than one Xregular expression for such lines; `diff' tries to match each line Xagainst each regular expression, starting with the last one given. This Xmeans that you can use `-p' and `-F' together, if you wish. X X XFile: diff.info, Node: C Function Headings, Prev: Specified Headings, Up: Sections X XShowing C Function Headings X........................... X X To show in which functions differences occur for C and similar Xlanguages, you can use the `-p' or `--show-c-function' option. This Xoption automatically defaults to the context output format (*note XContext Format::), with the default number of lines of context. You Xcan override that number with `-C LINES' elsewhere in the command line. XYou can override both the format and the number with `-U LINES' Xelsewhere in the command line. X X The `-p' and `--show-c-function' options are equivalent to `-F X'^[[:alpha:]$_]'' if the unified format is specified, otherwise `-c -F X'^[[:alpha:]$_]'' (*note Specified Headings::). GNU `diff' provides Xthem for the sake of convenience. X X XFile: diff.info, Node: Alternate Names, Prev: Sections, Up: Context X XShowing Alternate File Names X---------------------------- X X If you are comparing two files that have meaningless or uninformative Xnames, you might want `diff' to show alternate names in the header of Xthe context and unified output formats. To do this, use the X`--label=LABEL' option. The first time you give this option, its Xargument replaces the name and date of the first file in the header; Xthe second time, its argument replaces the name and date of the second Xfile. If you give this option more than twice, `diff' reports an Xerror. The `--label' option does not affect the file names in the `pr' Xheader when the `-l' or `--paginate' option is used (*note XPagination::). X X Here are the first two lines of the output from `diff -C 2 X--label=original --label=modified lao tzu': X X *** original X --- modified X X XFile: diff.info, Node: Side by Side, Next: Scripts, Prev: Context, Up: Output Formats X XShowing Differences Side by Side X================================ X X `diff' can produce a side by side difference listing of two files. XThe files are listed in two columns with a gutter between them. The Xgutter contains one of the following markers: X Xwhite space X The corresponding lines are in common. That is, either the lines X are identical, or the difference is ignored because of one of the X `--ignore' options (*note White Space::). X X`|' X The corresponding lines differ, and they are either both complete X or both incomplete. X X`<' X The files differ and only the first file contains the line. X X`>' X The files differ and only the second file contains the line. X X`(' X Only the first file contains the line, but the difference is X ignored. X X`)' X Only the second file contains the line, but the difference is X ignored. X X`\' X The corresponding lines differ, and only the first line is X incomplete. X X`/' X The corresponding lines differ, and only the second line is X incomplete. X X Normally, an output line is incomplete if and only if the lines that Xit contains are incomplete; *Note Incomplete Lines::. However, when an Xoutput line represents two differing lines, one might be incomplete Xwhile the other is not. In this case, the output line is complete, but Xits the gutter is marked `\' if the first line is incomplete, `/' if Xthe second line is. X X Side by side format is sometimes easiest to read, but it has Xlimitations. It generates much wider output than usual, and truncates Xlines that are too long to fit. Also, it relies on lining up output Xmore heavily than usual, so its output looks particularly bad if you Xuse varying width fonts, nonstandard tab stops, or nonprinting Xcharacters. X X You can use the `sdiff' command to interactively merge side by side Xdifferences. *Note Interactive Merging::, for more information on Xmerging files. X X* Menu: X X* Side by Side Format:: Controlling side by side output format. X* Example Side by Side:: Sample side by side output. X X XFile: diff.info, Node: Side by Side Format, Next: Example Side by Side, Up: Side by Side X XControlling Side by Side Format X------------------------------- X X The `-y' or `--side-by-side' option selects side by side format. XBecause side by side output lines contain two input lines, the output Xis wider than usual: normally 130 print columns, which can fit onto a Xtraditional printer line. You can set the width of the output with the X`-W COLUMNS' or `--width=COLUMNS' option. The output is split into two Xhalves of equal width, separated by a small gutter to mark differences; Xthe right half is aligned to a tab stop so that tabs line up. Input Xlines that are too long to fit in half of an output line are truncated Xfor output. X X The `--left-column' option prints only the left column of two common Xlines. The `--suppress-common-lines' option suppresses common lines Xentirely. X X XFile: diff.info, Node: Example Side by Side, Prev: Side by Side Format, Up: Side by Side X XAn Example of Side by Side Format X--------------------------------- X X Here is the output of the command `diff -y -W 72 lao tzu' (*note XSample diff Input::, for the complete contents of the two files). X X The Way that can be told of is n < X The name that can be named is no < X The Nameless is the origin of He The Nameless is the origin of He X The Named is the mother of all t | The named is the mother of all t X > X Therefore let there always be no Therefore let there always be no X so we may see their subtlety, so we may see their subtlety, X And let there always be being, And let there always be being, X so we may see their outcome. so we may see their outcome. X The two are the same, The two are the same, X But after they are produced, But after they are produced, X they have different names. they have different names. X > They both may be called deep and X > Deeper and more profound, X > The door of all subtleties! X X XFile: diff.info, Node: Scripts, Next: If-then-else, Prev: Side by Side, Up: Output Formats X XMaking Edit Scripts X=================== X X Several output modes produce command scripts for editing FROM-FILE Xto produce TO-FILE. X X* Menu: X X* ed Scripts:: Using `diff' to produce commands for `ed'. X* Forward ed:: Making forward `ed' scripts. X* RCS:: A special `diff' output format used by RCS. X X XFile: diff.info, Node: ed Scripts, Next: Forward ed, Up: Scripts X X`ed' Scripts X------------ X X `diff' can produce commands that direct the `ed' text editor to Xchange the first file into the second file. Long ago, this was the Xonly output mode that was suitable for editing one file into another Xautomatically; today, with `patch', it is almost obsolete. Use the X`-e' or `--ed' option to select this output format. X X Like the normal format (*note Normal::), this output format does not Xshow any context; unlike the normal format, it does not include the Xinformation necessary to apply the diff in reverse (to produce the first Xfile if all you have is the second file and the diff). X X If the file `d' contains the output of `diff -e old new', then the Xcommand `(cat d && echo w) | ed - old' edits `old' to make it a copy of X`new'. More generally, if `d1', `d2', ..., `dN' contain the outputs of X`diff -e old new1', `diff -e new1 new2', ..., `diff -e newN-1 newN', Xrespectively, then the command `(cat d1 d2 ... dN && echo w) | ed - Xold' edits `old' to make it a copy of `newN'. X X* Menu: X X* Detailed ed:: A detailed description of `ed' format. X* Example ed:: A sample `ed' script. X X XFile: diff.info, Node: Detailed ed, Next: Example ed, Up: ed Scripts X XDetailed Description of `ed' Format X................................... X X The `ed' output format consists of one or more hunks of differences. XThe changes closest to the ends of the files come first so that Xcommands that change the number of lines do not affect how `ed' Xinterprets line numbers in succeeding commands. `ed' format hunks look Xlike this: X X CHANGE-COMMAND X TO-FILE-LINE X TO-FILE-LINE... X . X X Because `ed' uses a single period on a line to indicate the end of Xinput, GNU `diff' protects lines of changes that contain a single Xperiod on a line by writing two periods instead, then writing a Xsubsequent `ed' command to change the two periods into one. The `ed' Xformat cannot represent an incomplete line, so if the second file ends Xin a changed incomplete line, `diff' reports an error and then pretends Xthat a newline was appended. X X There are three types of change commands. Each consists of a line Xnumber or comma-separated range of lines in the first file and a single Xcharacter indicating the kind of change to make. All line numbers are Xthe original line numbers in the file. The types of change commands Xare: X X`La' X Add text from the second file after line L in the first file. For X example, `8a' means to add the following lines after line 8 of file X 1. X X`Rc' X Replace the lines in range R in the first file with the following X lines. Like a combined add and delete, but more compact. For X example, `5,7c' means change lines 5-7 of file 1 to read as the X text file 2. X X`Rd' X Delete the lines in range R from the first file. For example, X `5,7d' means delete lines 5-7 of file 1. X X XFile: diff.info, Node: Example ed, Prev: Detailed ed, Up: ed Scripts X XExample `ed' Script X................... X X Here is the output of `diff -e lao tzu' (*note Sample diff Input::, Xfor the complete contents of the two files): X X 11a X They both may be called deep and profound. X Deeper and more profound, X The door of all subtleties! X . X 4c X The named is the mother of all things. X X . X 1,2d X X XFile: diff.info, Node: Forward ed, Next: RCS, Prev: ed Scripts, Up: Scripts X XForward `ed' Scripts X-------------------- X X `diff' can produce output that is like an `ed' script, but with Xhunks in forward (front to back) order. The format of the commands is Xalso changed slightly: command characters precede the lines they Xmodify, spaces separate line numbers in ranges, and no attempt is made Xto disambiguate hunk lines consisting of a single period. Like `ed' Xformat, forward `ed' format cannot represent incomplete lines. X X Forward `ed' format is not very useful, because neither `ed' nor X`patch' can apply diffs in this format. It exists mainly for Xcompatibility with older versions of `diff'. Use the `-f' or X`--forward-ed' option to select it. X X XFile: diff.info, Node: RCS, Prev: Forward ed, Up: Scripts X XRCS Scripts X----------- X X The RCS output format is designed specifically for use by the XRevision Control System, which is a set of free programs used for Xorganizing different versions and systems of files. Use the `-n' or X`--rcs' option to select this output format. It is like the forward X`ed' format (*note Forward ed::), but it can represent arbitrary Xchanges to the contents of a file because it avoids the forward `ed' Xformat's problems with lines consisting of a single period and with Xincomplete lines. Instead of ending text sections with a line Xconsisting of a single period, each command specifies the number of Xlines it affects; a combination of the `a' and `d' commands are used Xinstead of `c'. Also, if the second file ends in a changed incomplete Xline, then the output also ends in an incomplete line. X X Here is the output of `diff -n lao tzu' (*note Sample diff Input::, Xfor the complete contents of the two files): X X d1 2 X d4 1 X a4 2 X The named is the mother of all things. X X a11 3 X They both may be called deep and profound. X Deeper and more profound, X The door of all subtleties! X X XFile: diff.info, Node: If-then-else, Prev: Scripts, Up: Output Formats X XMerging Files with If-then-else X=============================== X X You can use `diff' to merge two files of C source code. The output Xof `diff' in this format contains all the lines of both files. Lines Xcommon to both files are output just once; the differing parts are Xseparated by the C preprocessor directives `#ifdef NAME' or `#ifndef XNAME', `#else', and `#endif'. When compiling the output, you select Xwhich version to use by either defining or leaving undefined the macro XNAME. X X To merge two files, use `diff' with the `-D NAME' or `--ifdef=NAME' Xoption. The argument NAME is the C preprocessor identifier to use in Xthe `#ifdef' and `#ifndef' directives. X X For example, if you change an instance of `wait (&s)' to `waitpid X(-1, &s, 0)' and then merge the old and new files with the X`--ifdef=HAVE_WAITPID' option, then the affected part of your code Xmight look like this: X X do { X #ifndef HAVE_WAITPID X if ((w = wait (&s)) < 0 && errno != EINTR) X #else /* HAVE_WAITPID */ X if ((w = waitpid (-1, &s, 0)) < 0 && errno != EINTR) X #endif /* HAVE_WAITPID */ X return w; X } while (w != child); X X You can specify formats for languages other than C by using line Xgroup formats and line formats, as described in the next sections. X X* Menu: X X* Line Group Formats:: Formats for general if-then-else line groups. X* Line Formats:: Formats for each line in a line group. X* Detailed If-then-else:: A detailed description of if-then-else format. X* Example If-then-else:: Sample if-then-else format output. X X XFile: diff.info, Node: Line Group Formats, Next: Line Formats, Up: If-then-else X XLine Group Formats X------------------ X X Line group formats let you specify formats suitable for many Xapplications that allow if-then-else input, including programming Xlanguages and text formatting languages. A line group format specifies Xthe output format for a contiguous group of similar lines. X X For example, the following command compares the TeX files `old' and X`new', and outputs a merged file in which old regions are surrounded by X`\begin{em}'-`\end{em}' lines, and new regions are surrounded by X`\begin{bf}'-`\end{bf}' lines. X X diff \ X --old-group-format='\begin{em} X %<\end{em} X ' \ X --new-group-format='\begin{bf} X %>\end{bf} X ' \ X old new X X The following command is equivalent to the above example, but it is a Xlittle more verbose, because it spells out the default line group Xformats. X X diff \ X --old-group-format='\begin{em} X %<\end{em} X ' \ X --new-group-format='\begin{bf} X %>\end{bf} X ' \ X --unchanged-group-format='%=' \ X --changed-group-format='\begin{em} X %<\end{em} X \begin{bf} X %>\end{bf} X ' \ X old new X X Here is a more advanced example, which outputs a diff listing with Xheaders containing line numbers in a "plain English" style. X X diff \ X --unchanged-group-format='' \ X --old-group-format='-------- %dn line%(n=1?:s) deleted at %df: X %<' \ X --new-group-format='-------- %dN line%(N=1?:s) added after %de: X %>' \ X --changed-group-format='-------- %dn line%(n=1?:s) changed at %df: X %<-------- to: X %>' \ X old new X X To specify a line group format, use `diff' with one of the options Xlisted below. You can specify up to four line group formats, one for Xeach kind of line group. You should quote FORMAT, because it typically Xcontains shell metacharacters. X X`--old-group-format=FORMAT' X These line groups are hunks containing only lines from the first X file. The default old group format is the same as the changed X group format if it is specified; otherwise it is a format that X outputs the line group as-is. X X`--new-group-format=FORMAT' X These line groups are hunks containing only lines from the second X file. The default new group format is same as the changed group X format if it is specified; otherwise it is a format that outputs X the line group as-is. X X`--changed-group-format=FORMAT' X These line groups are hunks containing lines from both files. The X default changed group format is the concatenation of the old and X new group formats. X X`--unchanged-group-format=FORMAT' X These line groups contain lines common to both files. The default X unchanged group format is a format that outputs the line group X as-is. X X In a line group format, ordinary characters represent themselves; Xconversion specifications start with `%' and have one of the following Xforms. X X`%<' X stands for the lines from the first file, including the trailing X newline. Each line is formatted according to the old line format X (*note Line Formats::). X X`%>' X stands for the lines from the second file, including the trailing X newline. Each line is formatted according to the new line format. X X`%=' X stands for the lines common to both files, including the trailing X newline. Each line is formatted according to the unchanged line X format. X X`%%' X stands for `%'. X X`%c'C'' X where C is a single character, stands for C. C may not be a X backslash or an apostrophe. For example, `%c':'' stands for a X colon, even inside the then-part of an if-then-else format, which X a colon would normally terminate. X X`%c'\O'' X where O is a string of 1, 2, or 3 octal digits, stands for the X character with octal code O. For example, `%c'\0'' stands for a X null character. X X`FN' X where F is a `printf' conversion specification and N is one of the X following letters, stands for N's value formatted with F. X X `e' X The line number of the line just before the group in the old X file. X X `f' X The line number of the first line in the group in the old X file; equals E + 1. X X `l' X The line number of the last line in the group in the old file. X X `m' X The line number of the line just after the group in the old X file; equals L + 1. X X `n' X The number of lines in the group in the old file; equals L - X F + 1. X X `E, F, L, M, N' X Likewise, for lines in the new file. X X The `printf' conversion specification can be `%d', `%o', `%x', or X `%X', specifying decimal, octal, lower case hexadecimal, or upper X case hexadecimal output respectively. After the `%' the following X options can appear in sequence: a series of zero or more flags; an X integer specifying the minimum field width; and a period followed X by an optional integer specifying the minimum number of digits. X The flags are `-' for left-justification, `'' for separating the X digit into groups as specified by the `LC_NUMERIC' locale category, X and `0' for padding with zeros instead of spaces. For example, X `%5dN' prints the number of new lines in the group in a field of X width 5 characters, using the `printf' format `"%5d"'. X X`(A=B?T:E)' X If A equals B then T else E. A and B are each either a decimal X constant or a single letter interpreted as above. This format X spec is equivalent to T if A's value equals B's; otherwise it is X equivalent to E. X X For example, `%(N=0?no:%dN) line%(N=1?:s)' is equivalent to `no X lines' if N (the number of lines in the group in the the new file) X is 0, to `1 line' if N is 1, and to `%dN lines' otherwise. X X XFile: diff.info, Node: Line Formats, Next: Detailed If-then-else, Prev: Line Group Formats, Up: If-then-else X XLine Formats X------------ X X Line formats control how each line taken from an input file is Xoutput as part of a line group in if-then-else format. X X For example, the following command outputs text with a one-character Xchange indicator to the left of the text. The first character of output Xis `-' for deleted lines, `|' for added lines, and a space for Xunchanged lines. The formats contain newline characters where newlines Xare desired on output. X X diff \ X --old-line-format='-%l X ' \ X --new-line-format='|%l X ' \ X --unchanged-line-format=' %l X ' \ X old new X X To specify a line format, use one of the following options. You Xshould quote FORMAT, since it often contains shell metacharacters. X X`--old-line-format=FORMAT' X formats lines just from the first file. X X`--new-line-format=FORMAT' X formats lines just from the second file. X X`--unchanged-line-format=FORMAT' X formats lines common to both files. X X`--line-format=FORMAT' X formats all lines; in effect, it sets all three above options X simultaneously. X X In a line format, ordinary characters represent themselves; Xconversion specifications start with `%' and have one of the following Xforms. X X`%l' X stands for the contents of the line, not counting its trailing X newline (if any). This format ignores whether the line is X incomplete; *Note Incomplete Lines::. X X`%L' X stands for the contents of the line, including its trailing newline X (if any). If a line is incomplete, this format preserves its X incompleteness. X X`%%' X stands for `%'. X X`%c'C'' X where C is a single character, stands for C. C may not be a X backslash or an apostrophe. For example, `%c':'' stands for a X colon. X X`%c'\O'' X where O is a string of 1, 2, or 3 octal digits, stands for the X character with octal code O. For example, `%c'\0'' stands for a X null character. X X`Fn' X where F is a `printf' conversion specification, stands for the X line number formatted with F. For example, `%.5dn' prints the X line number using the `printf' format `"%.5d"'. *Note Line Group X Formats::, for more about printf conversion specifications. X X The default line format is `%l' followed by a newline character. X X If the input contains tab characters and it is important that they Xline up on output, you should ensure that `%l' or `%L' in a line format Xis just after a tab stop (e.g. by preceding `%l' or `%L' with a tab Xcharacter), or you should use the `-t' or `--expand-tabs' option. X X Taken together, the line and line group formats let you specify many Xdifferent formats. For example, the following command uses a format Xsimilar to normal `diff' format. You can tailor this command to get Xfine control over `diff' output. X X diff \ X --old-line-format='< %l X ' \ X --new-line-format='> %l X ' \ X --old-group-format='%df%(f=l?:,%dl)d%dE X %<' \ X --new-group-format='%dea%dF%(F=L?:,%dL) X %>' \ X --changed-group-format='%df%(f=l?:,%dl)c%dF%(F=L?:,%dL) X %<--- X %>' \ X --unchanged-group-format='' \ X old new X X XFile: diff.info, Node: Detailed If-then-else, Next: Example If-then-else, Prev: Line Formats, Up: If-then-else X XDetailed Description of If-then-else Format X------------------------------------------- X X For lines common to both files, `diff' uses the unchanged line group Xformat. For each hunk of differences in the merged output format, if Xthe hunk contains only lines from the first file, `diff' uses the old Xline group format; if the hunk contains only lines from the second Xfile, `diff' uses the new group format; otherwise, `diff' uses the Xchanged group format. X X The old, new, and unchanged line formats specify the output format of Xlines from the first file, lines from the second file, and lines common Xto both files, respectively. X X The option `--ifdef=NAME' is equivalent to the following sequence of Xoptions using shell syntax: X X --old-group-format='#ifndef NAME X %<#endif /* ! NAME */ X ' \ X --new-group-format='#ifdef NAME X %>#endif /* NAME */ X ' \ X --unchanged-group-format='%=' \ X --changed-group-format='#ifndef NAME X %<#else /* NAME */ X %>#endif /* NAME */ X ' X X You should carefully check the `diff' output for proper nesting. XFor example, when using the `-D NAME' or `--ifdef=NAME' option, you Xshould check that if the differing lines contain any of the C Xpreprocessor directives `#ifdef', `#ifndef', `#else', `#elif', or X`#endif', they are nested properly and match. If they don't, you must Xmake corrections manually. It is a good idea to carefully check the Xresulting code anyway to make sure that it really does what you want it Xto; depending on how the input files were produced, the output might Xcontain duplicate or otherwise incorrect code. X X The `patch' `-D NAME' option behaves like the `diff' `-D NAME' Xoption, except it operates on a file and a diff to produce a merged Xfile; *Note patch Options::. X X XFile: diff.info, Node: Example If-then-else, Prev: Detailed If-then-else, Up: If-then-else X XAn Example of If-then-else Format X--------------------------------- X X Here is the output of `diff -DTWO lao tzu' (*note Sample diff XInput::, for the complete contents of the two files): X X #ifndef TWO X The Way that can be told of is not the eternal Way; X The name that can be named is not the eternal name. X #endif /* ! TWO */ X The Nameless is the origin of Heaven and Earth; X #ifndef TWO X The Named is the mother of all things. X #else /* TWO */ X The named is the mother of all things. X X #endif /* TWO */ X Therefore let there always be non-being, X so we may see their subtlety, X And let there always be being, X so we may see their outcome. X The two are the same, X But after they are produced, X they have different names. X #ifdef TWO X They both may be called deep and profound. X Deeper and more profound, X The door of all subtleties! X #endif /* TWO */ X X XFile: diff.info, Node: Incomplete Lines, Next: Comparing Directories, Prev: Output Formats, Up: Top X XIncomplete Lines X**************** X X When an input file ends in a non-newline character, its last line is Xcalled an "incomplete line" because its last character is not a Xnewline. All other lines are called "full lines" and end in a newline Xcharacter. Incomplete lines do not match full lines unless differences Xin white space are ignored (*note White Space::). X X An incomplete line is normally distinguished on output from a full Xline by a following line that starts with `\'. However, the RCS format X(*note RCS::) outputs the incomplete line as-is, without any trailing Xnewline or following line. The side by side format normally represents Xincomplete lines as-is, but in some cases uses a `\' or `/' gutter Xmarker; *Note Side by Side::. The if-then-else line format preserves a Xline's incompleteness with `%L', and discards the newline with `%l'; X*Note Line Formats::. Finally, with the `ed' and forward `ed' output Xformats (*note Output Formats::) `diff' cannot represent an incomplete Xline, so it pretends there was a newline and reports an error. X X For example, suppose `F' and `G' are one-byte files that contain Xjust `f' and `g', respectively. Then `diff F G' outputs X X 1c1 X < f X \ No newline at end of file X --- X > g X \ No newline at end of file X X(The exact message may differ in non-English locales.) `diff -n F G' Xoutputs the following without a trailing newline: X X d1 1 X a1 1 X g X X`diff -e F G' reports two errors and outputs the following: X X 1c X g X . X X XFile: diff.info, Node: Comparing Directories, Next: Adjusting Output, Prev: Incomplete Lines, Up: Top X XComparing Directories X********************* X X You can use `diff' to compare some or all of the files in two Xdirectory trees. When both file name arguments to `diff' are Xdirectories, it compares each file that is contained in both Xdirectories, examining file names in alphabetical order as specified by Xthe `LC_COLLATE' locale category. Normally `diff' is silent about Xpairs of files that contain no differences, but if you use the `-s' or X`--report-identical-files' option, it reports pairs of identical files. XNormally `diff' reports subdirectories common to both directories Xwithout comparing subdirectories' files, but if you use the `-r' or X`--recursive' option, it compares every corresponding pair of files in Xthe directory trees, as many levels deep as they go. X X For file names that are in only one of the directories, `diff' Xnormally does not show the contents of the file that exists; it reports Xonly that the file exists in that directory and not in the other. You Xcan make `diff' act as though the file existed but was empty in the Xother directory, so that it outputs the entire contents of the file that Xactually exists. (It is output as either an insertion or a deletion, Xdepending on whether it is in the first or the second directory given.) XTo do this, use the `-N' or `--new-file' option. X X If the older directory contains one or more large files that are not Xin the newer directory, you can make the patch smaller by using the X`--unidirectional-new-file' option instead of `-N'. This option is Xlike `-N' except that it only inserts the contents of files that appear Xin the second directory but not the first (that is, files that were Xadded). At the top of the patch, write instructions for the user Xapplying the patch to remove the files that were deleted before Xapplying the patch. *Note Making Patches::, for more discussion of Xmaking patches for distribution. X X To ignore some files while comparing directories, use the `-x XPATTERN' or `--exclude=PATTERN' option. This option ignores any files Xor subdirectories whose base names match the shell pattern PATTERN. XUnlike in the shell, a period at the start of the base of a file name Xmatches a wildcard at the start of a pattern. You should enclose XPATTERN in quotes so that the shell does not expand it. For example, Xthe option `-x '*.[ao]'' ignores any file whose name ends with `.a' or X`.o'. X X This option accumulates if you specify it more than once. For Xexample, using the options `-x 'RCS' -x '*,v'' ignores any file or Xsubdirectory whose base name is `RCS' or ends with `,v'. X X If you need to give this option many times, you can instead put the Xpatterns in a file, one pattern per line, and use the `-X FILE' or X`--exclude-from=FILE' option. X X If you have been comparing two directories and stopped partway Xthrough, later you might want to continue where you left off. You can Xdo this by using the `-S FILE' or `--starting-file=FILE' option. This Xcompares only the file FILE and all alphabetically later files in the Xtopmost directory level. X X If two directories differ only in that file names are lower case in Xone directory and upper case in the upper, `diff' normally reports many Xdifferences because it compares file names in a case sensitive way. XWith the `--ignore-file-name-case' option, `diff' ignores case Xdifferences in file names, so that for example the contents of the file X`Tao' in one directory are compared to the contents of the file `TAO' Xin the other. The `--no-ignore-file-name-case' option cancels the Xeffect of the `--ignore-file-name-case' option, reverting to the default Xbehavior. X X If an `-x PATTERN', `--exclude=PATTERN', `-X FILE', or X`--exclude-from=FILE' option is specified while the X`--ignore-file-name-case' option is in effect, case is ignored when Xexcluding file names matching the specified patterns. X X XFile: diff.info, Node: Adjusting Output, Next: diff Performance, Prev: Comparing Directories, Up: Top X XMaking `diff' Output Prettier X***************************** X X `diff' provides several ways to adjust the appearance of its output. XThese adjustments can be applied to any output format. X X* Menu: X X* Tabs:: Preserving the alignment of tab stops. X* Pagination:: Page numbering and time-stamping `diff' output. X X XFile: diff.info, Node: Tabs, Next: Pagination, Up: Adjusting Output X XPreserving Tab Stop Alignment X============================= X X The lines of text in some of the `diff' output formats are preceded Xby one or two characters that indicate whether the text is inserted, Xdeleted, or changed. The addition of those characters can cause tabs to Xmove to the next tab stop, throwing off the alignment of columns in the Xline. GNU `diff' provides two ways to make tab-aligned columns line up Xcorrectly. X X The first way is to have `diff' convert all tabs into the correct Xnumber of spaces before outputting them; select this method with the X`-t' or `--expand-tabs' option. `diff' assumes that tab stops are set Xevery 8 print columns. To use this form of output with `patch', you Xmust give `patch' the `-l' or `--ignore-white-space' option (*note XChanged White Space::, for more information). X X The other method for making tabs line up correctly is to add a tab Xcharacter instead of a space after the indicator character at the Xbeginning of the line. This ensures that all following tab characters Xare in the same position relative to tab stops that they were in the Xoriginal files, so that the output is aligned correctly. Its Xdisadvantage is that it can make long lines too long to fit on one line Xof the screen or the paper. It also does not work with the unified Xoutput format, which does not have a space character after the change Xtype indicator character. Select this method with the `-T' or X`--initial-tab' option. X X XFile: diff.info, Node: Pagination, Prev: Tabs, Up: Adjusting Output X XPaginating `diff' Output X======================== X X It can be convenient to have long output page-numbered and Xtime-stamped. The `-l' and `--paginate' options do this by sending the X`diff' output through the `pr' program. Here is what the page header Xmight look like for `diff -lc lao tzu': X X 2002-02-22 14:20 diff -lc lao tzu Page 1 X X XFile: diff.info, Node: diff Performance, Next: Comparing Three Files, Prev: Adjusting Output, Up: Top X X`diff' Performance Tradeoffs X**************************** X X GNU `diff' runs quite efficiently; however, in some circumstances Xyou can cause it to run faster or produce a more compact set of changes. X X One way to improve `diff' performance is to use hard or symbolic Xlinks to files instead of copies. This improves performance because X`diff' normally does not need to read two hard or symbolic links to the Xsame file, since their contents must be identical. For example, Xsuppose you copy a large directory hierarchy, make a few changes to the Xcopy, and then often use `diff -r' to compare the original to the copy. XIf the original files are read-only, you can greatly improve Xperformance by creating the copy using hard or symbolic links (e.g., Xwith GNU `cp -lR' or `cp -sR'). Before editing a file in the copy for Xthe first time, you should break the link and replace it with a regular Xcopy. X X You can also affect the performance of GNU `diff' by giving it Xoptions that change the way it compares files. Performance has more Xthan one dimension. These options improve one aspect of performance at Xthe cost of another, or they improve performance in some cases while Xhurting it in others. X X The way that GNU `diff' determines which lines have changed always Xcomes up with a near-minimal set of differences. Usually it is good Xenough for practical purposes. If the `diff' output is large, you Xmight want `diff' to use a modified algorithm that sometimes produces a Xsmaller set of differences. The `-d' or `--minimal' option does this; Xhowever, it can also cause `diff' to run more slowly than usual, so it Xis not the default behavior. X X When the files you are comparing are large and have small groups of Xchanges scattered throughout them, you can use the X`--speed-large-files' option to make a different modification to the Xalgorithm that `diff' uses. If the input files have a constant small Xdensity of changes, this option speeds up the comparisons without Xchanging the output. If not, `diff' might produce a larger set of Xdifferences; however, the output will still be correct. X X Normally `diff' discards the prefix and suffix that is common to Xboth files before it attempts to find a minimal set of differences. XThis makes `diff' run faster, but occasionally it may produce Xnon-minimal output. The `--horizon-lines=LINES' option prevents `diff' Xfrom discarding the last LINES lines of the prefix and the first LINES Xlines of the suffix. This gives `diff' further opportunities to find a Xminimal output. X X Suppose a run of changed lines includes a sequence of lines at one Xend and there is an identical sequence of lines just outside the other Xend. The `diff' command is free to choose which identical sequence is Xincluded in the hunk. In this case, `diff' normally shifts the hunk's Xboundaries when this merges adjacent hunks, or shifts a hunk's lines Xtowards the end of the file. Merging hunks can make the output look Xnicer in some cases. X X XFile: diff.info, Node: Comparing Three Files, Next: diff3 Merging, Prev: diff Performance, Up: Top X XComparing Three Files X********************* X X Use the program `diff3' to compare three files and show any Xdifferences among them. (`diff3' can also merge files; see *Note diff3 XMerging::). X X The "normal" `diff3' output format shows each hunk of differences Xwithout surrounding context. Hunks are labeled depending on whether Xthey are two-way or three-way, and lines are annotated by their Xlocation in the input files. X X *Note Invoking diff3::, for more information on how to run `diff3'. X X* Menu: X X* Sample diff3 Input:: Sample `diff3' input for examples. X* Detailed diff3 Normal:: A detailed description of normal output format. X* diff3 Hunks:: The format of normal output format. X* Example diff3 Normal:: Sample output in the normal format. X X XFile: diff.info, Node: Sample diff3 Input, Next: Detailed diff3 Normal, Up: Comparing Three Files X XA Third Sample Input File X========================= X X Here is a third sample file that will be used in examples to Xillustrate the output of `diff3' and how various options can change it. XThe first two files are the same that we used for `diff' (*note Sample Xdiff Input::). This is the third sample file, called `tao': X X The Way that can be told of is not the eternal Way; X The name that can be named is not the eternal name. X The Nameless is the origin of Heaven and Earth; X The named is the mother of all things. X X Therefore let there always be non-being, X so we may see their subtlety, X And let there always be being, X so we may see their result. X The two are the same, X But after they are produced, X they have different names. X X -- The Way of Lao-Tzu, tr. Wing-tsit Chan X X XFile: diff.info, Node: Detailed diff3 Normal, Next: diff3 Hunks, Prev: Sample diff3 Input, Up: Comparing Three Files X XDetailed Description of `diff3' Normal Format X============================================= X X Each hunk begins with a line marked `===='. Three-way hunks have Xplain `====' lines, and two-way hunks have `1', `2', or `3' appended to Xspecify which of the three input files differ in that hunk. The hunks Xcontain copies of two or three sets of input lines each preceded by one Xor two commands identifying where the lines came from. X X Normally, two spaces precede each copy of an input line to Xdistinguish it from the commands. But with the `-T' or `--initial-tab' Xoption, `diff3' uses a tab instead of two spaces; this lines up tabs Xcorrectly. *Note Tabs::, for more information. X X Commands take the following forms: X X`FILE:La' X This hunk appears after line L of file FILE, and contains no lines X in that file. To edit this file to yield the other files, one X must append hunk lines taken from the other files. For example, X `1:11a' means that the hunk follows line 11 in the first file and X contains no lines from that file. X X`FILE:Rc' X This hunk contains the lines in the range R of file FILE. The X range R is a comma-separated pair of line numbers, or just one X number if the range is a singleton. To edit this file to yield the X other files, one must change the specified lines to be the lines X taken from the other files. For example, `2:11,13c' means that X the hunk contains lines 11 through 13 from the second file. X X If the last line in a set of input lines is incomplete (*note XIncomplete Lines::), it is distinguished on output from a full line by Xa following line that starts with `\'. X X XFile: diff.info, Node: diff3 Hunks, Next: Example diff3 Normal, Prev: Detailed diff3 Normal, Up: Comparing Three Files X X`diff3' Hunks X============= X X Groups of lines that differ in two or three of the input files are Xcalled "diff3 hunks", by analogy with `diff' hunks (*note Hunks::). If Xall three input files differ in a `diff3' hunk, the hunk is called a X"three-way hunk"; if just two input files differ, it is a "two-way Xhunk". X X As with `diff', several solutions are possible. When comparing the Xfiles `A', `B', and `C', `diff3' normally finds `diff3' hunks by Xmerging the two-way hunks output by the two commands `diff A B' and X`diff A C'. This does not necessarily minimize the size of the output, Xbut exceptions should be rare. X X For example, suppose `F' contains the three lines `a', `b', `f', `G' Xcontains the lines `g', `b', `g', and `H' contains the lines `a', `b', X`h'. `diff3 F G H' might output the following: X X ====2 X 1:1c X 3:1c X a X 2:1c X g X ==== X 1:3c X f X 2:3c X g X 3:3c X h X Xbecause it found a two-way hunk containing `a' in the first and third Xfiles and `g' in the second file, then the single line `b' common to Xall three files, then a three-way hunk containing the last line of each Xfile. X X XFile: diff.info, Node: Example diff3 Normal, Prev: diff3 Hunks, Up: Comparing Three Files X XAn Example of `diff3' Normal Format X=================================== X X Here is the output of the command `diff3 lao tzu tao' (*note Sample Xdiff3 Input::, for the complete contents of the files). Notice that it Xshows only the lines that are different among the three files. X X ====2 X 1:1,2c X 3:1,2c X The Way that can be told of is not the eternal Way; X The name that can be named is not the eternal name. X 2:0a X ====1 X 1:4c X The Named is the mother of all things. X 2:2,3c X 3:4,5c X The named is the mother of all things. X X ====3 X 1:8c X 2:7c X so we may see their outcome. X 3:9c X so we may see their result. X ==== X 1:11a X 2:11,13c X They both may be called deep and profound. X Deeper and more profound, X The door of all subtleties! X 3:13,14c X X -- The Way of Lao-Tzu, tr. Wing-tsit Chan X X XFile: diff.info, Node: diff3 Merging, Next: Interactive Merging, Prev: Comparing Three Files, Up: Top X XMerging From a Common Ancestor X****************************** X X When two people have made changes to copies of the same file, X`diff3' can produce a merged output that contains both sets of changes Xtogether with warnings about conflicts. X X One might imagine programs with names like `diff4' and `diff5' to Xcompare more than three files simultaneously, but in practice the need Xrarely arises. You can use `diff3' to merge three or more sets of Xchanges to a file by merging two change sets at a time. X X `diff3' can incorporate changes from two modified versions into a Xcommon preceding version. This lets you merge the sets of changes Xrepresented by the two newer files. Specify the common ancestor version Xas the second argument and the two newer versions as the first and third Xarguments, like this: X X diff3 MINE OLDER YOURS X XYou can remember the order of the arguments by noting that they are in Xalphabetical order. X X You can think of this as subtracting OLDER from YOURS and adding the Xresult to MINE, or as merging into MINE the changes that would turn XOLDER into YOURS. This merging is well-defined as long as MINE and XOLDER match in the neighborhood of each such change. This fails to be Xtrue when all three input files differ or when only OLDER differs; we Xcall this a "conflict". When all three input files differ, we call the Xconflict an "overlap". X X `diff3' gives you several ways to handle overlaps and conflicts. XYou can omit overlaps or conflicts, or select only overlaps, or mark Xconflicts with special `<<<<<<<' and `>>>>>>>' lines. X X `diff3' can output the merge results as an `ed' script that that can Xbe applied to the first file to yield the merged output. However, it Xis usually better to have `diff3' generate the merged output directly; Xthis bypasses some problems with `ed'. X X* Menu: X X* Which Changes:: Selecting changes to incorporate. X* Marking Conflicts:: Marking conflicts. X* Bypassing ed:: Generating merged output directly. X* Merging Incomplete Lines:: How `diff3' merges incomplete lines. X* Saving the Changed File:: Emulating System V behavior. X X XFile: diff.info, Node: Which Changes, Next: Marking Conflicts, Up: diff3 Merging X XSelecting Which Changes to Incorporate X====================================== X X You can select all unmerged changes from OLDER to YOURS for merging Xinto MINE with the `-e' or `--ed' option. You can select only the Xnonoverlapping unmerged changes with `-3' or `--easy-only', and you can Xselect only the overlapping changes with `-x' or `--overlap-only'. X X The `-e', `-3' and `-x' options select only "unmerged changes", i.e. Xchanges where MINE and YOURS differ; they ignore changes from OLDER to XYOURS where MINE and YOURS are identical, because they assume that such Xchanges have already been merged. If this assumption is not a safe Xone, you can use the `-A' or `--show-all' option (*note Marking XConflicts::). X X Here is the output of the command `diff3' with each of these three Xoptions (*note Sample diff3 Input::, for the complete contents of the Xfiles). Notice that `-e' outputs the union of the disjoint sets of Xchanges output by `-3' and `-x'. X X Output of `diff3 -e lao tzu tao': X 11a X X -- The Way of Lao-Tzu, tr. Wing-tsit Chan X . X 8c X so we may see their result. X . X X Output of `diff3 -3 lao tzu tao': X 8c X so we may see their result. X . X X Output of `diff3 -x lao tzu tao': X 11a X X -- The Way of Lao-Tzu, tr. Wing-tsit Chan X . X X XFile: diff.info, Node: Marking Conflicts, Next: Bypassing ed, Prev: Which Changes, Up: diff3 Merging X XMarking Conflicts X================= X X `diff3' can mark conflicts in the merged output by bracketing them Xwith special marker lines. A conflict that comes from two files A and XB is marked as follows: X X <<<<<<< A X lines from A X ======= X lines from B X >>>>>>> B X X A conflict that comes from three files A, B and C is marked as Xfollows: X X <<<<<<< A X lines from A X ||||||| B X lines from B X ======= X lines from C X >>>>>>> C X X The `-A' or `--show-all' option acts like the `-e' option, except Xthat it brackets conflicts, and it outputs all changes from OLDER to XYOURS, not just the unmerged changes. Thus, given the sample input Xfiles (*note Sample diff3 Input::), `diff3 -A lao tzu tao' puts Xbrackets around the conflict where only `tzu' differs: X X <<<<<<< tzu X ======= X The Way that can be told of is not the eternal Way; X The name that can be named is not the eternal name. X >>>>>>> tao X X And it outputs the three-way conflict as follows: X X <<<<<<< lao X ||||||| tzu X They both may be called deep and profound. X Deeper and more profound, X The door of all subtleties! X ======= X X -- The Way of Lao-Tzu, tr. Wing-tsit Chan X >>>>>>> tao X X The `-E' or `--show-overlap' option outputs less information than Xthe `-A' or `--show-all' option, because it outputs only unmerged Xchanges, and it never outputs the contents of the second file. Thus Xthe `-E' option acts like the `-e' option, except that it brackets the Xfirst and third files from three-way overlapping changes. Similarly, X`-X' acts like `-x', except it brackets all its (necessarily Xoverlapping) changes. For example, for the three-way overlapping Xchange above, the `-E' and `-X' options output the following: X X <<<<<<< lao X ======= X X -- The Way of Lao-Tzu, tr. Wing-tsit Chan X >>>>>>> tao X X If you are comparing files that have meaningless or uninformative Xnames, you can use the `-L LABEL' or `--label=LABEL' option to show Xalternate names in the `<<<<<<<', `|||||||' and `>>>>>>>' brackets. XThis option can be given up to three times, once for each input file. XThus `diff3 -A -L X -L Y -L Z A B C' acts like `diff3 -A A B C', except Xthat the output looks like it came from files named `X', `Y' and `Z' Xrather than from files named `A', `B' and `C'. X X XFile: diff.info, Node: Bypassing ed, Next: Merging Incomplete Lines, Prev: Marking Conflicts, Up: diff3 Merging X XGenerating the Merged Output Directly X===================================== X X With the `-m' or `--merge' option, `diff3' outputs the merged file Xdirectly. This is more efficient than using `ed' to generate it, and Xworks even with non-text files that `ed' would reject. If you specify X`-m' without an `ed' script option, `-A' (`--show-all') is assumed. X X For example, the command `diff3 -m lao tzu tao' (*note Sample diff3 XInput:: for a copy of the input files) would output the following: X X <<<<<<< tzu X ======= X The Way that can be told of is not the eternal Way; X The name that can be named is not the eternal name. X >>>>>>> tao X The Nameless is the origin of Heaven and Earth; X The Named is the mother of all things. X Therefore let there always be non-being, X so we may see their subtlety, X And let there always be being, X so we may see their result. X The two are the same, X But after they are produced, X they have different names. X <<<<<<< lao X ||||||| tzu X They both may be called deep and profound. X Deeper and more profound, X The door of all subtleties! X ======= X X -- The Way of Lao-Tzu, tr. Wing-tsit Chan X >>>>>>> tao X X XFile: diff.info, Node: Merging Incomplete Lines, Next: Saving the Changed File, Prev: Bypassing ed, Up: diff3 Merging X XHow `diff3' Merges Incomplete Lines X=================================== X X With `-m', incomplete lines (*note Incomplete Lines::) are simply Xcopied to the output as they are found; if the merged output ends in an Xconflict and one of the input files ends in an incomplete line, Xsucceeding `|||||||', `=======' or `>>>>>>>' brackets appear somewhere Xother than the start of a line because they are appended to the Xincomplete line. X X Without `-m', if an `ed' script option is specified and an Xincomplete line is found, `diff3' generates a warning and acts as if a Xnewline had been present. X X XFile: diff.info, Node: Saving the Changed File, Prev: Merging Incomplete Lines, Up: diff3 Merging X XSaving the Changed File X======================= X X Traditional Unix `diff3' generates an `ed' script without the Xtrailing `w' and `q' commands that save the changes. System V `diff3' Xgenerates these extra commands. GNU `diff3' normally behaves like Xtraditional Unix `diff3', but with the `-i' option it behaves like XSystem V `diff3' and appends the `w' and `q' commands. X X The `-i' option requires one of the `ed' script options `-AeExX3', Xand is incompatible with the merged output option `-m'. X X XFile: diff.info, Node: Interactive Merging, Next: Merging with patch, Prev: diff3 Merging, Up: Top X XInteractive Merging with `sdiff' X******************************** X X With `sdiff', you can merge two files interactively based on a Xside-by-side `-y' format comparison (*note Side by Side::). Use `-o XFILE' or `--output=FILE' to specify where to put the merged text. X*Note Invoking sdiff::, for more details on the options to `sdiff'. X X Another way to merge files interactively is to use the Emacs Lisp Xpackage `emerge'. *Note emerge: (emacs)emerge, for more information. X X* Menu: X X* sdiff Option Summary:: Summary of `sdiff' options. X* Merge Commands:: Merging two files interactively. X X XFile: diff.info, Node: sdiff Option Summary, Next: Merge Commands, Up: Interactive Merging X XSpecifying `diff' Options to `sdiff' X==================================== X X The following `sdiff' options have the same meaning as for `diff'. X*Note diff Options::, for the use of these options. X X -a -b -d -i -t -v X -B -E -I REGEXP X X --ignore-blank-lines --ignore-case X --ignore-matching-lines=REGEXP --ignore-space-change X --ignore-tab-expansion X --left-column --minimal --speed-large-files X --strip-trailing-cr --suppress-common-lines --expand-tabs X --text --version --width=COLUMNS X X For historical reasons, `sdiff' has alternate names for some Xoptions. The `-l' option is equivalent to the `--left-column' option, Xand similarly `-s' is equivalent to `--suppress-common-lines'. The Xmeaning of the `sdiff' `-w' and `-W' options is interchanged from that Xof `diff': with `sdiff', `-w COLUMNS' is equivalent to X`--width=COLUMNS', and `-W' is equivalent to `--ignore-all-space'. X`sdiff' without the `-o' option is equivalent to `diff' with the `-y' Xor `--side-by-side' option (*note Side by Side::). X X XFile: diff.info, Node: Merge Commands, Prev: sdiff Option Summary, Up: Interactive Merging X XMerge Commands X============== X X Groups of common lines, with a blank gutter, are copied from the Xfirst file to the output. After each group of differing lines, `sdiff' Xprompts with `%' and pauses, waiting for one of the following commands. XFollow each command with . X X`e' X Discard both versions. Invoke a text editor on an empty temporary X file, then copy the resulting file to the output. X X`eb' X Concatenate the two versions, edit the result in a temporary file, X then copy the edited result to the output. X X`ed' X Like `eb', except precede each version with a header that shows X what file and lines the version came from. X X`el' X Edit a copy of the left version, then copy the result to the X output. X X`er' X Edit a copy of the right version, then copy the result to the X output. X X`l' X Copy the left version to the output. X X`q' X Quit. X X`r' X Copy the right version to the output. X X`s' X Silently copy common lines. X X`v' X Verbosely copy common lines. This is the default. X X The text editor invoked is specified by the `EDITOR' environment Xvariable if it is set. The default is system-dependent. X X XFile: diff.info, Node: Merging with patch, Next: Making Patches, Prev: Interactive Merging, Up: Top X XMerging with `patch' X******************** X X `patch' takes comparison output produced by `diff' and applies the Xdifferences to a copy of the original file, producing a patched Xversion. With `patch', you can distribute just the changes to a set of Xfiles instead of distributing the entire file set; your correspondents Xcan apply `patch' to update their copy of the files with your changes. X`patch' automatically determines the diff format, skips any leading or Xtrailing headers, and uses the headers to determine which file to Xpatch. This lets your correspondents feed a mail message containing a Xdifference listing directly to `patch'. X X `patch' detects and warns about common problems like forward Xpatches. It saves any patches that it could not apply. It can also Xmaintain a `patchlevel.h' file to ensure that your correspondents apply Xdiffs in the proper order. X X `patch' accepts a series of diffs in its standard input, usually Xseparated by headers that specify which file to patch. It applies X`diff' hunks (*note Hunks::) one by one. If a hunk does not exactly Xmatch the original file, `patch' uses heuristics to try to patch the Xfile as well as it can. If no approximate match can be found, `patch' Xrejects the hunk and skips to the next hunk. `patch' normally replaces Xeach file F with its new version, putting reject hunks (if any) into X`F.rej'. X X *Note Invoking patch::, for detailed information on the options to X`patch'. X X* Menu: X X* patch Input:: Selecting the type of `patch' input. X* Revision Control:: Getting files from RCS, SCCS, etc. X* Imperfect:: Dealing with imperfect patches. X* Creating and Removing:: Creating and removing files with a patch. X* Patching Time Stamps:: Updating time stamps on patched files. X* Multiple Patches:: Handling multiple patches in a file. X* patch Directories:: Changing directory and stripping directories. X* Backups:: Whether backup files are made. X* Backup Names:: Backup file names. X* Reject Names:: Reject file names. X* patch Messages:: Messages and questions `patch' can produce. X* patch and POSIX:: Conformance to the POSIX standard. X* patch and Tradition:: GNU versus traditional `patch'. X X XFile: diff.info, Node: patch Input, Next: Revision Control, Up: Merging with patch X XSelecting the `patch' Input Format X================================== X X `patch' normally determines which `diff' format the patch file uses Xby examining its contents. For patch files that contain particularly Xconfusing leading text, you might need to use one of the following Xoptions to force `patch' to interpret the patch file as a certain Xformat of diff. The output formats listed here are the only ones that X`patch' can understand. X X`-c' X`--context' X context diff. X X`-e' X`--ed' X `ed' script. X X`-n' X`--normal' X normal diff. X X`-u' X`--unified' X unified diff. X X XFile: diff.info, Node: Revision Control, Next: Imperfect, Prev: patch Input, Up: Merging with patch X XRevision Control X================ X X If a nonexistent input file is under a revision control system Xsupported by `patch', `patch' normally asks the user whether to get (or Xcheck out) the file from the revision control system. Patch currently Xsupports RCS, ClearCase and SCCS. Under RCS and SCCS, `patch' also Xasks when the input file is read-only and matches the default version Xin the revision control system. X X The `-g NUM' or `--get=NUM' affects access to files under supported Xrevision control systems. If NUM is positive, `patch' gets the file Xwithout asking the user; if zero, `patch' neither asks the user nor Xgets the file; and if negative, `patch' asks the user before getting Xthe file. The default value of NUM is given by the value of the X`PATCH_GET' environment variable if it is set; if not, the default Xvalue is zero if `patch' is conforming to POSIX, negative otherwise. X*Note patch and POSIX::. X X The choice of revision control system is unaffected by the X`VERSION_CONTROL' environment variable (*note Backup Names::). X X XFile: diff.info, Node: Imperfect, Next: Creating and Removing, Prev: Revision Control, Up: Merging with patch X XApplying Imperfect Patches X========================== X X `patch' tries to skip any leading text in the patch file, apply the Xdiff, and then skip any trailing text. Thus you can feed a mail Xmessage directly to `patch', and it should work. If the entire diff is Xindented by a constant amount of white space, `patch' automatically Xignores the indentation. If a context diff contains trailing carriage Xreturn on each line, `patch' automatically ignores the carriage return. XIf a context diff has been encapsulated by prepending `- ' to lines Xbeginning with `-' as per Internet RFC 934 X(ftp://ftp.isi.edu/in-notes/rfc934.txt), `patch' automatically Xunencapsulates the input. X X However, certain other types of imperfect input require user Xintervention or testing. X X* Menu: X X* Changed White Space:: When tabs and spaces don't match exactly. X* Reversed Patches:: Applying reversed patches correctly. X* Inexact:: Helping `patch' find close matches. X* Dry Runs:: Predicting what `patch' will do. X X XFile: diff.info, Node: Changed White Space, Next: Reversed Patches, Up: Imperfect X XApplying Patches with Changed White Space X----------------------------------------- X X Sometimes mailers, editors, or other programs change spaces into Xtabs, or vice versa. If this happens to a patch file or an input file, Xthe files might look the same, but `patch' will not be able to match Xthem properly. If this problem occurs, use the `-l' or X`--ignore-white-space' option, which makes `patch' compare blank Xcharacters (i.e. spaces and tabs) loosely so that any nonempty sequence Xof blanks in the patch file matches any nonempty sequence of blanks in Xthe input files. Non-blank characters must still match exactly. Each Xline of the context must still match a line in the input file. X X XFile: diff.info, Node: Reversed Patches, Next: Inexact, Prev: Changed White Space, Up: Imperfect X XApplying Reversed Patches X------------------------- X X Sometimes people run `diff' with the new file first instead of Xsecond. This creates a diff that is "reversed". To apply such Xpatches, give `patch' the `-R' or `--reverse' option. `patch' then Xattempts to swap each hunk around before applying it. Rejects come out Xin the swapped format. X X Often `patch' can guess that the patch is reversed. If the first Xhunk of a patch fails, `patch' reverses the hunk to see if it can apply Xit that way. If it can, `patch' asks you if you want to have the `-R' Xoption set; if it can't, `patch' continues to apply the patch normally. XThis method cannot detect a reversed patch if it is a normal diff and Xthe first command is an append (which should have been a delete) since Xappends always succeed, because a null context matches anywhere. But Xmost patches add or change lines rather than delete them, so most Xreversed normal diffs begin with a delete, which fails, and `patch' Xnotices. X X If you apply a patch that you have already applied, `patch' thinks Xit is a reversed patch and offers to un-apply the patch. This could be Xconstrued as a feature. If you did this inadvertently and you don't Xwant to un-apply the patch, just answer `n' to this offer and to the Xsubsequent "apply anyway" question--or type `C-c' to kill the `patch' Xprocess. X X XFile: diff.info, Node: Inexact, Next: Dry Runs, Prev: Reversed Patches, Up: Imperfect X XHelping `patch' Find Inexact Matches X------------------------------------ X X For context diffs, and to a lesser extent normal diffs, `patch' can Xdetect when the line numbers mentioned in the patch are incorrect, and Xit attempts to find the correct place to apply each hunk of the patch. XAs a first guess, it takes the line number mentioned in the hunk, plus Xor minus any offset used in applying the previous hunk. If that is not Xthe correct place, `patch' scans both forward and backward for a set of Xlines matching the context given in the hunk. X X First `patch' looks for a place where all lines of the context Xmatch. If it cannot find such a place, and it is reading a context or Xunified diff, and the maximum fuzz factor is set to 1 or more, then X`patch' makes another scan, ignoring the first and last line of Xcontext. If that fails, and the maximum fuzz factor is set to 2 or Xmore, it makes another scan, ignoring the first two and last two lines Xof context are ignored. It continues similarly if the maximum fuzz Xfactor is larger. X X The `-F LINES' or `--fuzz=LINES' option sets the maximum fuzz factor Xto LINES. This option only applies to context and unified diffs; it Xignores up to LINES lines while looking for the place to install a Xhunk. Note that a larger fuzz factor increases the odds of making a Xfaulty patch. The default fuzz factor is 2; there is no point to Xsetting it to more than the number of lines of context in the diff, Xordinarily 3. X X If `patch' cannot find a place to install a hunk of the patch, it Xwrites the hunk out to a reject file (*note Reject Names::, for Xinformation on how reject files are named). It writes out rejected Xhunks in context format no matter what form the input patch is in. If Xthe input is a normal or `ed' diff, many of the contexts are simply Xnull. The line numbers on the hunks in the reject file may be Xdifferent from those in the patch file: they show the approximate Xlocation where `patch' thinks the failed hunks belong in the new file Xrather than in the old one. X X If the `--verbose' option is given, then as it completes each hunk X`patch' tells you whether the hunk succeeded or failed, and if it Xfailed, on which line (in the new file) `patch' thinks the hunk should Xgo. If this is different from the line number specified in the diff, Xit tells you the offset. A single large offset _may_ indicate that X`patch' installed a hunk in the wrong place. `patch' also tells you if Xit used a fuzz factor to make the match, in which case you should also Xbe slightly suspicious. X X `patch' cannot tell if the line numbers are off in an `ed' script, Xand can only detect wrong line numbers in a normal diff when it finds a Xchange or delete command. It may have the same problem with a context Xdiff using a fuzz factor equal to or greater than the number of lines Xof context shown in the diff (typically 3). In these cases, you should Xprobably look at a context diff between your original and patched input Xfiles to see if the changes make sense. Compiling without errors is a Xpretty good indication that the patch worked, but not a guarantee. X X A patch against an empty file applies to a nonexistent file, and vice Xversa. *Note Creating and Removing::. X X `patch' usually produces the correct results, even when it must make Xmany guesses. However, the results are guaranteed only when the patch Xis applied to an exact copy of the file that the patch was generated Xfrom. X X XFile: diff.info, Node: Dry Runs, Prev: Inexact, Up: Imperfect X XPredicting what `patch' will do X------------------------------- X X It may not be obvious in advance what `patch' will do with a Xcomplicated or poorly formatted patch. If you are concerned that the Xinput might cause `patch' to modify the wrong files, you can use the X`--dry-run' option, which causes `patch' to print the results of Xapplying patches without actually changing any files. You can then Xinspect the diagnostics generated by the dry run to see whether `patch' Xwill modify the files that you expect. If the patch does not do what Xyou want, you can modify the patch (or the other options to `patch') Xand try another dry run. Once you are satisfied with the proposed Xpatch you can apply it by invoking `patch' as before, but this time Xwithout the `--dry-run' option. X X XFile: diff.info, Node: Creating and Removing, Next: Patching Time Stamps, Prev: Imperfect, Up: Merging with patch X XCreating and Removing Files X=========================== X X Sometimes when comparing two directories, a file may exist in one Xdirectory but not the other. If you give `diff' the `-N' or X`--new-file' option, or if you supply an old or new file that is named X`/dev/null' or is empty and is dated the Epoch (1970-01-01 00:00:00 XUTC), `diff' outputs a patch that adds or deletes the contents of this Xfile. When given such a patch, `patch' normally creates a new file or Xremoves the old file. However, when conforming to POSIX (*note patch Xand POSIX::), `patch' does not remove the old file, but leaves it empty. XThe `-E' or `--remove-empty-files' option causes `patch' to remove Xoutput files that are empty after applying a patch, even if the patch Xdoes not appear to be one that removed the file. X X If the patch appears to create a file that already exists, `patch' Xasks for confirmation before applying the patch. X X XFile: diff.info, Node: Patching Time Stamps, Next: Multiple Patches, Prev: Creating and Removing, Up: Merging with patch X XUpdating Time Stamps on Patched Files X===================================== X X When `patch' updates a file, it normally sets the file's Xlast-modified time stamp to the current time of day. If you are using X`patch' to track a software distribution, this can cause `make' to Xincorrectly conclude that a patched file is out of date. For example, Xif `syntax.c' depends on `syntax.y', and `patch' updates `syntax.c' and Xthen `syntax.y', then `syntax.c' will normally appear to be out of date Xwith respect to `syntax.y' even though its contents are actually up to Xdate. X X The `-Z' or `--set-utc' option causes `patch' to set a patched Xfile's modification and access times to the time stamps given in Xcontext diff headers. If the context diff headers do not specify a Xtime zone, they are assumed to use Coordinated Universal Time (UTC, Xoften known as GMT). X X The `-T' or `--set-time' option acts like `-Z' or `--set-utc', Xexcept that it assumes that the context diff headers' time stamps use Xlocal time instead of UTC. This option is not recommended, because Xpatches using local time cannot easily be used by people in other time Xzones, and because local time stamps are ambiguous when local clocks Xmove backwards during daylight-saving time adjustments. If the context Xdiff headers specify a time zone, this option is equivalent to `-Z' or X`--set-utc'. X X `patch' normally refrains from setting a file's time stamps if the Xfile's original last-modified time stamp does not match the time given Xin the diff header, of if the file's contents do not exactly match the Xpatch. However, if the `-f' or `--force' option is given, the file's Xtime stamps are set regardless. X X Due to the limitations of the current `diff' format, `patch' cannot Xupdate the times of files whose contents have not changed. Also, if Xyou set file time stamps to values other than the current time of day, Xyou should also remove (e.g., with `make clean') all files that depend Xon the patched files, so that later invocations of `make' do not get Xconfused by the patched files' times. X X XFile: diff.info, Node: Multiple Patches, Next: patch Directories, Prev: Patching Time Stamps, Up: Merging with patch X XMultiple Patches in a File X========================== X X If the patch file contains more than one patch, and if you do not Xspecify an input file on the command line, `patch' tries to apply each Xpatch as if they came from separate patch files. This means that it Xdetermines the name of the file to patch for each patch, and that it Xexamines the leading text before each patch for file names and Xprerequisite revision level (*note Making Patches::, for more on that Xtopic). X X `patch' uses the following rules to intuit a file name from the Xleading text before a patch. First, `patch' takes an ordered list of Xcandidate file names as follows: X X * If the header is that of a context diff, `patch' takes the old and X new file names in the header. A name is ignored if it does not X have enough slashes to satisfy the `-pNUM' or `--strip=NUM' X option. The name `/dev/null' is also ignored. X X * If there is an `Index:' line in the leading garbage and if either X the old and new names are both absent or if `patch' is conforming X to POSIX, `patch' takes the name in the `Index:' line. X X * For the purpose of the following rules, the candidate file names X are considered to be in the order (old, new, index), regardless of X the order that they appear in the header. X XThen `patch' selects a file name from the candidate list as follows: X X * If some of the named files exist, `patch' selects the first name X if conforming to POSIX, and the best name otherwise. X X * If `patch' is not ignoring RCS, ClearCase, and SCCS (*note X Revision Control::), and no named files exist but an RCS, X ClearCase, or SCCS master is found, `patch' selects the first X named file with an RCS, ClearCase, or SCCS master. X X * If no named files exist, no RCS, ClearCase, or SCCS master was X found, some names are given, `patch' is not conforming to POSIX, X and the patch appears to create a file, `patch' selects the best X name requiring the creation of the fewest directories. X X * If no file name results from the above heuristics, you are asked X for the name of the file to patch, and `patch' selects that name. X X To determine the "best" of a nonempty list of file names, `patch' Xfirst takes all the names with the fewest path name components; of Xthose, it then takes all the names with the shortest basename; of Xthose, it then takes all the shortest names; finally, it takes the Xfirst remaining name. X X *Note patch and POSIX::, to see whether `patch' is conforming to XPOSIX. X X XFile: diff.info, Node: patch Directories, Next: Backups, Prev: Multiple Patches, Up: Merging with patch X XApplying Patches in Other Directories X===================================== X X The `-d DIRECTORY' or `--directory=DIRECTORY' option to `patch' Xmakes directory DIRECTORY the current directory for interpreting both Xfile names in the patch file, and file names given as arguments to Xother options (such as `-B' and `-o'). For example, while in a mail Xreading program, you can patch a file in the `/usr/src/emacs' directory Xdirectly from a message containing the patch like this: X X | patch -d /usr/src/emacs X X Sometimes the file names given in a patch contain leading Xdirectories, but you keep your files in a directory different from the Xone given in the patch. In those cases, you can use the `-pNUMBER' or X`--strip=NUMBER' option to set the file name strip count to NUMBER. XThe strip count tells `patch' how many slashes, along with the directory Xnames between them, to strip from the front of file names. A sequence Xof one or more adjacent slashes is counted as a single slash. By Xdefault, `patch' strips off all leading directories, leaving just the Xbase file names. X X For example, suppose the file name in the patch file is X`/gnu/src/emacs/etc/NEWS'. Using `-p0' gives the entire file name Xunmodified, `-p1' gives `gnu/src/emacs/etc/NEWS' (no leading slash), X`-p4' gives `etc/NEWS', and not specifying `-p' at all gives `NEWS'. X X `patch' looks for each file (after any slashes have been stripped) Xin the current directory, or if you used the `-d DIRECTORY' option, in Xthat directory. X X XFile: diff.info, Node: Backups, Next: Backup Names, Prev: patch Directories, Up: Merging with patch X XBackup Files X============ X X Normally, `patch' creates a backup file if the patch does not Xexactly match the original input file, because in that case the Xoriginal data might not be recovered if you undo the patch with `patch X-R' (*note Reversed Patches::). However, when conforming to POSIX, X`patch' does not create backup files by default. *Note patch and XPOSIX::. X X The `-b' or `--backup' option causes `patch' to make a backup file Xregardless of whether the patch matches the original input. The X`--backup-if-mismatch' option causes `patch' to create backup files for Xmismatches files; this is the default when not conforming to POSIX. The X`--no-backup-if-mismatch' option causes `patch' to not create backup Xfiles, even for mismatched patches; this is the default when conforming Xto POSIX. X X When backing up a file that does not exist, an empty, unreadable Xbackup file is created as a placeholder to represent the nonexistent Xfile. X X XFile: diff.info, Node: Backup Names, Next: Reject Names, Prev: Backups, Up: Merging with patch X XBackup File Names X================= X X Normally, `patch' renames an original input file into a backup file Xby appending to its name the extension `.orig', or `~' if using `.orig' Xwould make the backup file name too long.(1) The `-z BACKUP-SUFFIX' or X`--suffix=BACKUP-SUFFIX' option causes `patch' to use BACKUP-SUFFIX as Xthe backup extension instead. X X Alternately, you can specify the extension for backup files with the X`SIMPLE_BACKUP_SUFFIX' environment variable, which the options override. X X `patch' can also create numbered backup files the way GNU Emacs Xdoes. With this method, instead of having a single backup of each file, X`patch' makes a new backup file name each time it patches a file. For Xexample, the backups of a file named `sink' would be called, Xsuccessively, `sink.~1~', `sink.~2~', `sink.~3~', etc. X X The `-V BACKUP-STYLE' or `--version-control=BACKUP-STYLE' option Xtakes as an argument a method for creating backup file names. You can Xalternately control the type of backups that `patch' makes with the X`PATCH_VERSION_CONTROL' environment variable, which the `-V' option Xoverrides. If `PATCH_VERSION_CONTROL' is not set, the X`VERSION_CONTROL' environment variable is used instead. Please note Xthat these options and variables control backup file names; they do not Xaffect the choice of revision control system (*note Revision Control::). X X The values of these environment variables and the argument to the X`-V' option are like the GNU Emacs `version-control' variable (*note XBackup Names: (emacs)Backup Names., for more information on backup Xversions in Emacs). They also recognize synonyms that are more Xdescriptive. The valid values are listed below; unique abbreviations Xare acceptable. X X`t' X`numbered' X Always make numbered backups. X X`nil' X`existing' X Make numbered backups of files that already have them, simple X backups of the others. This is the default. X X`never' X`simple' X Always make simple backups. X X You can also tell `patch' to prepend a prefix, such as a directory Xname, to produce backup file names. The `-B PREFIX' or X`--prefix=PREFIX' option makes backup files by prepending PREFIX to Xthem. The `-Y PREFIX' or `--basename-prefix=PREFIX' prepends PREFIX to Xthe last file name component of backup file names instead; for example, X`-Y ~' causes the backup name for `dir/file.c' to be `dir/~file.c'. If Xyou use either of these prefix options, the suffix-based options are Xignored. X X If you specify the output file with the `-o' option, that file is Xthe one that is backed up, not the input file. X X Options that affect the names of backup files do not affect whether Xbackups are made. For example, if you specify the X`--no-backup-if-mismatch' option, none of the options described in this Xsection have any affect, because no backups are made. X X ---------- Footnotes ---------- X X (1) A coding error in GNU `patch' version 2.5.4 causes it to always Xuse `~', but this should be fixed in the next release. X X XFile: diff.info, Node: Reject Names, Next: patch Messages, Prev: Backup Names, Up: Merging with patch X XReject File Names X================= X X The names for reject files (files containing patches that `patch' Xcould not find a place to apply) are normally the name of the output Xfile with `.rej' appended (or `#' if if using `.rej' would make the Xbackup file name too long). X X Alternatively, you can tell `patch' to place all of the rejected Xpatches in a single file. The `-r REJECT-FILE' or X`--reject-file=REJECT-FILE' option uses REJECT-FILE as the reject file Xname. X X XFile: diff.info, Node: patch Messages, Next: patch and POSIX, Prev: Reject Names, Up: Merging with patch X XMessages and Questions from `patch' X=================================== X X `patch' can produce a variety of messages, especially if it has Xtrouble decoding its input. In a few situations where it's not sure Xhow to proceed, `patch' normally prompts you for more information from Xthe keyboard. There are options to produce more or fewer messages, to Xhave it not ask for keyboard input, and to affect the way that file Xnames are quoted in messages. X X* Menu: X X* More or Fewer Messages:: Controlling the verbosity of `patch'. X* patch and Keyboard Input:: Inhibiting keyboard input. X* patch Quoting Style:: Quoting file names in diagnostics. X X `patch' exits with status 0 if all hunks are applied successfully, 1 Xif some hunks cannot be applied, and 2 if there is more serious trouble. XWhen applying a set of patches in a loop, you should check the exit Xstatus, so you don't apply a later patch to a partially patched file. X X XFile: diff.info, Node: More or Fewer Messages, Next: patch and Keyboard Input, Up: patch Messages X XControlling the Verbosity of `patch' X------------------------------------ X X You can cause `patch' to produce more messages by using the X`--verbose' option. For example, when you give this option, the Xmessage `Hmm...' indicates that `patch' is reading text in the patch Xfile, attempting to determine whether there is a patch in that text, Xand if so, what kind of patch it is. X X You can inhibit all terminal output from `patch', unless an error Xoccurs, by using the `-s', `--quiet', or `--silent' option. X X XFile: diff.info, Node: patch and Keyboard Input, Next: patch Quoting Style, Prev: More or Fewer Messages, Up: patch Messages X XInhibiting Keyboard Input X------------------------- X X There are two ways you can prevent `patch' from asking you any Xquestions. The `-f' or `--force' option assumes that you know what you Xare doing. It causes `patch' to do the following: X X * Skip patches that do not contain file names in their headers. X X * Patch files even though they have the wrong version for the X `Prereq:' line in the patch; X X * Assume that patches are not reversed even if they look like they X are. X XThe `-t' or `--batch' option is similar to `-f', in that it suppresses Xquestions, but it makes somewhat different assumptions: X X * Skip patches that do not contain file names in their headers (the X same as `-f'). X X * Skip patches for which the file has the wrong version for the X `Prereq:' line in the patch; X X * Assume that patches are reversed if they look like they are. X X XFile: diff.info, Node: patch Quoting Style, Prev: patch and Keyboard Input, Up: patch Messages X X`patch' Quoting Style X--------------------- X X When `patch' outputs a file name in a diagnostic message, it can Xformat the name in any of several ways. This can be useful to output Xfile names unambiguously, even if they contain punctuation or special Xcharacters like newlines. The `--quoting-style=WORD' option controls Xhow names are output. The WORD should be one of the following: X X`literal' X Output names as-is. X X`shell' X Quote names for the shell if they contain shell metacharacters or X would cause ambiguous output. X X`shell-always' X Quote names for the shell, even if they would normally not require X quoting. X X`c' X Quote names as for a C language string. X X`escape' X Quote as with `c' except omit the surrounding double-quote X characters. X X You can specify the default value of the `--quoting-style' option Xwith the environment variable `QUOTING_STYLE'. If that environment Xvariable is not set, the default value is `shell', but this default may Xchange in a future version of `patch'. X X XFile: diff.info, Node: patch and POSIX, Next: patch and Tradition, Prev: patch Messages, Up: Merging with patch X X`patch' and the POSIX Standard X============================== X X If you specify the `--posix' option, or set the `POSIXLY_CORRECT' Xenvironment variable, `patch' conforms more strictly to the POSIX Xstandard, as follows: X X * Take the first existing file from the list (old, new, index) when X intuiting file names from diff headers. *Note Multiple Patches::. X X * Do not remove files that are removed by a diff. *Note Creating X and Removing::. X X * Do not ask whether to get files from RCS, ClearCase, or SCCS. X *Note Revision Control::. X X * Require that all options precede the files in the command line. X X * Do not backup files, even when there is a mismatch. *Note X Backups::. X X X XFile: diff.info, Node: patch and Tradition, Prev: patch and POSIX, Up: Merging with patch X XGNU `patch' and Traditional `patch' X=================================== X X The current version of GNU `patch' normally follows the POSIX Xstandard. *Note patch and POSIX::, for the few exceptions to this Xgeneral rule. X X Unfortunately, POSIX redefined the behavior of `patch' in several Ximportant ways. You should be aware of the following differences if Xyou must interoperate with traditional `patch', or with GNU `patch' Xversion 2.1 and earlier. X X * In traditional `patch', the `-p' option's operand was optional, X and a bare `-p' was equivalent to `-p0'. The `-p' option now X requires an operand, and `-p 0' is now equivalent to `-p0'. For X maximum compatibility, use options like `-p0' and `-p1'. X X Also, traditional `patch' simply counted slashes when stripping X path prefixes; `patch' now counts pathname components. That is, a X sequence of one or more adjacent slashes now counts as a single X slash. For maximum portability, avoid sending patches containing X `//' in file names. X X * In traditional `patch', backups were enabled by default. This X behavior is now enabled with the `-b' or `--backup' option. X X Conversely, in POSIX `patch', backups are never made, even when X there is a mismatch. In GNU `patch', this behavior is enabled X with the `--no-backup-if-mismatch' option, or by conforming to X POSIX. X X The `-b SUFFIX' option of traditional `patch' is equivalent to the X `-b -z SUFFIX' options of GNU `patch'. X X * Traditional `patch' used a complicated (and incompletely X documented) method to intuit the name of the file to be patched X from the patch header. This method did not conform to POSIX, and X had a few gotchas. Now `patch' uses a different, equally X complicated (but better documented) method that is optionally X POSIX-conforming; we hope it has fewer gotchas. The two methods X are compatible if the file names in the context diff header and the X `Index:' line are all identical after prefix-stripping. Your X patch is normally compatible if each header's file names all X contain the same number of slashes. X X * When traditional `patch' asked the user a question, it sent the X question to standard error and looked for an answer from the first X file in the following list that was a terminal: standard error, X standard output, `/dev/tty', and standard input. Now `patch' X sends questions to standard output and gets answers from X `/dev/tty'. Defaults for some answers have been changed so that X `patch' never goes into an infinite loop when using default X answers. X X * Traditional `patch' exited with a status value that counted the X number of bad hunks, or with status 1 if there was real trouble. X Now `patch' exits with status 1 if some hunks failed, or with 2 if X there was real trouble. X X * Limit yourself to the following options when sending instructions X meant to be executed by anyone running GNU `patch', traditional X `patch', or a `patch' that conforms to POSIX. Spaces are X significant in the following list, and operands are required. X X `-c' X `-d DIR' X `-D DEFINE' X `-e' X `-l' X `-n' X `-N' X `-o OUTFILE' X `-pNUM' X `-R' X `-r REJECTFILE' X X X XFile: diff.info, Node: Making Patches, Next: Invoking cmp, Prev: Merging with patch, Up: Top X XTips for Making and Using Patches X********************************* X X Use some common sense when making and using patches. For example, Xwhen sending bug fixes to a program's maintainer, send several small Xpatches, one per independent subject, instead of one large, Xharder-to-digest patch that covers all the subjects. X X Here are some other things you should keep in mind if you are going Xto distribute patches for updating a software package. X X* Menu: X X* Tips for Patch Producers:: Advice for making patches. X* Tips for Patch Consumers:: Advice for using patches. X* Avoiding Common Mistakes:: Avoiding common mistakes when using `patch'. X* Generating Smaller Patches:: How to generate smaller patches. X X XFile: diff.info, Node: Tips for Patch Producers, Next: Tips for Patch Consumers, Up: Making Patches X XTips for Patch Producers X======================== X X To create a patch that changes an older version of a package into a Xnewer version, first make a copy of the older and newer versions in Xadjacent subdirectories. It is common to do that by unpacking `tar' Xarchives of the two versions. X X To generate the patch, use the command `diff -Naur OLD NEW' where XOLD and NEW identify the old and new directories. The names OLD and XNEW should not contain any slashes. The `-N' option lets the patch Xcreate and remove files; `-a' lets the patch update non-text files; `-u' Xgenerates useful time stamps and enough context; and `-r' lets the Xpatch update subdirectories. Here is an example command, using Bourne Xshell syntax: X X diff -Naur gcc-3.0.3 gcc-3.0.4 X X Tell your recipients how to apply the patches. This should include Xwhich working directory to use, and which `patch' options to use; the Xoption `-p1' is recommended. Test your procedure by pretending to be a Xrecipient and applying your patches to a copy of the original files. X X *Note Avoiding Common Mistakes::, for how to avoid common mistakes Xwhen generating a patch. X X XFile: diff.info, Node: Tips for Patch Consumers, Next: Avoiding Common Mistakes, Prev: Tips for Patch Producers, Up: Making Patches X XTips for Patch Consumers X======================== X X A patch producer should tell recipients how to apply the patches, so Xthe first rule of thumb for a patch consumer is to follow the Xinstructions supplied with the patch. X X GNU `diff' can analyze files with arbitrarily long lines and files Xthat end in incomplete lines. However, older versions of `patch' Xcannot patch such files. If you are having trouble applying such Xpatches, try upgrading to a recent version of GNU `patch'. X X XFile: diff.info, Node: Avoiding Common Mistakes, Next: Generating Smaller Patches, Prev: Tips for Patch Consumers, Up: Making Patches X XAvoiding Common Mistakes X======================== X X When producing a patch for multiple files, apply `diff' to Xdirectories whose names do not have slashes. This reduces confusion Xwhen the patch consumer specifies the `-pNUMBER' option, since this Xoption can have surprising results when the old and new file names have Xdifferent numbers of slashes. For example, do not send a patch with a Xheader that looks like this: X X diff -Naur v2.0.29/prog/README prog/README X --- v2.0.29/prog/README 2002-03-10 23:30:39.942229878 -0800 X +++ prog/README 2002-03-17 20:49:32.442260588 -0800 X Xbecause the two file names have different numbers of slashes, and Xdifferent versions of `patch' interpret the file names differently. To Xavoid confusion, send output that looks like this instead: X X diff -Naur v2.0.29/prog/README v2.0.30/prog/README X --- v2.0.29/prog/README 2002-03-10 23:30:39.942229878 -0800 X +++ v2.0.30/prog/README 2002-03-17 20:49:32.442260588 -0800 X X Make sure you have specified the file names correctly, either in a Xcontext diff header or with an `Index:' line. Take care to not send out Xreversed patches, since these make people wonder whether they have Xalready applied the patch. X X Avoid sending patches that compare backup file names like X`README.orig' or `README~', since this might confuse `patch' into Xpatching a backup file instead of the real file. Instead, send patches Xthat compare the same base file names in different directories, e.g. X`old/README' and `new/README'. X X To save people from partially applying a patch before other patches Xthat should have gone before it, you can make the first patch in the Xpatch file update a file with a name like `patchlevel.h' or X`version.c', which contains a patch level or version number. If the Xinput file contains the wrong version number, `patch' will complain Ximmediately. X X An even clearer way to prevent this problem is to put a `Prereq:' Xline before the patch. If the leading text in the patch file contains a Xline that starts with `Prereq:', `patch' takes the next word from that Xline (normally a version number) and checks whether the next input file Xcontains that word, preceded and followed by either white space or a Xnewline. If not, `patch' prompts you for confirmation before Xproceeding. This makes it difficult to accidentally apply patches in Xthe wrong order. X X XFile: diff.info, Node: Generating Smaller Patches, Prev: Avoiding Common Mistakes, Up: Making Patches X XGenerating Smaller Patches X========================== X X The simplest way to generate a patch is to use `diff -Naur' (*note XTips for Patch Producers::), but you might be able to reduce the size Xof the patch by renaming or removing some files before making the Xpatch. If the older version of the package contains any files that the Xnewer version does not, or if any files have been renamed between the Xtwo versions, make a list of `rm' and `mv' commands for the user to Xexecute in the old version directory before applying the patch. Then Xrun those commands yourself in the scratch directory. X X If there are any files that you don't need to include in the patch Xbecause they can easily be rebuilt from other files (for example, X`TAGS' and output from `yacc' and `makeinfo'), exclude them from the Xpatch by giving `diff' the `-x PATTERN' option (*note Comparing XDirectories::). If you want your patch to modify a derived file Xbecause your recipients lack tools to build it, make sure that the Xpatch for the derived file follows any patches for files that it Xdepends on, so that the recipients' time stamps will not confuse `make'. X X Now you can create the patch using `diff -Naur'. Make sure to Xspecify the scratch directory first and the newer directory second. X X Add to the top of the patch a note telling the user any `rm' and X`mv' commands to run before applying the patch. Then you can remove Xthe scratch directory. X X You can also shrink the patch size by using fewer lines of context, Xbut bear in mind that `patch' typically needs at least two lines for Xproper operation when patches do not exactly match the input files. X X XFile: diff.info, Node: Invoking cmp, Next: Invoking diff, Prev: Making Patches, Up: Top X XInvoking `cmp' X************** X X The `cmp' command compares two files, and if they differ, tells the Xfirst byte and line number where they differ. Bytes and lines are Xnumbered starting with 1. The arguments of `cmp' are as follows: X X cmp OPTIONS... FROM-FILE [TO-FILE [FROM-SKIP [TO-SKIP]]] X X The file name `-' is always the standard input. `cmp' also uses the Xstandard input if one file name is omitted. The FROM-SKIP and TO-SKIP Xoperands specify how many bytes to ignore at the start of each file; Xthey are equivalent to the `--ignore-initial=FROM-SKIP:TO-SKIP' option. X X An exit status of 0 means no differences were found, 1 means some Xdifferences were found, and 2 means trouble. X X* Menu: X X* cmp Options:: Summary of options to `cmp'. X X XFile: diff.info, Node: cmp Options, Up: Invoking cmp X XOptions to `cmp' X================ X X Below is a summary of all of the options that GNU `cmp' accepts. XMost options have two equivalent names, one of which is a single letter Xpreceded by `-', and the other of which is a long name preceded by X`--'. Multiple single letter options (unless they take an argument) Xcan be combined into a single command line word: `-bl' is equivalent to X`-b -l'. X X`-b' X`--print-bytes' X Print the differing bytes. Display control bytes as a `^' X followed by a letter of the alphabet and precede bytes that have X the high bit set with `M-' (which stands for "meta"). X X`--help' X Output a summary of usage and then exit. X X`-i SKIP' X`--ignore-initial=SKIP' X Ignore any differences in the first SKIP bytes of the input files. X Treat files with fewer than SKIP bytes as if they are empty. If X SKIP is of the form `FROM-SKIP:TO-SKIP', skip the first FROM-SKIP X bytes of the first input file and the first TO-SKIP bytes of the X second. X X`-l' X`--verbose' X Print the (decimal) byte numbers and (octal) values of all X differing bytes. X X`-n COUNT' X`--bytes=COUNT' X Compare at most COUNT input bytes. X X`-s' X`--quiet' X`--silent' X Do not print anything; only return an exit status indicating X whether the files differ. X X`-v' X`--version' X Output version information and then exit. X X In the above table, operands that are byte counts are normally Xdecimal, but may be preceded by `0' for octal and `0x' for hexadecimal. X X A byte count can be followed by a suffix to specify a multiple of Xthat count; in this case an omitted integer is understood to be 1. A Xbare size letter, or one followed by `iB', specifies a multiple using Xpowers of 1024. A size letter followed by `B' specifies powers of 1000 Xinstead. For example, `-n 4M' and `-n 4MiB' are equivalent to `-n X4194304', whereas `-n 4MB' is equivalent to `-n 4000000'. This Xnotation is upward compatible with the SI prefixes X(http://www.bipm.fr/enus/3_SI/si-prefixes.html) for decimal multiples Xand with the IEC 60027-2 prefixes for binary multiples X(http://physics.nist.gov/cuu/Units/binary.html). X X The following suffixes are defined. Large sizes like `1Y' may be Xrejected by your computer due to limitations of its arithmetic. X X`kB' X kilobyte: 10^3 = 1000. X X`k' X`K' X`KiB' X kibibyte: 2^10 = 1024. `K' is special: the SI prefix is `k' and X the IEC 60027-2 prefix is `Ki', but tradition and POSIX use `k' to X mean `KiB'. X X`MB' X megabyte: 10^6 = 1,000,000. X X`M' X`MiB' X mebibyte: 2^20 = 1,048,576. X X`GB' X gigabyte: 10^9 = 1,000,000,000. X X`G' X`GiB' X gibibyte: 2^30 = 1,073,741,824. X X`TB' X terabyte: 10^12 = 1,000,000,000,000. X X`T' X`TiB' X tebibyte: 2^40 = 1,099,511,627,776. X X`PB' X petabyte: 10^15 = 1,000,000,000,000,000. X X`P' X`PiB' X pebibyte: 2^50 = 1,125,899,906,842,624. X X`EB' X exabyte: 10^18 = 1,000,000,000,000,000,000. X X`E' X`EiB' X exbibyte: 2^60 = 1,152,921,504,606,846,976. X X`ZB' X zettabyte: 10^21 = 1,000,000,000,000,000,000,000 X X`Z' X`ZiB' X 2^70 = 1,180,591,620,717,411,303,424. (`Zi' is a GNU extension to X IEC 60027-2.) X X`YB' X yottabyte: 10^24 = 1,000,000,000,000,000,000,000,000. X X`Y' X`YiB' X 2^80 = 1,208,925,819,614,629,174,706,176. (`Yi' is a GNU X extension to IEC 60027-2.) X X XFile: diff.info, Node: Invoking diff, Next: Invoking diff3, Prev: Invoking cmp, Up: Top X XInvoking `diff' X*************** X X The format for running the `diff' command is: X X diff OPTIONS... FILES... X X In the simplest case, two file names FROM-FILE and TO-FILE are Xgiven, and `diff' compares the contents of FROM-FILE and TO-FILE. A Xfile name of `-' stands for text read from the standard input. As a Xspecial case, `diff - -' compares a copy of standard input to itself. X X If one file is a directory and the other is not, `diff' compares the Xfile in the directory whose name is that of the non-directory. The Xnon-directory file must not be `-'. X X If two file names are given and both are directories, `diff' Xcompares corresponding files in both directories, in alphabetical Xorder; this comparison is not recursive unless the `-r' or X`--recursive' option is given. `diff' never compares the actual Xcontents of a directory as if it were a file. The file that is fully Xspecified may not be standard input, because standard input is nameless Xand the notion of "file with the same name" does not apply. X X If the `--from-file=FILE' option is given, the number of file names Xis arbitrary, and FILE is compared to each named file. Similarly, if Xthe `--to-file=FILE' option is given, each named file is compared to XFILE. X X `diff' options begin with `-', so normally file names may not begin Xwith `-'. However, `--' as an argument by itself treats the remaining Xarguments as file names even if they begin with `-'. X X An exit status of 0 means no differences were found, 1 means some Xdifferences were found, and 2 means trouble. X X* Menu: X X* diff Options:: Summary of options to `diff'. X X XFile: diff.info, Node: diff Options, Up: Invoking diff X XOptions to `diff' X================= X X Below is a summary of all of the options that GNU `diff' accepts. XMost options have two equivalent names, one of which is a single letter Xpreceded by `-', and the other of which is a long name preceded by X`--'. Multiple single letter options (unless they take an argument) Xcan be combined into a single command line word: `-ac' is equivalent to X`-a -c'. Long named options can be abbreviated to any unique prefix of Xtheir name. Brackets ([ and ]) indicate that an option takes an Xoptional argument. X X`-a' X`--text' X Treat all files as text and compare them line-by-line, even if they X do not seem to be text. *Note Binary::. X X`-b' X`--ignore-space-change' X Ignore changes in amount of white space. *Note White Space::. X X`-B' X`--ignore-blank-lines' X Ignore changes that just insert or delete blank lines. *Note X Blank Lines::. X X`--binary' X Read and write data in binary mode. *Note Binary::. X X`-c' X Use the context output format, showing three lines of context. X *Note Context Format::. X X`-C LINES' X`--context[=LINES]' X Use the context output format, showing LINES (an integer) lines of X context, or three if LINES is not given. *Note Context Format::. X For proper operation, `patch' typically needs at least two lines of X context. X X On older systems, `diff' supports an obsolete option `-LINES' that X has effect when combined with `-c' or `-p'. POSIX 1003.1-2001 X (*note Standards conformance::) does not allow this; use `-C LINES' X instead. X X`--changed-group-format=FORMAT' X Use FORMAT to output a line group containing differing lines from X both files in if-then-else format. *Note Line Group Formats::. X X`-d' X`--minimal' X Change the algorithm perhaps find a smaller set of changes. This X makes `diff' slower (sometimes much slower). *Note diff X Performance::. X X`-D NAME' X`--ifdef=NAME' X Make merged `#ifdef' format output, conditional on the preprocessor X macro NAME. *Note If-then-else::. X X`-e' X`--ed' X Make output that is a valid `ed' script. *Note ed Scripts::. X X`-E' X`--ignore-tab-expansion' X Ignore changes due to tab expansion. *Note White Space::. X X`-f' X`--forward-ed' X Make output that looks vaguely like an `ed' script but has changes X in the order they appear in the file. *Note Forward ed::. X X`-F REGEXP' X`--show-function-line=REGEXP' X In context and unified format, for each hunk of differences, show X some of the last preceding line that matches REGEXP. *Note X Specified Headings::. X X`--from-file=FILE' X Compare FILE to each operand; FILE may be a directory. X X`--help' X Output a summary of usage and then exit. X X`--horizon-lines=LINES' X Do not discard the last LINES lines of the common prefix and the X first LINES lines of the common suffix. *Note diff Performance::. X X`-i' X`--ignore-case' X Ignore changes in case; consider upper- and lower-case letters X equivalent. *Note Case Folding::. X X`-I REGEXP' X`--ignore-matching-lines=REGEXP' X Ignore changes that just insert or delete lines that match REGEXP. X *Note Specified Folding::. X X`--ignore-file-name-case' X Ignore case when comparing file names during recursive comparison. X *Note Comparing Directories::. X X`-l' X`--paginate' X Pass the output through `pr' to paginate it. *Note Pagination::. X X`--label=LABEL' X Use LABEL instead of the file name in the context format (*note X Context Format::) and unified format (*note Unified Format::) X headers. *Note RCS::. X X`--left-column' X Print only the left column of two common lines in side by side X format. *Note Side by Side Format::. X X`--line-format=FORMAT' X Use FORMAT to output all input lines in if-then-else format. X *Note Line Formats::. X X`-n' X`--rcs' X Output RCS-format diffs; like `-f' except that each command X specifies the number of lines affected. *Note RCS::. X X`-N' X`--new-file' X In directory comparison, if a file is found in only one directory, X treat it as present but empty in the other directory. *Note X Comparing Directories::. X X`--new-group-format=FORMAT' X Use FORMAT to output a group of lines taken from just the second X file in if-then-else format. *Note Line Group Formats::. X X`--new-line-format=FORMAT' X Use FORMAT to output a line taken from just the second file in X if-then-else format. *Note Line Formats::. X X`--old-group-format=FORMAT' X Use FORMAT to output a group of lines taken from just the first X file in if-then-else format. *Note Line Group Formats::. X X`--old-line-format=FORMAT' X Use FORMAT to output a line taken from just the first file in X if-then-else format. *Note Line Formats::. X X`-p' X`--show-c-function' X Show which C function each change is in. *Note C Function X Headings::. X X`-q' X`--brief' X Report only whether the files differ, not the details of the X differences. *Note Brief::. X X`-r' X`--recursive' X When comparing directories, recursively compare any subdirectories X found. *Note Comparing Directories::. X X`-s' X`--report-identical-files' X Report when two files are the same. *Note Comparing Directories::. X X`-S FILE' X`--starting-file=FILE' X When comparing directories, start with the file FILE. This is X used for resuming an aborted comparison. *Note Comparing X Directories::. X X`--speed-large-files' X Use heuristics to speed handling of large files that have numerous X scattered small changes. *Note diff Performance::. X X`--strip-trailing-cr' X Strip any trailing carriage return at the end of an input line. X *Note Binary::. X X`--suppress-common-lines' X Do not print common lines in side by side format. *Note Side by X Side Format::. X X`-t' X`--expand-tabs' X Expand tabs to spaces in the output, to preserve the alignment of X tabs in the input files. *Note Tabs::. X X`-T' X`--initial-tab' X Output a tab rather than a space before the text of a line in X normal or context format. This causes the alignment of tabs in X the line to look normal. *Note Tabs::. X X`--to-file=FILE' X Compare each operand to FILE; FILE may be a directory. X X`-u' X Use the unified output format, showing three lines of context. X *Note Unified Format::. X X`--unchanged-group-format=FORMAT' X Use FORMAT to output a group of common lines taken from both files X in if-then-else format. *Note Line Group Formats::. X X`--unchanged-line-format=FORMAT' X Use FORMAT to output a line common to both files in if-then-else X format. *Note Line Formats::. X X`--unidirectional-new-file' X When comparing directories, if a file appears only in the second X directory of the two, treat it as present but empty in the other. X *Note Comparing Directories::. X X`-U LINES' X`--unified[=LINES]' X Use the unified output format, showing LINES (an integer) lines of X context, or three if LINES is not given. *Note Unified Format::. X For proper operation, `patch' typically needs at least two lines of X context. X X On older systems, `diff' supports an obsolete option `-LINES' that X has effect when combined with `-u'. POSIX 1003.1-2001 (*note X Standards conformance::) does not allow this; use `-U LINES' X instead. X X`-v' X`--version' X Output version information and then exit. X X`-w' X`--ignore-all-space' X Ignore white space when comparing lines. *Note White Space::. X X`-W COLUMNS' X`--width=COLUMNS' X Output at most COLUMNS (default 130) print columns per line in X side by side format. *Note Side by Side Format::. X X`-x PATTERN' X`--exclude=PATTERN' X When comparing directories, ignore files and subdirectories whose X basenames match PATTERN. *Note Comparing Directories::. X X`-X FILE' X`--exclude-from=FILE' X When comparing directories, ignore files and subdirectories whose X basenames match any pattern contained in FILE. *Note Comparing X Directories::. X X`-y' X`--side-by-side' X Use the side by side output format. *Note Side by Side Format::. X X XFile: diff.info, Node: Invoking diff3, Next: Invoking patch, Prev: Invoking diff, Up: Top X XInvoking `diff3' X**************** X X The `diff3' command compares three files and outputs descriptions of Xtheir differences. Its arguments are as follows: X X diff3 OPTIONS... MINE OLDER YOURS X X The files to compare are MINE, OLDER, and YOURS. At most one of Xthese three file names may be `-', which tells `diff3' to read the Xstandard input for that file. X X An exit status of 0 means `diff3' was successful, 1 means some Xconflicts were found, and 2 means trouble. X X* Menu: X X* diff3 Options:: Summary of options to `diff3'. X X XFile: diff.info, Node: diff3 Options, Up: Invoking diff3 X XOptions to `diff3' X================== X X Below is a summary of all of the options that GNU `diff3' accepts. XMultiple single letter options (unless they take an argument) can be Xcombined into a single command line argument. X X`-a' X`--text' X Treat all files as text and compare them line-by-line, even if they X do not appear to be text. *Note Binary::. X X`-A' X`--show-all' X Incorporate all unmerged changes from OLDER to YOURS into MINE, X surrounding conflicts with bracket lines. *Note Marking X Conflicts::. X X`--diff-program=PROGRAM' X Use the compatible comparison program PROGRAM to compare files X instead of `diff'. X X`-e' X`--ed' X Generate an `ed' script that incorporates all the changes from X OLDER to YOURS into MINE. *Note Which Changes::. X X`-E' X`--show-overlap' X Like `-e', except bracket lines from overlapping changes' first X and third files. *Note Marking Conflicts::. With `-E', an X overlapping change looks like this: X X <<<<<<< MINE X lines from MINE X ======= X lines from YOURS X >>>>>>> YOURS X X`--help' X Output a summary of usage and then exit. X X`-i' X Generate `w' and `q' commands at the end of the `ed' script for X System V compatibility. This option must be combined with one of X the `-AeExX3' options, and may not be combined with `-m'. *Note X Saving the Changed File::. X X`-L LABEL' X`--label=LABEL' X Use the label LABEL for the brackets output by the `-A', `-E' and X `-X' options. This option may be given up to three times, one for X each input file. The default labels are the names of the input X files. Thus `diff3 -L X -L Y -L Z -m A B C' acts like `diff3 -m A X B C', except that the output looks like it came from files named X `X', `Y' and `Z' rather than from files named `A', `B' and `C'. X *Note Marking Conflicts::. X X`-m' X`--merge' X Apply the edit script to the first file and send the result to X standard output. Unlike piping the output from `diff3' to `ed', X this works even for binary files and incomplete lines. `-A' is X assumed if no edit script option is specified. *Note Bypassing X ed::. X X`-T' X`--initial-tab' X Output a tab rather than two spaces before the text of a line in X normal format. This causes the alignment of tabs in the line to X look normal. *Note Tabs::. X X`-v' X`--version' X Output version information and then exit. X X`-x' X`--overlap-only' X Like `-e', except output only the overlapping changes. *Note X Which Changes::. X X`-X' X Like `-E', except output only the overlapping changes. In other X words, like `-x', except bracket changes as in `-E'. *Note X Marking Conflicts::. X X`-3' X`--easy-only' X Like `-e', except output only the nonoverlapping changes. *Note X Which Changes::. X X XFile: diff.info, Node: Invoking patch, Next: Invoking sdiff, Prev: Invoking diff3, Up: Top X XInvoking `patch' X**************** X X Normally `patch' is invoked like this: X X patch Xto coordinate with other volunteers. X X* Menu: X X* Shortcomings:: Suggested projects for improvements. X* Bugs:: Reporting bugs. X X XFile: diff.info, Node: Shortcomings, Next: Bugs, Up: Projects X XSuggested Projects for Improving GNU `diff' and `patch' X======================================================= X X One should be able to use GNU `diff' to generate a patch from any Xpair of directory trees, and given the patch and a copy of one such Xtree, use `patch' to generate a faithful copy of the other. XUnfortunately, some changes to directory trees cannot be expressed using Xcurrent patch formats; also, `patch' does not handle some of the Xexisting formats. These shortcomings motivate the following suggested Xprojects. X X* Menu: X X* Internationalization:: Handling multibyte and varying-width characters. X* Changing Structure:: Handling changes to the directory structure. X* Special Files:: Handling symbolic links, device special files, etc. X* Unusual File Names:: Handling file names that contain unusual characters. X* Time Stamp Order:: Outputting diffs in time stamp order. X* Ignoring Changes:: Ignoring certain changes while showing others. X* Speedups:: Improving performance. X X XFile: diff.info, Node: Internationalization, Next: Changing Structure, Up: Shortcomings X XHandling Multibyte and Varying-Width Characters X----------------------------------------------- X X `diff', `diff3' and `sdiff' treat each line of input as a string of Xunibyte characters. This can mishandle multibyte characters in some Xcases. For example, when asked to ignore spaces, `diff' does not Xproperly ignore a multibyte space character. X X Also, `diff' currently assumes that each byte is one column wide, Xand this assumption is incorrect in some locales, e.g., locales that Xuse UTF-8 encoding. This causes problems with the `-y' or X`--side-by-side' option of `diff'. X X These problems need to be fixed without unduly affecting the Xperformance of the utilities in unibyte environments. X X The IBM GNU/Linux Technology Center Internationalization Team has Xproposed some patches to support internationalized `diff' X`http://oss.software.ibm.com/developer/opensource/linux/patches/i18n/diffutils-2.7.2-i18n-0.1.patch.gz'. XUnfortunately, these patches are incomplete and are to an older version Xof `diff', so more work needs to be done in this area. X X XFile: diff.info, Node: Changing Structure, Next: Special Files, Prev: Internationalization, Up: Shortcomings X XHandling Changes to the Directory Structure X------------------------------------------- X X `diff' and `patch' do not handle some changes to directory Xstructure. For example, suppose one directory tree contains a directory Xnamed `D' with some subsidiary files, and another contains a file with Xthe same name `D'. `diff -r' does not output enough information for X`patch' to transform the directory subtree into the file. X X There should be a way to specify that a file has been removed without Xhaving to include its entire contents in the patch file. There should Xalso be a way to tell `patch' that a file was renamed, even if there is Xno way for `diff' to generate such information. There should be a way Xto tell `patch' that a file's time stamp has changed, even if its Xcontents have not changed. X X These problems can be fixed by extending the `diff' output format to Xrepresent changes in directory structure, and extending `patch' to Xunderstand these extensions. X X XFile: diff.info, Node: Special Files, Next: Unusual File Names, Prev: Changing Structure, Up: Shortcomings X XFiles that are Neither Directories Nor Regular Files X---------------------------------------------------- X X Some files are neither directories nor regular files: they are Xunusual files like symbolic links, device special files, named pipes, Xand sockets. Currently, `diff' treats symbolic links like regular Xfiles; it treats other special files like regular files if they are Xspecified at the top level, but simply reports their presence when Xcomparing directories. This means that `patch' cannot represent changes Xto such files. For example, if you change which file a symbolic link Xpoints to, `diff' outputs the difference between the two files, instead Xof the change to the symbolic link. X X `diff' should optionally report changes to special files specially, Xand `patch' should be extended to understand these extensions. X X XFile: diff.info, Node: Unusual File Names, Next: Time Stamp Order, Prev: Special Files, Up: Shortcomings X XFile Names that Contain Unusual Characters X------------------------------------------ X X When a file name contains an unusual character like a newline or Xwhite space, `diff -r' generates a patch that `patch' cannot parse. XThe problem is with format of `diff' output, not just with `patch', Xbecause with odd enough file names one can cause `diff' to generate a Xpatch that is syntactically correct but patches the wrong files. The Xformat of `diff' output should be extended to handle all possible file Xnames. X X XFile: diff.info, Node: Time Stamp Order, Next: Ignoring Changes, Prev: Unusual File Names, Up: Shortcomings X XOutputting Diffs in Time Stamp Order X------------------------------------ X X Applying `patch' to a multiple-file diff can result in files whose Xtime stamps are out of order. GNU `patch' has options to restore the Xtime stamps of the updated files (*note Patching Time Stamps::), but Xsometimes it is useful to generate a patch that works even if the Xrecipient does not have GNU patch, or does not use these options. One Xway to do this would be to implement a `diff' option to output diffs in Xtime stamp order. X X XFile: diff.info, Node: Ignoring Changes, Next: Speedups, Prev: Time Stamp Order, Up: Shortcomings X XIgnoring Certain Changes X------------------------ X X It would be nice to have a feature for specifying two strings, one in XFROM-FILE and one in TO-FILE, which should be considered to match. XThus, if the two strings are `foo' and `bar', then if two lines differ Xonly in that `foo' in file 1 corresponds to `bar' in file 2, the lines Xare treated as identical. X X It is not clear how general this feature can or should be, or what Xsyntax should be used for it. X X A partial substitute is to filter one or both files before comparing, Xe.g.: X X sed 's/foo/bar/g' file1 | diff - file2 X X However, this outputs the filtered text, not the original. X X XFile: diff.info, Node: Speedups, Prev: Ignoring Changes, Up: Shortcomings X XImproving Performance X--------------------- X X When comparing two large directory structures, one of which was Xoriginally copied from the other with time stamps preserved (e.g., with X`cp -pR'), it would greatly improve performance if an option told X`diff' to assume that two files with the same size and time stamps have Xthe same content. *Note diff Performance::. X X XFile: diff.info, Node: Bugs, Prev: Shortcomings, Up: Projects X XReporting Bugs X============== X X If you think you have found a bug in GNU `cmp', `diff', `diff3', or X`sdiff', please report it by electronic mail to the GNU utilities bug Xreport mailing list X(http://mail.gnu.org/mailman/listinfo/bug-gnu-utils) X. Please send bug reports for GNU `patch' to X. Send as precise a description of the problem as Xyou can, including the output of the `--version' option and sample Xinput files that produce the bug, if applicable. If you have a Xnontrivial fix for the bug, please send it as well. If you have a Xpatch, please send it too. It may simplify the maintainer's job if the Xpatch is relative to a recent test release, which you can find in the Xdirectory `ftp://alpha.gnu.org/gnu/diffutils/'. X X XFile: diff.info, Node: Copying This Manual, Next: Index, Prev: Projects, Up: Top X XCopying This Manual X******************* X X* Menu: X X* GNU Free Documentation License:: License for copying this manual. X X XFile: diff.info, Node: GNU Free Documentation License, Up: Copying This Manual X XGNU Free Documentation License X============================== X X Version 1.1, March 2000 X Copyright (C) 2000 Free Software Foundation, Inc. X 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA X X Everyone is permitted to copy and distribute verbatim copies X of this license document, but changing it is not allowed. X X 0. PREAMBLE X X The purpose of this License is to make a manual, textbook, or other X written document "free" in the sense of freedom: to assure everyone X the effective freedom to copy and redistribute it, with or without X modifying it, either commercially or noncommercially. Secondarily, X this License preserves for the author and publisher a way to get X credit for their work, while not being considered responsible for X modifications made by others. X X This License is a kind of "copyleft", which means that derivative X works of the document must themselves be free in the same sense. X It complements the GNU General Public License, which is a copyleft X license designed for free software. X X We have designed this License in order to use it for manuals for X free software, because free software needs free documentation: a X free program should come with manuals providing the same freedoms X that the software does. But this License is not limited to X software manuals; it can be used for any textual work, regardless X of subject matter or whether it is published as a printed book. X We recommend this License principally for works whose purpose is X instruction or reference. X X 1. APPLICABILITY AND DEFINITIONS X X This License applies to any manual or other work that contains a X notice placed by the copyright holder saying it can be distributed X under the terms of this License. The "Document", below, refers to X any such manual or work. Any member of the public is a licensee, X and is addressed as "you". X X A "Modified Version" of the Document means any work containing the X Document or a portion of it, either copied verbatim, or with X modifications and/or translated into another language. X X A "Secondary Section" is a named appendix or a front-matter X section of the Document that deals exclusively with the X relationship of the publishers or authors of the Document to the X Document's overall subject (or to related matters) and contains X nothing that could fall directly within that overall subject. X (For example, if the Document is in part a textbook of X mathematics, a Secondary Section may not explain any mathematics.) X The relationship could be a matter of historical connection with X the subject or with related matters, or of legal, commercial, X philosophical, ethical or political position regarding them. X X The "Invariant Sections" are certain Secondary Sections whose X titles are designated, as being those of Invariant Sections, in X the notice that says that the Document is released under this X License. X X The "Cover Texts" are certain short passages of text that are X listed, as Front-Cover Texts or Back-Cover Texts, in the notice X that says that the Document is released under this License. X X A "Transparent" copy of the Document means a machine-readable copy, X represented in a format whose specification is available to the X general public, whose contents can be viewed and edited directly X and straightforwardly with generic text editors or (for images X composed of pixels) generic paint programs or (for drawings) some X widely available drawing editor, and that is suitable for input to X text formatters or for automatic translation to a variety of X formats suitable for input to text formatters. A copy made in an X otherwise Transparent file format whose markup has been designed X to thwart or discourage subsequent modification by readers is not X Transparent. A copy that is not "Transparent" is called "Opaque". X X Examples of suitable formats for Transparent copies include plain X ASCII without markup, Texinfo input format, LaTeX input format, X SGML or XML using a publicly available DTD, and X standard-conforming simple HTML designed for human modification. X Opaque formats include PostScript, PDF, proprietary formats that X can be read and edited only by proprietary word processors, SGML X or XML for which the DTD and/or processing tools are not generally X available, and the machine-generated HTML produced by some word X processors for output purposes only. X X The "Title Page" means, for a printed book, the title page itself, X plus such following pages as are needed to hold, legibly, the X material this License requires to appear in the title page. For X works in formats which do not have any title page as such, "Title X Page" means the text near the most prominent appearance of the X work's title, preceding the beginning of the body of the text. X X 2. VERBATIM COPYING X X You may copy and distribute the Document in any medium, either X commercially or noncommercially, provided that this License, the X copyright notices, and the license notice saying this License X applies to the Document are reproduced in all copies, and that you X add no other conditions whatsoever to those of this License. You X may not use technical measures to obstruct or control the reading X or further copying of the copies you make or distribute. However, X you may accept compensation in exchange for copies. If you X distribute a large enough number of copies you must also follow X the conditions in section 3. X X You may also lend copies, under the same conditions stated above, X and you may publicly display copies. X X 3. COPYING IN QUANTITY X X If you publish printed copies of the Document numbering more than X 100, and the Document's license notice requires Cover Texts, you X must enclose the copies in covers that carry, clearly and legibly, X all these Cover Texts: Front-Cover Texts on the front cover, and X Back-Cover Texts on the back cover. Both covers must also clearly X and legibly identify you as the publisher of these copies. The X front cover must present the full title with all words of the X title equally prominent and visible. You may add other material X on the covers in addition. Copying with changes limited to the X covers, as long as they preserve the title of the Document and X satisfy these conditions, can be treated as verbatim copying in X other respects. X X If the required texts for either cover are too voluminous to fit X legibly, you should put the first ones listed (as many as fit X reasonably) on the actual cover, and continue the rest onto X adjacent pages. X X If you publish or distribute Opaque copies of the Document X numbering more than 100, you must either include a X machine-readable Transparent copy along with each Opaque copy, or X state in or with each Opaque copy a publicly-accessible X computer-network location containing a complete Transparent copy X of the Document, free of added material, which the general X network-using public has access to download anonymously at no X charge using public-standard network protocols. If you use the X latter option, you must take reasonably prudent steps, when you X begin distribution of Opaque copies in quantity, to ensure that X this Transparent copy will remain thus accessible at the stated X location until at least one year after the last time you X distribute an Opaque copy (directly or through your agents or X retailers) of that edition to the public. X X It is requested, but not required, that you contact the authors of X the Document well before redistributing any large number of X copies, to give them a chance to provide you with an updated X version of the Document. X X 4. MODIFICATIONS X X You may copy and distribute a Modified Version of the Document X under the conditions of sections 2 and 3 above, provided that you X release the Modified Version under precisely this License, with X the Modified Version filling the role of the Document, thus X licensing distribution and modification of the Modified Version to X whoever possesses a copy of it. In addition, you must do these X things in the Modified Version: X X A. Use in the Title Page (and on the covers, if any) a title X distinct from that of the Document, and from those of X previous versions (which should, if there were any, be listed X in the History section of the Document). You may use the X same title as a previous version if the original publisher of X that version gives permission. X X B. List on the Title Page, as authors, one or more persons or X entities responsible for authorship of the modifications in X the Modified Version, together with at least five of the X principal authors of the Document (all of its principal X authors, if it has less than five). X X C. State on the Title page the name of the publisher of the X Modified Version, as the publisher. X X D. Preserve all the copyright notices of the Document. X X E. Add an appropriate copyright notice for your modifications X adjacent to the other copyright notices. X X F. Include, immediately after the copyright notices, a license X notice giving the public permission to use the Modified X Version under the terms of this License, in the form shown in X the Addendum below. X X G. Preserve in that license notice the full lists of Invariant X Sections and required Cover Texts given in the Document's X license notice. X X H. Include an unaltered copy of this License. X X I. Preserve the section entitled "History", and its title, and X add to it an item stating at least the title, year, new X authors, and publisher of the Modified Version as given on X the Title Page. If there is no section entitled "History" in X the Document, create one stating the title, year, authors, X and publisher of the Document as given on its Title Page, X then add an item describing the Modified Version as stated in X the previous sentence. X X J. Preserve the network location, if any, given in the Document X for public access to a Transparent copy of the Document, and X likewise the network locations given in the Document for X previous versions it was based on. These may be placed in X the "History" section. You may omit a network location for a X work that was published at least four years before the X Document itself, or if the original publisher of the version X it refers to gives permission. X X K. In any section entitled "Acknowledgments" or "Dedications", X preserve the section's title, and preserve in the section all X the substance and tone of each of the contributor X acknowledgments and/or dedications given therein. X X L. Preserve all the Invariant Sections of the Document, X unaltered in their text and in their titles. Section numbers X or the equivalent are not considered part of the section X titles. X X M. Delete any section entitled "Endorsements". Such a section X may not be included in the Modified Version. X X N. Do not retitle any existing section as "Endorsements" or to X conflict in title with any Invariant Section. X X If the Modified Version includes new front-matter sections or X appendices that qualify as Secondary Sections and contain no X material copied from the Document, you may at your option X designate some or all of these sections as invariant. To do this, X add their titles to the list of Invariant Sections in the Modified X Version's license notice. These titles must be distinct from any X other section titles. X X You may add a section entitled "Endorsements", provided it contains X nothing but endorsements of your Modified Version by various X parties--for example, statements of peer review or that the text X has been approved by an organization as the authoritative X definition of a standard. X X You may add a passage of up to five words as a Front-Cover Text, X and a passage of up to 25 words as a Back-Cover Text, to the end X of the list of Cover Texts in the Modified Version. Only one X passage of Front-Cover Text and one of Back-Cover Text may be X added by (or through arrangements made by) any one entity. If the X Document already includes a cover text for the same cover, X previously added by you or by arrangement made by the same entity X you are acting on behalf of, you may not add another; but you may X replace the old one, on explicit permission from the previous X publisher that added the old one. X X The author(s) and publisher(s) of the Document do not by this X License give permission to use their names for publicity for or to X assert or imply endorsement of any Modified Version. X X 5. COMBINING DOCUMENTS X X You may combine the Document with other documents released under X this License, under the terms defined in section 4 above for X modified versions, provided that you include in the combination X all of the Invariant Sections of all of the original documents, X unmodified, and list them all as Invariant Sections of your X combined work in its license notice. X X The combined work need only contain one copy of this License, and X multiple identical Invariant Sections may be replaced with a single X copy. If there are multiple Invariant Sections with the same name X but different contents, make the title of each such section unique X by adding at the end of it, in parentheses, the name of the X original author or publisher of that section if known, or else a X unique number. Make the same adjustment to the section titles in X the list of Invariant Sections in the license notice of the X combined work. X X In the combination, you must combine any sections entitled X "History" in the various original documents, forming one section X entitled "History"; likewise combine any sections entitled X "Acknowledgments", and any sections entitled "Dedications". You X must delete all sections entitled "Endorsements." X X 6. COLLECTIONS OF DOCUMENTS X X You may make a collection consisting of the Document and other X documents released under this License, and replace the individual X copies of this License in the various documents with a single copy X that is included in the collection, provided that you follow the X rules of this License for verbatim copying of each of the X documents in all other respects. X X You may extract a single document from such a collection, and X distribute it individually under this License, provided you insert X a copy of this License into the extracted document, and follow X this License in all other respects regarding verbatim copying of X that document. X X 7. AGGREGATION WITH INDEPENDENT WORKS X X A compilation of the Document or its derivatives with other X separate and independent documents or works, in or on a volume of X a storage or distribution medium, does not as a whole count as a X Modified Version of the Document, provided no compilation X copyright is claimed for the compilation. Such a compilation is X called an "aggregate", and this License does not apply to the X other self-contained works thus compiled with the Document, on X account of their being thus compiled, if they are not themselves X derivative works of the Document. X X If the Cover Text requirement of section 3 is applicable to these X copies of the Document, then if the Document is less than one X quarter of the entire aggregate, the Document's Cover Texts may be X placed on covers that surround only the Document within the X aggregate. Otherwise they must appear on covers around the whole X aggregate. X X 8. TRANSLATION X X Translation is considered a kind of modification, so you may X distribute translations of the Document under the terms of section X 4. Replacing Invariant Sections with translations requires special X permission from their copyright holders, but you may include X translations of some or all Invariant Sections in addition to the X original versions of these Invariant Sections. You may include a X translation of this License provided that you also include the X original English version of this License. In case of a X disagreement between the translation and the original English X version of this License, the original English version will prevail. X X 9. TERMINATION X X You may not copy, modify, sublicense, or distribute the Document X except as expressly provided for under this License. Any other X attempt to copy, modify, sublicense or distribute the Document is X void, and will automatically terminate your rights under this X License. However, parties who have received copies, or rights, X from you under this License will not have their licenses X terminated so long as such parties remain in full compliance. X X 10. FUTURE REVISIONS OF THIS LICENSE X X The Free Software Foundation may publish new, revised versions of X the GNU Free Documentation License from time to time. Such new X versions will be similar in spirit to the present version, but may X differ in detail to address new problems or concerns. See X `http://www.gnu.org/copyleft/'. X X Each version of the License is given a distinguishing version X number. If the Document specifies that a particular numbered X version of this License "or any later version" applies to it, you X have the option of following the terms and conditions either of X that specified version or of any later version that has been X published (not as a draft) by the Free Software Foundation. If X the Document does not specify a version number of this License, X you may choose any version ever published (not as a draft) by the X Free Software Foundation. X XADDENDUM: How to use this License for your documents X---------------------------------------------------- X X To use this License in a document you have written, include a copy of Xthe License in the document and put the following copyright and license Xnotices just after the title page: X X Copyright (C) YEAR YOUR NAME. X Permission is granted to copy, distribute and/or modify this document X under the terms of the GNU Free Documentation License, Version 1.1 X or any later version published by the Free Software Foundation; X with the Invariant Sections being LIST THEIR TITLES, with the X Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. X A copy of the license is included in the section entitled ``GNU X Free Documentation License''. X X If you have no Invariant Sections, write "with no Invariant Sections" Xinstead of saying which ones are invariant. If you have no Front-Cover XTexts, write "no Front-Cover Texts" instead of "Front-Cover Texts being XLIST"; likewise for Back-Cover Texts. X X If your document contains nontrivial examples of program code, we Xrecommend releasing these examples in parallel under your choice of Xfree software license, such as the GNU General Public License, to Xpermit their use in free software. X X XFile: diff.info, Node: Index, Prev: Copying This Manual, Up: Top X XIndex X***** X X* Menu: X X* ! output format: Context. X* +- output format: Unified Format. X* < output format: Normal. X* <<<<<<< for marking conflicts: Marking Conflicts. X* _POSIX2_VERSION: Standards conformance. X* aligning tab stops: Tabs. X* alternate file names: Alternate Names. X* backup file names: Backup Names. X* backup file strategy: Backups. X* binary file diff: Binary. X* blank and tab difference suppression: White Space. X* blank line difference suppression: Blank Lines. X* brief difference reports: Brief. X* bug reports: Bugs. X* C function headings: C Function Headings. X* C if-then-else output format: If-then-else. X* case difference suppression: Case Folding. X* ClearCase: Revision Control. X* cmp invocation: Invoking cmp. X* cmp options: cmp Options. X* columnar output: Side by Side. X* common mistakes with patches: Avoiding Common Mistakes. X* comparing three files: Comparing Three Files. X* conflict: diff3 Merging. X* conflict marking: Marking Conflicts. X* context output format: Context. X* creating files: Creating and Removing. X* diagnostics from patch: patch Messages. X* diff invocation: Invoking diff. X* diff merging: Interactive Merging. X* diff options: diff Options. X* diff sample input: Sample diff Input. X* diff3 hunks: diff3 Hunks. X* diff3 invocation: Invoking diff3. X* diff3 options: diff3 Options. X* diff3 sample input: Sample diff3 Input. X* directories and patch: patch Directories. X* directory structure changes: Changing Structure. X* dry runs for patch: Dry Runs. X* ed script output format: ed Scripts. X* EDITOR: Merge Commands. X* empty files, removing: Creating and Removing. X* exabyte, definition of: cmp Options. X* exbibyte, definition of: cmp Options. X* FDL, GNU Free Documentation License: GNU Free Documentation License. X* file name alternates: Alternate Names. X* file names with unusual characters: Unusual File Names. X* format of diff output: Output Formats. X* format of diff3 output: Comparing Three Files. X* formats for if-then-else line groups: Line Group Formats. X* forward ed script output format: Forward ed. X* full lines: Incomplete Lines. X* function headings, C: C Function Headings. X* fuzz factor when patching: Inexact. X* gibibyte, definition of: cmp Options. X* gigabyte, definition of: cmp Options. X* headings: Sections. X* hunks: Hunks. X* hunks for diff3: diff3 Hunks. X* if-then-else output format: If-then-else. X* ifdef output format: If-then-else. X* imperfect patch application: Imperfect. X* incomplete line merging: Merging Incomplete Lines. X* incomplete lines: Incomplete Lines. X* inexact patches: Inexact. X* inhibit messages from patch: More or Fewer Messages. X* interactive merging: Interactive Merging. X* introduction: Comparison. X* intuiting file names from patches: Multiple Patches. X* invoking cmp: Invoking cmp. X* invoking diff: Invoking diff. X* invoking diff3: Invoking diff3. X* invoking patch: Invoking patch. X* invoking sdiff: Invoking sdiff. X* keyboard input to patch: patch and Keyboard Input. X* kibibyte, definition of: cmp Options. X* kilobyte, definition of: cmp Options. X* LC_COLLATE: Comparing Directories. X* LC_NUMERIC: Line Group Formats. X* LC_TIME: Detailed Context. X* line formats: Line Formats. X* line group formats: Line Group Formats. X* mebibyte, definition of: cmp Options. X* megabyte, definition of: cmp Options. X* merge commands: Merge Commands. X* merged diff3 format: Bypassing ed. X* merged output format: If-then-else. X* merging from a common ancestor: diff3 Merging. X* merging interactively: Merge Commands. X* messages from patch: patch Messages. X* multibyte characters: Internationalization. X* multiple patches: Multiple Patches. X* newline treatment by diff: Incomplete Lines. X* normal output format: Normal. X* options for cmp: cmp Options. X* options for diff: diff Options. X* options for diff3: diff3 Options. X* options for patch: patch Options. X* options for sdiff: sdiff Options. X* output formats: Output Formats. X* overlap: diff3 Merging. X* overlapping change, selection of: Which Changes. X* overview of diff and patch: Overview. X* paginating diff output: Pagination. X* patch consumer tips: Tips for Patch Consumers. X* patch input format: patch Input. X* patch invocation: Invoking patch. X* patch messages and questions: patch Messages. X* patch options: patch Options. X* patch producer tips: Tips for Patch Producers. X* patch, common mistakes: Avoiding Common Mistakes. X* PATCH_GET: Revision Control. X* PATCH_VERSION_CONTROL: Backup Names. X* patches, shrinking: Generating Smaller Patches. X* patching directories: patch Directories. X* pebibyte, definition of: cmp Options. X* performance of diff: diff Performance. X* petabyte, definition of: cmp Options. X* POSIX <1>: Standards conformance. X* POSIX: patch and POSIX. X* POSIXLY_CORRECT <1>: patch and POSIX. X* POSIXLY_CORRECT: Standards conformance. X* projects for directories: Shortcomings. X* quoting style: patch Quoting Style. X* QUOTING_STYLE: patch Quoting Style. X* RCS: Revision Control. X* RCS script output format: RCS. X* regular expression matching headings: Specified Headings. X* regular expression suppression: Specified Folding. X* reject file names: Reject Names. X* removing empty files: Creating and Removing. X* reporting bugs: Bugs. X* reversed patches: Reversed Patches. X* revision control: Revision Control. X* sample input for diff: Sample diff Input. X* sample input for diff3: Sample diff3 Input. X* SCCS: Revision Control. X* script output formats: Scripts. X* sdiff invocation: Invoking sdiff. X* sdiff options: sdiff Options. X* sdiff output format: sdiff Option Summary. X* section headings: Sections. X* side by side: Side by Side. X* side by side format: Side by Side Format. X* SIMPLE_BACKUP_SUFFIX: Backup Names. X* special files: Special Files. X* specified headings: Specified Headings. X* summarizing which files differ: Brief. X* System V diff3 compatibility: Saving the Changed File. X* tab and blank difference suppression: White Space. X* tab stop alignment: Tabs. X* tebibyte, definition of: cmp Options. X* terabyte, definition of: cmp Options. X* testing patch: Dry Runs. X* text versus binary diff: Binary. X* time stamp format, context diffs: Detailed Context. X* time stamp format, unified diffs: Detailed Unified. X* time stamps on patched files: Patching Time Stamps. X* traditional patch: patch and Tradition. X* two-column output: Side by Side. X* unified output format: Unified Format. X* unmerged change: Which Changes. X* varying-width characters: Internationalization. X* verbose messages from patch: More or Fewer Messages. X* version control: Revision Control. X* VERSION_CONTROL <1>: Backup Names. X* VERSION_CONTROL: Revision Control. X* white space in patches: Changed White Space. X* yottabyte, definition of: cmp Options. X* zettabyte, definition of: cmp Options. X X X XTag Table: XNode: Top1653 XNode: Overview4045 XNode: Comparison7202 XNode: Hunks9888 XNode: White Space11313 XNode: Blank Lines12807 XNode: Case Folding13562 XNode: Specified Folding13977 XNode: Brief15052 XNode: Binary16295 XNode: Output Formats20358 XNode: Sample diff Input21076 XNode: Normal22569 XNode: Detailed Normal23564 XNode: Example Normal25289 XNode: Context26011 XNode: Context Format27567 XNode: Detailed Context28345 XNode: Example Context30234 XNode: Less Context31748 XNode: Unified Format32894 XNode: Detailed Unified33676 XNode: Example Unified34787 XNode: Sections35807 XNode: Specified Headings36552 XNode: C Function Headings38083 XNode: Alternate Names38908 XNode: Side by Side39808 XNode: Side by Side Format41947 XNode: Example Side by Side42836 XNode: Scripts44162 XNode: ed Scripts44563 XNode: Detailed ed45756 XNode: Example ed47497 XNode: Forward ed47934 XNode: RCS48696 XNode: If-then-else49904 XNode: Line Group Formats51572 XNode: Line Formats57437 XNode: Detailed If-then-else60693 XNode: Example If-then-else62583 XNode: Incomplete Lines63632 XNode: Comparing Directories65263 XNode: Adjusting Output69220 XNode: Tabs69645 XNode: Pagination71177 XNode: diff Performance71626 XNode: Comparing Three Files74708 XNode: Sample diff3 Input75580 XNode: Detailed diff3 Normal76528 XNode: diff3 Hunks78307 XNode: Example diff3 Normal79593 XNode: diff3 Merging80616 XNode: Which Changes82854 XNode: Marking Conflicts84258 XNode: Bypassing ed86714 XNode: Merging Incomplete Lines88068 XNode: Saving the Changed File88784 XNode: Interactive Merging89390 XNode: sdiff Option Summary90094 XNode: Merge Commands91242 XNode: Merging with patch92503 XNode: patch Input94867 XNode: Revision Control95537 XNode: Imperfect96689 XNode: Changed White Space97825 XNode: Reversed Patches98606 XNode: Inexact100056 XNode: Dry Runs103599 XNode: Creating and Removing104447 XNode: Patching Time Stamps105486 XNode: Multiple Patches107677 XNode: patch Directories110328 XNode: Backups111942 XNode: Backup Names112996 XRef: Backup Names-Footnote-1115955 XNode: Reject Names116082 XNode: patch Messages116660 XNode: More or Fewer Messages117706 XNode: patch and Keyboard Input118319 XNode: patch Quoting Style119332 XNode: patch and POSIX120464 XNode: patch and Tradition121290 XNode: Making Patches124734 XNode: Tips for Patch Producers125552 XNode: Tips for Patch Consumers126796 XNode: Avoiding Common Mistakes127421 XNode: Generating Smaller Patches129934 XNode: Invoking cmp131683 XNode: cmp Options132532 XNode: Invoking diff135896 XNode: diff Options137599 XNode: Invoking diff3145722 XNode: diff3 Options146352 XNode: Invoking patch149255 XNode: patch Options150455 XNode: Invoking sdiff155669 XNode: sdiff Options156808 XNode: Standards conformance159561 XNode: Projects161299 XNode: Shortcomings162002 XNode: Internationalization163092 XNode: Changing Structure164247 XNode: Special Files165336 XNode: Unusual File Names166282 XNode: Time Stamp Order166904 XNode: Ignoring Changes167531 XNode: Speedups168285 XNode: Bugs168733 XNode: Copying This Manual169574 XNode: GNU Free Documentation License169782 XNode: Index189646 X XEnd Tag Table END-of-contrib/diff/doc/diff.info echo c - contrib/diff/lib mkdir -p contrib/diff/lib > /dev/null 2>&1 echo x - contrib/diff/lib/c-stack.h sed 's/^X//' >contrib/diff/lib/c-stack.h << 'END-of-contrib/diff/lib/c-stack.h' X/* Stack overflow handling. X X Copyright (C) 2002 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software Foundation, X Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#if ! HAVE_SIGINFO_T X# define siginfo_t void X#endif X Xint c_stack_action (void (*) (int, siginfo_t *, void *)); Xvoid c_stack_die (int, siginfo_t *, void *); END-of-contrib/diff/lib/c-stack.h echo x - contrib/diff/lib/cmpbuf.h sed 's/^X//' >contrib/diff/lib/cmpbuf.h << 'END-of-contrib/diff/lib/cmpbuf.h' X/* Buffer primitives for comparison operations. X X Copyright (C) 2002 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; see the file COPYING. X If not, write to the Free Software Foundation, X 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X Xsize_t block_read (int, char *, size_t); Xsize_t buffer_lcm (size_t, size_t, size_t); END-of-contrib/diff/lib/cmpbuf.h echo x - contrib/diff/lib/dirname.h sed 's/^X//' >contrib/diff/lib/dirname.h << 'END-of-contrib/diff/lib/dirname.h' X/* Copyright (C) 1998, 2001 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software Foundation, X Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#ifndef DIRNAME_H_ X# define DIRNAME_H_ 1 X X# ifndef PARAMS X# if defined PROTOTYPES || (defined __STDC__ && __STDC__) X# define PARAMS(Args) Args X# else X# define PARAMS(Args) () X# endif X# endif X X# ifndef DIRECTORY_SEPARATOR X# define DIRECTORY_SEPARATOR '/' X# endif X X# ifndef ISSLASH X# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR) X# endif X X# ifndef FILESYSTEM_PREFIX_LEN X# define FILESYSTEM_PREFIX_LEN(Filename) 0 X# endif X Xchar *base_name PARAMS ((char const *path)); Xchar *dir_name PARAMS ((char const *path)); Xsize_t base_len PARAMS ((char const *path)); Xsize_t dir_len PARAMS ((char const *path)); X Xint strip_trailing_slashes PARAMS ((char *path)); X X#endif /* not DIRNAME_H_ */ END-of-contrib/diff/lib/dirname.h echo x - contrib/diff/lib/error.h sed 's/^X//' >contrib/diff/lib/error.h << 'END-of-contrib/diff/lib/error.h' X/* Declaration for error-reporting function X Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. X X X NOTE: The canonical source of this file is maintained with the GNU C Library. X Bugs can be reported to bug-glibc@prep.ai.mit.edu. X X This program is free software; you can redistribute it and/or modify it X under the terms of the GNU General Public License as published by the X Free Software Foundation; either version 2, or (at your option) any X later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software X Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, X USA. */ X X#ifndef _ERROR_H X#define _ERROR_H 1 X X#ifndef __attribute__ X/* This feature is available in gcc versions 2.5 and later. */ X# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) X# define __attribute__(Spec) /* empty */ X# endif X/* The __-protected variants of `format' and `printf' attributes X are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */ X# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) X# define __format__ format X# define __printf__ printf X# endif X#endif X X#ifdef __cplusplus Xextern "C" { X#endif X X#if defined (__STDC__) && __STDC__ X X/* Print a message with `fprintf (stderr, FORMAT, ...)'; X if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM). X If STATUS is nonzero, terminate the program with `exit (STATUS)'. */ X Xextern void error (int status, int errnum, const char *format, ...) X __attribute__ ((__format__ (__printf__, 3, 4))); X Xextern void error_at_line (int status, int errnum, const char *fname, X unsigned int lineno, const char *format, ...) X __attribute__ ((__format__ (__printf__, 5, 6))); X X/* If NULL, error will flush stdout, then print on stderr the program X name, a colon and a space. Otherwise, error will call this X function without parameters instead. */ Xextern void (*error_print_progname) (void); X X#else Xvoid error (); Xvoid error_at_line (); Xextern void (*error_print_progname) (); X#endif X X/* This variable is incremented each time `error' is called. */ Xextern unsigned int error_message_count; X X/* Sometimes we want to have at most one error per line. This X variable controls whether this mode is selected or not. */ Xextern int error_one_per_line; X X#ifdef __cplusplus X} X#endif X X#endif /* error.h */ END-of-contrib/diff/lib/error.h echo x - contrib/diff/lib/exclude.h sed 's/^X//' >contrib/diff/lib/exclude.h << 'END-of-contrib/diff/lib/exclude.h' X/* exclude.h -- declarations for excluding file names X Copyright 1992, 1993, 1994, 1997, 1999, 2001 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; see the file COPYING. X If not, write to the Free Software Foundation, X 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X/* Written by Paul Eggert */ X X#ifndef PARAMS X# if defined PROTOTYPES || (defined __STDC__ && __STDC__) X# define PARAMS(Args) Args X# else X# define PARAMS(Args) () X# endif X#endif X X/* Exclude options, which can be ORed with fnmatch options. */ X X/* Patterns must match the start of file names, instead of matching X anywhere after a '/'. */ X#define EXCLUDE_ANCHORED (1 << 5) X X/* Include instead of exclude. */ X#define EXCLUDE_INCLUDE (1 << 6) X X/* '?', '*', '[', and '\\' are special in patterns. Without this X option, these characters are ordinary and fnmatch is not used. */ X#define EXCLUDE_WILDCARDS (1 << 7) X Xstruct exclude; X Xstruct exclude *new_exclude PARAMS ((void)); Xvoid free_exclude PARAMS ((struct exclude *)); Xvoid add_exclude PARAMS ((struct exclude *, char const *, int)); Xint add_exclude_file PARAMS ((void (*) (struct exclude *, char const *, int), X struct exclude *, char const *, int, char)); Xbool excluded_filename PARAMS ((struct exclude const *, char const *)); END-of-contrib/diff/lib/exclude.h echo x - contrib/diff/lib/exitfail.h sed 's/^X//' >contrib/diff/lib/exitfail.h << 'END-of-contrib/diff/lib/exitfail.h' X/* Failure exit status X X Copyright (C) 2002 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; see the file COPYING. X If not, write to the Free Software Foundation, X 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X Xextern int volatile exit_failure; END-of-contrib/diff/lib/exitfail.h echo x - contrib/diff/lib/fnmatch.hin sed 's/^X//' >contrib/diff/lib/fnmatch.hin << 'END-of-contrib/diff/lib/fnmatch.hin' X/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. X XNOTE: The canonical source of this file is maintained with the GNU C Library. XBugs can be reported to bug-glibc@prep.ai.mit.edu. X XThis program is free software; you can redistribute it and/or modify it Xunder the terms of the GNU General Public License as published by the XFree Software Foundation; either version 2, or (at your option) any Xlater version. X XThis program is distributed in the hope that it will be useful, Xbut WITHOUT ANY WARRANTY; without even the implied warranty of XMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the XGNU General Public License for more details. X XYou should have received a copy of the GNU General Public License Xalong with this program; if not, write to the Free Software Foundation, XInc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#ifndef _FNMATCH_H X X#define _FNMATCH_H 1 X X#ifdef __cplusplus Xextern "C" { X#endif X X#if defined (__cplusplus) || (defined (__STDC__) && __STDC__) X#undef __P X#define __P(protos) protos X#else /* Not C++ or ANSI C. */ X#undef __P X#define __P(protos) () X/* We can get away without defining `const' here only because in this file X it is used only inside the prototype for `fnmatch', which is elided in X non-ANSI C where `const' is problematical. */ X#endif /* C++ or ANSI C. */ X X X/* We #undef these before defining them because some losing systems X (HP-UX A.08.07 for example) define these in . */ X#undef FNM_PATHNAME X#undef FNM_NOESCAPE X#undef FNM_PERIOD X X/* Bits set in the FLAGS argument to `fnmatch'. */ X#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */ X#define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */ X#define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */ X X#if !defined (_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 2 || defined (_GNU_SOURCE) X#define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */ X#define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */ X#define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */ X#endif X X/* Value returned by `fnmatch' if STRING does not match PATTERN. */ X#define FNM_NOMATCH 1 X X/* Match STRING against the filename pattern PATTERN, X returning zero if it matches, FNM_NOMATCH if not. */ Xextern int fnmatch __P ((const char *__pattern, const char *__string, X int __flags)); X X#ifdef __cplusplus X} X#endif X X#endif /* fnmatch.h */ END-of-contrib/diff/lib/fnmatch.hin echo x - contrib/diff/lib/freesoft.h sed 's/^X//' >contrib/diff/lib/freesoft.h << 'END-of-contrib/diff/lib/freesoft.h' Xextern char const free_software_msgid[]; END-of-contrib/diff/lib/freesoft.h echo x - contrib/diff/lib/getopt.h sed 's/^X//' >contrib/diff/lib/getopt.h << 'END-of-contrib/diff/lib/getopt.h' X/* Declarations for getopt. X Copyright (C) 1989-1994, 1996-1999, 2001 Free Software Foundation, Inc. X This file is part of the GNU C Library. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software Foundation, X Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#ifndef _GETOPT_H X X#ifndef __need_getopt X# define _GETOPT_H 1 X#endif X X/* If __GNU_LIBRARY__ is not already defined, either we are being used X standalone, or this is the first header included in the source file. X If we are being used with glibc, we need to include , but X that does not exist if we are standalone. So: if __GNU_LIBRARY__ is X not defined, include , which will pull in for us X if it's from glibc. (Why ctype.h? It's guaranteed to exist and it X doesn't flood the namespace with stuff the way some other headers do.) */ X#if !defined __GNU_LIBRARY__ X# include X#endif X X#ifdef __cplusplus Xextern "C" { X#endif X X/* For communication from `getopt' to the caller. X When `getopt' finds an option that takes an argument, X the argument value is returned here. X Also, when `ordering' is RETURN_IN_ORDER, X each non-option ARGV-element is returned here. */ X Xextern char *optarg; X X/* Index in ARGV of the next element to be scanned. X This is used for communication to and from the caller X and for communication between successive calls to `getopt'. X X On entry to `getopt', zero means this is the first call; initialize. X X When `getopt' returns -1, this is the index of the first of the X non-option elements that the caller should itself scan. X X Otherwise, `optind' communicates from one call to the next X how much of ARGV has been scanned so far. */ X Xextern int optind; X X/* Callers store zero here to inhibit the error message `getopt' prints X for unrecognized options. */ X Xextern int opterr; X X/* Set to an option character which was unrecognized. */ X Xextern int optopt; X X#ifndef __need_getopt X/* Describe the long-named options requested by the application. X The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector X of `struct option' terminated by an element containing a name which is X zero. X X The field `has_arg' is: X no_argument (or 0) if the option does not take an argument, X required_argument (or 1) if the option requires an argument, X optional_argument (or 2) if the option takes an optional argument. X X If the field `flag' is not NULL, it points to a variable that is set X to the value given in the field `val' when the option is found, but X left unchanged if the option is not found. X X To have a long-named option do something other than set an `int' to X a compiled-in constant, such as set a value from `optarg', set the X option's `flag' field to zero and its `val' field to a nonzero X value (the equivalent single-letter option character, if there is X one). For long options that have a zero `flag' field, `getopt' X returns the contents of the `val' field. */ X Xstruct option X{ X# if (defined __STDC__ && __STDC__) || defined __cplusplus X const char *name; X# else X char *name; X# endif X /* has_arg can't be an enum because some compilers complain about X type mismatches in all the code that assumes it is an int. */ X int has_arg; X int *flag; X int val; X}; X X/* Names for the values of the `has_arg' field of `struct option'. */ X X# define no_argument 0 X# define required_argument 1 X# define optional_argument 2 X#endif /* need getopt */ X X X/* Get definitions and prototypes for functions to process the X arguments in ARGV (ARGC of them, minus the program name) for X options given in OPTS. X X Return the option character from OPTS just read. Return -1 when X there are no more options. For unrecognized options, or options X missing arguments, `optopt' is set to the option letter, and '?' is X returned. X X The OPTS string is a list of characters which are recognized option X letters, optionally followed by colons, specifying that that letter X takes an argument, to be placed in `optarg'. X X If a letter in OPTS is followed by two colons, its argument is X optional. This behavior is specific to the GNU `getopt'. X X The argument `--' causes premature termination of argument X scanning, explicitly telling `getopt' that there are no more X options. X X If OPTS begins with `--', then non-option arguments are treated as X arguments to the option '\0'. This behavior is specific to the GNU X `getopt'. */ X X#if (defined __STDC__ && __STDC__) || defined __cplusplus X# ifdef __GNU_LIBRARY__ X/* Many other libraries have conflicting prototypes for getopt, with X differences in the consts, in stdlib.h. To avoid compilation X errors, only prototype getopt for the GNU C library. */ Xextern int getopt (int __argc, char *const *__argv, const char *__shortopts); X# else /* not __GNU_LIBRARY__ */ Xextern int getopt (); X# endif /* __GNU_LIBRARY__ */ X X# ifndef __need_getopt Xextern int getopt_long (int __argc, char *const *__argv, const char *__shortopts, X const struct option *__longopts, int *__longind); Xextern int getopt_long_only (int __argc, char *const *__argv, X const char *__shortopts, X const struct option *__longopts, int *__longind); X X/* Internal only. Users should not call this directly. */ Xextern int _getopt_internal (int __argc, char *const *__argv, X const char *__shortopts, X const struct option *__longopts, int *__longind, X int __long_only); X# endif X#else /* not __STDC__ */ Xextern int getopt (); X# ifndef __need_getopt Xextern int getopt_long (); Xextern int getopt_long_only (); X Xextern int _getopt_internal (); X# endif X#endif /* __STDC__ */ X X#ifdef __cplusplus X} X#endif X X/* Make sure we later can get all the definitions and declarations. */ X#undef __need_getopt X X#endif /* getopt.h */ END-of-contrib/diff/lib/getopt.h echo x - contrib/diff/lib/gettext.h sed 's/^X//' >contrib/diff/lib/gettext.h << 'END-of-contrib/diff/lib/gettext.h' X/* Convenience header for conditional use of GNU . X Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify it X under the terms of the GNU Library General Public License as published X by the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU X Library General Public License for more details. X X You should have received a copy of the GNU Library General Public X License along with this program; if not, write to the Free Software X Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, X USA. */ X X#ifndef _LIBGETTEXT_H X#define _LIBGETTEXT_H 1 X X/* NLS can be disabled through the configure --disable-nls option. */ X#if ENABLE_NLS X X/* Get declarations of GNU message catalog functions. */ X# include X X#else X X/* Disabled NLS. X The casts to 'const char *' serve the purpose of producing warnings X for invalid uses of the value returned from these functions. X On pre-ANSI systems without 'const', the config.h file is supposed to X contain "#define const". */ X# define gettext(Msgid) ((const char *) (Msgid)) X# define dgettext(Domainname, Msgid) ((const char *) (Msgid)) X# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid)) X# define ngettext(Msgid1, Msgid2, N) \ X ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) X# define dngettext(Domainname, Msgid1, Msgid2, N) \ X ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) X# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ X ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) X# define textdomain(Domainname) ((const char *) (Domainname)) X# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname)) X# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset)) X X#endif X X/* A pseudo function call that serves as a marker for the automated X extraction of messages, but does not call gettext(). The run-time X translation is done at a different place in the code. X The argument, String, should be a literal string. Concatenated strings X and other string expressions won't work. X The macro's expansion is not parenthesized, so that it is suitable as X initializer for static 'char[]' or 'const char[]' variables. */ X#define gettext_noop(String) String X X#endif /* _LIBGETTEXT_H */ END-of-contrib/diff/lib/gettext.h echo x - contrib/diff/lib/hard-locale.h sed 's/^X//' >contrib/diff/lib/hard-locale.h << 'END-of-contrib/diff/lib/hard-locale.h' X#ifndef HARD_LOCALE_H_ X# define HARD_LOCALE_H_ 1 X X# if HAVE_CONFIG_H X# include X# endif X X# ifndef PARAMS X# if defined PROTOTYPES || (defined __STDC__ && __STDC__) X# define PARAMS(Args) Args X# else X# define PARAMS(Args) () X# endif X# endif X Xint hard_locale PARAMS ((int)); X X#endif /* HARD_LOCALE_H_ */ END-of-contrib/diff/lib/hard-locale.h echo x - contrib/diff/lib/inttostr.h sed 's/^X//' >contrib/diff/lib/inttostr.h << 'END-of-contrib/diff/lib/inttostr.h' X/* inttostr.h -- convert integers to printable strings X X Copyright (C) 2001 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software Foundation, X Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X/* Written by Paul Eggert */ X X#if HAVE_CONFIG_H X# include X#endif X X#if HAVE_INTTYPES_H X# include X#endif X X#if HAVE_LIMITS_H X# include X#endif X#ifndef CHAR_BIT X# define CHAR_BIT 8 X#endif X X#if HAVE_SYS_TYPES_H X# include X#endif X X#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) X X/* Upper bound on the string length of an integer converted to string. X 302 / 1000 is ceil (log10 (2.0)). Subtract 1 for the sign bit; X add 1 for integer division truncation; add 1 more for a minus sign. */ X#define INT_STRLEN_BOUND(t) \ X ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 + 1 + TYPE_SIGNED (t)) X X#define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1) X X#ifndef PARAMS X# if defined PROTOTYPES || defined __STDC__ X# define PARAMS(Args) Args X# else X# define PARAMS(Args) () X# endif X#endif X Xchar *offtostr PARAMS ((off_t, char *)); Xchar *imaxtostr PARAMS ((intmax_t, char *)); Xchar *umaxtostr PARAMS ((uintmax_t, char *)); END-of-contrib/diff/lib/inttostr.h echo x - contrib/diff/lib/prepargs.h sed 's/^X//' >contrib/diff/lib/prepargs.h << 'END-of-contrib/diff/lib/prepargs.h' X/* Parse arguments from a string and prepend them to an argv. */ X Xvoid prepend_default_options (char const *, int *, char ***); END-of-contrib/diff/lib/prepargs.h echo x - contrib/diff/lib/posixver.h sed 's/^X//' >contrib/diff/lib/posixver.h << 'END-of-contrib/diff/lib/posixver.h' Xint posix2_version (void); END-of-contrib/diff/lib/posixver.h echo x - contrib/diff/lib/quotesys.h sed 's/^X//' >contrib/diff/lib/quotesys.h << 'END-of-contrib/diff/lib/quotesys.h' X/* quotesys.h -- declarations for quoting system arguments */ X X#if defined __STDC__ || __GNUC__ X# define __QUOTESYS_P(args) args X#else X# define __QUOTESYS_P(args) () X#endif X Xsize_t quote_system_arg __QUOTESYS_P ((char *, char const *)); END-of-contrib/diff/lib/quotesys.h echo x - contrib/diff/lib/regex.hin sed 's/^X//' >contrib/diff/lib/regex.hin << 'END-of-contrib/diff/lib/regex.hin' X#ifndef _REGEX_H X#include X X/* Document internal interfaces. */ Xextern reg_syntax_t __re_set_syntax _RE_ARGS ((reg_syntax_t syntax)); X Xextern const char *__re_compile_pattern X _RE_ARGS ((const char *pattern, size_t length, X struct re_pattern_buffer *buffer)); X Xextern int __re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer)); X Xextern int __re_search X _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string, X int length, int start, int range, struct re_registers *regs)); X Xextern int __re_search_2 X _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1, X int length1, const char *string2, int length2, X int start, int range, struct re_registers *regs, int stop)); X Xextern int __re_match X _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string, X int length, int start, struct re_registers *regs)); X Xextern int __re_match_2 X _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1, X int length1, const char *string2, int length2, X int start, struct re_registers *regs, int stop)); X Xextern void __re_set_registers X _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs, X unsigned num_regs, regoff_t *starts, regoff_t *ends)); X Xextern int __regcomp _RE_ARGS ((regex_t *__preg, const char *__pattern, X int __cflags)); X Xextern int __regexec _RE_ARGS ((const regex_t *__preg, X const char *__string, size_t __nmatch, X regmatch_t __pmatch[], int __eflags)); X Xextern size_t __regerror _RE_ARGS ((int __errcode, const regex_t *__preg, X char *__errbuf, size_t __errbuf_size)); X Xextern void __regfree _RE_ARGS ((regex_t *__preg)); X#endif END-of-contrib/diff/lib/regex.hin echo x - contrib/diff/lib/setmode.h sed 's/^X//' >contrib/diff/lib/setmode.h << 'END-of-contrib/diff/lib/setmode.h' X/* Set a file descriptor's mode to binary or to text. X X Copyright (C) 2001 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; see the file COPYING. X If not, write to the Free Software Foundation, X 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X/* Written by Paul Eggert */ X X#ifndef set_binary_mode Xbool set_binary_mode (int, bool); X# if ! HAVE_SETMODE_DOS X# define set_binary_mode(fd, mode) 1 X# endif X#endif END-of-contrib/diff/lib/setmode.h echo x - contrib/diff/lib/unlocked-io.h sed 's/^X//' >contrib/diff/lib/unlocked-io.h << 'END-of-contrib/diff/lib/unlocked-io.h' X#ifndef UNLOCKED_IO_H X# define UNLOCKED_IO_H 1 X X# ifndef USE_UNLOCKED_IO X# define USE_UNLOCKED_IO 1 X# endif X X# if USE_UNLOCKED_IO X X/* These are wrappers for functions/macros from GNU libc. X The standard I/O functions are thread-safe. These *_unlocked ones are X more efficient but not thread-safe. That they're not thread-safe is X fine since all of the applications in this package are single threaded. */ X X# if HAVE_DECL_CLEARERR_UNLOCKED X# undef clearerr X# define clearerr(x) clearerr_unlocked (x) X# endif X# if HAVE_DECL_FEOF_UNLOCKED X# undef feof X# define feof(x) feof_unlocked (x) X# endif X# if HAVE_DECL_FERROR_UNLOCKED X# undef ferror X# define ferror(x) ferror_unlocked (x) X# endif X# if HAVE_DECL_FFLUSH_UNLOCKED X# undef fflush X# define fflush(x) fflush_unlocked (x) X# endif X# if HAVE_DECL_FGETS_UNLOCKED X# undef fgets X# define fgets(x,y,z) fgets_unlocked (x,y,z) X# endif X# if HAVE_DECL_FPUTC_UNLOCKED X# undef fputc X# define fputc(x,y) fputc_unlocked (x,y) X# endif X# if HAVE_DECL_FPUTS_UNLOCKED X# undef fputs X# define fputs(x,y) fputs_unlocked (x,y) X# endif X# if HAVE_DECL_FREAD_UNLOCKED X# undef fread X# define fread(w,x,y,z) fread_unlocked (w,x,y,z) X# endif X# if HAVE_DECL_FWRITE_UNLOCKED X# undef fwrite X# define fwrite(w,x,y,z) fwrite_unlocked (w,x,y,z) X# endif X# if HAVE_DECL_GETC_UNLOCKED X# undef getc X# define getc(x) getc_unlocked (x) X# endif X# if HAVE_DECL_GETCHAR_UNLOCKED X# undef getchar X# define getchar() getchar_unlocked () X# endif X# if HAVE_DECL_PUTC_UNLOCKED X# undef putc X# define putc(x,y) putc_unlocked (x,y) X# endif X# if HAVE_DECL_PUTCHAR_UNLOCKED X# undef putchar X# define putchar(x) putchar_unlocked (x) X# endif X X# endif /* USE_UNLOCKED_IO */ X#endif /* UNLOCKED_IO_H */ END-of-contrib/diff/lib/unlocked-io.h echo x - contrib/diff/lib/xalloc.h sed 's/^X//' >contrib/diff/lib/xalloc.h << 'END-of-contrib/diff/lib/xalloc.h' X/* xalloc.h -- malloc with out-of-memory checking X Copyright (C) 1990-1998, 1999, 2000, 2002 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software Foundation, X Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#ifndef XALLOC_H_ X# define XALLOC_H_ X X# ifndef PARAMS X# if defined PROTOTYPES || (defined __STDC__ && __STDC__) X# define PARAMS(Args) Args X# else X# define PARAMS(Args) () X# endif X# endif X X# ifndef __attribute__ X# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__ X# define __attribute__(x) X# endif X# endif X X# ifndef ATTRIBUTE_NORETURN X# define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__)) X# endif X X/* If this pointer is non-zero, run the specified function upon each X allocation failure. It is initialized to zero. */ Xextern void (*xalloc_fail_func) PARAMS ((void)); X X/* If XALLOC_FAIL_FUNC is undefined or a function that returns, this X message is output. It is translated via gettext. X Its value is "memory exhausted". */ Xextern char const xalloc_msg_memory_exhausted[]; X X/* This function is always triggered when memory is exhausted. It is X in charge of honoring the three previous items. This is the X function to call when one wants the program to die because of a X memory allocation failure. */ Xextern void xalloc_die PARAMS ((void)) ATTRIBUTE_NORETURN; X Xvoid *xmalloc PARAMS ((size_t n)); Xvoid *xcalloc PARAMS ((size_t n, size_t s)); Xvoid *xrealloc PARAMS ((void *p, size_t n)); Xchar *xstrdup PARAMS ((const char *str)); X X# define XMALLOC(Type, N_items) ((Type *) xmalloc (sizeof (Type) * (N_items))) X# define XCALLOC(Type, N_items) ((Type *) xcalloc (sizeof (Type), (N_items))) X# define XREALLOC(Ptr, Type, N_items) \ X ((Type *) xrealloc ((void *) (Ptr), sizeof (Type) * (N_items))) X X/* Declare and alloc memory for VAR of type TYPE. */ X# define NEW(Type, Var) Type *(Var) = XMALLOC (Type, 1) X X/* Free VAR only if non NULL. */ X# define XFREE(Var) \ X do { \ X if (Var) \ X free (Var); \ X } while (0) X X/* Return a pointer to a malloc'ed copy of the array SRC of NUM elements. */ X# define CCLONE(Src, Num) \ X (memcpy (xmalloc (sizeof (*Src) * (Num)), (Src), sizeof (*Src) * (Num))) X X/* Return a malloc'ed copy of SRC. */ X# define CLONE(Src) CCLONE (Src, 1) X X X#endif /* !XALLOC_H_ */ END-of-contrib/diff/lib/xalloc.h echo x - contrib/diff/lib/xstrtol.h sed 's/^X//' >contrib/diff/lib/xstrtol.h << 'END-of-contrib/diff/lib/xstrtol.h' X/* A more useful interface to strtol. X Copyright 1995, 1996, 1998, 1999, 2001 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software Foundation, X Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#ifndef XSTRTOL_H_ X# define XSTRTOL_H_ 1 X X# if HAVE_INTTYPES_H X# include /* for uintmax_t */ X# endif X X# ifndef PARAMS X# if defined PROTOTYPES || (defined __STDC__ && __STDC__) X# define PARAMS(Args) Args X# else X# define PARAMS(Args) () X# endif X# endif X X# ifndef _STRTOL_ERROR Xenum strtol_error X { X LONGINT_OK, LONGINT_INVALID, LONGINT_INVALID_SUFFIX_CHAR, LONGINT_OVERFLOW X }; Xtypedef enum strtol_error strtol_error; X# endif X X# define _DECLARE_XSTRTOL(name, type) \ X strtol_error \ X name PARAMS ((const char *s, char **ptr, int base, \ X type *val, const char *valid_suffixes)); X_DECLARE_XSTRTOL (xstrtol, long int) X_DECLARE_XSTRTOL (xstrtoul, unsigned long int) X_DECLARE_XSTRTOL (xstrtoimax, intmax_t) X_DECLARE_XSTRTOL (xstrtoumax, uintmax_t) X X# define _STRTOL_ERROR(Exit_code, Str, Argument_type_string, Err) \ X do \ X { \ X switch ((Err)) \ X { \ X case LONGINT_OK: \ X abort (); \ X \ X case LONGINT_INVALID: \ X error ((Exit_code), 0, "invalid %s `%s'", \ X (Argument_type_string), (Str)); \ X break; \ X \ X case LONGINT_INVALID_SUFFIX_CHAR: \ X error ((Exit_code), 0, "invalid character following %s in `%s'", \ X (Argument_type_string), (Str)); \ X break; \ X \ X case LONGINT_OVERFLOW: \ X error ((Exit_code), 0, "%s `%s' too large", \ X (Argument_type_string), (Str)); \ X break; \ X } \ X } \ X while (0) X X# define STRTOL_FATAL_ERROR(Str, Argument_type_string, Err) \ X _STRTOL_ERROR (2, Str, Argument_type_string, Err) X X# define STRTOL_FAIL_WARN(Str, Argument_type_string, Err) \ X _STRTOL_ERROR (0, Str, Argument_type_string, Err) X X#endif /* not XSTRTOL_H_ */ END-of-contrib/diff/lib/xstrtol.h echo x - contrib/diff/lib/Makefile.am sed 's/^X//' >contrib/diff/lib/Makefile.am << 'END-of-contrib/diff/lib/Makefile.am' X# Automakefile for GNU Diffutils library. X X# Copyright (C) 2001, 2002 Free Software Foundation, Inc. X X## This program is free software; you can redistribute it and/or modify X## it under the terms of the GNU General Public License as published by X## the Free Software Foundation; either version 2, or (at your option) X## any later version. X X## This program is distributed in the hope that it will be useful, X## but WITHOUT ANY WARRANTY; without even the implied warranty of X## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X## GNU General Public License for more details. X X## You should have received a copy of the GNU General Public License X## along with this program; if not, write to the Free Software X## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA X## 02111-1307, USA. X Xnoinst_LIBRARIES = libdiffutils.a X XEXTRA_DIST = alloca.c fnmatch.c inttostr.c malloc.c memchr.c mkstemp.c \ X realloc.c regex.c strcasecmp.c strtoimax.c strtol.c tempname.c waitpid.c \ X xstrtol.c XSUBDIRS = posix X Xnoinst_HEADERS = \ X c-stack.h cmpbuf.h dirname.h error.h exclude.h exitfail.h \ X fnmatch.hin freesoft.h getopt.h \ X gettext.h hard-locale.h inttostr.h prepargs.h posixver.h quotesys.h \ X regex.hin setmode.h unlocked-io.h xalloc.h xstrtol.h X Xlibdiffutils_a_SOURCES = \ X basename.c c-stack.c cmpbuf.c error.c exclude.c exitfail.c \ X freesoft.c getopt.c getopt1.c \ X hard-locale.c imaxtostr.c offtostr.c prepargs.c posixver.c quotesys.c \ X setmode.c strftime.c umaxtostr.c xmalloc.c xstrtoumax.c X Xlibdiffutils_a_LIBADD = @ALLOCA@ @LIBOBJS@ Xlibdiffutils_a_DEPENDENCIES = $(libdiffutils_a_LIBADD) X XDISTCLEANFILES = fnmatch.h fnmatch.hno regex.h regex.hno END-of-contrib/diff/lib/Makefile.am echo x - contrib/diff/lib/alloca.c sed 's/^X//' >contrib/diff/lib/alloca.c << 'END-of-contrib/diff/lib/alloca.c' X/* alloca.c -- allocate automatically reclaimed memory X (Mostly) portable public-domain implementation -- D A Gwyn X X This implementation of the PWB library alloca function, X which is used to allocate space off the run-time stack so X that it is automatically reclaimed upon procedure exit, X was inspired by discussions with J. Q. Johnson of Cornell. X J.Otto Tennant contributed the Cray support. X X There are some preprocessor constants that can X be defined when compiling for your specific system, for X improved efficiency; however, the defaults should be okay. X X The general concept of this implementation is to keep X track of all alloca-allocated blocks, and reclaim any X that are found to be deeper in the stack than the current X invocation. This heuristic does not reclaim storage as X soon as it becomes invalid, but it will do so eventually. X X As a special case, alloca(0) reclaims storage without X allocating any. It is a good idea to use alloca(0) in X your main control loop, etc. to force garbage collection. */ X X#ifdef HAVE_CONFIG_H X# include X#endif X X#if HAVE_STRING_H X# include X#endif X#if HAVE_STDLIB_H X# include X#endif X X#ifdef emacs X# include "blockinput.h" X#endif X X/* If compiling with GCC 2, this file's not needed. */ X#if !defined (__GNUC__) || __GNUC__ < 2 X X/* If someone has defined alloca as a macro, X there must be some other way alloca is supposed to work. */ X# ifndef alloca X X# ifdef emacs X# ifdef static X/* actually, only want this if static is defined as "" X -- this is for usg, in which emacs must undefine static X in order to make unexec workable X */ X# ifndef STACK_DIRECTION Xyou Xlose X-- must know STACK_DIRECTION at compile-time X# endif /* STACK_DIRECTION undefined */ X# endif /* static */ X# endif /* emacs */ X X/* If your stack is a linked list of frames, you have to X provide an "address metric" ADDRESS_FUNCTION macro. */ X X# if defined (CRAY) && defined (CRAY_STACKSEG_END) Xlong i00afunc (); X# define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg)) X# else X# define ADDRESS_FUNCTION(arg) &(arg) X# endif X X# if __STDC__ Xtypedef void *pointer; X# else Xtypedef char *pointer; X# endif X X# ifndef NULL X# define NULL 0 X# endif X X/* Different portions of Emacs need to call different versions of X malloc. The Emacs executable needs alloca to call xmalloc, because X ordinary malloc isn't protected from input signals. On the other X hand, the utilities in lib-src need alloca to call malloc; some of X them are very simple, and don't have an xmalloc routine. X X Non-Emacs programs expect this to call xmalloc. X X Callers below should use malloc. */ X X# ifndef emacs X# undef malloc X# define malloc xmalloc X# endif Xextern pointer malloc (); X X/* Define STACK_DIRECTION if you know the direction of stack X growth for your system; otherwise it will be automatically X deduced at run-time. X X STACK_DIRECTION > 0 => grows toward higher addresses X STACK_DIRECTION < 0 => grows toward lower addresses X STACK_DIRECTION = 0 => direction of growth unknown */ X X# ifndef STACK_DIRECTION X# define STACK_DIRECTION 0 /* Direction unknown. */ X# endif X X# if STACK_DIRECTION != 0 X X# define STACK_DIR STACK_DIRECTION /* Known at compile-time. */ X X# else /* STACK_DIRECTION == 0; need run-time code. */ X Xstatic int stack_dir; /* 1 or -1 once known. */ X# define STACK_DIR stack_dir X Xstatic void Xfind_stack_direction () X{ X static char *addr = NULL; /* Address of first `dummy', once known. */ X auto char dummy; /* To get stack address. */ X X if (addr == NULL) X { /* Initial entry. */ X addr = ADDRESS_FUNCTION (dummy); X X find_stack_direction (); /* Recurse once. */ X } X else X { X /* Second entry. */ X if (ADDRESS_FUNCTION (dummy) > addr) X stack_dir = 1; /* Stack grew upward. */ X else X stack_dir = -1; /* Stack grew downward. */ X } X} X X# endif /* STACK_DIRECTION == 0 */ X X/* An "alloca header" is used to: X (a) chain together all alloca'ed blocks; X (b) keep track of stack depth. X X It is very important that sizeof(header) agree with malloc X alignment chunk size. The following default should work okay. */ X X# ifndef ALIGN_SIZE X# define ALIGN_SIZE sizeof(double) X# endif X Xtypedef union hdr X{ X char align[ALIGN_SIZE]; /* To force sizeof(header). */ X struct X { X union hdr *next; /* For chaining headers. */ X char *deep; /* For stack depth measure. */ X } h; X} header; X Xstatic header *last_alloca_header = NULL; /* -> last alloca header. */ X X/* Return a pointer to at least SIZE bytes of storage, X which will be automatically reclaimed upon exit from X the procedure that called alloca. Originally, this space X was supposed to be taken from the current stack frame of the X caller, but that method cannot be made to work for some X implementations of C, for example under Gould's UTX/32. */ X Xpointer Xalloca (size_t size) X{ X auto char probe; /* Probes stack depth: */ X register char *depth = ADDRESS_FUNCTION (probe); X X# if STACK_DIRECTION == 0 X if (STACK_DIR == 0) /* Unknown growth direction. */ X find_stack_direction (); X# endif X X /* Reclaim garbage, defined as all alloca'd storage that X was allocated from deeper in the stack than currently. */ X X { X register header *hp; /* Traverses linked list. */ X X# ifdef emacs X BLOCK_INPUT; X# endif X X for (hp = last_alloca_header; hp != NULL;) X if ((STACK_DIR > 0 && hp->h.deep > depth) X || (STACK_DIR < 0 && hp->h.deep < depth)) X { X register header *np = hp->h.next; X X free ((pointer) hp); /* Collect garbage. */ X X hp = np; /* -> next header. */ X } X else X break; /* Rest are not deeper. */ X X last_alloca_header = hp; /* -> last valid storage. */ X X# ifdef emacs X UNBLOCK_INPUT; X# endif X } X X if (size == 0) X return NULL; /* No allocation required. */ X X /* Allocate combined header + user data storage. */ X X { X register pointer new = malloc (sizeof (header) + size); X /* Address of header. */ X X if (new == 0) X abort(); X X ((header *) new)->h.next = last_alloca_header; X ((header *) new)->h.deep = depth; X X last_alloca_header = (header *) new; X X /* User storage begins just after header. */ X X return (pointer) ((char *) new + sizeof (header)); X } X} X X# if defined (CRAY) && defined (CRAY_STACKSEG_END) X X# ifdef DEBUG_I00AFUNC X# include X# endif X X# ifndef CRAY_STACK X# define CRAY_STACK X# ifndef CRAY2 X/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */ Xstruct stack_control_header X { X long shgrow:32; /* Number of times stack has grown. */ X long shaseg:32; /* Size of increments to stack. */ X long shhwm:32; /* High water mark of stack. */ X long shsize:32; /* Current size of stack (all segments). */ X }; X X/* The stack segment linkage control information occurs at X the high-address end of a stack segment. (The stack X grows from low addresses to high addresses.) The initial X part of the stack segment linkage control information is X 0200 (octal) words. This provides for register storage X for the routine which overflows the stack. */ X Xstruct stack_segment_linkage X { X long ss[0200]; /* 0200 overflow words. */ X long sssize:32; /* Number of words in this segment. */ X long ssbase:32; /* Offset to stack base. */ X long:32; X long sspseg:32; /* Offset to linkage control of previous X segment of stack. */ X long:32; X long sstcpt:32; /* Pointer to task common address block. */ X long sscsnm; /* Private control structure number for X microtasking. */ X long ssusr1; /* Reserved for user. */ X long ssusr2; /* Reserved for user. */ X long sstpid; /* Process ID for pid based multi-tasking. */ X long ssgvup; /* Pointer to multitasking thread giveup. */ X long sscray[7]; /* Reserved for Cray Research. */ X long ssa0; X long ssa1; X long ssa2; X long ssa3; X long ssa4; X long ssa5; X long ssa6; X long ssa7; X long sss0; X long sss1; X long sss2; X long sss3; X long sss4; X long sss5; X long sss6; X long sss7; X }; X X# else /* CRAY2 */ X/* The following structure defines the vector of words X returned by the STKSTAT library routine. */ Xstruct stk_stat X { X long now; /* Current total stack size. */ X long maxc; /* Amount of contiguous space which would X be required to satisfy the maximum X stack demand to date. */ X long high_water; /* Stack high-water mark. */ X long overflows; /* Number of stack overflow ($STKOFEN) calls. */ X long hits; /* Number of internal buffer hits. */ X long extends; /* Number of block extensions. */ X long stko_mallocs; /* Block allocations by $STKOFEN. */ X long underflows; /* Number of stack underflow calls ($STKRETN). */ X long stko_free; /* Number of deallocations by $STKRETN. */ X long stkm_free; /* Number of deallocations by $STKMRET. */ X long segments; /* Current number of stack segments. */ X long maxs; /* Maximum number of stack segments so far. */ X long pad_size; /* Stack pad size. */ X long current_address; /* Current stack segment address. */ X long current_size; /* Current stack segment size. This X number is actually corrupted by STKSTAT to X include the fifteen word trailer area. */ X long initial_address; /* Address of initial segment. */ X long initial_size; /* Size of initial segment. */ X }; X X/* The following structure describes the data structure which trails X any stack segment. I think that the description in 'asdef' is X out of date. I only describe the parts that I am sure about. */ X Xstruct stk_trailer X { X long this_address; /* Address of this block. */ X long this_size; /* Size of this block (does not include X this trailer). */ X long unknown2; X long unknown3; X long link; /* Address of trailer block of previous X segment. */ X long unknown5; X long unknown6; X long unknown7; X long unknown8; X long unknown9; X long unknown10; X long unknown11; X long unknown12; X long unknown13; X long unknown14; X }; X X# endif /* CRAY2 */ X# endif /* not CRAY_STACK */ X X# ifdef CRAY2 X/* Determine a "stack measure" for an arbitrary ADDRESS. X I doubt that "lint" will like this much. */ X Xstatic long Xi00afunc (long *address) X{ X struct stk_stat status; X struct stk_trailer *trailer; X long *block, size; X long result = 0; X X /* We want to iterate through all of the segments. The first X step is to get the stack status structure. We could do this X more quickly and more directly, perhaps, by referencing the X $LM00 common block, but I know that this works. */ X X STKSTAT (&status); X X /* Set up the iteration. */ X X trailer = (struct stk_trailer *) (status.current_address X + status.current_size X - 15); X X /* There must be at least one stack segment. Therefore it is X a fatal error if "trailer" is null. */ X X if (trailer == 0) X abort (); X X /* Discard segments that do not contain our argument address. */ X X while (trailer != 0) X { X block = (long *) trailer->this_address; X size = trailer->this_size; X if (block == 0 || size == 0) X abort (); X trailer = (struct stk_trailer *) trailer->link; X if ((block <= address) && (address < (block + size))) X break; X } X X /* Set the result to the offset in this segment and add the sizes X of all predecessor segments. */ X X result = address - block; X X if (trailer == 0) X { X return result; X } X X do X { X if (trailer->this_size <= 0) X abort (); X result += trailer->this_size; X trailer = (struct stk_trailer *) trailer->link; X } X while (trailer != 0); X X /* We are done. Note that if you present a bogus address (one X not in any segment), you will get a different number back, formed X from subtracting the address of the first block. This is probably X not what you want. */ X X return (result); X} X X# else /* not CRAY2 */ X/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP. X Determine the number of the cell within the stack, X given the address of the cell. The purpose of this X routine is to linearize, in some sense, stack addresses X for alloca. */ X Xstatic long Xi00afunc (long address) X{ X long stkl = 0; X X long size, pseg, this_segment, stack; X long result = 0; X X struct stack_segment_linkage *ssptr; X X /* Register B67 contains the address of the end of the X current stack segment. If you (as a subprogram) store X your registers on the stack and find that you are past X the contents of B67, you have overflowed the segment. X X B67 also points to the stack segment linkage control X area, which is what we are really interested in. */ X X stkl = CRAY_STACKSEG_END (); X ssptr = (struct stack_segment_linkage *) stkl; X X /* If one subtracts 'size' from the end of the segment, X one has the address of the first word of the segment. X X If this is not the first segment, 'pseg' will be X nonzero. */ X X pseg = ssptr->sspseg; X size = ssptr->sssize; X X this_segment = stkl - size; X X /* It is possible that calling this routine itself caused X a stack overflow. Discard stack segments which do not X contain the target address. */ X X while (!(this_segment <= address && address <= stkl)) X { X# ifdef DEBUG_I00AFUNC X fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl); X# endif X if (pseg == 0) X break; X stkl = stkl - pseg; X ssptr = (struct stack_segment_linkage *) stkl; X size = ssptr->sssize; X pseg = ssptr->sspseg; X this_segment = stkl - size; X } X X result = address - this_segment; X X /* If you subtract pseg from the current end of the stack, X you get the address of the previous stack segment's end. X This seems a little convoluted to me, but I'll bet you save X a cycle somewhere. */ X X while (pseg != 0) X { X# ifdef DEBUG_I00AFUNC X fprintf (stderr, "%011o %011o\n", pseg, size); X# endif X stkl = stkl - pseg; X ssptr = (struct stack_segment_linkage *) stkl; X size = ssptr->sssize; X pseg = ssptr->sspseg; X result += size; X } X return (result); X} X X# endif /* not CRAY2 */ X# endif /* CRAY */ X X# endif /* no alloca */ X#endif /* not GCC version 2 */ END-of-contrib/diff/lib/alloca.c echo x - contrib/diff/lib/fnmatch.c sed 's/^X//' >contrib/diff/lib/fnmatch.c << 'END-of-contrib/diff/lib/fnmatch.c' X/* Copyright 1991, 1992, 1993, 1996, 1997, 2000 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software Foundation, X Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#if HAVE_CONFIG_H X# include X#endif X X/* Enable GNU extensions in fnmatch.h. */ X#ifndef _GNU_SOURCE X# define _GNU_SOURCE 1 X#endif X X#include X#include X#include X X#if defined STDC_HEADERS || !defined isascii X# define IN_CTYPE_DOMAIN(c) 1 X#else X# define IN_CTYPE_DOMAIN(c) isascii (c) X#endif X X#define ISUPPER(c) (IN_CTYPE_DOMAIN (c) && isupper (c)) X X X#ifndef errno Xextern int errno; X#endif X X/* Match STRING against the filename pattern PATTERN, returning zero if X it matches, nonzero if not. */ Xint Xfnmatch (const char *pattern, const char *string, int flags) X{ X register const char *p = pattern, *n = string; X register char c; X X/* Note that this evaluates C many times. */ X#define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER ((unsigned char) (c)) \ X ? tolower ((unsigned char) (c)) \ X : (c)) X X while ((c = *p++) != '\0') X { X c = FOLD (c); X X switch (c) X { X case '?': X if (*n == '\0') X return FNM_NOMATCH; X else if ((flags & FNM_FILE_NAME) && *n == '/') X return FNM_NOMATCH; X else if ((flags & FNM_PERIOD) && *n == '.' && X (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) X return FNM_NOMATCH; X break; X X case '\\': X if (!(flags & FNM_NOESCAPE)) X { X c = *p++; X if (c == '\0') X /* Trailing \ loses. */ X return FNM_NOMATCH; X c = FOLD (c); X } X if (FOLD (*n) != c) X return FNM_NOMATCH; X break; X X case '*': X if ((flags & FNM_PERIOD) && *n == '.' && X (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) X return FNM_NOMATCH; X X for (c = *p++; c == '?' || c == '*'; c = *p++) X { X if (c == '?') X { X /* A ? needs to match one character. */ X if (*n == '\0' || (*n == '/' && (flags & FNM_FILE_NAME))) X /* There isn't another character; no match. */ X return FNM_NOMATCH; X else X /* One character of the string is consumed in matching X this ? wildcard, so *??? won't match if there are X less than three characters. */ X ++n; X } X } X X if (c == '\0') X { X if ((flags & (FNM_FILE_NAME | FNM_LEADING_DIR)) == FNM_FILE_NAME) X for (; *n != '\0'; n++) X if (*n == '/') X return FNM_NOMATCH; X return 0; X } X X { X char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c; X c1 = FOLD (c1); X for (--p; *n != '\0'; ++n) X if ((c == '[' || FOLD (*n) == c1) && X fnmatch (p, n, flags & ~FNM_PERIOD) == 0) X return 0; X else if (*n == '/' && (flags & FNM_FILE_NAME)) X break; X return FNM_NOMATCH; X } X X case '[': X { X /* Nonzero if the sense of the character class is inverted. */ X register int not; X X if (*n == '\0') X return FNM_NOMATCH; X X if ((flags & FNM_PERIOD) && *n == '.' && X (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) X return FNM_NOMATCH; X X not = (*p == '!' || *p == '^'); X if (not) X ++p; X X c = *p++; X for (;;) X { X register char cstart = c, cend = c; X X if (!(flags & FNM_NOESCAPE) && c == '\\') X { X if (*p == '\0') X return FNM_NOMATCH; X cstart = cend = *p++; X } X X cstart = cend = FOLD (cstart); X X if (c == '\0') X /* [ (unterminated) loses. */ X return FNM_NOMATCH; X X c = *p++; X c = FOLD (c); X X if ((flags & FNM_FILE_NAME) && c == '/') X /* [/] can never match. */ X return FNM_NOMATCH; X X if (c == '-' && *p != ']') X { X cend = *p++; X if (!(flags & FNM_NOESCAPE) && cend == '\\') X cend = *p++; X if (cend == '\0') X return FNM_NOMATCH; X cend = FOLD (cend); X X c = *p++; X } X X if (FOLD (*n) >= cstart && FOLD (*n) <= cend) X goto matched; X X if (c == ']') X break; X } X if (!not) X return FNM_NOMATCH; X break; X X matched:; X /* Skip the rest of the [...] that already matched. */ X while (c != ']') X { X if (c == '\0') X /* [... (unterminated) loses. */ X return FNM_NOMATCH; X X c = *p++; X if (!(flags & FNM_NOESCAPE) && c == '\\') X { X if (*p == '\0') X return FNM_NOMATCH; X /* XXX 1003.2d11 is unclear if this is right. */ X ++p; X } X } X if (not) X return FNM_NOMATCH; X } X break; X X default: X if (c != FOLD (*n)) X return FNM_NOMATCH; X } X X ++n; X } X X if (*n == '\0') X return 0; X X if ((flags & FNM_LEADING_DIR) && *n == '/') X /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ X return 0; X X return FNM_NOMATCH; X X#undef FOLD X} END-of-contrib/diff/lib/fnmatch.c echo x - contrib/diff/lib/malloc.c sed 's/^X//' >contrib/diff/lib/malloc.c << 'END-of-contrib/diff/lib/malloc.c' X/* Work around bug on some systems where malloc (0) fails. X Copyright (C) 1997, 1998 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software Foundation, X Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X/* written by Jim Meyering */ X X#if HAVE_CONFIG_H X# include X#endif X#undef malloc X X#include X Xchar *malloc (); X X/* Allocate an N-byte block of memory from the heap. X If N is zero, allocate a 1-byte block. */ X Xchar * Xrpl_malloc (size_t n) X{ X if (n == 0) X n = 1; X return malloc (n); X} END-of-contrib/diff/lib/malloc.c echo x - contrib/diff/lib/memchr.c sed 's/^X//' >contrib/diff/lib/memchr.c << 'END-of-contrib/diff/lib/memchr.c' X/* Copyright (C) 1991,93,96,97,99,2000 Free Software Foundation, Inc. X Based on strlen implementation by Torbjorn Granlund (tege@sics.se), X with help from Dan Sahlin (dan@sics.se) and X commentary by Jim Blandy (jimb@ai.mit.edu); X adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu), X and implemented by Roland McGrath (roland@ai.mit.edu). X XNOTE: The canonical source of this file is maintained with the GNU C Library. XBugs can be reported to bug-glibc@prep.ai.mit.edu. X XThis program is free software; you can redistribute it and/or modify it Xunder the terms of the GNU General Public License as published by the XFree Software Foundation; either version 2, or (at your option) any Xlater version. X XThis program is distributed in the hope that it will be useful, Xbut WITHOUT ANY WARRANTY; without even the implied warranty of XMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the XGNU General Public License for more details. X XYou should have received a copy of the GNU General Public License Xalong with this program; if not, write to the Free Software XFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, XUSA. */ X X#ifdef HAVE_CONFIG_H X# include X#endif X X#undef __ptr_t X#if defined (__cplusplus) || (defined (__STDC__) && __STDC__) X# define __ptr_t void * X#else /* Not C++ or ANSI C. */ X# define __ptr_t char * X#endif /* C++ or ANSI C. */ X X#if defined _LIBC X# include X# include X#else X# define reg_char char X#endif X X#if HAVE_STDLIB_H || defined _LIBC X# include X#endif X X#if HAVE_LIMITS_H || defined _LIBC X# include X#endif X X#define LONG_MAX_32_BITS 2147483647 X X#ifndef LONG_MAX X# define LONG_MAX LONG_MAX_32_BITS X#endif X X#include X#if HAVE_BP_SYM_H || defined _LIBC X# include X#else X# define BP_SYM(sym) sym X#endif X X#undef memchr X#undef __memchr X X/* Search no more than N bytes of S for C. */ X__ptr_t X__memchr (s, c_in, n) X const __ptr_t s; X int c_in; X size_t n; X{ X const unsigned char *char_ptr; X const unsigned long int *longword_ptr; X unsigned long int longword, magic_bits, charmask; X unsigned reg_char c; X X c = (unsigned char) c_in; X X /* Handle the first few characters by reading one character at a time. X Do this until CHAR_PTR is aligned on a longword boundary. */ X for (char_ptr = (const unsigned char *) s; X n > 0 && ((unsigned long int) char_ptr X & (sizeof (longword) - 1)) != 0; X --n, ++char_ptr) X if (*char_ptr == c) X return (__ptr_t) char_ptr; X X /* All these elucidatory comments refer to 4-byte longwords, X but the theory applies equally well to 8-byte longwords. */ X X longword_ptr = (unsigned long int *) char_ptr; X X /* Bits 31, 24, 16, and 8 of this number are zero. Call these bits X the "holes." Note that there is a hole just to the left of X each byte, with an extra at the end: X X bits: 01111110 11111110 11111110 11111111 X bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD X X The 1-bits make sure that carries propagate to the next 0-bit. X The 0-bits provide holes for carries to fall into. */ X X if (sizeof (longword) != 4 && sizeof (longword) != 8) X abort (); X X#if LONG_MAX <= LONG_MAX_32_BITS X magic_bits = 0x7efefeff; X#else X magic_bits = ((unsigned long int) 0x7efefefe << 32) | 0xfefefeff; X#endif X X /* Set up a longword, each of whose bytes is C. */ X charmask = c | (c << 8); X charmask |= charmask << 16; X#if LONG_MAX > LONG_MAX_32_BITS X charmask |= charmask << 32; X#endif X X /* Instead of the traditional loop which tests each character, X we will test a longword at a time. The tricky part is testing X if *any of the four* bytes in the longword in question are zero. */ X while (n >= sizeof (longword)) X { X /* We tentatively exit the loop if adding MAGIC_BITS to X LONGWORD fails to change any of the hole bits of LONGWORD. X X 1) Is this safe? Will it catch all the zero bytes? X Suppose there is a byte with all zeros. Any carry bits X propagating from its left will fall into the hole at its X least significant bit and stop. Since there will be no X carry from its most significant bit, the LSB of the X byte to the left will be unchanged, and the zero will be X detected. X X 2) Is this worthwhile? Will it ignore everything except X zero bytes? Suppose every byte of LONGWORD has a bit set X somewhere. There will be a carry into bit 8. If bit 8 X is set, this will carry into bit 16. If bit 8 is clear, X one of bits 9-15 must be set, so there will be a carry X into bit 16. Similarly, there will be a carry into bit X 24. If one of bits 24-30 is set, there will be a carry X into bit 31, so all of the hole bits will be changed. X X The one misfire occurs when bits 24-30 are clear and bit X 31 is set; in this case, the hole at bit 31 is not X changed. If we had access to the processor carry flag, X we could close this loophole by putting the fourth hole X at bit 32! X X So it ignores everything except 128's, when they're aligned X properly. X X 3) But wait! Aren't we looking for C, not zero? X Good point. So what we do is XOR LONGWORD with a longword, X each of whose bytes is C. This turns each byte that is C X into a zero. */ X X longword = *longword_ptr++ ^ charmask; X X /* Add MAGIC_BITS to LONGWORD. */ X if ((((longword + magic_bits) X X /* Set those bits that were unchanged by the addition. */ X ^ ~longword) X X /* Look at only the hole bits. If any of the hole bits X are unchanged, most likely one of the bytes was a X zero. */ X & ~magic_bits) != 0) X { X /* Which of the bytes was C? If none of them were, it was X a misfire; continue the search. */ X X const unsigned char *cp = (const unsigned char *) (longword_ptr - 1); X X if (cp[0] == c) X return (__ptr_t) cp; X if (cp[1] == c) X return (__ptr_t) &cp[1]; X if (cp[2] == c) X return (__ptr_t) &cp[2]; X if (cp[3] == c) X return (__ptr_t) &cp[3]; X#if LONG_MAX > 2147483647 X if (cp[4] == c) X return (__ptr_t) &cp[4]; X if (cp[5] == c) X return (__ptr_t) &cp[5]; X if (cp[6] == c) X return (__ptr_t) &cp[6]; X if (cp[7] == c) X return (__ptr_t) &cp[7]; X#endif X } X X n -= sizeof (longword); X } X X char_ptr = (const unsigned char *) longword_ptr; X X while (n-- > 0) X { X if (*char_ptr == c) X return (__ptr_t) char_ptr; X else X ++char_ptr; X } X X return 0; X} X#ifdef weak_alias Xweak_alias (__memchr, BP_SYM (memchr)) X#endif END-of-contrib/diff/lib/memchr.c echo x - contrib/diff/lib/mkstemp.c sed 's/^X//' >contrib/diff/lib/mkstemp.c << 'END-of-contrib/diff/lib/mkstemp.c' X/* Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. X This file is derived from the one in the GNU C Library. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software Foundation, X Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#include X X/* Disable the definition of mkstemp to rpl_mkstemp (from config.h) in this X file. Otherwise, we'd get conflicting prototypes for rpl_mkstemp on X most systems. */ X#undef mkstemp X X#include X#include X X#ifndef __GT_FILE X# define __GT_FILE 0 X#endif X Xint __gen_tempname (); X X/* Generate a unique temporary file name from TEMPLATE. X The last six characters of TEMPLATE must be "XXXXXX"; X they are replaced with a string that makes the filename unique. X Then open the file and return a fd. */ Xint Xrpl_mkstemp (char *template) X{ X return __gen_tempname (template, __GT_FILE); X} END-of-contrib/diff/lib/mkstemp.c echo x - contrib/diff/lib/realloc.c sed 's/^X//' >contrib/diff/lib/realloc.c << 'END-of-contrib/diff/lib/realloc.c' X/* Work around bug on some systems where realloc (NULL, 0) fails. X Copyright (C) 1997 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software Foundation, X Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X/* written by Jim Meyering */ X X#if HAVE_CONFIG_H X# include X#endif X#undef realloc X X#include X Xchar *malloc (); Xchar *realloc (); X X/* Change the size of an allocated block of memory P to N bytes, X with error checking. If N is zero, change it to 1. If P is NULL, X use malloc. */ X Xchar * Xrpl_realloc (p, n) X char *p; X size_t n; X{ X if (n == 0) X n = 1; X if (p == 0) X return malloc (n); X return realloc (p, n); X} END-of-contrib/diff/lib/realloc.c echo x - contrib/diff/lib/regex.c sed 's/^X//' >contrib/diff/lib/regex.c << 'END-of-contrib/diff/lib/regex.c' X/* Extended regular expression matching and search library, X version 0.12. X (Implements POSIX draft P1003.2/D11.2, except for some of the X internationalization features.) X Copyright (C) 1993-1999, 2000, 2001 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software Foundation, X Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X/* AIX requires this to be the first thing in the file. */ X#if defined _AIX && !defined REGEX_MALLOC X #pragma alloca X#endif X X#undef _GNU_SOURCE X#define _GNU_SOURCE X X#ifdef HAVE_CONFIG_H X# include X#endif X X#ifndef PARAMS X# if defined __GNUC__ || (defined __STDC__ && __STDC__) X# define PARAMS(args) args X# else X# define PARAMS(args) () X# endif /* GCC. */ X#endif /* Not PARAMS. */ X X#ifndef INSIDE_RECURSION X X# if defined STDC_HEADERS && !defined emacs X# include X# else X/* We need this for `regex.h', and perhaps for the Emacs include files. */ X# include X# endif X X# define WIDE_CHAR_SUPPORT (HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_BTOWC) X X/* For platform which support the ISO C amendement 1 functionality we X support user defined character classes. */ X# if defined _LIBC || WIDE_CHAR_SUPPORT X/* Solaris 2.5 has a bug: must be included before . */ X# include X# include X# endif X X# ifdef _LIBC X/* We have to keep the namespace clean. */ X# define regfree(preg) __regfree (preg) X# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef) X# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags) X# define regerror(errcode, preg, errbuf, errbuf_size) \ X __regerror(errcode, preg, errbuf, errbuf_size) X# define re_set_registers(bu, re, nu, st, en) \ X __re_set_registers (bu, re, nu, st, en) X# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \ X __re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) X# define re_match(bufp, string, size, pos, regs) \ X __re_match (bufp, string, size, pos, regs) X# define re_search(bufp, string, size, startpos, range, regs) \ X __re_search (bufp, string, size, startpos, range, regs) X# define re_compile_pattern(pattern, length, bufp) \ X __re_compile_pattern (pattern, length, bufp) X# define re_set_syntax(syntax) __re_set_syntax (syntax) X# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \ X __re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop) X# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp) X X# define btowc __btowc X# define iswctype __iswctype X# define mbrtowc __mbrtowc X# define wcslen __wcslen X# define wcscoll __wcscoll X# define wcrtomb __wcrtomb X X/* We are also using some library internals. */ X# include X# include X# include X# include X# endif X X/* This is for other GNU distributions with internationalized messages. */ X# if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC X# include X# ifdef _LIBC X# undef gettext X# define gettext(msgid) __dcgettext ("libc", msgid, LC_MESSAGES) X# endif X# else X# define gettext(msgid) (msgid) X# endif X X# ifndef gettext_noop X/* This define is so xgettext can find the internationalizable X strings. */ X# define gettext_noop(String) String X# endif X X/* Support for bounded pointers. */ X# if !defined _LIBC && !defined __BOUNDED_POINTERS__ X# define __bounded /* nothing */ X# define __unbounded /* nothing */ X# define __ptrvalue /* nothing */ X# endif X X/* The `emacs' switch turns on certain matching commands X that make sense only in Emacs. */ X# ifdef emacs X X# include "lisp.h" X# include "buffer.h" X# include "syntax.h" X X# else /* not emacs */ X X/* If we are not linking with Emacs proper, X we can't use the relocating allocator X even if config.h says that we can. */ X# undef REL_ALLOC X X# if defined STDC_HEADERS || defined _LIBC X# include X# else Xchar *malloc (); Xchar *realloc (); X# endif X X/* When used in Emacs's lib-src, we need to get bzero and bcopy somehow. X If nothing else has been done, use the method below. */ X# ifdef INHIBIT_STRING_HEADER X# if !(defined HAVE_BZERO && defined HAVE_BCOPY) X# if !defined bzero && !defined bcopy X# undef INHIBIT_STRING_HEADER X# endif X# endif X# endif X X/* This is the normal way of making sure we have a bcopy and a bzero. X This is used in most programs--a few other programs avoid this X by defining INHIBIT_STRING_HEADER. */ X# ifndef INHIBIT_STRING_HEADER X# if defined HAVE_STRING_H || defined STDC_HEADERS || defined _LIBC X# include X# ifndef bzero X# ifndef _LIBC X# define bzero(s, n) (memset (s, '\0', n), (s)) X# else X# define bzero(s, n) __bzero (s, n) X# endif X# endif X# else X# include X# ifndef memcmp X# define memcmp(s1, s2, n) bcmp (s1, s2, n) X# endif X# ifndef memcpy X# define memcpy(d, s, n) (bcopy (s, d, n), (d)) X# endif X# endif X# endif X X/* Define the syntax stuff for \<, \>, etc. */ X X/* This must be nonzero for the wordchar and notwordchar pattern X commands in re_match_2. */ X# ifndef Sword X# define Sword 1 X# endif X X# ifdef SWITCH_ENUM_BUG X# define SWITCH_ENUM_CAST(x) ((int)(x)) X# else X# define SWITCH_ENUM_CAST(x) (x) X# endif X X# endif /* not emacs */ X X# if defined _LIBC || HAVE_LIMITS_H X# include X# endif X X# ifndef MB_LEN_MAX X# define MB_LEN_MAX 1 X# endif X X/* Get the interface, including the syntax bits. */ X# include X X/* isalpha etc. are used for the character classes. */ X# include X X/* Jim Meyering writes: X X "... Some ctype macros are valid only for character codes that X isascii says are ASCII (SGI's IRIX-4.0.5 is one such system --when X using /bin/cc or gcc but without giving an ansi option). So, all X ctype uses should be through macros like ISPRINT... If X STDC_HEADERS is defined, then autoconf has verified that the ctype X macros don't need to be guarded with references to isascii. ... X Defining isascii to 1 should let any compiler worth its salt X eliminate the && through constant folding." X Solaris defines some of these symbols so we must undefine them first. */ X X# if defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII) X# define IN_CTYPE_DOMAIN(c) 1 X# else X# define IN_CTYPE_DOMAIN(c) isascii(c) X# endif X X# ifdef isblank X# define ISBLANK(c) (IN_CTYPE_DOMAIN (c) && isblank (c)) X# else X# define ISBLANK(c) ((c) == ' ' || (c) == '\t') X# endif X# ifdef isgraph X# define ISGRAPH(c) (IN_CTYPE_DOMAIN (c) && isgraph (c)) X# else X# define ISGRAPH(c) (IN_CTYPE_DOMAIN (c) && isprint (c) && !isspace (c)) X# endif X X# undef ISPRINT X# define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint (c)) X# define ISDIGIT(c) (IN_CTYPE_DOMAIN (c) && isdigit (c)) X# define ISALNUM(c) (IN_CTYPE_DOMAIN (c) && isalnum (c)) X# define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha (c)) X# define ISCNTRL(c) (IN_CTYPE_DOMAIN (c) && iscntrl (c)) X# define ISLOWER(c) (IN_CTYPE_DOMAIN (c) && islower (c)) X# define ISPUNCT(c) (IN_CTYPE_DOMAIN (c) && ispunct (c)) X# define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c)) X# define ISUPPER(c) (IN_CTYPE_DOMAIN (c) && isupper (c)) X# define ISXDIGIT(c) (IN_CTYPE_DOMAIN (c) && isxdigit (c)) X X# ifdef _tolower X# define TOLOWER(c) _tolower(c) X# else X# define TOLOWER(c) tolower(c) X# endif X X# ifndef NULL X# define NULL (void *)0 X# endif X X/* We remove any previous definition of `SIGN_EXTEND_CHAR', X since ours (we hope) works properly with all combinations of X machines, compilers, `char' and `unsigned char' argument types. X (Per Bothner suggested the basic approach.) */ X# undef SIGN_EXTEND_CHAR X# if __STDC__ X# define SIGN_EXTEND_CHAR(c) ((signed char) (c)) X# else /* not __STDC__ */ X/* As in Harbison and Steele. */ X# define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128) X# endif X X# ifndef emacs X/* How many characters in the character set. */ X# define CHAR_SET_SIZE 256 X X# ifdef SYNTAX_TABLE X Xextern char *re_syntax_table; X X# else /* not SYNTAX_TABLE */ X Xstatic char re_syntax_table[CHAR_SET_SIZE]; X Xstatic void init_syntax_once PARAMS ((void)); X Xstatic void Xinit_syntax_once () X{ X register int c; X static int done = 0; X X if (done) X return; X bzero (re_syntax_table, sizeof re_syntax_table); X X for (c = 0; c < CHAR_SET_SIZE; ++c) X if (ISALNUM (c)) X re_syntax_table[c] = Sword; X X re_syntax_table['_'] = Sword; X X done = 1; X} X X# endif /* not SYNTAX_TABLE */ X X# define SYNTAX(c) re_syntax_table[(unsigned char) (c)] X X# endif /* emacs */ X X/* Should we use malloc or alloca? If REGEX_MALLOC is not defined, we X use `alloca' instead of `malloc'. This is because using malloc in X re_search* or re_match* could cause memory leaks when C-g is used in X Emacs; also, malloc is slower and causes storage fragmentation. On X the other hand, malloc is more portable, and easier to debug. X X Because we sometimes use alloca, some routines have to be macros, X not functions -- `alloca'-allocated space disappears at the end of the X function it is called in. */ X X# ifdef REGEX_MALLOC X X# define REGEX_ALLOCATE malloc X# define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize) X# define REGEX_FREE free X X# else /* not REGEX_MALLOC */ X X/* Emacs already defines alloca, sometimes. */ X# ifndef alloca X X/* Make alloca work the best possible way. */ X# ifdef __GNUC__ X# define alloca __builtin_alloca X# else /* not __GNUC__ */ X# if HAVE_ALLOCA_H X# include X# endif /* HAVE_ALLOCA_H */ X# endif /* not __GNUC__ */ X X# endif /* not alloca */ X X# define REGEX_ALLOCATE alloca X X/* Assumes a `char *destination' variable. */ X# define REGEX_REALLOCATE(source, osize, nsize) \ X (destination = (char *) alloca (nsize), \ X memcpy (destination, source, osize)) X X/* No need to do anything to free, after alloca. */ X# define REGEX_FREE(arg) ((void)0) /* Do nothing! But inhibit gcc warning. */ X X# endif /* not REGEX_MALLOC */ X X/* Define how to allocate the failure stack. */ X X# if defined REL_ALLOC && defined REGEX_MALLOC X X# define REGEX_ALLOCATE_STACK(size) \ X r_alloc (&failure_stack_ptr, (size)) X# define REGEX_REALLOCATE_STACK(source, osize, nsize) \ X r_re_alloc (&failure_stack_ptr, (nsize)) X# define REGEX_FREE_STACK(ptr) \ X r_alloc_free (&failure_stack_ptr) X X# else /* not using relocating allocator */ X X# ifdef REGEX_MALLOC X X# define REGEX_ALLOCATE_STACK malloc X# define REGEX_REALLOCATE_STACK(source, osize, nsize) realloc (source, nsize) X# define REGEX_FREE_STACK free X X# else /* not REGEX_MALLOC */ X X# define REGEX_ALLOCATE_STACK alloca X X# define REGEX_REALLOCATE_STACK(source, osize, nsize) \ X REGEX_REALLOCATE (source, osize, nsize) X/* No need to explicitly free anything. */ X# define REGEX_FREE_STACK(arg) X X# endif /* not REGEX_MALLOC */ X# endif /* not using relocating allocator */ X X X/* True if `size1' is non-NULL and PTR is pointing anywhere inside X `string1' or just past its end. This works if PTR is NULL, which is X a good thing. */ X# define FIRST_STRING_P(ptr) \ X (size1 && string1 <= (ptr) && (ptr) <= string1 + size1) X X/* (Re)Allocate N items of type T using malloc, or fail. */ X# define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t))) X# define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t))) X# define RETALLOC_IF(addr, n, t) \ X if (addr) RETALLOC((addr), (n), t); else (addr) = TALLOC ((n), t) X# define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t))) X X# define BYTEWIDTH 8 /* In bits. */ X X# define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) X X# undef MAX X# undef MIN X# define MAX(a, b) ((a) > (b) ? (a) : (b)) X# define MIN(a, b) ((a) < (b) ? (a) : (b)) X Xtypedef char boolean; X# define false 0 X# define true 1 X Xstatic reg_errcode_t byte_regex_compile _RE_ARGS ((const char *pattern, size_t size, X reg_syntax_t syntax, X struct re_pattern_buffer *bufp)); X Xstatic int byte_re_match_2_internal PARAMS ((struct re_pattern_buffer *bufp, X const char *string1, int size1, X const char *string2, int size2, X int pos, X struct re_registers *regs, X int stop)); Xstatic int byte_re_search_2 PARAMS ((struct re_pattern_buffer *bufp, X const char *string1, int size1, X const char *string2, int size2, X int startpos, int range, X struct re_registers *regs, int stop)); Xstatic int byte_re_compile_fastmap PARAMS ((struct re_pattern_buffer *bufp)); X X#ifdef MBS_SUPPORT Xstatic reg_errcode_t wcs_regex_compile _RE_ARGS ((const char *pattern, size_t size, X reg_syntax_t syntax, X struct re_pattern_buffer *bufp)); X X Xstatic int wcs_re_match_2_internal PARAMS ((struct re_pattern_buffer *bufp, X const char *cstring1, int csize1, X const char *cstring2, int csize2, X int pos, X struct re_registers *regs, X int stop, X wchar_t *string1, int size1, X wchar_t *string2, int size2, X int *mbs_offset1, int *mbs_offset2)); Xstatic int wcs_re_search_2 PARAMS ((struct re_pattern_buffer *bufp, X const char *string1, int size1, X const char *string2, int size2, X int startpos, int range, X struct re_registers *regs, int stop)); Xstatic int wcs_re_compile_fastmap PARAMS ((struct re_pattern_buffer *bufp)); X#endif X X/* These are the command codes that appear in compiled regular X expressions. Some opcodes are followed by argument bytes. A X command code can specify any interpretation whatsoever for its X arguments. Zero bytes may appear in the compiled regular expression. */ X Xtypedef enum X{ X no_op = 0, X X /* Succeed right away--no more backtracking. */ X succeed, X X /* Followed by one byte giving n, then by n literal bytes. */ X exactn, X X# ifdef MBS_SUPPORT X /* Same as exactn, but contains binary data. */ X exactn_bin, X# endif X X /* Matches any (more or less) character. */ X anychar, X X /* Matches any one char belonging to specified set. First X following byte is number of bitmap bytes. Then come bytes X for a bitmap saying which chars are in. Bits in each byte X are ordered low-bit-first. A character is in the set if its X bit is 1. A character too large to have a bit in the map is X automatically not in the set. */ X /* ifdef MBS_SUPPORT, following element is length of character X classes, length of collating symbols, length of equivalence X classes, length of character ranges, and length of characters. X Next, character class element, collating symbols elements, X equivalence class elements, range elements, and character X elements follow. X See regex_compile function. */ X charset, X X /* Same parameters as charset, but match any character that is X not one of those specified. */ X charset_not, X X /* Start remembering the text that is matched, for storing in a X register. Followed by one byte with the register number, in X the range 0 to one less than the pattern buffer's re_nsub X field. Then followed by one byte with the number of groups X inner to this one. (This last has to be part of the X start_memory only because we need it in the on_failure_jump X of re_match_2.) */ X start_memory, X X /* Stop remembering the text that is matched and store it in a X memory register. Followed by one byte with the register X number, in the range 0 to one less than `re_nsub' in the X pattern buffer, and one byte with the number of inner groups, X just like `start_memory'. (We need the number of inner X groups here because we don't have any easy way of finding the X corresponding start_memory when we're at a stop_memory.) */ X stop_memory, X X /* Match a duplicate of something remembered. Followed by one X byte containing the register number. */ X duplicate, X X /* Fail unless at beginning of line. */ X begline, X X /* Fail unless at end of line. */ X endline, X X /* Succeeds if at beginning of buffer (if emacs) or at beginning X of string to be matched (if not). */ X begbuf, X X /* Analogously, for end of buffer/string. */ X endbuf, X X /* Followed by two byte relative address to which to jump. */ X jump, X X /* Same as jump, but marks the end of an alternative. */ X jump_past_alt, X X /* Followed by two-byte relative address of place to resume at X in case of failure. */ X /* ifdef MBS_SUPPORT, the size of address is 1. */ X on_failure_jump, X X /* Like on_failure_jump, but pushes a placeholder instead of the X current string position when executed. */ X on_failure_keep_string_jump, X X /* Throw away latest failure point and then jump to following X two-byte relative address. */ X /* ifdef MBS_SUPPORT, the size of address is 1. */ X pop_failure_jump, X X /* Change to pop_failure_jump if know won't have to backtrack to X match; otherwise change to jump. This is used to jump X back to the beginning of a repeat. If what follows this jump X clearly won't match what the repeat does, such that we can be X sure that there is no use backtracking out of repetitions X already matched, then we change it to a pop_failure_jump. X Followed by two-byte address. */ X /* ifdef MBS_SUPPORT, the size of address is 1. */ X maybe_pop_jump, X X /* Jump to following two-byte address, and push a dummy failure X point. This failure point will be thrown away if an attempt X is made to use it for a failure. A `+' construct makes this X before the first repeat. Also used as an intermediary kind X of jump when compiling an alternative. */ X /* ifdef MBS_SUPPORT, the size of address is 1. */ X dummy_failure_jump, X X /* Push a dummy failure point and continue. Used at the end of X alternatives. */ X push_dummy_failure, X X /* Followed by two-byte relative address and two-byte number n. X After matching N times, jump to the address upon failure. */ X /* ifdef MBS_SUPPORT, the size of address is 1. */ X succeed_n, X X /* Followed by two-byte relative address, and two-byte number n. X Jump to the address N times, then fail. */ X /* ifdef MBS_SUPPORT, the size of address is 1. */ X jump_n, X X /* Set the following two-byte relative address to the X subsequent two-byte number. The address *includes* the two X bytes of number. */ X /* ifdef MBS_SUPPORT, the size of address is 1. */ X set_number_at, X X wordchar, /* Matches any word-constituent character. */ X notwordchar, /* Matches any char that is not a word-constituent. */ X X wordbeg, /* Succeeds if at word beginning. */ X wordend, /* Succeeds if at word end. */ X X wordbound, /* Succeeds if at a word boundary. */ X notwordbound /* Succeeds if not at a word boundary. */ X X# ifdef emacs X ,before_dot, /* Succeeds if before point. */ X at_dot, /* Succeeds if at point. */ X after_dot, /* Succeeds if after point. */ X X /* Matches any character whose syntax is specified. Followed by X a byte which contains a syntax code, e.g., Sword. */ X syntaxspec, X X /* Matches any character whose syntax is not that specified. */ X notsyntaxspec X# endif /* emacs */ X} re_opcode_t; X#endif /* not INSIDE_RECURSION */ X X X#ifdef BYTE X# define CHAR_T char X# define UCHAR_T unsigned char X# define COMPILED_BUFFER_VAR bufp->buffer X# define OFFSET_ADDRESS_SIZE 2 X# define PREFIX(name) byte_##name X# define ARG_PREFIX(name) name X# define PUT_CHAR(c) putchar (c) X#else X# ifdef WCHAR X# define CHAR_T wchar_t X# define UCHAR_T wchar_t X# define COMPILED_BUFFER_VAR wc_buffer X# define OFFSET_ADDRESS_SIZE 1 /* the size which STORE_NUMBER macro use */ X# define CHAR_CLASS_SIZE ((__alignof__(wctype_t)+sizeof(wctype_t))/sizeof(CHAR_T)+1) X# define PREFIX(name) wcs_##name X# define ARG_PREFIX(name) c##name X/* Should we use wide stream?? */ X# define PUT_CHAR(c) printf ("%C", c); X# define TRUE 1 X# define FALSE 0 X# else X# ifdef MBS_SUPPORT X# define WCHAR X# define INSIDE_RECURSION X# include "regex.c" X# undef INSIDE_RECURSION X# endif X# define BYTE X# define INSIDE_RECURSION X# include "regex.c" X# undef INSIDE_RECURSION X# endif X#endif X#include "unlocked-io.h" X X#ifdef INSIDE_RECURSION X/* Common operations on the compiled pattern. */ X X/* Store NUMBER in two contiguous bytes starting at DESTINATION. */ X/* ifdef MBS_SUPPORT, we store NUMBER in 1 element. */ X X# ifdef WCHAR X# define STORE_NUMBER(destination, number) \ X do { \ X *(destination) = (UCHAR_T)(number); \ X } while (0) X# else /* BYTE */ X# define STORE_NUMBER(destination, number) \ X do { \ X (destination)[0] = (number) & 0377; \ X (destination)[1] = (number) >> 8; \ X } while (0) X# endif /* WCHAR */ X X/* Same as STORE_NUMBER, except increment DESTINATION to X the byte after where the number is stored. Therefore, DESTINATION X must be an lvalue. */ X/* ifdef MBS_SUPPORT, we store NUMBER in 1 element. */ X X# define STORE_NUMBER_AND_INCR(destination, number) \ X do { \ X STORE_NUMBER (destination, number); \ X (destination) += OFFSET_ADDRESS_SIZE; \ X } while (0) X X/* Put into DESTINATION a number stored in two contiguous bytes starting X at SOURCE. */ X/* ifdef MBS_SUPPORT, we store NUMBER in 1 element. */ X X# ifdef WCHAR X# define EXTRACT_NUMBER(destination, source) \ X do { \ X (destination) = *(source); \ X } while (0) X# else /* BYTE */ X# define EXTRACT_NUMBER(destination, source) \ X do { \ X (destination) = *(source) & 0377; \ X (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8; \ X } while (0) X# endif X X# ifdef DEBUG Xstatic void PREFIX(extract_number) _RE_ARGS ((int *dest, UCHAR_T *source)); Xstatic void XPREFIX(extract_number) (dest, source) X int *dest; X UCHAR_T *source; X{ X# ifdef WCHAR X *dest = *source; X# else /* BYTE */ X int temp = SIGN_EXTEND_CHAR (*(source + 1)); X *dest = *source & 0377; X *dest += temp << 8; X# endif X} X X# ifndef EXTRACT_MACROS /* To debug the macros. */ X# undef EXTRACT_NUMBER X# define EXTRACT_NUMBER(dest, src) PREFIX(extract_number) (&dest, src) X# endif /* not EXTRACT_MACROS */ X X# endif /* DEBUG */ X X/* Same as EXTRACT_NUMBER, except increment SOURCE to after the number. X SOURCE must be an lvalue. */ X X# define EXTRACT_NUMBER_AND_INCR(destination, source) \ X do { \ X EXTRACT_NUMBER (destination, source); \ X (source) += OFFSET_ADDRESS_SIZE; \ X } while (0) X X# ifdef DEBUG Xstatic void PREFIX(extract_number_and_incr) _RE_ARGS ((int *destination, X UCHAR_T **source)); Xstatic void XPREFIX(extract_number_and_incr) (destination, source) X int *destination; X UCHAR_T **source; X{ X PREFIX(extract_number) (destination, *source); X *source += OFFSET_ADDRESS_SIZE; X} X X# ifndef EXTRACT_MACROS X# undef EXTRACT_NUMBER_AND_INCR X# define EXTRACT_NUMBER_AND_INCR(dest, src) \ X PREFIX(extract_number_and_incr) (&dest, &src) X# endif /* not EXTRACT_MACROS */ X X# endif /* DEBUG */ X X X X/* If DEBUG is defined, Regex prints many voluminous messages about what X it is doing (if the variable `debug' is nonzero). If linked with the X main program in `iregex.c', you can enter patterns and strings X interactively. And if linked with the main program in `main.c' and X the other test files, you can run the already-written tests. */ X X# ifdef DEBUG X X# ifndef DEFINED_ONCE X X/* We use standard I/O for debugging. */ X# include X X/* It is useful to test things that ``must'' be true when debugging. */ X# include X Xstatic int debug; X X# define DEBUG_STATEMENT(e) e X# define DEBUG_PRINT1(x) if (debug) printf (x) X# define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2) X# define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3) X# define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4) X# endif /* not DEFINED_ONCE */ X X# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \ X if (debug) PREFIX(print_partial_compiled_pattern) (s, e) X# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \ X if (debug) PREFIX(print_double_string) (w, s1, sz1, s2, sz2) X X X/* Print the fastmap in human-readable form. */ X X# ifndef DEFINED_ONCE Xvoid Xprint_fastmap (fastmap) X char *fastmap; X{ X unsigned was_a_range = 0; X unsigned i = 0; X X while (i < (1 << BYTEWIDTH)) X { X if (fastmap[i++]) X { X was_a_range = 0; X putchar (i - 1); X while (i < (1 << BYTEWIDTH) && fastmap[i]) X { X was_a_range = 1; X i++; X } X if (was_a_range) X { X printf ("-"); X putchar (i - 1); X } X } X } X putchar ('\n'); X} X# endif /* not DEFINED_ONCE */ X X X/* Print a compiled pattern string in human-readable form, starting at X the START pointer into it and ending just before the pointer END. */ X Xvoid XPREFIX(print_partial_compiled_pattern) (start, end) X UCHAR_T *start; X UCHAR_T *end; X{ X int mcnt, mcnt2; X UCHAR_T *p1; X UCHAR_T *p = start; X UCHAR_T *pend = end; X X if (start == NULL) X { X printf ("(null)\n"); X return; X } X X /* Loop over pattern commands. */ X while (p < pend) X { X# ifdef _LIBC X printf ("%td:\t", p - start); X# else X printf ("%ld:\t", (long int) (p - start)); X# endif X X switch ((re_opcode_t) *p++) X { X case no_op: X printf ("/no_op"); X break; X X case exactn: X mcnt = *p++; X printf ("/exactn/%d", mcnt); X do X { X putchar ('/'); X PUT_CHAR (*p++); X } X while (--mcnt); X break; X X# ifdef MBS_SUPPORT X case exactn_bin: X mcnt = *p++; X printf ("/exactn_bin/%d", mcnt); X do X { X printf("/%lx", (long int) *p++); X } X while (--mcnt); X break; X# endif /* MBS_SUPPORT */ X X case start_memory: X mcnt = *p++; X printf ("/start_memory/%d/%ld", mcnt, (long int) *p++); X break; X X case stop_memory: X mcnt = *p++; X printf ("/stop_memory/%d/%ld", mcnt, (long int) *p++); X break; X X case duplicate: X printf ("/duplicate/%ld", (long int) *p++); X break; X X case anychar: X printf ("/anychar"); X break; X X case charset: X case charset_not: X { X# ifdef WCHAR X int i, length; X wchar_t *workp = p; X printf ("/charset [%s", X (re_opcode_t) *(workp - 1) == charset_not ? "^" : ""); X p += 5; X length = *workp++; /* the length of char_classes */ X for (i=0 ; ibuffer; X X PREFIX(print_partial_compiled_pattern) (buffer, buffer X + bufp->used / sizeof(UCHAR_T)); X printf ("%ld bytes used/%ld bytes allocated.\n", X bufp->used, bufp->allocated); X X if (bufp->fastmap_accurate && bufp->fastmap) X { X printf ("fastmap: "); X print_fastmap (bufp->fastmap); X } X X# ifdef _LIBC X printf ("re_nsub: %Zd\t", bufp->re_nsub); X# else X printf ("re_nsub: %ld\t", (long int) bufp->re_nsub); X# endif X printf ("regs_alloc: %d\t", bufp->regs_allocated); X printf ("can_be_null: %d\t", bufp->can_be_null); X printf ("newline_anchor: %d\n", bufp->newline_anchor); X printf ("no_sub: %d\t", bufp->no_sub); X printf ("not_bol: %d\t", bufp->not_bol); X printf ("not_eol: %d\t", bufp->not_eol); X printf ("syntax: %lx\n", bufp->syntax); X /* Perhaps we should print the translate table? */ X} X X Xvoid XPREFIX(print_double_string) (where, string1, size1, string2, size2) X const CHAR_T *where; X const CHAR_T *string1; X const CHAR_T *string2; X int size1; X int size2; X{ X int this_char; X X if (where == NULL) X printf ("(null)"); X else X { X int cnt; X X if (FIRST_STRING_P (where)) X { X for (this_char = where - string1; this_char < size1; this_char++) X PUT_CHAR (string1[this_char]); X X where = string2; X } X X cnt = 0; X for (this_char = where - string2; this_char < size2; this_char++) X { X PUT_CHAR (string2[this_char]); X if (++cnt > 100) X { X fputs ("...", stdout); X break; X } X } X } X} X X# ifndef DEFINED_ONCE Xvoid Xprintchar (c) X int c; X{ X putc (c, stderr); X} X# endif X X# else /* not DEBUG */ X X# ifndef DEFINED_ONCE X# undef assert X# define assert(e) X X# define DEBUG_STATEMENT(e) X# define DEBUG_PRINT1(x) X# define DEBUG_PRINT2(x1, x2) X# define DEBUG_PRINT3(x1, x2, x3) X# define DEBUG_PRINT4(x1, x2, x3, x4) X# endif /* not DEFINED_ONCE */ X# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) X# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) X X# endif /* not DEBUG */ X X X X# ifdef WCHAR X/* This convert a multibyte string to a wide character string. X And write their correspondances to offset_buffer(see below) X and write whether each wchar_t is binary data to is_binary. X This assume invalid multibyte sequences as binary data. X We assume offset_buffer and is_binary is already allocated X enough space. */ X Xstatic size_t convert_mbs_to_wcs (CHAR_T *dest, const unsigned char* src, X size_t len, int *offset_buffer, X char *is_binary); Xstatic size_t Xconvert_mbs_to_wcs (dest, src, len, offset_buffer, is_binary) X CHAR_T *dest; X const unsigned char* src; X size_t len; /* the length of multibyte string. */ X X /* It hold correspondances between src(char string) and X dest(wchar_t string) for optimization. X e.g. src = "xxxyzz" X dest = {'X', 'Y', 'Z'} X (each "xxx", "y" and "zz" represent one multibyte character X corresponding to 'X', 'Y' and 'Z'.) X offset_buffer = {0, 0+3("xxx"), 0+3+1("y"), 0+3+1+2("zz")} X = {0, 3, 4, 6} X */ X int *offset_buffer; X char *is_binary; X{ X wchar_t *pdest = dest; X const unsigned char *psrc = src; X size_t wc_count = 0; X X mbstate_t mbs; X int i, consumed; X size_t mb_remain = len; X size_t mb_count = 0; X X /* Initialize the conversion state. */ X memset (&mbs, 0, sizeof (mbstate_t)); X X offset_buffer[0] = 0; X for( ; mb_remain > 0 ; ++wc_count, ++pdest, mb_remain -= consumed, X psrc += consumed) X { X consumed = mbrtowc (pdest, psrc, mb_remain, &mbs); X X if (consumed <= 0) X /* failed to convert. maybe src contains binary data. X So we consume 1 byte manualy. */ X { X *pdest = *psrc; X consumed = 1; X is_binary[wc_count] = TRUE; X } X else X is_binary[wc_count] = FALSE; X /* In sjis encoding, we use yen sign as escape character in X place of reverse solidus. So we convert 0x5c(yen sign in X sjis) to not 0xa5(yen sign in UCS2) but 0x5c(reverse X solidus in UCS2). */ X if (consumed == 1 && (int) *psrc == 0x5c && (int) *pdest == 0xa5) X *pdest = (wchar_t) *psrc; X X offset_buffer[wc_count + 1] = mb_count += consumed; X } X X /* Fill remain of the buffer with sentinel. */ X for (i = wc_count + 1 ; i <= len ; i++) X offset_buffer[i] = mb_count + 1; X X return wc_count; X} X X# endif /* WCHAR */ X X#else /* not INSIDE_RECURSION */ X X/* Set by `re_set_syntax' to the current regexp syntax to recognize. Can X also be assigned to arbitrarily: each pattern buffer stores its own X syntax, so it can be changed between regex compilations. */ X/* This has no initializer because initialized variables in Emacs X become read-only after dumping. */ Xreg_syntax_t re_syntax_options; X X X/* Specify the precise syntax of regexps for compilation. This provides X for compatibility for various utilities which historically have X different, incompatible syntaxes. X X The argument SYNTAX is a bit mask comprised of the various bits X defined in regex.h. We return the old syntax. */ X Xreg_syntax_t Xre_set_syntax (syntax) X reg_syntax_t syntax; X{ X reg_syntax_t ret = re_syntax_options; X X re_syntax_options = syntax; X# ifdef DEBUG X if (syntax & RE_DEBUG) X debug = 1; X else if (debug) /* was on but now is not */ X debug = 0; X# endif /* DEBUG */ X return ret; X} X# ifdef _LIBC Xweak_alias (__re_set_syntax, re_set_syntax) X# endif X X/* This table gives an error message for each of the error codes listed X in regex.h. Obviously the order here has to be same as there. X POSIX doesn't require that we do anything for REG_NOERROR, X but why not be nice? */ X Xstatic const char re_error_msgid[] = X { X# define REG_NOERROR_IDX 0 X gettext_noop ("Success") /* REG_NOERROR */ X "\0" X# define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success") X gettext_noop ("No match") /* REG_NOMATCH */ X "\0" X# define REG_BADPAT_IDX (REG_NOMATCH_IDX + sizeof "No match") X gettext_noop ("Invalid regular expression") /* REG_BADPAT */ X "\0" X# define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression") X gettext_noop ("Invalid collation character") /* REG_ECOLLATE */ X "\0" X# define REG_ECTYPE_IDX (REG_ECOLLATE_IDX + sizeof "Invalid collation character") X gettext_noop ("Invalid character class name") /* REG_ECTYPE */ X "\0" X# define REG_EESCAPE_IDX (REG_ECTYPE_IDX + sizeof "Invalid character class name") X gettext_noop ("Trailing backslash") /* REG_EESCAPE */ X "\0" X# define REG_ESUBREG_IDX (REG_EESCAPE_IDX + sizeof "Trailing backslash") X gettext_noop ("Invalid back reference") /* REG_ESUBREG */ X "\0" X# define REG_EBRACK_IDX (REG_ESUBREG_IDX + sizeof "Invalid back reference") X gettext_noop ("Unmatched [ or [^") /* REG_EBRACK */ X "\0" X# define REG_EPAREN_IDX (REG_EBRACK_IDX + sizeof "Unmatched [ or [^") X gettext_noop ("Unmatched ( or \\(") /* REG_EPAREN */ X "\0" X# define REG_EBRACE_IDX (REG_EPAREN_IDX + sizeof "Unmatched ( or \\(") X gettext_noop ("Unmatched \\{") /* REG_EBRACE */ X "\0" X# define REG_BADBR_IDX (REG_EBRACE_IDX + sizeof "Unmatched \\{") X gettext_noop ("Invalid content of \\{\\}") /* REG_BADBR */ X "\0" X# define REG_ERANGE_IDX (REG_BADBR_IDX + sizeof "Invalid content of \\{\\}") X gettext_noop ("Invalid range end") /* REG_ERANGE */ X "\0" X# define REG_ESPACE_IDX (REG_ERANGE_IDX + sizeof "Invalid range end") X gettext_noop ("Memory exhausted") /* REG_ESPACE */ X "\0" X# define REG_BADRPT_IDX (REG_ESPACE_IDX + sizeof "Memory exhausted") X gettext_noop ("Invalid preceding regular expression") /* REG_BADRPT */ X "\0" X# define REG_EEND_IDX (REG_BADRPT_IDX + sizeof "Invalid preceding regular expression") X gettext_noop ("Premature end of regular expression") /* REG_EEND */ X "\0" X# define REG_ESIZE_IDX (REG_EEND_IDX + sizeof "Premature end of regular expression") X gettext_noop ("Regular expression too big") /* REG_ESIZE */ X "\0" X# define REG_ERPAREN_IDX (REG_ESIZE_IDX + sizeof "Regular expression too big") X gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */ X }; X Xstatic const size_t re_error_msgid_idx[] = X { X REG_NOERROR_IDX, X REG_NOMATCH_IDX, X REG_BADPAT_IDX, X REG_ECOLLATE_IDX, X REG_ECTYPE_IDX, X REG_EESCAPE_IDX, X REG_ESUBREG_IDX, X REG_EBRACK_IDX, X REG_EPAREN_IDX, X REG_EBRACE_IDX, X REG_BADBR_IDX, X REG_ERANGE_IDX, X REG_ESPACE_IDX, X REG_BADRPT_IDX, X REG_EEND_IDX, X REG_ESIZE_IDX, X REG_ERPAREN_IDX X }; X X#endif /* INSIDE_RECURSION */ X X#ifndef DEFINED_ONCE X/* Avoiding alloca during matching, to placate r_alloc. */ X X/* Define MATCH_MAY_ALLOCATE unless we need to make sure that the X searching and matching functions should not call alloca. On some X systems, alloca is implemented in terms of malloc, and if we're X using the relocating allocator routines, then malloc could cause a X relocation, which might (if the strings being searched are in the X ralloc heap) shift the data out from underneath the regexp X routines. X X Here's another reason to avoid allocation: Emacs X processes input from X in a signal handler; processing X input may X call malloc; if input arrives while a matching routine is calling X malloc, then we're scrod. But Emacs can't just block input while X calling matching routines; then we don't notice interrupts when X they come in. So, Emacs blocks input around all regexp calls X except the matching calls, which it leaves unprotected, in the X faith that they will not malloc. */ X X/* Normally, this is fine. */ X# define MATCH_MAY_ALLOCATE X X/* When using GNU C, we are not REALLY using the C alloca, no matter X what config.h may say. So don't take precautions for it. */ X# ifdef __GNUC__ X# undef C_ALLOCA X# endif X X/* The match routines may not allocate if (1) they would do it with malloc X and (2) it's not safe for them to use malloc. X Note that if REL_ALLOC is defined, matching would not use malloc for the X failure stack, but we would still use it for the register vectors; X so REL_ALLOC should not affect this. */ X# if (defined C_ALLOCA || defined REGEX_MALLOC) && defined emacs X# undef MATCH_MAY_ALLOCATE X# endif X#endif /* not DEFINED_ONCE */ X X#ifdef INSIDE_RECURSION X/* Failure stack declarations and macros; both re_compile_fastmap and X re_match_2 use a failure stack. These have to be macros because of X REGEX_ALLOCATE_STACK. */ X X X/* Number of failure points for which to initially allocate space X when matching. If this number is exceeded, we allocate more X space, so it is not a hard limit. */ X# ifndef INIT_FAILURE_ALLOC X# define INIT_FAILURE_ALLOC 5 X# endif X X/* Roughly the maximum number of failure points on the stack. Would be X exactly that if always used MAX_FAILURE_ITEMS items each time we failed. X This is a variable only so users of regex can assign to it; we never X change it ourselves. */ X X# ifdef INT_IS_16BIT X X# ifndef DEFINED_ONCE X# if defined MATCH_MAY_ALLOCATE X/* 4400 was enough to cause a crash on Alpha OSF/1, X whose default stack limit is 2mb. */ Xlong int re_max_failures = 4000; X# else Xlong int re_max_failures = 2000; X# endif X# endif X Xunion PREFIX(fail_stack_elt) X{ X UCHAR_T *pointer; X long int integer; X}; X Xtypedef union PREFIX(fail_stack_elt) PREFIX(fail_stack_elt_t); X Xtypedef struct X{ X PREFIX(fail_stack_elt_t) *stack; X unsigned long int size; X unsigned long int avail; /* Offset of next open position. */ X} PREFIX(fail_stack_type); X X# else /* not INT_IS_16BIT */ X X# ifndef DEFINED_ONCE X# if defined MATCH_MAY_ALLOCATE X/* 4400 was enough to cause a crash on Alpha OSF/1, X whose default stack limit is 2mb. */ Xint re_max_failures = 4000; X# else Xint re_max_failures = 2000; X# endif X# endif X Xunion PREFIX(fail_stack_elt) X{ X UCHAR_T *pointer; X int integer; X}; X Xtypedef union PREFIX(fail_stack_elt) PREFIX(fail_stack_elt_t); X Xtypedef struct X{ X PREFIX(fail_stack_elt_t) *stack; X unsigned size; X unsigned avail; /* Offset of next open position. */ X} PREFIX(fail_stack_type); X X# endif /* INT_IS_16BIT */ X X# ifndef DEFINED_ONCE X# define FAIL_STACK_EMPTY() (fail_stack.avail == 0) X# define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0) X# define FAIL_STACK_FULL() (fail_stack.avail == fail_stack.size) X# endif X X X/* Define macros to initialize and free the failure stack. X Do `return -2' if the alloc fails. */ X X# ifdef MATCH_MAY_ALLOCATE X# define INIT_FAIL_STACK() \ X do { \ X fail_stack.stack = (PREFIX(fail_stack_elt_t) *) \ X REGEX_ALLOCATE_STACK (INIT_FAILURE_ALLOC * sizeof (PREFIX(fail_stack_elt_t))); \ X \ X if (fail_stack.stack == NULL) \ X return -2; \ X \ X fail_stack.size = INIT_FAILURE_ALLOC; \ X fail_stack.avail = 0; \ X } while (0) X X# define RESET_FAIL_STACK() REGEX_FREE_STACK (fail_stack.stack) X# else X# define INIT_FAIL_STACK() \ X do { \ X fail_stack.avail = 0; \ X } while (0) X X# define RESET_FAIL_STACK() X# endif X X X/* Double the size of FAIL_STACK, up to approximately `re_max_failures' items. X X Return 1 if succeeds, and 0 if either ran out of memory X allocating space for it or it was already too large. X X REGEX_REALLOCATE_STACK requires `destination' be declared. */ X X# define DOUBLE_FAIL_STACK(fail_stack) \ X ((fail_stack).size > (unsigned) (re_max_failures * MAX_FAILURE_ITEMS) \ X ? 0 \ X : ((fail_stack).stack = (PREFIX(fail_stack_elt_t) *) \ X REGEX_REALLOCATE_STACK ((fail_stack).stack, \ X (fail_stack).size * sizeof (PREFIX(fail_stack_elt_t)), \ X ((fail_stack).size << 1) * sizeof (PREFIX(fail_stack_elt_t))),\ X \ X (fail_stack).stack == NULL \ X ? 0 \ X : ((fail_stack).size <<= 1, \ X 1))) X X X/* Push pointer POINTER on FAIL_STACK. X Return 1 if was able to do so and 0 if ran out of memory allocating X space to do so. */ X# define PUSH_PATTERN_OP(POINTER, FAIL_STACK) \ X ((FAIL_STACK_FULL () \ X && !DOUBLE_FAIL_STACK (FAIL_STACK)) \ X ? 0 \ X : ((FAIL_STACK).stack[(FAIL_STACK).avail++].pointer = POINTER, \ X 1)) X X/* Push a pointer value onto the failure stack. X Assumes the variable `fail_stack'. Probably should only X be called from within `PUSH_FAILURE_POINT'. */ X# define PUSH_FAILURE_POINTER(item) \ X fail_stack.stack[fail_stack.avail++].pointer = (UCHAR_T *) (item) X X/* This pushes an integer-valued item onto the failure stack. X Assumes the variable `fail_stack'. Probably should only X be called from within `PUSH_FAILURE_POINT'. */ X# define PUSH_FAILURE_INT(item) \ X fail_stack.stack[fail_stack.avail++].integer = (item) X X/* Push a fail_stack_elt_t value onto the failure stack. X Assumes the variable `fail_stack'. Probably should only X be called from within `PUSH_FAILURE_POINT'. */ X# define PUSH_FAILURE_ELT(item) \ X fail_stack.stack[fail_stack.avail++] = (item) X X/* These three POP... operations complement the three PUSH... operations. X All assume that `fail_stack' is nonempty. */ X# define POP_FAILURE_POINTER() fail_stack.stack[--fail_stack.avail].pointer X# define POP_FAILURE_INT() fail_stack.stack[--fail_stack.avail].integer X# define POP_FAILURE_ELT() fail_stack.stack[--fail_stack.avail] X X/* Used to omit pushing failure point id's when we're not debugging. */ X# ifdef DEBUG X# define DEBUG_PUSH PUSH_FAILURE_INT X# define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_INT () X# else X# define DEBUG_PUSH(item) X# define DEBUG_POP(item_addr) X# endif X X X/* Push the information about the state we will need X if we ever fail back to it. X X Requires variables fail_stack, regstart, regend, reg_info, and X num_regs_pushed be declared. DOUBLE_FAIL_STACK requires `destination' X be declared. X X Does `return FAILURE_CODE' if runs out of memory. */ X X# define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code) \ X do { \ X char *destination; \ X /* Must be int, so when we don't save any registers, the arithmetic \ X of 0 + -1 isn't done as unsigned. */ \ X /* Can't be int, since there is not a shred of a guarantee that int \ X is wide enough to hold a value of something to which pointer can \ X be assigned */ \ X active_reg_t this_reg; \ X \ X DEBUG_STATEMENT (failure_id++); \ X DEBUG_STATEMENT (nfailure_points_pushed++); \ X DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id); \ X DEBUG_PRINT2 (" Before push, next avail: %d\n", (fail_stack).avail);\ X DEBUG_PRINT2 (" size: %d\n", (fail_stack).size);\ X \ X DEBUG_PRINT2 (" slots needed: %ld\n", NUM_FAILURE_ITEMS); \ X DEBUG_PRINT2 (" available: %d\n", REMAINING_AVAIL_SLOTS); \ X \ X /* Ensure we have enough space allocated for what we will push. */ \ X while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS) \ X { \ X if (!DOUBLE_FAIL_STACK (fail_stack)) \ X return failure_code; \ X \ X DEBUG_PRINT2 ("\n Doubled stack; size now: %d\n", \ X (fail_stack).size); \ X DEBUG_PRINT2 (" slots available: %d\n", REMAINING_AVAIL_SLOTS);\ X } \ X \ X /* Push the info, starting with the registers. */ \ X DEBUG_PRINT1 ("\n"); \ X \ X if (1) \ X for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \ X this_reg++) \ X { \ X DEBUG_PRINT2 (" Pushing reg: %lu\n", this_reg); \ X DEBUG_STATEMENT (num_regs_pushed++); \ X \ X DEBUG_PRINT2 (" start: %p\n", regstart[this_reg]); \ X PUSH_FAILURE_POINTER (regstart[this_reg]); \ X \ X DEBUG_PRINT2 (" end: %p\n", regend[this_reg]); \ X PUSH_FAILURE_POINTER (regend[this_reg]); \ X \ X DEBUG_PRINT2 (" info: %p\n ", \ X reg_info[this_reg].word.pointer); \ X DEBUG_PRINT2 (" match_null=%d", \ X REG_MATCH_NULL_STRING_P (reg_info[this_reg])); \ X DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg])); \ X DEBUG_PRINT2 (" matched_something=%d", \ X MATCHED_SOMETHING (reg_info[this_reg])); \ X DEBUG_PRINT2 (" ever_matched=%d", \ X EVER_MATCHED_SOMETHING (reg_info[this_reg])); \ X DEBUG_PRINT1 ("\n"); \ X PUSH_FAILURE_ELT (reg_info[this_reg].word); \ X } \ X \ X DEBUG_PRINT2 (" Pushing low active reg: %ld\n", lowest_active_reg);\ X PUSH_FAILURE_INT (lowest_active_reg); \ X \ X DEBUG_PRINT2 (" Pushing high active reg: %ld\n", highest_active_reg);\ X PUSH_FAILURE_INT (highest_active_reg); \ X \ X DEBUG_PRINT2 (" Pushing pattern %p:\n", pattern_place); \ X DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend); \ X PUSH_FAILURE_POINTER (pattern_place); \ X \ X DEBUG_PRINT2 (" Pushing string %p: `", string_place); \ X DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, \ X size2); \ X DEBUG_PRINT1 ("'\n"); \ X PUSH_FAILURE_POINTER (string_place); \ X \ X DEBUG_PRINT2 (" Pushing failure id: %u\n", failure_id); \ X DEBUG_PUSH (failure_id); \ X } while (0) X X# ifndef DEFINED_ONCE X/* This is the number of items that are pushed and popped on the stack X for each register. */ X# define NUM_REG_ITEMS 3 X X/* Individual items aside from the registers. */ X# ifdef DEBUG X# define NUM_NONREG_ITEMS 5 /* Includes failure point id. */ X# else X# define NUM_NONREG_ITEMS 4 X# endif X X/* We push at most this many items on the stack. */ X/* We used to use (num_regs - 1), which is the number of registers X this regexp will save; but that was changed to 5 X to avoid stack overflow for a regexp with lots of parens. */ X# define MAX_FAILURE_ITEMS (5 * NUM_REG_ITEMS + NUM_NONREG_ITEMS) X X/* We actually push this many items. */ X# define NUM_FAILURE_ITEMS \ X (((0 \ X ? 0 : highest_active_reg - lowest_active_reg + 1) \ X * NUM_REG_ITEMS) \ X + NUM_NONREG_ITEMS) X X/* How many items can still be added to the stack without overflowing it. */ X# define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail) X# endif /* not DEFINED_ONCE */ X X X/* Pops what PUSH_FAIL_STACK pushes. X X We restore into the parameters, all of which should be lvalues: X STR -- the saved data position. X PAT -- the saved pattern position. X LOW_REG, HIGH_REG -- the highest and lowest active registers. X REGSTART, REGEND -- arrays of string positions. X REG_INFO -- array of information about each subexpression. X X Also assumes the variables `fail_stack' and (if debugging), `bufp', X `pend', `string1', `size1', `string2', and `size2'. */ X# define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\ X{ \ X DEBUG_STATEMENT (unsigned failure_id;) \ X active_reg_t this_reg; \ X const UCHAR_T *string_temp; \ X \ X assert (!FAIL_STACK_EMPTY ()); \ X \ X /* Remove failure points and point to how many regs pushed. */ \ X DEBUG_PRINT1 ("POP_FAILURE_POINT:\n"); \ X DEBUG_PRINT2 (" Before pop, next avail: %d\n", fail_stack.avail); \ X DEBUG_PRINT2 (" size: %d\n", fail_stack.size); \ X \ X assert (fail_stack.avail >= NUM_NONREG_ITEMS); \ X \ X DEBUG_POP (&failure_id); \ X DEBUG_PRINT2 (" Popping failure id: %u\n", failure_id); \ X \ X /* If the saved string location is NULL, it came from an \ X on_failure_keep_string_jump opcode, and we want to throw away the \ X saved NULL, thus retaining our current position in the string. */ \ X string_temp = POP_FAILURE_POINTER (); \ X if (string_temp != NULL) \ X str = (const CHAR_T *) string_temp; \ X \ X DEBUG_PRINT2 (" Popping string %p: `", str); \ X DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \ X DEBUG_PRINT1 ("'\n"); \ X \ X pat = (UCHAR_T *) POP_FAILURE_POINTER (); \ X DEBUG_PRINT2 (" Popping pattern %p:\n", pat); \ X DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \ X \ X /* Restore register info. */ \ X high_reg = (active_reg_t) POP_FAILURE_INT (); \ X DEBUG_PRINT2 (" Popping high active reg: %ld\n", high_reg); \ X \ X low_reg = (active_reg_t) POP_FAILURE_INT (); \ X DEBUG_PRINT2 (" Popping low active reg: %ld\n", low_reg); \ X \ X if (1) \ X for (this_reg = high_reg; this_reg >= low_reg; this_reg--) \ X { \ X DEBUG_PRINT2 (" Popping reg: %ld\n", this_reg); \ X \ X reg_info[this_reg].word = POP_FAILURE_ELT (); \ X DEBUG_PRINT2 (" info: %p\n", \ X reg_info[this_reg].word.pointer); \ X \ X regend[this_reg] = (const CHAR_T *) POP_FAILURE_POINTER (); \ X DEBUG_PRINT2 (" end: %p\n", regend[this_reg]); \ X \ X regstart[this_reg] = (const CHAR_T *) POP_FAILURE_POINTER (); \ X DEBUG_PRINT2 (" start: %p\n", regstart[this_reg]); \ X } \ X else \ X { \ X for (this_reg = highest_active_reg; this_reg > high_reg; this_reg--) \ X { \ X reg_info[this_reg].word.integer = 0; \ X regend[this_reg] = 0; \ X regstart[this_reg] = 0; \ X } \ X highest_active_reg = high_reg; \ X } \ X \ X set_regs_matched_done = 0; \ X DEBUG_STATEMENT (nfailure_points_popped++); \ X} /* POP_FAILURE_POINT */ X X/* Structure for per-register (a.k.a. per-group) information. X Other register information, such as the X starting and ending positions (which are addresses), and the list of X inner groups (which is a bits list) are maintained in separate X variables. X X We are making a (strictly speaking) nonportable assumption here: that X the compiler will pack our bit fields into something that fits into X the type of `word', i.e., is something that fits into one item on the X failure stack. */ X X X/* Declarations and macros for re_match_2. */ X Xtypedef union X{ X PREFIX(fail_stack_elt_t) word; X struct X { X /* This field is one if this group can match the empty string, X zero if not. If not yet determined, `MATCH_NULL_UNSET_VALUE'. */ X# define MATCH_NULL_UNSET_VALUE 3 X unsigned match_null_string_p : 2; X unsigned is_active : 1; X unsigned matched_something : 1; X unsigned ever_matched_something : 1; X } bits; X} PREFIX(register_info_type); X X# ifndef DEFINED_ONCE X# define REG_MATCH_NULL_STRING_P(R) ((R).bits.match_null_string_p) X# define IS_ACTIVE(R) ((R).bits.is_active) X# define MATCHED_SOMETHING(R) ((R).bits.matched_something) X# define EVER_MATCHED_SOMETHING(R) ((R).bits.ever_matched_something) X X X/* Call this when have matched a real character; it sets `matched' flags X for the subexpressions which we are currently inside. Also records X that those subexprs have matched. */ X# define SET_REGS_MATCHED() \ X do \ X { \ X if (!set_regs_matched_done) \ X { \ X active_reg_t r; \ X set_regs_matched_done = 1; \ X for (r = lowest_active_reg; r <= highest_active_reg; r++) \ X { \ X MATCHED_SOMETHING (reg_info[r]) \ X = EVER_MATCHED_SOMETHING (reg_info[r]) \ X = 1; \ X } \ X } \ X } \ X while (0) X# endif /* not DEFINED_ONCE */ X X/* Registers are set to a sentinel when they haven't yet matched. */ Xstatic CHAR_T PREFIX(reg_unset_dummy); X# define REG_UNSET_VALUE (&PREFIX(reg_unset_dummy)) X# define REG_UNSET(e) ((e) == REG_UNSET_VALUE) X X/* Subroutine declarations and macros for regex_compile. */ Xstatic void PREFIX(store_op1) _RE_ARGS ((re_opcode_t op, UCHAR_T *loc, int arg)); Xstatic void PREFIX(store_op2) _RE_ARGS ((re_opcode_t op, UCHAR_T *loc, X int arg1, int arg2)); Xstatic void PREFIX(insert_op1) _RE_ARGS ((re_opcode_t op, UCHAR_T *loc, X int arg, UCHAR_T *end)); Xstatic void PREFIX(insert_op2) _RE_ARGS ((re_opcode_t op, UCHAR_T *loc, X int arg1, int arg2, UCHAR_T *end)); Xstatic boolean PREFIX(at_begline_loc_p) _RE_ARGS ((const CHAR_T *pattern, X const CHAR_T *p, X reg_syntax_t syntax)); Xstatic boolean PREFIX(at_endline_loc_p) _RE_ARGS ((const CHAR_T *p, X const CHAR_T *pend, X reg_syntax_t syntax)); X# ifdef WCHAR Xstatic reg_errcode_t wcs_compile_range _RE_ARGS ((CHAR_T range_start, X const CHAR_T **p_ptr, X const CHAR_T *pend, X char *translate, X reg_syntax_t syntax, X UCHAR_T *b, X CHAR_T *char_set)); Xstatic void insert_space _RE_ARGS ((int num, CHAR_T *loc, CHAR_T *end)); X# else /* BYTE */ Xstatic reg_errcode_t byte_compile_range _RE_ARGS ((unsigned int range_start, X const char **p_ptr, X const char *pend, X char *translate, X reg_syntax_t syntax, X unsigned char *b)); X# endif /* WCHAR */ X X/* Fetch the next character in the uncompiled pattern---translating it X if necessary. Also cast from a signed character in the constant X string passed to us by the user to an unsigned char that we can use X as an array index (in, e.g., `translate'). */ X/* ifdef MBS_SUPPORT, we translate only if character <= 0xff, X because it is impossible to allocate 4GB array for some encodings X which have 4 byte character_set like UCS4. */ X# ifndef PATFETCH X# ifdef WCHAR X# define PATFETCH(c) \ X do {if (p == pend) return REG_EEND; \ X c = (UCHAR_T) *p++; \ X if (translate && (c <= 0xff)) c = (UCHAR_T) translate[c]; \ X } while (0) X# else /* BYTE */ X# define PATFETCH(c) \ X do {if (p == pend) return REG_EEND; \ X c = (unsigned char) *p++; \ X if (translate) c = (unsigned char) translate[c]; \ X } while (0) X# endif /* WCHAR */ X# endif X X/* Fetch the next character in the uncompiled pattern, with no X translation. */ X# define PATFETCH_RAW(c) \ X do {if (p == pend) return REG_EEND; \ X c = (UCHAR_T) *p++; \ X } while (0) X X/* Go backwards one character in the pattern. */ X# define PATUNFETCH p-- X X X/* If `translate' is non-null, return translate[D], else just D. We X cast the subscript to translate because some data is declared as X `char *', to avoid warnings when a string constant is passed. But X when we use a character as a subscript we must make it unsigned. */ X/* ifdef MBS_SUPPORT, we translate only if character <= 0xff, X because it is impossible to allocate 4GB array for some encodings X which have 4 byte character_set like UCS4. */ X X# ifndef TRANSLATE X# ifdef WCHAR X# define TRANSLATE(d) \ X ((translate && ((UCHAR_T) (d)) <= 0xff) \ X ? (char) translate[(unsigned char) (d)] : (d)) X# else /* BYTE */ X# define TRANSLATE(d) \ X (translate ? (char) translate[(unsigned char) (d)] : (d)) X# endif /* WCHAR */ X# endif X X X/* Macros for outputting the compiled pattern into `buffer'. */ X X/* If the buffer isn't allocated when it comes in, use this. */ X# define INIT_BUF_SIZE (32 * sizeof(UCHAR_T)) X X/* Make sure we have at least N more bytes of space in buffer. */ X# ifdef WCHAR X# define GET_BUFFER_SPACE(n) \ X while (((unsigned long)b - (unsigned long)COMPILED_BUFFER_VAR \ X + (n)*sizeof(CHAR_T)) > bufp->allocated) \ X EXTEND_BUFFER () X# else /* BYTE */ X# define GET_BUFFER_SPACE(n) \ X while ((unsigned long) (b - bufp->buffer + (n)) > bufp->allocated) \ X EXTEND_BUFFER () X# endif /* WCHAR */ X X/* Make sure we have one more byte of buffer space and then add C to it. */ X# define BUF_PUSH(c) \ X do { \ X GET_BUFFER_SPACE (1); \ X *b++ = (UCHAR_T) (c); \ X } while (0) X X X/* Ensure we have two more bytes of buffer space and then append C1 and C2. */ X# define BUF_PUSH_2(c1, c2) \ X do { \ X GET_BUFFER_SPACE (2); \ X *b++ = (UCHAR_T) (c1); \ X *b++ = (UCHAR_T) (c2); \ X } while (0) X X X/* As with BUF_PUSH_2, except for three bytes. */ X# define BUF_PUSH_3(c1, c2, c3) \ X do { \ X GET_BUFFER_SPACE (3); \ X *b++ = (UCHAR_T) (c1); \ X *b++ = (UCHAR_T) (c2); \ X *b++ = (UCHAR_T) (c3); \ X } while (0) X X/* Store a jump with opcode OP at LOC to location TO. We store a X relative address offset by the three bytes the jump itself occupies. */ X# define STORE_JUMP(op, loc, to) \ X PREFIX(store_op1) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE))) X X/* Likewise, for a two-argument jump. */ X# define STORE_JUMP2(op, loc, to, arg) \ X PREFIX(store_op2) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)), arg) X X/* Like `STORE_JUMP', but for inserting. Assume `b' is the buffer end. */ X# define INSERT_JUMP(op, loc, to) \ X PREFIX(insert_op1) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)), b) X X/* Like `STORE_JUMP2', but for inserting. Assume `b' is the buffer end. */ X# define INSERT_JUMP2(op, loc, to, arg) \ X PREFIX(insert_op2) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)),\ X arg, b) X X/* This is not an arbitrary limit: the arguments which represent offsets X into the pattern are two bytes long. So if 2^16 bytes turns out to X be too small, many things would have to change. */ X/* Any other compiler which, like MSC, has allocation limit below 2^16 X bytes will have to use approach similar to what was done below for X MSC and drop MAX_BUF_SIZE a bit. Otherwise you may end up X reallocating to 0 bytes. Such thing is not going to work too well. X You have been warned!! */ X# ifndef DEFINED_ONCE X# if defined _MSC_VER && !defined WIN32 X/* Microsoft C 16-bit versions limit malloc to approx 65512 bytes. X The REALLOC define eliminates a flurry of conversion warnings, X but is not required. */ X# define MAX_BUF_SIZE 65500L X# define REALLOC(p,s) realloc ((p), (size_t) (s)) X# else X# define MAX_BUF_SIZE (1L << 16) X# define REALLOC(p,s) realloc ((p), (s)) X# endif X X/* Extend the buffer by twice its current size via realloc and X reset the pointers that pointed into the old block to point to the X correct places in the new one. If extending the buffer results in it X being larger than MAX_BUF_SIZE, then flag memory exhausted. */ X# if __BOUNDED_POINTERS__ X# define SET_HIGH_BOUND(P) (__ptrhigh (P) = __ptrlow (P) + bufp->allocated) X# define MOVE_BUFFER_POINTER(P) \ X (__ptrlow (P) += incr, SET_HIGH_BOUND (P), __ptrvalue (P) += incr) X# define ELSE_EXTEND_BUFFER_HIGH_BOUND \ X else \ X { \ X SET_HIGH_BOUND (b); \ X SET_HIGH_BOUND (begalt); \ X if (fixup_alt_jump) \ X SET_HIGH_BOUND (fixup_alt_jump); \ X if (laststart) \ X SET_HIGH_BOUND (laststart); \ X if (pending_exact) \ X SET_HIGH_BOUND (pending_exact); \ X } X# else X# define MOVE_BUFFER_POINTER(P) (P) += incr X# define ELSE_EXTEND_BUFFER_HIGH_BOUND X# endif X# endif /* not DEFINED_ONCE */ X X# ifdef WCHAR X# define EXTEND_BUFFER() \ X do { \ X UCHAR_T *old_buffer = COMPILED_BUFFER_VAR; \ X int wchar_count; \ X if (bufp->allocated + sizeof(UCHAR_T) > MAX_BUF_SIZE) \ X return REG_ESIZE; \ X bufp->allocated <<= 1; \ X if (bufp->allocated > MAX_BUF_SIZE) \ X bufp->allocated = MAX_BUF_SIZE; \ X /* How many characters the new buffer can have? */ \ X wchar_count = bufp->allocated / sizeof(UCHAR_T); \ X if (wchar_count == 0) wchar_count = 1; \ X /* Truncate the buffer to CHAR_T align. */ \ X bufp->allocated = wchar_count * sizeof(UCHAR_T); \ X RETALLOC (COMPILED_BUFFER_VAR, wchar_count, UCHAR_T); \ X bufp->buffer = (char*)COMPILED_BUFFER_VAR; \ X if (COMPILED_BUFFER_VAR == NULL) \ X return REG_ESPACE; \ X /* If the buffer moved, move all the pointers into it. */ \ X if (old_buffer != COMPILED_BUFFER_VAR) \ X { \ X int incr = COMPILED_BUFFER_VAR - old_buffer; \ X MOVE_BUFFER_POINTER (b); \ X MOVE_BUFFER_POINTER (begalt); \ X if (fixup_alt_jump) \ X MOVE_BUFFER_POINTER (fixup_alt_jump); \ X if (laststart) \ X MOVE_BUFFER_POINTER (laststart); \ X if (pending_exact) \ X MOVE_BUFFER_POINTER (pending_exact); \ X } \ X ELSE_EXTEND_BUFFER_HIGH_BOUND \ X } while (0) X# else /* BYTE */ X# define EXTEND_BUFFER() \ X do { \ X UCHAR_T *old_buffer = COMPILED_BUFFER_VAR; \ X if (bufp->allocated == MAX_BUF_SIZE) \ X return REG_ESIZE; \ X bufp->allocated <<= 1; \ X if (bufp->allocated > MAX_BUF_SIZE) \ X bufp->allocated = MAX_BUF_SIZE; \ X bufp->buffer = (UCHAR_T *) REALLOC (COMPILED_BUFFER_VAR, \ X bufp->allocated); \ X if (COMPILED_BUFFER_VAR == NULL) \ X return REG_ESPACE; \ X /* If the buffer moved, move all the pointers into it. */ \ X if (old_buffer != COMPILED_BUFFER_VAR) \ X { \ X int incr = COMPILED_BUFFER_VAR - old_buffer; \ X MOVE_BUFFER_POINTER (b); \ X MOVE_BUFFER_POINTER (begalt); \ X if (fixup_alt_jump) \ X MOVE_BUFFER_POINTER (fixup_alt_jump); \ X if (laststart) \ X MOVE_BUFFER_POINTER (laststart); \ X if (pending_exact) \ X MOVE_BUFFER_POINTER (pending_exact); \ X } \ X ELSE_EXTEND_BUFFER_HIGH_BOUND \ X } while (0) X# endif /* WCHAR */ X X# ifndef DEFINED_ONCE X/* Since we have one byte reserved for the register number argument to X {start,stop}_memory, the maximum number of groups we can report X things about is what fits in that byte. */ X# define MAX_REGNUM 255 X X/* But patterns can have more than `MAX_REGNUM' registers. We just X ignore the excess. */ Xtypedef unsigned regnum_t; X X X/* Macros for the compile stack. */ X X/* Since offsets can go either forwards or backwards, this type needs to X be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1. */ X/* int may be not enough when sizeof(int) == 2. */ Xtypedef long pattern_offset_t; X Xtypedef struct X{ X pattern_offset_t begalt_offset; X pattern_offset_t fixup_alt_jump; X pattern_offset_t inner_group_offset; X pattern_offset_t laststart_offset; X regnum_t regnum; X} compile_stack_elt_t; X X Xtypedef struct X{ X compile_stack_elt_t *stack; X unsigned size; X unsigned avail; /* Offset of next open position. */ X} compile_stack_type; X X X# define INIT_COMPILE_STACK_SIZE 32 X X# define COMPILE_STACK_EMPTY (compile_stack.avail == 0) X# define COMPILE_STACK_FULL (compile_stack.avail == compile_stack.size) X X/* The next available element. */ X# define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail]) X X# endif /* not DEFINED_ONCE */ X X/* Set the bit for character C in a list. */ X# ifndef DEFINED_ONCE X# define SET_LIST_BIT(c) \ X (b[((unsigned char) (c)) / BYTEWIDTH] \ X |= 1 << (((unsigned char) c) % BYTEWIDTH)) X# endif /* DEFINED_ONCE */ X X/* Get the next unsigned number in the uncompiled pattern. */ X# define GET_UNSIGNED_NUMBER(num) \ X { \ X while (p != pend) \ X { \ X PATFETCH (c); \ X if (c < '0' || c > '9') \ X break; \ X if (num <= RE_DUP_MAX) \ X { \ X if (num < 0) \ X num = 0; \ X num = num * 10 + c - '0'; \ X } \ X } \ X } X X# ifndef DEFINED_ONCE X# if defined _LIBC || WIDE_CHAR_SUPPORT X/* The GNU C library provides support for user-defined character classes X and the functions from ISO C amendement 1. */ X# ifdef CHARCLASS_NAME_MAX X# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX X# else X/* This shouldn't happen but some implementation might still have this X problem. Use a reasonable default value. */ X# define CHAR_CLASS_MAX_LENGTH 256 X# endif X X# ifdef _LIBC X# define IS_CHAR_CLASS(string) __wctype (string) X# else X# define IS_CHAR_CLASS(string) wctype (string) X# endif X# else X# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ X X# define IS_CHAR_CLASS(string) \ X (STREQ (string, "alpha") || STREQ (string, "upper") \ X || STREQ (string, "lower") || STREQ (string, "digit") \ X || STREQ (string, "alnum") || STREQ (string, "xdigit") \ X || STREQ (string, "space") || STREQ (string, "print") \ X || STREQ (string, "punct") || STREQ (string, "graph") \ X || STREQ (string, "cntrl") || STREQ (string, "blank")) X# endif X# endif /* DEFINED_ONCE */ X X# ifndef MATCH_MAY_ALLOCATE X X/* If we cannot allocate large objects within re_match_2_internal, X we make the fail stack and register vectors global. X The fail stack, we grow to the maximum size when a regexp X is compiled. X The register vectors, we adjust in size each time we X compile a regexp, according to the number of registers it needs. */ X Xstatic PREFIX(fail_stack_type) fail_stack; X X/* Size with which the following vectors are currently allocated. X That is so we can make them bigger as needed, X but never make them smaller. */ X# ifdef DEFINED_ONCE Xstatic int regs_allocated_size; X Xstatic const char ** regstart, ** regend; Xstatic const char ** old_regstart, ** old_regend; Xstatic const char **best_regstart, **best_regend; Xstatic const char **reg_dummy; X# endif /* DEFINED_ONCE */ X Xstatic PREFIX(register_info_type) *PREFIX(reg_info); Xstatic PREFIX(register_info_type) *PREFIX(reg_info_dummy); X X/* Make the register vectors big enough for NUM_REGS registers, X but don't make them smaller. */ X Xstatic void XPREFIX(regex_grow_registers) (num_regs) X int num_regs; X{ X if (num_regs > regs_allocated_size) X { X RETALLOC_IF (regstart, num_regs, const char *); X RETALLOC_IF (regend, num_regs, const char *); X RETALLOC_IF (old_regstart, num_regs, const char *); X RETALLOC_IF (old_regend, num_regs, const char *); X RETALLOC_IF (best_regstart, num_regs, const char *); X RETALLOC_IF (best_regend, num_regs, const char *); X RETALLOC_IF (PREFIX(reg_info), num_regs, PREFIX(register_info_type)); X RETALLOC_IF (reg_dummy, num_regs, const char *); X RETALLOC_IF (PREFIX(reg_info_dummy), num_regs, PREFIX(register_info_type)); X X regs_allocated_size = num_regs; X } X} X X# endif /* not MATCH_MAY_ALLOCATE */ X X# ifndef DEFINED_ONCE Xstatic boolean group_in_compile_stack _RE_ARGS ((compile_stack_type X compile_stack, X regnum_t regnum)); X# endif /* not DEFINED_ONCE */ X X/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX. X Returns one of error codes defined in `regex.h', or zero for success. X X Assumes the `allocated' (and perhaps `buffer') and `translate' X fields are set in BUFP on entry. X X If it succeeds, results are put in BUFP (if it returns an error, the X contents of BUFP are undefined): X `buffer' is the compiled pattern; X `syntax' is set to SYNTAX; X `used' is set to the length of the compiled pattern; X `fastmap_accurate' is zero; X `re_nsub' is the number of subexpressions in PATTERN; X `not_bol' and `not_eol' are zero; X X The `fastmap' and `newline_anchor' fields are neither X examined nor set. */ X X/* Return, freeing storage we allocated. */ X# ifdef WCHAR X# define FREE_STACK_RETURN(value) \ X return (free(pattern), free(mbs_offset), free(is_binary), free (compile_stack.stack), value) X# else X# define FREE_STACK_RETURN(value) \ X return (free (compile_stack.stack), value) X# endif /* WCHAR */ X Xstatic reg_errcode_t XPREFIX(regex_compile) (ARG_PREFIX(pattern), ARG_PREFIX(size), syntax, bufp) X const char *ARG_PREFIX(pattern); X size_t ARG_PREFIX(size); X reg_syntax_t syntax; X struct re_pattern_buffer *bufp; X{ X /* We fetch characters from PATTERN here. Even though PATTERN is X `char *' (i.e., signed), we declare these variables as unsigned, so X they can be reliably used as array indices. */ X register UCHAR_T c, c1; X X#ifdef WCHAR X /* A temporary space to keep wchar_t pattern and compiled pattern. */ X CHAR_T *pattern, *COMPILED_BUFFER_VAR; X size_t size; X /* offset buffer for optimization. See convert_mbs_to_wc. */ X int *mbs_offset = NULL; X /* It hold whether each wchar_t is binary data or not. */ X char *is_binary = NULL; X /* A flag whether exactn is handling binary data or not. */ X char is_exactn_bin = FALSE; X#endif /* WCHAR */ X X /* A random temporary spot in PATTERN. */ X const CHAR_T *p1; X X /* Points to the end of the buffer, where we should append. */ X register UCHAR_T *b; X X /* Keeps track of unclosed groups. */ X compile_stack_type compile_stack; X X /* Points to the current (ending) position in the pattern. */ X#ifdef WCHAR X const CHAR_T *p; X const CHAR_T *pend; X#else /* BYTE */ X const CHAR_T *p = pattern; X const CHAR_T *pend = pattern + size; X#endif /* WCHAR */ X X /* How to translate the characters in the pattern. */ X RE_TRANSLATE_TYPE translate = bufp->translate; X X /* Address of the count-byte of the most recently inserted `exactn' X command. This makes it possible to tell if a new exact-match X character can be added to that command or if the character requires X a new `exactn' command. */ X UCHAR_T *pending_exact = 0; X X /* Address of start of the most recently finished expression. X This tells, e.g., postfix * where to find the start of its X operand. Reset at the beginning of groups and alternatives. */ X UCHAR_T *laststart = 0; X X /* Address of beginning of regexp, or inside of last group. */ X UCHAR_T *begalt; X X /* Address of the place where a forward jump should go to the end of X the containing expression. Each alternative of an `or' -- except the X last -- ends with a forward jump of this sort. */ X UCHAR_T *fixup_alt_jump = 0; X X /* Counts open-groups as they are encountered. Remembered for the X matching close-group on the compile stack, so the same register X number is put in the stop_memory as the start_memory. */ X regnum_t regnum = 0; X X#ifdef WCHAR X /* Initialize the wchar_t PATTERN and offset_buffer. */ X p = pend = pattern = TALLOC(csize + 1, CHAR_T); X mbs_offset = TALLOC(csize + 1, int); X is_binary = TALLOC(csize + 1, char); X if (pattern == NULL || mbs_offset == NULL || is_binary == NULL) X { X free(pattern); X free(mbs_offset); X free(is_binary); X return REG_ESPACE; X } X pattern[csize] = L'\0'; /* sentinel */ X size = convert_mbs_to_wcs(pattern, cpattern, csize, mbs_offset, is_binary); X pend = p + size; X if (size < 0) X { X free(pattern); X free(mbs_offset); X free(is_binary); X return REG_BADPAT; X } X#endif X X#ifdef DEBUG X DEBUG_PRINT1 ("\nCompiling pattern: "); X if (debug) X { X unsigned debug_count; X X for (debug_count = 0; debug_count < size; debug_count++) X PUT_CHAR (pattern[debug_count]); X putchar ('\n'); X } X#endif /* DEBUG */ X X /* Initialize the compile stack. */ X compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t); X if (compile_stack.stack == NULL) X { X#ifdef WCHAR X free(pattern); X free(mbs_offset); X free(is_binary); X#endif X return REG_ESPACE; X } X X compile_stack.size = INIT_COMPILE_STACK_SIZE; X compile_stack.avail = 0; X X /* Initialize the pattern buffer. */ X bufp->syntax = syntax; X bufp->fastmap_accurate = 0; X bufp->not_bol = bufp->not_eol = 0; X X /* Set `used' to zero, so that if we return an error, the pattern X printer (for debugging) will think there's no pattern. We reset it X at the end. */ X bufp->used = 0; X X /* Always count groups, whether or not bufp->no_sub is set. */ X bufp->re_nsub = 0; X X#if !defined emacs && !defined SYNTAX_TABLE X /* Initialize the syntax table. */ X init_syntax_once (); X#endif X X if (bufp->allocated == 0) X { X if (bufp->buffer) X { /* If zero allocated, but buffer is non-null, try to realloc X enough space. This loses if buffer's address is bogus, but X that is the user's responsibility. */ X#ifdef WCHAR X /* Free bufp->buffer and allocate an array for wchar_t pattern X buffer. */ X free(bufp->buffer); X COMPILED_BUFFER_VAR = TALLOC (INIT_BUF_SIZE/sizeof(UCHAR_T), X UCHAR_T); X#else X RETALLOC (COMPILED_BUFFER_VAR, INIT_BUF_SIZE, UCHAR_T); X#endif /* WCHAR */ X } X else X { /* Caller did not allocate a buffer. Do it for them. */ X COMPILED_BUFFER_VAR = TALLOC (INIT_BUF_SIZE / sizeof(UCHAR_T), X UCHAR_T); X } X X if (!COMPILED_BUFFER_VAR) FREE_STACK_RETURN (REG_ESPACE); X#ifdef WCHAR X bufp->buffer = (char*)COMPILED_BUFFER_VAR; X#endif /* WCHAR */ X bufp->allocated = INIT_BUF_SIZE; X } X#ifdef WCHAR X else X COMPILED_BUFFER_VAR = (UCHAR_T*) bufp->buffer; X#endif X X begalt = b = COMPILED_BUFFER_VAR; X X /* Loop through the uncompiled pattern until we're at the end. */ X while (p != pend) X { X PATFETCH (c); X X switch (c) X { X case '^': X { X if ( /* If at start of pattern, it's an operator. */ X p == pattern + 1 X /* If context independent, it's an operator. */ X || syntax & RE_CONTEXT_INDEP_ANCHORS X /* Otherwise, depends on what's come before. */ X || PREFIX(at_begline_loc_p) (pattern, p, syntax)) X BUF_PUSH (begline); X else X goto normal_char; X } X break; X X X case '$': X { X if ( /* If at end of pattern, it's an operator. */ X p == pend X /* If context independent, it's an operator. */ X || syntax & RE_CONTEXT_INDEP_ANCHORS X /* Otherwise, depends on what's next. */ X || PREFIX(at_endline_loc_p) (p, pend, syntax)) X BUF_PUSH (endline); X else X goto normal_char; X } X break; X X X case '+': X case '?': X if ((syntax & RE_BK_PLUS_QM) X || (syntax & RE_LIMITED_OPS)) X goto normal_char; X handle_plus: X case '*': X /* If there is no previous pattern... */ X if (!laststart) X { X if (syntax & RE_CONTEXT_INVALID_OPS) X FREE_STACK_RETURN (REG_BADRPT); X else if (!(syntax & RE_CONTEXT_INDEP_OPS)) X goto normal_char; X } X X { X /* Are we optimizing this jump? */ X boolean keep_string_p = false; X X /* 1 means zero (many) matches is allowed. */ X char zero_times_ok = 0, many_times_ok = 0; X X /* If there is a sequence of repetition chars, collapse it X down to just one (the right one). We can't combine X interval operators with these because of, e.g., `a{2}*', X which should only match an even number of `a's. */ X X for (;;) X { X zero_times_ok |= c != '+'; X many_times_ok |= c != '?'; X X if (p == pend) X break; X X PATFETCH (c); X X if (c == '*' X || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?'))) X ; X X else if (syntax & RE_BK_PLUS_QM && c == '\\') X { X if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); X X PATFETCH (c1); X if (!(c1 == '+' || c1 == '?')) X { X PATUNFETCH; X PATUNFETCH; X break; X } X X c = c1; X } X else X { X PATUNFETCH; X break; X } X X /* If we get here, we found another repeat character. */ X } X X /* Star, etc. applied to an empty pattern is equivalent X to an empty pattern. */ X if (!laststart) X break; X X /* Now we know whether or not zero matches is allowed X and also whether or not two or more matches is allowed. */ X if (many_times_ok) X { /* More than one repetition is allowed, so put in at the X end a backward relative jump from `b' to before the next X jump we're going to put in below (which jumps from X laststart to after this jump). X X But if we are at the `*' in the exact sequence `.*\n', X insert an unconditional jump backwards to the ., X instead of the beginning of the loop. This way we only X push a failure point once, instead of every time X through the loop. */ X assert (p - 1 > pattern); X X /* Allocate the space for the jump. */ X GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); X X /* We know we are not at the first character of the pattern, X because laststart was nonzero. And we've already X incremented `p', by the way, to be the character after X the `*'. Do we have to do something analogous here X for null bytes, because of RE_DOT_NOT_NULL? */ X if (TRANSLATE (*(p - 2)) == TRANSLATE ('.') X && zero_times_ok X && p < pend && TRANSLATE (*p) == TRANSLATE ('\n') X && !(syntax & RE_DOT_NEWLINE)) X { /* We have .*\n. */ X STORE_JUMP (jump, b, laststart); X keep_string_p = true; X } X else X /* Anything else. */ X STORE_JUMP (maybe_pop_jump, b, laststart - X (1 + OFFSET_ADDRESS_SIZE)); X X /* We've added more stuff to the buffer. */ X b += 1 + OFFSET_ADDRESS_SIZE; X } X X /* On failure, jump from laststart to b + 3, which will be the X end of the buffer after this jump is inserted. */ X /* ifdef WCHAR, 'b + 1 + OFFSET_ADDRESS_SIZE' instead of X 'b + 3'. */ X GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); X INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump X : on_failure_jump, X laststart, b + 1 + OFFSET_ADDRESS_SIZE); X pending_exact = 0; X b += 1 + OFFSET_ADDRESS_SIZE; X X if (!zero_times_ok) X { X /* At least one repetition is required, so insert a X `dummy_failure_jump' before the initial X `on_failure_jump' instruction of the loop. This X effects a skip over that instruction the first time X we hit that loop. */ X GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); X INSERT_JUMP (dummy_failure_jump, laststart, laststart + X 2 + 2 * OFFSET_ADDRESS_SIZE); X b += 1 + OFFSET_ADDRESS_SIZE; X } X } X break; X X X case '.': X laststart = b; X BUF_PUSH (anychar); X break; X X X case '[': X { X boolean had_char_class = false; X#ifdef WCHAR X CHAR_T range_start = 0xffffffff; X#else X unsigned int range_start = 0xffffffff; X#endif X if (p == pend) FREE_STACK_RETURN (REG_EBRACK); X X#ifdef WCHAR X /* We assume a charset(_not) structure as a wchar_t array. X charset[0] = (re_opcode_t) charset(_not) X charset[1] = l (= length of char_classes) X charset[2] = m (= length of collating_symbols) X charset[3] = n (= length of equivalence_classes) X charset[4] = o (= length of char_ranges) X charset[5] = p (= length of chars) X X charset[6] = char_class (wctype_t) X charset[6+CHAR_CLASS_SIZE] = char_class (wctype_t) X ... X charset[l+5] = char_class (wctype_t) X X charset[l+6] = collating_symbol (wchar_t) X ... X charset[l+m+5] = collating_symbol (wchar_t) X ifdef _LIBC we use the index if X _NL_COLLATE_SYMB_EXTRAMB instead of X wchar_t string. X X charset[l+m+6] = equivalence_classes (wchar_t) X ... X charset[l+m+n+5] = equivalence_classes (wchar_t) X ifdef _LIBC we use the index in X _NL_COLLATE_WEIGHT instead of X wchar_t string. X X charset[l+m+n+6] = range_start X charset[l+m+n+7] = range_end X ... X charset[l+m+n+2o+4] = range_start X charset[l+m+n+2o+5] = range_end X ifdef _LIBC we use the value looked up X in _NL_COLLATE_COLLSEQ instead of X wchar_t character. X X charset[l+m+n+2o+6] = char X ... X charset[l+m+n+2o+p+5] = char X X */ X X /* We need at least 6 spaces: the opcode, the length of X char_classes, the length of collating_symbols, the length of X equivalence_classes, the length of char_ranges, the length of X chars. */ X GET_BUFFER_SPACE (6); X X /* Save b as laststart. And We use laststart as the pointer X to the first element of the charset here. X In other words, laststart[i] indicates charset[i]. */ X laststart = b; X X /* We test `*p == '^' twice, instead of using an if X statement, so we only need one BUF_PUSH. */ X BUF_PUSH (*p == '^' ? charset_not : charset); X if (*p == '^') X p++; X X /* Push the length of char_classes, the length of X collating_symbols, the length of equivalence_classes, the X length of char_ranges and the length of chars. */ X BUF_PUSH_3 (0, 0, 0); X BUF_PUSH_2 (0, 0); X X /* Remember the first position in the bracket expression. */ X p1 = p; X X /* charset_not matches newline according to a syntax bit. */ X if ((re_opcode_t) b[-6] == charset_not X && (syntax & RE_HAT_LISTS_NOT_NEWLINE)) X { X BUF_PUSH('\n'); X laststart[5]++; /* Update the length of characters */ X } X X /* Read in characters and ranges, setting map bits. */ X for (;;) X { X if (p == pend) FREE_STACK_RETURN (REG_EBRACK); X X PATFETCH (c); X X /* \ might escape characters inside [...] and [^...]. */ X if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\') X { X if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); X X PATFETCH (c1); X BUF_PUSH(c1); X laststart[5]++; /* Update the length of chars */ X range_start = c1; X continue; X } X X /* Could be the end of the bracket expression. If it's X not (i.e., when the bracket expression is `[]' so X far), the ']' character bit gets set way below. */ X if (c == ']' && p != p1 + 1) X break; X X /* Look ahead to see if it's a range when the last thing X was a character class. */ X if (had_char_class && c == '-' && *p != ']') X FREE_STACK_RETURN (REG_ERANGE); X X /* Look ahead to see if it's a range when the last thing X was a character: if this is a hyphen not at the X beginning or the end of a list, then it's the range X operator. */ X if (c == '-' X && !(p - 2 >= pattern && p[-2] == '[') X && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^') X && *p != ']') X { X reg_errcode_t ret; X /* Allocate the space for range_start and range_end. */ X GET_BUFFER_SPACE (2); X /* Update the pointer to indicate end of buffer. */ X b += 2; X ret = wcs_compile_range (range_start, &p, pend, translate, X syntax, b, laststart); X if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); X range_start = 0xffffffff; X } X else if (p[0] == '-' && p[1] != ']') X { /* This handles ranges made up of characters only. */ X reg_errcode_t ret; X X /* Move past the `-'. */ X PATFETCH (c1); X /* Allocate the space for range_start and range_end. */ X GET_BUFFER_SPACE (2); X /* Update the pointer to indicate end of buffer. */ X b += 2; X ret = wcs_compile_range (c, &p, pend, translate, syntax, b, X laststart); X if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); X range_start = 0xffffffff; X } X X /* See if we're at the beginning of a possible character X class. */ X else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':') X { /* Leave room for the null. */ X char str[CHAR_CLASS_MAX_LENGTH + 1]; X X PATFETCH (c); X c1 = 0; X X /* If pattern is `[[:'. */ X if (p == pend) FREE_STACK_RETURN (REG_EBRACK); X X for (;;) X { X PATFETCH (c); X if ((c == ':' && *p == ']') || p == pend) X break; X if (c1 < CHAR_CLASS_MAX_LENGTH) X str[c1++] = c; X else X /* This is in any case an invalid class name. */ X str[0] = '\0'; X } X str[c1] = '\0'; X X /* If isn't a word bracketed by `[:' and `:]': X undo the ending character, the letters, and leave X the leading `:' and `[' (but store them as character). */ X if (c == ':' && *p == ']') X { X wctype_t wt; X uintptr_t alignedp; X X /* Query the character class as wctype_t. */ X wt = IS_CHAR_CLASS (str); X if (wt == 0) X FREE_STACK_RETURN (REG_ECTYPE); X X /* Throw away the ] at the end of the character X class. */ X PATFETCH (c); X X if (p == pend) FREE_STACK_RETURN (REG_EBRACK); X X /* Allocate the space for character class. */ X GET_BUFFER_SPACE(CHAR_CLASS_SIZE); X /* Update the pointer to indicate end of buffer. */ X b += CHAR_CLASS_SIZE; X /* Move data which follow character classes X not to violate the data. */ X insert_space(CHAR_CLASS_SIZE, X laststart + 6 + laststart[1], X b - 1); X alignedp = ((uintptr_t)(laststart + 6 + laststart[1]) X + __alignof__(wctype_t) - 1) X & ~(uintptr_t)(__alignof__(wctype_t) - 1); X /* Store the character class. */ X *((wctype_t*)alignedp) = wt; X /* Update length of char_classes */ X laststart[1] += CHAR_CLASS_SIZE; X X had_char_class = true; X } X else X { X c1++; X while (c1--) X PATUNFETCH; X BUF_PUSH ('['); X BUF_PUSH (':'); X laststart[5] += 2; /* Update the length of characters */ X range_start = ':'; X had_char_class = false; X } X } X else if (syntax & RE_CHAR_CLASSES && c == '[' && (*p == '=' X || *p == '.')) X { X CHAR_T str[128]; /* Should be large enough. */ X CHAR_T delim = *p; /* '=' or '.' */ X# ifdef _LIBC X uint32_t nrules = X _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); X# endif X PATFETCH (c); X c1 = 0; X X /* If pattern is `[[=' or '[[.'. */ X if (p == pend) FREE_STACK_RETURN (REG_EBRACK); X X for (;;) X { X PATFETCH (c); X if ((c == delim && *p == ']') || p == pend) X break; X if (c1 < sizeof (str) - 1) X str[c1++] = c; X else X /* This is in any case an invalid class name. */ X str[0] = '\0'; X } X str[c1] = '\0'; X X if (c == delim && *p == ']' && str[0] != '\0') X { X unsigned int i, offset; X /* If we have no collation data we use the default X collation in which each character is in a class X by itself. It also means that ASCII is the X character set and therefore we cannot have character X with more than one byte in the multibyte X representation. */ X X /* If not defined _LIBC, we push the name and X `\0' for the sake of matching performance. */ X int datasize = c1 + 1; X X# ifdef _LIBC X int32_t idx = 0; X if (nrules == 0) X# endif X { X if (c1 != 1) X FREE_STACK_RETURN (REG_ECOLLATE); X } X# ifdef _LIBC X else X { X const int32_t *table; X const int32_t *weights; X const int32_t *extra; X const int32_t *indirect; X wint_t *cp; X X /* This #include defines a local function! */ X# include X X if(delim == '=') X { X /* We push the index for equivalence class. */ X cp = (wint_t*)str; X X table = (const int32_t *) X _NL_CURRENT (LC_COLLATE, X _NL_COLLATE_TABLEWC); X weights = (const int32_t *) X _NL_CURRENT (LC_COLLATE, X _NL_COLLATE_WEIGHTWC); X extra = (const int32_t *) X _NL_CURRENT (LC_COLLATE, X _NL_COLLATE_EXTRAWC); X indirect = (const int32_t *) X _NL_CURRENT (LC_COLLATE, X _NL_COLLATE_INDIRECTWC); X X idx = findidx ((const wint_t**)&cp); X if (idx == 0 || cp < (wint_t*) str + c1) X /* This is no valid character. */ X FREE_STACK_RETURN (REG_ECOLLATE); X X str[0] = (wchar_t)idx; X } X else /* delim == '.' */ X { X /* We push collation sequence value X for collating symbol. */ X int32_t table_size; X const int32_t *symb_table; X const unsigned char *extra; X int32_t idx; X int32_t elem; X int32_t second; X int32_t hash; X char char_str[c1]; X X /* We have to convert the name to a single-byte X string. This is possible since the names X consist of ASCII characters and the internal X representation is UCS4. */ X for (i = 0; i < c1; ++i) X char_str[i] = str[i]; X X table_size = X _NL_CURRENT_WORD (LC_COLLATE, X _NL_COLLATE_SYMB_HASH_SIZEMB); X symb_table = (const int32_t *) X _NL_CURRENT (LC_COLLATE, X _NL_COLLATE_SYMB_TABLEMB); X extra = (const unsigned char *) X _NL_CURRENT (LC_COLLATE, X _NL_COLLATE_SYMB_EXTRAMB); X X /* Locate the character in the hashing table. */ X hash = elem_hash (char_str, c1); X X idx = 0; X elem = hash % table_size; X second = hash % (table_size - 2); X while (symb_table[2 * elem] != 0) X { X /* First compare the hashing value. */ X if (symb_table[2 * elem] == hash X && c1 == extra[symb_table[2 * elem + 1]] X && memcmp (char_str, X &extra[symb_table[2 * elem + 1] X + 1], c1) == 0) X { X /* Yep, this is the entry. */ X idx = symb_table[2 * elem + 1]; X idx += 1 + extra[idx]; X break; X } X X /* Next entry. */ X elem += second; X } X X if (symb_table[2 * elem] != 0) X { X /* Compute the index of the byte sequence X in the table. */ X idx += 1 + extra[idx]; X /* Adjust for the alignment. */ X idx = (idx + 3) & ~3; X X str[0] = (wchar_t) idx + 4; X } X else if (symb_table[2 * elem] == 0 && c1 == 1) X { X /* No valid character. Match it as a X single byte character. */ X had_char_class = false; X BUF_PUSH(str[0]); X /* Update the length of characters */ X laststart[5]++; X range_start = str[0]; X X /* Throw away the ] at the end of the X collating symbol. */ X PATFETCH (c); X /* exit from the switch block. */ X continue; X } X else X FREE_STACK_RETURN (REG_ECOLLATE); X } X datasize = 1; X } X# endif X /* Throw away the ] at the end of the equivalence X class (or collating symbol). */ X PATFETCH (c); X X /* Allocate the space for the equivalence class X (or collating symbol) (and '\0' if needed). */ X GET_BUFFER_SPACE(datasize); X /* Update the pointer to indicate end of buffer. */ X b += datasize; X X if (delim == '=') X { /* equivalence class */ X /* Calculate the offset of char_ranges, X which is next to equivalence_classes. */ X offset = laststart[1] + laststart[2] X + laststart[3] +6; X /* Insert space. */ X insert_space(datasize, laststart + offset, b - 1); X X /* Write the equivalence_class and \0. */ X for (i = 0 ; i < datasize ; i++) X laststart[offset + i] = str[i]; X X /* Update the length of equivalence_classes. */ X laststart[3] += datasize; X had_char_class = true; X } X else /* delim == '.' */ X { /* collating symbol */ X /* Calculate the offset of the equivalence_classes, X which is next to collating_symbols. */ X offset = laststart[1] + laststart[2] + 6; X /* Insert space and write the collationg_symbol X and \0. */ X insert_space(datasize, laststart + offset, b-1); X for (i = 0 ; i < datasize ; i++) X laststart[offset + i] = str[i]; X X /* In re_match_2_internal if range_start < -1, we X assume -range_start is the offset of the X collating symbol which is specified as X the character of the range start. So we assign X -(laststart[1] + laststart[2] + 6) to X range_start. */ X range_start = -(laststart[1] + laststart[2] + 6); X /* Update the length of collating_symbol. */ X laststart[2] += datasize; X had_char_class = false; X } X } X else X { X c1++; X while (c1--) X PATUNFETCH; X BUF_PUSH ('['); X BUF_PUSH (delim); X laststart[5] += 2; /* Update the length of characters */ X range_start = delim; X had_char_class = false; X } X } X else X { X had_char_class = false; X BUF_PUSH(c); X laststart[5]++; /* Update the length of characters */ X range_start = c; X } X } X X#else /* BYTE */ X /* Ensure that we have enough space to push a charset: the X opcode, the length count, and the bitset; 34 bytes in all. */ X GET_BUFFER_SPACE (34); X X laststart = b; X X /* We test `*p == '^' twice, instead of using an if X statement, so we only need one BUF_PUSH. */ X BUF_PUSH (*p == '^' ? charset_not : charset); X if (*p == '^') X p++; X X /* Remember the first position in the bracket expression. */ X p1 = p; X X /* Push the number of bytes in the bitmap. */ X BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH); X X /* Clear the whole map. */ X bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH); X X /* charset_not matches newline according to a syntax bit. */ X if ((re_opcode_t) b[-2] == charset_not X && (syntax & RE_HAT_LISTS_NOT_NEWLINE)) X SET_LIST_BIT ('\n'); X X /* Read in characters and ranges, setting map bits. */ X for (;;) X { X if (p == pend) FREE_STACK_RETURN (REG_EBRACK); X X PATFETCH (c); X X /* \ might escape characters inside [...] and [^...]. */ X if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\') X { X if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); X X PATFETCH (c1); X SET_LIST_BIT (c1); X range_start = c1; X continue; X } X X /* Could be the end of the bracket expression. If it's X not (i.e., when the bracket expression is `[]' so X far), the ']' character bit gets set way below. */ X if (c == ']' && p != p1 + 1) X break; X X /* Look ahead to see if it's a range when the last thing X was a character class. */ X if (had_char_class && c == '-' && *p != ']') X FREE_STACK_RETURN (REG_ERANGE); X X /* Look ahead to see if it's a range when the last thing X was a character: if this is a hyphen not at the X beginning or the end of a list, then it's the range X operator. */ X if (c == '-' X && !(p - 2 >= pattern && p[-2] == '[') X && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^') X && *p != ']') X { X reg_errcode_t ret X = byte_compile_range (range_start, &p, pend, translate, X syntax, b); X if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); X range_start = 0xffffffff; X } X X else if (p[0] == '-' && p[1] != ']') X { /* This handles ranges made up of characters only. */ X reg_errcode_t ret; X X /* Move past the `-'. */ X PATFETCH (c1); X X ret = byte_compile_range (c, &p, pend, translate, syntax, b); X if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); X range_start = 0xffffffff; X } X X /* See if we're at the beginning of a possible character X class. */ X X else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':') X { /* Leave room for the null. */ X char str[CHAR_CLASS_MAX_LENGTH + 1]; X X PATFETCH (c); X c1 = 0; X X /* If pattern is `[[:'. */ X if (p == pend) FREE_STACK_RETURN (REG_EBRACK); X X for (;;) X { X PATFETCH (c); X if ((c == ':' && *p == ']') || p == pend) X break; X if (c1 < CHAR_CLASS_MAX_LENGTH) X str[c1++] = c; X else X /* This is in any case an invalid class name. */ X str[0] = '\0'; X } X str[c1] = '\0'; X X /* If isn't a word bracketed by `[:' and `:]': X undo the ending character, the letters, and leave X the leading `:' and `[' (but set bits for them). */ X if (c == ':' && *p == ']') X { X# if defined _LIBC || WIDE_CHAR_SUPPORT X boolean is_lower = STREQ (str, "lower"); X boolean is_upper = STREQ (str, "upper"); X wctype_t wt; X int ch; X X wt = IS_CHAR_CLASS (str); X if (wt == 0) X FREE_STACK_RETURN (REG_ECTYPE); X X /* Throw away the ] at the end of the character X class. */ X PATFETCH (c); X X if (p == pend) FREE_STACK_RETURN (REG_EBRACK); X X for (ch = 0; ch < 1 << BYTEWIDTH; ++ch) X { X if (iswctype (btowc (ch), wt)) X SET_LIST_BIT (ch); X X if (translate && (is_upper || is_lower) X && (ISUPPER (ch) || ISLOWER (ch))) X SET_LIST_BIT (ch); X } X X had_char_class = true; X# else X int ch; X boolean is_alnum = STREQ (str, "alnum"); X boolean is_alpha = STREQ (str, "alpha"); X boolean is_blank = STREQ (str, "blank"); X boolean is_cntrl = STREQ (str, "cntrl"); X boolean is_digit = STREQ (str, "digit"); X boolean is_graph = STREQ (str, "graph"); X boolean is_lower = STREQ (str, "lower"); X boolean is_print = STREQ (str, "print"); X boolean is_punct = STREQ (str, "punct"); X boolean is_space = STREQ (str, "space"); X boolean is_upper = STREQ (str, "upper"); X boolean is_xdigit = STREQ (str, "xdigit"); X X if (!IS_CHAR_CLASS (str)) X FREE_STACK_RETURN (REG_ECTYPE); X X /* Throw away the ] at the end of the character X class. */ X PATFETCH (c); X X if (p == pend) FREE_STACK_RETURN (REG_EBRACK); X X for (ch = 0; ch < 1 << BYTEWIDTH; ch++) X { X /* This was split into 3 if's to X avoid an arbitrary limit in some compiler. */ X if ( (is_alnum && ISALNUM (ch)) X || (is_alpha && ISALPHA (ch)) X || (is_blank && ISBLANK (ch)) X || (is_cntrl && ISCNTRL (ch))) X SET_LIST_BIT (ch); X if ( (is_digit && ISDIGIT (ch)) X || (is_graph && ISGRAPH (ch)) X || (is_lower && ISLOWER (ch)) X || (is_print && ISPRINT (ch))) X SET_LIST_BIT (ch); X if ( (is_punct && ISPUNCT (ch)) X || (is_space && ISSPACE (ch)) X || (is_upper && ISUPPER (ch)) X || (is_xdigit && ISXDIGIT (ch))) X SET_LIST_BIT (ch); X if ( translate && (is_upper || is_lower) X && (ISUPPER (ch) || ISLOWER (ch))) X SET_LIST_BIT (ch); X } X had_char_class = true; X# endif /* libc || wctype.h */ X } X else X { X c1++; X while (c1--) X PATUNFETCH; X SET_LIST_BIT ('['); X SET_LIST_BIT (':'); X range_start = ':'; X had_char_class = false; X } X } X else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == '=') X { X unsigned char str[MB_LEN_MAX + 1]; X# ifdef _LIBC X uint32_t nrules = X _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); X# endif X X PATFETCH (c); X c1 = 0; X X /* If pattern is `[[='. */ X if (p == pend) FREE_STACK_RETURN (REG_EBRACK); X X for (;;) X { X PATFETCH (c); X if ((c == '=' && *p == ']') || p == pend) X break; X if (c1 < MB_LEN_MAX) X str[c1++] = c; X else X /* This is in any case an invalid class name. */ X str[0] = '\0'; X } X str[c1] = '\0'; X X if (c == '=' && *p == ']' && str[0] != '\0') X { X /* If we have no collation data we use the default X collation in which each character is in a class X by itself. It also means that ASCII is the X character set and therefore we cannot have character X with more than one byte in the multibyte X representation. */ X# ifdef _LIBC X if (nrules == 0) X# endif X { X if (c1 != 1) X FREE_STACK_RETURN (REG_ECOLLATE); X X /* Throw away the ] at the end of the equivalence X class. */ X PATFETCH (c); X X /* Set the bit for the character. */ X SET_LIST_BIT (str[0]); X } X# ifdef _LIBC X else X { X /* Try to match the byte sequence in `str' against X those known to the collate implementation. X First find out whether the bytes in `str' are X actually from exactly one character. */ X const int32_t *table; X const unsigned char *weights; X const unsigned char *extra; X const int32_t *indirect; X int32_t idx; X const unsigned char *cp = str; X int ch; X X /* This #include defines a local function! */ X# include X X table = (const int32_t *) X _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); X weights = (const unsigned char *) X _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB); X extra = (const unsigned char *) X _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); X indirect = (const int32_t *) X _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); X X idx = findidx (&cp); X if (idx == 0 || cp < str + c1) X /* This is no valid character. */ X FREE_STACK_RETURN (REG_ECOLLATE); X X /* Throw away the ] at the end of the equivalence X class. */ X PATFETCH (c); X X /* Now we have to go throught the whole table X and find all characters which have the same X first level weight. X X XXX Note that this is not entirely correct. X we would have to match multibyte sequences X but this is not possible with the current X implementation. */ X for (ch = 1; ch < 256; ++ch) X /* XXX This test would have to be changed if we X would allow matching multibyte sequences. */ X if (table[ch] > 0) X { X int32_t idx2 = table[ch]; X size_t len = weights[idx2]; X X /* Test whether the lenghts match. */ X if (weights[idx] == len) X { X /* They do. New compare the bytes of X the weight. */ X size_t cnt = 0; X X while (cnt < len X && (weights[idx + 1 + cnt] X == weights[idx2 + 1 + cnt])) X ++cnt; X X if (cnt == len) X /* They match. Mark the character as X acceptable. */ X SET_LIST_BIT (ch); X } X } X } X# endif X had_char_class = true; X } X else X { X c1++; X while (c1--) X PATUNFETCH; X SET_LIST_BIT ('['); X SET_LIST_BIT ('='); X range_start = '='; X had_char_class = false; X } X } X else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == '.') X { X unsigned char str[128]; /* Should be large enough. */ X# ifdef _LIBC X uint32_t nrules = X _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); X# endif X X PATFETCH (c); X c1 = 0; X X /* If pattern is `[[.'. */ X if (p == pend) FREE_STACK_RETURN (REG_EBRACK); X X for (;;) X { X PATFETCH (c); X if ((c == '.' && *p == ']') || p == pend) X break; X if (c1 < sizeof (str)) X str[c1++] = c; X else X /* This is in any case an invalid class name. */ X str[0] = '\0'; X } X str[c1] = '\0'; X X if (c == '.' && *p == ']' && str[0] != '\0') X { X /* If we have no collation data we use the default X collation in which each character is the name X for its own class which contains only the one X character. It also means that ASCII is the X character set and therefore we cannot have character X with more than one byte in the multibyte X representation. */ X# ifdef _LIBC X if (nrules == 0) X# endif X { X if (c1 != 1) X FREE_STACK_RETURN (REG_ECOLLATE); X X /* Throw away the ] at the end of the equivalence X class. */ X PATFETCH (c); X X /* Set the bit for the character. */ X SET_LIST_BIT (str[0]); X range_start = ((const unsigned char *) str)[0]; X } X# ifdef _LIBC X else X { X /* Try to match the byte sequence in `str' against X those known to the collate implementation. X First find out whether the bytes in `str' are X actually from exactly one character. */ X int32_t table_size; X const int32_t *symb_table; X const unsigned char *extra; X int32_t idx; X int32_t elem; X int32_t second; X int32_t hash; X X table_size = X _NL_CURRENT_WORD (LC_COLLATE, X _NL_COLLATE_SYMB_HASH_SIZEMB); X symb_table = (const int32_t *) X _NL_CURRENT (LC_COLLATE, X _NL_COLLATE_SYMB_TABLEMB); X extra = (const unsigned char *) X _NL_CURRENT (LC_COLLATE, X _NL_COLLATE_SYMB_EXTRAMB); X X /* Locate the character in the hashing table. */ X hash = elem_hash (str, c1); X X idx = 0; X elem = hash % table_size; X second = hash % (table_size - 2); X while (symb_table[2 * elem] != 0) X { X /* First compare the hashing value. */ X if (symb_table[2 * elem] == hash X && c1 == extra[symb_table[2 * elem + 1]] X && memcmp (str, X &extra[symb_table[2 * elem + 1] X + 1], X c1) == 0) X { X /* Yep, this is the entry. */ X idx = symb_table[2 * elem + 1]; X idx += 1 + extra[idx]; X break; X } X X /* Next entry. */ X elem += second; X } X X if (symb_table[2 * elem] == 0) X /* This is no valid character. */ X FREE_STACK_RETURN (REG_ECOLLATE); X X /* Throw away the ] at the end of the equivalence X class. */ X PATFETCH (c); X X /* Now add the multibyte character(s) we found X to the accept list. X X XXX Note that this is not entirely correct. X we would have to match multibyte sequences X but this is not possible with the current X implementation. Also, we have to match X collating symbols, which expand to more than X one file, as a whole and not allow the X individual bytes. */ X c1 = extra[idx++]; X if (c1 == 1) X range_start = extra[idx]; X while (c1-- > 0) X { X SET_LIST_BIT (extra[idx]); X ++idx; X } X } X# endif X had_char_class = false; X } X else X { X c1++; X while (c1--) X PATUNFETCH; X SET_LIST_BIT ('['); X SET_LIST_BIT ('.'); X range_start = '.'; X had_char_class = false; X } X } X else X { X had_char_class = false; X SET_LIST_BIT (c); X range_start = c; X } X } X X /* Discard any (non)matching list bytes that are all 0 at the X end of the map. Decrease the map-length byte too. */ X while ((int) b[-1] > 0 && b[b[-1] - 1] == 0) X b[-1]--; X b += b[-1]; X#endif /* WCHAR */ X } X break; X X X case '(': X if (syntax & RE_NO_BK_PARENS) X goto handle_open; X else X goto normal_char; X X X case ')': X if (syntax & RE_NO_BK_PARENS) X goto handle_close; X else X goto normal_char; X X X case '\n': X if (syntax & RE_NEWLINE_ALT) X goto handle_alt; X else X goto normal_char; X X X case '|': X if (syntax & RE_NO_BK_VBAR) X goto handle_alt; X else X goto normal_char; X X X case '{': X if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES) X goto handle_interval; X else X goto normal_char; X X X case '\\': X if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); X X /* Do not translate the character after the \, so that we can X distinguish, e.g., \B from \b, even if we normally would X translate, e.g., B to b. */ X PATFETCH_RAW (c); X X switch (c) X { X case '(': X if (syntax & RE_NO_BK_PARENS) X goto normal_backslash; X X handle_open: X bufp->re_nsub++; X regnum++; X X if (COMPILE_STACK_FULL) X { X RETALLOC (compile_stack.stack, compile_stack.size << 1, X compile_stack_elt_t); X if (compile_stack.stack == NULL) return REG_ESPACE; X X compile_stack.size <<= 1; X } X X /* These are the values to restore when we hit end of this X group. They are all relative offsets, so that if the X whole pattern moves because of realloc, they will still X be valid. */ X COMPILE_STACK_TOP.begalt_offset = begalt - COMPILED_BUFFER_VAR; X COMPILE_STACK_TOP.fixup_alt_jump X = fixup_alt_jump ? fixup_alt_jump - COMPILED_BUFFER_VAR + 1 : 0; X COMPILE_STACK_TOP.laststart_offset = b - COMPILED_BUFFER_VAR; X COMPILE_STACK_TOP.regnum = regnum; X X /* We will eventually replace the 0 with the number of X groups inner to this one. But do not push a X start_memory for groups beyond the last one we can X represent in the compiled pattern. */ X if (regnum <= MAX_REGNUM) X { X COMPILE_STACK_TOP.inner_group_offset = b X - COMPILED_BUFFER_VAR + 2; X BUF_PUSH_3 (start_memory, regnum, 0); X } X X compile_stack.avail++; X X fixup_alt_jump = 0; X laststart = 0; X begalt = b; X /* If we've reached MAX_REGNUM groups, then this open X won't actually generate any code, so we'll have to X clear pending_exact explicitly. */ X pending_exact = 0; X break; X X X case ')': X if (syntax & RE_NO_BK_PARENS) goto normal_backslash; X X if (COMPILE_STACK_EMPTY) X { X if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) X goto normal_backslash; X else X FREE_STACK_RETURN (REG_ERPAREN); X } X X handle_close: X if (fixup_alt_jump) X { /* Push a dummy failure point at the end of the X alternative for a possible future X `pop_failure_jump' to pop. See comments at X `push_dummy_failure' in `re_match_2'. */ X BUF_PUSH (push_dummy_failure); X X /* We allocated space for this jump when we assigned X to `fixup_alt_jump', in the `handle_alt' case below. */ X STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1); X } X X /* See similar code for backslashed left paren above. */ X if (COMPILE_STACK_EMPTY) X { X if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) X goto normal_char; X else X FREE_STACK_RETURN (REG_ERPAREN); X } X X /* Since we just checked for an empty stack above, this X ``can't happen''. */ X assert (compile_stack.avail != 0); X { X /* We don't just want to restore into `regnum', because X later groups should continue to be numbered higher, X as in `(ab)c(de)' -- the second group is #2. */ X regnum_t this_group_regnum; X X compile_stack.avail--; X begalt = COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.begalt_offset; X fixup_alt_jump X = COMPILE_STACK_TOP.fixup_alt_jump X ? COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.fixup_alt_jump - 1 X : 0; X laststart = COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.laststart_offset; X this_group_regnum = COMPILE_STACK_TOP.regnum; X /* If we've reached MAX_REGNUM groups, then this open X won't actually generate any code, so we'll have to X clear pending_exact explicitly. */ X pending_exact = 0; X X /* We're at the end of the group, so now we know how many X groups were inside this one. */ X if (this_group_regnum <= MAX_REGNUM) X { X UCHAR_T *inner_group_loc X = COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.inner_group_offset; X X *inner_group_loc = regnum - this_group_regnum; X BUF_PUSH_3 (stop_memory, this_group_regnum, X regnum - this_group_regnum); X } X } X break; X X X case '|': /* `\|'. */ X if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR) X goto normal_backslash; X handle_alt: X if (syntax & RE_LIMITED_OPS) X goto normal_char; X X /* Insert before the previous alternative a jump which X jumps to this alternative if the former fails. */ X GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); X INSERT_JUMP (on_failure_jump, begalt, X b + 2 + 2 * OFFSET_ADDRESS_SIZE); X pending_exact = 0; X b += 1 + OFFSET_ADDRESS_SIZE; X X /* The alternative before this one has a jump after it X which gets executed if it gets matched. Adjust that X jump so it will jump to this alternative's analogous X jump (put in below, which in turn will jump to the next X (if any) alternative's such jump, etc.). The last such X jump jumps to the correct final destination. A picture: X _____ _____ X | | | | X | v | v X a | b | c X X If we are at `b', then fixup_alt_jump right now points to a X three-byte space after `a'. We'll put in the jump, set X fixup_alt_jump to right after `b', and leave behind three X bytes which we'll fill in when we get to after `c'. */ X X if (fixup_alt_jump) X STORE_JUMP (jump_past_alt, fixup_alt_jump, b); X X /* Mark and leave space for a jump after this alternative, X to be filled in later either by next alternative or X when know we're at the end of a series of alternatives. */ X fixup_alt_jump = b; X GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); X b += 1 + OFFSET_ADDRESS_SIZE; X X laststart = 0; X begalt = b; X break; X X X case '{': X /* If \{ is a literal. */ X if (!(syntax & RE_INTERVALS) X /* If we're at `\{' and it's not the open-interval X operator. */ X || (syntax & RE_NO_BK_BRACES)) X goto normal_backslash; X X handle_interval: X { X /* If got here, then the syntax allows intervals. */ X X /* At least (most) this many matches must be made. */ X int lower_bound = -1, upper_bound = -1; X X /* Place in the uncompiled pattern (i.e., just after X the '{') to go back to if the interval is invalid. */ X const CHAR_T *beg_interval = p; X X if (p == pend) X goto invalid_interval; X X GET_UNSIGNED_NUMBER (lower_bound); X X if (c == ',') X { X GET_UNSIGNED_NUMBER (upper_bound); X if (upper_bound < 0) X upper_bound = RE_DUP_MAX; X } X else X /* Interval such as `{1}' => match exactly once. */ X upper_bound = lower_bound; X X if (! (0 <= lower_bound && lower_bound <= upper_bound)) X goto invalid_interval; X X if (!(syntax & RE_NO_BK_BRACES)) X { X if (c != '\\' || p == pend) X goto invalid_interval; X PATFETCH (c); X } X X if (c != '}') X goto invalid_interval; X X /* If it's invalid to have no preceding re. */ X if (!laststart) X { X if (syntax & RE_CONTEXT_INVALID_OPS X && !(syntax & RE_INVALID_INTERVAL_ORD)) X FREE_STACK_RETURN (REG_BADRPT); X else if (syntax & RE_CONTEXT_INDEP_OPS) X laststart = b; X else X goto unfetch_interval; X } X X /* We just parsed a valid interval. */ X X if (RE_DUP_MAX < upper_bound) X FREE_STACK_RETURN (REG_BADBR); X X /* If the upper bound is zero, don't want to succeed at X all; jump from `laststart' to `b + 3', which will be X the end of the buffer after we insert the jump. */ X /* ifdef WCHAR, 'b + 1 + OFFSET_ADDRESS_SIZE' X instead of 'b + 3'. */ X if (upper_bound == 0) X { X GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); X INSERT_JUMP (jump, laststart, b + 1 X + OFFSET_ADDRESS_SIZE); X b += 1 + OFFSET_ADDRESS_SIZE; X } X X /* Otherwise, we have a nontrivial interval. When X we're all done, the pattern will look like: X set_number_at X set_number_at X succeed_n X X jump_n X (The upper bound and `jump_n' are omitted if X `upper_bound' is 1, though.) */ X else X { /* If the upper bound is > 1, we need to insert X more at the end of the loop. */ X unsigned nbytes = 2 + 4 * OFFSET_ADDRESS_SIZE + X (upper_bound > 1) * (2 + 4 * OFFSET_ADDRESS_SIZE); X X GET_BUFFER_SPACE (nbytes); X X /* Initialize lower bound of the `succeed_n', even X though it will be set during matching by its X attendant `set_number_at' (inserted next), X because `re_compile_fastmap' needs to know. X Jump to the `jump_n' we might insert below. */ X INSERT_JUMP2 (succeed_n, laststart, X b + 1 + 2 * OFFSET_ADDRESS_SIZE X + (upper_bound > 1) * (1 + 2 * OFFSET_ADDRESS_SIZE) X , lower_bound); X b += 1 + 2 * OFFSET_ADDRESS_SIZE; X X /* Code to initialize the lower bound. Insert X before the `succeed_n'. The `5' is the last two X bytes of this `set_number_at', plus 3 bytes of X the following `succeed_n'. */ X /* ifdef WCHAR, The '1+2*OFFSET_ADDRESS_SIZE' X is the 'set_number_at', plus '1+OFFSET_ADDRESS_SIZE' X of the following `succeed_n'. */ X PREFIX(insert_op2) (set_number_at, laststart, 1 X + 2 * OFFSET_ADDRESS_SIZE, lower_bound, b); X b += 1 + 2 * OFFSET_ADDRESS_SIZE; X X if (upper_bound > 1) X { /* More than one repetition is allowed, so X append a backward jump to the `succeed_n' X that starts this interval. X X When we've reached this during matching, X we'll have matched the interval once, so X jump back only `upper_bound - 1' times. */ X STORE_JUMP2 (jump_n, b, laststart X + 2 * OFFSET_ADDRESS_SIZE + 1, X upper_bound - 1); X b += 1 + 2 * OFFSET_ADDRESS_SIZE; X X /* The location we want to set is the second X parameter of the `jump_n'; that is `b-2' as X an absolute address. `laststart' will be X the `set_number_at' we're about to insert; X `laststart+3' the number to set, the source X for the relative address. But we are X inserting into the middle of the pattern -- X so everything is getting moved up by 5. X Conclusion: (b - 2) - (laststart + 3) + 5, X i.e., b - laststart. X X We insert this at the beginning of the loop X so that if we fail during matching, we'll X reinitialize the bounds. */ X PREFIX(insert_op2) (set_number_at, laststart, X b - laststart, X upper_bound - 1, b); X b += 1 + 2 * OFFSET_ADDRESS_SIZE; X } X } X pending_exact = 0; X break; X X invalid_interval: X if (!(syntax & RE_INVALID_INTERVAL_ORD)) X FREE_STACK_RETURN (p == pend ? REG_EBRACE : REG_BADBR); X unfetch_interval: X /* Match the characters as literals. */ X p = beg_interval; X c = '{'; X if (syntax & RE_NO_BK_BRACES) X goto normal_char; X else X goto normal_backslash; X } X X#ifdef emacs X /* There is no way to specify the before_dot and after_dot X operators. rms says this is ok. --karl */ X case '=': X BUF_PUSH (at_dot); X break; X X case 's': X laststart = b; X PATFETCH (c); X BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]); X break; X X case 'S': X laststart = b; X PATFETCH (c); X BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]); X break; X#endif /* emacs */ X X X case 'w': X if (syntax & RE_NO_GNU_OPS) X goto normal_char; X laststart = b; X BUF_PUSH (wordchar); X break; X X X case 'W': X if (syntax & RE_NO_GNU_OPS) X goto normal_char; X laststart = b; X BUF_PUSH (notwordchar); X break; X X X case '<': X if (syntax & RE_NO_GNU_OPS) X goto normal_char; X BUF_PUSH (wordbeg); X break; X X case '>': X if (syntax & RE_NO_GNU_OPS) X goto normal_char; X BUF_PUSH (wordend); X break; X X case 'b': X if (syntax & RE_NO_GNU_OPS) X goto normal_char; X BUF_PUSH (wordbound); X break; X X case 'B': X if (syntax & RE_NO_GNU_OPS) X goto normal_char; X BUF_PUSH (notwordbound); X break; X X case '`': X if (syntax & RE_NO_GNU_OPS) X goto normal_char; X BUF_PUSH (begbuf); X break; X X case '\'': X if (syntax & RE_NO_GNU_OPS) X goto normal_char; X BUF_PUSH (endbuf); X break; X X case '1': case '2': case '3': case '4': case '5': X case '6': case '7': case '8': case '9': X if (syntax & RE_NO_BK_REFS) X goto normal_char; X X c1 = c - '0'; X X if (c1 > regnum) X FREE_STACK_RETURN (REG_ESUBREG); X X /* Can't back reference to a subexpression if inside of it. */ X if (group_in_compile_stack (compile_stack, (regnum_t) c1)) X goto normal_char; X X laststart = b; X BUF_PUSH_2 (duplicate, c1); X break; X X X case '+': X case '?': X if (syntax & RE_BK_PLUS_QM) X goto handle_plus; X else X goto normal_backslash; X X default: X normal_backslash: X /* You might think it would be useful for \ to mean X not to translate; but if we don't translate it X it will never match anything. */ X c = TRANSLATE (c); X goto normal_char; X } X break; X X X default: X /* Expects the character in `c'. */ X normal_char: X /* If no exactn currently being built. */ X if (!pending_exact X#ifdef WCHAR X /* If last exactn handle binary(or character) and X new exactn handle character(or binary). */ X || is_exactn_bin != is_binary[p - 1 - pattern] X#endif /* WCHAR */ X X /* If last exactn not at current position. */ X || pending_exact + *pending_exact + 1 != b X X /* We have only one byte following the exactn for the count. */ X || *pending_exact == (1 << BYTEWIDTH) - 1 X X /* If followed by a repetition operator. */ X || *p == '*' || *p == '^' X || ((syntax & RE_BK_PLUS_QM) X ? *p == '\\' && (p[1] == '+' || p[1] == '?') X : (*p == '+' || *p == '?')) X || ((syntax & RE_INTERVALS) X && ((syntax & RE_NO_BK_BRACES) X ? *p == '{' X : (p[0] == '\\' && p[1] == '{')))) X { X /* Start building a new exactn. */ X X laststart = b; X X#ifdef WCHAR X /* Is this exactn binary data or character? */ X is_exactn_bin = is_binary[p - 1 - pattern]; X if (is_exactn_bin) X BUF_PUSH_2 (exactn_bin, 0); X else X BUF_PUSH_2 (exactn, 0); X#else X BUF_PUSH_2 (exactn, 0); X#endif /* WCHAR */ X pending_exact = b - 1; X } X X BUF_PUSH (c); X (*pending_exact)++; X break; X } /* switch (c) */ X } /* while p != pend */ X X X /* Through the pattern now. */ X X if (fixup_alt_jump) X STORE_JUMP (jump_past_alt, fixup_alt_jump, b); X X if (!COMPILE_STACK_EMPTY) X FREE_STACK_RETURN (REG_EPAREN); X X /* If we don't want backtracking, force success X the first time we reach the end of the compiled pattern. */ X if (syntax & RE_NO_POSIX_BACKTRACKING) X BUF_PUSH (succeed); X X#ifdef WCHAR X free (pattern); X free (mbs_offset); X free (is_binary); X#endif X free (compile_stack.stack); X X /* We have succeeded; set the length of the buffer. */ X#ifdef WCHAR X bufp->used = (uintptr_t) b - (uintptr_t) COMPILED_BUFFER_VAR; X#else X bufp->used = b - bufp->buffer; X#endif X X#ifdef DEBUG X if (debug) X { X DEBUG_PRINT1 ("\nCompiled pattern: \n"); X PREFIX(print_compiled_pattern) (bufp); X } X#endif /* DEBUG */ X X#ifndef MATCH_MAY_ALLOCATE X /* Initialize the failure stack to the largest possible stack. This X isn't necessary unless we're trying to avoid calling alloca in X the search and match routines. */ X { X int num_regs = bufp->re_nsub + 1; X X /* Since DOUBLE_FAIL_STACK refuses to double only if the current size X is strictly greater than re_max_failures, the largest possible stack X is 2 * re_max_failures failure points. */ X if (fail_stack.size < (2 * re_max_failures * MAX_FAILURE_ITEMS)) X { X fail_stack.size = (2 * re_max_failures * MAX_FAILURE_ITEMS); X X# ifdef emacs X if (! fail_stack.stack) X fail_stack.stack X = (PREFIX(fail_stack_elt_t) *) xmalloc (fail_stack.size X * sizeof (PREFIX(fail_stack_elt_t))); X else X fail_stack.stack X = (PREFIX(fail_stack_elt_t) *) xrealloc (fail_stack.stack, X (fail_stack.size X * sizeof (PREFIX(fail_stack_elt_t)))); X# else /* not emacs */ X if (! fail_stack.stack) X fail_stack.stack X = (PREFIX(fail_stack_elt_t) *) malloc (fail_stack.size X * sizeof (PREFIX(fail_stack_elt_t))); X else X fail_stack.stack X = (PREFIX(fail_stack_elt_t) *) realloc (fail_stack.stack, X (fail_stack.size X * sizeof (PREFIX(fail_stack_elt_t)))); X# endif /* not emacs */ X } X X PREFIX(regex_grow_registers) (num_regs); X } X#endif /* not MATCH_MAY_ALLOCATE */ X X return REG_NOERROR; X} /* regex_compile */ X X/* Subroutines for `regex_compile'. */ X X/* Store OP at LOC followed by two-byte integer parameter ARG. */ X/* ifdef WCHAR, integer parameter is 1 wchar_t. */ X Xstatic void XPREFIX(store_op1) (op, loc, arg) X re_opcode_t op; X UCHAR_T *loc; X int arg; X{ X *loc = (UCHAR_T) op; X STORE_NUMBER (loc + 1, arg); X} X X X/* Like `store_op1', but for two two-byte parameters ARG1 and ARG2. */ X/* ifdef WCHAR, integer parameter is 1 wchar_t. */ X Xstatic void XPREFIX(store_op2) (op, loc, arg1, arg2) X re_opcode_t op; X UCHAR_T *loc; X int arg1, arg2; X{ X *loc = (UCHAR_T) op; X STORE_NUMBER (loc + 1, arg1); X STORE_NUMBER (loc + 1 + OFFSET_ADDRESS_SIZE, arg2); X} X X X/* Copy the bytes from LOC to END to open up three bytes of space at LOC X for OP followed by two-byte integer parameter ARG. */ X/* ifdef WCHAR, integer parameter is 1 wchar_t. */ X Xstatic void XPREFIX(insert_op1) (op, loc, arg, end) X re_opcode_t op; X UCHAR_T *loc; X int arg; X UCHAR_T *end; X{ X register UCHAR_T *pfrom = end; X register UCHAR_T *pto = end + 1 + OFFSET_ADDRESS_SIZE; X X while (pfrom != loc) X *--pto = *--pfrom; X X PREFIX(store_op1) (op, loc, arg); X} X X X/* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2. */ X/* ifdef WCHAR, integer parameter is 1 wchar_t. */ X Xstatic void XPREFIX(insert_op2) (op, loc, arg1, arg2, end) X re_opcode_t op; X UCHAR_T *loc; X int arg1, arg2; X UCHAR_T *end; X{ X register UCHAR_T *pfrom = end; X register UCHAR_T *pto = end + 1 + 2 * OFFSET_ADDRESS_SIZE; X X while (pfrom != loc) X *--pto = *--pfrom; X X PREFIX(store_op2) (op, loc, arg1, arg2); X} X X X/* P points to just after a ^ in PATTERN. Return true if that ^ comes X after an alternative or a begin-subexpression. We assume there is at X least one character before the ^. */ X Xstatic boolean XPREFIX(at_begline_loc_p) (pattern, p, syntax) X const CHAR_T *pattern, *p; X reg_syntax_t syntax; X{ X const CHAR_T *prev = p - 2; X boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\'; X X return X /* After a subexpression? */ X (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash)) X /* After an alternative? */ X || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash)); X} X X X/* The dual of at_begline_loc_p. This one is for $. We assume there is X at least one character after the $, i.e., `P < PEND'. */ X Xstatic boolean XPREFIX(at_endline_loc_p) (p, pend, syntax) X const CHAR_T *p, *pend; X reg_syntax_t syntax; X{ X const CHAR_T *next = p; X boolean next_backslash = *next == '\\'; X const CHAR_T *next_next = p + 1 < pend ? p + 1 : 0; X X return X /* Before a subexpression? */ X (syntax & RE_NO_BK_PARENS ? *next == ')' X : next_backslash && next_next && *next_next == ')') X /* Before an alternative? */ X || (syntax & RE_NO_BK_VBAR ? *next == '|' X : next_backslash && next_next && *next_next == '|'); X} X X#else /* not INSIDE_RECURSION */ X X/* Returns true if REGNUM is in one of COMPILE_STACK's elements and X false if it's not. */ X Xstatic boolean Xgroup_in_compile_stack (compile_stack, regnum) X compile_stack_type compile_stack; X regnum_t regnum; X{ X int this_element; X X for (this_element = compile_stack.avail - 1; X this_element >= 0; X this_element--) X if (compile_stack.stack[this_element].regnum == regnum) X return true; X X return false; X} X#endif /* not INSIDE_RECURSION */ X X#ifdef INSIDE_RECURSION X X#ifdef WCHAR X/* This insert space, which size is "num", into the pattern at "loc". X "end" must point the end of the allocated buffer. */ Xstatic void Xinsert_space (num, loc, end) X int num; X CHAR_T *loc; X CHAR_T *end; X{ X register CHAR_T *pto = end; X register CHAR_T *pfrom = end - num; X X while (pfrom >= loc) X *pto-- = *pfrom--; X} X#endif /* WCHAR */ X X#ifdef WCHAR Xstatic reg_errcode_t Xwcs_compile_range (range_start_char, p_ptr, pend, translate, syntax, b, X char_set) X CHAR_T range_start_char; X const CHAR_T **p_ptr, *pend; X CHAR_T *char_set, *b; X RE_TRANSLATE_TYPE translate; X reg_syntax_t syntax; X{ X const CHAR_T *p = *p_ptr; X CHAR_T range_start, range_end; X reg_errcode_t ret; X# ifdef _LIBC X uint32_t nrules; X uint32_t start_val, end_val; X# endif X if (p == pend) X return REG_ERANGE; X X# ifdef _LIBC X nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); X if (nrules != 0) X { X const char *collseq = (const char *) _NL_CURRENT(LC_COLLATE, X _NL_COLLATE_COLLSEQWC); X const unsigned char *extra = (const unsigned char *) X _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); X X if (range_start_char < -1) X { X /* range_start is a collating symbol. */ X int32_t *wextra; X /* Retreive the index and get collation sequence value. */ X wextra = (int32_t*)(extra + char_set[-range_start_char]); X start_val = wextra[1 + *wextra]; X } X else X start_val = collseq_table_lookup(collseq, TRANSLATE(range_start_char)); X X end_val = collseq_table_lookup (collseq, TRANSLATE (p[0])); X X /* Report an error if the range is empty and the syntax prohibits X this. */ X ret = ((syntax & RE_NO_EMPTY_RANGES) X && (start_val > end_val))? REG_ERANGE : REG_NOERROR; X X /* Insert space to the end of the char_ranges. */ X insert_space(2, b - char_set[5] - 2, b - 1); X *(b - char_set[5] - 2) = (wchar_t)start_val; X *(b - char_set[5] - 1) = (wchar_t)end_val; X char_set[4]++; /* ranges_index */ X } X else X# endif X { X range_start = (range_start_char >= 0)? TRANSLATE (range_start_char): X range_start_char; X range_end = TRANSLATE (p[0]); X /* Report an error if the range is empty and the syntax prohibits X this. */ X ret = ((syntax & RE_NO_EMPTY_RANGES) X && (range_start > range_end))? REG_ERANGE : REG_NOERROR; X X /* Insert space to the end of the char_ranges. */ X insert_space(2, b - char_set[5] - 2, b - 1); X *(b - char_set[5] - 2) = range_start; X *(b - char_set[5] - 1) = range_end; X char_set[4]++; /* ranges_index */ X } X /* Have to increment the pointer into the pattern string, so the X caller isn't still at the ending character. */ X (*p_ptr)++; X X return ret; X} X#else /* BYTE */ X/* Read the ending character of a range (in a bracket expression) from the X uncompiled pattern *P_PTR (which ends at PEND). We assume the X starting character is in `P[-2]'. (`P[-1]' is the character `-'.) X Then we set the translation of all bits between the starting and X ending characters (inclusive) in the compiled pattern B. X X Return an error code. X X We use these short variable names so we can use the same macros as X `regex_compile' itself. */ X Xstatic reg_errcode_t Xbyte_compile_range (range_start_char, p_ptr, pend, translate, syntax, b) X unsigned int range_start_char; X const char **p_ptr, *pend; X RE_TRANSLATE_TYPE translate; X reg_syntax_t syntax; X unsigned char *b; X{ X unsigned this_char; X const char *p = *p_ptr; X reg_errcode_t ret; X# if _LIBC X const unsigned char *collseq; X unsigned int start_colseq; X unsigned int end_colseq; X# else X unsigned end_char; X# endif X X if (p == pend) X return REG_ERANGE; X X /* Have to increment the pointer into the pattern string, so the X caller isn't still at the ending character. */ X (*p_ptr)++; X X /* Report an error if the range is empty and the syntax prohibits this. */ X ret = syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR; X X# if _LIBC X collseq = (const unsigned char *) _NL_CURRENT (LC_COLLATE, X _NL_COLLATE_COLLSEQMB); X X start_colseq = collseq[(unsigned char) TRANSLATE (range_start_char)]; X end_colseq = collseq[(unsigned char) TRANSLATE (p[0])]; X for (this_char = 0; this_char <= (unsigned char) -1; ++this_char) X { X unsigned int this_colseq = collseq[(unsigned char) TRANSLATE (this_char)]; X X if (start_colseq <= this_colseq && this_colseq <= end_colseq) X { X SET_LIST_BIT (TRANSLATE (this_char)); X ret = REG_NOERROR; X } X } X# else X /* Here we see why `this_char' has to be larger than an `unsigned X char' -- we would otherwise go into an infinite loop, since all X characters <= 0xff. */ X range_start_char = TRANSLATE (range_start_char); X /* TRANSLATE(p[0]) is casted to char (not unsigned char) in TRANSLATE, X and some compilers cast it to int implicitly, so following for_loop X may fall to (almost) infinite loop. X e.g. If translate[p[0]] = 0xff, end_char may equals to 0xffffffff. X To avoid this, we cast p[0] to unsigned int and truncate it. */ X end_char = ((unsigned)TRANSLATE(p[0]) & ((1 << BYTEWIDTH) - 1)); X X for (this_char = range_start_char; this_char <= end_char; ++this_char) X { X SET_LIST_BIT (TRANSLATE (this_char)); X ret = REG_NOERROR; X } X# endif X X return ret; X} X#endif /* WCHAR */ X X/* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in X BUFP. A fastmap records which of the (1 << BYTEWIDTH) possible X characters can start a string that matches the pattern. This fastmap X is used by re_search to skip quickly over impossible starting points. X X The caller must supply the address of a (1 << BYTEWIDTH)-byte data X area as BUFP->fastmap. X X We set the `fastmap', `fastmap_accurate', and `can_be_null' fields in X the pattern buffer. X X Returns 0 if we succeed, -2 if an internal error. */ X X#ifdef WCHAR X/* local function for re_compile_fastmap. X truncate wchar_t character to char. */ Xstatic unsigned char truncate_wchar (CHAR_T c); X Xstatic unsigned char Xtruncate_wchar (c) X CHAR_T c; X{ X unsigned char buf[MB_CUR_MAX]; X mbstate_t state; X int retval; X memset (&state, '\0', sizeof (state)); X retval = wcrtomb (buf, c, &state); X return retval > 0 ? buf[0] : (unsigned char) c; X} X#endif /* WCHAR */ X Xstatic int XPREFIX(re_compile_fastmap) (bufp) X struct re_pattern_buffer *bufp; X{ X int j, k; X#ifdef MATCH_MAY_ALLOCATE X PREFIX(fail_stack_type) fail_stack; X#endif X#ifndef REGEX_MALLOC X char *destination; X#endif X X register char *fastmap = bufp->fastmap; X X#ifdef WCHAR X /* We need to cast pattern to (wchar_t*), because we casted this compiled X pattern to (char*) in regex_compile. */ X UCHAR_T *pattern = (UCHAR_T*)bufp->buffer; X register UCHAR_T *pend = (UCHAR_T*) (bufp->buffer + bufp->used); X#else /* BYTE */ X UCHAR_T *pattern = bufp->buffer; X register UCHAR_T *pend = pattern + bufp->used; X#endif /* WCHAR */ X UCHAR_T *p = pattern; X X#ifdef REL_ALLOC X /* This holds the pointer to the failure stack, when X it is allocated relocatably. */ X fail_stack_elt_t *failure_stack_ptr; X#endif X X /* Assume that each path through the pattern can be null until X proven otherwise. We set this false at the bottom of switch X statement, to which we get only if a particular path doesn't X match the empty string. */ X boolean path_can_be_null = true; X X /* We aren't doing a `succeed_n' to begin with. */ X boolean succeed_n_p = false; X X assert (fastmap != NULL && p != NULL); X X INIT_FAIL_STACK (); X bzero (fastmap, 1 << BYTEWIDTH); /* Assume nothing's valid. */ X bufp->fastmap_accurate = 1; /* It will be when we're done. */ X bufp->can_be_null = 0; X X while (1) X { X if (p == pend || *p == succeed) X { X /* We have reached the (effective) end of pattern. */ X if (!FAIL_STACK_EMPTY ()) X { X bufp->can_be_null |= path_can_be_null; X X /* Reset for next path. */ X path_can_be_null = true; X X p = fail_stack.stack[--fail_stack.avail].pointer; X X continue; X } X else X break; X } X X /* We should never be about to go beyond the end of the pattern. */ X assert (p < pend); X X switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++)) X { X X /* I guess the idea here is to simply not bother with a fastmap X if a backreference is used, since it's too hard to figure out X the fastmap for the corresponding group. Setting X `can_be_null' stops `re_search_2' from using the fastmap, so X that is all we do. */ X case duplicate: X bufp->can_be_null = 1; X goto done; X X X /* Following are the cases which match a character. These end X with `break'. */ X X#ifdef WCHAR X case exactn: X fastmap[truncate_wchar(p[1])] = 1; X break; X#else /* BYTE */ X case exactn: X fastmap[p[1]] = 1; X break; X#endif /* WCHAR */ X#ifdef MBS_SUPPORT X case exactn_bin: X fastmap[p[1]] = 1; X break; X#endif X X#ifdef WCHAR X /* It is hard to distinguish fastmap from (multi byte) characters X which depends on current locale. */ X case charset: X case charset_not: X case wordchar: X case notwordchar: X bufp->can_be_null = 1; X goto done; X#else /* BYTE */ X case charset: X for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) X if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) X fastmap[j] = 1; X break; X X X case charset_not: X /* Chars beyond end of map must be allowed. */ X for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++) X fastmap[j] = 1; X X for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) X if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))) X fastmap[j] = 1; X break; X X X case wordchar: X for (j = 0; j < (1 << BYTEWIDTH); j++) X if (SYNTAX (j) == Sword) X fastmap[j] = 1; X break; X X X case notwordchar: X for (j = 0; j < (1 << BYTEWIDTH); j++) X if (SYNTAX (j) != Sword) X fastmap[j] = 1; X break; X#endif /* WCHAR */ X X case anychar: X { X int fastmap_newline = fastmap['\n']; X X /* `.' matches anything ... */ X for (j = 0; j < (1 << BYTEWIDTH); j++) X fastmap[j] = 1; X X /* ... except perhaps newline. */ X if (!(bufp->syntax & RE_DOT_NEWLINE)) X fastmap['\n'] = fastmap_newline; X X /* Return if we have already set `can_be_null'; if we have, X then the fastmap is irrelevant. Something's wrong here. */ X else if (bufp->can_be_null) X goto done; X X /* Otherwise, have to check alternative paths. */ X break; X } X X#ifdef emacs X case syntaxspec: X k = *p++; X for (j = 0; j < (1 << BYTEWIDTH); j++) X if (SYNTAX (j) == (enum syntaxcode) k) X fastmap[j] = 1; X break; X X X case notsyntaxspec: X k = *p++; X for (j = 0; j < (1 << BYTEWIDTH); j++) X if (SYNTAX (j) != (enum syntaxcode) k) X fastmap[j] = 1; X break; X X X /* All cases after this match the empty string. These end with X `continue'. */ X X X case before_dot: X case at_dot: X case after_dot: X continue; X#endif /* emacs */ X X X case no_op: X case begline: X case endline: X case begbuf: X case endbuf: X case wordbound: X case notwordbound: X case wordbeg: X case wordend: X case push_dummy_failure: X continue; X X X case jump_n: X case pop_failure_jump: X case maybe_pop_jump: X case jump: X case jump_past_alt: X case dummy_failure_jump: X EXTRACT_NUMBER_AND_INCR (j, p); X p += j; X if (j > 0) X continue; X X /* Jump backward implies we just went through the body of a X loop and matched nothing. Opcode jumped to should be X `on_failure_jump' or `succeed_n'. Just treat it like an X ordinary jump. For a * loop, it has pushed its failure X point already; if so, discard that as redundant. */ X if ((re_opcode_t) *p != on_failure_jump X && (re_opcode_t) *p != succeed_n) X continue; X X p++; X EXTRACT_NUMBER_AND_INCR (j, p); X p += j; X X /* If what's on the stack is where we are now, pop it. */ X if (!FAIL_STACK_EMPTY () X && fail_stack.stack[fail_stack.avail - 1].pointer == p) X fail_stack.avail--; X X continue; X X X case on_failure_jump: X case on_failure_keep_string_jump: X handle_on_failure_jump: X EXTRACT_NUMBER_AND_INCR (j, p); X X /* For some patterns, e.g., `(a?)?', `p+j' here points to the X end of the pattern. We don't want to push such a point, X since when we restore it above, entering the switch will X increment `p' past the end of the pattern. We don't need X to push such a point since we obviously won't find any more X fastmap entries beyond `pend'. Such a pattern can match X the null string, though. */ X if (p + j < pend) X { X if (!PUSH_PATTERN_OP (p + j, fail_stack)) X { X RESET_FAIL_STACK (); X return -2; X } X } X else X bufp->can_be_null = 1; X X if (succeed_n_p) X { X EXTRACT_NUMBER_AND_INCR (k, p); /* Skip the n. */ X succeed_n_p = false; X } X X continue; X X X case succeed_n: X /* Get to the number of times to succeed. */ X p += OFFSET_ADDRESS_SIZE; X X /* Increment p past the n for when k != 0. */ X EXTRACT_NUMBER_AND_INCR (k, p); X if (k == 0) X { X p -= 2 * OFFSET_ADDRESS_SIZE; X succeed_n_p = true; /* Spaghetti code alert. */ X goto handle_on_failure_jump; X } X continue; X X X case set_number_at: X p += 2 * OFFSET_ADDRESS_SIZE; X continue; X X X case start_memory: X case stop_memory: X p += 2; X continue; X X X default: X abort (); /* We have listed all the cases. */ X } /* switch *p++ */ X X /* Getting here means we have found the possible starting X characters for one path of the pattern -- and that the empty X string does not match. We need not follow this path further. X Instead, look at the next alternative (remembered on the X stack), or quit if no more. The test at the top of the loop X does these things. */ X path_can_be_null = false; X p = pend; X } /* while p */ X X /* Set `can_be_null' for the last path (also the first path, if the X pattern is empty). */ X bufp->can_be_null |= path_can_be_null; X X done: X RESET_FAIL_STACK (); X return 0; X} X X#else /* not INSIDE_RECURSION */ X Xint Xre_compile_fastmap (bufp) X struct re_pattern_buffer *bufp; X{ X# ifdef MBS_SUPPORT X if (MB_CUR_MAX != 1) X return wcs_re_compile_fastmap(bufp); X else X# endif X return byte_re_compile_fastmap(bufp); X} /* re_compile_fastmap */ X#ifdef _LIBC Xweak_alias (__re_compile_fastmap, re_compile_fastmap) X#endif X X X/* Set REGS to hold NUM_REGS registers, storing them in STARTS and X ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use X this memory for recording register information. STARTS and ENDS X must be allocated using the malloc library routine, and must each X be at least NUM_REGS * sizeof (regoff_t) bytes long. X X If NUM_REGS == 0, then subsequent matches should allocate their own X register data. X X Unless this function is called, the first search or match using X PATTERN_BUFFER will allocate its own register data, without X freeing the old data. */ X Xvoid Xre_set_registers (bufp, regs, num_regs, starts, ends) X struct re_pattern_buffer *bufp; X struct re_registers *regs; X unsigned num_regs; X regoff_t *starts, *ends; X{ X if (num_regs) X { X bufp->regs_allocated = REGS_REALLOCATE; X regs->num_regs = num_regs; X regs->start = starts; X regs->end = ends; X } X else X { X bufp->regs_allocated = REGS_UNALLOCATED; X regs->num_regs = 0; X regs->start = regs->end = (regoff_t *) 0; X } X} X#ifdef _LIBC Xweak_alias (__re_set_registers, re_set_registers) X#endif X X/* Searching routines. */ X X/* Like re_search_2, below, but only one string is specified, and X doesn't let you say where to stop matching. */ X Xint Xre_search (bufp, string, size, startpos, range, regs) X struct re_pattern_buffer *bufp; X const char *string; X int size, startpos, range; X struct re_registers *regs; X{ X return re_search_2 (bufp, NULL, 0, string, size, startpos, range, X regs, size); X} X#ifdef _LIBC Xweak_alias (__re_search, re_search) X#endif X X X/* Using the compiled pattern in BUFP->buffer, first tries to match the X virtual concatenation of STRING1 and STRING2, starting first at index X STARTPOS, then at STARTPOS + 1, and so on. X X STRING1 and STRING2 have length SIZE1 and SIZE2, respectively. X X RANGE is how far to scan while trying to match. RANGE = 0 means try X only at STARTPOS; in general, the last start tried is STARTPOS + X RANGE. X X In REGS, return the indices of the virtual concatenation of STRING1 X and STRING2 that matched the entire BUFP->buffer and its contained X subexpressions. X X Do not consider matching one past the index STOP in the virtual X concatenation of STRING1 and STRING2. X X We return either the position in the strings at which the match was X found, -1 if no match, or -2 if error (such as failure X stack overflow). */ X Xint Xre_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop) X struct re_pattern_buffer *bufp; X const char *string1, *string2; X int size1, size2; X int startpos; X int range; X struct re_registers *regs; X int stop; X{ X# ifdef MBS_SUPPORT X if (MB_CUR_MAX != 1) X return wcs_re_search_2 (bufp, string1, size1, string2, size2, startpos, X range, regs, stop); X else X# endif X return byte_re_search_2 (bufp, string1, size1, string2, size2, startpos, X range, regs, stop); X} /* re_search_2 */ X#ifdef _LIBC Xweak_alias (__re_search_2, re_search_2) X#endif X X#endif /* not INSIDE_RECURSION */ X X#ifdef INSIDE_RECURSION X X#ifdef MATCH_MAY_ALLOCATE X# define FREE_VAR(var) if (var) REGEX_FREE (var); var = NULL X#else X# define FREE_VAR(var) if (var) free (var); var = NULL X#endif X X#ifdef WCHAR X# define MAX_ALLOCA_SIZE 2000 X X# define FREE_WCS_BUFFERS() \ X do { \ X if (size1 > MAX_ALLOCA_SIZE) \ X { \ X free (wcs_string1); \ X free (mbs_offset1); \ X } \ X else \ X { \ X FREE_VAR (wcs_string1); \ X FREE_VAR (mbs_offset1); \ X } \ X if (size2 > MAX_ALLOCA_SIZE) \ X { \ X free (wcs_string2); \ X free (mbs_offset2); \ X } \ X else \ X { \ X FREE_VAR (wcs_string2); \ X FREE_VAR (mbs_offset2); \ X } \ X } while (0) X X#endif X X Xstatic int XPREFIX(re_search_2) (bufp, string1, size1, string2, size2, startpos, range, X regs, stop) X struct re_pattern_buffer *bufp; X const char *string1, *string2; X int size1, size2; X int startpos; X int range; X struct re_registers *regs; X int stop; X{ X int val; X register char *fastmap = bufp->fastmap; X register RE_TRANSLATE_TYPE translate = bufp->translate; X int total_size = size1 + size2; X int endpos = startpos + range; X#ifdef WCHAR X /* We need wchar_t* buffers correspond to cstring1, cstring2. */ X wchar_t *wcs_string1 = NULL, *wcs_string2 = NULL; X /* We need the size of wchar_t buffers correspond to csize1, csize2. */ X int wcs_size1 = 0, wcs_size2 = 0; X /* offset buffer for optimizatoin. See convert_mbs_to_wc. */ X int *mbs_offset1 = NULL, *mbs_offset2 = NULL; X /* They hold whether each wchar_t is binary data or not. */ X char *is_binary = NULL; X#endif /* WCHAR */ X X /* Check for out-of-range STARTPOS. */ X if (startpos < 0 || startpos > total_size) X return -1; X X /* Fix up RANGE if it might eventually take us outside X the virtual concatenation of STRING1 and STRING2. X Make sure we won't move STARTPOS below 0 or above TOTAL_SIZE. */ X if (endpos < 0) X range = 0 - startpos; X else if (endpos > total_size) X range = total_size - startpos; X X /* If the search isn't to be a backwards one, don't waste time in a X search for a pattern that must be anchored. */ X if (bufp->used > 0 && range > 0 X && ((re_opcode_t) bufp->buffer[0] == begbuf X /* `begline' is like `begbuf' if it cannot match at newlines. */ X || ((re_opcode_t) bufp->buffer[0] == begline X && !bufp->newline_anchor))) X { X if (startpos > 0) X return -1; X else X range = 1; X } X X#ifdef emacs X /* In a forward search for something that starts with \=. X don't keep searching past point. */ X if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == at_dot && range > 0) X { X range = PT - startpos; X if (range <= 0) X return -1; X } X#endif /* emacs */ X X /* Update the fastmap now if not correct already. */ X if (fastmap && !bufp->fastmap_accurate) X if (re_compile_fastmap (bufp) == -2) X return -2; X X#ifdef WCHAR X /* Allocate wchar_t array for wcs_string1 and wcs_string2 and X fill them with converted string. */ X if (size1 != 0) X { X if (size1 > MAX_ALLOCA_SIZE) X { X wcs_string1 = TALLOC (size1 + 1, CHAR_T); X mbs_offset1 = TALLOC (size1 + 1, int); X is_binary = TALLOC (size1 + 1, char); X } X else X { X wcs_string1 = REGEX_TALLOC (size1 + 1, CHAR_T); X mbs_offset1 = REGEX_TALLOC (size1 + 1, int); X is_binary = REGEX_TALLOC (size1 + 1, char); X } X if (!wcs_string1 || !mbs_offset1 || !is_binary) X { X if (size1 > MAX_ALLOCA_SIZE) X { X free (wcs_string1); X free (mbs_offset1); X free (is_binary); X } X else X { X FREE_VAR (wcs_string1); X FREE_VAR (mbs_offset1); X FREE_VAR (is_binary); X } X return -2; X } X wcs_size1 = convert_mbs_to_wcs(wcs_string1, string1, size1, X mbs_offset1, is_binary); X wcs_string1[wcs_size1] = L'\0'; /* for a sentinel */ X if (size1 > MAX_ALLOCA_SIZE) X free (is_binary); X else X FREE_VAR (is_binary); X } X if (size2 != 0) X { X if (size2 > MAX_ALLOCA_SIZE) X { X wcs_string2 = TALLOC (size2 + 1, CHAR_T); X mbs_offset2 = TALLOC (size2 + 1, int); X is_binary = TALLOC (size2 + 1, char); X } X else X { X wcs_string2 = REGEX_TALLOC (size2 + 1, CHAR_T); X mbs_offset2 = REGEX_TALLOC (size2 + 1, int); X is_binary = REGEX_TALLOC (size2 + 1, char); X } X if (!wcs_string2 || !mbs_offset2 || !is_binary) X { X FREE_WCS_BUFFERS (); X if (size2 > MAX_ALLOCA_SIZE) X free (is_binary); X else X FREE_VAR (is_binary); X return -2; X } X wcs_size2 = convert_mbs_to_wcs(wcs_string2, string2, size2, X mbs_offset2, is_binary); X wcs_string2[wcs_size2] = L'\0'; /* for a sentinel */ X if (size2 > MAX_ALLOCA_SIZE) X free (is_binary); X else X FREE_VAR (is_binary); X } X#endif /* WCHAR */ X X X /* Loop through the string, looking for a place to start matching. */ X for (;;) X { X /* If a fastmap is supplied, skip quickly over characters that X cannot be the start of a match. If the pattern can match the X null string, however, we don't need to skip characters; we want X the first null string. */ X if (fastmap && startpos < total_size && !bufp->can_be_null) X { X if (range > 0) /* Searching forwards. */ X { X register const char *d; X register int lim = 0; X int irange = range; X X if (startpos < size1 && startpos + range >= size1) X lim = range - (size1 - startpos); X X d = (startpos >= size1 ? string2 - size1 : string1) + startpos; X X /* Written out as an if-else to avoid testing `translate' X inside the loop. */ X if (translate) X while (range > lim X && !fastmap[(unsigned char) X translate[(unsigned char) *d++]]) X range--; X else X while (range > lim && !fastmap[(unsigned char) *d++]) X range--; X X startpos += irange - range; X } X else /* Searching backwards. */ X { X register CHAR_T c = (size1 == 0 || startpos >= size1 X ? string2[startpos - size1] X : string1[startpos]); X X if (!fastmap[(unsigned char) TRANSLATE (c)]) X goto advance; X } X } X X /* If can't match the null string, and that's all we have left, fail. */ X if (range >= 0 && startpos == total_size && fastmap X && !bufp->can_be_null) X { X#ifdef WCHAR X FREE_WCS_BUFFERS (); X#endif X return -1; X } X X#ifdef WCHAR X val = wcs_re_match_2_internal (bufp, string1, size1, string2, X size2, startpos, regs, stop, X wcs_string1, wcs_size1, X wcs_string2, wcs_size2, X mbs_offset1, mbs_offset2); X#else /* BYTE */ X val = byte_re_match_2_internal (bufp, string1, size1, string2, X size2, startpos, regs, stop); X#endif /* BYTE */ X X#ifndef REGEX_MALLOC X# ifdef C_ALLOCA X alloca (0); X# endif X#endif X X if (val >= 0) X { X#ifdef WCHAR X FREE_WCS_BUFFERS (); X#endif X return startpos; X } X X if (val == -2) X { X#ifdef WCHAR X FREE_WCS_BUFFERS (); X#endif X return -2; X } X X advance: X if (!range) X break; X else if (range > 0) X { X range--; X startpos++; X } X else X { X range++; X startpos--; X } X } X#ifdef WCHAR X FREE_WCS_BUFFERS (); X#endif X return -1; X} X X#ifdef WCHAR X/* This converts PTR, a pointer into one of the search wchar_t strings X `string1' and `string2' into an multibyte string offset from the X beginning of that string. We use mbs_offset to optimize. X See convert_mbs_to_wcs. */ X# define POINTER_TO_OFFSET(ptr) \ X (FIRST_STRING_P (ptr) \ X ? ((regoff_t)(mbs_offset1 != NULL? mbs_offset1[(ptr)-string1] : 0)) \ X : ((regoff_t)((mbs_offset2 != NULL? mbs_offset2[(ptr)-string2] : 0) \ X + csize1))) X#else /* BYTE */ X/* This converts PTR, a pointer into one of the search strings `string1' X and `string2' into an offset from the beginning of that string. */ X# define POINTER_TO_OFFSET(ptr) \ X (FIRST_STRING_P (ptr) \ X ? ((regoff_t) ((ptr) - string1)) \ X : ((regoff_t) ((ptr) - string2 + size1))) X#endif /* WCHAR */ X X/* Macros for dealing with the split strings in re_match_2. */ X X#define MATCHING_IN_FIRST_STRING (dend == end_match_1) X X/* Call before fetching a character with *d. This switches over to X string2 if necessary. */ X#define PREFETCH() \ X while (d == dend) \ X { \ X /* End of string2 => fail. */ \ X if (dend == end_match_2) \ X goto fail; \ X /* End of string1 => advance to string2. */ \ X d = string2; \ X dend = end_match_2; \ X } X X/* Test if at very beginning or at very end of the virtual concatenation X of `string1' and `string2'. If only one string, it's `string2'. */ X#define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2) X#define AT_STRINGS_END(d) ((d) == end2) X X X/* Test if D points to a character which is word-constituent. We have X two special cases to check for: if past the end of string1, look at X the first character in string2; and if before the beginning of X string2, look at the last character in string1. */ X#ifdef WCHAR X/* Use internationalized API instead of SYNTAX. */ X# define WORDCHAR_P(d) \ X (iswalnum ((wint_t)((d) == end1 ? *string2 \ X : (d) == string2 - 1 ? *(end1 - 1) : *(d))) != 0 \ X || ((d) == end1 ? *string2 \ X : (d) == string2 - 1 ? *(end1 - 1) : *(d)) == L'_') X#else /* BYTE */ X# define WORDCHAR_P(d) \ X (SYNTAX ((d) == end1 ? *string2 \ X : (d) == string2 - 1 ? *(end1 - 1) : *(d)) \ X == Sword) X#endif /* WCHAR */ X X/* Disabled due to a compiler bug -- see comment at case wordbound */ X#if 0 X/* Test if the character before D and the one at D differ with respect X to being word-constituent. */ X#define AT_WORD_BOUNDARY(d) \ X (AT_STRINGS_BEG (d) || AT_STRINGS_END (d) \ X || WORDCHAR_P (d - 1) != WORDCHAR_P (d)) X#endif X X/* Free everything we malloc. */ X#ifdef MATCH_MAY_ALLOCATE X# ifdef WCHAR X# define FREE_VARIABLES() \ X do { \ X REGEX_FREE_STACK (fail_stack.stack); \ X FREE_VAR (regstart); \ X FREE_VAR (regend); \ X FREE_VAR (old_regstart); \ X FREE_VAR (old_regend); \ X FREE_VAR (best_regstart); \ X FREE_VAR (best_regend); \ X FREE_VAR (reg_info); \ X FREE_VAR (reg_dummy); \ X FREE_VAR (reg_info_dummy); \ X if (!cant_free_wcs_buf) \ X { \ X FREE_VAR (string1); \ X FREE_VAR (string2); \ X FREE_VAR (mbs_offset1); \ X FREE_VAR (mbs_offset2); \ X } \ X } while (0) X# else /* BYTE */ X# define FREE_VARIABLES() \ X do { \ X REGEX_FREE_STACK (fail_stack.stack); \ X FREE_VAR (regstart); \ X FREE_VAR (regend); \ X FREE_VAR (old_regstart); \ X FREE_VAR (old_regend); \ X FREE_VAR (best_regstart); \ X FREE_VAR (best_regend); \ X FREE_VAR (reg_info); \ X FREE_VAR (reg_dummy); \ X FREE_VAR (reg_info_dummy); \ X } while (0) X# endif /* WCHAR */ X#else X# ifdef WCHAR X# define FREE_VARIABLES() \ X do { \ X if (!cant_free_wcs_buf) \ X { \ X FREE_VAR (string1); \ X FREE_VAR (string2); \ X FREE_VAR (mbs_offset1); \ X FREE_VAR (mbs_offset2); \ X } \ X } while (0) X# else /* BYTE */ X# define FREE_VARIABLES() ((void)0) /* Do nothing! But inhibit gcc warning. */ X# endif /* WCHAR */ X#endif /* not MATCH_MAY_ALLOCATE */ X X/* These values must meet several constraints. They must not be valid X register values; since we have a limit of 255 registers (because X we use only one byte in the pattern for the register number), we can X use numbers larger than 255. They must differ by 1, because of X NUM_FAILURE_ITEMS above. And the value for the lowest register must X be larger than the value for the highest register, so we do not try X to actually save any registers when none are active. */ X#define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH) X#define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1) X X#else /* not INSIDE_RECURSION */ X/* Matching routines. */ X X#ifndef emacs /* Emacs never uses this. */ X/* re_match is like re_match_2 except it takes only a single string. */ X Xint Xre_match (bufp, string, size, pos, regs) X struct re_pattern_buffer *bufp; X const char *string; X int size, pos; X struct re_registers *regs; X{ X int result; X# ifdef MBS_SUPPORT X if (MB_CUR_MAX != 1) X result = wcs_re_match_2_internal (bufp, NULL, 0, string, size, X pos, regs, size, X NULL, 0, NULL, 0, NULL, NULL); X else X# endif X result = byte_re_match_2_internal (bufp, NULL, 0, string, size, X pos, regs, size); X# ifndef REGEX_MALLOC X# ifdef C_ALLOCA X alloca (0); X# endif X# endif X return result; X} X# ifdef _LIBC Xweak_alias (__re_match, re_match) X# endif X#endif /* not emacs */ X X#endif /* not INSIDE_RECURSION */ X X#ifdef INSIDE_RECURSION Xstatic boolean PREFIX(group_match_null_string_p) _RE_ARGS ((UCHAR_T **p, X UCHAR_T *end, X PREFIX(register_info_type) *reg_info)); Xstatic boolean PREFIX(alt_match_null_string_p) _RE_ARGS ((UCHAR_T *p, X UCHAR_T *end, X PREFIX(register_info_type) *reg_info)); Xstatic boolean PREFIX(common_op_match_null_string_p) _RE_ARGS ((UCHAR_T **p, X UCHAR_T *end, X PREFIX(register_info_type) *reg_info)); Xstatic int PREFIX(bcmp_translate) _RE_ARGS ((const CHAR_T *s1, const CHAR_T *s2, X int len, char *translate)); X#else /* not INSIDE_RECURSION */ X X/* re_match_2 matches the compiled pattern in BUFP against the X the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1 X and SIZE2, respectively). We start matching at POS, and stop X matching at STOP. X X If REGS is non-null and the `no_sub' field of BUFP is nonzero, we X store offsets for the substring each group matched in REGS. See the X documentation for exactly how many groups we fill. X X We return -1 if no match, -2 if an internal error (such as the X failure stack overflowing). Otherwise, we return the length of the X matched substring. */ X Xint Xre_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) X struct re_pattern_buffer *bufp; X const char *string1, *string2; X int size1, size2; X int pos; X struct re_registers *regs; X int stop; X{ X int result; X# ifdef MBS_SUPPORT X if (MB_CUR_MAX != 1) X result = wcs_re_match_2_internal (bufp, string1, size1, string2, size2, X pos, regs, stop, X NULL, 0, NULL, 0, NULL, NULL); X else X# endif X result = byte_re_match_2_internal (bufp, string1, size1, string2, size2, X pos, regs, stop); X X#ifndef REGEX_MALLOC X# ifdef C_ALLOCA X alloca (0); X# endif X#endif X return result; X} X#ifdef _LIBC Xweak_alias (__re_match_2, re_match_2) X#endif X X#endif /* not INSIDE_RECURSION */ X X#ifdef INSIDE_RECURSION X X#ifdef WCHAR Xstatic int count_mbs_length PARAMS ((int *, int)); X X/* This check the substring (from 0, to length) of the multibyte string, X to which offset_buffer correspond. And count how many wchar_t_characters X the substring occupy. We use offset_buffer to optimization. X See convert_mbs_to_wcs. */ X Xstatic int Xcount_mbs_length(offset_buffer, length) X int *offset_buffer; X int length; X{ X int upper, lower; X X /* Check whether the size is valid. */ X if (length < 0) X return -1; X X if (offset_buffer == NULL) X return 0; X X /* If there are no multibyte character, offset_buffer[i] == i. X Optmize for this case. */ X if (offset_buffer[length] == length) X return length; X X /* Set up upper with length. (because for all i, offset_buffer[i] >= i) */ X upper = length; X lower = 0; X X while (true) X { X int middle = (lower + upper) / 2; X if (middle == lower || middle == upper) X break; X if (offset_buffer[middle] > length) X upper = middle; X else if (offset_buffer[middle] < length) X lower = middle; X else X return middle; X } X X return -1; X} X#endif /* WCHAR */ X X/* This is a separate function so that we can force an alloca cleanup X afterwards. */ X#ifdef WCHAR Xstatic int Xwcs_re_match_2_internal (bufp, cstring1, csize1, cstring2, csize2, pos, X regs, stop, string1, size1, string2, size2, X mbs_offset1, mbs_offset2) X struct re_pattern_buffer *bufp; X const char *cstring1, *cstring2; X int csize1, csize2; X int pos; X struct re_registers *regs; X int stop; X /* string1 == string2 == NULL means string1/2, size1/2 and X mbs_offset1/2 need seting up in this function. */ X /* We need wchar_t* buffers correspond to cstring1, cstring2. */ X wchar_t *string1, *string2; X /* We need the size of wchar_t buffers correspond to csize1, csize2. */ X int size1, size2; X /* offset buffer for optimizatoin. See convert_mbs_to_wc. */ X int *mbs_offset1, *mbs_offset2; X#else /* BYTE */ Xstatic int Xbyte_re_match_2_internal (bufp, string1, size1,string2, size2, pos, X regs, stop) X struct re_pattern_buffer *bufp; X const char *string1, *string2; X int size1, size2; X int pos; X struct re_registers *regs; X int stop; X#endif /* BYTE */ X{ X /* General temporaries. */ X int mcnt; X UCHAR_T *p1; X#ifdef WCHAR X /* They hold whether each wchar_t is binary data or not. */ X char *is_binary = NULL; X /* If true, we can't free string1/2, mbs_offset1/2. */ X int cant_free_wcs_buf = 1; X#endif /* WCHAR */ X X /* Just past the end of the corresponding string. */ X const CHAR_T *end1, *end2; X X /* Pointers into string1 and string2, just past the last characters in X each to consider matching. */ X const CHAR_T *end_match_1, *end_match_2; X X /* Where we are in the data, and the end of the current string. */ X const CHAR_T *d, *dend; X X /* Where we are in the pattern, and the end of the pattern. */ X#ifdef WCHAR X UCHAR_T *pattern, *p; X register UCHAR_T *pend; X#else /* BYTE */ X UCHAR_T *p = bufp->buffer; X register UCHAR_T *pend = p + bufp->used; X#endif /* WCHAR */ X X /* Mark the opcode just after a start_memory, so we can test for an X empty subpattern when we get to the stop_memory. */ X UCHAR_T *just_past_start_mem = 0; X X /* We use this to map every character in the string. */ X RE_TRANSLATE_TYPE translate = bufp->translate; X X /* Failure point stack. Each place that can handle a failure further X down the line pushes a failure point on this stack. It consists of X restart, regend, and reg_info for all registers corresponding to X the subexpressions we're currently inside, plus the number of such X registers, and, finally, two char *'s. The first char * is where X to resume scanning the pattern; the second one is where to resume X scanning the strings. If the latter is zero, the failure point is X a ``dummy''; if a failure happens and the failure point is a dummy, X it gets discarded and the next next one is tried. */ X#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */ X PREFIX(fail_stack_type) fail_stack; X#endif X#ifdef DEBUG X static unsigned failure_id; X unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0; X#endif X X#ifdef REL_ALLOC X /* This holds the pointer to the failure stack, when X it is allocated relocatably. */ X fail_stack_elt_t *failure_stack_ptr; X#endif X X /* We fill all the registers internally, independent of what we X return, for use in backreferences. The number here includes X an element for register zero. */ X size_t num_regs = bufp->re_nsub + 1; X X /* The currently active registers. */ X active_reg_t lowest_active_reg = NO_LOWEST_ACTIVE_REG; X active_reg_t highest_active_reg = NO_HIGHEST_ACTIVE_REG; X X /* Information on the contents of registers. These are pointers into X the input strings; they record just what was matched (on this X attempt) by a subexpression part of the pattern, that is, the X regnum-th regstart pointer points to where in the pattern we began X matching and the regnum-th regend points to right after where we X stopped matching the regnum-th subexpression. (The zeroth register X keeps track of what the whole pattern matches.) */ X#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ X const CHAR_T **regstart, **regend; X#endif X X /* If a group that's operated upon by a repetition operator fails to X match anything, then the register for its start will need to be X restored because it will have been set to wherever in the string we X are when we last see its open-group operator. Similarly for a X register's end. */ X#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ X const CHAR_T **old_regstart, **old_regend; X#endif X X /* The is_active field of reg_info helps us keep track of which (possibly X nested) subexpressions we are currently in. The matched_something X field of reg_info[reg_num] helps us tell whether or not we have X matched any of the pattern so far this time through the reg_num-th X subexpression. These two fields get reset each time through any X loop their register is in. */ X#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */ X PREFIX(register_info_type) *reg_info; X#endif X X /* The following record the register info as found in the above X variables when we find a match better than any we've seen before. X This happens as we backtrack through the failure points, which in X turn happens only if we have not yet matched the entire string. */ X unsigned best_regs_set = false; X#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ X const CHAR_T **best_regstart, **best_regend; X#endif X X /* Logically, this is `best_regend[0]'. But we don't want to have to X allocate space for that if we're not allocating space for anything X else (see below). Also, we never need info about register 0 for X any of the other register vectors, and it seems rather a kludge to X treat `best_regend' differently than the rest. So we keep track of X the end of the best match so far in a separate variable. We X initialize this to NULL so that when we backtrack the first time X and need to test it, it's not garbage. */ X const CHAR_T *match_end = NULL; X X /* This helps SET_REGS_MATCHED avoid doing redundant work. */ X int set_regs_matched_done = 0; X X /* Used when we pop values we don't care about. */ X#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ X const CHAR_T **reg_dummy; X PREFIX(register_info_type) *reg_info_dummy; X#endif X X#ifdef DEBUG X /* Counts the total number of registers pushed. */ X unsigned num_regs_pushed = 0; X#endif X X /* Definitions for state transitions. More efficiently for gcc. */ X#ifdef __GNUC__ X# if defined HAVE_SUBTRACT_LOCAL_LABELS && defined SHARED X# define NEXT \ X do \ X { \ X int offset; \ X const void *__unbounded ptr; \ X offset = (p == pend \ X ? 0 : jmptable[SWITCH_ENUM_CAST ((re_opcode_t) *p++)]); \ X ptr = &&end_of_pattern + offset; \ X goto *ptr; \ X } \ X while (0) X# define REF(x) \ X &&label_##x - &&end_of_pattern X# define JUMP_TABLE_TYPE const int X# else X# define NEXT \ X do \ X { \ X const void *__unbounded ptr; \ X ptr = (p == pend ? &&end_of_pattern \ X : jmptable[SWITCH_ENUM_CAST ((re_opcode_t) *p++)]); \ X goto *ptr; \ X } \ X while (0) X# define REF(x) \ X &&label_##x X# define JUMP_TABLE_TYPE const void *const X# endif X# define CASE(x) label_##x X static JUMP_TABLE_TYPE jmptable[] = X { X REF (no_op), X REF (succeed), X REF (exactn), X# ifdef MBS_SUPPORT X REF (exactn_bin), X# endif X REF (anychar), X REF (charset), X REF (charset_not), X REF (start_memory), X REF (stop_memory), X REF (duplicate), X REF (begline), X REF (endline), X REF (begbuf), X REF (endbuf), X REF (jump), X REF (jump_past_alt), X REF (on_failure_jump), X REF (on_failure_keep_string_jump), X REF (pop_failure_jump), X REF (maybe_pop_jump), X REF (dummy_failure_jump), X REF (push_dummy_failure), X REF (succeed_n), X REF (jump_n), X REF (set_number_at), X REF (wordchar), X REF (notwordchar), X REF (wordbeg), X REF (wordend), X REF (wordbound), X REF (notwordbound) X# ifdef emacs X ,REF (before_dot), X REF (at_dot), X REF (after_dot), X REF (syntaxspec), X REF (notsyntaxspec) X# endif X }; X#else X# define NEXT \ X break X# define CASE(x) \ X case x X#endif X X DEBUG_PRINT1 ("\n\nEntering re_match_2.\n"); X X INIT_FAIL_STACK (); X X#ifdef MATCH_MAY_ALLOCATE X /* Do not bother to initialize all the register variables if there are X no groups in the pattern, as it takes a fair amount of time. If X there are groups, we include space for register 0 (the whole X pattern), even though we never use it, since it simplifies the X array indexing. We should fix this. */ X if (bufp->re_nsub) X { X regstart = REGEX_TALLOC (num_regs, const CHAR_T *); X regend = REGEX_TALLOC (num_regs, const CHAR_T *); X old_regstart = REGEX_TALLOC (num_regs, const CHAR_T *); X old_regend = REGEX_TALLOC (num_regs, const CHAR_T *); X best_regstart = REGEX_TALLOC (num_regs, const CHAR_T *); X best_regend = REGEX_TALLOC (num_regs, const CHAR_T *); X reg_info = REGEX_TALLOC (num_regs, PREFIX(register_info_type)); X reg_dummy = REGEX_TALLOC (num_regs, const CHAR_T *); X reg_info_dummy = REGEX_TALLOC (num_regs, PREFIX(register_info_type)); X X if (!(regstart && regend && old_regstart && old_regend && reg_info X && best_regstart && best_regend && reg_dummy && reg_info_dummy)) X { X FREE_VARIABLES (); X return -2; X } X } X else X { X /* We must initialize all our variables to NULL, so that X `FREE_VARIABLES' doesn't try to free them. */ X regstart = regend = old_regstart = old_regend = best_regstart X = best_regend = reg_dummy = NULL; X reg_info = reg_info_dummy = (PREFIX(register_info_type) *) NULL; X } X#endif /* MATCH_MAY_ALLOCATE */ X X /* The starting position is bogus. */ X#ifdef WCHAR X if (pos < 0 || pos > csize1 + csize2) X#else /* BYTE */ X if (pos < 0 || pos > size1 + size2) X#endif X { X FREE_VARIABLES (); X return -1; X } X X#ifdef WCHAR X /* Allocate wchar_t array for string1 and string2 and X fill them with converted string. */ X if (string1 == NULL && string2 == NULL) X { X /* We need seting up buffers here. */ X X /* We must free wcs buffers in this function. */ X cant_free_wcs_buf = 0; X X if (csize1 != 0) X { X string1 = REGEX_TALLOC (csize1 + 1, CHAR_T); X mbs_offset1 = REGEX_TALLOC (csize1 + 1, int); X is_binary = REGEX_TALLOC (csize1 + 1, char); X if (!string1 || !mbs_offset1 || !is_binary) X { X FREE_VAR (string1); X FREE_VAR (mbs_offset1); X FREE_VAR (is_binary); X return -2; X } X } X if (csize2 != 0) X { X string2 = REGEX_TALLOC (csize2 + 1, CHAR_T); X mbs_offset2 = REGEX_TALLOC (csize2 + 1, int); X is_binary = REGEX_TALLOC (csize2 + 1, char); X if (!string2 || !mbs_offset2 || !is_binary) X { X FREE_VAR (string1); X FREE_VAR (mbs_offset1); X FREE_VAR (string2); X FREE_VAR (mbs_offset2); X FREE_VAR (is_binary); X return -2; X } X size2 = convert_mbs_to_wcs(string2, cstring2, csize2, X mbs_offset2, is_binary); X string2[size2] = L'\0'; /* for a sentinel */ X FREE_VAR (is_binary); X } X } X X /* We need to cast pattern to (wchar_t*), because we casted this compiled X pattern to (char*) in regex_compile. */ X p = pattern = (CHAR_T*)bufp->buffer; X pend = (CHAR_T*)(bufp->buffer + bufp->used); X X#endif /* WCHAR */ X X /* Initialize subexpression text positions to -1 to mark ones that no X start_memory/stop_memory has been seen for. Also initialize the X register information struct. */ X for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) X { X regstart[mcnt] = regend[mcnt] X = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE; X X REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE; X IS_ACTIVE (reg_info[mcnt]) = 0; X MATCHED_SOMETHING (reg_info[mcnt]) = 0; X EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0; X } X X /* We move `string1' into `string2' if the latter's empty -- but not if X `string1' is null. */ X if (size2 == 0 && string1 != NULL) X { X string2 = string1; X size2 = size1; X string1 = 0; X size1 = 0; X#ifdef WCHAR X mbs_offset2 = mbs_offset1; X csize2 = csize1; X mbs_offset1 = NULL; X csize1 = 0; X#endif X } X end1 = string1 + size1; X end2 = string2 + size2; X X /* Compute where to stop matching, within the two strings. */ X#ifdef WCHAR X if (stop <= csize1) X { X mcnt = count_mbs_length(mbs_offset1, stop); X end_match_1 = string1 + mcnt; X end_match_2 = string2; X } X else X { X if (stop > csize1 + csize2) X stop = csize1 + csize2; X end_match_1 = end1; X mcnt = count_mbs_length(mbs_offset2, stop-csize1); X end_match_2 = string2 + mcnt; X } X if (mcnt < 0) X { /* count_mbs_length return error. */ X FREE_VARIABLES (); X return -1; X } X#else X if (stop <= size1) X { X end_match_1 = string1 + stop; X end_match_2 = string2; X } X else X { X end_match_1 = end1; X end_match_2 = string2 + stop - size1; X } X#endif /* WCHAR */ X X /* `p' scans through the pattern as `d' scans through the data. X `dend' is the end of the input string that `d' points within. `d' X is advanced into the following input string whenever necessary, but X this happens before fetching; therefore, at the beginning of the X loop, `d' can be pointing at the end of a string, but it cannot X equal `string2'. */ X#ifdef WCHAR X if (size1 > 0 && pos <= csize1) X { X mcnt = count_mbs_length(mbs_offset1, pos); X d = string1 + mcnt; X dend = end_match_1; X } X else X { X mcnt = count_mbs_length(mbs_offset2, pos-csize1); X d = string2 + mcnt; X dend = end_match_2; X } X X if (mcnt < 0) X { /* count_mbs_length return error. */ X FREE_VARIABLES (); X return -1; X } X#else X if (size1 > 0 && pos <= size1) X { X d = string1 + pos; X dend = end_match_1; X } X else X { X d = string2 + pos - size1; X dend = end_match_2; X } X#endif /* WCHAR */ X X DEBUG_PRINT1 ("The compiled pattern is:\n"); X DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend); X DEBUG_PRINT1 ("The string to match is: `"); X DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2); X DEBUG_PRINT1 ("'\n"); X X /* This loops over pattern commands. It exits by returning from the X function if the match is complete, or it drops through if the match X fails at this starting point in the input data. */ X for (;;) X { X#ifdef _LIBC X DEBUG_PRINT2 ("\n%p: ", p); X#else X DEBUG_PRINT2 ("\n0x%x: ", p); X#endif X X#ifdef __GNUC__ X NEXT; X#else X if (p == pend) X#endif X { X#ifdef __GNUC__ X end_of_pattern: X#endif X /* End of pattern means we might have succeeded. */ X DEBUG_PRINT1 ("end of pattern ... "); X X /* If we haven't matched the entire string, and we want the X longest match, try backtracking. */ X if (d != end_match_2) X { X /* 1 if this match ends in the same string (string1 or string2) X as the best previous match. */ X boolean same_str_p = (FIRST_STRING_P (match_end) X == MATCHING_IN_FIRST_STRING); X /* 1 if this match is the best seen so far. */ X boolean best_match_p; X X /* AIX compiler got confused when this was combined X with the previous declaration. */ X if (same_str_p) X best_match_p = d > match_end; X else X best_match_p = !MATCHING_IN_FIRST_STRING; X X DEBUG_PRINT1 ("backtracking.\n"); X X if (!FAIL_STACK_EMPTY ()) X { /* More failure points to try. */ X X /* If exceeds best match so far, save it. */ X if (!best_regs_set || best_match_p) X { X best_regs_set = true; X match_end = d; X X DEBUG_PRINT1 ("\nSAVING match as best so far.\n"); X X for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) X { X best_regstart[mcnt] = regstart[mcnt]; X best_regend[mcnt] = regend[mcnt]; X } X } X goto fail; X } X X /* If no failure points, don't restore garbage. And if X last match is real best match, don't restore second X best one. */ X else if (best_regs_set && !best_match_p) X { X restore_best_regs: X /* Restore best match. It may happen that `dend == X end_match_1' while the restored d is in string2. X For example, the pattern `x.*y.*z' against the X strings `x-' and `y-z-', if the two strings are X not consecutive in memory. */ X DEBUG_PRINT1 ("Restoring best registers.\n"); X X d = match_end; X dend = ((d >= string1 && d <= end1) X ? end_match_1 : end_match_2); X X for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) X { X regstart[mcnt] = best_regstart[mcnt]; X regend[mcnt] = best_regend[mcnt]; X } X } X } /* d != end_match_2 */ X X succeed_label: X DEBUG_PRINT1 ("Accepting match.\n"); X /* If caller wants register contents data back, do it. */ X if (regs && !bufp->no_sub) X { X /* Have the register data arrays been allocated? */ X if (bufp->regs_allocated == REGS_UNALLOCATED) X { /* No. So allocate them with malloc. We need one X extra element beyond `num_regs' for the `-1' marker X GNU code uses. */ X regs->num_regs = MAX (RE_NREGS, num_regs + 1); X regs->start = TALLOC (regs->num_regs, regoff_t); X regs->end = TALLOC (regs->num_regs, regoff_t); X if (regs->start == NULL || regs->end == NULL) X { X FREE_VARIABLES (); X return -2; X } X bufp->regs_allocated = REGS_REALLOCATE; X } X else if (bufp->regs_allocated == REGS_REALLOCATE) X { /* Yes. If we need more elements than were already X allocated, reallocate them. If we need fewer, just X leave it alone. */ X if (regs->num_regs < num_regs + 1) X { X regs->num_regs = num_regs + 1; X RETALLOC (regs->start, regs->num_regs, regoff_t); X RETALLOC (regs->end, regs->num_regs, regoff_t); X if (regs->start == NULL || regs->end == NULL) X { X FREE_VARIABLES (); X return -2; X } X } X } X else X { X /* These braces fend off a "empty body in an else-statement" X warning under GCC when assert expands to nothing. */ X assert (bufp->regs_allocated == REGS_FIXED); X } X X /* Convert the pointer data in `regstart' and `regend' to X indices. Register zero has to be set differently, X since we haven't kept track of any info for it. */ X if (regs->num_regs > 0) X { X regs->start[0] = pos; X#ifdef WCHAR X if (MATCHING_IN_FIRST_STRING) X regs->end[0] = (mbs_offset1 != NULL ? X mbs_offset1[d-string1] : 0); X else X regs->end[0] = csize1 + (mbs_offset2 != NULL X ? mbs_offset2[d-string2] : 0); X#else X regs->end[0] = (MATCHING_IN_FIRST_STRING X ? ((regoff_t) (d - string1)) X : ((regoff_t) (d - string2 + size1))); X#endif /* WCHAR */ X } X X /* Go through the first `min (num_regs, regs->num_regs)' X registers, since that is all we initialized. */ X for (mcnt = 1; (unsigned) mcnt < MIN (num_regs, regs->num_regs); X mcnt++) X { X if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt])) X regs->start[mcnt] = regs->end[mcnt] = -1; X else X { X regs->start[mcnt] X = (regoff_t) POINTER_TO_OFFSET (regstart[mcnt]); X regs->end[mcnt] X = (regoff_t) POINTER_TO_OFFSET (regend[mcnt]); X } X } X X /* If the regs structure we return has more elements than X were in the pattern, set the extra elements to -1. If X we (re)allocated the registers, this is the case, X because we always allocate enough to have at least one X -1 at the end. */ X for (mcnt = num_regs; (unsigned) mcnt < regs->num_regs; mcnt++) X regs->start[mcnt] = regs->end[mcnt] = -1; X } /* regs && !bufp->no_sub */ X X DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n", X nfailure_points_pushed, nfailure_points_popped, X nfailure_points_pushed - nfailure_points_popped); X DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed); X X#ifdef WCHAR X if (MATCHING_IN_FIRST_STRING) X mcnt = mbs_offset1 != NULL ? mbs_offset1[d-string1] : 0; X else X mcnt = (mbs_offset2 != NULL ? mbs_offset2[d-string2] : 0) + X csize1; X mcnt -= pos; X#else X mcnt = d - pos - (MATCHING_IN_FIRST_STRING X ? string1 : string2 - size1); X#endif /* WCHAR */ X X DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt); X X FREE_VARIABLES (); X return mcnt; X } X X#ifndef __GNUC__ X /* Otherwise match next pattern command. */ X switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++)) X { X#endif X /* Ignore these. Used to ignore the n of succeed_n's which X currently have n == 0. */ X CASE (no_op): X DEBUG_PRINT1 ("EXECUTING no_op.\n"); X NEXT; X X CASE (succeed): X DEBUG_PRINT1 ("EXECUTING succeed.\n"); X goto succeed_label; X X /* Match the next n pattern characters exactly. The following X byte in the pattern defines n, and the n bytes after that X are the characters to match. */ X CASE (exactn): X#ifdef MBS_SUPPORT X CASE (exactn_bin): X#endif X mcnt = *p++; X DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt); X X /* This is written out as an if-else so we don't waste time X testing `translate' inside the loop. */ X if (translate) X { X do X { X PREFETCH (); X#ifdef WCHAR X if (*d <= 0xff) X { X if ((UCHAR_T) translate[(unsigned char) *d++] X != (UCHAR_T) *p++) X goto fail; X } X else X { X if (*d++ != (CHAR_T) *p++) X goto fail; X } X#else X if ((UCHAR_T) translate[(unsigned char) *d++] X != (UCHAR_T) *p++) X goto fail; X#endif /* WCHAR */ X } X while (--mcnt); X } X else X { X do X { X PREFETCH (); X if (*d++ != (CHAR_T) *p++) goto fail; X } X while (--mcnt); X } X SET_REGS_MATCHED (); X NEXT; X X X /* Match any character except possibly a newline or a null. */ X CASE (anychar): X DEBUG_PRINT1 ("EXECUTING anychar.\n"); X X PREFETCH (); X X if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n') X || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000')) X goto fail; X X SET_REGS_MATCHED (); X DEBUG_PRINT2 (" Matched `%ld'.\n", (long int) *d); X d++; X NEXT; X X X CASE (charset): X CASE (charset_not): X { X register UCHAR_T c; X#ifdef WCHAR X unsigned int i, char_class_length, coll_symbol_length, X equiv_class_length, ranges_length, chars_length, length; X CHAR_T *workp, *workp2, *charset_top; X#define WORK_BUFFER_SIZE 128 X CHAR_T str_buf[WORK_BUFFER_SIZE]; X# ifdef _LIBC X uint32_t nrules; X# endif /* _LIBC */ X#endif /* WCHAR */ X boolean not = (re_opcode_t) *(p - 1) == charset_not; X X DEBUG_PRINT2 ("EXECUTING charset%s.\n", not ? "_not" : ""); X PREFETCH (); X c = TRANSLATE (*d); /* The character to match. */ X#ifdef WCHAR X# ifdef _LIBC X nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); X# endif /* _LIBC */ X charset_top = p - 1; X char_class_length = *p++; X coll_symbol_length = *p++; X equiv_class_length = *p++; X ranges_length = *p++; X chars_length = *p++; X /* p points charset[6], so the address of the next instruction X (charset[l+m+n+2o+k+p']) equals p[l+m+n+2*o+p'], X where l=length of char_classes, m=length of collating_symbol, X n=equivalence_class, o=length of char_range, X p'=length of character. */ X workp = p; X /* Update p to indicate the next instruction. */ X p += char_class_length + coll_symbol_length+ equiv_class_length + X 2*ranges_length + chars_length; X X /* match with char_class? */ X for (i = 0; i < char_class_length ; i += CHAR_CLASS_SIZE) X { X wctype_t wctype; X uintptr_t alignedp = ((uintptr_t)workp X + __alignof__(wctype_t) - 1) X & ~(uintptr_t)(__alignof__(wctype_t) - 1); X wctype = *((wctype_t*)alignedp); X workp += CHAR_CLASS_SIZE; X if (iswctype((wint_t)c, wctype)) X goto char_set_matched; X } X X /* match with collating_symbol? */ X# ifdef _LIBC X if (nrules != 0) X { X const unsigned char *extra = (const unsigned char *) X _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); X X for (workp2 = workp + coll_symbol_length ; workp < workp2 ; X workp++) X { X int32_t *wextra; X wextra = (int32_t*)(extra + *workp++); X for (i = 0; i < *wextra; ++i) X if (TRANSLATE(d[i]) != wextra[1 + i]) X break; X X if (i == *wextra) X { X /* Update d, however d will be incremented at X char_set_matched:, we decrement d here. */ X d += i - 1; X goto char_set_matched; X } X } X } X else /* (nrules == 0) */ X# endif X /* If we can't look up collation data, we use wcscoll X instead. */ X { X for (workp2 = workp + coll_symbol_length ; workp < workp2 ;) X { X const CHAR_T *backup_d = d, *backup_dend = dend; X length = wcslen (workp); X X /* If wcscoll(the collating symbol, whole string) > 0, X any substring of the string never match with the X collating symbol. */ X if (wcscoll (workp, d) > 0) X { X workp += length + 1; X continue; X } X X /* First, we compare the collating symbol with X the first character of the string. X If it don't match, we add the next character to X the compare buffer in turn. */ X for (i = 0 ; i < WORK_BUFFER_SIZE-1 ; i++, d++) X { X int match; X if (d == dend) X { X if (dend == end_match_2) X break; X d = string2; X dend = end_match_2; X } X X /* add next character to the compare buffer. */ X str_buf[i] = TRANSLATE(*d); X str_buf[i+1] = '\0'; X X match = wcscoll (workp, str_buf); X if (match == 0) X goto char_set_matched; X X if (match < 0) X /* (str_buf > workp) indicate (str_buf + X > workp), X because for all X (str_buf + X > str_buf). X So we don't need continue this loop. */ X break; X X /* Otherwise(str_buf < workp), X (str_buf+next_character) may equals (workp). X So we continue this loop. */ X } X /* not matched */ X d = backup_d; X dend = backup_dend; X workp += length + 1; X } X } X /* match with equivalence_class? */ X# ifdef _LIBC X if (nrules != 0) X { X const CHAR_T *backup_d = d, *backup_dend = dend; X /* Try to match the equivalence class against X those known to the collate implementation. */ X const int32_t *table; X const int32_t *weights; X const int32_t *extra; X const int32_t *indirect; X int32_t idx, idx2; X wint_t *cp; X size_t len; X X /* This #include defines a local function! */ X# include X X table = (const int32_t *) X _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEWC); X weights = (const wint_t *) X _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTWC); X extra = (const wint_t *) X _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAWC); X indirect = (const int32_t *) X _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTWC); X X /* Write 1 collating element to str_buf, and X get its index. */ X idx2 = 0; X X for (i = 0 ; idx2 == 0 && i < WORK_BUFFER_SIZE - 1; i++) X { X cp = (wint_t*)str_buf; X if (d == dend) X { X if (dend == end_match_2) X break; X d = string2; X dend = end_match_2; X } X str_buf[i] = TRANSLATE(*(d+i)); X str_buf[i+1] = '\0'; /* sentinel */ X idx2 = findidx ((const wint_t**)&cp); X } X X /* Update d, however d will be incremented at X char_set_matched:, we decrement d here. */ X d = backup_d + ((wchar_t*)cp - (wchar_t*)str_buf - 1); X if (d >= dend) X { X if (dend == end_match_2) X d = dend; X else X { X d = string2; X dend = end_match_2; X } X } X X len = weights[idx2]; X X for (workp2 = workp + equiv_class_length ; workp < workp2 ; X workp++) X { X idx = (int32_t)*workp; X /* We already checked idx != 0 in regex_compile. */ X X if (idx2 != 0 && len == weights[idx]) X { X int cnt = 0; X while (cnt < len && (weights[idx + 1 + cnt] X == weights[idx2 + 1 + cnt])) X ++cnt; X X if (cnt == len) X goto char_set_matched; X } X } X /* not matched */ X d = backup_d; X dend = backup_dend; X } X else /* (nrules == 0) */ X# endif X /* If we can't look up collation data, we use wcscoll X instead. */ X { X for (workp2 = workp + equiv_class_length ; workp < workp2 ;) X { X const CHAR_T *backup_d = d, *backup_dend = dend; X length = wcslen (workp); X X /* If wcscoll(the collating symbol, whole string) > 0, X any substring of the string never match with the X collating symbol. */ X if (wcscoll (workp, d) > 0) X { X workp += length + 1; X break; X } X X /* First, we compare the equivalence class with X the first character of the string. X If it don't match, we add the next character to X the compare buffer in turn. */ X for (i = 0 ; i < WORK_BUFFER_SIZE - 1 ; i++, d++) X { X int match; X if (d == dend) X { X if (dend == end_match_2) X break; X d = string2; X dend = end_match_2; X } X X /* add next character to the compare buffer. */ X str_buf[i] = TRANSLATE(*d); X str_buf[i+1] = '\0'; X X match = wcscoll (workp, str_buf); X X if (match == 0) X goto char_set_matched; X X if (match < 0) X /* (str_buf > workp) indicate (str_buf + X > workp), X because for all X (str_buf + X > str_buf). X So we don't need continue this loop. */ X break; X X /* Otherwise(str_buf < workp), X (str_buf+next_character) may equals (workp). X So we continue this loop. */ X } X /* not matched */ X d = backup_d; X dend = backup_dend; X workp += length + 1; X } X } X X /* match with char_range? */ X# ifdef _LIBC X if (nrules != 0) X { X uint32_t collseqval; X const char *collseq = (const char *) X _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC); X X collseqval = collseq_table_lookup (collseq, c); X X for (; workp < p - chars_length ;) X { X uint32_t start_val, end_val; X X /* We already compute the collation sequence value X of the characters (or collating symbols). */ X start_val = (uint32_t) *workp++; /* range_start */ X end_val = (uint32_t) *workp++; /* range_end */ X X if (start_val <= collseqval && collseqval <= end_val) X goto char_set_matched; X } X } X else X# endif X { X /* We set range_start_char at str_buf[0], range_end_char X at str_buf[4], and compared char at str_buf[2]. */ X str_buf[1] = 0; X str_buf[2] = c; X str_buf[3] = 0; X str_buf[5] = 0; X for (; workp < p - chars_length ;) X { X wchar_t *range_start_char, *range_end_char; X X /* match if (range_start_char <= c <= range_end_char). */ X X /* If range_start(or end) < 0, we assume -range_start(end) X is the offset of the collating symbol which is specified X as the character of the range start(end). */ X X /* range_start */ X if (*workp < 0) X range_start_char = charset_top - (*workp++); X else X { X str_buf[0] = *workp++; X range_start_char = str_buf; X } X X /* range_end */ X if (*workp < 0) X range_end_char = charset_top - (*workp++); X else X { X str_buf[4] = *workp++; X range_end_char = str_buf + 4; X } X X if (wcscoll (range_start_char, str_buf+2) <= 0 X && wcscoll (str_buf+2, range_end_char) <= 0) X goto char_set_matched; X } X } X X /* match with char? */ X for (; workp < p ; workp++) X if (c == *workp) X goto char_set_matched; X X not = !not; X X char_set_matched: X if (not) goto fail; X#else X /* Cast to `unsigned' instead of `unsigned char' in case the X bit list is a full 32 bytes long. */ X if (c < (unsigned) (*p * BYTEWIDTH) X && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) X not = !not; X X p += 1 + *p; X X if (!not) goto fail; X#undef WORK_BUFFER_SIZE X#endif /* WCHAR */ X SET_REGS_MATCHED (); X d++; X NEXT; X } X X X /* The beginning of a group is represented by start_memory. X The arguments are the register number in the next byte, and the X number of groups inner to this one in the next. The text X matched within the group is recorded (in the internal X registers data structure) under the register number. */ X CASE (start_memory): X DEBUG_PRINT3 ("EXECUTING start_memory %ld (%ld):\n", X (long int) *p, (long int) p[1]); X X /* Find out if this group can match the empty string. */ X p1 = p; /* To send to group_match_null_string_p. */ X X if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE) X REG_MATCH_NULL_STRING_P (reg_info[*p]) X = PREFIX(group_match_null_string_p) (&p1, pend, reg_info); X X /* Save the position in the string where we were the last time X we were at this open-group operator in case the group is X operated upon by a repetition operator, e.g., with `(a*)*b' X against `ab'; then we want to ignore where we are now in X the string in case this attempt to match fails. */ X old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) X ? REG_UNSET (regstart[*p]) ? d : regstart[*p] X : regstart[*p]; X DEBUG_PRINT2 (" old_regstart: %d\n", X POINTER_TO_OFFSET (old_regstart[*p])); X X regstart[*p] = d; X DEBUG_PRINT2 (" regstart: %d\n", POINTER_TO_OFFSET (regstart[*p])); X X IS_ACTIVE (reg_info[*p]) = 1; X MATCHED_SOMETHING (reg_info[*p]) = 0; X X /* Clear this whenever we change the register activity status. */ X set_regs_matched_done = 0; X X /* This is the new highest active register. */ X highest_active_reg = *p; X X /* If nothing was active before, this is the new lowest active X register. */ X if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) X lowest_active_reg = *p; X X /* Move past the register number and inner group count. */ X p += 2; X just_past_start_mem = p; X X NEXT; X X X /* The stop_memory opcode represents the end of a group. Its X arguments are the same as start_memory's: the register X number, and the number of inner groups. */ X CASE (stop_memory): X DEBUG_PRINT3 ("EXECUTING stop_memory %ld (%ld):\n", X (long int) *p, (long int) p[1]); X X /* We need to save the string position the last time we were at X this close-group operator in case the group is operated X upon by a repetition operator, e.g., with `((a*)*(b*)*)*' X against `aba'; then we want to ignore where we are now in X the string in case this attempt to match fails. */ X old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) X ? REG_UNSET (regend[*p]) ? d : regend[*p] X : regend[*p]; X DEBUG_PRINT2 (" old_regend: %d\n", X POINTER_TO_OFFSET (old_regend[*p])); X X regend[*p] = d; X DEBUG_PRINT2 (" regend: %d\n", POINTER_TO_OFFSET (regend[*p])); X X /* This register isn't active anymore. */ X IS_ACTIVE (reg_info[*p]) = 0; X X /* Clear this whenever we change the register activity status. */ X set_regs_matched_done = 0; X X /* If this was the only register active, nothing is active X anymore. */ X if (lowest_active_reg == highest_active_reg) X { X lowest_active_reg = NO_LOWEST_ACTIVE_REG; X highest_active_reg = NO_HIGHEST_ACTIVE_REG; X } X else X { /* We must scan for the new highest active register, since X it isn't necessarily one less than now: consider X (a(b)c(d(e)f)g). When group 3 ends, after the f), the X new highest active register is 1. */ X UCHAR_T r = *p - 1; X while (r > 0 && !IS_ACTIVE (reg_info[r])) X r--; X X /* If we end up at register zero, that means that we saved X the registers as the result of an `on_failure_jump', not X a `start_memory', and we jumped to past the innermost X `stop_memory'. For example, in ((.)*) we save X registers 1 and 2 as a result of the *, but when we pop X back to the second ), we are at the stop_memory 1. X Thus, nothing is active. */ X if (r == 0) X { X lowest_active_reg = NO_LOWEST_ACTIVE_REG; X highest_active_reg = NO_HIGHEST_ACTIVE_REG; X } X else X highest_active_reg = r; X } X X /* If just failed to match something this time around with a X group that's operated on by a repetition operator, try to X force exit from the ``loop'', and restore the register X information for this group that we had before trying this X last match. */ X if ((!MATCHED_SOMETHING (reg_info[*p]) X || just_past_start_mem == p - 1) X && (p + 2) < pend) X { X boolean is_a_jump_n = false; X X p1 = p + 2; X mcnt = 0; X switch ((re_opcode_t) *p1++) X { X case jump_n: X is_a_jump_n = true; X case pop_failure_jump: X case maybe_pop_jump: X case jump: X case dummy_failure_jump: X EXTRACT_NUMBER_AND_INCR (mcnt, p1); X if (is_a_jump_n) X p1 += OFFSET_ADDRESS_SIZE; X break; X X default: X /* do nothing */ ; X } X p1 += mcnt; X X /* If the next operation is a jump backwards in the pattern X to an on_failure_jump right before the start_memory X corresponding to this stop_memory, exit from the loop X by forcing a failure after pushing on the stack the X on_failure_jump's jump in the pattern, and d. */ X if (mcnt < 0 && (re_opcode_t) *p1 == on_failure_jump X && (re_opcode_t) p1[1+OFFSET_ADDRESS_SIZE] == start_memory X && p1[2+OFFSET_ADDRESS_SIZE] == *p) X { X /* If this group ever matched anything, then restore X what its registers were before trying this last X failed match, e.g., with `(a*)*b' against `ab' for X regstart[1], and, e.g., with `((a*)*(b*)*)*' X against `aba' for regend[3]. X X Also restore the registers for inner groups for, X e.g., `((a*)(b*))*' against `aba' (register 3 would X otherwise get trashed). */ X X if (EVER_MATCHED_SOMETHING (reg_info[*p])) X { X unsigned r; X X EVER_MATCHED_SOMETHING (reg_info[*p]) = 0; X X /* Restore this and inner groups' (if any) registers. */ X for (r = *p; r < (unsigned) *p + (unsigned) *(p + 1); X r++) X { X regstart[r] = old_regstart[r]; X X /* xx why this test? */ X if (old_regend[r] >= regstart[r]) X regend[r] = old_regend[r]; X } X } X p1++; X EXTRACT_NUMBER_AND_INCR (mcnt, p1); X PUSH_FAILURE_POINT (p1 + mcnt, d, -2); X X goto fail; X } X } X X /* Move past the register number and the inner group count. */ X p += 2; X NEXT; X X X /* \ has been turned into a `duplicate' command which is X followed by the numeric value of as the register number. */ X CASE (duplicate): X { X register const CHAR_T *d2, *dend2; X int regno = *p++; /* Get which register to match against. */ X DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno); X X /* Can't back reference a group which we've never matched. */ X if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno])) X goto fail; X X /* Where in input to try to start matching. */ X d2 = regstart[regno]; X X /* Where to stop matching; if both the place to start and X the place to stop matching are in the same string, then X set to the place to stop, otherwise, for now have to use X the end of the first string. */ X X dend2 = ((FIRST_STRING_P (regstart[regno]) X == FIRST_STRING_P (regend[regno])) X ? regend[regno] : end_match_1); X for (;;) X { X /* If necessary, advance to next segment in register X contents. */ X while (d2 == dend2) X { X if (dend2 == end_match_2) break; X if (dend2 == regend[regno]) break; X X /* End of string1 => advance to string2. */ X d2 = string2; X dend2 = regend[regno]; X } X /* At end of register contents => success */ X if (d2 == dend2) break; X X /* If necessary, advance to next segment in data. */ X PREFETCH (); X X /* How many characters left in this segment to match. */ X mcnt = dend - d; X X /* Want how many consecutive characters we can match in X one shot, so, if necessary, adjust the count. */ X if (mcnt > dend2 - d2) X mcnt = dend2 - d2; X X /* Compare that many; failure if mismatch, else move X past them. */ X if (translate X ? PREFIX(bcmp_translate) (d, d2, mcnt, translate) X : memcmp (d, d2, mcnt*sizeof(UCHAR_T))) X goto fail; X d += mcnt, d2 += mcnt; X X /* Do this because we've match some characters. */ X SET_REGS_MATCHED (); X } X } X NEXT; X X X /* begline matches the empty string at the beginning of the string X (unless `not_bol' is set in `bufp'), and, if X `newline_anchor' is set, after newlines. */ X CASE (begline): X DEBUG_PRINT1 ("EXECUTING begline.\n"); X X if (AT_STRINGS_BEG (d)) X { X if (!bufp->not_bol) X { X NEXT; X } X } X else if (d[-1] == '\n' && bufp->newline_anchor) X { X NEXT; X } X /* In all other cases, we fail. */ X goto fail; X X X /* endline is the dual of begline. */ X CASE (endline): X DEBUG_PRINT1 ("EXECUTING endline.\n"); X X if (AT_STRINGS_END (d)) X { X if (!bufp->not_eol) X { X NEXT; X } X } X X /* We have to ``prefetch'' the next character. */ X else if ((d == end1 ? *string2 : *d) == '\n' X && bufp->newline_anchor) X { X NEXT; X } X goto fail; X X X /* Match at the very beginning of the data. */ X CASE (begbuf): X DEBUG_PRINT1 ("EXECUTING begbuf.\n"); X if (AT_STRINGS_BEG (d)) X { X NEXT; X } X goto fail; X X X /* Match at the very end of the data. */ X CASE (endbuf): X DEBUG_PRINT1 ("EXECUTING endbuf.\n"); X if (AT_STRINGS_END (d)) X { X NEXT; X } X goto fail; X X X /* on_failure_keep_string_jump is used to optimize `.*\n'. It X pushes NULL as the value for the string on the stack. Then X `pop_failure_point' will keep the current value for the X string, instead of restoring it. To see why, consider X matching `foo\nbar' against `.*\n'. The .* matches the foo; X then the . fails against the \n. But the next thing we want X to do is match the \n against the \n; if we restored the X string value, we would be back at the foo. X X Because this is used only in specific cases, we don't need to X check all the things that `on_failure_jump' does, to make X sure the right things get saved on the stack. Hence we don't X share its code. The only reason to push anything on the X stack at all is that otherwise we would have to change X `anychar's code to do something besides goto fail in this X case; that seems worse than this. */ X CASE (on_failure_keep_string_jump): X DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump"); X X EXTRACT_NUMBER_AND_INCR (mcnt, p); X#ifdef _LIBC X DEBUG_PRINT3 (" %d (to %p):\n", mcnt, p + mcnt); X#else X DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt); X#endif X X PUSH_FAILURE_POINT (p + mcnt, NULL, -2); X NEXT; X X X /* Uses of on_failure_jump: X X Each alternative starts with an on_failure_jump that points X to the beginning of the next alternative. Each alternative X except the last ends with a jump that in effect jumps past X the rest of the alternatives. (They really jump to the X ending jump of the following alternative, because tensioning X these jumps is a hassle.) X X Repeats start with an on_failure_jump that points past both X the repetition text and either the following jump or X pop_failure_jump back to this on_failure_jump. */ X CASE (on_failure_jump): X on_failure: X DEBUG_PRINT1 ("EXECUTING on_failure_jump"); X X EXTRACT_NUMBER_AND_INCR (mcnt, p); X#ifdef _LIBC X DEBUG_PRINT3 (" %d (to %p)", mcnt, p + mcnt); X#else X DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt); X#endif X X /* If this on_failure_jump comes right before a group (i.e., X the original * applied to a group), save the information X for that group and all inner ones, so that if we fail back X to this point, the group's information will be correct. X For example, in \(a*\)*\1, we need the preceding group, X and in \(zz\(a*\)b*\)\2, we need the inner group. */ X X /* We can't use `p' to check ahead because we push X a failure point to `p + mcnt' after we do this. */ X p1 = p; X X /* We need to skip no_op's before we look for the X start_memory in case this on_failure_jump is happening as X the result of a completed succeed_n, as in \(a\)\{1,3\}b\1 X against aba. */ X while (p1 < pend && (re_opcode_t) *p1 == no_op) X p1++; X X if (p1 < pend && (re_opcode_t) *p1 == start_memory) X { X /* We have a new highest active register now. This will X get reset at the start_memory we are about to get to, X but we will have saved all the registers relevant to X this repetition op, as described above. */ X highest_active_reg = *(p1 + 1) + *(p1 + 2); X if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) X lowest_active_reg = *(p1 + 1); X } X X DEBUG_PRINT1 (":\n"); X PUSH_FAILURE_POINT (p + mcnt, d, -2); X NEXT; X X X /* A smart repeat ends with `maybe_pop_jump'. X We change it to either `pop_failure_jump' or `jump'. */ X CASE (maybe_pop_jump): X EXTRACT_NUMBER_AND_INCR (mcnt, p); X DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt); X { X register UCHAR_T *p2 = p; X X /* Compare the beginning of the repeat with what in the X pattern follows its end. If we can establish that there X is nothing that they would both match, i.e., that we X would have to backtrack because of (as in, e.g., `a*a') X then we can change to pop_failure_jump, because we'll X never have to backtrack. X X This is not true in the case of alternatives: in X `(a|ab)*' we do need to backtrack to the `ab' alternative X (e.g., if the string was `ab'). But instead of trying to X detect that here, the alternative has put on a dummy X failure point which is what we will end up popping. */ X X /* Skip over open/close-group commands. X If what follows this loop is a ...+ construct, X look at what begins its body, since we will have to X match at least one of that. */ X while (1) X { X if (p2 + 2 < pend X && ((re_opcode_t) *p2 == stop_memory X || (re_opcode_t) *p2 == start_memory)) X p2 += 3; X else if (p2 + 2 + 2 * OFFSET_ADDRESS_SIZE < pend X && (re_opcode_t) *p2 == dummy_failure_jump) X p2 += 2 + 2 * OFFSET_ADDRESS_SIZE; X else X break; X } X X p1 = p + mcnt; X /* p1[0] ... p1[2] are the `on_failure_jump' corresponding X to the `maybe_finalize_jump' of this case. Examine what X follows. */ X X /* If we're at the end of the pattern, we can change. */ X if (p2 == pend) X { X /* Consider what happens when matching ":\(.*\)" X against ":/". I don't really understand this code X yet. */ X p[-(1+OFFSET_ADDRESS_SIZE)] = (UCHAR_T) X pop_failure_jump; X DEBUG_PRINT1 X (" End of pattern: change to `pop_failure_jump'.\n"); X } X X else if ((re_opcode_t) *p2 == exactn X#ifdef MBS_SUPPORT X || (re_opcode_t) *p2 == exactn_bin X#endif X || (bufp->newline_anchor && (re_opcode_t) *p2 == endline)) X { X register UCHAR_T c X = *p2 == (UCHAR_T) endline ? '\n' : p2[2]; X X if (((re_opcode_t) p1[1+OFFSET_ADDRESS_SIZE] == exactn X#ifdef MBS_SUPPORT X || (re_opcode_t) p1[1+OFFSET_ADDRESS_SIZE] == exactn_bin X#endif X ) && p1[3+OFFSET_ADDRESS_SIZE] != c) X { X p[-(1+OFFSET_ADDRESS_SIZE)] = (UCHAR_T) X pop_failure_jump; X#ifdef WCHAR X DEBUG_PRINT3 (" %C != %C => pop_failure_jump.\n", X (wint_t) c, X (wint_t) p1[3+OFFSET_ADDRESS_SIZE]); X#else X DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n", X (char) c, X (char) p1[3+OFFSET_ADDRESS_SIZE]); X#endif X } X X#ifndef WCHAR X else if ((re_opcode_t) p1[3] == charset X || (re_opcode_t) p1[3] == charset_not) X { X int not = (re_opcode_t) p1[3] == charset_not; X X if (c < (unsigned) (p1[4] * BYTEWIDTH) X && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) X not = !not; X X /* `not' is equal to 1 if c would match, which means X that we can't change to pop_failure_jump. */ X if (!not) X { X p[-3] = (unsigned char) pop_failure_jump; X DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); X } X } X#endif /* not WCHAR */ X } X#ifndef WCHAR X else if ((re_opcode_t) *p2 == charset) X { X /* We win if the first character of the loop is not part X of the charset. */ X if ((re_opcode_t) p1[3] == exactn X && ! ((int) p2[1] * BYTEWIDTH > (int) p1[5] X && (p2[2 + p1[5] / BYTEWIDTH] X & (1 << (p1[5] % BYTEWIDTH))))) X { X p[-3] = (unsigned char) pop_failure_jump; X DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); X } X X else if ((re_opcode_t) p1[3] == charset_not) X { X int idx; X /* We win if the charset_not inside the loop X lists every character listed in the charset after. */ X for (idx = 0; idx < (int) p2[1]; idx++) X if (! (p2[2 + idx] == 0 X || (idx < (int) p1[4] X && ((p2[2 + idx] & ~ p1[5 + idx]) == 0)))) X break; X X if (idx == p2[1]) X { X p[-3] = (unsigned char) pop_failure_jump; X DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); X } X } X else if ((re_opcode_t) p1[3] == charset) X { X int idx; X /* We win if the charset inside the loop X has no overlap with the one after the loop. */ X for (idx = 0; X idx < (int) p2[1] && idx < (int) p1[4]; X idx++) X if ((p2[2 + idx] & p1[5 + idx]) != 0) X break; X X if (idx == p2[1] || idx == p1[4]) X { X p[-3] = (unsigned char) pop_failure_jump; X DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); X } X } X } X#endif /* not WCHAR */ X } X p -= OFFSET_ADDRESS_SIZE; /* Point at relative address again. */ X if ((re_opcode_t) p[-1] != pop_failure_jump) X { X p[-1] = (UCHAR_T) jump; X DEBUG_PRINT1 (" Match => jump.\n"); X goto unconditional_jump; X } X /* Note fall through. */ X X X /* The end of a simple repeat has a pop_failure_jump back to X its matching on_failure_jump, where the latter will push a X failure point. The pop_failure_jump takes off failure X points put on by this pop_failure_jump's matching X on_failure_jump; we got through the pattern to here from the X matching on_failure_jump, so didn't fail. */ X CASE (pop_failure_jump): X { X /* We need to pass separate storage for the lowest and X highest registers, even though we don't care about the X actual values. Otherwise, we will restore only one X register from the stack, since lowest will == highest in X `pop_failure_point'. */ X active_reg_t dummy_low_reg, dummy_high_reg; X UCHAR_T *pdummy = NULL; X const CHAR_T *sdummy = NULL; X X DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n"); X POP_FAILURE_POINT (sdummy, pdummy, X dummy_low_reg, dummy_high_reg, X reg_dummy, reg_dummy, reg_info_dummy); X } X /* Note fall through. */ X X unconditional_jump: X#ifdef _LIBC X DEBUG_PRINT2 ("\n%p: ", p); X#else X DEBUG_PRINT2 ("\n0x%x: ", p); X#endif X /* Note fall through. */ X X /* Unconditionally jump (without popping any failure points). */ X CASE (jump): X EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */ X DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt); X p += mcnt; /* Do the jump. */ X#ifdef _LIBC X DEBUG_PRINT2 ("(to %p).\n", p); X#else X DEBUG_PRINT2 ("(to 0x%x).\n", p); X#endif X NEXT; X X X /* We need this opcode so we can detect where alternatives end X in `group_match_null_string_p' et al. */ X CASE (jump_past_alt): X DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n"); X goto unconditional_jump; X X X /* Normally, the on_failure_jump pushes a failure point, which X then gets popped at pop_failure_jump. We will end up at X pop_failure_jump, also, and with a pattern of, say, `a+', we X are skipping over the on_failure_jump, so we have to push X something meaningless for pop_failure_jump to pop. */ X CASE (dummy_failure_jump): X DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n"); X /* It doesn't matter what we push for the string here. What X the code at `fail' tests is the value for the pattern. */ X PUSH_FAILURE_POINT (NULL, NULL, -2); X goto unconditional_jump; X X X /* At the end of an alternative, we need to push a dummy failure X point in case we are followed by a `pop_failure_jump', because X we don't want the failure point for the alternative to be X popped. For example, matching `(a|ab)*' against `aab' X requires that we match the `ab' alternative. */ X CASE (push_dummy_failure): X DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n"); X /* See comments just above at `dummy_failure_jump' about the X two zeroes. */ X PUSH_FAILURE_POINT (NULL, NULL, -2); X NEXT; X X /* Have to succeed matching what follows at least n times. X After that, handle like `on_failure_jump'. */ X CASE (succeed_n): X EXTRACT_NUMBER (mcnt, p + OFFSET_ADDRESS_SIZE); X DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt); X X assert (mcnt >= 0); X /* Originally, this is how many times we HAVE to succeed. */ X if (mcnt > 0) X { X mcnt--; X p += OFFSET_ADDRESS_SIZE; X STORE_NUMBER_AND_INCR (p, mcnt); X#ifdef _LIBC X DEBUG_PRINT3 (" Setting %p to %d.\n", p - OFFSET_ADDRESS_SIZE X , mcnt); X#else X DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p - OFFSET_ADDRESS_SIZE X , mcnt); X#endif X } X else if (mcnt == 0) X { X#ifdef _LIBC X DEBUG_PRINT2 (" Setting two bytes from %p to no_op.\n", X p + OFFSET_ADDRESS_SIZE); X#else X DEBUG_PRINT2 (" Setting two bytes from 0x%x to no_op.\n", X p + OFFSET_ADDRESS_SIZE); X#endif /* _LIBC */ X X#ifdef WCHAR X p[1] = (UCHAR_T) no_op; X#else X p[2] = (UCHAR_T) no_op; X p[3] = (UCHAR_T) no_op; X#endif /* WCHAR */ X goto on_failure; X } X NEXT; X X CASE (jump_n): X EXTRACT_NUMBER (mcnt, p + OFFSET_ADDRESS_SIZE); X DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt); X X /* Originally, this is how many times we CAN jump. */ X if (mcnt) X { X mcnt--; X STORE_NUMBER (p + OFFSET_ADDRESS_SIZE, mcnt); X X#ifdef _LIBC X DEBUG_PRINT3 (" Setting %p to %d.\n", p + OFFSET_ADDRESS_SIZE, X mcnt); X#else X DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p + OFFSET_ADDRESS_SIZE, X mcnt); X#endif /* _LIBC */ X goto unconditional_jump; X } X /* If don't have to jump any more, skip over the rest of command. */ X else X p += 2 * OFFSET_ADDRESS_SIZE; X NEXT; X X CASE (set_number_at): X { X DEBUG_PRINT1 ("EXECUTING set_number_at.\n"); X X EXTRACT_NUMBER_AND_INCR (mcnt, p); X p1 = p + mcnt; X EXTRACT_NUMBER_AND_INCR (mcnt, p); X#ifdef _LIBC X DEBUG_PRINT3 (" Setting %p to %d.\n", p1, mcnt); X#else X DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p1, mcnt); X#endif X STORE_NUMBER (p1, mcnt); X NEXT; X } X X#if 0 X /* The DEC Alpha C compiler 3.x generates incorrect code for the X test WORDCHAR_P (d - 1) != WORDCHAR_P (d) in the expansion of X AT_WORD_BOUNDARY, so this code is disabled. Expanding the X macro and introducing temporary variables works around the bug. */ X X CASE (wordbound): X DEBUG_PRINT1 ("EXECUTING wordbound.\n"); X if (AT_WORD_BOUNDARY (d)) X { X NEXT; X } X goto fail; X X CASE (notwordbound): X DEBUG_PRINT1 ("EXECUTING notwordbound.\n"); X if (AT_WORD_BOUNDARY (d)) X goto fail; X NEXT; X#else X CASE (wordbound): X { X boolean prevchar, thischar; X X DEBUG_PRINT1 ("EXECUTING wordbound.\n"); X if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d)) X { X NEXT; X } X X prevchar = WORDCHAR_P (d - 1); X thischar = WORDCHAR_P (d); X if (prevchar != thischar) X { X NEXT; X } X goto fail; X } X X CASE (notwordbound): X { X boolean prevchar, thischar; X X DEBUG_PRINT1 ("EXECUTING notwordbound.\n"); X if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d)) X goto fail; X X prevchar = WORDCHAR_P (d - 1); X thischar = WORDCHAR_P (d); X if (prevchar != thischar) X goto fail; X NEXT; X } X#endif X X CASE (wordbeg): X DEBUG_PRINT1 ("EXECUTING wordbeg.\n"); X if (!AT_STRINGS_END (d) && WORDCHAR_P (d) X && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1))) X { X NEXT; X } X goto fail; X X CASE (wordend): X DEBUG_PRINT1 ("EXECUTING wordend.\n"); X if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1) X && (AT_STRINGS_END (d) || !WORDCHAR_P (d))) X { X NEXT; X } X goto fail; X X#ifdef emacs X CASE (before_dot): X DEBUG_PRINT1 ("EXECUTING before_dot.\n"); X if (PTR_CHAR_POS ((unsigned char *) d) >= point) X goto fail; X NEXT; X X CASE (at_dot): X DEBUG_PRINT1 ("EXECUTING at_dot.\n"); X if (PTR_CHAR_POS ((unsigned char *) d) != point) X goto fail; X NEXT; X X CASE (after_dot): X DEBUG_PRINT1 ("EXECUTING after_dot.\n"); X if (PTR_CHAR_POS ((unsigned char *) d) <= point) X goto fail; X NEXT; X X CASE (syntaxspec): X DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt); X mcnt = *p++; X goto matchsyntax; X X CASE (wordchar): X DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n"); X mcnt = (int) Sword; X matchsyntax: X PREFETCH (); X /* Can't use *d++ here; SYNTAX may be an unsafe macro. */ X d++; X if (SYNTAX (d[-1]) != (enum syntaxcode) mcnt) X goto fail; X SET_REGS_MATCHED (); X NEXT; X X CASE (notsyntaxspec): X DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt); X mcnt = *p++; X goto matchnotsyntax; X X CASE (notwordchar): X DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n"); X mcnt = (int) Sword; X matchnotsyntax: X PREFETCH (); X /* Can't use *d++ here; SYNTAX may be an unsafe macro. */ X d++; X if (SYNTAX (d[-1]) == (enum syntaxcode) mcnt) X goto fail; X SET_REGS_MATCHED (); X NEXT; X X#else /* not emacs */ X CASE (wordchar): X DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n"); X PREFETCH (); X if (!WORDCHAR_P (d)) X goto fail; X SET_REGS_MATCHED (); X d++; X NEXT; X X CASE (notwordchar): X DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n"); X PREFETCH (); X if (WORDCHAR_P (d)) X goto fail; X SET_REGS_MATCHED (); X d++; X NEXT; X#endif /* not emacs */ X X#ifndef __GNUC__ X default: X abort (); X } X continue; /* Successfully executed one pattern command; keep going. */ X#endif X X X /* We goto here if a matching operation fails. */ X fail: X if (!FAIL_STACK_EMPTY ()) X { /* A restart point is known. Restore to that state. */ X DEBUG_PRINT1 ("\nFAIL:\n"); X POP_FAILURE_POINT (d, p, X lowest_active_reg, highest_active_reg, X regstart, regend, reg_info); X X /* If this failure point is a dummy, try the next one. */ X if (!p) X goto fail; X X /* If we failed to the end of the pattern, don't examine *p. */ X assert (p <= pend); X if (p < pend) X { X boolean is_a_jump_n = false; X X /* If failed to a backwards jump that's part of a repetition X loop, need to pop this failure point and use the next one. */ X switch ((re_opcode_t) *p) X { X case jump_n: X is_a_jump_n = true; X case maybe_pop_jump: X case pop_failure_jump: X case jump: X p1 = p + 1; X EXTRACT_NUMBER_AND_INCR (mcnt, p1); X p1 += mcnt; X X if ((is_a_jump_n && (re_opcode_t) *p1 == succeed_n) X || (!is_a_jump_n X && (re_opcode_t) *p1 == on_failure_jump)) X goto fail; X break; X default: X /* do nothing */ ; X } X } X X if (d >= string1 && d <= end1) X dend = end_match_1; X } X else X break; /* Matching at this starting point really fails. */ X } /* for (;;) */ X X if (best_regs_set) X goto restore_best_regs; X X FREE_VARIABLES (); X X return -1; /* Failure to match. */ X} /* re_match_2 */ X X/* Subroutine definitions for re_match_2. */ X X X/* We are passed P pointing to a register number after a start_memory. X X Return true if the pattern up to the corresponding stop_memory can X match the empty string, and false otherwise. X X If we find the matching stop_memory, sets P to point to one past its number. X Otherwise, sets P to an undefined byte less than or equal to END. X X We don't handle duplicates properly (yet). */ X Xstatic boolean XPREFIX(group_match_null_string_p) (p, end, reg_info) X UCHAR_T **p, *end; X PREFIX(register_info_type) *reg_info; X{ X int mcnt; X /* Point to after the args to the start_memory. */ X UCHAR_T *p1 = *p + 2; X X while (p1 < end) X { X /* Skip over opcodes that can match nothing, and return true or X false, as appropriate, when we get to one that can't, or to the X matching stop_memory. */ X X switch ((re_opcode_t) *p1) X { X /* Could be either a loop or a series of alternatives. */ X case on_failure_jump: X p1++; X EXTRACT_NUMBER_AND_INCR (mcnt, p1); X X /* If the next operation is not a jump backwards in the X pattern. */ X X if (mcnt >= 0) X { X /* Go through the on_failure_jumps of the alternatives, X seeing if any of the alternatives cannot match nothing. X The last alternative starts with only a jump, X whereas the rest start with on_failure_jump and end X with a jump, e.g., here is the pattern for `a|b|c': X X /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6 X /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3 X /exactn/1/c X X So, we have to first go through the first (n-1) X alternatives and then deal with the last one separately. */ X X X /* Deal with the first (n-1) alternatives, which start X with an on_failure_jump (see above) that jumps to right X past a jump_past_alt. */ X X while ((re_opcode_t) p1[mcnt-(1+OFFSET_ADDRESS_SIZE)] == X jump_past_alt) X { X /* `mcnt' holds how many bytes long the alternative X is, including the ending `jump_past_alt' and X its number. */ X X if (!PREFIX(alt_match_null_string_p) (p1, p1 + mcnt - X (1 + OFFSET_ADDRESS_SIZE), X reg_info)) X return false; X X /* Move to right after this alternative, including the X jump_past_alt. */ X p1 += mcnt; X X /* Break if it's the beginning of an n-th alternative X that doesn't begin with an on_failure_jump. */ X if ((re_opcode_t) *p1 != on_failure_jump) X break; X X /* Still have to check that it's not an n-th X alternative that starts with an on_failure_jump. */ X p1++; X EXTRACT_NUMBER_AND_INCR (mcnt, p1); X if ((re_opcode_t) p1[mcnt-(1+OFFSET_ADDRESS_SIZE)] != X jump_past_alt) X { X /* Get to the beginning of the n-th alternative. */ X p1 -= 1 + OFFSET_ADDRESS_SIZE; X break; X } X } X X /* Deal with the last alternative: go back and get number X of the `jump_past_alt' just before it. `mcnt' contains X the length of the alternative. */ X EXTRACT_NUMBER (mcnt, p1 - OFFSET_ADDRESS_SIZE); X X if (!PREFIX(alt_match_null_string_p) (p1, p1 + mcnt, reg_info)) X return false; X X p1 += mcnt; /* Get past the n-th alternative. */ X } /* if mcnt > 0 */ X break; X X X case stop_memory: X assert (p1[1] == **p); X *p = p1 + 2; X return true; X X X default: X if (!PREFIX(common_op_match_null_string_p) (&p1, end, reg_info)) X return false; X } X } /* while p1 < end */ X X return false; X} /* group_match_null_string_p */ X X X/* Similar to group_match_null_string_p, but doesn't deal with alternatives: X It expects P to be the first byte of a single alternative and END one X byte past the last. The alternative can contain groups. */ X Xstatic boolean XPREFIX(alt_match_null_string_p) (p, end, reg_info) X UCHAR_T *p, *end; X PREFIX(register_info_type) *reg_info; X{ X int mcnt; X UCHAR_T *p1 = p; X X while (p1 < end) X { X /* Skip over opcodes that can match nothing, and break when we get X to one that can't. */ X X switch ((re_opcode_t) *p1) X { X /* It's a loop. */ X case on_failure_jump: X p1++; X EXTRACT_NUMBER_AND_INCR (mcnt, p1); X p1 += mcnt; X break; X X default: X if (!PREFIX(common_op_match_null_string_p) (&p1, end, reg_info)) X return false; X } X } /* while p1 < end */ X X return true; X} /* alt_match_null_string_p */ X X X/* Deals with the ops common to group_match_null_string_p and X alt_match_null_string_p. X X Sets P to one after the op and its arguments, if any. */ X Xstatic boolean XPREFIX(common_op_match_null_string_p) (p, end, reg_info) X UCHAR_T **p, *end; X PREFIX(register_info_type) *reg_info; X{ X int mcnt; X boolean ret; X int reg_no; X UCHAR_T *p1 = *p; X X switch ((re_opcode_t) *p1++) X { X case no_op: X case begline: X case endline: X case begbuf: X case endbuf: X case wordbeg: X case wordend: X case wordbound: X case notwordbound: X#ifdef emacs X case before_dot: X case at_dot: X case after_dot: X#endif X break; X X case start_memory: X reg_no = *p1; X assert (reg_no > 0 && reg_no <= MAX_REGNUM); X ret = PREFIX(group_match_null_string_p) (&p1, end, reg_info); X X /* Have to set this here in case we're checking a group which X contains a group and a back reference to it. */ X X if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE) X REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret; X X if (!ret) X return false; X break; X X /* If this is an optimized succeed_n for zero times, make the jump. */ X case jump: X EXTRACT_NUMBER_AND_INCR (mcnt, p1); X if (mcnt >= 0) X p1 += mcnt; X else X return false; X break; X X case succeed_n: X /* Get to the number of times to succeed. */ X p1 += OFFSET_ADDRESS_SIZE; X EXTRACT_NUMBER_AND_INCR (mcnt, p1); X X if (mcnt == 0) X { X p1 -= 2 * OFFSET_ADDRESS_SIZE; X EXTRACT_NUMBER_AND_INCR (mcnt, p1); X p1 += mcnt; X } X else X return false; X break; X X case duplicate: X if (!REG_MATCH_NULL_STRING_P (reg_info[*p1])) X return false; X break; X X case set_number_at: X p1 += 2 * OFFSET_ADDRESS_SIZE; X X default: X /* All other opcodes mean we cannot match the empty string. */ X return false; X } X X *p = p1; X return true; X} /* common_op_match_null_string_p */ X X X/* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN X bytes; nonzero otherwise. */ X Xstatic int XPREFIX(bcmp_translate) (s1, s2, len, translate) X const CHAR_T *s1, *s2; X register int len; X RE_TRANSLATE_TYPE translate; X{ X register const UCHAR_T *p1 = (const UCHAR_T *) s1; X register const UCHAR_T *p2 = (const UCHAR_T *) s2; X while (len) X { X#ifdef WCHAR X if (((*p1<=0xff)?translate[*p1++]:*p1++) X != ((*p2<=0xff)?translate[*p2++]:*p2++)) X return 1; X#else /* BYTE */ X if (translate[*p1++] != translate[*p2++]) return 1; X#endif /* WCHAR */ X len--; X } X return 0; X} X X X#else /* not INSIDE_RECURSION */ X X/* Entry points for GNU code. */ X X/* re_compile_pattern is the GNU regular expression compiler: it X compiles PATTERN (of length SIZE) and puts the result in BUFP. X Returns 0 if the pattern was valid, otherwise an error string. X X Assumes the `allocated' (and perhaps `buffer') and `translate' fields X are set in BUFP on entry. X X We call regex_compile to do the actual compilation. */ X Xconst char * Xre_compile_pattern (pattern, length, bufp) X const char *pattern; X size_t length; X struct re_pattern_buffer *bufp; X{ X reg_errcode_t ret; X X /* GNU code is written to assume at least RE_NREGS registers will be set X (and at least one extra will be -1). */ X bufp->regs_allocated = REGS_UNALLOCATED; X X /* And GNU code determines whether or not to get register information X by passing null for the REGS argument to re_match, etc., not by X setting no_sub. */ X bufp->no_sub = 0; X X /* Match anchors at newline. */ X bufp->newline_anchor = 1; X X# ifdef MBS_SUPPORT X if (MB_CUR_MAX != 1) X ret = wcs_regex_compile (pattern, length, re_syntax_options, bufp); X else X# endif X ret = byte_regex_compile (pattern, length, re_syntax_options, bufp); X X if (!ret) X return NULL; X return gettext (re_error_msgid + re_error_msgid_idx[(int) ret]); X} X#ifdef _LIBC Xweak_alias (__re_compile_pattern, re_compile_pattern) X#endif X X/* Entry points compatible with 4.2 BSD regex library. We don't define X them unless specifically requested. */ X X#if defined _REGEX_RE_COMP || defined _LIBC X X/* BSD has one and only one pattern buffer. */ Xstatic struct re_pattern_buffer re_comp_buf; X Xchar * X#ifdef _LIBC X/* Make these definitions weak in libc, so POSIX programs can redefine X these names if they don't use our functions, and still use X regcomp/regexec below without link errors. */ Xweak_function X#endif Xre_comp (s) X const char *s; X{ X reg_errcode_t ret; X X if (!s) X { X if (!re_comp_buf.buffer) X return gettext ("No previous regular expression"); X return 0; X } X X if (!re_comp_buf.buffer) X { X re_comp_buf.buffer = (unsigned char *) malloc (200); X if (re_comp_buf.buffer == NULL) X return (char *) gettext (re_error_msgid X + re_error_msgid_idx[(int) REG_ESPACE]); X re_comp_buf.allocated = 200; X X re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH); X if (re_comp_buf.fastmap == NULL) X return (char *) gettext (re_error_msgid X + re_error_msgid_idx[(int) REG_ESPACE]); X } X X /* Since `re_exec' always passes NULL for the `regs' argument, we X don't need to initialize the pattern buffer fields which affect it. */ X X /* Match anchors at newlines. */ X re_comp_buf.newline_anchor = 1; X X# ifdef MBS_SUPPORT X if (MB_CUR_MAX != 1) X ret = wcs_regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf); X else X# endif X ret = byte_regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf); X X if (!ret) X return NULL; X X /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */ X return (char *) gettext (re_error_msgid + re_error_msgid_idx[(int) ret]); X} X X Xint X#ifdef _LIBC Xweak_function X#endif Xre_exec (s) X const char *s; X{ X const int len = strlen (s); X return X 0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0); X} X X#endif /* _REGEX_RE_COMP */ X X/* POSIX.2 functions. Don't define these for Emacs. */ X X#ifndef emacs X X/* regcomp takes a regular expression as a string and compiles it. X X PREG is a regex_t *. We do not expect any fields to be initialized, X since POSIX says we shouldn't. Thus, we set X X `buffer' to the compiled pattern; X `used' to the length of the compiled pattern; X `syntax' to RE_SYNTAX_POSIX_EXTENDED if the X REG_EXTENDED bit in CFLAGS is set; otherwise, to X RE_SYNTAX_POSIX_BASIC; X `newline_anchor' to REG_NEWLINE being set in CFLAGS; X `fastmap' to an allocated space for the fastmap; X `fastmap_accurate' to zero; X `re_nsub' to the number of subexpressions in PATTERN. X X PATTERN is the address of the pattern string. X X CFLAGS is a series of bits which affect compilation. X X If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we X use POSIX basic syntax. X X If REG_NEWLINE is set, then . and [^...] don't match newline. X Also, regexec will try a match beginning after every newline. X X If REG_ICASE is set, then we considers upper- and lowercase X versions of letters to be equivalent when matching. X X If REG_NOSUB is set, then when PREG is passed to regexec, that X routine will report only success or failure, and nothing about the X registers. X X It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for X the return codes and their meanings.) */ X Xint Xregcomp (preg, pattern, cflags) X regex_t *preg; X const char *pattern; X int cflags; X{ X reg_errcode_t ret; X reg_syntax_t syntax X = (cflags & REG_EXTENDED) ? X RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC; X X /* regex_compile will allocate the space for the compiled pattern. */ X preg->buffer = 0; X preg->allocated = 0; X preg->used = 0; X X /* Try to allocate space for the fastmap. */ X preg->fastmap = (char *) malloc (1 << BYTEWIDTH); X X if (cflags & REG_ICASE) X { X unsigned i; X X preg->translate X = (RE_TRANSLATE_TYPE) malloc (CHAR_SET_SIZE X * sizeof (*(RE_TRANSLATE_TYPE)0)); X if (preg->translate == NULL) X return (int) REG_ESPACE; X X /* Map uppercase characters to corresponding lowercase ones. */ X for (i = 0; i < CHAR_SET_SIZE; i++) X preg->translate[i] = ISUPPER (i) ? TOLOWER (i) : i; X } X else X preg->translate = NULL; X X /* If REG_NEWLINE is set, newlines are treated differently. */ X if (cflags & REG_NEWLINE) X { /* REG_NEWLINE implies neither . nor [^...] match newline. */ X syntax &= ~RE_DOT_NEWLINE; X syntax |= RE_HAT_LISTS_NOT_NEWLINE; X /* It also changes the matching behavior. */ X preg->newline_anchor = 1; X } X else X preg->newline_anchor = 0; X X preg->no_sub = !!(cflags & REG_NOSUB); X X /* POSIX says a null character in the pattern terminates it, so we X can use strlen here in compiling the pattern. */ X# ifdef MBS_SUPPORT X if (MB_CUR_MAX != 1) X ret = wcs_regex_compile (pattern, strlen (pattern), syntax, preg); X else X# endif X ret = byte_regex_compile (pattern, strlen (pattern), syntax, preg); X X /* POSIX doesn't distinguish between an unmatched open-group and an X unmatched close-group: both are REG_EPAREN. */ X if (ret == REG_ERPAREN) ret = REG_EPAREN; X X if (ret == REG_NOERROR && preg->fastmap) X { X /* Compute the fastmap now, since regexec cannot modify the pattern X buffer. */ X if (re_compile_fastmap (preg) == -2) X { X /* Some error occurred while computing the fastmap, just forget X about it. */ X free (preg->fastmap); X preg->fastmap = NULL; X } X } X X return (int) ret; X} X#ifdef _LIBC Xweak_alias (__regcomp, regcomp) X#endif X X X/* regexec searches for a given pattern, specified by PREG, in the X string STRING. X X If NMATCH is zero or REG_NOSUB was set in the cflags argument to X `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at X least NMATCH elements, and we set them to the offsets of the X corresponding matched substrings. X X EFLAGS specifies `execution flags' which affect matching: if X REG_NOTBOL is set, then ^ does not match at the beginning of the X string; if REG_NOTEOL is set, then $ does not match at the end. X X We return 0 if we find a match and REG_NOMATCH if not. */ X Xint Xregexec (preg, string, nmatch, pmatch, eflags) X const regex_t *preg; X const char *string; X size_t nmatch; X regmatch_t pmatch[]; X int eflags; X{ X int ret; X struct re_registers regs; X regex_t private_preg; X int len = strlen (string); X boolean want_reg_info = !preg->no_sub && nmatch > 0; X X private_preg = *preg; X X private_preg.not_bol = !!(eflags & REG_NOTBOL); X private_preg.not_eol = !!(eflags & REG_NOTEOL); X X /* The user has told us exactly how many registers to return X information about, via `nmatch'. We have to pass that on to the X matching routines. */ X private_preg.regs_allocated = REGS_FIXED; X X if (want_reg_info) X { X regs.num_regs = nmatch; X regs.start = TALLOC (nmatch * 2, regoff_t); X if (regs.start == NULL) X return (int) REG_NOMATCH; X regs.end = regs.start + nmatch; X } X X /* Perform the searching operation. */ X ret = re_search (&private_preg, string, len, X /* start: */ 0, /* range: */ len, X want_reg_info ? ®s : (struct re_registers *) 0); X X /* Copy the register information to the POSIX structure. */ X if (want_reg_info) X { X if (ret >= 0) X { X unsigned r; X X for (r = 0; r < nmatch; r++) X { X pmatch[r].rm_so = regs.start[r]; X pmatch[r].rm_eo = regs.end[r]; X } X } X X /* If we needed the temporary register info, free the space now. */ X free (regs.start); X } X X /* We want zero return to mean success, unlike `re_search'. */ X return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH; X} X#ifdef _LIBC Xweak_alias (__regexec, regexec) X#endif X X X/* Returns a message corresponding to an error code, ERRCODE, returned X from either regcomp or regexec. We don't use PREG here. */ X Xsize_t Xregerror (errcode, preg, errbuf, errbuf_size) X int errcode; X const regex_t *preg; X char *errbuf; X size_t errbuf_size; X{ X const char *msg; X size_t msg_size; X X if (errcode < 0 X || errcode >= (int) (sizeof (re_error_msgid_idx) X / sizeof (re_error_msgid_idx[0]))) X /* Only error codes returned by the rest of the code should be passed X to this routine. If we are given anything else, or if other regex X code generates an invalid error code, then the program has a bug. X Dump core so we can fix it. */ X abort (); X X msg = gettext (re_error_msgid + re_error_msgid_idx[errcode]); X X msg_size = strlen (msg) + 1; /* Includes the null. */ X X if (errbuf_size != 0) X { X if (msg_size > errbuf_size) X { X#if defined HAVE_MEMPCPY || defined _LIBC X *((char *) __mempcpy (errbuf, msg, errbuf_size - 1)) = '\0'; X#else X memcpy (errbuf, msg, errbuf_size - 1); X errbuf[errbuf_size - 1] = 0; X#endif X } X else X memcpy (errbuf, msg, msg_size); X } X X return msg_size; X} X#ifdef _LIBC Xweak_alias (__regerror, regerror) X#endif X X X/* Free dynamically allocated space used by PREG. */ X Xvoid Xregfree (preg) X regex_t *preg; X{ X if (preg->buffer != NULL) X free (preg->buffer); X preg->buffer = NULL; X X preg->allocated = 0; X preg->used = 0; X X if (preg->fastmap != NULL) X free (preg->fastmap); X preg->fastmap = NULL; X preg->fastmap_accurate = 0; X X if (preg->translate != NULL) X free (preg->translate); X preg->translate = NULL; X} X#ifdef _LIBC Xweak_alias (__regfree, regfree) X#endif X X#endif /* not emacs */ X X#endif /* not INSIDE_RECURSION */ X X X#undef STORE_NUMBER X#undef STORE_NUMBER_AND_INCR X#undef EXTRACT_NUMBER X#undef EXTRACT_NUMBER_AND_INCR X X#undef DEBUG_PRINT_COMPILED_PATTERN X#undef DEBUG_PRINT_DOUBLE_STRING X X#undef INIT_FAIL_STACK X#undef RESET_FAIL_STACK X#undef DOUBLE_FAIL_STACK X#undef PUSH_PATTERN_OP X#undef PUSH_FAILURE_POINTER X#undef PUSH_FAILURE_INT X#undef PUSH_FAILURE_ELT X#undef POP_FAILURE_POINTER X#undef POP_FAILURE_INT X#undef POP_FAILURE_ELT X#undef DEBUG_PUSH X#undef DEBUG_POP X#undef PUSH_FAILURE_POINT X#undef POP_FAILURE_POINT X X#undef REG_UNSET_VALUE X#undef REG_UNSET X X#undef PATFETCH X#undef PATFETCH_RAW X#undef PATUNFETCH X#undef TRANSLATE X X#undef INIT_BUF_SIZE X#undef GET_BUFFER_SPACE X#undef BUF_PUSH X#undef BUF_PUSH_2 X#undef BUF_PUSH_3 X#undef STORE_JUMP X#undef STORE_JUMP2 X#undef INSERT_JUMP X#undef INSERT_JUMP2 X#undef EXTEND_BUFFER X#undef GET_UNSIGNED_NUMBER X#undef FREE_STACK_RETURN X X# undef POINTER_TO_OFFSET X# undef MATCHING_IN_FRST_STRING X# undef PREFETCH X# undef AT_STRINGS_BEG X# undef AT_STRINGS_END X# undef WORDCHAR_P X# undef FREE_VAR X# undef FREE_VARIABLES X# undef NO_HIGHEST_ACTIVE_REG X# undef NO_LOWEST_ACTIVE_REG X X# undef CHAR_T X# undef UCHAR_T X# undef COMPILED_BUFFER_VAR X# undef OFFSET_ADDRESS_SIZE X# undef CHAR_CLASS_SIZE X# undef PREFIX X# undef ARG_PREFIX X# undef PUT_CHAR X# undef BYTE X# undef WCHAR X X# define DEFINED_ONCE END-of-contrib/diff/lib/regex.c echo x - contrib/diff/lib/strcasecmp.c sed 's/^X//' >contrib/diff/lib/strcasecmp.c << 'END-of-contrib/diff/lib/strcasecmp.c' X/* strcasecmp.c -- case insensitive string comparator X Copyright (C) 1998, 1999 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software Foundation, X Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#if HAVE_CONFIG_H X# include X#endif X X#ifdef LENGTH_LIMIT X# define STRXCASECMP_FUNCTION strncasecmp X# define STRXCASECMP_DECLARE_N , size_t n X# define LENGTH_LIMIT_EXPR(Expr) Expr X#else X# define STRXCASECMP_FUNCTION strcasecmp X# define STRXCASECMP_DECLARE_N /* empty */ X# define LENGTH_LIMIT_EXPR(Expr) 0 X#endif X X#include X#include X X#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch)) X X/* Compare {{no more than N characters of }}strings S1 and S2, X ignoring case, returning less than, equal to or X greater than zero if S1 is lexicographically less X than, equal to or greater than S2. */ X Xint XSTRXCASECMP_FUNCTION (const char *s1, const char *s2 STRXCASECMP_DECLARE_N) X{ X register const unsigned char *p1 = (const unsigned char *) s1; X register const unsigned char *p2 = (const unsigned char *) s2; X unsigned char c1, c2; X X if (p1 == p2 || LENGTH_LIMIT_EXPR (n == 0)) X return 0; X X do X { X c1 = TOLOWER (*p1); X c2 = TOLOWER (*p2); X X if (LENGTH_LIMIT_EXPR (--n == 0) || c1 == '\0') X break; X X ++p1; X ++p2; X } X while (c1 == c2); X X return c1 - c2; X} END-of-contrib/diff/lib/strcasecmp.c echo x - contrib/diff/lib/strtoul.c sed 's/^X//' >contrib/diff/lib/strtoul.c << 'END-of-contrib/diff/lib/strtoul.c' X/* Copyright (C) 1991, 1999, 2001 Free Software Foundation, Inc. X XNOTE: The canonical source of this file is maintained with the GNU C Library. XBugs can be reported to bug-glibc@prep.ai.mit.edu. X XThis program is free software; you can redistribute it and/or modify it Xunder the terms of the GNU General Public License as published by the XFree Software Foundation; either version 2, or (at your option) any Xlater version. X XThis program is distributed in the hope that it will be useful, Xbut WITHOUT ANY WARRANTY; without even the implied warranty of XMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the XGNU General Public License for more details. X XYou should have received a copy of the GNU General Public License Xalong with this program; if not, write to the Free Software Foundation, XInc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#define UNSIGNED 1 X X#include "strtol.c" END-of-contrib/diff/lib/strtoul.c echo x - contrib/diff/lib/strtoull.c sed 's/^X//' >contrib/diff/lib/strtoull.c << 'END-of-contrib/diff/lib/strtoull.c' X/* Function to parse an `unsigned long long int' from text. X Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc. X NOTE: The canonical source of this file is maintained with the GNU C X Library. Bugs can be reported to bug-glibc@gnu.org. X X This program is free software; you can redistribute it and/or modify it X under the terms of the GNU General Public License as published by the X Free Software Foundation; either version 2, or (at your option) any X later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software Foundation, X Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#define QUAD 1 X X#include "strtoul.c" X X#ifdef _LIBC Xstrong_alias (__strtoull_internal, __strtouq_internal) Xweak_alias (strtoull, strtouq) X#endif END-of-contrib/diff/lib/strtoull.c echo x - contrib/diff/lib/strtoumax.c sed 's/^X//' >contrib/diff/lib/strtoumax.c << 'END-of-contrib/diff/lib/strtoumax.c' X#define UNSIGNED 1 X#include "strtoimax.c" END-of-contrib/diff/lib/strtoumax.c echo x - contrib/diff/lib/tempname.c sed 's/^X//' >contrib/diff/lib/tempname.c << 'END-of-contrib/diff/lib/tempname.c' X/* Copyright (C) 1991-1999, 2000, 2001 Free Software Foundation, Inc. X This file is part of the GNU C Library. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software Foundation, X Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#if HAVE_CONFIG_H X# include X#endif X X#include X#include X X#include X#ifndef __set_errno X# define __set_errno(Val) errno = (Val) X#endif X X#include X#ifndef P_tmpdir X# define P_tmpdir "/tmp" X#endif X#ifndef TMP_MAX X# define TMP_MAX 238328 X#endif X#ifndef __GT_FILE X# define __GT_FILE 0 X# define __GT_BIGFILE 1 X# define __GT_DIR 2 X# define __GT_NOCREATE 3 X#endif X X#if STDC_HEADERS || _LIBC X# include X# include X#endif X X#include X X#if HAVE_FCNTL_H || _LIBC X# include X#endif X X#if HAVE_SYS_TIME_H || _LIBC X# include X#endif X X#if HAVE_STDINT_H || _LIBC X# include X#endif X X#if HAVE_UNISTD_H || _LIBC X# include X#endif X X#include X#if STAT_MACROS_BROKEN X# undef S_ISDIR X#endif X#if !defined S_ISDIR && defined S_IFDIR X# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) X#endif X#if !S_IRUSR && S_IREAD X# define S_IRUSR S_IREAD X#endif X#if !S_IRUSR X# define S_IRUSR 00400 X#endif X#if !S_IWUSR && S_IWRITE X# define S_IWUSR S_IWRITE X#endif X#if !S_IWUSR X# define S_IWUSR 00200 X#endif X#if !S_IXUSR && S_IEXEC X# define S_IXUSR S_IEXEC X#endif X#if !S_IXUSR X# define S_IXUSR 00100 X#endif X X#if _LIBC X# define struct_stat64 struct stat64 X#else X# define struct_stat64 struct stat X# define __getpid getpid X# define __gettimeofday gettimeofday X# define __mkdir mkdir X# define __open open X# define __open64 open X# define __lxstat64(version, path, buf) lstat (path, buf) X# define __xstat64(version, path, buf) stat (path, buf) X#endif X X#if ! (HAVE___SECURE_GETENV || _LIBC) X# define __secure_getenv getenv X#endif X X#ifdef _LIBC X# include X# if HP_TIMING_AVAIL X# define RANDOM_BITS(Var) \ X if (__builtin_expect (value == UINT64_C (0), 0)) \ X { \ X /* If this is the first time this function is used initialize \ X the variable we accumulate the value in to some somewhat \ X random value. If we'd not do this programs at startup time \ X might have a reduced set of possible names, at least on slow \ X machines. */ \ X struct timeval tv; \ X __gettimeofday (&tv, NULL); \ X value = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; \ X } \ X HP_TIMING_NOW (Var) X# endif X#endif X X/* Use the widest available unsigned type if uint64_t is not X available. The algorithm below extracts a number less than 62**6 X (approximately 2**35.725) from uint64_t, so ancient hosts where X uintmax_t is only 32 bits lose about 3.725 bits of randomness, X which is better than not having mkstemp at all. */ X#if !defined UINT64_MAX && !defined uint64_t X# define uint64_t uintmax_t X#endif X X/* Return nonzero if DIR is an existent directory. */ Xstatic int Xdirexists (const char *dir) X{ X struct_stat64 buf; X return __xstat64 (_STAT_VER, dir, &buf) == 0 && S_ISDIR (buf.st_mode); X} X X/* Path search algorithm, for tmpnam, tmpfile, etc. If DIR is X non-null and exists, uses it; otherwise uses the first of $TMPDIR, X P_tmpdir, /tmp that exists. Copies into TMPL a template suitable X for use with mk[s]temp. Will fail (-1) if DIR is non-null and X doesn't exist, none of the searched dirs exists, or there's not X enough space in TMPL. */ Xint X__path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, X int try_tmpdir) X{ X const char *d; X size_t dlen, plen; X X if (!pfx || !pfx[0]) X { X pfx = "file"; X plen = 4; X } X else X { X plen = strlen (pfx); X if (plen > 5) X plen = 5; X } X X if (try_tmpdir) X { X d = __secure_getenv ("TMPDIR"); X if (d != NULL && direxists (d)) X dir = d; X else if (dir != NULL && direxists (dir)) X /* nothing */ ; X else X dir = NULL; X } X if (dir == NULL) X { X if (direxists (P_tmpdir)) X dir = P_tmpdir; X else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp")) X dir = "/tmp"; X else X { X __set_errno (ENOENT); X return -1; X } X } X X dlen = strlen (dir); X while (dlen > 1 && dir[dlen - 1] == '/') X dlen--; /* remove trailing slashes */ X X /* check we have room for "${dir}/${pfx}XXXXXX\0" */ X if (tmpl_len < dlen + 1 + plen + 6 + 1) X { X __set_errno (EINVAL); X return -1; X } X X sprintf (tmpl, "%.*s/%.*sXXXXXX", (int) dlen, dir, (int) plen, pfx); X return 0; X} X X/* These are the characters used in temporary filenames. */ Xstatic const char letters[] = X"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; X X/* Generate a temporary file name based on TMPL. TMPL must match the X rules for mk[s]temp (i.e. end in "XXXXXX"). The name constructed X does not exist at the time of the call to __gen_tempname. TMPL is X overwritten with the result. X X KIND may be one of: X __GT_NOCREATE: simply verify that the name does not exist X at the time of the call. X __GT_FILE: create the file using open(O_CREAT|O_EXCL) X and return a read-write fd. The file is mode 0600. X __GT_BIGFILE: same as __GT_FILE but use open64(). X __GT_DIR: create a directory, which will be mode 0700. X X We use a clever algorithm to get hard-to-predict names. */ Xint X__gen_tempname (char *tmpl, int kind) X{ X int len; X char *XXXXXX; X static uint64_t value; X uint64_t random_time_bits; X unsigned int count; X int fd = -1; X int save_errno = errno; X struct_stat64 st; X X /* A lower bound on the number of temporary files to attempt to X generate. The maximum total number of temporary file names that X can exist for a given template is 62**6. It should never be X necessary to try all these combinations. Instead if a reasonable X number of names is tried (we define reasonable as 62**3) fail to X give the system administrator the chance to remove the problems. */ X unsigned int attempts_min = 62 * 62 * 62; X X /* The number of times to attempt to generate a temporary file. To X conform to POSIX, this must be no smaller than TMP_MAX. */ X unsigned int attempts = attempts_min < TMP_MAX ? TMP_MAX : attempts_min; X X len = strlen (tmpl); X if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX")) X { X __set_errno (EINVAL); X return -1; X } X X /* This is where the Xs start. */ X XXXXXX = &tmpl[len - 6]; X X /* Get some more or less random data. */ X#ifdef RANDOM_BITS X RANDOM_BITS (random_time_bits); X#else X# if HAVE_GETTIMEOFDAY || _LIBC X { X struct timeval tv; X __gettimeofday (&tv, NULL); X random_time_bits = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; X } X# else X random_time_bits = time (NULL); X# endif X#endif X value += random_time_bits ^ __getpid (); X X for (count = 0; count < attempts; value += 7777, ++count) X { X uint64_t v = value; X X /* Fill in the random bits. */ X XXXXXX[0] = letters[v % 62]; X v /= 62; X XXXXXX[1] = letters[v % 62]; X v /= 62; X XXXXXX[2] = letters[v % 62]; X v /= 62; X XXXXXX[3] = letters[v % 62]; X v /= 62; X XXXXXX[4] = letters[v % 62]; X v /= 62; X XXXXXX[5] = letters[v % 62]; X X switch (kind) X { X case __GT_FILE: X fd = __open (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); X break; X X case __GT_BIGFILE: X fd = __open64 (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); X break; X X case __GT_DIR: X fd = __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR); X break; X X case __GT_NOCREATE: X /* This case is backward from the other three. __gen_tempname X succeeds if __xstat fails because the name does not exist. X Note the continue to bypass the common logic at the bottom X of the loop. */ X if (__lxstat64 (_STAT_VER, tmpl, &st) < 0) X { X if (errno == ENOENT) X { X __set_errno (save_errno); X return 0; X } X else X /* Give up now. */ X return -1; X } X continue; X X default: X assert (! "invalid KIND in __gen_tempname"); X } X X if (fd >= 0) X { X __set_errno (save_errno); X return fd; X } X else if (errno != EEXIST) X return -1; X } X X /* We got out of the loop because we ran out of combinations to try. */ X __set_errno (EEXIST); X return -1; X} END-of-contrib/diff/lib/tempname.c echo x - contrib/diff/lib/waitpid.c sed 's/^X//' >contrib/diff/lib/waitpid.c << 'END-of-contrib/diff/lib/waitpid.c' X/* Emulate waitpid on systems that just have wait. X Copyright (C) 1994, 1995, 1998, 1999 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; see the file COPYING. X If not, write to the Free Software Foundation, X 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#if HAVE_CONFIG_H X# include X#endif X X#include X#ifndef errno Xextern int errno; X#endif X X#define WAITPID_CHILDREN 8 Xstatic pid_t waited_pid[WAITPID_CHILDREN]; Xstatic int waited_status[WAITPID_CHILDREN]; X Xpid_t Xwaitpid (pid_t pid, int *stat_loc, int options) X{ X int i; X pid_t p; X X if (!options && (pid == -1 || 0 < pid)) X { X /* If we have already waited for this child, return it immediately. */ X for (i = 0; i < WAITPID_CHILDREN; i++) X { X p = waited_pid[i]; X if (p && (p == pid || pid == -1)) X { X waited_pid[i] = 0; X goto success; X } X } X X /* The child has not returned yet; wait for it, accumulating status. */ X for (i = 0; i < WAITPID_CHILDREN; i++) X if (! waited_pid[i]) X { X p = wait (&waited_status[i]); X if (p < 0) X return p; X if (p == pid || pid == -1) X goto success; X waited_pid[i] = p; X } X } X X /* We cannot emulate this wait call, e.g. because of too many children. */ X errno = EINVAL; X return -1; X Xsuccess: X if (stat_loc) X *stat_loc = waited_status[i]; X return p; X} END-of-contrib/diff/lib/waitpid.c echo x - contrib/diff/lib/basename.c sed 's/^X//' >contrib/diff/lib/basename.c << 'END-of-contrib/diff/lib/basename.c' X/* basename.c -- return the last element in a path X Copyright (C) 1990, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software Foundation, X Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#if HAVE_CONFIG_H X# include X#endif X X#if STDC_HEADERS || HAVE_STRING_H X# include X#endif X#include "dirname.h" X X/* In general, we can't use the builtin `basename' function if available, X since it has different meanings in different environments. X In some environments the builtin `basename' modifies its argument. X X Return the address of the last file name component of NAME. If X NAME has no file name components because it is all slashes, return X NAME if it is empty, the address of its last slash otherwise. */ X Xchar * Xbase_name (char const *name) X{ X char const *base = name + FILESYSTEM_PREFIX_LEN (name); X char const *p; X X for (p = base; *p; p++) X { X if (ISSLASH (*p)) X { X /* Treat multiple adjacent slashes like a single slash. */ X do p++; X while (ISSLASH (*p)); X X /* If the file name ends in slash, use the trailing slash as X the basename if no non-slashes have been found. */ X if (! *p) X { X if (ISSLASH (*base)) X base = p - 1; X break; X } X X /* *P is a non-slash preceded by a slash. */ X base = p; X } X } X X return (char *) base; X} X X/* Return the length of of the basename NAME. Typically NAME is the X value returned by base_name. Act like strlen (NAME), except omit X redundant trailing slashes. */ X Xsize_t Xbase_len (char const *name) X{ X size_t len; X X for (len = strlen (name); 1 < len && ISSLASH (name[len - 1]); len--) X continue; X X return len; X} END-of-contrib/diff/lib/basename.c echo x - contrib/diff/lib/c-stack.c sed 's/^X//' >contrib/diff/lib/c-stack.c << 'END-of-contrib/diff/lib/c-stack.c' X/* Stack overflow handling. X X Copyright (C) 2002 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software Foundation, X Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X/* Written by Paul Eggert. */ X X/* This module assumes that each stack frame is smaller than a page. X If you use alloca, dynamic arrays, or large local variables, your X program may extend the stack by more than a page at a time. If so, X the code below may incorrectly report a program error, or worse X yet, may not detect the overflow at all. To avoid this problem, X don't use large local arrays. */ X X#if HAVE_CONFIG_H X# include X#endif X X#include "gettext.h" X#define _(msgid) gettext (msgid) X X#include X#ifndef ENOTSUP X# define ENOTSUP EINVAL X#endif X X#if HAVE_INTTYPES_H X# include X#else X# if HAVE_STDINT_H X# include X# endif X#endif X X#include X#include X#include X X#if HAVE_UNISTD_H X# include X#endif X#ifndef STDERR_FILENO X# define STDERR_FILENO 2 X#endif X X#include "c-stack.h" X#include "exitfail.h" X Xextern char *program_name; X X#if HAVE_XSI_STACK_OVERFLOW_HEURISTIC X X# include X X X/* Storage for the alternate signal stack. */ Xstatic union X{ X char buffer[SIGSTKSZ]; X X /* These other members are for proper alignment. There's no X standard way to guarantee stack alignment, but this seems enough X in practice. */ X long double ld; X uintmax_t u; X void *p; X} alternate_signal_stack; X X X/* Direction of the C runtime stack. This function is X async-signal-safe. */ X X# if STACK_DIRECTION X# define find_stack_direction(ptr) STACK_DIRECTION X# else Xstatic int Xfind_stack_direction (char const *addr) X{ X char dummy; X return ! addr ? find_stack_direction (&dummy) : addr < &dummy ? 1 : -1; X} X# endif X X/* The SIGSEGV handler. */ Xstatic void (* volatile segv_action) (int, siginfo_t *, void *); X X/* Handle a segmentation violation and exit. This function is X async-signal-safe. */ X Xstatic void Xsegv_handler (int signo, siginfo_t *info, void *context) X{ X /* Clear SIGNO if it seems to have been a stack overflow. */ X if (0 < info->si_code) X { X /* If the faulting address is within the stack, or within one X page of the stack end, assume that it is a stack X overflow. */ X ucontext_t const *user_context = context; X char const *stack_min = user_context->uc_stack.ss_sp; X size_t stack_size = user_context->uc_stack.ss_size; X char const *faulting_address = info->si_addr; X size_t s = faulting_address - stack_min; X size_t page_size = sysconf (_SC_PAGESIZE); X if (find_stack_direction (0) < 0) X s += page_size; X if (s < stack_size + page_size) X signo = 0; X } X X segv_action (signo, info, context); X} X X#endif /* HAVE_XSI_STACK_OVERFLOW_HEURISTIC */ X X X/* Translated messages for program errors and stack overflow. Do not X translate them in the signal handler, since gettext is not X async-signal-safe. */ Xstatic char const * volatile program_error_message; Xstatic char const * volatile stack_overflow_message; X X/* Output an error message, then exit with status EXIT_FAILURE if it X appears to have been a stack overflow, or with a core dump X otherwise. This function is async-signal-safe. */ X Xvoid Xc_stack_die (int signo, siginfo_t *info, void *context) X{ X char const *message = X signo ? program_error_message : stack_overflow_message; X write (STDERR_FILENO, program_name, strlen (program_name)); X write (STDERR_FILENO, ": ", 2); X write (STDERR_FILENO, message, strlen (message)); X write (STDERR_FILENO, "\n", 1); X if (! signo) X _exit (exit_failure); X#if HAVE_SIGINFO_T X if (context && info && 0 <= info->si_code) X { X /* Re-raise the exception at the same address. */ X char *addr = info->si_addr; X *addr = 0; X } X#endif X kill (getpid (), signo); X} X X X/* Set up ACTION so that it is invoked on C stack overflow. Return -1 X (setting errno) if this cannot be done. X X ACTION must invoke only async-signal-safe functions. ACTION X together with its callees must not require more than SIGSTKSZ bytes X of stack space. */ X Xint Xc_stack_action (void (*action) (int, siginfo_t *, void *)) X{ X#if ! HAVE_XSI_STACK_OVERFLOW_HEURISTIC X errno = ENOTSUP; X return -1; X#else X struct sigaction act; X stack_t st; X int r; X X st.ss_flags = 0; X st.ss_sp = alternate_signal_stack.buffer; X st.ss_size = sizeof alternate_signal_stack.buffer; X r = sigaltstack (&st, 0); X if (r != 0) X return r; X X program_error_message = _("program error"); X stack_overflow_message = _("stack overflow"); X segv_action = action; X X sigemptyset (&act.sa_mask); X X /* POSIX 1003.1-2001 says SA_RESETHAND implies SA_NODEFER, but this X is not true on Solaris 8 at least. It doesn't hurt to use X SA_NODEFER here, so leave it in. */ X act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO; X X act.sa_sigaction = segv_handler; X return sigaction (SIGSEGV, &act, 0); X#endif X} X X#if DEBUG X X#include X Xint volatile exit_failure; X Xstatic long Xrecurse (char *p) X{ X char array[500]; X array[0] = 1; X return *p + recurse (array); X} X Xchar *program_name; X Xint Xmain (int argc, char **argv) X{ X program_name = argv[0]; X c_stack_action (c_stack_die); X return recurse ("\1"); X} X X#endif /* DEBUG */ X X/* XLocal Variables: Xcompile-command: "gcc -D_GNU_SOURCE -DDEBUG \ X -DHAVE_INTTYPES_H -DHAVE_SIGINFO_T \ X -DHAVE_XSI_STACK_OVERFLOW_HEURISTIC -DHAVE_UNISTD_H \ X -Wall -W -g c-stack.c -o c-stack" XEnd: X*/ END-of-contrib/diff/lib/c-stack.c echo x - contrib/diff/lib/cmpbuf.c sed 's/^X//' >contrib/diff/lib/cmpbuf.c << 'END-of-contrib/diff/lib/cmpbuf.c' X/* Buffer primitives for comparison operations. X X Copyright (C) 1993, 1995, 1998, 2001, 2002 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; see the file COPYING. X If not, write to the Free Software Foundation, X 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#if HAVE_CONFIG_H X# include X#endif X X#include X#include X X#include X#ifndef SA_RESTART X# ifdef SA_INTERRUPT /* e.g. SunOS 4.1.x */ X# define SA_RESTART SA_INTERRUPT X# else X# define SA_RESTART 0 X# endif X#endif X X#if HAVE_UNISTD_H X# include X#endif X X#if HAVE_INTTYPES_H X# include X#endif X X#include X#include "cmpbuf.h" X X/* Determine whether an integer type is signed, and its bounds. X This code assumes two's (or one's!) complement with no holes. */ X X/* The extra casts work around common compiler bugs, X e.g. Cray C 5.0.3.0 when t == time_t. */ X#ifndef TYPE_SIGNED X# define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) X#endif X#ifndef TYPE_MINIMUM X# define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \ X ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) \ X : (t) 0)) X#endif X#ifndef TYPE_MAXIMUM X# define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t))) X#endif X X#ifndef PTRDIFF_MAX X# define PTRDIFF_MAX TYPE_MAXIMUM (ptrdiff_t) X#endif X#ifndef SIZE_MAX X# define SIZE_MAX TYPE_MAXIMUM (size_t) X#endif X#ifndef SSIZE_MAX X# define SSIZE_MAX TYPE_MAXIMUM (ssize_t) X#endif X X#undef MIN X#define MIN(a, b) ((a) <= (b) ? (a) : (b)) X X/* Read NBYTES bytes from descriptor FD into BUF. X NBYTES must not be SIZE_MAX. X Return the number of characters successfully read. X On error, return SIZE_MAX, setting errno. X The number returned is always NBYTES unless end-of-file or error. */ X Xsize_t Xblock_read (int fd, char *buf, size_t nbytes) X{ X char *bp = buf; X char const *buflim = buf + nbytes; X size_t readlim = SSIZE_MAX; X X do X { X size_t bytes_to_read = MIN (buflim - bp, readlim); X ssize_t nread = read (fd, bp, bytes_to_read); X if (nread <= 0) X { X if (nread == 0) X break; X X /* Accommodate Tru64 5.1, which can't read more than INT_MAX X bytes at a time. They call that a 64-bit OS? */ X if (errno == EINVAL && INT_MAX < bytes_to_read) X { X readlim = INT_MAX; X continue; X } X X /* This is needed for programs that have signal handlers on X older hosts without SA_RESTART. It also accommodates X ancient AIX hosts that set errno to EINTR after uncaught X SIGCONT. See X (1993-04-22). */ X if (! SA_RESTART && errno == EINTR) X continue; X X return SIZE_MAX; X } X bp += nread; X } X while (bp < buflim); X X return bp - buf; X} X X/* Least common multiple of two buffer sizes A and B. However, if X either A or B is zero, or if the multiple is greater than LCM_MAX, X return a reasonable buffer size. */ X Xsize_t Xbuffer_lcm (size_t a, size_t b, size_t lcm_max) X{ X size_t lcm, m, n, q, r; X X /* Yield reasonable values if buffer sizes are zero. */ X if (!a) X return b ? b : 8 * 1024; X if (!b) X return a; X X /* n = gcd (a, b) */ X for (m = a, n = b; (r = m % n) != 0; m = n, n = r) X continue; X X /* Yield a if there is an overflow. */ X q = a / n; X lcm = q * b; X return lcm <= lcm_max && lcm / b == q ? lcm : a; X} END-of-contrib/diff/lib/cmpbuf.c echo x - contrib/diff/lib/error.c sed 's/^X//' >contrib/diff/lib/error.c << 'END-of-contrib/diff/lib/error.c' X/* Error handler for noninteractive utilities X Copyright (C) 1990-1998, 2000, 2001 Free Software Foundation, Inc. X This file is part of the GNU C Library. Its master source is NOT part of X the C library, however. The master source lives in /gd/gnu/lib. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software Foundation, X Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X/* Written by David MacKenzie . */ X X#ifdef HAVE_CONFIG_H X# include X#endif X X#include X#if HAVE_LIBINTL_H X# include X#endif X#ifdef _LIBC X# include X# define mbsrtowcs __mbsrtowcs X#endif X X#if HAVE_VPRINTF || HAVE_DOPRNT || _LIBC X# if __STDC__ X# include X# define VA_START(args, lastarg) va_start(args, lastarg) X# else X# include X# define VA_START(args, lastarg) va_start(args) X# endif X#else X# define va_alist a1, a2, a3, a4, a5, a6, a7, a8 X# define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8; X#endif X X#if STDC_HEADERS || _LIBC X# include X# include X#else Xvoid exit (); X#endif X X#include "error.h" X#include "unlocked-io.h" X X#ifndef _ X# define _(String) String X#endif X X/* If NULL, error will flush stdout, then print on stderr the program X name, a colon and a space. Otherwise, error will call this X function without parameters instead. */ Xvoid (*error_print_progname) ( X#if __STDC__ - 0 X void X#endif X ); X X/* This variable is incremented each time `error' is called. */ Xunsigned int error_message_count; X X#ifdef _LIBC X/* In the GNU C library, there is a predefined variable for this. */ X X# define program_name program_invocation_name X# include X X/* In GNU libc we want do not want to use the common name `error' directly. X Instead make it a weak alias. */ Xextern void __error (int status, int errnum, const char *message, ...) X __attribute__ ((__format__ (__printf__, 3, 4))); Xextern void __error_at_line (int status, int errnum, const char *file_name, X unsigned int line_number, const char *message, X ...) X __attribute__ ((__format__ (__printf__, 5, 6)));; X# define error __error X# define error_at_line __error_at_line X X# ifdef USE_IN_LIBIO X# include X# define fflush(s) _IO_fflush (s) X# endif X X#else /* not _LIBC */ X X# if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P X# ifndef HAVE_DECL_STRERROR_R X"this configure-time declaration test was not run" X# endif Xchar *strerror_r (); X# endif X X/* The calling program should define program_name and set it to the X name of the executing program. */ Xextern char *program_name; X X# if HAVE_STRERROR_R || defined strerror_r X# define __strerror_r strerror_r X# else X# if HAVE_STRERROR X# ifndef HAVE_DECL_STRERROR X"this configure-time declaration test was not run" X# endif X# if !HAVE_DECL_STRERROR Xchar *strerror (); X# endif X# else Xstatic char * Xprivate_strerror (int errnum) X{ X extern char *sys_errlist[]; X extern int sys_nerr; X X if (errnum > 0 && errnum <= sys_nerr) X return _(sys_errlist[errnum]); X return _("Unknown system error"); X} X# define strerror private_strerror X# endif /* HAVE_STRERROR */ X# endif /* HAVE_STRERROR_R || defined strerror_r */ X#endif /* not _LIBC */ X Xstatic void Xprint_errno_message (int errnum) X{ X char const *s; X X#if defined HAVE_STRERROR_R || _LIBC X char errbuf[1024]; X# if STRERROR_R_CHAR_P || _LIBC X s = __strerror_r (errnum, errbuf, sizeof errbuf); X# else X if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0) X s = errbuf; X else X s = 0; X# endif X#else X s = strerror (errnum); X#endif X X#if !_LIBC X if (! s) X s = _("Unknown system error"); X#endif X X#if _LIBC && USE_IN_LIBIO X if (_IO_fwide (stderr, 0) > 0) X { X __fwprintf (stderr, L": %s", s); X return; X } X#endif X X fprintf (stderr, ": %s", s); X} X X#ifdef VA_START Xstatic void Xerror_tail (int status, int errnum, const char *message, va_list args) X{ X# if HAVE_VPRINTF || _LIBC X# if _LIBC && USE_IN_LIBIO X if (_IO_fwide (stderr, 0) > 0) X { X# define ALLOCA_LIMIT 2000 X size_t len = strlen (message) + 1; X wchar_t *wmessage = NULL; X mbstate_t st; X size_t res; X const char *tmp; X X do X { X if (len < ALLOCA_LIMIT) X wmessage = (wchar_t *) alloca (len * sizeof (wchar_t)); X else X { X if (wmessage != NULL && len / 2 < ALLOCA_LIMIT) X wmessage = NULL; X X wmessage = (wchar_t *) realloc (wmessage, X len * sizeof (wchar_t)); X X if (wmessage == NULL) X { X fputws_unlocked (L"out of memory\n", stderr); X return; X } X } X X memset (&st, '\0', sizeof (st)); X tmp =message; X } X while ((res = mbsrtowcs (wmessage, &tmp, len, &st)) == len); X X if (res == (size_t) -1) X /* The string cannot be converted. */ X wmessage = (wchar_t *) L"???"; X X __vfwprintf (stderr, wmessage, args); X } X else X# endif X vfprintf (stderr, message, args); X# else X _doprnt (message, args, stderr); X# endif X va_end (args); X X ++error_message_count; X if (errnum) X print_errno_message (errnum); X# if _LIBC && USE_IN_LIBIO X if (_IO_fwide (stderr, 0) > 0) X putwc (L'\n', stderr); X else X# endif X putc ('\n', stderr); X fflush (stderr); X if (status) X exit (status); X} X#endif X X X/* Print the program name and error message MESSAGE, which is a printf-style X format string with optional args. X If ERRNUM is nonzero, print its corresponding system error message. X Exit with status STATUS if it is nonzero. */ X/* VARARGS */ Xvoid X#if defined VA_START && __STDC__ Xerror (int status, int errnum, const char *message, ...) X#else Xerror (status, errnum, message, va_alist) X int status; X int errnum; X char *message; X va_dcl X#endif X{ X#ifdef VA_START X va_list args; X#endif X X fflush (stdout); X#ifdef _LIBC X# ifdef USE_IN_LIBIO X _IO_flockfile (stderr); X# else X __flockfile (stderr); X# endif X#endif X if (error_print_progname) X (*error_print_progname) (); X else X { X#if _LIBC && USE_IN_LIBIO X if (_IO_fwide (stderr, 0) > 0) X __fwprintf (stderr, L"%s: ", program_name); X else X#endif X fprintf (stderr, "%s: ", program_name); X } X X#ifdef VA_START X VA_START (args, message); X error_tail (status, errnum, message, args); X#else X fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8); X X ++error_message_count; X if (errnum) X print_errno_message (errnum); X putc ('\n', stderr); X fflush (stderr); X if (status) X exit (status); X#endif X X#ifdef _LIBC X# ifdef USE_IN_LIBIO X _IO_funlockfile (stderr); X# else X __funlockfile (stderr); X# endif X#endif X} X X/* Sometimes we want to have at most one error per line. This X variable controls whether this mode is selected or not. */ Xint error_one_per_line; X Xvoid X#if defined VA_START && __STDC__ Xerror_at_line (int status, int errnum, const char *file_name, X unsigned int line_number, const char *message, ...) X#else Xerror_at_line (status, errnum, file_name, line_number, message, va_alist) X int status; X int errnum; X const char *file_name; X unsigned int line_number; X char *message; X va_dcl X#endif X{ X#ifdef VA_START X va_list args; X#endif X X if (error_one_per_line) X { X static const char *old_file_name; X static unsigned int old_line_number; X X if (old_line_number == line_number X && (file_name == old_file_name X || strcmp (old_file_name, file_name) == 0)) X /* Simply return and print nothing. */ X return; X X old_file_name = file_name; X old_line_number = line_number; X } X X fflush (stdout); X#ifdef _LIBC X# ifdef USE_IN_LIBIO X _IO_flockfile (stderr); X# else X __flockfile (stderr); X# endif X#endif X if (error_print_progname) X (*error_print_progname) (); X else X { X#if _LIBC && USE_IN_LIBIO X if (_IO_fwide (stderr, 0) > 0) X __fwprintf (stderr, L"%s: ", program_name); X else X#endif X fprintf (stderr, "%s:", program_name); X } X X if (file_name != NULL) X { X#if _LIBC && USE_IN_LIBIO X if (_IO_fwide (stderr, 0) > 0) X __fwprintf (stderr, L"%s:%d: ", file_name, line_number); X else X#endif X fprintf (stderr, "%s:%d: ", file_name, line_number); X } X X#ifdef VA_START X VA_START (args, message); X error_tail (status, errnum, message, args); X#else X fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8); X X ++error_message_count; X if (errnum) X print_errno_message (errnum); X putc ('\n', stderr); X fflush (stderr); X if (status) X exit (status); X#endif X X#ifdef _LIBC X# ifdef USE_IN_LIBIO X _IO_funlockfile (stderr); X# else X __funlockfile (stderr); X# endif X#endif X} X X#ifdef _LIBC X/* Make the weak alias. */ X# undef error X# undef error_at_line Xweak_alias (__error, error) Xweak_alias (__error_at_line, error_at_line) X#endif END-of-contrib/diff/lib/error.c echo x - contrib/diff/lib/exclude.c sed 's/^X//' >contrib/diff/lib/exclude.c << 'END-of-contrib/diff/lib/exclude.c' X/* exclude.c -- exclude file names X X Copyright 1992, 1993, 1994, 1997, 1999, 2000, 2001 Free Software X Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; see the file COPYING. X If not, write to the Free Software Foundation, X 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X/* Written by Paul Eggert */ X X#if HAVE_CONFIG_H X# include X#endif X X#if HAVE_STDBOOL_H X# include X#else Xtypedef enum {false = 0, true = 1} bool; X#endif X X#include X#ifndef errno Xextern int errno; X#endif X#include X#if HAVE_SYS_TYPES_H X# include X#endif X#if HAVE_STDLIB_H X# include X#endif X#if HAVE_STRING_H X# include X#endif X#if HAVE_STRINGS_H X# include X#endif X#if HAVE_INTTYPES_H X# include X#else X# if HAVE_STDINT_H X# include X# endif X#endif X X#include "exclude.h" X#include "fnmatch.h" X#include "unlocked-io.h" X#include "xalloc.h" X X#ifndef SIZE_MAX X# define SIZE_MAX ((size_t) -1) X#endif X X/* Verify a requirement at compile-time (unlike assert, which is runtime). */ X#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; } X Xverify (EXCLUDE_macros_do_not_collide_with_FNM_macros, X (((EXCLUDE_ANCHORED | EXCLUDE_INCLUDE | EXCLUDE_WILDCARDS) X & (FNM_FILE_NAME | FNM_NOESCAPE | FNM_PERIOD | FNM_LEADING_DIR X | FNM_CASEFOLD)) X == 0)); X X/* An exclude pattern-options pair. The options are fnmatch options X ORed with EXCLUDE_* options. */ X Xstruct patopts X { X char const *pattern; X int options; X }; X X/* An exclude list, of pattern-options pairs. */ X Xstruct exclude X { X struct patopts *exclude; X size_t exclude_alloc; X size_t exclude_count; X }; X X/* Return a newly allocated and empty exclude list. */ X Xstruct exclude * Xnew_exclude (void) X{ X struct exclude *ex = (struct exclude *) xmalloc (sizeof *ex); X ex->exclude_count = 0; X ex->exclude_alloc = (1 << 6); /* This must be a power of 2. */ X ex->exclude = (struct patopts *) xmalloc (ex->exclude_alloc X * sizeof ex->exclude[0]); X return ex; X} X X/* Free the storage associated with an exclude list. */ X Xvoid Xfree_exclude (struct exclude *ex) X{ X free (ex->exclude); X free (ex); X} X X/* Return zero if PATTERN matches F, obeying OPTIONS, except that X (unlike fnmatch) wildcards are disabled in PATTERN. */ X Xstatic int Xfnmatch_no_wildcards (char const *pattern, char const *f, int options) X{ X if (! (options & FNM_LEADING_DIR)) X return ((options & FNM_CASEFOLD) X ? strcasecmp (pattern, f) X : strcmp (pattern, f)); X else X { X size_t patlen = strlen (pattern); X int r = ((options & FNM_CASEFOLD) X ? strncasecmp (pattern, f, patlen) X : strncmp (pattern, f, patlen)); X if (! r) X { X r = f[patlen]; X if (r == '/') X r = 0; X } X return r; X } X} X X/* Return true if EX excludes F. */ X Xbool Xexcluded_filename (struct exclude const *ex, char const *f) X{ X size_t exclude_count = ex->exclude_count; X X /* If no options are given, the default is to include. */ X if (exclude_count == 0) X return false; X else X { X struct patopts const *exclude = ex->exclude; X size_t i; X X /* Otherwise, the default is the opposite of the first option. */ X bool excluded = !! (exclude[0].options & EXCLUDE_INCLUDE); X X /* Scan through the options, seeing whether they change F from X excluded to included or vice versa. */ X for (i = 0; i < exclude_count; i++) X { X char const *pattern = exclude[i].pattern; X int options = exclude[i].options; X if (excluded == !! (options & EXCLUDE_INCLUDE)) X { X int (*matcher) PARAMS ((char const *, char const *, int)) = X (options & EXCLUDE_WILDCARDS X ? fnmatch X : fnmatch_no_wildcards); X bool matched = ((*matcher) (pattern, f, options) == 0); X char const *p; X X if (! (options & EXCLUDE_ANCHORED)) X for (p = f; *p && ! matched; p++) X if (*p == '/' && p[1] != '/') X matched = ((*matcher) (pattern, p + 1, options) == 0); X X excluded ^= matched; X } X } X X return excluded; X } X} X X/* Append to EX the exclusion PATTERN with OPTIONS. */ X Xvoid Xadd_exclude (struct exclude *ex, char const *pattern, int options) X{ X struct patopts *patopts; X X if (ex->exclude_alloc <= ex->exclude_count) X { X size_t s = 2 * ex->exclude_alloc; X if (! (0 < s && s <= SIZE_MAX / sizeof ex->exclude[0])) X xalloc_die (); X ex->exclude_alloc = s; X ex->exclude = (struct patopts *) xrealloc (ex->exclude, X s * sizeof ex->exclude[0]); X } X X patopts = &ex->exclude[ex->exclude_count++]; X patopts->pattern = pattern; X patopts->options = options; X} X X/* Use ADD_FUNC to append to EX the patterns in FILENAME, each with X OPTIONS. LINE_END terminates each pattern in the file. Return -1 X on failure, 0 on success. */ X Xint Xadd_exclude_file (void (*add_func) PARAMS ((struct exclude *, X char const *, int)), X struct exclude *ex, char const *filename, int options, X char line_end) X{ X bool use_stdin = filename[0] == '-' && !filename[1]; X FILE *in; X char *buf; X char *p; X char const *pattern; X char const *lim; X size_t buf_alloc = (1 << 10); /* This must be a power of two. */ X size_t buf_count = 0; X int c; X int e = 0; X X if (use_stdin) X in = stdin; X else if (! (in = fopen (filename, "r"))) X return -1; X X buf = xmalloc (buf_alloc); X X while ((c = getc (in)) != EOF) X { X buf[buf_count++] = c; X if (buf_count == buf_alloc) X { X buf_alloc *= 2; X if (! buf_alloc) X xalloc_die (); X buf = xrealloc (buf, buf_alloc); X } X } X X if (ferror (in)) X e = errno; X X if (!use_stdin && fclose (in) != 0) X e = errno; X X buf = xrealloc (buf, buf_count + 1); X X for (pattern = p = buf, lim = buf + buf_count; p <= lim; p++) X if (p < lim ? *p == line_end : buf < p && p[-1]) X { X *p = '\0'; X (*add_func) (ex, pattern, options); X pattern = p + 1; X } X X errno = e; X return e ? -1 : 0; X} END-of-contrib/diff/lib/exclude.c echo x - contrib/diff/lib/exitfail.c sed 's/^X//' >contrib/diff/lib/exitfail.c << 'END-of-contrib/diff/lib/exitfail.c' X/* Failure exit status X X Copyright (C) 2002 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; see the file COPYING. X If not, write to the Free Software Foundation, X 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#if HAVE_CONFIG_H X# include X#endif X X#if HAVE_STDLIB_H X# include X#endif X#ifndef EXIT_FAILURE X# define EXIT_FAILURE 1 X#endif X Xint volatile exit_failure = EXIT_FAILURE; END-of-contrib/diff/lib/exitfail.c echo x - contrib/diff/lib/freesoft.c sed 's/^X//' >contrib/diff/lib/freesoft.c << 'END-of-contrib/diff/lib/freesoft.c' X/* Free software message ID. X X Copyright (C) 2001 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software Foundation, X Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#if HAVE_CONFIG_H X# include X#endif X X#include "freesoft.h" X X#define N_(Text) Text X Xchar const free_software_msgid[] = N_("\ XThis program comes with NO WARRANTY, to the extent permitted by law.\n\ XYou may redistribute copies of this program\n\ Xunder the terms of the GNU General Public License.\n\ XFor more information about these matters, see the file named COPYING."); END-of-contrib/diff/lib/freesoft.c echo x - contrib/diff/lib/getopt.c sed 's/^X//' >contrib/diff/lib/getopt.c << 'END-of-contrib/diff/lib/getopt.c' X/* Getopt for GNU. X NOTE: getopt is now part of the C library, so if you don't know what X "Keep this file name-space clean" means, talk to drepper@gnu.org X before changing it! X Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001 X Free Software Foundation, Inc. X This file is part of the GNU C Library. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software Foundation, X Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X/* This tells Alpha OSF/1 not to define a getopt prototype in . X Ditto for AIX 3.2 and . */ X#ifndef _NO_PROTO X# define _NO_PROTO X#endif X X#ifdef HAVE_CONFIG_H X# include X#endif X X#if !defined __STDC__ || !__STDC__ X/* This is a separate conditional since some stdc systems X reject `defined (const)'. */ X# ifndef const X# define const X# endif X#endif X X#include X X/* Comment out all this code if we are using the GNU C Library, and are not X actually compiling the library itself. This code is part of the GNU C X Library, but also included in many other GNU distributions. Compiling X and linking in this code is a waste when using the GNU C library X (especially if it is a shared library). Rather than having every GNU X program understand `configure --with-gnu-libc' and omit the object files, X it is simpler to just do this in the source for each such file. */ X X#define GETOPT_INTERFACE_VERSION 2 X#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 X# include X# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION X# define ELIDE_CODE X# endif X#endif X X#ifndef ELIDE_CODE X X X/* This needs to come after some library #include X to get __GNU_LIBRARY__ defined. */ X#ifdef __GNU_LIBRARY__ X/* Don't include stdlib.h for non-GNU C libraries because some of them X contain conflicting prototypes for getopt. */ X# include X# include X#endif /* GNU C library. */ X X#ifdef VMS X# include X# if HAVE_STRING_H - 0 X# include X# endif X#endif X X#ifndef _ X/* This is for other GNU distributions with internationalized messages. */ X# if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC X# include X# ifndef _ X# define _(msgid) gettext (msgid) X# endif X# else X# define _(msgid) (msgid) X# endif X#endif X X/* This version of `getopt' appears to the caller like standard Unix `getopt' X but it behaves differently for the user, since it allows the user X to intersperse the options with the other arguments. X X As `getopt' works, it permutes the elements of ARGV so that, X when it is done, all the options precede everything else. Thus X all application programs are extended to handle flexible argument order. X X Setting the environment variable POSIXLY_CORRECT disables permutation. X Then the behavior is completely standard. X X GNU application programs can use a third alternative mode in which X they can distinguish the relative order of options and other arguments. */ X X#include "getopt.h" X X/* For communication from `getopt' to the caller. X When `getopt' finds an option that takes an argument, X the argument value is returned here. X Also, when `ordering' is RETURN_IN_ORDER, X each non-option ARGV-element is returned here. */ X Xchar *optarg; X X/* Index in ARGV of the next element to be scanned. X This is used for communication to and from the caller X and for communication between successive calls to `getopt'. X X On entry to `getopt', zero means this is the first call; initialize. X X When `getopt' returns -1, this is the index of the first of the X non-option elements that the caller should itself scan. X X Otherwise, `optind' communicates from one call to the next X how much of ARGV has been scanned so far. */ X X/* 1003.2 says this must be 1 before any call. */ Xint optind = 1; X X/* Formerly, initialization of getopt depended on optind==0, which X causes problems with re-calling getopt as programs generally don't X know that. */ X Xint __getopt_initialized; X X/* The next char to be scanned in the option-element X in which the last option character we returned was found. X This allows us to pick up the scan where we left off. X X If this is zero, or a null string, it means resume the scan X by advancing to the next ARGV-element. */ X Xstatic char *nextchar; X X/* Callers store zero here to inhibit the error message X for unrecognized options. */ X Xint opterr = 1; X X/* Set to an option character which was unrecognized. X This must be initialized on some systems to avoid linking in the X system's own getopt implementation. */ X Xint optopt = '?'; X X/* Describe how to deal with options that follow non-option ARGV-elements. X X If the caller did not specify anything, X the default is REQUIRE_ORDER if the environment variable X POSIXLY_CORRECT is defined, PERMUTE otherwise. X X REQUIRE_ORDER means don't recognize them as options; X stop option processing when the first non-option is seen. X This is what Unix does. X This mode of operation is selected by either setting the environment X variable POSIXLY_CORRECT, or using `+' as the first character X of the list of option characters. X X PERMUTE is the default. We permute the contents of ARGV as we scan, X so that eventually all the non-options are at the end. This allows options X to be given in any order, even with programs that were not written to X expect this. X X RETURN_IN_ORDER is an option available to programs that were written X to expect options and other ARGV-elements in any order and that care about X the ordering of the two. We describe each non-option ARGV-element X as if it were the argument of an option with character code 1. X Using `-' as the first character of the list of option characters X selects this mode of operation. X X The special argument `--' forces an end of option-scanning regardless X of the value of `ordering'. In the case of RETURN_IN_ORDER, only X `--' can cause `getopt' to return -1 with `optind' != ARGC. */ X Xstatic enum X{ X REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER X} ordering; X X/* Value of POSIXLY_CORRECT environment variable. */ Xstatic char *posixly_correct; X X#ifdef __GNU_LIBRARY__ X/* We want to avoid inclusion of string.h with non-GNU libraries X because there are many ways it can cause trouble. X On some systems, it contains special magic macros that don't work X in GCC. */ X# include X# define my_index strchr X#else X X# if HAVE_STRING_H X# include X# else X# include X# endif X X/* Avoid depending on library functions or files X whose names are inconsistent. */ X X#ifndef getenv Xextern char *getenv (); X#endif X Xstatic char * Xmy_index (str, chr) X const char *str; X int chr; X{ X while (*str) X { X if (*str == chr) X return (char *) str; X str++; X } X return 0; X} X X/* If using GCC, we can safely declare strlen this way. X If not using GCC, it is ok not to declare it. */ X#ifdef __GNUC__ X/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. X That was relevant to code that was here before. */ X# if (!defined __STDC__ || !__STDC__) && !defined strlen X/* gcc with -traditional declares the built-in strlen to return int, X and has done so at least since version 2.4.5. -- rms. */ Xextern int strlen (const char *); X# endif /* not __STDC__ */ X#endif /* __GNUC__ */ X X#endif /* not __GNU_LIBRARY__ */ X X/* Handle permutation of arguments. */ X X/* Describe the part of ARGV that contains non-options that have X been skipped. `first_nonopt' is the index in ARGV of the first of them; X `last_nonopt' is the index after the last of them. */ X Xstatic int first_nonopt; Xstatic int last_nonopt; X X#ifdef _LIBC X/* Bash 2.0 gives us an environment variable containing flags X indicating ARGV elements that should not be considered arguments. */ X X#ifdef USE_NONOPTION_FLAGS X/* Defined in getopt_init.c */ Xextern char *__getopt_nonoption_flags; X Xstatic int nonoption_flags_max_len; Xstatic int nonoption_flags_len; X#endif X Xstatic int original_argc; Xstatic char *const *original_argv; X X/* Make sure the environment variable bash 2.0 puts in the environment X is valid for the getopt call we must make sure that the ARGV passed X to getopt is that one passed to the process. */ Xstatic void X__attribute__ ((unused)) Xstore_args_and_env (int argc, char *const *argv) X{ X /* XXX This is no good solution. We should rather copy the args so X that we can compare them later. But we must not use malloc(3). */ X original_argc = argc; X original_argv = argv; X} X# ifdef text_set_element Xtext_set_element (__libc_subinit, store_args_and_env); X# endif /* text_set_element */ X X# ifdef USE_NONOPTION_FLAGS X# define SWAP_FLAGS(ch1, ch2) \ X if (nonoption_flags_len > 0) \ X { \ X char __tmp = __getopt_nonoption_flags[ch1]; \ X __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ X __getopt_nonoption_flags[ch2] = __tmp; \ X } X# else X# define SWAP_FLAGS(ch1, ch2) X# endif X#else /* !_LIBC */ X# define SWAP_FLAGS(ch1, ch2) X#endif /* _LIBC */ X X/* Exchange two adjacent subsequences of ARGV. X One subsequence is elements [first_nonopt,last_nonopt) X which contains all the non-options that have been skipped so far. X The other is elements [last_nonopt,optind), which contains all X the options processed since those non-options were skipped. X X `first_nonopt' and `last_nonopt' are relocated so that they describe X the new indices of the non-options in ARGV after they are moved. */ X X#if defined __STDC__ && __STDC__ Xstatic void exchange (char **); X#endif X Xstatic void Xexchange (argv) X char **argv; X{ X int bottom = first_nonopt; X int middle = last_nonopt; X int top = optind; X char *tem; X X /* Exchange the shorter segment with the far end of the longer segment. X That puts the shorter segment into the right place. X It leaves the longer segment in the right place overall, X but it consists of two parts that need to be swapped next. */ X X#if defined _LIBC && defined USE_NONOPTION_FLAGS X /* First make sure the handling of the `__getopt_nonoption_flags' X string can work normally. Our top argument must be in the range X of the string. */ X if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) X { X /* We must extend the array. The user plays games with us and X presents new arguments. */ X char *new_str = malloc (top + 1); X if (new_str == NULL) X nonoption_flags_len = nonoption_flags_max_len = 0; X else X { X memset (__mempcpy (new_str, __getopt_nonoption_flags, X nonoption_flags_max_len), X '\0', top + 1 - nonoption_flags_max_len); X nonoption_flags_max_len = top + 1; X __getopt_nonoption_flags = new_str; X } X } X#endif X X while (top > middle && middle > bottom) X { X if (top - middle > middle - bottom) X { X /* Bottom segment is the short one. */ X int len = middle - bottom; X register int i; X X /* Swap it with the top part of the top segment. */ X for (i = 0; i < len; i++) X { X tem = argv[bottom + i]; X argv[bottom + i] = argv[top - (middle - bottom) + i]; X argv[top - (middle - bottom) + i] = tem; X SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); X } X /* Exclude the moved bottom segment from further swapping. */ X top -= len; X } X else X { X /* Top segment is the short one. */ X int len = top - middle; X register int i; X X /* Swap it with the bottom part of the bottom segment. */ X for (i = 0; i < len; i++) X { X tem = argv[bottom + i]; X argv[bottom + i] = argv[middle + i]; X argv[middle + i] = tem; X SWAP_FLAGS (bottom + i, middle + i); X } X /* Exclude the moved top segment from further swapping. */ X bottom += len; X } X } X X /* Update records for the slots the non-options now occupy. */ X X first_nonopt += (optind - last_nonopt); X last_nonopt = optind; X} X X/* Initialize the internal data when the first call is made. */ X X#if defined __STDC__ && __STDC__ Xstatic const char *_getopt_initialize (int, char *const *, const char *); X#endif Xstatic const char * X_getopt_initialize (argc, argv, optstring) X int argc; X char *const *argv; X const char *optstring; X{ X /* Start processing options with ARGV-element 1 (since ARGV-element 0 X is the program name); the sequence of previously skipped X non-option ARGV-elements is empty. */ X X first_nonopt = last_nonopt = optind; X X nextchar = NULL; X X posixly_correct = getenv ("POSIXLY_CORRECT"); X X /* Determine how to handle the ordering of options and nonoptions. */ X X if (optstring[0] == '-') X { X ordering = RETURN_IN_ORDER; X ++optstring; X } X else if (optstring[0] == '+') X { X ordering = REQUIRE_ORDER; X ++optstring; X } X else if (posixly_correct != NULL) X ordering = REQUIRE_ORDER; X else X ordering = PERMUTE; X X#if defined _LIBC && defined USE_NONOPTION_FLAGS X if (posixly_correct == NULL X && argc == original_argc && argv == original_argv) X { X if (nonoption_flags_max_len == 0) X { X if (__getopt_nonoption_flags == NULL X || __getopt_nonoption_flags[0] == '\0') X nonoption_flags_max_len = -1; X else X { X const char *orig_str = __getopt_nonoption_flags; X int len = nonoption_flags_max_len = strlen (orig_str); X if (nonoption_flags_max_len < argc) X nonoption_flags_max_len = argc; X __getopt_nonoption_flags = X (char *) malloc (nonoption_flags_max_len); X if (__getopt_nonoption_flags == NULL) X nonoption_flags_max_len = -1; X else X memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), X '\0', nonoption_flags_max_len - len); X } X } X nonoption_flags_len = nonoption_flags_max_len; X } X else X nonoption_flags_len = 0; X#endif X X return optstring; X} X X/* Scan elements of ARGV (whose length is ARGC) for option characters X given in OPTSTRING. X X If an element of ARGV starts with '-', and is not exactly "-" or "--", X then it is an option element. The characters of this element X (aside from the initial '-') are option characters. If `getopt' X is called repeatedly, it returns successively each of the option characters X from each of the option elements. X X If `getopt' finds another option character, it returns that character, X updating `optind' and `nextchar' so that the next call to `getopt' can X resume the scan with the following option character or ARGV-element. X X If there are no more option characters, `getopt' returns -1. X Then `optind' is the index in ARGV of the first ARGV-element X that is not an option. (The ARGV-elements have been permuted X so that those that are not options now come last.) X X OPTSTRING is a string containing the legitimate option characters. X If an option character is seen that is not listed in OPTSTRING, X return '?' after printing an error message. If you set `opterr' to X zero, the error message is suppressed but we still return '?'. X X If a char in OPTSTRING is followed by a colon, that means it wants an arg, X so the following text in the same ARGV-element, or the text of the following X ARGV-element, is returned in `optarg'. Two colons mean an option that X wants an optional arg; if there is text in the current ARGV-element, X it is returned in `optarg', otherwise `optarg' is set to zero. X X If OPTSTRING starts with `-' or `+', it requests different methods of X handling the non-option ARGV-elements. X See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. X X Long-named options begin with `--' instead of `-'. X Their names may be abbreviated as long as the abbreviation is unique X or is an exact match for some defined option. If they have an X argument, it follows the option name in the same ARGV-element, separated X from the option name by a `=', or else the in next ARGV-element. X When `getopt' finds a long-named option, it returns 0 if that option's X `flag' field is nonzero, the value of the option's `val' field X if the `flag' field is zero. X X The elements of ARGV aren't really const, because we permute them. X But we pretend they're const in the prototype to be compatible X with other systems. X X LONGOPTS is a vector of `struct option' terminated by an X element containing a name which is zero. X X LONGIND returns the index in LONGOPT of the long-named option found. X It is only valid when a long-named option has been found by the most X recent call. X X If LONG_ONLY is nonzero, '-' as well as '--' can introduce X long-named options. */ X Xint X_getopt_internal (argc, argv, optstring, longopts, longind, long_only) X int argc; X char *const *argv; X const char *optstring; X const struct option *longopts; X int *longind; X int long_only; X{ X int print_errors = opterr; X if (optstring[0] == ':') X print_errors = 0; X X if (argc < 1) X return -1; X X optarg = NULL; X X if (optind == 0 || !__getopt_initialized) X { X if (optind == 0) X optind = 1; /* Don't scan ARGV[0], the program name. */ X optstring = _getopt_initialize (argc, argv, optstring); X __getopt_initialized = 1; X } X X /* Test whether ARGV[optind] points to a non-option argument. X Either it does not have option syntax, or there is an environment flag X from the shell indicating it is not an option. The later information X is only used when the used in the GNU libc. */ X#if defined _LIBC && defined USE_NONOPTION_FLAGS X# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ X || (optind < nonoption_flags_len \ X && __getopt_nonoption_flags[optind] == '1')) X#else X# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') X#endif X X if (nextchar == NULL || *nextchar == '\0') X { X /* Advance to the next ARGV-element. */ X X /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been X moved back by the user (who may also have changed the arguments). */ X if (last_nonopt > optind) X last_nonopt = optind; X if (first_nonopt > optind) X first_nonopt = optind; X X if (ordering == PERMUTE) X { X /* If we have just processed some options following some non-options, X exchange them so that the options come first. */ X X if (first_nonopt != last_nonopt && last_nonopt != optind) X exchange ((char **) argv); X else if (last_nonopt != optind) X first_nonopt = optind; X X /* Skip any additional non-options X and extend the range of non-options previously skipped. */ X X while (optind < argc && NONOPTION_P) X optind++; X last_nonopt = optind; X } X X /* The special ARGV-element `--' means premature end of options. X Skip it like a null option, X then exchange with previous non-options as if it were an option, X then skip everything else like a non-option. */ X X if (optind != argc && !strcmp (argv[optind], "--")) X { X optind++; X X if (first_nonopt != last_nonopt && last_nonopt != optind) X exchange ((char **) argv); X else if (first_nonopt == last_nonopt) X first_nonopt = optind; X last_nonopt = argc; X X optind = argc; X } X X /* If we have done all the ARGV-elements, stop the scan X and back over any non-options that we skipped and permuted. */ X X if (optind == argc) X { X /* Set the next-arg-index to point at the non-options X that we previously skipped, so the caller will digest them. */ X if (first_nonopt != last_nonopt) X optind = first_nonopt; X return -1; X } X X /* If we have come to a non-option and did not permute it, X either stop the scan or describe it to the caller and pass it by. */ X X if (NONOPTION_P) X { X if (ordering == REQUIRE_ORDER) X return -1; X optarg = argv[optind++]; X return 1; X } X X /* We have found another option-ARGV-element. X Skip the initial punctuation. */ X X nextchar = (argv[optind] + 1 X + (longopts != NULL && argv[optind][1] == '-')); X } X X /* Decode the current option-ARGV-element. */ X X /* Check whether the ARGV-element is a long option. X X If long_only and the ARGV-element has the form "-f", where f is X a valid short option, don't consider it an abbreviated form of X a long option that starts with f. Otherwise there would be no X way to give the -f short option. X X On the other hand, if there's a long option "fubar" and X the ARGV-element is "-fu", do consider that an abbreviation of X the long option, just like "--fu", and not "-f" with arg "u". X X This distinction seems to be the most useful approach. */ X X if (longopts != NULL X && (argv[optind][1] == '-' X || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) X { X char *nameend; X const struct option *p; X const struct option *pfound = NULL; X int exact = 0; X int ambig = 0; X int indfound = -1; X int option_index; X X for (nameend = nextchar; *nameend && *nameend != '='; nameend++) X /* Do nothing. */ ; X X /* Test all long options for either exact match X or abbreviated matches. */ X for (p = longopts, option_index = 0; p->name; p++, option_index++) X if (!strncmp (p->name, nextchar, nameend - nextchar)) X { X if ((unsigned int) (nameend - nextchar) X == (unsigned int) strlen (p->name)) X { X /* Exact match found. */ X pfound = p; X indfound = option_index; X exact = 1; X break; X } X else if (pfound == NULL) X { X /* First nonexact match found. */ X pfound = p; X indfound = option_index; X } X else if (long_only X || pfound->has_arg != p->has_arg X || pfound->flag != p->flag X || pfound->val != p->val) X /* Second or later nonexact match found. */ X ambig = 1; X } X X if (ambig && !exact) X { X if (print_errors) X fprintf (stderr, _("%s: option `%s' is ambiguous\n"), X argv[0], argv[optind]); X nextchar += strlen (nextchar); X optind++; X optopt = 0; X return '?'; X } X X if (pfound != NULL) X { X option_index = indfound; X optind++; X if (*nameend) X { X /* Don't test has_arg with >, because some C compilers don't X allow it to be used on enums. */ X if (pfound->has_arg) X optarg = nameend + 1; X else X { X if (print_errors) X { X if (argv[optind - 1][1] == '-') X /* --option */ X fprintf (stderr, X _("%s: option `--%s' doesn't allow an argument\n"), X argv[0], pfound->name); X else X /* +option or -option */ X fprintf (stderr, X _("%s: option `%c%s' doesn't allow an argument\n"), X argv[0], argv[optind - 1][0], pfound->name); X } X X nextchar += strlen (nextchar); X X optopt = pfound->val; X return '?'; X } X } X else if (pfound->has_arg == 1) X { X if (optind < argc) X optarg = argv[optind++]; X else X { X if (print_errors) X fprintf (stderr, X _("%s: option `%s' requires an argument\n"), X argv[0], argv[optind - 1]); X nextchar += strlen (nextchar); X optopt = pfound->val; X return optstring[0] == ':' ? ':' : '?'; X } X } X nextchar += strlen (nextchar); X if (longind != NULL) X *longind = option_index; X if (pfound->flag) X { X *(pfound->flag) = pfound->val; X return 0; X } X return pfound->val; X } X X /* Can't find it as a long option. If this is not getopt_long_only, X or the option starts with '--' or is not a valid short X option, then it's an error. X Otherwise interpret it as a short option. */ X if (!long_only || argv[optind][1] == '-' X || my_index (optstring, *nextchar) == NULL) X { X if (print_errors) X { X if (argv[optind][1] == '-') X /* --option */ X fprintf (stderr, _("%s: unrecognized option `--%s'\n"), X argv[0], nextchar); X else X /* +option or -option */ X fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), X argv[0], argv[optind][0], nextchar); X } X nextchar = (char *) ""; X optind++; X optopt = 0; X return '?'; X } X } X X /* Look at and handle the next short option-character. */ X X { X char c = *nextchar++; X char *temp = my_index (optstring, c); X X /* Increment `optind' when we start to process its last character. */ X if (*nextchar == '\0') X ++optind; X X if (temp == NULL || c == ':') X { X if (print_errors) X { X if (posixly_correct) X /* 1003.2 specifies the format of this message. */ X fprintf (stderr, _("%s: illegal option -- %c\n"), X argv[0], c); X else X fprintf (stderr, _("%s: invalid option -- %c\n"), X argv[0], c); X } X optopt = c; X return '?'; X } X /* Convenience. Treat POSIX -W foo same as long option --foo */ X if (temp[0] == 'W' && temp[1] == ';') X { X char *nameend; X const struct option *p; X const struct option *pfound = NULL; X int exact = 0; X int ambig = 0; X int indfound = 0; X int option_index; X X /* This is an option that requires an argument. */ X if (*nextchar != '\0') X { X optarg = nextchar; X /* If we end this ARGV-element by taking the rest as an arg, X we must advance to the next element now. */ X optind++; X } X else if (optind == argc) X { X if (print_errors) X { X /* 1003.2 specifies the format of this message. */ X fprintf (stderr, _("%s: option requires an argument -- %c\n"), X argv[0], c); X } X optopt = c; X if (optstring[0] == ':') X c = ':'; X else X c = '?'; X return c; X } X else X /* We already incremented `optind' once; X increment it again when taking next ARGV-elt as argument. */ X optarg = argv[optind++]; X X /* optarg is now the argument, see if it's in the X table of longopts. */ X X for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) X /* Do nothing. */ ; X X /* Test all long options for either exact match X or abbreviated matches. */ X for (p = longopts, option_index = 0; p->name; p++, option_index++) X if (!strncmp (p->name, nextchar, nameend - nextchar)) X { X if ((unsigned int) (nameend - nextchar) == strlen (p->name)) X { X /* Exact match found. */ X pfound = p; X indfound = option_index; X exact = 1; X break; X } X else if (pfound == NULL) X { X /* First nonexact match found. */ X pfound = p; X indfound = option_index; X } X else X /* Second or later nonexact match found. */ X ambig = 1; X } X if (ambig && !exact) X { X if (print_errors) X fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), X argv[0], argv[optind]); X nextchar += strlen (nextchar); X optind++; X return '?'; X } X if (pfound != NULL) X { X option_index = indfound; X if (*nameend) X { X /* Don't test has_arg with >, because some C compilers don't X allow it to be used on enums. */ X if (pfound->has_arg) X optarg = nameend + 1; X else X { X if (print_errors) X fprintf (stderr, _("\ X%s: option `-W %s' doesn't allow an argument\n"), X argv[0], pfound->name); X X nextchar += strlen (nextchar); X return '?'; X } X } X else if (pfound->has_arg == 1) X { X if (optind < argc) X optarg = argv[optind++]; X else X { X if (print_errors) X fprintf (stderr, X _("%s: option `%s' requires an argument\n"), X argv[0], argv[optind - 1]); X nextchar += strlen (nextchar); X return optstring[0] == ':' ? ':' : '?'; X } X } X nextchar += strlen (nextchar); X if (longind != NULL) X *longind = option_index; X if (pfound->flag) X { X *(pfound->flag) = pfound->val; X return 0; X } X return pfound->val; X } X nextchar = NULL; X return 'W'; /* Let the application handle it. */ X } X if (temp[1] == ':') X { X if (temp[2] == ':') X { X /* This is an option that accepts an argument optionally. */ X if (*nextchar != '\0') X { X optarg = nextchar; X optind++; X } X else X optarg = NULL; X nextchar = NULL; X } X else X { X /* This is an option that requires an argument. */ X if (*nextchar != '\0') X { X optarg = nextchar; X /* If we end this ARGV-element by taking the rest as an arg, X we must advance to the next element now. */ X optind++; X } X else if (optind == argc) X { X if (print_errors) X { X /* 1003.2 specifies the format of this message. */ X fprintf (stderr, X _("%s: option requires an argument -- %c\n"), X argv[0], c); X } X optopt = c; X if (optstring[0] == ':') X c = ':'; X else X c = '?'; X } X else X /* We already incremented `optind' once; X increment it again when taking next ARGV-elt as argument. */ X optarg = argv[optind++]; X nextchar = NULL; X } X } X return c; X } X} X Xint Xgetopt (argc, argv, optstring) X int argc; X char *const *argv; X const char *optstring; X{ X return _getopt_internal (argc, argv, optstring, X (const struct option *) 0, X (int *) 0, X 0); X} X X#endif /* Not ELIDE_CODE. */ X X#ifdef TEST X X/* Compile with -DTEST to make an executable for use in testing X the above definition of `getopt'. */ X Xint Xmain (argc, argv) X int argc; X char **argv; X{ X int c; X int digit_optind = 0; X X while (1) X { X int this_option_optind = optind ? optind : 1; X X c = getopt (argc, argv, "abc:d:0123456789"); X if (c == -1) X break; X X switch (c) X { X case '0': X case '1': X case '2': X case '3': X case '4': X case '5': X case '6': X case '7': X case '8': X case '9': X if (digit_optind != 0 && digit_optind != this_option_optind) X printf ("digits occur in two different argv-elements.\n"); X digit_optind = this_option_optind; X printf ("option %c\n", c); X break; X X case 'a': X printf ("option a\n"); X break; X X case 'b': X printf ("option b\n"); X break; X X case 'c': X printf ("option c with value `%s'\n", optarg); X break; X X case '?': X break; X X default: X printf ("?? getopt returned character code 0%o ??\n", c); X } X } X X if (optind < argc) X { X printf ("non-option ARGV-elements: "); X while (optind < argc) X printf ("%s ", argv[optind++]); X printf ("\n"); X } X X exit (0); X} X X#endif /* TEST */ END-of-contrib/diff/lib/getopt.c echo x - contrib/diff/lib/getopt1.c sed 's/^X//' >contrib/diff/lib/getopt1.c << 'END-of-contrib/diff/lib/getopt1.c' X/* getopt_long and getopt_long_only entry points for GNU getopt. X Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98 X Free Software Foundation, Inc. X This file is part of the GNU C Library. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software Foundation, X Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#ifdef HAVE_CONFIG_H X#include X#endif X X#include "getopt.h" X X#if !defined __STDC__ || !__STDC__ X/* This is a separate conditional since some stdc systems X reject `defined (const)'. */ X#ifndef const X#define const X#endif X#endif X X#include X X/* Comment out all this code if we are using the GNU C Library, and are not X actually compiling the library itself. This code is part of the GNU C X Library, but also included in many other GNU distributions. Compiling X and linking in this code is a waste when using the GNU C library X (especially if it is a shared library). Rather than having every GNU X program understand `configure --with-gnu-libc' and omit the object files, X it is simpler to just do this in the source for each such file. */ X X#define GETOPT_INTERFACE_VERSION 2 X#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 X#include X#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION X#define ELIDE_CODE X#endif X#endif X X#ifndef ELIDE_CODE X X X/* This needs to come after some library #include X to get __GNU_LIBRARY__ defined. */ X#ifdef __GNU_LIBRARY__ X#include X#endif X X#ifndef NULL X#define NULL 0 X#endif X Xint Xgetopt_long (argc, argv, options, long_options, opt_index) X int argc; X char *const *argv; X const char *options; X const struct option *long_options; X int *opt_index; X{ X return _getopt_internal (argc, argv, options, long_options, opt_index, 0); X} X X/* Like getopt_long, but '-' as well as '--' can indicate a long option. X If an option that starts with '-' (not '--') doesn't match a long option, X but does match a short option, it is parsed as a short option X instead. */ X Xint Xgetopt_long_only (argc, argv, options, long_options, opt_index) X int argc; X char *const *argv; X const char *options; X const struct option *long_options; X int *opt_index; X{ X return _getopt_internal (argc, argv, options, long_options, opt_index, 1); X} X X X#endif /* Not ELIDE_CODE. */ X X#ifdef TEST X X#include X Xint Xmain (argc, argv) X int argc; X char **argv; X{ X int c; X int digit_optind = 0; X X while (1) X { X int this_option_optind = optind ? optind : 1; X int option_index = 0; X static struct option long_options[] = X { X {"add", 1, 0, 0}, X {"append", 0, 0, 0}, X {"delete", 1, 0, 0}, X {"verbose", 0, 0, 0}, X {"create", 0, 0, 0}, X {"file", 1, 0, 0}, X {0, 0, 0, 0} X }; X X c = getopt_long (argc, argv, "abc:d:0123456789", X long_options, &option_index); X if (c == -1) X break; X X switch (c) X { X case 0: X printf ("option %s", long_options[option_index].name); X if (optarg) X printf (" with arg %s", optarg); X printf ("\n"); X break; X X case '0': X case '1': X case '2': X case '3': X case '4': X case '5': X case '6': X case '7': X case '8': X case '9': X if (digit_optind != 0 && digit_optind != this_option_optind) X printf ("digits occur in two different argv-elements.\n"); X digit_optind = this_option_optind; X printf ("option %c\n", c); X break; X X case 'a': X printf ("option a\n"); X break; X X case 'b': X printf ("option b\n"); X break; X X case 'c': X printf ("option c with value `%s'\n", optarg); X break; X X case 'd': X printf ("option d with value `%s'\n", optarg); X break; X X case '?': X break; X X default: X printf ("?? getopt returned character code 0%o ??\n", c); X } X } X X if (optind < argc) X { X printf ("non-option ARGV-elements: "); X while (optind < argc) X printf ("%s ", argv[optind++]); X printf ("\n"); X } X X exit (0); X} X X#endif /* TEST */ END-of-contrib/diff/lib/getopt1.c echo x - contrib/diff/lib/hard-locale.c sed 's/^X//' >contrib/diff/lib/hard-locale.c << 'END-of-contrib/diff/lib/hard-locale.c' X/* hard-locale.c -- Determine whether a locale is hard. X X Copyright (C) 1997, 1998, 1999, 2002 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software Foundation, X Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#if HAVE_CONFIG_H X# include X#endif X X#if HAVE_LOCALE_H X# include X#endif X X#if HAVE_STDLIB_H X# include X#endif X X#if HAVE_STRING_H X# include X#endif X X#include "hard-locale.h" X X/* Return nonzero if the current CATEGORY locale is hard, i.e. if you X can't get away with assuming traditional C or POSIX behavior. */ Xint Xhard_locale (int category) X{ X#if ! HAVE_SETLOCALE X return 0; X#else X X int hard = 1; X char const *p = setlocale (category, 0); X X if (p) X { X# if defined __GLIBC__ && 2 <= __GLIBC__ X if (strcmp (p, "C") == 0 || strcmp (p, "POSIX") == 0) X hard = 0; X# else X char *locale = malloc (strlen (p) + 1); X if (locale) X { X strcpy (locale, p); X X /* Temporarily set the locale to the "C" and "POSIX" locales X to find their names, so that we can determine whether one X or the other is the caller's locale. */ X if (((p = setlocale (category, "C")) X && strcmp (p, locale) == 0) X || ((p = setlocale (category, "POSIX")) X && strcmp (p, locale) == 0)) X hard = 0; X X /* Restore the caller's locale. */ X setlocale (category, locale); X free (locale); X } X# endif X } X X return hard; X X#endif X} END-of-contrib/diff/lib/hard-locale.c echo x - contrib/diff/lib/imaxtostr.c sed 's/^X//' >contrib/diff/lib/imaxtostr.c << 'END-of-contrib/diff/lib/imaxtostr.c' X#define inttostr imaxtostr X#define inttype intmax_t X#include "inttostr.c" END-of-contrib/diff/lib/imaxtostr.c echo x - contrib/diff/lib/offtostr.c sed 's/^X//' >contrib/diff/lib/offtostr.c << 'END-of-contrib/diff/lib/offtostr.c' X#define inttostr offtostr X#define inttype off_t X#include "inttostr.c" END-of-contrib/diff/lib/offtostr.c echo x - contrib/diff/lib/prepargs.c sed 's/^X//' >contrib/diff/lib/prepargs.c << 'END-of-contrib/diff/lib/prepargs.c' X/* Parse arguments from a string and prepend them to an argv. X X Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software X Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA X 02111-1307, USA. */ X X/* Written by Paul Eggert . */ X X#ifdef HAVE_CONFIG_H X# include X#endif X#include "prepargs.h" X#include X#include X#include X X#include X X/* IN_CTYPE_DOMAIN (C) is nonzero if the unsigned char C can safely be given X as an argument to macros like "isspace". */ X#ifdef STDC_HEADERS X# define IN_CTYPE_DOMAIN(c) 1 X#else X# define IN_CTYPE_DOMAIN(c) ((c) <= 0177) X#endif X X#define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c)) X X/* Find the white-space-separated options specified by OPTIONS, and X using BUF to store copies of these options, set ARGV[0], ARGV[1], X etc. to the option copies. Return the number N of options found. X Do not set ARGV[N]. If ARGV is zero, do not store ARGV[0] etc. X Backslash can be used to escape whitespace (and backslashes). */ Xstatic int Xprepend_args (char const *options, char *buf, char **argv) X{ X char const *o = options; X char *b = buf; X int n = 0; X X for (;;) X { X while (ISSPACE ((unsigned char) *o)) X o++; X if (!*o) X return n; X if (argv) X argv[n] = b; X n++; X X do X if ((*b++ = *o++) == '\\' && *o) X b[-1] = *o++; X while (*o && ! ISSPACE ((unsigned char) *o)); X X *b++ = '\0'; X } X} X X/* Prepend the whitespace-separated options in OPTIONS to the argument X vector of a main program with argument count *PARGC and argument X vector *PARGV. */ Xvoid Xprepend_default_options (char const *options, int *pargc, char ***pargv) X{ X if (options) X { X char *buf = xmalloc (strlen (options) + 1); X int prepended = prepend_args (options, buf, (char **) 0); X int argc = *pargc; X char * const *argv = *pargv; X char **pp = (char **) xmalloc ((prepended + argc + 1) * sizeof *pp); X *pargc = prepended + argc; X *pargv = pp; X *pp++ = *argv++; X pp += prepend_args (options, buf, pp); X while ((*pp++ = *argv++)) X continue; X } X} END-of-contrib/diff/lib/prepargs.c echo x - contrib/diff/lib/posixver.c sed 's/^X//' >contrib/diff/lib/posixver.c << 'END-of-contrib/diff/lib/posixver.c' X/* Which POSIX version to conform to, for utilities. X X Copyright (C) 2002 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify it X under the terms of the GNU Library General Public License as published X by the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU X Library General Public License for more details. X X You should have received a copy of the GNU Library General Public X License along with this program; if not, write to the Free Software X Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, X USA. */ X X/* Written by Paul Eggert. */ X X#if HAVE_CONFIG_H X# include X#endif X X#include X X#include X#if !HAVE_DECL_GETENV && !defined getenv Xchar *getenv (); X#endif X X#if HAVE_UNISTD_H X# include X#endif X#ifndef _POSIX2_VERSION X# define _POSIX2_VERSION 0 X#endif X X/* The POSIX version that utilities should conform to. The default is X specified by the system. */ X Xint Xposix2_version (void) X{ X long int v = _POSIX2_VERSION; X char const *s = getenv ("_POSIX2_VERSION"); X X if (s && *s) X { X char *e; X long int i = strtol (s, &e, 10); X if (! *e) X v = i; X } X X return v < INT_MIN ? INT_MIN : v < INT_MAX ? v : INT_MAX; X} END-of-contrib/diff/lib/posixver.c echo x - contrib/diff/lib/quotesys.c sed 's/^X//' >contrib/diff/lib/quotesys.c << 'END-of-contrib/diff/lib/quotesys.c' X/* Shell command argument quoting. X Copyright (C) 1994, 1995, 1997 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; see the file COPYING. X If not, write to the Free Software Foundation, X 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X/* Written by Paul Eggert */ X X#if HAVE_CONFIG_H X# include X#endif X X#include X#include X X/* Place into QUOTED a quoted version of ARG suitable for `system'. X Return the length of the resulting string (which is not null-terminated). X If QUOTED is null, return the length without any side effects. */ X Xsize_t Xquote_system_arg (quoted, arg) X char *quoted; X char const *arg; X{ X char const *a; X size_t len = 0; X X /* Scan ARG, copying it to QUOTED if QUOTED is not null, X looking for shell metacharacters. */ X X for (a = arg; ; a++) X { X char c = *a; X switch (c) X { X case 0: X /* ARG has no shell metacharacters. */ X return len; X X case '=': X if (*arg == '-') X break; X /* Fall through. */ X case '\t': case '\n': case ' ': X case '!': case '"': case '#': case '$': case '%': case '&': case '\'': X case '(': case ')': case '*': case ';': X case '<': case '>': case '?': case '[': case '\\': X case '^': case '`': case '|': case '~': X { X /* ARG has a shell metacharacter. X Start over, quoting it this time. */ X X len = 0; X c = *arg++; X X /* If ARG is an option, quote just its argument. X This is not necessary, but it looks nicer. */ X if (c == '-' && arg < a) X { X c = *arg++; X X if (quoted) X { X quoted[len] = '-'; X quoted[len + 1] = c; X } X len += 2; X X if (c == '-') X while (arg < a) X { X c = *arg++; X if (quoted) X quoted[len] = c; X len++; X if (c == '=') X break; X } X c = *arg++; X } X X if (quoted) X quoted[len] = '\''; X len++; X X for (; c; c = *arg++) X { X if (c == '\'') X { X if (quoted) X { X quoted[len] = '\''; X quoted[len + 1] = '\\'; X quoted[len + 2] = '\''; X } X len += 3; X } X if (quoted) X quoted[len] = c; X len++; X } X X if (quoted) X quoted[len] = '\''; X return len + 1; X } X } X X if (quoted) X quoted[len] = c; X len++; X } X} END-of-contrib/diff/lib/quotesys.c echo x - contrib/diff/lib/setmode.c sed 's/^X//' >contrib/diff/lib/setmode.c << 'END-of-contrib/diff/lib/setmode.c' X/* Set a file descriptor's mode to binary or to text. X X Copyright (C) 2001 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; see the file COPYING. X If not, write to the Free Software Foundation, X 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X/* Written by Paul Eggert */ X X#if HAVE_CONFIG_H X# include X#endif X X#if HAVE_STDBOOL_H X# include X#else Xtypedef enum {false = 0, true = 1} bool; X#endif X X#if HAVE_SETMODE_DOS X# include X# if HAVE_FCNTL_H X# include X# endif X# if HAVE_UNISTD_H X# include X# endif X#endif X X#include "setmode.h" X#undef set_binary_mode X X X/* Set the binary mode of FD to MODE, returning its previous mode. X MODE is 1 for binary and 0 for text. If setting the mode might X cause problems, ignore the request and return MODE. Always return X 1 on POSIX platforms, which do not distinguish between text and X binary. */ X Xbool Xset_binary_mode (int fd, bool mode) X{ X#if HAVE_SETMODE_DOS X if (isatty (fd)) X return mode; X return setmode (fd, mode ? O_BINARY : O_TEXT) != O_TEXT; X#else X return 1; X#endif X} END-of-contrib/diff/lib/setmode.c echo x - contrib/diff/lib/strftime.c sed 's/^X//' >contrib/diff/lib/strftime.c << 'END-of-contrib/diff/lib/strftime.c' X/* Copyright (C) 1991-1999, 2000, 2001 Free Software Foundation, Inc. X X NOTE: The canonical source of this file is maintained with the GNU C Library. X Bugs can be reported to bug-glibc@prep.ai.mit.edu. X X This program is free software; you can redistribute it and/or modify it X under the terms of the GNU General Public License as published by the X Free Software Foundation; either version 2, or (at your option) any X later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU X Library General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software X Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, X USA. */ X X#ifdef HAVE_CONFIG_H X# include X#endif X X#ifdef _LIBC X# define HAVE_LIMITS_H 1 X# define HAVE_MBLEN 1 X# define HAVE_MBRLEN 1 X# define HAVE_STRUCT_ERA_ENTRY 1 X# define HAVE_TM_GMTOFF 1 X# define HAVE_TM_ZONE 1 X# define HAVE_TZNAME 1 X# define HAVE_TZSET 1 X# define MULTIBYTE_IS_FORMAT_SAFE 1 X# define STDC_HEADERS 1 X# include "../locale/localeinfo.h" X#endif X X#if defined emacs && !defined HAVE_BCOPY X# define HAVE_MEMCPY 1 X#endif X X#include X#include /* Some systems define `time_t' here. */ X X#ifdef TIME_WITH_SYS_TIME X# include X# include X#else X# ifdef HAVE_SYS_TIME_H X# include X# else X# include X# endif X#endif X#if HAVE_TZNAME Xextern char *tzname[]; X#endif X X/* Do multibyte processing if multibytes are supported, unless X multibyte sequences are safe in formats. Multibyte sequences are X safe if they cannot contain byte sequences that look like format X conversion specifications. The GNU C Library uses UTF8 multibyte X encoding, which is safe for formats, but strftime.c can be used X with other C libraries that use unsafe encodings. */ X#define DO_MULTIBYTE (HAVE_MBLEN && ! MULTIBYTE_IS_FORMAT_SAFE) X X#if DO_MULTIBYTE X# if HAVE_MBRLEN X# include X# else X /* Simulate mbrlen with mblen as best we can. */ X# define mbstate_t int X# define mbrlen(s, n, ps) mblen (s, n) X# define mbsinit(ps) (*(ps) == 0) X# endif X static const mbstate_t mbstate_zero; X#endif X X#if HAVE_LIMITS_H X# include X#endif X X#if STDC_HEADERS X# include X# include X# include X#else X# ifndef HAVE_MEMCPY X# define memcpy(d, s, n) bcopy ((s), (d), (n)) X# endif X#endif X X#ifdef COMPILE_WIDE X# include X# define CHAR_T wchar_t X# define UCHAR_T unsigned int X# define L_(Str) L##Str X# define NLW(Sym) _NL_W##Sym X X# define MEMCPY(d, s, n) __wmemcpy (d, s, n) X# define STRLEN(s) __wcslen (s) X X#else X# define CHAR_T char X# define UCHAR_T unsigned char X# define L_(Str) Str X# define NLW(Sym) Sym X X# if !defined STDC_HEADERS && !defined HAVE_MEMCPY X# define MEMCPY(d, s, n) bcopy ((s), (d), (n)) X# else X# define MEMCPY(d, s, n) memcpy ((d), (s), (n)) X# endif X# define STRLEN(s) strlen (s) X X# ifdef _LIBC X# define MEMPCPY(d, s, n) __mempcpy (d, s, n) X# else X# ifndef HAVE_MEMPCPY X# define MEMPCPY(d, s, n) ((void *) ((char *) memcpy (d, s, n) + (n))) X# endif X# endif X#endif X X#ifndef __P X# if defined __GNUC__ || (defined __STDC__ && __STDC__) X# define __P(args) args X# else X# define __P(args) () X# endif /* GCC. */ X#endif /* Not __P. */ X X#ifndef PTR X# ifdef __STDC__ X# define PTR void * X# else X# define PTR char * X# endif X#endif X X#ifndef CHAR_BIT X# define CHAR_BIT 8 X#endif X X#ifndef NULL X# define NULL 0 X#endif X X#define TYPE_SIGNED(t) ((t) -1 < 0) X X/* Bound on length of the string representing an integer value of type t. X Subtract one for the sign bit if t is signed; X 302 / 1000 is log10 (2) rounded up; X add one for integer division truncation; X add one more for a minus sign if t is signed. */ X#define INT_STRLEN_BOUND(t) \ X ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 + 1 + TYPE_SIGNED (t)) X X#define TM_YEAR_BASE 1900 X X#ifndef __isleap X/* Nonzero if YEAR is a leap year (every 4 years, X except every 100th isn't, and every 400th is). */ X# define __isleap(year) \ X ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) X#endif X X X#ifdef _LIBC X# define my_strftime_gmtime_r __gmtime_r X# define my_strftime_localtime_r __localtime_r X# define tzname __tzname X# define tzset __tzset X#else X X/* If we're a strftime substitute in a GNU program, then prefer gmtime X to gmtime_r, since many gmtime_r implementations are buggy. X Similarly for localtime_r. */ X X# if ! HAVE_TM_GMTOFF Xstatic struct tm *my_strftime_gmtime_r __P ((const time_t *, struct tm *)); Xstatic struct tm * Xmy_strftime_gmtime_r (t, tp) X const time_t *t; X struct tm *tp; X{ X struct tm *l = gmtime (t); X if (! l) X return 0; X *tp = *l; X return tp; X} X Xstatic struct tm *my_strftime_localtime_r __P ((const time_t *, struct tm *)); Xstatic struct tm * Xmy_strftime_localtime_r (t, tp) X const time_t *t; X struct tm *tp; X{ X struct tm *l = localtime (t); X if (! l) X return 0; X *tp = *l; X return tp; X} X# endif /* ! HAVE_TM_GMTOFF */ X#endif /* ! defined _LIBC */ X X X#if !defined memset && !defined HAVE_MEMSET && !defined _LIBC X/* Some systems lack the `memset' function and we don't want to X introduce additional dependencies. */ X/* The SGI compiler reportedly barfs on the trailing null X if we use a string constant as the initializer. 28 June 1997, rms. */ Xstatic const CHAR_T spaces[16] = /* " " */ X{ X L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '), X L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' ') X}; Xstatic const CHAR_T zeroes[16] = /* "0000000000000000" */ X{ X L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'), X L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0') X}; X X# define memset_space(P, Len) \ X do { \ X int _len = (Len); \ X \ X do \ X { \ X int _this = _len > 16 ? 16 : _len; \ X (P) = MEMPCPY ((P), spaces, _this * sizeof (CHAR_T)); \ X _len -= _this; \ X } \ X while (_len > 0); \ X } while (0) X X# define memset_zero(P, Len) \ X do { \ X int _len = (Len); \ X \ X do \ X { \ X int _this = _len > 16 ? 16 : _len; \ X (P) = MEMPCPY ((P), zeroes, _this * sizeof (CHAR_T)); \ X _len -= _this; \ X } \ X while (_len > 0); \ X } while (0) X#else X# ifdef COMPILE_WIDE X# define memset_space(P, Len) (wmemset ((P), L' ', (Len)), (P) += (Len)) X# define memset_zero(P, Len) (wmemset ((P), L'0', (Len)), (P) += (Len)) X# else X# define memset_space(P, Len) (memset ((P), ' ', (Len)), (P) += (Len)) X# define memset_zero(P, Len) (memset ((P), '0', (Len)), (P) += (Len)) X# endif X#endif X X#define add(n, f) \ X do \ X { \ X int _n = (n); \ X int _delta = width - _n; \ X int _incr = _n + (_delta > 0 ? _delta : 0); \ X if (i + _incr >= maxsize) \ X return 0; \ X if (p) \ X { \ X if (_delta > 0) \ X { \ X if (pad == L_('0')) \ X memset_zero (p, _delta); \ X else \ X memset_space (p, _delta); \ X } \ X f; \ X p += _n; \ X } \ X i += _incr; \ X } while (0) X X#define cpy(n, s) \ X add ((n), \ X if (to_lowcase) \ X memcpy_lowcase (p, (s), _n); \ X else if (to_uppcase) \ X memcpy_uppcase (p, (s), _n); \ X else \ X MEMCPY ((PTR) p, (const PTR) (s), _n)) X X#ifdef COMPILE_WIDE X# define widen(os, ws, l) \ X { \ X mbstate_t __st; \ X const char *__s = os; \ X memset (&__st, '\0', sizeof (__st)); \ X l = __mbsrtowcs (NULL, &__s, 0, &__st); \ X ws = alloca ((l + 1) * sizeof (wchar_t)); \ X (void) __mbsrtowcs (ws, &__s, l, &__st); \ X } X#endif X X X#ifdef COMPILE_WIDE X# define TOUPPER(Ch) towupper (Ch) X# define TOLOWER(Ch) towlower (Ch) X#else X# ifdef _LIBC X# define TOUPPER(Ch) toupper (Ch) X# define TOLOWER(Ch) tolower (Ch) X# else X# define TOUPPER(Ch) (islower (Ch) ? toupper (Ch) : (Ch)) X# define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch)) X# endif X#endif X/* We don't use `isdigit' here since the locale dependent X interpretation is not what we want here. We only need to accept X the arabic digits in the ASCII range. One day there is perhaps a X more reliable way to accept other sets of digits. */ X#define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9) X Xstatic CHAR_T *memcpy_lowcase __P ((CHAR_T *dest, const CHAR_T *src, X size_t len)); X Xstatic CHAR_T * Xmemcpy_lowcase (dest, src, len) X CHAR_T *dest; X const CHAR_T *src; X size_t len; X{ X while (len-- > 0) X dest[len] = TOLOWER ((UCHAR_T) src[len]); X return dest; X} X Xstatic CHAR_T *memcpy_uppcase __P ((CHAR_T *dest, const CHAR_T *src, X size_t len)); X Xstatic CHAR_T * Xmemcpy_uppcase (dest, src, len) X CHAR_T *dest; X const CHAR_T *src; X size_t len; X{ X while (len-- > 0) X dest[len] = TOUPPER ((UCHAR_T) src[len]); X return dest; X} X X X#if ! HAVE_TM_GMTOFF X/* Yield the difference between *A and *B, X measured in seconds, ignoring leap seconds. */ X# define tm_diff ftime_tm_diff Xstatic int tm_diff __P ((const struct tm *, const struct tm *)); Xstatic int Xtm_diff (a, b) X const struct tm *a; X const struct tm *b; X{ X /* Compute intervening leap days correctly even if year is negative. X Take care to avoid int overflow in leap day calculations, X but it's OK to assume that A and B are close to each other. */ X int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3); X int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3); X int a100 = a4 / 25 - (a4 % 25 < 0); X int b100 = b4 / 25 - (b4 % 25 < 0); X int a400 = a100 >> 2; X int b400 = b100 >> 2; X int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400); X int years = a->tm_year - b->tm_year; X int days = (365 * years + intervening_leap_days X + (a->tm_yday - b->tm_yday)); X return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour)) X + (a->tm_min - b->tm_min)) X + (a->tm_sec - b->tm_sec)); X} X#endif /* ! HAVE_TM_GMTOFF */ X X X X/* The number of days from the first day of the first ISO week of this X year to the year day YDAY with week day WDAY. ISO weeks start on X Monday; the first ISO week has the year's first Thursday. YDAY may X be as small as YDAY_MINIMUM. */ X#define ISO_WEEK_START_WDAY 1 /* Monday */ X#define ISO_WEEK1_WDAY 4 /* Thursday */ X#define YDAY_MINIMUM (-366) Xstatic int iso_week_days __P ((int, int)); X#ifdef __GNUC__ X__inline__ X#endif Xstatic int Xiso_week_days (yday, wday) X int yday; X int wday; X{ X /* Add enough to the first operand of % to make it nonnegative. */ X int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7; X return (yday X - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7 X + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY); X} X X X#if !(defined _NL_CURRENT || HAVE_STRFTIME) Xstatic CHAR_T const weekday_name[][10] = X { X L_("Sunday"), L_("Monday"), L_("Tuesday"), L_("Wednesday"), X L_("Thursday"), L_("Friday"), L_("Saturday") X }; Xstatic CHAR_T const month_name[][10] = X { X L_("January"), L_("February"), L_("March"), L_("April"), L_("May"), X L_("June"), L_("July"), L_("August"), L_("September"), L_("October"), X L_("November"), L_("December") X }; X#endif X X X/* When compiling this file, GNU applications can #define my_strftime X to a symbol (typically nstrftime) to get an extended strftime with X extra arguments UT and NS. Emacs is a special case for now, but X this Emacs-specific code can be removed once Emacs's config.h X defines my_strftime. */ X#if defined emacs && !defined my_strftime X# define my_strftime nstrftime X#endif X X#ifdef my_strftime X# define extra_args , ut, ns X# define extra_args_spec int ut; int ns; X# define extra_args_spec_iso , int ut, int ns X#else X# ifdef COMPILE_WIDE X# define my_strftime wcsftime X# else X# define my_strftime strftime X# endif X# define extra_args X# define extra_args_spec X# define extra_args_spec_iso X/* We don't have this information in general. */ X# define ut 0 X# define ns 0 X#endif X X#if !defined _LIBC && HAVE_TZNAME && HAVE_TZSET X /* Solaris 2.5 tzset sometimes modifies the storage returned by localtime. X Work around this bug by copying *tp before it might be munged. */ X size_t _strftime_copytm __P ((char *, size_t, const char *, X const struct tm * extra_args_spec_iso)); X size_t X my_strftime (s, maxsize, format, tp extra_args) X CHAR_T *s; X size_t maxsize; X const CHAR_T *format; X const struct tm *tp; X extra_args_spec X { X struct tm tmcopy; X tmcopy = *tp; X return _strftime_copytm (s, maxsize, format, &tmcopy extra_args); X } X# undef my_strftime X# define my_strftime _strftime_copytm X#endif X X X/* Write information from TP into S according to the format X string FORMAT, writing no more that MAXSIZE characters X (including the terminating '\0') and returning number of X characters written. If S is NULL, nothing will be written X anywhere, so to determine how many characters would be X written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */ Xsize_t Xmy_strftime (s, maxsize, format, tp extra_args) X CHAR_T *s; X size_t maxsize; X const CHAR_T *format; X const struct tm *tp; X extra_args_spec X{ X int hour12 = tp->tm_hour; X#ifdef _NL_CURRENT X /* We cannot make the following values variables since we must delay X the evaluation of these values until really needed since some X expressions might not be valid in every situation. The `struct tm' X might be generated by a strptime() call that initialized X only a few elements. Dereference the pointers only if the format X requires this. Then it is ok to fail if the pointers are invalid. */ X# define a_wkday \ X ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday)) X# define f_wkday \ X ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday)) X# define a_month \ X ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon)) X# define f_month \ X ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon)) X# define ampm \ X ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \ X ? NLW(PM_STR) : NLW(AM_STR))) X X# define aw_len STRLEN (a_wkday) X# define am_len STRLEN (a_month) X# define ap_len STRLEN (ampm) X#else X# if !HAVE_STRFTIME X# define f_wkday (weekday_name[tp->tm_wday]) X# define f_month (month_name[tp->tm_mon]) X# define a_wkday f_wkday X# define a_month f_month X# define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11)) X X size_t aw_len = 3; X size_t am_len = 3; X size_t ap_len = 2; X# endif X#endif X const char *zone; X size_t i = 0; X CHAR_T *p = s; X const CHAR_T *f; X#if DO_MULTIBYTE && !defined COMPILE_WIDE X const char *format_end = NULL; X#endif X X zone = NULL; X#if HAVE_TM_ZONE X /* The POSIX test suite assumes that setting X the environment variable TZ to a new value before calling strftime() X will influence the result (the %Z format) even if the information in X TP is computed with a totally different time zone. X This is bogus: though POSIX allows bad behavior like this, X POSIX does not require it. Do the right thing instead. */ X zone = (const char *) tp->tm_zone; X#endif X#if HAVE_TZNAME X if (ut) X { X if (! (zone && *zone)) X zone = "GMT"; X } X else X { X /* POSIX.1 8.1.1 requires that whenever strftime() is called, the X time zone names contained in the external variable `tzname' shall X be set as if the tzset() function had been called. */ X# if HAVE_TZSET X tzset (); X# endif X } X#endif X X if (hour12 > 12) X hour12 -= 12; X else X if (hour12 == 0) X hour12 = 12; X X for (f = format; *f != '\0'; ++f) X { X int pad = 0; /* Padding for number ('-', '_', or 0). */ X int modifier; /* Field modifier ('E', 'O', or 0). */ X int digits; /* Max digits for numeric format. */ X int number_value; /* Numeric value to be printed. */ X int negative_number; /* 1 if the number is negative. */ X const CHAR_T *subfmt; X CHAR_T *bufp; X CHAR_T buf[1 + (sizeof (int) < sizeof (time_t) X ? INT_STRLEN_BOUND (time_t) X : INT_STRLEN_BOUND (int))]; X int width = -1; X int to_lowcase = 0; X int to_uppcase = 0; X int change_case = 0; X int format_char; X X#if DO_MULTIBYTE && !defined COMPILE_WIDE X switch (*f) X { X case L_('%'): X break; X X case L_('\b'): case L_('\t'): case L_('\n'): X case L_('\v'): case L_('\f'): case L_('\r'): X case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'): X case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'): X case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'): X case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'): X case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'): X case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'): X case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'): X case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'): X case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'): X case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'): X case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'): X case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'): X case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'): X case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'): X case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'): X case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'): X case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'): X case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'): X case L_('~'): X /* The C Standard requires these 98 characters (plus '%') to X be in the basic execution character set. None of these X characters can start a multibyte sequence, so they need X not be analyzed further. */ X add (1, *p = *f); X continue; X X default: X /* Copy this multibyte sequence until we reach its end, find X an error, or come back to the initial shift state. */ X { X mbstate_t mbstate = mbstate_zero; X size_t len = 0; X size_t fsize; X X if (! format_end) X format_end = f + strlen (f) + 1; X fsize = format_end - f; X X do X { X size_t bytes = mbrlen (f + len, fsize - len, &mbstate); X X if (bytes == 0) X break; X X if (bytes == (size_t) -2) X { X len += strlen (f + len); X break; X } X X if (bytes == (size_t) -1) X { X len++; X break; X } X X len += bytes; X } X while (! mbsinit (&mbstate)); X X cpy (len, f); X f += len - 1; X continue; X } X } X X#else /* ! DO_MULTIBYTE */ X X /* Either multibyte encodings are not supported, they are X safe for formats, so any non-'%' byte can be copied through, X or this is the wide character version. */ X if (*f != L_('%')) X { X add (1, *p = *f); X continue; X } X X#endif /* ! DO_MULTIBYTE */ X X /* Check for flags that can modify a format. */ X while (1) X { X switch (*++f) X { X /* This influences the number formats. */ X case L_('_'): X case L_('-'): X case L_('0'): X pad = *f; X continue; X X /* This changes textual output. */ X case L_('^'): X to_uppcase = 1; X continue; X case L_('#'): X change_case = 1; X continue; X X default: X break; X } X break; X } X X /* As a GNU extension we allow to specify the field width. */ X if (ISDIGIT (*f)) X { X width = 0; X do X { X width *= 10; X width += *f - L_('0'); X ++f; X } X while (ISDIGIT (*f)); X } X X /* Check for modifiers. */ X switch (*f) X { X case L_('E'): X case L_('O'): X modifier = *f++; X break; X X default: X modifier = 0; X break; X } X X /* Now do the specified format. */ X format_char = *f; X switch (format_char) X { X#define DO_NUMBER(d, v) \ X digits = width == -1 ? d : width; \ X number_value = v; goto do_number X#define DO_NUMBER_SPACEPAD(d, v) \ X digits = width == -1 ? d : width; \ X number_value = v; goto do_number_spacepad X X case L_('%'): X if (modifier != 0) X goto bad_format; X add (1, *p = *f); X break; X X case L_('a'): X if (modifier != 0) X goto bad_format; X if (change_case) X { X to_uppcase = 1; X to_lowcase = 0; X } X#if defined _NL_CURRENT || !HAVE_STRFTIME X cpy (aw_len, a_wkday); X break; X#else X goto underlying_strftime; X#endif X X case 'A': X if (modifier != 0) X goto bad_format; X if (change_case) X { X to_uppcase = 1; X to_lowcase = 0; X } X#if defined _NL_CURRENT || !HAVE_STRFTIME X cpy (STRLEN (f_wkday), f_wkday); X break; X#else X goto underlying_strftime; X#endif X X case L_('b'): X case L_('h'): /* POSIX.2 extension. */ X if (change_case) X { X to_uppcase = 1; X to_lowcase = 0; X } X if (modifier != 0) X goto bad_format; X#if defined _NL_CURRENT || !HAVE_STRFTIME X cpy (am_len, a_month); X break; X#else X goto underlying_strftime; X#endif X X case L_('B'): X if (modifier != 0) X goto bad_format; X if (change_case) X { X to_uppcase = 1; X to_lowcase = 0; X } X#if defined _NL_CURRENT || !HAVE_STRFTIME X cpy (STRLEN (f_month), f_month); X break; X#else X goto underlying_strftime; X#endif X X case L_('c'): X if (modifier == L_('O')) X goto bad_format; X#ifdef _NL_CURRENT X if (! (modifier == 'E' X && (*(subfmt = X (const CHAR_T *) _NL_CURRENT (LC_TIME, X NLW(ERA_D_T_FMT))) X != '\0'))) X subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT)); X#else X# if HAVE_STRFTIME X goto underlying_strftime; X# else X subfmt = L_("%a %b %e %H:%M:%S %Y"); X# endif X#endif X X subformat: X { X CHAR_T *old_start = p; X size_t len = my_strftime (NULL, (size_t) -1, subfmt, X tp extra_args); X add (len, my_strftime (p, maxsize - i, subfmt, X tp extra_args)); X X if (to_uppcase) X while (old_start < p) X { X *old_start = TOUPPER ((UCHAR_T) *old_start); X ++old_start; X } X } X break; X X#if HAVE_STRFTIME && ! (defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY) X underlying_strftime: X { X /* The relevant information is available only via the X underlying strftime implementation, so use that. */ X char ufmt[4]; X char *u = ufmt; X char ubuf[1024]; /* enough for any single format in practice */ X size_t len; X /* Make sure we're calling the actual underlying strftime. X In some cases, config.h contains something like X "#define strftime rpl_strftime". */ X# ifdef strftime X# undef strftime X size_t strftime (); X# endif X X *u++ = '%'; X if (modifier != 0) X *u++ = modifier; X *u++ = format_char; X *u = '\0'; X len = strftime (ubuf, sizeof ubuf, ufmt, tp); X if (len == 0 && ubuf[0] != '\0') X return 0; X cpy (len, ubuf); X } X break; X#endif X X case L_('C'): /* POSIX.2 extension. */ X if (modifier == L_('O')) X goto bad_format; X if (modifier == L_('E')) X { X#if HAVE_STRUCT_ERA_ENTRY X struct era_entry *era = _nl_get_era_entry (tp); X if (era) X { X# ifdef COMPILE_WIDE X size_t len = __wcslen (era->era_wname); X cpy (len, era->era_wname); X# else X size_t len = strlen (era->era_name); X cpy (len, era->era_name); X# endif X break; X } X#else X# if HAVE_STRFTIME X goto underlying_strftime; X# endif X#endif X } X X { X int year = tp->tm_year + TM_YEAR_BASE; X DO_NUMBER (1, year / 100 - (year % 100 < 0)); X } X X case L_('x'): X if (modifier == L_('O')) X goto bad_format; X#ifdef _NL_CURRENT X if (! (modifier == L_('E') X && (*(subfmt = X (const CHAR_T *)_NL_CURRENT (LC_TIME, NLW(ERA_D_FMT))) X != L_('\0')))) X subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT)); X goto subformat; X#else X# if HAVE_STRFTIME X goto underlying_strftime; X# else X /* Fall through. */ X# endif X#endif X case L_('D'): /* POSIX.2 extension. */ X if (modifier != 0) X goto bad_format; X subfmt = L_("%m/%d/%y"); X goto subformat; X X case L_('d'): X if (modifier == L_('E')) X goto bad_format; X X DO_NUMBER (2, tp->tm_mday); X X case L_('e'): /* POSIX.2 extension. */ X if (modifier == L_('E')) X goto bad_format; X X DO_NUMBER_SPACEPAD (2, tp->tm_mday); X X /* All numeric formats set DIGITS and NUMBER_VALUE and then X jump to one of these two labels. */ X X do_number_spacepad: X /* Force `_' flag unless overwritten by `0' flag. */ X if (pad != L_('0')) X pad = L_('_'); X X do_number: X /* Format the number according to the MODIFIER flag. */ X X if (modifier == L_('O') && 0 <= number_value) X { X#ifdef _NL_CURRENT X /* Get the locale specific alternate representation of X the number NUMBER_VALUE. If none exist NULL is returned. */ X# ifdef COMPILE_WIDE X const wchar_t *cp = _nl_get_walt_digit (number_value); X# else X const char *cp = _nl_get_alt_digit (number_value); X# endif X X if (cp != NULL) X { X size_t digitlen = STRLEN (cp); X if (digitlen != 0) X { X cpy (digitlen, cp); X break; X } X } X#else X# if HAVE_STRFTIME X goto underlying_strftime; X# endif X#endif X } X { X unsigned int u = number_value; X X bufp = buf + sizeof (buf) / sizeof (buf[0]); X negative_number = number_value < 0; X X if (negative_number) X u = -u; X X do X *--bufp = u % 10 + L_('0'); X while ((u /= 10) != 0); X } X X do_number_sign_and_padding: X if (negative_number) X *--bufp = L_('-'); X X if (pad != L_('-')) X { X int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0])) X - bufp); X X if (pad == L_('_')) X { X while (0 < padding--) X *--bufp = L_(' '); X } X else X { X bufp += negative_number; X while (0 < padding--) X *--bufp = L_('0'); X if (negative_number) X *--bufp = L_('-'); X } X } X X cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp); X break; X X case L_('F'): X if (modifier != 0) X goto bad_format; X subfmt = L_("%Y-%m-%d"); X goto subformat; X X case L_('H'): X if (modifier == L_('E')) X goto bad_format; X X DO_NUMBER (2, tp->tm_hour); X X case L_('I'): X if (modifier == L_('E')) X goto bad_format; X X DO_NUMBER (2, hour12); X X case L_('k'): /* GNU extension. */ X if (modifier == L_('E')) X goto bad_format; X X DO_NUMBER_SPACEPAD (2, tp->tm_hour); X X case L_('l'): /* GNU extension. */ X if (modifier == L_('E')) X goto bad_format; X X DO_NUMBER_SPACEPAD (2, hour12); X X case L_('j'): X if (modifier == L_('E')) X goto bad_format; X X DO_NUMBER (3, 1 + tp->tm_yday); X X case L_('M'): X if (modifier == L_('E')) X goto bad_format; X X DO_NUMBER (2, tp->tm_min); X X case L_('m'): X if (modifier == L_('E')) X goto bad_format; X X DO_NUMBER (2, tp->tm_mon + 1); X X case L_('N'): /* GNU extension. */ X if (modifier == L_('E')) X goto bad_format; X X number_value = ns; X if (width != -1) X { X /* Take an explicit width less than 9 as a precision. */ X int j; X for (j = width; j < 9; j++) X number_value /= 10; X } X X DO_NUMBER (9, number_value); X X case L_('n'): /* POSIX.2 extension. */ X add (1, *p = L_('\n')); X break; X X case L_('P'): X to_lowcase = 1; X#if !defined _NL_CURRENT && HAVE_STRFTIME X format_char = L_('p'); X#endif X /* FALLTHROUGH */ X X case L_('p'): X if (change_case) X { X to_uppcase = 0; X to_lowcase = 1; X } X#if defined _NL_CURRENT || !HAVE_STRFTIME X cpy (ap_len, ampm); X break; X#else X goto underlying_strftime; X#endif X X case L_('R'): /* ISO C99 extension. */ X subfmt = L_("%H:%M"); X goto subformat; X X case L_('r'): /* POSIX.2 extension. */ X#ifdef _NL_CURRENT X if (*(subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, X NLW(T_FMT_AMPM))) X == L_('\0')) X#endif X subfmt = L_("%I:%M:%S %p"); X goto subformat; X X case L_('S'): X if (modifier == L_('E')) X goto bad_format; X X DO_NUMBER (2, tp->tm_sec); X X case L_('s'): /* GNU extension. */ X { X struct tm ltm; X time_t t; X X ltm = *tp; X t = mktime (<m); X X /* Generate string value for T using time_t arithmetic; X this works even if sizeof (long) < sizeof (time_t). */ X X bufp = buf + sizeof (buf) / sizeof (buf[0]); X negative_number = t < 0; X X do X { X int d = t % 10; X t /= 10; X X if (negative_number) X { X d = -d; X X /* Adjust if division truncates to minus infinity. */ X if (0 < -1 % 10 && d < 0) X { X t++; X d += 10; X } X } X X *--bufp = d + L_('0'); X } X while (t != 0); X X digits = 1; X goto do_number_sign_and_padding; X } X X case L_('X'): X if (modifier == L_('O')) X goto bad_format; X#ifdef _NL_CURRENT X if (! (modifier == L_('E') X && (*(subfmt = X (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_T_FMT))) X != L_('\0')))) X subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT)); X goto subformat; X#else X# if HAVE_STRFTIME X goto underlying_strftime; X# else X /* Fall through. */ X# endif X#endif X case L_('T'): /* POSIX.2 extension. */ X subfmt = L_("%H:%M:%S"); X goto subformat; X X case L_('t'): /* POSIX.2 extension. */ X add (1, *p = L_('\t')); X break; X X case L_('u'): /* POSIX.2 extension. */ X DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1); X X case L_('U'): X if (modifier == L_('E')) X goto bad_format; X X DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7); X X case L_('V'): X case L_('g'): /* ISO C99 extension. */ X case L_('G'): /* ISO C99 extension. */ X if (modifier == L_('E')) X goto bad_format; X { X int year = tp->tm_year + TM_YEAR_BASE; X int days = iso_week_days (tp->tm_yday, tp->tm_wday); X X if (days < 0) X { X /* This ISO week belongs to the previous year. */ X year--; X days = iso_week_days (tp->tm_yday + (365 + __isleap (year)), X tp->tm_wday); X } X else X { X int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)), X tp->tm_wday); X if (0 <= d) X { X /* This ISO week belongs to the next year. */ X year++; X days = d; X } X } X X switch (*f) X { X case L_('g'): X DO_NUMBER (2, (year % 100 + 100) % 100); X X case L_('G'): X DO_NUMBER (1, year); X X default: X DO_NUMBER (2, days / 7 + 1); X } X } X X case L_('W'): X if (modifier == L_('E')) X goto bad_format; X X DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7); X X case L_('w'): X if (modifier == L_('E')) X goto bad_format; X X DO_NUMBER (1, tp->tm_wday); X X case L_('Y'): X if (modifier == 'E') X { X#if HAVE_STRUCT_ERA_ENTRY X struct era_entry *era = _nl_get_era_entry (tp); X if (era) X { X# ifdef COMPILE_WIDE X subfmt = era->era_wformat; X# else X subfmt = era->era_format; X# endif X goto subformat; X } X#else X# if HAVE_STRFTIME X goto underlying_strftime; X# endif X#endif X } X if (modifier == L_('O')) X goto bad_format; X else X DO_NUMBER (1, tp->tm_year + TM_YEAR_BASE); X X case L_('y'): X if (modifier == L_('E')) X { X#if HAVE_STRUCT_ERA_ENTRY X struct era_entry *era = _nl_get_era_entry (tp); X if (era) X { X int delta = tp->tm_year - era->start_date[0]; X DO_NUMBER (1, (era->offset X + delta * era->absolute_direction)); X } X#else X# if HAVE_STRFTIME X goto underlying_strftime; X# endif X#endif X } X DO_NUMBER (2, (tp->tm_year % 100 + 100) % 100); X X case L_('Z'): X if (change_case) X { X to_uppcase = 0; X to_lowcase = 1; X } X X#if HAVE_TZNAME X /* The tzset() call might have changed the value. */ X if (!(zone && *zone) && tp->tm_isdst >= 0) X zone = tzname[tp->tm_isdst]; X#endif X if (! zone) X zone = ""; /* POSIX.2 requires the empty string here. */ X X#ifdef COMPILE_WIDE X { X /* The zone string is always given in multibyte form. We have X to transform it first. */ X wchar_t *wczone; X size_t len; X widen (zone, wczone, len); X cpy (len, wczone); X } X#else X cpy (strlen (zone), zone); X#endif X break; X X case L_('z'): /* ISO C99 extension. */ X if (tp->tm_isdst < 0) X break; X X { X int diff; X#if HAVE_TM_GMTOFF X diff = tp->tm_gmtoff; X#else X if (ut) X diff = 0; X else X { X struct tm gtm; X struct tm ltm; X time_t lt; X X ltm = *tp; X lt = mktime (<m); X X if (lt == (time_t) -1) X { X /* mktime returns -1 for errors, but -1 is also a X valid time_t value. Check whether an error really X occurred. */ X struct tm tm; X X if (! my_strftime_localtime_r (<, &tm) X || ((ltm.tm_sec ^ tm.tm_sec) X | (ltm.tm_min ^ tm.tm_min) X | (ltm.tm_hour ^ tm.tm_hour) X | (ltm.tm_mday ^ tm.tm_mday) X | (ltm.tm_mon ^ tm.tm_mon) X | (ltm.tm_year ^ tm.tm_year))) X break; X } X X if (! my_strftime_gmtime_r (<, >m)) X break; X X diff = tm_diff (<m, >m); X } X#endif X X if (diff < 0) X { X add (1, *p = L_('-')); X diff = -diff; X } X else X add (1, *p = L_('+')); X X diff /= 60; X DO_NUMBER (4, (diff / 60) * 100 + diff % 60); X } X X case L_('\0'): /* GNU extension: % at end of format. */ X --f; X /* Fall through. */ X default: X /* Unknown format; output the format, including the '%', X since this is most likely the right thing to do if a X multibyte string has been misparsed. */ X bad_format: X { X int flen; X for (flen = 1; f[1 - flen] != L_('%'); flen++) X continue; X cpy (flen, &f[1 - flen]); X } X break; X } X } X X if (p && maxsize != 0) X *p = L_('\0'); X return i; X} X X X#ifdef emacs X/* For Emacs we have a separate interface which corresponds to the normal X strftime function plus the ut argument, but without the ns argument. */ Xsize_t Xemacs_strftimeu (s, maxsize, format, tp, ut) X char *s; X size_t maxsize; X const char *format; X const struct tm *tp; X int ut; X{ X return my_strftime (s, maxsize, format, tp, ut, 0); X} X#endif END-of-contrib/diff/lib/strftime.c echo x - contrib/diff/lib/umaxtostr.c sed 's/^X//' >contrib/diff/lib/umaxtostr.c << 'END-of-contrib/diff/lib/umaxtostr.c' X#define inttostr umaxtostr X#define inttype uintmax_t X#include "inttostr.c" END-of-contrib/diff/lib/umaxtostr.c echo x - contrib/diff/lib/xmalloc.c sed 's/^X//' >contrib/diff/lib/xmalloc.c << 'END-of-contrib/diff/lib/xmalloc.c' X/* xmalloc.c -- malloc with out of memory checking X Copyright (C) 1990-1999, 2000, 2002 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software Foundation, X Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#if HAVE_CONFIG_H X# include X#endif X X#include X X#if STDC_HEADERS X# include X#else Xvoid *calloc (); Xvoid *malloc (); Xvoid *realloc (); Xvoid free (); X#endif X X#if ENABLE_NLS X# include X# define _(Text) gettext (Text) X#else X# define textdomain(Domain) X# define _(Text) Text X#endif X#define N_(Text) Text X X#include "error.h" X#include "exitfail.h" X#include "xalloc.h" X X#ifndef EXIT_FAILURE X# define EXIT_FAILURE 1 X#endif X X#ifndef HAVE_DONE_WORKING_MALLOC_CHECK X"you must run the autoconf test for a properly working malloc -- see malloc.m4" X#endif X X#ifndef HAVE_DONE_WORKING_REALLOC_CHECK X"you must run the autoconf test for a properly working realloc --see realloc.m4" X#endif X X/* If non NULL, call this function when memory is exhausted. */ Xvoid (*xalloc_fail_func) PARAMS ((void)) = 0; X X/* If XALLOC_FAIL_FUNC is NULL, or does return, display this message X before exiting when memory is exhausted. Goes through gettext. */ Xchar const xalloc_msg_memory_exhausted[] = N_("memory exhausted"); X Xvoid Xxalloc_die (void) X{ X if (xalloc_fail_func) X (*xalloc_fail_func) (); X error (exit_failure, 0, "%s", _(xalloc_msg_memory_exhausted)); X /* The `noreturn' cannot be given to error, since it may return if X its first argument is 0. To help compilers understand the X xalloc_die does terminate, call exit. */ X exit (EXIT_FAILURE); X} X X/* Allocate N bytes of memory dynamically, with error checking. */ X Xvoid * Xxmalloc (size_t n) X{ X void *p; X X p = malloc (n); X if (p == 0) X xalloc_die (); X return p; X} X X/* Change the size of an allocated block of memory P to N bytes, X with error checking. */ X Xvoid * Xxrealloc (void *p, size_t n) X{ X p = realloc (p, n); X if (p == 0) X xalloc_die (); X return p; X} X X/* Allocate memory for N elements of S bytes, with error checking. */ X Xvoid * Xxcalloc (size_t n, size_t s) X{ X void *p; X X p = calloc (n, s); X if (p == 0) X xalloc_die (); X return p; X} END-of-contrib/diff/lib/xmalloc.c echo x - contrib/diff/lib/xstrtoumax.c sed 's/^X//' >contrib/diff/lib/xstrtoumax.c << 'END-of-contrib/diff/lib/xstrtoumax.c' X/* xstrtoumax.c -- A more useful interface to strtoumax. X Copyright 1999 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software Foundation, X Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X/* Written by Paul Eggert. */ X X#if HAVE_CONFIG_H X# include X#endif X X#if HAVE_INTTYPES_H X# include X#endif X X#define __strtol strtoumax X#define __strtol_t uintmax_t X#define __xstrtol xstrtoumax X#include "xstrtol.c" END-of-contrib/diff/lib/xstrtoumax.c echo x - contrib/diff/lib/inttostr.c sed 's/^X//' >contrib/diff/lib/inttostr.c << 'END-of-contrib/diff/lib/inttostr.c' X/* inttostr.c -- convert integers to printable strings X X Copyright (C) 2001 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software Foundation, X Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X/* Written by Paul Eggert */ X X#include "inttostr.h" X X/* Convert I to a printable string in BUF, which must be at least X INT_BUFSIZE_BOUND (INTTYPE) bytes long. Return the address of the X printable string, which need not start at BUF. */ X Xchar * Xinttostr (inttype i, char *buf) X{ X char *p = buf + INT_STRLEN_BOUND (inttype); X *p = 0; X X if (i < 0) X { X do X *--p = '0' - i % 10; X while ((i /= 10) != 0); X X *--p = '-'; X } X else X { X do X *--p = '0' + i % 10; X while ((i /= 10) != 0); X } X X return p; X} END-of-contrib/diff/lib/inttostr.c echo x - contrib/diff/lib/strtoimax.c sed 's/^X//' >contrib/diff/lib/strtoimax.c << 'END-of-contrib/diff/lib/strtoimax.c' X/* Convert string representation of a number into an intmax_t value. X X Copyright (C) 1999, 2001 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software Foundation, X Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X/* Written by Paul Eggert. */ X X#if HAVE_CONFIG_H X# include X#endif X X#if HAVE_INTTYPES_H X# include X#endif X X#if HAVE_STDLIB_H X# include X#endif X X#ifndef PARAMS X# if defined PROTOTYPES || defined __STDC__ X# define PARAMS(Args) Args X# else X# define PARAMS(Args) () X# endif X#endif X X/* Verify a requirement at compile-time (unlike assert, which is runtime). */ X#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; } X X#ifdef UNSIGNED X# ifndef HAVE_DECL_STRTOUL X"this configure-time declaration test was not run" X# endif X# if !HAVE_DECL_STRTOUL Xunsigned long strtoul PARAMS ((char const *, char **, int)); X# endif X# ifndef HAVE_DECL_STRTOULL X"this configure-time declaration test was not run" X# endif X# if !HAVE_DECL_STRTOULL && HAVE_UNSIGNED_LONG_LONG Xunsigned long long strtoull PARAMS ((char const *, char **, int)); X# endif X X#else X X# ifndef HAVE_DECL_STRTOL X"this configure-time declaration test was not run" X# endif X# if !HAVE_DECL_STRTOL Xlong strtol PARAMS ((char const *, char **, int)); X# endif X# ifndef HAVE_DECL_STRTOLL X"this configure-time declaration test was not run" X# endif X# if !HAVE_DECL_STRTOLL && HAVE_UNSIGNED_LONG_LONG Xlong long strtoll PARAMS ((char const *, char **, int)); X# endif X#endif X X#ifdef UNSIGNED X# undef HAVE_LONG_LONG X# define HAVE_LONG_LONG HAVE_UNSIGNED_LONG_LONG X# define INT uintmax_t X# define strtoimax strtoumax X# define strtol strtoul X# define strtoll strtoull X#else X# define INT intmax_t X#endif X XINT Xstrtoimax (char const *ptr, char **endptr, int base) X{ X#if HAVE_LONG_LONG X verify (size_is_that_of_long_or_long_long, X (sizeof (INT) == sizeof (long) X || sizeof (INT) == sizeof (long long))); X X if (sizeof (INT) != sizeof (long)) X return strtoll (ptr, endptr, base); X#else X verify (size_is_that_of_long, X sizeof (INT) == sizeof (long)); X#endif X X return strtol (ptr, endptr, base); X} END-of-contrib/diff/lib/strtoimax.c echo x - contrib/diff/lib/strtol.c sed 's/^X//' >contrib/diff/lib/strtol.c << 'END-of-contrib/diff/lib/strtol.c' X/* Convert string representation of a number into an integer value. X Copyright (C) 1991, 92, 94, 95, 96, 97, 98, 99 Free Software Foundation, Inc. X NOTE: The canonical source of this file is maintained with the GNU C X Library. Bugs can be reported to bug-glibc@gnu.org. X X This program is free software; you can redistribute it and/or modify it X under the terms of the GNU General Public License as published by the X Free Software Foundation; either version 2, or (at your option) any X later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software Foundation, X Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#if HAVE_CONFIG_H X# include X#endif X X#ifdef _LIBC X# define USE_NUMBER_GROUPING X# define STDC_HEADERS X# define HAVE_LIMITS_H X#endif X X#include X#include X#ifndef errno Xextern int errno; X#endif X#ifndef __set_errno X# define __set_errno(Val) errno = (Val) X#endif X X#ifdef HAVE_LIMITS_H X# include X#endif X X#ifdef STDC_HEADERS X# include X# include X# include X#else X# ifndef NULL X# define NULL 0 X# endif X#endif X X#ifdef USE_NUMBER_GROUPING X# include "../locale/localeinfo.h" X#endif X X/* Nonzero if we are defining `strtoul' or `strtoull', operating on X unsigned integers. */ X#ifndef UNSIGNED X# define UNSIGNED 0 X# define INT LONG int X#else X# define INT unsigned LONG int X#endif X X/* Determine the name. */ X#ifdef USE_IN_EXTENDED_LOCALE_MODEL X# if UNSIGNED X# ifdef USE_WIDE_CHAR X# ifdef QUAD X# define strtol __wcstoull_l X# else X# define strtol __wcstoul_l X# endif X# else X# ifdef QUAD X# define strtol __strtoull_l X# else X# define strtol __strtoul_l X# endif X# endif X# else X# ifdef USE_WIDE_CHAR X# ifdef QUAD X# define strtol __wcstoll_l X# else X# define strtol __wcstol_l X# endif X# else X# ifdef QUAD X# define strtol __strtoll_l X# else X# define strtol __strtol_l X# endif X# endif X# endif X#else X# if UNSIGNED X# ifdef USE_WIDE_CHAR X# ifdef QUAD X# define strtol wcstoull X# else X# define strtol wcstoul X# endif X# else X# ifdef QUAD X# define strtol strtoull X# else X# define strtol strtoul X# endif X# endif X# else X# ifdef USE_WIDE_CHAR X# ifdef QUAD X# define strtol wcstoll X# else X# define strtol wcstol X# endif X# else X# ifdef QUAD X# define strtol strtoll X# endif X# endif X# endif X#endif X X/* If QUAD is defined, we are defining `strtoll' or `strtoull', X operating on `long long int's. */ X#ifdef QUAD X# define LONG long long X# define STRTOL_LONG_MIN LONG_LONG_MIN X# define STRTOL_LONG_MAX LONG_LONG_MAX X# define STRTOL_ULONG_MAX ULONG_LONG_MAX X X/* The extra casts work around common compiler bugs, X e.g. Cray C 5.0.3.0 when t == time_t. */ X# ifndef TYPE_SIGNED X# define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) X# endif X# ifndef TYPE_MINIMUM X# define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \ X ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) \ X : (t) 0)) X# endif X# ifndef TYPE_MAXIMUM X# define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t))) X# endif X X# ifndef ULONG_LONG_MAX X# define ULONG_LONG_MAX TYPE_MAXIMUM (unsigned long long) X# endif X# ifndef LONG_LONG_MAX X# define LONG_LONG_MAX TYPE_MAXIMUM (long long int) X# endif X# ifndef LONG_LONG_MIN X# define LONG_LONG_MIN TYPE_MINIMUM (long long int) X# endif X X# if __GNUC__ == 2 && __GNUC_MINOR__ < 7 X /* Work around gcc bug with using this constant. */ X static const unsigned long long int maxquad = ULONG_LONG_MAX; X# undef STRTOL_ULONG_MAX X# define STRTOL_ULONG_MAX maxquad X# endif X#else X# define LONG long X X# ifndef ULONG_MAX X# define ULONG_MAX ((unsigned long) ~(unsigned long) 0) X# endif X# ifndef LONG_MAX X# define LONG_MAX ((long int) (ULONG_MAX >> 1)) X# endif X# define STRTOL_LONG_MIN LONG_MIN X# define STRTOL_LONG_MAX LONG_MAX X# define STRTOL_ULONG_MAX ULONG_MAX X#endif X X X/* We use this code also for the extended locale handling where the X function gets as an additional argument the locale which has to be X used. To access the values we have to redefine the _NL_CURRENT X macro. */ X#ifdef USE_IN_EXTENDED_LOCALE_MODEL X# undef _NL_CURRENT X# define _NL_CURRENT(category, item) \ X (current->values[_NL_ITEM_INDEX (item)].string) X# define LOCALE_PARAM , loc X# define LOCALE_PARAM_DECL __locale_t loc; X#else X# define LOCALE_PARAM X# define LOCALE_PARAM_DECL X#endif X X#if defined _LIBC || defined HAVE_WCHAR_H X# include X#endif X X#ifdef USE_WIDE_CHAR X# include X# define L_(Ch) L##Ch X# define UCHAR_TYPE wint_t X# define STRING_TYPE wchar_t X# ifdef USE_IN_EXTENDED_LOCALE_MODEL X# define ISSPACE(Ch) __iswspace_l ((Ch), loc) X# define ISALPHA(Ch) __iswalpha_l ((Ch), loc) X# define TOUPPER(Ch) __towupper_l ((Ch), loc) X# else X# define ISSPACE(Ch) iswspace (Ch) X# define ISALPHA(Ch) iswalpha (Ch) X# define TOUPPER(Ch) towupper (Ch) X# endif X#else X# if defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII) X# define IN_CTYPE_DOMAIN(c) 1 X# else X# define IN_CTYPE_DOMAIN(c) isascii(c) X# endif X# define L_(Ch) Ch X# define UCHAR_TYPE unsigned char X# define STRING_TYPE char X# ifdef USE_IN_EXTENDED_LOCALE_MODEL X# define ISSPACE(Ch) __isspace_l ((Ch), loc) X# define ISALPHA(Ch) __isalpha_l ((Ch), loc) X# define TOUPPER(Ch) __toupper_l ((Ch), loc) X# else X# define ISSPACE(Ch) (IN_CTYPE_DOMAIN (Ch) && isspace (Ch)) X# define ISALPHA(Ch) (IN_CTYPE_DOMAIN (Ch) && isalpha (Ch)) X# define TOUPPER(Ch) (IN_CTYPE_DOMAIN (Ch) ? toupper (Ch) : (Ch)) X# endif X#endif X X/* For compilers which are ansi but don't define __STDC__, like SGI X Irix-4.0.5 cc, also check whether PROTOTYPES is defined. */ X#if defined (__STDC__) || defined (PROTOTYPES) X# define INTERNAL(X) INTERNAL1(X) X# define INTERNAL1(X) __##X##_internal X# define WEAKNAME(X) WEAKNAME1(X) X#else X# define INTERNAL(X) __/**/X/**/_internal X#endif X X#ifdef USE_NUMBER_GROUPING X/* This file defines a function to check for correct grouping. */ X# include "grouping.h" X#endif X X X X/* Convert NPTR to an `unsigned long int' or `long int' in base BASE. X If BASE is 0 the base is determined by the presence of a leading X zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal. X If BASE is < 2 or > 36, it is reset to 10. X If ENDPTR is not NULL, a pointer to the character after the last X one converted is stored in *ENDPTR. */ X XINT XINTERNAL (strtol) (nptr, endptr, base, group LOCALE_PARAM) X const STRING_TYPE *nptr; X STRING_TYPE **endptr; X int base; X int group; X LOCALE_PARAM_DECL X{ X int negative; X register unsigned LONG int cutoff; X register unsigned int cutlim; X register unsigned LONG int i; X register const STRING_TYPE *s; X register UCHAR_TYPE c; X const STRING_TYPE *save, *end; X int overflow; X X#ifdef USE_NUMBER_GROUPING X# ifdef USE_IN_EXTENDED_LOCALE_MODEL X struct locale_data *current = loc->__locales[LC_NUMERIC]; X# endif X /* The thousands character of the current locale. */ X wchar_t thousands = L'\0'; X /* The numeric grouping specification of the current locale, X in the format described in . */ X const char *grouping; X X if (group) X { X grouping = _NL_CURRENT (LC_NUMERIC, GROUPING); X if (*grouping <= 0 || *grouping == CHAR_MAX) X grouping = NULL; X else X { X /* Figure out the thousands separator character. */ X# if defined _LIBC || defined _HAVE_BTOWC X thousands = __btowc (*_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP)); X if (thousands == WEOF) X thousands = L'\0'; X# endif X if (thousands == L'\0') X grouping = NULL; X } X } X else X grouping = NULL; X#endif X X if (base < 0 || base == 1 || base > 36) X { X __set_errno (EINVAL); X return 0; X } X X save = s = nptr; X X /* Skip white space. */ X while (ISSPACE (*s)) X ++s; X if (*s == L_('\0')) X goto noconv; X X /* Check for a sign. */ X if (*s == L_('-')) X { X negative = 1; X ++s; X } X else if (*s == L_('+')) X { X negative = 0; X ++s; X } X else X negative = 0; X X /* Recognize number prefix and if BASE is zero, figure it out ourselves. */ X if (*s == L_('0')) X { X if ((base == 0 || base == 16) && TOUPPER (s[1]) == L_('X')) X { X s += 2; X base = 16; X } X else if (base == 0) X base = 8; X } X else if (base == 0) X base = 10; X X /* Save the pointer so we can check later if anything happened. */ X save = s; X X#ifdef USE_NUMBER_GROUPING X if (group) X { X /* Find the end of the digit string and check its grouping. */ X end = s; X for (c = *end; c != L_('\0'); c = *++end) X if ((wchar_t) c != thousands X && ((wchar_t) c < L_('0') || (wchar_t) c > L_('9')) X && (!ISALPHA (c) || (int) (TOUPPER (c) - L_('A') + 10) >= base)) X break; X if (*s == thousands) X end = s; X else X end = correctly_grouped_prefix (s, end, thousands, grouping); X } X else X#endif X end = NULL; X X cutoff = STRTOL_ULONG_MAX / (unsigned LONG int) base; X cutlim = STRTOL_ULONG_MAX % (unsigned LONG int) base; X X overflow = 0; X i = 0; X for (c = *s; c != L_('\0'); c = *++s) X { X if (s == end) X break; X if (c >= L_('0') && c <= L_('9')) X c -= L_('0'); X else if (ISALPHA (c)) X c = TOUPPER (c) - L_('A') + 10; X else X break; X if ((int) c >= base) X break; X /* Check for overflow. */ X if (i > cutoff || (i == cutoff && c > cutlim)) X overflow = 1; X else X { X i *= (unsigned LONG int) base; X i += c; X } X } X X /* Check if anything actually happened. */ X if (s == save) X goto noconv; X X /* Store in ENDPTR the address of one character X past the last character we converted. */ X if (endptr != NULL) X *endptr = (STRING_TYPE *) s; X X#if !UNSIGNED X /* Check for a value that is within the range of X `unsigned LONG int', but outside the range of `LONG int'. */ X if (overflow == 0 X && i > (negative X ? -((unsigned LONG int) (STRTOL_LONG_MIN + 1)) + 1 X : (unsigned LONG int) STRTOL_LONG_MAX)) X overflow = 1; X#endif X X if (overflow) X { X __set_errno (ERANGE); X#if UNSIGNED X return STRTOL_ULONG_MAX; X#else X return negative ? STRTOL_LONG_MIN : STRTOL_LONG_MAX; X#endif X } X X /* Return the result of the appropriate sign. */ X return negative ? -i : i; X Xnoconv: X /* We must handle a special case here: the base is 0 or 16 and the X first two characters are '0' and 'x', but the rest are no X hexadecimal digits. This is no error case. We return 0 and X ENDPTR points to the `x`. */ X if (endptr != NULL) X { X if (save - nptr >= 2 && TOUPPER (save[-1]) == L_('X') X && save[-2] == L_('0')) X *endptr = (STRING_TYPE *) &save[-1]; X else X /* There was no number to convert. */ X *endptr = (STRING_TYPE *) nptr; X } X X return 0L; X} X X/* External user entry point. */ X X#if _LIBC - 0 == 0 X# undef PARAMS X# if defined (__STDC__) && __STDC__ X# define PARAMS(Args) Args X# else X# define PARAMS(Args) () X# endif X X/* Prototype. */ XINT strtol PARAMS ((const STRING_TYPE *nptr, STRING_TYPE **endptr, int base)); X#endif X X XINT X#ifdef weak_function Xweak_function X#endif Xstrtol (nptr, endptr, base LOCALE_PARAM) X const STRING_TYPE *nptr; X STRING_TYPE **endptr; X int base; X LOCALE_PARAM_DECL X{ X return INTERNAL (strtol) (nptr, endptr, base, 0 LOCALE_PARAM); X} END-of-contrib/diff/lib/strtol.c echo x - contrib/diff/lib/xstrtol.c sed 's/^X//' >contrib/diff/lib/xstrtol.c << 'END-of-contrib/diff/lib/xstrtol.c' X/* A more useful interface to strtol. X Copyright (C) 1995, 1996, 1998-2001 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software Foundation, X Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X/* Written by Jim Meyering. */ X X#if HAVE_CONFIG_H X# include X#endif X X#ifndef __strtol X# define __strtol strtol X# define __strtol_t long int X# define __xstrtol xstrtol X#endif X X/* Some pre-ANSI implementations (e.g. SunOS 4) X need stderr defined if assertion checking is enabled. */ X#include X X#if STDC_HEADERS X# include X#endif X X#if HAVE_STRING_H X# include X#else X# include X# ifndef strchr X# define strchr index X# endif X#endif X X#include X#include X X#include X#ifndef errno Xextern int errno; X#endif X X#if HAVE_LIMITS_H X# include X#endif X X#ifndef CHAR_BIT X# define CHAR_BIT 8 X#endif X X/* The extra casts work around common compiler bugs. */ X#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) X/* The outer cast is needed to work around a bug in Cray C 5.0.3.0. X It is necessary at least when t == time_t. */ X#define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \ X ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) : (t) 0)) X#define TYPE_MAXIMUM(t) (~ (t) 0 - TYPE_MINIMUM (t)) X X#if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII)) X# define IN_CTYPE_DOMAIN(c) 1 X#else X# define IN_CTYPE_DOMAIN(c) isascii(c) X#endif X X#define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c)) X X#include "xstrtol.h" X X#if !HAVE_DECL_STRTOL && !defined strtol Xlong int strtol (); X#endif X X#if !HAVE_DECL_STRTOUL && !defined strtoul Xunsigned long int strtoul (); X#endif X X#if !HAVE_DECL_STRTOIMAX && !defined strtoimax Xintmax_t strtoimax (); X#endif X X#if !HAVE_DECL_STRTOUMAX && !defined strtoumax Xuintmax_t strtoumax (); X#endif X Xstatic int Xbkm_scale (__strtol_t *x, int scale_factor) X{ X __strtol_t product = *x * scale_factor; X if (*x != product / scale_factor) X return 1; X *x = product; X return 0; X} X Xstatic int Xbkm_scale_by_power (__strtol_t *x, int base, int power) X{ X while (power--) X if (bkm_scale (x, base)) X return 1; X X return 0; X} X X/* FIXME: comment. */ X Xstrtol_error X__xstrtol (const char *s, char **ptr, int strtol_base, X __strtol_t *val, const char *valid_suffixes) X{ X char *t_ptr; X char **p; X __strtol_t tmp; X X assert (0 <= strtol_base && strtol_base <= 36); X X p = (ptr ? ptr : &t_ptr); X X if (! TYPE_SIGNED (__strtol_t)) X { X const char *q = s; X while (ISSPACE ((unsigned char) *q)) X ++q; X if (*q == '-') X return LONGINT_INVALID; X } X X errno = 0; X tmp = __strtol (s, p, strtol_base); X if (errno != 0) X return LONGINT_OVERFLOW; X X if (*p == s) X { X /* If there is no number but there is a valid suffix, assume the X number is 1. The string is invalid otherwise. */ X if (valid_suffixes && **p && strchr (valid_suffixes, **p)) X tmp = 1; X else X return LONGINT_INVALID; X } X X /* Let valid_suffixes == NULL mean `allow any suffix'. */ X /* FIXME: update all callers except the ones that allow suffixes X after the number, changing last parameter NULL to `""'. */ X if (!valid_suffixes) X { X *val = tmp; X return LONGINT_OK; X } X X if (**p != '\0') X { X int base = 1024; X int suffixes = 1; X int overflow; X X if (!strchr (valid_suffixes, **p)) X { X *val = tmp; X return LONGINT_INVALID_SUFFIX_CHAR; X } X X if (strchr (valid_suffixes, '0')) X { X /* The ``valid suffix'' '0' is a special flag meaning that X an optional second suffix is allowed, which can change X the base. A suffix "B" (e.g. "100MB") stands for a power X of 1000, whereas a suffix "iB" (e.g. "100MiB") stands for X a power of 1024. If no suffix (e.g. "100M"), assume X power-of-1024. */ X X switch (p[0][1]) X { X case 'i': X if (p[0][2] == 'B') X suffixes += 2; X break; X X case 'B': X case 'D': /* 'D' is obsolescent */ X base = 1000; X suffixes++; X break; X } X } X X switch (**p) X { X case 'b': X overflow = bkm_scale (&tmp, 512); X break; X X case 'B': X overflow = bkm_scale (&tmp, 1024); X break; X X case 'c': X overflow = 0; X break; X X case 'E': /* exa or exbi */ X overflow = bkm_scale_by_power (&tmp, base, 6); X break; X X case 'G': /* giga or gibi */ X case 'g': /* 'g' is undocumented; for compatibility only */ X overflow = bkm_scale_by_power (&tmp, base, 3); X break; X X case 'k': /* kilo */ X case 'K': /* kibi */ X overflow = bkm_scale_by_power (&tmp, base, 1); X break; X X case 'M': /* mega or mebi */ X case 'm': /* 'm' is undocumented; for compatibility only */ X overflow = bkm_scale_by_power (&tmp, base, 2); X break; X X case 'P': /* peta or pebi */ X overflow = bkm_scale_by_power (&tmp, base, 5); X break; X X case 'T': /* tera or tebi */ X case 't': /* 't' is undocumented; for compatibility only */ X overflow = bkm_scale_by_power (&tmp, base, 4); X break; X X case 'w': X overflow = bkm_scale (&tmp, 2); X break; X X case 'Y': /* yotta or 2**80 */ X overflow = bkm_scale_by_power (&tmp, base, 8); X break; X X case 'Z': /* zetta or 2**70 */ X overflow = bkm_scale_by_power (&tmp, base, 7); X break; X X default: X *val = tmp; X return LONGINT_INVALID_SUFFIX_CHAR; X break; X } X X if (overflow) X return LONGINT_OVERFLOW; X X (*p) += suffixes; X } X X *val = tmp; X return LONGINT_OK; X} X X#ifdef TESTING_XSTRTO X X# include X# include "error.h" X Xchar *program_name; X Xint Xmain (int argc, char** argv) X{ X strtol_error s_err; X int i; X X program_name = argv[0]; X for (i=1; i%lu (%s)\n", argv[i], val, p); X } X else X { X STRTOL_FATAL_ERROR (argv[i], "arg", s_err); X } X } X exit (0); X} X X#endif /* TESTING_XSTRTO */ END-of-contrib/diff/lib/xstrtol.c echo c - contrib/diff/lib/posix mkdir -p contrib/diff/lib/posix > /dev/null 2>&1 echo x - contrib/diff/lib/posix/Makefile.am sed 's/^X//' >contrib/diff/lib/posix/Makefile.am << 'END-of-contrib/diff/lib/posix/Makefile.am' X## Process this file with automake to create Makefile.in XAUTOMAKE_OPTIONS=no-dependencies X XEXTRA_DIST = regex.h END-of-contrib/diff/lib/posix/Makefile.am echo x - contrib/diff/lib/posix/regex.h sed 's/^X//' >contrib/diff/lib/posix/regex.h << 'END-of-contrib/diff/lib/posix/regex.h' X/* Definitions for data structures and routines for the regular X expression library, version 0.12. X Copyright (C) 1985,1989-1993,1995-1998, 2000 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software Foundation, X Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#ifndef _REGEX_H X#define _REGEX_H 1 X X/* Allow the use in C++ code. */ X#ifdef __cplusplus Xextern "C" { X#endif X X/* POSIX says that must be included (by the caller) before X . */ X X#if !defined _POSIX_C_SOURCE && !defined _POSIX_SOURCE && defined VMS X/* VMS doesn't have `size_t' in , even though POSIX says it X should be there. */ X# include X#endif X X/* The following two types have to be signed and unsigned integer type X wide enough to hold a value of a pointer. For most ANSI compilers X ptrdiff_t and size_t should be likely OK. Still size of these two X types is 2 for Microsoft C. Ugh... */ Xtypedef long int s_reg_t; Xtypedef unsigned long int active_reg_t; X X/* The following bits are used to determine the regexp syntax we X recognize. The set/not-set meanings are chosen so that Emacs syntax X remains the value 0. The bits are given in alphabetical order, and X the definitions shifted by one from the previous bit; thus, when we X add or remove a bit, only one other definition need change. */ Xtypedef unsigned long int reg_syntax_t; X X/* If this bit is not set, then \ inside a bracket expression is literal. X If set, then such a \ quotes the following character. */ X#define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1) X X/* If this bit is not set, then + and ? are operators, and \+ and \? are X literals. X If set, then \+ and \? are operators and + and ? are literals. */ X#define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1) X X/* If this bit is set, then character classes are supported. They are: X [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:], X [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:]. X If not set, then character classes are not supported. */ X#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1) X X/* If this bit is set, then ^ and $ are always anchors (outside bracket X expressions, of course). X If this bit is not set, then it depends: X ^ is an anchor if it is at the beginning of a regular X expression or after an open-group or an alternation operator; X $ is an anchor if it is at the end of a regular expression, or X before a close-group or an alternation operator. X X This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because X POSIX draft 11.2 says that * etc. in leading positions is undefined. X We already implemented a previous draft which made those constructs X invalid, though, so we haven't changed the code back. */ X#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1) X X/* If this bit is set, then special characters are always special X regardless of where they are in the pattern. X If this bit is not set, then special characters are special only in X some contexts; otherwise they are ordinary. Specifically, X * + ? and intervals are only special when not after the beginning, X open-group, or alternation operator. */ X#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1) X X/* If this bit is set, then *, +, ?, and { cannot be first in an re or X immediately after an alternation or begin-group operator. */ X#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1) X X/* If this bit is set, then . matches newline. X If not set, then it doesn't. */ X#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1) X X/* If this bit is set, then . doesn't match NUL. X If not set, then it does. */ X#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1) X X/* If this bit is set, nonmatching lists [^...] do not match newline. X If not set, they do. */ X#define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1) X X/* If this bit is set, either \{...\} or {...} defines an X interval, depending on RE_NO_BK_BRACES. X If not set, \{, \}, {, and } are literals. */ X#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1) X X/* If this bit is set, +, ? and | aren't recognized as operators. X If not set, they are. */ X#define RE_LIMITED_OPS (RE_INTERVALS << 1) X X/* If this bit is set, newline is an alternation operator. X If not set, newline is literal. */ X#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1) X X/* If this bit is set, then `{...}' defines an interval, and \{ and \} X are literals. X If not set, then `\{...\}' defines an interval. */ X#define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1) X X/* If this bit is set, (...) defines a group, and \( and \) are literals. X If not set, \(...\) defines a group, and ( and ) are literals. */ X#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1) X X/* If this bit is set, then \ matches . X If not set, then \ is a back-reference. */ X#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1) X X/* If this bit is set, then | is an alternation operator, and \| is literal. X If not set, then \| is an alternation operator, and | is literal. */ X#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1) X X/* If this bit is set, then an ending range point collating higher X than the starting range point, as in [z-a], is invalid. X If not set, then when ending range point collates higher than the X starting range point, the range is ignored. */ X#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1) X X/* If this bit is set, then an unmatched ) is ordinary. X If not set, then an unmatched ) is invalid. */ X#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1) X X/* If this bit is set, succeed as soon as we match the whole pattern, X without further backtracking. */ X#define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1) X X/* If this bit is set, do not process the GNU regex operators. X If not set, then the GNU regex operators are recognized. */ X#define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1) X X/* If this bit is set, turn on internal regex debugging. X If not set, and debugging was on, turn it off. X This only works if regex.c is compiled -DDEBUG. X We define this bit always, so that all that's needed to turn on X debugging is to recompile regex.c; the calling code can always have X this bit set, and it won't affect anything in the normal case. */ X#define RE_DEBUG (RE_NO_GNU_OPS << 1) X X/* If this bit is set, a syntactically invalid interval is treated as X a string of ordinary characters. For example, the ERE 'a{1' is X treated as 'a\{1'. */ X#define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1) X X/* This global variable defines the particular regexp syntax to use (for X some interfaces). When a regexp is compiled, the syntax used is X stored in the pattern buffer, so changing this does not affect X already-compiled regexps. */ Xextern reg_syntax_t re_syntax_options; X X/* Define combinations of the above bits for the standard possibilities. X (The [[[ comments delimit what gets put into the Texinfo file, so X don't delete them!) */ X/* [[[begin syntaxes]]] */ X#define RE_SYNTAX_EMACS 0 X X#define RE_SYNTAX_AWK \ X (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \ X | RE_NO_BK_PARENS | RE_NO_BK_REFS \ X | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \ X | RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \ X | RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS) X X#define RE_SYNTAX_GNU_AWK \ X ((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DEBUG) \ X & ~(RE_DOT_NOT_NULL | RE_INTERVALS | RE_CONTEXT_INDEP_OPS)) X X#define RE_SYNTAX_POSIX_AWK \ X (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \ X | RE_INTERVALS | RE_NO_GNU_OPS) X X#define RE_SYNTAX_GREP \ X (RE_BK_PLUS_QM | RE_CHAR_CLASSES \ X | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \ X | RE_NEWLINE_ALT) X X#define RE_SYNTAX_EGREP \ X (RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \ X | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \ X | RE_NEWLINE_ALT | RE_NO_BK_PARENS \ X | RE_NO_BK_VBAR) X X#define RE_SYNTAX_POSIX_EGREP \ X (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES \ X | RE_INVALID_INTERVAL_ORD) X X/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */ X#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC X X#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC X X/* Syntax bits common to both basic and extended POSIX regex syntax. */ X#define _RE_SYNTAX_POSIX_COMMON \ X (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \ X | RE_INTERVALS | RE_NO_EMPTY_RANGES) X X#define RE_SYNTAX_POSIX_BASIC \ X (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM) X X/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes X RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this X isn't minimal, since other operators, such as \`, aren't disabled. */ X#define RE_SYNTAX_POSIX_MINIMAL_BASIC \ X (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS) X X#define RE_SYNTAX_POSIX_EXTENDED \ X (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ X | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \ X | RE_NO_BK_PARENS | RE_NO_BK_VBAR \ X | RE_CONTEXT_INVALID_OPS | RE_UNMATCHED_RIGHT_PAREN_ORD) X X/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INDEP_OPS is X removed and RE_NO_BK_REFS is added. */ X#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \ X (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ X | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \ X | RE_NO_BK_PARENS | RE_NO_BK_REFS \ X | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD) X/* [[[end syntaxes]]] */ X X/* Maximum number of duplicates an interval can allow. Some systems X (erroneously) define this in other header files, but we want our X value, so remove any previous define. */ X#ifdef RE_DUP_MAX X# undef RE_DUP_MAX X#endif X/* If sizeof(int) == 2, then ((1 << 15) - 1) overflows. */ X#define RE_DUP_MAX (0x7fff) X X X/* POSIX `cflags' bits (i.e., information for `regcomp'). */ X X/* If this bit is set, then use extended regular expression syntax. X If not set, then use basic regular expression syntax. */ X#define REG_EXTENDED 1 X X/* If this bit is set, then ignore case when matching. X If not set, then case is significant. */ X#define REG_ICASE (REG_EXTENDED << 1) X X/* If this bit is set, then anchors do not match at newline X characters in the string. X If not set, then anchors do match at newlines. */ X#define REG_NEWLINE (REG_ICASE << 1) X X/* If this bit is set, then report only success or fail in regexec. X If not set, then returns differ between not matching and errors. */ X#define REG_NOSUB (REG_NEWLINE << 1) X X X/* POSIX `eflags' bits (i.e., information for regexec). */ X X/* If this bit is set, then the beginning-of-line operator doesn't match X the beginning of the string (presumably because it's not the X beginning of a line). X If not set, then the beginning-of-line operator does match the X beginning of the string. */ X#define REG_NOTBOL 1 X X/* Like REG_NOTBOL, except for the end-of-line. */ X#define REG_NOTEOL (1 << 1) X X X/* If any error codes are removed, changed, or added, update the X `re_error_msg' table in regex.c. */ Xtypedef enum X{ X#ifdef _XOPEN_SOURCE X REG_ENOSYS = -1, /* This will never happen for this implementation. */ X#endif X X REG_NOERROR = 0, /* Success. */ X REG_NOMATCH, /* Didn't find a match (for regexec). */ X X /* POSIX regcomp return error codes. (In the order listed in the X standard.) */ X REG_BADPAT, /* Invalid pattern. */ X REG_ECOLLATE, /* Not implemented. */ X REG_ECTYPE, /* Invalid character class name. */ X REG_EESCAPE, /* Trailing backslash. */ X REG_ESUBREG, /* Invalid back reference. */ X REG_EBRACK, /* Unmatched left bracket. */ X REG_EPAREN, /* Parenthesis imbalance. */ X REG_EBRACE, /* Unmatched \{. */ X REG_BADBR, /* Invalid contents of \{\}. */ X REG_ERANGE, /* Invalid range end. */ X REG_ESPACE, /* Ran out of memory. */ X REG_BADRPT, /* No preceding re for repetition op. */ X X /* Error codes we've added. */ X REG_EEND, /* Premature end. */ X REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */ X REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */ X} reg_errcode_t; X X/* This data structure represents a compiled pattern. Before calling X the pattern compiler, the fields `buffer', `allocated', `fastmap', X `translate', and `no_sub' can be set. After the pattern has been X compiled, the `re_nsub' field is available. All other fields are X private to the regex routines. */ X X#ifndef RE_TRANSLATE_TYPE X# define RE_TRANSLATE_TYPE char * X#endif X Xstruct re_pattern_buffer X{ X/* [[[begin pattern_buffer]]] */ X /* Space that holds the compiled pattern. It is declared as X `unsigned char *' because its elements are X sometimes used as array indexes. */ X unsigned char *buffer; X X /* Number of bytes to which `buffer' points. */ X unsigned long int allocated; X X /* Number of bytes actually used in `buffer'. */ X unsigned long int used; X X /* Syntax setting with which the pattern was compiled. */ X reg_syntax_t syntax; X X /* Pointer to a fastmap, if any, otherwise zero. re_search uses X the fastmap, if there is one, to skip over impossible X starting points for matches. */ X char *fastmap; X X /* Either a translate table to apply to all characters before X comparing them, or zero for no translation. The translation X is applied to a pattern when it is compiled and to a string X when it is matched. */ X RE_TRANSLATE_TYPE translate; X X /* Number of subexpressions found by the compiler. */ X size_t re_nsub; X X /* Zero if this pattern cannot match the empty string, one else. X Well, in truth it's used only in `re_search_2', to see X whether or not we should use the fastmap, so we don't set X this absolutely perfectly; see `re_compile_fastmap' (the X `duplicate' case). */ X unsigned can_be_null : 1; X X /* If REGS_UNALLOCATED, allocate space in the `regs' structure X for `max (RE_NREGS, re_nsub + 1)' groups. X If REGS_REALLOCATE, reallocate space if necessary. X If REGS_FIXED, use what's there. */ X#define REGS_UNALLOCATED 0 X#define REGS_REALLOCATE 1 X#define REGS_FIXED 2 X unsigned regs_allocated : 2; X X /* Set to zero when `regex_compile' compiles a pattern; set to one X by `re_compile_fastmap' if it updates the fastmap. */ X unsigned fastmap_accurate : 1; X X /* If set, `re_match_2' does not return information about X subexpressions. */ X unsigned no_sub : 1; X X /* If set, a beginning-of-line anchor doesn't match at the X beginning of the string. */ X unsigned not_bol : 1; X X /* Similarly for an end-of-line anchor. */ X unsigned not_eol : 1; X X /* If true, an anchor at a newline matches. */ X unsigned newline_anchor : 1; X X/* [[[end pattern_buffer]]] */ X}; X Xtypedef struct re_pattern_buffer regex_t; X X/* Type for byte offsets within the string. POSIX mandates this. */ Xtypedef int regoff_t; X X X/* This is the structure we store register match data in. See X regex.texinfo for a full description of what registers match. */ Xstruct re_registers X{ X unsigned num_regs; X regoff_t *start; X regoff_t *end; X}; X X X/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer, X `re_match_2' returns information about at least this many registers X the first time a `regs' structure is passed. */ X#ifndef RE_NREGS X# define RE_NREGS 30 X#endif X X X/* POSIX specification for registers. Aside from the different names than X `re_registers', POSIX uses an array of structures, instead of a X structure of arrays. */ Xtypedef struct X{ X regoff_t rm_so; /* Byte offset from string's start to substring's start. */ X regoff_t rm_eo; /* Byte offset from string's start to substring's end. */ X} regmatch_t; X X/* Declarations for routines. */ X X/* To avoid duplicating every routine declaration -- once with a X prototype (if we are ANSI), and once without (if we aren't) -- we X use the following macro to declare argument types. This X unfortunately clutters up the declarations a bit, but I think it's X worth it. */ X X#if __STDC__ X X# define _RE_ARGS(args) args X X#else /* not __STDC__ */ X X# define _RE_ARGS(args) () X X#endif /* not __STDC__ */ X X/* Sets the current default syntax to SYNTAX, and return the old syntax. X You can also simply assign to the `re_syntax_options' variable. */ Xextern reg_syntax_t re_set_syntax _RE_ARGS ((reg_syntax_t syntax)); X X/* Compile the regular expression PATTERN, with length LENGTH X and syntax given by the global `re_syntax_options', into the buffer X BUFFER. Return NULL if successful, and an error string if not. */ Xextern const char *re_compile_pattern X _RE_ARGS ((const char *pattern, size_t length, X struct re_pattern_buffer *buffer)); X X X/* Compile a fastmap for the compiled pattern in BUFFER; used to X accelerate searches. Return 0 if successful and -2 if was an X internal error. */ Xextern int re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer)); X X X/* Search in the string STRING (with length LENGTH) for the pattern X compiled into BUFFER. Start searching at position START, for RANGE X characters. Return the starting position of the match, -1 for no X match, or -2 for an internal error. Also return register X information in REGS (if REGS and BUFFER->no_sub are nonzero). */ Xextern int re_search X _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string, X int length, int start, int range, struct re_registers *regs)); X X X/* Like `re_search', but search in the concatenation of STRING1 and X STRING2. Also, stop searching at index START + STOP. */ Xextern int re_search_2 X _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1, X int length1, const char *string2, int length2, X int start, int range, struct re_registers *regs, int stop)); X X X/* Like `re_search', but return how many characters in STRING the regexp X in BUFFER matched, starting at position START. */ Xextern int re_match X _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string, X int length, int start, struct re_registers *regs)); X X X/* Relates to `re_match' as `re_search_2' relates to `re_search'. */ Xextern int re_match_2 X _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1, X int length1, const char *string2, int length2, X int start, struct re_registers *regs, int stop)); X X X/* Set REGS to hold NUM_REGS registers, storing them in STARTS and X ENDS. Subsequent matches using BUFFER and REGS will use this memory X for recording register information. STARTS and ENDS must be X allocated with malloc, and must each be at least `NUM_REGS * sizeof X (regoff_t)' bytes long. X X If NUM_REGS == 0, then subsequent matches should allocate their own X register data. X X Unless this function is called, the first search or match using X PATTERN_BUFFER will allocate its own register data, without X freeing the old data. */ Xextern void re_set_registers X _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs, X unsigned num_regs, regoff_t *starts, regoff_t *ends)); X X#if defined _REGEX_RE_COMP || defined _LIBC X# ifndef _CRAY X/* 4.2 bsd compatibility. */ Xextern char *re_comp _RE_ARGS ((const char *)); Xextern int re_exec _RE_ARGS ((const char *)); X# endif X#endif X X/* GCC 2.95 and later have "__restrict"; C99 compilers have X "restrict", and "configure" may have defined "restrict". */ X#ifndef __restrict X# if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__)) X# if defined restrict || 199901L <= __STDC_VERSION__ X# define __restrict restrict X# else X# define __restrict X# endif X# endif X#endif X/* For now unconditionally define __restrict_arr to expand to nothing. X Ideally we would have a test for the compiler which allows defining X it to restrict. */ X#define __restrict_arr X X/* POSIX compatibility. */ Xextern int regcomp _RE_ARGS ((regex_t *__restrict __preg, X const char *__restrict __pattern, X int __cflags)); X Xextern int regexec _RE_ARGS ((const regex_t *__restrict __preg, X const char *__restrict __string, size_t __nmatch, X regmatch_t __pmatch[__restrict_arr], X int __eflags)); X Xextern size_t regerror _RE_ARGS ((int __errcode, const regex_t *__preg, X char *__errbuf, size_t __errbuf_size)); X Xextern void regfree _RE_ARGS ((regex_t *__preg)); X X X#ifdef __cplusplus X} X#endif /* C++ */ X X#endif /* regex.h */ X X/* XLocal variables: Xmake-backup-files: t Xversion-control: t Xtrim-versions-without-asking: nil XEnd: X*/ END-of-contrib/diff/lib/posix/regex.h echo c - contrib/diff/src mkdir -p contrib/diff/src > /dev/null 2>&1 echo x - contrib/diff/src/diff.h sed 's/^X//' >contrib/diff/src/diff.h << 'END-of-contrib/diff/src/diff.h' X/* Shared definitions for GNU DIFF X X Copyright (C) 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1998, 2001, X 2002 Free Software Foundation, Inc. X X This file is part of GNU DIFF. X X GNU DIFF is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X GNU DIFF is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; see the file COPYING. X If not, write to the Free Software Foundation, X 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#include "system.h" X#include X X#define TAB_WIDTH 8 X X/* What kind of changes a hunk contains. */ Xenum changes X{ X /* No changes: lines common to both files. */ X UNCHANGED, X X /* Deletes only: lines taken from just the first file. */ X OLD, X X /* Inserts only: lines taken from just the second file. */ X NEW, X X /* Both deletes and inserts: a hunk containing both old and new lines. */ X CHANGED X}; X X/* Variables for command line options */ X X#ifndef GDIFF_MAIN X# define XTERN extern X#else X# define XTERN X#endif X Xenum output_style X{ X /* No output style specified. */ X OUTPUT_UNSPECIFIED, X X /* Default output style. */ X OUTPUT_NORMAL, X X /* Output the differences with lines of context before and after (-c). */ X OUTPUT_CONTEXT, X X /* Output the differences in a unified context diff format (-u). */ X OUTPUT_UNIFIED, X X /* Output the differences as commands suitable for `ed' (-e). */ X OUTPUT_ED, X X /* Output the diff as a forward ed script (-f). */ X OUTPUT_FORWARD_ED, X X /* Like -f, but output a count of changed lines in each "command" (-n). */ X OUTPUT_RCS, X X /* Output merged #ifdef'd file (-D). */ X OUTPUT_IFDEF, X X /* Output sdiff style (-y). */ X OUTPUT_SDIFF X}; X X/* True for output styles that are robust, X i.e. can handle a file that ends in a non-newline. */ X#define ROBUST_OUTPUT_STYLE(S) ((S) != OUTPUT_ED && (S) != OUTPUT_FORWARD_ED) X XXTERN enum output_style output_style; X X/* Nonzero if output cannot be generated for identical files. */ XXTERN bool no_diff_means_no_output; X X/* Number of lines of context to show in each set of diffs. X This is zero when context is not to be shown. */ XXTERN lin context; X X/* Consider all files as text files (-a). X Don't interpret codes over 0177 as implying a "binary file". */ XXTERN bool text; X X/* Number of lines to keep in identical prefix and suffix. */ XXTERN lin horizon_lines; X X/* The significance of white space during comparisons. */ XXTERN enum X{ X /* All white space is significant (the default). */ X IGNORE_NO_WHITE_SPACE, X X /* Ignore changes due to tab expansion (-E). */ X IGNORE_TAB_EXPANSION, X X /* Ignore changes in horizontal white space (-b). */ X IGNORE_SPACE_CHANGE, X X /* Ignore all horizontal white space (-w). */ X IGNORE_ALL_SPACE X} ignore_white_space; X X/* Ignore changes that affect only blank lines (-B). */ XXTERN bool ignore_blank_lines; X X/* Files can be compared byte-by-byte, as if they were binary. X This depends on various options. */ XXTERN bool files_can_be_treated_as_binary; X X/* Ignore differences in case of letters (-i). */ XXTERN bool ignore_case; X X/* Ignore differences in case of letters in file names. */ XXTERN bool ignore_file_name_case; X X/* File labels for `-c' output headers (--label). */ XXTERN char *file_label[2]; X X/* Regexp to identify function-header lines (-F). */ XXTERN struct re_pattern_buffer function_regexp; X X/* Ignore changes that affect only lines matching this regexp (-I). */ XXTERN struct re_pattern_buffer ignore_regexp; X X/* Say only whether files differ, not how (-q). */ XXTERN bool brief; X X/* Expand tabs in the output so the text lines up properly X despite the characters added to the front of each line (-t). */ XXTERN bool expand_tabs; X X/* Use a tab in the output, rather than a space, before the text of an X input line, so as to keep the proper alignment in the input line X without changing the characters in it (-T). */ XXTERN bool initial_tab; X X/* Remove trailing carriage returns from input. */ XXTERN bool strip_trailing_cr; X X/* In directory comparison, specify file to start with (-S). X This is used for resuming an aborted comparison. X All file names less than this name are ignored. */ XXTERN char const *starting_file; X X/* Pipe each file's output through pr (-l). */ XXTERN bool paginate; X X/* Line group formats for unchanged, old, new, and changed groups. */ XXTERN char const *group_format[CHANGED + 1]; X X/* Line formats for unchanged, old, and new lines. */ XXTERN char const *line_format[NEW + 1]; X X/* If using OUTPUT_SDIFF print extra information to help the sdiff filter. */ XXTERN bool sdiff_merge_assist; X X/* Tell OUTPUT_SDIFF to show only the left version of common lines. */ XXTERN bool left_column; X X/* Tell OUTPUT_SDIFF to not show common lines. */ XXTERN bool suppress_common_lines; X X/* The half line width and column 2 offset for OUTPUT_SDIFF. */ XXTERN unsigned int sdiff_half_width; XXTERN unsigned int sdiff_column2_offset; X X/* String containing all the command options diff received, X with spaces between and at the beginning but none at the end. X If there were no options given, this string is empty. */ XXTERN char *switch_string; X X/* Use heuristics for better speed with large files with a small X density of changes. */ XXTERN bool speed_large_files; X X/* Patterns that match file names to be excluded. */ XXTERN struct exclude *excluded; X X/* Don't discard lines. This makes things slower (sometimes much X slower) but will find a guaranteed minimal set of changes. */ XXTERN bool minimal; X X/* Name of program the user invoked (for error messages). */ XXTERN char *program_name; X X/* The strftime format to use for time strings. */ XXTERN char const *time_format; X X/* The result of comparison is an "edit script": a chain of `struct change'. X Each `struct change' represents one place where some lines are deleted X and some are inserted. X X LINE0 and LINE1 are the first affected lines in the two files (origin 0). X DELETED is the number of lines deleted here from file 0. X INSERTED is the number of lines inserted here in file 1. X X If DELETED is 0 then LINE0 is the number of the line before X which the insertion was done; vice versa for INSERTED and LINE1. */ X Xstruct change X{ X struct change *link; /* Previous or next edit command */ X lin inserted; /* # lines of file 1 changed here. */ X lin deleted; /* # lines of file 0 changed here. */ X lin line0; /* Line number of 1st deleted line. */ X lin line1; /* Line number of 1st inserted line. */ X bool ignore; /* Flag used in context.c. */ X}; X X/* Structures that describe the input files. */ X X/* Data on one input file being compared. */ X Xstruct file_data { X int desc; /* File descriptor */ X char const *name; /* File name */ X struct stat stat; /* File status */ X X /* Buffer in which text of file is read. */ X word *buffer; X X /* Allocated size of buffer, in bytes. Always a multiple of X sizeof *buffer. */ X size_t bufsize; X X /* Number of valid bytes now in the buffer. */ X size_t buffered; X X /* Array of pointers to lines in the file. */ X char const **linbuf; X X /* linbuf_base <= buffered_lines <= valid_lines <= alloc_lines. X linebuf[linbuf_base ... buffered_lines - 1] are possibly differing. X linebuf[linbuf_base ... valid_lines - 1] contain valid data. X linebuf[linbuf_base ... alloc_lines - 1] are allocated. */ X lin linbuf_base, buffered_lines, valid_lines, alloc_lines; X X /* Pointer to end of prefix of this file to ignore when hashing. */ X char const *prefix_end; X X /* Count of lines in the prefix. X There are this many lines in the file before linbuf[0]. */ X lin prefix_lines; X X /* Pointer to start of suffix of this file to ignore when hashing. */ X char const *suffix_begin; X X /* Vector, indexed by line number, containing an equivalence code for X each line. It is this vector that is actually compared with that X of another file to generate differences. */ X lin *equivs; X X /* Vector, like the previous one except that X the elements for discarded lines have been squeezed out. */ X lin *undiscarded; X X /* Vector mapping virtual line numbers (not counting discarded lines) X to real ones (counting those lines). Both are origin-0. */ X lin *realindexes; X X /* Total number of nondiscarded lines. */ X lin nondiscarded_lines; X X /* Vector, indexed by real origin-0 line number, X containing TRUE for a line that is an insertion or a deletion. X The results of comparison are stored here. */ X bool *changed; X X /* 1 if file ends in a line with no final newline. */ X bool missing_newline; X X /* 1 if at end of file. */ X bool eof; X X /* 1 more than the maximum equivalence value used for this or its X sibling file. */ X lin equiv_max; X}; X X/* The file buffer, considered as an array of bytes rather than X as an array of words. */ X#define FILE_BUFFER(f) ((char *) (f)->buffer) X X/* Data on two input files being compared. */ X Xstruct comparison X { X struct file_data file[2]; X struct comparison const *parent; /* parent, if a recursive comparison */ X }; X X/* Describe the two files currently being compared. */ X XXTERN struct file_data files[2]; X X/* Stdio stream to output diffs to. */ X XXTERN FILE *outfile; X X/* Declare various functions. */ X X/* analyze.c */ Xint diff_2_files (struct comparison *); X X/* context.c */ Xvoid print_context_header (struct file_data[], bool); Xvoid print_context_script (struct change *, bool); X X/* dir.c */ Xint diff_dirs (struct comparison const *, int (*) (struct comparison const *, char const *, char const *)); X X/* ed.c */ Xvoid print_ed_script (struct change *); Xvoid pr_forward_ed_script (struct change *); X X/* ifdef.c */ Xvoid print_ifdef_script (struct change *); X X/* io.c */ Xvoid file_block_read (struct file_data *, size_t); Xbool read_files (struct file_data[], bool); X X/* normal.c */ Xvoid print_normal_script (struct change *); X X/* rcs.c */ Xvoid print_rcs_script (struct change *); X X/* side.c */ Xvoid print_sdiff_script (struct change *); X X/* util.c */ Xextern char const change_letter[4]; Xextern char const pr_program[]; Xchar *concat (char const *, char const *, char const *); Xchar *dir_file_pathname (char const *, char const *); Xbool lines_differ (char const *, char const *); Xlin translate_line_number (struct file_data const *, lin); Xstruct change *find_change (struct change *); Xstruct change *find_reverse_change (struct change *); Xvoid *zalloc (size_t); Xenum changes analyze_hunk (struct change *, lin *, lin *, lin *, lin *); Xvoid begin_output (void); Xvoid debug_script (struct change *); Xvoid fatal (char const *) __attribute__((noreturn)); Xvoid finish_output (void); Xvoid message (char const *, char const *, char const *); Xvoid message5 (char const *, char const *, char const *, char const *, char const *); Xvoid output_1_line (char const *, char const *, char const *, char const *); Xvoid perror_with_name (char const *); Xvoid pfatal_with_name (char const *) __attribute__((noreturn)); Xvoid print_1_line (char const *, char const * const *); Xvoid print_message_queue (void); Xvoid print_number_range (char, struct file_data *, lin, lin); Xvoid print_script (struct change *, struct change * (*) (struct change *), void (*) (struct change *)); Xvoid setup_output (char const *, char const *, bool); Xvoid translate_range (struct file_data const *, lin, lin, long *, long *); X X/* version.c */ Xextern char const version_string[]; END-of-contrib/diff/src/diff.h echo x - contrib/diff/src/system.h sed 's/^X//' >contrib/diff/src/system.h << 'END-of-contrib/diff/src/system.h' X/* System dependent declarations. X X Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1998, 2001, 2002 X Free Software Foundation, Inc. X X This file is part of GNU DIFF. X X GNU DIFF is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X GNU DIFF is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; see the file COPYING. X If not, write to the Free Software Foundation, X 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#include X X/* Don't bother to support K&R C compilers any more; it's not worth X the trouble. These macros prevent some library modules from being X compiled in K&R C mode. */ X#define PARAMS(Args) Args X#define PROTOTYPES 1 X X/* Define `__attribute__' and `volatile' first X so that they're used consistently in all system includes. */ X#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 6) || __STRICT_ANSI__ X# define __attribute__(x) X#endif X#if defined const && !defined volatile X# define volatile X#endif X X/* Verify a requirement at compile-time (unlike assert, which is runtime). */ X#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; } X X X/* Determine whether an integer type is signed, and its bounds. X This code assumes two's (or one's!) complement with no holes. */ X X/* The extra casts work around common compiler bugs, X e.g. Cray C 5.0.3.0 when t == time_t. */ X#ifndef TYPE_SIGNED X# define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) X#endif X#ifndef TYPE_MINIMUM X# define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \ X ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) \ X : (t) 0)) X#endif X#ifndef TYPE_MAXIMUM X# define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t))) X#endif X X#include X#include X X#if STAT_MACROS_BROKEN X# undef S_ISBLK X# undef S_ISCHR X# undef S_ISDIR X# undef S_ISFIFO X# undef S_ISREG X# undef S_ISSOCK X#endif X#ifndef S_ISDIR X# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) X#endif X#ifndef S_ISREG X# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) X#endif X#if !defined S_ISBLK && defined S_IFBLK X# define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) X#endif X#if !defined S_ISCHR && defined S_IFCHR X# define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) X#endif X#if !defined S_ISFIFO && defined S_IFFIFO X# define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFFIFO) X#endif X#if !defined S_ISSOCK && defined S_IFSOCK X# define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) X#endif X#ifndef S_IXUSR X# define S_IXUSR 0100 X#endif X#ifndef S_IXGRP X# define S_IXGRP 0010 X#endif X#ifndef S_IXOTH X# define S_IXOTH 0001 X#endif X X#if HAVE_UNISTD_H X# include X#endif X X#ifndef SEEK_SET X# define SEEK_SET 0 X#endif X#ifndef SEEK_CUR X# define SEEK_CUR 1 X#endif X X#ifndef STDIN_FILENO X# define STDIN_FILENO 0 X#endif X#ifndef STDOUT_FILENO X# define STDOUT_FILENO 1 X#endif X#ifndef STDERR_FILENO X# define STDERR_FILENO 2 X#endif X X#if HAVE_TIME_H X# include X#else X# include X#endif X X#if HAVE_FCNTL_H X# include X#else X# if HAVE_SYS_FILE_H X# include X# endif X#endif X X#if !HAVE_DUP2 X# define dup2(f, t) (close (t), fcntl (f, F_DUPFD, t)) X#endif X X#ifndef O_RDONLY X# define O_RDONLY 0 X#endif X#ifndef O_RDWR X# define O_RDWR 2 X#endif X#ifndef S_IRUSR X# define S_IRUSR 0400 X#endif X#ifndef S_IWUSR X# define S_IWUSR 0200 X#endif X X#if HAVE_SYS_WAIT_H X# include X#endif X#ifndef WEXITSTATUS X# define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8) X#endif X#ifndef WIFEXITED X# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) X#endif X X#ifndef STAT_BLOCKSIZE X# if HAVE_STRUCT_STAT_ST_BLKSIZE X# define STAT_BLOCKSIZE(s) ((s).st_blksize) X# else X# define STAT_BLOCKSIZE(s) (8 * 1024) X# endif X#endif X X#if HAVE_DIRENT_H X# include X# define NAMLEN(dirent) strlen ((dirent)->d_name) X#else X# define dirent direct X# define NAMLEN(dirent) ((dirent)->d_namlen) X# if HAVE_SYS_NDIR_H X# include X# endif X# if HAVE_SYS_DIR_H X# include X# endif X# if HAVE_NDIR_H X# include X# endif X#endif X X#if HAVE_STDLIB_H X# include X#else X# ifndef getenv X char *getenv (); X# endif X#endif X#ifndef EXIT_SUCCESS X# define EXIT_SUCCESS 0 X#endif X#if !EXIT_FAILURE X# undef EXIT_FAILURE /* Sony NEWS-OS 4.0C defines EXIT_FAILURE to 0. */ X# define EXIT_FAILURE 1 X#endif X#define EXIT_TROUBLE 2 X X#include X#ifndef SSIZE_MAX X# define SSIZE_MAX TYPE_MAXIMUM (ssize_t) X#endif X X#if HAVE_INTTYPES_H X# include X#endif X#ifndef PTRDIFF_MAX X# define PTRDIFF_MAX TYPE_MAXIMUM (ptrdiff_t) X#endif X#ifndef SIZE_MAX X# define SIZE_MAX TYPE_MAXIMUM (size_t) X#endif X#ifndef UINTMAX_MAX X# define UINTMAX_MAX TYPE_MAXIMUM (uintmax_t) X#endif X#if ! HAVE_STRTOUMAX && ! defined strtoumax Xuintmax_t strtoumax (char const *, char **, int); X#endif X X#include X X#if STDC_HEADERS || HAVE_STRING_H X# include X#else X# if !HAVE_STRCHR X# define strchr index X# define strrchr rindex X# endif Xchar *strchr (), *strrchr (); X# if !HAVE_MEMCHR X# define memcmp(s1, s2, n) bcmp (s1, s2, n) X# define memcpy(d, s, n) bcopy (s, d, n) Xvoid *memchr (); X# endif X#endif X X#if HAVE_LOCALE_H X# include X#else X# define setlocale(category, locale) X#endif X X#include X X#define _(msgid) gettext (msgid) X#define N_(msgid) msgid X X#include X X/* CTYPE_DOMAIN (C) is nonzero if the unsigned char C can safely be given X as an argument to macros like `isspace'. */ X#if STDC_HEADERS X# define CTYPE_DOMAIN(c) 1 X#else X# define CTYPE_DOMAIN(c) ((unsigned int) (c) <= 0177) X#endif X#define ISPRINT(c) (CTYPE_DOMAIN (c) && isprint (c)) X#define ISSPACE(c) (CTYPE_DOMAIN (c) && isspace (c)) X X#if STDC_HEADERS X# define TOLOWER(c) tolower (c) X#else X# ifndef _tolower X# define _tolower(c) tolower (c) X# endif X# define TOLOWER(c) (CTYPE_DOMAIN (c) && isupper (c) ? _tolower (c) : (c)) X#endif X X/* ISDIGIT differs from isdigit, as follows: X - Its arg may be any int or unsigned int; it need not be an unsigned char. X - It's guaranteed to evaluate its argument exactly once. X - It's typically faster. X POSIX 1003.1-2001 says that only '0' through '9' are digits. X Prefer ISDIGIT to isdigit unless it's important to use the locale's X definition of `digit' even when the host does not conform to POSIX. */ X#define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9) X X#include X#if !STDC_HEADERS X extern int errno; X#endif X X#include X#ifndef SA_RESTART X# ifdef SA_INTERRUPT /* e.g. SunOS 4.1.x */ X# define SA_RESTART SA_INTERRUPT X# else X# define SA_RESTART 0 X# endif X#endif X#if !defined SIGCHLD && defined SIGCLD X# define SIGCHLD SIGCLD X#endif X X#undef MIN X#undef MAX X#define MIN(a, b) ((a) <= (b) ? (a) : (b)) X#define MAX(a, b) ((a) >= (b) ? (a) : (b)) X X#if HAVE_STDBOOL_H X# include X#else X# define bool unsigned char X#endif X X#if HAVE_VFORK_H X# include X#endif X X#if ! HAVE_WORKING_VFORK X# define vfork fork X#endif X X/* Type used for fast comparison of several bytes at a time. */ X X#ifndef word X# define word uintmax_t X#endif X X/* The integer type of a line number. Since files are read into main X memory, ptrdiff_t should be wide enough. */ X Xtypedef ptrdiff_t lin; X#define LIN_MAX PTRDIFF_MAX Xverify (lin_is_signed, TYPE_SIGNED (lin)); Xverify (lin_is_wide_enough, sizeof (ptrdiff_t) <= sizeof (lin)); Xverify (lin_is_printable_as_long, sizeof (lin) <= sizeof (long)); X X/* This section contains POSIX-compliant defaults for macros X that are meant to be overridden by hand in config.h as needed. */ X X#ifndef file_name_cmp X# define file_name_cmp strcmp X#endif X X#ifndef initialize_main X# define initialize_main(argcp, argvp) X#endif X X#ifndef NULL_DEVICE X# define NULL_DEVICE "/dev/null" X#endif X X/* Do struct stat *S, *T describe the same special file? */ X#ifndef same_special_file X# if HAVE_ST_RDEV && defined S_ISBLK && defined S_ISCHR X# define same_special_file(s, t) \ X (((S_ISBLK ((s)->st_mode) && S_ISBLK ((t)->st_mode)) \ X || (S_ISCHR ((s)->st_mode) && S_ISCHR ((t)->st_mode))) \ X && (s)->st_rdev == (t)->st_rdev) X# else X# define same_special_file(s, t) 0 X# endif X#endif X X/* Do struct stat *S, *T describe the same file? Answer -1 if unknown. */ X#ifndef same_file X# define same_file(s, t) \ X ((((s)->st_ino == (t)->st_ino) && ((s)->st_dev == (t)->st_dev)) \ X || same_special_file (s, t)) X#endif X X/* Do struct stat *S, *T have the same file attributes? X X POSIX says that two files are identical if st_ino and st_dev are X the same, but many filesystems incorrectly assign the same (device, X inode) pair to two distinct files, including: X X - GNU/Linux NFS servers that export all local filesystems as a X single NFS filesystem, if a local device number (st_dev) exceeds X 255, or if a local inode number (st_ino) exceeds 16777215. X X - Network Appliance NFS servers in snapshot directories; see X Network Appliance bug #195. X X - ClearCase MVFS; see bug id ATRia04618. X X Check whether two files that purport to be the same have the same X attributes, to work around instances of this common bug. Do not X inspect all attributes, only attributes useful in checking for this X bug. X X It's possible for two distinct files on a buggy filesystem to have X the same attributes, but it's not worth slowing down all X implementations (or complicating the configuration) to cater to X these rare cases in buggy implementations. */ X X#ifndef same_file_attributes X# define same_file_attributes(s, t) \ X ((s)->st_mode == (t)->st_mode \ X && (s)->st_nlink == (t)->st_nlink \ X && (s)->st_uid == (t)->st_uid \ X && (s)->st_gid == (t)->st_gid \ X && (s)->st_size == (t)->st_size \ X && (s)->st_mtime == (t)->st_mtime \ X && (s)->st_ctime == (t)->st_ctime) X#endif END-of-contrib/diff/src/system.h echo x - contrib/diff/src/Makefile.am sed 's/^X//' >contrib/diff/src/Makefile.am << 'END-of-contrib/diff/src/Makefile.am' X# Automakefile for GNU diffutils programs. X X# Copyright (C) 2001, 2002 Free Software Foundation, Inc. X X## This program is free software; you can redistribute it and/or modify X## it under the terms of the GNU General Public License as published by X## the Free Software Foundation; either version 2, or (at your option) X## any later version. X X## This program is distributed in the hope that it will be useful, X## but WITHOUT ANY WARRANTY; without even the implied warranty of X## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X## GNU General Public License for more details. X X## You should have received a copy of the GNU General Public License X## along with this program; if not, write to the Free Software X## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA X## 02111-1307, USA. X Xbin_PROGRAMS = cmp diff diff3 sdiff X Xnoinst_HEADERS = diff.h system.h X Xlocaledir = $(datadir)/locale X XAM_CPPFLAGS = -I../lib -I$(top_srcdir)/lib XDEFS = -DLOCALEDIR=\"$(localedir)\" @DEFS@ X XLDADD = ../lib/libdiffutils.a @LIBINTL@ Xdiff_LDADD = $(LDADD) @LIB_CLOCK_GETTIME@ X Xcmp_SOURCES = cmp.c version.c Xdiff3_SOURCES = diff3.c version.c Xsdiff_SOURCES = sdiff.c version.c Xdiff_SOURCES = \ X analyze.c context.c diff.c dir.c ed.c ifdef.c io.c \ X normal.c side.c util.c version.c X XMAINTAINERCLEANFILES = $(srcdir)/version.c X X$(srcdir)/version.c: $(top_srcdir)/configure.ac X (echo '#include ' && \ X echo 'char const version_string[] = "(GNU $(PACKAGE)) $(VERSION)";') \ X >$@ END-of-contrib/diff/src/Makefile.am echo x - contrib/diff/src/cmp.c sed 's/^X//' >contrib/diff/src/cmp.c << 'END-of-contrib/diff/src/cmp.c' X/* cmp - compare two files byte by byte X X Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 2001, X 2002 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. X See the GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; see the file COPYING. X If not, write to the Free Software Foundation, X 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#include "system.h" X X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X X#if defined LC_MESSAGES && ENABLE_NLS X# define hard_locale_LC_MESSAGES hard_locale (LC_MESSAGES) X#else X# define hard_locale_LC_MESSAGES 0 X#endif X Xstatic char const authorship_msgid[] = X N_("Written by Torbjorn Granlund and David MacKenzie."); X Xstatic char const copyright_string[] = X "Copyright (C) 2002 Free Software Foundation, Inc."; X Xextern char const version_string[]; X Xstatic int cmp (void); Xstatic off_t file_position (int); Xstatic size_t block_compare (word const *, word const *); Xstatic size_t block_compare_and_count (word const *, word const *, off_t *); Xstatic void sprintc (char *, unsigned char); X X/* Name under which this program was invoked. */ Xchar *program_name; X X/* Filenames of the compared files. */ Xstatic char const *file[2]; X X/* File descriptors of the files. */ Xstatic int file_desc[2]; X X/* Status of the files. */ Xstatic struct stat stat_buf[2]; X X/* Read buffers for the files. */ Xstatic word *buffer[2]; X X/* Optimal block size for the files. */ Xstatic size_t buf_size; X X/* Initial prefix to ignore for each file. */ Xstatic off_t ignore_initial[2]; X X/* Number of bytes to compare. */ Xstatic uintmax_t bytes = UINTMAX_MAX; X X/* Output format. */ Xstatic enum comparison_type X { X type_first_diff, /* Print the first difference. */ X type_all_diffs, /* Print all differences. */ X type_status /* Exit status only. */ X } comparison_type; X X/* If nonzero, print values of bytes quoted like cat -t does. */ Xstatic bool opt_print_bytes; X X/* Values for long options that do not have single-letter equivalents. */ Xenum X{ X HELP_OPTION = CHAR_MAX + 1 X}; X Xstatic struct option const long_options[] = X{ X {"print-bytes", 0, 0, 'b'}, X {"print-chars", 0, 0, 'c'}, /* obsolescent as of diffutils 2.7.3 */ X {"ignore-initial", 1, 0, 'i'}, X {"verbose", 0, 0, 'l'}, X {"bytes", 1, 0, 'n'}, X {"silent", 0, 0, 's'}, X {"quiet", 0, 0, 's'}, X {"version", 0, 0, 'v'}, X {"help", 0, 0, HELP_OPTION}, X {0, 0, 0, 0} X}; X Xstatic void try_help (char const *, char const *) __attribute__((noreturn)); Xstatic void Xtry_help (char const *reason_msgid, char const *operand) X{ X if (reason_msgid) X error (0, 0, _(reason_msgid), operand); X error (EXIT_TROUBLE, 0, X _("Try `%s --help' for more information."), program_name); X abort (); X} X Xstatic char const valid_suffixes[] = "kKMGTPEZY0"; X X/* Parse an operand *ARGPTR of --ignore-initial, updating *ARGPTR to X point after the operand. If DELIMITER is nonzero, the operand may X be followed by DELIMITER; otherwise it must be null-terminated. */ Xstatic off_t Xparse_ignore_initial (char **argptr, char delimiter) X{ X uintmax_t val; X off_t o; X char const *arg = *argptr; X strtol_error e = xstrtoumax (arg, argptr, 0, &val, valid_suffixes); X if (! (e == LONGINT_OK X || (e == LONGINT_INVALID_SUFFIX_CHAR && **argptr == delimiter)) X || (o = val) < 0 || o != val || val == UINTMAX_MAX) X try_help ("invalid --ignore-initial value `%s'", arg); X return o; X} X X/* Specify the output format. */ Xstatic void Xspecify_comparison_type (enum comparison_type t) X{ X if (comparison_type) X try_help ("options -l and -s are incompatible", 0); X comparison_type = t; X} X Xstatic void Xcheck_stdout (void) X{ X if (ferror (stdout)) X error (EXIT_TROUBLE, 0, "%s", _("write failed")); X else if (fclose (stdout) != 0) X error (EXIT_TROUBLE, errno, "%s", _("standard output")); X} X Xstatic char const * const option_help_msgid[] = { X N_("-b --print-bytes Print differing bytes."), X N_("-i SKIP --ignore-initial=SKIP Skip the first SKIP bytes of input."), X N_("-i SKIP1:SKIP2 --ignore-initial=SKIP1:SKIP2"), X N_(" Skip the first SKIP1 bytes of FILE1 and the first SKIP2 bytes of FILE2."), X N_("-l --verbose Output byte numbers and values of all differing bytes."), X N_("-n LIMIT --bytes=LIMIT Compare at most LIMIT bytes."), X N_("-s --quiet --silent Output nothing; yield exit status only."), X N_("-v --version Output version info."), X N_("--help Output this help."), X 0 X}; X Xstatic void Xusage (void) X{ X char const * const *p; X X printf (_("Usage: %s [OPTION]... FILE1 [FILE2 [SKIP1 [SKIP2]]]\n"), X program_name); X printf ("%s\n\n", _("Compare two files byte by byte.")); X for (p = option_help_msgid; *p; p++) X printf (" %s\n", _(*p)); X printf ("\n%s\n%s\n\n%s\n\n%s\n", X _("SKIP1 and SKIP2 are the number of bytes to skip in each file."), X _("SKIP values may be followed by the following multiplicative suffixes:\n\ XkB 1000, K 1024, MB 1,000,000, M 1,048,576,\n\ XGB 1,000,000,000, G 1,073,741,824, and so on for T, P, E, Z, Y."), X _("If a FILE is `-' or missing, read standard input."), X _("Report bugs to .")); X} X Xint Xmain (int argc, char **argv) X{ X int c, f, exit_status; X size_t words_per_buffer; X X exit_failure = EXIT_TROUBLE; X initialize_main (&argc, &argv); X program_name = argv[0]; X setlocale (LC_ALL, ""); X bindtextdomain (PACKAGE, LOCALEDIR); X textdomain (PACKAGE); X c_stack_action (c_stack_die); X X /* Parse command line options. */ X X while ((c = getopt_long (argc, argv, "bci:ln:sv", long_options, 0)) X != -1) X switch (c) X { X case 'b': X case 'c': /* 'c' is obsolescent as of diffutils 2.7.3 */ X opt_print_bytes = 1; X break; X X case 'i': X ignore_initial[0] = parse_ignore_initial (&optarg, ':'); X ignore_initial[1] = (*optarg++ == ':' X ? parse_ignore_initial (&optarg, 0) X : ignore_initial[0]); X break; X X case 'l': X specify_comparison_type (type_all_diffs); X break; X X case 'n': X { X uintmax_t n; X if (xstrtoumax (optarg, 0, 0, &n, valid_suffixes) != LONGINT_OK) X try_help ("invalid --bytes value `%s'", optarg); X if (n < bytes) X bytes = n; X } X break; X X case 's': X specify_comparison_type (type_status); X break; X X case 'v': X printf ("cmp %s\n%s\n\n%s\n\n%s\n", X version_string, copyright_string, X _(free_software_msgid), _(authorship_msgid)); X check_stdout (); X return EXIT_SUCCESS; X X case HELP_OPTION: X usage (); X check_stdout (); X return EXIT_SUCCESS; X X default: X try_help (0, 0); X } X X if (optind == argc) X try_help ("missing operand after `%s'", argv[argc - 1]); X X file[0] = argv[optind++]; X file[1] = optind < argc ? argv[optind++] : "-"; X X for (f = 0; f < 2 && optind < argc; f++) X { X char *arg = argv[optind++]; X ignore_initial[f] = parse_ignore_initial (&arg, 0); X } X X if (optind < argc) X try_help ("extra operand `%s'", argv[optind]); X X for (f = 0; f < 2; f++) X { X /* If file[1] is "-", treat it first; this avoids a misdiagnostic if X stdin is closed and opening file[0] yields file descriptor 0. */ X int f1 = f ^ (strcmp (file[1], "-") == 0); X X /* Two files with the same name are identical. X But wait until we open the file once, for proper diagnostics. */ X if (f && file_name_cmp (file[0], file[1]) == 0) X return EXIT_SUCCESS; X X file_desc[f1] = (strcmp (file[f1], "-") == 0 X ? STDIN_FILENO X : open (file[f1], O_RDONLY, 0)); X if (file_desc[f1] < 0 || fstat (file_desc[f1], stat_buf + f1) != 0) X { X if (file_desc[f1] < 0 && comparison_type == type_status) X exit (EXIT_TROUBLE); X else X error (EXIT_TROUBLE, errno, "%s", file[f1]); X } X X set_binary_mode (file_desc[f1], 1); X } X X /* If the files are links to the same inode and have the same file position, X they are identical. */ X X if (0 < same_file (&stat_buf[0], &stat_buf[1]) X && same_file_attributes (&stat_buf[0], &stat_buf[1]) X && file_position (0) == file_position (1)) X return EXIT_SUCCESS; X X /* If output is redirected to the null device, we may assume `-s'. */ X X if (comparison_type != type_status) X { X struct stat outstat, nullstat; X X if (fstat (STDOUT_FILENO, &outstat) == 0 X && stat (NULL_DEVICE, &nullstat) == 0 X && 0 < same_file (&outstat, &nullstat)) X comparison_type = type_status; X } X X /* If only a return code is needed, X and if both input descriptors are associated with plain files, X conclude that the files differ if they have different sizes X and if more bytes will be compared than are in the smaller file. */ X X if (comparison_type == type_status X && S_ISREG (stat_buf[0].st_mode) X && S_ISREG (stat_buf[1].st_mode)) X { X off_t s0 = stat_buf[0].st_size - file_position (0); X off_t s1 = stat_buf[1].st_size - file_position (1); X if (s0 < 0) X s0 = 0; X if (s1 < 0) X s1 = 0; X if (s0 != s1 && MIN (s0, s1) < bytes) X exit (EXIT_FAILURE); X } X X /* Get the optimal block size of the files. */ X X buf_size = buffer_lcm (STAT_BLOCKSIZE (stat_buf[0]), X STAT_BLOCKSIZE (stat_buf[1]), X PTRDIFF_MAX - sizeof (word)); X X /* Allocate word-aligned buffers, with space for sentinels at the end. */ X X words_per_buffer = (buf_size + 2 * sizeof (word) - 1) / sizeof (word); X buffer[0] = xmalloc (2 * sizeof (word) * words_per_buffer); X buffer[1] = buffer[0] + words_per_buffer; X X exit_status = cmp (); X X for (f = 0; f < 2; f++) X if (close (file_desc[f]) != 0) X error (EXIT_TROUBLE, errno, "%s", file[f]); X if (exit_status != 0 && comparison_type != type_status) X check_stdout (); X exit (exit_status); X return exit_status; X} X X/* Compare the two files already open on `file_desc[0]' and `file_desc[1]', X using `buffer[0]' and `buffer[1]'. X Return EXIT_SUCCESS if identical, EXIT_FAILURE if different, X >1 if error. */ X Xstatic int Xcmp (void) X{ X off_t line_number = 1; /* Line number (1...) of difference. */ X off_t byte_number = 1; /* Byte number (1...) of difference. */ X uintmax_t remaining = bytes; /* Remaining number of bytes to compare. */ X size_t read0, read1; /* Number of bytes read from each file. */ X size_t first_diff; /* Offset (0...) in buffers of 1st diff. */ X size_t smaller; /* The lesser of `read0' and `read1'. */ X word *buffer0 = buffer[0]; X word *buffer1 = buffer[1]; X char *buf0 = (char *) buffer0; X char *buf1 = (char *) buffer1; X int ret = EXIT_SUCCESS; X int f; X int offset_width; X X if (comparison_type == type_all_diffs) X { X off_t byte_number_max = MIN (bytes, TYPE_MAXIMUM (off_t)); X X for (f = 0; f < 2; f++) X if (S_ISREG (stat_buf[f].st_mode)) X { X off_t file_bytes = stat_buf[f].st_size - file_position (f); X if (file_bytes < byte_number_max) X byte_number_max = file_bytes; X } X X for (offset_width = 1; (byte_number_max /= 10) != 0; offset_width++) X continue; X } X X for (f = 0; f < 2; f++) X { X off_t ig = ignore_initial[f]; X if (ig && file_position (f) == -1) X { X /* lseek failed; read and discard the ignored initial prefix. */ X do X { X size_t bytes_to_read = MIN (ig, buf_size); X size_t r = block_read (file_desc[f], buf0, bytes_to_read); X if (r != bytes_to_read) X { X if (r == SIZE_MAX) X error (EXIT_TROUBLE, errno, "%s", file[f]); X break; X } X ig -= r; X } X while (ig); X } X } X X do X { X size_t bytes_to_read = buf_size; X X if (remaining != UINTMAX_MAX) X { X if (remaining < bytes_to_read) X bytes_to_read = remaining; X remaining -= bytes_to_read; X } X X read0 = block_read (file_desc[0], buf0, bytes_to_read); X if (read0 == SIZE_MAX) X error (EXIT_TROUBLE, errno, "%s", file[0]); X read1 = block_read (file_desc[1], buf1, bytes_to_read); X if (read1 == SIZE_MAX) X error (EXIT_TROUBLE, errno, "%s", file[1]); X X /* Insert sentinels for the block compare. */ X X buf0[read0] = ~buf1[read0]; X buf1[read1] = ~buf0[read1]; X X /* If the line number should be written for differing files, X compare the blocks and count the number of newlines X simultaneously. */ X first_diff = (comparison_type == type_first_diff X ? block_compare_and_count (buffer0, buffer1, &line_number) X : block_compare (buffer0, buffer1)); X X byte_number += first_diff; X smaller = MIN (read0, read1); X X if (first_diff < smaller) X { X switch (comparison_type) X { X case type_first_diff: X { X char byte_buf[INT_BUFSIZE_BOUND (off_t)]; X char line_buf[INT_BUFSIZE_BOUND (off_t)]; X char const *byte_num = offtostr (byte_number, byte_buf); X char const *line_num = offtostr (line_number, line_buf); X if (!opt_print_bytes) X { X /* See POSIX 1003.1-2001 for this format. This X message is used only in the POSIX locale, so it X need not be translated. */ X static char const char_message[] = X "%s %s differ: char %s, line %s\n"; X X /* The POSIX rationale recommends using the word X "byte" outside the POSIX locale. Some gettext X implementations translate even in the POSIX X locale if certain other environment variables X are set, so use "byte" if a translation is X available, or if outside the POSIX locale. */ X static char const byte_msgid[] = X N_("%s %s differ: byte %s, line %s\n"); X char const *byte_message = _(byte_msgid); X bool use_byte_message = (byte_message != byte_msgid X || hard_locale_LC_MESSAGES); X X printf ((use_byte_message X ? byte_message X : "%s %s differ: char %s, line %s\n"), X file[0], file[1], byte_num, line_num); X } X else X { X unsigned char c0 = buf0[first_diff]; X unsigned char c1 = buf1[first_diff]; X char s0[5]; X char s1[5]; X sprintc (s0, c0); X sprintc (s1, c1); X printf (_("%s %s differ: byte %s, line %s is %3o %s %3o %s\n"), X file[0], file[1], byte_num, line_num, X c0, s0, c1, s1); X } X } X /* Fall through. */ X case type_status: X return EXIT_FAILURE; X X case type_all_diffs: X do X { X unsigned char c0 = buf0[first_diff]; X unsigned char c1 = buf1[first_diff]; X if (c0 != c1) X { X char byte_buf[INT_BUFSIZE_BOUND (off_t)]; X char const *byte_num = offtostr (byte_number, byte_buf); X if (!opt_print_bytes) X { X /* See POSIX 1003.1-2001 for this format. */ X printf ("%*s %3o %3o\n", X offset_width, byte_num, c0, c1); X } X else X { X char s0[5]; X char s1[5]; X sprintc (s0, c0); X sprintc (s1, c1); X printf ("%*s %3o %-4s %3o %s\n", X offset_width, byte_num, c0, s0, c1, s1); X } X } X byte_number++; X first_diff++; X } X while (first_diff < smaller); X ret = EXIT_FAILURE; X break; X } X } X X if (read0 != read1) X { X if (comparison_type != type_status) X { X /* See POSIX 1003.1-2001 for this format. */ X fprintf (stderr, _("cmp: EOF on %s\n"), file[read1 < read0]); X } X X return EXIT_FAILURE; X } X } X while (read0 == buf_size); X X return ret; X} X X/* Compare two blocks of memory P0 and P1 until they differ, X and count the number of '\n' occurrences in the common X part of P0 and P1. X If the blocks are not guaranteed to be different, put sentinels at the ends X of the blocks before calling this function. X X Return the offset of the first byte that differs. X Increment *COUNT by the count of '\n' occurrences. */ X Xstatic size_t Xblock_compare_and_count (word const *p0, word const *p1, off_t *count) X{ X word l; /* One word from first buffer. */ X word const *l0, *l1; /* Pointers into each buffer. */ X char const *c0, *c1; /* Pointers for finding exact address. */ X size_t cnt = 0; /* Number of '\n' occurrences. */ X word nnnn; /* Newline, sizeof (word) times. */ X int i; X X nnnn = 0; X for (i = 0; i < sizeof nnnn; i++) X nnnn = (nnnn << CHAR_BIT) | '\n'; X X /* Find the rough position of the first difference by reading words, X not bytes. */ X X for (l0 = p0, l1 = p1; (l = *l0) == *l1; l0++, l1++) X { X l ^= nnnn; X for (i = 0; i < sizeof l; i++) X { X cnt += ! (unsigned char) l; X l >>= CHAR_BIT; X } X } X X /* Find the exact differing position (endianness independent). */ X X for (c0 = (char const *) l0, c1 = (char const *) l1; X *c0 == *c1; X c0++, c1++) X cnt += *c0 == '\n'; X X *count += cnt; X return c0 - (char const *) p0; X} X X/* Compare two blocks of memory P0 and P1 until they differ. X If the blocks are not guaranteed to be different, put sentinels at the ends X of the blocks before calling this function. X X Return the offset of the first byte that differs. */ X Xstatic size_t Xblock_compare (word const *p0, word const *p1) X{ X word const *l0, *l1; X char const *c0, *c1; X X /* Find the rough position of the first difference by reading words, X not bytes. */ X X for (l0 = p0, l1 = p1; *l0 == *l1; l0++, l1++) X continue; X X /* Find the exact differing position (endianness independent). */ X X for (c0 = (char const *) l0, c1 = (char const *) l1; X *c0 == *c1; X c0++, c1++) X continue; X X return c0 - (char const *) p0; X} X X/* Put into BUF the unsigned char C, making unprintable bytes X visible by quoting like cat -t does. */ X Xstatic void Xsprintc (char *buf, unsigned char c) X{ X if (! ISPRINT (c)) X { X if (c >= 128) X { X *buf++ = 'M'; X *buf++ = '-'; X c -= 128; X } X if (c < 32) X { X *buf++ = '^'; X c += 64; X } X else if (c == 127) X { X *buf++ = '^'; X c = '?'; X } X } X X *buf++ = c; X *buf = 0; X} X X/* Position file F to ignore_initial[F] bytes from its initial position, X and yield its new position. Don't try more than once. */ X Xstatic off_t Xfile_position (int f) X{ X static bool positioned[2]; X static off_t position[2]; X X if (! positioned[f]) X { X positioned[f] = 1; X position[f] = lseek (file_desc[f], ignore_initial[f], SEEK_CUR); X } X return position[f]; X} END-of-contrib/diff/src/cmp.c echo x - contrib/diff/src/version.c sed 's/^X//' >contrib/diff/src/version.c << 'END-of-contrib/diff/src/version.c' X#include Xchar const version_string[] = "(GNU diffutils) 2.8.1"; END-of-contrib/diff/src/version.c echo x - contrib/diff/src/analyze.c sed 's/^X//' >contrib/diff/src/analyze.c << 'END-of-contrib/diff/src/analyze.c' X/* Analyze file differences for GNU DIFF. X X Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1998, 2001, 2002 X Free Software Foundation, Inc. X X This file is part of GNU DIFF. X X GNU DIFF is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X GNU DIFF is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; see the file COPYING. X If not, write to the Free Software Foundation, X 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X/* The basic algorithm is described in: X "An O(ND) Difference Algorithm and its Variations", Eugene Myers, X Algorithmica Vol. 1 No. 2, 1986, pp. 251-266; X see especially section 4.2, which describes the variation used below. X Unless the --minimal option is specified, this code uses the TOO_EXPENSIVE X heuristic, by Paul Eggert, to limit the cost to O(N**1.5 log N) X at the price of producing suboptimal output for large inputs with X many differences. X X The basic algorithm was independently discovered as described in: X "Algorithms for Approximate String Matching", E. Ukkonen, X Information and Control Vol. 64, 1985, pp. 100-118. */ X X#include "diff.h" X#include X#include X#include X#include X Xstatic lin *xvec, *yvec; /* Vectors being compared. */ Xstatic lin *fdiag; /* Vector, indexed by diagonal, containing X 1 + the X coordinate of the point furthest X along the given diagonal in the forward X search of the edit matrix. */ Xstatic lin *bdiag; /* Vector, indexed by diagonal, containing X the X coordinate of the point furthest X along the given diagonal in the backward X search of the edit matrix. */ Xstatic lin too_expensive; /* Edit scripts longer than this are too X expensive to compute. */ X X#define SNAKE_LIMIT 20 /* Snakes bigger than this are considered `big'. */ X Xstruct partition X{ X lin xmid, ymid; /* Midpoints of this partition. */ X bool lo_minimal; /* Nonzero if low half will be analyzed minimally. */ X bool hi_minimal; /* Likewise for high half. */ X}; X X/* Find the midpoint of the shortest edit script for a specified X portion of the two files. X X Scan from the beginnings of the files, and simultaneously from the ends, X doing a breadth-first search through the space of edit-sequence. X When the two searches meet, we have found the midpoint of the shortest X edit sequence. X X If FIND_MINIMAL is nonzero, find the minimal edit script regardless X of expense. Otherwise, if the search is too expensive, use X heuristics to stop the search and report a suboptimal answer. X X Set PART->(xmid,ymid) to the midpoint (XMID,YMID). The diagonal number X XMID - YMID equals the number of inserted lines minus the number X of deleted lines (counting only lines before the midpoint). X Return the approximate edit cost; this is the total number of X lines inserted or deleted (counting only lines before the midpoint), X unless a heuristic is used to terminate the search prematurely. X X Set PART->lo_minimal to true iff the minimal edit script for the X left half of the partition is known; similarly for PART->hi_minimal. X X This function assumes that the first lines of the specified portions X of the two files do not match, and likewise that the last lines do not X match. The caller must trim matching lines from the beginning and end X of the portions it is going to specify. X X If we return the "wrong" partitions, X the worst this can do is cause suboptimal diff output. X It cannot cause incorrect diff output. */ X Xstatic lin Xdiag (lin xoff, lin xlim, lin yoff, lin ylim, bool find_minimal, X struct partition *part) X{ X lin *const fd = fdiag; /* Give the compiler a chance. */ X lin *const bd = bdiag; /* Additional help for the compiler. */ X lin const *const xv = xvec; /* Still more help for the compiler. */ X lin const *const yv = yvec; /* And more and more . . . */ X lin const dmin = xoff - ylim; /* Minimum valid diagonal. */ X lin const dmax = xlim - yoff; /* Maximum valid diagonal. */ X lin const fmid = xoff - yoff; /* Center diagonal of top-down search. */ X lin const bmid = xlim - ylim; /* Center diagonal of bottom-up search. */ X lin fmin = fmid, fmax = fmid; /* Limits of top-down search. */ X lin bmin = bmid, bmax = bmid; /* Limits of bottom-up search. */ X lin c; /* Cost. */ X bool odd = (fmid - bmid) & 1; /* True if southeast corner is on an odd X diagonal with respect to the northwest. */ X X fd[fmid] = xoff; X bd[bmid] = xlim; X X for (c = 1;; ++c) X { X lin d; /* Active diagonal. */ X bool big_snake = 0; X X /* Extend the top-down search by an edit step in each diagonal. */ X fmin > dmin ? fd[--fmin - 1] = -1 : ++fmin; X fmax < dmax ? fd[++fmax + 1] = -1 : --fmax; X for (d = fmax; d >= fmin; d -= 2) X { X lin x, y, oldx, tlo = fd[d - 1], thi = fd[d + 1]; X X if (tlo >= thi) X x = tlo + 1; X else X x = thi; X oldx = x; X y = x - d; X while (x < xlim && y < ylim && xv[x] == yv[y]) X ++x, ++y; X if (x - oldx > SNAKE_LIMIT) X big_snake = 1; X fd[d] = x; X if (odd && bmin <= d && d <= bmax && bd[d] <= x) X { X part->xmid = x; X part->ymid = y; X part->lo_minimal = part->hi_minimal = 1; X return 2 * c - 1; X } X } X X /* Similarly extend the bottom-up search. */ X bmin > dmin ? bd[--bmin - 1] = LIN_MAX : ++bmin; X bmax < dmax ? bd[++bmax + 1] = LIN_MAX : --bmax; X for (d = bmax; d >= bmin; d -= 2) X { X lin x, y, oldx, tlo = bd[d - 1], thi = bd[d + 1]; X X if (tlo < thi) X x = tlo; X else X x = thi - 1; X oldx = x; X y = x - d; X while (x > xoff && y > yoff && xv[x - 1] == yv[y - 1]) X --x, --y; X if (oldx - x > SNAKE_LIMIT) X big_snake = 1; X bd[d] = x; X if (!odd && fmin <= d && d <= fmax && x <= fd[d]) X { X part->xmid = x; X part->ymid = y; X part->lo_minimal = part->hi_minimal = 1; X return 2 * c; X } X } X X if (find_minimal) X continue; X X /* Heuristic: check occasionally for a diagonal that has made X lots of progress compared with the edit distance. X If we have any such, find the one that has made the most X progress and return it as if it had succeeded. X X With this heuristic, for files with a constant small density X of changes, the algorithm is linear in the file size. */ X X if (200 < c && big_snake && speed_large_files) X { X lin best; X X best = 0; X for (d = fmax; d >= fmin; d -= 2) X { X lin dd = d - fmid; X lin x = fd[d]; X lin y = x - d; X lin v = (x - xoff) * 2 - dd; X if (v > 12 * (c + (dd < 0 ? -dd : dd))) X { X if (v > best X && xoff + SNAKE_LIMIT <= x && x < xlim X && yoff + SNAKE_LIMIT <= y && y < ylim) X { X /* We have a good enough best diagonal; X now insist that it end with a significant snake. */ X int k; X X for (k = 1; xv[x - k] == yv[y - k]; k++) X if (k == SNAKE_LIMIT) X { X best = v; X part->xmid = x; X part->ymid = y; X break; X } X } X } X } X if (best > 0) X { X part->lo_minimal = 1; X part->hi_minimal = 0; X return 2 * c - 1; X } X X best = 0; X for (d = bmax; d >= bmin; d -= 2) X { X lin dd = d - bmid; X lin x = bd[d]; X lin y = x - d; X lin v = (xlim - x) * 2 + dd; X if (v > 12 * (c + (dd < 0 ? -dd : dd))) X { X if (v > best X && xoff < x && x <= xlim - SNAKE_LIMIT X && yoff < y && y <= ylim - SNAKE_LIMIT) X { X /* We have a good enough best diagonal; X now insist that it end with a significant snake. */ X int k; X X for (k = 0; xv[x + k] == yv[y + k]; k++) X if (k == SNAKE_LIMIT - 1) X { X best = v; X part->xmid = x; X part->ymid = y; X break; X } X } X } X } X if (best > 0) X { X part->lo_minimal = 0; X part->hi_minimal = 1; X return 2 * c - 1; X } X } X X /* Heuristic: if we've gone well beyond the call of duty, X give up and report halfway between our best results so far. */ X if (c >= too_expensive) X { X lin fxybest, fxbest; X lin bxybest, bxbest; X X fxbest = bxbest = 0; /* Pacify `gcc -Wall'. */ X X /* Find forward diagonal that maximizes X + Y. */ X fxybest = -1; X for (d = fmax; d >= fmin; d -= 2) X { X lin x = MIN (fd[d], xlim); X lin y = x - d; X if (ylim < y) X x = ylim + d, y = ylim; X if (fxybest < x + y) X { X fxybest = x + y; X fxbest = x; X } X } X X /* Find backward diagonal that minimizes X + Y. */ X bxybest = LIN_MAX; X for (d = bmax; d >= bmin; d -= 2) X { X lin x = MAX (xoff, bd[d]); X lin y = x - d; X if (y < yoff) X x = yoff + d, y = yoff; X if (x + y < bxybest) X { X bxybest = x + y; X bxbest = x; X } X } X X /* Use the better of the two diagonals. */ X if ((xlim + ylim) - bxybest < fxybest - (xoff + yoff)) X { X part->xmid = fxbest; X part->ymid = fxybest - fxbest; X part->lo_minimal = 1; X part->hi_minimal = 0; X } X else X { X part->xmid = bxbest; X part->ymid = bxybest - bxbest; X part->lo_minimal = 0; X part->hi_minimal = 1; X } X return 2 * c - 1; X } X } X} X X/* Compare in detail contiguous subsequences of the two files X which are known, as a whole, to match each other. X X The results are recorded in the vectors files[N].changed, by X storing 1 in the element for each line that is an insertion or deletion. X X The subsequence of file 0 is [XOFF, XLIM) and likewise for file 1. X X Note that XLIM, YLIM are exclusive bounds. X All line numbers are origin-0 and discarded lines are not counted. X X If FIND_MINIMAL, find a minimal difference no matter how X expensive it is. */ X Xstatic void Xcompareseq (lin xoff, lin xlim, lin yoff, lin ylim, bool find_minimal) X{ X lin * const xv = xvec; /* Help the compiler. */ X lin * const yv = yvec; X X /* Slide down the bottom initial diagonal. */ X while (xoff < xlim && yoff < ylim && xv[xoff] == yv[yoff]) X ++xoff, ++yoff; X /* Slide up the top initial diagonal. */ X while (xlim > xoff && ylim > yoff && xv[xlim - 1] == yv[ylim - 1]) X --xlim, --ylim; X X /* Handle simple cases. */ X if (xoff == xlim) X while (yoff < ylim) X files[1].changed[files[1].realindexes[yoff++]] = 1; X else if (yoff == ylim) X while (xoff < xlim) X files[0].changed[files[0].realindexes[xoff++]] = 1; X else X { X lin c; X struct partition part; X X /* Find a point of correspondence in the middle of the files. */ X X c = diag (xoff, xlim, yoff, ylim, find_minimal, &part); X X if (c == 1) X { X /* This should be impossible, because it implies that X one of the two subsequences is empty, X and that case was handled above without calling `diag'. X Let's verify that this is true. */ X abort (); X#if 0 X /* The two subsequences differ by a single insert or delete; X record it and we are done. */ X if (part.xmid - part.ymid < xoff - yoff) X files[1].changed[files[1].realindexes[part.ymid - 1]] = 1; X else X files[0].changed[files[0].realindexes[part.xmid]] = 1; X#endif X } X else X { X /* Use the partitions to split this problem into subproblems. */ X compareseq (xoff, part.xmid, yoff, part.ymid, part.lo_minimal); X compareseq (part.xmid, xlim, part.ymid, ylim, part.hi_minimal); X } X } X} X X/* Discard lines from one file that have no matches in the other file. X X A line which is discarded will not be considered by the actual X comparison algorithm; it will be as if that line were not in the file. X The file's `realindexes' table maps virtual line numbers X (which don't count the discarded lines) into real line numbers; X this is how the actual comparison algorithm produces results X that are comprehensible when the discarded lines are counted. X X When we discard a line, we also mark it as a deletion or insertion X so that it will be printed in the output. */ X Xstatic void Xdiscard_confusing_lines (struct file_data filevec[]) X{ X int f; X lin i; X char *discarded[2]; X lin *equiv_count[2]; X lin *p; X X /* Allocate our results. */ X p = xmalloc ((filevec[0].buffered_lines + filevec[1].buffered_lines) X * (2 * sizeof *p)); X for (f = 0; f < 2; f++) X { X filevec[f].undiscarded = p; p += filevec[f].buffered_lines; X filevec[f].realindexes = p; p += filevec[f].buffered_lines; X } X X /* Set up equiv_count[F][I] as the number of lines in file F X that fall in equivalence class I. */ X X p = zalloc (filevec[0].equiv_max * (2 * sizeof *p)); X equiv_count[0] = p; X equiv_count[1] = p + filevec[0].equiv_max; X X for (i = 0; i < filevec[0].buffered_lines; ++i) X ++equiv_count[0][filevec[0].equivs[i]]; X for (i = 0; i < filevec[1].buffered_lines; ++i) X ++equiv_count[1][filevec[1].equivs[i]]; X X /* Set up tables of which lines are going to be discarded. */ X X discarded[0] = zalloc (filevec[0].buffered_lines X + filevec[1].buffered_lines); X discarded[1] = discarded[0] + filevec[0].buffered_lines; X X /* Mark to be discarded each line that matches no line of the other file. X If a line matches many lines, mark it as provisionally discardable. */ X X for (f = 0; f < 2; f++) X { X size_t end = filevec[f].buffered_lines; X char *discards = discarded[f]; X lin *counts = equiv_count[1 - f]; X lin *equivs = filevec[f].equivs; X size_t many = 5; X size_t tem = end / 64; X X /* Multiply MANY by approximate square root of number of lines. X That is the threshold for provisionally discardable lines. */ X while ((tem = tem >> 2) > 0) X many *= 2; X X for (i = 0; i < end; i++) X { X lin nmatch; X if (equivs[i] == 0) X continue; X nmatch = counts[equivs[i]]; X if (nmatch == 0) X discards[i] = 1; X else if (nmatch > many) X discards[i] = 2; X } X } X X /* Don't really discard the provisional lines except when they occur X in a run of discardables, with nonprovisionals at the beginning X and end. */ X X for (f = 0; f < 2; f++) X { X lin end = filevec[f].buffered_lines; X register char *discards = discarded[f]; X X for (i = 0; i < end; i++) X { X /* Cancel provisional discards not in middle of run of discards. */ X if (discards[i] == 2) X discards[i] = 0; X else if (discards[i] != 0) X { X /* We have found a nonprovisional discard. */ X register lin j; X lin length; X lin provisional = 0; X X /* Find end of this run of discardable lines. X Count how many are provisionally discardable. */ X for (j = i; j < end; j++) X { X if (discards[j] == 0) X break; X if (discards[j] == 2) X ++provisional; X } X X /* Cancel provisional discards at end, and shrink the run. */ X while (j > i && discards[j - 1] == 2) X discards[--j] = 0, --provisional; X X /* Now we have the length of a run of discardable lines X whose first and last are not provisional. */ X length = j - i; X X /* If 1/4 of the lines in the run are provisional, X cancel discarding of all provisional lines in the run. */ X if (provisional * 4 > length) X { X while (j > i) X if (discards[--j] == 2) X discards[j] = 0; X } X else X { X register lin consec; X lin minimum = 1; X lin tem = length >> 2; X X /* MINIMUM is approximate square root of LENGTH/4. X A subrun of two or more provisionals can stand X when LENGTH is at least 16. X A subrun of 4 or more can stand when LENGTH >= 64. */ X while (0 < (tem >>= 2)) X minimum <<= 1; X minimum++; X X /* Cancel any subrun of MINIMUM or more provisionals X within the larger run. */ X for (j = 0, consec = 0; j < length; j++) X if (discards[i + j] != 2) X consec = 0; X else if (minimum == ++consec) X /* Back up to start of subrun, to cancel it all. */ X j -= consec; X else if (minimum < consec) X discards[i + j] = 0; X X /* Scan from beginning of run X until we find 3 or more nonprovisionals in a row X or until the first nonprovisional at least 8 lines in. X Until that point, cancel any provisionals. */ X for (j = 0, consec = 0; j < length; j++) X { X if (j >= 8 && discards[i + j] == 1) X break; X if (discards[i + j] == 2) X consec = 0, discards[i + j] = 0; X else if (discards[i + j] == 0) X consec = 0; X else X consec++; X if (consec == 3) X break; X } X X /* I advances to the last line of the run. */ X i += length - 1; X X /* Same thing, from end. */ X for (j = 0, consec = 0; j < length; j++) X { X if (j >= 8 && discards[i - j] == 1) X break; X if (discards[i - j] == 2) X consec = 0, discards[i - j] = 0; X else if (discards[i - j] == 0) X consec = 0; X else X consec++; X if (consec == 3) X break; X } X } X } X } X } X X /* Actually discard the lines. */ X for (f = 0; f < 2; f++) X { X char *discards = discarded[f]; X lin end = filevec[f].buffered_lines; X lin j = 0; X for (i = 0; i < end; ++i) X if (minimal || discards[i] == 0) X { X filevec[f].undiscarded[j] = filevec[f].equivs[i]; X filevec[f].realindexes[j++] = i; X } X else X filevec[f].changed[i] = 1; X filevec[f].nondiscarded_lines = j; X } X X free (discarded[0]); X free (equiv_count[0]); X} X X/* Adjust inserts/deletes of identical lines to join changes X as much as possible. X X We do something when a run of changed lines include a X line at one end and have an excluded, identical line at the other. X We are free to choose which identical line is included. X `compareseq' usually chooses the one at the beginning, X but usually it is cleaner to consider the following identical line X to be the "change". */ X Xstatic void Xshift_boundaries (struct file_data filevec[]) X{ X int f; X X for (f = 0; f < 2; f++) X { X bool *changed = filevec[f].changed; X bool const *other_changed = filevec[1 - f].changed; X lin const *equivs = filevec[f].equivs; X lin i = 0; X lin j = 0; X lin i_end = filevec[f].buffered_lines; X X while (1) X { X lin runlength, start, corresponding; X X /* Scan forwards to find beginning of another run of changes. X Also keep track of the corresponding point in the other file. */ X X while (i < i_end && !changed[i]) X { X while (other_changed[j++]) X continue; X i++; X } X X if (i == i_end) X break; X X start = i; X X /* Find the end of this run of changes. */ X X while (changed[++i]) X continue; X while (other_changed[j]) X j++; X X do X { X /* Record the length of this run of changes, so that X we can later determine whether the run has grown. */ X runlength = i - start; X X /* Move the changed region back, so long as the X previous unchanged line matches the last changed one. X This merges with previous changed regions. */ X X while (start && equivs[start - 1] == equivs[i - 1]) X { X changed[--start] = 1; X changed[--i] = 0; X while (changed[start - 1]) X start--; X while (other_changed[--j]) X continue; X } X X /* Set CORRESPONDING to the end of the changed run, at the last X point where it corresponds to a changed run in the other file. X CORRESPONDING == I_END means no such point has been found. */ X corresponding = other_changed[j - 1] ? i : i_end; X X /* Move the changed region forward, so long as the X first changed line matches the following unchanged one. X This merges with following changed regions. X Do this second, so that if there are no merges, X the changed region is moved forward as far as possible. */ X X while (i != i_end && equivs[start] == equivs[i]) X { X changed[start++] = 0; X changed[i++] = 1; X while (changed[i]) X i++; X while (other_changed[++j]) X corresponding = i; X } X } X while (runlength != i - start); X X /* If possible, move the fully-merged run of changes X back to a corresponding run in the other file. */ X X while (corresponding < i) X { X changed[--start] = 1; X changed[--i] = 0; X while (other_changed[--j]) X continue; X } X } X } X} X X/* Cons an additional entry onto the front of an edit script OLD. X LINE0 and LINE1 are the first affected lines in the two files (origin 0). X DELETED is the number of lines deleted here from file 0. X INSERTED is the number of lines inserted here in file 1. X X If DELETED is 0 then LINE0 is the number of the line before X which the insertion was done; vice versa for INSERTED and LINE1. */ X Xstatic struct change * Xadd_change (lin line0, lin line1, lin deleted, lin inserted, X struct change *old) X{ X struct change *new = xmalloc (sizeof *new); X X new->line0 = line0; X new->line1 = line1; X new->inserted = inserted; X new->deleted = deleted; X new->link = old; X return new; X} X X/* Scan the tables of which lines are inserted and deleted, X producing an edit script in reverse order. */ X Xstatic struct change * Xbuild_reverse_script (struct file_data const filevec[]) X{ X struct change *script = 0; X bool *changed0 = filevec[0].changed; X bool *changed1 = filevec[1].changed; X lin len0 = filevec[0].buffered_lines; X lin len1 = filevec[1].buffered_lines; X X /* Note that changedN[len0] does exist, and is 0. */ X X lin i0 = 0, i1 = 0; X X while (i0 < len0 || i1 < len1) X { X if (changed0[i0] | changed1[i1]) X { X lin line0 = i0, line1 = i1; X X /* Find # lines changed here in each file. */ X while (changed0[i0]) ++i0; X while (changed1[i1]) ++i1; X X /* Record this change. */ X script = add_change (line0, line1, i0 - line0, i1 - line1, script); X } X X /* We have reached lines in the two files that match each other. */ X i0++, i1++; X } X X return script; X} X X/* Scan the tables of which lines are inserted and deleted, X producing an edit script in forward order. */ X Xstatic struct change * Xbuild_script (struct file_data const filevec[]) X{ X struct change *script = 0; X bool *changed0 = filevec[0].changed; X bool *changed1 = filevec[1].changed; X lin i0 = filevec[0].buffered_lines, i1 = filevec[1].buffered_lines; X X /* Note that changedN[-1] does exist, and is 0. */ X X while (i0 >= 0 || i1 >= 0) X { X if (changed0[i0 - 1] | changed1[i1 - 1]) X { X lin line0 = i0, line1 = i1; X X /* Find # lines changed here in each file. */ X while (changed0[i0 - 1]) --i0; X while (changed1[i1 - 1]) --i1; X X /* Record this change. */ X script = add_change (i0, i1, line0 - i0, line1 - i1, script); X } X X /* We have reached lines in the two files that match each other. */ X i0--, i1--; X } X X return script; X} X X/* If CHANGES, briefly report that two files differed. X Return 2 if trouble, CHANGES otherwise. */ Xstatic int Xbriefly_report (int changes, struct file_data const filevec[]) X{ X if (changes) X { X char const *label0 = file_label[0] ? file_label[0] : filevec[0].name; X char const *label1 = file_label[1] ? file_label[1] : filevec[1].name; X X if (brief) X message ("Files %s and %s differ\n", label0, label1); X else X { X message ("Binary files %s and %s differ\n", label0, label1); X changes = 2; X } X } X X return changes; X} X X/* Report the differences of two files. */ Xint Xdiff_2_files (struct comparison *cmp) X{ X lin diags; X int f; X struct change *e, *p; X struct change *script; X int changes; X X X /* If we have detected that either file is binary, X compare the two files as binary. This can happen X only when the first chunk is read. X Also, --brief without any --ignore-* options means X we can speed things up by treating the files as binary. */ X X if (read_files (cmp->file, files_can_be_treated_as_binary)) X { X /* Files with different lengths must be different. */ X if (cmp->file[0].stat.st_size != cmp->file[1].stat.st_size X && (cmp->file[0].desc < 0 || S_ISREG (cmp->file[0].stat.st_mode)) X && (cmp->file[1].desc < 0 || S_ISREG (cmp->file[1].stat.st_mode))) X changes = 1; X X /* Standard input equals itself. */ X else if (cmp->file[0].desc == cmp->file[1].desc) X changes = 0; X X else X /* Scan both files, a buffer at a time, looking for a difference. */ X { X /* Allocate same-sized buffers for both files. */ X size_t lcm_max = PTRDIFF_MAX - 1; X size_t buffer_size = X buffer_lcm (sizeof (word), X buffer_lcm (STAT_BLOCKSIZE (cmp->file[0].stat), X STAT_BLOCKSIZE (cmp->file[1].stat), X lcm_max), X lcm_max); X for (f = 0; f < 2; f++) X cmp->file[f].buffer = xrealloc (cmp->file[f].buffer, buffer_size); X X for (;; cmp->file[0].buffered = cmp->file[1].buffered = 0) X { X /* Read a buffer's worth from both files. */ X for (f = 0; f < 2; f++) X if (0 <= cmp->file[f].desc) X file_block_read (&cmp->file[f], X buffer_size - cmp->file[f].buffered); X X /* If the buffers differ, the files differ. */ X if (cmp->file[0].buffered != cmp->file[1].buffered X || memcmp (cmp->file[0].buffer, X cmp->file[1].buffer, X cmp->file[0].buffered)) X { X changes = 1; X break; X } X X /* If we reach end of file, the files are the same. */ X if (cmp->file[0].buffered != buffer_size) X { X changes = 0; X break; X } X } X } X X changes = briefly_report (changes, cmp->file); X } X else X { X /* Allocate vectors for the results of comparison: X a flag for each line of each file, saying whether that line X is an insertion or deletion. X Allocate an extra element, always 0, at each end of each vector. */ X X size_t s = cmp->file[0].buffered_lines + cmp->file[1].buffered_lines + 4; X bool *flag_space = zalloc (s * sizeof *flag_space); X cmp->file[0].changed = flag_space + 1; X cmp->file[1].changed = flag_space + cmp->file[0].buffered_lines + 3; X X /* Some lines are obviously insertions or deletions X because they don't match anything. Detect them now, and X avoid even thinking about them in the main comparison algorithm. */ X X discard_confusing_lines (cmp->file); X X /* Now do the main comparison algorithm, considering just the X undiscarded lines. */ X X xvec = cmp->file[0].undiscarded; X yvec = cmp->file[1].undiscarded; X diags = (cmp->file[0].nondiscarded_lines X + cmp->file[1].nondiscarded_lines + 3); X fdiag = xmalloc (diags * (2 * sizeof *fdiag)); X bdiag = fdiag + diags; X fdiag += cmp->file[1].nondiscarded_lines + 1; X bdiag += cmp->file[1].nondiscarded_lines + 1; X X /* Set TOO_EXPENSIVE to be approximate square root of input size, X bounded below by 256. */ X too_expensive = 1; X for (; diags != 0; diags >>= 2) X too_expensive <<= 1; X too_expensive = MAX (256, too_expensive); X X files[0] = cmp->file[0]; X files[1] = cmp->file[1]; X X compareseq (0, cmp->file[0].nondiscarded_lines, X 0, cmp->file[1].nondiscarded_lines, minimal); X X free (fdiag - (cmp->file[1].nondiscarded_lines + 1)); X X /* Modify the results slightly to make them prettier X in cases where that can validly be done. */ X X shift_boundaries (cmp->file); X X /* Get the results of comparison in the form of a chain X of `struct change's -- an edit script. */ X X if (output_style == OUTPUT_ED) X script = build_reverse_script (cmp->file); X else X script = build_script (cmp->file); X X /* Set CHANGES if we had any diffs. X If some changes are ignored, we must scan the script to decide. */ X if (ignore_blank_lines || ignore_regexp.fastmap) X { X struct change *next = script; X changes = 0; X X while (next && changes == 0) X { X struct change *this, *end; X lin first0, last0, first1, last1; X X /* Find a set of changes that belong together. */ X this = next; X end = find_change (next); X X /* Disconnect them from the rest of the changes, making them X a hunk, and remember the rest for next iteration. */ X next = end->link; X end->link = 0; X X /* Determine whether this hunk is really a difference. */ X if (analyze_hunk (this, &first0, &last0, &first1, &last1)) X changes = 1; X X /* Reconnect the script so it will all be freed properly. */ X end->link = next; X } X } X else X changes = (script != 0); X X if (brief) X changes = briefly_report (changes, cmp->file); X else X { X if (changes | !no_diff_means_no_output) X { X /* Record info for starting up output, X to be used if and when we have some output to print. */ X setup_output (file_label[0] ? file_label[0] : cmp->file[0].name, X file_label[1] ? file_label[1] : cmp->file[1].name, X cmp->parent != 0); X X switch (output_style) X { X case OUTPUT_CONTEXT: X print_context_script (script, 0); X break; X X case OUTPUT_UNIFIED: X print_context_script (script, 1); X break; X X case OUTPUT_ED: X print_ed_script (script); X break; X X case OUTPUT_FORWARD_ED: X pr_forward_ed_script (script); X break; X X case OUTPUT_RCS: X print_rcs_script (script); X break; X X case OUTPUT_NORMAL: X print_normal_script (script); X break; X X case OUTPUT_IFDEF: X print_ifdef_script (script); X break; X X case OUTPUT_SDIFF: X print_sdiff_script (script); X break; X X default: X abort (); X } X X finish_output (); X } X } X X free (cmp->file[0].undiscarded); X X free (flag_space); X X for (f = 0; f < 2; f++) X { X free (cmp->file[f].equivs); X free (cmp->file[f].linbuf + cmp->file[f].linbuf_base); X } X X for (e = script; e; e = p) X { X p = e->link; X free (e); X } X X if (! ROBUST_OUTPUT_STYLE (output_style)) X for (f = 0; f < 2; ++f) X if (cmp->file[f].missing_newline) X { X error (0, 0, "%s: %s\n", X file_label[f] ? file_label[f] : cmp->file[f].name, X _("No newline at end of file")); X changes = 2; X } X } X X if (cmp->file[0].buffer != cmp->file[1].buffer) X free (cmp->file[0].buffer); X free (cmp->file[1].buffer); X X return changes; X} END-of-contrib/diff/src/analyze.c echo x - contrib/diff/src/context.c sed 's/^X//' >contrib/diff/src/context.c << 'END-of-contrib/diff/src/context.c' X/* Context-format output routines for GNU DIFF. X X Copyright (C) 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1998, 2001, X 2002 Free Software Foundation, Inc. X X This file is part of GNU DIFF. X X GNU DIFF is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X GNU DIFF is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; see the file COPYING. X If not, write to the Free Software Foundation, X 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#include "diff.h" X#include X#include X X#ifdef ST_MTIM_NSEC X# define TIMESPEC_NS(timespec) ((timespec).ST_MTIM_NSEC) X#else X# define TIMESPEC_NS(timespec) 0 X#endif X Xsize_t nstrftime (char *, size_t, char const *, struct tm const *, int, int); X Xstatic char const *find_function (char const * const *, lin); Xstatic struct change *find_hunk (struct change *); Xstatic void mark_ignorable (struct change *); Xstatic void pr_context_hunk (struct change *); Xstatic void pr_unidiff_hunk (struct change *); X X/* Last place find_function started searching from. */ Xstatic lin find_function_last_search; X X/* The value find_function returned when it started searching there. */ Xstatic lin find_function_last_match; X X/* Print a label for a context diff, with a file name and date or a label. */ X Xstatic void Xprint_context_label (char const *mark, X struct file_data *inf, X char const *label) X{ X if (label) X fprintf (outfile, "%s %s\n", mark, label); X else X { X char buf[MAX (INT_STRLEN_BOUND (int) + 32, X INT_STRLEN_BOUND (time_t) + 11)]; X struct tm const *tm = localtime (&inf->stat.st_mtime); X int nsec = TIMESPEC_NS (inf->stat.st_mtim); X if (! (tm && nstrftime (buf, sizeof buf, time_format, tm, 0, nsec))) X { X long sec = inf->stat.st_mtime; X verify (info_preserved, sizeof inf->stat.st_mtime <= sizeof sec); X sprintf (buf, "%ld.%.9d", sec, nsec); X } X fprintf (outfile, "%s %s\t%s\n", mark, inf->name, buf); X } X} X X/* Print a header for a context diff, with the file names and dates. */ X Xvoid Xprint_context_header (struct file_data inf[], bool unidiff) X{ X if (unidiff) X { X print_context_label ("---", &inf[0], file_label[0]); X print_context_label ("+++", &inf[1], file_label[1]); X } X else X { X print_context_label ("***", &inf[0], file_label[0]); X print_context_label ("---", &inf[1], file_label[1]); X } X} X X/* Print an edit script in context format. */ X Xvoid Xprint_context_script (struct change *script, bool unidiff) X{ X if (ignore_blank_lines || ignore_regexp.fastmap) X mark_ignorable (script); X else X { X struct change *e; X for (e = script; e; e = e->link) X e->ignore = 0; X } X X find_function_last_search = - files[0].prefix_lines; X find_function_last_match = LIN_MAX; X X if (unidiff) X print_script (script, find_hunk, pr_unidiff_hunk); X else X print_script (script, find_hunk, pr_context_hunk); X} X X/* Print a pair of line numbers with a comma, translated for file FILE. X If the second number is not greater, use the first in place of it. X X Args A and B are internal line numbers. X We print the translated (real) line numbers. */ X Xstatic void Xprint_context_number_range (struct file_data const *file, lin a, lin b) X{ X long trans_a, trans_b; X translate_range (file, a, b, &trans_a, &trans_b); X X /* We can have B <= A in the case of a range of no lines. X In this case, we should print the line number before the range, X which is B. X X POSIX 1003.1-2001 requires two line numbers separated by a comma X even if the line numbers are the same. However, this does not X match existing practice and is surely an error in the X specification. */ X X if (trans_b <= trans_a) X fprintf (outfile, "%ld", trans_b); X else X fprintf (outfile, "%ld,%ld", trans_a, trans_b); X} X X/* Print FUNCTION in a context header. */ Xstatic void Xprint_context_function (FILE *out, char const *function) X{ X int i; X putc (' ', out); X for (i = 0; i < 40 && function[i] != '\n'; i++) X continue; X fwrite (function, 1, i, out); X} X X/* Print a portion of an edit script in context format. X HUNK is the beginning of the portion to be printed. X The end is marked by a `link' that has been nulled out. X X Prints out lines from both files, and precedes each X line with the appropriate flag-character. */ X Xstatic void Xpr_context_hunk (struct change *hunk) X{ X lin first0, last0, first1, last1, i; X char const *prefix; X char const *function; X FILE *out; X X /* Determine range of line numbers involved in each file. */ X X enum changes changes = analyze_hunk (hunk, &first0, &last0, &first1, &last1); X if (! changes) X return; X X /* Include a context's width before and after. */ X X i = - files[0].prefix_lines; X first0 = MAX (first0 - context, i); X first1 = MAX (first1 - context, i); X if (last0 < files[0].valid_lines - context) X last0 += context; X else X last0 = files[0].valid_lines - 1; X if (last1 < files[1].valid_lines - context) X last1 += context; X else X last1 = files[1].valid_lines - 1; X X /* If desired, find the preceding function definition line in file 0. */ X function = 0; X if (function_regexp.fastmap) X function = find_function (files[0].linbuf, first0); X X begin_output (); X out = outfile; X X fprintf (out, "***************"); X X if (function) X print_context_function (out, function); X X fprintf (out, "\n*** "); X print_context_number_range (&files[0], first0, last0); X fprintf (out, " ****\n"); X X if (changes & OLD) X { X struct change *next = hunk; X X for (i = first0; i <= last0; i++) X { X /* Skip past changes that apply (in file 0) X only to lines before line I. */ X X while (next && next->line0 + next->deleted <= i) X next = next->link; X X /* Compute the marking for line I. */ X X prefix = " "; X if (next && next->line0 <= i) X /* The change NEXT covers this line. X If lines were inserted here in file 1, this is "changed". X Otherwise it is "deleted". */ X prefix = (next->inserted > 0 ? "!" : "-"); X X print_1_line (prefix, &files[0].linbuf[i]); X } X } X X fprintf (out, "--- "); X print_context_number_range (&files[1], first1, last1); X fprintf (out, " ----\n"); X X if (changes & NEW) X { X struct change *next = hunk; X X for (i = first1; i <= last1; i++) X { X /* Skip past changes that apply (in file 1) X only to lines before line I. */ X X while (next && next->line1 + next->inserted <= i) X next = next->link; X X /* Compute the marking for line I. */ X X prefix = " "; X if (next && next->line1 <= i) X /* The change NEXT covers this line. X If lines were deleted here in file 0, this is "changed". X Otherwise it is "inserted". */ X prefix = (next->deleted > 0 ? "!" : "+"); X X print_1_line (prefix, &files[1].linbuf[i]); X } X } X} X X/* Print a pair of line numbers with a comma, translated for file FILE. X If the second number is smaller, use the first in place of it. X If the numbers are equal, print just one number. X X Args A and B are internal line numbers. X We print the translated (real) line numbers. */ X Xstatic void Xprint_unidiff_number_range (struct file_data const *file, lin a, lin b) X{ X long trans_a, trans_b; X translate_range (file, a, b, &trans_a, &trans_b); X X /* We can have B < A in the case of a range of no lines. X In this case, we should print the line number before the range, X which is B. */ X if (trans_b <= trans_a) X fprintf (outfile, trans_b < trans_a ? "%ld,0" : "%ld", trans_b); X else X fprintf (outfile, "%ld,%ld", trans_a, trans_b - trans_a + 1); X} X X/* Print a portion of an edit script in unidiff format. X HUNK is the beginning of the portion to be printed. X The end is marked by a `link' that has been nulled out. X X Prints out lines from both files, and precedes each X line with the appropriate flag-character. */ X Xstatic void Xpr_unidiff_hunk (struct change *hunk) X{ X lin first0, last0, first1, last1; X lin i, j, k; X struct change *next; X char const *function; X FILE *out; X X /* Determine range of line numbers involved in each file. */ X X if (! analyze_hunk (hunk, &first0, &last0, &first1, &last1)) X return; X X /* Include a context's width before and after. */ X X i = - files[0].prefix_lines; X first0 = MAX (first0 - context, i); X first1 = MAX (first1 - context, i); X if (last0 < files[0].valid_lines - context) X last0 += context; X else X last0 = files[0].valid_lines - 1; X if (last1 < files[1].valid_lines - context) X last1 += context; X else X last1 = files[1].valid_lines - 1; X X /* If desired, find the preceding function definition line in file 0. */ X function = 0; X if (function_regexp.fastmap) X function = find_function (files[0].linbuf, first0); X X begin_output (); X out = outfile; X X fprintf (out, "@@ -"); X print_unidiff_number_range (&files[0], first0, last0); X fprintf (out, " +"); X print_unidiff_number_range (&files[1], first1, last1); X fprintf (out, " @@"); X X if (function) X print_context_function (out, function); X X putc ('\n', out); X X next = hunk; X i = first0; X j = first1; X X while (i <= last0 || j <= last1) X { X X /* If the line isn't a difference, output the context from file 0. */ X X if (!next || i < next->line0) X { X putc (initial_tab ? '\t' : ' ', out); X print_1_line (0, &files[0].linbuf[i++]); X j++; X } X else X { X /* For each difference, first output the deleted part. */ X X k = next->deleted; X while (k--) X { X putc ('-', out); X if (initial_tab) X putc ('\t', out); X print_1_line (0, &files[0].linbuf[i++]); X } X X /* Then output the inserted part. */ X X k = next->inserted; X while (k--) X { X putc ('+', out); X if (initial_tab) X putc ('\t', out); X print_1_line (0, &files[1].linbuf[j++]); X } X X /* We're done with this hunk, so on to the next! */ X X next = next->link; X } X } X} X X/* Scan a (forward-ordered) edit script for the first place that more than X 2*CONTEXT unchanged lines appear, and return a pointer X to the `struct change' for the last change before those lines. */ X Xstatic struct change * Xfind_hunk (struct change *start) X{ X struct change *prev; X lin top0, top1; X lin thresh; X X /* Threshold distance is 2 * CONTEXT + 1 between two non-ignorable X changes, but only CONTEXT if one is ignorable. Watch out for X integer overflow, though. */ X lin non_ignorable_threshold = X (LIN_MAX - 1) / 2 < context ? LIN_MAX : 2 * context + 1; X lin ignorable_threshold = context; X X do X { X /* Compute number of first line in each file beyond this changed. */ X top0 = start->line0 + start->deleted; X top1 = start->line1 + start->inserted; X prev = start; X start = start->link; X thresh = (prev->ignore || (start && start->ignore) X ? ignorable_threshold X : non_ignorable_threshold); X /* It is not supposed to matter which file we check in the end-test. X If it would matter, crash. */ X if (start && start->line0 - top0 != start->line1 - top1) X abort (); X } while (start X /* Keep going if less than THRESH lines X elapse before the affected line. */ X && start->line0 - top0 < thresh); X X return prev; X} X X/* Set the `ignore' flag properly in each change in SCRIPT. X It should be 1 if all the lines inserted or deleted in that change X are ignorable lines. */ X Xstatic void Xmark_ignorable (struct change *script) X{ X while (script) X { X struct change *next = script->link; X lin first0, last0, first1, last1; X X /* Turn this change into a hunk: detach it from the others. */ X script->link = 0; X X /* Determine whether this change is ignorable. */ X script->ignore = ! analyze_hunk (script, X &first0, &last0, &first1, &last1); X X /* Reconnect the chain as before. */ X script->link = next; X X /* Advance to the following change. */ X script = next; X } X} X X/* Find the last function-header line in LINBUF prior to line number LINENUM. X This is a line containing a match for the regexp in `function_regexp'. X Return the address of the text, or 0 if no function-header is found. */ X Xstatic char const * Xfind_function (char const * const *linbuf, lin linenum) X{ X lin i = linenum; X lin last = find_function_last_search; X find_function_last_search = i; X X while (last <= --i) X { X /* See if this line is what we want. */ X char const *line = linbuf[i]; X size_t linelen = linbuf[i + 1] - line - 1; X X /* FIXME: re_search's size args should be size_t, not int. */ X int len = MIN (linelen, INT_MAX); X X if (0 <= re_search (&function_regexp, line, len, 0, len, 0)) X { X find_function_last_match = i; X return line; X } X } X /* If we search back to where we started searching the previous time, X find the line we found last time. */ X if (find_function_last_match != LIN_MAX) X return linbuf[find_function_last_match]; X X return 0; X} END-of-contrib/diff/src/context.c echo x - contrib/diff/src/diff.c sed 's/^X//' >contrib/diff/src/diff.c << 'END-of-contrib/diff/src/diff.c' X/* diff - compare files line by line X X Copyright (C) 1988, 1989, 1992, 1993, 1994, 1996, 1998, 2001, 2002 X Free Software Foundation, Inc. X X This file is part of GNU DIFF. X X GNU DIFF is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X GNU DIFF is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. X See the GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with GNU DIFF; see the file COPYING. X If not, write to the Free Software Foundation, X 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#define GDIFF_MAIN X#include "diff.h" X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X Xstatic char const authorship_msgid[] = X N_("Written by Paul Eggert, Mike Haertel, David Hayes,\n\ XRichard Stallman, and Len Tower."); X Xstatic char const copyright_string[] = X "Copyright (C) 2002 Free Software Foundation, Inc."; X X#ifndef GUTTER_WIDTH_MINIMUM X# define GUTTER_WIDTH_MINIMUM 3 X#endif X Xstruct regexp_list X{ X char *regexps; /* chars representing disjunction of the regexps */ X size_t len; /* chars used in `regexps' */ X size_t size; /* size malloc'ed for `regexps'; 0 if not malloc'ed */ X bool multiple_regexps;/* Does `regexps' represent a disjunction? */ X struct re_pattern_buffer *buf; X}; X Xstatic int compare_files (struct comparison const *, char const *, char const *); Xstatic void add_regexp (struct regexp_list *, char const *); Xstatic void summarize_regexp_list (struct regexp_list *); Xstatic void specify_style (enum output_style); Xstatic void specify_value (char const **, char const *, char const *); Xstatic void try_help (char const *, char const *) __attribute__((noreturn)); Xstatic void check_stdout (void); Xstatic void usage (void); X X/* If comparing directories, compare their common subdirectories X recursively. */ Xstatic bool recursive; X X/* In context diffs, show previous lines that match these regexps. */ Xstatic struct regexp_list function_regexp_list; X X/* Ignore changes affecting only lines that match these regexps. */ Xstatic struct regexp_list ignore_regexp_list; X X#if HAVE_SETMODE_DOS X/* Use binary I/O when reading and writing data (--binary). X On POSIX hosts, this has no effect. */ Xstatic bool binary; X#endif X X/* When comparing directories, if a file appears only in one X directory, treat it as present but empty in the other (-N). X Then `patch' would create the file with appropriate contents. */ Xstatic bool new_file; X X/* When comparing directories, if a file appears only in the second X directory of the two, treat it as present but empty in the other X (--unidirectional-new-file). X Then `patch' would create the file with appropriate contents. */ Xstatic bool unidirectional_new_file; X X/* Report files compared that are the same (-s). X Normally nothing is output when that happens. */ Xstatic bool report_identical_files; X X X/* Return a string containing the command options with which diff was invoked. X Spaces appear between what were separate ARGV-elements. X There is a space at the beginning but none at the end. X If there were no options, the result is an empty string. X X Arguments: OPTIONVEC, a vector containing separate ARGV-elements, and COUNT, X the length of that vector. */ X Xstatic char * Xoption_list (char **optionvec, int count) X{ X int i; X size_t size = 1; X char *result; X char *p; X X for (i = 0; i < count; i++) X size += 1 + quote_system_arg ((char *) 0, optionvec[i]); X X p = result = xmalloc (size); X X for (i = 0; i < count; i++) X { X *p++ = ' '; X p += quote_system_arg (p, optionvec[i]); X } X X *p = 0; X return result; X} X X X/* Return an option value suitable for add_exclude. */ X Xstatic int Xexclude_options (void) X{ X return EXCLUDE_WILDCARDS | (ignore_file_name_case ? FNM_CASEFOLD : 0); X} X Xstatic char const shortopts[] = X"0123456789abBcC:dD:eEfF:hHiI:lL:nNpPqrsS:tTuU:vwW:x:X:y"; X X/* Values for long options that do not have single-letter equivalents. */ Xenum X{ X BINARY_OPTION = CHAR_MAX + 1, X FROM_FILE_OPTION, X HELP_OPTION, X HORIZON_LINES_OPTION, X IGNORE_FILE_NAME_CASE_OPTION, X INHIBIT_HUNK_MERGE_OPTION, X LEFT_COLUMN_OPTION, X LINE_FORMAT_OPTION, X NO_IGNORE_FILE_NAME_CASE_OPTION, X NORMAL_OPTION, X SDIFF_MERGE_ASSIST_OPTION, X STRIP_TRAILING_CR_OPTION, X SUPPRESS_COMMON_LINES_OPTION, X TO_FILE_OPTION, X X /* These options must be in sequence. */ X UNCHANGED_LINE_FORMAT_OPTION, X OLD_LINE_FORMAT_OPTION, X NEW_LINE_FORMAT_OPTION, X X /* These options must be in sequence. */ X UNCHANGED_GROUP_FORMAT_OPTION, X OLD_GROUP_FORMAT_OPTION, X NEW_GROUP_FORMAT_OPTION, X CHANGED_GROUP_FORMAT_OPTION X}; X Xstatic char const group_format_option[][sizeof "--unchanged-group-format"] = X { X "--unchanged-group-format", X "--old-group-format", X "--new-group-format", X "--changed-group-format" X }; X Xstatic char const line_format_option[][sizeof "--unchanged-line-format"] = X { X "--unchanged-line-format", X "--old-line-format", X "--new-line-format" X }; X Xstatic struct option const longopts[] = X{ X {"binary", 0, 0, BINARY_OPTION}, X {"brief", 0, 0, 'q'}, X {"changed-group-format", 1, 0, CHANGED_GROUP_FORMAT_OPTION}, X {"context", 2, 0, 'C'}, X {"ed", 0, 0, 'e'}, X {"exclude", 1, 0, 'x'}, X {"exclude-from", 1, 0, 'X'}, X {"expand-tabs", 0, 0, 't'}, X {"forward-ed", 0, 0, 'f'}, X {"from-file", 1, 0, FROM_FILE_OPTION}, X {"help", 0, 0, HELP_OPTION}, X {"horizon-lines", 1, 0, HORIZON_LINES_OPTION}, X {"ifdef", 1, 0, 'D'}, X {"ignore-all-space", 0, 0, 'w'}, X {"ignore-blank-lines", 0, 0, 'B'}, X {"ignore-case", 0, 0, 'i'}, X {"ignore-file-name-case", 0, 0, IGNORE_FILE_NAME_CASE_OPTION}, X {"ignore-matching-lines", 1, 0, 'I'}, X {"ignore-space-change", 0, 0, 'b'}, X {"ignore-tab-expansion", 0, 0, 'E'}, X {"inhibit-hunk-merge", 0, 0, INHIBIT_HUNK_MERGE_OPTION}, X {"initial-tab", 0, 0, 'T'}, X {"label", 1, 0, 'L'}, X {"left-column", 0, 0, LEFT_COLUMN_OPTION}, X {"line-format", 1, 0, LINE_FORMAT_OPTION}, X {"minimal", 0, 0, 'd'}, X {"new-file", 0, 0, 'N'}, X {"new-group-format", 1, 0, NEW_GROUP_FORMAT_OPTION}, X {"new-line-format", 1, 0, NEW_LINE_FORMAT_OPTION}, X {"no-ignore-file-name-case", 0, 0, NO_IGNORE_FILE_NAME_CASE_OPTION}, X {"normal", 0, 0, NORMAL_OPTION}, X {"old-group-format", 1, 0, OLD_GROUP_FORMAT_OPTION}, X {"old-line-format", 1, 0, OLD_LINE_FORMAT_OPTION}, X {"paginate", 0, 0, 'l'}, X {"rcs", 0, 0, 'n'}, X {"recursive", 0, 0, 'r'}, X {"report-identical-files", 0, 0, 's'}, X {"sdiff-merge-assist", 0, 0, SDIFF_MERGE_ASSIST_OPTION}, X {"show-c-function", 0, 0, 'p'}, X {"show-function-line", 1, 0, 'F'}, X {"side-by-side", 0, 0, 'y'}, X {"speed-large-files", 0, 0, 'H'}, X {"starting-file", 1, 0, 'S'}, X {"strip-trailing-cr", 0, 0, STRIP_TRAILING_CR_OPTION}, X {"suppress-common-lines", 0, 0, SUPPRESS_COMMON_LINES_OPTION}, X {"text", 0, 0, 'a'}, X {"to-file", 1, 0, TO_FILE_OPTION}, X {"unchanged-group-format", 1, 0, UNCHANGED_GROUP_FORMAT_OPTION}, X {"unchanged-line-format", 1, 0, UNCHANGED_LINE_FORMAT_OPTION}, X {"unidirectional-new-file", 0, 0, 'P'}, X {"unified", 2, 0, 'U'}, X {"version", 0, 0, 'v'}, X {"width", 1, 0, 'W'}, X {0, 0, 0, 0} X}; X Xint Xmain (int argc, char **argv) X{ X int exit_status = EXIT_SUCCESS; X int c; X int i; X int prev = -1; X lin ocontext = -1; X bool explicit_context = 0; X int width = 0; X bool show_c_function = 0; X char const *from_file = 0; X char const *to_file = 0; X uintmax_t numval; X char *numend; X X /* Do our initializations. */ X exit_failure = 2; X initialize_main (&argc, &argv); X program_name = argv[0]; X setlocale (LC_ALL, ""); X bindtextdomain (PACKAGE, LOCALEDIR); X textdomain (PACKAGE); X c_stack_action (c_stack_die); X function_regexp_list.buf = &function_regexp; X ignore_regexp_list.buf = &ignore_regexp; X re_set_syntax (RE_SYNTAX_GREP | RE_NO_POSIX_BACKTRACKING); X excluded = new_exclude (); X X /* Decode the options. */ X X while ((c = getopt_long (argc, argv, shortopts, longopts, 0)) != -1) X { X switch (c) X { X case 0: X break; X X case '0': X case '1': X case '2': X case '3': X case '4': X case '5': X case '6': X case '7': X case '8': X case '9': X if (! ISDIGIT (prev)) X ocontext = c - '0'; X else if (LIN_MAX / 10 < ocontext X || ((ocontext = 10 * ocontext + c - '0') < 0)) X ocontext = LIN_MAX; X break; X X case 'a': X text = 1; X break; X X case 'b': X if (ignore_white_space < IGNORE_SPACE_CHANGE) X ignore_white_space = IGNORE_SPACE_CHANGE; X break; X X case 'B': X ignore_blank_lines = 1; X break; X X case 'C': /* +context[=lines] */ X case 'U': /* +unified[=lines] */ X { X if (optarg) X { X numval = strtoumax (optarg, &numend, 10); X if (*numend) X try_help ("invalid context length `%s'", optarg); X if (LIN_MAX < numval) X numval = LIN_MAX; X } X else X numval = 3; X X specify_style (c == 'U' ? OUTPUT_UNIFIED : OUTPUT_CONTEXT); X if (context < numval) X context = numval; X explicit_context = 1; X } X break; X X case 'c': X specify_style (OUTPUT_CONTEXT); X if (context < 3) X context = 3; X break; X X case 'd': X minimal = 1; X break; X X case 'D': X specify_style (OUTPUT_IFDEF); X { X static char const C_ifdef_group_formats[] = X "%%=%c#ifndef %s\n%%<#endif /* ! %s */\n%c#ifdef %s\n%%>#endif /* %s */\n%c#ifndef %s\n%%<#else /* %s */\n%%>#endif /* %s */\n"; X char *b = xmalloc (sizeof C_ifdef_group_formats X + 7 * strlen (optarg) - 14 /* 7*"%s" */ X - 8 /* 5*"%%" + 3*"%c" */); X sprintf (b, C_ifdef_group_formats, X 0, X optarg, optarg, 0, X optarg, optarg, 0, X optarg, optarg, optarg); X for (i = 0; i < sizeof group_format / sizeof *group_format; i++) X { X specify_value (&group_format[i], b, "-D"); X b += strlen (b) + 1; X } X } X break; X X case 'e': X specify_style (OUTPUT_ED); X break; X X case 'E': X if (ignore_white_space < IGNORE_TAB_EXPANSION) X ignore_white_space = IGNORE_TAB_EXPANSION; X break; X X case 'f': X specify_style (OUTPUT_FORWARD_ED); X break; X X case 'F': X add_regexp (&function_regexp_list, optarg); X break; X X case 'h': X /* Split the files into chunks for faster processing. X Usually does not change the result. X X This currently has no effect. */ X break; X X case 'H': X speed_large_files = 1; X break; X X case 'i': X ignore_case = 1; X break; X X case 'I': X add_regexp (&ignore_regexp_list, optarg); X break; X X case 'l': X if (!pr_program[0]) X try_help ("pagination not supported on this host", 0); X paginate = 1; X#ifdef SIGCHLD X /* Pagination requires forking and waiting, and X System V fork+wait does not work if SIGCHLD is ignored. */ X signal (SIGCHLD, SIG_DFL); X#endif X break; X X case 'L': X if (!file_label[0]) X file_label[0] = optarg; X else if (!file_label[1]) X file_label[1] = optarg; X else X fatal ("too many file label options"); X break; X X case 'n': X specify_style (OUTPUT_RCS); X break; X X case 'N': X new_file = 1; X break; X X case 'p': X show_c_function = 1; X add_regexp (&function_regexp_list, "^[[:alpha:]$_]"); X break; X X case 'P': X unidirectional_new_file = 1; X break; X X case 'q': X brief = 1; X break; X X case 'r': X recursive = 1; X break; X X case 's': X report_identical_files = 1; X break; X X case 'S': X specify_value (&starting_file, optarg, "-S"); X break; X X case 't': X expand_tabs = 1; X break; X X case 'T': X initial_tab = 1; X break; X X case 'u': X specify_style (OUTPUT_UNIFIED); X if (context < 3) X context = 3; X break; X X case 'v': X printf ("diff %s\n%s\n\n%s\n\n%s\n", X version_string, copyright_string, X _(free_software_msgid), _(authorship_msgid)); X check_stdout (); X return EXIT_SUCCESS; X X case 'w': X ignore_white_space = IGNORE_ALL_SPACE; X break; X X case 'x': X add_exclude (excluded, optarg, exclude_options ()); X break; X X case 'X': X if (add_exclude_file (add_exclude, excluded, optarg, X exclude_options (), '\n')) X pfatal_with_name (optarg); X break; X X case 'y': X specify_style (OUTPUT_SDIFF); X break; X X case 'W': X numval = strtoumax (optarg, &numend, 10); X if (! (0 < numval && numval <= INT_MAX) || *numend) X try_help ("invalid width `%s'", optarg); X if (width != numval) X { X if (width) X fatal ("conflicting width options"); X width = numval; X } X break; X X case BINARY_OPTION: X#if HAVE_SETMODE_DOS X binary = 1; X set_binary_mode (STDOUT_FILENO, 1); X#endif X break; X X case FROM_FILE_OPTION: X specify_value (&from_file, optarg, "--from-file"); X break; X X case HELP_OPTION: X usage (); X check_stdout (); X return EXIT_SUCCESS; X X case HORIZON_LINES_OPTION: X numval = strtoumax (optarg, &numend, 10); X if (*numend) X try_help ("invalid horizon length `%s'", optarg); X horizon_lines = MAX (horizon_lines, MIN (numval, LIN_MAX)); X break; X X case IGNORE_FILE_NAME_CASE_OPTION: X ignore_file_name_case = 1; X break; X X case INHIBIT_HUNK_MERGE_OPTION: X /* This option is obsolete, but accept it for backward X compatibility. */ X break; X X case LEFT_COLUMN_OPTION: X left_column = 1; X break; X X case LINE_FORMAT_OPTION: X specify_style (OUTPUT_IFDEF); X for (i = 0; i < sizeof line_format / sizeof *line_format; i++) X specify_value (&line_format[i], optarg, "--line-format"); X break; X X case NO_IGNORE_FILE_NAME_CASE_OPTION: X ignore_file_name_case = 0; X break; X X case NORMAL_OPTION: X specify_style (OUTPUT_NORMAL); X break; X X case SDIFF_MERGE_ASSIST_OPTION: X specify_style (OUTPUT_SDIFF); X sdiff_merge_assist = 1; X break; X X case STRIP_TRAILING_CR_OPTION: X strip_trailing_cr = 1; X break; X X case SUPPRESS_COMMON_LINES_OPTION: X suppress_common_lines = 1; X break; X X case TO_FILE_OPTION: X specify_value (&to_file, optarg, "--to-file"); X break; X X case UNCHANGED_LINE_FORMAT_OPTION: X case OLD_LINE_FORMAT_OPTION: X case NEW_LINE_FORMAT_OPTION: X specify_style (OUTPUT_IFDEF); X c -= UNCHANGED_LINE_FORMAT_OPTION; X specify_value (&line_format[c], optarg, line_format_option[c]); X break; X X case UNCHANGED_GROUP_FORMAT_OPTION: X case OLD_GROUP_FORMAT_OPTION: X case NEW_GROUP_FORMAT_OPTION: X case CHANGED_GROUP_FORMAT_OPTION: X specify_style (OUTPUT_IFDEF); X c -= UNCHANGED_GROUP_FORMAT_OPTION; X specify_value (&group_format[c], optarg, group_format_option[c]); X break; X X default: X try_help (0, 0); X } X prev = c; X } X X if (output_style == OUTPUT_UNSPECIFIED) X { X if (show_c_function) X { X specify_style (OUTPUT_CONTEXT); X if (ocontext < 0) X context = 3; X } X else X specify_style (OUTPUT_NORMAL); X } X X if (output_style != OUTPUT_CONTEXT || hard_locale (LC_TIME)) X time_format = "%Y-%m-%d %H:%M:%S.%N %z"; X else X { X /* See POSIX 1003.1-2001 for this format. */ X time_format = "%a %b %e %T %Y"; X } X X if (0 <= ocontext) X { X bool modern_usage = 200112 <= posix2_version (); X X if ((output_style == OUTPUT_CONTEXT X || output_style == OUTPUT_UNIFIED) X && (context < ocontext X || (ocontext < context && ! explicit_context))) X { X if (modern_usage) X { X error (0, 0, X _("`-%ld' option is obsolete; use `-%c %ld'"), X (long) ocontext, X output_style == OUTPUT_CONTEXT ? 'C' : 'U', X (long) ocontext); X try_help (0, 0); X } X context = ocontext; X } X else X { X if (modern_usage) X { X error (0, 0, _("`-%ld' option is obsolete; omit it"), X (long) ocontext); X try_help (0, 0); X } X } X } X X { X /* X * We maximize first the half line width, and then the gutter width, X * according to the following constraints: X * 1. Two half lines plus a gutter must fit in a line. X * 2. If the half line width is nonzero: X * a. The gutter width is at least GUTTER_WIDTH_MINIMUM. X * b. If tabs are not expanded to spaces, X * a half line plus a gutter is an integral number of tabs, X * so that tabs in the right column line up. X */ X unsigned int t = expand_tabs ? 1 : TAB_WIDTH; X int w = width ? width : 130; X int off = (w + t + GUTTER_WIDTH_MINIMUM) / (2 * t) * t; X sdiff_half_width = MAX (0, MIN (off - GUTTER_WIDTH_MINIMUM, w - off)), X sdiff_column2_offset = sdiff_half_width ? off : w; X } X X /* Make the horizon at least as large as the context, so that X shift_boundaries has more freedom to shift the first and last hunks. */ X if (horizon_lines < context) X horizon_lines = context; X X summarize_regexp_list (&function_regexp_list); X summarize_regexp_list (&ignore_regexp_list); X X if (output_style == OUTPUT_IFDEF) X { X for (i = 0; i < sizeof line_format / sizeof *line_format; i++) X if (!line_format[i]) X line_format[i] = "%l\n"; X if (!group_format[OLD]) X group_format[OLD] X = group_format[CHANGED] ? group_format[CHANGED] : "%<"; X if (!group_format[NEW]) X group_format[NEW] X = group_format[CHANGED] ? group_format[CHANGED] : "%>"; X if (!group_format[UNCHANGED]) X group_format[UNCHANGED] = "%="; X if (!group_format[CHANGED]) X group_format[CHANGED] = concat (group_format[OLD], X group_format[NEW], ""); X } X X no_diff_means_no_output = X (output_style == OUTPUT_IFDEF ? X (!*group_format[UNCHANGED] X || (strcmp (group_format[UNCHANGED], "%=") == 0 X && !*line_format[UNCHANGED])) X : (output_style != OUTPUT_SDIFF) | suppress_common_lines); X X files_can_be_treated_as_binary = X (brief X & ~ (ignore_blank_lines | ignore_case | strip_trailing_cr X | (ignore_regexp_list.regexps || ignore_white_space))); X X switch_string = option_list (argv + 1, optind - 1); X X if (from_file) X { X if (to_file) X fatal ("--from-file and --to-file both specified"); X else X for (; optind < argc; optind++) X { X int status = compare_files ((struct comparison *) 0, X from_file, argv[optind]); X if (exit_status < status) X exit_status = status; X } X } X else X { X if (to_file) X for (; optind < argc; optind++) X { X int status = compare_files ((struct comparison *) 0, X argv[optind], to_file); X if (exit_status < status) X exit_status = status; X } X else X { X if (argc - optind != 2) X { X if (argc - optind < 2) X try_help ("missing operand after `%s'", argv[argc - 1]); X else X try_help ("extra operand `%s'", argv[optind + 2]); X } X X exit_status = compare_files ((struct comparison *) 0, X argv[optind], argv[optind + 1]); X } X } X X /* Print any messages that were saved up for last. */ X print_message_queue (); X X check_stdout (); X exit (exit_status); X return exit_status; X} X X/* Append to REGLIST the regexp PATTERN. */ X Xstatic void Xadd_regexp (struct regexp_list *reglist, char const *pattern) X{ X size_t patlen = strlen (pattern); X char const *m = re_compile_pattern (pattern, patlen, reglist->buf); X X if (m != 0) X error (0, 0, "%s: %s", pattern, m); X else X { X char *regexps = reglist->regexps; X size_t len = reglist->len; X bool multiple_regexps = reglist->multiple_regexps = regexps != 0; X size_t newlen = reglist->len = len + 2 * multiple_regexps + patlen; X size_t size = reglist->size; X X if (size <= newlen) X { X if (!size) X size = 1; X X do size *= 2; X while (size <= newlen); X X reglist->size = size; X reglist->regexps = regexps = xrealloc (regexps, size); X } X if (multiple_regexps) X { X regexps[len++] = '\\'; X regexps[len++] = '|'; X } X memcpy (regexps + len, pattern, patlen + 1); X } X} X X/* Ensure that REGLIST represents the disjunction of its regexps. X This is done here, rather than earlier, to avoid O(N^2) behavior. */ X Xstatic void Xsummarize_regexp_list (struct regexp_list *reglist) X{ X if (reglist->regexps) X { X /* At least one regexp was specified. Allocate a fastmap for it. */ X reglist->buf->fastmap = xmalloc (1 << CHAR_BIT); X if (reglist->multiple_regexps) X { X /* Compile the disjunction of the regexps. X (If just one regexp was specified, it is already compiled.) */ X char const *m = re_compile_pattern (reglist->regexps, reglist->len, X reglist->buf); X if (m != 0) X error (EXIT_TROUBLE, 0, "%s: %s", reglist->regexps, m); X } X } X} X Xstatic void Xtry_help (char const *reason_msgid, char const *operand) X{ X if (reason_msgid) X error (0, 0, _(reason_msgid), operand); X error (EXIT_TROUBLE, 0, _("Try `%s --help' for more information."), X program_name); X abort (); X} X Xstatic void Xcheck_stdout (void) X{ X if (ferror (stdout)) X fatal ("write failed"); X else if (fclose (stdout) != 0) X pfatal_with_name (_("standard output")); X} X Xstatic char const * const option_help_msgid[] = { X N_("Compare files line by line."), X "", X N_("-i --ignore-case Ignore case differences in file contents."), X N_("--ignore-file-name-case Ignore case when comparing file names."), X N_("--no-ignore-file-name-case Consider case when comparing file names."), X N_("-E --ignore-tab-expansion Ignore changes due to tab expansion."), X N_("-b --ignore-space-change Ignore changes in the amount of white space."), X N_("-w --ignore-all-space Ignore all white space."), X N_("-B --ignore-blank-lines Ignore changes whose lines are all blank."), X N_("-I RE --ignore-matching-lines=RE Ignore changes whose lines all match RE."), X N_("--strip-trailing-cr Strip trailing carriage return on input."), X#if HAVE_SETMODE_DOS X N_("--binary Read and write data in binary mode."), X#endif X N_("-a --text Treat all files as text."), X "", X N_("-c -C NUM --context[=NUM] Output NUM (default 3) lines of copied context.\n\ X-u -U NUM --unified[=NUM] Output NUM (default 3) lines of unified context.\n\ X --label LABEL Use LABEL instead of file name.\n\ X -p --show-c-function Show which C function each change is in.\n\ X -F RE --show-function-line=RE Show the most recent line matching RE."), X N_("-q --brief Output only whether files differ."), X N_("-e --ed Output an ed script."), X N_("--normal Output a normal diff."), X N_("-n --rcs Output an RCS format diff."), X N_("-y --side-by-side Output in two columns.\n\ X -W NUM --width=NUM Output at most NUM (default 130) print columns.\n\ X --left-column Output only the left column of common lines.\n\ X --suppress-common-lines Do not output common lines."), X N_("-D NAME --ifdef=NAME Output merged file to show `#ifdef NAME' diffs."), X N_("--GTYPE-group-format=GFMT Similar, but format GTYPE input groups with GFMT."), X N_("--line-format=LFMT Similar, but format all input lines with LFMT."), X N_("--LTYPE-line-format=LFMT Similar, but format LTYPE input lines with LFMT."), X N_(" LTYPE is `old', `new', or `unchanged'. GTYPE is LTYPE or `changed'."), X N_(" GFMT may contain:\n\ X %< lines from FILE1\n\ X %> lines from FILE2\n\ X %= lines common to FILE1 and FILE2\n\ X %[-][WIDTH][.[PREC]]{doxX}LETTER printf-style spec for LETTER\n\ X LETTERs are as follows for new group, lower case for old group:\n\ X F first line number\n\ X L last line number\n\ X N number of lines = L-F+1\n\ X E F-1\n\ X M L+1"), X N_(" LFMT may contain:\n\ X %L contents of line\n\ X %l contents of line, excluding any trailing newline\n\ X %[-][WIDTH][.[PREC]]{doxX}n printf-style spec for input line number"), X N_(" Either GFMT or LFMT may contain:\n\ X %% %\n\ X %c'C' the single character C\n\ X %c'\\OOO' the character with octal code OOO"), X "", X N_("-l --paginate Pass the output through `pr' to paginate it."), X N_("-t --expand-tabs Expand tabs to spaces in output."), X N_("-T --initial-tab Make tabs line up by prepending a tab."), X "", X N_("-r --recursive Recursively compare any subdirectories found."), X N_("-N --new-file Treat absent files as empty."), X N_("--unidirectional-new-file Treat absent first files as empty."), X N_("-s --report-identical-files Report when two files are the same."), X N_("-x PAT --exclude=PAT Exclude files that match PAT."), X N_("-X FILE --exclude-from=FILE Exclude files that match any pattern in FILE."), X N_("-S FILE --starting-file=FILE Start with FILE when comparing directories."), X N_("--from-file=FILE1 Compare FILE1 to all operands. FILE1 can be a directory."), X N_("--to-file=FILE2 Compare all operands to FILE2. FILE2 can be a directory."), X "", X N_("--horizon-lines=NUM Keep NUM lines of the common prefix and suffix."), X N_("-d --minimal Try hard to find a smaller set of changes."), X N_("--speed-large-files Assume large files and many scattered small changes."), X "", X N_("-v --version Output version info."), X N_("--help Output this help."), X "", X N_("FILES are `FILE1 FILE2' or `DIR1 DIR2' or `DIR FILE...' or `FILE... DIR'."), X N_("If --from-file or --to-file is given, there are no restrictions on FILES."), X N_("If a FILE is `-', read standard input."), X "", X N_("Report bugs to ."), X 0 X}; X Xstatic void Xusage (void) X{ X char const * const *p; X X printf (_("Usage: %s [OPTION]... FILES\n"), program_name); X X for (p = option_help_msgid; *p; p++) X { X if (!**p) X putchar ('\n'); X else X { X char const *msg = _(*p); X char const *nl; X while ((nl = strchr (msg, '\n'))) X { X int msglen = nl + 1 - msg; X printf (" %.*s", msglen, msg); X msg = nl + 1; X } X X printf (" %s\n" + 2 * (*msg != ' ' && *msg != '-'), msg); X } X } X} X X/* Set VAR to VALUE, reporting an OPTION error if this is a X conflict. */ Xstatic void Xspecify_value (char const **var, char const *value, char const *option) X{ X if (*var && strcmp (*var, value) != 0) X { X error (0, 0, _("conflicting %s option value `%s'"), option, value); X try_help (0, 0); X } X *var = value; X} X X/* Set the output style to STYLE, diagnosing conflicts. */ Xstatic void Xspecify_style (enum output_style style) X{ X if (output_style != style) X { X if (output_style != OUTPUT_UNSPECIFIED) X try_help ("conflicting output style options", 0); X output_style = style; X } X} X Xstatic char const * Xfiletype (struct stat const *st) X{ X /* See POSIX 1003.1-2001 for these formats. X X To keep diagnostics grammatical in English, the returned string X must start with a consonant. */ X X if (S_ISREG (st->st_mode)) X return st->st_size == 0 ? _("regular empty file") : _("regular file"); X X if (S_ISDIR (st->st_mode)) return _("directory"); X X#ifdef S_ISBLK X if (S_ISBLK (st->st_mode)) return _("block special file"); X#endif X#ifdef S_ISCHR X if (S_ISCHR (st->st_mode)) return _("character special file"); X#endif X#ifdef S_ISFIFO X if (S_ISFIFO (st->st_mode)) return _("fifo"); X#endif X /* S_ISLNK is impossible with `fstat' and `stat'. */ X#ifdef S_ISSOCK X if (S_ISSOCK (st->st_mode)) return _("socket"); X#endif X#ifdef S_TYPEISMQ X if (S_TYPEISMQ (st)) return _("message queue"); X#endif X#ifdef S_TYPEISSEM X if (S_TYPEISSEM (st)) return _("semaphore"); X#endif X#ifdef S_TYPEISSHM X if (S_TYPEISSHM (st)) return _("shared memory object"); X#endif X#ifdef S_TYPEISTMO X if (S_TYPEISTMO (st)) return _("typed memory object"); X#endif X X return _("weird file"); X} X X/* Set the last-modified time of *ST to be the current time. */ X Xstatic void Xset_mtime_to_now (struct stat *st) X{ X#ifdef ST_MTIM_NSEC X X# if HAVE_CLOCK_GETTIME && defined CLOCK_REALTIME X if (clock_gettime (CLOCK_REALTIME, &st->st_mtim) == 0) X return; X# endif X X# if HAVE_GETTIMEOFDAY X { X struct timeval timeval; X if (gettimeofday (&timeval, NULL) == 0) X { X st->st_mtime = timeval.tv_sec; X st->st_mtim.ST_MTIM_NSEC = timeval.tv_usec * 1000; X return; X } X } X# endif X X#endif /* ST_MTIM_NSEC */ X X time (&st->st_mtime); X} X X/* Compare two files (or dirs) with parent comparison PARENT X and names NAME0 and NAME1. X (If PARENT is 0, then the first name is just NAME0, etc.) X This is self-contained; it opens the files and closes them. X X Value is EXIT_SUCCESS if files are the same, EXIT_FAILURE if X different, EXIT_TROUBLE if there is a problem opening them. */ X Xstatic int Xcompare_files (struct comparison const *parent, X char const *name0, X char const *name1) X{ X struct comparison cmp; X#define DIR_P(f) (S_ISDIR (cmp.file[f].stat.st_mode) != 0) X register int f; X int status = EXIT_SUCCESS; X bool same_files; X char *free0, *free1; X X /* If this is directory comparison, perhaps we have a file X that exists only in one of the directories. X If so, just print a message to that effect. */ X X if (! ((name0 && name1) X || (unidirectional_new_file && name1) X || new_file)) X { X char const *name = name0 == 0 ? name1 : name0; X char const *dir = parent->file[name0 == 0].name; X X /* See POSIX 1003.1-2001 for this format. */ X message ("Only in %s: %s\n", dir, name); X X /* Return EXIT_FAILURE so that diff_dirs will return X EXIT_FAILURE ("some files differ"). */ X return EXIT_FAILURE; X } X X memset (cmp.file, 0, sizeof cmp.file); X cmp.parent = parent; X X /* cmp.file[f].desc markers */ X#define NONEXISTENT (-1) /* nonexistent file */ X#define UNOPENED (-2) /* unopened file (e.g. directory) */ X#define ERRNO_ENCODE(errno) (-3 - (errno)) /* encoded errno value */ X X#define ERRNO_DECODE(desc) (-3 - (desc)) /* inverse of ERRNO_ENCODE */ X X cmp.file[0].desc = name0 == 0 ? NONEXISTENT : UNOPENED; X cmp.file[1].desc = name1 == 0 ? NONEXISTENT : UNOPENED; X X /* Now record the full name of each file, including nonexistent ones. */ X X if (name0 == 0) X name0 = name1; X if (name1 == 0) X name1 = name0; X X if (!parent) X { X free0 = 0; X free1 = 0; X cmp.file[0].name = name0; X cmp.file[1].name = name1; X } X else X { X cmp.file[0].name = free0 X = dir_file_pathname (parent->file[0].name, name0); X cmp.file[1].name = free1 X = dir_file_pathname (parent->file[1].name, name1); X } X X /* Stat the files. */ X X for (f = 0; f < 2; f++) X { X if (cmp.file[f].desc != NONEXISTENT) X { X if (f && file_name_cmp (cmp.file[f].name, cmp.file[0].name) == 0) X { X cmp.file[f].desc = cmp.file[0].desc; X cmp.file[f].stat = cmp.file[0].stat; X } X else if (strcmp (cmp.file[f].name, "-") == 0) X { X cmp.file[f].desc = STDIN_FILENO; X if (fstat (STDIN_FILENO, &cmp.file[f].stat) != 0) X cmp.file[f].desc = ERRNO_ENCODE (errno); X else X { X if (S_ISREG (cmp.file[f].stat.st_mode)) X { X off_t pos = lseek (STDIN_FILENO, (off_t) 0, SEEK_CUR); X if (pos < 0) X cmp.file[f].desc = ERRNO_ENCODE (errno); X else X cmp.file[f].stat.st_size = X MAX (0, cmp.file[f].stat.st_size - pos); X } X X /* POSIX 1003.1-2001 requires current time for X stdin. */ X set_mtime_to_now (&cmp.file[f].stat); X } X } X else if (stat (cmp.file[f].name, &cmp.file[f].stat) != 0) X cmp.file[f].desc = ERRNO_ENCODE (errno); X } X } X X /* Mark files as nonexistent at the top level as needed for -N and X --unidirectional-new-file. */ X if (! parent) X { X if ((new_file | unidirectional_new_file) X && cmp.file[0].desc == ERRNO_ENCODE (ENOENT) X && cmp.file[1].desc == UNOPENED) X cmp.file[0].desc = NONEXISTENT; X X if (new_file X && cmp.file[0].desc == UNOPENED X && cmp.file[1].desc == ERRNO_ENCODE (ENOENT)) X cmp.file[1].desc = NONEXISTENT; X } X X for (f = 0; f < 2; f++) X if (cmp.file[f].desc == NONEXISTENT) X cmp.file[f].stat.st_mode = cmp.file[1 - f].stat.st_mode; X X for (f = 0; f < 2; f++) X { X int e = ERRNO_DECODE (cmp.file[f].desc); X if (0 <= e) X { X errno = e; X perror_with_name (cmp.file[f].name); X status = EXIT_TROUBLE; X } X } X X if (status == EXIT_SUCCESS && ! parent && DIR_P (0) != DIR_P (1)) X { X /* If one is a directory, and it was specified in the command line, X use the file in that dir with the other file's basename. */ X X int fnm_arg = DIR_P (0); X int dir_arg = 1 - fnm_arg; X char const *fnm = cmp.file[fnm_arg].name; X char const *dir = cmp.file[dir_arg].name; X char const *filename = cmp.file[dir_arg].name = free0 X = dir_file_pathname (dir, base_name (fnm)); X X if (strcmp (fnm, "-") == 0) X fatal ("cannot compare `-' to a directory"); X X if (stat (filename, &cmp.file[dir_arg].stat) != 0) X { X perror_with_name (filename); X status = EXIT_TROUBLE; X } X } X X if (status != EXIT_SUCCESS) X { X /* One of the files should exist but does not. */ X } X else if ((same_files X = (cmp.file[0].desc != NONEXISTENT X && cmp.file[1].desc != NONEXISTENT X && 0 < same_file (&cmp.file[0].stat, &cmp.file[1].stat) X && same_file_attributes (&cmp.file[0].stat, X &cmp.file[1].stat))) X && no_diff_means_no_output) X { X /* The two named files are actually the same physical file. X We know they are identical without actually reading them. */ X } X else if (DIR_P (0) & DIR_P (1)) X { X if (output_style == OUTPUT_IFDEF) X fatal ("-D option not supported with directories"); X X /* If both are directories, compare the files in them. */ X X if (parent && !recursive) X { X /* But don't compare dir contents one level down X unless -r was specified. X See POSIX 1003.1-2001 for this format. */ X message ("Common subdirectories: %s and %s\n", X cmp.file[0].name, cmp.file[1].name); X } X else X status = diff_dirs (&cmp, compare_files); X } X else if ((DIR_P (0) | DIR_P (1)) X || (parent X && (! S_ISREG (cmp.file[0].stat.st_mode) X || ! S_ISREG (cmp.file[1].stat.st_mode)))) X { X if (cmp.file[0].desc == NONEXISTENT || cmp.file[1].desc == NONEXISTENT) X { X /* We have a subdirectory that exists only in one directory. */ X X if ((DIR_P (0) | DIR_P (1)) X && recursive X && (new_file X || (unidirectional_new_file X && cmp.file[0].desc == NONEXISTENT))) X status = diff_dirs (&cmp, compare_files); X else X { X char const *dir X = parent->file[cmp.file[0].desc == NONEXISTENT].name; X X /* See POSIX 1003.1-2001 for this format. */ X message ("Only in %s: %s\n", dir, name0); X X status = EXIT_FAILURE; X } X } X else X { X /* We have two files that are not to be compared. */ X X /* See POSIX 1003.1-2001 for this format. */ X message5 ("File %s is a %s while file %s is a %s\n", X file_label[0] ? file_label[0] : cmp.file[0].name, X filetype (&cmp.file[0].stat), X file_label[1] ? file_label[1] : cmp.file[1].name, X filetype (&cmp.file[1].stat)); X X /* This is a difference. */ X status = EXIT_FAILURE; X } X } X else if (files_can_be_treated_as_binary X && cmp.file[0].stat.st_size != cmp.file[1].stat.st_size X && (cmp.file[0].desc == NONEXISTENT X || S_ISREG (cmp.file[0].stat.st_mode)) X && (cmp.file[1].desc == NONEXISTENT X || S_ISREG (cmp.file[1].stat.st_mode))) X { X message ("Files %s and %s differ\n", X file_label[0] ? file_label[0] : cmp.file[0].name, X file_label[1] ? file_label[1] : cmp.file[1].name); X status = EXIT_FAILURE; X } X else X { X /* Both exist and neither is a directory. */ X X /* Open the files and record their descriptors. */ X X if (cmp.file[0].desc == UNOPENED) X if ((cmp.file[0].desc = open (cmp.file[0].name, O_RDONLY, 0)) < 0) X { X perror_with_name (cmp.file[0].name); X status = EXIT_TROUBLE; X } X if (cmp.file[1].desc == UNOPENED) X { X if (same_files) X cmp.file[1].desc = cmp.file[0].desc; X else if ((cmp.file[1].desc = open (cmp.file[1].name, O_RDONLY, 0)) X < 0) X { X perror_with_name (cmp.file[1].name); X status = EXIT_TROUBLE; X } X } X X#if HAVE_SETMODE_DOS X if (binary) X for (f = 0; f < 2; f++) X if (0 <= cmp.file[f].desc) X set_binary_mode (cmp.file[f].desc, 1); X#endif X X /* Compare the files, if no error was found. */ X X if (status == EXIT_SUCCESS) X status = diff_2_files (&cmp); X X /* Close the file descriptors. */ X X if (0 <= cmp.file[0].desc && close (cmp.file[0].desc) != 0) X { X perror_with_name (cmp.file[0].name); X status = EXIT_TROUBLE; X } X if (0 <= cmp.file[1].desc && cmp.file[0].desc != cmp.file[1].desc X && close (cmp.file[1].desc) != 0) X { X perror_with_name (cmp.file[1].name); X status = EXIT_TROUBLE; X } X } X X /* Now the comparison has been done, if no error prevented it, X and STATUS is the value this function will return. */ X X if (status == EXIT_SUCCESS) X { X if (report_identical_files && !DIR_P (0)) X message ("Files %s and %s are identical\n", X file_label[0] ? file_label[0] : cmp.file[0].name, X file_label[1] ? file_label[1] : cmp.file[1].name); X } X else X { X /* Flush stdout so that the user sees differences immediately. X This can hurt performance, unfortunately. */ X if (fflush (stdout) != 0) X pfatal_with_name (_("standard output")); X } X X if (free0) X free (free0); X if (free1) X free (free1); X X return status; X} END-of-contrib/diff/src/diff.c echo x - contrib/diff/src/dir.c sed 's/^X//' >contrib/diff/src/dir.c << 'END-of-contrib/diff/src/dir.c' X/* Read, sort and compare two directories. Used for GNU DIFF. X X Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1998, 2001, 2002 X Free Software Foundation, Inc. X X This file is part of GNU DIFF. X X GNU DIFF is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X GNU DIFF is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; see the file COPYING. X If not, write to the Free Software Foundation, X 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#include "diff.h" X#include X#include X#include X#include X X/* Read the directory named by DIR and store into DIRDATA a sorted vector X of filenames for its contents. DIR->desc == -1 means this directory is X known to be nonexistent, so set DIRDATA to an empty vector. X Return -1 (setting errno) if error, 0 otherwise. */ X Xstruct dirdata X{ X size_t nnames; /* Number of names. */ X char const **names; /* Sorted names of files in dir, followed by 0. */ X char *data; /* Allocated storage for file names. */ X}; X X/* Whether file names in directories should be compared with strcoll. */ Xstatic bool locale_specific_sorting; X X/* Where to go if strcoll fails. */ Xstatic jmp_buf failed_strcoll; X Xstatic bool dir_loop (struct comparison const *, int); Xstatic int compare_names_for_qsort (void const *, void const *); X X X/* Read a directory and get its vector of names. */ X Xstatic bool Xdir_read (struct file_data const *dir, struct dirdata *dirdata) X{ X register struct dirent *next; X register size_t i; X X /* Address of block containing the files that are described. */ X char const **names; X X /* Number of files in directory. */ X size_t nnames; X X /* Allocated and used storage for file name data. */ X char *data; X size_t data_alloc, data_used; X X dirdata->names = 0; X dirdata->data = 0; X nnames = 0; X data = 0; X X if (dir->desc != -1) X { X /* Open the directory and check for errors. */ X register DIR *reading = opendir (dir->name); X if (!reading) X return 0; X X /* Initialize the table of filenames. */ X X data_alloc = 512; X data_used = 0; X dirdata->data = data = xmalloc (data_alloc); X X /* Read the directory entries, and insert the subfiles X into the `data' table. */ X X while ((errno = 0, (next = readdir (reading)) != 0)) X { X char *d_name = next->d_name; X size_t d_size = NAMLEN (next) + 1; X X /* Ignore "." and "..". */ X if (d_name[0] == '.' X && (d_name[1] == 0 || (d_name[1] == '.' && d_name[2] == 0))) X continue; X X if (excluded_filename (excluded, d_name)) X continue; X X while (data_alloc < data_used + d_size) X { X if (PTRDIFF_MAX / 2 <= data_alloc) X xalloc_die (); X dirdata->data = data = xrealloc (data, data_alloc *= 2); X } X X memcpy (data + data_used, d_name, d_size); X data_used += d_size; X nnames++; X } X if (errno) X { X int e = errno; X closedir (reading); X errno = e; X return 0; X } X#if CLOSEDIR_VOID X closedir (reading); X#else X if (closedir (reading) != 0) X return 0; X#endif X } X X /* Create the `names' table from the `data' table. */ X if (PTRDIFF_MAX / sizeof *names - 1 <= nnames) X xalloc_die (); X dirdata->names = names = xmalloc ((nnames + 1) * sizeof *names); X dirdata->nnames = nnames; X for (i = 0; i < nnames; i++) X { X names[i] = data; X data += strlen (data) + 1; X } X names[nnames] = 0; X return 1; X} X X/* Compare file names, returning a value compatible with strcmp. */ X Xstatic int Xcompare_names (char const *name1, char const *name2) X{ X if (ignore_file_name_case) X { X int r = strcasecmp (name1, name2); X if (r) X return r; X } X X if (locale_specific_sorting) X { X int r; X errno = 0; X r = strcoll (name1, name2); X if (errno) X { X error (0, errno, _("cannot compare file names `%s' and `%s'"), X name1, name2); X longjmp (failed_strcoll, 1); X } X if (r) X return r; X } X X return file_name_cmp (name1, name2); X} X X/* A wrapper for compare_names suitable as an argument for qsort. */ X Xstatic int Xcompare_names_for_qsort (void const *file1, void const *file2) X{ X char const *const *f1 = file1; X char const *const *f2 = file2; X return compare_names (*f1, *f2); X} X X/* Compare the contents of two directories named in CMP. X This is a top-level routine; it does everything necessary for diff X on two directories. X X CMP->file[0].desc == -1 says directory CMP->file[0] doesn't exist, X but pretend it is empty. Likewise for CMP->file[1]. X X HANDLE_FILE is a caller-provided subroutine called to handle each file. X It gets three operands: CMP, name of file in dir 0, name of file in dir 1. X These names are relative to the original working directory. X X For a file that appears in only one of the dirs, one of the name-args X to HANDLE_FILE is zero. X X Returns the maximum of all the values returned by HANDLE_FILE, X or EXIT_TROUBLE if trouble is encountered in opening files. */ X Xint Xdiff_dirs (struct comparison const *cmp, X int (*handle_file) (struct comparison const *, X char const *, char const *)) X{ X struct dirdata dirdata[2]; X int volatile val = EXIT_SUCCESS; X int i; X X if ((cmp->file[0].desc == -1 || dir_loop (cmp, 0)) X && (cmp->file[1].desc == -1 || dir_loop (cmp, 1))) X { X error (0, 0, "%s: recursive directory loop", X cmp->file[cmp->file[0].desc == -1].name); X return EXIT_TROUBLE; X } X X /* Get contents of both dirs. */ X for (i = 0; i < 2; i++) X if (! dir_read (&cmp->file[i], &dirdata[i])) X { X perror_with_name (cmp->file[i].name); X val = EXIT_TROUBLE; X } X X if (val == EXIT_SUCCESS) X { X char const **volatile names[2]; X names[0] = dirdata[0].names; X names[1] = dirdata[1].names; X X /* Use locale-specific sorting if possible, else native byte order. */ X locale_specific_sorting = 1; X if (setjmp (failed_strcoll)) X locale_specific_sorting = 0; X X /* Sort the directories. */ X for (i = 0; i < 2; i++) X qsort (names[i], dirdata[i].nnames, sizeof *dirdata[i].names, X compare_names_for_qsort); X X /* If `-S name' was given, and this is the topmost level of comparison, X ignore all file names less than the specified starting name. */ X X if (starting_file && ! cmp->parent) X { X while (*names[0] && compare_names (*names[0], starting_file) < 0) X names[0]++; X while (*names[1] && compare_names (*names[1], starting_file) < 0) X names[1]++; X } X X /* Loop while files remain in one or both dirs. */ X while (*names[0] || *names[1]) X { X /* Compare next name in dir 0 with next name in dir 1. X At the end of a dir, X pretend the "next name" in that dir is very large. */ X int nameorder = (!*names[0] ? 1 : !*names[1] ? -1 X : compare_names (*names[0], *names[1])); X int v1 = (*handle_file) (cmp, X 0 < nameorder ? 0 : *names[0]++, X nameorder < 0 ? 0 : *names[1]++); X if (val < v1) X val = v1; X } X } X X for (i = 0; i < 2; i++) X { X if (dirdata[i].names) X free (dirdata[i].names); X if (dirdata[i].data) X free (dirdata[i].data); X } X X return val; X} X X/* Return nonzero if CMP is looping recursively in argument I. */ X Xstatic bool Xdir_loop (struct comparison const *cmp, int i) X{ X struct comparison const *p = cmp; X while ((p = p->parent)) X if (0 < same_file (&p->file[i].stat, &cmp->file[i].stat)) X return 1; X return 0; X} END-of-contrib/diff/src/dir.c echo x - contrib/diff/src/ed.c sed 's/^X//' >contrib/diff/src/ed.c << 'END-of-contrib/diff/src/ed.c' X/* Output routines for ed-script format. X X Copyright (C) 1988, 1989, 1991, 1992, 1993, 1995, 1998, 2001 Free X Software Foundation, Inc. X X This file is part of GNU DIFF. X X GNU DIFF is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X GNU DIFF is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; see the file COPYING. X If not, write to the Free Software Foundation, X 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#include "diff.h" X Xstatic void print_ed_hunk (struct change *); Xstatic void print_rcs_hunk (struct change *); Xstatic void pr_forward_ed_hunk (struct change *); X X/* Print our script as ed commands. */ X Xvoid Xprint_ed_script (struct change *script) X{ X print_script (script, find_reverse_change, print_ed_hunk); X} X X/* Print a hunk of an ed diff */ X Xstatic void Xprint_ed_hunk (struct change *hunk) X{ X lin f0, l0, f1, l1; X enum changes changes; X X#ifdef DEBUG X debug_script (hunk); X#endif X X /* Determine range of line numbers involved in each file. */ X changes = analyze_hunk (hunk, &f0, &l0, &f1, &l1); X if (!changes) X return; X X begin_output (); X X /* Print out the line number header for this hunk */ X print_number_range (',', &files[0], f0, l0); X fprintf (outfile, "%c\n", change_letter[changes]); X X /* Print new/changed lines from second file, if needed */ X if (changes != OLD) X { X lin i; X for (i = f1; i <= l1; i++) X { X if (files[1].linbuf[i][0] == '.' && files[1].linbuf[i][1] == '\n') X { X /* The file's line is just a dot, and it would exit X insert mode. Precede the dot with another dot, exit X insert mode, remove the extra dot, and then resume X insert mode. */ X fprintf (outfile, "..\n.\ns/.//\na\n"); X } X else X print_1_line ("", &files[1].linbuf[i]); X } X X fprintf (outfile, ".\n"); X } X} X X/* Print change script in the style of ed commands, X but print the changes in the order they appear in the input files, X which means that the commands are not truly useful with ed. */ X Xvoid Xpr_forward_ed_script (struct change *script) X{ X print_script (script, find_change, pr_forward_ed_hunk); X} X Xstatic void Xpr_forward_ed_hunk (struct change *hunk) X{ X lin i, f0, l0, f1, l1; X X /* Determine range of line numbers involved in each file. */ X enum changes changes = analyze_hunk (hunk, &f0, &l0, &f1, &l1); X if (!changes) X return; X X begin_output (); X X fprintf (outfile, "%c", change_letter[changes]); X print_number_range (' ', files, f0, l0); X fprintf (outfile, "\n"); X X /* If deletion only, print just the number range. */ X X if (changes == OLD) X return; X X /* For insertion (with or without deletion), print the number range X and the lines from file 2. */ X X for (i = f1; i <= l1; i++) X print_1_line ("", &files[1].linbuf[i]); X X fprintf (outfile, ".\n"); X} X X/* Print in a format somewhat like ed commands X except that each insert command states the number of lines it inserts. X This format is used for RCS. */ X Xvoid Xprint_rcs_script (struct change *script) X{ X print_script (script, find_change, print_rcs_hunk); X} X X/* Print a hunk of an RCS diff */ X Xstatic void Xprint_rcs_hunk (struct change *hunk) X{ X lin i, f0, l0, f1, l1; X long tf0, tl0, tf1, tl1; X X /* Determine range of line numbers involved in each file. */ X enum changes changes = analyze_hunk (hunk, &f0, &l0, &f1, &l1); X if (!changes) X return; X X begin_output (); X X translate_range (&files[0], f0, l0, &tf0, &tl0); X X if (changes & OLD) X { X fprintf (outfile, "d"); X /* For deletion, print just the starting line number from file 0 X and the number of lines deleted. */ X fprintf (outfile, "%ld %ld\n", tf0, tf0 <= tl0 ? tl0 - tf0 + 1 : 1); X } X X if (changes & NEW) X { X fprintf (outfile, "a"); X X /* Take last-line-number from file 0 and # lines from file 1. */ X translate_range (&files[1], f1, l1, &tf1, &tl1); X fprintf (outfile, "%ld %ld\n", tl0, tf1 <= tl1 ? tl1 - tf1 + 1 : 1); X X /* Print the inserted lines. */ X for (i = f1; i <= l1; i++) X print_1_line ("", &files[1].linbuf[i]); X } X} END-of-contrib/diff/src/ed.c echo x - contrib/diff/src/ifdef.c sed 's/^X//' >contrib/diff/src/ifdef.c << 'END-of-contrib/diff/src/ifdef.c' X/* #ifdef-format output routines for GNU DIFF. X X Copyright (C) 1989, 1991, 1992, 1993, 1994, 2001, 2002 Free X Software Foundation, Inc. X X This file is part of GNU DIFF. X X GNU DIFF is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY. No author or distributor X accepts responsibility to anyone for the consequences of using it X or for whether it serves any particular purpose or works at all, X unless he says so in writing. Refer to the GNU DIFF General Public X License for full details. X X Everyone is granted permission to copy, modify and redistribute X GNU DIFF, but only under the conditions described in the X GNU DIFF General Public License. A copy of this license is X supposed to have been given to you along with GNU DIFF so you X can know your rights and responsibilities. It should be in a X file named COPYING. Among other things, the copyright notice X and this notice must be preserved on all copies. */ X X#include "diff.h" X X#include X Xstruct group X{ X struct file_data const *file; X lin from, upto; /* start and limit lines for this group of lines */ X}; X Xstatic char const *format_group (FILE *, char const *, char, X struct group const *); Xstatic char const *do_printf_spec (FILE *, char const *, X struct file_data const *, lin, X struct group const *); Xstatic char const *scan_char_literal (char const *, char *); Xstatic lin groups_letter_value (struct group const *, char); Xstatic void format_ifdef (char const *, lin, lin, lin, lin); Xstatic void print_ifdef_hunk (struct change *); Xstatic void print_ifdef_lines (FILE *, char const *, struct group const *); X Xstatic lin next_line; X X/* Print the edit-script SCRIPT as a merged #ifdef file. */ X Xvoid Xprint_ifdef_script (struct change *script) X{ X next_line = - files[0].prefix_lines; X print_script (script, find_change, print_ifdef_hunk); X if (next_line < files[0].valid_lines) X { X begin_output (); X format_ifdef (group_format[UNCHANGED], next_line, files[0].valid_lines, X next_line - files[0].valid_lines + files[1].valid_lines, X files[1].valid_lines); X } X} X X/* Print a hunk of an ifdef diff. X This is a contiguous portion of a complete edit script, X describing changes in consecutive lines. */ X Xstatic void Xprint_ifdef_hunk (struct change *hunk) X{ X lin first0, last0, first1, last1; X X /* Determine range of line numbers involved in each file. */ X enum changes changes = analyze_hunk (hunk, &first0, &last0, &first1, &last1); X if (!changes) X return; X X begin_output (); X X /* Print lines up to this change. */ X if (next_line < first0) X format_ifdef (group_format[UNCHANGED], next_line, first0, X next_line - first0 + first1, first1); X X /* Print this change. */ X next_line = last0 + 1; X format_ifdef (group_format[changes], first0, next_line, first1, last1 + 1); X} X X/* Print a set of lines according to FORMAT. X Lines BEG0 up to END0 are from the first file; X lines BEG1 up to END1 are from the second file. */ X Xstatic void Xformat_ifdef (char const *format, lin beg0, lin end0, lin beg1, lin end1) X{ X struct group groups[2]; X X groups[0].file = &files[0]; X groups[0].from = beg0; X groups[0].upto = end0; X groups[1].file = &files[1]; X groups[1].from = beg1; X groups[1].upto = end1; X format_group (outfile, format, 0, groups); X} X X/* Print to file OUT a set of lines according to FORMAT. X The format ends at the first free instance of ENDCHAR. X Yield the address of the terminating character. X GROUPS specifies which lines to print. X If OUT is zero, do not actually print anything; just scan the format. */ X Xstatic char const * Xformat_group (register FILE *out, char const *format, char endchar, X struct group const *groups) X{ X register char c; X register char const *f = format; X X while ((c = *f) != endchar && c != 0) X { X char const *f1 = ++f; X if (c == '%') X switch ((c = *f++)) X { X case '%': X break; X X case '(': X /* Print if-then-else format e.g. `%(n=1?thenpart:elsepart)'. */ X { X int i; X uintmax_t value[2]; X FILE *thenout, *elseout; X X for (i = 0; i < 2; i++) X { X if (ISDIGIT (*f)) X { X char *fend; X errno = 0; X value[i] = strtoumax (f, &fend, 10); X if (errno) X goto bad_format; X f = fend; X } X else X { X value[i] = groups_letter_value (groups, *f); X if (value[i] == -1) X goto bad_format; X f++; X } X if (*f++ != "=?"[i]) X goto bad_format; X } X if (value[0] == value[1]) X thenout = out, elseout = 0; X else X thenout = 0, elseout = out; X f = format_group (thenout, f, ':', groups); X if (*f) X { X f = format_group (elseout, f + 1, ')', groups); X if (*f) X f++; X } X } X continue; X X case '<': X /* Print lines deleted from first file. */ X print_ifdef_lines (out, line_format[OLD], &groups[0]); X continue; X X case '=': X /* Print common lines. */ X print_ifdef_lines (out, line_format[UNCHANGED], &groups[0]); X continue; X X case '>': X /* Print lines inserted from second file. */ X print_ifdef_lines (out, line_format[NEW], &groups[1]); X continue; X X default: X f = do_printf_spec (out, f - 2, 0, 0, groups); X if (f) X continue; X /* Fall through. */ X bad_format: X c = '%'; X f = f1; X break; X } X X if (out) X putc (c, out); X } X X return f; X} X X/* For the line group pair G, return the number corresponding to LETTER. X Return -1 if LETTER is not a group format letter. */ Xstatic lin Xgroups_letter_value (struct group const *g, char letter) X{ X switch (letter) X { X case 'E': letter = 'e'; g++; break; X case 'F': letter = 'f'; g++; break; X case 'L': letter = 'l'; g++; break; X case 'M': letter = 'm'; g++; break; X case 'N': letter = 'n'; g++; break; X } X X switch (letter) X { X case 'e': return translate_line_number (g->file, g->from) - 1; X case 'f': return translate_line_number (g->file, g->from); X case 'l': return translate_line_number (g->file, g->upto) - 1; X case 'm': return translate_line_number (g->file, g->upto); X case 'n': return g->upto - g->from; X default: return -1; X } X} X X/* Print to file OUT, using FORMAT to print the line group GROUP. X But do nothing if OUT is zero. */ Xstatic void Xprint_ifdef_lines (register FILE *out, char const *format, X struct group const *group) X{ X struct file_data const *file = group->file; X char const * const *linbuf = file->linbuf; X lin from = group->from, upto = group->upto; X X if (!out) X return; X X /* If possible, use a single fwrite; it's faster. */ X if (!expand_tabs && format[0] == '%') X { X if (format[1] == 'l' && format[2] == '\n' && !format[3] && from < upto) X { X fwrite (linbuf[from], sizeof (char), X linbuf[upto] + (linbuf[upto][-1] != '\n') - linbuf[from], X out); X return; X } X if (format[1] == 'L' && !format[2]) X { X fwrite (linbuf[from], sizeof (char), X linbuf[upto] - linbuf[from], out); X return; X } X } X X for (; from < upto; from++) X { X register char c; X register char const *f = format; X X while ((c = *f++) != 0) X { X char const *f1 = f; X if (c == '%') X switch ((c = *f++)) X { X case '%': X break; X X case 'l': X output_1_line (linbuf[from], X (linbuf[from + 1] X - (linbuf[from + 1][-1] == '\n')), X 0, 0); X continue; X X case 'L': X output_1_line (linbuf[from], linbuf[from + 1], 0, 0); X continue; X X default: X f = do_printf_spec (out, f - 2, file, from, 0); X if (f) X continue; X c = '%'; X f = f1; X break; X } X X putc (c, out); X } X } X} X Xstatic char const * Xdo_printf_spec (FILE *out, char const *spec, X struct file_data const *file, lin n, X struct group const *groups) X{ X char const *f = spec; X char c; X char c1; X X /* Scan printf-style SPEC of the form %[-'0]*[0-9]*(.[0-9]*)?[cdoxX]. */ X /* assert (*f == '%'); */ X f++; X while ((c = *f++) == '-' || c == '\'' || c == '0') X continue; X while (ISDIGIT (c)) X c = *f++; X if (c == '.') X while (ISDIGIT (c = *f++)) X continue; X c1 = *f++; X X switch (c) X { X case 'c': X if (c1 != '\'') X return 0; X else X { X char value; X f = scan_char_literal (f, &value); X if (!f) X return 0; X if (out) X putc (value, out); X } X break; X X case 'd': case 'o': case 'x': case 'X': X { X lin value; X X if (file) X { X if (c1 != 'n') X return 0; X value = translate_line_number (file, n); X } X else X { X value = groups_letter_value (groups, c1); X if (value < 0) X return 0; X } X X if (out) X { X /* For example, if the spec is "%3xn", use the printf X format spec "%3lx". Here the spec prefix is "%3". */ X long long_value = value; X size_t spec_prefix_len = f - spec - 2; X#if HAVE_C_VARARRAYS X char format[spec_prefix_len + 3]; X#else X char *format = xmalloc (spec_prefix_len + 3); X#endif X char *p = format + spec_prefix_len; X memcpy (format, spec, spec_prefix_len); X *p++ = 'l'; X *p++ = c; X *p = '\0'; X fprintf (out, format, long_value); X#if ! HAVE_C_VARARRAYS X free (format); X#endif X } X } X break; X X default: X return 0; X } X X return f; X} X X/* Scan the character literal represented in the string LIT; LIT points just X after the initial apostrophe. Put the literal's value into *VALPTR. X Yield the address of the first character after the closing apostrophe, X or zero if the literal is ill-formed. */ Xstatic char const * Xscan_char_literal (char const *lit, char *valptr) X{ X register char const *p = lit; X char value; X ptrdiff_t digits; X char c = *p++; X X switch (c) X { X case 0: X case '\'': X return 0; X X case '\\': X value = 0; X while ((c = *p++) != '\'') X { X unsigned int digit = c - '0'; X if (8 <= digit) X return 0; X value = 8 * value + digit; X } X digits = p - lit - 2; X if (! (1 <= digits && digits <= 3)) X return 0; X break; X X default: X value = c; X if (*p++ != '\'') X return 0; X break; X } X X *valptr = value; X return p; X} END-of-contrib/diff/src/ifdef.c echo x - contrib/diff/src/io.c sed 's/^X//' >contrib/diff/src/io.c << 'END-of-contrib/diff/src/io.c' X/* File I/O for GNU DIFF. X X Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1998, 2001, 2002 X Free Software Foundation, Inc. X X This file is part of GNU DIFF. X X GNU DIFF is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X GNU DIFF is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; see the file COPYING. X If not, write to the Free Software Foundation, X 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#include "diff.h" X#include X#include X#include X#include X X/* Rotate an unsigned value to the left. */ X#define ROL(v, n) ((v) << (n) | (v) >> (sizeof (v) * CHAR_BIT - (n))) X X/* Given a hash value and a new character, return a new hash value. */ X#define HASH(h, c) ((c) + ROL (h, 7)) X X/* The type of a hash value. */ Xtypedef size_t hash_value; Xverify (hash_value_is_unsigned, ! TYPE_SIGNED (hash_value)); X X/* Lines are put into equivalence classes of lines that match in lines_differ. X Each equivalence class is represented by one of these structures, X but only while the classes are being computed. X Afterward, each class is represented by a number. */ Xstruct equivclass X{ X lin next; /* Next item in this bucket. */ X hash_value hash; /* Hash of lines in this class. */ X char const *line; /* A line that fits this class. */ X size_t length; /* That line's length, not counting its newline. */ X}; X X/* Hash-table: array of buckets, each being a chain of equivalence classes. X buckets[-1] is reserved for incomplete lines. */ Xstatic lin *buckets; X X/* Number of buckets in the hash table array, not counting buckets[-1]. */ Xstatic size_t nbuckets; X X/* Array in which the equivalence classes are allocated. X The bucket-chains go through the elements in this array. X The number of an equivalence class is its index in this array. */ Xstatic struct equivclass *equivs; X X/* Index of first free element in the array `equivs'. */ Xstatic lin equivs_index; X X/* Number of elements allocated in the array `equivs'. */ Xstatic lin equivs_alloc; X X/* Read a block of data into a file buffer, checking for EOF and error. */ X Xvoid Xfile_block_read (struct file_data *current, size_t size) X{ X if (size && ! current->eof) X { X size_t s = block_read (current->desc, X FILE_BUFFER (current) + current->buffered, size); X if (s == SIZE_MAX) X pfatal_with_name (current->name); X current->buffered += s; X current->eof = s < size; X } X} X X/* Check for binary files and compare them for exact identity. */ X X/* Return 1 if BUF contains a non text character. X SIZE is the number of characters in BUF. */ X X#define binary_file_p(buf, size) (memchr (buf, 0, size) != 0) X X/* Get ready to read the current file. X Return nonzero if SKIP_TEST is zero, X and if it appears to be a binary file. */ X Xstatic bool Xsip (struct file_data *current, bool skip_test) X{ X /* If we have a nonexistent file at this stage, treat it as empty. */ X if (current->desc < 0) X { X /* Leave room for a sentinel. */ X current->bufsize = sizeof (word); X current->buffer = xmalloc (current->bufsize); X } X else X { X current->bufsize = buffer_lcm (sizeof (word), X STAT_BLOCKSIZE (current->stat), X PTRDIFF_MAX - 2 * sizeof (word)); X current->buffer = xmalloc (current->bufsize); X X if (! skip_test) X { X /* Check first part of file to see if it's a binary file. */ X X bool was_binary = set_binary_mode (current->desc, 1); X off_t buffered; X file_block_read (current, current->bufsize); X buffered = current->buffered; X X if (! was_binary) X { X /* Revert to text mode and seek back to the beginning to X reread the file. Use relative seek, since file X descriptors like stdin might not start at offset X zero. */ X X if (lseek (current->desc, - buffered, SEEK_CUR) == -1) X pfatal_with_name (current->name); X set_binary_mode (current->desc, 0); X current->buffered = 0; X current->eof = 0; X } X X return binary_file_p (current->buffer, buffered); X } X } X X current->buffered = 0; X current->eof = 0; X return 0; X} X X/* Slurp the rest of the current file completely into memory. */ X Xstatic void Xslurp (struct file_data *current) X{ X size_t cc; X X if (current->desc < 0) X { X /* The file is nonexistent. */ X return; X } X X if (S_ISREG (current->stat.st_mode)) X { X /* It's a regular file; slurp in the rest all at once. */ X X /* Get the size out of the stat block. X Allocate just enough room for appended newline plus word sentinel, X plus word-alignment since we want the buffer word-aligned. */ X size_t file_size = current->stat.st_size; X cc = file_size + 2 * sizeof (word) - file_size % sizeof (word); X if (file_size != current->stat.st_size || cc < file_size X || PTRDIFF_MAX <= cc) X xalloc_die (); X X if (current->bufsize < cc) X { X current->bufsize = cc; X current->buffer = xrealloc (current->buffer, cc); X } X X /* Try to read at least 1 more byte than the size indicates, to X detect whether the file is growing. This is a nicety for X users who run 'diff' on files while they are changing. */ X X if (current->buffered <= file_size) X { X file_block_read (current, file_size + 1 - current->buffered); X if (current->buffered <= file_size) X return; X } X } X X /* It's not a regular file, or it's a growing regular file; read it, X growing the buffer as needed. */ X X file_block_read (current, current->bufsize - current->buffered); X X if (current->buffered) X { X while (current->buffered == current->bufsize) X { X if (PTRDIFF_MAX / 2 - sizeof (word) < current->bufsize) X xalloc_die (); X current->bufsize *= 2; X current->buffer = xrealloc (current->buffer, current->bufsize); X file_block_read (current, current->bufsize - current->buffered); X } X X /* Allocate just enough room for appended newline plus word X sentinel, plus word-alignment. */ X cc = current->buffered + 2 * sizeof (word); X current->bufsize = cc - cc % sizeof (word); X current->buffer = xrealloc (current->buffer, current->bufsize); X } X} X X/* Split the file into lines, simultaneously computing the equivalence X class for each line. */ X Xstatic void Xfind_and_hash_each_line (struct file_data *current) X{ X hash_value h; X unsigned char const *p = (unsigned char const *) current->prefix_end; X unsigned char c; X lin i, *bucket; X size_t length; X X /* Cache often-used quantities in local variables to help the compiler. */ X char const **linbuf = current->linbuf; X lin alloc_lines = current->alloc_lines; X lin line = 0; X lin linbuf_base = current->linbuf_base; X lin *cureqs = xmalloc (alloc_lines * sizeof *cureqs); X struct equivclass *eqs = equivs; X lin eqs_index = equivs_index; X lin eqs_alloc = equivs_alloc; X char const *suffix_begin = current->suffix_begin; X char const *bufend = FILE_BUFFER (current) + current->buffered; X bool diff_length_compare_anyway = X ignore_white_space != IGNORE_NO_WHITE_SPACE; X bool same_length_diff_contents_compare_anyway = X diff_length_compare_anyway | ignore_case; X X while ((char const *) p < suffix_begin) X { X char const *ip = (char const *) p; X X h = 0; X X /* Hash this line until we find a newline. */ X if (ignore_case) X switch (ignore_white_space) X { X case IGNORE_ALL_SPACE: X while ((c = *p++) != '\n') X if (! ISSPACE (c)) X h = HASH (h, TOLOWER (c)); X break; X X case IGNORE_SPACE_CHANGE: X while ((c = *p++) != '\n') X { X if (ISSPACE (c)) X { X do X if ((c = *p++) == '\n') X goto hashing_done; X while (ISSPACE (c)); X X h = HASH (h, ' '); X } X X /* C is now the first non-space. */ X h = HASH (h, TOLOWER (c)); X } X break; X X case IGNORE_TAB_EXPANSION: X { X size_t column = 0; X while ((c = *p++) != '\n') X { X int repetitions = 1; X X switch (c) X { X case '\b': X column -= 0 < column; X break; X X case '\t': X c = ' '; X repetitions = TAB_WIDTH - column % TAB_WIDTH; X column += repetitions; X break; X X case '\r': X column = 0; X break; X X default: X c = TOLOWER (c); X column++; X break; X } X X do X h = HASH (h, c); X while (--repetitions != 0); X } X } X break; X X default: X while ((c = *p++) != '\n') X h = HASH (h, TOLOWER (c)); X break; X } X else X switch (ignore_white_space) X { X case IGNORE_ALL_SPACE: X while ((c = *p++) != '\n') X if (! ISSPACE (c)) X h = HASH (h, c); X break; X X case IGNORE_SPACE_CHANGE: X while ((c = *p++) != '\n') X { X if (ISSPACE (c)) X { X do X if ((c = *p++) == '\n') X goto hashing_done; X while (ISSPACE (c)); X X h = HASH (h, ' '); X } X X /* C is now the first non-space. */ X h = HASH (h, c); X } X break; X X case IGNORE_TAB_EXPANSION: X { X size_t column = 0; X while ((c = *p++) != '\n') X { X int repetitions = 1; X X switch (c) X { X case '\b': X column -= 0 < column; X break; X X case '\t': X c = ' '; X repetitions = TAB_WIDTH - column % TAB_WIDTH; X column += repetitions; X break; X X case '\r': X column = 0; X break; X X default: X column++; X break; X } X X do X h = HASH (h, c); X while (--repetitions != 0); X } X } X break; X X default: X while ((c = *p++) != '\n') X h = HASH (h, c); X break; X } X X hashing_done:; X X bucket = &buckets[h % nbuckets]; X length = (char const *) p - ip - 1; X X if ((char const *) p == bufend X && current->missing_newline X && ROBUST_OUTPUT_STYLE (output_style)) X { X /* This line is incomplete. If this is significant, X put the line into buckets[-1]. */ X if (ignore_white_space < IGNORE_SPACE_CHANGE) X bucket = &buckets[-1]; X X /* Omit the inserted newline when computing linbuf later. */ X p--; X bufend = suffix_begin = (char const *) p; X } X X for (i = *bucket; ; i = eqs[i].next) X if (!i) X { X /* Create a new equivalence class in this bucket. */ X i = eqs_index++; X if (i == eqs_alloc) X { X if (PTRDIFF_MAX / (2 * sizeof *eqs) <= eqs_alloc) X xalloc_die (); X eqs_alloc *= 2; X eqs = xrealloc (eqs, eqs_alloc * sizeof *eqs); X } X eqs[i].next = *bucket; X eqs[i].hash = h; X eqs[i].line = ip; X eqs[i].length = length; X *bucket = i; X break; X } X else if (eqs[i].hash == h) X { X char const *eqline = eqs[i].line; X X /* Reuse existing class if lines_differ reports the lines X equal. */ X if (eqs[i].length == length) X { X /* Reuse existing equivalence class if the lines are identical. X This detects the common case of exact identity X faster than lines_differ would. */ X if (memcmp (eqline, ip, length) == 0) X break; X if (!same_length_diff_contents_compare_anyway) X continue; X } X else if (!diff_length_compare_anyway) X continue; X X if (! lines_differ (eqline, ip)) X break; X } X X /* Maybe increase the size of the line table. */ X if (line == alloc_lines) X { X /* Double (alloc_lines - linbuf_base) by adding to alloc_lines. */ X if (PTRDIFF_MAX / 3 <= alloc_lines X || PTRDIFF_MAX / sizeof *cureqs <= 2 * alloc_lines - linbuf_base X || PTRDIFF_MAX / sizeof *linbuf <= alloc_lines - linbuf_base) X xalloc_die (); X alloc_lines = 2 * alloc_lines - linbuf_base; X cureqs = xrealloc (cureqs, alloc_lines * sizeof *cureqs); X linbuf += linbuf_base; X linbuf = xrealloc (linbuf, X (alloc_lines - linbuf_base) * sizeof *linbuf); X linbuf -= linbuf_base; X } X linbuf[line] = ip; X cureqs[line] = i; X ++line; X } X X current->buffered_lines = line; X X for (i = 0; ; i++) X { X /* Record the line start for lines in the suffix that we care about. X Record one more line start than lines, X so that we can compute the length of any buffered line. */ X if (line == alloc_lines) X { X /* Double (alloc_lines - linbuf_base) by adding to alloc_lines. */ X if (PTRDIFF_MAX / 3 <= alloc_lines X || PTRDIFF_MAX / sizeof *cureqs <= 2 * alloc_lines - linbuf_base X || PTRDIFF_MAX / sizeof *linbuf <= alloc_lines - linbuf_base) X xalloc_die (); X alloc_lines = 2 * alloc_lines - linbuf_base; X linbuf += linbuf_base; X linbuf = xrealloc (linbuf, X (alloc_lines - linbuf_base) * sizeof *linbuf); X linbuf -= linbuf_base; X } X linbuf[line] = (char const *) p; X X if ((char const *) p == bufend) X break; X X if (context <= i && no_diff_means_no_output) X break; X X line++; X X while (*p++ != '\n') X continue; X } X X /* Done with cache in local variables. */ X current->linbuf = linbuf; X current->valid_lines = line; X current->alloc_lines = alloc_lines; X current->equivs = cureqs; X equivs = eqs; X equivs_alloc = eqs_alloc; X equivs_index = eqs_index; X} X X/* Prepare the text. Make sure the text end is initialized. X Make sure text ends in a newline, X but remember that we had to add one. X Strip trailing CRs, if that was requested. */ X Xstatic void Xprepare_text (struct file_data *current) X{ X size_t buffered = current->buffered; X char *p = FILE_BUFFER (current); X char *dst; X X if (buffered == 0 || p[buffered - 1] == '\n') X current->missing_newline = 0; X else X { X p[buffered++] = '\n'; X current->missing_newline = 1; X } X X if (!p) X return; X X /* Don't use uninitialized storage when planting or using sentinels. */ X memset (p + buffered, 0, sizeof (word)); X X if (strip_trailing_cr && (dst = memchr (p, '\r', buffered))) X { X char const *src = dst; X char const *srclim = p + buffered; X X do X dst += ! ((*dst = *src++) == '\r' && *src == '\n'); X while (src < srclim); X X buffered -= src - dst; X } X X current->buffered = buffered; X} X X/* We have found N lines in a buffer of size S; guess the X proportionate number of lines that will be found in a buffer of X size T. However, do not guess a number of lines so large that the X resulting line table might cause overflow in size calculations. */ Xstatic lin Xguess_lines (lin n, size_t s, size_t t) X{ X size_t guessed_bytes_per_line = n < 10 ? 32 : s / (n - 1); X lin guessed_lines = MAX (1, t / guessed_bytes_per_line); X return MIN (guessed_lines, PTRDIFF_MAX / (2 * sizeof (char *) + 1) - 5) + 5; X} X X/* Given a vector of two file_data objects, find the identical X prefixes and suffixes of each object. */ X Xstatic void Xfind_identical_ends (struct file_data filevec[]) X{ X word *w0, *w1; X char *p0, *p1, *buffer0, *buffer1; X char const *end0, *beg0; X char const **linbuf0, **linbuf1; X lin i, lines; X size_t n0, n1; X lin alloc_lines0, alloc_lines1; X lin buffered_prefix, prefix_count, prefix_mask; X lin middle_guess, suffix_guess; X X slurp (&filevec[0]); X prepare_text (&filevec[0]); X if (filevec[0].desc != filevec[1].desc) X { X slurp (&filevec[1]); X prepare_text (&filevec[1]); X } X else X { X filevec[1].buffer = filevec[0].buffer; X filevec[1].bufsize = filevec[0].bufsize; X filevec[1].buffered = filevec[0].buffered; X filevec[1].missing_newline = filevec[0].missing_newline; X } X X /* Find identical prefix. */ X X w0 = filevec[0].buffer; X w1 = filevec[1].buffer; X p0 = buffer0 = (char *) w0; X p1 = buffer1 = (char *) w1; X n0 = filevec[0].buffered; X n1 = filevec[1].buffered; X X if (p0 == p1) X /* The buffers are the same; sentinels won't work. */ X p0 = p1 += n1; X else X { X /* Insert end sentinels, in this case characters that are guaranteed X to make the equality test false, and thus terminate the loop. */ X X if (n0 < n1) X p0[n0] = ~p1[n0]; X else X p1[n1] = ~p0[n1]; X X /* Loop until first mismatch, or to the sentinel characters. */ X X /* Compare a word at a time for speed. */ X while (*w0 == *w1) X w0++, w1++; X X /* Do the last few bytes of comparison a byte at a time. */ X p0 = (char *) w0; X p1 = (char *) w1; X while (*p0 == *p1) X p0++, p1++; X X /* Don't mistakenly count missing newline as part of prefix. */ X if (ROBUST_OUTPUT_STYLE (output_style) X && ((buffer0 + n0 - filevec[0].missing_newline < p0) X != X (buffer1 + n1 - filevec[1].missing_newline < p1))) X p0--, p1--; X } X X /* Now P0 and P1 point at the first nonmatching characters. */ X X /* Skip back to last line-beginning in the prefix, X and then discard up to HORIZON_LINES lines from the prefix. */ X i = horizon_lines; X while (p0 != buffer0 && (p0[-1] != '\n' || i--)) X p0--, p1--; X X /* Record the prefix. */ X filevec[0].prefix_end = p0; X filevec[1].prefix_end = p1; X X /* Find identical suffix. */ X X /* P0 and P1 point beyond the last chars not yet compared. */ X p0 = buffer0 + n0; X p1 = buffer1 + n1; X X if (! ROBUST_OUTPUT_STYLE (output_style) X || filevec[0].missing_newline == filevec[1].missing_newline) X { X end0 = p0; /* Addr of last char in file 0. */ X X /* Get value of P0 at which we should stop scanning backward: X this is when either P0 or P1 points just past the last char X of the identical prefix. */ X beg0 = filevec[0].prefix_end + (n0 < n1 ? 0 : n0 - n1); X X /* Scan back until chars don't match or we reach that point. */ X for (; p0 != beg0; p0--, p1--) X if (*p0 != *p1) X { X /* Point at the first char of the matching suffix. */ X beg0 = p0; X break; X } X X /* Are we at a line-beginning in both files? If not, add the rest of X this line to the main body. Discard up to HORIZON_LINES lines from X the identical suffix. Also, discard one extra line, X because shift_boundaries may need it. */ X i = horizon_lines + !((buffer0 == p0 || p0[-1] == '\n') X && X (buffer1 == p1 || p1[-1] == '\n')); X while (i-- && p0 != end0) X while (*p0++ != '\n') X continue; X X p1 += p0 - beg0; X } X X /* Record the suffix. */ X filevec[0].suffix_begin = p0; X filevec[1].suffix_begin = p1; X X /* Calculate number of lines of prefix to save. X X prefix_count == 0 means save the whole prefix; X we need this for options like -D that output the whole file, X or for enormous contexts (to avoid worrying about arithmetic overflow). X We also need it for options like -F that output some preceding line; X at least we will need to find the last few lines, X but since we don't know how many, it's easiest to find them all. X X Otherwise, prefix_count != 0. Save just prefix_count lines at start X of the line buffer; they'll be moved to the proper location later. X Handle 1 more line than the context says (because we count 1 too many), X rounded up to the next power of 2 to speed index computation. */ X X if (no_diff_means_no_output && ! function_regexp.fastmap X && context < LIN_MAX / 4 && context < n0) X { X middle_guess = guess_lines (0, 0, p0 - filevec[0].prefix_end); X suffix_guess = guess_lines (0, 0, buffer0 + n0 - p0); X for (prefix_count = 1; prefix_count <= context; prefix_count *= 2) X continue; X alloc_lines0 = (prefix_count + middle_guess X + MIN (context, suffix_guess)); X } X else X { X prefix_count = 0; X alloc_lines0 = guess_lines (0, 0, n0); X } X X prefix_mask = prefix_count - 1; X lines = 0; X linbuf0 = xmalloc (alloc_lines0 * sizeof *linbuf0); X p0 = buffer0; X X /* If the prefix is needed, find the prefix lines. */ X if (! (no_diff_means_no_output X && filevec[0].prefix_end == p0 X && filevec[1].prefix_end == p1)) X { X end0 = filevec[0].prefix_end; X while (p0 != end0) X { X lin l = lines++ & prefix_mask; X if (l == alloc_lines0) X { X if (PTRDIFF_MAX / (2 * sizeof *linbuf0) <= alloc_lines0) X xalloc_die (); X alloc_lines0 *= 2; X linbuf0 = xrealloc (linbuf0, alloc_lines0 * sizeof *linbuf0); X } X linbuf0[l] = p0; X while (*p0++ != '\n') X continue; X } X } X buffered_prefix = prefix_count && context < lines ? context : lines; X X /* Allocate line buffer 1. */ X X middle_guess = guess_lines (lines, p0 - buffer0, p1 - filevec[1].prefix_end); X suffix_guess = guess_lines (lines, p0 - buffer0, buffer1 + n1 - p1); X alloc_lines1 = buffered_prefix + middle_guess + MIN (context, suffix_guess); X if (alloc_lines1 < buffered_prefix X || PTRDIFF_MAX / sizeof *linbuf1 <= alloc_lines1) X xalloc_die (); X linbuf1 = xmalloc (alloc_lines1 * sizeof *linbuf1); X X if (buffered_prefix != lines) X { X /* Rotate prefix lines to proper location. */ X for (i = 0; i < buffered_prefix; i++) X linbuf1[i] = linbuf0[(lines - context + i) & prefix_mask]; X for (i = 0; i < buffered_prefix; i++) X linbuf0[i] = linbuf1[i]; X } X X /* Initialize line buffer 1 from line buffer 0. */ X for (i = 0; i < buffered_prefix; i++) X linbuf1[i] = linbuf0[i] - buffer0 + buffer1; X X /* Record the line buffer, adjusted so that X linbuf[0] points at the first differing line. */ X filevec[0].linbuf = linbuf0 + buffered_prefix; X filevec[1].linbuf = linbuf1 + buffered_prefix; X filevec[0].linbuf_base = filevec[1].linbuf_base = - buffered_prefix; X filevec[0].alloc_lines = alloc_lines0 - buffered_prefix; X filevec[1].alloc_lines = alloc_lines1 - buffered_prefix; X filevec[0].prefix_lines = filevec[1].prefix_lines = lines; X} X X/* If 1 < k, then (2**k - prime_offset[k]) is the largest prime less X than 2**k. This table is derived from Chris K. Caldwell's list X . */ X Xstatic unsigned char const prime_offset[] = X{ X 0, 0, 1, 1, 3, 1, 3, 1, 5, 3, 3, 9, 3, 1, 3, 19, 15, 1, 5, 1, 3, 9, 3, X 15, 3, 39, 5, 39, 57, 3, 35, 1, 5, 9, 41, 31, 5, 25, 45, 7, 87, 21, X 11, 57, 17, 55, 21, 115, 59, 81, 27, 129, 47, 111, 33, 55, 5, 13, 27, X 55, 93, 1, 57, 25 X}; X X/* Verify that this host's size_t is not too wide for the above table. */ X Xverify (enough_prime_offsets, X sizeof (size_t) * CHAR_BIT <= sizeof prime_offset); X X/* Given a vector of two file_data objects, read the file associated X with each one, and build the table of equivalence classes. X Return nonzero if either file appears to be a binary file. X If PRETEND_BINARY is nonzero, pretend they are binary regardless. */ X Xbool Xread_files (struct file_data filevec[], bool pretend_binary) X{ X int i; X bool skip_test = text | pretend_binary; X bool appears_binary = pretend_binary | sip (&filevec[0], skip_test); X X if (filevec[0].desc != filevec[1].desc) X appears_binary |= sip (&filevec[1], skip_test | appears_binary); X else X { X filevec[1].buffer = filevec[0].buffer; X filevec[1].bufsize = filevec[0].bufsize; X filevec[1].buffered = filevec[0].buffered; X } X if (appears_binary) X { X set_binary_mode (filevec[0].desc, 1); X set_binary_mode (filevec[1].desc, 1); X return 1; X } X X find_identical_ends (filevec); X X equivs_alloc = filevec[0].alloc_lines + filevec[1].alloc_lines + 1; X if (PTRDIFF_MAX / sizeof *equivs <= equivs_alloc) X xalloc_die (); X equivs = xmalloc (equivs_alloc * sizeof *equivs); X /* Equivalence class 0 is permanently safe for lines that were not X hashed. Real equivalence classes start at 1. */ X equivs_index = 1; X X /* Allocate (one plus) a prime number of hash buckets. Use a prime X number between 1/3 and 2/3 of the value of equiv_allocs, X approximately. */ X for (i = 9; (size_t) 1 << i < equivs_alloc / 3; i++) X continue; X nbuckets = ((size_t) 1 << i) - prime_offset[i]; X if (PTRDIFF_MAX / sizeof *buckets <= nbuckets) X xalloc_die (); X buckets = zalloc ((nbuckets + 1) * sizeof *buckets); X buckets++; X X for (i = 0; i < 2; i++) X find_and_hash_each_line (&filevec[i]); X X filevec[0].equiv_max = filevec[1].equiv_max = equivs_index; X X free (equivs); X free (buckets - 1); X X return 0; X} END-of-contrib/diff/src/io.c echo x - contrib/diff/src/normal.c sed 's/^X//' >contrib/diff/src/normal.c << 'END-of-contrib/diff/src/normal.c' X/* Normal-format output routines for GNU DIFF. X X Copyright (C) 1988, 1989, 1993, 1995, 1998, 2001 Free Software X Foundation, Inc. X X This file is part of GNU DIFF. X X GNU DIFF is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X GNU DIFF is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; see the file COPYING. X If not, write to the Free Software Foundation, X 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#include "diff.h" X Xstatic void print_normal_hunk (struct change *); X X/* Print the edit-script SCRIPT as a normal diff. X INF points to an array of descriptions of the two files. */ X Xvoid Xprint_normal_script (struct change *script) X{ X print_script (script, find_change, print_normal_hunk); X} X X/* Print a hunk of a normal diff. X This is a contiguous portion of a complete edit script, X describing changes in consecutive lines. */ X Xstatic void Xprint_normal_hunk (struct change *hunk) X{ X lin first0, last0, first1, last1; X register lin i; X X /* Determine range of line numbers involved in each file. */ X enum changes changes = analyze_hunk (hunk, &first0, &last0, &first1, &last1); X if (!changes) X return; X X begin_output (); X X /* Print out the line number header for this hunk */ X print_number_range (',', &files[0], first0, last0); X fprintf (outfile, "%c", change_letter[changes]); X print_number_range (',', &files[1], first1, last1); X fprintf (outfile, "\n"); X X /* Print the lines that the first file has. */ X if (changes & OLD) X for (i = first0; i <= last0; i++) X print_1_line ("<", &files[0].linbuf[i]); X X if (changes == CHANGED) X fprintf (outfile, "---\n"); X X /* Print the lines that the second file has. */ X if (changes & NEW) X for (i = first1; i <= last1; i++) X print_1_line (">", &files[1].linbuf[i]); X} END-of-contrib/diff/src/normal.c echo x - contrib/diff/src/side.c sed 's/^X//' >contrib/diff/src/side.c << 'END-of-contrib/diff/src/side.c' X/* sdiff-format output routines for GNU DIFF. X X Copyright (C) 1991, 1992, 1993, 1998, 2001, 2002 Free Software X Foundation, Inc. X X This file is part of GNU DIFF. X X GNU DIFF is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY. No author or distributor X accepts responsibility to anyone for the consequences of using it X or for whether it serves any particular purpose or works at all, X unless he says so in writing. Refer to the GNU DIFF General Public X License for full details. X X Everyone is granted permission to copy, modify and redistribute X GNU DIFF, but only under the conditions described in the X GNU DIFF General Public License. A copy of this license is X supposed to have been given to you along with GNU DIFF so you X can know your rights and responsibilities. It should be in a X file named COPYING. Among other things, the copyright notice X and this notice must be preserved on all copies. */ X X#include "diff.h" X Xstatic void print_sdiff_common_lines (lin, lin); Xstatic void print_sdiff_hunk (struct change *); X X/* Next line number to be printed in the two input files. */ Xstatic lin next0, next1; X X/* Print the edit-script SCRIPT as a sdiff style output. */ X Xvoid Xprint_sdiff_script (struct change *script) X{ X begin_output (); X X next0 = next1 = - files[0].prefix_lines; X print_script (script, find_change, print_sdiff_hunk); X X print_sdiff_common_lines (files[0].valid_lines, files[1].valid_lines); X} X X/* Tab from column FROM to column TO, where FROM <= TO. Yield TO. */ X Xstatic unsigned int Xtab_from_to (unsigned int from, unsigned int to) X{ X FILE *out = outfile; X unsigned int tab; X X if (!expand_tabs) X for (tab = from + TAB_WIDTH - from % TAB_WIDTH; tab <= to; tab += TAB_WIDTH) X { X putc ('\t', out); X from = tab; X } X while (from++ < to) X putc (' ', out); X return to; X} X X/* X * Print the text for half an sdiff line. This means truncate to width X * observing tabs, and trim a trailing newline. Returns the last column X * written (not the number of chars). X */ Xstatic unsigned int Xprint_half_line (char const *const *line, unsigned int indent, X unsigned int out_bound) X{ X FILE *out = outfile; X register unsigned int in_position = 0; X register unsigned int out_position = 0; X register char const *text_pointer = line[0]; X register char const *text_limit = line[1]; X X while (text_pointer < text_limit) X { X register unsigned char c = *text_pointer++; X X switch (c) X { X case '\t': X { X unsigned int spaces = TAB_WIDTH - in_position % TAB_WIDTH; X if (in_position == out_position) X { X unsigned int tabstop = out_position + spaces; X if (expand_tabs) X { X if (out_bound < tabstop) X tabstop = out_bound; X for (; out_position < tabstop; out_position++) X putc (' ', out); X } X else X if (tabstop < out_bound) X { X out_position = tabstop; X putc (c, out); X } X } X in_position += spaces; X } X break; X X case '\r': X { X putc (c, out); X tab_from_to (0, indent); X in_position = out_position = 0; X } X break; X X case '\b': X if (in_position != 0 && --in_position < out_bound) X { X if (out_position <= in_position) X /* Add spaces to make up for suppressed tab past out_bound. */ X for (; out_position < in_position; out_position++) X putc (' ', out); X else X { X out_position = in_position; X putc (c, out); X } X } X break; X X case '\f': X case '\v': X control_char: X if (in_position < out_bound) X putc (c, out); X break; X X default: X if (! ISPRINT (c)) X goto control_char; X /* falls through */ X case ' ': X if (in_position++ < out_bound) X { X out_position = in_position; X putc (c, out); X } X break; X X case '\n': X return out_position; X } X } X X return out_position; X} X X/* X * Print side by side lines with a separator in the middle. X * 0 parameters are taken to indicate white space text. X * Blank lines that can easily be caught are reduced to a single newline. X */ X Xstatic void Xprint_1sdiff_line (char const *const *left, char sep, X char const *const *right) X{ X FILE *out = outfile; X unsigned int hw = sdiff_half_width, c2o = sdiff_column2_offset; X unsigned int col = 0; X bool put_newline = 0; X X if (left) X { X put_newline |= left[1][-1] == '\n'; X col = print_half_line (left, 0, hw); X } X X if (sep != ' ') X { X col = tab_from_to (col, (hw + c2o - 1) / 2) + 1; X if (sep == '|' && put_newline != (right[1][-1] == '\n')) X sep = put_newline ? '/' : '\\'; X putc (sep, out); X } X X if (right) X { X put_newline |= right[1][-1] == '\n'; X if (**right != '\n') X { X col = tab_from_to (col, c2o); X print_half_line (right, col, hw); X } X } X X if (put_newline) X putc ('\n', out); X} X X/* Print lines common to both files in side-by-side format. */ Xstatic void Xprint_sdiff_common_lines (lin limit0, lin limit1) X{ X lin i0 = next0, i1 = next1; X X if (!suppress_common_lines && (i0 != limit0 || i1 != limit1)) X { X if (sdiff_merge_assist) X { X long len0 = limit0 - i0; X long len1 = limit1 - i1; X fprintf (outfile, "i%ld,%ld\n", len0, len1); X } X X if (!left_column) X { X while (i0 != limit0 && i1 != limit1) X print_1sdiff_line (&files[0].linbuf[i0++], ' ', X &files[1].linbuf[i1++]); X while (i1 != limit1) X print_1sdiff_line (0, ')', &files[1].linbuf[i1++]); X } X while (i0 != limit0) X print_1sdiff_line (&files[0].linbuf[i0++], '(', 0); X } X X next0 = limit0; X next1 = limit1; X} X X/* Print a hunk of an sdiff diff. X This is a contiguous portion of a complete edit script, X describing changes in consecutive lines. */ X Xstatic void Xprint_sdiff_hunk (struct change *hunk) X{ X lin first0, last0, first1, last1; X register lin i, j; X X /* Determine range of line numbers involved in each file. */ X enum changes changes = X analyze_hunk (hunk, &first0, &last0, &first1, &last1); X if (!changes) X return; X X /* Print out lines up to this change. */ X print_sdiff_common_lines (first0, first1); X X if (sdiff_merge_assist) X { X long len0 = last0 - first0 + 1; X long len1 = last1 - first1 + 1; X fprintf (outfile, "c%ld,%ld\n", len0, len1); X } X X /* Print ``xxx | xxx '' lines */ X if (changes == CHANGED) X { X for (i = first0, j = first1; i <= last0 && j <= last1; i++, j++) X print_1sdiff_line (&files[0].linbuf[i], '|', &files[1].linbuf[j]); X changes = (i <= last0 ? OLD : 0) + (j <= last1 ? NEW : 0); X next0 = first0 = i; X next1 = first1 = j; X } X X /* Print `` > xxx '' lines */ X if (changes & NEW) X { X for (j = first1; j <= last1; ++j) X print_1sdiff_line (0, '>', &files[1].linbuf[j]); X next1 = j; X } X X /* Print ``xxx < '' lines */ X if (changes & OLD) X { X for (i = first0; i <= last0; ++i) X print_1sdiff_line (&files[0].linbuf[i], '<', 0); X next0 = i; X } X} END-of-contrib/diff/src/side.c echo x - contrib/diff/src/util.c sed 's/^X//' >contrib/diff/src/util.c << 'END-of-contrib/diff/src/util.c' X/* Support routines for GNU DIFF. X X Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1998, 2001, 2002 X Free Software Foundation, Inc. X X This file is part of GNU DIFF. X X GNU DIFF is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X GNU DIFF is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; see the file COPYING. X If not, write to the Free Software Foundation, X 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#include "diff.h" X#include X#include X#include X#include X#include X Xchar const pr_program[] = PR_PROGRAM; X X/* Queue up one-line messages to be printed at the end, X when -l is specified. Each message is recorded with a `struct msg'. */ X Xstruct msg X{ X struct msg *next; X char args[1]; /* Format + 4 args, each '\0' terminated, concatenated. */ X}; X X/* Head of the chain of queues messages. */ X Xstatic struct msg *msg_chain; X X/* Tail of the chain of queues messages. */ X Xstatic struct msg **msg_chain_end = &msg_chain; X X/* Use when a system call returns non-zero status. X NAME should normally be the file name. */ X Xvoid Xperror_with_name (char const *name) X{ X error (0, errno, "%s", name); X} X X/* Use when a system call returns non-zero status and that is fatal. */ X Xvoid Xpfatal_with_name (char const *name) X{ X int e = errno; X print_message_queue (); X error (EXIT_TROUBLE, e, "%s", name); X abort (); X} X X/* Print an error message containing MSGID, then exit. */ X Xvoid Xfatal (char const *msgid) X{ X print_message_queue (); X error (EXIT_TROUBLE, 0, "%s", _(msgid)); X abort (); X} X X/* Like printf, except if -l in effect then save the message and print later. X This is used for things like "Only in ...". */ X Xvoid Xmessage (char const *format_msgid, char const *arg1, char const *arg2) X{ X message5 (format_msgid, arg1, arg2, 0, 0); X} X Xvoid Xmessage5 (char const *format_msgid, char const *arg1, char const *arg2, X char const *arg3, char const *arg4) X{ X if (paginate) X { X char *p; X char const *arg[5]; X int i; X size_t size[5]; X size_t total_size = offsetof (struct msg, args); X struct msg *new; X X arg[0] = format_msgid; X arg[1] = arg1; X arg[2] = arg2; X arg[3] = arg3 ? arg3 : ""; X arg[4] = arg4 ? arg4 : ""; X X for (i = 0; i < 5; i++) X total_size += size[i] = strlen (arg[i]) + 1; X X new = xmalloc (total_size); X X for (i = 0, p = new->args; i < 5; p += size[i++]) X memcpy (p, arg[i], size[i]); X X *msg_chain_end = new; X new->next = 0; X msg_chain_end = &new->next; X } X else X { X if (sdiff_merge_assist) X putchar (' '); X printf (_(format_msgid), arg1, arg2, arg3, arg4); X } X} X X/* Output all the messages that were saved up by calls to `message'. */ X Xvoid Xprint_message_queue (void) X{ X char const *arg[5]; X int i; X struct msg *m = msg_chain; X X while (m) X { X struct msg *next = m->next; X arg[0] = m->args; X for (i = 0; i < 4; i++) X arg[i + 1] = arg[i] + strlen (arg[i]) + 1; X printf (_(arg[0]), arg[1], arg[2], arg[3], arg[4]); X free (m); X m = next; X } X} X X/* Call before outputting the results of comparing files NAME0 and NAME1 X to set up OUTFILE, the stdio stream for the output to go to. X X Usually, OUTFILE is just stdout. But when -l was specified X we fork off a `pr' and make OUTFILE a pipe to it. X `pr' then outputs to our stdout. */ X Xstatic char const *current_name0; Xstatic char const *current_name1; Xstatic bool currently_recursive; X Xvoid Xsetup_output (char const *name0, char const *name1, bool recursive) X{ X current_name0 = name0; X current_name1 = name1; X currently_recursive = recursive; X outfile = 0; X} X X#if HAVE_WORKING_FORK || HAVE_WORKING_VFORK Xstatic pid_t pr_pid; X#endif X Xvoid Xbegin_output (void) X{ X char *name; X X if (outfile != 0) X return; X X /* Construct the header of this piece of diff. */ X name = xmalloc (strlen (current_name0) + strlen (current_name1) X + strlen (switch_string) + 7); X X /* POSIX 1003.1-2001 specifies this format. But there are some bugs in X the standard: it says that we must print only the last component X of the pathnames, and it requires two spaces after "diff" if X there are no options. These requirements are silly and do not X match historical practice. */ X sprintf (name, "diff%s %s %s", switch_string, current_name0, current_name1); X X if (paginate) X { X if (fflush (stdout) != 0) X pfatal_with_name (_("write failed")); X X /* Make OUTFILE a pipe to a subsidiary `pr'. */ X { X#if HAVE_WORKING_FORK || HAVE_WORKING_VFORK X int pipes[2]; X X if (pipe (pipes) != 0) X pfatal_with_name ("pipe"); X X pr_pid = vfork (); X if (pr_pid < 0) X pfatal_with_name ("fork"); X X if (pr_pid == 0) X { X close (pipes[1]); X if (pipes[0] != STDIN_FILENO) X { X if (dup2 (pipes[0], STDIN_FILENO) < 0) X pfatal_with_name ("dup2"); X close (pipes[0]); X } X X execl (pr_program, pr_program, "-h", name, 0); X _exit (errno == ENOEXEC ? 126 : 127); X } X else X { X close (pipes[0]); X outfile = fdopen (pipes[1], "w"); X if (!outfile) X pfatal_with_name ("fdopen"); X } X#else X char *command = xmalloc (sizeof pr_program - 1 + 7 X + quote_system_arg ((char *) 0, name) + 1); X char *p; X sprintf (command, "%s -f -h ", pr_program); X p = command + sizeof pr_program - 1 + 7; X p += quote_system_arg (p, name); X *p = 0; X errno = 0; X outfile = popen (command, "w"); X if (!outfile) X pfatal_with_name (command); X free (command); X#endif X } X } X else X { X X /* If -l was not specified, output the diff straight to `stdout'. */ X X outfile = stdout; X X /* If handling multiple files (because scanning a directory), X print which files the following output is about. */ X if (currently_recursive) X printf ("%s\n", name); X } X X free (name); X X /* A special header is needed at the beginning of context output. */ X switch (output_style) X { X case OUTPUT_CONTEXT: X print_context_header (files, 0); X break; X X case OUTPUT_UNIFIED: X print_context_header (files, 1); X break; X X default: X break; X } X} X X/* Call after the end of output of diffs for one file. X Close OUTFILE and get rid of the `pr' subfork. */ X Xvoid Xfinish_output (void) X{ X if (outfile != 0 && outfile != stdout) X { X int wstatus; X int werrno = 0; X if (ferror (outfile)) X fatal ("write failed"); X#if ! (HAVE_WORKING_FORK || HAVE_WORKING_VFORK) X wstatus = pclose (outfile); X if (wstatus == -1) X werrno = errno; X#else X if (fclose (outfile) != 0) X pfatal_with_name (_("write failed")); X if (waitpid (pr_pid, &wstatus, 0) < 0) X pfatal_with_name ("waitpid"); X#endif X if (! werrno && WIFEXITED (wstatus) && WEXITSTATUS (wstatus) == 127) X error (EXIT_TROUBLE, 0, _("subsidiary program `%s' not found"), X pr_program); X if (wstatus != 0) X error (EXIT_TROUBLE, werrno, _("subsidiary program `%s' failed"), X pr_program); X } X X outfile = 0; X} X X/* Compare two lines (typically one from each input file) X according to the command line options. X For efficiency, this is invoked only when the lines do not match exactly X but an option like -i might cause us to ignore the difference. X Return nonzero if the lines differ. */ X Xbool Xlines_differ (char const *s1, char const *s2) X{ X register unsigned char const *t1 = (unsigned char const *) s1; X register unsigned char const *t2 = (unsigned char const *) s2; X size_t column = 0; X X while (1) X { X register unsigned char c1 = *t1++; X register unsigned char c2 = *t2++; X X /* Test for exact char equality first, since it's a common case. */ X if (c1 != c2) X { X switch (ignore_white_space) X { X case IGNORE_ALL_SPACE: X /* For -w, just skip past any white space. */ X while (ISSPACE (c1) && c1 != '\n') c1 = *t1++; X while (ISSPACE (c2) && c2 != '\n') c2 = *t2++; X break; X X case IGNORE_SPACE_CHANGE: X /* For -b, advance past any sequence of white space in X line 1 and consider it just one space, or nothing at X all if it is at the end of the line. */ X if (ISSPACE (c1)) X { X while (c1 != '\n') X { X c1 = *t1++; X if (! ISSPACE (c1)) X { X --t1; X c1 = ' '; X break; X } X } X } X X /* Likewise for line 2. */ X if (ISSPACE (c2)) X { X while (c2 != '\n') X { X c2 = *t2++; X if (! ISSPACE (c2)) X { X --t2; X c2 = ' '; X break; X } X } X } X X if (c1 != c2) X { X /* If we went too far when doing the simple test X for equality, go back to the first non-white-space X character in both sides and try again. */ X if (c2 == ' ' && c1 != '\n' X && (unsigned char const *) s1 + 1 < t1 X && ISSPACE (t1[-2])) X { X --t1; X continue; X } X if (c1 == ' ' && c2 != '\n' X && (unsigned char const *) s2 + 1 < t2 X && ISSPACE (t2[-2])) X { X --t2; X continue; X } X } X X break; X X case IGNORE_TAB_EXPANSION: X if ((c1 == ' ' && c2 == '\t') X || (c1 == '\t' && c2 == ' ')) X { X size_t column2 = column; X for (;; c1 = *t1++) X { X if (c1 == ' ') X column++; X else if (c1 == '\t') X column += TAB_WIDTH - column % TAB_WIDTH; X else X break; X } X for (;; c2 = *t2++) X { X if (c2 == ' ') X column2++; X else if (c2 == '\t') X column2 += TAB_WIDTH - column2 % TAB_WIDTH; X else X break; X } X if (column != column2) X return 1; X } X break; X X case IGNORE_NO_WHITE_SPACE: X break; X } X X /* Lowercase all letters if -i is specified. */ X X if (ignore_case) X { X c1 = TOLOWER (c1); X c2 = TOLOWER (c2); X } X X if (c1 != c2) X break; X } X if (c1 == '\n') X return 0; X X column += c1 == '\t' ? TAB_WIDTH - column % TAB_WIDTH : 1; X } X X return 1; X} X X/* Find the consecutive changes at the start of the script START. X Return the last link before the first gap. */ X Xstruct change * Xfind_change (struct change *start) X{ X return start; X} X Xstruct change * Xfind_reverse_change (struct change *start) X{ X return start; X} X X/* Divide SCRIPT into pieces by calling HUNKFUN and X print each piece with PRINTFUN. X Both functions take one arg, an edit script. X X HUNKFUN is called with the tail of the script X and returns the last link that belongs together with the start X of the tail. X X PRINTFUN takes a subscript which belongs together (with a null X link at the end) and prints it. */ X Xvoid Xprint_script (struct change *script, X struct change * (*hunkfun) (struct change *), X void (*printfun) (struct change *)) X{ X struct change *next = script; X X while (next) X { X struct change *this, *end; X X /* Find a set of changes that belong together. */ X this = next; X end = (*hunkfun) (next); X X /* Disconnect them from the rest of the changes, X making them a hunk, and remember the rest for next iteration. */ X next = end->link; X end->link = 0; X#ifdef DEBUG X debug_script (this); X#endif X X /* Print this hunk. */ X (*printfun) (this); X X /* Reconnect the script so it will all be freed properly. */ X end->link = next; X } X} X X/* Print the text of a single line LINE, X flagging it with the characters in LINE_FLAG (which say whether X the line is inserted, deleted, changed, etc.). */ X Xvoid Xprint_1_line (char const *line_flag, char const *const *line) X{ X char const *base = line[0], *limit = line[1]; /* Help the compiler. */ X FILE *out = outfile; /* Help the compiler some more. */ X char const *flag_format = 0; X X /* If -T was specified, use a Tab between the line-flag and the text. X Otherwise use a Space (as Unix diff does). X Print neither space nor tab if line-flags are empty. */ X X if (line_flag && *line_flag) X { X flag_format = initial_tab ? "%s\t" : "%s "; X fprintf (out, flag_format, line_flag); X } X X output_1_line (base, limit, flag_format, line_flag); X X if ((!line_flag || line_flag[0]) && limit[-1] != '\n') X fprintf (out, "\n\\ %s\n", _("No newline at end of file")); X} X X/* Output a line from BASE up to LIMIT. X With -t, expand white space characters to spaces, and if FLAG_FORMAT X is nonzero, output it with argument LINE_FLAG after every X internal carriage return, so that tab stops continue to line up. */ X Xvoid Xoutput_1_line (char const *base, char const *limit, char const *flag_format, X char const *line_flag) X{ X if (!expand_tabs) X fwrite (base, limit - base, 1, outfile); X else X { X register FILE *out = outfile; X register unsigned char c; X register char const *t = base; X register unsigned int column = 0; X X while (t < limit) X switch ((c = *t++)) X { X case '\t': X { X unsigned int spaces = TAB_WIDTH - column % TAB_WIDTH; X column += spaces; X do X putc (' ', out); X while (--spaces); X } X break; X X case '\r': X putc (c, out); X if (flag_format && t < limit && *t != '\n') X fprintf (out, flag_format, line_flag); X column = 0; X break; X X case '\b': X if (column == 0) X continue; X column--; X putc (c, out); X break; X X default: X if (ISPRINT (c)) X column++; X putc (c, out); X break; X } X } X} X Xchar const change_letter[] = { 0, 'd', 'a', 'c' }; X X/* Translate an internal line number (an index into diff's table of lines) X into an actual line number in the input file. X The internal line number is I. FILE points to the data on the file. X X Internal line numbers count from 0 starting after the prefix. X Actual line numbers count from 1 within the entire file. */ X Xlin Xtranslate_line_number (struct file_data const *file, lin i) X{ X return i + file->prefix_lines + 1; X} X X/* Translate a line number range. This is always done for printing, X so for convenience translate to long rather than lin, so that the X caller can use printf with "%ld" without casting. */ X Xvoid Xtranslate_range (struct file_data const *file, X lin a, lin b, X long *aptr, long *bptr) X{ X *aptr = translate_line_number (file, a - 1) + 1; X *bptr = translate_line_number (file, b + 1) - 1; X} X X/* Print a pair of line numbers with SEPCHAR, translated for file FILE. X If the two numbers are identical, print just one number. X X Args A and B are internal line numbers. X We print the translated (real) line numbers. */ X Xvoid Xprint_number_range (char sepchar, struct file_data *file, lin a, lin b) X{ X long trans_a, trans_b; X translate_range (file, a, b, &trans_a, &trans_b); X X /* Note: we can have B < A in the case of a range of no lines. X In this case, we should print the line number before the range, X which is B. */ X if (trans_b > trans_a) X fprintf (outfile, "%ld%c%ld", trans_a, sepchar, trans_b); X else X fprintf (outfile, "%ld", trans_b); X} X X/* Look at a hunk of edit script and report the range of lines in each file X that it applies to. HUNK is the start of the hunk, which is a chain X of `struct change'. The first and last line numbers of file 0 are stored in X *FIRST0 and *LAST0, and likewise for file 1 in *FIRST1 and *LAST1. X Note that these are internal line numbers that count from 0. X X If no lines from file 0 are deleted, then FIRST0 is LAST0+1. X X Return UNCHANGED if only ignorable lines are inserted or deleted, X OLD if lines of file 0 are deleted, X NEW if lines of file 1 are inserted, X and CHANGED if both kinds of changes are found. */ X Xenum changes Xanalyze_hunk (struct change *hunk, X lin *first0, lin *last0, X lin *first1, lin *last1) X{ X struct change *next; X lin l0, l1; X lin show_from, show_to; X lin i; X bool trivial = ignore_blank_lines || ignore_regexp.fastmap; X size_t trivial_length = (int) ignore_blank_lines - 1; X /* If 0, ignore zero-length lines; X if SIZE_MAX, do not ignore lines just because of their length. */ X X char const * const *linbuf0 = files[0].linbuf; /* Help the compiler. */ X char const * const *linbuf1 = files[1].linbuf; X X show_from = show_to = 0; X X *first0 = hunk->line0; X *first1 = hunk->line1; X X next = hunk; X do X { X l0 = next->line0 + next->deleted - 1; X l1 = next->line1 + next->inserted - 1; X show_from += next->deleted; X show_to += next->inserted; X X for (i = next->line0; i <= l0 && trivial; i++) X { X char const *line = linbuf0[i]; X size_t len = linbuf0[i + 1] - line - 1; X if (len != trivial_length X && (! ignore_regexp.fastmap X || re_search (&ignore_regexp, line, len, 0, len, 0) < 0)) X trivial = 0; X } X X for (i = next->line1; i <= l1 && trivial; i++) X { X char const *line = linbuf1[i]; X size_t len = linbuf1[i + 1] - line - 1; X if (len != trivial_length X && (! ignore_regexp.fastmap X || re_search (&ignore_regexp, line, len, 0, len, 0) < 0)) X trivial = 0; X } X } X while ((next = next->link) != 0); X X *last0 = l0; X *last1 = l1; X X /* If all inserted or deleted lines are ignorable, X tell the caller to ignore this hunk. */ X X if (trivial) X return UNCHANGED; X X return (show_from ? OLD : UNCHANGED) | (show_to ? NEW : UNCHANGED); X} X X/* Concatenate three strings, returning a newly malloc'd string. */ X Xchar * Xconcat (char const *s1, char const *s2, char const *s3) X{ X char *new = xmalloc (strlen (s1) + strlen (s2) + strlen (s3) + 1); X sprintf (new, "%s%s%s", s1, s2, s3); X return new; X} X X/* Yield a new block of SIZE bytes, initialized to zero. */ X Xvoid * Xzalloc (size_t size) X{ X void *p = xmalloc (size); X memset (p, 0, size); X return p; X} X X/* Yield the newly malloc'd pathname X of the file in DIR whose filename is FILE. */ X Xchar * Xdir_file_pathname (char const *dir, char const *file) X{ X char const *base = base_name (dir); X bool omit_slash = !*base || base[strlen (base) - 1] == '/'; X return concat (dir, "/" + omit_slash, file); X} X Xvoid Xdebug_script (struct change *sp) X{ X fflush (stdout); X X for (; sp; sp = sp->link) X { X long line0 = sp->line0; X long line1 = sp->line1; X long deleted = sp->deleted; X long inserted = sp->inserted; X fprintf (stderr, "%3ld %3ld delete %ld insert %ld\n", X line0, line1, deleted, inserted); X } X X fflush (stderr); X} END-of-contrib/diff/src/util.c echo x - contrib/diff/src/diff3.c sed 's/^X//' >contrib/diff/src/diff3.c << 'END-of-contrib/diff/src/diff3.c' X/* diff3 - compare three files line by line X X Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1998, 2001, X 2002 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. X See the GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; see the file COPYING. X If not, write to the Free Software Foundation, X 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#include "system.h" X Xstatic char const copyright_string[] = X "Copyright (C) 2002 Free Software Foundation, Inc."; X Xstatic char const authorship_msgid[] = N_("Written by Randy Smith."); X X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X Xextern char const version_string[]; X X/* X * Internal data structures and macros for the diff3 program; includes X * data structures for both diff3 diffs and normal diffs. X */ X X/* Different files within a three way diff. */ X#define FILE0 0 X#define FILE1 1 X#define FILE2 2 X X/* X * A three way diff is built from two two-way diffs; the file which X * the two two-way diffs share is: X */ X#define FILEC FILE2 X X/* X * Different files within a two way diff. X * FC is the common file, FO the other file. X */ X#define FO 0 X#define FC 1 X X/* The ranges are indexed by */ X#define RANGE_START 0 X#define RANGE_END 1 X Xenum diff_type { X ERROR, /* Should not be used */ X ADD, /* Two way diff add */ X CHANGE, /* Two way diff change */ X DELETE, /* Two way diff delete */ X DIFF_ALL, /* All three are different */ X DIFF_1ST, /* Only the first is different */ X DIFF_2ND, /* Only the second */ X DIFF_3RD /* Only the third */ X}; X X/* Two way diff */ Xstruct diff_block { X lin ranges[2][2]; /* Ranges are inclusive */ X char **lines[2]; /* The actual lines (may contain nulls) */ X size_t *lengths[2]; /* Line lengths (including newlines, if any) */ X struct diff_block *next; X}; X X/* Three way diff */ X Xstruct diff3_block { X enum diff_type correspond; /* Type of diff */ X lin ranges[3][2]; /* Ranges are inclusive */ X char **lines[3]; /* The actual lines (may contain nulls) */ X size_t *lengths[3]; /* Line lengths (including newlines, if any) */ X struct diff3_block *next; X}; X X/* X * Access the ranges on a diff block. X */ X#define D_LOWLINE(diff, filenum) \ X ((diff)->ranges[filenum][RANGE_START]) X#define D_HIGHLINE(diff, filenum) \ X ((diff)->ranges[filenum][RANGE_END]) X#define D_NUMLINES(diff, filenum) \ X (D_HIGHLINE (diff, filenum) - D_LOWLINE (diff, filenum) + 1) X X/* X * Access the line numbers in a file in a diff by relative line X * numbers (i.e. line number within the diff itself). Note that these X * are lvalues and can be used for assignment. X */ X#define D_RELNUM(diff, filenum, linenum) \ X ((diff)->lines[filenum][linenum]) X#define D_RELLEN(diff, filenum, linenum) \ X ((diff)->lengths[filenum][linenum]) X X/* X * And get at them directly, when that should be necessary. X */ X#define D_LINEARRAY(diff, filenum) \ X ((diff)->lines[filenum]) X#define D_LENARRAY(diff, filenum) \ X ((diff)->lengths[filenum]) X X/* X * Next block. X */ X#define D_NEXT(diff) ((diff)->next) X X/* X * Access the type of a diff3 block. X */ X#define D3_TYPE(diff) ((diff)->correspond) X X/* X * Line mappings based on diffs. The first maps off the top of the X * diff, the second off of the bottom. X */ X#define D_HIGH_MAPLINE(diff, fromfile, tofile, linenum) \ X ((linenum) \ X - D_HIGHLINE ((diff), (fromfile)) \ X + D_HIGHLINE ((diff), (tofile))) X X#define D_LOW_MAPLINE(diff, fromfile, tofile, linenum) \ X ((linenum) \ X - D_LOWLINE ((diff), (fromfile)) \ X + D_LOWLINE ((diff), (tofile))) X X/* Options variables for flags set on command line. */ X X/* If nonzero, treat all files as text files, never as binary. */ Xstatic bool text; X X/* If nonzero, write out an ed script instead of the standard diff3 format. */ Xstatic bool edscript; X X/* If nonzero, in the case of overlapping diffs (type DIFF_ALL), X preserve the lines which would normally be deleted from X file 1 with a special flagging mechanism. */ Xstatic bool flagging; X X/* Use a tab to align output lines (-T). */ Xstatic bool initial_tab; X X/* If nonzero, do not output information for overlapping diffs. */ Xstatic bool simple_only; X X/* If nonzero, do not output information for non-overlapping diffs. */ Xstatic bool overlap_only; X X/* If nonzero, show information for DIFF_2ND diffs. */ Xstatic bool show_2nd; X X/* If nonzero, include `:wq' at the end of the script X to write out the file being edited. */ Xstatic bool finalwrite; X X/* If nonzero, output a merged file. */ Xstatic bool merge; X Xchar *program_name; X Xstatic char *read_diff (char const *, char const *, char **); Xstatic char *scan_diff_line (char *, char **, size_t *, char *, char); Xstatic enum diff_type process_diff_control (char **, struct diff_block *); Xstatic bool compare_line_list (char * const[], size_t const[], char * const[], size_t const[], lin); Xstatic bool copy_stringlist (char * const[], size_t const[], char *[], size_t[], lin); Xstatic bool output_diff3_edscript (FILE *, struct diff3_block *, int const[3], int const[3], char const *, char const *, char const *); Xstatic bool output_diff3_merge (FILE *, FILE *, struct diff3_block *, int const[3], int const[3], char const *, char const *, char const *); Xstatic struct diff3_block *create_diff3_block (lin, lin, lin, lin, lin, lin); Xstatic struct diff3_block *make_3way_diff (struct diff_block *, struct diff_block *); Xstatic struct diff3_block *reverse_diff3_blocklist (struct diff3_block *); Xstatic struct diff3_block *using_to_diff3_block (struct diff_block *[2], struct diff_block *[2], int, int, struct diff3_block const *); Xstatic struct diff_block *process_diff (char const *, char const *, struct diff_block **); Xstatic void check_stdout (void); Xstatic void fatal (char const *) __attribute__((noreturn)); Xstatic void output_diff3 (FILE *, struct diff3_block *, int const[3], int const[3]); Xstatic void perror_with_exit (char const *) __attribute__((noreturn)); Xstatic void try_help (char const *, char const *) __attribute__((noreturn)); Xstatic void usage (void); X Xstatic char const *diff_program = DEFAULT_DIFF_PROGRAM; X X/* Values for long options that do not have single-letter equivalents. */ Xenum X{ X DIFF_PROGRAM_OPTION = CHAR_MAX + 1, X HELP_OPTION X}; X Xstatic struct option const longopts[] = X{ X {"text", 0, 0, 'a'}, X {"show-all", 0, 0, 'A'}, X {"ed", 0, 0, 'e'}, X {"diff-program", 1, 0, DIFF_PROGRAM_OPTION}, X {"show-overlap", 0, 0, 'E'}, X {"label", 1, 0, 'L'}, X {"merge", 0, 0, 'm'}, X {"initial-tab", 0, 0, 'T'}, X {"overlap-only", 0, 0, 'x'}, X {"easy-only", 0, 0, '3'}, X {"version", 0, 0, 'v'}, X {"help", 0, 0, HELP_OPTION}, X {0, 0, 0, 0} X}; X X/* X * Main program. Calls diff twice on two pairs of input files, X * combines the two diffs, and outputs them. X */ Xint Xmain (int argc, char **argv) X{ X int c, i; X int common; X int mapping[3]; X int rev_mapping[3]; X int incompat = 0; X bool conflicts_found; X struct diff_block *thread0, *thread1, *last_block; X struct diff3_block *diff3; X int tag_count = 0; X char *tag_strings[3]; X char *commonname; X char **file; X struct stat statb; X X exit_failure = 2; X initialize_main (&argc, &argv); X program_name = argv[0]; X setlocale (LC_ALL, ""); X bindtextdomain (PACKAGE, LOCALEDIR); X textdomain (PACKAGE); X c_stack_action (c_stack_die); X X while ((c = getopt_long (argc, argv, "aeimvx3AEL:TX", longopts, 0)) != -1) X { X switch (c) X { X case 'a': X text = 1; X break; X case 'A': X show_2nd = 1; X flagging = 1; X incompat++; X break; X case 'x': X overlap_only = 1; X incompat++; X break; X case '3': X simple_only = 1; X incompat++; X break; X case 'i': X finalwrite = 1; X break; X case 'm': X merge = 1; X break; X case 'X': X overlap_only = 1; X /* Fall through. */ X case 'E': X flagging = 1; X /* Fall through. */ X case 'e': X incompat++; X break; X case 'T': X initial_tab = 1; X break; X case 'v': X printf ("diff3 %s\n%s\n\n%s\n\n%s\n", X version_string, copyright_string, X _(free_software_msgid), _(authorship_msgid)); X check_stdout (); X return EXIT_SUCCESS; X case DIFF_PROGRAM_OPTION: X diff_program = optarg; X break; X case HELP_OPTION: X usage (); X check_stdout (); X return EXIT_SUCCESS; X case 'L': X /* Handle up to three -L options. */ X if (tag_count < 3) X { X tag_strings[tag_count++] = optarg; X break; X } X try_help ("too many file label options", 0); X default: X try_help (0, 0); X } X } X X edscript = incompat & ~merge; /* -AeExX3 without -m implies ed script. */ X show_2nd |= ~incompat & merge; /* -m without -AeExX3 implies -A. */ X flagging |= ~incompat & merge; X X if (incompat > 1 /* Ensure at most one of -AeExX3. */ X || finalwrite & merge /* -i -m would rewrite input file. */ X || (tag_count && ! flagging)) /* -L requires one of -AEX. */ X try_help ("incompatible options", 0); X X if (argc - optind != 3) X { X if (argc - optind < 3) X try_help ("missing operand after `%s'", argv[argc - 1]); X else X try_help ("extra operand `%s'", argv[optind + 3]); X } X X file = &argv[optind]; X X for (i = tag_count; i < 3; i++) X tag_strings[i] = file[i]; X X /* Always compare file1 to file2, even if file2 is "-". X This is needed for -mAeExX3. Using the file0 as X the common file would produce wrong results, because if the X file0-file1 diffs didn't line up with the file0-file2 diffs X (which is entirely possible since we don't use diff's -n option), X diff3 might report phantom changes from file1 to file2. X X Also, try to compare file0 to file1, because this is where X changes are expected to come from. Diffing between these pairs X of files is more likely to avoid phantom changes from file0 to file1. X X Historically, the default common file was file2, so some older X applications (e.g. Emacs ediff) used file2 as the ancestor. So, X for compatibility, if this is a 3-way diff (not a merge or X edscript), prefer file2 as the common file. */ X X common = 2 - (edscript | merge); X X if (strcmp (file[common], "-") == 0) X { X /* Sigh. We've got standard input as the common file. We can't X call diff twice on stdin. Use the other arg as the common X file instead. */ X common = 3 - common; X if (strcmp (file[0], "-") == 0 || strcmp (file[common], "-") == 0) X fatal ("`-' specified for more than one input file"); X } X X mapping[0] = 0; X mapping[1] = 3 - common; X mapping[2] = common; X X for (i = 0; i < 3; i++) X rev_mapping[mapping[i]] = i; X X for (i = 0; i < 3; i++) X if (strcmp (file[i], "-") != 0) X { X if (stat (file[i], &statb) < 0) X perror_with_exit (file[i]); X else if (S_ISDIR (statb.st_mode)) X error (EXIT_TROUBLE, EISDIR, "%s", file[i]); X } X X#ifdef SIGCHLD X /* System V fork+wait does not work if SIGCHLD is ignored. */ X signal (SIGCHLD, SIG_DFL); X#endif X X commonname = file[rev_mapping[FILEC]]; X thread1 = process_diff (file[rev_mapping[FILE1]], commonname, &last_block); X thread0 = process_diff (file[rev_mapping[FILE0]], commonname, &last_block); X diff3 = make_3way_diff (thread0, thread1); X if (edscript) X conflicts_found X = output_diff3_edscript (stdout, diff3, mapping, rev_mapping, X tag_strings[0], tag_strings[1], tag_strings[2]); X else if (merge) X { X if (! freopen (file[rev_mapping[FILE0]], "r", stdin)) X perror_with_exit (file[rev_mapping[FILE0]]); X conflicts_found X = output_diff3_merge (stdin, stdout, diff3, mapping, rev_mapping, X tag_strings[0], tag_strings[1], tag_strings[2]); X if (ferror (stdin)) X fatal ("read failed"); X } X else X { X output_diff3 (stdout, diff3, mapping, rev_mapping); X conflicts_found = 0; X } X X check_stdout (); X exit (conflicts_found); X return conflicts_found; X} X Xstatic void Xtry_help (char const *reason_msgid, char const *operand) X{ X if (reason_msgid) X error (0, 0, _(reason_msgid), operand); X error (EXIT_TROUBLE, 0, X _("Try `%s --help' for more information."), program_name); X abort (); X} X Xstatic void Xcheck_stdout (void) X{ X if (ferror (stdout)) X fatal ("write failed"); X else if (fclose (stdout) != 0) X perror_with_exit (_("standard output")); X} X Xstatic char const * const option_help_msgid[] = { X N_("-e --ed Output unmerged changes from OLDFILE to YOURFILE into MYFILE."), X N_("-E --show-overlap Output unmerged changes, bracketing conflicts."), X N_("-A --show-all Output all changes, bracketing conflicts."), X N_("-x --overlap-only Output overlapping changes."), X N_("-X Output overlapping changes, bracketing them."), X N_("-3 --easy-only Output unmerged nonoverlapping changes."), X "", X N_("-m --merge Output merged file instead of ed script (default -A)."), X N_("-L LABEL --label=LABEL Use LABEL instead of file name."), X N_("-i Append `w' and `q' commands to ed scripts."), X N_("-a --text Treat all files as text."), X N_("-T --initial-tab Make tabs line up by prepending a tab."), X N_("--diff-program=PROGRAM Use PROGRAM to compare files."), X "", X N_("-v --version Output version info."), X N_("--help Output this help."), X 0 X}; X Xstatic void Xusage (void) X{ X char const * const *p; X X printf (_("Usage: %s [OPTION]... MYFILE OLDFILE YOURFILE\n"), X program_name); X printf ("%s\n\n", _("Compare three files line by line.")); X for (p = option_help_msgid; *p; p++) X if (**p) X printf (" %s\n", _(*p)); X else X putchar ('\n'); X printf ("\n%s\n\n%s\n", X _("If a FILE is `-', read standard input."), X _("Report bugs to .")); X} X X/* X * Routines that combine the two diffs together into one. The X * algorithm used follows: X * X * File2 is shared in common between the two diffs. X * Diff02 is the diff between 0 and 2. X * Diff12 is the diff between 1 and 2. X * X * 1) Find the range for the first block in File2. X * a) Take the lowest of the two ranges (in File2) in the two X * current blocks (one from each diff) as being the low X * water mark. Assign the upper end of this block as X * being the high water mark and move the current block up X * one. Mark the block just moved over as to be used. X * b) Check the next block in the diff that the high water X * mark is *not* from. X * X * *If* the high water mark is above X * the low end of the range in that block, X * X * mark that block as to be used and move the current X * block up. Set the high water mark to the max of X * the high end of this block and the current. Repeat b. X * X * 2) Find the corresponding ranges in File0 (from the blocks X * in diff02; line per line outside of diffs) and in File1. X * Create a diff3_block, reserving space as indicated by the ranges. X * X * 3) Copy all of the pointers for file2 in. At least for now, X * do memcmp's between corresponding strings in the two diffs. X * X * 4) Copy all of the pointers for file0 and 1 in. Get what you X * need from file2 (when there isn't a diff block, it's X * identical to file2 within the range between diff blocks). X * X * 5) If the diff blocks you used came from only one of the two X * strings of diffs, then that file (i.e. the one other than X * the common file in that diff) is the odd person out. If you used X * diff blocks from both sets, check to see if files 0 and 1 match: X * X * Same number of lines? If so, do a set of memcmp's (if a X * memcmp matches; copy the pointer over; it'll be easier later X * if you have to do any compares). If they match, 0 & 1 are X * the same. If not, all three different. X * X * Then you do it again, until you run out of blocks. X * X */ X X/* X * This routine makes a three way diff (chain of diff3_block's) from two X * two way diffs (chains of diff_block's). It is assumed that each of X * the two diffs passed are onto the same file (i.e. that each of the X * diffs were made "to" the same file). The three way diff pointer X * returned will have numbering FILE0--the other file in diff02, X * FILE1--the other file in diff12, and FILEC--the common file. X */ Xstatic struct diff3_block * Xmake_3way_diff (struct diff_block *thread0, struct diff_block *thread1) X{ X/* X * This routine works on the two diffs passed to it as threads. X * Thread number 0 is diff02, thread number 1 is diff12. The USING X * array is set to the base of the list of blocks to be used to X * construct each block of the three way diff; if no blocks from a X * particular thread are to be used, that element of the using array X * is set to 0. The elements LAST_USING array are set to the last X * elements on each of the using lists. X * X * The HIGH_WATER_MARK is set to the highest line number in the common file X * described in any of the diffs in either of the USING lists. The X * HIGH_WATER_THREAD names the thread. Similarly the BASE_WATER_MARK X * and BASE_WATER_THREAD describe the lowest line number in the common file X * described in any of the diffs in either of the USING lists. The X * HIGH_WATER_DIFF is the diff from which the HIGH_WATER_MARK was X * taken. X * X * The HIGH_WATER_DIFF should always be equal to LAST_USING X * [HIGH_WATER_THREAD]. The OTHER_DIFF is the next diff to check for X * higher water, and should always be equal to X * CURRENT[HIGH_WATER_THREAD ^ 0x1]. The OTHER_THREAD is the thread X * in which the OTHER_DIFF is, and hence should always be equal to X * HIGH_WATER_THREAD ^ 0x1. X * X * The variable LAST_DIFF is kept set to the last diff block produced X * by this routine, for line correspondence purposes between that diff X * and the one currently being worked on. It is initialized to X * ZERO_DIFF before any blocks have been created. X */ X X struct diff_block *using[2]; X struct diff_block *last_using[2]; X struct diff_block *current[2]; X X lin high_water_mark; X X int high_water_thread; X int base_water_thread; X int other_thread; X X struct diff_block *high_water_diff; X struct diff_block *other_diff; X X struct diff3_block *result; X struct diff3_block *tmpblock; X struct diff3_block **result_end; X X struct diff3_block const *last_diff3; X X static struct diff3_block const zero_diff3; X X /* Initialization */ X result = 0; X result_end = &result; X current[0] = thread0; current[1] = thread1; X last_diff3 = &zero_diff3; X X /* Sniff up the threads until we reach the end */ X X while (current[0] || current[1]) X { X using[0] = using[1] = last_using[0] = last_using[1] = 0; X X /* Setup low and high water threads, diffs, and marks. */ X if (!current[0]) X base_water_thread = 1; X else if (!current[1]) X base_water_thread = 0; X else X base_water_thread = X (D_LOWLINE (current[0], FC) > D_LOWLINE (current[1], FC)); X X high_water_thread = base_water_thread; X X high_water_diff = current[high_water_thread]; X X high_water_mark = D_HIGHLINE (high_water_diff, FC); X X /* Make the diff you just got info from into the using class */ X using[high_water_thread] X = last_using[high_water_thread] X = high_water_diff; X current[high_water_thread] = high_water_diff->next; X last_using[high_water_thread]->next = 0; X X /* And mark the other diff */ X other_thread = high_water_thread ^ 0x1; X other_diff = current[other_thread]; X X /* Shuffle up the ladder, checking the other diff to see if it X needs to be incorporated. */ X while (other_diff X && D_LOWLINE (other_diff, FC) <= high_water_mark + 1) X { X X /* Incorporate this diff into the using list. Note that X this doesn't take it off the current list */ X if (using[other_thread]) X last_using[other_thread]->next = other_diff; X else X using[other_thread] = other_diff; X last_using[other_thread] = other_diff; X X /* Take it off the current list. Note that this following X code assumes that other_diff enters it equal to X current[high_water_thread ^ 0x1] */ X current[other_thread] = current[other_thread]->next; X other_diff->next = 0; X X /* Set the high_water stuff X If this comparison is equal, then this is the last pass X through this loop; since diff blocks within a given X thread cannot overlap, the high_water_mark will be X *below* the range_start of either of the next diffs. */ X X if (high_water_mark < D_HIGHLINE (other_diff, FC)) X { X high_water_thread ^= 1; X high_water_diff = other_diff; X high_water_mark = D_HIGHLINE (other_diff, FC); X } X X /* Set the other diff */ X other_thread = high_water_thread ^ 0x1; X other_diff = current[other_thread]; X } X X /* The using lists contain a list of all of the blocks to be X included in this diff3_block. Create it. */ X X tmpblock = using_to_diff3_block (using, last_using, X base_water_thread, high_water_thread, X last_diff3); X X if (!tmpblock) X fatal ("internal error: screwup in format of diff blocks"); X X /* Put it on the list. */ X *result_end = tmpblock; X result_end = &tmpblock->next; X X /* Set up corresponding lines correctly. */ X last_diff3 = tmpblock; X } X return result; X} X X/* X * using_to_diff3_block: X * This routine takes two lists of blocks (from two separate diff X * threads) and puts them together into one diff3 block. X * It then returns a pointer to this diff3 block or 0 for failure. X * X * All arguments besides using are for the convenience of the routine; X * they could be derived from the using array. X * LAST_USING is a pair of pointers to the last blocks in the using X * structure. X * LOW_THREAD and HIGH_THREAD tell which threads contain the lowest X * and highest line numbers for File0. X * last_diff3 contains the last diff produced in the calling routine. X * This is used for lines mappings which would still be identical to X * the state that diff ended in. X * X * A distinction should be made in this routine between the two diffs X * that are part of a normal two diff block, and the three diffs that X * are part of a diff3_block. X */ Xstatic struct diff3_block * Xusing_to_diff3_block (struct diff_block *using[2], X struct diff_block *last_using[2], X int low_thread, int high_thread, X struct diff3_block const *last_diff3) X{ X lin low[2], high[2]; X struct diff3_block *result; X struct diff_block *ptr; X int d; X lin i; X X /* Find the range in the common file. */ X lin lowc = D_LOWLINE (using[low_thread], FC); X lin highc = D_HIGHLINE (last_using[high_thread], FC); X X /* Find the ranges in the other files. X If using[d] is null, that means that the file to which that diff X refers is equivalent to the common file over this range. */ X X for (d = 0; d < 2; d++) X if (using[d]) X { X low[d] = D_LOW_MAPLINE (using[d], FC, FO, lowc); X high[d] = D_HIGH_MAPLINE (last_using[d], FC, FO, highc); X } X else X { X low[d] = D_HIGH_MAPLINE (last_diff3, FILEC, FILE0 + d, lowc); X high[d] = D_HIGH_MAPLINE (last_diff3, FILEC, FILE0 + d, highc); X } X X /* Create a block with the appropriate sizes */ X result = create_diff3_block (low[0], high[0], low[1], high[1], lowc, highc); X X /* Copy information for the common file. X Return with a zero if any of the compares failed. */ X X for (d = 0; d < 2; d++) X for (ptr = using[d]; ptr; ptr = D_NEXT (ptr)) X { X lin result_offset = D_LOWLINE (ptr, FC) - lowc; X X if (!copy_stringlist (D_LINEARRAY (ptr, FC), X D_LENARRAY (ptr, FC), X D_LINEARRAY (result, FILEC) + result_offset, X D_LENARRAY (result, FILEC) + result_offset, X D_NUMLINES (ptr, FC))) X return 0; X } X X /* Copy information for file d. First deal with anything that might be X before the first diff. */ X X for (d = 0; d < 2; d++) X { X struct diff_block *u = using[d]; X lin lo = low[d], hi = high[d]; X X for (i = 0; X i + lo < (u ? D_LOWLINE (u, FO) : hi + 1); X i++) X { X D_RELNUM (result, FILE0 + d, i) = D_RELNUM (result, FILEC, i); X D_RELLEN (result, FILE0 + d, i) = D_RELLEN (result, FILEC, i); X } X X for (ptr = u; ptr; ptr = D_NEXT (ptr)) X { X lin result_offset = D_LOWLINE (ptr, FO) - lo; X lin linec; X X if (!copy_stringlist (D_LINEARRAY (ptr, FO), X D_LENARRAY (ptr, FO), X D_LINEARRAY (result, FILE0 + d) + result_offset, X D_LENARRAY (result, FILE0 + d) + result_offset, X D_NUMLINES (ptr, FO))) X return 0; X X /* Catch the lines between here and the next diff */ X linec = D_HIGHLINE (ptr, FC) + 1 - lowc; X for (i = D_HIGHLINE (ptr, FO) + 1 - lo; X i < (D_NEXT (ptr) ? D_LOWLINE (D_NEXT (ptr), FO) : hi + 1) - lo; X i++) X { X D_RELNUM (result, FILE0 + d, i) = D_RELNUM (result, FILEC, linec); X D_RELLEN (result, FILE0 + d, i) = D_RELLEN (result, FILEC, linec); X linec++; X } X } X } X X /* Set correspond */ X if (!using[0]) X D3_TYPE (result) = DIFF_2ND; X else if (!using[1]) X D3_TYPE (result) = DIFF_1ST; X else X { X lin nl0 = D_NUMLINES (result, FILE0); X lin nl1 = D_NUMLINES (result, FILE1); X X if (nl0 != nl1 X || !compare_line_list (D_LINEARRAY (result, FILE0), X D_LENARRAY (result, FILE0), X D_LINEARRAY (result, FILE1), X D_LENARRAY (result, FILE1), X nl0)) X D3_TYPE (result) = DIFF_ALL; X else X D3_TYPE (result) = DIFF_3RD; X } X X return result; X} X X/* X * This routine copies pointers from a list of strings to a different list X * of strings. If a spot in the second list is already filled, it X * makes sure that it is filled with the same string; if not it X * returns 0, the copy incomplete. X * Upon successful completion of the copy, it returns 1. X */ Xstatic bool Xcopy_stringlist (char * const fromptrs[], size_t const fromlengths[], X char *toptrs[], size_t tolengths[], X lin copynum) X{ X register char * const *f = fromptrs; X register char **t = toptrs; X register size_t const *fl = fromlengths; X register size_t *tl = tolengths; X X while (copynum--) X { X if (*t) X { if (*fl != *tl || memcmp (*f, *t, *fl)) return 0; } X else X { *t = *f ; *tl = *fl; } X X t++; f++; tl++; fl++; X } X return 1; X} X X/* X * Create a diff3_block, with ranges as specified in the arguments. X * Allocate the arrays for the various pointers (and zero them) based X * on the arguments passed. Return the block as a result. X */ Xstatic struct diff3_block * Xcreate_diff3_block (lin low0, lin high0, X lin low1, lin high1, X lin low2, lin high2) X{ X struct diff3_block *result = xmalloc (sizeof *result); X lin numlines; X X D3_TYPE (result) = ERROR; X D_NEXT (result) = 0; X X /* Assign ranges */ X D_LOWLINE (result, FILE0) = low0; X D_HIGHLINE (result, FILE0) = high0; X D_LOWLINE (result, FILE1) = low1; X D_HIGHLINE (result, FILE1) = high1; X D_LOWLINE (result, FILE2) = low2; X D_HIGHLINE (result, FILE2) = high2; X X /* Allocate and zero space */ X numlines = D_NUMLINES (result, FILE0); X if (numlines) X { X D_LINEARRAY (result, FILE0) = xcalloc (numlines, sizeof (char *)); X D_LENARRAY (result, FILE0) = xcalloc (numlines, sizeof (size_t)); X } X else X { X D_LINEARRAY (result, FILE0) = 0; X D_LENARRAY (result, FILE0) = 0; X } X X numlines = D_NUMLINES (result, FILE1); X if (numlines) X { X D_LINEARRAY (result, FILE1) = xcalloc (numlines, sizeof (char *)); X D_LENARRAY (result, FILE1) = xcalloc (numlines, sizeof (size_t)); X } X else X { X D_LINEARRAY (result, FILE1) = 0; X D_LENARRAY (result, FILE1) = 0; X } X X numlines = D_NUMLINES (result, FILE2); X if (numlines) X { X D_LINEARRAY (result, FILE2) = xcalloc (numlines, sizeof (char *)); X D_LENARRAY (result, FILE2) = xcalloc (numlines, sizeof (size_t)); X } X else X { X D_LINEARRAY (result, FILE2) = 0; X D_LENARRAY (result, FILE2) = 0; X } X X /* Return */ X return result; X} X X/* X * Compare two lists of lines of text. X * Return 1 if they are equivalent, 0 if not. X */ Xstatic bool Xcompare_line_list (char * const list1[], size_t const lengths1[], X char * const list2[], size_t const lengths2[], X lin nl) X{ X char X * const *l1 = list1, X * const *l2 = list2; X size_t const X *lgths1 = lengths1, X *lgths2 = lengths2; X X while (nl--) X if (!*l1 || !*l2 || *lgths1 != *lgths2++ X || memcmp (*l1++, *l2++, *lgths1++)) X return 0; X return 1; X} X X/* X * Routines to input and parse two way diffs. X */ X Xstatic struct diff_block * Xprocess_diff (char const *filea, X char const *fileb, X struct diff_block **last_block) X{ X char *diff_contents; X char *diff_limit; X char *scan_diff; X enum diff_type dt; X lin i; X struct diff_block *block_list, **block_list_end, *bptr; X size_t too_many_lines = (PTRDIFF_MAX X / MIN (sizeof *bptr->lines[1], X sizeof *bptr->lengths[1])); X X diff_limit = read_diff (filea, fileb, &diff_contents); X scan_diff = diff_contents; X block_list_end = &block_list; X bptr = 0; /* Pacify `gcc -W'. */ X X while (scan_diff < diff_limit) X { X bptr = xmalloc (sizeof *bptr); X bptr->lines[0] = bptr->lines[1] = 0; X bptr->lengths[0] = bptr->lengths[1] = 0; X X dt = process_diff_control (&scan_diff, bptr); X if (dt == ERROR || *scan_diff != '\n') X { X fprintf (stderr, _("%s: diff failed: "), program_name); X do X { X putc (*scan_diff, stderr); X } X while (*scan_diff++ != '\n'); X exit (EXIT_TROUBLE); X } X scan_diff++; X X /* Force appropriate ranges to be null, if necessary */ X switch (dt) X { X case ADD: X bptr->ranges[0][0]++; X break; X case DELETE: X bptr->ranges[1][0]++; X break; X case CHANGE: X break; X default: X fatal ("internal error: invalid diff type in process_diff"); X break; X } X X /* Allocate space for the pointers for the lines from filea, and X parcel them out among these pointers */ X if (dt != ADD) X { X lin numlines = D_NUMLINES (bptr, 0); X if (too_many_lines <= numlines) X xalloc_die (); X bptr->lines[0] = xmalloc (numlines * sizeof *bptr->lines[0]); X bptr->lengths[0] = xmalloc (numlines * sizeof *bptr->lengths[0]); X for (i = 0; i < numlines; i++) X scan_diff = scan_diff_line (scan_diff, X &(bptr->lines[0][i]), X &(bptr->lengths[0][i]), X diff_limit, X '<'); X } X X /* Get past the separator for changes */ X if (dt == CHANGE) X { X if (strncmp (scan_diff, "---\n", 4)) X fatal ("invalid diff format; invalid change separator"); X scan_diff += 4; X } X X /* Allocate space for the pointers for the lines from fileb, and X parcel them out among these pointers */ X if (dt != DELETE) X { X lin numlines = D_NUMLINES (bptr, 1); X if (too_many_lines <= numlines) X xalloc_die (); X bptr->lines[1] = xmalloc (numlines * sizeof *bptr->lines[1]); X bptr->lengths[1] = xmalloc (numlines * sizeof *bptr->lengths[1]); X for (i = 0; i < numlines; i++) X scan_diff = scan_diff_line (scan_diff, X &(bptr->lines[1][i]), X &(bptr->lengths[1][i]), X diff_limit, X '>'); X } X X /* Place this block on the blocklist. */ X *block_list_end = bptr; X block_list_end = &bptr->next; X } X X *block_list_end = 0; X *last_block = bptr; X return block_list; X} X X/* X * This routine will parse a normal format diff control string. It X * returns the type of the diff (ERROR if the format is bad). All of X * the other important information is filled into to the structure X * pointed to by db, and the string pointer (whose location is passed X * to this routine) is updated to point beyond the end of the string X * parsed. Note that only the ranges in the diff_block will be set by X * this routine. X * X * If some specific pair of numbers has been reduced to a single X * number, then both corresponding numbers in the diff block are set X * to that number. In general these numbers are interpreted as ranges X * inclusive, unless being used by the ADD or DELETE commands. It is X * assumed that these will be special cased in a superior routine. X */ X Xstatic enum diff_type Xprocess_diff_control (char **string, struct diff_block *db) X{ X char *s = *string; X lin holdnum; X enum diff_type type; X X/* These macros are defined here because they can use variables X defined in this function. Don't try this at home kids, we're X trained professionals! X X Also note that SKIPWHITE only recognizes tabs and spaces, and X that READNUM can only read positive, integral numbers */ X X#define SKIPWHITE(s) { while (*s == ' ' || *s == '\t') s++; } X#define READNUM(s, num) \ X { unsigned char c = *s; if (!ISDIGIT (c)) return ERROR; holdnum = 0; \ X do { holdnum = (c - '0' + holdnum * 10); } \ X while (ISDIGIT (c = *++s)); (num) = holdnum; } X X /* Read first set of digits */ X SKIPWHITE (s); X READNUM (s, db->ranges[0][RANGE_START]); X X /* Was that the only digit? */ X SKIPWHITE (s); X if (*s == ',') X { X /* Get the next digit */ X s++; X READNUM (s, db->ranges[0][RANGE_END]); X } X else X db->ranges[0][RANGE_END] = db->ranges[0][RANGE_START]; X X /* Get the letter */ X SKIPWHITE (s); X switch (*s) X { X case 'a': X type = ADD; X break; X case 'c': X type = CHANGE; X break; X case 'd': X type = DELETE; X break; X default: X return ERROR; /* Bad format */ X } X s++; /* Past letter */ X X /* Read second set of digits */ X SKIPWHITE (s); X READNUM (s, db->ranges[1][RANGE_START]); X X /* Was that the only digit? */ X SKIPWHITE (s); X if (*s == ',') X { X /* Get the next digit */ X s++; X READNUM (s, db->ranges[1][RANGE_END]); X SKIPWHITE (s); /* To move to end */ X } X else X db->ranges[1][RANGE_END] = db->ranges[1][RANGE_START]; X X *string = s; X return type; X} X Xstatic char * Xread_diff (char const *filea, X char const *fileb, X char **output_placement) X{ X char *diff_result; X size_t current_chunk_size, total; X int fd, wstatus; X int werrno = 0; X struct stat pipestat; X X#if HAVE_WORKING_FORK || HAVE_WORKING_VFORK X X char const *argv[8]; X char const **ap; X int fds[2]; X pid_t pid; X X ap = argv; X *ap++ = diff_program; X if (text) X *ap++ = "-a"; X *ap++ = "--horizon-lines=100"; X *ap++ = "--"; X *ap++ = filea; X *ap++ = fileb; X *ap = 0; X X if (pipe (fds) != 0) X perror_with_exit ("pipe"); X X pid = vfork (); X if (pid == 0) X { X /* Child */ X close (fds[0]); X if (fds[1] != STDOUT_FILENO) X { X dup2 (fds[1], STDOUT_FILENO); X close (fds[1]); X } X X /* The cast to (char **) is needed for portability to older X hosts with a nonstandard prototype for execvp. */ X execvp (diff_program, (char **) argv); X X _exit (errno == ENOEXEC ? 126 : 127); X } X X if (pid == -1) X perror_with_exit ("fork"); X X close (fds[1]); /* Prevent erroneous lack of EOF */ X fd = fds[0]; X X#else X X FILE *fpipe; X char const args[] = " -a --horizon-lines=100 -- "; X char *command = xmalloc (quote_system_arg (0, diff_program) X + sizeof args - 1 X + quote_system_arg (0, filea) + 1 X + quote_system_arg (0, fileb) + 1); X char *p = command; X p += quote_system_arg (p, diff_program); X strcpy (p, args + (text ? 0 : 3)); X p += strlen (p); X p += quote_system_arg (p, filea); X *p++ = ' '; X p += quote_system_arg (p, fileb); X *p = 0; X errno = 0; X fpipe = popen (command, "r"); X if (!fpipe) X perror_with_exit (command); X free (command); X fd = fileno (fpipe); X X#endif X X if (fstat (fd, &pipestat) != 0) X perror_with_exit ("fstat"); X current_chunk_size = MAX (1, STAT_BLOCKSIZE (pipestat)); X diff_result = xmalloc (current_chunk_size); X total = 0; X X for (;;) X { X size_t bytes_to_read = current_chunk_size - total; X size_t bytes = block_read (fd, diff_result + total, bytes_to_read); X total += bytes; X if (bytes != bytes_to_read) X { X if (bytes == SIZE_MAX) X perror_with_exit (_("read failed")); X break; X } X if (PTRDIFF_MAX / 2 <= current_chunk_size) X xalloc_die (); X current_chunk_size *= 2; X diff_result = xrealloc (diff_result, current_chunk_size); X } X X if (total != 0 && diff_result[total-1] != '\n') X fatal ("invalid diff format; incomplete last line"); X X *output_placement = diff_result; X X#if ! (HAVE_WORKING_FORK || HAVE_WORKING_VFORK) X X wstatus = pclose (fpipe); X if (wstatus == -1) X werrno = errno; X X#else X X if (close (fd) != 0) X perror_with_exit ("close"); X if (waitpid (pid, &wstatus, 0) < 0) X perror_with_exit ("waitpid"); X X#endif X X if (! werrno && WIFEXITED (wstatus)) X switch (WEXITSTATUS (wstatus)) X { X case 126: X error (EXIT_TROUBLE, 0, _("subsidiary program `%s' not executable"), X diff_program); X case 127: X error (EXIT_TROUBLE, 0, _("subsidiary program `%s' not found"), X diff_program); X } X if (werrno || ! (WIFEXITED (wstatus) && WEXITSTATUS (wstatus) < 2)) X error (EXIT_TROUBLE, werrno, _("subsidiary program `%s' failed"), X diff_program); X X return diff_result + total; X} X X X/* X * Scan a regular diff line (consisting of > or <, followed by a X * space, followed by text (including nulls) up to a newline. X * X * This next routine began life as a macro and many parameters in it X * are used as call-by-reference values. X */ Xstatic char * Xscan_diff_line (char *scan_ptr, char **set_start, size_t *set_length, X char *limit, char leadingchar) X{ X char *line_ptr; X X if (!(scan_ptr[0] == leadingchar X && scan_ptr[1] == ' ')) X fatal ("invalid diff format; incorrect leading line chars"); X X *set_start = line_ptr = scan_ptr + 2; X while (*line_ptr++ != '\n') X continue; X X /* Include newline if the original line ended in a newline, X or if an edit script is being generated. X Copy any missing newline message to stderr if an edit script is being X generated, because edit scripts cannot handle missing newlines. X Return the beginning of the next line. */ X *set_length = line_ptr - *set_start; X if (line_ptr < limit && *line_ptr == '\\') X { X if (edscript) X fprintf (stderr, "%s:", program_name); X else X --*set_length; X line_ptr++; X do X { X if (edscript) X putc (*line_ptr, stderr); X } X while (*line_ptr++ != '\n'); X } X X return line_ptr; X} X X/* X * This routine outputs a three way diff passed as a list of X * diff3_block's. X * The argument MAPPING is indexed by external file number (in the X * argument list) and contains the internal file number (from the X * diff passed). This is important because the user expects his X * outputs in terms of the argument list number, and the diff passed X * may have been done slightly differently (if the last argument X * was "-", for example). X * REV_MAPPING is the inverse of MAPPING. X */ Xstatic void Xoutput_diff3 (FILE *outputfile, struct diff3_block *diff, X int const mapping[3], int const rev_mapping[3]) X{ X int i; X int oddoneout; X char *cp; X struct diff3_block *ptr; X lin line; X size_t length; X int dontprint; X static int skew_increment[3] = { 2, 3, 1 }; /* 0==>2==>1==>3 */ X char const *line_prefix = initial_tab ? "\t" : " "; X X for (ptr = diff; ptr; ptr = D_NEXT (ptr)) X { X char x[2]; X X switch (ptr->correspond) X { X case DIFF_ALL: X x[0] = 0; X dontprint = 3; /* Print them all */ X oddoneout = 3; /* Nobody's odder than anyone else */ X break; X case DIFF_1ST: X case DIFF_2ND: X case DIFF_3RD: X oddoneout = rev_mapping[ptr->correspond - DIFF_1ST]; X X x[0] = oddoneout + '1'; X x[1] = 0; X dontprint = oddoneout == 0; X break; X default: X fatal ("internal error: invalid diff type passed to output"); X } X fprintf (outputfile, "====%s\n", x); X X /* Go 0, 2, 1 if the first and third outputs are equivalent. */ X for (i = 0; i < 3; X i = (oddoneout == 1 ? skew_increment[i] : i + 1)) X { X int realfile = mapping[i]; X lin lowt = D_LOWLINE (ptr, realfile); X lin hight = D_HIGHLINE (ptr, realfile); X long llowt = lowt; X long lhight = hight; X X fprintf (outputfile, "%d:", i + 1); X switch (lowt - hight) X { X case 1: X fprintf (outputfile, "%lda\n", llowt - 1); X break; X case 0: X fprintf (outputfile, "%ldc\n", llowt); X break; X default: X fprintf (outputfile, "%ld,%ldc\n", llowt, lhight); X break; X } X X if (i == dontprint) continue; X X if (lowt <= hight) X { X line = 0; X do X { X fprintf (outputfile, line_prefix); X cp = D_RELNUM (ptr, realfile, line); X length = D_RELLEN (ptr, realfile, line); X fwrite (cp, sizeof (char), length, outputfile); X } X while (++line < hight - lowt + 1); X if (cp[length - 1] != '\n') X fprintf (outputfile, "\n\\ %s\n", X _("No newline at end of file")); X } X } X } X} X X X/* X * Output to OUTPUTFILE the lines of B taken from FILENUM. X * Double any initial '.'s; yield nonzero if any initial '.'s were doubled. X */ Xstatic bool Xdotlines (FILE *outputfile, struct diff3_block *b, int filenum) X{ X lin i; X bool leading_dot = 0; X X for (i = 0; X i < D_NUMLINES (b, filenum); X i++) X { X char *line = D_RELNUM (b, filenum, i); X if (line[0] == '.') X { X leading_dot = 1; X fprintf (outputfile, "."); X } X fwrite (line, sizeof (char), X D_RELLEN (b, filenum, i), outputfile); X } X X return leading_dot; X} X X/* X * Output to OUTPUTFILE a '.' line. If LEADING_DOT is nonzero, X * also output a command that removes initial '.'s X * starting with line START and continuing for NUM lines. X * (START is long, not lin, for convenience with printf %ld formats.) X */ Xstatic void Xundotlines (FILE *outputfile, bool leading_dot, long start, lin num) X{ X fprintf (outputfile, ".\n"); X if (leading_dot) X { X if (num == 1) X fprintf (outputfile, "%lds/^\\.//\n", start); X else X fprintf (outputfile, "%ld,%lds/^\\.//\n", start, start + num - 1); X } X} X X/* X * This routine outputs a diff3 set of blocks as an ed script. This X * script applies the changes between file's 2 & 3 to file 1. It X * takes the precise format of the ed script to be output from global X * variables set during options processing. Note that it does X * destructive things to the set of diff3 blocks it is passed; it X * reverses their order (this gets around the problems involved with X * changing line numbers in an ed script). X * X * Note that this routine has the same problem of mapping as the last X * one did; the variable MAPPING maps from file number according to X * the argument list to file number according to the diff passed. All X * files listed below are in terms of the argument list. X * REV_MAPPING is the inverse of MAPPING. X * X * The arguments FILE0, FILE1 and FILE2 are the strings to print X * as the names of the three files. These may be the actual names, X * or may be the arguments specified with -L. X * X * Returns 1 if conflicts were found. X */ X Xstatic bool Xoutput_diff3_edscript (FILE *outputfile, struct diff3_block *diff, X int const mapping[3], int const rev_mapping[3], X char const *file0, char const *file1, char const *file2) X{ X bool leading_dot; X bool conflicts_found = 0, conflict; X struct diff3_block *b; X X for (b = reverse_diff3_blocklist (diff); b; b = b->next) X { X /* Must do mapping correctly. */ X enum diff_type type X = (b->correspond == DIFF_ALL X ? DIFF_ALL X : DIFF_1ST + rev_mapping[b->correspond - DIFF_1ST]); X X long low0, high0; X X /* If we aren't supposed to do this output block, skip it. */ X switch (type) X { X default: continue; X case DIFF_2ND: if (!show_2nd) continue; conflict = 1; break; X case DIFF_3RD: if (overlap_only) continue; conflict = 0; break; X case DIFF_ALL: if (simple_only) continue; conflict = flagging; break; X } X X low0 = D_LOWLINE (b, mapping[FILE0]); X high0 = D_HIGHLINE (b, mapping[FILE0]); X X if (conflict) X { X conflicts_found = 1; X X X /* Mark end of conflict. */ X X fprintf (outputfile, "%lda\n", high0); X leading_dot = 0; X if (type == DIFF_ALL) X { X if (show_2nd) X { X /* Append lines from FILE1. */ X fprintf (outputfile, "||||||| %s\n", file1); X leading_dot = dotlines (outputfile, b, mapping[FILE1]); X } X /* Append lines from FILE2. */ X fprintf (outputfile, "=======\n"); X leading_dot |= dotlines (outputfile, b, mapping[FILE2]); X } X fprintf (outputfile, ">>>>>>> %s\n", file2); X undotlines (outputfile, leading_dot, high0 + 2, X (D_NUMLINES (b, mapping[FILE1]) X + D_NUMLINES (b, mapping[FILE2]) + 1)); X X X /* Mark start of conflict. */ X X fprintf (outputfile, "%lda\n<<<<<<< %s\n", low0 - 1, X type == DIFF_ALL ? file0 : file1); X leading_dot = 0; X if (type == DIFF_2ND) X { X /* Prepend lines from FILE1. */ X leading_dot = dotlines (outputfile, b, mapping[FILE1]); X fprintf (outputfile, "=======\n"); X } X undotlines (outputfile, leading_dot, low0 + 1, X D_NUMLINES (b, mapping[FILE1])); X } X else if (D_NUMLINES (b, mapping[FILE2]) == 0) X /* Write out a delete */ X { X if (low0 == high0) X fprintf (outputfile, "%ldd\n", low0); X else X fprintf (outputfile, "%ld,%ldd\n", low0, high0); X } X else X /* Write out an add or change */ X { X switch (high0 - low0) X { X case -1: X fprintf (outputfile, "%lda\n", high0); X break; X case 0: X fprintf (outputfile, "%ldc\n", high0); X break; X default: X fprintf (outputfile, "%ld,%ldc\n", low0, high0); X break; X } X X undotlines (outputfile, dotlines (outputfile, b, mapping[FILE2]), X low0, D_NUMLINES (b, mapping[FILE2])); X } X } X if (finalwrite) fprintf (outputfile, "w\nq\n"); X return conflicts_found; X} X X/* X * Read from INFILE and output to OUTPUTFILE a set of diff3_ blocks DIFF X * as a merged file. This acts like 'ed file0 <[output_diff3_edscript]', X * except that it works even for binary data or incomplete lines. X * X * As before, MAPPING maps from arg list file number to diff file number, X * REV_MAPPING is its inverse, X * and FILE0, FILE1, and FILE2 are the names of the files. X * X * Returns 1 if conflicts were found. X */ X Xstatic bool Xoutput_diff3_merge (FILE *infile, FILE *outputfile, struct diff3_block *diff, X int const mapping[3], int const rev_mapping[3], X char const *file0, char const *file1, char const *file2) X{ X int c; X lin i; X bool conflicts_found = 0, conflict; X struct diff3_block *b; X lin linesread = 0; X X for (b = diff; b; b = b->next) X { X /* Must do mapping correctly. */ X enum diff_type type X = ((b->correspond == DIFF_ALL) X ? DIFF_ALL X : DIFF_1ST + rev_mapping[b->correspond - DIFF_1ST]); X char const *format_2nd = "<<<<<<< %s\n"; X X /* If we aren't supposed to do this output block, skip it. */ X switch (type) X { X default: continue; X case DIFF_2ND: if (!show_2nd) continue; conflict = 1; break; X case DIFF_3RD: if (overlap_only) continue; conflict = 0; break; X case DIFF_ALL: if (simple_only) continue; conflict = flagging; X format_2nd = "||||||| %s\n"; X break; X } X X /* Copy I lines from file 0. */ X i = D_LOWLINE (b, FILE0) - linesread - 1; X linesread += i; X while (0 <= --i) X do X { X c = getc (infile); X if (c == EOF) X { X if (ferror (infile)) X perror_with_exit (_("read failed")); X else if (feof (infile)) X fatal ("input file shrank"); X } X putc (c, outputfile); X } X while (c != '\n'); X X if (conflict) X { X conflicts_found = 1; X X if (type == DIFF_ALL) X { X /* Put in lines from FILE0 with bracket. */ X fprintf (outputfile, "<<<<<<< %s\n", file0); X for (i = 0; X i < D_NUMLINES (b, mapping[FILE0]); X i++) X fwrite (D_RELNUM (b, mapping[FILE0], i), sizeof (char), X D_RELLEN (b, mapping[FILE0], i), outputfile); X } X X if (show_2nd) X { X /* Put in lines from FILE1 with bracket. */ X fprintf (outputfile, format_2nd, file1); X for (i = 0; X i < D_NUMLINES (b, mapping[FILE1]); X i++) X fwrite (D_RELNUM (b, mapping[FILE1], i), sizeof (char), X D_RELLEN (b, mapping[FILE1], i), outputfile); X } X X fprintf (outputfile, "=======\n"); X } X X /* Put in lines from FILE2. */ X for (i = 0; X i < D_NUMLINES (b, mapping[FILE2]); X i++) X fwrite (D_RELNUM (b, mapping[FILE2], i), sizeof (char), X D_RELLEN (b, mapping[FILE2], i), outputfile); X X if (conflict) X fprintf (outputfile, ">>>>>>> %s\n", file2); X X /* Skip I lines in file 0. */ X i = D_NUMLINES (b, FILE0); X linesread += i; X while (0 <= --i) X while ((c = getc (infile)) != '\n') X if (c == EOF) X { X if (ferror (infile)) X perror_with_exit (_("read failed")); X else if (feof (infile)) X { X if (i || b->next) X fatal ("input file shrank"); X return conflicts_found; X } X } X } X /* Copy rest of common file. */ X while ((c = getc (infile)) != EOF || !(ferror (infile) | feof (infile))) X putc (c, outputfile); X return conflicts_found; X} X X/* X * Reverse the order of the list of diff3 blocks. X */ Xstatic struct diff3_block * Xreverse_diff3_blocklist (struct diff3_block *diff) X{ X register struct diff3_block *tmp, *next, *prev; X X for (tmp = diff, prev = 0; tmp; tmp = next) X { X next = tmp->next; X tmp->next = prev; X prev = tmp; X } X X return prev; X} X Xstatic void Xfatal (char const *msgid) X{ X error (EXIT_TROUBLE, 0, "%s", _(msgid)); X abort (); X} X Xstatic void Xperror_with_exit (char const *string) X{ X error (EXIT_TROUBLE, errno, "%s", string); X abort (); X} END-of-contrib/diff/src/diff3.c echo x - contrib/diff/src/sdiff.c sed 's/^X//' >contrib/diff/src/sdiff.c << 'END-of-contrib/diff/src/sdiff.c' X/* sdiff - side-by-side merge of file differences X X Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 2001, 2002 Free X Software Foundation, Inc. X X This file is part of GNU DIFF. X X GNU DIFF is free software; you can redistribute it and/or modify X it under the terms of the GNU General Public License as published by X the Free Software Foundation; either version 2, or (at your option) X any later version. X X GNU DIFF is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. X See the GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; see the file COPYING. X If not, write to the Free Software Foundation, X 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ X X#include "system.h" X X#include X#include X#include X#include X#include X#include X#include X#include X#include X Xstatic char const authorship_msgid[] = N_("Written by Thomas Lord."); X Xstatic char const copyright_string[] = X "Copyright (C) 2002 Free Software Foundation, Inc."; X Xextern char const version_string[]; X X/* Size of chunks read from files which must be parsed into lines. */ X#define SDIFF_BUFSIZE ((size_t) 65536) X Xchar *program_name; X Xstatic char const *editor_program = DEFAULT_EDITOR_PROGRAM; Xstatic char const **diffargv; X Xstatic char * volatile tmpname; Xstatic FILE *tmp; X X#if HAVE_WORKING_FORK || HAVE_WORKING_VFORK Xstatic pid_t volatile diffpid; X#endif X Xstruct line_filter; X Xstatic RETSIGTYPE catchsig (int); Xstatic bool edit (struct line_filter *, char const *, lin, lin, struct line_filter *, char const *, lin, lin, FILE *); Xstatic bool interact (struct line_filter *, struct line_filter *, char const *, struct line_filter *, char const *, FILE *); Xstatic void checksigs (void); Xstatic void diffarg (char const *); Xstatic void fatal (char const *) __attribute__((noreturn)); Xstatic void perror_fatal (char const *) __attribute__((noreturn)); Xstatic void trapsigs (void); Xstatic void untrapsig (int); X X#define NUM_SIGS (sizeof sigs / sizeof *sigs) Xstatic int const sigs[] = { X#ifdef SIGHUP X SIGHUP, X#endif X#ifdef SIGQUIT X SIGQUIT, X#endif X#ifdef SIGTERM X SIGTERM, X#endif X#ifdef SIGXCPU X SIGXCPU, X#endif X#ifdef SIGXFSZ X SIGXFSZ, X#endif X SIGINT, X SIGPIPE X}; X#define handler_index_of_SIGINT (NUM_SIGS - 2) X#define handler_index_of_SIGPIPE (NUM_SIGS - 1) X X#if HAVE_SIGACTION X /* Prefer `sigaction' if available, since `signal' can lose signals. */ X static struct sigaction initial_action[NUM_SIGS]; X# define initial_handler(i) (initial_action[i].sa_handler) X static void signal_handler (int, RETSIGTYPE (*) (int)); X#else X static RETSIGTYPE (*initial_action[NUM_SIGS]) (); X# define initial_handler(i) (initial_action[i]) X# define signal_handler(sig, handler) signal (sig, handler) X#endif X X#if ! HAVE_SIGPROCMASK X# define sigset_t int X# define sigemptyset(s) (*(s) = 0) X# ifndef sigmask X# define sigmask(sig) (1 << ((sig) - 1)) X# endif X# define sigaddset(s, sig) (*(s) |= sigmask (sig)) X# ifndef SIG_BLOCK X# define SIG_BLOCK 0 X# endif X# ifndef SIG_SETMASK X# define SIG_SETMASK (! SIG_BLOCK) X# endif X# define sigprocmask(how, n, o) \ X ((how) == SIG_BLOCK ? *(o) = sigblock (*(n)) : sigsetmask (*(n))) X#endif X Xstatic bool diraccess (char const *); Xstatic int temporary_file (void); X X/* Options: */ X X/* Name of output file if -o specified. */ Xstatic char const *output; X X/* Do not print common lines. */ Xstatic bool suppress_common_lines; X X/* Value for the long option that does not have single-letter equivalents. */ Xenum X{ X DIFF_PROGRAM_OPTION = CHAR_MAX + 1, X HELP_OPTION, X STRIP_TRAILING_CR_OPTION X}; X Xstatic struct option const longopts[] = X{ X {"diff-program", 1, 0, DIFF_PROGRAM_OPTION}, X {"expand-tabs", 0, 0, 't'}, X {"help", 0, 0, HELP_OPTION}, X {"ignore-all-space", 0, 0, 'W'}, /* swap W and w for historical reasons */ X {"ignore-blank-lines", 0, 0, 'B'}, X {"ignore-case", 0, 0, 'i'}, X {"ignore-matching-lines", 1, 0, 'I'}, X {"ignore-space-change", 0, 0, 'b'}, X {"ignore-tab-expansion", 0, 0, 'E'}, X {"left-column", 0, 0, 'l'}, X {"minimal", 0, 0, 'd'}, X {"output", 1, 0, 'o'}, X {"speed-large-files", 0, 0, 'H'}, X {"strip-trailing-cr", 0, 0, STRIP_TRAILING_CR_OPTION}, X {"suppress-common-lines", 0, 0, 's'}, X {"text", 0, 0, 'a'}, X {"version", 0, 0, 'v'}, X {"width", 1, 0, 'w'}, X {0, 0, 0, 0} X}; X Xstatic void try_help (char const *, char const *) __attribute__((noreturn)); Xstatic void Xtry_help (char const *reason_msgid, char const *operand) X{ X if (reason_msgid) X error (0, 0, _(reason_msgid), operand); X error (EXIT_TROUBLE, 0, _("Try `%s --help' for more information."), X program_name); X abort (); X} X Xstatic void Xcheck_stdout (void) X{ X if (ferror (stdout)) X fatal ("write failed"); X else if (fclose (stdout) != 0) X perror_fatal (_("standard output")); X} X Xstatic char const * const option_help_msgid[] = { X N_("-o FILE --output=FILE Operate interactively, sending output to FILE."), X "", X N_("-i --ignore-case Consider upper- and lower-case to be the same."), X N_("-E --ignore-tab-expansion Ignore changes due to tab expansion."), X N_("-b --ignore-space-change Ignore changes in the amount of white space."), X N_("-W --ignore-all-space Ignore all white space."), X N_("-B --ignore-blank-lines Ignore changes whose lines are all blank."), X N_("-I RE --ignore-matching-lines=RE Ignore changes whose lines all match RE."), X N_("--strip-trailing-cr Strip trailing carriage return on input."), X N_("-a --text Treat all files as text."), X "", X N_("-w NUM --width=NUM Output at most NUM (default 130) columns per line."), X N_("-l --left-column Output only the left column of common lines."), X N_("-s --suppress-common-lines Do not output common lines."), X "", X N_("-t --expand-tabs Expand tabs to spaces in output."), X "", X N_("-d --minimal Try hard to find a smaller set of changes."), X N_("-H --speed-large-files Assume large files and many scattered small changes."), X N_("--diff-program=PROGRAM Use PROGRAM to compare files."), X "", X N_("-v --version Output version info."), X N_("--help Output this help."), X 0 X}; X Xstatic void Xusage (void) X{ X char const * const *p; X X printf (_("Usage: %s [OPTION]... FILE1 FILE2\n"), program_name); X printf ("%s\n\n", _("Side-by-side merge of file differences.")); X for (p = option_help_msgid; *p; p++) X if (**p) X printf (" %s\n", _(*p)); X else X putchar ('\n'); X printf ("\n%s\n\n%s\n", X _("If a FILE is `-', read standard input."), X _("Report bugs to .")); X} X Xstatic void Xcleanup (void) X{ X#if HAVE_WORKING_FORK || HAVE_WORKING_VFORK X if (0 < diffpid) X kill (diffpid, SIGPIPE); X#endif X if (tmpname) X unlink (tmpname); X} X Xstatic void exiterr (void) __attribute__((noreturn)); Xstatic void Xexiterr (void) X{ X cleanup (); X untrapsig (0); X checksigs (); X exit (EXIT_TROUBLE); X} X Xstatic void Xfatal (char const *msgid) X{ X error (0, 0, "%s", _(msgid)); X exiterr (); X} X Xstatic void Xperror_fatal (char const *msg) X{ X int e = errno; X checksigs (); X error (0, e, "%s", msg); X exiterr (); X} X Xstatic void Xck_editor_status (int errnum, int status) X{ X if (errnum | status) X { X char const *failure_msgid = N_("subsidiary program `%s' failed"); X if (! errnum && WIFEXITED (status)) X switch (WEXITSTATUS (status)) X { X case 126: X failure_msgid = N_("subsidiary program `%s' not executable"); X break; X case 127: X failure_msgid = N_("subsidiary program `%s' not found"); X break; X } X error (0, errnum, _(failure_msgid), editor_program); X exiterr (); X } X} X Xstatic FILE * Xck_fopen (char const *fname, char const *type) X{ X FILE *r = fopen (fname, type); X if (! r) X perror_fatal (fname); X return r; X} X Xstatic void Xck_fclose (FILE *f) X{ X if (fclose (f)) X perror_fatal ("fclose"); X} X Xstatic size_t Xck_fread (char *buf, size_t size, FILE *f) X{ X size_t r = fread (buf, sizeof (char), size, f); X if (r == 0 && ferror (f)) X perror_fatal (_("read failed")); X return r; X} X Xstatic void Xck_fwrite (char const *buf, size_t size, FILE *f) X{ X if (fwrite (buf, sizeof (char), size, f) != size) X perror_fatal (_("write failed")); X} X Xstatic void Xck_fflush (FILE *f) X{ X if (fflush (f) != 0) X perror_fatal (_("write failed")); X} X Xstatic char const * Xexpand_name (char *name, bool is_dir, char const *other_name) X{ X if (strcmp (name, "-") == 0) X fatal ("cannot interactively merge standard input"); X if (! is_dir) X return name; X else X { X /* Yield NAME/BASE, where BASE is OTHER_NAME's basename. */ X char const *base = base_name (other_name); X size_t namelen = strlen (name), baselen = strlen (base); X bool insert_slash = *base_name (name) && name[namelen - 1] != '/'; X char *r = xmalloc (namelen + insert_slash + baselen + 1); X memcpy (r, name, namelen); X r[namelen] = '/'; X memcpy (r + namelen + insert_slash, base, baselen + 1); X return r; X } X} X X X Xstruct line_filter { X FILE *infile; X char *bufpos; X char *buffer; X char *buflim; X}; X Xstatic void Xlf_init (struct line_filter *lf, FILE *infile) X{ X lf->infile = infile; X lf->bufpos = lf->buffer = lf->buflim = xmalloc (SDIFF_BUFSIZE + 1); X lf->buflim[0] = '\n'; X} X X/* Fill an exhausted line_filter buffer from its INFILE */ Xstatic size_t Xlf_refill (struct line_filter *lf) X{ X size_t s = ck_fread (lf->buffer, SDIFF_BUFSIZE, lf->infile); X lf->bufpos = lf->buffer; X lf->buflim = lf->buffer + s; X lf->buflim[0] = '\n'; X checksigs (); X return s; X} X X/* Advance LINES on LF's infile, copying lines to OUTFILE */ Xstatic void Xlf_copy (struct line_filter *lf, lin lines, FILE *outfile) X{ X char *start = lf->bufpos; X X while (lines) X { X lf->bufpos = (char *) memchr (lf->bufpos, '\n', lf->buflim - lf->bufpos); X if (! lf->bufpos) X { X ck_fwrite (start, lf->buflim - start, outfile); X if (! lf_refill (lf)) X return; X start = lf->bufpos; X } X else X { X --lines; X ++lf->bufpos; X } X } X X ck_fwrite (start, lf->bufpos - start, outfile); X} X X/* Advance LINES on LF's infile without doing output */ Xstatic void Xlf_skip (struct line_filter *lf, lin lines) X{ X while (lines) X { X lf->bufpos = (char *) memchr (lf->bufpos, '\n', lf->buflim - lf->bufpos); X if (! lf->bufpos) X { X if (! lf_refill (lf)) X break; X } X else X { X --lines; X ++lf->bufpos; X } X } X} X X/* Snarf a line into a buffer. Return EOF if EOF, 0 if error, 1 if OK. */ Xstatic int Xlf_snarf (struct line_filter *lf, char *buffer, size_t bufsize) X{ X for (;;) X { X char *start = lf->bufpos; X char *next = (char *) memchr (start, '\n', lf->buflim + 1 - start); X size_t s = next - start; X if (bufsize <= s) X return 0; X memcpy (buffer, start, s); X if (next < lf->buflim) X { X buffer[s] = 0; X lf->bufpos = next + 1; X return 1; X } X if (! lf_refill (lf)) X return s ? 0 : EOF; X buffer += s; X bufsize -= s; X } X} X X X Xint Xmain (int argc, char *argv[]) X{ X int opt; X char const *prog; X X exit_failure = EXIT_TROUBLE; X initialize_main (&argc, &argv); X program_name = argv[0]; X setlocale (LC_ALL, ""); X bindtextdomain (PACKAGE, LOCALEDIR); X textdomain (PACKAGE); X c_stack_action (c_stack_die); X X prog = getenv ("EDITOR"); X if (prog) X editor_program = prog; X X diffarg (DEFAULT_DIFF_PROGRAM); X X /* parse command line args */ X while ((opt = getopt_long (argc, argv, "abBdHiI:lo:stvw:W", longopts, 0)) X != -1) X { X switch (opt) X { X case 'a': X diffarg ("-a"); X break; X X case 'b': X diffarg ("-b"); X break; X X case 'B': X diffarg ("-B"); X break; X X case 'd': X diffarg ("-d"); X break; X X case 'E': X diffarg ("-E"); X break; X X case 'H': X diffarg ("-H"); X break; X X case 'i': X diffarg ("-i"); X break; X X case 'I': X diffarg ("-I"); X diffarg (optarg); X break; X X case 'l': X diffarg ("--left-column"); X break; X X case 'o': X output = optarg; X break; X X case 's': X suppress_common_lines = 1; X break; X X case 't': X diffarg ("-t"); X break; X X case 'v': X printf ("sdiff %s\n%s\n\n%s\n\n%s\n", X version_string, copyright_string, X _(free_software_msgid), _(authorship_msgid)); X check_stdout (); X return EXIT_SUCCESS; X X case 'w': X diffarg ("-W"); X diffarg (optarg); X break; X X case 'W': X diffarg ("-w"); X break; X X case DIFF_PROGRAM_OPTION: X diffargv[0] = optarg; X break; X X case HELP_OPTION: X usage (); X check_stdout (); X return EXIT_SUCCESS; X X case STRIP_TRAILING_CR_OPTION: X diffarg ("--strip-trailing-cr"); X break; X X default: X try_help (0, 0); X } X } X X if (argc - optind != 2) X { X if (argc - optind < 2) X try_help ("missing operand after `%s'", argv[argc - 1]); X else X try_help ("extra operand `%s'", argv[optind + 2]); X } X X if (! output) X { X /* easy case: diff does everything for us */ X if (suppress_common_lines) X diffarg ("--suppress-common-lines"); X diffarg ("-y"); X diffarg ("--"); X diffarg (argv[optind]); X diffarg (argv[optind + 1]); X diffarg (0); X execvp (diffargv[0], (char **) diffargv); X perror_fatal (diffargv[0]); X } X else X { X char const *lname, *rname; X FILE *left, *right, *out, *diffout; X bool interact_ok; X struct line_filter lfilt; X struct line_filter rfilt; X struct line_filter diff_filt; X bool leftdir = diraccess (argv[optind]); X bool rightdir = diraccess (argv[optind + 1]); X X if (leftdir & rightdir) X fatal ("both files to be compared are directories"); X X lname = expand_name (argv[optind], leftdir, argv[optind + 1]); X left = ck_fopen (lname, "r"); X rname = expand_name (argv[optind + 1], rightdir, argv[optind]); X right = ck_fopen (rname, "r"); X out = ck_fopen (output, "w"); X X diffarg ("--sdiff-merge-assist"); X diffarg ("--"); X diffarg (argv[optind]); X diffarg (argv[optind + 1]); X diffarg (0); X X trapsigs (); X X#if ! (HAVE_WORKING_FORK || HAVE_WORKING_VFORK) X { X size_t cmdsize = 1; X char *p, *command; X int i; X X for (i = 0; diffargv[i]; i++) X cmdsize += quote_system_arg (0, diffargv[i]) + 1; X command = p = xmalloc (cmdsize); X for (i = 0; diffargv[i]; i++) X { X p += quote_system_arg (p, diffargv[i]); X *p++ = ' '; X } X p[-1] = 0; X errno = 0; X diffout = popen (command, "r"); X if (! diffout) X perror_fatal (command); X free (command); X } X#else X { X int diff_fds[2]; X# if HAVE_WORKING_VFORK X sigset_t procmask; X sigset_t blocked; X# endif X X if (pipe (diff_fds) != 0) X perror_fatal ("pipe"); X X# if HAVE_WORKING_VFORK X /* Block SIGINT and SIGPIPE. */ X sigemptyset (&blocked); X sigaddset (&blocked, SIGINT); X sigaddset (&blocked, SIGPIPE); X sigprocmask (SIG_BLOCK, &blocked, &procmask); X# endif X diffpid = vfork (); X if (diffpid < 0) X perror_fatal ("fork"); X if (! diffpid) X { X /* Alter the child's SIGINT and SIGPIPE handlers; X this may munge the parent. X The child ignores SIGINT in case the user interrupts the editor. X The child does not ignore SIGPIPE, even if the parent does. */ X if (initial_handler (handler_index_of_SIGINT) != SIG_IGN) X signal_handler (SIGINT, SIG_IGN); X signal_handler (SIGPIPE, SIG_DFL); X# if HAVE_WORKING_VFORK X /* Stop blocking SIGINT and SIGPIPE in the child. */ X sigprocmask (SIG_SETMASK, &procmask, 0); X# endif X close (diff_fds[0]); X if (diff_fds[1] != STDOUT_FILENO) X { X dup2 (diff_fds[1], STDOUT_FILENO); X close (diff_fds[1]); X } X X execvp (diffargv[0], (char **) diffargv); X _exit (errno == ENOEXEC ? 126 : 127); X } X X# if HAVE_WORKING_VFORK X /* Restore the parent's SIGINT and SIGPIPE behavior. */ X if (initial_handler (handler_index_of_SIGINT) != SIG_IGN) X signal_handler (SIGINT, catchsig); X if (initial_handler (handler_index_of_SIGPIPE) != SIG_IGN) X signal_handler (SIGPIPE, catchsig); X else X signal_handler (SIGPIPE, SIG_IGN); X X /* Stop blocking SIGINT and SIGPIPE in the parent. */ X sigprocmask (SIG_SETMASK, &procmask, 0); X# endif X X close (diff_fds[1]); X diffout = fdopen (diff_fds[0], "r"); X if (! diffout) X perror_fatal ("fdopen"); X } X#endif X X lf_init (&diff_filt, diffout); X lf_init (&lfilt, left); X lf_init (&rfilt, right); X X interact_ok = interact (&diff_filt, &lfilt, lname, &rfilt, rname, out); X X ck_fclose (left); X ck_fclose (right); X ck_fclose (out); X X { X int wstatus; X int werrno = 0; X X#if ! (HAVE_WORKING_FORK || HAVE_WORKING_VFORK) X wstatus = pclose (diffout); X if (wstatus == -1) X werrno = errno; X#else X ck_fclose (diffout); X while (waitpid (diffpid, &wstatus, 0) < 0) X if (errno == EINTR) X checksigs (); X else X perror_fatal ("waitpid"); X diffpid = 0; X#endif X X if (tmpname) X { X unlink (tmpname); X tmpname = 0; X } X X if (! interact_ok) X exiterr (); X X ck_editor_status (werrno, wstatus); X untrapsig (0); X checksigs (); X exit (WEXITSTATUS (wstatus)); X } X } X return EXIT_SUCCESS; /* Fool `-Wall'. */ X} X Xstatic void Xdiffarg (char const *a) X{ X static size_t diffargs, diffarglim; X X if (diffargs == diffarglim) X { X if (! diffarglim) X diffarglim = 16; X else if (PTRDIFF_MAX / (2 * sizeof *diffargv) <= diffarglim) X xalloc_die (); X else X diffarglim *= 2; X diffargv = xrealloc (diffargv, diffarglim * sizeof *diffargv); X } X diffargv[diffargs++] = a; X} X X X X X/* Signal handling */ X Xstatic bool volatile ignore_SIGINT; Xstatic int volatile signal_received; Xstatic bool sigs_trapped; X Xstatic RETSIGTYPE Xcatchsig (int s) X{ X#if ! HAVE_SIGACTION X signal (s, SIG_IGN); X#endif X if (! (s == SIGINT && ignore_SIGINT)) X signal_received = s; X} X X#if HAVE_SIGACTION Xstatic struct sigaction catchaction; X Xstatic void Xsignal_handler (int sig, RETSIGTYPE (*handler) (int)) X{ X catchaction.sa_handler = handler; X sigaction (sig, &catchaction, 0); X} X#endif X Xstatic void Xtrapsigs (void) X{ X int i; X X#if HAVE_SIGACTION X catchaction.sa_flags = SA_RESTART; X sigemptyset (&catchaction.sa_mask); X for (i = 0; i < NUM_SIGS; i++) X sigaddset (&catchaction.sa_mask, sigs[i]); X#endif X X for (i = 0; i < NUM_SIGS; i++) X { X#if HAVE_SIGACTION X sigaction (sigs[i], 0, &initial_action[i]); X#else X initial_action[i] = signal (sigs[i], SIG_IGN); X#endif X if (initial_handler (i) != SIG_IGN) X signal_handler (sigs[i], catchsig); X } X X#ifdef SIGCHLD X /* System V fork+wait does not work if SIGCHLD is ignored. */ X signal (SIGCHLD, SIG_DFL); X#endif X X sigs_trapped = 1; X} X X/* Untrap signal S, or all trapped signals if S is zero. */ Xstatic void Xuntrapsig (int s) X{ X int i; X X if (sigs_trapped) X for (i = 0; i < NUM_SIGS; i++) X if ((! s || sigs[i] == s) && initial_handler (i) != SIG_IGN) X#if HAVE_SIGACTION X sigaction (sigs[i], &initial_action[i], 0); X#else X signal (sigs[i], initial_action[i]); X#endif X} X X/* Exit if a signal has been received. */ Xstatic void Xchecksigs (void) X{ X int s = signal_received; X if (s) X { X cleanup (); X X /* Yield an exit status indicating that a signal was received. */ X untrapsig (s); X kill (getpid (), s); X X /* That didn't work, so exit with error status. */ X exit (EXIT_TROUBLE); X } X} X X Xstatic void Xgive_help (void) X{ X fprintf (stderr, "%s", _("\ Xed:\tEdit then use both versions, each decorated with a header.\n\ Xeb:\tEdit then use both versions.\n\ Xel:\tEdit then use the left version.\n\ Xer:\tEdit then use the right version.\n\ Xe:\tEdit a new version.\n\ Xl:\tUse the left version.\n\ Xr:\tUse the right version.\n\ Xs:\tSilently include common lines.\n\ Xv:\tVerbosely include common lines.\n\ Xq:\tQuit.\n\ X")); X} X Xstatic int Xskip_white (void) X{ X int c; X for (;;) X { X c = getchar (); X if (! ISSPACE (c) || c == '\n') X break; X checksigs (); X } X if (ferror (stdin)) X perror_fatal (_("read failed")); X return c; X} X Xstatic void Xflush_line (void) X{ X int c; X while ((c = getchar ()) != '\n' && c != EOF) X continue; X if (ferror (stdin)) X perror_fatal (_("read failed")); X} X X X/* interpret an edit command */ Xstatic bool Xedit (struct line_filter *left, char const *lname, lin lline, lin llen, X struct line_filter *right, char const *rname, lin rline, lin rlen, X FILE *outfile) X{ X for (;;) X { X int cmd0, cmd1; X bool gotcmd = 0; X X cmd1 = 0; /* Pacify `gcc -W'. */ X X while (! gotcmd) X { X if (putchar ('%') != '%') X perror_fatal (_("write failed")); X ck_fflush (stdout); X X cmd0 = skip_white (); X switch (cmd0) X { X case 'l': case 'r': case 's': case 'v': case 'q': X if (skip_white () != '\n') X { X give_help (); X flush_line (); X continue; X } X gotcmd = 1; X break; X X case 'e': X cmd1 = skip_white (); X switch (cmd1) X { X case 'b': case 'd': case 'l': case 'r': X if (skip_white () != '\n') X { X give_help (); X flush_line (); X continue; X } X gotcmd = 1; X break; X case '\n': X gotcmd = 1; X break; X default: X give_help (); X flush_line (); X continue; X } X break; X X case EOF: X if (feof (stdin)) X { X gotcmd = 1; X cmd0 = 'q'; X break; X } X /* Fall through. */ X default: X flush_line (); X /* Fall through. */ X case '\n': X give_help (); X continue; X } X } X X switch (cmd0) X { X case 'l': X lf_copy (left, llen, outfile); X lf_skip (right, rlen); X return 1; X case 'r': X lf_copy (right, rlen, outfile); X lf_skip (left, llen); X return 1; X case 's': X suppress_common_lines = 1; X break; X case 'v': X suppress_common_lines = 0; X break; X case 'q': X return 0; X case 'e': X { X int fd; X X if (tmpname) X tmp = fopen (tmpname, "w"); X else X { X if ((fd = temporary_file ()) < 0) X perror_fatal ("mkstemp"); X tmp = fdopen (fd, "w"); X } X X if (! tmp) X perror_fatal (tmpname); X X switch (cmd1) X { X case 'd': X if (llen) X { X if (llen == 1) X fprintf (tmp, "--- %s %ld\n", lname, (long) lline); X else X fprintf (tmp, "--- %s %ld,%ld\n", lname, X (long) lline, (long) (lline + llen - 1)); X } X /* Fall through. */ X case 'b': case 'l': X lf_copy (left, llen, tmp); X break; X X default: X lf_skip (left, llen); X break; X } X X switch (cmd1) X { X case 'd': X if (rlen) X { X if (rlen == 1) X fprintf (tmp, "+++ %s %ld\n", rname, (long) rline); X else X fprintf (tmp, "+++ %s %ld,%ld\n", rname, X (long) rline, (long) (rline + rlen - 1)); X } X /* Fall through. */ X case 'b': case 'r': X lf_copy (right, rlen, tmp); X break; X X default: X lf_skip (right, rlen); X break; X } X X ck_fclose (tmp); X X { X int wstatus; X int werrno = 0; X ignore_SIGINT = 1; X checksigs (); X X { X#if ! (HAVE_WORKING_FORK || HAVE_WORKING_VFORK) X char *command = X xmalloc (quote_system_arg (0, editor_program) X + 1 + strlen (tmpname) + 1); X sprintf (command + quote_system_arg (command, editor_program), X " %s", tmpname); X wstatus = system (command); X if (wstatus == -1) X werrno = errno; X free (command); X#else X pid_t pid; X X pid = vfork (); X if (pid == 0) X { X char const *argv[3]; X int i = 0; X X argv[i++] = editor_program; X argv[i++] = tmpname; X argv[i] = 0; X X execvp (editor_program, (char **) argv); X _exit (errno == ENOEXEC ? 126 : 127); X } X X if (pid < 0) X perror_fatal ("fork"); X X while (waitpid (pid, &wstatus, 0) < 0) X if (errno == EINTR) X checksigs (); X else X perror_fatal ("waitpid"); X#endif X } X X ignore_SIGINT = 0; X ck_editor_status (werrno, wstatus); X } X X { X char buf[SDIFF_BUFSIZE]; X size_t size; X tmp = ck_fopen (tmpname, "r"); X while ((size = ck_fread (buf, SDIFF_BUFSIZE, tmp)) != 0) X { X checksigs (); X ck_fwrite (buf, size, outfile); X } X ck_fclose (tmp); X } X return 1; X } X default: X give_help (); X break; X } X } X} X X X X/* Alternately reveal bursts of diff output and handle user commands. */ Xstatic bool Xinteract (struct line_filter *diff, X struct line_filter *left, char const *lname, X struct line_filter *right, char const *rname, X FILE *outfile) X{ X lin lline = 1, rline = 1; X X for (;;) X { X char diff_help[256]; X int snarfed = lf_snarf (diff, diff_help, sizeof diff_help); X X if (snarfed <= 0) X return snarfed != 0; X X checksigs (); X X if (diff_help[0] == ' ') X puts (diff_help + 1); X else X { X char *numend; X uintmax_t val; X lin llen, rlen, lenmax; X errno = 0; X llen = val = strtoumax (diff_help + 1, &numend, 10); X if (llen < 0 || llen != val || errno || *numend != ',') X fatal (diff_help); X rlen = val = strtoumax (numend + 1, &numend, 10); X if (rlen < 0 || rlen != val || errno || *numend) X fatal (diff_help); X X lenmax = MAX (llen, rlen); X X switch (diff_help[0]) X { X case 'i': X if (suppress_common_lines) X lf_skip (diff, lenmax); X else X lf_copy (diff, lenmax, stdout); X X lf_copy (left, llen, outfile); X lf_skip (right, rlen); X break; X X case 'c': X lf_copy (diff, lenmax, stdout); X if (! edit (left, lname, lline, llen, X right, rname, rline, rlen, X outfile)) X return 0; X break; X X default: X fatal (diff_help); X } X X lline += llen; X rline += rlen; X } X } X} X X/* Return nonzero if DIR is an existing directory. */ Xstatic bool Xdiraccess (char const *dir) X{ X struct stat buf; X return stat (dir, &buf) == 0 && S_ISDIR (buf.st_mode); X} X X#ifndef P_tmpdir X# define P_tmpdir "/tmp" X#endif X#ifndef TMPDIR_ENV X# define TMPDIR_ENV "TMPDIR" X#endif X X/* Open a temporary file and return its file descriptor. Put into X tmpname the address of a newly allocated buffer that holds the X file's name. Use the prefix "sdiff". */ Xstatic int Xtemporary_file (void) X{ X char const *tmpdir = getenv (TMPDIR_ENV); X char const *dir = tmpdir ? tmpdir : P_tmpdir; X char *buf = xmalloc (strlen (dir) + 1 + 5 + 6 + 1); X int fd; X int e; X sigset_t procmask; X sigset_t blocked; X sprintf (buf, "%s/sdiffXXXXXX", dir); X sigemptyset (&blocked); X sigaddset (&blocked, SIGINT); X sigprocmask (SIG_BLOCK, &blocked, &procmask); X fd = mkstemp (buf); X e = errno; X if (0 <= fd) X tmpname = buf; X sigprocmask (SIG_SETMASK, &procmask, 0); X errno = e; X return fd; X} END-of-contrib/diff/src/sdiff.c echo c - contrib/diff/man mkdir -p contrib/diff/man > /dev/null 2>&1 echo x - contrib/diff/man/cmp.1 sed 's/^X//' >contrib/diff/man/cmp.1 << 'END-of-contrib/diff/man/cmp.1' X.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.27. X.TH CMP "1" "April 2002" "diffutils 2.8.1" "User Commands" X.SH NAME Xcmp \- compare two files byte by byte X.SH SYNOPSIS X.B cmp X[\fIOPTION\fR]... \fIFILE1 \fR[\fIFILE2 \fR[\fISKIP1 \fR[\fISKIP2\fR]]] X.SH DESCRIPTION XCompare two files byte by byte. X.TP X\fB\-b\fR \fB\-\-print\-bytes\fR XPrint differing bytes. X.TP X\fB\-i\fR SKIP \fB\-\-ignore\-initial\fR=\fISKIP\fR XSkip the first SKIP bytes of input. X.HP X\fB\-i\fR SKIP1:SKIP2 \fB\-\-ignore\-initial\fR=\fISKIP1\fR:SKIP2 X.IP XSkip the first SKIP1 bytes of FILE1 and the first SKIP2 bytes of FILE2. X.TP X\fB\-l\fR \fB\-\-verbose\fR XOutput byte numbers and values of all differing bytes. X.TP X\fB\-n\fR LIMIT \fB\-\-bytes\fR=\fILIMIT\fR XCompare at most LIMIT bytes. X.TP X\fB\-s\fR \fB\-\-quiet\fR \fB\-\-silent\fR XOutput nothing; yield exit status only. X.TP X\fB\-v\fR \fB\-\-version\fR XOutput version info. X.TP X\fB\-\-help\fR XOutput this help. X.PP XSKIP1 and SKIP2 are the number of bytes to skip in each file. XSKIP values may be followed by the following multiplicative suffixes: XkB 1000, K 1024, MB 1,000,000, M 1,048,576, XGB 1,000,000,000, G 1,073,741,824, and so on for T, P, E, Z, Y. X.PP XIf a FILE is `-' or missing, read standard input. X.SH AUTHOR XWritten by Torbjorn Granlund and David MacKenzie. X.SH "REPORTING BUGS" XReport bugs to . X.SH COPYRIGHT XCopyright \(co 2002 Free Software Foundation, Inc. X.PP XThis program comes with NO WARRANTY, to the extent permitted by law. XYou may redistribute copies of this program Xunder the terms of the GNU General Public License. XFor more information about these matters, see the file named COPYING. X.SH "SEE ALSO" XThe full documentation for X.B cmp Xis maintained as a Texinfo manual. If the X.B info Xand X.B cmp Xprograms are properly installed at your site, the command X.IP X.B info diff X.PP Xshould give you access to the complete manual. END-of-contrib/diff/man/cmp.1 echo x - contrib/diff/man/diff.1 sed 's/^X//' >contrib/diff/man/diff.1 << 'END-of-contrib/diff/man/diff.1' X.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.27. X.TH DIFF "1" "April 2002" "diffutils 2.8.1" "User Commands" X.SH NAME Xdiff \- compare files line by line X.SH SYNOPSIS X.B diff X[\fIOPTION\fR]... \fIFILES\fR X.SH DESCRIPTION XCompare files line by line. X.TP X\fB\-i\fR \fB\-\-ignore\-case\fR XIgnore case differences in file contents. X.TP X\fB\-\-ignore\-file\-name\-case\fR XIgnore case when comparing file names. X.TP X\fB\-\-no\-ignore\-file\-name\-case\fR XConsider case when comparing file names. X.TP X\fB\-E\fR \fB\-\-ignore\-tab\-expansion\fR XIgnore changes due to tab expansion. X.TP X\fB\-b\fR \fB\-\-ignore\-space\-change\fR XIgnore changes in the amount of white space. X.TP X\fB\-w\fR \fB\-\-ignore\-all\-space\fR XIgnore all white space. X.TP X\fB\-B\fR \fB\-\-ignore\-blank\-lines\fR XIgnore changes whose lines are all blank. X.TP X\fB\-I\fR RE \fB\-\-ignore\-matching\-lines\fR=\fIRE\fR XIgnore changes whose lines all match RE. X.TP X\fB\-\-strip\-trailing\-cr\fR XStrip trailing carriage return on input. X.TP X\fB\-a\fR \fB\-\-text\fR XTreat all files as text. X.TP X\fB\-c\fR \fB\-C\fR NUM \fB\-\-context\fR[=\fINUM\fR] XOutput NUM (default 3) lines of copied context. X.TP X\fB\-u\fR \fB\-U\fR NUM \fB\-\-unified\fR[=\fINUM\fR] XOutput NUM (default 3) lines of unified context. X.TP X\fB\-\-label\fR LABEL XUse LABEL instead of file name. X.TP X\fB\-p\fR \fB\-\-show\-c\-function\fR XShow which C function each change is in. X.TP X\fB\-F\fR RE \fB\-\-show\-function\-line\fR=\fIRE\fR XShow the most recent line matching RE. X.TP X\fB\-q\fR \fB\-\-brief\fR XOutput only whether files differ. X.TP X\fB\-e\fR \fB\-\-ed\fR XOutput an ed script. X.TP X\fB\-\-normal\fR XOutput a normal diff. X.TP X\fB\-n\fR \fB\-\-rcs\fR XOutput an RCS format diff. X.TP X\fB\-y\fR \fB\-\-side\-by\-side\fR XOutput in two columns. X.TP X\fB\-W\fR NUM \fB\-\-width\fR=\fINUM\fR XOutput at most NUM (default 130) print columns. X.TP X\fB\-\-left\-column\fR XOutput only the left column of common lines. X.TP X\fB\-\-suppress\-common\-lines\fR XDo not output common lines. X.TP X\fB\-D\fR NAME \fB\-\-ifdef\fR=\fINAME\fR XOutput merged file to show `#ifdef NAME' diffs. X.TP X\fB\-\-GTYPE\-group\-format\fR=\fIGFMT\fR XSimilar, but format GTYPE input groups with GFMT. X.TP X\fB\-\-line\-format\fR=\fILFMT\fR XSimilar, but format all input lines with LFMT. X.TP X\fB\-\-LTYPE\-line\-format\fR=\fILFMT\fR XSimilar, but format LTYPE input lines with LFMT. X.TP XLTYPE is `old', `new', or `unchanged'. XGTYPE is LTYPE or `changed'. X.IP XGFMT may contain: X.TP X%< Xlines from FILE1 X.TP X%> Xlines from FILE2 X.TP X%= Xlines common to FILE1 and FILE2 X.TP X%[-][WIDTH][.[PREC]]{doxX}LETTER Xprintf-style spec for LETTER X.IP XLETTERs are as follows for new group, lower case for old group: X.TP XF Xfirst line number X.TP XL Xlast line number X.TP XN Xnumber of lines = L-F+1 X.TP XE XF-1 X.TP XM XL+1 X.IP XLFMT may contain: X.TP X%L Xcontents of line X.TP X%l Xcontents of line, excluding any trailing newline X.TP X%[-][WIDTH][.[PREC]]{doxX}n Xprintf-style spec for input line number X.IP XEither GFMT or LFMT may contain: X.TP X%% X% X.TP X%c'C' Xthe single character C X.TP X%c'\eOOO' Xthe character with octal code OOO X.TP X\fB\-l\fR \fB\-\-paginate\fR XPass the output through `pr' to paginate it. X.TP X\fB\-t\fR \fB\-\-expand\-tabs\fR XExpand tabs to spaces in output. X.TP X\fB\-T\fR \fB\-\-initial\-tab\fR XMake tabs line up by prepending a tab. X.TP X\fB\-r\fR \fB\-\-recursive\fR XRecursively compare any subdirectories found. X.TP X\fB\-N\fR \fB\-\-new\-file\fR XTreat absent files as empty. X.TP X\fB\-\-unidirectional\-new\-file\fR XTreat absent first files as empty. X.TP X\fB\-s\fR \fB\-\-report\-identical\-files\fR XReport when two files are the same. X.TP X\fB\-x\fR PAT \fB\-\-exclude\fR=\fIPAT\fR XExclude files that match PAT. X.TP X\fB\-X\fR FILE \fB\-\-exclude\-from\fR=\fIFILE\fR XExclude files that match any pattern in FILE. X.TP X\fB\-S\fR FILE \fB\-\-starting\-file\fR=\fIFILE\fR XStart with FILE when comparing directories. X.TP X\fB\-\-from\-file\fR=\fIFILE1\fR XCompare FILE1 to all operands. FILE1 can be a directory. X.TP X\fB\-\-to\-file\fR=\fIFILE2\fR XCompare all operands to FILE2. FILE2 can be a directory. X.TP X\fB\-\-horizon\-lines\fR=\fINUM\fR XKeep NUM lines of the common prefix and suffix. X.TP X\fB\-d\fR \fB\-\-minimal\fR XTry hard to find a smaller set of changes. X.TP X\fB\-\-speed\-large\-files\fR XAssume large files and many scattered small changes. X.TP X\fB\-v\fR \fB\-\-version\fR XOutput version info. X.TP X\fB\-\-help\fR XOutput this help. X.PP XFILES are `FILE1 FILE2' or `DIR1 DIR2' or `DIR FILE...' or `FILE... DIR'. XIf \fB\-\-from\-file\fR or \fB\-\-to\-file\fR is given, there are no restrictions on FILES. XIf a FILE is `-', read standard input. X.SH AUTHOR XWritten by Paul Eggert, Mike Haertel, David Hayes, XRichard Stallman, and Len Tower. X.SH "REPORTING BUGS" XReport bugs to . X.SH COPYRIGHT XCopyright \(co 2002 Free Software Foundation, Inc. X.PP XThis program comes with NO WARRANTY, to the extent permitted by law. XYou may redistribute copies of this program Xunder the terms of the GNU General Public License. XFor more information about these matters, see the file named COPYING. X.SH "SEE ALSO" XThe full documentation for X.B diff Xis maintained as a Texinfo manual. If the X.B info Xand X.B diff Xprograms are properly installed at your site, the command X.IP X.B info diff X.PP Xshould give you access to the complete manual. END-of-contrib/diff/man/diff.1 echo x - contrib/diff/man/diff3.1 sed 's/^X//' >contrib/diff/man/diff3.1 << 'END-of-contrib/diff/man/diff3.1' X.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.27. X.TH DIFF3 "1" "April 2002" "diffutils 2.8.1" "User Commands" X.SH NAME Xdiff3 \- compare three files line by line X.SH SYNOPSIS X.B diff3 X[\fIOPTION\fR]... \fIMYFILE OLDFILE YOURFILE\fR X.SH DESCRIPTION XCompare three files line by line. X.TP X\fB\-e\fR \fB\-\-ed\fR XOutput unmerged changes from OLDFILE to YOURFILE into MYFILE. X.TP X\fB\-E\fR \fB\-\-show\-overlap\fR XOutput unmerged changes, bracketing conflicts. X.TP X\fB\-A\fR \fB\-\-show\-all\fR XOutput all changes, bracketing conflicts. X.TP X\fB\-x\fR \fB\-\-overlap\-only\fR XOutput overlapping changes. X.TP X\fB\-X\fR XOutput overlapping changes, bracketing them. X.TP X\fB\-3\fR \fB\-\-easy\-only\fR XOutput unmerged nonoverlapping changes. X.TP X\fB\-m\fR \fB\-\-merge\fR XOutput merged file instead of ed script (default \fB\-A\fR). X.TP X\fB\-L\fR LABEL \fB\-\-label\fR=\fILABEL\fR XUse LABEL instead of file name. X.TP X\fB\-i\fR XAppend `w' and `q' commands to ed scripts. X.TP X\fB\-a\fR \fB\-\-text\fR XTreat all files as text. X.TP X\fB\-T\fR \fB\-\-initial\-tab\fR XMake tabs line up by prepending a tab. X.TP X\fB\-\-diff\-program\fR=\fIPROGRAM\fR XUse PROGRAM to compare files. X.TP X\fB\-v\fR \fB\-\-version\fR XOutput version info. X.TP X\fB\-\-help\fR XOutput this help. X.PP XIf a FILE is `-', read standard input. X.SH AUTHOR XWritten by Randy Smith. X.SH "REPORTING BUGS" XReport bugs to . X.SH COPYRIGHT XCopyright \(co 2002 Free Software Foundation, Inc. X.PP XThis program comes with NO WARRANTY, to the extent permitted by law. XYou may redistribute copies of this program Xunder the terms of the GNU General Public License. XFor more information about these matters, see the file named COPYING. X.SH "SEE ALSO" XThe full documentation for X.B diff3 Xis maintained as a Texinfo manual. If the X.B info Xand X.B diff3 Xprograms are properly installed at your site, the command X.IP X.B info diff X.PP Xshould give you access to the complete manual. END-of-contrib/diff/man/diff3.1 echo x - contrib/diff/man/sdiff.1 sed 's/^X//' >contrib/diff/man/sdiff.1 << 'END-of-contrib/diff/man/sdiff.1' X.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.27. X.TH SDIFF "1" "April 2002" "diffutils 2.8.1" "User Commands" X.SH NAME Xsdiff \- side-by-side merge of file differences X.SH SYNOPSIS X.B sdiff X[\fIOPTION\fR]... \fIFILE1 FILE2\fR X.SH DESCRIPTION XSide-by-side merge of file differences. X.TP X\fB\-o\fR FILE \fB\-\-output\fR=\fIFILE\fR XOperate interactively, sending output to FILE. X.TP X\fB\-i\fR \fB\-\-ignore\-case\fR XConsider upper- and lower-case to be the same. X.TP X\fB\-E\fR \fB\-\-ignore\-tab\-expansion\fR XIgnore changes due to tab expansion. X.TP X\fB\-b\fR \fB\-\-ignore\-space\-change\fR XIgnore changes in the amount of white space. X.TP X\fB\-W\fR \fB\-\-ignore\-all\-space\fR XIgnore all white space. X.TP X\fB\-B\fR \fB\-\-ignore\-blank\-lines\fR XIgnore changes whose lines are all blank. X.TP X\fB\-I\fR RE \fB\-\-ignore\-matching\-lines\fR=\fIRE\fR XIgnore changes whose lines all match RE. X.TP X\fB\-\-strip\-trailing\-cr\fR XStrip trailing carriage return on input. X.TP X\fB\-a\fR \fB\-\-text\fR XTreat all files as text. X.TP X\fB\-w\fR NUM \fB\-\-width\fR=\fINUM\fR XOutput at most NUM (default 130) columns per line. X.TP X\fB\-l\fR \fB\-\-left\-column\fR XOutput only the left column of common lines. X.TP X\fB\-s\fR \fB\-\-suppress\-common\-lines\fR XDo not output common lines. X.TP X\fB\-t\fR \fB\-\-expand\-tabs\fR XExpand tabs to spaces in output. X.TP X\fB\-d\fR \fB\-\-minimal\fR XTry hard to find a smaller set of changes. X.TP X\fB\-H\fR \fB\-\-speed\-large\-files\fR XAssume large files and many scattered small changes. X.TP X\fB\-\-diff\-program\fR=\fIPROGRAM\fR XUse PROGRAM to compare files. X.TP X\fB\-v\fR \fB\-\-version\fR XOutput version info. X.TP X\fB\-\-help\fR XOutput this help. X.PP XIf a FILE is `-', read standard input. X.SH AUTHOR XWritten by Thomas Lord. X.SH "REPORTING BUGS" XReport bugs to . X.SH COPYRIGHT XCopyright \(co 2002 Free Software Foundation, Inc. X.PP XThis program comes with NO WARRANTY, to the extent permitted by law. XYou may redistribute copies of this program Xunder the terms of the GNU General Public License. XFor more information about these matters, see the file named COPYING. X.SH "SEE ALSO" XThe full documentation for X.B sdiff Xis maintained as a Texinfo manual. If the X.B info Xand X.B sdiff Xprograms are properly installed at your site, the command X.IP X.B info diff X.PP Xshould give you access to the complete manual. END-of-contrib/diff/man/sdiff.1 echo x - contrib/diff/man/Makefile.am sed 's/^X//' >contrib/diff/man/Makefile.am << 'END-of-contrib/diff/man/Makefile.am' X# Automakefile for GNU diffutils man pages X X# Copyright (C) 2002 Free Software Foundation, Inc. X X## This program is free software; you can redistribute it and/or modify X## it under the terms of the GNU General Public License as published by X## the Free Software Foundation; either version 2, or (at your option) X## any later version. X X## This program is distributed in the hope that it will be useful, X## but WITHOUT ANY WARRANTY; without even the implied warranty of X## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X## GNU General Public License for more details. X X## You should have received a copy of the GNU General Public License X## along with this program; if not, write to the Free Software X## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA X## 02111-1307, USA. X Xdist_man_MANS = cmp.1 diff.1 diff3.1 sdiff.1 XMAINTAINERCLEANFILES = $(dist_man_MANS) X XS = $(top_srcdir)/src Xcmp.1: $S/cmp.c Xdiff.1: $S/diff.c Xdiff3.1: $S/diff3.c Xsdiff.1: $S/sdiff.c X X# Depend on configure.ac to get version number changes. X$(dist_man_MANS): $(top_srcdir)/configure.ac X base=`expr $@ : '\(.*\).1'` && \ X (echo '[NAME]' && sed 's@/\* *@@; s/-/\\-/; q' $S/$$base.c) | \ X $(HELP2MAN) -i - -S '$(PACKAGE) $(VERSION)' ../src/$$base | \ X sed 's/^\.B info .*/.B info diff/' >$@ END-of-contrib/diff/man/Makefile.am exit