Blame rules.c

Packit d394d9
/* Copyright (C) 1995 Bjoern Beutel. */
Packit d394d9
Packit d394d9
/* Description. =============================================================*/
Packit d394d9
Packit d394d9
/* This module contains the Malaga rule interpreter. */
Packit d394d9
Packit d394d9
/* Includes. ================================================================*/
Packit d394d9
Packit d394d9
#include <stdio.h>
Packit d394d9
#include <string.h>
Packit d394d9
#include <stdlib.h>
Packit d394d9
#include <time.h>
Packit d394d9
#include <math.h>
Packit d394d9
#include <setjmp.h>
Packit d394d9
#include <glib.h>
Packit d394d9
#include "basic.h"
Packit d394d9
#include "pools.h"
Packit d394d9
#include "values.h"
Packit d394d9
#include "symbols.h"
Packit d394d9
#include "patterns.h"
Packit d394d9
#include "files.h"
Packit d394d9
#include "malaga_files.h"
Packit d394d9
#include "rule_type.h"
Packit d394d9
#include "hangul.h"
Packit d394d9
#include "rules.h"
Packit d394d9
Packit d394d9
/* Types. ===================================================================*/
Packit d394d9
Packit d394d9
typedef struct /* Used to hold the value for a "switch". */
Packit d394d9
{
Packit d394d9
  list_node_t *next;
Packit d394d9
  symbol_t key; 
Packit d394d9
  value_t value; 
Packit d394d9
} switch_node_t;
Packit d394d9
Packit d394d9
typedef struct 
Packit d394d9
{ 
Packit d394d9
  list_node_t *next;
Packit d394d9
  int_t pc;
Packit d394d9
  int_t nested_subrules;
Packit d394d9
  int_t base; 
Packit d394d9
  int_t bottom;
Packit d394d9
} path_node_t;
Packit d394d9
Packit d394d9
/* Global variables. ========================================================*/
Packit d394d9
Packit d394d9
void (*add_end_state)( value_t feat );
Packit d394d9
void (*add_running_state)( value_t feat, int_t rule_set );
Packit d394d9
void (*add_allo)( string_t surf, value_t feat );
Packit d394d9
void (*debug_rule)( bool_t interrupt );
Packit d394d9
void (*transmit)( void );
Packit d394d9
Packit d394d9
rule_sys_t *executed_rule_sys;
Packit d394d9
int_t executed_rule_number = -1;
Packit d394d9
int_t pc = -1; /* Current instruction index. */
Packit d394d9
int_t base; /* Current frame base. */
Packit d394d9
int_t nested_subrules; /* Current nesting level. */
Packit d394d9
int_t path_count; /* Current number of alternative paths. */
Packit d394d9
Packit d394d9
rule_sys_t *debug_rule_sys;
Packit d394d9
bool_t rule_successful;
Packit d394d9
Packit d394d9
/* Variables. ===============================================================*/
Packit d394d9
Packit d394d9
static int_t bottom; /* Index of first stack element used in this branch. */
Packit d394d9
Packit d394d9
static list_t path_list; /* List of nodes for alternative paths. */
Packit d394d9
Packit d394d9
static list_t switch_list; /* The list of switches. */
Packit d394d9
Packit d394d9
static switch_node_t *current_switch; 
Packit d394d9
/* Needed for "get_first_switch" and "get_next_switch". */
Packit d394d9
Packit d394d9
/* Functions. ===============================================================*/
Packit d394d9
Packit d394d9
void 
Packit d394d9
set_switch( symbol_t key, value_t value )
Packit d394d9
/* Set the switch KEY to VALUE. */
Packit d394d9
{ 
Packit d394d9
  switch_node_t *node;
Packit d394d9
  switch_node_t *pre; /* predecessor node */
Packit d394d9
  string_t name = get_symbol_name( key );
Packit d394d9
Packit d394d9
  pre = NULL;
Packit d394d9
  FOREACH( node, switch_list )
Packit d394d9
  {
Packit d394d9
    if (strcmp_no_case( name, get_symbol_name( node->key ) ) <= 0) 
Packit d394d9
      break;
Packit d394d9
    pre = node;
Packit d394d9
  }
Packit d394d9
  if (node != NULL && key == node->key) 
Packit d394d9
    free_mem( &node->value );
Packit d394d9
  else 
Packit d394d9
  { 
Packit d394d9
    node = new_mem( sizeof( switch_node_t ) );
Packit d394d9
    node->key = key;
Packit d394d9
    insert_node( &switch_list, (list_node_t *) node, (list_node_t *) pre );
Packit d394d9
  }
Packit d394d9
  node->value = new_value( value );
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
value_t 
Packit d394d9
get_switch( symbol_t key )
Packit d394d9
/* Return the value of the switch KEY. 
Packit d394d9
 * Report an error if this switch doesn't exist. */
Packit d394d9
{ 
Packit d394d9
  switch_node_t *switch_node;
Packit d394d9
Packit d394d9
  FOREACH( switch_node, switch_list ) 
Packit d394d9
  { 
Packit d394d9
    if (switch_node->key == key) 
Packit d394d9
      return switch_node->value;
Packit d394d9
  }
Packit d394d9
  complain( "Switch \"%s\" is not defined.", get_symbol_name( key ) );
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
void
Packit d394d9
get_first_switch( value_t *value, symbol_t *key )
Packit d394d9
/* Return the first switch in *VALUE and its key in *KEY.
Packit d394d9
 * If there is no switch, *VALUE is NULL. */
Packit d394d9
{ 
Packit d394d9
  current_switch = (switch_node_t *) switch_list.first;
Packit d394d9
  get_next_switch( value, key );
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
void
Packit d394d9
get_next_switch( value_t *value, symbol_t *key )
Packit d394d9
/* Return the value of the next switch in *VALUE and its key in *KEY.
Packit d394d9
 * If there is no more switch, *VALUE is NULL. */
Packit d394d9
{ 
Packit d394d9
  if (current_switch == NULL) 
Packit d394d9
    *value = NULL;
Packit d394d9
  else 
Packit d394d9
  { 
Packit d394d9
    *key = current_switch->key;
Packit d394d9
    *value = current_switch->value;
Packit d394d9
    current_switch = (switch_node_t *) current_switch->next;
Packit d394d9
  }
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
void 
Packit d394d9
free_switches( void )
Packit d394d9
/* Free all switches. */
Packit d394d9
{ 
Packit d394d9
  switch_node_t *my_switch;
Packit d394d9
Packit d394d9
  FOREACH_FREE( my_switch, switch_list ) 
Packit d394d9
    free_mem( &my_switch->value );
Packit d394d9
}
Packit d394d9
Packit d394d9
/* Rule execution. ==========================================================*/
Packit d394d9
Packit d394d9
static void 
Packit d394d9
standard_function( int_t function )
Packit d394d9
/* Stack effect: VALUE -> NEW_VALUE.
Packit d394d9
 * Perform function FUNCTION on VALUE yielding NEW_VALUE. */
Packit d394d9
{ 
Packit d394d9
  char_t *buffer;
Packit d394d9
  string_t string;
Packit d394d9
  int_t start, end, len;
Packit d394d9
  gunichar code;
Packit d394d9
Packit d394d9
  switch (function) 
Packit d394d9
  {
Packit d394d9
  case FUNC_TO_ATOMS:
Packit d394d9
    push_value( get_atoms( value_to_symbol( value_stack[ --top ] ) ) );
Packit d394d9
    break;
Packit d394d9
  case FUNC_TO_MULTI:
Packit d394d9
    push_symbol_value( find_multi_symbol( value_stack[ --top ] ) );
Packit d394d9
    break;
Packit d394d9
  case FUNC_TO_SET:
Packit d394d9
    convert_list_to_set();
Packit d394d9
    break;
Packit d394d9
  case FUNC_IS_CAPITAL:
Packit d394d9
    code = g_utf8_get_char( value_to_string( value_stack[ --top ] ) );
Packit d394d9
    if (g_unichar_tolower( code ) != code) 
Packit d394d9
      push_symbol_value( YES_SYMBOL );
Packit d394d9
    else 
Packit d394d9
      push_symbol_value( NO_SYMBOL );
Packit d394d9
    break;
Packit d394d9
  case FUNC_GET_SWITCH:
Packit d394d9
    push_value( get_switch( value_to_symbol( value_stack[ --top ] ) ) );
Packit d394d9
    break;
Packit d394d9
  case FUNC_GET_LENGTH:
Packit d394d9
    if (get_value_type( value_stack[ top - 1 ] ) == STRING_SYMBOL)
Packit d394d9
    {
Packit d394d9
      push_number_value( 
Packit d394d9
	g_utf8_strlen( value_to_string( value_stack[ --top ] ), -1 ) );
Packit d394d9
    }
Packit d394d9
    else 
Packit d394d9
      push_number_value( get_list_length( value_stack[ --top ] ) );
Packit d394d9
    break;
Packit d394d9
  case FUNC_GET_VALUE_TYPE:
Packit d394d9
    push_symbol_value( get_value_type( value_stack[ --top ] ) );
Packit d394d9
    break;
Packit d394d9
  case FUNC_GET_VALUE_STRING:
Packit d394d9
    buffer = value_to_readable( value_stack[ --top ], TRUE, -1 );
Packit d394d9
    encode_hangul( &buffer );
Packit d394d9
    push_string_value( buffer, NULL );
Packit d394d9
    free_mem( &buffer );
Packit d394d9
    break;
Packit d394d9
  case FUNC_TRANSMIT:
Packit d394d9
    if (transmit == NULL) 
Packit d394d9
      complain( "No transmit function available." );
Packit d394d9
    transmit();
Packit d394d9
    break;
Packit d394d9
  case FUNC_FLOOR:
Packit d394d9
    push_number_value( floor( value_to_double( value_stack[ --top ] ) ) );
Packit d394d9
    break;
Packit d394d9
  case FUNC_SUBSTRING:
Packit d394d9
    string = value_to_string( value_stack[ top - 3 ] );
Packit d394d9
    start = value_to_int( value_stack[ top - 2 ] );
Packit d394d9
    if (value_stack[ top - 1 ] == NULL) 
Packit d394d9
      end = start;
Packit d394d9
    else 
Packit d394d9
      end = value_to_int( value_stack[ top - 1 ] );
Packit d394d9
    len = g_utf8_strlen( string, -1 );
Packit d394d9
    if (start < 0) 
Packit d394d9
      start += len + 1;
Packit d394d9
    if (end < 0) 
Packit d394d9
      end += len + 1;
Packit d394d9
    if (end < start) 
Packit d394d9
      push_string_value( "", NULL );
Packit d394d9
    else if (start <= 0 || end > len)
Packit d394d9
      complain( "Substring indexes out of bounds." );
Packit d394d9
    else 
Packit d394d9
      push_string_value( g_utf8_offset_to_pointer( string, start - 1 ), 
Packit d394d9
			 g_utf8_offset_to_pointer( string, end ) );
Packit d394d9
    value_stack[ top - 4 ] = value_stack[ top - 1 ];
Packit d394d9
    top -= 3;
Packit d394d9
    break;
Packit d394d9
  default:
Packit d394d9
    complain( "Internal error." );
Packit d394d9
  }
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
void 
Packit d394d9
execute_rule( rule_sys_t *rule_sys, int_t rule_number )
Packit d394d9
/* Execute rule RULE_NUMBER in the rule system RULE_SYS.
Packit d394d9
 * Any parameters must be on the value stack. */
Packit d394d9
{ 
Packit d394d9
  static symbol_t nil = NIL_SYMBOL; /* The "nil" symbol. */
Packit d394d9
  bool_t terminate; /* Shall we terminate the current rule internal path? */
Packit d394d9
  int_t i, info, new_pc, old_top, old_base, line;
Packit d394d9
  instr_t instruction;
Packit d394d9
  symbol_t symbol;
Packit d394d9
  path_node_t *path;
Packit d394d9
  string_t file;
Packit d394d9
          
Packit d394d9
  /* Initialise the value stack. */
Packit d394d9
  top = rule_sys->rules[ rule_number ].param_count;
Packit d394d9
  base = bottom = 0;
Packit d394d9
Packit d394d9
  /* Reset nesting and alternative paths. */
Packit d394d9
  nested_subrules = path_count = 0;
Packit d394d9
  while (path_list.first != NULL) 
Packit d394d9
    free_first_node( &path_list );
Packit d394d9
Packit d394d9
  /* Copy RULE_SYS and RULE_NUMBER for debugger and error messages. */
Packit d394d9
  executed_rule_sys = rule_sys;
Packit d394d9
  executed_rule_number = rule_number;
Packit d394d9
Packit d394d9
  pc = rule_sys->rules[ rule_number ].first_instr;
Packit d394d9
  TRY 
Packit d394d9
  { 
Packit d394d9
    rule_successful = FALSE;
Packit d394d9
    terminate = FALSE;
Packit d394d9
    while (! terminate) 
Packit d394d9
    { 
Packit d394d9
      if (user_break_requested) 
Packit d394d9
      {
Packit d394d9
	source_of_instr( rule_sys, pc, NULL, &file, NULL );
Packit d394d9
	if (file != NULL)
Packit d394d9
	{
Packit d394d9
	  if (debug_rule_sys == rule_sys) 
Packit d394d9
	    debug_rule( TRUE );
Packit d394d9
	  else 
Packit d394d9
	    complain( "User break." );
Packit d394d9
	}
Packit d394d9
      } 
Packit d394d9
      else if (debug_rule_sys == rule_sys) 
Packit d394d9
	debug_rule( FALSE );
Packit d394d9
      instruction = rule_sys->instrs[ pc ];
Packit d394d9
      new_pc = pc + 1;
Packit d394d9
      info = INSTR_INFO( instruction );
Packit d394d9
      switch (OPCODE( instruction ) ) 
Packit d394d9
      {
Packit d394d9
      case INS_SYSTEM_ERROR:
Packit d394d9
        switch (info) 
Packit d394d9
	{
Packit d394d9
        case ASSERTION_ERROR: 
Packit d394d9
	  complain( "Assertion failed." );
Packit d394d9
        case NO_RETURN_ERROR: 
Packit d394d9
	  complain( "Missing return statement." );
Packit d394d9
        }
Packit d394d9
      case INS_ERROR:
Packit d394d9
	complain( "%s", value_to_string( value_stack[ --top ] ) );
Packit d394d9
      case INS_TERMINATE:
Packit d394d9
        terminate = TRUE;
Packit d394d9
        break;
Packit d394d9
      case INS_NOP:
Packit d394d9
        break;
Packit d394d9
      case INS_TERMINATE_IF_NULL:
Packit d394d9
        if (value_stack[ --top ] == NULL) 
Packit d394d9
	  terminate = TRUE;
Packit d394d9
        break;
Packit d394d9
      case INS_ADD_END_STATE:
Packit d394d9
        add_end_state( value_stack[ --top ] );
Packit d394d9
        rule_successful = TRUE;
Packit d394d9
        break;
Packit d394d9
      case INS_ADD_STATE:
Packit d394d9
        add_running_state( value_stack[ --top ], info );
Packit d394d9
        rule_successful = TRUE;
Packit d394d9
        break;
Packit d394d9
      case INS_ADD_ALLO:
Packit d394d9
        add_allo( value_to_string( value_stack[ top - 2 ] ), 
Packit d394d9
		  value_stack[ top - 1] );
Packit d394d9
        top -= 2;
Packit d394d9
        rule_successful = TRUE;
Packit d394d9
        break;
Packit d394d9
      case INS_ACCEPT:
Packit d394d9
        path_count = 0;
Packit d394d9
        while (path_list.first != NULL) 
Packit d394d9
	  free_first_node( &path_list );
Packit d394d9
        terminate = TRUE;
Packit d394d9
        break;
Packit d394d9
      case INS_PUSH_NULL:
Packit d394d9
        for (i = 0; i < info; i++) 
Packit d394d9
	  push_value( NULL );
Packit d394d9
        break;
Packit d394d9
      case INS_PUSH_VAR:
Packit d394d9
        push_value( value_stack[ base + info ] );
Packit d394d9
        break;
Packit d394d9
      case INS_PUSH_CONST:
Packit d394d9
        push_value( rule_sys->values + info );
Packit d394d9
        break;
Packit d394d9
      case INS_PUSH_SYMBOL:
Packit d394d9
        push_symbol_value( info );
Packit d394d9
        break;
Packit d394d9
      case INS_PUSH_PATTERN_VAR:
Packit d394d9
        push_string_value( pattern_var[ info ], NULL );
Packit d394d9
        break;
Packit d394d9
      case INS_POP:
Packit d394d9
        top -= info;
Packit d394d9
        break;
Packit d394d9
      case INS_POP_TO:
Packit d394d9
        top = base + info;
Packit d394d9
        break;
Packit d394d9
      case INS_BUILD_LIST:
Packit d394d9
        build_list( info );
Packit d394d9
        break;
Packit d394d9
      case INS_BUILD_RECORD:
Packit d394d9
        build_record( info );
Packit d394d9
        break;
Packit d394d9
      case INS_BUILD_PATH:
Packit d394d9
        build_path( info );
Packit d394d9
        break;
Packit d394d9
      case INS_DOT_OPERATION:
Packit d394d9
        dot_operation();
Packit d394d9
        if (value_stack[ top - 1 ] == NULL) 
Packit d394d9
	  value_stack[ top - 1 ] = &nil;
Packit d394d9
        break;
Packit d394d9
      case INS_PLUS_OPERATION:
Packit d394d9
        plus_operation();
Packit d394d9
        break;
Packit d394d9
      case INS_MINUS_OPERATION:
Packit d394d9
        minus_operation();
Packit d394d9
        break;
Packit d394d9
      case INS_ASTERISK_OPERATION:
Packit d394d9
        asterisk_operation();
Packit d394d9
        break;
Packit d394d9
      case INS_SLASH_OPERATION:
Packit d394d9
        slash_operation();
Packit d394d9
        break;
Packit d394d9
      case INS_UNARY_MINUS_OP:
Packit d394d9
        unary_minus_operation();
Packit d394d9
        break;
Packit d394d9
      case INS_GET_ATTRIBUTE:
Packit d394d9
        value_stack[ top - 1 ] = get_attribute( value_stack[ top - 1 ], 
Packit d394d9
						(symbol_t) info );
Packit d394d9
        if (value_stack[ top - 1 ] == NULL) 
Packit d394d9
	  value_stack[ top - 1 ] = &nil;
Packit d394d9
        break;
Packit d394d9
      case INS_REMOVE_ATTRIBUTE:
Packit d394d9
        remove_attribute( (symbol_t) info );
Packit d394d9
        break;
Packit d394d9
      case INS_STD_FUNCTION:
Packit d394d9
        standard_function( info );
Packit d394d9
        break;
Packit d394d9
      case INS_MATCH:
Packit d394d9
        if (match_pattern( value_to_string( value_stack[ --top ] ), 
Packit d394d9
                           rule_sys->strings + info )) 
Packit d394d9
	{ 
Packit d394d9
	  push_symbol_value( YES_SYMBOL ); 
Packit d394d9
	} 
Packit d394d9
	else 
Packit d394d9
	  push_symbol_value( NO_SYMBOL );
Packit d394d9
        break;
Packit d394d9
      case INS_SET_VAR:
Packit d394d9
        value_stack[ base + info ] = value_stack[ --top ];
Packit d394d9
        break;
Packit d394d9
      case INS_PLUS_VAR:
Packit d394d9
        insert_value( 1, value_stack[ base + info ] );
Packit d394d9
        plus_operation();
Packit d394d9
        value_stack[ base + info ] = value_stack[ --top ];
Packit d394d9
        break;
Packit d394d9
      case INS_MINUS_VAR:
Packit d394d9
        insert_value( 1, value_stack[ base + info ]);
Packit d394d9
        minus_operation();
Packit d394d9
        value_stack[ base + info ] = value_stack[ --top ];
Packit d394d9
        break;
Packit d394d9
      case INS_ASTERISK_VAR:
Packit d394d9
        insert_value( 1, value_stack[ base + info ] );
Packit d394d9
        asterisk_operation();
Packit d394d9
        value_stack[ base + info ] = value_stack[ --top ];
Packit d394d9
        break;
Packit d394d9
      case INS_SLASH_VAR:
Packit d394d9
        insert_value( 1, value_stack[ base + info ] );
Packit d394d9
        slash_operation();
Packit d394d9
        value_stack[ base + info ] = value_stack[ --top ];
Packit d394d9
        break;
Packit d394d9
      case INS_SET_VAR_PATH:
Packit d394d9
        insert_value( 2, value_stack[ base + info ] );
Packit d394d9
        modify_value_part( right_value );
Packit d394d9
        value_stack[ base + info ] = value_stack[ --top ];
Packit d394d9
        break;
Packit d394d9
      case INS_PLUS_VAR_PATH:
Packit d394d9
        insert_value( 2, value_stack[ base + info ] );
Packit d394d9
        modify_value_part( plus_operation );
Packit d394d9
        value_stack[ base + info ] = value_stack[ --top ];
Packit d394d9
        break;
Packit d394d9
      case INS_MINUS_VAR_PATH:
Packit d394d9
        insert_value( 2, value_stack[ base + info ] );
Packit d394d9
        modify_value_part( minus_operation );
Packit d394d9
        value_stack[ base + info ] = value_stack[ --top ];
Packit d394d9
        break;
Packit d394d9
      case INS_ASTERISK_VAR_PATH:
Packit d394d9
        insert_value( 2, value_stack[ base + info ] );
Packit d394d9
        modify_value_part( asterisk_operation );
Packit d394d9
        value_stack[ base + info ] = value_stack[ --top ];
Packit d394d9
        break;
Packit d394d9
      case INS_SLASH_VAR_PATH:
Packit d394d9
        insert_value( 2, value_stack[ base + info ] );
Packit d394d9
        modify_value_part( slash_operation );
Packit d394d9
        value_stack[ base + info ] = value_stack[ --top ];
Packit d394d9
        break;
Packit d394d9
      case INS_DECOMPOSE_LIST:
Packit d394d9
        if (info != decompose_list()) 
Packit d394d9
	  complain( "List doesn't contain %d elements.", info );
Packit d394d9
        break;
Packit d394d9
      case INS_GET_1ST_ELEMENT:
Packit d394d9
        get_first_element();
Packit d394d9
        break;
Packit d394d9
      case INS_ITERATE:
Packit d394d9
        get_next_element( base + info );
Packit d394d9
        break;
Packit d394d9
      case INS_JUMP:
Packit d394d9
        new_pc = info;
Packit d394d9
        break;
Packit d394d9
      case INS_JUMP_IF_EQUAL:
Packit d394d9
	if (values_equal( value_stack[top - 2], value_stack[top - 1] )) 
Packit d394d9
	  new_pc = info;
Packit d394d9
        top -= 2;
Packit d394d9
        break;
Packit d394d9
      case INS_JUMP_IF_NOT_EQUAL:
Packit d394d9
        if (! values_equal( value_stack[top - 2], value_stack[top - 1] )) 
Packit d394d9
	  new_pc = info;
Packit d394d9
        top -= 2;
Packit d394d9
        break;
Packit d394d9
      case INS_JUMP_IF_CONGR:
Packit d394d9
        if (values_congruent( value_stack[top - 2], value_stack[top - 1] ))
Packit d394d9
	  new_pc = info;
Packit d394d9
        top -= 2;
Packit d394d9
        break;
Packit d394d9
      case INS_JUMP_IF_NOT_CONGR:
Packit d394d9
        if (! values_congruent( value_stack[top - 2], value_stack[top - 1] ))
Packit d394d9
	  new_pc = info;
Packit d394d9
        top -= 2;
Packit d394d9
        break;
Packit d394d9
      case INS_JUMP_IF_IN:
Packit d394d9
        if (value_in_value( value_stack[top - 2], value_stack[top - 1] )) 
Packit d394d9
	  new_pc = info;
Packit d394d9
        top -= 2;
Packit d394d9
        break;
Packit d394d9
      case INS_JUMP_IF_NOT_IN:
Packit d394d9
        if (! value_in_value( value_stack[top - 2], value_stack[top - 1] )) 
Packit d394d9
	  new_pc = info;
Packit d394d9
        top -= 2;
Packit d394d9
        break;
Packit d394d9
      case INS_JUMP_IF_LESS:
Packit d394d9
        if (value_to_double( value_stack[top - 2] ) 
Packit d394d9
            < value_to_double( value_stack[top - 1] )) 
Packit d394d9
	{ 
Packit d394d9
	  new_pc = info; 
Packit d394d9
	}
Packit d394d9
        top -= 2;
Packit d394d9
        break;
Packit d394d9
      case INS_JUMP_IF_NOT_LESS:
Packit d394d9
        if (! (value_to_double( value_stack[top - 2] )
Packit d394d9
               < value_to_double( value_stack[top - 1] ))) 
Packit d394d9
	{ 
Packit d394d9
	  new_pc = info; 
Packit d394d9
	}
Packit d394d9
        top -= 2;
Packit d394d9
        break;
Packit d394d9
      case INS_JUMP_IF_GREATER:
Packit d394d9
        if (value_to_double( value_stack[top - 2] )
Packit d394d9
            > value_to_double( value_stack[top - 1] )) 
Packit d394d9
	{ 
Packit d394d9
	  new_pc = info; 
Packit d394d9
	}
Packit d394d9
        top -= 2;
Packit d394d9
        break;
Packit d394d9
      case INS_JUMP_IF_NOT_GREATER:
Packit d394d9
        if (! (value_to_double( value_stack[top - 2] )
Packit d394d9
               > value_to_double( value_stack[top - 1] ))) 
Packit d394d9
	{ 
Packit d394d9
	  new_pc = info; 
Packit d394d9
	}
Packit d394d9
        top -= 2;
Packit d394d9
        break;
Packit d394d9
      case INS_JUMP_IF_NULL:
Packit d394d9
        if (value_stack[ --top ] == NULL) 
Packit d394d9
	  new_pc = info;
Packit d394d9
        break;
Packit d394d9
      case INS_JUMP_IF_NOT_NULL:
Packit d394d9
        if (value_stack[ --top ] != NULL) 
Packit d394d9
	  new_pc = info;
Packit d394d9
        break;
Packit d394d9
      case INS_JUMP_IF_YES:
Packit d394d9
        symbol = value_to_symbol( value_stack[ --top ] );
Packit d394d9
        if (symbol != YES_SYMBOL && symbol != NO_SYMBOL) 
Packit d394d9
	  complain( "Boolean value expected." );
Packit d394d9
        if (symbol == YES_SYMBOL) 
Packit d394d9
	  new_pc = info;
Packit d394d9
        break;
Packit d394d9
      case INS_JUMP_IF_NO:
Packit d394d9
        symbol = value_to_symbol( value_stack[ --top ] );
Packit d394d9
        if (symbol != YES_SYMBOL && symbol != NO_SYMBOL) 
Packit d394d9
	  complain( "Boolean value expected." );
Packit d394d9
        if (symbol == NO_SYMBOL) 
Packit d394d9
	  new_pc = info;
Packit d394d9
        break;
Packit d394d9
      case INS_JUMP_NOW:
Packit d394d9
        old_top = top;
Packit d394d9
        path = new_node( &path_list, sizeof( path_node_t ), LIST_START );
Packit d394d9
        path->pc = new_pc;
Packit d394d9
        path->nested_subrules = nested_subrules;
Packit d394d9
        path->base = base;
Packit d394d9
        path->bottom = bottom;
Packit d394d9
        while (bottom < old_top)
Packit d394d9
	  push_value( value_stack[ bottom++ ] );
Packit d394d9
        base += (top - old_top);
Packit d394d9
        path_count++;
Packit d394d9
        new_pc = info;
Packit d394d9
        break;
Packit d394d9
      case INS_JUMP_LATER:
Packit d394d9
        old_top = top;
Packit d394d9
        path = new_node( &path_list, sizeof( path_node_t ), LIST_START );
Packit d394d9
        path->pc = info;
Packit d394d9
        path->nested_subrules = nested_subrules;
Packit d394d9
        path->base = base;
Packit d394d9
        path->bottom = bottom;
Packit d394d9
        while (bottom < old_top) 
Packit d394d9
	  push_value( value_stack[ bottom++ ] );
Packit d394d9
        base += (top - old_top);
Packit d394d9
        path_count++;
Packit d394d9
        break;
Packit d394d9
      case INS_JUMP_SUBRULE:
Packit d394d9
        push_number_value( base - bottom );
Packit d394d9
        push_number_value( new_pc );
Packit d394d9
        base = top;
Packit d394d9
        new_pc = rule_sys->rules[ info ].first_instr;
Packit d394d9
        nested_subrules++;
Packit d394d9
        break;
Packit d394d9
      case INS_RETURN:
Packit d394d9
        old_base = bottom + value_to_int( value_stack[ base - 2 ] );
Packit d394d9
        new_pc = value_to_int( value_stack[ base - 1 ] );
Packit d394d9
        value_stack[ base - info - 2 ] = value_stack[ top - 1 ]; /* Result. */
Packit d394d9
        top = base - (info + 1);
Packit d394d9
        base = old_base;
Packit d394d9
        nested_subrules--;
Packit d394d9
        break;
Packit d394d9
      default:
Packit d394d9
        complain( "Internal error." );
Packit d394d9
        break;
Packit d394d9
      }
Packit d394d9
      if (! terminate) 
Packit d394d9
	pc = new_pc;
Packit d394d9
      else if (path_list.first != NULL) 
Packit d394d9
      { 
Packit d394d9
	/* Load a previously saved rule-internal path and continue. */
Packit d394d9
        path_count--;
Packit d394d9
        path = (path_node_t *) path_list.first;
Packit d394d9
        top = bottom;
Packit d394d9
        base = path->base;
Packit d394d9
        bottom = path->bottom;
Packit d394d9
        pc = path->pc;
Packit d394d9
        nested_subrules = path->nested_subrules;
Packit d394d9
        free_first_node( &path_list );
Packit d394d9
        terminate = FALSE;
Packit d394d9
      }
Packit d394d9
    }
Packit d394d9
  } 
Packit d394d9
  IF_ERROR 
Packit d394d9
  { 
Packit d394d9
    source_of_instr( executed_rule_sys, pc, &line, &file, NULL );
Packit d394d9
    print_text( error_text, " (\"%s\", line %d)", name_in_path( file ), line );
Packit d394d9
    if (in_emacs_malaga_mode) 
Packit d394d9
      printf( "SHOW \"%s\":%d:0\n", file, line );
Packit d394d9
  } 
Packit d394d9
  END_TRY;
Packit d394d9
Packit d394d9
  pc = -1;
Packit d394d9
  executed_rule_number = -1;
Packit d394d9
  executed_rule_sys = NULL;
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
rule_sys_t *
Packit d394d9
read_rule_sys( string_t file_name )
Packit d394d9
/* Read rule system from file FILE_NAME.
Packit d394d9
 * A symbol file must have already been loaded. */
Packit d394d9
{ 
Packit d394d9
  FILE *stream;
Packit d394d9
  rule_header_t header;
Packit d394d9
  rule_sys_t *rule_sys;
Packit d394d9
Packit d394d9
  stream = open_stream( file_name, "rb" );
Packit d394d9
  read_vector( &header, sizeof( header ), 1, stream, file_name );
Packit d394d9
  check_header( &header.common_header, file_name, 
Packit d394d9
                RULE_FILE, MIN_RULE_CODE_VERSION, RULE_CODE_VERSION );
Packit d394d9
Packit d394d9
  rule_sys = new_mem( sizeof( rule_sys_t ) );
Packit d394d9
  rule_sys->initial_rule_set = header.initial_rule_set;
Packit d394d9
  rule_sys->initial_feat = header.initial_feat;
Packit d394d9
  rule_sys->robust_rule = header.robust_rule;
Packit d394d9
  rule_sys->allo_rule = header.allo_rule;
Packit d394d9
  rule_sys->pruning_rule = header.pruning_rule;
Packit d394d9
  rule_sys->input_filter = header.input_filter;
Packit d394d9
  rule_sys->output_filter = header.output_filter;
Packit d394d9
  rule_sys->rule_count = header.rule_count;
Packit d394d9
  rule_sys->rules = read_new_vector( sizeof( rule_t ), header.rule_count,
Packit d394d9
                                     stream, file_name );
Packit d394d9
  rule_sys->rule_sets_size = header.rule_sets_size;
Packit d394d9
  rule_sys->rule_sets = read_new_vector( sizeof( int_t ), 
Packit d394d9
					 header.rule_sets_size,
Packit d394d9
                                         stream, file_name );
Packit d394d9
  rule_sys->instr_count = header.instr_count;
Packit d394d9
  rule_sys->instrs = read_new_vector( sizeof( instr_t ), header.instr_count, 
Packit d394d9
                                      stream, file_name );
Packit d394d9
  rule_sys->values_size = header.values_size;
Packit d394d9
  rule_sys->values = read_new_vector( sizeof( cell_t ), header.values_size, 
Packit d394d9
                                      stream, file_name );
Packit d394d9
  rule_sys->src_line_count = header.src_line_count;
Packit d394d9
  rule_sys->src_lines = read_new_vector( sizeof( src_line_t ), 
Packit d394d9
                                         header.src_line_count, 
Packit d394d9
                                         stream, file_name );
Packit d394d9
  rule_sys->var_count = header.var_count;
Packit d394d9
  rule_sys->vars = read_new_vector( sizeof( var_t ), header.var_count,
Packit d394d9
                                    stream, file_name );
Packit d394d9
  rule_sys->var_scope_count = header.var_scope_count;
Packit d394d9
  rule_sys->var_scopes = read_new_vector( sizeof( var_scope_t ), 
Packit d394d9
                                          header.var_scope_count,
Packit d394d9
                                          stream, file_name );
Packit d394d9
  rule_sys->constant_count = header.constant_count;
Packit d394d9
  rule_sys->constants = read_new_vector( sizeof( constant_t ), 
Packit d394d9
					 header.constant_count, 
Packit d394d9
					 stream, file_name );
Packit d394d9
  rule_sys->strings_size = header.strings_size;
Packit d394d9
  rule_sys->strings = read_new_vector( sizeof( char_t ), header.strings_size, 
Packit d394d9
                                       stream, file_name );
Packit d394d9
Packit d394d9
  close_stream( &stream, file_name );
Packit d394d9
  return rule_sys;
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
void 
Packit d394d9
free_rule_sys( rule_sys_t **rule_sys )
Packit d394d9
/* Free all memory used by *RULE_SYS. */
Packit d394d9
{ 
Packit d394d9
  if (*rule_sys != NULL) 
Packit d394d9
  { 
Packit d394d9
    free_mem( &(*rule_sys)->rules );
Packit d394d9
    free_mem( &(*rule_sys)->rule_sets );
Packit d394d9
    free_mem( &(*rule_sys)->instrs );
Packit d394d9
    free_mem( &(*rule_sys)->values );
Packit d394d9
    free_mem( &(*rule_sys)->src_lines );
Packit d394d9
    free_mem( &(*rule_sys)->vars );
Packit d394d9
    free_mem( &(*rule_sys)->var_scopes );
Packit d394d9
    free_mem( &(*rule_sys)->constants );
Packit d394d9
    free_mem( &(*rule_sys)->strings );
Packit d394d9
    free_mem( rule_sys );
Packit d394d9
  }
Packit d394d9
}
Packit d394d9
Packit d394d9
/* Debug support functions. =================================================*/
Packit d394d9
Packit d394d9
void 
Packit d394d9
source_of_instr( rule_sys_t *rule_sys, int_t instr_index, 
Packit d394d9
                 int_t *line, string_t *file_name, string_t *rule_name )
Packit d394d9
/* Set *LINE, *FILE_NAME and *RULE_NAME to appropriate values
Packit d394d9
 * for the statement that has generated the instruction at INSTR_INDEX. */
Packit d394d9
{ 
Packit d394d9
  int_t lower, upper, middle;
Packit d394d9
  src_line_t *src_line;
Packit d394d9
  int_t rule_number, i, first_instr;
Packit d394d9
  rule_t *rule;
Packit d394d9
    
Packit d394d9
  if (rule_sys->src_line_count == 0 
Packit d394d9
      || rule_sys->src_lines[0].instr > instr_index) 
Packit d394d9
  { 
Packit d394d9
    if (line != NULL) 
Packit d394d9
      *line = -1;
Packit d394d9
    if (file_name != NULL) 
Packit d394d9
      *file_name = NULL;
Packit d394d9
    if (rule_name != NULL) 
Packit d394d9
      *rule_name = NULL;
Packit d394d9
    return;
Packit d394d9
  }
Packit d394d9
  /* Find the last SRC_LINE entry with INSTR <= INSTR_INDEX. */
Packit d394d9
  lower = 0;
Packit d394d9
  upper = rule_sys->src_line_count - 1;
Packit d394d9
  while (lower < upper) 
Packit d394d9
  { 
Packit d394d9
    middle = (lower + upper + 1) / 2;
Packit d394d9
    src_line = rule_sys->src_lines + middle;
Packit d394d9
    if (src_line->instr <= instr_index) 
Packit d394d9
      lower = middle;
Packit d394d9
    else 
Packit d394d9
      upper = middle - 1;
Packit d394d9
  }
Packit d394d9
  src_line = rule_sys->src_lines + lower;
Packit d394d9
  if (line != NULL)  
Packit d394d9
    *line = src_line->line;
Packit d394d9
  if (file_name != NULL) 
Packit d394d9
  { 
Packit d394d9
    if (src_line->file != -1) 
Packit d394d9
      *file_name = rule_sys->strings + src_line->file;
Packit d394d9
    else 
Packit d394d9
      *file_name = NULL;
Packit d394d9
  }
Packit d394d9
Packit d394d9
  /* Find the rule of the statement */
Packit d394d9
  if (rule_name != NULL) 
Packit d394d9
  { 
Packit d394d9
    rule_number = 0;
Packit d394d9
    first_instr = -1;
Packit d394d9
    for (i = 0; i < rule_sys->rule_count; i++) 
Packit d394d9
    { 
Packit d394d9
      rule = rule_sys->rules + i;
Packit d394d9
      if (rule->first_instr <= instr_index && rule->first_instr > first_instr)
Packit d394d9
      { 
Packit d394d9
	rule_number = i;
Packit d394d9
        first_instr = rule->first_instr;
Packit d394d9
      }
Packit d394d9
    }
Packit d394d9
    *rule_name = rule_sys->strings + rule_sys->rules[ rule_number ].name;
Packit d394d9
  }
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
string_t 
Packit d394d9
rule_set_readable( rule_sys_t *rule_sys, int_t rule_set )
Packit d394d9
/* Return RULE_SET in RULE_SYS as a readable string.
Packit d394d9
 * The string must be freed after use. */
Packit d394d9
{ 
Packit d394d9
  text_t *text;
Packit d394d9
  bool_t name_has_been_printed;
Packit d394d9
  int_t *rule;
Packit d394d9
      
Packit d394d9
  text = new_text();
Packit d394d9
  if (rule_set == -1) 
Packit d394d9
    add_to_text( text, "(end state)" );
Packit d394d9
  else 
Packit d394d9
  { 
Packit d394d9
    add_to_text( text, "rules " );
Packit d394d9
    rule = rule_sys->rule_sets + rule_set;
Packit d394d9
    while (TRUE) 
Packit d394d9
    { 
Packit d394d9
      name_has_been_printed = FALSE;
Packit d394d9
      while (*rule >= 0) 
Packit d394d9
      { 
Packit d394d9
	if (name_has_been_printed) 
Packit d394d9
	  add_to_text( text, ", " );
Packit d394d9
	else 
Packit d394d9
	  name_has_been_printed = TRUE;
Packit d394d9
        add_to_text( text, 
Packit d394d9
		     rule_sys->strings + rule_sys->rules[ *rule++ ].name );
Packit d394d9
      }
Packit d394d9
      if (*rule == -1) 
Packit d394d9
	break;
Packit d394d9
      add_to_text( text, " else " );
Packit d394d9
      rule++;
Packit d394d9
    }
Packit d394d9
  }
Packit d394d9
  return text_to_string( &text );
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
static int_t 
Packit d394d9
first_variable_index( int_t instr_index )
Packit d394d9
/* Return the stack index of the first variable that is visible
Packit d394d9
 * when PC is at INSTR_INDEX in RULE_SYS. */
Packit d394d9
{ 
Packit d394d9
  rule_t *rule, *rule2;
Packit d394d9
  int_t i, first_instr;
Packit d394d9
Packit d394d9
  /* Find the rule/subrule we're in. */
Packit d394d9
  rule = NULL;
Packit d394d9
  first_instr = -1;
Packit d394d9
  for (i = 0; i < executed_rule_sys->rule_count; i++) 
Packit d394d9
  { 
Packit d394d9
    rule2 = executed_rule_sys->rules + i;
Packit d394d9
    if (rule2->first_instr <= instr_index && rule2->first_instr > first_instr)
Packit d394d9
    { 
Packit d394d9
      rule = rule2;
Packit d394d9
      first_instr = rule->first_instr;
Packit d394d9
    }
Packit d394d9
  }
Packit d394d9
Packit d394d9
  if (rule->type == SUBRULE) 
Packit d394d9
    return - (2 + rule->param_count);
Packit d394d9
  else 
Packit d394d9
    return 0;
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
int_t 
Packit d394d9
get_frame_count( void )
Packit d394d9
/* Get the number of frames in the current path. */
Packit d394d9
{ 
Packit d394d9
  int_t frame, count;
Packit d394d9
Packit d394d9
  /* Count the number of frames. */
Packit d394d9
  count = 1;
Packit d394d9
  for (frame = base; 
Packit d394d9
       frame > bottom; 
Packit d394d9
       frame = bottom + value_to_int( value_stack[ frame - 2 ] ))
Packit d394d9
  {
Packit d394d9
    count++;
Packit d394d9
  }
Packit d394d9
  return count;
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
void
Packit d394d9
get_frame_info( int_t frame, 
Packit d394d9
		int_t *pc_index, 
Packit d394d9
		int_t *base_index,
Packit d394d9
		int_t *first_var_index,
Packit d394d9
		int_t *last_var_index )
Packit d394d9
/* Return *PC_INDEX, *BASE_INDEX, *FIRST_VAR_INDEX and *LAST_VAR_INDEX
Packit d394d9
 * of the frame no. FRAME. Any result pointer may be NULL. 
Packit d394d9
 * Frame no. 0 is the current frame, 
Packit d394d9
 * frame no. "get_frame_count() - 1" is the outermost one. */
Packit d394d9
{ 
Packit d394d9
  int_t first_var_idx, last_var_idx, base_idx, pc_idx;
Packit d394d9
Packit d394d9
  last_var_idx = top;
Packit d394d9
  pc_idx = pc;
Packit d394d9
  base_idx = base;
Packit d394d9
  first_var_idx = base_idx + first_variable_index( pc_idx );
Packit d394d9
  
Packit d394d9
  /* Find the right frame. */
Packit d394d9
  for (; frame > 0; frame--)
Packit d394d9
  {
Packit d394d9
    last_var_idx = first_var_idx;
Packit d394d9
    pc_idx = value_to_int( value_stack[ base_idx - 1 ] );
Packit d394d9
    base_idx = bottom + value_to_int( value_stack[ base_idx - 2 ] );
Packit d394d9
    first_var_idx = base_idx + first_variable_index( pc_idx );
Packit d394d9
  }
Packit d394d9
Packit d394d9
  if (pc_index != NULL) 
Packit d394d9
    *pc_index = pc_idx;
Packit d394d9
  if (base_index != NULL) 
Packit d394d9
    *base_index = base_idx;
Packit d394d9
  if (first_var_index != NULL) 
Packit d394d9
    *first_var_index = first_var_idx;
Packit d394d9
  if (last_var_index != NULL) 
Packit d394d9
    *last_var_index = last_var_idx;
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
static var_scope_t *
Packit d394d9
get_var_scope( rule_sys_t *rule_sys, var_t *var, int_t instr_index )
Packit d394d9
/* Return the stack index of variable VAR at INSTR_INDEX.
Packit d394d9
 * Return -1 if it is not currently defined. */
Packit d394d9
{ 
Packit d394d9
  int_t lower, upper, middle;
Packit d394d9
  var_scope_t *var_scope;
Packit d394d9
Packit d394d9
  /* Find last scope whose FIRST_INSTR is not higher than INSTR_INDEX. */ 
Packit d394d9
  lower = var->first_scope;
Packit d394d9
  upper = lower + var->scope_count - 1;
Packit d394d9
Packit d394d9
  while (lower < upper) 
Packit d394d9
  { 
Packit d394d9
    middle = (lower + upper + 1) / 2;
Packit d394d9
    var_scope = rule_sys->var_scopes + middle;
Packit d394d9
    if (var_scope->first_instr <= instr_index) 
Packit d394d9
      lower = middle;
Packit d394d9
    else 
Packit d394d9
      upper = middle - 1;
Packit d394d9
  }
Packit d394d9
Packit d394d9
  /* LOWER is the index of the highest line
Packit d394d9
   * with an instruction index not more than INSTR_INDEX. */
Packit d394d9
  if (lower == upper) /* We found a scope. */
Packit d394d9
  { 
Packit d394d9
    var_scope = rule_sys->var_scopes + lower;
Packit d394d9
    if (instr_index >= var_scope->first_instr 
Packit d394d9
        && instr_index <= var_scope->last_instr) 
Packit d394d9
    { 
Packit d394d9
      return var_scope; 
Packit d394d9
    }
Packit d394d9
  }
Packit d394d9
  
Packit d394d9
  return NULL;
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
string_t 
Packit d394d9
variable_at_index( rule_sys_t *rule_sys, int_t stack_index, int_t instr_index )
Packit d394d9
/* Return the name of the variable that is defined at STACK_INDEX
Packit d394d9
 * when instruction INSTR_INDEX is executed or NULL if there is none. */
Packit d394d9
{ 
Packit d394d9
  int_t i;
Packit d394d9
  var_t *var;
Packit d394d9
  var_scope_t *var_scope;
Packit d394d9
Packit d394d9
  /* There is never a variable at stack index -2 or -1. */
Packit d394d9
  if (stack_index == -2 || stack_index == -1) 
Packit d394d9
    return NULL;
Packit d394d9
Packit d394d9
  /* For each variable name, test if it is the right one. */
Packit d394d9
  for (i = 0; i < rule_sys->var_count; i++)  
Packit d394d9
  { 
Packit d394d9
    var = rule_sys->vars + i;
Packit d394d9
    var_scope = get_var_scope( rule_sys, var, instr_index );
Packit d394d9
    if (var_scope != NULL && var_scope->stack_index == stack_index) 
Packit d394d9
      return rule_sys->strings + var->name;
Packit d394d9
  }
Packit d394d9
Packit d394d9
  return NULL;
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
var_scope_t *
Packit d394d9
get_var_scope_by_name( rule_sys_t *rule_sys, 
Packit d394d9
		       string_t var_name, 
Packit d394d9
		       int_t instr_index )
Packit d394d9
/* Return the scope of variable VAR_NAME at INSTR_INDEX. */
Packit d394d9
{ 
Packit d394d9
  int_t lower, upper, middle, result;
Packit d394d9
  var_t *var;
Packit d394d9
Packit d394d9
  /* Search for the right variable name (binary search). */
Packit d394d9
  lower = 0;
Packit d394d9
  upper = rule_sys->var_count - 1;
Packit d394d9
  while (lower <= upper) 
Packit d394d9
  { 
Packit d394d9
    middle = (lower + upper) / 2;
Packit d394d9
    var = rule_sys->vars + middle;
Packit d394d9
    result = strcmp_no_case( var_name, rule_sys->strings + var->name );
Packit d394d9
    if (result < 0) 
Packit d394d9
      upper = middle - 1;
Packit d394d9
    else if (result > 0) 
Packit d394d9
      lower = middle + 1;
Packit d394d9
    else 
Packit d394d9
      return get_var_scope( rule_sys, var, instr_index );
Packit d394d9
  }
Packit d394d9
  return NULL;
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
value_t
Packit d394d9
get_constant( rule_sys_t *rule_sys, string_t name )
Packit d394d9
/* Return the value of constant NAME in RULE_SYS.
Packit d394d9
 * Return NULL if there is no such constant. */
Packit d394d9
{ 
Packit d394d9
  int_t lower, upper, middle, result;
Packit d394d9
  constant_t *constant;
Packit d394d9
Packit d394d9
  /* Search for the right variable name (binary search). */
Packit d394d9
  lower = 0;
Packit d394d9
  upper = rule_sys->constant_count - 1;
Packit d394d9
  while (lower <= upper) 
Packit d394d9
  { 
Packit d394d9
    middle = (lower + upper) / 2;
Packit d394d9
    constant = rule_sys->constants + middle;
Packit d394d9
    result = strcmp_no_case( name, rule_sys->strings + constant->name );
Packit d394d9
    if (result < 0) 
Packit d394d9
      upper = middle - 1;
Packit d394d9
    else if (result > 0) 
Packit d394d9
      lower = middle + 1;
Packit d394d9
    else 
Packit d394d9
      return rule_sys->values + constant->value;
Packit d394d9
  }
Packit d394d9
  return NULL;
Packit d394d9
}
Packit d394d9
Packit d394d9
/* End of file. =============================================================*/