[pypy-commit] creflect default: Const pointers

arigo noreply at buildbot.pypy.org
Tue Sep 16 09:13:38 CEST 2014


Author: Armin Rigo <arigo at 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;
+}


More information about the pypy-commit mailing list