/******************************************************************
 *  (C) Copyright 1994; dit/upm
 *  Distributed under the conditions stated in the
 *  TOPO General Public License (see file LICENSE)
 ******************************************************************
 *  $Log$
 ******************************************************************/

#ifndef lint
static char rcsid[]= "$Id$";
#endif

/******************************************************************
 *  
 *  Santiago Pavon Gomez
 *
 *  30 Oct 1992
 *
 *  Management of Synchronization Information for Step-by-step
 *  debugging purposes.
 * 
 *  COMPILATION FLAGS:
 *  
 *  LOG:
 *
 ******************************************************************/

/* LINTLIBRARY */


/* KJT 12/02/12: Added */
#include <stdlib.h>
#include "listdh.h"
#include "limisc.h"
#include "listrbk.h"
#include "badefca.h"
#include "baattr.h"
#include "babeh.h"
#include "baprint.h"


/******************************************************************
 *                                                                *
 *          STA -> Synchronization Tree (SyncTreeTyp)             *
 *                                                                *
 ******************************************************************/


/* Blanks
 * Return a string with n blanks
 */
static char * Blanks( n )
     int n;
{
  int     i;
  char *  blanks;
  
  blanks = (char*)emalloc(n+1);
  for ( i=0; i<n; i++ )
    blanks[i] = ' ';
  blanks[n] = '\0';
  
  return blanks;
}

/*----------------------------------------------------------------*/

/* PrintPIL
 * Print a string of process instantiation cells.
 * if proc>0 then print only instantiations to proc.
 * return TRUE if something has been written.
 * The first line is preceeded by indent;
 * the following, by a string of ' ' of the same length that indent.
 */
static boolean PrintPIL( pil, pstr, proc, indent )
     BehTyp        pil;
     void        (*pstr)(); 
     DescriptorTyp proc;
     char *        indent;
{
  boolean first = TRUE;
  char *  blanks = NULL;
  
  while( pil!=NULL ) {
    LASSERT(LookTypeB(pil)==ProcessInstC);
    if ( proc==0 || LookNameB(pil)==proc ){
      if ( first ) {
        PrintBeh( pil, 1, NO_PROC, FALSE, indent, pstr, FALSE, TRUE );
        first = FALSE;
      }
      else {
        if ( blanks==NULL )
          blanks = Blanks(strlen(indent));
        PrintBeh( pil, 1, NO_PROC, FALSE, blanks, pstr, FALSE, TRUE );
      }
    }
    pil = LookArgB(pil,1);
  }
  if (blanks!=NULL)
    (void)free(blanks);
  return !first;
}

/*----------------------------------------------------------------*/

static void VPrintPar();

/* VPrST
 * par1 says when VPrST is printing the ST of the first operand of a parallel
 * ( parenthesis are compulsory for it )
 */
static void VPrST( st, pstr, proc, indent, par1 )
     SyncTreeTyp   st;
     void        (*pstr)(); 
     DescriptorTyp proc;
     StrBckTyp     indent;
     boolean       par1;
{
  SyncTreeTyp st2;
  StrBckTyp   skip;
  char *      blanks;
  
  if ( st==NULL )
    return;
  
  switch( LookTypeB(st) )
    {
    case ParallelC:
      VPrintPar( st, pstr, proc, indent, par1 );
      break;
      
    case GateC:
    case IC:
    case ExitC:
      if ( ( st2 = (SyncTreeTyp)LookAInfo(LookA(st,STA)) )!= NULL ) {
        switch ( LookTypeB( st2 ) ) 
          {
          case ProcessInstC:
            skip = CopyStrBck( indent );
            if ( !PrintPIL( st2, pstr, proc, LookStrStrBck(indent) ) ) {
              skip = ConcatStrBck( skip, " " );
              PrintBeh( st, 1, NO_PROC, FALSE, LookStrStrBck(skip),
                       pstr, FALSE, TRUE );
              FreeStrBck( skip );
            }
            else {
              blanks = Blanks( strlen(LookStrStrBck(indent))+1 );
              PrintBeh( st, 1, NO_PROC, FALSE, blanks,
                       pstr, FALSE, TRUE );
              (void)free(blanks);
            }
            break;
            
          case ParallelC:
            VPrST( st2, pstr, proc, indent, par1 );
            break;
          }
      }
      else {
        PrintBeh( st, 1, NO_PROC, FALSE, LookStrStrBck(indent),
		 pstr,  FALSE, TRUE );
      }
      break;
      
    case ProcessInstC:
      (void)PrintPIL( st, pstr, proc, LookStrStrBck(indent) );
      break;
      
    default:
      Error("VPrST: Unexpected cell type.");
    }
}

/*----------------------------------------------------------------*/

/* VPrintPar
 *  par forces parenthesis.
 */
