inifile.cc revision 178
110612SMarco.Elver@ARM.com/* 210612SMarco.Elver@ARM.com * Copyright (c) 2003 The Regents of The University of Michigan 310612SMarco.Elver@ARM.com * All rights reserved. 410612SMarco.Elver@ARM.com * 510612SMarco.Elver@ARM.com * Redistribution and use in source and binary forms, with or without 610612SMarco.Elver@ARM.com * modification, are permitted provided that the following conditions are 710612SMarco.Elver@ARM.com * met: redistributions of source code must retain the above copyright 810612SMarco.Elver@ARM.com * notice, this list of conditions and the following disclaimer; 910612SMarco.Elver@ARM.com * redistributions in binary form must reproduce the above copyright 1010612SMarco.Elver@ARM.com * notice, this list of conditions and the following disclaimer in the 1110612SMarco.Elver@ARM.com * documentation and/or other materials provided with the distribution; 1210612SMarco.Elver@ARM.com * neither the name of the copyright holders nor the names of its 1310612SMarco.Elver@ARM.com * contributors may be used to endorse or promote products derived from 1410612SMarco.Elver@ARM.com * this software without specific prior written permission. 1510612SMarco.Elver@ARM.com * 1610612SMarco.Elver@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1710612SMarco.Elver@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1810612SMarco.Elver@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1910612SMarco.Elver@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2010612SMarco.Elver@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2110612SMarco.Elver@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2210612SMarco.Elver@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2310612SMarco.Elver@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2410612SMarco.Elver@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2510612SMarco.Elver@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2610612SMarco.Elver@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2710612SMarco.Elver@ARM.com */ 2810612SMarco.Elver@ARM.com 2910612SMarco.Elver@ARM.com#define USE_CPP 3010612SMarco.Elver@ARM.com// #define CPP_PIPE 3110612SMarco.Elver@ARM.com 3210612SMarco.Elver@ARM.com 3310612SMarco.Elver@ARM.com#ifdef USE_CPP 3410612SMarco.Elver@ARM.com#include <sys/signal.h> 3510612SMarco.Elver@ARM.com#include <sys/types.h> 3610612SMarco.Elver@ARM.com#include <sys/wait.h> 3710612SMarco.Elver@ARM.com 3810612SMarco.Elver@ARM.com#include <stdio.h> 3910612SMarco.Elver@ARM.com#include <stdlib.h> 4010612SMarco.Elver@ARM.com#include <unistd.h> 4110612SMarco.Elver@ARM.com#endif 4211793Sbrandon.potter@amd.com 4311793Sbrandon.potter@amd.com#include <fstream> 4410612SMarco.Elver@ARM.com#include <iostream> 4510612SMarco.Elver@ARM.com#if __GNUC__ >= 3 4613449Sgabeblack@google.com#include <ext/stdio_filebuf.h> 4710612SMarco.Elver@ARM.com#endif 4810612SMarco.Elver@ARM.com 4910612SMarco.Elver@ARM.com#include <vector> 5010612SMarco.Elver@ARM.com#include <string> 5110612SMarco.Elver@ARM.com 5213892Sgabeblack@google.com#include "base/inifile.hh" 5310612SMarco.Elver@ARM.com#include "base/str.hh" 5410612SMarco.Elver@ARM.com 5510612SMarco.Elver@ARM.comusing namespace std; 5610612SMarco.Elver@ARM.com 5710612SMarco.Elver@ARM.comIniFile::IniFile() 5810612SMarco.Elver@ARM.com{} 5910612SMarco.Elver@ARM.com 6010612SMarco.Elver@ARM.comIniFile::~IniFile() 6110612SMarco.Elver@ARM.com{ 6210612SMarco.Elver@ARM.com SectionTable::iterator i = table.begin(); 6310612SMarco.Elver@ARM.com SectionTable::iterator end = table.end(); 6410612SMarco.Elver@ARM.com 6510612SMarco.Elver@ARM.com while (i != end) { 6610612SMarco.Elver@ARM.com delete (*i).second; 6710612SMarco.Elver@ARM.com ++i; 6810612SMarco.Elver@ARM.com } 6910612SMarco.Elver@ARM.com} 7010612SMarco.Elver@ARM.com 7110612SMarco.Elver@ARM.com 7210612SMarco.Elver@ARM.com#ifdef USE_CPP 7310612SMarco.Elver@ARM.combool 7410612SMarco.Elver@ARM.comIniFile::loadCPP(const string &file, vector<char *> &cppArgs) 7510612SMarco.Elver@ARM.com{ 7613784Sgabeblack@google.com int fd[2]; 7713784Sgabeblack@google.com 7810612SMarco.Elver@ARM.com // Open the file just to verify that we can. Otherwise if the 7910612SMarco.Elver@ARM.com // file doesn't exist or has bad permissions the user will get 8010612SMarco.Elver@ARM.com // confusing errors from cpp/g++. 8113784Sgabeblack@google.com ifstream tmpf(file.c_str()); 8210612SMarco.Elver@ARM.com 8310612SMarco.Elver@ARM.com if (!tmpf.is_open()) 8413892Sgabeblack@google.com return false; 8510612SMarco.Elver@ARM.com 8610612SMarco.Elver@ARM.com tmpf.close(); 8710612SMarco.Elver@ARM.com 8810612SMarco.Elver@ARM.com#ifdef CPP_PIPE 8910612SMarco.Elver@ARM.com if (pipe(fd) == -1) 9010612SMarco.Elver@ARM.com return false; 9110612SMarco.Elver@ARM.com#else 9210612SMarco.Elver@ARM.com char tempfile[] = "/tmp/configXXXXXX"; 9310612SMarco.Elver@ARM.com fd[0] = fd[1] = mkstemp(tempfile); 9410612SMarco.Elver@ARM.com#endif 9510612SMarco.Elver@ARM.com 9610612SMarco.Elver@ARM.com int pid = fork(); 9710612SMarco.Elver@ARM.com 9810612SMarco.Elver@ARM.com if (pid == -1) 9910612SMarco.Elver@ARM.com return 1; 10010612SMarco.Elver@ARM.com 10110612SMarco.Elver@ARM.com if (pid == 0) { 10210612SMarco.Elver@ARM.com char filename[FILENAME_MAX]; 10310612SMarco.Elver@ARM.com string::size_type i = file.copy(filename, sizeof(filename) - 1); 10410612SMarco.Elver@ARM.com filename[i] = '\0'; 10510612SMarco.Elver@ARM.com 10610612SMarco.Elver@ARM.com int arg_count = cppArgs.size(); 10710612SMarco.Elver@ARM.com 10810612SMarco.Elver@ARM.com char **args = new char *[arg_count + 20]; 10910612SMarco.Elver@ARM.com 11010612SMarco.Elver@ARM.com int nextArg = 0; 11110612SMarco.Elver@ARM.com args[nextArg++] = "g++"; 11210612SMarco.Elver@ARM.com args[nextArg++] = "-E"; 11310612SMarco.Elver@ARM.com args[nextArg++] = "-P"; 11410612SMarco.Elver@ARM.com args[nextArg++] = "-nostdinc"; 11510612SMarco.Elver@ARM.com args[nextArg++] = "-nostdinc++"; 11610612SMarco.Elver@ARM.com args[nextArg++] = "-x"; 11710612SMarco.Elver@ARM.com args[nextArg++] = "c++"; 11810612SMarco.Elver@ARM.com args[nextArg++] = "-undef"; 11910612SMarco.Elver@ARM.com 12010612SMarco.Elver@ARM.com for (int i = 0; i < arg_count; i++) 12110612SMarco.Elver@ARM.com args[nextArg++] = cppArgs[i]; 12210612SMarco.Elver@ARM.com 12310612SMarco.Elver@ARM.com args[nextArg++] = filename; 12410612SMarco.Elver@ARM.com args[nextArg++] = NULL; 12513449Sgabeblack@google.com 12610612SMarco.Elver@ARM.com close(STDOUT_FILENO); 12710612SMarco.Elver@ARM.com if (dup2(fd[1], STDOUT_FILENO) == -1) 12810612SMarco.Elver@ARM.com return 1; 12910612SMarco.Elver@ARM.com 13010612SMarco.Elver@ARM.com execvp("g++", args); 13113449Sgabeblack@google.com 13210612SMarco.Elver@ARM.com exit(1); 13310612SMarco.Elver@ARM.com } 13410612SMarco.Elver@ARM.com 13510612SMarco.Elver@ARM.com int retval; 13610612SMarco.Elver@ARM.com waitpid(pid, &retval, 0); 13710612SMarco.Elver@ARM.com 13810612SMarco.Elver@ARM.com // check for normal completion of CPP 13910612SMarco.Elver@ARM.com if (!WIFEXITED(retval) || WEXITSTATUS(retval) != 0) 14010612SMarco.Elver@ARM.com return false; 14110612SMarco.Elver@ARM.com 14210612SMarco.Elver@ARM.com#ifdef CPP_PIPE 14310612SMarco.Elver@ARM.com close(fd[1]); 14410612SMarco.Elver@ARM.com#else 14510612SMarco.Elver@ARM.com lseek(fd[0], 0, SEEK_SET); 14610612SMarco.Elver@ARM.com#endif 14710612SMarco.Elver@ARM.com 14810612SMarco.Elver@ARM.com bool status = false; 14911284Sandreas.hansson@arm.com 15011489Sandreas.hansson@arm.com#if __GNUC__ >= 3 15110612SMarco.Elver@ARM.com using namespace __gnu_cxx; 15210612SMarco.Elver@ARM.com stdio_filebuf<char> fbuf(fd[0], ios_base::in, true, 15310612SMarco.Elver@ARM.com static_cast<stdio_filebuf<char>::int_type>(BUFSIZ)); 15410612SMarco.Elver@ARM.com 15510612SMarco.Elver@ARM.com if (fbuf.is_open()) { 15610612SMarco.Elver@ARM.com istream f(&fbuf); 15710612SMarco.Elver@ARM.com status = load(f); 15813377Sodanrc@yahoo.com.br } 15910612SMarco.Elver@ARM.com 16010612SMarco.Elver@ARM.com#else 16110612SMarco.Elver@ARM.com ifstream f(fd[0]); 16210612SMarco.Elver@ARM.com if (f.is_open()) 16311284Sandreas.hansson@arm.com status = load(f); 16410612SMarco.Elver@ARM.com#endif 16510612SMarco.Elver@ARM.com 16610612SMarco.Elver@ARM.com#ifndef CPP_PIPE 16710612SMarco.Elver@ARM.com unlink(tempfile); 16810612SMarco.Elver@ARM.com#endif 16910612SMarco.Elver@ARM.com 17011284Sandreas.hansson@arm.com return status; 17110612SMarco.Elver@ARM.com} 17210612SMarco.Elver@ARM.com#endif 17310612SMarco.Elver@ARM.com 17410612SMarco.Elver@ARM.combool 17510612SMarco.Elver@ARM.comIniFile::load(const string &file) 17610612SMarco.Elver@ARM.com{ 17710612SMarco.Elver@ARM.com ifstream f(file.c_str()); 17810612SMarco.Elver@ARM.com 17910612SMarco.Elver@ARM.com if (!f.is_open()) 18010612SMarco.Elver@ARM.com return false; 18110612SMarco.Elver@ARM.com 18210612SMarco.Elver@ARM.com return load(f); 18310612SMarco.Elver@ARM.com} 18410612SMarco.Elver@ARM.com 18510612SMarco.Elver@ARM.com 18610612SMarco.Elver@ARM.comconst string & 18710612SMarco.Elver@ARM.comIniFile::Entry::getValue() const 18810612SMarco.Elver@ARM.com{ 18910612SMarco.Elver@ARM.com referenced = true; 19010612SMarco.Elver@ARM.com return value; 19110612SMarco.Elver@ARM.com} 19210612SMarco.Elver@ARM.com 19310612SMarco.Elver@ARM.com 19410612SMarco.Elver@ARM.comvoid 19510612SMarco.Elver@ARM.comIniFile::Section::addEntry(const std::string &entryName, 19610612SMarco.Elver@ARM.com const std::string &value, 19710612SMarco.Elver@ARM.com bool append) 19810612SMarco.Elver@ARM.com{ 19910612SMarco.Elver@ARM.com EntryTable::iterator ei = table.find(entryName); 20010612SMarco.Elver@ARM.com 20110612SMarco.Elver@ARM.com if (ei == table.end()) { 20210612SMarco.Elver@ARM.com // new entry 20310612SMarco.Elver@ARM.com table[entryName] = new Entry(value); 20410612SMarco.Elver@ARM.com } 20510612SMarco.Elver@ARM.com else if (append) { 20610612SMarco.Elver@ARM.com // append new reult to old entry 20710612SMarco.Elver@ARM.com ei->second->appendValue(value); 20810612SMarco.Elver@ARM.com } 20910612SMarco.Elver@ARM.com else { 21010612SMarco.Elver@ARM.com // override old entry 21110612SMarco.Elver@ARM.com ei->second->setValue(value); 21210612SMarco.Elver@ARM.com } 21310612SMarco.Elver@ARM.com} 21410612SMarco.Elver@ARM.com 21510612SMarco.Elver@ARM.com 21610612SMarco.Elver@ARM.combool 21710612SMarco.Elver@ARM.comIniFile::Section::add(const std::string &assignment) 21810612SMarco.Elver@ARM.com{ 21911284Sandreas.hansson@arm.com string::size_type offset = assignment.find('='); 22011284Sandreas.hansson@arm.com if (offset == string::npos) { 22110612SMarco.Elver@ARM.com // no '=' found 22210612SMarco.Elver@ARM.com cerr << "Can't parse .ini line " << assignment << endl; 22310612SMarco.Elver@ARM.com return false; 22410612SMarco.Elver@ARM.com } 22510612SMarco.Elver@ARM.com 22610612SMarco.Elver@ARM.com // if "+=" rather than just "=" then append value 22710612SMarco.Elver@ARM.com bool append = (assignment[offset-1] == '+'); 22810612SMarco.Elver@ARM.com 22910612SMarco.Elver@ARM.com string entryName = assignment.substr(0, append ? offset-1 : offset); 23010612SMarco.Elver@ARM.com string value = assignment.substr(offset + 1); 23110612SMarco.Elver@ARM.com 23210612SMarco.Elver@ARM.com eat_white(entryName); 23310612SMarco.Elver@ARM.com eat_white(value); 23410612SMarco.Elver@ARM.com 23510612SMarco.Elver@ARM.com addEntry(entryName, value, append); 23610612SMarco.Elver@ARM.com return true; 23710612SMarco.Elver@ARM.com} 23810612SMarco.Elver@ARM.com 23911489Sandreas.hansson@arm.com 24010612SMarco.Elver@ARM.comIniFile::Entry * 24110612SMarco.Elver@ARM.comIniFile::Section::findEntry(const std::string &entryName) const 24210612SMarco.Elver@ARM.com{ 24310612SMarco.Elver@ARM.com referenced = true; 24410612SMarco.Elver@ARM.com 24510612SMarco.Elver@ARM.com EntryTable::const_iterator ei = table.find(entryName); 24610612SMarco.Elver@ARM.com 24713377Sodanrc@yahoo.com.br return (ei == table.end()) ? NULL : ei->second; 24810612SMarco.Elver@ARM.com} 24910612SMarco.Elver@ARM.com 25010612SMarco.Elver@ARM.com 25110612SMarco.Elver@ARM.comIniFile::Section * 25210612SMarco.Elver@ARM.comIniFile::addSection(const string §ionName) 25310612SMarco.Elver@ARM.com{ 25410612SMarco.Elver@ARM.com SectionTable::iterator i = table.find(sectionName); 25510612SMarco.Elver@ARM.com 25610612SMarco.Elver@ARM.com if (i != table.end()) { 25710612SMarco.Elver@ARM.com return i->second; 25810612SMarco.Elver@ARM.com } 25910612SMarco.Elver@ARM.com else { 26010612SMarco.Elver@ARM.com // new entry 26110612SMarco.Elver@ARM.com Section *sec = new Section(); 26210612SMarco.Elver@ARM.com table[sectionName] = sec; 26310612SMarco.Elver@ARM.com return sec; 26410612SMarco.Elver@ARM.com } 26510612SMarco.Elver@ARM.com} 26610612SMarco.Elver@ARM.com 26710612SMarco.Elver@ARM.com 26810612SMarco.Elver@ARM.comIniFile::Section * 26910612SMarco.Elver@ARM.comIniFile::findSection(const string §ionName) const 27010612SMarco.Elver@ARM.com{ 27110612SMarco.Elver@ARM.com SectionTable::const_iterator i = table.find(sectionName); 27210612SMarco.Elver@ARM.com 27310612SMarco.Elver@ARM.com return (i == table.end()) ? NULL : i->second; 27410612SMarco.Elver@ARM.com} 27510612SMarco.Elver@ARM.com 27610612SMarco.Elver@ARM.com 27710612SMarco.Elver@ARM.com// Take string of the form "<section>:<parameter>=<value>" and add to 27810612SMarco.Elver@ARM.com// database. Return true if successful, false if parse error. 27910612SMarco.Elver@ARM.combool 28010612SMarco.Elver@ARM.comIniFile::add(const string &str) 28110612SMarco.Elver@ARM.com{ 28210612SMarco.Elver@ARM.com // find ':' 28310612SMarco.Elver@ARM.com string::size_type offset = str.find(':'); 28410612SMarco.Elver@ARM.com if (offset == string::npos) // no ':' found 28510612SMarco.Elver@ARM.com return false; 28610612SMarco.Elver@ARM.com 28710612SMarco.Elver@ARM.com string sectionName = str.substr(0, offset); 28810612SMarco.Elver@ARM.com string rest = str.substr(offset + 1); 28910612SMarco.Elver@ARM.com 29010612SMarco.Elver@ARM.com eat_white(sectionName); 29110612SMarco.Elver@ARM.com Section *s = addSection(sectionName); 29210612SMarco.Elver@ARM.com 29310612SMarco.Elver@ARM.com return s->add(rest); 29410612SMarco.Elver@ARM.com} 29510612SMarco.Elver@ARM.com 29610612SMarco.Elver@ARM.combool 29710612SMarco.Elver@ARM.comIniFile::load(istream &f) 29810612SMarco.Elver@ARM.com{ 29910612SMarco.Elver@ARM.com Section *section = NULL; 30010612SMarco.Elver@ARM.com 30110612SMarco.Elver@ARM.com while (!f.eof()) { 30210612SMarco.Elver@ARM.com f >> ws; // Eat whitespace 30310612SMarco.Elver@ARM.com if (f.eof()) { 30410612SMarco.Elver@ARM.com break; 30510612SMarco.Elver@ARM.com } 30610612SMarco.Elver@ARM.com 30710612SMarco.Elver@ARM.com string line; 30810612SMarco.Elver@ARM.com getline(f, line); 30910612SMarco.Elver@ARM.com if (line.size() == 0) 31010612SMarco.Elver@ARM.com continue; 31110612SMarco.Elver@ARM.com 31210612SMarco.Elver@ARM.com eat_end_white(line); 31310612SMarco.Elver@ARM.com int last = line.size() - 1; 31410612SMarco.Elver@ARM.com 31510612SMarco.Elver@ARM.com if (line[0] == '[' && line[last] == ']') { 31610612SMarco.Elver@ARM.com string sectionName = line.substr(1, last - 1); 31710612SMarco.Elver@ARM.com eat_white(sectionName); 31810612SMarco.Elver@ARM.com section = addSection(sectionName); 31910612SMarco.Elver@ARM.com continue; 32010612SMarco.Elver@ARM.com } 32110612SMarco.Elver@ARM.com 32210612SMarco.Elver@ARM.com if (section == NULL) 32310612SMarco.Elver@ARM.com continue; 32410612SMarco.Elver@ARM.com 32510612SMarco.Elver@ARM.com if (!section->add(line)) 32610612SMarco.Elver@ARM.com return false; 32710612SMarco.Elver@ARM.com } 32810612SMarco.Elver@ARM.com 32910612SMarco.Elver@ARM.com return true; 33010612SMarco.Elver@ARM.com} 33110612SMarco.Elver@ARM.com 33210612SMarco.Elver@ARM.combool 33310612SMarco.Elver@ARM.comIniFile::find(const string §ionName, const string &entryName, 33410612SMarco.Elver@ARM.com string &value) const 33510612SMarco.Elver@ARM.com{ 33610612SMarco.Elver@ARM.com Section *section = findSection(sectionName); 33710612SMarco.Elver@ARM.com if (section == NULL) 33810612SMarco.Elver@ARM.com return false; 33910612SMarco.Elver@ARM.com 34010612SMarco.Elver@ARM.com Entry *entry = section->findEntry(entryName); 34110612SMarco.Elver@ARM.com if (entry == NULL) 34210612SMarco.Elver@ARM.com return false; 34310612SMarco.Elver@ARM.com 34410612SMarco.Elver@ARM.com value = entry->getValue(); 34510612SMarco.Elver@ARM.com 34610612SMarco.Elver@ARM.com return true; 34710612SMarco.Elver@ARM.com} 34810612SMarco.Elver@ARM.com 34910713Sandreas.hansson@arm.combool 35010612SMarco.Elver@ARM.comIniFile::findDefault(const string &_section, const string &entry, 35110713Sandreas.hansson@arm.com string &value) const 35210612SMarco.Elver@ARM.com{ 35310612SMarco.Elver@ARM.com string section = _section; 35410612SMarco.Elver@ARM.com while (!find(section, entry, value)) { 35510713Sandreas.hansson@arm.com if (!find(section, "default", section)) 35610612SMarco.Elver@ARM.com return false; 35710713Sandreas.hansson@arm.com } 35810612SMarco.Elver@ARM.com 35910612SMarco.Elver@ARM.com return true; 36010612SMarco.Elver@ARM.com} 36110612SMarco.Elver@ARM.com 36210612SMarco.Elver@ARM.com 36310612SMarco.Elver@ARM.combool 36410612SMarco.Elver@ARM.comIniFile::Section::printUnreferenced(const string §ionName) 365{ 366 bool unref = false; 367 bool search_unref_entries = false; 368 vector<string> unref_ok_entries; 369 370 Entry *entry = findEntry("unref_entries_ok"); 371 if (entry != NULL) { 372 tokenize(unref_ok_entries, entry->getValue(), ' '); 373 if (unref_ok_entries.size()) { 374 search_unref_entries = true; 375 } 376 } 377 378 for (EntryTable::iterator ei = table.begin(); 379 ei != table.end(); ++ei) { 380 const string &entryName = ei->first; 381 Entry *entry = ei->second; 382 383 if (entryName == "unref_section_ok" || 384 entryName == "unref_entries_ok") 385 { 386 continue; 387 } 388 389 if (!entry->isReferenced()) { 390 if (search_unref_entries && 391 (std::find(unref_ok_entries.begin(), unref_ok_entries.end(), 392 entryName) != unref_ok_entries.end())) 393 { 394 continue; 395 } 396 397 cerr << "Parameter " << sectionName << ":" << entryName 398 << " not referenced." << endl; 399 unref = true; 400 } 401 } 402 403 return unref; 404} 405 406 407bool 408IniFile::printUnreferenced() 409{ 410 bool unref = false; 411 412 for (SectionTable::iterator i = table.begin(); 413 i != table.end(); ++i) { 414 const string §ionName = i->first; 415 Section *section = i->second; 416 417 if (!section->isReferenced()) { 418 if (section->findEntry("unref_section_ok") == NULL) { 419 cerr << "Section " << sectionName << " not referenced." 420 << endl; 421 unref = true; 422 } 423 } 424 else { 425 if (section->printUnreferenced(sectionName)) { 426 unref = true; 427 } 428 } 429 } 430 431 return unref; 432} 433 434 435void 436IniFile::Section::dump(const string §ionName) 437{ 438 for (EntryTable::iterator ei = table.begin(); 439 ei != table.end(); ++ei) { 440 cout << sectionName << ": " << (*ei).first << " => " 441 << (*ei).second->getValue() << "\n"; 442 } 443} 444 445void 446IniFile::dump() 447{ 448 for (SectionTable::iterator i = table.begin(); 449 i != table.end(); ++i) { 450 i->second->dump(i->first); 451 } 452} 453