/* * replace.c: * search & replace, from stdin or file, to stdout */ #include <stdio.h> #include <stdlib.h> #include <string.h> /* * Use a 4K temporary buffer */ #define MAXBUFSIZE 4096 /* * Boyer-Moore string search algorithm */ static char *search(char *spc, int slen, char *pat, int plen) { int skip[256]; int i, j, t; for (i = 0; i < 256; i++) skip[i] = plen; for (i = 0; i < plen; i++) skip[pat[i]] = plen - i - 1; for (i = plen - 1, j = plen - 1; j > 0; i--, j--) while (spc[i] != pat[j]) { t = skip[spc[i]]; i += plen - j > t ? plen - j : t; if (i >= slen) return NULL; j = plen - 1; } return spc + i; } int main(int argc, char *argv[]) { FILE *FIn; int plen, slen, rlen; char *buf; char *pbuf, *sbuf; int r, w; /* * process command line args */ if (argc < 3 || argc > 4) { fprintf(stderr, "Syntax: replace search_str replace_str [src_file]\n"); exit(0); } /* * get input */ if (argc == 3) FIn = stdin; else { if (!(FIn = fopen(argv[3], "rb"))) { fprintf(stderr, "Error opening %s\n", argv[3]); exit(0); } } /* * set up */ plen = strlen(argv[1]); /* search pattern length */ rlen = strlen(argv[2]); /* replacement string length */ slen = plen + MAXBUFSIZE; pbuf = NULL; w = 0; buf = (char *) malloc(slen + 1); if (!buf) { fprintf(stderr, "Error allocating memory for buffer.\n"); exit(0); } /* * use small buffers for lower memory usage */ r = fread(buf, 1, slen, FIn); while (r > 0) { /* * ensure buffer is null terminated */ buf[r] = '\0'; /* * scan buffer for the pattern */ pbuf = buf; while (sbuf = search(pbuf, r, argv[1], plen)) { /* * write characters from pbuf to sbuf -1 */ w = sbuf - pbuf; if (w) { fwrite(pbuf, 1, w, stdout); r -= w; } /* * write replacement string */ fwrite(argv[2], 1, rlen, stdout); /* * keep searching */ pbuf = sbuf + plen; r -= plen; } /* * Write out remaining chars in excess of plen */ if (r > plen) { fwrite(pbuf, 1, r - plen, stdout); pbuf += r - plen; w = plen; } else { w = r; } /* * Copy plen chars to beginning of buffer */ if (w) { strncpy(buf, pbuf, w); } if (feof(FIn)) break; r = fread(buf + w, 1, slen - w, FIn); if (r >= 0) { w += r; r = w; } } /* * Write out remaining chars in buffer */ if (w) { fwrite(buf, 1, w, stdout); } /* * Clean up */ free(buf); fflush(stdout); if (argc == 4) fclose(FIn); return 0; }