/*  This program changes characterstrings in files   */
/* For 100 KByte on the  RAMDisk it took  27 Seconds */
/* ------------------------------------------------- */
/* *************** Copyright Manfred Tornsdorf ***** */
/* ------------------------------------------------- */
#include <stdio.h>

#define FALSE 0                 /* Constants, make reading  */
#define TRUE 1                   /* the  program easier     */
#define byte unsigned char          
#define Maxbuffer 512            /* Size of the Read buffer */

 void Shift();
 char SearchString[127];        /* Search string */
 char ReplaceString[127];       /* replacement string */
 char Bufferin[Maxbuffer];       /* read buffer */
 int Pwrite;         /* Place in buffer for writing */
 int Pread;         /* Place in buffer for reading */

 unsigned long Num;  /* Num for characters */
 unsigned int Fromlen;
 unsigned int Tolen;
 unsigned int NumRepl;   /* Num for : how often replaced */
 FILE *Rin, *Rout;



/* -------------------- Get Parameters -------------------------- */
void GetPara(Para, First, Next)
char *Para;
char *First;
char *Next;
{
 int Number;
 int Length;      /* Number for length, 0 not counted */

 *First = 0;
 *Next = 0;
 Length = 0;      /* Length set to 0 */

 Number = atoi(Para);   /* check if  String or ASCII-value */
 if (Number != 0)         /* ASCII-value for String1 */
 {
   while ((*Para != 0)&&(*Para != ':'))    /* still more  String1 */
   {
      Number = atoi(Para);
      if (Number > 255)         /* number not allowed */
      {
         printf("Number is not ASCII-value\n");
         exit();
      }
      *(First++) = (char) Number;     /* take char */
      Length++;
      while ((*Para != 0)&&(*Para != ',')&&(*Para != ':'))
         Para++;         /* separate search */
      if (*Para == ',') Para++; /* skip , */
   }  /* End While */
   *First = 0;         /* end String1 with 0  */
   Fromlen = Length;      /* save length of String1 */
   }   /* End if( ASCII) */

 else             /* String1 is a String */
 {
    for(Length = 0; (*Para!=0)&&(*Para!=':'); Para++)
    {
       *(First++) = *Para;
       Length++;
    }
    *First = 0;         /* end search string with  0 */
    Fromlen = Length;      /* save lenght of string */
 }    /* End else */

if (Fromlen == 0)
    {
       printf("Search string must be given!\n");
       exit();
    }


 if (*Para != ':')
    {
       printf("Colon missing!\n");
       exit();
    }

 Para++;         /* Set Para after colon */
 Length = 0;         /* Length set to 0 */
 Number = atoi(Para);   /* Check if  String or ASCII-value */
 if (Number != 0)         /* ASCII-value for String2 */
 {
    while (*Para != 0)    /* Parameters for String2 */
    {
       Number = atoi(Para);
       if (Number > 255)         /* number not allowed */
       {
          printf("Number is not ASCII-value\n");
          exit();
       }
       *(Next++) = (char) Number;     /* take characters */
       Length++;         /* increase length */
       while ((*Para != 0)&&(*Para != ',')&&(*Para != ':'))
          Para++;         /* separate search */
       if (*Para == ',') Para++; /* skip */
    }  /* End While */
 *Next = 0;         /* end String2 with 0  */
 Tolen = Length;      /* save length of String2 */
 }   /* End if(ASCII)
 else             /* String2 is a String */
 {
    for(Length = 0; (*Para!=0); Para++)
    {
       *(Next++) = *Para;
       Length++;
    }
    *Next = 0;         /* end replace string with 0 */
    Tolen = Length;      /* save lenght of string */
 }    /* End else */

}

