inifile.cc revision 10385
15952Ssaidi@eecs.umich.edu/*
25952Ssaidi@eecs.umich.edu * Copyright (c) 2001-2005 The Regents of The University of Michigan
35952Ssaidi@eecs.umich.edu * All rights reserved.
45952Ssaidi@eecs.umich.edu *
55952Ssaidi@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
65952Ssaidi@eecs.umich.edu * modification, are permitted provided that the following conditions are
75952Ssaidi@eecs.umich.edu * met: redistributions of source code must retain the above copyright
85952Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
95952Ssaidi@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
105952Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
115952Ssaidi@eecs.umich.edu * documentation and/or other materials provided with the distribution;
125952Ssaidi@eecs.umich.edu * neither the name of the copyright holders nor the names of its
135952Ssaidi@eecs.umich.edu * contributors may be used to endorse or promote products derived from
145952Ssaidi@eecs.umich.edu * this software without specific prior written permission.
155952Ssaidi@eecs.umich.edu *
165952Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
175952Ssaidi@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
185952Ssaidi@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
195952Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
205952Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
215952Ssaidi@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
225952Ssaidi@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235952Ssaidi@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245952Ssaidi@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255952Ssaidi@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
265952Ssaidi@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275952Ssaidi@eecs.umich.edu *
285952Ssaidi@eecs.umich.edu * Authors: Nathan Binkert
295952Ssaidi@eecs.umich.edu *          Steve Reinhardt
305952Ssaidi@eecs.umich.edu */
315952Ssaidi@eecs.umich.edu
325952Ssaidi@eecs.umich.edu#include <algorithm>
335952Ssaidi@eecs.umich.edu#include <fstream>
345952Ssaidi@eecs.umich.edu#include <iostream>
355952Ssaidi@eecs.umich.edu#include <string>
365952Ssaidi@eecs.umich.edu#include <vector>
375952Ssaidi@eecs.umich.edu
385952Ssaidi@eecs.umich.edu#include "base/inifile.hh"
395952Ssaidi@eecs.umich.edu#include "base/str.hh"
405952Ssaidi@eecs.umich.edu
415952Ssaidi@eecs.umich.eduusing namespace std;
425952Ssaidi@eecs.umich.edu
435952Ssaidi@eecs.umich.eduIniFile::IniFile()
445952Ssaidi@eecs.umich.edu{}
455952Ssaidi@eecs.umich.edu
465952Ssaidi@eecs.umich.eduIniFile::~IniFile()
475952Ssaidi@eecs.umich.edu{
485952Ssaidi@eecs.umich.edu    SectionTable::iterator i = table.begin();
495952Ssaidi@eecs.umich.edu    SectionTable::iterator end = table.end();
505952Ssaidi@eecs.umich.edu
515952Ssaidi@eecs.umich.edu    while (i != end) {
525952Ssaidi@eecs.umich.edu        delete (*i).second;
535952Ssaidi@eecs.umich.edu        ++i;
545952Ssaidi@eecs.umich.edu    }
555952Ssaidi@eecs.umich.edu}
565952Ssaidi@eecs.umich.edu
575952Ssaidi@eecs.umich.edubool
585952Ssaidi@eecs.umich.eduIniFile::load(const string &file)
595952Ssaidi@eecs.umich.edu{
605952Ssaidi@eecs.umich.edu    ifstream f(file.c_str());
615952Ssaidi@eecs.umich.edu
625952Ssaidi@eecs.umich.edu    if (!f.is_open())
635952Ssaidi@eecs.umich.edu        return false;
645952Ssaidi@eecs.umich.edu
655952Ssaidi@eecs.umich.edu    return load(f);
665952Ssaidi@eecs.umich.edu}
675952Ssaidi@eecs.umich.edu
685952Ssaidi@eecs.umich.edu
695952Ssaidi@eecs.umich.educonst string &
705952Ssaidi@eecs.umich.eduIniFile::Entry::getValue() const
715952Ssaidi@eecs.umich.edu{
725952Ssaidi@eecs.umich.edu    referenced = true;
735952Ssaidi@eecs.umich.edu    return value;
745952Ssaidi@eecs.umich.edu}
755952Ssaidi@eecs.umich.edu
765952Ssaidi@eecs.umich.edu
775952Ssaidi@eecs.umich.eduvoid
785952Ssaidi@eecs.umich.eduIniFile::Section::addEntry(const std::string &entryName,
795952Ssaidi@eecs.umich.edu                           const std::string &value,
805952Ssaidi@eecs.umich.edu                           bool append)
815952Ssaidi@eecs.umich.edu{
825952Ssaidi@eecs.umich.edu    EntryTable::iterator ei = table.find(entryName);
835952Ssaidi@eecs.umich.edu
845952Ssaidi@eecs.umich.edu    if (ei == table.end()) {
855952Ssaidi@eecs.umich.edu        // new entry
865952Ssaidi@eecs.umich.edu        table[entryName] = new Entry(value);
875952Ssaidi@eecs.umich.edu    }
885952Ssaidi@eecs.umich.edu    else if (append) {
895952Ssaidi@eecs.umich.edu        // append new reult to old entry
905952Ssaidi@eecs.umich.edu        ei->second->appendValue(value);
915952Ssaidi@eecs.umich.edu    }
925952Ssaidi@eecs.umich.edu    else {
935952Ssaidi@eecs.umich.edu        // override old entry
945952Ssaidi@eecs.umich.edu        ei->second->setValue(value);
955952Ssaidi@eecs.umich.edu    }
965952Ssaidi@eecs.umich.edu}
975952Ssaidi@eecs.umich.edu
985952Ssaidi@eecs.umich.edu
995952Ssaidi@eecs.umich.edubool
1005952Ssaidi@eecs.umich.eduIniFile::Section::add(const std::string &assignment)
1015952Ssaidi@eecs.umich.edu{
1025952Ssaidi@eecs.umich.edu    string::size_type offset = assignment.find('=');
1035952Ssaidi@eecs.umich.edu    if (offset == string::npos) {
1045952Ssaidi@eecs.umich.edu        // no '=' found
1055952Ssaidi@eecs.umich.edu        cerr << "Can't parse .ini line " << assignment << endl;
1065952Ssaidi@eecs.umich.edu        return false;
1075952Ssaidi@eecs.umich.edu    }
1085952Ssaidi@eecs.umich.edu
1095952Ssaidi@eecs.umich.edu    // if "+=" rather than just "=" then append value
1105952Ssaidi@eecs.umich.edu    bool append = (assignment[offset-1] == '+');
1115952Ssaidi@eecs.umich.edu
1125952Ssaidi@eecs.umich.edu    string entryName = assignment.substr(0, append ? offset-1 : offset);
1135952Ssaidi@eecs.umich.edu    string value = assignment.substr(offset + 1);
1145952Ssaidi@eecs.umich.edu
1155952Ssaidi@eecs.umich.edu    eat_white(entryName);
1165952Ssaidi@eecs.umich.edu    eat_white(value);
1175952Ssaidi@eecs.umich.edu
1185952Ssaidi@eecs.umich.edu    addEntry(entryName, value, append);
1195952Ssaidi@eecs.umich.edu    return true;
1205952Ssaidi@eecs.umich.edu}
1215952Ssaidi@eecs.umich.edu
1225952Ssaidi@eecs.umich.edu
1235952Ssaidi@eecs.umich.eduIniFile::Entry *
1245952Ssaidi@eecs.umich.eduIniFile::Section::findEntry(const std::string &entryName) const
1255952Ssaidi@eecs.umich.edu{
1265952Ssaidi@eecs.umich.edu    referenced = true;
1275952Ssaidi@eecs.umich.edu
1285952Ssaidi@eecs.umich.edu    EntryTable::const_iterator ei = table.find(entryName);
1295952Ssaidi@eecs.umich.edu
1305952Ssaidi@eecs.umich.edu    return (ei == table.end()) ? NULL : ei->second;
1315952Ssaidi@eecs.umich.edu}
1325952Ssaidi@eecs.umich.edu
1335952Ssaidi@eecs.umich.edu
1345952Ssaidi@eecs.umich.eduIniFile::Section *
1355952Ssaidi@eecs.umich.eduIniFile::addSection(const string &sectionName)
1365952Ssaidi@eecs.umich.edu{
1375952Ssaidi@eecs.umich.edu    SectionTable::iterator i = table.find(sectionName);
1385952Ssaidi@eecs.umich.edu
1395952Ssaidi@eecs.umich.edu    if (i != table.end()) {
1405952Ssaidi@eecs.umich.edu        return i->second;
1415952Ssaidi@eecs.umich.edu    }
1425952Ssaidi@eecs.umich.edu    else {
1435952Ssaidi@eecs.umich.edu        // new entry
1445952Ssaidi@eecs.umich.edu        Section *sec = new Section();
1455952Ssaidi@eecs.umich.edu        table[sectionName] = sec;
1465952Ssaidi@eecs.umich.edu        return sec;
1475952Ssaidi@eecs.umich.edu    }
1485952Ssaidi@eecs.umich.edu}
1495952Ssaidi@eecs.umich.edu
1505952Ssaidi@eecs.umich.edu
1515952Ssaidi@eecs.umich.eduIniFile::Section *
1525952Ssaidi@eecs.umich.eduIniFile::findSection(const string &sectionName) const
1535952Ssaidi@eecs.umich.edu{
1545952Ssaidi@eecs.umich.edu    SectionTable::const_iterator i = table.find(sectionName);
1555952Ssaidi@eecs.umich.edu
1565952Ssaidi@eecs.umich.edu    return (i == table.end()) ? NULL : i->second;
1575952Ssaidi@eecs.umich.edu}
1585952Ssaidi@eecs.umich.edu
1595952Ssaidi@eecs.umich.edu
1605952Ssaidi@eecs.umich.edu// Take string of the form "<section>:<parameter>=<value>" and add to
1615952Ssaidi@eecs.umich.edu// database.  Return true if successful, false if parse error.
1625952Ssaidi@eecs.umich.edubool
1635952Ssaidi@eecs.umich.eduIniFile::add(const string &str)
1645952Ssaidi@eecs.umich.edu{
1655952Ssaidi@eecs.umich.edu    // find ':'
1665952Ssaidi@eecs.umich.edu    string::size_type offset = str.find(':');
1675952Ssaidi@eecs.umich.edu    if (offset == string::npos)  // no ':' found
1685952Ssaidi@eecs.umich.edu        return false;
1695952Ssaidi@eecs.umich.edu
1705952Ssaidi@eecs.umich.edu    string sectionName = str.substr(0, offset);
1715952Ssaidi@eecs.umich.edu    string rest = str.substr(offset + 1);
1725952Ssaidi@eecs.umich.edu
1735952Ssaidi@eecs.umich.edu    eat_white(sectionName);
1745952Ssaidi@eecs.umich.edu    Section *s = addSection(sectionName);
1755952Ssaidi@eecs.umich.edu
1765952Ssaidi@eecs.umich.edu    return s->add(rest);
1775952Ssaidi@eecs.umich.edu}
1785952Ssaidi@eecs.umich.edu
1795952Ssaidi@eecs.umich.edubool
1805952Ssaidi@eecs.umich.eduIniFile::load(istream &f)
1815952Ssaidi@eecs.umich.edu{
1825952Ssaidi@eecs.umich.edu    Section *section = NULL;
1835952Ssaidi@eecs.umich.edu
1845952Ssaidi@eecs.umich.edu    while (!f.eof()) {
1855952Ssaidi@eecs.umich.edu        f >> ws; // Eat whitespace
1865952Ssaidi@eecs.umich.edu        if (f.eof()) {
1875952Ssaidi@eecs.umich.edu            break;
1885952Ssaidi@eecs.umich.edu        }
1895952Ssaidi@eecs.umich.edu
1905952Ssaidi@eecs.umich.edu        string line;
1915952Ssaidi@eecs.umich.edu        getline(f, line);
1925952Ssaidi@eecs.umich.edu        if (line.size() == 0)
1935952Ssaidi@eecs.umich.edu            continue;
1945952Ssaidi@eecs.umich.edu
1955952Ssaidi@eecs.umich.edu        eat_end_white(line);
1965952Ssaidi@eecs.umich.edu        int last = line.size() - 1;
1975952Ssaidi@eecs.umich.edu
1985952Ssaidi@eecs.umich.edu        if (line[0] == '[' && line[last] == ']') {
1995952Ssaidi@eecs.umich.edu            string sectionName = line.substr(1, last - 1);
2005952Ssaidi@eecs.umich.edu            eat_white(sectionName);
2015952Ssaidi@eecs.umich.edu            section = addSection(sectionName);
2025952Ssaidi@eecs.umich.edu            continue;
2035952Ssaidi@eecs.umich.edu        }
2045952Ssaidi@eecs.umich.edu
2055952Ssaidi@eecs.umich.edu        if (section == NULL)
2065952Ssaidi@eecs.umich.edu            continue;
2075952Ssaidi@eecs.umich.edu
2085952Ssaidi@eecs.umich.edu        if (!section->add(line))
2095952Ssaidi@eecs.umich.edu            return false;
2105952Ssaidi@eecs.umich.edu    }
2115952Ssaidi@eecs.umich.edu
2125952Ssaidi@eecs.umich.edu    return true;
2135952Ssaidi@eecs.umich.edu}
2145952Ssaidi@eecs.umich.edu
2155952Ssaidi@eecs.umich.edubool
2165952Ssaidi@eecs.umich.eduIniFile::find(const string &sectionName, const string &entryName,
2175952Ssaidi@eecs.umich.edu              string &value) const
2185952Ssaidi@eecs.umich.edu{
2195952Ssaidi@eecs.umich.edu    Section *section = findSection(sectionName);
2205952Ssaidi@eecs.umich.edu    if (section == NULL)
2215952Ssaidi@eecs.umich.edu        return false;
2225952Ssaidi@eecs.umich.edu
2235952Ssaidi@eecs.umich.edu    Entry *entry = section->findEntry(entryName);
2245952Ssaidi@eecs.umich.edu    if (entry == NULL)
2255952Ssaidi@eecs.umich.edu        return false;
2265952Ssaidi@eecs.umich.edu
2275952Ssaidi@eecs.umich.edu    value = entry->getValue();
2285952Ssaidi@eecs.umich.edu
2295952Ssaidi@eecs.umich.edu    return true;
2305952Ssaidi@eecs.umich.edu}
2315952Ssaidi@eecs.umich.edu
2325952Ssaidi@eecs.umich.edubool
2335952Ssaidi@eecs.umich.eduIniFile::sectionExists(const string &sectionName) const
2345952Ssaidi@eecs.umich.edu{
2355952Ssaidi@eecs.umich.edu    return findSection(sectionName) != NULL;
2365952Ssaidi@eecs.umich.edu}
2375952Ssaidi@eecs.umich.edu
2385952Ssaidi@eecs.umich.edu
2395952Ssaidi@eecs.umich.edubool
2405952Ssaidi@eecs.umich.eduIniFile::Section::printUnreferenced(const string &sectionName)
2415952Ssaidi@eecs.umich.edu{
2425952Ssaidi@eecs.umich.edu    bool unref = false;
2435952Ssaidi@eecs.umich.edu    bool search_unref_entries = false;
2445952Ssaidi@eecs.umich.edu    vector<string> unref_ok_entries;
2455952Ssaidi@eecs.umich.edu
2465952Ssaidi@eecs.umich.edu    Entry *entry = findEntry("unref_entries_ok");
2475952Ssaidi@eecs.umich.edu    if (entry != NULL) {
2485952Ssaidi@eecs.umich.edu        tokenize(unref_ok_entries, entry->getValue(), ' ');
2495952Ssaidi@eecs.umich.edu        if (unref_ok_entries.size()) {
2505952Ssaidi@eecs.umich.edu            search_unref_entries = true;
2515952Ssaidi@eecs.umich.edu        }
2525952Ssaidi@eecs.umich.edu    }
2535952Ssaidi@eecs.umich.edu
2545952Ssaidi@eecs.umich.edu    for (EntryTable::iterator ei = table.begin();
2555952Ssaidi@eecs.umich.edu         ei != table.end(); ++ei) {
2565952Ssaidi@eecs.umich.edu        const string &entryName = ei->first;
2575952Ssaidi@eecs.umich.edu        entry = ei->second;
2585952Ssaidi@eecs.umich.edu
2595952Ssaidi@eecs.umich.edu        if (entryName == "unref_section_ok" ||
2605952Ssaidi@eecs.umich.edu            entryName == "unref_entries_ok")
2615952Ssaidi@eecs.umich.edu        {
2625952Ssaidi@eecs.umich.edu            continue;
2635952Ssaidi@eecs.umich.edu        }
2645952Ssaidi@eecs.umich.edu
2655952Ssaidi@eecs.umich.edu        if (!entry->isReferenced()) {
2665952Ssaidi@eecs.umich.edu            if (search_unref_entries &&
2675952Ssaidi@eecs.umich.edu                (std::find(unref_ok_entries.begin(), unref_ok_entries.end(),
2685952Ssaidi@eecs.umich.edu                           entryName) != unref_ok_entries.end()))
2695952Ssaidi@eecs.umich.edu            {
2705952Ssaidi@eecs.umich.edu                continue;
2715952Ssaidi@eecs.umich.edu            }
2725952Ssaidi@eecs.umich.edu
2735952Ssaidi@eecs.umich.edu            cerr << "Parameter " << sectionName << ":" << entryName
2745952Ssaidi@eecs.umich.edu                 << " not referenced." << endl;
2755952Ssaidi@eecs.umich.edu            unref = true;
2765952Ssaidi@eecs.umich.edu        }
2775952Ssaidi@eecs.umich.edu    }
2785952Ssaidi@eecs.umich.edu
2795952Ssaidi@eecs.umich.edu    return unref;
2805952Ssaidi@eecs.umich.edu}
2815952Ssaidi@eecs.umich.edu
2825952Ssaidi@eecs.umich.edu
2835952Ssaidi@eecs.umich.eduvoid
2845952Ssaidi@eecs.umich.eduIniFile::getSectionNames(vector<string> &list) const
2855952Ssaidi@eecs.umich.edu{
2865952Ssaidi@eecs.umich.edu    for (SectionTable::const_iterator i = table.begin();
2875952Ssaidi@eecs.umich.edu         i != table.end(); ++i)
2885952Ssaidi@eecs.umich.edu    {
2895952Ssaidi@eecs.umich.edu        list.push_back((*i).first);
2905952Ssaidi@eecs.umich.edu    }
2915952Ssaidi@eecs.umich.edu}
2925952Ssaidi@eecs.umich.edu
2935952Ssaidi@eecs.umich.edubool
2945952Ssaidi@eecs.umich.eduIniFile::printUnreferenced()
2955952Ssaidi@eecs.umich.edu{
2965952Ssaidi@eecs.umich.edu    bool unref = false;
2975952Ssaidi@eecs.umich.edu
2985952Ssaidi@eecs.umich.edu    for (SectionTable::iterator i = table.begin();
2995952Ssaidi@eecs.umich.edu         i != table.end(); ++i) {
3005952Ssaidi@eecs.umich.edu        const string &sectionName = i->first;
3015952Ssaidi@eecs.umich.edu        Section *section = i->second;
3025952Ssaidi@eecs.umich.edu
3035952Ssaidi@eecs.umich.edu        if (!section->isReferenced()) {
3045952Ssaidi@eecs.umich.edu            if (section->findEntry("unref_section_ok") == NULL) {
3055952Ssaidi@eecs.umich.edu                cerr << "Section " << sectionName << " not referenced."
3065952Ssaidi@eecs.umich.edu                     << endl;
3075952Ssaidi@eecs.umich.edu                unref = true;
3085952Ssaidi@eecs.umich.edu            }
3095952Ssaidi@eecs.umich.edu        }
3105952Ssaidi@eecs.umich.edu        else {
3115952Ssaidi@eecs.umich.edu            if (section->printUnreferenced(sectionName)) {
3125952Ssaidi@eecs.umich.edu                unref = true;
3135952Ssaidi@eecs.umich.edu            }
3145952Ssaidi@eecs.umich.edu        }
3155952Ssaidi@eecs.umich.edu    }
3165952Ssaidi@eecs.umich.edu
3175952Ssaidi@eecs.umich.edu    return unref;
3185952Ssaidi@eecs.umich.edu}
3195952Ssaidi@eecs.umich.edu
3205952Ssaidi@eecs.umich.edu
3215952Ssaidi@eecs.umich.eduvoid
3225952Ssaidi@eecs.umich.eduIniFile::Section::dump(const string &sectionName)
3235952Ssaidi@eecs.umich.edu{
3245952Ssaidi@eecs.umich.edu    for (EntryTable::iterator ei = table.begin();
3255952Ssaidi@eecs.umich.edu         ei != table.end(); ++ei) {
3265952Ssaidi@eecs.umich.edu        cout << sectionName << ": " << (*ei).first << " => "
3275952Ssaidi@eecs.umich.edu             << (*ei).second->getValue() << "\n";
3285952Ssaidi@eecs.umich.edu    }
3295952Ssaidi@eecs.umich.edu}
3305952Ssaidi@eecs.umich.edu
3315952Ssaidi@eecs.umich.eduvoid
3325952Ssaidi@eecs.umich.eduIniFile::dump()
3335952Ssaidi@eecs.umich.edu{
3345952Ssaidi@eecs.umich.edu    for (SectionTable::iterator i = table.begin();
3355952Ssaidi@eecs.umich.edu         i != table.end(); ++i) {
3365952Ssaidi@eecs.umich.edu        i->second->dump(i->first);
3375952Ssaidi@eecs.umich.edu    }
3385952Ssaidi@eecs.umich.edu}
3395952Ssaidi@eecs.umich.edu