/* match p1 p2 ... pn < texte */

#include <stdio.h>
#include "defs.h"

char patterns[MAXPAT][MAXSTR]; /* pattern array */
int num_of_pats=0;               /* number of patterns */

extern node *source;
extern node *APPEND_LETTER(),*CREATE_NODE(),*LOAD_KEYWORD();

node *currentnode;
int length;

int index[MAXPAT];            /* reading position in each pattern */

int occur[MAXPAT][MAXFRAG];   /* array for storing founded occurrences (end positions) */
int active[MAXPAT];           /* index of active fragment of every pattern */

MATCH(fp)
     FILE *fp;
{
  int position=0;
   int underloading[MAXPAT];             /* indicator "is under loading?" */      
   node *PORTNODE[MAXPAT];               /* array of portnodes */
   
   int i,j;
   node *portnode,*newportnode,*closestterminal,*currentterminal;
   node *CLOSEST_TERMINAL();
   char currentletter,patternletter;
   kwlist *kl;
/*   pair pp,UPDATE_CURRENT_NODE(); */

   source=CREATE_NODE();
   currentnode=source;
   length=0;
   for (i=0;i<num_of_pats;i++) {
     underloading[i]=YES; 
     PORTNODE[i]=source;
     index[i]=0;
   }
   while ((currentletter=getc(fp)) != EOF) {
     position++;
/*     printf("position=%d\n",position);  */
     /* stage 1 */
     for (i=0;i<num_of_pats;i++) {
       if (underloading[i]==YES) {
	 portnode=PORTNODE[i];
	 patternletter=patterns[i][index[i]++];
	 newportnode=APPEND_LETTER(portnode,LET_TO_NUM(patternletter));	   
	 newportnode->prefix_degree++;
	 if (patterns[i][index[i]]!=DONTCARE && index[i]<strlen(patterns[i])) 
	   PORTNODE[i] = newportnode;
         else {
	   underloading[i]=NO; 
           /* add patterns[i] to the list of terminal node for newportnode */
           kl = (kwlist*) malloc(sizeof(kwlist));
           kl->kw=i; kl->next=newportnode->terminal;
	   newportnode->terminal=kl;
	 }
       }
     }
     /* stage 2 */
/*     pp = UPDATE_CURRENT_NODE(currentnode,length,LET_TO_NUM(currentletter));*/
     UPDATE_CURRENT_NODE(LET_TO_NUM(currentletter));
/*     currentnode=pp.nod; length=pp.len; */
     /* stage 3 */
     if (currentnode->terminal != NULL && currentnode->depth==length)
        closestterminal=currentnode;
     else closestterminal=CLOSEST_TERMINAL(currentnode);
     while (closestterminal != UNDEFINED) {
        currentterminal=closestterminal;
        closestterminal=CLOSEST_TERMINAL(closestterminal);
        kl=currentterminal->terminal;
        while (kl != NULL) {
           i=kl->kw; /* index i of pattern patterns[i] in the list */
	   occur[i][active[i]++]=position;
           if (index[i]==strlen(patterns[i])) {
              printf("pattern %s occurs in the text at positions",patterns[i]);
	      for (j=0;j<active[i];j++) printf(" %d",occur[i][j]);
	      printf("\n");
	      exit(0);
	    }
           else {
/*	     putchar('\n'); */
/*	     printf("fragment recognized; position=%d\n",position); */
	      UNLOAD_KEYWORD(currentterminal);
	      currentterminal->terminal=kl->next;
	      free(kl);
	      kl=currentterminal->terminal;
              underloading[i]=YES;
              PORTNODE[i]=source;
	      index[i]++;
	    }
	 }
      }
   }
   printf("text does not have occurrences of P\n");
   exit(1);
 }

node *CLOSEST_TERMINAL(nod)   /* finds the closest anscestor (excluding nod) */
			      /* which is a terminal node; if there are none, */
                              /* return UNDEFINED */
     node *nod;
{
  node *aux=nod;
  while ((aux=aux->suf_pointer) != NULL)  /* aux is not source */
    if (aux->terminal != NULL) return(aux);
  return UNDEFINED;
}

UPDATE_CURRENT_NODE(currentletter)
int currentletter;
{
/*   pair p; */

   while (currentnode->out[currentletter]==UNDEFINED)
      if (currentnode==source) {
/*         p.nod=currentnode; p.len=0; return(p); */
	length=0;
	return;
      }
      else {
         currentnode = currentnode->suf_pointer;
         length = currentnode->depth;
      }
   currentnode = currentnode->out[currentletter];
   length++;
/*   p.nod=currentnode; p.len=length;*/
/*   return(p);*/
   return;
}

main(argc,argv)
     int argc;
     char *argv[];
{
FILE *fp, *fpattern, *fopen();
char c;
int index=0;
char *pointer;

if (argc==1) wrongcall();
if (argv[1][0]=='-') {
  if (argv[1][1]!='f') wrongcall();
  if (argc<4) wrongcall();
  fpattern=fopen(argv[2],"r");
  c=getc(fpattern);
  for(;;) {
    while (c != '|' && c != EOF) {
      patterns[num_of_pats][index++]=c;
      c=getc(fpattern);
    }
    patterns[num_of_pats++][index]='\0';
    index=0;
    if (c == EOF) break;
    c=getc(fpattern);
  }
}
else {
  if (argc<3) wrongcall();
  pointer=argv[1];
  for(;;) {
    index=0;
    while (*pointer!='|' && *pointer!='\0') {
      patterns[num_of_pats][index++]=*pointer;
      pointer++;
    }
    patterns[num_of_pats++][index]='\0';
    index=0;
    if (*pointer == '\0') break;
    pointer++;
  }
  fp=fopen(argv[2],"r");
}
MATCH(fp);
}

wrongcall()
{
  printf("Usage: grappe [ -f patternfile ] [ pattern ] textfile\n");
  exit(2);
}

