/* libsizzle/symbol.c - symbol functions
 
  Copyright (C) 1999, 2000 Martin Grabmueller <mgrabmue@cs.tu-berlin.de>
 
  This is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2, or (at your option)
  any later version.
  
  This software is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
  
  You should have received a copy of the GNU General Public License
  along with this package; see the file COPYING.  If not, write to
  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  Boston, MA 02111-1307, USA.  */

#if HAVE_CONFIG_H
# include <config.h>
#endif 

#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#if ENABLE_NLS
# include <libintl.h>
# define _(String) gettext(String)
#else
# define _(String) (String)
#endif

#include "alloc.h"
#include "node.h"
#include "validate.h"
#include "capi.h"
#include "symbol.h"

static int gen_sym_index;

/*:doc
  symbol?
  (symbol? obj) => boolean
  Returns @code{#t} if @var{obj} is a symbol, @code{#f} otherwise.
  doc:*/
#define FUNC_NAME "symbol?"
static result_t
symbol_p_func (zzz_scm_t env, zzz_scm_t obj, zzz_scm_t * result)
{
  if (symbol_p (obj))
    *result = zzz_true_value;
  else
    *result = zzz_false_value;
  return RESULT_SUCCESS;
}
#undef FUNC_NAME

/*:doc
  symbol->string
  (symbol->string symbol) => string
  Converts @var{symbol} to a string.
  doc:*/
#define FUNC_NAME "symbol->string"
static result_t
symbol_to_string_func (zzz_scm_t env, zzz_scm_t symbol, zzz_scm_t * result)
{
  static char * s_func_name = FUNC_NAME;

  CHECK_TYPE (1, symbol_p (symbol), zzz_symbol_type_name);
  *result = symbol_name (symbol);
  return RESULT_SUCCESS;
}
#undef FUNC_NAME

/*:doc
  string->symbol
  (string->symbol string) => symbol
  Converts @var{string} to a symbol.
  doc:*/
#define FUNC_NAME "string->symbol"
static result_t
string_to_symbol_func (zzz_scm_t env, zzz_scm_t string, zzz_scm_t * result)
{
  static char * s_func_name = FUNC_NAME;

  CHECK_TYPE (1, string_p (string), zzz_string_type_name);
  *result = zzz_make_symbol (string_val (string), string_len (string));
  return RESULT_SUCCESS;
}
#undef FUNC_NAME

/*:doc
  gensym
  (gensym [prefix]) => symbol
  Generate a new symbol, constructed from @var{prefix} and the value of a
  counter which is incremented after each call.  @var{prefix} defaults to
  @code{)gen}, if not given.
  doc:*/
#define FUNC_NAME "gensym"
static result_t
gensym_func (zzz_scm_t env, zzz_scm_t prefix, zzz_scm_t * result)
{
  static char * s_func_name = FUNC_NAME;
  char * pfx;
  char buf[128];

  if (prefix != zzz_undefined)
    {
      CHECK_TYPE (1, string_p (prefix), zzz_string_type_name);
      pfx = string_val (prefix);
    }
  else
    pfx = "%%%gen";
  strncpy (buf, pfx, sizeof (buf) - 32);
  buf[sizeof (buf) - 1] = '\0';
  pfx = buf;
  while (*pfx)
    pfx++;
  sprintf (pfx, "%d", gen_sym_index);
  gen_sym_index++;
  *result = zzz_make_symbol (buf, strlen (buf));
  return RESULT_SUCCESS;
}
#undef FUNC_NAME

result_t
zzz_init_symbol (void)
{
  gen_sym_index = 0;
  zzz_define_function ("symbol?", (zzz_prim_t) symbol_p_func, argv_1_0_0);
  zzz_define_function ("symbol->string", (zzz_prim_t) symbol_to_string_func,
		       argv_1_0_0);
  zzz_define_function ("string->symbol", (zzz_prim_t) string_to_symbol_func,
		       argv_1_0_0);
  zzz_define_function ("gensym", (zzz_prim_t) gensym_func, argv_0_1_0);

  return RESULT_SUCCESS;
}
