/* This file is part of the origami distribution (Amiga Port)
 *
 * Source code written by Thomas in December 1991
 * Version : 1.6.42 alpha, June 1992
 * refer 1.6
 * (C)1992 by Thomas Hadig
 */
#define version "1.6"

/*{{{  includes*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <local/bool.h>
#include <local/argparse.h>
/*}}}  */
/*{{{  variables*/
#define REFSTR "----------- ( Reference : %d ) ---------------------------------------------------------\n"
FILE *fp,*fg;

#define MAX_LEN 256
char *h,str[MAX_LEN];

int found=0,maxdef=0;

#define DEFMAX 20
char *defines[DEFMAX];

/*{{{  argparse*/
char define[30]="",envvar[30]="ORIAREA",filename[30]="T:ref",
     envvar2[30]="ORIWORD",filename2[30]="S:refer";
int  max_lines;
bool small=FALSE,quiet=FALSE,verbose=FALSE,usage=FALSE;
/*{{{  argument parser table*/
#define argnum 10

ARG argtab[] =
{
  'd', STRING_ARG, define,
  'e', STRING_ARG, envvar,
  'f', STRING_ARG, filename,
  'r', STRING_ARG, filename2,
  'g', STRING_ARG, envvar2,
  'm', INT_ARG,    &max_lines,
  's', BOOL_ARG,   &small,
  'q', BOOL_ARG,   &quiet,
  'v', BOOL_ARG,   &verbose,
  'h', BOOL_ARG,   &usage,
  '?', BOOL_ARG,   &usage
};
/*}}}  */
/*}}}  */
/*}}}  */

/*{{{  defined*/
int defined (char *ptr)

{
  int i=maxdef;

  if (!strcmp (ptr,define))
  {
    return 1;
  }
  if (!maxdef) return 0;
  while (i>=0)
  {
    if (!strcmp (ptr,defines[i])) return 1;
    i--;
  }
  return 0;
}
/*}}}  */
/*{{{  skip_to_space*/
char *skip_to_space (char *ptr)

{
  char *pptr=ptr;

  while ((!isspace(*pptr))&&(*pptr)) ++pptr;
  return pptr;
}
/*}}}  */
/*{{{  skip_to_no_space*/
char *skip_to_no_space (char *ptr)

{
  char *pptr=ptr;

  while (isspace(*pptr)) ++pptr;
  return pptr;
}
/*}}}  */
/*{{{  get_string*/
int get_string (char *buffer,int len, FILE *f)

{
  int ok=0;
  char *pt;

  while ((!ok)&&(!feof(f)))
  {
    if (fgets(buffer,len,f))
    /*{{{  parse line*/
    {
      if (buffer[strlen(buffer)-1]=='\n') buffer[strlen(buffer)-1]=0;
      if (verbose) fprintf (fg,"Parsing line >>%s<< ... ",buffer);
      pt = skip_to_no_space (buffer);
      switch (pt[0])
      {
        /*{{{  # commands*/
        case '#' :
        {
          /*{{{  define ?*/
          if (!strncmp (pt+1,"define",6))
          {
            if (verbose) fprintf (fg,"define\n");
            /*{{{  define*/
            if (maxdef<DEFMAX)
            {
              pt = skip_to_no_space (pt+7);
              defines[maxdef++] = (char *)strdup (pt);
            }
            /*}}}  */
            else if (!quiet) fprintf (fg,"Warning : too many defines !\n");
          }
          /*}}}  */
          /*{{{  if ?*/
          else if (!strncmp (pt+1,"if",2))
          {
            if (verbose) fprintf (fg,"if\n");
            pt = skip_to_no_space (pt+3);
            /*{{{  search for matching #endif*/
            if (!defined (pt))
            {
              int stop = 1;

              while ((!feof (f))&&(stop))
              {
                if (!fgets(buffer,len,f)) return 1;
                pt = skip_to_no_space (buffer);
                if (!strncmp (pt,"#endif",6)) --stop;
                else if (!strncmp (pt,"#if",3)) stop++;
              }
              if (feof (f)) return 1;
            }
            /*}}}  */
          }
          /*}}}  */
          /*{{{  endif ?*/
          else if (!strncmp (pt+1,"endif",5))
          {
            if (verbose) fprintf (fg,"endif !\n");
            break;
          }
          /*}}}  */
          /*{{{  unknown command*/
          else
          {
            if (!quiet) fprintf (fg,"Error unknown command : %s\n",buffer);
            return 1;
          }
          /*}}}  */
          break;
        }
        /*}}}  */
        /*{{{  comments*/
        case ';' :
          if (verbose) fprintf (fg,"comment\n");
          break;
        /*}}}  */
        /*{{{  default*/
        default :
          if (verbose) fprintf (fg,"reference line\n");
          ok=1;
          break;
        /*}}}  */
      }
    }
    /*}}}  */
    else return 1;
  }
 if (feof(f)) return 1;
 return 0;
}
/*}}}  */

