/* l2xisdcl.c  LTX2X declaration analysis */
/*  Written by: Peter Wilson, CUA  [email protected]                */
/*  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 "l2xiidbg.h"

/* EXTERNALS */

extern int line_number;
extern TOKEN_CODE token;

/* GLOBALS */

char buffer[MAX_PRINT_LINE_LENGTH];

char *defn_names[] = {
#define dfntc(a, b) b,
#include "l2xidftc.h"
#undef dfntc
};


char *form_names[] = {
#define fotc(a, b, c, d) d,
#define sotc(a, b, c, d)
#define sftc(a, b, c, d) d,
#include "l2xisftc.h"
#undef fotc
#undef sotc
#undef sftc
};



/* ANALYSIS */


/***************************************************************************/
/* analyze_const_defn(idp) Analyze a constant definition                   */

analyze_const_defn(idp)
SYMTAB_NODE_PTR idp;               /* constant id */
{
 char *bp;

 if (DEBUG < Danalyze) return;

 /* the name */
 sprintf(buffer, ">> id = %s\n", idp->name);
 debug_print(buffer);
 sprintf(buffer, ">>    address = %d\n", idp);

 /* definition and value */
 sprintf(buffer, ">>    defn = %s, value = ", defn_names[idp->defn.key]);
 bp = buffer + strlen(buffer);

 if ((idp->typep == integer_typep) || (idp->typep->form == ENUM_FORM))
   sprintf(bp, "%d\n", idp->defn.info.constant.value.integer);
 else if (idp->typep == real_typep)
   sprintf(bp, "%g\n", idp->defn.info.constant.value.real);
 else if (idp->typep->form == ARRAY_FORM)  /* ????????????????????????? */
   sprintf(bp, "'%s'\n", idp->defn.info.constant.value.stringp);
 else if (idp->typep->form == STRING_FORM)
   sprintf(bp, "'%s'\n", idp->defn.info.constant.value.stringp);
 debug_print(buffer);

 /* and type. careful as an enum type will get into an infinite loop */
 if (idp->typep->form != ENUM_FORM) analyze_type(idp->typep, FALSE);

}                                                /* end analyze_const_defn */
/***************************************************************************/



/***************************************************************************/
/* analyze_type_defn(idp) Analyze a type definition                        */

analyze_type_defn(idp)
SYMTAB_NODE_PTR idp;              /* id */
{
 char *bp;

 if (DEBUG < Danalyze) return;

 /* the type's name, definition ... */
 sprintf(buffer, ">>id = %s\n", idp->name);
 debug_print(buffer);
 sprintf(buffer, ">>    address = %d\n", idp);
 debug_print(buffer);

 sprintf(buffer, ">>    defn = %s\n", defn_names[idp->defn.key]);
/*  print_line(buffer); */
 debug_print(buffer);

 /* and type */
 analyze_type(idp->typep, TRUE);

}                                                 /* end analyze_type_defn */
/***************************************************************************/



/***************************************************************************/
/* analyze_type(tp, verbose_flag) Analyze a type definition                */

analyze_type(tp, verbose_flag)
TYPE_STRUCT_PTR tp;              /* pointer to type structure */
BOOLEAN verbose_flag;            /* TRUE for verbose analysis */
{
 char *bp;

 if (DEBUG < Danalyze) return;

 if (tp == NULL) return;

 /* the form, byte size (and name) */
 sprintf(buffer, ">>    form = %s, size = %d bytes, type id = ",
                        form_names[tp->form], tp->size);
 bp = buffer + strlen(buffer);
 if (tp->type_idp != NULL)
   sprintf(bp, "%s\n", tp->type_idp->name);
 else {
   sprintf(bp, "<unnamed type>\n");
   verbose_flag = TRUE;
 }
 debug_print(buffer);

 /* do the appropriate analysus */
 switch (tp->form) {
   case ENUM_FORM: {
     analyze_enum_type(tp, verbose_flag);
     break;
   }
   case SUBRANGE_FORM: {
     analyze_subrange_type(tp, verbose_flag);
     break;
   }
   case ARRAY_FORM: {
     analyze_array_type(tp, verbose_flag);
     break;
   }
   case STRING_FORM: {
     verbose_flag = TRUE;
     analyze_string_type(tp, verbose_flag);
     break;
   }
   case BOUND_FORM: {
     analyze_bound_type(tp, verbose_flag);
     break;
   }
   case ENTITY_FORM: {
     analyze_entity_type(tp, verbose_flag);
     break;
   }
   case BAG_FORM:
   case LIST_FORM:
   case SET_FORM: {
     analyze_bls_type(tp, verbose_flag);
     break;
   }
   default: {
     break;
   }
 } /* end switch */

}                                                      /* end analyze_type */
/***************************************************************************/



