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

« back to all changes in this revision

Viewing changes to boost/libs/regex/src/cregex.cpp

  • 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:        cregex.cpp
 
19
  *   VERSION:     see <boost/version.hpp>
 
20
  *   DESCRIPTION: Implements high level class boost::RexEx
 
21
  */
 
22
 
 
23
 
 
24
#define BOOST_REGEX_SOURCE
 
25
 
 
26
#include <boost/cregex.hpp>
 
27
#include <boost/regex.hpp>
 
28
#if !defined(BOOST_NO_STD_STRING)
 
29
#include <map>
 
30
#include <list>
 
31
#include <boost/regex/v3/fileiter.hpp>
 
32
#include <cstdio>
 
33
 
 
34
namespace boost{
 
35
 
 
36
#ifdef __BORLANDC__
 
37
#if __BORLANDC__ < 0x530
 
38
//
 
39
// we need to instantiate the vector classes we use
 
40
// since declaring a reference to type doesn't seem to
 
41
// do the job...
 
42
std::vector<std::size_t> inst1;
 
43
std::vector<std::string> inst2;
 
44
#endif
 
45
#endif
 
46
 
 
47
namespace{
 
48
 
 
49
template <class iterator>
 
50
std::string to_string(iterator i, iterator j)
 
51
{
 
52
   BOOST_RE_GUARD_STACK
 
53
   std::string s;
 
54
   while(i != j)
 
55
   {
 
56
      s.append(1, *i);
 
57
      ++i;
 
58
   }
 
59
   return s;
 
60
}
 
61
 
 
62
inline std::string to_string(const char* i, const char* j)
 
63
{
 
64
   return std::string(i, j);
 
65
}
 
66
 
 
67
}
 
68
namespace re_detail{
 
69
 
 
70
class RegExData
 
71
{
 
72
public:
 
73
   enum type
 
74
   {
 
75
      type_pc,
 
76
      type_pf,
 
77
      type_copy
 
78
   };
 
79
   regex e;
 
80
   cmatch m;
 
81
#ifndef BOOST_REGEX_NO_FILEITER
 
82
   match_results<mapfile::iterator, regex::allocator_type> fm;
 
83
#endif
 
84
   type t;
 
85
   const char* pbase;
 
86
   unsigned line;
 
87
#ifndef BOOST_REGEX_NO_FILEITER
 
88
   mapfile::iterator fbase;
 
89
#endif
 
90
   std::map<int, std::string, std::less<int> > strings;
 
91
   std::map<int, std::ptrdiff_t, std::less<int> > positions;
 
92
   void update();
 
93
   void clean();
 
94
   RegExData() : e(), m(),
 
95
#ifndef BOOST_REGEX_NO_FILEITER
 
96
   fm(),
 
97
#endif
 
98
   t(type_copy), pbase(0), line(0),
 
99
#ifndef BOOST_REGEX_NO_FILEITER
 
100
   fbase(),
 
101
#endif
 
102
   strings(), positions() {}
 
103
};
 
104
 
 
105
void RegExData::update()
 
106
{
 
107
   BOOST_RE_GUARD_STACK
 
108
   strings.erase(strings.begin(), strings.end());
 
109
   positions.erase(positions.begin(), positions.end());
 
110
   if(t == type_pc)
 
111
   {
 
112
      for(unsigned int i = 0; i < m.size(); ++i)
 
113
      {
 
114
         if(m[i].matched) strings[i] = std::string(m[i].first, m[i].second);
 
115
         positions[i] = m[i].matched ? m[i].first - pbase : -1;
 
116
      }
 
117
      line = m.line();
 
118
   }
 
119
#ifndef BOOST_REGEX_NO_FILEITER
 
120
   else
 
121
   {
 
122
      for(unsigned int i = 0; i < fm.size(); ++i)
 
123
      {
 
124
         if(fm[i].matched) strings[i] = to_string(fm[i].first, fm[i].second);
 
125
         positions[i] = fm[i].matched ? fm[i].first - fbase : -1;
 
126
      }
 
127
      line = fm.line();
 
128
   }
 
129
#endif
 
130
   t = type_copy;
 
131
}
 
132
 
 
133
void RegExData::clean()
 
134
{
 
135
   BOOST_RE_GUARD_STACK
 
136
#ifndef BOOST_REGEX_NO_FILEITER
 
137
   fbase = mapfile::iterator();
 
138
   fm = match_results<mapfile::iterator, regex::allocator_type>();
 
139
#endif
 
140
}
 
141
 
 
142
} // namespace
 
143
 
 
144
RegEx::RegEx()
 
145
{
 
146
   BOOST_RE_GUARD_STACK
 
147
   pdata = new re_detail::RegExData();
 
148
}
 
149
 
 
150
RegEx::RegEx(const RegEx& o)
 
151
{
 
152
   BOOST_RE_GUARD_STACK
 
153
   pdata = new re_detail::RegExData(*(o.pdata));
 
154
}
 
155
 
 
156
RegEx::~RegEx()
 
157
{
 
158
   BOOST_RE_GUARD_STACK
 
159
   delete pdata;
 
160
}
 
161
 
 
162
RegEx::RegEx(const char* c, bool icase)
 
163
{
 
164
   BOOST_RE_GUARD_STACK
 
165
   pdata = new re_detail::RegExData();
 
166
   SetExpression(c, icase);
 
167
}
 
168
 
 
169
RegEx::RegEx(const std::string& s, bool icase)
 
170
{
 
171
   BOOST_RE_GUARD_STACK
 
172
   pdata = new re_detail::RegExData();
 
173
   SetExpression(s.c_str(), icase);
 
174
}
 
175
 
 
176
RegEx& RegEx::operator=(const RegEx& o)
 
177
{
 
178
   BOOST_RE_GUARD_STACK
 
179
   *pdata = *(o.pdata);
 
180
   return *this;
 
181
}
 
182
 
 
183
RegEx& RegEx::operator=(const char* p)
 
184
{
 
185
   BOOST_RE_GUARD_STACK
 
186
   SetExpression(p, false);
 
187
   return *this;
 
188
}
 
189
 
 
190
unsigned int RegEx::SetExpression(const char* p, bool icase)
 
191
{
 
192
   BOOST_RE_GUARD_STACK
 
193
   boost::uint_fast32_t f = icase ? regbase::normal | regbase::use_except | regbase::icase : regbase::normal | regbase::use_except;
 
194
   return pdata->e.set_expression(p, f);
 
195
}
 
196
 
 
197
unsigned int RegEx::error_code()const
 
198
{
 
199
   return pdata->e.error_code();
 
200
}
 
201
 
 
202
 
 
203
std::string RegEx::Expression()const
 
204
{
 
205
   BOOST_RE_GUARD_STACK
 
206
   return pdata->e.expression();
 
207
}
 
208
 
 
209
//
 
210
// now matching operators:
 
211
//
 
212
bool RegEx::Match(const char* p, unsigned int flags)
 
213
{
 
214
   BOOST_RE_GUARD_STACK
 
215
   pdata->t = re_detail::RegExData::type_pc;
 
216
   pdata->pbase = p;
 
217
   const char* end = p;
 
218
   while(*end)++end;
 
219
 
 
220
   if(regex_match(p, end, pdata->m, pdata->e, flags))
 
221
   {
 
222
      pdata->update();
 
223
      return true;
 
224
   }
 
225
   return false;
 
226
}
 
227
 
 
228
bool RegEx::Search(const char* p, unsigned int flags)
 
229
{
 
230
   BOOST_RE_GUARD_STACK
 
231
   pdata->t = re_detail::RegExData::type_pc;
 
232
   pdata->pbase = p;
 
233
   const char* end = p;
 
234
   while(*end)++end;
 
235
 
 
236
   if(regex_search(p, end, pdata->m, pdata->e, flags))
 
237
   {
 
238
      pdata->update();
 
239
      return true;
 
240
   }
 
241
   return false;
 
242
}
 
243
namespace re_detail{
 
244
struct pred1
 
245
{
 
246
   GrepCallback cb;
 
247
   RegEx* pe;
 
248
   pred1(GrepCallback c, RegEx* i) : cb(c), pe(i) {}
 
249
   bool operator()(const cmatch& m)
 
250
   {
 
251
      pe->pdata->m = m;
 
252
      return cb(*pe);
 
253
   }
 
254
};
 
255
}
 
256
unsigned int RegEx::Grep(GrepCallback cb, const char* p, unsigned int flags)
 
257
{
 
258
   BOOST_RE_GUARD_STACK
 
259
   pdata->t = re_detail::RegExData::type_pc;
 
260
   pdata->pbase = p;
 
261
   const char* end = p;
 
262
   while(*end)++end;
 
263
 
 
264
   unsigned int result = regex_grep(re_detail::pred1(cb, this), p, end, pdata->e, flags);
 
265
   if(result)
 
266
      pdata->update();
 
267
   return result;
 
268
}
 
269
namespace re_detail{
 
270
struct pred2
 
271
{
 
272
   std::vector<std::string>& v;
 
273
   RegEx* pe;
 
274
   pred2(std::vector<std::string>& o, RegEx* e) : v(o), pe(e) {}
 
275
   bool operator()(const cmatch& m)
 
276
   {
 
277
      pe->pdata->m = m;
 
278
      v.push_back(std::string(m[0].first, m[0].second));
 
279
      return true;
 
280
   }
 
281
private:
 
282
   pred2& operator=(const pred2&);
 
283
};
 
284
}
 
285
 
 
286
unsigned int RegEx::Grep(std::vector<std::string>& v, const char* p, unsigned int flags)
 
287
{
 
288
   BOOST_RE_GUARD_STACK
 
289
   pdata->t = re_detail::RegExData::type_pc;
 
290
   pdata->pbase = p;
 
291
   const char* end = p;
 
292
   while(*end)++end;
 
293
 
 
294
   unsigned int result = regex_grep(re_detail::pred2(v, this), p, end, pdata->e, flags);
 
295
   if(result)
 
296
      pdata->update();
 
297
   return result;
 
298
}
 
299
namespace re_detail{
 
300
struct pred3
 
301
{
 
302
   std::vector<std::size_t>& v;
 
303
   const char* base;
 
304
   RegEx* pe;
 
305
   pred3(std::vector<std::size_t>& o, const char* pb, RegEx* p) : v(o), base(pb), pe(p) {}
 
306
   bool operator()(const cmatch& m)
 
307
   {
 
308
      pe->pdata->m = m;
 
309
      v.push_back(static_cast<std::size_t>(m[0].first - base));
 
310
      return true;
 
311
   }
 
312
private:
 
313
   pred3& operator=(const pred3&);
 
314
};
 
315
}
 
316
unsigned int RegEx::Grep(std::vector<std::size_t>& v, const char* p, unsigned int flags)
 
317
{
 
318
   BOOST_RE_GUARD_STACK
 
319
   pdata->t = re_detail::RegExData::type_pc;
 
320
   pdata->pbase = p;
 
321
   const char* end = p;
 
322
   while(*end)++end;
 
323
 
 
324
   unsigned int result = regex_grep(re_detail::pred3(v, p, this), p, end, pdata->e, flags);
 
325
   if(result)
 
326
      pdata->update();
 
327
   return result;
 
328
}
 
329
#ifndef BOOST_REGEX_NO_FILEITER
 
330
namespace re_detail{
 
331
struct pred4
 
332
{
 
333
   GrepFileCallback cb;
 
334
   RegEx* pe;
 
335
   const char* file;
 
336
   bool ok;
 
337
   pred4(GrepFileCallback c, RegEx* i, const char* f) : cb(c), pe(i), file(f), ok(true) {}
 
338
   bool operator()(const match_results<mapfile::iterator, regex::allocator_type>& m)
 
339
   {
 
340
      pe->pdata->t = RegExData::type_pf;
 
341
      pe->pdata->fm = m;
 
342
      pe->pdata->update();
 
343
      ok = cb(file, *pe);
 
344
      return ok;
 
345
   }
 
346
};
 
347
}
 
348
namespace{
 
349
void BuildFileList(std::list<std::string>* pl, const char* files, bool recurse)
 
350
{
 
351
   BOOST_RE_GUARD_STACK
 
352
   file_iterator start(files);
 
353
   file_iterator end;
 
354
   if(recurse)
 
355
   {
 
356
      // go through sub directories:
 
357
      char buf[MAX_PATH];
 
358
      std::strcpy(buf, start.root());
 
359
      if(*buf == 0)
 
360
      {
 
361
         std::strcpy(buf, ".");
 
362
         std::strcat(buf, directory_iterator::separator());
 
363
         std::strcat(buf, "*");
 
364
      }
 
365
      else
 
366
      {
 
367
         std::strcat(buf, directory_iterator::separator());
 
368
         std::strcat(buf, "*");
 
369
      }
 
370
      directory_iterator dstart(buf);
 
371
      directory_iterator dend;
 
372
 
 
373
      // now get the file mask bit of "files":
 
374
      const char* ptr = files;
 
375
      while(*ptr) ++ptr;
 
376
      while((ptr != files) && (*ptr != *directory_iterator::separator()) && (*ptr != '/'))--ptr;
 
377
      if(ptr != files) ++ptr;
 
378
 
 
379
      while(dstart != dend)
 
380
      {
 
381
         std::sprintf(buf, "%s%s%s", dstart.path(), directory_iterator::separator(), ptr);
 
382
         BuildFileList(pl, buf, recurse);
 
383
         ++dstart;
 
384
      }
 
385
   }
 
386
   while(start != end)
 
387
   {
 
388
      pl->push_back(*start);
 
389
      ++start;
 
390
   }
 
391
}
 
392
}
 
393
 
 
394
unsigned int RegEx::GrepFiles(GrepFileCallback cb, const char* files, bool recurse, unsigned int flags)
 
395
{
 
396
   BOOST_RE_GUARD_STACK
 
397
   unsigned int result = 0;
 
398
   std::list<std::string> file_list;
 
399
   BuildFileList(&file_list, files, recurse);
 
400
   std::list<std::string>::iterator start, end;
 
401
   start = file_list.begin();
 
402
   end = file_list.end();
 
403
 
 
404
   while(start != end)
 
405
   {
 
406
      mapfile map((*start).c_str());
 
407
      pdata->t = re_detail::RegExData::type_pf;
 
408
      pdata->fbase = map.begin();
 
409
      re_detail::pred4 pred(cb, this, (*start).c_str());
 
410
      int r = regex_grep(pred, map.begin(), map.end(), pdata->e, flags);
 
411
      result += r;
 
412
      ++start;
 
413
      pdata->clean();
 
414
      if(pred.ok == false)
 
415
         return result;
 
416
   }
 
417
 
 
418
   return result;
 
419
}
 
420
 
 
421
 
 
422
unsigned int RegEx::FindFiles(FindFilesCallback cb, const char* files, bool recurse, unsigned int flags)
 
423
{
 
424
   BOOST_RE_GUARD_STACK
 
425
   unsigned int result = 0;
 
426
   std::list<std::string> file_list;
 
427
   BuildFileList(&file_list, files, recurse);
 
428
   std::list<std::string>::iterator start, end;
 
429
   start = file_list.begin();
 
430
   end = file_list.end();
 
431
 
 
432
   while(start != end)
 
433
   {
 
434
      mapfile map((*start).c_str());
 
435
      pdata->t = re_detail::RegExData::type_pf;
 
436
      pdata->fbase = map.begin();
 
437
 
 
438
      if(regex_search(map.begin(), map.end(), pdata->fm, pdata->e, flags))
 
439
      {
 
440
         ++result;
 
441
         if(false == cb((*start).c_str()))
 
442
            return result;
 
443
      }
 
444
      //pdata->update();
 
445
      ++start;
 
446
      //pdata->clean();
 
447
   }
 
448
 
 
449
   return result;
 
450
}
 
451
#endif
 
452
 
 
453
std::string RegEx::Merge(const std::string& in, const std::string& fmt,
 
454
                    bool copy, unsigned int flags)
 
455
{
 
456
   std::string result;
 
457
   re_detail::string_out_iterator<std::string> i(result);
 
458
   if(!copy) flags |= format_no_copy;
 
459
   regex_merge(i, in.begin(), in.end(), pdata->e, fmt.c_str(), flags);
 
460
   return result;
 
461
}
 
462
 
 
463
std::string RegEx::Merge(const char* in, const char* fmt,
 
464
                    bool copy, unsigned int flags)
 
465
{
 
466
   std::string result;
 
467
   if(!copy) flags |= format_no_copy;
 
468
   re_detail::string_out_iterator<std::string> i(result);
 
469
   regex_merge(i, in, in + std::strlen(in), pdata->e, fmt, flags);
 
470
   return result;
 
471
}
 
472
 
 
473
std::size_t RegEx::Split(std::vector<std::string>& v, 
 
474
                      std::string& s,
 
475
                      unsigned flags,
 
476
                      unsigned max_count)
 
477
{
 
478
   return regex_split(std::back_inserter(v), s, pdata->e, flags, max_count);
 
479
}
 
480
 
 
481
 
 
482
 
 
483
//
 
484
// now operators for returning what matched in more detail:
 
485
//
 
486
std::size_t RegEx::Position(int i)const
 
487
{
 
488
   BOOST_RE_GUARD_STACK
 
489
   switch(pdata->t)
 
490
   {
 
491
   case re_detail::RegExData::type_pc:
 
492
      return pdata->m[i].matched ? pdata->m[i].first - pdata->pbase : RegEx::npos;
 
493
#ifndef BOOST_REGEX_NO_FILEITER
 
494
   case re_detail::RegExData::type_pf:
 
495
      return pdata->fm[i].matched ? pdata->fm[i].first - pdata->fbase : RegEx::npos;
 
496
#endif
 
497
   case re_detail::RegExData::type_copy:
 
498
      {
 
499
      std::map<int, std::ptrdiff_t, std::less<int> >::iterator pos = pdata->positions.find(i);
 
500
      if(pos == pdata->positions.end())
 
501
         return RegEx::npos;
 
502
      return (*pos).second;
 
503
      }
 
504
   }
 
505
   return RegEx::npos;
 
506
}
 
507
 
 
508
unsigned int RegEx::Line()const
 
509
{
 
510
   BOOST_RE_GUARD_STACK
 
511
   switch(pdata->t)
 
512
   {
 
513
   case re_detail::RegExData::type_pc:
 
514
      return pdata->m[0].matched ? pdata->m.line() : RegEx::npos;
 
515
#ifndef BOOST_REGEX_NO_FILEITER
 
516
   case re_detail::RegExData::type_pf:
 
517
      return pdata->fm[0].matched ? pdata->fm.line() : RegEx::npos;
 
518
#endif
 
519
   case re_detail::RegExData::type_copy:
 
520
      {
 
521
         return pdata->line;
 
522
      }
 
523
   }
 
524
   return RegEx::npos;
 
525
}
 
526
 
 
527
unsigned int RegEx::Marks()const
 
528
{
 
529
   BOOST_RE_GUARD_STACK
 
530
   return pdata->e.mark_count();
 
531
}
 
532
 
 
533
 
 
534
std::size_t RegEx::Length(int i)const
 
535
{
 
536
   BOOST_RE_GUARD_STACK
 
537
   switch(pdata->t)
 
538
   {
 
539
   case re_detail::RegExData::type_pc:
 
540
      return pdata->m[i].matched ? pdata->m[i].second - pdata->m[i].first : RegEx::npos;
 
541
#ifndef BOOST_REGEX_NO_FILEITER
 
542
   case re_detail::RegExData::type_pf:
 
543
      return pdata->fm[i].matched ? pdata->fm[i].second - pdata->fm[i].first : RegEx::npos;
 
544
#endif
 
545
   case re_detail::RegExData::type_copy:
 
546
      {
 
547
      std::map<int, std::string, std::less<int> >::iterator pos = pdata->strings.find(i);
 
548
      if(pos == pdata->strings.end())
 
549
         return RegEx::npos;
 
550
      return (*pos).second.size();
 
551
      }
 
552
   }
 
553
   return RegEx::npos;
 
554
}
 
555
 
 
556
bool RegEx::Matched(int i)const
 
557
{
 
558
   BOOST_RE_GUARD_STACK
 
559
   switch(pdata->t)
 
560
   {
 
561
   case re_detail::RegExData::type_pc:
 
562
      return pdata->m[i].matched;
 
563
#ifndef BOOST_REGEX_NO_FILEITER
 
564
   case re_detail::RegExData::type_pf:
 
565
      return pdata->fm[i].matched;
 
566
#endif      
 
567
   case re_detail::RegExData::type_copy:
 
568
      {
 
569
      std::map<int, std::string, std::less<int> >::iterator pos = pdata->strings.find(i);
 
570
      if(pos == pdata->strings.end())
 
571
         return false;
 
572
      return true;
 
573
      }
 
574
   }
 
575
   return false;
 
576
}
 
577
 
 
578
 
 
579
std::string RegEx::What(int i)const
 
580
{
 
581
   BOOST_RE_GUARD_STACK
 
582
   std::string result;
 
583
   switch(pdata->t)
 
584
   {
 
585
   case re_detail::RegExData::type_pc:
 
586
      if(pdata->m[i].matched) 
 
587
         result.assign(pdata->m[i].first, pdata->m[i].second);
 
588
      break;
 
589
   case re_detail::RegExData::type_pf:
 
590
      if(pdata->m[i].matched) 
 
591
         result.assign(to_string(pdata->m[i].first, pdata->m[i].second));
 
592
      break;
 
593
   case re_detail::RegExData::type_copy:
 
594
      {
 
595
      std::map<int, std::string, std::less<int> >::iterator pos = pdata->strings.find(i);
 
596
      if(pos != pdata->strings.end())
 
597
         result = (*pos).second;
 
598
      break;
 
599
      }
 
600
   }
 
601
   return result;
 
602
}
 
603
 
 
604
const unsigned int RegEx::npos = ~0u;
 
605
 
 
606
 
 
607
} // namespace boost
 
