summaryrefslogtreecommitdiff
path: root/pattern.c
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2012-07-21 20:40:00 +0000
committerLorry <lorry@roadtrain.codethink.co.uk>2012-09-24 16:52:48 +0000
commit09a405d8f652b56944c93ebf5c673cdfe5319b04 (patch)
tree9cc4518b0a21096735b20ac3204a6fa032f1c566 /pattern.c
downloadless-master.tar.gz
Imported from /srv/lorry/lorry-area/less/less-451.tar.gz.HEADless-451masterbaserock/morph
Diffstat (limited to 'pattern.c')
-rwxr-xr-xpattern.c364
1 files changed, 364 insertions, 0 deletions
diff --git a/pattern.c b/pattern.c
new file mode 100755
index 0000000..fa26b99
--- /dev/null
+++ b/pattern.c
@@ -0,0 +1,364 @@
+/*
+ * Copyright (C) 1984-2012 Mark Nudelman
+ *
+ * You may distribute under the terms of either the GNU General Public
+ * License or the Less License, as specified in the README file.
+ *
+ * For more information, see the README file.
+ */
+
+/*
+ * Routines to do pattern matching.
+ */
+
+#include "less.h"
+#include "pattern.h"
+
+extern int caseless;
+
+/*
+ * Compile a search pattern, for future use by match_pattern.
+ */
+ static int
+compile_pattern2(pattern, search_type, comp_pattern)
+ char *pattern;
+ int search_type;
+ void **comp_pattern;
+{
+ if (search_type & SRCH_NO_REGEX)
+ return (0);
+ {
+#if HAVE_GNU_REGEX
+ struct re_pattern_buffer *comp = (struct re_pattern_buffer *)
+ ecalloc(1, sizeof(struct re_pattern_buffer));
+ struct re_pattern_buffer **pcomp =
+ (struct re_pattern_buffer **) comp_pattern;
+ re_set_syntax(RE_SYNTAX_POSIX_EXTENDED);
+ if (re_compile_pattern(pattern, strlen(pattern), comp))
+ {
+ free(comp);
+ error("Invalid pattern", NULL_PARG);
+ return (-1);
+ }
+ if (*pcomp != NULL)
+ regfree(*pcomp);
+ *pcomp = comp;
+#endif
+#if HAVE_POSIX_REGCOMP
+ regex_t *comp = (regex_t *) ecalloc(1, sizeof(regex_t));
+ regex_t **pcomp = (regex_t **) comp_pattern;
+ if (regcomp(comp, pattern, REGCOMP_FLAG))
+ {
+ free(comp);
+ error("Invalid pattern", NULL_PARG);
+ return (-1);
+ }
+ if (*pcomp != NULL)
+ regfree(*pcomp);
+ *pcomp = comp;
+#endif
+#if HAVE_PCRE
+ pcre *comp;
+ pcre **pcomp = (pcre **) comp_pattern;
+ constant char *errstring;
+ int erroffset;
+ PARG parg;
+ comp = pcre_compile(pattern, 0,
+ &errstring, &erroffset, NULL);
+ if (comp == NULL)
+ {
+ parg.p_string = (char *) errstring;
+ error("%s", &parg);
+ return (-1);
+ }
+ *pcomp = comp;
+#endif
+#if HAVE_RE_COMP
+ PARG parg;
+ int *pcomp = (int *) comp_pattern;
+ if ((parg.p_string = re_comp(pattern)) != NULL)
+ {
+ error("%s", &parg);
+ return (-1);
+ }
+ *pcomp = 1;
+#endif
+#if HAVE_REGCMP
+ char *comp;
+ char **pcomp = (char **) comp_pattern;
+ if ((comp = regcmp(pattern, 0)) == NULL)
+ {
+ error("Invalid pattern", NULL_PARG);
+ return (-1);
+ }
+ if (pcomp != NULL)
+ free(*pcomp);
+ *pcomp = comp;
+#endif
+#if HAVE_V8_REGCOMP
+ struct regexp *comp;
+ struct regexp **pcomp = (struct regexp **) comp_pattern;
+ if ((comp = regcomp(pattern)) == NULL)
+ {
+ /*
+ * regcomp has already printed an error message
+ * via regerror().
+ */
+ return (-1);
+ }
+ if (*pcomp != NULL)
+ free(*pcomp);
+ *pcomp = comp;
+#endif
+ }
+ return (0);
+}
+
+/*
+ * Like compile_pattern2, but convert the pattern to lowercase if necessary.
+ */
+ public int
+compile_pattern(pattern, search_type, comp_pattern)
+ char *pattern;
+ int search_type;
+ void **comp_pattern;
+{
+ char *cvt_pattern;
+ int result;
+
+ if (caseless != OPT_ONPLUS)
+ cvt_pattern = pattern;
+ else
+ {
+ cvt_pattern = (char*) ecalloc(1, cvt_length(strlen(pattern), CVT_TO_LC));
+ cvt_text(cvt_pattern, pattern, (int *)NULL, (int *)NULL, CVT_TO_LC);
+ }
+ result = compile_pattern2(cvt_pattern, search_type, comp_pattern);
+ if (cvt_pattern != pattern)
+ free(cvt_pattern);
+ return (result);
+}
+
+/*
+ * Forget that we have a compiled pattern.
+ */
+ public void
+uncompile_pattern(pattern)
+ void **pattern;
+{
+#if HAVE_GNU_REGEX
+ struct re_pattern_buffer **pcomp = (struct re_pattern_buffer **) pattern;
+ if (*pcomp != NULL)
+ regfree(*pcomp);
+ *pcomp = NULL;
+#endif
+#if HAVE_POSIX_REGCOMP
+ regex_t **pcomp = (regex_t **) pattern;
+ if (*pcomp != NULL)
+ regfree(*pcomp);
+ *pcomp = NULL;
+#endif
+#if HAVE_PCRE
+ pcre **pcomp = (pcre **) pattern;
+ if (*pcomp != NULL)
+ pcre_free(*pcomp);
+ *pcomp = NULL;
+#endif
+#if HAVE_RE_COMP
+ int *pcomp = (int *) pattern;
+ *pcomp = 0;
+#endif
+#if HAVE_REGCMP
+ char **pcomp = (char **) pattern;
+ if (*pcomp != NULL)
+ free(*pcomp);
+ *pcomp = NULL;
+#endif
+#if HAVE_V8_REGCOMP
+ struct regexp **pcomp = (struct regexp **) pattern;
+ if (*pcomp != NULL)
+ free(*pcomp);
+ *pcomp = NULL;
+#endif
+}
+
+/*
+ * Is a compiled pattern null?
+ */
+ public int
+is_null_pattern(pattern)
+ void *pattern;
+{
+#if HAVE_GNU_REGEX
+ return (pattern == NULL);
+#endif
+#if HAVE_POSIX_REGCOMP
+ return (pattern == NULL);
+#endif
+#if HAVE_PCRE
+ return (pattern == NULL);
+#endif
+#if HAVE_RE_COMP
+ return (pattern == 0);
+#endif
+#if HAVE_REGCMP
+ return (pattern == NULL);
+#endif
+#if HAVE_V8_REGCOMP
+ return (pattern == NULL);
+#endif
+}
+
+/*
+ * Simple pattern matching function.
+ * It supports no metacharacters like *, etc.
+ */
+ static int
+match(pattern, pattern_len, buf, buf_len, pfound, pend)
+ char *pattern;
+ int pattern_len;
+ char *buf;
+ int buf_len;
+ char **pfound, **pend;
+{
+ register char *pp, *lp;
+ register char *pattern_end = pattern + pattern_len;
+ register char *buf_end = buf + buf_len;
+
+ for ( ; buf < buf_end; buf++)
+ {
+ for (pp = pattern, lp = buf; *pp == *lp; pp++, lp++)
+ if (pp == pattern_end || lp == buf_end)
+ break;
+ if (pp == pattern_end)
+ {
+ if (pfound != NULL)
+ *pfound = buf;
+ if (pend != NULL)
+ *pend = lp;
+ return (1);
+ }
+ }
+ return (0);
+}
+
+/*
+ * Perform a pattern match with the previously compiled pattern.
+ * Set sp and ep to the start and end of the matched string.
+ */
+ public int
+match_pattern(pattern, tpattern, line, line_len, sp, ep, notbol, search_type)
+ void *pattern;
+ char *tpattern;
+ char *line;
+ int line_len;
+ char **sp;
+ char **ep;
+ int notbol;
+ int search_type;
+{
+ int matched;
+#if HAVE_GNU_REGEX
+ struct re_pattern_buffer *spattern = (struct re_pattern_buffer *) pattern;
+#endif
+#if HAVE_POSIX_REGCOMP
+ regex_t *spattern = (regex_t *) pattern;
+#endif
+#if HAVE_PCRE
+ pcre *spattern = (pcre *) pattern;
+#endif
+#if HAVE_RE_COMP
+ int spattern = (int) pattern;
+#endif
+#if HAVE_REGCMP
+ char *spattern = (char *) pattern;
+#endif
+#if HAVE_V8_REGCOMP
+ struct regexp *spattern = (struct regexp *) pattern;
+#endif
+
+#if NO_REGEX
+ search_type |= SRCH_NO_REGEX;
+#endif
+ if (search_type & SRCH_NO_REGEX)
+ matched = match(tpattern, strlen(tpattern), line, line_len, sp, ep);
+ else
+ {
+#if HAVE_GNU_REGEX
+ {
+ struct re_registers search_regs;
+ regoff_t *starts = (regoff_t *) ecalloc(1, sizeof (regoff_t));
+ regoff_t *ends = (regoff_t *) ecalloc(1, sizeof (regoff_t));
+ spattern->not_bol = notbol;
+ re_set_registers(spattern, &search_regs, 1, starts, ends);
+ matched = re_search(spattern, line, line_len, 0, line_len, &search_regs) >= 0;
+ if (matched)
+ {
+ *sp = line + search_regs.start[0];
+ *ep = line + search_regs.end[0];
+ }
+ free(starts);
+ free(ends);
+ }
+#endif
+#if HAVE_POSIX_REGCOMP
+ {
+ regmatch_t rm;
+ int flags = (notbol) ? REG_NOTBOL : 0;
+ matched = !regexec(spattern, line, 1, &rm, flags);
+ if (matched)
+ {
+#ifndef __WATCOMC__
+ *sp = line + rm.rm_so;
+ *ep = line + rm.rm_eo;
+#else
+ *sp = rm.rm_sp;
+ *ep = rm.rm_ep;
+#endif
+ }
+ }
+#endif
+#if HAVE_PCRE
+ {
+ int flags = (notbol) ? PCRE_NOTBOL : 0;
+ int ovector[3];
+ matched = pcre_exec(spattern, NULL, line, line_len,
+ 0, flags, ovector, 3) >= 0;
+ if (matched)
+ {
+ *sp = line + ovector[0];
+ *ep = line + ovector[1];
+ }
+ }
+#endif
+#if HAVE_RE_COMP
+ matched = (re_exec(line) == 1);
+ /*
+ * re_exec doesn't seem to provide a way to get the matched string.
+ */
+ *sp = *ep = NULL;
+#endif
+#if HAVE_REGCMP
+ *ep = regex(spattern, line);
+ matched = (*ep != NULL);
+ if (matched)
+ *sp = __loc1;
+#endif
+#if HAVE_V8_REGCOMP
+#if HAVE_REGEXEC2
+ matched = regexec2(spattern, line, notbol);
+#else
+ matched = regexec(spattern, line);
+#endif
+ if (matched)
+ {
+ *sp = spattern->startp[0];
+ *ep = spattern->endp[0];
+ }
+#endif
+ }
+ matched = (!(search_type & SRCH_NO_MATCH) && matched) ||
+ ((search_type & SRCH_NO_MATCH) && !matched);
+ return (matched);
+}
+