/******************************************************
 *      auxiliary functions
 ******************************************************/
/**********************************************
* (C) Copyright 1992; The LotoSphere Consortium
***********************************************
$Log: basic.c,v $
 * Revision 2.3  1993/06/16  13:52:51  lotos
 * code cleaning
 * new annotations
 * sort annonations (arbitrary)
 * detect invalid options
 *
 * Revision 2.2  1992/09/11  16:55:21  lotos
 * track new location of annotations
 *
 * Revision 2.1  1992/05/07  19:48:29  lotos
 * integreted into topo
 *
 * Revision 1.8  92/03/05  18:50:04  gabriel
 * Adapted to CR v9
 * 
 * Revision 1.7  92/03/05  18:24:21  gabriel
 * colours.h colours.c grc.h nodes.h included as sources
 * 
 * Revision 1.6  92/01/31  11:35:02  gabriel
 * Adapted to TOPO 2R1.
 * It generates the CR as writen originally by the user.
 * Fixed the data types representation: now, it contains the original
 * data types and the semi-flattened versions of them.
 * Also the library is now correctly generated, with their own semi-
 * flattened representation.
 * 
 * Revision 1.5  92/01/08  13:39:07  gabriel
 * Added annotations for the lite compiler (colos)
 * Removed unneeded strdup's
 * Added progname variable
 * 
 * Revision 1.4  91/11/19  20:24:32  gabriel
 * Corrected bugs related with memory management in aux.c.
 * 
 * Revision 1.3  91/09/24  09:49:32  gabriel
 * Adapted to TOPO 1R7
 * 
 * Revision 1.2  91/07/05  18:25:28  gabriel
 * Cosmetics
 * Adapted to new version of TOPO
 * 
 * Revision 1.1  91/07/05  18:13:07  gabriel
 * Initial revision
 * 
 ***********************************/

# include "version.h"
#ifndef lint
static char rcsid[]= "$Id: basic.c,v 2.3 1993/06/16 13:52:51 lotos Exp $";
#endif

# include "nodes.h"
# include "swbus.h"
# include "csgiok.h"

PUBLIC int
Getid (h, nar)
  TNODE* h;
  int    nar;
{
  TATTR* clr;

  if ((clr = find_attr (c_iddec, h)) != NULL)
    return (int)clr->value;
  if ((clr = find_attr (c_idref, h)) != NULL)
    return (int)clr->value;
  if ((clr = find_attr (c_lexv, h)) != NULL)
    return (int)clr->value;
  /* lexv is meaningful in sort_identifiers for sortnames */
  (void)fprintf (stderr, "%s: neither iddec nor idref, rule %d\n",
		 progname, nar);
  drn_tree (h, 3);
  exit (1);
  return 0; /* to shut lint of */
}

PUBLIC char*
Getlexv (iddec)
  int iddec;
{
  return SymbolTable->data[(int)(ATable->data[iddec].value1)];
}

PUBLIC char*
int2str (i)
      int i;
{
  char* s;

  s = emalloc (7*sizeof(char));
  (void) sprintf (s, "%d", i);
  return s;
}

PUBLIC void
print_spe (TheSpecification)
  cr_specification TheSpecification;
{
  char* s;

  if (!debugging) {
    if (printable)
      print_cr_specification (TheSpecification);
    else {
      if ((s = CSGIOwrite_cr_specification (stdout, TheSpecification)) != NULL)
        (void)fprintf (stderr, "%s: Write error: %s\n", progname, s);
    }
  }
}

PUBLIC int
getid (h)
   TNODE* h;
{
  if (find_attr (c_iddec, h) != NULL)
    return (int)find_attr (c_iddec, h)->value;
  if (find_attr (c_idref, h) != NULL)
    return (int)find_attr (c_idref, h)->value;
  (void)fprintf (stderr, "%s: No identifier\n", progname);
  drn_tree (h, 2);
  exit (1);
  return 0; /* to shut lint of */
}

PUBLIC cr_value_identifier
make_cr_value_id (id)
   int id;
{
  if (ATfind (ATable, id, c_ui) != NULL)
    return CR_Value_id
      (CR_Identifier (mknocasestring (Getlexv(id)),
         	      CR_DefExtension (mknocasestring
                          (int2str((int)ATfind(ATable, id, c_ui)->value)))));
  (void)fprintf (stderr, "%s: unique identifier by class does not exit\n",
		 progname);
  exit (1);
  return 0; /* to shut lint off */
}

