summaryrefslogtreecommitdiff
path: root/gcc/fortran/constructor.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/fortran/constructor.c')
-rw-r--r--gcc/fortran/constructor.c277
1 files changed, 277 insertions, 0 deletions
diff --git a/gcc/fortran/constructor.c b/gcc/fortran/constructor.c
new file mode 100644
index 000000000..9f2cd2628
--- /dev/null
+++ b/gcc/fortran/constructor.c
@@ -0,0 +1,277 @@
+/* Array and structure constructors
+ Copyright (C) 2009, 2010, 2011
+ Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC 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, or (at your option) any later
+version.
+
+GCC 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 GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "gfortran.h"
+#include "constructor.h"
+
+
+static void
+node_free (splay_tree_value value)
+{
+ gfc_constructor *c = (gfc_constructor*)value;
+
+ if (c->expr)
+ gfc_free_expr (c->expr);
+
+ if (c->iterator)
+ gfc_free_iterator (c->iterator, 1);
+
+ mpz_clear (c->offset);
+ mpz_clear (c->repeat);
+
+ gfc_free (c);
+}
+
+
+static gfc_constructor *
+node_copy (splay_tree_node node, void *base)
+{
+ gfc_constructor *c, *src = (gfc_constructor*)node->value;
+
+ c = XCNEW (gfc_constructor);
+ c->base = (gfc_constructor_base)base;
+ c->expr = gfc_copy_expr (src->expr);
+ c->iterator = gfc_copy_iterator (src->iterator);
+ c->where = src->where;
+ c->n.component = src->n.component;
+
+ mpz_init_set (c->offset, src->offset);
+ mpz_init_set (c->repeat, src->repeat);
+
+ return c;
+}
+
+
+static int
+node_copy_and_insert (splay_tree_node node, void *base)
+{
+ int n = mpz_get_si (((gfc_constructor*)node->value)->offset);
+ gfc_constructor_insert ((gfc_constructor_base*)base,
+ node_copy (node, base), n);
+ return 0;
+}
+
+
+gfc_constructor *
+gfc_constructor_get (void)
+{
+ gfc_constructor *c = XCNEW (gfc_constructor);
+ c->base = NULL;
+ c->expr = NULL;
+ c->iterator = NULL;
+
+ mpz_init_set_si (c->offset, 0);
+ mpz_init_set_si (c->repeat, 1);
+
+ return c;
+}
+
+gfc_constructor_base gfc_constructor_get_base (void)
+{
+ return splay_tree_new (splay_tree_compare_ints, NULL, node_free);
+}
+
+
+gfc_constructor_base
+gfc_constructor_copy (gfc_constructor_base base)
+{
+ gfc_constructor_base new_base;
+
+ if (!base)
+ return NULL;
+
+ new_base = gfc_constructor_get_base ();
+ splay_tree_foreach (base, node_copy_and_insert, &new_base);
+
+ return new_base;
+}
+
+
+void
+gfc_constructor_free (gfc_constructor_base base)
+{
+ if (base)
+ splay_tree_delete (base);
+}
+
+
+gfc_constructor *
+gfc_constructor_append (gfc_constructor_base *base, gfc_constructor *c)
+{
+ int offset = 0;
+ if (*base)
+ offset = (int)(splay_tree_max (*base)->key) + 1;
+
+ return gfc_constructor_insert (base, c, offset);
+}
+
+
+gfc_constructor *
+gfc_constructor_append_expr (gfc_constructor_base *base,
+ gfc_expr *e, locus *where)
+{
+ gfc_constructor *c = gfc_constructor_get ();
+ c->expr = e;
+ if (where)
+ c->where = *where;
+
+ return gfc_constructor_append (base, c);
+}
+
+
+gfc_constructor *
+gfc_constructor_insert (gfc_constructor_base *base, gfc_constructor *c, int n)
+{
+ splay_tree_node node;
+
+ if (*base == NULL)
+ *base = splay_tree_new (splay_tree_compare_ints, NULL, node_free);
+
+ c->base = *base;
+ mpz_set_si (c->offset, n);
+
+ node = splay_tree_insert (*base, (splay_tree_key) n, (splay_tree_value) c);
+ gcc_assert (node);
+
+ return (gfc_constructor*)node->value;
+}
+
+
+gfc_constructor *
+gfc_constructor_insert_expr (gfc_constructor_base *base,
+ gfc_expr *e, locus *where, int n)
+{
+ gfc_constructor *c = gfc_constructor_get ();
+ c->expr = e;
+ if (where)
+ c->where = *where;
+
+ return gfc_constructor_insert (base, c, n);
+}
+
+
+gfc_constructor *
+gfc_constructor_lookup (gfc_constructor_base base, int offset)
+{
+ gfc_constructor *c;
+ splay_tree_node node;
+
+ if (!base)
+ return NULL;
+
+ node = splay_tree_lookup (base, (splay_tree_key) offset);
+ if (node)
+ return (gfc_constructor *) node->value;
+
+ /* Check if the previous node has a repeat count big enough to
+ cover the offset looked for. */
+ node = splay_tree_predecessor (base, (splay_tree_key) offset);
+ if (!node)
+ return NULL;
+
+ c = (gfc_constructor *) node->value;
+ if (mpz_cmp_si (c->repeat, 1) > 0)
+ {
+ if (mpz_get_si (c->offset) + mpz_get_si (c->repeat) <= offset)
+ c = NULL;
+ }
+ else
+ c = NULL;
+
+ return c;
+}
+
+
+gfc_expr *
+gfc_constructor_lookup_expr (gfc_constructor_base base, int offset)
+{
+ gfc_constructor *c = gfc_constructor_lookup (base, offset);
+ return c ? c->expr : NULL;
+}
+
+
+int
+gfc_constructor_expr_foreach (gfc_constructor *ctor ATTRIBUTE_UNUSED,
+ int(*f)(gfc_expr *) ATTRIBUTE_UNUSED)
+{
+ gcc_assert (0);
+ return 0;
+}
+
+void
+gfc_constructor_swap (gfc_constructor *ctor ATTRIBUTE_UNUSED,
+ int n ATTRIBUTE_UNUSED, int m ATTRIBUTE_UNUSED)
+{
+ gcc_assert (0);
+}
+
+
+
+gfc_constructor *
+gfc_constructor_first (gfc_constructor_base base)
+{
+ if (base)
+ {
+ splay_tree_node node = splay_tree_min (base);
+ return node ? (gfc_constructor*) node->value : NULL;
+ }
+ else
+ return NULL;
+}
+
+
+gfc_constructor *
+gfc_constructor_next (gfc_constructor *ctor)
+{
+ if (ctor)
+ {
+ splay_tree_node node = splay_tree_successor (ctor->base,
+ mpz_get_si (ctor->offset));
+ return node ? (gfc_constructor*) node->value : NULL;
+ }
+ else
+ return NULL;
+}
+
+
+void
+gfc_constructor_remove (gfc_constructor *ctor)
+{
+ if (ctor)
+ splay_tree_remove (ctor->base, mpz_get_si (ctor->offset));
+}
+
+
+gfc_constructor *
+gfc_constructor_lookup_next (gfc_constructor_base base, int offset)
+{
+ splay_tree_node node;
+
+ if (!base)
+ return NULL;
+
+ node = splay_tree_successor (base, (splay_tree_key) offset);
+ if (!node)
+ return NULL;
+
+ return (gfc_constructor *) node->value;
+}