~ubuntu-branches/ubuntu/warty/aqsis/warty

« back to all changes in this revision

Viewing changes to boost/boost/regex/v3/regex_compile.hpp

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones
  • Date: 2004-08-24 07:25:04 UTC
  • Revision ID: james.westby@ubuntu.com-20040824072504-zf993vnevvisdsvb
Tags: upstream-0.9.1
ImportĀ upstreamĀ versionĀ 0.9.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *
 
3
 * Copyright (c) 1998-2002
 
4
 * Dr John Maddock
 
5
 *
 
6
 * Permission to use, copy, modify, distribute and sell this software
 
7
 * and its documentation for any purpose is hereby granted without fee,
 
8
 * provided that the above copyright notice appear in all copies and
 
9
 * that both that copyright notice and this permission notice appear
 
10
 * in supporting documentation.  Dr John Maddock makes no representations
 
11
 * about the suitability of this software for any purpose.  
 
12
 * It is provided "as is" without express or implied warranty.
 
13
 *
 
14
 */
 
15
 
 
16
 /*
 
17
  *   LOCATION:    see http://www.boost.org for most recent version.
 
18
  *   FILE         regex_compile.hpp
 
19
  *   VERSION      see <boost/version.hpp>
 
20
  *   DESCRIPTION: Declares reg_expression<> member functions.  This is
 
21
  *                an internal header file, do not include directly.
 
22
  */
 
23
 
 
24
#ifndef BOOST_REGEX_COMPILE_HPP
 
25
#define BOOST_REGEX_COMPILE_HPP
 
26
 
 
27
namespace boost{
 
28
#ifdef __BORLANDC__
 
29
   #pragma option push -a8 -b -Vx -Ve -pc  -w-8004
 
30
#endif
 
31
   namespace re_detail{
 
32
 
 
33
 
 
34
template <class traits>
 
35
struct kmp_translator
 
36
{
 
37
   typedef typename traits::char_type char_type;
 
38
   bool icase;
 
39
   const traits* pt;
 
40
   kmp_translator(bool c, traits* p) : icase(c), pt(p) {}
 
41
   char_type operator()(char_type c)
 
42
   {
 
43
      return pt->translate(c, icase);
 
44
   }
 
45
};
 
46
 
 
47
 
 
48
template <class charT, class traits_type, class Allocator>
 
49
bool BOOST_REGEX_CALL re_maybe_set_member(charT c,
 
50
                                 const re_set_long* set_,
 
51
                                 const reg_expression<charT, traits_type, Allocator>& e)
 
52
{
 
53
   const charT* p = reinterpret_cast<const charT*>(set_+1);
 
54
   bool icase = e.flags() & regbase::icase;
 
55
   charT col = e.get_traits().translate(c, icase);
 
56
   for(unsigned int i = 0; i < set_->csingles; ++i)
 
57
   {
 
58
      if(col == *p)
 
59
         return set_->isnot ? false : true;
 
60
 
 
61
      while(*p)++p;
 
62
      ++p;     // skip null
 
63
   }
 
64
   return set_->isnot ? true : false;
 
65
}
 
66
 
 
67
} // namespace re_detail
 
68
 
 
69
 
 
70
template <class charT, class traits, class Allocator>
 
71
inline bool BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::can_start(charT c, const unsigned char* _map, unsigned char mask, const re_detail::_wide_type&)
 
72
{
 
73
   if((traits_size_type)(traits_uchar_type)c >= 256)
 
74
      return true;
 
75
   return BOOST_REGEX_MAKE_BOOL(_map[(traits_uchar_type)c] & mask);
 
76
}
 
77
 
 
78
template <class charT, class traits, class Allocator>
 
79
inline bool BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::can_start(charT c, const unsigned char* _map, unsigned char mask, const re_detail::_narrow_type&)
 
80
{
 
81
   return BOOST_REGEX_MAKE_BOOL(_map[(traits_uchar_type)c] & mask);
 
82
}
 
83
 
 
84
template <class charT, class traits, class Allocator>
 
85
reg_expression<charT, traits, Allocator>::reg_expression(const Allocator& a)
 
86
    : regbase(), data(a), pkmp(0), error_code_(REG_EMPTY), _expression(0)
 
87
{
 
88
}
 
89
 
 
90
template <class charT, class traits, class Allocator>
 
91
reg_expression<charT, traits, Allocator>::reg_expression(const charT* p, flag_type f, const Allocator& a)
 
92
    : data(a), pkmp(0), error_code_(REG_EMPTY), _expression(0)
 
93
{
 
94
   set_expression(p, f | regbase::use_except);
 
95
}
 
96
 
 
97
template <class charT, class traits, class Allocator>
 
98
reg_expression<charT, traits, Allocator>::reg_expression(const charT* p1, const charT* p2, flag_type f, const Allocator& a)
 
99
    : data(a), pkmp(0), error_code_(REG_EMPTY), _expression(0)
 
100
{
 
101
    set_expression(p1, p2, f | regbase::use_except);
 
102
}
 
103
 
 
104
template <class charT, class traits, class Allocator>
 
105
reg_expression<charT, traits, Allocator>::reg_expression(const charT* p, size_type len, flag_type f, const Allocator& a)
 
106
    : data(a), pkmp(0), error_code_(REG_EMPTY), _expression(0)
 
107
{
 
108
    set_expression(p, p + len, f | regbase::use_except);
 
109
}
 
110
 
 
111
template <class charT, class traits, class Allocator>
 
112
reg_expression<charT, traits, Allocator>::reg_expression(const reg_expression<charT, traits, Allocator>& e)
 
113
   : regbase(e), data(e.allocator()), pkmp(0), error_code_(REG_EMPTY), _expression(0)
 
114
{
 
115
   //
 
116
   // we do a deep copy only if e is a valid expression, otherwise fail.
 
117
   //
 
118
   if(e.error_code() == 0)
 
119
   {
 
120
      const charT* pe = e.expression();
 
121
      set_expression(pe, pe + e._expression_len, e.flags() | regbase::use_except);
 
122
   }
 
123
   else
 
124
   {
 
125
      _flags = e.flags() & ~(regbase::use_except);
 
126
      fail(e.error_code());
 
127
   }
 
128
}
 
129
 
 
130
template <class charT, class traits, class Allocator>
 
131
reg_expression<charT, traits, Allocator>::~reg_expression()
 
132
{
 
133
   if(pkmp)
 
134
      re_detail::kmp_free(pkmp, data.allocator());
 
135
}
 
136
 
 
137
template <class charT, class traits, class Allocator>
 
138
reg_expression<charT, traits, Allocator>& BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::operator=(const reg_expression<charT, traits, Allocator>& e)
 
139
{
 
140
   //
 
141
   // we do a deep copy only if e is a valid expression, otherwise fail.
 
142
   //
 
143
   if(this == &e) return *this;
 
144
   _flags = use_except;
 
145
   fail(e.error_code());
 
146
   if(error_code() == 0)
 
147
      set_expression(e._expression, e._expression + e._expression_len, e.flags() | regbase::use_except);
 
148
   return *this;
 
149
}
 
150
 
 
151
template <class charT, class traits, class Allocator>
 
152
inline bool BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::operator==(const reg_expression<charT, traits, Allocator>& e)const
 
153
{
 
154
   return (_flags == e.flags())
 
155
           && (_expression_len == e._expression_len)
 
156
           && (std::memcmp(_expression, e._expression, _expression_len * sizeof(charT)) == 0);
 
157
}
 
158
 
 
159
template <class charT, class traits, class Allocator>
 
160
bool BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::operator<(const reg_expression<charT, traits, Allocator>& e)const
 
161
{
 
162
   //
 
163
   // we can't offer a diffinitive ordering, but we can be consistant:
 
164
   if(_flags != e.flags()) return _flags < e.flags();
 
165
   if(_expression_len != e._expression_len) return _expression_len < e._expression_len;
 
166
   return std::memcmp(expression(), e.expression(), _expression_len);
 
167
}
 
168
 
 
169
template <class charT, class traits, class Allocator>
 
170
Allocator BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::allocator()const
 
171
{
 
172
    return data.allocator();
 
173
}
 
174
 
 
175
template <class charT, class traits, class Allocator>
 
176
Allocator BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::get_allocator()const
 
177
{
 
178
    return data.allocator();
 
179
}
 
180
 
 
181
template <class charT, class traits, class Allocator>
 
182
unsigned int BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::parse_inner_set(const charT*& first, const charT* last)
 
183
{
 
184
   //
 
185
   // we have an inner [...] construct
 
186
   //
 
187
   jm_assert(traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*first) == traits_type::syntax_open_set);
 
188
   const charT* base = first;
 
189
   while( (first != last)
 
190
      && (traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*first) != traits_type::syntax_close_set) )
 
191
         ++first;
 
192
   if(first == last)
 
193
      return 0;
 
194
   ++first;
 
195
   if((first-base) < 5)
 
196
      return 0;
 
197
   if(*(base+1) != *(first-2))
 
198
      return 0;
 
199
   unsigned int result = traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*(base+1));
 
200
   if((result == traits_type::syntax_colon) && ((first-base) == 5))
 
201
   {
 
202
      return traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*(base+2));
 
203
   }
 
204
   return ((result == traits_type::syntax_colon) || (result == traits_type::syntax_dot) || (result == traits_type::syntax_equal)) ? result : 0;
 
205
}
 
206
 
 
207
 
 
208
template <class charT, class traits, class Allocator>
 
209
bool BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::skip_space(const charT*& first, const charT* last)
 
210
{
 
211
   //
 
212
   // returns true if we get to last:
 
213
   //
 
214
   while((first != last) && (traits_inst.is_class(*first, traits_type::char_class_space) == true))
 
215
   {
 
216
      ++first;
 
217
   }
 
218
   return first == last;
 
219
}
 
220
 
 
221
template <class charT, class traits, class Allocator>
 
222
void BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::parse_range(const charT*& ptr, const charT* end, unsigned& min, unsigned& max)
 
223
{
 
224
   //
 
225
   // we have {x} or {x,} or {x,y} NB no spaces inside braces
 
226
   // anything else is illegal
 
227
   // On input ptr points to "{"
 
228
   //
 
229
   ++ptr;
 
230
   if(skip_space(ptr, end))
 
231
   {
 
232
      fail(REG_EBRACE);
 
233
      return;
 
234
   }
 
235
   if(traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*ptr) != traits_type::syntax_digit)
 
236
   {
 
237
      fail(REG_BADBR);
 
238
      return;
 
239
   }
 
240
   min = traits_inst.toi(ptr, end, 10);
 
241
   if(skip_space(ptr, end))
 
242
   {
 
243
      fail(REG_EBRACE);
 
244
      return;
 
245
   }
 
246
   if(traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*ptr) == traits_type::syntax_comma)
 
247
   {
 
248
      //we have a second interval:
 
249
      ++ptr;
 
250
      if(skip_space(ptr, end))
 
251
      {
 
252
         fail(REG_EBRACE);
 
253
         return;
 
254
      }
 
255
      if(traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*ptr) == traits_type::syntax_digit)
 
256
         max = traits_inst.toi(ptr, end, 10);
 
257
      else
 
258
         max = (unsigned)-1;
 
259
   }
 
260
   else
 
261
      max = min;
 
262
 
 
263
   // validate input:
 
264
   if(skip_space(ptr, end))
 
265
   {
 
266
      fail(REG_EBRACE);
 
267
      return;
 
268
   }
 
269
   if(max < min)
 
270
   {
 
271
      fail(REG_ERANGE);
 
272
      return;
 
273
   }
 
274
   if(_flags & bk_braces)
 
275
   {
 
276
      if(traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*ptr) != traits_type::syntax_slash)
 
277
      {
 
278
         fail(REG_BADBR);
 
279
         return;
 
280
      }
 
281
      else
 