PUBLIC cr_specification_identifier
make_cr_specification_id (id)
   int id;
{
  if (ATfind (ATable, id, c_ui) != NULL)
    return CR_Specification_id
      (CR_Identifier (mknocasestring (Getlexv(id)),
         	      CR_DefExtension (mknocasestring
                          (int2str((int)ATfind(ATable, id, c_ui)->value)))));
  (void)fprintf (stderr, "%s: unique identifier by class does not exit\n",
		 progname);
  exit (1);
  return 0; /* to shut lint off */
}

PUBLIC cr_gate_identifier
make_cr_gate_id (id)
    int id;
{
  if (ATfind (ATable, id, c_ui) != NULL)
    return CR_Gate_id
     (CR_Identifier (mknocasestring (Getlexv(id)),
                     CR_DefExtension (mknocasestring
                          (int2str((int)ATfind(ATable, id, c_ui)->value)))));
  (void)fprintf (stderr, "%s: unique identifier by class does not exit\n",
		 progname);
  exit (1);
  return 0; /* to shut lint off */
}

PUBLIC cr_sort_identifier
make_cr_sort_id (id)
    int id;
{
  if (ATfind (ATable, id, c_ui) != NULL)
    return CR_Sort_id (
      CR_Identifier(mknocasestring (Getlexv(id)),
         	      CR_DefExtension (mknocasestring
                          (int2str((int)ATfind(ATable, id, c_ui)->value)))));
  (void)fprintf (stderr, "%s: unique identifier by class does not exit\n",
		 progname);
  exit (1);
  return 0; /* to shut lint off */
}

PUBLIC cr_process_identifier
make_cr_process_id (id)
  int id;
{
  if (ATfind (ATable, id, c_ui) != NULL)
    return CR_Process_id
      (CR_Identifier (mknocasestring (Getlexv(id)),
         	      CR_DefExtension (mknocasestring
                        (int2str((int)ATfind(ATable, id, c_ui)->value+1)))));
            /* The unique identifier is incremented by one */
            /* in order to be able to treat the specification as */
            /* one more process. */
  (void)fprintf (stderr, "%s: unique identifier by class does not exit\n",
		 progname);
  exit (1);
  return 0; /* to shut lint off */
}

PUBLIC cr_type_identifier
make_cr_type_id (id)
   int id;
{
  if (ATfind (ATable, id, c_ui) != NULL)
    return CR_Type_id
      (CR_Identifier (mknocasestring (Getlexv(id)),
         	      CR_DefExtension (mknocasestring
                          (int2str((int)ATfind(ATable, id, c_ui)->value)))));
  (void)fprintf (stderr, "%s: unique identifier by class does not exit\n",
		 progname);
  exit (1);
  return 0; /* to shut lint off */
}

PUBLIC cr_operation_identifier
make_cr_operation_id (id)
    int id;
{
  if (ATfind (ATable, id, c_ui) != NULL)
    return CR_Operation_id (
      CR_Identifier (mknocasestring (Getlexv(id)),
         	      CR_DefExtension (mknocasestring
                          (int2str((int)ATfind(ATable, id, c_ui)->value)))));
  (void)fprintf (stderr, "%s: unique identifier by class does not exit\n",
		 progname);
  exit (1);
  return 0; /* to shut lint off */
}

PUBLIC cr_value_expression_list
get_val_expression_list (h)
  TNODE* h;
{
  TNODE* son = gt_fs(h);
  cr_value_expression_list vel = Nilcr_value_expression_list ();

  while (son != NULL) {
    vel = Conscr_value_expression_list (
             (cr_value_expression)fdclr (c_ccr_value_expression, son, -1),
             vel);
    son = gt_rb (son);
  }
  return reverse_cr_value_expression_list (vel);
}
 
PUBLIC cr_LABEL
make_cr_label (s, nar)
  char* s;
  int   nar;
{
  char *aux;

  aux = emalloc (sizeof(char)*(30 + strlen (s)));
  (void) sprintf (aux, "%s_%d", s, mk_unique++);
  return CR_Label (mkcasestring(aux));
}

/* It supposes that each _excomm node ONLY contains        */
/* ONE annotation (that is, only one c_c, c_default, etc). */

