Blame src/symbol.c

Packit Service a721b1
/* symbol.c -- symbol module.
Packit Service a721b1
   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
Packit Service a721b1
     National Institute of Advanced Industrial Science and Technology (AIST)
Packit Service a721b1
     Registration Number H15PRO112
Packit Service a721b1
Packit Service a721b1
   This file is part of the m17n library.
Packit Service a721b1
Packit Service a721b1
   The m17n library is free software; you can redistribute it and/or
Packit Service a721b1
   modify it under the terms of the GNU Lesser General Public License
Packit Service a721b1
   as published by the Free Software Foundation; either version 2.1 of
Packit Service a721b1
   the License, or (at your option) any later version.
Packit Service a721b1
Packit Service a721b1
   The m17n library is distributed in the hope that it will be useful,
Packit Service a721b1
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service a721b1
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service a721b1
   Lesser General Public License for more details.
Packit Service a721b1
Packit Service a721b1
   You should have received a copy of the GNU Lesser General Public
Packit Service a721b1
   License along with the m17n library; if not, write to the Free
Packit Service a721b1
   Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Packit Service a721b1
   Boston, MA 02110-1301 USA.  */
Packit Service a721b1
Packit Service a721b1
/***en
Packit Service a721b1
    @addtogroup m17nSymbol
Packit Service a721b1
Packit Service a721b1
    @brief Symbol objects and API for them.
Packit Service a721b1
Packit Service a721b1
    The m17n library uses objects called @e symbols as unambiguous
Packit Service a721b1
    identifiers.  Symbols are similar to atoms in the X library, but a
Packit Service a721b1
    symbol can have zero or more @e symbol @e properties.  A symbol
Packit Service a721b1
    property consists of a @e key and a @e value, where key is also a
Packit Service a721b1
    symbol and value is anything that can be cast to <tt>(void *)</tt>.  
Packit Service a721b1
    "The symbol property that belongs to the symbol S and
Packit Service a721b1
    whose key is K" may be shortened to "K property of S".
Packit Service a721b1
Packit Service a721b1
    Symbols are used mainly in the following three ways.
Packit Service a721b1
Packit Service a721b1
    @li As keys of symbol properties and other properties.
Packit Service a721b1
Packit Service a721b1
    @li To represent various objects, e.g. charsets, coding systems,
Packit Service a721b1
    fontsets.
Packit Service a721b1
Packit Service a721b1
    @li As arguments of the m17n library functions to control
Packit Service a721b1
    their behavior.
Packit Service a721b1
Packit Service a721b1
    There is a special kind of symbol, a @e managing @e key.  The
Packit Service a721b1
    value of a property whose key is a managing key must be a @e
Packit Service a721b1
    managed @e object.  See @ref m17nObject for the detail.
Packit Service a721b1
*/
Packit Service a721b1
/***ja
Packit Service a721b1
    @addtogroup m17nSymbol シンボル
Packit Service a721b1
Packit Service a721b1
    @brief シンボルオブジェクトとそれに関する API.
Packit Service a721b1
Packit Service a721b1
    m17n ライブラリは一意に決まる識別子として @e シンボル 
Packit Service a721b1
    と呼ぶオブジェクトを用いる。シンボルは X ライブラリのアトムと似ているが、
Packit Service a721b1
    0 個以上の @e シンボルプロパティ を持つことができる。シンボルプロパティは
Packit Service a721b1
    @e キー と @e 値 からなる。キーはそれ自体シンボルであり、値は 
Packit Service a721b1
    <tt>(void *)</tt> 型にキャストできるものなら何でもよい。「シンボル 
Packit Service a721b1
    S が持つシンボルプロパティのうちキーが K のもの」を簡単に「S の K 
Packit Service a721b1
    プロパティ」と呼ぶことがある。
Packit Service a721b1
Packit Service a721b1
    シンボルの用途は主に以下の3通りである。
Packit Service a721b1
Packit Service a721b1
    @li シンボルプロパティおよび他のプロパティのキーを表す。
Packit Service a721b1
Packit Service a721b1
    @li 文字セット、コード系、フォントセットなどの各種オブジェクトを表す。
Packit Service a721b1
Packit Service a721b1
    @li m17n ライブラリ関数の引数となり、関数の挙動を制御する。
Packit Service a721b1
Packit Service a721b1
    @e 管理キー と呼ばれる特別なシンボルがあり、管理キーをキーとして持つプロパティの値は
Packit Service a721b1
    @e 管理下オブジェクト でなくてはならない。詳細は @ref m17nObject 参照。
Packit Service a721b1
*/
Packit Service a721b1
Packit Service a721b1
/*=*/
Packit Service a721b1
Packit Service a721b1
#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
Packit Service a721b1
/*** @addtogroup m17nInternal
Packit Service a721b1
     @{ */