282
      {
 
283
         // back\ is OK now check the }
 
284
         ++ptr;
 
285
         if((ptr == end) || (traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*ptr) != traits_type::syntax_close_brace))
 
286
         {
 
287
            fail(REG_BADBR);
 
288
            return;
 
289
         }
 
290
      }
 
291
   }
 
292
   else if(traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*ptr) != traits_type::syntax_close_brace)
 
293
   {
 
294
      fail(REG_BADBR);
 
295
      return;
 
296
   }
 
297
}
 
298
 
 
299
template <class charT, class traits, class Allocator>
 
300
charT BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::parse_escape(const charT*& first, const charT* last)
 
301
{
 
302
   charT c(*first);
 
303
   traits_size_type c_unsigned = (traits_size_type)(traits_uchar_type)*first;
 
304
   // this is only used for the switch(), but cannot be folded in
 
305
   // due to a bug in Comeau 4.2.44beta3
 
306
   traits_size_type syntax = traits_inst.syntax_type(c_unsigned);
 
307
   switch(syntax)
 
308
   {
 
309
   case traits_type::syntax_a:
 
310
      c = '\a';
 
311
      ++first;
 
312
      break;
 
313
   case traits_type::syntax_f:
 
314
      c = '\f';
 
315
      ++first;
 
316
      break;
 
317
   case traits_type::syntax_n:
 
318
      c = '\n';
 
319
      ++first;
 
320
      break;
 
321
   case traits_type::syntax_r:
 
322
      c = '\r';
 
323
      ++first;
 
324
      break;
 
325
   case traits_type::syntax_t:
 
326
      c = '\t';
 
327
      ++first;
 
328
      break;
 
329
   case traits_type::syntax_v:
 
330
      c = '\v';
 
331
      ++first;
 
332
      break;
 
333
   case traits_type::syntax_x:
 
334
      ++first;
 
335
      if(first == last)
 
336
      {
 
337
         fail(REG_EESCAPE);
 
338
         break;
 
339
      }
 
340
      // maybe have \x{ddd}
 
341
      if(traits_inst.syntax_type((traits_size_type)(traits_uchar_type)(*first)) == traits_type::syntax_open_brace)
 
342
      {
 
343
         ++first;
 
344
         if(first == last)
 
345
         {
 
346
            fail(REG_EESCAPE);
 
347
            break;
 
348
         }
 
349
         if(traits_inst.is_class(*first, traits_type::char_class_xdigit) == false)
 
350
         {
 
351
            fail(REG_BADBR);
 
352
            break;
 
353
         }
 
354
         c = (charT)traits_inst.toi(first, last, -16);
 
355
         if((first == last) || (traits_inst.syntax_type((traits_size_type)(traits_uchar_type)(*first)) != traits_type::syntax_close_brace))
 
356
         {
 
357
            fail(REG_BADBR);
 
358
         }
 
359
         ++first;
 
360
         break;
 
361
      }
 
362
      else
 
363
      {
 
364
         if(traits_inst.is_class(*first, traits_type::char_class_xdigit) == false)
 
365
         {
 
366
            fail(REG_BADBR);
 
367
            break;
 
368
         }
 
369
         c = (charT)traits_inst.toi(first, last, -16);
 
370
      }
 
371
      break;
 
372
   case traits_type::syntax_c:
 
373
      ++first;
 
374
      if(first == last)
 
375
      {
 
376
         fail(REG_EESCAPE);
 
377
         break;
 
378
      }
 
379
      if(((traits_uchar_type)(*first) < (traits_uchar_type)'@')
 
380
            || ((traits_uchar_type)(*first) > (traits_uchar_type)127) )
 
381
      {
 
382
         fail(REG_EESCAPE);
 
383
         return (charT)0;
 
384
      }
 
385
      c = (charT)((traits_uchar_type)(*first) - (traits_uchar_type)'@');
 
386
      ++first;
 
387
      break;
 
388
   case traits_type::syntax_e:
 
389
      c = (charT)27;
 
390
      ++first;
 
391
      break;
 
392
   case traits_type::syntax_digit:
 
393
      c = (charT)traits_inst.toi(first, last, -8);
 
394
      break;
 
395
   default:
 
396
      //c = *first;
 
397
      ++first;
 
398
   }
 
399
   return c;
 
400
}
 
401
 
 
402
template <class charT, class traits, class Allocator>
 
403
void BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::compile_maps()
 
404
{
 
405
   re_detail::re_syntax_base* record = static_cast<re_detail::re_syntax_base*>(data.data());
 
406
   // always compile the first _map:
 
407
   std::memset(startmap, 0, 256);
 
408
   record->can_be_null = 0;
 
409
   compile_map(record, startmap, 0, re_detail::mask_all);
 
410
 
 
411
   while(record->type != re_detail::syntax_element_match)
 
412
   {
 
413
      if((record->type == re_detail::syntax_element_alt) || (record->type == re_detail::syntax_element_rep))
 
414
      {
 
415
         std::memset(&(static_cast<re_detail::re_jump*>(record)->_map), 0, 256);
 
416
         record->can_be_null = 0;
 
417
         compile_map(record->next.p, static_cast<re_detail::re_jump*>(record)->_map, &(record->can_be_null), re_detail::mask_take, static_cast<re_detail::re_jump*>(record)->alt.p);
 
418
         compile_map(static_cast<re_detail::re_jump*>(record)->alt.p, static_cast<re_detail::re_jump*>(record)->_map, &(record->can_be_null), re_detail::mask_skip);
 
419
         if(record->type == re_detail::syntax_element_rep)
 
420
         {
 
421
            re_detail::re_repeat* rep = static_cast<re_detail::re_repeat*>(record);
 
422
            // set whether this is a singleton repeat or not:
 
423
            if(rep->next.p->next.p->next.p == rep->alt.p)
 
424
            {
 
425
               rep->singleton = true;
 
426
            }
 
427
            else
 
428
               rep->singleton = false;
 
429
         }
 
430
      }
 
431
      else
 
432
      {
 
433
         record->can_be_null = 0;
 
434
         compile_map(record, 0, &(record->can_be_null), re_detail::mask_all);
 
435
      }
 
436
      record = record->next.p;
 
437
   }
 
438
   record->can_be_null = re_detail::mask_all;
 
439
}
 
440
 
 
441
template <class charT, class traits, class Allocator>
 
442
bool BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::probe_start(
 
443
                        re_detail::re_syntax_base* node, charT cc, re_detail::re_syntax_base* terminal) const
 
444
{
 
445
   unsigned int c;
 
446
 
 
447
   switch(node->type)
 
448
   {
 
449
   case re_detail::syntax_element_startmark:
 
450
      if(static_cast<const re_detail::re_brace*>(node)->index == -1)
 
451
      {
 
452
         return probe_start(node->next.p->next.p, cc, terminal)
 
453
            && probe_start(static_cast<const re_detail::re_jump*>(node->next.p)->alt.p, cc, terminal);
 
454
      }
 
455
      // fall through:
 
456
   case re_detail::syntax_element_endmark:
 
457
   case re_detail::syntax_element_start_line:
 
458
   case re_detail::syntax_element_word_boundary:
 
459
   case re_detail::syntax_element_buffer_start:
 
460
   case re_detail::syntax_element_restart_continue:
 
461
      // doesn't tell us anything about the next character, so:
 
462
      return probe_start(node->next.p, cc, terminal);
 
463
   case re_detail::syntax_element_literal:
 
464
      // only the first character of the literal can match:
 
465
      // note these have already been translated:
 
466
      if(*reinterpret_cast<charT*>(static_cast<re_detail::re_literal*>(node)+1) == traits_inst.translate(cc, (_flags & regbase::icase)))
 
467
         return true;
 
468
      return false;
 
469
   case re_detail::syntax_element_end_line:
 
470
      // next character (if there is one!) must be a newline:
 
471
      if(traits_inst.is_separator(traits_inst.translate(cc, (_flags & regbase::icase))))
 
472
         return true;
 
473
      return false;
 
474
   case re_detail::syntax_element_wild:
 
475
      return true;
 
476
   case re_detail::syntax_element_match:
 
477
      return true;
 
478
   case re_detail::syntax_element_within_word:
 
479
   case re_detail::syntax_element_word_start:
 
480
      return traits_inst.is_class(traits_inst.translate(cc, (_flags & regbase::icase)), traits_type::char_class_word);
 
481
   case re_detail::syntax_element_word_end:
 
482
      // what follows must not be a word character,
 
483
      return traits_inst.is_class(traits_inst.translate(cc, (_flags & regbase::icase)), traits_type::char_class_word) ? false : true;
 
484
   case re_detail::syntax_element_buffer_end:
 
485
      // we can be null, nothing must follow,
 
486
      // NB we assume that this is followed by
 
487
      // re_detail::syntax_element_match, if its not then we can
 
488
      // never match anything anyway!!
 
489
      return false;
 
490
   case re_detail::syntax_element_soft_buffer_end:
 
491
      // we can be null, only newlines must follow,
 
492
      // NB we assume that this is followed by
 
493
      // re_detail::syntax_element_match, if its not then we can
 
494
      // never match anything anyway!!
 
495
      return traits_inst.is_separator(traits_inst.translate(cc, (_flags & regbase::icase)));
 
496
   case re_detail::syntax_element_backref:
 
497
      // there's no easy way to determine this
 
498
      // which is not to say it can't be done!
 
499
      // for now:
 
500
      return true;
 
501
   case re_detail::syntax_element_long_set:
 
502
      // we can not be null,
 
503
      // we need to add already translated values in the set
 
504
      // to values in the _map
 
505
      return re_detail::re_maybe_set_member(cc, static_cast<const re_detail::re_set_long*>(node), *this) || (re_detail::re_is_set_member(static_cast<const charT*>(&cc), static_cast<const charT*>(&cc+1), static_cast<re_detail::re_set_long*>(node), *this) != &cc);
 
506
   case re_detail::syntax_element_set:
 
507
      // set all the elements that are set in corresponding set:
 
508
      c = (traits_size_type)(traits_uchar_type)traits_inst.translate(cc, (_flags & regbase::icase));
 
509
      return static_cast<re_detail::re_set*>(node)->_map[c] != 0;
 
510
   case re_detail::syntax_element_jump:
 
511
      if(static_cast<re_detail::re_jump*>(node)->alt.p < node)
 
512
      {
 
513
         // backwards jump,
 
514
         // caused only by end of repeat section, we'll treat this
 
515
         // the same as a match, because the sub-expression has matched.
 
516
         if(node->next.p == terminal)
 
517
            return true; // null repeat - we can always take this
 
518
         else
 
519
         {
 
520
            //
 
521
            // take the jump, add in fix for the fact that if the
 
522
            // repeat that we're jumping to has non-zero minimum count
 
523
            // then we need to add in the possiblity that we could still
 
524
            // skip that repeat.
 
525
            re_detail::re_syntax_base* next = static_cast<re_detail::re_jump*>(node)->alt.p;
 
526
            bool b = probe_start(next, cc, terminal);
 
527
            if((next->type == re_detail::syntax_element_rep) && (static_cast<re_detail::re_repeat*>(next)->min != 0))
 
528
            {
 
529
               b = b || probe_start(static_cast<re_detail::re_jump*>(next)->alt.p, cc, terminal);
 
530
            }
 
531
            return b;
 
532
         }
 
533
      }
 
534
      else
 
535
         // take the jump and compile:
 
536
         return probe_start(static_cast<re_detail::re_jump*>(node)->alt.p, cc, terminal);
 
537
   case re_detail::syntax_element_alt:
 
538
      // we need to take the OR of the two alternatives:
 
539
      return probe_start(static_cast<re_detail::re_jump*>(node)->alt.p, cc, terminal) || probe_start(node->next.p, cc, terminal);
 
540
   case re_detail::syntax_element_rep:
 
541
      // we need to take the OR of the two alternatives
 
542
      if(static_cast<re_detail::re_repeat*>(node)->min == 0)
 
543
         return probe_start(node->next.p, cc, static_cast<re_detail::re_jump*>(node)->alt.p) || probe_start(static_cast<re_detail::re_jump*>(node)->alt.p, cc, terminal);
 
544
      else
 
545
         return probe_start(node->next.p, cc, static_cast<re_detail::re_jump*>(node)->alt.p);
 
546
   case re_detail::syntax_element_combining:
 
547
      return !traits_inst.is_combining(traits_inst.translate(cc, (_flags & regbase::icase)));
 
548
   }
 
549
   return false;
 
550
}
 
