home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Distributions / ucb / spencer_2bsd.tar.gz / 2bsd.tar / src / ex / ex_re.c < prev    next >
C/C++ Source or Header  |  1980-02-17  |  14KB  |  846 lines

  1. /* Copyright (c) 1979 Regents of the University of California */
  2. #include "ex.h"
  3. #include "ex_re.h"
  4.  
  5. /*
  6.  * Global, substitute and regular expressions.
  7.  * Very similar to ed, with some re extensions and
  8.  * confirmed substitute.
  9.  */
  10. global(k)
  11.     bool k;
  12. {
  13.     register char *gp;
  14.     register int c;
  15.     register line *a1;
  16.     char globuf[GBSIZE], *Cwas;
  17.     int lines = lineDOL();
  18.     char *oglobp = globp;
  19.  
  20.     Cwas = Command;
  21.     if (inglobal)
  22.         error("Global within global@not allowed");
  23.     markDOT();
  24.     setall();
  25.     nonzero();
  26.     if (skipend())
  27.         error("Global needs re|Missing regular expression for global");
  28.     c = getchar();
  29.     ignore(compile(c, 0));
  30.     savere(scanre);
  31.     gp = globuf;
  32.     while ((c = getchar()) != '\n') {
  33.         switch (c) {
  34.  
  35.         case EOF:
  36.             c = '\n';
  37.             goto brkwh;
  38.  
  39.         case '\\':
  40.             c = getchar();
  41.             switch (c) {
  42.  
  43.             case '\\':
  44.                 ungetchar(c);
  45.                 break;
  46.  
  47.             case '\n':
  48.                 break;
  49.  
  50.             default:
  51.                 *gp++ = '\\';
  52.                 break;
  53.             }
  54.             break;
  55.         }
  56.         *gp++ = c;
  57.         if (gp >= &globuf[GBSIZE - 2])
  58.             error("Global command too long");
  59.     }
  60. brkwh:
  61.     ungetchar(c);
  62. out:
  63.     newline();
  64.     *gp++ = c;
  65.     *gp++ = 0;
  66.     inglobal = 1;
  67.     for (a1 = one; a1 <= dol; a1++) {
  68.         *a1 &= ~01;
  69.         if (a1 >= addr1 && a1 <= addr2 && execute(0, a1) == k)
  70.             *a1 |= 01;
  71.     }
  72.     /* should use gdelete from ed to avoid n**2 here on g/.../d */
  73.     saveall();
  74.     if (inopen)
  75.         inopen = -1;
  76.     for (a1 = one; a1 <= dol; a1++) {
  77.         if (*a1 & 01) {
  78.             *a1 &= ~01;
  79.             dot = a1;
  80.             globp = globuf;
  81.             commands(1, 1);
  82.             a1 = zero;
  83.         }
  84.     }
  85.     globp = oglobp;
  86.     inglobal = 0;
  87.     endline = 1;
  88.     Command = Cwas;
  89.     netchHAD(lines);
  90.     setlastchar(EOF);
  91.     if (inopen) {
  92.         ungetchar(EOF);
  93.         inopen = 1;
  94.     }
  95. }
  96.  
  97. bool    xflag;
  98. int    scount, slines, stotal;
  99.  
  100. substitute(c)
  101.     int c;
  102. {
  103.     register line *addr;
  104.     register int n;
  105.     int gsubf;
  106.  
  107.     gsubf = compsub(c);
  108.     if (!inglobal)
  109.         save12(), undkind = UNDCHANGE;
  110.     stotal = 0;
  111.     slines = 0;
  112.     for (addr = addr1; addr <= addr2; addr++) {
  113.         scount = 0;
  114.         if (dosubcon(0, addr) == 0)
  115.             continue;
  116.         if (gsubf)
  117.             while (*loc2)
  118.                 if (dosubcon(1, addr) == 0)
  119.                     break;
  120.         if (scount) {
  121.             stotal += scount;
  122.             slines++;
  123.             putmark(addr);
  124.             n = append(getsub, addr);
  125.             addr += n;
  126.             addr2 += n;
  127.         }
  128.     }
  129.     if (stotal == 0 && !inglobal && !xflag)
  130.         error("Fail|Substitute pattern match failed");
  131.     snote(stotal, slines);
  132.     return (stotal);
  133. }
  134.  
  135. compsub(ch)
  136. {
  137.     register int seof, c;
  138.     int gsubf;
  139.  
  140.     gsubf = 0;
  141.     xflag = 0;
  142.     switch (ch) {
  143.  
  144.     case 's':
  145.         ignore(skipwh());
  146.         seof = getchar();
  147.         if (endcmd(seof))
  148.             error("Substitute needs re|Missing regular expression for substitute");
  149.         seof = compile(seof, 1);
  150.         savere(subre);
  151.         comprhs(seof);
  152.         break;
  153.  
  154.     case '&':
  155.         if (subre.Expbuf[0] == 0)
  156.             error("No previous substitute re|No previous substitute to repeat");
  157.         resre(subre);
  158.         break;
  159.  
  160.     case '~':
  161.         if (re.Expbuf[0] == 0)
  162.             error("No previous re|No previous regular expression");
  163.         savere(subre);
  164.         break;
  165.     }
  166.     for (;;) {
  167.         c = getchar();
  168.         switch (c) {
  169.  
  170.         case 'g':
  171.             gsubf++;
  172.             continue;
  173.  
  174.         case 'c':
  175.             xflag++;
  176.             continue;
  177.  
  178.         default:
  179.             ungetchar(c);
  180.             setcount();
  181.             newline();
  182.             return (gsubf);
  183.         }
  184.     }
  185. }
  186.  
  187. comprhs(seof)
  188.     int seof;
  189. {
  190.     register char *rp, *orp;
  191.     register int c;
  192.     char orhsbuf[LBSIZE / 2];
  193.  
  194.     rp = rhsbuf;
  195.     CP(orhsbuf, rp);
  196.     for (;;) {
  197.         c = getchar();
  198.         if (c == seof)
  199.             break;
  200.         switch (c) {
  201.  
  202.         case '\\':
  203.             c = getchar();
  204.             if (c == EOF) {
  205.                 ungetchar(c);
  206.                 break;
  207.             }
  208.             if (value(MAGIC)) {
  209.                 /*
  210.                  * When "magic", \& turns into a plain &,
  211.                  * and all other chars work fine quoted.
  212.                  */
  213.                 if (c != '&')
  214.                     c |= QUOTE;
  215.                 break;
  216.             }
  217. magic:
  218.             if (c == '~') {
  219.                 for (orp = orhsbuf; *orp; *rp++ = *orp++)
  220.                     if (rp >= &rhsbuf[LBSIZE / 2 + 1])
  221.                         goto toobig;
  222.                 continue;
  223.             }
  224.             c |= QUOTE;
  225.             break;
  226.  
  227.         case '\n':
  228.         case EOF:
  229.             ungetchar(c);
  230.             goto endrhs;
  231.  
  232.         case '~':
  233.         case '&':
  234.             if (value(MAGIC))
  235.                 goto magic;
  236.             break;
  237.         }
  238.         if (rp >= &rhsbuf[LBSIZE / 2 - 1])
  239. toobig:
  240.             error("Replacement pattern too long@- limit 256 characters");
  241.         *rp++ = c;
  242.     }
  243. endrhs:
  244.     *rp++ = 0;
  245. }
  246.  
  247. getsub()
  248. {
  249.     register char *p;
  250.  
  251.     if ((p = linebp) == 0)
  252.         return (EOF);
  253.     strcLIN(p);
  254.     linebp = 0;
  255.     return (0);
  256. }
  257.  
  258. dosubcon(f, a)
  259.     bool f;
  260.     line *a;
  261. {
  262.  
  263.     if (execute(f, a) == 0)
  264.         return (0);
  265.     if (confirmed(a)) {
  266.         dosub();
  267.         scount++;
  268.     }
  269.     return (1);
  270. }
  271.  
  272. confirmed(a)
  273.     line *a;
  274. {
  275.     register int c, ch;
  276.  
  277.     if (xflag == 0)
  278.         return (1);
  279.     pofix();
  280.     pline(lineno(a));
  281.     if (inopen)
  282.         putchar('\n' | QUOTE);
  283.     c = column(loc1 - 1);
  284.     ugo(c - 1 + (inopen ? 1 : 0), ' ');
  285.     ugo(column(loc2 - 1) - c, '^');
  286.     flush();
  287.     ch = c = getkey();
  288. again:
  289.     if (c == '\r')
  290.         c = '\n';
  291.     if (inopen)
  292.         putchar(c), flush();
  293.     if (c != '\n' && c != EOF) {
  294.         c = getkey();
  295.         goto again;
  296.     }
  297.     noteinp();
  298.     return (ch == 'y');
  299. }
  300.  
  301. getch()
  302. {
  303.     char c;
  304.  
  305.     if (read(2, &c, 1) != 1)
  306.         return (EOF);
  307.     return (c & TRIM);
  308. }
  309.  
  310. ugo(cnt, with)
  311.     int with;
  312.     int cnt;
  313. {
  314.  
  315.     if (cnt > 0)
  316.         do
  317.             putchar(with);
  318.         while (--cnt > 0);
  319. }
  320.  
  321. int    casecnt;
  322. bool    destuc;
  323.  
  324. dosub()
  325. {
  326.     register char *lp, *sp, *rp;
  327.     int c;
  328.  
  329.     lp = linebuf;
  330.     sp = genbuf;
  331.     rp = rhsbuf;
  332.     while (lp < loc1)
  333.         *sp++ = *lp++;
  334.     casecnt = 0;
  335.     while (c = *rp++) {
  336.         if (c & QUOTE)
  337.             switch (c & TRIM) {
  338.  
  339.             case '&':
  340.                 sp = place(sp, loc1, loc2);
  341.                 if (sp == 0)
  342.                     goto ovflo;
  343.                 continue;
  344.  
  345.             case 'l':
  346.                 casecnt = 1;
  347.                 destuc = 0;
  348.                 continue;
  349.  
  350.             case 'L':
  351.                 casecnt = LBSIZE;
  352.                 destuc = 0;
  353.                 continue;
  354.  
  355.             case 'u':
  356.                 casecnt = 1;
  357.                 destuc = 1;
  358.                 continue;
  359.  
  360.             case 'U':
  361.                 casecnt = LBSIZE;
  362.                 destuc = 1;
  363.                 continue;
  364.  
  365.             case 'E':
  366.             case 'e':
  367.                 casecnt = 0;
  368.                 continue;
  369.             }
  370.         if (c < 0 && (c &= TRIM) >= '1' && c < nbra + '1') {
  371.             sp = place(sp, braslist[c - '1'], braelist[c - '1']);
  372.             if (sp == 0)
  373.                 goto ovflo;
  374.             continue;
  375.         }
  376.         if (casecnt)
  377.             *sp++ = fixcase(c & TRIM);
  378.         else
  379.             *sp++ = c & TRIM;
  380.         if (sp >= &genbuf[LBSIZE])
  381. ovflo:
  382.             error("Line overflow@in substitute - limit 512 chars");
  383.     }
  384.     lp = loc2;
  385.     loc2 = sp + (linebuf - genbuf) + (loc1 == loc2);
  386.     while (*sp++ = *lp++)
  387.         if (sp >= &genbuf[LBSIZE])
  388.             goto ovflo;
  389.     strcLIN(genbuf);
  390. }
  391.  
  392. fixcase(c)
  393.     register int c;
  394. {
  395.  
  396.     if (casecnt == 0)
  397.         return (c);
  398.     casecnt--;
  399.     if (destuc) {
  400.         if (islower(c))
  401.             c = toupper(c);
  402.     } else
  403.         if (isupper(c))
  404.             c = tolower(c);
  405.     return (c);
  406. }
  407.  
  408. char *
  409. place(sp, l1, l2)
  410.     register char *sp, *l1, *l2;
  411. {
  412.  
  413.     while (l1 < l2) {
  414.         *sp++ = fixcase(*l1++);
  415.         if (sp >= &genbuf[LBSIZE])
  416.             return (0);
  417.     }
  418.     return (sp);
  419. }
  420.  
  421. snote(total, lines)
  422.     register int total, lines;
  423. {
  424.  
  425.     if (!notable(total))
  426.         return;
  427.     printf(mesg("%d subs|%d substitutions"), total);
  428.     if (lines != 1 && lines != total)
  429.         printf(" on %d lines", lines);
  430.     noonl();
  431.     flush();
  432. }
  433.  
  434. compile(eof, oknl)
  435.     int eof;
  436.     int oknl;
  437. {
  438.     register int c;
  439.     register char *ep;
  440.     char *lastep;
  441.     char bracket[NBRA], *bracketp, *rhsp;
  442.     int cclcnt;
  443.  
  444.     if (isalpha(eof) || isdigit(eof))
  445.         error("Re delimiter must not be letter or digit|Regular expressions cannot be delimited by letters or digits");
  446.     ep = expbuf;
  447.     c = getchar();
  448.     if (eof == '\\')
  449.         switch (c) {
  450.  
  451.         case '/':
  452.         case '?':
  453.             if (scanre.Expbuf[0] == 0)
  454.                 error("No previous scan re|No previous scanning regular expression");
  455.             resre(scanre);
  456.             return (c);
  457.  
  458.         case '&':
  459.             if (subre.Expbuf[0] == 0)
  460.                 error("No previous substitute re|No previous substitute regular expression");
  461.             resre(subre);
  462.             return (c);
  463.  
  464.         default:
  465.             error("Badly formed re|Regular expression \ must be followed by / or ?");
  466.         }
  467.     if (c == eof || c == '\n' || c == EOF) {
  468.         if (*ep == 0)
  469.             error("No previous re|No previous regular expression");
  470.         if (c == '\n' && oknl == 0)
  471.             error("Missing closing delimiter@for regular expression");
  472.         if (c != eof)
  473.             ungetchar(c);
  474.         return (eof);
  475.     }
  476.     bracketp = bracket;
  477.     nbra = 0;
  478.     circfl = 0;
  479.     if (c == '^') {
  480.         c = getchar();
  481.         circfl++;
  482.     }
  483.     ungetchar(c);
  484.     for (;;) {
  485.         if (ep >= &expbuf[ESIZE - 2])
  486. complex:
  487.             cerror("Re too complex|Regular expression too complicated");
  488.         c = getchar();
  489.         if (c == eof || c == EOF) {
  490.             if (bracketp != bracket)
  491.                 cerror("Unmatched \\(|More \\('s than \\)'s in regular expression");
  492.             *ep++ = CEOF;
  493.             if (c == EOF)
  494.                 ungetchar(c);
  495.             return (eof);
  496.         }
  497.         if (value(MAGIC)) {
  498.             if (c != '*' || ep == expbuf)
  499.                 lastep = ep;
  500.         } else
  501.             if (c != '\\' || peekchar() != '*' || ep == expbuf)
  502.                 lastep = ep;
  503.         switch (c) {
  504.  
  505.         case '\\':
  506.             if (!intag)
  507.                 c = getchar();
  508.             switch (c) {
  509.  
  510.             case '(':
  511.                 if (nbra >= NBRA)
  512.                     cerror("Awash in \\('s!|Too many \\('d subexressions in a regular expression");
  513.                 *bracketp++ = nbra;
  514.                 *ep++ = CBRA;
  515.                 *ep++ = nbra++;
  516.                 continue;
  517.  
  518.             case ')':
  519.                 if (bracketp <= bracket)
  520.                     cerror("Extra \\)|More \\)'s than \\('s in regular expression");
  521.                 *ep++ = CKET;
  522.                 *ep++ = *--bracketp;
  523.                 continue;
  524.  
  525.             case '<':
  526.                 *ep++ = CBRC;
  527.                 continue;
  528.  
  529.             case '>':
  530.                 *ep++ = CLET;
  531.                 continue;
  532.             }
  533.             if (value(MAGIC) == 0 && !intag)
  534. magic:
  535.             switch (c) {
  536.  
  537.             case '.':
  538.                 *ep++ = CDOT;
  539.                 continue;
  540.  
  541.             case '~':
  542.                 rhsp = rhsbuf;
  543.                 while (*rhsp) {
  544.                     if (*rhsp & QUOTE) {
  545.                         c = *rhsp & TRIM;
  546.                         if (c == '&')
  547.                             error("Replacement pattern contains &@- cannot use in re");
  548.                         if (c >= '1' && c <= '9')
  549.                             error("Replacement pattern contains \\d@- cannot use in re");
  550.                     }
  551.                     if (ep >= &expbuf[ESIZE-2])
  552.                         goto complex;
  553.                     *ep++ = CCHR;
  554.                     *ep++ = *rhsp++ & TRIM;
  555.                 }
  556.                 continue;
  557.  
  558.             case '*':
  559.                 if (ep == expbuf)
  560.                     break;
  561.                 if (*lastep == CBRA || *lastep == CKET)
  562.                     cerror("Illegal *|Can't * a \\( ... \\) in regular expression");
  563.                 if (*lastep == CCHR && (lastep[1] & QUOTE))
  564.                     cerror("Illegal *|Can't * a \\n in regular expression");
  565.                 *lastep |= STAR;
  566.                 continue;
  567.  
  568.             case '[':
  569.                 *ep++ = CCL;
  570.                 *ep++ = 0;
  571.                 cclcnt = 1;
  572.                 c = getchar();
  573.                 if (c == '^') {
  574.                     c = getchar();
  575.                     ep[-2] = NCCL;
  576.                 }
  577.                 if (c == ']')
  578.                     cerror("Bad character class|Empty character class '[]' or '[^]' cannot match");
  579.                 while (c != ']') {
  580.                     if (c == '\\' && any(peekchar(), "]-^\\"))
  581.                         c = getchar() | QUOTE;
  582.                     if (c == '\n' || c == EOF)
  583.                         cerror("Missing ]");
  584.                     *ep++ = c;
  585.                     cclcnt++;
  586.                     if (ep >= &expbuf[ESIZE])
  587.                         goto complex;
  588.                     c = getchar();
  589.                 }
  590.                 lastep[1] = cclcnt;
  591.                 continue;
  592.             }
  593.             if (c == EOF) {
  594.                 ungetchar(EOF);
  595.                 c = '\\';
  596.                 goto defchar;
  597.             }
  598.             *ep++ = CCHR;
  599.             if (c == '\n')
  600.                 cerror("No newlines in re's|Can't escape newlines into regular expressions");
  601. /*
  602.             if (c < '1' || c > NBRA + '1') {
  603. */
  604.                 *ep++ = c;
  605.                 continue;
  606. /*
  607.             }
  608.             c -= '1';
  609.             if (c >= nbra)
  610.                 cerror("Bad \\n|\\n in regular expression with n greater than the number of \\('s");
  611.             *ep++ = c | QUOTE;
  612.             continue;
  613. */
  614.  
  615.         case '\n':
  616.             if (oknl) {
  617.                 ungetchar(c);
  618.                 *ep++ = CEOF;
  619.                 return (eof);
  620.             }
  621.             cerror("Badly formed re|Missing closing delimiter for regular expression");
  622.  
  623.         case '$':
  624.             if (peekchar() == eof || peekchar() == EOF || oknl && peekchar() == '\n') {
  625.                 *ep++ = CDOL;
  626.                 continue;
  627.             }
  628.             goto defchar;
  629.  
  630.         case '.':
  631.         case '~':
  632.         case '*':
  633.         case '[':
  634.             if (value(MAGIC) && !intag)
  635.                 goto magic;
  636. defchar:
  637.         default:
  638.             *ep++ = CCHR;
  639.             *ep++ = c;
  640.             continue;
  641.         }
  642.     }
  643. }
  644.  
  645. cerror(s)
  646.     char *s;
  647. {
  648.  
  649.     expbuf[0] = 0;
  650.     error(s);
  651. }
  652.  
  653. same(a, b)
  654.     register int a, b;
  655. {
  656.  
  657.     return (a == b || value(IGNORECASE) &&
  658.        ((islower(a) && toupper(a) == b) || (islower(b) && toupper(b) == a)));
  659. }
  660.  
  661. char    *locs;
  662.  
  663. execute(gf, addr)
  664.     line *addr;
  665. {
  666.     register char *p1, *p2;
  667.     register int c;
  668.  
  669.     if (gf) {
  670.         if (circfl)
  671.             return (0);
  672.         locs = p1 = loc2;
  673.     } else {
  674.         if (addr == zero)
  675.             return (0);
  676.         p1 = linebuf;
  677.         getline(*addr);
  678.         locs = 0;
  679.     }
  680.     p2 = expbuf;
  681.     if (circfl) {
  682.         loc1 = p1;
  683.         return (advance(p1, p2));
  684.     }
  685.     /* fast check for first character */
  686.     if (*p2 == CCHR) {
  687.         c = p2[1];
  688.         do {
  689.             if (c != *p1 && (!value(IGNORECASE) ||
  690.                !((islower(c) && toupper(c) == *p1) || (islower(*p1) && toupper(*p1) == c))))
  691.                 continue;
  692.             if (advance(p1, p2)) {
  693.                 loc1 = p1;
  694.                 return (1);
  695.             }
  696.         } while (*p1++);
  697.         return (0);
  698.     }
  699.     /* regular algorithm */
  700.     do {
  701.         if (advance(p1, p2)) {
  702.             loc1 = p1;
  703.             return (1);
  704.         }
  705.     } while (*p1++);
  706.     return (0);
  707. }
  708.  
  709. #define    uletter(c)    (isalpha(c) || c == '_')
  710.  
  711. advance(lp, ep)
  712.     register char *lp, *ep;
  713. {
  714.     register char *curlp;
  715.     char *sp, *sp1;
  716.     int c;
  717.  
  718.     for (;;) switch (*ep++) {
  719.  
  720.     case CCHR:
  721. /* useless
  722.         if (*ep & QUOTE) {
  723.             c = *ep++ & TRIM;
  724.             sp = braslist[c];
  725.             sp1 = braelist[c];
  726.             while (sp < sp1) {
  727.                 if (!same(*sp, *lp))
  728.                     return (0);
  729.                 sp++, lp++;
  730.             }
  731.             continue;
  732.         }
  733. */
  734.         if (!same(*ep, *lp))
  735.             return (0);
  736.         ep++, lp++;
  737.         continue;
  738.  
  739.     case CDOT:
  740.         if (*lp++)
  741.             continue;
  742.         return (0);
  743.  
  744.     case CDOL:
  745.         if (*lp == 0)
  746.             continue;
  747.         return (0);
  748.  
  749.     case CEOF:
  750.         loc2 = lp;
  751.         return (1);
  752.  
  753.     case CCL:
  754.         if (cclass(ep, *lp++, 1)) {
  755.             ep += *ep;
  756.             continue;
  757.         }
  758.         return (0);
  759.  
  760.     case NCCL:
  761.         if (cclass(ep, *lp++, 0)) {
  762.             ep += *ep;
  763.             continue;
  764.         }
  765.         return (0);
  766.  
  767.     case CBRA:
  768.         braslist[*ep++] = lp;
  769.         continue;
  770.  
  771.     case CKET:
  772.         braelist[*ep++] = lp;
  773.         continue;
  774.  
  775.     case CDOT|STAR:
  776.         curlp = lp;
  777.         while (*lp++)
  778.             continue;
  779.         goto star;
  780.  
  781.     case CCHR|STAR:
  782.         curlp = lp;
  783.         while (same(*lp, *ep))
  784.             lp++;
  785.         lp++;
  786.         ep++;
  787.         goto star;
  788.  
  789.     case CCL|STAR:
  790.     case NCCL|STAR:
  791.         curlp = lp;
  792.         while (cclass(ep, *lp++, ep[-1] == (CCL|STAR)))
  793.             continue;
  794.         ep += *ep;
  795.         goto star;
  796. star:
  797.         do {
  798.             lp--;
  799.             if (lp == locs)
  800.                 break;
  801.             if (advance(lp, ep))
  802.                 return (1);
  803.         } while (lp > curlp);
  804.         return (0);
  805.  
  806.     case CBRC:
  807.         if (lp == expbuf)
  808.             continue;
  809.         if ((isdigit(*lp) || uletter(*lp)) && !uletter(lp[-1]) && !isdigit(lp[-1]))
  810.             continue;
  811.         return (0);
  812.  
  813.     case CLET:
  814.         if (!uletter(*lp) && !isdigit(*lp))
  815.             continue;
  816.         return (0);
  817.  
  818.     default:
  819.         error("Re internal error");
  820.     }
  821. }
  822.  
  823. cclass(set, c, af)
  824.     register char *set;
  825.     register int c;
  826.     int af;
  827. {
  828.     register int n;
  829.  
  830.     if (c == 0)
  831.         return (0);
  832.     if (value(IGNORECASE) && isupper(c))
  833.         c = tolower(c);
  834.     n = *set++;
  835.     while (--n)
  836.         if (n > 2 && set[1] == '-') {
  837.             if (c >= (set[0] & TRIM) && c <= (set[2] & TRIM))
  838.                 return (af);
  839.             set += 3;
  840.             n -= 2;
  841.         } else
  842.             if ((*set++ & TRIM) == c)
  843.                 return (af);
  844.     return (!af);
  845. }
  846.