📄 lregex.c
字号:
{ const char* k = kinds; if (k [0] != ',' && (k [1] == ',' || k [1] == '\0')) *kind = *k++; else *kind = 'r'; if (*k == ',') ++k; if (k [0] == '\0') *kindName = eStrdup ("regex"); else { const char *const comma = strchr (k, ','); if (comma == NULL) *kindName = eStrdup (k); else { *kindName = (char*) eMalloc (comma - k + 1); strncpy (*kindName, k, comma - k); (*kindName) [comma - k] = '\0'; k = comma + 1; if (k [0] != '\0') *description = eStrdup (k); } } }}static void printRegexKind (const regexPattern *pat, unsigned int i, boolean indent){ const struct sKind *const kind = &pat [i].u.tag.kind; const char *const indentation = indent ? " " : ""; Assert (pat [i].type == PTRN_TAG); printf ("%s%c %s %s\n", indentation, kind->letter != '\0' ? kind->letter : '?', kind->description != NULL ? kind->description : kind->name, kind->enabled ? "" : " [off]");}static void processLanguageRegex (const langType language, const char* const parameter){ if (parameter == NULL || parameter [0] == '\0') clearPatternSet (language); else if (parameter [0] != '@') addLanguageRegex (language, parameter); else if (! doesFileExist (parameter + 1)) error (WARNING, "cannot open regex file"); else { const char* regexfile = parameter + 1; FILE* const fp = fopen (regexfile, "r"); if (fp == NULL) error (WARNING | PERROR, regexfile); else { vString* const regex = vStringNew (); while (readLine (regex, fp)) addLanguageRegex (language, vStringValue (regex)); fclose (fp); vStringDelete (regex); } }}/** Regex pattern matching*/#if defined (POSIX_REGEX)static vString* substitute ( const char* const in, const char* out, const int nmatch, const regmatch_t* const pmatch){ vString* result = vStringNew (); const char* p; for (p = out ; *p != '\0' ; p++) { if (*p == '\\' && isdigit ((int) *++p)) { const int dig = *p - '0'; if (0 < dig && dig < nmatch && pmatch [dig].rm_so != -1) { const int diglen = pmatch [dig].rm_eo - pmatch [dig].rm_so; vStringNCatS (result, in + pmatch [dig].rm_so, diglen); } } else if (*p != '\n' && *p != '\r') vStringPut (result, *p); } vStringTerminate (result); return result;}static void matchTagPattern (const vString* const line, const regexPattern* const patbuf, const regmatch_t* const pmatch){ vString *const name = substitute (vStringValue (line), patbuf->u.tag.name_pattern, BACK_REFERENCE_COUNT, pmatch); vStringStripLeading (name); vStringStripTrailing (name); if (vStringLength (name) > 0) makeRegexTag (name, &patbuf->u.tag.kind); else error (WARNING, "%s:%ld: null expansion of name pattern \"%s\"", getInputFileName (), getInputLineNumber (), patbuf->u.tag.name_pattern); vStringDelete (name);}static void matchCallbackPattern ( const vString* const line, const regexPattern* const patbuf, const regmatch_t* const pmatch){ regexMatch matches [BACK_REFERENCE_COUNT]; unsigned int count = 0; int i; for (i = 0 ; i < BACK_REFERENCE_COUNT && pmatch [i].rm_so != -1 ; ++i) { matches [i].start = pmatch [i].rm_so; matches [i].length = pmatch [i].rm_eo - pmatch [i].rm_so; ++count; } patbuf->u.callback.function (vStringValue (line), matches, count);}static boolean matchRegexPattern (const vString* const line, const regexPattern* const patbuf){ boolean result = FALSE; regmatch_t pmatch [BACK_REFERENCE_COUNT]; const int match = regexec (patbuf->pattern, vStringValue (line), BACK_REFERENCE_COUNT, pmatch, 0); if (match == 0) { result = TRUE; if (patbuf->type == PTRN_TAG) matchTagPattern (line, patbuf, pmatch); else if (patbuf->type == PTRN_CALLBACK) matchCallbackPattern (line, patbuf, pmatch); else { Assert ("invalid pattern type" == NULL); result = FALSE; } } return result;}#endif/* PUBLIC INTERFACE *//* Match against all patterns for specified language. Returns true if at least * on pattern matched. */extern boolean matchRegex (const vString* const line, const langType language){ boolean result = FALSE; if (language != LANG_IGNORE && language <= SetUpper && Sets [language].count > 0) { const patternSet* const set = Sets + language; unsigned int i; for (i = 0 ; i < set->count ; ++i) if (matchRegexPattern (line, set->patterns + i)) result = TRUE; } return result;}extern void findRegexTags (void){ /* merely read all lines of the file */ while (fileReadLine () != NULL) ;}#endif /* HAVE_REGEX */extern void addTagRegex ( const langType language __unused__, const char* const regex __unused__, const char* const name __unused__, const char* const kinds __unused__, const char* const flags __unused__){#ifdef HAVE_REGEX Assert (regex != NULL); Assert (name != NULL); if (! regexBroken) { regex_t* const cp = compileRegex (regex, flags); if (cp != NULL) { char kind; char* kindName; char* description; parseKinds (kinds, &kind, &kindName, &description); addCompiledTagPattern (language, cp, eStrdup (name), kind, kindName, description); } }#endif}extern void addCallbackRegex ( const langType language __unused__, const char* const regex __unused__, const char* const flags __unused__, const regexCallback callback __unused__){#ifdef HAVE_REGEX Assert (regex != NULL); if (! regexBroken) { regex_t* const cp = compileRegex (regex, flags); if (cp != NULL) addCompiledCallbackPattern (language, cp, callback); }#endif}extern void addLanguageRegex ( const langType language __unused__, const char* const regex __unused__){#ifdef HAVE_REGEX if (! regexBroken) { char *const regex_pat = eStrdup (regex); char *name, *kinds, *flags; if (parseTagRegex (regex_pat, &name, &kinds, &flags)) { addTagRegex (language, regex_pat, name, kinds, flags); eFree (regex_pat); } }#endif}/** Regex option parsing*/extern boolean processRegexOption (const char *const option, const char *const parameter __unused__){ boolean handled = FALSE; const char* const dash = strchr (option, '-'); if (dash != NULL && strncmp (option, "regex", dash - option) == 0) {#ifdef HAVE_REGEX langType language; language = getNamedLanguage (dash + 1); if (language == LANG_IGNORE) error (WARNING, "unknown language in --%s option", option); else processLanguageRegex (language, parameter);#else error (WARNING, "regex support not available; required for --%s option", option);#endif handled = TRUE; } return handled;}extern void disableRegexKinds (const langType language __unused__){#ifdef HAVE_REGEX if (language <= SetUpper && Sets [language].count > 0) { patternSet* const set = Sets + language; unsigned int i; for (i = 0 ; i < set->count ; ++i) if (set->patterns [i].type == PTRN_TAG) set->patterns [i].u.tag.kind.enabled = FALSE; }#endif}extern boolean enableRegexKind ( const langType language __unused__, const int kind __unused__, const boolean mode __unused__){ boolean result = FALSE;#ifdef HAVE_REGEX if (language <= SetUpper && Sets [language].count > 0) { patternSet* const set = Sets + language; unsigned int i; for (i = 0 ; i < set->count ; ++i) if (set->patterns [i].type == PTRN_TAG && set->patterns [i].u.tag.kind.letter == kind) { set->patterns [i].u.tag.kind.enabled = mode; result = TRUE; } }#endif return result;}extern void printRegexKinds (const langType language __unused__, boolean indent){#ifdef HAVE_REGEX if (language <= SetUpper && Sets [language].count > 0) { patternSet* const set = Sets + language; unsigned int i; for (i = 0 ; i < set->count ; ++i) if (set->patterns [i].type == PTRN_TAG) printRegexKind (set->patterns, i, indent); }#endif}extern void freeRegexResources (void){#ifdef HAVE_REGEX int i; for (i = 0 ; i <= SetUpper ; ++i) clearPatternSet (i); if (Sets != NULL) eFree (Sets); Sets = NULL; SetUpper = -1;#endif}/* Check for broken regcomp() on Cygwin */extern void checkRegex (void){#if defined (HAVE_REGEX) && defined (CHECK_REGCOMP) regex_t patbuf; int errcode; if (regcomp (&patbuf, "/hello/", 0) != 0) { error (WARNING, "Disabling broken regex"); regexBroken = TRUE; }#endif}/* vi:set tabstop=8 shiftwidth=4: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -