/* @(#)find.c	1.5	2/10/93 */
/*******************************************************************************

This code was written and designed by 
Andrew Gene HALL of I.N. Services Pty. Ltd., Scarborough WA, Australia,
for the 
University of Western Australia, Crawley WA, Australia.

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

#include "find.h"
#include "diagmesg.h"
#include "sf_space.h"

/* forward declarations */
Data_Seq	*find_Data_Name_in_BS( char *, Block_Seq **);
Data_Seq	*find_Data_Name_in_DS( char *, Data_Seq *);
Data_Seq	*find_Data_Name_in_GS( char *, Global_Seq *);
extern char	*re_comp( char *);

/* find_Data_Name_in_BS()
 * Given an RE matching a name,
   search a sequence of blocks to find its occurence,
   with precedence given to a Data Block before a Global Block.
 * Return a the position in a Data_Seq where it first occurs.
 */
Data_Seq	*find_Data_Name_in_BS(
char		*name,
Block_Seq	**blocks)
{
   Data_Seq	*tmp_ds = NULL;
   Block_Seq	*b = *blocks;

   for(; b; b = b->next )
      switch( b->tag ) {
      case DATA_BLOCK:
           if( tmp_ds = find_Data_Name_in_DS( 
                                         name,
                                         b->block.data_block.actual_data )) {
              *blocks = b;
              return( tmp_ds );
           }
           else if( tmp_ds = find_Data_Name_in_GS(
                                         name,
                                         b->block.data_block.global_data )) {
              *blocks = b;
              return( tmp_ds );
           }
           break;

      case GLOBAL_BLOCK:
         /* ignore these */
         break;

      default:
         ERROR_MSG("find_Data_Name_in_BS(): unknown block in Block_Seq.");
      }
   return( NULL );
} /* find_Data_Name_in_BS */

/* find_Data_Name_in_DS()
 */
Data_Seq	*find_Data_Name_in_DS(
char		*name,
Data_Seq	*data)
{
  for( ; data; data = data->next )
     if( matches_RE( name, data->name ) )
        return( data );
  return( NULL );
} /* find_Data_Name_in_DS() */

/* find_Data_Name_in_GS()
 */
Data_Seq	*find_Data_Name_in_GS(
char		*name,
Global_Seq	*globals)
{
  Data_Seq	*tmp_ds = NULL;

  for( ; globals; globals = globals->next )
     switch( globals->global_entry->tag ) {
     case DATA_BLOCK:
          ERROR_MSG("find_Data_Name_in_GS(): Ignoring Data Block encountered in a Global_Seq.");
          break;

     case GLOBAL_BLOCK:
          if( tmp_ds = find_Data_Name_in_DS(
                                    name,
                                    globals->global_entry->block.global_block) )
              return( tmp_ds );
          break;

     default:
          ERROR_MSG("find_Data_Name_in_GS(): unknown block in Block_Seq.");

      }
  return( NULL );
} /* find_Data_Name_in_GS() */

/* matches_RE()
 * The same as matches_re() but without the lowercase folding.
 */
Boolean matches_RE(
char *  re,
char *  string)
{
   static char *        last_re = NULL;

   /* compile the regular expression if necessary */
   if( re != last_re ) {
      /* not the same reg'exp' as last time */
      char              *err_msg = NULL;

      if( err_msg = re_comp( re ) ) {
         ERROR_MSG("matches_RE: Error compiling regular expression.");
         ERROR_MSG( err_msg );
         last_re = NULL;
      }
      else
         last_re = re;
   }
   /* match the lowercase string against the regular expression */
   switch( re_exec( string ) ) {
   case 0:
      return( FALSE );
      break;

   case 1:
      return( TRUE );
      break;

   case -1:
      ERROR_MSG("matches_RE: The regular expression was invalid.");
      break;

   default:
      ERROR_MSG("matches_RE: Error in matching the regular expression.");
   }
   /* only get this far if there was a problem */
   return( FALSE );
} /* matches_RE */

