[llvm-commits] CVS: llvm/test/Programs/MultiSource/Applications/spiff/LICENSE.TXT Makefile README Sample.1 Sample.2 Sample.3 Sample.4 command.c command.h comment.c comment.h compare.c compare.h edit.h exact.c exact.h flagdefs.h float.c float.h floatrep.c floatrep.h line.c line.h miller.c miller.h misc.c misc.h one output.c output.h paper.ms parse.c parse.h spiff.1 spiff.c strings.c strings.h token.c token.h tol.c tol.h two visual.c visual.h

Brian Gaeke gaeke at cs.uiuc.edu
Tue Jun 1 15:40:06 PDT 2004


Changes in directory llvm/test/Programs/MultiSource/Applications/spiff:

LICENSE.TXT added (r1.1)
Makefile added (r1.1)
README added (r1.1)
Sample.1 added (r1.1)
Sample.2 added (r1.1)
Sample.3 added (r1.1)
Sample.4 added (r1.1)
command.c added (r1.1)
command.h added (r1.1)
comment.c added (r1.1)
comment.h added (r1.1)
compare.c added (r1.1)
compare.h added (r1.1)
edit.h added (r1.1)
exact.c added (r1.1)
exact.h added (r1.1)
flagdefs.h added (r1.1)
float.c added (r1.1)
float.h added (r1.1)
floatrep.c added (r1.1)
floatrep.h added (r1.1)
line.c added (r1.1)
line.h added (r1.1)
miller.c added (r1.1)
miller.h added (r1.1)
misc.c added (r1.1)
misc.h added (r1.1)
one added (r1.1)
output.c added (r1.1)
output.h added (r1.1)
paper.ms added (r1.1)
parse.c added (r1.1)
parse.h added (r1.1)
spiff.1 added (r1.1)
spiff.c added (r1.1)
strings.c added (r1.1)
strings.h added (r1.1)
token.c added (r1.1)
token.h added (r1.1)
tol.c added (r1.1)
tol.h added (r1.1)
two added (r1.1)
visual.c added (r1.1)
visual.h added (r1.1)

---
Log message:

Importing spiff


---
Diffs of the changes:  (+7104 -0)

Index: llvm/test/Programs/MultiSource/Applications/spiff/LICENSE.TXT
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/LICENSE.TXT:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/LICENSE.TXT	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,13 ----
+ COPYRIGHT
+ 
+ Our lawyers advise the following:
+ 
+                    Copyright (c) 1988 Bellcore
+                        All Rights Reserved
+   Permission is granted to copy or use this program, EXCEPT that it
+   may not be sold for profit, the copyright notice must be reproduced
+   on copies, and credit should be given to Bellcore where it is due.
+   BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ 
+ Given that all of the above seems to be very reasonable, there should be no
+ reason for anyone to not play by the rules.


Index: llvm/test/Programs/MultiSource/Applications/spiff/Makefile
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/Makefile:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/Makefile	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,13 ----
+ LEVEL = ../../../../..
+ PROG     = spiff
+ CPPFLAGS = 
+ CFLAGS   = 
+ LDFLAGS  =
+ 
+ RUN_OPTIONS = ./Sample.1 ./Sample.2
+ #RUN_OPTIONS = ./Sample.3 ./Sample.4
+ #RUN_OPTIONS = ./one ./two
+ # you get the idea...
+ 
+ include ../../Makefile.multisrc
+ 


Index: llvm/test/Programs/MultiSource/Applications/spiff/README
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/README:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/README	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,264 ----
+ INSTALLATION
+ 	1) Change makefile settings to reflect
+ 		ATT vs. BSD software
+ 		termio vs. termcap
+ 		MGR vs. no MGR		(MGR is a BELLCORE produced
+ 					 window manager that is also available
+ 					 free to the public.)
+ 	2) Then, just say "make".
+ 		If you want to "make install", you should first
+ 		change definition of INSDIR in the makefile
+ 
+ 	3) to test the software say
+ 
+ 			spiff Sample.1 Sample.2
+ 
+ 		spiff should find 4 differences and
+ 		you should see the words "added", "deleted", "changed",
+ 		and "altered" as well as four number in stand-out mode.
+ 
+ 			spiff Sample.1 Sample.2 | cat
+ 
+ 		should produce the same output, only the differences
+ 		should be underlined However, on many terminals the underlining
+ 		does not appear. So try the command
+ 
+ 			spiff Sample.1 Sample.2 | cat -v
+ 
+ 		or whatever the equivalent to cat -v is on your system.
+ 
+ 		A more complicated test set is found in Sample.3 and Sample.4
+ 		These files show how to use embedded commands to do things
+ 		like change the commenting convention and tolerances on the
+ 		fly.  Be sure to run the command with the -s option to spiff:
+ 
+ 			spiff -s 'command spiffword' Sample.3 Sample.4
+ 
+ 		These files by no means provide an exhaustive test of
+ 		spiff's features. But they should give you some idea if things
+ 		are working right.
+ 
+ 	This code (or it's closely related cousins) has been run on
+ 	Vaxen running 4.3BSD, a CCI Power 6, some XENIX machines, and some
+ 	other machines running System V derivatives as well as
+ 	(thanks to eugene at ames.arpa) Cray, Amdahl and Convex machines.
+ 
+ 	4) Share and enjoy.
+ 
+ AUTHOR'S ADDRESS
+ 	Please send complaints, comments, praise, bug reports, etc to
+ 		Dan Nachbar
+ 		Bell Communications Research  (also known as BELLCORE)
+ 		445 South St. Room 2B-389
+ 		Morristown, NJ 07960
+ 
+ 			nachbar at bellcore.com
+ 		or
+ 			bellcore!nachbar
+ 		or
+ 			(201) 829-4392  (praise only, please)
+ 
+ OVERVIEW OF OPERATION
+ 
+ Each of two input files is read and stored in core.
+ Then it is parsed into a series of tokens (literal strings and
+ floating point numbers, white space is ignored).
+ The token sequences are stored in core as well.
+ After both files have been parsed, a differencing algorithm is applied to
+ the token sequences.  The differencing algorithm
+ produces an edit script, which is then passed to an output routine.
+ 
+ SIZE LIMITS AND OTHER DEFAULTS
+ 		file implementing limit		name		default value
+ maximum number of lines		lines.h		_L_MAXLINES	10000
+ 	per file
+ maximum number of tokens	token.h		K_MAXTOKENS	50000
+ 	per file
+ maximum line length		misc.h		Z_LINELEN	 1024
+ maximum word length		misc.h		Z_WORDLEN	   20
+  (length of misc buffers for
+  things like literal
+  delimiters.
+  NOT length of tokens which
+  can be virtually any length)
+ default absolute tolerance	tol.h		_T_ADEF		   "1e-10"   
+ default relative tolerance	tol.h		_T_RDEF		   "1e-10"  
+ maximum number of commands	command.h	_C_CMDMAX	  100
+  in effect at one time
+ maximum number of commenting	comment.h	W_COMMAX	   20
+  conventions that can be
+  in effect at one time
+  (not including commenting
+   conventions that are
+   restricted to beginning
+   of line)
+ maximum number of commenting	comment.h	W_BOLMAX	   20
+  conventions that are
+  restricted to beginning of
+  line that are in effect at
+  one time
+ maximum number of literal	comment.h	W_LITMAX	   20
+  string conventions that
+  can be in effect at one time
+ maximum number of tolerances	tol.h		_T_TOLMAX	   10
+  that can be in effect at one
+  time
+ 
+ 
+ DIFFERENCES BETWEEN THE CURRENT VERSION AND THE ENCLOSED PAPER
+ 
+ The files paper.ms and paper.out contain the nroff -ms input and
+ output respectively of a paper on spiff that was given the Summer '88
+ USENIX conference in San Francisco.  Since that time many changes
+ have been made to the code.  Many flags have changed and some have
+ had their meanings reversed, see the enclosed man page for the current
+ usage.  Also, there is no longer control over the
+ granularity of object used when applying the differencing algorithm.
+ The current version of spiff always applies the differencing
+ in terms of individual tokens.  The -t flag controls how the edit script
+ is printed.  This arrangement more closely reflects the original intent
+ of having multiple differencing granularities. 
+ 
+ PERFORMANCE
+ 
+ Spiff is big and slow.  It is big because all the storage is
+ in core.  It is a straightforward but boring task to move the temporary
+ storage into a file.  Someone who cares is invited to take on the job.
+ Spiff is slow because whenever a choice had to be made between
+ speed of operation and ease of coding, speed of operation almost always lost.
+ As the program matures it will almost certainly get smaller and faster.
+ Obvious performance enhancements have been avoided in order to make the
+ program available as soon as possible.
+ 
+ COPYRIGHT
+ 
+ Our lawyers advise the following:
+ 
+                    Copyright (c) 1988 Bellcore
+                        All Rights Reserved
+   Permission is granted to copy or use this program, EXCEPT that it
+   may not be sold for profit, the copyright notice must be reproduced
+   on copies, and credit should be given to Bellcore where it is due.
+   BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ 
+ Given that all of the above seems to be very reasonable, there should be no
+ reason for anyone to not play by the rules.
+ 
+ 
+ NAMING CONVENTIONS USED IN THE CODE
+ 
+ All symbols (functions, data declarations, macros) are named as follows:
+ 
+ 	L_foo	-- for names exported to other modules
+ 			and possibly used inside the module as well.
+ 	_L_foo	-- for names used by more than one routine
+ 			within a module
+ 	foo	-- for names used inside a single routine.
+ 
+ Each module uses a different value for "L" -- 
+ 	module files	   letter used     implements
+ 	spiff.c			Y	top level routines
+ 	misc.[ch]		Z	various routines used throughout
+ 	strings.[ch]		S	routines for handling strings
+ 	edit.h			E	list of changes found and printed
+ 	tol.[ch]		T	tolerances for real numbers
+ 	token.[ch]		K	storage for objects
+ 	float.[ch]		F	manipulation of floats
+ 	floatrep.[ch]		R	representation of floats
+ 	line.[ch]		L	storage for input lines
+ 	parse.[ch]		P	parse for input files
+ 	command.[ch]		C	storage and recognition of commands
+ 	comment.[ch]		W	comment list maintenance
+ 	compare.[ch]		X	comparisons of a single token
+ 	exact.[ch]		Q	exact match differencing algorithm
+ 	miller.[ch]		G	miller/myers differencing algorithm
+ 	output.[ch]		O	print listing of differences
+ 	flagdefs.h		U	define flag bits that are used in
+ 					several of the other modules.
+ 					These #defines could have been
+ 					included in misc.c, but were separated
+ 					out because of their explicit
+ 					communication function.
+ 	visual.[ch]		V	screen oriented display for MGR
+ 					window manager, also contains
+ 					dummy routines for people who don't
+ 					have MGR 
+ 
+ I haven't cleaned up visual.c yet.  It probably doesn't even compile
+ in this version anyway. But since most people don't have mgr, this
+ isn't urgent.
+ 
+ NON-OBVIOUS DATA STRUCTURES
+ 
+ The Floating Point Representation
+ 
+ Floating point numbers are stored in a struct R_flstr
+ The fractional part is often called the mantissa.
+ 
+ The structure consists of
+ 	a flag for the sign of the factional part
+ 	the exponent in binary 
+ 	a character string containing the fractional part
+ 
+ The structure could be converted to a float via
+ 	atof(strcat(".",mantissa)) * (10^exponent)
+ 
+ To be properly formed, the mantissa string must:
+ 	start with a digit between 1 and 9 (i.e. no leading zeros)
+ 		except for the zero, in which case the mantissa is exactly "0"
+ 	for the special case of zero, the exponent is always 0, and the
+ 		sign is always positive. (i.e. no negative 0)
+ 
+ In other words, (except for the value 0)
+ the mantissa is a fractional number ranging
+ between 0.1 (inclusive) and 1.0 (exclusive).
+ The exponent is interpreted as a power of 10.
+ 
+ Lines 
+ there are three sets of lines:
+ implemented in line.c and line.h
+ 	real_lines --
+ 	  the lines as they come from the file
+ 	content_lines --
+ 	  a subset of reallines that excluding embedded commands
+ implemented in token.c and token.h 
+ 	token_lines --
+ 	  a subset of content_lines consisting of those lines that
+ 		have tokens that begin on them (literals can go on for
+ 		more than one line)
+ 		i.e. content_lines excluding comments and blank lines.
+ 
+ 
+ THE STATE OF THE CODE
+ Things that should be added
+ 	visual mode should handle tabs and wrapped lines
+ 	handling huge files in chunks when in using the ordinal match
+ 	algorithm. right now you have to parse and then diff the
+ 	whole thing before you get any output.  often, you run out of memory.
+ 
+ Things that would be nice to add
+ 	output should optionally be expressed in real line numbers
+ 		(i.e. including command lines)
+ 	at present, all storage is in core. there should
+ 		be a compile time decision to allow temporary storage
+ 		in files rather than core. 
+ 		that way the user could decide how to handle the
+ 			speed/space tradeoff
+ 	a front end that looked like diff should be added so that
+ 		one could drop spiff into existing shell scripts
+ 	the parser converts floats into their internal form even when
+ 		it isn't necessary.
+ 	in the miller/myer code, the code should check for matching
+ 		end sequences.  it currently looks matching beginning
+ 		sequences.
+ 
+ Minor programming improvements (programming botches)
+ 	some of the #defines should really be enumerated types
+ 	all the routines in strings.c that alter the data at the end of
+ 		a pointer but return void should just return the correct
+ 		data. the current arrangement is a historical artifact
+ 		of the days when these routines returned a status code.
+ 		but then the code was never examined,
+ 		so i made them void . . .
+ 	comments should be added to the miller/myer code
+ 	in visual mode, ask for font by name rather than number


Index: llvm/test/Programs/MultiSource/Applications/spiff/Sample.1
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/Sample.1:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/Sample.1	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,11 ----
+ test file for spiff.
+ there is a word       here.
+ there is a deleted word in this line.
+ there is a word that is changed here.
+ 
+ no difference on 	this line  due to      white space.
+ default absolute tolerance should be 1e-10   
+ no difference --> 0.0           different --> 0.0
+ default relative tolerance should be 1e-10   
+ no difference --> 10.           different --> 10.00000
+ 


Index: llvm/test/Programs/MultiSource/Applications/spiff/Sample.2
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/Sample.2:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/Sample.2	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,11 ----
+ test file for spiff.
+ there is a word added here.
+ there is a         word in this line.
+ there is a word that is altered here.
+ no difference on this line due to white space.
+ 
+ default absolute tolerance should be .0000000001   
+ no difference --> 0.0000000001  different --> 0.00000000011
+ default relative tolerance should be 1.0e-10   
+ no difference --> 10.000000001  different --> 10.0000000011
+ 


Index: llvm/test/Programs/MultiSource/Applications/spiff/Sample.3
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/Sample.3:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/Sample.3	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,36 ----
+ spiffword rem this file should be named Sample.3
+ spiffword rem it is a test input file for spiff
+ spiffword rem it should be compared with a file named Sample.4, to use it
+ spiffword rem execute: spiff -s 'command spiffword' Sample.3 Sample.4
+ spiffword rem the -s argument is  essential, otherwise spiff will
+ spiffword rem will not recognized these comments for what they are.
+ spiffword rem first we'll check the default tolerances.  this is the
+ spiffword rem same test as is found in Sample.1/Sample.2
+ default absolute tolerance should be 1e-10   
+ no difference --> 0.0           different --> 0.0
+ default relative tolerance should be 1e-10   
+ no difference --> 10.           different --> 10.00000
+ spiffword rem Note that spiff said that the differences were on lines 2 and 4
+ spiffword rem of the input files even though they were really on lines 10 and
+ spiffword rem of this file.
+ spiffword rem That's because spiff does not count lines with commands.
+ spiffword rem As part of spiff's design, it is assumed that "embedded commands"
+ spiffword rem such as these are not of direct interest and have been added
+ spiffword rem soley for the purpose of controlling the spiffing process.
+ spiffword rem OK. Now we'll try changing some things. first, we'll add 
+ spiffword rem a commenting convention, everything from # to end of line
+ spiffword rem will be ignored.
+ spiffword comment # $
+ there should be NO differences on this line !!!! # Nah, Nah, can't see me !!
+ spiffword rem Well, that was fun. Now we'll ignore all differences
+ spiffword tol i
+ spiffword rem and there should be no differences the following lines
+ no difference --> 0.0           NO difference --> 0.0
+ no difference --> 10.           NO difference --> 10.00000
+ spiffword rem now we'll set the tolerance for the second number
+ spiffword rem on each line, to be lower than the others.
+ spiffword tol a0.02 ; a0.01 ; a0.02
+ spiffword rem and only the middle number should appear different
+ not different --> 0.0    different --> 0.0    not different --> 0.0
+ spiffword rem You get the idea. Enough fun for now.
+ Bye, Bye.


Index: llvm/test/Programs/MultiSource/Applications/spiff/Sample.4
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/Sample.4:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/Sample.4	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,36 ----
+ spiffword rem this file should be named Sample.4
+ spiffword rem it is a test input file for spiff
+ spiffword rem it should be compared with a file named Sample.3, to use it
+ spiffword rem execute: spiff -s 'command spiffword' Sample.3 Sample.4
+ spiffword rem the -s argument is  essential, otherwise spiff will
+ spiffword rem will not recognized these comments for what they are.
+ spiffword rem first we'll check the default tolerances.  this is the
+ spiffword rem same test as is found in Sample.1/Sample.2
+ default absolute tolerance should be .0000000001   
+ no difference --> 0.0000000001  different --> 0.00000000011
+ default relative tolerance should be 1.0e-10   
+ no difference --> 10.000000001  different --> 10.0000000011
+ spiffword rem Note that spiff said that the differences were on lines 1 and 3
+ spiffword rem of the input files even though they were really on lines 10 and
+ spiffword rem of this file.
+ spiffword rem That's because spiff does not count lines with commands.
+ spiffword rem As part of spiff's design, it is assumed that "embedded commands"
+ spiffword rem such as these are not of direct interest and have been added
+ spiffword rem soley for the purpose of controlling the spiffing process.
+ spiffword rem OK. Now we'll try changing some things. first, we'll add 
+ spiffword rem a commenting convention, everything from # to end of line
+ spiffword rem will be ignored.
+ spiffword comment # $
+ there should be NO differences on this line !!!! # No difference here !!
+ spiffword rem Well, that was fun. Now we'll ignore all differences
+ spiffword tol i
+ spiffword rem and there should be no differences the following lines
+ no difference --> 0.0000000001  NO difference --> 0.00000000011
+ no difference --> 10.000000001  NO difference --> 10.0000000011
+ spiffword rem now we'll set the tolerance for the second number
+ spiffword rem on each line, to be lower than the others.
+ spiffword tol a0.02 ; a0.01 ; a0.02
+ spiffword rem and only the middle number should appear different
+ not different --> 0.011  different --> 0.011  not different --> 0.011  
+ spiffword rem You get the idea. Enough fun for now.
+ All done.


Index: llvm/test/Programs/MultiSource/Applications/spiff/command.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/command.c:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/command.c	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,192 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ 
+ #ifndef lint
+ static char rcsid[]= "$Header: /home/vadve/shared/PublicCVS/llvm/test/Programs/MultiSource/Applications/spiff/command.c,v 1.1 2004/06/01 20:35:58 gaeke Exp $";
+ #endif
+ 
+ 
+ #include "misc.h"
+ #include "tol.h"
+ #include "comment.h"
+ #include "command.h"
+ #include "strings.h"
+ #include "parse.h"
+ 
+ /*
+ **	storage for the string that signals an embedded command
+ */
+ static char _C_cmdword[Z_WORDLEN];
+ 
+ /*
+ **	storage for the command script
+ */
+ static int _C_nextcmd = 0;
+ static char *_C_cmds[_C_CMDMAX];
+ 
+ 
+ /*
+ **	add a string to the command buffer
+ */
+ void
+ C_addcmd(str)
+ char *str;
+ {
+ 	S_savestr(&_C_cmds[_C_nextcmd++],str);
+ 	return;
+ }
+ 
+ /*
+ **	execute a single command
+ */
+ static void
+ _C_do_a_cmd(str)
+ char *str;
+ {
+ 	/*
+ 	**	place holder for the beginning of the string
+ 	*/
+ 	char *beginning = str;
+ 
+ 	S_skipspace(&str);
+ 
+ 	/*
+ 	**	set the command string to allow embedded commands
+ 	*/
+ 	if 	(!S_wordcmp(str,"command"))
+ 	{
+ 		S_nextword(&str);
+ 		if (strlen(str) >= Z_WORDLEN)
+ 		{
+ 			Z_fatal("command word is too long");
+ 		}
+ 		S_wordcpy(_C_cmdword,str);
+ 	}
+ 	/*
+ 	**	set the tolerances
+ 	*/
+ 	else if (!S_wordcmp(str,"tol"))
+ 	{
+ 		S_nextword(&str);
+ 		T_tolline(str);
+ 	}
+ 	/*
+ 	**	add a comment specification
+ 	*/
+ 	else if (!S_wordcmp(str,"comment"))
+ 	{
+ 		S_nextword(&str);
+ 		if (strlen(str) >= Z_WORDLEN)
+ 		{
+ 			Z_fatal("command word is too long");
+ 		}
+ 		W_addcom(str,0);
+ 	}
+ 	else if (!S_wordcmp(str,"nestcom"))
+ 	{
+ 		S_nextword(&str);
+ 		if (strlen(str) >= Z_WORDLEN)
+ 		{
+ 			Z_fatal("command word is too long");
+ 		}
+ 		W_addcom(str,1);
+ 	}
+ 	/*
+ 	**	add a literal string specification
+ 	*/
+ 	else if (!S_wordcmp(str,"literal"))
+ 	{
+ 		S_nextword(&str);
+ 		if (strlen(str) >= Z_WORDLEN)
+ 		{
+ 			Z_fatal("command word is too long");
+ 		}
+ 		W_addlit(str);
+ 	}
+ 	else if (!S_wordcmp(str,"resetcomments"))
+ 	{
+ 		W_clearcoms();
+ 	}
+ 	else if (!S_wordcmp(str,"resetliterals"))
+ 	{
+ 		W_clearlits();
+ 	}
+ 	else if (!S_wordcmp(str,"beginchar"))
+ 	{
+ 		S_nextword(&str);
+ 		W_setbolchar(*str);
+ 	}
+ 	else if (!S_wordcmp(str,"endchar"))
+ 	{
+ 		S_nextword(&str);
+ 		W_seteolchar(*str);
+ 	}
+ 	else if (!S_wordcmp(str,"addalpha"))
+ 	{
+ 		S_nextword(&str);
+ 		P_addalpha(str);
+ 	}
+ 	else if ((0 == strlen(str)) || !S_wordcmp(str,"rem") 
+ 				    || ('#' == *str))
+ 	{
+ 		/* do nothing */
+ 	}
+ 	else
+ 	{
+ 		(void) sprintf(Z_err_buf,
+ 			       "don't understand command %s\n",
+ 			       beginning);
+ 		Z_fatal(Z_err_buf);
+ 	}
+ 	return;
+ }
+ 
+ /*
+ **	execute the commands in the command buffer
+ */
+ void
+ C_docmds()
+ {
+ 	int i;
+ 	for (i=0;i<_C_nextcmd;i++)
+ 	{
+ 		_C_do_a_cmd(_C_cmds[i]);
+ 	}
+ 	return;
+ }
+ 
+ /*
+ **	disable embedded command key word recognition
+ */
+ void
+ C_clear_cmd()
+ {
+ 	_C_cmdword[0] = '\0';
+ 	return;
+ }
+ 
+ int
+ C_is_cmd(in_line)
+ char *in_line;
+ {
+ 	char *ptr;
+ 	/*
+ 	**	see if this is a command line
+ 	**	and if so, do the command right away
+ 	*/
+ 	if (('\0' != _C_cmdword[0]) && (!S_wordcmp(in_line,_C_cmdword)))
+ 	{
+ 		ptr = in_line;
+ 		S_nextword(&ptr);
+ 		_C_do_a_cmd(ptr);
+ 		return(1);
+ 	}
+ 	return(0);
+ }
+ 


Index: llvm/test/Programs/MultiSource/Applications/spiff/command.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/command.h:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/command.h	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,18 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ #ifndef C_INCLUDED
+ extern int C_is_cmd();
+ extern void C_clear_cmd();
+ extern void C_addcmd();
+ extern void C_docmds();
+ 
+ #define _C_CMDMAX	100
+ 
+ #define C_INCLUDED
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/spiff/comment.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/comment.c:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/comment.c	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,311 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ 
+ #ifndef lint
+ static char rcsid[]= "$Header: /home/vadve/shared/PublicCVS/llvm/test/Programs/MultiSource/Applications/spiff/comment.c,v 1.1 2004/06/01 20:35:58 gaeke Exp $";
+ #endif
+ 
+ 
+ #include "misc.h"
+ #include "comment.h"
+ #include "strings.h"
+ 
+ /*
+ **	storage for the comment specifiers that can appear
+ **		anywhere on a line
+ */
+ static int _W_nextcom = 0;
+ _W_comstruct _W_coms[_W_COMMAX];
+ 
+ /*
+ **	storage for comment specifiers that are examined only at the
+ **		beginning of each line
+ */
+ static int _W_nextbol = 0;
+ _W_bolstruct _W_bols[_W_BOLMAX];
+ 
+ /*
+ **	storage for delimiters of literal strings
+ */
+ static int _W_nextlit = 0;
+ _W_litstruct _W_lits[_W_LITMAX];
+ 
+ /*
+ **	storage for characters to specify beginning and end of line
+ **	in the comment and literal commands
+ */
+ char _W_bolchar = '^';
+ char _W_eolchar = '$';
+ 
+ 
+ /*
+ **	build up a list of comment delimiters
+ */
+ void
+ W_addcom(str,nestflag)
+ char *str;
+ int nestflag;
+ {
+ 	/*
+ 	**	check for comments that begin at the beginning of line
+ 	*/
+ 	if (*str ==  _W_bolchar)
+ 	{
+ 		if (_W_nextbol >= _W_BOLMAX)
+ 			Z_fatal("too many beginning of line comment delimiter sets");
+ 
+ 		str++;	/*skip the bol char */
+ 		S_wordcpy(_W_bols[_W_nextbol].begin,str);
+ 
+ 		S_nextword(&str);
+ 
+ 		if (*str == _W_eolchar)
+ 		{
+ 			(void) strcpy(_W_bols[_W_nextbol].end,"\n");
+ 		}
+ 		else
+ 		{
+ 			S_wordcpy(_W_bols[_W_nextbol].end,str);
+ 		}
+ 
+ 		S_nextword(&str);
+ 		S_wordcpy(_W_bols[_W_nextbol].escape,str);
+ 
+ 		/*
+ 		**
+ 		*/
+ 		if (nestflag)
+ 			Z_complain("begining of line comment won't nest");
+ 
+ 		_W_nextbol++;
+ 	}
+ 	else
+ 	{
+ 		if (_W_nextcom >= _W_COMMAX)
+ 			Z_fatal("too many comment delimiter sets");
+ 
+ 		S_wordcpy(_W_coms[_W_nextcom].begin,str);
+ 
+ 		S_nextword(&str);
+ 
+ 		if (*str == _W_eolchar)
+ 		{
+ 			(void) strcpy(_W_coms[_W_nextbol].end,"\n");
+ 		}
+ 		else
+ 		{
+ 			S_wordcpy(_W_coms[_W_nextbol].end,str);
+ 		}
+ 
+ 		S_nextword(&str);
+ 		S_wordcpy(_W_coms[_W_nextcom].escape,str);
+ 
+ 		_W_coms[_W_nextcom].nestbit = nestflag;
+ 
+ 		_W_nextcom++;
+ 	}
+ 	return;
+ }
+ 
+ 
+ /*
+ **	clear the comment delimiter storage
+ */
+ void
+ W_clearcoms()
+ {
+ 	_W_nextcom = 0;
+ 	_W_nextbol = 0;
+ 	return;
+ }
+ 
+ /*
+ **	build up the list of literal delimiters
+ */
+ void
+ W_addlit(str)
+ char *str;
+ {
+ 	if (_W_nextlit >= _W_LITMAX)
+ 		Z_fatal("too many literal delimiter sets");
+ 
+ 	S_wordcpy(_W_lits[_W_nextlit].begin,str);
+ 
+ 	S_nextword(&str);
+ 	S_wordcpy(_W_lits[_W_nextlit].end,str);
+ 
+ 	S_nextword(&str);
+ 	S_wordcpy(_W_lits[_W_nextlit].escape,str);
+ 
+ 	_W_nextlit++;
+ 	return;
+ }
+ 
+ /*
+ **	clear the literal delimiter storage
+ */
+ void
+ W_clearlits()
+ {
+ 	_W_nextlit = 0;
+ 	return;
+ }
+ 
+ 
+ 
+ static _W_bolstruct bol_scratch;
+ 
+ static void
+ _W_copybol(to,from)
+ W_bol to,from;
+ {
+ 	(void) strcpy(to->begin,from->begin);
+ 	(void) strcpy(to->end,from->end);
+ 	(void) strcpy(to->escape,from->escape);
+ }
+ 
+ W_bol
+ W_isbol(str)
+ char *str;
+ {
+ 	int i;
+ 
+ 	for(i=0;i<_W_nextbol;i++)
+ 	{
+ 		if(!S_wordcmp(str,_W_bols[i].begin))
+ 		{
+ 			_W_copybol(&bol_scratch,&_W_bols[i]);
+ 			return(&bol_scratch);
+ 		}
+ 	}
+ 	return(W_BOLNULL);
+ }
+ 
+ int
+ W_is_bol(ptr)
+ W_bol ptr;
+ {
+ 	int i;
+ 
+ 	for(i=0;i<_W_nextbol;i++)
+ 	{
+ 		if(!S_wordcmp(ptr->begin,_W_bols[i].begin) &&
+ 			!S_wordcmp(ptr->end,_W_bols[i].end) &&
+ 			!S_wordcmp(ptr->escape,_W_bols[i].escape))
+ 		{
+ 			return(1);
+ 		}
+ 
+ 	}
+ 	return(0);
+ }
+ 
+ 
+ static _W_litstruct lit_scratch;
+ 
+ static void
+ _W_copylit(to,from)
+ W_lit to,from;
+ {
+ 	(void) strcpy(to->begin,from->begin);
+ 	(void) strcpy(to->end,from->end);
+ 	(void) strcpy(to->escape,from->escape);
+ }
+ 
+ W_lit
+ W_islit(str)
+ char *str;
+ {
+ 	int i;
+ 
+ 	for(i=0;i<_W_nextlit;i++)
+ 	{
+ 		if(!S_wordcmp(str,_W_lits[i].begin))
+ 		{
+ 			_W_copylit(&lit_scratch,&_W_lits[i]);
+ 			return(&lit_scratch);
+ 		}
+ 	}
+ 	return(W_LITNULL);
+ }
+ 
+ int
+ W_is_lit(ptr)
+ W_lit ptr;
+ {
+ 	int i;
+ 
+ 	for(i=0;i<_W_nextlit;i++)
+ 	{
+ 		if(!S_wordcmp(ptr->begin,_W_lits[i].begin) &&
+ 			!S_wordcmp(ptr->end,_W_lits[i].end) &&
+ 			!S_wordcmp(ptr->escape,_W_lits[i].escape))
+ 		{
+ 			return(1);
+ 		}
+ 
+ 	}
+ 	return(0);
+ }
+ 
+ static _W_comstruct com_scratch;
+ 
+ static void
+ _W_copycom(to,from)
+ W_com to,from;
+ {
+ 	(void) strcpy(to->begin,from->begin);
+ 	(void) strcpy(to->end,from->end);
+ 	(void) strcpy(to->escape,from->escape);
+ 	to->nestbit = from->nestbit;
+ }
+ 
+ W_com
+ W_iscom(str)
+ char *str;
+ {
+ 	int i;
+ 
+ 	for(i=0;i<_W_nextcom;i++)
+ 	{
+ 		if(!S_wordcmp(str,_W_coms[i].begin))
+ 		{
+ 			_W_copycom(&com_scratch,&_W_coms[i]);
+ 			return(&com_scratch);
+ 		}
+ 	}
+ 	return(W_COMNULL);
+ }
+ 
+ int
+ W_is_com(ptr)
+ W_com ptr;
+ {
+ 	int i;
+ 
+ 	for(i=0;i<_W_nextcom;i++)
+ 	{
+ 		if(!S_wordcmp(ptr->begin,_W_coms[i].begin) &&
+ 			!S_wordcmp(ptr->end,_W_coms[i].end) &&
+ 			!S_wordcmp(ptr->escape,_W_coms[i].escape) &&
+ 			ptr->nestbit == _W_coms[i].nestbit)
+ 		{
+ 			return(1);
+ 		}
+ 
+ 	}
+ 	return(0);
+ }
+ 
+ int
+ W_is_nesting(ptr)
+ W_com ptr;
+ {
+ 	return(ptr->nestbit);
+ }


Index: llvm/test/Programs/MultiSource/Applications/spiff/comment.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/comment.h:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/comment.h	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,85 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ #ifndef W_INCLUDED
+ 
+ #include <stdio.h>
+ 
+ #define _W_COMWORD	16
+ #define _W_COMMAX	20
+ #define _W_BOLMAX	20
+ #define _W_LITMAX	20
+ 
+ /*
+ **	these three data structures used to be much
+ **		different.  eventually, the differences
+ **		have disappeared as the code has evolved.
+ **		obviously, they should now be collapsed.
+ **		someday . . .
+ */
+ typedef struct {
+ 	char begin[_W_COMWORD];
+ 	char end[_W_COMWORD];
+ 	char escape[_W_COMWORD];
+ } _W_bolstruct, *W_bol;
+ 
+ typedef struct {
+ 	char begin[_W_COMWORD];
+ 	char end[_W_COMWORD];
+ 	char escape[_W_COMWORD];
+ 	int nestbit;
+ } _W_comstruct, *W_com;
+ 
+ typedef struct {
+ 	char begin[_W_COMWORD];
+ 	char end[_W_COMWORD];
+ 	char escape[_W_COMWORD];
+ } _W_litstruct, *W_lit;
+ 
+ #define W_bolbegin(ptr)		(ptr->begin)
+ #define W_bolend(ptr)		(ptr->end)
+ #define W_bolescape(ptr)	(ptr->escape)
+ 
+ #define W_litbegin(ptr)		(ptr->begin)
+ #define W_litend(ptr)		(ptr->end)
+ #define W_litescape(ptr)	(ptr->escape)
+ 
+ #define W_combegin(ptr)		(ptr->begin)
+ #define W_comend(ptr)		(ptr->end)
+ #define W_comescape(ptr)	(ptr->escape)
+ 
+ extern char _W_bolchar;
+ extern char _W_eolchar;
+ 
+ #define W_setbolchar(x)		(_W_bolchar = x)
+ #define W_seteolchar(x)		(_W_eolchar = x)
+ 
+ extern W_bol W_isbol();
+ extern W_lit W_islit();
+ extern W_com W_iscom();
+ 
+ extern int W_is_bol();
+ extern int W_is_lit();
+ extern int W_is_com();
+ extern int W_is_nesting(W_com ptr);
+ 
+ extern _W_bolstruct _W_bols[];
+ extern _W_litstruct _W_lits[];
+ extern _W_comstruct _W_coms[];
+ 
+ extern void W_clearcoms();
+ extern void W_clearlits();
+ extern void W_addcom();
+ extern void W_addlit();
+ 
+ #define W_BOLNULL		((W_bol)0)
+ #define W_COMNULL		((W_com)0)
+ #define W_LITNULL		((W_lit)0)
+ 
+ #define W_INCLUDED
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/spiff/compare.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/compare.c:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/compare.c	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,205 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ 
+ #ifndef lint
+ static char rcsid[]= "$Header: /home/vadve/shared/PublicCVS/llvm/test/Programs/MultiSource/Applications/spiff/compare.c,v 1.1 2004/06/01 20:35:58 gaeke Exp $";
+ #endif
+ 
+ #include "misc.h"
+ #include "flagdefs.h"
+ #include "tol.h"
+ #include "token.h"
+ #include "line.h"
+ #include "float.h"
+ #include "compare.h"
+ 
+ #include <ctype.h>
+ 
+ static int _X_strcmp(char *s1,char *s2,int flags);
+ static int _X_cmptokens(K_token p1,K_token p2,int flags);
+ static int _X_floatdiff(F_float p1,F_float p2,T_tol the_tol);
+ 
+ int
+ X_com(a,b,flags)
+ int a,b,flags;
+ {
+ 	K_token atmp,btmp;
+ 
+ 	atmp = K_gettoken(0,a);
+ 	btmp = K_gettoken(1,b);
+ 	if(flags & U_BYTE_COMPARE)
+ 	{
+ 		return(_X_strcmp(K_gettext(atmp),K_gettext(btmp),flags));
+ 	}
+ 	else
+ 	{
+ 		return(_X_cmptokens(atmp,btmp,flags));
+ 	}
+ #ifndef lint 
+ 	Z_fatal("this line should never be reached in com");
+ 	return(-1);	/* Z_fatal never returns, but i need a this line
+ 				here to stop lint from complaining */
+ #endif
+ }
+ 
+ /*
+ **	same as strcmp() except that case can be optionally ignored
+ */
+ static int _X_strcmp(char *s1,char *s2,int flags)
+ {
+ 	if (flags & U_NO_CASE)
+ 	{
+ 		
+ 		for (;('\0' != s1) && ('\0' !=  *s2);s1++,s2++)
+ 		{
+ 			if(isalpha(*s1) && isalpha(*s2))
+ 			{
+ 				if(tolower(*s1) != tolower(*s2))
+ 				{
+ 					return(1);
+ 				}
+ 			}
+ 			else
+ 			{
+ 				if(*s1!=*s2)
+ 				{
+ 					return(1);
+ 				}
+ 			}
+ 		}
+ 		return(*s1 != *s2);
+ 	}
+ 	else
+ 	{
+ 		return(strcmp(s1,s2));
+ 	}
+ }
+ 
+ 
+ /*
+ **	routine to compare two tokens
+ */
+ static int _X_cmptokens(K_token p1,K_token p2,int flags)
+ {
+ 	if (K_gettype(p1) !=  K_gettype(p2))
+ 	{
+ 		return(1);
+ 	}
+ 
+ 	switch (K_gettype(p1))
+ 	{
+ 		case K_LIT:
+ 			return(_X_strcmp(K_gettext(p1),K_gettext(p2),flags));
+ 		case K_FLO_NUM:
+ 			return(_X_floatdiff(K_getfloat(p1),
+ 					   K_getfloat(p2),
+ 					   T_picktol(K_gettol(p1),
+ 						     K_gettol(p2))));
+ 		default:
+ 			Z_fatal("fell off switch in _X_cmptokens");
+ 			return(-1);	/* Z_fatal never returns, but i need a this line
+ 						here to stop lint from complaining */
+ 	}
+ 
+ }
+ 
+ /*
+ **	compare two F_floats using a tolerance
+ */
+ static int _X_floatdiff(F_float p1,F_float p2,T_tol the_tol)
+ {
+ 	F_float diff, float_tmp;
+ 	T_tol tol_tmp;
+ 
+ 	/*
+ 	** 	check for null tolerance list
+ 	*/
+ 	if (T_isnull(the_tol))
+ 	{
+ 		Z_fatal("_X_floatdiff called with a null tolerance");
+ 	}
+ 
+ 	/*
+ 	**	look for an easy answer. i.e -- check
+ 	**		to see if any of the tolerances are of type T_IGNORE
+ 	**		or if the numbers are too small to exceed an absolute
+ 	**		tolerance.
+ 	**		if so, return immediately
+ 	*/
+ 	for(tol_tmp=the_tol; !(T_isnull(tol_tmp)) ;tol_tmp=T_getnext(tol_tmp))
+ 	{
+ 		if ((T_IGNORE == T_gettype(tol_tmp)) || 
+ 			/*
+ 			**	take a look at the exponents before you bother
+ 			**	with the mantissas
+ 			*/
+ 			((T_ABSOLUTE == T_gettype(tol_tmp))
+ 				   && !F_zerofloat(T_getfloat(tol_tmp))
+ 				   && (F_getexp(p1) <
+ 					F_getexp(T_getfloat(tol_tmp))-1)
+ 				   && (F_getexp(p2) <
+ 					F_getexp(T_getfloat(tol_tmp))-1)))
+ 		{
+ 				return(0);
+ 		}
+ 	}
+ 
+ 	
+ 	/*
+ 	**	ok, we're going to have to do some arithmetic, so
+ 	**		first find the magnitude of the difference
+ 	*/
+ 	if (F_getsign(p1) != F_getsign(p2))
+ 	{
+ 		diff = F_floatmagadd(p1,p2);
+ 	}
+ 	else
+ 	{
+ 		diff = F_floatsub(p1,p2);
+ 	}
+ 
+ 	/*
+ 	**	now check to see if the difference exceeds any tolerance
+ 	*/
+ 	for(tol_tmp=the_tol; !(T_isnull(tol_tmp)) ;tol_tmp=T_getnext(tol_tmp))
+ 	{
+ 		float_tmp = T_getfloat(tol_tmp);
+ 
+ 		if (T_gettype(tol_tmp) == T_ABSOLUTE)
+ 		{
+ 			/* do nothing */
+ 		}
+ 		else if (T_gettype(tol_tmp) == T_RELATIVE)
+ 		{
+ 			if (F_floatcmp(p1,p2) > 0)
+ 			{
+ 				float_tmp = F_floatmul(p1, float_tmp);
+ 			}
+ 			else
+ 			{
+ 				float_tmp = F_floatmul(p2, float_tmp);
+ 			}
+ 		}
+ 		else
+ 		{
+ 			Z_fatal("bad value for type of tolerance in floatdiff");
+ 		}
+ 		/*
+ 		**	if we pass this tolerance, then we're done
+ 		*/
+ 		if (F_floatcmp(diff,float_tmp) <= 0)
+ 		{
+ 			return(0);
+ 		}
+ 	}
+ 	/*
+ 	**	all of the tolerances were exceeded
+ 	*/
+ 	return(1);
+ }


Index: llvm/test/Programs/MultiSource/Applications/spiff/compare.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/compare.h:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/compare.h	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,14 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ #ifndef X_INCLUDED
+ 
+ extern int X_com();
+ 
+ #define X_INCLUDED
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/spiff/edit.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/edit.h:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/edit.h	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,43 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ /*
+ **	the naming information hiding conventions are incompletely implemented
+ **	 for the edit module. I tried to clean it up once, but kept introducing
+ **	 nasty (ie. core dump) bugs in the miller code.  I give up for now.
+ */
+ #ifndef E_INCLUDED
+ 
+ #define E_INSERT	1
+ #define E_DELETE	2
+ 
+ typedef struct edt {
+ 	struct edt *link;
+ 	int op;
+ 	int line1;
+ 	int line2;
+ } _E_struct, *E_edit;
+ 
+ #define E_setop(x,y)		((x)->op = (y))
+ #define E_setl1(x,y)		((x)->line1 = (y))
+ #define E_setl2(x,y)		((x)->line2 = (y))
+ #define E_setnext(x,y)		((x)->link = (y))
+ 
+ #define E_getop(x)		((x)->op)
+ #define E_getl1(x)		((x)->line1)
+ #define E_getl2(x)		((x)->line2)
+ #define E_getnext(x)		((x)->link)
+ 
+ #define E_NULL 		((E_edit) 0)
+ #define E_edit_alloc()	(Z_ALLOC(1,_E_struct))
+ 
+ #define E_INCLUDED
+ 
+ #endif
+ 
+ 


Index: llvm/test/Programs/MultiSource/Applications/spiff/exact.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/exact.c:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/exact.c	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,93 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ 
+ #ifndef lint
+ static char rcsid[]= "$Header: /home/vadve/shared/PublicCVS/llvm/test/Programs/MultiSource/Applications/spiff/exact.c,v 1.1 2004/06/01 20:35:58 gaeke Exp $";
+ #endif
+ 
+ #include "misc.h"
+ #include "edit.h"
+ #include "compare.h"
+ 
+ /*
+ **	routine to compare each object with its ordinal twin
+ */
+ E_edit
+ Q_do_exact(size1,size2,max_d,comflags)
+ int size1;
+ int size2;
+ int max_d;
+ int comflags;
+ {
+ 	int i = 0;
+ 	int diffcnt = 0;
+ 	int last = Z_MIN(size1,size2);
+ 	int next_edit = 0;
+ 	E_edit last_ptr = E_NULL;
+ 	int start,tmp;
+ 	E_edit *script;
+ 
+ 	script = Z_ALLOC(max_d+1,E_edit);
+ 
+ 	if (size1 != size2)
+ 	{
+ 		(void) sprintf(Z_err_buf,"unequal number of tokens, %d and %d respectively\n",size1,size2);
+ 		Z_complain(Z_err_buf);
+ 	}
+ 
+ 	do
+ 	{
+ 		/*
+ 		**	skip identical objects
+ 		*/
+ 		while (i<last && (!X_com(i,i,comflags)))
+ 		{
+ 			i++;
+ 		}
+ 		start = i;
+ 		/*
+ 		**	see how many difference we have in a row
+ 		*/
+ 		while (i<last && X_com(i,i,comflags))
+ 		{
+ 			if ((diffcnt += 2) >= max_d+1)
+ 				Z_exceed(max_d);
+ 			i++;
+ 		}
+ 		/*
+ 		**	build the list of deletions
+ 		*/
+ 		for(tmp=start;tmp<i;tmp++,next_edit++)
+ 		{
+ 			script[next_edit] = E_edit_alloc();
+ 			E_setnext(script[next_edit],last_ptr);
+ 			last_ptr = script[next_edit];
+ 
+ 			E_setop(script[next_edit],E_DELETE);
+ 			E_setl1(script[next_edit],tmp+1);
+ 			/* no need to set line2, it is never used */
+ 			E_setl2(script[next_edit],0);
+ 		}
+ 		/*
+ 		**	build the list of insertions
+ 		*/
+ 		for(tmp=start;tmp<i;tmp++,next_edit++)
+ 		{
+ 			script[next_edit] = E_edit_alloc();
+ 			E_setnext(script[next_edit],last_ptr);
+ 			last_ptr = script[next_edit];
+ 
+ 			E_setop(script[next_edit],E_INSERT);
+ 			E_setl1(script[next_edit],i);
+ 			E_setl2(script[next_edit],tmp+1);
+ 		}
+ 	} while (i<last);
+ 
+ 	return(last_ptr);
+ }


Index: llvm/test/Programs/MultiSource/Applications/spiff/exact.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/exact.h:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/exact.h	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,17 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ #ifndef Q_INCLUDED
+ 
+ #include "edit.h"
+ 
+ extern E_edit Q_do_exact();
+ 
+ #define Q_INCLUDED
+ 
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/spiff/flagdefs.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/flagdefs.h:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/flagdefs.h	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,29 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ /*
+ **	flags used by both parser and comparison routines
+ */
+ #define U_INCLUDE_WS	001
+ 
+ /*
+ **	flags used only by the comparison routines
+ */
+ #define U_BYTE_COMPARE		002
+ #define U_NO_CASE		004
+ 
+ /*
+ **	flag used by the output routine
+ */
+ #define U_TOKENS		010
+ 
+ /*
+ **	flags used only by the parser
+ */
+ #define U_INC_SIGN	020
+ #define U_NEED_DECIMAL	040


