void test_starcode_2 (void) // Test addmatch(). { useq_t *u1 = new_useq(12983, "string 1", NULL); test_assert_critical(u1 != NULL); test_assert(u1->matches == NULL); useq_t *u2 = new_useq(-20838, "string 2", NULL); test_assert_critical(u2 != NULL); test_assert(u2->matches == NULL); // Add match to u1. addmatch(u1, u2, 1, 2); test_assert(u2->matches == NULL); test_assert(u1->matches != NULL); // Check failure. test_assert(addmatch(u1, u2, 3, 2) == 1); // Add match again to u1. addmatch(u1, u2, 1, 2); test_assert(u2->matches == NULL); test_assert_critical(u1->matches != NULL); test_assert_critical(u1->matches[1] != NULL); test_assert(u1->matches[1]->nitems == 2); destroy_useq(u1); destroy_useq(u2); }
void test_starcode_3 (void) // Test 'addmatch', 'transfer_counts_and_update_canonicals'. { useq_t *u1 = new_useq(1, "B}d2)$ChPyDC=xZ D-C", NULL); useq_t *u2 = new_useq(2, "RCD67vQc80:~@FV`?o%D", NULL); // Add match to 'u1'. addmatch(u1, u2, 1, 1); test_assert(u1->count == 1); test_assert(u2->count == 2); // This should not transfer counts but update canonical. transfer_counts_and_update_canonicals(u2); test_assert(u1->count == 1); test_assert(u2->count == 2); test_assert(u1->canonical == NULL); test_assert(u2->canonical == u2); // This should transfer the counts from 'u1' to 'u2'. transfer_counts_and_update_canonicals(u1); test_assert(u1->count == 0); test_assert(u2->count == 3); test_assert(u1->canonical == u2); test_assert(u2->canonical == u2); destroy_useq(u1); destroy_useq(u2); useq_t *u3 = new_useq(1, "{Lu[T}FOCMs}L_zx", NULL); useq_t *u4 = new_useq(2, "|kAV|Ch|RZ]h~WjCoDpX", NULL); useq_t *u5 = new_useq(2, "}lzHolUky", NULL); // Add matches to 'u3'. addmatch(u3, u4, 1, 1); addmatch(u3, u5, 1, 1); test_assert(u3->count == 1); test_assert(u4->count == 2); test_assert(u5->count == 2); transfer_counts_and_update_canonicals(u3); test_assert(u3->count == 0); test_assert(u3->count == 0); test_assert(u3->canonical == NULL); test_assert(u4->canonical == u4); test_assert(u5->canonical == u5); destroy_useq(u3); destroy_useq(u4); destroy_useq(u5); }
static void scan_match(struct matchtab *m, char *arg, uint16_t (*op)(char *)) { char *p = arg; char *b; char *work; while((b = strtok_r(p, " \t\n,", &work)) != NULL) { p = NULL; addmatch(m, op(b)); } }
static void glob_dir(glob_t* gp, globlist_t* ap) { register char* rescan; register char* prefix; register char* pat; register char* name; register int c; char* dirname; void* dirf; char first; regex_t* ire; regex_t* pre; regex_t rec; regex_t rei; int notdir; int t1; int t2; int bracket; int anymeta = ap->gl_flags & MATCH_META; int complete = 0; int err = 0; int meta = ((gp->re_flags & REG_ICASE) && *ap->gl_begin != '/') ? MATCH_META : 0; int quote = 0; int savequote = 0; char* restore1 = 0; char* restore2 = 0; regex_t* prec = 0; regex_t* prei = 0; char* matchdir = 0; int starstar = 0; if (*gp->gl_intr) { gp->gl_error = GLOB_INTR; return; } pat = rescan = ap->gl_begin; prefix = dirname = ap->gl_path + gp->gl_extra; first = (rescan == prefix); again: bracket = 0; for (;;) { switch (c = *rescan++) { case 0: if (meta) { rescan = 0; break; } if (quote) { trim(ap->gl_begin, rescan, &t1, NiL, NiL); rescan -= t1; } if (!first && !*rescan && *(rescan - 2) == gp->gl_delim) { *(rescan - 2) = 0; c = (*gp->gl_type)(gp, prefix, 0); *(rescan - 2) = gp->gl_delim; if (c == GLOB_DIR) addmatch(gp, NiL, prefix, NiL, rescan - 1, anymeta); } else if ((anymeta || !(gp->gl_flags & GLOB_NOCHECK)) && (*gp->gl_type)(gp, prefix, 0)) addmatch(gp, NiL, prefix, NiL, NiL, anymeta); return; case '[': if (!bracket) { bracket = MATCH_META; if (*rescan == '!' || *rescan == '^') rescan++; if (*rescan == ']') rescan++; } continue; case ']': meta |= bracket; continue; case '(': if (!(gp->gl_flags & GLOB_AUGMENTED)) continue; case '*': case '?': meta = MATCH_META; continue; case '\\': if (!(gp->gl_flags & GLOB_NOESCAPE)) { quote = 1; if (*rescan) rescan++; } continue; default: if (c == gp->gl_delim) { if (meta) break; pat = rescan; bracket = 0; savequote = quote; } continue; } break; } anymeta |= meta; if (matchdir) goto skip; if (pat == prefix) { prefix = 0; if (!rescan && (gp->gl_flags & GLOB_COMPLETE)) { complete = 1; dirname = 0; } else dirname = "."; } else { if (pat == prefix + 1) dirname = "/"; if (savequote) { quote = 0; trim(ap->gl_begin, pat, &t1, rescan, &t2); pat -= t1; if (rescan) rescan -= t2; } *(restore1 = pat - 1) = 0; } if (!complete && (gp->gl_flags & GLOB_STARSTAR)) while (pat[0] == '*' && pat[1] == '*' && (pat[2] == '/' || pat[2]==0)) { matchdir = pat; if (pat[2]) { pat += 3; while (*pat=='/') pat++; if (*pat) continue; } rescan = *pat?0:pat; pat = "*"; goto skip; } if (matchdir) { rescan = pat; goto again; } skip: if (rescan) *(restore2 = rescan - 1) = 0; if (rescan && !complete && (gp->gl_flags & GLOB_STARSTAR)) { register char *p = rescan; while (p[0] == '*' && p[1] == '*' && (p[2] == '/' || p[2]==0)) { rescan = p; if (starstar = (p[2]==0)) break; p += 3; while (*p=='/') p++; if (*p==0) { starstar = 2; break; } } } if (matchdir) gp->gl_starstar++; if (gp->gl_opt) pat = strcpy(gp->gl_opt, pat); for (;;) { if (complete) { if (!(dirname = (*gp->gl_nextdir)(gp, dirname))) break; prefix = streq(dirname, ".") ? (char*)0 : dirname; } if ((!starstar && !gp->gl_starstar || (*gp->gl_type)(gp, dirname, GLOB_STARSTAR) == GLOB_DIR) && (dirf = (*gp->gl_diropen)(gp, dirname))) { if (!(gp->re_flags & REG_ICASE) && ((*gp->gl_attr)(gp, dirname, 0) & GLOB_ICASE)) { if (!prei) { if (err = regcomp(&rei, pat, gp->re_flags|REG_ICASE)) break; prei = &rei; } pre = prei; if (gp->gl_ignore) { if (!gp->gl_ignorei) { if (regcomp(&gp->re_ignorei, gp->gl_fignore, gp->re_flags|REG_ICASE)) { gp->gl_error = GLOB_APPERR; break; } gp->gl_ignorei = &gp->re_ignorei; } ire = gp->gl_ignorei; } else ire = 0; } else { if (!prec) { if (err = regcomp(&rec, pat, gp->re_flags)) break; prec = &rec; } pre = prec; ire = gp->gl_ignore; } if (restore2) *restore2 = gp->gl_delim; while ((name = (*gp->gl_dirnext)(gp, dirf)) && !*gp->gl_intr) { if (notdir = (gp->gl_status & GLOB_NOTDIR)) gp->gl_status &= ~GLOB_NOTDIR; if (ire && !regexec(ire, name, 0, NiL, 0)) continue; if (matchdir && (name[0] != '.' || name[1] && (name[1] != '.' || name[2])) && !notdir) addmatch(gp, prefix, name, matchdir, NiL, anymeta); if (!regexec(pre, name, 0, NiL, 0)) { if (!rescan || !notdir) addmatch(gp, prefix, name, rescan, NiL, anymeta); if (starstar==1 || (starstar==2 && !notdir)) addmatch(gp, prefix, name, starstar==2?"":NiL, NiL, anymeta); } errno = 0; } (*gp->gl_dirclose)(gp, dirf); if (err || errno && !errorcheck(gp, dirname)) break; } else if (!complete && !errorcheck(gp, dirname)) break; if (!complete) break; if (*gp->gl_intr) { gp->gl_error = GLOB_INTR; break; } } if (restore1) *restore1 = gp->gl_delim; if (restore2) *restore2 = gp->gl_delim; if (prec) regfree(prec); if (prei) regfree(prei); if (err == REG_ESPACE) gp->gl_error = GLOB_NOSPACE; }
void findmatch(int n, int *x) { int flag = 1, delta = 1; for (int i = 0; i < n; i++) flag &= d[i] & 1; for (int i = 0; i < n-1; i++) delta *= d[i]; if (!flag) { if (n == 1) { for (int i = 0; i < d[0]; i += 2) addmatch(i, i+1); } else { flag = 1; for (int i = 0; i < n-1; i++) flag &= d[i] & 1; if (flag) { for (int i = 0; i < n-1; i++) x[i] = 0; findmatch(n-1, x); duplicate(n, delta); for (int i = 0; i < d[n-1]; i += 2) addmatch(delta*i, delta*(i+1)); } else { findmatch(n-1, x); duplicate(n, delta); } } } else { if (n == 1) { for (int i = 0; i < x[0]; i += 2) addmatch(i, i+1); for (int i = x[0]+1; i < d[0]; i += 2) addmatch(i, i+1); match[x[0]] = -1; } else if (x[n-1] & 1) { int dir = -1; if (x[n-2] == 0) dir = 1; x[n-2] += dir; findmatch(n-1, x); duplicate(n, delta); int base1 = encode(x, n-1); x[n-2] -= dir; int base = encode(x, n-1), base2 = match[base]; for (int i = 1; i < x[n-1]; i += 2) addmatch(delta*i+base, delta*(i+1)+base); for (int i = x[n-1]+1; i < d[n-1]-1; i += 2) addmatch(delta*i+base, delta*(i+1)+base); for (int i = 0; i < d[n-1]-1; i += 2) addmatch(delta*i+base1, delta*(i+1)+base1); addmatch(delta*(d[n-1]-1)+base1, delta*(d[n-1]-1)+base); for (int i = 1; i < d[n-1]; i += 2) addmatch(delta*i+base2, delta*(i+1)+base2); addmatch(base, base2); match[x[n-1]*delta+base] = -1; } else { findmatch(n-1, x); duplicate(n, delta); int base = encode(x, n-1); for (int i = 0; i < x[n-1]; i += 2) addmatch(delta*i+base, delta*(i+1)+base); for (int i = x[n-1]+1; i < d[n-1]; i += 2) addmatch(delta*i+base, delta*(i+1)+base); match[x[n-1]*delta+base] = -1; } } }
void test_starcode_4 (void) // Test 'canonical_order'. { useq_t *u1 = new_useq(1, "ABCD", NULL); useq_t *u2 = new_useq(2, "EFGH", NULL); test_assert_critical(u1 != NULL); test_assert_critical(u2 != NULL); // 'u1' and 'u2' have no canonical, so the // comparison is alphabetical. test_assert(canonical_order(&u1, &u2) < 0); test_assert(canonical_order(&u2, &u1) > 0); // Add match to 'u1', and update canonicals. addmatch(u1, u2, 1, 1); test_assert_critical(u1->matches != NULL); transfer_counts_and_update_canonicals(u1); test_assert(u1->count == 0); test_assert(u2->count == 3); // Now 'u1' and 'u2' have the same canonical ('u2') // so the comparison is again alphabetical. test_assert(canonical_order(&u1, &u2) < 0); test_assert(canonical_order(&u2, &u1) > 0); useq_t *u3 = new_useq(1, "CDEF", NULL); useq_t *u4 = new_useq(2, "GHIJ", NULL); test_assert_critical(u3 != NULL); test_assert_critical(u4 != NULL); // Comparisons with 'u1' or with 'u2' give the same // results because they have the same canonical ('u2'). test_assert(canonical_order(&u1, &u3) == -1); test_assert(canonical_order(&u2, &u3) == -1); test_assert(canonical_order(&u3, &u1) == 1); test_assert(canonical_order(&u3, &u2) == 1); test_assert(canonical_order(&u1, &u4) == -1); test_assert(canonical_order(&u2, &u4) == -1); test_assert(canonical_order(&u4, &u1) == 1); test_assert(canonical_order(&u4, &u2) == 1); // Comparisons between 'u3' and 'u4' are alphabetical. test_assert(canonical_order(&u3, &u4) < 0); test_assert(canonical_order(&u4, &u3) > 0); // Add match to 'u3', and update canonicals. addmatch(u3, u4, 1, 1); test_assert_critical(u3->matches != NULL); transfer_counts_and_update_canonicals(u3); test_assert(u3->count == 0); test_assert(u4->count == 3); // Now canonicals ('u2' and 'u4') have the same counts // so comparisons are always alphabetical. test_assert(canonical_order(&u1, &u3) < 0); test_assert(canonical_order(&u2, &u3) < 0); test_assert(canonical_order(&u3, &u1) > 0); test_assert(canonical_order(&u3, &u2) > 0); test_assert(canonical_order(&u1, &u4) < 0); test_assert(canonical_order(&u2, &u4) < 0); test_assert(canonical_order(&u4, &u1) > 0); test_assert(canonical_order(&u4, &u2) > 0); test_assert(canonical_order(&u3, &u4) < 0); test_assert(canonical_order(&u4, &u3) > 0); useq_t *u5 = new_useq(1, "CDEF", NULL); useq_t *u6 = new_useq(3, "GHIJ", NULL); test_assert_critical(u5 != NULL); test_assert_critical(u6 != NULL); // Comparisons between canonicals. test_assert(canonical_order(&u1, &u5) == -1); test_assert(canonical_order(&u2, &u5) == -1); test_assert(canonical_order(&u5, &u1) == 1); test_assert(canonical_order(&u5, &u2) == 1); test_assert(canonical_order(&u1, &u6) == -1); test_assert(canonical_order(&u2, &u6) == -1); test_assert(canonical_order(&u6, &u1) == 1); test_assert(canonical_order(&u6, &u2) == 1); test_assert(canonical_order(&u3, &u5) == -1); test_assert(canonical_order(&u4, &u5) == -1); test_assert(canonical_order(&u5, &u3) == 1); test_assert(canonical_order(&u5, &u4) == 1); test_assert(canonical_order(&u3, &u6) == -1); test_assert(canonical_order(&u4, &u6) == -1); test_assert(canonical_order(&u6, &u3) == 1); test_assert(canonical_order(&u6, &u4) == 1); // Alphabetical comparisons. test_assert(canonical_order(&u5, &u6) < 0); test_assert(canonical_order(&u6, &u5) > 0); // Add match to 'u5', and update canonicals. addmatch(u5, u6, 1, 1); test_assert_critical(u5->matches != NULL); transfer_counts_and_update_canonicals(u5); test_assert(u5->count == 0); test_assert(u6->count == 4); // Comparisons between canonicals ('u2', 'u4', 'u6'). test_assert(canonical_order(&u1, &u5) == 1); test_assert(canonical_order(&u2, &u5) == 1); test_assert(canonical_order(&u5, &u1) == -1); test_assert(canonical_order(&u5, &u2) == -1); test_assert(canonical_order(&u1, &u6) == 1); test_assert(canonical_order(&u2, &u6) == 1); test_assert(canonical_order(&u6, &u1) == -1); test_assert(canonical_order(&u6, &u2) == -1); test_assert(canonical_order(&u3, &u5) == 1); test_assert(canonical_order(&u4, &u5) == 1); test_assert(canonical_order(&u5, &u3) == -1); test_assert(canonical_order(&u5, &u4) == -1); test_assert(canonical_order(&u3, &u6) == 1); test_assert(canonical_order(&u4, &u6) == 1); test_assert(canonical_order(&u6, &u3) == -1); test_assert(canonical_order(&u6, &u4) == -1); // Alphabetical. test_assert(canonical_order(&u5, &u6) < 0); test_assert(canonical_order(&u6, &u5) > 0); useq_t *useq_array[6] = {u1,u2,u3,u4,u5,u6}; useq_t *sorted[6] = {u5,u6,u1,u2,u3,u4}; qsort(useq_array, 6, sizeof(useq_t *), canonical_order); for (int i = 0 ; i < 6 ; i++) { test_assert(useq_array[i] == sorted[i]); } destroy_useq(u1); destroy_useq(u2); destroy_useq(u3); destroy_useq(u4); destroy_useq(u5); destroy_useq(u6); }