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 | BOOST_REGEX_DECL int BOOST_REGEX_CCALL regcompA(regex_tA* expression, const char* ptr, int f) |
70 | { |
71 | #ifndef BOOST_NO_EXCEPTIONS |
72 | try{ |
73 | #endif |
74 | expression->guts = new c_regex_type(); |
75 | #ifndef BOOST_NO_EXCEPTIONS |
76 | } catch(...) |
77 | { |
78 | expression->guts = 0; |
79 | return REG_ESPACE; |
80 | } |
81 | #else |
82 | if(0 == expression->guts) |
83 | return REG_E_MEMORY; |
84 | #endif |
85 | // set default flags: |
86 | boost::uint_fast32_t flags = (f & REG_PERLEX) ? 0 : ((f & REG_EXTENDED) ? regex::extended : regex::basic); |
87 | expression->eflags = (f & REG_NEWLINE) ? match_not_dot_newline : match_default; |
88 | // and translate those that are actually set: |
89 | |
90 | if(f & REG_NOCOLLATE) |
91 | { |
92 | flags |= regex::nocollate; |
93 | #ifndef BOOST_REGEX_V3 |
94 | flags &= ~regex::collate; |
95 | #endif |
96 | } |
97 | |
98 | if(f & REG_NOSUB) |
99 | { |
100 | //expression->eflags |= match_any; |
101 | flags |= regex::nosubs; |
102 | } |
103 | |
104 | if(f & REG_NOSPEC) |
105 | flags |= regex::literal; |
106 | if(f & REG_ICASE) |
107 | flags |= regex::icase; |
108 | if(f & REG_ESCAPE_IN_LISTS) |
109 | flags &= ~regex::no_escape_in_lists; |
110 | if(f & REG_NEWLINE_ALT) |
111 | flags |= regex::newline_alt; |
112 | |
113 | const char* p2; |
114 | if(f & REG_PEND) |
115 | p2 = expression->re_endp; |
116 | else p2 = ptr + std::strlen(ptr); |
117 | |
118 | int result; |
119 | |
120 | #ifndef BOOST_NO_EXCEPTIONS |
121 | try{ |
122 | #endif |
123 | expression->re_magic = magic_value; |
124 | static_cast<c_regex_type*>(expression->guts)->set_expression(ptr, p2, flags); |
125 | expression->re_nsub = static_cast<c_regex_type*>(expression->guts)->mark_count(); |
126 | result = static_cast<c_regex_type*>(expression->guts)->error_code(); |
127 | #ifndef BOOST_NO_EXCEPTIONS |
128 | } |
129 | catch(const boost::regex_error& be) |
130 | { |
131 | result = be.code(); |
132 | } |
133 | catch(...) |
134 | { |
135 | result = REG_E_UNKNOWN; |
136 | } |
137 | #endif |
138 | if(result) |
139 | regfreeA(expression); |
140 | return result; |
141 | |
142 | } |
143 | |
144 | BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorA(int code, const regex_tA* e, char* buf, regsize_t buf_size) |
145 | { |
146 | std::size_t result = 0; |
147 | if(code & REG_ITOA) |
148 | { |
149 | code &= ~REG_ITOA; |
150 | if(code <= (int)REG_E_UNKNOWN) |
151 | { |
152 | result = std::strlen(names[code]) + 1; |
153 | if(buf_size >= result) |
154 | BOOST_REGEX_DETAIL_NS::strcpy_s(buf, buf_size, names[code]); |
155 | return result; |
156 | } |
157 | return result; |
158 | } |
159 | if(code == REG_ATOI) |
160 | { |
161 | char localbuf[5]; |
162 | if(e == 0) |
163 | return 0; |
164 | for(int i = 0; i <= (int)REG_E_UNKNOWN; ++i) |
165 | { |
166 | if(std::strcmp(e->re_endp, names[i]) == 0) |
167 | { |
168 | // |
169 | // We're converting an integer i to a string, and since i <= REG_E_UNKNOWN |
170 | // a five character string is *always* large enough: |
171 | // |
172 | #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(_WIN32_WCE) && !defined(UNDER_CE) |
173 | int r = (::sprintf_s)(localbuf, 5, "%d" , i); |
174 | #else |
175 | int r = (std::sprintf)(localbuf, "%d" , i); |
176 | #endif |
177 | if(r < 0) |
178 | return 0; // sprintf failed |
179 | if(std::strlen(localbuf) < buf_size) |
180 | BOOST_REGEX_DETAIL_NS::strcpy_s(buf, buf_size, localbuf); |
181 | return std::strlen(localbuf) + 1; |
182 | } |
183 | } |
184 | #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(_WIN32_WCE) && !defined(UNDER_CE) |
185 | int r = (::sprintf_s)(localbuf, 5, "%d" , 0); |
186 | #else |
187 | int r = (std::sprintf)(localbuf, "%d" , 0); |
188 | #endif |
189 | if(r < 0) |
190 | return 0; // sprintf failed |
191 | if(std::strlen(localbuf) < buf_size) |
192 | BOOST_REGEX_DETAIL_NS::strcpy_s(buf, buf_size, localbuf); |
193 | return std::strlen(localbuf) + 1; |
194 | } |
195 | if(code <= (int)REG_E_UNKNOWN) |
196 | { |
197 | std::string p; |
198 | if((e) && (e->re_magic == magic_value)) |
199 | p = static_cast<c_regex_type*>(e->guts)->get_traits().error_string(static_cast< ::boost::regex_constants::error_type>(code)); |
200 | else |
201 | { |
202 | p = BOOST_REGEX_DETAIL_NS::get_default_error_string(static_cast< ::boost::regex_constants::error_type>(code)); |
203 | } |
204 | std::size_t len = p.size(); |
205 | if(len < buf_size) |
206 | { |
207 | BOOST_REGEX_DETAIL_NS::strcpy_s(buf, buf_size, p.c_str()); |
208 | } |
209 | return len + 1; |
210 | } |
211 | if(buf_size) |
212 | *buf = 0; |
213 | return 0; |
214 | } |
215 | |
216 | BOOST_REGEX_DECL int BOOST_REGEX_CCALL regexecA(const regex_tA* expression, const char* buf, regsize_t n, regmatch_t* array, int eflags) |
217 | { |
218 | #ifdef BOOST_MSVC |
219 | #pragma warning(push) |
220 | #pragma warning(disable:4267) |
221 | #endif |
222 | bool result = false; |
223 | match_flag_type flags = match_default | expression->eflags; |
224 | const char* end; |
225 | const char* start; |
226 | cmatch m; |
227 | |
228 | if(eflags & REG_NOTBOL) |
229 | flags |= match_not_bol; |
230 | if(eflags & REG_NOTEOL) |
231 | flags |= match_not_eol; |
232 | if(eflags & REG_STARTEND) |
233 | { |
234 | start = buf + array[0].rm_so; |
235 | end = buf + array[0].rm_eo; |
236 | } |
237 | else |
238 | { |
239 | start = buf; |
240 | end = buf + std::strlen(buf); |
241 | } |
242 | |
243 | #ifndef BOOST_NO_EXCEPTIONS |
244 | try{ |
245 | #endif |
246 | if(expression->re_magic == magic_value) |
247 | { |
248 | result = regex_search(start, end, m, *static_cast<c_regex_type*>(expression->guts), flags); |
249 | } |
250 | else |
251 | return result; |
252 | #ifndef BOOST_NO_EXCEPTIONS |
253 | } catch(...) |
254 | { |
255 | return REG_E_UNKNOWN; |
256 | } |
257 | #endif |
258 | |
259 | if(result) |
260 | { |
261 | // extract what matched: |
262 | std::size_t i; |
263 | for(i = 0; (i < n) && (i < expression->re_nsub + 1); ++i) |
264 | { |
265 | array[i].rm_so = (m[i].matched == false) ? -1 : (m[i].first - buf); |
266 | array[i].rm_eo = (m[i].matched == false) ? -1 : (m[i].second - buf); |
267 | } |
268 | // and set anything else to -1: |
269 | for(i = expression->re_nsub + 1; i < n; ++i) |
270 | { |
271 | array[i].rm_so = -1; |
272 | array[i].rm_eo = -1; |
273 | } |
274 | return 0; |
275 | } |
276 | return REG_NOMATCH; |
277 | #ifdef BOOST_MSVC |
278 | #pragma warning(pop) |
279 | #endif |
280 | } |
281 | |
282 | BOOST_REGEX_DECL void BOOST_REGEX_CCALL regfreeA(regex_tA* expression) |
283 | { |
284 | if(expression->re_magic == magic_value) |
285 | { |
286 | delete static_cast<c_regex_type*>(expression->guts); |
287 | } |
288 | expression->re_magic = 0; |
289 | } |
290 | |
291 | } // namespace boost |
292 | |
293 | |
294 | |
295 | |
296 | |