/* repeat of last x or y = '&'                                            */
/* redundant last 3 values in rectangle poly = '|'                        */
/* a repeat of the value inthe same position in the last poly = '^'       */
/* the pattern "^&^" is shortened to '%'                                  */
/* the Xn-X(n-2) is the same in this poly as it was in the last P = '@'   */
/* if PnX0 - P(n-1)X0  == P(n-1)X0 - P(n-2)X0 then                        */
/*  PnX0 is replaced by '~'                                               */
/* The group "~%@|" is a common pattern and is replaced by '+'            */
/* The group "@&&" is a common pattern and is replaced by '!'             */
/* To be done:
   * extend P+ to cover non rectangle shapes.
   * common deltas
   * n == one before last
   * detect/compress ^!^! type sequence?
   * replace polys by boxes when only 50% compressed
   * put sequence compression on output stream
*/

static   char    compdracif_c_Sccs[] = "@(#)compdracif.c        1.7    10/4/89" ;
#include <stdio.h>
#include <ctype.h>
#include <time.h>
/* AUG/24/89 == 620005589 in time(0) form */
#define bombDate 620005589 + 3600*24*100
#define version 5
#define numpoints 2000
#define boxnums 10
#define numlayers 'z'-'a'
#define buf_len 10000
#define pi points[i]
#define opi opoints[i]
#define oopi oopoints[i]
#define bi b[i]
#define obi ob[i]
#define oobi oob[i]
#define ci c[i]
#define oci oc[i]
#define ooci ooc[i]
#define delOk(r,v) ( (abs( (v)/abs((v)-(r)) )>9) ? true : false )

/* set up parser vars */
char cmt_start_ch      = '(',
     cmt_end_ch        = ')',
     line_cmt_ch       = '#',
     x_id_start_chs[]  = {'$','\0'},
     x_id_chs[]        = {'$','\0'},
     x_space_chs[]     = {',',':','@','\0'},
     op_chs[]          = {'T','R',';','-','/','\0'};
char *keys[] = {"DUMMY"};
#include "procs6.h"

FILE *fo,*fs;

/* poly point data */
typedef struct { int v,used; char vtype,txt[N_L]; } point;
point   points[numpoints], opoints[numpoints], oopoints[numpoints];
boo     lastWasArray=false;

/* box data */
point   b[boxnums], ob[boxnums], oob[boxnums];
boo     lastWasArrayBox=false;

/* C data */
point   c[boxnums], oc[boxnums], ooc[boxnums];

/* char buffer */
char    buf[buf_len]; int ix=0;


init_data()
{int i;
 for(i=0;i<numpoints;i++)
 {pi.v=0; pi.vtype=' '; pi.used=false; opi.v=0;}
 for(i=0;i<=boxnums;i++)
 { bi.v=0L; obi.v=0L; bi.vtype=' '; bi.used=false;
   ci.v=0L; oci.v=0L; ci.vtype=' '; ci.used=false; ci.txt[0]='\0'; }
}

/*
boo delOk(r,v)
long r,v;
{
 if(r-v==0) return(true);
 if(abs( v/abs(v-r))>11) return true; 
 return false;
}
*/

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

write_call()
{int i,j=0,nosemi=false; char spacer[1];
 spacer[0]='\0';
 spacer[1]='\0';
 rmchar(' ',buf);

 for(i=0;ci.used;i++)
  if(ci.vtype==' ')
  { if(ci.v == oci.v) ci.vtype = '^';
     else if(ci.v-oci.v == oci.v-ooci.v) ci.vtype='~';

     else if(i>0 && ci.v==c[i-1].v) ci.vtype='&';

     /* equals one before last */
     else if(ci.v == ooci.v) ci.vtype='=';

     /* vertical delta */
     else if(delOk(oci.v,ci.v))
          { if(ci.v>oci.v) ci.vtype = '{'; else ci.vtype = '}'; }


  }


 /* for(i=0;ci.used;i++) printf("%d%c",ci.v,ci.vtype); printf("\n"); */

 /* write out the call */

  fpf(fo,"%s",buf);
  for(i=0;ci.used;i++)
  {if(ci.vtype!=' ')
   {
     if(i>0 && (ci.vtype == '[' || ci.vtype == ']'))
             { spacer[0]=' ';
               fpf(fo,"%c%d",ci.vtype,abs(ci.v-c[i-1].v)); }

     else if(ci.vtype == 'T'    &&
             c[i+1].vtype == '^'  &&
             c[i+2].vtype == '^'  &&
             !c[i+3].used                )
             { fpf(fo,"|"); i += 2; nosemi=true; }


     else if(ci.vtype == '{' || ci.vtype == '}')
             { spacer[0]=' ';
               fpf(fo,"%c%d",ci.vtype,abs(ci.v-oci.v)); }

     else if(ci.vtype == 't')
             { spacer[0]=' ';
               fpf(fo," %s ",ci.txt); }

     else { fputc(ci.vtype,fo); spacer[0]='\0'; }

   }
   else { if(ci.v<0) fpf(fo,"%d",ci.v);
           else fpf(fo,"%s%d",spacer,ci.v); spacer[0]=' '; }
  } /* for */


 if(!nosemi) fpf(fo,";");
 buf[ix++]=ch;
 lastWasArray=false;
 lastWasArrayBox=false;
}

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

