vlc/python | branch: master | Alberto Invernizzi <[email protected]> | Tue Apr 21 23:01:17 2020 +0200| [7b8704b2103fb7fb97fedf81b42acb3822437809] | committer: Alberto Invernizzi
fixes and changes - improvement for function pointer regex - improvements for Par parse_param - refactored parse_param as Par classmethod > http://git.videolan.org/gitweb.cgi/vlc/python.git/?a=commit;h=7b8704b2103fb7fb97fedf81b42acb3822437809 --- generator/generate.py | 151 +++++++++++++++++++++++++------------------------- 1 file changed, 76 insertions(+), 75 deletions(-) diff --git a/generator/generate.py b/generator/generate.py index c4b3e00..06543cb 100755 --- a/generator/generate.py +++ b/generator/generate.py @@ -156,7 +156,7 @@ callback_type_re = re.compile(r'^typedef\s+\w+(\s*\*)?\s*\(\s*\*') callback_re = re.compile(r'typedef\s+\*?(\w+\s*\*?)\s*\(\s*\*\s*(\w+)\s*\)\s*\((.+)\);') struct_type_re = re.compile(r'^typedef\s+struct\s*(\S+)\s*$') struct_re = re.compile(r'typedef\s+(struct)\s*(\S+)?\s*\{\s*(.+)\s*\}\s*(?:\S+)?\s*;') -func_pointer_re = re.compile(r'(\(?[^\(]+)\s+\((\*\s*\S*)\)(\(.*\))') # (ret_type, *pointer_name, ([params])) +func_pointer_re = re.compile(r'(\(?[^\(]+)\s*\((\*\s*\S*)\)(\(.*\))') # (ret_type, *pointer_name, ([params])) typedef_re = re.compile(r'^typedef\s+(?:struct\s+)?(\S+)\s+(\S+);') forward_re = re.compile(r'.+\(\s*(.+?)\s*\)(\s*\S+)') libvlc_re = re.compile(r'libvlc_[a-z_]+') @@ -442,6 +442,77 @@ class Par(object): else: # see ctypes 15.16.2.4 Function prototypes return f, self.name, default #PYCHOK expected + @classmethod + def parse_param(cls, param_raw): + """Parse a C parameter expression. + + It is used to parse the type/name of functions + and type/name of the function parameters. + + @return: a Par instance. + """ + param_raw = param_raw.strip() + if _VLC_FORWARD_ in param_raw: + m = forward_re.match(param_raw) + param_raw = m.group(1) + m.group(2) + + # is this a function pointer? + if func_pointer_re.search(param_raw): + return None + + # is this parameter a pointer? + split_pointer = param_raw.split('*') + if len(split_pointer) > 1: + param_type = split_pointer[0] + param_name = split_pointer[-1].split(' ')[-1] + param_deref_levels = len(split_pointer) - 1 + + # it is a pointer, so it should have at least 1 level of indirection + assert(param_deref_levels > 0) + + # POINTER SEMANTIC + constness = split_pointer[:-1] + constness += ['const' if len(split_pointer[-1].strip().split(' ')) > 1 else ''] + param_constness = ['const' in deref_level for deref_level in constness] + + # PARAM TYPE + param_type = split_pointer[0].replace('const ', '').strip() + # remove the struct keyword, this information is currently not used + param_type = param_type.replace('struct ', '').strip() + + # add back the information of how many dereference levels there are + param_type += '*' * param_deref_levels + + # ASSUMPTION + # just indirection level 0 and 1 can be const + for deref_level_constness in param_constness[2:]: assert(not deref_level_constness) + # ... or is it a simple variable? + else: + # WARNING: workaround for "union { struct {" + param_raw = param_raw.split('{')[-1] + + # ASSUMPTIONs + # these allows to constrain param_raw to these options: + # - named: "type name" (e.g. "int param") + # - anonymous: "type" (e.g. "int") + assert('struct' not in param_raw) + assert('const' not in param_raw) + + # normalize spaces + param_raw = re.sub('\s+', ' ', param_raw) + + split_value = param_raw.split(' ') + if len(split_value) > 1: + param_name = split_value[-1] + param_type = ' '.join(split_value[:-1]) + else: + param_type = split_value[0] + param_name = '' + + param_constness = [False] + + return Par(param_name.strip(), param_type.strip(), param_constness) + class Val(object): """Enum name and value. """ @@ -531,7 +602,7 @@ class Parser(object): _blacklist[name] = type_ continue - pars = [self.parse_param(p) for p in paramlist_re.split(pars)] + pars = [Par.parse_param(p) for p in paramlist_re.split(pars)] yield Func(name, type_.replace(' ', '') + '*', pars, docs, file_=self.h_file, line=line) @@ -584,7 +655,7 @@ class Parser(object): @return: yield a Struct instance for each struct. """ for typ, name, body, docs, line in self.parse_groups(struct_type_re.match, struct_re.match, re.compile(r'^\}(\s*\S+)?\s*;$')): - fields = [ self.parse_param(t.strip()) for t in decllist_re.split(body) if t.strip() and not '%s()' % name in t ] + fields = [ Par.parse_param(t.strip()) for t in decllist_re.split(body) if t.strip() and not '%s()' % name in t ] fields = [ f for f in fields if f is not None ] name = name.strip() @@ -606,12 +677,12 @@ class Parser(object): for name, pars, docs, line in self.parse_groups(match_t, api_re.match, ');'): - f = self.parse_param(name) + f = Par.parse_param(name) if f.name in _blacklist: _blacklist[f.name] = f.type continue - pars = [self.parse_param(p) for p in paramlist_re.split(pars)] + pars = [Par.parse_param(p) for p in paramlist_re.split(pars)] if len(pars) == 1 and pars[0].type == 'void': pars = [] # no parameters @@ -700,76 +771,6 @@ class Parser(object): d = [] f.close() - def parse_param(self, param_raw): - """Parse a C parameter expression. - - It is used to parse the type/name of functions - and type/name of the function parameters. - - @return: a Par instance. - """ - param_raw = param_raw.strip() - if _VLC_FORWARD_ in param_raw: - m = forward_re.match(param_raw) - param_raw = m.group(1) + m.group(2) - - # is this a function pointer? - if func_pointer_re.search(param_raw): - return None - - # is this parameter a pointer? - split_pointer = param_raw.split('*') - if len(split_pointer) > 1: - param_type = split_pointer[0] - param_name = split_pointer[-1] - param_deref_levels = len(split_pointer) - 1 - - # it is a pointer, so it should have at least 1 level of indirection - assert(param_deref_levels > 0) - - # PARAM TYPE - param_type = split_pointer[0].replace('const', '').strip() - # remove the struct keyword, this information is currently not used - param_type = param_type.replace('struct ', '').strip() - - # POINTER SEMANTIC - # add back the information of how many dereference levels there are - param_type += '*' * param_deref_levels - - constness = ['const' in deref_level for deref_level in split_pointer] - - # ASSUMPTION - # just indirection level 0 and 1 can be const - for deref_level_constness in constness[2:]: assert(not deref_level_constness) - - param_constness = constness[:2] - # ... or is it a simple variable? - else: - # WARNING: workaround for "union { struct {" - param_raw = param_raw.split('{')[-1] - - # ASSUMPTIONs - # these allows to constrain param_raw to these options: - # - named: "type name" (e.g. "int param") - # - anonymous: "type" (e.g. "int") - assert('struct' not in param_raw) - assert('const' not in param_raw) - - # normalize spaces - param_raw = re.sub('\s+', ' ', param_raw) - - split_value = param_raw.split(' ') - if len(split_value) > 1: - param_name = split_value[-1] - param_type = ' '.join(split_value[:-1]) - else: - param_type = split_value[0] - param_name = '' - - param_constness = [False] - - return Par(param_name.strip(), param_type.strip(), param_constness) - def parse_version(self, h_files): """Get the libvlc version from the C header files: LIBVLC_VERSION_MAJOR, _MINOR, _REVISION, _EXTRA _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