551
 
 
552
template <class charT, class traits, class Allocator>
 
553
bool BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::probe_start_null(re_detail::re_syntax_base* node, re_detail::re_syntax_base* terminal)const
 
554
{
 
555
   switch(node->type)
 
556
   {
 
557
   case re_detail::syntax_element_startmark:
 
558
   case re_detail::syntax_element_endmark:
 
559
   case re_detail::syntax_element_start_line:
 
560
   case re_detail::syntax_element_word_boundary:
 
561
   case re_detail::syntax_element_buffer_start:
 
562
   case re_detail::syntax_element_restart_continue:
 
563
   case re_detail::syntax_element_end_line:
 
564
   case re_detail::syntax_element_word_end:
 
565
      // doesn't tell us anything about the next character, so:
 
566
      return probe_start_null(node->next.p, terminal);
 
567
   case re_detail::syntax_element_match:
 
568
   case re_detail::syntax_element_buffer_end:
 
569
   case re_detail::syntax_element_soft_buffer_end:
 
570
   case re_detail::syntax_element_backref:
 
571
      return true;
 
572
   case re_detail::syntax_element_jump:
 
573
      if(static_cast<re_detail::re_jump*>(node)->alt.p < node)
 
574
      {
 
575
         // backwards jump,
 
576
         // caused only by end of repeat section, we'll treat this
 
577
         // the same as a match, because the sub-expression has matched.
 
578
         // this is only caused by NULL repeats as in "(a*)*" or "(\<)*"
 
579
         // these are really nonsensence and make the matching code much
 
580
         // harder, it would be nice to get rid of them altogether.
 
581
         if(node->next.p == terminal)
 
582
            return true;
 
583
         else
 
584
            return probe_start_null(static_cast<re_detail::re_jump*>(node)->alt.p, terminal);
 
585
      }
 
586
      else
 
587
         // take the jump and compile:
 
588
         return probe_start_null(static_cast<re_detail::re_jump*>(node)->alt.p, terminal);
 
589
   case re_detail::syntax_element_alt:
 
590
      // we need to take the OR of the two alternatives:
 
591
      return probe_start_null(static_cast<re_detail::re_jump*>(node)->alt.p, terminal) || probe_start_null(node->next.p, terminal);
 
592
   case re_detail::syntax_element_rep:
 
593
      // only need to consider skipping the repeat:
 
594
      return probe_start_null(static_cast<re_detail::re_jump*>(node)->alt.p, terminal);
 
595
   default:
 
596
      break;
 
597
   }
 
598
   return false;
 
599
}
 
600
 
 
601
template <class charT, class traits, class Allocator>
 
602
void BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::compile_map(
 
603
                        re_detail::re_syntax_base* node, unsigned char* _map,
 
604
                        unsigned int* pnull, unsigned char mask, re_detail::re_syntax_base* terminal)const
 
605
{
 
606
   if(_map)
 
607
   {
 
608
      for(unsigned int i = 0; i < 256; ++i)
 
609
      {
 
610
         if(probe_start(node, (charT)i, terminal))
 
611
            _map[i] |= mask;
 
612
      }
 
613
   }
 
614
   if(pnull && probe_start_null(node, terminal))
 
615
      *pnull |= mask;
 
616
}
 
617
  
 
618
template <class charT, class traits, class Allocator>
 
619
void BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::move_offsets(re_detail::re_syntax_base* j, unsigned size)
 
620
{
 
621
# ifdef BOOST_MSVC
 
622
#  pragma warning(push)
 
623
#  pragma warning(disable: 4127)
 
624
#endif
 
625
   // move all offsets starting with j->link forward by size
 
626
   // called after an insert:
 
627
   j = reinterpret_cast<re_detail::re_syntax_base*>(reinterpret_cast<char*>(data.data()) + j->next.i);
 
628
   while(true)
 
629
   {
 
630
      switch(j->type)
 
631
      {
 
632
      case re_detail::syntax_element_rep:
 
633
         static_cast<re_detail::re_jump*>(j)->alt.i += size;
 
634
         j->next.i += size;
 
635
         break;
 
636
      case re_detail::syntax_element_jump:
 
637
      case re_detail::syntax_element_alt:
 
638
         static_cast<re_detail::re_jump*>(j)->alt.i += size;
 
639
         j->next.i += size;
 
640
         break;
 
641
      default:
 
642
         j->next.i += size;
 
643
         break;
 
644
      }
 
645
      if(j->next.i == size)
 
646
         break;
 
647
      j = reinterpret_cast<re_detail::re_syntax_base*>(reinterpret_cast<char*>(data.data()) + j->next.i);
 
648
   }
 
649
# ifdef BOOST_MSVC
 
650
#  pragma warning(pop)
 
651
#endif
 
652
}
 
653
 
 
654
template <class charT, class traits, class Allocator>
 
655
re_detail::re_syntax_base* BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::compile_set_simple(re_detail::re_syntax_base* dat, unsigned long cls, bool isnot)
 
656
{
 
657
   typedef typename re_detail::is_byte<charT>::width_type width_type;
 
658
   re_detail::jstack<traits_string_type, Allocator> singles(64, data.allocator());
 
659
   re_detail::jstack<traits_string_type, Allocator> ranges(64, data.allocator());
 
660
   re_detail::jstack<boost::uint_fast32_t, Allocator> classes(64, data.allocator());
 
661
   re_detail::jstack<traits_string_type, Allocator> equivalents(64, data.allocator());
 
662
   classes.push(cls);
 
663
   if(dat)
 
664
   {
 
665
      data.align();
 
666
      dat->next.i = data.size();
 
667
   }
 
668
   return compile_set_aux(singles, ranges, classes, equivalents, isnot, width_type());
 
669
}
 
670
 
 
671
template <class charT, class traits, class Allocator>
 
672
re_detail::re_syntax_base* BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::compile_set(const charT*& first, const charT* last)
 
673
{
 
674
   re_detail::jstack<traits_string_type, Allocator> singles(64, data.allocator());
 
675
   re_detail::jstack<traits_string_type, Allocator> ranges(64, data.allocator());
 
676
   re_detail::jstack<boost::uint_fast32_t, Allocator> classes(64, data.allocator());
 
677
   re_detail::jstack<traits_string_type, Allocator> equivalents(64, data.allocator());
 
678
   bool has_digraphs = false;
 
679
   jm_assert(traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*first) == traits_type::syntax_open_set);
 
680
   ++first;
 
681
   bool started = false;
 
682
   bool done = false;
 
683
   bool isnot = false;
 
684
 
 
685
   enum last_type
 
686
   {
 
687
      last_single,
 
688
      last_none,
 
689
      last_dash
 
690
   };
 
691
 
 
692
   unsigned l = last_none;
 
693
   traits_string_type s;
 
694
 
 
695
   while((first != last) && !done)
 
696
   {
 
697
      traits_size_type c = (traits_size_type)(traits_uchar_type)*first;
 
698
      // this is only used for the switch(), but cannot be folded in
 
699
      // due to a bug in Comeau 4.2.44beta3
 
700
      traits_size_type syntax = traits_inst.syntax_type(c);
 
701
      switch(syntax)
 
702
      {
 
703
      case traits_type::syntax_caret:
 
704
         if(!started && !isnot)
 
705
         {
 
706
            isnot = true;
 
707
         }
 
708
         else
 
709
         {
 
710
            s = (charT)c;
 
711
            goto char_set_literal;
 
712
         }
 
713
         break;
 
714
      case traits_type::syntax_open_set:
 
715
      {
 
716
         if((_flags & char_classes) == 0)
 
717
         {
 
718
            s = (charT)c;
 
719
            goto char_set_literal;
 
720
         }
 
721
         // check to see if we really have a class:
 
722
         const charT* base = first;
 
723
         // this is only used for the switch(), but cannot be folded in
 
724
         // due to a bug in Comeau 4.2.44beta3
 
725
    unsigned int inner_set = parse_inner_set(first, last);
 
726
         switch(inner_set)
 
727
         {
 
728
         case traits_type::syntax_colon:
 
729
            {
 
730
               if(l == last_dash)
 
731
               {
 
732
                  fail(REG_ERANGE);
 
733
                  return 0;
 
734
               }
 
735
               boost::uint_fast32_t id = traits_inst.lookup_classname(base+2, first-2);
 
736
               if(_flags & regbase::icase)
 
737
               {
 
738
                  if((id == traits_type::char_class_upper) || (id == traits_type::char_class_lower))
 
739
                  {
 
740
                     id = traits_type::char_class_alpha;
 
741
                  }
 
742
               }
 
743
               if(id == 0)
 
744
               {
 
745
                  fail(REG_ECTYPE);
 
746
                  return 0;
 
747
               }
 
748
               classes.push(id);
 
749
               started = true;
 
750
               l = last_none;
 
751
            }
 
752
            break;
 
753
         case traits_type::syntax_dot:
 
754
            //
 
755
            // we have a collating element [.collating-name.]
 
756
            //
 
757
            if(traits_inst.lookup_collatename(s, base+2, first-2))
 
758
            {
 
759
               --first;
 
760
               if(s.size() > 1)
 
761
                  has_digraphs = true;
 
762
               if(s.size())goto char_set_literal;
 
763
            }
 
764
            fail(REG_ECOLLATE);
 
765
            return 0;
 
766
         case traits_type::syntax_equal:
 
767
            //
 
768
            // we have an equivalence class [=collating-name=]
 
769
            //
 
770
            if(traits_inst.lookup_collatename(s, base+2, first-2))
 
771
            {
 
772
               std::size_t len = s.size();
 
773
               if(len)
 
774
               {
 
775
                  unsigned i = 0;
 
776
                  while(i < len)
 
777
                  {
 
778
                     s[i] = traits_inst.translate(s[i], (_flags & regbase::icase));
 
779
                     ++i;
 
780
                  }
 
781
                  traits_string_type s2;
 
782
                  traits_inst.transform_primary(s2, s);
 
783
                  equivalents.push(s2);
 
784
                  started = true;
 
785
                  l = last_none;
 
786
                  break;
 
787
               }
 
788
            }
 
789
            fail(REG_ECOLLATE);
 
790
            return 0;
 
791
         case traits_type::syntax_left_word:
 
792
            if((started == false) && (traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*first) == traits_type::syntax_close_set))
 
793
            {
 
794
               ++first;
 
795
               return add_simple(0, re_detail::syntax_element_word_start);
 
796
            }
 
797
            fail(REG_EBRACK);
 
798
            return 0;
 
799
         case traits_type::syntax_right_word:
 
800
            if((started == false) && (traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*first) == traits_type::syntax_close_set))
 
801
            {
 
802
               ++first;
 
803
               return add_simple(0, re_detail::syntax_element_word_end);
 
804
            }
 
805
            fail(REG_EBRACK);
 
806
            return 0;
 
807
         default:
 
808
            if(started == false)
 
809
            {
 
810
               unsigned int t = traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*(base+1));
 
811
               if((t != traits_type::syntax_colon) && (t != traits_type::syntax_dot) && (t != traits_type::syntax_equal))
 
812
               {
 
813
                  first = base;
 
814
                  s = (charT)c;
 
815
                  goto char_set_literal;
 
816
               }
 
817
            }
 
818
            fail(REG_EBRACK);
 
819
            return 0;
 
820
         }
 
