/* { cc replace.c -o replace } */
/*
   This Program reads a text file and replaces every occurence of
   the specified string by the specified replacement string.
*/

#include <stdio.h>

#define TMPFILE "ram:REPLTMP"
#define TRUE -1
#define FALSE 0

FILE *fpin, *fpout;
int  filter = 0;

help()
{
printf("This Program reads a text file and replaces every occurence of\n");
printf("the specified string by the specified replacement string.\n");
printf("call convention:\n");
printf("replace -s 'search_string' -r 'replacement' [-f] -i file1 file2...\n");
printf("options:\n");
printf("  -s string    set search string\n");
printf("  -r string    set replace string\n");
printf("  -f      act as filter\n");
printf("  -v      verify input strings\n");
printf("  -i file[s]   input files\n");
printf("\n");
printf("(C) June 1991 by RAKO\n");
exit(0);
}

main(argc,argv)
int argc;
char *argv[];
{
int n,m,l;
unsigned char s[2048], z[256], search[256], replace[256];

   if(argc == 1) help();

   filter = 0;
   if(checkopt(argc,argv,"-f",z)) {
      filter = -1;
      fpin = stdin;
      fpout = stdout;
      xcng(s);
      exit_(s);
   }
   if(!checkopt(argc,argv,"-s",s)) help();
   cvtbs(search,s);
   if(!checkopt(argc,argv,"-r",s)) help();
   cvtbs(replace,s);

   if(checkopt(argc,argv,"-v",s)) {
      printf("search string =%s\nreplace string =%s\ncontinue ?\n",
              search,replace);
      scanf("%s",s);
      if(s[0] == 'n') exit(0);
      if(s[0] == 'N') exit(0);
   }

   for(m = 2 ; m < argc; m++) if(strcmp(argv[m],"-i") == 0) break;
   if(m == argc) help();
   for(n = m+1; n < argc; n++) {
      fpin = fopen(argv[n],"r");
      if(fpin == NULL) {
         fprintf(stderr,"replace: file not found %s\n",argv[n]);
         continue;
      }
      fpout = fopen(TMPFILE,"w");
      if(fpout == NULL) {
         fprintf(stderr,"could not open temporary file %s\n",TMPFILE);
         fclose(fpin);
         continue;
      }
      xcng(s,search,replace);
      fclose(fpin); fclose(fpout);
      renamefile(argv[n],s);
   }
   exit(0);
}

xcng(s,search,replace)
unsigned char *s, *search, *replace;
{
int p,i,n,l,l_search;
unsigned char s1[256], s2[256];

   l_search = strlen(search);
   while(!feof(fpin)) {
      fgets(s,4095,fpin);
      if(feof(fpin)) break;
      l = strlen(s);
      n = l - 1;
      if(l > 4090) {
         fprintf(stderr,"line too long!\n exiting...\n");
         exit_(s);
      }
      while(1==1) {
         p=instr(search,s);
         if(p < 0) break;
         midstr(s1,s,0,p-1);
         midstr(s2,s,p+l_search,l);
         strcpy(s,s1); strcat(s,replace); strcat(s,s2);
      }
      fputs(s,fpout);
   }
}

exit_(s)
unsigned char *s;
{
   if(filter == 0) {
      fclose(fpin);
      fclose(fpout);
   }
   exit(0);
}

renamefile(name,s)
char name[];
register unsigned char *s;
{
   fpout = fopen(name,"w");
   fpin = fopen(TMPFILE,"r");
   while(!feof(fpin)) {
      fgets(s,256,fpin);
      if(feof(fpin)) break;
      fputs(s,fpout);
   }
   fclose(fpin);
   fclose(fpout);
   unlink(TMPFILE);
}


checkopt(argc,argv,s,sv)
int argc;
char *argv[],s[],sv[];
{
int   n,m,i,erg;
char  c,z[80];

   erg=FALSE;
   for(n=1;n<argc;n++) {
      if(strcmp(argv[n],s)==0) {
         erg = TRUE;
         strcpy(sv,argv[n+1]);
      }
   }
   return(erg);
}

