inifile.cc (5202:ff56fa8c2091) | inifile.cc (5544:65b27e939646) |
---|---|
1/* 2 * Copyright (c) 2001-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Nathan Binkert 29 * Steve Reinhardt 30 */ 31 | 1/* 2 * Copyright (c) 2001-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Nathan Binkert 29 * Steve Reinhardt 30 */ 31 |
32#define USE_CPP 33 34#ifdef USE_CPP 35#include <sys/signal.h> 36#include <sys/types.h> 37#include <sys/wait.h> 38 39#include <libgen.h> 40#include <stdio.h> 41#include <stdlib.h> 42#include <unistd.h> 43#endif 44 | |
45#include <fstream> 46#include <iostream> | 32#include <fstream> 33#include <iostream> |
47 | |
48#include <vector> 49#include <string> 50 51#include "base/inifile.hh" 52#include "base/str.hh" 53 54using namespace std; 55 56IniFile::IniFile() 57{} 58 59IniFile::~IniFile() 60{ 61 SectionTable::iterator i = table.begin(); 62 SectionTable::iterator end = table.end(); 63 64 while (i != end) { 65 delete (*i).second; 66 ++i; 67 } 68} 69 | 34#include <vector> 35#include <string> 36 37#include "base/inifile.hh" 38#include "base/str.hh" 39 40using namespace std; 41 42IniFile::IniFile() 43{} 44 45IniFile::~IniFile() 46{ 47 SectionTable::iterator i = table.begin(); 48 SectionTable::iterator end = table.end(); 49 50 while (i != end) { 51 delete (*i).second; 52 ++i; 53 } 54} 55 |
70 71#ifdef USE_CPP | |
72bool | 56bool |
73IniFile::loadCPP(const string &file, vector<char *> &cppArgs) 74{ 75 // Open the file just to verify that we can. Otherwise if the 76 // file doesn't exist or has bad permissions the user will get 77 // confusing errors from cpp/g++. 78 ifstream tmpf(file.c_str()); 79 80 if (!tmpf.is_open()) 81 return false; 82 83 tmpf.close(); 84 85 char *cfile = strncpy(new char[file.size() + 1], file.c_str(), 86 file.size()); 87 char *dir = dirname(cfile); 88 char *dir_arg = NULL; 89 if (*dir != '.') { 90 string arg = "-I"; 91 arg += dir; 92 93 dir_arg = new char[arg.size() + 1]; 94 strncpy(dir_arg, arg.c_str(), arg.size()); 95 } 96 97 delete [] cfile; 98 99 char tempfile[] = "/tmp/configXXXXXX"; 100 int tmp_fd = mkstemp(tempfile); 101 102 int pid = fork(); 103 104 if (pid == -1) 105 return false; 106 107 if (pid == 0) { 108 char filename[FILENAME_MAX]; 109 string::size_type i = file.copy(filename, sizeof(filename) - 1); 110 filename[i] = '\0'; 111 112 int arg_count = cppArgs.size(); 113 114 const char **args = new const char *[arg_count + 20]; 115 116 int nextArg = 0; 117 args[nextArg++] = "g++"; 118 args[nextArg++] = "-E"; 119 args[nextArg++] = "-P"; 120 args[nextArg++] = "-nostdinc"; 121 args[nextArg++] = "-nostdinc++"; 122 args[nextArg++] = "-x"; 123 args[nextArg++] = "c++"; 124 args[nextArg++] = "-undef"; 125 126 for (int i = 0; i < arg_count; i++) 127 args[nextArg++] = cppArgs[i]; 128 129 if (dir_arg) 130 args[nextArg++] = dir_arg; 131 132 args[nextArg++] = filename; 133 args[nextArg++] = NULL; 134 135 close(STDOUT_FILENO); 136 if (dup2(tmp_fd, STDOUT_FILENO) == -1) 137 exit(1); 138 139 // execvp signature is intentionally broken wrt const-ness for 140 // backwards compatibility... see man page 141 execvp("g++", const_cast<char * const *>(args)); 142 143 exit(0); 144 } 145 146 int retval; 147 waitpid(pid, &retval, 0); 148 149 delete [] dir_arg; 150 151 // check for normal completion of CPP 152 if (!WIFEXITED(retval) || WEXITSTATUS(retval) != 0) 153 return false; 154 155 close(tmp_fd); 156 157 bool status = false; 158 159 status = load(tempfile); 160 161 unlink(tempfile); 162 163 return status; 164} 165#endif 166 167bool | |
168IniFile::load(const string &file) 169{ 170 ifstream f(file.c_str()); 171 172 if (!f.is_open()) 173 return false; 174 175 return load(f); 176} 177 178 179const string & 180IniFile::Entry::getValue() const 181{ 182 referenced = true; 183 return value; 184} 185 186 187void 188IniFile::Section::addEntry(const std::string &entryName, 189 const std::string &value, 190 bool append) 191{ 192 EntryTable::iterator ei = table.find(entryName); 193 194 if (ei == table.end()) { 195 // new entry 196 table[entryName] = new Entry(value); 197 } 198 else if (append) { 199 // append new reult to old entry 200 ei->second->appendValue(value); 201 } 202 else { 203 // override old entry 204 ei->second->setValue(value); 205 } 206} 207 208 209bool 210IniFile::Section::add(const std::string &assignment) 211{ 212 string::size_type offset = assignment.find('='); 213 if (offset == string::npos) { 214 // no '=' found 215 cerr << "Can't parse .ini line " << assignment << endl; 216 return false; 217 } 218 219 // if "+=" rather than just "=" then append value 220 bool append = (assignment[offset-1] == '+'); 221 222 string entryName = assignment.substr(0, append ? offset-1 : offset); 223 string value = assignment.substr(offset + 1); 224 225 eat_white(entryName); 226 eat_white(value); 227 228 addEntry(entryName, value, append); 229 return true; 230} 231 232 233IniFile::Entry * 234IniFile::Section::findEntry(const std::string &entryName) const 235{ 236 referenced = true; 237 238 EntryTable::const_iterator ei = table.find(entryName); 239 240 return (ei == table.end()) ? NULL : ei->second; 241} 242 243 244IniFile::Section * 245IniFile::addSection(const string §ionName) 246{ 247 SectionTable::iterator i = table.find(sectionName); 248 249 if (i != table.end()) { 250 return i->second; 251 } 252 else { 253 // new entry 254 Section *sec = new Section(); 255 table[sectionName] = sec; 256 return sec; 257 } 258} 259 260 261IniFile::Section * 262IniFile::findSection(const string §ionName) const 263{ 264 SectionTable::const_iterator i = table.find(sectionName); 265 266 return (i == table.end()) ? NULL : i->second; 267} 268 269 270// Take string of the form "<section>:<parameter>=<value>" and add to 271// database. Return true if successful, false if parse error. 272bool 273IniFile::add(const string &str) 274{ 275 // find ':' 276 string::size_type offset = str.find(':'); 277 if (offset == string::npos) // no ':' found 278 return false; 279 280 string sectionName = str.substr(0, offset); 281 string rest = str.substr(offset + 1); 282 283 eat_white(sectionName); 284 Section *s = addSection(sectionName); 285 286 return s->add(rest); 287} 288 289bool 290IniFile::load(istream &f) 291{ 292 Section *section = NULL; 293 294 while (!f.eof()) { 295 f >> ws; // Eat whitespace 296 if (f.eof()) { 297 break; 298 } 299 300 string line; 301 getline(f, line); 302 if (line.size() == 0) 303 continue; 304 305 eat_end_white(line); 306 int last = line.size() - 1; 307 308 if (line[0] == '[' && line[last] == ']') { 309 string sectionName = line.substr(1, last - 1); 310 eat_white(sectionName); 311 section = addSection(sectionName); 312 continue; 313 } 314 315 if (section == NULL) 316 continue; 317 318 if (!section->add(line)) 319 return false; 320 } 321 322 return true; 323} 324 325bool 326IniFile::find(const string §ionName, const string &entryName, 327 string &value) const 328{ 329 Section *section = findSection(sectionName); 330 if (section == NULL) 331 return false; 332 333 Entry *entry = section->findEntry(entryName); 334 if (entry == NULL) 335 return false; 336 337 value = entry->getValue(); 338 339 return true; 340} 341 342bool 343IniFile::sectionExists(const string §ionName) const 344{ 345 return findSection(sectionName) != NULL; 346} 347 348 349bool 350IniFile::Section::printUnreferenced(const string §ionName) 351{ 352 bool unref = false; 353 bool search_unref_entries = false; 354 vector<string> unref_ok_entries; 355 356 Entry *entry = findEntry("unref_entries_ok"); 357 if (entry != NULL) { 358 tokenize(unref_ok_entries, entry->getValue(), ' '); 359 if (unref_ok_entries.size()) { 360 search_unref_entries = true; 361 } 362 } 363 364 for (EntryTable::iterator ei = table.begin(); 365 ei != table.end(); ++ei) { 366 const string &entryName = ei->first; 367 Entry *entry = ei->second; 368 369 if (entryName == "unref_section_ok" || 370 entryName == "unref_entries_ok") 371 { 372 continue; 373 } 374 375 if (!entry->isReferenced()) { 376 if (search_unref_entries && 377 (std::find(unref_ok_entries.begin(), unref_ok_entries.end(), 378 entryName) != unref_ok_entries.end())) 379 { 380 continue; 381 } 382 383 cerr << "Parameter " << sectionName << ":" << entryName 384 << " not referenced." << endl; 385 unref = true; 386 } 387 } 388 389 return unref; 390} 391 392 393bool 394IniFile::printUnreferenced() 395{ 396 bool unref = false; 397 398 for (SectionTable::iterator i = table.begin(); 399 i != table.end(); ++i) { 400 const string §ionName = i->first; 401 Section *section = i->second; 402 403 if (!section->isReferenced()) { 404 if (section->findEntry("unref_section_ok") == NULL) { 405 cerr << "Section " << sectionName << " not referenced." 406 << endl; 407 unref = true; 408 } 409 } 410 else { 411 if (section->printUnreferenced(sectionName)) { 412 unref = true; 413 } 414 } 415 } 416 417 return unref; 418} 419 420 421void 422IniFile::Section::dump(const string §ionName) 423{ 424 for (EntryTable::iterator ei = table.begin(); 425 ei != table.end(); ++ei) { 426 cout << sectionName << ": " << (*ei).first << " => " 427 << (*ei).second->getValue() << "\n"; 428 } 429} 430 431void 432IniFile::dump() 433{ 434 for (SectionTable::iterator i = table.begin(); 435 i != table.end(); ++i) { 436 i->second->dump(i->first); 437 } 438} | 57IniFile::load(const string &file) 58{ 59 ifstream f(file.c_str()); 60 61 if (!f.is_open()) 62 return false; 63 64 return load(f); 65} 66 67 68const string & 69IniFile::Entry::getValue() const 70{ 71 referenced = true; 72 return value; 73} 74 75 76void 77IniFile::Section::addEntry(const std::string &entryName, 78 const std::string &value, 79 bool append) 80{ 81 EntryTable::iterator ei = table.find(entryName); 82 83 if (ei == table.end()) { 84 // new entry 85 table[entryName] = new Entry(value); 86 } 87 else if (append) { 88 // append new reult to old entry 89 ei->second->appendValue(value); 90 } 91 else { 92 // override old entry 93 ei->second->setValue(value); 94 } 95} 96 97 98bool 99IniFile::Section::add(const std::string &assignment) 100{ 101 string::size_type offset = assignment.find('='); 102 if (offset == string::npos) { 103 // no '=' found 104 cerr << "Can't parse .ini line " << assignment << endl; 105 return false; 106 } 107 108 // if "+=" rather than just "=" then append value 109 bool append = (assignment[offset-1] == '+'); 110 111 string entryName = assignment.substr(0, append ? offset-1 : offset); 112 string value = assignment.substr(offset + 1); 113 114 eat_white(entryName); 115 eat_white(value); 116 117 addEntry(entryName, value, append); 118 return true; 119} 120 121 122IniFile::Entry * 123IniFile::Section::findEntry(const std::string &entryName) const 124{ 125 referenced = true; 126 127 EntryTable::const_iterator ei = table.find(entryName); 128 129 return (ei == table.end()) ? NULL : ei->second; 130} 131 132 133IniFile::Section * 134IniFile::addSection(const string §ionName) 135{ 136 SectionTable::iterator i = table.find(sectionName); 137 138 if (i != table.end()) { 139 return i->second; 140 } 141 else { 142 // new entry 143 Section *sec = new Section(); 144 table[sectionName] = sec; 145 return sec; 146 } 147} 148 149 150IniFile::Section * 151IniFile::findSection(const string §ionName) const 152{ 153 SectionTable::const_iterator i = table.find(sectionName); 154 155 return (i == table.end()) ? NULL : i->second; 156} 157 158 159// Take string of the form "<section>:<parameter>=<value>" and add to 160// database. Return true if successful, false if parse error. 161bool 162IniFile::add(const string &str) 163{ 164 // find ':' 165 string::size_type offset = str.find(':'); 166 if (offset == string::npos) // no ':' found 167 return false; 168 169 string sectionName = str.substr(0, offset); 170 string rest = str.substr(offset + 1); 171 172 eat_white(sectionName); 173 Section *s = addSection(sectionName); 174 175 return s->add(rest); 176} 177 178bool 179IniFile::load(istream &f) 180{ 181 Section *section = NULL; 182 183 while (!f.eof()) { 184 f >> ws; // Eat whitespace 185 if (f.eof()) { 186 break; 187 } 188 189 string line; 190 getline(f, line); 191 if (line.size() == 0) 192 continue; 193 194 eat_end_white(line); 195 int last = line.size() - 1; 196 197 if (line[0] == '[' && line[last] == ']') { 198 string sectionName = line.substr(1, last - 1); 199 eat_white(sectionName); 200 section = addSection(sectionName); 201 continue; 202 } 203 204 if (section == NULL) 205 continue; 206 207 if (!section->add(line)) 208 return false; 209 } 210 211 return true; 212} 213 214bool 215IniFile::find(const string §ionName, const string &entryName, 216 string &value) const 217{ 218 Section *section = findSection(sectionName); 219 if (section == NULL) 220 return false; 221 222 Entry *entry = section->findEntry(entryName); 223 if (entry == NULL) 224 return false; 225 226 value = entry->getValue(); 227 228 return true; 229} 230 231bool 232IniFile::sectionExists(const string §ionName) const 233{ 234 return findSection(sectionName) != NULL; 235} 236 237 238bool 239IniFile::Section::printUnreferenced(const string §ionName) 240{ 241 bool unref = false; 242 bool search_unref_entries = false; 243 vector<string> unref_ok_entries; 244 245 Entry *entry = findEntry("unref_entries_ok"); 246 if (entry != NULL) { 247 tokenize(unref_ok_entries, entry->getValue(), ' '); 248 if (unref_ok_entries.size()) { 249 search_unref_entries = true; 250 } 251 } 252 253 for (EntryTable::iterator ei = table.begin(); 254 ei != table.end(); ++ei) { 255 const string &entryName = ei->first; 256 Entry *entry = ei->second; 257 258 if (entryName == "unref_section_ok" || 259 entryName == "unref_entries_ok") 260 { 261 continue; 262 } 263 264 if (!entry->isReferenced()) { 265 if (search_unref_entries && 266 (std::find(unref_ok_entries.begin(), unref_ok_entries.end(), 267 entryName) != unref_ok_entries.end())) 268 { 269 continue; 270 } 271 272 cerr << "Parameter " << sectionName << ":" << entryName 273 << " not referenced." << endl; 274 unref = true; 275 } 276 } 277 278 return unref; 279} 280 281 282bool 283IniFile::printUnreferenced() 284{ 285 bool unref = false; 286 287 for (SectionTable::iterator i = table.begin(); 288 i != table.end(); ++i) { 289 const string §ionName = i->first; 290 Section *section = i->second; 291 292 if (!section->isReferenced()) { 293 if (section->findEntry("unref_section_ok") == NULL) { 294 cerr << "Section " << sectionName << " not referenced." 295 << endl; 296 unref = true; 297 } 298 } 299 else { 300 if (section->printUnreferenced(sectionName)) { 301 unref = true; 302 } 303 } 304 } 305 306 return unref; 307} 308 309 310void 311IniFile::Section::dump(const string §ionName) 312{ 313 for (EntryTable::iterator ei = table.begin(); 314 ei != table.end(); ++ei) { 315 cout << sectionName << ": " << (*ei).first << " => " 316 << (*ei).second->getValue() << "\n"; 317 } 318} 319 320void 321IniFile::dump() 322{ 323 for (SectionTable::iterator i = table.begin(); 324 i != table.end(); ++i) { 325 i->second->dump(i->first); 326 } 327} |