1 /*
2 *
3 * Copyright (c) 1998-2002
4 * John Maddock
5 *
6 * Use, modification and distribution are subject to the
7 * Boost Software License, Version 1.0. (See accompanying file
8 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 *
10 */
11
12 /*
13 * LOCATION: see http://www.boost.org for most recent version.
14 * FILE: posix_api.cpp
15 * VERSION: see <boost/version.hpp>
16 * DESCRIPTION: Implements the Posix API wrappers.
17 */
18
19 #define BOOST_REGEX_SOURCE
20
21 #include <boost/config.hpp>
22 #include <cstdio>
23 #include <boost/regex.hpp>
24 #include <boost/cregex.hpp>
25
26 #if defined(BOOST_NO_STDC_NAMESPACE)
27 namespace std{
28 using ::sprintf;
29 using ::strcpy;
30 using ::strcmp;
31 }
32 #endif
33
34
35 namespace boost{
36
37 namespace{
38
39 unsigned int magic_value = 25631;
40
41 const char* names[] = {
42 "REG_NOERROR",
43 "REG_NOMATCH",
44 "REG_BADPAT",
45 "REG_ECOLLATE",
46 "REG_ECTYPE",
47 "REG_EESCAPE",
48 "REG_ESUBREG",
49 "REG_EBRACK",
50 "REG_EPAREN",
51 "REG_EBRACE",
52 "REG_BADBR",
53 "REG_ERANGE",
54 "REG_ESPACE",
55 "REG_BADRPT",
56 "REG_EEND",
57 "REG_ESIZE",
58 "REG_ERPAREN",
59 "REG_EMPTY",
60 "REG_ECOMPLEXITY",
61 "REG_ESTACK",
62 "REG_E_PERL",
63 "REG_E_UNKNOWN",
64 };
65 } // namespace
66
67 typedef boost::basic_regex<char, c_regex_traits<char> > c_regex_type;
68
69 #ifdef BOOST_MSVC
70 # pragma warning(push)
71 #pragma warning(disable:26812)
72 #endif
regcompA(regex_tA * expression,const char * ptr,int f)73 BOOST_REGEX_DECL int BOOST_REGEX_CCALL regcompA(regex_tA* expression, const char* ptr, int f)
74 {
75 #ifndef BOOST_NO_EXCEPTIONS
76 try{
77 #endif
78 expression->guts = new c_regex_type();
79 #ifndef BOOST_NO_EXCEPTIONS
80 } catch(...)
81 {
82 expression->guts = 0;
83 return REG_ESPACE;
84 }
85 #else
86 if(0 == expression->guts)
87 return REG_E_MEMORY;
88 #endif
89 // set default flags:
90 boost::uint_fast32_t flags = (f & REG_PERLEX) ? 0 : ((f & REG_EXTENDED) ? regex::extended : regex::basic);
91 expression->eflags = (f & REG_NEWLINE) ? match_not_dot_newline : match_default;
92 // and translate those that are actually set:
93
94 if(f & REG_NOCOLLATE)
95 {
96 flags |= regex::nocollate;
97 #ifndef BOOST_REGEX_V3
98 flags &= ~regex::collate;
99 #endif
100 }
101
102 if(f & REG_NOSUB)
103 {
104 //expression->eflags |= match_any;
105 flags |= regex::nosubs;
106 }
107
108 if(f & REG_NOSPEC)
109 flags |= regex::literal;
110 if(f & REG_ICASE)
111 flags |= regex::icase;
112 if(f & REG_ESCAPE_IN_LISTS)
113 flags &= ~regex::no_escape_in_lists;
114 if(f & REG_NEWLINE_ALT)
115 flags |= regex::newline_alt;
116
117 const char* p2;
118 if(f & REG_PEND)
119 p2 = expression->re_endp;
120 else p2 = ptr + std::strlen(ptr);
121
122 int result;
123
124 #ifndef BOOST_NO_EXCEPTIONS
125 try{
126 #endif
127 expression->re_magic = magic_value;
128 static_cast<c_regex_type*>(expression->guts)->set_expression(ptr, p2, flags);
129 expression->re_nsub = static_cast<c_regex_type*>(expression->guts)->mark_count();
130 result = static_cast<c_regex_type*>(expression->guts)->error_code();
131 #ifndef BOOST_NO_EXCEPTIONS
132 }
133 catch(const boost::regex_error& be)
134 {
135 result = be.code();
136 }
137 catch(...)
138 {
139 result = REG_E_UNKNOWN;
140 }
141 #endif
142 if(result)
143 regfreeA(expression);
144 return result;
145
146 }
147 #ifdef BOOST_MSVC
148 # pragma warning(pop)
149 #endif
150
regerrorA(int code,const regex_tA * e,char * buf,regsize_t buf_size)151 BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorA(int code, const regex_tA* e, char* buf, regsize_t buf_size)
152 {
153 std::size_t result = 0;
154 if(code & REG_ITOA)
155 {
156 code &= ~REG_ITOA;
157 if(code <= (int)REG_E_UNKNOWN)
158 {
159 result = std::strlen(names[code]) + 1;
160 if(buf_size >= result)
161 BOOST_REGEX_DETAIL_NS::strcpy_s(buf, buf_size, names[code]);
162 return result;
163 }
164 return result;
165 }
166 if(code == REG_ATOI)
167 {
168 char localbuf[5];
169 if(e == 0)
170 return 0;
171 for(int i = 0; i <= (int)REG_E_UNKNOWN; ++i)
172 {
173 if(std::strcmp(e->re_endp, names[i]) == 0)
174 {
175 //
176 // We're converting an integer i to a string, and since i <= REG_E_UNKNOWN
177 // a five character string is *always* large enough:
178 //
179 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(_WIN32_WCE) && !defined(UNDER_CE)
180 int r = (::sprintf_s)(localbuf, 5, "%d", i);
181 #else
182 int r = (std::sprintf)(localbuf, "%d", i);
183 #endif
184 if(r < 0)
185 return 0; // sprintf failed
186 if(std::strlen(localbuf) < buf_size)
187 BOOST_REGEX_DETAIL_NS::strcpy_s(buf, buf_size, localbuf);
188 return std::strlen(localbuf) + 1;
189 }
190 }
191 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(_WIN32_WCE) && !defined(UNDER_CE)
192 int r = (::sprintf_s)(localbuf, 5, "%d", 0);
193 #else
194 int r = (std::sprintf)(localbuf, "%d", 0);
195 #endif
196 if(r < 0)
197 return 0; // sprintf failed
198 if(std::strlen(localbuf) < buf_size)
199 BOOST_REGEX_DETAIL_NS::strcpy_s(buf, buf_size, localbuf);
200 return std::strlen(localbuf) + 1;
201 }
202 if(code <= (int)REG_E_UNKNOWN)
203 {
204 std::string p;
205 if((e) && (e->re_magic == magic_value))
206 p = static_cast<c_regex_type*>(e->guts)->get_traits().error_string(static_cast< ::boost::regex_constants::error_type>(code));
207 else
208 {
209 p = BOOST_REGEX_DETAIL_NS::get_default_error_string(static_cast< ::boost::regex_constants::error_type>(code));
210 }
211 std::size_t len = p.size();
212 if(len < buf_size)
213 {
214 BOOST_REGEX_DETAIL_NS::strcpy_s(buf, buf_size, p.c_str());
215 }
216 return len + 1;
217 }
218 if(buf_size)
219 *buf = 0;
220 return 0;
221 }
222
regexecA(const regex_tA * expression,const char * buf,regsize_t n,regmatch_t * array,int eflags)223 BOOST_REGEX_DECL int BOOST_REGEX_CCALL regexecA(const regex_tA* expression, const char* buf, regsize_t n, regmatch_t* array, int eflags)
224 {
225 #ifdef BOOST_MSVC
226 #pragma warning(push)
227 #pragma warning(disable:4267)
228 #endif
229 bool result = false;
230 match_flag_type flags = match_default | expression->eflags;
231 const char* end;
232 const char* start;
233 cmatch m;
234
235 if(eflags & REG_NOTBOL)
236 flags |= match_not_bol;
237 if(eflags & REG_NOTEOL)
238 flags |= match_not_eol;
239 if(eflags & REG_STARTEND)
240 {
241 start = buf + array[0].rm_so;
242 end = buf + array[0].rm_eo;
243 }
244 else
245 {
246 start = buf;
247 end = buf + std::strlen(buf);
248 }
249
250 #ifndef BOOST_NO_EXCEPTIONS
251 try{
252 #endif
253 if(expression->re_magic == magic_value)
254 {
255 result = regex_search(start, end, m, *static_cast<c_regex_type*>(expression->guts), flags);
256 }
257 else
258 return result;
259 #ifndef BOOST_NO_EXCEPTIONS
260 } catch(...)
261 {
262 return REG_E_UNKNOWN;
263 }
264 #endif
265
266 if(result)
267 {
268 // extract what matched:
269 std::size_t i;
270 for(i = 0; (i < n) && (i < expression->re_nsub + 1); ++i)
271 {
272 array[i].rm_so = (m[i].matched == false) ? -1 : (m[i].first - buf);
273 array[i].rm_eo = (m[i].matched == false) ? -1 : (m[i].second - buf);
274 }
275 // and set anything else to -1:
276 for(i = expression->re_nsub + 1; i < n; ++i)
277 {
278 array[i].rm_so = -1;
279 array[i].rm_eo = -1;
280 }
281 return 0;
282 }
283 return REG_NOMATCH;
284 #ifdef BOOST_MSVC
285 #pragma warning(pop)
286 #endif
287 }
288
regfreeA(regex_tA * expression)289 BOOST_REGEX_DECL void BOOST_REGEX_CCALL regfreeA(regex_tA* expression)
290 {
291 if(expression->re_magic == magic_value)
292 {
293 delete static_cast<c_regex_type*>(expression->guts);
294 }
295 expression->re_magic = 0;
296 }
297
298 } // namespace boost
299
300
301
302
303