int Reader(Amount)
int Amount;
{
 register char Charsin;
 register int numread;

 numread = 0;

 for(numread = 0; numread < Amount; numread++)
 {
   Charsin = fgetc(Rin);
   if (Charsin == EOF)
     return(numread);      /* no more chars in file */
   Num++;         /* increase num chars */
   Bufferin[Pread++] = Charsin;
   if (Pread >= Maxbuffer)   /* Buffer at end, overflow */
      Shift();      /* shift to beginning */
 }
 return(numread);
}

void Shift()  /* contents in buffer shifted */
 {
  register int howmany;
  register int i;

  howmany = Pread - Pwrite;
  for (i = 0; i< howmany; i++)
     Bufferin[i] = Bufferin[Pwrite+i];
  Pwrite = 0;             /*  set new Indices */
  Pread = i;
 }

int Checkbuffer()       /* compare Search string with buffer */
{
 register char *string;
 register int i;

 i = Pwrite;
 for (string = &SearchString[0]; *string != 0; string++)
 {
    if (*string != Bufferin[i])
       return(FALSE);
    i++;
 }
 return(TRUE);
}

void Writecharacter()   /* Write Char in in buffer to file */
{
 register char Charsin;

 Charsin = Bufferin[Pwrite];
 fputc(Charsin, Rout);
 Pwrite++;      /* reset write pointer */
}

void Replace()      /* write replace string, buffer send */
{
 int i;
 char *string;
 register char Charsin;

 i = 1;
 for (string = &ReplaceString[0]; *string != 0; string++)
 {
    Charsin = *string;
    fputc(Charsin, Rout);
    i++;
 }
 Pwrite = Pread;     /* write = read pointer -> clear buffer */
}

void Writerest()   /* no more chars in file, write buffer */
{
 register char Charsin;
 int i;

i = 0;
 for(i = Pwrite; i < Pread; i++)
 {
    Charsin = Bufferin[i];
    putc(Charsin, Rout);
 }
}



main (Amount, Argument)
int Amount;
char *Argument[];
{
 int Numtoread;
 int Totalread;
 int Error;
 if (Amount != 4)
    {
        printf("This program replaces char strings \n");
        printf("Copyright Manfred Tornsdorf\n");
    printf("Call: Filenameold Filenamenew String\n");
        printf("either :String = Number,Number,Number...:Number,Number,Number...\n");
        printf("or     :String = string:string\n\n");
        printf("Example :Replace t.txt tt.txt Mytext:32,33,32\n");
        printf("gives   :<Mytext> -> < ! >\n");
        printf("No replace string, so it is deleted\n");
    exit();
        }

 GetPara(Argument[3], &SearchString, &ReplaceString );
/* build search and replace string  */
 Fromlen = strlen(SearchString);
 Tolen = strlen(ReplaceString);

 Rin = fopen(Argument[1], "r");
 Rout = fopen(Argument[2], "w");
 if (Rin == 0)
 {
 puts ("Input file not found!");
 exit ();
 }
 if (Rout == 0)
 {
 puts ("Cannot open th eoutput file!");
 exit ();
 }
 Num = 0;
 Pwrite = 0;         /* Write pointer to start of buffer */
 Pread = 0;         /* read pointer to start of buffer */
 Numtoread = Fromlen;      /* Search string chars to read */
 NumRepl = 0;      /* Default: not found */

 Totalread = 1;      /* Default, the TC to count */
 while(Totalread != 0)
 {
    Totalread = Reader(Numtoread); /* read amount fro file */
    Error = Checkbuffer();
    if(Error == FALSE)    /* not found */
    {
       Writecharacter();    /* 1. write chars */
       Numtoread = 1;             /* read one char */
    }
    else             /* found */
    {
      Replace();      /* write replace string, off buffer */
      NumRepl++;       /* increse number replaced */
      Numtoread = Fromlen;
    }
 }   /* End while(), File empty */
 Writerest();         /* Write last char from buffer */

 printf("\nString replaced %d times!\n", NumRepl);
 fclose(Rin);
 fclose(Rout);
 exit();


}
