summaryrefslogtreecommitdiff
path: root/support/ltx2x/l2xidecl.c
diff options
context:
space:
mode:
Diffstat (limited to 'support/ltx2x/l2xidecl.c')
-rw-r--r--support/ltx2x/l2xidecl.c958
1 files changed, 958 insertions, 0 deletions
diff --git a/support/ltx2x/l2xidecl.c b/support/ltx2x/l2xidecl.c
new file mode 100644
index 0000000000..8777516b0a
--- /dev/null
+++ b/support/ltx2x/l2xidecl.c
@@ -0,0 +1,958 @@
+/* l2xidecl.c LTX2X interpreter parsing routines for declarations */
+/* Written by: Peter Wilson, CUA pwilson@cme.nist.gov */
+/* This code is partly based on algorithms presented by Ronald Mak in */
+/* "Writing Compilers & Interpreters", John Wiley & Sons, 1991 */
+
+#include <stdio.h>
+#include "l2xicmon.h"
+#include "l2xierr.h"
+#include "l2xiscan.h"
+#include "l2xisymt.h"
+#include "l2xiprse.h"
+#include "l2xiidbg.h"
+#ifndef l2xicpr_h
+#include "l2xicpr.h"
+#endif
+
+#include "listsetc.h"
+
+
+/* EXTERNALS */
+
+extern TOKEN_CODE token;
+extern char word_string[];
+extern LITERAL literal;
+extern SYMTAB_NODE_PTR symtab_display[];
+extern int level;
+
+extern SYMTAB_NODE_PTR string_idp;
+
+/* FORWARDS */
+
+TYPE_STRUCT_PTR identifier_type(), enumeration_type(),
+ subrange_type(), array_type();
+
+TYPE_STRUCT_PTR get_type(), get_array_type(), get_bound_spec_type();
+
+TYPE_STRUCT_PTR an_entity(), a_type(), get_bls_type();
+
+TOKEN_CODE express_decl_list[] = {XENTITY, TYPE, XRULE,
+ FUNCTION, PROCEDURE, 0};
+
+
+/***************************************************************************/
+/* declarations(rtn_idp) Call routines to process constant definitions, */
+/* type definitions, variable declarations, */
+/* procedure definitions, function definitions. */
+/* at entry, token is one of declaration_start_list bag */
+/* at exit, token is the one following all declarations (e.g., start */
+/* of assignment statement) */
+
+declarations(rtn_idp)
+SYMTAB_NODE_PTR rtn_idp; /* program or routine id */
+{
+ entry_debug("declarations");
+
+ /* for EXPRESS */
+ /* loop for general declarations */
+ while (token_in(express_decl_list)) {
+ switch (token) {
+ case XENTITY: {
+ an_entity();
+ break;
+ }
+ case TYPE: {
+ a_type();
+ break;
+ }
+ case XRULE: {
+ a_rule();
+ break;
+ }
+ case PROCEDURE: {
+ a_procedure();
+ break;
+ }
+ case FUNCTION: {
+ a_function();
+ break;
+ }
+ default: {
+ error(UNIMPLEMENTED_FEATURE);
+ break;
+ }
+ } /* end switch */
+ } /* end while over general declarations */
+
+ if (token == XCONSTANT) {
+ get_token();
+ constant_block();
+ }
+ if (token == XLOCAL) {
+ get_token();
+ local_block(rtn_idp);
+ }
+
+ exit_debug("declarations");
+ return;
+
+} /* end declarations */
+/***************************************************************************/
+
+
+/***************************************************************************/
+/* skip_declarations(rtn_idp) Skip declaration parsing */
+
+skip_declarations(rtn_idp)
+SYMTAB_NODE_PTR rtn_idp; /* program id */
+{
+ SYMTAB_NODE_PTR const_idp; /* constant id */
+ char tmp_buff[MAX_SOURCE_LINE_LENGTH];
+ entry_debug("skip_declarations");
+
+ strcpy(tmp_buff, word_string);
+ strcpy(word_string, "_ZeRo");
+
+ search_and_enter_local_symtab(const_idp);
+ strcpy(word_string, tmp_buff);
+ const_idp->defn.key = CONST_DEFN;
+
+ const_idp->defn.info.constant.value.integer = 0;
+ const_idp->typep = integer_typep;
+
+ analyze_const_defn(const_idp);
+
+ exit_debug("skip_declarations");
+ return;
+} /* end SKIP_DECLARATIONS */
+/***************************************************************************/
+
+
+/* EXPRESS CONSTANTS and LOCALS */
+
+/***************************************************************************/
+/* constant_block() Process EXPRESS constant block */
+/* CONSTANT { <constant_definition> } END_CONSTANT ; */
+/* at entry, current token is CONSTANT */
+/* at exit, current token is after the semicolon */
+
+constant_block()
+{
+ entry_debug("constant_block");
+
+ error(UNIMPLEMENTED_FEATURE);
+
+ while (token != XEND_CONSTANT) {
+ get_token();
+ }
+
+ get_token();
+ if_token_get_else_error(SEMICOLON, MISSING_SEMICOLON);
+
+ exit_debug("constant_block");
+ return;
+} /* end CONSTANT_BLOCK */
+/***************************************************************************/
+
+
+/***************************************************************************/
+/* a_constant_definition() Process EXPRESS constant */
+/* <constant_id> : <type> := <expression> ; */
+/* at entry, current token is <constant_id> */
+/* at exit, current token is after closing semicolon */
+
+a_constant_definition()
+{
+ SYMTAB_NODE_PTR type_idp; /* constant id */
+
+ if (token != IDENTIFIER) {
+ error(UNEXPECTED_TOKEN);
+ return;
+ }
+
+ search_and_enter_local_symtab(type_idp);
+ type_idp->defn.key = TYPE_DEFN;
+
+ get_token();
+ if_token_get_else_error(COLON, MISSING_COLON);
+
+ /* process the type */
+ type_idp->typep = get_type();
+ if (type_idp->typep->type_idp == NULL) {
+ type_idp->typep->type_idp = type_idp;
+ }
+
+ get_token();
+ if_token_get_else_error(COLONEQUAL, MISSING_COLONEQUAL);
+
+ /* process the expression */ /* SKIP THIS FOR NOW */
+ while (token != SEMICOLON) {
+ get_token();
+ }
+ get_token();
+
+ return;
+
+} /* end A_CONSTANT_DEFINITION */
+/***************************************************************************/
+
+
+
+/***************************************************************************/
+/* local_block(rtn_idp) Process EXPRESS local block */
+/* LOCAL { <local_definition> } END_LOCAL ; */
+/* at entry, current token is the one after LOCAL */
+/* at exit, current token is after closing semicolon */
+
+local_block(rtn_idp)
+SYMTAB_NODE_PTR rtn_idp; /* id of routine */
+{
+ entry_debug("local_block");
+
+ local_decls(rtn_idp,
+ STACK_FRAME_HEADER_SIZE + rtn_idp->defn.info.routine.parm_count);
+
+ exit_debug("local_block");
+ return;
+} /* end LOCAL_BLOCK */
+/***************************************************************************/
+
+
+/***************************************************************************/
+/* local_decls(rtn_idp, record_tp, offset) Process EXPRESS local variables */
+/* at entry, current token is <var_id> */
+/* at exit, current token is after closing END_LOCAL ; */
+
+local_decls(rtn_idp, offset)
+SYMTAB_NODE_PTR rtn_idp;
+int offset;
+{
+ SYMTAB_NODE_PTR idp, first_idp, last_idp; /* variable ids */
+ SYMTAB_NODE_PTR prev_last_idp = NULL; /* last id of a list */
+ TYPE_STRUCT_PTR tp; /* type */
+ int size;
+ int total_size = 0;
+
+ entry_debug("local_decls");
+
+ /* loop to process sublist, each of a single type */
+ while (token == IDENTIFIER) { /* loop over semicolon seperated list */
+ first_idp = NULL;
+
+ /* loop to process each var in a list */
+ while (token == IDENTIFIER) { /* loop over comma seperated list */
+ search_and_enter_local_symtab(idp);
+ idp->defn.key = VAR_DEFN;
+ idp->label_index = 0;
+
+ /* link ids into a sublist */
+ if (first_idp == NULL) {
+ first_idp = last_idp = idp;
+ if (rtn_idp->defn.info.routine.locals == NULL) {
+ rtn_idp->defn.info.routine.locals = idp;
+ }
+ }
+ else {
+ last_idp->next = idp;
+ last_idp = idp;
+ }
+ get_token();
+ if_token_get(COMMA);
+ } /* end while over a comma seperated list */
+
+ /* Process the sublist's type */
+ if_token_get_else_error(COLON, MISSING_COLON);
+ tp = get_type();
+ size = tp->size;
+
+ /* Assign the offset and the type to all ids in the list */
+ for (idp = first_idp; idp != NULL; idp = idp->next) {
+ idp->typep = tp;
+ total_size += size;
+ idp->defn.info.data.offset = offset++;
+ analyze_var_decl(idp);
+ } /* end for */
+
+ /* link this sublist to previous sublist */
+ if (prev_last_idp != NULL) prev_last_idp->next = first_idp;
+ prev_last_idp = last_idp;
+
+ /* optional expression here SKIP FOR NOW */
+ get_token();
+ if_token_get_else_error(SEMICOLON, MISSING_SEMICOLON);
+
+ } /* end while over semicolon seperated list */
+
+ if_token_get_else_error(XEND_LOCAL, MISSING_END);
+ if_token_get_else_error(SEMICOLON, MISSING_SEMICOLON);
+
+ rtn_idp->defn.info.routine.total_local_size = total_size;
+
+ exit_debug("local_decls");
+ return;
+} /* end LOCAL_DECLS */
+/***************************************************************************/
+
+
+
+/***************************************************************************/
+/* an_entity() Process an EXPRESS entity */
+/* ENTITY <entity_body> END_ENTITY ; */
+/* at entry, current token = ENTITY */
+/* at exit, current token is after END_ENTITY ; */
+
+TYPE_STRUCT_PTR an_entity()
+{
+ SYMTAB_NODE_PTR idp; /* entity id */
+ TYPE_STRUCT_PTR entity_tp = alloc_struct(TYPE_STRUCT);
+ entry_debug("an_entity (l2xidecl.c)");
+
+ entity_tp->form = ENTITY_FORM;
+ entity_tp->type_idp = NULL;
+ entity_tp->info.entity.attribute_symtab = NULL;
+
+ get_token(); /* name of the entity */
+ if (token != IDENTIFIER) {
+ error(UNEXPECTED_TOKEN);
+ }
+ search_and_enter_local_symtab(idp);
+ idp->defn.key = TYPE_DEFN;
+ idp->label_index = 0;
+ idp->typep = entity_tp;
+
+ get_token(); /* semicolon */
+ if_token_get_else_error(SEMICOLON, MISSING_SEMICOLON);
+
+ attribute_declarations(NULL, entity_tp, 0);
+
+ analyze_type_defn(idp);
+ /* skip to the end */
+ while (token != XEND_ENTITY) {
+ get_token();
+ }
+
+ get_token();
+ if_token_get_else_error(SEMICOLON, MISSING_SEMICOLON);
+
+ exit_debug("an_entity");
+ return(entity_tp);
+} /* end AN_ENTITY */
+/***************************************************************************/
+
+
+
+/***************************************************************************/
+/* a_type() Process an EXPRESS type */
+/* TYPE <type_body> END_TYPE ; */
+/* at entry, current token = TYPE */
+/* at exit, current token is after END_TYPE ; */
+
+TYPE_STRUCT_PTR a_type()
+{
+ SYMTAB_NODE_PTR type_idp; /* the TYPE id */
+ TYPE_STRUCT_PTR tsp; /* type structure pointer */
+ entry_debug("a_type (l2xidecl.c)");
+
+ get_token(); /* the type id */
+ if (token != IDENTIFIER) {
+ error(UNEXPECTED_TOKEN);
+ exit_debug("a_type");
+ return(&dummy_type);
+ }
+ search_and_enter_local_symtab(type_idp);
+ type_idp->defn.key = TYPE_DEFN;
+
+ get_token();
+ if_token_get_else_error(EQUAL, MISSING_EQUAL);
+
+ /* process the type */
+ if (token == XENUMERATION) { /* an ENUMERATION type */
+ get_token();
+ if_token_get_else_error(OF, MISSING_OF);
+ if (token != LPAREN) {
+ error(MISSING_LPAREN);
+ }
+ /* process the enumeration */
+ type_idp->typep = enumeration_type();
+ if_token_get_else_error(SEMICOLON, MISSING_SEMICOLON);
+ }
+ else { /* an ordinary type */
+ type_idp->typep = get_type();
+ get_token();
+ if (token != SEMICOLON) error(MISSING_SEMICOLON);
+ }
+ if (type_idp->typep->type_idp == NULL) type_idp->typep->type_idp = type_idp;
+ analyze_type_defn(type_idp);
+
+ /* skip to end of definition */
+ while (token != XEND_TYPE) {
+ get_token();
+ }
+
+ get_token();
+ if_token_get_else_error(SEMICOLON, MISSING_SEMICOLON);
+
+ exit_debug("a_type");
+ return(type_idp->typep);
+} /* end A_TYPE */
+/***************************************************************************/
+
+
+
+/***************************************************************************/
+/* a_rule() Process an EXPRESS rule */
+/* RULE <rule_body> END_RULE ; */
+/* at entry, current token = RULE */
+/* at exit, current token is after END_RULE ; */
+
+a_rule()
+{
+
+ error(UNIMPLEMENTED_FEATURE);
+
+ while (token != XEND_RULE) {
+ get_token();
+ }
+
+ get_token();
+ if_token_get_else_error(SEMICOLON, MISSING_SEMICOLON);
+
+ return;
+} /* end A_RULE */
+/***************************************************************************/
+
+
+
+
+
+
+/* CONSTANTS */
+
+
+
+
+
+/* TYPES */
+
+
+/***************************************************************************/
+/* get_type() Process a type identifier. Call the function to make the */
+/* type structure, and return pointer to it. */
+/* at entry, token is the id */
+/* at exit, token is unaltered */
+
+TYPE_STRUCT_PTR get_type()
+{
+ TYPE_STRUCT_PTR tsp;
+ entry_debug("get_type");
+
+ if (token_in(simple_type_list)) { /* predefined simple type */
+ switch (token) {
+ case XINTEGER : {
+ tsp = integer_typep;
+ break;
+ }
+ case XREAL : {
+ tsp = real_typep;
+ break;
+ }
+ case XBOOLEAN : {
+ tsp = boolean_typep;
+ break;
+ }
+ case XLOGICAL : {
+ tsp = logical_typep;
+ break;
+ }
+ case XSTRING : {
+ tsp = make_string_typep(0);
+ break;
+ }
+ default : {
+ error(UNIMPLEMENTED_SIMPLE_TYPE);
+ tsp = &dummy_type;
+ break;
+ }
+ } /* end switch */
+ exit_debug("get_type");
+ return(tsp);
+ } /* end predefined simple types */
+
+ if (token_in(aggregation_type_list)) { /* predefined aggregation type */
+ switch (token) {
+ case ARRAY : {
+ return(get_array_type());
+ break;
+ }
+ case XBAG:
+ case XLIST:
+ case SET: {
+ return(get_bls_type());
+ break;
+ }
+ default : {
+ error(UNIMPLEMENTED_AGGREGATION_TYPE);
+ tsp = &dummy_type;
+ break;
+ }
+ } /* end switch */
+ exit_debug("get_type");
+ return(tsp);
+ } /* end predefined aggregation types */
+
+
+
+
+ switch (token) {
+ case IDENTIFIER: {
+ SYMTAB_NODE_PTR idp;
+
+ search_all_symtab(idp);
+
+ if (idp == NULL) {
+ error(UNDEFINED_IDENTIFIER);
+ exit_debug("get_type");
+ return(&dummy_type);
+ }
+ else if (idp->defn.key == TYPE_DEFN) {
+ exit_debug("get_type");
+ return(identifier_type(idp));
+ }
+/* else if (idp->defn.key == CONST_DEFN) {
+ exit_debug("get_type");
+ return(subrange_type(idp));
+ } */
+ else {
+ error(NOT_A_TYPE_IDENTIFIER);
+ exit_debug("get_type");
+ return(&dummy_type);
+ }
+ }
+
+ default : {
+ error(INVALID_TYPE);
+ exit_debug("get_type");
+ return(&dummy_type);
+ }
+ } /* end switch */
+} /* end get_type */
+/***************************************************************************/
+
+
+
+/***************************************************************************/
+/* identifier_type(idp) Process an identifier type (the identifier at the */
+/* LHS of an assignment). */
+/* return pointer to the type structure. */
+
+TYPE_STRUCT_PTR identifier_type(idp)
+SYMTAB_NODE_PTR idp; /* type id */
+{
+ TYPE_STRUCT_PTR tp = NULL;
+
+ tp = idp->typep;
+/* get_token(); */
+ return(tp);
+} /* end identifier_type */
+/***************************************************************************/
+
+
+
+/***************************************************************************/
+/* enumeration_type() Process an enumeration type. */
+/* ( <id>, <id>, ... ) */
+/* Make and return a type structure. */
+/* at entry: token is opening ( */
+/* at exit: token is after closing ) */
+
+TYPE_STRUCT_PTR enumeration_type()
+{
+ SYMTAB_NODE_PTR const_idp; /* constant id */
+ SYMTAB_NODE_PTR last_idp = NULL; /* last constant id */
+ TYPE_STRUCT_PTR tp = alloc_struct(TYPE_STRUCT);
+ int const_value = -1; /* constant value */
+
+ tp->form = ENUM_FORM;
+ tp->size = sizeof(int);
+ tp->type_idp = NULL;
+
+ get_token();
+
+ /* loop to process ids */
+ while (token == IDENTIFIER) {
+ search_and_enter_local_symtab(const_idp);
+ const_idp->defn.key = CONST_DEFN;
+ const_idp->defn.info.constant.value.integer = ++const_value;
+ const_idp->typep = tp;
+
+ /* link ids into list */
+ if (last_idp == NULL) tp->info.enumeration.const_idp = last_idp = const_idp;
+ else {
+ last_idp->next = const_idp;
+ last_idp = const_idp;
+ }
+ get_token();
+ if_token_get(COMMA);
+ } /* end while */
+ if_token_get_else_error(RPAREN, MISSING_RPAREN);
+
+ tp->info.enumeration.max = const_value;
+ return(tp);
+} /* end enumeration_type */
+/***************************************************************************/
+
+
+
+
+/***************************************************************************/
+/* make_string_typep(length) Make a type structure for a string of the */
+/* given length. */
+/* return a pointer to it. */
+/* rewritten for new structure */
+
+TYPE_STRUCT_PTR make_string_typep(length)
+int length; /* string length */
+{
+ TYPE_STRUCT_PTR string_tp = alloc_struct(TYPE_STRUCT);
+ entry_debug("make_string_type");
+
+ if (length > MAX_EXPRESS_STRING) {
+ error(STRING_TOO_LONG);
+ }
+
+ string_tp->form = STRING_FORM;
+ string_tp->size = sizeof(STRING);
+ string_tp->type_idp = string_idp;
+/* string_tp->type_idp = NULL; */
+ string_tp->info.string.max_length = MAX_EXPRESS_STRING;
+ string_tp->info.string.length = length;
+
+ exit_debug("make_string_type");
+ return(string_tp);
+} /* end make_string_typep */
+/***************************************************************************/
+
+
+
+/***************************************************************************/
+/* calculate_array_size(tp) Return the size in bytes of an EXPRESS */
+/* array by recursively */
+/* calculating the size of each dimension. */
+
+int calculate_array_size(tp)
+TYPE_STRUCT_PTR tp; /* ptr to array type structure */
+{
+ if (tp->info.array.elmt_typep->size == 0) {
+ tp->info.array.elmt_typep->size =
+ calculate_array_size(tp->info.array.elmt_typep);
+ }
+
+ tp->size = tp->info.array.elmt_count * tp->info.array.elmt_typep->size;
+ return(tp->size);
+} /* end array_size */
+/***************************************************************************/
+
+
+/* VARIABLES */
+
+
+
+/***************************************************************************/
+/* attribute_declarations(rtn_idp, entity_tp, offset) */
+/* Process entity attribute definitions. All ids declared */
+/* with the same type are linked into a sublist, and all the */
+/* sublists are then liked together. */
+
+attribute_declarations(rtn_idp, entity_tp, offset)
+SYMTAB_NODE_PTR rtn_idp;
+TYPE_STRUCT_PTR entity_tp;
+int offset;
+{
+ SYMTAB_NODE_PTR idp, first_idp, last_idp; /* variable or field ids */
+ SYMTAB_NODE_PTR prev_last_idp = NULL; /* last id of a list */
+ TYPE_STRUCT_PTR tp; /* type */
+ int size;
+ int total_size = 0;
+
+ entry_debug("attribute_declarations (l2xidecl.c)");
+
+ /* loop to process sublist, each of a single type */
+ while (!token_in(follow_attributes_list)) {
+ first_idp = NULL;
+
+ /* loop to process each attribute in a list */
+ while (token == IDENTIFIER) {
+ search_and_enter_this_symtab(idp, entity_tp->info.entity.attribute_symtab);
+ idp->defn.key = ATTRIBUTE_DEFN;
+ idp->label_index = 0;
+
+ /* link ids into a sublist */
+ if (first_idp == NULL) {
+ first_idp = last_idp = idp;
+ }
+ else {
+ last_idp->next = idp;
+ last_idp = idp;
+ }
+ get_token();
+ if_token_get(COMMA);
+ } /* end while */
+
+ /* Process the sublist's type */
+ if_token_get_else_error(COLON, MISSING_COLON);
+ tp = get_type();
+ size = tp->size;
+
+ /* Assign the offset and the type to all ids in the list */
+ for (idp = first_idp; idp != NULL; idp = idp->next) {
+ idp->typep = tp;
+ idp->defn.info.data.offset = offset;
+ offset += size;
+ } /* end for */
+
+ /* link this sublist to previous sublist */
+ if (prev_last_idp != NULL) prev_last_idp->next = first_idp;
+ prev_last_idp = last_idp;
+
+ get_token(); /* move on from type processing */
+ if_token_get_else_error(SEMICOLON, MISSING_SEMICOLON);
+
+ } /* end while */
+
+ entity_tp->size = offset;
+
+ exit_debug("attribute_declarations");
+ return;
+} /* end ATTRIBUTE_DECLARATIONS */
+/***************************************************************************/
+
+
+
+
+
+
+/***************************************************************************/
+/* get_array_type() Process an array type */
+/* ARRAY <bound_spec> OF <elmt-type> */
+/* Make a structure and return pointer. */
+/* at entry: token is ARRAY */
+/* at exit: token is */
+
+TYPE_STRUCT_PTR get_array_type()
+{
+ TYPE_STRUCT_PTR tp = alloc_struct(TYPE_STRUCT);
+ TYPE_STRUCT_PTR index_tp; /* index type */
+ TYPE_STRUCT_PTR elmt_tp = tp; /* element type */
+ TYPE_STRUCT_PTR bound_tp; /* bound type */
+ int min, max, count;
+ int calculate_array_size();
+ entry_debug("get_array_type (l2xidecl.c)");
+
+ get_token();
+
+ elmt_tp->form = ARRAY_FORM;
+ elmt_tp->size = 0;
+ elmt_tp->type_idp = NULL;
+ elmt_tp->info.array.index_typep = integer_typep;
+
+ if (token != LBRACKET) error(MISSING_LBRACKET);
+
+ bound_tp = get_bound_spec_type();
+ min = bound_tp->info.bound.min;
+ max = bound_tp->info.bound.max;
+ if (min == QUERY_CHAR || max == QUERY_CHAR) {
+ error(INVALID_INDEX_TYPE);
+ count = 0;
+ }
+ else if (min > max) {
+ error(MIN_GT_MAX);
+ count = 0;
+ }
+ else {
+ elmt_tp->info.array.min_index = min;
+ elmt_tp->info.array.max_index = max;
+ count = (max - min) + 1;
+ }
+ elmt_tp->info.array.elmt_count = count;
+
+
+ /* sync. Should be OF */
+ synchronize(follow_indexes_list, declaration_start_list, statement_start_list);
+ if_token_get_else_error(OF, MISSING_OF);
+
+ /* element type */
+ elmt_tp->info.array.elmt_typep = get_type();
+ tp->size = calculate_array_size(tp); /* was array_size(tp); */
+
+ exit_debug("get_array_type");
+ return(tp);
+} /* end GET_ARRAY_TYPE */
+/***************************************************************************/
+
+
+
+/***************************************************************************/
+/* get_bls_type() Process a BAG, etc type */
+/* BAG [ <bound_spec> ] OF <elmt-type> */
+/* Make a structure and return pointer. */
+/* at entry: token is BAG */
+/* at exit: token is */
+
+TYPE_STRUCT_PTR get_bls_type()
+{
+ TYPE_STRUCT_PTR tp = alloc_struct(TYPE_STRUCT);
+ TYPE_STRUCT_PTR index_tp; /* index type */
+ TYPE_STRUCT_PTR elmt_tp = tp; /* element type */
+ TYPE_STRUCT_PTR bound_tp; /* bound type */
+ int min, max, count, size;
+ entry_debug("get_bls_type (l2xidecl.c)");
+
+ count = 0;
+ if (token == XBAG) {
+ elmt_tp->form = BAG_FORM;
+ }
+ else if (token == XLIST) {
+ elmt_tp->form = LIST_FORM;
+ }
+ else if (token == SET) {
+ elmt_tp->form = SET_FORM;
+ }
+ elmt_tp->size = 0;
+ elmt_tp->type_idp = NULL;
+ elmt_tp->info.dynagg.index_typep = integer_typep;
+
+ get_token();
+ if (token == LBRACKET) { /* a bound spec */
+ bound_tp = get_bound_spec_type();
+ min = bound_tp->info.bound.min;
+ max = bound_tp->info.bound.max;
+ if (min == QUERY_CHAR) {
+ error(INVALID_INDEX_TYPE);
+ min = 0;
+ count = 0;
+ }
+ else if (min < 0) {
+ error(INVALID_INDEX_TYPE);
+ min = 0;
+ count = 0;
+ }
+ else if (max != QUERY_CHAR) {
+ if (min > max) {
+ error(MIN_GT_MAX);
+ max = min;
+ count = 0;
+ }
+ }
+ else {
+/* count = (max - min) + 1; */
+ count = 0;
+ }
+ }
+ else { /* default [0:?] bound spec */
+ min = 0;
+ max = QUERY_CHAR;
+ count = 0;
+ }
+
+ /* sync. Should be OF */
+ synchronize(follow_indexes_list, declaration_start_list, statement_start_list);
+ if_token_get_else_error(OF, MISSING_OF);
+
+ if (max == QUERY_CHAR) {
+ max = MAX_AGG_SIZE;
+ }
+
+ elmt_tp->info.dynagg.min_index = min;
+ elmt_tp->info.dynagg.max_index = max;
+ elmt_tp->info.dynagg.elmt_count = count;
+ elmt_tp->info.dynagg.elmt_typep = get_type();
+ tp->size = sizeof(LBS_PTR);
+
+ exit_debug("get_bls_type");
+ return(tp);
+} /* end GET_BLS_TYPE */
+/***************************************************************************/
+
+
+
+/***************************************************************************/
+/* get_bound_spec_type() Process a bound spec */
+/* [ <int_expr> : <int_expr> ] */
+/* make a type structure and return a pointer to it */
+/* at entry: token is opening [ */
+/* at exit: token is after closing ] */
+
+TYPE_STRUCT_PTR get_bound_spec_type()
+{
+ TYPE_STRUCT_PTR tp;
+ entry_debug("get_bound_spec_type (l2xidecl.c)");
+
+ tp = alloc_struct(TYPE_STRUCT);
+
+ tp->form = BOUND_FORM;
+ tp->type_idp = NULL;
+ tp->size = sizeof(int);
+ tp->info.bound.bound_typep = integer_typep;
+
+ /* lower bound */
+ get_token();
+ tp->info.bound.min = get_bound_limit();
+
+ /* sync. should be a : */
+ synchronize(follow_min_bound_list, NULL, NULL);
+ if_token_get(COLON);
+ else if (token_in(follow_min_bound_list) ||
+ token_in(declaration_start_list) ||
+ token_in(statement_start_list)) error(MISSING_COLON);
+
+ /* upper bound */
+ tp->info.bound.max = get_bound_limit();
+
+ if_token_get_else_error(RBRACKET, MISSING_RBRACKET);
+
+ exit_debug("get_bound_spec_type");
+ return(tp);
+} /* end GET_BOUND_SPEC_TYPE */
+/***************************************************************************/
+
+
+/***************************************************************************/
+/* get_bound_limit(minmax_idp, minmaxp, typepp) Process the min or */
+/* max limits of a bound spec */
+/* [ + | - ] INTEGER_LITERAL */
+/* at entry: token is the limit (value) */
+/* at exit: token is after the limit */
+
+int get_bound_limit()
+{
+ TOKEN_CODE sign = PLUS; /* unary + or - sign */
+ int result = QUERY_CHAR; /* undef result */
+
+ /* unary + or - sign */
+ if ((token == PLUS) || (token == MINUS)) {
+ sign = token;
+ get_token();
+ }
+
+ /* numeric limit --- integer only */
+ if (token == NUMBER_LITERAL) {
+ if (literal.type == INTEGER_LIT) {
+ result = (sign == PLUS) ? literal.value.integer
+ : -literal.value.integer;
+ }
+ else error(INVALID_BOUND_TYPE);
+ }
+ else if (token == QUERY_CHAR) {
+ result = QUERY_CHAR;
+ }
+ else {
+ error(INVALID_BOUND_TYPE);
+ }
+
+ get_token();
+ return(result);
+} /* end GET_BOUND_LIMIT */
+/***************************************************************************/
+
+
+