/***************************************************************************/
/* analyze_enum_type(tp, verbose_flag) Analyze an enumeration type         */

analyze_enum_type(tp, verbose_flag)
TYPE_STRUCT_PTR tp;              /* pointer to type structure */
BOOLEAN verbose_flag;            /* TRUE for verbose analysis */
{
 SYMTAB_NODE_PTR idp;              /* id */

 if (DEBUG < Danalyze) return;

 if (!verbose_flag) return;

 /* loop to analyze each enum constant as a constant defn */
 debug_print(">>    -- Enum Constants --\n");
 for (idp = tp->info.enumeration.const_idp; idp != NULL; idp = idp->next) {
   analyze_const_defn(idp);
 }

}                                                 /* end analyze_enum_type */
/***************************************************************************/



/***************************************************************************/
/* analyze_subrange_type(tp, verbose_flag) Analyze a subrange type */

analyze_subrange_type(tp, verbose_flag)
TYPE_STRUCT_PTR tp;              /* pointer to type structure */
BOOLEAN verbose_flag;            /* TRUE for verbose analysis */
{
 SYMTAB_NODE_PTR idp;              /* id */

 if (DEBUG < Danalyze) return;

 if (!verbose_flag) return;

 sprintf(buffer, ">>    min value = %d, max value = %d\n",
                   tp->info.subrange.min, tp->info.subrange.max);
 debug_print(buffer);

 debug_print(">>    -- Range Type -- \n");
 analyze_type(tp->info.subrange.range_typep, FALSE);

}                                             /* end analyze_subrange_type */
/***************************************************************************/



/***************************************************************************/
/* analyze_bound_type(tp, verbose_flag) Analyze a bound               type */

analyze_bound_type(tp, verbose_flag)
TYPE_STRUCT_PTR tp;              /* pointer to type structure */
BOOLEAN verbose_flag;            /* TRUE for verbose analysis */
{
 SYMTAB_NODE_PTR idp;              /* id */

 if (DEBUG < Danalyze) return;

 if (!verbose_flag) return;

 sprintf(buffer, ">>    min value = %d, max value = %d\n",
                   tp->info.bound.min, tp->info.bound.max);
 debug_print(buffer);

 debug_print(">>    -- Bound Type -- \n");
 analyze_type(tp->info.bound.bound_typep, FALSE);

}                                                /* end analyze_bound_type */
/***************************************************************************/



/***************************************************************************/
/* analyze_array_type(tp, verbose_flag) Analyze an array type              */

analyze_array_type(tp, verbose_flag)
TYPE_STRUCT_PTR tp;              /* pointer to type structure */
BOOLEAN verbose_flag;            /* TRUE for verbose analysis */
{
 SYMTAB_NODE_PTR idp;              /* id */

 if (DEBUG < Danalyze) return;

 if (!verbose_flag) return;

 sprintf(buffer, ">>    element count = %d\n",
                   tp->info.array.elmt_count);
 debug_print(buffer);
 sprintf(buffer, ">>    index limits = %d to %d\n",
                   tp->info.array.min_index, tp->info.array.max_index);
 debug_print(buffer);

 debug_print(">>    -- INDEX TYPE -- \n");
 analyze_type(tp->info.array.index_typep, FALSE);

 debug_print(">>    -- ELEMENT TYPE -- \n");
 analyze_type(tp->info.array.elmt_typep, FALSE);

}                                                /* end analyze_array_type */
/***************************************************************************/



