From 876bf28031ff65be89e3d3bc173a0ea16df75af4 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Tue, 17 Nov 2009 17:24:36 -0500 Subject: Fix various cases when parsing types Fix the following cases: - tuples - 'L' and 'K' - 'D' - 's#' and 'z#' - 'et#' - 'w' and its variants Simplify type comparison by stripping off "const" and signedness modifiers from the front of types --- validate.py | 55 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/validate.py b/validate.py index 6d50921..5fdf92a 100644 --- a/validate.py +++ b/validate.py @@ -66,7 +66,8 @@ def get_types(location, strfmt): else: next = None - # FIXME: '(', ')' tuple support + if c in ['(', ')']: + continue if c in [':', ';']: break @@ -84,10 +85,11 @@ def get_types(location, strfmt): 'n':'Py_ssize_t', 'l':'long', 'k':'unsigned long', - # L, K: FIXME + 'L':'PY_LONG_LONG', + 'K':'unsigned PY_LONG_LONG', 'f':'float', 'd':'double', - # D: FIXME, + 'D':'Py_complex', 'c':'char', } if c in simple: @@ -95,7 +97,10 @@ def get_types(location, strfmt): elif c in ['s', 'z']: # string, possibly NULL/None if next == '#': - result += ['const char * *', 'int *'] + if True: # FIXME: is PY_SSIZE_T_CLEAN defined? + result += ['const char * *', 'Py_ssize_t *'] + else: + result += ['const char * *', 'int *'] i += 1 elif next == '*': result.append('Py_buffer *') @@ -112,6 +117,7 @@ def get_types(location, strfmt): if i < len(strfmt): if strfmt[i] == '#': result.append('int *') + i+=1 elif c == 'S': result.append('PyObject * *') elif c == 'U': @@ -130,7 +136,14 @@ def get_types(location, strfmt): else: result.append('PyObject * *') elif c == 'w': - raise UnhandledCode(location, strfmt, c) # FIXME + if next == '#': + result += ['char * *', 'Py_ssize_t *'] + i += 1 + elif next == '*': + result.append('Py_buffer *') + i += 1 + else: + result.append('char * *') elif c == 't': if next == '#': result += ['char * *', 'int *'] @@ -176,21 +189,24 @@ class MismatchingType(FormatStringError): self.exp_type, self.actual_type) +def strip_prefix(t, prefix): + if t.startswith(prefix): + return t[len(prefix):] + else: + return t -def type_equality(t1, t2): - if t1 == t2: - return True - +def simplify_type(t): # do we really care about char/const char mismatches?: - if t1.startswith('const char *'): - if t1 == 'const '+t2: - return True - if t2.startswith('const char *'): - if 'const '+t1 == t2: - return True + t = strip_prefix(t, 'signed ') + t = strip_prefix(t, 'unsigned ') + t = strip_prefix(t, 'const ') + return t - return False +def type_equality(t1, t2): + t1 = simplify_type(t1) + t2 = simplify_type(t2) + return t1 == t2 def validate_type(location, format_string, index, actual_num_args, actual_type): if False: @@ -243,6 +259,13 @@ class TestArgParsing(unittest.TestCase): 'int *', 'int *']) + def test_posixmodule_listdir(self): + self.assert_args("et#:listdir", + ['const char *', 'char * *', 'int *']) + + def test_bsddb_DBSequence_set_range(self): + self.assert_args("(LL):set_range", + ['PY_LONG_LONG *', 'PY_LONG_LONG *']) if __name__ == '__main__': unittest.main() -- cgit