| /* 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(char *s1,char *s2,int flags); |
| static int _X_cmptokens(K_token p1,K_token p2,int flags); |
| static int _X_floatdiff(F_float p1,F_float p2,T_tol the_tol); |
| |
| int |
| X_com(a,b,flags) |
| int a,b,flags; |
| { |
| K_token atmp,btmp; |
| |
| atmp = K_gettoken(0,a); |
| btmp = K_gettoken(1,b); |
| if(flags & U_BYTE_COMPARE) |
| { |
| return(_X_strcmp(K_gettext(atmp),K_gettext(btmp),flags)); |
| } |
| else |
| { |
| return(_X_cmptokens(atmp,btmp,flags)); |
| } |
| #ifndef lint |
| Z_fatal("this line should never be reached in com"); |
| return(-1); /* Z_fatal never returns, but i need a this line |
| here to stop lint from complaining */ |
| #endif |
| } |
| |
| /* |
| ** same as strcmp() except that case can be optionally ignored |
| */ |
| static int _X_strcmp(char *s1,char *s2,int flags) |
| { |
| if (flags & U_NO_CASE) |
| { |
| |
| for (;('\0' != s1) && ('\0' != *s2);s1++,s2++) |
| { |
| if(isalpha(*s1) && isalpha(*s2)) |
| { |
| if(tolower(*s1) != tolower(*s2)) |
| { |
| return(1); |
| } |
| } |
| else |
| { |
| if(*s1!=*s2) |
| { |
| return(1); |
| } |
| } |
| } |
| return(*s1 != *s2); |
| } |
| else |
| { |
| return(strcmp(s1,s2)); |
| } |
| } |
| |
| |
| /* |
| ** routine to compare two tokens |
| */ |
| static int _X_cmptokens(K_token p1,K_token p2,int flags) |
| { |
| if (K_gettype(p1) != K_gettype(p2)) |
| { |
| return(1); |
| } |
| |
| switch (K_gettype(p1)) |
| { |
| case K_LIT: |
| return(_X_strcmp(K_gettext(p1),K_gettext(p2),flags)); |
| case K_FLO_NUM: |
| return(_X_floatdiff(K_getfloat(p1), |
| K_getfloat(p2), |
| T_picktol(K_gettol(p1), |
| K_gettol(p2)))); |
| default: |
| Z_fatal("fell off switch in _X_cmptokens"); |
| return(-1); /* Z_fatal never returns, but i need a this line |
| here to stop lint from complaining */ |
| } |
| |
| } |
| |
| /* |
| ** compare two F_floats using a tolerance |
| */ |
| static int _X_floatdiff(F_float p1,F_float p2,T_tol the_tol) |
| { |
| F_float diff, float_tmp; |
| T_tol tol_tmp; |
| |
| /* |
| ** check for null tolerance list |
| */ |
| if (T_isnull(the_tol)) |
| { |
| Z_fatal("_X_floatdiff called with a null tolerance"); |
| } |
| |
| /* |
| ** look for an easy answer. i.e -- check |
| ** to see if any of the tolerances are of type T_IGNORE |
| ** or if the numbers are too small to exceed an absolute |
| ** tolerance. |
| ** if so, return immediately |
| */ |
| for(tol_tmp=the_tol; !(T_isnull(tol_tmp)) ;tol_tmp=T_getnext(tol_tmp)) |
| { |
| if ((T_IGNORE == T_gettype(tol_tmp)) || |
| /* |
| ** take a look at the exponents before you bother |
| ** with the mantissas |
| */ |
| ((T_ABSOLUTE == T_gettype(tol_tmp)) |
| && !F_zerofloat(T_getfloat(tol_tmp)) |
| && (F_getexp(p1) < |
| F_getexp(T_getfloat(tol_tmp))-1) |
| && (F_getexp(p2) < |
| F_getexp(T_getfloat(tol_tmp))-1))) |
| { |
| return(0); |
| } |
| } |
| |
| |
| /* |
| ** ok, we're going to have to do some arithmetic, so |
| ** first find the magnitude of the difference |
| */ |
| if (F_getsign(p1) != F_getsign(p2)) |
| { |
| diff = F_floatmagadd(p1,p2); |
| } |
| else |
| { |
| diff = F_floatsub(p1,p2); |
| } |
| |
| /* |
| ** now check to see if the difference exceeds any tolerance |
| */ |
| for(tol_tmp=the_tol; !(T_isnull(tol_tmp)) ;tol_tmp=T_getnext(tol_tmp)) |
| { |
| float_tmp = T_getfloat(tol_tmp); |
| |
| if (T_gettype(tol_tmp) == T_ABSOLUTE) |
| { |
| /* do nothing */ |
| } |
| else if (T_gettype(tol_tmp) == T_RELATIVE) |
| { |
| if (F_floatcmp(p1,p2) > 0) |
| { |
| float_tmp = F_floatmul(p1, float_tmp); |
| } |
| else |
| { |
| float_tmp = F_floatmul(p2, float_tmp); |
| } |
| } |
| else |
| { |
| Z_fatal("bad value for type of tolerance in floatdiff"); |
| } |
| /* |
| ** if we pass this tolerance, then we're done |
| */ |
| if (F_floatcmp(diff,float_tmp) <= 0) |
| { |
| return(0); |
| } |
| } |
| /* |
| ** all of the tolerances were exceeded |
| */ |
| return(1); |
| } |