| /* Array and structure constructors |
| Copyright (C) 2009-2022 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 "coretypes.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); |
| |
| 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; |
| } |
| |
| static 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; |
| } |
| |
| |
| 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; |
| } |