821
         if(first == last)
 
822
         {
 
823
            fail(REG_EBRACK);
 
824
            return 0;
 
825
         }
 
826
         continue;
 
827
      }
 
828
      case traits_type::syntax_close_set:
 
829
         if(started == false)
 
830
         {
 
831
            s = (charT)c;
 
832
            goto char_set_literal;
 
833
         }
 
834
         done = true;
 
835
         break;
 
836
      case traits_type::syntax_dash:
 
837
         if(!started)
 
838
         {
 
839
            s = (charT)c;
 
840
            goto char_set_literal;
 
841
         }
 
842
         ++first;
 
843
         if(traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*first) == traits_type::syntax_close_set)
 
844
         {
 
845
            --first;
 
846
            s = (charT)c;
 
847
            goto char_set_literal;
 
848
         }
 
849
         if((singles.empty() == true) || (l != last_single))
 
850
         {
 
851
            fail(REG_ERANGE);
 
852
            return 0;
 
853
         }
 
854
         ranges.push(singles.peek());
 
855
         if(singles.peek().size() <= 1)  // leave digraphs and ligatures in place
 
856
            singles.pop();
 
857
         l = last_dash;
 
858
         continue;
 
859
      case traits_type::syntax_slash:
 
860
         if(_flags & regbase::escape_in_lists)
 
861
         {
 
862
            ++first;
 
863
            if(first == last)
 
864
               continue;
 
865
            traits_size_type c = (traits_size_type)(traits_uchar_type)*first;
 
866
            // this is only used for the switch(), but cannot be folded in
 
867
            // due to a bug in Comeau 4.2.44beta3
 
868
            traits_size_type syntax = traits_inst.syntax_type(c);
 
869
            switch(syntax)
 
870
            {
 
871
            case traits_type::syntax_w:
 
872
               if(l == last_dash)
 
873
               {
 
874
                  fail(REG_ERANGE);
 
875
                  return 0;
 
876
               }
 
877
               classes.push(traits_type::char_class_word);
 
878
               started = true;
 
879
               l = last_none;
 
880
               ++first;
 
881
               continue;
 
882
            case traits_type::syntax_d:
 
883
               if(l == last_dash)
 
884
               {
 
885
                  fail(REG_ERANGE);
 
886
                  return 0;
 
887
               }
 
888
               classes.push(traits_type::char_class_digit);
 
889
               started = true;
 
890
               l = last_none;
 
891
               ++first;
 
892
               continue;
 
893
            case traits_type::syntax_s:
 
894
               if(l == last_dash)
 
895
               {
 
896
                  fail(REG_ERANGE);
 
897
                  return 0;
 
898
               }
 
899
               classes.push(traits_type::char_class_space);
 
900
               started = true;
 
901
               l = last_none;
 
902
               ++first;
 
903
               continue;
 
904
            case traits_type::syntax_l:
 
905
               if(l == last_dash)
 
906
               {
 
907
                  fail(REG_ERANGE);
 
908
                  return 0;
 
909
               }
 
910
               classes.push(traits_type::char_class_lower);
 
911
               started = true;
 
912
               l = last_none;
 
913
               ++first;
 
914
               continue;
 
915
            case traits_type::syntax_u:
 
916
               if(l == last_dash)
 
917
               {
 
918
                  fail(REG_ERANGE);
 
919
                  return 0;
 
920
               }
 
921
               classes.push(traits_type::char_class_upper);
 
922
               started = true;
 
923
               l = last_none;
 
924
               ++first;
 
925
               continue;
 
926
            case traits_type::syntax_W:
 
927
            case traits_type::syntax_D:
 
928
            case traits_type::syntax_S:
 
929
            case traits_type::syntax_U:
 
930
            case traits_type::syntax_L:
 
931
               fail(REG_EESCAPE);
 
932
               return 0;
 
933
            default:
 
934
               c = parse_escape(first, last);
 
935
               --first;
 
936
               s = (charT)c;
 
937
               goto char_set_literal;
 
938
            }
 
939
         }
 
940
         else
 
941
         {
 
942
            s = (charT)c;
 
943
            goto char_set_literal;
 
944
         }
 
945
      default:
 
946
         s = (charT)c;
 
947
         char_set_literal:
 
948
         unsigned i = 0;
 
949
         // get string length to stop us going past the end of string (DWA)
 
950
         std::size_t len = s.size();
 
951
         while(i < len)
 
952
         {
 
953
            s[i] = traits_inst.translate(s[i], (_flags & regbase::icase));
 
954
            ++i;
 
955
         }
 
956
         started = true;
 
957
         if(l == last_dash)
 
958
         {
 
959
            ranges.push(s);
 
960
            l = last_none;
 
961
            if(s.size() > 1)   // add ligatures to singles list as well
 
962
               singles.push(s);
 
963
         }
 
964
         else
 
965
         {
 
966
            singles.push(s);
 
967
            l = last_single;
 
968
         }
 
969
      }
 
970
      ++first;
 
971
   }
 
972
   if(!done)
 
973
      return 0;
 
974
 
 
975
   typedef typename re_detail::is_byte<charT>::width_type width_type;
 
976
   
 
977
   re_detail::re_syntax_base* result;
 
978
   if(has_digraphs)
 
979
      result = compile_set_aux(singles, ranges, classes, equivalents, isnot, re_detail::_wide_type());
 
980
   else
 
981
      result = compile_set_aux(singles, ranges, classes, equivalents, isnot, width_type());
 
982
   #ifdef __BORLANDC__
 
983
   // delayed throw:
 
984
   if((result == 0) && (_flags & regbase::use_except))
 
985
      fail(error_code());
 
986
   #endif
 
987
   return result;
 
988
}
 
989
 
 
990
template <class charT, class traits, class Allocator>
 
991
re_detail::re_syntax_base* BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::compile_set_aux(re_detail::jstack<traits_string_type, Allocator>& singles, re_detail::jstack<traits_string_type, Allocator>& ranges, re_detail::jstack<boost::uint_fast32_t, Allocator>& classes, re_detail::jstack<traits_string_type, Allocator>& equivalents, bool isnot, const re_detail::_wide_type&)
 
992
{
 
993
   size_type base = data.size();
 
994
   data.extend(sizeof(re_detail::re_set_long));
 
995
   unsigned int csingles = 0;
 
996
   unsigned int cranges = 0;
 
997
   boost::uint_fast32_t cclasses = 0;
 
998
   unsigned int cequivalents = 0;
 
999
   bool nocollate_state = flags() & regbase::nocollate;
 
1000
 
 
1001
   while(singles.empty() == false)
 
1002
   {
 
1003
      ++csingles;
 
1004
      const traits_string_type& s = singles.peek();
 
1005
      std::size_t len = (s.size() + 1) * sizeof(charT);
 
1006
      std::memcpy(reinterpret_cast<charT*>(data.extend(len)), s.c_str(), len);
 
1007
      singles.pop();
 
1008
   }
 
1009
   while(ranges.empty() == false)
 
1010
   {
 
1011
      traits_string_type c1, c2;
 
1012
      if(nocollate_state)
 
1013
         c1 = ranges.peek();
 
1014
      else
 
1015
         traits_inst.transform(c1, ranges.peek());
 
1016
      ranges.pop();
 
1017
      if(nocollate_state)
 
1018
         c2 = ranges.peek();
 
1019
      else
 
1020
         traits_inst.transform(c2, ranges.peek());
 
1021
      ranges.pop();
 
1022
      if(c1 < c2)
 
1023
      {
 
1024
         // for some reason bc5 crashes when throwing exceptions
 
1025
         // from here - probably an EH-compiler bug, but hard to
 
1026
         // be sure...
 
1027
         // delay throw to later:
 
1028
         #ifdef __BORLANDC__
 
1029
         boost::uint_fast32_t f = _flags;
 
1030
         _flags &= ~regbase::use_except;
 
1031
         #endif
 
1032
         fail(REG_ERANGE);
 
1033
         #ifdef __BORLANDC__
 
1034
         _flags = f;
 
1035
         #endif
 
1036
         return 0;
 
1037
      }
 
1038
      ++cranges;
 
1039
      std::size_t len = (re_detail::re_strlen(c1.c_str()) + 1) * sizeof(charT);
 
1040
      std::memcpy(data.extend(len), c1.c_str(), len);
 
1041
      len = (re_detail::re_strlen(c2.c_str()) + 1) * sizeof(charT);
 
1042
      std::memcpy(data.extend(len), c2.c_str(), len);
 
1043
   }
 
1044
   while(classes.empty() == false)
 
1045
   {
 
1046
      cclasses |= classes.peek();
 
1047
      classes.pop();
 
1048
   }
 
1049
   while(equivalents.empty() == false)
 
1050
   {
 
1051
      ++cequivalents;
 
1052
      const traits_string_type& s = equivalents.peek();
 
1053
      std::size_t len = (re_detail::re_strlen(s.c_str()) + 1) * sizeof(charT);
 
1054
      std::memcpy(reinterpret_cast<charT*>(data.extend(len)), s.c_str(), len);
 
1055
      equivalents.pop();
 
1056
   }
 
1057
 
 
1058
   re_detail::re_set_long* dat = reinterpret_cast<re_detail::re_set_long*>(reinterpret_cast<unsigned char*>(data.data()) + base);
 
1059
   dat->type = re_detail::syntax_element_long_set;
 
1060
   dat->csingles = csingles;
 
1061
   dat->cranges = cranges;
 
1062
   dat->cclasses = cclasses;
 
1063
   dat->cequivalents = cequivalents;
 
1064
   dat->isnot = isnot;
 
1065
   dat->next.i = 0;
 
1066
   return dat;
 
1067
}
 
1068
 
 
1069
template <class charT, class traits, class Allocator>
 
1070
re_detail::re_syntax_base* BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::compile_set_aux(re_detail::jstack<traits_string_type, Allocator>& singles, re_detail::jstack<traits_string_type, Allocator>& ranges, re_detail::jstack<boost::uint_fast32_t, Allocator>& classes, re_detail::jstack<traits_string_type, Allocator>& equivalents, bool isnot, const re_detail::_narrow_type&)
 
