parser-util.cc

Go to the documentation of this file.
00001 
00002 // -*- mode: c++; c-basic-offset:4 -*-
00003 
00004 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
00005 // Access Protocol.
00006 
00007 // Copyright (c) 2002,2003 OPeNDAP, Inc.
00008 // Author: James Gallagher <jgallagher@opendap.org>
00009 //
00010 // This library is free software; you can redistribute it and/or
00011 // modify it under the terms of the GNU Lesser General Public
00012 // License as published by the Free Software Foundation; either
00013 // version 2.1 of the License, or (at your option) any later version.
00014 //
00015 // This library is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023 //
00024 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
00025 
00026 // (c) COPYRIGHT URI/MIT 1995-1999
00027 // Please read the full copyright statement in the file COPYRIGHT_URI.
00028 //
00029 // Authors:
00030 //      jhrg,jimg       James Gallagher <jgallagher@gso.uri.edu>
00031 
00032 // These functions are utility functions used by the various DAP parsers (the
00033 // DAS, DDS and constraint expression parsers).
00034 // jhrg 9/7/95
00035 
00036 #include "config.h"
00037 
00038 static char rcsid[] not_used =
00039     { "$Id: parser-util.cc 16088 2007-03-28 21:42:19Z jimg $"
00040     };
00041 
00042 #include <stdio.h>
00043 #include <stdlib.h>
00044 #include <assert.h>
00045 #include <math.h>
00046 #include <errno.h>
00047 
00048 #include <iostream>
00049 #include <sstream>
00050 
00051 //  We wrap VC++ 6.x strtod() to account for a short comming
00052 //  in that function in regards to "NaN".
00053 #ifdef WIN32
00054 #include <limits>
00055 double w32strtod(const char *, char **);
00056 #endif
00057 
00058 #include "debug.h"
00059 #include "parser.h"             // defines constants such as ID_MAX
00060 #include "dods-limits.h"
00061 #include "util.h"               // Jose Garcia: for append_long_to_string.
00062 
00063 using std::cerr;
00064 using std::endl;
00065 
00066 // Deprecated, but still used by the HDF4 EOS server code.
00067 void
00068 parse_error(parser_arg * arg, const char *msg, const int line_num,
00069             const char *context)
00070 {
00071     // Jose Garcia
00072     // This assert(s) is (are) only for developing purposes
00073     // For production servers remove it by compiling with NDEBUG
00074     assert(arg);
00075     assert(msg);
00076 
00077     arg->set_status(FALSE);
00078 
00079     string oss = "";
00080 
00081     if (line_num != 0) {
00082         oss += "Error parsing the text on line ";
00083         append_long_to_string(line_num, 10, oss);
00084     }
00085     else {
00086         oss += "Parse error.";
00087     }
00088 
00089     if (context)
00090         oss += (string) " at or near: " + context + (string) "\n" + msg
00091                + (string) "\n";
00092     else
00093         oss += (string) "\n" + msg + (string) "\n";
00094 
00095     arg->set_error(new Error(unknown_error, oss.c_str()));
00096 }
00097 
00098 void
00099 parse_error(const char *msg, const int line_num, const char *context)
00100 {
00101     // Jose Garcia
00102     // This assert(s) is (are) only for developing purposes
00103     // For production servers remove it by compiling with NDEBUG
00104     assert(msg);
00105 
00106     string oss = "";
00107 
00108     if (line_num != 0) {
00109         oss += "Error parsing the text on line ";
00110         append_long_to_string(line_num, 10, oss);
00111     }
00112     else {
00113         oss += "Parse error.";
00114     }
00115 
00116     if (context)
00117         oss += (string) " at or near: " + context + (string) "\n" + msg
00118                + (string) "\n";
00119     else
00120         oss += (string) "\n" + msg + (string) "\n";
00121 
00122     throw Error(oss);
00123 }
00124 
00125 // context comes from the parser and will always be a char * unless the
00126 // parsers change dramatically.
00127 void
00128 parse_error(const string & msg, const int line_num, const char *context)
00129 {
00130     parse_error(msg.c_str(), line_num, context);
00131 }
00132 
00133 void save_str(char *dst, const char *src, const int line_num)
00134 {
00135     if (strlen(src) >= ID_MAX)
00136         parse_error(string("The word `") + string(src)
00137                     + string("' is too long (it should be no longer than ")
00138                     + long_to_string(ID_MAX) + string(")."), line_num);
00139 
00140     strncpy(dst, src, ID_MAX);
00141     dst[ID_MAX - 1] = '\0';     /* in case ... */
00142 }
00143 
00144 void save_str(string & dst, const char *src, const int)
00145 {
00146     dst = src;
00147 }
00148 
00149 bool is_keyword(string id, const string & keyword)
00150 {
00151     downcase(id);
00152     id = prune_spaces(id);
00153     DBG(cerr << "is_keyword: " << keyword << " = " << id << endl);
00154     return id == keyword;
00155 }
00156 
00157 int check_byte(const char *val)
00158 {
00159     char *ptr;
00160     long v = strtol(val, &ptr, 0);
00161 
00162     if ((v == 0 && val == ptr) || *ptr != '\0') {
00163         return FALSE;
00164     }
00165 
00166     DBG(cerr << "v: " << v << endl);
00167 
00168     // We're very liberal here with values. Anything that can fit into 8 bits
00169     // is allowed through. Clients will have to deal with the fact that the
00170     // ASCII representation for the value might need to be tweaked. This is
00171     // especially the case for Java clients where Byte datatypes are
00172     // signed. 3/20/2000 jhrg
00173     if ((v < 0 && v < DODS_SCHAR_MIN)
00174         || v > 0 && static_cast < unsigned long >(v) > DODS_UCHAR_MAX)
00175         return FALSE;
00176 
00177     return TRUE;
00178 }
00179 
00180 // This version of check_int will pass base 8, 10 and 16 numbers when they
00181 // use the ANSI standard for string representation of those number bases.
00182 
00183 int check_int16(const char *val)
00184 {
00185     char *ptr;
00186     long v = strtol(val, &ptr, 0);      // `0' --> use val to determine base
00187 
00188     if ((v == 0 && val == ptr) || *ptr != '\0') {
00189         return FALSE;
00190     }
00191     // Don't use the constant from limits.h, use the ones in dods-limits.h
00192     if (v > DODS_SHRT_MAX || v < DODS_SHRT_MIN) {
00193         return FALSE;
00194     }
00195 
00196     return TRUE;
00197 }
00198 
00199 int check_uint16(const char *val)
00200 {
00201     char *ptr;
00202     unsigned long v = strtol(val, &ptr, 0);
00203 
00204     if ((v == 0 && val == ptr) || *ptr != '\0') {
00205         return FALSE;
00206     }
00207 
00208     if (v > DODS_USHRT_MAX) {
00209         return FALSE;
00210     }
00211 
00212     return TRUE;
00213 }
00214 
00215 int check_int32(const char *val)
00216 {
00217     char *ptr;
00218     long v = strtol(val, &ptr, 0);      // `0' --> use val to determine base
00219 
00220     if ((v == 0 && val == ptr) || *ptr != '\0') {
00221         return FALSE;
00222     }
00223 
00224     if (v > DODS_INT_MAX || v < DODS_INT_MIN) {
00225         return FALSE;
00226     }
00227 
00228     return TRUE;
00229 }
00230 
00231 int check_uint32(const char *val)
00232 {
00233     char *ptr;
00234     unsigned long v = strtol(val, &ptr, 0);
00235 
00236     if ((v == 0 && val == ptr) || *ptr != '\0') {
00237         return FALSE;
00238     }
00239 
00240     return TRUE;
00241 }
00242 
00243 // Check first for system errors (like numbers so small they convert
00244 // (erroneously) to zero. Then make sure that the value is within
00245 // limits.
00246 
00247 int check_float32(const char *val)
00248 {
00249     char *ptr;
00250     errno = 0;                  // Clear previous value. Fix for the 64bit
00251     // IRIX from Rob Morris. 5/21/2001 jhrg
00252 
00253 #ifdef WIN32
00254     double v = w32strtod(val, &ptr);
00255 #else
00256     double v = strtod(val, &ptr);
00257 #endif
00258 
00259     DBG(cerr << "v: " << v << ", ptr: " << ptr
00260         << ", errno: " << errno << ", val==ptr: " << (val == ptr) << endl);
00261     if ((v == 0.0 && (val == ptr || errno == HUGE_VAL || errno == ERANGE))
00262         || *ptr != '\0') {
00263         return FALSE;
00264     }
00265 
00266     DBG(cerr << "fabs(" << val << ") = " << fabs(v) << endl);
00267     double abs_val = fabs(v);
00268     if (abs_val > DODS_FLT_MAX
00269         || (abs_val != 0.0 && abs_val < DODS_FLT_MIN))
00270         return FALSE;
00271 
00272     return TRUE;
00273 }
00274 
00275 int check_float64(const char *val)
00276 {
00277     DBG(cerr << "val: " << val << endl);
00278     char *ptr;
00279     errno = 0;                  // Clear previous value. 5/21/2001 jhrg
00280 
00281 #ifdef WIN32
00282     double v = w32strtod(val, &ptr);
00283 #else
00284     double v = strtod(val, &ptr);
00285 #endif
00286 
00287     DBG(cerr << "v: " << v << ", ptr: " << ptr
00288         << ", errno: " << errno << ", val==ptr: " << (val == ptr) << endl);
00289 
00290     if ((v == 0.0 && (val == ptr || errno == HUGE_VAL || errno == ERANGE))
00291         || *ptr != '\0') {
00292         return FALSE;
00293     }
00294 
00295     DBG(cerr << "fabs(" << val << ") = " << fabs(v) << endl);
00296     double abs_val = fabs(v);
00297     if (abs_val > DODS_DBL_MAX
00298         || (abs_val != 0.0 && abs_val < DODS_DBL_MIN))
00299         return FALSE;
00300 
00301     return TRUE;
00302 }
00303 
00304 #ifdef WIN32
00305 //  VC++ 6.x strtod() doesn't recognize "NaN".  Account for it
00306 //  by wrapping it around a check for the Nan string.  Use of
00307 //  the product is obsolete as of 1/2007, but it is unknown if
00308 //  the issue is still there in later releases of that product.
00309 //  ROM - 01/2007
00310 double w32strtod(const char *val, char **ptr)
00311 {
00312     //  Convert the two char arrays to compare to strings.
00313     string *sval = new string(val);
00314     string *snan = new string("NaN");
00315 
00316     //  If val doesn't contain "NaN|Nan|nan|etc", use strtod as
00317     //  provided.
00318     if (stricmp(sval->c_str(), snan->c_str()) != 0)
00319         return (strtod(val, ptr));
00320 
00321     //  But if it does, return the bit pattern for Nan and point
00322     //  the parsing ptr arg at the trailing '\0'.
00323     *ptr = (char *) val + strlen(val);
00324     return (std::numeric_limits < double >::quiet_NaN());
00325 }
00326 #endif
00327 
00328 /*
00329   Maybe someday we will really check the Urls to see if they are valid...
00330 */
00331 
00332 int check_url(const char *)
00333 {
00334     return TRUE;
00335 }

Generated on Wed Jun 27 12:56:39 2007 for libdap++ by  doxygen 1.4.7