/*{{{  handle*/
int handle (char *pptr,char *refname)

{
  /*{{{  variables*/
  int line;
  long seekpos;
  char name[MAX_LEN],*p,*ptr,*pold,endstring[MAX_LEN]="",firststring[MAX_LEN]="";
  FILE *ff;
  /*}}}  */

  pold = ptr = strdup (pptr);
  found++;
  if (!quiet) fprintf (fg,REFSTR,found);
  /*{{{  get datas*/
  /*{{{  skip search_word*/
  ptr = skip_to_space(ptr);
  ptr = skip_to_no_space(ptr);
  /*}}}  */
  /*{{{  get number of lines in ref of endstring*/
  if (!(line = atoi (ptr)))
  {
    p=ptr;
    ptr = skip_to_space (ptr);
    *ptr=0;
    ptr++;
    if (!strcmp (p,"(^L)")) strcpy (endstring,"\x0c");
    else strncpy (endstring,p,MAX_LEN);
  }
  else ptr = skip_to_space(ptr);
  ptr = skip_to_no_space(ptr);
  /*}}}  */
  /*{{{  get filename*/
  /*{{{  get path of referencefile*/
  strcpy (name,refname);
  seekpos = strlen(name);
  while ((--seekpos)&&((name[seekpos]!=':')&&(name[seekpos]!='/')));
  if ((name[seekpos]==':')||(name[seekpos]=='/')) seekpos++;
  name[seekpos]=0;
  /*}}}  */
  /*{{{  skip to end of filename*/
  p=ptr;
  ptr = skip_to_space(ptr);
  *ptr=0;
  /*}}}  */
  strcat (name,p);
  ptr++;
  /*}}}  */
  /*{{{  look for @@ and get seekpos or firststring*/
  ptr = skip_to_no_space(ptr);
  if (strncmp (ptr,"@@",2)) strncpy (firststring,ptr,MAX_LEN);
  else
  {
    ptr +=2;
    seekpos = atol (ptr);
  }
  /*}}}  */
  if (verbose) fprintf (fg,
      "Got reference datas :\n Lines %d, File %s, SeekPos %ld\n  First string %s\n  End string %s\n",
      line,name,seekpos,firststring,endstring);
  /*}}}  */
  /*{{{  get seekpos and lines if firststring or endstring*/
  /*{{{  firststring*/
  if (*firststring)
  {
    long ll;

    /*{{{  open file*/
    if ((ff = fopen (name,"r"))==NULL)
    {
      free (ptr);
      return 1;
    }
    if (verbose) fprintf (fg,"Opened File >>%s<<\n",name);
    /*}}}  */
    /*{{{  look for string*/
    seekpos =0;
    while (!(feof (ff)||seekpos))
    {
      ll = ftell (ff);
      fgets (str,MAX_LEN,ff);
      if (*str) /* fix for sas bug */
        if (strstr (str,firststring)) seekpos = ll;
    }
    /*}}}  */
    /*{{{  close file*/
    if (!*endstring) fclose (ff);
    /*}}}  */
    if (verbose) fprintf (fg, "Got seekpos : %ld\n",seekpos);
  }
  /*}}}  */
  /*{{{  endstring*/
  if (*endstring)
  {
    long ll=0;

    /*{{{  open file*/
    if (!*firststring)
    {
      if ((ff = fopen (name,"r"))==NULL)
      {
        free (ptr);
        return 1;
      }
      else fseek (ff,seekpos,0);
    }
    if (verbose) fprintf (fg,"Opened File >>%s<<\n",name);
    /*}}}  */
    /*{{{  look for endstring*/
    line = 0;
    while (!(feof (ff)||line))
      {
        ll++; /* count lines */
        fgets (str,MAX_LEN,ff);
        if (*str) /* fix for sas bug */
          if (strstr (str,endstring)) line = ll;
      }

    /*}}}  */
    /*{{{  close file*/
    fclose (ff);
    /*}}}  */
    if (verbose) fprintf (fg,"Got number of lines : %d\n",line);
  }
  /*}}}  */
  /*}}}  */
  if ((line<max_lines)||(max_lines==0))
  /*{{{  write reference files*/
  {
    /*{{{  open file*/
    if ((ff = fopen (name,"r"))==NULL)
    {
      free (ptr);
      return 1;
    }
    if (verbose) fprintf (fg,"Opened File >>%s<<\n",name);
    /*}}}  */
    /*{{{  goto seek pos*/
    if (fseek (ff,seekpos,0))
    {
      free (ptr);
      return 1;
    }
    if (verbose) fprintf (fg,"Got SeekPos !\n",name);
    /*}}}  */
    /*{{{  write lines*/
    while (line--)
    {
      fgets (str,MAX_LEN,ff);
      fputs (str,fg);
    }
    /*}}}  */
    /*{{{  close file*/
    fclose (ff);
    /*}}}  */
  }
  /*}}}  */
  else fprintf (fg,"%s\n",pptr);
  free (pold);
  return 0;
}
/*}}}  */
/*{{{  parse_file*/
void parse_file (char *name)

 {
  /*{{{  variables*/
  FILE *fd;
  int len;
  char *sstr;
  /*}}}  */

  /*{{{  open file*/
  if ((fd = fopen (name,"r"))==NULL)
   {
    if (!quiet) fprintf (fg,"Warning : Can not open file >>%s<< !\n",name);
    return;
   }
  if (verbose) fprintf (fg,"Opened files >>%s<<\n",name);
  /*}}}  */
  len = strlen (h);
  while (!feof(fd))
  /*{{{  parse one line*/
  {
    if (!get_string (str,MAX_LEN,fd))
    {
      sstr = skip_to_no_space(str);
      if (!strncmp (sstr,h,len))
      /*{{{  found ?*/
      {
        if (isspace(sstr[len]))
        /*{{{  yes*/
        {
          if (verbose) fprintf (fg,"Search string found !\n");
          if (small)
          {
            found++;
            if (!quiet) fprintf (fg,REFSTR,found);
            fprintf (fg,"%s\n",sstr);
          }
          else if (handle (sstr,name))
          {
            if (!quiet)
              fprintf (fg,"Error scanning file : %s, line %s\n",name,sstr);
          }
        }
        /*}}}  */
      }
      /*}}}  */
    }
  }
  /*}}}  */
 }