1071
{
 
1072
   re_detail::re_set* dat = reinterpret_cast<re_detail::re_set*>(data.extend(sizeof(re_detail::re_set)));
 
1073
   std::memset(dat, 0, sizeof(re_detail::re_set));
 
1074
 
 
1075
   while(singles.empty() == false)
 
1076
   {
 
1077
      dat->_map[(traits_size_type)(traits_uchar_type)*(singles.peek().c_str())] = re_detail::mask_all;
 
1078
      singles.pop();
 
1079
   }
 
1080
   while(ranges.empty() == false)
 
1081
   {
 
1082
      traits_string_type c1, c2, c3, c4;
 
1083
 
 
1084
      if(flags() & regbase::nocollate)
 
1085
         c1 = ranges.peek();
 
1086
      else
 
1087
         traits_inst.transform(c1, ranges.peek());
 
1088
      ranges.pop();
 
1089
      if(flags() & regbase::nocollate)
 
1090
         c2 = ranges.peek();
 
1091
      else
 
1092
         traits_inst.transform(c2, ranges.peek());
 
1093
      ranges.pop();
 
1094
 
 
1095
      if(c1 < c2)
 
1096
      {
 
1097
         // for some reason bc5 crashes when throwing exceptions
 
1098
         // from here - probably an EH-compiler bug, but hard to
 
1099
         // be sure...
 
1100
         // delay throw to later:
 
1101
         #ifdef __BORLANDC__
 
1102
         boost::uint_fast32_t f = _flags;
 
1103
         _flags &= ~regbase::use_except;
 
1104
         #endif
 
1105
         fail(REG_ERANGE);
 
1106
         #ifdef __BORLANDC__
 
1107
         _flags = f;
 
1108
         #endif
 
1109
         return 0;
 
1110
      }
 
1111
      for(unsigned int i = 0; i < 256; ++i)
 
1112
      {
 
1113
         c4 = (charT)i;
 
1114
         if(flags() & regbase::nocollate)
 
1115
            c3 = c4;
 
1116
         else
 
1117
            traits_inst.transform(c3, c4);
 
1118
         if((c3 <= c1) && (c3 >= c2))
 
1119
            dat->_map[i] = re_detail::mask_all;
 
1120
      }
 
1121
   }
 
1122
   while(equivalents.empty() == false)
 
1123
   {
 
1124
      traits_string_type c1, c2;
 
1125
      for(unsigned int i = 0; i < 256; ++i)
 
1126
      {
 
1127
         c2 = (charT)i;
 
1128
         traits_inst.transform_primary(c1, c2);
 
1129
         if(c1 == equivalents.peek())
 
1130
            dat->_map[i] = re_detail::mask_all;
 
1131
      }
 
1132
      equivalents.pop();
 
1133
   }
 
1134
 
 
1135
   boost::uint_fast32_t flags = 0;
 
1136
   while(classes.empty() == false)
 
1137
   {
 
1138
      flags |= classes.peek();
 
1139
      classes.pop();
 
1140
   }
 
1141
   if(flags)
 
1142
   {
 
1143
      for(unsigned int i = 0; i < 256; ++i)
 
1144
      {
 
1145
         if(traits_inst.is_class(charT(i), flags))
 
1146
            dat->_map[(traits_uchar_type)traits_inst.translate((charT)i, (_flags & regbase::icase))] = re_detail::mask_all;
 
1147
      }
 
1148
   }
 
1149
 
 
1150
   if(isnot)
 
1151
   {
 
1152
      for(unsigned int i = 0; i < 256; ++i)
 
1153
      {
 
1154
         dat->_map[i] = !dat->_map[i];
 
1155
      }
 
1156
   }
 
1157
 
 
1158
   dat->type = re_detail::syntax_element_set;
 
1159
   dat->next.i = 0;
 
1160
   return dat;
 
1161
}
 
1162
 
 
1163
#ifndef __CODEGUARD__
 
1164
// this must not be inline when Borland's codeguard support is turned
 
1165
// on, otherwise we _will_ get surious codeguard errors...
 
1166
inline
 
1167
#endif
 
1168
 re_detail::re_syntax_base* add_offset(void* base, std::ptrdiff_t off)
 
1169
{
 
1170
   return reinterpret_cast<re_detail::re_syntax_base*>(reinterpret_cast<char*>(base) + off);
 
1171
}
 
1172
 
 
1173
 
 
1174
template <class charT, class traits, class Allocator>
 
1175
void BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::fixup_apply(re_detail::re_syntax_base* b, unsigned cbraces)
 
1176
{
 
1177
   typedef typename boost::detail::rebind_allocator<bool, Allocator>::type b_alloc;
 
1178
   
 
1179
   register unsigned char* base = reinterpret_cast<unsigned char*>(b);
 
1180
   register re_detail::re_syntax_base* ptr = b;
 
1181
   bool* pb = 0;
 
1182
   b_alloc a(data.allocator());
 
1183
#ifndef BOOST_NO_EXCEPTIONS
 
1184
   try
 
1185
   {
 
1186
#endif
 
1187
      pb = a.allocate(cbraces);
 
1188
      BOOST_REGEX_NOEH_ASSERT(pb)
 
1189
      for(unsigned i = 0; i < cbraces; ++i)
 
1190
         pb[i] = false;
 
1191
 
 
1192
      repeats = 0;
 
1193
 
 
1194
      while(ptr->next.i)
 
1195
      {
 
1196
         switch(ptr->type)
 
1197
         {
 
1198
         case re_detail::syntax_element_rep:
 
1199
            jm_assert(data.size() > static_cast<re_detail::re_jump*>(ptr)->alt.i);
 
1200
            static_cast<re_detail::re_jump*>(ptr)->alt.p = add_offset(base, static_cast<re_detail::re_jump*>(ptr)->alt.i);
 
1201
#ifdef BOOST_REGEX_DEBUG
 
1202
            if((re_detail::padding_mask & reinterpret_cast<int>(static_cast<re_detail::re_jump*>(ptr)->alt.p)) && (static_cast<re_detail::re_jump*>(ptr)->alt.p != b))
 
1203
            {
 
1204
               jm_trace("padding mis-aligment in repeat jump to object type: " << static_cast<re_detail::re_jump*>(ptr)->alt.p->type)
 
1205
               //jm_assert(0 == (padding_mask & (int)((re_detail::re_jump*)ptr)->alt.p));
 
1206
            }
 
1207
#endif
 
1208
            static_cast<re_detail::re_repeat*>(ptr)->id = repeats;
 
1209
            ++repeats;
 
1210
            goto rebase;
 
1211
         case re_detail::syntax_element_jump:
 
1212
         case re_detail::syntax_element_alt:
 
1213
            jm_assert(data.size() > static_cast<re_detail::re_jump*>(ptr)->alt.i);
 
1214
            static_cast<re_detail::re_jump*>(ptr)->alt.p = add_offset(base, static_cast<re_detail::re_jump*>(ptr)->alt.i);
 
1215
#ifdef BOOST_REGEX_DEBUG
 
1216
            if((re_detail::padding_mask & reinterpret_cast<int>(static_cast<re_detail::re_jump*>(ptr)->alt.p) && (static_cast<re_detail::re_jump*>(ptr)->alt.p != b)))
 
1217
            {
 
1218
               jm_trace("padding mis-aligment in alternation jump to object type: " << static_cast<re_detail::re_jump*>(ptr)->alt.p->type)
 
1219
               //jm_assert(0 == (padding_mask & (int)((re_detail::re_jump*)ptr)->alt.p));
 
1220
            }
 
1221
#endif
 
1222
            goto rebase;
 
1223
         case re_detail::syntax_element_backref:
 
1224
            if((static_cast<re_detail::re_brace*>(ptr)->index >= (int)cbraces) || (pb[static_cast<re_detail::re_brace*>(ptr)->index] == false) )
 
1225
            {
 
1226
               fail(REG_ESUBREG);
 
1227
               a.deallocate(pb, cbraces);
 
1228
               return;
 
1229
            }
 
1230
            goto rebase;
 
1231
         case re_detail::syntax_element_endmark:
 
1232
            if(static_cast<re_detail::re_brace*>(ptr)->index > 0)
 
1233
               pb[static_cast<re_detail::re_brace*>(ptr)->index] = true;
 
1234
            goto rebase;
 
1235
         default:
 
1236
            rebase:
 
1237
            jm_assert(data.size() > ptr->next.i);
 
1238
            ptr->next.p = add_offset(base, ptr->next.i);
 
1239
#ifdef BOOST_REGEX_DEBUG
 
1240
            if((re_detail::padding_mask & (int)(ptr->next.p)) && (static_cast<re_detail::re_jump*>(ptr)->alt.p != b))
 
1241
            {
 
1242
               jm_trace("padding mis-alignment in next record of type " << ptr->next.p->type)
 
1243
               jm_assert(0 == (re_detail::padding_mask & (int)(ptr->next.p)));
 
1244
            }
 
1245
#endif
 
1246
            ptr = ptr->next.p;
 
1247
         }
 
1248
      }
 
1249
      a.deallocate(pb, cbraces);
 
1250
      pb = 0;
 
1251
#ifndef BOOST_NO_EXCEPTIONS
 
1252
   }
 
1253
   catch(...)
 
1254
   {
 
1255
      if(pb)
 
1256
         a.deallocate(pb, cbraces);
 
1257
      throw;
 
1258
   }
 
1259
#endif
 
1260
}
 
1261
 
 
1262
 
 
1263
template <class charT, class traits, class Allocator>
 
1264
unsigned int BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::set_expression(const charT* p, const charT* end, flag_type f)
 