Index: llvm/test/Programs/MultiSource/Applications/spiff/float.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/float.c:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/float.c	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,813 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ 
+ #ifndef lint
+ static char rcsid[]= "$Header: /home/vadve/shared/PublicCVS/llvm/test/Programs/MultiSource/Applications/spiff/float.c,v 1.1 2004/06/01 20:35:58 gaeke Exp $";
+ #endif
+ 
+ #include <ctype.h>
+ #include "misc.h"
+ #include "floatrep.h"
+ #include "float.h"
+ #include "strings.h"
+ 
+ #define _F_GETEND(x)	(x + (strlen(x)-1)) 
+ 
+ /*
+ int floatcnt = 0;
+ */
+ /*
+ **	routines to convert strings to our internal floating point form
+ **		isfloat just looks at the string
+ **		to see if a conversion is reasonable
+ **			it does look-ahead on when it sees an 'e' and such.
+ **		atocf actually does the conversion.
+ **	these two routines could probably be combined
+ */
+ 
+ /*
+ **	test to see if the string can reasonably
+ **		be interpreted as floating point number
+ **	returns 0 if string can't be interpreted as a float
+ **	otherwise returns the number of digits that will be used in F_atof
+ */
+ int
+ F_isfloat(str,need_decimal,allow_sign)
+ char *str;
+ int need_decimal;	/* if non-zero, require that a decimal point be present
+ 				otherwise, accept strings like "123" */
+ int allow_sign;		/* if non-zero, allow + or - to set the sign */
+ {
+ 	int man_length = 0;	/* length of the fractional part (mantissa) */
+ 	int exp_length = 0;	/* length of the exponential part */
+ 	int got_a_digit = 0;	/* flag to set if we ever see a digit */
+ 
+ 	/*
+ 	**	look for an optional leading sign marker
+ 	*/
+ 	if (allow_sign && ('+' == *str  || '-' == *str))
+ 	{
+ 		str++; man_length++;
+ 	}
+ 	/*
+ 	**	count up the digits on the left hand side
+ 	**		 of the decimal point
+ 	*/
+ 	while(isdigit(*str))
+ 	{
+ 		got_a_digit = 1;
+ 		str++; man_length++;
+ 	}
+ 
+ 	/*
+ 	**	check for a decimal point
+ 	*/
+ 	if ('.' == *str)
+ 	{
+ 		str++; man_length++;
+ 	}
+ 	else
+ 	{
+ 		if (need_decimal)
+ 		{
+ 			return(0);
+ 		}
+ 	}
+ 
+ 	/*
+ 	**	collect the digits on the right hand
+ 	**		side of the decimal point
+ 	*/
+ 	while(isdigit(*str))
+ 	{
+ 		got_a_digit = 1;
+ 		str++; man_length++;
+ 	}
+ 
+ 	if (!got_a_digit)
+ 		return(0);
+ 
+ 	/*
+ 	**	now look ahead for an exponent
+ 	*/
+ 	if ('e' == *str ||
+ 	    'E' == *str ||
+ 	    'd' == *str ||
+ 	    'D' == *str)
+ 	{
+ 		str++; exp_length++;
+ 		if ('+' == *str  || '-' == *str)
+ 		{
+ 			str++; exp_length++;
+ 		}
+ 
+ 		if (!isdigit(*str))
+ 		{
+ 			/*
+ 			**	look ahead went too far,
+ 			**	so return just the length of the mantissa
+ 			*/
+ 			return(man_length);
+ 		}
+ 
+ 		while (isdigit(*str))
+ 		{
+ 			str++; exp_length++;
+ 		}
+ 	}
+ 	return(man_length+exp_length);	/* return the total length */
+ }
+ 
+ /*
+ **	routine to convert a string to our internal
+ **	floating point representation
+ **
+ **		similar to atof()
+ */
+ F_float
+ F_atof(str,allflag)
+ char *str;
+ int allflag;	/* require that exactly all the characters are used */
+ {
+ 	char *beg = str; /* place holder for beginning of the string */ 
+ 	char man[R_MANMAX];	/* temporary location to build the mantissa */
+ 	int length = 0;	/* length of the mantissa so far */
+ 	int got_a_digit = 0;	/* flag to set if we get a non-zero digit */ 
+ 	int i;
+ 	int resexp;
+ 
+ 	F_float res;	/* where we build the result */
+ 
+ /*
+ floatcnt++;
+ */
+ 	res = R_makefloat();
+ 
+ 	R_setsign(res,R_POSITIVE);
+ 
+ 	resexp = 0;
+ 	man[0] = '\0';
+ 
+ 	/*
+ 	**	check for leading sign
+ 	*/
+ 	if ('+' == *str)
+ 	{
+ 		/*
+ 		**	sign should already be positive, see above in this
+ 		**		routine, so just skip the plus sign
+ 		*/
+ 		str++;
+ 	}
+ 	else
+ 	{
+ 		if ('-' == *str)
+ 		{
+ 			R_setsign(res,R_NEGATIVE);
+ 			str++;
+ 		}
+ 	}
+ 
+ 	/*
+ 	**	skip any leading zeros
+ 	*/
+ 	while('0' == *str)
+ 	{
+ 		str++;
+ 	}
+ 
+ 	/*
+ 	**	now snarf up the digits on the left hand side
+ 	**		of the decimal point
+ 	*/
+ 	while(isdigit(*str))
+ 	{
+ 		got_a_digit = 1;
+ 		man[length++] = *str++;
+ 		man[length] = '\0';
+ 		resexp++;
+ 	}
+ 
+ 	/*
+ 	**	skip the decimal point if there is one
+ 	*/
+ 	if ('.' == *str)
+ 		str++;
+ 
+ 	/*
+ 	**	trim off any leading zeros (on the right hand side)
+ 	**	if there were no digits in front of the decimal point.
+ 	*/
+ 
+ 	if (!got_a_digit)
+ 	{
+ 		while('0' == *str)
+ 		{
+ 			str++;
+ 			resexp--;
+ 		}
+ 	}
+ 
+ 	/*
+ 	**	now snarf up the digits on the right hand side
+ 	*/
+ 	while(isdigit(*str))
+ 	{
+ 		man[length++] = *str++;
+ 		man[length] = '\0';
+ 	}
+ 
+ 	if ('e' == *str ||
+             'E' == *str ||
+             'd' == *str ||
+             'D' == *str )
+ 	{
+ 		str++;
+ 		resexp += atoi(str);
+ 	}
+ 
+ 	if (allflag)
+ 	{
+ 		if ('+' == *str ||
+ 		    '-' == *str)
+ 		{
+ 			str++;
+ 		}
+ 		while (isdigit(*str))
+ 		{
+ 			str++;
+ 		}
+ 		if ('\0' != *str)
+ 		{
+ 			(void) sprintf(Z_err_buf,
+ 					"didn't use up all of %s in atocf",
+ 					beg);
+ 			Z_fatal(Z_err_buf);
+ 		}
+ 	}
+ 
+ 	/*
+ 	**	check for special case of all zeros in the mantissa
+ 	*/
+ 	for (i=0;i<length;i++)
+ 	{
+ 		if (man[i] != '0')
+ 		{
+ 			/*
+ 			**	the mantissa is non-zero, so return it unchanged
+ 			*/
+ 			S_trimzeros(man);
+ 			/*
+ 			**	save a copy of the mantissa
+ 			*/
+ 			R_setfrac(res,man);
+ 			R_setexp(res,resexp);
+ 			return(res);
+ 		}
+ 	}
+ 
+ 	/*
+ 	**	the answer is 0, so . . .
+ 	*/
+ 	R_setzero(res);
+ 	return(res);
+ }
+ 
+ 
+ /*
+ **	add s2 to s1
+ */
+ static
+ void
+ _F_stradd(s1,s2)
+ char *s1,*s2;
+ {
+ 	char *end1 = s1 + (strlen(s1)-1);
+ 	char *end2 = s2 + (strlen(s2)-1);
+ 
+ 	static char result[R_MANMAX];
+ 	char *resptr = result+(R_MANMAX-1); /*point to the end of the array */
+ 	int carry = 0;
+ 	int tmp,val1,val2;
+ 
+ 	*resptr-- = '\0';
+ 
+ 	while ((end1 >= s1) ||  ( end2 >= s2))
+ 	{
+ 		if (end1 >= s1)
+ 		{
+ 			val1 = *end1 - '0';
+ 			--end1;
+ 		}
+ 		else
+ 		{
+ 			val1 = 0;
+ 		}
+ 
+ 		if (end2 >= s2)
+ 		{
+ 			val2 = *end2 - '0';
+ 			--end2;
+ 		}
+ 		else
+ 		{
+ 			val2 = 0;
+ 		}
+ 
+ 		tmp = val1 + val2 + carry;
+ 		if (tmp > 9)
+ 		{
+ 			carry = 1;
+ 			tmp -= 10;
+ 		}
+ 		else
+ 		{
+ 			carry = 0;
+ 		}
+ 
+ 		*resptr-- = tmp+'0';
+ 	}
+ 	if (carry)
+ 	{
+ 		*resptr =  '1';
+ 	}
+ 	else
+ 	{
+ 		resptr++;
+ 	}
+ 	(void) strcpy(s1,resptr);
+ 	return;
+ }
+ 
+ /*
+ **	add zero(s) onto the end of a string
+ */
+ static void
+ addzeros(ptr,count)
+ char *ptr;
+ int count;
+ {
+ 	for(;count> 0;count--)
+ 	{
+ 		(void) strcat(ptr,"0");
+ 	}
+ 	return;
+ }
+ 
+ /*
+ **	subtract two mantissa strings
+ */
+ F_float
+ F_floatsub(p1,p2)
+ F_float  p1,p2;
+ {
+ 	static F_float result;
+ 	static int needinit = 1;
+ 	static char man1[R_MANMAX],man2[R_MANMAX],diff[R_MANMAX];
+ 	int exp1,exp2;
+ 	char *diffptr,*big,*small;
+ 	int man_cmp_val,i,borrow;
+ 
+ 	if (needinit)
+ 	{
+ 		result = R_makefloat();
+ 		needinit = 0;
+ 	}
+ 
+ 	man1[0] = '\0';
+ 	man2[0] = '\0';
+ 
+ 	exp1 = R_getexp(p1);
+ 	exp2 = R_getexp(p2);
+ 
+ 	/*
+ 	**	line up the mantissas
+ 	*/
+ 	while (exp1 < exp2)
+ 	{
+ 		(void) strcat(man1,"0");
+ 		exp1++;
+ 	}
+ 
+ 	while(exp1 > exp2)
+ 	{
+ 		(void) strcat(man2,"0");
+ 		exp2++;
+ 	}
+ 
+ 	if (exp1 != exp2)	/* boiler plate assertion */
+ 	{
+ 		Z_fatal("mantissas didn't get lined up properly in floatsub");
+ 	}
+ 
+ 	(void) strcat(man1,R_getfrac(p1));
+ 	(void) strcat(man2,R_getfrac(p2));
+ 	
+ 	/*
+ 	**	now that the mantissa are aligned,
+ 	**	if the strings are the same, return 0
+ 	*/
+ 	if((man_cmp_val = strcmp(man1,man2)) == 0)
+ 	{
+ 		R_setzero(result);
+ 		return(result);
+ 	}
+ 
+ 	/*
+ 	**	pad the shorter string with 0's
+ 	**		when this loop finishes, both mantissas should
+ 	**		have the same length
+ 	*/
+ 	if (strlen(man1)> strlen(man2))
+ 	{
+ 		addzeros(man2,strlen(man1)-strlen(man2));
+ 	}
+ 	else
+ 	{
+ 		if (strlen(man1)<strlen(man2))
+ 		{
+ 			addzeros(man1,strlen(man2)-strlen(man1));
+ 		}
+ 	}
+ 
+ 	if (strlen(man1) != strlen(man2))	/* pure boilerplate */
+ 	{
+ 		Z_fatal("lengths not equal in F_floatsub");
+ 	}
+ 
+ 	if (man_cmp_val < 0)
+ 	{
+ 		big = man2;
+ 		small = man1;
+ 	}
+ 	else
+ 	{
+ 		big = man1;
+ 		small = man2;
+ 	}
+ 
+ 	/*
+ 	**	find the difference between the mantissas
+ 	*/
+ 	for(i=(strlen(big)-1),borrow=0,diff[strlen(big)] = '\0';i>=0;i--)
+ 	{
+ 		char from;
+ 		if (borrow)
+ 		{
+ 			if (big[i] == '0')
+ 			{
+ 				from = '9';
+ 			}
+ 			else
+ 			{
+ 				from = big[i]-1;
+ 				borrow = 0;
+ 			}
+ 		}
+ 		else
+ 		{
+ 			if(big[i]<small[i])
+ 			{
+ 				from = '9'+1;
+ 				borrow = 1;
+ 			}
+ 			else
+ 			{
+ 				from = big[i];
+ 			}
+ 		}
+ 		diff[i] = (from-small[i]) + '0';
+ 	}
+ 
+ 	/*
+ 	** trim the leading zeros on the difference
+ 	*/
+ 	diffptr = diff;
+ 	while('0' == *diffptr)
+ 	{
+ 		diffptr++;
+ 		exp1--;
+ 	}
+ 
+ 	R_setexp(result,exp1); /* exponents are equal at the point */
+ 	R_setfrac(result,diffptr);
+ 	R_setsign(result,R_POSITIVE);
+ 	return(result);
+ }
+ 
+ int F_floatcmp(F_float f1,F_float f2)
+ {
+ 	static char man1[R_MANMAX],man2[R_MANMAX];
+ 
+ 	/*
+ 	**		special case for zero
+ 	*/
+ 	if (R_zerofloat(f1))
+ 	{
+ 		if (R_zerofloat(f2))
+ 		{
+ 			return(0);
+ 		}
+ 		else
+ 		{
+ 			return(-1);
+ 		}
+ 	}
+ 	else
+ 	{
+ 		if (R_zerofloat(f2))
+ 		{
+ 			return(1);
+ 		}
+ 	}
+ 
+ 	/*
+ 	**	to reach this point, both numbers must be non zeros
+ 	*/
+ 	if (R_getexp(f1) < R_getexp(f2))
+ 	{
+ 		return(-1);
+ 	}
+ 
+ 	if (R_getexp(f1) > R_getexp(f2))
+ 	{
+ 		return(1);
+ 	}
+ 
+ 	(void) strcpy(man1,R_getfrac(f1));
+ 	S_trimzeros(man1);
+ 
+ 	(void) strcpy(man2,R_getfrac(f2));
+ 	S_trimzeros(man2);
+ 	return(strcmp(man1,man2));
+ }
+ 
+ F_float
+ F_floatmul(f1,f2)
+ F_float f1,f2;
+ {
+ 	static char prod[R_MANMAX];
+ 	char *end;
+ 	int count1 = 0;
+ 	int count2 = 0;
+ 	int tmp,len;
+ 	char *end1;
+ 	char *end2;
+ 	static char man1[R_MANMAX],man2[R_MANMAX];
+ 	char *bigman,*smallman;
+ 	static F_float result;
+ 	static int needinit = 1;
+ 
+ 	if (needinit)
+ 	{
+ 		result = R_makefloat();
+ 		needinit = 0;
+ 	}
+ 	/*
+ 	**	special case for a zero result
+ 	*/
+ 	if (R_zerofloat(f1) || R_zerofloat(f2))
+ 	{
+ 		R_setzero(result);
+ 		return(result);
+ 	}
+ 
+ 	(void) strcpy(man1,R_getfrac(f1));
+ 	(void) strcpy(man2,R_getfrac(f2));
+ 
+ 	end1 = _F_GETEND(man1);
+ 	end2 = _F_GETEND(man2);
+ 
+ 	/*
+ 	**	decide which number will cause multiplication loop to go
+ 	**	around the least
+ 	*/
+ 	while(end1 >= man1)
+ 	{
+ 		count1 += *end1 - '0';
+ 		end1--;
+ 	}
+ 
+ 	while(end2 >= man2)
+ 	{
+ 		count2 += *end2 - '0';
+ 		end2--;
+ 	}
+ 
+ 
+ 	if (count1 > count2)
+ 	{
+ 		bigman = man1;
+ 		smallman = man2;
+ 	}
+ 	else
+ 	{
+ 		bigman = man2;
+ 		smallman = man1;
+ 	}
+ 	S_trimzeros(bigman);
+ 	S_trimzeros(smallman);
+ 	len = strlen(bigman) +  strlen(smallman);
+ 
+ 	end = _F_GETEND(smallman);
+ 	(void) strcpy(prod,"0");
+ 
+ 	/*
+ 	**	multiplication by repeated addition
+ 	*/
+ 	while(end >= smallman)
+ 	{
+ 		for(tmp = 0;tmp<*end-'0';tmp++)
+ 		{
+ 			_F_stradd(prod,bigman);
+ 		}
+ 		addzeros(bigman,1);
+ 		end--;
+ 	}
+ 
+ 	R_setfrac(result,prod);
+ 	R_setexp(result,(((R_getexp(f1) + R_getexp(f2)) - len)+ strlen(prod)));
+ 
+ 	if (R_getsign(f1) == R_getsign(f2))
+ 	{
+ 		R_setsign(result,R_POSITIVE);
+ 	}
+ 	else
+ 	{
+ 		R_setsign(result,R_NEGATIVE);
+ 	}
+ 	return(result);
+ }
+ 
+ int
+ _F_xor(x,y)
+ {
+ 	return(((x) && !(y)) || (!(x) && (y)));
+ }
+ #define	_F_SAMESIGN(x,y)	_F_xor((x<0),(y<0))
+ #define _F_ABSADD(x,y)		(Z_ABS(x) + Z_ABS(y))
+ 
+ int
+ _F_ABSDIFF(x,y)
+ {
+ 	if (Z_ABS(x) < Z_ABS(y))
+ 	{
+ 		return(Z_ABS(y) - Z_ABS(x));
+ 	}
+ 	else
+ 	{
+ 		return(Z_ABS(x) - Z_ABS(y));
+ 	}
+ }
+ /*
+ **	add two floats without regard to sign
+ */
+ F_float
+ F_floatmagadd(p1,p2)
+ F_float p1,p2;
+ {
+ 	static F_float result;
+ 	static int needinit = 1;
+ 
+ 	static char  man1[R_MANMAX],man2[R_MANMAX];
+ 
+ 	int digits;	/* count of the number of digits needed to represent the
+ 				result */
+ 	int resexp;	/* exponent of the result */
+ 	int len;	/* length of the elements before adding */
+ 	char *diffptr;
+ 
+ 	if (needinit)
+ 	{
+ 		result = R_makefloat();
+ 		needinit = 0;
+ 	}
+ 	(void) strcpy(man1,"");
+ 	(void) strcpy(man2,"");
+ 
+ 	/*
+ 	**	find the difference in the exponents number of digits
+ 	*/
+ 	if( _F_SAMESIGN(R_getexp(p1),R_getexp(p2)))
+ 	{
+ 		digits =  _F_ABSDIFF(R_getexp(p1),R_getexp(p2));
+ 	}
+ 	else
+ 	{
+ 		digits = _F_ABSADD(R_getexp(p1),R_getexp(p2));
+ 	}
+ 
+ 	/*
+ 	**	make sure that there is room to store the result
+ 	*/
+ 	if (digits>0)
+ 	{ 
+ 		if (R_getexp(p1) < R_getexp(p2))
+ 		{
+ 			/*
+ 			**	leave room for terminator
+ 			*/
+ 			if (digits+strlen(R_getfrac(p1)) > (R_MANMAX-1))
+ 			{
+ 				(void) sprintf(Z_err_buf,
+ 				   "numbers differ by too much in magnitude");
+ 				Z_fatal(Z_err_buf);
+ 			}
+ 		}
+ 		else
+ 		{
+ 			/*
+ 			**	leave room for terminator
+ 			*/
+ 			if (digits+strlen(R_getfrac(p2)) > (R_MANMAX-1))
+ 			{
+ 				(void) sprintf(Z_err_buf,
+ 				   "numbers differ by too much in magnitude");
+ 				Z_fatal(Z_err_buf);
+ 			}
+ 		}
+ 	}
+ 	else
+ 	{
+ 		/*
+ 		**	leave room for terminator and possible carry
+ 		*/
+ 		if (Z_MAX(strlen(R_getfrac(p1)),
+ 			strlen(R_getfrac(p2))) > (R_MANMAX-2))
+ 		{						
+ 			(void) sprintf(Z_err_buf,
+ 			   "numbers differ by too much in magnitude");
+ 			Z_fatal(Z_err_buf);
+ 		}
+ 	}
+ 
+ 	/*
+ 	**	pad zeroes on the front of the smaller number
+ 	*/
+ 	if (R_getexp(p1) < R_getexp(p2))
+ 	{
+ 
+ 		addzeros(man1,digits);
+ 		resexp = R_getexp(p2);
+ 	}
+ 	else
+ 	{
+ 		addzeros(man2,digits);
+ 		resexp = R_getexp(p1);
+ 	}
+ 	(void) strcat(man1,R_getfrac(p1));
+ 	(void) strcat(man2,R_getfrac(p2));
+ 
+ 	len = Z_MAX(strlen(man1),strlen(man2));
+ 
+ 	/*
+ 	**	add the two values
+ 	*/
+ 	_F_stradd(man1,man2);
+ 
+ 	/*
+ 	**	adjust the exponent to account for a
+ 	**		possible carry
+ 	*/
+ 	resexp += strlen(man1) - len;
+ 
+ 
+ 	/*
+ 	** trim the leading zeros on the sum
+ 	*/
+ 	diffptr = man1;
+ 	while('0' == *diffptr)
+ 	{
+ 		diffptr++;
+ 		resexp--;
+ 	}
+ 
+ 	R_setfrac(result,diffptr);
+ 	R_setexp(result,resexp);
+ 	R_setsign(result,R_POSITIVE);
+ 
+ 	return(result);
+ }
+ 
+ /*
+ **	useful debugging routine. we don't call it in the release,
+ **	so it is commented out, but we'll leave it for future use
+ */
+ 
+ /*
+ F_printfloat(fl)
+ F_float fl;
+ {
+ 	(void) printf("fraction = :%s: exp = %d sign = %c\n",
+ 			R_getfrac(fl),
+ 			R_getexp(fl),
+ 			((R_getsign(fl) == R_POSITIVE) ? '+': '-'));
+ 
+ }
+ */


Index: llvm/test/Programs/MultiSource/Applications/spiff/float.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/float.h:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/float.h	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,37 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ 
+ #include "floatrep.h"
+ 
+ #ifndef F_INCLUDED
+ 
+ /*
+ **	flags for F_atof
+ */
+ #define NO_USE_ALL	0
+ #define USE_ALL		1
+ 
+ typedef struct R_flstr *F_float;
+ #define F_getexp(x)	R_getexp(x)
+ #define F_getsign(x)	R_getsign(x)
+ #define F_zerofloat(x)	R_zerofloat(x)
+ 
+ extern F_float F_atof();
+ 
+ extern F_float F_floatmul();
+ extern F_float F_floatmagadd();
+ extern F_float F_floatsub();
+ extern int F_floatcmp(F_float f1,F_float f2);
+ extern int F_isfloat(char *str,int need_decimal,int allow_sign);
+ 
+ #define F_null	((F_float) 0)
+ 
+ #define F_INCLUDED
+ 
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/spiff/floatrep.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/floatrep.c:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/floatrep.c	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,33 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ 
+ #ifndef lint
+ static char rcsid[]= "$Header: /home/vadve/shared/PublicCVS/llvm/test/Programs/MultiSource/Applications/spiff/floatrep.c,v 1.1 2004/06/01 20:35:58 gaeke Exp $";
+ #endif
+ 
+ #include "misc.h"
+ #include "floatrep.h"
+ 
+ R_float
+ R_makefloat()
+ {
+ 	R_float retval;
+ 
+ 	retval = Z_ALLOC(1,struct R_flstr);
+ 	retval->mantissa = Z_ALLOC(R_MANMAX,char);
+ 	return(retval);
+ }
+ 
+ int
+ R_getexp(ptr)
+ R_float ptr;
+ {
+ 	return(ptr->exponent);
+ }
+ 


Index: llvm/test/Programs/MultiSource/Applications/spiff/floatrep.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/floatrep.h:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/floatrep.h	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,66 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ /*
+ ** header file that defines canonical floating point structure
+ **	and routines
+ */
+ 
+ 
+ #ifndef  R_INCLUDED
+ 
+ /*
+ **	when evaluated to a string, the fractional part will
+ **		not exceed this length
+ */
+ #define R_MANMAX	200
+ 
+ #define R_POSITIVE	0
+ #define R_NEGATIVE	1
+ 
+ struct  R_flstr {
+ 	int exponent;
+ 	int man_sign;
+ 	char *mantissa;
+ };
+ 
+ typedef struct R_flstr *R_float;
+ 
+ #define R_getfrac(x)	(x->mantissa)
+ 
+ extern R_float R_makefloat();
+ 
+ extern int R_getexp();
+ 
+ #define R_getsign(x)	(x->man_sign)
+ 
+ /*
+ **	takes a string
+ */
+ #define R_setfrac(x,y)	((void)strcpy(x->mantissa,y))
+ /*
+ **	takes an int
+ */
+ #define R_setexp(x,y)	(x->exponent = y)
+ /*
+ **	takes a sign
+ */
+ #define R_setsign(x,y)	(x->man_sign = y)
+ 
+ /*
+ #define R_incexp(x)	((x->exponent)++)
+ #define R_decexp(x)	((x->exponent)--)
+ */
+ 
+ #define R_setzero(x)	R_setfrac(x,"0");R_setexp(x,0);R_setsign(x,R_POSITIVE)
+ 
+ #define R_zerofloat(x)	((0 == x->exponent) && (!strcmp(x->mantissa,"0")))
+ 
+ #define R_INCLUDED
+ 
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/spiff/line.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/line.c:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/line.c	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,167 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ 
+ #ifndef lint
+ static char rcsid[]= "$Header: /home/vadve/shared/PublicCVS/llvm/test/Programs/MultiSource/Applications/spiff/line.c,v 1.1 2004/06/01 20:35:58 gaeke Exp $";
+ #endif
+ 
+ #include <stdio.h>
+ #include "misc.h"
+ #include "token.h"
+ #include "line.h"
+ 
+ char *_L_al[_L_MAXLINES];  /* storage for lines */
+ char *_L_bl[_L_MAXLINES];
+ 
+ int   _L_ai[_L_MAXLINES];  /* index from token line number to first token */
+ int   _L_bi[_L_MAXLINES];
+ 
+ int   _L_ac[_L_MAXLINES];  /* count of tokens on this token line */
+ int   _L_bc[_L_MAXLINES];
+ 
+ int   _L_arlm;		/* count of real lines in the file */
+ int   _L_brlm;
+ 
+ int   _L_aclm;		/* count of content lines in the file */
+ int   _L_bclm;
+ 
+ int   _L_atlm;		/* count of token lines in the file */
+ int   _L_btlm;
+ 
+ int   _L_aclindex[_L_MAXLINES]; /* mapping from content lines to real lines*/
+ int   _L_bclindex[_L_MAXLINES]; 
+ 
+ int   _L_atlindex[_L_MAXLINES]; /*mapping from token lines to content lines */
+ int   _L_btlindex[_L_MAXLINES];
+ 
+ 
+ static void
+ _L_setrline(file,X,str)
+ int file;
+ int X;
+ char *str;
+ {
+ 	if (file)
+ 	{
+ 		S_savestr(&_L_bl[X],str);
+ 	}
+ 	else
+ 	{
+ 		S_savestr(&_L_al[X],str);
+ 	}
+ 	return;
+ }
+ /*
+ **	returns 1 if we reached the end of file
+ **	returns 0 if there is more to do
+ **
+ **	stores data and sets maximum counts
+ */
+ int L_init_file(int fnumber, char *fname)
+ {
+ 	extern char *fgets();
+ 	FILE *fp;
+ 	static char buf[Z_LINELEN+2];	/* +2 is to leave room for us to add
+ 						a newline if we need to */
+ 	int ret_val = 1;
+ 	int tmplen;
+ 
+ 	if ((fp = fopen(fname,"r")) == (FILE*) NULL)
+ 	{
+ 		(void) sprintf(Z_err_buf, "Cannot open file %s.\n",fname);
+ 		Z_fatal(Z_err_buf);
+ 	}
+ 
+ 	/*
+ 	**	clear the line count
+ 	*/
+ 	_L_setrlmx(fnumber,0);
+ 
+ 	/*
+ 	**	read in the entire file
+ 	*/
+ 	while (fgets(buf,Z_LINELEN+1,fp) != (char *) NULL)
+ 	{
+ 		tmplen = strlen(buf);
+ 		if (tmplen <= 0)
+ 		{
+ 			(void) sprintf(Z_err_buf,
+ 			  "fatal error -- got 0 length line %d in file %s\n",
+ 				L_getrlmax(fnumber)+1,
+ 				fname);
+ 			Z_fatal(Z_err_buf);
+ 		}
+ 		else if (tmplen > Z_LINELEN)
+ 		{
+ 			(void) sprintf(Z_err_buf,
+   "got fatally long line %d in file %s length is %d, must be a bug\n",
+ 				L_getrlmax(fnumber)+1,
+ 				fname,tmplen);
+ 			Z_fatal(Z_err_buf);
+ 		}
+ 		/*
+ 		**	look for newline as last character
+ 		*/
+ 		if ('\n' != buf[tmplen-1])
+ 		{
+ 			/*
+ 			**	did we run out room in the buffer?
+ 			*/
+ 			if (tmplen == Z_LINELEN)
+ 			{
+ 			(void) sprintf(Z_err_buf,
+ 	"line %d too long in file %s, newline added after %d characters\n",
+ 				L_getrlmax(fnumber)+1,
+ 				fname,Z_LINELEN);
+ 			Z_complain(Z_err_buf);
+ 			}
+ 			else
+ 			{
+ 			(void) sprintf(Z_err_buf,
+ 	"didn't find a newline at end of line %d in file %s, added one\n",
+ 				L_getrlmax(fnumber)+1,
+ 				fname);
+ 			Z_complain(Z_err_buf);
+ 			}
+ 
+ 			buf[tmplen] = '\n';
+ 			buf[tmplen+1] = '\0';
+ 		}
+ 
+ 		_L_setrline(fnumber,L_getrlmax(fnumber),buf);
+ 
+ 		if (L_getrlmax(fnumber) >= _L_MAXLINES-1)
+ 		{
+ 			(void) sprintf(Z_err_buf,
+ 	"warning -- ran out of space reading %s, truncated to %d lines\n",
+ 				fname,_L_MAXLINES);
+ 			Z_complain(Z_err_buf);
+ 			ret_val= 0;
+ 			break;
+ 		}
+ 		else
+ 		{
+ 			/*
+ 			**	increment the line count
+ 			*/
+ 			_L_incrlmx(fnumber);
+ 		}
+ 
+ 	}
+ 
+ 	(void) fclose(fp);
+ 	/*
+ 	**	reset line numbers
+ 	*/
+ 	L_setclmax(fnumber,0);
+ 	L_settlmax(fnumber,0);
+ 
+ 	return(ret_val);
+ }
+ 


Index: llvm/test/Programs/MultiSource/Applications/spiff/line.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/line.h:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/line.h	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,115 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ 
+ #ifndef L_INCLUDED
+ 
+ #define _L_MAXLINES	10000
+ 
+ /*
+ **	oh god, is this an ugly implementation.
+ **	I really should have a two dimensional array of structures
+ **		the history of the current arrangement is too long
+ **		and ugly to record here.
+ **		Someday when I have too much time on my hands . . .
+ */
+ 
+ extern char *_L_al[];	/* storage for text in first file */
+ extern char *_L_bl[];	/* storage for text in second file */
+ 
+ extern int _L_ai[];	/* pointer from token line to first token */
+ extern int _L_bi[];
+ 
+ extern int _L_ac[];	/* number of tokens on a given token line */
+ extern int _L_bc[];
+ 
+ extern int _L_aclindex[]; /* mapping from content lines to real lines */
+ extern int _L_bclindex[];
+ 
+ extern int _L_atlindex[]; /* mapping from lines with tokens to content lines */
+ extern int _L_btlindex[];
+ 
+ extern int _L_arlm;	/* count of real lines */
+ extern int _L_brlm;
+ 
+ extern int _L_aclm;	/* count of content lines */
+ extern int _L_bclm;
+ 
+ extern int _L_atlm;	/* count of lines with tokens */
+ extern int _L_btlm;
+ 
+ extern int L_init_file(int fnumber, char *fname);
+ 
+ /*
+ **	routines to set up mappings from token lines to content lines
+ **	  and from content lines to real lines
+ */
+ #define L_setclindex(file,content,real) (file?(_L_bclindex[content]=real):\
+ 					     (_L_aclindex[content]=real))
+ 
+ #define L_settlindex(file,token,content) (file?(_L_btlindex[token]=content):\
+ 					      (_L_atlindex[token]=content))
+ /*
+ **	get line number X from file
+ */
+ #define L_getrline(file, X)	 (file?(_L_bl[X]):(_L_al[X]))
+ #define L_getcline(file, X)	 (file?(_L_bl[_L_bclindex[X]]):\
+ 				       (_L_al[_L_aclindex[X]]))
+ #define L_gettline(file, X)	 (file?(_L_bl[_L_bclindex[_L_btlindex[X]]]):\
+ 				       (_L_al[_L_aclindex[_L_atlindex[X]]]))
+ 
+ #define L_cl2rl(file, X)	 (file?(_L_bclindex[X]):\
+ 				       (_L_aclindex[X]))
+ #define L_tl2cl(file, X)	 (file?(_L_btlindex[X]):\
+ 				       (_L_atlindex[X]))
+ #define L_tl2rl(file, X)	 (file?(_L_bclindex[_L_btlindex[X]]):\
+ 				       (_L_aclindex[_L_atlindex[X]]))
+ 
+ /*
+ **	get number of first token on line X of the file
+ */
+ #define L_getindex(file,X)	(file?(_L_bi[X]):(_L_ai[X]))
+ 
+ /*
+ **	get count of number of tokens on line X of first file
+ */
+ #define L_getcount(file,X)	(file?(_L_bc[X]):(_L_ac[X]))
+ 
+ /*
+ **	save number of first token for line X of file
+ */
+ #define L_setindex(file,index,value)	(file?(_L_bi[index]=value):(_L_ai[index]=value))
+ /*
+ **	save count of tokens on line X of file
+ */
+ #define L_setcount(file,index,value)	(file?(_L_bc[index]=value):(_L_ac[index]=value))
+ #define	L_inccount(file,index)		(file?(_L_bc[index]++):(_L_ac[index]++))
+ 
+ /*
+ **	retrieve line and token counts
+ */
+ #define L_getrlmax(file)	(file?_L_brlm:_L_arlm)
+ #define L_getclmax(file)	(file?_L_bclm:_L_aclm)
+ #define L_gettlmax(file)	(file?_L_btlm:_L_atlm)
+ 
+ /*
+ **	set line and token counts
+ */
+ #define _L_setrlmx(file,value)	(file?(_L_brlm=(value)):(_L_arlm=(value)))
+ #define L_setclmax(file,value)	(file?(_L_bclm=(value)):(_L_aclm=(value)))
+ #define L_settlmax(file,value)	(file?(_L_btlm=(value)):(_L_atlm=(value)))
+ 
+ /*
+ **	increment line and token counts
+ */
+ #define	_L_incrlmx(file)		(file?(_L_brlm++):(_L_arlm++))
+ #define	L_incclmax(file)		(file?(_L_bclm++):(_L_aclm++))
+ #define	L_inctlmax(file)		(file?(_L_btlm++):(_L_atlm++))
+ 
+ #define L_INCLUDED
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/spiff/miller.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/miller.c:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/miller.c	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,128 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ 
+ #ifndef lint
+ static char rcsid[]= "$Header: /home/vadve/shared/PublicCVS/llvm/test/Programs/MultiSource/Applications/spiff/miller.c,v 1.1 2004/06/01 20:35:58 gaeke Exp $";
+ #endif
+ 
+ #include "misc.h"
+ #include "token.h"
+ #include "edit.h"
+ #include "compare.h"
+ 
+ #define MAXT	K_MAXTOKENS
+ #define ORIGIN (max_obj/2)
+ 
+ #define MILLER_CHATTER	100
+ 
+ /*
+ **	totally opaque miller/myers code
+ **		hacked from a version provided by the author
+ */
+ 
+ 
+ E_edit
+ G_do_miller(m,n,max_d,comflags)
+ int m;
+ int n;
+ int max_d;
+ int comflags;
+ {
+     int	max_obj = m + n;
+     int
+ 	lower,
+ 	upper,
+ 	d,
+ 	k,
+ 	row,
+ 	col;
+ 	E_edit new;
+ 
+ #ifdef STATIC_MEM
+ 	static E_edit script[MAXT+1];
+ 	static int last_d[MAXT+1];
+ #else
+ 	E_edit *script;
+ 	int *last_d;
+ 	/*
+ 	**	make space for the two big arrays
+ 	**		these could probably be smaller if I
+ 	**		understood this algorithm at all
+ 	**		as is, i just shoe horned it into my program.
+ 	**	be sure to allocate max_obj + 1 objects as was done
+ 	**		in original miller/myers code
+ 	*/
+ 	script = Z_ALLOC(max_obj+1,E_edit);
+ 	last_d = Z_ALLOC(max_obj+1,int);
+ 
+ #endif
+ 	for (row=0;row < m && row < n && X_com(row,row,comflags) == 0; ++row)
+ 		;
+ 	last_d[ORIGIN] = row;
+ 	script[ORIGIN] = E_NULL;
+ 	lower = (row == m) ? ORIGIN+1 : ORIGIN - 1;
+ 	upper = (row == n) ? ORIGIN-1 : ORIGIN + 1;
+ 	if (lower > upper)
+ 	{
+ 		/*
+ 		**	the files are identical
+ 		*/
+ 		return(E_NULL);
+ 	}
+ 	for (d = 1; d <= max_d; ++d) {
+ 		for (k = lower; k<= upper; k+= 2) {
+ 			new = E_edit_alloc();
+ 
+ 			if (k == ORIGIN-d || (k!= ORIGIN+d && last_d[k+1] >= last_d[k-1])) {
+ 				row = last_d[k+1]+1;
+ 				E_setnext(new,script[k+1]);
+ 				E_setop(new,E_DELETE);
+ 			} else {
+ 				row = last_d[k-1];
+ 				E_setnext(new,script[k-1]);
+ 				E_setop(new,E_INSERT);
+ 			}
+ 
+ 			E_setl1(new,row);
+ 			col = row + k - ORIGIN;
+ 			E_setl2(new,col);
+ 			script[k] = new;
+ 
+ 			while (row < m && col < n && X_com(row,col,comflags) == 0) {
+ 				++row;
+ 				++col;
+ 			}
+ 			last_d[k] = row;
+ 			if (row == m && col == n) {
+ 				return(script[k]);
+ 			}
+ 			if (row == m)
+ 				lower = k+2;
+ 			if (col == n)
+ 				upper = k-2;
+ 		}
+ 		--lower;
+ 		++upper;
+ #ifndef NOCHATTER
+ 		if ((d > 0) && (0 == (d % MILLER_CHATTER)))
+ 		{
+ 			(void) sprintf(Z_err_buf,
+ 				"found %d differences\n",
+ 				d);
+ 			Z_chatter(Z_err_buf);
+ 		}
+ #endif
+ 	}
+ 	Z_exceed(max_d);
+ 	/*
+ 	**	dummy lines to shut up lint
+ 	*/
+ 	Z_fatal("fell off end of do_miller\n");
+ 	return(E_NULL);
+ }


Index: llvm/test/Programs/MultiSource/Applications/spiff/miller.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/miller.h:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/miller.h	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,17 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ #ifndef G_INCLUDED
+ 
+ #include "edit.h"
+ 
+ extern E_edit G_do_miller();
+ 
+ #define G_INCLUDED
+ 
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/spiff/misc.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/misc.c:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/misc.c	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,119 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ 
+ #ifndef lint
+ static char rcsid[]= "$Header: /home/vadve/shared/PublicCVS/llvm/test/Programs/MultiSource/Applications/spiff/misc.c,v 1.1 2004/06/01 20:35:58 gaeke Exp $";
+ #endif
+ 
+ #include <stdio.h>
+ #include "misc.h"
+ #include "visual.h"
+ #include "output.h"
+ 
+ /*
+ **	various routines used throughout the program
+ */
+ 
+ static int _Z_qflag = 0;
+ 
+ void
+ Z_setquiet()
+ {
+ 	_Z_qflag = 1;
+ }
+ 
+ char Z_err_buf[Z_LINELEN];
+ 
+ #ifndef NOCHATTER
+ /*
+ **	I/O coverup to reassure users with HUGE files
+ **	that spiff is doing something
+ */
+ void
+ Z_chatter(str)
+ char *str;
+ {
+ 	if (!_Z_qflag)
+ 	{
+ 		(void) fputs("spiff -- ",stderr);
+ 		(void) fputs(str,stderr);
+ 	}
+ }
+ #endif
+ 
+ /*
+ **	complain unless you've been told to be quiet
+ */
+ void
+ Z_complain(str)
+ char *str;
+ {
+ 	if (!_Z_qflag)
+ 		(void) fputs(str,stderr);
+ }
+ 
+ /*
+ **	quit with an error code
+ */
+ static void
+ _Z_errexit()
+ {
+ 	(void) exit(2);
+ }
+ 
+ /*
+ **	complain and die
+ */
+ void
+ _Z_qfatal(str)
+ char *str;
+ {
+ 	V_cleanup();	/* try reset the device to normal */
+ 	O_cleanup();	/*  "    "    "     "   "    "    */
+ 	Z_complain(str);
+ 	_Z_errexit();
+ }
+ 
+ /*
+ **	scream and die
+ */
+ void
+ Z_fatal(str)
+ char *str;
+ {
+ 	V_cleanup();	/* try reset the device to normal */
+ 	O_cleanup();	/*  "    "    "     "   "    "    */
+ 	(void) fputs(str,stderr);
+ 	_Z_errexit();
+ }
+ 
+ /*
+ **	allocate memory with error checking
+ */
+ int*
+ _Z_myalloc(k)
+ int k;
+ {
+ 	int *tmp;
+ 	if ((tmp = (int*) calloc((unsigned)k,(unsigned)1)) != 0)
+ 	{
+ 		return(tmp);
+ 	}
+ 	Z_fatal("Out of Memory\n");
+ 	return(tmp);	/* boilerplate to shut up lint */
+ }
+ 
+ void
+ Z_exceed(d)
+ int d;
+ {
+ 	(void) sprintf(Z_err_buf,
+ 		"The files differ in more than %d places\n", d);
+ 	_Z_qfatal(Z_err_buf);
+ }


Index: llvm/test/Programs/MultiSource/Applications/spiff/misc.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/misc.h:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/misc.h	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,49 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ #ifndef Z_INCLUDED
+ 
+ /*
+ **	make sure that if we have a XENIX system, that
+ **	we also treat it as an AT and T derivative
+ */
+ #ifdef XENIX
+ #ifndef ATT
+ #define ATT
+ #endif
+ #endif
+ 
+ #define	Z_LINELEN	1024
+ #define	Z_WORDLEN	  20
+ 
+ extern char Z_err_buf[];
+ 
+ /*
+ **	helpful macros
+ */
+ #define Z_ABS(x)	(( (x) < (0) )? (-(x)):(x))
+ #define Z_MIN(x,y)	(( (x) < (y) )? (x):(y))
+ #define Z_MAX(x,y)	(( (x) > (y) )? (x):(y))
+ 
+ #define Z_ALLOC(n,type)	((type*) _Z_myalloc((n) * sizeof (type)))
+ extern int *_Z_myalloc();
+ 
+ #include <stdio.h>
+ #include <string.h>
+ #include <stdlib.h>
+ 
+ extern void Z_complain();
+ extern void Z_fatal();
+ extern void Z_exceed();
+ extern void Z_setquiet();
+ #ifndef NOCHATTER
+ extern void Z_chatter();
+ #endif
+ 
+ #define Z_INCLUDED
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/spiff/one
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/one:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/one	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,3 ----
+ Hello there
+ you world
+ leaders.


Index: llvm/test/Programs/MultiSource/Applications/spiff/output.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/output.c:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/output.c	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,560 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ 
+ #ifndef lint
+ static char rcsid[]= "$Header: /home/vadve/shared/PublicCVS/llvm/test/Programs/MultiSource/Applications/spiff/output.c,v 1.1 2004/06/01 20:35:58 gaeke Exp $";
+ #endif
+ 
+ #include <stdio.h>
+ 
+ #ifdef M_TERMINFO
+ #include <curses.h>
+ #include <term.h>
+ #endif
+ 
+ #ifdef M_TERMCAP
+ #ifdef XENIX
+ #include <tcap.h>
+ #endif
+ #endif
+ 
+ #include <unistd.h>
+ 
+ #include "misc.h"
+ #include "flagdefs.h"
+ #include "edit.h"
+ #include "line.h"
+ #include "token.h"
+ 
+ static int _O_need_init = 1;
+ static int _O_st_ok = 0;
+ static int _O_doing_ul = 0;
+ static	char *_O_st_tmp;
+ #ifdef M_TERMCAP
+ static	char _O_startline[Z_WORDLEN];
+ static	char _O_endline[Z_WORDLEN];
+ #endif
+ 
+ static void
+ _O_st_init()
+ {
+ 	char termn[Z_WORDLEN];
+ #ifdef M_TERMCAP
+ 	static	char entry[1024];
+ #endif
+ 
+ 	/*
+ 	**	see if standard out is a terminal
+ 	*/
+ 	if (!isatty(1))
+ 	{
+ 		_O_need_init = 0;
+ 		_O_st_ok = 0;
+ 		return;
+ 	}
+ 
+ 	if (NULL == (_O_st_tmp = (char*) getenv("TERM")))
+ 	{
+ 		Z_complain("can't find TERM entry in environment\n");
+ 		_O_need_init = 0;
+ 		_O_st_ok = 0;
+ 		return;
+ 	}
+ 	(void) strcpy(termn,_O_st_tmp);
+ 
+ #ifdef M_TERMCAP
+ 	if (1 != tgetent(entry,termn))
+ 	{
+ 		Z_complain("can't get TERMCAP info for terminal\n");
+ 		_O_need_init = 0;
+ 		_O_st_ok = 0;
+ 		return;
+ 	}
+ 
+ 	_O_st_tmp = _O_startline;
+ 	_O_startline[0] = '\0';
+ 	tgetstr("so",&_O_st_tmp);
+ 
+ 	_O_st_tmp = _O_endline;
+ 	_O_endline[0] = '\0';
+ 	tgetstr("se",&_O_st_tmp);
+ 
+ 	_O_st_ok = (strlen(_O_startline) > 0) && (strlen(_O_endline) > 0);
+ #endif
+ 
+ #ifdef M_TERMINFO
+ 	setupterm(termn,1,&_O_st_ok);
+ #endif
+ 	_O_need_init = 0;
+ }
+ 
+ void
+ O_cleanup()
+ {
+ 	/*
+ 	**	this probably isn't necessary, but in the
+ 	**	name of compeleteness.
+ 	*/
+ #ifdef M_TERMINFO
+ 	resetterm();
+ #endif
+ }
+ 
+ static void
+ _O_start_standout()
+ {
+ 	if (_O_need_init)
+ 	{
+ 		_O_st_init();
+ 	}
+ 	if (_O_st_ok)
+ 	{
+ #ifdef M_TERMCAP
+ 		(void) printf("%s",_O_startline);
+ #endif 
+ #ifdef M_TERMINFO
+ 		vidattr(A_STANDOUT);
+ #endif
+ 	}
+ 	else
+ 	{
+ 		_O_doing_ul = 1;
+ 	}
+ }
+ 
+ static void
+ _O_end_standout()
+ {
+ 	if (_O_need_init)
+ 	{
+ 		_O_st_init();
+ 	}
+ 	if (_O_st_ok)
+ 	{
+ #ifdef M_TERMCAP
+ 		(void) printf("%s",_O_endline);
+ #endif 
+ #ifdef M_TERMINFO
+ 		vidattr(0);
+ #endif
+ 	}
+ 	else
+ 	{
+ 		_O_doing_ul = 0;
+ 	}
+ }
+ 
+ static void
+ _O_pchars(line,start,end)
+ char *line;
+ int start,end;
+ {
+ 	int cnt;
+ 
+ 	for(cnt=start;cnt < end; cnt++)
+ 	{
+ 		if (0 && _O_doing_ul)
+ 		{
+ 			(void) putchar('_');
+ 			(void) putchar('\b');
+ 		}
+ 		(void) putchar(line[cnt]);
+ 	}
+ }
+ 
+ 
+ /*
+ **	convert a 0 origin token number to a 1 orgin token
+ **		number or 1 origin line number as appropriate
+ */
+ static int
+ _O_con_line(numb,flags,filenum)
+ int numb, flags,filenum;
+ {
+ 	if (flags & U_TOKENS)
+ 	{
+ 		return(numb+1);
+ 	}
+ 	else
+ 	{
+ 		/*
+ 		**	 check to make sure that this is a real
+ 		**	line number. if not, then return 0
+ 		**	on rare occasions, (i.e. insertion/deletion
+ 		**	of the first token in a file) we'll get
+ 		**	line numbers of -1.  the usual look-up technique
+ 		**	won't work since we have no lines before than 0.
+ 		*/
+ 		if (numb < 0)
+ 			return(0);
+ 		/*
+ 		**	look up the line number the token and then
+ 		**	add 1 to make line number 1 origin
+ 		*/
+ 		return(L_tl2cl(filenum,numb)+1);
+ 	}
+ }
+ 
+ static char *
+ _O_convert(ptr)
+ char *ptr;
+ {
+ 	static char spacetext[Z_WORDLEN];
+ 
+ 	if (1 == strlen(ptr))
+ 	{
+ 		switch (*ptr)
+ 		{
+ 			default:
+ 				break;
+ 			case '\n' :
+ 				(void) strcpy(spacetext,"<NEWLINE>");
+ 				return(spacetext);
+ 			case '\t' :
+ 				(void) strcpy(spacetext,"<TAB>");
+ 				return(spacetext);
+ 			case ' ' :
+ 				(void) strcpy(spacetext,"<SPACE>");
+ 				return(spacetext);
+ 		}
+ 				
+ 	}
+ 	return(ptr);
+ }
+ 
+ static char*
+ _O_get_text(file,index,flags)
+ int file,index,flags;
+ {
+ 	static char buf[Z_LINELEN*2];	/* leave lots of room for both
+ 						the token text and the
+ 						chatter that preceeds it */
+ 	char *text;
+ 	K_token tmp;
+ 
+ 	if (flags & U_TOKENS)
+ 	{
+ 		tmp = K_gettoken(file,index);
+ 		text = _O_convert(K_gettext(tmp));
+ 		(void) sprintf(buf,"%s -- line %d, character %d\n",
+ 				text,
+ 				/*
+ 				**	add 1 to make output start at line 1 
+ 				**	and character numbers start at 1
+ 				*/
+ 				L_tl2cl(file,K_getline(tmp))+1,
+ 				K_getpos(tmp)+1);
+ 		return(buf);
+ 	}
+ 	else
+ 	{
+ 		return(L_gettline(file,index));
+ 	}
+ }
+ #define	_O_APP		1
+ #define _O_DEL		2
+ #define _O_CHA		3
+ #define _O_TYPE_E	4
+ 
+ static void
+ _O_do_lines(start,end,file)
+ int start,end,file;
+ {
+ 	int cnt;
+ 	int lastline = -1;
+ 	int nextline;
+ 	K_token nexttoken;
+ 	for (cnt=start;cnt <= end; cnt++)
+ 	{
+ 		nexttoken = K_get_token(file,cnt);
+ 		nextline = K_getline(nexttoken);
+ 		if (lastline != nextline)
+ 		{
+ 			int lastone,lastchar;
+ 			K_token lasttok;
+ 			char linetext[Z_LINELEN+1];	/* leave room for
+ 							   terminator */
+ 			if (0 == file)
+ 			{
+ 				(void) printf("< ");
+ 			}
+ 			else
+ 			{
+ 				(void) printf("> ");
+ 			}
+ 
+ 			/*
+ 			**	put loop here if you want to print
+ 			**	out any intervening lines that don't
+ 			**	have any tokens on them
+ 			*/
+ 
+ 			/*
+ 			**	following line is necessary because
+ 			**	L_gettline is a macro, and can't be passed
+ 			*/
+ 			(void) strcpy(linetext,L_gettline(file,nextline));
+ 			_O_pchars(linetext,0,K_getpos(nexttoken));
+ 			_O_start_standout();
+ 			/*
+ 			** 	look for last token on this line to be
+ 			**	highlighted
+ 			*/
+ 			for ( lastone=cnt,lasttok = K_get_token(file,lastone);
+ 			      (lastone<=end)&&(nextline == K_getline(lasttok));
+ 				lastone++,lasttok = K_get_token(file,lastone))
+ 			{
+ 			}
+ 			lastone--;
+ 			lasttok = K_get_token(file,lastone);
+ 			lastchar = K_getpos(lasttok)
+ 					+ strlen(K_gettext(lasttok));
+ 			_O_pchars(linetext,K_getpos(nexttoken),lastchar);
+ 			_O_end_standout();
+ 			_O_pchars(linetext,lastchar,strlen(linetext));
+ 			
+ 			lastline = nextline;
+ 		}
+ 	}
+ }
+ 
+ void
+ O_output(start,flags)
+ E_edit start;
+ int flags;
+ {
+ 	int type = _O_TYPE_E;	/* initialize to error state
+ 				** this is to make sure that type is set
+ 				** somewhere
+ 				*/
+ 	int t_beg1, t_beg2, t_end1, t_end2; /* token numbers */
+ 	int first1, last1, first2, last2;
+ 
+ 	E_edit ep, behind, ahead, a, b;
+ 
+ 	/*
+ 	**	reverse the list of edits
+ 	*/
+ 	ahead = start;
+ 	ep = E_NULL;
+ 	while (ahead != E_NULL) {
+ 		/*
+ 		**	set token numbers intentionally out of range
+ 		**		as boilerplate
+ 		*/
+ 		t_beg1 = t_beg2 = t_end1 = t_end2 = -1;
+ 		/*
+ 		**	edit script is 1 origin, all of
+ 		**	 our routines are zero origin
+ 		*/
+ 		E_setl1(ahead,(E_getl1(ahead))-1);
+ 		E_setl2(ahead,(E_getl2(ahead))-1);
+ 
+ 		behind = ep;
+ 		ep = ahead;
+ 		ahead = E_getnext(ahead);
+ 		E_setnext(ep,behind);
+ 	}
+ 
+ 	/*
+ 	**	now run down the list and collect the following information
+ 	**	type of change (_O_APP, _O_DEL or _O_CHA)
+ 	**	start and length for each file
+ 	*/
+ 	while (ep != E_NULL)
+ 	{
+ 		b = ep;
+ 		/*
+ 		**	operation always start here
+ 		*/
+ 		t_beg1 = E_getl1(ep);
+ 		/*
+ 		**	any deletions will appear before any insertions,
+ 		**	so, if the first edit is an E_INSERT, then this
+ 		**	this is an _O_APP
+ 		*/
+ 		if (E_getop(ep) == E_INSERT)
+ 			type = _O_APP;
+ 		else {
+ 			/*
+ 			**	run down the list looking for the edit
+ 			**	that is not part of the current deletion
+ 			*/	
+ 			do {
+ 				a = b;
+ 				b = E_getnext(b);
+ 			} while ((b != E_NULL) &&
+ 				 (E_getop(b) == E_DELETE) &&
+ 				 ((E_getl1(b)) == ((E_getl1(a))+1)));
+ 			/*
+ 			**	if we have an insertion at the same place
+ 			**	as the deletion we just scanned, then
+ 			**	this is a change
+ 			*/
+ 			if ((b != E_NULL) &&
+ 				((E_getop(b)) == E_INSERT) &&
+ 				((E_getl1(b))==(E_getl1(a))))
+ 			{
+ 				type = _O_CHA;
+ 			}
+ 			else
+ 			{
+ 				type = _O_DEL;
+ 			}
+ 			/*
+ 			**	set up start and length information for
+ 			**	first file
+ 			*/
+ 			t_end1 = E_getl1(a);
+ 			/*
+ 			**	move pointer to beginning of insertion
+ 			*/
+ 			ep = b;
+ 			/*
+ 			**	if we are showing only a deletion,
+ 			**	then we're all done, so skip ahead
+ 			*/ 
+ 			if (_O_DEL == type)
+ 			{
+ 				t_beg2 = E_getl2(a);
+ 				t_end2 = -1;	/* dummy number, won't
+ 							ever be printed */
+ 						   
+ 				goto skipit;
+ 			}
+ 		}
+ 		t_beg2 = E_getl2(ep);
+ 		t_end2 = t_beg2-1;
+ 		/*
+ 		**	now run down the list lookingfor the
+ 		**	end of this insertion and keep count
+ 		**	of the number of times we step along
+ 		*/
+ 		do {
+ 			t_end2++;
+ 			ep = E_getnext(ep);
+ 		} while ((ep != E_NULL) && ((E_getop(ep)) == E_INSERT) &&
+ 					((E_getl1(ep)) == (E_getl1(b))));
+ 
+ skipit:;
+ 		if (flags & U_TOKENS)
+ 		{
+ 			/*
+ 			**	if we are dealing with tokens individually,
+ 			**	then just print then set printing so
+ 			*/
+ 				first1 = t_beg1;
+ 				last1 = t_end1;
+ 				first2 = t_beg2;
+ 				last2 = t_end2;
+ 		}
+ 		else
+ 		{
+ 			/*
+ 			**	we are printing differences in terms of lines
+ 			**	so find the beginning and ending lines of the
+ 			**	changes and print header in those terms
+ 			*/
+ 			if ( t_beg1 >= 0)
+ 				first1 = K_getline(K_get_token(0,t_beg1));
+ 			else
+ 				first1 = t_beg1;
+ 
+ 			if ( t_end1 >= 0)
+ 				last1 = K_getline(K_get_token(0,t_end1));
+ 			else
+ 				last1 = t_end1;
+ 
+ 			if ( t_beg2 >= 0)
+ 				first2 = K_getline(K_get_token(1,t_beg2));
+ 			else
+ 				first2 = t_beg2;
+ 
+ 			if ( t_end2 >= 0)
+ 				last2 = K_getline(K_get_token(1,t_end2));
+ 			else
+ 				last2 = t_end2;
+ 
+ 		}
+ 		/*
+ 		**	print the header for this difference
+ 		*/
+ 		(void) printf("%d",_O_con_line(first1,flags,0));
+ 		switch (type)
+ 		{
+ 		case _O_APP :
+ 			(void) printf("a%d",_O_con_line(first2,flags,1));
+ 			if (last2 > first2)
+ 			{
+ 				(void) printf(",%d",_O_con_line(last2,flags,1));
+ 			}
+ 			(void) printf("\n");
+ 			break;
+ 		case _O_DEL :
+ 			if (last1 > first1)
+ 			{
+ 				(void) printf(",%d",_O_con_line(last1,flags,0));
+ 			}
+ 			(void) printf("d%d\n",_O_con_line(first2,flags,1));
+ 			break;
+ 		case _O_CHA :
+ 			if (last1 > first1)
+ 			{
+ 				(void) printf(",%d",_O_con_line(last1,flags,0));
+ 			}
+ 			(void) printf("c%d",_O_con_line(first2,flags,1));
+ 			if (last2 > first2)
+ 			{
+ 				(void) printf(",%d",_O_con_line(last2,flags,1));
+ 			}
+ 			(void) printf("\n");
+ 			break;
+ 		default:
+ 			Z_fatal("type in O_output wasn't set\n");
+ 		}
+ 		if (_O_DEL == type || _O_CHA == type)
+ 		{
+ 			if (flags & U_TOKENS)
+ 			{
+ 				int cnt;
+ 				for(cnt=first1;cnt <= last1; cnt++)
+ 				{
+ 		(void) printf("< %s",
+ 							_O_get_text(0,cnt,flags));
+ 				}
+ 			}
+ 			else
+ 			{	
+ 				_O_do_lines(t_beg1,t_end1,0);
+ 			}
+ 		}
+ 		if (_O_CHA == type)
+ 		{
+ 			(void) printf("---\n");
+ 		}
+ 		if (_O_APP == type || _O_CHA == type)
+ 		{
+ 			if (flags & U_TOKENS)
+ 			{
+ 				int cnt;
+ 				for(cnt=first2;cnt <= last2; cnt++)
+ 				{
+ 					(void) printf("> %s",
+ 						_O_get_text(1,cnt,flags));
+ 				}
+ 			}
+ 			else
+ 			{
+ 				_O_do_lines(t_beg2,t_end2,1);
+ 			}
+ 		}
+ 	}
+ 	O_cleanup();
+ 	return;
+ }


