summaryrefslogtreecommitdiff
path: root/linkers/rld-config.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linkers/rld-config.cpp')
-rw-r--r--linkers/rld-config.cpp211
1 files changed, 211 insertions, 0 deletions
diff --git a/linkers/rld-config.cpp b/linkers/rld-config.cpp
new file mode 100644
index 0000000..ee619c8
--- /dev/null
+++ b/linkers/rld-config.cpp
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2014, Chris Johns <chrisj@rtems.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rld
+ *
+ * @brief INI Configuration reader.
+ *
+ */
+
+#include <errno.h>
+
+#include <rld-config.h>
+
+#include <SimpleIni.h>
+
+namespace rld
+{
+ namespace config
+ {
+ item::item (const std::string& text)
+ : text (text)
+ {
+ }
+
+ item::item (const char* text)
+ : text (text)
+ {
+ }
+
+ const record&
+ section::get_record (const std::string& name) const
+ {
+ for (records::const_iterator ri = recs.begin ();
+ ri != recs.end ();
+ ++ri)
+ {
+ if ((*ri).name == name)
+ return *ri;
+ }
+
+ throw error ("not found", "config record: " + this->name + '/' + name);
+ }
+
+ std::string
+ section::get_record_item (const std::string& rec_name) const
+ {
+ const record& rec = get_record (rec_name);
+ if (rec.items_.size () != 1)
+ throw rld::error ("duplicate", "record item: " + name + '/' + rec_name);
+ return rec.items_[0].text;
+ }
+
+ void
+ section::get_record_items (const std::string& rec_name, rld::strings& items) const
+ {
+ const record& rec = get_record (rec_name);
+ items.clear ();
+ for (rld::config::items::const_iterator ii = rec.items_.begin ();
+ ii != rec.items_.end ();
+ ++ii)
+ {
+ items.push_back ((*ii).text);
+ }
+ }
+
+ config::config()
+ {
+ }
+
+ config::~config()
+ {
+ }
+
+ void
+ config::clear ()
+ {
+ secs.clear ();
+ }
+
+ void
+ config::load (const std::string& path)
+ {
+ CSimpleIniCaseA ini (false, true, true);
+
+ if (ini.LoadFile (path.c_str ()) != SI_OK)
+ throw rld::error (::strerror (errno), "load config: " + path);
+
+ paths_.push_back (path);
+
+ /*
+ * Merge the loaded configuration into our configuration.
+ */
+
+ CSimpleIniCaseA::TNamesDepend skeys;
+
+ ini.GetAllSections(skeys);
+
+ for (CSimpleIniCaseA::TNamesDepend::const_iterator si = skeys.begin ();
+ si != skeys.end ();
+ ++si)
+ {
+ section sec;
+
+ sec.name = (*si).pItem;
+
+ CSimpleIniCaseA::TNamesDepend rkeys;
+
+ ini.GetAllKeys((*si).pItem, rkeys);
+
+ for (CSimpleIniCaseA::TNamesDepend::const_iterator ri = rkeys.begin ();
+ ri != rkeys.end ();
+ ++ri)
+ {
+ record rec;
+
+ rec.name = (*ri).pItem;
+
+ CSimpleIniCaseA::TNamesDepend vals;
+
+ ini.GetAllValues((*si).pItem, (*ri).pItem, vals);
+
+ for (CSimpleIniCaseA::TNamesDepend::const_iterator vi = vals.begin ();
+ vi != vals.end ();
+ ++vi)
+ {
+ rec.items_.push_back (item ((*vi).pItem));
+ }
+
+ sec.recs.push_back (rec);
+ }
+
+ secs.push_back (sec);
+ }
+ }
+
+
+ void
+ config::includes (const section& sec, bool must_exist)
+ {
+ bool have_includes = false;
+
+ try
+ {
+ rld::strings is;
+ parse_items (sec, "include", is);
+
+ have_includes = true;
+
+ /*
+ * Include records are a path which we can just load.
+ *
+ * @todo Add a search path. See 'rld::files' for details. We can default
+ * the search path to the install $prefix of this tool and we can
+ * then provide a default set of function signatures for RTEMS
+ * APIs.
+ */
+
+ for (rld::strings::const_iterator isi = is.begin ();
+ isi != is.end ();
+ ++isi)
+ {
+ load (*isi);
+ }
+ }
+ catch (rld::error re)
+ {
+ /*
+ * No include records, must be all inlined. If we have includes it must
+ * be another error so throw it.
+ */
+ if (have_includes || (!have_includes && must_exist))
+ throw;
+ }
+ }
+
+ const section&
+ config::get_section (const std::string& name) const
+ {
+ for (sections::const_iterator si = secs.begin ();
+ si != secs.end ();
+ ++si)
+ {
+ if ((*si).name == name)
+ return *si;
+ }
+
+ throw error ("not found", "config section: " + name);
+ }
+
+ const paths&
+ config::get_paths () const
+ {
+ return paths_;
+ }
+ }
+}