Packit Service a721b1
Packit Service a721b1
#include <config.h>
Packit Service a721b1
#include <stdlib.h>
Packit Service a721b1
#include <string.h>
Packit Service a721b1
#include <ctype.h>
Packit Service a721b1
Packit Service a721b1
#include "m17n.h"
Packit Service a721b1
#include "m17n-misc.h"
Packit Service a721b1
#include "internal.h"
Packit Service a721b1
#include "symbol.h"
Packit Service a721b1
#include "character.h"
Packit Service a721b1
#include "mtext.h"
Packit Service a721b1
#include "plist.h"
Packit Service a721b1
Packit Service a721b1
static int num_symbols;
Packit Service a721b1
Packit Service a721b1
#define SYMBOL_TABLE_SIZE 1024
Packit Service a721b1
Packit Service a721b1
static MSymbol symbol_table[SYMBOL_TABLE_SIZE];
Packit Service a721b1
Packit Service a721b1
static unsigned
Packit Service a721b1
hash_string (const char *str, int len)
Packit Service a721b1
{
Packit Service a721b1
  unsigned hash = 0;
Packit Service a721b1
  const char *end = str + len;
Packit Service a721b1
  unsigned c;
Packit Service a721b1
Packit Service a721b1
  while (str < end)
Packit Service a721b1
    {
Packit Service a721b1
      c = *((unsigned char *) str++);
Packit Service a721b1
      if (c >= 0140)
Packit Service a721b1
	c -= 40;
Packit Service a721b1
      hash = ((hash << 3) + (hash >> 28) + c);
Packit Service a721b1
    }
Packit Service a721b1
  return hash & (SYMBOL_TABLE_SIZE - 1);
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
Packit Service a721b1
static MPlist *
Packit Service a721b1
serialize_symbol (void *val)
Packit Service a721b1
{
Packit Service a721b1
  MPlist *plist = mplist ();
Packit Service a721b1
Packit Service a721b1
  mplist_add (plist, Msymbol, val);
Packit Service a721b1
  return plist;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
static void *
Packit Service a721b1
deserialize_symbol (MPlist *plist)
Packit Service a721b1
{
Packit Service a721b1
  return (MPLIST_SYMBOL_P (plist) ? MPLIST_SYMBOL (plist) : Mnil);
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1

Packit Service a721b1
/* Internal API */
Packit Service a721b1
Packit Service a721b1
int
Packit Service a721b1
msymbol__init ()
Packit Service a721b1
{
Packit Service a721b1
  num_symbols = 0;
Packit Service a721b1
  Mnil = (MSymbol) 0;
Packit Service a721b1
  Mt = msymbol ("t");
Packit Service a721b1
  Msymbol = msymbol ("symbol");
Packit Service a721b1
  Mstring = msymbol ("string");
Packit Service a721b1
  return 0;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
void
Packit Service a721b1
msymbol__fini ()
Packit Service a721b1
{
Packit Service a721b1
  int i;
Packit Service a721b1
  MSymbol sym;
Packit Service a721b1
Packit Service a721b1
  for (i = 0; i < SYMBOL_TABLE_SIZE; i++)
Packit Service a721b1
    for (sym = symbol_table[i]; sym; sym = sym->next)
Packit Service a721b1
      if (! MPLIST_TAIL_P (&sym->plist))
Packit Service a721b1
	{
Packit Service a721b1
	  if (sym->plist.key->managing_key)
Packit Service a721b1
	    M17N_OBJECT_UNREF (MPLIST_VAL (&sym->plist));
Packit Service a721b1
	  M17N_OBJECT_UNREF (sym->plist.next);
Packit Service a721b1
	  sym->plist.key = Mnil;
Packit Service a721b1
	}
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
void
Packit Service a721b1
msymbol__free_table ()
Packit Service a721b1
{
Packit Service a721b1
  int i;
Packit Service a721b1
  MSymbol sym, next;
Packit Service a721b1
  int freed_symbols = 0;
Packit Service a721b1
Packit Service a721b1
  for (i = 0; i < SYMBOL_TABLE_SIZE; i++)
Packit Service a721b1
    {
Packit Service a721b1
      for (sym = symbol_table[i]; sym; sym = next)
Packit Service a721b1
	{
Packit Service a721b1
	  next = sym->next;
Packit Service a721b1
	  free (sym->name);
Packit Service a721b1
	  free (sym);
Packit Service a721b1
	  freed_symbols++;
Packit Service a721b1
	}
Packit Service a721b1
      symbol_table[i] = NULL;
Packit Service a721b1
    }
Packit Service a721b1
  if (mdebug__flags[MDEBUG_FINI])
Packit Service a721b1
    fprintf (mdebug__output, "%16s %7d %7d %7d\n", "Symbol",
Packit Service a721b1
	     num_symbols, freed_symbols, num_symbols - freed_symbols);
Packit Service a721b1
  num_symbols = 0;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
Packit Service a721b1
MSymbol
Packit Service a721b1
msymbol__with_len (const char *name, int len)
Packit Service a721b1
{
Packit Service a721b1
  char *p = alloca (len + 1);
Packit Service a721b1
Packit Service a721b1
  memcpy (p, name, len);
Packit Service a721b1
  p[len] = '\0';
Packit Service a721b1
  return msymbol (p);
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
/** Return a plist of symbols that has non-NULL property PROP.  If
Packit Service a721b1
    PROP is Mnil, return a plist of all symbols.  Values of the plist
Packit Service a721b1
    is NULL.  */
Packit Service a721b1
Packit Service a721b1
MPlist *
Packit Service a721b1
msymbol__list (MSymbol prop)
Packit Service a721b1
{
Packit Service a721b1
  MPlist *plist = mplist ();
Packit Service a721b1
  int i;
Packit Service a721b1
  MSymbol sym;
Packit Service a721b1
Packit Service a721b1
  for (i = 0; i < SYMBOL_TABLE_SIZE; i++)
Packit Service a721b1
    for (sym = symbol_table[i]; sym; sym = sym->next)
Packit Service a721b1
      if (prop == Mnil || msymbol_get (sym, prop))
Packit Service a721b1
	mplist_push (plist, sym, NULL);
Packit Service a721b1
  return plist;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
Packit Service a721b1
/** Canonicalize the name of SYM, and return a symbol of the
Packit Service a721b1
    canonicalized name.  Canonicalization is done by this rule:
Packit Service a721b1
	o convert all uppercase characters to lowercase.
Packit Service a721b1
	o remove all non alpha-numeric characters.
Packit Service a721b1
	o change the leading "ibm" to "cp".
Packit Service a721b1
	o change the leading "windows-" to "cp".
Packit Service a721b1
	o change the leading "cp" to "ibm".
Packit Service a721b1
	o remove the leading "iso".
Packit Service a721b1
    For instance:
Packit Service a721b1
	"ISO-8859-2" -> "88592"
Packit Service a721b1
	"euc-JP" -> "eucjp"
Packit Service a721b1
	"IBM851" -> "cp851"
Packit Service a721b1
	"windows-1250" -> "cp250"
Packit Service a721b1
Packit Service a721b1
    This function is used to canonicalize charset and coding system
Packit Service a721b1
    names.  */
Packit Service a721b1
Packit Service a721b1
MSymbol
Packit Service a721b1
msymbol__canonicalize (MSymbol sym)
Packit Service a721b1
{
Packit Service a721b1
  char *name = sym->name;
Packit Service a721b1
  /* Extra 2 bytes are for changing "cpXXX" to "ibmXXX" and
Packit Service a721b1
     terminating '\0'.  */
Packit Service a721b1
  char *canon = (char *) alloca (strlen (name) + 2);
Packit Service a721b1
  char *p = canon;
Packit Service a721b1
Packit Service a721b1
  for (; *name; name++)
Packit Service a721b1
    if (ISALNUM (*name))
Packit Service a721b1
      *p++ = TOLOWER (*name);
Packit Service a721b1
  *p = '\0';
Packit Service a721b1
  if (p - canon > 3 && canon[0] == 'i')
Packit Service a721b1
    {
Packit Service a721b1
      if (canon[1] == 'b' && canon[2] == 'm' && isdigit (canon[3]))
Packit Service a721b1
	{
Packit Service a721b1
	  /* Change "ibmXXX" to "cpXXX".  */
Packit Service a721b1
	  canon++;
Packit Service a721b1
	  canon[0] = 'c';
Packit Service a721b1
	  canon[1] = 'p';
Packit Service a721b1
	}
Packit Service a721b1
      else if (canon[1] == 's' && canon[2] == 'o')
Packit Service a721b1
	{
Packit Service a721b1
	  /* Change "isoXXX" to "XXX".  */
Packit Service a721b1
	  canon += 3;
Packit Service a721b1
	}
Packit Service a721b1
    }
Packit Service a721b1
  else if (p - canon > 2
Packit Service a721b1
	   && canon[0] == 'c' && canon[1] == 'p' && isdigit (canon[2]))
Packit Service a721b1
    {
Packit Service a721b1
      /* Change "cpXXX" to "ibmXXX".  */
Packit Service a721b1
      for (; p >= canon + 2; p--)
Packit Service a721b1
	p[1] = p[0];
Packit Service a721b1
      canon[0] = 'i';
Packit Service a721b1
      canon[1] = 'b';
Packit Service a721b1
      canon[2] = 'm';
Packit Service a721b1
    }
Packit Service a721b1
  else if (canon[0] == 'w' && p - canon > 7
Packit Service a721b1
	   && memcmp (canon + 1, "indows", 6) == 0
Packit Service a721b1
	   && isdigit (canon[7]))
Packit Service a721b1
    {
Packit Service a721b1
      /* Change "windowsXXX" to "cpXXX" */
Packit Service a721b1
      canon += 5;
Packit Service a721b1
      canon[0] = 'c';
Packit Service a721b1
      canon[1] = 'p';
Packit Service a721b1
    }
Packit Service a721b1
  return msymbol (canon);
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
MTextPropSerializeFunc msymbol__serializer = serialize_symbol;
Packit Service a721b1
MTextPropDeserializeFunc msymbol__deserializer = deserialize_symbol;
Packit Service a721b1
Packit Service a721b1
/*** @} */
Packit Service a721b1
#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
Packit Service a721b1
Packit Service a721b1

Packit Service a721b1
/* External API */
Packit Service a721b1
Packit Service a721b1
/*** @addtogroup m17nSymbol */
Packit Service a721b1
/*** @{ */
Packit Service a721b1
Packit Service a721b1
/*=*/
Packit Service a721b1
/***en
Packit Service a721b1
    @brief Symbol whose name is "nil".
Packit Service a721b1
Packit Service a721b1
    The symbol #Mnil has the name <tt>"nil"</tt> and, in general,
Packit Service a721b1
    represents @e false or @e no.  When coerced to "int", its value is
Packit Service a721b1
    zero.  #Mnil can't have any symbol property.  */
Packit Service a721b1
/***ja
Packit Service a721b1
    @brief "nil" を名前として持つシンボル.
Packit Service a721b1
Packit Service a721b1
    シンボル #Mnil は <tt>"nil"</tt> 
Packit Service a721b1
    という名前を持ち、一般に「偽」または「否定」を意味する。
Packit Service a721b1
    "int" に変換された場合、値は 0 である。
Packit Service a721b1
    #Mnil 自身はいかなるシンボルプロパティも持たない。  */
Packit Service a721b1
Packit Service a721b1
MSymbol Mnil;
Packit Service a721b1
Packit Service a721b1
/*=*/
Packit Service a721b1
Packit Service a721b1
/***en
Packit Service a721b1
    @brief Symbol whose name is "t".
Packit Service a721b1
Packit Service a721b1
    The symbol #Mt has the name <tt>"t"</tt> and, in general,
Packit Service a721b1
    represents @e true or @e yes.  */
Packit Service a721b1
/***ja
Packit Service a721b1
    @brief "t" を名前として持つシンボル.
Packit Service a721b1
Packit Service a721b1
    シンボル #Mt は <tt>"t"</tt> という名前を持ち、一般に「真」または「肯定」を意味する。  */
Packit Service a721b1
Packit Service a721b1
MSymbol Mt;
Packit Service a721b1
Packit Service a721b1
/*=*/
Packit Service a721b1
Packit Service a721b1
/***en
Packit Service a721b1
    @brief Symbol whose name is "string".
Packit Service a721b1
Packit Service a721b1
    The symbol #Mstring has the name <tt>"string"</tt> and is used
Packit Service a721b1
    as an argument of the functions mchar_define_property (),
Packit Service a721b1
    etc.  */
Packit Service a721b1
/***ja
Packit Service a721b1
    @brief "string" を名前として持つシンボル.
Packit Service a721b1
Packit Service a721b1
    シンボル #Mstring は <tt>"string"</tt> という名前を持ち、関数 
Packit Service a721b1
    mchar_define_property () などの引数として用いられる。  */
Packit Service a721b1
Packit Service a721b1
MSymbol Mstring;
Packit Service a721b1
Packit Service a721b1
/*=*/
Packit Service a721b1
Packit Service a721b1
/***en
Packit Service a721b1
    @brief Symbol whose name is "symbol".
Packit Service a721b1
Packit Service a721b1
    The symbol #Msymbol has the name <tt>"symbol"</tt> and is used
Packit Service a721b1
    as an argument of the functions mchar_define_property (),
Packit Service a721b1
    etc.  */
Packit Service a721b1
/***ja
Packit Service a721b1
    @brief "symbol" を名前として持つシンボル.
Packit Service a721b1
Packit Service a721b1
    定義済みシンボル #Msymbol は <tt>"symbol"</tt> という名前を持ち、関数
Packit Service a721b1
    mchar_define_property () などの引数として使われる。  */
Packit Service a721b1
Packit Service a721b1
MSymbol Msymbol;
Packit Service a721b1
Packit Service a721b1
/*=*/
Packit Service a721b1
Packit Service a721b1
/***en
Packit Service a721b1
    @brief Get a symbol.
Packit Service a721b1
Packit Service a721b1
    The msymbol () function returns the canonical symbol whose name is
Packit Service a721b1
    $NAME.  If there is none, one is created.  The created one is not
Packit Service a721b1
    a managing key.
Packit Service a721b1
Packit Service a721b1
    Symbols whose name starts by two spaces are reserved by the m17n
Packit Service a721b1
    library, and are used by the library only internally.
Packit Service a721b1
Packit Service a721b1
    @return
Packit Service a721b1
    This function returns the found or created symbol.
Packit Service a721b1
Packit Service a721b1
    @errors
Packit Service a721b1
    This function never fails.  */
Packit Service a721b1
/***ja
Packit Service a721b1
    @brief シンボルを得る.
Packit Service a721b1
Packit Service a721b1
    関数 msymbol () は $NAME 
Packit Service a721b1
    という名前を持つ正規化されたシンボルを返す。そのようなシンボルが存在しない場合には、生成する。生成されたシンボルは管理キーではない。
Packit Service a721b1
Packit Service a721b1
    空白文字二つで始まるシンボルは m17n ライブラリ用であり、内部的にのみ用いられる。
Packit Service a721b1
Packit Service a721b1
    @return
Packit Service a721b1
    この関数は見つけたか生成したかしたシンボルを返す。
Packit Service a721b1
Packit Service a721b1
    @errors
Packit Service a721b1
    この関数は決して失敗しない。
Packit Service a721b1
Packit Service a721b1
    @latexonly \IPAlabel{msymbol} @endlatexonly  */
Packit Service a721b1
Packit Service a721b1
/***
Packit Service a721b1
    @seealso
Packit Service a721b1
    msymbol_as_managing_key (), msymbol_name (), msymbol_exist ()  */
Packit Service a721b1
Packit Service a721b1
MSymbol
Packit Service a721b1
msymbol (const char *name)
Packit Service a721b1
{
Packit Service a721b1
  MSymbol sym;
Packit Service a721b1
  int len;
Packit Service a721b1
  unsigned hash;
Packit Service a721b1
Packit Service a721b1
  len = strlen (name);
Packit Service a721b1
  if (len == 3 && name[0] == 'n' && name[1] == 'i' && name[2] == 'l')
Packit Service a721b1
    return Mnil;
Packit Service a721b1
  hash = hash_string (name, len);
Packit Service a721b1
  len++;
Packit Service a721b1
  for (sym = symbol_table[hash]; sym; sym = sym->next)
Packit Service a721b1
    if (len == sym->length
Packit Service a721b1
	&& *name == *(sym->name)
Packit Service a721b1
	&& ! memcmp (name, sym->name, len))
Packit Service a721b1
      return sym;
Packit Service a721b1
Packit Service a721b1
  num_symbols++;
Packit Service a721b1
  MTABLE_CALLOC (sym, 1, MERROR_SYMBOL);
Packit Service a721b1
  MTABLE_MALLOC (sym->name, len, MERROR_SYMBOL);
Packit Service a721b1
  memcpy (sym->name, name, len);
Packit Service a721b1
  sym->length = len;
Packit Service a721b1
  sym->next = symbol_table[hash];
Packit Service a721b1
  symbol_table[hash] = sym;
Packit Service a721b1
  return sym;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
/***en
Packit Service a721b1
    @brief Create a managing key.
Packit Service a721b1
Packit Service a721b1
    The msymbol_as_managing_key () function returns a newly created
Packit Service a721b1
    managing key whose name is $NAME.  It there already exists a
Packit Service a721b1
    symbol of name $NAME, it returns #Mnil.
Packit Service a721b1
Packit Service a721b1
    Symbols whose name starts by two spaces are reserved by the m17n
Packit Service a721b1
    library, and are used by the library only internally.
Packit Service a721b1
Packit Service a721b1
    @return
Packit Service a721b1
    If the operation was successful, this function returns the created
Packit Service a721b1
    symbol.  Otherwise, it returns #Mnil.  */
Packit Service a721b1
/***ja
Packit Service a721b1
    @brief 管理キーを作る.
Packit Service a721b1
Packit Service a721b1
    関数 msymbol_as_managing_key () は名前 $NAME 
Packit Service a721b1
    を持つ新しく作られた管理キーを返す。すでに名前 $NAME を持つシンボルがあれば、
Packit Service a721b1
    #Mnil を返す。
Packit Service a721b1
Packit Service a721b1
    空白文字二つで始まるシンボルは m17n ライブラリ用であり、内部的にのみ用いられる。
Packit Service a721b1
Packit Service a721b1
    @return
Packit Service a721b1
    処理に成功すれば、この関数は生成したシンボルを返す。そうでなければ
Packit Service a721b1
    #Mnil を返す。   */
Packit Service a721b1
Packit Service a721b1
/***
Packit Service a721b1
    @errors
Packit Service a721b1
    MERROR_SYMBOL
Packit Service a721b1
Packit Service a721b1
    @seealso
Packit Service a721b1
    msymbol (), msymbol_exist ()  */
Packit Service a721b1
Packit Service a721b1
MSymbol
Packit Service a721b1
msymbol_as_managing_key (const char *name)
Packit Service a721b1
{
Packit Service a721b1
  MSymbol sym;
Packit Service a721b1
  int len;
Packit Service a721b1
  unsigned hash;
Packit Service a721b1
Packit Service a721b1
  len = strlen (name);
Packit Service a721b1
  if (len == 3 && name[0] == 'n' && name[1] == 'i' && name[2] == 'l')
Packit Service a721b1
    MERROR (MERROR_SYMBOL, Mnil);
Packit Service a721b1
  hash = hash_string (name, len);
Packit Service a721b1
  len++;
Packit Service a721b1
  for (sym = symbol_table[hash]; sym; sym = sym->next)
Packit Service a721b1
    if (len == sym->length
Packit Service a721b1
	&& *name == *(sym->name)
Packit Service a721b1
	&& ! memcmp (name, sym->name, len))
Packit Service a721b1
      MERROR (MERROR_SYMBOL, Mnil);
Packit Service a721b1
Packit Service a721b1
  num_symbols++;
Packit Service a721b1
  MTABLE_CALLOC (sym, 1, MERROR_SYMBOL);
Packit Service a721b1
  sym->managing_key = 1;
Packit Service a721b1
  MTABLE_MALLOC (sym->name, len, MERROR_SYMBOL);
Packit Service a721b1
  memcpy (sym->name, name, len);
Packit Service a721b1
  sym->length = len;
Packit Service a721b1
  sym->next = symbol_table[hash];
Packit Service a721b1
  symbol_table[hash] = sym;
Packit Service a721b1
  return sym;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
/*=*/
Packit Service a721b1
Packit Service a721b1
/***en
Packit Service a721b1
    @brief Check if a symbol is a managing key.
Packit Service a721b1
Packit Service a721b1
    The msymbol_is_managing_key () function checks if the symbol
Packit Service a721b1
    $SYMBOL is a managing key or not.
Packit Service a721b1
Packit Service a721b1
    @return 
Packit Service a721b1
    Return 1 if the symbol is a managing key.  Otherwise,
Packit Service a721b1
    return 0.  */
Packit Service a721b1
Packit Service a721b1
int
Packit Service a721b1
msymbol_is_managing_key (MSymbol symbol)
Packit Service a721b1
{
Packit Service a721b1
  return (symbol->managing_key == 1);
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
/*=*/
Packit Service a721b1
Packit Service a721b1
/***en
Packit Service a721b1
    @brief Search for a symbol that has a specified name.
Packit Service a721b1
Packit Service a721b1
    The msymbol_exist () function searches for the symbol whose name
Packit Service a721b1
    is $NAME.
Packit Service a721b1
Packit Service a721b1
    @return
Packit Service a721b1
    If such a symbol exists, msymbol_exist () returns that symbol.
Packit Service a721b1
    Otherwise it returns the predefined symbol #Mnil.
Packit Service a721b1
Packit Service a721b1
    @errors
Packit Service a721b1
    This function never fails.  */
Packit Service a721b1
/***ja
Packit Service a721b1
    @brief 指定された名前を持つシンボルを探す.
Packit Service a721b1
Packit Service a721b1
    関数 msymbol_exist () は $NAME という名前を持つシンボルを探す。
Packit Service a721b1
Packit Service a721b1
    @return
Packit Service a721b1
    もしそのようなシンボルが存在するならばそのシンボルを返す。そうでなければ、定義済みシンボル
Packit Service a721b1
    #Mnil を返す。  
Packit Service a721b1
Packit Service a721b1
    @errors
Packit Service a721b1
    この関数は決して失敗しない。     */
Packit Service a721b1
Packit Service a721b1
/***@seealso
Packit Service a721b1
    msymbol_name (), msymbol ()  */
Packit Service a721b1
Packit Service a721b1
MSymbol
Packit Service a721b1
msymbol_exist (const char *name)
Packit Service a721b1
{
Packit Service a721b1
  MSymbol sym;
Packit Service a721b1
  int len;
Packit Service a721b1
  unsigned hash;
Packit Service a721b1
Packit Service a721b1
  len = strlen (name);
Packit Service a721b1
  if (len == 3 && name[0] == 'n' && name[1] == 'i' && name[2] == 'l')
Packit Service a721b1
    return Mnil;
Packit Service a721b1
  hash = hash_string (name, len);
Packit Service a721b1
  len++;
Packit Service a721b1
  for (sym = symbol_table[hash]; sym; sym = sym->next)
Packit Service a721b1
    if (len == sym->length
Packit Service a721b1
	&& *name == *(sym->name)
Packit Service a721b1
	&& ! memcmp (name, sym->name, len))
Packit Service a721b1
      return sym;
Packit Service a721b1
  return Mnil;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
/*=*/
Packit Service a721b1
Packit Service a721b1
/***en
Packit Service a721b1
    @brief Get symbol name.
Packit Service a721b1
Packit Service a721b1
    The msymbol_name () function returns a pointer to a string
Packit Service a721b1
    containing the name of $SYMBOL.
Packit Service a721b1
Packit Service a721b1
    @errors
Packit Service a721b1
    This function never fails.  */
Packit Service a721b1
/***ja
Packit Service a721b1
    @brief シンボルの名前を得る.
Packit Service a721b1
Packit Service a721b1
    関数 msymbol_name () は指定されたシンボル $SYMBOL 
Packit Service a721b1
    の名前を含む文字列へのポインタを返す。
Packit Service a721b1
Packit Service a721b1
    @errors
Packit Service a721b1
    この関数は決して失敗しない。     */
Packit Service a721b1
Packit Service a721b1
/***@seealso
Packit Service a721b1
    msymbol (), msymbol_exist ()  */
Packit Service a721b1
Packit Service a721b1
char *
Packit Service a721b1
msymbol_name (MSymbol symbol)
Packit Service a721b1
{
Packit Service a721b1
  return (symbol == Mnil ? "nil" : symbol->name);
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
/*=*/
Packit Service a721b1
/***en
Packit Service a721b1
    @brief Set the value of a symbol property.
Packit Service a721b1
Packit Service a721b1
    The msymbol_put () function assigns $VAL to the value of the
Packit Service a721b1
    symbol property that belongs to $SYMBOL and whose key is $KEY.  If
Packit Service a721b1
    the symbol property already has a value, $VAL overwrites the old
Packit Service a721b1
    one.  Both $SYMBOL and $KEY must not be #Mnil.
Packit Service a721b1
Packit Service a721b1
    If $KEY is a managing key, $VAL must be a managed object.  In this
Packit Service a721b1
    case, the reference count of the old value, if not @c NULL, is
Packit Service a721b1
    decremented by one, and that of $VAL is incremented by one.
Packit Service a721b1
Packit Service a721b1
    @return
Packit Service a721b1
    If the operation was successful, msymbol_put () returns 0.
Packit Service a721b1
    Otherwise it returns -1 and assigns an error code to the external
Packit Service a721b1
    variable #merror_code.  */
Packit Service a721b1
/***ja
Packit Service a721b1
    @brief シンボルプロパティに値を設定する.
Packit Service a721b1
Packit Service a721b1
    関数 msymbol_put () は、シンボル $SYMBOL 中でキーが $KEY であるシンボルプロパティの値を
Packit Service a721b1
    $VAL に設定する。そのシンボルプロパティにすでに値があれば上書きする。
Packit Service a721b1
    $SYMBOL, $KEY とも #Mnil であってはならない。
Packit Service a721b1
Packit Service a721b1
    $KEY が管理キーならば、$VAL は管理下オブジェクトでなくてはならない。この場合、古い値の参照数は
Packit Service a721b1
    @c NULL でなければ 1 減らされ、$VAL の参照数は 1 増やされる。
Packit Service a721b1
Packit Service a721b1
    @return
Packit Service a721b1
    処理が成功すれば、msymbol_put () は 0 を返す。そうでなければ -1 
Packit Service a721b1
    を返し、外部変数 #merror_code にエラーコードを設定する。  */
Packit Service a721b1
Packit Service a721b1
/***
Packit Service a721b1
    @errors
Packit Service a721b1
    @c MERROR_SYMBOL
Packit Service a721b1
Packit Service a721b1
    @seealso
Packit Service a721b1
    msymbol_get () */
Packit Service a721b1
Packit Service a721b1
int
Packit Service a721b1
msymbol_put (MSymbol symbol, MSymbol key, void *val)
Packit Service a721b1
{
Packit Service a721b1
  if (symbol == Mnil || key == Mnil)
Packit Service a721b1
    MERROR (MERROR_SYMBOL, -1);
Packit Service a721b1
  mplist_put (&symbol->plist, key, val);
Packit Service a721b1
  return 0;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
/*=*/
Packit Service a721b1
Packit Service a721b1
/***en
Packit Service a721b1
    @brief Get the value of a symbol property.
Packit Service a721b1
Packit Service a721b1
    The msymbol_get () function searches for the value of the symbol
Packit Service a721b1
    property that belongs to $SYMBOL and whose key is $KEY.  If
Packit Service a721b1
    $SYMBOL has such a symbol property, its value is returned.
Packit Service a721b1
    Otherwise @c NULL is returned.
Packit Service a721b1
Packit Service a721b1
    @return
Packit Service a721b1
    If an error is detected, msymbol_get () returns @c NULL and
Packit Service a721b1
    assigns an error code to the external variable #merror_code.  */
Packit Service a721b1
/***ja
Packit Service a721b1
    @brief シンボルプロパティの値を得る.
Packit Service a721b1
Packit Service a721b1
    関数 msymbol_get () は、シンボル $SYMBOL 
Packit Service a721b1
    が持つシンボルプロパティのうち、キーが $KEY 
Packit Service a721b1
    であるものを探す。もし該当するシンボルプロパティが存在すれば、それの値を返す。そうでなければ
Packit Service a721b1
    @c NULL を返す。
Packit Service a721b1
Packit Service a721b1
    @return 
Packit Service a721b1
    エラーが検出された場合、msymbol_get () は @c NULL 
Packit Service a721b1
    を返し、外部変数 #merror_code にエラーコードを設定する。  */
Packit Service a721b1
Packit Service a721b1
/***
Packit Service a721b1
    @errors
Packit Service a721b1
    @c MERROR_SYMBOL
Packit Service a721b1
Packit Service a721b1
    @seealso
Packit Service a721b1
    msymbol_put () */
Packit Service a721b1
Packit Service a721b1
void *
Packit Service a721b1
msymbol_get (MSymbol symbol, MSymbol key)
Packit Service a721b1
{
Packit Service a721b1
  MPlist *plist;
Packit Service a721b1
Packit Service a721b1
  if (symbol == Mnil || key == Mnil)
Packit Service a721b1
    return NULL;
Packit Service a721b1
  plist = &symbol->plist;
Packit Service a721b1
  MPLIST_FIND (plist, key);
Packit Service a721b1
  return (MPLIST_TAIL_P (plist) ? NULL : MPLIST_VAL (plist));
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
/*=*/
Packit Service a721b1
/***en
Packit Service a721b1
    @brief Set the value (function pointer) of a symbol property.
Packit Service a721b1
Packit Service a721b1
    The msymbol_put_func () function is similar to msymbol_put () but for
Packit Service a721b1
    setting function pointer $FUNC as the property value of $SYMBOL for
Packit Service a721b1
    key $KEY.  */
Packit Service a721b1
Packit Service a721b1
/***ja
Packit Service a721b1
    @brief シンボルプロパティの値(関数ポインタ)を設定する.
Packit Service a721b1
Packit Service a721b1
    関数 msymbol_put_func () は、関数 msymbol_put () と同様に、シンボル
Packit Service a721b1
    $SYMBOL のキーが $KEY であるシンボルプロパティの値を設定する。但し
Packit Service a721b1
    その値は関数ポインタ $FUNC である。 */
Packit Service a721b1
Packit Service a721b1
/***
Packit Service a721b1
    @seealso
Packit Service a721b1
     msymbol_put (), M17N_FUNC ()  */
Packit Service a721b1
int
Packit Service a721b1
msymbol_put_func (MSymbol symbol, MSymbol key, M17NFunc func)
Packit Service a721b1
{
Packit Service a721b1
  if (symbol == Mnil || key == Mnil)
Packit Service a721b1
    MERROR (MERROR_SYMBOL, -1);
Packit Service a721b1
  mplist_put_func (&symbol->plist, key, func);
Packit Service a721b1
  return 0;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
/*=*/
Packit Service a721b1
Packit Service a721b1
/***en
Packit Service a721b1
    @brief Get the value (function pointer) of a symbol property.
Packit Service a721b1
Packit Service a721b1
    The msymbol_get_func () function is similar to msymbol_get () but for
Packit Service a721b1
    getting a function pointer form the property of symbol $SYMBOL.  */
Packit Service a721b1
Packit Service a721b1
/***ja
Packit Service a721b1
    @brief シンボルプロパティの値 (関数ポインタ) を得る.
Packit Service a721b1
Packit Service a721b1
    関数 msymbol_get_func () は、関数 msymbol_get () と同様に、シンボル
Packit Service a721b1
    $SYMBOL が持つシンボルプロパティのうち、キーが $KEY であるものを得る。但し
Packit Service a721b1
    その値は関数ポインタをである。    */
Packit Service a721b1
Packit Service a721b1
/***
Packit Service a721b1
    @seealso
Packit Service a721b1
    msymbol_get ()  */
Packit Service a721b1
Packit Service a721b1
M17NFunc
Packit Service a721b1
msymbol_get_func (MSymbol symbol, MSymbol key)
Packit Service a721b1
{
Packit Service a721b1
  if (symbol == Mnil || key == Mnil)
Packit Service a721b1
    return NULL;
Packit Service a721b1
  return mplist_get_func (&symbol->plist, key);
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
/*** @} */
Packit Service a721b1
Packit Service a721b1
#include <stdio.h>
Packit Service a721b1
Packit Service a721b1
/*** @addtogroup m17nDebug */
Packit Service a721b1
/*=*/
Packit Service a721b1
/*** @{ */
Packit Service a721b1
Packit Service a721b1
/***en
Packit Service a721b1
    @brief Dump a symbol.
Packit Service a721b1
Packit Service a721b1
    The mdebug_dump_symbol () function prints symbol $SYMBOL in a
Packit Service a721b1
    human readable way to the stderr or to what specified by the
Packit Service a721b1
    environment variable MDEBUG_OUTPUT_FILE.  $INDENT specifies how
Packit Service a721b1
    many columns to indent the lines but the first one.
Packit Service a721b1
Packit Service a721b1
    @return
Packit Service a721b1
    This function returns $SYMBOL.
Packit Service a721b1
Packit Service a721b1
    @errors
Packit Service a721b1
    MERROR_DEBUG  */
Packit Service a721b1
/***ja
Packit Service a721b1
    @brief シンボルをダンプする.
Packit Service a721b1
Packit Service a721b1
    関数 mdebug_dump_symbol () はシンボル $symbol を標準エラー出力もし
Packit Service a721b1
    くは環境変数 MDEBUG_DUMP_FONT で指定されたファイルに人間に可読な形
Packit Service a721b1
    で印刷する。 $INDENT は2行目以降のインデントを指定する。
Packit Service a721b1
Packit Service a721b1
    @return
Packit Service a721b1
    この関数は $SYMBOL を返す。 
Packit Service a721b1
Packit Service a721b1
    @errors
Packit Service a721b1
    MERROR_DEBUG  */
Packit Service a721b1
Packit Service a721b1
MSymbol
Packit Service a721b1
mdebug_dump_symbol (MSymbol symbol, int indent)
Packit Service a721b1
{
Packit Service a721b1
  char *prefix;
Packit Service a721b1
  MPlist *plist;
Packit Service a721b1
  char *name;
Packit Service a721b1
Packit Service a721b1
  if (indent < 0)
Packit Service a721b1
    MERROR (MERROR_DEBUG, Mnil);
Packit Service a721b1
  prefix = (char *) alloca (indent + 1);
Packit Service a721b1
  memset (prefix, 32, indent);
Packit Service a721b1
  prefix[indent] = 0;
Packit Service a721b1
Packit Service a721b1
  if (symbol == Mnil)
Packit Service a721b1
    plist = NULL, name = "nil";
Packit Service a721b1
  else
Packit Service a721b1
    plist = &symbol->plist, name = symbol->name;
Packit Service a721b1
Packit Service a721b1
  fprintf (mdebug__output, "%s%s", prefix, name);
Packit Service a721b1
  while (plist && MPLIST_KEY (plist) != Mnil)
Packit Service a721b1
    {
Packit Service a721b1
      fprintf (mdebug__output, ":%s", MPLIST_KEY (plist)->name);
Packit Service a721b1
      plist = MPLIST_NEXT (plist);
Packit Service a721b1
    }
Packit Service a721b1
  return symbol;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
/***en
Packit Service a721b1
    @brief Dump all symbol names.
Packit Service a721b1
Packit Service a721b1
    The mdebug_dump_all_symbols () function prints names of all
Packit Service a721b1
    symbols to the stderr or to what specified by the environment
Packit Service a721b1
    variable MDEBUG_OUTPUT_FILE.  $INDENT specifies how many columns
Packit Service a721b1
    to indent the lines but the first one.
Packit Service a721b1
Packit Service a721b1
    @return
Packit Service a721b1
    This function returns #Mnil.
Packit Service a721b1
Packit Service a721b1
    @errors
Packit Service a721b1
    MERROR_DEBUG  */
Packit Service a721b1
/***ja
Packit Service a721b1
    @brief すべてのシンボル名をダンプする.
Packit Service a721b1
Packit Service a721b1
    関数 mdebug_dump_all_symbols () は、すべてのシンボルの名前を標準エ
Packit Service a721b1
    ラー出力もしくは環境変数 MDEBUG_DUMP_FONT で指定されたファイルに印
Packit Service a721b1
    刷する。 $INDENT は2行目以降のインデントを指定する。
Packit Service a721b1
Packit Service a721b1
    @return
Packit Service a721b1
    この関数は #Mnil を返す。 
Packit Service a721b1
Packit Service a721b1
    @errors
Packit Service a721b1
    MERROR_DEBUG  */
Packit Service a721b1
Packit Service a721b1
Packit Service a721b1
MSymbol
Packit Service a721b1
mdebug_dump_all_symbols (int indent)
Packit Service a721b1
{
Packit Service a721b1
  char *prefix;
Packit Service a721b1
  int i, n;
Packit Service a721b1
  MSymbol sym;
Packit Service a721b1
Packit Service a721b1
  if (indent < 0)
Packit Service a721b1
    MERROR (MERROR_DEBUG, Mnil);
Packit Service a721b1
  prefix = (char *) alloca (indent + 1);
Packit Service a721b1
  memset (prefix, 32, indent);
Packit Service a721b1
  prefix[indent] = 0;
Packit Service a721b1
Packit Service a721b1
  fprintf (mdebug__output, "(symbol-list");
Packit Service a721b1
  for (i = n = 0; i < SYMBOL_TABLE_SIZE; i++)
Packit Service a721b1
    if ((sym = symbol_table[i]))
Packit Service a721b1
      {
Packit Service a721b1
	fprintf (mdebug__output, "\n%s  (%4d", prefix, i);
Packit Service a721b1
	for (; sym; sym = sym->next, n++)
Packit Service a721b1
	  fprintf (mdebug__output, " '%s'", sym->name);
Packit Service a721b1
	fprintf (mdebug__output, ")");
Packit Service a721b1
      }
Packit Service a721b1
  fprintf (mdebug__output, "\n%s  (total %d)", prefix, n);
Packit Service a721b1
  fprintf (mdebug__output, ")");
Packit Service a721b1
  return Mnil;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
/*** @} */ 
Packit Service a721b1
Packit Service a721b1
/*
Packit Service a721b1
  Local Variables:
Packit Service a721b1
  coding: euc-japan
Packit Service a721b1
  End:
Packit Service a721b1
*/