mescc: Tinycc support: support foo.bar[baz], foo->bar[baz] for struct bar.
authorJan Nieuwenhuizen <janneke@gnu.org>
Tue, 1 Aug 2017 09:26:00 +0000 (11:26 +0200)
committerJan Nieuwenhuizen <janneke@gnu.org>
Tue, 1 Aug 2017 09:26:00 +0000 (11:26 +0200)
* module/language/c99/compiler.mes (struct-field): Use negative
  pointer for struct array fields.
  (expr->accu): support: support foo.bar[baz], foo->bar[baz] for struct bar.
* scaffold/tests/7c-dynarray.c: Test it.

make.scm
module/language/c99/compiler.mes
scaffold/tests/7c-dynarray.c [new file with mode: 0644]

index f86dc99dc254c5ca965924838d8e639ecf034209..7c5d28839b642a51a9d1aca9e79262cbdd1a0891 100755 (executable)
--- a/make.scm
+++ b/make.scm
@@ -161,7 +161,8 @@ exec ${GUILE-guile} --no-auto-compile -L . -L guile -C . -C guile -s "$0" ${1+"$
    "78-union-struct"
    "79-int-array"
    "7a-struct-char-array"
-   "7b-struct-int-array"))
+   "7b-struct-int-array"
+   "7c-dynarray"))
 
 (add-target (group "check-scaffold-tests/7" #:dependencies (filter (target-prefix? "check-scaffold/tests/7") %targets)))
 
index 55bea4a8aa9e6429b241ad6791972e0e5e22ed39..36cd72cd59b015fcd6b4fb3237cb5fdf189ca28c 100644 (file)
          (let* ((info ((expr->accu* info) o))
                 (type0 (ident->type info struct0))
                 (type1 (field-type info type0 field0))
+                (struct? (and (pair? type1) (equal? (car type1) "tag")))
+                (ptr (field-pointer info type0 field0))
                 (size (ast-type->size info type1)))
-           (append-text info (wrap-as (if (= size 1) (i386:byte-mem->accu)
-                                          (i386:mem->accu))))))
+           (if (= ptr -3) info
+               (append-text info (wrap-as (append (if (and (= ptr -2) struct?) (i386:mem->accu) '())
+                                                  (if (= size 1) (i386:byte-mem->accu)
+                                                      (i386:mem->accu))))))))
 
         ;; foo->bar[baz])
         ((array-ref ,index (i-sel (ident ,field0) (p-expr (ident ,struct0))))
          (let* ((info ((expr->accu* info) o))
                 (type0 (ident->type info struct0))
                 (type1 (field-type info type0 field0))
+                (struct? (and (pair? type1) (equal? (car type1) "tag")))
+                (ptr (field-pointer info type0 field0))
                 (size (ast-type->size info type1)))
-           (append-text info (wrap-as (if (= size 1) (i386:byte-mem->accu)
-                                          (i386:mem->accu))))))
+           (append-text info (wrap-as (append (if (and (= ptr -2) struct?) (i386:mem->accu) '())
+                                              (if (= size 1) (i386:byte-mem->accu)
+                                                  (i386:mem->accu)))))))
 
         ;; <expr>[baz]
         ((array-ref ,index ,array)
              (count (p-expr->number info count)))
          (list name type (* count size) -1)))
       ((comp-decl (decl-spec-list (type-spec (struct-ref (ident (,type))))) (comp-declr-list (comp-declr (ptr-declr (pointer (pointer)) (ident ,name)))))
-       (list name `("tag" ,type) 4 2))
+       (list name `("tag" ,type) 4 -2))
 
       ((comp-decl (decl-spec-list (type-spec (struct-ref (ident ,type)))) (comp-declr-list (comp-declr (ptr-declr (pointer (pointer)) (ident ,name)))))
-       (list name `("tag" ,type) 4 2))
+       (list name `("tag" ,type) 4 -2))
 
       ((comp-decl (decl-spec-list (type-spec (struct-ref (ident (,type))))) (comp-declr-list (comp-declr (ptr-declr (pointer) (ident ,name)))))
        (list name `("tag" ,type) 4 1))
diff --git a/scaffold/tests/7c-dynarray.c b/scaffold/tests/7c-dynarray.c
new file mode 100644 (file)
index 0000000..71fe72a
--- /dev/null
@@ -0,0 +1,100 @@
+/* -*-comment-start: "//";comment-end:""-*-
+ * Mes --- Maxwell Equations of Software
+ * Copyright © 2017 Jan Nieuwenhuizen <janneke@gnu.org>
+ *
+ * This file is part of Mes.
+ *
+ * Mes is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * Mes is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Mes.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "30-test.i"
+
+#include <mlibc.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+void
+add (void *ptab, int *nb_ptr, void *data)
+{
+    int nb, nb_alloc;
+    int **pp;
+
+    nb = *nb_ptr;
+    pp = *(void ***)ptab;
+    /* every power of two we double array size */
+    if ((nb & (nb - 1)) == 0) {
+        if (!nb)
+            nb_alloc = 1;
+        else
+            nb_alloc = nb * 2;
+          pp = realloc (pp, nb_alloc * sizeof(void *));
+        *(void***)ptab = pp;
+    }
+    pp[nb++] = data;
+    *nb_ptr = nb;
+}
+
+struct file {
+  char name[4];
+};
+
+struct state {
+  char **paths;
+  int path_count;
+  struct file **files;
+  int file_count;
+};
+
+struct state g_s;
+
+int
+test ()
+{
+  struct state *s = &g_s;
+
+  char* file_name = "file-name";
+  struct file *file;
+
+  file = malloc (sizeof (struct file) + strlen (file_name));
+  strcpy (file->name, file_name);
+  add (&s->files, &s->file_count, file);
+
+  char *path_name = "foo:bar:baz";
+  add (&s->paths, &s->path_count, path_name);
+
+  if (strcmp (*s->paths, path_name)) return 1;
+
+  eputs ("&PATHS="); eputs (itoa (&s->paths)); eputs ("\n");
+  eputs ("&FILES="); eputs (itoa (&s->files)); eputs ("\n");
+
+  struct file *fs = s->files[0];
+  eputs ("add s=   "); eputs (itoa (s)); eputs ("\n");
+  eputs ("add fs=  "); eputs (itoa (fs)); eputs ("\n");
+  eputs ("&fs->[0]="); eputs (itoa (fs->name)); eputs ("\n");
+  eputs ("fs->name="); eputs (fs->name); eputs ("\n");
+
+  eputs ("ps=      "); eputs (itoa (s->paths)); eputs ("\n");
+  eputs ("*ps      "); eputs (*s->paths); eputs ("\n");
+
+  if (strcmp (fs->name, file_name)) return 1;
+  
+  eputs ("&fs->[0]="); eputs (itoa (fs->name)); eputs ("\n");
+  eputs ("fs->name="); eputs (fs->name); eputs ("\n");
+
+  eputs ("ps=      "); eputs (itoa (s->paths)); eputs ("\n");
+  eputs ("*ps      "); eputs (*s->paths); eputs ("\n");
+
+  return 0;
+}