1
0

Source code upload

This commit is contained in:
calmsacibis995
2022-09-29 17:59:04 +03:00
parent 72fa9da3d7
commit 8fc8fa8089
33399 changed files with 11964078 additions and 0 deletions

249
eoe/cmd/diff/COPYING Normal file
View File

@@ -0,0 +1,249 @@
GNU GENERAL PUBLIC LICENSE
Version 1, February 1989
Copyright (C) 1989 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The license agreements of most software companies try to keep users
at the mercy of those companies. By contrast, our 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. The
General Public License applies to the Free Software Foundation's
software and to any other program whose authors commit to using it.
You can use it for your programs, too.
When we speak of free software, we are referring to freedom, not
price. Specifically, the General Public License is designed to make
sure that you have the freedom to give away or sell copies of free
software, 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 a 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 tell them 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.
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 Agreement 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 work containing the
Program or a portion of it, either verbatim or with modifications. Each
licensee is addressed as "you".
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
General Public License and to the absence of any warranty; and give any
other recipients of the Program a copy of this General Public License
along with the Program. You may charge a fee for the physical act of
transferring a copy.
2. You may modify your copy or copies of the Program or any portion of
it, and copy and distribute such modifications under the terms of Paragraph
1 above, provided that you also do the following:
a) cause the modified files to carry prominent notices stating that
you changed the files and the date of any change; and
b) cause the whole of any work that you distribute or publish, that
in whole or in part contains the Program or any part thereof, either
with or without modifications, to be licensed at no charge to all
third parties under the terms of this General Public License (except
that you may choose to grant warranty protection to some or all
third parties, at your option).
c) If the modified program normally reads commands interactively when
run, you must cause it, when started running for such interactive use
in the simplest and most usual 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 General
Public License.
d) 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.
Mere aggregation of another independent work with the Program (or its
derivative) on a volume of a storage or distribution medium does not bring
the other work under the scope of these terms.
3. You may copy and distribute the Program (or a portion or derivative of
it, under Paragraph 2) in object code or executable form under the terms of
Paragraphs 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
Paragraphs 1 and 2 above; or,
b) accompany it with a written offer, valid for at least three
years, to give any third party free (except for a nominal charge
for the cost of distribution) a complete machine-readable copy of the
corresponding source code, to be distributed under the terms of
Paragraphs 1 and 2 above; or,
c) accompany it with the information you received as to where the
corresponding source code may be obtained. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form alone.)
Source code for a work means the preferred form of the work for making
modifications to it. For an executable file, complete source code means
all the source code for all modules it contains; but, as a special
exception, it need not include source code for modules which are standard
libraries that accompany the operating system on which the executable
file runs, or for standard header files or definitions files that
accompany that operating system.
4. You may not copy, modify, sublicense, distribute or transfer the
Program except as expressly provided under this General Public License.
Any attempt otherwise to copy, modify, sublicense, distribute or transfer
the Program is void, and will automatically terminate your rights to use
the Program under this License. However, parties who have received
copies, or rights to use copies, from you under this General Public
License will not have their licenses terminated so long as such parties
remain in full compliance.
5. By copying, distributing or modifying 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.
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.
7. 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 the 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
the license, you may choose any version ever published by the Free Software
Foundation.
8. 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
9. 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.
10. 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
Appendix: 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 humanity, 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.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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) 19xx 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 a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
program `Gnomovision' (a program to direct compilers to make passes
at assemblers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
That's all there is to it!

555
eoe/cmd/diff/ChangeLog Normal file
View File

@@ -0,0 +1,555 @@
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.
Cancelling provisionals near start of run must handle already
cancelled provisionals.
Cancelling subruns of provisionals was cancelling 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 cancelling 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 (diif_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 assigment.
* 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 typo `preceeding' 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).
Local Variables:
mode: indented-text
left-margin: 8
version-control: never
End:

View File

@@ -0,0 +1,42 @@
This file describes the more significant of the changes
made by Silicon Graphics, during its port of DIFF 1.15.
The file "Changes.gnu-sgi.diff.out" contains a diff
(using -uw options) output between the original source
and the final SGI port, for each *.c and *.h file.
As part of the port, SGI:
1) optimized performance in the case that the files
being diff'd don't fit comfortably in main memory.
In this large file case, if no GNU specific options
are specified, and if /usr/bin/odiff is present,
then odiff is automatically invoked, since it is
much faster on huge files. This port of GNU diff
is typically faster on files that fit in main memory,
thanks in part to its use of mmap, and to a quite
different algorithm optimized for this case.
2) optimized performance in the case that the two
files being diff'd are identical. Consequently
diff of two identical files is actually quite
a bit faster than "cmp" of the same two files.
3) Dropped support for GNU's +longoptions, in part
since they are changing the syntax to --longoption
in future GNU diff releases, and it didn't make
sense to support the +longoption form for just
this single release from SGI.
4) added the local SGI "diff -x" option, for excluding
subtrees on a recursive diff.
5) determine if files are binary (which by default
can result in the message: Binary files %s and %s differ)
by checking for NUL bytes in the first BUFSIZ (8k)
bytes. This NUL check is consistent with SVR4
and with previous versions of diff on SGI systems.
The GNU source for diff 1.15 checked instead
for characters that were not in the ISO 8859 set.
Silicon Graphics
Dec 29, 1992

View File

