summaryrefslogtreecommitdiff
path: root/linkers/rtems-tld.cpp
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2014-08-07 18:15:06 +1000
committerChris Johns <chrisj@rtems.org>2014-08-07 18:15:06 +1000
commit097f1fdf569e631f5fae95f27e0ec2a2f626bcbc (patch)
treeaa7833be2ef390df431228e6b3b4143e03306786 /linkers/rtems-tld.cpp
parent4fd758e4f69bb6fca1aee16502d10fdeb80fc79b (diff)
rtms-tld: Refactor the code to match a better configuration format.
Diffstat (limited to 'linkers/rtems-tld.cpp')
-rw-r--r--linkers/rtems-tld.cpp540
1 files changed, 300 insertions, 240 deletions
diff --git a/linkers/rtems-tld.cpp b/linkers/rtems-tld.cpp
index ec8ccb5..d206da7 100644
--- a/linkers/rtems-tld.cpp
+++ b/linkers/rtems-tld.cpp
@@ -70,7 +70,7 @@ namespace rld
/**
* A function's signature.
*/
- struct function_sig
+ struct signature
{
std::string name; /**< The function's name. */
function_args args; /**< The function's list of arguments. */
@@ -79,17 +79,12 @@ namespace rld
/**
* The default constructor.
*/
- function_sig ();
+ signature ();
/**
* Construct the signature loading it from the configuration.
*/
- function_sig (const rld::config::record& record);
-
- /**
- * Copy constructor.
- */
- function_sig (const function_sig& orig);
+ signature (const rld::config::record& record);
/**
* Return the function's declaration.
@@ -98,61 +93,70 @@ namespace rld
};
/**
- * A container of function signatures.
+ * A container of signatures.
*/
- typedef std::map < std::string, function_sig > function_sigs;
+ typedef std::map < std::string, signature > signatures;
/**
- * Wrappers hold the data used when wrapping the code. It knows how to wrap
- * a specific trace function. Wrapping a function requires specific defines
- * and header files.
+ * A function is list of function signatures headers and defines that allow
+ * a function to be wrapped.
*/
- struct wrapper
+ struct function
{
- std::string name; /**< The name of this wrapper. */
- rld::strings headers; /**< Include statements. */
- rld::strings defines; /**< Define statements. */
- std::string map_sym_prefix; /**< Mapping symbol prefix. */
- std::string arg_trace; /**< Code template to trace an argument. */
- std::string ret_trace; /**< Code template to trace the return value. */
- rld::strings& code; /**< Code block inserted before the trace code. */
- function_sigs sigs; /**< The functions this wrapper wraps. */
+ std::string name; /**< The name of this wrapper. */
+ rld::strings headers; /**< Include statements. */
+ rld::strings defines; /**< Define statements. */
+ signatures signatures_; /**< Signatures in this function. */
/**
- * Load the wrapper.
+ * Load the function.
*/
- wrapper (const std::string& name,
- rld::strings& code,
- rld::config::config& config);
+ function (rld::config::config& config,
+ const std::string& name);
/**
- * Parse the generator.
+ * Dump the function.
*/
- void parse_generator (rld::config::config& config,
- const rld::config::section& section);
+ void dump (std::ostream& out) const;
+ };
+
+ /**
+ * A container of functions.
+ */
+ typedef std::vector < function > functions;
+
+ /**
+ * A generator and that contains the functions used to trace arguments and
+ * return values. It also provides the implementation of those functions.
+ */
+ struct generator
+ {
+ std::string name; /**< The name of this wrapper. */
+ rld::strings headers; /**< Include statements. */
+ rld::strings defines; /**< Define statements. */
+ std::string map_sym_prefix; /**< Mapping symbol prefix. */
+ std::string arg_trace; /**< Code template to trace an argument. */
+ std::string ret_trace; /**< Code template to trace the return value. */
+ rld::strings code; /**< Code block inserted before the trace code. */
/**
- * Recursive parser for strings.
+ * Default constructor.
*/
- void parse (rld::config::config& config,
- const rld::config::section& section,
- const std::string& sec_name,
- const std::string& rec_name,
- rld::strings& items,
- int depth = 0);
+ generator ();
/**
- * Dump the wrapper.
+ * Load the generator.
+ */
+ generator (rld::config::config& config,
+ const std::string& name);
+
+ /**
+ * Dump the generator.
*/
void dump (std::ostream& out) const;
};
/**
- * A container of wrappers. The order is the order we wrap.
- */
- typedef std::vector < wrapper > wrappers;
-
- /**
* Tracer.
*/
class tracer
@@ -167,6 +171,18 @@ namespace rld
const std::string& section);
/**
+ * The the functions for the trace.
+ */
+ void load_functions (rld::config::config& config,
+ const rld::config::section& section);
+
+ /**
+ * The the traces for the tracer.
+ */
+ void load_traces (rld::config::config& config,
+ const rld::config::section& section);
+
+ /**
* Generate the wrapper object file.
*/
void generate ();
@@ -183,11 +199,11 @@ namespace rld
private:
- std::string name; /**< The name of the trace. */
- std::string bsp; /**< The BSP we are linking to. */
- rld::strings traces; /**< The functions to trace. */
- wrappers wrappers; /**< Wrappers wrap trace functions. */
- rld::strings code; /**< Wrapper code records. Must be unique. */
+ std::string name; /**< The name of the trace. */
+ std::string bsp; /**< The BSP we are linking to. */
+ rld::strings traces; /**< The functions to trace. */
+ functions functions_; /**< The functions that can be traced. */
+ generator generator_; /**< The tracer's generator. */
};
/**
@@ -217,25 +233,62 @@ namespace rld
private:
rld::config::config config; /**< User configuration. */
- tracer tracer; /**< The tracer */
+ tracer tracer_; /**< The tracer */
};
- function_sig::function_sig ()
+ /**
+ * Recursive parser for strings.
+ */
+ void
+ parse (rld::config::config& config,
+ const rld::config::section& section,
+ const std::string& sec_name,
+ const std::string& rec_name,
+ rld::strings& items,
+ bool split = true,
+ int depth = 0)
+ {
+ if (depth > 32)
+ throw rld::error ("too deep", "parsing: " + sec_name + '/' + rec_name);
+
+ rld::config::parse_items (section, rec_name, items, false, false, split);
+
+ rld::strings sl;
+
+ rld::config::parse_items (section, sec_name, sl);
+
+ for (rld::strings::iterator sli = sl.begin ();
+ sli != sl.end ();
+ ++sli)
+ {
+ const rld::config::section& sec = config.get_section (*sli);
+ parse (config, sec, sec_name, rec_name, items, split, depth + 1);
+ }
+
+ /*
+ * Make the items unique.
+ */
+ rld::strings::iterator ii;
+ ii = std::unique (items.begin (), items.end ());
+ items.resize (std::distance (items.begin (), ii));
+ }
+
+ signature::signature ()
{
}
- function_sig::function_sig (const rld::config::record& record)
+ signature::signature (const rld::config::record& record)
{
/*
* There can only be one function signature in the configuration.
*/
if (!record.single ())
- throw rld::error ("duplicate", "function signature: " + record.name);
+ throw rld::error ("duplicate", "signature: " + record.name);
name = record.name;
/*
- * Function signatures are defined as the return value then the arguments
+ * Signatures are defined as the return value then the arguments
* delimited by a comma and white space. No checking is made of the
* return value or arguments.
*/
@@ -243,24 +296,17 @@ namespace rld
rld::config::parse_items (record, si);
if (si.size () == 0)
- throw rld::error ("no return value", "function signature: " + record.name);
+ throw rld::error ("no return value", "signature: " + record.name);
if (si.size () == 1)
- throw rld::error ("no arguments", "function signature: " + record.name);
+ throw rld::error ("no arguments", "signature: " + record.name);
ret = si[0];
args.resize (si.size () - 1);
std::copy (si.begin () + 1, si.end (), args.begin ());
}
- function_sig::function_sig (const function_sig& orig)
- : name (orig.name),
- args (orig.args),
- ret (orig.ret)
- {
- }
-
const std::string
- function_sig::decl () const
+ signature::decl () const
{
std::string ds = ret + ' ' + name + '(';
int arg = 0;
@@ -276,129 +322,114 @@ namespace rld
return ds;
}
- wrapper::wrapper (const std::string& name,
- rld::strings& code,
- rld::config::config& config)
- : name (name),
- code (code)
+ function::function (rld::config::config& config,
+ const std::string& name)
+ : name (name)
{
/*
- * A wrapper section optionally contain one or more records of:
+ * A function section optionally contain one or more records of:
*
- * # trace A list of functions to trace.
- * # generator The name of the generator section. Defaults if not present.
- * # headers A list of sections containing headers or header records.
- * # header A list of include string that are single or double quoted.
- * # defines A list of sections containing defines or define record.
- * # defines A list of define string that are single or double quoted.
- * # signatures A list of section names of function signatures.
+ * # headers A list of sections containing headers or header records.
+ * # header A list of include string that are single or double quoted.
+ * # defines A list of sections containing defines or define record.
+ * # defines A list of define string that are single or double quoted.
+ * # signatures A list of section names of signatures.
+ * # includes A list of files to include.
*
* @note The quoting and list spliting is a little weak because a delimiter
* in a quote should not be seen as a delimiter.
*/
const rld::config::section& section = config.get_section (name);
+ config.includes (section);
+
parse (config, section, "headers", "header", headers);
parse (config, section, "defines", "define", defines);
- parse_generator (config, section);
-
rld::strings sig_list;
-
- rld::config::parse_items (section, "signatures", sig_list);
+ section.get_record_items ("signatures", sig_list);
for (rld::strings::const_iterator sli = sig_list.begin ();
sli != sig_list.end ();
++sli)
{
const rld::config::section& sig_sec = config.get_section (*sli);
- for (rld::config::records::const_iterator ri = sig_sec.recs.begin ();
- ri != sig_sec.recs.end ();
- ++ri)
+ for (rld::config::records::const_iterator si = sig_sec.recs.begin ();
+ si != sig_sec.recs.end ();
+ ++si)
{
- function_sig func (*ri);
- sigs[func.name] = func;
+ signature sig (*si);
+ signatures_[sig.name] = sig;
}
}
}
void
- wrapper::parse_generator (rld::config::config& config,
- const rld::config::section& section)
+ function::dump (std::ostream& out) const
{
- const rld::config::record* rec = 0;
- try
- {
- const rld::config::record& record = section.get_record ("generator");
- rec = &record;
- }
- catch (rld::error re)
+ out << " Function: " << name << std::endl
+ << " Headers: " << headers.size () << std::endl;
+ for (rld::strings::const_iterator hi = headers.begin ();
+ hi != headers.end ();
+ ++hi)
{
- /*
- * No error, continue.
- */
+ out << " " << (*hi) << std::endl;
}
-
- std::string gen_section;
-
- if (rec)
+ out << " Defines: " << defines.size () << std::endl;
+ for (rld::strings::const_iterator di = defines.begin ();
+ di != defines.end ();
+ ++di)
{
- if (!rec->single ())
- throw rld::error ("duplicate", "generator: " + section.name + "/generator");
- gen_section = rec->items[0].text;
+ out << " " << (*di) << std::endl;
}
- else
+ out << " Signatures: " << signatures_.size () << std::endl;
+ for (signatures::const_iterator si = signatures_.begin ();
+ si != signatures_.end ();
+ ++si)
{
- gen_section = config.get_section ("default-generator").get_record_item ("generator");
+ const signature& sig = (*si).second;
+ out << " " << sig.name << ": " << sig.decl () << ';' << std::endl;
}
-
- const rld::config::section& sec = config.get_section (gen_section);
-
- map_sym_prefix = sec.get_record_item ("map-sym-prefix");
- arg_trace = rld::dequote (sec.get_record_item ("arg-trace"));
- ret_trace = rld::dequote (sec.get_record_item ("ret-trace"));
-
- /*
- * The code block, if present is placed in the code conttainer if unique.
- * If referenced by more than wrapper and duplicated a compiler error
- * will be generated.
- */
- rld::strings::iterator ci;
- code.push_back (rld::dequote (sec.get_record_item ("code")));
- ci = std::unique (code.begin (), code.end ());
- code.resize (std::distance (code.begin (), ci));
}
- void
- wrapper::parse (rld::config::config& config,
- const rld::config::section& section,
- const std::string& sec_name,
- const std::string& rec_name,
- rld::strings& items,
- int depth)
+ generator::generator ()
{
- if (depth > 32)
- throw rld::error ("too deep", "parsing: " + sec_name + '/' + rec_name);
+ }
- rld::config::parse_items (section, rec_name, items);
+ generator::generator (rld::config::config& config,
+ const std::string& name)
+ : name (name)
+ {
+ /*
+ * A generator section optionally contain one or more records of:
+ *
+ * # headers A list of sections containing headers or header records.
+ * # header A list of include string that are single or double quoted.
+ * # defines A list of sections containing defines or define record.
+ * # defines A list of define string that are single or double quoted.
+ * # code-blocks A list of section names of code blocks.
+ * # includes A list of files to include.
+ *
+ * @note The quoting and list spliting is a little weak because a delimiter
+ * in a quote should not be seen as a delimiter.
+ */
+ const rld::config::section& section = config.get_section (name);
- rld::strings sl;
+ config.includes (section);
- rld::config::parse_items (section, sec_name, sl);
+ parse (config, section, "headers", "header", headers);
+ parse (config, section, "defines", "define", defines);
+ parse (config, section, "code-blocks", "code", code, false);
- for (rld::strings::const_iterator sli = sl.begin ();
- sli != sl.end ();
- ++sli)
- {
- const rld::config::section& sec = config.get_section (*sli);
- parse (config, sec, sec_name, rec_name, items, depth + 1);
- }
+ map_sym_prefix = section.get_record_item ("map-sym-prefix");
+ arg_trace = rld::dequote (section.get_record_item ("arg-trace"));
+ ret_trace = rld::dequote (section.get_record_item ("ret-trace"));
}
void
- wrapper::dump (std::ostream& out) const
+ generator::dump (std::ostream& out) const
{
- out << " Wrapper: " << name << std::endl
+ out << " Generator: " << name << std::endl
<< " Headers: " << headers.size () << std::endl;
for (rld::strings::const_iterator hi = headers.begin ();
hi != headers.end ();
@@ -416,13 +447,13 @@ namespace rld
out << " Mapping Symbol Prefix: " << map_sym_prefix << std::endl
<< " Arg Trace Code: " << arg_trace << std::endl
<< " Return Trace Code: " << ret_trace << std::endl
- << " Function Signatures: " << sigs.size () << std::endl;
- for (function_sigs::const_iterator si = sigs.begin ();
- si != sigs.end ();
- ++si)
+ << " Code blocks: " << std::endl;
+ for (rld::strings::const_iterator ci = code.begin ();
+ ci != code.end ();
+ ++ci)
{
- const function_sig& sig = (*si).second;
- out << " " << sig.name << ": " << sig.decl () << ';' << std::endl;
+ out << " > "
+ << rld::find_replace (*ci, "\n", "\n | ") << std::endl;
}
}
@@ -432,70 +463,76 @@ namespace rld
void
tracer::load (rld::config::config& config,
- const std::string& section)
+ const std::string& tname)
{
/*
- * The configuration must contain a "trace" section. This is the top level
- * configuration and must the following fields:
- *
- * # name The name of trace being linked.
- * # trace The list of sections containing functions to trace.
- * # wrapper The list of sections containing wrapping details.
+ * The configuration must contain a "section" section. This is the top level
+ * configuration and may contain:
*
- * The following record are optional:
+ * # name The name of trace being linked.
+ * # bsp The architecture/bsp name of the BSP.
+ * # options A list of options as per the long command line args.
+ * # traces The list of sections containing function lists to trace.
+ * # functions The list of sections containing function details.
+ * # include The list of files to include.
*
- * # bdp The BSP the executable is for. Can be supplied on the command
- * line.
- * # include Include the INI file.
+ * The following records are required:
*
- * The following will throw an error is the section or records are not
- * found.
+ * # name
+ * # bsp
+ * # trace
+ * # functions
*/
- rld::strings ss;
+ const rld::config::section& section = config.get_section (tname);
- const rld::config::section& tsec = config.get_section (section);
- const rld::config::record& nrec = tsec.get_record ("name");
- const rld::config::record& brec = tsec.get_record ("bsp");
- const rld::config::record& trec = tsec.get_record ("trace");
- const rld::config::record& wrec = tsec.get_record ("wrapper");
+ config.includes (section);
- if (!nrec.single ())
- throw rld::error ("duplicate", "trace names");
- name = nrec.items[0].text;
+ name = section.get_record_item ("name");
+ bsp = section.get_record_item ("bsp");
- if (!brec.single ())
- throw rld::error ("duplicate", "trace bsp");
- bsp = brec.items[0].text;
-
- /*
- * Include any files.
- */
- config.includes (tsec);
+ load_functions (config, section);
+ load_traces (config, section);
+ }
- /*
- * Load the wrappers.
- */
- rld::strings wi;
- rld::config::parse_items (wrec, wi);
- for (rld::strings::const_iterator wsi = wi.begin ();
- wsi != wi.end ();
- ++wsi)
+ void
+ tracer::load_functions (rld::config::config& config,
+ const rld::config::section& section)
+ {
+ rld::strings fl;
+ rld::config::parse_items (section, "functions", fl, true);
+ for (rld::strings::const_iterator fli = fl.begin ();
+ fli != fl.end ();
+ ++fli)
{
- wrappers.push_back (wrapper (*wsi, code, config));
+ functions_.push_back (function (config, *fli));
}
+ }
- /*
- * Load the trace functions.
- */
- rld::strings ti;
- rld::config::parse_items (trec, ti);
- for (rld::strings::const_iterator tsi = ti.begin ();
- tsi != ti.end ();
- ++tsi)
+ void
+ tracer::load_traces (rld::config::config& config,
+ const rld::config::section& section)
+ {
+ parse (config, section, "traces", "trace", traces);
+
+ rld::strings gens;
+ std::string gen;
+
+ parse (config, section, "traces", "generator", gens);
+
+ if (gens.size () > 1)
+ throw rld::error ("duplicate generators", "tracer: " + section.name);
+
+ if (gens.size () == 0)
+ {
+ gen =
+ config.get_section ("default-generator").get_record_item ("generator");
+ }
+ else
{
- rld::config::parse_items (config, *tsi, "trace", traces, true);
+ gen = gens[0];
}
+ generator_ = generator (config, gen);
}
void
@@ -515,24 +552,14 @@ namespace rld
c.write_line (" * Automatically generated.");
c.write_line (" */");
- for (wrappers::const_iterator wi = wrappers.begin ();
- wi != wrappers.end ();
- ++wi)
- {
- const wrapper& wrap = *wi;
- c.write_line ("");
- c.write_line ("/*");
- c.write_line (" * Wrapper: " + wrap.name);
- c.write_line (" */");
- c.write_lines (wrap.defines);
- c.write_lines (wrap.headers);
- }
-
c.write_line ("");
c.write_line ("/*");
- c.write_line (" * Code blocks");
+ c.write_line (" * Generator: " + generator_.name);
c.write_line (" */");
- c.write_lines (code);
+ c.write_lines (generator_.defines);
+ c.write_lines (generator_.headers);
+ c.write_line ("");
+ c.write_lines (generator_.code);
generate_traces (c);
}
@@ -548,28 +575,59 @@ namespace rld
void
tracer::generate_traces (rld::process::tempfile& c)
{
+ for (functions::const_iterator fi = functions_.begin ();
+ fi != functions_.end ();
+ ++fi)
+ {
+ const function& funcs = *fi;
+
+ for (rld::strings::const_iterator ti = traces.begin ();
+ ti != traces.end ();
+ ++ti)
+ {
+ const std::string& trace = *ti;
+ signatures::const_iterator si = funcs.signatures_.find (trace);
+
+ if (si != funcs.signatures_.end ())
+ {
+ c.write_line ("");
+ c.write_line ("/*");
+ c.write_line (" * Function: " + funcs.name);
+ c.write_line (" */");
+ c.write_lines (funcs.defines);
+ c.write_lines (funcs.headers);
+ break;
+ }
+ }
+ }
+
+ c.write_line ("");
+ c.write_line ("/*");
+ c.write_line (" * Wrappers.");
+ c.write_line (" */");
+
for (rld::strings::const_iterator ti = traces.begin ();
ti != traces.end ();
++ti)
{
- const std::string& func = *ti;
+ const std::string& trace = *ti;
bool found = false;
- for (wrappers::const_iterator wi = wrappers.begin ();
- wi != wrappers.end ();
- ++wi)
+ for (functions::const_iterator fi = functions_.begin ();
+ fi != functions_.end ();
+ ++fi)
{
- const wrapper& wrap = *wi;
- function_sigs::const_iterator fsi = wrap.sigs.find (func);
+ const function& funcs = *fi;
+ signatures::const_iterator si = funcs.signatures_.find (trace);
- if (fsi != wrap.sigs.end ())
+ if (si != funcs.signatures_.end ())
{
found = true;
- const function_sig& fs = (*fsi).second;
+ const signature& sig = (*si).second;
c.write_line("");
- c.write_line(fs.decl ());
+ c.write_line(sig.decl ());
c.write_line("{");
std::string l;
@@ -578,14 +636,14 @@ namespace rld
* @todo Need to define as part of the function signature if ret
* processing is required.
*/
- if (fs.ret != "void")
+ if (sig.ret != "void")
{
- c.write_line(" " + fs.ret + " ret;");
+ c.write_line(" " + sig.ret + " ret;");
l = " ret =";
}
- l += " " + wrap.map_sym_prefix + fs.name + '(';
- for (size_t a = 0; a < fs.args.size (); ++a)
+ l += " " + generator_.map_sym_prefix + sig.name + '(';
+ for (size_t a = 0; a < sig.args.size (); ++a)
{
if (a)
l += ", ";
@@ -594,7 +652,7 @@ namespace rld
l += ");";
c.write_line(l);
- if (fs.ret != "void")
+ if (sig.ret != "void")
{
c.write_line(" return ret;");
}
@@ -604,7 +662,7 @@ namespace rld
}
if (!found)
- throw rld::error ("not found", "trace function: " + func);
+ throw rld::error ("not found", "trace function: " + trace);
}
}
@@ -612,21 +670,23 @@ namespace rld
tracer::dump (std::ostream& out) const
{
out << " Tracer: " << name << std::endl
- << " BSP: " << bsp << std::endl;
- for (wrappers::const_iterator wi = wrappers.begin ();
- wi != wrappers.end ();
- ++wi)
+ << " BSP: " << bsp << std::endl
+ << " Traces: " << traces.size () << std::endl;
+ for (rld::strings::const_iterator ti = traces.begin ();
+ ti != traces.end ();
+ ++ti)
{
- (*wi).dump (out);
+ out << " " << (*ti) << std::endl;
}
- out << " Code blocks: " << std::endl;
- for (rld::strings::const_iterator ci = code.begin ();
- ci != code.end ();
- ++ci)
+ out << " Functions: " << functions_.size () << std::endl;
+ for (functions::const_iterator fi = functions_.begin ();
+ fi != functions_.end ();
+ ++fi)
{
- out << " > "
- << rld::find_replace (*ci, "\n", "\n | ") << std::endl;
+ (*fi).dump (out);
}
+ out << " Generator: " << std::endl;
+ generator_.dump (out);
}
linker::linker ()
@@ -639,13 +699,13 @@ namespace rld
{
config.clear ();
config.load (path);
- tracer.load (config, trace);
+ tracer_.load (config, trace);
}
void
linker::generate_wrapper ()
{
- tracer.generate ();
+ tracer_.generate ();
}
void
@@ -660,7 +720,7 @@ namespace rld
out << " " << (*pi) << std::endl;
}
- tracer.dump (out);
+ tracer_.dump (out);
}
}
}