From 5586788852983394df5ad656887405e8aef55d8a Mon Sep 17 00:00:00 2001 From: Peter Avalos Date: Sun, 5 Aug 2007 05:20:51 +0000 Subject: [PATCH] Import GNU diffutils-2.8.7. --- contrib/diffutils-2.8/COPYING | 340 ++ contrib/diffutils-2.8/ChangeLog | 3878 +++++++++++++++++ contrib/diffutils-2.8/NEWS | 244 ++ contrib/diffutils-2.8/README | 69 + contrib/diffutils-2.8/doc/diff.info | 5223 +++++++++++++++++++++++ contrib/diffutils-2.8/doc/diff.texi | 4649 ++++++++++++++++++++ contrib/diffutils-2.8/doc/fdl.texi | 452 ++ contrib/diffutils-2.8/doc/stamp-vti | 4 + contrib/diffutils-2.8/doc/version.texi | 4 + contrib/diffutils-2.8/lib/basename.c | 79 + contrib/diffutils-2.8/lib/c-stack.c | 311 ++ contrib/diffutils-2.8/lib/c-stack.h | 19 + contrib/diffutils-2.8/lib/cmpbuf.c | 147 + contrib/diffutils-2.8/lib/cmpbuf.h | 21 + contrib/diffutils-2.8/lib/dirname.h | 43 + contrib/diffutils-2.8/lib/error.c | 310 ++ contrib/diffutils-2.8/lib/error.h | 66 + contrib/diffutils-2.8/lib/exclude.c | 263 ++ contrib/diffutils-2.8/lib/exclude.h | 43 + contrib/diffutils-2.8/lib/exit.h | 32 + contrib/diffutils-2.8/lib/exitfail.c | 27 + contrib/diffutils-2.8/lib/exitfail.h | 20 + contrib/diffutils-2.8/lib/file-type.c | 75 + contrib/diffutils-2.8/lib/file-type.h | 166 + contrib/diffutils-2.8/lib/gettext.h | 68 + contrib/diffutils-2.8/lib/hard-locale.c | 74 + contrib/diffutils-2.8/lib/hard-locale.h | 24 + contrib/diffutils-2.8/lib/inttostr.h | 47 + contrib/diffutils-2.8/lib/posixver.c | 59 + contrib/diffutils-2.8/lib/posixver.h | 1 + contrib/diffutils-2.8/lib/prepargs.h | 3 + contrib/diffutils-2.8/lib/quotesys.c | 125 + contrib/diffutils-2.8/lib/quotesys.h | 9 + contrib/diffutils-2.8/lib/setmode.h | 27 + contrib/diffutils-2.8/lib/strcase.h | 35 + contrib/diffutils-2.8/lib/strftime.c | 1330 ++++++ contrib/diffutils-2.8/lib/strtoimax.c | 80 + contrib/diffutils-2.8/lib/strtoumax.c | 2 + contrib/diffutils-2.8/lib/unlocked-io.h | 132 + contrib/diffutils-2.8/lib/version-etc.c | 176 + contrib/diffutils-2.8/lib/version-etc.h | 37 + contrib/diffutils-2.8/lib/xalloc.h | 87 + contrib/diffutils-2.8/lib/xmalloc.c | 255 ++ contrib/diffutils-2.8/man/diff.1 | 227 + contrib/diffutils-2.8/man/diff3.1 | 78 + contrib/diffutils-2.8/man/sdiff.1 | 90 + contrib/diffutils-2.8/src/analyze.c | 1038 +++++ contrib/diffutils-2.8/src/context.c | 478 +++ contrib/diffutils-2.8/src/diff.c | 1353 ++++++ contrib/diffutils-2.8/src/diff.h | 375 ++ contrib/diffutils-2.8/src/diff3.c | 1744 ++++++++ contrib/diffutils-2.8/src/dir.c | 288 ++ contrib/diffutils-2.8/src/ed.c | 169 + contrib/diffutils-2.8/src/ifdef.c | 430 ++ contrib/diffutils-2.8/src/io.c | 859 ++++ contrib/diffutils-2.8/src/normal.c | 71 + contrib/diffutils-2.8/src/sdiff.c | 1225 ++++++ contrib/diffutils-2.8/src/side.c | 281 ++ contrib/diffutils-2.8/src/system.h | 326 ++ contrib/diffutils-2.8/src/util.c | 775 ++++ 60 files changed, 28863 insertions(+) create mode 100644 contrib/diffutils-2.8/COPYING create mode 100644 contrib/diffutils-2.8/ChangeLog create mode 100644 contrib/diffutils-2.8/NEWS create mode 100644 contrib/diffutils-2.8/README create mode 100644 contrib/diffutils-2.8/doc/diff.info create mode 100644 contrib/diffutils-2.8/doc/diff.texi create mode 100644 contrib/diffutils-2.8/doc/fdl.texi create mode 100644 contrib/diffutils-2.8/doc/stamp-vti create mode 100644 contrib/diffutils-2.8/doc/version.texi create mode 100644 contrib/diffutils-2.8/lib/basename.c create mode 100644 contrib/diffutils-2.8/lib/c-stack.c create mode 100644 contrib/diffutils-2.8/lib/c-stack.h create mode 100644 contrib/diffutils-2.8/lib/cmpbuf.c create mode 100644 contrib/diffutils-2.8/lib/cmpbuf.h create mode 100644 contrib/diffutils-2.8/lib/dirname.h create mode 100644 contrib/diffutils-2.8/lib/error.c create mode 100644 contrib/diffutils-2.8/lib/error.h create mode 100644 contrib/diffutils-2.8/lib/exclude.c create mode 100644 contrib/diffutils-2.8/lib/exclude.h create mode 100644 contrib/diffutils-2.8/lib/exit.h create mode 100644 contrib/diffutils-2.8/lib/exitfail.c create mode 100644 contrib/diffutils-2.8/lib/exitfail.h create mode 100644 contrib/diffutils-2.8/lib/file-type.c create mode 100644 contrib/diffutils-2.8/lib/file-type.h create mode 100644 contrib/diffutils-2.8/lib/gettext.h create mode 100644 contrib/diffutils-2.8/lib/hard-locale.c create mode 100644 contrib/diffutils-2.8/lib/hard-locale.h create mode 100644 contrib/diffutils-2.8/lib/inttostr.h create mode 100644 contrib/diffutils-2.8/lib/posixver.c create mode 100644 contrib/diffutils-2.8/lib/posixver.h create mode 100644 contrib/diffutils-2.8/lib/prepargs.h create mode 100644 contrib/diffutils-2.8/lib/quotesys.c create mode 100644 contrib/diffutils-2.8/lib/quotesys.h create mode 100644 contrib/diffutils-2.8/lib/setmode.h create mode 100644 contrib/diffutils-2.8/lib/strcase.h create mode 100644 contrib/diffutils-2.8/lib/strftime.c create mode 100644 contrib/diffutils-2.8/lib/strtoimax.c create mode 100644 contrib/diffutils-2.8/lib/strtoumax.c create mode 100644 contrib/diffutils-2.8/lib/unlocked-io.h create mode 100644 contrib/diffutils-2.8/lib/version-etc.c create mode 100644 contrib/diffutils-2.8/lib/version-etc.h create mode 100644 contrib/diffutils-2.8/lib/xalloc.h create mode 100644 contrib/diffutils-2.8/lib/xmalloc.c create mode 100644 contrib/diffutils-2.8/man/diff.1 create mode 100644 contrib/diffutils-2.8/man/diff3.1 create mode 100644 contrib/diffutils-2.8/man/sdiff.1 create mode 100644 contrib/diffutils-2.8/src/analyze.c create mode 100644 contrib/diffutils-2.8/src/context.c create mode 100644 contrib/diffutils-2.8/src/diff.c create mode 100644 contrib/diffutils-2.8/src/diff.h create mode 100644 contrib/diffutils-2.8/src/diff3.c create mode 100644 contrib/diffutils-2.8/src/dir.c create mode 100644 contrib/diffutils-2.8/src/ed.c create mode 100644 contrib/diffutils-2.8/src/ifdef.c create mode 100644 contrib/diffutils-2.8/src/io.c create mode 100644 contrib/diffutils-2.8/src/normal.c create mode 100644 contrib/diffutils-2.8/src/sdiff.c create mode 100644 contrib/diffutils-2.8/src/side.c create mode 100644 contrib/diffutils-2.8/src/system.h create mode 100644 contrib/diffutils-2.8/src/util.c diff --git a/contrib/diffutils-2.8/COPYING b/contrib/diffutils-2.8/COPYING new file mode 100644 index 0000000000..d60c31a97a --- /dev/null +++ b/contrib/diffutils-2.8/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/contrib/diffutils-2.8/ChangeLog b/contrib/diffutils-2.8/ChangeLog new file mode 100644 index 0000000000..291919dfe1 --- /dev/null +++ b/contrib/diffutils-2.8/ChangeLog @@ -0,0 +1,3878 @@ +2004-04-13 Paul Eggert + + * NEWS, configure.ac (AC_INIT): Version 2.8.7. + * configure.ac (AM_GNU_GETTEXT_VERSION): Add. + (XGETTEXT): Restore from pre-2004-04-12 version. This fixes + a bug that lost many msgids in doc/diffutils.pot. + * bootstrap: New file. + * exgettext: Don't generate a temporary file, as this runs afoul + of "make distcheck" which operates with read-only directories. + * Makefile.am (EXTRA_DIST): Add bootstrap. + Remove config/config.rpath as it is deduced automatically these days. + +2004-04-12 Paul Eggert + + * NEWS, configure.ac (AC_INIT): Version 2.8.6. + + * NEWS: Add news for 2.8.4, 2.8.6. + + * README: Move copyright notice to end. Defer to "configure + --help" for special "configure" options. Suggest latest libiconv. + Update version numbers of Autoconf etc. to current. + + * configure.ac: Quote various arguments better. + (AC_CONFIG_MACRO_DIR): Add call, specifying "m4". + (AC_CONFIG_HEADER): Replaces AM_CONFIG_HEADER. + (gl_USE_SYSTEM_EXTENSIONS): Replaces AC_GNU_SOURCE. + (AC_ISC_POSIX): Remove; nobody ports to ancient ISC any more. + (AC_PROG_CPP, AC_PROG_INSTALL, AC_C_INLINE, + AC_HEADER_STDBOOL, AC_HEADER_STDC, AM_GNU_GETTEXT, XGETTEXT, + AC_HEADER_STAT, AC_FUNC_VPRINTF, jm_FUNC_GLIBC_UNLOCKED_IO, + jm_FUNC_GNU_STRFTIME, jm_FUNC_MALLOC, jm_FUNC_REALLOC, + jm_PREREQ_C_STACK, jm_PREREQ_ERROR, jm_PREREQ_HARD_LOCALE, + jm_PREREQ_QUOTEARG, jm_PREREQ_REGEX, AC_FUNC_FNMATCH_GNU, jm_AC_DOS): + Remove; not needed here, as our files don't use them directly + or we rely on gnulib modules. + (AC_C_CONST): Remove; we assume C89 now. + (AC_CHECK_HEADERS): Remove libintl.h, limits.h, stdlib.h, string.h, + time.h. + (AC_CHECK_TYPE): Remove ptrdiff_t, ssize_t. + (AC_CHECK_FUNCS): Remove diraccess, strchr, strerror, tmpnam). + (AC_REPLACE_FUNCS): Remove memchr, mkstemp, strcasecmp. + (GNULIB_AUTOCONF_SNIPPET): Add call. This replaces much of + the above. + (AC_CONFIG_FILES): Remove lib/posix/Makefile. + (AC_CONFIG_COMMANDS): Remove. + + * doc/diff.texi (dircategory): Change to "Text creation and + manipulation" from "GNU packages". + (Translations): New node. + (Overview): Improve quality of algorithm citations. + (Binary): -q doesn't exactly cause diff to assume files are binary. + (Normal): Place after Side by Side, since it's less important. + (Detailed Context, Detailed Unified, Detailed ed, + Detailed if-then-else, diff3 Hunks, Detailed diff3 Normal): + Place at end of menu. + (Detailed Unified): Mention that fractional timestamps are + omitted on hosts that don't support them. + Mention what happens when hunks contain just one line. + (Line Group Formats, Reject Names): Fix duplicate-word typos. + (Comparing Directories): Trailing white space and empty lines are + ignored in the -X file. + (diff Options): Add --strip-trailing-cr. + (Projects): gnu -> gvc@gnu.org. + + * lib/Makefile.am (SUBDIRS): Remove. + (EXTRA_DIST, noinst_HEADERS): Remove most entries. + (libdiffutils_a_SOURCES): Now just lib_SOURCES. + (lib_SOURCES): New macro. + (DISTCLEANFILES, MOSTLYCLEANFILES): Set to empty now. + (gnulib.mk): Include: this does most of the work eliminated + by the above changes. + + * lib/inttostr.c (inttostr): Protect i < 0 by compile-time + test intended to suppress compiler warnings. + * lib/inttostr.h: Include limits.h unilaterally. + (CHAR_BIT): Remove. + (PARAMS): Remove; all uses changed. + * lib/setmode.c (__attribute__): New macro. + (set_binary_mode): Define only if HAVE_SETMODE_DOS. + Otherwise define a dummy static char, as C89 requires + that we define something. + * lib/setmode.h (set_binary_mode): Return true, not 1. + + * src/analyze.c, src/context.c, src/diff.c, src/io.c, src/util.c: + Do not include regex.h, as diff.h does this now. + + * src/cmp.c: Sort includes. Include , . + (specify_comparison_type): Don't report an error if the comparison + type has already been specified the same way as this one. + + * src/cmp.c (usage): Mention exit status. + * src/diff.c (option_help_msgid): Likewise. + * src/diff3.c (usage): Likewise. + * src/sdiff.c (usage): Likewise. + + * src/cmp.c (main): Adjust to latest gnulib c_stack_action + calling conventions. + * src/diff.c (main): Likewise. + * src/diff3.c (main): Likewise. + * src/sdiff.c (main): Likewise. + + * src/cmp.c (main): Adjust to latest version_etc calling conventions. + * src/diff.c (main): Likewise. + * src/diff3.c (main): Likewise. + * src/sdiff.c (main): Likewise. + + * src/diff.c: Include . + (binary): Define to true if not declared. + (longopts): Set tabsize flag to 1. + (main): Don't output nanoseconds if platform lacks them. + Don't treat files as binary if !binary. + (set_mtime_to_now): Use 0, not NULL. + (compare_files): Mark files as nonexistent if it looks like + 'patch' created inaccessible regular empty files to denote + nonexistent backups. Don't compare such files. + Clear st_* members of status of nonexistent file. + Remove now-unnecessary tests. + + * src/diff.h: Include regex.h, unlocked-io.h. + (struct file_data.changed): Now char *, not bool *, to save + space on hosts where bool takes more space than char. + All uses changed. + + * src/diff3.c: Include unlocked-io.h. + (strip_trailing_cr): New var. + (STRIP_TRAILING_CR_OPTION): New enum. + (longopts, main, option_help_msgid, read_diff): + Add --strip-trailing-cr support. + (read_diff): Exit with status 126 (not 127) if errno != ENOENT + after failed execvp in child. Report this in parent. + + * src/dir.c: Include . + (failed_locale_specific_sorting): Renamed from failed_strcoll. + All uses changed. + (compare_names): Don't invoke strcasecmp first thing when + ignore_file_name_case; if locale_specific_sorting, we should + just use that. + + * src/ifdef.c (next_line): Remove; replace with... + (next_line0, next_line1): New vars. + (print_ifdef_script, print_ifdef_hunk): + Use them to fix line-number computation bug. + + * src/io.c (find_and_hash_each_line): Don't convert char * + to unsigned char *; just leave pointers as char *. This + lessens the number of potentially-dangerous casts. + * src/util.c (lines_differ): Likewise. + + * src/sdiff.c: Include , . + (check_child_status): Renamed from ck_editor_status, and + accept a new arg MAX_OK_STATUS. All callers changed. + Handle status 126/127 as per POSIX. + (edit): Likewise. + (main): Likewise. Fix getopt typo: -E wasn't supported. + + * src/system.h (S_IRWXU, S_IRWXG, S_IRWXO): Define if not defined. + (S_IXUSR, S_IXGRP, S_IXOTH): Remove. + Include unconditionally, since we can assume C89 now. + Likewise for , . + (getenv, EXIT_SUCCESS, EXIT_FAILURE, SSIZE_MAX, strchr, strrchr, + memcmp, memcpy): Remove decl; no longer needed. + (strcasecoll, strcasecmp): Define if not built in. + (CTYPE_DOMAIN, ISPRINT, ISSPACE, TOLOWER, _tolower, errno): Remove; + we now assume C89 or better. All uses changed. + Include unconditionally now, since gnulib supports it + if the C compiler doesn't. All boolean uses of 0 and 1 now + changed to false and true. + (lin_is_printable_as_long_int): Renamed from lin_is_printable_as_long. + + * src/util.c (begin_output): Fix bug: 0 wasn't cast to char * arg, + which led to undefined behavior on 64-bit hosts. + Use more-standard test for exit status 126 versus 127. + (finish_output): Likewise. + (analyze_hunk): Do not cast bool to int. + +2004-03-15 Paul Eggert + + * src/cmp.c (main): Don't consider two files with the same name to + be the same, if their initial skip values differ. This fixes a + bug reported by Hideki Iwamoto in + . + +2004-03-11 Paul Eggert + + * src/analyze.c (diag): Return void, not lin, since the return + value wasn't needed. All callers changed. + (diag, diff_2_files): + Use 'true' and 'false' instead of '1' and '0', when appropriate. + (compareseq): Use lin const * local variables instead of lin *. + Don't bother checking diag's return value. + (shift_boundaries, build_reverse_script, build_script, diff_2_files): + Use char arrays, not bool arrays, since + sizeof (bool) might be greater than 1. + +2004-02-09 Paul Eggert + + * m4/setmode.m4 (AC_FUNC_SETMODE_DOS): AC_LIBOBJ(setmode) if + we would return true. + +2002-10-14 Paul Eggert + + * src/Makefile.am (diff3.$(OBJEXT), diff.$(OBJEXT), + sdiff.$(OBJEXT)): Rename from (misspelled) diff3.$(OBJECT), + diff.$(OBJECT), sdiff.$(OBJECT). Patch by Paul D. Smith in + . + Bug reported by Chris Bainbridge. + +2002-10-13 Paul Eggert + + * src/Makefile.am (MOSTLYCLEANFILES): Add paths.ht. + (paths.h): Send output to paths.ht first, and then rename to + paths.h at the end. This avoids problems if the disk is full. + It also works around what appears to be a bug with GNU make -j + (3.79.1); see . + +2002-06-27 Paul Eggert + + * NEWS, configure.ac (AC_INIT): Version 2.8.4. + + * config/config.sub: Sync with latest version maintained in other + packages. + + * lib/file-type.h: Protect against double inclusion. Detect + whether has been included. Fix from Jim Meyering. + + * src/analyze.c (briefly_report): Don't say "Binary files differ", + since one of the files may not be a binary file. + Bug reported by Dan Jacobson. + +2002-06-22 Paul Eggert + + * lib/c-stack.c (segv_handler, c_stack_action) [! defined + SA_SIGINFO]: Do not assume SA_SIGINFO behavior. + Bug reported by Jim Meyering on NetBSD 1.5.2. + +2002-06-16 Paul Eggert + + * NEWS, configure.ac (AC_INIT): Version 2.8.3. + + * config/depcomp, config/missing, README: Update to automake 1.6.2. + + * po/LINGUAS: Add en_US. + * po/en_US.po: New file. + * po/POTFILES.in: Remove lib/freesoft.c. + Add lib/file-type.c, lib/version-etc.c, lib/xmalloc.c. + +2002-06-15 Paul Eggert + + * doc/diff.texi (Special Files): Document behavior of symlink + loops. + + * lib/Makefile.am (noinst_HEADERS): Remove freesoft.h. + Add version-etc.h. + (libdiffutils_a_SOURCES): Remove freesoft.c. Add version-etc.c. + * lib/freesoft.c, lib/freesoft.h: Remove. + * lib/version-etc.h (PARAMS): Remove; we now assume C89 at least. + + * lib/version-etc.h (version_etc): Remove package and version args. + (version_etc_copyright): Remove. + * lib/version-etc.c: Likewise. + Do not include unlocked-io.h; no longer needed. + Include gettext.h rather than libinto.h. + (_): Define unconditionally. + (version_etc): Adjust wording to match current GNU coding standards. + Translate "(C)" if possible. + + * lib/version-etc.c, lib/version-etc.h: New files, taken from + fileutils. + + * src/Makefile.am (cmp_SOURCES, diff3_SOURCES, sdiff_SOURCES, + diff_SOURCES): Remove version.c. + (MAINTAINERCLEANFILES, $(srcdir)/version.c): Remove. + + * src/cmp.c: Include version-etc.h, not freesoft.h. + (copyright_notice): Remove. + (main): Use version_etc to print version. + * src/diff.c, src/diff3.c, src/sdiff.c: Likewise. + + * src/cmp.c (version_string): Remove decl. + * src/diff.h, src/diff3.c, src/sdiff.c: Likewise. + +2002-06-11 Paul Eggert + + * lib/fnmatch.c, lib/fnmatch_loop.c (WIDE_CHAR_SUPPORT): + New macro. Use it uniformly instead of + (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H). + It also uses HAVE_BTOWC, to fix a porting bug on Solaris 2.5.1 + reported by Vin Shelton. + * m4/fnmatch.m4 (_AC_LIBOBJ_FNMATCH): Check for btowc. + + * NEWS, configure.ac (AC_INIT): Version 2.8.2. + + * ABOUT-NLS, config/config.guess, config/config.sub, + config/depcomp, config/texinfo.tex, lib/posix/regex.h, + m4/c-bs-a.m4, m4/gettext.m4, m4/gnu-source.m4, m4/lib-link.m4, + m4/malloc.m4: + Update to recent version (maintained in other packages). + * m4/prereq.m4 (jm_PREREQ_EXCLUSIVE): AC_FUNC_FNMATCH_GNU + no longer takes a lib. + + * README: Incorporate contents from INSTALLME. + * INSTALLME: Remove. + * Makefile.am (EXTRA_DIST): Remove INSTALLME. + + * configure.ac (AC_GNU_SOURCE): Move up, so that it affects + later compilations properly. + (DEFAULT_DIFF_PROGRAM, AC_TYPE_SIGNAL): Remove. + (jm_AC_TYPE_INTMAX_T): Add. + (AC_FUNC_FNMATCH_GNU): Use this, instead of AC_FUNC_FNMATCH. + (AC_CONFIG_LINKS): regex.hin renamed from regex_.h. + + * doc/diff.texi: Reword "@option{-f} and @option{--foo}" to + "@option{-f} or @option{--foo}". + Use @acronym instead of @sc where appropriate. + (Specified Lines): Renamed from Specified Folding. + (Comparison, Blank Lines): + Clarify wordings for Blank Lines and Specified Lines nodes. + (Binary): Mention --verbose and --print-bytes. + (Tabs, sdiff Option Summary, diff Options): + New option --tabsize=COLUMNS. + + * lib/Makefile.am (EXTRA_DIST): Add fnmatch_loop.c. + (noinst_HEADERS): fnmatch_.h renamed from fnmatch.hin. + regex_.h renamed from regex.hin. + Add file-type.h. + (libdiffutils_a_SOURCES): Add file-type.c. + (DISTCLEANFILES): Remove fnmatch.hno, regex.hno. + + * lib/c-stack.c (__attribute__): New macro. + (EOVERFLOW): Define if not defined. + (stack_t): Define to struct sigaltstack if not defined or declared. + Include , if available. + Include if DEBUG. + Do not include or . + (c_stack_die): Remove info and context args. All uses changed. + (segv_action): Likewise. + (alternate_signal_stack): Change uintmax_t to long, to ease porting. + (get_stack_location, min_address_from_argv, max_address_from_argv, + null_action): New functions. + (stack_base, stack_size): New vars. + (segv_handler): context arg may not be used. + Use global stack_base, stack_size if + ! HAVE_XSI_STACK_OVERFLOW_HEURISTIC. + Add debug code. + Invoke die (rather than segv_action) to exit. + (c_stack_action): Accept new argv arg, and simpler handler arg. + All uses changed. Move code into new functions above. + Allow null action. + [! (defined SA_ONSTACK && defined _SC_PAGESIZE)]: Assume all segvs + are stack overflows. + (main) [DEBUG]: Describe what output should be like. + + * lib/c-stack.h (siginfo_t, c_stack_die): Remove decl. + + * lib/file-type.c, lib/file-type.h: New files. These contain code + that was in src/diff.c, but is now librarified and spiffed up a + bit. Jim Meyering suggested this. + + * lib/fnmatch.c (alloca, __builtin_expect): Define for non-GCC hosts. + : Include only if HAVE_STRINGS_H. + : Include if we include stdlib.h. + Do not comment out all code if ! HAVE_FNMATCH_GNU. + (getenv): Do not declare if HAVE_DECL_GETENV. + (__strchrnul, __wcschrnul): Remove; not used. + (MEMPCPY): Use mempcpy if not _LIBC; use memcpy if neither _LIBC + nor HAVE_MEMPCPY. + (FOLD) [HANDLE_MULTIBYTE]: Do not pass wide char to ISUPPER. + (STRLEN, STRCAT, MEMPCPY) [HANDLE_MULTIBYTE && !defined _LIBC]: + Use wcslen rather than __wcslen, and likewise for wcscat, wmempcpy. + (MEMPCPY) [HANDLE_MULTIBYTE]: Use wmempcpy if not _LIBC; use wmemcpy + if neither _LIBC nor HAVE_WMEMPCPY. + * lib/fnmatch_.h (__const): Do not define to empty, as this breaks + Sun cc. The code doesn't work with K&R anyway. + * lib/fnmatch_loop.c (struct patternlist.str): Size 1, not 0, + as C89 requires this. + (NEW_PATTERN): Use offsetof, not sizeof, since str now has size 1. + * lib/fnmatch_.h: Import from glibc fnmatch.h. + * lib/fnmatch.c, lib/fnmatch_loop.c: Import from glibc. + + * lib/posixver.c: Include posixver.h. + + * lib/regex_.h: Renamed from lib/regex.hin. + + * m4/c-stack.m4 (jm_PREREQ_C_STACK): Do not AC_REQUIRE + jm_AC_TYPE_UINTMAX_T and do not use uintmax_t. + Check for sys/resource.h, uccontext.h. + Check for decls and existence of getcontext, sigaltstack. + Check for stack_t. + + * m4/codeset.m4, m4/glibc21.m4, m4/lcmessage.m4: Remove. + + * m4/fnmatch.m4: Update to latest Autoconf CVS for AC_FUNC_FNMATCH_GNU. + * m4/gnu-source.m4: Likewise, for AC_GNU_SOURCE (renamed from + AC__GNU_SOURCE). + + * m4/mbstate_t.m4 (AC_TYPE_MBSTATE_T): Renamed from AC_MBSTATE_T. + All uses changed. Upgrade to recent Autoconf CVS. + + * m4/stdbool.m4 (AC_HEADER_STDBOOL): Do not cast pointer to + bool in integer constant expression; C99 does not allow it. + Reported by Bruno Haible. + + * po/LINGUAS: Add hu, pt_BR. + * po/hu.po, po/pt_BR.po: New files. + + * src/Makefile.am (noinst_HEADERS): Remove diff.h. + (DEFS): Remove. + (diff_sources): Add diff.h. + (MOSTLYCLEANFILES): New macro. + (cmp.$(OBJEXT) diff3.$(OBJECT) diff.$(OBJECT) sdiff.$(OBJECT)): Depend + on paths.h. + (paths.h): New rule. + + * src/analyze.c, src/cmp.c, src/diff.c, src/diff3.c, src/io.c, + src/sdiff.c: Include . + + * src/cmp.c: Include paths.h. + (copyright_notice): Renamed from copyright_string. + Now a msgid, so that copyright symbol can be translated. + All uses changed. + * src/diff.c, src/diff3.c, src/sdiff.c: Likewise. + + * src/diff.c: Include posixver.h. + (TABSIZE_OPTION): New constant. + (main): Allow widths up to SIZE_MAX. + (filetype): Move to lib/file-type.c and rename to file_type. + All uses changed. + + * src/diff.c (longopts, main, usage): New option --tabsize=COLUMNS. + * src/io.c (find_and_hash_each_line): Likewise. + + * src/diff.h (TAB_WIDTH): Remove. + (tabsize): New decl. + (sdiff_half_width, sdiff_column2_offset): Now size_t rather than + unsigned int. + + * src/diff3.c (skipwhite, readnum): New functions. + (process_diff_control): Use them. + (SKIPWHITE, READNUM): Remove. + (read_diff): Don't worry about errno == ENOEXEC. + + * src/sdiff.c (catchsig, signal_handler, initial_action): Signal + handlers return void, not RETSIGTYPE, since we no longer support + K&R. + (TABSIZE_OPTION): New constant. + (longopts, usage, main): New option --tabsize=COLUMNS. + (cleanup): New arg signo. All uses changed. + (ck_editor_status, main, edit): Don't worry about ENOEXEC. + + * src/side.c (tab_from_to, print_half_line, print_1sdiff_line): + New option --tabsize=COLUMNS. + + * src/system.h (S_ISBLK, S_ISCHR, S_ISDIR, S_ISFIFO, S_ISREG, + S_ISSOCK): Remove; now in lib/file-type.h. + + * src/util.c (finish_output): Check for ENOEXEC. + (lines_differ, output_1_line): New option --tabsize=COLUMNS. + (analyze_hunk): If -b or -w is also specified, -B now considers + lines to be empty if they contain only white space. + +2002-04-05 Paul Eggert + + * NEWS, configure.ac (AC_INIT): Version 2.8.1. + + * configure.ac (AC_HEADER_STDBOOL): Add. + (AC_CHECK_HEADERS): Remove stdbool.h. + * m4/stdbool.m4: New file. + * m4/prereq.m4 (jm_PREREQ_EXCLUDE): + Use AC_HEADER_STDBOOL rather than AC_CHECK_HEADERS(stdbool.h). + (jm_PREREQ_HASH): Likewise. + + * src/system.h (SSIZE_MAX): Define if limits.h doesn't. + + * src/analyze.c (diff_2_files): Assign PTRDIFF_MAX - 1 to a + size_t variable, just in case there's a problem with ptrdiff_t + versus size_t. + + * lib/cmpbuf.c (errno): Remove decl; K&R C is no longer supported. + Include limits.h. + (SIZE_MAX, SSIZE_MAX): Define if standard headers don't. + (MIN): New macro. + (block_read): Do not attempt to read more than SSIZE_MAX bytes, as the + resulting behavior is implementation-defined. Work around bug in + Tru64 5.1, which can't read more than INT_MAX bytes at a time. + * src/cmp.c (cmp): Use block_read instead of read, to work + around Tru64 5.1 bug. + * src/diff3.c (read_diff): Likewise. + * src/diff3.c: Include cmpbuf.h. + + * THANKS: Add Ulrich Drepper. + + * INSTALLME: Mention GNU texinfo. + + * doc/diff.texi: + Use new @copying directive. + Put @contents first, not last, since Texinfo now suggests this. + Fix bug in -w documentation noted by Karl Berry. + Mention links for speedup. + New node "Speedups" for future speedups. + Just say "Index", not "Concept Index". + +2002-03-26 Paul Eggert + + * src/Makefile.am: + (INCLUDES): Remove this obsolete macro, replacing it with: + (AM_CPPFLAGS): New macro. + +2002-03-26 Albert Chin-A-Young + + * src/Makefile.am (datadir): Remove, as it conflicts with --datadir. + +2002-03-26 Paul Eggert + + * doc/diff.texi (dircategory GNU packages): Fix typo: a "* " was + missing before the menu entry. Bug diagnosed by Adam Heath. + Also, put this dircategory after the Individual utilities dircategory, + to work around a compatibility problem with Debian install-info. + +2002-03-24 Eli Zaretskii + + * src/io.c (sip): Do not mishandle buffered count when reverting + to text mode. + +2002-03-23 Paul Eggert + + * NEWS, configure.ac (AC_INIT): Version 2.8. + * configure.ac (AC_PREREQ): 2.53. + * INSTALLME: Upgrade to gettext 0.11.1 and help2man 1.27. + + * doc/diff.texi: Upgrade the description of `patch' to GNU patch + 2.5.4, and revamp the documentation accordingly. + + * src/diff.c (main): Fix typo that prevented diff -y from working. + Bug reported by Mitsuru Chinen. + +2002-03-15 Paul Eggert + + * lib/c-stack.c (c_stack_die) [!HAVE_SIGINFO_T]: Don't use info. + Bug reported by Eli Zaretskii. + +2002-03-15 Eli Zaretskii + + * ms/config.sed: Tweak editing of install-info-am target. + +2002-03-12 Paul Eggert + + * NEWS, configure.ac (AC_INIT): Version 2.7.10. + + * NEWS: cmp -l -s and cmp -s -l are not allowed. + Deprecate diff -h, -H, -L, -P, --inhibit-hunk-merge. + + * configure.ac (jm_PREREQ_HARD_LOCALE): Add. + (AM_INIT_AUTOMAKE): Do not distribute shar file. + + * doc/diff.texi (Overview): byte != character. + (Detailed Context, Detailed Unified, Alternate Names, diff Options): + Do not document diff -L. + (Comparing Directories, Making Patches, diff Options): + Do not document diff -P. + (diff Performance, sdiff Option Summary, diff Options, sdiff Options): + Do not document diff -H. + (diff Performance, diff Options): Do not document --horizon-lines. + (cmp Options): Prefer -b to -c. + (cmp Options, diff Options, diff3 Options, patch Options, + sdiff Options): Put short options next to the similar long options. + Document --help, and use the same wording for --verbose. + (diff3 Options): Fix typo in description of -E, which used wrongly used + "-e" instead of "-E". + + * lib/hard-locale.c (alloca): Remove. + Include stdlib.h if available, for malloc. + (hard_locale): Use malloc, not alloca, so that we need not worry about + alloca issues. Test for storage allocation failure. + + * m4/prereq.m4 (jm_PREREQ): Add jm_PREREQ_HARD_LOCALE. + (jm_PREREQ_HARD_LOCALE): New macro. + + * src/cmp.c (specify_comparison_type): New function. + (check_stdout): "indices and codes" -> "byte numbers and values" + (main): Detect clashing options. + (cmp): Use "byte" rather than "char" if a translation for "byte" + is available, even when in the POSIX locale. + + * src/diff.c (option_help_msgid): Do not document -L, -P, + --horizon-lines, --inhibit-hunk-merge, -H. + * src/diff.h: -L -> --label + +2002-03-11 Paul Eggert + + * NEWS, configure.ac (AC_INIT): Version 2.7.9. + + * INSTALLME: Update to autoconf 2.53, automake 1.6, help2man + 1.25 with patch. + + * configure.ac (AC_INIT): + Change package name from diff to diffutils. + (AM_INIT_AUTOMAKE): Use new form, with option gnits, + rather than old from that duplicated AC_INIT. + (AM_MISSING_PROG): Add help2man. + (REGEX_MALLOC): Define. + (AC_CONFIG_FILES): Add man/Makefile. + + * Makefile.am (AUTOMAKE_OPTIONS): Remove. + * doc/Makefile.am (AUTOMAKE_OPTIONS): Remove. + * lib/Makefile.am (AUTOMAKE_OPTIONS): Likewise. + * ms/Makefile.am (AUTOMAKE_OPTIONS): Likewise. + * src/Makefile.am (AUTOMAKE_OPTIONS): Likewise. + + * lib/c-stack.c: Include + (ENOTSUP): Define if errno.h doesn't. + (SA_NODEFER, SA_ONSTACK, SA_RESETHAND, SA_SIGINFO, SIGSTKSZ, + _SC_PAGESIZE, ALTERNATE_STACK_SIZE, stack_t, sigaltstack): + Remove; we now assume them all when + HAVE_XSI_STACK_OVERFLOW_HEURISTIC, so we don't need + substitutes. + (): Include only if HAVE_XSI_STACK_OVERFLOW_HEURISTIC. + (alternate_signal_stack): Now of size SIGSTKSZ. + (segv_handler): Simplify, under the assumption that + HAVE_XSI_STACK_OVERFLOW_HEURISTIC is nonzero. + (c_stack_action): Likewise. + (exit_failure) [DEBUG]: Initialize to 0, not 1. + (recurse, main) [DEBUG]: Remove main args. + + * m4/c-stack.m4 (AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC): Change + wording of message. Do not check for stdbool.h or ucontext.h, + or for ucontext_t or sigaction or sigaltstack. + + * po/LINGUAS: Add zh_TW. + + * Makefile.am (SUBDIRS): Add man. + * man/Makefile.am: New file. + * src/cmp.c (usage): Reword for help2man. + * src/diff.c (option_help_msgid): Likewise. + * src/diff3.c (option_help_msgid, usage): Likewise. + * src/sdiff3.c (option_help_msgid, usage): Likewise. + Reword for help2man. + + * THANKS: Add email address for Tower. + + * config/config.guess, config/config.sub, config/depcomp, + config/install-sh, config/mdate-sh, config/missing, + config/mkinstalldirs, config/texinfo.tex: Update + to recent version (maintained in other packages). + +2002-03-04 Bruno Haible + + * m4/gettext.m4 (AM_GNU_GETTEXT): Set LIBINTL and LTLIBINTL to empty if + no preinstalled GNU gettext was found. + +2002-03-02 Eli Zaretskii + + * ms/config.sed: Tweak editing of install-info-am and + uninstall-info-am targets, to include 8+3-butchered names of Info + files. + +2002-02-28 Paul Eggert + + * NEWS, configure.ac (AC_INIT, AM_INIT_AUTOMAKE): Version 2.7.8. + + * doc/diff.texi: Add vr index. + Update copyright to 2002. + (Standards conformance): New chapter. + (Binary): Differing binary files are trouble unless the user asked for + brief output. + (Detailed Context): Prefer ISO time stamp format in discussion. + (Detailed Unified, Pagination): Likewise. + (Less Context): Likewise. Also use short option. + (Alternate Names): Separate option from arg. + (Making Patches): Mention -U 2. + (diff Options): Deprecate -LINES, as POSIX 1003.1-2001 does not + allow it. + + * INSTALLME: Update advice for Solaris installation problems. + We no longer use a test version of gettext. + Autoconf test version updated from 2.52f to 2.52h. + POSIX 1003.1-2001 patch for Automake. + + * configure.ac (AC__GNU_SOURCE): Add this, + replacing AH_VERBATIM of _GNU_SOURCE. + (tempname): Use AC_LIBOBJS, not LIBOBJS=, as now required by autoconf. + (jm_PREREQ_C_STACK): Add. + (AC_CONFIG_FILES): Remove intl/Makefile. + (AM_GNU_GETTEXT): Add external arg, from gettext 0.11. + + * lib/c-stack.c, lib/c-stack.h, lib/exitfail.c, lib/exitfail.h, + lib/posixver.c, lib/posixver.h, m4/c-stack.m4, m4/gnu-source.m4, + po/cs.po, po/ja.po: New files. + + * intl/ChangeLog, intl/Makefile.in, intl/VERSION, + intl/bindtextdom.c, intl/config.charset, intl/dcgettext.c, + intl/dcigettext.c, intl/dcngettext.c, intl/dgettext.c, + intl/dngettext.c, intl/explodename.c, intl/finddomain.c, + intl/gettext.c, intl/gettextP.h, intl/gmo.h, intl/hash-string.h, + intl/intl-compat.c, intl/l10nflist.c, intl/libgnuintl.h, + intl/loadinfo.h, intl/loadmsgcat.c, intl/localcharset.c, + intl/locale.alias, intl/localealias.c, intl/localename.c, + intl/ngettext.c, intl/os2compat.c, intl/os2compat.h, intl/osdep.c, + intl/plural-eval.c, intl/plural-exp.c, intl/plural-exp.h, + intl/plural.c, intl/plural.y, intl/ref-add.sin, intl/ref-del.sin, + intl/textdomain.c, m4/isc-posix.m4, m4/libtool.m4: Remove. + + * ABOUT-NLS: Update to Gettext 0.11. + + * Makefile.am (SUBDIRS): Remove intl. + + * config/config.guess, config/config.rpath, config/config.sub, + config/texinfo.tex, config/depcomp, config/texinfo.tex, + lib/tempname.c: Update to latest version from other packages. + + * lib/xalloc.h (xalloc_exit_failure): Remove; subsumed by exit_failure. + * lib/xmalloc.c: Include exitfail.h. + (xalloc_exit_failure): Remove; subsumed by exit_failure. + All uses changed. + + * lib/Makefile.am (noinst_HEADERS): Add c-stack.h, exitfail.h. + (libdiffutils_a_SOURCES): Add c-stack.c, exitfail.c, quotesys.c. + (INCLUDES): Remove. + + * lib/cmpbuf.h (buffer_lcm): New arg LCM_MAX. + * lib/cmpbuf.c: Include errno.h. + (errno): Declare if !STDC_HEADERS. + Include signal.h. + (SA_RESTART): Define if not already defined. + Include . + (PTRDIFF_MAX): Define if not already defined. + (TYPE_SIGNED, TYPE_MINIMUM, TYPE_MAXIMUM): Likewise. + (block_read): Accommodate ancient AIX hosts that set errno to EINTR + after uncaught SIGCONT. + (buffer_lcm): Return a reasonable size if the multiple is too large. + New arg LCM_MAX. All callers changed. + + * lib/hard-locale.c: Include "hard-locale.h". + (hard_locale): Ignore ENABLE_NLS, since we want to operate on + locales other than LC_MESSAGES. + + * m4/prereq.m4 (jm_PREREQ): Add jm_PREREQ_POSIXVER. + (jm_PREREQ_POSIXVER): New macro. + + * m4/setmode.m4 (AC_FUNC_SETMODE_DOS): + Check for fcntl.h and unistd.h unconditionally. + Suggested by Bruno Haible. + + * po/LINGUAS: Add cs, ja. + * po/POTFILES.in: Add lib/c-stack.c, src/dir.c. + + * src/Makefile.am (datadir): @DATADIRNAME@ -> share. + (INCLUDES): Remove intl. + (LDADD): Change INTLLIBS to LIBINTL. + No longer need to link libdiffutils.a twice. + + * src/analyze.c (diff_2_files): + Avoid arithmetic overflow in buffer size calculation. + + * src/cmp.c: Include c-stack.h, exitfail.h. + (hard_locale_LC_MESSAGES): Depend on ENABLE_NLS. + (try_help, check_stdout, main, cmp): 2 -> EXIT_TROUBLE. + (main): Check for stack overflow. + 0 -> EXIT_SUCCESS. + 1 -> EXIT_FAILURE. + (cmp): Likewise. + Accommodate ancient AIX hosts that set errno to + EINTR after uncaught SIGCONT. + + * src/context.c (pr_context_hunk): + Do not dump core if an enormous context causes an + arithmetic overflow. + (pr_unidiff_hunk): Likewise. + (find_hunk): Likewise. + + * src/diff.h: unsigned -> unsigned int. + * src/diff.c: Include c-stack.h, exitfail.h. + Do not include signal.h. + (specify_style, specify_value): Bring these routines back, as POSIX + requires that the order of options not matter. + (shortopts): New constant. + (group_format_option, line_format_option): New constants. + (main): 0 -> EXIT_SUCCESS, 1 -> EXIT_FAILURE, 2 -> EXIT_TROUBLE. + Ensure that order of options does not matter. + Check for stack overflow. + If contexts overflow, substitute LIN_MAX, as that's good enough. + If multiple contexts are specified, use their maximum. + -c is equivalent to -C 3 now, instead of having an implicit context; + likewise for -u and -U 3. + Use specify_style and specify_value. + (SIGCHLD): Do not define; now done in a header. + Use new style time stamp format for -u / -U. + Reject numeric-string options if operating in POSIX 1003.1-2001 mode. + Avoid overflow problems with tab width. + Simplify from-file and to-file code. + (usage): Do not mention obsolete options. + (filetype): Do not mention whether a file is executable. + Add typed memory objects. + (compare_files): 0 -> EXIT_SUCCESS, 1 -> EXIT_FAILURE, 2 -> + EXIT_TROUBLE. + + * src/diff3.c: Include c-stack.h, exitfail.h. + (ALLOCATE): Remove. All uses changed to xmalloc, or to xmalloc plus + an overflow check. + (myread): Remove. + (main): Check for stack overflow. + 0 -> EXIT_SUCCESS, 1 -> EXIT_FAIULRE, 2 -> EXIT_TROUBLE. + (try_help): Likewise. + (process_diff): Check for integer overflow, to avoid core dumps. + 2 -> EXIT_TROUBLE. + (read_diff): Exit with status 126 if the file is not executable, + for compatibility with POSIX 1003.1-2001. + Accommodate ancient AIX hosts that set errno to EINTR after uncaught + SIGCONT. + Check for integer overflow to avoid core dumps. + (fatal, perror_with_exit): 2 -> EXIT_TROUBLE. + + * src/dir.c (dir_read): + Ignore st_size of directories: POSIX says it's garbage. + Check for integer overflow to avoid core dumps. + (diff_dirs): 0 -> EXIT_SUCCESS, 2 -> EXIT_TROUBLE. + + * src/ifdef.c: Include . + (format_group, print_ifdef_lines): Avoid core dumps with bad formats. + (do_printf_spec): Avoid alloca. + + * src/io.c (sip): + Avoid integer overflow and core dumps if buffer alignments are + preposterously incompatible. + (slurp): Do not dump core if the file is growing as we read it. + If a regular file grows, keep reading until we catch up with its EOF. + (find_and_hash_each_line): Check for integer overflow to avoid cores. + (GUESS_LINES): Remove. + (guess_lines): New function. Avoid integer overflow. + (find_identical_ends): Use it. + Avoid integer overflow and possible core dumps. + + * src/sdiff.c: Include c-stack.h, exitfail.h. Do not include signal.h. + 0 -> EXIT_SUCCESS, 1 -> EXIT_FAILURE, 2 -> EXIT_TROUBLE. + (ck_editor_status): New function. + (main): Check for stack overflow. + Adopt POSIX convention for subsidiary programs not found. + (diffarg): Check for integer overflow to avoid core dumps. + (trapsigs): Remove SA_INTERRUPT special case; now done by header. + (SIGCHLD): Likewise. + (edit): Adopt POSIX convention for subsidiary programs not found. + + * src/side.c: unsigned -> unsigned int. + + * src/system.h: Don't use alloca or include . + unsigned -> unsigned int + (EXIT_SUCCESS, EXIT_FAILURE, EXIT_TROUBLE): Define if not defined. + Include signal.h. + (SA_RESTART): Define if not defined. + (SIGCHLD): Likewise. + + * src/util.c: 2 -> EXIT_TROUBLE. + Adopt POSIX convention for ENOEXEC and exit status 126. + unsigned -> unsigned int + +2002-01-24 Paul Eggert + + * NEWS, configure.ac (AC_INIT, AM_INIT_AUTOMAKE): Version 2.7.7. + + * intl/plural.c: Regenerate with Bison 1.31. + + * ABOUT-NLS, intl/*: Update to Gettext 0.11-pre5++. + * INSTALL: Update to Autoconf 2.52f. + + * INSTALLME: New file. + * Makefile.am (EXTRA_DIST): Add config/config.rpath, INSTALLME. + (DISTCLEANFILES): Remove. + * NEWS: Reformat for imminent 2.8 release. + * README: Mention INSTALLME. + * README-alpha: Move most of contents to INSTALLME. + * THANKS: Add Bruno Haible, Jim Meyering, and Eli Zaretskii. + + * config: New subdirectory, containing the following files from .: + config.guess, config.sub, depcomp, missing, install-sh, mkinstalldirs. + Move the following files here from doc: texinfo.tex, mdate-sh. + * config/config.guess, config/config.sub, config/texinfo.tex: + Update to latest version from FSF. + * config/config.rpath: New file, from Gettext 0.11-pre5++. + + * configure.ac (AC_INIT): Use new 3-arg form. + (AC_CONFIG_SRCDIR): Specify src/diff.c here, not in AC_INIT. + (ALL_LINGUAS): Remove: now in po/LINGUAS as per Gettext 0.11. + (AC_CONFIG_AUX_DIR): New macro invocation. + + * lib/Makefile.am (noinst_HEADERS): Add gettext.h. + * lib/gettext.h: New file, from Gettext 0.11-pre5++. + * lib/prepargs.c: Include . Reported by Bruno Haible. + + * m4/codeset.m4, m4/gettext.m4, glibc21.m4, iconv.m4, isc-posix.m4, + lcmessage.m4, progtest.m4: Upgrade to Gettext 0.11-pre5++. + * m4/lib-ld.m4, m4/lib-link.m4, m4/lib-prefix.m4: New files, from + Gettext 0.11-pre5++. + + * po/LINGUAS: New file. + * po/Makefile.in.in: Upgrade to Gettext 0.11-pre5++. + * po/Makevars, po/Rules-quot, po/boldquot.sed: New files, + from Gettext 0.11-pre5++. + + * src/cmp.c (copyright_string): Update to 2002. + * src/diff.c (copyright_string): Likewise. + * src/diff3.c (copyright_string): Likewise. + * src/sdiff.c (copyright_string): Likewise. + + * src/cmp.c (specify_ignore_initial): Renamed from + parse_ignore_initial, with different signature, to take the + maximum of multiple options rather than the last one. + All uses changed. + + * src/cmp.c (bytes, specify_ignore_initial, cmp): Use UINTMAX_MAX + instead of (uintmax_t) -1, to avoid warnings on some compilers. + * src/io.c (file_block_read): Likewise, for SIZE_MAX. + + * src/cmp.c (usage): Reformat messages to ease translation. + * src/diff3.c (usage): Likewise. + * src/sdiff.c (usage): Likewise. + + * src/cmp.c (main): Two files with the same name are identical + only if the same offset is specified. + (block_compare_and_count): Avoid cast to unsigned char. + + * src/diff3.c (main): Remove unused variable. + + * src/dir.c: Include + (struct dirdata): New member nnames. + (locale_specific_sorting, failed_strcoll): New vars. + (dir_read): Renamed from dir_sort. Don't sort the dir. + Set new nnames member of struct dirdata. All callers changed. + (compare_names): Don't check for errno after strcasecmp. + Use strcoll only if locale_specific_sorting is nonzero. + If strcoll fails, longjmp out rather than returning a value + that might result in an invalid comparison function that might + make qsort dump core. + (diff_dirs): Sort the directory ourselves. Use setjmp to recover + from strcoll failure, falling back on native byte comparison. + Make local variables volatile if they need to preserve their value + after setjmp/longjmp. + + * src/sdiff.c (handler_index_of_SIGINT, handler_index_of_SIGPIPE): + New macros. + (main): Do not confuse signal numbers with their indices. + Bug reported by Bruno Haible. + (edit): Cat lin to long before printing with %ld, since lin might + be narrow than long. + + * src/system.h (UINTMAX_MAX): New macro. + Include gettext.h, not libgettext.h. + (N_): Do not wrap arg in parentheses. Fix from Bruno Haible. + + * src/util.c (finish_output): Ensure that werrno is initialized. + (lines_differ): Have an explicit do-nothing case for + IGNORE_NO_WHITE_SPACE, to pacify gcc -Wall. + +2001-12-29 Eli Zaretskii + + * src/sdiff.c (interact): After extracting rlen from the editor + command, test for a terminating null character, not for a newline. + + * ms/config.bat: Allow longer source directory names without + overflowing the line length limits. Create the cache in the + build directory, not in the source directory + * ms/config.sed: Fix AC_CONFIG_LINKS for when symlinks are + unavailable. + +2001-12-23 Paul Eggert + + * NEWS, configure.ac (AM_INIT_AUTOMAKE): Version 2.7.6. + + * configure.ac (ALL_LINGUAS): Add tr. + + * src/util.c (begin_output): + Have child exit with status 127 rather than reporting + failure on its own. Set errno to 0 before invoking popen. + (finish_output): Report errno on pclose failure. + Distinguish between subsidiary program not found, and failure. + + * src/sdiff.c (not_found, execdiff): Remove. + (DIFF_PROGRAM_OPTION): New constant. + (longopts, option_help_msgid, main): Add --diff-program=PROGRAM. + (check_stdout): New function. + (main): Remove DIFF_PROGRAM. Check stdout after printing version. + Use check_stdout after printing help. Use execvp/perror_fatail rather + than execdiff. Set errno to 0 before invoking popen. + Check for pclose failure properly. + (main, edit): If child exec fails, exit with 127 rather than trying to + print diagnostic. + Distinguish between subsidiary program failing and not being found. + (edit): Handle signals the same way, regardless of whether we're using + system or fork+exec. Check for system returning -1. + + * src/diff3.c (DIFF_PROGRAM_OPTION, HELP_OPTION): New constants. + (longopts, main): Use them. + (longopts, main, option_help_msgid): New option --diff-option=PROGRAM. + (main): Remove DIFF_PROGRAM support. + Check stdout after printing version. + (check_stdout): Report errno info if fclose fails. + (read_diff): Have child exit with status 127 when program is not found, + rather than trying to have the child report failure. Check for + pclose returning -1. + + * src/diff.c (DEFAULT_WIDTH): Remove. + (main): Use 130 instead of DEFAULT_WIDTH, since it's not really + builder-settable. Do not prepend DIFF_OPTIONS. + (check-stdout): If fclose (stdout) fails, print errno info. + (option_help_msgid): Default context is 3, not 2. + (usage): Work even if ptrdiff_t is wider than int. + + * doc/diff.texi (diff Options): Remove DIFF_OPTIONS. + (Invoking diff3, Invoking sdiff): Remove DIFF_PROGRAM. + (diff3 Options, sdiff Options): Add --diff-program. + + * src/cmp.c (valid_suffixes): + Add '0', to support suffixes like "MB" and "MiB". + (check_stdout): Don't assume that the translations of "write failed" + and of "standard output" lack '%'. + (main): Check stdout after printing version. + + * lib/setmode.c: [HAVE_FCNTL_H && HAVE_SETMODE_DOS]: Include . + [!HAVE_SETMODE_DOS]: Do not include . + (set_binary_mode): Return mode (not 1) if fd is a tty. + Do not assume that O_TEXT is zero. + + * doc/diff.texi (cmp Options): + In byte counts, a plain suffix (without any integer) + is assumed to modify the integer 1. Index terms like "kibibyte". + Document plain "k". + + (Reporting Bugs): Mention bug-report archive and test version + location. Ask for "diff --version" in bug reports. + +2001-12-13 Paul Eggert + + * src/diff.c (DEFAULT_WIDTH): Remove; couldn't be changed without + also changing option_help_msgid. All uses replaced with 130. + + * lib/setmode.c: Include fcntl.h and unistd.h only if + HAVE_SETMODE_DOS. + (setmode): Assume a file is binary unless the mode is O_TEXT. + * ms/README: Fix minor typos. + +2001-12-13 Eli Zaretskii + + * ms/README: New file. + + * lib/setmode.c (set_binary_mode) [HAVE_SETMODE_DOS]: Don't assume + O_TEXT has a zero value. If FD is a terminal device, do nothing + and return MODE, thus pretending that it was already in the + requested MODE. + [HAVE_FCNTL_H]: Include fcntl.h (needed for O_BINARY). + + * ms/config.sed: Remove the split prevention of config.status. + Fix Sed commands for converting absolute file names into + top_srcdir-relative ones. + + * ms/config.bat: Fix typos. + +2001-12-12 Neal H Walfield + + * diff.c (option_help_msgid): Correct the default context width + from 2 to 3. + +2001-12-11 Paul Eggert + + * m4/Makefile.am.in: Remove jm-glibc-io.m4 + + * NEWS, configure.ac (AM_INIT_AUTOMAKE): Version 2.7.5. + + * configure.ac (PR_PROGRAM): Use AC_DEFINE_UNQUOTED, so that + $PR_PROGRAM is expanded by sh. + (ptrdiff_t, ssize_t): Use AC_CHECK_TYPE with a default of int, + not AC_CHECK_TYPES. + (jm_AC_DOS, AC_FUNC_SETMODE_DOS): New macros. + (AC_CONFIG_FILES): Add ms/Makefile. + + * doc/diff.texi: Add --no-ignore-file-name-case. + File name case sensitivity now affects file name exclusion. + Fix typos. + + * src/util.c: Include dirname.h. + (dir_file_pathname): Use base_name rather than file_name_lastdirchar. + + * src/system.h (S_IXUSR, S_IXGRP, S_IXOTH): New macros. + Include rather than rolling it ourselves. + (file_name_lastdirchar, HAVE_SETMODE, set_binary_mode): Remove. + + * src/sdiff.c: Include . + (expand_name): Use base_name rather than file_name_lastdirchar, for + portability to DOS. + (main): Initialize xalloc_exit_failure before possibly invoking + any memory allocator. + + * src/io.c: Include setmode.h. + + * src/diff3.c (main): + Initialize xalloc_exit_failure before possibly invoking any memory + allocator. + + * src/diff.c: Include dirname.h, setmode.h. + + (main): Later values and/or styles now silently override earlier. + (specify_value, specify_style): Likewise. All callers changed. + Remove. + (binary, main, option_help_msgid, compare_files): + HAVE_SETMODE -> HAVE_SETMODE_DOS. + (NO_IGNORE_FILE_NAME_CASE_OPTION): New constant. + (longopts, main, option_help_msgid): Support it. + (exclude_options): New function. + (main): Use it. Initialize xalloc_exit_failure before potentially + allocating memory. + + (filetype): Distinguish executable files from others, as POSIX + suggests. + + (compare_files): Use base_name instead of file_name_lastdirchar. + + * src/cmp.c: Include , . + (hard_locale_LC_MESSAGES): New macro. + (sprintc): Remove int width arg; it's now the caller's responsibility + to pad. All callers changed. + (stat_buf): New static var; was formerly a local var in 'main'. + (valid_suffixes): Add 'K', for 'KiB'. + (option_help_msgid): Don't confuse bytes with characters. + (main): Set xalloc_exit_failure before invoking anything that might + allocate memory. Fix bug: -n was incorrectly ignored when optimizing + the case of regular files with different lengths. + (cmp): Use an index column wide enough to store this comparison's + indexes. In locales other than the POSIX locale, say "byte" + rather than "char". + + * ms/config.bat: pc -> ms + + * ms/Makefile.am, m4/setmode.m4, lib/setmode.c, lib/setmode.h: + New file. + + * lib/Makefile.am (noinst_HEADERS): Add dirname.h, setmode.h. + (libdiffutils_a_SOURCES): Add basename.c, setmode.c. + + * Makefile.am (SUBDIRS): Add ms. + +2001-12-10 Paul Eggert + + * m4/fnmatch.m4: Test for FNM_CASEFOLD. + +2001-12-03 Paul Eggert + + * lib/posix/regex.h: Fix copyright notice. + +2001-12-03 Paul Eggert + + * NEWS, configure.ac (AM_INIT_AUTOMAKE): Version 2.7.4. + + * diff.texi (direntry, Overview, Comparison, Binary, Invoking cmp): + Use "byte" rather than "character" when talking about cmp, since + it compares bytes, not character. + (Invoking cmp): New trailing operands FROM-SKIP and TO-SKIP. + -i or --ignore-initial now accepts FROM-SKIP:TO-SKIP. + New option -n or --bytes. + Count operands now may be in octal or hex, and may be followed by a + size multiplier. + + * configure.ac (DEFAULT_DIFF_PROGRAM): + Define to "diff", not "$bindir/diff" (which didn't work anyway). + (AC_CHECK_MEMBERS): Add struct stat.st_blksize, struct stat.st_rdev. + (AC_STRUCT_ST_BLKSIZE, AC_STRUCT_ST_RDEV): Remove; obsolescent. + (AC_FUNC_FORK): Use this, instead of obsolescent AC_FUNC_VFORK. + (AC_CONFIG_FILES, AC_CONFIG_COMMANDS): Add. + (AC_OUTPUT): Remove args; they were obsolescent. + + * util.c (setup_output, begin_output, finish_output): + HAVE_FORK -> HAVE_WORKING_FORK || HAVE_WORKING_VFORK. + * sdiff.c (diffpid, cleanup, main, edit): Likewise. + * diff3.c (read_diff): Likewise. + + * system.h (STAT_BLOCKSIZE): + Use HAVE_STRUCT_STAT_ST_BLKSIZE, not HAVE_ST_BLKSIZE. + (vfork): New macro. + (HAVE_FORK): Remove. + (set_binary_mode): New macro. + + * sdiff.c (main): HAVE_VFORK -> HAVE_WORKING_VFORK. + (edit): Reopen the temporary file after the editor has run, in case + the editor operates by unlinking the old file and linking a new one. + (P_tmpdir): Rename from PVT_tmpdir; this fixes a typo. + All uses changed. + + * io.c (sip, read_files): + Remove tests for HAVE_SETMODE; use set_binary_mode + instead of setmode. + (sip): Fix typo in backward lseek when reverting to text mode. + + * config.site, config.sed, config.bat: New file. + + * Makefile.am (EXTRA_DIST): Add xstrtol.c. + (noinst_HEADERS): Add xstrtol.h. + (libdiffutils_a_SOURCES): Add xstrtoumax.c. + + * cmp.c: : Include. + (ignore_initial): Now an array with 2 elements. All uses changed. + (bytes): New var. + (HELP_OPTION): New constant. + (long_options, main): Use it. + (long_options, option_help_msgid, main, cmp): + Add support for -n or --bytes. + (parse_ignore_initial): New function. + (option_help_msgid, main): Add -i M:N. + (usage, main): Add two optional trailing operands, a la BSD. + (main): setmode -> set_binary_mode. + (cmp): Report byte number of what we've seen, not of the entire file. + This is to be consistent with the line number, which is always relative + with what we've seen. + +2001-12-02 Paul Eggert + + * diff.c (main, compare_files): setmode -> set_binary_mode. + + * xstrtol.c (__xstrtol): Don't accept 'Ki'; require 'KiB'. + + * xstrtol.c (__xstrtol): Add support for IEC 60027-2. + +2001-11-25 Paul Eggert + + * NEWS, configure.ac (AM_INIT_AUTOMAKE): Version 2.7.3. + + * README-alpha: New file. + + * src/Makefile.am (INCLUDES): Add -I../lib, for regex.h. + + * configure.ac: + Don't set LIB_CLOCK_GETTIME to 'none required'; set it to + the empty string instead. + + * lib/Makefile.am (EXTRA_DIST): Add strtoimax.c, strtol.c. + + * Makefile.am (SUBDIRS): Put intl before lib, so that libintl.h exists. + + * lib/Makefile.am (noinst_HEADERS): Add unlocked-io.h. + + * configure.ac (__EXTENSIONS__): New define, for the unlocked macros. + + * README: Add copyright notice. + Remove stuff that doesn't apply any more. + + * doc/diff.texi: offsets -> indices for cmp + + * src/cmp.c (option_help_msgid): offsets -> indices + + * src/diff.c (option_help_msgid): + Don't mention --binary on POSIX hosts. + + * src/sdiff.c (STRIP_TRAILING_CR_OPTION): New constant. + (longopts, option_help_msgid, main): Add -E, --ignore-tab-expansion, + --strip-trailing-cr. + + * doc/diff.texi: Change direcategory from Utilities to GNU Packages. + Add individual utilities. + Switch to Free Documentation License. + @code -> @command + @samp -> @option + GNU -> @sc{gnu} + Expand tabs to spaces, except when in an example that actually + uses tabs. + Prefer @node with just one arg. + Document -E or --ignore-tab-expansion, --strip-trailing-cr, + --ignore-file-name-case. + Regular expressions are now grep style, not Emacs style. + cmp's -c or --print-chars option is now -b or --print-bytes. + Time stamps now depend on LC_TIME. + -p now implies ^[[:alpha:]$_]. + Flags now include ' and 0. + cmp -i is an alias for --ignore-initial + Document --from-file, --to-file. + Document DIFF_OPTIONS. + + * configure.ac (AC_CHECK_FUNCS): Add gettimeofday, clock_gettime. + (LIB_CLOCK_GETTIME): New subst. + + * src/system.h: Assume C89 or better. + (_GNU_SOURCE): Remove; config.h now defines it. + (alloca): Declare like coreutils does it. + (verify, TYPE_SIGNED, TYPE_MINIMUM, TYPE_MAXIMUM, O_RDWR, + S_IRUSR, S_IWUSR): New macros. + (STAT_BLOCKSIZE): Parenthesize definiens. + : Include if HAVE_INTTYPES_H. + (CHAR_MAX, INT_MAX): Remove. + (PTRDIFF_MAX, SIZE_MAX): New macros. + (strtoumax): New decl. + Include stddef.h. + (bzero): Remove. + (bindtextdomain, textdomain, N_): New macros. + (ISPRINT, ISSPACE): Remove ifndef wrappers. + (ISUPPER, ISDIGIT): Remove. + (TOLOWER): New macro. + (MIN): Renamed from min; all callers changed. + (MAX): Likewise, from max. + (lin): New type. + (LIN_MAX): New macro. + (file_name_cmp): Renamed from filename_cmp. All callers changed. + (file_name_lastdirchar): Renamed from file_name_lastdirchar. + All callers changed. + (could_be_mvfs_stat_bug, could_be_nfs_stat_bug, + dev_may_have_duplicate_ino): Remove. + (HAVE_SETMODE, NULL_DEVICE): New macros. + (same_file): Do not check attributes. + (same_file_attributes): New macro. + + * src/util.c: Assume C89 or better. + int -> bool for booleans. + int -> lin for line numbers. + int -> size_t for sizes. + Use angle-brackets when including quotesys.h. + Include error.h, regex.h, xalloc.h. + (message5): sizeof -> offsetof + (begin_output): Invoke pr without -f. + (lines_differ): Renamed from line_cmp, and return bool not 3-way int. + All callers changed. + Add support for IGNORE_TAB_EXPANSION. + (change_letter): Now an array rather than a function. All + callers changed. + (translate_range): Translate line numbers to long, not lin, + for convenience with printf. + (analyze_hunk): Return enum changes instead of a count of + inserts and deletes. All callers changed. + (zalloc): New function. + + * src/side.c: Assume C89 or better. + int -> bool for booleans. + int -> lin for line numbers. + + * src/sdiff.c: Assume C89 or better. + int -> bool for booleans. + int -> lin for line numbers. + Use angle-brackets when including getopt.h, quotesys.h. + Include error.h, freesoft.h, stdio.h, xalloc.h. + (copyright_string): Use only most recent year. + (authorship_msgid, option_help_msgid): Wrap in N_(). + + (tmpname): Now volatile. + (tmpmade): Remove. + (tmp): New var. + (private_tempnam, exists, letters): Remove. + (temporary_file): New function. + (edit): Use it. + (interact): Use strtoumax, not atoi. + + * src/normal.c: Assume C89 or better. + int -> lin for line numbers. + + * src/io.c: Assume C89 or better. + int -> bool for booleans. + int -> lin for line numbers. + int -> size_t for sizes. + Use angle-brackets when including cmpbuf.h. + Include regex.h, xalloc.h. + (word): Remove; now done in system.h. + (hash_value): New type; use it instead of 'unsigned' for hash values. + (file_block_read): New function. + (sip, slurp): Use it. Now static. + (sip): Ensure block size is a multiple of word size. Clear eof flag. + (slurp): Use xalloc_die to report memory exhaustion. + (find_and_hash_each_line): Use TOLOWER instead of _tolower. + Add support for IGNORE_TAB_EXPANSION. + (prepare_text_end): Strip trailing CR if requested. + (find_identical_ends): Prepare the text only once, + if they're duplicates. + Let the compiler take advantage more of the fact that the buffers are + word-aligned. + (primes): Remove. + (prime_offset): New var. + (read_var): Use prime_offset instead of primes. + Use zalloc instead of xmalloc + bzero. + + * src/ifdef.c: Assume C89 or better. + int -> lin for line numbers. + (format_group): Use strtoumax to parse line numbers. + (format_group, print_ifdef_lines): Use do_printf_spec to + handle printf specs. + (groups_letter_value): Don't use _tolower; it's locale-dependent. + (do_printf_spec): Renamed from scan_printf_spec; now does the printing. + + * src/ed.c: Assume C89 or better. + int -> lin for line numbers (or 'long' when that's more convenient). + (print_ed_hunk): Fix bug when handling double-dot inserts. + + * src/dir.c: Assume C89 or better. + int -> bool for booleans. + Include error.h, exclude.h, xalloc.h. + + (dir_sort): Return 0 on error, 1 on success. All callers changed. + compare_names -> compare_names_for_qsort. + + (compare_names): Try strcasecmp if ignore_file_name_case. Then try + strcoll. Use file_name_cmp only as a last resort. Warn about + strcasecmp or strcoll failure. + (compare_names_for_qsort): New function. + + (diff_dirs): Use compare_names rather than filename_cmp. + + * src/diff3.c: Assume C89 or better. + int -> bool for booleans. + int -> lin for line numbers. + Use angle-brackets when including getopt.h, quotesys.h. + Include error.h, freesoft.h, inttostr.h, xalloc.h. + (copyright_string): Use only most recent year. + (authorship_msgid, option_help_msgid): Wrap in N_(). + + Rename the following variables for consistency with user-visible + option spellings. All uses changed. + (text): Renamed from always_text. + (initial_tab): Renamed from tab_align_flag. + + (horizon_lines): Remove. Remove all uses. + + (main): Invoke bindtextdomain and textdomain after setlocale. + Rename "DIFF" to "DIFF_PROGRAM". + + Try to compare file0 to file1, because this is where changes are + expected to come from. Diffing between these pairs of files is more + likely to avoid phantom changes from file0 to file1. + However, use file2 as the common file if this is a 3-way diff, + for backward compatibility. Suggested by Karl Tomlinson. + + (create_diff3_block): Use xcalloc instead of malloc + bzero. + + (INT_STRLEN_BOUND): Remove; now in system.h. + + (read_diff): Always use --horizon-lines=100 rather than trying + to guess it. + Do not pass --inhibit-hunk-merge. + Minimum chunk size is 1, not 8KiB. + Use xalloc_die to report memory exhaustion. + (undotlines): Use long for start, not int. + + * src/diff.h: Assume C89 or better. + int -> bool for booleans. + int -> lin for line numbers. + Don't include regex.h. + (enum changes): New enum. + (enum line_class): Remove; subsumed by enum changes. + (enum output_style): New constant OUTPUT_UNSPECIFIED. + + (ignore_space_change_flag, ignore_all_space_flag): Remove. + (ignore_white_space): New decl, subsuming the above two. All + uses changed. + + Rename the following decls for consistency with user-visible + option spellings. All uses changed. + (text): Renamed from always_text_flag. + (ignore_blank_lines): Renamed from ignore_blank_lines_flag. + (ignore_case): Renamed from ignore_case_flag. + (brief): Renamed from no_details_flag. + (initial_tab): Renamed from tab_align_flag. + (expand_tabs): Renamed from tab_expand_flag. + (starting_file): Renamed from dir_start_file. + (paginate): Renamed from paginate_flag. + (sdiff_merge_assist): Renamed from sdiff_help_sdiff. + (left_column): Renamed from sdiff_left_only. + (suppress_common_lines): Renamed from sdiff_skip_common_lines. + (speed_large_files): Renamed from heuristic. + (minimal): Renamed from no_discards. + + (inhibit_hunk_merge): Remove. + + (strip_trailing_cr, excluded, time_format): New decls. + + (files_can_be_treated_as_binary): Renamed from ignore_some_changes. + + (group_format, line_format): Now char const *[], not char *[]. + + (struct file_data): Buffer is now word*, not char*, as it's always + aligned and this can help the compiler. buffered_chars -> buffered + (since it's a byte count, not a char count). All uses changed. + New member `eof'. + + (FILE_BUFFER): New macro. + + (excluded_filename, error, free_software_msgid): Remove decls; now in + other .h files. + + (sip, slurp): Remove decls. + (file_block_read): New decl. + (change_letter): Now an array, not a function. + (lines_differ): Renamed from line_cmp. + (analyze_hunk): Now returns enum changes rather than two change counts. + + * src/Makefile.am (diff_LDADD): New symbol. + + * src/diff.c: Assume C89 or better. + int -> bool for booleans. + long -> off_t for line numbers. + Use angle-brackets when including getopt.h, fnmatch.h, quotesys.h. + Include error.h, exclude.h, freesoft.h, hard-locale.h, prepargs.h, + regex.h, signal.h, xalloc.h. + (copyright_string): Use only most recent year. + (authorship_msgid, option_help_msgid): Wrap in N_(). + + Rename the following variables for consistency with user-visible + option spellings. All uses changed. + (binary): Renamed from binary_flag. + (new_file): Renamed from entire_new_file_flag. + (unidirectional_new_file): Renamed from unidirectional_new_file_flag. + (report_identical_files): Renamed from print_file_same_flag. + + (numeric_arg): Remove. + + (exclude, exclude_alloc, exclude_count, excluded_filename, add_exclude, + add_exclude_file): + Remove; now done by exclude.h. + + (BINARY_OPTION, FROM_FILE_OPTION, HELP_OPTION, HORIZON_LINES_OPTION, + IGNORE_FILE_NAME_CASE_OPTION, INHIBIT_HUNK_MERGE_OPTION, + LEFT_COLUMN_OPTION, LINE_FORMAT_OPTION, NORMAL_OPTION, + SDIFF_MERGE_ASSIST_OPTION, STRIP_TRAILING_CR_OPTION, + SUPPRESS_COMMON_LINES_OPTION, TO_FILE_OPTION, + UNCHANGED_LINE_FORMAT_OPTION, OLD_LINE_FORMAT_OPTION, + NEW_LINE_FORMAT_OPTION, UNCHANGED_GROUP_FORMAT_OPTION, + OLD_GROUP_FORMAT_OPTION, NEW_GROUP_FORMAT_OPTION, + CHANGED_GROUP_FORMAT_OPTION): New constants. + (longopts, main): Use them. + + (longopts, main, option_help_msgid): Add -E, --from-file, --to-file. + + (main): Invoke bindtextdomain and textdomain after setlocale. + Use grep syntax, not Emacs, for regular expressions. + Use exclude.h, not our own functions. + Use ISO 8601 time format in hard locales. + Prepend DIFF_OPTIONS. + Don't update ignore_some_changes. + Use strtoumax instead of numeric_arg. + Use specify_value when appropriate. + error -> try_help when appropriate. + -p now means ^[[:alpha:]$_], not ^[_a-zA-Z$]. + Ignore --inhibit-hunk-merge. + Prefer changed group formats to unchanged ones. + Remove now-unnecessary casts. + Set files_can_be_treated_as_binary. + + (specify_value): Renamed from specify_format. All uses changed. + + (specify_style): Default is now unspecified, not normal. All + uses changed. + + (set_mtime_to_now): New function. + (compare_files): Use it. Use memset, not bzero. + Set stdin mtime to current time even when stdin is not a regular file. + Check for same file attributes, as well as for same file. + Use files_can_be_treated_as_binary. + "write failed" -> "standard output on output failure. + + * src/context.c: Assume C89 or better. + int -> lin for line numbers. + Include inttostr.h, regex.h. + (TIMESPEC_NS): New macro. + (nstrftime): New decl. + (print_context_label): Use nstrftime and time_format to format times. + Print numeric time stamp value if localtime fails. + (print_context_function): New function. + (pr_context_hunk, pr_unidiff_hunk): Use it. + (find_function): Use size_t for sizes, not int. + + * src/cmp.c: Assume C89 or better. + int -> bool for booleans. + long -> off_t for line numbers. + Use angle-brackets when including cmpbuf.h, getopt.h. + Include error.h, freesoft.h, inttostr.h, xalloc.h. + (copyright_string): Use only most recent year. + (authorship_msgid): Wrap in N_(). + (buffer): Now word*, not char*. All uses changed. + (word): Remove macro; now in system.h. + (long_options, option_help_msgid, main): -c --print-chars -> + -b --print-bytes + (check_stdout): "write failed" -> "standard output" + (option_help_msgid): Wrap in N_(). + (main): Invoke bindtextdomain and textdomain after setlocale. + Use strtoumax instead of doing the work ourselves. + Check for same_file_attributes as well as same_file. + (cmp): Use ssize_t for read returns, not size_t. + Do not assume that size_t is not narrower than int. + Do not assume that line numbers fit in 'long'. + (block_compare_and_count, block_compare): + Compiler now checks that buffers are word-aligned. + (block_compare_and_count): Count sizes with size_t, not long. + (sprintc): byte arg is unsigned char, not unsigned. + + * src/analyze.c: Assume C89 or better. + int -> lin for line numbers. + int -> bool for booleans. + unsigned int -> size_t for sizes. + Use angle-brackets when including cmpbuf.h. + Include error.h, regex.h, xalloc.h. + (discard_confusing_lines, diff_2_files): Use zalloc rather + than xalloc+bzero. + (discard_confusing_lines): unsigned int -> lin for values that + are really line numbers. + (shift_boundaries): Do not inhibit hunk merges. + (build_reverse_script, build_script, diff_2_files): Use |, not ||. + (diff_2_files): no_details_flag & ~ignore_some_changes -> + files_can_be_treated_as_binary. Esure that buffer size is a multiple + of sizeof (word). Use file_block_read to read buffers. + (diff_2_files): Abort if output style is not one of the + expected styles. + +2001-11-23 Paul Eggert + + * src/Makefile.am, m4/vararrays.m4: New file. + + * m4/prereq.m4 (jm_PREREQ_READUTMP): + Remove, as it gives autoheader the willies. + + * m4/README, lib/prepargs.h, lib/prepargs.c, lib/offtostr.c, + lib/umaxtostr.c, lib/inttostr.c, lib/inttostr.h, + lib/imaxtostr.c, lib/freesoft.h: New files. + + * lib/freesoft.c: Include config.h, freesoft.h rather than diff.h. + (free_software_msgid): Wrap contents in N_. + + * lib/cmpbuf.h: Use prototypes instead of old-style functions. + + * lib/cmpbuf.c: + Don't include system.h; instead, include config.h, unistd.h. + Use prototypes instead of old-style functions. + (block_read): Don't assume that int is no wider than size_t. + + * lib/Makefile.am, po/POTFILES.in: New file. + +2001-11-22 Paul Eggert + + * pc/config.h: + Define filename_cmp as an object-like macro, not as a function-like + macro. + + * exgettext: Always operate in the C locale. + Set AWK using a method that works even with broken shells. + + * doc/Makefile.am: New file. + + * configure.ac (AC_INIT): + Use src/diff.c, not diff.h, as the source files got removed. + (AM_CONFIG_HEADER): Switch from AC_CONFIG_HEADER. + (AC_ARG_PROGRAM, AC_MINIX): Remove. + + (AC_PREREQ, AM_INIT_AUTOMAKE, ALL_LINGUAS, AC_PROG_AWK, + AM_PROG_CC_STDC, AC_PROG_RANLIB, AC_C_INLINE, AC_C_VARARRAYS, + DEFAULT_DIFF_PROGRAM, DEFAULT_EDITOR_PROGRAM, + AC_STRUCT_ST_MTIM_NSEC): Add. + + (PR_PROGRAM): AC_DEFINE. + + (AC_SYS_LARGEFILE): Use instead of our homebrew version. + + (_GNU_SOURCE): Define if not defined. + + (AC_CHECK_HEADERS): Add stdbool.h, unistd.h. + (AC_CHECK_TYPES): Add ptrdiff_t, uintmax_t. + (AM_GNU_GETTEXT, XGETTEXT): Add. + + (WITH_MVFS_STAT_BUG, WITH_NFS_STAT_BUG): Remove. + (HAVE_MEMCHR): Remove. + (AC_CHECK_FUNCS): Add diraccess. + (AC_REPLACE_FUNCS): Add memchr, waitpid. + (jm_FUNC_GLIBC_UNLOCKED_IO, jm_FUNC_GNU_STRFTIME, jm_FUNC_MALLOC, + jm_FUNC_REALLOC, jm_PREREQ_ERROR, jm_PREREQ_QUOTEARG, jm_PREREQ_REGEX, + jm_PREREQ_TEMPNAME, jm_AC_PREREQ_XSTRTOUMAX, AC_FUNC_FNMATCH): Add. + (fnmatch.h, regex.h): Do not create these files unless we're using + our own fnmatch and regex. + + (AC_OUTPUT): Add doc/Makefile, intl/Makefile, lib/Makefile, + lib/posix/Makefile, m4/Makefile, po/Makefile.in, src/Makefile. + + * Makefile.am: New file. + + * po/en_GB.po: Don't translate "program" to "programme". + +2001-11-20 Paul Eggert + + * m4/prereq.m4: New file. + +2001-03-16 Paul Eggert + + * lib/tempname.c (uint64_t): + Define if not defined, and if UINT64_MAX is not defined. + +2001-02-26 Paul Eggert + + * lib/tempname.c: glibc 1.32 + +2001-02-17 Paul Eggert + + * m4/Makefile.am.in: GNU fileutils 4.1 + +2001-01-09 Paul Eggert + + * lib/tempname.c (struct_stat64): New macro. + (direxists, __gen_tempname): Use it. This avoids a portability problem + with Solaris 8. + + * lib/tempname.c (): Include if HAVE_CONFIG_H. + (, , ): + Include only if STDC_HEADERS || _LIBC. + (): Include only if HAVE_FCNTL_H || _LIBC. + (): Include only if HAVE_UNISTD_H || _LIBC. + (): Include only if HAVE_SYS_TIME_H || _LIBC. + (__set_errno): Define this macro if doesn't. + (P_tmpdir, TMP_MAX, __GT_FILE, __GT_BIGFILE, __GT_DIR, __GT_NOCREATE): + Define these macros if doesn't. + (S_ISDIR, S_IRUSR, S_IWUSR, S_IXUSR): + Define these macros if + doesn't. Ignore S_ISDIR if STAT_MACROS_BROKEN. + (stat64, __getpid, __gettimeofday, __mkdir, __open, __open64, lxstat64, + __xstat64): Define if not _LIBC. + (__secure_getenv): Define if ! (HAVE___SECURE_GETENV || _LIBC). + (__gen_tempname): Invoke gettimeofday only if HAVE_GETTIMEOFDAY + || _LIBC; otherwise, fall back on plain "time". + Use macros like S_IRUSR | S_IWUSR rather than octal values like 0600. + + * lib/mkstemp.c (__GT_FILE): Define to zero if not defined. + +2000-10-25 Paul Eggert + + * lib/hard-locale.c: New file. + +2000-02-05 Paul Eggert + + * exgettext: From GCC repository + +1999-07-06 Paul Eggert + + * lib/mkstemp.c: glibc 2.2 + +1998-12-11 Paul Eggert + + * src/sdiff.c (lf_snarf): + Fix bug when help line wrapped around the input buffer. + +1998-09-15 Paul Eggert + + * diff.texi: Add @dircategory and @direntry. + +1998-09-14 Paul Eggert + + * Makefile.in (VERSION): Version 2.7.2. + (DEFAULT_DIFF_PROGRAM): Renamed from DIFF_PROGRAM. + (PR_PROGRAM): All `configure' to define it. + (srcs): Add $(diffutils_srcs), freesoft.c, quotearg.c instead of + quote.c, quotearg.h. + (distfiles): Add acconfig.h, message/*. + (all): Depend on $(destfiles), not info. + (version.c): Parenthesize `GNU diffutils'. + (common_o): Add freesoft.o + (diff_o): quote.o -> quotearg.o + (diff3_o, sdiff_o): Likewise. + (diff.dvi): Depend on version.texi. + (diff.o diff3.o quotearg.o sdiff.o util.o): + New dependency on quotearg.h + (diff3.o): DIFF_PROGRAM -> DEFAULT_DIFF_PROGRAM. + (sdiff.o): Likewise. + (messages.po): Remove. + (message/msgid.po, message/template.po): New rules. + (maintainer-clean): Renamed from realclean. + (install): Install from source directory, if applicable. + Invoke install-info if needed. + (install-strip): New rule. + (check): Set DIFF. + (stamp-h.in): Don't put the date into the timestamp. + (D_dirs): Add $D/message. + ($D.tar.gz): Compress with gzip -9. + Don't use ln to create distribution; it doesn't work with symlinks. + (srcs, distfiles, diff_o, diff3_o, sdiff_o): Rename quotearg.c to + quotesys.c and quotearg.h to quotesys.h. + + * configure.in (AC_PATH_PROG): Add PR_PROGRAM. + If available, prefer support for large files unless the user specified + one of the CPPFLAGS, LDFLAGS, or LIBS variables. + (AC_STRUCT_ST_RDEV): Add. + (HAVE_ST_FSTYPE_STRING): Add. + (--with-mvfs-stat-bug, --with-nfs-stat-bug): New options. + (HAVE_MEMCHR): New macro. + (AC_CHECK_FUNCS): Add sicprocmask. + + * diff.h (XTERN): Renamed from EXTERN. + (struct filedata): Remove dir_p arg. + (struct comparison): New type. + (diff_2_files, diff_dirs)" Ise ot/ + (error): Add printf attribute if applicable. + (free_software_msgid): New decl. + (pr_program): New decl. + (fatal): Add noreturn attribute. + (pfatal_with_name): Likewise. + + * system.h (__attribute__): New macro. + (getenv): Don't declare if HAVE_STDLIB_H. + (CHAR_MAX): New macro. + (): New include. + (): Include before . + (could_be_mvfs_stat_bug, could_be_nfs_stat_bug, + dev_may_have_duplicate_ino, same_special_file): New macros. + (same_file): Use them. + + * cmp.c (authorship_msgid): New var. + (free_software_msgid): New decl. + (error): Now has printf attribute. + (try_help): Likewise. + (long_options): Don't assume ASCII. + (try_help): Now accepts operand arg. + (main): Check for -1, not EOF, when calling getopt_long. + Report --ignore-initial value when complaining about it. + Output copyright and free software info with -v. + Don't assume ASCII. + Report last operand when one is missing. + Report text of extra operand. + Move block_read into cmpbuf.c. + + * diff.c (authorship_msgid): New var. + (quotesys.h): Include. + (ck_atoi): Remove. + (function_regexp_list, ignore_regexp_list): Now static. + (binary_flag): Renamed from binary_I_O. + (entire_new_file_flag, unidirectional_new_file_flag, + print_file_same_flag): Now static. + (numeric_arg): Renamed from ck_atoi. + New argument specifying the argument type. + (longopts, main): Don't assume ASCII. + (longopts): Remove old aliases --file-label, --entire-new-file, + --ascii, --print. + (main): Check for -1, not EOF, when calling getopt_long. + Use numeric_arg to report errors. + Report error if -l specified but pagination is not supported. + Report error if -S is specified twice with conflicting values. + Have --version conform to the new GNU standards. + Add new --from-file, --to-file, --inhibit-hun,-merge options. + Make the horizon at least as large as the context. + Add casts to pacify gcc -Wall. + (try_help): Add operand arg. + (option_help_msgid): Doc fix to match above. + (usage): Indent option_help_msgid. + (compare_files): Now takes struct comparison + instead of two directory names and a depth. + (NONEXISTENT, UNOPENED, ERRNO_ENCODE, ERRNO_DECODE): + New macros. + (DIR_P): New macro. + Report error if fflush does. + + * cmpbuf.c (block_read): Moved here from cmp.c. + + * cmpbuf.h (block_read): New decl. + + * io.c (cmpbuf.h): Include. + (slurp): Check for arithmetic overflow when computing buffer size. + + * dir.c (diff_dirs): Check for recursive directory loop. + Arg is now struct comparison const *. + (dir_loop): New function + + * analyze.c (no_discards): Remove. + (inhibit): Remove. + (shift_boundaries): Don't inhibit. If inhibit_hunk_merge is nonzero, + don't merge hunks. + (briefly_report): Now returns 2 if trouble, CHANGES otherwise. + (diff_2_files): Now takes struct comparison. If briefly_report reports + trouble, pass it on to caller. + + * side.c (print_half_line): Add brackets to pacify GCC -Wall. + + * sdiff.c (quotesys.h): Include. + (DIFF_PROGRAM, DEFAULT_EDITOR_PROGRAM): Remove. + (free_software_msgid, editor_program, not_found): New vars. + (diffbin, edbin): Remove. + (editor_program): Renamed from edbin. + (edit, interact): Now take extra string arg. + (exiterr, fatal, perror_fatal, try_help): Add noreturn attribute. + (sigset_t, sigemptyset, sigmask, sigaddset, SIG_BLOCK, SIG_SETMASK): + (sigprocmask): New macros, if !HAVE_SIGPROCMASK. + (error): Now has printf attribute. + (longopts, main): Don't assume ASCII. + (try_help): New operand arg. + (usage): Conform to new GNU standards. + (main): Set static vars for editor and diff program. + Compare getopt_long result to -1, not EOF. + -v conforms to new GNU standard. + Complain better about extra and missing operands. + If HAVE_VFORK, block SIGINT and SIGPIPE in the parent, since when + the child munges its handlers it may somp on the parent. + Pass rname to intract. + Translate not-found message before forking. + (give_help): Just output it all at once. + (edit): New args lname, lline, rname, rline. + (edit): New command 'd'. + (interact): New args lname, rname. + + * util.c (quotesys.h): Include. + (PR_PROGRAM): New macro. + (pfatal_with_name): Abort if error returns. + (fatal): Likewise. + (print_message_queue): Free message chain after printing. + (currently_recursive): Renamed from current_depth, and now a boolean. + (begin_output): Report error if fflush does. + Avoid stdio and gettext in child. + + * diff3.c (quotesys.h): Include. + (free_software_msgid): New decl. + (RANGE_START, RANGE_END): Renamed from START and END. + (fatal, perror_with_exit, try_help): Add noreturn attribute. + (error): Add printf attribute. + (diff_program): Now a ptr, not an array. + Initialize to DEFAULT_DIFF_PROGRAM instead of DIFF_PROGRAM. + (longopts, main): Don't assume ASCII. + (main): Use DIFF environment var to specify name of diff program. + Compare getopt_long result to -1, not EOF. + -v now reports version according to new GNU standard. + Report spelling of extra operand, or last operand before missing one. + (try_help): Now takes operand arg. + (option_help_ms): Fix typo: missing comma. + (usage): Update as per current GNU standards. + (environ): Remove decl. + (read_diff): Invoke diff with --inhibit-hunk-merge. + Translate `not found' message before forking. + Quote name of diff program. + Pass horizon lines. + `memory exhausted' -> `Memory exhausted' + + * pc/makefile (%.exe): Remove. + (pc-clean): Remove *.exe + * pc/makefile.sed (DEFAULT_DIFF_PROGRAM): Renamed from DIFF_PROGRAM. + When editing mkinstalldirs rule, look for exec_prefix and prefix. + Add .exe when installing files. + * pc/emx/config.h (same_file): Add. + * pc/config.h (same_file): Remove. + * pc/djgpp/config.h: Adjust to latest patch from eliz. + * pc/djgpp/makefile.sed: Don't alter PROGRAMS. + * pc/pc.c: Update FSF address. + (quote_system_arg): Renamed from system_quote_arg. + + * README: Add --with-mvfs-stat-bug, --with-nfs-stat-bug. + + * getmsgids: Add copyright date and update FSF address. + + * diff.texi: Document recent changes. + The patch doc still corresponds to patch 2.2, unfortunately. + Update GNU bug reporting address. Omit Larry Wall's address; + it's obsolete and he's busy with perl. + + * context.c: Fix spacing. + + * NEWS: Mention --from-file=FILE, --to-file=FILE, ed. + + * acconfig.h, freesoft.c, message/de.po, message/en_UK.po, + message/es.po, message/fr.po, message/pl.po, message/sv.po: + New files. + + * ed.c: Remove `#if 0'ed code. + + * normal.c, waitpid.c: Update FSF address. + +1998-03-15 Paul Eggert + + * quotesys.c: Renamed from quotearg.c. + + * quotesys.h: Renamed from quotearg.h + (__QUOTESYS_P): Renamed from __QUOTEARG_P. + +1997-05-05 Paul Eggert + + * quotesys.c, quotesys.h: New file. + +Mon Nov 14 05:10:56 1994 Paul Eggert + + Add internationalization support. + Several messages have been changed slightly, + to make them more consistent and easier to translate. + All strings that are messages are passed through gettext once before + being used, so that they can be localized. + Each function and macro whose first parameter is a gettext msgid + has had its first parameter's name changed so it ends in `msgid'. + All arrays of msgids have had their names changed to end in `msgid'. + `getmsgids' uses this to determine which strings are msgids. + + * pc/COPYING, pc/INSTALL, pc/config.h, + pc/djgpp/config.h, pc/djgpp/makefile.sed, + pc/emx/config.h, pc/emx/diff.def, pc/emx/gnuregex.def, + pc/emx/makefile.sed, + pc/makefile, pc/makefile.sed, pc/pc.c: New files, for PC support. + + * getmsgids: New file. + + * Makefile.in (PACKAGE, VERSION, diffutils_srcs, D): New vars. + (version.c, version.texi, messages.po): New files. + messages.po is built automatically from source files and `getmsgids'. + (distfiles): Add them, pc/*, and getmsgids. + (diff.info): Now depends on version.texi. + (realclean): Clean messages.po, version.*. + (dist): Just build $D.tar.gz. + ($D.tar.gz): New file, takes over old `dist' function. + Don't assume $(distfiles) are all in same directory. + + * configure.in (AC_CHECK_HEADERS): Add libintl.h, locale.h. + (AC_CHECK_LIB): Check for -lintl. + + * analyze.c (briefly_report): Rewrite `message (A?"B":"C")' as + `if (A) message ("B") : message ("C")'; this is for getmsgids. + (briefly_report, diff_2_files): For label, use file_label if set. + * diff.c (compare_files): Likewise. + + * system.h (gettext): Declare; use a stub if ! HAVE_LIBINTL_H. + (setlocale): Declare; use a stub if ! HAVE_LOCALE_H. + + * cmp.c, diff.c, diff3.c, sdiff.c (main): + Invoke setlocale first thing, to tell library we're internationalized. + (option_help_msgid): New constant. + (usage): Use it, so message is translated one option at a time. + * sdiff (help_msgid, give_help): Likewise. + + * cmp.c (sprintc): Renamed from `printc'. + Now outputs to a buffer instead of stdout. + (cmp): Use new sprintc; it's easier to internationalize. + + * diff.c (main): -D FOO now outputs `/* ! FOO */ instead of + `/* not FOO */'. + + * sdiff.c (version_string): Fix decl typo: `const' was missing. + (trapsigs): Ignore sigaction failure, to be compatible with `signal'. + + * util.c (struct msg, message5, print_message_queue): + Allocate just one block of memory to save a message. + +Wed Nov 9 17:42:44 1994 Paul Eggert + + * sdiff.c (trapsigs): Don't check signal return value, since it's + bogus under djgpp. + +Mon Oct 31 07:27:27 1994 Paul Eggert + + * Makefile.in (srcs, diff_o, diff3_o, sdiff_o): + New files quote.c, quote.o. + + * diff.h (function_regexp, ignore_regexp): Replace lists of compiled + regexps with these single compiled regexps. All users changed. + (regexp_list,function_regexp_list,ignore_regexp_list): Move to diff.c. + * diff.c (add_regexp): Build one big regexp instead of a regexp list. + (summarize_regexp_list): New function. + (regexp_list): Redesigned struct; moved here from diff.h. + (function_regexp_list, ignore_regexp_list): Likewise, for vars. + + * context.c (find_function): Simplify interface: + don't return size of function line. All callers changed. + (print_context_script, find_function): INT_MAX now denotes no + previous match; this is simpler than `- file->prefix_lines - 1'. + + * diff3.c (read_diff): Quote arguments with system_quote_arg. + * sdiff.c (main): Use system_quote_arg to compute command. + * diff.c (option_list): Quote options with system_quote_arg. + * util.c (begin_output): Use system_quote_arg to compute command. + + * util.c (pr_program): New var. + (analyze_hunk): Fix off-by-1 line length bug. + Match with one big regexp instead of a list of regexps. + Use new `trivial_length' local instead of comparing first byte to `\n'. + Help the compiler with linbuf local vars. + + * system.h (system_quote_arg): + New function; replaces SYSTEM_QUOTE_ARG macro. + +Sat Oct 15 20:09:12 1994 Paul Eggert + + * system.h (_tolower): Define if not already defined. + * io.c (find_and_hash_each_line): Change tolower to _tolower; this + speeds up diff -i considerably on some hosts (e.g. Solaris 2.3). + * util.c (line_cmp): Likewise. + * ifdef.c (groups_letter_value): Likewise. + + * diff.h (ignore_some_line_changes): Remove. All users changed. + * io.c (find_and_hash_each_line): Don't invoke line_cmp if the length + differs and -i is in force. Don't assume ISSPACE ('\n') is nonzero. + + * diff.h (xmalloc_exit_failure): New variable. + All `main' programs set this variable at the start. + xmalloc and xrealloc are now taken from GNU library. + * cmp.c (main): Align buffer size to word size; some mallocs care. + * io.c (slurp): Likewise. + * diff.c (add_exclude): Can now assume xrealloc (0, ...) works. + (add_regexp): Free storage on failure. Allocate storage all at one go. + * system.h (malloc, realloc): Remove unused declarations. + * diff3.c, sdiff.c, util.c (xmalloc, xrealloc): Remove. + * sdiff.c (diffarg): Take advantage of cleaner xrealloc semantics. + + * io.c (ROL): Use sizeof to make it more generic. + + * Makefile.in (common_o): New variable. + Link error.o and xmalloc.o into all programs. + (check): Depend on $(PROGRAMS). + + * diff.h (error): Change to GNU library standard. All callers changed. + * diff3.c (main): Use strerror (EISDIR) instead of "Is a directory". + (fatal, perror_with_exit): Use `error'. + * util.c (perror_with_name, fatal): Use GNU `error'. + (error): Remove. + +Wed Oct 12 17:04:40 1994 David J. MacKenzie (djm@duality.gnu.ai.mit.edu) + + * cmp.c (main): Set xmalloc_exit_failure. + +Sat Oct 1 05:24:19 1994 Paul Eggert + + * Version 2.7 released. + + * configure.in (AC_HEADER_SYS_WAIT): Add. + (AC_CHECK_HEADERS): Remove sys/wait.h. + (AC_CHECK_FUNCS): Add tmpnam. + * system.h (, WEXITSTATUS): Use simpler scheme + now that HAVE_SYS_WAIT_H is not set on hosts + that are incompatible with Posix applications. + + * util.c (dir_file_pathname): Use filename_lastdirchar not strrchr. + * sdiff.c (expand_name): Likewise. + (private_tempnam): Use tmpnam if HAVE_TMPNAM; this simplifies porting. + (exists, letters): Omit if HAVE_TMPNAM. + + * diff3.c (read_diff): If STAT_BLOCKSIZE yields zero, + adjust it to a more reasonable value. + +Sat Sep 24 20:36:40 1994 Paul Eggert + + * sdiff.c (exists, private_tempname): Adopt latest GNU libc algorithm. + (private_tempnam): Specialize for sdiff to avoid portability problems. + +Thu Sep 22 16:47:00 1994 Paul Eggert + + * configure.in (AC_ARG_PROGRAM): Added. + (AC_OUTPUT): Add [date > stamp-h]. + + * Makefile.in (DEFAULT_EDITOR_PROGRAM, DIFF_PROGRAM, LIBOBJS, + NULL_DEVICE, PR_PROGRAM, PROGRAMS): New variables. + (check, stamp-h.in, cmp.o, util.o): New targets. + (edit_program_name): New variable; replaces old binprefix method. + (install, uninstall): Use it. + (binprefix): Removed. + (distfiles): Add stamp-h.in. + (clean): Clean stamp-h. + (config.hin, config.h): Use time stamp files. + (cmp_o): Add $(LIBOBJS). + (install): Install info files from srcdir if they're not in `.'. + + * cmp.c, io.c (word): Don't define if already defined. + + * comp.c (main): Use setmode, not open(..., O_BINARY); this gets stdin. + Use NULL_DEVICE instead of "/dev/null". + (cmp): Use %lu instead of %ld when it is more likely to be right. + + * diff.h (PR_FILE_NAME): Rename to PR_PROGRAM and move to Makefile.in, + util.c. + + * diff3.c (main): Give proper diagnostic if too many labels were given. + (read_diff): Use SYSTEM_QUOTE_ARG. + + * system.h: : Include if HAVE_STRING_H, too. + : Include here. All includers changed. + (CTYPE_DOMAIN, ISDIGIT, ISPRINT, ISSPACE, ISUPPER): New macros that + work around common problems. + (O_BINARY): Remove. + (SYSTEM_QUOTE_ARG): New macros. + + * diff.c: Add comment. + + * util.c (PR_PROGRAM): Moved here from diff.h. + (begin_output): Use SYSTEM_QUOTE_ARG. + + * io.c (read_files): Set mode to binary before returning 1. + + * sdiff.c (TMPDIR_ENV): New macro. + (DEFAULT_EDITOR_PROGRAM): Renamed from DEFAULT_EDITOR for consistency. + (expand_name): Change `isdir' to `is_dir' to avoid theoretical ctype + namespace contamination. + (main): Use SYSTEM_QUOTE_ARG. + (private_tempnam): Don't access "/tmp" directly; use PVT_tmpdir. + +Tue Sep 13 18:46:43 1994 Paul Eggert + + * configure.in (AC_FUNC_MEMCHR): Remove. Autoconf didn't adopt this, + since we need not worry about an old experimental library + where memchr didn't work. + (AC_FUNC_MEMCMP): Not needed, since we only test for equality. + (AC_REPLACE_FUNCS): Add test for memchr. + (AC_CHECK_FUNCS): Check for memchr, not memcpy, since it'll be cached. + (AC_CHECK_HEADERS): Add string.h; regex.c uses on some old hosts. + + * system.h (memcmp): Define in terms of bcmp. + Use HAVE_MEMCHR to test for all mem* routines. + + * Makefile.in (srcs): Remove memcmp.c. + We use bcmp if memcmp doesn't work, since we only test for equality. + +Mon Sep 12 15:52:22 1994 Paul Eggert + + * configure.in (AC_CONFIG_HEADER): Rename config.h.in to config.hin. + (AC_ISC_POSIX, AC_MINIX): Go back to these old names for Autoconf 2. + (AC_CHECK_HEADERS): Remove now-redundant check for . + (AC_CHECK_FUNCS): Check for strchr. + (AC_FUNC_MEMCHR, AC_FUNC_MEMCMP, AC_CHECK_FUNCS): Use special-purpose + macros when suitable. + * memcmp.c: New file. + * Makefile.in (CPPFLAGS, DEFS, CFLAGS, LDFLAGS, prefix, exec_prefix): + Default to autoconf-specified strings. + (COMPILE): Use the defaults. + (srcs): Add memcmp.c. + (distfiles): Rename config.h.in->config.hin, install.sh->install-sh. + (Makefile, config.h, config.hin, config.status): Rework for + compatibility with Autoconf 2. + * io.c (binary_file_p): Assume non-broken memchr. + * memchr.c: Assume compiler understands void *; otherwise + we don't match GCC's internal declaration of memchr. + * system.h: Use more modern autoconf approach to standard C headers. + * version.c: Include , not "config.h". + + * diff.c, diff.h (ignore_some_line_changes): + New variable; replaces `length_varies'. + (line_end_char): Replace with '\n'; it wasn't being used consistently. + + * io.c (find_and_hash_each_line): Fix inconsistencies with -b -w -i and + incomplete lines. Put incomplete lines into their own bucket. + This means line_cmp no longer needs line length arguments, + and equivalence classes' line lengths no longer need to include \n. + Invoke line_cmp only if ignore_some_line_changes. + (prepare_text_end): -B no longer ignores missing newlines. + (read_files): Allocate another bucket for incomplete lines. + + * util.c (line_cmp): Now takes just two arguments. No longer + optimizes for common case of exact equality; the caller does that + optimization now. The caller is changed accordingly. + Optimize for the common case of mostly equality. + Use isupper+tolower instead of islower+toupper, for consistency. + + * waitpid.c (waitpid): Fix typo with internal scoping. + +Thu Sep 8 08:23:15 1994 Paul Eggert + + * configure.in: Revamp for Autoconf 2. + * memchr.c, waitpid.c: New source files for substitute functions. + * Makefile.in (diff_o, diff3_o, sdiff_o): Add $(LIBOBJS). + (srcs): Add memchr.c, waitpid.c. + (distfiles): Add install.sh, memchr.c, waitpid.c, install.sh. + * system.h: Use Autoconf 2 style HAVE_DIRENT_H etc. macros for dirs. + * dir.c (dir_sort): Prefer NAMLEN (p) to strlen (p->d_name). + Change VOID_CLOSEDIR to CLOSEDIR_VOID for Autoconf 2. + * sdiff.c, util.c (memchr, waitpid): Remove; use new substitutes. + * diff3.c (read_diff): Use new waitpid substitute. + + * cmp.c, diff.c, diff3.c, sdiff.c (check_stdout, try_help): New fns. + (usage): Just print more detailed usage message; let caller exit. + * diff.c (option_help): New variable. + (filetype): Add Posix.1b file types. + +Fri Sep 2 16:01:49 1994 Paul Eggert + + * configure.in: Switch to new autoconf names. Add sys/file.h test. + * Makefile.in (distclean): Clean config.cache, config.log + (used by new autoconf). + + * diff.c, diff3.c, (main), sdiff.c (trapsigs): If we'll have children, + make sure SIGCHLD isn't ignored. + + * diff3.c (DIFF_CHUNK_SIZE): Removed. Get size from STAT_BLOCKSIZE. + (INT_STRLEN_BOUND): New macro. + + * ifdef.c (format_group, groups_letter_value): + Use * instead of [] in prototypes. + + * system.h: Include only if HAVE_SYS_FILE_H. + (S_IXGRP, S_IXOTH, S_IXUSR): Remove unused macros. + + * util.c (begin_output): Check fdopen result. + + The following changes simplify porting to non-Posix environments. + * cmp.c, diff.c, diff3.c, sdiff.c, (main): Call initialize_main first. + * diff.c (binary_I_O): New variable for --binary option. + (main, usage, compare_files): Support --binary option. + (compare_files): Use filename_lastdirchar to find last + directory char in a file name. + * cmp.c (main), diff.c (compare_files), dir.c (compare_names, + diff_dirs): Use filename_cmp to compare file names. + Use same_file to determine whether two files are the same. + * context.c (print_context_label): Check whether ctime yields 0. + * diff3.c (read_diff), sdiff.c (cleanup, main, waitpid), + util.c (begin_output): Use popen+pclose if !HAVE_FORK. + * io.c (sip): If HAVE_SETMODE, test for binary files in O_BINARY mode. + * sdiff.c (ck_fdopen): Function removed. + (edit): Use system if !HAVE_FORK. + (execdiff): Now assumes caller has pushed all args, plus trailing 0. + All callers changed. + (private_tempnam): Try TMP if TMPDIR isn't defined. + Fit temporary filenames into 8.3 limit. + * system.h (STAT_BLOCKSIZE): Don't define if already defined. + (min, max): Undef if already defined. + (filename_cmp, filename_lastdirchar, HAVE_FORK, HAVE_SETMODE, + initialize_main, O_BINARY, same_file): New macros. + +Fri Jun 17 11:23:53 1994 David J. MacKenzie (djm@geech.gnu.ai.mit.edu) + + * Makefile.in (info, dvi, diff.dvi): New targets. + (clean): Remove TeX output files. + +Fri Jun 17 05:37:52 1994 Paul Eggert (eggert@twinsun.com) + + * cmp.c, io.c (word): Change from typedef to #define, to avoid + collision with Unicos 8.0 , which also typedefs `word'. + +Thu Apr 15 00:53:01 1994 Paul Eggert (eggert@twinsun.com) + + * diff3.c (scan_diff_line), util.c (print_number_range): Don't + rely on promotion to make the old-style parameter type agree + with the prototype parameter type; this doesn't work on + Apollos running bsd4.3. + +Mon Jan 3 02:05:51 1994 Paul Eggert (eggert@twinsun.com) + + * Makefile.in (LDFLAGS): Remove -g. Change all link commands + to use both $(CFLAGS) and $(LDFLAGS). + +Mon Dec 13 12:23:27 1993 Paul Eggert (eggert@twinsun.com) + + * system.h: Don't assume dirent.h exists just because + _POSIX_VERSION is defined. + +Fri Dec 3 18:39:39 1993 Paul Eggert (eggert@twinsun.com) + + * diff.c (main): allow -pu. + +Tue Nov 23 03:51:08 1993 Paul Eggert (eggert@twinsun.com) + + * Makefile.in (distclean): Remove config.h. + +Wed Nov 10 00:28:27 1993 Paul Eggert (eggert@twinsun.com) + + * Version 2.6 released. + + * analyze.c (too_expensive): New variable, for heuristic to + limit the worst-case cost to O(N**1.5 log N) at the price of + producing suboptimal output for large inputs with many differences. + (diff_2_files): Initialize it. + (struct partition): New type. + (SNAKE_LIMIT): New macro; merely documents already-used number 20. + (diag): New `minimal' arg; all callers changed. Put results into + struct partition. Apply `too_expensive' heuristic. Tune. + (compareseq): New `minimal' arg; all callers changed. Tune. + (shift_boundaries): Improve heuristic to also coalesce adjacent runs + of changes more often. + + * diff.c (long_options, main, usage): Add `--help'. + (main): Send version number to stdout, not stderr. + (usage): Send usage to stdout, not stderr. + (compare_files): Initialize `inf' properly. + + * io.c (word): Change to `int'; it makes a big difference on x86. + (sip, slurp): Put off allocating room to hold the whole file until we + have to read the whole file. This wins if the file turns out + to be binary. + + * util.c (xmalloc, xrealloc): "virtual memory" -> "memory" + (primes): Omit large primes if INT_MAX is small. + + * sdiff.c (usage): Send usage to stdout, not stderr. + (long_options, main, usage): Add `--help'. + (main): Send version number to stdout, not stderr. Exit afterwards. + + * diff3.c (usage): Send usage to stdout, not stderr. + (long_options, main, usage): Add `--help'. + (read_diff): Detect integer overflow in buffer size calculations. + + * cmp.c (word): New type. All uses of `long' for + word-at-a-time comparisons changed to `word'. + (long_options, main, usage): Add `--help'. + (usage): Send usage to stdout, not stderr. + (main): Add `-v'. Send version number to stdout, not stderr. + + * configure.in (AC_HAVE_HEADERS): Add unistd.h; remove AC_UNISTD_H. + +Mon Sep 27 07:20:24 1993 Paul Eggert (eggert@twinsun.com) + + * diff.c (add_exclude_file): Cast memchr to (char *) + to suppress bogus warnings on some nonstandard hosts. + + * Makefile.in (cmp): Add version.o. + + * analyze.c (diff_2_files): Work around memcmp bug with size=0. + + * cmp.c (main, usage, version_string): Add --version option. + + * system.h (malloc, realloc): Declare only if !HAVE_STDLIB_H. + (memchr): Declare only if !HAVE_MEMCHR. These changes are + needed to keep some nonstandard hosts happy. + + * util.c (memchr): Make first arg char const * + to match standard. + (xmalloc, xrealloc): Cast malloc, realloc + to (VOID *) to suppress bogus warnings on some nonstandard hosts. + + * diff3.c (xmalloc, xrealloc): Cast malloc, realloc + to (VOID *) to suppress bogus warnings on some nonstandard hosts. + + * sdiff.c (xmalloc, xrealloc): Cast malloc, realloc + to (VOID *) to suppress bogus warnings on some nonstandard hosts. + (lf_copy, lf_skip, lf_snarf): Cast memchr to (char *) + to suppress bogus warnings on some nonstandard hosts. + (memchr): Make first arg char const * + to match standard. + +Mon Sep 27 00:23:37 1993 Paul Eggert (eggert@twinsun.com) + + * Version 2.5 released. + + * analyze.c (diff_2_files): Work around memcmp bug with size=0. + + * cmp.c (main, usage, version_string): Add --version option. + * Makefile.in (cmp): Add version.o. + + * diff.c (add_exclude_file): Cast memchr to (char *) + to suppress bogus warnings on some nonstandard hosts. + * sdiff.c (lf_copy, lf_skip, lf_snarf): Likewise. + + * diff3.c, sdiff.c, util.c (xmalloc, xrealloc): Cast malloc, realloc + to (VOID *) to suppress bogus warnings on some nonstandard hosts. + + * sdiff.c, util.c (memchr): Make first arg char const * + to match standard. + + * system.h (malloc, realloc): Declare only if !HAVE_STDLIB_H. + (memchr): Declare only if !HAVE_MEMCHR. These changes are + needed to keep some nonstandard hosts happy. + + * xmalloc.c: Include always; some nonstandard hosts + need it for size_t even if STDC_HEADERS. + +Sat Sep 18 01:33:07 1993 Paul Eggert (eggert@twinsun.com) + + * configure.in (AC_STAT_MACROS_BROKEN): Add. + * system.h (S_IS{BLK,CHR,DIR,FIFO,REG,SOCK}): Fix defns if + STAT_MACROS_BROKEN. + + * Makefile.in (diff3, sdiff, cmp): Do not link $(ALLOCA). + + * analyze.c (discard_confusing_lines): Make defn static, like decl. + * sdiff.c (xmalloc): Likewise. + + * ifdef.c (format_group): Ensure isdigit argument isn't < 0. + + * side.c (print_half_line): Use isprint, since some hosts lack isgraph. + * util.c (output_1_line): Likewise. Ensure its argument isn't < 0. + (xmalloc, xrealloc): Remove needless casts. + + * system.h (volatile, const): + Define these before including any system headers, + so that they're used consistently in all system includes. + (getenv, malloc, realloc): Declare even if HAVE_STDLIB_H, since some + s don't declare them. + (memchr): Likewise for . + + * cmp.c, diff3.c, diff.h, sdiff.c: Include "system.h" first. + * diff.c: Remove redundant "system.h" inclusion. + + * diff3.c (xmalloc): Now static. + (xmalloc, realloc): Remove needless casts. + (READNUM): Ensure isdigit argument isn't negative. + +Wed Sep 14 07:14:15 1993 Paul Eggert (eggert@twinsun.com) + + * Version 2.4 released. + + * ifdef.c (scan_char_literal): New function, for new %c'x' and + %c'\ooo' format specs. + (format_group, print_ifdef_lines): Use it. Remove %0 format spec. + + * cmp.c (cmp): Don't try to read past end of file; this doesn't + work on ttys. + + * system.h, version.c: #include , not "config.h", to allow + configuring in a separate directory when the source directory has + already been configured. + * Makefile.in (COMPILE): New defn, with proper -I options so that + `#include ' works. + (.c.o, diff3.o, sdiff.o): Use it. + +Mon Sep 13 06:45:43 1993 Paul Eggert (eggert@twinsun.com) + + * diff.c (main, longopts): Add --line-format=FORMAT option. + (specify_format): Args no longer const pointers. All callers changed. + + * ifdef.c: Add support for %?c, %(A=B?T:E), PRINTF_SPECn formats. + (struct group): New struct. + (print_ifdef_lines): Use it to simplify argument passing. + Remove the convention that last arg -1 signifies that the lines + from file 2 are the same as the lines from file 1; this + convention no longer works, now that line numbers might be + printed out, since the line numbers may differ. + Add first FILE * argument to output to. All callers changed. + Use a faster test for the single-fwrite optimization. + (format_group, scan_printf_spec, groups_letter_value): New functions. + + * diff.h (group_format, line_format): No longer const pointers. + (format_ifdef): 1st arg is no longer const pointer. + + * configure.in: Configure HAVE_LIMITS_H, HAVE_STDLIB_H. + * system.h , , : + Include only if HAVE_LIMITS_H etc. + + * system.h (memcmp, memcpy, strchr, strrchr, struct dirent): Prefer + these standard names to the traditional names (bcmp, bcpy, index, + rindex, struct direct). All callers changed. + + * system.h (PARAMS, VOID): + Define earlier so that malloc decl can use VOID. + (STAT_BLOCKSIZE): Simplify ersatz defn; just use 8K. + +Fri Sep 3 00:21:02 1993 Paul Eggert (eggert@twinsun.com) + + * diff.c (compare_files): Two files with the same name must be + the same file; avoid a needless `stat' in that case. + +Fri Aug 27 06:59:03 1993 Paul Eggert (eggert@twinsun.com) + + * Pervasive changes for portability to 64-bit hosts: + Add prototypes to function declarations. + Use size_t, not int, when needed. + + * Other pervasive changes: + Use `const' more often. + Use STD{IN,OUT,ERR}_FILENO instead of [012]. + Use 0, not NULL, for portability to broken hosts. + + * Makefile.in: (srcs, objs, distfiles, cmp): New files cmpbuf.[ch]. + (distfiles): New files config.h.in, mkinstalldirs. + (.c.o): Add -DHAVE_CONFIG_H. + + * analyze.c: (diag): Pacify `gcc -Wall' with a useless assignment. + (diff_2_files): Use l.c.m., not max, of files' buffer sizes. + + * cmp.c: Make globals static when possible. + + (file): Now a 2-element array; replaces `file1' and `file2'. + (file_desc, buffer): Likewise, for file[12]_desc and buf[12]. + (main): Likewise, for stat_buf[12]. Index these variables with `i'. + + (ignore_initial): New var. + (long_options): Now const. Add `--ignore-initial'. + (usage): Sort options and add `--ignore-initial'. + (main, cmp): Add `--ignore-initial' support. + + (main): `cmp - -' now succeeds. + When comparing standard input to a file, and using a shortcut (e.g. + looking at file sizes or inode numbers), take the lseek offset into + account before deciding whether the files are identical. + Avoid mentioning `dev_t', `ino_t' for portability to nonstandard hosts. + Use l.c.m. of files' buffer sizes, not 8 * 1024. + ferror (stdout) does not imply errno has a useful value. + If 2nd file is "-", treat it first, in case stdin is closed. + + (cmp): Always compute `char_number', `smaller' for speed and simplicity. + Say `cmp: EOF on input', not `/usr/gnu/bin/cmp: EOF on input', + as per Posix.2. + + (block_compare_and_count): Increment line_number argument. + Remove end_char argument; it's always '\n'. All callers changed. + Do not assume sizeof(long) == 4; this isn't true on some 64-bit hosts. + (block_compare): Minimize differences with block_compare_and_count. + + (block_read): Coalesce `bp += nread's. + + (printc): Remove `FILE *' arg; output to stdout. All callers changed. + + * configure.in: Configure HAVE_SIGACTION, RETSIGTYPE, HAVE_VPRINTF. + Configure into config.h. + + * context.c (print_context_label): + Standard input's st_mtime is no longer a special case + here, since `compare_files' now sets it to the current time. + + * diff.c (usage): Sort options. + (filetype): New function. + (compare_files): Set stdin's st_mtime to be the current time. + Leave its name "-" instead of changing it to "Standard Input"; + to test whether a file is stdin, we must compare its name to "-" instead + of its desc to 0, since if it's closed other file descs may be 0. + When comparing standard input to a file, and using a shortcut (e.g. + looking at file sizes or inode numbers), take the lseek offset into + account before deciding whether the files are identical. + Pretend that nonexistent files have the same filetype as existing files. + Rename `errorcount' to `failed', since it's boolean. + In directory comparisons, if a file is neither a regular file nor a + directory, just print its type and the other file's type. + + * diff.h (Is_space, textchar): Remove. + (struct msg, msg_chain, msg_chain_end): Move to util.c. + (VOID): Move to system.h. + (line_cmp, version_string, change_letter, print_number_range, + find_change): New decls. + + * diff.texi: + whitespace -> white space. It now stands for whatever isspace yields. + Add --ignore-initial. + + * diff3.c (VOID): Move to system.h. + (version_string): Now char[]. + (usage): Sort options. + (process_diff): Pacify `gcc -Wall' with a useless assignment. + (read_diff): pid is of type pid_t, not int. Use waitpid if available. + (output_diff3): Simplify test for `\ No newline at end of file' message. + + * dir.c (struct dirdata): Rename `files' to `names' to avoid confusion + with external struct file_data `files'. + + * io.c (line_cmp): Move declaration to diff.h. + (textchar): Remove. + (find_and_hash_each_line): Use locale's definition of white space + instead of using one hardwired defn for -b and another for -w. + + * normal.c (change_letter, print_number_range, find_change): + Move decls to diff.h. + (print_normal_hunk): Now static. + + * sdiff.c (SEEK_SET): Move to system.h. + (version_string): Now char[], not char*. + (private_tempnam): Remove hardcoded limit on temporary file names. + (exiterr, perror_fatal, main): When exiting because of a signal, + exit with that signal's status. + (lf_refill, main, skip_white, edit, interact): Check for signal. + (ignore_SIGINT): Renamed from `ignore_signals'. + (NUM_SIGS, initial_handler): New macros. + (initial_action, signal_received, sigs_trapped): New vars. + (catchsig, trapsigs): Use sigaction if possible, since this closes the + windows of vulnerability that `signal' has. Use RETSIGTYPE not void. + When a signal comes in, just set a global variable; this is safer. + (checksigs, untrapsig): New functions. + (edit): Pacify `gcc -Wall' with a useless assignment. + Respond to each empty line with help, not to every other empty line. + (private_tempnam): Remove hardcoded limit on temporary file name length. + Don't assume sizeof (pid_t) <= sizeof (int). + + * system.h: (S_IXOTH, S_IXGRP, S_IXUSR, + SEEK_SET, SEEK_CUR, + STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO): + New macros, if system doesn't define them. + (volatile): Don't define if already defined. + (PARAMS): New macro. + (VOID): Move here from diff.h. + + * util.c (struct msg, msg_chain, msg_chain_end): Moved here from diff.h. + (message5): New function. + (pr_pid): New var. + (begin_output): Allocate `name' more precisely. + Put child pid into pr_pid, so that we can wait for it later. + Don't check execl's return value, since any return must be an error. + (finish_output): Detect and report output errors. + Use waitpid if available. Check pr exit status. + (line_cmp): Use locale's definition of white space + instead of using one hardwired defn for -b and another for -w. + (analyze_cmp): Avoid double negation with `! nontrivial'. + Pacify `gcc -Wall' be rewriting for-loop into do-while-loop. + (dir_file_pathname): New function. + + * version.c (version_string): Now char[], not char*. + +Thu Jul 29 20:44:30 1993 David J. MacKenzie (djm@wookumz.gnu.ai.mit.edu) + + * Makefile.in (config.status): Run config.status --recheck, not + configure, to get the right args passed. + +Thu Jul 22 10:46:30 1993 Paul Eggert (eggert@twinsun.com) + + * Makefile.in (dist): Replace `if [ ! TEST ]; then ACTION; fi' + with `[ TEST ] || ACTION || exit' so that the containing for-loop exits + with proper status for `make'. + +Thu Jul 8 19:47:22 1993 David J. MacKenzie (djm@goldman.gnu.ai.mit.edu) + + * Makefile.in (installdirs): New target. + (install): Use it. + (Makefile, config.status, configure): New targets. + +Sat Jun 5 23:10:40 1993 Paul Eggert (eggert@twinsun.com) + + * Makefile.in (dist): Switch from .z to .gz. + +Wed May 26 17:16:02 1993 Paul Eggert (eggert@twinsun.com) + + * diff.c (main): Cast args to compare_files, for traditional C. + * side.c (print_sdiff_common_lines, print_sdiff_hunk): Likewise. + * analyze.c, diff3.c, sdiff.c, util.c: Don't assume NULL is defined + properly. + +Tue May 25 14:54:05 1993 Paul Eggert (eggert@twinsun.com) + + * analyze.c (diff_2_files): With -q, do not report that files differ + if all their differences are ignored. + (briefly_report): New function. + * diff.h (ignore_some_changes): New variable. + * diff.c (compare_files): Don't use the file size shortcut if + ignore_some_changes is nonzero, since the file size may differ + merely due to ignored changes. + (main): Set ignore_some_changes if we might ignore some changes. + Remove unsystematic assignment of 0 to static vars. + * io.c (read_files): New argument PRETEND_BINARY says whether to + pretend the files are binary. + + * diff3.c (tab_align_flag): New variable, for new -T option. + (main, usage, output_diff3): Add support for -T. + +Sun May 23 15:25:29 1993 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * dir.c (dir_sort): Always init `data' to avoid GCC warning. + +Sat May 22 15:35:02 1993 Paul Eggert (eggert@twinsun.com) + + * Makefile.in (dist): Change name of package from diff to diffutils. + Don't bother to build .Z dist; .z suffices. + +Fri May 21 16:35:22 1993 Paul Eggert (eggert@twinsun.com) + + * diff.c: Include "system.h" to get memchr declaration. + * system.h (memchr): Declare if !HAVE_MEMCHR, not if + !HAVE_MEMCHR && !STDC_HEADERS. + +Wed May 19 17:43:55 1993 Paul Eggert (eggert@twinsun.com) + + * Version 2.3 released. + +Fri Apr 23 17:18:44 1993 Paul Eggert (eggert@twinsun.com) + + * io.c (find_identical_ends): Do not discard the last HORIZON_LINES + lines of the prefix, or the first HORIZON_LINES lines of the suffix. + * diff.c (main, longopts, usage): Add --horizon-lines option. + * diff3.c (main, process_diff, read_diff): Invoke second diff + with --horizon-lines determined by the first diff. + * diff.h, diff3.c (horizon_lines): New variable. + +Mon Mar 22 16:16:00 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) + + * system.h [HAVE_STRING_H || STDC_HEADERS] (bcopy, bcmp, bzero): + Don't define if already defined. + +Fri Mar 5 00:20:16 1993 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * diff.c (main): Use NULL in arg to compare_files. + +Thu Feb 25 15:26:01 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) + + * system.h: Declare memchr #if !HAVE_MEMCHR && !STDC_HEADERS, + not #if !HAVE_MEMCHR || !STDC_HEADERS. + +Mon Feb 22 15:04:46 1993 Richard Stallman (rms@geech.gnu.ai.mit.edu) + + * io.c (find_identical_ends): Move complicated arg outside GUESS_LINES. + +Mon Feb 22 12:56:12 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) + + * Makefile.in (.c.o): Add -I$(srcdir); put $(CFLAGS) last before $<. + +Sat Feb 20 19:18:56 1993 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * io.c (binary_file_p): Return zero if file size is zero. + +Fri Feb 19 17:31:32 1993 Roland McGrath (roland@geech.gnu.ai.mit.edu) + + * Version 2.2 released. + + * system.h [HAVE_STRING_H || STDC_HEADERS] (index, rindex): Don't + define if already defined. + +Wed Feb 17 17:08:00 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) + + * Makefile.in (srcs): Remove limits.h. + +Thu Feb 11 03:36:00 1993 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * diff3.c (xmalloc): No longer static. + + * sdiff.c (edit): Allocate buf dynamically. + + * dir.c (dir_sort): Handle VOID_CLOSEDIR. + +Wed Feb 10 00:15:54 1993 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * limits.h: File deleted (should never have been there). + +Tue Feb 9 03:53:22 1993 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * Makefile.in (.c.o, diff3.o, sdiff.o): Put $(CFLAGS) last. + +Wed Feb 3 15:42:10 1993 David J. MacKenzie (djm@goldman.gnu.ai.mit.edu) + + * system.h: Don't #define const; let configure do it. + +Mon Feb 1 02:13:23 1993 Paul Eggert (eggert@hal.gnu.ai.mit.edu) + + * Version 2.1 released. + + * Makefile.in (dist): Survive ln failures. Create .tar.z + (gzipped tar) file as well as .tar.Z (compressed tar) file. + +Fri Jan 8 22:31:41 1993 Paul Eggert (eggert@twinsun.com) + + * side.c (print_half_line): When the input position falls + outside the column, do not output a tab even if the output + position still falls within the column. + +Mon Dec 21 13:54:36 1992 David J. MacKenzie (djm@kropotkin.gnu.ai.mit.edu) + + * Makefile.in (.c.o): Add -I. + +Fri Dec 18 14:08:20 1992 Paul Eggert (eggert@twinsun.com) + + * configure.in: Add HAVE_FCNTL_H, since system.h uses it. + +Tue Nov 24 10:06:48 1992 David J. MacKenzie (djm@goldman.gnu.ai.mit.edu) + + * Makefile.in: Note change from USG to HAVE_STRING_H. + +Mon Nov 23 18:44:00 1992 Paul Eggert (eggert@twinsun.com) + + * io.c (find_and_hash_each_line): When running out of lines, + double the number of allocated lines, instead of just doubling + that number minus the prefix lines. This is more likely to + avoid the need for further memory allocation. + +Wed Nov 18 20:40:28 1992 Paul Eggert (eggert@twinsun.com) + + * dir.c (dir_sort): Plug memory leak: space holding directory + contents was not being reclaimed. Get directory size from + struct file_data for initial guess at memory needed. + Detect errors when reading and closing directory. + (diff_dirs): Pass struct file_data to dir_sort. Finish plugging leak. + * diff.c (compare_files): Pass struct file_data to diff_dirs. + + * io.c (find_and_hash_each_line): Don't assume alloc_lines is + nonzero when allocating more lines. + +Thu Nov 12 16:02:18 1992 Paul Eggert (eggert@twinsun.com) + + * diff.c (main): Add `-U lines' as an alias for `--unified=lines'. + + * diff3.c (usage): Add third --label option in example. + + * util.c (analyze_hunk): Fix test for ignoring blank lines. + + * configure.in, system.h: Avoid USG; use HAVE_TIME_H etc. instead. + +Mon Nov 9 05:13:25 1992 Paul Eggert (eggert@twinsun.com) + + * diff3.c (main, usage): Add -A or --show-all. + -m now defaults to -A, not -E. Allow up to three -L options. + (output_diff3_edscript, output_diff3_merge): + Remove spurious differences between these two functions. + Output ||||||| for -A. Distinguish between conflicts and overlaps. + (dotlines, undotlines): New functions that output `Ns', not `N,Ns'. + (output_diff3_edscript, output_diff3_merge): Use them. + + * io.c (find_identical_ends): shift_boundaries needs an extra + identical line at the end, not at the beginning. + + * sdiff.c (edit): execvp wants char **, not const char **. + +Mon Oct 19 04:39:32 1992 Paul Eggert (eggert@twinsun.com) + + * context.c (print_context_script, find_function): Context + line numbers start with - file->prefix_lines, not 0. + + * io.c (binary_file_p): Undo last change; it was a library bug. + +Sun Oct 18 00:17:29 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * io.c (binary_file_p): Consider empty file as non-binary. + +Mon Oct 5 05:18:46 1992 Paul Eggert (eggert@twinsun.com) + + * diff3.c (main, make_3way_diff, using_to_diff3_block): Don't + report bogus differences (for one of -mexEX3) just because the + file0-file1 diffs don't line up with the file0-file2 diffs. + (This is entirely possible since we don't use diff's -n + option.) Always compare file1 to file2, so that diff3 sees + those changes directly. Typically, file2 is now the common + file, not file0. + (output_diff3_merge): The input file is file 0, not the common file. + + (FC, FO): New macros; they replace FILE1, FILE0 for two-way diffs, + to distinguish them from three-way diffs. + + * diff3.c (using_to_diff3_block): Fold repeated code into loops. + + * diff3.c (make_3way_diff, process_diff): Have the *_end + variable point to the next field to be changed, not to the last + object allocated; this saves an if-then-else. + + * diff3.c (process_diff): Use D_NUMLINES instead of its definiens. + + * diff3.c: Make fns and vars static unless they must be external. + +Wed Sep 30 09:21:59 1992 Paul Eggert (eggert@twinsun.com) + + * analyze.c (diff_2_files): OUTPUT_IFDEF is now robust. + * diff.h (ROBUST_OUTPUT_STYLE): Likewise. + (default_line_format): Remove. All refs removed. + + * ifdef.c (print_ifdef_lines): Add %L. Optimize %l\n even if user + specified it, as opposed to its being the default. + +Tue Sep 29 19:01:28 1992 Paul Eggert (eggert@twinsun.com) + + * diff.c (longopts, main): --{old,new,unchanged,changed}--group-format + are new options, so that -D is no longer overloaded. Set + no_diff_means_no_output if --unchanged-{line,group}-format allows it. + * diff.h (enum line_class): New type. + (group_format, line_format): Use it to regularize option flags. + All refs changed. + + * ifdef.c (format_ifdef, print_ifdef_lines): %n is no longer a format. + +Mon Sep 28 04:51:42 1992 Paul Eggert (eggert@twinsun.com) + + * diff.c (main, usage): Replace --line-prefix with the more general + --{old,new,unchanged}-line-format options. + * ifdef.c (format_ifdef, print_ifdef_lines): Likewise. + * diff.h (line_format): Renamed from line_prefix. All refs changed. + * diff.h, ifdef.c (default_line_format): New variable. + * util.c (output_1_line): New function. + (print_1_line): Use it. + + * ifdef.c: (format_ifdef, print_ifdef_lines): Add %0 format. + +Sun Sep 27 05:38:13 1992 Paul Eggert (eggert@twinsun.com) + + * diff.c (main): Add -E or --line-prefix option. Add -D'=xxx' + for common lines. Change default -D< format from copy of -D> + format to to -D<%<; similarly for default -D> format. + * diff.h (common_format, line_prefix): New variables. + * ifdef.c (format_ifdef): New function. + (print_ifdef_script, print_ifdef_hunk, print_ifdef_lines): + Use it for -D'=xxx', -E. + + * context.c (find_hunk): Glue together two non-ignorable changes that + are exactly CONTEXT * 2 lines apart. This shortens output, removes + a behavioral discontinuity at CONTEXT = 0, and is more compatible + with traditional diff. + + * io.c (find_identical_ends): Slurp stdin at most once. + + * util.c (print_line_line): line_flag is const char *. + +Thu Sep 24 15:18:07 1992 Paul Eggert (eggert@twinsun.com) + + * ifdef.c (print_ifdef_lines): New function, which fwrites a sequence + of lines all at once for speed. + (print_ifdef_script, print_ifdef_hunk): Use it. + +Thu Sep 24 05:54:14 1992 Paul Eggert (eggert@twinsun.com) + + * diff.c (main): Support new -D options for if-then-else formats. + (specify_format): New function. + * diff.h (ifndef_format, ifdef_format, ifnelse_format): New variables. + * ifdef.c (print_ifdef_hunk): Use the new variables instead of + a hardwired format. + + * side.c (print_1sdiff_line): Represent incomplete lines on output. + (print_sdiff_script): Likewise. Don't print 'q' at end, + since that doesn't work with incomplete lines. + * sdiff.c (interact): Don't assume diff output ends with 'q' line. + * diff.h (ROBUST_OUTPUT_STYLE): OUTPUT_SDIFF is now robust. + + * sdiff.c (lf_copy, lf_snarf): Use memchr instead of index, + to avoid dumping core when files contain null characters. + (memchr): New function (if memchr is missing). + + * io.c (sip): New arg SKIP_TEST to skip test for binary file. + (read_files): Don't bother testing second file if first is binary. + +Thu Sep 17 21:17:49 1992 David J. MacKenzie (djm@nutrimat.gnu.ai.mit.edu) + + * system.h [!USG && !_POSIX_VERSION]: Protect from conflicting + prototype for wait in sys/wait.h. + +Wed Sep 16 12:32:18 1992 David J. MacKenzie (djm@nutrimat.gnu.ai.mit.edu) + + * Makefile.in: Include binprefix in -DDIFF_PROGRAM. + +Tue Sep 15 14:27:25 1992 David J. MacKenzie (djm@nutrimat.gnu.ai.mit.edu) + + * Version 2.0. + +Sat Sep 12 01:31:19 1992 David J. MacKenzie (djm@nutrimat.gnu.ai.mit.edu) + + * util.c, diff.h, system.h [!HAVE_MEMCHR]: Don't use void * + and const when declaring memchr replacement. Declare memchr + if !STDC_HEADERS && !USG. + +Thu Sep 10 15:17:32 1992 David J. MacKenzie (djm@nutrimat.gnu.ai.mit.edu) + + * Makefile.in (uninstall): New target. + + * diff.c (excluded_filename): Use fnmatch, not wildmat. + (usage): Document -x, -X, --exclude, --exclude-from. + Makefile.in: Use fnmatch.c, not wildmat.c. + +Sun Sep 6 23:46:25 1992 Paul Eggert (eggert@twinsun.com) + + * configure.in: Add HAVE_MEMCHR. + * diff.h, util.c: Use it instead of MEMCHR_MISSING. + +Sun Sep 6 07:25:49 1992 Paul Eggert (eggert@twinsun.com) + + * diff.h: (struct line_def): Replace this 3-word struct with char *. + This uses less memory, particularly for large files with short lines. + (struct file_data): New member linbuf_base counts number of lines + in common prefix that are not recorded in linbuf; + this uses less memory if files are identical or differ only at end. + New member buffered_lines counts possibly differing lines. + New member valid_lines counts valid data. + New member alloc_lines - linbuf_base replaces old linbufsize. + linbuf[0] now always points at first differing line. + Remove unused members ltran, suffix_lines. + Add const where appropriate. + (Is_space): New macro, for consistent definition of `white space'. + (excluded_filename, memchr, sip, slurp): New declarations. + * ed.c (print_ed_hunk): Adjust to diff.h's struct changes. + * context.c (pr_context_hunk): Likewise. + * ifdef.c (print_ifdef_script): Likewise. + * side.c (print_sdiff_script, print_half_line): Likewise. + * util.c (analyze_hunk, line_cmp, print_1_line): Likewise. + + * analyze.c (shift_boundaries): Remove unneeded variable `end' and + unnecessary comparisons of `preceding' and `other_preceding' against 0. + (diff_2_files): When comparing files byte-by-byte for equality, + don't slurp them all in at once; just compare them a buffer at a time. + This can win big if they differ early on. + Move some code to compare_files to enable this change. + Use only one buffer for stdin with `diff - -'. + (discard_confusing_lines, diff_2_files): Coalesce malloc/free calls. + (build_script): Remove obsolete OUTPUT_RCS code. + + * diff.c (add_exclude, add_exclude_file, excluded_filename): New fns. + (main): Use them for the new --exclude and --exclude-from options. + (compare_files): Don't open a file unless it must be read. + Treat `diff file file' and `diff file dir' similarly. + Move some code here from diff_2_files to enable this. + Simplify file vs dir warning. + + * dir.c (dir_sort): Support new --exclude* options. + + * io.c (struct equivclass): Put hash code and line length here instead + of struct line_def, so that they can be shared. + (find_and_hash_each_line): Compute equivalence class as we go, + instead of doing it in a separate pass; this thrashes memory less. + Make buckets realloc-able, since we can't preallocate them. + Record one more line start than there are lines, so that we can compute + any line's length by subtracting its start from the next line's, + instead of storing the length explicitly. This saves memory. + Move prefix-handling code to find_identical_ends; + this wins with large prefixes. + Use Is_space, not is_space, for consistent treatment of white space. + (prepare_text_end): New function. + (find_identical_ends): Move slurping here, so it's only done when + needed. Work even if the buffers are the same (because of `diff - -'). + Compare prefixes a word at a time for speed. + (find_equiv_class): Delete; now done by find_and_hash_each_line. + (read_files): Don't slurp unless needed. + find_equiv_class's work is now folded into find_and_hash_each_line. + Don't copy stdin buffer if `diff - -'. + Check for running out of primes. + (sip, slurp): Split first part of `slurp' into another function `sip'. + `sip' sets things up and perhaps reads the first ST_BLKSIZE buffer to + see whether the file is binary; `slurp' now just finishes the job. + This lets diff_2_files compare binary files lazily. + Allocate a one-word sentinel to allow word-at-a-time prefix comparison. + Count prefix lines only if needed, only count the first file's prefix. + Don't bother to count suffix lines; it's never needed. + Set up linbuf[0] to point at first differing line. + (binary_file_p): Change test for binary files: + if it has a null byte in its first buffer, it's binary. + (primes): Add more primes. + + * util.c (line_cmp): Use bcmp for speed. + Use Is_space, not is_space, for consistent treatment of white space. + (translate_line_number): Internal line numbers now count from 0 + starting after the prefix. + (memchr): New function (if memchr is missing). + + * Makefile.in: Document HAVE_ST_BLKSIZE. Link with wildmat.o. + * system.h (STAT_BLOCKSIZE): New macro based on HAVE_ST_BLKSIZE. + * configure.in: Add AC_ST_BLKSIZE. + * wildmat.c: New file. + +Fri Sep 4 01:28:51 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * sdiff.c (xmalloc): Renamed from ck_malloc. Callers changed. + +Thu Sep 3 15:28:59 1992 David J. MacKenzie (djm@nutrimat.gnu.ai.mit.edu) + + * diff.h: Don't declare free, index, rindex. + +Tue Aug 11 22:18:06 1992 John Gilmore (gnu at cygnus.com) + + * io.c (binary_file_p): Use heuristic to avoid declaring info + files as binary files. Allow about 1.5% non-printing + characters (in info's case, ^_). + +Tue Jul 7 01:09:26 1992 David J. MacKenzie (djm@nutrimat.gnu.ai.mit.edu) + + * diff.h: Replace function_regexp and ignore_regexp with lists + of compiled regexps. + * analyze.c, context.c, util.c: Test whether the lists, not + the old variables, are empty. + * util.c (analyze_hunk), context.c (find_function): Compare + lines with the lists of regexps. + * diff.c (add_regexp): New function. + (main): Use it. + + * diff3: Add -v --version option. + * Makefile.in: Link with version.o. + + * system.h: New file. + * diff.h, cmp.c, diff3.c, sdiff.c: Use it. + + * diff.h, diff3.c: Include string.h or strings.h, as appropriate. + Declare malloc and realloc. + + * diff3.c (perror_with_exit): Include program name in message. + + * diff3.c: Lowercase error messages for GNU standards. + + * sdiff.c [USG || STDC_HEADERS]: Define bcopy in terms of memcpy. + + * sdiff.c: Use the version number from version.c. + * Makefile.in: Link with version.o. + + * cmp.c error.c xmalloc.c: New files from textutils. + * Makefile.in: Add rules for them. + + * diff.c (longopts): --unidirectional-new-file is like -P, not -N. + Rename --file-label to --label (leave old name, but undocumented). + + * sdiff.c, diff.c (usage): Condense messages and fix some errors. + + * diff3.c (main, usage): Add long-named options. + +Fri Jul 3 14:31:18 1992 David J. MacKenzie (djm@nutrimat.gnu.ai.mit.edu) + + * diff.h, diff3.c, sdiff.c: Change FOO_MISSING macros to HAVE_FOO. + +Thu Jun 25 16:59:47 1992 David J. MacKenzie (djm@apple-gunkies.gnu.ai.mit.edu) + + * diff.c: --reversed-ed -> --forward-ed. + +Wed Feb 26 12:17:32 1992 Paul Eggert (eggert@yata.uucp) + + * analyze.c, diff.c, diff.h, io.c: For -y, compare even if same file. + +Fri Feb 14 22:46:38 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * io.c, diff3.c, analyze.c: Add extra parentheses. + +Sun Feb 9 00:22:42 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * diff.h (unidirectional_new_file_flag): New variable. + * diff.c (main): Set that for -P. + (compare_files): Support -P, somewhat like -N. + (longopts): Support long name for -P. + +Sat Jan 4 20:10:34 1992 Paul Eggert (eggert at yata.uucp) + + * Makefile.in: Distribute diff.info-* too. + + * README, sdiff.c: version number now matches version.c. + + * configure: Fix and document vfork test. + + * ifdef.c: Don't dump core if `diff -Dx f f'. + +Mon Dec 23 23:36:08 1991 David J. MacKenzie (djm at wookumz.gnu.ai.mit.edu) + + * diff.h, diff3.c, sdiff.c: Change POSIX ifdefs to + HAVE_UNISTD_H and _POSIX_VERSION. + +Wed Dec 18 17:00:31 1991 David J. MacKenzie (djm at wookumz.gnu.ai.mit.edu) + + * Makefile.in (srcs): Add sdiff.c. + (tapefiles): Add diff.texi and diff.info. + + * diff.h, diff3.c, sdiff.c: Use HAVE_VFORK_H instead of + VFORK_HEADER and VFORK_WORKS. + +Tue Dec 17 00:02:59 1991 Paul Eggert (eggert at yata.uucp) + + * Makefile.in (all): Add diff.info, sdiff. + + * configure, diff.c, sdiff.c: + Prefix long options with `--', not `+'. + * diff.c: Regularize option names. + + * configure: Fix check for vfork. + * configure, diff.c, diff.h, diff3.c, sdiff.c: + Use Posix definitions when possible. + + * context.c: Align context with tab if -T is given. Tune. + * diff.c, diff.h, side.c: Calculate column widths so that tabs line up. + * io.c: Add distinction between white space and printing chars. + * side.c: Don't expand tabs unless -t is given. + * side.c, util.c: Tab expansion now knows about '\b', '\f', '\r', '\v'. + * util.c: -w skips all white space. Remove lint. Tune. + + * sdiff.c: Support many more diff options, e.g. `-', `sdiff file dir'. + Ignore interrupts while the subsidiary editor is in control. + Clean up temporary file and kill subsidiary diff if interrupted. + Ensure subsidiary diff doesn't ignore SIGPIPE. + Don't get confused while waiting for two subprocesses. + Don't let buffers overflow. Check for I/O errors. + Convert to GNU style. Tune. + + * sdiff.c, util.c: Don't lose errno. + Don't confuse sdiff with messages like `Binary files differ'. + * sdiff.c, side.c: Don't assume that common lines are identical. + Simplify --sdiff-merge-assist format. + +Mon Sep 16 16:42:01 1991 Tom Lord (lord at churchy.gnu.ai.mit.edu) + + * Makefile.in, sdiff.c: introduced sdiff front end to diff. + + * Makefile.in, analyze.c, diff.c, diff.h, io.c, side.c: Added + sdiff-style output format to diff. + +Mon Aug 26 16:44:55 1991 David J. MacKenzie (djm at pogo.gnu.ai.mit.edu) + + * Makefile.in, configure: Only put $< in Makefile if using VPATH, + because older makes don't understand it. + +Fri Aug 2 12:22:30 1991 David J. MacKenzie (djm at apple-gunkies) + + * configure: Create config.status. Remove it and Makefile if + interrupted while creating them. + +Thu Aug 1 22:24:31 1991 David J. MacKenzie (djm at apple-gunkies) + + * configure: Check for +srcdir etc. arg and look for + Makefile.in in that directory. Set VPATH if srcdir is not `.'. + * Makefile.in: Get rid of $(archpfx). + +Tue Jul 30 21:28:44 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu) + + * Makefile.in (prefix): Renamed from DESTDIR. + +Wed Jul 24 23:08:56 1991 David J. MacKenzie (djm at wookumz.gnu.ai.mit.edu) + + * diff.h, diff3.c: Rearrange ifdefs to use POSIX, + STDC_HEADERS, VFORK_MISSING, DIRENT. This way it works on + more systems that aren't pure USG or BSD. + Don't not define const if __GNUC__ is defined -- that would + break with -traditional. + * configure: Check for those features. + +Wed Jul 10 01:39:23 1991 David J. MacKenzie (djm at wookumz.gnu.ai.mit.edu) + + * configure, Makefile.in: $(INSTALLPROG) -> $(INSTALL). + +Sat Jul 6 16:39:04 1991 David J. MacKenzie (djm at geech.gnu.ai.mit.edu) + + * Replace Makefile with configure and Makefile.in. + Update README with current compilation instructions. + +Sat Jul 6 14:03:29 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu) + + * util.c (setup_output): Just save the args for later use. + (begin_output): Do the real work, with the values that were saved. + It's safe to call begin_output more than once. + Print the special headers for context format here. + * analyze.c (diff_2_files): Don't print special headers here. + * context.c (pr_context_hunk, pr_unidiff_hunk): Call begin_output. + * ed.c (print_ed_hunk, print_forward_ed_hunk, print_rcs_hunk): + * normal.c (print_normal_hunk): Likewise. + * ifdef.c (print_ifdef_hunk): Likewise. + * util.c (finish_output): Don't die if begin_output was not called. + +Thu Jun 20 23:10:01 1991 David J. MacKenzie (djm at geech.gnu.ai.mit.edu) + + * Makefile: Add TAGS, distclean, and realclean targets. + Set SHELL. + +Tue Apr 30 13:54:36 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu) + + * diff.h (TRUE, FALSE): Undefine these before defining. + +Thu Mar 14 18:27:27 1991 Richard Stallman (rms@mole.ai.mit.edu) + + * Makefile (objs): Include $(ALLOCA). + +Sat Mar 9 22:34:03 1991 Richard Stallman (rms at mole.ai.mit.edu) + + * diff.h: Include regex.h. + +Thu Feb 28 18:59:53 1991 Richard Stallman (rms at mole.ai.mit.edu) + + * Makefile (diff3): Link with GNU getopt. + +Sat Feb 23 12:49:43 1991 Richard Stallman (rms at mole.ai.mit.edu) + + * io.c (find_equiv_class): Make hash code unsigned before mod. + + * diff.h (files): Add EXTERN. + +Sun Jan 13 21:33:01 1991 Richard Stallman (rms at mole.ai.mit.edu) + + * diff.c: +print option renamed +paginate. Remove +all-text. + +Mon Jan 7 06:18:01 1991 David J. MacKenzie (djm at geech.ai.mit.edu) + + * Makefile (dist): New target, replacing diff.tar and + diff.tar.Z, to encode version number in distribution directory + and tar file names. + +Sun Jan 6 18:42:23 1991 Michael I Bushnell (mib at geech.ai.mit.edu) + + * Version 1.15 released. + + * version.c: Updated from 1.15 alpha to 1.15 + + * context.c (print_context_number_range, + print_unidiff_number_range): Don't print N,M when N=M, print + just N instead. + + * README: Updated for version 1.15. + Makefile: Updated for version 1.15. + + * diff3.c (main): Don't get confused if one of the arguments + is a directory. + + * diff.c (compare_files): Don't get confused if comparing + standard input to a directory; print error instead. + + * analyze.c (diff_2_files), context.c (print_context_header, + print_context_script), diff.c (main), diff.h (enum + output_style): Tread unidiff as an output style in its own + right. This also generates an error when both -u and -c are + given. + + * diff.c (main): Better error messages when regexps are bad. + + * diff.c (compare_files): Don't assume stdin is opened. + + * diff3.c (read_diff): Don't assume things about the order of + descriptor assignment and closes. + + * util.c (setup_output): Don't assume things about the order + of descriptor assignment and closes. + + * diff.c (compare_files): Set a flag so that closes don't + happen more than once. + + * diff.c (main): Don't just flush stdout, do a close. That + way on broken systems we can still get errors. + +Mon Dec 24 16:24:17 1990 Richard Stallman (rms at mole.ai.mit.edu) + + * diff.c (usage): Use = for args of long options. + +Mon Dec 17 18:19:20 1990 Michael I Bushnell (mib at geech.ai.mit.edu) + + * context.c (print_context_label): Labels were interchanged badly. + + * context.c (pr_unidiff_hunk): Changes to deal with files + ending in incomplete lines. + * util.c (print_1_line): Other half of the changes. + +Mon Dec 3 14:23:55 1990 Richard Stallman (rms at mole.ai.mit.edu) + + * diff.c (longopts, usage): unidiff => unified. + +Wed Nov 7 17:13:08 1990 Richard Stallman (rms at mole.ai.mit.edu) + + * analyze.c (diff_2_files): No warnings about newlines for -D. + + * diff.c (pr_unidiff_hunk): Remove ref to output_patch_flag. + +Tue Oct 23 23:19:18 1990 Richard Stallman (rms at mole.ai.mit.edu) + + * diff.c (compare_files): For -D, compare even args are same file. + * analyze.c (diff_2_files): Likewise. + Also, output even if files have no differences. + + * analyze.c (diff_2_files): Print missing newline messages last. + Return 2 if a newline is missing. + Print them even if files end with identical text. + +Mon Oct 22 19:40:09 1990 Richard Stallman (rms at mole.ai.mit.edu) + + * diff.c (usage): Return 2. + +Wed Oct 10 20:54:04 1990 Richard Stallman (rms at mole.ai.mit.edu) + + * diff.c (longopts): Add +new-files. + +Sun Sep 23 22:49:29 1990 Richard Stallman (rms at mole.ai.mit.edu) + + * context.c (print_context_script): Handle unidiff_flag. + (print_context_header): Likewise. + (print_unidiff_number_range, pr_unidiff_hunk): New functions. + * diff.c (longopts): Add element for +unidiff. + (main): Handle +unidiff and -u. + (usage): Mention them. + +Wed Sep 5 16:33:22 1990 Richard Stallman (rms at mole.ai.mit.edu) + + * io.c (find_and_hash_each_line): Deal with missing final newline + after buffering necessary context lines. + +Sat Sep 1 16:32:32 1990 Richard Stallman (rms at mole.ai.mit.edu) + + * io.c (find_identical_ends): ROBUST_OUTPUT_FORMAT test was backward. + +Thu Aug 23 17:17:20 1990 Richard Stallman (rms at mole.ai.mit.edu) + + * diff3.c (WIFEXITED): Undef it if WEXITSTATUS is not defined. + * context.c (find_function): Don't try to return values. + +Wed Aug 22 11:54:39 1990 Richard Stallman (rms at mole.ai.mit.edu) + + * diff.h (O_RDONLY): Define if not defined. + +Tue Aug 21 13:49:26 1990 Richard Stallman (rms at mole.ai.mit.edu) + + * Handle -L option. + * context.c (print_context_label): New function. + (print_context_header): Use that. + * diff.c (main): Recognize the option. + (usage): Updated. + * diff.h (file_label): New variable. + * diff3.c (main): Recognize -L instead of -t. + + * diff3.c (main): Support -m without other option. + + * diff3.c (WEXITSTATUS, WIFEXITED): Define whenever not defined. + + * diff3.c (bcopy, index, rindex): Delete definitions; not used. + (D_LINENUM, D_LINELEN): Likewise. + (struct diff_block): lengths includes newlines. + (struct diff3_block): Likewise. + (always_text, merge): New variables. + (read_diff): Return address of end, not size read. Calls changed. + Pass -a to diff if given to diff3. + current_chunk_size now an int. Detect error in `pipe'. + Check for incomplete line of output here. + (scan_diff_line): Don't make scan_ptr + 2 before knowing it is valid. + No need to check validity of diff output here. + Include newline in length of line. + (main): Compute rev_mapping here. Handle -a and -m. + Error message if excess -t operands. Error for incompatible options. + Error if `-' given more than once. + Fix error storing in tag_strings. + (output_diff3): REV_MAPPING is now an arg. Call changed. + Change syntax of "missing newline" message. + Expect length of line to include newline. + (output_diff3_edscript): Return just 0 or 1. + REV_MAPPING is now an arg. Call changed. + (output_diff3_merge): New function. + (process_diff): Better error message for bad diff format. + (fatal, perror_with_exit): Return status 2. + + * analyze.c (diff_2_files): Report missing newline in either + or both files, if not robust output style. + + * util.c (setup_output): Detect error from pipe. + No need to close stdin. + + * util.c (print_1_line): Change format of missing-newline msg. + Change if statements to switch. + + * io.c (slurp): Don't mention differences in final newline if -B. + + * io.c (binary_file_p): Use ISO char set as criterion, not ASCII. + + * io.c (find_identical_ends): Increase value of BEG0 by 1. + Other changes in backwards scan to avoid decrementing pointers + before start of array, and set LINES properly. + + * diff.h (ROBUST_OUTPUT_STYLE): New macro. + * io.c (find_identical_ends, find_and_hash_each_line): Use that macro. + + * diff.h (dup2): Don't define if XENIX. + + * diff.c (main): Check for write error at end. + + * context.c (find_function): Don't return a value. + Use argument FILE rather than global files. + + * analyze.c: Add external function declarations. + * analyze.c (build_script): Turn off explicit check for final newline. + + * analyze.c (discard_confusing_lines): Make integers unsigned. + +Tue Jul 31 21:37:16 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * io.c (find_and_hash_each_line): Correct the criterion + for leaving out the newline from the end of the line. + +Tue May 29 21:28:16 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * dir.c (diff_dirs): Free things only if nonzero. + +Mon Apr 16 18:31:05 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * diff.h (NDIR_IN_SYS): New macro controls location of ndir.h. + + * diff3.c (xmalloc, xrealloc): Don't die if size == 0 returns 0. + +Sun Mar 25 15:58:42 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * analyze.c (discard_confusing_lines): + `many' wasn't being used; use it. + Canceling provisionals near start of run must handle already + canceled provisionals. + Canceling subruns of provisionals was canceling last nonprovisional. + +Sat Mar 24 14:02:51 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * analyze.c (discard_confusing_lines): + Threshold for line occurring many times scales by square root + of total lines. + Within each run, cancel any long subrun of provisionals. + Don't update `provisional' while canceling provisionals. + In big outer loop, handle provisional and nonprovisional separately. + +Thu Mar 22 16:35:33 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * analyze.c (discard_confusing_lines): + The first loops to discard provisionals from ends failed to step. + In second such loops, keep discarding all consecutive provisionals. + Increase threshold for stopping discarding, and also check for + consecutive nondiscardables as separate threshold. + +Fri Mar 16 00:33:08 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * diff3.c (read_diff): Pass -- as first arg to diff. + + * diff3.c: Include wait.h or define equivalent macros. + (read_diff): Don't use stdio printing error in the inferior. + Remember the pid and wait for it. Report failing status. + Report failure of vfork. + +Sun Mar 11 17:10:32 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * diff3.c (main): Accept -t options and pass to output_diff3_edscript. + (usage): Mention -t. + (read_diff): Use vfork. + (vfork): Don't use it on Sparc. + + * diff.h (vfork): Don't use it on Sparc. + +Tue Mar 6 22:37:20 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * diff3.c (dup2): Don't define on Xenix. + + * Makefile: Comments for Xenix. + +Thu Mar 1 17:19:23 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * analyze.c (diff_2_files): `message' requires three args. + +Fri Feb 23 10:56:50 1990 David J. MacKenzie (djm at albert.ai.mit.edu) + + * diff.h, util.c, diff3.c: Change 'void *' to 'VOID *', with + VOID defined as void if __STDC__, char if not. + +Sun Feb 18 20:31:58 1990 David J. MacKenzie (djm at albert.ai.mit.edu) + + * Makefile: Add rules for getopt.c, getopt1.c, getopt.h. + + * getopt.c, getopt.h, getopt1.c: New files. + + * main.c (main, usage): Add long options. + + * analyze.c (shift_boundaries): Remove unused var 'j_end'. + +Thu Feb 8 02:43:16 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu) + + * GNUmakefile: include ../Makerules before Makefile. + +Fri Feb 2 23:21:38 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * analyze.c (diff_2_files): If -B or -I, don't return 1 + if all changes were ignored. + +Wed Jan 24 20:43:57 1990 Richard Stallman (rms at albert.ai.mit.edu) + + * diff3.c (fatal): Output to stderr. + +Thu Jan 11 00:25:56 1990 David J. MacKenzie (djm at hobbes.ai.mit.edu) + + * diff.c (usage): Mention -v. + +Wed Jan 10 16:06:38 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * diff3.c (output_diff3_edscript): Return number of overlaps. + (main): If have overlaps, exit with status 1. + +Sun Dec 24 10:29:20 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * io.c (find_equiv_class): Fix typo that came from changing init of B + to an assignment. + + * version.c: New file. + * diff.c (main): -v prints version number. + + * io.c (binary_file_p): Null char implies binary file. + +Fri Nov 17 23:44:55 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * util.c (print_1_line): Fix off by 1 error. + +Thu Nov 16 13:51:10 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * util.c (xcalloc): Function deleted. + + * io.c (slurp): Null-terminate the buffer. + + * io.c (read_files): Delete unused vars. + + * io.c (find_equiv_class): Don't index by N if too low. + + * dir.c (dir_sort): Delete the extra declaration of compare_names. + + * diff.h: Don't declare xcalloc. Declare some other functions. + + * analyze.c (shift_boundaries): + Test for END at end of range before indexing by it. + Fix misspelling of `preceding' in var names. + +Sat Nov 11 14:04:16 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * diff3.c (using_to_diff3_block): Delete unused vars. + (make_3way_diff, process_diff_control, read_diff, output_diff3): Likewise. + +Mon Nov 6 18:15:50 EST 1989 Jay Fenlason (hack@ai.mit.edu) + + * README Fix typo. + +Fri Nov 3 15:27:47 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * diff.c (usage): Mention -D. + + * ifdef.c (print_ifdef_hunk): Write comments on #else and #endif. + +Sun Oct 29 16:41:07 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * diff.c (compare_files): Don't fflush for identical files. + +Wed Oct 25 17:57:12 1989 Randy Smith (randy at apple-gunkies.ai.mit.edu) + + * diff3.c (using_to_diff3_block): When defaulting lines from + FILE0, only copy up to just under the *lowest* line mentioned + in the next diff. + + * diff3.c (fatal): Add \n to error messages. + +Wed Oct 25 15:05:49 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * Makefile (tapefiles): Add ChangeLog. + +Tue Oct 3 00:51:17 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * diff3.c (process_diff, create_diff3_block): Init ->next field. + +Fri Sep 29 08:16:45 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * util.c (line_cmp): Alter end char of line 2, not line 1. + +Wed Sep 20 00:12:37 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * Makefile (diff.tar): Expect ln to fail on some files; + copy them with cp. + +Mon Sep 18 02:54:29 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * Handle -D option: + * io.c (find_and_hash_each_line): Keep all lines of 1st file. + * diff.c (main): Handle -D option. + (compare_files): Reject -D if files spec'd are directories. + * analyze.c (diff_2_files): Handle OUTPUT_IFDEF case. + +Fri Sep 1 20:15:50 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * diff.c (option_list): Rename arg VECTOR as OPTIONVEC. + +Mon Aug 28 17:58:27 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * diff.c (compare_files): Clear entire inf[i].stat. + +Wed Aug 23 17:48:47 1989 Richard Stallman (rms at apple-gunkies.ai.mit.edu) + + * io.c (find_identical_ends): Sign was backward + determining where to bound the scan for the suffix. + +Wed Aug 16 12:49:16 1989 Richard Stallman (rms at hobbes.ai.mit.edu) + + * analyze.c (diff_2_files): If -q, treat all files as binary. + * diff.c (main): Detect -q, record in no_details_flag. + +Sun Jul 30 23:12:00 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * diff.c (usage): New function. + (main): Call it. + +Wed Jul 26 02:02:19 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * diff.c (main): Make -C imply -c. + +Thu Jul 20 17:57:51 1989 Chris Hanson (cph at kleph) + + * io.c (find_and_hash_each_line): Bug fix in context handling, + introduced by last change. + +Fri Jul 14 17:39:20 1989 Chris Hanson (cph at kleph) + + * analyze.c: To make RCS work correctly on files that don't + necessarily end in newline, introduce some changes that cause + diffs to be sensitive to missing final newline. Because + non-RCS modes don't want to be affected by these changes, they + are conditional on `output_style == OUTPUT_RCS'. + (diff_2_files) [OUTPUT_RCS]: Suppress the "File X missing + newline" message. + (build_script) [OUTPUT_RCS]: Cause the last line to compare as + different if exactly one of the files is missing its final + newline. + + * io.c (find_and_hash_each_line): Bug fix in + ignore_space_change mode. Change line's length to include the + newline. For OUTPUT_RCS, decrement last line's length if + there is no final newline. + (find_identical_ends) [OUTPUT_RCS]: If one of the files is + missing a final newline, make sure it's not included in either + the prefix or suffix. + + * util.c (print_1_line): Change line output routine to account + for line length including the newline. + +Tue Jun 27 02:35:28 1989 Roland McGrath (roland at hobbes.ai.mit.edu) + + * Makefile: Inserted $(archpfx) where appropriate. + +Wed May 17 20:18:43 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * diff3.c [USG]: Include fcntl.h. + + * diff.h [USG]: New compilation flags HAVE_NDIR, HAVE_DIRECT. + +Wed Apr 26 15:35:57 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * dir.c (diff_dirs): Two new args, NONEX1 and NONEX2, say to pretend + nonex dirs are empty. + (dir_sort): New arg NONEX, likewise. + * diff.c (compare_files): Pass those args. + Sometimes call diff_dirs if subdir exists in just one place. + +Wed Apr 12 01:10:27 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * io.c (find_identical_ends): Set END0 *after* last char + during backward scan for suffix. + +Sat Apr 8 15:49:49 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu) + + * diff3.c (using_to_diff3_block): Now find high marks in files 1 + and 2 through mapping off of the last difference instead of the + first. + + * diff3.c: Many trivial changes to spelling inside comments. + +Fri Feb 24 12:38:03 1989 Randall Smith (randy at gluteus.ai.mit.edu) + + * util.c, normal.c, io.c, ed.c, dir.c, diff.h, diff.c, context.c, + analyze.c, Makefile: Changed copyright header to conform with new + GNU General Public license. + * diff3.c: Changed copyright header to conform with new GNU + General Public license. + * COPYING: Made a hard link to /gp/rms/COPYING. + +Fri Feb 24 10:01:58 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * io.c (slurp): Leave 2 chars space at end of buffer, not one. + (find_identical_ends): Special case if either file is empty; + don't try to make a sentinel since could crash. + +Wed Feb 15 14:24:48 1989 Jay Fenlason (hack at apple-gunkies.ai.mit.edu) + + * diff3.c (message) Re-wrote routine to avoid using alloca() + +Wed Feb 15 06:19:14 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * io.c (find_identical_ends): Delete the variable `bytes'. + +Sun Feb 12 11:50:36 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * io.c (slurp): ->bufsize is nominal amount we have room for; + add room for sentinel when calling xmalloc or xrealloc. + + * io.c (find_identical_ends): Do need overrun check in finding suffix. + +Fri Feb 10 01:28:15 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * diff.c (main): -C now takes arg to specify context length. + Now -p to show C function name--Damned IEEE! + Fatal error if context length spec'd twice. + + * ed.c (print_ed_hunk): Now special treatment only for lines containing + precisely a dot and nothing else. Output `..', end the insert, + substitute that one line, then resume the insert if nec. + + * io.c (find_and_hash_lines): When backing up over starting context, + don't move past buffer-beg. + + * io.c (find_identical_ends): Use sentinels to make the loops faster. + If files are identical, skip the 2nd loop and return quickly. + (slurp): Leave 1 char extra space after each buffer. + + * analyze.c (diff_2_files): Mention difference in final newlines. + +Wed Jan 25 22:44:44 1989 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * dir.c (diff_dirs): Use * when calling fcn ptr variable. + +Sat Dec 17 14:12:06 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * Makefile: New vars INSTALL and LIBS used in some rules; + provide default defns plus commented-put defns for sysV. + +Thu Nov 17 16:42:53 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * dir.c (dir_sort): Open-trouble not fatal; just say # files is -1. + (diff_dirs): If dir_sort does that, give up and return 2. + + * diff.c (compare_files): Don't open directories. + Don't close them specially either. + Cross-propagate inf[i].dir_p sooner. + +Sun Nov 13 11:19:36 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu) + + * diff.h: Declare index, rindex. + + * diff.c (compare_files): If comparing foodir with b/f, + use foodir/f, not foodir/b/f. + + * diff.c (compare_files): Don't print "are identical" msg for 2 dirs. + Status now 1 if one file is a dir and the other isn't, etc. + +Thu Nov 3 16:30:24 1988 Randall Smith (randy at gluteus.ai.mit.edu) + + * Makefile: Added a define for diff3 to define DIFF_PROGRAM. + + * util.c: Added hack to make sure that perror was not called with + a null pointer. + + * diff.c: Changed S_IFDIR to S_IFMT in masking type of file bits + out. + + * diff3.c: Included USG compatibility defines. + + * diff.h: Moved sys/file.h into #else USG section (not needed or + wanted on System V). + + * ed.c, analyze.c, context.c: Shortened names to 12 characters for + the sake of System V (too simple not to do). + + +Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1997, 1998, 1999, +2000, 2001, 2002 Free Software Foundation, Inc. + +This file is part of GNU Diffutils. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that they will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. diff --git a/contrib/diffutils-2.8/NEWS b/contrib/diffutils-2.8/NEWS new file mode 100644 index 0000000000..3854f8b5e8 --- /dev/null +++ b/contrib/diffutils-2.8/NEWS @@ -0,0 +1,244 @@ +Version 2.8.7 contains no user-visible changes. + +User-visible changes in version 2.8.6: + +* New diff3 option --strip-trailing-cr. + +* With -N and -P, inaccessible empty regular files (the kind of files + that 'patch' creates to indicate nonexistent backups) are now + treated as nonexistent when they are in the 'backup' file position. + +* If multiple SKIP values are given to cmp, e.g., `cmp -i 10 -i 20', + cmp now uses the maximal value instead of the last one. + +* diff now omits the ".000000000" on hosts that do not support + fractional time stamps. + +Version 2.8.5 was not publicly released. + +User-visible changes in version 2.8.4: + +* Diff now simply prints "Files A and B differ" instead of "Binary + files A and B differ". The message is output if either A or B + appears to be a binary file, and the old wording was misleading + because it implied that both files are binary, which is not + necessarily the case. + +User-visible changes in version 2.8.3: + +* New locale: en_US. + +User-visible changes in version 2.8.2: + +* New diff and sdiff option: + --tabsize=COLUMNS +* If --ignore-space-change or --ignore-all-space is also specified, + --ignore-blank-lines now considers lines to be empty if they contain + only white space. +* More platforms now handle multibyte characters correctly when + excluding files by name (diff -x and -X). +* New locales: hu, pt_BR. + +User-visible changes in version 2.8.1: + +* Documentation fixes. + +User-visible changes in version 2.8: + +* cmp and diff now conform to POSIX 1003.1-2001 (IEEE Std 1003.1-2001) + if the underlying system conforms to POSIX and if the _POSIX2_VERSION + environment variable is set to 200112. Conformance removes support + for `diff -NUM', where NUM is a number. Use -C NUM or -U NUM instead. +* cmp now supports trailing operands SKIP1 and SKIP2, like BSD cmp. +* cmp -i or --ignore-initial now accepts SKIP1:SKIP2 option value. +* New cmp option: -n or --bytes. +* cmp's old -c or --print-chars option has been renamed; + use -b or --print-bytes instead. +* cmp now outputs "byte" rather than "char" outside the POSIX locale. +* cmp -l's index column width now adjusts to fit larger (or smaller) files. +* cmp -l -s and cmp -s -l are not allowed. Use cmp -s or cmp -l instead. +* diff uses ISO 8601 style time stamps for output times (e.g. "2001-11-23 + 16:44:36.875702460 -0800") unless in the C or POSIX locale and the + -c style is specified. +* diff's -I and -F options use the regexp syntax of grep, not of Emacs. +* diff now accepts multiple context arguments, and uses their maximum value. +* New diff and sdiff options: + -E --ignore-tab-expansion + --strip-trailing-cr +* New diff options: + --from-file=FILE, --to-file=FILE + --ignore-file-name-case + --no-ignore-file-name-case +* New diff3 and sdiff option: + --diff-program=PROGRAM +* The following diff options are still accepted, but are no longer documented. + They may be withdrawn in future releases. + -h (omit; it has no effect) + -H (use --speed-large-files instead) + -L (use --label instead) + -P (use --unidirectional-new-file instead) + --inhibit-hunk-merge (omit; it has no effect) +* Recursive diffs now sort file names according to the LC_COLLATE locale + category if possible, instead of using native byte comparison. +* Recursive diffs now detect and report directory loops. +* Diff printf specs can now use the "0" and "'" flags. +* The new sdiff interactive command `ed' precedes each version with a header. +* On 64-bit hosts, files larger than 2 GB can be compared. +* Some internationalization support has been added, but multibyte locales + are still not completely supported yet. +* Some diagnostics have been reworded slightly for consistency. + Also, `diff -D FOO' now outputs `/* ! FOO */' instead of `/* not FOO */'. +* The `patch' part of the manual now describes `patch' version 2.5.4. +* Man pages are now distributed and installed. +* There is support for DJGPP; see the 'ms' subdirectory and the files + m4/dos.m4 and */setmode.*. + + +User-visible changes in version 2.7: + +* New diff option: --binary (useful only on non-POSIX hosts) +* diff -b and -w now ignore line incompleteness; -B no longer does this. +* cmp -c now uses locale to decide which output characters to quote. +* Help and version messages are reorganized. + + +User-visible changes in version 2.6: + +* New cmp, diff, diff3, sdiff option: --help +* A new heuristic for diff greatly reduces the time needed to compare + large input files that contain many differences. +* Partly as a result, GNU diff's output is not exactly the same as before. + Usually it is a bit smaller, but sometimes it is a bit larger. + + +User-visible changes in version 2.5: + +* New cmp option: -v --version + + +User-visible changes in version 2.4: + +* New cmp option: --ignore-initial=BYTES +* New diff3 option: -T --initial-tab +* New diff option: --line-format=FORMAT +* New diff group format specifications: + [eflmnEFLMN] + A printf spec followed by one of the following letters + causes the integer corresponding to that letter to be + printed according to the printf specification. + E.g. `%5df' prints the number of the first line in the + group in the old file using the "%5d" format. + e: line number just before the group in old file; equals f - 1 + f: first line number in group in the old file + l: last line number in group in the old file + m: line number just after the group in old file; equals l + 1 + n: number of lines in group in the old file; equals l - f + 1 + E, F, L, M, N: likewise, for lines in the new file + %(A=B?T:E) + If A equals B then T else E. A and B are each either a decimal + constant or a single letter interpreted as above. T and E are + arbitrary format strings. This format spec is equivalent to T if + A's value equals B's; otherwise it is equivalent to E. For + example, `%(N=0?no:%dN) line%(N=1?:s)' is equivalent to `no lines' + if N (the number of lines in the group in the the new file) is 0, + to `1 line' if N is 1, and to `%dN lines' otherwise. + %c'C' + where C is a single character, stands for the character C. C may not + be a backslash or an apostrophe. E.g. %c':' stands for a colon. + %c'\O' + where O is a string of 1, 2, or 3 octal digits, stands for the + character with octal code O. E.g. %c'\0' stands for a null character. +* New diff line format specifications: + n + The line number, printed with . + E.g. `%5dn' prints the line number with a "%5d" format. + %c'C' + %c'\O' + The character C, or with octal code O, as above. +* Supported s have the same meaning as with printf, but must + match the extended regular expression %-*[0-9]*(\.[0-9]*)?[doxX]. +* The format spec %0 introduced in version 2.1 has been removed, since it + is incompatible with printf specs like %02d. To represent a null char, + use %c'\0' instead. +* cmp and diff now conform to POSIX 1003.2-1992 (ISO/IEC 9945-2:1993) + if the underlying system conforms to POSIX: + - Some messages' wordings are changed in minor ways. + - ``White space'' is now whatever C's `isspace' says it is. + - When comparing directories, if `diff' finds a file that is not a regular + file or a directory, it reports the file's type instead of diffing it. + (As usual, it follows symbolic links first.) + - When signaled, sdiff exits with the signal's status, not with status 2. +* Now portable to hosts where int, long, pointer, etc. are not all the same + size. +* `cmp - -' now works like `diff - -'. + + +User-visible changes in version 2.3: + +* New diff option: --horizon-lines=lines + + +User-visible changes in version 2.1: + +* New diff options: + --{old,new,unchanged}-line-format='format' + --{old,new,unchanged,changed}-group-format='format' + -U +* New diff3 option: + -A --show-all +* diff3 -m now defaults to -A, not -E. +* diff3 now takes up to three -L or --label options, not just two. + If just two options are given, they refer to the first two input files, + not the first and third input files. +* sdiff and diff -y handle incomplete lines. + + +User-visible changes in version 2.0: + +* Add sdiff and cmp programs. +* Add Texinfo documentation. +* Add configure script. +* Improve diff performance. +* New diff options: +-x --exclude +-X --exclude-from +-P --unidirectional-new-file +-W --width +-y --side-by-side +--left-column +--sdiff-merge-assist +--suppress-common-lines +* diff options renamed: +--label renamed from --file-label +--forward-ed renamed from --reversed-ed +--paginate renamed from --print +--entire-new-file renamed from --entire-new-files +--new-file renamed from --new-files +--all-text removed +* New diff3 options: +-v --version +* Add long-named equivalents for other diff3 options. +* diff options -F (--show-function-line) and -I (--ignore-matching-lines) + can now be given more than once. + + + +Copyright (C) 1993, 1994, 1998, 2001, 2002, 2004 Free Software +Foundation, Inc. + +This file is part of GNU Diffutils. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that they will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. diff --git a/contrib/diffutils-2.8/README b/contrib/diffutils-2.8/README new file mode 100644 index 0000000000..0c3723022a --- /dev/null +++ b/contrib/diffutils-2.8/README @@ -0,0 +1,69 @@ +README for GNU DIFF + +This directory contains the GNU diff, diff3, sdiff, and cmp utilities. +Their features are a superset of the Unix features and they are +significantly faster. + +Please see the file COPYING for copying conditions. + +Please see the file doc/version.texi for version information. + +Please see the file doc/diff.texi (or doc/diff.info) for documentation +that can be printed with TeX, or read with the `info' program or with +Emacs's `M-x info'. Brief man pages are in man/*, but they are no +substitute for the documentation. + +Please see the file ABOUT-NLS for notes about translations. + +Please see the file INSTALL for generic compilation and installation +instructions. Briefly, you can run "./configure; make install". The +command "./configure --help" lists the supported --enable and --with +options. + +If you have a problem with internationalization, you might be able to +work around it as described in ABOUT-NLS by invoking `./configure +--disable-nls'. Many of the problems arise from dynamic linking +issues on non-GNU platforms (e.g. with the iconv library). Such +problems tend to be shared by other GNU applications on these +platforms, and can usually be fixed by carefully tweaking your non-GNU +installation. If you have an older version of libiconv, please +upgrade to the latest one; see . If +the problem seems isolated to diffutils, though, please report a bug. + +This program requires a Standard C compiler (C89 or later). If you +have a nonstandard compiler, please install GCC first. + +If you make changes to the source code, you may need appropriate +versions of GNU build tools to regenerate the intermediate files. The +following versions were used to generate the intermediate files in +this distribution: + +* Autoconf 2.59 +* Automake 1.8.3 +* gettext 0.14.1 +* help2man 1.33 +* Texinfo 4.7 + +Please report bugs to . + +----- + +Copyright (C) 1992, 1998, 2001, 2002, 2004 Free Software Foundation, +Inc. + +This file is part of GNU Diffutils. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. diff --git a/contrib/diffutils-2.8/doc/diff.info b/contrib/diffutils-2.8/doc/diff.info new file mode 100644 index 0000000000..ca363455f3 --- /dev/null +++ b/contrib/diffutils-2.8/doc/diff.info @@ -0,0 +1,5223 @@ +This is diff.info, produced by makeinfo version 4.7 from diff.texi. + + This manual is for GNU Diffutils (version 2.8.7, 12 April 2004), and +documents the GNU `diff', `diff3', `sdiff', and `cmp' commands for +showing the differences between files and the GNU `patch' command for +using their output to update files. + + Copyright (C) 1992, 1993, 1994, 1998, 2001, 2002, 2004 Free Software +Foundation, Inc. + + Permission is granted to copy, distribute and/or modify this + document under the terms of the GNU Free Documentation License, + Version 1.1 or any later version published by the Free Software + Foundation; with no Invariant Sections, with the Front-Cover texts + being "A GNU Manual," and with the Back-Cover Texts as in (a) + below. A copy of the license is included in the section entitled + "GNU Free Documentation License." + + (a) The FSF's Back-Cover Text is: "You have freedom to copy and + modify this GNU Manual, like GNU software. Copies published by + the Free Software Foundation raise funds for GNU development." + +INFO-DIR-SECTION Individual utilities +START-INFO-DIR-ENTRY +* cmp: (diff)Invoking cmp. Compare 2 files byte by byte. +* diff: (diff)Invoking diff. Compare 2 files line by line. +* diff3: (diff)Invoking diff3. Compare 3 files line by line. +* patch: (diff)Invoking patch. Apply a patch to a file. +* sdiff: (diff)Invoking sdiff. Merge 2 files side-by-side. +END-INFO-DIR-ENTRY + +INFO-DIR-SECTION Text creation and manipulation +START-INFO-DIR-ENTRY +* Diff: (diff). Comparing and merging files. +END-INFO-DIR-ENTRY + + +File: diff.info, Node: Top, Next: Overview, Up: (dir) + +Comparing and Merging Files +*************************** + +This manual is for GNU Diffutils (version 2.8.7, 12 April 2004), and +documents the GNU `diff', `diff3', `sdiff', and `cmp' commands for +showing the differences between files and the GNU `patch' command for +using their output to update files. + + Copyright (C) 1992, 1993, 1994, 1998, 2001, 2002, 2004 Free Software +Foundation, Inc. + + Permission is granted to copy, distribute and/or modify this + document under the terms of the GNU Free Documentation License, + Version 1.1 or any later version published by the Free Software + Foundation; with no Invariant Sections, with the Front-Cover texts + being "A GNU Manual," and with the Back-Cover Texts as in (a) + below. A copy of the license is included in the section entitled + "GNU Free Documentation License." + + (a) The FSF's Back-Cover Text is: "You have freedom to copy and + modify this GNU Manual, like GNU software. Copies published by + the Free Software Foundation raise funds for GNU development." + +* Menu: + +* Overview:: Preliminary information. +* Comparison:: What file comparison means. + +* Output Formats:: Formats for two-way difference reports. +* Incomplete Lines:: Lines that lack trailing newlines. +* Comparing Directories:: Comparing files and directories. +* Adjusting Output:: Making `diff' output prettier. +* diff Performance:: Making `diff' smarter or faster. + +* Comparing Three Files:: Formats for three-way difference reports. +* diff3 Merging:: Merging from a common ancestor. + +* Interactive Merging:: Interactive merging with `sdiff'. + +* Merging with patch:: Using `patch' to change old files into new ones. +* Making Patches:: Tips for making and using patch distributions. + +* Invoking cmp:: Compare two files byte by byte. +* Invoking diff:: Compare two files line by line. +* Invoking diff3:: Compare three files line by line. +* Invoking patch:: Apply a diff file to an original. +* Invoking sdiff:: Side-by-side merge of file differences. + +* Standards conformance:: Conformance to the POSIX standard. +* Projects:: If you've found a bug or other shortcoming. + +* Copying This Manual:: How to make copies of this manual. +* Translations:: Available translations of this manual. +* Index:: Index. + + +File: diff.info, Node: Overview, Next: Comparison, Prev: Top, Up: Top + +Overview +******** + +Computer users often find occasion to ask how two files differ. Perhaps +one file is a newer version of the other file. Or maybe the two files +started out as identical copies but were changed by different people. + + You can use the `diff' command to show differences between two +files, or each corresponding file in two directories. `diff' outputs +differences between files line by line in any of several formats, +selectable by command line options. This set of differences is often +called a "diff" or "patch". For files that are identical, `diff' +normally produces no output; for binary (non-text) files, `diff' +normally reports only that they are different. + + You can use the `cmp' command to show the byte and line numbers +where two files differ. `cmp' can also show all the bytes that differ +between the two files, side by side. A way to compare two files +character by character is the Emacs command `M-x compare-windows'. +*Note Other Window: (emacs)Other Window, for more information on that +command. + + You can use the `diff3' command to show differences among three +files. When two people have made independent changes to a common +original, `diff3' can report the differences between the original and +the two changed versions, and can produce a merged file that contains +both persons' changes together with warnings about conflicts. + + You can use the `sdiff' command to merge two files interactively. + + You can use the set of differences produced by `diff' to distribute +updates to text files (such as program source code) to other people. +This method is especially useful when the differences are small compared +to the complete files. Given `diff' output, you can use the `patch' +program to update, or "patch", a copy of the file. If you think of +`diff' as subtracting one file from another to produce their +difference, you can think of `patch' as adding the difference to one +file to reproduce the other. + + This manual first concentrates on making diffs, and later shows how +to use diffs to update files. + + GNU `diff' was written by Paul Eggert, Mike Haertel, David Hayes, +Richard Stallman, and Len Tower. Wayne Davison designed and +implemented the unified output format. The basic algorithm is described +by Eugene W. Myers in "An O(ND) Difference Algorithm and its +Variations", `Algorithmica' Vol. 1 No. 2, 1986, pp. 251-266; and in "A +File Comparison Program", Webb Miller and Eugene W. Myers, +`Software--Practice and Experience' Vol. 15 No. 11, 1985, pp. 1025-1040. +The algorithm was independently discovered as described by E. Ukkonen in +"Algorithms for Approximate String Matching", `Information and Control' +Vol. 64, 1985, pp. 100-118. Unless the `--minimal' option is used, +`diff' uses a heuristic by Paul Eggert that limits the cost to O(N^1.5 +log N) at the price of producing suboptimal output for large inputs +with many differences. Related algorithms are surveyed by Alfred V. +Aho in section 6.3 of "Algorithms for Finding Patterns in Strings", +`Handbook of Theoretical Computer Science' (Jan Van Leeuwen, ed.), Vol. +A, `Algorithms and Complexity', Elsevier/MIT Press, 1990, pp. 255-300. + + GNU `diff3' was written by Randy Smith. GNU `sdiff' was written by +Thomas Lord. GNU `cmp' was written by Torbjo"rn Granlund and David +MacKenzie. + + GNU `patch' was written mainly by Larry Wall and Paul Eggert; +several GNU enhancements were contributed by Wayne Davison and David +MacKenzie. Parts of this manual are adapted from a manual page written +by Larry Wall, with his permission. + + +File: diff.info, Node: Comparison, Next: Output Formats, Prev: Overview, Up: Top + +1 What Comparison Means +*********************** + +There are several ways to think about the differences between two files. +One way to think of the differences is as a series of lines that were +deleted from, inserted in, or changed in one file to produce the other +file. `diff' compares two files line by line, finds groups of lines +that differ, and reports each group of differing lines. It can report +the differing lines in several formats, which have different purposes. + + GNU `diff' can show whether files are different without detailing +the differences. It also provides ways to suppress certain kinds of +differences that are not important to you. Most commonly, such +differences are changes in the amount of white space between words or +lines. `diff' also provides ways to suppress differences in alphabetic +case or in lines that match a regular expression that you provide. +These options can accumulate; for example, you can ignore changes in +both white space and alphabetic case. + + Another way to think of the differences between two files is as a +sequence of pairs of bytes that can be either identical or different. +`cmp' reports the differences between two files byte by byte, instead +of line by line. As a result, it is often more useful than `diff' for +comparing binary files. For text files, `cmp' is useful mainly when +you want to know only whether two files are identical, or whether one +file is a prefix of the other. + + To illustrate the effect that considering changes byte by byte can +have compared with considering them line by line, think of what happens +if a single newline character is added to the beginning of a file. If +that file is then compared with an otherwise identical file that lacks +the newline at the beginning, `diff' will report that a blank line has +been added to the file, while `cmp' will report that almost every byte +of the two files differs. + + `diff3' normally compares three input files line by line, finds +groups of lines that differ, and reports each group of differing lines. +Its output is designed to make it easy to inspect two different sets of +changes to the same file. + +* Menu: + +* Hunks:: Groups of differing lines. +* White Space:: Suppressing differences in white space. +* Blank Lines:: Suppressing differences whose lines are all blank. +* Specified Lines:: Suppressing differences whose lines all match a pattern. +* Case Folding:: Suppressing differences in alphabetic case. +* Brief:: Summarizing which files are different. +* Binary:: Comparing binary files or forcing text comparisons. + + +File: diff.info, Node: Hunks, Next: White Space, Up: Comparison + +1.1 Hunks +========= + +When comparing two files, `diff' finds sequences of lines common to +both files, interspersed with groups of differing lines called "hunks". +Comparing two identical files yields one sequence of common lines and +no hunks, because no lines differ. Comparing two entirely different +files yields no common lines and one large hunk that contains all lines +of both files. In general, there are many ways to match up lines +between two given files. `diff' tries to minimize the total hunk size +by finding large sequences of common lines interspersed with small +hunks of differing lines. + + For example, suppose the file `F' contains the three lines `a', `b', +`c', and the file `G' contains the same three lines in reverse order +`c', `b', `a'. If `diff' finds the line `c' as common, then the command +`diff F G' produces this output: + + 1,2d0 + < a + < b + 3a2,3 + > b + > a + +But if `diff' notices the common line `b' instead, it produces this +output: + + 1c1 + < a + --- + > c + 3c3 + < c + --- + > a + +It is also possible to find `a' as the common line. `diff' does not +always find an optimal matching between the files; it takes shortcuts +to run faster. But its output is usually close to the shortest +possible. You can adjust this tradeoff with the `-d' or `--minimal' +option (*note diff Performance::). + + +File: diff.info, Node: White Space, Next: Blank Lines, Prev: Hunks, Up: Comparison + +1.2 Suppressing Differences in Blank and Tab Spacing +==================================================== + +The `-E' or `--ignore-tab-expansion' option ignores the distinction +between tabs and spaces on input. A tab is considered to be equivalent +to the number of spaces to the next tab stop (*note Tabs::). + + The `-b' or `--ignore-space-change' option is stronger. It ignores +white space at line end, and considers all other sequences of one or +more white space characters within a line to be equivalent. With this +option, `diff' considers the following two lines to be equivalent, +where `$' denotes the line end: + + Here lyeth muche rychnesse in lytell space. -- John Heywood$ + Here lyeth muche rychnesse in lytell space. -- John Heywood $ + + The `-w' or `--ignore-all-space' option is stronger still. It +ignores differences even if one line has white space where the other +line has none. "White space" characters include tab, newline, vertical +tab, form feed, carriage return, and space; some locales may define +additional characters to be white space. With this option, `diff' +considers the following two lines to be equivalent, where `$' denotes +the line end and `^M' denotes a carriage return: + + Here lyeth muche rychnesse in lytell space.-- John Heywood$ + He relyeth much erychnes seinly tells pace. --John Heywood ^M$ + + +File: diff.info, Node: Blank Lines, Next: Specified Lines, Prev: White Space, Up: Comparison + +1.3 Suppressing Differences Whose Lines Are All Blank +===================================================== + +The `-B' or `--ignore-blank-lines' option ignores changes that consist +entirely of blank lines. With this option, for example, a file +containing + 1. A point is that which has no part. + + 2. A line is breadthless length. + -- Euclid, The Elements, I + is considered identical to a file containing + 1. A point is that which has no part. + 2. A line is breadthless length. + + + -- Euclid, The Elements, I + + Normally this option affects only lines that are completely empty, +but if you also specify the `-b' or `--ignore-space-change' option, or +the `-w' or `--ignore-all-space' option, lines are also affected if +they look empty but contain white space. In other words, `-B' is +equivalent to `-I '^$'' by default, but it is equivalent to `-I +'^[[:space:]]*$'' if `-b' or `-w' is also specified. + + +File: diff.info, Node: Specified Lines, Next: Case Folding, Prev: Blank Lines, Up: Comparison + +1.4 Suppressing Differences Whose Lines All Match a Regular Expression +====================================================================== + +To ignore insertions and deletions of lines that match a `grep'-style +regular expression, use the `-I REGEXP' or +`--ignore-matching-lines=REGEXP' option. You should escape regular +expressions that contain shell metacharacters to prevent the shell from +expanding them. For example, `diff -I '^[[:digit:]]'' ignores all +changes to lines beginning with a digit. + + However, `-I' only ignores the insertion or deletion of lines that +contain the regular expression if every changed line in the hunk--every +insertion and every deletion--matches the regular expression. In other +words, for each nonignorable change, `diff' prints the complete set of +changes in its vicinity, including the ignorable ones. + + You can specify more than one regular expression for lines to ignore +by using more than one `-I' option. `diff' tries to match each line +against each regular expression. + + +File: diff.info, Node: Case Folding, Next: Brief, Prev: Specified Lines, Up: Comparison + +1.5 Suppressing Case Differences +================================ + +GNU `diff' can treat lower case letters as equivalent to their upper +case counterparts, so that, for example, it considers `Funky Stuff', +`funky STUFF', and `fUNKy stuFf' to all be the same. To request this, +use the `-i' or `--ignore-case' option. + + +File: diff.info, Node: Brief, Next: Binary, Prev: Case Folding, Up: Comparison + +1.6 Summarizing Which Files Differ +================================== + +When you only want to find out whether files are different, and you +don't care what the differences are, you can use the summary output +format. In this format, instead of showing the differences between the +files, `diff' simply reports whether files differ. The `-q' or +`--brief' option selects this output format. + + This format is especially useful when comparing the contents of two +directories. It is also much faster than doing the normal line by line +comparisons, because `diff' can stop analyzing the files as soon as it +knows that there are any differences. + + You can also get a brief indication of whether two files differ by +using `cmp'. For files that are identical, `cmp' produces no output. +When the files differ, by default, `cmp' outputs the byte and line +number where the first difference occurs, or reports that one file is a +prefix of the other. You can use the `-s', `--quiet', or `--silent' +option to suppress that information, so that `cmp' produces no output +and reports whether the files differ using only its exit status (*note +Invoking cmp::). + + Unlike `diff', `cmp' cannot compare directories; it can only compare +two files. + + +File: diff.info, Node: Binary, Prev: Brief, Up: Comparison + +1.7 Binary Files and Forcing Text Comparisons +============================================= + +If `diff' thinks that either of the two files it is comparing is binary +(a non-text file), it normally treats that pair of files much as if the +summary output format had been selected (*note Brief::), and reports +only that the binary files are different. This is because line by line +comparisons are usually not meaningful for binary files. + + `diff' determines whether a file is text or binary by checking the +first few bytes in the file; the exact number of bytes is system +dependent, but it is typically several thousand. If every byte in that +part of the file is non-null, `diff' considers the file to be text; +otherwise it considers the file to be binary. + + Sometimes you might want to force `diff' to consider files to be +text. For example, you might be comparing text files that contain null +characters; `diff' would erroneously decide that those are non-text +files. Or you might be comparing documents that are in a format used +by a word processing system that uses null characters to indicate +special formatting. You can force `diff' to consider all files to be +text files, and compare them line by line, by using the `-a' or +`--text' option. If the files you compare using this option do not in +fact contain text, they will probably contain few newline characters, +and the `diff' output will consist of hunks showing differences between +long lines of whatever characters the files contain. + + You can also force `diff' to report only whether files differ (but +not how). Use the `-q' or `--brief' option for this. + + Normally, differing binary files count as trouble because the +resulting `diff' output does not capture all the differences. This +trouble causes `diff' to exit with status 2. However, this trouble +cannot occur with the `-a' or `--text' option, or with the `-q' or +`--brief' option, as these options both cause `diff' to generate a form +of output that represents differences as requested. + + In operating systems that distinguish between text and binary files, +`diff' normally reads and writes all data as text. Use the `--binary' +option to force `diff' to read and write binary data instead. This +option has no effect on a POSIX-compliant system like GNU or +traditional Unix. However, many personal computer operating systems +represent the end of a line with a carriage return followed by a +newline. On such systems, `diff' normally ignores these carriage +returns on input and generates them at the end of each output line, but +with the `--binary' option `diff' treats each carriage return as just +another input character, and does not generate a carriage return at the +end of each output line. This can be useful when dealing with non-text +files that are meant to be interchanged with POSIX-compliant systems. + + The `--strip-trailing-cr' causes `diff' to treat input lines that +end in carriage return followed by newline as if they end in plain +newline. This can be useful when comparing text that is imperfectly +imported from many personal computer operating systems. This option +affects how lines are read, which in turn affects how they are compared +and output. + + If you want to compare two files byte by byte, you can use the `cmp' +program with the `-l' or `--verbose' option to show the values of each +differing byte in the two files. With GNU `cmp', you can also use the +`-b' or `--print-bytes' option to show the ASCII representation of +those bytes. *Note Invoking cmp::, for more information. + + If `diff3' thinks that any of the files it is comparing is binary (a +non-text file), it normally reports an error, because such comparisons +are usually not useful. `diff3' uses the same test as `diff' to decide +whether a file is binary. As with `diff', if the input files contain a +few non-text bytes but otherwise are like text files, you can force +`diff3' to consider all files to be text files and compare them line by +line by using the `-a' or `--text' option. + + +File: diff.info, Node: Output Formats, Next: Incomplete Lines, Prev: Comparison, Up: Top + +2 `diff' Output Formats +*********************** + +`diff' has several mutually exclusive options for output format. The +following sections describe each format, illustrating how `diff' +reports the differences between two sample input files. + +* Menu: + +* Sample diff Input:: Sample `diff' input files for examples. +* Context:: Showing differences with the surrounding text. +* Side by Side:: Showing differences in two columns. +* Normal:: Showing differences without surrounding text. +* Scripts:: Generating scripts for other programs. +* If-then-else:: Merging files with if-then-else. + + +File: diff.info, Node: Sample diff Input, Next: Context, Up: Output Formats + +2.1 Two Sample Input Files +========================== + +Here are two sample files that we will use in numerous examples to +illustrate the output of `diff' and how various options can change it. + + This is the file `lao': + + The Way that can be told of is not the eternal Way; + The name that can be named is not the eternal name. + The Nameless is the origin of Heaven and Earth; + The Named is the mother of all things. + Therefore let there always be non-being, + so we may see their subtlety, + And let there always be being, + so we may see their outcome. + The two are the same, + But after they are produced, + they have different names. + + This is the file `tzu': + + The Nameless is the origin of Heaven and Earth; + The named is the mother of all things. + + Therefore let there always be non-being, + so we may see their subtlety, + And let there always be being, + so we may see their outcome. + The two are the same, + But after they are produced, + they have different names. + They both may be called deep and profound. + Deeper and more profound, + The door of all subtleties! + + In this example, the first hunk contains just the first two lines of +`lao', the second hunk contains the fourth line of `lao' opposing the +second and third lines of `tzu', and the last hunk contains just the +last three lines of `tzu'. + + +File: diff.info, Node: Context, Next: Side by Side, Prev: Sample diff Input, Up: Output Formats + +2.2 Showing Differences in Their Context +======================================== + +Usually, when you are looking at the differences between files, you will +also want to see the parts of the files near the lines that differ, to +help you understand exactly what has changed. These nearby parts of the +files are called the "context". + + GNU `diff' provides two output formats that show context around the +differing lines: "context format" and "unified format". It can +optionally show in which function or section of the file the differing +lines are found. + + If you are distributing new versions of files to other people in the +form of `diff' output, you should use one of the output formats that +show context so that they can apply the diffs even if they have made +small changes of their own to the files. `patch' can apply the diffs +in this case by searching in the files for the lines of context around +the differing lines; if those lines are actually a few lines away from +where the diff says they are, `patch' can adjust the line numbers +accordingly and still apply the diff correctly. *Note Imperfect::, for +more information on using `patch' to apply imperfect diffs. + +* Menu: + +* Context Format:: An output format that shows surrounding lines. +* Unified Format:: A more compact output format that shows context. +* Sections:: Showing which sections of the files differences are in. +* Alternate Names:: Showing alternate file names in context headers. + + +File: diff.info, Node: Context Format, Next: Unified Format, Up: Context + +2.2.1 Context Format +-------------------- + +The context output format shows several lines of context around the +lines that differ. It is the standard format for distributing updates +to source code. + + To select this output format, use the `-C LINES', +`--context[=LINES]', or `-c' option. The argument LINES that some of +these options take is the number of lines of context to show. If you +do not specify LINES, it defaults to three. For proper operation, +`patch' typically needs at least two lines of context. + +* Menu: + +* Example Context:: Sample output in context format. +* Less Context:: Another sample with less context. +* Detailed Context:: A detailed description of the context output format. + + +File: diff.info, Node: Example Context, Next: Less Context, Up: Context Format + +2.2.1.1 An Example of Context Format +.................................... + +Here is the output of `diff -c lao tzu' (*note Sample diff Input::, for +the complete contents of the two files). Notice that up to three lines +that are not different are shown around each line that is different; +they are the context lines. Also notice that the first two hunks have +run together, because their contents overlap. + + *** lao 2002-02-21 23:30:39.942229878 -0800 + --- tzu 2002-02-21 23:30:50.442260588 -0800 + *************** + *** 1,7 **** + - The Way that can be told of is not the eternal Way; + - The name that can be named is not the eternal name. + The Nameless is the origin of Heaven and Earth; + ! The Named is the mother of all things. + Therefore let there always be non-being, + so we may see their subtlety, + And let there always be being, + --- 1,6 ---- + The Nameless is the origin of Heaven and Earth; + ! The named is the mother of all things. + ! + Therefore let there always be non-being, + so we may see their subtlety, + And let there always be being, + *************** + *** 9,11 **** + --- 8,13 ---- + The two are the same, + But after they are produced, + they have different names. + + They both may be called deep and profound. + + Deeper and more profound, + + The door of all subtleties! + + +File: diff.info, Node: Less Context, Next: Detailed Context, Prev: Example Context, Up: Context Format + +2.2.1.2 An Example of Context Format with Less Context +...................................................... + +Here is the output of `diff -C 1 lao tzu' (*note Sample diff Input::, +for the complete contents of the two files). Notice that at most one +context line is reported here. + + *** lao 2002-02-21 23:30:39.942229878 -0800 + --- tzu 2002-02-21 23:30:50.442260588 -0800 + *************** + *** 1,5 **** + - The Way that can be told of is not the eternal Way; + - The name that can be named is not the eternal name. + The Nameless is the origin of Heaven and Earth; + ! The Named is the mother of all things. + Therefore let there always be non-being, + --- 1,4 ---- + The Nameless is the origin of Heaven and Earth; + ! The named is the mother of all things. + ! + Therefore let there always be non-being, + *************** + *** 11 **** + --- 10,13 ---- + they have different names. + + They both may be called deep and profound. + + Deeper and more profound, + + The door of all subtleties! + + +File: diff.info, Node: Detailed Context, Prev: Less Context, Up: Context Format + +2.2.1.3 Detailed Description of Context Format +.............................................. + +The context output format starts with a two-line header, which looks +like this: + + *** FROM-FILE FROM-FILE-MODIFICATION-TIME + --- TO-FILE TO-FILE-MODIFICATION TIME + +The time stamp normally looks like `2002-02-21 23:30:39.942229878 +-0800' to indicate the date, time with fractional seconds, and time +zone in Internet RFC 2822 format +(ftp://ftp.isi.edu/in-notes/rfc2822.txt). (The fractional seconds are +omitted on hosts that do not support fractional time stamps.) However, +a traditional time stamp like `Thu Feb 21 23:30:39 2002' is used if the +`LC_TIME' locale category is either `C' or `POSIX'. + + You can change the header's content with the `--label=LABEL' option; +see *Note Alternate Names::. + + Next come one or more hunks of differences; each hunk shows one area +where the files differ. Context format hunks look like this: + + *************** + *** FROM-FILE-LINE-NUMBERS **** + FROM-FILE-LINE + FROM-FILE-LINE... + --- TO-FILE-LINE-NUMBERS ---- + TO-FILE-LINE + TO-FILE-LINE... + + If a hunk contains two or more lines, its line numbers look like +`START,END'. Otherwise only its end line number appears. An empty +hunk is considered to end at the line that precedes the hunk. + + The lines of context around the lines that differ start with two +space characters. The lines that differ between the two files start +with one of the following indicator characters, followed by a space +character: + +`!' + A line that is part of a group of one or more lines that changed + between the two files. There is a corresponding group of lines + marked with `!' in the part of this hunk for the other file. + +`+' + An "inserted" line in the second file that corresponds to nothing + in the first file. + +`-' + A "deleted" line in the first file that corresponds to nothing in + the second file. + + If all of the changes in a hunk are insertions, the lines of +FROM-FILE are omitted. If all of the changes are deletions, the lines +of TO-FILE are omitted. + + +File: diff.info, Node: Unified Format, Next: Sections, Prev: Context Format, Up: Context + +2.2.2 Unified Format +-------------------- + +The unified output format is a variation on the context format that is +more compact because it omits redundant context lines. To select this +output format, use the `-U LINES', `--unified[=LINES]', or `-u' option. +The argument LINES is the number of lines of context to show. When it +is not given, it defaults to three. + + At present, only GNU `diff' can produce this format and only GNU +`patch' can automatically apply diffs in this format. For proper +operation, `patch' typically needs at least three lines of context. + +* Menu: + +* Example Unified:: Sample output in unified format. +* Detailed Unified:: A detailed description of unified format. + + +File: diff.info, Node: Example Unified, Next: Detailed Unified, Up: Unified Format + +2.2.2.1 An Example of Unified Format +.................................... + +Here is the output of the command `diff -u lao tzu' (*note Sample diff +Input::, for the complete contents of the two files): + + --- lao 2002-02-21 23:30:39.942229878 -0800 + +++ tzu 2002-02-21 23:30:50.442260588 -0800 + @@ -1,7 +1,6 @@ + -The Way that can be told of is not the eternal Way; + -The name that can be named is not the eternal name. + The Nameless is the origin of Heaven and Earth; + -The Named is the mother of all things. + +The named is the mother of all things. + + + Therefore let there always be non-being, + so we may see their subtlety, + And let there always be being, + @@ -9,3 +8,6 @@ + The two are the same, + But after they are produced, + they have different names. + +They both may be called deep and profound. + +Deeper and more profound, + +The door of all subtleties! + + +File: diff.info, Node: Detailed Unified, Prev: Example Unified, Up: Unified Format + +2.2.2.2 Detailed Description of Unified Format +.............................................. + +The unified output format starts with a two-line header, which looks +like this: + + --- FROM-FILE FROM-FILE-MODIFICATION-TIME + +++ TO-FILE TO-FILE-MODIFICATION-TIME + +The time stamp looks like `2002-02-21 23:30:39.942229878 -0800' to +indicate the date, time with fractional seconds, and time zone. The +fractional seconds are omitted on hosts that do not support fractional +time stamps. + + You can change the header's content with the `--label=LABEL' option; +see *Note Alternate Names::. + + Next come one or more hunks of differences; each hunk shows one area +where the files differ. Unified format hunks look like this: + + @@ FROM-FILE-LINE-NUMBERS TO-FILE-LINE-NUMBERS @@ + LINE-FROM-EITHER-FILE + LINE-FROM-EITHER-FILE... + + If a hunk contains just one line, only its start line number appears. +Otherwise its line numbers look like `START,COUNT'. An empty hunk is +considered to start at the line that follows the hunk. + + If a hunk and its context contain two or more lines, its line +numbers look like `START,COUNT'. Otherwise only its end line number +appears. An empty hunk is considered to end at the line that precedes +the hunk. + + The lines common to both files begin with a space character. The +lines that actually differ between the two files have one of the +following indicator characters in the left print column: + +`+' + A line was added here to the first file. + +`-' + A line was removed here from the first file. + + +File: diff.info, Node: Sections, Next: Alternate Names, Prev: Unified Format, Up: Context + +2.2.3 Showing Which Sections Differences Are in +----------------------------------------------- + +Sometimes you might want to know which part of the files each change +falls in. If the files are source code, this could mean which function +was changed. If the files are documents, it could mean which chapter +or appendix was changed. GNU `diff' can show this by displaying the +nearest section heading line that precedes the differing lines. Which +lines are "section headings" is determined by a regular expression. + +* Menu: + +* Specified Headings:: Showing headings that match regular expressions. +* C Function Headings:: Showing headings of C functions. + + +File: diff.info, Node: Specified Headings, Next: C Function Headings, Up: Sections + +2.2.3.1 Showing Lines That Match Regular Expressions +.................................................... + +To show in which sections differences occur for files that are not +source code for C or similar languages, use the `-F REGEXP' or +`--show-function-line=REGEXP' option. `diff' considers lines that +match the `grep'-style regular expression REGEXP to be the beginning of +a section of the file. Here are suggested regular expressions for some +common languages: + +`^[[:alpha:]$_]' + C, C++, Prolog + +`^(' + Lisp + +`^@node' + Texinfo + + This option does not automatically select an output format; in order +to use it, you must select the context format (*note Context Format::) +or unified format (*note Unified Format::). In other output formats it +has no effect. + + The `-F' or `--show-function-line' option finds the nearest +unchanged line that precedes each hunk of differences and matches the +given regular expression. Then it adds that line to the end of the +line of asterisks in the context format, or to the `@@' line in unified +format. If no matching line exists, this option leaves the output for +that hunk unchanged. If that line is more than 40 characters long, it +outputs only the first 40 characters. You can specify more than one +regular expression for such lines; `diff' tries to match each line +against each regular expression, starting with the last one given. This +means that you can use `-p' and `-F' together, if you wish. + + +File: diff.info, Node: C Function Headings, Prev: Specified Headings, Up: Sections + +2.2.3.2 Showing C Function Headings +................................... + +To show in which functions differences occur for C and similar +languages, you can use the `-p' or `--show-c-function' option. This +option automatically defaults to the context output format (*note +Context Format::), with the default number of lines of context. You +can override that number with `-C LINES' elsewhere in the command line. +You can override both the format and the number with `-U LINES' +elsewhere in the command line. + + The `-p' or `--show-c-function' option is equivalent to `-F +'^[[:alpha:]$_]'' if the unified format is specified, otherwise `-c -F +'^[[:alpha:]$_]'' (*note Specified Headings::). GNU `diff' provides +this option for the sake of convenience. + + +File: diff.info, Node: Alternate Names, Prev: Sections, Up: Context + +2.2.4 Showing Alternate File Names +---------------------------------- + +If you are comparing two files that have meaningless or uninformative +names, you might want `diff' to show alternate names in the header of +the context and unified output formats. To do this, use the +`--label=LABEL' option. The first time you give this option, its +argument replaces the name and date of the first file in the header; +the second time, its argument replaces the name and date of the second +file. If you give this option more than twice, `diff' reports an +error. The `--label' option does not affect the file names in the `pr' +header when the `-l' or `--paginate' option is used (*note +Pagination::). + + Here are the first two lines of the output from `diff -C 2 +--label=original --label=modified lao tzu': + + *** original + --- modified + + +File: diff.info, Node: Side by Side, Next: Normal, Prev: Context, Up: Output Formats + +2.3 Showing Differences Side by Side +==================================== + +`diff' can produce a side by side difference listing of two files. The +files are listed in two columns with a gutter between them. The gutter +contains one of the following markers: + +white space + The corresponding lines are in common. That is, either the lines + are identical, or the difference is ignored because of one of the + `--ignore' options (*note White Space::). + +`|' + The corresponding lines differ, and they are either both complete + or both incomplete. + +`<' + The files differ and only the first file contains the line. + +`>' + The files differ and only the second file contains the line. + +`(' + Only the first file contains the line, but the difference is + ignored. + +`)' + Only the second file contains the line, but the difference is + ignored. + +`\' + The corresponding lines differ, and only the first line is + incomplete. + +`/' + The corresponding lines differ, and only the second line is + incomplete. + + Normally, an output line is incomplete if and only if the lines that +it contains are incomplete; *Note Incomplete Lines::. However, when an +output line represents two differing lines, one might be incomplete +while the other is not. In this case, the output line is complete, but +its the gutter is marked `\' if the first line is incomplete, `/' if +the second line is. + + Side by side format is sometimes easiest to read, but it has +limitations. It generates much wider output than usual, and truncates +lines that are too long to fit. Also, it relies on lining up output +more heavily than usual, so its output looks particularly bad if you +use varying width fonts, nonstandard tab stops, or nonprinting +characters. + + You can use the `sdiff' command to interactively merge side by side +differences. *Note Interactive Merging::, for more information on +merging files. + +* Menu: + +* Side by Side Format:: Controlling side by side output format. +* Example Side by Side:: Sample side by side output. + + +File: diff.info, Node: Side by Side Format, Next: Example Side by Side, Up: Side by Side + +2.3.1 Controlling Side by Side Format +------------------------------------- + +The `-y' or `--side-by-side' option selects side by side format. +Because side by side output lines contain two input lines, the output +is wider than usual: normally 130 print columns, which can fit onto a +traditional printer line. You can set the width of the output with the +`-W COLUMNS' or `--width=COLUMNS' option. The output is split into two +halves of equal width, separated by a small gutter to mark differences; +the right half is aligned to a tab stop so that tabs line up. Input +lines that are too long to fit in half of an output line are truncated +for output. + + The `--left-column' option prints only the left column of two common +lines. The `--suppress-common-lines' option suppresses common lines +entirely. + + +File: diff.info, Node: Example Side by Side, Prev: Side by Side Format, Up: Side by Side + +2.3.2 An Example of Side by Side Format +--------------------------------------- + +Here is the output of the command `diff -y -W 72 lao tzu' (*note Sample +diff Input::, for the complete contents of the two files). + + The Way that can be told of is n < + The name that can be named is no < + The Nameless is the origin of He The Nameless is the origin of He + The Named is the mother of all t | The named is the mother of all t + > + Therefore let there always be no Therefore let there always be no + so we may see their subtlety, so we may see their subtlety, + And let there always be being, And let there always be being, + so we may see their outcome. so we may see their outcome. + The two are the same, The two are the same, + But after they are produced, But after they are produced, + they have different names. they have different names. + > They both may be called deep and + > Deeper and more profound, + > The door of all subtleties! + + +File: diff.info, Node: Normal, Next: Scripts, Prev: Side by Side, Up: Output Formats + +2.4 Showing Differences Without Context +======================================= + +The "normal" `diff' output format shows each hunk of differences +without any surrounding context. Sometimes such output is the clearest +way to see how lines have changed, without the clutter of nearby +unchanged lines (although you can get similar results with the context +or unified formats by using 0 lines of context). However, this format +is no longer widely used for sending out patches; for that purpose, the +context format (*note Context Format::) and the unified format (*note +Unified Format::) are superior. Normal format is the default for +compatibility with older versions of `diff' and the POSIX standard. +Use the `--normal' option to select this output format explicitly. + +* Menu: + +* Example Normal:: Sample output in the normal format. +* Detailed Normal:: A detailed description of normal output format. + + +File: diff.info, Node: Example Normal, Next: Detailed Normal, Up: Normal + +2.4.1 An Example of Normal Format +--------------------------------- + +Here is the output of the command `diff lao tzu' (*note Sample diff +Input::, for the complete contents of the two files). Notice that it +shows only the lines that are different between the two files. + + 1,2d0 + < The Way that can be told of is not the eternal Way; + < The name that can be named is not the eternal name. + 4c2,3 + < The Named is the mother of all things. + --- + > The named is the mother of all things. + > + 11a11,13 + > They both may be called deep and profound. + > Deeper and more profound, + > The door of all subtleties! + + +File: diff.info, Node: Detailed Normal, Prev: Example Normal, Up: Normal + +2.4.2 Detailed Description of Normal Format +------------------------------------------- + +The normal output format consists of one or more hunks of differences; +each hunk shows one area where the files differ. Normal format hunks +look like this: + + CHANGE-COMMAND + < FROM-FILE-LINE + < FROM-FILE-LINE... + --- + > TO-FILE-LINE + > TO-FILE-LINE... + + There are three types of change commands. Each consists of a line +number or comma-separated range of lines in the first file, a single +character indicating the kind of change to make, and a line number or +comma-separated range of lines in the second file. All line numbers are +the original line numbers in each file. The types of change commands +are: + +`LaR' + Add the lines in range R of the second file after line L of the + first file. For example, `8a12,15' means append lines 12-15 of + file 2 after line 8 of file 1; or, if changing file 2 into file 1, + delete lines 12-15 of file 2. + +`FcT' + Replace the lines in range F of the first file with lines in range + T of the second file. This is like a combined add and delete, but + more compact. For example, `5,7c8,10' means change lines 5-7 of + file 1 to read as lines 8-10 of file 2; or, if changing file 2 into + file 1, change lines 8-10 of file 2 to read as lines 5-7 of file 1. + +`RdL' + Delete the lines in range R from the first file; line L is where + they would have appeared in the second file had they not been + deleted. For example, `5,7d3' means delete lines 5-7 of file 1; + or, if changing file 2 into file 1, append lines 5-7 of file 1 + after line 3 of file 2. + + +File: diff.info, Node: Scripts, Next: If-then-else, Prev: Normal, Up: Output Formats + +2.5 Making Edit Scripts +======================= + +Several output modes produce command scripts for editing FROM-FILE to +produce TO-FILE. + +* Menu: + +* ed Scripts:: Using `diff' to produce commands for `ed'. +* Forward ed:: Making forward `ed' scripts. +* RCS:: A special `diff' output format used by RCS. + + +File: diff.info, Node: ed Scripts, Next: Forward ed, Up: Scripts + +2.5.1 `ed' Scripts +------------------ + +`diff' can produce commands that direct the `ed' text editor to change +the first file into the second file. Long ago, this was the only +output mode that was suitable for editing one file into another +automatically; today, with `patch', it is almost obsolete. Use the +`-e' or `--ed' option to select this output format. + + Like the normal format (*note Normal::), this output format does not +show any context; unlike the normal format, it does not include the +information necessary to apply the diff in reverse (to produce the first +file if all you have is the second file and the diff). + + If the file `d' contains the output of `diff -e old new', then the +command `(cat d && echo w) | ed - old' edits `old' to make it a copy of +`new'. More generally, if `d1', `d2', ..., `dN' contain the outputs of +`diff -e old new1', `diff -e new1 new2', ..., `diff -e newN-1 newN', +respectively, then the command `(cat d1 d2 ... dN && echo w) | ed - +old' edits `old' to make it a copy of `newN'. + +* Menu: + +* Example ed:: A sample `ed' script. +* Detailed ed:: A detailed description of `ed' format. + + +File: diff.info, Node: Example ed, Next: Detailed ed, Up: ed Scripts + +2.5.1.1 Example `ed' Script +........................... + +Here is the output of `diff -e lao tzu' (*note Sample diff Input::, for +the complete contents of the two files): + + 11a + They both may be called deep and profound. + Deeper and more profound, + The door of all subtleties! + . + 4c + The named is the mother of all things. + + . + 1,2d + + +File: diff.info, Node: Detailed ed, Prev: Example ed, Up: ed Scripts + +2.5.1.2 Detailed Description of `ed' Format +........................................... + +The `ed' output format consists of one or more hunks of differences. +The changes closest to the ends of the files come first so that +commands that change the number of lines do not affect how `ed' +interprets line numbers in succeeding commands. `ed' format hunks look +like this: + + CHANGE-COMMAND + TO-FILE-LINE + TO-FILE-LINE... + . + + Because `ed' uses a single period on a line to indicate the end of +input, GNU `diff' protects lines of changes that contain a single +period on a line by writing two periods instead, then writing a +subsequent `ed' command to change the two periods into one. The `ed' +format cannot represent an incomplete line, so if the second file ends +in a changed incomplete line, `diff' reports an error and then pretends +that a newline was appended. + + There are three types of change commands. Each consists of a line +number or comma-separated range of lines in the first file and a single +character indicating the kind of change to make. All line numbers are +the original line numbers in the file. The types of change commands +are: + +`La' + Add text from the second file after line L in the first file. For + example, `8a' means to add the following lines after line 8 of file + 1. + +`Rc' + Replace the lines in range R in the first file with the following + lines. Like a combined add and delete, but more compact. For + example, `5,7c' means change lines 5-7 of file 1 to read as the + text file 2. + +`Rd' + Delete the lines in range R from the first file. For example, + `5,7d' means delete lines 5-7 of file 1. + + +File: diff.info, Node: Forward ed, Next: RCS, Prev: ed Scripts, Up: Scripts + +2.5.2 Forward `ed' Scripts +-------------------------- + +`diff' can produce output that is like an `ed' script, but with hunks +in forward (front to back) order. The format of the commands is also +changed slightly: command characters precede the lines they modify, +spaces separate line numbers in ranges, and no attempt is made to +disambiguate hunk lines consisting of a single period. Like `ed' +format, forward `ed' format cannot represent incomplete lines. + + Forward `ed' format is not very useful, because neither `ed' nor +`patch' can apply diffs in this format. It exists mainly for +compatibility with older versions of `diff'. Use the `-f' or +`--forward-ed' option to select it. + + +File: diff.info, Node: RCS, Prev: Forward ed, Up: Scripts + +2.5.3 RCS Scripts +----------------- + +The RCS output format is designed specifically for use by the Revision +Control System, which is a set of free programs used for organizing +different versions and systems of files. Use the `-n' or `--rcs' +option to select this output format. It is like the forward `ed' +format (*note Forward ed::), but it can represent arbitrary changes to +the contents of a file because it avoids the forward `ed' format's +problems with lines consisting of a single period and with incomplete +lines. Instead of ending text sections with a line consisting of a +single period, each command specifies the number of lines it affects; a +combination of the `a' and `d' commands are used instead of `c'. Also, +if the second file ends in a changed incomplete line, then the output +also ends in an incomplete line. + + Here is the output of `diff -n lao tzu' (*note Sample diff Input::, +for the complete contents of the two files): + + d1 2 + d4 1 + a4 2 + The named is the mother of all things. + + a11 3 + They both may be called deep and profound. + Deeper and more profound, + The door of all subtleties! + + +File: diff.info, Node: If-then-else, Prev: Scripts, Up: Output Formats + +2.6 Merging Files with If-then-else +=================================== + +You can use `diff' to merge two files of C source code. The output of +`diff' in this format contains all the lines of both files. Lines +common to both files are output just once; the differing parts are +separated by the C preprocessor directives `#ifdef NAME' or `#ifndef +NAME', `#else', and `#endif'. When compiling the output, you select +which version to use by either defining or leaving undefined the macro +NAME. + + To merge two files, use `diff' with the `-D NAME' or `--ifdef=NAME' +option. The argument NAME is the C preprocessor identifier to use in +the `#ifdef' and `#ifndef' directives. + + For example, if you change an instance of `wait (&s)' to `waitpid +(-1, &s, 0)' and then merge the old and new files with the +`--ifdef=HAVE_WAITPID' option, then the affected part of your code +might look like this: + + do { + #ifndef HAVE_WAITPID + if ((w = wait (&s)) < 0 && errno != EINTR) + #else /* HAVE_WAITPID */ + if ((w = waitpid (-1, &s, 0)) < 0 && errno != EINTR) + #endif /* HAVE_WAITPID */ + return w; + } while (w != child); + + You can specify formats for languages other than C by using line +group formats and line formats, as described in the next sections. + +* Menu: + +* Line Group Formats:: Formats for general if-then-else line groups. +* Line Formats:: Formats for each line in a line group. +* Example If-then-else:: Sample if-then-else format output. +* Detailed If-then-else:: A detailed description of if-then-else format. + + +File: diff.info, Node: Line Group Formats, Next: Line Formats, Up: If-then-else + +2.6.1 Line Group Formats +------------------------ + +Line group formats let you specify formats suitable for many +applications that allow if-then-else input, including programming +languages and text formatting languages. A line group format specifies +the output format for a contiguous group of similar lines. + + For example, the following command compares the TeX files `old' and +`new', and outputs a merged file in which old regions are surrounded by +`\begin{em}'-`\end{em}' lines, and new regions are surrounded by +`\begin{bf}'-`\end{bf}' lines. + + diff \ + --old-group-format='\begin{em} + %<\end{em} + ' \ + --new-group-format='\begin{bf} + %>\end{bf} + ' \ + old new + + The following command is equivalent to the above example, but it is a +little more verbose, because it spells out the default line group +formats. + + diff \ + --old-group-format='\begin{em} + %<\end{em} + ' \ + --new-group-format='\begin{bf} + %>\end{bf} + ' \ + --unchanged-group-format='%=' \ + --changed-group-format='\begin{em} + %<\end{em} + \begin{bf} + %>\end{bf} + ' \ + old new + + Here is a more advanced example, which outputs a diff listing with +headers containing line numbers in a "plain English" style. + + diff \ + --unchanged-group-format='' \ + --old-group-format='-------- %dn line%(n=1?:s) deleted at %df: + %<' \ + --new-group-format='-------- %dN line%(N=1?:s) added after %de: + %>' \ + --changed-group-format='-------- %dn line%(n=1?:s) changed at %df: + %<-------- to: + %>' \ + old new + + To specify a line group format, use `diff' with one of the options +listed below. You can specify up to four line group formats, one for +each kind of line group. You should quote FORMAT, because it typically +contains shell metacharacters. + +`--old-group-format=FORMAT' + These line groups are hunks containing only lines from the first + file. The default old group format is the same as the changed + group format if it is specified; otherwise it is a format that + outputs the line group as-is. + +`--new-group-format=FORMAT' + These line groups are hunks containing only lines from the second + file. The default new group format is same as the changed group + format if it is specified; otherwise it is a format that outputs + the line group as-is. + +`--changed-group-format=FORMAT' + These line groups are hunks containing lines from both files. The + default changed group format is the concatenation of the old and + new group formats. + +`--unchanged-group-format=FORMAT' + These line groups contain lines common to both files. The default + unchanged group format is a format that outputs the line group + as-is. + + In a line group format, ordinary characters represent themselves; +conversion specifications start with `%' and have one of the following +forms. + +`%<' + stands for the lines from the first file, including the trailing + newline. Each line is formatted according to the old line format + (*note Line Formats::). + +`%>' + stands for the lines from the second file, including the trailing + newline. Each line is formatted according to the new line format. + +`%=' + stands for the lines common to both files, including the trailing + newline. Each line is formatted according to the unchanged line + format. + +`%%' + stands for `%'. + +`%c'C'' + where C is a single character, stands for C. C may not be a + backslash or an apostrophe. For example, `%c':'' stands for a + colon, even inside the then-part of an if-then-else format, which + a colon would normally terminate. + +`%c'\O'' + where O is a string of 1, 2, or 3 octal digits, stands for the + character with octal code O. For example, `%c'\0'' stands for a + null character. + +`FN' + where F is a `printf' conversion specification and N is one of the + following letters, stands for N's value formatted with F. + + `e' + The line number of the line just before the group in the old + file. + + `f' + The line number of the first line in the group in the old + file; equals E + 1. + + `l' + The line number of the last line in the group in the old file. + + `m' + The line number of the line just after the group in the old + file; equals L + 1. + + `n' + The number of lines in the group in the old file; equals L - + F + 1. + + `E, F, L, M, N' + Likewise, for lines in the new file. + + + The `printf' conversion specification can be `%d', `%o', `%x', or + `%X', specifying decimal, octal, lower case hexadecimal, or upper + case hexadecimal output respectively. After the `%' the following + options can appear in sequence: a series of zero or more flags; an + integer specifying the minimum field width; and a period followed + by an optional integer specifying the minimum number of digits. + The flags are `-' for left-justification, `'' for separating the + digit into groups as specified by the `LC_NUMERIC' locale category, + and `0' for padding with zeros instead of spaces. For example, + `%5dN' prints the number of new lines in the group in a field of + width 5 characters, using the `printf' format `"%5d"'. + +`(A=B?T:E)' + If A equals B then T else E. A and B are each either a decimal + constant or a single letter interpreted as above. This format + spec is equivalent to T if A's value equals B's; otherwise it is + equivalent to E. + + For example, `%(N=0?no:%dN) line%(N=1?:s)' is equivalent to `no + lines' if N (the number of lines in the group in the new file) is + 0, to `1 line' if N is 1, and to `%dN lines' otherwise. + + +File: diff.info, Node: Line Formats, Next: Example If-then-else, Prev: Line Group Formats, Up: If-then-else + +2.6.2 Line Formats +------------------ + +Line formats control how each line taken from an input file is output +as part of a line group in if-then-else format. + + For example, the following command outputs text with a one-character +change indicator to the left of the text. The first character of output +is `-' for deleted lines, `|' for added lines, and a space for +unchanged lines. The formats contain newline characters where newlines +are desired on output. + + diff \ + --old-line-format='-%l + ' \ + --new-line-format='|%l + ' \ + --unchanged-line-format=' %l + ' \ + old new + + To specify a line format, use one of the following options. You +should quote FORMAT, since it often contains shell metacharacters. + +`--old-line-format=FORMAT' + formats lines just from the first file. + +`--new-line-format=FORMAT' + formats lines just from the second file. + +`--unchanged-line-format=FORMAT' + formats lines common to both files. + +`--line-format=FORMAT' + formats all lines; in effect, it sets all three above options + simultaneously. + + In a line format, ordinary characters represent themselves; +conversion specifications start with `%' and have one of the following +forms. + +`%l' + stands for the contents of the line, not counting its trailing + newline (if any). This format ignores whether the line is + incomplete; *Note Incomplete Lines::. + +`%L' + stands for the contents of the line, including its trailing newline + (if any). If a line is incomplete, this format preserves its + incompleteness. + +`%%' + stands for `%'. + +`%c'C'' + where C is a single character, stands for C. C may not be a + backslash or an apostrophe. For example, `%c':'' stands for a + colon. + +`%c'\O'' + where O is a string of 1, 2, or 3 octal digits, stands for the + character with octal code O. For example, `%c'\0'' stands for a + null character. + +`Fn' + where F is a `printf' conversion specification, stands for the + line number formatted with F. For example, `%.5dn' prints the + line number using the `printf' format `"%.5d"'. *Note Line Group + Formats::, for more about printf conversion specifications. + + + The default line format is `%l' followed by a newline character. + + If the input contains tab characters and it is important that they +line up on output, you should ensure that `%l' or `%L' in a line format +is just after a tab stop (e.g. by preceding `%l' or `%L' with a tab +character), or you should use the `-t' or `--expand-tabs' option. + + Taken together, the line and line group formats let you specify many +different formats. For example, the following command uses a format +similar to normal `diff' format. You can tailor this command to get +fine control over `diff' output. + + diff \ + --old-line-format='< %l + ' \ + --new-line-format='> %l + ' \ + --old-group-format='%df%(f=l?:,%dl)d%dE + %<' \ + --new-group-format='%dea%dF%(F=L?:,%dL) + %>' \ + --changed-group-format='%df%(f=l?:,%dl)c%dF%(F=L?:,%dL) + %<--- + %>' \ + --unchanged-group-format='' \ + old new + + +File: diff.info, Node: Example If-then-else, Next: Detailed If-then-else, Prev: Line Formats, Up: If-then-else + +2.6.3 An Example of If-then-else Format +--------------------------------------- + +Here is the output of `diff -DTWO lao tzu' (*note Sample diff Input::, +for the complete contents of the two files): + + #ifndef TWO + The Way that can be told of is not the eternal Way; + The name that can be named is not the eternal name. + #endif /* ! TWO */ + The Nameless is the origin of Heaven and Earth; + #ifndef TWO + The Named is the mother of all things. + #else /* TWO */ + The named is the mother of all things. + + #endif /* TWO */ + Therefore let there always be non-being, + so we may see their subtlety, + And let there always be being, + so we may see their outcome. + The two are the same, + But after they are produced, + they have different names. + #ifdef TWO + They both may be called deep and profound. + Deeper and more profound, + The door of all subtleties! + #endif /* TWO */ + + +File: diff.info, Node: Detailed If-then-else, Prev: Example If-then-else, Up: If-then-else + +2.6.4 Detailed Description of If-then-else Format +------------------------------------------------- + +For lines common to both files, `diff' uses the unchanged line group +format. For each hunk of differences in the merged output format, if +the hunk contains only lines from the first file, `diff' uses the old +line group format; if the hunk contains only lines from the second +file, `diff' uses the new group format; otherwise, `diff' uses the +changed group format. + + The old, new, and unchanged line formats specify the output format of +lines from the first file, lines from the second file, and lines common +to both files, respectively. + + The option `--ifdef=NAME' is equivalent to the following sequence of +options using shell syntax: + + --old-group-format='#ifndef NAME + %<#endif /* ! NAME */ + ' \ + --new-group-format='#ifdef NAME + %>#endif /* NAME */ + ' \ + --unchanged-group-format='%=' \ + --changed-group-format='#ifndef NAME + %<#else /* NAME */ + %>#endif /* NAME */ + ' + + You should carefully check the `diff' output for proper nesting. +For example, when using the `-D NAME' or `--ifdef=NAME' option, you +should check that if the differing lines contain any of the C +preprocessor directives `#ifdef', `#ifndef', `#else', `#elif', or +`#endif', they are nested properly and match. If they don't, you must +make corrections manually. It is a good idea to carefully check the +resulting code anyway to make sure that it really does what you want it +to; depending on how the input files were produced, the output might +contain duplicate or otherwise incorrect code. + + The `patch' `-D NAME' option behaves like the `diff' `-D NAME' +option, except it operates on a file and a diff to produce a merged +file; *Note patch Options::. + + +File: diff.info, Node: Incomplete Lines, Next: Comparing Directories, Prev: Output Formats, Up: Top + +3 Incomplete Lines +****************** + +When an input file ends in a non-newline character, its last line is +called an "incomplete line" because its last character is not a +newline. All other lines are called "full lines" and end in a newline +character. Incomplete lines do not match full lines unless differences +in white space are ignored (*note White Space::). + + An incomplete line is normally distinguished on output from a full +line by a following line that starts with `\'. However, the RCS format +(*note RCS::) outputs the incomplete line as-is, without any trailing +newline or following line. The side by side format normally represents +incomplete lines as-is, but in some cases uses a `\' or `/' gutter +marker; *Note Side by Side::. The if-then-else line format preserves a +line's incompleteness with `%L', and discards the newline with `%l'; +*Note Line Formats::. Finally, with the `ed' and forward `ed' output +formats (*note Output Formats::) `diff' cannot represent an incomplete +line, so it pretends there was a newline and reports an error. + + For example, suppose `F' and `G' are one-byte files that contain +just `f' and `g', respectively. Then `diff F G' outputs + + 1c1 + < f + \ No newline at end of file + --- + > g + \ No newline at end of file + +(The exact message may differ in non-English locales.) `diff -n F G' +outputs the following without a trailing newline: + + d1 1 + a1 1 + g + +`diff -e F G' reports two errors and outputs the following: + + 1c + g + . + + +File: diff.info, Node: Comparing Directories, Next: Adjusting Output, Prev: Incomplete Lines, Up: Top + +4 Comparing Directories +*********************** + +You can use `diff' to compare some or all of the files in two directory +trees. When both file name arguments to `diff' are directories, it +compares each file that is contained in both directories, examining +file names in alphabetical order as specified by the `LC_COLLATE' +locale category. Normally `diff' is silent about pairs of files that +contain no differences, but if you use the `-s' or +`--report-identical-files' option, it reports pairs of identical files. +Normally `diff' reports subdirectories common to both directories +without comparing subdirectories' files, but if you use the `-r' or +`--recursive' option, it compares every corresponding pair of files in +the directory trees, as many levels deep as they go. + + For file names that are in only one of the directories, `diff' +normally does not show the contents of the file that exists; it reports +only that the file exists in that directory and not in the other. You +can make `diff' act as though the file existed but was empty in the +other directory, so that it outputs the entire contents of the file that +actually exists. (It is output as either an insertion or a deletion, +depending on whether it is in the first or the second directory given.) +To do this, use the `-N' or `--new-file' option. + + If the older directory contains one or more large files that are not +in the newer directory, you can make the patch smaller by using the +`--unidirectional-new-file' option instead of `-N'. This option is +like `-N' except that it only inserts the contents of files that appear +in the second directory but not the first (that is, files that were +added). At the top of the patch, write instructions for the user +applying the patch to remove the files that were deleted before +applying the patch. *Note Making Patches::, for more discussion of +making patches for distribution. + + To ignore some files while comparing directories, use the `-x +PATTERN' or `--exclude=PATTERN' option. This option ignores any files +or subdirectories whose base names match the shell pattern PATTERN. +Unlike in the shell, a period at the start of the base of a file name +matches a wildcard at the start of a pattern. You should enclose +PATTERN in quotes so that the shell does not expand it. For example, +the option `-x '*.[ao]'' ignores any file whose name ends with `.a' or +`.o'. + + This option accumulates if you specify it more than once. For +example, using the options `-x 'RCS' -x '*,v'' ignores any file or +subdirectory whose base name is `RCS' or ends with `,v'. + + If you need to give this option many times, you can instead put the +patterns in a file, one pattern per line, and use the `-X FILE' or +`--exclude-from=FILE' option. Trailing white space and empty lines are +ignored in the pattern file. + + If you have been comparing two directories and stopped partway +through, later you might want to continue where you left off. You can +do this by using the `-S FILE' or `--starting-file=FILE' option. This +compares only the file FILE and all alphabetically later files in the +topmost directory level. + + If two directories differ only in that file names are lower case in +one directory and upper case in the upper, `diff' normally reports many +differences because it compares file names in a case sensitive way. +With the `--ignore-file-name-case' option, `diff' ignores case +differences in file names, so that for example the contents of the file +`Tao' in one directory are compared to the contents of the file `TAO' +in the other. The `--no-ignore-file-name-case' option cancels the +effect of the `--ignore-file-name-case' option, reverting to the default +behavior. + + If an `-x PATTERN' or `--exclude=PATTERN' option, or an `-X FILE' or +`--exclude-from=FILE' option, is specified while the +`--ignore-file-name-case' option is in effect, case is ignored when +excluding file names matching the specified patterns. + + +File: diff.info, Node: Adjusting Output, Next: diff Performance, Prev: Comparing Directories, Up: Top + +5 Making `diff' Output Prettier +******************************* + +`diff' provides several ways to adjust the appearance of its output. +These adjustments can be applied to any output format. + +* Menu: + +* Tabs:: Preserving the alignment of tab stops. +* Pagination:: Page numbering and time-stamping `diff' output. + + +File: diff.info, Node: Tabs, Next: Pagination, Up: Adjusting Output + +5.1 Preserving Tab Stop Alignment +================================= + +The lines of text in some of the `diff' output formats are preceded by +one or two characters that indicate whether the text is inserted, +deleted, or changed. The addition of those characters can cause tabs +to move to the next tab stop, throwing off the alignment of columns in +the line. GNU `diff' provides two ways to make tab-aligned columns +line up correctly. + + The first way is to have `diff' convert all tabs into the correct +number of spaces before outputting them; select this method with the +`-t' or `--expand-tabs' option. To use this form of output with +`patch', you must give `patch' the `-l' or `--ignore-white-space' +option (*note Changed White Space::, for more information). `diff' +normally assumes that tab stops are set every 8 print columns, but this +can be altered by the `--tabsize=COLUMNS' option. + + The other method for making tabs line up correctly is to add a tab +character instead of a space after the indicator character at the +beginning of the line. This ensures that all following tab characters +are in the same position relative to tab stops that they were in the +original files, so that the output is aligned correctly. Its +disadvantage is that it can make long lines too long to fit on one line +of the screen or the paper. It also does not work with the unified +output format, which does not have a space character after the change +type indicator character. Select this method with the `-T' or +`--initial-tab' option. + + +File: diff.info, Node: Pagination, Prev: Tabs, Up: Adjusting Output + +5.2 Paginating `diff' Output +============================ + +It can be convenient to have long output page-numbered and time-stamped. +The `-l' or `--paginate' option does this by sending the `diff' output +through the `pr' program. Here is what the page header might look like +for `diff -lc lao tzu': + + 2002-02-22 14:20 diff -lc lao tzu Page 1 + + +File: diff.info, Node: diff Performance, Next: Comparing Three Files, Prev: Adjusting Output, Up: Top + +6 `diff' Performance Tradeoffs +****************************** + +GNU `diff' runs quite efficiently; however, in some circumstances you +can cause it to run faster or produce a more compact set of changes. + + One way to improve `diff' performance is to use hard or symbolic +links to files instead of copies. This improves performance because +`diff' normally does not need to read two hard or symbolic links to the +same file, since their contents must be identical. For example, +suppose you copy a large directory hierarchy, make a few changes to the +copy, and then often use `diff -r' to compare the original to the copy. +If the original files are read-only, you can greatly improve +performance by creating the copy using hard or symbolic links (e.g., +with GNU `cp -lR' or `cp -sR'). Before editing a file in the copy for +the first time, you should break the link and replace it with a regular +copy. + + You can also affect the performance of GNU `diff' by giving it +options that change the way it compares files. Performance has more +than one dimension. These options improve one aspect of performance at +the cost of another, or they improve performance in some cases while +hurting it in others. + + The way that GNU `diff' determines which lines have changed always +comes up with a near-minimal set of differences. Usually it is good +enough for practical purposes. If the `diff' output is large, you +might want `diff' to use a modified algorithm that sometimes produces a +smaller set of differences. The `-d' or `--minimal' option does this; +however, it can also cause `diff' to run more slowly than usual, so it +is not the default behavior. + + When the files you are comparing are large and have small groups of +changes scattered throughout them, you can use the +`--speed-large-files' option to make a different modification to the +algorithm that `diff' uses. If the input files have a constant small +density of changes, this option speeds up the comparisons without +changing the output. If not, `diff' might produce a larger set of +differences; however, the output will still be correct. + + Normally `diff' discards the prefix and suffix that is common to +both files before it attempts to find a minimal set of differences. +This makes `diff' run faster, but occasionally it may produce +non-minimal output. The `--horizon-lines=LINES' option prevents `diff' +from discarding the last LINES lines of the prefix and the first LINES +lines of the suffix. This gives `diff' further opportunities to find a +minimal output. + + Suppose a run of changed lines includes a sequence of lines at one +end and there is an identical sequence of lines just outside the other +end. The `diff' command is free to choose which identical sequence is +included in the hunk. In this case, `diff' normally shifts the hunk's +boundaries when this merges adjacent hunks, or shifts a hunk's lines +towards the end of the file. Merging hunks can make the output look +nicer in some cases. + + +File: diff.info, Node: Comparing Three Files, Next: diff3 Merging, Prev: diff Performance, Up: Top + +7 Comparing Three Files +*********************** + +Use the program `diff3' to compare three files and show any differences +among them. (`diff3' can also merge files; see *Note diff3 Merging::). + + The "normal" `diff3' output format shows each hunk of differences +without surrounding context. Hunks are labeled depending on whether +they are two-way or three-way, and lines are annotated by their +location in the input files. + + *Note Invoking diff3::, for more information on how to run `diff3'. + +* Menu: + +* Sample diff3 Input:: Sample `diff3' input for examples. +* Example diff3 Normal:: Sample output in the normal format. +* diff3 Hunks:: The format of normal output format. +* Detailed diff3 Normal:: A detailed description of normal output format. + + +File: diff.info, Node: Sample diff3 Input, Next: Example diff3 Normal, Up: Comparing Three Files + +7.1 A Third Sample Input File +============================= + +Here is a third sample file that will be used in examples to illustrate +the output of `diff3' and how various options can change it. The first +two files are the same that we used for `diff' (*note Sample diff +Input::). This is the third sample file, called `tao': + + The Way that can be told of is not the eternal Way; + The name that can be named is not the eternal name. + The Nameless is the origin of Heaven and Earth; + The named is the mother of all things. + + Therefore let there always be non-being, + so we may see their subtlety, + And let there always be being, + so we may see their result. + The two are the same, + But after they are produced, + they have different names. + + -- The Way of Lao-Tzu, tr. Wing-tsit Chan + + +File: diff.info, Node: Example diff3 Normal, Next: diff3 Hunks, Prev: Sample diff3 Input, Up: Comparing Three Files + +7.2 An Example of `diff3' Normal Format +======================================= + +Here is the output of the command `diff3 lao tzu tao' (*note Sample +diff3 Input::, for the complete contents of the files). Notice that it +shows only the lines that are different among the three files. + + ====2 + 1:1,2c + 3:1,2c + The Way that can be told of is not the eternal Way; + The name that can be named is not the eternal name. + 2:0a + ====1 + 1:4c + The Named is the mother of all things. + 2:2,3c + 3:4,5c + The named is the mother of all things. + + ====3 + 1:8c + 2:7c + so we may see their outcome. + 3:9c + so we may see their result. + ==== + 1:11a + 2:11,13c + They both may be called deep and profound. + Deeper and more profound, + The door of all subtleties! + 3:13,14c + + -- The Way of Lao-Tzu, tr. Wing-tsit Chan + + +File: diff.info, Node: Detailed diff3 Normal, Prev: diff3 Hunks, Up: Comparing Three Files + +7.3 Detailed Description of `diff3' Normal Format +================================================= + +Each hunk begins with a line marked `===='. Three-way hunks have plain +`====' lines, and two-way hunks have `1', `2', or `3' appended to +specify which of the three input files differ in that hunk. The hunks +contain copies of two or three sets of input lines each preceded by one +or two commands identifying where the lines came from. + + Normally, two spaces precede each copy of an input line to +distinguish it from the commands. But with the `-T' or `--initial-tab' +option, `diff3' uses a tab instead of two spaces; this lines up tabs +correctly. *Note Tabs::, for more information. + + Commands take the following forms: + +`FILE:La' + This hunk appears after line L of file FILE, and contains no lines + in that file. To edit this file to yield the other files, one + must append hunk lines taken from the other files. For example, + `1:11a' means that the hunk follows line 11 in the first file and + contains no lines from that file. + +`FILE:Rc' + This hunk contains the lines in the range R of file FILE. The + range R is a comma-separated pair of line numbers, or just one + number if the range is a singleton. To edit this file to yield the + other files, one must change the specified lines to be the lines + taken from the other files. For example, `2:11,13c' means that + the hunk contains lines 11 through 13 from the second file. + + If the last line in a set of input lines is incomplete (*note +Incomplete Lines::), it is distinguished on output from a full line by +a following line that starts with `\'. + + +File: diff.info, Node: diff3 Hunks, Next: Detailed diff3 Normal, Prev: Example diff3 Normal, Up: Comparing Three Files + +7.4 `diff3' Hunks +================= + +Groups of lines that differ in two or three of the input files are +called "diff3 hunks", by analogy with `diff' hunks (*note Hunks::). If +all three input files differ in a `diff3' hunk, the hunk is called a +"three-way hunk"; if just two input files differ, it is a "two-way +hunk". + + As with `diff', several solutions are possible. When comparing the +files `A', `B', and `C', `diff3' normally finds `diff3' hunks by +merging the two-way hunks output by the two commands `diff A B' and +`diff A C'. This does not necessarily minimize the size of the output, +but exceptions should be rare. + + For example, suppose `F' contains the three lines `a', `b', `f', `G' +contains the lines `g', `b', `g', and `H' contains the lines `a', `b', +`h'. `diff3 F G H' might output the following: + + ====2 + 1:1c + 3:1c + a + 2:1c + g + ==== + 1:3c + f + 2:3c + g + 3:3c + h + +because it found a two-way hunk containing `a' in the first and third +files and `g' in the second file, then the single line `b' common to +all three files, then a three-way hunk containing the last line of each +file. + + +File: diff.info, Node: diff3 Merging, Next: Interactive Merging, Prev: Comparing Three Files, Up: Top + +8 Merging From a Common Ancestor +******************************** + +When two people have made changes to copies of the same file, `diff3' +can produce a merged output that contains both sets of changes together +with warnings about conflicts. + + One might imagine programs with names like `diff4' and `diff5' to +compare more than three files simultaneously, but in practice the need +rarely arises. You can use `diff3' to merge three or more sets of +changes to a file by merging two change sets at a time. + + `diff3' can incorporate changes from two modified versions into a +common preceding version. This lets you merge the sets of changes +represented by the two newer files. Specify the common ancestor version +as the second argument and the two newer versions as the first and third +arguments, like this: + + diff3 MINE OLDER YOURS + +You can remember the order of the arguments by noting that they are in +alphabetical order. + + You can think of this as subtracting OLDER from YOURS and adding the +result to MINE, or as merging into MINE the changes that would turn +OLDER into YOURS. This merging is well-defined as long as MINE and +OLDER match in the neighborhood of each such change. This fails to be +true when all three input files differ or when only OLDER differs; we +call this a "conflict". When all three input files differ, we call the +conflict an "overlap". + + `diff3' gives you several ways to handle overlaps and conflicts. +You can omit overlaps or conflicts, or select only overlaps, or mark +conflicts with special `<<<<<<<' and `>>>>>>>' lines. + + `diff3' can output the merge results as an `ed' script that that can +be applied to the first file to yield the merged output. However, it +is usually better to have `diff3' generate the merged output directly; +this bypasses some problems with `ed'. + +* Menu: + +* Which Changes:: Selecting changes to incorporate. +* Marking Conflicts:: Marking conflicts. +* Bypassing ed:: Generating merged output directly. +* Merging Incomplete Lines:: How `diff3' merges incomplete lines. +* Saving the Changed File:: Emulating System V behavior. + + +File: diff.info, Node: Which Changes, Next: Marking Conflicts, Up: diff3 Merging + +8.1 Selecting Which Changes to Incorporate +========================================== + +You can select all unmerged changes from OLDER to YOURS for merging +into MINE with the `-e' or `--ed' option. You can select only the +nonoverlapping unmerged changes with `-3' or `--easy-only', and you can +select only the overlapping changes with `-x' or `--overlap-only'. + + The `-e', `-3' and `-x' options select only "unmerged changes", i.e. +changes where MINE and YOURS differ; they ignore changes from OLDER to +YOURS where MINE and YOURS are identical, because they assume that such +changes have already been merged. If this assumption is not a safe +one, you can use the `-A' or `--show-all' option (*note Marking +Conflicts::). + + Here is the output of the command `diff3' with each of these three +options (*note Sample diff3 Input::, for the complete contents of the +files). Notice that `-e' outputs the union of the disjoint sets of +changes output by `-3' and `-x'. + + Output of `diff3 -e lao tzu tao': + 11a + + -- The Way of Lao-Tzu, tr. Wing-tsit Chan + . + 8c + so we may see their result. + . + + Output of `diff3 -3 lao tzu tao': + 8c + so we may see their result. + . + + Output of `diff3 -x lao tzu tao': + 11a + + -- The Way of Lao-Tzu, tr. Wing-tsit Chan + . + + +File: diff.info, Node: Marking Conflicts, Next: Bypassing ed, Prev: Which Changes, Up: diff3 Merging + +8.2 Marking Conflicts +===================== + +`diff3' can mark conflicts in the merged output by bracketing them with +special marker lines. A conflict that comes from two files A and B is +marked as follows: + + <<<<<<< A + lines from A + ======= + lines from B + >>>>>>> B + + A conflict that comes from three files A, B and C is marked as +follows: + + <<<<<<< A + lines from A + ||||||| B + lines from B + ======= + lines from C + >>>>>>> C + + The `-A' or `--show-all' option acts like the `-e' option, except +that it brackets conflicts, and it outputs all changes from OLDER to +YOURS, not just the unmerged changes. Thus, given the sample input +files (*note Sample diff3 Input::), `diff3 -A lao tzu tao' puts +brackets around the conflict where only `tzu' differs: + + <<<<<<< tzu + ======= + The Way that can be told of is not the eternal Way; + The name that can be named is not the eternal name. + >>>>>>> tao + + And it outputs the three-way conflict as follows: + + <<<<<<< lao + ||||||| tzu + They both may be called deep and profound. + Deeper and more profound, + The door of all subtleties! + ======= + + -- The Way of Lao-Tzu, tr. Wing-tsit Chan + >>>>>>> tao + + The `-E' or `--show-overlap' option outputs less information than +the `-A' or `--show-all' option, because it outputs only unmerged +changes, and it never outputs the contents of the second file. Thus +the `-E' option acts like the `-e' option, except that it brackets the +first and third files from three-way overlapping changes. Similarly, +`-X' acts like `-x', except it brackets all its (necessarily +overlapping) changes. For example, for the three-way overlapping +change above, the `-E' and `-X' options output the following: + + <<<<<<< lao + ======= + + -- The Way of Lao-Tzu, tr. Wing-tsit Chan + >>>>>>> tao + + If you are comparing files that have meaningless or uninformative +names, you can use the `--label=LABEL' option to show alternate names +in the `<<<<<<<', `|||||||' and `>>>>>>>' brackets. This option can be +given up to three times, once for each input file. Thus `diff3 -A +--label X --label Y --label Z A B C' acts like `diff3 -A A B C', except +that the output looks like it came from files named `X', `Y' and `Z' +rather than from files named `A', `B' and `C'. + + +File: diff.info, Node: Bypassing ed, Next: Merging Incomplete Lines, Prev: Marking Conflicts, Up: diff3 Merging + +8.3 Generating the Merged Output Directly +========================================= + +With the `-m' or `--merge' option, `diff3' outputs the merged file +directly. This is more efficient than using `ed' to generate it, and +works even with non-text files that `ed' would reject. If you specify +`-m' without an `ed' script option, `-A' is assumed. + + For example, the command `diff3 -m lao tzu tao' (*note Sample diff3 +Input:: for a copy of the input files) would output the following: + + <<<<<<< tzu + ======= + The Way that can be told of is not the eternal Way; + The name that can be named is not the eternal name. + >>>>>>> tao + The Nameless is the origin of Heaven and Earth; + The Named is the mother of all things. + Therefore let there always be non-being, + so we may see their subtlety, + And let there always be being, + so we may see their result. + The two are the same, + But after they are produced, + they have different names. + <<<<<<< lao + ||||||| tzu + They both may be called deep and profound. + Deeper and more profound, + The door of all subtleties! + ======= + + -- The Way of Lao-Tzu, tr. Wing-tsit Chan + >>>>>>> tao + + +File: diff.info, Node: Merging Incomplete Lines, Next: Saving the Changed File, Prev: Bypassing ed, Up: diff3 Merging + +8.4 How `diff3' Merges Incomplete Lines +======================================= + +With `-m', incomplete lines (*note Incomplete Lines::) are simply +copied to the output as they are found; if the merged output ends in an +conflict and one of the input files ends in an incomplete line, +succeeding `|||||||', `=======' or `>>>>>>>' brackets appear somewhere +other than the start of a line because they are appended to the +incomplete line. + + Without `-m', if an `ed' script option is specified and an +incomplete line is found, `diff3' generates a warning and acts as if a +newline had been present. + + +File: diff.info, Node: Saving the Changed File, Prev: Merging Incomplete Lines, Up: diff3 Merging + +8.5 Saving the Changed File +=========================== + +Traditional Unix `diff3' generates an `ed' script without the trailing +`w' and `q' commands that save the changes. System V `diff3' generates +these extra commands. GNU `diff3' normally behaves like traditional +Unix `diff3', but with the `-i' option it behaves like System V `diff3' +and appends the `w' and `q' commands. + + The `-i' option requires one of the `ed' script options `-AeExX3', +and is incompatible with the merged output option `-m'. + + +File: diff.info, Node: Interactive Merging, Next: Merging with patch, Prev: diff3 Merging, Up: Top + +9 Interactive Merging with `sdiff' +********************************** + +With `sdiff', you can merge two files interactively based on a +side-by-side `-y' format comparison (*note Side by Side::). Use `-o +FILE' or `--output=FILE' to specify where to put the merged text. +*Note Invoking sdiff::, for more details on the options to `sdiff'. + + Another way to merge files interactively is to use the Emacs Lisp +package `emerge'. *Note emerge: (emacs)emerge, for more information. + +* Menu: + +* sdiff Option Summary:: Summary of `sdiff' options. +* Merge Commands:: Merging two files interactively. + + +File: diff.info, Node: sdiff Option Summary, Next: Merge Commands, Up: Interactive Merging + +9.1 Specifying `diff' Options to `sdiff' +======================================== + +The following `sdiff' options have the same meaning as for `diff'. +*Note diff Options::, for the use of these options. + + -a -b -d -i -t -v + -B -E -I REGEXP + + --expand-tabs + --ignore-blank-lines --ignore-case + --ignore-matching-lines=REGEXP --ignore-space-change + --ignore-tab-expansion + --left-column --minimal --speed-large-files + --strip-trailing-cr --suppress-common-lines + --tabsize=COLUMNS --text --version --width=COLUMNS + + For historical reasons, `sdiff' has alternate names for some +options. The `-l' option is equivalent to the `--left-column' option, +and similarly `-s' is equivalent to `--suppress-common-lines'. The +meaning of the `sdiff' `-w' and `-W' options is interchanged from that +of `diff': with `sdiff', `-w COLUMNS' is equivalent to +`--width=COLUMNS', and `-W' is equivalent to `--ignore-all-space'. +`sdiff' without the `-o' option is equivalent to `diff' with the `-y' +or `--side-by-side' option (*note Side by Side::). + + +File: diff.info, Node: Merge Commands, Prev: sdiff Option Summary, Up: Interactive Merging + +9.2 Merge Commands +================== + +Groups of common lines, with a blank gutter, are copied from the first +file to the output. After each group of differing lines, `sdiff' +prompts with `%' and pauses, waiting for one of the following commands. +Follow each command with . + +`e' + Discard both versions. Invoke a text editor on an empty temporary + file, then copy the resulting file to the output. + +`eb' + Concatenate the two versions, edit the result in a temporary file, + then copy the edited result to the output. + +`ed' + Like `eb', except precede each version with a header that shows + what file and lines the version came from. + +`el' + Edit a copy of the left version, then copy the result to the + output. + +`er' + Edit a copy of the right version, then copy the result to the + output. + +`l' + Copy the left version to the output. + +`q' + Quit. + +`r' + Copy the right version to the output. + +`s' + Silently copy common lines. + +`v' + Verbosely copy common lines. This is the default. + + The text editor invoked is specified by the `EDITOR' environment +variable if it is set. The default is system-dependent. + + +File: diff.info, Node: Merging with patch, Next: Making Patches, Prev: Interactive Merging, Up: Top + +10 Merging with `patch' +*********************** + +`patch' takes comparison output produced by `diff' and applies the +differences to a copy of the original file, producing a patched +version. With `patch', you can distribute just the changes to a set of +files instead of distributing the entire file set; your correspondents +can apply `patch' to update their copy of the files with your changes. +`patch' automatically determines the diff format, skips any leading or +trailing headers, and uses the headers to determine which file to +patch. This lets your correspondents feed a mail message containing a +difference listing directly to `patch'. + + `patch' detects and warns about common problems like forward +patches. It saves any patches that it could not apply. It can also +maintain a `patchlevel.h' file to ensure that your correspondents apply +diffs in the proper order. + + `patch' accepts a series of diffs in its standard input, usually +separated by headers that specify which file to patch. It applies +`diff' hunks (*note Hunks::) one by one. If a hunk does not exactly +match the original file, `patch' uses heuristics to try to patch the +file as well as it can. If no approximate match can be found, `patch' +rejects the hunk and skips to the next hunk. `patch' normally replaces +each file F with its new version, putting reject hunks (if any) into +`F.rej'. + + *Note Invoking patch::, for detailed information on the options to +`patch'. + +* Menu: + +* patch Input:: Selecting the type of `patch' input. +* Revision Control:: Getting files from RCS, SCCS, etc. +* Imperfect:: Dealing with imperfect patches. +* Creating and Removing:: Creating and removing files with a patch. +* Patching Time Stamps:: Updating time stamps on patched files. +* Multiple Patches:: Handling multiple patches in a file. +* patch Directories:: Changing directory and stripping directories. +* Backups:: Whether backup files are made. +* Backup Names:: Backup file names. +* Reject Names:: Reject file names. +* patch Messages:: Messages and questions `patch' can produce. +* patch and POSIX:: Conformance to the POSIX standard. +* patch and Tradition:: GNU versus traditional `patch'. + + +File: diff.info, Node: patch Input, Next: Revision Control, Up: Merging with patch + +10.1 Selecting the `patch' Input Format +======================================= + +`patch' normally determines which `diff' format the patch file uses by +examining its contents. For patch files that contain particularly +confusing leading text, you might need to use one of the following +options to force `patch' to interpret the patch file as a certain +format of diff. The output formats listed here are the only ones that +`patch' can understand. + +`-c' +`--context' + context diff. + +`-e' +`--ed' + `ed' script. + +`-n' +`--normal' + normal diff. + +`-u' +`--unified' + unified diff. + + +File: diff.info, Node: Revision Control, Next: Imperfect, Prev: patch Input, Up: Merging with patch + +10.2 Revision Control +===================== + +If a nonexistent input file is under a revision control system +supported by `patch', `patch' normally asks the user whether to get (or +check out) the file from the revision control system. Patch currently +supports RCS, ClearCase and SCCS. Under RCS and SCCS, `patch' also +asks when the input file is read-only and matches the default version +in the revision control system. + + The `-g NUM' or `--get=NUM' option affects access to files under +supported revision control systems. If NUM is positive, `patch' gets +the file without asking the user; if zero, `patch' neither asks the +user nor gets the file; and if negative, `patch' asks the user before +getting the file. The default value of NUM is given by the value of the +`PATCH_GET' environment variable if it is set; if not, the default +value is zero if `patch' is conforming to POSIX, negative otherwise. +*Note patch and POSIX::. + + The choice of revision control system is unaffected by the +`VERSION_CONTROL' environment variable (*note Backup Names::). + + +File: diff.info, Node: Imperfect, Next: Creating and Removing, Prev: Revision Control, Up: Merging with patch + +10.3 Applying Imperfect Patches +=============================== + +`patch' tries to skip any leading text in the patch file, apply the +diff, and then skip any trailing text. Thus you can feed a mail +message directly to `patch', and it should work. If the entire diff is +indented by a constant amount of white space, `patch' automatically +ignores the indentation. If a context diff contains trailing carriage +return on each line, `patch' automatically ignores the carriage return. +If a context diff has been encapsulated by prepending `- ' to lines +beginning with `-' as per Internet RFC 934 +(ftp://ftp.isi.edu/in-notes/rfc934.txt), `patch' automatically +unencapsulates the input. + + However, certain other types of imperfect input require user +intervention or testing. + +* Menu: + +* Changed White Space:: When tabs and spaces don't match exactly. +* Reversed Patches:: Applying reversed patches correctly. +* Inexact:: Helping `patch' find close matches. +* Dry Runs:: Predicting what `patch' will do. + + +File: diff.info, Node: Changed White Space, Next: Reversed Patches, Up: Imperfect + +10.3.1 Applying Patches with Changed White Space +------------------------------------------------ + +Sometimes mailers, editors, or other programs change spaces into tabs, +or vice versa. If this happens to a patch file or an input file, the +files might look the same, but `patch' will not be able to match them +properly. If this problem occurs, use the `-l' or +`--ignore-white-space' option, which makes `patch' compare blank +characters (i.e. spaces and tabs) loosely so that any nonempty sequence +of blanks in the patch file matches any nonempty sequence of blanks in +the input files. Non-blank characters must still match exactly. Each +line of the context must still match a line in the input file. + + +File: diff.info, Node: Reversed Patches, Next: Inexact, Prev: Changed White Space, Up: Imperfect + +10.3.2 Applying Reversed Patches +-------------------------------- + +Sometimes people run `diff' with the new file first instead of second. +This creates a diff that is "reversed". To apply such patches, give +`patch' the `-R' or `--reverse' option. `patch' then attempts to swap +each hunk around before applying it. Rejects come out in the swapped +format. + + Often `patch' can guess that the patch is reversed. If the first +hunk of a patch fails, `patch' reverses the hunk to see if it can apply +it that way. If it can, `patch' asks you if you want to have the `-R' +option set; if it can't, `patch' continues to apply the patch normally. +This method cannot detect a reversed patch if it is a normal diff and +the first command is an append (which should have been a delete) since +appends always succeed, because a null context matches anywhere. But +most patches add or change lines rather than delete them, so most +reversed normal diffs begin with a delete, which fails, and `patch' +notices. + + If you apply a patch that you have already applied, `patch' thinks +it is a reversed patch and offers to un-apply the patch. This could be +construed as a feature. If you did this inadvertently and you don't +want to un-apply the patch, just answer `n' to this offer and to the +subsequent "apply anyway" question--or type `C-c' to kill the `patch' +process. + + +File: diff.info, Node: Inexact, Next: Dry Runs, Prev: Reversed Patches, Up: Imperfect + +10.3.3 Helping `patch' Find Inexact Matches +------------------------------------------- + +For context diffs, and to a lesser extent normal diffs, `patch' can +detect when the line numbers mentioned in the patch are incorrect, and +it attempts to find the correct place to apply each hunk of the patch. +As a first guess, it takes the line number mentioned in the hunk, plus +or minus any offset used in applying the previous hunk. If that is not +the correct place, `patch' scans both forward and backward for a set of +lines matching the context given in the hunk. + + First `patch' looks for a place where all lines of the context +match. If it cannot find such a place, and it is reading a context or +unified diff, and the maximum fuzz factor is set to 1 or more, then +`patch' makes another scan, ignoring the first and last line of +context. If that fails, and the maximum fuzz factor is set to 2 or +more, it makes another scan, ignoring the first two and last two lines +of context are ignored. It continues similarly if the maximum fuzz +factor is larger. + + The `-F LINES' or `--fuzz=LINES' option sets the maximum fuzz factor +to LINES. This option only applies to context and unified diffs; it +ignores up to LINES lines while looking for the place to install a +hunk. Note that a larger fuzz factor increases the odds of making a +faulty patch. The default fuzz factor is 2; there is no point to +setting it to more than the number of lines of context in the diff, +ordinarily 3. + + If `patch' cannot find a place to install a hunk of the patch, it +writes the hunk out to a reject file (*note Reject Names::, for +information on how reject files are named). It writes out rejected +hunks in context format no matter what form the input patch is in. If +the input is a normal or `ed' diff, many of the contexts are simply +null. The line numbers on the hunks in the reject file may be +different from those in the patch file: they show the approximate +location where `patch' thinks the failed hunks belong in the new file +rather than in the old one. + + If the `--verbose' option is given, then as it completes each hunk +`patch' tells you whether the hunk succeeded or failed, and if it +failed, on which line (in the new file) `patch' thinks the hunk should +go. If this is different from the line number specified in the diff, +it tells you the offset. A single large offset _may_ indicate that +`patch' installed a hunk in the wrong place. `patch' also tells you if +it used a fuzz factor to make the match, in which case you should also +be slightly suspicious. + + `patch' cannot tell if the line numbers are off in an `ed' script, +and can only detect wrong line numbers in a normal diff when it finds a +change or delete command. It may have the same problem with a context +diff using a fuzz factor equal to or greater than the number of lines +of context shown in the diff (typically 3). In these cases, you should +probably look at a context diff between your original and patched input +files to see if the changes make sense. Compiling without errors is a +pretty good indication that the patch worked, but not a guarantee. + + A patch against an empty file applies to a nonexistent file, and vice +versa. *Note Creating and Removing::. + + `patch' usually produces the correct results, even when it must make +many guesses. However, the results are guaranteed only when the patch +is applied to an exact copy of the file that the patch was generated +from. + + +File: diff.info, Node: Dry Runs, Prev: Inexact, Up: Imperfect + +10.3.4 Predicting what `patch' will do +-------------------------------------- + +It may not be obvious in advance what `patch' will do with a +complicated or poorly formatted patch. If you are concerned that the +input might cause `patch' to modify the wrong files, you can use the +`--dry-run' option, which causes `patch' to print the results of +applying patches without actually changing any files. You can then +inspect the diagnostics generated by the dry run to see whether `patch' +will modify the files that you expect. If the patch does not do what +you want, you can modify the patch (or the other options to `patch') +and try another dry run. Once you are satisfied with the proposed +patch you can apply it by invoking `patch' as before, but this time +without the `--dry-run' option. + + +File: diff.info, Node: Creating and Removing, Next: Patching Time Stamps, Prev: Imperfect, Up: Merging with patch + +10.4 Creating and Removing Files +================================ + +Sometimes when comparing two directories, a file may exist in one +directory but not the other. If you give `diff' the `-N' or +`--new-file' option, or if you supply an old or new file that is named +`/dev/null' or is empty and is dated the Epoch (1970-01-01 00:00:00 +UTC), `diff' outputs a patch that adds or deletes the contents of this +file. When given such a patch, `patch' normally creates a new file or +removes the old file. However, when conforming to POSIX (*note patch +and POSIX::), `patch' does not remove the old file, but leaves it empty. +The `-E' or `--remove-empty-files' option causes `patch' to remove +output files that are empty after applying a patch, even if the patch +does not appear to be one that removed the file. + + If the patch appears to create a file that already exists, `patch' +asks for confirmation before applying the patch. + + +File: diff.info, Node: Patching Time Stamps, Next: Multiple Patches, Prev: Creating and Removing, Up: Merging with patch + +10.5 Updating Time Stamps on Patched Files +========================================== + +When `patch' updates a file, it normally sets the file's last-modified +time stamp to the current time of day. If you are using `patch' to +track a software distribution, this can cause `make' to incorrectly +conclude that a patched file is out of date. For example, if +`syntax.c' depends on `syntax.y', and `patch' updates `syntax.c' and +then `syntax.y', then `syntax.c' will normally appear to be out of date +with respect to `syntax.y' even though its contents are actually up to +date. + + The `-Z' or `--set-utc' option causes `patch' to set a patched +file's modification and access times to the time stamps given in +context diff headers. If the context diff headers do not specify a +time zone, they are assumed to use Coordinated Universal Time (UTC, +often known as GMT). + + The `-T' or `--set-time' option acts like `-Z' or `--set-utc', +except that it assumes that the context diff headers' time stamps use +local time instead of UTC. This option is not recommended, because +patches using local time cannot easily be used by people in other time +zones, and because local time stamps are ambiguous when local clocks +move backwards during daylight-saving time adjustments. If the context +diff headers specify a time zone, this option is equivalent to `-Z' or +`--set-utc'. + + `patch' normally refrains from setting a file's time stamps if the +file's original last-modified time stamp does not match the time given +in the diff header, of if the file's contents do not exactly match the +patch. However, if the `-f' or `--force' option is given, the file's +time stamps are set regardless. + + Due to the limitations of the current `diff' format, `patch' cannot +update the times of files whose contents have not changed. Also, if +you set file time stamps to values other than the current time of day, +you should also remove (e.g., with `make clean') all files that depend +on the patched files, so that later invocations of `make' do not get +confused by the patched files' times. + + +File: diff.info, Node: Multiple Patches, Next: patch Directories, Prev: Patching Time Stamps, Up: Merging with patch + +10.6 Multiple Patches in a File +=============================== + +If the patch file contains more than one patch, and if you do not +specify an input file on the command line, `patch' tries to apply each +patch as if they came from separate patch files. This means that it +determines the name of the file to patch for each patch, and that it +examines the leading text before each patch for file names and +prerequisite revision level (*note Making Patches::, for more on that +topic). + + `patch' uses the following rules to intuit a file name from the +leading text before a patch. First, `patch' takes an ordered list of +candidate file names as follows: + + * If the header is that of a context diff, `patch' takes the old and + new file names in the header. A name is ignored if it does not + have enough slashes to satisfy the `-pNUM' or `--strip=NUM' + option. The name `/dev/null' is also ignored. + + * If there is an `Index:' line in the leading garbage and if either + the old and new names are both absent or if `patch' is conforming + to POSIX, `patch' takes the name in the `Index:' line. + + * For the purpose of the following rules, the candidate file names + are considered to be in the order (old, new, index), regardless of + the order that they appear in the header. + +Then `patch' selects a file name from the candidate list as follows: + + * If some of the named files exist, `patch' selects the first name + if conforming to POSIX, and the best name otherwise. + + * If `patch' is not ignoring RCS, ClearCase, and SCCS (*note + Revision Control::), and no named files exist but an RCS, + ClearCase, or SCCS master is found, `patch' selects the first + named file with an RCS, ClearCase, or SCCS master. + + * If no named files exist, no RCS, ClearCase, or SCCS master was + found, some names are given, `patch' is not conforming to POSIX, + and the patch appears to create a file, `patch' selects the best + name requiring the creation of the fewest directories. + + * If no file name results from the above heuristics, you are asked + for the name of the file to patch, and `patch' selects that name. + + To determine the "best" of a nonempty list of file names, `patch' +first takes all the names with the fewest path name components; of +those, it then takes all the names with the shortest basename; of +those, it then takes all the shortest names; finally, it takes the +first remaining name. + + *Note patch and POSIX::, to see whether `patch' is conforming to +POSIX. + + +File: diff.info, Node: patch Directories, Next: Backups, Prev: Multiple Patches, Up: Merging with patch + +10.7 Applying Patches in Other Directories +========================================== + +The `-d DIRECTORY' or `--directory=DIRECTORY' option to `patch' makes +directory DIRECTORY the current directory for interpreting both file +names in the patch file, and file names given as arguments to other +options (such as `-B' and `-o'). For example, while in a mail reading +program, you can patch a file in the `/usr/src/emacs' directory +directly from a message containing the patch like this: + + | patch -d /usr/src/emacs + + Sometimes the file names given in a patch contain leading +directories, but you keep your files in a directory different from the +one given in the patch. In those cases, you can use the `-pNUMBER' or +`--strip=NUMBER' option to set the file name strip count to NUMBER. +The strip count tells `patch' how many slashes, along with the directory +names between them, to strip from the front of file names. A sequence +of one or more adjacent slashes is counted as a single slash. By +default, `patch' strips off all leading directories, leaving just the +base file names. + + For example, suppose the file name in the patch file is +`/gnu/src/emacs/etc/NEWS'. Using `-p0' gives the entire file name +unmodified, `-p1' gives `gnu/src/emacs/etc/NEWS' (no leading slash), +`-p4' gives `etc/NEWS', and not specifying `-p' at all gives `NEWS'. + + `patch' looks for each file (after any slashes have been stripped) +in the current directory, or if you used the `-d DIRECTORY' option, in +that directory. + + +File: diff.info, Node: Backups, Next: Backup Names, Prev: patch Directories, Up: Merging with patch + +10.8 Backup Files +================= + +Normally, `patch' creates a backup file if the patch does not exactly +match the original input file, because in that case the original data +might not be recovered if you undo the patch with `patch -R' (*note +Reversed Patches::). However, when conforming to POSIX, `patch' does +not create backup files by default. *Note patch and POSIX::. + + The `-b' or `--backup' option causes `patch' to make a backup file +regardless of whether the patch matches the original input. The +`--backup-if-mismatch' option causes `patch' to create backup files for +mismatches files; this is the default when not conforming to POSIX. The +`--no-backup-if-mismatch' option causes `patch' to not create backup +files, even for mismatched patches; this is the default when conforming +to POSIX. + + When backing up a file that does not exist, an empty, unreadable +backup file is created as a placeholder to represent the nonexistent +file. + + +File: diff.info, Node: Backup Names, Next: Reject Names, Prev: Backups, Up: Merging with patch + +10.9 Backup File Names +====================== + +Normally, `patch' renames an original input file into a backup file by +appending to its name the extension `.orig', or `~' if using `.orig' +would make the backup file name too long.(1) The `-z BACKUP-SUFFIX' or +`--suffix=BACKUP-SUFFIX' option causes `patch' to use BACKUP-SUFFIX as +the backup extension instead. + + Alternately, you can specify the extension for backup files with the +`SIMPLE_BACKUP_SUFFIX' environment variable, which the options override. + + `patch' can also create numbered backup files the way GNU Emacs +does. With this method, instead of having a single backup of each +file, `patch' makes a new backup file name each time it patches a file. +For example, the backups of a file named `sink' would be called, +successively, `sink.~1~', `sink.~2~', `sink.~3~', etc. + + The `-V BACKUP-STYLE' or `--version-control=BACKUP-STYLE' option +takes as an argument a method for creating backup file names. You can +alternately control the type of backups that `patch' makes with the +`PATCH_VERSION_CONTROL' environment variable, which the `-V' option +overrides. If `PATCH_VERSION_CONTROL' is not set, the +`VERSION_CONTROL' environment variable is used instead. Please note +that these options and variables control backup file names; they do not +affect the choice of revision control system (*note Revision Control::). + + The values of these environment variables and the argument to the +`-V' option are like the GNU Emacs `version-control' variable (*note +Backup Names: (emacs)Backup Names, for more information on backup +versions in Emacs). They also recognize synonyms that are more +descriptive. The valid values are listed below; unique abbreviations +are acceptable. + +`t' +`numbered' + Always make numbered backups. + +`nil' +`existing' + Make numbered backups of files that already have them, simple + backups of the others. This is the default. + +`never' +`simple' + Always make simple backups. + + You can also tell `patch' to prepend a prefix, such as a directory +name, to produce backup file names. The `-B PREFIX' or +`--prefix=PREFIX' option makes backup files by prepending PREFIX to +them. The `-Y PREFIX' or `--basename-prefix=PREFIX' prepends PREFIX to +the last file name component of backup file names instead; for example, +`-Y ~' causes the backup name for `dir/file.c' to be `dir/~file.c'. If +you use either of these prefix options, the suffix-based options are +ignored. + + If you specify the output file with the `-o' option, that file is +the one that is backed up, not the input file. + + Options that affect the names of backup files do not affect whether +backups are made. For example, if you specify the +`--no-backup-if-mismatch' option, none of the options described in this +section have any affect, because no backups are made. + + ---------- Footnotes ---------- + + (1) A coding error in GNU `patch' version 2.5.4 causes it to always +use `~', but this should be fixed in the next release. + + +File: diff.info, Node: Reject Names, Next: patch Messages, Prev: Backup Names, Up: Merging with patch + +10.10 Reject File Names +======================= + +The names for reject files (files containing patches that `patch' could +not find a place to apply) are normally the name of the output file +with `.rej' appended (or `#' if using `.rej' would make the backup file +name too long). + + Alternatively, you can tell `patch' to place all of the rejected +patches in a single file. The `-r REJECT-FILE' or +`--reject-file=REJECT-FILE' option uses REJECT-FILE as the reject file +name. + + +File: diff.info, Node: patch Messages, Next: patch and POSIX, Prev: Reject Names, Up: Merging with patch + +10.11 Messages and Questions from `patch' +========================================= + +`patch' can produce a variety of messages, especially if it has trouble +decoding its input. In a few situations where it's not sure how to +proceed, `patch' normally prompts you for more information from the +keyboard. There are options to produce more or fewer messages, to have +it not ask for keyboard input, and to affect the way that file names +are quoted in messages. + +* Menu: + +* More or Fewer Messages:: Controlling the verbosity of `patch'. +* patch and Keyboard Input:: Inhibiting keyboard input. +* patch Quoting Style:: Quoting file names in diagnostics. + + `patch' exits with status 0 if all hunks are applied successfully, 1 +if some hunks cannot be applied, and 2 if there is more serious trouble. +When applying a set of patches in a loop, you should check the exit +status, so you don't apply a later patch to a partially patched file. + + +File: diff.info, Node: More or Fewer Messages, Next: patch and Keyboard Input, Up: patch Messages + +10.11.1 Controlling the Verbosity of `patch' +-------------------------------------------- + +You can cause `patch' to produce more messages by using the `--verbose' +option. For example, when you give this option, the message `Hmm...' +indicates that `patch' is reading text in the patch file, attempting to +determine whether there is a patch in that text, and if so, what kind +of patch it is. + + You can inhibit all terminal output from `patch', unless an error +occurs, by using the `-s', `--quiet', or `--silent' option. + + +File: diff.info, Node: patch and Keyboard Input, Next: patch Quoting Style, Prev: More or Fewer Messages, Up: patch Messages + +10.11.2 Inhibiting Keyboard Input +--------------------------------- + +There are two ways you can prevent `patch' from asking you any +questions. The `-f' or `--force' option assumes that you know what you +are doing. It causes `patch' to do the following: + + * Skip patches that do not contain file names in their headers. + + * Patch files even though they have the wrong version for the + `Prereq:' line in the patch; + + * Assume that patches are not reversed even if they look like they + are. + +The `-t' or `--batch' option is similar to `-f', in that it suppresses +questions, but it makes somewhat different assumptions: + + * Skip patches that do not contain file names in their headers (the + same as `-f'). + + * Skip patches for which the file has the wrong version for the + `Prereq:' line in the patch; + + * Assume that patches are reversed if they look like they are. + + +File: diff.info, Node: patch Quoting Style, Prev: patch and Keyboard Input, Up: patch Messages + +10.11.3 `patch' Quoting Style +----------------------------- + +When `patch' outputs a file name in a diagnostic message, it can format +the name in any of several ways. This can be useful to output file +names unambiguously, even if they contain punctuation or special +characters like newlines. The `--quoting-style=WORD' option controls +how names are output. The WORD should be one of the following: + +`literal' + Output names as-is. + +`shell' + Quote names for the shell if they contain shell metacharacters or + would cause ambiguous output. + +`shell-always' + Quote names for the shell, even if they would normally not require + quoting. + +`c' + Quote names as for a C language string. + +`escape' + Quote as with `c' except omit the surrounding double-quote + characters. + + You can specify the default value of the `--quoting-style' option +with the environment variable `QUOTING_STYLE'. If that environment +variable is not set, the default value is `shell', but this default may +change in a future version of `patch'. + + +File: diff.info, Node: patch and POSIX, Next: patch and Tradition, Prev: patch Messages, Up: Merging with patch + +10.12 `patch' and the POSIX Standard +==================================== + +If you specify the `--posix' option, or set the `POSIXLY_CORRECT' +environment variable, `patch' conforms more strictly to the POSIX +standard, as follows: + + * Take the first existing file from the list (old, new, index) when + intuiting file names from diff headers. *Note Multiple Patches::. + + * Do not remove files that are removed by a diff. *Note Creating + and Removing::. + + * Do not ask whether to get files from RCS, ClearCase, or SCCS. + *Note Revision Control::. + + * Require that all options precede the files in the command line. + + * Do not backup files, even when there is a mismatch. *Note + Backups::. + + + +File: diff.info, Node: patch and Tradition, Prev: patch and POSIX, Up: Merging with patch + +10.13 GNU `patch' and Traditional `patch' +========================================= + +The current version of GNU `patch' normally follows the POSIX standard. +*Note patch and POSIX::, for the few exceptions to this general rule. + + Unfortunately, POSIX redefined the behavior of `patch' in several +important ways. You should be aware of the following differences if +you must interoperate with traditional `patch', or with GNU `patch' +version 2.1 and earlier. + + * In traditional `patch', the `-p' option's operand was optional, + and a bare `-p' was equivalent to `-p0'. The `-p' option now + requires an operand, and `-p 0' is now equivalent to `-p0'. For + maximum compatibility, use options like `-p0' and `-p1'. + + Also, traditional `patch' simply counted slashes when stripping + path prefixes; `patch' now counts pathname components. That is, a + sequence of one or more adjacent slashes now counts as a single + slash. For maximum portability, avoid sending patches containing + `//' in file names. + + * In traditional `patch', backups were enabled by default. This + behavior is now enabled with the `-b' or `--backup' option. + + Conversely, in POSIX `patch', backups are never made, even when + there is a mismatch. In GNU `patch', this behavior is enabled + with the `--no-backup-if-mismatch' option, or by conforming to + POSIX. + + The `-b SUFFIX' option of traditional `patch' is equivalent to the + `-b -z SUFFIX' options of GNU `patch'. + + * Traditional `patch' used a complicated (and incompletely + documented) method to intuit the name of the file to be patched + from the patch header. This method did not conform to POSIX, and + had a few gotchas. Now `patch' uses a different, equally + complicated (but better documented) method that is optionally + POSIX-conforming; we hope it has fewer gotchas. The two methods + are compatible if the file names in the context diff header and the + `Index:' line are all identical after prefix-stripping. Your + patch is normally compatible if each header's file names all + contain the same number of slashes. + + * When traditional `patch' asked the user a question, it sent the + question to standard error and looked for an answer from the first + file in the following list that was a terminal: standard error, + standard output, `/dev/tty', and standard input. Now `patch' + sends questions to standard output and gets answers from + `/dev/tty'. Defaults for some answers have been changed so that + `patch' never goes into an infinite loop when using default + answers. + + * Traditional `patch' exited with a status value that counted the + number of bad hunks, or with status 1 if there was real trouble. + Now `patch' exits with status 1 if some hunks failed, or with 2 if + there was real trouble. + + * Limit yourself to the following options when sending instructions + meant to be executed by anyone running GNU `patch', traditional + `patch', or a `patch' that conforms to POSIX. Spaces are + significant in the following list, and operands are required. + + `-c' + `-d DIR' + `-D DEFINE' + `-e' + `-l' + `-n' + `-N' + `-o OUTFILE' + `-pNUM' + `-R' + `-r REJECTFILE' + + + +File: diff.info, Node: Making Patches, Next: Invoking cmp, Prev: Merging with patch, Up: Top + +11 Tips for Making and Using Patches +************************************ + +Use some common sense when making and using patches. For example, when +sending bug fixes to a program's maintainer, send several small +patches, one per independent subject, instead of one large, +harder-to-digest patch that covers all the subjects. + + Here are some other things you should keep in mind if you are going +to distribute patches for updating a software package. + +* Menu: + +* Tips for Patch Producers:: Advice for making patches. +* Tips for Patch Consumers:: Advice for using patches. +* Avoiding Common Mistakes:: Avoiding common mistakes when using `patch'. +* Generating Smaller Patches:: How to generate smaller patches. + + +File: diff.info, Node: Tips for Patch Producers, Next: Tips for Patch Consumers, Up: Making Patches + +11.1 Tips for Patch Producers +============================= + +To create a patch that changes an older version of a package into a +newer version, first make a copy of the older and newer versions in +adjacent subdirectories. It is common to do that by unpacking `tar' +archives of the two versions. + + To generate the patch, use the command `diff -Naur OLD NEW' where +OLD and NEW identify the old and new directories. The names OLD and +NEW should not contain any slashes. The `-N' option lets the patch +create and remove files; `-a' lets the patch update non-text files; `-u' +generates useful time stamps and enough context; and `-r' lets the +patch update subdirectories. Here is an example command, using Bourne +shell syntax: + + diff -Naur gcc-3.0.3 gcc-3.0.4 + + Tell your recipients how to apply the patches. This should include +which working directory to use, and which `patch' options to use; the +option `-p1' is recommended. Test your procedure by pretending to be a +recipient and applying your patches to a copy of the original files. + + *Note Avoiding Common Mistakes::, for how to avoid common mistakes +when generating a patch. + + +File: diff.info, Node: Tips for Patch Consumers, Next: Avoiding Common Mistakes, Prev: Tips for Patch Producers, Up: Making Patches + +11.2 Tips for Patch Consumers +============================= + +A patch producer should tell recipients how to apply the patches, so +the first rule of thumb for a patch consumer is to follow the +instructions supplied with the patch. + + GNU `diff' can analyze files with arbitrarily long lines and files +that end in incomplete lines. However, older versions of `patch' +cannot patch such files. If you are having trouble applying such +patches, try upgrading to a recent version of GNU `patch'. + + +File: diff.info, Node: Avoiding Common Mistakes, Next: Generating Smaller Patches, Prev: Tips for Patch Consumers, Up: Making Patches + +11.3 Avoiding Common Mistakes +============================= + +When producing a patch for multiple files, apply `diff' to directories +whose names do not have slashes. This reduces confusion when the patch +consumer specifies the `-pNUMBER' option, since this option can have +surprising results when the old and new file names have different +numbers of slashes. For example, do not send a patch with a header +that looks like this: + + diff -Naur v2.0.29/prog/README prog/README + --- v2.0.29/prog/README 2002-03-10 23:30:39.942229878 -0800 + +++ prog/README 2002-03-17 20:49:32.442260588 -0800 + +because the two file names have different numbers of slashes, and +different versions of `patch' interpret the file names differently. To +avoid confusion, send output that looks like this instead: + + diff -Naur v2.0.29/prog/README v2.0.30/prog/README + --- v2.0.29/prog/README 2002-03-10 23:30:39.942229878 -0800 + +++ v2.0.30/prog/README 2002-03-17 20:49:32.442260588 -0800 + + Make sure you have specified the file names correctly, either in a +context diff header or with an `Index:' line. Take care to not send out +reversed patches, since these make people wonder whether they have +already applied the patch. + + Avoid sending patches that compare backup file names like +`README.orig' or `README~', since this might confuse `patch' into +patching a backup file instead of the real file. Instead, send patches +that compare the same base file names in different directories, e.g. +`old/README' and `new/README'. + + To save people from partially applying a patch before other patches +that should have gone before it, you can make the first patch in the +patch file update a file with a name like `patchlevel.h' or +`version.c', which contains a patch level or version number. If the +input file contains the wrong version number, `patch' will complain +immediately. + + An even clearer way to prevent this problem is to put a `Prereq:' +line before the patch. If the leading text in the patch file contains a +line that starts with `Prereq:', `patch' takes the next word from that +line (normally a version number) and checks whether the next input file +contains that word, preceded and followed by either white space or a +newline. If not, `patch' prompts you for confirmation before +proceeding. This makes it difficult to accidentally apply patches in +the wrong order. + + +File: diff.info, Node: Generating Smaller Patches, Prev: Avoiding Common Mistakes, Up: Making Patches + +11.4 Generating Smaller Patches +=============================== + +The simplest way to generate a patch is to use `diff -Naur' (*note Tips +for Patch Producers::), but you might be able to reduce the size of the +patch by renaming or removing some files before making the patch. If +the older version of the package contains any files that the newer +version does not, or if any files have been renamed between the two +versions, make a list of `rm' and `mv' commands for the user to execute +in the old version directory before applying the patch. Then run those +commands yourself in the scratch directory. + + If there are any files that you don't need to include in the patch +because they can easily be rebuilt from other files (for example, +`TAGS' and output from `yacc' and `makeinfo'), exclude them from the +patch by giving `diff' the `-x PATTERN' option (*note Comparing +Directories::). If you want your patch to modify a derived file +because your recipients lack tools to build it, make sure that the +patch for the derived file follows any patches for files that it +depends on, so that the recipients' time stamps will not confuse `make'. + + Now you can create the patch using `diff -Naur'. Make sure to +specify the scratch directory first and the newer directory second. + + Add to the top of the patch a note telling the user any `rm' and +`mv' commands to run before applying the patch. Then you can remove +the scratch directory. + + You can also shrink the patch size by using fewer lines of context, +but bear in mind that `patch' typically needs at least two lines for +proper operation when patches do not exactly match the input files. + + +File: diff.info, Node: Invoking cmp, Next: Invoking diff, Prev: Making Patches, Up: Top + +12 Invoking `cmp' +***************** + +The `cmp' command compares two files, and if they differ, tells the +first byte and line number where they differ or reports that one file +is a prefix of the other. Bytes and lines are numbered starting with +1. The arguments of `cmp' are as follows: + + cmp OPTIONS... FROM-FILE [TO-FILE [FROM-SKIP [TO-SKIP]]] + + The file name `-' is always the standard input. `cmp' also uses the +standard input if one file name is omitted. The FROM-SKIP and TO-SKIP +operands specify how many bytes to ignore at the start of each file; +they are equivalent to the `--ignore-initial=FROM-SKIP:TO-SKIP' option. + + By default, `cmp' outputs nothing if the two files have the same +contents. If one file is a prefix of the other, `cmp' prints to +standard error a message of the following form: + + cmp: EOF on SHORTER-FILE + + Otherwise, `cmp' prints to standard output a message of the +following form: + + FROM-FILE TO-FILE differ: char BYTE-NUMBER, line LINE-NUMBER + + The message formats can differ outside the POSIX locale. Also, +POSIX allows the EOF message to be followed by a blank and some +additional information. + + An exit status of 0 means no differences were found, 1 means some +differences were found, and 2 means trouble. + +* Menu: + +* cmp Options:: Summary of options to `cmp'. + + +File: diff.info, Node: cmp Options, Up: Invoking cmp + +12.1 Options to `cmp' +===================== + +Below is a summary of all of the options that GNU `cmp' accepts. Most +options have two equivalent names, one of which is a single letter +preceded by `-', and the other of which is a long name preceded by +`--'. Multiple single letter options (unless they take an argument) +can be combined into a single command line word: `-bl' is equivalent to +`-b -l'. + +`-b' +`--print-bytes' + Print the differing bytes. Display control bytes as a `^' + followed by a letter of the alphabet and precede bytes that have + the high bit set with `M-' (which stands for "meta"). + +`--help' + Output a summary of usage and then exit. + +`-i SKIP' +`--ignore-initial=SKIP' + Ignore any differences in the first SKIP bytes of the input files. + Treat files with fewer than SKIP bytes as if they are empty. If + SKIP is of the form `FROM-SKIP:TO-SKIP', skip the first FROM-SKIP + bytes of the first input file and the first TO-SKIP bytes of the + second. + +`-l' +`--verbose' + Output the (decimal) byte numbers and (octal) values of all + differing bytes, instead of the default standard output. + +`-n COUNT' +`--bytes=COUNT' + Compare at most COUNT input bytes. + +`-s' +`--quiet' +`--silent' + Do not print anything; only return an exit status indicating + whether the files differ. + +`-v' +`--version' + Output version information and then exit. + + In the above table, operands that are byte counts are normally +decimal, but may be preceded by `0' for octal and `0x' for hexadecimal. + + A byte count can be followed by a suffix to specify a multiple of +that count; in this case an omitted integer is understood to be 1. A +bare size letter, or one followed by `iB', specifies a multiple using +powers of 1024. A size letter followed by `B' specifies powers of 1000 +instead. For example, `-n 4M' and `-n 4MiB' are equivalent to `-n +4194304', whereas `-n 4MB' is equivalent to `-n 4000000'. This +notation is upward compatible with the SI prefixes +(http://www.bipm.fr/enus/3_SI/si-prefixes.html) for decimal multiples +and with the IEC 60027-2 prefixes for binary multiples +(http://physics.nist.gov/cuu/Units/binary.html). + + The following suffixes are defined. Large sizes like `1Y' may be +rejected by your computer due to limitations of its arithmetic. + +`kB' + kilobyte: 10^3 = 1000. + +`k' +`K' +`KiB' + kibibyte: 2^10 = 1024. `K' is special: the SI prefix is `k' and + the IEC 60027-2 prefix is `Ki', but tradition and POSIX use `k' to + mean `KiB'. + +`MB' + megabyte: 10^6 = 1,000,000. + +`M' +`MiB' + mebibyte: 2^20 = 1,048,576. + +`GB' + gigabyte: 10^9 = 1,000,000,000. + +`G' +`GiB' + gibibyte: 2^30 = 1,073,741,824. + +`TB' + terabyte: 10^12 = 1,000,000,000,000. + +`T' +`TiB' + tebibyte: 2^40 = 1,099,511,627,776. + +`PB' + petabyte: 10^15 = 1,000,000,000,000,000. + +`P' +`PiB' + pebibyte: 2^50 = 1,125,899,906,842,624. + +`EB' + exabyte: 10^18 = 1,000,000,000,000,000,000. + +`E' +`EiB' + exbibyte: 2^60 = 1,152,921,504,606,846,976. + +`ZB' + zettabyte: 10^21 = 1,000,000,000,000,000,000,000 + +`Z' +`ZiB' + 2^70 = 1,180,591,620,717,411,303,424. (`Zi' is a GNU extension to + IEC 60027-2.) + +`YB' + yottabyte: 10^24 = 1,000,000,000,000,000,000,000,000. + +`Y' +`YiB' + 2^80 = 1,208,925,819,614,629,174,706,176. (`Yi' is a GNU + extension to IEC 60027-2.) + + +File: diff.info, Node: Invoking diff, Next: Invoking diff3, Prev: Invoking cmp, Up: Top + +13 Invoking `diff' +****************** + +The format for running the `diff' command is: + + diff OPTIONS... FILES... + + In the simplest case, two file names FROM-FILE and TO-FILE are +given, and `diff' compares the contents of FROM-FILE and TO-FILE. A +file name of `-' stands for text read from the standard input. As a +special case, `diff - -' compares a copy of standard input to itself. + + If one file is a directory and the other is not, `diff' compares the +file in the directory whose name is that of the non-directory. The +non-directory file must not be `-'. + + If two file names are given and both are directories, `diff' +compares corresponding files in both directories, in alphabetical +order; this comparison is not recursive unless the `-r' or +`--recursive' option is given. `diff' never compares the actual +contents of a directory as if it were a file. The file that is fully +specified may not be standard input, because standard input is nameless +and the notion of "file with the same name" does not apply. + + If the `--from-file=FILE' option is given, the number of file names +is arbitrary, and FILE is compared to each named file. Similarly, if +the `--to-file=FILE' option is given, each named file is compared to +FILE. + + `diff' options begin with `-', so normally file names may not begin +with `-'. However, `--' as an argument by itself treats the remaining +arguments as file names even if they begin with `-'. + + An exit status of 0 means no differences were found, 1 means some +differences were found, and 2 means trouble. Normally, differing +binary files count as trouble, but this can be altered by using the +`-a' or `--text' option, or the `-q' or `--brief' option. + +* Menu: + +* diff Options:: Summary of options to `diff'. + + +File: diff.info, Node: diff Options, Up: Invoking diff + +13.1 Options to `diff' +====================== + +Below is a summary of all of the options that GNU `diff' accepts. Most +options have two equivalent names, one of which is a single letter +preceded by `-', and the other of which is a long name preceded by +`--'. Multiple single letter options (unless they take an argument) +can be combined into a single command line word: `-ac' is equivalent to +`-a -c'. Long named options can be abbreviated to any unique prefix of +their name. Brackets ([ and ]) indicate that an option takes an +optional argument. + +`-a' +`--text' + Treat all files as text and compare them line-by-line, even if they + do not seem to be text. *Note Binary::. + +`-b' +`--ignore-space-change' + Ignore changes in amount of white space. *Note White Space::. + +`-B' +`--ignore-blank-lines' + Ignore changes that just insert or delete blank lines. *Note + Blank Lines::. + +`--binary' + Read and write data in binary mode. *Note Binary::. + +`-c' + Use the context output format, showing three lines of context. + *Note Context Format::. + +`-C LINES' +`--context[=LINES]' + Use the context output format, showing LINES (an integer) lines of + context, or three if LINES is not given. *Note Context Format::. + For proper operation, `patch' typically needs at least two lines of + context. + + On older systems, `diff' supports an obsolete option `-LINES' that + has effect when combined with `-c' or `-p'. POSIX 1003.1-2001 + (*note Standards conformance::) does not allow this; use `-C LINES' + instead. + +`--changed-group-format=FORMAT' + Use FORMAT to output a line group containing differing lines from + both files in if-then-else format. *Note Line Group Formats::. + +`-d' +`--minimal' + Change the algorithm perhaps find a smaller set of changes. This + makes `diff' slower (sometimes much slower). *Note diff + Performance::. + +`-D NAME' +`--ifdef=NAME' + Make merged `#ifdef' format output, conditional on the preprocessor + macro NAME. *Note If-then-else::. + +`-e' +`--ed' + Make output that is a valid `ed' script. *Note ed Scripts::. + +`-E' +`--ignore-tab-expansion' + Ignore changes due to tab expansion. *Note White Space::. + +`-f' +`--forward-ed' + Make output that looks vaguely like an `ed' script but has changes + in the order they appear in the file. *Note Forward ed::. + +`-F REGEXP' +`--show-function-line=REGEXP' + In context and unified format, for each hunk of differences, show + some of the last preceding line that matches REGEXP. *Note + Specified Headings::. + +`--from-file=FILE' + Compare FILE to each operand; FILE may be a directory. + +`--help' + Output a summary of usage and then exit. + +`--horizon-lines=LINES' + Do not discard the last LINES lines of the common prefix and the + first LINES lines of the common suffix. *Note diff Performance::. + +`-i' +`--ignore-case' + Ignore changes in case; consider upper- and lower-case letters + equivalent. *Note Case Folding::. + +`-I REGEXP' +`--ignore-matching-lines=REGEXP' + Ignore changes that just insert or delete lines that match REGEXP. + *Note Specified Lines::. + +`--ignore-file-name-case' + Ignore case when comparing file names during recursive comparison. + *Note Comparing Directories::. + +`-l' +`--paginate' + Pass the output through `pr' to paginate it. *Note Pagination::. + +`--label=LABEL' + Use LABEL instead of the file name in the context format (*note + Context Format::) and unified format (*note Unified Format::) + headers. *Note RCS::. + +`--left-column' + Print only the left column of two common lines in side by side + format. *Note Side by Side Format::. + +`--line-format=FORMAT' + Use FORMAT to output all input lines in if-then-else format. + *Note Line Formats::. + +`-n' +`--rcs' + Output RCS-format diffs; like `-f' except that each command + specifies the number of lines affected. *Note RCS::. + +`-N' +`--new-file' + In directory comparison, if a file is found in only one directory, + treat it as present but empty in the other directory. *Note + Comparing Directories::. + +`--new-group-format=FORMAT' + Use FORMAT to output a group of lines taken from just the second + file in if-then-else format. *Note Line Group Formats::. + +`--new-line-format=FORMAT' + Use FORMAT to output a line taken from just the second file in + if-then-else format. *Note Line Formats::. + +`--old-group-format=FORMAT' + Use FORMAT to output a group of lines taken from just the first + file in if-then-else format. *Note Line Group Formats::. + +`--old-line-format=FORMAT' + Use FORMAT to output a line taken from just the first file in + if-then-else format. *Note Line Formats::. + +`-p' +`--show-c-function' + Show which C function each change is in. *Note C Function + Headings::. + +`-q' +`--brief' + Report only whether the files differ, not the details of the + differences. *Note Brief::. + +`-r' +`--recursive' + When comparing directories, recursively compare any subdirectories + found. *Note Comparing Directories::. + +`-s' +`--report-identical-files' + Report when two files are the same. *Note Comparing Directories::. + +`-S FILE' +`--starting-file=FILE' + When comparing directories, start with the file FILE. This is + used for resuming an aborted comparison. *Note Comparing + Directories::. + +`--speed-large-files' + Use heuristics to speed handling of large files that have numerous + scattered small changes. *Note diff Performance::. + +`--strip-trailing-cr' + Strip any trailing carriage return at the end of an input line. + *Note Binary::. + +`--suppress-common-lines' + Do not print common lines in side by side format. *Note Side by + Side Format::. + +`-t' +`--expand-tabs' + Expand tabs to spaces in the output, to preserve the alignment of + tabs in the input files. *Note Tabs::. + +`-T' +`--initial-tab' + Output a tab rather than a space before the text of a line in + normal or context format. This causes the alignment of tabs in + the line to look normal. *Note Tabs::. + +`--tabsize=COLUMNS' + Assume that tab stops are set every COLUMNS (default 8) print + columns. *Note Tabs::. + +`--to-file=FILE' + Compare each operand to FILE; FILE may be a directory. + +`-u' + Use the unified output format, showing three lines of context. + *Note Unified Format::. + +`--unchanged-group-format=FORMAT' + Use FORMAT to output a group of common lines taken from both files + in if-then-else format. *Note Line Group Formats::. + +`--unchanged-line-format=FORMAT' + Use FORMAT to output a line common to both files in if-then-else + format. *Note Line Formats::. + +`--unidirectional-new-file' + When comparing directories, if a file appears only in the second + directory of the two, treat it as present but empty in the other. + *Note Comparing Directories::. + +`-U LINES' +`--unified[=LINES]' + Use the unified output format, showing LINES (an integer) lines of + context, or three if LINES is not given. *Note Unified Format::. + For proper operation, `patch' typically needs at least two lines of + context. + + On older systems, `diff' supports an obsolete option `-LINES' that + has effect when combined with `-u'. POSIX 1003.1-2001 (*note + Standards conformance::) does not allow this; use `-U LINES' + instead. + +`-v' +`--version' + Output version information and then exit. + +`-w' +`--ignore-all-space' + Ignore white space when comparing lines. *Note White Space::. + +`-W COLUMNS' +`--width=COLUMNS' + Output at most COLUMNS (default 130) print columns per line in + side by side format. *Note Side by Side Format::. + +`-x PATTERN' +`--exclude=PATTERN' + When comparing directories, ignore files and subdirectories whose + basenames match PATTERN. *Note Comparing Directories::. + +`-X FILE' +`--exclude-from=FILE' + When comparing directories, ignore files and subdirectories whose + basenames match any pattern contained in FILE. *Note Comparing + Directories::. + +`-y' +`--side-by-side' + Use the side by side output format. *Note Side by Side Format::. + + +File: diff.info, Node: Invoking diff3, Next: Invoking patch, Prev: Invoking diff, Up: Top + +14 Invoking `diff3' +******************* + +The `diff3' command compares three files and outputs descriptions of +their differences. Its arguments are as follows: + + diff3 OPTIONS... MINE OLDER YOURS + + The files to compare are MINE, OLDER, and YOURS. At most one of +these three file names may be `-', which tells `diff3' to read the +standard input for that file. + + An exit status of 0 means `diff3' was successful, 1 means some +conflicts were found, and 2 means trouble. + +* Menu: + +* diff3 Options:: Summary of options to `diff3'. + + +File: diff.info, Node: diff3 Options, Up: Invoking diff3 + +14.1 Options to `diff3' +======================= + +Below is a summary of all of the options that GNU `diff3' accepts. +Multiple single letter options (unless they take an argument) can be +combined into a single command line argument. + +`-a' +`--text' + Treat all files as text and compare them line-by-line, even if they + do not appear to be text. *Note Binary::. + +`-A' +`--show-all' + Incorporate all unmerged changes from OLDER to YOURS into MINE, + surrounding conflicts with bracket lines. *Note Marking + Conflicts::. + +`--diff-program=PROGRAM' + Use the compatible comparison program PROGRAM to compare files + instead of `diff'. + +`-e' +`--ed' + Generate an `ed' script that incorporates all the changes from + OLDER to YOURS into MINE. *Note Which Changes::. + +`-E' +`--show-overlap' + Like `-e', except bracket lines from overlapping changes' first + and third files. *Note Marking Conflicts::. With `-E', an + overlapping change looks like this: + + <<<<<<< MINE + lines from MINE + ======= + lines from YOURS + >>>>>>> YOURS + +`--help' + Output a summary of usage and then exit. + +`-i' + Generate `w' and `q' commands at the end of the `ed' script for + System V compatibility. This option must be combined with one of + the `-AeExX3' options, and may not be combined with `-m'. *Note + Saving the Changed File::. + +`--label=LABEL' + Use the label LABEL for the brackets output by the `-A', `-E' and + `-X' options. This option may be given up to three times, one for + each input file. The default labels are the names of the input + files. Thus `diff3 --label X --label Y --label Z -m A B C' acts + like `diff3 -m A B C', except that the output looks like it came + from files named `X', `Y' and `Z' rather than from files named + `A', `B' and `C'. *Note Marking Conflicts::. + +`-m' +`--merge' + Apply the edit script to the first file and send the result to + standard output. Unlike piping the output from `diff3' to `ed', + this works even for binary files and incomplete lines. `-A' is + assumed if no edit script option is specified. *Note Bypassing + ed::. + +`--strip-trailing-cr' + Strip any trailing carriage return at the end of an input line. + *Note Binary::. + +`-T' +`--initial-tab' + Output a tab rather than two spaces before the text of a line in + normal format. This causes the alignment of tabs in the line to + look normal. *Note Tabs::. + +`-v' +`--version' + Output version information and then exit. + +`-x' +`--overlap-only' + Like `-e', except output only the overlapping changes. *Note + Which Changes::. + +`-X' + Like `-E', except output only the overlapping changes. In other + words, like `-x', except bracket changes as in `-E'. *Note + Marking Conflicts::. + +`-3' +`--easy-only' + Like `-e', except output only the nonoverlapping changes. *Note + Which Changes::. + + +File: diff.info, Node: Invoking patch, Next: Invoking sdiff, Prev: Invoking diff3, Up: Top + +15 Invoking `patch' +******************* + +Normally `patch' is invoked like this: + + patch +to coordinate with other volunteers. + +* Menu: + +* Shortcomings:: Suggested projects for improvements. +* Bugs:: Reporting bugs. + + +File: diff.info, Node: Shortcomings, Next: Bugs, Up: Projects + +18.1 Suggested Projects for Improving GNU `diff' and `patch' +============================================================ + +One should be able to use GNU `diff' to generate a patch from any pair +of directory trees, and given the patch and a copy of one such tree, +use `patch' to generate a faithful copy of the other. Unfortunately, +some changes to directory trees cannot be expressed using current patch +formats; also, `patch' does not handle some of the existing formats. +These shortcomings motivate the following suggested projects. + +* Menu: + +* Internationalization:: Handling multibyte and varying-width characters. +* Changing Structure:: Handling changes to the directory structure. +* Special Files:: Handling symbolic links, device special files, etc. +* Unusual File Names:: Handling file names that contain unusual characters. +* Time Stamp Order:: Outputting diffs in time stamp order. +* Ignoring Changes:: Ignoring certain changes while showing others. +* Speedups:: Improving performance. + + +File: diff.info, Node: Internationalization, Next: Changing Structure, Up: Shortcomings + +18.1.1 Handling Multibyte and Varying-Width Characters +------------------------------------------------------ + +`diff', `diff3' and `sdiff' treat each line of input as a string of +unibyte characters. This can mishandle multibyte characters in some +cases. For example, when asked to ignore spaces, `diff' does not +properly ignore a multibyte space character. + + Also, `diff' currently assumes that each byte is one column wide, +and this assumption is incorrect in some locales, e.g., locales that +use UTF-8 encoding. This causes problems with the `-y' or +`--side-by-side' option of `diff'. + + These problems need to be fixed without unduly affecting the +performance of the utilities in unibyte environments. + + The IBM GNU/Linux Technology Center Internationalization Team has +proposed patches to support internationalized `diff' +(http://oss.software.ibm.com/developer/opensource/linux/patches/i18n/diffutils-2.7.2-i18n-0.1.patch.gz). +Unfortunately, these patches are incomplete and are to an older version +of `diff', so more work needs to be done in this area. + + +File: diff.info, Node: Changing Structure, Next: Special Files, Prev: Internationalization, Up: Shortcomings + +18.1.2 Handling Changes to the Directory Structure +-------------------------------------------------- + +`diff' and `patch' do not handle some changes to directory structure. +For example, suppose one directory tree contains a directory named `D' +with some subsidiary files, and another contains a file with the same +name `D'. `diff -r' does not output enough information for `patch' to +transform the directory subtree into the file. + + There should be a way to specify that a file has been removed without +having to include its entire contents in the patch file. There should +also be a way to tell `patch' that a file was renamed, even if there is +no way for `diff' to generate such information. There should be a way +to tell `patch' that a file's time stamp has changed, even if its +contents have not changed. + + These problems can be fixed by extending the `diff' output format to +represent changes in directory structure, and extending `patch' to +understand these extensions. + + +File: diff.info, Node: Special Files, Next: Unusual File Names, Prev: Changing Structure, Up: Shortcomings + +18.1.3 Files that are Neither Directories Nor Regular Files +----------------------------------------------------------- + +Some files are neither directories nor regular files: they are unusual +files like symbolic links, device special files, named pipes, and +sockets. Currently, `diff' treats symbolic links as if they were the +pointed-to files, except that a recursive `diff' reports an error if it +detects infinite loops of symbolic links (e.g., symbolic links to +`..'). `diff' treats other special files like regular files if they +are specified at the top level, but simply reports their presence when +comparing directories. This means that `patch' cannot represent +changes to such files. For example, if you change which file a +symbolic link points to, `diff' outputs the difference between the two +files, instead of the change to the symbolic link. + + `diff' should optionally report changes to special files specially, +and `patch' should be extended to understand these extensions. + + +File: diff.info, Node: Unusual File Names, Next: Time Stamp Order, Prev: Special Files, Up: Shortcomings + +18.1.4 File Names that Contain Unusual Characters +------------------------------------------------- + +When a file name contains an unusual character like a newline or white +space, `diff -r' generates a patch that `patch' cannot parse. The +problem is with format of `diff' output, not just with `patch', because +with odd enough file names one can cause `diff' to generate a patch +that is syntactically correct but patches the wrong files. The format +of `diff' output should be extended to handle all possible file names. + + +File: diff.info, Node: Time Stamp Order, Next: Ignoring Changes, Prev: Unusual File Names, Up: Shortcomings + +18.1.5 Outputting Diffs in Time Stamp Order +------------------------------------------- + +Applying `patch' to a multiple-file diff can result in files whose time +stamps are out of order. GNU `patch' has options to restore the time +stamps of the updated files (*note Patching Time Stamps::), but +sometimes it is useful to generate a patch that works even if the +recipient does not have GNU patch, or does not use these options. One +way to do this would be to implement a `diff' option to output diffs in +time stamp order. + + +File: diff.info, Node: Ignoring Changes, Next: Speedups, Prev: Time Stamp Order, Up: Shortcomings + +18.1.6 Ignoring Certain Changes +------------------------------- + +It would be nice to have a feature for specifying two strings, one in +FROM-FILE and one in TO-FILE, which should be considered to match. +Thus, if the two strings are `foo' and `bar', then if two lines differ +only in that `foo' in file 1 corresponds to `bar' in file 2, the lines +are treated as identical. + + It is not clear how general this feature can or should be, or what +syntax should be used for it. + + A partial substitute is to filter one or both files before comparing, +e.g.: + + sed 's/foo/bar/g' file1 | diff - file2 + + However, this outputs the filtered text, not the original. + + +File: diff.info, Node: Speedups, Prev: Ignoring Changes, Up: Shortcomings + +18.1.7 Improving Performance +---------------------------- + +When comparing two large directory structures, one of which was +originally copied from the other with time stamps preserved (e.g., with +`cp -pR'), it would greatly improve performance if an option told +`diff' to assume that two files with the same size and time stamps have +the same content. *Note diff Performance::. + + +File: diff.info, Node: Bugs, Prev: Shortcomings, Up: Projects + +18.2 Reporting Bugs +=================== + +If you think you have found a bug in GNU `cmp', `diff', `diff3', or +`sdiff', please report it by electronic mail to the GNU utilities bug +report mailing list +(http://mail.gnu.org/mailman/listinfo/bug-gnu-utils) +. Please send bug reports for GNU `patch' to +. Send as precise a description of the problem as +you can, including the output of the `--version' option and sample +input files that produce the bug, if applicable. If you have a +nontrivial fix for the bug, please send it as well. If you have a +patch, please send it too. It may simplify the maintainer's job if the +patch is relative to a recent test release, which you can find in the +directory `ftp://alpha.gnu.org/gnu/diffutils/'. + + +File: diff.info, Node: Copying This Manual, Next: Translations, Prev: Projects, Up: Top + +Appendix A Copying This Manual +****************************** + +* Menu: + +* GNU Free Documentation License:: License for copying this manual. + + +File: diff.info, Node: GNU Free Documentation License, Up: Copying This Manual + +A.1 GNU Free Documentation License +================================== + + Version 1.2, November 2002 + + Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + 0. PREAMBLE + + The purpose of this License is to make a manual, textbook, or other + functional and useful document "free" in the sense of freedom: to + assure everyone the effective freedom to copy and redistribute it, + with or without modifying it, either commercially or + noncommercially. Secondarily, this License preserves for the + author and publisher a way to get credit for their work, while not + being considered responsible for modifications made by others. + + This License is a kind of "copyleft", which means that derivative + works of the document must themselves be free in the same sense. + It complements the GNU General Public License, which is a copyleft + license designed for free software. + + We have designed this License in order to use it for manuals for + free software, because free software needs free documentation: a + free program should come with manuals providing the same freedoms + that the software does. But this License is not limited to + software manuals; it can be used for any textual work, regardless + of subject matter or whether it is published as a printed book. + We recommend this License principally for works whose purpose is + instruction or reference. + + 1. APPLICABILITY AND DEFINITIONS + + This License applies to any manual or other work, in any medium, + that contains a notice placed by the copyright holder saying it + can be distributed under the terms of this License. Such a notice + grants a world-wide, royalty-free license, unlimited in duration, + to use that work under the conditions stated herein. The + "Document", below, refers to any such manual or work. Any member + of the public is a licensee, and is addressed as "you". You + accept the license if you copy, modify or distribute the work in a + way requiring permission under copyright law. + + A "Modified Version" of the Document means any work containing the + Document or a portion of it, either copied verbatim, or with + modifications and/or translated into another language. + + A "Secondary Section" is a named appendix or a front-matter section + of the Document that deals exclusively with the relationship of the + publishers or authors of the Document to the Document's overall + subject (or to related matters) and contains nothing that could + fall directly within that overall subject. (Thus, if the Document + is in part a textbook of mathematics, a Secondary Section may not + explain any mathematics.) The relationship could be a matter of + historical connection with the subject or with related matters, or + of legal, commercial, philosophical, ethical or political position + regarding them. + + The "Invariant Sections" are certain Secondary Sections whose + titles are designated, as being those of Invariant Sections, in + the notice that says that the Document is released under this + License. If a section does not fit the above definition of + Secondary then it is not allowed to be designated as Invariant. + The Document may contain zero Invariant Sections. If the Document + does not identify any Invariant Sections then there are none. + + The "Cover Texts" are certain short passages of text that are + listed, as Front-Cover Texts or Back-Cover Texts, in the notice + that says that the Document is released under this License. A + Front-Cover Text may be at most 5 words, and a Back-Cover Text may + be at most 25 words. + + A "Transparent" copy of the Document means a machine-readable copy, + represented in a format whose specification is available to the + general public, that is suitable for revising the document + straightforwardly with generic text editors or (for images + composed of pixels) generic paint programs or (for drawings) some + widely available drawing editor, and that is suitable for input to + text formatters or for automatic translation to a variety of + formats suitable for input to text formatters. A copy made in an + otherwise Transparent file format whose markup, or absence of + markup, has been arranged to thwart or discourage subsequent + modification by readers is not Transparent. An image format is + not Transparent if used for any substantial amount of text. A + copy that is not "Transparent" is called "Opaque". + + Examples of suitable formats for Transparent copies include plain + ASCII without markup, Texinfo input format, LaTeX input format, + SGML or XML using a publicly available DTD, and + standard-conforming simple HTML, PostScript or PDF designed for + human modification. Examples of transparent image formats include + PNG, XCF and JPG. Opaque formats include proprietary formats that + can be read and edited only by proprietary word processors, SGML or + XML for which the DTD and/or processing tools are not generally + available, and the machine-generated HTML, PostScript or PDF + produced by some word processors for output purposes only. + + The "Title Page" means, for a printed book, the title page itself, + plus such following pages as are needed to hold, legibly, the + material this License requires to appear in the title page. For + works in formats which do not have any title page as such, "Title + Page" means the text near the most prominent appearance of the + work's title, preceding the beginning of the body of the text. + + A section "Entitled XYZ" means a named subunit of the Document + whose title either is precisely XYZ or contains XYZ in parentheses + following text that translates XYZ in another language. (Here XYZ + stands for a specific section name mentioned below, such as + "Acknowledgements", "Dedications", "Endorsements", or "History".) + To "Preserve the Title" of such a section when you modify the + Document means that it remains a section "Entitled XYZ" according + to this definition. + + The Document may include Warranty Disclaimers next to the notice + which states that this License applies to the Document. These + Warranty Disclaimers are considered to be included by reference in + this License, but only as regards disclaiming warranties: any other + implication that these Warranty Disclaimers may have is void and + has no effect on the meaning of this License. + + 2. VERBATIM COPYING + + You may copy and distribute the Document in any medium, either + commercially or noncommercially, provided that this License, the + copyright notices, and the license notice saying this License + applies to the Document are reproduced in all copies, and that you + add no other conditions whatsoever to those of this License. You + may not use technical measures to obstruct or control the reading + or further copying of the copies you make or distribute. However, + you may accept compensation in exchange for copies. If you + distribute a large enough number of copies you must also follow + the conditions in section 3. + + You may also lend copies, under the same conditions stated above, + and you may publicly display copies. + + 3. COPYING IN QUANTITY + + If you publish printed copies (or copies in media that commonly + have printed covers) of the Document, numbering more than 100, and + the Document's license notice requires Cover Texts, you must + enclose the copies in covers that carry, clearly and legibly, all + these Cover Texts: Front-Cover Texts on the front cover, and + Back-Cover Texts on the back cover. Both covers must also clearly + and legibly identify you as the publisher of these copies. The + front cover must present the full title with all words of the + title equally prominent and visible. You may add other material + on the covers in addition. Copying with changes limited to the + covers, as long as they preserve the title of the Document and + satisfy these conditions, can be treated as verbatim copying in + other respects. + + If the required texts for either cover are too voluminous to fit + legibly, you should put the first ones listed (as many as fit + reasonably) on the actual cover, and continue the rest onto + adjacent pages. + + If you publish or distribute Opaque copies of the Document + numbering more than 100, you must either include a + machine-readable Transparent copy along with each Opaque copy, or + state in or with each Opaque copy a computer-network location from + which the general network-using public has access to download + using public-standard network protocols a complete Transparent + copy of the Document, free of added material. If you use the + latter option, you must take reasonably prudent steps, when you + begin distribution of Opaque copies in quantity, to ensure that + this Transparent copy will remain thus accessible at the stated + location until at least one year after the last time you + distribute an Opaque copy (directly or through your agents or + retailers) of that edition to the public. + + It is requested, but not required, that you contact the authors of + the Document well before redistributing any large number of + copies, to give them a chance to provide you with an updated + version of the Document. + + 4. MODIFICATIONS + + You may copy and distribute a Modified Version of the Document + under the conditions of sections 2 and 3 above, provided that you + release the Modified Version under precisely this License, with + the Modified Version filling the role of the Document, thus + licensing distribution and modification of the Modified Version to + whoever possesses a copy of it. In addition, you must do these + things in the Modified Version: + + A. Use in the Title Page (and on the covers, if any) a title + distinct from that of the Document, and from those of + previous versions (which should, if there were any, be listed + in the History section of the Document). You may use the + same title as a previous version if the original publisher of + that version gives permission. + + B. List on the Title Page, as authors, one or more persons or + entities responsible for authorship of the modifications in + the Modified Version, together with at least five of the + principal authors of the Document (all of its principal + authors, if it has fewer than five), unless they release you + from this requirement. + + C. State on the Title page the name of the publisher of the + Modified Version, as the publisher. + + D. Preserve all the copyright notices of the Document. + + E. Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices. + + F. Include, immediately after the copyright notices, a license + notice giving the public permission to use the Modified + Version under the terms of this License, in the form shown in + the Addendum below. + + G. Preserve in that license notice the full lists of Invariant + Sections and required Cover Texts given in the Document's + license notice. + + H. Include an unaltered copy of this License. + + I. Preserve the section Entitled "History", Preserve its Title, + and add to it an item stating at least the title, year, new + authors, and publisher of the Modified Version as given on + the Title Page. If there is no section Entitled "History" in + the Document, create one stating the title, year, authors, + and publisher of the Document as given on its Title Page, + then add an item describing the Modified Version as stated in + the previous sentence. + + J. Preserve the network location, if any, given in the Document + for public access to a Transparent copy of the Document, and + likewise the network locations given in the Document for + previous versions it was based on. These may be placed in + the "History" section. You may omit a network location for a + work that was published at least four years before the + Document itself, or if the original publisher of the version + it refers to gives permission. + + K. For any section Entitled "Acknowledgements" or "Dedications", + Preserve the Title of the section, and preserve in the + section all the substance and tone of each of the contributor + acknowledgements and/or dedications given therein. + + L. Preserve all the Invariant Sections of the Document, + unaltered in their text and in their titles. Section numbers + or the equivalent are not considered part of the section + titles. + + M. Delete any section Entitled "Endorsements". Such a section + may not be included in the Modified Version. + + N. Do not retitle any existing section to be Entitled + "Endorsements" or to conflict in title with any Invariant + Section. + + O. Preserve any Warranty Disclaimers. + + If the Modified Version includes new front-matter sections or + appendices that qualify as Secondary Sections and contain no + material copied from the Document, you may at your option + designate some or all of these sections as invariant. To do this, + add their titles to the list of Invariant Sections in the Modified + Version's license notice. These titles must be distinct from any + other section titles. + + You may add a section Entitled "Endorsements", provided it contains + nothing but endorsements of your Modified Version by various + parties--for example, statements of peer review or that the text + has been approved by an organization as the authoritative + definition of a standard. + + You may add a passage of up to five words as a Front-Cover Text, + and a passage of up to 25 words as a Back-Cover Text, to the end + of the list of Cover Texts in the Modified Version. Only one + passage of Front-Cover Text and one of Back-Cover Text may be + added by (or through arrangements made by) any one entity. If the + Document already includes a cover text for the same cover, + previously added by you or by arrangement made by the same entity + you are acting on behalf of, you may not add another; but you may + replace the old one, on explicit permission from the previous + publisher that added the old one. + + The author(s) and publisher(s) of the Document do not by this + License give permission to use their names for publicity for or to + assert or imply endorsement of any Modified Version. + + 5. COMBINING DOCUMENTS + + You may combine the Document with other documents released under + this License, under the terms defined in section 4 above for + modified versions, provided that you include in the combination + all of the Invariant Sections of all of the original documents, + unmodified, and list them all as Invariant Sections of your + combined work in its license notice, and that you preserve all + their Warranty Disclaimers. + + The combined work need only contain one copy of this License, and + multiple identical Invariant Sections may be replaced with a single + copy. If there are multiple Invariant Sections with the same name + but different contents, make the title of each such section unique + by adding at the end of it, in parentheses, the name of the + original author or publisher of that section if known, or else a + unique number. Make the same adjustment to the section titles in + the list of Invariant Sections in the license notice of the + combined work. + + In the combination, you must combine any sections Entitled + "History" in the various original documents, forming one section + Entitled "History"; likewise combine any sections Entitled + "Acknowledgements", and any sections Entitled "Dedications". You + must delete all sections Entitled "Endorsements." + + 6. COLLECTIONS OF DOCUMENTS + + You may make a collection consisting of the Document and other + documents released under this License, and replace the individual + copies of this License in the various documents with a single copy + that is included in the collection, provided that you follow the + rules of this License for verbatim copying of each of the + documents in all other respects. + + You may extract a single document from such a collection, and + distribute it individually under this License, provided you insert + a copy of this License into the extracted document, and follow + this License in all other respects regarding verbatim copying of + that document. + + 7. AGGREGATION WITH INDEPENDENT WORKS + + A compilation of the Document or its derivatives with other + separate and independent documents or works, in or on a volume of + a storage or distribution medium, is called an "aggregate" if the + copyright resulting from the compilation is not used to limit the + legal rights of the compilation's users beyond what the individual + works permit. When the Document is included in an aggregate, this + License does not apply to the other works in the aggregate which + are not themselves derivative works of the Document. + + If the Cover Text requirement of section 3 is applicable to these + copies of the Document, then if the Document is less than one half + of the entire aggregate, the Document's Cover Texts may be placed + on covers that bracket the Document within the aggregate, or the + electronic equivalent of covers if the Document is in electronic + form. Otherwise they must appear on printed covers that bracket + the whole aggregate. + + 8. TRANSLATION + + Translation is considered a kind of modification, so you may + distribute translations of the Document under the terms of section + 4. Replacing Invariant Sections with translations requires special + permission from their copyright holders, but you may include + translations of some or all Invariant Sections in addition to the + original versions of these Invariant Sections. You may include a + translation of this License, and all the license notices in the + Document, and any Warranty Disclaimers, provided that you also + include the original English version of this License and the + original versions of those notices and disclaimers. In case of a + disagreement between the translation and the original version of + this License or a notice or disclaimer, the original version will + prevail. + + If a section in the Document is Entitled "Acknowledgements", + "Dedications", or "History", the requirement (section 4) to + Preserve its Title (section 1) will typically require changing the + actual title. + + 9. TERMINATION + + You may not copy, modify, sublicense, or distribute the Document + except as expressly provided for under this License. Any other + attempt to copy, modify, sublicense or distribute the Document is + void, and will automatically terminate your rights under this + License. However, parties who have received copies, or rights, + from you under this License will not have their licenses + terminated so long as such parties remain in full compliance. + + 10. FUTURE REVISIONS OF THIS LICENSE + + The Free Software Foundation may publish new, revised versions of + the GNU Free Documentation License from time to time. Such new + versions will be similar in spirit to the present version, but may + differ in detail to address new problems or concerns. See + `http://www.gnu.org/copyleft/'. + + Each version of the License is given a distinguishing version + number. If the Document specifies that a particular numbered + version of this License "or any later version" applies to it, you + have the option of following the terms and conditions either of + that specified version or of any later version that has been + published (not as a draft) by the Free Software Foundation. If + the Document does not specify a version number of this License, + you may choose any version ever published (not as a draft) by the + Free Software Foundation. + +A.1.1 ADDENDUM: How to use this License for your documents +---------------------------------------------------------- + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and license +notices just after the title page: + + Copyright (C) YEAR YOUR NAME. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.2 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover + Texts. A copy of the license is included in the section entitled ``GNU + Free Documentation License''. + + If you have Invariant Sections, Front-Cover Texts and Back-Cover +Texts, replace the "with...Texts." line with this: + + with the Invariant Sections being LIST THEIR TITLES, with + the Front-Cover Texts being LIST, and with the Back-Cover Texts + being LIST. + + If you have Invariant Sections without Cover Texts, or some other +combination of the three, merge those two alternatives to suit the +situation. + + If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of +free software license, such as the GNU General Public License, to +permit their use in free software. + + +File: diff.info, Node: Translations, Next: Index, Prev: Copying This Manual, Up: Top + +Appendix B Translations of This Manual +************************************** + +Nishio Futoshi of the GNUjdoc project has prepared a Japanese +translation of this manual. Its most recent version can be found at +`http://openlab.ring.gr.jp/gnujdoc/cvsweb/cvsweb.cgi/gnujdoc/'. + + +File: diff.info, Node: Index, Prev: Translations, Up: Top + +Appendix C Index +**************** + +[index] +* Menu: + +* ! output format: Context. (line 6) +* +- output format: Unified Format. (line 6) +* < output format: Normal. (line 6) +* <<<<<<< for marking conflicts: Marking Conflicts. (line 6) +* _POSIX2_VERSION: Standards conformance. + (line 24) +* aligning tab stops: Tabs. (line 6) +* alternate file names: Alternate Names. (line 6) +* backup file names: Backup Names. (line 6) +* backup file strategy: Backups. (line 6) +* binary file diff: Binary. (line 6) +* blank and tab difference suppression: White Space. (line 6) +* blank line difference suppression: Blank Lines. (line 6) +* brief difference reports: Brief. (line 6) +* bug reports: Bugs. (line 6) +* C function headings: C Function Headings. (line 6) +* C if-then-else output format: If-then-else. (line 6) +* case difference suppression: Case Folding. (line 6) +* ClearCase: Revision Control. (line 6) +* cmp invocation: Invoking cmp. (line 6) +* cmp options: cmp Options. (line 6) +* columnar output: Side by Side. (line 6) +* common mistakes with patches: Avoiding Common Mistakes. + (line 6) +* comparing three files: Comparing Three Files. + (line 6) +* conflict: diff3 Merging. (line 26) +* conflict marking: Marking Conflicts. (line 6) +* context output format: Context. (line 6) +* creating files: Creating and Removing. + (line 6) +* diagnostics from patch: patch Messages. (line 6) +* diff invocation: Invoking diff. (line 6) +* diff merging: Interactive Merging. (line 6) +* diff options: diff Options. (line 6) +* diff sample input: Sample diff Input. (line 6) +* diff3 hunks: diff3 Hunks. (line 6) +* diff3 invocation: Invoking diff3. (line 6) +* diff3 options: diff3 Options. (line 6) +* diff3 sample input: Sample diff3 Input. (line 6) +* directories and patch: patch Directories. (line 6) +* directory structure changes: Changing Structure. (line 6) +* dry runs for patch: Dry Runs. (line 6) +* ed script output format: ed Scripts. (line 6) +* EDITOR: Merge Commands. (line 46) +* empty files, removing: Creating and Removing. + (line 6) +* exabyte, definition of: cmp Options. (line 105) +* exbibyte, definition of: cmp Options. (line 109) +* FDL, GNU Free Documentation License: GNU Free Documentation License. + (line 6) +* file name alternates: Alternate Names. (line 6) +* file names with unusual characters: Unusual File Names. (line 6) +* format of diff output: Output Formats. (line 6) +* format of diff3 output: Comparing Three Files. + (line 6) +* formats for if-then-else line groups: Line Group Formats. (line 6) +* forward ed script output format: Forward ed. (line 6) +* full lines: Incomplete Lines. (line 6) +* function headings, C: C Function Headings. (line 6) +* fuzz factor when patching: Inexact. (line 6) +* gibibyte, definition of: cmp Options. (line 88) +* gigabyte, definition of: cmp Options. (line 84) +* headings: Sections. (line 6) +* hunks: Hunks. (line 6) +* hunks for diff3: diff3 Hunks. (line 6) +* if-then-else output format: If-then-else. (line 6) +* ifdef output format: If-then-else. (line 6) +* imperfect patch application: Imperfect. (line 6) +* incomplete line merging: Merging Incomplete Lines. + (line 6) +* incomplete lines: Incomplete Lines. (line 6) +* inexact patches: Inexact. (line 6) +* inhibit messages from patch: More or Fewer Messages. + (line 6) +* interactive merging: Interactive Merging. (line 6) +* introduction: Comparison. (line 6) +* intuiting file names from patches: Multiple Patches. (line 6) +* invoking cmp: Invoking cmp. (line 6) +* invoking diff: Invoking diff. (line 6) +* invoking diff3: Invoking diff3. (line 6) +* invoking patch: Invoking patch. (line 6) +* invoking sdiff: Invoking sdiff. (line 6) +* keyboard input to patch: patch and Keyboard Input. + (line 6) +* kibibyte, definition of: cmp Options. (line 72) +* kilobyte, definition of: cmp Options. (line 67) +* LC_COLLATE: Comparing Directories. + (line 6) +* LC_NUMERIC: Line Group Formats. (line 144) +* LC_TIME: Detailed Context. (line 12) +* line formats: Line Formats. (line 6) +* line group formats: Line Group Formats. (line 6) +* mebibyte, definition of: cmp Options. (line 81) +* megabyte, definition of: cmp Options. (line 77) +* merge commands: Merge Commands. (line 6) +* merged diff3 format: Bypassing ed. (line 6) +* merged output format: If-then-else. (line 6) +* merging from a common ancestor: diff3 Merging. (line 6) +* merging interactively: Merge Commands. (line 6) +* messages from patch: patch Messages. (line 6) +* multibyte characters: Internationalization. + (line 6) +* multiple patches: Multiple Patches. (line 6) +* newline treatment by diff: Incomplete Lines. (line 6) +* normal output format: Normal. (line 6) +* options for cmp: cmp Options. (line 6) +* options for diff: diff Options. (line 6) +* options for diff3: diff3 Options. (line 6) +* options for patch: patch Options. (line 6) +* options for sdiff: sdiff Options. (line 6) +* output formats: Output Formats. (line 6) +* overlap: diff3 Merging. (line 26) +* overlapping change, selection of: Which Changes. (line 6) +* overview of diff and patch: Overview. (line 6) +* paginating diff output: Pagination. (line 6) +* patch consumer tips: Tips for Patch Consumers. + (line 6) +* patch input format: patch Input. (line 6) +* patch invocation: Invoking patch. (line 6) +* patch messages and questions: patch Messages. (line 6) +* patch options: patch Options. (line 6) +* patch producer tips: Tips for Patch Producers. + (line 6) +* patch, common mistakes: Avoiding Common Mistakes. + (line 6) +* PATCH_GET: Revision Control. (line 13) +* PATCH_VERSION_CONTROL: Backup Names. (line 21) +* patches, shrinking: Generating Smaller Patches. + (line 6) +* patching directories: patch Directories. (line 6) +* pebibyte, definition of: cmp Options. (line 102) +* performance of diff: diff Performance. (line 6) +* petabyte, definition of: cmp Options. (line 98) +* POSIX <1>: Standards conformance. + (line 6) +* POSIX: patch and POSIX. (line 6) +* POSIXLY_CORRECT <1>: patch and POSIX. (line 6) +* POSIXLY_CORRECT: Standards conformance. + (line 6) +* projects for directories: Shortcomings. (line 6) +* quoting style: patch Quoting Style. (line 6) +* QUOTING_STYLE: patch Quoting Style. (line 30) +* RCS: Revision Control. (line 6) +* RCS script output format: RCS. (line 6) +* regular expression matching headings: Specified Headings. (line 6) +* regular expression suppression: Specified Lines. (line 6) +* reject file names: Reject Names. (line 6) +* removing empty files: Creating and Removing. + (line 6) +* reporting bugs: Bugs. (line 6) +* reversed patches: Reversed Patches. (line 6) +* revision control: Revision Control. (line 6) +* sample input for diff: Sample diff Input. (line 6) +* sample input for diff3: Sample diff3 Input. (line 6) +* SCCS: Revision Control. (line 6) +* script output formats: Scripts. (line 6) +* sdiff invocation: Invoking sdiff. (line 6) +* sdiff options: sdiff Options. (line 6) +* sdiff output format: sdiff Option Summary. + (line 6) +* section headings: Sections. (line 6) +* side by side: Side by Side. (line 6) +* side by side format: Side by Side Format. (line 6) +* SIMPLE_BACKUP_SUFFIX: Backup Names. (line 12) +* special files: Special Files. (line 6) +* specified headings: Specified Headings. (line 6) +* summarizing which files differ: Brief. (line 6) +* System V diff3 compatibility: Saving the Changed File. + (line 6) +* tab and blank difference suppression: White Space. (line 6) +* tab stop alignment: Tabs. (line 6) +* tebibyte, definition of: cmp Options. (line 95) +* terabyte, definition of: cmp Options. (line 91) +* testing patch: Dry Runs. (line 6) +* text versus binary diff: Binary. (line 6) +* time stamp format, context diffs: Detailed Context. (line 12) +* time stamp format, unified diffs: Detailed Unified. (line 12) +* time stamps on patched files: Patching Time Stamps. + (line 6) +* traditional patch: patch and Tradition. (line 6) +* two-column output: Side by Side. (line 6) +* unified output format: Unified Format. (line 6) +* unmerged change: Which Changes. (line 6) +* varying-width characters: Internationalization. + (line 6) +* verbose messages from patch: More or Fewer Messages. + (line 6) +* version control: Revision Control. (line 6) +* VERSION_CONTROL <1>: Revision Control. (line 22) +* VERSION_CONTROL: Backup Names. (line 21) +* white space in patches: Changed White Space. (line 6) +* yottabyte, definition of: cmp Options. (line 120) +* zettabyte, definition of: cmp Options. (line 112) + + + +Tag Table: +Node: Top1678 +Node: Overview4139 +Node: Comparison7763 +Node: Hunks10461 +Node: White Space11899 +Node: Blank Lines13354 +Node: Specified Lines14384 +Node: Case Folding15506 +Node: Brief15918 +Node: Binary17237 +Node: Output Formats21322 +Node: Sample diff Input22042 +Node: Context23536 +Node: Context Format25108 +Node: Example Context25895 +Node: Less Context27397 +Node: Detailed Context28581 +Node: Unified Format30774 +Node: Example Unified31565 +Node: Detailed Unified32598 +Node: Sections34240 +Node: Specified Headings34994 +Node: C Function Headings36543 +Node: Alternate Names37385 +Node: Side by Side38294 +Node: Side by Side Format40438 +Node: Example Side by Side41336 +Node: Normal42671 +Node: Example Normal43666 +Node: Detailed Normal44397 +Node: Scripts46131 +Node: ed Scripts46531 +Node: Example ed47733 +Node: Detailed ed48178 +Node: Forward ed49932 +Node: RCS50703 +Node: If-then-else51915 +Node: Line Group Formats53588 +Node: Line Formats59459 +Node: Example If-then-else62724 +Node: Detailed If-then-else63798 +Node: Incomplete Lines65676 +Node: Comparing Directories67308 +Node: Adjusting Output71352 +Node: Tabs71778 +Node: Pagination73383 +Node: diff Performance73836 +Node: Comparing Three Files76919 +Node: Sample diff3 Input77792 +Node: Example diff3 Normal78735 +Node: Detailed diff3 Normal79780 +Node: diff3 Hunks81537 +Node: diff3 Merging82828 +Node: Which Changes85067 +Node: Marking Conflicts86466 +Node: Bypassing ed88920 +Node: Merging Incomplete Lines90259 +Node: Saving the Changed File90980 +Node: Interactive Merging91591 +Node: sdiff Option Summary92296 +Node: Merge Commands93467 +Node: Merging with patch94733 +Node: patch Input97100 +Node: Revision Control97777 +Node: Imperfect98943 +Node: Changed White Space100086 +Node: Reversed Patches100878 +Node: Inexact102338 +Node: Dry Runs105892 +Node: Creating and Removing106751 +Node: Patching Time Stamps107797 +Node: Multiple Patches109995 +Node: patch Directories112653 +Node: Backups114274 +Node: Backup Names115335 +Ref: Backup Names-Footnote-1118299 +Node: Reject Names118426 +Node: patch Messages119010 +Node: More or Fewer Messages120065 +Node: patch and Keyboard Input120691 +Node: patch Quoting Style121717 +Node: patch and POSIX122862 +Node: patch and Tradition123697 +Node: Making Patches127149 +Node: Tips for Patch Producers127970 +Node: Tips for Patch Consumers129221 +Node: Avoiding Common Mistakes129853 +Node: Generating Smaller Patches132373 +Node: Invoking cmp134129 +Node: cmp Options135547 +Node: Invoking diff138960 +Node: diff Options140813 +Node: Invoking diff3149059 +Node: diff3 Options149692 +Node: Invoking patch152720 +Node: patch Options153923 +Node: Invoking sdiff159145 +Node: sdiff Options160287 +Node: Standards conformance163162 +Node: Projects164903 +Node: Shortcomings165609 +Node: Internationalization166706 +Node: Changing Structure167867 +Node: Special Files168966 +Node: Unusual File Names170073 +Node: Time Stamp Order170707 +Node: Ignoring Changes171345 +Node: Speedups172110 +Node: Bugs172569 +Node: Copying This Manual173417 +Node: GNU Free Documentation License173654 +Node: Translations196061 +Node: Index196428 + +End Tag Table diff --git a/contrib/diffutils-2.8/doc/diff.texi b/contrib/diffutils-2.8/doc/diff.texi new file mode 100644 index 0000000000..a8724f4528 --- /dev/null +++ b/contrib/diffutils-2.8/doc/diff.texi @@ -0,0 +1,4649 @@ +\input texinfo @c -*-texinfo-*- +@comment $Id: diff.texi,v 1.25 2004/04/12 07:44:35 eggert Exp $ +@comment %**start of header +@setfilename diff.info +@include version.texi +@settitle Comparing and Merging Files +@syncodeindex vr cp +@setchapternewpage odd +@comment %**end of header +@copying +This manual is for GNU Diffutils +(version @value{VERSION}, @value{UPDATED}), +and documents the @acronym{GNU} @command{diff}, @command{diff3}, +@command{sdiff}, and @command{cmp} commands for showing the +differences between files and the @acronym{GNU} @command{patch} command for +using their output to update files. + +Copyright @copyright{} 1992, 1993, 1994, 1998, 2001, 2002, 2004 Free +Software Foundation, Inc. + +@quotation +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.1 or +any later version published by the Free Software Foundation; with no +Invariant Sections, with the Front-Cover texts being ``A GNU Manual,'' +and with the Back-Cover Texts as in (a) below. A copy of the +license is included in the section entitled ``GNU Free Documentation +License.'' + +(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify +this GNU Manual, like GNU software. Copies published by the Free +Software Foundation raise funds for GNU development.'' +@end quotation +@end copying + +@c Debian install-info (up through at least version 1.9.20) uses only the +@c first dircategory. Put this one first, as it is more useful in practice. +@dircategory Individual utilities +@direntry +* cmp: (diff)Invoking cmp. Compare 2 files byte by byte. +* diff: (diff)Invoking diff. Compare 2 files line by line. +* diff3: (diff)Invoking diff3. Compare 3 files line by line. +* patch: (diff)Invoking patch. Apply a patch to a file. +* sdiff: (diff)Invoking sdiff. Merge 2 files side-by-side. +@end direntry + +@dircategory Text creation and manipulation +@direntry +* Diff: (diff). Comparing and merging files. +@end direntry + +@titlepage +@title Comparing and Merging Files +@subtitle for Diffutils @value{VERSION} and @code{patch} 2.5.4 +@subtitle @value{UPDATED} +@author David MacKenzie, Paul Eggert, and Richard Stallman +@page +@vskip 0pt plus 1filll +@insertcopying +@end titlepage + +@shortcontents +@contents + +@ifnottex +@node Top +@top Comparing and Merging Files + +@insertcopying +@end ifnottex + +@menu +* Overview:: Preliminary information. +* Comparison:: What file comparison means. + +* Output Formats:: Formats for two-way difference reports. +* Incomplete Lines:: Lines that lack trailing newlines. +* Comparing Directories:: Comparing files and directories. +* Adjusting Output:: Making @command{diff} output prettier. +* diff Performance:: Making @command{diff} smarter or faster. + +* Comparing Three Files:: Formats for three-way difference reports. +* diff3 Merging:: Merging from a common ancestor. + +* Interactive Merging:: Interactive merging with @command{sdiff}. + +* Merging with patch:: Using @command{patch} to change old files into new ones. +* Making Patches:: Tips for making and using patch distributions. + +* Invoking cmp:: Compare two files byte by byte. +* Invoking diff:: Compare two files line by line. +* Invoking diff3:: Compare three files line by line. +* Invoking patch:: Apply a diff file to an original. +* Invoking sdiff:: Side-by-side merge of file differences. + +* Standards conformance:: Conformance to the @acronym{POSIX} standard. +* Projects:: If you've found a bug or other shortcoming. + +* Copying This Manual:: How to make copies of this manual. +* Translations:: Available translations of this manual. +* Index:: Index. +@end menu + +@node Overview +@unnumbered Overview +@cindex overview of @command{diff} and @command{patch} + +Computer users often find occasion to ask how two files differ. Perhaps +one file is a newer version of the other file. Or maybe the two files +started out as identical copies but were changed by different people. + +You can use the @command{diff} command to show differences between two +files, or each corresponding file in two directories. @command{diff} +outputs differences between files line by line in any of several +formats, selectable by command line options. This set of differences is +often called a @dfn{diff} or @dfn{patch}. For files that are identical, +@command{diff} normally produces no output; for binary (non-text) files, +@command{diff} normally reports only that they are different. + +You can use the @command{cmp} command to show the byte and line numbers +where two files differ. @command{cmp} can also show all the bytes +that differ between the two files, side by side. A way to compare +two files character by character is the Emacs command @kbd{M-x +compare-windows}. @xref{Other Window, , Other Window, emacs, The @acronym{GNU} +Emacs Manual}, for more information on that command. + +You can use the @command{diff3} command to show differences among three +files. When two people have made independent changes to a common +original, @command{diff3} can report the differences between the original +and the two changed versions, and can produce a merged file that +contains both persons' changes together with warnings about conflicts. + +You can use the @command{sdiff} command to merge two files interactively. + +You can use the set of differences produced by @command{diff} to distribute +updates to text files (such as program source code) to other people. +This method is especially useful when the differences are small compared +to the complete files. Given @command{diff} output, you can use the +@command{patch} program to update, or @dfn{patch}, a copy of the file. If you +think of @command{diff} as subtracting one file from another to produce +their difference, you can think of @command{patch} as adding the difference +to one file to reproduce the other. + +This manual first concentrates on making diffs, and later shows how to +use diffs to update files. + +@acronym{GNU} @command{diff} was written by Paul Eggert, Mike Haertel, +David Hayes, Richard Stallman, and Len Tower. Wayne Davison designed and +implemented the unified output format. The basic algorithm is described +by Eugene W. Myers in ``An O(ND) Difference Algorithm and its Variations'', +@cite{Algorithmica} Vol.@: 1 No.@: 2, 1986, pp.@: 251--266; and in ``A File +Comparison Program'', Webb Miller and Eugene W. Myers, +@cite{Software---Practice and Experience} Vol.@: 15 No.@: 11, 1985, +pp.@: 1025--1040. +@c From: "Gene Myers" +@c They are about the same basic algorithm; the Algorithmica +@c paper gives a rigorous treatment and the sub-algorithm for +@c delivering scripts and should be the primary reference, but +@c both should be mentioned. +The algorithm was independently discovered as described by E. Ukkonen in +``Algorithms for Approximate String Matching'', +@cite{Information and Control} Vol.@: 64, 1985, pp.@: 100--118. +@c From: "Gene Myers" +@c Date: Wed, 29 Sep 1993 08:27:55 MST +@c Ukkonen should be given credit for also discovering the algorithm used +@c in GNU diff. +Unless the @option{--minimal} option is used, @command{diff} uses a +heuristic by Paul Eggert that limits the cost to @math{O(N^1.5 log N)} +at the price of producing suboptimal output for large inputs with many +differences. Related algorithms are surveyed by Alfred V. Aho in +section 6.3 of ``Algorithms for Finding Patterns in Strings'', +@cite{Handbook of Theoretical Computer Science} (Jan Van Leeuwen, +ed.), Vol.@: A, @cite{Algorithms and Complexity}, Elsevier/MIT Press, +1990, pp.@: 255--300. + +@acronym{GNU} @command{diff3} was written by Randy Smith. @acronym{GNU} +@command{sdiff} was written by Thomas Lord. @acronym{GNU} @command{cmp} +was written by Torbj@"orn Granlund and David MacKenzie. + +@acronym{GNU} @command{patch} was written mainly by Larry Wall and Paul Eggert; +several @acronym{GNU} enhancements were contributed by Wayne Davison and +David MacKenzie. Parts of this manual are adapted from a manual page +written by Larry Wall, with his permission. + +@node Comparison +@chapter What Comparison Means +@cindex introduction + +There are several ways to think about the differences between two files. +One way to think of the differences is as a series of lines that were +deleted from, inserted in, or changed in one file to produce the other +file. @command{diff} compares two files line by line, finds groups of +lines that differ, and reports each group of differing lines. It can +report the differing lines in several formats, which have different +purposes. + +@acronym{GNU} @command{diff} can show whether files are different +without detailing the differences. It also provides ways to suppress +certain kinds of differences that are not important to you. Most +commonly, such differences are changes in the amount of white space +between words or lines. @command{diff} also provides ways to suppress +differences in alphabetic case or in lines that match a regular +expression that you provide. These options can accumulate; for +example, you can ignore changes in both white space and alphabetic +case. + +Another way to think of the differences between two files is as a +sequence of pairs of bytes that can be either identical or +different. @command{cmp} reports the differences between two files +byte by byte, instead of line by line. As a result, it is often +more useful than @command{diff} for comparing binary files. For text +files, @command{cmp} is useful mainly when you want to know only whether +two files are identical, or whether one file is a prefix of the other. + +To illustrate the effect that considering changes byte by byte +can have compared with considering them line by line, think of what +happens if a single newline character is added to the beginning of a +file. If that file is then compared with an otherwise identical file +that lacks the newline at the beginning, @command{diff} will report that a +blank line has been added to the file, while @command{cmp} will report that +almost every byte of the two files differs. + +@command{diff3} normally compares three input files line by line, finds +groups of lines that differ, and reports each group of differing lines. +Its output is designed to make it easy to inspect two different sets of +changes to the same file. + +@menu +* Hunks:: Groups of differing lines. +* White Space:: Suppressing differences in white space. +* Blank Lines:: Suppressing differences whose lines are all blank. +* Specified Lines:: Suppressing differences whose lines all match a pattern. +* Case Folding:: Suppressing differences in alphabetic case. +* Brief:: Summarizing which files are different. +* Binary:: Comparing binary files or forcing text comparisons. +@end menu + +@node Hunks +@section Hunks +@cindex hunks + +When comparing two files, @command{diff} finds sequences of lines common to +both files, interspersed with groups of differing lines called +@dfn{hunks}. Comparing two identical files yields one sequence of +common lines and no hunks, because no lines differ. Comparing two +entirely different files yields no common lines and one large hunk that +contains all lines of both files. In general, there are many ways to +match up lines between two given files. @command{diff} tries to minimize +the total hunk size by finding large sequences of common lines +interspersed with small hunks of differing lines. + +For example, suppose the file @file{F} contains the three lines +@samp{a}, @samp{b}, @samp{c}, and the file @file{G} contains the same +three lines in reverse order @samp{c}, @samp{b}, @samp{a}. If +@command{diff} finds the line @samp{c} as common, then the command +@samp{diff F G} produces this output: + +@example +1,2d0 +< a +< b +3a2,3 +> b +> a +@end example + +@noindent +But if @command{diff} notices the common line @samp{b} instead, it produces +this output: + +@example +1c1 +< a +--- +> c +3c3 +< c +--- +> a +@end example + +@noindent +It is also possible to find @samp{a} as the common line. @command{diff} +does not always find an optimal matching between the files; it takes +shortcuts to run faster. But its output is usually close to the +shortest possible. You can adjust this tradeoff with the +@option{-d} or @option{--minimal} option (@pxref{diff Performance}). + +@node White Space +@section Suppressing Differences in Blank and Tab Spacing +@cindex blank and tab difference suppression +@cindex tab and blank difference suppression + +The @option{-E} or @option{--ignore-tab-expansion} option ignores the +distinction between tabs and spaces on input. A tab is considered to be +equivalent to the number of spaces to the next tab stop (@pxref{Tabs}). + +The @option{-b} or @option{--ignore-space-change} option is stronger. +It ignores white space at line end, and considers all other sequences of +one or more white space characters within a line to be equivalent. With this +option, @command{diff} considers the following two lines to be equivalent, +where @samp{$} denotes the line end: + +@example +Here lyeth muche rychnesse in lytell space. -- John Heywood$ +Here lyeth muche rychnesse in lytell space. -- John Heywood $ +@end example + +The @option{-w} or @option{--ignore-all-space} option is stronger still. +It ignores differences even if one line has white space where +the other line has none. @dfn{White space} characters include +tab, newline, vertical tab, form feed, carriage return, and space; +some locales may define additional characters to be white space. +With this option, @command{diff} considers the +following two lines to be equivalent, where @samp{$} denotes the line +end and @samp{^M} denotes a carriage return: + +@example +Here lyeth muche rychnesse in lytell space.-- John Heywood$ + He relyeth much erychnes seinly tells pace. --John Heywood ^M$ +@end example + +@node Blank Lines +@section Suppressing Differences Whose Lines Are All Blank +@cindex blank line difference suppression + +The @option{-B} or @option{--ignore-blank-lines} option ignores changes +that consist entirely of blank lines. With this option, for example, a +file containing +@example +1. A point is that which has no part. + +2. A line is breadthless length. +-- Euclid, The Elements, I +@end example +@noindent +is considered identical to a file containing +@example +1. A point is that which has no part. +2. A line is breadthless length. + + +-- Euclid, The Elements, I +@end example + +Normally this option affects only lines that are completely empty, but +if you also specify the @option{-b} or @option{--ignore-space-change} +option, or the @option{-w} or @option{--ignore-all-space} option, +lines are also affected if they look empty but contain white space. +In other words, @option{-B} is equivalent to @samp{-I '^$'} by +default, but it is equivalent to @option{-I '^[[:space:]]*$'} if +@option{-b} or @option{-w} is also specified. + +@node Specified Lines +@section Suppressing Differences Whose Lines All Match a Regular Expression +@cindex regular expression suppression + +To ignore insertions and deletions of lines that match a +@command{grep}-style regular expression, use the @option{-I +@var{regexp}} or @option{--ignore-matching-lines=@var{regexp}} option. +You should escape +regular expressions that contain shell metacharacters to prevent the +shell from expanding them. For example, @samp{diff -I '^[[:digit:]]'} ignores +all changes to lines beginning with a digit. + +However, @option{-I} only ignores the insertion or deletion of lines that +contain the regular expression if every changed line in the hunk---every +insertion and every deletion---matches the regular expression. In other +words, for each nonignorable change, @command{diff} prints the complete set +of changes in its vicinity, including the ignorable ones. + +You can specify more than one regular expression for lines to ignore by +using more than one @option{-I} option. @command{diff} tries to match each +line against each regular expression. + +@node Case Folding +@section Suppressing Case Differences +@cindex case difference suppression + +@acronym{GNU} @command{diff} can treat lower case letters as +equivalent to their upper case counterparts, so that, for example, it +considers @samp{Funky Stuff}, @samp{funky STUFF}, and @samp{fUNKy +stuFf} to all be the same. To request this, use the @option{-i} or +@option{--ignore-case} option. + +@node Brief +@section Summarizing Which Files Differ +@cindex summarizing which files differ +@cindex brief difference reports + +When you only want to find out whether files are different, and you +don't care what the differences are, you can use the summary output +format. In this format, instead of showing the differences between the +files, @command{diff} simply reports whether files differ. The @option{-q} +or @option{--brief} option selects this output format. + +This format is especially useful when comparing the contents of two +directories. It is also much faster than doing the normal line by line +comparisons, because @command{diff} can stop analyzing the files as soon as +it knows that there are any differences. + +You can also get a brief indication of whether two files differ by using +@command{cmp}. For files that are identical, @command{cmp} produces no +output. When the files differ, by default, @command{cmp} outputs the byte +and line number where the first difference occurs, or reports that one +file is a prefix of the other. You can use +the @option{-s}, @option{--quiet}, or @option{--silent} option to +suppress that information, so that @command{cmp} +produces no output and reports whether the files differ using only its +exit status (@pxref{Invoking cmp}). + +@c Fix this. +Unlike @command{diff}, @command{cmp} cannot compare directories; it can only +compare two files. + +@node Binary +@section Binary Files and Forcing Text Comparisons +@cindex binary file diff +@cindex text versus binary diff + +If @command{diff} thinks that either of the two files it is comparing is +binary (a non-text file), it normally treats that pair of files much as +if the summary output format had been selected (@pxref{Brief}), and +reports only that the binary files are different. This is because line +by line comparisons are usually not meaningful for binary files. + +@command{diff} determines whether a file is text or binary by checking the +first few bytes in the file; the exact number of bytes is system +dependent, but it is typically several thousand. If every byte in +that part of the file is non-null, @command{diff} considers the file to be +text; otherwise it considers the file to be binary. + +Sometimes you might want to force @command{diff} to consider files to be +text. For example, you might be comparing text files that contain +null characters; @command{diff} would erroneously decide that those are +non-text files. Or you might be comparing documents that are in a +format used by a word processing system that uses null characters to +indicate special formatting. You can force @command{diff} to consider all +files to be text files, and compare them line by line, by using the +@option{-a} or @option{--text} option. If the files you compare using this +option do not in fact contain text, they will probably contain few +newline characters, and the @command{diff} output will consist of hunks +showing differences between long lines of whatever characters the files +contain. + +You can also force @command{diff} to report only whether files differ +(but not how). Use the @option{-q} or @option{--brief} option for +this. + +Normally, differing binary files count as trouble because the +resulting @command{diff} output does not capture all the differences. +This trouble causes @command{diff} to exit with status 2. However, +this trouble cannot occur with the @option{-a} or @option{--text} +option, or with the @option{-q} or @option{--brief} option, as these +options both cause @command{diff} to generate a form of output that +represents differences as requested. + +In operating systems that distinguish between text and binary files, +@command{diff} normally reads and writes all data as text. Use the +@option{--binary} option to force @command{diff} to read and write binary +data instead. This option has no effect on a @acronym{POSIX}-compliant system +like @acronym{GNU} or traditional Unix. However, many personal computer +operating systems represent the end of a line with a carriage return +followed by a newline. On such systems, @command{diff} normally ignores +these carriage returns on input and generates them at the end of each +output line, but with the @option{--binary} option @command{diff} treats +each carriage return as just another input character, and does not +generate a carriage return at the end of each output line. This can be +useful when dealing with non-text files that are meant to be +interchanged with @acronym{POSIX}-compliant systems. + +The @option{--strip-trailing-cr} causes @command{diff} to treat input +lines that end in carriage return followed by newline as if they end +in plain newline. This can be useful when comparing text that is +imperfectly imported from many personal computer operating systems. +This option affects how lines are read, which in turn affects how they +are compared and output. + +If you want to compare two files byte by byte, you can use the +@command{cmp} program with the @option{-l} or @option{--verbose} +option to show the values of each differing byte in the two files. +With @acronym{GNU} @command{cmp}, you can also use the @option{-b} or +@option{--print-bytes} option to show the @acronym{ASCII} representation of +those bytes. @xref{Invoking cmp}, for more information. + +If @command{diff3} thinks that any of the files it is comparing is binary +(a non-text file), it normally reports an error, because such +comparisons are usually not useful. @command{diff3} uses the same test as +@command{diff} to decide whether a file is binary. As with @command{diff}, if +the input files contain a few non-text bytes but otherwise are like +text files, you can force @command{diff3} to consider all files to be text +files and compare them line by line by using the @option{-a} or +@option{--text} option. + +@node Output Formats +@chapter @command{diff} Output Formats +@cindex output formats +@cindex format of @command{diff} output + +@command{diff} has several mutually exclusive options for output format. +The following sections describe each format, illustrating how +@command{diff} reports the differences between two sample input files. + +@menu +* Sample diff Input:: Sample @command{diff} input files for examples. +* Context:: Showing differences with the surrounding text. +* Side by Side:: Showing differences in two columns. +* Normal:: Showing differences without surrounding text. +* Scripts:: Generating scripts for other programs. +* If-then-else:: Merging files with if-then-else. +@end menu + +@node Sample diff Input +@section Two Sample Input Files +@cindex @command{diff} sample input +@cindex sample input for @command{diff} + +Here are two sample files that we will use in numerous examples to +illustrate the output of @command{diff} and how various options can change +it. + +This is the file @file{lao}: + +@example +The Way that can be told of is not the eternal Way; +The name that can be named is not the eternal name. +The Nameless is the origin of Heaven and Earth; +The Named is the mother of all things. +Therefore let there always be non-being, + so we may see their subtlety, +And let there always be being, + so we may see their outcome. +The two are the same, +But after they are produced, + they have different names. +@end example + +This is the file @file{tzu}: + +@example +The Nameless is the origin of Heaven and Earth; +The named is the mother of all things. + +Therefore let there always be non-being, + so we may see their subtlety, +And let there always be being, + so we may see their outcome. +The two are the same, +But after they are produced, + they have different names. +They both may be called deep and profound. +Deeper and more profound, +The door of all subtleties! +@end example + +In this example, the first hunk contains just the first two lines of +@file{lao}, the second hunk contains the fourth line of @file{lao} +opposing the second and third lines of @file{tzu}, and the last hunk +contains just the last three lines of @file{tzu}. + +@node Context +@section Showing Differences in Their Context +@cindex context output format +@cindex @samp{!} output format + +Usually, when you are looking at the differences between files, you will +also want to see the parts of the files near the lines that differ, to +help you understand exactly what has changed. These nearby parts of the +files are called the @dfn{context}. + +@acronym{GNU} @command{diff} provides two output formats that show context +around the differing lines: @dfn{context format} and @dfn{unified +format}. It can optionally show in which function or section of the +file the differing lines are found. + +If you are distributing new versions of files to other people in the +form of @command{diff} output, you should use one of the output formats +that show context so that they can apply the diffs even if they have +made small changes of their own to the files. @command{patch} can apply +the diffs in this case by searching in the files for the lines of +context around the differing lines; if those lines are actually a few +lines away from where the diff says they are, @command{patch} can adjust +the line numbers accordingly and still apply the diff correctly. +@xref{Imperfect}, for more information on using @command{patch} to apply +imperfect diffs. + +@menu +* Context Format:: An output format that shows surrounding lines. +* Unified Format:: A more compact output format that shows context. +* Sections:: Showing which sections of the files differences are in. +* Alternate Names:: Showing alternate file names in context headers. +@end menu + +@node Context Format +@subsection Context Format + +The context output format shows several lines of context around the +lines that differ. It is the standard format for distributing updates +to source code. + +To select this output format, use the @option{-C @var{lines}}, +@option{--context@r{[}=@var{lines}@r{]}}, or @option{-c} option. The +argument @var{lines} that some of these options take is the number of +lines of context to show. If you do not specify @var{lines}, it +defaults to three. For proper operation, @command{patch} typically needs +at least two lines of context. + +@menu +* Example Context:: Sample output in context format. +* Less Context:: Another sample with less context. +* Detailed Context:: A detailed description of the context output format. +@end menu + +@node Example Context +@subsubsection An Example of Context Format + +Here is the output of @samp{diff -c lao tzu} (@pxref{Sample diff Input}, +for the complete contents of the two files). Notice that up to three +lines that are not different are shown around each line that is +different; they are the context lines. Also notice that the first two +hunks have run together, because their contents overlap. + +@example +*** lao 2002-02-21 23:30:39.942229878 -0800 +--- tzu 2002-02-21 23:30:50.442260588 -0800 +*************** +*** 1,7 **** +- The Way that can be told of is not the eternal Way; +- The name that can be named is not the eternal name. + The Nameless is the origin of Heaven and Earth; +! The Named is the mother of all things. + Therefore let there always be non-being, + so we may see their subtlety, + And let there always be being, +--- 1,6 ---- + The Nameless is the origin of Heaven and Earth; +! The named is the mother of all things. +! + Therefore let there always be non-being, + so we may see their subtlety, + And let there always be being, +*************** +*** 9,11 **** +--- 8,13 ---- + The two are the same, + But after they are produced, + they have different names. ++ They both may be called deep and profound. ++ Deeper and more profound, ++ The door of all subtleties! +@end example + +@node Less Context +@subsubsection An Example of Context Format with Less Context + +Here is the output of @samp{diff -C 1 lao tzu} (@pxref{Sample diff +Input}, for the complete contents of the two files). Notice that at +most one context line is reported here. + +@example +*** lao 2002-02-21 23:30:39.942229878 -0800 +--- tzu 2002-02-21 23:30:50.442260588 -0800 +*************** +*** 1,5 **** +- The Way that can be told of is not the eternal Way; +- The name that can be named is not the eternal name. + The Nameless is the origin of Heaven and Earth; +! The Named is the mother of all things. + Therefore let there always be non-being, +--- 1,4 ---- + The Nameless is the origin of Heaven and Earth; +! The named is the mother of all things. +! + Therefore let there always be non-being, +*************** +*** 11 **** +--- 10,13 ---- + they have different names. ++ They both may be called deep and profound. ++ Deeper and more profound, ++ The door of all subtleties! +@end example + +@node Detailed Context +@subsubsection Detailed Description of Context Format + +The context output format starts with a two-line header, which looks +like this: + +@example +*** @var{from-file} @var{from-file-modification-time} +--- @var{to-file} @var{to-file-modification time} +@end example + +@noindent +@vindex LC_TIME +@cindex time stamp format, context diffs +The time stamp normally looks like @samp{2002-02-21 23:30:39.942229878 +-0800} to indicate the date, time with fractional seconds, and time +zone in @uref{ftp://ftp.isi.edu/in-notes/rfc2822.txt, Internet RFC +2822 format}. (The fractional seconds are omitted on hosts that do +not support fractional time stamps.) However, a traditional time +stamp like @samp{Thu Feb 21 23:30:39 2002} is used if the +@env{LC_TIME} locale category is either @samp{C} or @samp{POSIX}. + +You can change the header's content with the +@option{--label=@var{label}} option; see @ref{Alternate Names}. + +Next come one or more hunks of differences; each hunk shows one area +where the files differ. Context format hunks look like this: + +@example +*************** +*** @var{from-file-line-numbers} **** + @var{from-file-line} + @var{from-file-line}@dots{} +--- @var{to-file-line-numbers} ---- + @var{to-file-line} + @var{to-file-line}@dots{} +@end example + +If a hunk contains two or more lines, its line numbers look like +@samp{@var{start},@var{end}}. Otherwise only its end line number +appears. An empty hunk is considered to end at the line that precedes +the hunk. + +The lines of context around the lines that differ start with two space +characters. The lines that differ between the two files start with one +of the following indicator characters, followed by a space character: + +@table @samp +@item ! +A line that is part of a group of one or more lines that changed between +the two files. There is a corresponding group of lines marked with +@samp{!} in the part of this hunk for the other file. + +@item + +An ``inserted'' line in the second file that corresponds to nothing in +the first file. + +@item - +A ``deleted'' line in the first file that corresponds to nothing in the +second file. +@end table + +If all of the changes in a hunk are insertions, the lines of +@var{from-file} are omitted. If all of the changes are deletions, the +lines of @var{to-file} are omitted. + +@node Unified Format +@subsection Unified Format +@cindex unified output format +@cindex @samp{+-} output format + +The unified output format is a variation on the context format that is +more compact because it omits redundant context lines. To select this +output format, use the @option{-U @var{lines}}, +@option{--unified@r{[}=@var{lines}@r{]}}, or @option{-u} +option. The argument @var{lines} is the number of lines of context to +show. When it is not given, it defaults to three. + +At present, only @acronym{GNU} @command{diff} can produce this format and +only @acronym{GNU} @command{patch} can automatically apply diffs in this +format. For proper operation, @command{patch} typically needs at +least three lines of context. + +@menu +* Example Unified:: Sample output in unified format. +* Detailed Unified:: A detailed description of unified format. +@end menu + +@node Example Unified +@subsubsection An Example of Unified Format + +Here is the output of the command @samp{diff -u lao tzu} +(@pxref{Sample diff Input}, for the complete contents of the two files): + +@example +--- lao 2002-02-21 23:30:39.942229878 -0800 ++++ tzu 2002-02-21 23:30:50.442260588 -0800 +@@@@ -1,7 +1,6 @@@@ +-The Way that can be told of is not the eternal Way; +-The name that can be named is not the eternal name. + The Nameless is the origin of Heaven and Earth; +-The Named is the mother of all things. ++The named is the mother of all things. ++ + Therefore let there always be non-being, + so we may see their subtlety, + And let there always be being, +@@@@ -9,3 +8,6 @@@@ + The two are the same, + But after they are produced, + they have different names. ++They both may be called deep and profound. ++Deeper and more profound, ++The door of all subtleties! +@end example + +@node Detailed Unified +@subsubsection Detailed Description of Unified Format + +The unified output format starts with a two-line header, which looks +like this: + +@example +--- @var{from-file} @var{from-file-modification-time} ++++ @var{to-file} @var{to-file-modification-time} +@end example + +@noindent +@cindex time stamp format, unified diffs +The time stamp looks like @samp{2002-02-21 23:30:39.942229878 -0800} +to indicate the date, time with fractional seconds, and time zone. +The fractional seconds are omitted on hosts that do not support +fractional time stamps. + +You can change the header's content with the +@option{--label=@var{label}} option; see @xref{Alternate Names}. + +Next come one or more hunks of differences; each hunk shows one area +where the files differ. Unified format hunks look like this: + +@example +@@@@ @var{from-file-line-numbers} @var{to-file-line-numbers} @@@@ + @var{line-from-either-file} + @var{line-from-either-file}@dots{} +@end example + +If a hunk contains just one line, only its start line number appears. +Otherwise its line numbers look like @samp{@var{start},@var{count}}. +An empty hunk is considered to start at the line that follows the hunk. + +If a hunk and its context contain two or more lines, its +line numbers look like @samp{@var{start},@var{count}}. Otherwise only +its end line number appears. An empty hunk is considered to end at +the line that precedes the hunk. + +The lines common to both files begin with a space character. The lines +that actually differ between the two files have one of the following +indicator characters in the left print column: + +@table @samp +@item + +A line was added here to the first file. + +@item - +A line was removed here from the first file. +@end table + +@node Sections +@subsection Showing Which Sections Differences Are in +@cindex headings +@cindex section headings + +Sometimes you might want to know which part of the files each change +falls in. If the files are source code, this could mean which +function was changed. If the files are documents, it could mean which +chapter or appendix was changed. @acronym{GNU} @command{diff} can +show this by displaying the nearest section heading line that precedes +the differing lines. Which lines are ``section headings'' is +determined by a regular expression. + +@menu +* Specified Headings:: Showing headings that match regular expressions. +* C Function Headings:: Showing headings of C functions. +@end menu + +@node Specified Headings +@subsubsection Showing Lines That Match Regular Expressions +@cindex specified headings +@cindex regular expression matching headings + +To show in which sections differences occur for files that are not +source code for C or similar languages, use the @option{-F @var{regexp}} +or @option{--show-function-line=@var{regexp}} option. @command{diff} +considers lines that match the @command{grep}-style regular expression +@var{regexp} to be the beginning +of a section of the file. Here are suggested regular expressions for +some common languages: + +@c Please add to this list, e.g. Fortran, Pascal, Perl, Python. +@table @samp +@item ^[[:alpha:]$_] +C, C++, Prolog +@item ^( +Lisp +@item ^@@node +Texinfo +@end table + +This option does not automatically select an output format; in order to +use it, you must select the context format (@pxref{Context Format}) or +unified format (@pxref{Unified Format}). In other output formats it +has no effect. + +The @option{-F} or @option{--show-function-line} option finds the nearest +unchanged line that precedes each hunk of differences and matches the +given regular expression. Then it adds that line to the end of the +line of asterisks in the context format, or to the @samp{@@@@} line in +unified format. If no matching line exists, this option leaves the output for +that hunk unchanged. If that line is more than 40 characters long, it +outputs only the first 40 characters. You can specify more than one +regular expression for such lines; @command{diff} tries to match each line +against each regular expression, starting with the last one given. This +means that you can use @option{-p} and @option{-F} together, if you wish. + +@node C Function Headings +@subsubsection Showing C Function Headings +@cindex C function headings +@cindex function headings, C + +To show in which functions differences occur for C and similar +languages, you can use the @option{-p} or @option{--show-c-function} option. +This option automatically defaults to the context output format +(@pxref{Context Format}), with the default number of lines of context. +You can override that number with @option{-C @var{lines}} elsewhere in the +command line. You can override both the format and the number with +@option{-U @var{lines}} elsewhere in the command line. + +The @option{-p} or @option{--show-c-function} option is equivalent to +@option{-F '^[[:alpha:]$_]'} if the unified format is specified, otherwise +@option{-c -F '^[[:alpha:]$_]'} (@pxref{Specified Headings}). @acronym{GNU} +@command{diff} provides this option for the sake of convenience. + +@node Alternate Names +@subsection Showing Alternate File Names +@cindex alternate file names +@cindex file name alternates + +If you are comparing two files that have meaningless or uninformative +names, you might want @command{diff} to show alternate names in the header +of the context and unified output formats. To do this, use the +@option{--label=@var{label}} option. The first time +you give this option, its argument replaces the name and date of the +first file in the header; the second time, its argument replaces the +name and date of the second file. If you give this option more than +twice, @command{diff} reports an error. The @option{--label} option does not +affect the file names in the @command{pr} header when the @option{-l} or +@option{--paginate} option is used (@pxref{Pagination}). + +Here are the first two lines of the output from @samp{diff -C 2 +--label=original --label=modified lao tzu}: + +@example +*** original +--- modified +@end example + +@node Side by Side +@section Showing Differences Side by Side +@cindex side by side +@cindex two-column output +@cindex columnar output + +@command{diff} can produce a side by side difference listing of two files. +The files are listed in two columns with a gutter between them. The +gutter contains one of the following markers: + +@table @asis +@item white space +The corresponding lines are in common. That is, either the lines are +identical, or the difference is ignored because of one of the +@option{--ignore} options (@pxref{White Space}). + +@item @samp{|} +The corresponding lines differ, and they are either both complete +or both incomplete. + +@item @samp{<} +The files differ and only the first file contains the line. + +@item @samp{>} +The files differ and only the second file contains the line. + +@item @samp{(} +Only the first file contains the line, but the difference is ignored. + +@item @samp{)} +Only the second file contains the line, but the difference is ignored. + +@item @samp{\} +The corresponding lines differ, and only the first line is incomplete. + +@item @samp{/} +The corresponding lines differ, and only the second line is incomplete. +@end table + +Normally, an output line is incomplete if and only if the lines that it +contains are incomplete; @xref{Incomplete Lines}. However, when an +output line represents two differing lines, one might be incomplete +while the other is not. In this case, the output line is complete, +but its the gutter is marked @samp{\} if the first line is incomplete, +@samp{/} if the second line is. + +Side by side format is sometimes easiest to read, but it has limitations. +It generates much wider output than usual, and truncates lines that are +too long to fit. Also, it relies on lining up output more heavily than +usual, so its output looks particularly bad if you use varying +width fonts, nonstandard tab stops, or nonprinting characters. + +You can use the @command{sdiff} command to interactively merge side by side +differences. @xref{Interactive Merging}, for more information on merging files. + +@menu +* Side by Side Format:: Controlling side by side output format. +* Example Side by Side:: Sample side by side output. +@end menu + +@node Side by Side Format +@subsection Controlling Side by Side Format +@cindex side by side format + +The @option{-y} or @option{--side-by-side} option selects side by side +format. Because side by side output lines contain two input lines, the +output is wider than usual: normally 130 print columns, which can fit +onto a traditional printer line. You can set the width of the output +with the @option{-W @var{columns}} or @option{--width=@var{columns}} +option. The output is split into two halves of equal width, separated by a +small gutter to mark differences; the right half is aligned to a tab +stop so that tabs line up. Input lines that are too long to fit in half +of an output line are truncated for output. + +The @option{--left-column} option prints only the left column of two +common lines. The @option{--suppress-common-lines} option suppresses +common lines entirely. + +@node Example Side by Side +@subsection An Example of Side by Side Format + +Here is the output of the command @samp{diff -y -W 72 lao tzu} +(@pxref{Sample diff Input}, for the complete contents of the two files). + +@example +The Way that can be told of is n < +The name that can be named is no < +The Nameless is the origin of He The Nameless is the origin of He +The Named is the mother of all t | The named is the mother of all t + > +Therefore let there always be no Therefore let there always be no + so we may see their subtlety, so we may see their subtlety, +And let there always be being, And let there always be being, + so we may see their outcome. so we may see their outcome. +The two are the same, The two are the same, +But after they are produced, But after they are produced, + they have different names. they have different names. + > They both may be called deep and + > Deeper and more profound, + > The door of all subtleties! +@end example + +@node Normal +@section Showing Differences Without Context +@cindex normal output format +@cindex @samp{<} output format + +The ``normal'' @command{diff} output format shows each hunk of differences +without any surrounding context. Sometimes such output is the clearest +way to see how lines have changed, without the clutter of nearby +unchanged lines (although you can get similar results with the context +or unified formats by using 0 lines of context). However, this format +is no longer widely used for sending out patches; for that purpose, the +context format (@pxref{Context Format}) and the unified format +(@pxref{Unified Format}) are superior. Normal format is the default for +compatibility with older versions of @command{diff} and the @acronym{POSIX} +standard. Use the @option{--normal} option to select this output +format explicitly. + +@menu +* Example Normal:: Sample output in the normal format. +* Detailed Normal:: A detailed description of normal output format. +@end menu + +@node Example Normal +@subsection An Example of Normal Format + +Here is the output of the command @samp{diff lao tzu} +(@pxref{Sample diff Input}, for the complete contents of the two files). +Notice that it shows only the lines that are different between the two +files. + +@example +1,2d0 +< The Way that can be told of is not the eternal Way; +< The name that can be named is not the eternal name. +4c2,3 +< The Named is the mother of all things. +--- +> The named is the mother of all things. +> +11a11,13 +> They both may be called deep and profound. +> Deeper and more profound, +> The door of all subtleties! +@end example + +@node Detailed Normal +@subsection Detailed Description of Normal Format + +The normal output format consists of one or more hunks of differences; +each hunk shows one area where the files differ. Normal format hunks +look like this: + +@example +@var{change-command} +< @var{from-file-line} +< @var{from-file-line}@dots{} +--- +> @var{to-file-line} +> @var{to-file-line}@dots{} +@end example + +There are three types of change commands. Each consists of a line +number or comma-separated range of lines in the first file, a single +character indicating the kind of change to make, and a line number or +comma-separated range of lines in the second file. All line numbers are +the original line numbers in each file. The types of change commands +are: + +@table @samp +@item @var{l}a@var{r} +Add the lines in range @var{r} of the second file after line @var{l} of +the first file. For example, @samp{8a12,15} means append lines 12--15 +of file 2 after line 8 of file 1; or, if changing file 2 into file 1, +delete lines 12--15 of file 2. + +@item @var{f}c@var{t} +Replace the lines in range @var{f} of the first file with lines in range +@var{t} of the second file. This is like a combined add and delete, but +more compact. For example, @samp{5,7c8,10} means change lines 5--7 of +file 1 to read as lines 8--10 of file 2; or, if changing file 2 into +file 1, change lines 8--10 of file 2 to read as lines 5--7 of file 1. + +@item @var{r}d@var{l} +Delete the lines in range @var{r} from the first file; line @var{l} is where +they would have appeared in the second file had they not been deleted. +For example, @samp{5,7d3} means delete lines 5--7 of file 1; or, if +changing file 2 into file 1, append lines 5--7 of file 1 after line 3 of +file 2. +@end table + +@node Scripts +@section Making Edit Scripts +@cindex script output formats + +Several output modes produce command scripts for editing @var{from-file} +to produce @var{to-file}. + +@menu +* ed Scripts:: Using @command{diff} to produce commands for @command{ed}. +* Forward ed:: Making forward @command{ed} scripts. +* RCS:: A special @command{diff} output format used by @acronym{RCS}. +@end menu + +@node ed Scripts +@subsection @command{ed} Scripts +@cindex @command{ed} script output format + +@command{diff} can produce commands that direct the @command{ed} text editor +to change the first file into the second file. Long ago, this was the +only output mode that was suitable for editing one file into another +automatically; today, with @command{patch}, it is almost obsolete. Use the +@option{-e} or @option{--ed} option to select this output format. + +Like the normal format (@pxref{Normal}), this output format does not +show any context; unlike the normal format, it does not include the +information necessary to apply the diff in reverse (to produce the first +file if all you have is the second file and the diff). + +If the file @file{d} contains the output of @samp{diff -e old new}, then +the command @samp{(cat d && echo w) | ed - old} edits @file{old} to make +it a copy of @file{new}. More generally, if @file{d1}, @file{d2}, +@dots{}, @file{dN} contain the outputs of @samp{diff -e old new1}, +@samp{diff -e new1 new2}, @dots{}, @samp{diff -e newN-1 newN}, +respectively, then the command @samp{(cat d1 d2 @dots{} dN && echo w) | +ed - old} edits @file{old} to make it a copy of @file{newN}. + +@menu +* Example ed:: A sample @command{ed} script. +* Detailed ed:: A detailed description of @command{ed} format. +@end menu + +@node Example ed +@subsubsection Example @command{ed} Script + +Here is the output of @samp{diff -e lao tzu} (@pxref{Sample +diff Input}, for the complete contents of the two files): + +@example +11a +They both may be called deep and profound. +Deeper and more profound, +The door of all subtleties! +. +4c +The named is the mother of all things. + +. +1,2d +@end example + +@node Detailed ed +@subsubsection Detailed Description of @command{ed} Format + +The @command{ed} output format consists of one or more hunks of +differences. The changes closest to the ends of the files come first so +that commands that change the number of lines do not affect how +@command{ed} interprets line numbers in succeeding commands. @command{ed} +format hunks look like this: + +@example +@var{change-command} +@var{to-file-line} +@var{to-file-line}@dots{} +. +@end example + +Because @command{ed} uses a single period on a line to indicate the +end of input, @acronym{GNU} @command{diff} protects lines of changes +that contain a single period on a line by writing two periods instead, +then writing a subsequent @command{ed} command to change the two +periods into one. The @command{ed} format cannot represent an +incomplete line, so if the second file ends in a changed incomplete +line, @command{diff} reports an error and then pretends that a newline +was appended. + +There are three types of change commands. Each consists of a line +number or comma-separated range of lines in the first file and a single +character indicating the kind of change to make. All line numbers are +the original line numbers in the file. The types of change commands +are: + +@table @samp +@item @var{l}a +Add text from the second file after line @var{l} in the first file. For +example, @samp{8a} means to add the following lines after line 8 of file +1. + +@item @var{r}c +Replace the lines in range @var{r} in the first file with the following +lines. Like a combined add and delete, but more compact. For example, +@samp{5,7c} means change lines 5--7 of file 1 to read as the text file +2. + +@item @var{r}d +Delete the lines in range @var{r} from the first file. For example, +@samp{5,7d} means delete lines 5--7 of file 1. +@end table + +@node Forward ed +@subsection Forward @command{ed} Scripts +@cindex forward @command{ed} script output format + +@command{diff} can produce output that is like an @command{ed} script, but +with hunks in forward (front to back) order. The format of the commands +is also changed slightly: command characters precede the lines they +modify, spaces separate line numbers in ranges, and no attempt is made +to disambiguate hunk lines consisting of a single period. Like +@command{ed} format, forward @command{ed} format cannot represent incomplete +lines. + +Forward @command{ed} format is not very useful, because neither @command{ed} +nor @command{patch} can apply diffs in this format. It exists mainly for +compatibility with older versions of @command{diff}. Use the @option{-f} or +@option{--forward-ed} option to select it. + +@node RCS +@subsection @acronym{RCS} Scripts +@cindex @acronym{RCS} script output format + +The @acronym{RCS} output format is designed specifically for use by +the Revision Control System, which is a set of free programs used for +organizing different versions and systems of files. Use the +@option{-n} or @option{--rcs} option to select this output format. It +is like the forward @command{ed} format (@pxref{Forward ed}), but it +can represent arbitrary changes to the contents of a file because it +avoids the forward @command{ed} format's problems with lines +consisting of a single period and with incomplete lines. Instead of +ending text sections with a line consisting of a single period, each +command specifies the number of lines it affects; a combination of the +@samp{a} and @samp{d} commands are used instead of @samp{c}. Also, if +the second file ends in a changed incomplete line, then the output +also ends in an incomplete line. + +Here is the output of @samp{diff -n lao tzu} (@pxref{Sample +diff Input}, for the complete contents of the two files): + +@example +d1 2 +d4 1 +a4 2 +The named is the mother of all things. + +a11 3 +They both may be called deep and profound. +Deeper and more profound, +The door of all subtleties! +@end example + +@node If-then-else +@section Merging Files with If-then-else +@cindex merged output format +@cindex if-then-else output format +@cindex C if-then-else output format +@cindex @command{ifdef} output format + +You can use @command{diff} to merge two files of C source code. The output +of @command{diff} in this format contains all the lines of both files. +Lines common to both files are output just once; the differing parts are +separated by the C preprocessor directives @code{#ifdef @var{name}} or +@code{#ifndef @var{name}}, @code{#else}, and @code{#endif}. When +compiling the output, you select which version to use by either defining +or leaving undefined the macro @var{name}. + +To merge two files, use @command{diff} with the @option{-D @var{name}} or +@option{--ifdef=@var{name}} option. The argument @var{name} is the C +preprocessor identifier to use in the @code{#ifdef} and @code{#ifndef} +directives. + +For example, if you change an instance of @code{wait (&s)} to +@code{waitpid (-1, &s, 0)} and then merge the old and new files with +the @option{--ifdef=HAVE_WAITPID} option, then the affected part of your code +might look like this: + +@example + do @{ +#ifndef HAVE_WAITPID + if ((w = wait (&s)) < 0 && errno != EINTR) +#else /* HAVE_WAITPID */ + if ((w = waitpid (-1, &s, 0)) < 0 && errno != EINTR) +#endif /* HAVE_WAITPID */ + return w; + @} while (w != child); +@end example + +You can specify formats for languages other than C by using line group +formats and line formats, as described in the next sections. + +@menu +* Line Group Formats:: Formats for general if-then-else line groups. +* Line Formats:: Formats for each line in a line group. +* Example If-then-else:: Sample if-then-else format output. +* Detailed If-then-else:: A detailed description of if-then-else format. +@end menu + +@node Line Group Formats +@subsection Line Group Formats +@cindex line group formats +@cindex formats for if-then-else line groups + +Line group formats let you specify formats suitable for many +applications that allow if-then-else input, including programming +languages and text formatting languages. A line group format specifies +the output format for a contiguous group of similar lines. + +For example, the following command compares the TeX files @file{old} +and @file{new}, and outputs a merged file in which old regions are +surrounded by @samp{\begin@{em@}}-@samp{\end@{em@}} lines, and new +regions are surrounded by @samp{\begin@{bf@}}-@samp{\end@{bf@}} lines. + +@example +diff \ + --old-group-format='\begin@{em@} +%<\end@{em@} +' \ + --new-group-format='\begin@{bf@} +%>\end@{bf@} +' \ + old new +@end example + +The following command is equivalent to the above example, but it is a +little more verbose, because it spells out the default line group formats. + +@example +diff \ + --old-group-format='\begin@{em@} +%<\end@{em@} +' \ + --new-group-format='\begin@{bf@} +%>\end@{bf@} +' \ + --unchanged-group-format='%=' \ + --changed-group-format='\begin@{em@} +%<\end@{em@} +\begin@{bf@} +%>\end@{bf@} +' \ + old new +@end example + +Here is a more advanced example, which outputs a diff listing with +headers containing line numbers in a ``plain English'' style. + +@example +diff \ + --unchanged-group-format='' \ + --old-group-format='-------- %dn line%(n=1?:s) deleted at %df: +%<' \ + --new-group-format='-------- %dN line%(N=1?:s) added after %de: +%>' \ + --changed-group-format='-------- %dn line%(n=1?:s) changed at %df: +%<-------- to: +%>' \ + old new +@end example + +To specify a line group format, use @command{diff} with one of the options +listed below. You can specify up to four line group formats, one for +each kind of line group. You should quote @var{format}, because it +typically contains shell metacharacters. + +@table @option +@item --old-group-format=@var{format} +These line groups are hunks containing only lines from the first file. +The default old group format is the same as the changed group format if +it is specified; otherwise it is a format that outputs the line group as-is. + +@item --new-group-format=@var{format} +These line groups are hunks containing only lines from the second +file. The default new group format is same as the changed group +format if it is specified; otherwise it is a format that outputs the +line group as-is. + +@item --changed-group-format=@var{format} +These line groups are hunks containing lines from both files. The +default changed group format is the concatenation of the old and new +group formats. + +@item --unchanged-group-format=@var{format} +These line groups contain lines common to both files. The default +unchanged group format is a format that outputs the line group as-is. +@end table + +In a line group format, ordinary characters represent themselves; +conversion specifications start with @samp{%} and have one of the +following forms. + +@table @samp +@item %< +stands for the lines from the first file, including the trailing newline. +Each line is formatted according to the old line format (@pxref{Line Formats}). + +@item %> +stands for the lines from the second file, including the trailing newline. +Each line is formatted according to the new line format. + +@item %= +stands for the lines common to both files, including the trailing newline. +Each line is formatted according to the unchanged line format. + +@item %% +stands for @samp{%}. + +@item %c'@var{C}' +where @var{C} is a single character, stands for @var{C}. +@var{C} may not be a backslash or an apostrophe. +For example, @samp{%c':'} stands for a colon, even inside +the then-part of an if-then-else format, which a colon would +normally terminate. + +@item %c'\@var{O}' +where @var{O} is a string of 1, 2, or 3 octal digits, +stands for the character with octal code @var{O}. +For example, @samp{%c'\0'} stands for a null character. + +@item @var{F}@var{n} +where @var{F} is a @code{printf} conversion specification and @var{n} is one +of the following letters, stands for @var{n}'s value formatted with @var{F}. + +@table @samp +@item e +The line number of the line just before the group in the old file. + +@item f +The line number of the first line in the group in the old file; +equals @var{e} + 1. + +@item l +The line number of the last line in the group in the old file. + +@item m +The line number of the line just after the group in the old file; +equals @var{l} + 1. + +@item n +The number of lines in the group in the old file; equals @var{l} - @var{f} + 1. + +@item E, F, L, M, N +Likewise, for lines in the new file. + +@end table + +@vindex LC_NUMERIC +The @code{printf} conversion specification can be @samp{%d}, +@samp{%o}, @samp{%x}, or @samp{%X}, specifying decimal, octal, +lower case hexadecimal, or upper case hexadecimal output +respectively. After the @samp{%} the following options can appear in +sequence: a series of zero or more flags; an integer +specifying the minimum field width; and a period followed by an +optional integer specifying the minimum number of digits. +The flags are @samp{-} for left-justification, @samp{'} for separating +the digit into groups as specified by the @env{LC_NUMERIC} locale category, +and @samp{0} for padding with zeros instead of spaces. +For example, @samp{%5dN} prints the number of new lines in the group +in a field of width 5 characters, using the @code{printf} format @code{"%5d"}. + +@item (@var{A}=@var{B}?@var{T}:@var{E}) +If @var{A} equals @var{B} then @var{T} else @var{E}. +@var{A} and @var{B} are each either a decimal constant +or a single letter interpreted as above. +This format spec is equivalent to @var{T} if +@var{A}'s value equals @var{B}'s; otherwise it is equivalent to @var{E}. + +For example, @samp{%(N=0?no:%dN) line%(N=1?:s)} is equivalent to +@samp{no lines} if @var{N} (the number of lines in the group in the +new file) is 0, to @samp{1 line} if @var{N} is 1, and to @samp{%dN lines} +otherwise. +@end table + +@node Line Formats +@subsection Line Formats +@cindex line formats + +Line formats control how each line taken from an input file is +output as part of a line group in if-then-else format. + +For example, the following command outputs text with a one-character +change indicator to the left of the text. The first character of output +is @samp{-} for deleted lines, @samp{|} for added lines, and a space for +unchanged lines. The formats contain newline characters where newlines +are desired on output. + +@example +diff \ + --old-line-format='-%l +' \ + --new-line-format='|%l +' \ + --unchanged-line-format=' %l +' \ + old new +@end example + +To specify a line format, use one of the following options. You should +quote @var{format}, since it often contains shell metacharacters. + +@table @option +@item --old-line-format=@var{format} +formats lines just from the first file. + +@item --new-line-format=@var{format} +formats lines just from the second file. + +@item --unchanged-line-format=@var{format} +formats lines common to both files. + +@item --line-format=@var{format} +formats all lines; in effect, it sets all three above options simultaneously. +@end table + +In a line format, ordinary characters represent themselves; +conversion specifications start with @samp{%} and have one of the +following forms. + +@table @samp +@item %l +stands for the contents of the line, not counting its trailing +newline (if any). This format ignores whether the line is incomplete; +@xref{Incomplete Lines}. + +@item %L +stands for the contents of the line, including its trailing newline +(if any). If a line is incomplete, this format preserves its +incompleteness. + +@item %% +stands for @samp{%}. + +@item %c'@var{C}' +where @var{C} is a single character, stands for @var{C}. +@var{C} may not be a backslash or an apostrophe. +For example, @samp{%c':'} stands for a colon. + +@item %c'\@var{O}' +where @var{O} is a string of 1, 2, or 3 octal digits, +stands for the character with octal code @var{O}. +For example, @samp{%c'\0'} stands for a null character. + +@item @var{F}n +where @var{F} is a @code{printf} conversion specification, +stands for the line number formatted with @var{F}. +For example, @samp{%.5dn} prints the line number using the +@code{printf} format @code{"%.5d"}. @xref{Line Group Formats}, for +more about printf conversion specifications. + +@end table + +The default line format is @samp{%l} followed by a newline character. + +If the input contains tab characters and it is important that they line +up on output, you should ensure that @samp{%l} or @samp{%L} in a line +format is just after a tab stop (e.g.@: by preceding @samp{%l} or +@samp{%L} with a tab character), or you should use the @option{-t} or +@option{--expand-tabs} option. + +Taken together, the line and line group formats let you specify many +different formats. For example, the following command uses a format +similar to normal @command{diff} format. You can tailor this command +to get fine control over @command{diff} output. + +@example +diff \ + --old-line-format='< %l +' \ + --new-line-format='> %l +' \ + --old-group-format='%df%(f=l?:,%dl)d%dE +%<' \ + --new-group-format='%dea%dF%(F=L?:,%dL) +%>' \ + --changed-group-format='%df%(f=l?:,%dl)c%dF%(F=L?:,%dL) +%<--- +%>' \ + --unchanged-group-format='' \ + old new +@end example + +@node Example If-then-else +@subsection An Example of If-then-else Format + +Here is the output of @samp{diff -DTWO lao tzu} (@pxref{Sample +diff Input}, for the complete contents of the two files): + +@example +#ifndef TWO +The Way that can be told of is not the eternal Way; +The name that can be named is not the eternal name. +#endif /* ! TWO */ +The Nameless is the origin of Heaven and Earth; +#ifndef TWO +The Named is the mother of all things. +#else /* TWO */ +The named is the mother of all things. + +#endif /* TWO */ +Therefore let there always be non-being, + so we may see their subtlety, +And let there always be being, + so we may see their outcome. +The two are the same, +But after they are produced, + they have different names. +#ifdef TWO +They both may be called deep and profound. +Deeper and more profound, +The door of all subtleties! +#endif /* TWO */ +@end example + +@node Detailed If-then-else +@subsection Detailed Description of If-then-else Format + +For lines common to both files, @command{diff} uses the unchanged line +group format. For each hunk of differences in the merged output +format, if the hunk contains only lines from the first file, +@command{diff} uses the old line group format; if the hunk contains only +lines from the second file, @command{diff} uses the new group format; +otherwise, @command{diff} uses the changed group format. + +The old, new, and unchanged line formats specify the output format of +lines from the first file, lines from the second file, and lines common +to both files, respectively. + +The option @option{--ifdef=@var{name}} is equivalent to +the following sequence of options using shell syntax: + +@example +--old-group-format='#ifndef @var{name} +%<#endif /* ! @var{name} */ +' \ +--new-group-format='#ifdef @var{name} +%>#endif /* @var{name} */ +' \ +--unchanged-group-format='%=' \ +--changed-group-format='#ifndef @var{name} +%<#else /* @var{name} */ +%>#endif /* @var{name} */ +' +@end example + +You should carefully check the @command{diff} output for proper nesting. +For example, when using the @option{-D @var{name}} or +@option{--ifdef=@var{name}} option, you should check that if the +differing lines contain any of the C preprocessor directives +@samp{#ifdef}, @samp{#ifndef}, @samp{#else}, @samp{#elif}, or +@samp{#endif}, they are nested properly and match. If they don't, you +must make corrections manually. It is a good idea to carefully check +the resulting code anyway to make sure that it really does what you +want it to; depending on how the input files were produced, the output +might contain duplicate or otherwise incorrect code. + +The @command{patch} @option{-D @var{name}} option behaves like +the @command{diff} @option{-D @var{name}} option, except it operates on +a file and a diff to produce a merged file; @xref{patch Options}. + +@node Incomplete Lines +@chapter Incomplete Lines +@cindex incomplete lines +@cindex full lines +@cindex newline treatment by @command{diff} + +When an input file ends in a non-newline character, its last line is +called an @dfn{incomplete line} because its last character is not a +newline. All other lines are called @dfn{full lines} and end in a +newline character. Incomplete lines do not match full lines unless +differences in white space are ignored (@pxref{White Space}). + +An incomplete line is normally distinguished on output from a full +line by a following line that starts with @samp{\}. However, the +@acronym{RCS} format (@pxref{RCS}) outputs the incomplete line as-is, +without any trailing newline or following line. The side by side +format normally represents incomplete lines as-is, but in some cases +uses a @samp{\} or @samp{/} gutter marker; @xref{Side by Side}. The +if-then-else line format preserves a line's incompleteness with +@samp{%L}, and discards the newline with @samp{%l}; @xref{Line +Formats}. Finally, with the @command{ed} and forward @command{ed} +output formats (@pxref{Output Formats}) @command{diff} cannot +represent an incomplete line, so it pretends there was a newline and +reports an error. + +For example, suppose @file{F} and @file{G} are one-byte files that +contain just @samp{f} and @samp{g}, respectively. Then @samp{diff F G} +outputs + +@example +1c1 +< f +\ No newline at end of file +--- +> g +\ No newline at end of file +@end example + +@noindent +(The exact message may differ in non-English locales.) +@samp{diff -n F G} outputs the following without a trailing newline: + +@example +d1 1 +a1 1 +g +@end example + +@noindent +@samp{diff -e F G} reports two errors and outputs the following: + +@example +1c +g +. +@end example + +@node Comparing Directories +@chapter Comparing Directories + +@vindex LC_COLLATE +You can use @command{diff} to compare some or all of the files in two +directory trees. When both file name arguments to @command{diff} are +directories, it compares each file that is contained in both +directories, examining file names in alphabetical order as specified by +the @env{LC_COLLATE} locale category. Normally +@command{diff} is silent about pairs of files that contain no differences, +but if you use the @option{-s} or @option{--report-identical-files} option, +it reports pairs of identical files. Normally @command{diff} reports +subdirectories common to both directories without comparing +subdirectories' files, but if you use the @option{-r} or +@option{--recursive} option, it compares every corresponding pair of files +in the directory trees, as many levels deep as they go. + +For file names that are in only one of the directories, @command{diff} +normally does not show the contents of the file that exists; it reports +only that the file exists in that directory and not in the other. You +can make @command{diff} act as though the file existed but was empty in the +other directory, so that it outputs the entire contents of the file that +actually exists. (It is output as either an insertion or a +deletion, depending on whether it is in the first or the second +directory given.) To do this, use the @option{-N} or @option{--new-file} +option. + +If the older directory contains one or more large files that are not in +the newer directory, you can make the patch smaller by using the +@option{--unidirectional-new-file} option instead of @option{-N}. +This option is like @option{-N} except that it only inserts the contents +of files that appear in the second directory but not the first (that is, +files that were added). At the top of the patch, write instructions for +the user applying the patch to remove the files that were deleted before +applying the patch. @xref{Making Patches}, for more discussion of +making patches for distribution. + +To ignore some files while comparing directories, use the @option{-x +@var{pattern}} or @option{--exclude=@var{pattern}} option. This option +ignores any files or subdirectories whose base names match the shell +pattern @var{pattern}. Unlike in the shell, a period at the start of +the base of a file name matches a wildcard at the start of a pattern. +You should enclose @var{pattern} in quotes so that the shell does not +expand it. For example, the option @option{-x '*.[ao]'} ignores any file +whose name ends with @samp{.a} or @samp{.o}. + +This option accumulates if you specify it more than once. For example, +using the options @option{-x 'RCS' -x '*,v'} ignores any file or +subdirectory whose base name is @samp{RCS} or ends with @samp{,v}. + +If you need to give this option many times, you can instead put the +patterns in a file, one pattern per line, and use the @option{-X +@var{file}} or @option{--exclude-from=@var{file}} option. Trailing +white space and empty lines are ignored in the pattern file. + +If you have been comparing two directories and stopped partway through, +later you might want to continue where you left off. You can do this by +using the @option{-S @var{file}} or @option{--starting-file=@var{file}} +option. This compares only the file @var{file} and all alphabetically +later files in the topmost directory level. + +If two directories differ only in that file names are lower case in +one directory and upper case in the upper, @command{diff} normally +reports many differences because it compares file names in a +case sensitive way. With the @option{--ignore-file-name-case} option, +@command{diff} ignores case differences in file names, so that for example +the contents of the file @file{Tao} in one directory are compared to +the contents of the file @file{TAO} in the other. The +@option{--no-ignore-file-name-case} option cancels the effect of the +@option{--ignore-file-name-case} option, reverting to the default +behavior. + +If an @option{-x @var{pattern}} or @option{--exclude=@var{pattern}} +option, or an @option{-X @var{file}} or +@option{--exclude-from=@var{file}} option, +is specified while the @option{--ignore-file-name-case} option is in +effect, case is ignored when excluding file names matching the +specified patterns. + +@node Adjusting Output +@chapter Making @command{diff} Output Prettier + +@command{diff} provides several ways to adjust the appearance of its output. +These adjustments can be applied to any output format. + +@menu +* Tabs:: Preserving the alignment of tab stops. +* Pagination:: Page numbering and time-stamping @command{diff} output. +@end menu + +@node Tabs +@section Preserving Tab Stop Alignment +@cindex tab stop alignment +@cindex aligning tab stops + +The lines of text in some of the @command{diff} output formats are +preceded by one or two characters that indicate whether the text is +inserted, deleted, or changed. The addition of those characters can +cause tabs to move to the next tab stop, throwing off the alignment of +columns in the line. @acronym{GNU} @command{diff} provides two ways +to make tab-aligned columns line up correctly. + +The first way is to have @command{diff} convert all tabs into the correct +number of spaces before outputting them; select this method with the +@option{-t} or @option{--expand-tabs} option. To use this form of output with +@command{patch}, you must give @command{patch} the @option{-l} or +@option{--ignore-white-space} option (@pxref{Changed White Space}, for more +information). @command{diff} normally assumes that tab stops are set +every 8 print columns, but this can be altered by the +@option{--tabsize=@var{columns}} option. + +The other method for making tabs line up correctly is to add a tab +character instead of a space after the indicator character at the +beginning of the line. This ensures that all following tab characters +are in the same position relative to tab stops that they were in the +original files, so that the output is aligned correctly. Its +disadvantage is that it can make long lines too long to fit on one line +of the screen or the paper. It also does not work with the unified +output format, which does not have a space character after the change +type indicator character. Select this method with the @option{-T} or +@option{--initial-tab} option. + +@node Pagination +@section Paginating @command{diff} Output +@cindex paginating @command{diff} output + +It can be convenient to have long output page-numbered and time-stamped. +The @option{-l} or @option{--paginate} option does this by sending the +@command{diff} output through the @command{pr} program. Here is what the page +header might look like for @samp{diff -lc lao tzu}: + +@example +2002-02-22 14:20 diff -lc lao tzu Page 1 +@end example + +@node diff Performance +@chapter @command{diff} Performance Tradeoffs +@cindex performance of @command{diff} + +@acronym{GNU} @command{diff} runs quite efficiently; however, in some +circumstances you can cause it to run faster or produce a more compact +set of changes. + +One way to improve @command{diff} performance is to use hard or +symbolic links to files instead of copies. This improves performance +because @command{diff} normally does not need to read two hard or +symbolic links to the same file, since their contents must be +identical. For example, suppose you copy a large directory hierarchy, +make a few changes to the copy, and then often use @samp{diff -r} to +compare the original to the copy. If the original files are +read-only, you can greatly improve performance by creating the copy +using hard or symbolic links (e.g., with @acronym{GNU} @samp{cp -lR} or +@samp{cp -sR}). Before editing a file in the copy for the first time, +you should break the link and replace it with a regular copy. + +You can also affect the performance of @acronym{GNU} @command{diff} by +giving it options that change the way it compares files. +Performance has more than one dimension. These options improve one +aspect of performance at the cost of another, or they improve +performance in some cases while hurting it in others. + +The way that @acronym{GNU} @command{diff} determines which lines have +changed always comes up with a near-minimal set of differences. +Usually it is good enough for practical purposes. If the +@command{diff} output is large, you might want @command{diff} to use a +modified algorithm that sometimes produces a smaller set of +differences. The @option{-d} or @option{--minimal} option does this; +however, it can also cause @command{diff} to run more slowly than +usual, so it is not the default behavior. + +When the files you are comparing are large and have small groups of +changes scattered throughout them, you can use the +@option{--speed-large-files} option to make a different modification to +the algorithm that @command{diff} uses. If the input files have a constant +small density of changes, this option speeds up the comparisons without +changing the output. If not, @command{diff} might produce a larger set of +differences; however, the output will still be correct. + +Normally @command{diff} discards the prefix and suffix that is common to +both files before it attempts to find a minimal set of differences. +This makes @command{diff} run faster, but occasionally it may produce +non-minimal output. The @option{--horizon-lines=@var{lines}} option +prevents @command{diff} from discarding the last @var{lines} lines of the +prefix and the first @var{lines} lines of the suffix. This gives +@command{diff} further opportunities to find a minimal output. + +Suppose a run of changed lines includes a sequence of lines at one end +and there is an identical sequence of lines just outside the other end. +The @command{diff} command is free to choose which identical sequence is +included in the hunk. In this case, @command{diff} normally shifts the +hunk's boundaries when this merges adjacent hunks, or shifts a hunk's +lines towards the end of the file. Merging hunks can make the output +look nicer in some cases. + +@node Comparing Three Files +@chapter Comparing Three Files +@cindex comparing three files +@cindex format of @command{diff3} output + +Use the program @command{diff3} to compare three files and show any +differences among them. (@command{diff3} can also merge files; see +@ref{diff3 Merging}). + +The ``normal'' @command{diff3} output format shows each hunk of +differences without surrounding context. Hunks are labeled depending +on whether they are two-way or three-way, and lines are annotated by +their location in the input files. + +@xref{Invoking diff3}, for more information on how to run @command{diff3}. + +@menu +* Sample diff3 Input:: Sample @command{diff3} input for examples. +* Example diff3 Normal:: Sample output in the normal format. +* diff3 Hunks:: The format of normal output format. +* Detailed diff3 Normal:: A detailed description of normal output format. +@end menu + +@node Sample diff3 Input +@section A Third Sample Input File +@cindex @command{diff3} sample input +@cindex sample input for @command{diff3} + +Here is a third sample file that will be used in examples to illustrate +the output of @command{diff3} and how various options can change it. The +first two files are the same that we used for @command{diff} (@pxref{Sample +diff Input}). This is the third sample file, called @file{tao}: + +@example +The Way that can be told of is not the eternal Way; +The name that can be named is not the eternal name. +The Nameless is the origin of Heaven and Earth; +The named is the mother of all things. + +Therefore let there always be non-being, + so we may see their subtlety, +And let there always be being, + so we may see their result. +The two are the same, +But after they are produced, + they have different names. + + -- The Way of Lao-Tzu, tr. Wing-tsit Chan +@end example + +@node Example diff3 Normal +@section An Example of @command{diff3} Normal Format + +Here is the output of the command @samp{diff3 lao tzu tao} +(@pxref{Sample diff3 Input}, for the complete contents of the files). +Notice that it shows only the lines that are different among the three +files. + +@example +====2 +1:1,2c +3:1,2c + The Way that can be told of is not the eternal Way; + The name that can be named is not the eternal name. +2:0a +====1 +1:4c + The Named is the mother of all things. +2:2,3c +3:4,5c + The named is the mother of all things. + +====3 +1:8c +2:7c + so we may see their outcome. +3:9c + so we may see their result. +==== +1:11a +2:11,13c + They both may be called deep and profound. + Deeper and more profound, + The door of all subtleties! +3:13,14c + + -- The Way of Lao-Tzu, tr. Wing-tsit Chan +@end example + +@node Detailed diff3 Normal +@section Detailed Description of @command{diff3} Normal Format + +Each hunk begins with a line marked @samp{====}. Three-way hunks have +plain @samp{====} lines, and two-way hunks have @samp{1}, @samp{2}, or +@samp{3} appended to specify which of the three input files differ in +that hunk. The hunks contain copies of two or three sets of input +lines each preceded by one or two commands identifying where the lines +came from. + +Normally, two spaces precede each copy of an input line to distinguish +it from the commands. But with the @option{-T} or @option{--initial-tab} +option, @command{diff3} uses a tab instead of two spaces; this lines up +tabs correctly. @xref{Tabs}, for more information. + +Commands take the following forms: + +@table @samp +@item @var{file}:@var{l}a +This hunk appears after line @var{l} of file @var{file}, and +contains no lines in that file. To edit this file to yield the other +files, one must append hunk lines taken from the other files. For +example, @samp{1:11a} means that the hunk follows line 11 in the first +file and contains no lines from that file. + +@item @var{file}:@var{r}c +This hunk contains the lines in the range @var{r} of file @var{file}. +The range @var{r} is a comma-separated pair of line numbers, or just one +number if the range is a singleton. To edit this file to yield the +other files, one must change the specified lines to be the lines taken +from the other files. For example, @samp{2:11,13c} means that the hunk +contains lines 11 through 13 from the second file. +@end table + +If the last line in a set of input lines is incomplete +(@pxref{Incomplete Lines}), it is distinguished on output from a full +line by a following line that starts with @samp{\}. + +@node diff3 Hunks +@section @command{diff3} Hunks +@cindex hunks for @command{diff3} +@cindex @command{diff3} hunks + +Groups of lines that differ in two or three of the input files are +called @dfn{diff3 hunks}, by analogy with @command{diff} hunks +(@pxref{Hunks}). If all three input files differ in a @command{diff3} +hunk, the hunk is called a @dfn{three-way hunk}; if just two input files +differ, it is a @dfn{two-way hunk}. + +As with @command{diff}, several solutions are possible. When comparing the +files @samp{A}, @samp{B}, and @samp{C}, @command{diff3} normally finds +@command{diff3} hunks by merging the two-way hunks output by the two +commands @samp{diff A B} and @samp{diff A C}. This does not necessarily +minimize the size of the output, but exceptions should be rare. + +For example, suppose @file{F} contains the three lines @samp{a}, +@samp{b}, @samp{f}, @file{G} contains the lines @samp{g}, @samp{b}, +@samp{g}, and @file{H} contains the lines @samp{a}, @samp{b}, +@samp{h}. @samp{diff3 F G H} might output the following: + +@example +====2 +1:1c +3:1c + a +2:1c + g +==== +1:3c + f +2:3c + g +3:3c + h +@end example + +@noindent +because it found a two-way hunk containing @samp{a} in the first and +third files and @samp{g} in the second file, then the single line +@samp{b} common to all three files, then a three-way hunk containing +the last line of each file. + +@node diff3 Merging +@chapter Merging From a Common Ancestor +@cindex merging from a common ancestor + +When two people have made changes to copies of the same file, +@command{diff3} can produce a merged output that contains both sets of +changes together with warnings about conflicts. + +One might imagine programs with names like @command{diff4} and @command{diff5} +to compare more than three files simultaneously, but in practice the +need rarely arises. You can use @command{diff3} to merge three or more +sets of changes to a file by merging two change sets at a time. + +@command{diff3} can incorporate changes from two modified versions into a +common preceding version. This lets you merge the sets of changes +represented by the two newer files. Specify the common ancestor version +as the second argument and the two newer versions as the first and third +arguments, like this: + +@example +diff3 @var{mine} @var{older} @var{yours} +@end example + +@noindent +You can remember the order of the arguments by noting that they are in +alphabetical order. + +@cindex conflict +@cindex overlap +You can think of this as subtracting @var{older} from @var{yours} and +adding the result to @var{mine}, or as merging into @var{mine} the +changes that would turn @var{older} into @var{yours}. This merging is +well-defined as long as @var{mine} and @var{older} match in the +neighborhood of each such change. This fails to be true when all three +input files differ or when only @var{older} differs; we call this +a @dfn{conflict}. When all three input files differ, we call the +conflict an @dfn{overlap}. + +@command{diff3} gives you several ways to handle overlaps and conflicts. +You can omit overlaps or conflicts, or select only overlaps, +or mark conflicts with special @samp{<<<<<<<} and @samp{>>>>>>>} lines. + +@command{diff3} can output the merge results as an @command{ed} script that +that can be applied to the first file to yield the merged output. +However, it is usually better to have @command{diff3} generate the merged +output directly; this bypasses some problems with @command{ed}. + +@menu +* Which Changes:: Selecting changes to incorporate. +* Marking Conflicts:: Marking conflicts. +* Bypassing ed:: Generating merged output directly. +* Merging Incomplete Lines:: How @command{diff3} merges incomplete lines. +* Saving the Changed File:: Emulating System V behavior. +@end menu + +@node Which Changes +@section Selecting Which Changes to Incorporate +@cindex overlapping change, selection of +@cindex unmerged change + +You can select all unmerged changes from @var{older} to @var{yours} for merging +into @var{mine} with the @option{-e} or @option{--ed} option. You can +select only the nonoverlapping unmerged changes with @option{-3} or +@option{--easy-only}, and you can select only the overlapping changes with +@option{-x} or @option{--overlap-only}. + +The @option{-e}, @option{-3} and @option{-x} options select only +@dfn{unmerged changes}, i.e.@: changes where @var{mine} and @var{yours} +differ; they ignore changes from @var{older} to @var{yours} where +@var{mine} and @var{yours} are identical, because they assume that such +changes have already been merged. If this assumption is not a safe +one, you can use the @option{-A} or @option{--show-all} option +(@pxref{Marking Conflicts}). + +Here is the output of the command @command{diff3} with each of these three +options (@pxref{Sample diff3 Input}, for the complete contents of the files). +Notice that @option{-e} outputs the union of the disjoint sets of changes +output by @option{-3} and @option{-x}. + +Output of @samp{diff3 -e lao tzu tao}: +@example +11a + + -- The Way of Lao-Tzu, tr. Wing-tsit Chan +. +8c + so we may see their result. +. +@end example + +Output of @samp{diff3 -3 lao tzu tao}: +@example +8c + so we may see their result. +. +@end example + +Output of @samp{diff3 -x lao tzu tao}: +@example +11a + + -- The Way of Lao-Tzu, tr. Wing-tsit Chan +. +@end example + +@node Marking Conflicts +@section Marking Conflicts +@cindex conflict marking +@cindex @samp{<<<<<<<} for marking conflicts + +@command{diff3} can mark conflicts in the merged output by +bracketing them with special marker lines. A conflict +that comes from two files @var{A} and @var{B} is marked as follows: + +@example +<<<<<<< @var{A} +@r{lines from @var{A}} +======= +@r{lines from @var{B}} +>>>>>>> @var{B} +@end example + +A conflict that comes from three files @var{A}, @var{B} and @var{C} is +marked as follows: + +@example +<<<<<<< @var{A} +@r{lines from @var{A}} +||||||| @var{B} +@r{lines from @var{B}} +======= +@r{lines from @var{C}} +>>>>>>> @var{C} +@end example + +The @option{-A} or @option{--show-all} option acts like the @option{-e} +option, except that it brackets conflicts, and it outputs all changes +from @var{older} to @var{yours}, not just the unmerged changes. Thus, +given the sample input files (@pxref{Sample diff3 Input}), @samp{diff3 +-A lao tzu tao} puts brackets around the conflict where only @file{tzu} +differs: + +@example +<<<<<<< tzu +======= +The Way that can be told of is not the eternal Way; +The name that can be named is not the eternal name. +>>>>>>> tao +@end example + +And it outputs the three-way conflict as follows: + +@example +<<<<<<< lao +||||||| tzu +They both may be called deep and profound. +Deeper and more profound, +The door of all subtleties! +======= + + -- The Way of Lao-Tzu, tr. Wing-tsit Chan +>>>>>>> tao +@end example + +The @option{-E} or @option{--show-overlap} option outputs less information +than the @option{-A} or @option{--show-all} option, because it outputs only +unmerged changes, and it never outputs the contents of the second +file. Thus the @option{-E} option acts like the @option{-e} option, +except that it brackets the first and third files from three-way +overlapping changes. Similarly, @option{-X} acts like @option{-x}, except +it brackets all its (necessarily overlapping) changes. For example, +for the three-way overlapping change above, the @option{-E} and @option{-X} +options output the following: + +@example +<<<<<<< lao +======= + + -- The Way of Lao-Tzu, tr. Wing-tsit Chan +>>>>>>> tao +@end example + +If you are comparing files that have meaningless or uninformative names, +you can use the @option{--label=@var{label}} +option to show alternate names in the @samp{<<<<<<<}, @samp{|||||||} +and @samp{>>>>>>>} brackets. This option can be given up to three +times, once for each input file. Thus @samp{diff3 -A --label X +--label Y --label Z A +B C} acts like @samp{diff3 -A A B C}, except that the output looks like +it came from files named @samp{X}, @samp{Y} and @samp{Z} rather than +from files named @samp{A}, @samp{B} and @samp{C}. + +@node Bypassing ed +@section Generating the Merged Output Directly +@cindex merged @command{diff3} format + +With the @option{-m} or @option{--merge} option, @command{diff3} outputs the +merged file directly. This is more efficient than using @command{ed} to +generate it, and works even with non-text files that @command{ed} would +reject. If you specify @option{-m} without an @command{ed} script option, +@option{-A} is assumed. + +For example, the command @samp{diff3 -m lao tzu tao} +(@pxref{Sample diff3 Input} for a copy of the input files) would output +the following: + +@example +<<<<<<< tzu +======= +The Way that can be told of is not the eternal Way; +The name that can be named is not the eternal name. +>>>>>>> tao +The Nameless is the origin of Heaven and Earth; +The Named is the mother of all things. +Therefore let there always be non-being, + so we may see their subtlety, +And let there always be being, + so we may see their result. +The two are the same, +But after they are produced, + they have different names. +<<<<<<< lao +||||||| tzu +They both may be called deep and profound. +Deeper and more profound, +The door of all subtleties! +======= + + -- The Way of Lao-Tzu, tr. Wing-tsit Chan +>>>>>>> tao +@end example + +@node Merging Incomplete Lines +@section How @command{diff3} Merges Incomplete Lines +@cindex incomplete line merging + +With @option{-m}, incomplete lines (@pxref{Incomplete Lines}) are simply +copied to the output as they are found; if the merged output ends in an +conflict and one of the input files ends in an incomplete +line, succeeding @samp{|||||||}, @samp{=======} or @samp{>>>>>>>} +brackets appear somewhere other than the start of a line because +they are appended to the incomplete line. + +Without @option{-m}, if an @command{ed} script option is specified and an +incomplete line is found, @command{diff3} generates a warning and acts as +if a newline had been present. + +@node Saving the Changed File +@section Saving the Changed File +@cindex System V @command{diff3} compatibility + +Traditional Unix @command{diff3} generates an @command{ed} script without the +trailing @samp{w} and @samp{q} commands that save the changes. +System V @command{diff3} generates these extra commands. @acronym{GNU} +@command{diff3} normally behaves like traditional Unix +@command{diff3}, but with the @option{-i} option it behaves like +System V @command{diff3} and appends the @samp{w} and @samp{q} +commands. + +The @option{-i} option requires one of the @command{ed} script options +@option{-AeExX3}, and is incompatible with the merged output option +@option{-m}. + +@node Interactive Merging +@chapter Interactive Merging with @command{sdiff} +@cindex diff merging +@cindex interactive merging + +With @command{sdiff}, you can merge two files interactively based on a +side-by-side @option{-y} format comparison (@pxref{Side by Side}). Use +@option{-o @var{file}} or @option{--output=@var{file}} to specify where to +put the merged text. @xref{Invoking sdiff}, for more details on the +options to @command{sdiff}. + +Another way to merge files interactively is to use the Emacs Lisp +package @command{emerge}. @xref{emerge, , emerge, emacs, The +@acronym{GNU} Emacs Manual}, for more information. + +@menu +* sdiff Option Summary:: Summary of @command{sdiff} options. +* Merge Commands:: Merging two files interactively. +@end menu + +@node sdiff Option Summary +@section Specifying @command{diff} Options to @command{sdiff} +@cindex @command{sdiff} output format + +The following @command{sdiff} options have the same meaning as for +@command{diff}. @xref{diff Options}, for the use of these options. + +@example +-a -b -d -i -t -v +-B -E -I @var{regexp} + +--expand-tabs +--ignore-blank-lines --ignore-case +--ignore-matching-lines=@var{regexp} --ignore-space-change +--ignore-tab-expansion +--left-column --minimal --speed-large-files +--strip-trailing-cr --suppress-common-lines +--tabsize=@var{columns} --text --version --width=@var{columns} +@end example + +For historical reasons, @command{sdiff} has alternate names for some +options. The @option{-l} option is equivalent to the +@option{--left-column} option, and similarly @option{-s} is equivalent +to @option{--suppress-common-lines}. The meaning of the @command{sdiff} +@option{-w} and @option{-W} options is interchanged from that of +@command{diff}: with @command{sdiff}, @option{-w @var{columns}} is +equivalent to @option{--width=@var{columns}}, and @option{-W} is +equivalent to @option{--ignore-all-space}. @command{sdiff} without the +@option{-o} option is equivalent to @command{diff} with the @option{-y} +or @option{--side-by-side} option (@pxref{Side by Side}). + +@node Merge Commands +@section Merge Commands +@cindex merge commands +@cindex merging interactively + +Groups of common lines, with a blank gutter, are copied from the first +file to the output. After each group of differing lines, @command{sdiff} +prompts with @samp{%} and pauses, waiting for one of the following +commands. Follow each command with @key{RET}. + +@table @samp +@item e +Discard both versions. +Invoke a text editor on an empty temporary file, +then copy the resulting file to the output. + +@item eb +Concatenate the two versions, edit the result in a temporary file, +then copy the edited result to the output. + +@item ed +Like @samp{eb}, except precede each version with a header that +shows what file and lines the version came from. + +@item el +Edit a copy of the left version, then copy the result to the output. + +@item er +Edit a copy of the right version, then copy the result to the output. + +@item l +Copy the left version to the output. + +@item q +Quit. + +@item r +Copy the right version to the output. + +@item s +Silently copy common lines. + +@item v +Verbosely copy common lines. This is the default. +@end table + +@vindex EDITOR +The text editor invoked is specified by the @env{EDITOR} environment +variable if it is set. The default is system-dependent. + +@node Merging with patch +@chapter Merging with @command{patch} + +@command{patch} takes comparison output produced by @command{diff} and applies +the differences to a copy of the original file, producing a patched +version. With @command{patch}, you can distribute just the changes to a +set of files instead of distributing the entire file set; your +correspondents can apply @command{patch} to update their copy of the files +with your changes. @command{patch} automatically determines the diff +format, skips any leading or trailing headers, and uses the headers to +determine which file to patch. This lets your correspondents feed a +mail message containing a difference listing directly to +@command{patch}. + +@command{patch} detects and warns about common problems like forward +patches. It saves any patches that it could not apply. It can also maintain a +@code{patchlevel.h} file to ensure that your correspondents apply +diffs in the proper order. + +@command{patch} accepts a series of diffs in its standard input, usually +separated by headers that specify which file to patch. It applies +@command{diff} hunks (@pxref{Hunks}) one by one. If a hunk does not +exactly match the original file, @command{patch} uses heuristics to try to +patch the file as well as it can. If no approximate match can be found, +@command{patch} rejects the hunk and skips to the next hunk. @command{patch} +normally replaces each file @var{f} with its new version, putting reject +hunks (if any) into @samp{@var{f}.rej}. + +@xref{Invoking patch}, for detailed information on the options to +@command{patch}. + +@menu +* patch Input:: Selecting the type of @command{patch} input. +* Revision Control:: Getting files from @acronym{RCS}, @acronym{SCCS}, etc. +* Imperfect:: Dealing with imperfect patches. +* Creating and Removing:: Creating and removing files with a patch. +* Patching Time Stamps:: Updating time stamps on patched files. +* Multiple Patches:: Handling multiple patches in a file. +* patch Directories:: Changing directory and stripping directories. +* Backups:: Whether backup files are made. +* Backup Names:: Backup file names. +* Reject Names:: Reject file names. +* patch Messages:: Messages and questions @command{patch} can produce. +* patch and POSIX:: Conformance to the @acronym{POSIX} standard. +* patch and Tradition:: @acronym{GNU} versus traditional @command{patch}. +@end menu + +@node patch Input +@section Selecting the @command{patch} Input Format +@cindex @command{patch} input format + +@command{patch} normally determines which @command{diff} format the patch +file uses by examining its contents. For patch files that contain +particularly confusing leading text, you might need to use one of the +following options to force @command{patch} to interpret the patch file as a +certain format of diff. The output formats listed here are the only +ones that @command{patch} can understand. + +@table @option +@item -c +@itemx --context +context diff. + +@item -e +@itemx --ed +@command{ed} script. + +@item -n +@itemx --normal +normal diff. + +@item -u +@itemx --unified +unified diff. +@end table + +@node Revision Control +@section Revision Control +@cindex revision control +@cindex version control +@cindex @acronym{RCS} +@cindex ClearCase +@cindex @acronym{SCCS} + +If a nonexistent input file is under a revision control system +supported by @command{patch}, @command{patch} normally asks the user +whether to get (or check out) the file from the revision control +system. Patch currently supports @acronym{RCS}, ClearCase and +@acronym{SCCS}. Under @acronym{RCS} and @acronym{SCCS}, +@command{patch} also asks when the input file is read-only and matches +the default version in the revision control system. + +@vindex PATCH_GET +The @option{-g @var{num}} or @option{--get=@var{num}} option affects access +to files under supported revision control systems. If @var{num} is +positive, @command{patch} gets the file without asking the user; if +zero, @command{patch} neither asks the user nor gets the file; and if +negative, @command{patch} asks the user before getting the file. The +default value of @var{num} is given by the value of the +@env{PATCH_GET} environment variable if it is set; if not, the default +value is zero if @command{patch} is conforming to @acronym{POSIX}, negative +otherwise. @xref{patch and POSIX}. + +@vindex VERSION_CONTROL +The choice of revision control system is unaffected by the +@env{VERSION_CONTROL} environment variable (@pxref{Backup Names}). + +@node Imperfect +@section Applying Imperfect Patches +@cindex imperfect patch application + +@command{patch} tries to skip any leading text in the patch file, +apply the diff, and then skip any trailing text. Thus you can feed a +mail message directly to @command{patch}, and it should work. If the +entire diff is indented by a constant amount of white space, +@command{patch} automatically ignores the indentation. If a context +diff contains trailing carriage return on each line, @command{patch} +automatically ignores the carriage return. If a context diff has been +encapsulated by prepending @w{@samp{- }} to lines beginning with @samp{-} +as per @uref{ftp://ftp.isi.edu/in-notes/rfc934.txt, Internet RFC 934}, +@command{patch} automatically unencapsulates the input. + +However, certain other types of imperfect input require user +intervention or testing. + +@menu +* Changed White Space:: When tabs and spaces don't match exactly. +* Reversed Patches:: Applying reversed patches correctly. +* Inexact:: Helping @command{patch} find close matches. +* Dry Runs:: Predicting what @command{patch} will do. +@end menu + +@node Changed White Space +@subsection Applying Patches with Changed White Space +@cindex white space in patches + +Sometimes mailers, editors, or other programs change spaces into tabs, +or vice versa. If this happens to a patch file or an input file, the +files might look the same, but @command{patch} will not be able to match +them properly. If this problem occurs, use the @option{-l} or +@option{--ignore-white-space} option, which makes @command{patch} compare +blank characters (i.e.@: spaces and tabs) loosely so that any nonempty +sequence of blanks in the patch file matches any nonempty sequence of +blanks in the input files. Non-blank +characters must still match exactly. Each line of the context must +still match a line in the input file. + +@node Reversed Patches +@subsection Applying Reversed Patches +@cindex reversed patches + +Sometimes people run @command{diff} with the new file first instead of +second. This creates a diff that is ``reversed''. To apply such +patches, give @command{patch} the @option{-R} or @option{--reverse} option. +@command{patch} then attempts to swap each hunk around before applying it. +Rejects come out in the swapped format. + +Often @command{patch} can guess that the patch is reversed. If the first +hunk of a patch fails, @command{patch} reverses the hunk to see if it can +apply it that way. If it can, @command{patch} asks you if you want to have +the @option{-R} option set; if it can't, @command{patch} continues to apply +the patch normally. This method cannot detect a reversed patch if it is +a normal diff and the first command is an append (which should have been +a delete) since appends always succeed, because a null context matches +anywhere. But most patches add or change lines rather than delete them, +so most reversed normal diffs begin with a delete, which fails, and +@command{patch} notices. + +If you apply a patch that you have already applied, @command{patch} thinks +it is a reversed patch and offers to un-apply the patch. This could be +construed as a feature. If you did this inadvertently and you don't +want to un-apply the patch, just answer @samp{n} to this offer and to +the subsequent ``apply anyway'' question---or type @kbd{C-c} to kill the +@command{patch} process. + +@node Inexact +@subsection Helping @command{patch} Find Inexact Matches +@cindex inexact patches +@cindex fuzz factor when patching + +For context diffs, and to a lesser extent normal diffs, @command{patch} can +detect when the line numbers mentioned in the patch are incorrect, and +it attempts to find the correct place to apply each hunk of the patch. +As a first guess, it takes the line number mentioned in the hunk, plus +or minus any offset used in applying the previous hunk. If that is not +the correct place, @command{patch} scans both forward and backward for a +set of lines matching the context given in the hunk. + +First @command{patch} looks for a place where all lines of the context +match. If it cannot find such a place, and it is reading a context or +unified diff, and the maximum fuzz factor is set to 1 or more, then +@command{patch} makes another scan, ignoring the first and last line of +context. If that fails, and the maximum fuzz factor is set to 2 or +more, it makes another scan, ignoring the first two and last two lines +of context are ignored. It continues similarly if the maximum fuzz +factor is larger. + +The @option{-F @var{lines}} or @option{--fuzz=@var{lines}} option sets the +maximum fuzz factor to @var{lines}. This option only applies to context +and unified diffs; it ignores up to @var{lines} lines while looking for +the place to install a hunk. Note that a larger fuzz factor increases +the odds of making a faulty patch. The default fuzz factor is 2; there +is no point to setting it to more than the number of lines of context +in the diff, ordinarily 3. + +If @command{patch} cannot find a place to install a hunk of the patch, it +writes the hunk out to a reject file (@pxref{Reject Names}, for information +on how reject files are named). It writes out rejected hunks in context +format no matter what form the input patch is in. If the input is a +normal or @command{ed} diff, many of the contexts are simply null. The +line numbers on the hunks in the reject file may be different from those +in the patch file: they show the approximate location where @command{patch} +thinks the failed hunks belong in the new file rather than in the old +one. + +If the @option{--verbose} option is given, then +as it completes each hunk @command{patch} tells you whether the hunk +succeeded or failed, and if it failed, on which line (in the new file) +@command{patch} thinks the hunk should go. If this is different from the +line number specified in the diff, it tells you the offset. A single +large offset @emph{may} indicate that @command{patch} installed a hunk in +the wrong place. @command{patch} also tells you if it used a fuzz factor +to make the match, in which case you should also be slightly suspicious. + +@command{patch} cannot tell if the line numbers are off in an @command{ed} +script, and can only detect wrong line numbers in a normal diff when it +finds a change or delete command. It may have the same problem with a +context diff using a fuzz factor equal to or greater than the number of +lines of context shown in the diff (typically 3). In these cases, you +should probably look at a context diff between your original and patched +input files to see if the changes make sense. Compiling without errors +is a pretty good indication that the patch worked, but not a guarantee. + +A patch against an empty file applies to a nonexistent file, and vice +versa. @xref{Creating and Removing}. + +@command{patch} usually produces the correct results, even when it must +make many guesses. However, the results are guaranteed only when +the patch is applied to an exact copy of the file that the patch was +generated from. + +@node Dry Runs +@subsection Predicting what @command{patch} will do +@cindex testing @command{patch} +@cindex dry runs for @command{patch} + +It may not be obvious in advance what @command{patch} will do with a +complicated or poorly formatted patch. If you are concerned that the +input might cause @command{patch} to modify the wrong files, you can +use the @option{--dry-run} option, which causes @command{patch} to +print the results of applying patches without actually changing any +files. You can then inspect the diagnostics generated by the dry run +to see whether @command{patch} will modify the files that you expect. +If the patch does not do what you want, you can modify the patch (or +the other options to @command{patch}) and try another dry run. Once +you are satisfied with the proposed patch you can apply it by invoking +@command{patch} as before, but this time without the +@option{--dry-run} option. + +@node Creating and Removing +@section Creating and Removing Files +@cindex creating files +@cindex empty files, removing +@cindex removing empty files + +Sometimes when comparing two directories, a file may exist in one +directory but not the other. If you give @command{diff} the +@option{-N} or @option{--new-file} option, or if you supply an old or +new file that is named @file{/dev/null} or is empty and is dated the +Epoch (1970-01-01 00:00:00 UTC), @command{diff} outputs a patch that +adds or deletes the contents of this file. When given such a patch, +@command{patch} normally creates a new file or removes the old file. +However, when conforming to @acronym{POSIX} (@pxref{patch and POSIX}), +@command{patch} does not remove the old file, but leaves it empty. +The @option{-E} or @option{--remove-empty-files} option causes +@command{patch} to remove output files that are empty after applying a +patch, even if the patch does not appear to be one that removed the +file. + +If the patch appears to create a file that already exists, +@command{patch} asks for confirmation before applying the patch. + +@node Patching Time Stamps +@section Updating Time Stamps on Patched Files +@cindex time stamps on patched files + +When @command{patch} updates a file, it normally sets the file's +last-modified time stamp to the current time of day. If you are using +@command{patch} to track a software distribution, this can cause +@command{make} to incorrectly conclude that a patched file is out of +date. For example, if @file{syntax.c} depends on @file{syntax.y}, and +@command{patch} updates @file{syntax.c} and then @file{syntax.y}, then +@file{syntax.c} will normally appear to be out of date with respect to +@file{syntax.y} even though its contents are actually up to date. + +The @option{-Z} or @option{--set-utc} option causes @command{patch} to +set a patched file's modification and access times to the time stamps +given in context diff headers. If the context diff headers do not +specify a time zone, they are assumed to use Coordinated Universal +Time (@acronym{UTC}, often known as @acronym{GMT}). + +The @option{-T} or @option{--set-time} option acts like @option{-Z} or +@option{--set-utc}, except that it assumes that the context diff +headers' time stamps use local time instead of @acronym{UTC}. This option +is not recommended, because patches using local time cannot easily be +used by people in other time zones, and because local time stamps are +ambiguous when local clocks move backwards during daylight-saving time +adjustments. If the context diff headers specify a time zone, this +option is equivalent to @option{-Z} or @option{--set-utc}. + +@command{patch} normally refrains from setting a file's time stamps if +the file's original last-modified time stamp does not match the time +given in the diff header, of if the file's contents do not exactly +match the patch. However, if the @option{-f} or @option{--force} +option is given, the file's time stamps are set regardless. + +Due to the limitations of the current @command{diff} format, +@command{patch} cannot update the times of files whose contents have +not changed. Also, if you set file time stamps to values other than +the current time of day, you should also remove (e.g., with @samp{make +clean}) all files that depend on the patched files, so that later +invocations of @command{make} do not get confused by the patched +files' times. + +@node Multiple Patches +@section Multiple Patches in a File +@cindex multiple patches +@cindex intuiting file names from patches + +If the patch file contains more than one patch, and if you do not +specify an input file on the command line, @command{patch} tries to +apply each patch as if they came from separate patch files. This +means that it determines the name of the file to patch for each patch, +and that it examines the leading text before each patch for file names +and prerequisite revision level (@pxref{Making Patches}, for more on +that topic). + +@command{patch} uses the following rules to intuit a file name from +the leading text before a patch. First, @command{patch} takes an +ordered list of candidate file names as follows: + +@itemize @bullet +@item +If the header is that of a context diff, @command{patch} takes the old +and new file names in the header. A name is ignored if it does not +have enough slashes to satisfy the @option{-p@var{num}} or +@option{--strip=@var{num}} option. The name @file{/dev/null} is also +ignored. + +@item +If there is an @samp{Index:} line in the leading garbage and if either +the old and new names are both absent or if @command{patch} is +conforming to @acronym{POSIX}, @command{patch} takes the name in the +@samp{Index:} line. + +@item +For the purpose of the following rules, the candidate file names are +considered to be in the order (old, new, index), regardless of the +order that they appear in the header. +@end itemize + +@noindent +Then @command{patch} selects a file name from the candidate list as +follows: + +@itemize @bullet +@item +If some of the named files exist, @command{patch} selects the first +name if conforming to @acronym{POSIX}, and the best name otherwise. + +@item +If @command{patch} is not ignoring @acronym{RCS}, ClearCase, and @acronym{SCCS} +(@pxref{Revision Control}), and no named files exist but an @acronym{RCS}, +ClearCase, or @acronym{SCCS} master is found, @command{patch} selects the +first named file with an @acronym{RCS}, ClearCase, or @acronym{SCCS} master. + +@item +If no named files exist, no @acronym{RCS}, ClearCase, or @acronym{SCCS} master +was found, some names are given, @command{patch} is not conforming to +@acronym{POSIX}, and the patch appears to create a file, @command{patch} +selects the best name requiring the creation of the fewest +directories. + +@item +If no file name results from the above heuristics, you are asked for +the name of the file to patch, and @command{patch} selects that name. +@end itemize + +To determine the @dfn{best} of a nonempty list of file names, +@command{patch} first takes all the names with the fewest path name +components; of those, it then takes all the names with the shortest +basename; of those, it then takes all the shortest names; finally, it +takes the first remaining name. + +@xref{patch and POSIX}, to see whether @command{patch} is conforming +to @acronym{POSIX}. + +@node patch Directories +@section Applying Patches in Other Directories +@cindex directories and patch +@cindex patching directories + +The @option{-d @var{directory}} or @option{--directory=@var{directory}} +option to @command{patch} makes directory @var{directory} the current +directory for interpreting both file names in the patch file, and file +names given as arguments to other options (such as @option{-B} and +@option{-o}). For example, while in a mail reading program, you can patch +a file in the @file{/usr/src/emacs} directory directly from a message +containing the patch like this: + +@example +| patch -d /usr/src/emacs +@end example + +Sometimes the file names given in a patch contain leading directories, +but you keep your files in a directory different from the one given in +the patch. In those cases, you can use the +@option{-p@var{number}} or @option{--strip=@var{number}} +option to set the file name strip count to @var{number}. The strip +count tells @command{patch} how many slashes, along with the directory +names between them, to strip from the front of file names. A sequence +of one or more adjacent slashes is counted as a single slash. By +default, @command{patch} strips off all leading directories, leaving +just the base file names. + +For example, suppose the file name in the patch file is +@file{/gnu/src/emacs/etc/NEWS}. Using @option{-p0} gives the +entire file name unmodified, @option{-p1} gives +@file{gnu/src/emacs/etc/NEWS} (no leading slash), @option{-p4} gives +@file{etc/NEWS}, and not specifying @option{-p} at all gives @file{NEWS}. + +@command{patch} looks for each file (after any slashes have been stripped) +in the current directory, or if you used the @option{-d @var{directory}} +option, in that directory. + +@node Backups +@section Backup Files +@cindex backup file strategy + +Normally, @command{patch} creates a backup file if the patch does not +exactly match the original input file, because in that case the +original data might not be recovered if you undo the patch with +@samp{patch -R} (@pxref{Reversed Patches}). However, when conforming +to @acronym{POSIX}, @command{patch} does not create backup files by +default. @xref{patch and POSIX}. + +The @option{-b} or @option{--backup} option causes @command{patch} to +make a backup file regardless of whether the patch matches the +original input. The @option{--backup-if-mismatch} option causes +@command{patch} to create backup files for mismatches files; this is +the default when not conforming to @acronym{POSIX}. The +@option{--no-backup-if-mismatch} option causes @command{patch} to not +create backup files, even for mismatched patches; this is the default +when conforming to @acronym{POSIX}. + +When backing up a file that does not exist, an empty, unreadable +backup file is created as a placeholder to represent the nonexistent +file. + +@node Backup Names +@section Backup File Names +@cindex backup file names + +Normally, @command{patch} renames an original input file into a backup +file by appending to its name the extension @samp{.orig}, or @samp{~} +if using @samp{.orig} would make the backup file name too +long.@footnote{A coding error in @acronym{GNU} @command{patch} version +2.5.4 causes it to always use @samp{~}, but this should be fixed in +the next release.} The @option{-z @var{backup-suffix}} or +@option{--suffix=@var{backup-suffix}} option causes @command{patch} to +use @var{backup-suffix} as the backup extension instead. + +@vindex SIMPLE_BACKUP_SUFFIX +Alternately, you can specify the extension for backup files with the +@env{SIMPLE_BACKUP_SUFFIX} environment variable, which the options +override. + +@command{patch} can also create numbered backup files the way +@acronym{GNU} Emacs does. With this method, instead of having a +single backup of each file, @command{patch} makes a new backup file +name each time it patches a file. For example, the backups of a file +named @file{sink} would be called, successively, @file{sink.~1~}, +@file{sink.~2~}, @file{sink.~3~}, etc. + +@vindex PATCH_VERSION_CONTROL +@vindex VERSION_CONTROL +The @option{-V @var{backup-style}} or +@option{--version-control=@var{backup-style}} option takes as an +argument a method for creating backup file names. You can alternately +control the type of backups that @command{patch} makes with the +@env{PATCH_VERSION_CONTROL} environment variable, which the +@option{-V} option overrides. If @env{PATCH_VERSION_CONTROL} is not +set, the @env{VERSION_CONTROL} environment variable is used instead. +Please note that these options and variables control backup file +names; they do not affect the choice of revision control system +(@pxref{Revision Control}). + +The values of these environment variables and the argument to the +@option{-V} option are like the @acronym{GNU} Emacs @code{version-control} +variable (@pxref{Backup Names, , , emacs, The @acronym{GNU} Emacs Manual}, +for more information on backup versions in Emacs). They also +recognize synonyms that are more descriptive. The valid values are +listed below; unique abbreviations are acceptable. + +@table @option +@item t +@itemx numbered +Always make numbered backups. + +@item nil +@itemx existing +Make numbered backups of files that already have them, simple backups of +the others. This is the default. + +@item never +@itemx simple +Always make simple backups. +@end table + +You can also tell @command{patch} to prepend a prefix, such as a +directory name, to produce backup file names. The @option{-B +@var{prefix}} or @option{--prefix=@var{prefix}} option makes backup +files by prepending @var{prefix} to them. The @option{-Y +@var{prefix}} or @option{--basename-prefix=@var{prefix}} prepends +@var{prefix} to the last file name component of backup file names +instead; for example, @option{-Y ~} causes the backup name for +@file{dir/file.c} to be @file{dir/~file.c}. If you use either of +these prefix options, the suffix-based options are ignored. + +If you specify the output file with the @option{-o} option, that file is +the one that is backed up, not the input file. + +Options that affect the names of backup files do not affect whether +backups are made. For example, if you specify the +@option{--no-backup-if-mismatch} option, none of the options described +in this section have any affect, because no backups are made. + +@node Reject Names +@section Reject File Names +@cindex reject file names + +The names for reject files (files containing patches that +@command{patch} could not find a place to apply) are normally the name +of the output file with @samp{.rej} appended (or @samp{#} if using +@samp{.rej} would make the backup file name too long). + +Alternatively, you can tell @command{patch} to place all of the rejected +patches in a single file. The @option{-r @var{reject-file}} or +@option{--reject-file=@var{reject-file}} option uses @var{reject-file} as +the reject file name. + +@node patch Messages +@section Messages and Questions from @command{patch} +@cindex @command{patch} messages and questions +@cindex diagnostics from @command{patch} +@cindex messages from @command{patch} + +@command{patch} can produce a variety of messages, especially if it +has trouble decoding its input. In a few situations where it's not +sure how to proceed, @command{patch} normally prompts you for more +information from the keyboard. There are options to produce more or +fewer messages, to have it not ask for keyboard input, and to +affect the way that file names are quoted in messages. + +@menu +* More or Fewer Messages:: Controlling the verbosity of @command{patch}. +* patch and Keyboard Input:: Inhibiting keyboard input. +* patch Quoting Style:: Quoting file names in diagnostics. +@end menu + +@command{patch} exits with status 0 if all hunks are applied successfully, +1 if some hunks cannot be applied, and 2 if there is more serious trouble. +When applying a set of patches in a loop, you should check the +exit status, so you don't apply a later patch to a partially patched +file. + +@node More or Fewer Messages +@subsection Controlling the Verbosity of @command{patch} +@cindex verbose messages from @command{patch} +@cindex inhibit messages from @command{patch} + +You can cause @command{patch} to produce more messages by using the +@option{--verbose} option. For example, when you give this option, +the message @samp{Hmm...} indicates that @command{patch} is reading text in +the patch file, attempting to determine whether there is a patch in that +text, and if so, what kind of patch it is. + +You can inhibit all terminal output from @command{patch}, unless an error +occurs, by using the @option{-s}, @option{--quiet}, or @option{--silent} +option. + +@node patch and Keyboard Input +@subsection Inhibiting Keyboard Input +@cindex keyboard input to @command{patch} + +There are two ways you can prevent @command{patch} from asking you any +questions. The @option{-f} or @option{--force} option assumes that you know +what you are doing. It causes @command{patch} to do the following: + +@itemize @bullet +@item +Skip patches that do not contain file names in their headers. + +@item +Patch files even though they have the wrong version for the +@samp{Prereq:} line in the patch; + +@item +Assume that patches are not reversed even if they look like they are. +@end itemize + +@noindent +The @option{-t} or @option{--batch} option is similar to @option{-f}, in that +it suppresses questions, but it makes somewhat different assumptions: + +@itemize @bullet +@item +Skip patches that do not contain file names in their headers +(the same as @option{-f}). + +@item +Skip patches for which the file has the wrong version for the +@samp{Prereq:} line in the patch; + +@item +Assume that patches are reversed if they look like they are. +@end itemize + +@node patch Quoting Style +@subsection @command{patch} Quoting Style +@cindex quoting style + +When @command{patch} outputs a file name in a diagnostic message, it +can format the name in any of several ways. This can be useful to +output file names unambiguously, even if they contain punctuation or +special characters like newlines. The +@option{--quoting-style=@var{word}} option controls how names are +output. The @var{word} should be one of the following: + +@table @samp +@item literal +Output names as-is. +@item shell +Quote names for the shell if they contain shell metacharacters or would +cause ambiguous output. +@item shell-always +Quote names for the shell, even if they would normally not require quoting. +@item c +Quote names as for a C language string. +@item escape +Quote as with @samp{c} except omit the surrounding double-quote +characters. +@c The following are not yet implemented in patch 2.5.4. +@c @item clocale +@c Quote as with @samp{c} except use quotation marks appropriate for the +@c locale. +@c @item locale +@c @c Use @t instead of @samp to avoid duplicate quoting in some output styles. +@c Like @samp{clocale}, but quote @t{`like this'} instead of @t{"like +@c this"} in the default C locale. This looks nicer on many displays. +@end table + +@vindex QUOTING_STYLE +You can specify the default value of the @option{--quoting-style} +option with the environment variable @env{QUOTING_STYLE}. If that +environment variable is not set, the default value is @samp{shell}, +but this default may change in a future version of @command{patch}. + +@node patch and POSIX +@section @command{patch} and the @acronym{POSIX} Standard +@cindex @acronym{POSIX} + +@vindex POSIXLY_CORRECT +If you specify the @option{--posix} option, or set the +@env{POSIXLY_CORRECT} environment variable, @command{patch} conforms +more strictly to the @acronym{POSIX} standard, as follows: + +@itemize @bullet +@item +Take the first existing file from the list (old, new, index) +when intuiting file names from diff headers. @xref{Multiple Patches}. + +@item +Do not remove files that are removed by a diff. +@xref{Creating and Removing}. + +@item +Do not ask whether to get files from @acronym{RCS}, ClearCase, or +@acronym{SCCS}. @xref{Revision Control}. + +@item +Require that all options precede the files in the command line. + +@item +Do not backup files, even when there is a mismatch. @xref{Backups}. + +@end itemize + +@node patch and Tradition +@section @acronym{GNU} @command{patch} and Traditional @command{patch} +@cindex traditional @command{patch} + +The current version of @acronym{GNU} @command{patch} normally follows the +@acronym{POSIX} standard. @xref{patch and POSIX}, for the few exceptions +to this general rule. + +Unfortunately, @acronym{POSIX} redefined the behavior of @command{patch} in +several important ways. You should be aware of the following +differences if you must interoperate with traditional @command{patch}, +or with @acronym{GNU} @command{patch} version 2.1 and earlier. + +@itemize @bullet +@item +In traditional @command{patch}, the @option{-p} option's operand was +optional, and a bare @option{-p} was equivalent to @option{-p0}. The +@option{-p} option now requires an operand, and @option{-p@ 0} is now +equivalent to @option{-p0}. For maximum compatibility, use options +like @option{-p0} and @option{-p1}. + +Also, traditional @command{patch} simply counted slashes when +stripping path prefixes; @command{patch} now counts pathname +components. That is, a sequence of one or more adjacent slashes now +counts as a single slash. For maximum portability, avoid sending +patches containing @file{//} in file names. + +@item +In traditional @command{patch}, backups were enabled by default. This +behavior is now enabled with the @option{-b} or @option{--backup} +option. + +Conversely, in @acronym{POSIX} @command{patch}, backups are never made, +even when there is a mismatch. In @acronym{GNU} @command{patch}, this +behavior is enabled with the @option{--no-backup-if-mismatch} option, +or by conforming to @acronym{POSIX}. + +The @option{-b@ @var{suffix}} option of traditional @command{patch} is +equivalent to the @samp{-b -z@ @var{suffix}} options of @acronym{GNU} +@command{patch}. + +@item +Traditional @command{patch} used a complicated (and incompletely +documented) method to intuit the name of the file to be patched from +the patch header. This method did not conform to @acronym{POSIX}, and had +a few gotchas. Now @command{patch} uses a different, equally +complicated (but better documented) method that is optionally +@acronym{POSIX}-conforming; we hope it has fewer gotchas. The two methods +are compatible if the file names in the context diff header and the +@samp{Index:} line are all identical after prefix-stripping. Your +patch is normally compatible if each header's file names all contain +the same number of slashes. + +@item +When traditional @command{patch} asked the user a question, it sent +the question to standard error and looked for an answer from the first +file in the following list that was a terminal: standard error, +standard output, @file{/dev/tty}, and standard input. Now +@command{patch} sends questions to standard output and gets answers +from @file{/dev/tty}. Defaults for some answers have been changed so +that @command{patch} never goes into an infinite loop when using +default answers. + +@item +Traditional @command{patch} exited with a status value that counted +the number of bad hunks, or with status 1 if there was real trouble. +Now @command{patch} exits with status 1 if some hunks failed, or with +2 if there was real trouble. + +@item +Limit yourself to the following options when sending instructions +meant to be executed by anyone running @acronym{GNU} @command{patch}, +traditional @command{patch}, or a @command{patch} that conforms to +@acronym{POSIX}. Spaces are significant in the following list, and +operands are required. + +@example +@option{-c} +@option{-d @var{dir}} +@option{-D @var{define}} +@option{-e} +@option{-l} +@option{-n} +@option{-N} +@option{-o @var{outfile}} +@option{-p@var{num}} +@option{-R} +@option{-r @var{rejectfile}} +@end example + +@end itemize + +@node Making Patches +@chapter Tips for Making and Using Patches + +Use some common sense when making and using patches. For example, +when sending bug fixes to a program's maintainer, send several small +patches, one per independent subject, instead of one large, +harder-to-digest patch that covers all the subjects. + +Here are some other things you should keep in mind if you are going to +distribute patches for updating a software package. + +@menu +* Tips for Patch Producers:: Advice for making patches. +* Tips for Patch Consumers:: Advice for using patches. +* Avoiding Common Mistakes:: Avoiding common mistakes when using @command{patch}. +* Generating Smaller Patches:: How to generate smaller patches. +@end menu + +@node Tips for Patch Producers +@section Tips for Patch Producers +@cindex patch producer tips + +To create a patch that changes an older version of a package into a +newer version, first make a copy of the older and newer versions in +adjacent subdirectories. It is common to do that by unpacking +@command{tar} archives of the two versions. + +To generate the patch, use the command @samp{diff -Naur @var{old} +@var{new}} where @var{old} and @var{new} identify the old and new +directories. The names @var{old} and @var{new} should not contain any +slashes. The @option{-N} option lets the patch create and remove +files; @option{-a} lets the patch update non-text files; @option{-u} +generates useful time stamps and enough context; and @option{-r} lets +the patch update subdirectories. Here is an example command, using +Bourne shell syntax: + +@example +diff -Naur gcc-3.0.3 gcc-3.0.4 +@end example + +Tell your recipients how to apply the patches. This should include +which working directory to use, and which @command{patch} options to +use; the option @samp{-p1} is recommended. Test your procedure by +pretending to be a recipient and applying your patches to a copy of +the original files. + +@xref{Avoiding Common Mistakes}, for how to avoid common mistakes when +generating a patch. + +@node Tips for Patch Consumers +@section Tips for Patch Consumers +@cindex patch consumer tips + +A patch producer should tell recipients how to apply the patches, so +the first rule of thumb for a patch consumer is to follow the +instructions supplied with the patch. + +@acronym{GNU} @command{diff} can analyze files with arbitrarily long lines +and files that end in incomplete lines. However, older versions of +@command{patch} cannot patch such files. If you are having trouble +applying such patches, try upgrading to a recent version of @acronym{GNU} +@command{patch}. + +@node Avoiding Common Mistakes +@section Avoiding Common Mistakes +@cindex common mistakes with patches +@cindex patch, common mistakes + +When producing a patch for multiple files, apply @command{diff} to +directories whose names do not have slashes. This reduces confusion +when the patch consumer specifies the @option{-p@var{number}} option, +since this option can have surprising results when the old and new +file names have different numbers of slashes. For example, do not +send a patch with a header that looks like this: + +@example +diff -Naur v2.0.29/prog/README prog/README +--- v2.0.29/prog/README 2002-03-10 23:30:39.942229878 -0800 ++++ prog/README 2002-03-17 20:49:32.442260588 -0800 +@end example + +@noindent +because the two file names have different numbers of slashes, and +different versions of @command{patch} interpret the file names +differently. To avoid confusion, send output that looks like this +instead: + +@example +diff -Naur v2.0.29/prog/README v2.0.30/prog/README +--- v2.0.29/prog/README 2002-03-10 23:30:39.942229878 -0800 ++++ v2.0.30/prog/README 2002-03-17 20:49:32.442260588 -0800 +@end example + +Make sure you have specified the file names correctly, either in a +context diff header or with an @samp{Index:} line. Take care to not send out +reversed patches, since these make people wonder whether they have +already applied the patch. + +Avoid sending patches that compare backup file names like +@file{README.orig} or @file{README~}, since this might confuse +@command{patch} into patching a backup file instead of the real file. +Instead, send patches that compare the same base file names in +different directories, e.g.@: @file{old/README} and @file{new/README}. + +To save people from partially applying a patch before other patches that +should have gone before it, you can make the first patch in the patch +file update a file with a name like @file{patchlevel.h} or +@file{version.c}, which contains a patch level or version number. If +the input file contains the wrong version number, @command{patch} will +complain immediately. + +An even clearer way to prevent this problem is to put a @samp{Prereq:} +line before the patch. If the leading text in the patch file contains a +line that starts with @samp{Prereq:}, @command{patch} takes the next word +from that line (normally a version number) and checks whether the next +input file contains that word, preceded and followed by either +white space or a newline. If not, @command{patch} prompts you for +confirmation before proceeding. This makes it difficult to accidentally +apply patches in the wrong order. + +@node Generating Smaller Patches +@section Generating Smaller Patches +@cindex patches, shrinking + +The simplest way to generate a patch is to use @samp{diff -Naur} +(@pxref{Tips for Patch Producers}), but you might be able to reduce +the size of the patch by renaming or removing some files before making +the patch. If the older version of the package contains any files +that the newer version does not, or if any files have been renamed +between the two versions, make a list of @command{rm} and @command{mv} +commands for the user to execute in the old version directory before +applying the patch. Then run those commands yourself in the scratch +directory. + +If there are any files that you don't need to include in the patch +because they can easily be rebuilt from other files (for example, +@file{TAGS} and output from @command{yacc} and @command{makeinfo}), +exclude them from the patch by giving @command{diff} the @option{-x +@var{pattern}} option (@pxref{Comparing Directories}). If you want +your patch to modify a derived file because your recipients lack tools +to build it, make sure that the patch for the derived file follows any +patches for files that it depends on, so that the recipients' time +stamps will not confuse @command{make}. + +Now you can create the patch using @samp{diff -Naur}. Make sure to +specify the scratch directory first and the newer directory second. + +Add to the top of the patch a note telling the user any @command{rm} and +@command{mv} commands to run before applying the patch. Then you can +remove the scratch directory. + +You can also shrink the patch size by using fewer lines of context, +but bear in mind that @command{patch} typically needs at least two +lines for proper operation when patches do not exactly match the input +files. + +@node Invoking cmp +@chapter Invoking @command{cmp} +@cindex invoking @command{cmp} +@cindex @command{cmp} invocation + +The @command{cmp} command compares two files, and if they differ, +tells the first byte and line number where they differ or reports +that one file is a prefix of the other. Bytes and +lines are numbered starting with 1. The arguments of @command{cmp} +are as follows: + +@example +cmp @var{options}@dots{} @var{from-file} @r{[}@var{to-file} @r{[}@var{from-skip} @r{[}@var{to-skip}@r{]}@r{]}@r{]} +@end example + +The file name @file{-} is always the standard input. @command{cmp} +also uses the standard input if one file name is omitted. The +@var{from-skip} and @var{to-skip} operands specify how many bytes to +ignore at the start of each file; they are equivalent to the +@option{--ignore-initial=@var{from-skip}:@var{to-skip}} option. + +By default, @command{cmp} outputs nothing if the two files have the +same contents. If one file is a prefix of the other, @command{cmp} +prints to standard error a message of the following form: + +@example +cmp: EOF on @var{shorter-file} +@end example + +Otherwise, @command{cmp} prints to standard output a message of the +following form: + +@example +@var{from-file} @var{to-file} differ: char @var{byte-number}, line @var{line-number} +@end example + +The message formats can differ outside the @acronym{POSIX} locale. +Also, @acronym{POSIX} allows the @acronym{EOF} message to be followed +by a blank and some additional information. + +An exit status of 0 means no differences were found, 1 means some +differences were found, and 2 means trouble. + +@menu +* cmp Options:: Summary of options to @command{cmp}. +@end menu + +@node cmp Options +@section Options to @command{cmp} +@cindex @command{cmp} options +@cindex options for @command{cmp} + +Below is a summary of all of the options that @acronym{GNU} +@command{cmp} accepts. Most options have two equivalent names, one of +which is a single letter preceded by @samp{-}, and the other of which +is a long name preceded by @samp{--}. Multiple single letter options +(unless they take an argument) can be combined into a single command +line word: @option{-bl} is equivalent to @option{-b -l}. + +@table @option +@item -b +@itemx --print-bytes +Print the differing bytes. Display control bytes as a +@samp{^} followed by a letter of the alphabet and precede bytes +that have the high bit set with @samp{M-} (which stands for ``meta''). + +@item --help +Output a summary of usage and then exit. + +@item -i @var{skip} +@itemx --ignore-initial=@var{skip} +Ignore any differences in the first @var{skip} bytes of the input +files. Treat files with fewer than @var{skip} bytes as if they are +empty. If @var{skip} is of the form +@option{@var{from-skip}:@var{to-skip}}, skip the first @var{from-skip} +bytes of the first input file and the first @var{to-skip} bytes of the +second. + +@item -l +@itemx --verbose +Output the (decimal) byte numbers and (octal) values of all differing bytes, +instead of the default standard output. + +@item -n @var{count} +@itemx --bytes=@var{count} +Compare at most @var{count} input bytes. + +@item -s +@itemx --quiet +@itemx --silent +Do not print anything; only return an exit status indicating whether +the files differ. + +@item -v +@itemx --version +Output version information and then exit. +@end table + +In the above table, operands that are byte counts are normally +decimal, but may be preceded by @samp{0} for octal and @samp{0x} for +hexadecimal. + +A byte count can be followed by a suffix to specify a multiple of that +count; in this case an omitted integer is understood to be 1. A bare +size letter, or one followed by @samp{iB}, specifies a multiple using +powers of 1024. A size letter followed by @samp{B} specifies powers +of 1000 instead. For example, @option{-n 4M} and @option{-n 4MiB} are +equivalent to @option{-n 4194304}, whereas @option{-n 4MB} is +equivalent to @option{-n 4000000}. This notation is upward compatible +with the @uref{http://www.bipm.fr/enus/3_SI/si-prefixes.html, SI +prefixes} for decimal multiples and with the +@uref{http://physics.nist.gov/cuu/Units/binary.html, IEC 60027-2 +prefixes for binary multiples}. + +The following suffixes are defined. Large sizes like @code{1Y} may be +rejected by your computer due to limitations of its arithmetic. + +@table @samp +@item kB +@cindex kilobyte, definition of +kilobyte: @math{10^3 = 1000}. +@item k +@itemx K +@itemx KiB +@cindex kibibyte, definition of +kibibyte: @math{2^10 = 1024}. @samp{K} is special: the SI prefix is +@samp{k} and the IEC 60027-2 prefix is @samp{Ki}, but tradition and +@acronym{POSIX} use @samp{k} to mean @samp{KiB}. +@item MB +@cindex megabyte, definition of +megabyte: @math{10^6 = 1,000,000}. +@item M +@itemx MiB +@cindex mebibyte, definition of +mebibyte: @math{2^20 = 1,048,576}. +@item GB +@cindex gigabyte, definition of +gigabyte: @math{10^9 = 1,000,000,000}. +@item G +@itemx GiB +@cindex gibibyte, definition of +gibibyte: @math{2^30 = 1,073,741,824}. +@item TB +@cindex terabyte, definition of +terabyte: @math{10^12 = 1,000,000,000,000}. +@item T +@itemx TiB +@cindex tebibyte, definition of +tebibyte: @math{2^40 = 1,099,511,627,776}. +@item PB +@cindex petabyte, definition of +petabyte: @math{10^15 = 1,000,000,000,000,000}. +@item P +@itemx PiB +@cindex pebibyte, definition of +pebibyte: @math{2^50 = 1,125,899,906,842,624}. +@item EB +@cindex exabyte, definition of +exabyte: @math{10^18 = 1,000,000,000,000,000,000}. +@item E +@itemx EiB +@cindex exbibyte, definition of +exbibyte: @math{2^60 = 1,152,921,504,606,846,976}. +@item ZB +@cindex zettabyte, definition of +zettabyte: @math{10^21 = 1,000,000,000,000,000,000,000} +@item Z +@itemx ZiB +@math{2^70 = 1,180,591,620,717,411,303,424}. +(@samp{Zi} is a GNU extension to IEC 60027-2.) +@item YB +@cindex yottabyte, definition of +yottabyte: @math{10^24 = 1,000,000,000,000,000,000,000,000}. +@item Y +@itemx YiB +@math{2^80 = 1,208,925,819,614,629,174,706,176}. +(@samp{Yi} is a GNU extension to IEC 60027-2.) +@end table + +@node Invoking diff +@chapter Invoking @command{diff} +@cindex invoking @command{diff} +@cindex @command{diff} invocation + +The format for running the @command{diff} command is: + +@example +diff @var{options}@dots{} @var{files}@dots{} +@end example + +In the simplest case, two file names @var{from-file} and +@var{to-file} are given, and @command{diff} compares the contents of +@var{from-file} and @var{to-file}. A file name of @file{-} stands for +text read from the standard input. As a special case, @samp{diff - -} +compares a copy of standard input to itself. + +If one file is a directory and the other is not, @command{diff} compares +the file in the directory whose name is that of the non-directory. +The non-directory file must not be @file{-}. + +If two file names are given and both are directories, +@command{diff} compares corresponding files in both directories, in +alphabetical order; this comparison is not recursive unless the +@option{-r} or @option{--recursive} option is given. @command{diff} never +compares the actual contents of a directory as if it were a file. The +file that is fully specified may not be standard input, because standard +input is nameless and the notion of ``file with the same name'' does not +apply. + +If the @option{--from-file=@var{file}} option is given, the number of +file names is arbitrary, and @var{file} is compared to each named file. +Similarly, if the @option{--to-file=@var{file}} option is given, each +named file is compared to @var{file}. + +@command{diff} options begin with @samp{-}, so normally file names +may not begin with @samp{-}. However, @option{--} as an +argument by itself treats the remaining arguments as file names even if +they begin with @samp{-}. + +An exit status of 0 means no differences were found, 1 means some +differences were found, and 2 means trouble. Normally, differing +binary files count as trouble, but this can be altered by using the +@option{-a} or @option{--text} option, or the @option{-q} or +@option{--brief} option. + +@menu +* diff Options:: Summary of options to @command{diff}. +@end menu + +@node diff Options +@section Options to @command{diff} +@cindex @command{diff} options +@cindex options for @command{diff} + +Below is a summary of all of the options that @acronym{GNU} +@command{diff} accepts. Most options have two equivalent names, one +of which is a single letter preceded by @samp{-}, and the other of +which is a long name preceded by @samp{--}. Multiple single letter +options (unless they take an argument) can be combined into a single +command line word: @option{-ac} is equivalent to @option{-a -c}. Long +named options can be abbreviated to any unique prefix of their name. +Brackets ([ and ]) indicate that an option takes an optional argument. + +@table @option +@item -a +@itemx --text +Treat all files as text and compare them line-by-line, even if they +do not seem to be text. @xref{Binary}. + +@item -b +@itemx --ignore-space-change +Ignore changes in amount of white space. @xref{White Space}. + +@item -B +@itemx --ignore-blank-lines +Ignore changes that just insert or delete blank lines. @xref{Blank +Lines}. + +@item --binary +Read and write data in binary mode. @xref{Binary}. + +@item -c +Use the context output format, showing three lines of context. +@xref{Context Format}. + +@item -C @var{lines} +@itemx --context@r{[}=@var{lines}@r{]} +Use the context output format, showing @var{lines} (an integer) lines of +context, or three if @var{lines} is not given. @xref{Context Format}. +For proper operation, @command{patch} typically needs at least two lines of +context. + +On older systems, @command{diff} supports an obsolete option +@option{-@var{lines}} that has effect when combined with @option{-c} +or @option{-p}. @acronym{POSIX} 1003.1-2001 (@pxref{Standards +conformance}) does not allow this; use @option{-C @var{lines}} +instead. + +@item --changed-group-format=@var{format} +Use @var{format} to output a line group containing differing lines from +both files in if-then-else format. @xref{Line Group Formats}. + +@item -d +@itemx --minimal +Change the algorithm perhaps find a smaller set of changes. This makes +@command{diff} slower (sometimes much slower). @xref{diff Performance}. + +@item -D @var{name} +@itemx --ifdef=@var{name} +Make merged @samp{#ifdef} format output, conditional on the preprocessor +macro @var{name}. @xref{If-then-else}. + +@item -e +@itemx --ed +Make output that is a valid @command{ed} script. @xref{ed Scripts}. + +@item -E +@itemx --ignore-tab-expansion +Ignore changes due to tab expansion. +@xref{White Space}. + +@item -f +@itemx --forward-ed +Make output that looks vaguely like an @command{ed} script but has changes +in the order they appear in the file. @xref{Forward ed}. + +@item -F @var{regexp} +@itemx --show-function-line=@var{regexp} +In context and unified format, for each hunk of differences, show some +of the last preceding line that matches @var{regexp}. @xref{Specified +Headings}. + +@item --from-file=@var{file} +Compare @var{file} to each operand; @var{file} may be a directory. + +@item --help +Output a summary of usage and then exit. + +@item --horizon-lines=@var{lines} +Do not discard the last @var{lines} lines of the common prefix +and the first @var{lines} lines of the common suffix. +@xref{diff Performance}. + +@item -i +@itemx --ignore-case +Ignore changes in case; consider upper- and lower-case letters +equivalent. @xref{Case Folding}. + +@item -I @var{regexp} +@itemx --ignore-matching-lines=@var{regexp} +Ignore changes that just insert or delete lines that match @var{regexp}. +@xref{Specified Lines}. + +@item --ignore-file-name-case +Ignore case when comparing file names during recursive comparison. +@xref{Comparing Directories}. + +@item -l +@itemx --paginate +Pass the output through @command{pr} to paginate it. @xref{Pagination}. + +@item --label=@var{label} +Use @var{label} instead of the file name in the context format +(@pxref{Context Format}) and unified format (@pxref{Unified Format}) +headers. @xref{RCS}. + +@item --left-column +Print only the left column of two common lines in side by side format. +@xref{Side by Side Format}. + +@item --line-format=@var{format} +Use @var{format} to output all input lines in if-then-else format. +@xref{Line Formats}. + +@item -n +@itemx --rcs +Output @acronym{RCS}-format diffs; like @option{-f} except that each command +specifies the number of lines affected. @xref{RCS}. + +@item -N +@itemx --new-file +In directory comparison, if a file is found in only one directory, +treat it as present but empty in the other directory. @xref{Comparing +Directories}. + +@item --new-group-format=@var{format} +Use @var{format} to output a group of lines taken from just the second +file in if-then-else format. @xref{Line Group Formats}. + +@item --new-line-format=@var{format} +Use @var{format} to output a line taken from just the second file in +if-then-else format. @xref{Line Formats}. + +@item --old-group-format=@var{format} +Use @var{format} to output a group of lines taken from just the first +file in if-then-else format. @xref{Line Group Formats}. + +@item --old-line-format=@var{format} +Use @var{format} to output a line taken from just the first file in +if-then-else format. @xref{Line Formats}. + +@item -p +@itemx --show-c-function +Show which C function each change is in. @xref{C Function Headings}. + +@item -q +@itemx --brief +Report only whether the files differ, not the details of the +differences. @xref{Brief}. + +@item -r +@itemx --recursive +When comparing directories, recursively compare any subdirectories +found. @xref{Comparing Directories}. + +@item -s +@itemx --report-identical-files +Report when two files are the same. @xref{Comparing Directories}. + +@item -S @var{file} +@itemx --starting-file=@var{file} +When comparing directories, start with the file @var{file}. This is +used for resuming an aborted comparison. @xref{Comparing Directories}. + +@item --speed-large-files +Use heuristics to speed handling of large files that have numerous +scattered small changes. @xref{diff Performance}. + +@item --strip-trailing-cr +Strip any trailing carriage return at the end of an input line. +@xref{Binary}. + +@item --suppress-common-lines +Do not print common lines in side by side format. +@xref{Side by Side Format}. + +@item -t +@itemx --expand-tabs +Expand tabs to spaces in the output, to preserve the alignment of tabs +in the input files. @xref{Tabs}. + +@item -T +@itemx --initial-tab +Output a tab rather than a space before the text of a line in normal or +context format. This causes the alignment of tabs in the line to look +normal. @xref{Tabs}. + +@item --tabsize=@var{columns} +Assume that tab stops are set every @var{columns} (default 8) print +columns. @xref{Tabs}. + +@item --to-file=@var{file} +Compare each operand to @var{file}; @var{file} may be a directory. + +@item -u +Use the unified output format, showing three lines of context. +@xref{Unified Format}. + +@item --unchanged-group-format=@var{format} +Use @var{format} to output a group of common lines taken from both files +in if-then-else format. @xref{Line Group Formats}. + +@item --unchanged-line-format=@var{format} +Use @var{format} to output a line common to both files in if-then-else +format. @xref{Line Formats}. + +@item --unidirectional-new-file +When comparing directories, if a file appears only in the second +directory of the two, treat it as present but empty in the other. +@xref{Comparing Directories}. + +@item -U @var{lines} +@itemx --unified@r{[}=@var{lines}@r{]} +Use the unified output format, showing @var{lines} (an integer) lines of +context, or three if @var{lines} is not given. @xref{Unified Format}. +For proper operation, @command{patch} typically needs at least two lines of +context. + +On older systems, @command{diff} supports an obsolete option +@option{-@var{lines}} that has effect when combined with @option{-u}. +@acronym{POSIX} 1003.1-2001 (@pxref{Standards conformance}) does not allow +this; use @option{-U @var{lines}} instead. + +@item -v +@itemx --version +Output version information and then exit. + +@item -w +@itemx --ignore-all-space +Ignore white space when comparing lines. @xref{White Space}. + +@item -W @var{columns} +@itemx --width=@var{columns} +Output at most @var{columns} (default 130) print columns per line in +side by side format. @xref{Side by Side Format}. + +@item -x @var{pattern} +@itemx --exclude=@var{pattern} +When comparing directories, ignore files and subdirectories whose basenames +match @var{pattern}. @xref{Comparing Directories}. + +@item -X @var{file} +@itemx --exclude-from=@var{file} +When comparing directories, ignore files and subdirectories whose basenames +match any pattern contained in @var{file}. @xref{Comparing Directories}. + +@item -y +@itemx --side-by-side +Use the side by side output format. @xref{Side by Side Format}. +@end table + +@node Invoking diff3 +@chapter Invoking @command{diff3} +@cindex invoking @command{diff3} +@cindex @command{diff3} invocation + +The @command{diff3} command compares three files and outputs descriptions +of their differences. Its arguments are as follows: + +@example +diff3 @var{options}@dots{} @var{mine} @var{older} @var{yours} +@end example + +The files to compare are @var{mine}, @var{older}, and @var{yours}. +At most one of these three file names may be @file{-}, +which tells @command{diff3} to read the standard input for that file. + +An exit status of 0 means @command{diff3} was successful, 1 means some +conflicts were found, and 2 means trouble. + +@menu +* diff3 Options:: Summary of options to @command{diff3}. +@end menu + +@node diff3 Options +@section Options to @command{diff3} +@cindex @command{diff3} options +@cindex options for @command{diff3} + +Below is a summary of all of the options that @acronym{GNU} @command{diff3} +accepts. Multiple single letter options (unless they take an argument) +can be combined into a single command line argument. + +@table @option +@item -a +@itemx --text +Treat all files as text and compare them line-by-line, even if they +do not appear to be text. @xref{Binary}. + +@item -A +@itemx --show-all +Incorporate all unmerged changes from @var{older} to @var{yours} into +@var{mine}, surrounding conflicts with bracket lines. +@xref{Marking Conflicts}. + +@item --diff-program=@var{program} +Use the compatible comparison program @var{program} to compare files +instead of @command{diff}. + +@item -e +@itemx --ed +Generate an @command{ed} script that incorporates all the changes from +@var{older} to @var{yours} into @var{mine}. @xref{Which Changes}. + +@item -E +@itemx --show-overlap +Like @option{-e}, except bracket lines from overlapping changes' first +and third files. +@xref{Marking Conflicts}. +With @option{-E}, an overlapping change looks like this: + +@example +<<<<<<< @var{mine} +@r{lines from @var{mine}} +======= +@r{lines from @var{yours}} +>>>>>>> @var{yours} +@end example + +@item --help +Output a summary of usage and then exit. + +@item -i +Generate @samp{w} and @samp{q} commands at the end of the @command{ed} +script for System V compatibility. This option must be combined with +one of the @option{-AeExX3} options, and may not be combined with @option{-m}. +@xref{Saving the Changed File}. + +@item --label=@var{label} +Use the label @var{label} for the brackets output by the @option{-A}, +@option{-E} and @option{-X} options. This option may be given up to three +times, one for each input file. The default labels are the names of +the input files. Thus @samp{diff3 --label X --label Y --label Z -m A +B C} acts like +@samp{diff3 -m A B C}, except that the output looks like it came from +files named @samp{X}, @samp{Y} and @samp{Z} rather than from files +named @samp{A}, @samp{B} and @samp{C}. @xref{Marking Conflicts}. + +@item -m +@itemx --merge +Apply the edit script to the first file and send the result to standard +output. Unlike piping the output from @command{diff3} to @command{ed}, this +works even for binary files and incomplete lines. @option{-A} is assumed +if no edit script option is specified. @xref{Bypassing ed}. + +@item --strip-trailing-cr +Strip any trailing carriage return at the end of an input line. +@xref{Binary}. + +@item -T +@itemx --initial-tab +Output a tab rather than two spaces before the text of a line in normal format. +This causes the alignment of tabs in the line to look normal. @xref{Tabs}. + +@item -v +@itemx --version +Output version information and then exit. + +@item -x +@itemx --overlap-only +Like @option{-e}, except output only the overlapping changes. +@xref{Which Changes}. + +@item -X +Like @option{-E}, except output only the overlapping changes. +In other words, like @option{-x}, except bracket changes as in @option{-E}. +@xref{Marking Conflicts}. + +@item -3 +@itemx --easy-only +Like @option{-e}, except output only the nonoverlapping changes. +@xref{Which Changes}. +@end table + +@node Invoking patch +@chapter Invoking @command{patch} +@cindex invoking @command{patch} +@cindex @command{patch} invocation + +Normally @command{patch} is invoked like this: + +@example +patch <@var{patchfile} +@end example + +The full format for invoking @command{patch} is: + +@example +patch @var{options}@dots{} @r{[}@var{origfile} @r{[}@var{patchfile}@r{]}@r{]} +@end example + +You can also specify where to read the patch from with the @option{-i +@var{patchfile}} or @option{--input=@var{patchfile}} option. +If you do not specify @var{patchfile}, or if @var{patchfile} is +@file{-}, @command{patch} reads the patch (that is, the @command{diff} output) +from the standard input. + +If you do not specify an input file on the command line, @command{patch} +tries to intuit from the @dfn{leading text} (any text in the patch +that comes before the @command{diff} output) which file to edit. +@xref{Multiple Patches}. + +By default, @command{patch} replaces the original input file with the +patched version, possibly after renaming the original file into a +backup file (@pxref{Backup Names}, for a description of how +@command{patch} names backup files). You can also specify where to +put the output with the @option{-o @var{file}} or +@option{--output=@var{file}} option; however, do not use this option +if @var{file} is one of the input files. + +@menu +* patch Options:: Summary table of options to @command{patch}. +@end menu + +@node patch Options +@section Options to @command{patch} +@cindex @command{patch} options +@cindex options for @command{patch} + +Here is a summary of all of the options that @acronym{GNU} @command{patch} +accepts. @xref{patch and Tradition}, for which of these options are +safe to use in older versions of @command{patch}. + +Multiple single-letter options that do not take an argument can be +combined into a single command line argument with only one dash. + +@table @option +@item -b +@itemx --backup +Back up the original contents of each file, even if backups would +normally not be made. @xref{Backups}. + +@item -B @var{prefix} +@itemx --prefix=@var{prefix} +Prepend @var{prefix} to backup file names. @xref{Backup Names}. + +@item --backup-if-mismatch +Back up the original contents of each file if the patch does not +exactly match the file. This is the default behavior when not +conforming to @acronym{POSIX}. @xref{Backups}. + +@item --binary +Read and write all files in binary mode, except for standard output +and @file{/dev/tty}. This option has no effect on +@acronym{POSIX}-conforming systems like @acronym{GNU}/Linux. On systems where +this option makes a difference, the patch should be generated by +@samp{diff -a --binary}. @xref{Binary}. + +@item -c +@itemx --context +Interpret the patch file as a context diff. @xref{patch Input}. + +@item -d @var{directory} +@itemx --directory=@var{directory} +Make directory @var{directory} the current directory for interpreting +both file names in the patch file, and file names given as arguments to +other options. @xref{patch Directories}. + +@item -D @var{name} +@itemx --ifdef=@var{name} +Make merged if-then-else output using @var{name}. @xref{If-then-else}. + +@item --dry-run +Print the results of applying the patches without actually changing +any files. @xref{Dry Runs}. + +@item -e +@itemx --ed +Interpret the patch file as an @command{ed} script. @xref{patch Input}. + +@item -E +@itemx --remove-empty-files +Remove output files that are empty after the patches have been applied. +@xref{Creating and Removing}. + +@item -f +@itemx --force +Assume that the user knows exactly what he or she is doing, and do not +ask any questions. @xref{patch Messages}. + +@item -F @var{lines} +@itemx --fuzz=@var{lines} +Set the maximum fuzz factor to @var{lines}. @xref{Inexact}. + +@item -g @var{num} +@itemx --get=@var{num} +If @var{num} is positive, get input files from a revision control +system as necessary; if zero, do not get the files; if negative, ask +the user whether to get the files. @xref{Revision Control}. + +@item --help +Output a summary of usage and then exit. + +@item -i @var{patchfile} +@itemx --input=@var{patchfile} +Read the patch from @var{patchfile} rather than from standard input. +@xref{patch Options}. + +@item -l +@itemx --ignore-white-space +Let any sequence of blanks (spaces or tabs) in the patch file match +any sequence of blanks in the input file. @xref{Changed White Space}. + +@item -n +@itemx --normal +Interpret the patch file as a normal diff. @xref{patch Input}. + +@item -N +@itemx --forward +Ignore patches that @command{patch} thinks are reversed or already applied. +See also @option{-R}. @xref{Reversed Patches}. + +@item --no-backup-if-mismatch +Do not back up the original contents of files. This is the default +behavior when conforming to @acronym{POSIX}. @xref{Backups}. + +@item -o @var{file} +@itemx --output=@var{file} +Use @var{file} as the output file name. @xref{patch Options}. + +@item -p@var{number} +@itemx --strip=@var{number} +Set the file name strip count to @var{number}. @xref{patch Directories}. + +@item --posix +Conform to @acronym{POSIX}, as if the @env{POSIXLY_CORRECT} environment +variable had been set. @xref{patch and POSIX}. + +@item --quoting-style=@var{word} +Use style @var{word} to quote names in diagnostics, as if the +@env{QUOTING_STYLE} environment variable had been set to @var{word}. +@xref{patch Quoting Style}. + +@item -r @var{reject-file} +@itemx --reject-file=@var{reject-file} +Use @var{reject-file} as the reject file name. @xref{Reject Names}. + +@item -R +@itemx --reverse +Assume that this patch was created with the old and new files swapped. +@xref{Reversed Patches}. + +@item -s +@itemx --quiet +@itemx --silent +Work silently unless an error occurs. @xref{patch Messages}. + +@item -t +@itemx --batch +Do not ask any questions. @xref{patch Messages}. + +@item -T +@itemx --set-time +Set the modification and access times of patched files from time +stamps given in context diff headers, assuming that the context diff +headers use local time. @xref{Patching Time Stamps}. + +@item -u +@itemx --unified +Interpret the patch file as a unified diff. @xref{patch Input}. + +@item -v +@itemx --version +Output version information and then exit. + +@item -V @var{backup-style} +@itemx --version=control=@var{backup-style} +Select the naming convention for backup file names. @xref{Backup Names}. + +@item --verbose +Print more diagnostics than usual. @xref{patch Messages}. + +@item -x @var{number} +@itemx --debug=@var{number} +Set internal debugging flags. Of interest only to @command{patch} +patchers. + +@item -Y @var{prefix} +@itemx --basename-prefix=@var{prefix} +Prepend @var{prefix} to base names of backup files. @xref{Backup Names}. + +@item -z @var{suffix} +@itemx --suffix=@var{suffix} +Use @var{suffix} as the backup extension instead of @samp{.orig} or +@samp{~}. @xref{Backup Names}. + +@item -Z +@itemx --set-utc +Set the modification and access times of patched files from time +stamps given in context diff headers, assuming that the context diff +headers use @acronym{UTC}. @xref{Patching Time Stamps}. + +@end table + +@node Invoking sdiff +@chapter Invoking @command{sdiff} +@cindex invoking @command{sdiff} +@cindex @command{sdiff} invocation + +The @command{sdiff} command merges two files and interactively outputs the +results. Its arguments are as follows: + +@example +sdiff -o @var{outfile} @var{options}@dots{} @var{from-file} @var{to-file} +@end example + +This merges @var{from-file} with @var{to-file}, with output to @var{outfile}. +If @var{from-file} is a directory and @var{to-file} is not, @command{sdiff} +compares the file in @var{from-file} whose file name is that of @var{to-file}, +and vice versa. @var{from-file} and @var{to-file} may not both be +directories. + +@command{sdiff} options begin with @samp{-}, so normally @var{from-file} +and @var{to-file} may not begin with @samp{-}. However, @option{--} as an +argument by itself treats the remaining arguments as file names even if +they begin with @samp{-}. You may not use @file{-} as an input file. + +@command{sdiff} without @option{-o} (or @option{--output}) produces a +side-by-side difference. This usage is obsolete; use the @option{-y} +or @option{--side-by-side} option of @command{diff} instead. + +An exit status of 0 means no differences were found, 1 means some +differences were found, and 2 means trouble. + +@menu +* sdiff Options:: Summary of options to @command{diff}. +@end menu + +@node sdiff Options +@section Options to @command{sdiff} +@cindex @command{sdiff} options +@cindex options for @command{sdiff} + +Below is a summary of all of the options that @acronym{GNU} +@command{sdiff} accepts. Each option has two equivalent names, one of +which is a single letter preceded by @samp{-}, and the other of which +is a long name preceded by @samp{--}. Multiple single letter options +(unless they take an argument) can be combined into a single command +line argument. Long named options can be abbreviated to any unique +prefix of their name. + +@table @option +@item -a +@itemx --text +Treat all files as text and compare them line-by-line, even if they +do not appear to be text. @xref{Binary}. + +@item -b +@itemx --ignore-space-change +Ignore changes in amount of white space. @xref{White Space}. + +@item -B +@itemx --ignore-blank-lines +Ignore changes that just insert or delete blank lines. @xref{Blank +Lines}. + +@item -d +@itemx --minimal +Change the algorithm to perhaps find a smaller set of changes. This +makes @command{sdiff} slower (sometimes much slower). @xref{diff +Performance}. + +@item --diff-program=@var{program} +Use the compatible comparison program @var{program} to compare files +instead of @command{diff}. + +@item -E +@itemx --ignore-tab-expansion +Ignore changes due to tab expansion. +@xref{White Space}. + +@item --help +Output a summary of usage and then exit. + +@item -i +@itemx --ignore-case +Ignore changes in case; consider upper- and lower-case to be the same. +@xref{Case Folding}. + +@item -I @var{regexp} +@itemx --ignore-matching-lines=@var{regexp} +Ignore changes that just insert or delete lines that match @var{regexp}. +@xref{Specified Lines}. + +@item -l +@itemx --left-column +Print only the left column of two common lines. +@xref{Side by Side Format}. + +@item -o @var{file} +@itemx --output=@var{file} +Put merged output into @var{file}. This option is required for merging. + +@item -s +@itemx --suppress-common-lines +Do not print common lines. @xref{Side by Side Format}. + +@item --speed-large-files +Use heuristics to speed handling of large files that have numerous +scattered small changes. @xref{diff Performance}. + +@item --strip-trailing-cr +Strip any trailing carriage return at the end of an input line. +@xref{Binary}. + +@item -t +@itemx --expand-tabs +Expand tabs to spaces in the output, to preserve the alignment of tabs +in the input files. @xref{Tabs}. + +@item --tabsize=@var{columns} +Assume that tab stops are set every @var{columns} (default 8) print +columns. @xref{Tabs}. + +@item -v +@itemx --version +Output version information and then exit. + +@item -w @var{columns} +@itemx --width=@var{columns} +Output at most @var{columns} (default 130) print columns per line. +@xref{Side by Side Format}. Note that for historical reasons, this +option is @option{-W} in @command{diff}, @option{-w} in @command{sdiff}. + +@item -W +@itemx --ignore-all-space +Ignore white space when comparing lines. @xref{White Space}. +Note that for historical reasons, this option is @option{-w} in @command{diff}, +@option{-W} in @command{sdiff}. +@end table + +@node Standards conformance +@chapter Standards conformance +@cindex @acronym{POSIX} + +@vindex POSIXLY_CORRECT +In a few cases, the @acronym{GNU} utilities' default behavior is +incompatible with the @acronym{POSIX} standard. To suppress these +incompatibilities, define the @env{POSIXLY_CORRECT} environment +variable. Unless you are checking for @acronym{POSIX} conformance, you +probably do not need to define @env{POSIXLY_CORRECT}. + +Normally options and operands can appear in any order, and programs act +as if all the options appear before any operands. For example, +@samp{diff lao tzu -C 2} acts like @samp{diff -C 2 lao tzu}, since +@samp{2} is an option-argument of @option{-C}. However, if the +@env{POSIXLY_CORRECT} environment variable is set, options must appear +before operands, unless otherwise specified for a particular command. + +Newer versions of @acronym{POSIX} are occasionally incompatible with older +versions. For example, older versions of @acronym{POSIX} allowed the +command @samp{diff -c -10} to have the same meaning as @samp{diff -C +10}, but @acronym{POSIX} 1003.1-2001 @samp{diff} no longer allows +digit-string options like @option{-10}. + +@vindex _POSIX2_VERSION +The @acronym{GNU} utilities normally conform to the version of @acronym{POSIX} +that is standard for your system. To cause them to conform to a +different version of @acronym{POSIX}, define the @env{_POSIX2_VERSION} +environment variable to a value of the form @var{yyyymm} specifying +the year and month the standard was adopted. Two values are currently +supported for @env{_POSIX2_VERSION}: @samp{199209} stands for +@acronym{POSIX} 1003.2-1992, and @samp{200112} stands for @acronym{POSIX} +1003.1-2001. For example, if you are running older software that +assumes an older version of @acronym{POSIX} and uses @samp{diff -c -10}, +you can work around the compatibility problems by setting +@samp{_POSIX2_VERSION=199209} in your environment. + +@node Projects +@chapter Future Projects + +Here are some ideas for improving @acronym{GNU} @command{diff} and +@command{patch}. The @acronym{GNU} project has identified some +improvements as potential programming projects for volunteers. You +can also help by reporting any bugs that you find. + +If you are a programmer and would like to contribute something to the +@acronym{GNU} project, please consider volunteering for one of these +projects. If you are seriously contemplating work, please write to +@email{gvc@@gnu.org} to coordinate with other volunteers. + +@menu +* Shortcomings:: Suggested projects for improvements. +* Bugs:: Reporting bugs. +@end menu + +@node Shortcomings +@section Suggested Projects for Improving @acronym{GNU} @command{diff} and @command{patch} +@cindex projects for directories + +One should be able to use @acronym{GNU} @command{diff} to generate a +patch from any pair of directory trees, and given the patch and a copy +of one such tree, use @command{patch} to generate a faithful copy of +the other. Unfortunately, some changes to directory trees cannot be +expressed using current patch formats; also, @command{patch} does not +handle some of the existing formats. These shortcomings motivate the +following suggested projects. + +@menu +* Internationalization:: Handling multibyte and varying-width characters. +* Changing Structure:: Handling changes to the directory structure. +* Special Files:: Handling symbolic links, device special files, etc. +* Unusual File Names:: Handling file names that contain unusual characters. +* Time Stamp Order:: Outputting diffs in time stamp order. +* Ignoring Changes:: Ignoring certain changes while showing others. +* Speedups:: Improving performance. +@end menu + +@node Internationalization +@subsection Handling Multibyte and Varying-Width Characters +@cindex multibyte characters +@cindex varying-width characters + +@command{diff}, @command{diff3} and @command{sdiff} treat each line of +input as a string of unibyte characters. This can mishandle multibyte +characters in some cases. For example, when asked to ignore spaces, +@command{diff} does not properly ignore a multibyte space character. + +Also, @command{diff} currently assumes that each byte is one column +wide, and this assumption is incorrect in some locales, e.g., locales +that use UTF-8 encoding. This causes problems with the @option{-y} or +@option{--side-by-side} option of @command{diff}. + +These problems need to be fixed without unduly affecting the +performance of the utilities in unibyte environments. + +The IBM GNU/Linux Technology Center Internationalization Team has +proposed +@uref{http://oss.software.ibm.com/developer/opensource/linux/patches/i18n/diffutils-2.7.2-i18n-0.1.patch.gz,patches +to support internationalized @command{diff}}. +Unfortunately, these patches are incomplete and are to an older +version of @command{diff}, so more work needs to be done in this area. + +@node Changing Structure +@subsection Handling Changes to the Directory Structure +@cindex directory structure changes + +@command{diff} and @command{patch} do not handle some changes to directory +structure. For example, suppose one directory tree contains a directory +named @samp{D} with some subsidiary files, and another contains a file +with the same name @samp{D}. @samp{diff -r} does not output enough +information for @command{patch} to transform the directory subtree into +the file. + +There should be a way to specify that a file has been removed without +having to include its entire contents in the patch file. There should +also be a way to tell @command{patch} that a file was renamed, even if +there is no way for @command{diff} to generate such information. +There should be a way to tell @command{patch} that a file's time stamp +has changed, even if its contents have not changed. + +These problems can be fixed by extending the @command{diff} output format +to represent changes in directory structure, and extending @command{patch} +to understand these extensions. + +@node Special Files +@subsection Files that are Neither Directories Nor Regular Files +@cindex special files + +Some files are neither directories nor regular files: they are unusual +files like symbolic links, device special files, named pipes, and +sockets. Currently, @command{diff} treats symbolic links as if they +were the pointed-to files, except that a recursive @command{diff} +reports an error if it detects infinite loops of symbolic links (e.g., +symbolic links to @file{..}). @command{diff} treats other special +files like regular files if they are specified at the top level, but +simply reports their presence when comparing directories. This means +that @command{patch} cannot represent changes to such files. For +example, if you change which file a symbolic link points to, +@command{diff} outputs the difference between the two files, instead +of the change to the symbolic link. + +@c This might not be a good idea; is it wise for root to install devices +@c this way? +@command{diff} should optionally report changes to special files specially, +and @command{patch} should be extended to understand these extensions. + +@node Unusual File Names +@subsection File Names that Contain Unusual Characters +@cindex file names with unusual characters + +When a file name contains an unusual character like a newline or +white space, @samp{diff -r} generates a patch that @command{patch} cannot +parse. The problem is with format of @command{diff} output, not just with +@command{patch}, because with odd enough file names one can cause +@command{diff} to generate a patch that is syntactically correct but +patches the wrong files. The format of @command{diff} output should be +extended to handle all possible file names. + +@node Time Stamp Order +@subsection Outputting Diffs in Time Stamp Order + +Applying @command{patch} to a multiple-file diff can result in files +whose time stamps are out of order. @acronym{GNU} @command{patch} has +options to restore the time stamps of the updated files +(@pxref{Patching Time Stamps}), but sometimes it is useful to generate +a patch that works even if the recipient does not have @acronym{GNU} patch, +or does not use these options. One way to do this would be to +implement a @command{diff} option to output diffs in time stamp order. + +@node Ignoring Changes +@subsection Ignoring Certain Changes + +It would be nice to have a feature for specifying two strings, one in +@var{from-file} and one in @var{to-file}, which should be considered to +match. Thus, if the two strings are @samp{foo} and @samp{bar}, then if +two lines differ only in that @samp{foo} in file 1 corresponds to +@samp{bar} in file 2, the lines are treated as identical. + +It is not clear how general this feature can or should be, or +what syntax should be used for it. + +A partial substitute is to filter one or both files before comparing, +e.g.: + +@example +sed 's/foo/bar/g' file1 | diff - file2 +@end example + +However, this outputs the filtered text, not the original. + +@node Speedups +@subsection Improving Performance + +When comparing two large directory structures, one of which was +originally copied from the other with time stamps preserved (e.g., +with @samp{cp -pR}), it would greatly improve performance if an option +told @command{diff} to assume that two files with the same size and +time stamps have the same content. @xref{diff Performance}. + +@node Bugs +@section Reporting Bugs +@cindex bug reports +@cindex reporting bugs + +If you think you have found a bug in @acronym{GNU} @command{cmp}, +@command{diff}, @command{diff3}, or @command{sdiff}, please report it +by electronic mail to the +@uref{http://mail.gnu.org/mailman/listinfo/bug-gnu-utils,GNU utilities +bug report mailing list} @email{bug-gnu-utils@@gnu.org}. Please send +bug reports for @acronym{GNU} @command{patch} to +@email{bug-patch@@gnu.org}. Send as precise a description of the +problem as you can, including the output of the @option{--version} +option and sample input files that produce the bug, if applicable. If +you have a nontrivial fix for the bug, please send it as well. If you +have a patch, please send it too. It may simplify the maintainer's +job if the patch is relative to a recent test release, which you can +find in the directory @uref{ftp://alpha.gnu.org/gnu/diffutils/}. + +@node Copying This Manual +@appendix Copying This Manual + +@menu +* GNU Free Documentation License:: License for copying this manual. +@end menu + +@include fdl.texi + +@node Translations +@appendix Translations of This Manual + +Nishio Futoshi of the GNUjdoc project has prepared a Japanese +translation of this manual. Its most recent version can be found at +@uref{http://openlab.ring.gr.jp/gnujdoc/cvsweb/cvsweb.cgi/gnujdoc/}. + +@node Index +@appendix Index + +@printindex cp + +@bye diff --git a/contrib/diffutils-2.8/doc/fdl.texi b/contrib/diffutils-2.8/doc/fdl.texi new file mode 100644 index 0000000000..11737cc89b --- /dev/null +++ b/contrib/diffutils-2.8/doc/fdl.texi @@ -0,0 +1,452 @@ + +@node GNU Free Documentation License +@appendixsec GNU Free Documentation License + +@cindex FDL, GNU Free Documentation License +@center Version 1.2, November 2002 + +@display +Copyright @copyright{} 2000,2001,2002 Free Software Foundation, Inc. +59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. +@end display + +@enumerate 0 +@item +PREAMBLE + +The purpose of this License is to make a manual, textbook, or other +functional and useful document @dfn{free} in the sense of freedom: to +assure everyone the effective freedom to copy and redistribute it, +with or without modifying it, either commercially or noncommercially. +Secondarily, this License preserves for the author and publisher a way +to get credit for their work, while not being considered responsible +for modifications made by others. + +This License is a kind of ``copyleft'', which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + +@item +APPLICABILITY AND DEFINITIONS + +This License applies to any manual or other work, in any medium, that +contains a notice placed by the copyright holder saying it can be +distributed under the terms of this License. Such a notice grants a +world-wide, royalty-free license, unlimited in duration, to use that +work under the conditions stated herein. The ``Document'', below, +refers to any such manual or work. Any member of the public is a +licensee, and is addressed as ``you''. You accept the license if you +copy, modify or distribute the work in a way requiring permission +under copyright law. + +A ``Modified Version'' of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +A ``Secondary Section'' is a named appendix or a front-matter section +of the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document's overall +subject (or to related matters) and contains nothing that could fall +directly within that overall subject. (Thus, if the Document is in +part a textbook of mathematics, a Secondary Section may not explain +any mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +The ``Invariant Sections'' are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. If a +section does not fit the above definition of Secondary then it is not +allowed to be designated as Invariant. The Document may contain zero +Invariant Sections. If the Document does not identify any Invariant +Sections then there are none. + +The ``Cover Texts'' are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. A Front-Cover Text may +be at most 5 words, and a Back-Cover Text may be at most 25 words. + +A ``Transparent'' copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, that is suitable for revising the document +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup, or absence of markup, has been arranged to thwart +or discourage subsequent modification by readers is not Transparent. +An image format is not Transparent if used for any substantial amount +of text. A copy that is not ``Transparent'' is called ``Opaque''. + +Examples of suitable formats for Transparent copies include plain +@sc{ascii} without markup, Texinfo input format, La@TeX{} input +format, @acronym{SGML} or @acronym{XML} using a publicly available +@acronym{DTD}, and standard-conforming simple @acronym{HTML}, +PostScript or @acronym{PDF} designed for human modification. Examples +of transparent image formats include @acronym{PNG}, @acronym{XCF} and +@acronym{JPG}. Opaque formats include proprietary formats that can be +read and edited only by proprietary word processors, @acronym{SGML} or +@acronym{XML} for which the @acronym{DTD} and/or processing tools are +not generally available, and the machine-generated @acronym{HTML}, +PostScript or @acronym{PDF} produced by some word processors for +output purposes only. + +The ``Title Page'' means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, ``Title Page'' means +the text near the most prominent appearance of the work's title, +preceding the beginning of the body of the text. + +A section ``Entitled XYZ'' means a named subunit of the Document whose +title either is precisely XYZ or contains XYZ in parentheses following +text that translates XYZ in another language. (Here XYZ stands for a +specific section name mentioned below, such as ``Acknowledgements'', +``Dedications'', ``Endorsements'', or ``History''.) To ``Preserve the Title'' +of such a section when you modify the Document means that it remains a +section ``Entitled XYZ'' according to this definition. + +The Document may include Warranty Disclaimers next to the notice which +states that this License applies to the Document. These Warranty +Disclaimers are considered to be included by reference in this +License, but only as regards disclaiming warranties: any other +implication that these Warranty Disclaimers may have is void and has +no effect on the meaning of this License. + +@item +VERBATIM COPYING + +You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no other +conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +You may also lend copies, under the same conditions stated above, and +you may publicly display copies. + +@item +COPYING IN QUANTITY + +If you publish printed copies (or copies in media that commonly have +printed covers) of the Document, numbering more than 100, and the +Document's license notice requires Cover Texts, you must enclose the +copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a computer-network location from which the general network-using +public has access to download using public-standard network protocols +a complete Transparent copy of the Document, free of added material. +If you use the latter option, you must take reasonably prudent steps, +when you begin distribution of Opaque copies in quantity, to ensure +that this Transparent copy will remain thus accessible at the stated +location until at least one year after the last time you distribute an +Opaque copy (directly or through your agents or retailers) of that +edition to the public. + +It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to give +them a chance to provide you with an updated version of the Document. + +@item +MODIFICATIONS + +You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + +@enumerate A +@item +Use in the Title Page (and on the covers, if any) a title distinct +from that of the Document, and from those of previous versions +(which should, if there were any, be listed in the History section +of the Document). You may use the same title as a previous version +if the original publisher of that version gives permission. + +@item +List on the Title Page, as authors, one or more persons or entities +responsible for authorship of the modifications in the Modified +Version, together with at least five of the principal authors of the +Document (all of its principal authors, if it has fewer than five), +unless they release you from this requirement. + +@item +State on the Title page the name of the publisher of the +Modified Version, as the publisher. + +@item +Preserve all the copyright notices of the Document. + +@item +Add an appropriate copyright notice for your modifications +adjacent to the other copyright notices. + +@item +Include, immediately after the copyright notices, a license notice +giving the public permission to use the Modified Version under the +terms of this License, in the form shown in the Addendum below. + +@item +Preserve in that license notice the full lists of Invariant Sections +and required Cover Texts given in the Document's license notice. + +@item +Include an unaltered copy of this License. + +@item +Preserve the section Entitled ``History'', Preserve its Title, and add +to it an item stating at least the title, year, new authors, and +publisher of the Modified Version as given on the Title Page. If +there is no section Entitled ``History'' in the Document, create one +stating the title, year, authors, and publisher of the Document as +given on its Title Page, then add an item describing the Modified +Version as stated in the previous sentence. + +@item +Preserve the network location, if any, given in the Document for +public access to a Transparent copy of the Document, and likewise +the network locations given in the Document for previous versions +it was based on. These may be placed in the ``History'' section. +You may omit a network location for a work that was published at +least four years before the Document itself, or if the original +publisher of the version it refers to gives permission. + +@item +For any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve +the Title of the section, and preserve in the section all the +substance and tone of each of the contributor acknowledgements and/or +dedications given therein. + +@item +Preserve all the Invariant Sections of the Document, +unaltered in their text and in their titles. Section numbers +or the equivalent are not considered part of the section titles. + +@item +Delete any section Entitled ``Endorsements''. Such a section +may not be included in the Modified Version. + +@item +Do not retitle any existing section to be Entitled ``Endorsements'' or +to conflict in title with any Invariant Section. + +@item +Preserve any Warranty Disclaimers. +@end enumerate + +If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version's license notice. +These titles must be distinct from any other section titles. + +You may add a section Entitled ``Endorsements'', provided it contains +nothing but endorsements of your Modified Version by various +parties---for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. + +@item +COMBINING DOCUMENTS + +You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice, and that you preserve all their Warranty Disclaimers. + +The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +In the combination, you must combine any sections Entitled ``History'' +in the various original documents, forming one section Entitled +``History''; likewise combine any sections Entitled ``Acknowledgements'', +and any sections Entitled ``Dedications''. You must delete all +sections Entitled ``Endorsements.'' + +@item +COLLECTIONS OF DOCUMENTS + +You may make a collection consisting of the Document and other documents +released under this License, and replace the individual copies of this +License in the various documents with a single copy that is included in +the collection, provided that you follow the rules of this License for +verbatim copying of each of the documents in all other respects. + +You may extract a single document from such a collection, and distribute +it individually under this License, provided you insert a copy of this +License into the extracted document, and follow this License in all +other respects regarding verbatim copying of that document. + +@item +AGGREGATION WITH INDEPENDENT WORKS + +A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, is called an ``aggregate'' if the copyright +resulting from the compilation is not used to limit the legal rights +of the compilation's users beyond what the individual works permit. +When the Document is included in an aggregate, this License does not +apply to the other works in the aggregate which are not themselves +derivative works of the Document. + +If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one half of +the entire aggregate, the Document's Cover Texts may be placed on +covers that bracket the Document within the aggregate, or the +electronic equivalent of covers if the Document is in electronic form. +Otherwise they must appear on printed covers that bracket the whole +aggregate. + +@item +TRANSLATION + +Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License, and all the license notices in the +Document, and any Warranty Disclaimers, provided that you also include +the original English version of this License and the original versions +of those notices and disclaimers. In case of a disagreement between +the translation and the original version of this License or a notice +or disclaimer, the original version will prevail. + +If a section in the Document is Entitled ``Acknowledgements'', +``Dedications'', or ``History'', the requirement (section 4) to Preserve +its Title (section 1) will typically require changing the actual +title. + +@item +TERMINATION + +You may not copy, modify, sublicense, or distribute the Document except +as expressly provided for under this License. Any other attempt to +copy, modify, sublicense or distribute the Document is void, and will +automatically terminate your rights under this License. However, +parties who have received copies, or rights, from you under this +License will not have their licenses terminated so long as such +parties remain in full compliance. + +@item +FUTURE REVISIONS OF THIS LICENSE + +The Free Software Foundation may publish new, revised versions +of the GNU Free Documentation License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. See +@uref{http://www.gnu.org/copyleft/}. + +Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License ``or any later version'' applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. +@end enumerate + +@page +@appendixsubsec ADDENDUM: How to use this License for your documents + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and +license notices just after the title page: + +@smallexample +@group + Copyright (C) @var{year} @var{your name}. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.2 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover + Texts. A copy of the license is included in the section entitled ``GNU + Free Documentation License''. +@end group +@end smallexample + +If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, +replace the ``with...Texts.'' line with this: + +@smallexample +@group + with the Invariant Sections being @var{list their titles}, with + the Front-Cover Texts being @var{list}, and with the Back-Cover Texts + being @var{list}. +@end group +@end smallexample + +If you have Invariant Sections without Cover Texts, or some other +combination of the three, merge those two alternatives to suit the +situation. + +If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of +free software license, such as the GNU General Public License, +to permit their use in free software. + +@c Local Variables: +@c ispell-local-pdict: "ispell-dict" +@c End: + diff --git a/contrib/diffutils-2.8/doc/stamp-vti b/contrib/diffutils-2.8/doc/stamp-vti new file mode 100644 index 0000000000..cb009ceda4 --- /dev/null +++ b/contrib/diffutils-2.8/doc/stamp-vti @@ -0,0 +1,4 @@ +@set UPDATED 12 April 2004 +@set UPDATED-MONTH April 2004 +@set EDITION 2.8.7 +@set VERSION 2.8.7 diff --git a/contrib/diffutils-2.8/doc/version.texi b/contrib/diffutils-2.8/doc/version.texi new file mode 100644 index 0000000000..cb009ceda4 --- /dev/null +++ b/contrib/diffutils-2.8/doc/version.texi @@ -0,0 +1,4 @@ +@set UPDATED 12 April 2004 +@set UPDATED-MONTH April 2004 +@set EDITION 2.8.7 +@set VERSION 2.8.7 diff --git a/contrib/diffutils-2.8/lib/basename.c b/contrib/diffutils-2.8/lib/basename.c new file mode 100644 index 0000000000..5ff2989330 --- /dev/null +++ b/contrib/diffutils-2.8/lib/basename.c @@ -0,0 +1,79 @@ +/* basename.c -- return the last element in a path + + Copyright (C) 1990, 1998, 1999, 2000, 2001, 2003 Free Software + Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#if HAVE_CONFIG_H +# include +#endif + +#include "dirname.h" +#include + +/* In general, we can't use the builtin `basename' function if available, + since it has different meanings in different environments. + In some environments the builtin `basename' modifies its argument. + + Return the address of the last file name component of NAME. If + NAME has no file name components because it is all slashes, return + NAME if it is empty, the address of its last slash otherwise. */ + +char * +base_name (char const *name) +{ + char const *base = name + FILESYSTEM_PREFIX_LEN (name); + char const *p; + + for (p = base; *p; p++) + { + if (ISSLASH (*p)) + { + /* Treat multiple adjacent slashes like a single slash. */ + do p++; + while (ISSLASH (*p)); + + /* If the file name ends in slash, use the trailing slash as + the basename if no non-slashes have been found. */ + if (! *p) + { + if (ISSLASH (*base)) + base = p - 1; + break; + } + + /* *P is a non-slash preceded by a slash. */ + base = p; + } + } + + return (char *) base; +} + +/* Return the length of of the basename NAME. Typically NAME is the + value returned by base_name. Act like strlen (NAME), except omit + redundant trailing slashes. */ + +size_t +base_len (char const *name) +{ + size_t len; + + for (len = strlen (name); 1 < len && ISSLASH (name[len - 1]); len--) + continue; + + return len; +} diff --git a/contrib/diffutils-2.8/lib/c-stack.c b/contrib/diffutils-2.8/lib/c-stack.c new file mode 100644 index 0000000000..a018e5158e --- /dev/null +++ b/contrib/diffutils-2.8/lib/c-stack.c @@ -0,0 +1,311 @@ +/* Stack overflow handling. + + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Paul Eggert. */ + +/* NOTES: + + A program that uses alloca, dynamic arrays, or large local + variables may extend the stack by more than a page at a time. If + so, when the stack overflows the operating system may not detect + the overflow until the program uses the array, and this module may + incorrectly report a program error instead of a stack overflow. + + To avoid this problem, allocate only small objects on the stack; a + program should be OK if it limits single allocations to a page or + less. Allocate larger arrays in static storage, or on the heap + (e.g., with malloc). Yes, this is a pain, but we don't know of any + better solution that is portable. + + No attempt has been made to deal with multithreaded applications. */ + +#if HAVE_CONFIG_H +# include +#endif + +#ifndef __attribute__ +# if __GNUC__ < 3 || __STRICT_ANSI__ +# define __attribute__(x) +# endif +#endif + +#include "gettext.h" +#define _(msgid) gettext (msgid) + +#include +#ifndef ENOTSUP +# define ENOTSUP EINVAL +#endif +#ifndef EOVERFLOW +# define EOVERFLOW EINVAL +#endif + +#include +#if ! HAVE_STACK_T && ! defined stack_t +typedef struct sigaltstack stack_t; +#endif + +#include +#include + +#if HAVE_SYS_RESOURCE_H +/* Include sys/time.h here, because... + SunOS-4.1.x fails to include . + This gives "incomplete type" errors for ru_utime and tu_stime. */ +# if HAVE_SYS_TIME_H +# include +# endif +# include +#endif + +#if HAVE_UCONTEXT_H +# include +#endif + +#if HAVE_UNISTD_H +# include +#endif +#ifndef STDERR_FILENO +# define STDERR_FILENO 2 +#endif + +#if DEBUG +# include +#endif + +#include "c-stack.h" +#include "exitfail.h" + +#if (HAVE_STRUCT_SIGACTION_SA_SIGACTION && defined SA_NODEFER \ + && defined SA_ONSTACK && defined SA_RESETHAND && defined SA_SIGINFO) +# define SIGACTION_WORKS 1 +#else +# define SIGACTION_WORKS 0 +#endif + +extern char *program_name; + +/* The user-specified action to take when a SEGV-related program error + or stack overflow occurs. */ +static void (* volatile segv_action) (int); + +/* Translated messages for program errors and stack overflow. Do not + translate them in the signal handler, since gettext is not + async-signal-safe. */ +static char const * volatile program_error_message; +static char const * volatile stack_overflow_message; + +/* Output an error message, then exit with status EXIT_FAILURE if it + appears to have been a stack overflow, or with a core dump + otherwise. This function is async-signal-safe. */ + +static void die (int) __attribute__ ((noreturn)); +static void +die (int signo) +{ + char const *message; + segv_action (signo); + message = signo ? program_error_message : stack_overflow_message; + write (STDERR_FILENO, program_name, strlen (program_name)); + write (STDERR_FILENO, ": ", 2); + write (STDERR_FILENO, message, strlen (message)); + write (STDERR_FILENO, "\n", 1); + if (! signo) + _exit (exit_failure); + kill (getpid (), signo); + abort (); +} + +#if HAVE_SIGALTSTACK && HAVE_DECL_SIGALTSTACK + +/* Direction of the C runtime stack. This function is + async-signal-safe. */ + +# if STACK_DIRECTION +# define find_stack_direction(ptr) STACK_DIRECTION +# else +static int +find_stack_direction (char const *addr) +{ + char dummy; + return ! addr ? find_stack_direction (&dummy) : addr < &dummy ? 1 : -1; +} +# endif + +/* Storage for the alternate signal stack. */ +static union +{ + char buffer[SIGSTKSZ]; + + /* These other members are for proper alignment. There's no + standard way to guarantee stack alignment, but this seems enough + in practice. */ + long double ld; + long l; + void *p; +} alternate_signal_stack; + +# if SIGACTION_WORKS + +/* Handle a segmentation violation and exit. This function is + async-signal-safe. */ + +static void segv_handler (int, siginfo_t *, void *) __attribute__((noreturn)); +static void +segv_handler (int signo, siginfo_t *info, + void *context __attribute__ ((unused))) +{ + /* Clear SIGNO if it seems to have been a stack overflow. */ + if (0 < info->si_code) + { +# if ! HAVE_XSI_STACK_OVERFLOW_HEURISTIC + /* We can't easily determine whether it is a stack overflow; so + assume that the rest of our program is perfect (!) and that + this segmentation violation is a stack overflow. */ + signo = 0; +# else + /* If the faulting address is within the stack, or within one + page of the stack end, assume that it is a stack + overflow. */ + ucontext_t const *user_context = context; + char const *stack_base = user_context->uc_stack.ss_sp; + size_t stack_size = user_context->uc_stack.ss_size; + char const *faulting_address = info->si_addr; + size_t s = faulting_address - stack_base; + size_t page_size = sysconf (_SC_PAGESIZE); + if (find_stack_direction (0) < 0) + s += page_size; + if (s < stack_size + page_size) + signo = 0; + +# if DEBUG + { + char buf[1024]; + sprintf (buf, + "segv_handler fault=%p base=%p size=%lx page=%lx signo=%d\n", + faulting_address, stack_base, (unsigned long) stack_size, + (unsigned long) page_size, signo); + write (STDERR_FILENO, buf, strlen (buf)); + } +# endif +# endif + } + + die (signo); +} +# endif + +static void +null_action (int signo __attribute__ ((unused))) +{ +} + +/* Set up ACTION so that it is invoked on C stack overflow. Return -1 + (setting errno) if this cannot be done. + + When ACTION is called, it is passed an argument equal to SIGSEGV + for a segmentation violation that does not appear related to stack + overflow, and is passed zero otherwise. On many platforms it is + hard to tell; when in doubt, zero is passed. + + A null ACTION acts like an action that does nothing. + + ACTION must be async-signal-safe. ACTION together with its callees + must not require more than SIGSTKSZ bytes of stack space. */ + +int +c_stack_action (void (*action) (int)) +{ + int r; + stack_t st; + st.ss_flags = 0; + st.ss_sp = alternate_signal_stack.buffer; + st.ss_size = sizeof alternate_signal_stack.buffer; + r = sigaltstack (&st, 0); + if (r != 0) + return r; + + segv_action = action ? action : null_action; + program_error_message = _("program error"); + stack_overflow_message = _("stack overflow"); + + { +# if SIGACTION_WORKS + struct sigaction act; + sigemptyset (&act.sa_mask); + + /* POSIX 1003.1-2001 says SA_RESETHAND implies SA_NODEFER, but + this is not true on Solaris 8 at least. It doesn't hurt to use + SA_NODEFER here, so leave it in. */ + act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO; + + act.sa_sigaction = segv_handler; + + return sigaction (SIGSEGV, &act, 0); +# else + return signal (SIGSEGV, die) == SIG_ERR ? -1 : 0; +# endif + } +} + +#else /* ! (HAVE_SIGALTSTACK && HAVE_DECL_SIGALTSTACK) */ + +int +c_stack_action (void (*action) (int) __attribute__ ((unused))) +{ + errno = ENOTSUP; + return -1; +} + +#endif + + + +#if DEBUG + +int volatile exit_failure; + +static long +recurse (char *p) +{ + char array[500]; + array[0] = 1; + return *p + recurse (array); +} + +char *program_name; + +int +main (int argc __attribute__ ((unused)), char **argv) +{ + program_name = argv[0]; + fprintf (stderr, + "The last output line should contain \"stack overflow\".\n"); + if (c_stack_action (0) == 0) + return recurse ("\1"); + perror ("c_stack_action"); + return 1; +} + +#endif /* DEBUG */ + +/* +Local Variables: +compile-command: "gcc -DDEBUG -DHAVE_CONFIG_H -I.. -g -O -Wall -W c-stack.c" +End: +*/ diff --git a/contrib/diffutils-2.8/lib/c-stack.h b/contrib/diffutils-2.8/lib/c-stack.h new file mode 100644 index 0000000000..968fd5229f --- /dev/null +++ b/contrib/diffutils-2.8/lib/c-stack.h @@ -0,0 +1,19 @@ +/* Stack overflow handling. + + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +int c_stack_action (void (*) (int)); diff --git a/contrib/diffutils-2.8/lib/cmpbuf.c b/contrib/diffutils-2.8/lib/cmpbuf.c new file mode 100644 index 0000000000..858aa39346 --- /dev/null +++ b/contrib/diffutils-2.8/lib/cmpbuf.c @@ -0,0 +1,147 @@ +/* Buffer primitives for comparison operations. + + Copyright (C) 1993, 1995, 1998, 2001, 2002 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#if HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include +#ifndef SA_RESTART +# ifdef SA_INTERRUPT /* e.g. SunOS 4.1.x */ +# define SA_RESTART SA_INTERRUPT +# else +# define SA_RESTART 0 +# endif +#endif + +#if HAVE_UNISTD_H +# include +#endif + +#if HAVE_INTTYPES_H +# include +#endif + +#include +#include "cmpbuf.h" + +/* Determine whether an integer type is signed, and its bounds. + This code assumes two's (or one's!) complement with no holes. */ + +/* The extra casts work around common compiler bugs, + e.g. Cray C 5.0.3.0 when t == time_t. */ +#ifndef TYPE_SIGNED +# define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) +#endif +#ifndef TYPE_MINIMUM +# define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \ + ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) \ + : (t) 0)) +#endif +#ifndef TYPE_MAXIMUM +# define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t))) +#endif + +#ifndef PTRDIFF_MAX +# define PTRDIFF_MAX TYPE_MAXIMUM (ptrdiff_t) +#endif +#ifndef SIZE_MAX +# define SIZE_MAX TYPE_MAXIMUM (size_t) +#endif +#ifndef SSIZE_MAX +# define SSIZE_MAX TYPE_MAXIMUM (ssize_t) +#endif + +#undef MIN +#define MIN(a, b) ((a) <= (b) ? (a) : (b)) + +/* Read NBYTES bytes from descriptor FD into BUF. + NBYTES must not be SIZE_MAX. + Return the number of characters successfully read. + On error, return SIZE_MAX, setting errno. + The number returned is always NBYTES unless end-of-file or error. */ + +size_t +block_read (int fd, char *buf, size_t nbytes) +{ + char *bp = buf; + char const *buflim = buf + nbytes; + size_t readlim = SSIZE_MAX; + + do + { + size_t bytes_to_read = MIN (buflim - bp, readlim); + ssize_t nread = read (fd, bp, bytes_to_read); + if (nread <= 0) + { + if (nread == 0) + break; + + /* Accommodate Tru64 5.1, which can't read more than INT_MAX + bytes at a time. They call that a 64-bit OS? */ + if (errno == EINVAL && INT_MAX < bytes_to_read) + { + readlim = INT_MAX; + continue; + } + + /* This is needed for programs that have signal handlers on + older hosts without SA_RESTART. It also accommodates + ancient AIX hosts that set errno to EINTR after uncaught + SIGCONT. See + (1993-04-22). */ + if (! SA_RESTART && errno == EINTR) + continue; + + return SIZE_MAX; + } + bp += nread; + } + while (bp < buflim); + + return bp - buf; +} + +/* Least common multiple of two buffer sizes A and B. However, if + either A or B is zero, or if the multiple is greater than LCM_MAX, + return a reasonable buffer size. */ + +size_t +buffer_lcm (size_t a, size_t b, size_t lcm_max) +{ + size_t lcm, m, n, q, r; + + /* Yield reasonable values if buffer sizes are zero. */ + if (!a) + return b ? b : 8 * 1024; + if (!b) + return a; + + /* n = gcd (a, b) */ + for (m = a, n = b; (r = m % n) != 0; m = n, n = r) + continue; + + /* Yield a if there is an overflow. */ + q = a / n; + lcm = q * b; + return lcm <= lcm_max && lcm / b == q ? lcm : a; +} diff --git a/contrib/diffutils-2.8/lib/cmpbuf.h b/contrib/diffutils-2.8/lib/cmpbuf.h new file mode 100644 index 0000000000..9b29cd0827 --- /dev/null +++ b/contrib/diffutils-2.8/lib/cmpbuf.h @@ -0,0 +1,21 @@ +/* Buffer primitives for comparison operations. + + Copyright (C) 2002 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +size_t block_read (int, char *, size_t); +size_t buffer_lcm (size_t, size_t, size_t); diff --git a/contrib/diffutils-2.8/lib/dirname.h b/contrib/diffutils-2.8/lib/dirname.h new file mode 100644 index 0000000000..62da37dc9a --- /dev/null +++ b/contrib/diffutils-2.8/lib/dirname.h @@ -0,0 +1,43 @@ +/* Take file names apart into directory and base names. + + Copyright (C) 1998, 2001, 2003 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef DIRNAME_H_ +# define DIRNAME_H_ 1 + +# include + +# ifndef DIRECTORY_SEPARATOR +# define DIRECTORY_SEPARATOR '/' +# endif + +# ifndef ISSLASH +# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR) +# endif + +# ifndef FILESYSTEM_PREFIX_LEN +# define FILESYSTEM_PREFIX_LEN(Filename) 0 +# endif + +char *base_name (char const *path); +char *dir_name (char const *path); +size_t base_len (char const *path); +size_t dir_len (char const *path); + +int strip_trailing_slashes (char *path); + +#endif /* not DIRNAME_H_ */ diff --git a/contrib/diffutils-2.8/lib/error.c b/contrib/diffutils-2.8/lib/error.c new file mode 100644 index 0000000000..1149235a10 --- /dev/null +++ b/contrib/diffutils-2.8/lib/error.c @@ -0,0 +1,310 @@ +/* Error handler for noninteractive utilities + Copyright (C) 1990-1998, 2000-2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by David MacKenzie . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "error.h" + +#include +#include +#include +#include + +#ifdef _LIBC +# include +#else +# include "gettext.h" +#endif + +#ifdef _LIBC +# include +# define mbsrtowcs __mbsrtowcs +#endif + +#if !_LIBC +# include "unlocked-io.h" +#endif + +#ifndef _ +# define _(String) String +#endif + +/* If NULL, error will flush stdout, then print on stderr the program + name, a colon and a space. Otherwise, error will call this + function without parameters instead. */ +void (*error_print_progname) (void); + +/* This variable is incremented each time `error' is called. */ +unsigned int error_message_count; + +#ifdef _LIBC +/* In the GNU C library, there is a predefined variable for this. */ + +# define program_name program_invocation_name +# include +# include + +/* In GNU libc we want do not want to use the common name `error' directly. + Instead make it a weak alias. */ +extern void __error (int status, int errnum, const char *message, ...) + __attribute__ ((__format__ (__printf__, 3, 4))); +extern void __error_at_line (int status, int errnum, const char *file_name, + unsigned int line_number, const char *message, + ...) + __attribute__ ((__format__ (__printf__, 5, 6)));; +# define error __error +# define error_at_line __error_at_line + +# include +# define fflush(s) INTUSE(_IO_fflush) (s) +# undef putc +# define putc(c, fp) INTUSE(_IO_putc) (c, fp) + +# include + +#else /* not _LIBC */ + +# if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P +# ifndef HAVE_DECL_STRERROR_R +"this configure-time declaration test was not run" +# endif +char *strerror_r (); +# endif + +# ifndef SIZE_MAX +# define SIZE_MAX ((size_t) -1) +# endif + +/* The calling program should define program_name and set it to the + name of the executing program. */ +extern char *program_name; + +# if HAVE_STRERROR_R || defined strerror_r +# define __strerror_r strerror_r +# endif +#endif /* not _LIBC */ + +static void +print_errno_message (int errnum) +{ + char const *s; + +#if defined HAVE_STRERROR_R || _LIBC + char errbuf[1024]; +# if STRERROR_R_CHAR_P || _LIBC + s = __strerror_r (errnum, errbuf, sizeof errbuf); +# else + if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0) + s = errbuf; + else + s = 0; +# endif +#else + s = strerror (errnum); +#endif + +#if !_LIBC + if (! s) + s = _("Unknown system error"); +#endif + +#if _LIBC + if (_IO_fwide (stderr, 0) > 0) + { + __fwprintf (stderr, L": %s", s); + return; + } +#endif + + fprintf (stderr, ": %s", s); +} + +static void +error_tail (int status, int errnum, const char *message, va_list args) +{ +#if _LIBC + if (_IO_fwide (stderr, 0) > 0) + { +# define ALLOCA_LIMIT 2000 + size_t len = strlen (message) + 1; + const wchar_t *wmessage = L"out of memory"; + wchar_t *wbuf = (len < ALLOCA_LIMIT + ? alloca (len * sizeof *wbuf) + : len <= SIZE_MAX / sizeof *wbuf + ? malloc (len * sizeof *wbuf) + : NULL); + + if (wbuf) + { + size_t res; + mbstate_t st; + const char *tmp = message; + memset (&st, '\0', sizeof (st)); + res = mbsrtowcs (wbuf, &tmp, len, &st); + wmessage = res == (size_t) -1 ? L"???" : wbuf; + } + + __vfwprintf (stderr, wmessage, args); + if (! (len < ALLOCA_LIMIT)) + free (wbuf); + } + else +#endif + vfprintf (stderr, message, args); + va_end (args); + + ++error_message_count; + if (errnum) + print_errno_message (errnum); +#if _LIBC + if (_IO_fwide (stderr, 0) > 0) + putwc (L'\n', stderr); + else +#endif + putc ('\n', stderr); + fflush (stderr); + if (status) + exit (status); +} + + +/* Print the program name and error message MESSAGE, which is a printf-style + format string with optional args. + If ERRNUM is nonzero, print its corresponding system error message. + Exit with status STATUS if it is nonzero. */ +void +error (int status, int errnum, const char *message, ...) +{ + va_list args; + +#if defined _LIBC && defined __libc_ptf_call + /* We do not want this call to be cut short by a thread + cancellation. Therefore disable cancellation for now. */ + int state = PTHREAD_CANCEL_ENABLE; + __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state), + 0); +#endif + + fflush (stdout); +#ifdef _LIBC + _IO_flockfile (stderr); +#endif + if (error_print_progname) + (*error_print_progname) (); + else + { +#if _LIBC + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s: ", program_name); + else +#endif + fprintf (stderr, "%s: ", program_name); + } + + va_start (args, message); + error_tail (status, errnum, message, args); + +#ifdef _LIBC + _IO_funlockfile (stderr); +# ifdef __libc_ptf_call + __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0); +# endif +#endif +} + +/* Sometimes we want to have at most one error per line. This + variable controls whether this mode is selected or not. */ +int error_one_per_line; + +void +error_at_line (int status, int errnum, const char *file_name, + unsigned int line_number, const char *message, ...) +{ + va_list args; + + if (error_one_per_line) + { + static const char *old_file_name; + static unsigned int old_line_number; + + if (old_line_number == line_number + && (file_name == old_file_name + || strcmp (old_file_name, file_name) == 0)) + /* Simply return and print nothing. */ + return; + + old_file_name = file_name; + old_line_number = line_number; + } + +#if defined _LIBC && defined __libc_ptf_call + /* We do not want this call to be cut short by a thread + cancellation. Therefore disable cancellation for now. */ + int state = PTHREAD_CANCEL_ENABLE; + __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state), + 0); +#endif + + fflush (stdout); +#ifdef _LIBC + _IO_flockfile (stderr); +#endif + if (error_print_progname) + (*error_print_progname) (); + else + { +#if _LIBC + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s: ", program_name); + else +#endif + fprintf (stderr, "%s:", program_name); + } + + if (file_name != NULL) + { +#if _LIBC + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s:%d: ", file_name, line_number); + else +#endif + fprintf (stderr, "%s:%d: ", file_name, line_number); + } + + va_start (args, message); + error_tail (status, errnum, message, args); + +#ifdef _LIBC + _IO_funlockfile (stderr); +# ifdef __libc_ptf_call + __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0); +# endif +#endif +} + +#ifdef _LIBC +/* Make the weak alias. */ +# undef error +# undef error_at_line +weak_alias (__error, error) +weak_alias (__error_at_line, error_at_line) +#endif diff --git a/contrib/diffutils-2.8/lib/error.h b/contrib/diffutils-2.8/lib/error.h new file mode 100644 index 0000000000..8ed63595f2 --- /dev/null +++ b/contrib/diffutils-2.8/lib/error.h @@ -0,0 +1,66 @@ +/* Declaration for error-reporting function + Copyright (C) 1995, 1996, 1997, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _ERROR_H +#define _ERROR_H 1 + +#ifndef __attribute__ +/* This feature is available in gcc versions 2.5 and later. */ +# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) +# define __attribute__(Spec) /* empty */ +# endif +/* The __-protected variants of `format' and `printf' attributes + are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */ +# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) +# define __format__ format +# define __printf__ printf +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Print a message with `fprintf (stderr, FORMAT, ...)'; + if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM). + If STATUS is nonzero, terminate the program with `exit (STATUS)'. */ + +extern void error (int __status, int __errnum, const char *__format, ...) + __attribute__ ((__format__ (__printf__, 3, 4))); + +extern void error_at_line (int __status, int __errnum, const char *__fname, + unsigned int __lineno, const char *__format, ...) + __attribute__ ((__format__ (__printf__, 5, 6))); + +/* If NULL, error will flush stdout, then print on stderr the program + name, a colon and a space. Otherwise, error will call this + function without parameters instead. */ +extern void (*error_print_progname) (void); + +/* This variable is incremented each time `error' is called. */ +extern unsigned int error_message_count; + +/* Sometimes we want to have at most one error per line. This + variable controls whether this mode is selected or not. */ +extern int error_one_per_line; + +#ifdef __cplusplus +} +#endif + +#endif /* error.h */ diff --git a/contrib/diffutils-2.8/lib/exclude.c b/contrib/diffutils-2.8/lib/exclude.c new file mode 100644 index 0000000000..55f1a39185 --- /dev/null +++ b/contrib/diffutils-2.8/lib/exclude.c @@ -0,0 +1,263 @@ +/* exclude.c -- exclude file names + + Copyright (C) 1992, 1993, 1994, 1997, 1999, 2000, 2001, 2002, 2003 Free + Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Paul Eggert */ + +#if HAVE_CONFIG_H +# include +#endif + +#include + +#include +#include +#ifndef errno +extern int errno; +#endif +#include +#include +#include +#include + +#include "exclude.h" +#include "fnmatch.h" +#include "unlocked-io.h" +#include "xalloc.h" + +#if STDC_HEADERS || (! defined isascii && ! HAVE_ISASCII) +# define IN_CTYPE_DOMAIN(c) true +#else +# define IN_CTYPE_DOMAIN(c) isascii (c) +#endif + +static inline bool +is_space (unsigned char c) +{ + return IN_CTYPE_DOMAIN (c) && isspace (c); +} + +/* Verify a requirement at compile-time (unlike assert, which is runtime). */ +#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; } + +/* Non-GNU systems lack these options, so we don't need to check them. */ +#ifndef FNM_CASEFOLD +# define FNM_CASEFOLD 0 +#endif +#ifndef FNM_LEADING_DIR +# define FNM_LEADING_DIR 0 +#endif + +verify (EXCLUDE_macros_do_not_collide_with_FNM_macros, + (((EXCLUDE_ANCHORED | EXCLUDE_INCLUDE | EXCLUDE_WILDCARDS) + & (FNM_PATHNAME | FNM_NOESCAPE | FNM_PERIOD | FNM_LEADING_DIR + | FNM_CASEFOLD)) + == 0)); + +/* An exclude pattern-options pair. The options are fnmatch options + ORed with EXCLUDE_* options. */ + +struct patopts + { + char const *pattern; + int options; + }; + +/* An exclude list, of pattern-options pairs. */ + +struct exclude + { + struct patopts *exclude; + size_t exclude_alloc; + size_t exclude_count; + }; + +/* Return a newly allocated and empty exclude list. */ + +struct exclude * +new_exclude (void) +{ + return xzalloc (sizeof *new_exclude ()); +} + +/* Free the storage associated with an exclude list. */ + +void +free_exclude (struct exclude *ex) +{ + free (ex->exclude); + free (ex); +} + +/* Return zero if PATTERN matches F, obeying OPTIONS, except that + (unlike fnmatch) wildcards are disabled in PATTERN. */ + +static int +fnmatch_no_wildcards (char const *pattern, char const *f, int options) +{ + if (! (options & FNM_LEADING_DIR)) + return ((options & FNM_CASEFOLD) + ? strcasecmp (pattern, f) + : strcmp (pattern, f)); + else + { + size_t patlen = strlen (pattern); + int r = ((options & FNM_CASEFOLD) + ? strncasecmp (pattern, f, patlen) + : strncmp (pattern, f, patlen)); + if (! r) + { + r = f[patlen]; + if (r == '/') + r = 0; + } + return r; + } +} + +/* Return true if EX excludes F. */ + +bool +excluded_filename (struct exclude const *ex, char const *f) +{ + size_t exclude_count = ex->exclude_count; + + /* If no options are given, the default is to include. */ + if (exclude_count == 0) + return false; + else + { + struct patopts const *exclude = ex->exclude; + size_t i; + + /* Otherwise, the default is the opposite of the first option. */ + bool excluded = !! (exclude[0].options & EXCLUDE_INCLUDE); + + /* Scan through the options, seeing whether they change F from + excluded to included or vice versa. */ + for (i = 0; i < exclude_count; i++) + { + char const *pattern = exclude[i].pattern; + int options = exclude[i].options; + if (excluded == !! (options & EXCLUDE_INCLUDE)) + { + int (*matcher) (char const *, char const *, int) = + (options & EXCLUDE_WILDCARDS + ? fnmatch + : fnmatch_no_wildcards); + bool matched = ((*matcher) (pattern, f, options) == 0); + char const *p; + + if (! (options & EXCLUDE_ANCHORED)) + for (p = f; *p && ! matched; p++) + if (*p == '/' && p[1] != '/') + matched = ((*matcher) (pattern, p + 1, options) == 0); + + excluded ^= matched; + } + } + + return excluded; + } +} + +/* Append to EX the exclusion PATTERN with OPTIONS. */ + +void +add_exclude (struct exclude *ex, char const *pattern, int options) +{ + struct patopts *patopts; + + if (ex->exclude_count == ex->exclude_alloc) + ex->exclude = x2nrealloc (ex->exclude, &ex->exclude_alloc, + sizeof *ex->exclude); + + patopts = &ex->exclude[ex->exclude_count++]; + patopts->pattern = pattern; + patopts->options = options; +} + +/* Use ADD_FUNC to append to EX the patterns in FILENAME, each with + OPTIONS. LINE_END terminates each pattern in the file. If + LINE_END is a space character, ignore trailing spaces and empty + lines in FILE. Return -1 on failure, 0 on success. */ + +int +add_exclude_file (void (*add_func) (struct exclude *, char const *, int), + struct exclude *ex, char const *filename, int options, + char line_end) +{ + bool use_stdin = filename[0] == '-' && !filename[1]; + FILE *in; + char *buf = NULL; + char *p; + char const *pattern; + char const *lim; + size_t buf_alloc = 0; + size_t buf_count = 0; + int c; + int e = 0; + + if (use_stdin) + in = stdin; + else if (! (in = fopen (filename, "r"))) + return -1; + + while ((c = getc (in)) != EOF) + { + if (buf_count == buf_alloc) + buf = x2realloc (buf, &buf_alloc); + buf[buf_count++] = c; + } + + if (ferror (in)) + e = errno; + + if (!use_stdin && fclose (in) != 0) + e = errno; + + buf = xrealloc (buf, buf_count + 1); + buf[buf_count] = line_end; + lim = buf + buf_count + ! (buf_count == 0 || buf[buf_count - 1] == line_end); + pattern = buf; + + for (p = buf; p < lim; p++) + if (*p == line_end) + { + char *pattern_end = p; + + if (is_space (line_end)) + { + for (; ; pattern_end--) + if (pattern_end == pattern) + goto next_pattern; + else if (! is_space (pattern_end[-1])) + break; + } + + *pattern_end = '\0'; + (*add_func) (ex, pattern, options); + + next_pattern: + pattern = p + 1; + } + + errno = e; + return e ? -1 : 0; +} diff --git a/contrib/diffutils-2.8/lib/exclude.h b/contrib/diffutils-2.8/lib/exclude.h new file mode 100644 index 0000000000..a7e2971102 --- /dev/null +++ b/contrib/diffutils-2.8/lib/exclude.h @@ -0,0 +1,43 @@ +/* exclude.h -- declarations for excluding file names + + Copyright (C) 1992, 1993, 1994, 1997, 1999, 2001, 2002, 2003 Free + Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Paul Eggert */ + +/* Exclude options, which can be ORed with fnmatch options. */ + +/* Patterns must match the start of file names, instead of matching + anywhere after a '/'. */ +#define EXCLUDE_ANCHORED (1 << 30) + +/* Include instead of exclude. */ +#define EXCLUDE_INCLUDE (1 << 29) + +/* '?', '*', '[', and '\\' are special in patterns. Without this + option, these characters are ordinary and fnmatch is not used. */ +#define EXCLUDE_WILDCARDS (1 << 28) + +struct exclude; + +struct exclude *new_exclude (void); +void free_exclude (struct exclude *); +void add_exclude (struct exclude *, char const *, int); +int add_exclude_file (void (*) (struct exclude *, char const *, int), + struct exclude *, char const *, int, char); +bool excluded_filename (struct exclude const *, char const *); diff --git a/contrib/diffutils-2.8/lib/exit.h b/contrib/diffutils-2.8/lib/exit.h new file mode 100644 index 0000000000..4e8d465165 --- /dev/null +++ b/contrib/diffutils-2.8/lib/exit.h @@ -0,0 +1,32 @@ +/* exit() function. + Copyright (C) 1995, 2001 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _EXIT_H +#define _EXIT_H + +/* Get exit() declaration. */ +#include + +/* Some systems do not define EXIT_*, even with STDC_HEADERS. */ +#ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +#endif +#ifndef EXIT_FAILURE +# define EXIT_FAILURE 1 +#endif + +#endif /* _EXIT_H */ diff --git a/contrib/diffutils-2.8/lib/exitfail.c b/contrib/diffutils-2.8/lib/exitfail.c new file mode 100644 index 0000000000..2ae5f69555 --- /dev/null +++ b/contrib/diffutils-2.8/lib/exitfail.c @@ -0,0 +1,27 @@ +/* Failure exit status + + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#if HAVE_CONFIG_H +# include +#endif + +#include "exitfail.h" +#include "exit.h" + +int volatile exit_failure = EXIT_FAILURE; diff --git a/contrib/diffutils-2.8/lib/exitfail.h b/contrib/diffutils-2.8/lib/exitfail.h new file mode 100644 index 0000000000..cf5ab71958 --- /dev/null +++ b/contrib/diffutils-2.8/lib/exitfail.h @@ -0,0 +1,20 @@ +/* Failure exit status + + Copyright (C) 2002 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +extern int volatile exit_failure; diff --git a/contrib/diffutils-2.8/lib/file-type.c b/contrib/diffutils-2.8/lib/file-type.c new file mode 100644 index 0000000000..3c58c7fb06 --- /dev/null +++ b/contrib/diffutils-2.8/lib/file-type.c @@ -0,0 +1,75 @@ +/* Return a string describing the type of a file. + + Copyright (C) 1993, 1994, 2001, 2002, 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Paul Eggert. */ + +#if HAVE_CONFIG_H +# include +#endif + +#include +#include +#include "file-type.h" + +#include +#define _(text) gettext (text) + +char const * +file_type (struct stat const *st) +{ + /* See POSIX 1003.1-2001 XCU Table 4-8 lines 17093-17107 for some of + these formats. + + To keep diagnostics grammatical in English, the returned string + must start with a consonant. */ + + if (S_ISREG (st->st_mode)) + return st->st_size == 0 ? _("regular empty file") : _("regular file"); + + if (S_ISDIR (st->st_mode)) + return _("directory"); + + if (S_ISBLK (st->st_mode)) + return _("block special file"); + + if (S_ISCHR (st->st_mode)) + return _("character special file"); + + if (S_ISFIFO (st->st_mode)) + return _("fifo"); + + if (S_ISLNK (st->st_mode)) + return _("symbolic link"); + + if (S_ISSOCK (st->st_mode)) + return _("socket"); + + if (S_TYPEISMQ (st)) + return _("message queue"); + + if (S_TYPEISSEM (st)) + return _("semaphore"); + + if (S_TYPEISSHM (st)) + return _("shared memory object"); + + if (S_TYPEISTMO (st)) + return _("typed memory object"); + + return _("weird file"); +} diff --git a/contrib/diffutils-2.8/lib/file-type.h b/contrib/diffutils-2.8/lib/file-type.h new file mode 100644 index 0000000000..502f091635 --- /dev/null +++ b/contrib/diffutils-2.8/lib/file-type.h @@ -0,0 +1,166 @@ +/* Return a string describing the type of a file. + + Copyright (C) 1993, 1994, 2001, 2002, 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Paul Eggert and Jim Meyering. */ + +#ifndef FILE_TYPE_H +# define FILE_TYPE_H 1 + +# if ! defined S_ISREG && ! defined S_IFREG +you must include before including this file +# endif + +char const *file_type (struct stat const *); + +# ifndef S_IFMT +# define S_IFMT 0170000 +# endif + +# if STAT_MACROS_BROKEN +# undef S_ISBLK +# undef S_ISCHR +# undef S_ISDIR +# undef S_ISDOOR +# undef S_ISFIFO +# undef S_ISLNK +# undef S_ISNAM +# undef S_ISMPB +# undef S_ISMPC +# undef S_ISNWK +# undef S_ISREG +# undef S_ISSOCK +# endif + + +# ifndef S_ISBLK +# ifdef S_IFBLK +# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) +# else +# define S_ISBLK(m) 0 +# endif +# endif + +# ifndef S_ISCHR +# ifdef S_IFCHR +# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) +# else +# define S_ISCHR(m) 0 +# endif +# endif + +# ifndef S_ISDIR +# ifdef S_IFDIR +# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +# else +# define S_ISDIR(m) 0 +# endif +# endif + +# ifndef S_ISDOOR /* Solaris 2.5 and up */ +# ifdef S_IFDOOR +# define S_ISDOOR(m) (((m) & S_IFMT) == S_IFDOOR) +# else +# define S_ISDOOR(m) 0 +# endif +# endif + +# ifndef S_ISFIFO +# ifdef S_IFIFO +# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) +# else +# define S_ISFIFO(m) 0 +# endif +# endif + +# ifndef S_ISLNK +# ifdef S_IFLNK +# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +# else +# define S_ISLNK(m) 0 +# endif +# endif + +# ifndef S_ISMPB /* V7 */ +# ifdef S_IFMPB +# define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB) +# define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC) +# else +# define S_ISMPB(m) 0 +# define S_ISMPC(m) 0 +# endif +# endif + +# ifndef S_ISNAM /* Xenix */ +# ifdef S_IFNAM +# define S_ISNAM(m) (((m) & S_IFMT) == S_IFNAM) +# else +# define S_ISNAM(m) 0 +# endif +# endif + +# ifndef S_ISNWK /* HP/UX */ +# ifdef S_IFNWK +# define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK) +# else +# define S_ISNWK(m) 0 +# endif +# endif + +# ifndef S_ISREG +# ifdef S_IFREG +# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +# else +# define S_ISREG(m) 0 +# endif +# endif + +# ifndef S_ISSOCK +# ifdef S_IFSOCK +# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) +# else +# define S_ISSOCK(m) 0 +# endif +# endif + + +# ifndef S_TYPEISMQ +# define S_TYPEISMQ(p) 0 +# endif + +# ifndef S_TYPEISTMO +# define S_TYPEISTMO(p) 0 +# endif + + +# ifndef S_TYPEISSEM +# ifdef S_INSEM +# define S_TYPEISSEM(p) (S_ISNAM ((p)->st_mode) && (p)->st_rdev == S_INSEM) +# else +# define S_TYPEISSEM(p) 0 +# endif +# endif + +# ifndef S_TYPEISSHM +# ifdef S_INSHD +# define S_TYPEISSHM(p) (S_ISNAM ((p)->st_mode) && (p)->st_rdev == S_INSHD) +# else +# define S_TYPEISSHM(p) 0 +# endif +# endif + +#endif /* FILE_TYPE_H */ diff --git a/contrib/diffutils-2.8/lib/gettext.h b/contrib/diffutils-2.8/lib/gettext.h new file mode 100644 index 0000000000..835732e01f --- /dev/null +++ b/contrib/diffutils-2.8/lib/gettext.h @@ -0,0 +1,68 @@ +/* Convenience header for conditional use of GNU . + Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _LIBGETTEXT_H +#define _LIBGETTEXT_H 1 + +/* NLS can be disabled through the configure --disable-nls option. */ +#if ENABLE_NLS + +/* Get declarations of GNU message catalog functions. */ +# include + +#else + +/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which + chokes if dcgettext is defined as a macro. So include it now, to make + later inclusions of a NOP. We don't include + as well because people using "gettext.h" will not include , + and also including would fail on SunOS 4, whereas + is OK. */ +#if defined(__sun) +# include +#endif + +/* Disabled NLS. + The casts to 'const char *' serve the purpose of producing warnings + for invalid uses of the value returned from these functions. + On pre-ANSI systems without 'const', the config.h file is supposed to + contain "#define const". */ +# define gettext(Msgid) ((const char *) (Msgid)) +# define dgettext(Domainname, Msgid) ((const char *) (Msgid)) +# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid)) +# define ngettext(Msgid1, Msgid2, N) \ + ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) +# define dngettext(Domainname, Msgid1, Msgid2, N) \ + ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) +# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ + ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) +# define textdomain(Domainname) ((const char *) (Domainname)) +# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname)) +# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset)) + +#endif + +/* A pseudo function call that serves as a marker for the automated + extraction of messages, but does not call gettext(). The run-time + translation is done at a different place in the code. + The argument, String, should be a literal string. Concatenated strings + and other string expressions won't work. + The macro's expansion is not parenthesized, so that it is suitable as + initializer for static 'char[]' or 'const char[]' variables. */ +#define gettext_noop(String) String + +#endif /* _LIBGETTEXT_H */ diff --git a/contrib/diffutils-2.8/lib/hard-locale.c b/contrib/diffutils-2.8/lib/hard-locale.c new file mode 100644 index 0000000000..8c0ee8c777 --- /dev/null +++ b/contrib/diffutils-2.8/lib/hard-locale.c @@ -0,0 +1,74 @@ +/* hard-locale.c -- Determine whether a locale is hard. + + Copyright (C) 1997, 1998, 1999, 2002, 2003 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#if HAVE_CONFIG_H +# include +#endif + +#include "hard-locale.h" + +#if HAVE_LOCALE_H +# include +#endif + +#include +#include + +/* Return nonzero if the current CATEGORY locale is hard, i.e. if you + can't get away with assuming traditional C or POSIX behavior. */ +int +hard_locale (int category) +{ +#if ! HAVE_SETLOCALE + return 0; +#else + + int hard = 1; + char const *p = setlocale (category, 0); + + if (p) + { +# if defined __GLIBC__ && 2 <= __GLIBC__ + if (strcmp (p, "C") == 0 || strcmp (p, "POSIX") == 0) + hard = 0; +# else + char *locale = malloc (strlen (p) + 1); + if (locale) + { + strcpy (locale, p); + + /* Temporarily set the locale to the "C" and "POSIX" locales + to find their names, so that we can determine whether one + or the other is the caller's locale. */ + if (((p = setlocale (category, "C")) + && strcmp (p, locale) == 0) + || ((p = setlocale (category, "POSIX")) + && strcmp (p, locale) == 0)) + hard = 0; + + /* Restore the caller's locale. */ + setlocale (category, locale); + free (locale); + } +# endif + } + + return hard; + +#endif +} diff --git a/contrib/diffutils-2.8/lib/hard-locale.h b/contrib/diffutils-2.8/lib/hard-locale.h new file mode 100644 index 0000000000..ddc15d019d --- /dev/null +++ b/contrib/diffutils-2.8/lib/hard-locale.h @@ -0,0 +1,24 @@ +/* Determine whether a locale is hard. + + Copyright (C) 1999, 2003 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef HARD_LOCALE_H_ +# define HARD_LOCALE_H_ 1 + +int hard_locale (int); + +#endif /* HARD_LOCALE_H_ */ diff --git a/contrib/diffutils-2.8/lib/inttostr.h b/contrib/diffutils-2.8/lib/inttostr.h new file mode 100644 index 0000000000..6f2416b53f --- /dev/null +++ b/contrib/diffutils-2.8/lib/inttostr.h @@ -0,0 +1,47 @@ +/* inttostr.h -- convert integers to printable strings + + Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Paul Eggert */ + +#if HAVE_CONFIG_H +# include +#endif + +#if HAVE_INTTYPES_H +# include +#endif +#if HAVE_STDINT_H +# include +#endif + +#include + +#if HAVE_SYS_TYPES_H +# include +#endif + +/* Upper bound on the string length of an integer converted to string. + 302 / 1000 is ceil (log10 (2.0)). Subtract 1 for the sign bit; + add 1 for integer division truncation; add 1 more for a minus sign. */ +#define INT_STRLEN_BOUND(t) ((sizeof (t) * CHAR_BIT - 1) * 302 / 1000 + 2) + +#define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1) + +char *offtostr (off_t, char *); +char *imaxtostr (intmax_t, char *); +char *umaxtostr (uintmax_t, char *); diff --git a/contrib/diffutils-2.8/lib/posixver.c b/contrib/diffutils-2.8/lib/posixver.c new file mode 100644 index 0000000000..754d7ac55a --- /dev/null +++ b/contrib/diffutils-2.8/lib/posixver.c @@ -0,0 +1,59 @@ +/* Which POSIX version to conform to, for utilities. + + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Paul Eggert. */ + +#if HAVE_CONFIG_H +# include +#endif + +#include "posixver.h" + +#include +#include + +#if HAVE_UNISTD_H +# include +#endif +#ifndef _POSIX2_VERSION +# define _POSIX2_VERSION 0 +#endif + +#ifndef DEFAULT_POSIX2_VERSION +# define DEFAULT_POSIX2_VERSION _POSIX2_VERSION +#endif + +/* The POSIX version that utilities should conform to. The default is + specified by the system. */ + +int +posix2_version (void) +{ + long int v = DEFAULT_POSIX2_VERSION; + char const *s = getenv ("_POSIX2_VERSION"); + + if (s && *s) + { + char *e; + long int i = strtol (s, &e, 10); + if (! *e) + v = i; + } + + return v < INT_MIN ? INT_MIN : v < INT_MAX ? v : INT_MAX; +} diff --git a/contrib/diffutils-2.8/lib/posixver.h b/contrib/diffutils-2.8/lib/posixver.h new file mode 100644 index 0000000000..b64f6a2ea1 --- /dev/null +++ b/contrib/diffutils-2.8/lib/posixver.h @@ -0,0 +1 @@ +int posix2_version (void); diff --git a/contrib/diffutils-2.8/lib/prepargs.h b/contrib/diffutils-2.8/lib/prepargs.h new file mode 100644 index 0000000000..ce93ea870c --- /dev/null +++ b/contrib/diffutils-2.8/lib/prepargs.h @@ -0,0 +1,3 @@ +/* Parse arguments from a string and prepend them to an argv. */ + +void prepend_default_options (char const *, int *, char ***); diff --git a/contrib/diffutils-2.8/lib/quotesys.c b/contrib/diffutils-2.8/lib/quotesys.c new file mode 100644 index 0000000000..528f382272 --- /dev/null +++ b/contrib/diffutils-2.8/lib/quotesys.c @@ -0,0 +1,125 @@ +/* Shell command argument quoting. + Copyright (C) 1994, 1995, 1997 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Paul Eggert */ + +#if HAVE_CONFIG_H +# include +#endif + +#include +#include + +/* Place into QUOTED a quoted version of ARG suitable for `system'. + Return the length of the resulting string (which is not null-terminated). + If QUOTED is null, return the length without any side effects. */ + +size_t +quote_system_arg (quoted, arg) + char *quoted; + char const *arg; +{ + char const *a; + size_t len = 0; + + /* Scan ARG, copying it to QUOTED if QUOTED is not null, + looking for shell metacharacters. */ + + for (a = arg; ; a++) + { + char c = *a; + switch (c) + { + case 0: + /* ARG has no shell metacharacters. */ + return len; + + case '=': + if (*arg == '-') + break; + /* Fall through. */ + case '\t': case '\n': case ' ': + case '!': case '"': case '#': case '$': case '%': case '&': case '\'': + case '(': case ')': case '*': case ';': + case '<': case '>': case '?': case '[': case '\\': + case '^': case '`': case '|': case '~': + { + /* ARG has a shell metacharacter. + Start over, quoting it this time. */ + + len = 0; + c = *arg++; + + /* If ARG is an option, quote just its argument. + This is not necessary, but it looks nicer. */ + if (c == '-' && arg < a) + { + c = *arg++; + + if (quoted) + { + quoted[len] = '-'; + quoted[len + 1] = c; + } + len += 2; + + if (c == '-') + while (arg < a) + { + c = *arg++; + if (quoted) + quoted[len] = c; + len++; + if (c == '=') + break; + } + c = *arg++; + } + + if (quoted) + quoted[len] = '\''; + len++; + + for (; c; c = *arg++) + { + if (c == '\'') + { + if (quoted) + { + quoted[len] = '\''; + quoted[len + 1] = '\\'; + quoted[len + 2] = '\''; + } + len += 3; + } + if (quoted) + quoted[len] = c; + len++; + } + + if (quoted) + quoted[len] = '\''; + return len + 1; + } + } + + if (quoted) + quoted[len] = c; + len++; + } +} diff --git a/contrib/diffutils-2.8/lib/quotesys.h b/contrib/diffutils-2.8/lib/quotesys.h new file mode 100644 index 0000000000..0d0d825709 --- /dev/null +++ b/contrib/diffutils-2.8/lib/quotesys.h @@ -0,0 +1,9 @@ +/* quotesys.h -- declarations for quoting system arguments */ + +#if defined __STDC__ || __GNUC__ +# define __QUOTESYS_P(args) args +#else +# define __QUOTESYS_P(args) () +#endif + +size_t quote_system_arg __QUOTESYS_P ((char *, char const *)); diff --git a/contrib/diffutils-2.8/lib/setmode.h b/contrib/diffutils-2.8/lib/setmode.h new file mode 100644 index 0000000000..8381d124e9 --- /dev/null +++ b/contrib/diffutils-2.8/lib/setmode.h @@ -0,0 +1,27 @@ +/* Set a file descriptor's mode to binary or to text. + + Copyright (C) 2001, 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Paul Eggert */ + +#ifndef set_binary_mode +bool set_binary_mode (int, bool); +# if ! HAVE_SETMODE_DOS +# define set_binary_mode(fd, mode) true +# endif +#endif diff --git a/contrib/diffutils-2.8/lib/strcase.h b/contrib/diffutils-2.8/lib/strcase.h new file mode 100644 index 0000000000..f17e64832f --- /dev/null +++ b/contrib/diffutils-2.8/lib/strcase.h @@ -0,0 +1,35 @@ +/* Case-insensitive string comparison functions. + Copyright (C) 1995-1996, 2001, 2003 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _STRCASE_H +#define _STRCASE_H + +#include + +/* Compare strings S1 and S2, ignoring case, returning less than, equal to or + greater than zero if S1 is lexicographically less than, equal to or greater + than S2. + Note: This function does not work correctly in multibyte locales. */ +extern int strcasecmp (const char *s1, const char *s2); + +/* Compare no more than N characters of strings S1 and S2, ignoring case, + returning less than, equal to or greater than zero if S1 is + lexicographically less than, equal to or greater than S2. + Note: This function can not work correctly in multibyte locales. */ +extern int strncasecmp (const char *s1, const char *s2, size_t n); + +#endif /* _STRCASE_H */ diff --git a/contrib/diffutils-2.8/lib/strftime.c b/contrib/diffutils-2.8/lib/strftime.c new file mode 100644 index 0000000000..dccbaf7a18 --- /dev/null +++ b/contrib/diffutils-2.8/lib/strftime.c @@ -0,0 +1,1330 @@ +/* Copyright (C) 1991-1999, 2000, 2001, 2003 Free Software Foundation, Inc. + + NOTE: The canonical source of this file is maintained with the GNU C Library. + Bugs can be reported to bug-glibc@prep.ai.mit.edu. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef _LIBC +# define HAVE_MBLEN 1 +# define HAVE_MBRLEN 1 +# define HAVE_STRUCT_ERA_ENTRY 1 +# define HAVE_TM_GMTOFF 1 +# define HAVE_TM_ZONE 1 +# define HAVE_TZNAME 1 +# define HAVE_TZSET 1 +# define MULTIBYTE_IS_FORMAT_SAFE 1 +# include "../locale/localeinfo.h" +#endif + +#include +#include /* Some systems define `time_t' here. */ + +#ifdef TIME_WITH_SYS_TIME +# include +# include +#else +# ifdef HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif +#if HAVE_TZNAME +extern char *tzname[]; +#endif + +/* Do multibyte processing if multibytes are supported, unless + multibyte sequences are safe in formats. Multibyte sequences are + safe if they cannot contain byte sequences that look like format + conversion specifications. The GNU C Library uses UTF8 multibyte + encoding, which is safe for formats, but strftime.c can be used + with other C libraries that use unsafe encodings. */ +#define DO_MULTIBYTE (HAVE_MBLEN && ! MULTIBYTE_IS_FORMAT_SAFE) + +#if DO_MULTIBYTE +# if HAVE_MBRLEN +# include +# else + /* Simulate mbrlen with mblen as best we can. */ +# define mbstate_t int +# define mbrlen(s, n, ps) mblen (s, n) +# define mbsinit(ps) (*(ps) == 0) +# endif + static const mbstate_t mbstate_zero; +#endif + +#include +#include +#include +#include + +#ifdef COMPILE_WIDE +# include +# define CHAR_T wchar_t +# define UCHAR_T unsigned int +# define L_(Str) L##Str +# define NLW(Sym) _NL_W##Sym + +# define MEMCPY(d, s, n) __wmemcpy (d, s, n) +# define STRLEN(s) __wcslen (s) + +#else +# define CHAR_T char +# define UCHAR_T unsigned char +# define L_(Str) Str +# define NLW(Sym) Sym + +# define MEMCPY(d, s, n) memcpy (d, s, n) +# define STRLEN(s) strlen (s) + +# ifdef _LIBC +# define MEMPCPY(d, s, n) __mempcpy (d, s, n) +# else +# ifndef HAVE_MEMPCPY +# define MEMPCPY(d, s, n) ((void *) ((char *) memcpy (d, s, n) + (n))) +# endif +# endif +#endif + +#define TYPE_SIGNED(t) ((t) -1 < 0) + +/* Bound on length of the string representing an integer value of type t. + Subtract one for the sign bit if t is signed; + 302 / 1000 is log10 (2) rounded up; + add one for integer division truncation; + add one more for a minus sign if t is signed. */ +#define INT_STRLEN_BOUND(t) \ + ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 + 1 + TYPE_SIGNED (t)) + +#define TM_YEAR_BASE 1900 + +#ifndef __isleap +/* Nonzero if YEAR is a leap year (every 4 years, + except every 100th isn't, and every 400th is). */ +# define __isleap(year) \ + ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) +#endif + + +#ifdef _LIBC +# define tzname __tzname +# define tzset __tzset +#endif + +#if !HAVE_TM_GMTOFF +/* Portable standalone applications should supply a "time_r.h" that + declares a POSIX-compliant localtime_r, for the benefit of older + implementations that lack localtime_r or have a nonstandard one. + See the gnulib time_r module for one way to implement this. */ +# include "time_r.h" +# undef __gmtime_r +# undef __localtime_r +# define __gmtime_r gmtime_r +# define __localtime_r localtime_r +#endif + + +#ifdef COMPILE_WIDE +# define memset_space(P, Len) (wmemset (P, L' ', Len), (P) += (Len)) +# define memset_zero(P, Len) (wmemset (P, L'0', Len), (P) += (Len)) +#else +# define memset_space(P, Len) (memset (P, ' ', Len), (P) += (Len)) +# define memset_zero(P, Len) (memset (P, '0', Len), (P) += (Len)) +#endif + +#define add(n, f) \ + do \ + { \ + int _n = (n); \ + int _delta = width - _n; \ + int _incr = _n + (_delta > 0 ? _delta : 0); \ + if ((size_t) _incr >= maxsize - i) \ + return 0; \ + if (p) \ + { \ + if (_delta > 0) \ + { \ + if (pad == L_('0')) \ + memset_zero (p, _delta); \ + else \ + memset_space (p, _delta); \ + } \ + f; \ + p += _n; \ + } \ + i += _incr; \ + } while (0) + +#define cpy(n, s) \ + add ((n), \ + if (to_lowcase) \ + memcpy_lowcase (p, (s), _n LOCALE_ARG); \ + else if (to_uppcase) \ + memcpy_uppcase (p, (s), _n LOCALE_ARG); \ + else \ + MEMCPY ((void *) p, (void const *) (s), _n)) + +#ifdef COMPILE_WIDE +# ifndef USE_IN_EXTENDED_LOCALE_MODEL +# undef __mbsrtowcs_l +# define __mbsrtowcs_l(d, s, l, st, loc) __mbsrtowcs (d, s, l, st) +# endif +# define widen(os, ws, l) \ + { \ + mbstate_t __st; \ + const char *__s = os; \ + memset (&__st, '\0', sizeof (__st)); \ + l = __mbsrtowcs_l (NULL, &__s, 0, &__st, loc); \ + ws = (wchar_t *) alloca ((l + 1) * sizeof (wchar_t)); \ + (void) __mbsrtowcs_l (ws, &__s, l, &__st, loc); \ + } +#endif + + +#if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL +/* We use this code also for the extended locale handling where the + function gets as an additional argument the locale which has to be + used. To access the values we have to redefine the _NL_CURRENT + macro. */ +# define strftime __strftime_l +# define wcsftime __wcsftime_l +# undef _NL_CURRENT +# define _NL_CURRENT(category, item) \ + (current->values[_NL_ITEM_INDEX (item)].string) +# define LOCALE_ARG , loc +# define LOCALE_PARAM_PROTO , __locale_t loc +# define HELPER_LOCALE_ARG , current +#else +# define LOCALE_PARAM_PROTO +# define LOCALE_ARG +# ifdef _LIBC +# define HELPER_LOCALE_ARG , _NL_CURRENT_DATA (LC_TIME) +# else +# define HELPER_LOCALE_ARG +# endif +#endif + +#ifdef COMPILE_WIDE +# ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define TOUPPER(Ch, L) __towupper_l (Ch, L) +# define TOLOWER(Ch, L) __towlower_l (Ch, L) +# else +# define TOUPPER(Ch, L) towupper (Ch) +# define TOLOWER(Ch, L) towlower (Ch) +# endif +#else +# ifdef _LIBC +# ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define TOUPPER(Ch, L) __toupper_l (Ch, L) +# define TOLOWER(Ch, L) __tolower_l (Ch, L) +# else +# define TOUPPER(Ch, L) toupper (Ch) +# define TOLOWER(Ch, L) tolower (Ch) +# endif +# else +# define TOUPPER(Ch, L) (islower (Ch) ? toupper (Ch) : (Ch)) +# define TOLOWER(Ch, L) (isupper (Ch) ? tolower (Ch) : (Ch)) +# endif +#endif +/* We don't use `isdigit' here since the locale dependent + interpretation is not what we want here. We only need to accept + the arabic digits in the ASCII range. One day there is perhaps a + more reliable way to accept other sets of digits. */ +#define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9) + +static CHAR_T * +memcpy_lowcase (CHAR_T *dest, const CHAR_T *src, + size_t len LOCALE_PARAM_PROTO) +{ + while (len-- > 0) + dest[len] = TOLOWER ((UCHAR_T) src[len], loc); + return dest; +} + +static CHAR_T * +memcpy_uppcase (CHAR_T *dest, const CHAR_T *src, + size_t len LOCALE_PARAM_PROTO) +{ + while (len-- > 0) + dest[len] = TOUPPER ((UCHAR_T) src[len], loc); + return dest; +} + + +#if ! HAVE_TM_GMTOFF +/* Yield the difference between *A and *B, + measured in seconds, ignoring leap seconds. */ +# define tm_diff ftime_tm_diff +static int +tm_diff (const struct tm *a, const struct tm *b) +{ + /* Compute intervening leap days correctly even if year is negative. + Take care to avoid int overflow in leap day calculations, + but it's OK to assume that A and B are close to each other. */ + int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3); + int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3); + int a100 = a4 / 25 - (a4 % 25 < 0); + int b100 = b4 / 25 - (b4 % 25 < 0); + int a400 = a100 >> 2; + int b400 = b100 >> 2; + int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400); + int years = a->tm_year - b->tm_year; + int days = (365 * years + intervening_leap_days + + (a->tm_yday - b->tm_yday)); + return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour)) + + (a->tm_min - b->tm_min)) + + (a->tm_sec - b->tm_sec)); +} +#endif /* ! HAVE_TM_GMTOFF */ + + + +/* The number of days from the first day of the first ISO week of this + year to the year day YDAY with week day WDAY. ISO weeks start on + Monday; the first ISO week has the year's first Thursday. YDAY may + be as small as YDAY_MINIMUM. */ +#define ISO_WEEK_START_WDAY 1 /* Monday */ +#define ISO_WEEK1_WDAY 4 /* Thursday */ +#define YDAY_MINIMUM (-366) +#ifdef __GNUC__ +__inline__ +#endif +static int +iso_week_days (int yday, int wday) +{ + /* Add enough to the first operand of % to make it nonnegative. */ + int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7; + return (yday + - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7 + + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY); +} + + +#if !(defined _NL_CURRENT || HAVE_STRFTIME) +static CHAR_T const weekday_name[][10] = + { + L_("Sunday"), L_("Monday"), L_("Tuesday"), L_("Wednesday"), + L_("Thursday"), L_("Friday"), L_("Saturday") + }; +static CHAR_T const month_name[][10] = + { + L_("January"), L_("February"), L_("March"), L_("April"), L_("May"), + L_("June"), L_("July"), L_("August"), L_("September"), L_("October"), + L_("November"), L_("December") + }; +#endif + + +/* When compiling this file, GNU applications can #define my_strftime + to a symbol (typically nstrftime) to get an extended strftime with + extra arguments UT and NS. Emacs is a special case for now, but + this Emacs-specific code can be removed once Emacs's config.h + defines my_strftime. */ +#if defined emacs && !defined my_strftime +# define my_strftime nstrftime +#endif + +#ifdef my_strftime +# define extra_args , ut, ns +# define extra_args_spec , int ut, int ns +#else +# ifdef COMPILE_WIDE +# define my_strftime wcsftime +# define nl_get_alt_digit _nl_get_walt_digit +# else +# define my_strftime strftime +# define nl_get_alt_digit _nl_get_alt_digit +# endif +# define extra_args +# define extra_args_spec +/* We don't have this information in general. */ +# define ut 0 +# define ns 0 +#endif + +#if ! defined _LIBC && ! HAVE_RUN_TZSET_TEST +/* Solaris 2.5.x and 2.6 tzset sometimes modify the storage returned + by localtime. On such systems, we must use the tzset and localtime + wrappers to work around the bug. */ +"you must run the autoconf test for a working tzset function" +#endif + + +/* Write information from TP into S according to the format + string FORMAT, writing no more that MAXSIZE characters + (including the terminating '\0') and returning number of + characters written. If S is NULL, nothing will be written + anywhere, so to determine how many characters would be + written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */ +size_t +my_strftime (CHAR_T *s, size_t maxsize, const CHAR_T *format, + const struct tm *tp extra_args_spec LOCALE_PARAM_PROTO) +{ +#if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL + struct locale_data *const current = loc->__locales[LC_TIME]; +#endif + + int hour12 = tp->tm_hour; +#ifdef _NL_CURRENT + /* We cannot make the following values variables since we must delay + the evaluation of these values until really needed since some + expressions might not be valid in every situation. The `struct tm' + might be generated by a strptime() call that initialized + only a few elements. Dereference the pointers only if the format + requires this. Then it is ok to fail if the pointers are invalid. */ +# define a_wkday \ + ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday)) +# define f_wkday \ + ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday)) +# define a_month \ + ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon)) +# define f_month \ + ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon)) +# define ampm \ + ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \ + ? NLW(PM_STR) : NLW(AM_STR))) + +# define aw_len STRLEN (a_wkday) +# define am_len STRLEN (a_month) +# define ap_len STRLEN (ampm) +#else +# if !HAVE_STRFTIME +# define f_wkday (weekday_name[tp->tm_wday]) +# define f_month (month_name[tp->tm_mon]) +# define a_wkday f_wkday +# define a_month f_month +# define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11)) + + size_t aw_len = 3; + size_t am_len = 3; + size_t ap_len = 2; +# endif +#endif + const char *zone; + size_t i = 0; + CHAR_T *p = s; + const CHAR_T *f; +#if DO_MULTIBYTE && !defined COMPILE_WIDE + const char *format_end = NULL; +#endif + + zone = NULL; +#if HAVE_TM_ZONE + /* The POSIX test suite assumes that setting + the environment variable TZ to a new value before calling strftime() + will influence the result (the %Z format) even if the information in + TP is computed with a totally different time zone. + This is bogus: though POSIX allows bad behavior like this, + POSIX does not require it. Do the right thing instead. */ + zone = (const char *) tp->tm_zone; +#endif +#if HAVE_TZNAME + if (ut) + { + if (! (zone && *zone)) + zone = "GMT"; + } + else + { + /* POSIX.1 requires that local time zone information be used as + though strftime called tzset. */ +# if HAVE_TZSET + tzset (); +# endif + } +#endif + + if (hour12 > 12) + hour12 -= 12; + else + if (hour12 == 0) + hour12 = 12; + + for (f = format; *f != '\0'; ++f) + { + int pad = 0; /* Padding for number ('-', '_', or 0). */ + int modifier; /* Field modifier ('E', 'O', or 0). */ + int digits; /* Max digits for numeric format. */ + int number_value; /* Numeric value to be printed. */ + int negative_number; /* 1 if the number is negative. */ + const CHAR_T *subfmt; + CHAR_T *bufp; + CHAR_T buf[1 + (sizeof (int) < sizeof (time_t) + ? INT_STRLEN_BOUND (time_t) + : INT_STRLEN_BOUND (int))]; + int width = -1; + int to_lowcase = 0; + int to_uppcase = 0; + int change_case = 0; + int format_char; + +#if DO_MULTIBYTE && !defined COMPILE_WIDE + switch (*f) + { + case L_('%'): + break; + + case L_('\b'): case L_('\t'): case L_('\n'): + case L_('\v'): case L_('\f'): case L_('\r'): + case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'): + case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'): + case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'): + case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'): + case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'): + case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'): + case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'): + case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'): + case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'): + case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'): + case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'): + case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'): + case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'): + case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'): + case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'): + case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'): + case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'): + case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'): + case L_('~'): + /* The C Standard requires these 98 characters (plus '%') to + be in the basic execution character set. None of these + characters can start a multibyte sequence, so they need + not be analyzed further. */ + add (1, *p = *f); + continue; + + default: + /* Copy this multibyte sequence until we reach its end, find + an error, or come back to the initial shift state. */ + { + mbstate_t mbstate = mbstate_zero; + size_t len = 0; + size_t fsize; + + if (! format_end) + format_end = f + strlen (f) + 1; + fsize = format_end - f; + + do + { + size_t bytes = mbrlen (f + len, fsize - len, &mbstate); + + if (bytes == 0) + break; + + if (bytes == (size_t) -2) + { + len += strlen (f + len); + break; + } + + if (bytes == (size_t) -1) + { + len++; + break; + } + + len += bytes; + } + while (! mbsinit (&mbstate)); + + cpy (len, f); + f += len - 1; + continue; + } + } + +#else /* ! DO_MULTIBYTE */ + + /* Either multibyte encodings are not supported, they are + safe for formats, so any non-'%' byte can be copied through, + or this is the wide character version. */ + if (*f != L_('%')) + { + add (1, *p = *f); + continue; + } + +#endif /* ! DO_MULTIBYTE */ + + /* Check for flags that can modify a format. */ + while (1) + { + switch (*++f) + { + /* This influences the number formats. */ + case L_('_'): + case L_('-'): + case L_('0'): + pad = *f; + continue; + + /* This changes textual output. */ + case L_('^'): + to_uppcase = 1; + continue; + case L_('#'): + change_case = 1; + continue; + + default: + break; + } + break; + } + + /* As a GNU extension we allow to specify the field width. */ + if (ISDIGIT (*f)) + { + width = 0; + do + { + if (width > INT_MAX / 10 + || (width == INT_MAX / 10 && *f - L_('0') > INT_MAX % 10)) + /* Avoid overflow. */ + width = INT_MAX; + else + { + width *= 10; + width += *f - L_('0'); + } + ++f; + } + while (ISDIGIT (*f)); + } + + /* Check for modifiers. */ + switch (*f) + { + case L_('E'): + case L_('O'): + modifier = *f++; + break; + + default: + modifier = 0; + break; + } + + /* Now do the specified format. */ + format_char = *f; + switch (format_char) + { +#define DO_NUMBER(d, v) \ + digits = d > width ? d : width; \ + number_value = v; goto do_number +#define DO_NUMBER_SPACEPAD(d, v) \ + digits = d > width ? d : width; \ + number_value = v; goto do_number_spacepad + + case L_('%'): + if (modifier != 0) + goto bad_format; + add (1, *p = *f); + break; + + case L_('a'): + if (modifier != 0) + goto bad_format; + if (change_case) + { + to_uppcase = 1; + to_lowcase = 0; + } +#if defined _NL_CURRENT || !HAVE_STRFTIME + cpy (aw_len, a_wkday); + break; +#else + goto underlying_strftime; +#endif + + case 'A': + if (modifier != 0) + goto bad_format; + if (change_case) + { + to_uppcase = 1; + to_lowcase = 0; + } +#if defined _NL_CURRENT || !HAVE_STRFTIME + cpy (STRLEN (f_wkday), f_wkday); + break; +#else + goto underlying_strftime; +#endif + + case L_('b'): + case L_('h'): + if (change_case) + { + to_uppcase = 1; + to_lowcase = 0; + } + if (modifier != 0) + goto bad_format; +#if defined _NL_CURRENT || !HAVE_STRFTIME + cpy (am_len, a_month); + break; +#else + goto underlying_strftime; +#endif + + case L_('B'): + if (modifier != 0) + goto bad_format; + if (change_case) + { + to_uppcase = 1; + to_lowcase = 0; + } +#if defined _NL_CURRENT || !HAVE_STRFTIME + cpy (STRLEN (f_month), f_month); + break; +#else + goto underlying_strftime; +#endif + + case L_('c'): + if (modifier == L_('O')) + goto bad_format; +#ifdef _NL_CURRENT + if (! (modifier == 'E' + && (*(subfmt = + (const CHAR_T *) _NL_CURRENT (LC_TIME, + NLW(ERA_D_T_FMT))) + != '\0'))) + subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT)); +#else +# if HAVE_STRFTIME + goto underlying_strftime; +# else + subfmt = L_("%a %b %e %H:%M:%S %Y"); +# endif +#endif + + subformat: + { + CHAR_T *old_start = p; + size_t len = my_strftime (NULL, (size_t) -1, subfmt, + tp extra_args LOCALE_ARG); + add (len, my_strftime (p, maxsize - i, subfmt, + tp extra_args LOCALE_ARG)); + + if (to_uppcase) + while (old_start < p) + { + *old_start = TOUPPER ((UCHAR_T) *old_start, loc); + ++old_start; + } + } + break; + +#if HAVE_STRFTIME && ! (defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY) + underlying_strftime: + { + /* The relevant information is available only via the + underlying strftime implementation, so use that. */ + char ufmt[4]; + char *u = ufmt; + char ubuf[1024]; /* enough for any single format in practice */ + size_t len; + /* Make sure we're calling the actual underlying strftime. + In some cases, config.h contains something like + "#define strftime rpl_strftime". */ +# ifdef strftime +# undef strftime + size_t strftime (); +# endif + + *u++ = '%'; + if (modifier != 0) + *u++ = modifier; + *u++ = format_char; + *u = '\0'; + len = strftime (ubuf, sizeof ubuf, ufmt, tp); + if (len == 0 && ubuf[0] != '\0') + return 0; + cpy (len, ubuf); + } + break; +#endif + + case L_('C'): + if (modifier == L_('O')) + goto bad_format; + if (modifier == L_('E')) + { +#if HAVE_STRUCT_ERA_ENTRY + struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG); + if (era) + { +# ifdef COMPILE_WIDE + size_t len = __wcslen (era->era_wname); + cpy (len, era->era_wname); +# else + size_t len = strlen (era->era_name); + cpy (len, era->era_name); +# endif + break; + } +#else +# if HAVE_STRFTIME + goto underlying_strftime; +# endif +#endif + } + + { + int year = tp->tm_year + TM_YEAR_BASE; + DO_NUMBER (1, year / 100 - (year % 100 < 0)); + } + + case L_('x'): + if (modifier == L_('O')) + goto bad_format; +#ifdef _NL_CURRENT + if (! (modifier == L_('E') + && (*(subfmt = + (const CHAR_T *)_NL_CURRENT (LC_TIME, NLW(ERA_D_FMT))) + != L_('\0')))) + subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT)); + goto subformat; +#else +# if HAVE_STRFTIME + goto underlying_strftime; +# else + /* Fall through. */ +# endif +#endif + case L_('D'): + if (modifier != 0) + goto bad_format; + subfmt = L_("%m/%d/%y"); + goto subformat; + + case L_('d'): + if (modifier == L_('E')) + goto bad_format; + + DO_NUMBER (2, tp->tm_mday); + + case L_('e'): + if (modifier == L_('E')) + goto bad_format; + + DO_NUMBER_SPACEPAD (2, tp->tm_mday); + + /* All numeric formats set DIGITS and NUMBER_VALUE and then + jump to one of these two labels. */ + + do_number_spacepad: + /* Force `_' flag unless overridden by `0' or `-' flag. */ + if (pad != L_('0') && pad != L_('-')) + pad = L_('_'); + + do_number: + /* Format the number according to the MODIFIER flag. */ + + if (modifier == L_('O') && 0 <= number_value) + { +#ifdef _NL_CURRENT + /* Get the locale specific alternate representation of + the number NUMBER_VALUE. If none exist NULL is returned. */ + const CHAR_T *cp = nl_get_alt_digit (number_value + HELPER_LOCALE_ARG); + + if (cp != NULL) + { + size_t digitlen = STRLEN (cp); + if (digitlen != 0) + { + cpy (digitlen, cp); + break; + } + } +#else +# if HAVE_STRFTIME + goto underlying_strftime; +# endif +#endif + } + { + unsigned int u = number_value; + + bufp = buf + sizeof (buf) / sizeof (buf[0]); + negative_number = number_value < 0; + + if (negative_number) + u = -u; + + do + *--bufp = u % 10 + L_('0'); + while ((u /= 10) != 0); + } + + do_number_sign_and_padding: + if (negative_number) + *--bufp = L_('-'); + + if (pad != L_('-')) + { + int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0])) + - bufp); + + if (padding > 0) + { + if (pad == L_('_')) + { + if ((size_t) padding >= maxsize - i) + return 0; + + if (p) + memset_space (p, padding); + i += padding; + width = width > padding ? width - padding : 0; + } + else + { + if ((size_t) digits >= maxsize - i) + return 0; + + if (negative_number) + { + ++bufp; + + if (p) + *p++ = L_('-'); + ++i; + } + + if (p) + memset_zero (p, padding); + i += padding; + width = 0; + } + } + } + + cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp); + break; + + case L_('F'): + if (modifier != 0) + goto bad_format; + subfmt = L_("%Y-%m-%d"); + goto subformat; + + case L_('H'): + if (modifier == L_('E')) + goto bad_format; + + DO_NUMBER (2, tp->tm_hour); + + case L_('I'): + if (modifier == L_('E')) + goto bad_format; + + DO_NUMBER (2, hour12); + + case L_('k'): /* GNU extension. */ + if (modifier == L_('E')) + goto bad_format; + + DO_NUMBER_SPACEPAD (2, tp->tm_hour); + + case L_('l'): /* GNU extension. */ + if (modifier == L_('E')) + goto bad_format; + + DO_NUMBER_SPACEPAD (2, hour12); + + case L_('j'): + if (modifier == L_('E')) + goto bad_format; + + DO_NUMBER (3, 1 + tp->tm_yday); + + case L_('M'): + if (modifier == L_('E')) + goto bad_format; + + DO_NUMBER (2, tp->tm_min); + + case L_('m'): + if (modifier == L_('E')) + goto bad_format; + + DO_NUMBER (2, tp->tm_mon + 1); + +#ifndef _LIBC + case L_('N'): /* GNU extension. */ + if (modifier == L_('E')) + goto bad_format; + + number_value = ns; + if (width != -1) + { + /* Take an explicit width less than 9 as a precision. */ + int j; + for (j = width; j < 9; j++) + number_value /= 10; + } + + DO_NUMBER (9, number_value); +#endif + + case L_('n'): + add (1, *p = L_('\n')); + break; + + case L_('P'): + to_lowcase = 1; +#if !defined _NL_CURRENT && HAVE_STRFTIME + format_char = L_('p'); +#endif + /* FALLTHROUGH */ + + case L_('p'): + if (change_case) + { + to_uppcase = 0; + to_lowcase = 1; + } +#if defined _NL_CURRENT || !HAVE_STRFTIME + cpy (ap_len, ampm); + break; +#else + goto underlying_strftime; +#endif + + case L_('R'): + subfmt = L_("%H:%M"); + goto subformat; + + case L_('r'): +#if !defined _NL_CURRENT && HAVE_STRFTIME + goto underlying_strftime; +#else +# ifdef _NL_CURRENT + if (*(subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, + NLW(T_FMT_AMPM))) + == L_('\0')) +# endif + subfmt = L_("%I:%M:%S %p"); + goto subformat; +#endif + + case L_('S'): + if (modifier == L_('E')) + goto bad_format; + + DO_NUMBER (2, tp->tm_sec); + + case L_('s'): /* GNU extension. */ + { + struct tm ltm; + time_t t; + + ltm = *tp; + t = mktime (<m); + + /* Generate string value for T using time_t arithmetic; + this works even if sizeof (long) < sizeof (time_t). */ + + bufp = buf + sizeof (buf) / sizeof (buf[0]); + negative_number = t < 0; + + do + { + int d = t % 10; + t /= 10; + + if (negative_number) + { + d = -d; + + /* Adjust if division truncates to minus infinity. */ + if (0 < -1 % 10 && d < 0) + { + t++; + d += 10; + } + } + + *--bufp = d + L_('0'); + } + while (t != 0); + + digits = 1; + goto do_number_sign_and_padding; + } + + case L_('X'): + if (modifier == L_('O')) + goto bad_format; +#ifdef _NL_CURRENT + if (! (modifier == L_('E') + && (*(subfmt = + (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_T_FMT))) + != L_('\0')))) + subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT)); + goto subformat; +#else +# if HAVE_STRFTIME + goto underlying_strftime; +# else + /* Fall through. */ +# endif +#endif + case L_('T'): + subfmt = L_("%H:%M:%S"); + goto subformat; + + case L_('t'): + add (1, *p = L_('\t')); + break; + + case L_('u'): + DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1); + + case L_('U'): + if (modifier == L_('E')) + goto bad_format; + + DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7); + + case L_('V'): + case L_('g'): + case L_('G'): + if (modifier == L_('E')) + goto bad_format; + { + int year = tp->tm_year + TM_YEAR_BASE; + int days = iso_week_days (tp->tm_yday, tp->tm_wday); + + if (days < 0) + { + /* This ISO week belongs to the previous year. */ + year--; + days = iso_week_days (tp->tm_yday + (365 + __isleap (year)), + tp->tm_wday); + } + else + { + int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)), + tp->tm_wday); + if (0 <= d) + { + /* This ISO week belongs to the next year. */ + year++; + days = d; + } + } + + switch (*f) + { + case L_('g'): + DO_NUMBER (2, (year % 100 + 100) % 100); + + case L_('G'): + DO_NUMBER (1, year); + + default: + DO_NUMBER (2, days / 7 + 1); + } + } + + case L_('W'): + if (modifier == L_('E')) + goto bad_format; + + DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7); + + case L_('w'): + if (modifier == L_('E')) + goto bad_format; + + DO_NUMBER (1, tp->tm_wday); + + case L_('Y'): + if (modifier == 'E') + { +#if HAVE_STRUCT_ERA_ENTRY + struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG); + if (era) + { +# ifdef COMPILE_WIDE + subfmt = era->era_wformat; +# else + subfmt = era->era_format; +# endif + goto subformat; + } +#else +# if HAVE_STRFTIME + goto underlying_strftime; +# endif +#endif + } + if (modifier == L_('O')) + goto bad_format; + else + DO_NUMBER (1, tp->tm_year + TM_YEAR_BASE); + + case L_('y'): + if (modifier == L_('E')) + { +#if HAVE_STRUCT_ERA_ENTRY + struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG); + if (era) + { + int delta = tp->tm_year - era->start_date[0]; + DO_NUMBER (1, (era->offset + + delta * era->absolute_direction)); + } +#else +# if HAVE_STRFTIME + goto underlying_strftime; +# endif +#endif + } + DO_NUMBER (2, (tp->tm_year % 100 + 100) % 100); + + case L_('Z'): + if (change_case) + { + to_uppcase = 0; + to_lowcase = 1; + } + +#if HAVE_TZNAME + /* The tzset() call might have changed the value. */ + if (!(zone && *zone) && tp->tm_isdst >= 0) + zone = tzname[tp->tm_isdst]; +#endif + if (! zone) + zone = ""; + +#ifdef COMPILE_WIDE + { + /* The zone string is always given in multibyte form. We have + to transform it first. */ + wchar_t *wczone; + size_t len; + widen (zone, wczone, len); + cpy (len, wczone); + } +#else + cpy (strlen (zone), zone); +#endif + break; + + case L_('z'): + if (tp->tm_isdst < 0) + break; + + { + int diff; +#if HAVE_TM_GMTOFF + diff = tp->tm_gmtoff; +#else + if (ut) + diff = 0; + else + { + struct tm gtm; + struct tm ltm; + time_t lt; + + ltm = *tp; + lt = mktime (<m); + + if (lt == (time_t) -1) + { + /* mktime returns -1 for errors, but -1 is also a + valid time_t value. Check whether an error really + occurred. */ + struct tm tm; + + if (! __localtime_r (<, &tm) + || ((ltm.tm_sec ^ tm.tm_sec) + | (ltm.tm_min ^ tm.tm_min) + | (ltm.tm_hour ^ tm.tm_hour) + | (ltm.tm_mday ^ tm.tm_mday) + | (ltm.tm_mon ^ tm.tm_mon) + | (ltm.tm_year ^ tm.tm_year))) + break; + } + + if (! __gmtime_r (<, >m)) + break; + + diff = tm_diff (<m, >m); + } +#endif + + if (diff < 0) + { + add (1, *p = L_('-')); + diff = -diff; + } + else + add (1, *p = L_('+')); + + diff /= 60; + DO_NUMBER (4, (diff / 60) * 100 + diff % 60); + } + + case L_('\0'): /* GNU extension: % at end of format. */ + --f; + /* Fall through. */ + default: + /* Unknown format; output the format, including the '%', + since this is most likely the right thing to do if a + multibyte string has been misparsed. */ + bad_format: + { + int flen; + for (flen = 1; f[1 - flen] != L_('%'); flen++) + continue; + cpy (flen, &f[1 - flen]); + } + break; + } + } + + if (p && maxsize != 0) + *p = L_('\0'); + return i; +} +#ifdef _LIBC +libc_hidden_def (my_strftime) +#endif + + +#ifdef emacs +/* For Emacs we have a separate interface which corresponds to the normal + strftime function plus the ut argument, but without the ns argument. */ +size_t +emacs_strftimeu (char *s, size_t maxsize, const char *format, + const struct tm *tp, int ut) +{ + return my_strftime (s, maxsize, format, tp, ut, 0); +} +#endif diff --git a/contrib/diffutils-2.8/lib/strtoimax.c b/contrib/diffutils-2.8/lib/strtoimax.c new file mode 100644 index 0000000000..4ce741cfdd --- /dev/null +++ b/contrib/diffutils-2.8/lib/strtoimax.c @@ -0,0 +1,80 @@ +/* Convert string representation of a number into an intmax_t value. + Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Paul Eggert. */ + +#if HAVE_CONFIG_H +# include +#endif + +#if HAVE_INTTYPES_H +# include +#elif HAVE_STDINT_H +# include +#endif + +#include + +/* Verify a requirement at compile-time (unlike assert, which is runtime). */ +#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; } + +#ifdef UNSIGNED +# ifndef HAVE_DECL_STRTOULL +"this configure-time declaration test was not run" +# endif +# if !HAVE_DECL_STRTOULL && HAVE_UNSIGNED_LONG_LONG +unsigned long long strtoull (char const *, char **, int); +# endif + +#else + +# ifndef HAVE_DECL_STRTOLL +"this configure-time declaration test was not run" +# endif +# if !HAVE_DECL_STRTOLL && HAVE_UNSIGNED_LONG_LONG +long long strtoll (char const *, char **, int); +# endif +#endif + +#ifdef UNSIGNED +# undef HAVE_LONG_LONG +# define HAVE_LONG_LONG HAVE_UNSIGNED_LONG_LONG +# define INT uintmax_t +# define strtoimax strtoumax +# define strtol strtoul +# define strtoll strtoull +#else +# define INT intmax_t +#endif + +INT +strtoimax (char const *ptr, char **endptr, int base) +{ +#if HAVE_LONG_LONG + verify (size_is_that_of_long_or_long_long, + (sizeof (INT) == sizeof (long) + || sizeof (INT) == sizeof (long long))); + + if (sizeof (INT) != sizeof (long)) + return strtoll (ptr, endptr, base); +#else + verify (size_is_that_of_long, + sizeof (INT) == sizeof (long)); +#endif + + return strtol (ptr, endptr, base); +} diff --git a/contrib/diffutils-2.8/lib/strtoumax.c b/contrib/diffutils-2.8/lib/strtoumax.c new file mode 100644 index 0000000000..dc395d626a --- /dev/null +++ b/contrib/diffutils-2.8/lib/strtoumax.c @@ -0,0 +1,2 @@ +#define UNSIGNED 1 +#include "strtoimax.c" diff --git a/contrib/diffutils-2.8/lib/unlocked-io.h b/contrib/diffutils-2.8/lib/unlocked-io.h new file mode 100644 index 0000000000..36a7a4885d --- /dev/null +++ b/contrib/diffutils-2.8/lib/unlocked-io.h @@ -0,0 +1,132 @@ +/* Prefer faster, non-thread-safe stdio functions if available. + + Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Jim Meyering. */ + +#ifndef UNLOCKED_IO_H +# define UNLOCKED_IO_H 1 + +# ifndef USE_UNLOCKED_IO +# define USE_UNLOCKED_IO 1 +# endif + +# if USE_UNLOCKED_IO + +/* These are wrappers for functions/macros from the GNU C library, and + from other C libraries supporting POSIX's optional thread-safe functions. + + The standard I/O functions are thread-safe. These *_unlocked ones are + more efficient but not thread-safe. That they're not thread-safe is + fine since all of the applications in this package are single threaded. + + Also, some code that is shared with the GNU C library may invoke + the *_unlocked functions directly. On hosts that lack those + functions, invoke the non-thread-safe versions instead. */ + +# include + +# if HAVE_DECL_CLEARERR_UNLOCKED +# undef clearerr +# define clearerr(x) clearerr_unlocked (x) +# else +# define clearerr_unlocked(x) clearerr (x) +# endif +# if HAVE_DECL_FEOF_UNLOCKED +# undef feof +# define feof(x) feof_unlocked (x) +# else +# define feof_unlocked(x) feof (x) +# endif +# if HAVE_DECL_FERROR_UNLOCKED +# undef ferror +# define ferror(x) ferror_unlocked (x) +# else +# define ferror_unlocked(x) ferror (x) +# endif +# if HAVE_DECL_FFLUSH_UNLOCKED +# undef fflush +# define fflush(x) fflush_unlocked (x) +# else +# define fflush_unlocked(x) fflush (x) +# endif +# if HAVE_DECL_FGETS_UNLOCKED +# undef fgets +# define fgets(x,y,z) fgets_unlocked (x,y,z) +# else +# define fgets_unlocked(x,y,z) fgets (x,y,z) +# endif +# if HAVE_DECL_FPUTC_UNLOCKED +# undef fputc +# define fputc(x,y) fputc_unlocked (x,y) +# else +# define fputc_unlocked(x,y) fputc (x,y) +# endif +# if HAVE_DECL_FPUTS_UNLOCKED +# undef fputs +# define fputs(x,y) fputs_unlocked (x,y) +# else +# define fputs_unlocked(x,y) fputs (x,y) +# endif +# if HAVE_DECL_FREAD_UNLOCKED +# undef fread +# define fread(w,x,y,z) fread_unlocked (w,x,y,z) +# else +# define fread_unlocked(w,x,y,z) fread (w,x,y,z) +# endif +# if HAVE_DECL_FWRITE_UNLOCKED +# undef fwrite +# define fwrite(w,x,y,z) fwrite_unlocked (w,x,y,z) +# else +# define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z) +# endif +# if HAVE_DECL_GETC_UNLOCKED +# undef getc +# define getc(x) getc_unlocked (x) +# else +# define getc_unlocked(x) getc (x) +# endif +# if HAVE_DECL_GETCHAR_UNLOCKED +# undef getchar +# define getchar() getchar_unlocked () +# else +# define getchar_unlocked() getchar () +# endif +# if HAVE_DECL_PUTC_UNLOCKED +# undef putc +# define putc(x,y) putc_unlocked (x,y) +# else +# define putc_unlocked(x,y) putc (x,y) +# endif +# if HAVE_DECL_PUTCHAR_UNLOCKED +# undef putchar +# define putchar(x) putchar_unlocked (x) +# else +# define putchar_unlocked(x) putchar (x) +# endif + +# undef flockfile +# define flockfile(x) ((void) 0) + +# undef ftrylockfile +# define ftrylockfile(x) 0 + +# undef funlockfile +# define funlockfile(x) ((void) 0) + +# endif /* USE_UNLOCKED_IO */ +#endif /* UNLOCKED_IO_H */ diff --git a/contrib/diffutils-2.8/lib/version-etc.c b/contrib/diffutils-2.8/lib/version-etc.c new file mode 100644 index 0000000000..7523b087b2 --- /dev/null +++ b/contrib/diffutils-2.8/lib/version-etc.c @@ -0,0 +1,176 @@ +/* Utility to help print --version output in a consistent format. + Copyright (C) 1999-2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Jim Meyering. */ + +#if HAVE_CONFIG_H +# include +#endif + +/* Specification. */ +#include "version-etc.h" + +#include +#include +#include +#include "unlocked-io.h" + +#include "gettext.h" +#define _(msgid) gettext (msgid) + +/* Default copyright goes to the FSF. */ + +const char* version_etc_copyright = + /* Do *not* mark this string for translation. */ + "Copyright (C) 2004 Free Software Foundation, Inc."; + + +/* Like version_etc, below, but with the NULL-terminated author list + provided via a variable of type va_list. */ +void +version_etc_va (FILE *stream, + const char *command_name, const char *package, + const char *version, va_list authors) +{ + unsigned int n_authors; + + /* Count the number of authors. */ + { + va_list tmp_authors; + +#ifdef __va_copy + __va_copy (tmp_authors, authors); +#else + tmp_authors = authors; +#endif + + n_authors = 0; + while (va_arg (tmp_authors, const char *) != NULL) + ++n_authors; + } + + if (command_name) + fprintf (stream, "%s (%s) %s\n", command_name, package, version); + else + fprintf (stream, "%s %s\n", package, version); + + switch (n_authors) + { + case 0: + /* The caller must provide at least one author name. */ + abort (); + case 1: + /* TRANSLATORS: %s denotes an author name. */ + vfprintf (stream, _("Written by %s.\n"), authors); + break; + case 2: + /* TRANSLATORS: Each %s denotes an author name. */ + vfprintf (stream, _("Written by %s and %s.\n"), authors); + break; + case 3: + /* TRANSLATORS: Each %s denotes an author name. */ + vfprintf (stream, _("Written by %s, %s, and %s.\n"), authors); + break; + case 4: + /* TRANSLATORS: Each %s denotes an author name. + You can use line breaks, estimating that each author name occupies + ca. 16 screen columns and that a screen line has ca. 80 columns. */ + vfprintf (stream, _("Written by %s, %s, %s,\nand %s.\n"), authors); + break; + case 5: + /* TRANSLATORS: Each %s denotes an author name. + You can use line breaks, estimating that each author name occupies + ca. 16 screen columns and that a screen line has ca. 80 columns. */ + vfprintf (stream, _("Written by %s, %s, %s,\n%s, and %s.\n"), authors); + break; + case 6: + /* TRANSLATORS: Each %s denotes an author name. + You can use line breaks, estimating that each author name occupies + ca. 16 screen columns and that a screen line has ca. 80 columns. */ + vfprintf (stream, _("Written by %s, %s, %s,\n%s, %s, and %s.\n"), + authors); + break; + case 7: + /* TRANSLATORS: Each %s denotes an author name. + You can use line breaks, estimating that each author name occupies + ca. 16 screen columns and that a screen line has ca. 80 columns. */ + vfprintf (stream, _("Written by %s, %s, %s,\n%s, %s, %s, and %s.\n"), + authors); + break; + case 8: + /* TRANSLATORS: Each %s denotes an author name. + You can use line breaks, estimating that each author name occupies + ca. 16 screen columns and that a screen line has ca. 80 columns. */ + vfprintf (stream, _("\ +Written by %s, %s, %s,\n%s, %s, %s, %s,\nand %s.\n"), + authors); + break; + case 9: + /* TRANSLATORS: Each %s denotes an author name. + You can use line breaks, estimating that each author name occupies + ca. 16 screen columns and that a screen line has ca. 80 columns. */ + vfprintf (stream, _("\ +Written by %s, %s, %s,\n%s, %s, %s, %s,\n%s, and %s.\n"), + authors); + break; + default: + /* 10 or more authors. Use an abbreviation, since the human reader + will probably not want to read the entire list anyway. */ + /* TRANSLATORS: Each %s denotes an author name. + You can use line breaks, estimating that each author name occupies + ca. 16 screen columns and that a screen line has ca. 80 columns. */ + vfprintf (stream, _("\ +Written by %s, %s, %s,\n%s, %s, %s, %s,\n%s, %s, and others.\n"), + authors); + break; + } + va_end (authors); + putc ('\n', stream); + + fputs (version_etc_copyright, stream); + putc ('\n', stream); + + fputs (_("\ +This is free software; see the source for copying conditions. There is NO\n\ +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"), + stream); +} + + +/* Display the --version information the standard way. + + If COMMAND_NAME is NULL, the PACKAGE is asumed to be the name of + the program. The formats are therefore: + + PACKAGE VERSION + + or + + COMMAND_NAME (PACKAGE) VERSION. + + The author names are passed as separate arguments, with an additional + NULL argument at the end. */ +void +version_etc (FILE *stream, + const char *command_name, const char *package, + const char *version, /* const char *author1, ...*/ ...) +{ + va_list authors; + + va_start (authors, version); + version_etc_va (stream, command_name, package, version, authors); +} diff --git a/contrib/diffutils-2.8/lib/version-etc.h b/contrib/diffutils-2.8/lib/version-etc.h new file mode 100644 index 0000000000..d505e75eae --- /dev/null +++ b/contrib/diffutils-2.8/lib/version-etc.h @@ -0,0 +1,37 @@ +/* Utility to help print --version output in a consistent format. + Copyright (C) 1999, 2003 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Jim Meyering. */ + +#ifndef VERSION_ETC_H +# define VERSION_ETC_H 1 + +# include +# include + +extern const char *version_etc_copyright; + +extern void version_etc_va (FILE *stream, + const char *command_name, const char *package, + const char *version, va_list authors); + +extern void version_etc (FILE *stream, + const char *command_name, const char *package, + const char *version, + /* const char *author1, ...*/ ...); + +#endif /* VERSION_ETC_H */ diff --git a/contrib/diffutils-2.8/lib/xalloc.h b/contrib/diffutils-2.8/lib/xalloc.h new file mode 100644 index 0000000000..4b6585811b --- /dev/null +++ b/contrib/diffutils-2.8/lib/xalloc.h @@ -0,0 +1,87 @@ +/* xalloc.h -- malloc with out-of-memory checking + + Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, + 1999, 2000, 2003 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef XALLOC_H_ +# define XALLOC_H_ + +# include + +# ifndef __attribute__ +# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__ +# define __attribute__(x) +# endif +# endif + +# ifndef ATTRIBUTE_NORETURN +# define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__)) +# endif + +/* If this pointer is non-zero, run the specified function upon each + allocation failure. It is initialized to zero. */ +extern void (*xalloc_fail_func) (void); + +/* If XALLOC_FAIL_FUNC is undefined or a function that returns, this + message is output. It is translated via gettext. + Its value is "memory exhausted". */ +extern char const xalloc_msg_memory_exhausted[]; + +/* This function is always triggered when memory is exhausted. It is + in charge of honoring the two previous items. It exits with status + exit_failure (defined in exitfail.h). This is the + function to call when one wants the program to die because of a + memory allocation failure. */ +extern void xalloc_die (void) ATTRIBUTE_NORETURN; + +void *xmalloc (size_t s); +void *xnmalloc (size_t n, size_t s); +void *xzalloc (size_t s); +void *xcalloc (size_t n, size_t s); +void *xrealloc (void *p, size_t s); +void *xnrealloc (void *p, size_t n, size_t s); +void *x2realloc (void *p, size_t *pn); +void *x2nrealloc (void *p, size_t *pn, size_t s); +void *xclone (void const *p, size_t s); +char *xstrdup (const char *str); + +/* Return 1 if an array of N objects, each of size S, cannot exist due + to size arithmetic overflow. S must be positive and N must be + nonnegative. This is a macro, not an inline function, so that it + works correctly even when SIZE_MAX < N. + + By gnulib convention, SIZE_MAX represents overflow in size + calculations, so the conservative dividend to use here is + SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value. + However, malloc (SIZE_MAX) fails on all known hosts where + sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for + exactly-SIZE_MAX allocations on such hosts; this avoids a test and + branch when S is known to be 1. */ +# define xalloc_oversized(n, s) \ + ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n)) + +/* These macros are deprecated; they will go away soon, and are retained + temporarily only to ease conversion to the functions described above. */ +# define CCLONE(p, n) xclone (p, (n) * sizeof *(p)) +# define CLONE(p) xclone (p, sizeof *(p)) +# define NEW(type, var) type *var = xmalloc (sizeof (type)) +# define XCALLOC(type, n) xcalloc (n, sizeof (type)) +# define XMALLOC(type, n) xnmalloc (n, sizeof (type)) +# define XREALLOC(p, type, n) xnrealloc (p, n, sizeof (type)) +# define XFREE(p) free (p) + +#endif /* !XALLOC_H_ */ diff --git a/contrib/diffutils-2.8/lib/xmalloc.c b/contrib/diffutils-2.8/lib/xmalloc.c new file mode 100644 index 0000000000..181006b43d --- /dev/null +++ b/contrib/diffutils-2.8/lib/xmalloc.c @@ -0,0 +1,255 @@ +/* xmalloc.c -- malloc with out of memory checking + + Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2003, + 1999, 2000, 2002, 2003 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#if HAVE_CONFIG_H +# include +#endif + +#include "xalloc.h" + +#include +#include + +#include "gettext.h" +#define _(msgid) gettext (msgid) +#define N_(msgid) msgid + +#include "error.h" +#include "exitfail.h" + +#ifndef SIZE_MAX +# define SIZE_MAX ((size_t) -1) +#endif + +#ifndef HAVE_MALLOC +"you must run the autoconf test for a GNU libc compatible malloc" +#endif + +#ifndef HAVE_REALLOC +"you must run the autoconf test for a GNU libc compatible realloc" +#endif + +/* If non NULL, call this function when memory is exhausted. */ +void (*xalloc_fail_func) (void) = 0; + +/* If XALLOC_FAIL_FUNC is NULL, or does return, display this message + before exiting when memory is exhausted. Goes through gettext. */ +char const xalloc_msg_memory_exhausted[] = N_("memory exhausted"); + +void +xalloc_die (void) +{ + if (xalloc_fail_func) + (*xalloc_fail_func) (); + error (exit_failure, 0, "%s", _(xalloc_msg_memory_exhausted)); + /* The `noreturn' cannot be given to error, since it may return if + its first argument is 0. To help compilers understand the + xalloc_die does terminate, call abort. */ + abort (); +} + +/* Allocate an array of N objects, each with S bytes of memory, + dynamically, with error checking. S must be nonzero. */ + +static inline void * +xnmalloc_inline (size_t n, size_t s) +{ + void *p; + if (xalloc_oversized (n, s) || ! (p = malloc (n * s))) + xalloc_die (); + return p; +} + +void * +xnmalloc (size_t n, size_t s) +{ + return xnmalloc_inline (n, s); +} + +/* Allocate N bytes of memory dynamically, with error checking. */ + +void * +xmalloc (size_t n) +{ + return xnmalloc_inline (n, 1); +} + +/* Change the size of an allocated block of memory P to an array of N + objects each of S bytes, with error checking. S must be nonzero. */ + +static inline void * +xnrealloc_inline (void *p, size_t n, size_t s) +{ + if (xalloc_oversized (n, s) || ! (p = realloc (p, n * s))) + xalloc_die (); + return p; +} + +void * +xnrealloc (void *p, size_t n, size_t s) +{ + return xnrealloc_inline (p, n, s); +} + +/* Change the size of an allocated block of memory P to N bytes, + with error checking. */ + +void * +xrealloc (void *p, size_t n) +{ + return xnrealloc_inline (p, n, 1); +} + + +/* If P is null, allocate a block of at least *PN such objects; + otherwise, reallocate P so that it contains more than *PN objects + each of S bytes. *PN must be nonzero unless P is null, and S must + be nonzero. Set *PN to the new number of objects, and return the + pointer to the new block. *PN is never set to zero, and the + returned pointer is never null. + + Repeated reallocations are guaranteed to make progress, either by + allocating an initial block with a nonzero size, or by allocating a + larger block. + + In the following implementation, nonzero sizes are doubled so that + repeated reallocations have O(N log N) overall cost rather than + O(N**2) cost, but the specification for this function does not + guarantee that sizes are doubled. + + Here is an example of use: + + int *p = NULL; + size_t used = 0; + size_t allocated = 0; + + void + append_int (int value) + { + if (used == allocated) + p = x2nrealloc (p, &allocated, sizeof *p); + p[used++] = value; + } + + This causes x2nrealloc to allocate a block of some nonzero size the + first time it is called. + + To have finer-grained control over the initial size, set *PN to a + nonzero value before calling this function with P == NULL. For + example: + + int *p = NULL; + size_t used = 0; + size_t allocated = 0; + size_t allocated1 = 1000; + + void + append_int (int value) + { + if (used == allocated) + { + p = x2nrealloc (p, &allocated1, sizeof *p); + allocated = allocated1; + } + p[used++] = value; + } + + */ + +static inline void * +x2nrealloc_inline (void *p, size_t *pn, size_t s) +{ + size_t n = *pn; + + if (! p) + { + if (! n) + { + /* The approximate size to use for initial small allocation + requests, when the invoking code specifies an old size of + zero. 64 bytes is the largest "small" request for the + GNU C library malloc. */ + enum { DEFAULT_MXFAST = 64 }; + + n = DEFAULT_MXFAST / s; + n += !n; + } + } + else + { + if (SIZE_MAX / 2 / s < n) + xalloc_die (); + n *= 2; + } + + *pn = n; + return xrealloc (p, n * s); +} + +void * +x2nrealloc (void *p, size_t *pn, size_t s) +{ + return x2nrealloc_inline (p, pn, s); +} + +/* If P is null, allocate a block of at least *PN bytes; otherwise, + reallocate P so that it contains more than *PN bytes. *PN must be + nonzero unless P is null. Set *PN to the new block's size, and + return the pointer to the new block. *PN is never set to zero, and + the returned pointer is never null. */ + +void * +x2realloc (void *p, size_t *pn) +{ + return x2nrealloc_inline (p, pn, 1); +} + +/* Allocate S bytes of zeroed memory dynamically, with error checking. + There's no need for xnzalloc (N, S), since it would be equivalent + to xcalloc (N, S). */ + +void * +xzalloc (size_t s) +{ + return memset (xmalloc (s), 0, s); +} + +/* Allocate zeroed memory for N elements of S bytes, with error + checking. S must be nonzero. */ + +void * +xcalloc (size_t n, size_t s) +{ + void *p; + /* Test for overflow, since some calloc implementations don't have + proper overflow checks. */ + if (xalloc_oversized (n, s) || ! (p = calloc (n, s))) + xalloc_die (); + return p; +} + +/* Clone an object P of size S, with error checking. There's no need + for xnclone (P, N, S), since xclone (P, N * S) works without any + need for an arithmetic overflow check. */ + +void * +xclone (void const *p, size_t s) +{ + return memcpy (xmalloc (s), p, s); +} diff --git a/contrib/diffutils-2.8/man/diff.1 b/contrib/diffutils-2.8/man/diff.1 new file mode 100644 index 0000000000..cef8e1a1c7 --- /dev/null +++ b/contrib/diffutils-2.8/man/diff.1 @@ -0,0 +1,227 @@ +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.33. +.TH DIFF "1" "April 2004" "diffutils 2.8.7" "User Commands" +.SH NAME +diff \- compare files line by line +.SH SYNOPSIS +.B diff +[\fIOPTION\fR]... \fIFILES\fR +.SH DESCRIPTION +Compare files line by line. +.TP +\fB\-i\fR \fB\-\-ignore\-case\fR +Ignore case differences in file contents. +.TP +\fB\-\-ignore\-file\-name\-case\fR +Ignore case when comparing file names. +.TP +\fB\-\-no\-ignore\-file\-name\-case\fR +Consider case when comparing file names. +.TP +\fB\-E\fR \fB\-\-ignore\-tab\-expansion\fR +Ignore changes due to tab expansion. +.TP +\fB\-b\fR \fB\-\-ignore\-space\-change\fR +Ignore changes in the amount of white space. +.TP +\fB\-w\fR \fB\-\-ignore\-all\-space\fR +Ignore all white space. +.TP +\fB\-B\fR \fB\-\-ignore\-blank\-lines\fR +Ignore changes whose lines are all blank. +.TP +\fB\-I\fR RE \fB\-\-ignore\-matching\-lines\fR=\fIRE\fR +Ignore changes whose lines all match RE. +.TP +\fB\-\-strip\-trailing\-cr\fR +Strip trailing carriage return on input. +.TP +\fB\-a\fR \fB\-\-text\fR +Treat all files as text. +.TP +\fB\-c\fR \fB\-C\fR NUM \fB\-\-context\fR[=\fINUM\fR] +Output NUM (default 3) lines of copied context. +.TP +\fB\-u\fR \fB\-U\fR NUM \fB\-\-unified\fR[=\fINUM\fR] +Output NUM (default 3) lines of unified context. +.TP +\fB\-\-label\fR LABEL +Use LABEL instead of file name. +.TP +\fB\-p\fR \fB\-\-show\-c\-function\fR +Show which C function each change is in. +.TP +\fB\-F\fR RE \fB\-\-show\-function\-line\fR=\fIRE\fR +Show the most recent line matching RE. +.TP +\fB\-q\fR \fB\-\-brief\fR +Output only whether files differ. +.TP +\fB\-e\fR \fB\-\-ed\fR +Output an ed script. +.TP +\fB\-\-normal\fR +Output a normal diff. +.TP +\fB\-n\fR \fB\-\-rcs\fR +Output an RCS format diff. +.TP +\fB\-y\fR \fB\-\-side\-by\-side\fR +Output in two columns. +.TP +\fB\-W\fR NUM \fB\-\-width\fR=\fINUM\fR +Output at most NUM (default 130) print columns. +.TP +\fB\-\-left\-column\fR +Output only the left column of common lines. +.TP +\fB\-\-suppress\-common\-lines\fR +Do not output common lines. +.TP +\fB\-D\fR NAME \fB\-\-ifdef\fR=\fINAME\fR +Output merged file to show `#ifdef NAME' diffs. +.TP +\fB\-\-GTYPE\-group\-format\fR=\fIGFMT\fR +Similar, but format GTYPE input groups with GFMT. +.TP +\fB\-\-line\-format\fR=\fILFMT\fR +Similar, but format all input lines with LFMT. +.TP +\fB\-\-LTYPE\-line\-format\fR=\fILFMT\fR +Similar, but format LTYPE input lines with LFMT. +.TP +LTYPE is `old', `new', or `unchanged'. +GTYPE is LTYPE or `changed'. +.IP +GFMT may contain: +.TP +%< +lines from FILE1 +.TP +%> +lines from FILE2 +.TP +%= +lines common to FILE1 and FILE2 +.TP +%[-][WIDTH][.[PREC]]{doxX}LETTER +printf-style spec for LETTER +.IP +LETTERs are as follows for new group, lower case for old group: +.TP +F +first line number +.TP +L +last line number +.TP +N +number of lines = L-F+1 +.TP +E +F-1 +.TP +M +L+1 +.IP +LFMT may contain: +.TP +%L +contents of line +.TP +%l +contents of line, excluding any trailing newline +.TP +%[-][WIDTH][.[PREC]]{doxX}n +printf-style spec for input line number +.IP +Either GFMT or LFMT may contain: +.TP +%% +% +.TP +%c'C' +the single character C +.TP +%c'\eOOO' +the character with octal code OOO +.TP +\fB\-l\fR \fB\-\-paginate\fR +Pass the output through `pr' to paginate it. +.TP +\fB\-t\fR \fB\-\-expand\-tabs\fR +Expand tabs to spaces in output. +.TP +\fB\-T\fR \fB\-\-initial\-tab\fR +Make tabs line up by prepending a tab. +.TP +\fB\-\-tabsize\fR=\fINUM\fR +Tab stops are every NUM (default 8) print columns. +.TP +\fB\-r\fR \fB\-\-recursive\fR +Recursively compare any subdirectories found. +.TP +\fB\-N\fR \fB\-\-new\-file\fR +Treat absent files as empty. +.TP +\fB\-\-unidirectional\-new\-file\fR +Treat absent first files as empty. +.TP +\fB\-s\fR \fB\-\-report\-identical\-files\fR +Report when two files are the same. +.TP +\fB\-x\fR PAT \fB\-\-exclude\fR=\fIPAT\fR +Exclude files that match PAT. +.TP +\fB\-X\fR FILE \fB\-\-exclude\-from\fR=\fIFILE\fR +Exclude files that match any pattern in FILE. +.TP +\fB\-S\fR FILE \fB\-\-starting\-file\fR=\fIFILE\fR +Start with FILE when comparing directories. +.TP +\fB\-\-from\-file\fR=\fIFILE1\fR +Compare FILE1 to all operands. FILE1 can be a directory. +.TP +\fB\-\-to\-file\fR=\fIFILE2\fR +Compare all operands to FILE2. FILE2 can be a directory. +.TP +\fB\-\-horizon\-lines\fR=\fINUM\fR +Keep NUM lines of the common prefix and suffix. +.TP +\fB\-d\fR \fB\-\-minimal\fR +Try hard to find a smaller set of changes. +.TP +\fB\-\-speed\-large\-files\fR +Assume large files and many scattered small changes. +.TP +\fB\-v\fR \fB\-\-version\fR +Output version info. +.TP +\fB\-\-help\fR +Output this help. +.PP +FILES are `FILE1 FILE2' or `DIR1 DIR2' or `DIR FILE...' or `FILE... DIR'. +If \fB\-\-from\-file\fR or \fB\-\-to\-file\fR is given, there are no restrictions on FILES. +If a FILE is `-', read standard input. +Exit status is 0 if inputs are the same, 1 if different, 2 if trouble. +.SH AUTHOR +Written by Paul Eggert, Mike Haertel, David Hayes, +Richard Stallman, and Len Tower. +.SH "REPORTING BUGS" +Report bugs to . +.SH COPYRIGHT +Copyright \(co 2004 Free Software Foundation, Inc. +.br +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +.SH "SEE ALSO" +The full documentation for +.B diff +is maintained as a Texinfo manual. If the +.B info +and +.B diff +programs are properly installed at your site, the command +.IP +.B info diff +.PP +should give you access to the complete manual. diff --git a/contrib/diffutils-2.8/man/diff3.1 b/contrib/diffutils-2.8/man/diff3.1 new file mode 100644 index 0000000000..f7daee23a6 --- /dev/null +++ b/contrib/diffutils-2.8/man/diff3.1 @@ -0,0 +1,78 @@ +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.33. +.TH DIFF3 "1" "April 2004" "diffutils 2.8.7" "User Commands" +.SH NAME +diff3 \- compare three files line by line +.SH SYNOPSIS +.B diff3 +[\fIOPTION\fR]... \fIMYFILE OLDFILE YOURFILE\fR +.SH DESCRIPTION +Compare three files line by line. +.TP +\fB\-e\fR \fB\-\-ed\fR +Output unmerged changes from OLDFILE to YOURFILE into MYFILE. +.TP +\fB\-E\fR \fB\-\-show\-overlap\fR +Output unmerged changes, bracketing conflicts. +.TP +\fB\-A\fR \fB\-\-show\-all\fR +Output all changes, bracketing conflicts. +.TP +\fB\-x\fR \fB\-\-overlap\-only\fR +Output overlapping changes. +.TP +\fB\-X\fR +Output overlapping changes, bracketing them. +.TP +\fB\-3\fR \fB\-\-easy\-only\fR +Output unmerged nonoverlapping changes. +.TP +\fB\-m\fR \fB\-\-merge\fR +Output merged file instead of ed script (default \fB\-A\fR). +.TP +\fB\-L\fR LABEL \fB\-\-label\fR=\fILABEL\fR +Use LABEL instead of file name. +.TP +\fB\-i\fR +Append `w' and `q' commands to ed scripts. +.TP +\fB\-a\fR \fB\-\-text\fR +Treat all files as text. +.TP +\fB\-\-strip\-trailing\-cr\fR +Strip trailing carriage return on input. +.TP +\fB\-T\fR \fB\-\-initial\-tab\fR +Make tabs line up by prepending a tab. +.TP +\fB\-\-diff\-program\fR=\fIPROGRAM\fR +Use PROGRAM to compare files. +.TP +\fB\-v\fR \fB\-\-version\fR +Output version info. +.TP +\fB\-\-help\fR +Output this help. +.PP +If a FILE is `-', read standard input. +Exit status is 0 if successful, 1 if conflicts, 2 if trouble. +.SH AUTHOR +Written by Randy Smith. +.SH "REPORTING BUGS" +Report bugs to . +.SH COPYRIGHT +Copyright \(co 2004 Free Software Foundation, Inc. +.br +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +.SH "SEE ALSO" +The full documentation for +.B diff3 +is maintained as a Texinfo manual. If the +.B info +and +.B diff3 +programs are properly installed at your site, the command +.IP +.B info diff +.PP +should give you access to the complete manual. diff --git a/contrib/diffutils-2.8/man/sdiff.1 b/contrib/diffutils-2.8/man/sdiff.1 new file mode 100644 index 0000000000..ab64c7eafc --- /dev/null +++ b/contrib/diffutils-2.8/man/sdiff.1 @@ -0,0 +1,90 @@ +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.33. +.TH SDIFF "1" "April 2004" "diffutils 2.8.7" "User Commands" +.SH NAME +sdiff \- side-by-side merge of file differences +.SH SYNOPSIS +.B sdiff +[\fIOPTION\fR]... \fIFILE1 FILE2\fR +.SH DESCRIPTION +Side-by-side merge of file differences. +.TP +\fB\-o\fR FILE \fB\-\-output\fR=\fIFILE\fR +Operate interactively, sending output to FILE. +.TP +\fB\-i\fR \fB\-\-ignore\-case\fR +Consider upper- and lower-case to be the same. +.TP +\fB\-E\fR \fB\-\-ignore\-tab\-expansion\fR +Ignore changes due to tab expansion. +.TP +\fB\-b\fR \fB\-\-ignore\-space\-change\fR +Ignore changes in the amount of white space. +.TP +\fB\-W\fR \fB\-\-ignore\-all\-space\fR +Ignore all white space. +.TP +\fB\-B\fR \fB\-\-ignore\-blank\-lines\fR +Ignore changes whose lines are all blank. +.TP +\fB\-I\fR RE \fB\-\-ignore\-matching\-lines\fR=\fIRE\fR +Ignore changes whose lines all match RE. +.TP +\fB\-\-strip\-trailing\-cr\fR +Strip trailing carriage return on input. +.TP +\fB\-a\fR \fB\-\-text\fR +Treat all files as text. +.TP +\fB\-w\fR NUM \fB\-\-width\fR=\fINUM\fR +Output at most NUM (default 130) print columns. +.TP +\fB\-l\fR \fB\-\-left\-column\fR +Output only the left column of common lines. +.TP +\fB\-s\fR \fB\-\-suppress\-common\-lines\fR +Do not output common lines. +.TP +\fB\-t\fR \fB\-\-expand\-tabs\fR +Expand tabs to spaces in output. +.TP +\fB\-\-tabsize\fR=\fINUM\fR +Tab stops are every NUM (default 8) print columns. +.TP +\fB\-d\fR \fB\-\-minimal\fR +Try hard to find a smaller set of changes. +.TP +\fB\-H\fR \fB\-\-speed\-large\-files\fR +Assume large files and many scattered small changes. +.TP +\fB\-\-diff\-program\fR=\fIPROGRAM\fR +Use PROGRAM to compare files. +.TP +\fB\-v\fR \fB\-\-version\fR +Output version info. +.TP +\fB\-\-help\fR +Output this help. +.PP +If a FILE is `-', read standard input. +Exit status is 0 if inputs are the same, 1 if different, 2 if trouble. +.SH AUTHOR +Written by Thomas Lord. +.SH "REPORTING BUGS" +Report bugs to . +.SH COPYRIGHT +Copyright \(co 2004 Free Software Foundation, Inc. +.br +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +.SH "SEE ALSO" +The full documentation for +.B sdiff +is maintained as a Texinfo manual. If the +.B info +and +.B sdiff +programs are properly installed at your site, the command +.IP +.B info diff +.PP +should give you access to the complete manual. diff --git a/contrib/diffutils-2.8/src/analyze.c b/contrib/diffutils-2.8/src/analyze.c new file mode 100644 index 0000000000..7d6750a421 --- /dev/null +++ b/contrib/diffutils-2.8/src/analyze.c @@ -0,0 +1,1038 @@ +/* Analyze file differences for GNU DIFF. + + Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1998, 2001, 2002, + 2004 Free Software Foundation, Inc. + + This file is part of GNU DIFF. + + GNU DIFF is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GNU DIFF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* The basic algorithm is described in: + "An O(ND) Difference Algorithm and its Variations", Eugene Myers, + Algorithmica Vol. 1 No. 2, 1986, pp. 251-266; + see especially section 4.2, which describes the variation used below. + Unless the --minimal option is specified, this code uses the TOO_EXPENSIVE + heuristic, by Paul Eggert, to limit the cost to O(N**1.5 log N) + at the price of producing suboptimal output for large inputs with + many differences. + + The basic algorithm was independently discovered as described in: + "Algorithms for Approximate String Matching", E. Ukkonen, + Information and Control Vol. 64, 1985, pp. 100-118. */ + +#include "diff.h" +#include +#include +#include +#include + +static lin *xvec, *yvec; /* Vectors being compared. */ +static lin *fdiag; /* Vector, indexed by diagonal, containing + 1 + the X coordinate of the point furthest + along the given diagonal in the forward + search of the edit matrix. */ +static lin *bdiag; /* Vector, indexed by diagonal, containing + the X coordinate of the point furthest + along the given diagonal in the backward + search of the edit matrix. */ +static lin too_expensive; /* Edit scripts longer than this are too + expensive to compute. */ + +#define SNAKE_LIMIT 20 /* Snakes bigger than this are considered `big'. */ + +struct partition +{ + lin xmid, ymid; /* Midpoints of this partition. */ + bool lo_minimal; /* Nonzero if low half will be analyzed minimally. */ + bool hi_minimal; /* Likewise for high half. */ +}; + +/* Find the midpoint of the shortest edit script for a specified + portion of the two files. + + Scan from the beginnings of the files, and simultaneously from the ends, + doing a breadth-first search through the space of edit-sequence. + When the two searches meet, we have found the midpoint of the shortest + edit sequence. + + If FIND_MINIMAL is nonzero, find the minimal edit script regardless + of expense. Otherwise, if the search is too expensive, use + heuristics to stop the search and report a suboptimal answer. + + Set PART->(xmid,ymid) to the midpoint (XMID,YMID). The diagonal number + XMID - YMID equals the number of inserted lines minus the number + of deleted lines (counting only lines before the midpoint). + + Set PART->lo_minimal to true iff the minimal edit script for the + left half of the partition is known; similarly for PART->hi_minimal. + + This function assumes that the first lines of the specified portions + of the two files do not match, and likewise that the last lines do not + match. The caller must trim matching lines from the beginning and end + of the portions it is going to specify. + + If we return the "wrong" partitions, + the worst this can do is cause suboptimal diff output. + It cannot cause incorrect diff output. */ + +static void +diag (lin xoff, lin xlim, lin yoff, lin ylim, bool find_minimal, + struct partition *part) +{ + lin *const fd = fdiag; /* Give the compiler a chance. */ + lin *const bd = bdiag; /* Additional help for the compiler. */ + lin const *const xv = xvec; /* Still more help for the compiler. */ + lin const *const yv = yvec; /* And more and more . . . */ + lin const dmin = xoff - ylim; /* Minimum valid diagonal. */ + lin const dmax = xlim - yoff; /* Maximum valid diagonal. */ + lin const fmid = xoff - yoff; /* Center diagonal of top-down search. */ + lin const bmid = xlim - ylim; /* Center diagonal of bottom-up search. */ + lin fmin = fmid, fmax = fmid; /* Limits of top-down search. */ + lin bmin = bmid, bmax = bmid; /* Limits of bottom-up search. */ + lin c; /* Cost. */ + bool odd = (fmid - bmid) & 1; /* True if southeast corner is on an odd + diagonal with respect to the northwest. */ + + fd[fmid] = xoff; + bd[bmid] = xlim; + + for (c = 1;; ++c) + { + lin d; /* Active diagonal. */ + bool big_snake = false; + + /* Extend the top-down search by an edit step in each diagonal. */ + fmin > dmin ? fd[--fmin - 1] = -1 : ++fmin; + fmax < dmax ? fd[++fmax + 1] = -1 : --fmax; + for (d = fmax; d >= fmin; d -= 2) + { + lin x, y, oldx, tlo = fd[d - 1], thi = fd[d + 1]; + + if (tlo >= thi) + x = tlo + 1; + else + x = thi; + oldx = x; + y = x - d; + while (x < xlim && y < ylim && xv[x] == yv[y]) + ++x, ++y; + if (x - oldx > SNAKE_LIMIT) + big_snake = true; + fd[d] = x; + if (odd && bmin <= d && d <= bmax && bd[d] <= x) + { + part->xmid = x; + part->ymid = y; + part->lo_minimal = part->hi_minimal = true; + return; + } + } + + /* Similarly extend the bottom-up search. */ + bmin > dmin ? bd[--bmin - 1] = LIN_MAX : ++bmin; + bmax < dmax ? bd[++bmax + 1] = LIN_MAX : --bmax; + for (d = bmax; d >= bmin; d -= 2) + { + lin x, y, oldx, tlo = bd[d - 1], thi = bd[d + 1]; + + if (tlo < thi) + x = tlo; + else + x = thi - 1; + oldx = x; + y = x - d; + while (x > xoff && y > yoff && xv[x - 1] == yv[y - 1]) + --x, --y; + if (oldx - x > SNAKE_LIMIT) + big_snake = true; + bd[d] = x; + if (!odd && fmin <= d && d <= fmax && x <= fd[d]) + { + part->xmid = x; + part->ymid = y; + part->lo_minimal = part->hi_minimal = true; + return; + } + } + + if (find_minimal) + continue; + + /* Heuristic: check occasionally for a diagonal that has made + lots of progress compared with the edit distance. + If we have any such, find the one that has made the most + progress and return it as if it had succeeded. + + With this heuristic, for files with a constant small density + of changes, the algorithm is linear in the file size. */ + + if (200 < c && big_snake && speed_large_files) + { + lin best = 0; + + for (d = fmax; d >= fmin; d -= 2) + { + lin dd = d - fmid; + lin x = fd[d]; + lin y = x - d; + lin v = (x - xoff) * 2 - dd; + if (v > 12 * (c + (dd < 0 ? -dd : dd))) + { + if (v > best + && xoff + SNAKE_LIMIT <= x && x < xlim + && yoff + SNAKE_LIMIT <= y && y < ylim) + { + /* We have a good enough best diagonal; + now insist that it end with a significant snake. */ + int k; + + for (k = 1; xv[x - k] == yv[y - k]; k++) + if (k == SNAKE_LIMIT) + { + best = v; + part->xmid = x; + part->ymid = y; + break; + } + } + } + } + if (best > 0) + { + part->lo_minimal = true; + part->hi_minimal = false; + return; + } + + best = 0; + for (d = bmax; d >= bmin; d -= 2) + { + lin dd = d - bmid; + lin x = bd[d]; + lin y = x - d; + lin v = (xlim - x) * 2 + dd; + if (v > 12 * (c + (dd < 0 ? -dd : dd))) + { + if (v > best + && xoff < x && x <= xlim - SNAKE_LIMIT + && yoff < y && y <= ylim - SNAKE_LIMIT) + { + /* We have a good enough best diagonal; + now insist that it end with a significant snake. */ + int k; + + for (k = 0; xv[x + k] == yv[y + k]; k++) + if (k == SNAKE_LIMIT - 1) + { + best = v; + part->xmid = x; + part->ymid = y; + break; + } + } + } + } + if (best > 0) + { + part->lo_minimal = false; + part->hi_minimal = true; + return; + } + } + + /* Heuristic: if we've gone well beyond the call of duty, + give up and report halfway between our best results so far. */ + if (c >= too_expensive) + { + lin fxybest, fxbest; + lin bxybest, bxbest; + + fxbest = bxbest = 0; /* Pacify `gcc -Wall'. */ + + /* Find forward diagonal that maximizes X + Y. */ + fxybest = -1; + for (d = fmax; d >= fmin; d -= 2) + { + lin x = MIN (fd[d], xlim); + lin y = x - d; + if (ylim < y) + x = ylim + d, y = ylim; + if (fxybest < x + y) + { + fxybest = x + y; + fxbest = x; + } + } + + /* Find backward diagonal that minimizes X + Y. */ + bxybest = LIN_MAX; + for (d = bmax; d >= bmin; d -= 2) + { + lin x = MAX (xoff, bd[d]); + lin y = x - d; + if (y < yoff) + x = yoff + d, y = yoff; + if (x + y < bxybest) + { + bxybest = x + y; + bxbest = x; + } + } + + /* Use the better of the two diagonals. */ + if ((xlim + ylim) - bxybest < fxybest - (xoff + yoff)) + { + part->xmid = fxbest; + part->ymid = fxybest - fxbest; + part->lo_minimal = true; + part->hi_minimal = false; + } + else + { + part->xmid = bxbest; + part->ymid = bxybest - bxbest; + part->lo_minimal = false; + part->hi_minimal = true; + } + return; + } + } +} + +/* Compare in detail contiguous subsequences of the two files + which are known, as a whole, to match each other. + + The results are recorded in the vectors files[N].changed, by + storing 1 in the element for each line that is an insertion or deletion. + + The subsequence of file 0 is [XOFF, XLIM) and likewise for file 1. + + Note that XLIM, YLIM are exclusive bounds. + All line numbers are origin-0 and discarded lines are not counted. + + If FIND_MINIMAL, find a minimal difference no matter how + expensive it is. */ + +static void +compareseq (lin xoff, lin xlim, lin yoff, lin ylim, bool find_minimal) +{ + lin const *xv = xvec; /* Help the compiler. */ + lin const *yv = yvec; + + /* Slide down the bottom initial diagonal. */ + while (xoff < xlim && yoff < ylim && xv[xoff] == yv[yoff]) + ++xoff, ++yoff; + /* Slide up the top initial diagonal. */ + while (xlim > xoff && ylim > yoff && xv[xlim - 1] == yv[ylim - 1]) + --xlim, --ylim; + + /* Handle simple cases. */ + if (xoff == xlim) + while (yoff < ylim) + files[1].changed[files[1].realindexes[yoff++]] = 1; + else if (yoff == ylim) + while (xoff < xlim) + files[0].changed[files[0].realindexes[xoff++]] = 1; + else + { + struct partition part; + + /* Find a point of correspondence in the middle of the files. */ + diag (xoff, xlim, yoff, ylim, find_minimal, &part); + + /* Use the partitions to split this problem into subproblems. */ + compareseq (xoff, part.xmid, yoff, part.ymid, part.lo_minimal); + compareseq (part.xmid, xlim, part.ymid, ylim, part.hi_minimal); + } +} + +/* Discard lines from one file that have no matches in the other file. + + A line which is discarded will not be considered by the actual + comparison algorithm; it will be as if that line were not in the file. + The file's `realindexes' table maps virtual line numbers + (which don't count the discarded lines) into real line numbers; + this is how the actual comparison algorithm produces results + that are comprehensible when the discarded lines are counted. + + When we discard a line, we also mark it as a deletion or insertion + so that it will be printed in the output. */ + +static void +discard_confusing_lines (struct file_data filevec[]) +{ + int f; + lin i; + char *discarded[2]; + lin *equiv_count[2]; + lin *p; + + /* Allocate our results. */ + p = xmalloc ((filevec[0].buffered_lines + filevec[1].buffered_lines) + * (2 * sizeof *p)); + for (f = 0; f < 2; f++) + { + filevec[f].undiscarded = p; p += filevec[f].buffered_lines; + filevec[f].realindexes = p; p += filevec[f].buffered_lines; + } + + /* Set up equiv_count[F][I] as the number of lines in file F + that fall in equivalence class I. */ + + p = zalloc (filevec[0].equiv_max * (2 * sizeof *p)); + equiv_count[0] = p; + equiv_count[1] = p + filevec[0].equiv_max; + + for (i = 0; i < filevec[0].buffered_lines; ++i) + ++equiv_count[0][filevec[0].equivs[i]]; + for (i = 0; i < filevec[1].buffered_lines; ++i) + ++equiv_count[1][filevec[1].equivs[i]]; + + /* Set up tables of which lines are going to be discarded. */ + + discarded[0] = zalloc (filevec[0].buffered_lines + + filevec[1].buffered_lines); + discarded[1] = discarded[0] + filevec[0].buffered_lines; + + /* Mark to be discarded each line that matches no line of the other file. + If a line matches many lines, mark it as provisionally discardable. */ + + for (f = 0; f < 2; f++) + { + size_t end = filevec[f].buffered_lines; + char *discards = discarded[f]; + lin *counts = equiv_count[1 - f]; + lin *equivs = filevec[f].equivs; + size_t many = 5; + size_t tem = end / 64; + + /* Multiply MANY by approximate square root of number of lines. + That is the threshold for provisionally discardable lines. */ + while ((tem = tem >> 2) > 0) + many *= 2; + + for (i = 0; i < end; i++) + { + lin nmatch; + if (equivs[i] == 0) + continue; + nmatch = counts[equivs[i]]; + if (nmatch == 0) + discards[i] = 1; + else if (nmatch > many) + discards[i] = 2; + } + } + + /* Don't really discard the provisional lines except when they occur + in a run of discardables, with nonprovisionals at the beginning + and end. */ + + for (f = 0; f < 2; f++) + { + lin end = filevec[f].buffered_lines; + register char *discards = discarded[f]; + + for (i = 0; i < end; i++) + { + /* Cancel provisional discards not in middle of run of discards. */ + if (discards[i] == 2) + discards[i] = 0; + else if (discards[i] != 0) + { + /* We have found a nonprovisional discard. */ + register lin j; + lin length; + lin provisional = 0; + + /* Find end of this run of discardable lines. + Count how many are provisionally discardable. */ + for (j = i; j < end; j++) + { + if (discards[j] == 0) + break; + if (discards[j] == 2) + ++provisional; + } + + /* Cancel provisional discards at end, and shrink the run. */ + while (j > i && discards[j - 1] == 2) + discards[--j] = 0, --provisional; + + /* Now we have the length of a run of discardable lines + whose first and last are not provisional. */ + length = j - i; + + /* If 1/4 of the lines in the run are provisional, + cancel discarding of all provisional lines in the run. */ + if (provisional * 4 > length) + { + while (j > i) + if (discards[--j] == 2) + discards[j] = 0; + } + else + { + register lin consec; + lin minimum = 1; + lin tem = length >> 2; + + /* MINIMUM is approximate square root of LENGTH/4. + A subrun of two or more provisionals can stand + when LENGTH is at least 16. + A subrun of 4 or more can stand when LENGTH >= 64. */ + while (0 < (tem >>= 2)) + minimum <<= 1; + minimum++; + + /* Cancel any subrun of MINIMUM or more provisionals + within the larger run. */ + for (j = 0, consec = 0; j < length; j++) + if (discards[i + j] != 2) + consec = 0; + else if (minimum == ++consec) + /* Back up to start of subrun, to cancel it all. */ + j -= consec; + else if (minimum < consec) + discards[i + j] = 0; + + /* Scan from beginning of run + until we find 3 or more nonprovisionals in a row + or until the first nonprovisional at least 8 lines in. + Until that point, cancel any provisionals. */ + for (j = 0, consec = 0; j < length; j++) + { + if (j >= 8 && discards[i + j] == 1) + break; + if (discards[i + j] == 2) + consec = 0, discards[i + j] = 0; + else if (discards[i + j] == 0) + consec = 0; + else + consec++; + if (consec == 3) + break; + } + + /* I advances to the last line of the run. */ + i += length - 1; + + /* Same thing, from end. */ + for (j = 0, consec = 0; j < length; j++) + { + if (j >= 8 && discards[i - j] == 1) + break; + if (discards[i - j] == 2) + consec = 0, discards[i - j] = 0; + else if (discards[i - j] == 0) + consec = 0; + else + consec++; + if (consec == 3) + break; + } + } + } + } + } + + /* Actually discard the lines. */ + for (f = 0; f < 2; f++) + { + char *discards = discarded[f]; + lin end = filevec[f].buffered_lines; + lin j = 0; + for (i = 0; i < end; ++i) + if (minimal || discards[i] == 0) + { + filevec[f].undiscarded[j] = filevec[f].equivs[i]; + filevec[f].realindexes[j++] = i; + } + else + filevec[f].changed[i] = 1; + filevec[f].nondiscarded_lines = j; + } + + free (discarded[0]); + free (equiv_count[0]); +} + +/* Adjust inserts/deletes of identical lines to join changes + as much as possible. + + We do something when a run of changed lines include a + line at one end and have an excluded, identical line at the other. + We are free to choose which identical line is included. + `compareseq' usually chooses the one at the beginning, + but usually it is cleaner to consider the following identical line + to be the "change". */ + +static void +shift_boundaries (struct file_data filevec[]) +{ + int f; + + for (f = 0; f < 2; f++) + { + char *changed = filevec[f].changed; + char *other_changed = filevec[1 - f].changed; + lin const *equivs = filevec[f].equivs; + lin i = 0; + lin j = 0; + lin i_end = filevec[f].buffered_lines; + + while (1) + { + lin runlength, start, corresponding; + + /* Scan forwards to find beginning of another run of changes. + Also keep track of the corresponding point in the other file. */ + + while (i < i_end && !changed[i]) + { + while (other_changed[j++]) + continue; + i++; + } + + if (i == i_end) + break; + + start = i; + + /* Find the end of this run of changes. */ + + while (changed[++i]) + continue; + while (other_changed[j]) + j++; + + do + { + /* Record the length of this run of changes, so that + we can later determine whether the run has grown. */ + runlength = i - start; + + /* Move the changed region back, so long as the + previous unchanged line matches the last changed one. + This merges with previous changed regions. */ + + while (start && equivs[start - 1] == equivs[i - 1]) + { + changed[--start] = 1; + changed[--i] = 0; + while (changed[start - 1]) + start--; + while (other_changed[--j]) + continue; + } + + /* Set CORRESPONDING to the end of the changed run, at the last + point where it corresponds to a changed run in the other file. + CORRESPONDING == I_END means no such point has been found. */ + corresponding = other_changed[j - 1] ? i : i_end; + + /* Move the changed region forward, so long as the + first changed line matches the following unchanged one. + This merges with following changed regions. + Do this second, so that if there are no merges, + the changed region is moved forward as far as possible. */ + + while (i != i_end && equivs[start] == equivs[i]) + { + changed[start++] = 0; + changed[i++] = 1; + while (changed[i]) + i++; + while (other_changed[++j]) + corresponding = i; + } + } + while (runlength != i - start); + + /* If possible, move the fully-merged run of changes + back to a corresponding run in the other file. */ + + while (corresponding < i) + { + changed[--start] = 1; + changed[--i] = 0; + while (other_changed[--j]) + continue; + } + } + } +} + +/* Cons an additional entry onto the front of an edit script OLD. + LINE0 and LINE1 are the first affected lines in the two files (origin 0). + DELETED is the number of lines deleted here from file 0. + INSERTED is the number of lines inserted here in file 1. + + If DELETED is 0 then LINE0 is the number of the line before + which the insertion was done; vice versa for INSERTED and LINE1. */ + +static struct change * +add_change (lin line0, lin line1, lin deleted, lin inserted, + struct change *old) +{ + struct change *new = xmalloc (sizeof *new); + + new->line0 = line0; + new->line1 = line1; + new->inserted = inserted; + new->deleted = deleted; + new->link = old; + return new; +} + +/* Scan the tables of which lines are inserted and deleted, + producing an edit script in reverse order. */ + +static struct change * +build_reverse_script (struct file_data const filevec[]) +{ + struct change *script = 0; + char *changed0 = filevec[0].changed; + char *changed1 = filevec[1].changed; + lin len0 = filevec[0].buffered_lines; + lin len1 = filevec[1].buffered_lines; + + /* Note that changedN[len0] does exist, and is 0. */ + + lin i0 = 0, i1 = 0; + + while (i0 < len0 || i1 < len1) + { + if (changed0[i0] | changed1[i1]) + { + lin line0 = i0, line1 = i1; + + /* Find # lines changed here in each file. */ + while (changed0[i0]) ++i0; + while (changed1[i1]) ++i1; + + /* Record this change. */ + script = add_change (line0, line1, i0 - line0, i1 - line1, script); + } + + /* We have reached lines in the two files that match each other. */ + i0++, i1++; + } + + return script; +} + +/* Scan the tables of which lines are inserted and deleted, + producing an edit script in forward order. */ + +static struct change * +build_script (struct file_data const filevec[]) +{ + struct change *script = 0; + char *changed0 = filevec[0].changed; + char *changed1 = filevec[1].changed; + lin i0 = filevec[0].buffered_lines, i1 = filevec[1].buffered_lines; + + /* Note that changedN[-1] does exist, and is 0. */ + + while (i0 >= 0 || i1 >= 0) + { + if (changed0[i0 - 1] | changed1[i1 - 1]) + { + lin line0 = i0, line1 = i1; + + /* Find # lines changed here in each file. */ + while (changed0[i0 - 1]) --i0; + while (changed1[i1 - 1]) --i1; + + /* Record this change. */ + script = add_change (i0, i1, line0 - i0, line1 - i1, script); + } + + /* We have reached lines in the two files that match each other. */ + i0--, i1--; + } + + return script; +} + +/* If CHANGES, briefly report that two files differed. + Return 2 if trouble, CHANGES otherwise. */ +static int +briefly_report (int changes, struct file_data const filevec[]) +{ + if (changes) + { + char const *label0 = file_label[0] ? file_label[0] : filevec[0].name; + char const *label1 = file_label[1] ? file_label[1] : filevec[1].name; + message ("Files %s and %s differ\n", label0, label1); + if (! brief) + changes = 2; + } + + return changes; +} + +/* Report the differences of two files. */ +int +diff_2_files (struct comparison *cmp) +{ + lin diags; + int f; + struct change *e, *p; + struct change *script; + int changes; + + + /* If we have detected that either file is binary, + compare the two files as binary. This can happen + only when the first chunk is read. + Also, --brief without any --ignore-* options means + we can speed things up by treating the files as binary. */ + + if (read_files (cmp->file, files_can_be_treated_as_binary)) + { + /* Files with different lengths must be different. */ + if (cmp->file[0].stat.st_size != cmp->file[1].stat.st_size + && (cmp->file[0].desc < 0 || S_ISREG (cmp->file[0].stat.st_mode)) + && (cmp->file[1].desc < 0 || S_ISREG (cmp->file[1].stat.st_mode))) + changes = 1; + + /* Standard input equals itself. */ + else if (cmp->file[0].desc == cmp->file[1].desc) + changes = 0; + + else + /* Scan both files, a buffer at a time, looking for a difference. */ + { + /* Allocate same-sized buffers for both files. */ + size_t lcm_max = PTRDIFF_MAX - 1; + size_t buffer_size = + buffer_lcm (sizeof (word), + buffer_lcm (STAT_BLOCKSIZE (cmp->file[0].stat), + STAT_BLOCKSIZE (cmp->file[1].stat), + lcm_max), + lcm_max); + for (f = 0; f < 2; f++) + cmp->file[f].buffer = xrealloc (cmp->file[f].buffer, buffer_size); + + for (;; cmp->file[0].buffered = cmp->file[1].buffered = 0) + { + /* Read a buffer's worth from both files. */ + for (f = 0; f < 2; f++) + if (0 <= cmp->file[f].desc) + file_block_read (&cmp->file[f], + buffer_size - cmp->file[f].buffered); + + /* If the buffers differ, the files differ. */ + if (cmp->file[0].buffered != cmp->file[1].buffered + || memcmp (cmp->file[0].buffer, + cmp->file[1].buffer, + cmp->file[0].buffered)) + { + changes = 1; + break; + } + + /* If we reach end of file, the files are the same. */ + if (cmp->file[0].buffered != buffer_size) + { + changes = 0; + break; + } + } + } + + changes = briefly_report (changes, cmp->file); + } + else + { + /* Allocate vectors for the results of comparison: + a flag for each line of each file, saying whether that line + is an insertion or deletion. + Allocate an extra element, always 0, at each end of each vector. */ + + size_t s = cmp->file[0].buffered_lines + cmp->file[1].buffered_lines + 4; + char *flag_space = zalloc (s); + cmp->file[0].changed = flag_space + 1; + cmp->file[1].changed = flag_space + cmp->file[0].buffered_lines + 3; + + /* Some lines are obviously insertions or deletions + because they don't match anything. Detect them now, and + avoid even thinking about them in the main comparison algorithm. */ + + discard_confusing_lines (cmp->file); + + /* Now do the main comparison algorithm, considering just the + undiscarded lines. */ + + xvec = cmp->file[0].undiscarded; + yvec = cmp->file[1].undiscarded; + diags = (cmp->file[0].nondiscarded_lines + + cmp->file[1].nondiscarded_lines + 3); + fdiag = xmalloc (diags * (2 * sizeof *fdiag)); + bdiag = fdiag + diags; + fdiag += cmp->file[1].nondiscarded_lines + 1; + bdiag += cmp->file[1].nondiscarded_lines + 1; + + /* Set TOO_EXPENSIVE to be approximate square root of input size, + bounded below by 256. */ + too_expensive = 1; + for (; diags != 0; diags >>= 2) + too_expensive <<= 1; + too_expensive = MAX (256, too_expensive); + + files[0] = cmp->file[0]; + files[1] = cmp->file[1]; + + compareseq (0, cmp->file[0].nondiscarded_lines, + 0, cmp->file[1].nondiscarded_lines, minimal); + + free (fdiag - (cmp->file[1].nondiscarded_lines + 1)); + + /* Modify the results slightly to make them prettier + in cases where that can validly be done. */ + + shift_boundaries (cmp->file); + + /* Get the results of comparison in the form of a chain + of `struct change's -- an edit script. */ + + if (output_style == OUTPUT_ED) + script = build_reverse_script (cmp->file); + else + script = build_script (cmp->file); + + /* Set CHANGES if we had any diffs. + If some changes are ignored, we must scan the script to decide. */ + if (ignore_blank_lines || ignore_regexp.fastmap) + { + struct change *next = script; + changes = 0; + + while (next && changes == 0) + { + struct change *this, *end; + lin first0, last0, first1, last1; + + /* Find a set of changes that belong together. */ + this = next; + end = find_change (next); + + /* Disconnect them from the rest of the changes, making them + a hunk, and remember the rest for next iteration. */ + next = end->link; + end->link = 0; + + /* Determine whether this hunk is really a difference. */ + if (analyze_hunk (this, &first0, &last0, &first1, &last1)) + changes = 1; + + /* Reconnect the script so it will all be freed properly. */ + end->link = next; + } + } + else + changes = (script != 0); + + if (brief) + changes = briefly_report (changes, cmp->file); + else + { + if (changes | !no_diff_means_no_output) + { + /* Record info for starting up output, + to be used if and when we have some output to print. */ + setup_output (file_label[0] ? file_label[0] : cmp->file[0].name, + file_label[1] ? file_label[1] : cmp->file[1].name, + cmp->parent != 0); + + switch (output_style) + { + case OUTPUT_CONTEXT: + print_context_script (script, false); + break; + + case OUTPUT_UNIFIED: + print_context_script (script, true); + break; + + case OUTPUT_ED: + print_ed_script (script); + break; + + case OUTPUT_FORWARD_ED: + pr_forward_ed_script (script); + break; + + case OUTPUT_RCS: + print_rcs_script (script); + break; + + case OUTPUT_NORMAL: + print_normal_script (script); + break; + + case OUTPUT_IFDEF: + print_ifdef_script (script); + break; + + case OUTPUT_SDIFF: + print_sdiff_script (script); + break; + + default: + abort (); + } + + finish_output (); + } + } + + free (cmp->file[0].undiscarded); + + free (flag_space); + + for (f = 0; f < 2; f++) + { + free (cmp->file[f].equivs); + free (cmp->file[f].linbuf + cmp->file[f].linbuf_base); + } + + for (e = script; e; e = p) + { + p = e->link; + free (e); + } + + if (! ROBUST_OUTPUT_STYLE (output_style)) + for (f = 0; f < 2; ++f) + if (cmp->file[f].missing_newline) + { + error (0, 0, "%s: %s\n", + file_label[f] ? file_label[f] : cmp->file[f].name, + _("No newline at end of file")); + changes = 2; + } + } + + if (cmp->file[0].buffer != cmp->file[1].buffer) + free (cmp->file[0].buffer); + free (cmp->file[1].buffer); + + return changes; +} diff --git a/contrib/diffutils-2.8/src/context.c b/contrib/diffutils-2.8/src/context.c new file mode 100644 index 0000000000..2055ff19ea --- /dev/null +++ b/contrib/diffutils-2.8/src/context.c @@ -0,0 +1,478 @@ +/* Context-format output routines for GNU DIFF. + + Copyright (C) 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1998, 2001, + 2002, 2004 Free Software Foundation, Inc. + + This file is part of GNU DIFF. + + GNU DIFF is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GNU DIFF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "diff.h" +#include + +#ifdef ST_MTIM_NSEC +# define TIMESPEC_NS(timespec) ((timespec).ST_MTIM_NSEC) +#else +# define TIMESPEC_NS(timespec) 0 +#endif + +size_t nstrftime (char *, size_t, char const *, struct tm const *, int, int); + +static char const *find_function (char const * const *, lin); +static struct change *find_hunk (struct change *); +static void mark_ignorable (struct change *); +static void pr_context_hunk (struct change *); +static void pr_unidiff_hunk (struct change *); + +/* Last place find_function started searching from. */ +static lin find_function_last_search; + +/* The value find_function returned when it started searching there. */ +static lin find_function_last_match; + +/* Print a label for a context diff, with a file name and date or a label. */ + +static void +print_context_label (char const *mark, + struct file_data *inf, + char const *label) +{ + if (label) + fprintf (outfile, "%s %s\n", mark, label); + else + { + char buf[MAX (INT_STRLEN_BOUND (int) + 32, + INT_STRLEN_BOUND (time_t) + 11)]; + struct tm const *tm = localtime (&inf->stat.st_mtime); + int nsec = TIMESPEC_NS (inf->stat.st_mtim); + if (! (tm && nstrftime (buf, sizeof buf, time_format, tm, 0, nsec))) + { + long int sec = inf->stat.st_mtime; + verify (info_preserved, sizeof inf->stat.st_mtime <= sizeof sec); + sprintf (buf, "%ld.%.9d", sec, nsec); + } + fprintf (outfile, "%s %s\t%s\n", mark, inf->name, buf); + } +} + +/* Print a header for a context diff, with the file names and dates. */ + +void +print_context_header (struct file_data inf[], bool unidiff) +{ + if (unidiff) + { + print_context_label ("---", &inf[0], file_label[0]); + print_context_label ("+++", &inf[1], file_label[1]); + } + else + { + print_context_label ("***", &inf[0], file_label[0]); + print_context_label ("---", &inf[1], file_label[1]); + } +} + +/* Print an edit script in context format. */ + +void +print_context_script (struct change *script, bool unidiff) +{ + if (ignore_blank_lines || ignore_regexp.fastmap) + mark_ignorable (script); + else + { + struct change *e; + for (e = script; e; e = e->link) + e->ignore = false; + } + + find_function_last_search = - files[0].prefix_lines; + find_function_last_match = LIN_MAX; + + if (unidiff) + print_script (script, find_hunk, pr_unidiff_hunk); + else + print_script (script, find_hunk, pr_context_hunk); +} + +/* Print a pair of line numbers with a comma, translated for file FILE. + If the second number is not greater, use the first in place of it. + + Args A and B are internal line numbers. + We print the translated (real) line numbers. */ + +static void +print_context_number_range (struct file_data const *file, lin a, lin b) +{ + long int trans_a, trans_b; + translate_range (file, a, b, &trans_a, &trans_b); + + /* We can have B <= A in the case of a range of no lines. + In this case, we should print the line number before the range, + which is B. + + POSIX 1003.1-2001 requires two line numbers separated by a comma + even if the line numbers are the same. However, this does not + match existing practice and is surely an error in the + specification. */ + + if (trans_b <= trans_a) + fprintf (outfile, "%ld", trans_b); + else + fprintf (outfile, "%ld,%ld", trans_a, trans_b); +} + +/* Print FUNCTION in a context header. */ +static void +print_context_function (FILE *out, char const *function) +{ + int i; + putc (' ', out); + for (i = 0; i < 40 && function[i] != '\n'; i++) + continue; + fwrite (function, sizeof (char), i, out); +} + +/* Print a portion of an edit script in context format. + HUNK is the beginning of the portion to be printed. + The end is marked by a `link' that has been nulled out. + + Prints out lines from both files, and precedes each + line with the appropriate flag-character. */ + +static void +pr_context_hunk (struct change *hunk) +{ + lin first0, last0, first1, last1, i; + char const *prefix; + char const *function; + FILE *out; + + /* Determine range of line numbers involved in each file. */ + + enum changes changes = analyze_hunk (hunk, &first0, &last0, &first1, &last1); + if (! changes) + return; + + /* Include a context's width before and after. */ + + i = - files[0].prefix_lines; + first0 = MAX (first0 - context, i); + first1 = MAX (first1 - context, i); + if (last0 < files[0].valid_lines - context) + last0 += context; + else + last0 = files[0].valid_lines - 1; + if (last1 < files[1].valid_lines - context) + last1 += context; + else + last1 = files[1].valid_lines - 1; + + /* If desired, find the preceding function definition line in file 0. */ + function = 0; + if (function_regexp.fastmap) + function = find_function (files[0].linbuf, first0); + + begin_output (); + out = outfile; + + fprintf (out, "***************"); + + if (function) + print_context_function (out, function); + + fprintf (out, "\n*** "); + print_context_number_range (&files[0], first0, last0); + fprintf (out, " ****\n"); + + if (changes & OLD) + { + struct change *next = hunk; + + for (i = first0; i <= last0; i++) + { + /* Skip past changes that apply (in file 0) + only to lines before line I. */ + + while (next && next->line0 + next->deleted <= i) + next = next->link; + + /* Compute the marking for line I. */ + + prefix = " "; + if (next && next->line0 <= i) + /* The change NEXT covers this line. + If lines were inserted here in file 1, this is "changed". + Otherwise it is "deleted". */ + prefix = (next->inserted > 0 ? "!" : "-"); + + print_1_line (prefix, &files[0].linbuf[i]); + } + } + + fprintf (out, "--- "); + print_context_number_range (&files[1], first1, last1); + fprintf (out, " ----\n"); + + if (changes & NEW) + { + struct change *next = hunk; + + for (i = first1; i <= last1; i++) + { + /* Skip past changes that apply (in file 1) + only to lines before line I. */ + + while (next && next->line1 + next->inserted <= i) + next = next->link; + + /* Compute the marking for line I. */ + + prefix = " "; + if (next && next->line1 <= i) + /* The change NEXT covers this line. + If lines were deleted here in file 0, this is "changed". + Otherwise it is "inserted". */ + prefix = (next->deleted > 0 ? "!" : "+"); + + print_1_line (prefix, &files[1].linbuf[i]); + } + } +} + +/* Print a pair of line numbers with a comma, translated for file FILE. + If the second number is smaller, use the first in place of it. + If the numbers are equal, print just one number. + + Args A and B are internal line numbers. + We print the translated (real) line numbers. */ + +static void +print_unidiff_number_range (struct file_data const *file, lin a, lin b) +{ + long int trans_a, trans_b; + translate_range (file, a, b, &trans_a, &trans_b); + + /* We can have B < A in the case of a range of no lines. + In this case, we print the line number before the range, + which is B. It would be more logical to print A, but + 'patch' expects B in order to detect diffs against empty files. */ + if (trans_b <= trans_a) + fprintf (outfile, trans_b < trans_a ? "%ld,0" : "%ld", trans_b); + else + fprintf (outfile, "%ld,%ld", trans_a, trans_b - trans_a + 1); +} + +/* Print a portion of an edit script in unidiff format. + HUNK is the beginning of the portion to be printed. + The end is marked by a `link' that has been nulled out. + + Prints out lines from both files, and precedes each + line with the appropriate flag-character. */ + +static void +pr_unidiff_hunk (struct change *hunk) +{ + lin first0, last0, first1, last1; + lin i, j, k; + struct change *next; + char const *function; + FILE *out; + + /* Determine range of line numbers involved in each file. */ + + if (! analyze_hunk (hunk, &first0, &last0, &first1, &last1)) + return; + + /* Include a context's width before and after. */ + + i = - files[0].prefix_lines; + first0 = MAX (first0 - context, i); + first1 = MAX (first1 - context, i); + if (last0 < files[0].valid_lines - context) + last0 += context; + else + last0 = files[0].valid_lines - 1; + if (last1 < files[1].valid_lines - context) + last1 += context; + else + last1 = files[1].valid_lines - 1; + + /* If desired, find the preceding function definition line in file 0. */ + function = 0; + if (function_regexp.fastmap) + function = find_function (files[0].linbuf, first0); + + begin_output (); + out = outfile; + + fprintf (out, "@@ -"); + print_unidiff_number_range (&files[0], first0, last0); + fprintf (out, " +"); + print_unidiff_number_range (&files[1], first1, last1); + fprintf (out, " @@"); + + if (function) + print_context_function (out, function); + + putc ('\n', out); + + next = hunk; + i = first0; + j = first1; + + while (i <= last0 || j <= last1) + { + + /* If the line isn't a difference, output the context from file 0. */ + + if (!next || i < next->line0) + { + putc (initial_tab ? '\t' : ' ', out); + print_1_line (0, &files[0].linbuf[i++]); + j++; + } + else + { + /* For each difference, first output the deleted part. */ + + k = next->deleted; + while (k--) + { + putc ('-', out); + if (initial_tab) + putc ('\t', out); + print_1_line (0, &files[0].linbuf[i++]); + } + + /* Then output the inserted part. */ + + k = next->inserted; + while (k--) + { + putc ('+', out); + if (initial_tab) + putc ('\t', out); + print_1_line (0, &files[1].linbuf[j++]); + } + + /* We're done with this hunk, so on to the next! */ + + next = next->link; + } + } +} + +/* Scan a (forward-ordered) edit script for the first place that more than + 2*CONTEXT unchanged lines appear, and return a pointer + to the `struct change' for the last change before those lines. */ + +static struct change * +find_hunk (struct change *start) +{ + struct change *prev; + lin top0, top1; + lin thresh; + + /* Threshold distance is 2 * CONTEXT + 1 between two non-ignorable + changes, but only CONTEXT if one is ignorable. Watch out for + integer overflow, though. */ + lin non_ignorable_threshold = + (LIN_MAX - 1) / 2 < context ? LIN_MAX : 2 * context + 1; + lin ignorable_threshold = context; + + do + { + /* Compute number of first line in each file beyond this changed. */ + top0 = start->line0 + start->deleted; + top1 = start->line1 + start->inserted; + prev = start; + start = start->link; + thresh = (prev->ignore || (start && start->ignore) + ? ignorable_threshold + : non_ignorable_threshold); + /* It is not supposed to matter which file we check in the end-test. + If it would matter, crash. */ + if (start && start->line0 - top0 != start->line1 - top1) + abort (); + } while (start + /* Keep going if less than THRESH lines + elapse before the affected line. */ + && start->line0 - top0 < thresh); + + return prev; +} + +/* Set the `ignore' flag properly in each change in SCRIPT. + It should be 1 if all the lines inserted or deleted in that change + are ignorable lines. */ + +static void +mark_ignorable (struct change *script) +{ + while (script) + { + struct change *next = script->link; + lin first0, last0, first1, last1; + + /* Turn this change into a hunk: detach it from the others. */ + script->link = 0; + + /* Determine whether this change is ignorable. */ + script->ignore = ! analyze_hunk (script, + &first0, &last0, &first1, &last1); + + /* Reconnect the chain as before. */ + script->link = next; + + /* Advance to the following change. */ + script = next; + } +} + +/* Find the last function-header line in LINBUF prior to line number LINENUM. + This is a line containing a match for the regexp in `function_regexp'. + Return the address of the text, or 0 if no function-header is found. */ + +static char const * +find_function (char const * const *linbuf, lin linenum) +{ + lin i = linenum; + lin last = find_function_last_search; + find_function_last_search = i; + + while (last <= --i) + { + /* See if this line is what we want. */ + char const *line = linbuf[i]; + size_t linelen = linbuf[i + 1] - line - 1; + + /* FIXME: re_search's size args should be size_t, not int. */ + int len = MIN (linelen, INT_MAX); + + if (0 <= re_search (&function_regexp, line, len, 0, len, 0)) + { + find_function_last_match = i; + return line; + } + } + /* If we search back to where we started searching the previous time, + find the line we found last time. */ + if (find_function_last_match != LIN_MAX) + return linbuf[find_function_last_match]; + + return 0; +} diff --git a/contrib/diffutils-2.8/src/diff.c b/contrib/diffutils-2.8/src/diff.c new file mode 100644 index 0000000000..a975107657 --- /dev/null +++ b/contrib/diffutils-2.8/src/diff.c @@ -0,0 +1,1353 @@ +/* diff - compare files line by line + + Copyright (C) 1988, 1989, 1992, 1993, 1994, 1996, 1998, 2001, 2002, + 2004 Free Software Foundation, Inc. + + This file is part of GNU DIFF. + + GNU DIFF is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GNU DIFF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNU DIFF; see the file COPYING. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#define GDIFF_MAIN +#include "diff.h" +#include "paths.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef GUTTER_WIDTH_MINIMUM +# define GUTTER_WIDTH_MINIMUM 3 +#endif + +struct regexp_list +{ + char *regexps; /* chars representing disjunction of the regexps */ + size_t len; /* chars used in `regexps' */ + size_t size; /* size malloc'ed for `regexps'; 0 if not malloc'ed */ + bool multiple_regexps;/* Does `regexps' represent a disjunction? */ + struct re_pattern_buffer *buf; +}; + +static int compare_files (struct comparison const *, char const *, char const *); +static void add_regexp (struct regexp_list *, char const *); +static void summarize_regexp_list (struct regexp_list *); +static void specify_style (enum output_style); +static void specify_value (char const **, char const *, char const *); +static void try_help (char const *, char const *) __attribute__((noreturn)); +static void check_stdout (void); +static void usage (void); + +/* If comparing directories, compare their common subdirectories + recursively. */ +static bool recursive; + +/* In context diffs, show previous lines that match these regexps. */ +static struct regexp_list function_regexp_list; + +/* Ignore changes affecting only lines that match these regexps. */ +static struct regexp_list ignore_regexp_list; + +#if HAVE_SETMODE_DOS +/* Use binary I/O when reading and writing data (--binary). + On POSIX hosts, this has no effect. */ +static bool binary; +#else +enum { binary = true }; +#endif + +/* When comparing directories, if a file appears only in one + directory, treat it as present but empty in the other (-N). + Then `patch' would create the file with appropriate contents. */ +static bool new_file; + +/* When comparing directories, if a file appears only in the second + directory of the two, treat it as present but empty in the other + (--unidirectional-new-file). + Then `patch' would create the file with appropriate contents. */ +static bool unidirectional_new_file; + +/* Report files compared that are the same (-s). + Normally nothing is output when that happens. */ +static bool report_identical_files; + + +/* Return a string containing the command options with which diff was invoked. + Spaces appear between what were separate ARGV-elements. + There is a space at the beginning but none at the end. + If there were no options, the result is an empty string. + + Arguments: OPTIONVEC, a vector containing separate ARGV-elements, and COUNT, + the length of that vector. */ + +static char * +option_list (char **optionvec, int count) +{ + int i; + size_t size = 1; + char *result; + char *p; + + for (i = 0; i < count; i++) + size += 1 + quote_system_arg ((char *) 0, optionvec[i]); + + p = result = xmalloc (size); + + for (i = 0; i < count; i++) + { + *p++ = ' '; + p += quote_system_arg (p, optionvec[i]); + } + + *p = 0; + return result; +} + + +/* Return an option value suitable for add_exclude. */ + +static int +exclude_options (void) +{ + return EXCLUDE_WILDCARDS | (ignore_file_name_case ? FNM_CASEFOLD : 0); +} + +static char const shortopts[] = +"0123456789abBcC:dD:eEfF:hHiI:lL:nNpPqrsS:tTuU:vwW:x:X:y"; + +/* Values for long options that do not have single-letter equivalents. */ +enum +{ + BINARY_OPTION = CHAR_MAX + 1, + FROM_FILE_OPTION, + HELP_OPTION, + HORIZON_LINES_OPTION, + IGNORE_FILE_NAME_CASE_OPTION, + INHIBIT_HUNK_MERGE_OPTION, + LEFT_COLUMN_OPTION, + LINE_FORMAT_OPTION, + NO_IGNORE_FILE_NAME_CASE_OPTION, + NORMAL_OPTION, + SDIFF_MERGE_ASSIST_OPTION, + STRIP_TRAILING_CR_OPTION, + SUPPRESS_COMMON_LINES_OPTION, + TABSIZE_OPTION, + TO_FILE_OPTION, + + /* These options must be in sequence. */ + UNCHANGED_LINE_FORMAT_OPTION, + OLD_LINE_FORMAT_OPTION, + NEW_LINE_FORMAT_OPTION, + + /* These options must be in sequence. */ + UNCHANGED_GROUP_FORMAT_OPTION, + OLD_GROUP_FORMAT_OPTION, + NEW_GROUP_FORMAT_OPTION, + CHANGED_GROUP_FORMAT_OPTION +}; + +static char const group_format_option[][sizeof "--unchanged-group-format"] = + { + "--unchanged-group-format", + "--old-group-format", + "--new-group-format", + "--changed-group-format" + }; + +static char const line_format_option[][sizeof "--unchanged-line-format"] = + { + "--unchanged-line-format", + "--old-line-format", + "--new-line-format" + }; + +static struct option const longopts[] = +{ + {"binary", 0, 0, BINARY_OPTION}, + {"brief", 0, 0, 'q'}, + {"changed-group-format", 1, 0, CHANGED_GROUP_FORMAT_OPTION}, + {"context", 2, 0, 'C'}, + {"ed", 0, 0, 'e'}, + {"exclude", 1, 0, 'x'}, + {"exclude-from", 1, 0, 'X'}, + {"expand-tabs", 0, 0, 't'}, + {"forward-ed", 0, 0, 'f'}, + {"from-file", 1, 0, FROM_FILE_OPTION}, + {"help", 0, 0, HELP_OPTION}, + {"horizon-lines", 1, 0, HORIZON_LINES_OPTION}, + {"ifdef", 1, 0, 'D'}, + {"ignore-all-space", 0, 0, 'w'}, + {"ignore-blank-lines", 0, 0, 'B'}, + {"ignore-case", 0, 0, 'i'}, + {"ignore-file-name-case", 0, 0, IGNORE_FILE_NAME_CASE_OPTION}, + {"ignore-matching-lines", 1, 0, 'I'}, + {"ignore-space-change", 0, 0, 'b'}, + {"ignore-tab-expansion", 0, 0, 'E'}, + {"inhibit-hunk-merge", 0, 0, INHIBIT_HUNK_MERGE_OPTION}, + {"initial-tab", 0, 0, 'T'}, + {"label", 1, 0, 'L'}, + {"left-column", 0, 0, LEFT_COLUMN_OPTION}, + {"line-format", 1, 0, LINE_FORMAT_OPTION}, + {"minimal", 0, 0, 'd'}, + {"new-file", 0, 0, 'N'}, + {"new-group-format", 1, 0, NEW_GROUP_FORMAT_OPTION}, + {"new-line-format", 1, 0, NEW_LINE_FORMAT_OPTION}, + {"no-ignore-file-name-case", 0, 0, NO_IGNORE_FILE_NAME_CASE_OPTION}, + {"normal", 0, 0, NORMAL_OPTION}, + {"old-group-format", 1, 0, OLD_GROUP_FORMAT_OPTION}, + {"old-line-format", 1, 0, OLD_LINE_FORMAT_OPTION}, + {"paginate", 0, 0, 'l'}, + {"rcs", 0, 0, 'n'}, + {"recursive", 0, 0, 'r'}, + {"report-identical-files", 0, 0, 's'}, + {"sdiff-merge-assist", 0, 0, SDIFF_MERGE_ASSIST_OPTION}, + {"show-c-function", 0, 0, 'p'}, + {"show-function-line", 1, 0, 'F'}, + {"side-by-side", 0, 0, 'y'}, + {"speed-large-files", 0, 0, 'H'}, + {"starting-file", 1, 0, 'S'}, + {"strip-trailing-cr", 0, 0, STRIP_TRAILING_CR_OPTION}, + {"suppress-common-lines", 0, 0, SUPPRESS_COMMON_LINES_OPTION}, + {"tabsize", 1, 0, TABSIZE_OPTION}, + {"text", 0, 0, 'a'}, + {"to-file", 1, 0, TO_FILE_OPTION}, + {"unchanged-group-format", 1, 0, UNCHANGED_GROUP_FORMAT_OPTION}, + {"unchanged-line-format", 1, 0, UNCHANGED_LINE_FORMAT_OPTION}, + {"unidirectional-new-file", 0, 0, 'P'}, + {"unified", 2, 0, 'U'}, + {"version", 0, 0, 'v'}, + {"width", 1, 0, 'W'}, + {0, 0, 0, 0} +}; + +int +main (int argc, char **argv) +{ + int exit_status = EXIT_SUCCESS; + int c; + int i; + int prev = -1; + lin ocontext = -1; + bool explicit_context = false; + size_t width = 0; + bool show_c_function = false; + char const *from_file = 0; + char const *to_file = 0; + uintmax_t numval; + char *numend; + + /* Do our initializations. */ + exit_failure = 2; + initialize_main (&argc, &argv); + program_name = argv[0]; + setlocale (LC_ALL, ""); + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + c_stack_action (0); + function_regexp_list.buf = &function_regexp; + ignore_regexp_list.buf = &ignore_regexp; + re_set_syntax (RE_SYNTAX_GREP | RE_NO_POSIX_BACKTRACKING); + excluded = new_exclude (); + + /* Decode the options. */ + + while ((c = getopt_long (argc, argv, shortopts, longopts, 0)) != -1) + { + switch (c) + { + case 0: + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (! ISDIGIT (prev)) + ocontext = c - '0'; + else if (LIN_MAX / 10 < ocontext + || ((ocontext = 10 * ocontext + c - '0') < 0)) + ocontext = LIN_MAX; + break; + + case 'a': + text = true; + break; + + case 'b': + if (ignore_white_space < IGNORE_SPACE_CHANGE) + ignore_white_space = IGNORE_SPACE_CHANGE; + break; + + case 'B': + ignore_blank_lines = true; + break; + + case 'C': + case 'U': + { + if (optarg) + { + numval = strtoumax (optarg, &numend, 10); + if (*numend) + try_help ("invalid context length `%s'", optarg); + if (LIN_MAX < numval) + numval = LIN_MAX; + } + else + numval = 3; + + specify_style (c == 'U' ? OUTPUT_UNIFIED : OUTPUT_CONTEXT); + if (context < numval) + context = numval; + explicit_context = true; + } + break; + + case 'c': + specify_style (OUTPUT_CONTEXT); + if (context < 3) + context = 3; + break; + + case 'd': + minimal = true; + break; + + case 'D': + specify_style (OUTPUT_IFDEF); + { + static char const C_ifdef_group_formats[] = + "%%=%c#ifndef %s\n%%<#endif /* ! %s */\n%c#ifdef %s\n%%>#endif /* %s */\n%c#ifndef %s\n%%<#else /* %s */\n%%>#endif /* %s */\n"; + char *b = xmalloc (sizeof C_ifdef_group_formats + + 7 * strlen (optarg) - 14 /* 7*"%s" */ + - 8 /* 5*"%%" + 3*"%c" */); + sprintf (b, C_ifdef_group_formats, + 0, + optarg, optarg, 0, + optarg, optarg, 0, + optarg, optarg, optarg); + for (i = 0; i < sizeof group_format / sizeof *group_format; i++) + { + specify_value (&group_format[i], b, "-D"); + b += strlen (b) + 1; + } + } + break; + + case 'e': + specify_style (OUTPUT_ED); + break; + + case 'E': + if (ignore_white_space < IGNORE_TAB_EXPANSION) + ignore_white_space = IGNORE_TAB_EXPANSION; + break; + + case 'f': + specify_style (OUTPUT_FORWARD_ED); + break; + + case 'F': + add_regexp (&function_regexp_list, optarg); + break; + + case 'h': + /* Split the files into chunks for faster processing. + Usually does not change the result. + + This currently has no effect. */ + break; + + case 'H': + speed_large_files = true; + break; + + case 'i': + ignore_case = true; + break; + + case 'I': + add_regexp (&ignore_regexp_list, optarg); + break; + + case 'l': + if (!pr_program[0]) + try_help ("pagination not supported on this host", 0); + paginate = true; +#ifdef SIGCHLD + /* Pagination requires forking and waiting, and + System V fork+wait does not work if SIGCHLD is ignored. */ + signal (SIGCHLD, SIG_DFL); +#endif + break; + + case 'L': + if (!file_label[0]) + file_label[0] = optarg; + else if (!file_label[1]) + file_label[1] = optarg; + else + fatal ("too many file label options"); + break; + + case 'n': + specify_style (OUTPUT_RCS); + break; + + case 'N': + new_file = true; + break; + + case 'p': + show_c_function = true; + add_regexp (&function_regexp_list, "^[[:alpha:]$_]"); + break; + + case 'P': + unidirectional_new_file = true; + break; + + case 'q': + brief = true; + break; + + case 'r': + recursive = true; + break; + + case 's': + report_identical_files = true; + break; + + case 'S': + specify_value (&starting_file, optarg, "-S"); + break; + + case 't': + expand_tabs = true; + break; + + case 'T': + initial_tab = true; + break; + + case 'u': + specify_style (OUTPUT_UNIFIED); + if (context < 3) + context = 3; + break; + + case 'v': + version_etc (stdout, "diff", PACKAGE_NAME, PACKAGE_VERSION, + "Paul Eggert", "Mike Haertel", "David Hayes", + "Richard Stallman", "Len Tower", (char *) 0); + check_stdout (); + return EXIT_SUCCESS; + + case 'w': + ignore_white_space = IGNORE_ALL_SPACE; + break; + + case 'x': + add_exclude (excluded, optarg, exclude_options ()); + break; + + case 'X': + if (add_exclude_file (add_exclude, excluded, optarg, + exclude_options (), '\n')) + pfatal_with_name (optarg); + break; + + case 'y': + specify_style (OUTPUT_SDIFF); + break; + + case 'W': + numval = strtoumax (optarg, &numend, 10); + if (! (0 < numval && numval <= SIZE_MAX) || *numend) + try_help ("invalid width `%s'", optarg); + if (width != numval) + { + if (width) + fatal ("conflicting width options"); + width = numval; + } + break; + + case BINARY_OPTION: +#if HAVE_SETMODE_DOS + binary = true; + set_binary_mode (STDOUT_FILENO, true); +#endif + break; + + case FROM_FILE_OPTION: + specify_value (&from_file, optarg, "--from-file"); + break; + + case HELP_OPTION: + usage (); + check_stdout (); + return EXIT_SUCCESS; + + case HORIZON_LINES_OPTION: + numval = strtoumax (optarg, &numend, 10); + if (*numend) + try_help ("invalid horizon length `%s'", optarg); + horizon_lines = MAX (horizon_lines, MIN (numval, LIN_MAX)); + break; + + case IGNORE_FILE_NAME_CASE_OPTION: + ignore_file_name_case = true; + break; + + case INHIBIT_HUNK_MERGE_OPTION: + /* This option is obsolete, but accept it for backward + compatibility. */ + break; + + case LEFT_COLUMN_OPTION: + left_column = true; + break; + + case LINE_FORMAT_OPTION: + specify_style (OUTPUT_IFDEF); + for (i = 0; i < sizeof line_format / sizeof *line_format; i++) + specify_value (&line_format[i], optarg, "--line-format"); + break; + + case NO_IGNORE_FILE_NAME_CASE_OPTION: + ignore_file_name_case = false; + break; + + case NORMAL_OPTION: + specify_style (OUTPUT_NORMAL); + break; + + case SDIFF_MERGE_ASSIST_OPTION: + specify_style (OUTPUT_SDIFF); + sdiff_merge_assist = true; + break; + + case STRIP_TRAILING_CR_OPTION: + strip_trailing_cr = true; + break; + + case SUPPRESS_COMMON_LINES_OPTION: + suppress_common_lines = true; + break; + + case TABSIZE_OPTION: + numval = strtoumax (optarg, &numend, 10); + if (! (0 < numval && numval <= SIZE_MAX) || *numend) + try_help ("invalid tabsize `%s'", optarg); + if (tabsize != numval) + { + if (tabsize) + fatal ("conflicting tabsize options"); + tabsize = numval; + } + break; + + case TO_FILE_OPTION: + specify_value (&to_file, optarg, "--to-file"); + break; + + case UNCHANGED_LINE_FORMAT_OPTION: + case OLD_LINE_FORMAT_OPTION: + case NEW_LINE_FORMAT_OPTION: + specify_style (OUTPUT_IFDEF); + c -= UNCHANGED_LINE_FORMAT_OPTION; + specify_value (&line_format[c], optarg, line_format_option[c]); + break; + + case UNCHANGED_GROUP_FORMAT_OPTION: + case OLD_GROUP_FORMAT_OPTION: + case NEW_GROUP_FORMAT_OPTION: + case CHANGED_GROUP_FORMAT_OPTION: + specify_style (OUTPUT_IFDEF); + c -= UNCHANGED_GROUP_FORMAT_OPTION; + specify_value (&group_format[c], optarg, group_format_option[c]); + break; + + default: + try_help (0, 0); + } + prev = c; + } + + if (output_style == OUTPUT_UNSPECIFIED) + { + if (show_c_function) + { + specify_style (OUTPUT_CONTEXT); + if (ocontext < 0) + context = 3; + } + else + specify_style (OUTPUT_NORMAL); + } + + if (output_style != OUTPUT_CONTEXT || hard_locale (LC_TIME)) + { +#ifdef ST_MTIM_NSEC + time_format = "%Y-%m-%d %H:%M:%S.%N %z"; +#else + time_format = "%Y-%m-%d %H:%M:%S %z"; +#endif + } + else + { + /* See POSIX 1003.1-2001 for this format. */ + time_format = "%a %b %e %T %Y"; + } + + if (0 <= ocontext) + { + bool modern_usage = 200112 <= posix2_version (); + + if ((output_style == OUTPUT_CONTEXT + || output_style == OUTPUT_UNIFIED) + && (context < ocontext + || (ocontext < context && ! explicit_context))) + { + if (modern_usage) + { + error (0, 0, + _("`-%ld' option is obsolete; use `-%c %ld'"), + (long int) ocontext, + output_style == OUTPUT_CONTEXT ? 'C' : 'U', + (long int) ocontext); + try_help (0, 0); + } + context = ocontext; + } + else + { + if (modern_usage) + { + error (0, 0, _("`-%ld' option is obsolete; omit it"), + (long int) ocontext); + try_help (0, 0); + } + } + } + + if (! tabsize) + tabsize = 8; + if (! width) + width = 130; + + { + /* Maximize first the half line width, and then the gutter width, + according to the following constraints: + + 1. Two half lines plus a gutter must fit in a line. + 2. If the half line width is nonzero: + a. The gutter width is at least GUTTER_WIDTH_MINIMUM. + b. If tabs are not expanded to spaces, + a half line plus a gutter is an integral number of tabs, + so that tabs in the right column line up. */ + + intmax_t t = expand_tabs ? 1 : tabsize; + intmax_t w = width; + intmax_t off = (w + t + GUTTER_WIDTH_MINIMUM) / (2 * t) * t; + sdiff_half_width = MAX (0, MIN (off - GUTTER_WIDTH_MINIMUM, w - off)), + sdiff_column2_offset = sdiff_half_width ? off : w; + } + + /* Make the horizon at least as large as the context, so that + shift_boundaries has more freedom to shift the first and last hunks. */ + if (horizon_lines < context) + horizon_lines = context; + + summarize_regexp_list (&function_regexp_list); + summarize_regexp_list (&ignore_regexp_list); + + if (output_style == OUTPUT_IFDEF) + { + for (i = 0; i < sizeof line_format / sizeof *line_format; i++) + if (!line_format[i]) + line_format[i] = "%l\n"; + if (!group_format[OLD]) + group_format[OLD] + = group_format[CHANGED] ? group_format[CHANGED] : "%<"; + if (!group_format[NEW]) + group_format[NEW] + = group_format[CHANGED] ? group_format[CHANGED] : "%>"; + if (!group_format[UNCHANGED]) + group_format[UNCHANGED] = "%="; + if (!group_format[CHANGED]) + group_format[CHANGED] = concat (group_format[OLD], + group_format[NEW], ""); + } + + no_diff_means_no_output = + (output_style == OUTPUT_IFDEF ? + (!*group_format[UNCHANGED] + || (strcmp (group_format[UNCHANGED], "%=") == 0 + && !*line_format[UNCHANGED])) + : (output_style != OUTPUT_SDIFF) | suppress_common_lines); + + files_can_be_treated_as_binary = + (brief & binary + & ~ (ignore_blank_lines | ignore_case | strip_trailing_cr + | (ignore_regexp_list.regexps || ignore_white_space))); + + switch_string = option_list (argv + 1, optind - 1); + + if (from_file) + { + if (to_file) + fatal ("--from-file and --to-file both specified"); + else + for (; optind < argc; optind++) + { + int status = compare_files ((struct comparison *) 0, + from_file, argv[optind]); + if (exit_status < status) + exit_status = status; + } + } + else + { + if (to_file) + for (; optind < argc; optind++) + { + int status = compare_files ((struct comparison *) 0, + argv[optind], to_file); + if (exit_status < status) + exit_status = status; + } + else + { + if (argc - optind != 2) + { + if (argc - optind < 2) + try_help ("missing operand after `%s'", argv[argc - 1]); + else + try_help ("extra operand `%s'", argv[optind + 2]); + } + + exit_status = compare_files ((struct comparison *) 0, + argv[optind], argv[optind + 1]); + } + } + + /* Print any messages that were saved up for last. */ + print_message_queue (); + + check_stdout (); + exit (exit_status); + return exit_status; +} + +/* Append to REGLIST the regexp PATTERN. */ + +static void +add_regexp (struct regexp_list *reglist, char const *pattern) +{ + size_t patlen = strlen (pattern); + char const *m = re_compile_pattern (pattern, patlen, reglist->buf); + + if (m != 0) + error (0, 0, "%s: %s", pattern, m); + else + { + char *regexps = reglist->regexps; + size_t len = reglist->len; + bool multiple_regexps = reglist->multiple_regexps = regexps != 0; + size_t newlen = reglist->len = len + 2 * multiple_regexps + patlen; + size_t size = reglist->size; + + if (size <= newlen) + { + if (!size) + size = 1; + + do size *= 2; + while (size <= newlen); + + reglist->size = size; + reglist->regexps = regexps = xrealloc (regexps, size); + } + if (multiple_regexps) + { + regexps[len++] = '\\'; + regexps[len++] = '|'; + } + memcpy (regexps + len, pattern, patlen + 1); + } +} + +/* Ensure that REGLIST represents the disjunction of its regexps. + This is done here, rather than earlier, to avoid O(N^2) behavior. */ + +static void +summarize_regexp_list (struct regexp_list *reglist) +{ + if (reglist->regexps) + { + /* At least one regexp was specified. Allocate a fastmap for it. */ + reglist->buf->fastmap = xmalloc (1 << CHAR_BIT); + if (reglist->multiple_regexps) + { + /* Compile the disjunction of the regexps. + (If just one regexp was specified, it is already compiled.) */ + char const *m = re_compile_pattern (reglist->regexps, reglist->len, + reglist->buf); + if (m != 0) + error (EXIT_TROUBLE, 0, "%s: %s", reglist->regexps, m); + } + } +} + +static void +try_help (char const *reason_msgid, char const *operand) +{ + if (reason_msgid) + error (0, 0, _(reason_msgid), operand); + error (EXIT_TROUBLE, 0, _("Try `%s --help' for more information."), + program_name); + abort (); +} + +static void +check_stdout (void) +{ + if (ferror (stdout)) + fatal ("write failed"); + else if (fclose (stdout) != 0) + pfatal_with_name (_("standard output")); +} + +static char const * const option_help_msgid[] = { + N_("Compare files line by line."), + "", + N_("-i --ignore-case Ignore case differences in file contents."), + N_("--ignore-file-name-case Ignore case when comparing file names."), + N_("--no-ignore-file-name-case Consider case when comparing file names."), + N_("-E --ignore-tab-expansion Ignore changes due to tab expansion."), + N_("-b --ignore-space-change Ignore changes in the amount of white space."), + N_("-w --ignore-all-space Ignore all white space."), + N_("-B --ignore-blank-lines Ignore changes whose lines are all blank."), + N_("-I RE --ignore-matching-lines=RE Ignore changes whose lines all match RE."), + N_("--strip-trailing-cr Strip trailing carriage return on input."), +#if HAVE_SETMODE_DOS + N_("--binary Read and write data in binary mode."), +#endif + N_("-a --text Treat all files as text."), + "", + N_("-c -C NUM --context[=NUM] Output NUM (default 3) lines of copied context.\n\ +-u -U NUM --unified[=NUM] Output NUM (default 3) lines of unified context.\n\ + --label LABEL Use LABEL instead of file name.\n\ + -p --show-c-function Show which C function each change is in.\n\ + -F RE --show-function-line=RE Show the most recent line matching RE."), + N_("-q --brief Output only whether files differ."), + N_("-e --ed Output an ed script."), + N_("--normal Output a normal diff."), + N_("-n --rcs Output an RCS format diff."), + N_("-y --side-by-side Output in two columns.\n\ + -W NUM --width=NUM Output at most NUM (default 130) print columns.\n\ + --left-column Output only the left column of common lines.\n\ + --suppress-common-lines Do not output common lines."), + N_("-D NAME --ifdef=NAME Output merged file to show `#ifdef NAME' diffs."), + N_("--GTYPE-group-format=GFMT Similar, but format GTYPE input groups with GFMT."), + N_("--line-format=LFMT Similar, but format all input lines with LFMT."), + N_("--LTYPE-line-format=LFMT Similar, but format LTYPE input lines with LFMT."), + N_(" LTYPE is `old', `new', or `unchanged'. GTYPE is LTYPE or `changed'."), + N_(" GFMT may contain:\n\ + %< lines from FILE1\n\ + %> lines from FILE2\n\ + %= lines common to FILE1 and FILE2\n\ + %[-][WIDTH][.[PREC]]{doxX}LETTER printf-style spec for LETTER\n\ + LETTERs are as follows for new group, lower case for old group:\n\ + F first line number\n\ + L last line number\n\ + N number of lines = L-F+1\n\ + E F-1\n\ + M L+1"), + N_(" LFMT may contain:\n\ + %L contents of line\n\ + %l contents of line, excluding any trailing newline\n\ + %[-][WIDTH][.[PREC]]{doxX}n printf-style spec for input line number"), + N_(" Either GFMT or LFMT may contain:\n\ + %% %\n\ + %c'C' the single character C\n\ + %c'\\OOO' the character with octal code OOO"), + "", + N_("-l --paginate Pass the output through `pr' to paginate it."), + N_("-t --expand-tabs Expand tabs to spaces in output."), + N_("-T --initial-tab Make tabs line up by prepending a tab."), + N_("--tabsize=NUM Tab stops are every NUM (default 8) print columns."), + "", + N_("-r --recursive Recursively compare any subdirectories found."), + N_("-N --new-file Treat absent files as empty."), + N_("--unidirectional-new-file Treat absent first files as empty."), + N_("-s --report-identical-files Report when two files are the same."), + N_("-x PAT --exclude=PAT Exclude files that match PAT."), + N_("-X FILE --exclude-from=FILE Exclude files that match any pattern in FILE."), + N_("-S FILE --starting-file=FILE Start with FILE when comparing directories."), + N_("--from-file=FILE1 Compare FILE1 to all operands. FILE1 can be a directory."), + N_("--to-file=FILE2 Compare all operands to FILE2. FILE2 can be a directory."), + "", + N_("--horizon-lines=NUM Keep NUM lines of the common prefix and suffix."), + N_("-d --minimal Try hard to find a smaller set of changes."), + N_("--speed-large-files Assume large files and many scattered small changes."), + "", + N_("-v --version Output version info."), + N_("--help Output this help."), + "", + N_("FILES are `FILE1 FILE2' or `DIR1 DIR2' or `DIR FILE...' or `FILE... DIR'."), + N_("If --from-file or --to-file is given, there are no restrictions on FILES."), + N_("If a FILE is `-', read standard input."), + N_("Exit status is 0 if inputs are the same, 1 if different, 2 if trouble."), + "", + N_("Report bugs to ."), + 0 +}; + +static void +usage (void) +{ + char const * const *p; + + printf (_("Usage: %s [OPTION]... FILES\n"), program_name); + + for (p = option_help_msgid; *p; p++) + { + if (!**p) + putchar ('\n'); + else + { + char const *msg = _(*p); + char const *nl; + while ((nl = strchr (msg, '\n'))) + { + int msglen = nl + 1 - msg; + printf (" %.*s", msglen, msg); + msg = nl + 1; + } + + printf (" %s\n" + 2 * (*msg != ' ' && *msg != '-'), msg); + } + } +} + +/* Set VAR to VALUE, reporting an OPTION error if this is a + conflict. */ +static void +specify_value (char const **var, char const *value, char const *option) +{ + if (*var && strcmp (*var, value) != 0) + { + error (0, 0, _("conflicting %s option value `%s'"), option, value); + try_help (0, 0); + } + *var = value; +} + +/* Set the output style to STYLE, diagnosing conflicts. */ +static void +specify_style (enum output_style style) +{ + if (output_style != style) + { + if (output_style != OUTPUT_UNSPECIFIED) + try_help ("conflicting output style options", 0); + output_style = style; + } +} + +/* Set the last-modified time of *ST to be the current time. */ + +static void +set_mtime_to_now (struct stat *st) +{ +#ifdef ST_MTIM_NSEC + +# if HAVE_CLOCK_GETTIME && defined CLOCK_REALTIME + if (clock_gettime (CLOCK_REALTIME, &st->st_mtim) == 0) + return; +# endif + +# if HAVE_GETTIMEOFDAY + { + struct timeval timeval; + if (gettimeofday (&timeval, 0) == 0) + { + st->st_mtime = timeval.tv_sec; + st->st_mtim.ST_MTIM_NSEC = timeval.tv_usec * 1000; + return; + } + } +# endif + +#endif /* ST_MTIM_NSEC */ + + time (&st->st_mtime); +} + +/* Compare two files (or dirs) with parent comparison PARENT + and names NAME0 and NAME1. + (If PARENT is 0, then the first name is just NAME0, etc.) + This is self-contained; it opens the files and closes them. + + Value is EXIT_SUCCESS if files are the same, EXIT_FAILURE if + different, EXIT_TROUBLE if there is a problem opening them. */ + +static int +compare_files (struct comparison const *parent, + char const *name0, + char const *name1) +{ + struct comparison cmp; +#define DIR_P(f) (S_ISDIR (cmp.file[f].stat.st_mode) != 0) + register int f; + int status = EXIT_SUCCESS; + bool same_files; + char *free0, *free1; + + /* If this is directory comparison, perhaps we have a file + that exists only in one of the directories. + If so, just print a message to that effect. */ + + if (! ((name0 && name1) + || (unidirectional_new_file && name1) + || new_file)) + { + char const *name = name0 == 0 ? name1 : name0; + char const *dir = parent->file[name0 == 0].name; + + /* See POSIX 1003.1-2001 for this format. */ + message ("Only in %s: %s\n", dir, name); + + /* Return EXIT_FAILURE so that diff_dirs will return + EXIT_FAILURE ("some files differ"). */ + return EXIT_FAILURE; + } + + memset (cmp.file, 0, sizeof cmp.file); + cmp.parent = parent; + + /* cmp.file[f].desc markers */ +#define NONEXISTENT (-1) /* nonexistent file */ +#define UNOPENED (-2) /* unopened file (e.g. directory) */ +#define ERRNO_ENCODE(errno) (-3 - (errno)) /* encoded errno value */ + +#define ERRNO_DECODE(desc) (-3 - (desc)) /* inverse of ERRNO_ENCODE */ + + cmp.file[0].desc = name0 == 0 ? NONEXISTENT : UNOPENED; + cmp.file[1].desc = name1 == 0 ? NONEXISTENT : UNOPENED; + + /* Now record the full name of each file, including nonexistent ones. */ + + if (name0 == 0) + name0 = name1; + if (name1 == 0) + name1 = name0; + + if (!parent) + { + free0 = 0; + free1 = 0; + cmp.file[0].name = name0; + cmp.file[1].name = name1; + } + else + { + cmp.file[0].name = free0 + = dir_file_pathname (parent->file[0].name, name0); + cmp.file[1].name = free1 + = dir_file_pathname (parent->file[1].name, name1); + } + + /* Stat the files. */ + + for (f = 0; f < 2; f++) + { + if (cmp.file[f].desc != NONEXISTENT) + { + if (f && file_name_cmp (cmp.file[f].name, cmp.file[0].name) == 0) + { + cmp.file[f].desc = cmp.file[0].desc; + cmp.file[f].stat = cmp.file[0].stat; + } + else if (strcmp (cmp.file[f].name, "-") == 0) + { + cmp.file[f].desc = STDIN_FILENO; + if (fstat (STDIN_FILENO, &cmp.file[f].stat) != 0) + cmp.file[f].desc = ERRNO_ENCODE (errno); + else + { + if (S_ISREG (cmp.file[f].stat.st_mode)) + { + off_t pos = lseek (STDIN_FILENO, (off_t) 0, SEEK_CUR); + if (pos < 0) + cmp.file[f].desc = ERRNO_ENCODE (errno); + else + cmp.file[f].stat.st_size = + MAX (0, cmp.file[f].stat.st_size - pos); + } + + /* POSIX 1003.1-2001 requires current time for + stdin. */ + set_mtime_to_now (&cmp.file[f].stat); + } + } + else if (stat (cmp.file[f].name, &cmp.file[f].stat) != 0) + cmp.file[f].desc = ERRNO_ENCODE (errno); + } + } + + /* Mark files as nonexistent as needed for -N and -P, if they are + inaccessible empty regular files (the kind of files that 'patch' + creates to indicate nonexistent backups), or if they are + top-level files that do not exist but their counterparts do + exist. */ + for (f = 0; f < 2; f++) + if ((new_file || (f == 0 && unidirectional_new_file)) + && (cmp.file[f].desc == UNOPENED + ? (S_ISREG (cmp.file[f].stat.st_mode) + && ! (cmp.file[f].stat.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) + && cmp.file[f].stat.st_size == 0) + : (cmp.file[f].desc == ERRNO_ENCODE (ENOENT) + && ! parent + && cmp.file[1 - f].desc == UNOPENED))) + cmp.file[f].desc = NONEXISTENT; + + for (f = 0; f < 2; f++) + if (cmp.file[f].desc == NONEXISTENT) + { + memset (&cmp.file[f].stat, 0, sizeof cmp.file[f].stat); + cmp.file[f].stat.st_mode = cmp.file[1 - f].stat.st_mode; + } + + for (f = 0; f < 2; f++) + { + int e = ERRNO_DECODE (cmp.file[f].desc); + if (0 <= e) + { + errno = e; + perror_with_name (cmp.file[f].name); + status = EXIT_TROUBLE; + } + } + + if (status == EXIT_SUCCESS && ! parent && DIR_P (0) != DIR_P (1)) + { + /* If one is a directory, and it was specified in the command line, + use the file in that dir with the other file's basename. */ + + int fnm_arg = DIR_P (0); + int dir_arg = 1 - fnm_arg; + char const *fnm = cmp.file[fnm_arg].name; + char const *dir = cmp.file[dir_arg].name; + char const *filename = cmp.file[dir_arg].name = free0 + = dir_file_pathname (dir, base_name (fnm)); + + if (strcmp (fnm, "-") == 0) + fatal ("cannot compare `-' to a directory"); + + if (stat (filename, &cmp.file[dir_arg].stat) != 0) + { + perror_with_name (filename); + status = EXIT_TROUBLE; + } + } + + if (status != EXIT_SUCCESS) + { + /* One of the files should exist but does not. */ + } + else if (cmp.file[0].desc == NONEXISTENT + && cmp.file[1].desc == NONEXISTENT) + { + /* Neither file "exists", so there's nothing to compare. */ + } + else if ((same_files + = (cmp.file[0].desc != NONEXISTENT + && cmp.file[1].desc != NONEXISTENT + && 0 < same_file (&cmp.file[0].stat, &cmp.file[1].stat) + && same_file_attributes (&cmp.file[0].stat, + &cmp.file[1].stat))) + && no_diff_means_no_output) + { + /* The two named files are actually the same physical file. + We know they are identical without actually reading them. */ + } + else if (DIR_P (0) & DIR_P (1)) + { + if (output_style == OUTPUT_IFDEF) + fatal ("-D option not supported with directories"); + + /* If both are directories, compare the files in them. */ + + if (parent && !recursive) + { + /* But don't compare dir contents one level down + unless -r was specified. + See POSIX 1003.1-2001 for this format. */ + message ("Common subdirectories: %s and %s\n", + cmp.file[0].name, cmp.file[1].name); + } + else + status = diff_dirs (&cmp, compare_files); + } + else if ((DIR_P (0) | DIR_P (1)) + || (parent + && (! S_ISREG (cmp.file[0].stat.st_mode) + || ! S_ISREG (cmp.file[1].stat.st_mode)))) + { + if (cmp.file[0].desc == NONEXISTENT || cmp.file[1].desc == NONEXISTENT) + { + /* We have a subdirectory that exists only in one directory. */ + + if ((DIR_P (0) | DIR_P (1)) + && recursive + && (new_file + || (unidirectional_new_file + && cmp.file[0].desc == NONEXISTENT))) + status = diff_dirs (&cmp, compare_files); + else + { + char const *dir + = parent->file[cmp.file[0].desc == NONEXISTENT].name; + + /* See POSIX 1003.1-2001 for this format. */ + message ("Only in %s: %s\n", dir, name0); + + status = EXIT_FAILURE; + } + } + else + { + /* We have two files that are not to be compared. */ + + /* See POSIX 1003.1-2001 for this format. */ + message5 ("File %s is a %s while file %s is a %s\n", + file_label[0] ? file_label[0] : cmp.file[0].name, + file_type (&cmp.file[0].stat), + file_label[1] ? file_label[1] : cmp.file[1].name, + file_type (&cmp.file[1].stat)); + + /* This is a difference. */ + status = EXIT_FAILURE; + } + } + else if (files_can_be_treated_as_binary + && S_ISREG (cmp.file[0].stat.st_mode) + && S_ISREG (cmp.file[1].stat.st_mode) + && cmp.file[0].stat.st_size != cmp.file[1].stat.st_size) + { + message ("Files %s and %s differ\n", + file_label[0] ? file_label[0] : cmp.file[0].name, + file_label[1] ? file_label[1] : cmp.file[1].name); + status = EXIT_FAILURE; + } + else + { + /* Both exist and neither is a directory. */ + + /* Open the files and record their descriptors. */ + + if (cmp.file[0].desc == UNOPENED) + if ((cmp.file[0].desc = open (cmp.file[0].name, O_RDONLY, 0)) < 0) + { + perror_with_name (cmp.file[0].name); + status = EXIT_TROUBLE; + } + if (cmp.file[1].desc == UNOPENED) + { + if (same_files) + cmp.file[1].desc = cmp.file[0].desc; + else if ((cmp.file[1].desc = open (cmp.file[1].name, O_RDONLY, 0)) + < 0) + { + perror_with_name (cmp.file[1].name); + status = EXIT_TROUBLE; + } + } + +#if HAVE_SETMODE_DOS + if (binary) + for (f = 0; f < 2; f++) + if (0 <= cmp.file[f].desc) + set_binary_mode (cmp.file[f].desc, true); +#endif + + /* Compare the files, if no error was found. */ + + if (status == EXIT_SUCCESS) + status = diff_2_files (&cmp); + + /* Close the file descriptors. */ + + if (0 <= cmp.file[0].desc && close (cmp.file[0].desc) != 0) + { + perror_with_name (cmp.file[0].name); + status = EXIT_TROUBLE; + } + if (0 <= cmp.file[1].desc && cmp.file[0].desc != cmp.file[1].desc + && close (cmp.file[1].desc) != 0) + { + perror_with_name (cmp.file[1].name); + status = EXIT_TROUBLE; + } + } + + /* Now the comparison has been done, if no error prevented it, + and STATUS is the value this function will return. */ + + if (status == EXIT_SUCCESS) + { + if (report_identical_files && !DIR_P (0)) + message ("Files %s and %s are identical\n", + file_label[0] ? file_label[0] : cmp.file[0].name, + file_label[1] ? file_label[1] : cmp.file[1].name); + } + else + { + /* Flush stdout so that the user sees differences immediately. + This can hurt performance, unfortunately. */ + if (fflush (stdout) != 0) + pfatal_with_name (_("standard output")); + } + + if (free0) + free (free0); + if (free1) + free (free1); + + return status; +} diff --git a/contrib/diffutils-2.8/src/diff.h b/contrib/diffutils-2.8/src/diff.h new file mode 100644 index 0000000000..e7a4b2db3f --- /dev/null +++ b/contrib/diffutils-2.8/src/diff.h @@ -0,0 +1,375 @@ +/* Shared definitions for GNU DIFF + + Copyright (C) 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1998, 2001, + 2002, 2004 Free Software Foundation, Inc. + + This file is part of GNU DIFF. + + GNU DIFF is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GNU DIFF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "system.h" +#include +#include +#include + +/* What kind of changes a hunk contains. */ +enum changes +{ + /* No changes: lines common to both files. */ + UNCHANGED, + + /* Deletes only: lines taken from just the first file. */ + OLD, + + /* Inserts only: lines taken from just the second file. */ + NEW, + + /* Both deletes and inserts: a hunk containing both old and new lines. */ + CHANGED +}; + +/* Variables for command line options */ + +#ifndef GDIFF_MAIN +# define XTERN extern +#else +# define XTERN +#endif + +enum output_style +{ + /* No output style specified. */ + OUTPUT_UNSPECIFIED, + + /* Default output style. */ + OUTPUT_NORMAL, + + /* Output the differences with lines of context before and after (-c). */ + OUTPUT_CONTEXT, + + /* Output the differences in a unified context diff format (-u). */ + OUTPUT_UNIFIED, + + /* Output the differences as commands suitable for `ed' (-e). */ + OUTPUT_ED, + + /* Output the diff as a forward ed script (-f). */ + OUTPUT_FORWARD_ED, + + /* Like -f, but output a count of changed lines in each "command" (-n). */ + OUTPUT_RCS, + + /* Output merged #ifdef'd file (-D). */ + OUTPUT_IFDEF, + + /* Output sdiff style (-y). */ + OUTPUT_SDIFF +}; + +/* True for output styles that are robust, + i.e. can handle a file that ends in a non-newline. */ +#define ROBUST_OUTPUT_STYLE(S) ((S) != OUTPUT_ED && (S) != OUTPUT_FORWARD_ED) + +XTERN enum output_style output_style; + +/* Nonzero if output cannot be generated for identical files. */ +XTERN bool no_diff_means_no_output; + +/* Number of lines of context to show in each set of diffs. + This is zero when context is not to be shown. */ +XTERN lin context; + +/* Consider all files as text files (-a). + Don't interpret codes over 0177 as implying a "binary file". */ +XTERN bool text; + +/* Number of lines to keep in identical prefix and suffix. */ +XTERN lin horizon_lines; + +/* The significance of white space during comparisons. */ +XTERN enum +{ + /* All white space is significant (the default). */ + IGNORE_NO_WHITE_SPACE, + + /* Ignore changes due to tab expansion (-E). */ + IGNORE_TAB_EXPANSION, + + /* Ignore changes in horizontal white space (-b). */ + IGNORE_SPACE_CHANGE, + + /* Ignore all horizontal white space (-w). */ + IGNORE_ALL_SPACE +} ignore_white_space; + +/* Ignore changes that affect only blank lines (-B). */ +XTERN bool ignore_blank_lines; + +/* Files can be compared byte-by-byte, as if they were binary. + This depends on various options. */ +XTERN bool files_can_be_treated_as_binary; + +/* Ignore differences in case of letters (-i). */ +XTERN bool ignore_case; + +/* Ignore differences in case of letters in file names. */ +XTERN bool ignore_file_name_case; + +/* File labels for `-c' output headers (--label). */ +XTERN char *file_label[2]; + +/* Regexp to identify function-header lines (-F). */ +XTERN struct re_pattern_buffer function_regexp; + +/* Ignore changes that affect only lines matching this regexp (-I). */ +XTERN struct re_pattern_buffer ignore_regexp; + +/* Say only whether files differ, not how (-q). */ +XTERN bool brief; + +/* Expand tabs in the output so the text lines up properly + despite the characters added to the front of each line (-t). */ +XTERN bool expand_tabs; + +/* Number of columns between tab stops. */ +XTERN size_t tabsize; + +/* Use a tab in the output, rather than a space, before the text of an + input line, so as to keep the proper alignment in the input line + without changing the characters in it (-T). */ +XTERN bool initial_tab; + +/* Remove trailing carriage returns from input. */ +XTERN bool strip_trailing_cr; + +/* In directory comparison, specify file to start with (-S). + This is used for resuming an aborted comparison. + All file names less than this name are ignored. */ +XTERN char const *starting_file; + +/* Pipe each file's output through pr (-l). */ +XTERN bool paginate; + +/* Line group formats for unchanged, old, new, and changed groups. */ +XTERN char const *group_format[CHANGED + 1]; + +/* Line formats for unchanged, old, and new lines. */ +XTERN char const *line_format[NEW + 1]; + +/* If using OUTPUT_SDIFF print extra information to help the sdiff filter. */ +XTERN bool sdiff_merge_assist; + +/* Tell OUTPUT_SDIFF to show only the left version of common lines. */ +XTERN bool left_column; + +/* Tell OUTPUT_SDIFF to not show common lines. */ +XTERN bool suppress_common_lines; + +/* The half line width and column 2 offset for OUTPUT_SDIFF. */ +XTERN size_t sdiff_half_width; +XTERN size_t sdiff_column2_offset; + +/* String containing all the command options diff received, + with spaces between and at the beginning but none at the end. + If there were no options given, this string is empty. */ +XTERN char *switch_string; + +/* Use heuristics for better speed with large files with a small + density of changes. */ +XTERN bool speed_large_files; + +/* Patterns that match file names to be excluded. */ +XTERN struct exclude *excluded; + +/* Don't discard lines. This makes things slower (sometimes much + slower) but will find a guaranteed minimal set of changes. */ +XTERN bool minimal; + +/* Name of program the user invoked (for error messages). */ +XTERN char *program_name; + +/* The strftime format to use for time strings. */ +XTERN char const *time_format; + +/* The result of comparison is an "edit script": a chain of `struct change'. + Each `struct change' represents one place where some lines are deleted + and some are inserted. + + LINE0 and LINE1 are the first affected lines in the two files (origin 0). + DELETED is the number of lines deleted here from file 0. + INSERTED is the number of lines inserted here in file 1. + + If DELETED is 0 then LINE0 is the number of the line before + which the insertion was done; vice versa for INSERTED and LINE1. */ + +struct change +{ + struct change *link; /* Previous or next edit command */ + lin inserted; /* # lines of file 1 changed here. */ + lin deleted; /* # lines of file 0 changed here. */ + lin line0; /* Line number of 1st deleted line. */ + lin line1; /* Line number of 1st inserted line. */ + bool ignore; /* Flag used in context.c. */ +}; + +/* Structures that describe the input files. */ + +/* Data on one input file being compared. */ + +struct file_data { + int desc; /* File descriptor */ + char const *name; /* File name */ + struct stat stat; /* File status */ + + /* Buffer in which text of file is read. */ + word *buffer; + + /* Allocated size of buffer, in bytes. Always a multiple of + sizeof *buffer. */ + size_t bufsize; + + /* Number of valid bytes now in the buffer. */ + size_t buffered; + + /* Array of pointers to lines in the file. */ + char const **linbuf; + + /* linbuf_base <= buffered_lines <= valid_lines <= alloc_lines. + linebuf[linbuf_base ... buffered_lines - 1] are possibly differing. + linebuf[linbuf_base ... valid_lines - 1] contain valid data. + linebuf[linbuf_base ... alloc_lines - 1] are allocated. */ + lin linbuf_base, buffered_lines, valid_lines, alloc_lines; + + /* Pointer to end of prefix of this file to ignore when hashing. */ + char const *prefix_end; + + /* Count of lines in the prefix. + There are this many lines in the file before linbuf[0]. */ + lin prefix_lines; + + /* Pointer to start of suffix of this file to ignore when hashing. */ + char const *suffix_begin; + + /* Vector, indexed by line number, containing an equivalence code for + each line. It is this vector that is actually compared with that + of another file to generate differences. */ + lin *equivs; + + /* Vector, like the previous one except that + the elements for discarded lines have been squeezed out. */ + lin *undiscarded; + + /* Vector mapping virtual line numbers (not counting discarded lines) + to real ones (counting those lines). Both are origin-0. */ + lin *realindexes; + + /* Total number of nondiscarded lines. */ + lin nondiscarded_lines; + + /* Vector, indexed by real origin-0 line number, + containing 1 for a line that is an insertion or a deletion. + The results of comparison are stored here. */ + char *changed; + + /* 1 if file ends in a line with no final newline. */ + bool missing_newline; + + /* 1 if at end of file. */ + bool eof; + + /* 1 more than the maximum equivalence value used for this or its + sibling file. */ + lin equiv_max; +}; + +/* The file buffer, considered as an array of bytes rather than + as an array of words. */ +#define FILE_BUFFER(f) ((char *) (f)->buffer) + +/* Data on two input files being compared. */ + +struct comparison + { + struct file_data file[2]; + struct comparison const *parent; /* parent, if a recursive comparison */ + }; + +/* Describe the two files currently being compared. */ + +XTERN struct file_data files[2]; + +/* Stdio stream to output diffs to. */ + +XTERN FILE *outfile; + +/* Declare various functions. */ + +/* analyze.c */ +int diff_2_files (struct comparison *); + +/* context.c */ +void print_context_header (struct file_data[], bool); +void print_context_script (struct change *, bool); + +/* dir.c */ +int diff_dirs (struct comparison const *, int (*) (struct comparison const *, char const *, char const *)); + +/* ed.c */ +void print_ed_script (struct change *); +void pr_forward_ed_script (struct change *); + +/* ifdef.c */ +void print_ifdef_script (struct change *); + +/* io.c */ +void file_block_read (struct file_data *, size_t); +bool read_files (struct file_data[], bool); + +/* normal.c */ +void print_normal_script (struct change *); + +/* rcs.c */ +void print_rcs_script (struct change *); + +/* side.c */ +void print_sdiff_script (struct change *); + +/* util.c */ +extern char const change_letter[4]; +extern char const pr_program[]; +char *concat (char const *, char const *, char const *); +char *dir_file_pathname (char const *, char const *); +bool lines_differ (char const *, char const *); +lin translate_line_number (struct file_data const *, lin); +struct change *find_change (struct change *); +struct change *find_reverse_change (struct change *); +void *zalloc (size_t); +enum changes analyze_hunk (struct change *, lin *, lin *, lin *, lin *); +void begin_output (void); +void debug_script (struct change *); +void fatal (char const *) __attribute__((noreturn)); +void finish_output (void); +void message (char const *, char const *, char const *); +void message5 (char const *, char const *, char const *, char const *, char const *); +void output_1_line (char const *, char const *, char const *, char const *); +void perror_with_name (char const *); +void pfatal_with_name (char const *) __attribute__((noreturn)); +void print_1_line (char const *, char const * const *); +void print_message_queue (void); +void print_number_range (char, struct file_data *, lin, lin); +void print_script (struct change *, struct change * (*) (struct change *), void (*) (struct change *)); +void setup_output (char const *, char const *, bool); +void translate_range (struct file_data const *, lin, lin, long int *, long int *); diff --git a/contrib/diffutils-2.8/src/diff3.c b/contrib/diffutils-2.8/src/diff3.c new file mode 100644 index 0000000000..261eeabfdf --- /dev/null +++ b/contrib/diffutils-2.8/src/diff3.c @@ -0,0 +1,1744 @@ +/* diff3 - compare three files line by line + + Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1998, 2001, + 2002, 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "system.h" +#include "paths.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Internal data structures and macros for the diff3 program; includes + data structures for both diff3 diffs and normal diffs. */ + +/* Different files within a three way diff. */ +#define FILE0 0 +#define FILE1 1 +#define FILE2 2 + +/* A three way diff is built from two two-way diffs; the file which + the two two-way diffs share is: */ +#define FILEC FILE2 + +/* Different files within a two way diff. + FC is the common file, FO the other file. */ +#define FO 0 +#define FC 1 + +/* The ranges are indexed by */ +#define RANGE_START 0 +#define RANGE_END 1 + +enum diff_type { + ERROR, /* Should not be used */ + ADD, /* Two way diff add */ + CHANGE, /* Two way diff change */ + DELETE, /* Two way diff delete */ + DIFF_ALL, /* All three are different */ + DIFF_1ST, /* Only the first is different */ + DIFF_2ND, /* Only the second */ + DIFF_3RD /* Only the third */ +}; + +/* Two way diff */ +struct diff_block { + lin ranges[2][2]; /* Ranges are inclusive */ + char **lines[2]; /* The actual lines (may contain nulls) */ + size_t *lengths[2]; /* Line lengths (including newlines, if any) */ + struct diff_block *next; +}; + +/* Three way diff */ + +struct diff3_block { + enum diff_type correspond; /* Type of diff */ + lin ranges[3][2]; /* Ranges are inclusive */ + char **lines[3]; /* The actual lines (may contain nulls) */ + size_t *lengths[3]; /* Line lengths (including newlines, if any) */ + struct diff3_block *next; +}; + +/* Access the ranges on a diff block. */ +#define D_LOWLINE(diff, filenum) \ + ((diff)->ranges[filenum][RANGE_START]) +#define D_HIGHLINE(diff, filenum) \ + ((diff)->ranges[filenum][RANGE_END]) +#define D_NUMLINES(diff, filenum) \ + (D_HIGHLINE (diff, filenum) - D_LOWLINE (diff, filenum) + 1) + +/* Access the line numbers in a file in a diff by relative line + numbers (i.e. line number within the diff itself). Note that these + are lvalues and can be used for assignment. */ +#define D_RELNUM(diff, filenum, linenum) \ + ((diff)->lines[filenum][linenum]) +#define D_RELLEN(diff, filenum, linenum) \ + ((diff)->lengths[filenum][linenum]) + +/* And get at them directly, when that should be necessary. */ +#define D_LINEARRAY(diff, filenum) \ + ((diff)->lines[filenum]) +#define D_LENARRAY(diff, filenum) \ + ((diff)->lengths[filenum]) + +/* Next block. */ +#define D_NEXT(diff) ((diff)->next) + +/* Access the type of a diff3 block. */ +#define D3_TYPE(diff) ((diff)->correspond) + +/* Line mappings based on diffs. The first maps off the top of the + diff, the second off of the bottom. */ +#define D_HIGH_MAPLINE(diff, fromfile, tofile, linenum) \ + ((linenum) \ + - D_HIGHLINE ((diff), (fromfile)) \ + + D_HIGHLINE ((diff), (tofile))) + +#define D_LOW_MAPLINE(diff, fromfile, tofile, linenum) \ + ((linenum) \ + - D_LOWLINE ((diff), (fromfile)) \ + + D_LOWLINE ((diff), (tofile))) + +/* Options variables for flags set on command line. */ + +/* If nonzero, treat all files as text files, never as binary. */ +static bool text; + +/* Remove trailing carriage returns from input. */ +static bool strip_trailing_cr; + +/* If nonzero, write out an ed script instead of the standard diff3 format. */ +static bool edscript; + +/* If nonzero, in the case of overlapping diffs (type DIFF_ALL), + preserve the lines which would normally be deleted from + file 1 with a special flagging mechanism. */ +static bool flagging; + +/* Use a tab to align output lines (-T). */ +static bool initial_tab; + +/* If nonzero, do not output information for overlapping diffs. */ +static bool simple_only; + +/* If nonzero, do not output information for non-overlapping diffs. */ +static bool overlap_only; + +/* If nonzero, show information for DIFF_2ND diffs. */ +static bool show_2nd; + +/* If nonzero, include `:wq' at the end of the script + to write out the file being edited. */ +static bool finalwrite; + +/* If nonzero, output a merged file. */ +static bool merge; + +char *program_name; + +static char *read_diff (char const *, char const *, char **); +static char *scan_diff_line (char *, char **, size_t *, char *, char); +static enum diff_type process_diff_control (char **, struct diff_block *); +static bool compare_line_list (char * const[], size_t const[], char * const[], size_t const[], lin); +static bool copy_stringlist (char * const[], size_t const[], char *[], size_t[], lin); +static bool output_diff3_edscript (FILE *, struct diff3_block *, int const[3], int const[3], char const *, char const *, char const *); +static bool output_diff3_merge (FILE *, FILE *, struct diff3_block *, int const[3], int const[3], char const *, char const *, char const *); +static struct diff3_block *create_diff3_block (lin, lin, lin, lin, lin, lin); +static struct diff3_block *make_3way_diff (struct diff_block *, struct diff_block *); +static struct diff3_block *reverse_diff3_blocklist (struct diff3_block *); +static struct diff3_block *using_to_diff3_block (struct diff_block *[2], struct diff_block *[2], int, int, struct diff3_block const *); +static struct diff_block *process_diff (char const *, char const *, struct diff_block **); +static void check_stdout (void); +static void fatal (char const *) __attribute__((noreturn)); +static void output_diff3 (FILE *, struct diff3_block *, int const[3], int const[3]); +static void perror_with_exit (char const *) __attribute__((noreturn)); +static void try_help (char const *, char const *) __attribute__((noreturn)); +static void usage (void); + +static char const *diff_program = DEFAULT_DIFF_PROGRAM; + +/* Values for long options that do not have single-letter equivalents. */ +enum +{ + DIFF_PROGRAM_OPTION = CHAR_MAX + 1, + HELP_OPTION, + STRIP_TRAILING_CR_OPTION +}; + +static struct option const longopts[] = +{ + {"diff-program", 1, 0, DIFF_PROGRAM_OPTION}, + {"easy-only", 0, 0, '3'}, + {"ed", 0, 0, 'e'}, + {"help", 0, 0, HELP_OPTION}, + {"initial-tab", 0, 0, 'T'}, + {"label", 1, 0, 'L'}, + {"merge", 0, 0, 'm'}, + {"overlap-only", 0, 0, 'x'}, + {"show-all", 0, 0, 'A'}, + {"show-overlap", 0, 0, 'E'}, + {"strip-trailing-cr", 0, 0, STRIP_TRAILING_CR_OPTION}, + {"text", 0, 0, 'a'}, + {"version", 0, 0, 'v'}, + {0, 0, 0, 0} +}; + +int +main (int argc, char **argv) +{ + int c, i; + int common; + int mapping[3]; + int rev_mapping[3]; + int incompat = 0; + bool conflicts_found; + struct diff_block *thread0, *thread1, *last_block; + struct diff3_block *diff3; + int tag_count = 0; + char *tag_strings[3]; + char *commonname; + char **file; + struct stat statb; + + exit_failure = 2; + initialize_main (&argc, &argv); + program_name = argv[0]; + setlocale (LC_ALL, ""); + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + c_stack_action (0); + + while ((c = getopt_long (argc, argv, "aeimvx3AEL:TX", longopts, 0)) != -1) + { + switch (c) + { + case 'a': + text = true; + break; + case 'A': + show_2nd = true; + flagging = true; + incompat++; + break; + case 'x': + overlap_only = true; + incompat++; + break; + case '3': + simple_only = true; + incompat++; + break; + case 'i': + finalwrite = true; + break; + case 'm': + merge = true; + break; + case 'X': + overlap_only = true; + /* Fall through. */ + case 'E': + flagging = true; + /* Fall through. */ + case 'e': + incompat++; + break; + case 'T': + initial_tab = true; + break; + case STRIP_TRAILING_CR_OPTION: + strip_trailing_cr = true; + break; + case 'v': + version_etc (stdout, "diff3", PACKAGE_NAME, PACKAGE_VERSION, + "Randy Smith", (char *) 0); + check_stdout (); + return EXIT_SUCCESS; + case DIFF_PROGRAM_OPTION: + diff_program = optarg; + break; + case HELP_OPTION: + usage (); + check_stdout (); + return EXIT_SUCCESS; + case 'L': + /* Handle up to three -L options. */ + if (tag_count < 3) + { + tag_strings[tag_count++] = optarg; + break; + } + try_help ("too many file label options", 0); + default: + try_help (0, 0); + } + } + + edscript = incompat & ~merge; /* -AeExX3 without -m implies ed script. */ + show_2nd |= ~incompat & merge; /* -m without -AeExX3 implies -A. */ + flagging |= ~incompat & merge; + + if (incompat > 1 /* Ensure at most one of -AeExX3. */ + || finalwrite & merge /* -i -m would rewrite input file. */ + || (tag_count && ! flagging)) /* -L requires one of -AEX. */ + try_help ("incompatible options", 0); + + if (argc - optind != 3) + { + if (argc - optind < 3) + try_help ("missing operand after `%s'", argv[argc - 1]); + else + try_help ("extra operand `%s'", argv[optind + 3]); + } + + file = &argv[optind]; + + for (i = tag_count; i < 3; i++) + tag_strings[i] = file[i]; + + /* Always compare file1 to file2, even if file2 is "-". + This is needed for -mAeExX3. Using the file0 as + the common file would produce wrong results, because if the + file0-file1 diffs didn't line up with the file0-file2 diffs + (which is entirely possible since we don't use diff's -n option), + diff3 might report phantom changes from file1 to file2. + + Also, try to compare file0 to file1, because this is where + changes are expected to come from. Diffing between these pairs + of files is more likely to avoid phantom changes from file0 to file1. + + Historically, the default common file was file2, so some older + applications (e.g. Emacs ediff) used file2 as the ancestor. So, + for compatibility, if this is a 3-way diff (not a merge or + edscript), prefer file2 as the common file. */ + + common = 2 - (edscript | merge); + + if (strcmp (file[common], "-") == 0) + { + /* Sigh. We've got standard input as the common file. We can't + call diff twice on stdin. Use the other arg as the common + file instead. */ + common = 3 - common; + if (strcmp (file[0], "-") == 0 || strcmp (file[common], "-") == 0) + fatal ("`-' specified for more than one input file"); + } + + mapping[0] = 0; + mapping[1] = 3 - common; + mapping[2] = common; + + for (i = 0; i < 3; i++) + rev_mapping[mapping[i]] = i; + + for (i = 0; i < 3; i++) + if (strcmp (file[i], "-") != 0) + { + if (stat (file[i], &statb) < 0) + perror_with_exit (file[i]); + else if (S_ISDIR (statb.st_mode)) + error (EXIT_TROUBLE, EISDIR, "%s", file[i]); + } + +#ifdef SIGCHLD + /* System V fork+wait does not work if SIGCHLD is ignored. */ + signal (SIGCHLD, SIG_DFL); +#endif + + /* Invoke diff twice on two pairs of input files, combine the two + diffs, and output them. */ + + commonname = file[rev_mapping[FILEC]]; + thread1 = process_diff (file[rev_mapping[FILE1]], commonname, &last_block); + thread0 = process_diff (file[rev_mapping[FILE0]], commonname, &last_block); + diff3 = make_3way_diff (thread0, thread1); + if (edscript) + conflicts_found + = output_diff3_edscript (stdout, diff3, mapping, rev_mapping, + tag_strings[0], tag_strings[1], tag_strings[2]); + else if (merge) + { + if (! freopen (file[rev_mapping[FILE0]], "r", stdin)) + perror_with_exit (file[rev_mapping[FILE0]]); + conflicts_found + = output_diff3_merge (stdin, stdout, diff3, mapping, rev_mapping, + tag_strings[0], tag_strings[1], tag_strings[2]); + if (ferror (stdin)) + fatal ("read failed"); + } + else + { + output_diff3 (stdout, diff3, mapping, rev_mapping); + conflicts_found = false; + } + + check_stdout (); + exit (conflicts_found); + return conflicts_found; +} + +static void +try_help (char const *reason_msgid, char const *operand) +{ + if (reason_msgid) + error (0, 0, _(reason_msgid), operand); + error (EXIT_TROUBLE, 0, + _("Try `%s --help' for more information."), program_name); + abort (); +} + +static void +check_stdout (void) +{ + if (ferror (stdout)) + fatal ("write failed"); + else if (fclose (stdout) != 0) + perror_with_exit (_("standard output")); +} + +static char const * const option_help_msgid[] = { + N_("-e --ed Output unmerged changes from OLDFILE to YOURFILE into MYFILE."), + N_("-E --show-overlap Output unmerged changes, bracketing conflicts."), + N_("-A --show-all Output all changes, bracketing conflicts."), + N_("-x --overlap-only Output overlapping changes."), + N_("-X Output overlapping changes, bracketing them."), + N_("-3 --easy-only Output unmerged nonoverlapping changes."), + "", + N_("-m --merge Output merged file instead of ed script (default -A)."), + N_("-L LABEL --label=LABEL Use LABEL instead of file name."), + N_("-i Append `w' and `q' commands to ed scripts."), + N_("-a --text Treat all files as text."), + N_("--strip-trailing-cr Strip trailing carriage return on input."), + N_("-T --initial-tab Make tabs line up by prepending a tab."), + N_("--diff-program=PROGRAM Use PROGRAM to compare files."), + "", + N_("-v --version Output version info."), + N_("--help Output this help."), + 0 +}; + +static void +usage (void) +{ + char const * const *p; + + printf (_("Usage: %s [OPTION]... MYFILE OLDFILE YOURFILE\n"), + program_name); + printf ("%s\n\n", _("Compare three files line by line.")); + for (p = option_help_msgid; *p; p++) + if (**p) + printf (" %s\n", _(*p)); + else + putchar ('\n'); + printf ("\n%s\n%s\n\n%s\n", + _("If a FILE is `-', read standard input."), + _("Exit status is 0 if successful, 1 if conflicts, 2 if trouble."), + _("Report bugs to .")); +} + +/* Combine the two diffs together into one. + Here is the algorithm: + + File2 is shared in common between the two diffs. + Diff02 is the diff between 0 and 2. + Diff12 is the diff between 1 and 2. + + 1) Find the range for the first block in File2. + a) Take the lowest of the two ranges (in File2) in the two + current blocks (one from each diff) as being the low + water mark. Assign the upper end of this block as + being the high water mark and move the current block up + one. Mark the block just moved over as to be used. + b) Check the next block in the diff that the high water + mark is *not* from. + + *If* the high water mark is above + the low end of the range in that block, + + mark that block as to be used and move the current + block up. Set the high water mark to the max of + the high end of this block and the current. Repeat b. + + 2) Find the corresponding ranges in File0 (from the blocks + in diff02; line per line outside of diffs) and in File1. + Create a diff3_block, reserving space as indicated by the ranges. + + 3) Copy all of the pointers for file2 in. At least for now, + do memcmp's between corresponding strings in the two diffs. + + 4) Copy all of the pointers for file0 and 1 in. Get what is + needed from file2 (when there isn't a diff block, it's + identical to file2 within the range between diff blocks). + + 5) If the diff blocks used came from only one of the two + strings of diffs, then that file (i.e. the one other than + the common file in that diff) is the odd person out. If + diff blocks are used from both sets, check to see if files + 0 and 1 match: + + Same number of lines? If so, do a set of memcmp's (if + a memcmp matches; copy the pointer over; it'll be easier + later during comparisons). If they match, 0 & 1 are the + same. If not, all three different. + + Then do it again, until the blocks are exhausted. */ + + +/* Make a three way diff (chain of diff3_block's) from two two way + diffs (chains of diff_block's). Assume that each of the two diffs + passed are onto the same file (i.e. that each of the diffs were + made "to" the same file). Return a three way diff pointer with + numbering FILE0 = the other file in diff02, FILE1 = the other file + in diff12, and FILEC = the common file. */ + +static struct diff3_block * +make_3way_diff (struct diff_block *thread0, struct diff_block *thread1) +{ + /* Work on the two diffs passed to it as threads. Thread number 0 + is diff02, thread number 1 is diff12. USING is the base of the + list of blocks to be used to construct each block of the three + way diff; if no blocks from a particular thread are to be used, + that element of USING is 0. LAST_USING contains the last + elements on each of the using lists. + + HIGH_WATER_MARK is the highest line number in the common file + described in any of the diffs in either of the USING lists. + HIGH_WATER_THREAD names the thread. Similarly BASE_WATER_MARK + and BASE_WATER_THREAD describe the lowest line number in the + common file described in any of the diffs in either of the USING + lists. HIGH_WATER_DIFF is the diff from which the + HIGH_WATER_MARK was taken. + + HIGH_WATER_DIFF should always be equal to + LAST_USING[HIGH_WATER_THREAD]. OTHER_DIFF is the next diff to + check for higher water, and should always be equal to + CURRENT[HIGH_WATER_THREAD ^ 1]. OTHER_THREAD is the thread in + which the OTHER_DIFF is, and hence should always be equal to + HIGH_WATER_THREAD ^ 1. + + LAST_DIFF is the last diff block produced by this routine, for + line correspondence purposes between that diff and the one + currently being worked on. It is ZERO_DIFF before any blocks + have been created. */ + + struct diff_block *using[2]; + struct diff_block *last_using[2]; + struct diff_block *current[2]; + + lin high_water_mark; + + int high_water_thread; + int base_water_thread; + int other_thread; + + struct diff_block *high_water_diff; + struct diff_block *other_diff; + + struct diff3_block *result; + struct diff3_block *tmpblock; + struct diff3_block **result_end; + + struct diff3_block const *last_diff3; + + static struct diff3_block const zero_diff3; + + /* Initialization */ + result = 0; + result_end = &result; + current[0] = thread0; current[1] = thread1; + last_diff3 = &zero_diff3; + + /* Sniff up the threads until we reach the end */ + + while (current[0] || current[1]) + { + using[0] = using[1] = last_using[0] = last_using[1] = 0; + + /* Setup low and high water threads, diffs, and marks. */ + if (!current[0]) + base_water_thread = 1; + else if (!current[1]) + base_water_thread = 0; + else + base_water_thread = + (D_LOWLINE (current[0], FC) > D_LOWLINE (current[1], FC)); + + high_water_thread = base_water_thread; + + high_water_diff = current[high_water_thread]; + + high_water_mark = D_HIGHLINE (high_water_diff, FC); + + /* Make the diff you just got info from into the using class */ + using[high_water_thread] + = last_using[high_water_thread] + = high_water_diff; + current[high_water_thread] = high_water_diff->next; + last_using[high_water_thread]->next = 0; + + /* And mark the other diff */ + other_thread = high_water_thread ^ 0x1; + other_diff = current[other_thread]; + + /* Shuffle up the ladder, checking the other diff to see if it + needs to be incorporated. */ + while (other_diff + && D_LOWLINE (other_diff, FC) <= high_water_mark + 1) + { + + /* Incorporate this diff into the using list. Note that + this doesn't take it off the current list */ + if (using[other_thread]) + last_using[other_thread]->next = other_diff; + else + using[other_thread] = other_diff; + last_using[other_thread] = other_diff; + + /* Take it off the current list. Note that this following + code assumes that other_diff enters it equal to + current[high_water_thread ^ 0x1] */ + current[other_thread] = current[other_thread]->next; + other_diff->next = 0; + + /* Set the high_water stuff + If this comparison is equal, then this is the last pass + through this loop; since diff blocks within a given + thread cannot overlap, the high_water_mark will be + *below* the range_start of either of the next diffs. */ + + if (high_water_mark < D_HIGHLINE (other_diff, FC)) + { + high_water_thread ^= 1; + high_water_diff = other_diff; + high_water_mark = D_HIGHLINE (other_diff, FC); + } + + /* Set the other diff */ + other_thread = high_water_thread ^ 0x1; + other_diff = current[other_thread]; + } + + /* The using lists contain a list of all of the blocks to be + included in this diff3_block. Create it. */ + + tmpblock = using_to_diff3_block (using, last_using, + base_water_thread, high_water_thread, + last_diff3); + + if (!tmpblock) + fatal ("internal error: screwup in format of diff blocks"); + + /* Put it on the list. */ + *result_end = tmpblock; + result_end = &tmpblock->next; + + /* Set up corresponding lines correctly. */ + last_diff3 = tmpblock; + } + return result; +} + +/* Take two lists of blocks (from two separate diff threads) and put + them together into one diff3 block. Return a pointer to this diff3 + block or 0 for failure. + + All arguments besides using are for the convenience of the routine; + they could be derived from the using array. LAST_USING is a pair + of pointers to the last blocks in the using structure. LOW_THREAD + and HIGH_THREAD tell which threads contain the lowest and highest + line numbers for File0. LAST_DIFF3 contains the last diff produced + in the calling routine. This is used for lines mappings that + would still be identical to the state that diff ended in. + + A distinction should be made in this routine between the two diffs + that are part of a normal two diff block, and the three diffs that + are part of a diff3_block. */ + +static struct diff3_block * +using_to_diff3_block (struct diff_block *using[2], + struct diff_block *last_using[2], + int low_thread, int high_thread, + struct diff3_block const *last_diff3) +{ + lin low[2], high[2]; + struct diff3_block *result; + struct diff_block *ptr; + int d; + lin i; + + /* Find the range in the common file. */ + lin lowc = D_LOWLINE (using[low_thread], FC); + lin highc = D_HIGHLINE (last_using[high_thread], FC); + + /* Find the ranges in the other files. + If using[d] is null, that means that the file to which that diff + refers is equivalent to the common file over this range. */ + + for (d = 0; d < 2; d++) + if (using[d]) + { + low[d] = D_LOW_MAPLINE (using[d], FC, FO, lowc); + high[d] = D_HIGH_MAPLINE (last_using[d], FC, FO, highc); + } + else + { + low[d] = D_HIGH_MAPLINE (last_diff3, FILEC, FILE0 + d, lowc); + high[d] = D_HIGH_MAPLINE (last_diff3, FILEC, FILE0 + d, highc); + } + + /* Create a block with the appropriate sizes */ + result = create_diff3_block (low[0], high[0], low[1], high[1], lowc, highc); + + /* Copy information for the common file. + Return with a zero if any of the compares failed. */ + + for (d = 0; d < 2; d++) + for (ptr = using[d]; ptr; ptr = D_NEXT (ptr)) + { + lin result_offset = D_LOWLINE (ptr, FC) - lowc; + + if (!copy_stringlist (D_LINEARRAY (ptr, FC), + D_LENARRAY (ptr, FC), + D_LINEARRAY (result, FILEC) + result_offset, + D_LENARRAY (result, FILEC) + result_offset, + D_NUMLINES (ptr, FC))) + return 0; + } + + /* Copy information for file d. First deal with anything that might be + before the first diff. */ + + for (d = 0; d < 2; d++) + { + struct diff_block *u = using[d]; + lin lo = low[d], hi = high[d]; + + for (i = 0; + i + lo < (u ? D_LOWLINE (u, FO) : hi + 1); + i++) + { + D_RELNUM (result, FILE0 + d, i) = D_RELNUM (result, FILEC, i); + D_RELLEN (result, FILE0 + d, i) = D_RELLEN (result, FILEC, i); + } + + for (ptr = u; ptr; ptr = D_NEXT (ptr)) + { + lin result_offset = D_LOWLINE (ptr, FO) - lo; + lin linec; + + if (!copy_stringlist (D_LINEARRAY (ptr, FO), + D_LENARRAY (ptr, FO), + D_LINEARRAY (result, FILE0 + d) + result_offset, + D_LENARRAY (result, FILE0 + d) + result_offset, + D_NUMLINES (ptr, FO))) + return 0; + + /* Catch the lines between here and the next diff */ + linec = D_HIGHLINE (ptr, FC) + 1 - lowc; + for (i = D_HIGHLINE (ptr, FO) + 1 - lo; + i < (D_NEXT (ptr) ? D_LOWLINE (D_NEXT (ptr), FO) : hi + 1) - lo; + i++) + { + D_RELNUM (result, FILE0 + d, i) = D_RELNUM (result, FILEC, linec); + D_RELLEN (result, FILE0 + d, i) = D_RELLEN (result, FILEC, linec); + linec++; + } + } + } + + /* Set correspond */ + if (!using[0]) + D3_TYPE (result) = DIFF_2ND; + else if (!using[1]) + D3_TYPE (result) = DIFF_1ST; + else + { + lin nl0 = D_NUMLINES (result, FILE0); + lin nl1 = D_NUMLINES (result, FILE1); + + if (nl0 != nl1 + || !compare_line_list (D_LINEARRAY (result, FILE0), + D_LENARRAY (result, FILE0), + D_LINEARRAY (result, FILE1), + D_LENARRAY (result, FILE1), + nl0)) + D3_TYPE (result) = DIFF_ALL; + else + D3_TYPE (result) = DIFF_3RD; + } + + return result; +} + +/* Copy pointers from a list of strings to a different list of + strings. If a spot in the second list is already filled, make sure + that it is filled with the same string; if not, return false, the copy + incomplete. Upon successful completion of the copy, return true. */ + +static bool +copy_stringlist (char * const fromptrs[], size_t const fromlengths[], + char *toptrs[], size_t tolengths[], + lin copynum) +{ + register char * const *f = fromptrs; + register char **t = toptrs; + register size_t const *fl = fromlengths; + register size_t *tl = tolengths; + + while (copynum--) + { + if (*t) + { + if (*fl != *tl || memcmp (*f, *t, *fl) != 0) + return false; + } + else + { + *t = *f; + *tl = *fl; + } + + t++; f++; tl++; fl++; + } + + return true; +} + +/* Create a diff3_block, with ranges as specified in the arguments. + Allocate the arrays for the various pointers (and zero them) based + on the arguments passed. Return the block as a result. */ + +static struct diff3_block * +create_diff3_block (lin low0, lin high0, + lin low1, lin high1, + lin low2, lin high2) +{ + struct diff3_block *result = xmalloc (sizeof *result); + lin numlines; + + D3_TYPE (result) = ERROR; + D_NEXT (result) = 0; + + /* Assign ranges */ + D_LOWLINE (result, FILE0) = low0; + D_HIGHLINE (result, FILE0) = high0; + D_LOWLINE (result, FILE1) = low1; + D_HIGHLINE (result, FILE1) = high1; + D_LOWLINE (result, FILE2) = low2; + D_HIGHLINE (result, FILE2) = high2; + + /* Allocate and zero space */ + numlines = D_NUMLINES (result, FILE0); + if (numlines) + { + D_LINEARRAY (result, FILE0) = xcalloc (numlines, sizeof (char *)); + D_LENARRAY (result, FILE0) = xcalloc (numlines, sizeof (size_t)); + } + else + { + D_LINEARRAY (result, FILE0) = 0; + D_LENARRAY (result, FILE0) = 0; + } + + numlines = D_NUMLINES (result, FILE1); + if (numlines) + { + D_LINEARRAY (result, FILE1) = xcalloc (numlines, sizeof (char *)); + D_LENARRAY (result, FILE1) = xcalloc (numlines, sizeof (size_t)); + } + else + { + D_LINEARRAY (result, FILE1) = 0; + D_LENARRAY (result, FILE1) = 0; + } + + numlines = D_NUMLINES (result, FILE2); + if (numlines) + { + D_LINEARRAY (result, FILE2) = xcalloc (numlines, sizeof (char *)); + D_LENARRAY (result, FILE2) = xcalloc (numlines, sizeof (size_t)); + } + else + { + D_LINEARRAY (result, FILE2) = 0; + D_LENARRAY (result, FILE2) = 0; + } + + /* Return */ + return result; +} + +/* Compare two lists of lines of text. + Return 1 if they are equivalent, 0 if not. */ + +static bool +compare_line_list (char * const list1[], size_t const lengths1[], + char * const list2[], size_t const lengths2[], + lin nl) +{ + char * const *l1 = list1; + char * const *l2 = list2; + size_t const *lgths1 = lengths1; + size_t const *lgths2 = lengths2; + + while (nl--) + if (!*l1 || !*l2 || *lgths1 != *lgths2++ + || memcmp (*l1++, *l2++, *lgths1++) != 0) + return false; + return true; +} + +/* Input and parse two way diffs. */ + +static struct diff_block * +process_diff (char const *filea, + char const *fileb, + struct diff_block **last_block) +{ + char *diff_contents; + char *diff_limit; + char *scan_diff; + enum diff_type dt; + lin i; + struct diff_block *block_list, **block_list_end, *bptr; + size_t too_many_lines = (PTRDIFF_MAX + / MIN (sizeof *bptr->lines[1], + sizeof *bptr->lengths[1])); + + diff_limit = read_diff (filea, fileb, &diff_contents); + scan_diff = diff_contents; + block_list_end = &block_list; + bptr = 0; /* Pacify `gcc -W'. */ + + while (scan_diff < diff_limit) + { + bptr = xmalloc (sizeof *bptr); + bptr->lines[0] = bptr->lines[1] = 0; + bptr->lengths[0] = bptr->lengths[1] = 0; + + dt = process_diff_control (&scan_diff, bptr); + if (dt == ERROR || *scan_diff != '\n') + { + fprintf (stderr, _("%s: diff failed: "), program_name); + do + { + putc (*scan_diff, stderr); + } + while (*scan_diff++ != '\n'); + exit (EXIT_TROUBLE); + } + scan_diff++; + + /* Force appropriate ranges to be null, if necessary */ + switch (dt) + { + case ADD: + bptr->ranges[0][0]++; + break; + case DELETE: + bptr->ranges[1][0]++; + break; + case CHANGE: + break; + default: + fatal ("internal error: invalid diff type in process_diff"); + break; + } + + /* Allocate space for the pointers for the lines from filea, and + parcel them out among these pointers */ + if (dt != ADD) + { + lin numlines = D_NUMLINES (bptr, 0); + if (too_many_lines <= numlines) + xalloc_die (); + bptr->lines[0] = xmalloc (numlines * sizeof *bptr->lines[0]); + bptr->lengths[0] = xmalloc (numlines * sizeof *bptr->lengths[0]); + for (i = 0; i < numlines; i++) + scan_diff = scan_diff_line (scan_diff, + &(bptr->lines[0][i]), + &(bptr->lengths[0][i]), + diff_limit, + '<'); + } + + /* Get past the separator for changes */ + if (dt == CHANGE) + { + if (strncmp (scan_diff, "---\n", 4)) + fatal ("invalid diff format; invalid change separator"); + scan_diff += 4; + } + + /* Allocate space for the pointers for the lines from fileb, and + parcel them out among these pointers */ + if (dt != DELETE) + { + lin numlines = D_NUMLINES (bptr, 1); + if (too_many_lines <= numlines) + xalloc_die (); + bptr->lines[1] = xmalloc (numlines * sizeof *bptr->lines[1]); + bptr->lengths[1] = xmalloc (numlines * sizeof *bptr->lengths[1]); + for (i = 0; i < numlines; i++) + scan_diff = scan_diff_line (scan_diff, + &(bptr->lines[1][i]), + &(bptr->lengths[1][i]), + diff_limit, + '>'); + } + + /* Place this block on the blocklist. */ + *block_list_end = bptr; + block_list_end = &bptr->next; + } + + *block_list_end = 0; + *last_block = bptr; + return block_list; +} + +/* Skip tabs and spaces, and return the first character after them. */ + +static char * +skipwhite (char *s) +{ + while (*s == ' ' || *s == '\t') + s++; + return s; +} + +/* Read a nonnegative line number from S, returning the address of the + first character after the line number, and storing the number into + *PNUM. Return 0 if S does not point to a valid line number. */ + +static char * +readnum (char *s, lin *pnum) +{ + unsigned char c = *s; + lin num = 0; + + if (! ISDIGIT (c)) + return 0; + + do + { + num = c - '0' + num * 10; + c = *++s; + } + while (ISDIGIT (c)); + + *pnum = num; + return s; +} + +/* Parse a normal format diff control string. Return the type of the + diff (ERROR if the format is bad). All of the other important + information is filled into to the structure pointed to by db, and + the string pointer (whose location is passed to this routine) is + updated to point beyond the end of the string parsed. Note that + only the ranges in the diff_block will be set by this routine. + + If some specific pair of numbers has been reduced to a single + number, then both corresponding numbers in the diff block are set + to that number. In general these numbers are interpreted as ranges + inclusive, unless being used by the ADD or DELETE commands. It is + assumed that these will be special cased in a superior routine. */ + +static enum diff_type +process_diff_control (char **string, struct diff_block *db) +{ + char *s = *string; + enum diff_type type; + + /* Read first set of digits */ + s = readnum (skipwhite (s), &db->ranges[0][RANGE_START]); + if (! s) + return ERROR; + + /* Was that the only digit? */ + s = skipwhite (s); + if (*s == ',') + { + s = readnum (s + 1, &db->ranges[0][RANGE_END]); + if (! s) + return ERROR; + } + else + db->ranges[0][RANGE_END] = db->ranges[0][RANGE_START]; + + /* Get the letter */ + s = skipwhite (s); + switch (*s) + { + case 'a': + type = ADD; + break; + case 'c': + type = CHANGE; + break; + case 'd': + type = DELETE; + break; + default: + return ERROR; /* Bad format */ + } + s++; /* Past letter */ + + /* Read second set of digits */ + s = readnum (skipwhite (s), &db->ranges[1][RANGE_START]); + if (! s) + return ERROR; + + /* Was that the only digit? */ + s = skipwhite (s); + if (*s == ',') + { + s = readnum (s + 1, &db->ranges[1][RANGE_END]); + if (! s) + return ERROR; + s = skipwhite (s); /* To move to end */ + } + else + db->ranges[1][RANGE_END] = db->ranges[1][RANGE_START]; + + *string = s; + return type; +} + +static char * +read_diff (char const *filea, + char const *fileb, + char **output_placement) +{ + char *diff_result; + size_t current_chunk_size, total; + int fd, wstatus, status; + int werrno = 0; + struct stat pipestat; + +#if HAVE_WORKING_FORK || HAVE_WORKING_VFORK + + char const *argv[9]; + char const **ap; + int fds[2]; + pid_t pid; + + ap = argv; + *ap++ = diff_program; + if (text) + *ap++ = "-a"; + if (strip_trailing_cr) + *ap++ = "--strip-trailing-cr"; + *ap++ = "--horizon-lines=100"; + *ap++ = "--"; + *ap++ = filea; + *ap++ = fileb; + *ap = 0; + + if (pipe (fds) != 0) + perror_with_exit ("pipe"); + + pid = vfork (); + if (pid == 0) + { + /* Child */ + close (fds[0]); + if (fds[1] != STDOUT_FILENO) + { + dup2 (fds[1], STDOUT_FILENO); + close (fds[1]); + } + + /* The cast to (char **) is needed for portability to older + hosts with a nonstandard prototype for execvp. */ + execvp (diff_program, (char **) argv); + + _exit (errno == ENOENT ? 127 : 126); + } + + if (pid == -1) + perror_with_exit ("fork"); + + close (fds[1]); /* Prevent erroneous lack of EOF */ + fd = fds[0]; + +#else + + FILE *fpipe; + char const args[] = " --horizon-lines=100 -- "; + char *command = xmalloc (quote_system_arg (0, diff_program) + + sizeof "-a" + + sizeof "--strip-trailing-cr" + + sizeof args - 1 + + quote_system_arg (0, filea) + 1 + + quote_system_arg (0, fileb) + 1); + char *p = command; + p += quote_system_arg (p, diff_program); + if (text) + { + strcpy (p, " -a"); + p += 3; + } + if (strip_trailing_cr) + { + strcpy (p, " --strip-trailing-cr"); + p += 20; + } + strcpy (p, args); + p += sizeof args - 1; + p += quote_system_arg (p, filea); + *p++ = ' '; + p += quote_system_arg (p, fileb); + *p = 0; + errno = 0; + fpipe = popen (command, "r"); + if (!fpipe) + perror_with_exit (command); + free (command); + fd = fileno (fpipe); + +#endif + + if (fstat (fd, &pipestat) != 0) + perror_with_exit ("fstat"); + current_chunk_size = MAX (1, STAT_BLOCKSIZE (pipestat)); + diff_result = xmalloc (current_chunk_size); + total = 0; + + for (;;) + { + size_t bytes_to_read = current_chunk_size - total; + size_t bytes = block_read (fd, diff_result + total, bytes_to_read); + total += bytes; + if (bytes != bytes_to_read) + { + if (bytes == SIZE_MAX) + perror_with_exit (_("read failed")); + break; + } + if (PTRDIFF_MAX / 2 <= current_chunk_size) + xalloc_die (); + current_chunk_size *= 2; + diff_result = xrealloc (diff_result, current_chunk_size); + } + + if (total != 0 && diff_result[total-1] != '\n') + fatal ("invalid diff format; incomplete last line"); + + *output_placement = diff_result; + +#if ! (HAVE_WORKING_FORK || HAVE_WORKING_VFORK) + + wstatus = pclose (fpipe); + if (wstatus == -1) + werrno = errno; + +#else + + if (close (fd) != 0) + perror_with_exit ("close"); + if (waitpid (pid, &wstatus, 0) < 0) + perror_with_exit ("waitpid"); + +#endif + + status = ! werrno && WIFEXITED (wstatus) ? WEXITSTATUS (wstatus) : INT_MAX; + + if (EXIT_TROUBLE <= status) + error (EXIT_TROUBLE, werrno, + _(status == 126 + ? "subsidiary program `%s' could not be invoked" + : status == 127 + ? "subsidiary program `%s' not found" + : status == INT_MAX + ? "subsidiary program `%s' failed" + : "subsidiary program `%s' failed (exit status %d)"), + diff_program, status); + + return diff_result + total; +} + + +/* Scan a regular diff line (consisting of > or <, followed by a + space, followed by text (including nulls) up to a newline. + + This next routine began life as a macro and many parameters in it + are used as call-by-reference values. */ +static char * +scan_diff_line (char *scan_ptr, char **set_start, size_t *set_length, + char *limit, char leadingchar) +{ + char *line_ptr; + + if (!(scan_ptr[0] == leadingchar + && scan_ptr[1] == ' ')) + fatal ("invalid diff format; incorrect leading line chars"); + + *set_start = line_ptr = scan_ptr + 2; + while (*line_ptr++ != '\n') + continue; + + /* Include newline if the original line ended in a newline, + or if an edit script is being generated. + Copy any missing newline message to stderr if an edit script is being + generated, because edit scripts cannot handle missing newlines. + Return the beginning of the next line. */ + *set_length = line_ptr - *set_start; + if (line_ptr < limit && *line_ptr == '\\') + { + if (edscript) + fprintf (stderr, "%s:", program_name); + else + --*set_length; + line_ptr++; + do + { + if (edscript) + putc (*line_ptr, stderr); + } + while (*line_ptr++ != '\n'); + } + + return line_ptr; +} + +/* Output a three way diff passed as a list of diff3_block's. The + argument MAPPING is indexed by external file number (in the + argument list) and contains the internal file number (from the diff + passed). This is important because the user expects outputs in + terms of the argument list number, and the diff passed may have + been done slightly differently (if the last argument was "-", for + example). REV_MAPPING is the inverse of MAPPING. */ + +static void +output_diff3 (FILE *outputfile, struct diff3_block *diff, + int const mapping[3], int const rev_mapping[3]) +{ + int i; + int oddoneout; + char *cp; + struct diff3_block *ptr; + lin line; + size_t length; + int dontprint; + static int skew_increment[3] = { 2, 3, 1 }; /* 0==>2==>1==>3 */ + char const *line_prefix = initial_tab ? "\t" : " "; + + for (ptr = diff; ptr; ptr = D_NEXT (ptr)) + { + char x[2]; + + switch (ptr->correspond) + { + case DIFF_ALL: + x[0] = 0; + dontprint = 3; /* Print them all */ + oddoneout = 3; /* Nobody's odder than anyone else */ + break; + case DIFF_1ST: + case DIFF_2ND: + case DIFF_3RD: + oddoneout = rev_mapping[ptr->correspond - DIFF_1ST]; + + x[0] = oddoneout + '1'; + x[1] = 0; + dontprint = oddoneout == 0; + break; + default: + fatal ("internal error: invalid diff type passed to output"); + } + fprintf (outputfile, "====%s\n", x); + + /* Go 0, 2, 1 if the first and third outputs are equivalent. */ + for (i = 0; i < 3; + i = (oddoneout == 1 ? skew_increment[i] : i + 1)) + { + int realfile = mapping[i]; + lin lowt = D_LOWLINE (ptr, realfile); + lin hight = D_HIGHLINE (ptr, realfile); + long int llowt = lowt; + long int lhight = hight; + + fprintf (outputfile, "%d:", i + 1); + switch (lowt - hight) + { + case 1: + fprintf (outputfile, "%lda\n", llowt - 1); + break; + case 0: + fprintf (outputfile, "%ldc\n", llowt); + break; + default: + fprintf (outputfile, "%ld,%ldc\n", llowt, lhight); + break; + } + + if (i == dontprint) continue; + + if (lowt <= hight) + { + line = 0; + do + { + fprintf (outputfile, line_prefix); + cp = D_RELNUM (ptr, realfile, line); + length = D_RELLEN (ptr, realfile, line); + fwrite (cp, sizeof (char), length, outputfile); + } + while (++line < hight - lowt + 1); + if (cp[length - 1] != '\n') + fprintf (outputfile, "\n\\ %s\n", + _("No newline at end of file")); + } + } + } +} + + +/* Output to OUTPUTFILE the lines of B taken from FILENUM. Double any + initial '.'s; yield nonzero if any initial '.'s were doubled. */ + +static bool +dotlines (FILE *outputfile, struct diff3_block *b, int filenum) +{ + lin i; + bool leading_dot = false; + + for (i = 0; + i < D_NUMLINES (b, filenum); + i++) + { + char *line = D_RELNUM (b, filenum, i); + if (line[0] == '.') + { + leading_dot = true; + fprintf (outputfile, "."); + } + fwrite (line, sizeof (char), + D_RELLEN (b, filenum, i), outputfile); + } + + return leading_dot; +} + +/* Output to OUTPUTFILE a '.' line. If LEADING_DOT is true, also + output a command that removes initial '.'s starting with line START + and continuing for NUM lines. (START is long int, not lin, for + convenience with printf %ld formats.) */ + +static void +undotlines (FILE *outputfile, bool leading_dot, long int start, lin num) +{ + fprintf (outputfile, ".\n"); + if (leading_dot) + { + if (num == 1) + fprintf (outputfile, "%lds/^\\.//\n", start); + else + fprintf (outputfile, "%ld,%lds/^\\.//\n", start, start + num - 1); + } +} + +/* Output a diff3 set of blocks as an ed script. This script applies + the changes between file's 2 & 3 to file 1. Take the precise + format of the ed script to be output from global variables set + during options processing. Reverse the order of + the set of diff3 blocks in DIFF; this gets + around the problems involved with changing line numbers in an ed + script. + + As in `output_diff3', the variable MAPPING maps from file number + according to the argument list to file number according to the diff + passed. All files listed below are in terms of the argument list. + REV_MAPPING is the inverse of MAPPING. + + FILE0, FILE1 and FILE2 are the strings to print as the names of the + three files. These may be the actual names, or may be the + arguments specified with -L. + + Return 1 if conflicts were found. */ + +static bool +output_diff3_edscript (FILE *outputfile, struct diff3_block *diff, + int const mapping[3], int const rev_mapping[3], + char const *file0, char const *file1, char const *file2) +{ + bool leading_dot; + bool conflicts_found = false; + bool conflict; + struct diff3_block *b; + + for (b = reverse_diff3_blocklist (diff); b; b = b->next) + { + /* Must do mapping correctly. */ + enum diff_type type + = (b->correspond == DIFF_ALL + ? DIFF_ALL + : DIFF_1ST + rev_mapping[b->correspond - DIFF_1ST]); + + long int low0, high0; + + /* If we aren't supposed to do this output block, skip it. */ + switch (type) + { + default: continue; + case DIFF_2ND: if (!show_2nd) continue; conflict = true; break; + case DIFF_3RD: if (overlap_only) continue; conflict = false; break; + case DIFF_ALL: if (simple_only) continue; conflict = flagging; break; + } + + low0 = D_LOWLINE (b, mapping[FILE0]); + high0 = D_HIGHLINE (b, mapping[FILE0]); + + if (conflict) + { + conflicts_found = true; + + + /* Mark end of conflict. */ + + fprintf (outputfile, "%lda\n", high0); + leading_dot = false; + if (type == DIFF_ALL) + { + if (show_2nd) + { + /* Append lines from FILE1. */ + fprintf (outputfile, "||||||| %s\n", file1); + leading_dot = dotlines (outputfile, b, mapping[FILE1]); + } + /* Append lines from FILE2. */ + fprintf (outputfile, "=======\n"); + leading_dot |= dotlines (outputfile, b, mapping[FILE2]); + } + fprintf (outputfile, ">>>>>>> %s\n", file2); + undotlines (outputfile, leading_dot, high0 + 2, + (D_NUMLINES (b, mapping[FILE1]) + + D_NUMLINES (b, mapping[FILE2]) + 1)); + + + /* Mark start of conflict. */ + + fprintf (outputfile, "%lda\n<<<<<<< %s\n", low0 - 1, + type == DIFF_ALL ? file0 : file1); + leading_dot = false; + if (type == DIFF_2ND) + { + /* Prepend lines from FILE1. */ + leading_dot = dotlines (outputfile, b, mapping[FILE1]); + fprintf (outputfile, "=======\n"); + } + undotlines (outputfile, leading_dot, low0 + 1, + D_NUMLINES (b, mapping[FILE1])); + } + else if (D_NUMLINES (b, mapping[FILE2]) == 0) + /* Write out a delete */ + { + if (low0 == high0) + fprintf (outputfile, "%ldd\n", low0); + else + fprintf (outputfile, "%ld,%ldd\n", low0, high0); + } + else + /* Write out an add or change */ + { + switch (high0 - low0) + { + case -1: + fprintf (outputfile, "%lda\n", high0); + break; + case 0: + fprintf (outputfile, "%ldc\n", high0); + break; + default: + fprintf (outputfile, "%ld,%ldc\n", low0, high0); + break; + } + + undotlines (outputfile, dotlines (outputfile, b, mapping[FILE2]), + low0, D_NUMLINES (b, mapping[FILE2])); + } + } + if (finalwrite) fprintf (outputfile, "w\nq\n"); + return conflicts_found; +} + +/* Read from INFILE and output to OUTPUTFILE a set of diff3_blocks + DIFF as a merged file. This acts like 'ed file0 + <[output_diff3_edscript]', except that it works even for binary + data or incomplete lines. + + As before, MAPPING maps from arg list file number to diff file + number, REV_MAPPING is its inverse, and FILE0, FILE1, and FILE2 are + the names of the files. + + Return 1 if conflicts were found. */ + +static bool +output_diff3_merge (FILE *infile, FILE *outputfile, struct diff3_block *diff, + int const mapping[3], int const rev_mapping[3], + char const *file0, char const *file1, char const *file2) +{ + int c; + lin i; + bool conflicts_found = false; + bool conflict; + struct diff3_block *b; + lin linesread = 0; + + for (b = diff; b; b = b->next) + { + /* Must do mapping correctly. */ + enum diff_type type + = ((b->correspond == DIFF_ALL) + ? DIFF_ALL + : DIFF_1ST + rev_mapping[b->correspond - DIFF_1ST]); + char const *format_2nd = "<<<<<<< %s\n"; + + /* If we aren't supposed to do this output block, skip it. */ + switch (type) + { + default: continue; + case DIFF_2ND: if (!show_2nd) continue; conflict = true; break; + case DIFF_3RD: if (overlap_only) continue; conflict = false; break; + case DIFF_ALL: if (simple_only) continue; conflict = flagging; + format_2nd = "||||||| %s\n"; + break; + } + + /* Copy I lines from file 0. */ + i = D_LOWLINE (b, FILE0) - linesread - 1; + linesread += i; + while (0 <= --i) + do + { + c = getc (infile); + if (c == EOF) + { + if (ferror (infile)) + perror_with_exit (_("read failed")); + else if (feof (infile)) + fatal ("input file shrank"); + } + putc (c, outputfile); + } + while (c != '\n'); + + if (conflict) + { + conflicts_found = true; + + if (type == DIFF_ALL) + { + /* Put in lines from FILE0 with bracket. */ + fprintf (outputfile, "<<<<<<< %s\n", file0); + for (i = 0; + i < D_NUMLINES (b, mapping[FILE0]); + i++) + fwrite (D_RELNUM (b, mapping[FILE0], i), sizeof (char), + D_RELLEN (b, mapping[FILE0], i), outputfile); + } + + if (show_2nd) + { + /* Put in lines from FILE1 with bracket. */ + fprintf (outputfile, format_2nd, file1); + for (i = 0; + i < D_NUMLINES (b, mapping[FILE1]); + i++) + fwrite (D_RELNUM (b, mapping[FILE1], i), sizeof (char), + D_RELLEN (b, mapping[FILE1], i), outputfile); + } + + fprintf (outputfile, "=======\n"); + } + + /* Put in lines from FILE2. */ + for (i = 0; + i < D_NUMLINES (b, mapping[FILE2]); + i++) + fwrite (D_RELNUM (b, mapping[FILE2], i), sizeof (char), + D_RELLEN (b, mapping[FILE2], i), outputfile); + + if (conflict) + fprintf (outputfile, ">>>>>>> %s\n", file2); + + /* Skip I lines in file 0. */ + i = D_NUMLINES (b, FILE0); + linesread += i; + while (0 <= --i) + while ((c = getc (infile)) != '\n') + if (c == EOF) + { + if (ferror (infile)) + perror_with_exit (_("read failed")); + else if (feof (infile)) + { + if (i || b->next) + fatal ("input file shrank"); + return conflicts_found; + } + } + } + /* Copy rest of common file. */ + while ((c = getc (infile)) != EOF || !(ferror (infile) | feof (infile))) + putc (c, outputfile); + return conflicts_found; +} + +/* Reverse the order of the list of diff3 blocks. */ + +static struct diff3_block * +reverse_diff3_blocklist (struct diff3_block *diff) +{ + register struct diff3_block *tmp, *next, *prev; + + for (tmp = diff, prev = 0; tmp; tmp = next) + { + next = tmp->next; + tmp->next = prev; + prev = tmp; + } + + return prev; +} + +static void +fatal (char const *msgid) +{ + error (EXIT_TROUBLE, 0, "%s", _(msgid)); + abort (); +} + +static void +perror_with_exit (char const *string) +{ + error (EXIT_TROUBLE, errno, "%s", string); + abort (); +} diff --git a/contrib/diffutils-2.8/src/dir.c b/contrib/diffutils-2.8/src/dir.c new file mode 100644 index 0000000000..cc0c8793fd --- /dev/null +++ b/contrib/diffutils-2.8/src/dir.c @@ -0,0 +1,288 @@ +/* Read, sort and compare two directories. Used for GNU DIFF. + + Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1998, 2001, 2002, + 2004 Free Software Foundation, Inc. + + This file is part of GNU DIFF. + + GNU DIFF is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GNU DIFF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "diff.h" +#include +#include +#include +#include +#include + +/* Read the directory named by DIR and store into DIRDATA a sorted vector + of filenames for its contents. DIR->desc == -1 means this directory is + known to be nonexistent, so set DIRDATA to an empty vector. + Return -1 (setting errno) if error, 0 otherwise. */ + +struct dirdata +{ + size_t nnames; /* Number of names. */ + char const **names; /* Sorted names of files in dir, followed by 0. */ + char *data; /* Allocated storage for file names. */ +}; + +/* Whether file names in directories should be compared with + locale-specific sorting. */ +static bool locale_specific_sorting; + +/* Where to go if locale-specific sorting fails. */ +static jmp_buf failed_locale_specific_sorting; + +static bool dir_loop (struct comparison const *, int); +static int compare_names_for_qsort (void const *, void const *); + + +/* Read a directory and get its vector of names. */ + +static bool +dir_read (struct file_data const *dir, struct dirdata *dirdata) +{ + register struct dirent *next; + register size_t i; + + /* Address of block containing the files that are described. */ + char const **names; + + /* Number of files in directory. */ + size_t nnames; + + /* Allocated and used storage for file name data. */ + char *data; + size_t data_alloc, data_used; + + dirdata->names = 0; + dirdata->data = 0; + nnames = 0; + data = 0; + + if (dir->desc != -1) + { + /* Open the directory and check for errors. */ + register DIR *reading = opendir (dir->name); + if (!reading) + return false; + + /* Initialize the table of filenames. */ + + data_alloc = 512; + data_used = 0; + dirdata->data = data = xmalloc (data_alloc); + + /* Read the directory entries, and insert the subfiles + into the `data' table. */ + + while ((errno = 0, (next = readdir (reading)) != 0)) + { + char *d_name = next->d_name; + size_t d_size = NAMLEN (next) + 1; + + /* Ignore "." and "..". */ + if (d_name[0] == '.' + && (d_name[1] == 0 || (d_name[1] == '.' && d_name[2] == 0))) + continue; + + if (excluded_filename (excluded, d_name)) + continue; + + while (data_alloc < data_used + d_size) + { + if (PTRDIFF_MAX / 2 <= data_alloc) + xalloc_die (); + dirdata->data = data = xrealloc (data, data_alloc *= 2); + } + + memcpy (data + data_used, d_name, d_size); + data_used += d_size; + nnames++; + } + if (errno) + { + int e = errno; + closedir (reading); + errno = e; + return false; + } +#if CLOSEDIR_VOID + closedir (reading); +#else + if (closedir (reading) != 0) + return false; +#endif + } + + /* Create the `names' table from the `data' table. */ + if (PTRDIFF_MAX / sizeof *names - 1 <= nnames) + xalloc_die (); + dirdata->names = names = xmalloc ((nnames + 1) * sizeof *names); + dirdata->nnames = nnames; + for (i = 0; i < nnames; i++) + { + names[i] = data; + data += strlen (data) + 1; + } + names[nnames] = 0; + return true; +} + +/* Compare file names, returning a value compatible with strcmp. */ + +static int +compare_names (char const *name1, char const *name2) +{ + if (locale_specific_sorting) + { + int r; + errno = 0; + if (ignore_file_name_case) + r = strcasecoll (name1, name2); + else + r = strcoll (name1, name2); + if (errno) + { + error (0, errno, _("cannot compare file names `%s' and `%s'"), + name1, name2); + longjmp (failed_locale_specific_sorting, 1); + } + return r; + } + + return (ignore_file_name_case + ? strcasecmp (name1, name2) + : file_name_cmp (name1, name2)); +} + +/* A wrapper for compare_names suitable as an argument for qsort. */ + +static int +compare_names_for_qsort (void const *file1, void const *file2) +{ + char const *const *f1 = file1; + char const *const *f2 = file2; + return compare_names (*f1, *f2); +} + +/* Compare the contents of two directories named in CMP. + This is a top-level routine; it does everything necessary for diff + on two directories. + + CMP->file[0].desc == -1 says directory CMP->file[0] doesn't exist, + but pretend it is empty. Likewise for CMP->file[1]. + + HANDLE_FILE is a caller-provided subroutine called to handle each file. + It gets three operands: CMP, name of file in dir 0, name of file in dir 1. + These names are relative to the original working directory. + + For a file that appears in only one of the dirs, one of the name-args + to HANDLE_FILE is zero. + + Returns the maximum of all the values returned by HANDLE_FILE, + or EXIT_TROUBLE if trouble is encountered in opening files. */ + +int +diff_dirs (struct comparison const *cmp, + int (*handle_file) (struct comparison const *, + char const *, char const *)) +{ + struct dirdata dirdata[2]; + int volatile val = EXIT_SUCCESS; + int i; + + if ((cmp->file[0].desc == -1 || dir_loop (cmp, 0)) + && (cmp->file[1].desc == -1 || dir_loop (cmp, 1))) + { + error (0, 0, "%s: recursive directory loop", + cmp->file[cmp->file[0].desc == -1].name); + return EXIT_TROUBLE; + } + + /* Get contents of both dirs. */ + for (i = 0; i < 2; i++) + if (! dir_read (&cmp->file[i], &dirdata[i])) + { + perror_with_name (cmp->file[i].name); + val = EXIT_TROUBLE; + } + + if (val == EXIT_SUCCESS) + { + char const **volatile names[2]; + names[0] = dirdata[0].names; + names[1] = dirdata[1].names; + + /* Use locale-specific sorting if possible, else native byte order. */ + locale_specific_sorting = true; + if (setjmp (failed_locale_specific_sorting)) + locale_specific_sorting = false; + + /* Sort the directories. */ + for (i = 0; i < 2; i++) + qsort (names[i], dirdata[i].nnames, sizeof *dirdata[i].names, + compare_names_for_qsort); + + /* If `-S name' was given, and this is the topmost level of comparison, + ignore all file names less than the specified starting name. */ + + if (starting_file && ! cmp->parent) + { + while (*names[0] && compare_names (*names[0], starting_file) < 0) + names[0]++; + while (*names[1] && compare_names (*names[1], starting_file) < 0) + names[1]++; + } + + /* Loop while files remain in one or both dirs. */ + while (*names[0] || *names[1]) + { + /* Compare next name in dir 0 with next name in dir 1. + At the end of a dir, + pretend the "next name" in that dir is very large. */ + int nameorder = (!*names[0] ? 1 : !*names[1] ? -1 + : compare_names (*names[0], *names[1])); + int v1 = (*handle_file) (cmp, + 0 < nameorder ? 0 : *names[0]++, + nameorder < 0 ? 0 : *names[1]++); + if (val < v1) + val = v1; + } + } + + for (i = 0; i < 2; i++) + { + if (dirdata[i].names) + free (dirdata[i].names); + if (dirdata[i].data) + free (dirdata[i].data); + } + + return val; +} + +/* Return nonzero if CMP is looping recursively in argument I. */ + +static bool +dir_loop (struct comparison const *cmp, int i) +{ + struct comparison const *p = cmp; + while ((p = p->parent)) + if (0 < same_file (&p->file[i].stat, &cmp->file[i].stat)) + return true; + return false; +} diff --git a/contrib/diffutils-2.8/src/ed.c b/contrib/diffutils-2.8/src/ed.c new file mode 100644 index 0000000000..c90ed78f0d --- /dev/null +++ b/contrib/diffutils-2.8/src/ed.c @@ -0,0 +1,169 @@ +/* Output routines for ed-script format. + + Copyright (C) 1988, 1989, 1991, 1992, 1993, 1995, 1998, 2001, 2004 + Free Software Foundation, Inc. + + This file is part of GNU DIFF. + + GNU DIFF is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GNU DIFF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "diff.h" + +static void print_ed_hunk (struct change *); +static void print_rcs_hunk (struct change *); +static void pr_forward_ed_hunk (struct change *); + +/* Print our script as ed commands. */ + +void +print_ed_script (struct change *script) +{ + print_script (script, find_reverse_change, print_ed_hunk); +} + +/* Print a hunk of an ed diff */ + +static void +print_ed_hunk (struct change *hunk) +{ + lin f0, l0, f1, l1; + enum changes changes; + +#ifdef DEBUG + debug_script (hunk); +#endif + + /* Determine range of line numbers involved in each file. */ + changes = analyze_hunk (hunk, &f0, &l0, &f1, &l1); + if (!changes) + return; + + begin_output (); + + /* Print out the line number header for this hunk */ + print_number_range (',', &files[0], f0, l0); + fprintf (outfile, "%c\n", change_letter[changes]); + + /* Print new/changed lines from second file, if needed */ + if (changes != OLD) + { + lin i; + for (i = f1; i <= l1; i++) + { + if (files[1].linbuf[i][0] == '.' && files[1].linbuf[i][1] == '\n') + { + /* The file's line is just a dot, and it would exit + insert mode. Precede the dot with another dot, exit + insert mode, remove the extra dot, and then resume + insert mode. */ + fprintf (outfile, "..\n.\ns/.//\na\n"); + } + else + print_1_line ("", &files[1].linbuf[i]); + } + + fprintf (outfile, ".\n"); + } +} + +/* Print change script in the style of ed commands, + but print the changes in the order they appear in the input files, + which means that the commands are not truly useful with ed. */ + +void +pr_forward_ed_script (struct change *script) +{ + print_script (script, find_change, pr_forward_ed_hunk); +} + +static void +pr_forward_ed_hunk (struct change *hunk) +{ + lin i, f0, l0, f1, l1; + + /* Determine range of line numbers involved in each file. */ + enum changes changes = analyze_hunk (hunk, &f0, &l0, &f1, &l1); + if (!changes) + return; + + begin_output (); + + fprintf (outfile, "%c", change_letter[changes]); + print_number_range (' ', files, f0, l0); + fprintf (outfile, "\n"); + + /* If deletion only, print just the number range. */ + + if (changes == OLD) + return; + + /* For insertion (with or without deletion), print the number range + and the lines from file 2. */ + + for (i = f1; i <= l1; i++) + print_1_line ("", &files[1].linbuf[i]); + + fprintf (outfile, ".\n"); +} + +/* Print in a format somewhat like ed commands + except that each insert command states the number of lines it inserts. + This format is used for RCS. */ + +void +print_rcs_script (struct change *script) +{ + print_script (script, find_change, print_rcs_hunk); +} + +/* Print a hunk of an RCS diff */ + +static void +print_rcs_hunk (struct change *hunk) +{ + lin i, f0, l0, f1, l1; + long int tf0, tl0, tf1, tl1; + + /* Determine range of line numbers involved in each file. */ + enum changes changes = analyze_hunk (hunk, &f0, &l0, &f1, &l1); + if (!changes) + return; + + begin_output (); + + translate_range (&files[0], f0, l0, &tf0, &tl0); + + if (changes & OLD) + { + fprintf (outfile, "d"); + /* For deletion, print just the starting line number from file 0 + and the number of lines deleted. */ + fprintf (outfile, "%ld %ld\n", tf0, tf0 <= tl0 ? tl0 - tf0 + 1 : 1); + } + + if (changes & NEW) + { + fprintf (outfile, "a"); + + /* Take last-line-number from file 0 and # lines from file 1. */ + translate_range (&files[1], f1, l1, &tf1, &tl1); + fprintf (outfile, "%ld %ld\n", tl0, tf1 <= tl1 ? tl1 - tf1 + 1 : 1); + + /* Print the inserted lines. */ + for (i = f1; i <= l1; i++) + print_1_line ("", &files[1].linbuf[i]); + } +} diff --git a/contrib/diffutils-2.8/src/ifdef.c b/contrib/diffutils-2.8/src/ifdef.c new file mode 100644 index 0000000000..22f1cb1fa9 --- /dev/null +++ b/contrib/diffutils-2.8/src/ifdef.c @@ -0,0 +1,430 @@ +/* #ifdef-format output routines for GNU DIFF. + + Copyright (C) 1989, 1991, 1992, 1993, 1994, 2001, 2002, 2004 Free + Software Foundation, Inc. + + This file is part of GNU DIFF. + + GNU DIFF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. No author or distributor + accepts responsibility to anyone for the consequences of using it + or for whether it serves any particular purpose or works at all, + unless he says so in writing. Refer to the GNU DIFF General Public + License for full details. + + Everyone is granted permission to copy, modify and redistribute + GNU DIFF, but only under the conditions described in the + GNU DIFF General Public License. A copy of this license is + supposed to have been given to you along with GNU DIFF so you + can know your rights and responsibilities. It should be in a + file named COPYING. Among other things, the copyright notice + and this notice must be preserved on all copies. */ + +#include "diff.h" + +#include + +struct group +{ + struct file_data const *file; + lin from, upto; /* start and limit lines for this group of lines */ +}; + +static char const *format_group (FILE *, char const *, char, + struct group const *); +static char const *do_printf_spec (FILE *, char const *, + struct file_data const *, lin, + struct group const *); +static char const *scan_char_literal (char const *, char *); +static lin groups_letter_value (struct group const *, char); +static void format_ifdef (char const *, lin, lin, lin, lin); +static void print_ifdef_hunk (struct change *); +static void print_ifdef_lines (FILE *, char const *, struct group const *); + +static lin next_line0; +static lin next_line1; + +/* Print the edit-script SCRIPT as a merged #ifdef file. */ + +void +print_ifdef_script (struct change *script) +{ + next_line0 = next_line1 = - files[0].prefix_lines; + print_script (script, find_change, print_ifdef_hunk); + if (next_line0 < files[0].valid_lines + || next_line1 < files[1].valid_lines) + { + begin_output (); + format_ifdef (group_format[UNCHANGED], + next_line0, files[0].valid_lines, + next_line1, files[1].valid_lines); + } +} + +/* Print a hunk of an ifdef diff. + This is a contiguous portion of a complete edit script, + describing changes in consecutive lines. */ + +static void +print_ifdef_hunk (struct change *hunk) +{ + lin first0, last0, first1, last1; + + /* Determine range of line numbers involved in each file. */ + enum changes changes = analyze_hunk (hunk, &first0, &last0, &first1, &last1); + if (!changes) + return; + + begin_output (); + + /* Print lines up to this change. */ + if (next_line0 < first0 || next_line1 < first1) + format_ifdef (group_format[UNCHANGED], + next_line0, first0, + next_line1, first1); + + /* Print this change. */ + next_line0 = last0 + 1; + next_line1 = last1 + 1; + format_ifdef (group_format[changes], + first0, next_line0, + first1, next_line1); +} + +/* Print a set of lines according to FORMAT. + Lines BEG0 up to END0 are from the first file; + lines BEG1 up to END1 are from the second file. */ + +static void +format_ifdef (char const *format, lin beg0, lin end0, lin beg1, lin end1) +{ + struct group groups[2]; + + groups[0].file = &files[0]; + groups[0].from = beg0; + groups[0].upto = end0; + groups[1].file = &files[1]; + groups[1].from = beg1; + groups[1].upto = end1; + format_group (outfile, format, 0, groups); +} + +/* Print to file OUT a set of lines according to FORMAT. + The format ends at the first free instance of ENDCHAR. + Yield the address of the terminating character. + GROUPS specifies which lines to print. + If OUT is zero, do not actually print anything; just scan the format. */ + +static char const * +format_group (register FILE *out, char const *format, char endchar, + struct group const *groups) +{ + register char c; + register char const *f = format; + + while ((c = *f) != endchar && c != 0) + { + char const *f1 = ++f; + if (c == '%') + switch ((c = *f++)) + { + case '%': + break; + + case '(': + /* Print if-then-else format e.g. `%(n=1?thenpart:elsepart)'. */ + { + int i; + uintmax_t value[2]; + FILE *thenout, *elseout; + + for (i = 0; i < 2; i++) + { + if (ISDIGIT (*f)) + { + char *fend; + errno = 0; + value[i] = strtoumax (f, &fend, 10); + if (errno) + goto bad_format; + f = fend; + } + else + { + value[i] = groups_letter_value (groups, *f); + if (value[i] == -1) + goto bad_format; + f++; + } + if (*f++ != "=?"[i]) + goto bad_format; + } + if (value[0] == value[1]) + thenout = out, elseout = 0; + else + thenout = 0, elseout = out; + f = format_group (thenout, f, ':', groups); + if (*f) + { + f = format_group (elseout, f + 1, ')', groups); + if (*f) + f++; + } + } + continue; + + case '<': + /* Print lines deleted from first file. */ + print_ifdef_lines (out, line_format[OLD], &groups[0]); + continue; + + case '=': + /* Print common lines. */ + print_ifdef_lines (out, line_format[UNCHANGED], &groups[0]); + continue; + + case '>': + /* Print lines inserted from second file. */ + print_ifdef_lines (out, line_format[NEW], &groups[1]); + continue; + + default: + f = do_printf_spec (out, f - 2, 0, 0, groups); + if (f) + continue; + /* Fall through. */ + bad_format: + c = '%'; + f = f1; + break; + } + + if (out) + putc (c, out); + } + + return f; +} + +/* For the line group pair G, return the number corresponding to LETTER. + Return -1 if LETTER is not a group format letter. */ +static lin +groups_letter_value (struct group const *g, char letter) +{ + switch (letter) + { + case 'E': letter = 'e'; g++; break; + case 'F': letter = 'f'; g++; break; + case 'L': letter = 'l'; g++; break; + case 'M': letter = 'm'; g++; break; + case 'N': letter = 'n'; g++; break; + } + + switch (letter) + { + case 'e': return translate_line_number (g->file, g->from) - 1; + case 'f': return translate_line_number (g->file, g->from); + case 'l': return translate_line_number (g->file, g->upto) - 1; + case 'm': return translate_line_number (g->file, g->upto); + case 'n': return g->upto - g->from; + default: return -1; + } +} + +/* Print to file OUT, using FORMAT to print the line group GROUP. + But do nothing if OUT is zero. */ +static void +print_ifdef_lines (register FILE *out, char const *format, + struct group const *group) +{ + struct file_data const *file = group->file; + char const * const *linbuf = file->linbuf; + lin from = group->from, upto = group->upto; + + if (!out) + return; + + /* If possible, use a single fwrite; it's faster. */ + if (!expand_tabs && format[0] == '%') + { + if (format[1] == 'l' && format[2] == '\n' && !format[3] && from < upto) + { + fwrite (linbuf[from], sizeof (char), + linbuf[upto] + (linbuf[upto][-1] != '\n') - linbuf[from], + out); + return; + } + if (format[1] == 'L' && !format[2]) + { + fwrite (linbuf[from], sizeof (char), + linbuf[upto] - linbuf[from], out); + return; + } + } + + for (; from < upto; from++) + { + register char c; + register char const *f = format; + + while ((c = *f++) != 0) + { + char const *f1 = f; + if (c == '%') + switch ((c = *f++)) + { + case '%': + break; + + case 'l': + output_1_line (linbuf[from], + (linbuf[from + 1] + - (linbuf[from + 1][-1] == '\n')), + 0, 0); + continue; + + case 'L': + output_1_line (linbuf[from], linbuf[from + 1], 0, 0); + continue; + + default: + f = do_printf_spec (out, f - 2, file, from, 0); + if (f) + continue; + c = '%'; + f = f1; + break; + } + + putc (c, out); + } + } +} + +static char const * +do_printf_spec (FILE *out, char const *spec, + struct file_data const *file, lin n, + struct group const *groups) +{ + char const *f = spec; + char c; + char c1; + + /* Scan printf-style SPEC of the form %[-'0]*[0-9]*(.[0-9]*)?[cdoxX]. */ + /* assert (*f == '%'); */ + f++; + while ((c = *f++) == '-' || c == '\'' || c == '0') + continue; + while (ISDIGIT (c)) + c = *f++; + if (c == '.') + while (ISDIGIT (c = *f++)) + continue; + c1 = *f++; + + switch (c) + { + case 'c': + if (c1 != '\'') + return 0; + else + { + char value; + f = scan_char_literal (f, &value); + if (!f) + return 0; + if (out) + putc (value, out); + } + break; + + case 'd': case 'o': case 'x': case 'X': + { + lin value; + + if (file) + { + if (c1 != 'n') + return 0; + value = translate_line_number (file, n); + } + else + { + value = groups_letter_value (groups, c1); + if (value < 0) + return 0; + } + + if (out) + { + /* For example, if the spec is "%3xn", use the printf + format spec "%3lx". Here the spec prefix is "%3". */ + long int long_value = value; + size_t spec_prefix_len = f - spec - 2; +#if HAVE_C_VARARRAYS + char format[spec_prefix_len + 3]; +#else + char *format = xmalloc (spec_prefix_len + 3); +#endif + char *p = format + spec_prefix_len; + memcpy (format, spec, spec_prefix_len); + *p++ = 'l'; + *p++ = c; + *p = '\0'; + fprintf (out, format, long_value); +#if ! HAVE_C_VARARRAYS + free (format); +#endif + } + } + break; + + default: + return 0; + } + + return f; +} + +/* Scan the character literal represented in the string LIT; LIT points just + after the initial apostrophe. Put the literal's value into *VALPTR. + Yield the address of the first character after the closing apostrophe, + or zero if the literal is ill-formed. */ +static char const * +scan_char_literal (char const *lit, char *valptr) +{ + register char const *p = lit; + char value; + ptrdiff_t digits; + char c = *p++; + + switch (c) + { + case 0: + case '\'': + return 0; + + case '\\': + value = 0; + while ((c = *p++) != '\'') + { + unsigned int digit = c - '0'; + if (8 <= digit) + return 0; + value = 8 * value + digit; + } + digits = p - lit - 2; + if (! (1 <= digits && digits <= 3)) + return 0; + break; + + default: + value = c; + if (*p++ != '\'') + return 0; + break; + } + + *valptr = value; + return p; +} diff --git a/contrib/diffutils-2.8/src/io.c b/contrib/diffutils-2.8/src/io.c new file mode 100644 index 0000000000..3ddc1f8ab3 --- /dev/null +++ b/contrib/diffutils-2.8/src/io.c @@ -0,0 +1,859 @@ +/* File I/O for GNU DIFF. + + Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1998, 2001, 2002, + 2004 Free Software Foundation, Inc. + + This file is part of GNU DIFF. + + GNU DIFF is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GNU DIFF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "diff.h" +#include +#include +#include +#include + +/* Rotate an unsigned value to the left. */ +#define ROL(v, n) ((v) << (n) | (v) >> (sizeof (v) * CHAR_BIT - (n))) + +/* Given a hash value and a new character, return a new hash value. */ +#define HASH(h, c) ((c) + ROL (h, 7)) + +/* The type of a hash value. */ +typedef size_t hash_value; +verify (hash_value_is_unsigned, ! TYPE_SIGNED (hash_value)); + +/* Lines are put into equivalence classes of lines that match in lines_differ. + Each equivalence class is represented by one of these structures, + but only while the classes are being computed. + Afterward, each class is represented by a number. */ +struct equivclass +{ + lin next; /* Next item in this bucket. */ + hash_value hash; /* Hash of lines in this class. */ + char const *line; /* A line that fits this class. */ + size_t length; /* That line's length, not counting its newline. */ +}; + +/* Hash-table: array of buckets, each being a chain of equivalence classes. + buckets[-1] is reserved for incomplete lines. */ +static lin *buckets; + +/* Number of buckets in the hash table array, not counting buckets[-1]. */ +static size_t nbuckets; + +/* Array in which the equivalence classes are allocated. + The bucket-chains go through the elements in this array. + The number of an equivalence class is its index in this array. */ +static struct equivclass *equivs; + +/* Index of first free element in the array `equivs'. */ +static lin equivs_index; + +/* Number of elements allocated in the array `equivs'. */ +static lin equivs_alloc; + +/* Read a block of data into a file buffer, checking for EOF and error. */ + +void +file_block_read (struct file_data *current, size_t size) +{ + if (size && ! current->eof) + { + size_t s = block_read (current->desc, + FILE_BUFFER (current) + current->buffered, size); + if (s == SIZE_MAX) + pfatal_with_name (current->name); + current->buffered += s; + current->eof = s < size; + } +} + +/* Check for binary files and compare them for exact identity. */ + +/* Return 1 if BUF contains a non text character. + SIZE is the number of characters in BUF. */ + +#define binary_file_p(buf, size) (memchr (buf, 0, size) != 0) + +/* Get ready to read the current file. + Return nonzero if SKIP_TEST is zero, + and if it appears to be a binary file. */ + +static bool +sip (struct file_data *current, bool skip_test) +{ + /* If we have a nonexistent file at this stage, treat it as empty. */ + if (current->desc < 0) + { + /* Leave room for a sentinel. */ + current->bufsize = sizeof (word); + current->buffer = xmalloc (current->bufsize); + } + else + { + current->bufsize = buffer_lcm (sizeof (word), + STAT_BLOCKSIZE (current->stat), + PTRDIFF_MAX - 2 * sizeof (word)); + current->buffer = xmalloc (current->bufsize); + + if (! skip_test) + { + /* Check first part of file to see if it's a binary file. */ + + bool was_binary = set_binary_mode (current->desc, true); + off_t buffered; + file_block_read (current, current->bufsize); + buffered = current->buffered; + + if (! was_binary) + { + /* Revert to text mode and seek back to the beginning to + reread the file. Use relative seek, since file + descriptors like stdin might not start at offset + zero. */ + + if (lseek (current->desc, - buffered, SEEK_CUR) == -1) + pfatal_with_name (current->name); + set_binary_mode (current->desc, false); + current->buffered = 0; + current->eof = false; + } + + return binary_file_p (current->buffer, buffered); + } + } + + current->buffered = 0; + current->eof = false; + return false; +} + +/* Slurp the rest of the current file completely into memory. */ + +static void +slurp (struct file_data *current) +{ + size_t cc; + + if (current->desc < 0) + { + /* The file is nonexistent. */ + return; + } + + if (S_ISREG (current->stat.st_mode)) + { + /* It's a regular file; slurp in the rest all at once. */ + + /* Get the size out of the stat block. + Allocate just enough room for appended newline plus word sentinel, + plus word-alignment since we want the buffer word-aligned. */ + size_t file_size = current->stat.st_size; + cc = file_size + 2 * sizeof (word) - file_size % sizeof (word); + if (file_size != current->stat.st_size || cc < file_size + || PTRDIFF_MAX <= cc) + xalloc_die (); + + if (current->bufsize < cc) + { + current->bufsize = cc; + current->buffer = xrealloc (current->buffer, cc); + } + + /* Try to read at least 1 more byte than the size indicates, to + detect whether the file is growing. This is a nicety for + users who run 'diff' on files while they are changing. */ + + if (current->buffered <= file_size) + { + file_block_read (current, file_size + 1 - current->buffered); + if (current->buffered <= file_size) + return; + } + } + + /* It's not a regular file, or it's a growing regular file; read it, + growing the buffer as needed. */ + + file_block_read (current, current->bufsize - current->buffered); + + if (current->buffered) + { + while (current->buffered == current->bufsize) + { + if (PTRDIFF_MAX / 2 - sizeof (word) < current->bufsize) + xalloc_die (); + current->bufsize *= 2; + current->buffer = xrealloc (current->buffer, current->bufsize); + file_block_read (current, current->bufsize - current->buffered); + } + + /* Allocate just enough room for appended newline plus word + sentinel, plus word-alignment. */ + cc = current->buffered + 2 * sizeof (word); + current->bufsize = cc - cc % sizeof (word); + current->buffer = xrealloc (current->buffer, current->bufsize); + } +} + +/* Split the file into lines, simultaneously computing the equivalence + class for each line. */ + +static void +find_and_hash_each_line (struct file_data *current) +{ + hash_value h; + char const *p = current->prefix_end; + unsigned char c; + lin i, *bucket; + size_t length; + + /* Cache often-used quantities in local variables to help the compiler. */ + char const **linbuf = current->linbuf; + lin alloc_lines = current->alloc_lines; + lin line = 0; + lin linbuf_base = current->linbuf_base; + lin *cureqs = xmalloc (alloc_lines * sizeof *cureqs); + struct equivclass *eqs = equivs; + lin eqs_index = equivs_index; + lin eqs_alloc = equivs_alloc; + char const *suffix_begin = current->suffix_begin; + char const *bufend = FILE_BUFFER (current) + current->buffered; + bool diff_length_compare_anyway = + ignore_white_space != IGNORE_NO_WHITE_SPACE; + bool same_length_diff_contents_compare_anyway = + diff_length_compare_anyway | ignore_case; + + while (p < suffix_begin) + { + char const *ip = p; + + h = 0; + + /* Hash this line until we find a newline. */ + if (ignore_case) + switch (ignore_white_space) + { + case IGNORE_ALL_SPACE: + while ((c = *p++) != '\n') + if (! isspace (c)) + h = HASH (h, tolower (c)); + break; + + case IGNORE_SPACE_CHANGE: + while ((c = *p++) != '\n') + { + if (isspace (c)) + { + do + if ((c = *p++) == '\n') + goto hashing_done; + while (isspace (c)); + + h = HASH (h, ' '); + } + + /* C is now the first non-space. */ + h = HASH (h, tolower (c)); + } + break; + + case IGNORE_TAB_EXPANSION: + { + size_t column = 0; + while ((c = *p++) != '\n') + { + size_t repetitions = 1; + + switch (c) + { + case '\b': + column -= 0 < column; + break; + + case '\t': + c = ' '; + repetitions = tabsize - column % tabsize; + column = (column + repetitions < column + ? 0 + : column + repetitions); + break; + + case '\r': + column = 0; + break; + + default: + c = tolower (c); + column++; + break; + } + + do + h = HASH (h, c); + while (--repetitions != 0); + } + } + break; + + default: + while ((c = *p++) != '\n') + h = HASH (h, tolower (c)); + break; + } + else + switch (ignore_white_space) + { + case IGNORE_ALL_SPACE: + while ((c = *p++) != '\n') + if (! isspace (c)) + h = HASH (h, c); + break; + + case IGNORE_SPACE_CHANGE: + while ((c = *p++) != '\n') + { + if (isspace (c)) + { + do + if ((c = *p++) == '\n') + goto hashing_done; + while (isspace (c)); + + h = HASH (h, ' '); + } + + /* C is now the first non-space. */ + h = HASH (h, c); + } + break; + + case IGNORE_TAB_EXPANSION: + { + size_t column = 0; + while ((c = *p++) != '\n') + { + size_t repetitions = 1; + + switch (c) + { + case '\b': + column -= 0 < column; + break; + + case '\t': + c = ' '; + repetitions = tabsize - column % tabsize; + column = (column + repetitions < column + ? 0 + : column + repetitions); + break; + + case '\r': + column = 0; + break; + + default: + column++; + break; + } + + do + h = HASH (h, c); + while (--repetitions != 0); + } + } + break; + + default: + while ((c = *p++) != '\n') + h = HASH (h, c); + break; + } + + hashing_done:; + + bucket = &buckets[h % nbuckets]; + length = p - ip - 1; + + if (p == bufend + && current->missing_newline + && ROBUST_OUTPUT_STYLE (output_style)) + { + /* This line is incomplete. If this is significant, + put the line into buckets[-1]. */ + if (ignore_white_space < IGNORE_SPACE_CHANGE) + bucket = &buckets[-1]; + + /* Omit the inserted newline when computing linbuf later. */ + p--; + bufend = suffix_begin = p; + } + + for (i = *bucket; ; i = eqs[i].next) + if (!i) + { + /* Create a new equivalence class in this bucket. */ + i = eqs_index++; + if (i == eqs_alloc) + { + if (PTRDIFF_MAX / (2 * sizeof *eqs) <= eqs_alloc) + xalloc_die (); + eqs_alloc *= 2; + eqs = xrealloc (eqs, eqs_alloc * sizeof *eqs); + } + eqs[i].next = *bucket; + eqs[i].hash = h; + eqs[i].line = ip; + eqs[i].length = length; + *bucket = i; + break; + } + else if (eqs[i].hash == h) + { + char const *eqline = eqs[i].line; + + /* Reuse existing class if lines_differ reports the lines + equal. */ + if (eqs[i].length == length) + { + /* Reuse existing equivalence class if the lines are identical. + This detects the common case of exact identity + faster than lines_differ would. */ + if (memcmp (eqline, ip, length) == 0) + break; + if (!same_length_diff_contents_compare_anyway) + continue; + } + else if (!diff_length_compare_anyway) + continue; + + if (! lines_differ (eqline, ip)) + break; + } + + /* Maybe increase the size of the line table. */ + if (line == alloc_lines) + { + /* Double (alloc_lines - linbuf_base) by adding to alloc_lines. */ + if (PTRDIFF_MAX / 3 <= alloc_lines + || PTRDIFF_MAX / sizeof *cureqs <= 2 * alloc_lines - linbuf_base + || PTRDIFF_MAX / sizeof *linbuf <= alloc_lines - linbuf_base) + xalloc_die (); + alloc_lines = 2 * alloc_lines - linbuf_base; + cureqs = xrealloc (cureqs, alloc_lines * sizeof *cureqs); + linbuf += linbuf_base; + linbuf = xrealloc (linbuf, + (alloc_lines - linbuf_base) * sizeof *linbuf); + linbuf -= linbuf_base; + } + linbuf[line] = ip; + cureqs[line] = i; + ++line; + } + + current->buffered_lines = line; + + for (i = 0; ; i++) + { + /* Record the line start for lines in the suffix that we care about. + Record one more line start than lines, + so that we can compute the length of any buffered line. */ + if (line == alloc_lines) + { + /* Double (alloc_lines - linbuf_base) by adding to alloc_lines. */ + if (PTRDIFF_MAX / 3 <= alloc_lines + || PTRDIFF_MAX / sizeof *cureqs <= 2 * alloc_lines - linbuf_base + || PTRDIFF_MAX / sizeof *linbuf <= alloc_lines - linbuf_base) + xalloc_die (); + alloc_lines = 2 * alloc_lines - linbuf_base; + linbuf += linbuf_base; + linbuf = xrealloc (linbuf, + (alloc_lines - linbuf_base) * sizeof *linbuf); + linbuf -= linbuf_base; + } + linbuf[line] = p; + + if (p == bufend) + break; + + if (context <= i && no_diff_means_no_output) + break; + + line++; + + while (*p++ != '\n') + continue; + } + + /* Done with cache in local variables. */ + current->linbuf = linbuf; + current->valid_lines = line; + current->alloc_lines = alloc_lines; + current->equivs = cureqs; + equivs = eqs; + equivs_alloc = eqs_alloc; + equivs_index = eqs_index; +} + +/* Prepare the text. Make sure the text end is initialized. + Make sure text ends in a newline, + but remember that we had to add one. + Strip trailing CRs, if that was requested. */ + +static void +prepare_text (struct file_data *current) +{ + size_t buffered = current->buffered; + char *p = FILE_BUFFER (current); + char *dst; + + if (buffered == 0 || p[buffered - 1] == '\n') + current->missing_newline = false; + else + { + p[buffered++] = '\n'; + current->missing_newline = true; + } + + if (!p) + return; + + /* Don't use uninitialized storage when planting or using sentinels. */ + memset (p + buffered, 0, sizeof (word)); + + if (strip_trailing_cr && (dst = memchr (p, '\r', buffered))) + { + char const *src = dst; + char const *srclim = p + buffered; + + do + dst += ! ((*dst = *src++) == '\r' && *src == '\n'); + while (src < srclim); + + buffered -= src - dst; + } + + current->buffered = buffered; +} + +/* We have found N lines in a buffer of size S; guess the + proportionate number of lines that will be found in a buffer of + size T. However, do not guess a number of lines so large that the + resulting line table might cause overflow in size calculations. */ +static lin +guess_lines (lin n, size_t s, size_t t) +{ + size_t guessed_bytes_per_line = n < 10 ? 32 : s / (n - 1); + lin guessed_lines = MAX (1, t / guessed_bytes_per_line); + return MIN (guessed_lines, PTRDIFF_MAX / (2 * sizeof (char *) + 1) - 5) + 5; +} + +/* Given a vector of two file_data objects, find the identical + prefixes and suffixes of each object. */ + +static void +find_identical_ends (struct file_data filevec[]) +{ + word *w0, *w1; + char *p0, *p1, *buffer0, *buffer1; + char const *end0, *beg0; + char const **linbuf0, **linbuf1; + lin i, lines; + size_t n0, n1; + lin alloc_lines0, alloc_lines1; + lin buffered_prefix, prefix_count, prefix_mask; + lin middle_guess, suffix_guess; + + slurp (&filevec[0]); + prepare_text (&filevec[0]); + if (filevec[0].desc != filevec[1].desc) + { + slurp (&filevec[1]); + prepare_text (&filevec[1]); + } + else + { + filevec[1].buffer = filevec[0].buffer; + filevec[1].bufsize = filevec[0].bufsize; + filevec[1].buffered = filevec[0].buffered; + filevec[1].missing_newline = filevec[0].missing_newline; + } + + /* Find identical prefix. */ + + w0 = filevec[0].buffer; + w1 = filevec[1].buffer; + p0 = buffer0 = (char *) w0; + p1 = buffer1 = (char *) w1; + n0 = filevec[0].buffered; + n1 = filevec[1].buffered; + + if (p0 == p1) + /* The buffers are the same; sentinels won't work. */ + p0 = p1 += n1; + else + { + /* Insert end sentinels, in this case characters that are guaranteed + to make the equality test false, and thus terminate the loop. */ + + if (n0 < n1) + p0[n0] = ~p1[n0]; + else + p1[n1] = ~p0[n1]; + + /* Loop until first mismatch, or to the sentinel characters. */ + + /* Compare a word at a time for speed. */ + while (*w0 == *w1) + w0++, w1++; + + /* Do the last few bytes of comparison a byte at a time. */ + p0 = (char *) w0; + p1 = (char *) w1; + while (*p0 == *p1) + p0++, p1++; + + /* Don't mistakenly count missing newline as part of prefix. */ + if (ROBUST_OUTPUT_STYLE (output_style) + && ((buffer0 + n0 - filevec[0].missing_newline < p0) + != + (buffer1 + n1 - filevec[1].missing_newline < p1))) + p0--, p1--; + } + + /* Now P0 and P1 point at the first nonmatching characters. */ + + /* Skip back to last line-beginning in the prefix, + and then discard up to HORIZON_LINES lines from the prefix. */ + i = horizon_lines; + while (p0 != buffer0 && (p0[-1] != '\n' || i--)) + p0--, p1--; + + /* Record the prefix. */ + filevec[0].prefix_end = p0; + filevec[1].prefix_end = p1; + + /* Find identical suffix. */ + + /* P0 and P1 point beyond the last chars not yet compared. */ + p0 = buffer0 + n0; + p1 = buffer1 + n1; + + if (! ROBUST_OUTPUT_STYLE (output_style) + || filevec[0].missing_newline == filevec[1].missing_newline) + { + end0 = p0; /* Addr of last char in file 0. */ + + /* Get value of P0 at which we should stop scanning backward: + this is when either P0 or P1 points just past the last char + of the identical prefix. */ + beg0 = filevec[0].prefix_end + (n0 < n1 ? 0 : n0 - n1); + + /* Scan back until chars don't match or we reach that point. */ + for (; p0 != beg0; p0--, p1--) + if (*p0 != *p1) + { + /* Point at the first char of the matching suffix. */ + beg0 = p0; + break; + } + + /* Are we at a line-beginning in both files? If not, add the rest of + this line to the main body. Discard up to HORIZON_LINES lines from + the identical suffix. Also, discard one extra line, + because shift_boundaries may need it. */ + i = horizon_lines + !((buffer0 == p0 || p0[-1] == '\n') + && + (buffer1 == p1 || p1[-1] == '\n')); + while (i-- && p0 != end0) + while (*p0++ != '\n') + continue; + + p1 += p0 - beg0; + } + + /* Record the suffix. */ + filevec[0].suffix_begin = p0; + filevec[1].suffix_begin = p1; + + /* Calculate number of lines of prefix to save. + + prefix_count == 0 means save the whole prefix; + we need this for options like -D that output the whole file, + or for enormous contexts (to avoid worrying about arithmetic overflow). + We also need it for options like -F that output some preceding line; + at least we will need to find the last few lines, + but since we don't know how many, it's easiest to find them all. + + Otherwise, prefix_count != 0. Save just prefix_count lines at start + of the line buffer; they'll be moved to the proper location later. + Handle 1 more line than the context says (because we count 1 too many), + rounded up to the next power of 2 to speed index computation. */ + + if (no_diff_means_no_output && ! function_regexp.fastmap + && context < LIN_MAX / 4 && context < n0) + { + middle_guess = guess_lines (0, 0, p0 - filevec[0].prefix_end); + suffix_guess = guess_lines (0, 0, buffer0 + n0 - p0); + for (prefix_count = 1; prefix_count <= context; prefix_count *= 2) + continue; + alloc_lines0 = (prefix_count + middle_guess + + MIN (context, suffix_guess)); + } + else + { + prefix_count = 0; + alloc_lines0 = guess_lines (0, 0, n0); + } + + prefix_mask = prefix_count - 1; + lines = 0; + linbuf0 = xmalloc (alloc_lines0 * sizeof *linbuf0); + p0 = buffer0; + + /* If the prefix is needed, find the prefix lines. */ + if (! (no_diff_means_no_output + && filevec[0].prefix_end == p0 + && filevec[1].prefix_end == p1)) + { + end0 = filevec[0].prefix_end; + while (p0 != end0) + { + lin l = lines++ & prefix_mask; + if (l == alloc_lines0) + { + if (PTRDIFF_MAX / (2 * sizeof *linbuf0) <= alloc_lines0) + xalloc_die (); + alloc_lines0 *= 2; + linbuf0 = xrealloc (linbuf0, alloc_lines0 * sizeof *linbuf0); + } + linbuf0[l] = p0; + while (*p0++ != '\n') + continue; + } + } + buffered_prefix = prefix_count && context < lines ? context : lines; + + /* Allocate line buffer 1. */ + + middle_guess = guess_lines (lines, p0 - buffer0, p1 - filevec[1].prefix_end); + suffix_guess = guess_lines (lines, p0 - buffer0, buffer1 + n1 - p1); + alloc_lines1 = buffered_prefix + middle_guess + MIN (context, suffix_guess); + if (alloc_lines1 < buffered_prefix + || PTRDIFF_MAX / sizeof *linbuf1 <= alloc_lines1) + xalloc_die (); + linbuf1 = xmalloc (alloc_lines1 * sizeof *linbuf1); + + if (buffered_prefix != lines) + { + /* Rotate prefix lines to proper location. */ + for (i = 0; i < buffered_prefix; i++) + linbuf1[i] = linbuf0[(lines - context + i) & prefix_mask]; + for (i = 0; i < buffered_prefix; i++) + linbuf0[i] = linbuf1[i]; + } + + /* Initialize line buffer 1 from line buffer 0. */ + for (i = 0; i < buffered_prefix; i++) + linbuf1[i] = linbuf0[i] - buffer0 + buffer1; + + /* Record the line buffer, adjusted so that + linbuf[0] points at the first differing line. */ + filevec[0].linbuf = linbuf0 + buffered_prefix; + filevec[1].linbuf = linbuf1 + buffered_prefix; + filevec[0].linbuf_base = filevec[1].linbuf_base = - buffered_prefix; + filevec[0].alloc_lines = alloc_lines0 - buffered_prefix; + filevec[1].alloc_lines = alloc_lines1 - buffered_prefix; + filevec[0].prefix_lines = filevec[1].prefix_lines = lines; +} + +/* If 1 < k, then (2**k - prime_offset[k]) is the largest prime less + than 2**k. This table is derived from Chris K. Caldwell's list + . */ + +static unsigned char const prime_offset[] = +{ + 0, 0, 1, 1, 3, 1, 3, 1, 5, 3, 3, 9, 3, 1, 3, 19, 15, 1, 5, 1, 3, 9, 3, + 15, 3, 39, 5, 39, 57, 3, 35, 1, 5, 9, 41, 31, 5, 25, 45, 7, 87, 21, + 11, 57, 17, 55, 21, 115, 59, 81, 27, 129, 47, 111, 33, 55, 5, 13, 27, + 55, 93, 1, 57, 25 +}; + +/* Verify that this host's size_t is not too wide for the above table. */ + +verify (enough_prime_offsets, + sizeof (size_t) * CHAR_BIT <= sizeof prime_offset); + +/* Given a vector of two file_data objects, read the file associated + with each one, and build the table of equivalence classes. + Return nonzero if either file appears to be a binary file. + If PRETEND_BINARY is nonzero, pretend they are binary regardless. */ + +bool +read_files (struct file_data filevec[], bool pretend_binary) +{ + int i; + bool skip_test = text | pretend_binary; + bool appears_binary = pretend_binary | sip (&filevec[0], skip_test); + + if (filevec[0].desc != filevec[1].desc) + appears_binary |= sip (&filevec[1], skip_test | appears_binary); + else + { + filevec[1].buffer = filevec[0].buffer; + filevec[1].bufsize = filevec[0].bufsize; + filevec[1].buffered = filevec[0].buffered; + } + if (appears_binary) + { + set_binary_mode (filevec[0].desc, true); + set_binary_mode (filevec[1].desc, true); + return true; + } + + find_identical_ends (filevec); + + equivs_alloc = filevec[0].alloc_lines + filevec[1].alloc_lines + 1; + if (PTRDIFF_MAX / sizeof *equivs <= equivs_alloc) + xalloc_die (); + equivs = xmalloc (equivs_alloc * sizeof *equivs); + /* Equivalence class 0 is permanently safe for lines that were not + hashed. Real equivalence classes start at 1. */ + equivs_index = 1; + + /* Allocate (one plus) a prime number of hash buckets. Use a prime + number between 1/3 and 2/3 of the value of equiv_allocs, + approximately. */ + for (i = 9; (size_t) 1 << i < equivs_alloc / 3; i++) + continue; + nbuckets = ((size_t) 1 << i) - prime_offset[i]; + if (PTRDIFF_MAX / sizeof *buckets <= nbuckets) + xalloc_die (); + buckets = zalloc ((nbuckets + 1) * sizeof *buckets); + buckets++; + + for (i = 0; i < 2; i++) + find_and_hash_each_line (&filevec[i]); + + filevec[0].equiv_max = filevec[1].equiv_max = equivs_index; + + free (equivs); + free (buckets - 1); + + return false; +} diff --git a/contrib/diffutils-2.8/src/normal.c b/contrib/diffutils-2.8/src/normal.c new file mode 100644 index 0000000000..4a01596544 --- /dev/null +++ b/contrib/diffutils-2.8/src/normal.c @@ -0,0 +1,71 @@ +/* Normal-format output routines for GNU DIFF. + + Copyright (C) 1988, 1989, 1993, 1995, 1998, 2001 Free Software + Foundation, Inc. + + This file is part of GNU DIFF. + + GNU DIFF is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GNU DIFF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "diff.h" + +static void print_normal_hunk (struct change *); + +/* Print the edit-script SCRIPT as a normal diff. + INF points to an array of descriptions of the two files. */ + +void +print_normal_script (struct change *script) +{ + print_script (script, find_change, print_normal_hunk); +} + +/* Print a hunk of a normal diff. + This is a contiguous portion of a complete edit script, + describing changes in consecutive lines. */ + +static void +print_normal_hunk (struct change *hunk) +{ + lin first0, last0, first1, last1; + register lin i; + + /* Determine range of line numbers involved in each file. */ + enum changes changes = analyze_hunk (hunk, &first0, &last0, &first1, &last1); + if (!changes) + return; + + begin_output (); + + /* Print out the line number header for this hunk */ + print_number_range (',', &files[0], first0, last0); + fprintf (outfile, "%c", change_letter[changes]); + print_number_range (',', &files[1], first1, last1); + fprintf (outfile, "\n"); + + /* Print the lines that the first file has. */ + if (changes & OLD) + for (i = first0; i <= last0; i++) + print_1_line ("<", &files[0].linbuf[i]); + + if (changes == CHANGED) + fprintf (outfile, "---\n"); + + /* Print the lines that the second file has. */ + if (changes & NEW) + for (i = first1; i <= last1; i++) + print_1_line (">", &files[1].linbuf[i]); +} diff --git a/contrib/diffutils-2.8/src/sdiff.c b/contrib/diffutils-2.8/src/sdiff.c new file mode 100644 index 0000000000..2b0a2aee94 --- /dev/null +++ b/contrib/diffutils-2.8/src/sdiff.c @@ -0,0 +1,1225 @@ +/* sdiff - side-by-side merge of file differences + + Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 2001, 2002, 2004 + Free Software Foundation, Inc. + + This file is part of GNU DIFF. + + GNU DIFF is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GNU DIFF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "system.h" +#include "paths.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Size of chunks read from files which must be parsed into lines. */ +#define SDIFF_BUFSIZE ((size_t) 65536) + +char *program_name; + +static char const *editor_program = DEFAULT_EDITOR_PROGRAM; +static char const **diffargv; + +static char * volatile tmpname; +static FILE *tmp; + +#if HAVE_WORKING_FORK || HAVE_WORKING_VFORK +static pid_t volatile diffpid; +#endif + +struct line_filter; + +static void catchsig (int); +static bool edit (struct line_filter *, char const *, lin, lin, struct line_filter *, char const *, lin, lin, FILE *); +static bool interact (struct line_filter *, struct line_filter *, char const *, struct line_filter *, char const *, FILE *); +static void checksigs (void); +static void diffarg (char const *); +static void fatal (char const *) __attribute__((noreturn)); +static void perror_fatal (char const *) __attribute__((noreturn)); +static void trapsigs (void); +static void untrapsig (int); + +#define NUM_SIGS (sizeof sigs / sizeof *sigs) +static int const sigs[] = { +#ifdef SIGHUP + SIGHUP, +#endif +#ifdef SIGQUIT + SIGQUIT, +#endif +#ifdef SIGTERM + SIGTERM, +#endif +#ifdef SIGXCPU + SIGXCPU, +#endif +#ifdef SIGXFSZ + SIGXFSZ, +#endif + SIGINT, + SIGPIPE +}; +#define handler_index_of_SIGINT (NUM_SIGS - 2) +#define handler_index_of_SIGPIPE (NUM_SIGS - 1) + +#if HAVE_SIGACTION + /* Prefer `sigaction' if available, since `signal' can lose signals. */ + static struct sigaction initial_action[NUM_SIGS]; +# define initial_handler(i) (initial_action[i].sa_handler) + static void signal_handler (int, void (*) (int)); +#else + static void (*initial_action[NUM_SIGS]) (); +# define initial_handler(i) (initial_action[i]) +# define signal_handler(sig, handler) signal (sig, handler) +#endif + +#if ! HAVE_SIGPROCMASK +# define sigset_t int +# define sigemptyset(s) (*(s) = 0) +# ifndef sigmask +# define sigmask(sig) (1 << ((sig) - 1)) +# endif +# define sigaddset(s, sig) (*(s) |= sigmask (sig)) +# ifndef SIG_BLOCK +# define SIG_BLOCK 0 +# endif +# ifndef SIG_SETMASK +# define SIG_SETMASK (! SIG_BLOCK) +# endif +# define sigprocmask(how, n, o) \ + ((how) == SIG_BLOCK ? *(o) = sigblock (*(n)) : sigsetmask (*(n))) +#endif + +static bool diraccess (char const *); +static int temporary_file (void); + +/* Options: */ + +/* Name of output file if -o specified. */ +static char const *output; + +/* Do not print common lines. */ +static bool suppress_common_lines; + +/* Value for the long option that does not have single-letter equivalents. */ +enum +{ + DIFF_PROGRAM_OPTION = CHAR_MAX + 1, + HELP_OPTION, + STRIP_TRAILING_CR_OPTION, + TABSIZE_OPTION +}; + +static struct option const longopts[] = +{ + {"diff-program", 1, 0, DIFF_PROGRAM_OPTION}, + {"expand-tabs", 0, 0, 't'}, + {"help", 0, 0, HELP_OPTION}, + {"ignore-all-space", 0, 0, 'W'}, /* swap W and w for historical reasons */ + {"ignore-blank-lines", 0, 0, 'B'}, + {"ignore-case", 0, 0, 'i'}, + {"ignore-matching-lines", 1, 0, 'I'}, + {"ignore-space-change", 0, 0, 'b'}, + {"ignore-tab-expansion", 0, 0, 'E'}, + {"left-column", 0, 0, 'l'}, + {"minimal", 0, 0, 'd'}, + {"output", 1, 0, 'o'}, + {"speed-large-files", 0, 0, 'H'}, + {"strip-trailing-cr", 0, 0, STRIP_TRAILING_CR_OPTION}, + {"suppress-common-lines", 0, 0, 's'}, + {"tabsize", 1, 0, TABSIZE_OPTION}, + {"text", 0, 0, 'a'}, + {"version", 0, 0, 'v'}, + {"width", 1, 0, 'w'}, + {0, 0, 0, 0} +}; + +static void try_help (char const *, char const *) __attribute__((noreturn)); +static void +try_help (char const *reason_msgid, char const *operand) +{ + if (reason_msgid) + error (0, 0, _(reason_msgid), operand); + error (EXIT_TROUBLE, 0, _("Try `%s --help' for more information."), + program_name); + abort (); +} + +static void +check_stdout (void) +{ + if (ferror (stdout)) + fatal ("write failed"); + else if (fclose (stdout) != 0) + perror_fatal (_("standard output")); +} + +static char const * const option_help_msgid[] = { + N_("-o FILE --output=FILE Operate interactively, sending output to FILE."), + "", + N_("-i --ignore-case Consider upper- and lower-case to be the same."), + N_("-E --ignore-tab-expansion Ignore changes due to tab expansion."), + N_("-b --ignore-space-change Ignore changes in the amount of white space."), + N_("-W --ignore-all-space Ignore all white space."), + N_("-B --ignore-blank-lines Ignore changes whose lines are all blank."), + N_("-I RE --ignore-matching-lines=RE Ignore changes whose lines all match RE."), + N_("--strip-trailing-cr Strip trailing carriage return on input."), + N_("-a --text Treat all files as text."), + "", + N_("-w NUM --width=NUM Output at most NUM (default 130) print columns."), + N_("-l --left-column Output only the left column of common lines."), + N_("-s --suppress-common-lines Do not output common lines."), + "", + N_("-t --expand-tabs Expand tabs to spaces in output."), + N_("--tabsize=NUM Tab stops are every NUM (default 8) print columns."), + "", + N_("-d --minimal Try hard to find a smaller set of changes."), + N_("-H --speed-large-files Assume large files and many scattered small changes."), + N_("--diff-program=PROGRAM Use PROGRAM to compare files."), + "", + N_("-v --version Output version info."), + N_("--help Output this help."), + 0 +}; + +static void +usage (void) +{ + char const * const *p; + + printf (_("Usage: %s [OPTION]... FILE1 FILE2\n"), program_name); + printf ("%s\n\n", _("Side-by-side merge of file differences.")); + for (p = option_help_msgid; *p; p++) + if (**p) + printf (" %s\n", _(*p)); + else + putchar ('\n'); + printf ("\n%s\n%s\n\n%s\n", + _("If a FILE is `-', read standard input."), + _("Exit status is 0 if inputs are the same, 1 if different, 2 if trouble."), + _("Report bugs to .")); +} + +/* Clean up after a signal or other failure. This function is + async-signal-safe. */ +static void +cleanup (int signo __attribute__((unused))) +{ +#if HAVE_WORKING_FORK || HAVE_WORKING_VFORK + if (0 < diffpid) + kill (diffpid, SIGPIPE); +#endif + if (tmpname) + unlink (tmpname); +} + +static void exiterr (void) __attribute__((noreturn)); +static void +exiterr (void) +{ + cleanup (0); + untrapsig (0); + checksigs (); + exit (EXIT_TROUBLE); +} + +static void +fatal (char const *msgid) +{ + error (0, 0, "%s", _(msgid)); + exiterr (); +} + +static void +perror_fatal (char const *msg) +{ + int e = errno; + checksigs (); + error (0, e, "%s", msg); + exiterr (); +} + +static void +check_child_status (int werrno, int wstatus, int max_ok_status, + char const *subsidiary_program) +{ + int status = (! werrno && WIFEXITED (wstatus) + ? WEXITSTATUS (wstatus) + : INT_MAX); + + if (max_ok_status < status) + { + error (0, werrno, + _(status == 126 + ? "subsidiary program `%s' could not be invoked" + : status == 127 + ? "subsidiary program `%s' not found" + : status == INT_MAX + ? "subsidiary program `%s' failed" + : "subsidiary program `%s' failed (exit status %d)"), + subsidiary_program, status); + exiterr (); + } +} + +static FILE * +ck_fopen (char const *fname, char const *type) +{ + FILE *r = fopen (fname, type); + if (! r) + perror_fatal (fname); + return r; +} + +static void +ck_fclose (FILE *f) +{ + if (fclose (f)) + perror_fatal ("fclose"); +} + +static size_t +ck_fread (char *buf, size_t size, FILE *f) +{ + size_t r = fread (buf, sizeof (char), size, f); + if (r == 0 && ferror (f)) + perror_fatal (_("read failed")); + return r; +} + +static void +ck_fwrite (char const *buf, size_t size, FILE *f) +{ + if (fwrite (buf, sizeof (char), size, f) != size) + perror_fatal (_("write failed")); +} + +static void +ck_fflush (FILE *f) +{ + if (fflush (f) != 0) + perror_fatal (_("write failed")); +} + +static char const * +expand_name (char *name, bool is_dir, char const *other_name) +{ + if (strcmp (name, "-") == 0) + fatal ("cannot interactively merge standard input"); + if (! is_dir) + return name; + else + { + /* Yield NAME/BASE, where BASE is OTHER_NAME's basename. */ + char const *base = base_name (other_name); + size_t namelen = strlen (name), baselen = strlen (base); + bool insert_slash = *base_name (name) && name[namelen - 1] != '/'; + char *r = xmalloc (namelen + insert_slash + baselen + 1); + memcpy (r, name, namelen); + r[namelen] = '/'; + memcpy (r + namelen + insert_slash, base, baselen + 1); + return r; + } +} + +struct line_filter { + FILE *infile; + char *bufpos; + char *buffer; + char *buflim; +}; + +static void +lf_init (struct line_filter *lf, FILE *infile) +{ + lf->infile = infile; + lf->bufpos = lf->buffer = lf->buflim = xmalloc (SDIFF_BUFSIZE + 1); + lf->buflim[0] = '\n'; +} + +/* Fill an exhausted line_filter buffer from its INFILE */ +static size_t +lf_refill (struct line_filter *lf) +{ + size_t s = ck_fread (lf->buffer, SDIFF_BUFSIZE, lf->infile); + lf->bufpos = lf->buffer; + lf->buflim = lf->buffer + s; + lf->buflim[0] = '\n'; + checksigs (); + return s; +} + +/* Advance LINES on LF's infile, copying lines to OUTFILE */ +static void +lf_copy (struct line_filter *lf, lin lines, FILE *outfile) +{ + char *start = lf->bufpos; + + while (lines) + { + lf->bufpos = (char *) memchr (lf->bufpos, '\n', lf->buflim - lf->bufpos); + if (! lf->bufpos) + { + ck_fwrite (start, lf->buflim - start, outfile); + if (! lf_refill (lf)) + return; + start = lf->bufpos; + } + else + { + --lines; + ++lf->bufpos; + } + } + + ck_fwrite (start, lf->bufpos - start, outfile); +} + +/* Advance LINES on LF's infile without doing output */ +static void +lf_skip (struct line_filter *lf, lin lines) +{ + while (lines) + { + lf->bufpos = (char *) memchr (lf->bufpos, '\n', lf->buflim - lf->bufpos); + if (! lf->bufpos) + { + if (! lf_refill (lf)) + break; + } + else + { + --lines; + ++lf->bufpos; + } + } +} + +/* Snarf a line into a buffer. Return EOF if EOF, 0 if error, 1 if OK. */ +static int +lf_snarf (struct line_filter *lf, char *buffer, size_t bufsize) +{ + for (;;) + { + char *start = lf->bufpos; + char *next = (char *) memchr (start, '\n', lf->buflim + 1 - start); + size_t s = next - start; + if (bufsize <= s) + return 0; + memcpy (buffer, start, s); + if (next < lf->buflim) + { + buffer[s] = 0; + lf->bufpos = next + 1; + return 1; + } + if (! lf_refill (lf)) + return s ? 0 : EOF; + buffer += s; + bufsize -= s; + } +} + +int +main (int argc, char *argv[]) +{ + int opt; + char const *prog; + + exit_failure = EXIT_TROUBLE; + initialize_main (&argc, &argv); + program_name = argv[0]; + setlocale (LC_ALL, ""); + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + c_stack_action (cleanup); + + prog = getenv ("EDITOR"); + if (prog) + editor_program = prog; + + diffarg (DEFAULT_DIFF_PROGRAM); + + /* parse command line args */ + while ((opt = getopt_long (argc, argv, "abBdEHiI:lo:stvw:W", longopts, 0)) + != -1) + { + switch (opt) + { + case 'a': + diffarg ("-a"); + break; + + case 'b': + diffarg ("-b"); + break; + + case 'B': + diffarg ("-B"); + break; + + case 'd': + diffarg ("-d"); + break; + + case 'E': + diffarg ("-E"); + break; + + case 'H': + diffarg ("-H"); + break; + + case 'i': + diffarg ("-i"); + break; + + case 'I': + diffarg ("-I"); + diffarg (optarg); + break; + + case 'l': + diffarg ("--left-column"); + break; + + case 'o': + output = optarg; + break; + + case 's': + suppress_common_lines = true; + break; + + case 't': + diffarg ("-t"); + break; + + case 'v': + version_etc (stdout, "sdiff", PACKAGE_NAME, PACKAGE_VERSION, + "Thomas Lord", (char *) 0); + check_stdout (); + return EXIT_SUCCESS; + + case 'w': + diffarg ("-W"); + diffarg (optarg); + break; + + case 'W': + diffarg ("-w"); + break; + + case DIFF_PROGRAM_OPTION: + diffargv[0] = optarg; + break; + + case HELP_OPTION: + usage (); + check_stdout (); + return EXIT_SUCCESS; + + case STRIP_TRAILING_CR_OPTION: + diffarg ("--strip-trailing-cr"); + break; + + case TABSIZE_OPTION: + diffarg ("--tabsize"); + diffarg (optarg); + break; + + default: + try_help (0, 0); + } + } + + if (argc - optind != 2) + { + if (argc - optind < 2) + try_help ("missing operand after `%s'", argv[argc - 1]); + else + try_help ("extra operand `%s'", argv[optind + 2]); + } + + if (! output) + { + /* easy case: diff does everything for us */ + if (suppress_common_lines) + diffarg ("--suppress-common-lines"); + diffarg ("-y"); + diffarg ("--"); + diffarg (argv[optind]); + diffarg (argv[optind + 1]); + diffarg (0); + execvp (diffargv[0], (char **) diffargv); + perror_fatal (diffargv[0]); + } + else + { + char const *lname, *rname; + FILE *left, *right, *out, *diffout; + bool interact_ok; + struct line_filter lfilt; + struct line_filter rfilt; + struct line_filter diff_filt; + bool leftdir = diraccess (argv[optind]); + bool rightdir = diraccess (argv[optind + 1]); + + if (leftdir & rightdir) + fatal ("both files to be compared are directories"); + + lname = expand_name (argv[optind], leftdir, argv[optind + 1]); + left = ck_fopen (lname, "r"); + rname = expand_name (argv[optind + 1], rightdir, argv[optind]); + right = ck_fopen (rname, "r"); + out = ck_fopen (output, "w"); + + diffarg ("--sdiff-merge-assist"); + diffarg ("--"); + diffarg (argv[optind]); + diffarg (argv[optind + 1]); + diffarg (0); + + trapsigs (); + +#if ! (HAVE_WORKING_FORK || HAVE_WORKING_VFORK) + { + size_t cmdsize = 1; + char *p, *command; + int i; + + for (i = 0; diffargv[i]; i++) + cmdsize += quote_system_arg (0, diffargv[i]) + 1; + command = p = xmalloc (cmdsize); + for (i = 0; diffargv[i]; i++) + { + p += quote_system_arg (p, diffargv[i]); + *p++ = ' '; + } + p[-1] = 0; + errno = 0; + diffout = popen (command, "r"); + if (! diffout) + perror_fatal (command); + free (command); + } +#else + { + int diff_fds[2]; +# if HAVE_WORKING_VFORK + sigset_t procmask; + sigset_t blocked; +# endif + + if (pipe (diff_fds) != 0) + perror_fatal ("pipe"); + +# if HAVE_WORKING_VFORK + /* Block SIGINT and SIGPIPE. */ + sigemptyset (&blocked); + sigaddset (&blocked, SIGINT); + sigaddset (&blocked, SIGPIPE); + sigprocmask (SIG_BLOCK, &blocked, &procmask); +# endif + diffpid = vfork (); + if (diffpid < 0) + perror_fatal ("fork"); + if (! diffpid) + { + /* Alter the child's SIGINT and SIGPIPE handlers; + this may munge the parent. + The child ignores SIGINT in case the user interrupts the editor. + The child does not ignore SIGPIPE, even if the parent does. */ + if (initial_handler (handler_index_of_SIGINT) != SIG_IGN) + signal_handler (SIGINT, SIG_IGN); + signal_handler (SIGPIPE, SIG_DFL); +# if HAVE_WORKING_VFORK + /* Stop blocking SIGINT and SIGPIPE in the child. */ + sigprocmask (SIG_SETMASK, &procmask, 0); +# endif + close (diff_fds[0]); + if (diff_fds[1] != STDOUT_FILENO) + { + dup2 (diff_fds[1], STDOUT_FILENO); + close (diff_fds[1]); + } + + execvp (diffargv[0], (char **) diffargv); + _exit (errno == ENOENT ? 127 : 126); + } + +# if HAVE_WORKING_VFORK + /* Restore the parent's SIGINT and SIGPIPE behavior. */ + if (initial_handler (handler_index_of_SIGINT) != SIG_IGN) + signal_handler (SIGINT, catchsig); + if (initial_handler (handler_index_of_SIGPIPE) != SIG_IGN) + signal_handler (SIGPIPE, catchsig); + else + signal_handler (SIGPIPE, SIG_IGN); + + /* Stop blocking SIGINT and SIGPIPE in the parent. */ + sigprocmask (SIG_SETMASK, &procmask, 0); +# endif + + close (diff_fds[1]); + diffout = fdopen (diff_fds[0], "r"); + if (! diffout) + perror_fatal ("fdopen"); + } +#endif + + lf_init (&diff_filt, diffout); + lf_init (&lfilt, left); + lf_init (&rfilt, right); + + interact_ok = interact (&diff_filt, &lfilt, lname, &rfilt, rname, out); + + ck_fclose (left); + ck_fclose (right); + ck_fclose (out); + + { + int wstatus; + int werrno = 0; + +#if ! (HAVE_WORKING_FORK || HAVE_WORKING_VFORK) + wstatus = pclose (diffout); + if (wstatus == -1) + werrno = errno; +#else + ck_fclose (diffout); + while (waitpid (diffpid, &wstatus, 0) < 0) + if (errno == EINTR) + checksigs (); + else + perror_fatal ("waitpid"); + diffpid = 0; +#endif + + if (tmpname) + { + unlink (tmpname); + tmpname = 0; + } + + if (! interact_ok) + exiterr (); + + check_child_status (werrno, wstatus, EXIT_FAILURE, diffargv[0]); + untrapsig (0); + checksigs (); + exit (WEXITSTATUS (wstatus)); + } + } + return EXIT_SUCCESS; /* Fool `-Wall'. */ +} + +static void +diffarg (char const *a) +{ + static size_t diffargs, diffarglim; + + if (diffargs == diffarglim) + { + if (! diffarglim) + diffarglim = 16; + else if (PTRDIFF_MAX / (2 * sizeof *diffargv) <= diffarglim) + xalloc_die (); + else + diffarglim *= 2; + diffargv = xrealloc (diffargv, diffarglim * sizeof *diffargv); + } + diffargv[diffargs++] = a; +} + +/* Signal handling */ + +static bool volatile ignore_SIGINT; +static int volatile signal_received; +static bool sigs_trapped; + +static void +catchsig (int s) +{ +#if ! HAVE_SIGACTION + signal (s, SIG_IGN); +#endif + if (! (s == SIGINT && ignore_SIGINT)) + signal_received = s; +} + +#if HAVE_SIGACTION +static struct sigaction catchaction; + +static void +signal_handler (int sig, void (*handler) (int)) +{ + catchaction.sa_handler = handler; + sigaction (sig, &catchaction, 0); +} +#endif + +static void +trapsigs (void) +{ + int i; + +#if HAVE_SIGACTION + catchaction.sa_flags = SA_RESTART; + sigemptyset (&catchaction.sa_mask); + for (i = 0; i < NUM_SIGS; i++) + sigaddset (&catchaction.sa_mask, sigs[i]); +#endif + + for (i = 0; i < NUM_SIGS; i++) + { +#if HAVE_SIGACTION + sigaction (sigs[i], 0, &initial_action[i]); +#else + initial_action[i] = signal (sigs[i], SIG_IGN); +#endif + if (initial_handler (i) != SIG_IGN) + signal_handler (sigs[i], catchsig); + } + +#ifdef SIGCHLD + /* System V fork+wait does not work if SIGCHLD is ignored. */ + signal (SIGCHLD, SIG_DFL); +#endif + + sigs_trapped = true; +} + +/* Untrap signal S, or all trapped signals if S is zero. */ +static void +untrapsig (int s) +{ + int i; + + if (sigs_trapped) + for (i = 0; i < NUM_SIGS; i++) + if ((! s || sigs[i] == s) && initial_handler (i) != SIG_IGN) + { +#if HAVE_SIGACTION + sigaction (sigs[i], &initial_action[i], 0); +#else + signal (sigs[i], initial_action[i]); +#endif + } +} + +/* Exit if a signal has been received. */ +static void +checksigs (void) +{ + int s = signal_received; + if (s) + { + cleanup (0); + + /* Yield an exit status indicating that a signal was received. */ + untrapsig (s); + kill (getpid (), s); + + /* That didn't work, so exit with error status. */ + exit (EXIT_TROUBLE); + } +} + +static void +give_help (void) +{ + fprintf (stderr, "%s", _("\ +ed:\tEdit then use both versions, each decorated with a header.\n\ +eb:\tEdit then use both versions.\n\ +el:\tEdit then use the left version.\n\ +er:\tEdit then use the right version.\n\ +e:\tEdit a new version.\n\ +l:\tUse the left version.\n\ +r:\tUse the right version.\n\ +s:\tSilently include common lines.\n\ +v:\tVerbosely include common lines.\n\ +q:\tQuit.\n\ +")); +} + +static int +skip_white (void) +{ + int c; + for (;;) + { + c = getchar (); + if (! isspace (c) || c == '\n') + break; + checksigs (); + } + if (ferror (stdin)) + perror_fatal (_("read failed")); + return c; +} + +static void +flush_line (void) +{ + int c; + while ((c = getchar ()) != '\n' && c != EOF) + continue; + if (ferror (stdin)) + perror_fatal (_("read failed")); +} + + +/* interpret an edit command */ +static bool +edit (struct line_filter *left, char const *lname, lin lline, lin llen, + struct line_filter *right, char const *rname, lin rline, lin rlen, + FILE *outfile) +{ + for (;;) + { + int cmd0, cmd1; + bool gotcmd = false; + + cmd1 = 0; /* Pacify `gcc -W'. */ + + while (! gotcmd) + { + if (putchar ('%') != '%') + perror_fatal (_("write failed")); + ck_fflush (stdout); + + cmd0 = skip_white (); + switch (cmd0) + { + case 'l': case 'r': case 's': case 'v': case 'q': + if (skip_white () != '\n') + { + give_help (); + flush_line (); + continue; + } + gotcmd = true; + break; + + case 'e': + cmd1 = skip_white (); + switch (cmd1) + { + case 'b': case 'd': case 'l': case 'r': + if (skip_white () != '\n') + { + give_help (); + flush_line (); + continue; + } + gotcmd = true; + break; + case '\n': + gotcmd = true; + break; + default: + give_help (); + flush_line (); + continue; + } + break; + + case EOF: + if (feof (stdin)) + { + gotcmd = true; + cmd0 = 'q'; + break; + } + /* Fall through. */ + default: + flush_line (); + /* Fall through. */ + case '\n': + give_help (); + continue; + } + } + + switch (cmd0) + { + case 'l': + lf_copy (left, llen, outfile); + lf_skip (right, rlen); + return true; + case 'r': + lf_copy (right, rlen, outfile); + lf_skip (left, llen); + return true; + case 's': + suppress_common_lines = true; + break; + case 'v': + suppress_common_lines = false; + break; + case 'q': + return false; + case 'e': + { + int fd; + + if (tmpname) + tmp = fopen (tmpname, "w"); + else + { + if ((fd = temporary_file ()) < 0) + perror_fatal ("mkstemp"); + tmp = fdopen (fd, "w"); + } + + if (! tmp) + perror_fatal (tmpname); + + switch (cmd1) + { + case 'd': + if (llen) + { + if (llen == 1) + fprintf (tmp, "--- %s %ld\n", lname, (long int) lline); + else + fprintf (tmp, "--- %s %ld,%ld\n", lname, + (long int) lline, + (long int) (lline + llen - 1)); + } + /* Fall through. */ + case 'b': case 'l': + lf_copy (left, llen, tmp); + break; + + default: + lf_skip (left, llen); + break; + } + + switch (cmd1) + { + case 'd': + if (rlen) + { + if (rlen == 1) + fprintf (tmp, "+++ %s %ld\n", rname, (long int) rline); + else + fprintf (tmp, "+++ %s %ld,%ld\n", rname, + (long int) rline, + (long int) (rline + rlen - 1)); + } + /* Fall through. */ + case 'b': case 'r': + lf_copy (right, rlen, tmp); + break; + + default: + lf_skip (right, rlen); + break; + } + + ck_fclose (tmp); + + { + int wstatus; + int werrno = 0; + ignore_SIGINT = true; + checksigs (); + + { +#if ! (HAVE_WORKING_FORK || HAVE_WORKING_VFORK) + char *command = + xmalloc (quote_system_arg (0, editor_program) + + 1 + strlen (tmpname) + 1); + sprintf (command + quote_system_arg (command, editor_program), + " %s", tmpname); + wstatus = system (command); + if (wstatus == -1) + werrno = errno; + free (command); +#else + pid_t pid; + + pid = vfork (); + if (pid == 0) + { + char const *argv[3]; + int i = 0; + + argv[i++] = editor_program; + argv[i++] = tmpname; + argv[i] = 0; + + execvp (editor_program, (char **) argv); + _exit (errno == ENOENT ? 127 : 126); + } + + if (pid < 0) + perror_fatal ("fork"); + + while (waitpid (pid, &wstatus, 0) < 0) + if (errno == EINTR) + checksigs (); + else + perror_fatal ("waitpid"); +#endif + } + + ignore_SIGINT = false; + check_child_status (werrno, wstatus, EXIT_SUCCESS, + editor_program); + } + + { + char buf[SDIFF_BUFSIZE]; + size_t size; + tmp = ck_fopen (tmpname, "r"); + while ((size = ck_fread (buf, SDIFF_BUFSIZE, tmp)) != 0) + { + checksigs (); + ck_fwrite (buf, size, outfile); + } + ck_fclose (tmp); + } + return true; + } + default: + give_help (); + break; + } + } +} + +/* Alternately reveal bursts of diff output and handle user commands. */ +static bool +interact (struct line_filter *diff, + struct line_filter *left, char const *lname, + struct line_filter *right, char const *rname, + FILE *outfile) +{ + lin lline = 1, rline = 1; + + for (;;) + { + char diff_help[256]; + int snarfed = lf_snarf (diff, diff_help, sizeof diff_help); + + if (snarfed <= 0) + return snarfed != 0; + + checksigs (); + + if (diff_help[0] == ' ') + puts (diff_help + 1); + else + { + char *numend; + uintmax_t val; + lin llen, rlen, lenmax; + errno = 0; + llen = val = strtoumax (diff_help + 1, &numend, 10); + if (llen < 0 || llen != val || errno || *numend != ',') + fatal (diff_help); + rlen = val = strtoumax (numend + 1, &numend, 10); + if (rlen < 0 || rlen != val || errno || *numend) + fatal (diff_help); + + lenmax = MAX (llen, rlen); + + switch (diff_help[0]) + { + case 'i': + if (suppress_common_lines) + lf_skip (diff, lenmax); + else + lf_copy (diff, lenmax, stdout); + + lf_copy (left, llen, outfile); + lf_skip (right, rlen); + break; + + case 'c': + lf_copy (diff, lenmax, stdout); + if (! edit (left, lname, lline, llen, + right, rname, rline, rlen, + outfile)) + return false; + break; + + default: + fatal (diff_help); + } + + lline += llen; + rline += rlen; + } + } +} + +/* Return true if DIR is an existing directory. */ +static bool +diraccess (char const *dir) +{ + struct stat buf; + return stat (dir, &buf) == 0 && S_ISDIR (buf.st_mode); +} + +#ifndef P_tmpdir +# define P_tmpdir "/tmp" +#endif +#ifndef TMPDIR_ENV +# define TMPDIR_ENV "TMPDIR" +#endif + +/* Open a temporary file and return its file descriptor. Put into + tmpname the address of a newly allocated buffer that holds the + file's name. Use the prefix "sdiff". */ +static int +temporary_file (void) +{ + char const *tmpdir = getenv (TMPDIR_ENV); + char const *dir = tmpdir ? tmpdir : P_tmpdir; + char *buf = xmalloc (strlen (dir) + 1 + 5 + 6 + 1); + int fd; + int e; + sigset_t procmask; + sigset_t blocked; + sprintf (buf, "%s/sdiffXXXXXX", dir); + sigemptyset (&blocked); + sigaddset (&blocked, SIGINT); + sigprocmask (SIG_BLOCK, &blocked, &procmask); + fd = mkstemp (buf); + e = errno; + if (0 <= fd) + tmpname = buf; + sigprocmask (SIG_SETMASK, &procmask, 0); + errno = e; + return fd; +} diff --git a/contrib/diffutils-2.8/src/side.c b/contrib/diffutils-2.8/src/side.c new file mode 100644 index 0000000000..3eaef4d205 --- /dev/null +++ b/contrib/diffutils-2.8/src/side.c @@ -0,0 +1,281 @@ +/* sdiff-format output routines for GNU DIFF. + + Copyright (C) 1991, 1992, 1993, 1998, 2001, 2002, 2004 Free + Software Foundation, Inc. + + This file is part of GNU DIFF. + + GNU DIFF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. No author or distributor + accepts responsibility to anyone for the consequences of using it + or for whether it serves any particular purpose or works at all, + unless he says so in writing. Refer to the GNU DIFF General Public + License for full details. + + Everyone is granted permission to copy, modify and redistribute + GNU DIFF, but only under the conditions described in the + GNU DIFF General Public License. A copy of this license is + supposed to have been given to you along with GNU DIFF so you + can know your rights and responsibilities. It should be in a + file named COPYING. Among other things, the copyright notice + and this notice must be preserved on all copies. */ + +#include "diff.h" + +static void print_sdiff_common_lines (lin, lin); +static void print_sdiff_hunk (struct change *); + +/* Next line number to be printed in the two input files. */ +static lin next0, next1; + +/* Print the edit-script SCRIPT as a sdiff style output. */ + +void +print_sdiff_script (struct change *script) +{ + begin_output (); + + next0 = next1 = - files[0].prefix_lines; + print_script (script, find_change, print_sdiff_hunk); + + print_sdiff_common_lines (files[0].valid_lines, files[1].valid_lines); +} + +/* Tab from column FROM to column TO, where FROM <= TO. Yield TO. */ + +static size_t +tab_from_to (size_t from, size_t to) +{ + FILE *out = outfile; + size_t tab; + size_t tab_size = tabsize; + + if (!expand_tabs) + for (tab = from + tab_size - from % tab_size; tab <= to; tab += tab_size) + { + putc ('\t', out); + from = tab; + } + while (from++ < to) + putc (' ', out); + return to; +} + +/* Print the text for half an sdiff line. This means truncate to + width observing tabs, and trim a trailing newline. Return the + last column written (not the number of chars). */ + +static size_t +print_half_line (char const *const *line, size_t indent, size_t out_bound) +{ + FILE *out = outfile; + register size_t in_position = 0; + register size_t out_position = 0; + register char const *text_pointer = line[0]; + register char const *text_limit = line[1]; + + while (text_pointer < text_limit) + { + register unsigned char c = *text_pointer++; + + switch (c) + { + case '\t': + { + size_t spaces = tabsize - in_position % tabsize; + if (in_position == out_position) + { + size_t tabstop = out_position + spaces; + if (expand_tabs) + { + if (out_bound < tabstop) + tabstop = out_bound; + for (; out_position < tabstop; out_position++) + putc (' ', out); + } + else + if (tabstop < out_bound) + { + out_position = tabstop; + putc (c, out); + } + } + in_position += spaces; + } + break; + + case '\r': + { + putc (c, out); + tab_from_to (0, indent); + in_position = out_position = 0; + } + break; + + case '\b': + if (in_position != 0 && --in_position < out_bound) + { + if (out_position <= in_position) + /* Add spaces to make up for suppressed tab past out_bound. */ + for (; out_position < in_position; out_position++) + putc (' ', out); + else + { + out_position = in_position; + putc (c, out); + } + } + break; + + case '\f': + case '\v': + control_char: + if (in_position < out_bound) + putc (c, out); + break; + + default: + if (! isprint (c)) + goto control_char; + /* falls through */ + case ' ': + if (in_position++ < out_bound) + { + out_position = in_position; + putc (c, out); + } + break; + + case '\n': + return out_position; + } + } + + return out_position; +} + +/* Print side by side lines with a separator in the middle. + 0 parameters are taken to indicate white space text. + Blank lines that can easily be caught are reduced to a single newline. */ + +static void +print_1sdiff_line (char const *const *left, char sep, + char const *const *right) +{ + FILE *out = outfile; + size_t hw = sdiff_half_width; + size_t c2o = sdiff_column2_offset; + size_t col = 0; + bool put_newline = false; + + if (left) + { + put_newline |= left[1][-1] == '\n'; + col = print_half_line (left, 0, hw); + } + + if (sep != ' ') + { + col = tab_from_to (col, (hw + c2o - 1) / 2) + 1; + if (sep == '|' && put_newline != (right[1][-1] == '\n')) + sep = put_newline ? '/' : '\\'; + putc (sep, out); + } + + if (right) + { + put_newline |= right[1][-1] == '\n'; + if (**right != '\n') + { + col = tab_from_to (col, c2o); + print_half_line (right, col, hw); + } + } + + if (put_newline) + putc ('\n', out); +} + +/* Print lines common to both files in side-by-side format. */ +static void +print_sdiff_common_lines (lin limit0, lin limit1) +{ + lin i0 = next0, i1 = next1; + + if (!suppress_common_lines && (i0 != limit0 || i1 != limit1)) + { + if (sdiff_merge_assist) + { + long int len0 = limit0 - i0; + long int len1 = limit1 - i1; + fprintf (outfile, "i%ld,%ld\n", len0, len1); + } + + if (!left_column) + { + while (i0 != limit0 && i1 != limit1) + print_1sdiff_line (&files[0].linbuf[i0++], ' ', + &files[1].linbuf[i1++]); + while (i1 != limit1) + print_1sdiff_line (0, ')', &files[1].linbuf[i1++]); + } + while (i0 != limit0) + print_1sdiff_line (&files[0].linbuf[i0++], '(', 0); + } + + next0 = limit0; + next1 = limit1; +} + +/* Print a hunk of an sdiff diff. + This is a contiguous portion of a complete edit script, + describing changes in consecutive lines. */ + +static void +print_sdiff_hunk (struct change *hunk) +{ + lin first0, last0, first1, last1; + register lin i, j; + + /* Determine range of line numbers involved in each file. */ + enum changes changes = + analyze_hunk (hunk, &first0, &last0, &first1, &last1); + if (!changes) + return; + + /* Print out lines up to this change. */ + print_sdiff_common_lines (first0, first1); + + if (sdiff_merge_assist) + { + long int len0 = last0 - first0 + 1; + long int len1 = last1 - first1 + 1; + fprintf (outfile, "c%ld,%ld\n", len0, len1); + } + + /* Print ``xxx | xxx '' lines */ + if (changes == CHANGED) + { + for (i = first0, j = first1; i <= last0 && j <= last1; i++, j++) + print_1sdiff_line (&files[0].linbuf[i], '|', &files[1].linbuf[j]); + changes = (i <= last0 ? OLD : 0) + (j <= last1 ? NEW : 0); + next0 = first0 = i; + next1 = first1 = j; + } + + /* Print `` > xxx '' lines */ + if (changes & NEW) + { + for (j = first1; j <= last1; ++j) + print_1sdiff_line (0, '>', &files[1].linbuf[j]); + next1 = j; + } + + /* Print ``xxx < '' lines */ + if (changes & OLD) + { + for (i = first0; i <= last0; ++i) + print_1sdiff_line (&files[0].linbuf[i], '<', 0); + next0 = i; + } +} diff --git a/contrib/diffutils-2.8/src/system.h b/contrib/diffutils-2.8/src/system.h new file mode 100644 index 0000000000..e480cc5c70 --- /dev/null +++ b/contrib/diffutils-2.8/src/system.h @@ -0,0 +1,326 @@ +/* System dependent declarations. + + Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1998, 2001, 2002, + 2004 Free Software Foundation, Inc. + + This file is part of GNU DIFF. + + GNU DIFF is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GNU DIFF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include + +/* Don't bother to support K&R C compilers any more; it's not worth + the trouble. These macros prevent some library modules from being + compiled in K&R C mode. */ +#define PARAMS(Args) Args +#define PROTOTYPES 1 + +/* Define `__attribute__' and `volatile' first + so that they're used consistently in all system includes. */ +#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 6) || __STRICT_ANSI__ +# define __attribute__(x) +#endif +#if defined const && !defined volatile +# define volatile +#endif + +/* Verify a requirement at compile-time (unlike assert, which is runtime). */ +#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; } + + +/* Determine whether an integer type is signed, and its bounds. + This code assumes two's (or one's!) complement with no holes. */ + +/* The extra casts work around common compiler bugs, + e.g. Cray C 5.0.3.0 when t == time_t. */ +#ifndef TYPE_SIGNED +# define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) +#endif +#ifndef TYPE_MINIMUM +# define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \ + ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) \ + : (t) 0)) +#endif +#ifndef TYPE_MAXIMUM +# define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t))) +#endif + +#include +#include + +#ifndef S_IRWXU +# define S_IRWXU 0700 +#endif +#ifndef S_IRWXG +# define S_IRWXG 0070 +#endif +#ifndef S_IRWXO +# define S_IRWXO 0007 +#endif + +#if HAVE_UNISTD_H +# include +#endif + +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif +#ifndef SEEK_CUR +# define SEEK_CUR 1 +#endif + +#ifndef STDIN_FILENO +# define STDIN_FILENO 0 +#endif +#ifndef STDOUT_FILENO +# define STDOUT_FILENO 1 +#endif +#ifndef STDERR_FILENO +# define STDERR_FILENO 2 +#endif + +#include + +#if HAVE_FCNTL_H +# include +#else +# if HAVE_SYS_FILE_H +# include +# endif +#endif + +#if !HAVE_DUP2 +# define dup2(f, t) (close (t), fcntl (f, F_DUPFD, t)) +#endif + +#ifndef O_RDONLY +# define O_RDONLY 0 +#endif +#ifndef O_RDWR +# define O_RDWR 2 +#endif +#ifndef S_IRUSR +# define S_IRUSR 0400 +#endif +#ifndef S_IWUSR +# define S_IWUSR 0200 +#endif + +#if HAVE_SYS_WAIT_H +# include +#endif +#ifndef WEXITSTATUS +# define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8) +#endif +#ifndef WIFEXITED +# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif + +#ifndef STAT_BLOCKSIZE +# if HAVE_STRUCT_STAT_ST_BLKSIZE +# define STAT_BLOCKSIZE(s) ((s).st_blksize) +# else +# define STAT_BLOCKSIZE(s) (8 * 1024) +# endif +#endif + +#if HAVE_DIRENT_H +# include +# define NAMLEN(dirent) strlen ((dirent)->d_name) +#else +# define dirent direct +# define NAMLEN(dirent) ((dirent)->d_namlen) +# if HAVE_SYS_NDIR_H +# include +# endif +# if HAVE_SYS_DIR_H +# include +# endif +# if HAVE_NDIR_H +# include +# endif +#endif + +#include +#define EXIT_TROUBLE 2 + +#include + +#if HAVE_INTTYPES_H +# include +#endif +#ifndef PTRDIFF_MAX +# define PTRDIFF_MAX TYPE_MAXIMUM (ptrdiff_t) +#endif +#ifndef SIZE_MAX +# define SIZE_MAX TYPE_MAXIMUM (size_t) +#endif +#ifndef UINTMAX_MAX +# define UINTMAX_MAX TYPE_MAXIMUM (uintmax_t) +#endif +#if ! HAVE_STRTOUMAX && ! defined strtoumax +uintmax_t strtoumax (char const *, char **, int); +#endif + +#include + +#include +#if ! HAVE_STRCASECOLL +# if HAVE_STRICOLL || defined stricoll +# define strcasecoll(a, b) stricoll (a, b) +# else +# define strcasecoll(a, b) strcasecmp (a, b) /* best we can do */ +# endif +#endif +#if ! (HAVE_STRCASECMP || defined strcasecmp) +int strcasecmp (char const *, char const *); +#endif + +#if HAVE_LOCALE_H +# include +#else +# define setlocale(category, locale) +#endif + +#include + +#define _(msgid) gettext (msgid) +#define N_(msgid) msgid + +#include + +/* ISDIGIT differs from isdigit, as follows: + - Its arg may be any int or unsigned int; it need not be an unsigned char. + - It's guaranteed to evaluate its argument exactly once. + - It's typically faster. + POSIX 1003.1-2001 says that only '0' through '9' are digits. + Prefer ISDIGIT to isdigit unless it's important to use the locale's + definition of `digit' even when the host does not conform to POSIX. */ +#define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9) + +#include + +#include +#ifndef SA_RESTART +# ifdef SA_INTERRUPT /* e.g. SunOS 4.1.x */ +# define SA_RESTART SA_INTERRUPT +# else +# define SA_RESTART 0 +# endif +#endif +#if !defined SIGCHLD && defined SIGCLD +# define SIGCHLD SIGCLD +#endif + +#undef MIN +#undef MAX +#define MIN(a, b) ((a) <= (b) ? (a) : (b)) +#define MAX(a, b) ((a) >= (b) ? (a) : (b)) + +#include + +#if HAVE_VFORK_H +# include +#endif + +#if ! HAVE_WORKING_VFORK +# define vfork fork +#endif + +/* Type used for fast comparison of several bytes at a time. */ + +#ifndef word +# define word uintmax_t +#endif + +/* The integer type of a line number. Since files are read into main + memory, ptrdiff_t should be wide enough. */ + +typedef ptrdiff_t lin; +#define LIN_MAX PTRDIFF_MAX +verify (lin_is_signed, TYPE_SIGNED (lin)); +verify (lin_is_wide_enough, sizeof (ptrdiff_t) <= sizeof (lin)); +verify (lin_is_printable_as_long_int, sizeof (lin) <= sizeof (long int)); + +/* This section contains POSIX-compliant defaults for macros + that are meant to be overridden by hand in config.h as needed. */ + +#ifndef file_name_cmp +# define file_name_cmp strcmp +#endif + +#ifndef initialize_main +# define initialize_main(argcp, argvp) +#endif + +#ifndef NULL_DEVICE +# define NULL_DEVICE "/dev/null" +#endif + +/* Do struct stat *S, *T describe the same special file? */ +#ifndef same_special_file +# if HAVE_ST_RDEV && defined S_ISBLK && defined S_ISCHR +# define same_special_file(s, t) \ + (((S_ISBLK ((s)->st_mode) && S_ISBLK ((t)->st_mode)) \ + || (S_ISCHR ((s)->st_mode) && S_ISCHR ((t)->st_mode))) \ + && (s)->st_rdev == (t)->st_rdev) +# else +# define same_special_file(s, t) 0 +# endif +#endif + +/* Do struct stat *S, *T describe the same file? Answer -1 if unknown. */ +#ifndef same_file +# define same_file(s, t) \ + ((((s)->st_ino == (t)->st_ino) && ((s)->st_dev == (t)->st_dev)) \ + || same_special_file (s, t)) +#endif + +/* Do struct stat *S, *T have the same file attributes? + + POSIX says that two files are identical if st_ino and st_dev are + the same, but many filesystems incorrectly assign the same (device, + inode) pair to two distinct files, including: + + - GNU/Linux NFS servers that export all local filesystems as a + single NFS filesystem, if a local device number (st_dev) exceeds + 255, or if a local inode number (st_ino) exceeds 16777215. + + - Network Appliance NFS servers in snapshot directories; see + Network Appliance bug #195. + + - ClearCase MVFS; see bug id ATRia04618. + + Check whether two files that purport to be the same have the same + attributes, to work around instances of this common bug. Do not + inspect all attributes, only attributes useful in checking for this + bug. + + It's possible for two distinct files on a buggy filesystem to have + the same attributes, but it's not worth slowing down all + implementations (or complicating the configuration) to cater to + these rare cases in buggy implementations. */ + +#ifndef same_file_attributes +# define same_file_attributes(s, t) \ + ((s)->st_mode == (t)->st_mode \ + && (s)->st_nlink == (t)->st_nlink \ + && (s)->st_uid == (t)->st_uid \ + && (s)->st_gid == (t)->st_gid \ + && (s)->st_size == (t)->st_size \ + && (s)->st_mtime == (t)->st_mtime \ + && (s)->st_ctime == (t)->st_ctime) +#endif diff --git a/contrib/diffutils-2.8/src/util.c b/contrib/diffutils-2.8/src/util.c new file mode 100644 index 0000000000..809f125854 --- /dev/null +++ b/contrib/diffutils-2.8/src/util.c @@ -0,0 +1,775 @@ +/* Support routines for GNU DIFF. + + Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1998, 2001, 2002, + 2004 Free Software Foundation, Inc. + + This file is part of GNU DIFF. + + GNU DIFF is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GNU DIFF is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "diff.h" +#include +#include +#include +#include + +char const pr_program[] = PR_PROGRAM; + +/* Queue up one-line messages to be printed at the end, + when -l is specified. Each message is recorded with a `struct msg'. */ + +struct msg +{ + struct msg *next; + char args[1]; /* Format + 4 args, each '\0' terminated, concatenated. */ +}; + +/* Head of the chain of queues messages. */ + +static struct msg *msg_chain; + +/* Tail of the chain of queues messages. */ + +static struct msg **msg_chain_end = &msg_chain; + +/* Use when a system call returns non-zero status. + NAME should normally be the file name. */ + +void +perror_with_name (char const *name) +{ + error (0, errno, "%s", name); +} + +/* Use when a system call returns non-zero status and that is fatal. */ + +void +pfatal_with_name (char const *name) +{ + int e = errno; + print_message_queue (); + error (EXIT_TROUBLE, e, "%s", name); + abort (); +} + +/* Print an error message containing MSGID, then exit. */ + +void +fatal (char const *msgid) +{ + print_message_queue (); + error (EXIT_TROUBLE, 0, "%s", _(msgid)); + abort (); +} + +/* Like printf, except if -l in effect then save the message and print later. + This is used for things like "Only in ...". */ + +void +message (char const *format_msgid, char const *arg1, char const *arg2) +{ + message5 (format_msgid, arg1, arg2, 0, 0); +} + +void +message5 (char const *format_msgid, char const *arg1, char const *arg2, + char const *arg3, char const *arg4) +{ + if (paginate) + { + char *p; + char const *arg[5]; + int i; + size_t size[5]; + size_t total_size = offsetof (struct msg, args); + struct msg *new; + + arg[0] = format_msgid; + arg[1] = arg1; + arg[2] = arg2; + arg[3] = arg3 ? arg3 : ""; + arg[4] = arg4 ? arg4 : ""; + + for (i = 0; i < 5; i++) + total_size += size[i] = strlen (arg[i]) + 1; + + new = xmalloc (total_size); + + for (i = 0, p = new->args; i < 5; p += size[i++]) + memcpy (p, arg[i], size[i]); + + *msg_chain_end = new; + new->next = 0; + msg_chain_end = &new->next; + } + else + { + if (sdiff_merge_assist) + putchar (' '); + printf (_(format_msgid), arg1, arg2, arg3, arg4); + } +} + +/* Output all the messages that were saved up by calls to `message'. */ + +void +print_message_queue (void) +{ + char const *arg[5]; + int i; + struct msg *m = msg_chain; + + while (m) + { + struct msg *next = m->next; + arg[0] = m->args; + for (i = 0; i < 4; i++) + arg[i + 1] = arg[i] + strlen (arg[i]) + 1; + printf (_(arg[0]), arg[1], arg[2], arg[3], arg[4]); + free (m); + m = next; + } +} + +/* Call before outputting the results of comparing files NAME0 and NAME1 + to set up OUTFILE, the stdio stream for the output to go to. + + Usually, OUTFILE is just stdout. But when -l was specified + we fork off a `pr' and make OUTFILE a pipe to it. + `pr' then outputs to our stdout. */ + +static char const *current_name0; +static char const *current_name1; +static bool currently_recursive; + +void +setup_output (char const *name0, char const *name1, bool recursive) +{ + current_name0 = name0; + current_name1 = name1; + currently_recursive = recursive; + outfile = 0; +} + +#if HAVE_WORKING_FORK || HAVE_WORKING_VFORK +static pid_t pr_pid; +#endif + +void +begin_output (void) +{ + char *name; + + if (outfile != 0) + return; + + /* Construct the header of this piece of diff. */ + name = xmalloc (strlen (current_name0) + strlen (current_name1) + + strlen (switch_string) + 7); + + /* POSIX 1003.1-2001 specifies this format. But there are some bugs in + the standard: it says that we must print only the last component + of the pathnames, and it requires two spaces after "diff" if + there are no options. These requirements are silly and do not + match historical practice. */ + sprintf (name, "diff%s %s %s", switch_string, current_name0, current_name1); + + if (paginate) + { + if (fflush (stdout) != 0) + pfatal_with_name (_("write failed")); + + /* Make OUTFILE a pipe to a subsidiary `pr'. */ + { +#if HAVE_WORKING_FORK || HAVE_WORKING_VFORK + int pipes[2]; + + if (pipe (pipes) != 0) + pfatal_with_name ("pipe"); + + pr_pid = vfork (); + if (pr_pid < 0) + pfatal_with_name ("fork"); + + if (pr_pid == 0) + { + close (pipes[1]); + if (pipes[0] != STDIN_FILENO) + { + if (dup2 (pipes[0], STDIN_FILENO) < 0) + pfatal_with_name ("dup2"); + close (pipes[0]); + } + + execl (pr_program, pr_program, "-h", name, (char *) 0); + _exit (errno == ENOENT ? 127 : 126); + } + else + { + close (pipes[0]); + outfile = fdopen (pipes[1], "w"); + if (!outfile) + pfatal_with_name ("fdopen"); + } +#else + char *command = xmalloc (sizeof pr_program - 1 + 7 + + quote_system_arg ((char *) 0, name) + 1); + char *p; + sprintf (command, "%s -f -h ", pr_program); + p = command + sizeof pr_program - 1 + 7; + p += quote_system_arg (p, name); + *p = 0; + errno = 0; + outfile = popen (command, "w"); + if (!outfile) + pfatal_with_name (command); + free (command); +#endif + } + } + else + { + + /* If -l was not specified, output the diff straight to `stdout'. */ + + outfile = stdout; + + /* If handling multiple files (because scanning a directory), + print which files the following output is about. */ + if (currently_recursive) + printf ("%s\n", name); + } + + free (name); + + /* A special header is needed at the beginning of context output. */ + switch (output_style) + { + case OUTPUT_CONTEXT: + print_context_header (files, false); + break; + + case OUTPUT_UNIFIED: + print_context_header (files, true); + break; + + default: + break; + } +} + +/* Call after the end of output of diffs for one file. + Close OUTFILE and get rid of the `pr' subfork. */ + +void +finish_output (void) +{ + if (outfile != 0 && outfile != stdout) + { + int status; + int wstatus; + int werrno = 0; + if (ferror (outfile)) + fatal ("write failed"); +#if ! (HAVE_WORKING_FORK || HAVE_WORKING_VFORK) + wstatus = pclose (outfile); + if (wstatus == -1) + werrno = errno; +#else + if (fclose (outfile) != 0) + pfatal_with_name (_("write failed")); + if (waitpid (pr_pid, &wstatus, 0) < 0) + pfatal_with_name ("waitpid"); +#endif + status = (! werrno && WIFEXITED (wstatus) + ? WEXITSTATUS (wstatus) + : INT_MAX); + if (status) + error (EXIT_TROUBLE, werrno, + _(status == 126 + ? "subsidiary program `%s' could not be invoked" + : status == 127 + ? "subsidiary program `%s' not found" + : status == INT_MAX + ? "subsidiary program `%s' failed" + : "subsidiary program `%s' failed (exit status %d)"), + pr_program, status); + } + + outfile = 0; +} + +/* Compare two lines (typically one from each input file) + according to the command line options. + For efficiency, this is invoked only when the lines do not match exactly + but an option like -i might cause us to ignore the difference. + Return nonzero if the lines differ. */ + +bool +lines_differ (char const *s1, char const *s2) +{ + register char const *t1 = s1; + register char const *t2 = s2; + size_t column = 0; + + while (1) + { + register unsigned char c1 = *t1++; + register unsigned char c2 = *t2++; + + /* Test for exact char equality first, since it's a common case. */ + if (c1 != c2) + { + switch (ignore_white_space) + { + case IGNORE_ALL_SPACE: + /* For -w, just skip past any white space. */ + while (isspace (c1) && c1 != '\n') c1 = *t1++; + while (isspace (c2) && c2 != '\n') c2 = *t2++; + break; + + case IGNORE_SPACE_CHANGE: + /* For -b, advance past any sequence of white space in + line 1 and consider it just one space, or nothing at + all if it is at the end of the line. */ + if (isspace (c1)) + { + while (c1 != '\n') + { + c1 = *t1++; + if (! isspace (c1)) + { + --t1; + c1 = ' '; + break; + } + } + } + + /* Likewise for line 2. */ + if (isspace (c2)) + { + while (c2 != '\n') + { + c2 = *t2++; + if (! isspace (c2)) + { + --t2; + c2 = ' '; + break; + } + } + } + + if (c1 != c2) + { + /* If we went too far when doing the simple test + for equality, go back to the first non-white-space + character in both sides and try again. */ + if (c2 == ' ' && c1 != '\n' + && s1 + 1 < t1 + && isspace ((unsigned char) t1[-2])) + { + --t1; + continue; + } + if (c1 == ' ' && c2 != '\n' + && s2 + 1 < t2 + && isspace ((unsigned char) t2[-2])) + { + --t2; + continue; + } + } + + break; + + case IGNORE_TAB_EXPANSION: + if ((c1 == ' ' && c2 == '\t') + || (c1 == '\t' && c2 == ' ')) + { + size_t column2 = column; + for (;; c1 = *t1++) + { + if (c1 == ' ') + column++; + else if (c1 == '\t') + column += tabsize - column % tabsize; + else + break; + } + for (;; c2 = *t2++) + { + if (c2 == ' ') + column2++; + else if (c2 == '\t') + column2 += tabsize - column2 % tabsize; + else + break; + } + if (column != column2) + return true; + } + break; + + case IGNORE_NO_WHITE_SPACE: + break; + } + + /* Lowercase all letters if -i is specified. */ + + if (ignore_case) + { + c1 = tolower (c1); + c2 = tolower (c2); + } + + if (c1 != c2) + break; + } + if (c1 == '\n') + return false; + + column += c1 == '\t' ? tabsize - column % tabsize : 1; + } + + return true; +} + +/* Find the consecutive changes at the start of the script START. + Return the last link before the first gap. */ + +struct change * +find_change (struct change *start) +{ + return start; +} + +struct change * +find_reverse_change (struct change *start) +{ + return start; +} + +/* Divide SCRIPT into pieces by calling HUNKFUN and + print each piece with PRINTFUN. + Both functions take one arg, an edit script. + + HUNKFUN is called with the tail of the script + and returns the last link that belongs together with the start + of the tail. + + PRINTFUN takes a subscript which belongs together (with a null + link at the end) and prints it. */ + +void +print_script (struct change *script, + struct change * (*hunkfun) (struct change *), + void (*printfun) (struct change *)) +{ + struct change *next = script; + + while (next) + { + struct change *this, *end; + + /* Find a set of changes that belong together. */ + this = next; + end = (*hunkfun) (next); + + /* Disconnect them from the rest of the changes, + making them a hunk, and remember the rest for next iteration. */ + next = end->link; + end->link = 0; +#ifdef DEBUG + debug_script (this); +#endif + + /* Print this hunk. */ + (*printfun) (this); + + /* Reconnect the script so it will all be freed properly. */ + end->link = next; + } +} + +/* Print the text of a single line LINE, + flagging it with the characters in LINE_FLAG (which say whether + the line is inserted, deleted, changed, etc.). */ + +void +print_1_line (char const *line_flag, char const *const *line) +{ + char const *base = line[0], *limit = line[1]; /* Help the compiler. */ + FILE *out = outfile; /* Help the compiler some more. */ + char const *flag_format = 0; + + /* If -T was specified, use a Tab between the line-flag and the text. + Otherwise use a Space (as Unix diff does). + Print neither space nor tab if line-flags are empty. */ + + if (line_flag && *line_flag) + { + flag_format = initial_tab ? "%s\t" : "%s "; + fprintf (out, flag_format, line_flag); + } + + output_1_line (base, limit, flag_format, line_flag); + + if ((!line_flag || line_flag[0]) && limit[-1] != '\n') + fprintf (out, "\n\\ %s\n", _("No newline at end of file")); +} + +/* Output a line from BASE up to LIMIT. + With -t, expand white space characters to spaces, and if FLAG_FORMAT + is nonzero, output it with argument LINE_FLAG after every + internal carriage return, so that tab stops continue to line up. */ + +void +output_1_line (char const *base, char const *limit, char const *flag_format, + char const *line_flag) +{ + if (!expand_tabs) + fwrite (base, sizeof (char), limit - base, outfile); + else + { + register FILE *out = outfile; + register unsigned char c; + register char const *t = base; + register size_t column = 0; + size_t tab_size = tabsize; + + while (t < limit) + switch ((c = *t++)) + { + case '\t': + { + size_t spaces = tab_size - column % tab_size; + column += spaces; + do + putc (' ', out); + while (--spaces); + } + break; + + case '\r': + putc (c, out); + if (flag_format && t < limit && *t != '\n') + fprintf (out, flag_format, line_flag); + column = 0; + break; + + case '\b': + if (column == 0) + continue; + column--; + putc (c, out); + break; + + default: + column += isprint (c) != 0; + putc (c, out); + break; + } + } +} + +char const change_letter[] = { 0, 'd', 'a', 'c' }; + +/* Translate an internal line number (an index into diff's table of lines) + into an actual line number in the input file. + The internal line number is I. FILE points to the data on the file. + + Internal line numbers count from 0 starting after the prefix. + Actual line numbers count from 1 within the entire file. */ + +lin +translate_line_number (struct file_data const *file, lin i) +{ + return i + file->prefix_lines + 1; +} + +/* Translate a line number range. This is always done for printing, + so for convenience translate to long int rather than lin, so that the + caller can use printf with "%ld" without casting. */ + +void +translate_range (struct file_data const *file, + lin a, lin b, + long int *aptr, long int *bptr) +{ + *aptr = translate_line_number (file, a - 1) + 1; + *bptr = translate_line_number (file, b + 1) - 1; +} + +/* Print a pair of line numbers with SEPCHAR, translated for file FILE. + If the two numbers are identical, print just one number. + + Args A and B are internal line numbers. + We print the translated (real) line numbers. */ + +void +print_number_range (char sepchar, struct file_data *file, lin a, lin b) +{ + long int trans_a, trans_b; + translate_range (file, a, b, &trans_a, &trans_b); + + /* Note: we can have B < A in the case of a range of no lines. + In this case, we should print the line number before the range, + which is B. */ + if (trans_b > trans_a) + fprintf (outfile, "%ld%c%ld", trans_a, sepchar, trans_b); + else + fprintf (outfile, "%ld", trans_b); +} + +/* Look at a hunk of edit script and report the range of lines in each file + that it applies to. HUNK is the start of the hunk, which is a chain + of `struct change'. The first and last line numbers of file 0 are stored in + *FIRST0 and *LAST0, and likewise for file 1 in *FIRST1 and *LAST1. + Note that these are internal line numbers that count from 0. + + If no lines from file 0 are deleted, then FIRST0 is LAST0+1. + + Return UNCHANGED if only ignorable lines are inserted or deleted, + OLD if lines of file 0 are deleted, + NEW if lines of file 1 are inserted, + and CHANGED if both kinds of changes are found. */ + +enum changes +analyze_hunk (struct change *hunk, + lin *first0, lin *last0, + lin *first1, lin *last1) +{ + struct change *next; + lin l0, l1; + lin show_from, show_to; + lin i; + bool trivial = ignore_blank_lines || ignore_regexp.fastmap; + size_t trivial_length = ignore_blank_lines - 1; + /* If 0, ignore zero-length lines; + if SIZE_MAX, do not ignore lines just because of their length. */ + bool skip_leading_white_space = + (ignore_blank_lines && IGNORE_SPACE_CHANGE <= ignore_white_space); + + char const * const *linbuf0 = files[0].linbuf; /* Help the compiler. */ + char const * const *linbuf1 = files[1].linbuf; + + show_from = show_to = 0; + + *first0 = hunk->line0; + *first1 = hunk->line1; + + next = hunk; + do + { + l0 = next->line0 + next->deleted - 1; + l1 = next->line1 + next->inserted - 1; + show_from += next->deleted; + show_to += next->inserted; + + for (i = next->line0; i <= l0 && trivial; i++) + { + char const *line = linbuf0[i]; + char const *newline = linbuf0[i + 1] - 1; + size_t len = newline - line; + char const *p = line; + if (skip_leading_white_space) + while (isspace ((unsigned char) *p) && *p != '\n') + p++; + if (newline - p != trivial_length + && (! ignore_regexp.fastmap + || re_search (&ignore_regexp, line, len, 0, len, 0) < 0)) + trivial = 0; + } + + for (i = next->line1; i <= l1 && trivial; i++) + { + char const *line = linbuf1[i]; + char const *newline = linbuf1[i + 1] - 1; + size_t len = newline - line; + char const *p = line; + if (skip_leading_white_space) + while (isspace ((unsigned char) *p) && *p != '\n') + p++; + if (newline - p != trivial_length + && (! ignore_regexp.fastmap + || re_search (&ignore_regexp, line, len, 0, len, 0) < 0)) + trivial = 0; + } + } + while ((next = next->link) != 0); + + *last0 = l0; + *last1 = l1; + + /* If all inserted or deleted lines are ignorable, + tell the caller to ignore this hunk. */ + + if (trivial) + return UNCHANGED; + + return (show_from ? OLD : UNCHANGED) | (show_to ? NEW : UNCHANGED); +} + +/* Concatenate three strings, returning a newly malloc'd string. */ + +char * +concat (char const *s1, char const *s2, char const *s3) +{ + char *new = xmalloc (strlen (s1) + strlen (s2) + strlen (s3) + 1); + sprintf (new, "%s%s%s", s1, s2, s3); + return new; +} + +/* Yield a new block of SIZE bytes, initialized to zero. */ + +void * +zalloc (size_t size) +{ + void *p = xmalloc (size); + memset (p, 0, size); + return p; +} + +/* Yield the newly malloc'd pathname + of the file in DIR whose filename is FILE. */ + +char * +dir_file_pathname (char const *dir, char const *file) +{ + char const *base = base_name (dir); + bool omit_slash = !*base || base[strlen (base) - 1] == '/'; + return concat (dir, "/" + omit_slash, file); +} + +void +debug_script (struct change *sp) +{ + fflush (stdout); + + for (; sp; sp = sp->link) + { + long int line0 = sp->line0; + long int line1 = sp->line1; + long int deleted = sp->deleted; + long int inserted = sp->inserted; + fprintf (stderr, "%3ld %3ld delete %ld insert %ld\n", + line0, line1, deleted, inserted); + } + + fflush (stderr); +} -- 2.41.0