summaryrefslogtreecommitdiffstats
path: root/contrib/less/pattern.c
diff options
context:
space:
mode:
authordelphij <delphij@FreeBSD.org>2009-07-29 09:20:32 +0000
committerdelphij <delphij@FreeBSD.org>2009-07-29 09:20:32 +0000
commita1420f2d09d95e286325db1a123862cb8a6fb33d (patch)
tree4fdfa6d784030f8906ba6b58fa39cec909b27661 /contrib/less/pattern.c
parent7b17971146d9d04f6fdfc56456eda87bddfb201f (diff)
parenta169eab989211273bac7f266a725febc6d6767ef (diff)
downloadFreeBSD-src-a1420f2d09d95e286325db1a123862cb8a6fb33d.zip
FreeBSD-src-a1420f2d09d95e286325db1a123862cb8a6fb33d.tar.gz
Update less to v436. This is considered as a bugfix release from vendor.
Major changes from v429: * Don't pass "-" to non-pipe LESSOPEN unless it starts with "-". * Allow a fraction as the argument to the -# (--shift) option. * Fix highlight bug when underlined/overstruck text matches at end of line. * Fix non-regex searches with ctrl-R. Approved by: re (kensmith, kib)
Diffstat (limited to 'contrib/less/pattern.c')
-rw-r--r--contrib/less/pattern.c322
1 files changed, 322 insertions, 0 deletions
diff --git a/contrib/less/pattern.c b/contrib/less/pattern.c
new file mode 100644
index 0000000..f1fb3ef
--- /dev/null
+++ b/contrib/less/pattern.c
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 1984-2009 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 about less, or for information on how to
+ * contact the author, 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) == 0)
+ {
+#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;
+ const 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_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_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
+#if NO_REGEX
+ return (search_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_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 (search_type & SRCH_NO_REGEX)
+ matched = match(tpattern, strlen(tpattern), line, line_len, sp, ep);
+ else
+ {
+#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
+#if NO_REGEX
+ matched = match(tpattern, strlen(tpattern), line, line_len, sp, ep);
+#endif
+ }
+ matched = (!(search_type & SRCH_NO_MATCH) && matched) ||
+ ((search_type & SRCH_NO_MATCH) && !matched);
+ return (matched);
+}
+
OpenPOWER on IntegriCloud