+++ /dev/null
-The copyright below applies to Spiff 1.0 as redistributed as part of LLVM
-and/or its test suite.
-
-------------------------------------------------------------------------------
-
-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.
+++ /dev/null
-LEVEL = ../..
-TOOLNAME = spiff
-CPPFLAGS += -DATT -DNOCHATTER
-
-include $(LEVEL)/Makefile.common
-
+++ /dev/null
-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@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@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
+++ /dev/null
-/* 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$";
-#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;
-}
-
-#define inline spiff_inline
-int
-C_is_cmd(inline)
-char *inline;
-{
- char *ptr;
- /*
- ** see if this is a command line
- ** and if so, do the command right away
- */
- if (('\0' != _C_cmdword[0]) && (!S_wordcmp(inline,_C_cmdword)))
- {
- ptr = inline;
- S_nextword(&ptr);
- _C_do_a_cmd(ptr);
- return(1);
- }
- return(0);
-}
-
+++ /dev/null
-/* 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
+++ /dev/null
-/* 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$";
-#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);
-}
+++ /dev/null
-/* 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();
-
-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
+++ /dev/null
-/* 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$";
-#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();
-static int _X_cmptokens();
-static int _X_floatdiff();
-
-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(s1,s2,flags)
-char *s1,*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(p1,p2,flags)
-K_token p1, 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(p1,p2,the_tol)
-F_float p1,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);
-}
+++ /dev/null
-/* 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
+++ /dev/null
-/* 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
-
-
+++ /dev/null
-/* 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$";
-#endif
-
-#include "misc.h"
-#include "edit.h"
-#include "compare.h"
-#include <stdio.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);
-}
+++ /dev/null
-/* 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
+++ /dev/null
-/* 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
+++ /dev/null
-/* 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$";
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#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(f1,f2)
-F_float f1,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)
-int 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)
-int 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) ? '+': '-'));
-
-}
-*/
+++ /dev/null
-/* 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();
-extern int F_isfloat();
-
-#define F_null ((F_float) 0)
-
-#define F_INCLUDED
-
-#endif
+++ /dev/null
-/* 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$";
-#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);
-}
-
+++ /dev/null
-/* 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
+++ /dev/null
-/* 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$";
-#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(fnumber,fname)
-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);
-}
-
+++ /dev/null
-/* 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 300000
-
-/*
-** 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;
-
-/*
-** 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
+++ /dev/null
-/* 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$";
-#endif
-
-#include <stdio.h>
-#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);
-}
+++ /dev/null
-/* 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
+++ /dev/null
-/* 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$";
-#endif
-
-#include <stdio.h>
-#include "misc.h"
-#include "visual.h"
-#include "output.h"
-#include <stdlib.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)))
- {
- 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);
-}
+++ /dev/null
-/* 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();
-
-/*
-** lines needed to shut up lint
-*/
-
-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
+++ /dev/null
-/* 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$";
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#ifdef M_TERMINFO
-#include <curses.h>
-#include <term.h>
-#endif
-
-#ifdef M_TERMCAP
-#ifdef XENIX
-#include <tcap.h>
-#endif
-#endif
-
-#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; */ /* disabled by brg 13-April-2004 - this
- makes the output unreadable */
- }
-}
-
-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 (_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;
-}
+++ /dev/null
-/* 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
+++ /dev/null
-.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
+++ /dev/null
-/* 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$";
-#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 int index();
-#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)))
- {
- 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;
-}
+++ /dev/null
-/* 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();
+++ /dev/null
-.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).
+++ /dev/null
-/* 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$";
-#endif
-
-
-#include <stdio.h>
-#include <stdlib.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"
-
-extern int L_init_file();
-extern int V_visual();
-
-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];
-}
+++ /dev/null
-/* 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$";
-#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;
-int cnt;
-{
- 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);
-}
+++ /dev/null
-/* 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
-#include <string.h>
-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
+++ /dev/null
-/* 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$";
-#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;
- }
-}
+++ /dev/null
-/* 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
+++ /dev/null
-/* 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$";
-#endif
-
-#include <stdio.h>
-#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(next_tol)
-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);
- }
- }
-}
+++ /dev/null
-/* 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();
-
-#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
+++ /dev/null
-/* 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$";
-#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 */
-
-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
+++ /dev/null
-/* 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();
-
-#define V_INCLUDED
-
-#endif