/************************************************************
**
** Application: SyncDiscs
**
** Title:       c.zone
**
*************************************************************/

/*
*
* Copyright (c) 2017, David Pilling and Chris Johnson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of the copyright holder nor the names of their
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/

/* Include files */
/* from standard clib */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>



#include "Tasklib:h.os"
#include "Tasklib:h.flex"
#include "Tasklib:h.bits"
#include "Tasklib:h.fsx"
#include "Tasklib:h.bf"
#include "Tasklib:h.werr"


/* from application */
#include "h.zone"



/************************************************************/
/* global variables */

static char * zone;
static int    zonelen;



/************************************************************/

static os_error * addzones(char * path,int all)
{
 os_error * err;
 int        len;
 char     * p;

 err=NULL;

 if(all<0 || all>2) all=0;

 p=zone;
 while((p-zone)<zonelen)
 {
  len=strlen(p)+2;
  if(!cstrcmp(p,path))
  {
   *(p+len-1)=all;
   break;
  }
  p+=len;
 }


 if((p-zone)>=zonelen)
 {
  len=strlen(path)+2;

  err=flex_extend((flex_ptr)&zone,zonelen+len);
  if(!err)
  {
   strcpy(zone+zonelen,path);
   zonelen+=len;
   zone[zonelen-1]=all;
  }
 }


 return(err);
}


/************************************************************/

static char * addstring[3]=
{
 "some",
 "all",
 "none"
};



static os_error * addzone(char * args[],int argc)
{
 int code;

 code=0;

 if(argc==2)
 {
  for(code=0;code<3;code++)
    if(!cstrcmp(args[1],addstring[code])) break;
 }

 return(addzones(args[0],code)); /* know this traps bad values */
}



/************************************************************/

// return 1 to ignore this path

int inzone(char * path,int * all)
{
 char * p;
 int    len;
 char * q1;
 char * q10;
 char * q2;
 char * q20;
 int    c1;
 int    c2;


 p=zone;
 while(p<(zone+zonelen))
 {
  len=strlen(p)+2;

  /* is p the lhs of path? */

  if(strncmp(p,"...",3)==0)
  {
   q10=path;
   q20=p+3;
   while(*q20=='*') q20++;  // no ... *  sequence
   q1=q10+strlen(q10);
   q2=q20+strlen(q20);

   while(1)
   {
    c1=toupper(*q1--);
    c2=toupper(*q2--);

    if(c2=='?')
    {
     // matches anything
    }
    else
    if(c2=='*')
    {
     c2=toupper(*q2);
     if(c2!='*')
     {
      if(c1!=c2) q2++;
      else       q2--;
     }
    }
    else
    {
     if(c1!=c2) break;
    }

    if(q2<q20)
    {
     if(all) *all=*(p+len-1);
     return(1);
    }

    if(q1<q10) break;
   }
  }
  else
  {
   q1=path;
   q2=p;            // pattern

   while(1)
   {
    c2=toupper(*q2++);
    if(!c2)
    {
     if(all) *all=*(p+len-1);
     return(1);
    }

    c1=toupper(*q1++);

    if(c2=='?')
    {
     // matches anything
    }
    else
    if(c2=='*')
    {
     c2=toupper(*q2);
     if(c2!='*')
     {
      if(c1!=c2) q2--;
      else
      if(c2) q2++;
     }
    }
    else
    {
     if(c1!=c2) break;
    }
   }
  }

  p+=len;
 }

 return(0);
}







/************************************************************/

os_error * zoneinit(char * zpath)
{
 os_error * err;
 buffer     bf;
 char     * string[1];
 char       arg[256];
 int        type;
 int        eof;

 err=flex_alloc((flex_ptr)&zone,0);
 zonelen=0;

 string[0]=arg;

 if(!err)
 {
  fs_exists(zpath,&type);
  if(type==1)
  {
   err=bf_open(zpath,'r',DEFBUFFSIZE,&bf);
   if(!err)
   {
    while(1)
    {
     err=bf_getstring(&bf,string[0],sizeof(arg),&eof);
     if(err) break;
     if(eof) break;
     if ((strcmp(string[0],"")!=0) && (*string[0] != '#'))
       addzone(string,1);
    }
    err=bf_close(&bf,err);
   }
  }
 }

 return(err);
}




/************************************************************/

os_error * zone_finit(void)
{
  os_error * err;

  err = flex_free ((flex_ptr)&zone);

  return (NULL);

}



/*************  End of c.zone  ***********************/