/*}}}  */

/*{{{  main*/
void main (int argc, char **argv)

 {
  argc=argparse(argc,argv,argtab,argnum);
  /*{{{  usage*/
  if ((usage)||(argc>1))
  {
    fprintf (stderr,"refer Version %s\nUsage : %s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
           version,
           argv[0],"-f filename (write to file, T:ref)",
           "-r filename (reference file, S:refer)",
           "-g env-var (search string from env-var, ORIWORD)",
           "-e env-var (filename to env-var, ORIAREA)",
           "-d define (define symbol)",
           "-v (verbose)       -s (small)",
           "-h,-? (usage)      -q (quiet)",
           "-m lines (max ref lines)");
    exit (0);
  }
  /*}}}  */
  if (verbose) quiet = FALSE;
  /*{{{  open write file*/
  if ((fg = fopen (filename,"w"))==NULL) exit (1);
  if (verbose) fprintf (fg,"Opened file >>%s<<\n",filename);
  /*}}}  */
  /*{{{  setenv*/
  if (*envvar)
  {
    sprintf (str,"%s=%s",envvar,filename);
    putenv (str);
    if (verbose) fprintf (fg,"Set env-var >>%s<<\n",str);
  }
  /*}}}  */
  /*{{{  get search string*/
  if ((h = (char *)getenv (envvar2))==NULL)
   {
    if (!quiet) fprintf (fg,"Enviroment-Variable %s not set !\n",envvar2);
    exit (2);
   }
  if (verbose)
    fprintf (fg,"Got search string >>%s<< from env-var >>%s<<\n",h,envvar2);
  /*}}}  */
  /*{{{  get file*/
  if ((fp = fopen(filename2,"r"))==NULL)
   {
    if (!quiet) fprintf (fg,"Can not open file %s\n",filename2);
    exit (3);
   }
  if (verbose) fprintf (fg,"Opened file >>%s<<\n",filename2);
  /*}}}  */
  /*{{{  parse file*/
  while (!feof(fp))
   {
    char s[80],*ss;

    get_string (s,80,fp);
    ss = skip_to_no_space(s);
    if (strlen(ss)>0) parse_file (ss);
   }
  /*}}}  */
  /*{{{  print sorry message*/
  if ((!found)&&(!quiet))
   {
    fprintf (fg,"Sorry no reference available !\n");
   }
  /*}}}  */
  /*{{{  close files*/
  fclose (fg);
  fclose (fp);
  /*}}}  */
 }
/*}}}  */

#ifndef LATTICE
/*{{{  putenv*/
int putenv (char *env)

 {
  FILE *fd;
  int i;
  char *ptr=env;

  while ((*ptr)&&(*ptr!=' ')) ptr++;
  if (*ptr!=' ') return -1;
  *ptr=0;
  ptr++;
  if (fd = fopen (env,"w")) return -2;
  fprintf (fd,"%s",ptr);
  fclose (fd);
  return 0;
 }
/*}}}  */
#endif