/***************************************************************************/
/* analyze_bls_type(tp, verbose_flag) Analyze a bag, etc type              */

analyze_bls_type(tp, verbose_flag)
TYPE_STRUCT_PTR tp;              /* pointer to type structure */
BOOLEAN verbose_flag;            /* TRUE for verbose analysis */
{
 SYMTAB_NODE_PTR idp;              /* id */

 if (DEBUG < Danalyze) return;

 if (!verbose_flag) return;

 sprintf(buffer, ">>    element count = %d\n",
                   tp->info.dynagg.elmt_count);
 debug_print(buffer);
 sprintf(buffer, ">>    index limits = %d to %d\n",
                   tp->info.dynagg.min_index, tp->info.dynagg.max_index);
 debug_print(buffer);

 debug_print(">>    -- INDEX TYPE -- \n");
 analyze_type(tp->info.dynagg.index_typep, FALSE);

 debug_print(">>    -- ELEMENT TYPE -- \n");
 analyze_type(tp->info.dynagg.elmt_typep, FALSE);

}                                                /* end analyze_bls_type */
/***************************************************************************/



/***************************************************************************/
/* analyze_string_type(tp, verbose_flag) Analyze a string type              */

analyze_string_type(tp, verbose_flag)
TYPE_STRUCT_PTR tp;              /* pointer to type structure */
BOOLEAN verbose_flag;            /* TRUE for verbose analysis */
{
 SYMTAB_NODE_PTR idp;              /* id */

 if (DEBUG < Danalyze) return;

 if (!verbose_flag) return;

 sprintf(buffer, ">>    maximum length = %d\n",
                   tp->info.string.max_length);
 debug_print(buffer);

 sprintf(buffer, ">>            length = %d\n",
                   tp->info.string.length);
 debug_print(buffer);
 return;

}                                                /* end analyze_string_type */
/***************************************************************************/



/***************************************************************************/
/* analyze_entity_type(tp, verbose_flag) Analyze an entity type            */

analyze_entity_type(tp, verbose_flag)
TYPE_STRUCT_PTR tp;              /* pointer to type structure */
BOOLEAN verbose_flag;            /* TRUE for verbose analysis */
{
 SYMTAB_NODE_PTR idp;              /* id */

 if (DEBUG < Danalyze) return;

 if (!verbose_flag) return;

 /* loop to analyze each attribute as a variable decl */
 debug_print(">>    -- Attributes -- \n");
 for (idp = tp->info.entity.attribute_symtab; idp != NULL; idp = idp->next) {
   analyze_var_decl(idp);
 }

}                                               /* end analyze_entity_type */
/***************************************************************************/



/***************************************************************************/
/* analyze_var_decl(idp) Analyze a variable declaration                    */

analyze_var_decl(idp)
SYMTAB_NODE_PTR idp;              /* id */
{

 if (DEBUG < Danalyze) return;

 /* the name, definition and offset */
 sprintf(buffer, ">>  id = %s\n", idp->name);
 debug_print(buffer);
 sprintf(buffer, ">>    address = %d\n", idp);
 debug_print(buffer);

 sprintf(buffer, ">>    defn = %s, offset = %d\n",
                    defn_names[idp->defn.key], idp->defn.info.data.offset);
/*  print_line(buffer); */
 debug_print(buffer);

 /* and type */
 analyze_type(idp->typep, FALSE);

}                                                  /* end analyze_var_decl */
/***************************************************************************/



/***************************************************************************/
/* analyze_block(code_segment)   a dummy procedure                         */

analyze_block(code_segment)
char *code_segment;
{
 return;
}                                                     /* end analyze_block */
/***************************************************************************/



/***************************************************************************/
/* analyze_routine_header(rtn_idp)  a dummy procedure                      */

analyze_routine_header(rtn_idp)
SYMTAB_NODE_PTR rtn_idp;

{
 return;
}                                           /* end analyze_routine_header */
/***************************************************************************/



/***************************************************************************/