| 1 | // | 
|---|
| 2 | // keyvalipv2.cc | 
|---|
| 3 | // | 
|---|
| 4 | // Copyright (C) 1996 Limit Point Systems, Inc. | 
|---|
| 5 | // | 
|---|
| 6 | // Author: Curtis Janssen <cljanss@limitpt.com> | 
|---|
| 7 | // Maintainer: LPS | 
|---|
| 8 | // | 
|---|
| 9 | // This file is part of the SC Toolkit. | 
|---|
| 10 | // | 
|---|
| 11 | // The SC Toolkit is free software; you can redistribute it and/or modify | 
|---|
| 12 | // it under the terms of the GNU Library General Public License as published by | 
|---|
| 13 | // the Free Software Foundation; either version 2, or (at your option) | 
|---|
| 14 | // any later version. | 
|---|
| 15 | // | 
|---|
| 16 | // The SC Toolkit is distributed in the hope that it will be useful, | 
|---|
| 17 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
| 18 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|---|
| 19 | // GNU Library General Public License for more details. | 
|---|
| 20 | // | 
|---|
| 21 | // You should have received a copy of the GNU Library General Public License | 
|---|
| 22 | // along with the SC Toolkit; see the file COPYING.LIB.  If not, write to | 
|---|
| 23 | // the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | 
|---|
| 24 | // | 
|---|
| 25 | // The U.S. Government is granted a limited license as per AL 91-7. | 
|---|
| 26 | // | 
|---|
| 27 |  | 
|---|
| 28 | #include <scconfig.h> | 
|---|
| 29 | #include <iostream> | 
|---|
| 30 | #ifdef HAVE_SSTREAM | 
|---|
| 31 | #  include <sstream> | 
|---|
| 32 | #else | 
|---|
| 33 | #  include <strstream.h> | 
|---|
| 34 | #endif | 
|---|
| 35 | #include <fstream> | 
|---|
| 36 | #include <stdlib.h> | 
|---|
| 37 | #include <string.h> | 
|---|
| 38 | #include <sys/stat.h> | 
|---|
| 39 |  | 
|---|
| 40 | #include <util/misc/string.h> | 
|---|
| 41 | #include <util/misc/formio.h> | 
|---|
| 42 | #include <util/keyval/ipv2.h> | 
|---|
| 43 | #include <util/keyval/keyval.h> | 
|---|
| 44 |  | 
|---|
| 45 | using namespace std; | 
|---|
| 46 | using namespace sc; | 
|---|
| 47 |  | 
|---|
| 48 | ParsedKeyVal::ParsedKeyVal(IPV2*i): | 
|---|
| 49 | nfile(0), | 
|---|
| 50 | file(0), | 
|---|
| 51 | nfp(0) | 
|---|
| 52 | { | 
|---|
| 53 | ipv2 = i; | 
|---|
| 54 | } | 
|---|
| 55 |  | 
|---|
| 56 | ParsedKeyVal::ParsedKeyVal(): | 
|---|
| 57 | nfile(0), | 
|---|
| 58 | file(0), | 
|---|
| 59 | nfp(0) | 
|---|
| 60 | { | 
|---|
| 61 | ipv2 = new IPV2; | 
|---|
| 62 | } | 
|---|
| 63 |  | 
|---|
| 64 | ParsedKeyVal::ParsedKeyVal(const char* name): | 
|---|
| 65 | nfile(0), | 
|---|
| 66 | file(0), | 
|---|
| 67 | nfp(0) | 
|---|
| 68 | { | 
|---|
| 69 | ipv2 = new IPV2; | 
|---|
| 70 | read(name); | 
|---|
| 71 | } | 
|---|
| 72 |  | 
|---|
| 73 | ParsedKeyVal::ParsedKeyVal(istream& fp): | 
|---|
| 74 | nfile(0), | 
|---|
| 75 | file(0), | 
|---|
| 76 | nfp(0) | 
|---|
| 77 | { | 
|---|
| 78 | ipv2 = new IPV2; | 
|---|
| 79 | read(fp); | 
|---|
| 80 | } | 
|---|
| 81 |  | 
|---|
| 82 | ParsedKeyVal::ParsedKeyVal(const char* keyprefix, const Ref<KeyVal>& keyval): | 
|---|
| 83 | nfile(0), | 
|---|
| 84 | file(0), | 
|---|
| 85 | nfp(0) | 
|---|
| 86 | { | 
|---|
| 87 | ipv2 = new IPV2; | 
|---|
| 88 |  | 
|---|
| 89 | char* filespec = new char[strlen(keyprefix)+6]; | 
|---|
| 90 | strcpy(filespec,keyprefix); | 
|---|
| 91 | strcat(filespec,"files"); | 
|---|
| 92 |  | 
|---|
| 93 | char* dirspec = new char[strlen(keyprefix)+6]; | 
|---|
| 94 | strcpy(dirspec,keyprefix); | 
|---|
| 95 | strcat(dirspec,"dir"); | 
|---|
| 96 |  | 
|---|
| 97 | char* directory = keyval->pcharvalue(dirspec); | 
|---|
| 98 | if (!directory) { | 
|---|
| 99 | directory = getenv("SCLIBDIR"); | 
|---|
| 100 | if (directory) { | 
|---|
| 101 | char *tmp = strchr(directory,'='); | 
|---|
| 102 | if (!tmp) tmp = directory; | 
|---|
| 103 | else tmp = &tmp[1]; | 
|---|
| 104 |  | 
|---|
| 105 | directory = strcpy(new char[strlen(tmp)+1], tmp); | 
|---|
| 106 | } | 
|---|
| 107 | else { | 
|---|
| 108 | struct stat sb; | 
|---|
| 109 | const char *dir = INSTALLED_SCLIBDIR; | 
|---|
| 110 | #ifdef SRC_SCLIBDIR | 
|---|
| 111 | if (stat(dir, &sb) != 0) { | 
|---|
| 112 | ExEnv::out0() << indent << "WARNING: could not find " | 
|---|
| 113 | << dir << endl; | 
|---|
| 114 | dir = SRC_SCLIBDIR; | 
|---|
| 115 | } | 
|---|
| 116 | #endif | 
|---|
| 117 | directory = strcpy(new char[strlen(dir)+1], dir); | 
|---|
| 118 | } | 
|---|
| 119 | } | 
|---|
| 120 |  | 
|---|
| 121 | int nfiles = keyval->count(filespec); | 
|---|
| 122 | for (int i=0; i<nfiles; i++) { | 
|---|
| 123 | char* filename = keyval->pcharvalue(filespec,i); | 
|---|
| 124 | char* fullname; | 
|---|
| 125 | if (directory) { | 
|---|
| 126 | fullname = new char[strlen(directory)+strlen(filename)+1]; | 
|---|
| 127 | strcpy(fullname,directory); | 
|---|
| 128 | strcat(fullname,filename); | 
|---|
| 129 | } | 
|---|
| 130 | else { | 
|---|
| 131 | fullname = filename; | 
|---|
| 132 | } | 
|---|
| 133 | read(fullname); | 
|---|
| 134 | if (directory) { | 
|---|
| 135 | delete[] filename; | 
|---|
| 136 | } | 
|---|
| 137 | delete[] fullname; | 
|---|
| 138 | } | 
|---|
| 139 |  | 
|---|
| 140 | if (directory) delete[] directory; | 
|---|
| 141 |  | 
|---|
| 142 | delete[] dirspec; | 
|---|
| 143 | delete[] filespec; | 
|---|
| 144 |  | 
|---|
| 145 | } | 
|---|
| 146 |  | 
|---|
| 147 | void | 
|---|
| 148 | ParsedKeyVal::cat_files(const char* keyprefix, const Ref<KeyVal>& keyval, | 
|---|
| 149 | ostream &ostr) | 
|---|
| 150 | { | 
|---|
| 151 | char* filespec = new char[strlen(keyprefix)+6]; | 
|---|
| 152 | strcpy(filespec,keyprefix); | 
|---|
| 153 | strcat(filespec,"files"); | 
|---|
| 154 |  | 
|---|
| 155 | char* dirspec = new char[strlen(keyprefix)+6]; | 
|---|
| 156 | strcpy(dirspec,keyprefix); | 
|---|
| 157 | strcat(dirspec,"dir"); | 
|---|
| 158 |  | 
|---|
| 159 | char* directory = keyval->pcharvalue(dirspec); | 
|---|
| 160 | if (!directory) { | 
|---|
| 161 | directory = getenv("SCLIBDIR"); | 
|---|
| 162 | if (directory) { | 
|---|
| 163 | char *tmp = strchr(directory,'='); | 
|---|
| 164 | if (!tmp) tmp = directory; | 
|---|
| 165 | else tmp = &tmp[1]; | 
|---|
| 166 |  | 
|---|
| 167 | directory = strcpy(new char[strlen(tmp)+1], tmp); | 
|---|
| 168 | } | 
|---|
| 169 | else { | 
|---|
| 170 | struct stat sb; | 
|---|
| 171 | const char *dir = INSTALLED_SCLIBDIR; | 
|---|
| 172 | #ifdef SRC_SCLIBDIR | 
|---|
| 173 | if (stat(dir, &sb) != 0) { | 
|---|
| 174 | ExEnv::out0() << indent << "WARNING: could not find " | 
|---|
| 175 | << dir << endl; | 
|---|
| 176 | dir = SRC_SCLIBDIR; | 
|---|
| 177 | } | 
|---|
| 178 | #endif | 
|---|
| 179 | directory = strcpy(new char[strlen(dir)+1], dir); | 
|---|
| 180 | } | 
|---|
| 181 | } | 
|---|
| 182 |  | 
|---|
| 183 | int nfiles = keyval->count(filespec); | 
|---|
| 184 | for (int i=0; i<nfiles; i++) { | 
|---|
| 185 | char* filename = keyval->pcharvalue(filespec,i); | 
|---|
| 186 | char* fullname; | 
|---|
| 187 | if (directory) { | 
|---|
| 188 | fullname = new char[strlen(directory)+strlen(filename)+1]; | 
|---|
| 189 | strcpy(fullname,directory); | 
|---|
| 190 | strcat(fullname,filename); | 
|---|
| 191 | } | 
|---|
| 192 | else { | 
|---|
| 193 | fullname = filename; | 
|---|
| 194 | } | 
|---|
| 195 | ifstream is(fullname); | 
|---|
| 196 | is >> ostr.rdbuf(); | 
|---|
| 197 | if (directory) { | 
|---|
| 198 | delete[] filename; | 
|---|
| 199 | } | 
|---|
| 200 | delete[] fullname; | 
|---|
| 201 | } | 
|---|
| 202 |  | 
|---|
| 203 | if (directory) delete[] directory; | 
|---|
| 204 |  | 
|---|
| 205 | delete[] dirspec; | 
|---|
| 206 | delete[] filespec; | 
|---|
| 207 |  | 
|---|
| 208 | } | 
|---|
| 209 |  | 
|---|
| 210 | void | 
|---|
| 211 | ParsedKeyVal::read(const char* name) | 
|---|
| 212 | { | 
|---|
| 213 | ifstream infp(name,ios::in); | 
|---|
| 214 | if (infp.bad()) { | 
|---|
| 215 | ExEnv::errn() << "ParsedKeyVal couldn't open " << name << endl; | 
|---|
| 216 | exit(1); | 
|---|
| 217 | } | 
|---|
| 218 |  | 
|---|
| 219 | int i; | 
|---|
| 220 | char**newfile = new char*[nfile+1]; | 
|---|
| 221 | for (i=0; i<nfile; i++) newfile[i] = file[i]; | 
|---|
| 222 | if (file) delete[] file; | 
|---|
| 223 | file = newfile; | 
|---|
| 224 | newfile[nfile] = strdup(name); | 
|---|
| 225 | nfile++; | 
|---|
| 226 |  | 
|---|
| 227 | read(infp); | 
|---|
| 228 | nfp--; // read(infp) will incr nfp, but this isn't desired so undo | 
|---|
| 229 | } | 
|---|
| 230 |  | 
|---|
| 231 | void ParsedKeyVal::read(istream&infp) | 
|---|
| 232 | { | 
|---|
| 233 | nfp++; | 
|---|
| 234 | ipv2->read(infp,ExEnv::errn(),"<stream>"); | 
|---|
| 235 | } | 
|---|
| 236 |  | 
|---|
| 237 | void | 
|---|
| 238 | ParsedKeyVal::parse_string(const char *str) | 
|---|
| 239 | { | 
|---|
| 240 | #ifdef HAVE_SSTREAM | 
|---|
| 241 | istringstream in(str); | 
|---|
| 242 | #else | 
|---|
| 243 | istrstream in(str); | 
|---|
| 244 | #endif | 
|---|
| 245 | ipv2->read(in,ExEnv::errn(),"<string>"); | 
|---|
| 246 | } | 
|---|
| 247 |  | 
|---|
| 248 | ParsedKeyVal::~ParsedKeyVal() | 
|---|
| 249 | { | 
|---|
| 250 | delete ipv2; | 
|---|
| 251 | for (int i=0; i<nfile; i++) free(file[i]); | 
|---|
| 252 | delete[] file; | 
|---|
| 253 | } | 
|---|
| 254 |  | 
|---|
| 255 | static KeyVal::KeyValError maperr(IPV2::Status err) | 
|---|
| 256 | { | 
|---|
| 257 | if (err == IPV2::OK            ) return KeyVal::OK; | 
|---|
| 258 | if (err == IPV2::KeyNotFound ) return KeyVal::UnknownKeyword; | 
|---|
| 259 | if (err == IPV2::OutOfBounds ) return KeyVal::UnknownKeyword; | 
|---|
| 260 | if (err == IPV2::Malloc        ) return KeyVal::OperationFailed; | 
|---|
| 261 | if (err == IPV2::NotAnArray  ) return KeyVal::UnknownKeyword; | 
|---|
| 262 | if (err == IPV2::NotAScalar  ) return KeyVal::HasNoValue; | 
|---|
| 263 | if (err == IPV2::Type          ) return KeyVal::WrongType; | 
|---|
| 264 | if (err == IPV2::HasNoValue  ) return KeyVal::HasNoValue; | 
|---|
| 265 | if (err == IPV2::ValNotExpd  ) return KeyVal::OperationFailed; | 
|---|
| 266 | return KeyVal::OperationFailed; | 
|---|
| 267 | } | 
|---|
| 268 |  | 
|---|
| 269 | const char* ParsedKeyVal::stringrep(const char* key) | 
|---|
| 270 | { | 
|---|
| 271 | const char* result; | 
|---|
| 272 | seterror(maperr(ipv2->value_v((char *)key,&result,0,0))); | 
|---|
| 273 | if (error() != OK) { | 
|---|
| 274 | result = 0; | 
|---|
| 275 | } | 
|---|
| 276 | return result; | 
|---|
| 277 | } | 
|---|
| 278 |  | 
|---|
| 279 | const char* | 
|---|
| 280 | ParsedKeyVal::classname(const char* key) | 
|---|
| 281 | { | 
|---|
| 282 | const char* result; | 
|---|
| 283 | seterror(maperr(ipv2->classname_v((char *)key,&result,0,0))); | 
|---|
| 284 | return result; | 
|---|
| 285 | } | 
|---|
| 286 |  | 
|---|
| 287 | const char* | 
|---|
| 288 | ParsedKeyVal::truekeyword(const char*key) | 
|---|
| 289 | { | 
|---|
| 290 | const char* result; | 
|---|
| 291 | seterror(maperr(ipv2->truekeyword_v((char *)key,&result,0,0))); | 
|---|
| 292 | if (!result && error() == OK) return key; | 
|---|
| 293 | else return result; | 
|---|
| 294 | } | 
|---|
| 295 |  | 
|---|
| 296 | void ParsedKeyVal::errortrace(ostream&fp) | 
|---|
| 297 | { | 
|---|
| 298 | fp << indent << "ParsedKeyVal: error: \"" << errormsg() << "\"" << endl; | 
|---|
| 299 | if (nfp) { | 
|---|
| 300 | fp << indent | 
|---|
| 301 | << "    reading from " << nfp << " files with unknown names" << endl; | 
|---|
| 302 | } | 
|---|
| 303 | for (int i=0; i<nfile; i++) { | 
|---|
| 304 | fp << indent << "    reading from \"" << file[i] << "\"" << endl; | 
|---|
| 305 | } | 
|---|
| 306 | } | 
|---|
| 307 |  | 
|---|
| 308 | void ParsedKeyVal::dump(ostream&fp) | 
|---|
| 309 | { | 
|---|
| 310 | fp << indent << "ParsedKeyVal: error: \"" << errormsg() << "\"" << endl; | 
|---|
| 311 | if (nfp) { | 
|---|
| 312 | fp << indent | 
|---|
| 313 | << "    reading from " << nfp << " files with unknown names" << endl; | 
|---|
| 314 | } | 
|---|
| 315 | for (int i=0; i<nfile; i++) { | 
|---|
| 316 | fp << indent << "    reading from \"" << file[i] << "\"" << endl; | 
|---|
| 317 | } | 
|---|
| 318 | fp << indent << "The IPV2 tree:" << endl; | 
|---|
| 319 | ipv2->print_tree(fp); | 
|---|
| 320 |  | 
|---|
| 321 | } | 
|---|
| 322 |  | 
|---|
| 323 | void ParsedKeyVal::print_unseen(ostream&fp) | 
|---|
| 324 | { | 
|---|
| 325 | ipv2->print_unseen(fp); | 
|---|
| 326 | } | 
|---|
| 327 |  | 
|---|
| 328 | int ParsedKeyVal::have_unseen() | 
|---|
| 329 | { | 
|---|
| 330 | return ipv2->have_unseen(); | 
|---|
| 331 | } | 
|---|
| 332 |  | 
|---|
| 333 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
| 334 |  | 
|---|
| 335 | // Local Variables: | 
|---|
| 336 | // mode: c++ | 
|---|
| 337 | // c-file-style: "CLJ" | 
|---|
| 338 | // End: | 
|---|