608
 
 
609
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x550) && (__BORLANDC__ <= 0x551) && !defined(_RWSTD_COMPILE_INSTANTIATE)
 
610
//
 
611
// this is an ugly hack to work around an ugly problem:
 
612
// by default this file will produce unresolved externals during
 
613
// linking unless _RWSTD_COMPILE_INSTANTIATE is defined (Borland bug).
 
614
// However if _RWSTD_COMPILE_INSTANTIATE is defined then we get separate
 
615
// copies of basic_string's static data in the RTL and this DLL, this messes
 
616
// with basic_string's memory management and results in run-time crashes,
 
617
// Oh sweet joy of Catch 22....
 
618
//
 
619
namespace std{
 
620
template<> template<>
 
621
basic_string<char>&
 
622
basic_string<char>::replace<const char*>(char* f1, char* f2, const char* i1, const char* i2)
 
623
{
 
624
   unsigned insert_pos = f1 - begin();
 
625
   unsigned remove_len = f2 - f1;
 
626
   unsigned insert_len = i2 - i1;
 
627
   unsigned org_size = size();
 
628
   if(insert_len > remove_len)
 
629
   {
 
630
      append(insert_len-remove_len, ' ');
 
631
      std::copy_backward(begin() + insert_pos + remove_len, begin() + org_size, end());
 
632
      std::copy(i1, i2, begin() + insert_pos);
 
633
   }
 
634
   else
 
635
   {
 
636
      std::copy(begin() + insert_pos + remove_len, begin() + org_size, begin() + insert_pos + insert_len);
 
637
      std::copy(i1, i2, begin() + insert_pos);
 
638
      erase(size() + insert_len - remove_len);
 
639
   }
 
640
   return *this;
 
641
}
 
642
}
 
643
#endif
 
644
 
 
645
#endif
 
646
 
 
647
 
 
648
 
 
649
 
 
650
 
 
651
 
 
652
 
 
653
 
 
654
 
 
655
 
 
656
 
 
657
 
 
658