1265
{
 
1266
# ifdef BOOST_MSVC
 
1267
#  pragma warning(push)
 
1268
#  pragma warning(disable: 4127)
 
1269
#endif
 
1270
#ifdef __OpenBSD__
 
1271
   // strxfrm not working on OpenBSD??
 
1272
   f |= regbase::nocollate;
 
1273
#endif
 
1274
 
 
1275
   if(p == expression())
 
1276
   {
 
1277
      traits_string_type s(p, end);
 
1278
      return set_expression(s.c_str(), s.c_str() + s.size(), f);
 
1279
   }
 
1280
   typedef typename traits_type::sentry sentry_t;
 
1281
   sentry_t sent(traits_inst);
 
1282
   if(sent){
 
1283
 
 
1284
   const charT* base = p;
 
1285
   data.clear();
 
1286
   _flags = f;
 
1287
   fail(REG_NOERROR);  // clear any error
 
1288
 
 
1289
   if(p >= end)
 
1290
   {
 
1291
      fail(REG_EMPTY);
 
1292
      return error_code();
 
1293
   }
 
1294
 
 
1295
   const charT* ptr = p;
 
1296
   marks = 0;
 
1297
   re_detail::jstack<std::size_t, Allocator> mark(64, data.allocator());
 
1298
   re_detail::jstack<int, Allocator> markid(64, data.allocator());
 
1299
   std::size_t last_mark_popped = 0;
 
1300
   register traits_size_type c;
 
1301
   register re_detail::re_syntax_base* dat;
 
1302
 
 
1303
   unsigned rep_min = 0;
 
1304
   unsigned rep_max = 0;
 
1305
 
 
1306
   //
 
1307
   // set up header:
 
1308
   //
 
1309
   ++marks;
 
1310
   dat = 0;
 
1311
 
 
1312
   if(_flags & regbase::literal)
 
1313
   {
 
1314
      while(ptr != end)
 
1315
      {
 
1316
         dat = add_literal(dat, traits_inst.translate(*ptr, (_flags & regbase::icase)));
 
1317
         ++ptr;
 
1318
      }
 
1319
   }
 
1320
 
 
1321
   while (ptr < end)
 
1322
   {
 
1323
      c = (traits_size_type)(traits_uchar_type)*ptr;
 
1324
      // this is only used for the switch(), but cannot be folded in
 
1325
      // due to a bug in Comeau 4.2.44beta3
 
1326
      traits_size_type syntax = traits_inst.syntax_type(c);
 
1327
      switch(syntax)
 
1328
      {
 
1329
      case traits_type::syntax_open_bracket:
 
1330
         if(_flags & bk_parens)
 
1331
         {
 
1332
            dat = add_literal(dat, (charT)c);
 
1333
            ++ptr;
 
1334
            continue;
 
1335
         }
 
1336
         open_bracked_jump:
 
1337
         // extend:
 
1338
         dat = add_simple(dat, re_detail::syntax_element_startmark, sizeof(re_detail::re_brace));
 
1339
         markid.push(marks);
 
1340
         static_cast<re_detail::re_brace*>(dat)->index = marks++;
 
1341
         mark.push(data.index(dat));
 
1342
         ++ptr;
 
1343
         //
 
1344
         // check for perl like (?...) extention syntax
 
1345
         c = (traits_size_type)(traits_uchar_type)*ptr;
 
1346
         if(((_flags & bk_parens) == 0) && (traits_type::syntax_question == traits_inst.syntax_type(c)))
 
1347
         {
 
1348
            ++ptr;
 
1349
            c = (traits_size_type)(traits_uchar_type)*ptr;
 
1350
            // this is only used for the switch(), but cannot be folded in
 
1351
            // due to a bug in Comeau 4.2.44beta3
 
1352
            traits_size_type syntax = traits_inst.syntax_type(c);
 
1353
            switch(syntax)
 
1354
            {
 
1355
            case traits_type::syntax_colon:
 
1356
               static_cast<re_detail::re_brace*>(dat)->index = 0;
 
1357
               --marks;
 
1358
               markid.pop();
 
1359
               markid.push(0);
 
1360
               ++ptr;
 
1361
               continue;
 
1362
            case traits_type::syntax_equal:
 
1363
               static_cast<re_detail::re_brace*>(dat)->index = -1;
 
1364
               markid.pop();
 
1365
               markid.push(-1);
 
1366
               common_forward_assert:
 
1367
               --marks;
 
1368
               ++ptr;
 
1369
               // extend:
 
1370
               dat = add_simple(dat, re_detail::syntax_element_jump, re_detail::re_jump_size);
 
1371
               data.align();
 
1372
               //
 
1373
               // we don't know what value to put here yet,
 
1374
               // use an arbitrarily large value for now
 
1375
               // and check it later:
 
1376
               static_cast<re_detail::re_jump*>(dat)->alt.i = INT_MAX/2;
 
1377
               mark.push(data.size() - re_detail::re_jump_size);
 
1378
               continue;
 
1379
            case traits_type::syntax_not:
 
1380
               static_cast<re_detail::re_brace*>(dat)->index = -2;
 
1381
               markid.pop();
 
1382
               markid.push(-2);
 
1383
               goto common_forward_assert;
 
1384
            case traits_type::syntax_hash:
 
1385
               // comment just skip it:
 
1386
               static_cast<re_detail::re_brace*>(dat)->index = 0;
 
1387
               --marks;
 
1388
               markid.pop();
 
1389
               mark.pop();
 
1390
               do{
 
1391
                  ++ptr;
 
1392
                  c = (traits_size_type)(traits_uchar_type)*ptr;
 
1393
               }while(traits_type::syntax_close_bracket != traits_inst.syntax_type(c));
 
1394
               ++ptr;
 
1395
               continue;
 
1396
            default:
 
1397
               //
 
1398
               // error, return to standard parsing and let that handle the error:
 
1399
               --ptr;
 
1400
               continue;
 
1401
            }
 
1402
         }
 
1403
         break;
 
1404
      case traits_type::syntax_close_bracket:
 
1405
         if(_flags & bk_parens)
 
1406
         {
 
1407
            dat = add_literal(dat, (charT)c);
 
1408
            ++ptr;
 
1409
            continue;
 
1410
         }
 
1411
         
 
1412
         close_bracked_jump:
 
1413
         if(dat)
 
1414
         {
 
1415
            data.align();
 
1416
            dat->next.i = data.size();
 
1417
         }
 
1418
 
 
1419
         if(mark.empty())
 
1420
         {
 
1421
            fail(REG_EPAREN);
 
1422
            return error_code();
 
1423
         }
 
1424
         // see if we have an empty alternative:
 
1425
         if(mark.peek() == data.index(dat) )
 
1426
         {
 
1427
            re_detail::re_syntax_base* para = reinterpret_cast<re_detail::re_syntax_base*>(reinterpret_cast<char*>(data.data()) + mark.peek());
 
1428
            if(para->type == re_detail::syntax_element_jump)
 
1429
            {
 
1430
               fail(REG_EMPTY);
 
1431
               return error_code();
 
1432
            }
 
1433
         }
 
1434
 
 
1435
         // pop any pushed alternatives and set the target end destination:
 
1436
         dat = reinterpret_cast<re_detail::re_syntax_base*>(reinterpret_cast<unsigned char*>(data.data()) + mark.peek());
 
1437
         while(dat->type == re_detail::syntax_element_jump)
 
1438
         {
 
1439
            static_cast<re_detail::re_jump*>(dat)->alt.i = data.size();
 
1440
            mark.pop();
 
1441
            if(mark.empty())
 
1442
            {
 
1443
               fail(REG_EPAREN);
 
1444
               return error_code();
 
1445
            }
 
1446
            dat = reinterpret_cast<re_detail::re_jump*>(reinterpret_cast<unsigned char*>(data.data()) + mark.peek());
 
1447
         }
 
1448
 
 
1449
         dat = add_simple(0, re_detail::syntax_element_endmark, sizeof(re_detail::re_brace));
 
1450
         static_cast<re_detail::re_brace*>(dat)->index = markid.peek();
 
1451
         markid.pop();
 
1452
         last_mark_popped = mark.peek();
 
1453
         mark.pop();
 
1454
         ++ptr;
 
1455
         break;
 
1456
      case traits_type::syntax_char:
 
1457
         dat = add_literal(dat, (charT)c);
 
1458
         ++ptr;
 
1459
         break;
 
1460
      case traits_type::syntax_slash:
 
1461
      {
 
1462
         if(++ptr == end)
 
1463
         {
 
1464
            fail(REG_EESCAPE);
 
1465
            return error_code();
 
1466
         }
 
1467
         c = (traits_size_type)(traits_uchar_type)*ptr;
 
1468
         // this is only used for the switch(), but cannot be folded in
 
1469
         // due to a bug in Comeau 4.2.44beta3
 
1470
         traits_size_type syntax = traits_inst.syntax_type(c);
 
1471
         switch(syntax)
 
1472
         {
 
1473
         case traits_type::syntax_open_bracket:
 
1474
            if(_flags & bk_parens)
 
1475
               goto open_bracked_jump;
 
1476
            break;
 
1477
         case traits_type::syntax_close_bracket:
 
1478
            if(_flags & bk_parens)
 
1479
               goto close_bracked_jump;
 
1480
            break;
 
1481
         case traits_type::syntax_plus:
 
1482
            if((_flags & bk_plus_qm) && ((_flags & limited_ops) == 0))
 
1483
            {
 
1484
               rep_min = 1;
 
1485
               rep_max = (unsigned)-1;
 
1486
               goto repeat_jump;
 
1487
            }
 
1488
            break;
 
1489
         case traits_type::syntax_question:
 
1490
            if((_flags & bk_plus_qm) && ((_flags & limited_ops) == 0))
 
1491
            {
 
1492
               rep_min = 0;
 
1493
               rep_max = 1;
 
1494
               goto repeat_jump;
 
1495
            }
 
1496
            break;
 
1497
         case traits_type::syntax_or:
 
1498
            if(((_flags & bk_vbar) == 0) || (_flags & limited_ops))
 
1499
               break;
 
1500
            goto alt_string_jump;
 
1501
         case traits_type::syntax_open_brace:
 
1502
            if( ((_flags & bk_braces) == 0) || ((_flags & intervals) == 0))
 
1503
               break;
 
1504
 
 
1505
            // we have {x} or {x,} or {x,y}:
 
1506
            parse_range(ptr, end, rep_min, rep_max);
 
1507
            goto repeat_jump;
 
1508
 
 
1509
         case traits_type::syntax_digit:
 
1510
            if(_flags & bk_refs)
 
1511
            {
 
1512
               // update previous:
 
1513
               int i = traits_inst.toi((charT)c);
 
1514
               if(i == 0)
 
1515
               {
 
1516
                  // we can have \025 which means take char whose
 
1517
                  // code is 25 (octal), so parse string:
 
1518
                  c = traits_inst.toi(ptr, end, -8);
 
1519
                  --ptr;
 
1520
                  break;
 
1521
               }
 
1522
               dat = add_simple(dat, re_detail::syntax_element_backref, sizeof(re_detail::re_brace));
 
1523
               static_cast<re_detail::re_brace*>(dat)->index = i;
 
1524
               ++ptr;
 
1525
               continue;
 
1526
            }
 
1527
            break;
 
1528
         case traits_type::syntax_b:     // re_detail::syntax_element_word_boundary
 
1529
            dat = add_simple(dat, re_detail::syntax_element_word_boundary);
 
1530
            ++ptr;
 
1531
            continue;
 
1532
         case traits_type::syntax_B:
 
1533
            dat = add_simple(dat, re_detail::syntax_element_within_word);
 
1534
            ++ptr;
 
1535
            continue;
 
1536
         case traits_type::syntax_left_word:
 
1537
            dat = add_simple(dat, re_detail::syntax_element_word_start);
 
1538
            ++ptr;
 
1539
            continue;
 
1540
         case traits_type::syntax_right_word:
 
1541
            dat = add_simple(dat, re_detail::syntax_element_word_end);
 
1542
            ++ptr;
 
1543
            continue;
 
1544
         case traits_type::syntax_w:     //re_detail::syntax_element_word_char
 
1545
            dat = compile_set_simple(dat, traits_type::char_class_word);
 
1546
            ++ptr;
 
1547
            continue;
 
1548
         case traits_type::syntax_W:
 
1549
            dat = compile_set_simple(dat, traits_type::char_class_word, true);
 
1550
            ++ptr;
 
1551
            continue;
 
1552
         case traits_type::syntax_d:     //re_detail::syntax_element_word_char
 
1553
            dat = compile_set_simple(dat, traits_type::char_class_digit);
 
1554
            ++ptr;
 
1555
            continue;
 
1556
         case traits_type::syntax_D:
 
1557
            dat = compile_set_simple(dat, traits_type::char_class_digit, true);
 
1558
            ++ptr;
 
1559
            continue;
 
1560
         case traits_type::syntax_s:     //re_detail::syntax_element_word_char
 
1561
            dat = compile_set_simple(dat, traits_type::char_class_space);
 
1562
            ++ptr;
 
1563
            continue;
 
1564
         case traits_type::syntax_S:
 
1565
            dat = compile_set_simple(dat, traits_type::char_class_space, true);
 
1566
            ++ptr;
 
1567
            continue;
 
1568
         case traits_type::syntax_l:     //re_detail::syntax_element_word_char
 
1569
            dat = compile_set_simple(dat, traits_type::char_class_lower);
 
1570
            ++ptr;
 
1571
            continue;
 
1572
         case traits_type::syntax_L:
 
1573
            dat = compile_set_simple(dat, traits_type::char_class_lower, true);
 
1574
            ++ptr;
 
1575
            continue;
 
1576
         case traits_type::syntax_u:     //re_detail::syntax_element_word_char
 
1577
            dat = compile_set_simple(dat, traits_type::char_class_upper);
 
1578
            ++ptr;
 
1579
            continue;
 
1580
         case traits_type::syntax_U:
 
1581
            dat = compile_set_simple(dat, traits_type::char_class_upper, true);
 
1582
            ++ptr;
 
1583
            continue;
 
1584
         case traits_type::syntax_Q:
 
1585
            ++ptr;
 
1586
            while(true)
 
1587
            {
 
1588
               if(ptr == end)
 
1589
               {
 
1590
                  fail(REG_EESCAPE);
 
1591
                  return error_code();
 
1592
               }
 
1593
               if(traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*ptr) == traits_type::syntax_slash)
 
1594
               {
 
1595
                  ++ptr;
 
1596
                  if((ptr != end) && (traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*ptr) == traits_type::syntax_E))
 
1597
                     break;
 
1598
                  else
 
1599
                  {
 
1600
                     dat = add_literal(dat, *(ptr-1));
 
1601
                     continue;
 
1602
                  }
 
1603
               }
 
1604
               dat = add_literal(dat, *ptr);
 
1605
               ++ptr;
 
1606
            }
 
1607
            ++ptr;
 
1608
            continue;
 
1609
         case traits_type::syntax_C:
 
1610
            dat = add_simple(dat, re_detail::syntax_element_wild);
 
1611
            ++ptr;
 
1612
            continue;
 
1613
         case traits_type::syntax_X:
 
1614
            dat = add_simple(dat, re_detail::syntax_element_combining);
 
1615
            ++ptr;
 
1616
            continue;
 
1617
         case traits_type::syntax_Z:
 
1618
            dat = add_simple(dat, re_detail::syntax_element_soft_buffer_end);
 
1619
            ++ptr;
 
1620
            continue;
 
1621
         case traits_type::syntax_G:
 
1622
            dat = add_simple(dat, re_detail::syntax_element_restart_continue);
 
1623
            ++ptr;
 
1624
            continue;
 
1625
         case traits_type::syntax_start_buffer:
 
1626
            dat = add_simple(dat, re_detail::syntax_element_buffer_start);
 
1627
            ++ptr;
 
1628
            continue;
 
1629
         case traits_type::syntax_end_buffer:
 
1630
            dat = add_simple(dat, re_detail::syntax_element_buffer_end);
 
1631
            ++ptr;
 
1632
            continue;
 
1633
         default:
 
1634
            c = (traits_size_type)(traits_uchar_type)parse_escape(ptr, end);
 
1635
            dat = add_literal(dat, (charT)c);
 
1636
            continue;
 
1637
         }
 
1638
         dat = add_literal(dat, (charT)c);
 
1639
         ++ptr;
 
1640
         break;
 
1641
      }
 
1642
      case traits_type::syntax_dollar:
 
1643
         dat = add_simple(dat, re_detail::syntax_element_end_line, sizeof(re_detail::re_syntax_base));
 
1644
         ++ptr;
 
1645
         continue;
 
1646
      case traits_type::syntax_caret:
 
1647
         dat = add_simple(dat, re_detail::syntax_element_start_line, sizeof(re_detail::re_syntax_base));
 
1648
         ++ptr;
 
1649
         continue;
 
1650
      case traits_type::syntax_dot:
 
1651
         dat = add_simple(dat, re_detail::syntax_element_wild, sizeof(re_detail::re_syntax_base));
 
1652
         ++ptr;
 
1653
         continue;
 
1654
      case traits_type::syntax_star:
 
1655
         rep_min = 0;
 
1656
         rep_max = (unsigned)-1;
 
1657
 
 
1658
         repeat_jump:
 
1659
         {
 
1660
          std::ptrdiff_t offset;
 
1661
            if(dat == 0)
 
1662
            {
 
1663
               fail(REG_BADRPT);
 
1664
               return error_code();
 
1665
            }
 
1666
            switch(dat->type)
 
1667
            {
 
1668
            case re_detail::syntax_element_endmark:
 
1669
               offset = last_mark_popped;
 
1670
               break;
 
1671
            case re_detail::syntax_element_literal:
 
1672
               if(static_cast<re_detail::re_literal*>(dat)->length > 1)
 
1673
               {
 
1674
                  // update previous:
 
1675
                  charT lit = *reinterpret_cast<charT*>(reinterpret_cast<char*>(dat) + sizeof(re_detail::re_literal) + ((static_cast<re_detail::re_literal*>(dat)->length-1)*sizeof(charT)));
 
1676
                  --static_cast<re_detail::re_literal*>(dat)->length;
 
1677
                  dat = add_simple(dat, re_detail::syntax_element_literal, sizeof(re_detail::re_literal) + sizeof(charT));
 
1678
                  static_cast<re_detail::re_literal*>(dat)->length = 1;
 
1679
                  *reinterpret_cast<charT*>(static_cast<re_detail::re_literal*>(dat)+1) = lit;
 
1680
               }
 
1681
               offset = reinterpret_cast<char*>(dat) - reinterpret_cast<char*>(data.data());
 
1682
               break;
 
1683
            case re_detail::syntax_element_backref:
 
1684
            case re_detail::syntax_element_long_set:
 
1685
            case re_detail::syntax_element_set:
 
1686
            case re_detail::syntax_element_wild:
 
1687
            case re_detail::syntax_element_combining:
 
1688
               // we're repeating a single item:
 
1689
               offset = reinterpret_cast<char*>(dat) - reinterpret_cast<char*>(data.data());
 
1690
               break;
 
1691
            default:
 
1692
               fail(REG_BADRPT);
 
1693
               return error_code();
 
1694
            }
 
1695
            data.align();
 
1696
            dat->next.i = data.size();
 
1697
            //unsigned pos = (char*)dat - (char*)data.data();
 
1698
 
 
1699
            // add the trailing jump:
 
1700
            dat = add_simple(dat, re_detail::syntax_element_jump, re_detail::re_jump_size);
 
1701
            static_cast<re_detail::re_jump*>(dat)->alt.i = 0;
 
1702
 
 
1703
            // now insert the leading repeater:
 
1704
            dat = static_cast<re_detail::re_syntax_base*>(data.insert(offset, re_detail::re_repeater_size));
 
1705
            dat->next.i = (reinterpret_cast<char*>(dat) - reinterpret_cast<char*>(data.data())) + re_detail::re_repeater_size;
 
1706
            dat->type = re_detail::syntax_element_rep;
 
1707
            static_cast<re_detail::re_repeat*>(dat)->alt.i = data.size();
 
1708
            static_cast<re_detail::re_repeat*>(dat)->min = rep_min;
 
1709
            static_cast<re_detail::re_repeat*>(dat)->max = rep_max;
 
1710
            static_cast<re_detail::re_repeat*>(dat)->leading = false;
 
1711
            static_cast<re_detail::re_repeat*>(dat)->greedy = true;
 
1712
            move_offsets(dat, re_detail::re_repeater_size);
 
1713
            ++ptr;
 
1714
            //
 
1715
            // now check to see if we have a non-greedy repeat:
 
1716
            if((ptr != end) && (_flags & (limited_ops | bk_plus_qm | bk_braces)) == 0)
 
1717
            {
 
1718
               c = (traits_size_type)(traits_uchar_type)*ptr;
 
1719
               if(traits_type::syntax_question == traits_inst.syntax_type(c))
 
1720
               {
 
1721
                  // OK repeat is non-greedy:
 
1722
                  static_cast<re_detail::re_repeat*>(dat)->greedy = false;
 
1723
                  ++ptr;
 
1724
               }
 
1725
            }
 
1726
            dat = reinterpret_cast<re_detail::re_syntax_base*>(reinterpret_cast<char*>(data.data()) + data.size() - re_detail::re_jump_size);
 
1727
            static_cast<re_detail::re_repeat*>(dat)->alt.i = offset;
 
1728
            continue;
 
1729
         }
 
1730
      case traits_type::syntax_plus:
 
1731
         if(_flags & (bk_plus_qm | limited_ops))
 
1732
         {
 
1733
            dat = add_literal(dat, (charT)c);
 
1734
            ++ptr;
 
1735
            continue;
 
1736
         }
 
1737
         rep_min = 1;
 
1738
         rep_max = (unsigned)-1;
 
1739
         goto repeat_jump;
 
1740
      case traits_type::syntax_question:
 
1741
         if(_flags & (bk_plus_qm | limited_ops))
 
1742
         {
 
1743
            dat = add_literal(dat, (charT)c);
 
1744
            ++ptr;
 
1745
            continue;
 
1746
         }
 
1747
         rep_min = 0;
 
1748
         rep_max = 1;
 
1749
         goto repeat_jump;
 
1750
      case traits_type::syntax_open_set:
 
1751
         // update previous:
 
1752
         if(dat)
 
1753
         {
 
1754
            data.align();
 
1755
            dat->next.i = data.size();
 
1756
         }
 
1757
         // extend:
 
1758
         dat = compile_set(ptr, end);
 
1759
         if(dat == 0)
 
1760
         {
 
1761
            if((_flags & regbase::failbit) == 0)
 
1762
               fail(REG_EBRACK);
 
1763
            return error_code();
 
1764
         }
 
1765
         break;
 
1766
      case traits_type::syntax_or:
 
1767
      {
 
1768
         if(_flags & (bk_vbar | limited_ops))
 
1769
         {
 
1770
            dat = add_literal(dat, (charT)c);
 
1771
            ++ptr;
 
1772
            continue;
 
1773
         }
 
1774
 
 
1775
         alt_string_jump:
 
1776
 
 
1777
         // update previous:
 
1778
         if(dat == 0)
 
1779
         {
 
1780
            // start of pattern can't have empty "|"
 
1781
            fail(REG_EMPTY);
 
1782
            return error_code();
 
1783
         }
 
1784
         // see if we have an empty alternative:
 
1785
         if(mark.empty() == false)
 
1786
            if(mark.peek() == data.index(dat))
 
1787
            {
 
1788
               fail(REG_EMPTY);
 
1789
               return error_code();
 
1790
            }
 
1791
         // extend:
 
1792
         dat = add_simple(dat, re_detail::syntax_element_jump, re_detail::re_jump_size);
 
1793
         data.align();
 
1794
         //
 
1795
         // we don't know what value to put here yet,
 
1796
         // use an arbitrarily large value for now
 
1797
         // and check it later (TODO!)
 
1798
         static_cast<re_detail::re_jump*>(dat)->alt.i = INT_MAX/2;
 
1799
 
 
1800
         // now work out where to insert:
 
1801
         std::size_t offset = 0;
 
1802
         if(mark.empty() == false)
 
1803
         {
 
1804
            // we have a '(' or '|' to go back to:
 
1805
            offset = mark.peek();
 
1806
            re_detail::re_syntax_base* base = reinterpret_cast<re_detail::re_syntax_base*>(reinterpret_cast<unsigned char*>(data.data()) + offset);
 
1807
            offset = base->next.i;
 
1808
         }
 
1809
         re_detail::re_jump* j = static_cast<re_detail::re_jump*>(data.insert(offset, re_detail::re_jump_size));
 
1810
         j->type = re_detail::syntax_element_alt;
 
1811
         j->next.i = offset + re_detail::re_jump_size;
 
1812
         j->alt.i = data.size();
 
1813
         move_offsets(j, re_detail::re_jump_size);
 
1814
         dat = reinterpret_cast<re_detail::re_syntax_base*>(reinterpret_cast<unsigned char*>(data.data()) + data.size() - re_detail::re_jump_size);
 
1815
         mark.push(data.size() - re_detail::re_jump_size);
 
1816
         ++ptr;
 
1817
         break;
 
1818
      }
 
1819
      case traits_type::syntax_open_brace:
 
1820
         if((_flags & bk_braces) || ((_flags & intervals) == 0))
 
1821
         {
 
1822
            dat = add_literal(dat, (charT)c);
 
1823
            ++ptr;
 
1824
            continue;
 
1825
         }
 
1826
         // we have {x} or {x,} or {x,y}:
 
1827
         parse_range(ptr, end, rep_min, rep_max);
 
1828
         goto repeat_jump;
 
1829
      case traits_type::syntax_newline:
 
1830
         if(_flags & newline_alt)
 
1831
            goto alt_string_jump;
 
1832
         dat = add_literal(dat, (charT)c);
 
1833
         ++ptr;
 
1834
         continue;
 
1835
      case traits_type::syntax_close_brace:
 
1836
         if(_flags & bk_braces)
 
1837
         {
 
1838
            dat = add_literal(dat, (charT)c);
 
1839
            ++ptr;
 
1840
            continue;
 
1841
         }
 
1842
         fail(REG_BADPAT);
 
1843
         return error_code();
 
1844
      default:
 
1845
         dat = add_literal(dat, (charT)c);
 
1846
         ++ptr;
 
1847
         break;
 
1848
      }  // switch
 
1849
   }     // while
 