PUBLIC casestring
make_annotations (h)
  TNODE* h;
{
  TATTR* clr;
  char *s;

  if ((clr = find_attr (c_c, h)) != NULL) {
    s = emalloc (sizeof(char)*(15 + strlen ((char*)(clr->value))));
    (void)sprintf (s, "| C %s |", (char*)(clr->value));
    return mkcasestring(s);
  }
  if ((clr = find_attr (c_call, h)) != NULL) {
    s = emalloc (sizeof(char)*(15 + strlen ((char*)(clr->value))));
    (void)sprintf (s, "| call %s |", (char*)(clr->value));
    return mkcasestring(s);
  }
  if ((clr = find_attr (c_constructor, h)) != NULL) {
    s = emalloc (sizeof(char)*(20 + strlen ((char*)(clr->value))));
    (void)sprintf (s, "| constructor %s |", (char*)(clr->value));
    return mkcasestring(s);
  }
  if ((clr = find_attr (c_copy, h)) != NULL) {
    s = emalloc (sizeof(char)*(15 + strlen ((char*)(clr->value))));
    (void)sprintf (s, "| copy %s |", (char*)(clr->value));
    return mkcasestring(s);
  }
  if ((clr = find_attr (c_default, h)) != NULL) {
    s = emalloc (sizeof(char)*(15 + strlen ((char*)(clr->value))));
    (void)sprintf (s, "| default %s |", (char*)(clr->value));
    return mkcasestring(s);
  }
  if ((clr = find_attr (c_delay, h)) != NULL) {
    s = emalloc (sizeof(char)*(15 + strlen ((char*)(clr->value))));
    (void)sprintf (s, "| delay %s |", (char*)(clr->value));
    return mkcasestring(s);
  }
  if ((clr = find_attr (c_draw, h)) != NULL) {
    s = emalloc (sizeof(char)*(15 + strlen ((char*)(clr->value))));
    (void)sprintf (s, "| draw %s |", (char*)(clr->value));
    return mkcasestring(s);
  }
  if ((clr = find_attr (c_equal, h)) != NULL) {
    s = emalloc (sizeof(char)*(15 + strlen ((char*)(clr->value))));
    (void)sprintf (s, "| equal %s |", (char*)(clr->value));
    return mkcasestring(s);
  }
  if ((clr = find_attr (c_eval, h)) != NULL) {
    s = emalloc (sizeof(char)*(15 + strlen ((char*)(clr->value))));
    (void)sprintf (s, "| eval %s |", (char*)(clr->value));
    return mkcasestring(s);
  }
  if (find_attr (c_extern, h) != NULL) {
    s = emalloc (sizeof(char)*15);
    (void)strcpy (s, "| extern |");
    return mkcasestring(s);
  }
  if ((clr = find_attr (c_free, h)) != NULL) {
    s = emalloc (sizeof(char)*(15 + strlen ((char*)(clr->value))));
    (void)sprintf (s, "| free %s |", (char*)(clr->value));
    return mkcasestring(s);
  }
  if ((clr = find_attr (c_if, h)) != NULL) {
    s = emalloc (sizeof(char)*(10 + strlen ((char*)(clr->value))));
    (void)sprintf (s, "| if %s |", (char*)(clr->value));
    return mkcasestring(s);
  }
  if ((clr = find_attr (c_internal, h)) != NULL) {
    s = emalloc (sizeof(char)*(15 + strlen ((char*)(clr->value))));
    (void)sprintf (s, "| internal %s |", (char*)(clr->value));
    return mkcasestring(s);
  }
  if ((clr = find_attr (c_lbc, h)) != NULL) {
    s = emalloc (sizeof(char)*(15 + strlen ((char*)(clr->value))));
    (void)sprintf (s, "| lbc %s |", (char*)(clr->value));
    return mkcasestring(s);
  }
  if ((clr = find_attr (c_ldc, h)) != NULL) {
    s = emalloc (sizeof(char)*(15 + strlen ((char*)(clr->value))));
    (void)sprintf (s, "| ldc %s |", (char*)(clr->value));
    return mkcasestring(s);
  }
  if ((clr = find_attr (c_ldcinit, h)) != NULL) {
    s = emalloc (sizeof(char)*(15 + strlen ((char*)(clr->value))));
    (void)sprintf (s, "| ldcinit %s |", (char*)(clr->value));
    return mkcasestring(s);
  }
  if ((clr = find_attr (c_lexical, h)) != NULL) {
    s = emalloc (sizeof(char)*(15 + strlen ((char*)(clr->value))));
    (void)sprintf (s, "| lexical %s |", (char*)(clr->value));
    return mkcasestring(s);
  }
  if ((clr = find_attr (c_lexicalifpossible, h)) != NULL) {
    s = emalloc (sizeof(char)*(25 + strlen ((char*)(clr->value))));
    (void)sprintf (s, "| lexicalifpossible %s |", (char*)(clr->value));
    return mkcasestring(s);
  }
  if ((clr = find_attr (c_name, h)) != NULL) {
    if (h->type != tspecification) {
      /* this is due to the _specification node use the name */
      /* annotation to put the filename which contains the   */
      /* specification itself.                               */
      s = emalloc (sizeof(char)*(15 + strlen ((char*)(clr->value))));
      (void)sprintf (s, "| name %s |", (char*)(clr->value));
      return mkcasestring(s);
    }
  }
  if ((clr = find_attr (c_nonconstructor, h)) != NULL) {
    s = emalloc (sizeof(char)*(25 + strlen ((char*)(clr->value))));
    (void)sprintf (s, "| nonconstructor %s |", (char*)(clr->value));
    return mkcasestring(s);
  }
  if ((clr = find_attr (c_parse, h)) != NULL) {
    s = emalloc (sizeof(char)*(15 + strlen ((char*)(clr->value))));
    (void)sprintf (s, "| parse %s |", (char*)(clr->value));
    return mkcasestring(s);
  }
  if ((clr = find_attr (c_partial, h)) != NULL) {
    s = emalloc (sizeof(char)*(15 + strlen ((char*)(clr->value))));
    (void)sprintf (s, "| partial %s |", (char*)(clr->value));
    return mkcasestring(s);
  }
  if ((clr = find_attr (c_priority, h)) != NULL) {
    s = emalloc (sizeof(char)*(15 + strlen ((char*)(clr->value))));
    (void)sprintf (s, "| priority %s |", (char*)(clr->value));
    return mkcasestring(s);
  }
  if ((clr = find_attr (c_type, h)) != NULL) {
    s = emalloc (sizeof(char)*(15 + strlen ((char*)(clr->value))));
    (void)sprintf (s, "| type %s |", (char*)(clr->value));
    return mkcasestring(s);
  }
  if ((clr = find_attr (c_use, h)) != NULL) {
    s = emalloc (sizeof(char)*(10 + strlen ((char*)(clr->value))));
    (void)sprintf (s, "| use %s |", (char*)(clr->value));
    return mkcasestring(s);
  }
  if ((clr = find_attr (c_using, h)) != NULL) {
    s = emalloc (sizeof(char)*(15 + strlen ((char*)(clr->value))));
    (void)sprintf (s, "| using %s |", (char*)(clr->value));
    return mkcasestring(s);
  }
  if ((clr = find_attr (c_wait, h)) != NULL) {
    s = emalloc (sizeof(char)*(15 + strlen ((char*)(clr->value))));
    (void)sprintf (s, "| wait %s |", (char*)(clr->value));
    return mkcasestring(s);
  }

  if ((clr = find_attr (c_implby, h)) != NULL) {
    s = emalloc (sizeof(char)*(25 + strlen ((char*)(clr->value))));
    (void)sprintf (s, "| implementedby %s |", (char*)(clr->value));
    return mkcasestring(s);
  }
  if ((clr = find_attr (c_initSby, h)) != NULL) {
    s = emalloc (sizeof(char)*(25 + strlen ((char*)(clr->value))));
    (void)sprintf (s, "| initialisedby %s |", (char*)(clr->value));
    return mkcasestring(s);
  }
  if ((clr = find_attr (c_initZby, h)) != NULL) {
    s = emalloc (sizeof(char)*(25 + strlen ((char*)(clr->value))));
    (void)sprintf (s, "| initializedby %s |", (char*)(clr->value));
    return mkcasestring(s);
  }
  (void)fprintf (stderr, "%s: no annotation in _excomm node\n");
  exit (1);
  return 0; /* to shut lint off */
}

