You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
193 lines
4.3 KiB
193 lines
4.3 KiB
#!/usr/bin/env python |
|
import xml.etree.ElementTree as ET |
|
import os |
|
import re |
|
import codecs |
|
|
|
class Scope(object): |
|
""" |
|
Single parameter group |
|
""" |
|
re_deep_lines = re.compile(r'.*\/.*\/') |
|
def __init__(self, ): |
|
self.scope = set() |
|
|
|
|
|
def __str__(self): |
|
return self.scope.__str__() |
|
|
|
def Add(self, scope): |
|
""" |
|
Add Scope to set |
|
""" |
|
self.scope.add(scope) |
|
|
|
def Has(self, scope): |
|
""" |
|
Check for existance |
|
""" |
|
if len(self.scope) == 0: |
|
return True |
|
# Anything in the form xxxxx/yyyyy/zzzzz.... |
|
# is treated as xxxxx/yyyyy |
|
while (self.re_deep_lines.match(scope)): |
|
scope = os.path.dirname(scope) |
|
return scope in self.scope |
|
|
|
|
|
|
|
class CMakeParser(object): |
|
""" |
|
Parses provided data and stores all found paths in scope. |
|
""" |
|
re_split_lines = re.compile(r'[\r\n]+') |
|
re_comment = re.compile(r'^\#') |
|
re_start = re.compile(r'set\s*\(\s*config_module_list') |
|
re_end = re.compile(r'\)\s*') |
|
|
|
def Parse(self, scope, contents): |
|
""" |
|
Incrementally parse cmake file contents and append all found path scope |
|
to scope. |
|
""" |
|
# This code is essentially a comment-parsing grammar. "state" |
|
# represents parser state. It contains human-readable state |
|
# names. |
|
state = None |
|
for line in self.re_split_lines.split(contents): |
|
line = line.strip() |
|
# Ignore empty lines |
|
if line == "": |
|
continue |
|
if self.re_comment.match(line): |
|
continue |
|
elif self.re_start.match(line): |
|
state = "gather" |
|
continue |
|
elif state is not None and state == "gather": |
|
if self.re_end.match(line): |
|
return True |
|
scope.Add(line) |
|
return False |
|
|
|
|
|
if len(os.sys.argv) < 2: |
|
print("Error in %s" % os.sys.argv[0]) |
|
print("Usage: %s <parameters.xml> [cmake-file-scoping] " % os.sys.argv[0]) |
|
raise SystemExit |
|
|
|
|
|
scope = Scope() |
|
if len(os.sys.argv) == 3: |
|
with codecs.open(os.sys.argv[2], 'r', 'utf-8') as f: |
|
try: |
|
contents = f.read() |
|
f.close() |
|
parser = CMakeParser() |
|
parser.Parse(scope, contents) |
|
except: |
|
contents = '' |
|
print('Failed reading file: %s, skipping scoping.' % os.sys.argv[2]) |
|
pass |
|
|
|
fp_header = open("px4_parameters.h", "w") |
|
fp_src = open("px4_parameters.c", "w") |
|
|
|
tree = ET.parse(os.sys.argv[1]) |
|
root = tree.getroot() |
|
|
|
# Generate the header file content |
|
header = """ |
|
#include <stdint.h> |
|
#include <systemlib/param/param.h> |
|
|
|
// DO NOT EDIT |
|
// This file is autogenerated from parameters.xml |
|
|
|
__BEGIN_DECLS |
|
|
|
struct px4_parameters_t { |
|
""" |
|
start_name = "" |
|
end_name = "" |
|
|
|
for group in root: |
|
if group.tag == "group" and "no_code_generation" not in group.attrib: |
|
section = """ |
|
/***************************************************************** |
|
* %s |
|
****************************************************************/""" % group.attrib["name"] |
|
for param in group: |
|
scope_ = param.find('scope').text |
|
if not scope.Has(scope_): |
|
continue |
|
if not start_name: |
|
start_name = param.attrib["name"] |
|
end_name = param.attrib["name"] |
|
header += section |
|
section ="" |
|
header += """ |
|
const struct param_info_s __param__%s;""" % param.attrib["name"] |
|
header += """ |
|
const unsigned int param_count; |
|
}; |
|
|
|
extern const struct px4_parameters_t px4_parameters; |
|
""" |
|
|
|
# Generate the C file content |
|
src = """ |
|
#include <px4_parameters.h> |
|
|
|
// DO NOT EDIT |
|
// This file is autogenerated from paramaters.xml |
|
|
|
const |
|
#ifndef __PX4_DARWIN |
|
__attribute__((used, section("__param"))) |
|
#endif |
|
struct px4_parameters_t px4_parameters = { |
|
""" |
|
i=0 |
|
for group in root: |
|
if group.tag == "group" and "no_code_generation" not in group.attrib: |
|
section = """ |
|
/***************************************************************** |
|
* %s |
|
****************************************************************/""" % group.attrib["name"] |
|
for param in group: |
|
scope_ = param.find('scope').text |
|
if not scope.Has(scope_): |
|
continue |
|
if not start_name: |
|
start_name = param.attrib["name"] |
|
end_name = param.attrib["name"] |
|
val_str = "#error UNKNOWN PARAM TYPE, FIX px_generate_params.py" |
|
if (param.attrib["type"] == "FLOAT"): |
|
val_str = ".val.f = " |
|
elif (param.attrib["type"] == "INT32"): |
|
val_str = ".val.i = " |
|
i+=1 |
|
src += section |
|
section ="" |
|
src += """ |
|
{ |
|
"%s", |
|
PARAM_TYPE_%s, |
|
%s%s |
|
}, |
|
""" % (param.attrib["name"], param.attrib["type"], val_str, param.attrib["default"]) |
|
src += """ |
|
%d |
|
}; |
|
|
|
//extern const struct px4_parameters_t px4_parameters; |
|
|
|
__END_DECLS |
|
|
|
""" % i |
|
|
|
fp_header.write(header) |
|
fp_src.write(src) |
|
fp_header.close() |
|
fp_src.close()
|
|
|