1850
 
 
1851
   //
 
1852
   // update previous:
 
1853
   if(dat)
 
1854
   {
 
1855
      data.align();
 
1856
      dat->next.i = data.size();
 
1857
   }
 
1858
 
 
1859
   // see if we have an empty alternative:
 
1860
   if(mark.empty() == false)
 
1861
      if(mark.peek() == data.index(dat) )
 
1862
      {
 
1863
         re_detail::re_syntax_base* para = reinterpret_cast<re_detail::re_syntax_base*>(reinterpret_cast<char*>(data.data()) + mark.peek());
 
1864
         if(para->type == re_detail::syntax_element_jump)
 
1865
         {
 
1866
            fail(REG_EMPTY);
 
1867
            return error_code();
 
1868
         }
 
1869
      }
 
1870
   //
 
1871
   // set up tail:
 
1872
   //
 
1873
   if(mark.empty() == false)
 
1874
   {
 
1875
      // pop any pushed alternatives and set the target end destination:
 
1876
      dat = reinterpret_cast<re_detail::re_syntax_base*>(reinterpret_cast<unsigned char*>(data.data()) + mark.peek());
 
1877
      while(dat->type == re_detail::syntax_element_jump)
 
1878
      {
 
1879
         static_cast<re_detail::re_jump*>(dat)->alt.i = data.size();
 
1880
         mark.pop();
 
1881
         if(mark.empty() == true)
 
1882
            break;
 
1883
         dat = reinterpret_cast<re_detail::re_jump*>(reinterpret_cast<unsigned char*>(data.data()) + mark.peek());
 
1884
      }
 
1885
   }
 
