tfe-1.0/area/
tfe-1.0/files/
tfe-1.0/logs/
tfe-1.0/logs/immortal/
tfe-1.0/logs/mob/
tfe-1.0/logs/object/
tfe-1.0/logs/player/
tfe-1.0/logs/room/
tfe-1.0/notes/clans/
tfe-1.0/player/
tfe-1.0/prev/
tfe-1.0/prev/area/
tfe-1.0/prev/player/
tfe-1.0/prev/rooms/
tfe-1.0/rooms/
tfe-1.0/src-gc/
tfe-1.0/src-msvc/
tfe-1.0/src-unix/
tfe-1.0/www/
tfe-1.0/www/html/
#include "ctype.h"
#include "sys/types.h"
#include "stdio.h"
#include "stdlib.h"
#include "define.h"
#include "struct.h"
 

/*
 *   LOCAL FUNCTIONS
 */


void   clear_variables        ( void );
void   free_code              ( struct mem_block* );

void    remove_queue  ( queue_data* );  
void*   proc_arg      ( struct arg_type* );

bool end_prog;
bool cont_prog;
bool queue_prog;

queue_data*  queue_list  = NULL;
stack_data*  stack_list  = NULL;


/*
 *   VARIABLES/CONSTANTS
 */


char_data*   var_victim;
char_data*   var_rch;
char_data*   var_mob;  
char_data*   var_ch;
obj_data*    var_obj;
obj_data*    var_container;
room_data*   var_room;
char*        var_arg;
int          var_i;
int          var_j;


/*
 *   MEMORY ROUTINES
 */


char* code_alloc( const char* argument )
{
  mem_block*  block;
  int          size  = strlen( argument );

  if( size == 0 )
    return empty_string;

  block       = new mem_block( size+1 );
  block->next = block_list;
  block_list  = block;

  memcpy( block->pntr, argument, size+1 );

  return (char*) block->pntr;
}


/*
 *   BUG ROUTINE
 */


void code_bug( char *text )
{
  char tmp [ MAX_INPUT_LENGTH ];

  bug( text );

  sprintf( tmp, "-- Char = %s  Mob = %s  Victim = %s",
    var_ch  == NULL    ? "NULL" : var_ch->descr->name,
    var_mob == NULL    ? "NULL" : var_mob->descr->name,
    var_victim == NULL ? "NULL" : var_victim->descr->name );
  bug( tmp );
  
  sprintf( tmp, "-- Rch = %s, Room #%d, i = %d",
    var_rch == NULL  ? "NULL" : var_rch->descr->name,
    var_room == NULL ? -1 : var_room->vnum, var_i );  
  bug( tmp );
}


/*
 *   STACK ROUTINES
 */


void push( )
{
  stack_data* stack;

  stack = new stack_data;
  
  stack->room   = var_room;
  stack->ch     = var_ch;
  stack->victim = var_victim;
  stack->obj    = var_obj;
  stack->mob    = var_mob;
  stack->rch    = var_rch;
  stack->i      = var_i;

  stack->next = stack_list;
  stack_list  = stack;
}


void pop( )
{
  stack_data* stack;

  stack      = stack_list;
  stack_list = stack->next;

  var_room   = stack->room;
  var_ch     = stack->ch;
  var_victim = stack->victim;
  var_obj    = stack->obj;
  var_mob    = stack->mob;
  var_rch    = stack->rch;
  var_i      = stack->i;

  delete stack;
}


/*
 *   QUEUE ROUTINES
 */


void do_ps( char_data* ch, char* )
{
  queue_data* queue;

  if( queue_list == NULL ) {
    send( ch, "The queue is empty.\n\r" );
    return;
    }

  page_underlined( ch, "Vnum     Type        Location\n\r" );   

  for( queue = queue_list; queue != NULL; queue = queue->next )
     queue->program->display( ch );
}  


void update_queue( void )
{
  struct queue_data *queue, *queue_next;
//  struct mem_block *tmp_list = block_list;

  for( queue = queue_list; queue != NULL; queue = queue_next ) {
    queue_next = queue->next;

    if( queue->time-- > 1 )
      continue;

    var_room = queue->room;
    var_ch   = queue->ch;
    var_mob  = queue->mob;
    var_obj  = queue->obj;
    var_i    = queue->i;

    error_buf[0] = '\0';
    end_prog     = FALSE;
    cont_prog    = FALSE;
    queue_prog   = FALSE;

    proc_arg( queue->arg->next );

    if( queue_prog ) 
      queue_list->program = queue->program;
    else 
      queue->program->active--;
         
    remove( queue_list, queue );
    delete queue;
    }

  clear_variables( );
}


/*
 *   CLEAR QUEUE OF A VARIABLE
 */


void clear_queue( char_data* ch )
{
  queue_data* queue;
  stack_data* stack;

  for( queue = queue_list; queue != NULL; queue = queue->next ) {
    if( queue->mob == ch )  queue->mob = NULL;
    if(  queue->ch == ch )   queue->ch = NULL;
    }

  if(    var_mob == ch )      var_mob = NULL;
  if(     var_ch == ch )       var_ch = NULL;
  if( var_victim == ch )   var_victim = NULL;
  if(    var_rch == ch )      var_rch = NULL;

  for( stack = stack_list; stack != NULL; stack = stack->next ) {
    if(     stack->ch == ch )      stack->ch = NULL;
    if( stack->victim == ch )  stack->victim = NULL;
    if(    stack->rch == ch )     stack->rch = NULL;
    if(    stack->mob == ch )     stack->mob = NULL;
    } 
}


