aboutsummaryrefslogtreecommitdiff
path: root/gcc/ch/grant.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ch/grant.c')
-rw-r--r--gcc/ch/grant.c3053
1 files changed, 3053 insertions, 0 deletions
diff --git a/gcc/ch/grant.c b/gcc/ch/grant.c
new file mode 100644
index 0000000..5dcf450
--- /dev/null
+++ b/gcc/ch/grant.c
@@ -0,0 +1,3053 @@
+/* Implement grant-file output & seize-file input for CHILL.
+ Copyright (C) 1992, 93, 94, 95, 1996 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC 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 2, or (at your option)
+any later version.
+
+GNU CC 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 GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include "config.h"
+#include "tree.h"
+#include "ch-tree.h"
+#include "lex.h"
+#include "flags.h"
+#include "actions.h"
+#include "input.h"
+#include "errno.h"
+#include "rtl.h"
+#include "tasking.h"
+
+/* Disable possible macro over-rides, so the externs parse
+ portably. */
+#undef strchr
+#undef strrchr
+
+#define APPEND(X,Y) X = append (X, Y)
+#define PREPEND(X,Y) X = prepend (X, Y);
+#define FREE(x) strfree (x)
+#define ALLOCAMOUNT 10000
+/* may be we can handle this in a more exciting way,
+ but this also should work for the moment */
+#define MAYBE_NEWLINE(X) \
+do \
+{ \
+ if (X->len && X->str[X->len - 1] != '\n') \
+ APPEND (X, ";\n"); \
+} while (0)
+
+extern void assemble_constructor PROTO((char *));
+extern void assemble_name PROTO((FILE *, char *));
+extern void error PROTO((char *, ...));
+extern tree tasking_list;
+extern void tasking_registry PROTO((void));
+extern void tasking_setup PROTO((void));
+extern void build_enum_tables PROTO((void));
+extern tree process_type;
+extern void warning PROTO((char *, ...));
+extern tree get_file_function_name PROTO((int));
+extern char *asm_file_name;
+extern char *dump_base_name;
+
+/* forward declarations */
+
+/* variable indicates compilation at module level */
+int chill_at_module_level = 0;
+
+
+/* mark that a SPEC MODULE was generated */
+static int spec_module_generated = 0;
+
+/* define version strings */
+extern char *gnuchill_version;
+extern char *version_string;
+
+/* define a faster string handling */
+typedef struct
+{
+ char *str;
+ int len;
+ int allocated;
+} MYSTRING;
+
+/* structure used for handling multiple grant files */
+char *grant_file_name;
+MYSTRING *gstring = NULL;
+MYSTRING *selective_gstring = NULL;
+
+static MYSTRING *decode_decl PROTO((tree));
+static MYSTRING *decode_constant PROTO((tree));
+static void grant_one_decl PROTO((tree));
+static MYSTRING *get_type PROTO((tree));
+static MYSTRING *decode_mode PROTO((tree));
+static MYSTRING *decode_prefix_rename PROTO((tree));
+static MYSTRING *decode_constant_selective PROTO((tree, tree));
+static MYSTRING *decode_mode_selective PROTO((tree, tree));
+static MYSTRING *get_type_selective PROTO((tree, tree));
+static MYSTRING *decode_decl_selective PROTO((tree, tree));
+
+/* list of the VAR_DECLs of the module initializer entries */
+tree module_init_list = NULL_TREE;
+
+/* handle different USE_SEIZE_FILE's in case of selective granting */
+typedef struct SEIZEFILELIST
+{
+ struct SEIZEFILELIST *next;
+ tree filename;
+ MYSTRING *seizes;
+} seizefile_list;
+
+static seizefile_list *selective_seizes = 0;
+
+
+static MYSTRING *
+newstring (str)
+ char *str;
+{
+ MYSTRING *tmp = (MYSTRING *) xmalloc (sizeof (MYSTRING));
+ unsigned len = strlen (str);
+
+ tmp->allocated = len + ALLOCAMOUNT;
+ tmp->str = xmalloc ((unsigned)tmp->allocated);
+ strcpy (tmp->str, str);
+ tmp->len = len;
+ return (tmp);
+}
+
+static void
+strfree (str)
+ MYSTRING *str;
+{
+ free (str->str);
+ free (str);
+}
+
+static MYSTRING *
+append (inout, in)
+ MYSTRING *inout;
+ char *in;
+{
+ int inlen = strlen (in);
+ int amount = ALLOCAMOUNT;
+
+ if (inlen >= amount)
+ amount += inlen;
+ if ((inout->len + inlen) >= inout->allocated)
+ inout->str = xrealloc (inout->str, inout->allocated += amount);
+ strcpy (inout->str + inout->len, in);
+ inout->len += inlen;
+ return (inout);
+}
+
+static MYSTRING *
+prepend (inout, in)
+ MYSTRING *inout;
+ char *in;
+{
+ MYSTRING *res = inout;
+ if (strlen (in))
+ {
+ res = newstring (in);
+ res = APPEND (res, inout->str);
+ FREE (inout);
+ }
+ return res;
+}
+
+void
+grant_use_seizefile (seize_filename)
+ char *seize_filename;
+{
+ APPEND (gstring, "<> USE_SEIZE_FILE \"");
+ APPEND (gstring, seize_filename);
+ APPEND (gstring, "\" <>\n");
+}
+
+static MYSTRING *
+decode_layout (layout)
+ tree layout;
+{
+ tree temp;
+ tree stepsize = NULL_TREE;
+ int was_step = 0;
+ MYSTRING *result = newstring ("");
+ MYSTRING *work;
+
+ if (layout == integer_zero_node) /* NOPACK */
+ {
+ APPEND (result, " NOPACK");
+ return result;
+ }
+
+ if (layout == integer_one_node) /* PACK */
+ {
+ APPEND (result, " PACK");
+ return result;
+ }
+
+ APPEND (result, " ");
+ temp = layout;
+ if (TREE_PURPOSE (temp) == NULL_TREE)
+ {
+ APPEND (result, "STEP(");
+ was_step = 1;
+ temp = TREE_VALUE (temp);
+ stepsize = TREE_VALUE (temp);
+ }
+ APPEND (result, "POS(");
+
+ /* Get the starting word */
+ temp = TREE_PURPOSE (temp);
+ work = decode_constant (TREE_PURPOSE (temp));
+ APPEND (result, work->str);
+ FREE (work);
+
+ temp = TREE_VALUE (temp);
+ if (temp != NULL_TREE)
+ {
+ /* Get the starting bit */
+ APPEND (result, ", ");
+ work = decode_constant (TREE_PURPOSE (temp));
+ APPEND (result, work->str);
+ FREE (work);
+
+ temp = TREE_VALUE (temp);
+ if (temp != NULL_TREE)
+ {
+ /* Get the length or the ending bit */
+ tree what = TREE_PURPOSE (temp);
+ if (what == integer_zero_node) /* length */
+ {
+ APPEND (result, ", ");
+ }
+ else
+ {
+ APPEND (result, ":");
+ }
+ work = decode_constant (TREE_VALUE (temp));
+ APPEND (result, work->str);
+ FREE (work);
+ }
+ }
+ APPEND (result, ")");
+
+ if (was_step)
+ {
+ if (stepsize != NULL_TREE)
+ {
+ APPEND (result, ", ");
+ work = decode_constant (stepsize);
+ APPEND (result, work->str);
+ FREE (work);
+ }
+ APPEND (result, ")");
+ }
+
+ return result;
+}
+
+static MYSTRING *
+grant_array_type (type)
+ tree type;
+{
+ MYSTRING *result = newstring ("");
+ MYSTRING *mode_string;
+ tree layout;
+ int varying = 0;
+
+ if (chill_varying_type_p (type))
+ {
+ varying = 1;
+ type = CH_VARYING_ARRAY_TYPE (type);
+ }
+ if (CH_STRING_TYPE_P (type))
+ {
+ tree fields = TYPE_DOMAIN (type);
+ tree maxval = TYPE_MAX_VALUE (fields);
+
+ if (TREE_CODE (TREE_TYPE (type)) == CHAR_TYPE)
+ APPEND (result, "CHARS (");
+ else
+ APPEND (result, "BOOLS (");
+ if (TREE_CODE (maxval) == INTEGER_CST)
+ {
+ char wrk[20];
+ sprintf (wrk, "%d", TREE_INT_CST_LOW (maxval) + 1);
+ APPEND (result, wrk);
+ }
+ else if (TREE_CODE (maxval) == MINUS_EXPR
+ && TREE_OPERAND (maxval, 1) == integer_one_node)
+ {
+ mode_string = decode_constant (TREE_OPERAND (maxval, 0));
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ }
+ else
+ {
+ mode_string = decode_constant (maxval);
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ APPEND (result, "+1");
+ }
+ APPEND (result, ")");
+ if (varying)
+ APPEND (result, " VARYING");
+ return result;
+ }
+
+ APPEND (result, "ARRAY (");
+ if (TREE_CODE (TYPE_DOMAIN (type)) == INTEGER_TYPE
+ && TREE_TYPE (TYPE_DOMAIN (type)) == ridpointers[(int) RID_RANGE])
+ {
+ mode_string = decode_constant (TYPE_MIN_VALUE (TYPE_DOMAIN (type)));
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+
+ APPEND (result, ":");
+ mode_string = decode_constant (TYPE_MAX_VALUE (TYPE_DOMAIN (type)));
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ }
+ else
+ {
+ mode_string = decode_mode (TYPE_DOMAIN (type));
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ }
+ APPEND (result, ") ");
+ if (varying)
+ APPEND (result, "VARYING ");
+
+ mode_string = get_type (TREE_TYPE (type));
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+
+ layout = TYPE_ATTRIBUTES (type);
+ if (layout != NULL_TREE)
+ {
+ mode_string = decode_layout (layout);
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ }
+
+ return result;
+}
+
+static MYSTRING *
+grant_array_type_selective (type, all_decls)
+ tree type;
+ tree all_decls;
+{
+ MYSTRING *result = newstring ("");
+ MYSTRING *mode_string;
+ int varying = 0;
+
+ if (chill_varying_type_p (type))
+ {
+ varying = 1;
+ type = CH_VARYING_ARRAY_TYPE (type);
+ }
+ if (CH_STRING_TYPE_P (type))
+ {
+ tree fields = TYPE_DOMAIN (type);
+ tree maxval = TYPE_MAX_VALUE (fields);
+
+ if (TREE_CODE (maxval) != INTEGER_CST)
+ {
+ if (TREE_CODE (maxval) == MINUS_EXPR
+ && TREE_OPERAND (maxval, 1) == integer_one_node)
+ {
+ mode_string = decode_constant_selective (TREE_OPERAND (maxval, 0), all_decls);
+ if (mode_string->len)
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ }
+ else
+ {
+ mode_string = decode_constant_selective (maxval, all_decls);
+ if (mode_string->len)
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ }
+ }
+ return result;
+ }
+
+ if (TREE_CODE (TYPE_DOMAIN (type)) == INTEGER_TYPE
+ && TREE_TYPE (TYPE_DOMAIN (type)) == ridpointers[(int) RID_RANGE])
+ {
+ mode_string = decode_constant_selective (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), all_decls);
+ if (mode_string->len)
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+
+ mode_string = decode_constant_selective (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), all_decls);
+ if (mode_string->len)
+ {
+ MAYBE_NEWLINE (result);
+ APPEND (result, mode_string->str);
+ }
+ FREE (mode_string);
+ }
+ else
+ {
+ mode_string = decode_mode_selective (TYPE_DOMAIN (type), all_decls);
+ if (mode_string->len)
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ }
+
+ mode_string = get_type_selective (TREE_TYPE (type), all_decls);
+ if (mode_string->len)
+ {
+ MAYBE_NEWLINE (result);
+ APPEND (result, mode_string->str);
+ }
+ FREE (mode_string);
+
+ return result;
+}
+
+static MYSTRING *
+get_tag_value (val)
+ tree val;
+{
+ MYSTRING *result;
+
+ if (TREE_CODE (val) == CONST_DECL && DECL_NAME (val))
+ {
+ result = newstring (IDENTIFIER_POINTER (DECL_NAME (val)));
+ }
+ else if (TREE_CODE (val) == CONST_DECL)
+ {
+ /* it's a synonym -- get the value */
+ result = decode_constant (DECL_INITIAL (val));
+ }
+ else
+ {
+ result = decode_constant (val);
+ }
+ return (result);
+}
+
+static MYSTRING *
+get_tag_value_selective (val, all_decls)
+ tree val;
+ tree all_decls;
+{
+ MYSTRING *result;
+
+ if (TREE_CODE (val) == CONST_DECL && DECL_NAME (val))
+ result = newstring ("");
+ else if (TREE_CODE (val) == CONST_DECL)
+ {
+ /* it's a synonym -- get the value */
+ result = decode_constant_selective (DECL_INITIAL (val), all_decls);
+ }
+ else
+ {
+ result = decode_constant_selective (val, all_decls);
+ }
+ return (result);
+}
+
+static MYSTRING *
+print_enumeral (type)
+ tree type;
+{
+ MYSTRING *result = newstring ("");
+ tree fields;
+
+#if 0
+ if (TYPE_LANG_SPECIFIC (type) == NULL)
+#endif
+ {
+
+ APPEND (result, "SET (");
+ for (fields = TYPE_VALUES (type);
+ fields != NULL_TREE;
+ fields = TREE_CHAIN (fields))
+ {
+ if (TREE_PURPOSE (fields) == NULL_TREE)
+ APPEND (result, "*");
+ else
+ {
+ tree decl = TREE_VALUE (fields);
+ APPEND (result, IDENTIFIER_POINTER (TREE_PURPOSE (fields)));
+ if (TREE_CODE (decl) == CONST_DECL && DECL_INITIAL (decl))
+ {
+ MYSTRING *val_string = decode_constant (DECL_INITIAL (decl));
+ APPEND (result, " = ");
+ APPEND (result, val_string->str);
+ FREE (val_string);
+ }
+ }
+ if (TREE_CHAIN (fields) != NULL_TREE)
+ APPEND (result, ",\n ");
+ }
+ APPEND (result, ")");
+ }
+ return result;
+}
+
+static MYSTRING *
+print_enumeral_selective (type, all_decls)
+ tree type;
+ tree all_decls;
+{
+ MYSTRING *result = newstring ("");
+ tree fields;
+
+ for (fields = TYPE_VALUES (type);
+ fields != NULL_TREE;
+ fields = TREE_CHAIN (fields))
+ {
+ if (TREE_PURPOSE (fields) != NULL_TREE)
+ {
+ tree decl = TREE_VALUE (fields);
+ if (TREE_CODE (decl) == CONST_DECL && DECL_INITIAL (decl))
+ {
+ MYSTRING *val_string = decode_constant_selective (DECL_INITIAL (decl), all_decls);
+ if (val_string->len)
+ APPEND (result, val_string->str);
+ FREE (val_string);
+ }
+ }
+ }
+ return result;
+}
+
+static MYSTRING *
+print_integer_type (type)
+ tree type;
+{
+ MYSTRING *result = newstring ("");
+ MYSTRING *mode_string;
+ char *name_ptr;
+ tree base_type;
+
+ if (TREE_TYPE (type))
+ {
+ mode_string = decode_mode (TREE_TYPE (type));
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+
+ APPEND (result, "(");
+ mode_string = decode_constant (TYPE_MIN_VALUE (type));
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+
+ if (TREE_TYPE (type) != ridpointers[(int) RID_BIN])
+ {
+ APPEND (result, ":");
+ mode_string = decode_constant (TYPE_MAX_VALUE (type));
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ }
+
+ APPEND (result, ")");
+ return result;
+ }
+ /* We test TYPE_MAIN_VARIANT because pushdecl often builds
+ a copy of a built-in type node, which is logically id-
+ entical but has a different address, and the same
+ TYPE_MAIN_VARIANT. */
+ /* FIXME this should not be needed! */
+
+ base_type = TREE_TYPE (type) ? TREE_TYPE (type) : type;
+
+ if (TREE_UNSIGNED (base_type))
+ {
+ if (base_type == chill_unsigned_type_node
+ || TYPE_MAIN_VARIANT(base_type) ==
+ TYPE_MAIN_VARIANT (chill_unsigned_type_node))
+ name_ptr = "UINT";
+ else if (base_type == long_integer_type_node
+ || TYPE_MAIN_VARIANT(base_type) ==
+ TYPE_MAIN_VARIANT (long_unsigned_type_node))
+ name_ptr = "ULONG";
+ else if (type == unsigned_char_type_node
+ || TYPE_MAIN_VARIANT(base_type) ==
+ TYPE_MAIN_VARIANT (unsigned_char_type_node))
+ name_ptr = "UBYTE";
+ else if (type == duration_timing_type_node
+ || TYPE_MAIN_VARIANT (base_type) ==
+ TYPE_MAIN_VARIANT (duration_timing_type_node))
+ name_ptr = "DURATION";
+ else if (type == abs_timing_type_node
+ || TYPE_MAIN_VARIANT (base_type) ==
+ TYPE_MAIN_VARIANT (abs_timing_type_node))
+ name_ptr = "TIME";
+ else
+ name_ptr = "UINT";
+ }
+ else
+ {
+ if (base_type == chill_integer_type_node
+ || TYPE_MAIN_VARIANT (base_type) ==
+ TYPE_MAIN_VARIANT (chill_integer_type_node))
+ name_ptr = "INT";
+ else if (base_type == long_integer_type_node
+ || TYPE_MAIN_VARIANT (base_type) ==
+ TYPE_MAIN_VARIANT (long_integer_type_node))
+ name_ptr = "LONG";
+ else if (type == signed_char_type_node
+ || TYPE_MAIN_VARIANT (base_type) ==
+ TYPE_MAIN_VARIANT (signed_char_type_node))
+ name_ptr = "BYTE";
+ else
+ name_ptr = "INT";
+ }
+
+ APPEND (result, name_ptr);
+
+ /* see if we have a range */
+ if (TREE_TYPE (type) != NULL)
+ {
+ mode_string = decode_constant (TYPE_MIN_VALUE (type));
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ APPEND (result, ":");
+ mode_string = decode_constant (TYPE_MAX_VALUE (type));
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ }
+
+ return result;
+}
+
+static tree
+find_enum_parent (enumname, all_decls)
+ tree enumname;
+ tree all_decls;
+{
+ tree wrk;
+
+ for (wrk = all_decls; wrk != NULL_TREE; wrk = TREE_CHAIN (wrk))
+ {
+ if (TREE_TYPE (wrk) != NULL_TREE && TREE_CODE (wrk) != CONST_DECL &&
+ TREE_CODE (TREE_TYPE (wrk)) == ENUMERAL_TYPE)
+ {
+ tree list;
+ for (list = TYPE_VALUES (TREE_TYPE (wrk)); list != NULL_TREE; list = TREE_CHAIN (list))
+ {
+ if (DECL_NAME (TREE_VALUE (list)) == enumname)
+ return wrk;
+ }
+ }
+ }
+ return NULL_TREE;
+}
+
+static MYSTRING *
+print_integer_selective (type, all_decls)
+ tree type;
+ tree all_decls;
+{
+ MYSTRING *result = newstring ("");
+ MYSTRING *mode_string;
+
+ if (TREE_TYPE (type))
+ {
+ mode_string = decode_mode_selective (TREE_TYPE (type), all_decls);
+ if (mode_string->len)
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+
+ if (TREE_TYPE (type) == ridpointers[(int)RID_RANGE] &&
+ TREE_CODE (TYPE_MIN_VALUE (type)) == IDENTIFIER_NODE &&
+ TREE_CODE (TYPE_MAX_VALUE (type)) == IDENTIFIER_NODE)
+ {
+ /* we have a range of a set. Find parant mode and write it
+ to SPEC MODULE. This will loose if the parent mode was SEIZED from
+ another file.*/
+ tree minparent = find_enum_parent (TYPE_MIN_VALUE (type), all_decls);
+ tree maxparent = find_enum_parent (TYPE_MAX_VALUE (type), all_decls);
+
+ if (minparent != NULL_TREE)
+ {
+ if (! CH_ALREADY_GRANTED (minparent))
+ {
+ mode_string = decode_decl (minparent);
+ if (mode_string->len)
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ CH_ALREADY_GRANTED (minparent) = 1;
+ }
+ }
+ if (minparent != maxparent && maxparent != NULL_TREE)
+ {
+ if (!CH_ALREADY_GRANTED (maxparent))
+ {
+ mode_string = decode_decl (maxparent);
+ if (mode_string->len)
+ {
+ MAYBE_NEWLINE (result);
+ APPEND (result, mode_string->str);
+ }
+ FREE (mode_string);
+ CH_ALREADY_GRANTED (maxparent) = 1;
+ }
+ }
+ }
+ else
+ {
+ mode_string = decode_constant_selective (TYPE_MIN_VALUE (type), all_decls);
+ if (mode_string->len)
+ {
+ MAYBE_NEWLINE (result);
+ APPEND (result, mode_string->str);
+ }
+ FREE (mode_string);
+
+ mode_string = decode_constant_selective (TYPE_MAX_VALUE (type), all_decls);
+ if (mode_string->len)
+ {
+ MAYBE_NEWLINE (result);
+ APPEND (result, mode_string->str);
+ }
+ FREE (mode_string);
+ }
+ return result;
+ }
+
+ /* see if we have a range */
+ if (TREE_TYPE (type) != NULL)
+ {
+ mode_string = decode_constant_selective (TYPE_MIN_VALUE (type), all_decls);
+ if (mode_string->len)
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+
+ mode_string = decode_constant_selective (TYPE_MAX_VALUE (type), all_decls);
+ if (mode_string->len)
+ {
+ MAYBE_NEWLINE (result);
+ APPEND (result, mode_string->str);
+ }
+ FREE (mode_string);
+ }
+
+ return result;
+}
+
+static MYSTRING *
+print_struct (type)
+ tree type;
+{
+ MYSTRING *result = newstring ("");
+ MYSTRING *mode_string;
+ tree fields;
+
+ if (chill_varying_type_p (type))
+ {
+ mode_string = grant_array_type (type);
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ }
+ else
+ {
+ fields = TYPE_FIELDS (type);
+
+ APPEND (result, "STRUCT (");
+ while (fields != NULL_TREE)
+ {
+ if (TREE_CODE (TREE_TYPE (fields)) == UNION_TYPE)
+ {
+ tree variants;
+ /* Format a tagged variant record type. */
+ APPEND (result, " CASE ");
+ if (TYPE_TAGFIELDS (TREE_TYPE (fields)) != NULL_TREE)
+ {
+ tree tag_list = TYPE_TAGFIELDS (TREE_TYPE (fields));
+ for (;;)
+ {
+ tree tag_name = DECL_NAME (TREE_VALUE (tag_list));
+ APPEND (result, IDENTIFIER_POINTER (tag_name));
+ tag_list = TREE_CHAIN (tag_list);
+ if (tag_list == NULL_TREE)
+ break;
+ APPEND (result, ", ");
+ }
+ }
+ APPEND (result, " OF\n");
+ variants = TYPE_FIELDS (TREE_TYPE (fields));
+
+ /* Each variant is a FIELD_DECL whose type is an anonymous
+ struct within the anonymous union. */
+ while (variants != NULL_TREE)
+ {
+ tree tag_list = TYPE_TAG_VALUES (TREE_TYPE (variants));
+ tree struct_elts = TYPE_FIELDS (TREE_TYPE (variants));
+
+ while (tag_list != NULL_TREE)
+ {
+ tree tag_values = TREE_VALUE (tag_list);
+ APPEND (result, " (");
+ while (tag_values != NULL_TREE)
+ {
+ mode_string = get_tag_value (TREE_VALUE (tag_values));
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ if (TREE_CHAIN (tag_values) != NULL_TREE)
+ {
+ APPEND (result, ",\n ");
+ tag_values = TREE_CHAIN (tag_values);
+ }
+ else break;
+ }
+ APPEND (result, ")");
+ tag_list = TREE_CHAIN (tag_list);
+ if (tag_list)
+ APPEND (result, ",");
+ else
+ break;
+ }
+ APPEND (result, " : ");
+
+ while (struct_elts != NULL_TREE)
+ {
+ mode_string = decode_decl (struct_elts);
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+
+ if (TREE_CHAIN (struct_elts) != NULL_TREE)
+ APPEND (result, ",\n ");
+ struct_elts = TREE_CHAIN (struct_elts);
+ }
+
+ variants = TREE_CHAIN (variants);
+ if (variants != NULL_TREE
+ && TREE_CHAIN (variants) == NULL_TREE
+ && DECL_NAME (variants) == ELSE_VARIANT_NAME)
+ {
+ tree else_elts = TYPE_FIELDS (TREE_TYPE (variants));
+ APPEND (result, "\n ELSE ");
+ while (else_elts != NULL_TREE)
+ {
+ mode_string = decode_decl (else_elts);
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ if (TREE_CHAIN (else_elts) != NULL_TREE)
+ APPEND (result, ",\n ");
+ else_elts = TREE_CHAIN (else_elts);
+ }
+ break;
+ }
+ if (variants != NULL_TREE)
+ APPEND (result, ",\n");
+ }
+
+ APPEND (result, "\n ESAC");
+ }
+ else
+ {
+ mode_string = decode_decl (fields);
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ }
+
+ fields = TREE_CHAIN (fields);
+ if (fields != NULL_TREE)
+ APPEND (result, ",\n ");
+ }
+ APPEND (result, ")");
+ }
+ return result;
+}
+
+static MYSTRING *
+print_struct_selective (type, all_decls)
+ tree type;
+ tree all_decls;
+{
+ MYSTRING *result = newstring ("");
+ MYSTRING *mode_string;
+ tree fields;
+
+ if (chill_varying_type_p (type))
+ {
+ mode_string = grant_array_type_selective (type, all_decls);
+ if (mode_string->len)
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ }
+ else
+ {
+ fields = TYPE_FIELDS (type);
+
+ while (fields != NULL_TREE)
+ {
+ if (TREE_CODE (TREE_TYPE (fields)) == UNION_TYPE)
+ {
+ tree variants;
+ /* Format a tagged variant record type. */
+
+ variants = TYPE_FIELDS (TREE_TYPE (fields));
+
+ /* Each variant is a FIELD_DECL whose type is an anonymous
+ struct within the anonymous union. */
+ while (variants != NULL_TREE)
+ {
+ tree tag_list = TYPE_TAG_VALUES (TREE_TYPE (variants));
+ tree struct_elts = TYPE_FIELDS (TREE_TYPE (variants));
+
+ while (tag_list != NULL_TREE)
+ {
+ tree tag_values = TREE_VALUE (tag_list);
+ while (tag_values != NULL_TREE)
+ {
+ mode_string = get_tag_value_selective (TREE_VALUE (tag_values),
+ all_decls);
+ if (mode_string->len)
+ {
+ MAYBE_NEWLINE (result);
+ APPEND (result, mode_string->str);
+ }
+ FREE (mode_string);
+ if (TREE_CHAIN (tag_values) != NULL_TREE)
+ tag_values = TREE_CHAIN (tag_values);
+ else break;
+ }
+ tag_list = TREE_CHAIN (tag_list);
+ if (!tag_list)
+ break;
+ }
+
+ while (struct_elts != NULL_TREE)
+ {
+ mode_string = decode_decl_selective (struct_elts, all_decls);
+ if (mode_string->len)
+ {
+ MAYBE_NEWLINE (result);
+ APPEND (result, mode_string->str);
+ }
+ FREE (mode_string);
+
+ struct_elts = TREE_CHAIN (struct_elts);
+ }
+
+ variants = TREE_CHAIN (variants);
+ if (variants != NULL_TREE
+ && TREE_CHAIN (variants) == NULL_TREE
+ && DECL_NAME (variants) == ELSE_VARIANT_NAME)
+ {
+ tree else_elts = TYPE_FIELDS (TREE_TYPE (variants));
+ while (else_elts != NULL_TREE)
+ {
+ mode_string = decode_decl_selective (else_elts, all_decls);
+ if (mode_string->len)
+ {
+ MAYBE_NEWLINE (result);
+ APPEND (result, mode_string->str);
+ }
+ FREE (mode_string);
+ else_elts = TREE_CHAIN (else_elts);
+ }
+ break;
+ }
+ }
+ }
+ else
+ {
+ mode_string = decode_decl_selective (fields, all_decls);
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ }
+
+ fields = TREE_CHAIN (fields);
+ }
+ }
+ return result;
+}
+
+static MYSTRING *
+print_proc_exceptions (ex)
+ tree ex;
+{
+ MYSTRING *result = newstring ("");
+
+ if (ex != NULL_TREE)
+ {
+ APPEND (result, "\n EXCEPTIONS (");
+ for ( ; ex != NULL_TREE; ex = TREE_CHAIN (ex))
+ {
+ APPEND (result, IDENTIFIER_POINTER (TREE_VALUE (ex)));
+ if (TREE_CHAIN (ex) != NULL_TREE)
+ APPEND (result, ",\n ");
+ }
+ APPEND (result, ")");
+ }
+ return result;
+}
+
+static MYSTRING *
+print_proc_tail (type, args, print_argnames)
+ tree type;
+ tree args;
+ int print_argnames;
+{
+ MYSTRING *result = newstring ("");
+ MYSTRING *mode_string;
+ int count = 0;
+ int stopat = list_length (args) - 3;
+
+ /* do the argument modes */
+ for ( ; args != NULL_TREE;
+ args = TREE_CHAIN (args), count++)
+ {
+ char buf[20];
+ tree argmode = TREE_VALUE (args);
+ tree attribute = TREE_PURPOSE (args);
+
+ if (argmode == void_type_node)
+ continue;
+
+ /* if we have exceptions don't print last 2 arguments */
+ if (TYPE_RAISES_EXCEPTIONS (type) && count == stopat)
+ break;
+
+ if (count)
+ APPEND (result, ",\n ");
+ if (print_argnames)
+ {
+ sprintf(buf, "arg%d ", count);
+ APPEND (result, buf);
+ }
+
+ if (attribute == ridpointers[(int) RID_LOC])
+ argmode = TREE_TYPE (argmode);
+ mode_string = get_type (argmode);
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+
+ if (attribute != NULL_TREE)
+ {
+ sprintf (buf, " %s", IDENTIFIER_POINTER (attribute));
+ APPEND (result, buf);
+ }
+ }
+ APPEND (result, ")");
+
+ /* return type */
+ {
+ tree retn_type = TREE_TYPE (type);
+
+ if (retn_type != NULL_TREE
+ && TREE_CODE (retn_type) != VOID_TYPE)
+ {
+ mode_string = get_type (retn_type);
+ APPEND (result, "\n RETURNS (");
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ if (TREE_CODE (retn_type) == REFERENCE_TYPE)
+ APPEND (result, " LOC");
+ APPEND (result, ")");
+ }
+ }
+
+ mode_string = print_proc_exceptions (TYPE_RAISES_EXCEPTIONS (type));
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+
+ return result;
+}
+
+static MYSTRING *
+print_proc_tail_selective (type, args, all_decls)
+ tree type;
+ tree args;
+ tree all_decls;
+{
+ MYSTRING *result = newstring ("");
+ MYSTRING *mode_string;
+ int count = 0;
+ int stopat = list_length (args) - 3;
+
+ /* do the argument modes */
+ for ( ; args != NULL_TREE;
+ args = TREE_CHAIN (args), count++)
+ {
+ tree argmode = TREE_VALUE (args);
+ tree attribute = TREE_PURPOSE (args);
+
+ if (argmode == void_type_node)
+ continue;
+
+ /* if we have exceptions don't process last 2 arguments */
+ if (TYPE_RAISES_EXCEPTIONS (type) && count == stopat)
+ break;
+
+ if (attribute == ridpointers[(int) RID_LOC])
+ argmode = TREE_TYPE (argmode);
+ mode_string = get_type_selective (argmode, all_decls);
+ if (mode_string->len)
+ {
+ MAYBE_NEWLINE (result);
+ APPEND (result, mode_string->str);
+ }
+ FREE (mode_string);
+ }
+
+ /* return type */
+ {
+ tree retn_type = TREE_TYPE (type);
+
+ if (retn_type != NULL_TREE
+ && TREE_CODE (retn_type) != VOID_TYPE)
+ {
+ mode_string = get_type_selective (retn_type, all_decls);
+ if (mode_string->len)
+ {
+ MAYBE_NEWLINE (result);
+ APPEND (result, mode_string->str);
+ }
+ FREE (mode_string);
+ }
+ }
+
+ return result;
+}
+
+/* output a mode (or type). */
+
+static MYSTRING *
+decode_mode (type)
+ tree type;
+{
+ MYSTRING *result = newstring ("");
+ MYSTRING *mode_string;
+
+ switch ((enum chill_tree_code)TREE_CODE (type))
+ {
+ case TYPE_DECL:
+ if (DECL_NAME (type))
+ {
+ APPEND (result, IDENTIFIER_POINTER (DECL_NAME (type)));
+ return result;
+ }
+ type = TREE_TYPE (type);
+ break;
+
+ case IDENTIFIER_NODE:
+ APPEND (result, IDENTIFIER_POINTER (type));
+ return result;
+
+ case LANG_TYPE:
+ /* LANG_TYPE are only used until satisfy is done,
+ as place-holders for 'READ T', NEWMODE/SYNMODE modes,
+ parameterised modes, and old-fashioned CHAR(N). */
+ if (TYPE_READONLY (type))
+ APPEND (result, "READ ");
+
+ mode_string = get_type (TREE_TYPE (type));
+ APPEND (result, mode_string->str);
+ if (TYPE_DOMAIN (type) != NULL_TREE)
+ {
+ /* Parameterized mode,
+ or old-fashioned CHAR(N) string declaration.. */
+ APPEND (result, "(");
+ mode_string = decode_constant (TYPE_DOMAIN (type));
+ APPEND (result, mode_string->str);
+ APPEND (result, ")");
+ }
+ FREE (mode_string);
+ break;
+
+ case ARRAY_TYPE:
+ mode_string = grant_array_type (type);
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ break;
+
+ case BOOLEAN_TYPE:
+ APPEND (result, "BOOL");
+ break;
+
+ case CHAR_TYPE:
+ APPEND (result, "CHAR");
+ break;
+
+ case ENUMERAL_TYPE:
+ mode_string = print_enumeral (type);
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ break;
+
+ case FUNCTION_TYPE:
+ {
+ tree args = TYPE_ARG_TYPES (type);
+
+ APPEND (result, "PROC (");
+
+ mode_string = print_proc_tail (type, args, 0);
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ }
+ break;
+
+ case INTEGER_TYPE:
+ mode_string = print_integer_type (type);
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ break;
+
+ case RECORD_TYPE:
+ if (CH_IS_INSTANCE_MODE (type))
+ {
+ APPEND (result, "INSTANCE");
+ return result;
+ }
+ else if (CH_IS_BUFFER_MODE (type) || CH_IS_EVENT_MODE (type))
+ { tree bufsize = max_queue_size (type);
+ APPEND (result, CH_IS_BUFFER_MODE (type) ? "BUFFER " : "EVENT ");
+ if (bufsize != NULL_TREE)
+ {
+ APPEND (result, "(");
+ mode_string = decode_constant (bufsize);
+ APPEND (result, mode_string->str);
+ APPEND (result, ") ");
+ FREE (mode_string);
+ }
+ if (CH_IS_BUFFER_MODE (type))
+ {
+ mode_string = decode_mode (buffer_element_mode (type));
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ }
+ break;
+ }
+ else if (CH_IS_ACCESS_MODE (type))
+ {
+ tree indexmode, recordmode, dynamic;
+
+ APPEND (result, "ACCESS");
+ recordmode = access_recordmode (type);
+ indexmode = access_indexmode (type);
+ dynamic = access_dynamic (type);
+
+ if (indexmode != void_type_node)
+ {
+ mode_string = decode_mode (indexmode);
+ APPEND (result, " (");
+ APPEND (result, mode_string->str);
+ APPEND (result, ")");
+ FREE (mode_string);
+ }
+ if (recordmode != void_type_node)
+ {
+ mode_string = decode_mode (recordmode);
+ APPEND (result, " ");
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ }
+ if (dynamic != integer_zero_node)
+ APPEND (result, " DYNAMIC");
+ break;
+ }
+ else if (CH_IS_TEXT_MODE (type))
+ {
+ tree indexmode, dynamic, length;
+
+ APPEND (result, "TEXT (");
+ length = text_length (type);
+ indexmode = text_indexmode (type);
+ dynamic = text_dynamic (type);
+
+ mode_string = decode_constant (length);
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ APPEND (result, ")");
+ if (indexmode != void_type_node)
+ {
+ APPEND (result, " ");
+ mode_string = decode_mode (indexmode);
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ }
+ if (dynamic != integer_zero_node)
+ APPEND (result, " DYNAMIC");
+ return result;
+ }
+ mode_string = print_struct (type);
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ break;
+
+ case POINTER_TYPE:
+ if (TREE_CODE (TREE_TYPE (type)) == VOID_TYPE)
+ APPEND (result, "PTR");
+ else
+ {
+ if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
+ {
+ mode_string = get_type (TREE_TYPE (type));
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ }
+ else
+ {
+ APPEND (result, "REF ");
+ mode_string = get_type (TREE_TYPE (type));
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ }
+ }
+ break;
+
+ case REAL_TYPE:
+ if (TREE_INT_CST_LOW (TYPE_SIZE (type)) == 32)
+ APPEND (result, "REAL");
+ else
+ APPEND (result, "LONG_REAL");
+ break;
+
+ case SET_TYPE:
+ if (CH_BOOLS_TYPE_P (type))
+ mode_string = grant_array_type (type);
+ else
+ {
+ APPEND (result, "POWERSET ");
+ mode_string = get_type (TYPE_DOMAIN (type));
+ }
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ break;
+
+ case REFERENCE_TYPE:
+ mode_string = get_type (TREE_TYPE (type));
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ break;
+
+ default:
+ APPEND (result, "/* ---- not implemented ---- */");
+ break;
+ }
+
+ return (result);
+}
+
+static tree
+find_in_decls (id, all_decls)
+ tree id;
+ tree all_decls;
+{
+ tree wrk;
+
+ for (wrk = all_decls; wrk != NULL_TREE; wrk = TREE_CHAIN (wrk))
+ {
+ if (DECL_NAME (wrk) == id || DECL_POSTFIX (wrk) == id)
+ return wrk;
+ }
+ return NULL_TREE;
+}
+
+static int
+in_ridpointers (id)
+ tree id;
+{
+ int i;
+ for (i = RID_UNUSED; i < RID_MAX; i++)
+ {
+ if (id == ridpointers[i])
+ return 1;
+ }
+ return 0;
+}
+
+static void
+grant_seized_identifier (decl)
+ tree decl;
+{
+ seizefile_list *wrk = selective_seizes;
+ MYSTRING *mode_string;
+
+ CH_ALREADY_GRANTED (decl) = 1;
+
+ /* comes from a SPEC MODULE in the module */
+ if (DECL_SEIZEFILE (decl) == NULL_TREE)
+ return;
+
+ /* search file already in process */
+ while (wrk != 0)
+ {
+ if (wrk->filename == DECL_SEIZEFILE (decl))
+ break;
+ wrk = wrk->next;
+ }
+ if (!wrk)
+ {
+ wrk = (seizefile_list *)xmalloc (sizeof (seizefile_list));
+ wrk->next = selective_seizes;
+ selective_seizes = wrk;
+ wrk->filename = DECL_SEIZEFILE (decl);
+ wrk->seizes = newstring ("<> USE_SEIZE_FILE \"");
+ APPEND (wrk->seizes, IDENTIFIER_POINTER (DECL_SEIZEFILE (decl)));
+ APPEND (wrk->seizes, "\" <>\n");
+ }
+ APPEND (wrk->seizes, "SEIZE ");
+ mode_string = decode_prefix_rename (decl);
+ APPEND (wrk->seizes, mode_string->str);
+ FREE (mode_string);
+ APPEND (wrk->seizes, ";\n");
+}
+
+static MYSTRING *
+decode_mode_selective (type, all_decls)
+ tree type;
+ tree all_decls;
+{
+ MYSTRING *result = newstring ("");
+ MYSTRING *mode_string;
+ tree decl;
+
+ switch ((enum chill_tree_code)TREE_CODE (type))
+ {
+ case TYPE_DECL:
+ /* FIXME: could this ever happen ?? */
+ if (DECL_NAME (type))
+ {
+ FREE (result);
+ result = decode_mode_selective (DECL_NAME (type), all_decls);
+ return result;
+ }
+ break;
+
+ case IDENTIFIER_NODE:
+ if (in_ridpointers (type))
+ /* it's a predefined, we must not search the whole list */
+ return result;
+
+ decl = find_in_decls (type, all_decls);
+ if (decl != NULL_TREE)
+ {
+ if (CH_ALREADY_GRANTED (decl))
+ /* already processed */
+ return result;
+
+ if (TREE_CODE (decl) == ALIAS_DECL && DECL_POSTFIX (decl) != NULL_TREE)
+ {
+ /* If CH_DECL_GRANTED, decl was granted into this scope, and
+ so wasn't in the source code. */
+ if (!CH_DECL_GRANTED (decl))
+ {
+ grant_seized_identifier (decl);
+ }
+ }
+ else
+ {
+ result = decode_decl (decl);
+ mode_string = decode_decl_selective (decl, all_decls);
+ if (mode_string->len)
+ {
+ PREPEND (result, mode_string->str);
+ }
+ FREE (mode_string);
+ }
+ }
+ return result;
+
+ case LANG_TYPE:
+ mode_string = get_type_selective (TREE_TYPE (type), all_decls);
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ break;
+
+ case ARRAY_TYPE:
+ mode_string = grant_array_type_selective (type, all_decls);
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ break;
+
+ case BOOLEAN_TYPE:
+ return result;
+ break;
+
+ case CHAR_TYPE:
+ return result;
+ break;
+
+ case ENUMERAL_TYPE:
+ mode_string = print_enumeral_selective (type, all_decls);
+ if (mode_string->len)
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ break;
+
+ case FUNCTION_TYPE:
+ {
+ tree args = TYPE_ARG_TYPES (type);
+
+ mode_string = print_proc_tail_selective (type, args, all_decls);
+ if (mode_string->len)
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ }
+ break;
+
+ case INTEGER_TYPE:
+ mode_string = print_integer_selective (type, all_decls);
+ if (mode_string->len)
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ break;
+
+ case RECORD_TYPE:
+ if (CH_IS_INSTANCE_MODE (type))
+ {
+ return result;
+ }
+ else if (CH_IS_BUFFER_MODE (type) || CH_IS_EVENT_MODE (type))
+ {
+ tree bufsize = max_queue_size (type);
+ if (bufsize != NULL_TREE)
+ {
+ mode_string = decode_constant_selective (bufsize, all_decls);
+ if (mode_string->len)
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ }
+ if (CH_IS_BUFFER_MODE (type))
+ {
+ mode_string = decode_mode_selective (buffer_element_mode (type), all_decls);
+ if (mode_string->len)
+ {
+ MAYBE_NEWLINE (result);
+ APPEND (result, mode_string->str);
+ }
+ FREE (mode_string);
+ }
+ break;
+ }
+ else if (CH_IS_ACCESS_MODE (type))
+ {
+ tree indexmode = access_indexmode (type);
+ tree recordmode = access_recordmode (type);
+
+ if (indexmode != void_type_node)
+ {
+ mode_string = decode_mode_selective (indexmode, all_decls);
+ if (mode_string->len)
+ {
+ if (result->len && result->str[result->len - 1] != '\n')
+ APPEND (result, ";\n");
+ APPEND (result, mode_string->str);
+ }
+ FREE (mode_string);
+ }
+ if (recordmode != void_type_node)
+ {
+ mode_string = decode_mode_selective (recordmode, all_decls);
+ if (mode_string->len)
+ {
+ if (result->len && result->str[result->len - 1] != '\n')
+ APPEND (result, ";\n");
+ APPEND (result, mode_string->str);
+ }
+ FREE (mode_string);
+ }
+ break;
+ }
+ else if (CH_IS_TEXT_MODE (type))
+ {
+ tree indexmode = text_indexmode (type);
+ tree length = text_length (type);
+
+ mode_string = decode_constant_selective (length, all_decls);
+ if (mode_string->len)
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ if (indexmode != void_type_node)
+ {
+ mode_string = decode_mode_selective (indexmode, all_decls);
+ if (mode_string->len)
+ {
+ if (result->len && result->str[result->len - 1] != '\n')
+ APPEND (result, ";\n");
+ APPEND (result, mode_string->str);
+ }
+ FREE (mode_string);
+ }
+ break;
+ }
+ mode_string = print_struct_selective (type, all_decls);
+ if (mode_string->len)
+ {
+ MAYBE_NEWLINE (result);
+ APPEND (result, mode_string->str);
+ }
+ FREE (mode_string);
+ break;
+
+ case POINTER_TYPE:
+ if (TREE_CODE (TREE_TYPE (type)) == VOID_TYPE)
+ break;
+ else
+ {
+ if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
+ {
+ mode_string = get_type_selective (TREE_TYPE (type), all_decls);
+ if (mode_string->len)
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ }
+ else
+ {
+ mode_string = get_type_selective (TREE_TYPE (type), all_decls);
+ if (mode_string->len)
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ }
+ }
+ break;
+
+ case REAL_TYPE:
+ return result;
+ break;
+
+ case SET_TYPE:
+ if (CH_BOOLS_TYPE_P (type))
+ mode_string = grant_array_type_selective (type, all_decls);
+ else
+ mode_string = get_type_selective (TYPE_DOMAIN (type), all_decls);
+ if (mode_string->len)
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ break;
+
+ case REFERENCE_TYPE:
+ mode_string = get_type_selective (TREE_TYPE (type), all_decls);
+ if (mode_string->len)
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ break;
+
+ default:
+ APPEND (result, "/* ---- not implemented ---- */");
+ break;
+ }
+
+ return (result);
+}
+
+static MYSTRING *
+get_type (type)
+ tree type;
+{
+ if (type == NULL_TREE || TREE_CODE (type) == ERROR_MARK)
+ return newstring ("");
+
+ return (decode_mode (type));
+}
+
+static MYSTRING *
+get_type_selective (type, all_decls)
+ tree type;
+ tree all_decls;
+{
+ if (type == NULL_TREE || TREE_CODE (type) == ERROR_MARK)
+ return newstring ("");
+
+ return (decode_mode_selective (type, all_decls));
+}
+
+#if 0
+static int
+is_forbidden (str, forbid)
+ tree str;
+ tree forbid;
+{
+ if (forbid == NULL_TREE)
+ return (0);
+
+ if (TREE_CODE (forbid) == INTEGER_CST)
+ return (1);
+
+ while (forbid != NULL_TREE)
+ {
+ if (TREE_VALUE (forbid) == str)
+ return (1);
+ forbid = TREE_CHAIN (forbid);
+ }
+ /* nothing found */
+ return (0);
+}
+#endif
+
+static MYSTRING *
+decode_constant (init)
+ tree init;
+{
+ MYSTRING *result = newstring ("");
+ MYSTRING *tmp_string;
+ tree type = TREE_TYPE (init);
+ tree val = init;
+ char *op;
+ char wrk[256];
+ MYSTRING *mode_string;
+
+ switch ((enum chill_tree_code)TREE_CODE (val))
+ {
+ case CALL_EXPR:
+ tmp_string = decode_constant (TREE_OPERAND (val, 0));
+ APPEND (result, tmp_string->str);
+ FREE (tmp_string);
+ val = TREE_OPERAND (val, 1); /* argument list */
+ if (val != NULL_TREE && TREE_CODE (val) != TREE_LIST)
+ {
+ APPEND (result, " ");
+ tmp_string = decode_constant (val);
+ APPEND (result, tmp_string->str);
+ FREE (tmp_string);
+ }
+ else
+ {
+ APPEND (result, " (");
+ if (val != NULL_TREE)
+ {
+ for (;;)
+ {
+ tmp_string = decode_constant (TREE_VALUE (val));
+ APPEND (result, tmp_string->str);
+ FREE (tmp_string);
+ val = TREE_CHAIN (val);
+ if (val == NULL_TREE)
+ break;
+ APPEND (result, ", ");
+ }
+ }
+ APPEND (result, ")");
+ }
+ return result;
+
+ case NOP_EXPR:
+ /* Generate an "expression conversion" expression (a cast). */
+ tmp_string = decode_mode (type);
+
+ APPEND (result, tmp_string->str);
+ FREE (tmp_string);
+ APPEND (result, "(");
+ val = TREE_OPERAND (val, 0);
+ type = TREE_TYPE (val);
+
+ /* If the coercee is a tuple, make sure it is prefixed by its mode. */
+ if (TREE_CODE (val) == CONSTRUCTOR
+ && !CH_BOOLS_TYPE_P (type) && !chill_varying_type_p (type))
+ {
+ tmp_string = decode_mode (type);
+ APPEND (result, tmp_string->str);
+ FREE (tmp_string);
+ APPEND (result, " ");
+ }
+
+ tmp_string = decode_constant (val);
+ APPEND (result, tmp_string->str);
+ FREE (tmp_string);
+ APPEND (result, ")");
+ return result;
+
+ case IDENTIFIER_NODE:
+ APPEND (result, IDENTIFIER_POINTER (val));
+ return result;
+
+ case PAREN_EXPR:
+ APPEND (result, "(");
+ tmp_string = decode_constant (TREE_OPERAND (val, 0));
+ APPEND (result, tmp_string->str);
+ FREE (tmp_string);
+ APPEND (result, ")");
+ return result;
+
+ case UNDEFINED_EXPR:
+ APPEND (result, "*");
+ return result;
+
+ case PLUS_EXPR: op = "+"; goto binary;
+ case MINUS_EXPR: op = "-"; goto binary;
+ case MULT_EXPR: op = "*"; goto binary;
+ case TRUNC_DIV_EXPR: op = "/"; goto binary;
+ case FLOOR_MOD_EXPR: op = " MOD "; goto binary;
+ case TRUNC_MOD_EXPR: op = " REM "; goto binary;
+ case CONCAT_EXPR: op = "//"; goto binary;
+ case BIT_IOR_EXPR: op = " OR "; goto binary;
+ case BIT_XOR_EXPR: op = " XOR "; goto binary;
+ case TRUTH_ORIF_EXPR: op = " ORIF "; goto binary;
+ case BIT_AND_EXPR: op = " AND "; goto binary;
+ case TRUTH_ANDIF_EXPR: op = " ANDIF "; goto binary;
+ case GT_EXPR: op = ">"; goto binary;
+ case GE_EXPR: op = ">="; goto binary;
+ case SET_IN_EXPR: op = " IN "; goto binary;
+ case LT_EXPR: op = "<"; goto binary;
+ case LE_EXPR: op = "<="; goto binary;
+ case EQ_EXPR: op = "="; goto binary;
+ case NE_EXPR: op = "/="; goto binary;
+ case RANGE_EXPR:
+ if (TREE_OPERAND (val, 0) == NULL_TREE)
+ {
+ APPEND (result, TREE_OPERAND (val, 1) == NULL_TREE ? "*" : "ELSE");
+ return result;
+ }
+ op = ":"; goto binary;
+ binary:
+ tmp_string = decode_constant (TREE_OPERAND (val, 0));
+ APPEND (result, tmp_string->str);
+ FREE (tmp_string);
+ APPEND (result, op);
+ tmp_string = decode_constant (TREE_OPERAND (val, 1));
+ APPEND (result, tmp_string->str);
+ FREE (tmp_string);
+ return result;
+
+ case REPLICATE_EXPR:
+ APPEND (result, "(");
+ tmp_string = decode_constant (TREE_OPERAND (val, 0));
+ APPEND (result, tmp_string->str);
+ FREE (tmp_string);
+ APPEND (result, ")");
+ tmp_string = decode_constant (TREE_OPERAND (val, 1));
+ APPEND (result, tmp_string->str);
+ FREE (tmp_string);
+ return result;
+
+ case NEGATE_EXPR: op = "-"; goto unary;
+ case BIT_NOT_EXPR: op = " NOT "; goto unary;
+ case ADDR_EXPR: op = "->"; goto unary;
+ unary:
+ APPEND (result, op);
+ tmp_string = decode_constant (TREE_OPERAND (val, 0));
+ APPEND (result, tmp_string->str);
+ FREE (tmp_string);
+ return result;
+
+ case INTEGER_CST:
+ APPEND (result, display_int_cst (val));
+ return result;
+
+ case REAL_CST:
+#ifndef REAL_IS_NOT_DOUBLE
+ sprintf (wrk, "%.20g", TREE_REAL_CST (val));
+#else
+ REAL_VALUE_TO_DECIMAL (TREE_REAL_CST (val), "%.20g", wrk);
+#endif
+ APPEND (result, wrk);
+ return result;
+
+ case STRING_CST:
+ {
+ char *ptr = TREE_STRING_POINTER (val);
+ int i = TREE_STRING_LENGTH (val);
+ APPEND (result, "\"");
+ while (--i >= 0)
+ {
+ char buf[10];
+ unsigned char c = *ptr++;
+ if (c == '^')
+ APPEND (result, "^^");
+ else if (c == '"')
+ APPEND (result, "\"\"");
+ else if (c == '\n')
+ APPEND (result, "^J");
+ else if (c < ' ' || c > '~')
+ {
+ sprintf (buf, "^(%u)", c);
+ APPEND (result, buf);
+ }
+ else
+ {
+ buf[0] = c;
+ buf[1] = 0;
+ APPEND (result, buf);
+ }
+ }
+ APPEND (result, "\"");
+ return result;
+ }
+
+ case CONSTRUCTOR:
+ val = TREE_OPERAND (val, 1);
+ if (type != NULL && TREE_CODE (type) == SET_TYPE
+ && CH_BOOLS_TYPE_P (type))
+ {
+ /* It's a bitstring. */
+ tree domain = TYPE_DOMAIN (type);
+ tree domain_max = TYPE_MAX_VALUE (domain);
+ char *buf;
+ register char *ptr;
+ int len;
+ if (TREE_CODE (domain_max) != INTEGER_CST
+ || (val && TREE_CODE (val) != TREE_LIST))
+ goto fail;
+
+ len = TREE_INT_CST_LOW (domain_max) + 1;
+ if (TREE_CODE (init) != CONSTRUCTOR)
+ goto fail;
+ buf = (char *) alloca (len + 10);
+ ptr = buf;
+ *ptr++ = ' ';
+ *ptr++ = 'B';
+ *ptr++ = '\'';
+ if (get_set_constructor_bits (init, ptr, len))
+ goto fail;
+ for (; --len >= 0; ptr++)
+ *ptr += '0';
+ *ptr++ = '\'';
+ *ptr = '\0';
+ APPEND (result, buf);
+ return result;
+ }
+ else
+ { /* It's some kind of tuple */
+ if (type != NULL_TREE)
+ {
+ mode_string = get_type (type);
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ APPEND (result, " ");
+ }
+ if (val == NULL_TREE
+ || TREE_CODE (val) == ERROR_MARK)
+ APPEND (result, "[ ]");
+ else if (TREE_CODE (val) != TREE_LIST)
+ goto fail;
+ else
+ {
+ APPEND (result, "[");
+ for ( ; ; )
+ {
+ tree lo_val = TREE_PURPOSE (val);
+ tree hi_val = TREE_VALUE (val);
+ MYSTRING *val_string;
+ if (TUPLE_NAMED_FIELD (val))
+ APPEND(result, ".");
+ if (lo_val != NULL_TREE)
+ {
+ val_string = decode_constant (lo_val);
+ APPEND (result, val_string->str);
+ FREE (val_string);
+ APPEND (result, ":");
+ }
+ val_string = decode_constant (hi_val);
+ APPEND (result, val_string->str);
+ FREE (val_string);
+ val = TREE_CHAIN (val);
+ if (val == NULL_TREE)
+ break;
+ APPEND (result, ", ");
+ }
+ APPEND (result, "]");
+ }
+ }
+ return result;
+ case COMPONENT_REF:
+ {
+ tree op1;
+
+ mode_string = decode_constant (TREE_OPERAND (init, 0));
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ op1 = TREE_OPERAND (init, 1);
+ if (TREE_CODE (op1) != IDENTIFIER_NODE)
+ {
+ error ("decode_constant: invalid component_ref");
+ break;
+ }
+ APPEND (result, ".");
+ APPEND (result, IDENTIFIER_POINTER (op1));
+ return result;
+ }
+ fail:
+ error ("decode_constant: mode and value mismatch");
+ break;
+ default:
+ error ("decode_constant: cannot decode this mode");
+ break;
+ }
+ return result;
+}
+
+static MYSTRING *
+decode_constant_selective (init, all_decls)
+ tree init;
+ tree all_decls;
+{
+ MYSTRING *result = newstring ("");
+ MYSTRING *tmp_string;
+ tree type = TREE_TYPE (init);
+ tree val = init;
+ char *op;
+ char wrk[256];
+ MYSTRING *mode_string;
+
+ switch ((enum chill_tree_code)TREE_CODE (val))
+ {
+ case CALL_EXPR:
+ tmp_string = decode_constant_selective (TREE_OPERAND (val, 0), all_decls);
+ if (tmp_string->len)
+ APPEND (result, tmp_string->str);
+ FREE (tmp_string);
+ val = TREE_OPERAND (val, 1); /* argument list */
+ if (val != NULL_TREE && TREE_CODE (val) != TREE_LIST)
+ {
+ tmp_string = decode_constant_selective (val, all_decls);
+ if (tmp_string->len)
+ {
+ MAYBE_NEWLINE (result);
+ APPEND (result, tmp_string->str);
+ }
+ FREE (tmp_string);
+ }
+ else
+ {
+ if (val != NULL_TREE)
+ {
+ for (;;)
+ {
+ tmp_string = decode_constant_selective (TREE_VALUE (val), all_decls);
+ if (tmp_string->len)
+ {
+ MAYBE_NEWLINE (result);
+ APPEND (result, tmp_string->str);
+ }
+ FREE (tmp_string);
+ val = TREE_CHAIN (val);
+ if (val == NULL_TREE)
+ break;
+ }
+ }
+ }
+ return result;
+
+ case NOP_EXPR:
+ /* Generate an "expression conversion" expression (a cast). */
+ tmp_string = decode_mode_selective (type, all_decls);
+ if (tmp_string->len)
+ APPEND (result, tmp_string->str);
+ FREE (tmp_string);
+ val = TREE_OPERAND (val, 0);
+ type = TREE_TYPE (val);
+
+ /* If the coercee is a tuple, make sure it is prefixed by its mode. */
+ if (TREE_CODE (val) == CONSTRUCTOR
+ && !CH_BOOLS_TYPE_P (type) && !chill_varying_type_p (type))
+ {
+ tmp_string = decode_mode_selective (type, all_decls);
+ if (tmp_string->len)
+ APPEND (result, tmp_string->str);
+ FREE (tmp_string);
+ }
+
+ tmp_string = decode_constant_selective (val, all_decls);
+ if (tmp_string->len)
+ APPEND (result, tmp_string->str);
+ FREE (tmp_string);
+ return result;
+
+ case IDENTIFIER_NODE:
+ tmp_string = decode_mode_selective (val, all_decls);
+ if (tmp_string->len)
+ APPEND (result, tmp_string->str);
+ FREE (tmp_string);
+ return result;
+
+ case PAREN_EXPR:
+ tmp_string = decode_constant_selective (TREE_OPERAND (val, 0), all_decls);
+ if (tmp_string->len)
+ APPEND (result, tmp_string->str);
+ FREE (tmp_string);
+ return result;
+
+ case UNDEFINED_EXPR:
+ return result;
+
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ case MULT_EXPR:
+ case TRUNC_DIV_EXPR:
+ case FLOOR_MOD_EXPR:
+ case TRUNC_MOD_EXPR:
+ case CONCAT_EXPR:
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ case TRUTH_ORIF_EXPR:
+ case BIT_AND_EXPR:
+ case TRUTH_ANDIF_EXPR:
+ case GT_EXPR:
+ case GE_EXPR:
+ case SET_IN_EXPR:
+ case LT_EXPR:
+ case LE_EXPR:
+ case EQ_EXPR:
+ case NE_EXPR:
+ goto binary;
+ case RANGE_EXPR:
+ if (TREE_OPERAND (val, 0) == NULL_TREE)
+ return result;
+
+ binary:
+ tmp_string = decode_constant_selective (TREE_OPERAND (val, 0), all_decls);
+ if (tmp_string->len)
+ APPEND (result, tmp_string->str);
+ FREE (tmp_string);
+ tmp_string = decode_constant_selective (TREE_OPERAND (val, 1), all_decls);
+ if (tmp_string->len)
+ {
+ MAYBE_NEWLINE (result);
+ APPEND (result, tmp_string->str);
+ }
+ FREE (tmp_string);
+ return result;
+
+ case REPLICATE_EXPR:
+ tmp_string = decode_constant_selective (TREE_OPERAND (val, 0), all_decls);
+ if (tmp_string->len)
+ APPEND (result, tmp_string->str);
+ FREE (tmp_string);
+ tmp_string = decode_constant_selective (TREE_OPERAND (val, 1), all_decls);
+ if (tmp_string->len)
+ {
+ MAYBE_NEWLINE (result);
+ APPEND (result, tmp_string->str);
+ }
+ FREE (tmp_string);
+ return result;
+
+ case NEGATE_EXPR:
+ case BIT_NOT_EXPR:
+ case ADDR_EXPR:
+ tmp_string = decode_constant_selective (TREE_OPERAND (val, 0), all_decls);
+ if (tmp_string->len)
+ APPEND (result, tmp_string->str);
+ FREE (tmp_string);
+ return result;
+
+ case INTEGER_CST:
+ return result;
+
+ case REAL_CST:
+ return result;
+
+ case STRING_CST:
+ return result;
+
+ case CONSTRUCTOR:
+ val = TREE_OPERAND (val, 1);
+ if (type != NULL && TREE_CODE (type) == SET_TYPE
+ && CH_BOOLS_TYPE_P (type))
+ /* It's a bitstring. */
+ return result;
+ else
+ { /* It's some kind of tuple */
+ if (type != NULL_TREE)
+ {
+ mode_string = get_type_selective (type, all_decls);
+ if (mode_string->len)
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ }
+ if (val == NULL_TREE
+ || TREE_CODE (val) == ERROR_MARK)
+ return result;
+ else if (TREE_CODE (val) != TREE_LIST)
+ goto fail;
+ else
+ {
+ for ( ; ; )
+ {
+ tree lo_val = TREE_PURPOSE (val);
+ tree hi_val = TREE_VALUE (val);
+ MYSTRING *val_string;
+ if (lo_val != NULL_TREE)
+ {
+ val_string = decode_constant_selective (lo_val, all_decls);
+ if (val_string->len)
+ APPEND (result, val_string->str);
+ FREE (val_string);
+ }
+ val_string = decode_constant_selective (hi_val, all_decls);
+ if (val_string->len)
+ {
+ MAYBE_NEWLINE (result);
+ APPEND (result, val_string->str);
+ }
+ FREE (val_string);
+ val = TREE_CHAIN (val);
+ if (val == NULL_TREE)
+ break;
+ }
+ }
+ }
+ return result;
+ case COMPONENT_REF:
+ {
+ mode_string = decode_constant_selective (TREE_OPERAND (init, 0), all_decls);
+ if (mode_string->len)
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ return result;
+ }
+ fail:
+ error ("decode_constant_selective: mode and value mismatch");
+ break;
+ default:
+ error ("decode_constant_selective: cannot decode this mode");
+ break;
+ }
+ return result;
+}
+
+/* Assuming DECL is an ALIAS_DECL, return its prefix rename clause. */
+
+static MYSTRING *
+decode_prefix_rename (decl)
+ tree decl;
+{
+ MYSTRING *result = newstring ("");
+ if (DECL_OLD_PREFIX (decl) || DECL_NEW_PREFIX (decl))
+ {
+ APPEND (result, "(");
+ if (DECL_OLD_PREFIX (decl))
+ APPEND (result, IDENTIFIER_POINTER (DECL_OLD_PREFIX (decl)));
+ APPEND (result, "->");
+ if (DECL_NEW_PREFIX (decl))
+ APPEND (result, IDENTIFIER_POINTER (DECL_NEW_PREFIX (decl)));
+ APPEND (result, ")!");
+ }
+ if (DECL_POSTFIX_ALL (decl))
+ APPEND (result, "ALL");
+ else
+ APPEND (result, IDENTIFIER_POINTER (DECL_POSTFIX (decl)));
+ return result;
+}
+
+static MYSTRING *
+decode_decl (decl)
+ tree decl;
+{
+ MYSTRING *result = newstring ("");
+ MYSTRING *mode_string;
+ tree type;
+
+ switch ((enum chill_tree_code)TREE_CODE (decl))
+ {
+ case VAR_DECL:
+ case BASED_DECL:
+ APPEND (result, "DCL ");
+ APPEND (result, IDENTIFIER_POINTER (DECL_NAME (decl)));
+ APPEND (result, " ");
+ mode_string = get_type (TREE_TYPE (decl));
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ if ((enum chill_tree_code)TREE_CODE (decl) == BASED_DECL)
+ {
+ APPEND (result, " BASED (");
+ APPEND (result, IDENTIFIER_POINTER (DECL_ABSTRACT_ORIGIN (decl)));
+ APPEND (result, ")");
+ }
+ break;
+
+ case TYPE_DECL:
+ if (CH_DECL_SIGNAL (decl))
+ {
+ /* this is really a signal */
+ tree fields = TYPE_FIELDS (TREE_TYPE (decl));
+ tree signame = DECL_NAME (decl);
+ tree sigdest;
+
+ APPEND (result, "SIGNAL ");
+ APPEND (result, IDENTIFIER_POINTER (signame));
+ if (IDENTIFIER_SIGNAL_DATA (signame))
+ {
+ APPEND (result, " = (");
+ for ( ; fields != NULL_TREE;
+ fields = TREE_CHAIN (fields))
+ {
+ MYSTRING *mode_string;
+
+ mode_string = get_type (TREE_TYPE (fields));
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ if (TREE_CHAIN (fields) != NULL_TREE)
+ APPEND (result, ", ");
+ }
+ APPEND (result, ")");
+ }
+ sigdest = IDENTIFIER_SIGNAL_DEST (signame);
+ if (sigdest != NULL_TREE)
+ {
+ APPEND (result, " TO ");
+ APPEND (result, IDENTIFIER_POINTER (DECL_NAME (sigdest)));
+ }
+ }
+ else
+ {
+ /* avoid defining a mode as itself */
+ if (CH_NOVELTY (TREE_TYPE (decl)) == decl)
+ APPEND (result, "NEWMODE ");
+ else
+ APPEND (result, "SYNMODE ");
+ APPEND (result, IDENTIFIER_POINTER (DECL_NAME (decl)));
+ APPEND (result, " = ");
+ mode_string = decode_mode (TREE_TYPE (decl));
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ }
+ break;
+
+ case FUNCTION_DECL:
+ {
+ tree args;
+
+ type = TREE_TYPE (decl);
+ args = TYPE_ARG_TYPES (type);
+
+ APPEND (result, IDENTIFIER_POINTER (DECL_NAME (decl)));
+
+ if (CH_DECL_PROCESS (decl))
+ APPEND (result, ": PROCESS (");
+ else
+ APPEND (result, ": PROC (");
+
+ args = TYPE_ARG_TYPES (type);
+
+ mode_string = print_proc_tail (type, args, 1);
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+
+ /* generality */
+ if (CH_DECL_GENERAL (decl))
+ APPEND (result, " GENERAL");
+ if (CH_DECL_SIMPLE (decl))
+ APPEND (result, " SIMPLE");
+ if (DECL_INLINE (decl))
+ APPEND (result, " INLINE");
+ if (CH_DECL_RECURSIVE (decl))
+ APPEND (result, " RECURSIVE");
+ APPEND (result, " END");
+ }
+ break;
+
+ case FIELD_DECL:
+ APPEND (result, IDENTIFIER_POINTER (DECL_NAME (decl)));
+ APPEND (result, " ");
+ mode_string = get_type (TREE_TYPE (decl));
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ if (DECL_INITIAL (decl) != NULL_TREE)
+ {
+ mode_string = decode_layout (DECL_INITIAL (decl));
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ }
+#if 0
+ if (is_forbidden (DECL_NAME (decl), forbid))
+ APPEND (result, " FORBID");
+#endif
+ break;
+
+ case CONST_DECL:
+ if (DECL_INITIAL (decl) == NULL_TREE
+ || TREE_CODE (DECL_INITIAL (decl)) == ERROR_MARK)
+ break;
+ APPEND (result, "SYN ");
+ APPEND (result, IDENTIFIER_POINTER (DECL_NAME (decl)));
+ APPEND (result, " ");
+ mode_string = get_type (TREE_TYPE (decl));
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ APPEND (result, " = ");
+ mode_string = decode_constant (DECL_INITIAL (decl));
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ break;
+
+ case ALIAS_DECL:
+ /* If CH_DECL_GRANTED, decl was granted into this scope, and
+ so wasn't in the source code. */
+ if (!CH_DECL_GRANTED (decl))
+ {
+ static int restricted = 0;
+
+ if (DECL_SEIZEFILE (decl) != use_seizefile_name
+ && DECL_SEIZEFILE (decl))
+ {
+ use_seizefile_name = DECL_SEIZEFILE (decl);
+ restricted = use_seizefile_name == NULL_TREE ? 0 : CH_USE_SEIZEFILE_RESTRICTED (use_seizefile_name);
+ if (! restricted)
+ grant_use_seizefile (IDENTIFIER_POINTER (use_seizefile_name));
+ mark_use_seizefile_written (use_seizefile_name);
+ }
+ if (! restricted)
+ {
+ APPEND (result, "SEIZE ");
+ mode_string = decode_prefix_rename (decl);
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ }
+ }
+ break;
+
+ default:
+ APPEND (result, "----- not implemented ------");
+ break;
+ }
+ return (result);
+}
+
+static MYSTRING *
+decode_decl_selective (decl, all_decls)
+ tree decl;
+ tree all_decls;
+{
+ MYSTRING *result = newstring ("");
+ MYSTRING *mode_string;
+ tree type;
+
+ if (CH_ALREADY_GRANTED (decl))
+ /* do nothing */
+ return result;
+
+ CH_ALREADY_GRANTED (decl) = 1;
+
+ switch ((enum chill_tree_code)TREE_CODE (decl))
+ {
+ case VAR_DECL:
+ case BASED_DECL:
+ mode_string = get_type_selective (TREE_TYPE (decl), all_decls);
+ if (mode_string->len)
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ if ((enum chill_tree_code)TREE_CODE (decl) == BASED_DECL)
+ {
+ mode_string = decode_mode_selective (DECL_ABSTRACT_ORIGIN (decl), all_decls);
+ if (mode_string->len)
+ PREPEND (result, mode_string->str);
+ FREE (mode_string);
+ }
+ break;
+
+ case TYPE_DECL:
+ if (CH_DECL_SIGNAL (decl))
+ {
+ /* this is really a signal */
+ tree fields = TYPE_FIELDS (TREE_TYPE (decl));
+ tree signame = DECL_NAME (decl);
+ tree sigdest;
+
+ if (IDENTIFIER_SIGNAL_DATA (signame))
+ {
+ for ( ; fields != NULL_TREE;
+ fields = TREE_CHAIN (fields))
+ {
+ MYSTRING *mode_string;
+
+ mode_string = get_type_selective (TREE_TYPE (fields),
+ all_decls);
+ if (mode_string->len)
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ }
+ }
+ sigdest = IDENTIFIER_SIGNAL_DEST (signame);
+ if (sigdest != NULL_TREE)
+ {
+ mode_string = decode_mode_selective (DECL_NAME (sigdest), all_decls);
+ if (mode_string->len)
+ {
+ MAYBE_NEWLINE (result);
+ APPEND (result, mode_string->str);
+ }
+ FREE (mode_string);
+ }
+ }
+ else
+ {
+ /* avoid defining a mode as itself */
+ mode_string = decode_mode_selective (TREE_TYPE (decl), all_decls);
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ }
+ break;
+
+ case FUNCTION_DECL:
+ {
+ tree args;
+
+ type = TREE_TYPE (decl);
+ args = TYPE_ARG_TYPES (type);
+
+ args = TYPE_ARG_TYPES (type);
+
+ mode_string = print_proc_tail_selective (type, args, all_decls);
+ if (mode_string->len)
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ }
+ break;
+
+ case FIELD_DECL:
+ mode_string = get_type_selective (TREE_TYPE (decl), all_decls);
+ if (mode_string->len)
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ break;
+
+ case CONST_DECL:
+ if (DECL_INITIAL (decl) == NULL_TREE
+ || TREE_CODE (DECL_INITIAL (decl)) == ERROR_MARK)
+ break;
+ mode_string = get_type_selective (TREE_TYPE (decl), all_decls);
+ if (mode_string->len)
+ APPEND (result, mode_string->str);
+ FREE (mode_string);
+ mode_string = decode_constant_selective (DECL_INITIAL (decl), all_decls);
+ if (mode_string->len)
+ {
+ MAYBE_NEWLINE (result);
+ APPEND (result, mode_string->str);
+ }
+ FREE (mode_string);
+ break;
+
+ }
+ MAYBE_NEWLINE (result);
+ return (result);
+}
+
+static void
+globalize_decl (decl)
+ tree decl;
+{
+ if (!TREE_PUBLIC (decl) && DECL_NAME (decl) &&
+ (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL))
+ {
+ extern FILE *asm_out_file;
+ extern char *first_global_object_name;
+ char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
+
+ if (!first_global_object_name)
+ first_global_object_name = name + (name[0] == '*');
+ ASM_GLOBALIZE_LABEL (asm_out_file, name);
+ }
+}
+
+
+static void
+grant_one_decl (decl)
+ tree decl;
+{
+ MYSTRING *result;
+
+ if (DECL_SOURCE_LINE (decl) == 0)
+ return;
+ result = decode_decl (decl);
+ if (result->len)
+ {
+ APPEND (result, ";\n");
+ APPEND (gstring, result->str);
+ }
+ FREE (result);
+}
+
+static void
+grant_one_decl_selective (decl, all_decls)
+ tree decl;
+ tree all_decls;
+{
+ MYSTRING *result;
+ MYSTRING *fixups;
+
+ tree d = DECL_ABSTRACT_ORIGIN (decl);
+
+ if (CH_ALREADY_GRANTED (d))
+ /* already done */
+ return;
+
+ result = decode_decl (d);
+ if (!result->len)
+ {
+ /* nothing to do */
+ FREE (result);
+ return;
+ }
+
+ APPEND (result, ";\n");
+
+ /* now process all undefined items in the decl */
+ fixups = decode_decl_selective (d, all_decls);
+ if (fixups->len)
+ {
+ PREPEND (result, fixups->str);
+ }
+ FREE (fixups);
+
+ /* we have finished a decl */
+ APPEND (selective_gstring, result->str);
+ FREE (result);
+}
+
+static int
+compare_memory_file (fname, buf)
+ char *fname;
+ char *buf;
+{
+ FILE *fb;
+ int c;
+
+ /* check if we have something to write */
+ if (!buf || !strlen (buf))
+ return (0);
+
+ if ((fb = fopen (fname, "r")) == NULL)
+ return (1);
+
+ while ((c = getc (fb)) != EOF)
+ {
+ if (c != *buf++)
+ {
+ fclose (fb);
+ return (1);
+ }
+ }
+ fclose (fb);
+ return (*buf ? 1 : 0);
+}
+
+void
+write_grant_file ()
+{
+ FILE *fb;
+
+ /* We only write out the grant file if it has changed,
+ to avoid changing its time-stamp and triggering an
+ unnecessary 'make' action. Return if no change. */
+ if (gstring == NULL || !spec_module_generated ||
+ !compare_memory_file (grant_file_name, gstring->str))
+ return;
+
+ fb = fopen (grant_file_name, "w");
+ if (fb == NULL)
+ pfatal_with_name (grant_file_name);
+
+ /* write file. Due to problems with record sizes on VAX/VMS
+ write string to '\n' */
+#ifdef VMS
+ /* do it this way for VMS, cause of problems with
+ record sizes */
+ p = gstring->str;
+ while (*p)
+ {
+ extern char* strchr ();
+ p1 = strchr (p, '\n');
+ c = *++p1;
+ *p1 = '\0';
+ fprintf (fb, "%s", p);
+ *p1 = c;
+ p = p1;
+ }
+#else
+ /* faster way to write */
+ if (write (fileno (fb), gstring->str, gstring->len) < 0)
+ {
+ int save_errno = errno;
+ unlink (grant_file_name);
+ errno = save_errno;
+ pfatal_with_name (grant_file_name);
+ }
+#endif
+ fclose (fb);
+}
+
+
+/* handle grant statement */
+
+void
+set_default_grant_file ()
+{
+#undef strrchr
+ extern char *strrchr ();
+ char *p, *tmp, *fname;
+
+ if (dump_base_name)
+ fname = dump_base_name; /* Probably invoked via gcc */
+ else
+ { /* Probably invoked directly (not via gcc) */
+ fname = asm_file_name;
+ if (!fname)
+ fname = main_input_filename ? main_input_filename : input_filename;
+ if (!fname)
+ return;
+ }
+
+ p = strrchr (fname, '.');
+ if (!p)
+ {
+ tmp = (char *) alloca (strlen (fname) + 10);
+ strcpy (tmp, fname);
+ }
+ else
+ {
+ int i = p - fname;
+
+ tmp = (char *) alloca (i + 10);
+ strncpy (tmp, fname, i);
+ tmp[i] = '\0';
+ }
+ strcat (tmp, ".grt");
+ default_grant_file = build_string (strlen (tmp), tmp);
+
+ grant_file_name = TREE_STRING_POINTER (default_grant_file);
+
+ if (gstring == NULL)
+ gstring = newstring ("");
+ if (selective_gstring == NULL)
+ selective_gstring = newstring ("");
+}
+
+/* Make DECL visible under the name NAME in the (fake) outermost scope. */
+
+void
+push_granted (name, decl)
+ tree name, decl;
+{
+#if 0
+ IDENTIFIER_GRANTED_VALUE (name) = decl;
+ granted_decls = tree_cons (name, decl, granted_decls);
+#endif
+}
+
+void
+chill_grant (old_prefix, new_prefix, postfix, forbid)
+ tree old_prefix;
+ tree new_prefix;
+ tree postfix;
+ tree forbid;
+{
+ if (pass == 1)
+ {
+#if 0
+ tree old_name = old_prefix == NULL_TREE ? postfix
+ : get_identifier3 (IDENTIFIER_POINTER (old_prefix),
+ "!", IDENTIFIER_POINTER (postfix));
+ tree new_name = new_prefix == NULL_TREE ? postfix
+ : get_identifier3 (IDENTIFIER_POINTER (new_prefix),
+ "!", IDENTIFIER_POINTER (postfix));
+#endif
+ tree alias = build_alias_decl (old_prefix, new_prefix, postfix);
+ CH_DECL_GRANTED (alias) = 1;
+ DECL_SEIZEFILE (alias) = current_seizefile_name;
+ TREE_CHAIN (alias) = current_module->granted_decls;
+ current_module->granted_decls = alias;
+
+ if (forbid)
+ warning ("FORBID is not yet implemented"); /* FIXME */
+ }
+}
+
+/* flag GRANT ALL only once. Avoids search in case of GRANT ALL. */
+static int grant_all_seen = 0;
+
+/* check if a decl is in the list of granted decls. */
+static int
+search_in_list (name, granted_decls)
+ tree name;
+ tree granted_decls;
+{
+ tree vars;
+
+ for (vars = granted_decls; vars != NULL_TREE; vars = TREE_CHAIN (vars))
+ if (DECL_SOURCE_LINE (vars))
+ {
+ if (DECL_POSTFIX_ALL (vars))
+ {
+ grant_all_seen = 1;
+ return 1;
+ }
+ else if (name == DECL_NAME (vars))
+ return 1;
+ }
+ /* not found */
+ return 0;
+}
+
+static int
+really_grant_this (decl, granted_decls)
+ tree decl;
+ tree granted_decls;
+{
+ /* we never grant labels at module level */
+ if ((enum chill_tree_code)TREE_CODE (decl) == LABEL_DECL)
+ return 0;
+
+ if (grant_all_seen)
+ return 1;
+
+ switch ((enum chill_tree_code)TREE_CODE (decl))
+ {
+ case VAR_DECL:
+ case BASED_DECL:
+ case FUNCTION_DECL:
+ return search_in_list (DECL_NAME (decl), granted_decls);
+ case ALIAS_DECL:
+ case CONST_DECL:
+ return 1;
+ case TYPE_DECL:
+ if (CH_DECL_SIGNAL (decl))
+ return search_in_list (DECL_NAME (decl), granted_decls);
+ else
+ return 1;
+ }
+
+ /* this nerver should happen */
+ error_with_decl (decl, "function \"really_grant_this\" called for `%s'.");
+ return 1;
+}
+
+/* Write a SPEC MODULE using the declarations in the list DECLS. */
+static int header_written = 0;
+static char *header_template =
+"--\n-- WARNING: this file was generated by\n\
+-- GNUCHILL version %s\n-- based on gcc version %s\n--\n";
+
+void
+write_spec_module (decls, granted_decls)
+ tree decls;
+ tree granted_decls;
+{
+ tree vars;
+ char *hdr;
+
+ if (granted_decls == NULL_TREE)
+ return;
+
+ use_seizefile_name = NULL_TREE;
+
+ if (!header_written)
+ {
+ hdr = (char*) alloca (strlen (gnuchill_version)
+ + strlen (version_string)
+ + strlen (header_template) + 1);
+ sprintf (hdr, header_template, gnuchill_version, version_string);
+ APPEND (gstring, hdr);
+ header_written = 1;
+ }
+ APPEND (gstring, IDENTIFIER_POINTER (current_module->name));
+ APPEND (gstring, ": SPEC MODULE\n");
+
+ /* first of all we look for GRANT ALL specified */
+ search_in_list (NULL_TREE, granted_decls);
+
+ if (grant_all_seen != 0)
+ {
+ /* write all identifiers to grant file */
+ for (vars = decls; vars != NULL_TREE; vars = TREE_CHAIN (vars))
+ {
+ if (DECL_SOURCE_LINE (vars))
+ {
+ if (DECL_NAME (vars))
+ {
+ if ((TREE_CODE (vars) != CONST_DECL || !CH_DECL_ENUM (vars)) &&
+ really_grant_this (vars, granted_decls))
+ grant_one_decl (vars);
+ }
+ else if (DECL_POSTFIX_ALL (vars))
+ {
+ static int restricted = 0;
+
+ if (DECL_SEIZEFILE (vars) != use_seizefile_name
+ && DECL_SEIZEFILE (vars))
+ {
+ use_seizefile_name = DECL_SEIZEFILE (vars);
+ restricted = use_seizefile_name == NULL_TREE ? 0 : CH_USE_SEIZEFILE_RESTRICTED (use_seizefile_name);
+ if (! restricted)
+ grant_use_seizefile (IDENTIFIER_POINTER (use_seizefile_name));
+ mark_use_seizefile_written (use_seizefile_name);
+ }
+ if (! restricted)
+ {
+ APPEND (gstring, "SEIZE ALL;\n");
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ seizefile_list *wrk, *x;
+
+ /* do a selective write to the grantfile. This will reduce the
+ size of a grantfile and speed up compilation of
+ modules depending on this grant file */
+
+ if (selective_gstring == 0)
+ selective_gstring = newstring ("");
+
+ /* first of all process all SEIZE ALL's */
+ for (vars = decls; vars != NULL_TREE; vars = TREE_CHAIN (vars))
+ {
+ if (DECL_SOURCE_LINE (vars)
+ && DECL_POSTFIX_ALL (vars))
+ grant_seized_identifier (vars);
+ }
+
+ /* now walk through granted decls */
+ granted_decls = nreverse (granted_decls);
+ for (vars = granted_decls; vars != NULL_TREE; vars = TREE_CHAIN (vars))
+ {
+ grant_one_decl_selective (vars, decls);
+ }
+ granted_decls = nreverse (granted_decls);
+
+ /* append all SEIZES */
+ wrk = selective_seizes;
+ while (wrk != 0)
+ {
+ x = wrk->next;
+ APPEND (gstring, wrk->seizes->str);
+ FREE (wrk->seizes);
+ free (wrk);
+ wrk = x;
+ }
+ selective_seizes = 0;
+
+ /* append generated string to grant file */
+ APPEND (gstring, selective_gstring->str);
+ FREE (selective_gstring);
+ selective_gstring = NULL;
+ }
+
+ for (vars = granted_decls; vars != NULL_TREE; vars = TREE_CHAIN (vars))
+ if (DECL_SOURCE_LINE (vars))
+ {
+ MYSTRING *mode_string = decode_prefix_rename (vars);
+ APPEND (gstring, "GRANT ");
+ APPEND (gstring, mode_string->str);
+ FREE (mode_string);
+ APPEND (gstring, ";\n");
+ }
+
+ APPEND (gstring, "END;\n");
+ spec_module_generated = 1;
+
+ /* initialize this for next spec module */
+ grant_all_seen = 0;
+}
+
+/*
+ * after the dark comes, after all of the modules are at rest,
+ * we tuck the compilation unit to bed... A story in pass 1
+ * and a hug-and-a-kiss goodnight in pass 2.
+ */
+void
+chill_finish_compile ()
+{
+ tree global_list;
+ tree chill_init_function;
+
+ tasking_setup ();
+ build_enum_tables ();
+
+ /* We only need an initializer function for the source file if
+ a) there's module-level code to be called, or
+ b) tasking-related stuff to be initialized. */
+ if (module_init_list != NULL_TREE || tasking_list != NULL_TREE)
+ {
+ extern tree initializer_type;
+ static tree chill_init_name;
+
+ /* declare the global initializer list */
+ global_list = do_decl (get_identifier ("_ch_init_list"),
+ build_chill_pointer_type (initializer_type), 1, 0,
+ NULL_TREE, 1);
+
+ /* Now, we're building the function which is the *real*
+ constructor - if there's any module-level code in this
+ source file, the compiler puts the file's initializer entry
+ onto the global initializer list, so each module's body code
+ will eventually get called, after all of the processes have
+ been started up. */
+
+ /* This is better done in pass 2 (when first_global_object_name
+ may have been set), but that is too late.
+ Perhaps rewrite this so nothing is done in pass 1. */
+ if (pass == 1)
+ {
+ extern char *first_global_object_name;
+ /* If we don't do this spoof, we get the name of the first
+ tasking_code variable, and not the file name. */
+ char *tmp = first_global_object_name;
+
+ first_global_object_name = NULL;
+ chill_init_name = get_file_function_name ('I');
+ first_global_object_name = tmp;
+ /* strip off the file's extension, if any. */
+ tmp = strrchr (IDENTIFIER_POINTER (chill_init_name), '.');
+ if (tmp)
+ *tmp = '\0';
+ }
+
+ start_chill_function (chill_init_name, void_type_node, NULL_TREE,
+ NULL_TREE, NULL_TREE);
+ TREE_PUBLIC (current_function_decl) = 1;
+ chill_init_function = current_function_decl;
+
+ /* For each module that we've compiled, that had module-level
+ code to be called, add its entry to the global initializer
+ list. */
+
+ if (pass == 2)
+ {
+ tree module_init;
+
+ for (module_init = module_init_list;
+ module_init != NULL_TREE;
+ module_init = TREE_CHAIN (module_init))
+ {
+ tree init_entry = TREE_VALUE (module_init);
+
+ /* assign module_entry.next := _ch_init_list; */
+ expand_expr_stmt (
+ build_chill_modify_expr (
+ build_component_ref (init_entry,
+ get_identifier ("__INIT_NEXT")),
+ global_list));
+
+ /* assign _ch_init_list := &module_entry; */
+ expand_expr_stmt (
+ build_chill_modify_expr (global_list,
+ build1 (ADDR_EXPR, ptr_type_node, init_entry)));
+ }
+ }
+
+ tasking_registry ();
+
+ make_decl_rtl (current_function_decl, NULL, 1);
+
+ finish_chill_function ();
+
+ if (pass == 2)
+ {
+ assemble_constructor (IDENTIFIER_POINTER (chill_init_name));
+ globalize_decl (chill_init_function);
+ }
+
+ /* ready now to link decls onto this list in pass 2. */
+ module_init_list = NULL_TREE;
+ tasking_list = NULL_TREE;
+ }
+}
+
+