|
|
1.1 ! root 1: /* ! 2: * An editor. ! 3: * Regular expressions and the substitute and global commands. ! 4: */ ! 5: #include <stdio.h> ! 6: #include <ctype.h> ! 7: #include "ed.h" ! 8: ! 9: /* ! 10: * Global command. ! 11: */ ! 12: global(a1, a2, not) ! 13: { ! 14: register int a, c; ! 15: register char *gp; ! 16: ! 17: if (a1>a2 || a1<1 || a2>doladd) { ! 18: derror("Address out of range"); ! 19: return (0); ! 20: } ! 21: if (gcp != NULL) { ! 22: derror("Global inside global not allowed"); ! 23: return (0); ! 24: } ! 25: if ((c=getx()) == '\n') { ! 26: ungetx(c); ! 27: derror("Syntax error"); ! 28: return (0); ! 29: } ! 30: if (compile(c) == 0) ! 31: return; ! 32: gp = globbuf; ! 33: while ((c=getx()) != '\n') { ! 34: if (gp >= &globbuf[GBSIZE-3]) { ! 35: derror("Global buffer overflow"); ! 36: return (0); ! 37: } ! 38: if (c == '\\') ! 39: if ((c=getx())!='\n' && c!='\\') ! 40: *gp++ = '\\'; ! 41: *gp++ = c; ! 42: } ! 43: if (gp == globbuf) ! 44: goto out; ! 45: *gp++ = '\n'; ! 46: *gp = '\0'; ! 47: for (a=a1; a<=a2; a++) { ! 48: if (intflag) ! 49: goto out; ! 50: if (execute(a) != not) ! 51: line[a] |= 1; ! 52: } ! 53: a = 1; ! 54: while (a <= doladd) { ! 55: if (intflag) ! 56: goto out; ! 57: if ((line[a]&1) == 0) { ! 58: a++; ! 59: continue; ! 60: } ! 61: --line[a]; ! 62: dotadd = a; ! 63: gcp = globbuf; ! 64: while (*gcp != '\0') ! 65: if (command() == 0) ! 66: goto out; ! 67: a = 1; ! 68: } ! 69: out: ! 70: for (a=1; a<=doladd; a++) ! 71: line[a] &= ~1; ! 72: gcp = NULL; ! 73: ungetx('\n'); ! 74: return (1); ! 75: } ! 76: ! 77: /* ! 78: * Substitute part 1. ! 79: * Check that address range is legal and parse substitute command. ! 80: */ ! 81: subs1(a1, a2) ! 82: { ! 83: register int ec, c; ! 84: register char *sp; ! 85: ! 86: if (a1>a2 || a1<1 || a2>doladd) { ! 87: derror("Address out of range"); ! 88: return (0); ! 89: } ! 90: subnewl = 0; ! 91: subnths = 1; ! 92: if (isascii(c=getx()) && isdigit(c)) { ! 93: subnths = 0; ! 94: while (isascii(c) && isdigit(c)) { ! 95: subnths = subnths*10 + c-'0'; ! 96: c = getx(); ! 97: } ! 98: } ! 99: if ((ec=c) == '\n') { ! 100: ungetx(c); ! 101: derror("Syntax error"); ! 102: return (0); ! 103: } ! 104: if (compile(ec) == 0) ! 105: return (0); ! 106: sp = subsbuf; ! 107: while ((c=getx()) != ec) { ! 108: if (sp >= &subsbuf[SBSIZE-4]) { ! 109: derror("Temporary buffer overflow"); ! 110: return (0); ! 111: } ! 112: switch (c) { ! 113: case '\n': ! 114: ungetx(c); ! 115: derror("Syntax error"); ! 116: return (0); ! 117: case '&': ! 118: *sp++ = '\\'; ! 119: *sp++ = '0'; ! 120: continue; ! 121: case '\\': ! 122: if ((c=getx()) == '\\') { ! 123: *sp++ = '\\'; ! 124: *sp++ = '\\'; ! 125: continue; ! 126: } ! 127: if (c >= '1' && c <= '9') { ! 128: *sp++ = '\\'; ! 129: *sp++ = c; ! 130: continue; ! 131: } ! 132: if (c == '\n') ! 133: subnewl++; ! 134: default: ! 135: *sp++ = c; ! 136: continue; ! 137: } ! 138: } ! 139: *sp++ = '\0'; ! 140: if ((c=getx()) == 'g') ! 141: subnths = 0; ! 142: else ! 143: ungetx(c); ! 144: return (1); ! 145: } ! 146: ! 147: /* ! 148: * Substitute (part 2). ! 149: * Execute substitute command. ! 150: */ ! 151: subs2(a1, a2) ! 152: { ! 153: long seek, mark; ! 154: int len, nth, err, a; ! 155: char *mp, *sp; ! 156: register int n; ! 157: register char *lp, *rp; ! 158: ! 159: err = 1; ! 160: for (a=a1; a<=a2; a++) { ! 161: if (intflag) ! 162: return (1); ! 163: if (getline(a, tempbuf) == 0) ! 164: return (0); ! 165: for (n=0; n<1+BRSIZE; n++) { ! 166: brace[n].b_bp = NULL; ! 167: brace[n].b_ep = NULL; ! 168: } ! 169: brace[0].b_ep = tempbuf; ! 170: mp = tempbuf; ! 171: lp = linebuf; ! 172: nth = 0; ! 173: for (;;) { ! 174: rp = codebuf; ! 175: if (*rp == CSSOL) { ! 176: if (mp != tempbuf) ! 177: break; ! 178: rp++; ! 179: } ! 180: if ((rp=match(mp, rp)) == NULL) { ! 181: if (*mp++ == '\0') ! 182: break; ! 183: continue; ! 184: } ! 185: nth++; ! 186: if (subnths) { ! 187: if (nth < subnths) { ! 188: mp = rp; ! 189: continue; ! 190: } ! 191: if (nth > subnths) ! 192: goto done; ! 193: } ! 194: err = 0; ! 195: saved = 0; ! 196: dotadd = a; ! 197: brace[0].b_bp = mp; ! 198: mp = rp; ! 199: rp = brace[0].b_ep; ! 200: brace[0].b_ep = mp; ! 201: len = mp - brace[0].b_bp; ! 202: n = brace[0].b_bp - rp; ! 203: if (lp+n >= &linebuf[LBSIZE-1]) ! 204: goto ovf; ! 205: while (n--) ! 206: *lp++ = *rp++; ! 207: sp = subsbuf; ! 208: while (*sp) { ! 209: if (lp >= &linebuf[LBSIZE-4]) ! 210: goto ovf; ! 211: if (*sp != '\\') { ! 212: *lp++ = *sp++; ! 213: continue; ! 214: } ! 215: if (*++sp == '\\') { ! 216: *lp++ = *sp++; ! 217: continue; ! 218: } ! 219: n = *sp++ - '0'; ! 220: if ((rp=brace[n].b_bp) == NULL) ! 221: continue; ! 222: n = brace[n].b_ep-rp; ! 223: if (lp+n >= &linebuf[LBSIZE-4]) ! 224: goto ovf; ! 225: while (n--) ! 226: *lp++ = *rp++; ! 227: } ! 228: if (*mp == '\0') ! 229: break; ! 230: if (len == 0) ! 231: mp++; ! 232: if (subnths!=0 && nth==subnths) ! 233: break; ! 234: } ! 235: done: ! 236: if (dotadd != a) ! 237: continue; ! 238: rp = brace[0].b_ep; ! 239: while (*rp) { ! 240: if (lp >= &linebuf[LBSIZE-1]) ! 241: goto ovf; ! 242: *lp++ = *rp++; ! 243: } ! 244: *lp++ = '\0'; ! 245: seek = linead(); ! 246: if (subnewl) { ! 247: lp = linebuf; ! 248: while (*lp != '\n') ! 249: lp++; ! 250: *lp++ = '\0'; ! 251: } ! 252: if (putline(linebuf, lp-linebuf) == 0) ! 253: return (0); ! 254: suborig = line[a]; ! 255: if (suborig&1) ! 256: --suborig; ! 257: subseek = seek|1; ! 258: line[a] = seek; ! 259: mark = suborig|1; ! 260: for (n=0; n<MKSIZE; n++) ! 261: if (marklin[n] == mark) ! 262: marklin[n] = subseek; ! 263: if (subnewl != 0) { ! 264: n = 1; ! 265: do { ! 266: mp = lp; ! 267: while (*lp!='\n' && *lp!='\0') ! 268: lp++; ! 269: if (*lp == '\0') ! 270: n = 0; ! 271: *lp++ = '\0'; ! 272: seek = linead(); ! 273: if (putline(mp, lp-mp) == 0) ! 274: return (0); ! 275: if (expand(a) == 0) ! 276: return (0); ! 277: line[++a] = seek; ! 278: dotadd = a; ! 279: a2++; ! 280: } while (n); ! 281: } ! 282: } ! 283: if (err!=0 && gcp==NULL) { ! 284: derror("Pattern not matched"); ! 285: return (0); ! 286: } ! 287: return (1); ! 288: ! 289: ovf: ! 290: derror("Temporary buffer overflow"); ! 291: return (0); ! 292: } ! 293: ! 294: /* ! 295: * Compile a regular expression. `ec' is the character upon which ! 296: * the regular expression ends. If an error is encountered, the ! 297: * pattern is restored and input characters are thrown away until ! 298: * a new line is found. ! 299: */ ! 300: compile(ec) ! 301: { ! 302: int bstack[BRSIZE], bcount, blevel, n; ! 303: register int c; ! 304: register char *cp, *lcp; ! 305: ! 306: bcopy(tempbuf, codebuf); ! 307: bcount = 1; ! 308: blevel = 0; ! 309: cp = &codebuf[0]; ! 310: if ((c=getx()) == ec) { ! 311: if (*cp == CSNUL) { ! 312: derror("No saved pattern"); ! 313: goto err; ! 314: } ! 315: return (1); ! 316: } ! 317: if (c == '^') { ! 318: *cp++ = CSSOL; ! 319: c = getx(); ! 320: } ! 321: while (c != ec) { ! 322: if (c == '\n') { ! 323: goto nwl; ! 324: } ! 325: if (cp > &codebuf[CBSIZE-4]) ! 326: goto ovf; ! 327: switch (c) { ! 328: case '*': ! 329: goto syn; ! 330: case '.': ! 331: if ((c=getx()) != '*') { ! 332: *cp++ = CSDOT; ! 333: continue; ! 334: } ! 335: *cp++ = CMDOT; ! 336: c = getx(); ! 337: continue; ! 338: case '$': ! 339: if ((c=getx()) != ec) { ! 340: ungetx(c); ! 341: c = '$'; ! 342: goto character; ! 343: } ! 344: *cp++ = CSEOL; ! 345: continue; ! 346: case '[': ! 347: lcp = cp; ! 348: if ((c=getx()) == '^') ! 349: *cp++ = CSNCL; ! 350: else { ! 351: ungetx(c); ! 352: *cp++ = CSCCL; ! 353: } ! 354: *cp++ = 0; ! 355: if ((c=getx()) == ']') ! 356: *cp++ = c; ! 357: else ! 358: ungetx(c); ! 359: while ((c=getx()) != ']') { ! 360: if (c == '\n') ! 361: goto nwl; ! 362: if (c!='-' || cp==lcp+2) { ! 363: if (cp >= &codebuf[CBSIZE-4]) ! 364: goto ovf; ! 365: *cp++ = c; ! 366: if (sflag && isascii(c) && isallet(c)) ! 367: *cp++ = toother(c); ! 368: continue; ! 369: } ! 370: if ((c=getx()) == '\n') ! 371: goto nwl; ! 372: if (c == ']') { ! 373: *cp++ = '-'; ! 374: ungetx(c); ! 375: continue; ! 376: } ! 377: if ((n=cp[-1]) > c) ! 378: goto syn; ! 379: while (++n <= c) { ! 380: if (cp >= &codebuf[CBSIZE-4]) ! 381: goto ovf; ! 382: *cp++ = n; ! 383: if (sflag && isascii(c) && isallet(c)) ! 384: *cp++ = toother(c); ! 385: } ! 386: } ! 387: if ((c=getx()) == '*') { ! 388: (*lcp)++; ! 389: c = getx(); ! 390: } ! 391: if ((n=cp-(lcp+2)) > 255) { ! 392: derror("Character class too large"); ! 393: goto err; ! 394: } ! 395: *++lcp = n; ! 396: continue; ! 397: case '\\': ! 398: switch (c=getx()) { ! 399: case '\n': ! 400: goto nwl; ! 401: case '(': ! 402: if (bcount > BRSIZE) { ! 403: derror("Too many \\("); ! 404: goto err; ! 405: } ! 406: *cp++ = CSOPR; ! 407: *cp++ = bstack[blevel++] = bcount++; ! 408: c = getx(); ! 409: continue; ! 410: case ')': ! 411: if (blevel == 0) ! 412: goto syn; ! 413: *cp++ = CSCPR; ! 414: *cp++ = bstack[--blevel]; ! 415: c = getx(); ! 416: continue; ! 417: default: ! 418: if (isascii(c) && isdigit(c)) { ! 419: *cp++ = CSBRN; ! 420: *cp++ = c-'0'; ! 421: c = getx(); ! 422: continue; ! 423: } ! 424: } ! 425: default: ! 426: character: ! 427: if (sflag && isascii(c) && isallet(c)) { ! 428: *cp++ = CSSCC; ! 429: if (isupper(c)) ! 430: c = tolower(c); ! 431: } else ! 432: *cp++ = CSCHR; ! 433: *cp++ = c; ! 434: if ((c=getx()) == '*') { ! 435: cp[-2]++; ! 436: c = getx(); ! 437: } ! 438: } ! 439: } ! 440: *cp++ = CSNUL; ! 441: return (1); ! 442: ovf: ! 443: derror("Code buffer overflow"); ! 444: bcopy(codebuf, tempbuf); ! 445: return (0); ! 446: nwl: ! 447: ungetx(c); ! 448: syn: ! 449: derror("Syntax error"); ! 450: err: ! 451: bcopy(codebuf, tempbuf); ! 452: return (0); ! 453: } ! 454: ! 455: /* ! 456: * Copy BSIZE buffer into dest from source ! 457: */ ! 458: bcopy(dest, source) ! 459: register char *dest; ! 460: register char *source; ! 461: { ! 462: register int n; ! 463: ! 464: n = CBSIZE; ! 465: do ! 466: *dest++ = *source++; ! 467: while (--n > 0); ! 468: } ! 469: ! 470: /* ! 471: * Return 1 if the compiled expression in `codebuf' matches the line in ! 472: * `linebuf', else 0. ! 473: */ ! 474: execute(a) ! 475: { ! 476: register int i; ! 477: register char *lp, *ep; ! 478: ! 479: if (getline(a, linebuf) == 0) ! 480: return (0); ! 481: for (i=0; i<1+BRSIZE; i++) { ! 482: brace[i].b_bp = NULL; ! 483: brace[i].b_ep = NULL; ! 484: } ! 485: if (codebuf[0] == CSSOL) ! 486: ep = match(lp=linebuf, &codebuf[1]); ! 487: else { ! 488: ep = NULL; ! 489: lp = linebuf; ! 490: do { ! 491: if (ep=match(lp, codebuf)) ! 492: break; ! 493: } while (*lp++); ! 494: } ! 495: if (ep) { ! 496: brace[0].b_bp = lp; ! 497: brace[0].b_ep = ep; ! 498: } ! 499: return (ep ? 1 : 0); ! 500: } ! 501: ! 502: /* ! 503: * Given a pointer to a compiled expression, `cp', and a pointer to ! 504: * a line, `lp', return 1 if the expression matches, else 0. ! 505: */ ! 506: char * ! 507: match(lp, cp) ! 508: register char *lp, *cp; ! 509: { ! 510: register int n; ! 511: char *llp, *lcp; ! 512: ! 513: for (;;) { ! 514: switch (*cp++) { ! 515: case CSNUL: ! 516: return (lp); ! 517: case CSEOL: ! 518: if (*lp) ! 519: return (NULL); ! 520: return (lp); ! 521: case CSOPR: ! 522: brace[*cp++].b_bp = lp; ! 523: continue; ! 524: case CSCPR: ! 525: brace[*cp++].b_ep = lp; ! 526: continue; ! 527: case CSBRN: ! 528: n = *cp++; ! 529: lcp = cp; ! 530: cp = brace[n].b_bp; ! 531: n = brace[n].b_ep - cp; ! 532: if (n > LBSIZE) ! 533: return (NULL); ! 534: while (n-- > 0) ! 535: if (*lp++ != *cp++) ! 536: return (NULL); ! 537: cp = lcp; ! 538: continue; ! 539: case CSDOT: ! 540: if (*lp++ == '\0') ! 541: return (NULL); ! 542: continue; ! 543: case CMDOT: ! 544: llp = lp; ! 545: while (*lp) ! 546: lp++; ! 547: goto star; ! 548: case CSCHR: ! 549: if (*cp++ != *lp++) ! 550: return (NULL); ! 551: continue; ! 552: case CMCHR: ! 553: llp = lp; ! 554: while (*cp == *lp) ! 555: lp++; ! 556: cp++; ! 557: goto star; ! 558: case CSSCC: ! 559: if (*cp++ == tolower(*lp++)) ! 560: continue; ! 561: return (NULL); ! 562: case CMSCC: ! 563: llp = lp; ! 564: while (*cp == tolower(*lp++)) ! 565: ; ! 566: cp++; ! 567: goto star; ! 568: case CSCCL: ! 569: n = *cp++; ! 570: while (*cp++ != *lp) ! 571: if (--n == 0) ! 572: return (NULL); ! 573: lp++; ! 574: cp += n-1; ! 575: continue; ! 576: case CMCCL: ! 577: llp = lp; ! 578: lcp = cp; ! 579: while (*lp) { ! 580: cp = lcp; ! 581: n = *cp++; ! 582: while (*cp++ != *lp) ! 583: if (--n == 0) ! 584: goto star; ! 585: lp++; ! 586: } ! 587: cp = lcp + *lcp + 1; ! 588: goto star; ! 589: case CSNCL: ! 590: if (*lp == '\0') ! 591: return (NULL); ! 592: n = *cp++; ! 593: while (n--) ! 594: if (*cp++ == *lp) ! 595: return (NULL); ! 596: lp++; ! 597: continue; ! 598: case CMNCL: ! 599: llp = lp; ! 600: lcp = cp; ! 601: while (*lp) { ! 602: cp = lcp; ! 603: n = *cp++; ! 604: while (n--) { ! 605: if (*cp++ == *lp) { ! 606: cp = lcp + *lcp + 1; ! 607: goto star; ! 608: } ! 609: } ! 610: lp++; ! 611: } ! 612: cp = lcp + *lcp + 1; ! 613: star: ! 614: do { ! 615: if (lcp=match(lp, cp)) ! 616: return (lcp); ! 617: } while (--lp >= llp); ! 618: return (NULL); ! 619: } ! 620: } ! 621: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.