1 /* Construct a regular expression from a literal string.
2 Copyright (C) 1995, 2010-2013 Free Software Foundation, Inc.
3 Written by Bruno Haible <haible@clisp.cons.org>, 2010.
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 #include "regex-quote.h"
28 /* Characters that are special in a BRE. */
29 static const char bre_special[] = "$^.*[]\\";
31 /* Characters that are special in an ERE. */
32 static const char ere_special[] = "$^.*[]\\+?{}()|";
34 struct regex_quote_spec
35 regex_quote_spec_posix (int cflags, bool anchored)
37 struct regex_quote_spec result;
39 strcpy (result.special, cflags != 0 ? ere_special : bre_special);
40 result.multibyte = true;
41 result.anchored = anchored;
46 /* Syntax bit values, defined in GNU <regex.h>. We don't include it here,
47 otherwise this module would need to depend on gnulib module 'regex'. */
48 #define RE_BK_PLUS_QM 0x00000002
49 #define RE_INTERVALS 0x00000200
50 #define RE_LIMITED_OPS 0x00000400
51 #define RE_NEWLINE_ALT 0x00000800
52 #define RE_NO_BK_BRACES 0x00001000
53 #define RE_NO_BK_PARENS 0x00002000
54 #define RE_NO_BK_VBAR 0x00008000
56 struct regex_quote_spec
57 regex_quote_spec_gnu (unsigned long /*reg_syntax_t*/ syntax, bool anchored)
59 struct regex_quote_spec result;
63 memcpy (p, bre_special, sizeof (bre_special) - 1);
64 p += sizeof (bre_special) - 1;
65 if ((syntax & RE_LIMITED_OPS) == 0 && (syntax & RE_BK_PLUS_QM) == 0)
70 if ((syntax & RE_INTERVALS) != 0 && (syntax & RE_NO_BK_BRACES) != 0)
75 if ((syntax & RE_NO_BK_PARENS) != 0)
80 if ((syntax & RE_LIMITED_OPS) == 0 && (syntax & RE_NO_BK_VBAR) != 0)
82 if ((syntax & RE_NEWLINE_ALT) != 0)
86 result.multibyte = true;
87 result.anchored = anchored;
92 /* Characters that are special in a PCRE. */
93 static const char pcre_special[] = "$^.*[]\\+?{}()|";
95 /* Options bit values, defined in <pcre.h>. We don't include it here, because
96 it is not a standard header. */
97 #define PCRE_ANCHORED 0x00000010
98 #define PCRE_EXTENDED 0x00000008
100 struct regex_quote_spec
101 regex_quote_spec_pcre (int options, bool anchored)
103 struct regex_quote_spec result;
107 memcpy (p, bre_special, sizeof (pcre_special) - 1);
108 p += sizeof (pcre_special) - 1;
109 if (options & PCRE_EXTENDED)
121 /* PCRE regular expressions consist of UTF-8 characters of options contains
122 PCRE_UTF8 and of single bytes otherwise. */
123 result.multibyte = false;
124 /* If options contains PCRE_ANCHORED, the anchoring is implicit. */
125 result.anchored = (options & PCRE_ANCHORED ? 0 : anchored);
131 regex_quote_length (const char *string, const struct regex_quote_spec *spec)
133 const char *special = spec->special;
138 length += 2; /* for '^' at the beginning and '$' at the end */
141 mbui_iterator_t iter;
143 for (mbui_init (iter, string); mbui_avail (iter); mbui_advance (iter))
145 /* We know that special contains only ASCII characters. */
146 if (mb_len (mbui_cur (iter)) == 1
147 && strchr (special, * mbui_cur_ptr (iter)))
149 length += mb_len (mbui_cur (iter));
156 for (iter = string; *iter != '\0'; iter++)
158 if (strchr (special, *iter))
168 regex_quote_copy (char *p, const char *string, const struct regex_quote_spec *spec)
170 const char *special = spec->special;
176 mbui_iterator_t iter;
178 for (mbui_init (iter, string); mbui_avail (iter); mbui_advance (iter))
180 /* We know that special contains only ASCII characters. */
181 if (mb_len (mbui_cur (iter)) == 1
182 && strchr (special, * mbui_cur_ptr (iter)))
184 memcpy (p, mbui_cur_ptr (iter), mb_len (mbui_cur (iter)));
185 p += mb_len (mbui_cur (iter));
192 for (iter = string; *iter != '\0'; iter++)
194 if (strchr (special, *iter))
206 regex_quote (const char *string, const struct regex_quote_spec *spec)
208 size_t length = regex_quote_length (string, spec);
209 char *result = XNMALLOC (length + 1, char);
213 p = regex_quote_copy (p, string, spec);