static void VPrintPar( st, pstr, proc, indent, par )
     SyncTreeTyp   st;
     void        (*pstr)(); 
     DescriptorTyp proc;
     StrBckTyp     indent;
     boolean       par;
{
  char       *blanks;
  boolean     printed;
  StrBckTyp   skip;
  
  printed = PrintPIL( (SyncTreeTyp)LookAInfo(LookA(st,STA)),
                     pstr, proc, LookStrStrBck(indent) );
  
  if ( printed || par ) {
    /* PIL printed or left parallel arg => () are needed */
    
    blanks = Blanks( strlen(LookStrStrBck(indent)) );
    
    /* 1st Arg */
    if ( !printed && par ) {
      skip   = CopyStrBck( indent );
    }
    else {
      skip   = CreateStrBck();
      skip   = ConcatStrBck( skip, blanks );
    }
    skip   = ConcatStrBck( skip,"(  ");
    VPrST( LookArgB( st, 1 ), pstr, proc, skip, TRUE );
    FreeStrBck(skip);
    
    /* Parallel */
    pstr( blanks );
    pstr(" ");
    PrintParOper( st, pstr );
    pstr( "\n" );
    
    /* 2nd Arg */
    skip   = CreateStrBck();
    skip   = ConcatStrBck( skip, blanks );
    skip   = ConcatStrBck( skip, "   " );
    VPrST( LookArgB( st, 2 ), pstr, proc, skip, FALSE );
    FreeStrBck(skip);
    pstr( blanks );
    pstr( ")\n" );
    (void)free(blanks);
  }
  else {
    /* 1st Arg */
    blanks = Blanks( strlen(LookStrStrBck(indent)) );
    skip   = CopyStrBck( indent );
    skip   = ConcatStrBck( skip, "  " );
    VPrST( LookArgB( st, 1 ), pstr, proc, skip, TRUE );
    FreeStrBck(skip);
    /* Parallel */
    pstr( blanks );
    PrintParOper( st, pstr );
    pstr( "\n" );
    /* 2nd Arg */
    skip   = CreateStrBck();
    skip   = ConcatStrBck( skip, blanks );
    skip   = ConcatStrBck( skip,"  ");
    VPrST( LookArgB( st, 2 ), pstr, proc, skip, FALSE );
    FreeStrBck(skip);
    /* pstr( "\n" ); */
    (void)free(blanks);
  }
}

/*----------------------------------------------------------------*/

/* VPrintST
 * Verbose printing of the synchronization Tree st.
 * pstr is the function used to print strings.
 * proc is the selected process ( only instantiations to this process will be
 * printed )
 */
void VPrintST( st, pstr, proc, indent )
     SyncTreeTyp   st;
     void        (*pstr)(); 
     DescriptorTyp proc;
     int           indent;
{
  StrBckTyp skip;
  char       *blanks;
  
  skip = CreateStrBck();
  blanks = Blanks( indent );
  skip   = ConcatStrBck( skip, blanks );
  (void)free(blanks);
  VPrST( st, pstr, proc, skip, FALSE );
  FreeStrBck( skip );
}

/*----------------------------------------------------------------*/

/* PrintST
 * Print the synchronization Tree st.
 * pstr is the function used to print strings.
 */
void PrintST( st, pstr )
     SyncTreeTyp   st;
     void        (*pstr)(); 
{
  pstr("\n{");
  VPrintST( st, pstr, 0, 0 );
  pstr("\n}");
}

/*----------------------------------------------------------------*/

/* FreeST
 * Free a Synchronization Tree
 */
void FreeST( st )
     SyncTreeTyp st;
{
  FreeB(UnshareB(st));
  
}

/*----------------------------------------------------------------*/

/* CopyST
 * Copy a synchronization Tree
 */
SyncTreeTyp CopyST( st )
     SyncTreeTyp st;
{
  return ShareB( CopyB( st ) );
}

/*----------------------------------------------------------------*/

/* IsEventLeafST
 * Say whether an event is a leaf of the ST or not.
 * ( if it is, its STA is a process insts list )
 */
boolean IsEventLeafST( event )
     BehTyp event;
{
  return LookA(event,STA)==NULL ||
    (LookTypeB( (BehTyp)LookAInfo(LookA(event,STA)))==ProcessInstC );
  /*
   * equivalent :
   *
   * LookA( event,SSLA )!=NULL
   *
   */
}



/******************************************************************
 *                                                                *
 *       SSLA -> Specification Source Line (int)                  *
 *                                                                *
 ******************************************************************/


/* FreeSSL
 * Free a SSL
 */
void FreeSSL( sl )
     int sl;
{
  sl = sl;
}

/*----------------------------------------------------------------*/

/* PrintSSL
 * Print the attribute specification source line
 * pstr is the function used to print strings.
 */
void PrintSSL( sl, pstr )
     int    sl;
     void (*pstr)();
{
  pstr(" (* line ");
  PrintInt(pstr,sl);
  pstr(" *)");
}

/*----------------------------------------------------------------*/

/* SPrintSSL
 * Make a string with the specification source line.
 */
char * SPrintSSL( sl )
     int   sl;
{
  char * str;
  
  str = (char*)emalloc(32);
  (void)sprintf( str," (* line %d *)", sl );
  return str;
}

/*----------------------------------------------------------------*/






