mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-20 00:51:42 +00:00
Quite a few functions aren't wrapped, but the most critical ones for vision should be. This also fixes a couple of issues: - nivision_arm.ini (and imaqdx_arm.ini) are now generated without need for running the output on the RoboRIO. - enum values are generated even if the value is not directly specified.
227 lines
8.2 KiB
Python
227 lines
8.2 KiB
Python
from __future__ import print_function
|
|
import re
|
|
import traceback
|
|
|
|
__all__ = ["define_after_struct", "defined", "forward_structs", "opaque_structs", "enums", "structs", "prescan_file", "parse_file", "number_re", "constant_re"]
|
|
|
|
# parser regular expressions
|
|
number_re = re.compile(r'-?[0-9]+')
|
|
constant_re = re.compile(r'[A-Z0-9_]+')
|
|
define_re = re.compile(r'^#define\s+(?P<name>(IMAQ|ERR)[A-Z0-9_]+)\s+(?P<value>.*)')
|
|
enum_re = re.compile(r'^typedef\s+enum\s+(?P<name>[A-Za-z0-9]+)_enum\s*{')
|
|
enum_value_re = re.compile(r'^\s*(?P<name>[A-Za-z0-9_]+)\s*(=\s*(?P<value>-?[0-9A-Fx]+))?\s*,?')
|
|
struct_re = re.compile(r'^typedef\s+struct\s+(?P<name>[A-Za-z0-9]+)_struct\s*{')
|
|
union_re = re.compile(r'^typedef\s+union\s+(?P<name>[A-Za-z0-9]+)_union\s*{')
|
|
func_pointer_re = re.compile(r'\s*(?P<restype>[A-Za-z0-9_*]+)\s*\(\s*[A-Za-z0-9_]*\s*[*]\s*(?P<name>[A-Za-z0-9_]+)\s*\)\s*\((?P<params>[^)]*)\)')
|
|
static_const_re = re.compile(r'^static\s+const\s+(?P<type>[A-Za-z0-9_]+)\s+(?P<name>[A-Za-z0-9_]+)\s*=\s*(?P<value>[^;]+);')
|
|
function_re = re.compile(r'^((IMAQ|NI)_FUNC\s+)?(?P<restype>(const\s+)?[A-Za-z0-9_*]+)\s+((IMAQ_STDCALL|NI_FUNC[C]?)\s+)?(?P<name>[A-Za-z0-9_]+)\s*\((?P<params>[^)]*)\);')
|
|
|
|
# defines deferred until after structures
|
|
define_after_struct = []
|
|
defined = set()
|
|
forward_structs = set()
|
|
opaque_structs = set()
|
|
enums = set()
|
|
structs = set()
|
|
|
|
def parse_cdecl(decl):
|
|
decl = " ".join(decl.split())
|
|
ctype, sep, name = decl.rpartition(' ')
|
|
# look for array[]
|
|
name, bracket, arr = name.partition('[')
|
|
if arr:
|
|
arr = arr[:-1]
|
|
else:
|
|
arr = None
|
|
return name, ctype, arr
|
|
|
|
def split_comment(line):
|
|
if line.startswith('/*'):
|
|
return "", ""
|
|
parts = line.split('//', 1)
|
|
code = parts[0].strip()
|
|
comment = parts[1].strip() if len(parts) > 1 else None
|
|
return code, comment
|
|
|
|
def prescan_file(f):
|
|
for line in f:
|
|
code, comment = split_comment(line)
|
|
if not code and not comment:
|
|
continue
|
|
|
|
# typedef struct {
|
|
m = struct_re.match(code)
|
|
if m is not None:
|
|
structs.add(m.group('name'))
|
|
continue
|
|
|
|
# other typedef
|
|
if code.startswith("typedef"):
|
|
if '(' in code:
|
|
continue
|
|
name, typedef, arr = parse_cdecl(code[8:-1])
|
|
if typedef.startswith("struct"):
|
|
forward_structs.add(name)
|
|
continue
|
|
|
|
opaque_structs.update(forward_structs - structs)
|
|
|
|
def parse_file(emit, f, block_comment_exclude):
|
|
in_block_comment = False
|
|
cur_block = ""
|
|
in_enum = None
|
|
in_struct = None
|
|
in_union = None
|
|
|
|
for lineno, line in enumerate(f):
|
|
code, comment = split_comment(line)
|
|
if not code and not comment:
|
|
continue
|
|
#print(comment)
|
|
|
|
# in block comment
|
|
if in_block_comment:
|
|
if not code and comment is not None and comment[0] == '=':
|
|
# closing block comment; emit if not excluded
|
|
if cur_block not in block_comment_exclude:
|
|
try:
|
|
emit.block_comment(cur_block)
|
|
except Exception as e:
|
|
print("%d: exception in block_comment():\n%s" % (lineno+1, traceback.format_exc()))
|
|
in_block_comment = False
|
|
# emit "after struct" constants in Globals
|
|
if cur_block == "Globals":
|
|
for dname, dtext in define_after_struct:
|
|
try:
|
|
emit.text(dtext)
|
|
except Exception as e:
|
|
print("%d: exception in text():\n%s" % (lineno+1, traceback.format_exc()))
|
|
defined.add(dname)
|
|
continue
|
|
if not code and comment is not None:
|
|
# remember current block
|
|
cur_block = comment
|
|
continue
|
|
|
|
# inside enum
|
|
if in_enum is not None:
|
|
if code[0] == '}':
|
|
# closing
|
|
try:
|
|
emit.enum(*in_enum)
|
|
except Exception as e:
|
|
print("%d: exception in enum():\n%s" % (lineno+1, traceback.format_exc()))
|
|
in_enum = None
|
|
continue
|
|
m = enum_value_re.match(code)
|
|
if m is not None:
|
|
in_enum[1].append((m.group('name'), m.group('value'), comment))
|
|
continue
|
|
|
|
# inside struct/union
|
|
if in_struct is not None or in_union is not None:
|
|
if code[0] == '}':
|
|
# closing
|
|
if in_struct is not None:
|
|
try:
|
|
emit.struct(*in_struct)
|
|
except Exception as e:
|
|
print("%d: exception in struct(\"%s\"):\n%s" % (lineno+1, in_struct[0], traceback.format_exc()))
|
|
in_struct = None
|
|
if in_union is not None:
|
|
try:
|
|
emit.union(*in_union)
|
|
except Exception as e:
|
|
print("%d: exception in union(\"%s\"):\n%s" % (lineno+1, in_union[0], traceback.format_exc()))
|
|
in_union = None
|
|
continue
|
|
name, ctype, arr = parse_cdecl(code[:-1])
|
|
# add to fields
|
|
if in_struct is not None:
|
|
in_struct[1].append((name, ctype, arr, comment))
|
|
if in_union is not None:
|
|
in_union[1].append((name, ctype, arr, comment))
|
|
continue
|
|
|
|
# block comment
|
|
if not code and comment is not None and comment[0] == '=':
|
|
in_block_comment = True
|
|
|
|
# #define
|
|
m = define_re.match(code)
|
|
if m is not None:
|
|
try:
|
|
emit.define(m.group('name'), m.group('value').strip(), comment)
|
|
except Exception as e:
|
|
print("%d: exception in define():\n%s" % (lineno+1, traceback.format_exc()))
|
|
continue
|
|
|
|
# typedef enum {
|
|
m = enum_re.match(code)
|
|
if m is not None:
|
|
in_enum = (m.group('name'), [])
|
|
continue
|
|
|
|
# typedef struct {
|
|
m = struct_re.match(code)
|
|
if m is not None:
|
|
in_struct = (m.group('name'), [])
|
|
continue
|
|
|
|
# typedef union {
|
|
m = union_re.match(code)
|
|
if m is not None:
|
|
in_union = (m.group('name'), [])
|
|
continue
|
|
|
|
# other typedef
|
|
if code.startswith("typedef"):
|
|
# typedef function?
|
|
m = func_pointer_re.match(code[8:-1])
|
|
if m is not None:
|
|
params = [parse_cdecl(param.strip()) for param in m.group('params').strip().split(',') if param.strip()]
|
|
try:
|
|
emit.typedef_function(m.group('name'), m.group('restype'), params)
|
|
except Exception as e:
|
|
print("%d: exception in typedef_function():\n%s" % (lineno+1, traceback.format_exc()))
|
|
continue
|
|
if '(' in code:
|
|
print("Invalid typedef: %s" % code)
|
|
continue
|
|
emit.typedef(*parse_cdecl(code[8:-1]))
|
|
continue
|
|
|
|
# function
|
|
m = function_re.match(code)
|
|
if m is not None:
|
|
params = [parse_cdecl(param.strip()) for param in m.group('params').strip().split(',') if param.strip()]
|
|
try:
|
|
emit.function(m.group('name'), m.group('restype'), params)
|
|
except Exception as e:
|
|
print("%d: exception in function(\"%s\"):\n%s" % (lineno+1, m.group('name'), traceback.format_exc()))
|
|
continue
|
|
|
|
# static const
|
|
m = static_const_re.match(code)
|
|
if m is not None:
|
|
value = m.group('value')
|
|
if value[0] == '{':
|
|
value = [v.strip() for v in value[1:-1].strip().split(',') if v.strip()]
|
|
try:
|
|
emit.static_const(m.group('name'), m.group('type'), value)
|
|
except Exception as e:
|
|
print("%d: exception in static_const():\n%s" % (lineno+1, traceback.format_exc()))
|
|
continue
|
|
|
|
if not code or code[0] == '#':
|
|
continue
|
|
|
|
if not code or code[0] == '#':
|
|
continue
|
|
|
|
if code == 'extern "C" {' or code == "}":
|
|
continue
|
|
|
|
print("%d: Unrecognized: %s" % (lineno+1, code))
|
|
|