Update copyright to LGPL on all files
[dyninst.git] / common / src / String.C
1 /*
2  * Copyright (c) 1996-2009 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32
33 // $Id: String.C,v 1.39 2008/07/01 19:26:47 legendre Exp $
34
35 #include "common/h/headers.h"
36 #include <assert.h>
37 #if !defined (os_windows)
38 #include <sys/types.h>
39 #include <regex.h>
40 #endif
41
42 #include <boost/functional/hash.hpp>
43
44 /* This doesn't actually belong here. */
45 void dedemangle( char * demangled, char * result ) 
46 {
47    /* Lifted from Jeffrey Odom.  Code reformatted so
48       I could figure out how to eliminate compiler warnings.
49       Adjusted to handle spaces inside templates intelligently.
50       We cut off everything after the first l-paren, so we don't
51       need to worry about the space after the parameters but
52       before the 'const'. */
53    char * resultBegins = NULL;
54    char * resultEnds = NULL;
55    
56    if ( demangled[0] == '(' &&
57         strstr( demangled, "::" ) != NULL) 
58    {
59      int depth = 0, i = 0;
60      for (;;)
61      { 
62        if (demangled[i] == '\0')
63          break;
64        if (demangled[i] == '(')
65          depth++;
66        if (demangled[i] == ')') {
67          depth--;
68          if (!depth)
69            break;
70        }
71        i++;
72      }
73      if (demangled[i] != '\0') {
74        resultBegins = demangled+i+1;
75        if (resultBegins[0] == ':' && resultBegins[1] == ':')
76          resultBegins += 2;
77        resultEnds = const_cast<char *>(strrchr(resultBegins, ' '));
78        if (resultEnds)
79          resultEnds = '\0';
80      }
81      demangled = resultBegins;
82    }
83    if ( strrchr( demangled, '(' ) != NULL ) 
84    {
85       /* Strip off return types, if any.  Be careful not to
86          pull off [template?/]class/namespace information.
87
88          The only space that matters is the one that's _not_
89          inside a template, so skip the templates and cut at the
90          first space.  We can ignore 'operator[<[<]|>[>]]' because
91          we'll stop before we reach it.
92
93          Caveat: conversion operators (e.g., "operator bool") have
94          spaces in the function name.  Right now we deal with this
95          specifically (is the function "operator *"?).  Could be
96          altered to after the last template but before the last
97          left parenthesis.  (Instead of next, for "operator ()".)
98       */
99
100       resultBegins = demangled;
101       int stack = 0; bool inTemplate = false;
102       unsigned int offset, start_template_offset=0, stop_template_offset=0;
103       int lastColon = 0;
104       for ( offset = 0; offset < strlen( resultBegins ); offset++ ) 
105       {
106          if ( resultBegins[offset] == '<' ) 
107          {
108             stack++;
109             inTemplate = true;
110             if (stack == 1)
111                start_template_offset = offset;
112          }
113          else if ( resultBegins[offset] == '>' ) 
114          {
115             stack--;
116             if ( stack == 0 ) 
117             { 
118                inTemplate = false;
119                stop_template_offset = offset;
120             }
121          }
122          else if ( !inTemplate && resultBegins[offset] == '(' ) 
123          {
124             /* We've stumbled on something without a return value. */
125
126 #ifdef os_solaris
127             /* ptr return types for native compiler don't seem to have a space
128                before the start of the func name (e.g. void*func_name(void*) ).
129
130                need to find last asterick before '(' and see if it's within
131                a template area. if not, then set resultBegins to next offset.
132             */
133             char *prefix = (char*)malloc(strlen(demangled));
134             if (prefix != NULL) 
135             {
136                strncpy(prefix, demangled, offset+1); 
137                prefix[offset+1] = '\0';
138                char *last_ast = strrchr(prefix, '*');            
139                if ( last_ast != NULL ) 
140                {
141                   unsigned last_ast_off = last_ast - prefix;
142                   if ( stop_template_offset ) 
143                   {
144                      if ( last_ast_off > start_template_offset &&
145                           last_ast_off < stop_template_offset ) 
146                      {
147                         // last '*' is in template, no return type
148                         offset = 0;
149                         resultBegins = demangled;
150                         free(prefix);
151                         break;
152                      }
153                   }
154                   // not in template, so last '*' must be end of return type
155                   resultBegins = demangled + last_ast_off + 1;
156                   offset = last_ast_off + 1;
157                   free(prefix);
158                   break;
159                }
160             }
161             // no '*', is actually no return type function
162             offset = 0;
163             resultBegins = demangled;
164 #else
165             offset = 0;
166             resultBegins = demangled;
167 #endif
168             break;
169          }
170          else if ( !inTemplate && resultBegins[offset] == ' ' ) 
171          {
172             /* FIXME: verify that the space isn't in the function name,
173                e.g., 'operator bool'.  If the first space we meet _is_
174                a function name, it doesn't have a(n explicit) return type. */
175             if ( strstr( &(resultBegins[ lastColon + 1 ]), "operator " ) == resultBegins + lastColon + 1 ) 
176             {
177                resultBegins = demangled;
178                offset = 0;
179             }
180             else 
181             {
182                resultBegins = &(resultBegins[offset + 1]);
183                offset++;
184             }
185
186             break;
187          }
188          else if ( !inTemplate && resultBegins[offset] == ':' ) 
189          {
190             lastColon = offset;
191          }
192       } /* end template elimination loop */
193
194       /* Scan past the function name; the first left parenthesis
195          not in in a template declaration starts the function arguments. */
196       stack = 0; inTemplate = false;
197       for ( ; offset < strlen( resultBegins ); offset++ ) 
198       {
199          if ( resultBegins[offset] == '<' ) 
200          {
201             stack++;
202             inTemplate = true;
203          }
204          if ( resultBegins[offset] == '>' ) 
205          {
206             stack--;
207             if ( stack == 0 ) { inTemplate = false; }
208          }
209          if ( !inTemplate && resultBegins[offset] == '(' ) 
210          {
211             resultEnds = const_cast<char *>(&(resultBegins[offset]));
212             * resultEnds = '\0';
213             break;
214          } 
215       } /* end template elimination loop */
216    } /* end if a function prototype */
217    else 
218    {
219       /* Assume demangle OK. */
220       resultBegins = demangled;
221    }
222
223    strcpy( result, resultBegins );
224 } /* end dedemangle */
225
226
227 // Use POSIX regular expression pattern matching to check if string s matches
228 // the pattern in this string
229 bool regexEquiv(const char *str_,  const char *s, bool checkCase ) 
230 {
231 // Would this work under NT?  I don't know.
232 #if !defined(os_windows)
233         regex_t r;
234         int err;
235         bool match = false;
236         int cflags = REG_NOSUB;
237         if ( !checkCase )
238                 cflags |= REG_ICASE;
239
240         // Regular expressions must be compiled first, see 'man regexec'
241         err = regcomp( &r, str_, cflags );
242
243         if ( err == 0 ) 
244    {
245                 // Now we can check for a match
246                 err = regexec( &r, s, 0, NULL, 0 );
247                 if( err == 0 )
248                         match = true;
249         }
250
251         // Deal with errors
252         if ( err != 0 && err != REG_NOMATCH ) 
253    {
254                 char errbuf[80];
255                 regerror( err, &r, errbuf, 80 );
256                 //cerr << "string_ll::regexEquiv -- " << errbuf << endl;
257         }
258
259         // Free the pattern buffer
260         regfree( &r );
261         return match;
262 #else
263         return false;
264 #endif
265 }
266
267 bool prefixed_by(std::string &haystack, std::string &prefix)
268 {
269    if (!haystack.c_str()) 
270       return false;
271
272    const char *res = strstr(haystack.c_str(), prefix.c_str());
273
274    if (res == haystack.c_str())
275       return true;
276
277    return false;
278 }
279
280 bool prefixed_by(std::string &haystack, const char *prefix)
281 {
282    std::string pref_str(prefix);
283    return prefixed_by(haystack, pref_str);
284 }
285
286
287 bool suffixed_by(std::string &haystack, std::string &suffix)
288 {
289    if (!haystack.c_str()) 
290       return false;
291
292    int lastchar = haystack.length() - 1;
293
294    int j = 0;
295    for (int i = suffix.length() - 1; i >= 0; i--)
296    {
297       if (haystack[lastchar - i] != suffix[j])
298          return false;
299       j++;
300    }
301
302    return true;
303 }
304
305 bool suffixed_by(std::string &haystack, const char *suffix)
306 {
307    std::string suff_str(suffix);
308    return suffixed_by(haystack, suff_str);
309 }
310
311 #if defined (cap_use_pdstring)
312
313 #if !defined(os_windows)
314 #include <regex.h>
315 #endif
316
317 #include "common/h/String.h"
318
319 // Declare static member vrbles:
320 pdstring *pdstring::nilptr = NULL;
321 long pdstring::nilptr_initialized = 0;
322 int string_counter::count = 0;
323 string_counter sc;
324
325
326 string_ll::string_ll()
327    : str_(0), len_(0), key_(0) {
328    }
329
330 string_ll::string_ll(const char* str)
331 {
332    str_ = str ? STRDUP(str) : NULL;
333    len_ = str ? STRLEN(str) : 0;
334    key_ = 0; // lazy key define
335 }
336
337 string_ll::string_ll(const char *str, unsigned len) {
338    // same as above constructor, but copies less than the entire string.
339    // You specifiy the # of chars to copy.
340    if (len > strlen(str))
341       // just copy the whole string
342       len = strlen(str);
343
344    len_ = len;
345    str_ = (char *) malloc(sizeof(char) * (len+1));
346    (void) P_memcpy(str_, str, len);
347    str_[len] = '\0';
348
349    key_ = 0; // lazy key define
350 }
351
352 string_ll::string_ll(const string_ll& s)
353    : str_(STRDUP(s.str_)), len_(s.len_), key_(s.key_) {
354       // lazy key define iff "s" lazy key define (as it should be)
355    }
356
357 string_ll::string_ll(const char c) {
358    char tempBuffer[2]; //only need space for one character and '\0'
359    sprintf(tempBuffer, "%c", c);
360
361    str_ = STRDUP(tempBuffer);
362    len_ = STRLEN(tempBuffer);
363
364    key_ = 0; // lazy key define
365 }
366
367 string_ll::string_ll(int i) {
368    char tempBuffer[40];
369    sprintf(tempBuffer, "%d", i);
370
371    str_ = STRDUP(tempBuffer);
372    len_ = STRLEN(tempBuffer);
373
374    key_ = 0; // lazy key define
375 }
376
377 string_ll::string_ll(long l) {
378    char tempBuffer[40];
379    sprintf(tempBuffer, "%ld", l);
380
381    str_ = STRDUP(tempBuffer);
382    len_ = STRLEN(tempBuffer);
383
384    key_ = 0; // lazy key define
385 }
386
387 string_ll::string_ll(unsigned u) {
388    char tempBuffer[40];
389    sprintf(tempBuffer, "%u", u);
390
391    str_ = STRDUP(tempBuffer);
392    len_ = STRLEN(tempBuffer);
393
394    key_ = 0; // lazy key define
395 }
396
397 string_ll::string_ll(unsigned long ul) {
398    char tempBuffer[40];
399    sprintf(tempBuffer, "%lu", ul);
400
401    str_ = STRDUP(tempBuffer);
402    len_ = STRLEN(tempBuffer);
403
404    key_ = 0; // lazy key define
405 }
406
407 string_ll::string_ll(float f) {
408    char tempBuffer[40];
409    sprintf(tempBuffer, "%f", f);
410
411    str_ = STRDUP(tempBuffer);
412    len_ = STRLEN(tempBuffer);
413
414    key_ = 0; // lazy key define
415 }
416
417 string_ll::string_ll(double d) {
418    char tempBuffer[40];
419    sprintf(tempBuffer, "%g", d);
420
421    str_ = STRDUP(tempBuffer);
422    len_ = STRLEN(tempBuffer);
423
424    key_ = 0; // lazy key define
425 }
426
427 string_ll::~string_ll() { 
428    assert(this);
429    if (str_)
430    {
431       free(str_);
432       str_ = 0;
433    }
434 }
435
436 string_ll&
437 string_ll::operator=(const char* str) {
438    if (str_ == str) {
439       return *this;
440    }
441
442    free(str_); str_ = 0;
443
444    str_ = STRDUP(str);
445    len_ = STRLEN(str);
446
447    key_ = 0; // lazy key define
448
449     return *this;
450 }
451
452 string_ll&
453 string_ll::operator=(const string_ll& s) {
454     if (this == &s) {
455         return *this;
456     }
457
458     free(str_); str_ = 0;
459
460     str_ = STRDUP(s.str_);
461     len_ = s.len_;
462     key_ = s.key_; // lazy key define iff "s" lazy key define, which is correct
463
464     return *this;
465 }
466
467 string_ll&
468 string_ll::operator+=(const string_ll& s) {
469     unsigned nlen = len_ + s.len_;
470     char*    ptr  = (char *) malloc(sizeof(char) * (nlen+1));
471     assert(ptr);
472
473     memcpy(ptr, str_, len_);
474     memcpy(&ptr[len_], s.str_, s.len_);
475     ptr[nlen] = '\0';
476
477     free(str_); str_ = 0;
478     str_ = ptr;
479     len_ = nlen;
480
481     key_ = 0;
482
483     return *this;
484 }
485
486 string_ll&
487 string_ll::operator+=(const char *ptr) {
488    // this routine exists as an optimization, sometimes avoiding the need to create
489    // a temporary string, which can be expensive.
490
491    const int ptr_len = P_strlen(ptr);
492    const unsigned nlen = len_ + ptr_len;
493    char *new_ptr = (char *) malloc(sizeof(char) * (nlen+1));
494    assert(new_ptr);
495
496    memcpy(new_ptr, str_, len_);
497    memcpy(&new_ptr[len_], ptr, ptr_len);
498    new_ptr[nlen] = '\0';
499   
500    if (str_)
501       free(str_);
502    str_ = new_ptr;
503    len_ = nlen;
504
505    key_ = 0; // lazy key define
506
507    return *this;
508 }
509
510 string_ll
511 string_ll::operator+(const string_ll& s) const {
512     string_ll ret = *this;
513     return (ret += s);
514 }
515
516 string_ll
517 string_ll::operator+(const char *ptr) const {
518    string_ll ret = *this;
519    return (ret += ptr);
520 }
521
522 bool
523 string_ll::operator==(const string_ll& s) const {
524    if (&s == this) return true;
525
526    updateKeyIfNeeded(); s.updateKeyIfNeeded();
527    if (key_ != s.key_) return false;
528    if (len_ != s.len_) return false;
529    return STREQ(str_, s.str_);
530 }
531
532 bool
533 string_ll::operator!=(const string_ll& s) const {
534    if (&s == this) return false;
535    if (len_ != s.len_) return true;
536    return STRNE(str_, s.str_);
537 }
538
539 bool
540 string_ll::operator<=(const string_ll& s) const {
541     return ((&s == this) || STRLE(str_, s.str_));
542 }
543
544 bool
545 string_ll::operator>=(const string_ll& s) const {
546     return ((&s == this) || STRGE(str_, s.str_));
547 }
548
549 bool
550 string_ll::prefix_of(const char* s, unsigned sl) const {
551     return ((len_ > sl) ? false : STREQN(str_, s, len_));
552 }
553
554 bool
555 string_ll::prefix_of(const string_ll& s) const {
556     return ((&s == this) || prefix_of(s.str_, s.len_));
557 }
558
559 bool
560 string_ll::prefixed_by(const char* s, unsigned sl) const {
561     return ((sl > len_) ? false : STREQN(str_, s, sl));
562 }
563
564 bool
565 string_ll::prefixed_by(const string_ll& s) const {
566     return ((&s == this) || prefixed_by(s.str_, s.len_));
567 }
568
569 bool
570 string_ll::suffix_of(const char* s, unsigned sl) const {
571     return ((len_ > sl) ? false : STREQN(str_, s + strlen( s ) - len_, len_));
572 }
573
574 bool
575 string_ll::suffix_of(const string_ll& s) const {
576     return ((&s == this) || suffix_of(s.str_, s.len_));
577 }
578
579 bool
580 string_ll::suffixed_by(const char* s, unsigned sl) const {
581     return ((sl > len_) ? false : STREQN(str_ + len_ - sl, s, sl));
582 }
583
584 bool
585 string_ll::suffixed_by(const string_ll& s) const {
586     return ((&s == this) || suffixed_by(s.str_, s.len_));
587 }
588
589
590 unsigned
591 string_ll::find (const char *s, unsigned sl) const {
592    if (!len_) return 0;
593   for(unsigned int i=0; i<=(len_-sl); i++) {
594     if( STREQN(str_ + i, s, sl) ) return i;
595   }
596   return len_;
597 }
598
599 unsigned 
600 string_ll::find (const string_ll &s) const{
601   return ((&s == this) ? 0 : find(s.str_, s.len_)); 
602 }
603
604 unsigned
605 string_ll::hashs(const char* str) {
606     if (!str)
607        return 1; // 0 is reserved for unhashed key
608
609     unsigned h = 5381;
610     while (*str) {
611         h = (h << 5) + h + (unsigned) (*str);
612         str++;
613     }
614     return h==0 ? 1 : h; // 0 is reserved for unhashed key
615 }
616
617 unsigned
618 string_ll::STRLEN(const char* str) {
619     return ((str)?(P_strlen(str)):(0));
620 }
621
622 char*
623 string_ll::STRDUP(const char* str) {
624     if (!str) {
625         return 0;
626     }
627
628     unsigned size = P_strlen(str)+1;
629     char*    p    = (char *)malloc(sizeof(char) * size);
630     assert(p);
631
632     (void) P_memcpy(p, str, size);
633     return p;
634 }
635
636 bool
637 string_ll::STREQ(const char* s1, const char* s2) {
638     return ((s1&&s2)?(P_strcmp(s1,s2)==0):(!(s1||s2)));
639 }
640
641 bool
642 string_ll::STREQN(const char* s1, const char* s2, unsigned len) {
643     return ((s1&&s2)?(P_strncmp(s1,s2,len)==0):(!(s1||s2)));
644 }
645
646 bool
647 string_ll::STRNE(const char* s1, const char* s2) {
648     return ((s1&&s2)?(P_strcmp(s1,s2)!=0):(false));
649 }
650
651 bool
652 string_ll::STRLT(const char* s1, const char* s2) {
653     return ((s1&&s2)?(P_strcmp(s1,s2)<0):(false));
654 }
655
656 bool
657 string_ll::STRLE(const char* s1, const char* s2) {
658     return ((s1&&s2)?(P_strcmp(s1,s2)<=0):(!(s1||s2)));
659 }
660
661 bool
662 string_ll::STRGT(const char* s1, const char* s2) {
663     return ((s1&&s2)?(P_strcmp(s1,s2)>0):(false));
664 }
665
666 bool
667 string_ll::STRGE(const char* s1, const char* s2) {
668     return ((s1&&s2)?(P_strcmp(s1,s2)>=0):(!(s1||s2)));
669 }
670
671 const char *
672 string_ll::STRCHR(const char* s, char c) {
673     return (s?(P_strchr(s,c)):(NULL));
674 }
675
676 string_ll
677 string_ll::substr(unsigned pos, unsigned len) const {
678         if( pos >= len_ )
679                 return string_ll( "" );
680         else
681                 return string_ll( str_ + pos, len );
682 }
683
684 bool
685 string_ll::wildcardEquiv( const string_ll &them, bool checkCase ) const {
686         if( *this == them )
687                 return true;
688         else
689                 return pattern_match( str_, them.str_, checkCase );
690 }
691
692
693 // This function will match string s against pattern p.
694 // Asterisks match 0 or more wild characters, and a question
695 // mark matches exactly one wild character.  In other words,
696 // the asterisk is the equivalent of the regex ".*" and the
697 // question mark is the equivalent of "."
698
699 bool
700 string_ll::pattern_match( const char *p, const char *s, bool checkCase ) {
701         //const char *p = ptrn;
702         //char *s = str;
703
704         while ( true ) {
705                 // If at the end of the pattern, it matches if also at the end of the string
706                 if( *p == '\0' )
707                         return ( *s == '\0' );
708
709                 // Process a '*'
710                 if( *p == MULTIPLE_WILDCARD_CHAR ) {
711                         ++p;
712                         
713                         // If at the end of the pattern, it matches
714                         if( *p == '\0' )
715                                 return true;
716
717                         // Try to match the remaining pattern for each remaining substring of s
718                         for(; *s != '\0'; ++s )
719                                 if( pattern_match( p, s, checkCase ) )
720                                         return true;
721                         // Failed
722                         return false;
723                 }
724
725                 // If at the end of the string (and at this point, not of the pattern), it fails
726                 if( *s == '\0' )
727                         return false;
728
729                 // Check if this character matches
730                 bool matchChar = false;
731                 if( *p == WILDCARD_CHAR || *p == *s )
732                         matchChar = true;
733                 else if( !checkCase ) {
734                         if( *p >= 'A' && *p <= 'Z' && *s == ( *p + ( 'a' - 'A' ) ) )
735                                 matchChar = true;
736                         else if( *p >= 'a' && *p <= 'z' && *s == ( *p - ( 'a' - 'A' ) ) )
737                                 matchChar = true;
738                 }
739
740                 if( matchChar ) {
741                         ++p;
742                         ++s;
743                         continue;
744                 }
745
746                 // Did not match
747                 return false;
748         }
749 }
750
751
752 // Use POSIX regular expression pattern matching to check if string s matches
753 // the pattern in this string
754 bool
755 string_ll::regexEquiv( const char *s, bool checkCase ) const {
756 // Would this work under NT?  I don't know.
757 #if !defined(os_windows)
758         regex_t r;
759         int err;
760         bool match = false;
761         int cflags = REG_NOSUB;
762         if( !checkCase )
763                 cflags |= REG_ICASE;
764
765         // Regular expressions must be compiled first, see 'man regexec'
766         err = regcomp( &r, str_, cflags );
767
768         if( err == 0 ) {
769                 // Now we can check for a match
770                 err = regexec( &r, s, 0, NULL, 0 );
771                 if( err == 0 )
772                         match = true;
773         }
774
775         // Deal with errors
776         if( err != 0 && err != REG_NOMATCH ) {
777                 char errbuf[80];
778                 regerror( err, &r, errbuf, 80 );
779                 //cerr << "string_ll::regexEquiv -- " << errbuf << endl;
780         }
781
782         // Free the pattern buffer
783         regfree( &r );
784         return match;
785 #else
786         return false;
787 #endif
788 }
789
790
791 ostream& operator<< (ostream &os, const string_ll &s) {
792    if(s.str_ != NULL)
793       os << s.str_;
794    return os;
795 }
796
797 //debug_ostream& operator<< (debug_ostream &os, const string_ll &s) {
798 //   if(s.str_ != NULL)
799 //      os << s.str_;
800 //   return os;
801 //}
802
803 pdstring operator+(const char *ptr, const pdstring &str) {
804    // a syntactical convenience.
805    // This fn could probably be optimized quite a bit (pre-allocate exactly
806    // the # of bytes that are needed)
807    pdstring result(ptr);
808    result += str;
809    return result;
810 }
811
812 void pdstring::initialize_static_stuff() {
813    // should only get called once:
814    // VG(06/15/02): this assertion doesn't hold w/VC.NET because nilptr is never initialized!
815    //assert(nilptr == NULL);
816
817    nilptr = new pdstring((char*)NULL);
818       // the typecast is essential, lest NULL be interpreted
819       // as the integer 0 instead of the pointer 0!
820
821    nilptr_initialized = MAGIC_NILPTR_FLAG;
822       // magic value: see getNilptr() for explanation
823 }
824
825 void pdstring::free_static_stuff() {
826    delete nilptr;
827    nilptr = NULL;
828 }
829
830
831 #endif /*defined(cap_use_pdstring) */