/* it returns f(L1, f(L2, f(L3, ..., f(Ln, init)...))) */
/* it also ensures that the colour attr is evaluated   */
/* L1,..,Ln is a list of TNODE* brothers               */
/* L is the first brother of them                      */
/* init is the initial value                           */
/* f() is a funtion                                    */

PUBLIC CLR_TYPE
reduce (f, L, attr, init, nrs)
   CLR_TYPE (*f)();
   TNODE*   L;
   int      attr;
   CLR_TYPE init;
   int      nrs; /* just for error reporting */
{
  if (L == NULL) return init;
  if (L->brothers == NULL)
    return f (fdclr (attr, L, nrs), init);
  return f (fdclr (attr, L, nrs), reduce (f, L->brothers, attr, init, nrs));
}

/*
PRIVATE TNODE*
last_brother (L)
  TNODE* L;
{
  for (; L->brothers != NULL; L = L->brothers)
    ;
  return L;
}

PRIVATE TNODE*
rigth_brother (init, actual)
  TNODE *init, *actual;
{
  for (; init->brothers != actual; init = init->brothers)
    ;
  return init;
}

PUBLIC CLR_TYPE
reduce (f, L, attr, init, nrs)
   CLR_TYPE (*f)();
   TNODE*   L;
   int      attr;
   CLR_TYPE init;
   int      nrs; / just for error reporting /
{
  CLR_TYPE result = init;
  TNODE*   aux;

  if (L == NULL) return init;
  if (L->brothers == NULL)
    return f (fdclr (attr, L, nrs), init);
  for (aux = last_brother (L); aux != L; aux = rigth_brother (L, aux))
    result = f (fdclr (attr, aux, nrs), result);
  return f(fdclr (attr, L, nrs), result);
}
*/

