int RegExpFind::regmatch()

in Source/kwsys/RegularExpression.cxx [971:1193]


int RegExpFind::regmatch(char const* prog)
{
  char const* scan; // Current node.
  char const* next; // Next node.

  scan = prog;

  while (scan) {

    next = regnext(scan);

    switch (OP(scan)) {
      case BOL:
        if (reginput != regbol)
          return (0);
        break;
      case EOL:
        if (*reginput != '\0')
          return (0);
        break;
      case ANY:
        if (*reginput == '\0')
          return (0);
        reginput++;
        break;
      case EXACTLY: {
        size_t len;
        char const* opnd;

        opnd = OPERAND(scan);
        // Inline the first character, for speed.
        if (*opnd != *reginput)
          return (0);
        len = strlen(opnd);
        if (len > 1 && strncmp(opnd, reginput, len) != 0)
          return (0);
        reginput += len;
      } break;
      case ANYOF:
        if (*reginput == '\0' || !strchr(OPERAND(scan), *reginput))
          return (0);
        reginput++;
        break;
      case ANYBUT:
        if (*reginput == '\0' || strchr(OPERAND(scan), *reginput))
          return (0);
        reginput++;
        break;
      case NOTHING:
        break;
      case BACK:
        break;
      case OPEN + 1:
      case OPEN + 2:
      case OPEN + 3:
      case OPEN + 4:
      case OPEN + 5:
      case OPEN + 6:
      case OPEN + 7:
      case OPEN + 8:
      case OPEN + 9:
      case OPEN + 10:
      case OPEN + 11:
      case OPEN + 12:
      case OPEN + 13:
      case OPEN + 14:
      case OPEN + 15:
      case OPEN + 16:
      case OPEN + 17:
      case OPEN + 18:
      case OPEN + 19:
      case OPEN + 20:
      case OPEN + 21:
      case OPEN + 22:
      case OPEN + 23:
      case OPEN + 24:
      case OPEN + 25:
      case OPEN + 26:
      case OPEN + 27:
      case OPEN + 28:
      case OPEN + 29:
      case OPEN + 30:
      case OPEN + 31:
      case OPEN + 32: {
        int no;
        char const* save;

        no = OP(scan) - OPEN;
        save = reginput;

        if (regmatch(next)) {

          //
          // Don't set startp if some later invocation of the
          // same parentheses already has.
          //
          if (!regstartp[no])
            regstartp[no] = save;
          return (1);
        } else
          return (0);
      }
      //              break;
      case CLOSE + 1:
      case CLOSE + 2:
      case CLOSE + 3:
      case CLOSE + 4:
      case CLOSE + 5:
      case CLOSE + 6:
      case CLOSE + 7:
      case CLOSE + 8:
      case CLOSE + 9:
      case CLOSE + 10:
      case CLOSE + 11:
      case CLOSE + 12:
      case CLOSE + 13:
      case CLOSE + 14:
      case CLOSE + 15:
      case CLOSE + 16:
      case CLOSE + 17:
      case CLOSE + 18:
      case CLOSE + 19:
      case CLOSE + 20:
      case CLOSE + 21:
      case CLOSE + 22:
      case CLOSE + 23:
      case CLOSE + 24:
      case CLOSE + 25:
      case CLOSE + 26:
      case CLOSE + 27:
      case CLOSE + 28:
      case CLOSE + 29:
      case CLOSE + 30:
      case CLOSE + 31:
      case CLOSE + 32: {
        int no;
        char const* save;

        no = OP(scan) - CLOSE;
        save = reginput;

        if (regmatch(next)) {

          //
          // Don't set endp if some later invocation of the
          // same parentheses already has.
          //
          if (!regendp[no])
            regendp[no] = save;
          return (1);
        } else
          return (0);
      }
      //              break;
      case BRANCH: {

        char const* save;

        if (OP(next) != BRANCH) // No choice.
          next = OPERAND(scan); // Avoid recursion.
        else {
          do {
            save = reginput;
            if (regmatch(OPERAND(scan)))
              return (1);
            reginput = save;
            scan = regnext(scan);
          } while (scan && OP(scan) == BRANCH);
          return (0);
          // NOTREACHED
        }
      } break;
      case STAR:
      case PLUS: {
        char nextch;
        int no;
        char const* save;
        int min_no;

        //
        // Lookahead to avoid useless match attempts when we know
        // what character comes next.
        //
        nextch = '\0';
        if (OP(next) == EXACTLY)
          nextch = *OPERAND(next);
        min_no = (OP(scan) == STAR) ? 0 : 1;
        save = reginput;
        no = regrepeat(OPERAND(scan));
        while (no >= min_no) {
          // If it could work, try it.
          if (nextch == '\0' || *reginput == nextch)
            if (regmatch(next))
              return (1);
          // Couldn't or didn't -- back up.
          no--;
          reginput = save + no;
        }
        return (0);
      }
      //              break;
      case END:
        if (reginput == regreject)
          return (0); // Can't end a match here
        return (1);   // Success!

      default:
        // RAISE Error, SYM(RegularExpression), SYM(Internal_Error),
        printf(
          "RegularExpression::find(): Internal error -- memory corrupted.\n");
        return 0;
    }
    scan = next;
  }

  //
  //  We get here only if there's trouble -- normally "case END" is the
  //  terminating point.
  //
  // RAISE Error, SYM(RegularExpression), SYM(Internal_Error),
  printf("RegularExpression::find(): Internal error -- corrupted pointers.\n");
  return (0);
}