process_call()
{int i;

 for(i=0;i<boxnums;i++)
 { ooci.v=oci.v; oci.v=ci.v; ci.vtype=' '; ci.used=false; ci.txt[0]='\0'; }
 xg(); g_s();
 for(i=0;s[0]!=';' && i<boxnums;i++)
 {
   if(s[0]=='-') { ci.v = -get_int(); if(s[0]=='-') error("syntax"); }
      else if(t==integer) ci.v = atoi(s);
      else if(t==chopp) ci.vtype=s[0];
      else if(t==ident) { ci.vtype='t'; SCY(ci.txt,s); }
      else error("box syntax");
   ci.used=true;
   g_s();
 }
 if(!feof(fin)) write_call();

} /* process_box */

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


process_layer()
{int i;
 static char layers[numlayers][N_L];
 static boo  firstCall=true;
 static char x[N_L];

 if(firstCall)
 { for(i=0;i<=numlayers;i++) layers[i][0]='\0'; firstCall = false; }

 i=0;
 while(ch!=';') x[i++]=xg();
 xg();
 x[i]='\0';
 for(i=0;i<=numlayers&&layers[i][0]!='\0'&&SNE(x,layers[i]);i++) ;
 if(layers[i][0]=='\0')
  { SCY(layers[i],x); /* enter to tab */
    rmchar(' ',buf); fpf(fo,"%s",buf);
    fpf(fo,"%s",x);
  }
   else
   { rmchar(' ',buf); fpf(fo,"%s",buf);
     fpf(fo,"%c",'a'+i); }


  ix=0;
  buf[ix++]=ch;
  lastWasArray=false; lastWasArrayBox=false;
/*
i=0; 
printf("l\n");
while(layers[i][0]!='\0') printf("%s\n",layers[i++]);
*/
}


process_poly()
{int i;
   /* copy last P to opoints */
   for(i=0;i<numpoints,pi.used;i++)
   { oopi.v = opi.v; opi.v = pi.v; pi.used = false; pi.vtype = ' '; }

   xg(); g_s();
   for(i=0;!feof(fin) && s[0]!=';';i++) /* read coords into points */
   {
     if(s[0]=='-') pi.v = -get_int();
      else  if(t==integer) pi.v = atoi(s);
     pi.used = true;
     g_s();
     if(i>numpoints-10) error("Too many points in the polygon");
   }
   if(!feof(fin)) wp();

}


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

