From moraes@deshaw.com Fri Apr 16 18:55:26 1993 Received: from Larry.McRCIM.McGill.EDU by Lightning.McRCIM.McGill.EDU (5.65) with SMTP id <9304162255.AA28218@Lightning.McRCIM.McGill.EDU>; Fri, 16 Apr 93 18:55:24 -0400 Received: from master.deshaw.com by Larry.McRCIM.McGill.EDU (5.61) with SMTP id <9304162255.AA10468@Larry.McRCIM.McGill.EDU>; Fri, 16 Apr 93 18:55:21 -0400 Received: from cs2.deshaw.com by master.deshaw.com with SMTP id AA12439 (5.65c/IDA-1.4.4 for ); Fri, 16 Apr 1993 18:55:17 -0400 Message-Id: <199304162255.AA12439@master.deshaw.com> To: mouse@larry.mcrcim.mcgill.edu Subject: an enhancement to qsubst Date: Fri, 16 Apr 93 18:55:16 -0400 From: Mark Moraes Status: R Hi Mike (or do you prefer Mouse? I can never remember, sorry) Here's a small enhancement to qsubst -- what I call "case-sensible" replacement. This may be an old version of qsubst -- I remember you saying that it hadn't changed when I sent you diffs for SGIs (and SysV termio support) a couple of years back. If you want, I'll send you the entire thing, or, if you have a new improved qsubst, I'll hack these changes into it (unless you've already done this) How's life treating you these days? Regards, Mark. *** /tmp/T0a19143 Fri Apr 16 18:47:21 1993 --- qsubst.1 Fri Apr 16 18:46:25 1993 *************** *** 64,69 **** --- 64,76 ---- Negate a \-go or \-noask option. \fIQsubst\fP will once more prompt the user as usual. .TP + \-case + Do a case-insensitive replacement. \fIQsubst\fP will find and replace + instances of the first string in any case with the second string -- the + replacement is done "intuitively" -- the second string is mapped to the case + of the first string (if the second string is longer than the first string, + then the characters in the longer part retain their case). + .TP \-CA\fIN\fP Give \fIN\fP lines of context above the line with the match when prompting the user. *** /tmp/T0a19143 Fri Apr 16 18:47:22 1993 --- qsubst.c Fri Apr 16 18:42:55 1993 *************** *** 120,125 **** --- 120,132 ---- char tcp_buf[1024]; char cap_buf[1024]; + extern char *nochange(); + extern int casecmp(), bcmp(); + extern char *changecase(); + + char *(*casifyfunc)() = nochange; + int (*comparefunc)() = bcmp; + #ifdef sgi /* kludge till Irix3.3 */ # define sigblock(x) 0 *************** *** 126,131 **** --- 133,147 ---- # define sigsetmask(x) 0 #endif + /* ARGSUSED src srclen dstlen */ + char * + nochange(src, srclen, dst, dstlen) + char *src, *dst; + int srclen, dstlen; + { + return dst; + } + tstp_self() { int (*old_tstp)(); *************** *** 238,243 **** --- 254,263 ---- (strcmp(*av,"ask") == 0) ) { allfly = 0; } + else if (strcmp(*av,"case") == 0) + { casifyfunc = changecase; + comparefunc = casecmp; + } else if (**av == 'c') { cabove = atoi(++*av); cbelow = cabove; *************** *** 353,364 **** return; } } ! if ((bcmp(buf,str1,s1l) == 0) && doit()) { if (tbeg < 0) { tbeg = ftell(workf) - s1l; fseek(tempf,0L,0); } ! fwrite(str2,1,s2l,tempf); n = 0; } else --- 373,384 ---- return; } } ! if (((*comparefunc)(buf,str1,s1l) == 0) && doit(buf)) { if (tbeg < 0) { tbeg = ftell(workf) - s1l; fseek(tempf,0L,0); } ! fwrite((*casifyfunc)(buf,s1l,str2,s2l),1,s2l,tempf); n = 0; } else *************** *** 395,401 **** return(c); } ! int doit() { long int save; int i; --- 415,422 ---- return(c); } ! int doit(buf) ! char *buf; { long int save; int i; *************** *** 414,420 **** for (i=save-nls[i]-s1l;i;i--) { putchar(getc(workf)); } ! put_ul(use_replacement?str2:str1); fseek(workf,save,0); i = cbelow + 1; while (i > 0) --- 435,441 ---- for (i=save-nls[i]-s1l;i;i--) { putchar(getc(workf)); } ! put_ul(use_replacement?(*casifyfunc)(buf,s1l,str2,s2l):(*casifyfunc)(buf,s1l,str1,s1l)); fseek(workf,save,0); i = cbelow + 1; while (i > 0) *** /dev/null Fri Apr 16 18:03:01 1993 --- case.c Fri Apr 16 18:41:39 1993 *************** *** 0 **** --- 1,82 ---- + #include + #include + #include + + /* + * compares (case-insensitively) two counted byte arrays sa and sb, both + * assumed to be of length len + */ + int + casecmp(sa, sb, len) + register char *sa, *sb; + register int len; + { + register char ca, cb; + + while (len-- > 0) { + ca = *sa++; + cb = *sb++; + if (ca == cb) + continue; + if (isascii(ca) && isascii(cb)) { + if (isupper(ca) && islower(cb) && tolower(ca) == cb) + continue; + if (isupper(cb) && islower(ca) && tolower(cb) == ca) + continue; + } + return ca - cb; + } + } + + /* + * converts counted byte array dst to have the same case as src. Both dst and + * src are assumed to be of length len. + */ + char * + changecase(src, srclen, dst, dstlen) + char *src, *dst; + int srclen, dstlen; + { + static char *buf; + register char *cp; + register int i; + register int len = (dstlen < srclen) ? dstlen : srclen; + static int buflen; + + if (buf == NULL || buflen < dstlen) { + buflen = dstlen + 1; + buf = buf ? realloc(buf, buflen) : malloc(buflen); + if (buf == NULL) { + fprintf(stderr, "realloc to %d failed\n", dstlen); + exit(2); + } + } + bcopy(dst, buf, dstlen); + for (i = 0; i < len; i++) { + char cs = src[i], cd = buf[i];; + if (!isascii(cd) || !isascii(cs)) + continue; + if (isupper(cs) && islower(cd)) + buf[i] = toupper(cd); + else if (islower(cs) && isupper(cd)) + buf[i] = tolower(cd); + } + for (i = len; i < dstlen; i++) + buf[i] = dst[i]; + buf[dstlen] = '\0'; /* NUL terminate it for luck! */ + return buf; + } + + #ifdef TEST + int + main() + { + char a[1024], b[1024]; + + while (scanf(" %s %s", a, b) == 2) { + printf("changecase %s %s = %s\n", a, b, changecase(a, strlen(a), b, strlen(b))); + /* printf("casecmp %s %s = %d\n", a, b, casecmp(a, b, strlen(a)));*/ + } + return 0; + } + #endif