From 96d9dde04836a0afe47d703919ba9b73b705e4b4 Mon Sep 17 00:00:00 2001 From: John Scipione Date: Fri, 20 Jun 2014 19:13:27 -0400 Subject: [PATCH] Tracker: style fixes to RegExp (minor) --- src/kits/tracker/RegExp.cpp | 470 ++++++++++++++++++++++-------------- src/kits/tracker/RegExp.h | 3 + 2 files changed, 294 insertions(+), 179 deletions(-) diff --git a/src/kits/tracker/RegExp.cpp b/src/kits/tracker/RegExp.cpp index 15cf7b89f6..3338d28e2f 100644 --- a/src/kits/tracker/RegExp.cpp +++ b/src/kits/tracker/RegExp.cpp @@ -168,6 +168,7 @@ const char* kMeta = "^$.[()|?+*\\"; const int32 kMaxSize = 32767L; // Probably could be 65535L. + // Flags to be passed up and down: enum { kHasWidth = 01, // Known never to match null string. @@ -176,6 +177,7 @@ enum { kWorst = 0 // Worst case. }; + const char* kRegExpErrorStringArray[] = { "Unmatched parenthesis.", "Expression too long.", @@ -194,28 +196,36 @@ const char* kRegExpErrorStringArray[] = { "Corrupted opcode." }; + #ifdef DEBUG int32 regnarrate = 0; #endif + +// #pragma mark - RegExp + + RegExp::RegExp() - : fError(B_OK), - fRegExp(NULL) + : + fError(B_OK), + fRegExp(NULL) { } RegExp::RegExp(const char* pattern) - : fError(B_OK), - fRegExp(NULL) + : + fError(B_OK), + fRegExp(NULL) { fRegExp = Compile(pattern); } RegExp::RegExp(const BString &pattern) - : fError(B_OK), - fRegExp(NULL) + : + fError(B_OK), + fRegExp(NULL) { fRegExp = Compile(pattern.String()); } @@ -257,7 +267,7 @@ RegExp::SetTo(const BString &pattern) bool RegExp::Matches(const char* string) const { - if (!fRegExp || !string) + if (fRegExp == NULL || string == NULL) return false; return RunMatcher(fRegExp, string) == 1; @@ -267,7 +277,7 @@ RegExp::Matches(const char* string) const bool RegExp::Matches(const BString &string) const { - if (!fRegExp) + if (fRegExp == NULL) return false; return RunMatcher(fRegExp, string.String()) == 1; @@ -320,7 +330,7 @@ RegExp::Compile(const char* exp) r = (regexp*)malloc(sizeof(regexp) + fCodeSize); // Allocate space - if (!r) { + if (r == NULL) { SetError(B_NO_MEMORY); return NULL; } @@ -336,7 +346,8 @@ RegExp::Compile(const char* exp) } // Dig out information for optimizations. - r->regstart = '\0'; // Worst-case defaults. + r->regstart = '\0'; + // Worst-case defaults. r->reganch = 0; r->regmust = NULL; r->regmlen = 0; @@ -358,15 +369,16 @@ RegExp::Compile(const char* exp) // the regstart check works with the beginning of the r.e. // and avoiding duplication strengthens checking. Not a // strong reason, but sufficient in the absence of others. - if (flags&kSPStart) { + if ((flags & kSPStart) != 0) { longest = NULL; len = 0; - for (; scan != NULL; scan = Next((char*)scan)) + for (; scan != NULL; scan = Next((char*)scan)) { if (*scan == kRegExpExactly && (int32)strlen(Operand(scan)) >= len) { longest = Operand(scan); len = (int32)strlen(Operand(scan)); } + } r->regmust = longest; r->regmlen = len; } @@ -387,8 +399,9 @@ const char* RegExp::ErrorString() const { if (fError >= REGEXP_UNMATCHED_PARENTHESIS - && fError <= REGEXP_CORRUPTED_OPCODE) + && fError <= REGEXP_CORRUPTED_OPCODE) { return kRegExpErrorStringArray[fError - B_ERRORS_END]; + } return strerror(fError); } @@ -419,7 +432,8 @@ RegExp::Reg(int32 paren, int32* flagp) int32 parno = 0; int32 flags; - *flagp = kHasWidth; // Tentatively. + *flagp = kHasWidth; + // Tentatively. // Make an kRegExpOpen node, if parenthesized. if (paren) { @@ -437,21 +451,28 @@ RegExp::Reg(int32 paren, int32* flagp) br = Branch(&flags); if (br == NULL) return NULL; - if (ret != NULL) - Tail(ret, br); // kRegExpOpen -> first - else + + if (ret != NULL) { + Tail(ret, br); + // kRegExpOpen -> first + } else ret = br; + if (!(flags & kHasWidth)) *flagp &= ~kHasWidth; + *flagp |= flags&kSPStart; while (*fInputScanPointer == '|') { fInputScanPointer++; br = Branch(&flags); if (br == NULL) return NULL; - Tail(ret, br); // kRegExpBranch -> kRegExpBranch. + + Tail(ret, br); + // kRegExpBranch -> kRegExpBranch. if (!(flags & kHasWidth)) *flagp &= ~kHasWidth; + *flagp |= flags&kSPStart; } @@ -495,7 +516,8 @@ RegExp::Branch(int32* flagp) char* latest; int32 flags; - *flagp = kWorst; // Tentatively. + *flagp = kWorst; + // Tentatively. ret = Node(kRegExpBranch); chain = NULL; @@ -505,15 +527,21 @@ RegExp::Branch(int32* flagp) latest = Piece(&flags); if (latest == NULL) return NULL; + *flagp |= flags & kHasWidth; - if (chain == NULL) // First piece. + if (chain == NULL) { + // First piece. *flagp |= flags & kSPStart; - else + } else Tail(chain, latest); + chain = latest; } - if (chain == NULL) // Loop ran zero times. + + if (chain == NULL) { + // Loop ran zero times. Node(kRegExpNothing); + } return ret; } @@ -556,33 +584,47 @@ RegExp::Piece(int32* flagp) Insert(kRegExpStar, ret); else if (op == '*') { // Emit x* as (x&|), where & means "self". - Insert(kRegExpBranch, ret); // Either x - OpTail(ret, Node(kRegExpBack)); // and loop - OpTail(ret, ret); // back - Tail(ret, Node(kRegExpBranch)); // or - Tail(ret, Node(kRegExpNothing)); // null. + Insert(kRegExpBranch, ret); + // Either x + OpTail(ret, Node(kRegExpBack)); + // and loop + OpTail(ret, ret); + // back + Tail(ret, Node(kRegExpBranch)); + // or + Tail(ret, Node(kRegExpNothing)); + // null. } else if (op == '+' && (flags & kSimple)) Insert(kRegExpPlus, ret); else if (op == '+') { // Emit x+ as x(&|), where & means "self". - next = Node(kRegExpBranch); // Either + next = Node(kRegExpBranch); + // Either Tail(ret, next); - Tail(Node(kRegExpBack), ret); // loop back - Tail(next, Node(kRegExpBranch)); // or - Tail(ret, Node(kRegExpNothing)); // null. + Tail(Node(kRegExpBack), ret); + // loop back + Tail(next, Node(kRegExpBranch)); + // or + Tail(ret, Node(kRegExpNothing)); + // null. } else if (op == '?') { // Emit x? as (x|) - Insert(kRegExpBranch, ret); // Either x - Tail(ret, Node(kRegExpBranch)); // or - next = Node(kRegExpNothing); // null. + Insert(kRegExpBranch, ret); + // Either x + Tail(ret, Node(kRegExpBranch)); + // or + next = Node(kRegExpNothing); + // null. Tail(ret, next); OpTail(ret, next); } + fInputScanPointer++; if (IsMult(*fInputScanPointer)) { SetError(REGEXP_NESTED_STAR_QUESTION_PLUS); return NULL; } + return ret; } @@ -601,77 +643,87 @@ RegExp::Atom(int32* flagp) char* ret; int32 flags; - *flagp = kWorst; // Tentatively. + *flagp = kWorst; + // tentatively switch (*fInputScanPointer++) { case '^': ret = Node(kRegExpBol); break; + case '$': ret = Node(kRegExpEol); break; + case '.': ret = Node(kRegExpAny); *flagp |= kHasWidth|kSimple; break; - case '[': - { - int32 cclass; - int32 classend; - if (*fInputScanPointer == '^') { // Complement of range. - ret = Node(kRegExpAnyBut); - fInputScanPointer++; - } else - ret = Node(kRegExpAnyOf); - if (*fInputScanPointer == ']' || *fInputScanPointer == '-') - Char(*fInputScanPointer++); - while (*fInputScanPointer != '\0' - && *fInputScanPointer != ']') { - if (*fInputScanPointer == '-') { - fInputScanPointer++; - if (*fInputScanPointer == ']' - || *fInputScanPointer == '\0') { - Char('-'); - } else { - cclass = UCharAt(fInputScanPointer - 2) + 1; - classend = UCharAt(fInputScanPointer); - if (cclass > classend + 1) { - SetError(REGEXP_INVALID_BRACKET_RANGE); - return NULL; - } - for (; cclass <= classend; cclass++) - Char((char)cclass); - fInputScanPointer++; - } - } else - Char(*fInputScanPointer++); - } - Char('\0'); - if (*fInputScanPointer != ']') { - SetError(REGEXP_UNMATCHED_BRACKET); - return NULL; - } + case '[': + { + int32 cclass; + int32 classend; + + if (*fInputScanPointer == '^') { + // complement of range + ret = Node(kRegExpAnyBut); fInputScanPointer++; - *flagp |= kHasWidth | kSimple; + } else + ret = Node(kRegExpAnyOf); + if (*fInputScanPointer == ']' || *fInputScanPointer == '-') + Char(*fInputScanPointer++); + while (*fInputScanPointer != '\0' + && *fInputScanPointer != ']') { + if (*fInputScanPointer == '-') { + fInputScanPointer++; + if (*fInputScanPointer == ']' + || *fInputScanPointer == '\0') { + Char('-'); + } else { + cclass = UCharAt(fInputScanPointer - 2) + 1; + classend = UCharAt(fInputScanPointer); + if (cclass > classend + 1) { + SetError(REGEXP_INVALID_BRACKET_RANGE); + return NULL; + } + for (; cclass <= classend; cclass++) + Char((char)cclass); + fInputScanPointer++; + } + } else + Char(*fInputScanPointer++); } + Char('\0'); + if (*fInputScanPointer != ']') { + SetError(REGEXP_UNMATCHED_BRACKET); + return NULL; + } + fInputScanPointer++; + *flagp |= kHasWidth | kSimple; break; + } + case '(': ret = Reg(1, &flags); if (ret == NULL) return NULL; *flagp |= flags & (kHasWidth | kSPStart); break; + case '\0': case '|': case ')': SetError(REGEXP_INTERNAL_ERROR); - return NULL; // Supposed to be caught earlier. + return NULL; + // supposed to be caught earlier + case '?': case '+': case '*': SetError(REGEXP_QUESTION_PLUS_STAR_FOLLOWS_NOTHING); return NULL; + case '\\': if (*fInputScanPointer == '\0') { SetError(REGEXP_TRAILING_BACKSLASH); @@ -682,6 +734,7 @@ RegExp::Atom(int32* flagp) Char('\0'); *flagp |= kHasWidth|kSimple; break; + default: { int32 len; @@ -695,8 +748,10 @@ RegExp::Atom(int32* flagp) } ender = *(fInputScanPointer + len); - if (len > 1 && IsMult(ender)) - len--; // Back off clear of ?+* operand. + if (len > 1 && IsMult(ender)) { + // Back off clear of ?+* operand. + len--; + } *flagp |= kHasWidth; if (len == 1) @@ -720,7 +775,9 @@ RegExp::Atom(int32* flagp) // // - Node - emit a node // -char* // Location. +// Returns location. +// +char* RegExp::Node(char op) { char* ret; @@ -734,7 +791,8 @@ RegExp::Node(char op) ptr = ret; *ptr++ = op; - *ptr++ = '\0'; // Null "next" pointer. + *ptr++ = '\0'; + // Null "next" pointer. *ptr++ = '\0'; fCodeEmitPointer = ptr; @@ -778,7 +836,8 @@ RegExp::Insert(char op, char* opnd) while (src > opnd) *--dst = *--src; - place = opnd; // Op node, where operand used to be. + place = opnd; + // Op node, where operand used to be. *place++ = op; *place++ = '\0'; *place++ = '\0'; @@ -826,6 +885,7 @@ RegExp::OpTail(char* p, char* val) // "Operandless" and "op != kRegExpBranch" are synonymous in practice. if (p == NULL || p == &fDummy || *p != kRegExpBranch) return; + Tail(Operand(p), val); } @@ -842,54 +902,59 @@ RegExp::RunMatcher(regexp* prog, const char* string) const { const char* s; - // Be paranoid... + // be paranoid... if (prog == NULL || string == NULL) { SetError(B_BAD_VALUE); return 0; } - // Check validity of program. + // check validity of program if (UCharAt(prog->program) != kRegExpMagic) { SetError(REGEXP_CORRUPTED_PROGRAM); return 0; } - // If there is a "must appear" string, look for it. + // if there is a "must appear" string, look for it if (prog->regmust != NULL) { s = string; while ((s = strchr(s, prog->regmust[0])) != NULL) { - if (strncmp(s, prog->regmust, (size_t)prog->regmlen) == 0) - break; // Found it. + if (strncmp(s, prog->regmust, (size_t)prog->regmlen) == 0) { + // found it + break; + } s++; } - if (s == NULL) // Not present. + if (s == NULL) { + // not present return 0; + } } - // Mark beginning of line for ^ . + // mark beginning of line for ^ fRegBol = string; - // Simplest case: anchored match need be tried only once. + // simplest case: anchored match need be tried only once if (prog->reganch) return Try(prog, (char*)string); - // Messy cases: unanchored match. + // messy cases: unanchored match s = string; - if (prog->regstart != '\0') - // We know what char it must start with. + if (prog->regstart != '\0') { + // we know what char it must start with while ((s = strchr(s, prog->regstart)) != NULL) { if (Try(prog, (char*)s)) return 1; s++; } - else - // We don't -- general case. + } else { + // we don't -- general case. do { if (Try(prog, (char*)s)) return 1; } while (*s++ != '\0'); + } - // Failure. + // failure return 0; } @@ -897,7 +962,9 @@ RegExp::RunMatcher(regexp* prog, const char* string) const // // - Try - try match at specific point // -int32 // 0 failure, 1 success +// Returns 0 on failure, 1 on success. +// +int32 RegExp::Try(regexp* prog, const char* string) const { int32 i; @@ -932,8 +999,10 @@ RegExp::Try(regexp* prog, const char* string) const // recursion, in particular by going through "ordinary" nodes (that don't // need to know whether the rest of the match failed) by a loop instead of // by recursion. -/// -int32 // 0 failure, 1 success +// +// Returns 0 on failure, 1 on success. +// +int32 RegExp::Match(const char* prog) const { const char* scan; // Current node. @@ -956,47 +1025,57 @@ RegExp::Match(const char* prog) const if (fStringInputPointer != fRegBol) return 0; break; + case kRegExpEol: if (*fStringInputPointer != '\0') return 0; break; + case kRegExpAny: if (*fStringInputPointer == '\0') return 0; fStringInputPointer++; break; + case kRegExpExactly: - { - const char* opnd = Operand(scan); - // Inline the first character, for speed. - if (*opnd != *fStringInputPointer) - return 0; + { + const char* opnd = Operand(scan); + // Inline the first character, for speed. + if (*opnd != *fStringInputPointer) + return 0; - uint32 len = strlen(opnd); - if (len > 1 - && strncmp(opnd, fStringInputPointer, len) != 0) { - return 0; - } - - fStringInputPointer += len; + uint32 len = strlen(opnd); + if (len > 1 + && strncmp(opnd, fStringInputPointer, len) != 0) { + return 0; } - break; + + fStringInputPointer += len; + } + break; + case kRegExpAnyOf: if (*fStringInputPointer == '\0' - || strchr(Operand(scan), *fStringInputPointer) == NULL) + || strchr(Operand(scan), *fStringInputPointer) == NULL) { return 0; + } fStringInputPointer++; break; + case kRegExpAnyBut: if (*fStringInputPointer == '\0' - || strchr(Operand(scan), *fStringInputPointer) != NULL) + || strchr(Operand(scan), *fStringInputPointer) != NULL) { return 0; + } fStringInputPointer++; break; + case kRegExpNothing: break; + case kRegExpBack: break; + case kRegExpOpen + 1: case kRegExpOpen + 2: case kRegExpOpen + 3: @@ -1006,26 +1085,27 @@ RegExp::Match(const char* prog) const case kRegExpOpen + 7: case kRegExpOpen + 8: case kRegExpOpen + 9: - { - int32 no; - const char* save; + { + int32 no; + const char* save; - no = *scan - kRegExpOpen; - save = fStringInputPointer; + no = *scan - kRegExpOpen; + save = fStringInputPointer; + + if (Match(next)) { + // + // Don't set startp if some later + // invocation of the same parentheses + // already has. + // + if (fStartPArrayPointer[no] == NULL) + fStartPArrayPointer[no] = save; + return 1; + } else + return 0; + } + break; - if (Match(next)) { - // - // Don't set startp if some later - // invocation of the same parentheses - // already has. - // - if (fStartPArrayPointer[no] == NULL) - fStartPArrayPointer[no] = save; - return 1; - } else - return 0; - } - break; case kRegExpClose + 1: case kRegExpClose + 2: case kRegExpClose + 3: @@ -1035,45 +1115,49 @@ RegExp::Match(const char* prog) const case kRegExpClose + 7: case kRegExpClose + 8: case kRegExpClose + 9: - { - int32 no; - const char* save; + { + int32 no; + const char* save; - no = *scan - kRegExpClose; - save = fStringInputPointer; + no = *scan - kRegExpClose; + save = fStringInputPointer; + + if (Match(next)) { + // + // Don't set endp if some later + // invocation of the same parentheses + // already has. + // + if (fEndPArrayPointer[no] == NULL) + fEndPArrayPointer[no] = save; + return 1; + } else + return 0; + } + break; - if (Match(next)) { - // - // Don't set endp if some later - // invocation of the same parentheses - // already has. - // - if (fEndPArrayPointer[no] == NULL) - fEndPArrayPointer[no] = save; - return 1; - } else - return 0; - } - break; case kRegExpBranch: - { - const char* save; + { + const char* save; - if (*next != kRegExpBranch) // No choice. - next = Operand(scan); // Avoid recursion. - else { - do { - save = fStringInputPointer; - if (Match(Operand(scan))) - return 1; - fStringInputPointer = save; - scan = Next(scan); - } while (scan != NULL && *scan == kRegExpBranch); - return 0; - // NOTREACHED/ - } + if (*next != kRegExpBranch) { + // no choice + next = Operand(scan); + // avoid recursion + } else { + do { + save = fStringInputPointer; + if (Match(Operand(scan))) + return 1; + fStringInputPointer = save; + scan = Next(scan); + } while (scan != NULL && *scan == kRegExpBranch); + return 0; + // NOTREACHED } - break; + } + break; + case kRegExpStar: case kRegExpPlus: { @@ -1083,7 +1167,7 @@ RegExp::Match(const char* prog) const int32 min; // - //Lookahead to avoid useless match attempts + // Lookahead to avoid useless match attempts // when we know what character comes next. // nextch = '\0'; @@ -1093,19 +1177,22 @@ RegExp::Match(const char* prog) const save = fStringInputPointer; no = Repeat(Operand(scan)); while (no >= min) { - // If it could work, try it. - if (nextch == '\0' || *fStringInputPointer == nextch) + // if it could work, try it + if (nextch == '\0' || *fStringInputPointer == nextch) { if (Match(next)) return 1; - // Couldn't or didn't -- back up. + } + // couldn't or didn't, back up no--; fStringInputPointer = save + no; } return 0; } break; + case kRegExpEnd: - return 1; // Success! + return 1; + // Success! default: SetError(REGEXP_MEMORY_CORRUPTION); @@ -1120,6 +1207,7 @@ RegExp::Match(const char* prog) const // the terminating point. // SetError(REGEXP_CORRUPTED_POINTERS); + return 0; } @@ -1163,9 +1251,11 @@ RegExp::Repeat(const char* p) const } break; - default: // Oh dear. Called inappropriately. + default: + // oh dear, called inappropriately SetError(REGEXP_INTERNAL_ERROR); - count = 0; // Best compromise. + count = 0; + // best compromise break; } fStringInputPointer = scan; @@ -1253,22 +1343,27 @@ void RegExp::Dump() { const char* s; - char op = kRegExpExactly; // Arbitrary non-kRegExpEnd op. + char op = kRegExpExactly; + // Arbitrary non-kRegExpEnd op. const char* next; s = fRegExp->program + 1; - while (op != kRegExpEnd) { // While that wasn't kRegExpEnd last time... + while (op != kRegExpEnd) { + // While that wasn't kRegExpEnd last time... op = *s; - printf("%2ld%s", s - fRegExp->program, Prop(s)); // Where, what. + printf("%2ld%s", s - fRegExp->program, Prop(s)); + // Where, what. next = Next(s); - if (next == NULL) // Next ptr. + if (next == NULL) { + // next ptr printf("(0)"); - else + } else printf("(%ld)", (s - fRegExp->program) + (next - s)); + s += 3; if (op == kRegExpAnyOf || op == kRegExpAnyBut || op == kRegExpExactly) { - // Literal string, where present. + // literal string, where present while (*s != '\0') { putchar(*s); s++; @@ -1278,13 +1373,16 @@ RegExp::Dump() putchar('\n'); } - // Header fields of interest. + // header fields of interest if (fRegExp->regstart != '\0') printf("start `%c' ", fRegExp->regstart); + if (fRegExp->reganch) printf("anchored "); + if (fRegExp->regmust != NULL) printf("must have \"%s\"", fRegExp->regmust); + printf("\n"); } @@ -1298,39 +1396,49 @@ RegExp::Prop(const char* op) const const char* p = NULL; static char buf[50]; - (void) strcpy(buf, ":"); + strcpy(buf, ":"); switch (*op) { case kRegExpBol: p = "kRegExpBol"; break; + case kRegExpEol: p = "kRegExpEol"; break; + case kRegExpAny: p = "kRegExpAny"; break; + case kRegExpAnyOf: p = "kRegExpAnyOf"; break; + case kRegExpAnyBut: p = "kRegExpAnyBut"; break; + case kRegExpBranch: p = "kRegExpBranch"; break; + case kRegExpExactly: p = "kRegExpExactly"; break; + case kRegExpNothing: p = "kRegExpNothing"; break; + case kRegExpBack: p = "kRegExpBack"; break; + case kRegExpEnd: p = "kRegExpEnd"; break; + case kRegExpOpen + 1: case kRegExpOpen + 2: case kRegExpOpen + 3: @@ -1343,6 +1451,7 @@ RegExp::Prop(const char* op) const sprintf(buf + strlen(buf), "kRegExpOpen%d", *op - kRegExpOpen); p = NULL; break; + case kRegExpClose + 1: case kRegExpClose + 2: case kRegExpClose + 3: @@ -1355,12 +1464,15 @@ RegExp::Prop(const char* op) const sprintf(buf + strlen(buf), "kRegExpClose%d", *op - kRegExpClose); p = NULL; break; + case kRegExpStar: p = "kRegExpStar"; break; + case kRegExpPlus: p = "kRegExpPlus"; break; + default: RegExpError("corrupted opcode"); break; @@ -1379,4 +1491,4 @@ RegExp::RegExpError(const char*) const // does nothing now, perhaps it should printf? } -#endif +#endif // DEBUG diff --git a/src/kits/tracker/RegExp.h b/src/kits/tracker/RegExp.h index f1021e10fe..7142028aa8 100644 --- a/src/kits/tracker/RegExp.h +++ b/src/kits/tracker/RegExp.h @@ -89,8 +89,10 @@ enum { REGEXP_CORRUPTED_OPCODE }; + const int32 kSubExpressionMax = 10; + struct regexp { const char* startp[kSubExpressionMax]; const char* endp[kSubExpressionMax]; @@ -183,4 +185,5 @@ private: using namespace BPrivate; + #endif // _REG_EXP_H