summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2014-08-04 09:19:55 +1000
committerChris Johns <chrisj@rtems.org>2014-08-04 09:19:55 +1000
commit28884db485eba2b580d8da526e190f903b2e6174 (patch)
tree6cd24717823743f18041b6113351ff6a3468d3b4
parent482ca38073a878814640089086c0ba262e80e4cd (diff)
rtems-tld: Add trace configuration support.
Extend the configuration support to provide the needed configuration required to generate the C stub support.
-rw-r--r--rld-config.cpp40
-rw-r--r--rld-config.h95
-rw-r--r--rld.h116
-rw-r--r--rtems-tld.cpp485
-rw-r--r--rtems.ini20
-rw-r--r--test-fsigs.ini3
-rw-r--r--test-trace.ini35
7 files changed, 609 insertions, 185 deletions
diff --git a/rld-config.cpp b/rld-config.cpp
index b6b84c2..b197e5d 100644
--- a/rld-config.cpp
+++ b/rld-config.cpp
@@ -25,7 +25,6 @@
#include <errno.h>
#include <rld-config.h>
-#include <rld.h>
#include <SimpleIni.h>
@@ -127,6 +126,45 @@ namespace rld
}
}
+
+ void
+ config::includes (const section& sec, bool must_exist)
+ {
+ bool have_includes = false;
+
+ try
+ {
+ const rld::config::record& rec = sec.get_record ("include");
+
+ 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::config::items::const_iterator ri = rec.items.begin ();
+ ri != rec.items.end ();
+ ++ri)
+ {
+ load ((*ri).text);
+ }
+ }
+ 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
{
diff --git a/rld-config.h b/rld-config.h
index fe622e4..eb6d614 100644
--- a/rld-config.h
+++ b/rld-config.h
@@ -29,6 +29,8 @@
#include <list>
#include <vector>
+#include <rld.h>
+
namespace rld
{
namespace config
@@ -61,6 +63,13 @@ namespace rld
{
std::string name; //< Name of the record.
items items; //< The record's items.
+
+ /**
+ * Return true if there is only one item.
+ */
+ bool single () const {
+ return items.size () == 1;
+ }
};
/**
@@ -116,6 +125,13 @@ namespace rld
void load (const std::string& name);
/**
+ * Process any include records in the section named. If the section has
+ * any records named 'include' split the items and include the
+ * configuration files.
+ */
+ void includes (const section& sec, bool must_exist = false);
+
+ /**
* Get the section and throw an error if not found.
*/
const section& get_section (const std::string& name) const;
@@ -130,6 +146,85 @@ namespace rld
paths paths; /**< The path's of the loaded files. */
sections secs; /**< The sections loaded from configuration files */
};
+
+ /**
+ * Return the items from a record.
+ */
+ template < typename T >
+ void parse_items (const rld::config::record& record, T& items)
+ {
+ items.clear ();
+ for (rld::config::items::const_iterator ii = record.items.begin ();
+ ii != record.items.end ();
+ ++ii)
+ {
+ rld::strings ss;
+ rld::split (ss, (*ii).text, ',');
+ std::copy (ss.begin (), ss.end (), std::back_inserter (items));
+ }
+ }
+
+ /**
+ * Return the items from a record in a section. Optionally raise an error
+ * if the record is not found and it is to be present.
+ */
+ template < typename T >
+ void parse_items (const rld::config::section& section,
+ const std::string& name,
+ T& items,
+ bool present = false)
+ {
+ items.clear ();
+ const rld::config::record* rec = 0;
+ try
+ {
+ const rld::config::record& rr = section.get_record (name);
+ rec = &rr;
+ }
+ catch (rld::error re)
+ {
+ /*
+ * Ignore the error if it does not need to exist.
+ */
+ if (present)
+ throw rld::error ("not found", "record: " + section.name + name);
+ }
+
+ if (rec)
+ parse_items (*rec, items);
+ }
+
+ /**
+ * Return the items from a record in a section in the
+ * configuration. Optionally raise an error if the section is not found and
+ * it is to be present.
+ */
+ template < typename T >
+ void parse_items (const rld::config::config& config,
+ const std::string& section,
+ const std::string& record,
+ T& items,
+ bool present = false)
+ {
+ items.clear ();
+ const rld::config::section* sec = 0;
+ try
+ {
+ const rld::config::section& sr = config.get_section (section);
+ sec = &sr;
+ }
+ catch (rld::error re)
+ {
+ /*
+ * Ignore the error if it does not need to exist.
+ */
+ if (present)
+ throw rld::error ("not found", "section: " + section);
+ }
+
+ if (sec)
+ parse_items (*sec, record, items);
+ }
}
}
diff --git a/rld.h b/rld.h
index c6cd3ed..e1cfbf5 100644
--- a/rld.h
+++ b/rld.h
@@ -25,7 +25,11 @@
#if !defined (_RLD_H_)
#define _RLD_H_
+#include <algorithm>
+#include <cctype>
+#include <functional>
#include <iostream>
+#include <locale>
#include <sstream>
#include <string>
@@ -77,17 +81,6 @@ namespace rld
namespace rld
{
/**
- * Convert a supported type to a string.
- */
- template <class T>
- std::string to_string (T t, std::ios_base & (*f)(std::ios_base&) = std::dec)
- {
- std::ostringstream oss;
- oss << f << t;
- return oss.str();
- }
-
- /**
* General error.
*/
struct error
@@ -111,6 +104,107 @@ namespace rld
rld::error (_what, std::string (__FILE__) + ":" + to_string (__LINE__))
/**
+ * Convert a supported type to a string.
+ */
+ template <class T>
+ std::string to_string (T t, std::ios_base & (*f)(std::ios_base&) = std::dec)
+ {
+ std::ostringstream oss;
+ oss << f << t;
+ return oss.str();
+ }
+
+ /**
+ * A container of strings.
+ */
+ typedef std::vector < std::string > strings;
+
+ /**
+ * Trim from start.
+ */
+ inline std::string& ltrim (std::string &s)
+ {
+ s.erase (s.begin (),
+ std::find_if (s.begin (), s.end (),
+ std::not1 (std::ptr_fun < int, int > (std::isspace))));
+ return s;
+ }
+
+ /**
+ * Trim from end.
+ */
+ inline std::string& rtrim (std::string &s)
+ {
+ s.erase (std::find_if (s.rbegin (), s.rend (),
+ std::not1 (std::ptr_fun < int, int > (std::isspace))).base(),
+ s.end());
+ return s;
+ }
+
+ /**
+ * Trim from both ends.
+ */
+ inline std::string& trim (std::string &s)
+ {
+ return ltrim (rtrim (s));
+ }
+
+ /**
+ * Split the string in a contain of strings based on the the
+ * delimiter. Optionally trim any white space or include empty string.
+ *
+ * @todo The split should optionally honour string quoting.
+ */
+ inline strings& split (strings& se,
+ const std::string& s,
+ char delimiter,
+ bool strip_quotes = true,
+ bool strip_whitespace = true,
+ bool empty = false)
+ {
+ std::stringstream ss(s);
+ std::string e;
+ se.clear ();
+ while (std::getline (ss, e, delimiter))
+ {
+ if (strip_whitespace)
+ trim (e);
+ if (strip_quotes)
+ {
+ if ((e.front () == '"') || (e.front () == '\''))
+ {
+ if (e.front () != e.back ())
+ throw rld::error ("invalid quoting", "string: " + s);
+ e = e.substr (1, e.length () - 1);
+ }
+ }
+ if (empty || !e.empty ())
+ {
+ se.push_back (e);
+ }
+ }
+ return se;
+ }
+
+ /**
+ * Join the strings together with the separator.
+ */
+ inline std::string& join (const strings& ss,
+ const std::string& separator,
+ std::string& s)
+ {
+ for (strings::const_iterator ssi = ss.begin ();
+ ssi != ss.end ();
+ ++ssi)
+ {
+ s += *ssi;
+ if ((ssi != ss.begin ()) && (ssi != ss.end ()))
+ s += separator;
+ }
+ return s;
+ }
+
+ /**
* Increment the verbose level.
*/
void verbose_inc ();
diff --git a/rtems-tld.cpp b/rtems-tld.cpp
index edc6e55..4f17fba 100644
--- a/rtems-tld.cpp
+++ b/rtems-tld.cpp
@@ -52,226 +52,376 @@
namespace rld
{
-
/**
- * Trim from start.
+ * RTEMS Trace Linker.
*/
- inline std::string &ltrim (std::string &s)
+ namespace trace
{
- s.erase (s.begin (),
- std::find_if (s.begin (), s.end (),
- std::not1 (std::ptr_fun < int, int > (std::isspace))));
- return s;
- }
+ /**
+ * A container of arguments.
+ */
+ typedef std::vector < std::string > function_args;
- /**
- * Trim from end.
- */
- inline std::string &rtrim (std::string &s)
- {
- s.erase (std::find_if (s.rbegin (), s.rend (),
- std::not1 (std::ptr_fun < int, int > (std::isspace))).base(),
- s.end());
- return s;
- }
+ /**
+ * The return value.
+ */
+ typedef std::string function_return;
- /**
- * Trim from both ends.
- */
- inline std::string &trim (std::string &s)
- {
- return ltrim (rtrim (s));
- }
-}
+ /**
+ * A function's signature.
+ */
+ struct function_sig
+ {
+ std::string name; /**< The function's name. */
+ function_args args; /**< The function's list of arguments. */
+ function_return ret; /**< The fuctions return value. */
-/**
- * RTEMS Trace Linker.
- */
-namespace trace
-{
- /**
- * A container of arguments.
- */
- typedef std::vector < std::string > function_args;
+ /**
+ * The default constructor.
+ */
+ function_sig ();
- /**
- * The return value.
- */
- typedef std::string function_return;
+ /**
+ * Construct the signature loading it from the configuration.
+ */
+ function_sig (const rld::config::record& record);
- /**
- * A function's signature.
- */
- struct function_sig
- {
- std::string name; /**< The function's name. */
- function_args args; /**< The function's list of arguments. */
- function_return ret; /**< The fuctions return value. */
- };
+ /**
+ * Copy constructor.
+ */
+ function_sig (const function_sig& orig);
- /**
- * A container of function signatures.
- */
- typedef std::map < std::string, function_sig > function_sigs;
+ /**
+ * Return the function's declaration.
+ */
+ const std::string decl () const;
+ };
- /**
- * Trace Linker.
- */
- class linker
- {
- public:
- linker ();
+ /**
+ * A container of function signatures.
+ */
+ typedef std::map < std::string, function_sig > function_sigs;
/**
- * Load the user's configuration.
+ * 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.
*/
- void load_config (const std::string& path);
+ struct wrapper
+ {
+ std::string name; /**< The name of this wrapper. */
+ rld::strings headers; /**< Include statements. */
+ rld::strings defines; /**< Define statements. */
+ function_sigs sigs; /**< The functions this wrapper wraps. */
+
+ /**
+ * Load the wrapper.
+ */
+ wrapper (const std::string& name,
+ rld::config::config& config);
+
+ /**
+ * Dump the wrapper.
+ */
+ void dump (std::ostream& out) const;
+ };
/**
- * Dump the linker status.
+ * A container of wrappers. The order is the order we wrap.
*/
- void dump (std::ostream& out);
+ typedef std::vector < wrapper > wrappers;
- private:
+ /**
+ * Tracer.
+ */
+ class tracer
+ {
+ public:
+ tracer ();
- rld::config::config config; /**< User configuration. */
- function_sigs sigs; /**< Function signatures. */
- };
+ /**
+ * Load the user's configuration.
+ */
+ void load (rld::config::config& config,
+ const std::string& section);
- linker::linker ()
- {
- }
+ /**
+ * Dump the wrapper.
+ */
+ void dump (std::ostream& out) const;
- void
- linker::load_config (const std::string& path)
- {
- config.clear ();
- config.load (path);
+ private:
- /*
- * The configuration must contain a "trace" section. This is the top level
- * configuration and must the following fields:
- *
- * # < add here >
- *
- * The 'trace" section may optionally contain a number of 'include' records
- * and these configuration files are included.
+ std::string name; /**< The name of the trace. */
+ std::string bsp; /**< The BSP we are linking to. */
+ rld::strings trace; /**< The functions to trace. */
+ wrappers wrappers; /**< Wrappers wrap trace functions. */
+ };
+
+ /**
+ * Trace Linker.
*/
+ class linker
+ {
+ public:
+ linker ();
- const rld::config::section& tsec = config.get_section ("trace");
- bool have_includes = false;
+ /**
+ * Load the user's configuration.
+ */
+ void load_config (const std::string& path,
+ const std::string& trace);
- try
+ /**
+ * Generate the C file.
+ */
+ void generate_c ();
+
+ /**
+ * Dump the linker.
+ */
+ void dump (std::ostream& out) const;
+
+ private:
+
+ rld::config::config config; /**< User configuration. */
+ tracer tracer; /**< The tracer */
+ };
+
+ function_sig::function_sig ()
{
- const rld::config::record& irec = tsec.get_record ("include");
+ }
- have_includes = true;
+ function_sig::function_sig (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);
+
+ name = record.name;
+
+ /*
+ * Function 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.
+ */
+ rld::strings si;
+ rld::config::parse_items (record, si);
+
+ if (si.size () == 0)
+ throw rld::error ("no return value", "function signature: " + record.name);
+ if (si.size () == 1)
+ throw rld::error ("no arguments", "function 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
+ {
+ std::string ds = ret + ' ' + name + '(';
+ int arg = 0;
+ for (function_args::const_iterator ai = args.begin ();
+ ai != args.end ();
+ ++ai)
+ {
+ if (ai != args.begin ())
+ ds += ", ";
+ ds += (*ai) + " a" + rld::to_string (++arg);
+ }
+ ds += ')';
+
+ return ds;
+ }
+ wrapper::wrapper (const std::string& name,
+ rld::config::config& config)
+ : name (name)
+ {
/*
- * Include records are a path which we can just load.
+ * A wrapper section optionally contain one or more records of:
+ *
+ * # header A list of include string that are single or double quoted.
+ * # define A list of define string that are single or double quoted.
+ * # signature A list of section names of function signatures.
*
- * @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.
+ * @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);
- for (rld::config::items::const_iterator ii = irec.items.begin ();
- ii != irec.items.end ();
- ++ii)
+ rld::strings sig_list;
+
+ rld::config::parse_items (section, "header", headers);
+ rld::config::parse_items (section, "define", defines);
+ rld::config::parse_items (section, "signature", sig_list);
+
+ for (rld::strings::const_iterator sli = sig_list.begin ();
+ sli != sig_list.end ();
+ ++sli)
{
- config.load ((*ii).text);
+ 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)
+ {
+ function_sig func (*ri);
+ sigs[func.name] = func;
+ }
}
}
- catch (rld::error re)
+
+ void
+ wrapper::dump (std::ostream& out) const
+ {
+ out << " Wrapper: " << name << std::endl
+ << " Headers: " << headers.size () << std::endl;
+ for (rld::strings::const_iterator hi = headers.begin ();
+ hi != headers.end ();
+ ++hi)
+ {
+ out << " " << (*hi) << std::endl;
+ }
+ out << " Defines: " << defines.size () << std::endl;
+ for (rld::strings::const_iterator di = defines.begin ();
+ di != defines.end ();
+ ++di)
+ {
+ out << " " << (*di) << std::endl;
+ }
+ out << " Function Signatures: " << sigs.size () << std::endl;
+ for (function_sigs::const_iterator si = sigs.begin ();
+ si != sigs.end ();
+ ++si)
+ {
+ const function_sig& sig = (*si).second;
+ out << " " << sig.name << ": " << sig.decl () << ';' << std::endl;
+ }
+ }
+
+ tracer::tracer ()
+ {
+ }
+
+ void
+ tracer::load (rld::config::config& config,
+ const std::string& section)
{
/*
- * No include records, must be all inlined. If we have includes it must
- * be another error so throw it.
+ * 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 following record are optional:
+ *
+ * # bdp The BSP the executable is for. Can be supplied on the command
+ * line.
+ * # include Include the INI file.
+ *
+ * The following will throw an error is the section or records are not
+ * found.
*/
- if (have_includes)
- throw;
- }
+ rld::strings ss;
- /*
- * Get the function signatures from the configuration and load them into
- * the sig map.
- */
+ 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");
- const rld::config::section& fssec = config.get_section ("function-signatures");
+ if (!nrec.single ())
+ throw rld::error ("duplicate", "trace names");
+ name = nrec.items[0].text;
+
+ if (!brec.single ())
+ throw rld::error ("duplicate", "trace bsp");
+ bsp = brec.items[0].text;
- for (rld::config::records::const_iterator ri = fssec.recs.begin ();
- ri != fssec.recs.end ();
- ++ri)
- {
/*
- * There can only be one function signature in the configuration.
+ * Include any files.
*/
- if ((*ri).items.size () > 1)
- throw rld::error ("duplicate", "function signature: " + (*ri).name);
+ config.includes (tsec);
- function_sig sig;
- sig.name = (*ri).name;
+ /*
+ * Load the wrappers.
+ */
+ rld::strings wi;
+ rld::config::parse_items (wrec, wi);
+ for (rld::strings::const_iterator wsi = wi.begin ();
+ wsi != wi.end ();
+ ++wsi)
+ {
+ wrappers.push_back (wrapper (*wsi, config));
+ }
/*
- * Function 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.
+ * Load the trace functions.
*/
- rld::config::items::const_iterator ii = (*ri).items.begin ();
- std::stringstream ts((*ii).text);
- std::string arg;
- while (std::getline (ts, arg, ','))
+ rld::strings ti;
+ rld::config::parse_items (trec, ti);
+ for (rld::strings::const_iterator tsi = ti.begin ();
+ tsi != ti.end ();
+ ++tsi)
{
- rld::trim (arg);
- if (!arg.empty ())
- {
- if (sig.ret.empty ())
- sig.ret = arg;
- else
- sig.args.push_back(arg);
- }
+ rld::config::parse_items (config, *tsi, "trace", trace, true);
}
- if (sig.ret.empty ())
- throw rld::error ("no return value", "function signature: " + (*ri).name);
+ }
- if (sig.args.empty ())
- throw rld::error ("no arguments", "function signature: " + (*ri).name);
+ void
+ 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)
+ {
+ (*wi).dump (out);
+ }
+ }
- sigs[sig.name] = sig;
+ linker::linker ()
+ {
}
- }
- void
- linker::dump (std::ostream& out)
- {
- const rld::config::paths& cpaths = config.get_paths ();
- out << "Configuration Files: " << cpaths.size () << std::endl;
- for (rld::config::paths::const_iterator pi = cpaths.begin ();
- pi != cpaths.end ();
- ++pi)
+ void
+ linker::load_config (const std::string& path,
+ const std::string& trace)
{
- out << " " << (*pi) << std::endl;
+ config.clear ();
+ config.load (path);
+ tracer.load (config, trace);
}
- out << std::endl
- << "Function Signatures: " << sigs.size () << std::endl;
- for (function_sigs::const_iterator si = sigs.begin ();
- si != sigs.end ();
- ++si)
+ void
+ linker::dump (std::ostream& out) const
{
- const function_sig& sig = (*si).second;
- out << " " << sig.name << ": " << sig.ret << ' ' << sig.name << '(';
- for (function_args::const_iterator fai = sig.args.begin ();
- fai != sig.args.end ();
- ++fai)
+ const rld::config::paths& cpaths = config.get_paths ();
+ out << "RTEMS Trace Linker" << std::endl
+ << " Configuration Files: " << cpaths.size () << std::endl;
+ for (rld::config::paths::const_iterator pi = cpaths.begin ();
+ pi != cpaths.end ();
+ ++pi)
{
- if (fai != sig.args.begin ())
- out << ", ";
- out << (*fai);
+ out << " " << (*pi) << std::endl;
}
- out << ");" << std::endl;
+
+ tracer.dump (out);
}
}
}
@@ -353,12 +503,13 @@ main (int argc, char* argv[])
try
{
- trace::linker linker;
- std::string ld_cmd;
- std::string configuration;
- bool exec_prefix_set = false;
+ rld::trace::linker linker;
+ std::string ld_cmd;
+ std::string configuration;
+ std::string trace = "tracer";
+ bool exec_prefix_set = false;
#if HAVE_WARNINGS
- bool warnings = false;
+ bool warnings = false;
#endif
while (true)
@@ -439,7 +590,7 @@ main (int argc, char* argv[])
*/
try
{
- linker.load_config (configuration);
+ linker.load_config (configuration, trace);
linker.dump (std::cout);
}
catch (...)
diff --git a/rtems.ini b/rtems.ini
new file mode 100644
index 0000000..cd59f72
--- /dev/null
+++ b/rtems.ini
@@ -0,0 +1,20 @@
+;
+; RTEMS API Trace Configurations
+;
+[rtems-api]
+header = rtems-api-headers
+define = rtems-api-defines
+signature = rtems-api-signatures
+
+[rtems-api-headers]
+header = "#include <rtems.h>"
+
+[rtems-api-defines]
+; Currently empty
+
+[rtems-api-task]
+trace = rtems_task_create
+
+[rtems-api-signatures]
+rtems_task_create = rtems_status_code, rtems_name, rtems_task_priority, size_t, rtems_mode, rtems_attribute, rtems_id*
+
diff --git a/test-fsigs.ini b/test-fsigs.ini
deleted file mode 100644
index a0d1e22..0000000
--- a/test-fsigs.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[function-signatures]
-rtems_task_create = rtems_status_code, rtems_name, rtems_task_priority, size_t, rtems_mode, rtems_attribute, rtems_id*
-
diff --git a/test-trace.ini b/test-trace.ini
index 049e8e8..2901952 100644
--- a/test-trace.ini
+++ b/test-trace.ini
@@ -3,12 +3,41 @@
;
; We must provide a top level trace section.
;
-[trace]
+[tracer]
;
; Name of the trace.
;
name = RTEMS Trace Linker Test
;
-; Include the function signatures.
+; The BSP.
;
-include = test-fsigs.ini
+bsp = sis
+;
+; Functions to trace.
+;
+trace = test-trace, test-trace-funcs, rtems-api-task
+;
+; Define the wrapper.
+;
+wrapper = test-trace, rtems-api
+;
+; Include RTEMS Trace support.
+;
+include = rtems.ini
+
+;
+; User application trace example.
+;
+[test-trace-funcs]
+trace = test_trace_1, test_trace_2
+
+[test-trace]
+trace = test_trace_3
+header = '#include "test-trace.h"'
+define = "#define TEST_TRACE 1"
+signature = test-signatures
+
+[test-signatures]
+test_trace_1 = void, int
+test_trace_2 = test_type_2, test_type_1
+test_trace_3 = float, float*