write_box()
{int i,j=0,nosemi=false; char spacer[1];
 spacer[0]='\0';
 spacer[1]='\0';
 rmchar(' ',buf);

 for(i=0;bi.used;i++)
  if(bi.vtype==' ')
  { if(bi.v == obi.v) bi.vtype = '^';
     else if(bi.v-obi.v == obi.v-oobi.v) bi.vtype='~';

     /* equals last num */
     else if(i>0 && bi.v==b[i-1].v) bi.vtype='&';

     /* equals one before last */
     else if(bi.v == oobi.v) bi.vtype='=';

     /* vertical delta */
     else if(delOk(obi.v,bi.v))
          { if(bi.v>obi.v) bi.vtype = '{'; else bi.vtype = '}'; }

     /* horiz delta */
     else if(i>0 && delOk(b[i-1].v,bi.v))
          { if(bi.v>b[i-1].v) bi.vtype = '['; else bi.vtype = ']'; }
  }


 /* for(i=0;bi.used;i++) printf("%d%c",bi.v,bi.vtype); printf("\n"); */

 /* write out the box */

 /* This is the detection of a regular array box '+' */
 if(b[0].vtype == '^' &&
    b[1].vtype == '^' &&
    b[2].vtype == '~' &&
    b[3].vtype == '^'    )
  { if(lastWasArrayBox) fputc('+',fo);
     else { fpf(fo,"%s+",buf); }
    lastWasArrayBox = true; nosemi=true; }

 else
 if(b[0].vtype == '^' &&
    b[1].vtype == '^' &&
    b[2].vtype == '^' &&
    b[3].vtype == '~'    )
  { if(lastWasArrayBox) fputc('*',fo);
     else { fpf(fo,"%s*",buf); }
    lastWasArrayBox = true; nosemi=true; }

 else
 {fpf(fo,"%s",buf);
  lastWasArrayBox = false;
  for(i=0;bi.used;i++)
  {if(bi.vtype!=' ')
   {
     if(     b[i].vtype          == '^' &&
             b[i+1].vtype        == '^'    )
              {fputc('_',fo); i+=1; spacer[0]='\0';}

     else if(i>0 && (bi.vtype == '[' || bi.vtype == ']'))
              {spacer[0]=' ';
               fpf(fo,"%c%d",bi.vtype,abs(bi.v-b[i-1].v)); }

     else if(bi.vtype == '{' || bi.vtype == '}')
             { spacer[0]=' ';
               fpf(fo,"%c%d",bi.vtype,abs(bi.v-obi.v)); }

     else { fputc(bi.vtype,fo); spacer[0]='\0'; }

   }
   else  { if(bi.v<0) fpf(fo,"%d",bi.v);
            else fpf(fo,"%s%d",spacer,bi.v); spacer[0]=' '; }
  } /* for */

 } /*else */

 if(!nosemi) fpf(fo,";");
 buf[ix++]=ch;
 lastWasArray=false;
}

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

process_box()
{int i;

 for(i=0;i<boxnums;i++)
 { oobi.v=obi.v; obi.v=bi.v; bi.vtype=' '; bi.used=false; }
 xg(); g_s();
 for(i=0;s[0]!=';' && i<boxnums;i++)
 {
   if(s[0]=='-') bi.v = -get_int();
      else if(t==integer) bi.v = atoi(s);
      else if(t==chopp) bi.vtype=s[0];
      else error("box syntax");
   bi.used=true;
   g_s();
 }
 if(!feof(fin)) write_box();

} /* process_box */

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

process_com()
{int i;

 /* locate and read if valid com */
 while (isspace(ch) && !feof(fin))  buf[ix++]=xg();
 buf[ix] = '\0';
 ix=0;

 if (ch=='P') process_poly();
  else if(ch=='B') process_box();
  else if(ch=='L') process_layer();
  else if(ch=='C') process_call();

 else {/* copy to next ';' */
       fpf(fo,"%s",buf);
       while (ch!=';' && !feof(fin)) { xg(); if(!feof(fin)) fputc(ch,fo); }
       if(!feof(fin)) {xg(); fputc(ch,fo);}
       lastWasArray = false;
       lastWasArrayBox = false;
      }

 /*  for(i=0;pi.used;i++) printf("p %d ",pi.v); printf("\n");
     printf("exit rp with ch=%c\n",ch); */
} /* pc */

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