void clear_queue( obj_data* obj )
{
  queue_data* queue;
  stack_data* stack;

  for( queue = queue_list; queue != NULL; queue = queue->next ) 
    if( queue->obj == obj )
      queue->obj = NULL;

  if(       var_obj == obj )         var_obj = NULL;
  if( var_container == obj )   var_container = NULL;

  for( stack = stack_list; stack != NULL; stack = stack->next ) 
    if( stack->obj == obj )
      stack->obj = NULL;
}


void clear_queue( program_data* program )
{
  queue_data*  queue;
  queue_data*   next;

  for( queue = queue_list; queue != NULL; queue = next ) {
    next = queue->next; 
    if( queue->program == program )  
      remove( queue_list, queue );
    }

  program->active = 0;
}


/*
 *   RUN-TIME FUNCTIONS 
 */


bool execute( program_data* program )
{
  bool flag;

  if( program->binary == NULL ) {
    compile( program );
    if( program->binary == NULL ) {
      delete_list( program->memory );
      return FALSE;
      }
    }

  if( program->active > 50 ) {
    bug( "Execute: infinite recursive loop." );
    return FALSE;
    }

  end_prog   = FALSE;
  cont_prog  = FALSE;
  queue_prog = FALSE;

  program->active++;
  proc_arg( program->binary );

  if( queue_prog ) 
    queue_list->program = program;
  else 
    program->active--;

  flag = cont_prog;

  end_prog   = FALSE;
  cont_prog  = FALSE;
  queue_prog = FALSE;

  clear_variables( );

  return flag;
}


void* proc_arg( struct arg_type* arg )  
{
  afunc_type*    afunc;
  arg_type*   arg_next;
  void*           farg  [4];
  void**          pntr;
  void*         result;
  int                i;

  if( end_prog )
    return NULL;  

  if( arg == NULL )
    return NULL;

  arg_next = arg->next;

  if( arg_next != NULL ) {
    arg->next = NULL;
    proc_arg( arg );
    arg->next = arg_next;
    if( end_prog )
      return NULL;
    proc_arg( arg_next );
    return NULL;
    }

  if( arg->family == cont ) {
    cont_prog = TRUE;
    end_prog  = TRUE;
    return NULL;
    }

  if( arg->family == end ) {
    end_prog = TRUE;
    return NULL;
    }

  if( arg->family == constant ) 
    return arg->value;

  if( arg->family == variable ) {
    pntr = (void**) arg->value;
    return (void*) ( arg->neg ? *pntr == NULL : *pntr );   
    }

  if( arg->family == loop ) {
    loop_type*      aloop  = (loop_type*) arg;
    char_data*        rch;
    char_data*     leader  = var_ch;
   
    if( aloop->fruit == loop_unknown ) {
      for( i = 0; i < 100; i++ ) {
        if( ( proc_arg( aloop->condition ) == NULL ) != aloop->neg )
          break;
        proc_arg( aloop->aloop );
        }
      if( i == 100 )
        bug( "Proc_arg: Infinite script loop." );
      return NULL;
      }    

    if( var_room == NULL ) {
      code_bug( "Proc_arg: NULL room in loop_followers." );
      return NULL;
      }

    for( i = 0; i < var_room->contents; i++ ) {
      if( ( rch = character( var_room->contents[i] ) ) == NULL
        || ( aloop->fruit == loop_followers && rch->leader != leader ) )
        continue; 
      var_rch = rch;
      proc_arg( aloop->aloop );
      }       

    return NULL;
    }

  if( arg->family == if_clause ) {
    aif_type*   aif  = (aif_type*) arg; 
    void*      flag  = proc_arg( aif->condition );

    if( flag == NULL )
      proc_arg( aif->no );
    else
      proc_arg( aif->yes );

    return NULL;
    }

  afunc = (afunc_type*) arg;

  for( i = 0; i < 4; i++ )
    farg[i] = NULL; 

  if( afunc->func->func_call == code_set_equal ) {
    farg[0] = afunc->arg[0];         
    farg[1] = proc_arg( afunc->arg[1] );
    code_set_equal( farg );
    return NULL;
    }

  for( i = 0; i < 4; i++ ) {
    if( afunc->arg[i] == NULL )
      break; 
    farg[i] = proc_arg( afunc->arg[i] );         
    }

  curr_arg = arg;
  result   = ( afunc->func->func_call )( farg );

  if( !arg->neg )
    return result;

  return (void*) ( result == NULL );
}


/*
 *   MISC SUPPORT ROUTINES
 */


char* get_string( const char* name, extra_array& list )
{
  for( int i = 0; i < list; i++ )
    if( !strcasecmp( name, list[i]->keyword ) )
      return list[i]->text;

  return NULL;
}


void clear_variables( )
{
  var_victim    = NULL;
  var_rch       = NULL;
  var_mob       = NULL;
  var_ch        = NULL;
  var_obj       = NULL;
  var_container = NULL;
  var_room      = NULL;
}