VirtualBox

source: kBuild/vendor/grep/2.12/src/pcresearch.c@ 2595

Last change on this file since 2595 was 2595, checked in by bird, 12 years ago

gnu grep version 2.12 (grep-2.12.tar.xz, md5sum=8d2f0346d08b13c18afb81f0e8aa1e2f)

  • Property svn:eol-style set to native
File size: 5.3 KB
Line 
1/* pcresearch.c - searching subroutines using PCRE for grep.
2 Copyright 2000, 2007, 2009-2012 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
17 02110-1301, USA. */
18
19/* Written August 1992 by Mike Haertel. */
20
21#include <config.h>
22#include "search.h"
23#if HAVE_PCRE_H
24# include <pcre.h>
25#elif HAVE_PCRE_PCRE_H
26# include <pcre/pcre.h>
27#endif
28
29#if HAVE_LIBPCRE
30/* Compiled internal form of a Perl regular expression. */
31static pcre *cre;
32
33/* Additional information about the pattern. */
34static pcre_extra *extra;
35#endif
36
37void
38Pcompile (char const *pattern, size_t size)
39{
40#if !HAVE_LIBPCRE
41 error (EXIT_TROUBLE, 0, "%s",
42 _("support for the -P option is not compiled into "
43 "this --disable-perl-regexp binary"));
44#else
45 int e;
46 char const *ep;
47 char *re = xnmalloc (4, size + 7);
48 int flags = PCRE_MULTILINE | (match_icase ? PCRE_CASELESS : 0);
49 char const *patlim = pattern + size;
50 char *n = re;
51 char const *p;
52 char const *pnul;
53
54 /* FIXME: Remove these restrictions. */
55 if (memchr(pattern, '\n', size))
56 error (EXIT_TROUBLE, 0, _("the -P option only supports a single pattern"));
57
58 *n = '\0';
59 if (match_lines)
60 strcpy (n, "^(");
61 if (match_words)
62 strcpy (n, "\\b(");
63 n += strlen (n);
64
65 /* The PCRE interface doesn't allow NUL bytes in the pattern, so
66 replace each NUL byte in the pattern with the four characters
67 "\000", removing a preceding backslash if there are an odd
68 number of backslashes before the NUL.
69
70 FIXME: This method does not work with some multibyte character
71 encodings, notably Shift-JIS, where a multibyte character can end
72 in a backslash byte. */
73 for (p = pattern; (pnul = memchr (p, '\0', patlim - p)); p = pnul + 1)
74 {
75 memcpy (n, p, pnul - p);
76 n += pnul - p;
77 for (p = pnul; pattern < p && p[-1] == '\\'; p--)
78 continue;
79 n -= (pnul - p) & 1;
80 strcpy (n, "\\000");
81 n += 4;
82 }
83
84 memcpy (n, p, patlim - p);
85 n += patlim - p;
86 *n = '\0';
87 if (match_words)
88 strcpy (n, ")\\b");
89 if (match_lines)
90 strcpy (n, ")$");
91
92 cre = pcre_compile (re, flags, &ep, &e, pcre_maketables ());
93 if (!cre)
94 error (EXIT_TROUBLE, 0, "%s", ep);
95
96 extra = pcre_study (cre, 0, &ep);
97 if (ep)
98 error (EXIT_TROUBLE, 0, "%s", ep);
99
100 free (re);
101#endif
102}
103
104size_t
105Pexecute (char const *buf, size_t size, size_t *match_size,
106 char const *start_ptr)
107{
108#if !HAVE_LIBPCRE
109 /* We can't get here, because Pcompile would have been called earlier. */
110 error (EXIT_TROUBLE, 0, _("internal error"));
111 return -1;
112#else
113 /* This array must have at least two elements; everything after that
114 is just for performance improvement in pcre_exec. */
115 int sub[300];
116
117 const char *line_buf, *line_end, *line_next;
118 int e = PCRE_ERROR_NOMATCH;
119 ptrdiff_t start_ofs = start_ptr ? start_ptr - buf : 0;
120
121 /* PCRE can't limit the matching to single lines, therefore we have to
122 match each line in the buffer separately. */
123 for (line_next = buf;
124 e == PCRE_ERROR_NOMATCH && line_next < buf + size;
125 start_ofs -= line_next - line_buf)
126 {
127 line_buf = line_next;
128 line_end = memchr (line_buf, eolbyte, (buf + size) - line_buf);
129 if (line_end == NULL)
130 line_next = line_end = buf + size;
131 else
132 line_next = line_end + 1;
133
134 if (start_ptr && start_ptr >= line_end)
135 continue;
136
137 if (INT_MAX < line_end - line_buf)
138 error (EXIT_TROUBLE, 0, _("exceeded PCRE's line length limit"));
139
140 e = pcre_exec (cre, extra, line_buf, line_end - line_buf,
141 start_ofs < 0 ? 0 : start_ofs, 0,
142 sub, sizeof sub / sizeof *sub);
143 }
144
145 if (e <= 0)
146 {
147 switch (e)
148 {
149 case PCRE_ERROR_NOMATCH:
150 return -1;
151
152 case PCRE_ERROR_NOMEMORY:
153 error (EXIT_TROUBLE, 0, _("memory exhausted"));
154
155 case PCRE_ERROR_MATCHLIMIT:
156 error (EXIT_TROUBLE, 0,
157 _("exceeded PCRE's backtracking limit"));
158
159 default:
160 abort ();
161 }
162 }
163 else
164 {
165 /* Narrow down to the line we've found. */
166 char const *beg = line_buf + sub[0];
167 char const *end = line_buf + sub[1];
168 char const *buflim = buf + size;
169 char eol = eolbyte;
170 if (!start_ptr)
171 {
172 /* FIXME: The case when '\n' is not found indicates a bug:
173 Since grep is line oriented, the match should never contain
174 a newline, so there _must_ be a newline following.
175 */
176 if (!(end = memchr (end, eol, buflim - end)))
177 end = buflim;
178 else
179 end++;
180 while (buf < beg && beg[-1] != eol)
181 --beg;
182 }
183
184 *match_size = end - beg;
185 return beg - buf;
186 }
187#endif
188}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette