modules/up/src/gnug++/String.h

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. String
  2. SubString
  3. SubString
  4. String
  5. String
  6. SubString
  7. empty
  8. chars
  9. allocation
  10. length
  11. empty
  12. chars
  13. String
  14. String
  15. String
  16. String
  17. String
  18. String
  19. String
  20. SubString
  21. SubString
  22. SubString
  23. cat
  24. cat
  25. cat
  26. cat
  27. cat
  28. cat
  29. cat
  30. cat
  31. cat
  32. cat
  33. cat
  34. cat
  35. cat
  36. cat
  37. cat
  38. cat
  39. cat
  40. cat
  41. cat
  42. cat
  43. cat
  44. cat
  45. cat
  46. cat
  47. cat
  48. cat
  49. cat
  50. cat
  51. cat
  52. cat
  53. cat
  54. cat
  55. cat
  56. cat
  57. cat
  58. cat
  59. reverse
  60. upcase
  61. downcase
  62. capitalize
  63. reverse
  64. upcase
  65. downcase
  66. capitalize
  67. prepend
  68. prepend
  69. prepend
  70. prepend
  71. reverse
  72. upcase
  73. downcase
  74. capitalize
  75. elem
  76. firstchar
  77. lastchar
  78. index
  79. index
  80. index
  81. index
  82. index
  83. contains
  84. contains
  85. contains
  86. contains
  87. contains
  88. contains
  89. contains
  90. contains
  91. contains
  92. contains
  93. matches
  94. matches
  95. matches
  96. matches
  97. matches
  98. contains
  99. contains
  100. contains
  101. contains
  102. contains
  103. matches
  104. gsub
  105. gsub
  106. gsub
  107. gsub
  108. gsub
  109. _substr

   1 // This may look like C code, but it is really -*- C++ -*-
   2 /* 
   3 Copyright (C) 1988 Free Software Foundation
   4     written by Doug Lea (dl@rocky.oswego.edu)
   5 
   6 This file is part of the GNU C++ Library.  This library is free
   7 software; you can redistribute it and/or modify it under the terms of
   8 the GNU Library General Public License as published by the Free
   9 Software Foundation; either version 2 of the License, or (at your
  10 option) any later version.  This library is distributed in the hope
  11 that it will be useful, but WITHOUT ANY WARRANTY; without even the
  12 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  13 PURPOSE.  See the GNU Library General Public License for more details.
  14 You should have received a copy of the GNU Library General Public
  15 License along with this library; if not, write to the Free Software
  16 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17 */
  18 
  19 
  20 #ifndef _String_h
  21 #ifdef __GNUG__
  22 #pragma interface
  23 #endif
  24 #define _String_h 1
  25 
  26 #include <iostream.h>
  27 #include "Regex.h"
  28 
  29 #undef OK
  30 
  31 struct StrRep                     // internal String representations
  32 {
  33   unsigned short    len;         // string length 
  34   unsigned short    sz;          // allocated space
  35   char              s[1];        // the string starts here 
  36                                  // (at least 1 char for trailing null)
  37                                  // allocated & expanded via non-public fcts
  38 };
  39 
  40 // primitive ops on StrReps -- nearly all String fns go through these.
  41 
  42 StrRep*     Salloc(StrRep*, const char*, int, int);
  43 StrRep*     Scopy(StrRep*, const StrRep*);
  44 StrRep*     Scat(StrRep*, const char*, int, const char*, int);
  45 StrRep*     Scat(StrRep*, const char*, int,const char*,int, const char*,int);
  46 StrRep*     Sprepend(StrRep*, const char*, int);
  47 StrRep*     Sreverse(const StrRep*, StrRep*);
  48 StrRep*     Supcase(const StrRep*, StrRep*);
  49 StrRep*     Sdowncase(const StrRep*, StrRep*);
  50 StrRep*     Scapitalize(const StrRep*, StrRep*);
  51 
  52 // These classes need to be defined in the order given
  53 
  54 class String;
     /* [<][>][^][v][top][bottom][index][help] */
  55 class SubString;
     /* [<][>][^][v][top][bottom][index][help] */
  56 
  57 class SubString
     /* [<][>][^][v][top][bottom][index][help] */
  58 {
  59   friend class      String;
     /* [<][>][^][v][top][bottom][index][help] */
  60 protected:
  61 
  62   String&           S;        // The String I'm a substring of
  63   unsigned short    pos;      // starting position in S's rep
  64   unsigned short    len;      // length of substring
  65 
  66   void              assign(const StrRep*, const char*, int = -1);
  67                     SubString(String& x, int p, int l);
  68                     SubString(const SubString& x);
  69 
  70 public:
  71 
  72 // Note there are no public constructors. SubStrings are always
  73 // created via String operations
  74 
  75                    ~SubString();
  76 
  77   SubString&        operator =  (const String&     y);
  78   SubString&        operator =  (const SubString&  y);
  79   SubString&        operator =  (const char* t);
  80   SubString&        operator =  (char        c);
  81 
  82 // return 1 if target appears anywhere in SubString; else 0
  83 
  84   int               contains(char        c) const;
  85   int               contains(const String&     y) const;
  86   int               contains(const SubString&  y) const;
  87   int               contains(const char* t) const;
  88   int               contains(const Regex&       r) const;
  89 
  90 // return 1 if target matches entire SubString
  91 
  92   int               matches(const Regex&  r) const;
  93 
  94 // IO 
  95 
  96   friend ostream&   operator<<(ostream& s, const SubString& x);
  97 
  98 // status
  99 
 100   unsigned int      length() const;
 101   int               empty() const;
 102   const char*       chars() const;
 103 
 104   int               OK() const; 
 105 
 106 };
 107 
 108 
 109 class String
     /* [<][>][^][v][top][bottom][index][help] */
 110 {
 111   friend class      SubString;
     /* [<][>][^][v][top][bottom][index][help] */
 112 
 113 protected:
 114   StrRep*           rep;   // Strings are pointers to their representations
 115 
 116 // some helper functions
 117 
 118   int               search(int, int, const char*, int = -1) const;
 119   int               search(int, int, char) const;
 120   int               match(int, int, int, const char*, int = -1) const;
 121   int               _gsub(const char*, int, const char* ,int);
 122   int               _gsub(const Regex&, const char*, int);
 123   SubString         _substr(int, int);
 124 
 125 public:
 126 
 127 // constructors & assignment
 128 
 129                     String();
 130                     String(const String& x);
 131                     String(const SubString&  x);
 132                     String(const char* t);
 133                     String(const char* t, int len);
 134                     String(char c);
 135 
 136                     ~String();
 137 
 138   String&           operator =  (const String&     y);
 139   String&           operator =  (const char* y);
 140   String&           operator =  (char        c);
 141   String&           operator =  (const SubString&  y);
 142 
 143 // concatenation
 144 
 145   String&           operator += (const String&     y); 
 146   String&           operator += (const SubString&  y);
 147   String&           operator += (const char* t);
 148   String&           operator += (char        c);
 149 
 150   void              prepend(const String&     y); 
 151   void              prepend(const SubString&  y);
 152   void              prepend(const char* t);
 153   void              prepend(char        c);
 154 
 155 
 156 // procedural versions:
 157 // concatenate first 2 args, store result in last arg
 158 
 159   friend inline void     cat(const String&, const String&, String&);
 160   friend inline void     cat(const String&, const SubString&, String&);
 161   friend inline void     cat(const String&, const char*, String&);
 162   friend inline void     cat(const String&, char, String&);
 163 
 164   friend inline void     cat(const SubString&, const String&, String&);
 165   friend inline void     cat(const SubString&, const SubString&, String&);
 166   friend inline void     cat(const SubString&, const char*, String&);
 167   friend inline void     cat(const SubString&, char, String&);
 168 
 169   friend inline void     cat(const char*, const String&, String&);
 170   friend inline void     cat(const char*, const SubString&, String&);
 171   friend inline void     cat(const char*, const char*, String&);
 172   friend inline void     cat(const char*, char, String&);
 173 
 174 // double concatenation, by request. (yes, there are too many versions, 
 175 // but if one is supported, then the others should be too...)
 176 // Concatenate first 3 args, store in last arg
 177 
 178   friend inline void     cat(const String&,const String&, const String&,String&);
 179   friend inline void     cat(const String&,const String&,const SubString&,String&);
 180   friend inline void     cat(const String&,const String&, const char*, String&);
 181   friend inline void     cat(const String&,const String&, char, String&);
 182   friend inline void     cat(const String&,const SubString&,const String&,String&);
 183   inline friend void     cat(const String&,const SubString&,const SubString&,String&);
 184   friend inline void     cat(const String&,const SubString&, const char*, String&);
 185   friend inline void     cat(const String&,const SubString&, char, String&);
 186   friend inline void     cat(const String&,const char*, const String&,    String&);
 187   friend inline void     cat(const String&,const char*, const SubString&, String&);
 188   friend inline void     cat(const String&,const char*, const char*, String&);
 189   friend inline void     cat(const String&,const char*, char, String&);
 190 
 191   friend inline void     cat(const char*, const String&, const String&,String&);
 192   friend inline void     cat(const char*,const String&,const SubString&,String&);
 193   friend inline void     cat(const char*,const String&, const char*, String&);
 194   friend inline void     cat(const char*,const String&, char, String&);
 195   friend inline void     cat(const char*,const SubString&,const String&,String&);
 196   friend inline void     cat(const char*,const SubString&,const SubString&,String&);
 197   friend inline void     cat(const char*,const SubString&, const char*, String&);
 198   friend inline void     cat(const char*,const SubString&, char, String&);
 199   friend inline void     cat(const char*,const char*, const String&,    String&);
 200   friend inline void     cat(const char*,const char*, const SubString&, String&);
 201   friend inline void     cat(const char*,const char*, const char*, String&);
 202   friend inline void     cat(const char*,const char*, char, String&);
 203 
 204 
 205 // searching & matching
 206 
 207 // return position of target in string or -1 for failure
 208 
 209   int               index(char        c, int startpos = 0) const;      
 210   int               index(const String&     y, int startpos = 0) const;      
 211   int               index(const SubString&  y, int startpos = 0) const;      
 212   int               index(const char* t, int startpos = 0) const;  
 213   int               index(const Regex&      r, int startpos = 0) const;       
 214 
 215 // return 1 if target appears anyhere in String; else 0
 216 
 217   int               contains(char        c) const;
 218   int               contains(const String&     y) const;
 219   int               contains(const SubString&  y) const;
 220   int               contains(const char* t) const;
 221   int               contains(const Regex&      r) const;
 222 
 223 // return 1 if target appears anywhere after position pos 
 224 // (or before, if pos is negative) in String; else 0
 225 
 226   int               contains(char        c, int pos) const;
 227   int               contains(const String&     y, int pos) const;
 228   int               contains(const SubString&  y, int pos) const;
 229   int               contains(const char* t, int pos) const;
 230   int               contains(const Regex&      r, int pos) const;
 231 
 232 // return 1 if target appears at position pos in String; else 0
 233 
 234   int               matches(char        c, int pos = 0) const;
 235   int               matches(const String&     y, int pos = 0) const;
 236   int               matches(const SubString&  y, int pos = 0) const;
 237   int               matches(const char* t, int pos = 0) const;
 238   int               matches(const Regex&      r, int pos = 0) const;
 239 
 240 //  return number of occurences of target in String
 241 
 242   int               freq(char        c) const; 
 243   int               freq(const String&     y) const;
 244   int               freq(const SubString&  y) const;
 245   int               freq(const char* t) const;
 246 
 247 // SubString extraction
 248 
 249 // Note that you can't take a substring of a const String, since
 250 // this leaves open the possiblility of indirectly modifying the
 251 // String through the SubString
 252 
 253   SubString         at(int         pos, int len);
 254   SubString         operator () (int         pos, int len); // synonym for at
 255 
 256   SubString         at(const String&     x, int startpos = 0); 
 257   SubString         at(const SubString&  x, int startpos = 0); 
 258   SubString         at(const char* t, int startpos = 0);
 259   SubString         at(char        c, int startpos = 0);
 260   SubString         at(const Regex&      r, int startpos = 0); 
 261 
 262   SubString         before(int          pos);
 263   SubString         before(const String&      x, int startpos = 0);
 264   SubString         before(const SubString&   x, int startpos = 0);
 265   SubString         before(const char*  t, int startpos = 0);
 266   SubString         before(char         c, int startpos = 0);
 267   SubString         before(const Regex&       r, int startpos = 0);
 268 
 269   SubString         through(int          pos);
 270   SubString         through(const String&      x, int startpos = 0);
 271   SubString         through(const SubString&   x, int startpos = 0);
 272   SubString         through(const char*  t, int startpos = 0);
 273   SubString         through(char         c, int startpos = 0);
 274   SubString         through(const Regex&       r, int startpos = 0);
 275 
 276   SubString         from(int          pos);
 277   SubString         from(const String&      x, int startpos = 0);
 278   SubString         from(const SubString&   x, int startpos = 0);
 279   SubString         from(const char*  t, int startpos = 0);
 280   SubString         from(char         c, int startpos = 0);
 281   SubString         from(const Regex&       r, int startpos = 0);
 282 
 283   SubString         after(int         pos);
 284   SubString         after(const String&     x, int startpos = 0);
 285   SubString         after(const SubString&  x, int startpos = 0);
 286   SubString         after(const char* t, int startpos = 0);
 287   SubString         after(char        c, int startpos = 0);
 288   SubString         after(const Regex&      r, int startpos = 0);
 289 
 290 
 291 // deletion
 292 
 293 // delete len chars starting at pos
 294   void              del(int         pos, int len);
 295 
 296 // delete the first occurrence of target after startpos
 297 
 298   void              del(const String&     y, int startpos = 0);
 299   void              del(const SubString&  y, int startpos = 0);
 300   void              del(const char* t, int startpos = 0);
 301   void              del(char        c, int startpos = 0);
 302   void              del(const Regex&      r, int startpos = 0);
 303 
 304 // global substitution: substitute all occurrences of pat with repl
 305 
 306   int               gsub(const String&     pat, const String&     repl);
 307   int               gsub(const SubString&  pat, const String&     repl);
 308   int               gsub(const char* pat, const String&     repl);
 309   int               gsub(const char* pat, const char* repl);
 310   int               gsub(const Regex&      pat, const String&     repl);
 311 
 312 // friends & utilities
 313 
 314 // split string into array res at separators; return number of elements
 315 
 316   friend int        split(const String& x, String res[], int maxn, 
 317                           const String& sep);
 318   friend int        split(const String& x, String res[], int maxn, 
 319                           const Regex&  sep);
 320 
 321   friend String     common_prefix(const String& x, const String& y, 
 322                                   int startpos = 0);
 323   friend String     common_suffix(const String& x, const String& y, 
 324                                   int startpos = -1);
 325   friend String     replicate(char        c, int n);
 326   friend String     replicate(const String&     y, int n);
 327   friend String     join(String src[], int n, const String& sep);
 328 
 329 // simple builtin transformations
 330 
 331   friend inline String     reverse(const String& x);
 332   friend inline String     upcase(const String& x);
 333   friend inline String     downcase(const String& x);
 334   friend inline String     capitalize(const String& x);
 335 
 336 // in-place versions of above
 337 
 338   void              reverse();
 339   void              upcase();
 340   void              downcase();
 341   void              capitalize();
 342 
 343 // element extraction
 344 
 345   char&             operator [] (int i);
 346   const char&       operator [] (int i) const;
 347   char              elem(int i) const;
 348   char              firstchar() const;
 349   char              lastchar() const;
 350 
 351 // conversion
 352 
 353                     operator const char*() const;
 354   const char*       chars() const;
 355 
 356 
 357 // IO
 358 
 359   friend inline ostream&   operator<<(ostream& s, const String& x);
 360   friend ostream&   operator<<(ostream& s, const SubString& x);
 361   friend istream&   operator>>(istream& s, String& x);
 362 
 363   friend int        readline(istream& s, String& x, 
 364                              char terminator = '\n',
 365                              int discard_terminator = 1);
 366 
 367 // status
 368 
 369   unsigned int      length() const;
 370   int               empty() const;
 371 
 372 // preallocate some space for String
 373   void              alloc(int newsize);
 374 
 375 // report current allocation (not length!)
 376 
 377   int               allocation() const;
 378 
 379 
 380   void     error(const char* msg) const;
 381 
 382   int               OK() const;
 383 };
 384 
 385 typedef String StrTmp; // for backward compatibility
 386 
 387 // other externs
 388 
 389 int        compare(const String&    x, const String&     y);
 390 int        compare(const String&    x, const SubString&  y);
 391 int        compare(const String&    x, const char* y);
 392 int        compare(const SubString& x, const String&     y);
 393 int        compare(const SubString& x, const SubString&  y);
 394 int        compare(const SubString& x, const char* y);
 395 int        fcompare(const String&   x, const String&     y); // ignore case
 396 
 397 extern StrRep  _nilStrRep;
 398 extern String _nilString;
 399 
 400 // status reports, needed before defining other things
 401 
 402 inline unsigned int String::length() const {  return rep->len; }
 403 inline int         String::empty() const { return rep->len == 0; }
     /* [<][>][^][v][top][bottom][index][help] */
 404 inline const char* String::chars() const { return &(rep->s[0]); }
     /* [<][>][^][v][top][bottom][index][help] */
 405 inline int         String::allocation() const { return rep->sz; }
     /* [<][>][^][v][top][bottom][index][help] */
 406 
 407 inline unsigned int SubString::length() const { return len; }
     /* [<][>][^][v][top][bottom][index][help] */
 408 inline int         SubString::empty() const { return len == 0; }
     /* [<][>][^][v][top][bottom][index][help] */
 409 inline const char* SubString::chars() const { return &(S.rep->s[pos]); }
     /* [<][>][^][v][top][bottom][index][help] */
 410 
 411 
 412 // constructors
 413 
 414 inline String::String() 
     /* [<][>][^][v][top][bottom][index][help] */
 415   : rep(&_nilStrRep) {}
 416 inline String::String(const String& x) 
     /* [<][>][^][v][top][bottom][index][help] */
 417   : rep(Scopy(0, x.rep)) {}
 418 inline String::String(const char* t) 
     /* [<][>][^][v][top][bottom][index][help] */
 419   : rep(Salloc(0, t, -1, -1)) {}
 420 inline String::String(const char* t, int tlen)
     /* [<][>][^][v][top][bottom][index][help] */
 421   : rep(Salloc(0, t, tlen, tlen)) {}
 422 inline String::String(const SubString& y)
     /* [<][>][^][v][top][bottom][index][help] */
 423   : rep(Salloc(0, y.chars(), y.length(), y.length())) {}
 424 inline String::String(char c) 
     /* [<][>][^][v][top][bottom][index][help] */
 425   : rep(Salloc(0, &c, 1, 1)) {}
 426 
 427 inline String::~String() { if (rep != &_nilStrRep) delete rep; }
     /* [<][>][^][v][top][bottom][index][help] */
 428 
 429 inline SubString::SubString(const SubString& x)
     /* [<][>][^][v][top][bottom][index][help] */
 430   :S(x.S), pos(x.pos), len(x.len) {}
 431 inline SubString::SubString(String& x, int first, int l)
     /* [<][>][^][v][top][bottom][index][help] */
 432   :S(x), pos(first), len(l) {}
 433 
 434 inline SubString::~SubString() {}
     /* [<][>][^][v][top][bottom][index][help] */
 435 
 436 // assignment
 437 
 438 inline String& String::operator =  (const String& y)
 439 { 
 440   rep = Scopy(rep, y.rep);
 441   return *this;
 442 }
 443 
 444 inline String& String::operator=(const char* t)
 445 {
 446   rep = Salloc(rep, t, -1, -1);
 447   return *this;
 448 }
 449 
 450 inline String& String::operator=(const SubString&  y)
 451 {
 452   rep = Salloc(rep, y.chars(), y.length(), y.length());
 453   return *this;
 454 }
 455 
 456 inline String& String::operator=(char c)
 457 {
 458   rep = Salloc(rep, &c, 1, 1);
 459   return *this;
 460 }
 461 
 462 
 463 inline SubString& SubString::operator = (const char* ys)
 464 {
 465   assign(0, ys);
 466   return *this;
 467 }
 468 
 469 inline SubString& SubString::operator = (char ch)
 470 {
 471   assign(0, &ch, 1);
 472   return *this;
 473 }
 474 
 475 inline SubString& SubString::operator = (const String& y)
 476 {
 477   assign(y.rep, y.chars(), y.length());
 478   return *this;
 479 }
 480 
 481 inline SubString& SubString::operator = (const SubString& y)
 482 {
 483   assign(y.S.rep, y.chars(), y.length());
 484   return *this;
 485 }
 486 
 487 // Zillions of cats...
 488 
 489 inline void cat(const String& x, const String& y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 490 {
 491   r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length());
 492 }
 493 
 494 inline void cat(const String& x, const SubString& y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 495 {
 496   r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length());
 497 }
 498 
 499 inline void cat(const String& x, const char* y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 500 {
 501   r.rep = Scat(r.rep, x.chars(), x.length(), y, -1);
 502 }
 503 
 504 inline void cat(const String& x, char y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 505 {
 506   r.rep = Scat(r.rep, x.chars(), x.length(), &y, 1);
 507 }
 508 
 509 inline void cat(const SubString& x, const String& y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 510 {
 511   r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length());
 512 }
 513 
 514 inline void cat(const SubString& x, const SubString& y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 515 {
 516   r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length());
 517 }
 518 
 519 inline void cat(const SubString& x, const char* y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 520 {
 521   r.rep = Scat(r.rep, x.chars(), x.length(), y, -1);
 522 }
 523 
 524 inline void cat(const SubString& x, char y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 525 {
 526   r.rep = Scat(r.rep, x.chars(), x.length(), &y, 1);
 527 }
 528 
 529 inline void cat(const char* x, const String& y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 530 {
 531   r.rep = Scat(r.rep, x, -1, y.chars(), y.length());
 532 }
 533 
 534 inline void cat(const char* x, const SubString& y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 535 {
 536   r.rep = Scat(r.rep, x, -1, y.chars(), y.length());
 537 }
 538 
 539 inline void cat(const char* x, const char* y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 540 {
 541   r.rep = Scat(r.rep, x, -1, y, -1);
 542 }
 543 
 544 inline void cat(const char* x, char y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 545 {
 546   r.rep = Scat(r.rep, x, -1, &y, 1);
 547 }
 548 
 549 inline void cat(const String& a, const String& x, const String& y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 550 {
 551   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length());
 552 }
 553 
 554 inline void cat(const String& a, const String& x, const SubString& y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 555 {
 556   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length());
 557 }
 558 
 559 inline void cat(const String& a, const String& x, const char* y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 560 {
 561   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y, -1);
 562 }
 563 
 564 inline void cat(const String& a, const String& x, char y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 565 {
 566   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), &y, 1);
 567 }
 568 
 569 inline void cat(const String& a, const SubString& x, const String& y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 570 {
 571   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length());
 572 }
 573 
 574 inline void cat(const String& a, const SubString& x, const SubString& y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 575 {
 576   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length());
 577 }
 578 
 579 inline void cat(const String& a, const SubString& x, const char* y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 580 {
 581   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y, -1);
 582 }
 583 
 584 inline void cat(const String& a, const SubString& x, char y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 585 {
 586   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), &y, 1);
 587 }
 588 
 589 inline void cat(const String& a, const char* x, const String& y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 590 {
 591   r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, y.chars(), y.length());
 592 }
 593 
 594 inline void cat(const String& a, const char* x, const SubString& y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 595 {
 596   r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, y.chars(), y.length());
 597 }
 598 
 599 inline void cat(const String& a, const char* x, const char* y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 600 {
 601   r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, y, -1);
 602 }
 603 
 604 inline void cat(const String& a, const char* x, char y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 605 {
 606   r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, &y, 1);
 607 }
 608 
 609 
 610 inline void cat(const char* a, const String& x, const String& y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 611 {
 612   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length());
 613 }
 614 
 615 inline void cat(const char* a, const String& x, const SubString& y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 616 {
 617   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length());
 618 }
 619 
 620 inline void cat(const char* a, const String& x, const char* y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 621 {
 622   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y, -1);
 623 }
 624 
 625 inline void cat(const char* a, const String& x, char y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 626 {
 627   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), &y, 1);
 628 }
 629 
 630 inline void cat(const char* a, const SubString& x, const String& y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 631 {
 632   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length());
 633 }
 634 
 635 inline void cat(const char* a, const SubString& x, const SubString& y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 636 {
 637   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length());
 638 }
 639 
 640 inline void cat(const char* a, const SubString& x, const char* y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 641 {
 642   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y, -1);
 643 }
 644 
 645 inline void cat(const char* a, const SubString& x, char y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 646 {
 647   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), &y, 1);
 648 }
 649 
 650 inline void cat(const char* a, const char* x, const String& y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 651 {
 652   r.rep = Scat(r.rep, a, -1, x, -1, y.chars(), y.length());
 653 }
 654 
 655 inline void cat(const char* a, const char* x, const SubString& y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 656 {
 657   r.rep = Scat(r.rep, a, -1, x, -1, y.chars(), y.length());
 658 }
 659 
 660 inline void cat(const char* a, const char* x, const char* y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 661 {
 662   r.rep = Scat(r.rep, a, -1, x, -1, y, -1);
 663 }
 664 
 665 inline void cat(const char* a, const char* x, char y, String& r)
     /* [<][>][^][v][top][bottom][index][help] */
 666 {
 667   r.rep = Scat(r.rep, a, -1, x, -1, &y, 1);
 668 }
 669 
 670 
 671 // operator versions
 672 
 673 inline String& String::operator +=(const String& y)
 674 {
 675   cat(*this, y, *this);
 676   return *this;
 677 }
 678 
 679 inline String& String::operator +=(const SubString& y)
 680 {
 681   cat(*this, y, *this);
 682   return *this;
 683 }
 684 
 685 inline String& String::operator += (const char* y)
 686 {
 687   cat(*this, y, *this);
 688   return *this;
 689 }
 690 
 691 inline String& String:: operator +=(char y)
 692 {
 693   cat(*this, y, *this);
 694   return *this;
 695 }
 696 
 697 // constructive concatenation
 698 
 699 #if defined(__GNUG__) && !defined(_G_NO_NRV)
 700 
 701 inline String operator + (const String& x, const String& y) return r;
 702 {
 703   cat(x, y, r);
 704 }
 705 
 706 inline String operator + (const String& x, const SubString& y) return r;
 707 {
 708   cat(x, y, r);
 709 }
 710 
 711 inline String operator + (const String& x, const char* y) return r;
 712 {
 713   cat(x, y, r);
 714 }
 715 
 716 inline String operator + (const String& x, char y) return r;
 717 {
 718   cat(x, y, r);
 719 }
 720 
 721 inline String operator + (const SubString& x, const String& y) return r;
 722 {
 723   cat(x, y, r);
 724 }
 725 
 726 inline String operator + (const SubString& x, const SubString& y) return r;
 727 {
 728   cat(x, y, r);
 729 }
 730 
 731 inline String operator + (const SubString& x, const char* y) return r;
 732 {
 733   cat(x, y, r);
 734 }
 735 
 736 inline String operator + (const SubString& x, char y) return r;
 737 {
 738   cat(x, y, r);
 739 }
 740 
 741 inline String operator + (const char* x, const String& y) return r;
 742 {
 743   cat(x, y, r);
 744 }
 745 
 746 inline String operator + (const char* x, const SubString& y) return r;
 747 {
 748   cat(x, y, r);
 749 }
 750 
 751 inline String reverse(const String& x) return r;
     /* [<][>][^][v][top][bottom][index][help] */
 752 {
 753   r.rep = Sreverse(x.rep, r.rep);
 754 }
 755 
 756 inline String upcase(const String& x) return r;
     /* [<][>][^][v][top][bottom][index][help] */
 757 {
 758   r.rep = Supcase(x.rep, r.rep);
 759 }
 760 
 761 inline String downcase(const String& x) return r;
     /* [<][>][^][v][top][bottom][index][help] */
 762 {
 763   r.rep = Sdowncase(x.rep, r.rep);
 764 }
 765 
 766 inline String capitalize(const String& x) return r;
     /* [<][>][^][v][top][bottom][index][help] */
 767 {
 768   r.rep = Scapitalize(x.rep, r.rep);
 769 }
 770 
 771 #else /* NO_NRV */
 772 
 773 inline String operator + (const String& x, const String& y)
 774 {
 775   String r;  cat(x, y, r);  return r;
 776 }
 777 
 778 inline String operator + (const String& x, const SubString& y) 
 779 {
 780   String r; cat(x, y, r); return r;
 781 }
 782 
 783 inline String operator + (const String& x, const char* y) 
 784 {
 785   String r; cat(x, y, r); return r;
 786 }
 787 
 788 inline String operator + (const String& x, char y) 
 789 {
 790   String r; cat(x, y, r); return r;
 791 }
 792 
 793 inline String operator + (const SubString& x, const String& y) 
 794 {
 795   String r; cat(x, y, r); return r;
 796 }
 797 
 798 inline String operator + (const SubString& x, const SubString& y) 
 799 {
 800   String r; cat(x, y, r); return r;
 801 }
 802 
 803 inline String operator + (const SubString& x, const char* y) 
 804 {
 805   String r; cat(x, y, r); return r;
 806 }
 807 
 808 inline String operator + (const SubString& x, char y) 
 809 {
 810   String r; cat(x, y, r); return r;
 811 }
 812 
 813 inline String operator + (const char* x, const String& y) 
 814 {
 815   String r; cat(x, y, r); return r;
 816 }
 817 
 818 inline String operator + (const char* x, const SubString& y) 
 819 {
 820   String r; cat(x, y, r); return r;
 821 }
 822 
 823 inline String reverse(const String& x) 
     /* [<][>][^][v][top][bottom][index][help] */
 824 {
 825   String r; r.rep = Sreverse(x.rep, r.rep); return r;
 826 }
 827 
 828 inline String upcase(const String& x) 
     /* [<][>][^][v][top][bottom][index][help] */
 829 {
 830   String r; r.rep = Supcase(x.rep, r.rep); return r;
 831 }
 832 
 833 inline String downcase(const String& x) 
     /* [<][>][^][v][top][bottom][index][help] */
 834 {
 835   String r; r.rep = Sdowncase(x.rep, r.rep); return r;
 836 }
 837 
 838 inline String capitalize(const String& x) 
     /* [<][>][^][v][top][bottom][index][help] */
 839 {
 840   String r; r.rep = Scapitalize(x.rep, r.rep); return r;
 841 }
 842 
 843 #endif
 844 
 845 // prepend
 846 
 847 inline void String::prepend(const String& y)
     /* [<][>][^][v][top][bottom][index][help] */
 848 {
 849   rep = Sprepend(rep, y.chars(), y.length());
 850 }
 851 
 852 inline void String::prepend(const char* y)
     /* [<][>][^][v][top][bottom][index][help] */
 853 {
 854   rep = Sprepend(rep, y, -1); 
 855 }
 856 
 857 inline void String::prepend(char y)
     /* [<][>][^][v][top][bottom][index][help] */
 858 {
 859   rep = Sprepend(rep, &y, 1); 
 860 }
 861 
 862 inline void String::prepend(const SubString& y)
     /* [<][>][^][v][top][bottom][index][help] */
 863 {
 864   rep = Sprepend(rep, y.chars(), y.length());
 865 }
 866 
 867 // misc transformations
 868 
 869 
 870 inline void String::reverse()
     /* [<][>][^][v][top][bottom][index][help] */
 871 {
 872   rep = Sreverse(rep, rep);
 873 }
 874 
 875 
 876 inline void String::upcase()
     /* [<][>][^][v][top][bottom][index][help] */
 877 {
 878   rep = Supcase(rep, rep);
 879 }
 880 
 881 
 882 inline void String::downcase()
     /* [<][>][^][v][top][bottom][index][help] */
 883 {
 884   rep = Sdowncase(rep, rep);
 885 }
 886 
 887 
 888 inline void String::capitalize()
     /* [<][>][^][v][top][bottom][index][help] */
 889 {
 890   rep = Scapitalize(rep, rep);
 891 }
 892 
 893 // element extraction
 894 
 895 inline char&  String::operator [] (int i) 
 896 { 
 897   if (((unsigned)i) >= length()) error("invalid index");
 898   return rep->s[i];
 899 }
 900 
 901 inline const char&  String::operator [] (int i) const
 902 { 
 903   if (((unsigned)i) >= length()) error("invalid index");
 904   return rep->s[i];
 905 }
 906 
 907 inline char  String::elem (int i) const
     /* [<][>][^][v][top][bottom][index][help] */
 908 { 
 909   if (((unsigned)i) >= length()) error("invalid index");
 910   return rep->s[i];
 911 }
 912 
 913 inline char  String::firstchar() const
     /* [<][>][^][v][top][bottom][index][help] */
 914 { 
 915   return elem(0);
 916 }
 917 
 918 inline char  String::lastchar() const
     /* [<][>][^][v][top][bottom][index][help] */
 919 { 
 920   return elem(length() - 1);
 921 }
 922 
 923 // searching
 924 
 925 inline int String::index(char c, int startpos) const
     /* [<][>][^][v][top][bottom][index][help] */
 926 {
 927   return search(startpos, length(), c);
 928 }
 929 
 930 inline int String::index(const char* t, int startpos) const
     /* [<][>][^][v][top][bottom][index][help] */
 931 {   
 932   return search(startpos, length(), t);
 933 }
 934 
 935 inline int String::index(const String& y, int startpos) const
     /* [<][>][^][v][top][bottom][index][help] */
 936 {   
 937   return search(startpos, length(), y.chars(), y.length());
 938 }
 939 
 940 inline int String::index(const SubString& y, int startpos) const
     /* [<][>][^][v][top][bottom][index][help] */
 941 {   
 942   return search(startpos, length(), y.chars(), y.length());
 943 }
 944 
 945 inline int String::index(const Regex& r, int startpos) const
     /* [<][>][^][v][top][bottom][index][help] */
 946 {
 947   int unused;  return r.search(chars(), length(), unused, startpos);
 948 }
 949 
 950 inline int String::contains(char c) const
     /* [<][>][^][v][top][bottom][index][help] */
 951 {
 952   return search(0, length(), c) >= 0;
 953 }
 954 
 955 inline int String::contains(const char* t) const
     /* [<][>][^][v][top][bottom][index][help] */
 956 {   
 957   return search(0, length(), t) >= 0;
 958 }
 959 
 960 inline int String::contains(const String& y) const
     /* [<][>][^][v][top][bottom][index][help] */
 961 {   
 962   return search(0, length(), y.chars(), y.length()) >= 0;
 963 }
 964 
 965 inline int String::contains(const SubString& y) const
     /* [<][>][^][v][top][bottom][index][help] */
 966 {   
 967   return search(0, length(), y.chars(), y.length()) >= 0;
 968 }
 969 
 970 inline int String::contains(char c, int p) const
     /* [<][>][^][v][top][bottom][index][help] */
 971 {
 972   return match(p, length(), 0, &c, 1) >= 0;
 973 }
 974 
 975 inline int String::contains(const char* t, int p) const
     /* [<][>][^][v][top][bottom][index][help] */
 976 {
 977   return match(p, length(), 0, t) >= 0;
 978 }
 979 
 980 inline int String::contains(const String& y, int p) const
     /* [<][>][^][v][top][bottom][index][help] */
 981 {
 982   return match(p, length(), 0, y.chars(), y.length()) >= 0;
 983 }
 984 
 985 inline int String::contains(const SubString& y, int p) const
     /* [<][>][^][v][top][bottom][index][help] */
 986 {
 987   return match(p, length(), 0, y.chars(), y.length()) >= 0;
 988 }
 989 
 990 inline int String::contains(const Regex& r) const
     /* [<][>][^][v][top][bottom][index][help] */
 991 {
 992   int unused;  return r.search(chars(), length(), unused, 0) >= 0;
 993 }
 994 
 995 inline int String::contains(const Regex& r, int p) const
     /* [<][>][^][v][top][bottom][index][help] */
 996 {
 997   return r.match(chars(), length(), p) >= 0;
 998 }
 999 
1000 
1001 inline int String::matches(const SubString& y, int p) const
     /* [<][>][^][v][top][bottom][index][help] */
1002 {
1003   return match(p, length(), 1, y.chars(), y.length()) >= 0;
1004 }
1005 
1006 inline int String::matches(const String& y, int p) const
     /* [<][>][^][v][top][bottom][index][help] */
1007 {
1008   return match(p, length(), 1, y.chars(), y.length()) >= 0;
1009 }
1010 
1011 inline int String::matches(const char* t, int p) const
     /* [<][>][^][v][top][bottom][index][help] */
1012 {
1013   return match(p, length(), 1, t) >= 0;
1014 }
1015 
1016 inline int String::matches(char c, int p) const
     /* [<][>][^][v][top][bottom][index][help] */
1017 {
1018   return match(p, length(), 1, &c, 1) >= 0;
1019 }
1020 
1021 inline int String::matches(const Regex& r, int p) const
     /* [<][>][^][v][top][bottom][index][help] */
1022 {
1023   int l = (p < 0)? -p : length() - p;
1024   return r.match(chars(), length(), p) == l;
1025 }
1026 
1027 
1028 inline int SubString::contains(const char* t) const
     /* [<][>][^][v][top][bottom][index][help] */
1029 {   
1030   return S.search(pos, pos+len, t) >= 0;
1031 }
1032 
1033 inline int SubString::contains(const String& y) const
     /* [<][>][^][v][top][bottom][index][help] */
1034 {   
1035   return S.search(pos, pos+len, y.chars(), y.length()) >= 0;
1036 }
1037 
1038 inline int SubString::contains(const SubString&  y) const
     /* [<][>][^][v][top][bottom][index][help] */
1039 {   
1040   return S.search(pos, pos+len, y.chars(), y.length()) >= 0;
1041 }
1042 
1043 inline int SubString::contains(char c) const
     /* [<][>][^][v][top][bottom][index][help] */
1044 {
1045   return S.search(pos, pos+len, c) >= 0;
1046 }
1047 
1048 inline int SubString::contains(const Regex& r) const
     /* [<][>][^][v][top][bottom][index][help] */
1049 {
1050   int unused;  return r.search(chars(), len, unused, 0) >= 0;
1051 }
1052 
1053 inline int SubString::matches(const Regex& r) const
     /* [<][>][^][v][top][bottom][index][help] */
1054 {
1055   return r.match(chars(), len, 0) == len;
1056 }
1057 
1058 
1059 inline int String::gsub(const String& pat, const String& r)
     /* [<][>][^][v][top][bottom][index][help] */
1060 {
1061   return _gsub(pat.chars(), pat.length(), r.chars(), r.length());
1062 }
1063 
1064 inline int String::gsub(const SubString&  pat, const String& r)
     /* [<][>][^][v][top][bottom][index][help] */
1065 {
1066   return _gsub(pat.chars(), pat.length(), r.chars(), r.length());
1067 }
1068 
1069 inline int String::gsub(const Regex& pat, const String& r)
     /* [<][>][^][v][top][bottom][index][help] */
1070 {
1071   return _gsub(pat, r.chars(), r.length());
1072 }
1073 
1074 inline int String::gsub(const char* pat, const String& r)
     /* [<][>][^][v][top][bottom][index][help] */
1075 {
1076   return _gsub(pat, -1, r.chars(), r.length());
1077 }
1078 
1079 inline int String::gsub(const char* pat, const char* r)
     /* [<][>][^][v][top][bottom][index][help] */
1080 {
1081   return _gsub(pat, -1, r, -1);
1082 }
1083 
1084 
1085 
1086 inline  ostream& operator<<(ostream& s, const String& x)
1087 {
1088    s << x.chars(); return s;
1089 }
1090 
1091 // a zillion comparison operators
1092 
1093 inline int operator==(const String& x, const String& y) 
1094 {
1095   return compare(x, y) == 0; 
1096 }
1097 
1098 inline int operator!=(const String& x, const String& y)
1099 {
1100   return compare(x, y) != 0; 
1101 }
1102 
1103 inline int operator>(const String& x, const String& y)
1104 {
1105   return compare(x, y) > 0; 
1106 }
1107 
1108 inline int operator>=(const String& x, const String& y)
1109 {
1110   return compare(x, y) >= 0; 
1111 }
1112 
1113 inline int operator<(const String& x, const String& y)
1114 {
1115   return compare(x, y) < 0; 
1116 }
1117 
1118 inline int operator<=(const String& x, const String& y)
1119 {
1120   return compare(x, y) <= 0; 
1121 }
1122 
1123 inline int operator==(const String& x, const SubString&  y) 
1124 {
1125   return compare(x, y) == 0; 
1126 }
1127 
1128 inline int operator!=(const String& x, const SubString&  y)
1129 {
1130   return compare(x, y) != 0; 
1131 }
1132 
1133 inline int operator>(const String& x, const SubString&  y)      
1134 {
1135   return compare(x, y) > 0; 
1136 }
1137 
1138 inline int operator>=(const String& x, const SubString&  y)
1139 {
1140   return compare(x, y) >= 0; 
1141 }
1142 
1143 inline int operator<(const String& x, const SubString&  y) 
1144 {
1145   return compare(x, y) < 0; 
1146 }
1147 
1148 inline int operator<=(const String& x, const SubString&  y)
1149 {
1150   return compare(x, y) <= 0; 
1151 }
1152 
1153 inline int operator==(const String& x, const char* t) 
1154 {
1155   return compare(x, t) == 0; 
1156 }
1157 
1158 inline int operator!=(const String& x, const char* t) 
1159 {
1160   return compare(x, t) != 0; 
1161 }
1162 
1163 inline int operator>(const String& x, const char* t)  
1164 {
1165   return compare(x, t) > 0; 
1166 }
1167 
1168 inline int operator>=(const String& x, const char* t) 
1169 {
1170   return compare(x, t) >= 0; 
1171 }
1172 
1173 inline int operator<(const String& x, const char* t)  
1174 {
1175   return compare(x, t) < 0; 
1176 }
1177 
1178 inline int operator<=(const String& x, const char* t) 
1179 {
1180   return compare(x, t) <= 0; 
1181 }
1182 
1183 inline int operator==(const SubString& x, const String& y) 
1184 {
1185   return compare(y, x) == 0; 
1186 }
1187 
1188 inline int operator!=(const SubString& x, const String& y)
1189 {
1190   return compare(y, x) != 0;
1191 }
1192 
1193 inline int operator>(const SubString& x, const String& y)      
1194 {
1195   return compare(y, x) < 0;
1196 }
1197 
1198 inline int operator>=(const SubString& x, const String& y)     
1199 {
1200   return compare(y, x) <= 0;
1201 }
1202 
1203 inline int operator<(const SubString& x, const String& y)      
1204 {
1205   return compare(y, x) > 0;
1206 }
1207 
1208 inline int operator<=(const SubString& x, const String& y)     
1209 {
1210   return compare(y, x) >= 0;
1211 }
1212 
1213 inline int operator==(const SubString& x, const SubString&  y) 
1214 {
1215   return compare(x, y) == 0; 
1216 }
1217 
1218 inline int operator!=(const SubString& x, const SubString&  y)
1219 {
1220   return compare(x, y) != 0;
1221 }
1222 
1223 inline int operator>(const SubString& x, const SubString&  y)      
1224 {
1225   return compare(x, y) > 0;
1226 }
1227 
1228 inline int operator>=(const SubString& x, const SubString&  y)
1229 {
1230   return compare(x, y) >= 0;
1231 }
1232 
1233 inline int operator<(const SubString& x, const SubString&  y) 
1234 {
1235   return compare(x, y) < 0;
1236 }
1237 
1238 inline int operator<=(const SubString& x, const SubString&  y)
1239 {
1240   return compare(x, y) <= 0;
1241 }
1242 
1243 inline int operator==(const SubString& x, const char* t) 
1244 {
1245   return compare(x, t) == 0; 
1246 }
1247 
1248 inline int operator!=(const SubString& x, const char* t) 
1249 {
1250   return compare(x, t) != 0;
1251 }
1252 
1253 inline int operator>(const SubString& x, const char* t)  
1254 {
1255   return compare(x, t) > 0; 
1256 }
1257 
1258 inline int operator>=(const SubString& x, const char* t) 
1259 {
1260   return compare(x, t) >= 0; 
1261 }
1262 
1263 inline int operator<(const SubString& x, const char* t)  
1264 {
1265   return compare(x, t) < 0; 
1266 }
1267 
1268 inline int operator<=(const SubString& x, const char* t) 
1269 {
1270   return compare(x, t) <= 0; 
1271 }
1272 
1273 
1274 // a helper needed by at, before, etc.
1275 
1276 inline SubString String::_substr(int first, int l)
     /* [<][>][^][v][top][bottom][index][help] */
1277 {
1278   if (first < 0 || (unsigned)(first + l) > length() )
1279     return SubString(_nilString, 0, 0) ;
1280   else 
1281     return SubString(*this, first, l);
1282 }
1283 
1284 #endif

/* [<][>][^][v][top][bottom][index][help] */