Index: llvm/test/Programs/MultiSource/Applications/spiff/output.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/output.h:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/output.h	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,17 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ 
+ #ifndef O_INCLUDED
+ 
+ extern void O_output();
+ extern void O_cleanup();
+ 
+ #define O_INCLUDED
+ 
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/spiff/paper.ms
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/paper.ms:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/paper.ms	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,819 ----
+ .ll 6i
+ .nr PO 1.15i
+ .nr HM 0i
+ .nr FM 1.05i
+ .TL
+ SPIFF -- A Program for Making Controlled Approximate Comparisons of Files
+ .AU
+ Daniel Nachbar
+ .AI
+ Software Engineering Research Group
+ Bell Communications Research
+ Morristown, New Jersey
+ .AB
+ The well known program 
+ .B
+ diff
+ .R
+ [1]
+ is inappropriate for some
+ common tasks such as comparing the output of floating
+ point calculations where roundoff errors
+ lead 
+ .B
+ diff
+ .R
+ astray and comparing program source code
+ where some differences in the text (such as white space and comments)
+ have no effect on the operation of the compiled code. A new program,
+ named 
+ .B
+ spiff,
+ .R
+ addresses these and other similar cases
+ by lexical parsing of the input files and then applying
+ a differencing algorithm to the token sequences.  
+ .B
+ Spiff
+ .R
+ ignores differences
+ between floating point numbers that are below a user settable tolerance.
+ Other features include user settable commenting and literal string
+ conventions and a choice of differencing algorithm.
+ There is also an interactive mode wherein the input texts are displayed
+ with differences highlighted.  The user can change numeric tolerances
+ "on the fly" and 
+ .B
+ spiff
+ .R
+ will adjust the highlighting accordingly. 
+ .AE
+ .SH
+ Some Troubles With Diff
+ .PP
+ Over the past several years, it has been fairly easy to tell when 
+ a new type of computer arrived at a nearby computer center.
+ The best clue was the discordant chorus of
+ groaning, sighing, gnashing of teeth, pounding of foreheads on desks,
+ and other sounds of distress.  Tracing these noises to their source, one
+ would find some poor soul in the process of installing
+ a numerical analysis package on the new machine.
+ .PP
+ One might expect that "moving up" to a new machine
+ would be a cause for celebration.
+ After all, new machines are typically bigger, faster,
+ and better than old machines.
+ However, the floating point arithmetic on any new machine is frequently
+ slightly different from any old machine.
+ As a consequence,
+ software package test routines produce output that is slightly different,
+ but still correct, on the new machines.
+ Serious troubles appear when the person installing the software package
+ attempts to compare the test output files from two different machines
+ by using a difference finding program such as
+ .B
+ diff.
+ .R
+ Programs such as 
+ .B
+ diff
+ .R
+ do a character by character comparison.
+ .B
+ Diff
+ .R
+ finds a great many differences,  most of which
+ are due to roundoff errors in the least significant digits of floating point
+ numbers.  Others are the result of differences in the way
+ in which the two test runs
+ had printed a number (3.4e-1 vs. 0.34).
+ In one case, the test suite for the S statistical analysis package[2],
+ over 1700 floating point numbers are produced
+ (per machine). In the eyes of 
+ .B
+ diff,
+ .R
+ roughly 1200 of these numbers are different.
+ However, none of the "differences" are important ones.
+ Nonetheless, software installers wind up inspecting the output by eye.
+ .PP
+ A similar problem arises when one attempts to
+ look for differences between two versions
+ of the same C program.
+ .B
+ Diff
+ .R
+ reports many differences that are not of interest.  In
+ particular, white space (except inside quotation marks) and
+ anything inside a comment have no effect on the operation of the compiled
+ program and are usually not of interest.
+ .B
+ Diff
+ .R
+ does have a mode of operation where white space
+ within a line (spaces and tabs) can be ignored.
+ However, differences in the placement of newlines cannot be ignored.
+ This is particularly annoying since C programming
+ styles differ on whether to place a newline character before or after the '{'
+ characters that start blocks.
+ .SH
+ The Problem in General Terms
+ .PP
+ As already mentioned, programs such as 
+ .B
+ diff
+ .R
+ do
+ a character-by-character comparison of the input files.
+ However, when it comes to interpreting
+ the contents of a file (either by a human or by a program)
+ it is almost never the case that characters
+ are treated individually. Rather, characters make up tokens such
+ as words and numbers, or act as separators between these tokens.
+ When comparing files, one is usually looking for
+ differences between these tokens, not the characters that make them up
+ or the characters that separate them.
+ .PP
+ What is needed is a program that first parses the input files
+ into tokens, and then applies a differencing algorithm to the token
+ sequences. 
+ In addition to finding differences in terms of tokens,
+ it is possible to interpret the tokens and
+ compare different types of tokens in different ways.  Numbers, for example,
+ can differ by a lot or a little.\**
+ .FS
+ Current differencing programs do not have such a notion because
+ the difference between two characters is a binary function.
+ Two characters are the same or they are not.
+ .FE
+ It is possible to use a tolerance when comparing two number tokens and
+ report only those differences that exceed the tolerance.
+ .SH
+ Design Issues
+ .PP
+ A serious design issue for such a program is how
+ complex to make the parse.  The
+ .I
+ deeper
+ .R
+ one goes in the parsing the larger
+ the unit of text that can be manipulated.  For instance, if one is looking
+ for differences in C code, a complete parse tree can be produced and
+ the differencing algorithm could examine insertion and deletion of entire
+ branches of the tree.  However, deep parsing requires much more
+ complex parsing and slower differencing algorithms.
+ .PP
+ Another design issue is deciding how to interpret the tokens.
+ Closer interpretation may lead to greater flexibility in comparing tokens, but
+ also results in a more cumbersome and error-prone implementation.
+ .PP
+ In the program described here, we attempt to keep both the depth
+ of the parse and the semantics of the tokens to a minimum.
+ The parse is a simple
+ lexical parse with the input files broken up into one dimensional
+ sequences of numbers, literal strings and white space.
+ Literal strings and white space are not interpreted. Numbers
+ are treated as representing points on the real number line.
+ .SH
+ Default Operation
+ .PP
+ .B
+ Spiff\**
+ .R
+ .FS
+ We picked the name as a way to pay a small tribute to that famous intergalactic
+ adventurer Spaceman Spiff[3].
+ .B
+ Spiff
+ .R
+ is also a contraction of "spiffy diff".
+ .FE
+ works very much like 
+ .B
+ diff.
+ .R
+ It reads two files, looks
+ for differences, and prints a listing of the
+ differences in the form of
+ an edit script.\**
+ .FS
+ An edit script is a sequence of insertions and deletions
+ that will transform the first file into the second.
+ .FE
+ As already suggested, 
+ .B
+ spiff
+ .R
+ parses the files into
+ literal strings and real numbers.
+ The definition of these tokens can be altered somewhat by the user
+ (more on this later).  For now, suffice it
+ to say that literals are strings like "cow", "sit",
+ "into", etc.  Real numbers look like "1.3", "1.6e-4" and so on.
+ All of the common formats for real numbers are recognized.
+ The only requirements for a string to be
+ treated as a real number is the presence
+ of a period and at least one digit.
+ By default, a string of digits without a decimal point
+ (such as "1988") is not considered to be a real number,
+ but rather a literal string.\**
+ Each non-alphanumeric character (such as #$@^&*)
+ is parsed into a separate literal token.
+ .FS 
+ Integer numbers are often used as indices, labels, and so on.
+ Under these circumstances, it is more appropriate to treat them as literals.
+ Our choice of default was driven by a design goal
+ of having 
+ .B
+ spiff
+ .R
+ be very conservative
+ when choosing to ignore differences.
+ .FE
+ .PP
+ Once 
+ .B
+ spiff
+ .R
+ determines the two sequences of tokens,
+ it compares members of the first sequence with
+ members of the second sequence.
+ If two tokens are of different types,
+ .B
+ spiff
+ .R
+ deems them to be different, regardless of their content.
+ If both tokens are literal tokens, 
+ .B
+ spiff
+ .R
+ will deem them
+ to be different if any of their characters differ.
+ When comparing two real numbers,
+ .B
+ spiff
+ .R
+ will deem them to be different only if
+ the difference in their values exceeds a user settable tolerance.
+ .SH
+ Altering Spiff's Operation 
+ .PP
+ To make 
+ .B
+ spiff
+ .R
+ more generally useful, the user can control:
+ .IP \(bu
+ how text strings are parsed into tokens 
+ .IP \(bu
+ how tokens of the same type are compared
+ .IP \(bu
+ the choice of differencing algorithm used
+ .IP \(bu
+ and the granularity of edit considered by the differencing algorithm.
+ .LP
+ .PP
+ These features are described next.
+ .SH
+ Altering the Parse
+ .PP
+ The operation of the parser can be altered in several ways.
+ The user can specify that delimited sections of text are to be ignored
+ completely.  This is useful for selectively ignoring the contents of
+ comments in programs.  Similarly, the user can specify that
+ delimited sections of text (including white space)
+ be treated as a single literal token.  So, literal strings in program
+ text can be treated appropriately.
+ Multiple sets of
+ delimiters may be specified at once (to handle cases such as the
+ Modula-2 programming language
+ where there are two ways to specify quoted strings). At present,
+ the delimiters must be fixed string (possibly restricted to the
+ beginning of the line) or end of line.
+ As a consequence of the mechanism for specifying literal strings,
+ multicharacter operators (such as the += operator in C)
+ can be parsed into a single token.
+ .PP
+ As yet, no provision is made for allowing delimiter
+ specification in terms of regular expressions.  This omission 
+ was made for the sake of simplifying the parser.
+ Nothing prevents the addition of regular expressions in the
+ future.  However, the simple mechanism
+ already in place handles the literal string and commenting conventions
+ for most well known programming languages.\**
+ .FS
+ See the manual page in the appendix for examples of handling
+ C, Bourne Shell, Fortran, Lisp, Pascal, and Modula-2.  The only
+ cases that are known not to work are comments in BASIC and
+ Hollerith strings in Fortran.
+ .FE
+ .PP
+ In addition to controlling literal string and comments, the user
+ may also specify whether to treat white space characters as any other
+ non-alphanumeric character (in other words, parse each white space
+ character into its own literal token),
+ whether to parse sign markers as part
+ of the number that they precede or as separate tokens, whether
+ to treat numbers without printed decimal markers (e.g. "1988") 
+ as real numbers rather than as literal strings, and whether
+ to parse real numbers into literal tokens.
+ .SH
+ Altering the Comparison of Individual Tokens
+ .PP
+ As mentioned earlier, the user can set a tolerance below which differences
+ between real numbers are ignored.  
+ .B
+ Spiff
+ .R
+ allows two kinds of tolerances:
+ absolute and relative. 
+ Specifying an absolute tolerance will cause 
+ .B
+ spiff
+ .R
+ to ignore differences
+ that are less than the specified value.
+ For instance, specifying an absolute tolerance of 0.01 will
+ cause only those differences greater than or equal to 0.01 to be reported.
+ Specifying a relative tolerance will cause 
+ .B
+ spiff
+ .R
+ to ignore differences that are
+ smaller than some fraction of the number of larger magnitude.
+ Specifically, the value of the tolerance is interpreted
+ as a fraction of the larger (in absolute terms) 
+ of the two floating point numbers being compared.
+ For example,
+ specifying a relative tolerance of 0.1
+ will cause the two floating point numbers 1.0 and 0.91 to be deemed within
+ tolerance. The numbers 1.0 and 0.9 will be outside the tolerance.
+ Absolute and relative tolerances can be OR'ed together.  In fact,
+ the most effective way to ignore differences that are due to roundoff errors
+ in floating point calculations is to use both
+ a relative tolerance (to handle limits in precision) as well as an absolute
+ tolerance (to handle cases when one number is zero and the other number is
+ almost zero).\**
+ .FS
+ All numbers differ from zero by 100% of their magnitude.  Thus, to handle
+ numbers that are near zero, one would have to specify a relative tolerance
+ of 100% which would be unreasonably large when both numbers are non-zero.
+ .FE
+ In addition, the user can specify an infinite tolerance.  This is useful
+ for checking the format of output while ignoring the actual numbers
+ produced.
+ .SH
+ Altering the Differencing Algorithm
+ .PP
+ By default, 
+ .B
+ spiff
+ .R
+ produces a minimal edit sequence (using the Miller/Myers differencing algorithm[4])
+ that will convert the first file into the second.
+ However, a minimal edit sequences is not always desirable. 
+ For example, for the following two tables of numbers:
+ .DS
+ 0.1   0.2   0.3				0.2   0.3   0.4
+ 0.4   0.5   0.6				0.5   0.6   0.7
+ .DE
+ a minimal edit sequence to convert the table on
+ the left into the table on the right be to
+ would delete the first number (0.1) and insert 0.7 at the end.\**
+ .FS
+ The problem of having the elements of tables become misaligned when
+ the differencing algorithm is trying
+ to find a minimal number of edits can be reduced somewhat
+ by retaining newlines and not using tolerances.
+ Unfortunately, it does not go away.
+ .FE
+ Such a result, while logically correct, does not provide a good picture
+ of the differences between the two files.
+ In general, for text with a very definite structure (such as tables),
+ we may not want to consider insertions and deletions at all, but
+ only one-to-one changes.\**
+ .FS
+ A "change" can be expressed as one deletion and one insertion at the same
+ point in the text.
+ .FE
+ So, rather than look for a minimal edit script, we
+ merely want to compare each token in the first file with
+ the corresponding token in the second file.
+ .PP
+ The user can choose which differencing algorithm to use
+ (the default Miller/Myers or
+ the alternative one-to-one comparison)
+ based upon what is known about the input files. In general,
+ files produced mechanically
+ (such the output from test suites) have a very regular structure
+ and the one-to-one comparison works surprisingly well.
+ For files created by humans, the Miller/Myers
+ algorithm is more appropriate.
+ There is nothing in
+ .B
+ spiff's
+ .R
+ internal design that limits
+ the number of differencing algorithms that it can run.
+ Other differencing algorithms,
+ in particular the one used in
+ .B
+ diff,
+ .R
+ will probably be added later.
+ .SH
+ Altering the Granularity of the Edit Sequence
+ .PP
+ By default,
+ .B
+ spiff
+ .R
+ produces an edit sequence
+ in terms of insertions and deletions of individual tokens.
+ At times it may be more useful to
+ treat the contents of the files as tokens when looking for differences
+ but
+ express the edit script in terms of entire lines of the files rather
+ than individual tokens.\**
+ .FS
+ For instance, if one wants to have 
+ .B
+ spiff
+ .R
+ produce output that can be fed into
+ the
+ .B
+ ed
+ .R
+ editor.
+ .FE
+ .B
+ Spiff
+ .R
+ provides a facility for restricting the edits to entire lines.
+ .SH
+ Treating Parts of the Files Differently
+ .PP
+ For complex input files, it is important that different parts of the
+ file be treated in different ways.  In other words, it may be impossible
+ to find one set of parsing/differencing rules that work well for the
+ entire file.
+ .B
+ Spiff
+ .R
+ can differentiate between parts of the input files on two bases:
+ within a line and between lines.
+ Within a line, a different tolerance can be applied to each real number.
+ The tolerances are specified in terms of the ordinal position of the
+ numbers on the line (i.e. one tolerance is applied to the first real number
+ on each line, a different tolerance is applied to the second number on
+ each line, a third tolerance is applied to the third, and so on).  If more
+ numbers appear on a line than there are tolerances specified, the last
+ tolerance is applied to all subsequent numbers on the line (i.e., if the user
+ specifies three tolerances, the third is applied to the third, fourth
+ fifth, . . . number on each line).  This feature is useful for applying
+ different tolerances to the different columns of a table of numbers.
+ .PP
+ Between lines, the user can place "embedded commands" in the input files.
+ These commands
+ are instructions to parser that can change what tolerances are attached
+ to real numbers and the commenting and literal string conventions used by the
+ parser.  Embedded commands are flagged to the parser
+ by starting the line with a user-specified
+ escape string.  By combining within line and between line differentiation,
+ it is possible for the user to specify a different tolerance
+ for every single real number in the input files.
+ .SH
+ Visual Mode
+ .PP
+ So far,
+ .B
+ spiff's
+ .R
+ operation as an intelligent filter has been described.
+ .B
+ Spiff
+ .R
+ also has an interactive mode.
+ When operating in interactive mode,
+ .B
+ spiff
+ .R
+ places corresponding sections of the input files 
+ side by side on user's screen.\**
+ .FS
+ Although the current implementation of
+ .B
+ spiff
+ .R
+ runs in many environments,
+ interactive mode works only under the MGR window manager.[5]
+ Other graphics interfaces will probably be added over time.
+ .FE
+ Tokens are compared using a one-to-one ordinal comparison, and any tokens that
+ are found to be different are highlighted in reverse video.
+ The user can interactively change the tolerances and 
+ .B
+ spiff
+ .R
+ will alter the display
+ to reflect which real numbers exceed the new tolerances.
+ Other commands allow the user to page through the file and exit.
+ .SH
+ Performance
+ .PP
+ Two components of 
+ .B
+ spiff,
+ .R
+ the parser and the differencing algorithm,
+ account for most of the execution time.  Miller and Myers compare their
+ algorithm to the one used in the diff program.  To restate their results,
+ the Miller/Myers algorithm is faster for files
+ that have relatively few differences but much
+ slower (quadratic time) for files with a great many differences.
+ .PP
+ For cases where the files do not differ greatly,
+ parsing the input files takes most of the time (around 80% of the total).\**
+ .FS
+ No effort has yet been made to make the parser run more quickly.
+ A faster parser could no doubt be written by generating a special state machine.
+ .FE
+ The performance of the parser is roughly similar to programs that do a similar
+ level of parsing (i.e. programs that must examine each character in the file).
+ For files where roughly half of the tokens are real numbers, 
+ .B
+ spiff
+ .R
+ takes about twice as long to parse the input files
+ as an
+ .B
+ awk
+ .R
+ program that counts the number of words in a file:\**
+ .FS
+ For
+ .B
+ awk,
+ .R
+ a word is any string separated by white space.
+ .FE
+ .B
+ .DS
+ awk '{total += NF}' firstfile secondfile
+ .DE
+ .R
+ .PP
+ The time that it takes 
+ .B
+ spiff
+ .R
+ to parse a file is substantially
+ increased if scanning is done for comments
+ and delimited literal strings.  The precise effect depends upon the length of
+ the delimiters, whether they are restricted to appear at beginning of line, and
+ the frequency with which literals and comments appear in the input files.
+ As an example, adding the 12 literal conventions\**
+ .FS
+ One literal convention is for C literal strings.  The rest enumerate multicharacter
+ operators.
+ .FE
+ and 1 commenting convention
+ required for C code roughly doubles the time required to parse input files.\**
+ .FS
+ So in total, it takes 
+ .B
+ spiff
+ .R
+ about 4 times longer to parse a C program than it takes
+ .B
+ awk
+ .R
+ to count the number of words in the same file.
+ .FE
+ .PP
+ A more complete approach to evaluating
+ .B
+ spiff's
+ .R
+ performance must measure the total time that it takes for the user to complete a
+ differencing task.  For example, consider one of the
+ test suites for the S statistical
+ analysis package mentioned at the beginning of this paper.
+ The output file for each machine is 427 lines long and contains
+ 1090 floating point numbers.  It takes
+ .B
+ diff 
+ .R
+ approximately 2 seconds on one of our "6 MIPS"\** computers
+ .FS
+ We will not comment on the usefulness of "MIPS" as a measure
+ of computing speed.  The numbers provided are only intended to
+ give the reader some vague idea of how fast these programs run. 
+ .FE
+ to compare the two files and produce
+ an edit script that is 548 lines long containing 1003 "differences"
+ in the floating point numbers.  It takes the average tester
+ 5 minutes to print out the edit script and roughly 2 hours to examine
+ the output by hand to determine that the machines are, in fact,
+ both giving nearly identical answers.  The total time needed is
+ 2 hours 5 minutes and 2 seconds.
+ .PP
+ In contrast, it takes
+ .B
+ spiff
+ .R
+ approximately 6 seconds on one of our "6 MIPS" computers to
+ produce an output file that is 4 lines long.\**
+ .FS
+ The output would be zero length except that the output of the
+ .B
+ time
+ .R
+ command is built into the S tests.
+ The timing information could easily be ignored using
+ .B
+ spiff's
+ .R
+ embedded commands. But, as we shall see, it hardly seems worth the trouble.
+ .FE
+ It takes the average tester 30 seconds to examine
+ .B
+ spiff's
+ .R
+ output.  The total for
+ .B
+ spiff
+ .R
+ is 36 seconds.  Therefore for this case, 
+ .B
+ spiff
+ .R
+ will get the job done roughly 208.88 times faster than
+ .B
+ diff.
+ .R
+ .PP
+ In general, it is misleading to compare
+ .B
+ spiff's
+ .R
+ speed with that of
+ .B
+ diff.
+ .R
+ While both programs are looking for differences between files,
+ they operate on very different types of data (tokens vs. bytes).
+ An analogous comparison could be made between the speed of an assembler
+ and the speed of a C compiler.  They are both language translators.
+ One runs much faster than the other.
+ None the less, most programmers use the slower program
+ whenever possible.
+ .SH
+ Using Spiff For Making Regression Tests Of Software
+ .PP
+ We envision 
+ .B
+ spiff
+ .R
+ to be the first of several tools for aiding in the now
+ arduous task of making regression tests.\**
+ .FS
+ In software engineering parlance, a "regression test" is the process by
+ which a tester checks to make sure that the new version of a piece of
+ software still performs the same way as the older versions 
+ on overlapping tasks.
+ .FE
+ Given 
+ .B
+ spiff's
+ .R
+ current capabilities, the regression test designer can
+ take the output of an older version of software and through
+ the use of literal string and commenting conventions,
+ specify what parts of the output must remain identical and
+ what sections can change completely.  By specifying tolerances, the test
+ designer can take into account how much of a difference in floating
+ point calculations is acceptable.
+ .PP
+ The test designer is also free to
+ edit the output from the older version of the software and add embedded
+ commands that can instruct 
+ .B
+ spiff
+ .R
+ to treat various parts of the output
+ differently.  The newly edited output can then serve as a template for
+ the output of later versions of the software.
+ .PP
+ Obviously, editing output by hand is a very low level mechanism for adding
+ specification information.  It is our intention that 
+ .B
+ spiff
+ .R
+ will become
+ the last element in a pipeline of programs.  Programs (as yet unwritten) located
+ earlier in the pipeline
+ can implement a higher level representation of the specification information.
+ They read in the old and new input files, add the appropriate embedded commands,
+ and then pass the results to 
+ .B
+ spiff
+ .R
+ which will do the actual differencing.
+ .SH
+ Future Work
+ .PP
+ There are many features that could be added to 
+ .B
+ spiff
+ .R
+ (if there are not
+ too many already).  Some of these include: 
+ .IP \(bu
+ Using separate differencing algorithms on separate sections of the file
+ and/or limiting the scope of an edit sequence (fencing) 
+ .IP \(bu
+ Providing a more general mechanism for specifying comments and literals
+ (perhaps allowing specification in terms of regular expressions).
+ As yet, we have not encountered any important cases where regular expressions
+ have been needed.  Until such a case is encountered, we will leave regular
+ expressions out in the name of simplicity.
+ .IP \(bu
+ Allowing for a more general specification of what lines should look like.
+ At present, the user can only specify tolerances for numbers as a function
+ of their ordinal position on a line.  The difficulty in expanding the
+ specification abilities of 
+ .B
+ spiff
+ .R
+ is knowing when to stop.  In the extreme,
+ we might add all of the functionality of a program such as
+ .B
+ awk.\**
+ .R
+ .FS
+ Imagine handling the case such as
+ "apply this tolerance to all numbers that appear
+ on a line starting with the word `foo' but only if the number is between 1.9
+ and 3.6 and the word `bar' does not appear on the line".
+ .FE
+ We hope to keep 
+ .B
+ spiff
+ .R
+ as simple as possible.  Our first efforts in
+ this direction will try to implement higher level specification functions
+ outside of 
+ .B
+ spiff.
+ .R
+ .SH
+ Acknowledgements
+ .PP
+ First and foremost, we thank Stu Feldman for his endless patience, constant encouragement
+ and numerous good ideas. We also extend thanks to Doug McIlroy for bringing the Miller/Myers
+ algorithm to our attention, Nat Howard for a key insight
+ and for his editorial comments
+ and Steve Uhler and Mike Bianchi for their editorial comments.
+ .SH
+ References
+ .IP [1]
+ Hunt,J.W. and M.D. McIlroy.
+ .I
+ An Algorithm For Differential File Comparisons, 
+ .R
+ .B
+ Bell Labs Computer Science Technical Report,
+ .R
+ Number 41, 1975.
+ .IP [2]
+ Becker,R.A. and J.M. Chambers (1984).
+ .B
+ S \- An Interactive Environment For Data Analysis And
+ Graphics.
+ .R
+ Belmont, CA: Wadsworth Inc.
+ .IP [3]
+ Watterson, B. (1987).
+ .B
+ Calvin and Hobbes.
+ .R
+ New York: Andrews, McMeel & Parker.
+ .IP [4]
+ Miller, W. and E.W. Myers.
+ .I
+ A File Comparison Program,
+ .R
+ .B
+ Software \-
+ Practice and Experience
+ .R
+ 15, 11, 1025-1040, 1985.
+ .IP [5]
+ Uhler, S.A.
+ .I
+ MGR -- A Window Manager For UNIX,
+ .R
+ Sun User's Group Meeting. September 1986.
+ .LP


Index: llvm/test/Programs/MultiSource/Applications/spiff/parse.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/parse.c:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/parse.c	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,803 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ 
+ #ifndef lint
+ static char rcsid[]= "$Header: /home/vadve/shared/PublicCVS/llvm/test/Programs/MultiSource/Applications/spiff/parse.c,v 1.1 2004/06/01 20:35:58 gaeke Exp $";
+ #endif
+ 
+ #include "misc.h"
+ #include "flagdefs.h"
+ #include "float.h"
+ #include "tol.h"
+ #include "token.h"
+ #include "line.h"
+ #include "command.h"
+ #include "comment.h"
+ #include "parse.h"
+ 
+ 
+ #include <ctype.h>
+ 
+ #define _P_PARSE_CHATTER	1000
+ 
+ 
+ static	int _P_realline;	/* loop counter */
+ static  int _P_fnumb;
+ 
+ static  char *_P_nextchr;	/* pointer to the next character to parse */
+ static	char *_P_firstchr;		/* pointer to the beginning of the line being parsed */
+ static	int _P_next_tol;		/* number of floats seen on this line */
+ static	int _P_stringsize;		/* count of number of characters that are being
+ 					read into a comment or literal */
+ static int _P_has_content;	/* flag to indicate if the line being
+ 					parsed has any tokens on it */
+ static int _P_start;		/* first line to parse */
+ static int _P_lcount;		/* number of lines to parse */
+ 
+ static int _P_flags;		/* location for global flags */
+ 
+ /*
+ **	by default, "words" can be made up of numbers and letters
+ **	the following code allows for extending the alphabet that can
+ **	be used in words. this is useful for handling languages such
+ **	as C where the underscore character is an allowable character
+ **	in an identifier.  If a character (such as underscore) is NOT added
+ **	to the alphabet, the identifier will be broken into 2 or more "words"
+ **	by the parser.  as such the two sequences
+ **			one_two
+ **		and
+ **			one _ two
+ **	would look identical to spiff.
+ */
+ #define _P_ALPHALEN 256
+ static char _P_alpha[_P_ALPHALEN];
+ 
+ static void
+ _P_alpha_clear()
+ {
+ 	*_P_alpha = '\0';
+ }
+ 
+ 
+ static int
+ _P_in_alpha(chr)
+ char chr;
+ {
+ #ifndef ATT
+ 	extern char *index(const char *s, int c);
+ #endif
+ 	/*
+ 	**	special case when string terminator
+ 	**	is handed to us
+ 	*/
+ 	if ('\0' == chr)
+ 		return(0);
+ 
+ #ifdef ATT
+ 	return((int) strchr(_P_alpha,chr));
+ #else
+ 	return((int) index(_P_alpha,chr));
+ #endif
+ }
+ 
+ void
+ P_addalpha(ptr)
+ char *ptr;
+ {
+ 	char buf[Z_LINELEN];
+ 
+ 	S_wordcpy(buf,ptr);		/* copy up to (but not including)
+ 						the first whitespace char */
+ 
+ 	if ((strlen(_P_alpha) + strlen(buf)) >= _P_ALPHALEN)
+ 	{
+ 		Z_fatal("too many characters added to extended alphabet");
+ 	}
+ 	(void) strcat(_P_alpha,buf);
+ }
+ 
+ /*
+ **	put parser in a default state
+ */
+ 
+ static char _P_dummyline[2];	/* a place to aim wild pointers */
+ static void
+ _P_initparser()
+ {
+ 	_P_dummyline[0] = '\0';
+ 
+ 	/*
+ 	**	now reset all the state of each module
+ 	*/
+ 	C_clear_cmd();		/* disable embedded command key word */ 
+ 	T_clear_tols();
+ 	W_clearcoms();
+ 	W_clearlits();
+ 	_P_alpha_clear();	/* disable extended alphabet */
+ 
+ 	/*
+ 	**	and set state as defined by execute-time commands.
+ 	*/
+ 	C_docmds();
+ 	return;
+ }
+ 
+ 
+ static int
+ _P_needmore()
+ {
+ 	return(*_P_nextchr == '\0');
+ }
+ 
+ static int
+ _P_nextline()
+ {
+ 	/*
+ 	**	if the line that we just finished had
+ 	**		some content,  increment the count
+ 	*/
+ 	if (_P_has_content)
+ 	{
+ 		L_incclmax(_P_fnumb);
+ 		/*
+ 		**	if the previous line had a token
+ 		**		increment the line
+ 		*/
+ 		if (L_getcount(_P_fnumb,L_gettlmax(_P_fnumb)))
+ 		{
+ 			L_inctlmax(_P_fnumb);
+ 			L_setcount(_P_fnumb,L_gettlmax(_P_fnumb),0);
+ 		}
+ 		_P_has_content = 0;
+ 	}
+ 
+ 	/*
+ 	**	reset the number of floats seen on the line
+ 	*/
+ 	_P_next_tol = 0;
+ 
+ 	/*
+ 	**	get another line if there is one available
+ 	*/
+ 	_P_realline++;
+ 	if (_P_realline >= _P_start+_P_lcount)
+ 	{
+ 		return(1);
+ 	}
+ 
+ 	_P_firstchr = _P_nextchr = L_getrline(_P_fnumb,_P_realline);
+ 	/*
+ 	**	and look for a command
+ 	*/
+ 	if (C_is_cmd(_P_firstchr))
+ 	{
+ 		_P_nextchr = _P_dummyline;
+ 		_P_has_content = 0;
+ 	}
+ 	else
+ 	{
+ 		/*
+ 		**	we have a real line, so set up the index
+ 		*/
+ 		L_setclindex(_P_fnumb,L_getclmax(_P_fnumb),_P_realline);
+ 		_P_has_content = 1;
+ 	}
+ 	return(0);
+ }
+ 
+ /*
+ **	the following three routines (_P_litsnarf, _P_bolsnarf, and _P_comsnarf
+ **	all do roughly the same thing. they scan ahead and collect the
+ **	specified string, move _P_nextchr to the end of the
+ **	comment or literal and return 1 if we run off the end of file,
+ **	0 otherwise.  it would have been nice to have 1 routine handle
+ **	all three task (there is much common code), however there were
+ **	so enough differences, (for instance, only comments check for nesting,
+ **	only literals need to set _P_stringsize, etc)
+ **	that I decided to split them up.
+ */
+ static int
+ _P_litsnarf(litptr)
+ W_lit litptr; 
+ {
+ 	_P_stringsize = 0;
+ 	/*
+ 	**	skip the start of literal string
+ 	*/
+ 	_P_nextchr += strlen(W_litbegin(litptr));
+ 	_P_stringsize += strlen(W_litbegin(litptr));
+ 	/*
+ 	**	is there a separate end string?
+ 	**		if not, then we're done
+ 	*/
+ 	if ('\0' == *(W_litend(litptr)))
+ 	{
+ 		return(0);
+ 	}
+ 	/*
+ 	**	loop once for each character in the literal
+ 	*/
+ 	while(1)
+ 	{
+ 		/*
+ 		**	if we are out of characters, move on to next line
+ 		*/
+ 		if (_P_needmore())
+ 		{
+ 			if (_P_nextline())
+ 			{
+ 				return(1);
+ 			}
+ 			if (!_P_has_content)
+ 			{
+ 				/*
+ 				**	since we've just gotten a command
+ 				**		check to see if this literal
+ 				**		is still legit ...
+ 				**		could have just been reset
+ 				**		by the command
+ 				*/
+ 				if (!W_is_lit(litptr))
+ 				{
+ 					return(0);
+ 				}
+ 			}
+ 		} /* if _P_needmore */
+ 
+ 		/*
+ 		**	see if we have an escaped end of literal string
+ 		*/
+ 		if (('\0' != *(W_litescape(litptr))) && /* escape string exists */
+ 		  !S_wordcmp(_P_nextchr,
+ 			   W_litescape(litptr)) &&     /* and escape matches */
+ 		  !S_wordcmp(_P_nextchr+strlen(W_litescape(litptr)),
+ 			   W_litend(litptr)))	     /* and endstring matches */
+ 		{
+ 			_P_nextchr += strlen(W_litescape(litptr))
+ 					+ strlen(W_litend(litptr));
+ 			_P_stringsize += strlen(W_litescape(litptr))
+ 					+ strlen(W_litend(litptr));
+ 			continue;
+ 		}
+ 
+ 		/*
+ 		**	see if we have an end of literal string
+ 		*/
+ 		if (!S_wordcmp(_P_nextchr,W_litend(litptr))) /* escape matches */
+ 		{
+ 			_P_nextchr += strlen(W_litend(litptr));
+ 			_P_stringsize += strlen(W_litend(litptr));
+ 			return(0);
+ 		}
+ 		/*
+ 		**	this must be yet another character in the literal, so
+ 		**	just snarf it up
+ 		*/
+ 		_P_nextchr++;
+ 		_P_stringsize++;
+ 	}	/* while loop once for each character */
+ 
+ #ifndef lint
+ 	Z_fatal("shouldn't execute this line at the end of _P_litsnarf");
+ #endif
+ } /* _P_litsnarf */
+ 
+ static int
+ _P_bolsnarf(bolptr)
+ W_bol bolptr; 
+ {
+ 	/*
+ 	**	skip the start of comment string
+ 	*/
+ 	_P_nextchr += strlen(W_bolbegin(bolptr));
+ 	/*
+ 	**	is there a separate end string
+ 	**		if not, then we're done
+ 	*/
+ 	if ('\0' == *(W_bolend(bolptr)))
+ 	{
+ 		return(0);
+ 	}
+ 	/*
+ 	**	loop once for each character in the comment
+ 	*/
+ 	while(1)
+ 	{
+ 		/*
+ 		**	if we are out of characters,move on to next line
+ 		*/
+ 		if (_P_needmore())
+ 		{
+ 			if (_P_nextline())
+ 			{
+ 				return(1);
+ 			}
+ 			if (!_P_has_content)
+ 			{
+ 				/*
+ 				**	since we've just gotten a command
+ 				**		check to see if this comment
+ 				**		is still legit ... comments
+ 				**		could have just been reset
+ 				**		by the command
+ 				*/
+ 				if (!W_is_bol(bolptr))
+ 				{
+ 					return(0);
+ 				}
+ 			}
+ 		} /* if at end of line */
+ 
+ 		/*
+ 		**	see if we have an escaped end of comment string
+ 		*/
+ 		if ('\0' != *(W_bolescape(bolptr)) && /* escape string exists */
+ 		  !S_wordcmp(_P_nextchr,
+ 			   W_bolescape(bolptr)) &&     /* and escape matches */
+ 		  !S_wordcmp(_P_nextchr+strlen(W_bolescape(bolptr)),
+ 			   W_bolend(bolptr)))	 /* and end string matches */
+ 		{
+ 			_P_nextchr += strlen(W_bolescape(bolptr))
+ 					+ strlen(W_bolend(bolptr));
+ 			continue;
+ 		}
+ 
+ 		/*
+ 		**	see if we have an end of comment string
+ 		*/
+ 		if (!S_wordcmp(_P_nextchr,W_bolend(bolptr)))
+ 		{
+ 			_P_nextchr += strlen(W_bolend(bolptr));
+ 			return(0);
+ 		}
+ 		/*
+ 		**	this must be yet another character in the comment, so
+ 		**	just snarf it up
+ 		*/
+ 		_P_nextchr++;
+ 	}	/* while loop once for each character */
+ 
+ #ifndef lint
+ 	Z_fatal("shouldn't execute this line in at end of _P_bolsnarf");
+ #endif
+ } /* _P_bolsnarf */
+ 
+ /*
+ **	pass over a comment -- look for nexting
+ */
+ static int
+ _P_comsnarf(comptr)
+ W_com comptr; 
+ {
+ 	int depth = 1; /* nesting depth */
+ 	/*
+ 	**	skip the start of comment string
+ 	*/
+ 	_P_nextchr += strlen(W_combegin(comptr));
+ 
+ 	/*
+ 	**	is there a separate end string
+ 	**		if not, then we're done
+ 	*/
+ 	if ('\0' == *(W_comend(comptr)))
+ 	{
+ 		return(0);
+ 	}
+ 	/*
+ 	**	loop once for each character in the comment
+ 	*/
+ 	while(1)
+ 	{
+ 		/*
+ 		**	if we are out of characters, move on to next line
+ 		*/
+ 		if (_P_needmore())
+ 		{
+ 			if (_P_nextline())
+ 			{
+ 				return(1);
+ 			}
+ 			if (!_P_has_content)
+ 			{
+ 				/*
+ 				**	since we've just gotten a command
+ 				**		check to see if this comment
+ 				**		is still legit ... comments
+ 				**		could have just been reset
+ 				**		by the command
+ 				*/
+ 				if (!W_is_com(comptr))
+ 				{
+ 					return(0);
+ 				}
+ 			}
+ 		} /* if at end of line */
+ 
+ 		/*
+ 		**	see if we have an escaped end of comment string
+ 		*/
+ 		if ('\0' != *(W_comescape(comptr)) &&  /* escape string exists */
+ 		  !S_wordcmp(_P_nextchr,
+ 			   W_comescape(comptr)) &&    /* and escape matches */
+ 		  !S_wordcmp(_P_nextchr+strlen(W_comescape(comptr)),
+ 			   W_comend(comptr)))	/* and end string matches */
+ 		{
+ 			/*
+ 			** skip over the escape sequence and the end sequence
+ 			*/
+ 			_P_nextchr += strlen(W_comescape(comptr))
+ 					+ strlen(W_comend(comptr));
+ 			continue;
+ 		}
+ 
+ 		/*
+ 		**	see if we have an end of comment string
+ 		*/
+ 		if (!S_wordcmp(_P_nextchr,W_comend(comptr))) /* end  matches */
+ 		{
+ 			/*
+ 			**	skip over the end sequence
+ 			*/
+ 			_P_nextchr += strlen(W_comend(comptr));
+ 			if (W_is_nesting(comptr))
+ 			{
+ 				depth--;
+ 				if (0 == depth)
+ 					return(0);
+ 			}
+ 			else
+ 			{
+ 				return(0);
+ 			}
+ 			continue;
+ 		}
+ 		/*
+ 		**	see if we have another beginning of comment string
+ 		*/
+ 		if (W_is_nesting(comptr) &&
+ 			!S_wordcmp(_P_nextchr,W_comend(comptr))) /* end matches */
+ 		{
+ 			_P_nextchr += strlen(W_comend(comptr));
+ 			depth++;
+ 			continue;
+ 		}
+ 		/*
+ 		**	this must be yet another character in the comment, so
+ 		**	just snarf it up
+ 		*/
+ 		_P_nextchr++;
+ 	}	/* while loop once for each character */
+ 
+ #ifndef lint
+ 		Z_fatal("should not execute this line in _P_comsnarf\n");
+ #endif
+ 
+ } /* _P_comsnarf */
+ 
+ 
+ /*
+ **	parse a file
+ */
+ static void
+ _P_do_parse()
+ {
+ 
+ 	char *ptr;		/* scratch space */
+ 	int tmp;
+ 	int ret_code;
+ 
+ 	K_token newtoken;
+ 	W_bol bolptr;
+ 	W_com comptr;
+ 	W_lit litptr;
+ 
+ 	int startline, endline, startpos;
+ 
+ 	/*
+ 	**	main parsing loop
+ 	*/
+ 	while (1)
+ 	{
+ 		/*
+ 		**	get more text if necessary
+ 		*/
+ 		if (_P_needmore())
+ 		{
+ 			if (_P_nextline())
+ 			{
+ 				return;
+ 			}
+ 
+ 			/*
+ 			**	if the line contains nothing of interest,
+ 			**		try again
+ 			*/
+ 			if (!_P_has_content)
+ 			{
+ 				continue;
+ 			}
+ 
+ 			/*
+ 			**	check to see if this line starts a comment
+ 			*/
+ 			if ((bolptr = W_isbol(_P_firstchr)) != W_BOLNULL)
+ 			{
+ 				if (_P_bolsnarf(bolptr))
+ 				{
+ 					return;
+ 				}
+ 				continue;
+ 			}
+ 		} /* if _P_needmore */
+ 
+ 		/*
+ 		**	skip whitespace
+ 		*/
+ 		if (!(U_INCLUDE_WS & _P_flags) && isspace(*_P_nextchr))
+ 		{
+ 			_P_nextchr++;
+ 			continue;
+ 		}
+ 
+ 		/*
+ 		**	check to see if this character starts a comment
+ 		*/
+ 		if ((comptr = W_iscom(_P_nextchr)) != W_COMNULL)
+ 		{
+ 			if (_P_comsnarf(comptr))
+ 			{
+ 				return;
+ 			}
+ 			continue;
+ 		}
+ 
+ 		/*
+ 		**	if there aren't any tokens on this line already
+ 		**	set up the index from the token line to the content line
+ 		*/
+ 		if (!L_getcount(_P_fnumb,L_gettlmax(_P_fnumb)))
+ 		{
+ 			L_settlindex(_P_fnumb,
+ 					L_gettlmax(_P_fnumb),
+ 					L_getclmax(_P_fnumb));
+ 			/*
+ 			**	and the pointer from the token line to the 
+ 			** 	first  token on the line
+ 			*/
+ 			L_setindex(_P_fnumb,
+ 					L_gettlmax(_P_fnumb),
+ 					K_gettmax(_P_fnumb));
+ 		}
+ 
+ 		startline =  L_tl2cl(_P_fnumb,L_gettlmax(_P_fnumb));
+ 		startpos = _P_nextchr-_P_firstchr;
+ 
+ 		newtoken = K_maketoken();
+ 		K_setline(newtoken,L_gettlmax(_P_fnumb));
+ 		K_setpos(newtoken,startpos);
+ 
+ 		ret_code = 0;
+ 		/*
+ 		**	check to see if this character starts a
+ 		**		delimited literal string
+ 		*/
+ 		if ((litptr = W_islit(_P_nextchr)) != W_LITNULL)
+ 		{
+ 			ret_code = _P_litsnarf(litptr);
+ 			K_settype(newtoken,K_LIT);
+ 			S_allocstr(&ptr,_P_stringsize);
+ 			/*
+ 			**	fixed nasty memory bug here by adding else
+ 			**	old code copied entire line even if literal
+ 			**	ended before the end of line
+ 			**		should check into getting strcpy loaded
+ 			**		locally
+ 			*/
+ 			endline = L_getclmax(_P_fnumb);
+ 			if (endline > startline)
+ 			{
+ 				/*
+ 				**	copy in the first line of the literal
+ 				*/
+ 				(void) strcpy(ptr,
+ 					      L_getcline(_P_fnumb,startline)
+ 							+startpos);
+ 				/*
+ 				**	now copy all the lines between
+ 				**		the first and last
+ 				*/
+ 				for (tmp=startline+1;tmp<endline;tmp++)
+ 				{
+ 					(void) strcat(ptr,
+ 						      L_getcline(_P_fnumb,tmp));
+ 				}
+ 				/*
+ 				**	and now copy in the last line
+ 				*/
+ 				(void) strncat(ptr,
+ 					       L_getcline(_P_fnumb,endline),
+ 					       _P_stringsize-strlen(ptr));
+ 			}
+ 			else
+ 			{
+ 				(void) strncpy(ptr,
+ 					       L_getcline(_P_fnumb,startline)
+ 								+startpos,
+ 					      _P_stringsize);
+ 				/*
+ 				**	terminate the string you just copied
+ 				*/
+ 				ptr[_P_stringsize] = '\0';
+ 			}
+ 			K_settext(newtoken,ptr);
+ 		} /* if is_lit */
+ 
+ 		/*
+ 		**	see if this is a floating point number
+ 		*/
+ 		else if ((tmp = F_isfloat(_P_nextchr,
+ 				       _P_flags & U_NEED_DECIMAL,
+ 				       _P_flags & U_INC_SIGN)) != 0)
+ 		{
+ 			K_saventext(newtoken,_P_nextchr,tmp);
+ 			K_settype(newtoken,K_FLO_NUM);
+ 			if (!(_P_flags & U_BYTE_COMPARE))
+ 			{
+ 				K_setfloat(newtoken,
+ 					   F_atof(K_gettext(newtoken),
+ 					   USE_ALL));
+ 
+ 				/*
+ 				**	assign the curent tolerance
+ 				*/
+ 				K_settol(newtoken,T_gettol(_P_next_tol));
+ 			}
+ 
+ 			/*
+ 			**	use next tolerance in the
+ 			**		specification if there is one
+ 			*/
+ 			if (T_moretols(_P_next_tol))
+ 			{
+ 				_P_next_tol++;
+ 			}
+ 			/*
+ 			**	and move pointer past the float
+ 			*/
+ 			_P_nextchr += tmp;
+ 		}
+ 
+ 		/*
+ 		**	is this a fixed point number
+ 		*/
+ 		else if (isdigit(*_P_nextchr))
+ 		{
+ 			for(ptr=_P_nextchr; isdigit(*ptr); ptr++)
+ 			{
+ 			}
+ 			K_saventext(newtoken,_P_nextchr,ptr-_P_nextchr);
+ 			K_settype(newtoken,K_LIT);
+ 			_P_nextchr = ptr;
+ 		}
+ 
+ 		/*
+ 		**	try an alpha-numeric word
+ 		*/
+ 		else if (isalpha(*_P_nextchr) || _P_in_alpha(*_P_nextchr))
+ 		{
+ 			/*
+ 			**	it's a multi character word
+ 			*/
+ 			for(ptr = _P_nextchr;
+ 			    isalpha(*ptr)
+ 				|| isdigit(*ptr)
+ 				|| _P_in_alpha(*ptr);
+ 			    ptr++)
+ 			{
+ 			}
+ 			K_saventext(newtoken,_P_nextchr,ptr-_P_nextchr);
+ 			K_settype(newtoken,K_LIT);
+ 			_P_nextchr = ptr;
+ 		}
+ 		else
+ 		{
+ 			/*
+ 			**	otherwise, treat the char itself as a token
+ 			*/
+ 			K_saventext(newtoken,_P_nextchr,1);
+ 			K_settype(newtoken,K_LIT);
+ 			_P_nextchr++;
+ 		}
+ 
+ 		K_settoken(_P_fnumb,K_gettmax(_P_fnumb),newtoken);
+ 		L_inccount(_P_fnumb,L_gettlmax(_P_fnumb));
+ 		/*
+ 		**	if we are out of space, complain and quit
+ 		*/
+ 		if (K_inctmax(_P_fnumb))
+ 		{
+ 			(void) sprintf(Z_err_buf,
+      "warning -- to many tokens in file only first %d tokens will be used.\n",
+ 				       K_MAXTOKENS);
+ 			Z_complain(Z_err_buf);
+ 			return;
+ 		}
+ #ifndef NOCHATTER
+ 		if (0 == (K_gettmax(_P_fnumb) % _P_PARSE_CHATTER))
+ 		{
+ 			int max = K_gettmax(_P_fnumb);
+ 			(void) sprintf(Z_err_buf,
+ 				"scanned %d words from file #%d\n",
+ 					max,_P_fnumb+1);
+ 			Z_chatter(Z_err_buf);
+ 		}
+ #endif
+ 
+ 		/*
+ 		**	are we done?
+ 		*/
+ 		if(ret_code)
+ 		{
+ 			return;
+ 		}
+ 	}   /* loop once per object on a line */
+ 
+ #ifndef lint 
+ 	Z_fatal("this line should never execute");
+ #endif
+ }
+ 
+ void
+ P_file_parse(num,strt,lcnt,flags)
+ int num;	/* file number */
+ int strt;	/* first line to parse expressed in real line numbers */
+ int lcnt;	/* max number of lines to parse */
+ int flags;	/* flags for controlling the parse mode */
+ {
+ 	/*
+ 	**	set module-wide state variables
+ 	*/
+ 	_P_fnumb = num;		
+ 	_P_start = strt;	
+ 	_P_lcount = lcnt;
+ 	_P_flags = flags;
+ 
+ 	_P_initparser();
+ 
+ 	_P_nextchr = _P_dummyline;
+ 
+ 	_P_has_content = 0;
+ 	_P_next_tol = 0;
+ 	L_setcount(_P_fnumb,L_gettlmax(_P_fnumb),0);
+ 	/*
+ 	**	start everything back one line (it will be incremented
+ 	**		just before the first line is accessed
+ 	*/
+ 	_P_realline = _P_start-1;
+ 
+ 	_P_do_parse();
+ 
+ 	/*
+ 	**	if the last line had content, increment the count
+ 	*/
+ 	if (_P_has_content)
+ 	{
+ /*
+ **	this code will get executed if we stopped parsing in the middle
+ **	of a line.  i haven't looked at this case carefully.
+ **	so, there is a good chance that it is buggy.
+ */
+ (void) sprintf(Z_err_buf,"parser got confused at end of file\n");
+ Z_complain(Z_err_buf);
+ 		L_incclmax(_P_fnumb);
+ 		if (L_getcount(_P_fnumb,L_gettlmax(_P_fnumb)))
+ 			L_inctlmax(_P_fnumb);
+ 	}
+ 	return;
+ }


Index: llvm/test/Programs/MultiSource/Applications/spiff/parse.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/parse.h:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/parse.h	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,10 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ extern void P_file_parse();
+ extern void P_addalpha();


Index: llvm/test/Programs/MultiSource/Applications/spiff/spiff.1
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/spiff.1:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/spiff.1	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,454 ----
+ .ll 6i
+ .pl 10.5i
+ .po 1.25i
+ .\"	@(#)spiff.1	1.0 (Bellcore) 9/20/87
+ .\"
+ .lt 6.0i
+ .TH SPIFF 1 "February 2, 1988"
+ .AT 3
+ .SH NAME
+ spiff \- make controlled approximate comparisons between files 
+ .SH SYNOPSIS
+ .B spiff
+ [
+ .B \-s
+ script ] [
+ .B \-f
+ sfile ] [
+ .B \-bteviqcdwm
+ ] [
+ .B \-a
+ \(br
+ .B \-r
+ value ] \-value file1 file2
+ .SH DESCRIPTION
+ .I Spiff
+ compares the contents of 
+ .B file1
+ and
+ .B file2
+ and prints a description of the important differences between
+ the files.
+ White space is ignored except to separate other objects.
+ .I Spiff
+ maintains tolerances below which differences between two floating point
+ numbers are ignored. 
+ Differences in floating point notation (such as 3.4 3.40 and 3.4e01)
+ are treated as unimportant.
+ User specified delimited strings (i.e. comments) can also be ignored.
+ Inside other user specified delimited strings
+ (i.e. quoted strings) whitespace can be significant.
+ .PP
+ .I Spiff's
+ operation can be altered via command line options, a command script, and with
+ commands that are embedded in the input files.
+ .PP
+ The following options affect
+ .I spiff's
+ overall operation.
+ .TP
+ .B \-q
+ suppresses warning messages.
+ .TP
+ .B \-v
+ use a visually oriented display.  Works only in MGR windows.
+ .PP
+ .I Spiff
+ has several flags to aid differencing of various programming languages.
+ See EXAMPLES for a detailed description of the effects of these flags.
+ .TP
+ .B \-C
+ treat the input files as C program source code.
+ .TP
+ .B \-S
+ treat the input files as Bourne shell program source code.
+ .TP
+ .B \-F
+ treat the input files as Fortran program source code.
+ .TP
+ .B \-M
+ treat the input files as Modula-2 program source code.
+ .TP
+ .B \-L
+ treat the input files as Lisp program source code.
+ .PP
+ By default, the output looks somewhat similar in appearance
+ to the output of diff(1).  Lines with differences are printed with
+ the differences highlighted.  If stdout is a terminal, as determined
+ by isatty(), then highlighting uses standout mode as determined by termcap.
+ If stdout is not a tty, then the underlining (via underscore/backspace/char)
+ is used to highlight differences.
+ The following option can control the format of the ouput.
+ .TP
+ .B \-t
+ produce output in terms of individual tokens.  This option is
+ most useful for debugging as the output produced is verbose to
+ the point of being unreadable.
+ .PP
+ The following option controls the differencing algorithm.
+ .TP
+ .B \-e
+ compare each token 
+ in the files with the object in the same ordinal
+ position in the other file.  If the files have a different number
+ of objects, a warning message is printed
+ and the objects at the end of the longer file are ignored.
+ By default,
+ .I spiff
+ uses a Miller/Myers algorithm to find a minimal edit sequence
+ that will convert the contents of the first file into the second.
+ .TP
+ \-<decimal-value>
+ sets a limit on the total number of insertions and deletions
+ that will be considered.
+ If the files differ by more than the stated amount,
+ the program will give up, print a warning message, and exit.
+ .PP
+ The following options control the command script.  More than one of
+ each may appear at at time. The commands accumulate.
+ .TP
+ .B \-f sfile
+ a command script to be taken from file
+ .IR sfile 
+ .TP
+ .B \-s command-script
+ causes the following argument to be taken as a command script.
+ .PP
+ The following options control how individual objects are compared.
+ .TP
+ .B \-b
+ treat all objects (including floating point numbers) as literals.
+ .TP
+ .B \-c
+ ignore differences between upper and lower case.
+ .PP
+ The following commands will control how the files are parsed.
+ .TP
+ .B \-w
+ treat white space as objects.  Each white space character will
+ be treated as a separate object when the program is comparing the
+ files.
+ .TP
+ .B \-m
+ treat leading sign characters ( + and \- ) as separate even
+ if they are followed by floating point numbers.
+ .TP
+ .B \-d
+ treat integer decimal numbers (such as 1987) as real numbers (subject to
+ tolerances) rather than as literal strings.
+ .PP
+ The following three flags are used to set the default tolerances.
+ The floating-point-numbers may be given in the formats accepted
+ by atof(3).
+ .TP
+ .B \-a floating-point-number
+ specifies an absolute value for the tolerance in floating point numbers.
+ The flag
+ .B \-a1e-2
+ will cause all differences greater than 0.01 to be reported.
+ .TP
+ .B \-r floating-point-number
+ specifies a relative tolerance. The value given is interpreted
+ as a fraction of the larger (in absolute terms) 
+ of the two floating point numbers being compared.
+ Thus, the flag
+ .B \-r0.1
+ will cause the two floating point numbers 1.0 and 0.9 to be deemed within
+ tolerance. The numbers 1.0 and 0.89 will be outside the tolerance.
+ .TP
+ .B \-i
+ causes differences between floating point numbers to be ignored.
+ .PP
+ If more than one
+ .B \-a, \-r,
+ or
+ .B \-i
+ flag appear on the command line,
+ the tolerances will be OR'd together (i.e. any difference that is within
+ any of the tolerances will be ignored). 
+ .PP
+ If no default tolerances is set on the command line,
+ the program will use a default tolerance of
+ .B '\-a 1e-10 \-r 1e-10'.
+ .SH SCRIPT COMMANDS
+ .PP
+ A script consists of commands, one per line.
+ Each command consists of a keyword possibly followed by arguments.
+ Arguments are separated by one or more tabs or spaces.
+ The commands are:
+ .TP
+ literal BEGIN-STRING [END-STRING [ESCAPE-STRING]]
+ Specifies the delimiters surrounding text that is to be treated as a single
+ literal object. If only one argument is present, then only that string itself is treated
+ as a literal. If only two arguments are present, they are taking as the starting
+ and ending delimiters respectively.  If three arguments are present, they are treated
+ as the start delimiter, end delimiter, and a string that may be used to escape
+ an instance of the end delimiter.
+ .TP
+ beginchar BEGINNING-OF-LINE-CHARACTER
+ Set the the beginning of line character for BEGIN-STRING's in comments.
+ The default is '^'.
+ .TP
+ endchar END-OF-LINE-CHARACTER
+ Set the end of line character for END-STRING's in comments.
+ The default is '$'.
+ .TP
+ addalpha NEW-ALPHA-CHARACTER
+ Add NEW-ALPHA-CHARACTER to the set of characters allowed in literal strings.
+ By default, 
+ .I spiff
+ parses sequences of characters that begin with a letter and followed by
+ zero or more letters or numbers as a single literal token.  This definition
+ is overly restrictive when dealing with programming languages.
+ For example, in the C programming language,
+ the underscore character is allowed in identifiers. 
+ .TP
+ comment BEGIN-STRING [END-STRING [ESCAPE-STRING]]
+ Specifies the delimiters surrounding text that is to be be ignored entirely
+ (i.e. viewed as comments).
+ The operation of the comment command is very similar to the literal command.
+ In addition, if the END-STRING consists of only
+ the end of line character, the end of line will delimit the end of the comment.
+ Also, if the BEGIN-STRING starts with the beginning of line character, only
+ lines that begin with the BEGIN-STRING will be ignored.
+ .PP
+ More than one comment specification and more than one literal string specification
+ may be specified at a time.
+ .TP
+ nestcom BEGIN-STRING [END-STRING [ESCAPE-STRING]]
+ Similar to the comment command, but allows comments to be nested.
+ Note, due to the design of the parser nested comments can not
+ have a BEGIN-STRING that starts with the beginning of line character.  
+ .TP
+ resetcomments
+ Clears the list of comment specifications.
+ .TP
+ resetliterals
+ Clears the list of literal specifications.
+ .TP
+ tol [aVALUE\(brrVALUE\(bri\(brd . . . [ ; aVALUE\(brrVALUE\(bri\(brd . . . ] . . . ]
+ set the tolerance for floating point comparisons.  
+ The arguments to the tol command are a set of tolerance specifications
+ separated by semicolons.  If more than one a,r,d, or i appears within
+ a specification, then the tolerances are OR'd together (i.e. any difference
+ that is within any tolerance will be ignored).
+ The semantics of a,r, and i are identical to the
+ .B \-a, \-r,
+ and
+ .B \-i
+ flags. The d means that the default tolerance (as specified by the invocation
+ options) should be used.
+ If more than one specification appears on the line, the first
+ specification is applied to the first floating point number on each line,
+ the second specification to the second floating point number one each line
+ of the input files, and so on.  If there are more floating point numbers
+ on a given line of input than tolerance specifications,
+ the last specification is used repeatedly for all remaining floating point numbers
+ on that line.
+ .TP
+ command STRING
+ lines in the input file that start with STRING will be interpreted as
+ command lines. If no "command" is given as part of a
+ .B \-s
+ or
+ .B \-f
+ then it will be impossible to embed commands in the input files.
+ .TP
+ rem
+ .TP
+ #
+ used to places human readable remarks into a commands script. Note that the
+ use of the '#' character differs from other command languages (for instance
+ the Bourne shell).
+ .I Spiff
+ will only recognize the '#' as beginning a comment when it is the first
+ non-blank character on the command line.  A '#' character appearing elsewhere
+ will be treated as part of the command.  Cautious users should use 'rem'.
+ Those hopelessly addicted to '#' as a comment character can have command
+ scripts with a familiar format.
+ .PP
+ Tolerances specified in the command scripts have precedence over the tolerance
+ specified on the invocation command line. The tolerance specified in
+ .I file1
+ has precedence over the tolerance specified in
+ .I file2.
+ .PP
+ .SH VISUAL MODE
+ If
+ .I spiff
+ is invoked with the \-v option, it will enter an interactive mode rather
+ than produce an edit sequence.  Three windows will be put on the screen.
+ Two windows will contain corresponding segments of the input files.
+ Objects that appear in both segments will be examined for differences and
+ if any difference is found, the objects will be highlighted in reverse video
+ on the screen.  Objects that appear in only one window will have a line drawn
+ through them to indicate that they aren't being compared with anything in the other
+ text window. The third window is a command window.  The command window will
+ accept a single tolerance specification (followed by a newline)
+ in a form suitable to the
+ .B tol
+ command.  The tolerance specified will then be used as the default tolerance
+ and the display will be updated to highlight only those objects that exceed
+ the new default tolerance.  Typing 
+ .B m
+ (followed by a newline) will display the next screenfull of text. Typing
+ .B q
+ (followed by a newline)  will cause the program to exit.
+ .SH LIMITS
+ Each input files can be no longer that 10,000 line long or contain more
+ than 50,000 tokens. Longer files will be truncated.
+ No line can be longer than 1024 characters.  Newlines
+ will be inserted every 1024 character.
+ .SH EXAMPLES
+ .TP
+ spiff \-e \-d foo bar
+ this invocation (using exact match algorithm and treating integer numbers
+ as if they were floats) is very useful for examining large tables of numbers.
+ .TP
+ spiff \-0 foo bar
+ compare the two files, quitting after the first difference is found.
+ This makes the program operate roughly like cmp(1).
+ .TP
+ spiff \-0 -q foo bar
+ same as the above, but no output is produced.
+ The return code is still useful.
+ .TP
+ spiff \-w \-b foo bar
+ will make the program operate much like diff(1).
+ .TP
+ spiff \-a1e-5 \-r0.001 foo bar
+ compare the contents of the files foo and bar and ignore all differences between
+ floating point numbers that are less than or equal to
+ 0.00001 or 0.1% of the number of larger magnitude.
+ .TP
+ tol a.01 r.01
+ will cause all differences between floating point numbers that are less than
+ or equal to
+ 0.01 or 1% of the number of larger magnitude to be ignored.
+ .TP
+ tol a.01 r.01 ; i
+ will cause the tolerance in the previous example to be applied to the first
+ floating point number on each line.  All differences between the second and
+ subsequent floating point numbers on each line will be ignored.
+ .TP
+ tol a.01 r.01 ; i ; a.0001
+ like the above except that only differences between the second floating point
+ number on each line will be ignored. The differences between
+ third and subsequent floating point numbers on each number will be ignored if they
+ are less than or equal to 0.0001.
+ .IP
+ A useful script for examing C code is:
+ .nf
+ literal  "    "    \\ 
+ comment  /*  */
+ literal  &&
+ literal  \(br\(br
+ literal  <=
+ literal  >=
+ literal  !=
+ literal  ==
+ literal  --
+ literal  ++
+ literal  <<
+ literal  >>
+ literal  ->
+ addalpha _
+ tol      a0
+ .fi
+ .IP
+ A useful script for shell programs is:
+ .nf
+ literal  '    '    \\
+ comment  #    $
+ tol      a0
+ .fi
+ .IP
+ A useful script for Fortran programs is:
+ .nf
+ literal ' ' '
+ comment ^C $
+ tol     a0
+ .fi
+ .IP
+ A useful script for Modula 2 programs is:
+ .nf
+ literal ' '
+ literal " "
+ nestcom (* *)
+ literal :=
+ literal <>
+ literal <=
+ literal >=
+ tol     a0
+ .fi
+ .IP
+ A useful script for Lisp programs is:
+ .nf
+ literal " "
+ comment ; $
+ tol     a0
+ .fi
+ .SH DIAGNOSTICS
+ .I Spiff's
+ exit status is 0 if no differences are found, 1 if differences are found, and
+ 2 upon error.
+ .SH BUGS
+ In C code, escaped newlines will appear as differences.
+ .PP
+ Comments are treated as token delimiters.
+ .PP
+ Comments in Basic don't work right.  The line number is not ignored.
+ .PP
+ Continuation lines in Fortran comments don't work.
+ .PP
+ There is no way to represent strings specified using a
+ Hollerith notation in Fortran.
+ .PP
+ In formated English text, hyphenated words,
+ movements in pictures, footnotes, etc.
+ will be reported as differences.
+ .PP
+ STRING's in script commands can not include whitespace.
+ .PP
+ Visual mode does not handle tabs properly.  Files containing
+ tabs should be run through
+ expand(1) before trying to display them with visual mode.
+ .PP
+ In visual mode, the text windows appear in a fixed size and font.
+ Lines longer than the window size will not be handled properly.
+ .PP
+ Objects (literal strings) that contain newlines cause trouble in several places
+ in visual mode.
+ .PP
+ Visual mode should accept more than one tolerance specification.
+ .PP
+ When using visual mode or the exact match comparison algorithm, the program
+ should do the parsing on the fly rather than truncating long files.
+ .SH AUTHOR
+ Daniel Nachbar
+ .SH COPYRIGHT
+ .nf
+                  Copyright (c) 1988 Bellcore
+                      All Rights Reserved
+ Permission is granted to copy or use this program,
+ EXCEPT that it may not be sold for profit, the copyright
+ notice must be reproduced on copies, and credit should
+ be given to Bellcore where it is due.
+          BELLCORE MAKES NO WARRANTY AND ACCEPTS
+             NO LIABILITY FOR THIS PROGRAM.
+ .fi
+ 
+ .br
+ .SH SEE ALSO
+ atof(3)
+ isatty(2)
+ diff(1)
+ cmp(1)
+ expand(1)
+ mgr(1L)
+ .PP
+ "Spiff -- A Program for Making Controlled Approximate Comparisons of Files",
+ by Daniel Nachbar.
+ .PP
+ "A File Comparison Program" by Webb Miller and Eugene W. Myers in Software \-
+ Practice and Experience, Volume 15(11), pp.1025-1040, (November 1985).


Index: llvm/test/Programs/MultiSource/Applications/spiff/spiff.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/spiff.c:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/spiff.c	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,342 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ 
+ #ifndef lint
+ static char rcsid[]= "$Header: /home/vadve/shared/PublicCVS/llvm/test/Programs/MultiSource/Applications/spiff/spiff.c,v 1.1 2004/06/01 20:35:58 gaeke Exp $";
+ #endif
+ 
+ 
+ #include <stdio.h>
+ #include "misc.h"
+ #include "flagdefs.h"
+ #include "parse.h"
+ #include "edit.h"
+ #include "line.h"
+ #include "token.h"
+ #include "tol.h"
+ #include "command.h"
+ #include "compare.h"
+ #include "exact.h"
+ #include "miller.h"
+ #include "visual.h"
+ #include "output.h"
+ 
+ static void _Y_doargs();
+ 
+ static int _Y_eflag = 0;	/* use exact match algorithm */
+ static int _Y_vflag = 0;	/* use visual mode */
+ 
+ /*
+ **	this is the set of flags that gets used throughout the top module
+ **	as well as being used to communicate between modules.
+ */
+ static int _Y_flags;
+ 
+ int
+ main(argc,argv)
+ int argc;
+ char *argv[];
+ {
+ 	E_edit edit_end;
+ 	char *filename[2];
+ 
+ 	int max_d; 	/* max number of differences allowed */
+ 	int i;		/* loop counter */
+ 
+ 	/*
+ 	**	parse the command line
+ 	*/
+ 	_Y_doargs(argc,argv,&(filename[0]),&(filename[1]),&max_d);
+ 
+ 	/*
+ 	**	initialize the default tolerance if it
+ 	**		hasn't been set already.
+ 	*/
+ 	T_initdefault();
+ 
+ 	/*
+ 	**	read and then parse the files
+ 	*/
+ 
+ 	/*
+ 	**	L_initfile return a code that indicates if the
+ 	**	entire file was read or not
+ 	**
+ 	**	P_fileparse also knows how to start at someplace other
+ 	**		than the first line of file
+ 	**
+ 	**	Taken together, this is enough to do step our way
+ 	**		through the file using an exact match algorithm.
+ 	**
+ 	**	Oh well, someday . . .
+ 	*/
+ 	for(i=0;i<=1;i++)
+ 	{
+ 		/*
+ 		**	read the file into core
+ 		*/
+ 		(void) L_init_file(i,filename[i]);
+ 		K_settmax(i,0);		/* start tokens at 0 */
+ 		/*
+ 		**	and parse the files into tokens
+ 		*/
+ 		P_file_parse(i,0,L_getrlmax(i),_Y_flags);
+ 	}
+ 
+ 	if (_Y_vflag)
+ 	{
+ 		return(V_visual(_Y_flags));
+ 	}
+ 
+ 	/*
+ 	**	if max_d was not set on the command line
+ 	**		set it to be as large as is possible
+ 	**		since the most changes possible would
+ 	**		be to delete all the tokens in the
+ 	**		first file and add all the tokens from
+ 	**		the second, the max possible is the
+ 	**		sum of the number of tokens in the
+ 	**		two files.
+ 	*/
+ 	if (-1 == max_d)
+ 		max_d = K_gettmax(0) + K_gettmax(1);
+ 
+ 	if (_Y_eflag)
+ 	{
+ 		edit_end = Q_do_exact(K_gettmax(0),K_gettmax(1),
+ 					max_d,_Y_flags);
+ 	}
+ 	else
+ 	{
+ 		edit_end = G_do_miller(K_gettmax(0), K_gettmax(1),
+ 				     max_d,_Y_flags);
+ 	}
+ 
+ 	if (E_NULL != edit_end)
+ 	{
+ 		O_output(edit_end,_Y_flags);
+ 		return(1);
+ 	}
+ 	return(0);
+ }
+ 
+ /*
+ **	break a string into individual lines and feed
+ **		them to the command module
+ */
+ static void
+ _Y_cmdlines(from)
+ char *from;
+ {
+ 	char buf[Z_LINELEN]; 
+ 	char *to;
+ 	while ('\0' != *from)
+ 	{
+ 		/*
+ 		**	copy line into buf
+ 		*/
+ 		to = buf;
+ 		while (('\0' != *from) && ('\n' != *from))
+ 		{
+ 			*to++ = *from++;
+ 		}
+ 		*to = '\0';	/* terminate the line */
+ 
+ 		/*
+ 		**	hand the line to the command module
+ 		*/
+ 		C_addcmd(buf);
+ 		/*
+ 		**	skip the newline
+ 		*/
+ 		if ('\n' == *from)
+ 		{
+ 			from++;
+ 		}
+ 	}
+ }
+ 
+ /*
+ **	this useful macro handle arguements that are adjacent
+ **	to a flag or in the following word e.g --
+ **
+ **		-a XXX 
+ **	and
+ **		-aXXX 
+ **
+ **	both work when SETPTR is used. 
+ */
+ #define SETPTR	{if(strlen(argv[1]) == 2) {argv++;argc--;ptr=argv[1];}else ptr=(&argv[1][2]);}
+ 
+ static void
+ _Y_doargs(argc,argv,file1,file2,max_d)
+ int argc;
+ char *argv[];
+ char **file1,**file2;
+ int *max_d;
+ {
+ 	char *ptr;
+ 
+ 	/*
+ 	**	mark maximum number of tokens as being unset
+ 	*/
+ 	*max_d = -1;
+ 
+ 	while (argc > 1 && argv[1][0] == '-')
+ 	{
+ 		switch (argv[1][1])
+ 		{
+ 			case 't':
+ 				_Y_flags |= U_TOKENS;
+ 				break;
+ 			case 'w':
+ 				_Y_flags |= U_INCLUDE_WS;
+ 				break;
+ 
+ 			case 'b':
+ 				_Y_flags |= U_BYTE_COMPARE;
+ 				break;
+ 
+ 			case 'c':
+ 				_Y_flags |= U_NO_CASE;
+ 				break;
+ 			case 'd' :
+ 				_Y_flags |= U_NEED_DECIMAL;
+ 				break;
+ 			case 'm' :
+ 				_Y_flags |= U_INC_SIGN;
+ 				break;
+ 			case 'a':
+ 				SETPTR;
+ 				T_defatol(ptr);
+ 				break;
+ 			case 'r':
+ 				SETPTR;
+ 				T_defrtol(ptr);
+ 				break;
+ 			case 'i':
+ 				T_defitol();
+ 				break;
+ 			case 'e' :
+ 				_Y_eflag = 1;
+ 				break;
+ 			case 'v' :
+ 				_Y_vflag = 1;
+ 				break;
+ 			case 'q' :
+ 				Z_setquiet();
+ 				break;
+ 			case 's' :
+ 				SETPTR;
+ 				_Y_cmdlines(ptr);
+ 				break;
+ 			case 'f' :
+ 			{
+ 				extern FILE *fopen();
+ 				char buf[Z_LINELEN];
+ 				FILE *cmdfile;
+ 				SETPTR;
+ 				if ((FILE*) NULL ==
+ 					(cmdfile = fopen(ptr,"r")))
+ 				{
+ 					Z_fatal("can't open command file\n");
+ 				}
+ 				while ((char*) NULL !=
+ 					(char*) fgets(buf,Z_LINELEN,cmdfile))
+ 				{
+ 					C_addcmd(buf);
+ 				}
+ 				(void) fclose(cmdfile);
+ 				break;
+ 			}
+ 			/*
+ 			**	useful commands for
+ 			**	 the C programming language
+ 			*/
+ 			case 'C' :
+ 				C_addcmd("literal  \"   \"    \\ ");
+ 				C_addcmd("comment  /*  */	 ");
+ 				C_addcmd("literal  &&		 ");
+ 				C_addcmd("literal  ||		 ");
+ 				C_addcmd("literal  <=		 ");
+ 				C_addcmd("literal  >=		 ");
+ 				C_addcmd("literal  !=		 ");
+ 				C_addcmd("literal  ==		 ");
+ 				C_addcmd("literal  --		 ");
+ 				C_addcmd("literal  ++		 ");
+ 				C_addcmd("literal  <<		 ");
+ 				C_addcmd("literal  >>		 ");
+ 				C_addcmd("literal  ->		 ");
+ 				C_addcmd("addalpha _		 ");
+ 				C_addcmd("tol      a0 		 ");
+ 				break;
+ 			/*
+ 			**	useful commands for
+ 			**	 the Bourne shell programming language
+ 			*/
+ 			case 'S' :
+ 				C_addcmd("literal  '    '    \\	");
+ 				C_addcmd("comment  #    $	");
+ 				C_addcmd("tol      a0 		");
+ 				break;
+ 			/*
+ 			**	useful commands for
+ 			**	 the Fortran programming language
+ 			*/
+ 			case 'F' :
+ 				C_addcmd("literal  '	'     ' ");
+ 				C_addcmd("comment  ^C   $	");
+ 				C_addcmd("tol      a0 		");
+ 				break;
+ 			/*
+ 			**	useful commands for
+ 			**	 the Lisp programming language
+ 			*/
+ 			case 'L' :
+ 				C_addcmd("literal  \" 	\"	");
+ 				C_addcmd("comment  ; 	$	");
+ 				C_addcmd("tol      a0 		");
+ 				break;
+ 			/*
+ 			**	useful commands for
+ 			**	 the Modula-2 programming language
+ 			*/
+ 			case 'M' :
+ 				C_addcmd("literal ' 	'	");
+ 				C_addcmd("literal \"	\"	");
+ 				C_addcmd("comment (*	*)	");
+ 				C_addcmd("literal :=		");
+ 				C_addcmd("literal <>		");
+ 				C_addcmd("literal <=		");
+ 				C_addcmd("literal >=		");
+ 				C_addcmd("tol      a0 		");
+ 				break;
+ 			case '0':
+ 			case '1':
+ 			case '2':
+ 			case '3':
+ 			case '4':
+ 			case '5':
+ 			case '6':
+ 			case '7':
+ 			case '8':
+ 			case '9':
+ 				*max_d = atoi(&argv[1][1]);
+ 				break;
+ 			default:
+ 				Z_fatal("don't understand arguments\n");
+ 		}
+ 		++argv;
+ 		--argc;
+ 	}
+ 	if (argc != 3)
+ 		Z_fatal ("spiff requires two file names.\n");
+ 	*file1 = argv[1];
+ 	*file2 = argv[2];
+ }


Index: llvm/test/Programs/MultiSource/Applications/spiff/strings.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/strings.c:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/strings.c	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,162 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ 
+ #ifndef lint
+ static char rcsid[]= "$Header: /home/vadve/shared/PublicCVS/llvm/test/Programs/MultiSource/Applications/spiff/strings.c,v 1.1 2004/06/01 20:35:58 gaeke Exp $";
+ #endif
+ 
+ #include <ctype.h>
+ #include "misc.h"
+ #include "strings.h"
+ 
+ /*
+ **	routines for handling strings.
+ **		several routines manipulate  "words"
+ **		a "word" is a string not containing whitespace
+ */
+ 
+ /*
+ **	copy a single word. similar to  strcpy
+ */
+ void
+ S_wordcpy(to,from)
+ char *to, *from;
+ {
+ 	while ((*from != '\0') && isprint(*from) && (!isspace(*from)))
+ 	{
+ 		*to++ = *from++;
+ 	}
+ 	*to = '\0';
+ 	return;
+ }
+ 
+ /*
+ **	find the next whitespace character.  The address of the pointer
+ **		is passed and the pointer itself is changed.
+ */
+ void
+ S_skipword(theptr)
+ char **theptr;
+ {
+ 	while((**theptr != '\0') && isprint(**theptr) && (!isspace(**theptr)))
+ 	{
+ 		(*theptr)++;	/* increment the pointer, NOT the pointer
+ 					to the pointer */
+ 	}
+ 	return;
+ }
+ 
+ /*
+ **	find the next non-whitespace character.  The address of the pointer
+ **		is passed and the pointer itself is changed.
+ */
+ void
+ S_skipspace(theptr)
+ char **theptr;
+ {
+ 	while((**theptr != '\0') && isspace(**theptr))
+ 	{
+ 		(*theptr)++;	/* increment the pointer, NOT the pointer
+ 					to the pointer */
+ 	}
+ 	return;
+ }
+ 
+ /*
+ **	move the pointer to the beginning of the next word
+ */
+ void
+ S_nextword(theptr)
+ char **theptr;
+ {
+ 	S_skipword(theptr);
+ 	S_skipspace(theptr);
+ 	return;
+ }
+ 
+ /*
+ **	see if the first string is a prefix of the second
+ **		returns 0 if yes
+ **		non zero if now
+ **		sigh -- the way strcmp does
+ */
+ int
+ S_wordcmp(s1,s2)
+ char *s1,*s2;
+ {
+ 	return(strncmp(s1,s2,strlen(s2)));
+ }
+ 
+ /*
+ **	chop off any trailing zeros on a string
+ **		but leave one zero if there are only zeros
+ */
+ void
+ S_trimzeros(str)
+ char *str;
+ {
+ 	/*
+ 	**	end starts out pointing at the null terminator
+ 	*/
+ 	char *end = str + strlen(str);
+ 
+ 	/*
+ 	**	if there is more than one character left in the string
+ 	*/
+ 	while(end > (str+1))
+ 	{
+ 		--end;
+ 		if ('0' == *end)
+ 		{
+ 			*end = '\0';
+ 		}
+ 		else
+ 		{
+ 			return;
+ 		}
+ 	}
+ 	return;
+ }
+ 
+ /*
+ **	save a copy of the string
+ */
+ void
+ S_savestr(to,from)
+ char **to,*from;
+ {
+ 	S_allocstr(to,strlen(from));
+ 	(void) strcpy(*to,from);
+ 	return;
+ }
+ 
+ /*
+ **	save cnt characters of the string
+ */
+ void
+ S_savenstr(to,from,cnt)
+ char **to,*from;
+ {
+ 	S_allocstr(to,cnt);
+ 	(void) strncpy(*to,from,cnt);
+ 	*((*to)+cnt) = '\0';
+ 	return;
+ }
+ 
+ /*
+ **	allocate space for a string,  add 1 to size to
+ **		make sure that there is room for the terminating null character
+ */
+ void
+ S_allocstr(to,size)
+ char **to;
+ int size;
+ {
+ 	*to = Z_ALLOC(size+1,char);
+ }


Index: llvm/test/Programs/MultiSource/Applications/spiff/strings.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/strings.h:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/strings.h	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,20 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ #ifndef S_INCLUDED
+ extern void S_wordcpy();
+ extern void S_skipword();
+ extern void S_skipspace();
+ extern void S_nextword();
+ extern int  S_wordcmp();
+ extern void S_trimzeros();
+ extern void S_savestr();
+ extern void S_savenstr();
+ extern void S_allocstr();
+ #define S_INCLUDED
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/spiff/token.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/token.c:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/token.c	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,37 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ 
+ #ifndef lint
+ static char rcsid[]= "$Header: /home/vadve/shared/PublicCVS/llvm/test/Programs/MultiSource/Applications/spiff/token.c,v 1.1 2004/06/01 20:35:58 gaeke Exp $";
+ #endif
+ 
+ #include "misc.h"
+ #include "token.h"
+ 
+ K_token _K_ato[K_MAXTOKENS]; /* storage for tokens */
+ K_token _K_bto[K_MAXTOKENS];
+ 
+ int _K_atm;
+ int _K_btm;
+ 
+ void
+ K_settoken(file,index,pointer)
+ int file;
+ int index;
+ K_token pointer;
+ {
+ 	if (file)
+ 	{
+ 		_K_bto[index] = pointer;
+ 	}
+ 	else
+ 	{
+ 		_K_ato[index] = pointer;
+ 	}
+ }


Index: llvm/test/Programs/MultiSource/Applications/spiff/token.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/token.h:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/token.h	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,81 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ 
+ #ifndef K_INCLUDED
+ #include "float.h"
+ #include "tol.h"
+ #include "strings.h"
+ 
+ #define		K_MAXTOKENS	50000
+ /*
+ **	values for token type
+ */
+ #define K_LIT		1
+ #define	K_FLO_NUM	2
+ 
+ 
+ typedef struct {
+ 	int linenum;		/* line that the token started on */
+ 	int pos;		/* position on the line where token started */
+ 	int type;		/* token type */
+ 	char *text;	 	/* literal token text */
+ 	/*
+ 	**	canonical floationg point representation
+ 	*/
+ 	F_float flo_num;
+ 	T_tol tolerance;
+ } _K_str, *K_token;
+ 
+ /*
+ **	this should really be a two dimensional array
+ **	but i'm too lazy to recode it
+ */
+ extern K_token _K_ato[];	/* storage for the tokens */
+ extern K_token _K_bto[];
+ /*
+ **	save token X from file
+ */
+ extern void K_settoken(/*file,X,ptr*/);
+ #define K_gettoken(file, X)	(file?(_K_bto[X]):(_K_ato[X]))
+ 
+ extern int _K_atm;	/* count of tokens */
+ extern int _K_btm;
+ 
+ /*
+ **	get token number X from file
+ */
+ #define K_get_token(file, X)	(file?(_K_bto[X]):(_K_ato[X]))
+ 
+ #define K_gettmax(file)		(file?_K_btm:_K_atm)
+ #define K_settmax(file,value)	(file?(_K_btm=(value)):(_K_atm=(value)))
+ /*
+ **	increment and return true on overflow
+ */
+ #define	K_inctmax(file)		((file?(++_K_btm):(++_K_atm))>=K_MAXTOKENS)
+ 
+ #define K_setline(x,y)		(x->linenum = y)
+ #define K_setpos(x,y)		(x->pos = y)
+ #define K_settext(x,y)		(x->text = y)
+ #define K_savetext(x,y,z)	S_savestr(&(x->text),y)
+ #define K_saventext(x,y,z)	S_savenstr(&(x->text),y,z)
+ #define K_setfloat(x,y)		(x->flo_num = y)
+ #define K_settol(x,y)		(x->tolerance = y)
+ #define K_settype(x,y)		(x->type = y)
+ 
+ #define K_getline(x)		(x->linenum)
+ #define K_getpos(x)		(x->pos)
+ #define K_gettext(x)		(x->text)
+ #define K_getfloat(x)		(x->flo_num)
+ #define K_gettol(x)		(x->tolerance)
+ #define K_gettype(x)		(x->type)
+ 
+ #define K_maketoken()		(Z_ALLOC(1,_K_str))
+ 
+ #define K_INCLUDED
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/spiff/tol.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/tol.c:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/tol.c	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,362 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ 
+ #ifndef lint
+ static char rcsid[]= "$Header: /home/vadve/shared/PublicCVS/llvm/test/Programs/MultiSource/Applications/spiff/tol.c,v 1.1 2004/06/01 20:35:58 gaeke Exp $";
+ #endif
+ 
+ #include "misc.h"
+ #include "float.h"
+ #include "tol.h"
+ #include "token.h"
+ 
+ /*
+ **	storage for the default tolerances
+ */
+ T_tol _T_gtol = _T_null;
+ 
+ /*
+ **	tolerances that can be set in the command script and attached to floating
+ **		point numbers at parse time
+ */
+ static T_tol _T_tols[_T_TOLMAX];
+ 
+ /*
+ **	initialize the global tolerance
+ **	should be called only once at the beginning of the program
+ */
+ void
+ T_initdefault()
+ {
+ 	static int called_before = 0;
+ 
+ 	if (called_before)
+ 	{
+ 		Z_fatal("T_initdefault called more than once\n");
+ 	}
+ 
+ 	/*
+ 	**	if the default tolerance was set somewhere else
+ 	**	don't set it here
+ 	*/
+ 	if (T_isnull(_T_gtol))
+ 	{
+ 		T_defatol(_T_ADEF);
+ 		T_defrtol(_T_RDEF);
+ 	}
+ 	called_before = 1;
+ }
+ 
+ static void
+ _T_tolclear(addr)
+ T_tol *addr;
+ {
+ 	*addr = _T_null;
+ }
+ 
+ /*
+ **	clear the parse time tolerances
+ */
+ void
+ T_clear_tols()
+ {
+ 	int i;
+ 	for(i=0;i<_T_TOLMAX;i++)
+ 	{
+ 		_T_tolclear(&_T_tols[i]);
+ 	}
+ }
+ 
+ static void
+ _T_defclear()
+ {
+ 	_T_tolclear(&_T_gtol);
+ }
+ 
+ /*
+ **	take a series of specifiers and add them to the tolerance
+ */
+ static void
+ _T_settol(toladdr,str)
+ T_tol *toladdr;
+ char *str;
+ {
+ 	char typechar;
+ 	while ('\0' != *str)
+ 	{
+ 		/*
+ 		**	find the first non-whitespace character
+ 		*/
+ 		S_skipspace(&str);
+ 		/*
+ 		**	snarf up the type specifier
+ 		*/
+ 		typechar = *str;
+ 		/*
+ 		**	now skip the first char
+ 		*/
+ 		str++;
+ 		/*
+ 		**	skip any possibly intervening whitespace
+ 		*/
+ 		S_skipspace(&str);
+ 		switch (typechar)
+ 		{
+ 			case 'a':
+ 				_T_addtol(toladdr,T_ABSOLUTE,str);
+ 				break;
+ 			case 'r':
+ 				_T_addtol(toladdr,T_RELATIVE,str);
+ 				break;
+ 			case 'i':
+ 				_T_addtol(toladdr,T_IGNORE,(char*)0);
+ 				break;
+ 			case 'd':
+ 				_T_appendtols(toladdr,_T_gtol);
+ 				break;
+ 			default:
+ 				(void) sprintf(Z_err_buf,
+ 				  "don't understand tolerance type '%c'\n",typechar);
+ 				Z_fatal(Z_err_buf);
+ 		}
+ 		/*
+ 		**	and skip to next tolerance
+ 		*/
+ 		S_nextword(&str);
+ 	}
+ }
+ 
+ /*
+ **	set the default tolerance 
+ */
+ void
+ T_setdef(str)
+ char *str;
+ {
+ 	_T_defclear();
+ 	_T_settol(&_T_gtol,str);
+ }
+ 
+ 
+ static char*
+ _T_nextspec(ptr)
+ char *ptr;
+ {
+ 	/*
+ 	**	find the end of the current spec
+ 	*/
+ 	for(;(_T_SEPCHAR != *ptr) && ('\0' != *ptr);ptr++)
+ 	{
+ 	}
+ 
+ 	/*
+ 	**	and step over the seperator if necessary
+ 	*/
+ 	if (_T_SEPCHAR == *ptr)
+ 		ptr++;
+ 
+ 	return(ptr);
+ }
+ 
+ /*
+ **	return just the next set of specs
+ **		ie the string up to end of line or
+ **			the first _T_SEPCHAR
+ **	returned string does not include the _T_SEPCHAR
+ */
+ static char *
+ _T_getspec(from)
+ char *from;
+ {
+ 	static char retval[Z_LINELEN];
+ 	char *ptr = retval;
+ 
+ 	while((_T_SEPCHAR != *from) && ('\0' != *from))
+ 	{
+ 		*ptr++ = *from++;
+ 	}
+ 	*ptr = '\0';	/* terminate the line */
+ 	return(retval);
+ }
+ 
+ /*
+ **	parse a series of _T_SEPCHAR separated tolerance specifications
+ */
+ void
+ T_tolline(str)
+ char *str;
+ {
+ 	int nexttol;
+ 
+ 	T_clear_tols();
+ 
+ 	for(nexttol=0;'\0' != *str;nexttol++,str = _T_nextspec(str))
+ 	{
+ 		/*
+ 		**	make sure we haven't run off the end
+ 		*/
+ 		if (nexttol >= _T_TOLMAX)
+ 		{
+ 			Z_fatal("too many tolerances per line");
+ 		}
+ 
+ 		/*
+ 		**	and set the tolerance
+ 		*/
+ 		_T_settol(&_T_tols[nexttol],_T_getspec(str));
+ 	}
+ }
+ 
+ int
+ T_moretols(int next_tol)
+ {
+ 	return((next_tol >= 0) &&
+ 		(_T_TOLMAX-1 > next_tol) &&
+ 		(!T_isnull( _T_tols[next_tol+1])));
+ }
+ 
+ T_tol
+ T_gettol(index)
+ int index;
+ {
+ 	return(_T_tols[index]);
+ }
+ 
+ /*
+ **	chose which tolerance to use
+ **		 precidence is
+ **			first tolerance
+ **			second tolerance
+ **			default tolerance
+ */
+ T_tol
+ T_picktol(p1,p2)
+ T_tol p1, p2;
+ {
+ 	if (!(T_isnull(p1)))
+ 		return(p1);
+ 
+ 	if (!(T_isnull(p2)))
+ 		return(p2);
+ 
+ 	return(_T_gtol);
+ }
+ 
+ void
+ _T_appendtols(to,from)
+ T_tol *to,from;
+ {
+ 
+ 	T_tol last;
+ 
+ 	/*
+ 	**	are there any elements on the list yet
+ 	*/
+ 	if (T_isnull(*to))
+ 	{
+ 		/*
+ 		**	it's a null list, so allocat space for the
+ 		**		first element and set pointer to it.
+ 		*/
+ 
+ 		*to = from;
+ 	}
+ 	else
+ 	{
+ 		/*
+ 		**	find the last element on the list
+ 		*/
+ 		for(last= *to;!T_isnull(T_getnext(last));last = T_getnext(last))
+ 		{
+ 		}
+ 		/*
+ 		**	add an element on the end
+ 		*/
+ 		T_setnext(last,from);
+ 	}
+ }
+ 
+ /*
+ **	add a tolerance to a list
+ */
+ void
+ _T_addtol(listptr,type,str)
+ T_tol *listptr;
+ int type;
+ char *str;
+ {
+ 	T_tol last;
+ 
+ 	/*
+ 	**	are there any elements on the list yet
+ 	*/
+ 	if (T_isnull(*listptr))
+ 	{
+ 		/*
+ 		**	it's a null list, so allocat space for the
+ 		**		first element and set pointer to it.
+ 		*/
+ 
+ 		last = *listptr = Z_ALLOC(1,_T_struct);
+ 	}
+ 	else
+ 	{
+ 		/*
+ 		**	find the last element on the list
+ 		*/
+ 		for(last= *listptr;!T_isnull(T_getnext(last));last = T_getnext(last))
+ 		{
+ 		}
+ 		/*
+ 		**	add an element on the end
+ 		*/
+ 		T_setnext(last,Z_ALLOC(1,_T_struct));
+ 
+ 		/*
+ 		**	and point to the new element
+ 		*/
+ 		last = T_getnext(last);
+ 	}
+ 
+ 	T_settype(last,type);
+ 	T_setnext(last,_T_null);
+ 
+ 	/*
+ 	**	set the float value only if necessary
+ 	*/
+ 	if (T_IGNORE == type)
+ 	{
+ 		T_setfloat(last,F_null);
+ 	}
+ 	else
+ 	{
+ 		T_setfloat(last,F_atof(str,NO_USE_ALL));
+ 
+ 		/*
+ 		**	test new tolerance for sanity
+ 		*/
+ 		if (F_getsign(T_getfloat(last)))
+ 		{
+ 			(void) sprintf(Z_err_buf,
+ 			"%s : negative tolerances don't make any sense\n",str);
+ 			Z_fatal(Z_err_buf);
+ 		}
+ 		/*
+ 		**	check for excessively large relative tolerances
+ 		*/
+ 		if ((T_RELATIVE == type) &&
+ 			 (F_floatcmp(T_getfloat(last),
+ 				     F_atof("2.0",USE_ALL)) > 0))
+ 		{
+ 			(void) sprintf(Z_err_buf,
+ 	"%s : relative tolerances greater than 2 don't make any sense\n",str);
+ 			Z_fatal(Z_err_buf);
+ 		}
+ 	}
+ }


Index: llvm/test/Programs/MultiSource/Applications/spiff/tol.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/tol.h:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/tol.h	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,65 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ #include "float.h"
+ 
+ #ifndef T_INCLUDED
+ /*
+ **	values for tol_type
+ */
+ #define T_ABSOLUTE 		0
+ #define T_RELATIVE 		1
+ #define T_IGNORE		2
+ 
+ typedef struct _T_tstr{
+ 	int tol_type;		/* one of the above */
+ 	F_float flo_tol;	/* tolerance is expressed in
+ 				    terms of a floating point value */
+ 	struct _T_tstr *next;
+ } _T_struct, *T_tol;
+ 
+ #define _T_TOLMAX	10	/* number of tolerances that can
+ 					be in effect at one time */
+ 
+ #define _T_ADEF		"1e-10"	/* default absolute tolerance */
+ #define _T_RDEF		"1e-10"	/* default relative tolerance */
+ 
+ extern T_tol T_gettol();
+ extern void T_clear_tols();
+ extern void T_initdefault();
+ extern void T_setdef();
+ extern void T_tolline();
+ extern T_tol T_picktol();
+ extern int T_moretols(int next_tol);
+ 
+ #define T_gettype(x)	(x->tol_type)
+ #define T_getfloat(x)	(x->flo_tol)
+ #define T_getnext(x)	(x->next)
+ 
+ #define T_settype(x,y)	(x->tol_type = y)
+ #define T_setfloat(x,y)	(x->flo_tol = y)
+ #define T_setnext(x,y)	(x->next = y)
+ 
+ #define _T_null		((T_tol) 0)
+ #define T_isnull(x)	((x) == _T_null)
+ 
+ extern T_tol _T_gtol;
+ extern void _T_addtol();
+ extern void _T_appendtols();
+ 
+ /*
+ **	routines for building the global tolerance list
+ */
+ #define T_defatol(x)	_T_addtol(&_T_gtol,T_ABSOLUTE,x)
+ #define T_defrtol(x)	_T_addtol(&_T_gtol,T_RELATIVE,x)
+ #define T_defitol()	_T_addtol(&_T_gtol,T_IGNORE,(char*)NULL)
+ 
+ #define _T_SEPCHAR	';'
+ 
+ #define T_INCLUDED
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/spiff/two
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/two:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/two	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,3 ----
+ Hello there
+ you wierd
+ leaders.


Index: llvm/test/Programs/MultiSource/Applications/spiff/visual.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/visual.c:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/visual.c	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,413 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ 
+ #ifndef lint
+ static char rcsid[]= "$Header: /home/vadve/shared/PublicCVS/llvm/test/Programs/MultiSource/Applications/spiff/visual.c,v 1.1 2004/06/01 20:35:58 gaeke Exp $";
+ #endif
+ 
+ #ifdef MGR
+ 
+ #include "misc.h"
+ #include "line.h"
+ #include "token.h"
+ #include "/usr/public/pkg/mgr/include/term.h"
+ #include "/usr/public/pkg/mgr/include/restart.h"
+ 
+ #define OTHER		0
+ #define ON_DEBUG	1
+ #define OFF_DEBUG	2
+ #define DO_QUIT		3
+ #define DO_PAGE		4
+ #define NEW_PREC	5
+ 
+ 
+ #define NROW	60
+ #define NCOL	80
+ 
+ int isdiff[MAXTOKENS];	/* flag showing if a token pair was shown different*/
+ 
+ int comwin,wina, winb;	/* location to store window numbers */
+ int fontx,fonty;	/* size of the font in pixels */
+ 
+ int debug =0;
+ 
+ 
+ int firsttoken = 0;	/* index of first token pair being displayed */
+ int tokencnt;		/* count of the number of token pairs being displayed */
+ 
+ int
+ V_visual(flags)
+ int flags;
+ {
+ 
+ 	int moretodo = 1;	/* flag to clear when we're finished */
+ 
+ 	messup();
+ 
+ 	m_selectwin(comwin);
+ 	m_setmode(W_ACTIVATE);
+ 
+ 	showpages(comroutine,flags);
+ 
+ 	do
+ 	{
+ 		switch(getinput())
+ 		{
+ 			case ON_DEBUG:
+ 				debug = 0;
+ 				break;
+ 			case OFF_DEBUG:
+ 				debug = 1;
+ 				break;
+ 			case DO_QUIT:
+ 				moretodo = 0;
+ 				break;
+ 			case DO_PAGE:
+ 				if((firsttoken+tokencnt>= K_gettmax(0))||
+ 				   (firsttoken+tokencnt>= K_gettmax(1)))
+ 				{
+ 					m_selectwin(comwin);
+ 					m_printstr("\007this is the last page\n");
+ 					break;
+ 				}
+ 				firsttoken += tokencnt;
+ 				showpages(comroutine,flags);
+ 				break;
+ 			case NEW_PREC:
+ 				updatepages(comroutine,flags);
+ 				break;
+ 			case OTHER:
+ 				break;
+ 			default :
+ 				Z_fatal("bad value in main switch");
+ 				
+ 		}
+ 	} while (moretodo);
+ 
+ 	V_cleanup();
+ 	return(0);
+ }
+ 
+ getinput()
+ {
+ 	char ibuf[Z_LINELEN];	/* input buffer */
+ 	char *ptr;
+ 
+ 	m_selectwin(comwin);
+ 	m_setmode(W_ACTIVATE);
+ 	switch (m_getchar())
+ 	{
+ 		case 't':
+ 			m_gets(ibuf);
+ 			/*
+ 			**	skip the 'tol'
+ 			*/
+ 			ptr = ibuf;
+ 			S_nextword(&ptr);
+ 			T_setdef(ptr);
+ 			return(NEW_PREC);
+ 		case 'q':
+ 			return(DO_QUIT);
+ 		case 'd':
+ 			return(OFF_DEBUG);
+ 		case 'D':
+ 			return(ON_DEBUG);
+ 		case 'm':
+ 			return(DO_PAGE);
+ 		default:
+ 			return(OTHER);
+ 	}
+ 	
+ }
+ 
+ showpages(comroutine,flags)
+ int (*comroutine)();
+ int flags;
+ {
+ 	int i;
+ 		m_selectwin(wina);
+ 		m_clear();
+ 		m_selectwin(winb);
+ 		m_clear();
+ 		showlines();
+ 
+ 		for(i=firsttoken;i<tokencnt+firsttoken; i++)
+ 		{
+ 			isdiff[i] = 0;
+ 		}
+ 		updatepages(comroutine,flags);
+ }
+ 
+ updatepages(comroutine,flags)
+ int (*comroutine)();
+ int flags;
+ {
+ 	int i;
+ 
+ 	for(i=firsttoken;i<tokencnt+firsttoken; i++)
+ 	{
+ 		if (isdiff[i])
+ 		{
+ 
+ 			if (0 == X_com(i,i,flags))
+ 			{
+ 				m_selectwin(wina);
+ 				un_highlight(0,K_gettoken(0,i),K_getline(K_gettoken(0,firsttoken)));
+ 				m_selectwin(winb);
+ 				un_highlight(1,K_gettoken(1,i),K_getline(K_gettoken(1,firsttoken)));
+ 				isdiff[i] = 0;
+ 			}
+ 		}
+ 		else
+ 		{
+ 			if (0 != X_com(i,i,flags))
+ 			{
+ 				m_selectwin(wina);
+ 				highlight(0,K_gettoken(0,i),K_getline(K_gettoken(0,firsttoken)));
+ 				m_selectwin(winb);
+ 				highlight(1,K_gettoken(1,i),K_getline(K_gettoken(1,firsttoken)));
+ 				isdiff[i] = 1;
+ 			}
+ 		}
+ 	}
+ }
+ 
+ un_highlight(file,ptr,firstline)
+ int file;
+ K_token ptr;
+ int firstline;
+ {
+ 	highlight(file,ptr,firstline);
+ }
+ 
+ /*
+ **	argument expressed in terms of token lines
+ */
+ highlight(file,ptr,firstline)
+ int file;
+ K_token ptr;
+ int firstline;
+ {
+ 	int startx = K_getpos(ptr)*fontx;
+ 	int starty = (L_tl2cl(file,K_getline(ptr))-L_tl2cl(file,firstline))*fonty;
+ 
+ 	int sizex = fontx*strlen(K_gettext(ptr));
+ 	int sizey = fonty;
+ 	m_bitwrite(startx,starty,sizex,sizey);
+ }
+ 
+ showlines()
+ {
+ 	int Alinecnt = 0;
+ 	int Blinecnt = 0;
+ 
+ 	int Atfirstline = K_getline(K_gettoken(0,firsttoken));
+ 	int Btfirstline = K_getline(K_gettoken(1,firsttoken));
+ 	int Afirstline =  L_tl2cl(0,K_getline(K_gettoken(0,firsttoken)));
+ 	int Bfirstline =  L_tl2cl(1,K_getline(K_gettoken(1,firsttoken)));
+ 	int Anexttoken = L_getindex(0,Atfirstline);
+ 	int Bnexttoken = L_getindex(1,Btfirstline);
+ 	int i;
+ 	/*
+ 	**	first print the lines on the screen
+ 	*/
+ 	for(i=0;i < NROW;i++)
+ 	{
+ 		if(Afirstline+i < L_getclmax(0))
+ 		{
+ 			m_selectwin(wina);
+ 			showline(0,Afirstline+i,i);
+ 			Alinecnt++;
+ 		}
+ 
+ 		if(Bfirstline+i < L_getclmax(1))
+ 		{
+ 			m_selectwin(winb);
+ 			showline(1,Bfirstline+i,i);
+ 			Blinecnt++;
+ 		}
+ 	}
+ 	/*
+ 	**	now figure out how many tokens we actually printed
+ 	*/
+ 	for(i=Atfirstline;Anexttoken<K_gettmax(0) && L_tl2cl(0,i) < Afirstline+Alinecnt;i++)
+ 	{
+ 			Anexttoken += L_getcount(0,i);
+ 	}
+ 
+ 	for(i=Btfirstline;Bnexttoken<K_gettmax(1) && L_tl2cl(1,i) < Bfirstline+Blinecnt;i++)
+ 	{
+ 			Bnexttoken += L_getcount(1,i);
+ 	}
+ 	tokencnt = MIN(Anexttoken,Bnexttoken) - firsttoken;
+ 
+ 	/*
+ 	**	draw a line through any tokens that come before the first
+ 	**		token that is being compared
+ 	*/
+ 	if (L_getindex(0,Atfirstline) != firsttoken)
+ 	{
+ 		m_selectwin(wina);
+ 		for(i=L_getindex(0,Atfirstline);i<firsttoken;i++)
+ 		{
+ 			drawline(K_gettoken(0,i),0);
+ 		}
+ 	}
+ 
+ 	if (L_getindex(1,Btfirstline) != firsttoken)
+ 	{
+ 		m_selectwin(winb);
+ 
+ 		for(i=L_getindex(1,Btfirstline);i<firsttoken;i++)
+ 		{
+ 			drawline(K_gettoken(1,i),0);
+ 		}
+ /*
+ m_line(Bt[Bindex[Bfirstline]]->pos*fontx,fonty/2,(Bt[firsttoken]->pos*fontx)-2,fonty/2);
+ */
+ 	}
+ 
+ 	if (Anexttoken > Bnexttoken)
+ 	{
+ 		m_selectwin(wina);
+ 		for(i=Bnexttoken;i<Anexttoken;i++)
+ 		{
+ 			drawline(K_gettoken(0,i),L_tl2cl(0,K_getline(K_gettoken(0,i)))-Afirstline);
+ 		}
+ 	}
+ 
+ 	if (Anexttoken < Bnexttoken)
+ 	{
+ 		m_selectwin(winb);
+ 		for(i=Anexttoken;i<Bnexttoken;i++)
+ 		{
+ 			drawline(K_gettoken(1,i),L_tl2cl(1,K_getline(K_gettoken(1,i)))-Bfirstline);
+ 		}
+ 	}
+ 
+ }
+ 
+ /*
+ **	line is given in conten line
+ */
+ drawline(ptr,line)
+ K_token ptr;
+ int line;
+ {
+ 		m_line(K_getpos(ptr)*fontx,
+ 			(line*fonty)+fonty/2,
+ 			(K_getpos(ptr)+strlen(K_gettext(ptr)))*fontx,
+ 			(line*fonty)+fonty/2);
+ }
+ 
+ /*
+ **	takes arguments in terms of content lines
+ */
+ showline(file,index,row)
+ int file;
+ int index;
+ int row;
+ {
+ 	static char tmp[Z_LINELEN];
+ 	m_move(0,row);
+ 	stripnl(tmp,L_getcline(file,index));
+ 	m_printstr(tmp);
+ }
+ 
+ stripnl(to,from)
+ char *to,*from;
+ {
+ 	while ((*from != '\n') && (*from != '\0'))
+ 	{
+ 		*to++ = *from++;
+ 	}
+ 	*to = '\0';
+ }
+ 
+ static int didscr = 0;
+ 
+ messup()
+ {
+ 	int col, row;
+ 	int dum1,dum2,dum3,border;
+ 
+ 	m_setup(W_FLUSH|W_DEBUG);
+ 	m_push(P_EVENT|P_FLAGS|P_POSITION);
+ 	get_param(&dum1,&dum2,&dum3,&border);
+ 	didscr = 1;
+ 	comwin =  m_makewindow(192,50,732,116);
+ 	wina = m_makewindow(0,218,570,670);
+ 	m_selectwin(wina);
+ 	m_font(2);
+ 	get_font(&fontx,&fonty);
+ 	m_shapewindow(0,218,NCOL*fontx+(2*border),NROW*fonty+(2*border));
+ 
+ 	get_colrow(&col,&row);
+ 	if ((col != NCOL) || (row != NROW))
+ 	{
+ 		Z_fatal("bad window size");
+ 	}
+ 	m_func(B_INVERT);
+ 	m_setmode(W_ABS);
+ 
+ 	winb = m_makewindow(580,218,570,670);
+ 	m_selectwin(winb);
+ 	m_font(2);
+ 	get_font(&fontx,&fonty);
+ 	m_shapewindow(580,218,NCOL*fontx+(2*border),NROW*fonty+(2*border));
+ 
+ 	get_colrow(&col,&row);
+ 	if ((col != NCOL) || (row != NROW))
+ 	{
+ 		Z_fatal("bad window size");
+ 	}
+ 	m_func(B_INVERT);
+ 	m_setmode(W_ABS);
+ 
+ 	m_selectwin(comwin);
+ 	m_clear();
+ 	m_setmode(W_ABS);
+ 	m_setmode(W_ACTIVATE);
+ }
+ 
+ V_cleanup()
+ {
+ 	if (didscr)
+ 	{
+ 		m_destroywin(wina);
+ 		m_destroywin(winb);
+ 		m_destroywin(comwin);
+ 		m_popall();
+ 		m_setecho();
+ 		(void) fclose(m_termin);
+ 		(void) fclose(m_termout);
+ 	}
+ }
+ 
+ #else
+ 
+ #include "misc.h"
+ /*
+ **	dummy code for systems that don't have
+ **	the mgr window manager installed
+ */
+ int
+ V_visual(d)
+ int d;
+ {
+ 	Z_fatal("visual mode is not available on this machine\n");
+ 	return(-d);	/* boiler plate */
+ }
+ 
+ void
+ V_cleanup()
+ {
+ }
+ 
+ #endif


Index: llvm/test/Programs/MultiSource/Applications/spiff/visual.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/spiff/visual.h:1.1
*** /dev/null	Tue Jun  1 15:36:08 2004
--- llvm/test/Programs/MultiSource/Applications/spiff/visual.h	Tue Jun  1 15:35:58 2004
***************
*** 0 ****
--- 1,18 ----
+ /*                        Copyright (c) 1988 Bellcore
+ **                            All Rights Reserved
+ **       Permission is granted to copy or use this program, EXCEPT that it
+ **       may not be sold for profit, the copyright notice must be reproduced
+ **       on copies, and credit should be given to Bellcore where it is due.
+ **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
+ */
+ 
+ 
+ #ifndef V_INCLUDED
+ 
+ 
+ extern void V_cleanup();
+ extern int V_visual (int d);
+ 
+ #define V_INCLUDED
+ 
+ #endif





More information about the llvm-commits mailing list