/[pcre]/code/trunk/pcrecpp.cc
ViewVC logotype

Diff of /code/trunk/pcrecpp.cc

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 77 by nigel, Sat Feb 24 21:40:45 2007 UTC revision 326 by ph10, Sat Mar 8 17:24:02 2008 UTC
# Line 29  Line 29 
29  //  //
30  // Author: Sanjay Ghemawat  // Author: Sanjay Ghemawat
31    
32    #ifdef HAVE_CONFIG_H
33    #include "config.h"
34    #endif
35    
36  #include <stdlib.h>  #include <stdlib.h>
37  #include <stdio.h>  #include <stdio.h>
38  #include <ctype.h>  #include <ctype.h>
# Line 36  Line 40 
40  #include <assert.h>  #include <assert.h>
41  #include <errno.h>  #include <errno.h>
42  #include <string>  #include <string>
43  #include "config.h"  #include <algorithm>
44  // We need this to compile the proper dll on windows/msys.  This is copied  
45  // from pcre_internal.h.  It would probably be better just to include that.  #include "pcrecpp_internal.h"
 #define PCRE_DEFINITION  /* Win32 __declspec(export) trigger for .dll */  
46  #include "pcre.h"  #include "pcre.h"
 #include "pcre_stringpiece.h"  
47  #include "pcrecpp.h"  #include "pcrecpp.h"
48    #include "pcre_stringpiece.h"
49    
50    
51  namespace pcrecpp {  namespace pcrecpp {
# Line 52  static const int kMaxArgs = 16; Line 55  static const int kMaxArgs = 16;
55  static const int kVecSize = (1 + kMaxArgs) * 3;  // results + PCRE workspace  static const int kVecSize = (1 + kMaxArgs) * 3;  // results + PCRE workspace
56    
57  // Special object that stands-in for no argument  // Special object that stands-in for no argument
58  Arg no_arg((void*)NULL);  Arg RE::no_arg((void*)NULL);
59    
60    // This is for ABI compatibility with old versions of pcre (pre-7.6),
61    // which defined a global no_arg variable instead of putting it in the
62    // RE class.  This works on GCC >= 3, at least.  We could probably have
63    // a more inclusive test if we ever needed it.
64    #if defined(__GNUC__) && __GNUC__ >= 3
65    extern Arg no_arg __attribute__((alias("_ZN7pcrecpp2RE6no_argE")));
66    #endif
67    
68  // If a regular expression has no error, its error_ field points here  // If a regular expression has no error, its error_ field points here
69  static const string empty_string;  static const string empty_string;
# Line 60  static const string empty_string; Line 71  static const string empty_string;
71  // If the user doesn't ask for any options, we just use this one  // If the user doesn't ask for any options, we just use this one
72  static RE_Options default_options;  static RE_Options default_options;
73    
74  void RE::Init(const char* pat, const RE_Options* options) {  void RE::Init(const string& pat, const RE_Options* options) {
75    pattern_ = pat;    pattern_ = pat;
76    if (options == NULL) {    if (options == NULL) {
77      options_ = default_options;      options_ = default_options;
# Line 73  void RE::Init(const char* pat, const RE_ Line 84  void RE::Init(const char* pat, const RE_
84    
85    re_partial_ = Compile(UNANCHORED);    re_partial_ = Compile(UNANCHORED);
86    if (re_partial_ != NULL) {    if (re_partial_ != NULL) {
87      // Check for complicated patterns.  The following change is      re_full_ = Compile(ANCHOR_BOTH);
     // conservative in that it may treat some "simple" patterns  
     // as "complex" (e.g., if the vertical bar is in a character  
     // class or is escaped).  But it seems good enough.  
     if (strchr(pat, '|') == NULL) {  
       // Simple pattern: we can use position-based checks to perform  
       // fully anchored matches  
       re_full_ = re_partial_;  
     } else {  
       // We need a special pattern for anchored matches  
       re_full_ = Compile(ANCHOR_BOTH);  
     }  
88    }    }
89  }  }
90    
91    void RE::Cleanup() {
92      if (re_full_ != NULL)         (*pcre_free)(re_full_);
93      if (re_partial_ != NULL)      (*pcre_free)(re_partial_);
94      if (error_ != &empty_string)  delete error_;
95    }
96    
97    
98  RE::~RE() {  RE::~RE() {
99    if (re_full_ != NULL && re_full_ != re_partial_) (*pcre_free)(re_full_);    Cleanup();
   if (re_partial_ != NULL)                         (*pcre_free)(re_partial_);  
   if (error_ != &empty_string)                     delete error_;  
100  }  }
101    
102    
103  pcre* RE::Compile(Anchor anchor) {  pcre* RE::Compile(Anchor anchor) {
104    // First, convert RE_Options into pcre options    // First, convert RE_Options into pcre options
105    int pcre_options = 0;    int pcre_options = 0;
106    if (options_.utf8())    pcre_options = options_.all_options();
     pcre_options |= PCRE_UTF8;  
107    
108    // Special treatment for anchoring.  This is needed because at    // Special treatment for anchoring.  This is needed because at
109    // runtime pcre only provides an option for anchoring at the    // runtime pcre only provides an option for anchoring at the
# Line 332  bool RE::Replace(const StringPiece& rewr Line 337  bool RE::Replace(const StringPiece& rewr
337    return true;    return true;
338  }  }
339    
340    // Returns PCRE_NEWLINE_CRLF, PCRE_NEWLINE_CR, or PCRE_NEWLINE_LF.
341    // Note that PCRE_NEWLINE_CRLF is defined to be P_N_CR | P_N_LF.
342    // Modified by PH to add PCRE_NEWLINE_ANY and PCRE_NEWLINE_ANYCRLF.
343    
344    static int NewlineMode(int pcre_options) {
345      // TODO: if we can make it threadsafe, cache this var
346      int newline_mode = 0;
347      /* if (newline_mode) return newline_mode; */  // do this once it's cached
348      if (pcre_options & (PCRE_NEWLINE_CRLF|PCRE_NEWLINE_CR|PCRE_NEWLINE_LF|
349                          PCRE_NEWLINE_ANY|PCRE_NEWLINE_ANYCRLF)) {
350        newline_mode = (pcre_options &
351                        (PCRE_NEWLINE_CRLF|PCRE_NEWLINE_CR|PCRE_NEWLINE_LF|
352                         PCRE_NEWLINE_ANY|PCRE_NEWLINE_ANYCRLF));
353      } else {
354        int newline;
355        pcre_config(PCRE_CONFIG_NEWLINE, &newline);
356        if (newline == 10)
357          newline_mode = PCRE_NEWLINE_LF;
358        else if (newline == 13)
359          newline_mode = PCRE_NEWLINE_CR;
360        else if (newline == 3338)
361          newline_mode = PCRE_NEWLINE_CRLF;
362        else if (newline == -1)
363          newline_mode = PCRE_NEWLINE_ANY;
364        else if (newline == -2)
365          newline_mode = PCRE_NEWLINE_ANYCRLF;
366        else
367          assert("" == "Unexpected return value from pcre_config(NEWLINE)");
368      }
369      return newline_mode;
370    }
371    
372  int RE::GlobalReplace(const StringPiece& rewrite,  int RE::GlobalReplace(const StringPiece& rewrite,
373                        string *str) const {                        string *str) const {
374    int count = 0;    int count = 0;
# Line 340  int RE::GlobalReplace(const StringPiece& Line 377  int RE::GlobalReplace(const StringPiece&
377    int start = 0;    int start = 0;
378    int lastend = -1;    int lastend = -1;
379    
380    for (; start <= static_cast<int>(str->length()); count++) {    while (start <= static_cast<int>(str->length())) {
381      int matches = TryMatch(*str, start, UNANCHORED, vec, kVecSize);      int matches = TryMatch(*str, start, UNANCHORED, vec, kVecSize);
382      if (matches <= 0)      if (matches <= 0)
383        break;        break;
# Line 350  int RE::GlobalReplace(const StringPiece& Line 387  int RE::GlobalReplace(const StringPiece&
387      if (matchstart == matchend && matchstart == lastend) {      if (matchstart == matchend && matchstart == lastend) {
388        // advance one character if we matched an empty string at the same        // advance one character if we matched an empty string at the same
389        // place as the last match occurred        // place as the last match occurred
390        if (start < static_cast<int>(str->length()))        matchend = start + 1;
391          out.push_back((*str)[start]);        // If the current char is CR and we're in CRLF mode, skip LF too.
392        start++;        // Note it's better to call pcre_fullinfo() than to examine
393          // all_options(), since options_ could have changed bewteen
394          // compile-time and now, but this is simpler and safe enough.
395          // Modified by PH to add ANY and ANYCRLF.
396          if (start+1 < static_cast<int>(str->length()) &&
397              (*str)[start] == '\r' && (*str)[start+1] == '\n' &&
398              (NewlineMode(options_.all_options()) == PCRE_NEWLINE_CRLF ||
399               NewlineMode(options_.all_options()) == PCRE_NEWLINE_ANY ||
400               NewlineMode(options_.all_options()) == PCRE_NEWLINE_ANYCRLF)
401              ) {
402            matchend++;
403          }
404          // We also need to advance more than one char if we're in utf8 mode.
405    #ifdef SUPPORT_UTF8
406          if (options_.utf8()) {
407            while (matchend < static_cast<int>(str->length()) &&
408                   ((*str)[matchend] & 0xc0) == 0x80)
409              matchend++;
410          }
411    #endif
412          if (matchend <= static_cast<int>(str->length()))
413            out.append(*str, start, matchend - start);
414          start = matchend;
415      } else {      } else {
416        out.append(*str, start, matchstart - start);        out.append(*str, start, matchstart - start);
417        Rewrite(&out, rewrite, *str, vec, matches);        Rewrite(&out, rewrite, *str, vec, matches);
# Line 378  bool RE::Extract(const StringPiece& rewr Line 437  bool RE::Extract(const StringPiece& rewr
437    int matches = TryMatch(text, 0, UNANCHORED, vec, kVecSize);    int matches = TryMatch(text, 0, UNANCHORED, vec, kVecSize);
438    if (matches == 0)    if (matches == 0)
439      return false;      return false;
440    out->clear();    out->erase();
441    return Rewrite(out, rewrite, text, vec, matches);    return Rewrite(out, rewrite, text, vec, matches);
442  }  }
443    
444    /*static*/ string RE::QuoteMeta(const StringPiece& unquoted) {
445      string result;
446    
447      // Escape any ascii character not in [A-Za-z_0-9].
448      //
449      // Note that it's legal to escape a character even if it has no
450      // special meaning in a regular expression -- so this function does
451      // that.  (This also makes it identical to the perl function of the
452      // same name; see `perldoc -f quotemeta`.)  The one exception is
453      // escaping NUL: rather than doing backslash + NUL, like perl does,
454      // we do '\0', because pcre itself doesn't take embedded NUL chars.
455      for (int ii = 0; ii < unquoted.size(); ++ii) {
456        // Note that using 'isalnum' here raises the benchmark time from
457        // 32ns to 58ns:
458        if (unquoted[ii] == '\0') {
459          result += "\\0";
460        } else if ((unquoted[ii] < 'a' || unquoted[ii] > 'z') &&
461                   (unquoted[ii] < 'A' || unquoted[ii] > 'Z') &&
462                   (unquoted[ii] < '0' || unquoted[ii] > '9') &&
463                   unquoted[ii] != '_' &&
464                   // If this is the part of a UTF8 or Latin1 character, we need
465                   // to copy this byte without escaping.  Experimentally this is
466                   // what works correctly with the regexp library.
467                   !(unquoted[ii] & 128)) {
468          result += '\\';
469          result += unquoted[ii];
470        } else {
471          result += unquoted[ii];
472        }
473      }
474    
475      return result;
476    }
477    
478  /***** Actual matching and rewriting code *****/  /***** Actual matching and rewriting code *****/
479    
480  int RE::TryMatch(const StringPiece& text,  int RE::TryMatch(const StringPiece& text,
# Line 395  int RE::TryMatch(const StringPiece& text Line 488  int RE::TryMatch(const StringPiece& text
488      return 0;      return 0;
489    }    }
490    
491    pcre_extra extra = { 0 };    pcre_extra extra = { 0, 0, 0, 0, 0, 0 };
492    if (options_.match_limit() > 0) {    if (options_.match_limit() > 0) {
493      extra.flags = PCRE_EXTRA_MATCH_LIMIT;      extra.flags |= PCRE_EXTRA_MATCH_LIMIT;
494      extra.match_limit = options_.match_limit();      extra.match_limit = options_.match_limit();
495    }    }
496      if (options_.match_limit_recursion() > 0) {
497        extra.flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
498        extra.match_limit_recursion = options_.match_limit_recursion();
499      }
500    int rc = pcre_exec(re,              // The regular expression object    int rc = pcre_exec(re,              // The regular expression object
501                       &extra,                       &extra,
502                       text.data(),                       (text.data() == NULL) ? "" : text.data(),
503                       text.size(),                       text.size(),
504                       startpos,                       startpos,
505                       (anchor == UNANCHORED) ? 0 : PCRE_ANCHORED,                       (anchor == UNANCHORED) ? 0 : PCRE_ANCHORED,
# Line 424  int RE::TryMatch(const StringPiece& text Line 521  int RE::TryMatch(const StringPiece& text
521      rc = vecsize / 2;      rc = vecsize / 2;
522    }    }
523    
   if ((anchor == ANCHOR_BOTH) && (re_full_ == re_partial_)) {  
     // We need an extra check to make sure that the match extended  
     // to the end of the input string  
     assert(vec[0] == 0);                 // PCRE_ANCHORED forces starting match  
     if (vec[1] != text.size()) return 0; // Did not get ending match  
   }  
   
524    return rc;    return rc;
525  }  }
526    
# Line 449  bool RE::DoMatchImpl(const StringPiece& Line 539  bool RE::DoMatchImpl(const StringPiece&
539    
540    *consumed = vec[1];    *consumed = vec[1];
541    
542    if (args == NULL) {    if (n == 0 || args == NULL) {
543      // We are not interested in results      // We are not interested in results
544      return true;      return true;
545    }    }
546    
547      if (NumberOfCapturingGroups() < n) {
548        // RE has fewer capturing groups than number of arg pointers passed in
549        return false;
550      }
551    
552    // If we got here, we must have matched the whole pattern.    // If we got here, we must have matched the whole pattern.
553    // We do not need (can not do) any more checks on the value of 'matches' here    // We do not need (can not do) any more checks on the value of 'matches' here
554    // -- see the comment for TryMatch.    // -- see the comment for TryMatch.
# Line 517  bool RE::Rewrite(string *out, const Stri Line 612  bool RE::Rewrite(string *out, const Stri
612    
613  // Return the number of capturing subpatterns, or -1 if the  // Return the number of capturing subpatterns, or -1 if the
614  // regexp wasn't valid on construction.  // regexp wasn't valid on construction.
615  int RE::NumberOfCapturingGroups() {  int RE::NumberOfCapturingGroups() const {
616    if (re_partial_ == NULL) return -1;    if (re_partial_ == NULL) return -1;
617    
618    int result;    int result;
# Line 537  bool Arg::parse_null(const char* str, in Line 632  bool Arg::parse_null(const char* str, in
632  }  }
633    
634  bool Arg::parse_string(const char* str, int n, void* dest) {  bool Arg::parse_string(const char* str, int n, void* dest) {
635      if (dest == NULL) return true;
636    reinterpret_cast<string*>(dest)->assign(str, n);    reinterpret_cast<string*>(dest)->assign(str, n);
637    return true;    return true;
638  }  }
639    
640  bool Arg::parse_stringpiece(const char* str, int n, void* dest) {  bool Arg::parse_stringpiece(const char* str, int n, void* dest) {
641      if (dest == NULL) return true;
642    reinterpret_cast<StringPiece*>(dest)->set(str, n);    reinterpret_cast<StringPiece*>(dest)->set(str, n);
643    return true;    return true;
644  }  }
645    
646  bool Arg::parse_char(const char* str, int n, void* dest) {  bool Arg::parse_char(const char* str, int n, void* dest) {
647    if (n != 1) return false;    if (n != 1) return false;
648      if (dest == NULL) return true;
649    *(reinterpret_cast<char*>(dest)) = str[0];    *(reinterpret_cast<char*>(dest)) = str[0];
650    return true;    return true;
651  }  }
652    
653  bool Arg::parse_uchar(const char* str, int n, void* dest) {  bool Arg::parse_uchar(const char* str, int n, void* dest) {
654    if (n != 1) return false;    if (n != 1) return false;
655      if (dest == NULL) return true;
656    *(reinterpret_cast<unsigned char*>(dest)) = str[0];    *(reinterpret_cast<unsigned char*>(dest)) = str[0];
657    return true;    return true;
658  }  }
# Line 602  bool Arg::parse_long_radix(const char* s Line 701  bool Arg::parse_long_radix(const char* s
701    long r = strtol(str, &end, radix);    long r = strtol(str, &end, radix);
702    if (end != str + n) return false;   // Leftover junk    if (end != str + n) return false;   // Leftover junk
703    if (errno) return false;    if (errno) return false;
704      if (dest == NULL) return true;
705    *(reinterpret_cast<long*>(dest)) = r;    *(reinterpret_cast<long*>(dest)) = r;
706    return true;    return true;
707  }  }
# Line 613  bool Arg::parse_ulong_radix(const char* Line 713  bool Arg::parse_ulong_radix(const char*
713    if (n == 0) return false;    if (n == 0) return false;
714    char buf[kMaxNumberLength+1];    char buf[kMaxNumberLength+1];
715    str = TerminateNumber(buf, str, n);    str = TerminateNumber(buf, str, n);
716      if (str[0] == '-') return false;    // strtoul() on a negative number?!
717    char* end;    char* end;
718    errno = 0;    errno = 0;
719    unsigned long r = strtoul(str, &end, radix);    unsigned long r = strtoul(str, &end, radix);
720    if (end != str + n) return false;   // Leftover junk    if (end != str + n) return false;   // Leftover junk
721    if (errno) return false;    if (errno) return false;
722      if (dest == NULL) return true;
723    *(reinterpret_cast<unsigned long*>(dest)) = r;    *(reinterpret_cast<unsigned long*>(dest)) = r;
724    return true;    return true;
725  }  }
# Line 629  bool Arg::parse_short_radix(const char* Line 731  bool Arg::parse_short_radix(const char*
731    long r;    long r;
732    if (!parse_long_radix(str, n, &r, radix)) return false; // Could not parse    if (!parse_long_radix(str, n, &r, radix)) return false; // Could not parse
733    if (r < SHRT_MIN || r > SHRT_MAX) return false;       // Out of range    if (r < SHRT_MIN || r > SHRT_MAX) return false;       // Out of range
734    *(reinterpret_cast<short*>(dest)) = r;    if (dest == NULL) return true;
735      *(reinterpret_cast<short*>(dest)) = static_cast<short>(r);
736    return true;    return true;
737  }  }
738    
# Line 640  bool Arg::parse_ushort_radix(const char* Line 743  bool Arg::parse_ushort_radix(const char*
743    unsigned long r;    unsigned long r;
744    if (!parse_ulong_radix(str, n, &r, radix)) return false; // Could not parse    if (!parse_ulong_radix(str, n, &r, radix)) return false; // Could not parse
745    if (r > USHRT_MAX) return false;                      // Out of range    if (r > USHRT_MAX) return false;                      // Out of range
746    *(reinterpret_cast<unsigned short*>(dest)) = r;    if (dest == NULL) return true;
747      *(reinterpret_cast<unsigned short*>(dest)) = static_cast<unsigned short>(r);
748    return true;    return true;
749  }  }
750    
# Line 651  bool Arg::parse_int_radix(const char* st Line 755  bool Arg::parse_int_radix(const char* st
755    long r;    long r;
756    if (!parse_long_radix(str, n, &r, radix)) return false; // Could not parse    if (!parse_long_radix(str, n, &r, radix)) return false; // Could not parse
757    if (r < INT_MIN || r > INT_MAX) return false;         // Out of range    if (r < INT_MIN || r > INT_MAX) return false;         // Out of range
758      if (dest == NULL) return true;
759    *(reinterpret_cast<int*>(dest)) = r;    *(reinterpret_cast<int*>(dest)) = r;
760    return true;    return true;
761  }  }
# Line 662  bool Arg::parse_uint_radix(const char* s Line 767  bool Arg::parse_uint_radix(const char* s
767    unsigned long r;    unsigned long r;
768    if (!parse_ulong_radix(str, n, &r, radix)) return false; // Could not parse    if (!parse_ulong_radix(str, n, &r, radix)) return false; // Could not parse
769    if (r > UINT_MAX) return false;                       // Out of range    if (r > UINT_MAX) return false;                       // Out of range
770      if (dest == NULL) return true;
771    *(reinterpret_cast<unsigned int*>(dest)) = r;    *(reinterpret_cast<unsigned int*>(dest)) = r;
772    return true;    return true;
773  }  }
# Line 682  bool Arg::parse_longlong_radix(const cha Line 788  bool Arg::parse_longlong_radix(const cha
788    long long r = strtoq(str, &end, radix);    long long r = strtoq(str, &end, radix);
789  #elif defined HAVE_STRTOLL  #elif defined HAVE_STRTOLL
790    long long r = strtoll(str, &end, radix);    long long r = strtoll(str, &end, radix);
791    #elif defined HAVE__STRTOI64
792      long long r = _strtoi64(str, &end, radix);
793  #else  #else
794  #error parse_longlong_radix: cannot convert input to a long-long  #error parse_longlong_radix: cannot convert input to a long-long
795  #endif  #endif
796    if (end != str + n) return false;   // Leftover junk    if (end != str + n) return false;   // Leftover junk
797    if (errno) return false;    if (errno) return false;
798      if (dest == NULL) return true;
799    *(reinterpret_cast<long long*>(dest)) = r;    *(reinterpret_cast<long long*>(dest)) = r;
800    return true;    return true;
801  #endif   /* HAVE_LONG_LONG */  #endif   /* HAVE_LONG_LONG */
# Line 702  bool Arg::parse_ulonglong_radix(const ch Line 811  bool Arg::parse_ulonglong_radix(const ch
811    if (n == 0) return false;    if (n == 0) return false;
812    char buf[kMaxNumberLength+1];    char buf[kMaxNumberLength+1];
813    str = TerminateNumber(buf, str, n);    str = TerminateNumber(buf, str, n);
814      if (str[0] == '-') return false;    // strtoull() on a negative number?!
815    char* end;    char* end;
816    errno = 0;    errno = 0;
817  #if defined HAVE_STRTOQ  #if defined HAVE_STRTOQ
818    unsigned long long r = strtouq(str, &end, radix);    unsigned long long r = strtouq(str, &end, radix);
819  #elif defined HAVE_STRTOLL  #elif defined HAVE_STRTOLL
820    unsigned long long r = strtoull(str, &end, radix);    unsigned long long r = strtoull(str, &end, radix);
821    #elif defined HAVE__STRTOI64
822      unsigned long long r = _strtoui64(str, &end, radix);
823  #else  #else
824  #error parse_ulonglong_radix: cannot convert input to a long-long  #error parse_ulonglong_radix: cannot convert input to a long-long
825  #endif  #endif
826    if (end != str + n) return false;   // Leftover junk    if (end != str + n) return false;   // Leftover junk
827    if (errno) return false;    if (errno) return false;
828      if (dest == NULL) return true;
829    *(reinterpret_cast<unsigned long long*>(dest)) = r;    *(reinterpret_cast<unsigned long long*>(dest)) = r;
830    return true;    return true;
831  #endif   /* HAVE_UNSIGNED_LONG_LONG */  #endif   /* HAVE_UNSIGNED_LONG_LONG */
# Line 730  bool Arg::parse_double(const char* str, Line 843  bool Arg::parse_double(const char* str,
843    double r = strtod(buf, &end);    double r = strtod(buf, &end);
844    if (end != buf + n) return false;   // Leftover junk    if (end != buf + n) return false;   // Leftover junk
845    if (errno) return false;    if (errno) return false;
846      if (dest == NULL) return true;
847    *(reinterpret_cast<double*>(dest)) = r;    *(reinterpret_cast<double*>(dest)) = r;
848    return true;    return true;
849  }  }
# Line 737  bool Arg::parse_double(const char* str, Line 851  bool Arg::parse_double(const char* str,
851  bool Arg::parse_float(const char* str, int n, void* dest) {  bool Arg::parse_float(const char* str, int n, void* dest) {
852    double r;    double r;
853    if (!parse_double(str, n, &r)) return false;    if (!parse_double(str, n, &r)) return false;
854      if (dest == NULL) return true;
855    *(reinterpret_cast<float*>(dest)) = static_cast<float>(r);    *(reinterpret_cast<float*>(dest)) = static_cast<float>(r);
856    return true;    return true;
857  }  }
# Line 756  bool Arg::parse_float(const char* str, i Line 871  bool Arg::parse_float(const char* str, i
871      return parse_##name##_radix(str, n, dest, 0);                       \      return parse_##name##_radix(str, n, dest, 0);                       \
872    }    }
873    
874  DEFINE_INTEGER_PARSERS(short);  DEFINE_INTEGER_PARSERS(short)      /*                                   */
875  DEFINE_INTEGER_PARSERS(ushort);  DEFINE_INTEGER_PARSERS(ushort)     /*                                   */
876  DEFINE_INTEGER_PARSERS(int);  DEFINE_INTEGER_PARSERS(int)        /* Don't use semicolons after these  */
877  DEFINE_INTEGER_PARSERS(uint);  DEFINE_INTEGER_PARSERS(uint)       /* statements because they can cause */
878  DEFINE_INTEGER_PARSERS(long);  DEFINE_INTEGER_PARSERS(long)       /* compiler warnings if the checking */
879  DEFINE_INTEGER_PARSERS(ulong);  DEFINE_INTEGER_PARSERS(ulong)      /* level is turned up high enough.   */
880  DEFINE_INTEGER_PARSERS(longlong);  DEFINE_INTEGER_PARSERS(longlong)   /*                                   */
881  DEFINE_INTEGER_PARSERS(ulonglong);  DEFINE_INTEGER_PARSERS(ulonglong)  /*                                   */
882    
883  #undef DEFINE_INTEGER_PARSERS  #undef DEFINE_INTEGER_PARSERS
884    

Legend:
Removed from v.77  
changed lines
  Added in v.326

  ViewVC Help
Powered by ViewVC 1.1.5