/*
 * SCPSD.C - PostScript diff
 *         - compares two PostScript files upto roundoff
 *         - NOTE: intended for testing PGS generated PostScript
 *         -  files.  Any others MIGHT work but no guarantees.
 *         - NOTE: two defects for future consideration
 *         -  1) No way to really compare images (very hard)
 *         -  2) Assumes only 1 line at a time differs
 *         -     This could be fixed to save and check a section
 *         -     at a time (moderate difficulty)
 *         -     For example
 *         -       3357c3357
 *         -       < 1 0 0 1 213 1615 0 Tp
 *         -       ---
 *         -       > 1 0 0 1 212 1615 0 Tp
 *         -     is handled correctly and
 *         -       3357,8c3357,8
 *         -       < 1 0 0 1 213 1615 0 Tp
 *         -       < 1 0 0 1 213 2183 0 Tp
 *         -       ---
 *         -       > 1 0 0 1 212 1615 0 Tp
 *         -       < 1 0 0 1 213 2183 0 Tp
 *         -     will only check the second line for difference
 *         -     missing the difference in the first line
 */

#include "score.h"

#define LINE_LEN   120

/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/

/* DIFF_LINE - compare a line of difference */

static int diff_line(bfA, bfB, verbose, ecnt, eA, eB)
   char *bfA, *bfB;
   int verbose;
   char *ecnt, *eA, *eB;
   {int errl;
    int ia, ib, di;
    double da, db, dd, toler;
    char *ta, *tb;

    errl  = 0;
    toler = 1.0e-10;

/* ignore PostScript comments (they begin with %) */
    if ((bfA[0] == '%') && (bfB[0] == '%'))
       return(errl);

/* NOTE: if we have images to compare the entire line will be one
 *       very long word comparisons will be meaningless
 *       so check that the line is less than LINE_LEN characters long
 *       which ought to be enough for anything but an image
 */
    else if ((strlen(bfA) < LINE_LEN) &&
	     (strlen(bfB) < LINE_LEN))
       {if (verbose)
	   {printf("< (%d) %s", (int) strlen(bfA), bfA);
	    printf("> (%d) %s", (int) strlen(bfB), bfB);};

	errl = 0;
	while (errl == 0)
	   {ta = SC_firsttok(bfA, " \t\n\f\r");
	    tb = SC_firsttok(bfB, " \t\n\f\r");
	    if (ta == NULL)
	       break;

/* if the tokens are the same OK */
	    if (strcmp(ta, tb) == 0)
	       continue;

/* if they are integer check equality to tolerance */
	    if (SC_intstrp(ta, 10) && SC_intstrp(tb, 10))
	       {ia   = SC_stoi(ta);
		ib   = SC_stoi(tb);
		di   = ia - ib;
		di   = abs(di);
		errl = (di > 1);}

/* if they are double check equality to tolerance */
	    else if (SC_fltstrp(ta) && SC_fltstrp(tb))
	       {da   = SC_stof(ta);
		db   = SC_stof(tb);
		dd   = (da - db)/(ABS(da) + ABS(db) + SMALL);
		errl = (ABS(dd) > toler);}

/* otherwise it is an error */
	    else
	       errl = TRUE;};

	if (errl)
	   {printf("%s", ecnt);
	    printf("%s", eA);
	    printf("---\n");
	    printf("%s", eB);};};

    return(errl);}

/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/

/* PS_DIFF - compare the specified PostScript files upto roundoff
 *         - we really want to check items that look like
 *         -   3357c3357
 *         -   < 1 0 0 1 213 1615 0 Tp
 *         -   ---
 *         -   > 1 0 0 1 212 1615 0 Tp
 *         - or
 *         -   3366c3366
 *         -   < ( 100    0.00e+00   1.00e+01   -1.00e-00   1.00e+00) Tx
 *         -   ---
 *         -   > ( 100    0.00e+00   1.00e+01   -1.00e+00   1.00e+00) Tx
 */

static int ps_diff(f1, f2, verbose)
   char *f1, *f2;
   int verbose;
   {int err;
    int la, lb;
    char eA[MAX_LEX_BUFFER], eB[MAX_LEX_BUFFER], ecnt[MAX_LEX_BUFFER];
    char bfA[MAX_LEX_BUFFER], bfB[MAX_LEX_BUFFER];
    char s[MAX_LEX_BUFFER], cmnd[MAXLINE];
    FILE *fd;

    sprintf(cmnd, "diff %s %s > __tmp__", f1, f2);
    system(cmnd);

    fd = fopen("__tmp__", "r");

    la = 0;
    lb = 0;

    err = 0;

    while (TRUE)
       {if (fgets(s, MAXLINE, fd) == NULL)
           {fclose(fd);
	    unlink("__tmp__");
	    return(0);};

/* copy the A file difference */
	if (s[0] == '<')
	   {strcpy(eA, s);
	    strcpy(bfA, s+2);
	    la = strlen(bfA);}

/* ignore the difference separator: --- */
	else if (strncmp(s, "---", 3) == 0)
           continue;

/* copy the B file difference */
	else if (s[0] == '>')
	   {strcpy(eB, s);
	    strcpy(bfB, s+2);
	    lb = strlen(bfB);}

/* now process the actual differences in this line */
	else if ((la != 0) && (lb != 0))
	   {err |= diff_line(bfA, bfB, verbose, ecnt, eA, eB);

/* reset for the next difference */
	    la = 0;
	    lb = 0;
	    strcpy(ecnt, s);}

/* make a copy of the diff line info */
	else
	   strcpy(ecnt, s);};

    return(err);}

/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/

/* MAIN - start here */

int main(c, v)
   int c;
   char **v;
   {int err, verbose;
    int i, nf;
    char *file[10];

    verbose = FALSE;
    nf      = 0;

    for (i = 1; i < c; i++)
        {if (strcmp(v[i], "-v") == 0)
            verbose = TRUE;
	 else
            file[nf++] = v[i];};

    if (nf == 2)
       err = ps_diff(file[0], file[1], verbose);

    else
       {printf("Too many files specified (%d)\n", nf);
	err = TRUE;};

    return(err);}

/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
