mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-11-04 02:41:36 +08:00
DSDL compiler for libuavcan - dsdlc
This commit is contained in:
@@ -12,3 +12,6 @@ lib*.so.*
|
|||||||
.project
|
.project
|
||||||
.cproject
|
.cproject
|
||||||
.pydevproject
|
.pydevproject
|
||||||
|
|
||||||
|
# libuavcan DSDL compiler default output directory
|
||||||
|
*dsdlc_output
|
||||||
|
|||||||
@@ -1 +1,182 @@
|
|||||||
|
/*
|
||||||
|
* UAVCAN data structure definition for libuavcan.
|
||||||
|
*
|
||||||
|
* Autogenerated, do not edit.
|
||||||
|
*
|
||||||
|
* Source file: ${t.filename}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <uavcan/data_type.hpp>
|
||||||
|
#include <uavcan/global_data_type_registry.hpp>
|
||||||
|
#include <uavcan/internal/util.hpp>
|
||||||
|
|
||||||
|
% for inc in t.cpp_includes:
|
||||||
|
#include <${inc}>
|
||||||
|
% endfor
|
||||||
|
|
||||||
|
#if !defined(UAVCAN_CONSTEXPR)
|
||||||
|
# if __cplusplus < 201100L
|
||||||
|
# define UAVCAN_CONSTEXPR const
|
||||||
|
# else
|
||||||
|
# define UAVCAN_CONSTEXPR constexpr
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
<%!
|
||||||
|
indent = lambda text, idnt=' ': idnt + text.replace('\n', '\n' + idnt)
|
||||||
|
%>
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
% for line in t.source_text.strip().splitlines():
|
||||||
|
${line}
|
||||||
|
% endfor
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
% for nsc in t.cpp_namespace_components:
|
||||||
|
namespace ${nsc}
|
||||||
|
{
|
||||||
|
% endfor
|
||||||
|
|
||||||
|
struct ${t.short_name}
|
||||||
|
{
|
||||||
|
<%def name="generate_primary_body(type_name, max_bitlen, fields, constants)" buffered="True">
|
||||||
|
typedef const ${type_name}& ParameterType;
|
||||||
|
typedef ${type_name}& ReferenceType;
|
||||||
|
|
||||||
|
<%def name="expand_attr_types(group_name, attrs)">
|
||||||
|
struct ${group_name}
|
||||||
|
{
|
||||||
|
% for a in attrs:
|
||||||
|
typedef ${a.cpp_type} ${a.name};
|
||||||
|
% endfor
|
||||||
|
};
|
||||||
|
</%def>
|
||||||
|
${expand_attr_types('ConstantTypes', constants)}
|
||||||
|
${expand_attr_types('FieldTypes', fields)}
|
||||||
|
|
||||||
|
<%def name="expand_enum_per_field(enum_name)">
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
${enum_name}
|
||||||
|
% for idx,a in enumerate(fields):
|
||||||
|
${'=' if idx == 0 else '+'} FieldTypes::${a.name}::${enum_name}
|
||||||
|
% endfor
|
||||||
|
};
|
||||||
|
</%def>
|
||||||
|
${expand_enum_per_field('MinBitLen')}
|
||||||
|
${expand_enum_per_field('MaxBitLen')}
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
% for a in constants:
|
||||||
|
% if a.cpp_use_enum:
|
||||||
|
enum { ${a.name} = ${a.cpp_value} }; // ${a.init_expression}
|
||||||
|
% else:
|
||||||
|
static UAVCAN_CONSTEXPR typename ::uavcan::StorageType<ConstantTypes::${a.name}>::Type
|
||||||
|
${a.name} = ${a.cpp_value}; // ${a.init_expression}
|
||||||
|
%endif
|
||||||
|
% endfor
|
||||||
|
|
||||||
|
// Fields
|
||||||
|
% for a in fields:
|
||||||
|
typename ::uavcan::StorageType<FieldTypes::${a.name}>::Type ${a.name};
|
||||||
|
% endfor
|
||||||
|
|
||||||
|
${type_name}()
|
||||||
|
% for idx,a in enumerate(fields):
|
||||||
|
${':' if idx == 0 else ','} ${a.name}()
|
||||||
|
% endfor
|
||||||
|
{
|
||||||
|
#if UAVCAN_DEBUG
|
||||||
|
/*
|
||||||
|
* Cross-checking MaxBitLen provided by the DSDL compiler.
|
||||||
|
* This check shall never be performed in user code because MaxBitLen value
|
||||||
|
* actually depends on the nested types, thus it is not invariant.
|
||||||
|
*/
|
||||||
|
::uavcan::StaticAssert<${max_bitlen} == MaxBitLen>::check();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
<%def name="generate_codec_calls_per_field(call_name, self_parameter_type)">
|
||||||
|
static int ${call_name}(${self_parameter_type} self, ::uavcan::ScalarCodec& codec,
|
||||||
|
::uavcan::TailArrayOptimizationMode tao_mode = ::uavcan::TailArrayOptEnabled)
|
||||||
|
{
|
||||||
|
int res = 1;
|
||||||
|
% for idx,a in enumerate(fields):
|
||||||
|
res = FieldTypes::${a.name}::${call_name}(self.${a.name}, codec, \
|
||||||
|
${'::uavcan::TailArrayOptDisabled' if (idx + 1) < len(fields) else 'tao_mode'});
|
||||||
|
if (res <= 0)
|
||||||
|
return res;
|
||||||
|
% endfor
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
</%def>
|
||||||
|
${generate_codec_calls_per_field('encode', 'ParameterType')}
|
||||||
|
${generate_codec_calls_per_field('decode', 'ReferenceType')}
|
||||||
|
</%def>
|
||||||
|
% if t.kind == t.KIND_SERVICE:
|
||||||
|
struct Request
|
||||||
|
{
|
||||||
|
${generate_primary_body(t.short_name, t.get_max_bitlen_request(), t.request_fields, t.request_constants) | indent}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Response
|
||||||
|
{
|
||||||
|
${generate_primary_body(t.short_name, t.get_max_bitlen_response(), t.response_fields, t.response_constants) | indent}
|
||||||
|
};
|
||||||
|
% else:
|
||||||
|
${generate_primary_body(t.short_name, t.get_max_bitlen(), t.fields, t.constants)}
|
||||||
|
% endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Static type info
|
||||||
|
*/
|
||||||
|
enum { DataTypeKind = ${t.cpp_kind} };
|
||||||
|
% if t.has_default_dtid:
|
||||||
|
enum { DefaultDataTypeID = ${t.default_dtid} };
|
||||||
|
% else:
|
||||||
|
// This type has no default data type ID
|
||||||
|
% endif
|
||||||
|
|
||||||
|
static const char* getDataTypeFullName()
|
||||||
|
{
|
||||||
|
return "${t.full_name}";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void extendDataTypeSignature(::uavcan::DataTypeSignature& signature)
|
||||||
|
{
|
||||||
|
signature.extend(getDataTypeSignature());
|
||||||
|
}
|
||||||
|
|
||||||
|
static ::uavcan::DataTypeSignature getDataTypeSignature()
|
||||||
|
{
|
||||||
|
::uavcan::DataTypeSignature signature(${hex(t.dsdl_signature)});
|
||||||
|
<%def name="extend_signature_per_field(scope_prefix, fields)">
|
||||||
|
% for a in fields:
|
||||||
|
${scope_prefix}FieldTypes::${a.name}::extendDataTypeSignature(signature);
|
||||||
|
% endfor
|
||||||
|
</%def>
|
||||||
|
% if t.kind == t.KIND_SERVICE:
|
||||||
|
${extend_signature_per_field('Request::', t.request_fields)}
|
||||||
|
${extend_signature_per_field('Response::', t.response_fields)}
|
||||||
|
% else:
|
||||||
|
${extend_signature_per_field('', t.fields)}
|
||||||
|
% endif
|
||||||
|
return signature;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO Stream operator
|
||||||
|
|
||||||
|
% if t.has_default_dtid:
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
::uavcan::DefaultDataTypeRegistrator<${t.short_name}> _uavcan_gdtr_registrator_${t.short_name};
|
||||||
|
}
|
||||||
|
% endif
|
||||||
|
|
||||||
|
% for nsc in t.cpp_namespace_components:
|
||||||
|
}
|
||||||
|
% endfor
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
# Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
|
# Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
|
||||||
#
|
#
|
||||||
|
|
||||||
import sys, os
|
import sys, os, argparse, logging
|
||||||
|
from mako.template import Template
|
||||||
|
|
||||||
RUNNING_FROM_SRC_DIR = os.path.abspath(__file__).endswith(os.path.join('libuavcan', 'dsdl_compiler', 'dsdlc.py'))
|
RUNNING_FROM_SRC_DIR = os.path.abspath(__file__).endswith(os.path.join('libuavcan', 'dsdl_compiler', 'dsdlc.py'))
|
||||||
if RUNNING_FROM_SRC_DIR:
|
if RUNNING_FROM_SRC_DIR:
|
||||||
@@ -15,4 +16,173 @@ if RUNNING_FROM_SRC_DIR:
|
|||||||
|
|
||||||
from pyuavcan import dsdl
|
from pyuavcan import dsdl
|
||||||
|
|
||||||
print('Hello')
|
MAX_BITLEN_FOR_ENUM = 31
|
||||||
|
CPP_HEADER_EXTENSION = 'hpp'
|
||||||
|
TEMPLATE_FILENAME = os.path.join(os.path.dirname(__file__), 'data_type_template.hpp')
|
||||||
|
|
||||||
|
# -----------------
|
||||||
|
|
||||||
|
class DsdlCompilerException(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def pretty_filename(filename):
|
||||||
|
a = os.path.abspath(filename)
|
||||||
|
r = os.path.relpath(filename)
|
||||||
|
return a if len(a) < len(r) else r
|
||||||
|
|
||||||
|
def type_output_filename(t):
|
||||||
|
assert t.category == t.CATEGORY_COMPOUND
|
||||||
|
return t.full_name.replace('.', os.path.sep) + '.' + CPP_HEADER_EXTENSION
|
||||||
|
|
||||||
|
def die(text):
|
||||||
|
print(text, file=sys.stderr)
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
def configure_logging(verbosity):
|
||||||
|
fmt = '%(message)s'
|
||||||
|
level = { 0: logging.WARNING, 1: logging.INFO, 2: logging.DEBUG }.get(verbosity or 0, logging.DEBUG)
|
||||||
|
logging.basicConfig(stream=sys.stderr, level=level, format=fmt)
|
||||||
|
|
||||||
|
def run_parser(source_dir, search_dirs):
|
||||||
|
try:
|
||||||
|
types = dsdl.parse_namespace(source_dir, search_dirs)
|
||||||
|
except dsdl.DsdlException as ex:
|
||||||
|
errtext = str(ex) # TODO: gcc-style formatting
|
||||||
|
die(errtext)
|
||||||
|
logging.info('%d types from [%s] parsed successfully', len(types), source_dir)
|
||||||
|
return types
|
||||||
|
|
||||||
|
def run_generator(types, dest_dir):
|
||||||
|
try:
|
||||||
|
dest_dir = os.path.abspath(dest_dir) # Removing '..'
|
||||||
|
os.makedirs(dest_dir, exist_ok=True)
|
||||||
|
for t in types:
|
||||||
|
logging.info('Generating type %s', t.full_name)
|
||||||
|
file_path = os.path.join(dest_dir, type_output_filename(t))
|
||||||
|
dir_path = os.path.dirname(file_path)
|
||||||
|
os.makedirs(dir_path, exist_ok=True)
|
||||||
|
text = generate_one_type(t)
|
||||||
|
with open(file_path, 'w') as f:
|
||||||
|
f.write(text)
|
||||||
|
except Exception as ex:
|
||||||
|
logging.info('Generator error', exc_info=True)
|
||||||
|
die(str(ex))
|
||||||
|
|
||||||
|
def type_to_cpp_type(t):
|
||||||
|
if t.category == t.CATEGORY_PRIMITIVE:
|
||||||
|
cast_mode = {
|
||||||
|
t.CAST_MODE_SATURATED: '::uavcan::CastModeSaturate',
|
||||||
|
t.CAST_MODE_TRUNCATED: '::uavcan::CastModeTruncate',
|
||||||
|
}[t.cast_mode]
|
||||||
|
if t.kind == t.KIND_FLOAT:
|
||||||
|
return '::uavcan::FloatSpec<%d, %s>' % (t.bitlen, cast_mode)
|
||||||
|
else:
|
||||||
|
signedness = {
|
||||||
|
t.KIND_BOOLEAN: '::uavcan::SignednessUnsigned',
|
||||||
|
t.KIND_UNSIGNED_INT: '::uavcan::SignednessUnsigned',
|
||||||
|
t.KIND_SIGNED_INT: '::uavcan::SignednessSigned',
|
||||||
|
}[t.kind]
|
||||||
|
return '::uavcan::IntegerSpec<%d, %s, %s>' % (t.bitlen, signedness, cast_mode)
|
||||||
|
elif t.category == t.CATEGORY_ARRAY:
|
||||||
|
value_type = type_to_cpp_type(t.value_type)
|
||||||
|
mode = {
|
||||||
|
t.MODE_STATIC: '::uavcan::ArrayModeStatic',
|
||||||
|
t.MODE_DYNAMIC: '::uavcan::ArrayModeDynamic',
|
||||||
|
}[t.mode]
|
||||||
|
return '::uavcan::Array<%s, %s, %d>' % (value_type, mode, t.max_size)
|
||||||
|
elif t.category == t.CATEGORY_COMPOUND:
|
||||||
|
return '::' + t.full_name.replace('.', '::')
|
||||||
|
else:
|
||||||
|
raise DsdlCompilerException('Unknown type category: %s' % t.category)
|
||||||
|
|
||||||
|
def generate_one_type(t):
|
||||||
|
t.short_name = t.full_name.split('.')[-1]
|
||||||
|
|
||||||
|
# Dependencies (no duplicates)
|
||||||
|
def fields_includes(fields):
|
||||||
|
return set(type_output_filename(x.type) for x in fields if x.type.category == x.type.CATEGORY_COMPOUND)
|
||||||
|
|
||||||
|
if t.kind == t.KIND_MESSAGE:
|
||||||
|
t.cpp_includes = fields_includes(t.fields)
|
||||||
|
else:
|
||||||
|
t.cpp_includes = fields_includes(t.request_fields + t.response_fields)
|
||||||
|
|
||||||
|
t.cpp_namespace_components = t.full_name.split('.')[:-1]
|
||||||
|
t.has_default_dtid = t.default_dtid is not None
|
||||||
|
|
||||||
|
# Attribute types
|
||||||
|
def inject_cpp_types(attributes):
|
||||||
|
for a in attributes:
|
||||||
|
a.cpp_type = type_to_cpp_type(a.type)
|
||||||
|
|
||||||
|
if t.kind == t.KIND_MESSAGE:
|
||||||
|
inject_cpp_types(t.fields)
|
||||||
|
inject_cpp_types(t.constants)
|
||||||
|
else:
|
||||||
|
inject_cpp_types(t.request_fields)
|
||||||
|
inject_cpp_types(t.request_constants)
|
||||||
|
inject_cpp_types(t.response_fields)
|
||||||
|
inject_cpp_types(t.response_constants)
|
||||||
|
|
||||||
|
# Constant properties
|
||||||
|
def inject_constant_info(constants):
|
||||||
|
for c in constants:
|
||||||
|
if c.type.kind == c.type.KIND_FLOAT:
|
||||||
|
c.cpp_use_enum = False
|
||||||
|
numeric_limits = '::std::numeric_limits<typename ::uavcan::StorageType<typename ConstantTypes::%s>::Type>' % c.name
|
||||||
|
numeric_limits_inf = numeric_limits + '::infinity()'
|
||||||
|
special_values = {
|
||||||
|
'inf': numeric_limits_inf,
|
||||||
|
'+inf': numeric_limits_inf,
|
||||||
|
'-inf': '-' + numeric_limits_inf,
|
||||||
|
'nan': numeric_limits + '::quiet_NaN()',
|
||||||
|
}
|
||||||
|
if c.string_value in special_values:
|
||||||
|
c.cpp_value = special_values[c.string_value]
|
||||||
|
else:
|
||||||
|
float(c.string_value) # making sure that this is a valid float literal
|
||||||
|
c.cpp_value = c.string_value
|
||||||
|
else:
|
||||||
|
c.cpp_use_enum = c.value >= 0 and c.type.bitlen <= MAX_BITLEN_FOR_ENUM
|
||||||
|
c.cpp_value = c.string_value
|
||||||
|
if t.kind == t.KIND_MESSAGE:
|
||||||
|
inject_constant_info(t.constants)
|
||||||
|
else:
|
||||||
|
inject_constant_info(t.request_constants)
|
||||||
|
inject_constant_info(t.response_constants)
|
||||||
|
|
||||||
|
# Data type kind
|
||||||
|
t.cpp_kind = {
|
||||||
|
t.KIND_MESSAGE: '::uavcan::DataTypeKindMessage',
|
||||||
|
t.KIND_SERVICE: '::uavcan::DataTypeKindService',
|
||||||
|
}[t.kind]
|
||||||
|
|
||||||
|
# Generation
|
||||||
|
template = Template(filename=TEMPLATE_FILENAME)
|
||||||
|
text = template.render(t=t)
|
||||||
|
text = '\n'.join(x.rstrip() for x in text.splitlines())
|
||||||
|
text = text.replace('\n\n\n\n', '\n\n').replace('\n\n\n', '\n\n')
|
||||||
|
text = text.replace('{\n\n ', '{\n ')
|
||||||
|
return text
|
||||||
|
|
||||||
|
# -----------------
|
||||||
|
|
||||||
|
DESCRIPTION = '''UAVCAN DSDL compiler. Takes an input directory that contains an hierarchy of DSDL
|
||||||
|
definitions and converts it into compatible hierarchy of C++ types for libuavcan.'''
|
||||||
|
|
||||||
|
DEFAULT_OUTDIR = './dsdlc_output'
|
||||||
|
|
||||||
|
argparser = argparse.ArgumentParser(description=DESCRIPTION)
|
||||||
|
argparser.add_argument('source_dir', help='source directory with DSDL definitions')
|
||||||
|
argparser.add_argument('--verbose', '-v', action='count', help='verbosity level (-v, -vv)')
|
||||||
|
argparser.add_argument('--outdir', '-O', default=DEFAULT_OUTDIR, help='output directory, default %s' % DEFAULT_OUTDIR)
|
||||||
|
argparser.add_argument('--incdir', '-I', default=[], action='append', help='nested type namespaces')
|
||||||
|
args = argparser.parse_args()
|
||||||
|
|
||||||
|
configure_logging(args.verbose)
|
||||||
|
|
||||||
|
types = run_parser(args.source_dir, args.incdir)
|
||||||
|
if not types:
|
||||||
|
die('No type definitions were found')
|
||||||
|
|
||||||
|
run_generator(types, args.outdir)
|
||||||
|
|||||||
@@ -2,5 +2,10 @@
|
|||||||
# Test file
|
# Test file
|
||||||
#
|
#
|
||||||
|
|
||||||
|
int2 SMALL_CONST = -2
|
||||||
|
int61 CONST = -123456789
|
||||||
|
float16 FLOAT_CONST = 1.23
|
||||||
|
float16 FLOAT_CONST2 = nan
|
||||||
|
float16 FLOAT_CONST3 = -inf
|
||||||
root_b.TypeInRootB type_in_root_b
|
root_b.TypeInRootB type_in_root_b
|
||||||
root_a.ns2.TypeInNs2[<5] type_in_ns_2
|
root_a.ns2.TypeInNs2[<5] type_in_ns_2
|
||||||
|
|||||||
@@ -92,13 +92,14 @@ class CompoundType(Type):
|
|||||||
KIND_SERVICE = 0
|
KIND_SERVICE = 0
|
||||||
KIND_MESSAGE = 1
|
KIND_MESSAGE = 1
|
||||||
|
|
||||||
def __init__(self, full_name, kind, dsdl_signature, dsdl_path, default_dtid, filename):
|
def __init__(self, full_name, kind, dsdl_signature, dsdl_path, default_dtid, filename, source_text):
|
||||||
super().__init__(full_name, Type.CATEGORY_COMPOUND)
|
super().__init__(full_name, Type.CATEGORY_COMPOUND)
|
||||||
self.dsdl_signature = dsdl_signature
|
self.dsdl_signature = dsdl_signature
|
||||||
self.dsdl_path = dsdl_path
|
self.dsdl_path = dsdl_path
|
||||||
self.default_dtid = default_dtid
|
self.default_dtid = default_dtid
|
||||||
self.kind = kind
|
self.kind = kind
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
|
self.source_text = source_text
|
||||||
max_bitlen_sum = lambda fields: sum([x.type.get_max_bitlen() for x in fields])
|
max_bitlen_sum = lambda fields: sum([x.type.get_max_bitlen() for x in fields])
|
||||||
if kind == CompoundType.KIND_SERVICE:
|
if kind == CompoundType.KIND_SERVICE:
|
||||||
self.request_fields = []
|
self.request_fields = []
|
||||||
@@ -362,10 +363,10 @@ class Parser:
|
|||||||
try:
|
try:
|
||||||
filename = os.path.abspath(filename)
|
filename = os.path.abspath(filename)
|
||||||
with open(filename) as f:
|
with open(filename) as f:
|
||||||
text = f.read()
|
source_text = f.read()
|
||||||
|
|
||||||
full_typename, default_dtid = self._full_typename_and_dtid_from_filename(filename)
|
full_typename, default_dtid = self._full_typename_and_dtid_from_filename(filename)
|
||||||
numbered_lines = list(self._tokenize(text))
|
numbered_lines = list(self._tokenize(source_text))
|
||||||
all_attributes_names = set()
|
all_attributes_names = set()
|
||||||
fields, constants, resp_fields, resp_constants = [], [], [], []
|
fields, constants, resp_fields, resp_constants = [], [], [], []
|
||||||
response_part = False
|
response_part = False
|
||||||
@@ -396,7 +397,7 @@ class Parser:
|
|||||||
dsdl_signature = self._compute_dsdl_signature(full_typename, fields, constants,
|
dsdl_signature = self._compute_dsdl_signature(full_typename, fields, constants,
|
||||||
resp_fields, resp_constants)
|
resp_fields, resp_constants)
|
||||||
typedef = CompoundType(full_typename, CompoundType.KIND_SERVICE, dsdl_signature, filename,
|
typedef = CompoundType(full_typename, CompoundType.KIND_SERVICE, dsdl_signature, filename,
|
||||||
default_dtid, filename)
|
default_dtid, filename, source_text)
|
||||||
typedef.request_fields = fields
|
typedef.request_fields = fields
|
||||||
typedef.request_constants = constants
|
typedef.request_constants = constants
|
||||||
typedef.response_fields = resp_fields
|
typedef.response_fields = resp_fields
|
||||||
@@ -406,7 +407,7 @@ class Parser:
|
|||||||
else:
|
else:
|
||||||
dsdl_signature = self._compute_dsdl_signature(full_typename, fields, constants)
|
dsdl_signature = self._compute_dsdl_signature(full_typename, fields, constants)
|
||||||
typedef = CompoundType(full_typename, CompoundType.KIND_MESSAGE, dsdl_signature, filename,
|
typedef = CompoundType(full_typename, CompoundType.KIND_MESSAGE, dsdl_signature, filename,
|
||||||
default_dtid, filename)
|
default_dtid, filename, source_text)
|
||||||
typedef.fields = fields
|
typedef.fields = fields
|
||||||
typedef.constants = constants
|
typedef.constants = constants
|
||||||
max_bitlen = typedef.get_max_bitlen()
|
max_bitlen = typedef.get_max_bitlen()
|
||||||
|
|||||||
Reference in New Issue
Block a user