@@ -0,0 +1,956 @@
--- source.gnu.orig/analyze.c Sun Jan 6 15:05:11 1991
+++ analyze.c Fri Jul 31 23:08:48 1992
@@ -35,6 +35,7 @@
void setup_output ();
extern int no_discards;
+extern int files_are_identical;
static int *xvec, *yvec; /* Vectors being compared. */
static int *fdiag; /* Vector, indexed by diagonal, containing
@@ -711,7 +712,112 @@
return script;
}
-
+
+#include <invent.h>
+/* Return size of main memory in bytes */
+memsize(){
+ inventory_t *getinvent(void);
+ inventory_t *sp;
+ static int sz = 0;
+
+ if (sz == 0)
+ {
+ while ((sp = getinvent()) != 0)
+ {
+ if (sp->inv_class == INV_MEMORY && sp->inv_type == INV_MAIN)
+ {
+ sz = sp->inv_state;
+ break;
+ }
+ }
+ }
+
+ if (sz == 0)
+ sz = 8*1024*1024; /* 8 MByte default main memory size */
+
+ return sz;
+}
+
+#include <signal.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+int
+tryodiff (char *cmd, int argc, char **argv)
+{
+ int status, pid, w, sig;
+ struct sigaction oldistat, oldqstat, oldcstat, newiqstat, newcstat, newustat;
+
+ /*
+ * ignore INT and QUIT, saving previous handlers and masks
+ */
+ if (sigaction(SIGINT,NULL,&oldistat) == -1)
+ return(-1);
+
+ newiqstat.sa_handler = SIG_IGN;
+ newiqstat.sa_flags = 0;
+ newcstat.sa_handler = SIG_DFL;
+ newcstat.sa_flags = 0;
+
+ if ( (sigaction(SIGINT,&newiqstat,&oldistat) == -1) ||
+ (sigaction(SIGQUIT,&newiqstat,&oldqstat) == -1) ||
+ (sigaction(SIGCLD,&newcstat,&oldcstat) == -1) ) {
+ return(-1);
+ }
+
+ if ((pid = fork()) == 0) {
+ char *emsg = ": sigaction internal botch\n";
+ /* Child process */
+ /* reinstall old handlers and masks. */
+ (void) sigaction(SIGINT,&oldistat,NULL);
+ (void) sigaction(SIGQUIT,&oldqstat,NULL);
+ (void) sigaction(SIGCLD,&oldcstat,NULL);
+ argv[0] = cmd;
+ (void) execvp(argv[0], argv);
+
+ /* oops - exec failed - tell parent that we didn't
+ * do anything useful by committing SIGUSR2 harikari.
+ */
+ newustat.sa_handler = SIG_DFL;
+ newustat.sa_flags = 0;
+ sigaction(SIGUSR2,&newustat,NULL);
+ kill(getpid(), SIGUSR2);
+ /* should be dead by now -- but just in case ... */
+ /* Avoid stdio: parent process's buffers are inherited. */
+ write (fileno (stderr), program, strlen (program));
+ write (fileno (stderr), emsg, strlen(emsg));
+ _exit(127); /* dont double fflush stdio */
+ /* NOTREACHED */
+ }
+
+ if (pid < 0) {
+ w = -1; /* fork failed */
+ } else {
+ w = waitpid(pid,&status,0);
+ }
+
+ /* reinstall old handlers and masks. */
+ (void) sigaction(SIGINT,&oldistat,NULL);
+ (void) sigaction(SIGQUIT,&oldqstat,NULL);
+ (void) sigaction(SIGCLD,&oldcstat,NULL);
+
+ sig = WTERMSIG(status);
+
+ if (w == -1)
+ return -1; /* fork failed */
+ else if (WIFSIGNALED(status) && sig == SIGUSR2)
+ return -1; /* exec failed */
+ else if (WIFEXITED(status))
+ return WEXITSTATUS(status); /* normal odiff exit */
+ else if (WIFSIGNALED(status) && (sig == SIGINT || sig == SIGQUIT))
+ kill(getpid(), sig); /* reissue held off signal to self */
+ return 2; /* problems */
+}
+
+extern int xargc;
+extern char **xargv;
+extern int gnudiffopts;
+
/* Report the differences of two files. DEPTH is the current directory
depth. */
int
@@ -734,8 +840,42 @@
&& filevec[0].stat.st_dev == filevec[1].stat.st_dev)
return 0;
+ /* See if the two named files are too big to fit in memory
+ comfortably. Since GNU diff reads/mmaps both files into its
+ virtual addr space, it pages heavily on huge files. The old BSD
+ derived "odiff" is much more space (swap and main memory)
+ efficient. But if the files fit in main memory, then the GNU
+ diff is quite a bit faster - as much as 2x to 3x faster. Arbitrarily
+ consider 1/4 Main Memory size as too big. User can force choice:
+ specify -H always gets GNU diff, use odiff always gets the old BSD diff.
+ Return of -1 from tryodiff means that odiff wasn't even run - so we
+ should try further here instead. */
+
+ if (gnudiffopts == 0 &&
+ (filevec[0].stat.st_size + filevec[1].stat.st_size) > memsize()/4 )
+ {
+ int ret;
+ if ((ret = tryodiff("odiff",xargc,xargv)) != -1)
+ return ret;
+ }
+
+ files_are_identical = 0;
+
binary = read_files (filevec);
+ if (files_are_identical)
+ {
+ for (i = 0; i < 2; ++i)
+ if (filevec[i].buffer)
+ {
+ if (filevec[i].buffer_was_mmapped)
+ munmap (filevec[i].buffer, filevec[i].bufsize + 2);
+ else
+ free (filevec[i].buffer);
+ }
+ return 0;
+ }
+
/* If we have detected that file 0 is a binary file,
compare the two files as binary. This can happen
only when the first chunk is read.
@@ -753,7 +893,12 @@
for (i = 0; i < 2; ++i)
if (filevec[i].buffer)
+ {
+ if (filevec[i].buffer_was_mmapped)
+ munmap (filevec[i].buffer, filevec[i].bufsize + 2);
+ else
free (filevec[i].buffer);
+ }
return differs;
}
@@ -900,7 +1045,12 @@
for (i = 0; i < 2; ++i)
{
if (filevec[i].buffer != 0)
+ {
+ if (filevec[i].buffer_was_mmapped)
+ munmap (filevec[i].buffer, filevec[i].bufsize + 2);
+ else
free (filevec[i].buffer);
+ }
free (filevec[i].linbuf);
}
--- source.gnu.orig/diff.c Mon Mar 9 19:58:10 1992
+++ diff.c Fri Jul 31 23:08:49 1992
@@ -23,7 +23,7 @@
#define GDIFF_MAIN
#include "regex.h"
#include "diff.h"
-#include "getopt.h"
+#include <getopt.h>
/* Nonzero for -r: if comparing two directories,
@@ -66,45 +66,12 @@
return result;
}
-
-/* The numbers 129 and 130 that appear in the fourth element
- for the context and unidiff entries are used as a way of
- telling the big switch in `main' how to process those options. */
-static struct option longopts[] =
-{
- {"ignore-blank-lines", 0, 0, 'B'},
- {"context", 2, 0, 129},
- {"ifdef", 1, 0, 'D'},
- {"show-function-line", 1, 0, 'F'},
- {"speed-large-files", 0, 0, 'H'},
- {"ignore-matching-lines", 1, 0, 'I'},
- {"file-label", 1, 0, 'L'},
- {"entire-new-files", 0, 0, 'N'},
- {"new-files", 0, 0, 'N'},
- {"starting-file", 1, 0, 'S'},
- {"initial-tab", 0, 0, 'T'},
- {"text", 0, 0, 'a'},
- {"all-text", 0, 0, 'a'},
- {"ascii", 0, 0, 'a'},
- {"ignore-space-change", 0, 0, 'b'},
- {"minimal", 0, 0, 'd'},
- {"ed", 0, 0, 'e'},
- {"reversed-ed", 0, 0, 'f'},
- {"ignore-case", 0, 0, 'i'},
- {"print", 0, 0, 'l'},
- {"rcs", 0, 0, 'n'},
- {"show-c-function", 0, 0, 'p'},
- {"binary", 0, 0, 'q'},
- {"brief", 0, 0, 'q'},
- {"recursive", 0, 0, 'r'},
- {"report-identical-files", 0, 0, 's'},
- {"expand-tabs", 0, 0, 't'},
- {"ignore-all-space", 0, 0, 'w'},
- {"unified", 2, 0, 130},
- {"version", 0, 0, 'v'},
- {0, 0, 0, 0}
-};
+int xargc;
+char **xargv;
+int gnudiffopts;
+int sgidiffopts;
+
main (argc, argv)
int argc;
@@ -113,8 +80,10 @@
int val;
int c;
int prev = -1;
- int longind;
extern char *version_string;
+ extern char *optarg;
+ extern int optind;
+ extern void setxpat(char *);
program = argv[0];
@@ -143,28 +112,30 @@
msg_chain = NULL;
msg_chain_end = NULL;
no_discards = 0;
+ gnudiffopts = 0;
+ sgidiffopts = 0;
+ xargc = argc;
+ xargv = argv;
/* Decode the options. */
- while ((c = getopt_long (argc, argv,
- "0123456789abBcC:dD:efF:hHiI:lL:nNpqrsS:tTuvw",
- longopts, &longind)) != EOF)
+ while ((c = getopt (argc, argv,
+ "0123456789abBcC:dD:efF:hHiI:lL:nNpqrsS:tTuvwx:"
+ )) != EOF)
{
- if (c == 0) /* Long option. */
- c = longopts[longind].val;
switch (c)
{
/* All digits combine in decimal to specify the context-size. */
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case '0':
+ case '1': gnudiffopts++;
+ case '2': gnudiffopts++;
+ case '3': gnudiffopts++;
+ case '4': gnudiffopts++;
+ case '5': gnudiffopts++;
+ case '6': gnudiffopts++;
+ case '7': gnudiffopts++;
+ case '8': gnudiffopts++;
+ case '9': gnudiffopts++;
+ case '0': gnudiffopts++;
if (context == -1)
context = 0;
/* If a context length has already been specified,
@@ -176,25 +147,23 @@
context = context * 10 + c - '0';
break;
- case 'a':
+ case 'a': gnudiffopts++;
/* Treat all files as text files; never treat as binary. */
always_text_flag = 1;
break;
- case 'b':
+ case 'b': sgidiffopts++;
/* Ignore changes in amount of whitespace. */
ignore_space_change_flag = 1;
length_varies = 1;
break;
- case 'B':
+ case 'B': gnudiffopts++;
/* Ignore changes affecting only blank lines. */
ignore_blank_lines_flag = 1;
break;
- case 'C':
- case 129: /* +context[=lines] */
- case 130: /* +unified[=lines] */
+ case 'C': gnudiffopts++;
if (optarg)
{
if (context >= 0)
@@ -209,35 +178,35 @@
}
/* Falls through. */
- case 'c':
+ case 'c': sgidiffopts++;
/* Make context-style output. */
specify_style (c == 130 ? OUTPUT_UNIFIED : OUTPUT_CONTEXT);
break;
- case 'd':
+ case 'd': gnudiffopts++;
/* Don't discard lines. This makes things slower (sometimes much
slower) but will find a guaranteed minimal set of changes. */
no_discards = 1;
break;
- case 'D':
+ case 'D': sgidiffopts++;
/* Make merged #ifdef output. */
specify_style (OUTPUT_IFDEF);
ifdef_string = optarg;
break;
- case 'e':
+ case 'e': sgidiffopts++;
/* Make output that is a valid `ed' script. */
specify_style (OUTPUT_ED);
break;
- case 'f':
+ case 'f': sgidiffopts++;
/* Make output that looks vaguely like an `ed' script
but has changes in the order they appear in the file. */
specify_style (OUTPUT_FORWARD_ED);
break;
- case 'F':
+ case 'F': gnudiffopts++;
/* Show, for each set of changes, the previous line that
matches the specified regexp. Currently affects only
context-style output. */
@@ -244,7 +213,7 @@
function_regexp = optarg;
break;
- case 'h':
+ case 'h': sgidiffopts++;
/* Split the files into chunks of around 1500 lines
for faster processing. Usually does not change the result.
@@ -251,29 +220,29 @@
This currently has no effect. */
break;
- case 'H':
+ case 'H': gnudiffopts++;
/* Turn on heuristics that speed processing of large files
with a small density of changes. */
heuristic = 1;
break;
- case 'i':
+ case 'i': sgidiffopts++;
/* Ignore changes in case. */
ignore_case_flag = 1;
break;
- case 'I':
+ case 'I': gnudiffopts++;
/* Ignore changes affecting only lines that match the
specified regexp. */
ignore_regexp = optarg;
break;
- case 'l':
+ case 'l': sgidiffopts++;
/* Pass the output through `pr' to paginate it. */
paginate_flag = 1;
break;
- case 'L':
+ case 'L': gnudiffopts++;
/* Specify file labels for `-c' output headers. */
if (!file_label[0])
file_label[0] = optarg;
@@ -283,52 +252,52 @@
fatal ("too many file label options");
break;
- case 'n':
+ case 'n': sgidiffopts++;
/* Output RCS-style diffs, like `-f' except that each command
specifies the number of lines affected. */
specify_style (OUTPUT_RCS);
break;
- case 'N':
+ case 'N': gnudiffopts++;
/* When comparing directories, if a file appears only in one
directory, treat it as present but empty in the other. */
entire_new_file_flag = 1;
break;
- case 'p':
+ case 'p': gnudiffopts++;
/* Make context-style output and show name of last C function. */
specify_style (OUTPUT_CONTEXT);
function_regexp = "^[_a-zA-Z]";
break;
- case 'q':
+ case 'q': gnudiffopts++;
no_details_flag = 1;
break;
- case 'r':
+ case 'r': sgidiffopts++;
/* When comparing directories,
recursively compare any subdirectories found. */
recursive = 1;
break;
- case 's':
+ case 's': sgidiffopts++;
/* Print a message if the files are the same. */
print_file_same_flag = 1;
break;
- case 'S':
+ case 'S': sgidiffopts++;
/* When comparing directories, start with the specified
file name. This is used for resuming an aborted comparison. */
dir_start_file = optarg;
break;
- case 't':
+ case 't': sgidiffopts++;
/* Expand tabs to spaces in the output so that it preserves
the alignment of the input files. */
tab_expand_flag = 1;
break;
- case 'T':
+ case 'T': gnudiffopts++;
/* 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. */
@@ -335,21 +304,25 @@
tab_align_flag = 1;
break;
- case 'v':
+ case 'v': gnudiffopts++;
printf ("GNU diff version %s\n", version_string);
break;
- case 'u':
+ case 'u': gnudiffopts++;
/* Output the context diff in unidiff format. */
specify_style (OUTPUT_UNIFIED);
break;
- case 'w':
+ case 'w': sgidiffopts++;
/* Ignore horizontal whitespace when comparing lines. */
ignore_all_space_flag = 1;
length_varies = 1;
break;
+ case 'x': sgidiffopts++;
+ setxpat(optarg);
+ break;
+
default:
usage ();
}
@@ -401,19 +374,8 @@
usage ()
{
- fprintf (stderr, "\
-Usage: diff [-#] [-abBcdefhHilnNprstTuvw] [-C lines] [-F regexp] [-I regexp]\n\
- [-L label [-L label]] [-S file] [-D symbol] [+ignore-blank-lines]\n\
- [+context[=lines]] [+unified[=lines]] [+ifdef=symbol]\n\
- [+show-function-line=regexp]\n");
- fprintf (stderr, "\
- [+speed-large-files] [+ignore-matching-lines=regexp] [+new-file]\n\
- [+initial-tab] [+starting-file=file] [+text] [+all-text] [+ascii]\n\
- [+minimal] [+ignore-space-change] [+ed] [+reversed-ed] [+ignore-case]\n");
- fprintf (stderr, "\
- [+print] [+rcs] [+show-c-function] [+binary] [+brief] [+recursive]\n\
- [+report-identical-files] [+expand-tabs] [+ignore-all-space]\n\
- [+file-label=label [+file-label=label]] [+version] path1 path2\n");
+ fprintf (stderr, "Usage: diff [-bcefhilnrstw -Dstring -Sname -xpattern ] file1 file2\n");
+ fprintf (stderr, "\tGNU diff options: [-# -aBdHNpqTuv -Cnum -Fregexp -Iregexp -Llabel]\n");
exit (2);
}
--- source.gnu.orig/diff.h Mon Dec 9 21:50:39 1991
+++ diff.h Fri Jul 31 23:08:50 1992
@@ -90,7 +90,7 @@
#endif
/* Support old-fashioned C compilers. */
-#if !defined (__STDC__) && !defined (__GNUC__)
+#if !defined (__STDC__) && !defined (__GNUC__) && !defined(_MODERN_C)
#define const
#endif
@@ -314,6 +314,8 @@
The allocated size is always linbufsize
and the number of valid elements is buffered_lines. */
int *ltran;
+ /* 1 if buffer was mmapped - need to munmap instead of free */
+ int buffer_was_mmapped;
};
/* Describe the two files currently being compared. */
--- source.gnu.orig/dir.c Mon Mar 9 19:57:40 1992
+++ dir.c Fri Jul 31 23:08:50 1992
@@ -17,8 +17,41 @@
along with GNU DIFF; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+#include "regex.h"
#include "diff.h"
+static struct re_pattern_buffer **revec = NULL;
+static struct re_pattern_buffer **revec_end;
+
+/* add a directory name to the list to exclude
+ */
+void
+setxpat(char *pat)
+{
+ char *val;
+ int old_re_syntax = re_set_syntax (RE_SYNTAX_EGREP);
+
+ if (revec == NULL)
+ revec_end = revec = (struct re_pattern_buffer **) xmalloc (sizeof *revec);
+ else
+ {
+ int oldsz = revec_end - revec;
+ revec = (struct re_pattern_buffer **) xrealloc (revec, (oldsz+1) * (sizeof *revec));
+ revec_end = revec + oldsz;
+ }
+ *revec_end = (struct re_pattern_buffer *) xmalloc (sizeof (struct re_pattern_buffer));
+ bzero (*revec_end, sizeof (struct re_pattern_buffer));
+ if ((val = re_compile_pattern (pat, strlen(pat), *revec_end)) != NULL)
+ {
+ error ("%s: %s", pat, val);
+ fatal ("use egrep(1) style patterns");
+ /* NOTREACHED */
+ }
+ (*revec_end)->fastmap = (char *) xmalloc (256);
+ revec_end++;
+ re_set_syntax (old_re_syntax);
+}
+
static int compare_names ();
/* Read the directory named DIRNAME and return a sorted vector
@@ -76,6 +109,21 @@
while (next = readdir (reading))
{
+ if (revec)
+ {
+ struct re_pattern_buffer **rep;
+ int old_re_syntax = re_set_syntax (RE_SYNTAX_EGREP);
+ char *s = next->d_name;
+ int len = strlen (s);
+
+ for (rep = revec; rep < revec_end; rep++)
+ if (re_search (*rep, s, len, 0, len, 0) >= 0)
+ break;
+ re_set_syntax (old_re_syntax);
+ if (rep != revec_end)
+ continue;
+ }
+
/* Ignore the files `.' and `..' */
if (next->d_name[0] == '.'
&& (next->d_name[1] == 0
--- source.gnu.orig/io.c Thu Nov 29 13:15:43 1990
+++ io.c Fri Jul 31 23:08:51 1992
@@ -18,6 +18,7 @@
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "diff.h"
+#include <sys/mman.h>
/* Rotate a value n bits to the left. */
#define UINT_BIT (sizeof (unsigned) * CHAR_BIT)
@@ -28,10 +29,11 @@
/* Current file under consideration. */
struct file_data *current;
+int files_are_identical;
/* Check for binary files and compare them for exact identity. */
-/* Return 1 if BUF contains a non text character.
+/* Return 1 if BUF contains a nul character.
SIZE is the number of characters in BUF. */
static int
@@ -39,48 +41,13 @@
char *buf;
int size;
{
- static const char textchar[] = {
- /* ISO 8859 */
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1, 1, 1, 1, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- };
while (--size >= 0)
- if (!textchar[*buf++ & 0377])
+ if (*buf++ == '\0')
return 1;
return 0;
}
-int binary_file_threshold = 512;
+int binary_file_threshold = BUFSIZ;
/* Slurp the current file completely into core.
Return nonzero if it appears to be a binary file. */
@@ -104,6 +71,17 @@
else if ((current->stat.st_mode & S_IFMT) == S_IFREG)
{
current->bufsize = current->stat.st_size;
+ current->buffer = (char *)(-1);
+ current->buffer_was_mmapped = 0;
+ if (current->bufsize > 0) {
+ current->buffer
+ = (char *)mmap((void *)0, current->bufsize + 2,
+ PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_AUTOGROW, current->desc, 0);
+ }
+ if ((int)(current->buffer) != -1) {
+ current->buffered_chars = current->bufsize;
+ current->buffer_was_mmapped = 1;
+ } else {
current->buffer = (char *) xmalloc (current->bufsize + 2);
current->buffered_chars
= read (current->desc, current->buffer, current->bufsize);
@@ -110,6 +88,7 @@
if (current->buffered_chars < 0)
pfatal_with_name (current->name);
}
+ }
else
{
int cc;
@@ -334,6 +313,43 @@
&& current->suffix_begin == current->buffer + current->buffered_chars)
--current->linbuf[current->buffered_lines - 1].length;
}
+
+/* For same size files, look for mismatch w/o counting lines, in case identical */
+loop_for_mismatch (pp0, pp1)
+ char **pp0, **pp1;
+{
+ char *p0 = *pp0;
+ char *p1 = *pp1;
+
+ {
+ register int *ip0 = (int *)p0;
+ register int *ip1 = (int *)p1;
+ while (*ip0++ == *ip1++)
+ ;
+ --ip0; --ip1;
+ p0 = (char *)(ip0);
+ p1 = (char *)(ip1);
+ }
+ while (*p0++ == *p1++)
+ ;
+ *pp0 = p0;
+ *pp1 = p1;
+}
+
+/* Don't count lines until failed files_are_identical test */
+loop_for_line_count (pbase, pend)
+ char *pbase, *pend;
+{
+ int i = 0;
+ int j = pend - pbase;
+ int lines = 0;
+
+ while (i < j)
+ if (pbase[i++] == '\n')
+ ++lines;
+
+ return lines;
+}
/* Given a vector of two file_data objects, find the identical
prefixes and suffixes of each object. */
@@ -370,7 +386,28 @@
else
p1[filevec[1].buffered_chars] = ~p0[filevec[1].buffered_chars];
+ if (filevec[0].buffered_chars == filevec[1].buffered_chars)
+ {
/* Loop until first mismatch, or to the sentinel characters. */
+ loop_for_mismatch (&p0, &p1);
+
+ /* If the sentinel was passed, and lengths are equal, the
+ files are identical. */
+ if (p0 - filevec[0].buffer > filevec[0].buffered_chars)
+ {
+ filevec[0].prefix_end = p0 - 1;
+ filevec[1].prefix_end = p1 - 1;
+ filevec[0].prefix_lines = filevec[1].prefix_lines = 0;
+ filevec[0].suffix_begin = filevec[0].buffer;
+ filevec[1].suffix_begin = filevec[1].buffer;
+ filevec[0].suffix_lines = filevec[1].suffix_lines = 0;
+ files_are_identical = 1;
+ return;
+ }
+
+ lines = loop_for_line_count (filevec[0].buffer, p0 - 1);
+ }
+ else
while (1)
{
char c = *p0++;
@@ -389,20 +426,6 @@
&& p1 - filevec[1].buffer > filevec[1].buffered_chars)))
--p0, --p1, --lines;
- /* If the sentinel was passed, and lengths are equal, the
- files are identical. */
- if (p0 - filevec[0].buffer > filevec[0].buffered_chars
- && filevec[0].buffered_chars == filevec[1].buffered_chars)
- {
- filevec[0].prefix_end = p0 - 1;
- filevec[1].prefix_end = p1 - 1;
- filevec[0].prefix_lines = filevec[1].prefix_lines = lines;
- filevec[0].suffix_begin = filevec[0].buffer;
- filevec[1].suffix_begin = filevec[1].buffer;
- filevec[0].suffix_lines = filevec[1].suffix_lines = lines;
- return;
- }
-
/* Point at first nonmatching characters. */
--p0, --p1;
@@ -592,7 +615,12 @@
if (binary || this_binary)
return 1;
+ files_are_identical = 0;
+
find_identical_ends (filevec);
+
+ if (files_are_identical)
+ return 0;
for (i = 0; i < 2; ++i)
{
--- source.gnu.orig/util.c Sun Jan 6 15:14:14 1991
+++ util.c Fri Jul 31 23:08:53 1992
@@ -203,33 +203,24 @@
{
register char *t1, *t2;
register char end_char = line_end_char;
- int savechar;
/* Check first for exact identity.
If that is true, return 0 immediately.
This detects the common case of exact identity
- faster than complete comparison would. */
+ faster than complete comparison would.
+ The check for equal lengths is almost always not needed.
+ Only if the last line of two files both hash to the same
+ value, and the last line in the first file is a prefix
+ of the last line in the second file, and the first file
+ lacks a trailing newline, and length_varies is set,
+ and a ROBUST output style is chosen (which doesnt include
+ the artificial final newline in the length of the final line)
+ THEN does the length compare become critical to avoid falsely
+ concluding that the two lines are the same. Many thanks
+ to Paul Eggert for noticing this bug. */
- t1 = s1->text;
- t2 = s2->text;
-
- /* Alter the character following line 2 so it doesn't
- match that following line 1.
- (We used to alter the character after line 1,
- but that caused trouble if line 2 directly follows line 1.) */
- savechar = s2->text[s2->length];
- s2->text[s2->length] = s1->text[s1->length] + 1;
-
- /* Now find the first mismatch; this won't go past the
- character we just changed. */
- while (*t1++ == *t2++);
-
- /* Undo the alteration. */
- s2->text[s2->length] = savechar;
-
- /* If the comparison stopped at the alteration,
- the two lines are identical. */
- if (t2 == s2->text + s2->length + 1)
+ if (s1->length == s2->length
+ && memcmp (s1->text, s2->text, s1->length) == 0)
return 0;
/* Not exactly identical, but perhaps they match anyway
--- source.gnu.orig/diff3.c Fri Sep 30 22:14:15 1994
+++ diff3.c Tue Apr 15 17:16:51 1997
@@ -20,7 +20,7 @@
#include "system.h"
#include <stdio.h>
#include <signal.h>
-#include "getopt.h"
+#include <getopt.h>
extern char const version_string[];
@@ -202,6 +202,7 @@
static char const diff_program[] = DIFF_PROGRAM;
+#if 0
static struct option const longopts[] =
{
{"text", 0, 0, 'a'},
@@ -217,6 +218,7 @@
{"help", 0, 0, 129},
{0, 0, 0, 0}
};
+#endif
/*
* Main program. Calls diff twice on two pairs of input files,
@@ -243,7 +245,7 @@
initialize_main (&argc, &argv);
program_name = argv[0];
- while ((c = getopt_long (argc, argv, "aeimvx3AEL:TX", longopts, 0)) != EOF)
+ while ((c = getopt (argc, argv, "aeimvx3AEL:TX")) != EOF)
{
switch (c)
{
@@ -281,9 +283,11 @@
case 'T':
tab_align_flag = 1;
break;
+#if 0
case 'v':
printf ("diff3 - GNU diffutils version %s\n", version_string);
exit (0);
+#endif
case 129:
usage ();
check_stdout ();
@@ -561,9 +565,9 @@
*tmpblock,
**result_end;
- struct diff3_block const *last_diff3;
+ struct diff3_block *last_diff3;
- static struct diff3_block const zero_diff3;
+ static struct diff3_block zero_diff3;
/* Initialization */
result = 0;
@@ -1152,9 +1156,11 @@
*ap++ = diff_program;
if (always_text)
*ap++ = "-a";
+#if 0
sprintf (horizon_arg, "--horizon-lines=%d", horizon_lines);
*ap++ = horizon_arg;
*ap++ = "--";
+#endif
*ap++ = filea;
*ap++ = fileb;
*ap = 0;

78
eoe/cmd/diff/Makefile Normal file
View File

@@ -0,0 +1,78 @@
# Makefile for GNU DIFF
# Copyright (C) 1988, 1989 Free Software Foundation, Inc.
include $(ROOT)/usr/include/make/commondefs
# This file is part of GNU DIFF, as ported to Silicon Graphics systems.
# 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA.
#
# Report problems and direct all questions to:
#
# Your Silicon Graphics representative
# or the Silicon Graphics Geometry Hotline.
#
# This Makefile has been radically altered by SGI from the one
# in the original 1.15 diff release distributed by the Free
# Software Foundation, to better fit the Makefile tools
# supplied by SGI. Those porting this diff command to
# non-SGI systems should examine the original diff Makefile
# from FSF, as it contains instructions and options designed
# to facilitate ports to various systems. A copy of the original
# Makefile is included in this source as: Makefile.gnu.orig
#
# Those modifying and porting diff for use on SGI systems
# should find this Makefile well suited for their needs.
LCDEFS=-Dsparc
LLDOPTS =-Wl,-woff,85 # don't complain about regex stuff overriding libc
USRBIN=/usr/bin
SOURCEDIR=/usr/share/src/gnutools/diff
TARGETS=diff diff3
CFILES=diff.c analyze.c io.c context.c ed.c normal.c ifdef.c util.c dir.c \
version.c regex.c limits.h diff3.c alloca.c
HFILES=diff.h regex.h
DIFFOBJS=diff.o analyze.o io.o context.o ed.o normal.o util.o dir.o regex.o\
ifdef.o version.o
DIFF3OBJS=diff3.o
GNUSRCFILES=$(CFILES) $(HFILES) README diagmeet.note \
Makefile COPYING ChangeLog Makefile.gnu.orig Changes.gnu-sgi.README \
Changes.gnu-sgi.diff.out getopt.c getopt1.c getopt.h limits.h
default: $(TARGETS)
include $(COMMONRULES)
diff3: diff3.o
$(CCF) -o $@ $(DIFF3OBJS) $(LDFLAGS)
diff: $(DIFFOBJS)
$(CCF) -o $@ $(DIFFOBJS) $(LDFLAGS)
diff3.o: diff3.c
$(CCF) -c -DDIFF_PROGRAM=\"$(USRBIN)/diff\" diff3.c
install: default
$(INSTALL) -F $(USRBIN) diff
$(INSTALL) $(I_FLAGS) -F $(USRBIN) diff3
$(INSTALL) -m 444 -F $(SOURCEDIR) "$(GNUSRCFILES)"

View File

@@ -0,0 +1,108 @@
# Makefile for GNU DIFF
# Copyright (C) 1988, 1989 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA.
# You can compile this with ordinary cc as well,
# but gcc makes it faster.
# Also, gcc supports -O and -g together.
CC=cc -O
CFLAGS = -g -Dsparc # set -Dsparc to: 1) get alloca.h, 2) disable vfork - pj
INSTALL = cp
# On system V, enable these three lines:
# CFLAGS = -g -DUSG
# LIBS = -lPW
# INSTALL = cp
# (If you compile with GCC, you don't need to define LIBS.)
# And, depending on the names and contents of your header files,
# add either -DHAVE_NDIR or -DHAVE_DIRECT or both to CFLAGS.
# Add -DHAVE_NDIR to CFLAGS if your system used ndir.h instead of dirent.h
# Add -DHAVE_DIRECT to CFLAGS if your system uses 'struct direct' instead of
# 'struct dirent' (this is the case at least with one add-on ndir library).
# Use these definitions for XENIX:
# There are rumors of bugs in various Xenix's dirent.h and -ldir. As
# a result, we suggest using HAVE_NDIR and not using -ldir.
# CFLAGS = -O -DUSG -DXENIX -DHAVE_NDIR -DHAVE_DIRECT -DNDIR_IN_SYS
# LIBS = -lx -lPW
# INSTALL = cp
# Some System V machines do not come with libPW. If this is true, use
# the GNU alloca by switching the comment on the following lines.
ALLOCA =
# ALLOCA = $(archpfx)/alloca.o
bindir=/usr/local/bin/rcs5.6
prefix=
# All source files
srcs=diff.c analyze.c io.c context.c ed.c normal.c ifdef.c util.c dir.c \
version.c diff.h regex.c regex.h limits.h diff3.c \
getopt.c getopt1.c getopt.h alloca.c
# Object files for diff only.
objs=$(archpfx)diff.o $(archpfx)analyze.o $(archpfx)io.o $(archpfx)context.o \
$(archpfx)ed.o $(archpfx)normal.o $(archpfx)util.o $(archpfx)dir.o \
$(archpfx)regex.o $(archpfx)ifdef.o $(archpfx)version.o \
$(archpfx)getopt.o $(archpfx)getopt1.o
tapefiles = $(srcs) README diagmeet.note Makefile COPYING ChangeLog
all: $(archpfx)diff $(archpfx)diff3
$(archpfx)diff3: $(archpfx)diff3.o
$(CC) -o $(archpfx)diff3 $(CFLAGS) $(LDFLAGS) $(archpfx)diff3.o $(LIBS)
$(archpfx)diff: $(objs)
$(CC) -o $(archpfx)diff $(CFLAGS) $(LDFLAGS) $(objs) $(LIBS)
$(objs): diff.h
$(archpfx)context.o $(archpfx)diff.o: regex.h
$(archpfx)diff3.o: diff3.c
$(CC) -c $(CFLAGS) -DDIFF_PROGRAM=\"$(bindir)/diff\" diff3.c \
$(OUTPUT_OPTION)
clean:
rm -f *.o $(archpfx)diff $(archpfx)diff3 diff.tar diff.tar.Z
install: install-diff install-diff3
install-diff: $(prefix)$(bindir)/diff
$(prefix)$(bindir)/diff: $(archpfx)diff
strip $(archpfx)diff
$(INSTALL) $(archpfx)diff $(prefix)$(bindir)/diff
install-diff3: $(prefix)$(bindir)/diff3
$(prefix)$(bindir)/diff3: $(archpfx)diff3
strip $(archpfx)diff3
$(INSTALL) $(archpfx)diff3 $(prefix)$(bindir)/diff3
diff.tar: $(tapefiles)
mkdir tmp
mkdir tmp/diff
-ln $(tapefiles) tmp/diff
for file in $(tapefiles); do \
if [ ! -r tmp/diff/$$file ]; then cp $$file tmp/diff; fi \
done
cd tmp; tar cf ../diff.tar diff
rm -rf tmp
diff.tar.Z: diff.tar
compress < diff.tar > diff.tar.Z

184
eoe/cmd/diff/README Normal file
View File

@@ -0,0 +1,184 @@
This directory contains the GNU DIFF and DIFF3 utilities, version 1.15,
and version 2.7, respectively, as ported to Silicon Graphics systems.
See file COPYING for copying conditions. To compile and install on
Silicon Graphics systems, you may use the Makefile as provided.
To port to other systems, consider modifying the file Makefile.gnu.orig
acording to comments therein.
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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA.
See the file Changes.gnu-sgi.README for a description
of the changes made by SGI in its port of this software.
The rest of this README is copied directly from the
README contained in the original GNU diff 1.15 source.
---
Version 1.15 has the following new features; please see below for details.
-L (+file-label) option
-u (+unified) option
-a and -m options for diff3
Most output styles can represent incomplete input lines.
`Text' is defined by ISO 8859.
diff3 exit status 0 means success, 1 means overlaps, 2 means trouble.
This version of diff provides all the features of BSD's diff.
It has these additional features:
An input file may end in a non-newline character. If so, its last
line is called an incomplete line and is distinguished on output
from a full line. In the default, -c, and -u output styles, an
incomplete output line is followed by a diagnostic line that starts
with \. With -n, an incomplete line is output without a trailing
newline. Other output styles (-D, -e, -f) cannot represent an
incomplete line, so they pretend that there was a newline, and -e and -f
also print an error message. 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 diagnostic message may differ, e.g. for non-English locales.)
``diff -n F G'' outputs the following without a trailing newline:
d1 1
a1 1
g
``diff -e F G'' sends two diagnostics to stderr and the following to stdout:
1c
g
.
A file is considered to be text if its first characters are all in the
ISO 8859 character set; BSD's diff uses Ascii.
GNU DIFF has the following additional options:
-a Always treat files as text and compare them line-by-line,
even if they do not appear to be text.
-B ignore changes that just insert or delete blank lines.
-C #
request -c format and specify number of context lines.
-F regexp
in context format, for each unit of differences, show some of
the last preceding line that matches the specified regexp.
-H use heuristics to speed handling of large files that
have numerous scattered small changes. The algorithm becomes
asymptotically linear for such files!
-I regexp
ignore changes that just insert or delete lines that
match the specified regexp.
-L label
Use the specified label in file header lines output by the -c option.
This option may be given zero, one, or two times,
to affect neither label, just the first file's label, or both labels.
A file's default label is its name, a tab, and its modification date.
-N in directory comparison, if a file is found in only one directory,
treat it as present but empty in the other directory.
-p equivalent to -c -F'^[_a-zA-Z]'. This is useful for C code
because it shows which function each change is in.
-T print 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.
-u[#]
produce unified style output with # context lines (default 3).
This style is like -c, but it is more compact because context
lines are printed only once. Lines from just the first file
are marked '-'; lines from just the second file are marked '+'.
This version of diff3 has all of BSD diff3's features, with the following
additional features.
An input file may end in a non-newline character. With the -m option,
an incomplete last line stays incomplete. Other output styles treat
incomplete lines like diff.
The file name '-' denotes the standard input. It can appear at most once.
diff3 has the following additional options:
-a Always treat files as text and compare them line-by-line,
even if they do not appear to be text.
-i Include 'w' and 'q' commands at the end of the output, to write out
the changed file, thus emulating system V behavior. One of the edit
script options -e, -E, -x, -X, -3 must also be specified.
-m Apply the edit script to the first file and send the result to
standard output. Unlike piping diff3's output to ed(1), this works
even for binary files and incomplete lines. -E is assumed if no edit
script option is specified. This option is incompatible with -i.
-L label
Use the specified label for lines output by the -E and -X options,
one of which must also be specified. This option may be given zero,
one, or two times; the first label marks <<<<<<< lines and the second
marks >>>>>>> lines. The default labels are the names of the first and
third files on the command line. Thus ``diff3 -L X -L Z -E A B C''
acts like ``diff3 -E A B C'', except that the output looks like it
came from files named X and Z rather than from files named A and C.
Exit status 0 means success, 1 means overlaps were found and -E or -X was
specified, and 2 means trouble.
GNU DIFF was written by Mike Haertel, David Hayes, Richard Stallman
and Len Tower. The basic algorithm is described in: "An O(ND)
Difference Algorithm and its Variations", Eugene Myers, Algorithmica
Vol. 1 No. 2, 1986, p 251.
Many bugs were fixed by Paul Eggert. The unified diff idea and format
are from Wayne Davison.
Suggested projects for improving GNU DIFF:
* Handle very large files by not keeping the entire text in core.
One way to do this is to scan the files sequentally to compute hash
codes of the lines and put the lines in equivalence classes based only
on hash code. Then compare the files normally. This will produce
some false matches.
Then scan the two files sequentially again, checking each match to see
whether it is real. When a match is not real, mark both the
"matching" lines as changed. Then build an edit script as usual.
The output routines would have to be changed to scan the files
sequentially looking for the text to print.

191
eoe/cmd/diff/alloca.c Normal file
View File

@@ -0,0 +1,191 @@
/*
alloca -- (mostly) portable public-domain implementation -- D A Gwyn
last edit: 86/05/30 rms
include config.h, since on VMS it renames some symbols.
Use xmalloc instead of malloc.
This implementation of the PWB library alloca() function,
which is used to allocate space off the run-time stack so
that it is automatically reclaimed upon procedure exit,
was inspired by discussions with J. Q. Johnson of Cornell.
It should work under any C implementation that uses an
actual procedure stack (as opposed to a linked list of
frames). There are some preprocessor constants that can
be defined when compiling for your specific system, for
improved efficiency; however, the defaults should be okay.
The general concept of this implementation is to keep
track of all alloca()-allocated blocks, and reclaim any
that are found to be deeper in the stack than the current
invocation. This heuristic does not reclaim storage as
soon as it becomes invalid, but it will do so eventually.
As a special case, alloca(0) reclaims storage without
allocating any. It is a good idea to use alloca(0) in
your main control loop, etc. to force garbage collection.
*/
#ifndef lint
static char SCCSid[] = "@(#)alloca.c 1.1"; /* for the "what" utility */
#endif
#ifdef emacs
#include "config.h"
#ifdef static
/* actually, only want this if static is defined as ""
-- this is for usg, in which emacs must undefine static
in order to make unexec workable
*/
#ifndef STACK_DIRECTION
you
lose
-- must know STACK_DIRECTION at compile-time
#endif /* STACK_DIRECTION undefined */
#endif static
#endif emacs
#ifdef X3J11
typedef void *pointer; /* generic pointer type */
#else
typedef char *pointer; /* generic pointer type */
#endif
#define NULL 0 /* null pointer constant */
extern void free();
extern pointer xmalloc();
/*
Define STACK_DIRECTION if you know the direction of stack
growth for your system; otherwise it will be automatically
deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown
*/
#ifndef STACK_DIRECTION
#define STACK_DIRECTION 0 /* direction unknown */
#endif
#if STACK_DIRECTION != 0
#define STACK_DIR STACK_DIRECTION /* known at compile-time */
#else /* STACK_DIRECTION == 0; need run-time code */
static int stack_dir; /* 1 or -1 once known */
#define STACK_DIR stack_dir
static void
find_stack_direction (/* void */)
{
static char *addr = NULL; /* address of first
`dummy', once known */
auto char dummy; /* to get stack address */
if (addr == NULL)
{ /* initial entry */
addr = &dummy;
find_stack_direction (); /* recurse once */
}
else /* second entry */
if (&dummy > addr)
stack_dir = 1; /* stack grew upward */
else
stack_dir = -1; /* stack grew downward */
}
#endif /* STACK_DIRECTION == 0 */
/*
An "alloca header" is used to:
(a) chain together all alloca()ed blocks;
(b) keep track of stack depth.
It is very important that sizeof(header) agree with malloc()
alignment chunk size. The following default should work okay.
*/
#ifndef ALIGN_SIZE
#define ALIGN_SIZE sizeof(double)
#endif
typedef union hdr
{
char align[ALIGN_SIZE]; /* to force sizeof(header) */
struct
{
union hdr *next; /* for chaining headers */
char *deep; /* for stack depth measure */
} h;
} header;
/*
alloca( size ) returns a pointer to at least `size' bytes of
storage which will be automatically reclaimed upon exit from
the procedure that called alloca(). Originally, this space
was supposed to be taken from the current stack frame of the
caller, but that method cannot be made to work for some
implementations of C, for example under Gould's UTX/32.
*/
static header *last_alloca_header = NULL; /* -> last alloca header */
pointer
alloca (size) /* returns pointer to storage */
unsigned size; /* # bytes to allocate */
{
auto char probe; /* probes stack depth: */
register char *depth = &probe;
#if STACK_DIRECTION == 0
if (STACK_DIR == 0) /* unknown growth direction */
find_stack_direction ();
#endif
/* Reclaim garbage, defined as all alloca()ed storage that
was allocated from deeper in the stack than currently. */
{
register header *hp; /* traverses linked list */
for (hp = last_alloca_header; hp != NULL;)
if (STACK_DIR > 0 && hp->h.deep > depth
|| STACK_DIR < 0 && hp->h.deep < depth)
{
register header *np = hp->h.next;
free ((pointer) hp); /* collect garbage */
hp = np; /* -> next header */
}
else
break; /* rest are not deeper */
last_alloca_header = hp; /* -> last valid storage */
}
if (size == 0)
return NULL; /* no allocation required */
/* Allocate combined header + user data storage. */
{
register pointer new = xmalloc (sizeof (header) + size);
/* address of header */
((header *)new)->h.next = last_alloca_header;
((header *)new)->h.deep = depth;
last_alloca_header = (header *)new;
/* User storage begins just after header. */
return (pointer)((char *)new + sizeof(header));
}
}

1076
eoe/cmd/diff/analyze.c Normal file

File diff suppressed because it is too large Load Diff

118
eoe/cmd/diff/config.h Normal file
View File

@@ -0,0 +1,118 @@
/* config.h. Generated automatically by configure. */
/* config.hin. Generated automatically from configure.in by autoheader. */
/* Define if using alloca.c. */
/* #undef C_ALLOCA */
/* Define if the closedir function returns void instead of int. */
/* #undef CLOSEDIR_VOID */
/* Define to empty if the keyword does not work. */
/* #undef const */
/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
This function is required for alloca.c support on those systems. */
/* #undef CRAY_STACKSEG_END */
/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
#define HAVE_ALLOCA_H 1
/* Define if you don't have vprintf but do have _doprnt. */
/* #undef HAVE_DOPRNT */
/* Define if your struct stat has st_blksize. */
#define HAVE_ST_BLKSIZE 1
/* Define if you have <vfork.h>. */
/* #undef HAVE_VFORK_H */
/* Define if you have the vprintf function. */
#define HAVE_VPRINTF 1
/* Define if on MINIX. */
/* #undef _MINIX */
/* Define to `int' if <sys/types.h> doesn't define. */
/* #undef pid_t */
/* Define if the system does not provide POSIX.1 features except
with this defined. */
/* #undef _POSIX_1_SOURCE */
/* Define if you need to in order for stat and other things to work. */
/* #undef _POSIX_SOURCE */
/* Define as the return type of signal handlers (int or void). */
#define RETSIGTYPE void
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown
*/
/* #undef STACK_DIRECTION */
/* Define if the `S_IS*' macros in <sys/stat.h> do not work properly. */
/* #undef STAT_MACROS_BROKEN */
/* Define if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define if <sys/wait.h> is compatible with Posix applications. */
#define HAVE_SYS_WAIT_H 1
/* Define vfork as fork if vfork does not work. */
#define vfork fork
/* Define if you have the dup2 function. */
#define HAVE_DUP2 1
/* Define if you have the memchr function. */
#define HAVE_MEMCHR 1
/* Define if you have the sigaction function. */
#define HAVE_SIGACTION 1
/* Define if you have the strchr function. */
#define HAVE_STRCHR 1
/* Define if you have the strerror function. */
#define HAVE_STRERROR 1
/* Define if you have the tmpnam function. */
#define HAVE_TMPNAM 1
/* Define if you have the <dirent.h> header file. */
#define HAVE_DIRENT_H 1
/* Define if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
/* Define if you have the <limits.h> header file. */
#define HAVE_LIMITS_H 1
/* Define if you have the <ndir.h> header file. */
/* #undef HAVE_NDIR_H */
/* Define if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define if you have the <sys/dir.h> header file. */
/* #undef HAVE_SYS_DIR_H */
/* Define if you have the <sys/file.h> header file. */
#define HAVE_SYS_FILE_H 1
/* Define if you have the <sys/ndir.h> header file. */
/* #undef HAVE_SYS_NDIR_H */
/* Define if you have the <time.h> header file. */
#define HAVE_TIME_H 1
/* Define if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1

450
eoe/cmd/diff/context.c Normal file
View File

@@ -0,0 +1,450 @@
/* Context-format output routines for GNU DIFF.
Copyright (C) 1988, 1989 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "diff.h"
#include "regex.h"
static void pr_context_hunk ();
static void pr_unidiff_hunk ();
static struct change *find_hunk ();
static void mark_ignorable ();
static void find_function ();
/* Last place find_function started searching from. */
static int find_function_last_search;
/* The value find_function returned when it started searching there. */
static int 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 (mark, inf, label)
const char *mark;
struct file_data *inf;
const char *label;
{
if (label)
fprintf (outfile, "%s %s\n", mark, label);
else if (inf->stat.st_mtime)
fprintf (outfile, "%s %s\t%s", mark, inf->name, ctime(&inf->stat.st_mtime));
else
/* Don't pretend that standard input is ancient. */
fprintf (outfile, "%s %s\n", mark, inf->name);
}
/* Print a header for a context diff, with the file names and dates. */
void
print_context_header (inf, unidiff_flag)
struct file_data *inf;
int unidiff_flag;
{
if (unidiff_flag)
{
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 (script, unidiff_flag)
struct change *script;
int unidiff_flag;
{
if (ignore_blank_lines_flag || ignore_regexp)
mark_ignorable (script);
else
{
struct change *e;
for (e = script; e; e = e->link)
e->ignore = 0;
}
find_function_last_search = 0;
find_function_last_match = -1;
if (unidiff_flag)
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 (file, a, b)
struct file_data *file;
int a, b;
{
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, "%d,%d", trans_a, trans_b);
else
fprintf (outfile, "%d", trans_b);
}
/* 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 (hunk)
struct change *hunk;
{
int first0, last0, first1, last1, show_from, show_to, i;
struct change *next;
char *prefix;
char *function;
int function_length;
/* Determine range of line numbers involved in each file. */
analyze_hunk (hunk, &first0, &last0, &first1, &last1, &show_from, &show_to);
if (!show_from && !show_to)
return;
/* Include a context's width before and after. */
first0 = max (first0 - context, 0);
first1 = max (first1 - context, 0);
last0 = min (last0 + context, files[0].buffered_lines - 1);
last1 = min (last1 + context, files[1].buffered_lines - 1);
/* If desired, find the preceding function definition line in file 0. */
function = 0;
if (function_regexp)
find_function (&files[0], first0, &function, &function_length);
/* If we looked for and found a function this is part of,
include its name in the header of the diff section. */
fprintf (outfile, "***************");
if (function)
{
fprintf (outfile, " ");
fwrite (function, 1, min (function_length - 1, 40), outfile);
}
fprintf (outfile, "\n*** ");
print_context_number_range (&files[0], first0, last0);
fprintf (outfile, " ****\n");
if (show_from)
{
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 (outfile, "--- ");
print_context_number_range (&files[1], first1, last1);
fprintf (outfile, " ----\n");
if (show_to)
{
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 (file, a, b)
struct file_data *file;
int a, b;
{
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, trans_b == trans_a ? "%d" : "%d,0", trans_b);
else
fprintf (outfile, "%d,%d", 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 (hunk)
struct change *hunk;
{
int first0, last0, first1, last1, show_from, show_to, i, j, k;
struct change *next;
int lastline;
char *function;
int function_length;
/* Determine range of line numbers involved in each file. */
analyze_hunk (hunk, &first0, &last0, &first1, &last1, &show_from, &show_to);
if (!show_from && !show_to)
return;
/* Include a context's width before and after. */
first0 = max (first0 - context, 0);
first1 = max (first1 - context, 0);
last0 = min (last0 + context, files[0].buffered_lines - 1);
last1 = min (last1 + context, files[1].buffered_lines - 1);
/* If desired, find the preceding function definition line in file 0. */
function = 0;
if (function_regexp)
find_function (&files[0], first0, &function, &function_length);
/* If we looked for and found a function this is part of,
include its name in the header of the diff section. */
fprintf (outfile, "@@ -");
print_unidiff_number_range (&files[0], first0, last0);
fprintf (outfile, " +");
print_unidiff_number_range (&files[1], first1, last1);
fprintf (outfile, " @@");
if (function)
{
putc (' ', outfile);
fwrite (function, 1, min (function_length - 1, 40), outfile);
}
putc ('\n', outfile);
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 (' ', outfile);
print_1_line ((char *)0, &files[0].linbuf[i++]);
j++;
}
else
{
/* For each difference, first output the deleted part. */
k = next->deleted;
while (k--)
{
putc ('-', outfile);
print_1_line ((char *)0, &files[0].linbuf[i++]);
}
/* Then output the inserted part. */
k = next->inserted;
while (k--)
{
putc ('+', outfile);
print_1_line ((char *)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 at least
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 (start)
struct change *start;
{
struct change *prev;
int top0, top1;
int thresh;
do
{
/* Computer 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;
/* Threshold distance is 2*CONTEXT between two non-ignorable changes,
but only CONTEXT if one is ignorable. */
thresh = ((prev->ignore || (start && start->ignore))
? context
: 2 * context);
/* 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 (script)
struct change *script;
{
while (script)
{
struct change *next = script->link;
int first0, last0, first1, last1, deletes, inserts;
/* Turn this change into a hunk: detach it from the others. */
script->link = 0;
/* Determine whether this change is ignorable. */
analyze_hunk (script, &first0, &last0, &first1, &last1, &deletes, &inserts);
/* Reconnect the chain as before. */
script->link = next;
/* If the change is ignorable, mark it. */
script->ignore = (!deletes && !inserts);
/* Advance to the following change. */
script = next;
}
}
/* Find the last function-header line in FILE prior to line number LINENUM.
This is a line containing a match for the regexp in `function_regexp'.
Store the address of the line text into LINEP and the length of the
line into LENP.
Do not store anything if no function-header is found. */
static void
find_function (file, linenum, linep, lenp)
struct file_data *file;
int linenum;
char **linep;
int *lenp;
{
int i = linenum;
int last = find_function_last_search;
find_function_last_search = i;
while (--i >= last)
{
/* See if this line is what we want. */
if (0 <= re_search (&function_regexp_compiled,
file->linbuf[i].text,
file->linbuf[i].length,
0, file->linbuf[i].length,
0))
{
*linep = file->linbuf[i].text;
*lenp = file->linbuf[i].length;
find_function_last_match = i;
return;
}
}
/* If we search back to where we started searching the previous time,
find the line we found last time. */
if (find_function_last_match >= 0)
{
i = find_function_last_match;
*linep = file->linbuf[i].text;
*lenp = file->linbuf[i].length;
return;
}
return;
}

View File

@@ -0,0 +1,71 @@
Here is a comparison matrix which shows a case in which
it is possible for the forward and backward scan in `diag'
to meet along a nonzero length of diagonal simultaneous
(so that bdiag[d] and fdiag[d] are not equal)
even though there is no snake on that diagonal at the meeting point.
85 1 1 1 159 1 1 17
1 2 3 4
60
1 2
1
2 2 3 4
71
3 3 4 5
85
4 3 4 5
17
5 4 5
1
6 4 5 6
183
7 5 6 7
10
8 6 7
1
9 6 7 8
12
7 8 9 10
13
10 8 9 10
14
10 9 10
17
10 10
1
10 9 10
1
8 10 10 10
183
8 7 9 9 9
10
7 6 8 9 8 8
1
6 5 7 7
1
5 6 6
1
5 5 5
50
5 4 4 4
1
4 3 3
85
5 4 3 2 2
1
2 1
17
5 4 3 2 1 1
1
1 0
85 1 1 1 159 1 1 17

713
eoe/cmd/diff/diff.c Normal file
View File

@@ -0,0 +1,713 @@
/* GNU DIFF main routine.
Copyright (C) 1988, 1989 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* GNU DIFF was written by Mike Haertel, David Hayes,
Richard Stallman and Len Tower. */
#define GDIFF_MAIN
#include "regex.h"
#include "diff.h"
#include <getopt.h>
/* Nonzero for -r: if comparing two directories,
compare their common subdirectories recursively. */
int recursive;
/* For debugging: don't do discard_confusing_lines. */
int no_discards;
/* 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 (optionvec, count)
char **optionvec; /* Was `vector', but that collides on Alliant. */
int count;
{
int i;
int length = 0;
char *result;
for (i = 0; i < count; i++)
length += strlen (optionvec[i]) + 1;
result = (char *) xmalloc (length + 1);
result[0] = 0;
for (i = 0; i < count; i++)
{
strcat (result, " ");
strcat (result, optionvec[i]);
}
return result;
}
int xargc;
char **xargv;
int gnudiffopts;
int sgidiffopts;
VOID
usage ()
{
fprintf (stderr, "Usage: diff [-bcefhilnrstw -Dstring -Sname -xpattern ] file1 file2\n");
fprintf (stderr, "\tGNU diff options: [-# -aBdHNpqTuv -Cnum -Fregexp -Iregexp -Llabel]\n");
exit (2);
}
VOID
specify_style (style)
enum output_style style;
{
if (output_style != OUTPUT_NORMAL
&& output_style != style)
error ("conflicting specifications of output style");
output_style = style;
}
main (argc, argv)
int argc;
char *argv[];
{
int val;
int c;
int prev = -1;
extern char *version_string;
extern char *optarg;
extern int optind;
extern void setxpat(char *);
program = argv[0];
/* Do our initializations. */
output_style = OUTPUT_NORMAL;
always_text_flag = FALSE;
ignore_space_change_flag = FALSE;
ignore_all_space_flag = FALSE;
length_varies = FALSE;
ignore_case_flag = FALSE;
ignore_blank_lines_flag = FALSE;
ignore_regexp = 0;
function_regexp = 0;
print_file_same_flag = FALSE;
entire_new_file_flag = FALSE;
no_details_flag = FALSE;
context = -1;
line_end_char = '\n';
tab_align_flag = FALSE;
tab_expand_flag = FALSE;
recursive = FALSE;
paginate_flag = FALSE;
ifdef_string = NULL;
heuristic = FALSE;
dir_start_file = NULL;
msg_chain = NULL;
msg_chain_end = NULL;
no_discards = 0;
gnudiffopts = 0;
sgidiffopts = 0;
xargc = 0;
xargv = xmalloc ((argc+1) * sizeof(*xargv));
bzero (xargv, (argc+1) * sizeof(*xargv));
/*
* Put all but the last 2 args (the filenames to diff)
* in the xargv[] vector, to be passed to odiff by tryodiff().
*
* If "diff -r dir1 dir2" calls odiff on a big file
* somewhere, must call odiff with "diff -r file1 file2"
* not with original "dir1 dir2" args. Otherwise get
* all output repeated -- see SGI PV Incident 234771.
* Would be better to also trim -r, but that seems
* harder, and I can't see that it matters. pj.
*/
while (xargc < argc - 2) {
xargv[xargc] = argv[xargc];
xargc++;
}
xargv[xargc+2] = 0;
/* Decode the options. */
while ((c = getopt (argc, argv,
"0123456789abBcC:dD:efF:hHiI:lL:nNpqrsS:tTuvwx:"
)) != EOF)
{
switch (c)
{
/* All digits combine in decimal to specify the context-size. */
case '1': gnudiffopts++;
case '2': gnudiffopts++;
case '3': gnudiffopts++;
case '4': gnudiffopts++;
case '5': gnudiffopts++;
case '6': gnudiffopts++;
case '7': gnudiffopts++;
case '8': gnudiffopts++;
case '9': gnudiffopts++;
case '0': gnudiffopts++;
if (context == -1)
context = 0;
/* If a context length has already been specified,
more digits allowed only if they follow right after the others.
Reject two separate runs of digits, or digits after -C. */
else if (prev < '0' || prev > '9')
fatal ("context length specified twice");
context = context * 10 + c - '0';
break;
case 'a': gnudiffopts++;
/* Treat all files as text files; never treat as binary. */
always_text_flag = 1;
break;
case 'b': sgidiffopts++;
/* Ignore changes in amount of whitespace. */
ignore_space_change_flag = 1;
length_varies = 1;
break;
case 'B': gnudiffopts++;
/* Ignore changes affecting only blank lines. */
ignore_blank_lines_flag = 1;
break;
case 'C': gnudiffopts++;
if (optarg)
{
if (context >= 0)
fatal ("context length specified twice");
{
char *p;
for (p = optarg; *p; p++)
if (*p < '0' || *p > '9')
fatal ("invalid context length argument");
}
context = atoi (optarg);
}
/* Falls through. */
case 'c': sgidiffopts++;
/* Make context-style output. */
specify_style (c == 130 ? OUTPUT_UNIFIED : OUTPUT_CONTEXT);
break;
case 'd': gnudiffopts++;
/* Don't discard lines. This makes things slower (sometimes much
slower) but will find a guaranteed minimal set of changes. */
no_discards = 1;
break;
case 'D': sgidiffopts++;
/* Make merged #ifdef output. */
specify_style (OUTPUT_IFDEF);
ifdef_string = optarg;
break;
case 'e': sgidiffopts++;
/* Make output that is a valid `ed' script. */
specify_style (OUTPUT_ED);
break;
case 'f': sgidiffopts++;
/* Make output that looks vaguely like an `ed' script
but has changes in the order they appear in the file. */
specify_style (OUTPUT_FORWARD_ED);
break;
case 'F': gnudiffopts++;
/* Show, for each set of changes, the previous line that
matches the specified regexp. Currently affects only
context-style output. */
function_regexp = optarg;
break;
case 'h': sgidiffopts++;
/* Split the files into chunks of around 1500 lines
for faster processing. Usually does not change the result.
This currently has no effect. */
break;
case 'H': gnudiffopts++;
/* Turn on heuristics that speed processing of large files
with a small density of changes. */
heuristic = 1;
break;
case 'i': sgidiffopts++;
/* Ignore changes in case. */
ignore_case_flag = 1;
break;
case 'I': gnudiffopts++;
/* Ignore changes affecting only lines that match the
specified regexp. */
ignore_regexp = optarg;
break;
case 'l': sgidiffopts++;
/* Pass the output through `pr' to paginate it. */
paginate_flag = 1;
break;
case 'L': gnudiffopts++;
/* Specify file labels for `-c' output headers. */
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': sgidiffopts++;
/* Output RCS-style diffs, like `-f' except that each command
specifies the number of lines affected. */
specify_style (OUTPUT_RCS);
break;
case 'N': gnudiffopts++;
/* When comparing directories, if a file appears only in one
directory, treat it as present but empty in the other. */
entire_new_file_flag = 1;
break;
case 'p': gnudiffopts++;
/* Make context-style output and show name of last C function. */
specify_style (OUTPUT_CONTEXT);
function_regexp = "^[_a-zA-Z]";
break;
case 'q': gnudiffopts++;
no_details_flag = 1;
break;
case 'r': sgidiffopts++;
/* When comparing directories,
recursively compare any subdirectories found. */
recursive = 1;
break;
case 's': sgidiffopts++;
/* Print a message if the files are the same. */
print_file_same_flag = 1;
break;
case 'S': sgidiffopts++;
/* When comparing directories, start with the specified
file name. This is used for resuming an aborted comparison. */
dir_start_file = optarg;
break;
case 't': sgidiffopts++;
/* Expand tabs to spaces in the output so that it preserves
the alignment of the input files. */
tab_expand_flag = 1;
break;
case 'T': gnudiffopts++;
/* 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. */
tab_align_flag = 1;
break;
case 'v': gnudiffopts++;
printf ("GNU diff version %s\n", version_string);
break;
case 'u': gnudiffopts++;
/* Output the context diff in unidiff format. */
specify_style (OUTPUT_UNIFIED);
break;
case 'w': sgidiffopts++;
/* Ignore horizontal whitespace when comparing lines. */
ignore_all_space_flag = 1;
length_varies = 1;
break;
case 'x': sgidiffopts++;
setxpat(optarg);
break;
default:
usage ();
}
prev = c;
}
if (optind != argc - 2)
usage ();
if (ignore_regexp)
{
char *val;
bzero (&ignore_regexp_compiled, sizeof ignore_regexp_compiled);
val = re_compile_pattern (ignore_regexp, strlen (ignore_regexp),
&ignore_regexp_compiled);
if (val != 0)
error ("%s: %s", ignore_regexp, val);
ignore_regexp_compiled.fastmap = (char *) xmalloc (256);
}
if (function_regexp)
{
char *val;
bzero (&function_regexp_compiled, sizeof function_regexp_compiled);
val = re_compile_pattern (function_regexp, strlen (function_regexp),
&function_regexp_compiled);
if (val != 0)
error ("%s: %s", function_regexp, val);
function_regexp_compiled.fastmap = (char *) xmalloc (256);
}
if (output_style != OUTPUT_CONTEXT && output_style != OUTPUT_UNIFIED)
context = 0;
else if (context == -1)
/* Default amount of context for -c. */
context = 3;
switch_string = option_list (argv + 1, optind - 1);
val = compare_files (0, argv[optind], 0, argv[optind + 1], 0);
/* Print any messages that were saved up for last. */
print_message_queue ();
if (ferror (stdout) || fclose (stdout) != 0)
fatal ("write error");
exit (val);
}
static char *
type( mode_t mode )
{
if(S_ISFIFO(mode))
return("fifo");
else if(S_ISCHR(mode))
return("character special");
else if(S_ISBLK(mode))
return("block special");
else if(S_ISREG(mode))
return("regular");
else if(S_ISLNK(mode))
return("symbolic link");
else if(S_ISSOCK(mode))
return("socket");
else
return("unknown");
}
/* Compare two files (or dirs) with specified names
DIR0/NAME0 and DIR1/NAME1, at level DEPTH in directory recursion.
(if DIR0 is 0, then the name is just NAME0, etc.)
This is self-contained; it opens the files and closes them.
Value is 0 if files are identical, 1 if different,
2 if there is a problem opening them. */
int
compare_files (dir0, name0, dir1, name1, depth)
char *dir0, *dir1;
char *name0, *name1;
int depth;
{
static char Standard_Input[] = "Standard Input";
struct file_data inf[2];
register int i;
int val;
int errorcount = 0; /* Bit 1 for stat or open errors */
/* Bit 2 for fifo, block and character special */
int stat_result[2];
/* 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 (! entire_new_file_flag && (name0 == 0 || name1 == 0))
{
char *name = name0 == 0 ? name1 : name0;
char *dir = name0 == 0 ? dir1 : dir0;
message ("Only in %s: %s\n", dir, name);
/* Return 1 so that diff_dirs will return 1 ("some files differ"). */
return 1;
}
/* Mark any nonexistent file with -1 in the desc field. */
/* Mark unopened files (i.e. directories) with -2. */
inf[0].desc = name0 == 0 ? -1 : -2;
inf[1].desc = name1 == 0 ? -1 : -2;
/* Now record the full name of each file, including nonexistent ones. */
if (name0 == 0)
name0 = name1;
if (name1 == 0)
name1 = name0;
inf[0].name = dir0 == 0 ? name0 : concat (dir0, "/", name0);
inf[1].name = dir1 == 0 ? name1 : concat (dir1, "/", name1);
/* Stat the files. Record whether they are directories.
Record in stat_result whether stat fails. */
for (i = 0; i <= 1; i++)
{
bzero (&inf[i].stat, sizeof(struct stat));
inf[i].dir_p = 0;
stat_result[i] = 0;
if (inf[i].desc != -1)
{
char *filename = inf[i].name;
stat_result[i] =
strcmp (filename, "-")
? stat (filename, &inf[i].stat)
: fstat (0, &inf[i].stat);
if (stat_result[i] < 0)
{
perror_with_name (filename);
errorcount |= 1;
}
else
inf[i].dir_p =
S_IFDIR == (inf[i].stat.st_mode & S_IFMT)
&& strcmp (filename, "-");
}
}
/* See if the two named files are actually the same physical file.
If so, we know they are identical without actually reading them. */
if (output_style != OUTPUT_IFDEF
&& inf[0].stat.st_ino == inf[1].stat.st_ino
&& inf[0].stat.st_dev == inf[1].stat.st_dev
&& stat_result[0] == 0
&& stat_result[1] == 0)
{
val = 0;
goto done;
}
if (name0 == 0)
inf[0].dir_p = inf[1].dir_p;
if (name1 == 0)
inf[1].dir_p = inf[0].dir_p;
/* Open the files and record their descriptors. */
for (i = 0; i <= 1; i++)
{
if (inf[i].desc == -1)
;
else if (!strcmp (inf[i].name, "-"))
{
inf[i].desc = 0;
inf[i].name = Standard_Input;
}
/* Don't bother opening if stat already failed. */
else if (stat_result[i] == 0 && ! inf[i].dir_p)
{
char *filename = inf[i].name;
/* If both are directories */
#ifdef sgi
if(dir0 != 0 && dir1 != 0)
#else
if(strchr(inf[0].name,'/') && strchr(inf[1].name,'/'))
#endif
{
/* Check for a fifo, block or character special */
if(inf[i].stat.st_mode & (S_IFIFO|S_IFCHR|S_IFBLK))
errorcount |= 2;
}
if(!(errorcount&2))
{
inf[i].desc = open (filename, O_RDONLY, 0);
if (0 > inf[i].desc)
{
perror_with_name (filename);
errorcount |= 1;
}
}
}
}
if (errorcount)
{
if(errorcount & 2)
{
fprintf(stdout,"File %s is a %s while file %s is a %s\n",
inf[0].name,type(inf[0].stat.st_mode),
inf[1].name,type(inf[1].stat.st_mode));
}
/* If either file should exist but fails to be opened, return 2.
if it was just a file type mismatch, return 1 */
val = (errorcount & 1) ? 2 : 1;
}
else if (inf[0].dir_p && inf[1].dir_p)
{
if (output_style == OUTPUT_IFDEF)
fatal ("-D option not supported with directories");
/* If both are directories, compare the files in them. */
if (depth > 0 && !recursive)
{
/* But don't compare dir contents one level down
unless -r was specified. */
message ("Common subdirectories: %s and %s\n",
inf[0].name, inf[1].name);
val = 0;
}
else
{
val = diff_dirs (inf[0].name, inf[1].name,
compare_files, depth, 0, 0);
}
}
else if (depth == 0 && (inf[0].dir_p || inf[1].dir_p))
{
/* If only one is a directory, and it was specified in the command line,
use the file in that dir whose basename matches the other file. */
int dir_arg = (inf[0].dir_p ? 0 : 1);
int fnm_arg = (inf[0].dir_p ? 1 : 0);
char *p = rindex (inf[fnm_arg].name, '/');
char *filename = concat (inf[dir_arg].name, "/",
(p ? p+1 : inf[fnm_arg].name));
if (inf[fnm_arg].name == Standard_Input)
fatal ("can't compare - to a directory");
inf[dir_arg].desc = open (filename, O_RDONLY, 0);
if (0 > inf[dir_arg].desc)
{
perror_with_name (filename);
val = 2;
}
else
{
/* JF: patch from the net to check and make sure we can really free
this. If it's from argv[], freeing it is a *really* bad idea */
if (0 != (dir_arg ? dir1 : dir0))
free (inf[dir_arg].name);
inf[dir_arg].name = filename;
if (fstat (inf[dir_arg].desc, &inf[dir_arg].stat) < 0)
pfatal_with_name (inf[dir_arg].name);
inf[dir_arg].dir_p
= (S_IFDIR == (inf[dir_arg].stat.st_mode & S_IFMT));
if (inf[dir_arg].dir_p)
{
error ("%s is a directory but %s is not",
inf[dir_arg].name, inf[fnm_arg].name);
val = 1;
}
else
val = diff_2_files (inf, depth);
}
}
else if (depth > 0 && (inf[0].dir_p || inf[1].dir_p))
{
/* Perhaps we have a subdirectory that exists only in one directory.
If so, just print a message to that effect. */
if (inf[0].desc == -1 || inf[1].desc == -1)
{
if (entire_new_file_flag && recursive)
val = diff_dirs (inf[0].name, inf[1].name, compare_files, depth,
inf[0].desc == -1, inf[1].desc == -1);
else
{
char *dir = (inf[0].desc == -1) ? dir1 : dir0;
message ("Only in %s: %s\n", dir, name0);
val = 1;
}
}
else
{
/* We have a subdirectory in one directory
and a file in the other. */
if (inf[0].dir_p)
message ("%s is a directory but %s is not\n",
inf[0].name, inf[1].name);
else
message ("%s is a directory but %s is not\n",
inf[1].name, inf[0].name);
/* This is a difference. */
val = 1;
}
}
else
{
/* Both exist and both are ordinary files. */
val = diff_2_files (inf, depth);
}
/* Now the comparison has been done, if no error prevented it,
and VAL is the value this function will return. */
if (inf[0].desc >= 0)
close (inf[0].desc);
if (inf[1].desc >= 0)
close (inf[1].desc);
done:
if (val == 0 && !inf[0].dir_p)
{
if (print_file_same_flag)
message ("Files %s and %s are identical\n",
inf[0].name, inf[1].name);
}
else
fflush (stdout);
if (dir0 != 0)
free (inf[0].name);
if (dir1 != 0)
free (inf[1].name);
return val;
}

381
eoe/cmd/diff/diff.h Normal file
View File

@@ -0,0 +1,381 @@
/* Shared definitions for GNU DIFF
Copyright (C) 1988, 1989 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <ctype.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#if defined(USG) || defined(sgi)
#include <time.h>
#ifdef HAVE_NDIR
#ifdef NDIR_IN_SYS
#include <sys/ndir.h>
#else
#include <ndir.h>
#endif /* not NDIR_IN_SYS */
#else
#include <dirent.h>
#endif /* not HAVE_NDIR */
#include <fcntl.h>
#ifndef HAVE_DIRECT
#ifdef sgi
#define direct dirent64
#define readdir readdir64
#else
#define direct dirent
#endif
#endif
#ifdef sgi
#define stat stat64
#define fstat fstat64
#endif
#else /* not USG */
#include <sys/time.h>
#include <sys/dir.h>
#include <sys/file.h>
#endif
#ifdef USG
/* Define needed BSD functions in terms of sysV library. */
#define bcopy(s,d,n) memcpy((d),(s),(n))
#define bcmp(s1,s2,n) memcmp((s1),(s2),(n))
#define bzero(s,n) memset((s),0,(n))
#ifndef XENIX
#define dup2(f,t) (close(t),fcntl((f),F_DUPFD,(t)))
#endif
#define vfork fork
#define index strchr
#define rindex strrchr
#endif
#ifdef sparc
/* vfork clobbers registers on the Sparc, so don't use it. */
#define vfork fork
#endif
#include <errno.h>
extern int errno;
extern int sys_nerr;
extern char *sys_errlist[];
#define EOS (0)
#define FALSE (0)
#define TRUE 1
#define min(a,b) ((a) <= (b) ? (a) : (b))
#define max(a,b) ((a) >= (b) ? (a) : (b))
#ifndef PR_FILE_NAME
#define PR_FILE_NAME "/bin/pr"
#endif
/* Support old-fashioned C compilers. */
#if defined (__STDC__) || defined (__GNUC__)
#include "limits.h"
#else
#define INT_MAX 2147483647
#define CHAR_BIT 8
#endif
/* Support old-fashioned C compilers. */
#if !defined (__STDC__) && !defined (__GNUC__) && !defined(_MODERN_C)
#define const
#endif
#ifndef O_RDONLY
#define O_RDONLY 0
#endif
/* Variables for command line options */
#ifndef GDIFF_MAIN
#define EXTERN extern
#else
#define EXTERN
#endif
enum output_style {
/* 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 };
/* 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_CONTEXT || (S) == OUTPUT_UNIFIED || (S) == OUTPUT_RCS \
|| (S) == OUTPUT_NORMAL)
EXTERN enum output_style output_style;
/* Number of lines of context to show in each set of diffs.
This is zero when context is not to be shown. */
EXTERN int context;
/* Consider all files as text files (-a).
Don't interpret codes over 0177 as implying a "binary file". */
EXTERN int always_text_flag;
/* Ignore changes in horizontal whitespace (-b). */
EXTERN int ignore_space_change_flag;
/* Ignore all horizontal whitespace (-w). */
EXTERN int ignore_all_space_flag;
/* Ignore changes that affect only blank lines (-B). */
EXTERN int ignore_blank_lines_flag;
/* Ignore changes that affect only lines matching this regexp (-I). */
EXTERN char *ignore_regexp;
/* Result of regex-compilation of `ignore_regexp'. */
EXTERN struct re_pattern_buffer ignore_regexp_compiled;
/* 1 if lines may match even if their lengths are different.
This depends on various options. */
EXTERN int length_varies;
/* Ignore differences in case of letters (-i). */
EXTERN int ignore_case_flag;
/* File labels for `-c' output headers (-L). */
EXTERN char *file_label[2];
/* Regexp to identify function-header lines (-F). */
EXTERN char *function_regexp;
/* Result of regex-compilation of `function_regexp'. */
EXTERN struct re_pattern_buffer function_regexp_compiled;
/* Say only whether files differ, not how (-q). */
EXTERN int no_details_flag;
/* Report files compared that match (-s).
Normally nothing is output when that happens. */
EXTERN int print_file_same_flag;
/* character that ends a line. Currently this is always `\n'. */
EXTERN char line_end_char;
/* Output the differences with exactly 8 columns added to each line
so that any tabs in the text line up properly (-T). */
EXTERN int tab_align_flag;
/* Expand tabs in the output so the text lines up properly
despite the characters added to the front of each line (-t). */
EXTERN int tab_expand_flag;
/* In directory comparison, specify file to start with (-S).
All file names less than this name are ignored. */
EXTERN char *dir_start_file;
/* If a file is new (appears in only one dir)
include its entire contents (-N).
Then `patch' would create the file with appropriate contents. */
EXTERN int entire_new_file_flag;
/* Pipe each file's output through pr (-l). */
EXTERN int paginate_flag;
/* String to use for #ifdef (-D). */
EXTERN char * ifdef_string;
/* 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. */
EXTERN char * switch_string;
/* Nonzero means use heuristics for better speed. */
EXTERN int heuristic;
/* Name of program the user invoked (for error messages). */
EXTERN char * program;
/* 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 */
int inserted; /* # lines of file 1 changed here. */
int deleted; /* # lines of file 0 changed here. */
int line0; /* Line number of 1st deleted line. */
int line1; /* Line number of 1st inserted line. */
char ignore; /* Flag used in context.c */
};
/* Structures that describe the input files. */
/* Data on one line of text. */
struct line_def {
char *text;
int length;
unsigned hash;
};
/* Data on one input file being compared. */
struct file_data {
int desc; /* File descriptor */
char *name; /* File name */
struct stat stat; /* File status from fstat() */
int dir_p; /* 1 if file is a directory */
/* Buffer in which text of file is read. */
char * buffer;
/* Allocated size of buffer. */
int bufsize;
/* Number of valid characters now in the buffer. */
int buffered_chars;
/* Array of data on analyzed lines of this chunk of this file. */
struct line_def *linbuf;
/* Allocated size of linbuf array (# of elements). */
int linbufsize;
/* Number of elements of linbuf containing valid data. */
int buffered_lines;
/* Pointer to end of prefix of this file to ignore when hashing. */
char *prefix_end;
/* Count of lines in the prefix. */
int prefix_lines;
/* Pointer to start of suffix of this file to ignore when hashing. */
char *suffix_begin;
/* Count of lines in the suffix. */
int suffix_lines;
/* 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. */
int *equivs;
/* Vector, like the previous one except that
the elements for discarded lines have been squeezed out. */
int *undiscarded;
/* Vector mapping virtual line numbers (not counting discarded lines)
to real ones (counting those lines). Both are origin-0. */
int *realindexes;
/* Total number of nondiscarded lines. */
int 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_flag;
/* 1 if file ends in a line with no final newline. */
int missing_newline;
/* 1 more than the maximum equivalence value used for this or its
sibling file. */
int equiv_max;
/* Table translating diff's internal line numbers
to actual line numbers in the file.
This is needed only when some lines have been discarded.
The allocated size is always linbufsize
and the number of valid elements is buffered_lines. */
int *ltran;
/* 1 if buffer was mmapped - need to munmap instead of free */
int buffer_was_mmapped;
};
/* Describe the two files currently being compared. */
EXTERN struct file_data files[2];
/* 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 *format;
char *arg1;
char *arg2;
};
/* Head of the chain of queues messages. */
EXTERN struct msg *msg_chain;
/* Tail of the chain of queues messages. */
EXTERN struct msg *msg_chain_end;
/* Stdio stream to output diffs to. */
EXTERN FILE *outfile;
/* Declare various functions. */
#ifdef __STDC__
#define VOID void
#else
#define VOID char
#endif
VOID *xmalloc ();
VOID *xrealloc ();
char *concat ();
void free ();
char *rindex ();
char *index ();
void analyze_hunk ();
void error ();
void fatal ();
void message ();
void perror_with_name ();
void pfatal_with_name ();
void print_1_line ();
void print_message_queue ();
void print_number_range ();
void print_script ();
void translate_range ();

1784
eoe/cmd/diff/diff3.c Normal file

File diff suppressed because it is too large Load Diff

265
eoe/cmd/diff/dir.c Normal file
View File

@@ -0,0 +1,265 @@
/* Read, sort and compare two directories. Used for GNU DIFF.
Copyright (C) 1988, 1989 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "regex.h"
#include "diff.h"
static struct re_pattern_buffer **revec = NULL;
static struct re_pattern_buffer **revec_end;
/* add a directory name to the list to exclude
*/
void
setxpat(char *pat)
{
char *val;
int old_re_syntax = re_set_syntax (RE_SYNTAX_EGREP);
if (revec == NULL)
revec_end = revec = (struct re_pattern_buffer **) xmalloc (sizeof *revec);
else
{
int oldsz = revec_end - revec;
revec = (struct re_pattern_buffer **) xrealloc (revec, (oldsz+1) * (sizeof *revec));
revec_end = revec + oldsz;
}
*revec_end = (struct re_pattern_buffer *) xmalloc (sizeof (struct re_pattern_buffer));
bzero (*revec_end, sizeof (struct re_pattern_buffer));
if ((val = re_compile_pattern (pat, strlen(pat), *revec_end)) != NULL)
{
error ("%s: %s", pat, val);
fatal ("use egrep(1) style patterns");
/* NOTREACHED */
}
(*revec_end)->fastmap = (char *) xmalloc (256);
revec_end++;
re_set_syntax (old_re_syntax);
}
static int compare_names ();
/* Read the directory named DIRNAME and return a sorted vector
of filenames for its contents. NONEX nonzero means this directory is
known to be nonexistent, so return zero files. */
struct dirdata
{
int length; /* # elements in `files' */
char **files; /* Sorted names of files in the dir */
};
static struct dirdata
dir_sort (dirname, nonex)
char *dirname;
int nonex;
{
register DIR *reading;
register struct direct *next;
struct dirdata dirdata;
/* Address of block containing the files that are described. */
char **files;
/* Length of block that `files' points to, measured in files. */
int nfiles;
/* Index of first unused in `files'. */
int files_index;
if (nonex)
{
dirdata.length = 0;
dirdata.files = 0;
return dirdata;
}
/* Open the directory and check for errors. */
reading = opendir (dirname);
if (!reading)
{
perror_with_name (dirname);
dirdata.length = -1;
return dirdata;
}
/* Initialize the table of filenames. */
nfiles = 100;
files = (char **) xmalloc (nfiles * sizeof (char *));
files_index = 0;
/* Read the directory entries, and insert the subfiles
into the `files' table. */
while (next = readdir (reading))
{
if (revec)
{
struct re_pattern_buffer **rep;
int old_re_syntax = re_set_syntax (RE_SYNTAX_EGREP);
char *s = next->d_name;
int len = strlen (s);
for (rep = revec; rep < revec_end; rep++)
if (re_search (*rep, s, len, 0, len, 0) >= 0)
break;
re_set_syntax (old_re_syntax);
if (rep != revec_end)
continue;
}
/* Ignore the files `.' and `..' */
if (next->d_name[0] == '.'
&& (next->d_name[1] == 0
|| (next->d_name[1] == '.'
&& next->d_name[2] == 0)))
continue;
if (files_index == nfiles)
{
nfiles *= 2;
files
= (char **) xrealloc (files, sizeof (char *) * nfiles);
}
files[files_index++] = concat (next->d_name, "", "");
}
closedir (reading);
/* Sort the table. */
qsort (files, files_index, sizeof (char *), compare_names);
/* Return a description of location and length of the table. */
dirdata.files = files;
dirdata.length = files_index;
return dirdata;
}
/* Sort the files now in the table. */
static int
compare_names (file1, file2)
char **file1, **file2;
{
return strcmp (*file1, *file2);
}
/* Compare the contents of two directories named NAME1 and NAME2.
This is a top-level routine; it does everything necessary for diff
on two directories.
NONEX1 nonzero says directory NAME1 doesn't exist, but pretend it is
empty. Likewise NONEX2.
HANDLE_FILE is a caller-provided subroutine called to handle each file.
It gets five operands: dir and name (rel to original working dir) of file
in dir 1, dir and name pathname of file in dir 2, and the recursion depth.
For a file that appears in only one of the dirs, one of the name-args
to HANDLE_FILE is zero.
DEPTH is the current depth in recursion.
Returns the maximum of all the values returned by HANDLE_FILE,
or 2 if trouble is encountered in opening files. */
int
diff_dirs (name1, name2, handle_file, depth, nonex1, nonex2)
char *name1, *name2;
int (*handle_file) ();
int nonex1, nonex2;
{
struct dirdata data1, data2;
register int i1, i2;
int val = 0;
int v1;
/* Get sorted contents of both dirs. */
data1 = dir_sort (name1, nonex1);
data2 = dir_sort (name2, nonex2);
if (data1.length == -1 || data2.length == -1)
{
if (data1.length >= 0)
free (data1.files);
if (data2.length >= 0)
free (data2.files);
return 2;
}
i1 = 0;
i2 = 0;
/* If -Sname was specified, and this is the topmost level of comparison,
ignore all file names less than the specified starting name. */
if (dir_start_file && depth == 0)
{
while (i1 < data1.length && strcmp (data1.files[i1], dir_start_file) < 0)
i1++;
while (i2 < data2.length && strcmp (data2.files[i2], dir_start_file) < 0)
i2++;
}
/* Loop while files remain in one or both dirs. */
while (i1 < data1.length || i2 < data2.length)
{
int nameorder;
/* Compare next name in dir 1 with next name in dir 2.
At the end of a dir,
pretend the "next name" in that dir is very large. */
if (i1 == data1.length)
nameorder = 1;
else if (i2 == data2.length)
nameorder = -1;
else
nameorder = strcmp (data1.files[i1], data2.files[i2]);
if (nameorder == 0)
{
/* We have found a file (or subdir) in common between both dirs.
Compare the two files. */
v1 = (*handle_file) (name1, data1.files[i1], name2, data2.files[i2],
depth + 1);
i1++, i2++;
}
if (nameorder < 0)
{
/* Next filename in dir 1 is less; that is a file in dir 1 only. */
v1 = (*handle_file) (name1, data1.files[i1], name2, 0, depth + 1);
i1++;
}
if (nameorder > 0)
{
/* Next filename in dir 2 is less; that is a file in dir 2 only. */
v1 = (*handle_file) (name1, 0, name2, data2.files[i2], depth + 1);
i2++;
}
if (v1 > val)
val = v1;
}
if (data1.files)
free (data1.files);
if (data2.files)
free (data2.files);
return val;
}

197
eoe/cmd/diff/ed.c Normal file
View File

@@ -0,0 +1,197 @@
/* Output routines for ed-script format.
Copyright (C) 1988, 1989 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "diff.h"
static void print_rcs_hunk ();
static void print_ed_hunk ();
static void pr_forward_ed_hunk ();
void translate_range ();
struct change *find_change ();
struct change *find_reverse_change ();
/* Print our script as ed commands. */
void
print_ed_script (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 (hunk)
struct change *hunk;
{
int f0, l0, f1, l1;
int deletes, inserts;
#if 0
hunk = flip_script (hunk);
#endif
#ifdef DEBUG
debug_script (hunk);
#endif
/* Determine range of line numbers involved in each file. */
analyze_hunk (hunk, &f0, &l0, &f1, &l1, &deletes, &inserts);
if (!deletes && !inserts)
return;
/* Print out the line number header for this hunk */
print_number_range (',', &files[0], f0, l0);
fprintf (outfile, "%c\n", change_letter (inserts, deletes));
/* Print new/changed lines from second file, if needed */
if (inserts)
{
int i;
int inserting = 1;
for (i = f1; i <= l1; i++)
{
/* Resume the insert, if we stopped. */
if (! inserting)
fprintf (outfile, "%da\n",
i - f1 + translate_line_number (&files[0], f0) - 1);
inserting = 1;
/* If the file's line is just a dot, it would confuse `ed'.
So output it with a double dot, and set the flag LEADING_DOT
so that we will output another ed-command later
to change the double dot into a single dot. */
if (files[1].linbuf[i].text[0] == '.'
&& files[1].linbuf[i].text[1] == '\n')
{
fprintf (outfile, "..\n");
fprintf (outfile, ".\n");
/* Now change that double dot to the desired single dot. */
fprintf (outfile, "%ds/^\\.\\././\n",
i - f1 + translate_line_number (&files[0], f0));
inserting = 0;
}
else
/* Line is not `.', so output it unmodified. */
print_1_line ("", &files[1].linbuf[i]);
}
/* End insert mode, if we are still in it. */
if (inserting)
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 (script)
struct change *script;
{
print_script (script, find_change, pr_forward_ed_hunk);
}
static void
pr_forward_ed_hunk (hunk)
struct change *hunk;
{
int i;
int f0, l0, f1, l1;
int deletes, inserts;
/* Determine range of line numbers involved in each file. */
analyze_hunk (hunk, &f0, &l0, &f1, &l1, &deletes, &inserts);
if (!deletes && !inserts)
return;
fprintf (outfile, "%c", change_letter (inserts, deletes));
print_number_range (' ', files, f0, l0);
fprintf (outfile, "\n");
/* If deletion only, print just the number range. */
if (!inserts)
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 (script)
struct change *script;
{
print_script (script, find_change, print_rcs_hunk);
}
/* Print a hunk of an RCS diff */
static void
print_rcs_hunk (hunk)
struct change *hunk;
{
int i;
int f0, l0, f1, l1;
int deletes, inserts;
int tf0, tl0, tf1, tl1;
/* Determine range of line numbers involved in each file. */
analyze_hunk (hunk, &f0, &l0, &f1, &l1, &deletes, &inserts);
if (!deletes && !inserts)
return;
translate_range (&files[0], f0, l0, &tf0, &tl0);
if (deletes)
{
fprintf (outfile, "d");
/* For deletion, print just the starting line number from file 0
and the number of lines deleted. */
fprintf (outfile, "%d %d\n",
tf0,
(tl0 >= tf0 ? tl0 - tf0 + 1 : 1));
}
if (inserts)
{
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, "%d %d\n",
tl0,
(tl1 >= tf1 ? tl1 - tf1 + 1 : 1));
/* Print the inserted lines. */
for (i = f1; i <= l1; i++)
print_1_line ("", &files[1].linbuf[i]);
}
}

595
eoe/cmd/diff/getopt.c Normal file
View File

@@ -0,0 +1,595 @@
/* Getopt for GNU.
Copyright (C) 1987, 1989, 1990 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 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef __STDC__
#define CONST const
#else
#define CONST
#endif
/* This version of `getopt' appears to the caller like standard Unix `getopt'
but it behaves differently for the user, since it allows the user
to intersperse the options with the other arguments.
As `getopt' works, it permutes the elements of `argv' so that,
when it is done, all the options precede everything else. Thus
all application programs are extended to handle flexible argument order.
Setting the environment variable _POSIX_OPTION_ORDER disables permutation.
Then the behavior is completely standard.
GNU application programs can use a third alternative mode in which
they can distinguish the relative order of options and other arguments. */
#include <stdio.h>
/* If compiled with GNU C, use the built-in alloca */
#ifdef __GNUC__
#define alloca __builtin_alloca
#else /* not __GNUC__ */
#ifdef sparc
#include <alloca.h>
#else
char *alloca ();
#endif
#endif /* not __GNUC__ */
#if defined(STDC_HEADERS) || defined(__GNU_LIBRARY__)
#include <stdlib.h>
#include <string.h>
#define bcopy(s, d, n) memcpy ((d), (s), (n))
#define index strchr
#else
#ifdef USG
#include <string.h>
#define bcopy(s, d, n) memcpy ((d), (s), (n))
#define index strchr
#else
#ifdef VMS
#include <string.h>
#else
#include <strings.h>
#endif
void bcopy ();
#endif
char *getenv ();
char *malloc ();
#endif
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
char *optarg = 0;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns EOF, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
int optind = 0;
/* The next char to be scanned in the option-element
in which the last option character we returned was found.
This allows us to pick up the scan where we left off.
If this is zero, or a null string, it means resume the scan
by advancing to the next ARGV-element. */
static char *nextchar;
/* Callers store zero here to inhibit the error message
for unrecognized options. */
int opterr = 1;
/* Describe how to deal with options that follow non-option ARGV-elements.
If the caller did not specify anything,
the default is REQUIRE_ORDER if the environment variable
_POSIX_OPTION_ORDER is defined, PERMUTE otherwise.
REQUIRE_ORDER means don't recognize them as options;
stop option processing when the first non-option is seen.
This is what Unix does.
This mode of operation is selected by either setting the environment
variable _POSIX_OPTION_ORDER, or using `+' as the first character
of the list of option characters.
PERMUTE is the default. We permute the contents of ARGV as we scan,
so that eventually all the non-options are at the end. This allows options
to be given in any order, even with programs that were not written to
expect this.
RETURN_IN_ORDER is an option available to programs that were written
to expect options and other ARGV-elements in any order and that care about
the ordering of the two. We describe each non-option ARGV-element
as if it were the argument of an option with character code 1.
Using `-' as the first character of the list of option characters
selects this mode of operation.
The special argument `--' forces an end of option-scanning regardless
of the value of `ordering'. In the case of RETURN_IN_ORDER, only
`--' can cause `getopt' to return EOF with `optind' != ARGC. */
static enum
{
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
} ordering;
/* Describe the long-named options requested by the application.
_GETOPT_LONG_OPTIONS is a vector of `struct option' terminated by an
element containing a name which is zero.
The field `has_arg' is 1 if the option takes an argument,
2 if it takes an optional argument. */
struct option
{
char *name;
int has_arg;
int *flag;
int val;
};
CONST struct option *_getopt_long_options;
int _getopt_long_only = 0;
/* Index in _GETOPT_LONG_OPTIONS of the long-named option actually found.
Only valid when a long-named option was found. */
int option_index;
/* Handle permutation of arguments. */
/* Describe the part of ARGV that contains non-options that have
been skipped. `first_nonopt' is the index in ARGV of the first of them;
`last_nonopt' is the index after the last of them. */
static int first_nonopt;
static int last_nonopt;
/* Exchange two adjacent subsequences of ARGV.
One subsequence is elements [first_nonopt,last_nonopt)
which contains all the non-options that have been skipped so far.
The other is elements [last_nonopt,optind), which contains all
the options processed since those non-options were skipped.
`first_nonopt' and `last_nonopt' are relocated so that they describe
the new indices of the non-options in ARGV after they are moved. */
static void
exchange (argv)
char **argv;
{
int nonopts_size = (last_nonopt - first_nonopt) * sizeof (char *);
char **temp = (char **) alloca (nonopts_size);
/* Interchange the two blocks of data in ARGV. */
bcopy (&argv[first_nonopt], temp, nonopts_size);
bcopy (&argv[last_nonopt], &argv[first_nonopt],
(optind - last_nonopt) * sizeof (char *));
bcopy (temp, &argv[first_nonopt + optind - last_nonopt], nonopts_size);
/* Update records for the slots the non-options now occupy. */
first_nonopt += (optind - last_nonopt);
last_nonopt = optind;
}
/* Scan elements of ARGV (whose length is ARGC) for option characters
given in OPTSTRING.
If an element of ARGV starts with '-', and is not exactly "-" or "--",
then it is an option element. The characters of this element
(aside from the initial '-') are option characters. If `getopt'
is called repeatedly, it returns successively each of the option characters
from each of the option elements.
If `getopt' finds another option character, it returns that character,
updating `optind' and `nextchar' so that the next call to `getopt' can
resume the scan with the following option character or ARGV-element.
If there are no more option characters, `getopt' returns `EOF'.
Then `optind' is the index in ARGV of the first ARGV-element
that is not an option. (The ARGV-elements have been permuted
so that those that are not options now come last.)
OPTSTRING is a string containing the legitimate option characters.
If an option character is seen that is not listed in OPTSTRING,
return '?' after printing an error message. If you set `opterr' to
zero, the error message is suppressed but we still return '?'.
If a char in OPTSTRING is followed by a colon, that means it wants an arg,
so the following text in the same ARGV-element, or the text of the following
ARGV-element, is returned in `optarg'. Two colons mean an option that
wants an optional arg; if there is text in the current ARGV-element,
it is returned in `optarg', otherwise `optarg' is set to zero.
If OPTSTRING starts with `-' or `+', it requests different methods of
handling the non-option ARGV-elements.
See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
Long-named options begin with `+' instead of `-'.
Their names may be abbreviated as long as the abbreviation is unique
or is an exact match for some defined option. If they have an
argument, it follows the option name in the same ARGV-element, separated
from the option name by a `=', or else the in next ARGV-element.
When `getopt' finds a long-named option, it returns 0 if that option's
`flag' field is nonzero, the value of the option's `val' field
otherwise. */
int
getopt (argc, argv, optstring)
int argc;
char **argv;
CONST char *optstring;
{
optarg = 0;
/* Initialize the internal data when the first call is made.
Start processing options with ARGV-element 1 (since ARGV-element 0
is the program name); the sequence of previously skipped
non-option ARGV-elements is empty. */
if (optind == 0)
{
first_nonopt = last_nonopt = optind = 1;
nextchar = 0;
/* Determine how to handle the ordering of options and nonoptions. */
if (optstring[0] == '-')
{
ordering = RETURN_IN_ORDER;
++optstring;
}
else if (optstring[0] == '+')
{
ordering = REQUIRE_ORDER;
++optstring;
}
else if (getenv ("_POSIX_OPTION_ORDER") != 0)
ordering = REQUIRE_ORDER;
else
ordering = PERMUTE;
}
if (nextchar == 0 || *nextchar == 0)
{
if (ordering == PERMUTE)
{
/* If we have just processed some options following some non-options,
exchange them so that the options come first. */
if (first_nonopt != last_nonopt && last_nonopt != optind)
exchange (argv);
else if (last_nonopt != optind)
first_nonopt = optind;
/* Now skip any additional non-options
and extend the range of non-options previously skipped. */
while (optind < argc
&& (argv[optind][0] != '-'
|| argv[optind][1] == 0)
&& (_getopt_long_options == 0
|| argv[optind][0] != '+'
|| argv[optind][1] == 0))
optind++;
last_nonopt = optind;
}
/* Special ARGV-element `--' means premature end of options.
Skip it like a null option,
then exchange with previous non-options as if it were an option,
then skip everything else like a non-option. */
if (optind != argc && !strcmp (argv[optind], "--"))
{
optind++;
if (first_nonopt != last_nonopt && last_nonopt != optind)
exchange (argv);
else if (first_nonopt == last_nonopt)
first_nonopt = optind;
last_nonopt = argc;
optind = argc;
}
/* If we have done all the ARGV-elements, stop the scan
and back over any non-options that we skipped and permuted. */
if (optind == argc)
{
/* Set the next-arg-index to point at the non-options
that we previously skipped, so the caller will digest them. */
if (first_nonopt != last_nonopt)
optind = first_nonopt;
return EOF;
}
/* If we have come to a non-option and did not permute it,
either stop the scan or describe it to the caller and pass it by. */
if ((argv[optind][0] != '-' || argv[optind][1] == 0)
&& (_getopt_long_options == 0
|| argv[optind][0] != '+' || argv[optind][1] == 0))
{
if (ordering == REQUIRE_ORDER)
return EOF;
optarg = argv[optind++];
return 1;
}
/* We have found another option-ARGV-element.
Start decoding its characters. */
nextchar = argv[optind] + 1;
}
if (_getopt_long_options != 0
&& (argv[optind][0] == '+'
|| (_getopt_long_only && argv[optind][0] == '-'))
)
{
CONST struct option *p;
char *s = nextchar;
int exact = 0;
int ambig = 0;
CONST struct option *pfound = 0;
int indfound;
while (*s && *s != '=')
s++;
/* Test all options for either exact match or abbreviated matches. */
for (p = _getopt_long_options, option_index = 0; p->name;
p++, option_index++)
if (!strncmp (p->name, nextchar, s - nextchar))
{
if (s - nextchar == strlen (p->name))
{
/* Exact match found. */
pfound = p;
indfound = option_index;
exact = 1;
break;
}
else if (pfound == 0)
{
/* First nonexact match found. */
pfound = p;
indfound = option_index;
}
else
/* Second nonexact match found. */
ambig = 1;
}
if (ambig && !exact)
{
fprintf (stderr, "%s: option `%s' is ambiguous\n",
argv[0], argv[optind]);
nextchar += strlen (nextchar);
optind++;
return '?';
}
if (pfound != 0)
{
option_index = indfound;
optind++;
if (*s)
{
if (pfound->has_arg > 0)
optarg = s + 1;
else
{
fprintf (stderr,
"%s: option `%c%s' doesn't allow an argument\n",
argv[0], argv[optind - 1][0], pfound->name);
nextchar += strlen (nextchar);
return '?';
}
}
else if (pfound->has_arg == 1)
{
if (optind < argc)
optarg = argv[optind++];
else
{
fprintf (stderr, "%s: option `%s' requires an argument\n",
argv[0], argv[optind - 1]);
nextchar += strlen (nextchar);
return '?';
}
}
nextchar += strlen (nextchar);
if (pfound->flag)
{
*(pfound->flag) = pfound->val;
return 0;
}
return pfound->val;
}
/* Can't find it as a long option. If this is getopt_long_only,
and the option starts with '-' and is a valid short
option, then interpret it as a short option. Otherwise it's
an error. */
if (_getopt_long_only == 0 || argv[optind][0] == '+' ||
index (optstring, *nextchar) == 0)
{
if (opterr != 0)
fprintf (stderr, "%s: unrecognized option `%c%s'\n",
argv[0], argv[optind][0], nextchar);
nextchar += strlen (nextchar);
optind++;
return '?';
}
}
/* Look at and handle the next option-character. */
{
char c = *nextchar++;
char *temp = index (optstring, c);
/* Increment `optind' when we start to process its last character. */
if (*nextchar == 0)
optind++;
if (temp == 0 || c == ':')
{
if (opterr != 0)
{
if (c < 040 || c >= 0177)
fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
argv[0], c);
else
fprintf (stderr, "%s: unrecognized option `-%c'\n",
argv[0], c);
}
return '?';
}
if (temp[1] == ':')
{
if (temp[2] == ':')
{
/* This is an option that accepts an argument optionally. */
if (*nextchar != 0)
{
optarg = nextchar;
optind++;
}
else
optarg = 0;
nextchar = 0;
}
else
{
/* This is an option that requires an argument. */
if (*nextchar != 0)
{
optarg = nextchar;
/* If we end this ARGV-element by taking the rest as an arg,
we must advance to the next element now. */
optind++;
}
else if (optind == argc)
{
if (opterr != 0)
fprintf (stderr, "%s: option `-%c' requires an argument\n",
argv[0], c);
c = '?';
}
else
/* We already incremented `optind' once;
increment it again when taking next ARGV-elt as argument. */
optarg = argv[optind++];
nextchar = 0;
}
}
return c;
}
}
#ifdef TEST
/* Compile with -DTEST to make an executable for use in testing
the above definition of `getopt'. */
int
main (argc, argv)
int argc;
char **argv;
{
int c;
int digit_optind = 0;
while (1)
{
int this_option_optind = optind ? optind : 1;
c = getopt (argc, argv, "abc:d:0123456789");
if (c == EOF)
break;
switch (c)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (digit_optind != 0 && digit_optind != this_option_optind)
printf ("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;
printf ("option %c\n", c);
break;
case 'a':
printf ("option a\n");
break;
case 'b':
printf ("option b\n");
break;
case 'c':
printf ("option c with value `%s'\n", optarg);
break;
case '?':
break;
default:
printf ("?? getopt returned character code 0%o ??\n", c);
}
}
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
printf ("\n");
}
exit (0);
}
#endif /* TEST */

102
eoe/cmd/diff/getopt.h Normal file
View File

@@ -0,0 +1,102 @@
/* declarations for getopt
Copyright (C) 1989, 1990 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 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
extern char *optarg;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns EOF, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
extern int optind;
/* Callers store zero here to inhibit the error message `getopt' prints
for unrecognized options. */
extern int opterr;
/* Describe the long-named options requested by the application.
_GETOPT_LONG_OPTIONS is a vector of `struct option' terminated by an
element containing a name which is zero.
The field `has_arg' is:
0 if the option does not take an argument,
1 if the option requires an argument,
2 if the option takes an optional argument.
If the field `flag' is nonzero, it points to a variable that is set
to the value given in the field `val' when the option is found, but
left unchanged if the option is not found.
To have a long-named option do something other than set an `int' to
a compiled-in constant, such as set a value from `optarg', set the
option's `flag' field to zero and its `val' field to a nonzero
value (the equivalent single-letter option character, if there is
one). For long options that have a zero `flag' field, `getopt'
returns the contents of the `val' field. */
struct option
{
char *name;
int has_arg;
int *flag;
int val;
};
#ifdef __STDC__
extern const struct option *_getopt_long_options;
#else
extern struct option *_getopt_long_options;
#endif
/* If nonzero, '-' can introduce long-named options.
Set by getopt_long_only. */
extern int _getopt_long_only;
/* The index in GETOPT_LONG_OPTIONS of the long-named option found.
Only valid when a long-named option has been found by the most
recent call to `getopt'. */
extern int option_index;
#ifdef __STDC__
int getopt (int argc, char **argv, const char *shortopts);
int getopt_long (int argc, char **argv, const char *shortopts,
const struct option *longopts, int *longind);
int getopt_long_only (int argc, char **argv, const char *shortopts,
const struct option *longopts, int *longind);
void envopt(int *pargc, char ***pargv, char *optstr);
#else
int getopt ();
int getopt_long ();
int getopt_long_only ();
void envopt();
#endif

160
eoe/cmd/diff/getopt1.c Normal file
View File

@@ -0,0 +1,160 @@
/* Getopt for GNU.
Copyright (C) 1987, 1989 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 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "getopt.h"
#ifdef __STDC__
#define CONST const
#else
#define CONST
#endif
#if !defined (NULL)
#define NULL 0
#endif
int
getopt_long (argc, argv, options, long_options, opt_index)
int argc;
char **argv;
CONST char *options;
CONST struct option *long_options;
int *opt_index;
{
int val;
_getopt_long_options = long_options;
val = getopt (argc, argv, options);
if (val == 0 && opt_index != NULL)
*opt_index = option_index;
return val;
}
/* Like getopt_long, but '-' as well as '+' can indicate a long option.
If an option that starts with '-' doesn't match a long option,
but does match a short option, it is parsed as a short option
instead. */
int
getopt_long_only (argc, argv, options, long_options, opt_index)
int argc;
char **argv;
CONST char *options;
CONST struct option *long_options;
int *opt_index;
{
int val;
_getopt_long_options = long_options;
_getopt_long_only = 1;
val = getopt (argc, argv, options);
if (val == 0 && opt_index != NULL)
*opt_index = option_index;
return val;
}
#ifdef TEST
#include <stdio.h>
int
main (argc, argv)
int argc;
char **argv;
{
int c;
int digit_optind = 0;
while (1)
{
int this_option_optind = optind ? optind : 1;
char *name = '\0';
int option_index = 0;
static struct option long_options[] =
{
{"add", 1, 0, 0},
{"append", 0, 0, 0},
{"delete", 1, 0, 0},
{"verbose", 0, 0, 0},
{"create", 0, 0, 0},
{"file", 1, 0, 0},
{0, 0, 0, 0}
};
c = getopt_long (argc, argv, "abc:d:0123456789",
long_options, &option_index);
if (c == EOF)
break;
switch (c)
{
case 0:
printf ("option %s", (long_options[option_index]).name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (digit_optind != 0 && digit_optind != this_option_optind)
printf ("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;
printf ("option %c\n", c);
break;
case 'a':
printf ("option a\n");
break;
case 'b':
printf ("option b\n");
break;
case 'c':
printf ("option c with value `%s'\n", optarg);
break;
case '?':
break;
default:
printf ("?? getopt returned character code 0%o ??\n", c);
}
}
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
printf ("\n");
}
exit (0);
}
#endif /* TEST */

85
eoe/cmd/diff/ifdef.c Normal file
View File

@@ -0,0 +1,85 @@
/* #ifdef-format output routines for GNU DIFF.
Copyright (C) 1989 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_ifdef_hunk ();
struct change *find_change ();
static int next_line;
/* Print the edit-script SCRIPT as a merged #ifdef file. */
void
print_ifdef_script (script)
struct change *script;
{
next_line = 0;
print_script (script, find_change, print_ifdef_hunk);
while (next_line < files[0].buffered_lines)
print_1_line ("", &files[0].linbuf[next_line++]);
}
/* 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 (hunk)
struct change *hunk;
{
int first0, last0, first1, last1, deletes, inserts;
register int i;
/* Determine range of line numbers involved in each file. */
analyze_hunk (hunk, &first0, &last0, &first1, &last1, &deletes, &inserts);
if (!deletes && !inserts)
return;
/* Print out lines up to this change. */
while (next_line < first0)
print_1_line ("", &files[0].linbuf[next_line++]);
/* Print out stuff deleted from first file. */
if (deletes)
{
fprintf (outfile, "#ifndef %s\n", ifdef_string);
for (i = first0; i <= last0; i++)
print_1_line ("", &files[0].linbuf[i]);
next_line = i;
}
/* Print out stuff inserted from second file. */
if (inserts)
{
if (deletes)
fprintf (outfile, "#else /* %s */\n", ifdef_string);
else
fprintf (outfile, "#ifdef %s\n", ifdef_string);
for (i = first1; i <= last1; i++)
print_1_line ("", &files[1].linbuf[i]);
}
if (inserts)
fprintf (outfile, "#endif /* %s */\n", ifdef_string);
else
fprintf (outfile, "#endif /* not %s */\n", ifdef_string);
}

663
eoe/cmd/diff/io.c Normal file
View File

@@ -0,0 +1,663 @@
/* File I/O for GNU DIFF.
Copyright (C) 1988, 1989 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "diff.h"
#include <sys/mman.h>
/* Rotate a value n bits to the left. */
#define UINT_BIT (sizeof (unsigned) * CHAR_BIT)
#define ROL(v, n) ((v) << (n) | (v) >> UINT_BIT - (n))
/* Given a hash value and a new character, return a new hash value. */
#define HASH(h, c) ((c) + ROL (h, 7))
/* Current file under consideration. */
struct file_data *current;
int files_are_identical;
/* Check for binary files and compare them for exact identity. */
/* Return 1 if BUF contains a nul character.
SIZE is the number of characters in BUF. */
static int
binary_file_p (buf, size)
char *buf;
int size;
{
while (--size >= 0)
if (*buf++ == '\0')
return 1;
return 0;
}
int binary_file_threshold = BUFSIZ;
/* Slurp the current file completely into core.
Return nonzero if it appears to be a binary file. */
static int
slurp ()
{
/* If we have a nonexistent file at this stage, treat it as empty. */
if (current->desc < 0)
{
current->bufsize = 0;
current->buffered_chars = 0;
current->buffer = 0;
}
/* If it's a regular file, we can just get the size out of the stat
block and slurp it in all at once. */
/* In all cases, we leave room in the buffer for 2 extra chars
beyond those that current->bufsize describes:
one for a newline (in case the text does not end with one)
and one for a sentinel in find_identical_ends. */
else if ((current->stat.st_mode & S_IFMT) == S_IFREG)
{
current->bufsize = current->stat.st_size;
if (current->bufsize != current->stat.st_size)
pfatal_with_name (current->name);
current->buffer = (char *)(-1);
current->buffer_was_mmapped = 0;
if (current->bufsize > 0) {
current->buffer
= (char *)mmap((void *)0, current->bufsize + 2,
PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_AUTOGROW, current->desc, 0);
}
if ((int)(current->buffer) != -1) {
current->buffered_chars = current->bufsize;
current->buffer_was_mmapped = 1;
} else {
current->buffer = (char *) xmalloc (current->bufsize + 2);
current->buffered_chars
= read (current->desc, current->buffer, current->bufsize);
if (current->buffered_chars < 0)
pfatal_with_name (current->name);
}
}
else
{
int cc;
current->bufsize = 4096;
current->buffer = (char *) xmalloc (current->bufsize + 2);
current->buffered_chars = 0;
/* Not a regular file; read it in a little at a time, growing the
buffer as necessary. */
while ((cc = read (current->desc,
current->buffer + current->buffered_chars,
current->bufsize - current->buffered_chars))
> 0)
{
current->buffered_chars += cc;
if (current->buffered_chars == current->bufsize)
{
current->bufsize = current->bufsize * 2;
current->buffer = (char *) xrealloc (current->buffer,
current->bufsize + 2);
}
}
if (cc < 0)
pfatal_with_name (current->name);
}
/* Check first part of file to see if it's a binary file. */
if (! always_text_flag
&& binary_file_p (current->buffer,
min (current->buffered_chars, binary_file_threshold)))
return 1;
/* If not binary, make sure text ends in a newline,
but remember that we had to add one unless -B is in effect. */
if (current->buffered_chars > 0
&& current->buffer[current->buffered_chars - 1] != '\n')
{
current->missing_newline = !ignore_blank_lines_flag;
current->buffer[current->buffered_chars++] = '\n';
}
else
current->missing_newline = 0;
/* Don't use uninitialized storage. */
if (current->buffer != 0)
current->buffer[current->buffered_chars] = '\0';
return 0;
}
/* Split the file into lines, simultaneously computing the hash codes for
each line. */
void
find_and_hash_each_line ()
{
unsigned h;
int i;
unsigned char *p = (unsigned char *) current->prefix_end, *ip, c;
/* Attempt to get a good initial guess as to the number of lines. */
current->linbufsize = current->buffered_chars / 50 + 5;
current->linbuf
= (struct line_def *) xmalloc (current->linbufsize * sizeof (struct line_def));
if (function_regexp || output_style == OUTPUT_IFDEF)
{
/* If the -C, -D or -F option is used, we need to find the lines
of the matching prefix. At least we will need to find the last few,
but since we don't know how many, it's easiest to find them all.
If -D is specified, we need all the lines of the first file. */
current->buffered_lines = 0;
p = (unsigned char *) current->buffer;
}
else
{
/* Skip the identical prefixes, except be prepared to handle context.
In fact, handle 1 more preceding line than the context says,
in case shift_boundaries moves things backwards in this file. */
current->buffered_lines = current->prefix_lines - context - 1;
if (current->buffered_lines < 0)
current->buffered_lines = 0;
for (i = 0; i < context + 1; ++i)
/* Unless we are at the beginning, */
if ((char *) p != current->buffer)
/* Back up at least 1 char until at the start of a line. */
while ((char *) --p != current->buffer && p[-1] != '\n')
;
}
while ((char *) p < current->suffix_begin)
{
h = 0;
ip = p;
if (current->prefix_end <= (char *) p)
{
/* Hash this line until we find a newline. */
if (ignore_case_flag)
{
if (ignore_all_space_flag)
while ((c = *p) != '\n')
{
if (! isspace (c))
if (isupper (c))
h = HASH (h, tolower (c));
else
h = HASH (h, c);
++p;
}
else if (ignore_space_change_flag)
while ((c = *p) != '\n')
{
if (c == ' ' || c == '\t')
{
while ((c = *p) == ' ' || c == '\t')
++p;
if (c == '\n')
break;
h = HASH (h, ' ');
}
/* C is now the first non-space. */
if (isupper (c))
h = HASH (h, tolower (c));
else
h = HASH (h, c);
++p;
}
else
while ((c = *p) != '\n')
{
if (isupper (c))
h = HASH (h, tolower (c));
else
h = HASH (h, c);
++p;
}
}
else
{
if (ignore_all_space_flag)
while ((c = *p) != '\n')
{
if (! isspace (c))
h = HASH (h, c);
++p;
}
else if (ignore_space_change_flag)
while ((c = *p) != '\n')
{
if (c == ' ' || c == '\t')
{
while ((c = *p) == ' ' || c == '\t')
++p;
if (c == '\n')
break;
h = HASH (h, ' ');
}
/* C is not the first non-space. */
h = HASH (h, c);
++p;
}
else
while ((c = *p) != '\n')
{
h = HASH (h, c);
++p;
}
}
}
else
/* This line is part of the matching prefix,
so we don't need to hash it. */
while (*p != '\n')
++p;
/* Maybe increase the size of the line table. */
if (current->buffered_lines >= current->linbufsize)
{
while (current->buffered_lines >= current->linbufsize)
current->linbufsize *= 2;
current->linbuf
= (struct line_def *) xrealloc (current->linbuf,
current->linbufsize
* sizeof (struct line_def));
}
current->linbuf[current->buffered_lines].text = (char *) ip;
current->linbuf[current->buffered_lines].length = p - ip + 1;
current->linbuf[current->buffered_lines].hash = h;
++current->buffered_lines;
++p;
}
i = 0;
while ((i < context || output_style == OUTPUT_IFDEF)
&& (char *) p < current->buffer + current->buffered_chars)
{
ip = p;
while (*p++ != '\n')
;
/* Maybe increase the size of the line table. */
if (current->buffered_lines >= current->linbufsize)
{
while (current->buffered_lines >= current->linbufsize)
current->linbufsize *= 2;
current->linbuf
= (struct line_def *) xrealloc (current->linbuf,
current->linbufsize
* sizeof (struct line_def));
}
current->linbuf[current->buffered_lines].text = (char *) ip;
current->linbuf[current->buffered_lines].length = p - ip;
current->linbuf[current->buffered_lines].hash = 0;
++current->buffered_lines;
++i;
}
if (ROBUST_OUTPUT_STYLE (output_style)
&& current->missing_newline
&& current->suffix_begin == current->buffer + current->buffered_chars)
--current->linbuf[current->buffered_lines - 1].length;
}
/* For same size files, look for mismatch w/o counting lines, in case identical */
VOID
loop_for_mismatch (char **pp0, char **pp1)
{
char *p0 = *pp0;
char *p1 = *pp1;
{
register int *ip0 = (int *)p0;
register int *ip1 = (int *)p1;
while (*ip0++ == *ip1++)
;
--ip0; --ip1;
p0 = (char *)(ip0);
p1 = (char *)(ip1);
}
while (*p0++ == *p1++)
;
*pp0 = p0;
*pp1 = p1;
}
/* Don't count lines until failed files_are_identical test */
loop_for_line_count (pbase, pend)
char *pbase, *pend;
{
int i = 0;
int j = pend - pbase;
int lines = 0;
while (i < j)
if (pbase[i++] == '\n')
++lines;
return lines;
}
/* Given a vector of two file_data objects, find the identical
prefixes and suffixes of each object. */
static void
find_identical_ends (filevec)
struct file_data filevec[];
{
char *p0, *p1, *end0, *beg0;
int lines;
if (filevec[0].buffered_chars == 0 || filevec[1].buffered_chars == 0)
{
filevec[0].prefix_end = filevec[0].buffer;
filevec[1].prefix_end = filevec[1].buffer;
filevec[0].prefix_lines = filevec[1].prefix_lines = 0;
filevec[0].suffix_begin = filevec[0].buffer + filevec[0].buffered_chars;
filevec[1].suffix_begin = filevec[1].buffer + filevec[1].buffered_chars;
filevec[0].suffix_lines = filevec[1].suffix_lines = 0;
return;
}
/* Find identical prefix. */
p0 = filevec[0].buffer;
p1 = filevec[1].buffer;
lines = 0;
/* Insert end "sentinels", in this case characters that are guaranteed
to make the equality test false, and thus terminate the loop. */
if (filevec[0].buffered_chars < filevec[1].buffered_chars)
p0[filevec[0].buffered_chars] = ~p1[filevec[0].buffered_chars];
else
p1[filevec[1].buffered_chars] = ~p0[filevec[1].buffered_chars];
if (filevec[0].buffered_chars == filevec[1].buffered_chars)
{
/* Loop until first mismatch, or to the sentinel characters. */
loop_for_mismatch (&p0, &p1);
/* If the sentinel was passed, and lengths are equal, the
files are identical. */
if (p0 - filevec[0].buffer > filevec[0].buffered_chars)
{
filevec[0].prefix_end = p0 - 1;
filevec[1].prefix_end = p1 - 1;
filevec[0].prefix_lines = filevec[1].prefix_lines = 0;
filevec[0].suffix_begin = filevec[0].buffer;
filevec[1].suffix_begin = filevec[1].buffer;
filevec[0].suffix_lines = filevec[1].suffix_lines = 0;
files_are_identical = 1;
return;
}
lines = loop_for_line_count (filevec[0].buffer, p0 - 1);
}
else
while (1)
{
char c = *p0++;
if (c != *p1++)
break;
if (c == '\n')
++lines;
}
/* Don't count missing newline as part of prefix in RCS mode. */
if (ROBUST_OUTPUT_STYLE (output_style)
&& ((filevec[0].missing_newline
&& p0 - filevec[0].buffer > filevec[0].buffered_chars)
||
(filevec[1].missing_newline
&& p1 - filevec[1].buffer > filevec[1].buffered_chars)))
--p0, --p1, --lines;
/* Point at first nonmatching characters. */
--p0, --p1;
/* Skip back to last line-beginning in the prefix. */
while (p0 != filevec[0].buffer && p0[-1] != '\n')
--p0, --p1;
/* Record the prefix. */
filevec[0].prefix_end = p0;
filevec[1].prefix_end = p1;
filevec[0].prefix_lines = filevec[1].prefix_lines = lines;
/* Find identical suffix. */
/* P0 and P1 point beyond the last chars not yet compared. */
p0 = filevec[0].buffer + filevec[0].buffered_chars;
p1 = filevec[1].buffer + filevec[1].buffered_chars;
lines = 0;
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. */
if (filevec[0].buffered_chars < filevec[1].buffered_chars)
beg0 = filevec[0].prefix_end;
else
/* Figure out where P0 will be when P1 is at the end of the prefix.
Thus we only need to test P0. */
beg0 = (filevec[0].prefix_end
+ filevec[0].buffered_chars - filevec[1].buffered_chars);
/* Scan back until chars don't match or we reach that point. */
while (p0 != beg0)
{
char c = *--p0;
if (c != *--p1)
{
/* Point at the first char of the matching suffix. */
++p0, ++p1;
break;
}
if (c == '\n')
++lines;
}
/* Are we at a line-beginning in both files? */
if (p0 != end0
&& !((p0 == filevec[0].buffer || p0[-1] == '\n')
&&
(p1 == filevec[1].buffer || p1[-1] == '\n')))
{
/* No. We counted one line too many. */
--lines;
/* Advance to next place that is a line-beginning in both files. */
do
{
++p0, ++p1;
}
while (p0 != end0 && p0[-1] != '\n');
}
}
/* Record the suffix. */
filevec[0].suffix_begin = p0;
filevec[1].suffix_begin = p1;
filevec[0].suffix_lines = filevec[1].suffix_lines = lines;
}
/* Lines are put into equivalence classes (of lines that match in line_cmp).
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
{
struct equivclass *next; /* Next item in this bucket. */
struct line_def line; /* A line that fits this class. */
};
/* Hash-table: array of buckets, each being a chain of equivalence classes. */
static struct equivclass **buckets;
/* Size of the bucket array. */
static int 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 int equivs_index;
/* Size allocated to the array `equivs'. */
static int equivs_alloc;
/* Largest primes less than some power of two, for nbuckets. Values range
from useful to preposterous. If one of these numbers isn't prime
after all, don't blame it on me, blame it on primes (6) . . . */
static int primes[] =
{
509,
1021,
2039,
4093,
8191,
16381,
32749,
65521,
131071,
262139,
524287,
1048573,
2097143,
4194301,
8388593,
16777213,
33554393,
67108859, /* Preposterously large . . . */
-1
};
/* Index of current nbuckets in primes. */
static int primes_index;
/* Find the equiv class associated with line N of the current file. */
static int
find_equiv_class (n)
int n;
{
int bucket;
struct equivclass *b, *p = NULL;
/* Equivalence class 0 is permanently allocated to lines that were
not hashed because they were parts of identical prefixes or
suffixes. */
if (n < current->prefix_lines
|| current->linbuf[n].text >= current->suffix_begin)
return 0;
/* Check through the appropriate bucket to see if there isn't already
an equivalence class for this line. */
bucket = current->linbuf[n].hash % nbuckets;
b = buckets[bucket];
while (b)
{
if (b->line.hash == current->linbuf[n].hash
&& (b->line.length == current->linbuf[n].length
/* Lines of different lengths can match with certain options. */
|| length_varies)
&& !line_cmp (&b->line, &current->linbuf[n]))
return b - equivs;
p = b, b = b->next;
}
/* Create a new equivalence class in this bucket. */
p = &equivs[equivs_index++];
p->next = buckets[bucket];
buckets[bucket] = p;
p->line = current->linbuf[n];
return equivs_index - 1;
}
/* 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. */
int
read_files (filevec)
struct file_data filevec[];
{
int i, j;
int binary = 0;
int this_binary;
current = &filevec[0];
binary = this_binary = slurp ();
current = &filevec[1];
this_binary = slurp ();
if (binary || this_binary)
return 1;
files_are_identical = 0;
find_identical_ends (filevec);
if (files_are_identical)
return 0;
for (i = 0; i < 2; ++i)
{
current = &filevec[i];
find_and_hash_each_line ();
}
/* This is guaranteed to be enough space. */
equivs_alloc = filevec[0].buffered_lines + filevec[1].buffered_lines + 1;
equivs = (struct equivclass *) xmalloc (equivs_alloc * sizeof (struct equivclass));
/* Equivalence class 0 is permanently safe for lines that were not
hashed. Real equivalence classes start at 1. */
equivs_index = 1;
primes_index = 0;
while (primes[primes_index] < equivs_alloc / 3)
primes_index++;
buckets = (struct equivclass **) xmalloc (primes[primes_index] * sizeof (struct equivclass *));
bzero (buckets, primes[primes_index] * sizeof (struct equivclass *));
nbuckets = primes[primes_index];
for (i = 0; i < 2; ++i)
{
current = &filevec[i];
current->equivs
= (int *) xmalloc (current->buffered_lines * sizeof (int));
for (j = 0; j < current->buffered_lines; ++j)
current->equivs[j] = find_equiv_class (j);
}
filevec[0].equiv_max = filevec[1].equiv_max = equivs_index;
free (equivs);
free (buckets);
return 0;
}

43
eoe/cmd/diff/limits.h Normal file
View File

@@ -0,0 +1,43 @@
/* Number of bits in a `char'. */
#define CHAR_BIT 8
/* No multibyte characters supported yet. */
#define MB_LEN_MAX 1
/* Minimum and maximum values a `signed char' can hold. */
#define SCHAR_MIN (-128)
#define SCHAR_MAX 127
/* Maximum value an `unsigned char' can hold. (Minimum is 0). */
#define UCHAR_MAX 255U
/* Minimum and maximum values a `char' can hold. */
#ifdef __CHAR_UNSIGNED__
#define CHAR_MIN 0
#define CHAR_MAX 255U
#else
#define CHAR_MIN (-128)
#define CHAR_MAX 127
#endif
/* Minimum and maximum values a `signed short int' can hold. */
#define SHRT_MIN (-32768)
#define SHRT_MAX 32767
/* Maximum value an `unsigned short int' can hold. (Minimum is 0). */
#define USHRT_MAX 65535U
/* Minimum and maximum values a `signed int' can hold. */
#define INT_MIN (-INT_MAX-1)
#define INT_MAX 2147483647
/* Maximum value an `unsigned int' can hold. (Minimum is 0). */
#define UINT_MAX 4294967295U
/* Minimum and maximum values a `signed long int' can hold.
(Same as `int'). */
#define LONG_MIN (-LONG_MAX-1)
#define LONG_MAX 2147483647
/* Maximum value an `unsigned long int' can hold. (Minimum is 0). */
#define ULONG_MAX 4294967295U

71
eoe/cmd/diff/normal.c Normal file
View File

@@ -0,0 +1,71 @@
/* Normal-format output routines for GNU DIFF.
Copyright (C) 1988, 1989 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "diff.h"
void print_normal_hunk ();
void print_number_range ();
struct change *find_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 (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. */
void
print_normal_hunk (hunk)
struct change *hunk;
{
int first0, last0, first1, last1, deletes, inserts;
register int i;
/* Determine range of line numbers involved in each file. */
analyze_hunk (hunk, &first0, &last0, &first1, &last1, &deletes, &inserts);
if (!deletes && !inserts)
return;
/* Print out the line number header for this hunk */
print_number_range (',', &files[0], first0, last0);
fprintf (outfile, "%c", change_letter (inserts, deletes));
print_number_range (',', &files[1], first1, last1);
fprintf (outfile, "\n");
/* Print the lines that the first file has. */
if (deletes)
for (i = first0; i <= last0; i++)
print_1_line ("<", &files[0].linbuf[i]);
if (inserts && deletes)
fprintf (outfile, "---\n");
/* Print the lines that the second file has. */
if (inserts)
for (i = first1; i <= last1; i++)
print_1_line (">", &files[1].linbuf[i]);
}

2768
eoe/cmd/diff/regex.c Normal file

File diff suppressed because it is too large Load Diff

257
eoe/cmd/diff/regex.h Normal file
View File

@@ -0,0 +1,257 @@
/* Definitions for data structures callers pass the regex library.
Copyright (C) 1985, 1989-90 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 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef __GNUC__
#pragma once
#endif
#ifndef __REGEXP_LIBRARY
#define __REGEXP_LIBRARY
/* Define number of parens for which we record the beginnings and ends.
This affects how much space the `struct re_registers' type takes up. */
#ifndef RE_NREGS
#define RE_NREGS 10
#endif
#define BYTEWIDTH 8
/* Maximum number of duplicates an interval can allow. */
#define RE_DUP_MAX ((1 << 15) - 1)
/* This defines the various regexp syntaxes. */
extern int obscure_syntax;
/* The following bits are used in the obscure_syntax variable to choose among
alternative regexp syntaxes. */
/* If this bit is set, plain parentheses serve as grouping, and backslash
parentheses are needed for literal searching.
If not set, backslash-parentheses are grouping, and plain parentheses
are for literal searching. */
#define RE_NO_BK_PARENS 1
/* If this bit is set, plain | serves as the `or'-operator, and \| is a
literal.
If not set, \| serves as the `or'-operator, and | is a literal. */
#define RE_NO_BK_VBAR (1 << 1)
/* If this bit is not set, plain + or ? serves as an operator, and \+, \? are
literals.
If set, \+, \? are operators and plain +, ? are literals. */
#define RE_BK_PLUS_QM (1 << 2)
/* If this bit is set, | binds tighter than ^ or $.
If not set, the contrary. */
#define RE_TIGHT_VBAR (1 << 3)
/* If this bit is set, then treat newline as an OR operator.
If not set, treat it as a normal character. */
#define RE_NEWLINE_OR (1 << 4)
/* If this bit is set, then special characters may act as normal
characters in some contexts. Specifically, this applies to:
^ -- only special at the beginning, or after ( or |;
$ -- only special at the end, or before ) or |;
*, +, ? -- only special when not after the beginning, (, or |.
If this bit is not set, special characters (such as *, ^, and $)
always have their special meaning regardless of the surrounding
context. */
#define RE_CONTEXT_INDEP_OPS (1 << 5)
/* If this bit is not set, then \ before anything inside [ and ] is taken as
a real \.
If set, then such a \ escapes the following character. This is a
special case for awk. */
#define RE_AWK_CLASS_HACK (1 << 6)
/* If this bit is set, then \{ and \} or { and } serve as interval operators.
If not set, then \{ and \} and { and } are treated as literals. */
#define RE_INTERVALS (1 << 7)
/* If this bit is not set, then \{ and \} serve as interval operators and
{ and } are literals.
If set, then { and } serve as interval operators and \{ and \} are
literals. */
#define RE_NO_BK_CURLY_BRACES (1 << 8)
/* If this bit is set, then character classes are supported; they are:
[:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:],
[:space:], [:print:], [:punct:], [:graph:], and [:cntrl:].
If not set, then character classes are not supported. */
#define RE_CHAR_CLASSES (1 << 9)
/* If this bit is set, then the dot re doesn't match a null byte.
If not set, it does. */
#define RE_DOT_NOT_NULL (1 << 10)
/* If this bit is set, then [^...] doesn't match a newline.
If not set, it does. */
#define RE_HAT_NOT_NEWLINE (1 << 11)
/* If this bit is set, back references are recognized.
If not set, they aren't. */
#define RE_NO_BK_REFS (1 << 12)
/* If this bit is set, back references must refer to a preceding
subexpression. If not set, a back reference to a nonexistent
subexpression is treated as literal characters. */
#define RE_NO_EMPTY_BK_REF (1 << 13)
/* If this bit is set, bracket expressions can't be empty.
If it is set, they can be empty. */
#define RE_NO_EMPTY_BRACKETS (1 << 14)
/* If this bit is set, then *, +, ? and { cannot be first in an re or
immediately after a |, or a (. Furthermore, a | cannot be first or
last in an re, or immediately follow another | or a (. Also, a ^
cannot appear in a nonleading position and a $ cannot appear in a
nontrailing position (outside of bracket expressions, that is). */
#define RE_CONTEXTUAL_INVALID_OPS (1 << 15)
/* If this bit is set, then +, ? and | aren't recognized as operators.
If it's not, they are. */
#define RE_LIMITED_OPS (1 << 16)
/* If this bit is set, then an ending range point has to collate higher
or equal to the starting range point.
If it's not set, then when the ending range point collates higher
than the starting range point, the range is just considered empty. */
#define RE_NO_EMPTY_RANGES (1 << 17)
/* If this bit is set, then a hyphen (-) can't be an ending range point.
If it isn't, then it can. */
#define RE_NO_HYPHEN_RANGE_END (1 << 18)
/* Define combinations of bits for the standard possibilities. */
#define RE_SYNTAX_POSIX_AWK (RE_NO_BK_PARENS | RE_NO_BK_VBAR \
| RE_CONTEXT_INDEP_OPS)
#define RE_SYNTAX_AWK (RE_NO_BK_PARENS | RE_NO_BK_VBAR \
| RE_CONTEXT_INDEP_OPS | RE_AWK_CLASS_HACK)
#define RE_SYNTAX_EGREP (RE_NO_BK_PARENS | RE_NO_BK_VBAR \
| RE_CONTEXT_INDEP_OPS | RE_NEWLINE_OR)
#define RE_SYNTAX_GREP (RE_BK_PLUS_QM | RE_NEWLINE_OR)
#define RE_SYNTAX_EMACS 0
#define RE_SYNTAX_POSIX_BASIC (RE_INTERVALS | RE_BK_PLUS_QM \
| RE_CHAR_CLASSES | RE_DOT_NOT_NULL \
| RE_HAT_NOT_NEWLINE | RE_NO_EMPTY_BK_REF \
| RE_NO_EMPTY_BRACKETS | RE_LIMITED_OPS \
| RE_NO_EMPTY_RANGES | RE_NO_HYPHEN_RANGE_END)
#define RE_SYNTAX_POSIX_EXTENDED (RE_INTERVALS | RE_NO_BK_CURLY_BRACES \
| RE_NO_BK_VBAR | RE_NO_BK_PARENS \
| RE_HAT_NOT_NEWLINE | RE_CHAR_CLASSES \
| RE_NO_EMPTY_BRACKETS | RE_CONTEXTUAL_INVALID_OPS \
| RE_NO_BK_REFS | RE_NO_EMPTY_RANGES \
| RE_NO_HYPHEN_RANGE_END)
/* This data structure is used to represent a compiled pattern. */
struct re_pattern_buffer
{
char *buffer; /* Space holding the compiled pattern commands. */
long allocated; /* Size of space that `buffer' points to. */
long used; /* Length of portion of buffer actually occupied */
char *fastmap; /* Pointer to fastmap, if any, or zero if none. */
/* re_search uses the fastmap, if there is one,
to skip over totally implausible characters. */
char *translate; /* Translate table to apply to all characters before
comparing, or zero for no translation.
The translation is applied to a pattern when it is
compiled and to data when it is matched. */
char fastmap_accurate;
/* Set to zero when a new pattern is stored,
set to one when the fastmap is updated from it. */
char can_be_null; /* Set to one by compiling fastmap
if this pattern might match the null string.
It does not necessarily match the null string
in that case, but if this is zero, it cannot.
2 as value means can match null string
but at end of range or before a character
listed in the fastmap. */
};
/* search.c (search_buffer) needs this one value. It is defined both in
regex.c and here. */
#define RE_EXACTN_VALUE 1
/* Structure to store register contents data in.
Pass the address of such a structure as an argument to re_match, etc.,
if you want this information back.
For i from 1 to RE_NREGS - 1, start[i] records the starting index in
the string of where the ith subexpression matched, and end[i] records
one after the ending index. start[0] and end[0] are analogous, for
the entire pattern. */
struct re_registers
{
int start[RE_NREGS];
int end[RE_NREGS];
};
#ifdef __STDC__
extern char *re_compile_pattern (char *, int, struct re_pattern_buffer *);
/* Is this really advertised? */
extern void re_compile_fastmap (struct re_pattern_buffer *);
extern int re_search (struct re_pattern_buffer *, char*, int, int, int,
struct re_registers *);
extern int re_search_2 (struct re_pattern_buffer *, char *, int,
char *, int, int, int,
struct re_registers *, int);
extern int re_match (struct re_pattern_buffer *, char *, int, int,
struct re_registers *);
extern int re_match_2 (struct re_pattern_buffer *, char *, int,
char *, int, int, struct re_registers *, int);
/* 4.2 bsd compatibility. */
extern char *re_comp (char *);
extern int re_exec (char *);
#else /* !__STDC__ */
extern char *re_compile_pattern ();
/* Is this really advertised? */
extern void re_compile_fastmap ();
extern int re_search (), re_search_2 ();
extern int re_match (), re_match_2 ();
/* 4.2 bsd compatibility. */
extern char *re_comp ();
extern int re_exec ();
#endif /* __STDC__ */
#ifdef SYNTAX_TABLE
extern char *re_syntax_table;
#endif
#endif /* !__REGEXP_LIBRARY */

267
eoe/cmd/diff/system.h Normal file
View File

@@ -0,0 +1,267 @@
/* System dependent declarations.
Copyright (C) 1988, 1989, 1992, 1993, 1994 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* We must define `volatile' and `const' first (the latter inside config.h),
so that they're used consistently in all system includes. */
#if !__STDC__
#ifndef volatile
#define volatile
#endif
#endif
#include "config.h"
#include <sys/types.h>
#include <sys/stat.h>
#if __STDC__
#define PARAMS(args) args
#define VOID void
#else
#define PARAMS(args) ()
#define VOID char
#endif
#if STAT_MACROS_BROKEN
#undef S_ISBLK
#undef S_ISCHR
#undef S_ISDIR
#undef S_ISFIFO
#undef S_ISREG
#undef S_ISSOCK
#endif
#ifndef S_ISDIR
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#endif
#ifndef S_ISREG
#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
#endif
#if !defined(S_ISBLK) && defined(S_IFBLK)
#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
#endif
#if !defined(S_ISCHR) && defined(S_IFCHR)
#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
#endif
#if !defined(S_ISFIFO) && defined(S_IFFIFO)
#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFFIFO)
#endif
#if !defined(S_ISSOCK) && defined(S_IFSOCK)
#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
#endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifndef SEEK_SET
#define SEEK_SET 0
#endif
#ifndef SEEK_CUR
#define SEEK_CUR 1
#endif
#ifndef STDIN_FILENO
#define STDIN_FILENO 0
#endif
#ifndef STDOUT_FILENO
#define STDOUT_FILENO 1
#endif
#ifndef STDERR_FILENO
#define STDERR_FILENO 2
#endif
#if HAVE_TIME_H
#include <time.h>
#else
#include <sys/time.h>
#endif
#if HAVE_FCNTL_H
#include <fcntl.h>
#else
#if HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#endif
#if !HAVE_DUP2
#define dup2(f,t) (close (t), fcntl (f,F_DUPFD,t))
#endif
#ifndef O_RDONLY
#define O_RDONLY 0
#endif
#if HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifndef WEXITSTATUS
#define WEXITSTATUS(stat_val) ((unsigned) (stat_val) >> 8)
#endif
#ifndef WIFEXITED
#define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
#endif
#ifndef STAT_BLOCKSIZE
#if HAVE_ST_BLKSIZE
#define STAT_BLOCKSIZE(s) (s).st_blksize
#else
#define STAT_BLOCKSIZE(s) (8 * 1024)
#endif
#endif
#if HAVE_DIRENT_H
# include <dirent.h>
# define NAMLEN(dirent) strlen((dirent)->d_name)
#else
# define dirent direct
# define NAMLEN(dirent) ((dirent)->d_namlen)
# if HAVE_SYS_NDIR_H
# include <sys/ndir.h>
# endif
# if HAVE_SYS_DIR_H
# include <sys/dir.h>
# endif
# if HAVE_NDIR_H
# include <ndir.h>
# endif
#endif
#if HAVE_VFORK_H
#include <vfork.h>
#endif
#if HAVE_STDLIB_H
#include <stdlib.h>
#else
VOID *malloc ();
VOID *realloc ();
#endif
#ifndef getenv
char *getenv ();
#endif
#if HAVE_LIMITS_H
#include <limits.h>
#endif
#ifndef INT_MAX
#define INT_MAX 2147483647
#endif
#ifndef CHAR_BIT
#define CHAR_BIT 8
#endif
#if STDC_HEADERS || HAVE_STRING_H
# include <string.h>
# ifndef bzero
# define bzero(s, n) memset (s, 0, n)
# endif
#else
# if !HAVE_STRCHR
# define strchr index
# define strrchr rindex
# endif
char *strchr (), *strrchr ();
# if !HAVE_MEMCHR
# define memcmp(s1, s2, n) bcmp (s1, s2, n)
# define memcpy(d, s, n) bcopy (s, d, n)
void *memchr ();
# endif
#endif
#include <ctype.h>
/* CTYPE_DOMAIN (C) is nonzero if the unsigned char C can safely be given
as an argument to <ctype.h> macros like `isspace'. */
#if STDC_HEADERS
#define CTYPE_DOMAIN(c) 1
#else
#define CTYPE_DOMAIN(c) ((unsigned) (c) <= 0177)
#endif
#ifndef ISPRINT
#define ISPRINT(c) (CTYPE_DOMAIN (c) && isprint (c))
#endif
#ifndef ISSPACE
#define ISSPACE(c) (CTYPE_DOMAIN (c) && isspace (c))
#endif
#ifndef ISUPPER
#define ISUPPER(c) (CTYPE_DOMAIN (c) && isupper (c))
#endif
#ifndef ISDIGIT
#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)
#endif
#include <errno.h>
#if !STDC_HEADERS
extern int errno;
#endif
#ifdef min
#undef min
#endif
#ifdef max
#undef max
#endif
#define min(a,b) ((a) <= (b) ? (a) : (b))
#define max(a,b) ((a) >= (b) ? (a) : (b))
/* This section contains Posix-compliant defaults for macros
that are meant to be overridden by hand in config.h as needed. */
#ifndef filename_cmp
#define filename_cmp(a, b) strcmp (a, b)
#endif
#ifndef filename_lastdirchar
#define filename_lastdirchar(filename) strrchr (filename, '/')
#endif
#ifndef HAVE_FORK
#define HAVE_FORK 1
#endif
#ifndef HAVE_SETMODE
#define HAVE_SETMODE 0
#endif
#ifndef initialize_main
#define initialize_main(argcp, argvp)
#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)
#endif
/* Place into Q a quoted version of A suitable for `popen' or `system',
incrementing Q and junking A.
Do not increment Q by more than 4 * strlen (A) + 2. */
#ifndef SYSTEM_QUOTE_ARG
#define SYSTEM_QUOTE_ARG(q, a) \
{ \
*(q)++ = '\''; \
for (; *(a); *(q)++ = *(a)++) \
if (*(a) == '\'') \
{ \
*(q)++ = '\''; \
*(q)++ = '\\'; \
*(q)++ = '\''; \
} \
*(q)++ = '\''; \
}
#endif

619
eoe/cmd/diff/util.c Normal file
View File

@@ -0,0 +1,619 @@
/* Support routines for GNU DIFF.
Copyright (C) 1988, 1989 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "diff.h"
VOID debug_script (struct change *sp);
/* Use when a system call returns non-zero status.
TEXT should normally be the file name. */
void
perror_with_name (text)
char *text;
{
fprintf (stderr, "%s: ", program);
perror (text);
}
/* Use when a system call returns non-zero status and that is fatal. */
void
pfatal_with_name (text)
char *text;
{
print_message_queue ();
fprintf (stderr, "%s: ", program);
perror (text);
exit (2);
}
/* Print an error message from the format-string FORMAT
with args ARG1 and ARG2. */
void
error (format, arg, arg1)
char *format;
char *arg;
char *arg1;
{
fprintf (stderr, "%s: ", program);
fprintf (stderr, format, arg, arg1);
fprintf (stderr, "\n");
}
/* Print an error message containing the string TEXT, then exit. */
void
fatal (message)
char *message;
{
print_message_queue ();
error (message, "");
exit (2);
}
/* Like printf, except if -l in effect then save the message and print later.
This is used for things like "binary files differ" and "Only in ...". */
void
message (format, arg1, arg2)
char *format, *arg1, *arg2;
{
if (paginate_flag)
{
struct msg *new = (struct msg *) xmalloc (sizeof (struct msg));
if (msg_chain_end == 0)
msg_chain = msg_chain_end = new;
else
{
msg_chain_end->next = new;
msg_chain_end = new;
}
new->format = format;
new->arg1 = concat (arg1, "", "");
new->arg2 = concat (arg2, "", "");
new->next = 0;
}
else
printf (format, arg1, arg2);
}
/* Output all the messages that were saved up by calls to `message'. */
void
print_message_queue ()
{
struct msg *m;
for (m = msg_chain; m; m = m->next)
printf (m->format, m->arg1, m->arg2);
}
/* 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. */
void
setup_output (name0, name1, depth)
char *name0, *name1;
int depth;
{
char *name;
/* Construct the header of this piece of diff. */
name = (char *) xmalloc (strlen (name0) + strlen (name1)
+ strlen (switch_string) + 15);
strcpy (name, "diff");
strcat (name, switch_string);
strcat (name, " ");
strcat (name, name0);
strcat (name, " ");
strcat (name, name1);
if (paginate_flag)
{
int pipes[2];
int desc;
/* For a `pr' and make OUTFILE a pipe to it. */
if (pipe (pipes) < 0)
pfatal_with_name ("pipe");
fflush (stdout);
desc = vfork ();
if (desc < 0)
pfatal_with_name ("vfork");
if (desc == 0)
{
close (pipes[1]);
if (pipes[0] != fileno (stdin))
{
if (dup2 (pipes[0], fileno (stdin)) < 0)
pfatal_with_name ("dup2");
close (pipes[0]);
}
if (execl (PR_FILE_NAME, PR_FILE_NAME, "-f", "-h", name, 0) < 0)
pfatal_with_name (PR_FILE_NAME);
}
else
{
close (pipes[0]);
outfile = fdopen (pipes[1], "w");
}
}
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 (depth > 0)
printf ("%s\n", name);
}
free (name);
}
/* Call after the end of output of diffs for one file.
Close OUTFILE and get rid of the `pr' subfork. */
void
finish_output ()
{
if (outfile != stdout)
{
fclose (outfile);
wait (0);
}
}
/* Compare two lines (typically one from each input file)
according to the command line options.
Each line is described by a `struct line_def'.
Return 1 if the lines differ, like `bcmp'. */
int
line_cmp (s1, s2)
struct line_def *s1, *s2;
{
register char *t1, *t2;
register char end_char = line_end_char;
/* Check first for exact identity.
If that is true, return 0 immediately.
This detects the common case of exact identity
faster than complete comparison would.
The check for equal lengths is almost always not needed.
Only if the last line of two files both hash to the same
value, and the last line in the first file is a prefix
of the last line in the second file, and the first file
lacks a trailing newline, and length_varies is set,
and a ROBUST output style is chosen (which doesnt include
the artificial final newline in the length of the final line)
THEN does the length compare become critical to avoid falsely
concluding that the two lines are the same. Many thanks
to Paul Eggert for noticing this bug. */
if (s1->length == s2->length
&& memcmp (s1->text, s2->text, s1->length) == 0)
return 0;
/* Not exactly identical, but perhaps they match anyway
when case or whitespace is ignored. */
if (ignore_case_flag || ignore_space_change_flag || ignore_all_space_flag)
{
t1 = s1->text;
t2 = s2->text;
while (1)
{
register char c1 = *t1++;
register char c2 = *t2++;
/* Ignore horizontal whitespace if -b or -w is specified. */
if (ignore_all_space_flag)
{
/* For -w, just skip past any spaces or tabs. */
while (c1 == ' ' || c1 == '\t') c1 = *t1++;
while (c2 == ' ' || c2 == '\t') c2 = *t2++;
}
else if (ignore_space_change_flag)
{
/* For -b, advance past any sequence of whitespace in line 1
and consider it just one Space, or nothing at all
if it is at the end of the line. */
if (c1 == ' ' || c1 == '\t')
{
while (1)
{
c1 = *t1++;
if (c1 == end_char)
break;
if (c1 != ' ' && c1 != '\t')
{
--t1;
c1 = ' ';
break;
}
}
}
/* Likewise for line 2. */
if (c2 == ' ' || c2 == '\t')
{
while (1)
{
c2 = *t2++;
if (c2 == end_char)
break;
if (c2 != ' ' && c2 != '\t')
{
--t2;
c2 = ' ';
break;
}
}
}
}
/* Upcase all letters if -i is specified. */
if (ignore_case_flag)
{
if (islower (c1))
c1 = toupper (c1);
if (islower (c2))
c2 = toupper (c2);
}
if (c1 != c2)
break;
if (c1 == end_char)
return 0;
}
}
return (1);
}
/* Find the consecutive changes at the start of the script START.
Return the last link before the first gap. */
struct change *
find_change (start)
struct change *start;
{
return start;
}
struct change *
find_reverse_change (start)
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 (script, hunkfun, printfun)
struct change *script;
struct change * (*hunkfun) ();
void (*printfun) ();
{
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 = NULL;
#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 (line_flag, line)
char *line_flag;
struct line_def *line;
{
int length = line->length; /* must be nonzero */
const char *text = line->text; /* Help the compiler. */
FILE *out = outfile; /* Help the compiler some more. */
/* 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 != NULL && line_flag[0] != 0)
fprintf (out, tab_align_flag ? "%s\t" : "%s ", line_flag);
/* Now output the contents of the line.
If -t was specified, expand tabs to spaces.
Otherwise output verbatim. */
if (tab_expand_flag)
{
register int column = 0;
register int i;
for (i = 0; i < line->length; i++)
{
register char c = line->text[i];
switch (c)
{
case '\t':
column++;
while (column & 7)
{
putc (' ', out);
column++;
}
c = ' ';
break;
case '\b':
column--;
break;
default:
column++;
break;
}
putc (c, out);
}
}
else
fwrite (text, sizeof (char), length, out);
if ((line_flag == NULL || line_flag[0] != 0) && text[length - 1] != '\n'
&& line_end_char == '\n')
fprintf (out, "\n\\ No newline at end of file\n");
}
change_letter (inserts, deletes)
int inserts, deletes;
{
if (!inserts)
return 'd';
else if (!deletes)
return 'a';
else
return '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 LNUM. FILE points to the data on the file.
Internal line numbers count from 0 within the current chunk.
Actual line numbers count from 1 within the entire file;
in addition, they include lines ignored for comparison purposes.
The `ltran' feature is no longer in use. */
int
translate_line_number (file, lnum)
struct file_data *file;
int lnum;
{
return lnum + 1;
}
void
translate_range (file, a, b, aptr, bptr)
struct file_data *file;
int a, b;
int *aptr, *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 (sepchar, file, a, b)
char sepchar;
struct file_data *file;
int a, b;
{
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, "%d%c%d", trans_a, sepchar, trans_b);
else
fprintf (outfile, "%d", 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.
Also set *DELETES nonzero if any lines of file 0 are deleted
and set *INSERTS nonzero if any lines of file 1 are inserted.
If only ignorable lines are inserted or deleted, both are
set to 0. */
void
analyze_hunk (hunk, first0, last0, first1, last1, deletes, inserts)
struct change *hunk;
int *first0, *last0, *first1, *last1;
int *deletes, *inserts;
{
int f0, l0, f1, l1, show_from, show_to;
int i;
int nontrivial = !(ignore_blank_lines_flag || ignore_regexp);
struct change *next;
show_from = show_to = 0;
f0 = hunk->line0;
f1 = hunk->line1;
for (next = hunk; next; next = next->link)
{
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 && ! nontrivial; i++)
if ((!ignore_blank_lines_flag || files[0].linbuf[i].length > 1)
&& (!ignore_regexp
|| 0 > re_search (&ignore_regexp_compiled,
files[0].linbuf[i].text,
files[0].linbuf[i].length, 0,
files[0].linbuf[i].length, 0)))
nontrivial = 1;
for (i = next->line1; i <= l1 && ! nontrivial; i++)
if ((!ignore_blank_lines_flag || files[1].linbuf[i].length > 1)
&& (!ignore_regexp
|| 0 > re_search (&ignore_regexp_compiled,
files[1].linbuf[i].text,
files[1].linbuf[i].length, 0,
files[1].linbuf[i].length, 0)))
nontrivial = 1;
}
*first0 = f0;
*last0 = l0;
*first1 = f1;
*last1 = l1;
/* If all inserted or deleted lines are ignorable,
tell the caller to ignore this hunk. */
if (!nontrivial)
show_from = show_to = 0;
*deletes = show_from;
*inserts = show_to;
}
/* malloc a block of memory, with fatal error message if we can't do it. */
VOID *
xmalloc (size)
unsigned size;
{
register VOID *value;
if (size == 0)
size = 1;
value = (VOID *) malloc (size);
if (!value)
fatal ("virtual memory exhausted");
return value;
}
/* realloc a block of memory, with fatal error message if we can't do it. */
VOID *
xrealloc (old, size)
VOID *old;
unsigned int size;
{
register VOID *value;
if (size == 0)
size = 1;
value = (VOID *) realloc (old, size);
if (!value)
fatal ("virtual memory exhausted");
return value;
}
/* Concatenate three strings, returning a newly malloc'd string. */
char *
concat (s1, s2, s3)
char *s1, *s2, *s3;
{
int len = strlen (s1) + strlen (s2) + strlen (s3);
char *new = (char *) xmalloc (len + 1);
strcpy (new, s1);
strcat (new, s2);
strcat (new, s3);
return new;
}
VOID
debug_script (struct change *sp)
{
fflush (stdout);
for (; sp; sp = sp->link)
fprintf (stderr, "%3d %3d delete %d insert %d\n",
sp->line0, sp->line1, sp->deleted, sp->inserted);
fflush (stderr);
}

3
eoe/cmd/diff/version.c Normal file
View File

@@ -0,0 +1,3 @@
/* Version number of GNU diff. */
char *version_string = "1.15";