/* gres - grep and substitute Author: Martin C. Atkins */ /* * globally search, and replace * *<-xtx-*>cc -o gres gres.c -lregexp */ /* * This program was written by: * Martin C. Atkins, * University of York, * Heslington, * York. Y01 5DD * England * and is released into the public domain, on the condition * that this comment is always included without alteration. */ #include "stdio.h" #include "regexp.h" #define MAXLINE (1024) int status = 1; char *usagemsg = "Usage: gres [-g] search replace [file ...]\n"; char *progname; int gflag = 0; /* != 0 => only do first substitution on line */ extern char *index(); FILE *fopen(); main(argc,argv) int argc; char *argv[]; { regexp *exp; char *repstr; char **argp = &argv[1]; progname = argv[0]; if(*argp != 0 && argp[0][0] == '-' && argp[0][1] == 'g') { gflag = 1; argp++,argc--; } if(argc < 3) { std_err(usagemsg); done(2); } if(argp[0][0] == '\0') { std_err("gres: null match string is silly\n"); done(2); } if((exp = regcomp(*argp++)) == NULL) { std_err("gres: regcomp failed\n"); done(2); } repstr = *argp++; if(*argp == 0) process(stdin,exp,repstr); else while(*argp) { FILE *inf; if(strcmp(*argp,"-") == 0) process(stdin,exp,repstr); else { if((inf = fopen(*argp,"r")) == NULL) { std_err("gres: Can't open "); std_err(*argp); std_err("\n"); status = 2; } else { process(inf,exp,repstr); fclose(inf); } } argp++; } done(status); } /* * This routine does the processing */ process(inf, exp, repstr) FILE *inf; regexp *exp; char *repstr; { char ibuf[MAXLINE]; while(fgets(ibuf,MAXLINE,inf) != NULL) { char *cr = index(ibuf,'\n'); if(cr == 0) std_err("gres: Line broken\n"); else *cr = '\0'; if(regexec(exp,ibuf,1)) { pline(exp,ibuf,repstr); if(status != 2) status = 0; } else printf("%s\n",ibuf); } } void regerror(s) char *s; { std_err("gres: "); std_err(s); std_err("\n"); done(2); } char * getbuf(exp, repstr) regexp *exp; char *repstr; { char *malloc(); void free(); static bufsize = 0; static char *buf = 0; int guess = 10; int ch; while(*repstr) { switch(*repstr) { case '&': guess += exp->endp[0] - exp->startp[0]; break; case '\\': if((ch = *++repstr) < '0' || ch > '9') guess += 2; else { ch -= '0'; guess += exp->endp[ch] - exp->startp[ch]; } break; default: guess++; } repstr++; } if(bufsize < guess) { if(buf != 0) free((char *)buf); buf = malloc(guess); } return buf; } pline(exp, ibuf, repstr) regexp *exp; char ibuf[]; char *repstr; { do { dosub(exp,ibuf,repstr); ibuf = exp->endp[0]; if(*ibuf == '\0') break; if(ibuf == exp->startp[0]) putchar(*ibuf++); } while(!gflag && regexec(exp,ibuf,0)); printf("%s\n",ibuf); } /* * print one subsitution */ dosub(exp,ibuf,repstr) regexp *exp; char ibuf[]; char *repstr; { char *buf = getbuf(exp, repstr); char *end = exp->startp[0]; int ch = *end; *end = '\0'; fputs(ibuf,stdout); /* output the initial part of line */ *end = ch; regsub(exp, repstr, buf); fputs(buf,stdout); } done(n) int n; { _cleanup(); /* flush stdio's internal buffers */ exit(n); }