wp()
{int i,j=0,nosemi=false; char spacer[1];
 spacer[0]='\0';
 spacer[1]='\0';
 rmchar(' ',buf);

 /* is it the same val as last poly? */
 for(i=0;pi.used;i++)
   if(pi.v == opi.v) pi.vtype = '^';

 /* put in the & */
 for(i=2;pi.used;i++)
   if(pi.v == points[i-2].v) pi.vtype = '&';

 /* detection of last 3 redundant values in rectangle */
 i--;
 if(pi.v == points[1].v) pi.vtype = '<';
 if(points[i-1].v == points[0].v) points[i-1].vtype = '<';


 /* put in the '@' */
 for(i=2;pi.used;i++)
  if(pi.vtype==' ')
   if(points[i-2].v-points[i].v == opoints[i-2].v-opoints[i].v)
     points[i].vtype = '@';

 /* put in the '~' */
 if(points[0].v-opoints[0].v == opoints[0].v-oopoints[0].v)
  points[0].vtype='~';

 /* vertical  delta */
 for(i=0;pi.used;i++)
  if(pi.vtype==' ')
     if(delOk(opi.v,pi.v))
      if(pi.v>opi.v) pi.vtype = '{'; else pi.vtype = '}';

 /* horiz delta */
 for(i=2;pi.used;i++)
  if(pi.vtype==' ')
    if(delOk(points[i-2].v,pi.v))
     if(pi.v>points[i-2].v) pi.vtype = '['; else pi.vtype = ']';


 /* for(i=0;pi.used;i++) printf("%d%c",pi.v,pi.vtype); printf("\n"); */

 /* write out the poly */

 /* This is the detection of a regular array rectangle '+' */
 if(points[0].vtype == '~' &&
    points[1].vtype == '^' &&
    points[2].vtype == '&' &&
    points[3].vtype == '^' &&
    points[4].vtype == '@' &&
    points[5].vtype == '&' &&
    points[6].vtype == '&' &&
    points[7].vtype == '<' &&
    points[8].used == false  )
  { if(lastWasArray) fputc('+',fo);
     else { fpf(fo,"%s+",buf); }
    lastWasArray = true; nosemi=true; }

 else
 {fpf(fo,"%s",buf);
  lastWasArray = false;
  for(i=0;pi.used;i++)
  {if(pi.vtype!=' ')
   {
    if(pi.vtype          == '^' &&
       points[i+1].vtype == '&' &&
       points[i+2].vtype == '^' &&
       points[i+3].vtype == '@' &&
       points[i+4].vtype == '&' &&
       points[i+5].vtype == '&' &&
       points[i+6].vtype == '<' &&
       points[i+7].used == false   )
              {fputc('?',fo); i+=6; spacer[0]='\0'; nosemi=true;}

     else if(pi.vtype          == '^' &&
             points[i+1].vtype == '&' &&
             points[i+2].vtype == '^')
              {fputc('%',fo); i+=2; spacer[0]='\0';}

     else if(pi.vtype          == '&' &&
             points[i+1].vtype == '&' &&
             points[i+2].vtype == '<' &&
             points[i+3].used  == false   )
              {fpf(fo,"|"); i+=2; spacer[0]='\0'; nosemi=true;}

     else if(pi.vtype          == '@' &&
             points[i+1].vtype == '&' &&
             points[i+2].vtype == '&' &&
             points[i+3].vtype != '<'    )
              {fputc('!',fo); i+=2; spacer[0]='\0';}

     else if(pi.vtype == '[' || pi.vtype == ']')
              {spacer[0]=' ';
               fpf(fo,"%c%d",pi.vtype,abs(pi.v-points[i-2].v)); }

     else if(pi.vtype == '{' || pi.vtype == '}')
             { spacer[0]=' ';
               fpf(fo,"%c%d",pi.vtype,abs(pi.v-opi.v)); }

     else { fputc(pi.vtype,fo); spacer[0]='\0'; }

   }
   else { if(pi.v<0) fpf(fo,"%d",pi.v);
           else fpf(fo,"%s%d",spacer,pi.v); spacer[0]=' ';  }
  } /* for */
 } /*else */

 if(!nosemi) fpf(fo,";");
 /* write the last ch read in process_poly */
 buf[ix++]=ch;
 lastWasArrayBox=false;
}

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

main(argc,argv)
int argc; char *argv[];
{

 if(bombDate-3600*240 < time(0)) fpf(stderr,"Expires in < 10days.\n");
 if(bombDate < time(0)) error("Version has expired. Contact US2.");

 /* command line parsing */

 if (arg_num(argc,argv,"-i*d")) {printf("Version %d\n",version); exit(0);}
 if (argc <2) error("USAGE: compdracif infile");

 fin=efopen(argv[1],"r");
 fo=efopen(cf(argv[1],".R"),"w");
 init();
 fpf(fo,"VERSION %d\n",version);
 SCY(s,"%");


 init_data();

 while(!feof(fin)) process_com();


} /* main */

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