Blame sym_compiler.c

Packit d394d9
/* Copyright (C) 1995 Bjoern Beutel. */
Packit d394d9
Packit d394d9
/* Description. =============================================================*/
Packit d394d9
Packit d394d9
/* This module compiles malaga symbol files. */
Packit d394d9
Packit d394d9
/* Includes. ================================================================*/
Packit d394d9
Packit d394d9
#include <stdio.h>
Packit d394d9
#include <stdlib.h>
Packit d394d9
#include <time.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 "scanner.h"
Packit d394d9
#include "files.h"
Packit d394d9
#include "malaga_files.h"
Packit d394d9
#include "symbols.h"
Packit d394d9
#include "avl_trees.h"
Packit d394d9
#include "hangul.h"
Packit d394d9
#include "sym_compiler.h"
Packit d394d9
Packit d394d9
/* Types. ===================================================================*/
Packit d394d9
Packit d394d9
typedef struct /* A node of the symbol table. */
Packit d394d9
{ 
Packit d394d9
  avln_node_t node; /* The symbol tree is an AVLN tree. */
Packit d394d9
  value_t atoms; /* List of atoms in VALUE_POOL. */
Packit d394d9
  symbol_t symbol; /* Symbol which this node represents. */
Packit d394d9
} symbol_node_t;
Packit d394d9
Packit d394d9
typedef struct /* A node of the atoms tree. */
Packit d394d9
{
Packit d394d9
  avl_node_t node; /* The atoms tree is an AVL tree, sorted by its atoms. */
Packit d394d9
  value_t atoms;
Packit d394d9
  symbol_t symbol;
Packit d394d9
  string_t name;
Packit d394d9
} atoms_node_t;
Packit d394d9
Packit d394d9
/* Variables. ===============================================================*/
Packit d394d9
Packit d394d9
static avln_node_t *symbol_tree; /* The symbol table, sorted by names.
Packit d394d9
				  * This is actually a symbol_node_t. */
Packit d394d9
static avl_node_t *atoms_tree; /* The symbol table, sorted by atoms.
Packit d394d9
				* This is actually a atoms_node_t. */
