/* replacestring.c */
/* This program reads a stream from standard
   input, and writes it to standard output,
   after performing string replacement.  It
   takes two arguments, the string to be 
   replaced and the replacement string.

   To display debugging info, compile with
   -D _DEBUG_
*/

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

/******** STRINGMATCH **************
  returns 1 if the string to be found (str) starts
  at buf[i], 0 otherwise
**********************************/
int stringmatch(char buf[], int i, char str[])
{
  int j=0;
  while (buf[i++]==str[j++]) { }
  if (j > 0 && str[j-1]=='\0')
     return 1;
  else return 0;
} 


/******** READTHEFILE **************
  Reads the entire file from standard
  input into a buffer.  If the amount of
  memory in the buffer is not large enough,
  it doubles the size of the buffer.
  It returns a pointer to the buffer.  The
  argument will be set to the number of bytes
  read from the file.
****************************************/
char *ReadTheFile(int *bytesread)
{
  char *buf;
  int n, i, available, bufsize;

  *bytesread = 0;
  bufsize = 1024;
  buf = (char *)malloc(bufsize);
  available = bufsize - *bytesread;
  /**************************************
   bufsize is the size of the buffer
   available is the number of free space
      remaining in the buffer
   bytesread is the total number of bytes
      read so far.
   available should equal bufsize minus bytesread
  ****************************************/
  n =read(0, &buf[*bytesread], available);
  while (1) {
    if (n < 0) {
       fprintf(stderr,"Error reading: good bye\n");
       exit(0);
    }
    if (n==0) break; /* file is complete */
    *bytesread += n;
    available -= n;
    if (available == 0) { /* no more space in the buffer */
      char *temp;
      bufsize *= 2;  /* make the buffer twice as big */
      temp = malloc(bufsize);
      for (i=0;i<bufsize/2;i++) /* copy the data in the old
                                   buffer to the new buffer */
	temp[i]=buf[i];
      free (buf);
      buf = temp;
      available = bufsize - *bytesread;
    }
    n = read(0,&buf[*bytesread], available);
  }  /* end of the while statement.  When we get
        here, the file has been completely read */
  return buf;
}
         
  
/***** MAIN ******************
  Reads the entire input file into a buffer
  and then searches the entire buffer for
  instances of the string to be matched.
******************************/
int main(int argc, char *argv[])
{
  char *buf;
  int i;
  int len1, len2;
  int count;

  if (argc != 3) {
    fprintf(stderr, 
        "error, wrong number of arguments, good bye\n");
    exit(0);
  }
  
#ifdef _DEBUG_
    fprintf(stderr,"DEBUG starting replacestring with args %s and %s\n",argv[1], argv[2]);
#endif
  len1 = strlen(argv[1]);
  len2 = strlen(argv[2]);
  buf = ReadTheFile(&count);
    i = 0;
    while (i < count) {
      if (stringmatch(buf,i,argv[1])) {
	write(1,argv[2],len2);
        i += len1;
      }
      else {
         write(1,&buf[i],1);
         i++;
      }
    }
#ifdef _DEBUG_
      fprintf(stderr,"DEBUG ending replacestring %s %s, %d bytes were read\n",
	      argv[1], argv[2], count);
#endif
      /* note that the number of bytes written is not necessarily
         the same as the number of bytes read */
  return 0;
}