1886
 
 
1887
   dat = static_cast<re_detail::re_brace*>(data.extend(sizeof(re_detail::re_syntax_base)));
 
1888
   dat->type = re_detail::syntax_element_match;
 
1889
   dat->next.i = 0;
 
1890
 
 
1891
   if(mark.empty() == false)
 
1892
   {
 
1893
      fail(REG_EPAREN);
 
1894
      return error_code();
 
1895
   }
 
1896
 
 
1897
   //
 
1898
   // allocate space for start _map:
 
1899
   startmap = reinterpret_cast<unsigned char*>(data.extend(256 + ((end - base + 1) * sizeof(charT))));
 
1900
   //
 
1901
   // and copy the expression we just compiled:
 
1902
   _expression = reinterpret_cast<charT*>(reinterpret_cast<char*>(startmap) + 256);
 
1903
   _expression_len = end - base;
 
1904
   std::memcpy(_expression, base, _expression_len * sizeof(charT));
 
1905
   *(_expression + _expression_len) = charT(0);
 
1906
 
 
1907
   //
 
1908
   // now we need to apply fixups to the array
 
1909
   // so that we can use pointers and not indexes
 
1910
   fixup_apply(static_cast<re_detail::re_syntax_base*>(data.data()), marks);
 
1911
 
 
1912
   // check for error during fixup:
 
1913
   if(_flags & regbase::failbit)
 
1914
      return error_code();
 
1915
 
 
1916
   //
 
1917
   // finally compile the maps so that we can make intelligent choices
 
1918
   // whenever we encounter an alternative:
 
1919
   compile_maps();
 
1920
   if(pkmp)
 
1921
   {
 
1922
      re_detail::kmp_free(pkmp, data.allocator());
 
1923
      pkmp = 0;
 
1924
   }
 
1925
   re_detail::re_syntax_base* sbase = static_cast<re_detail::re_syntax_base*>(data.data());
 
1926
   _restart_type = probe_restart(sbase);
 
1927
   _leading_len = fixup_leading_rep(sbase, 0);
 
1928
   if((sbase->type == re_detail::syntax_element_literal) && (sbase->next.p->type == re_detail::syntax_element_match))
 
1929
   {
 
1930
      _restart_type = restart_fixed_lit;
 
1931
      if(0 == pkmp)
 
1932
      {
 
1933
         charT* p1 = reinterpret_cast<charT*>(reinterpret_cast<char*>(sbase) + sizeof(re_detail::re_literal));
 
1934
         charT* p2 = p1 + static_cast<re_detail::re_literal*>(sbase)->length;
 
1935
         pkmp = re_detail::kmp_compile(p1, p2, charT(), re_detail::kmp_translator<traits>(_flags&regbase::icase, &traits_inst), data.allocator());
 
1936
      }
 
1937
   }
 
1938
   return error_code();
 
1939
 
 
1940
   } // sentry
 
1941
   return REG_EMPTY;
 
1942
 
 
1943
# ifdef BOOST_MSVC
 
1944
#  pragma warning(pop)
 
1945
#endif
 
1946
 
 
1947
}
 
1948
 
 
1949
template <class charT, class traits, class Allocator>
 
1950
re_detail::re_syntax_base* BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::add_simple(re_detail::re_syntax_base* dat, re_detail::syntax_element_type type, unsigned int size)
 
1951
{
 
1952
   if(dat)
 
1953
   {
 
1954
      data.align();
 
1955
      dat->next.i = data.size();
 
1956
   }
 
1957
   if(size < sizeof(re_detail::re_syntax_base))
 
1958
      size = sizeof(re_detail::re_syntax_base);
 
1959
   dat = static_cast<re_detail::re_syntax_base*>(data.extend(size));
 
1960
   dat->type = type;
 
1961
   dat->next.i = 0;
 
1962
   return dat;
 
1963
}
 
1964
 
 
1965
template <class charT, class traits, class Allocator>
 
1966
re_detail::re_syntax_base* BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::add_literal(re_detail::re_syntax_base* dat, charT c)
 
1967
{
 
1968
   if(dat && (dat->type == re_detail::syntax_element_literal))
 
1969
   {
 
1970
      // add another charT to the list:
 
1971
      std::ptrdiff_t pos = reinterpret_cast<unsigned char*>(dat) - reinterpret_cast<unsigned char*>(data.data());
 
1972
      *reinterpret_cast<charT*>(data.extend(sizeof(charT))) = traits_inst.translate(c, (_flags & regbase::icase));
 
1973
      dat = reinterpret_cast<re_detail::re_syntax_base*>(reinterpret_cast<unsigned char*>(data.data()) + pos);
 
1974
      ++(static_cast<re_detail::re_literal*>(dat)->length);
 
1975
   }
 
1976
   else
 
1977
   {
 
1978
      // extend:
 
1979
      dat = add_simple(dat, re_detail::syntax_element_literal, sizeof(re_detail::re_literal) + sizeof(charT));
 
1980
      static_cast<re_detail::re_literal*>(dat)->length = 1;
 
1981
      *reinterpret_cast<charT*>(reinterpret_cast<re_detail::re_literal*>(dat)+1) = traits_inst.translate(c, (_flags & regbase::icase));
 
1982
   }
 
1983
   return dat;
 
1984
}
 
1985
 
 
1986
template <class charT, class traits, class Allocator>
 
1987
unsigned int BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::probe_restart(re_detail::re_syntax_base* dat)
 
1988
{
 
1989
   switch(dat->type)
 
1990
   {
 
1991
   case re_detail::syntax_element_startmark:
 
1992
   case re_detail::syntax_element_endmark:
 
1993
      if(static_cast<const re_detail::re_brace*>(dat)->index == -2)
 
1994
         return regbase::restart_any;
 
1995
      return probe_restart(dat->next.p);
 
1996
   case re_detail::syntax_element_start_line:
 
1997
      return regbase::restart_line;
 
1998
   case re_detail::syntax_element_word_start:
 
1999
      return regbase::restart_word;
 
2000
   case re_detail::syntax_element_buffer_start:
 
2001
      return regbase::restart_buf;
 
2002
   case re_detail::syntax_element_restart_continue:
 
2003
      return regbase::restart_continue;
 
2004
   default:
 
2005
      return regbase::restart_any;
 
2006
   }
 
2007
}
 
2008
 
 
2009
template <class charT, class traits, class Allocator>
 
2010
unsigned int BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::fixup_leading_rep(re_detail::re_syntax_base* dat, re_detail::re_syntax_base* end)
 
2011
{
 
2012
   unsigned int len = 0;
 
2013
   bool leading_lit = end ? false : true;
 
2014
   while(dat != end)
 
2015
   {
 
2016
      switch(dat->type)
 
2017
      {
 
2018
      case re_detail::syntax_element_literal:
 
2019
         len += static_cast<re_detail::re_literal*>(dat)->length;
 
2020
         if((leading_lit) && (static_cast<re_detail::re_literal*>(dat)->length > 2))
 
2021
         {
 
2022
            // we can do a literal search for the leading literal string
 
2023
            // using Knuth-Morris-Pratt (or whatever), and only then check for
 
2024
            // matches.  We need a decent length string though to make it
 
2025
            // worth while.
 
2026
            _leading_string = reinterpret_cast<charT*>(reinterpret_cast<char*>(dat) + sizeof(re_detail::re_literal));
 
2027
            _leading_string_len = static_cast<re_detail::re_literal*>(dat)->length;
 
2028
            _restart_type = restart_lit;
 
2029
            leading_lit = false;
 
2030
            const charT* p1 = _leading_string;
 
2031
            const charT* p2 = _leading_string + _leading_string_len;
 
2032
            pkmp = re_detail::kmp_compile(p1, p2, charT(), re_detail::kmp_translator<traits>(_flags&regbase::icase, &traits_inst), data.allocator());
 
2033
         }
 
2034
         leading_lit = false;
 
2035
         break;
 
2036
      case re_detail::syntax_element_wild:
 
2037
         ++len;
 
2038
         leading_lit = false;
 
2039
         break;
 
2040
      case re_detail::syntax_element_match:
 
2041
         return len;
 
2042
      case re_detail::syntax_element_backref:
 
2043
      //case re_detail::syntax_element_jump:
 
2044
      case re_detail::syntax_element_alt:
 
2045
      case re_detail::syntax_element_combining:
 
2046
         return 0;
 
2047
      case re_detail::syntax_element_long_set:
 
2048
      {
 
2049
         // we need to verify that there are no multi-character
 
2050
         // collating elements inside the repeat:
 
2051
         const charT* p = reinterpret_cast<const charT*>(reinterpret_cast<const char*>(dat) + sizeof(re_detail::re_set_long));
 
2052
         unsigned int csingles = static_cast<re_detail::re_set_long*>(dat)->csingles;
 
2053
         for(unsigned int i = 0; i < csingles; ++i)
 
2054
         {
 
2055
            if(re_detail::re_strlen(p) > 1)
 
2056
               return 0;
 
2057
            while(*p)++p;
 
2058
            ++p;
 
2059
         }
 
2060
         ++len;
 
2061
         leading_lit = false;
 
2062
         break;
 
2063
      }
 
2064
      case re_detail::syntax_element_set:
 
2065
         ++len;
 
2066
         leading_lit = false;
 
2067
         break;
 
2068
      case re_detail::syntax_element_rep:
 
2069
         if((len == 0) && (1 == fixup_leading_rep(dat->next.p, static_cast<re_detail::re_repeat*>(dat)->alt.p) ))
 
2070
         {
 
2071
            static_cast<re_detail::re_repeat*>(dat)->leading = leading_lit;
 
2072
            return len;
 
2073
         }
 
2074
         return len;
 
2075
      case re_detail::syntax_element_startmark:
 
2076
         if(static_cast<const re_detail::re_brace*>(dat)->index == -2)
 
2077
            return 0;
 
2078
         // fall through:
 
2079
      default:
 
2080
         break;
 
2081
      }
 
2082
      dat = dat->next.p;
 
2083
   }
 
2084
   return len;
 
2085
}
 
2086
 
 
2087
template <class charT, class traits, class Allocator>
 
2088
void BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::fail(unsigned int err)
 
2089
{
 
2090
   error_code_  = err;
 
2091
   if(err)
 
2092
   {
 
2093
      _flags |= regbase::failbit;
 
2094
#ifndef BOOST_NO_EXCEPTIONS
 
2095
      if(_flags & regbase::use_except)
 
2096
      {
 
2097
         throw bad_expression(traits_inst.error_string(err));
 
2098
      }
 
2099
#endif
 
2100
   }
 
2101
   else
 
2102
      _flags &= ~regbase::failbit;
 
2103
}
 
2104
 
 
2105
 
 
2106
#ifdef __BORLANDC__
 
2107
  #pragma option pop
 
2108
#endif
 
2109
 
 
2110
} // namespace boost
 
2111
 
 
2112
 
 
2113
#endif   // BOOST_REGEX_COMPILE_HPP
 
2114
 
 
2115
 
 
2116
 
 
2117
 
 
2118
 
 
2119
 
 
2120
 
 
2121
 
 
2122
 
 
2123
 
 
2124