Packit d394d9
Packit d394d9
static pool_t symbol_pool; /* Symbol entries. */
Packit d394d9
static pool_t value_pool; /* Lists of atomic symbols. */
Packit d394d9
static pool_t string_pool; /* Symbol names. */
Packit d394d9
Packit d394d9
/* Functions. ===============================================================*/
Packit d394d9
Packit d394d9
static int_t 
Packit d394d9
compare_by_atoms( avl_node_t *node1, avl_node_t *node2 )
Packit d394d9
/* Callback function for AVL tree functions. */
Packit d394d9
{
Packit d394d9
  return compare_atom_lists( ((atoms_node_t *) node1)->atoms,
Packit d394d9
                             ((atoms_node_t *) node2)->atoms );
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
static symbol_node_t *
Packit d394d9
find_symbol_node( string_t name )
Packit d394d9
/* Find and return a symbol node with given name. 
Packit d394d9
 * If no symbol node exists, return NULL. */
Packit d394d9
{
Packit d394d9
  avln_node_t *node;
Packit d394d9
  int_t result;
Packit d394d9
Packit d394d9
  /* Look for existing node. */
Packit d394d9
  node = symbol_tree;
Packit d394d9
  while (node != NULL) 
Packit d394d9
  { 
Packit d394d9
    result = strcmp_no_case( name, node->name );
Packit d394d9
    if (result < 0) 
Packit d394d9
      node = node->left;
Packit d394d9
    else if (result > 0) 
Packit d394d9
      node = node->right;
Packit d394d9
    else 
Packit d394d9
      return (symbol_node_t *) node;
Packit d394d9
  }
Packit d394d9
  return NULL;
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
static symbol_t 
Packit d394d9
find_atomic_symbol( string_t name )
Packit d394d9
/* Find symbol NAME and check if it is atomic. Return the symbol. */
Packit d394d9
{
Packit d394d9
  symbol_node_t *node;
Packit d394d9
Packit d394d9
  node = find_symbol_node( name );
Packit d394d9
  if (node == NULL) 
Packit d394d9
    complain( "Symbol \"%s\" is not defined.", name );
Packit d394d9
  else if (get_list_length( node->atoms ) > 1) 
Packit d394d9
    complain( "Symbol \"%s\" is not atomic.", name );
Packit d394d9
  return node->symbol;
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
static void 
Packit d394d9
enter_symbol( string_t name, value_t atoms )
Packit d394d9
/* Enter NAME as a symbol name with atomic symbol list ATOMS
Packit d394d9
 * in the symbol tree. */
Packit d394d9
{
Packit d394d9
  symbol_node_t *node;
Packit d394d9
  atoms_node_t *atoms_node;
Packit d394d9
  symbol_entry_t symbol_entry;
Packit d394d9
  int_t result;
Packit d394d9
Packit d394d9
  node = find_symbol_node( name );
Packit d394d9
  if (atoms == NULL) 
Packit d394d9
  { 
Packit d394d9
    /* Make atom list for atomic symbol. */
Packit d394d9
    top = 0;
Packit d394d9
    if (node != NULL) 
Packit d394d9
      push_symbol_value( node->symbol );
Packit d394d9
    else 
Packit d394d9
      push_symbol_value( pool_item_count( symbol_pool ) );
Packit d394d9
    build_list(1);
Packit d394d9
    atoms = value_stack[0];
Packit d394d9
  }
Packit d394d9
  if (node != NULL) 
Packit d394d9
  { 
Packit d394d9
    /* Compare with previous definition. */
Packit d394d9
    if (compare_atom_lists( atoms, node->atoms ) != 0) 
Packit d394d9
    { 
Packit d394d9
      complain( "Atom list for \"%s\" differs in previous definition.", 
Packit d394d9
		node->node.name );
Packit d394d9
    }
Packit d394d9
  }
Packit d394d9
  else 
Packit d394d9
  { 
Packit d394d9
    /* Create new symbol node. */
Packit d394d9
    node = new_mem( sizeof( symbol_node_t ) );
Packit d394d9
    node->node.name = copy_string_to_pool( string_pool, name, 
Packit d394d9
					   &symbol_entry.name );
Packit d394d9
    node->symbol = pool_item_count( symbol_pool );
Packit d394d9
    if (node->symbol >= SYMBOL_MAX) 
Packit d394d9
      complain( "Too many symbols." );
Packit d394d9
    node->atoms = copy_value_to_pool( value_pool, atoms, &symbol_entry.atoms );
Packit d394d9
    insert_avln_node( (avln_node_t *) node, &symbol_tree );
Packit d394d9
    copy_to_pool( symbol_pool, &symbol_entry, 1, NULL );
Packit d394d9
    if (get_list_length( atoms ) > 1) 
Packit d394d9
    { 
Packit d394d9
      /* Check that there is no identical atom list. */
Packit d394d9
      atoms_node = (atoms_node_t *) atoms_tree;
Packit d394d9
      while (atoms_node != NULL) 
Packit d394d9
      { 
Packit d394d9
	result = compare_atom_lists( atoms, atoms_node->atoms );
Packit d394d9
        if (result < 0) 
Packit d394d9
	  atoms_node = (atoms_node_t *) atoms_node->node.left;
Packit d394d9
        else if (result > 0) 
Packit d394d9
	  atoms_node = (atoms_node_t *) atoms_node->node.right;
Packit d394d9
	else 
Packit d394d9
	{
Packit d394d9
	  complain( "Atom list is the same as for \"%s\".", 
Packit d394d9
		    atoms_node->name );
Packit d394d9
	}
Packit d394d9
      }
Packit d394d9
Packit d394d9
      /* Create new atoms node. */
Packit d394d9
      atoms_node = new_mem( sizeof( atoms_node_t ) );
Packit d394d9
      atoms_node->atoms = node->atoms;
Packit d394d9
      atoms_node->name = node->node.name;
Packit d394d9
      atoms_node->symbol = node->symbol;
Packit d394d9
      insert_avl_node( (avl_node_t *) atoms_node, &atoms_tree, 
Packit d394d9
		       compare_by_atoms );
Packit d394d9
    }
Packit d394d9
  }
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
static void 
Packit d394d9
parse_atom_list( value_t *atom_list_p )
Packit d394d9
/* Stack effects: (nothing) -> LIST.
Packit d394d9
 * Parse a list of symbols. Return it as *ATOM_LIST_P. */
Packit d394d9
{
Packit d394d9
  int_t i;
Packit d394d9
Packit d394d9
  top = 0;
Packit d394d9
  test_token( '<' );
Packit d394d9
  do 
Packit d394d9
  { 
Packit d394d9
    read_next_token();
Packit d394d9
    test_token( TOK_IDENT );
Packit d394d9
    push_symbol_value( find_atomic_symbol( token_name ) );
Packit d394d9
    
Packit d394d9
    /* Test if SYMBOL already occurs in symbol list. */
Packit d394d9
    for (i = 0; i < top-1; i++) 
Packit d394d9
    { 
Packit d394d9
      if (values_equal( value_stack[ top - 1 ], value_stack[i] )) 
Packit d394d9
	complain( "Symbol \"%s\" twice in atom list.", token_name );
Packit d394d9
    }
Packit d394d9
    /* Read after TOKEN_NAME. */
Packit d394d9
    read_next_token();
Packit d394d9
  } while (next_token == ',');
Packit d394d9
  
Packit d394d9
  parse_token( '>' );
Packit d394d9
  if (top < 2) 
Packit d394d9
    complain( "Atom list must contain at least two atoms." );
Packit d394d9
  build_list( top );
Packit d394d9
  *atom_list_p = value_stack[0];
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
static void 
Packit d394d9
parse_symbols( void )
Packit d394d9
/* Parse a symbol file. */
Packit d394d9
{
Packit d394d9
  string_t file_name, symbol_name;
Packit d394d9
  value_t atom_list;
Packit d394d9
          
Packit d394d9
  while (next_token != EOF) 
Packit d394d9
  { 
Packit d394d9
    if (next_token == TOK_INCLUDE) 
Packit d394d9
    { 
Packit d394d9
      /* Include a new file. */
Packit d394d9
      read_next_token();
Packit d394d9
      test_token( TOK_STRING );
Packit d394d9
      file_name = absolute_path( token_string, current_file_name() );
Packit d394d9
      read_next_token();
Packit d394d9
      begin_include( file_name );
Packit d394d9
      parse_symbols();
Packit d394d9
      end_include();
Packit d394d9
      free_mem( &file_name );
Packit d394d9
      parse_token( ';' );
Packit d394d9
    } 
Packit d394d9
    else 
Packit d394d9
    { 
Packit d394d9
      /* Read a symbol. */
Packit d394d9
      test_token( TOK_IDENT );
Packit d394d9
      symbol_name = new_string( token_name, NULL );
Packit d394d9
      read_next_token();
Packit d394d9
      if (next_token == TOK_ASSIGN) 
Packit d394d9
      { 
Packit d394d9
	read_next_token();
Packit d394d9
        parse_atom_list( &atom_list );
Packit d394d9
      } 
Packit d394d9
      else 
Packit d394d9
	atom_list = NULL;
Packit d394d9
      enter_symbol( symbol_name, atom_list );
Packit d394d9
      free_mem( &symbol_name );
Packit d394d9
      parse_token( ';' );
Packit d394d9
    } 
Packit d394d9
  }
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
static void 
Packit d394d9
write_symbols( string_t file_name )
Packit d394d9
/* Write symbol table to file FILE_NAME. */
Packit d394d9
{ 
Packit d394d9
  FILE *stream;
Packit d394d9
  symbol_header_t symbol_header;
Packit d394d9
Packit d394d9
  stream = open_stream( file_name, "wb" );
Packit d394d9
Packit d394d9
  /* Set rule file header data. */
Packit d394d9
  set_header( &symbol_header.common_header, SYMBOL_FILE, SYMBOL_CODE_VERSION );
Packit d394d9
  symbol_header.symbol_count = pool_item_count( symbol_pool );
Packit d394d9
  symbol_header.values_size = pool_item_count( value_pool );
Packit d394d9
  symbol_header.strings_size = pool_item_count( string_pool );
Packit d394d9
Packit d394d9
  /* Write header. */
Packit d394d9
  write_vector( &symbol_header, sizeof( symbol_header ), 1, stream, 
Packit d394d9
		file_name ); 
Packit d394d9
Packit d394d9
  /* Write tables to stream. */
Packit d394d9
  write_pool( symbol_pool, stream, file_name );
Packit d394d9
  write_pool( value_pool, stream, file_name );
Packit d394d9
  write_pool( string_pool, stream, file_name );
Packit d394d9
Packit d394d9
  close_stream( &stream, file_name );
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
static void 
Packit d394d9
init_sym_compiler( void )
Packit d394d9
/* Initialise this module. */
Packit d394d9
{
Packit d394d9
  symbol_pool = new_pool( sizeof( symbol_entry_t ) );
Packit d394d9
  value_pool = new_pool( sizeof( symbol_t ) );
Packit d394d9
  string_pool = new_pool( sizeof( char_t ) );
Packit d394d9
}
Packit d394d9
  
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
static void free_tree( avl_node_t *node )
Packit d394d9
{
Packit d394d9
  if (node == NULL) 
Packit d394d9
    return;
Packit d394d9
  free_tree( node->left );
Packit d394d9
  free_tree( node->right );
Packit d394d9
  free_mem( &node );
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
static void 
Packit d394d9
terminate_sym_compiler( void )
Packit d394d9
/* Terminate this module. */
Packit d394d9
{
Packit d394d9
  free_tree( (avl_node_t *) symbol_tree );
Packit d394d9
  symbol_tree = NULL;
Packit d394d9
  free_tree( (avl_node_t *) atoms_tree );
Packit d394d9
  atoms_tree = NULL;
Packit d394d9
  free_pool( &symbol_pool );
Packit d394d9
  free_pool( &value_pool );
Packit d394d9
  free_pool( &string_pool );
Packit d394d9
}
Packit d394d9
  
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
void 
Packit d394d9
compile_symbol_file( string_t source_file, string_t object_file,
Packit d394d9
                     string_t old_symbol_file )
Packit d394d9
/* Read symbol file SOURCE_FILE and create translated file OBJECT_FILE.
Packit d394d9
 * If OLD_SYMBOL_FILE != NULL, all symbols from this file are included in
Packit d394d9
 * the new file. */
Packit d394d9
{
Packit d394d9
  value_t atoms;
Packit d394d9
  symbol_t symbol;
Packit d394d9
    
Packit d394d9
  init_sym_compiler();
Packit d394d9
  if (old_symbol_file != NULL) 
Packit d394d9
  { 
Packit d394d9
    /* Enter the symbols from OLD_SYMBOL_FILE. */
Packit d394d9
    init_symbols( old_symbol_file );
Packit d394d9
    init_hangul();
Packit d394d9
    for (symbol = 0; symbol < symbol_count(); symbol++) 
Packit d394d9
    { 
Packit d394d9
      atoms = get_atoms( symbol );
Packit d394d9
      if (get_list_length( atoms ) <= 1) 
Packit d394d9
	atoms = NULL;
Packit d394d9
      enter_symbol( get_symbol_name( symbol ), atoms );
Packit d394d9
    }
Packit d394d9
    terminate_symbols();
Packit d394d9
    set_esym_stamp();
Packit d394d9
  } 
Packit d394d9
  else 
Packit d394d9
  { 
Packit d394d9
    /* Enter the standard symbols in the same order as in "values.h". */
Packit d394d9
    enter_symbol( "nil", NULL );
Packit d394d9
    enter_symbol( "yes", NULL );
Packit d394d9
    enter_symbol( "no", NULL );
Packit d394d9
    enter_symbol( "symbol", NULL );
Packit d394d9
    enter_symbol( "string", NULL );
Packit d394d9
    enter_symbol( "number", NULL );
Packit d394d9
    enter_symbol( "list", NULL );
Packit d394d9
    enter_symbol( "record", NULL );
Packit d394d9
    set_sym_stamp();
Packit d394d9
  }
Packit d394d9
  begin_include( source_file ); 
Packit d394d9
  TRY 
Packit d394d9
  { 
Packit d394d9
    parse_symbols();
Packit d394d9
    if (next_token != EOF) 
Packit d394d9
      complain( "Symbol definition expected." );
Packit d394d9
  } 
Packit d394d9
  IF_ERROR 
Packit d394d9
  { 
Packit d394d9
    print_text( error_text, " (\"%s\", line %d, column %d)", 
Packit d394d9
		name_in_path( current_file_name() ), 
Packit d394d9
		current_line_number(), current_column() );
Packit d394d9
    if (in_emacs_malaga_mode) 
Packit d394d9
    { 
Packit d394d9
      printf( "SHOW \"%s\":%d:%d\n", current_file_name(), 
Packit d394d9
	      current_line_number(), current_column() );
Packit d394d9
    }
Packit d394d9
  } 
Packit d394d9
  FINALLY 
Packit d394d9
    end_includes();
Packit d394d9
  END_TRY;
Packit d394d9
  write_symbols( object_file );
Packit d394d9
  terminate_sym_compiler();
Packit d394d9
  terminate_hangul();
Packit d394d9
}
Packit d394d9
Packit d394d9
/* End of file. =============================================================*/