/* sen_reduce: Is the same as reduce, but node-sensible.               */
/* That means only nodes of type 'ntype' will be consider.             */
/* other nodes will be ignored                                         */
/* this is usefull in node-lists with heterogeneous components         */
/* for example, a _data_type_definitions is a list of _type_definition */
/* and _library_declaration. sen_reduce will be apply on               */
/* _type_definitions components or _library_declaration ones. So:      */

/* it returns f(L1, f(L2, f(L3, ..., f(Ln, init)...))) */
/* apply on nodes of type 'ntype'                      */
/* it also ensures that the colour attr is evaluated   */
/* L1,..,Ln is a list of TNODE* brothers               */
/* L is the first brother of them                      */
/* init is the initial value                           */
/* f() is a funtion                                    */

PUBLIC CLR_TYPE
sen_reduce (f, L, attr, init, ntype, nrs)
   CLR_TYPE (*f)();
   TNODE*   L;
   int      attr;
   CLR_TYPE init;
   int      ntype;
   int      nrs; /* just for error reporting */
{
  if (L == NULL) return init;
  if (L->brothers == NULL)
    return (L->type == ntype) ? f (fdclr (attr, L, nrs), init) : init;
  return 
    (L->type == ntype)
      ? f (fdclr (attr, L, nrs),
	   sen_reduce (f, L->brothers, attr, init, ntype, nrs))
	: sen_reduce (f, L->brothers, attr, init, ntype, nrs);
}

/* it returns f(...f(f(f(init, L1), L2), L3), ..., Ln) */
/* it also ensures that the colour attr is evaluated   */
/* L1,..,Ln is a list of TNODE* brothers               */
/* L is the first brother of them                      */
/* init is the initial value                           */
/* f() is a funtion                                    */

PUBLIC CLR_TYPE
red_inv (f, L, attr, init, nrs)
   CLR_TYPE (*f)();
   TNODE*   L;
   int      attr;
   CLR_TYPE init;
   int      nrs; /* just for error reporting */
{
  CLR_TYPE result = init;

  if (L == NULL) return init;
  for ( ; L->brothers != NULL; L = L->brothers)
    result = f (fdclr (attr, L, nrs), result);
  return f(fdclr (attr, L, nrs), result);
}

PUBLIC cr_data_type_definition_list
mkconscr_data_type_definition_list (clr, res)
  CLR_TYPE clr;
  CLR_TYPE res;
{
  if (clr != NULL)
    return Conscr_data_type_definition_list (
	      (cr_data_type_definition)clr,
	      (cr_data_type_definition_list)res);
  return (cr_data_type_definition_list)res;
}

PUBLIC cr_process_definition_list
mkconscr_process_definition_list (clr, res)
  CLR_TYPE clr;
  CLR_TYPE res;
{
  if (clr != NULL)
    return Conscr_process_definition_list (
	      (cr_process_definition)clr,
	      (cr_process_definition_list)res);
  return (cr_process_definition_list)res;
}

PUBLIC cr_value_identifier_list
mkconscr_value_identifier_list (clr, res)
  CLR_TYPE clr;
  CLR_TYPE res;
{
  return Conscr_value_identifier_list (
	    CR_annotated_val_id (
		 (cr_value_identifier)clr,
		 Nilcr_annotation_list()),
            (cr_value_identifier_list)res);
}

