Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r41:a913f8ec3a30 Date: 2014-09-16 09:13 +0200 http://bitbucket.org/cffi/creflect/changeset/a913f8ec3a30/
Log: Const pointers diff --git a/creflect/cparser.py b/creflect/cparser.py --- a/creflect/cparser.py +++ b/creflect/cparser.py @@ -136,10 +136,10 @@ realtype = self._get_type(decl.type, name=decl.name) self.declarations.append(model.TypeDef(decl.name, realtype)) - def _get_type_pointer(self, type): + def _get_type_pointer(self, type, const): if isinstance(type, model.RawFunctionType): return type.as_function_pointer() - return model.PointerType(type) + return model.PointerType(type, const) def _get_type(self, typenode, name=None, partial_length_ok=False): # first, dereference typedefs, if we have it already parsed, we're good @@ -162,7 +162,8 @@ # if isinstance(typenode, pycparser.c_ast.PtrDecl): # pointer type - return self._get_type_pointer(self._get_type(typenode.type)) + const = 'const' in typenode.quals + return self._get_type_pointer(self._get_type(typenode.type), const) # if isinstance(typenode, pycparser.c_ast.TypeDecl): const = 'const' in typenode.quals diff --git a/creflect/model.py b/creflect/model.py --- a/creflect/model.py +++ b/creflect/model.py @@ -150,16 +150,18 @@ class PointerType(BaseType): _attrs_ = ('totype',) - _base_pattern = "*&" - _base_pattern_array = "(*&)" + _base_pattern = { + (False, False): "*&", + (True, False): "(*&)", + (False, True): "*const &", + (True, True): "(*const &)", + } - def __init__(self, totype): + def __init__(self, totype, const): self.totype = totype + self.const = const base = self.totype.c_name_with_marker - if self.totype.is_array_type: - extra = self._base_pattern_array - else: - extra = self._base_pattern + extra = self._base_pattern[self.totype.is_array_type, self.const] self.c_name_with_marker = base.replace('&', extra) def inspect_type(self, block, inspect): @@ -167,12 +169,28 @@ new_var = 'p%d' % (len(inspect.levels) + 2,) block.writedecl("char *%s;" % (new_var,)) inspect.assign_to_p1("&%s" % (new_var,)) + # + if self.const: + errmsg = "type '%s' is not a pointer, but an array type" % ( + inspect.get_comment_type(0, False),) + inspect.assign_target = new_var + def after(): + ampersand_star_p1 = '&' + star_p1 + if ampersand_star_p1.startswith('&*'): + ampersand_star_p1 = ampersand_star_p1[2:] + block.writeline("if ((void *)%s == (void *)%s) {" % ( + ampersand_star_p1, star_p1)) + block.writeline(" r = r0;") + block.sprintf(r"#error %s\n" % errmsg, indent=4) + block.tr.need_return_value() + block.writeline(" r1 = -1;") + block.writeline(" goto %s;" % block.get_skip_label()) + block.writeline("}") + inspect.after_star_p1_assignment.append(after) inspect.levels.append('*') self.totype.inspect_type(block, inspect) - if self.totype.is_array_type: - extra = self._base_pattern_array - else: - extra = self._base_pattern + # + extra = self._base_pattern[self.totype.is_array_type, self.const] block.sprintf_add_both_sides(extra) @@ -292,6 +310,7 @@ self.started = True self.after_star_p1_assignment = [] self.at_end = [] + self.assign_target = None def get_comment_type(self, levels_delta, ignore_array, minlevel=0): end = len(self.levels) @@ -333,20 +352,25 @@ return star_p1 def assign_to_p1(self, expr): - length = len(self.levels) - while length > 0 and self.levels[length - 1] == '[]': - length -= 1 - comment = self.get_comment(-1, True, "a pointer type") - spaces = comment and (' ' * (3 - len(expr))) + if self.assign_target is None: + length = len(self.levels) + while length > 0 and self.levels[length - 1] == '[]': + length -= 1 + comment = self.get_comment(-1, True, "a pointer type") + spaces = comment and (' ' * (3 - len(expr))) + self.assign_target = '%sp1' % ('*' * length,) + else: + spaces = comment = '' if self.structfield is None: - line = '%sp1 = (void *)%s;%s%s' % ('*' * length, expr, spaces, - comment) + line = '%s = (void *)%s;%s%s' % (self.assign_target, expr, spaces, + comment) else: if length > 0: line = '%sp1->%s = (void *)%s;%s%s' % ( '*' * (length - 1), self.structfield, expr, spaces, comment) else: line = 'p1 = (void *)(((char *)%s) - (long)o);' % (expr,) + self.assign_target = None self.block.writeline(line.rstrip()) for fn in self.after_star_p1_assignment: fn() diff --git a/test/codegen/006b.c b/test/codegen/006b.c new file mode 100644 --- /dev/null +++ b/test/codegen/006b.c @@ -0,0 +1,60 @@ +typedef int *const num_t; + +# ____________________________________________________________ + +int test006b(char *r) +{ + int r1 = 0; + if (!r) + return 57 + 8 + 18 + 16; + { + num_t *p1; + char *p2; + char b[sizeof(**p1)]; /* check that '*num_t' is a valid type */ + char *r0 = r; + p1 = (void *)&p2; + p2 = (void *)b; + if ((void *)p1 == (void *)*p1) { + r = r0; + r += sprintf(r, "#error type 'num_t' is not a pointer, but an array type\n"); + r1 = -1; + goto f2; + } + (void)(**p1 << 1); /* check that '*num_t' is an integer type */ + r += sprintf(r, "typedef "); + **p1 = -1; /* check that '*num_t' is not declared 'const' */ + if (**p1 > 0) { + if (sizeof(**p1) == 1 && **p1 == 1) + r += sprintf(r, "_Bool"); + else if (sizeof(**p1) == sizeof(unsigned int)) + r += sprintf(r, "unsigned int"); + else if (sizeof(**p1) == sizeof(unsigned short)) + r += sprintf(r, "unsigned short"); + else if (sizeof(**p1) == sizeof(unsigned char)) + r += sprintf(r, "unsigned char"); + else if (sizeof(**p1) == sizeof(unsigned long)) + r += sprintf(r, "unsigned long"); + else if (sizeof(**p1) == sizeof(unsigned long long)) + r += sprintf(r, "unsigned long long"); + else + r += sprintf(r, "uint%u_t", (int)sizeof(**p1) * 8); + } + else { + if (sizeof(**p1) == sizeof(int)) + r += sprintf(r, "int"); + else if (sizeof(**p1) == sizeof(short)) + r += sprintf(r, "short"); + else if (sizeof(**p1) == sizeof(signed char)) + r += sprintf(r, "signed char"); + else if (sizeof(**p1) == sizeof(long)) + r += sprintf(r, "long"); + else if (sizeof(**p1) == sizeof(long long)) + r += sprintf(r, "long long"); + else + r += sprintf(r, "int%u_t", (int)sizeof(**p1) * 8); + } + r += sprintf(r, " *const num_t;\n"); + f2:; + } + return r1; +} diff --git a/test/codegen/006c.c b/test/codegen/006c.c new file mode 100644 --- /dev/null +++ b/test/codegen/006c.c @@ -0,0 +1,66 @@ +typedef int (*const foo_t)[27]; + +# ____________________________________________________________ + +int test006c(char *r) +{ + int r1 = 0; + if (!r) + return 57 + 58 + 8 + 18 + 44; + { + foo_t *p1; + char *p2; + char b[sizeof(***p1)]; /* check that '(*foo_t)[]' is a valid type */ + char *r0 = r; + p1 = (void *)&p2; + p2 = (void *)b; + if ((void *)p1 == (void *)*p1) { + r = r0; + r += sprintf(r, "#error type 'foo_t' is not a pointer, but an array type\n"); + r1 = -1; + goto f2; + } + if ((void *)*p1 != (void *)**p1) { + r = r0; + r += sprintf(r, "#error type '*foo_t' is not an array, but a pointer type\n"); + r1 = -1; + goto f2; + } + (void)(***p1 << 1); /* check that '(*foo_t)[]' is an integer type */ + r += sprintf(r, "typedef "); + ***p1 = -1; /* check that '(*foo_t)[]' is not declared 'const' */ + if (***p1 > 0) { + if (sizeof(***p1) == 1 && ***p1 == 1) + r += sprintf(r, "_Bool"); + else if (sizeof(***p1) == sizeof(unsigned int)) + r += sprintf(r, "unsigned int"); + else if (sizeof(***p1) == sizeof(unsigned short)) + r += sprintf(r, "unsigned short"); + else if (sizeof(***p1) == sizeof(unsigned char)) + r += sprintf(r, "unsigned char"); + else if (sizeof(***p1) == sizeof(unsigned long)) + r += sprintf(r, "unsigned long"); + else if (sizeof(***p1) == sizeof(unsigned long long)) + r += sprintf(r, "unsigned long long"); + else + r += sprintf(r, "uint%u_t", (int)sizeof(***p1) * 8); + } + else { + if (sizeof(***p1) == sizeof(int)) + r += sprintf(r, "int"); + else if (sizeof(***p1) == sizeof(short)) + r += sprintf(r, "short"); + else if (sizeof(***p1) == sizeof(signed char)) + r += sprintf(r, "signed char"); + else if (sizeof(***p1) == sizeof(long)) + r += sprintf(r, "long"); + else if (sizeof(***p1) == sizeof(long long)) + r += sprintf(r, "long long"); + else + r += sprintf(r, "int%u_t", (int)sizeof(***p1) * 8); + } + r += sprintf(r, " (*const foo_t)[%lld];\n", (long long)(sizeof(**p1) / sizeof(***p1))); + f2:; + } + return r1; +} _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit