Task: Globally replace text in several files

C: #include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <err.h>
#include <string.h>

char * find_match(const char *buf, const char * buf_end, const char *pat, size_t len)
{
	ptrdiff_t i;
	char *start = buf;
	while (start + len < buf_end) {
		for (i = 0; i < len; i++)
			if (start[i] != pat[i]) break;

		if (i == len) return (char *)start;
		start++;
	}
	return 0;
}

int replace(const char *from, const char *to, const char *fname)
{
#define bail(msg) { warn(msg" '%s'", fname); goto done; }
	struct stat st;
	int ret = 0;
	char *buf = 0, *start, *end;
	size_t len = strlen(from), nlen = strlen(to);
	int fd = open(fname, O_RDWR);

	if (fd == -1) bail("Can't open");
	if (fstat(fd, &st) == -1) bail("Can't stat");
	if (!(buf = malloc(st.st_size))) bail("Can't alloc");
	if (read(fd, buf, st.st_size) != st.st_size) bail("Bad read");

	start = buf;
	end = find_match(start, buf + st.st_size, from, len);
	if (!end) goto done; 

	ftruncate(fd, 0);
	lseek(fd, 0, 0);
	do {
		write(fd, start, end - start);	
		write(fd, to, nlen);		
		start = end + len;		
						
		end = find_match(start, buf + st.st_size, from, len);
	} while (end);

	
	if (start < buf + st.st_size)
		write(fd, start, buf + st.st_size - start);

done:
	if (fd != -1) close(fd);
	if (buf) free(buf);
	return ret;
}

int main()
{
	const char *from = "Goodbye, London!";
	const char *to   = "Hello, New York!";
	const char * files[] = { "test1.txt", "test2.txt", "test3.txt" };
	int i;

	for (i = 0; i < sizeof(files)/sizeof(char*); i++)
		replace(from, to, files[i]);

	return 0;
}










Fortran:       SUBROUTINE FILEHACK(FNAME,THIS,THAT)	
       CHARACTER*(*) FNAME	
       CHARACTER*(*) THIS	
       CHARACTER*(*) THAT	
       INTEGER F,T		
       PARAMETER (F=66,T=67)	
       INTEGER L		
       CHARACTER*6666 ALINE	
       LOGICAL AHIT		
        INQUIRE(FILE = FNAME, EXIST = AHIT)	
        IF (.NOT.AHIT) RETURN			
        OPEN (F,FILE=FNAME,STATUS="OLD",ACTION="READWRITE")	
        OPEN (T,STATUS="SCRATCH")	
        AHIT = .FALSE.		
Chew through the input, replacing THIS by THAT while writing to the temporary file..
   10   READ (F,11,END = 20) L,ALINE(1:MIN(L,LEN(ALINE)))	
        IF (L.GT.LEN(ALINE)) STOP "Monster record
   11   FORMAT (Q,A)		
        L1 = 1			
   12   L2 = INDEX(ALINE(L1:L),THIS)	
        IF (L2.LE.0) THEN		
          WRITE (T,13) ALINE(L1:L)	
   13     FORMAT (A)			
          GO TO 10			
        END IF				
   14   L2 = L1 + L2 - 2	
        WRITE (T,15) ALINE(L1:L2)	
   15   FORMAT (A,$)			
        WRITE (T,15) THAT		
        AHIT = .TRUE.			
        L1 = L2 + LEN(THIS) + 1		
        IF (L - L1 + 1 .GE. LEN(THIS)) GO TO 12	
        WRITE (T,13) ALINE(L1:L)	
        GO TO 10		
Copy the temporary file back over the source file. Hope for no mishap and data loss
   20   IF (AHIT) THEN	
          CLOSE (F)		
          REWIND T		
          OPEN (F,FILE="new"//FNAME,STATUS = "REPLACE",ACTION = "WRITE")	
   21     READ (T,11,END = 22) L,ALINE(1:MIN(L,LEN(ALINE)))	
          IF (L.GT.LEN(ALINE)) STOP "Monster changed record
          WRITE (F,13) ALINE(1:L) 		
          GO TO 21			
        END IF		
   22   CLOSE(T)	
        CLOSE(F)	
      END	

      PROGRAM ATTACK
      INTEGER N
      PARAMETER (N = 6)		
      CHARACTER*48 VICTIM(N)	
      DATA VICTIM/		
     1 "StaffStory.txt",
     2 "Accounts.dat",
     3 "TravelAgent.txt",
     4 "RemovalFirm.dat",
     5 "Addresses.txt",
     6 "SongLyrics.txt"/	

      DO I = 1,N	
        CALL FILEHACK(VICTIM(I),"Goodbye London
      END DO		

      END