/* -------------------------------------------
   return position of a substring in a string
   ------------------------------------------- */
instr(substr,str)
char  str[],substr[];
{  short i,p,flg,l1,l2;

   l1=strlen(str); l2=strlen(substr);
   for(p=0; p < l1; p++) {
      flg=0;
      for(i=0; i < l2; i++) {
         if(str[p+i] != substr[i]) {
            flg = -1; break;
         }
      }
      if(flg == 0) return(p);
   }
   return(-1);
}


/* -------------------------------------------------
   return a substring from within a mainstring
   ------------------------------------------------- */
midstr(substr,str,ss,es)
char  substr[],str[];
short ss,es;
{  short i,j;

   i=0;
   for(j=ss; j <= es; j++) substr[i++]=str[j];
   substr[i]=0;
}


/* ---------------------------------------------------
   return right hand end of a string
   --------------------------------------------------- */
rightstr(substr,str,ss)
char  substr[],str[];
short ss;
{  short l;

   l=strlen(str); midstr(substr,str,ss,l-1);
}


/* -----------------------------------------------------
   return left hand side of a string
   ----------------------------------------------------- */
leftstr(substr,str,es)
char  substr[],str[];
short es;
{
   midstr(substr,str,0,es);
}


/* -------------------------------------------------------
   adjust string to the left, removing spaces
   ------------------------------------------------------- */
left(str)
char  str[];
{  short i;

   i=0;
   while(str[i] == ' ') i++;
   rightstr(str,str,i);
}


/* -------------------------------------------------------
   reverse a string
   ------------------------------------------------------- */
reverse(str)
char  str[];
{  short l,n,i,c;

   l=strlen(str)-1, n=l/2;
   for(i=0; i <=n; i++) {
      c=str[l-i]; str[l-i]=str[i]; str[i]=c;
   }
}


/* ------------------------------------------------------
   compare two strings equating upper and lower case
   ------------------------------------------------------ */
lexcmp(str1,str2)
char  str1[],str2[];
{  char s1[256],s2[256];

   strcpy(s1,str1); strcpy(s2,str2);
   strupc(s1); strupc(s2);
   return(strcmp(s1,s2));
}


/* ---------------------------------------------
   convert string to upper case
   --------------------------------------------- */
strupc(str)
char  str[];
{  short  l,i;

   l=strlen(str);
   for(i=0; i < l; i++) str[i]=toupper(str[i]);
}


/* convert string which includes the backslash */

cvtbs(s2,s1)
char s2[] , s1[];
{  int   i , l , i2 , i1 ;
   char  c , cc , s[8];

   l=strlen(s1); i2=0 ;
   for (i1 = 0; i1 <= l; i1++) {
      c=s1[i1];
      if(c == '\\') {
         cc=s1[++i1];
         switch(cc) {
         case 'n':
            c='\n' ;  break ;
         case 'f':
            c='\f' ;  break ;
         case 't':
            c='\t' ;  break ;
         case 'b':
            c='\b' ;  break ;
         case 'x': /* hexadecimal conversion */
            s[0]=s1[++i1] ; s[1]=s1[++i1] ; s[2]=0 ;
            c=xtoi(s) ; break ;
         default:
            ; } ;
         } ;
      s2[i2++]=c ; }
   s2[i2]=0 ;
   return(i2-1);
}

/* since the library c.lib is incomplete , i have to add xtoi here */

xtoi(s)
char  s[];
{  int i,m,l,e;
   char c;

   l=strlen(s); e=0;
   for( i = 0 ; i < l ; i++ ) {
      c = s[i] ; c = toupper(c) ;
      m = c - '0' ;
      if( m > 9 ) m = m - 7 ;
      e = 16 * e + m ;
      } ;
   return(e) ;
}
