Blame src/chartab.c

Packit Service a721b1
/* chartab.h -- character table 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 m17nChartable
Packit Service a721b1
    @brief Chartable objects and API for them.
Packit Service a721b1
Packit Service a721b1
    The m17n library supports enormous number of characters.  Thus, if
Packit Service a721b1
    attributes of each character are to be stored in a simple array,
Packit Service a721b1
    such an array would be impractically big.  The attributes usually
Packit Service a721b1
    used, however, are often assigned only to a range of characters.
Packit Service a721b1
    Even when all characters have attributes, characters of
Packit Service a721b1
    consecutive character code tend to have the same attribute values.
Packit Service a721b1
Packit Service a721b1
    The m17n library utilizes this tendency to store characters and
Packit Service a721b1
    their attribute values efficiently in an object called @e
Packit Service a721b1
    Chartable.  Although a chartable object is not a simple array,
Packit Service a721b1
    application programs can handle a chartable as if it is an array.
Packit Service a721b1
    Attribute values of a character can be obtained by accessing a
Packit Service a721b1
    Chartable for the attribute with the character code of the
Packit Service a721b1
    specified character.
Packit Service a721b1
Packit Service a721b1
    A chartable is a managed object.  */
Packit Service a721b1
Packit Service a721b1
/***ja
Packit Service a721b1
    @addtogroup m17nChartable 文字テーブル
Packit Service a721b1
Packit Service a721b1
    @brief 文字テーブルとそれに関する API.
Packit Service a721b1
Packit Service a721b1
    m17n ライブラリが扱う文字の空間は広大であるため、文字毎の情報を単純な配列に格納しようとすると、その配列は巨大になりすぎ、非実用的である。
Packit Service a721b1
    しかし通常必要となる文字についての情報は、ある特定の範囲の文字にのみ付いていることが多い。
Packit Service a721b1
    全文字に関して情報がある場合にも、連続した文字コードを持つ文字は同じ情報を持つことが多い。
Packit Service a721b1
Packit Service a721b1
    このような傾向を利用して文字とその付加情報を効率的に格納するために、
Packit Service a721b1
    m17n ライブラリは @e 文字テーブル (chartable) と呼ぶオブジェクトを用いる。
Packit Service a721b1
    文字テーブルは配列ではないが、アプリケーションプログラムは文字テーブルを配列の一種として扱うことができる。
Packit Service a721b1
    ある文字についての特定の情報は、その情報を持つ文字テーブルをその文字のコードで引くこと
Packit Service a721b1
    で得られる。  
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 <limits.h>
Packit Service a721b1
#include <ctype.h>
Packit Service a721b1
#include <stdio.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
Packit Service a721b1
static M17NObjectArray chartable_table;
Packit Service a721b1
Packit Service a721b1
/*** Maximum depth of char-table.  */
Packit Service a721b1
#define CHAR_TAB_MAX_DEPTH 3
Packit Service a721b1
Packit Service a721b1
/** @name Define: Number of characters covered by char-table of each level.
Packit Service a721b1
    @{ */
Packit Service a721b1
Packit Service a721b1
/** BITs for number of characters covered by char-table of each
Packit Service a721b1
    level.  */
Packit Service a721b1
#if MCHAR_MAX < 0x400000
Packit Service a721b1
Packit Service a721b1
#define SUB_BITS_0	22	/* i.e. 0x400000 chars */
Packit Service a721b1
#define SUB_BITS_1	16	/* i.e. 0x10000 chars */
Packit Service a721b1
#define SUB_BITS_2	12	/* i.e. 0x1000 chars */
Packit Service a721b1
#define SUB_BITS_3	7	/* i.e. 0x80 chars */
Packit Service a721b1
Packit Service a721b1
#else  /* MCHAR_MAX >= 0x400000 */
Packit Service a721b1
Packit Service a721b1
#define SUB_BITS_0	31
Packit Service a721b1
#define SUB_BITS_1	24
Packit Service a721b1
#define SUB_BITS_2	16
Packit Service a721b1
#define SUB_BITS_3	8
Packit Service a721b1
#endif
Packit Service a721b1
Packit Service a721b1
/** @} */
Packit Service a721b1
Packit Service a721b1
/** How many characters a char-table covers at each level.  */
Packit Service a721b1
static const int chartab_chars[] =
Packit Service a721b1
  { (1 << SUB_BITS_0),
Packit Service a721b1
    (1 << SUB_BITS_1),
Packit Service a721b1
    (1 << SUB_BITS_2),
Packit Service a721b1
    (1 << SUB_BITS_3) };
Packit Service a721b1
Packit Service a721b1
/** How many slots a char-table has at each level.  */
Packit Service a721b1
static const int chartab_slots[] =
Packit Service a721b1
  { (1 << (SUB_BITS_0 - SUB_BITS_1)),
Packit Service a721b1
    (1 << (SUB_BITS_1 - SUB_BITS_2)),
Packit Service a721b1
    (1 << (SUB_BITS_2 - SUB_BITS_3)),
Packit Service a721b1
    (1 << SUB_BITS_3) };
Packit Service a721b1
Packit Service a721b1
/** Mask bits to obtain the valid bits from a character code for looking
Packit Service a721b1
    up a char-table of each level.  */
Packit Service a721b1
static const int chartab_mask[] =
Packit Service a721b1
  { (int) ((((unsigned) 1) << SUB_BITS_0) - 1),
Packit Service a721b1
    (1 << SUB_BITS_1) - 1,
Packit Service a721b1
    (1 << SUB_BITS_2) - 1,
Packit Service a721b1
    (1 << SUB_BITS_3) - 1 };
Packit Service a721b1
Packit Service a721b1
/** Bit-shifting counts to obtain a valid index from a character code
Packit Service a721b1
    for looking up a char-table of each level.  */
Packit Service a721b1
static const int chartab_shift[] =
Packit Service a721b1
  { SUB_BITS_1, SUB_BITS_2, SUB_BITS_3, 0 };
Packit Service a721b1
Packit Service a721b1
Packit Service a721b1
/** Index for looking up character C in a char-table at DEPTH.  */
Packit Service a721b1
#define SUB_IDX(depth, c)	\
Packit Service a721b1
  (((c) & chartab_mask[depth]) >> chartab_shift[depth])
Packit Service a721b1
Packit Service a721b1
Packit Service a721b1
/** Structure of sub char-table.  */
Packit Service a721b1
typedef struct MSubCharTable MSubCharTable;
Packit Service a721b1
Packit Service a721b1
struct MSubCharTable
Packit Service a721b1
{
Packit Service a721b1
#if SUB_BITS_0 > 24
Packit Service a721b1
Packit Service a721b1
  /* The depth of the table; 0, 1, 2, or 3. */
Packit Service a721b1
  int depth;
Packit Service a721b1
Packit Service a721b1
  /* The minimum character covered by the table.  */
Packit Service a721b1
  int min_char;
Packit Service a721b1
Packit Service a721b1
#else  /* SUB_BITS_0 <= 24 */
Packit Service a721b1
Packit Service a721b1
  /* The value is ((<depth> << 24) | <min_char>).  */
Packit Service a721b1
  int depth_min_char;
Packit Service a721b1
Packit Service a721b1
#endif	/* SUB_BITS_0 <= 24 */
Packit Service a721b1
Packit Service a721b1
  /** The default value of characters covered by the table.  */
Packit Service a721b1
  void *default_value;
Packit Service a721b1
Packit Service a721b1
  /** For a table of bottom level, array of values.  For a non-bottom
Packit Service a721b1
     table, array of sub char-tables.  It may be NULL if all
Packit Service a721b1
     characters covered by the table has <default_value>.  */
Packit Service a721b1
  union {
Packit Service a721b1
    void **values;
Packit Service a721b1
    MSubCharTable *tables;
Packit Service a721b1
  } contents;
Packit Service a721b1
};
Packit Service a721b1
Packit Service a721b1
#if SUB_BITS_0 > 24
Packit Service a721b1
#define TABLE_DEPTH(table) ((table)->depth)
Packit Service a721b1
#define TABLE_MIN_CHAR(table) ((table)->min_char)
Packit Service a721b1
#define SET_DEPTH_MIN_CHAR(table, DEPTH, MIN_CHAR) \
Packit Service a721b1
  ((table)->depth = (DEPTH), (table)->min_char = (MIN_CHAR))
Packit Service a721b1
#else  /* SUB_BITS_0 <= 24 */
Packit Service a721b1
#define TABLE_DEPTH(table) ((table)->depth_min_char >> 24)
Packit Service a721b1
#define TABLE_MIN_CHAR(table) ((table)->depth_min_char & 0xFFFFFF)
Packit Service a721b1
#define SET_DEPTH_MIN_CHAR(table, DEPTH, MIN_CHAR) \
Packit Service a721b1
  ((table)->depth_min_char = ((DEPTH) << 24) | (MIN_CHAR))
Packit Service a721b1
#endif  /* SUB_BITS_0 <= 24 */
Packit Service a721b1
Packit Service a721b1
/** Structure of char-table.  */
Packit Service a721b1
Packit Service a721b1
struct MCharTable
Packit Service a721b1
{
Packit Service a721b1
  /** Common header for a managed object.  */
Packit Service a721b1
  M17NObject control;
Packit Service a721b1
Packit Service a721b1
  /** Key of the table.  */
Packit Service a721b1
  MSymbol key;
Packit Service a721b1
Packit Service a721b1
  /** The minimum and maximum characters covered by the table.  */
Packit Service a721b1
  int min_char, max_char;
Packit Service a721b1
Packit Service a721b1
  MSubCharTable subtable;
Packit Service a721b1
};
Packit Service a721b1
Packit Service a721b1
Packit Service a721b1

Packit Service a721b1
Packit Service a721b1
/* Local functions.  */
Packit Service a721b1
Packit Service a721b1
/** Allocate and initialize an array of sub-tables for sub char-table
Packit Service a721b1
    TABLE.  It is assumed that TABLE_DEPTH (TABLE) <
Packit Service a721b1
    CHAR_TAB_MAX_DEPTH.*/
Packit Service a721b1
Packit Service a721b1
static void
Packit Service a721b1
make_sub_tables (MSubCharTable *table, int managedp)
Packit Service a721b1
{
Packit Service a721b1
  int depth = TABLE_DEPTH (table);
Packit Service a721b1
  int min_char = TABLE_MIN_CHAR (table);
Packit Service a721b1
  int slots = chartab_slots[depth];
Packit Service a721b1
  int chars = chartab_chars[depth + 1];
Packit Service a721b1
  MSubCharTable *tables;
Packit Service a721b1
  int i;
Packit Service a721b1
Packit Service a721b1
  MTABLE_MALLOC (tables, slots, MERROR_CHARTABLE);
Packit Service a721b1
Packit Service a721b1
  for (i = 0; i < slots; i++, min_char += chars)
Packit Service a721b1
    {
Packit Service a721b1
      SET_DEPTH_MIN_CHAR (tables + i, depth + 1, min_char);
Packit Service a721b1
      tables[i].default_value = table->default_value;
Packit Service a721b1
      tables[i].contents.tables = NULL;
Packit Service a721b1
    }
Packit Service a721b1
  if (managedp && table->default_value)
Packit Service a721b1
    M17N_OBJECT_REF_NTIMES (tables->default_value, slots);
Packit Service a721b1
  table->contents.tables = tables;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
Packit Service a721b1
/** Allocate and initialize an array of values for sub char-table
Packit Service a721b1
    TABLE.  It is assumed that TABLE_DEPTH (TABLE) ==
Packit Service a721b1
    CHAR_TAB_MAX_DEPTH.  */
Packit Service a721b1
Packit Service a721b1
static void
Packit Service a721b1
make_sub_values (MSubCharTable *table, int managedp)
Packit Service a721b1
{
Packit Service a721b1
  int slots = chartab_slots[CHAR_TAB_MAX_DEPTH];
Packit Service a721b1
  void **values;
Packit Service a721b1
  int i;
Packit Service a721b1
Packit Service a721b1
  MTABLE_MALLOC (values, slots, MERROR_CHARTABLE);
Packit Service a721b1
Packit Service a721b1
  for (i = 0; i < slots; i++)
Packit Service a721b1
    values[i] = table->default_value;
Packit Service a721b1
  if (managedp && table->default_value)
Packit Service a721b1
    M17N_OBJECT_REF_NTIMES (table->default_value, slots);
Packit Service a721b1
  table->contents.values = values;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
Packit Service a721b1
/** Free contents of sub char-table TABLE and the default value of
Packit Service a721b1
    TABLE.  Free also the sub-tables recursively.  */
Packit Service a721b1
Packit Service a721b1
static void
Packit Service a721b1
free_sub_tables (MSubCharTable *table, int managedp)
Packit Service a721b1
{
Packit Service a721b1
  int depth = TABLE_DEPTH (table);
Packit Service a721b1
  int slots = chartab_slots[depth];
Packit Service a721b1
Packit Service a721b1
  if (table->contents.tables)
Packit Service a721b1
    {
Packit Service a721b1
      if (depth < CHAR_TAB_MAX_DEPTH)
Packit Service a721b1
	{
Packit Service a721b1
	  while (slots--)
Packit Service a721b1
	    free_sub_tables (table->contents.tables + slots, managedp);
Packit Service a721b1
	  free (table->contents.tables);
Packit Service a721b1
	}
Packit Service a721b1
      else
Packit Service a721b1
	{
Packit Service a721b1
	  if (managedp)
Packit Service a721b1
	    while (slots--)
Packit Service a721b1
	      {
Packit Service a721b1
		if (table->contents.values[slots])
Packit Service a721b1
		  M17N_OBJECT_UNREF (table->contents.values[slots]);
Packit Service a721b1
	      }
Packit Service a721b1
	  free (table->contents.values);
Packit Service a721b1
	}
Packit Service a721b1
      table->contents.tables = NULL;
Packit Service a721b1
    }
Packit Service a721b1
  if (managedp && table->default_value)
Packit Service a721b1
    M17N_OBJECT_UNREF (table->default_value);
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
Packit Service a721b1
/** In sub char-table TABLE, set value VAL for characters of the range
Packit Service a721b1
    FROM and TO. */
Packit Service a721b1
Packit Service a721b1
static void
Packit Service a721b1
set_chartable_range (MSubCharTable *table, int from, int to, void *val,
Packit Service a721b1
		     int managedp)
Packit Service a721b1
{
Packit Service a721b1
  int depth = TABLE_DEPTH (table);
Packit Service a721b1
  int min_char = TABLE_MIN_CHAR (table);
Packit Service a721b1
  int max_char = min_char + (chartab_chars[depth] - 1);
Packit Service a721b1
  int i;
Packit Service a721b1
Packit Service a721b1
  if (max_char < 0 || max_char > MCHAR_MAX)
Packit Service a721b1
    max_char = MCHAR_MAX;
Packit Service a721b1
Packit Service a721b1
  if (from < min_char)
Packit Service a721b1
    from = min_char;
Packit Service a721b1
  if (to > max_char)
Packit Service a721b1
    to = max_char;
Packit Service a721b1
Packit Service a721b1
  if (from == min_char && to == max_char)
Packit Service a721b1
    {
Packit Service a721b1
      free_sub_tables (table, managedp);
Packit Service a721b1
      if (managedp && val)
Packit Service a721b1
	M17N_OBJECT_REF (val);
Packit Service a721b1
      table->default_value = val;
Packit Service a721b1
      return;
Packit Service a721b1
    }
Packit Service a721b1
Packit Service a721b1
  if (depth < CHAR_TAB_MAX_DEPTH)
Packit Service a721b1
    {
Packit Service a721b1
      if (! table->contents.tables)
Packit Service a721b1
	make_sub_tables (table, managedp);
Packit Service a721b1
      i = SUB_IDX (depth, from);
Packit Service a721b1
      table = table->contents.tables + i;
Packit Service a721b1
      while (i < chartab_slots[depth] && TABLE_MIN_CHAR (table) <= to)
Packit Service a721b1
	{
Packit Service a721b1
	  set_chartable_range (table, from, to, val, managedp);
Packit Service a721b1
	  table++, i++;
Packit Service a721b1
	}
Packit Service a721b1
    }
Packit Service a721b1
  else
Packit Service a721b1
    {
Packit Service a721b1
      int idx_from = SUB_IDX (depth, from);
Packit Service a721b1
      int idx_to = SUB_IDX (depth, to);
Packit Service a721b1
Packit Service a721b1
      if (! table->contents.values)
Packit Service a721b1
	make_sub_values (table, managedp);
Packit Service a721b1
      for (i = idx_from; i <= idx_to; i++)
Packit Service a721b1
	{
Packit Service a721b1
	  if (managedp && table->contents.values[i])
Packit Service a721b1
	    M17N_OBJECT_UNREF (table->contents.values[i]);
Packit Service a721b1
	  table->contents.values[i] = val;
Packit Service a721b1
	}
Packit Service a721b1
      if (managedp && val)
Packit Service a721b1
	M17N_OBJECT_REF_NTIMES (val, (idx_to - idx_from + 1));
Packit Service a721b1
    }
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
Packit Service a721b1
/** Lookup the sub char-table TABLE for the character C.  If NEXT_C is
Packit Service a721b1
    not NULL, set *NEXT_C to the next interesting character to lookup
Packit Service a721b1
    for.  If DEFAULT_P is zero, the next interesting character is what
Packit Service a721b1
    possibly has the different value than C.  Otherwise, the next
Packit Service a721b1
    interesting character is what possibly has the default value (if C
Packit Service a721b1
    has a value deferent from the default value) or has a value
Packit Service a721b1
    different from the default value (if C has the default value).  */
Packit Service a721b1
Packit Service a721b1
static void *
Packit Service a721b1
lookup_chartable (MSubCharTable *table, int c, int *next_c, int default_p)
Packit Service a721b1
{
Packit Service a721b1
  int depth = TABLE_DEPTH (table);
Packit Service a721b1
  void *val;
Packit Service a721b1
  void *default_value = table->default_value;
Packit Service a721b1
  int idx;
Packit Service a721b1
Packit Service a721b1
  while (1)
Packit Service a721b1
    {
Packit Service a721b1
      if (! table->contents.tables)
Packit Service a721b1
	{
Packit Service a721b1
	  if (next_c)
Packit Service a721b1
	    *next_c = TABLE_MIN_CHAR (table) + chartab_chars[depth];
Packit Service a721b1
	  return table->default_value;
Packit Service a721b1
	}
Packit Service a721b1
      if (depth == CHAR_TAB_MAX_DEPTH)
Packit Service a721b1
	break;
Packit Service a721b1
      table = table->contents.tables + SUB_IDX (depth, c);
Packit Service a721b1
      depth++;
Packit Service a721b1
    }
Packit Service a721b1
Packit Service a721b1
  idx = SUB_IDX (depth, c);
Packit Service a721b1
  val = table->contents.values[idx];
Packit Service a721b1
Packit Service a721b1
  if (next_c)
Packit Service a721b1
    {
Packit Service a721b1
      int max_char = TABLE_MIN_CHAR (table) + (chartab_chars[depth] - 1);
Packit Service a721b1
Packit Service a721b1
      if (max_char < 0 || max_char > MCHAR_MAX)
Packit Service a721b1
	max_char = MCHAR_MAX;
Packit Service a721b1
      if (default_p && val != default_value)
Packit Service a721b1
	{
Packit Service a721b1
	  do { c++, idx++; }
Packit Service a721b1
	  while (c >= 0 && c <= max_char
Packit Service a721b1
		 && table->contents.values[idx] != default_value);
Packit Service a721b1
	}
Packit Service a721b1
      else
Packit Service a721b1
	{
Packit Service a721b1
	  do { c++, idx++; }
Packit Service a721b1
	  while (c >= 0 && c <= max_char
Packit Service a721b1
		 && table->contents.values[idx] == val);
Packit Service a721b1
	}
Packit Service a721b1
      *next_c = c;
Packit Service a721b1
    }
Packit Service a721b1
  return val;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
/** Call FUNC for characters in sub char-table TABLE.  Ignore such
Packit Service a721b1
    characters that has a value IGNORE.  FUNC is called with four
Packit Service a721b1
    arguments; FROM, TO, VAL, and ARG (same as FUNC_ARG).  If
Packit Service a721b1
    DEFAULT_P is zero, FROM and TO are range of characters that has
Packit Service a721b1
    the same value VAL.  Otherwise, FROM and TO are range of
Packit Service a721b1
    characters that has the different value than the default value of
Packit Service a721b1
    TABLE.  */
Packit Service a721b1
Packit Service a721b1
static void
Packit Service a721b1
map_chartable (MSubCharTable *table, void *ignore, int default_p,
Packit Service a721b1
		void (*func) (int, int, void *, void *),
Packit Service a721b1
		void *func_arg)
Packit Service a721b1
{
Packit Service a721b1
  void *current;
Packit Service a721b1
  int from = 0;
Packit Service a721b1
  int c, next_c;
Packit Service a721b1
Packit Service a721b1
  current = lookup_chartable (table, 0, &next_c, default_p);
Packit Service a721b1
  c = next_c;
Packit Service a721b1
  while (c >= 0 && c <= MCHAR_MAX)
Packit Service a721b1
    {
Packit Service a721b1
      void *next = lookup_chartable (table, c, &next_c, default_p);
Packit Service a721b1
Packit Service a721b1
      if (current != next)
Packit Service a721b1
	{
Packit Service a721b1
	  if (current != ignore)
Packit Service a721b1
	    (*func) (from, c - 1, current, func_arg);
Packit Service a721b1
	  current = next;
Packit Service a721b1
	  from = c;
Packit Service a721b1
	}
Packit Service a721b1
      c = next_c;
Packit Service a721b1
    }
Packit Service a721b1
  if (from <= MCHAR_MAX && current != ignore)
Packit Service a721b1
    (*func) (from, MCHAR_MAX, current, func_arg);
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
Packit Service a721b1
/* Return the smallest character whose value is not DEFAULT_VALUE in
Packit Service a721b1
   TABLE.  If all characters in TABLE have DEFAULT_VALUE, return
Packit Service a721b1
   -1.  */
Packit Service a721b1
Packit Service a721b1
static int
Packit Service a721b1
chartab_min_non_default_char (MSubCharTable *table, void *default_value)
Packit Service a721b1
{
Packit Service a721b1
  int depth = TABLE_DEPTH (table);
Packit Service a721b1
  int slots;
Packit Service a721b1
  int i, c;
Packit Service a721b1
Packit Service a721b1
  if (!table->contents.tables)
Packit Service a721b1
    return (default_value == table->default_value
Packit Service a721b1
	    ? -1 : TABLE_MIN_CHAR (table));
Packit Service a721b1
Packit Service a721b1
  slots = chartab_slots[depth];
Packit Service a721b1
Packit Service a721b1
  if (depth == CHAR_TAB_MAX_DEPTH)
Packit Service a721b1
    {
Packit Service a721b1
      for (i = 0; i < slots; i++)
Packit Service a721b1
	if (table->contents.values[i] != default_value)
Packit Service a721b1
	  return (TABLE_MIN_CHAR (table) + i);
Packit Service a721b1
    }
Packit Service a721b1
  else
Packit Service a721b1
    {
Packit Service a721b1
      for (i = 0; i < slots; i++)
Packit Service a721b1
	if ((c = chartab_min_non_default_char (table->contents.tables + i,
Packit Service a721b1
					       default_value))
Packit Service a721b1
	    >= 0)
Packit Service a721b1
	  return c;
Packit Service a721b1
    }
Packit Service a721b1
  return -1;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
Packit Service a721b1
/* Return the largest character whose value is not DEFAULT_VALUE in
Packit Service a721b1
   TABLE.  If all characters in TABLE have DEFAULT_VALUE, return
Packit Service a721b1
   -1.  */
Packit Service a721b1
Packit Service a721b1
static int
Packit Service a721b1
chartab_max_non_default_char (MSubCharTable *table, void *default_value)
Packit Service a721b1
{
Packit Service a721b1
  int depth = TABLE_DEPTH (table);
Packit Service a721b1
  int slots;
Packit Service a721b1
  int i, c;
Packit Service a721b1
Packit Service a721b1
  if (!table->contents.tables)
Packit Service a721b1
    return (default_value == table->default_value
Packit Service a721b1
	    ? -1 : TABLE_MIN_CHAR (table) + chartab_chars[depth] - 1);
Packit Service a721b1
Packit Service a721b1
  slots = chartab_slots[depth];
Packit Service a721b1
Packit Service a721b1
  if (depth == CHAR_TAB_MAX_DEPTH)
Packit Service a721b1
    {
Packit Service a721b1
      for (i = slots - 1; i >= 0; i--)
Packit Service a721b1
	if (table->contents.values[i] != default_value)
Packit Service a721b1
	  return (TABLE_MIN_CHAR (table) + i);
Packit Service a721b1
    }
Packit Service a721b1
  else
Packit Service a721b1
    {
Packit Service a721b1
      for (i = slots - 1; i >= 0; i--)
Packit Service a721b1
	if ((c = chartab_max_non_default_char (table->contents.tables + i,
Packit Service a721b1
					       default_value))
Packit Service a721b1
	    >= 0)
Packit Service a721b1
	  return c;
Packit Service a721b1
    }
Packit Service a721b1
  return -1;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
static void
Packit Service a721b1
free_chartable (void *object)
Packit Service a721b1
{
Packit Service a721b1
  MCharTable *table = (MCharTable *) object;
Packit Service a721b1
  int managedp = table->key != Mnil && table->key->managing_key;
Packit Service a721b1
Packit Service a721b1
  if (table->subtable.contents.tables)
Packit Service a721b1
    {
Packit Service a721b1
      int i;
Packit Service a721b1
Packit Service a721b1
      for (i = 0; i < chartab_slots[0]; i++)
Packit Service a721b1
	free_sub_tables (table->subtable.contents.tables + i, managedp);
Packit Service a721b1
      free (table->subtable.contents.tables);
Packit Service a721b1
      if (managedp && table->subtable.default_value)
Packit Service a721b1
	M17N_OBJECT_UNREF (table->subtable.default_value);
Packit Service a721b1
    }
Packit Service a721b1
  M17N_OBJECT_UNREGISTER (chartable_table, table);
Packit Service a721b1
  free (object);
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
#include <stdio.h>
Packit Service a721b1
Packit Service a721b1
/* Support function of mdebug_dump_chartab.  */
Packit Service a721b1
Packit Service a721b1
static void
Packit Service a721b1
dump_sub_chartab (MSubCharTable *table, void *default_value,
Packit Service a721b1
		  MSymbol key, int indent)
Packit Service a721b1
{
Packit Service a721b1
  int depth = TABLE_DEPTH (table);
Packit Service a721b1
  int min_char = TABLE_MIN_CHAR (table);
Packit Service a721b1
  int max_char = min_char + (chartab_chars[depth] - 1);
Packit Service a721b1
  char *prefix = (char *) alloca (indent + 1);
Packit Service a721b1
  int i;
Packit Service a721b1
Packit Service a721b1
  if (max_char < 0 || max_char > MCHAR_MAX)
Packit Service a721b1
    max_char = MCHAR_MAX;
Packit Service a721b1
Packit Service a721b1
  memset (prefix, 32, indent);
Packit Service a721b1
  prefix[indent] = 0;
Packit Service a721b1
Packit Service a721b1
  if (! table->contents.tables && table->default_value == default_value)
Packit Service a721b1
    return;
Packit Service a721b1
  fprintf (mdebug__output, "\n%s(sub%d (U+%04X U+%04X) ",
Packit Service a721b1
	   prefix, depth, min_char, max_char);
Packit Service a721b1
  if (key == Msymbol)
Packit Service a721b1
    {
Packit Service a721b1
      if (table->default_value)
Packit Service a721b1
	fprintf (mdebug__output, "(default %s)",
Packit Service a721b1
		 ((MSymbol) table->default_value)->name);
Packit Service a721b1
      else
Packit Service a721b1
	fprintf (mdebug__output, "(default nil)");
Packit Service a721b1
    }
Packit Service a721b1
  else
Packit Service a721b1
    fprintf (mdebug__output, "(default #x%X)", (unsigned) table->default_value);
Packit Service a721b1
Packit Service a721b1
  default_value = table->default_value;
Packit Service a721b1
  if (table->contents.tables)
Packit Service a721b1
    {
Packit Service a721b1
      if (depth < CHAR_TAB_MAX_DEPTH)
Packit Service a721b1
	for (i = 0; i < chartab_slots[depth]; i++)
Packit Service a721b1
	  dump_sub_chartab (table->contents.tables + i, default_value,
Packit Service a721b1
			    key, indent  + 2);
Packit Service a721b1
      else
Packit Service a721b1
	for (i = 0; i < chartab_slots[depth]; i++, min_char++)
Packit Service a721b1
	  {
Packit Service a721b1
	    void **val = table->contents.values + i;
Packit Service a721b1
Packit Service a721b1
	    if (val == default_value)
Packit Service a721b1
	      continue;
Packit Service a721b1
	    default_value = *val;
Packit Service a721b1
	    fprintf (mdebug__output, "\n%s  (U+%04X", prefix, min_char);
Packit Service a721b1
	    while (i + 1 < chartab_slots[depth]
Packit Service a721b1
		   && val[1] == default_value)
Packit Service a721b1
	      i++, val++, min_char++;
Packit Service a721b1
	    fprintf (mdebug__output, "-U+%04X ", min_char);
Packit Service a721b1
	    if (key == Msymbol)
Packit Service a721b1
	      {
Packit Service a721b1
		if (default_value)
Packit Service a721b1
		  fprintf (mdebug__output, "%s)",
Packit Service a721b1
			   ((MSymbol) default_value)->name);
Packit Service a721b1
		else
Packit Service a721b1
		  fprintf (mdebug__output, "nil)");
Packit Service a721b1
	      }
Packit Service a721b1
	    else
Packit Service a721b1
	      fprintf (mdebug__output, " #xx%X)", (unsigned) default_value);
Packit Service a721b1
	  }
Packit Service a721b1
    }
Packit Service a721b1
  fprintf (mdebug__output, ")");
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1

Packit Service a721b1
/* Internal API */
Packit Service a721b1
Packit Service a721b1
int
Packit Service a721b1
mchartable__init ()
Packit Service a721b1
{
Packit Service a721b1
  M17N_OBJECT_ADD_ARRAY (chartable_table, "Chartable");
Packit Service a721b1
  return 0;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
void
Packit Service a721b1
mchartable__fini ()
Packit Service a721b1
{
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
void *
Packit Service a721b1
mchartable__lookup (MCharTable *table, int c, int *next_c, int default_p)
Packit Service a721b1
{
Packit Service a721b1
  return lookup_chartable (&table->subtable, c, next_c, default_p);
Packit Service a721b1
}
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 m17nChartable */
Packit Service a721b1
/*** @{ */
Packit Service a721b1
/*=*/
Packit Service a721b1
Packit Service a721b1
/***en
Packit Service a721b1
    @brief Symbol whose name is "char-table".
Packit Service a721b1
Packit Service a721b1
    The symbol @c Mchar_table has the name <tt>"char-table"</tt>.  */
Packit Service a721b1
Packit Service a721b1
/***ja
Packit Service a721b1
    @brief "char-table" という名前を持つシンボル.
Packit Service a721b1
Packit Service a721b1
    シンボル @c Mchar_table は名前 <tt>"char-table"</tt> を持つ。
Packit Service a721b1
    */
Packit Service a721b1
Packit Service a721b1
MSymbol Mchar_table;
Packit Service a721b1
Packit Service a721b1
/*=*/
Packit Service a721b1
Packit Service a721b1
/***en
Packit Service a721b1
    @brief Create a new chartable.
Packit Service a721b1
Packit Service a721b1
    The mchartable () function creates a new chartable object with
Packit Service a721b1
    symbol $KEY and the default value $DEFAULT_VALUE.  If $KEY is a
Packit Service a721b1
    managing key, the elements of the table (including the default
Packit Service a721b1
    value) are managed objects or NULL.
Packit Service a721b1
Packit Service a721b1
    @return
Packit Service a721b1
    If the operation was successful, mchartable () returns a pointer
Packit Service a721b1
    to the created chartable.  Otherwise it returns @c NULL and
Packit Service a721b1
    assigns an error code to the external variable #merror_code.  */
Packit Service a721b1
Packit Service a721b1
/***ja
Packit Service a721b1
    @brief 新しい文字テーブルを作る.
Packit Service a721b1
Packit Service a721b1
    関数 mchartable () はキーが $KEY で要素のデフォルト値が 
Packit Service a721b1
    $DEFAULT_VALUE である新しい文字テーブルを作る。もし $KEY 
Packit Service a721b1
    が管理キーであれば、このテーブルの要素は(デフォルト値を含めて)管理下オブジェクトか 
Packit Service a721b1
    NULL のいずれかである。
Packit Service a721b1
Packit Service a721b1
    @return
Packit Service a721b1
    処理が成功すれば mchartable () は作成された文字テーブルへのポインタを返す。
Packit Service a721b1
    失敗した場合は @c NULL を返し、外部変数 #merror_code にエラーコードを設定する。  */
Packit Service a721b1
Packit Service a721b1
MCharTable *
Packit Service a721b1
mchartable (MSymbol key, void *default_value)
Packit Service a721b1
{
Packit Service a721b1
  MCharTable *table;
Packit Service a721b1
Packit Service a721b1
  M17N_OBJECT (table, free_chartable, MERROR_CHARTABLE);
Packit Service a721b1
  M17N_OBJECT_REGISTER (chartable_table, table);
Packit Service a721b1
  table->key = key;
Packit Service a721b1
  table->min_char = -1;
Packit Service a721b1
  table->max_char = -1;
Packit Service a721b1
  SET_DEPTH_MIN_CHAR (&table->subtable, 0, 0);
Packit Service a721b1
  table->subtable.default_value = default_value;
Packit Service a721b1
  if (key != Mnil && key->managing_key && default_value)
Packit Service a721b1
    M17N_OBJECT_REF (default_value);
Packit Service a721b1
  table->subtable.contents.tables = NULL;
Packit Service a721b1
  return table;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
/*=*/
Packit Service a721b1
Packit Service a721b1
/***en
Packit Service a721b1
    @brief Return the minimum character whose value is set in a chartabe.
Packit Service a721b1
Packit Service a721b1
    The mchartable_min_char () function return the minimum character
Packit Service a721b1
    whose value is set in chartable $TABLE.  No character is set its
Packit Service a721b1
    value, the function returns -1.
Packit Service a721b1
 */
Packit Service a721b1
Packit Service a721b1
int
Packit Service a721b1
mchartable_min_char (MCharTable *table)
Packit Service a721b1
{
Packit Service a721b1
  return table->min_char;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
/*=*/
Packit Service a721b1
Packit Service a721b1
/***en
Packit Service a721b1
    @brief Return the maximum character whose value is set in a chartabe.
Packit Service a721b1
Packit Service a721b1
    The mchartable_max_char () function return the maximum character
Packit Service a721b1
    whose value is set in chartable $TABLE.  No character is set its
Packit Service a721b1
    value, the function returns -1.
Packit Service a721b1
 */
Packit Service a721b1
Packit Service a721b1
int
Packit Service a721b1
mchartable_max_char (MCharTable *table)
Packit Service a721b1
{
Packit Service a721b1
  return table->max_char;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
/*=*/
Packit Service a721b1
Packit Service a721b1
/***en
Packit Service a721b1
    @brief Return the assigned value of a character in a chartable.
Packit Service a721b1
Packit Service a721b1
    The mchartable_lookup () function returns the value assigned to
Packit Service a721b1
    character $C in chartable $TABLE.  If no value has been set for $C
Packit Service a721b1
    explicitly, the default value of $TABLE is returned.  If $C is not
Packit Service a721b1
    a valid character, mchartable_lookup () returns @c NULL and
Packit Service a721b1
    assigns an error code to the external variable #merror_code.  */
Packit Service a721b1
Packit Service a721b1
/***ja
Packit Service a721b1
    @brief 文字テーブル中で文字に割り当てられた値を返す.
Packit Service a721b1
Packit Service a721b1
    関数 mchartable_lookup () は文字テーブル $TABLE 中で文字 $C 
Packit Service a721b1
    に割り当てられた値を返す。$C に対する明示的な値がなければ、$TABLE 
Packit Service a721b1
    のデフォルト値を返す。$C が妥当な文字でなければ、mchartable_lookup () は 
Packit Service a721b1
    @c NULL を返し、外部変数 #merror_code にエラーコードを設定する。  */
Packit Service a721b1
Packit Service a721b1
/***
Packit Service a721b1
    @errors
Packit Service a721b1
    @c MERROR_CHAR
Packit Service a721b1
Packit Service a721b1
    @seealso
Packit Service a721b1
    mchartable_set ()  */
Packit Service a721b1
Packit Service a721b1
void *
Packit Service a721b1
mchartable_lookup (MCharTable *table, int c)
Packit Service a721b1
{
Packit Service a721b1
  M_CHECK_CHAR (c, NULL);
Packit Service a721b1
Packit Service a721b1
  if (c < table->min_char || c > table->max_char)
Packit Service a721b1
    return table->subtable.default_value;
Packit Service a721b1
  return lookup_chartable (&table->subtable, c, NULL, 0);
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
/*=*/
Packit Service a721b1
Packit Service a721b1
/***en
Packit Service a721b1
    @brief Assign a value to a character in a chartable.
Packit Service a721b1
Packit Service a721b1
    The mchartable_set () function sets the value of character $C in
Packit Service a721b1
    chartable $TABLE to $VAL.
Packit Service a721b1
Packit Service a721b1
    @return
Packit Service a721b1
    If the operation was successful, mchartable_set () 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
Packit Service a721b1
/***ja
Packit Service a721b1
    @brief 文字テーブル中での文字の値を設定する.
Packit Service a721b1
Packit Service a721b1
    関数 mchartable_set () は、文字テーブル $TABLE 中の文字 $C 
Packit Service a721b1
    に値 $VAL を割り当てる。
Packit Service a721b1
Packit Service a721b1
    @return
Packit Service a721b1
    処理が成功すれば、mchartable_set () は 0 を返す。そうでなければ -1 
Packit Service a721b1
    を返し、外部変数 #merror_code にエラーコードを設定する。  */
Packit Service a721b1
Packit Service a721b1
/***
Packit Service a721b1
    @errors
Packit Service a721b1
    @c MERROR_CHAR
Packit Service a721b1
Packit Service a721b1
    @seealso
Packit Service a721b1
    mchartable_lookup (), mchartable_set_range ()  */
Packit Service a721b1
Packit Service a721b1
Packit Service a721b1
int
Packit Service a721b1
mchartable_set (MCharTable *table, int c, void *val)
Packit Service a721b1
{
Packit Service a721b1
  int managedp = table->key != Mnil && table->key->managing_key;
Packit Service a721b1
  MSubCharTable *sub = &table->subtable;
Packit Service a721b1
  int i;
Packit Service a721b1
Packit Service a721b1
  M_CHECK_CHAR (c, -1);
Packit Service a721b1
Packit Service a721b1
  if (table->max_char < 0)
Packit Service a721b1
    table->min_char = table->max_char = c;
Packit Service a721b1
  else
Packit Service a721b1
    {
Packit Service a721b1
      if (c < table->min_char)
Packit Service a721b1
	table->min_char = c;
Packit Service a721b1
      else if (c > table->max_char)
Packit Service a721b1
	table->max_char = c;
Packit Service a721b1
    }
Packit Service a721b1
Packit Service a721b1
  for (i = 0; i < CHAR_TAB_MAX_DEPTH; i++)
Packit Service a721b1
    {
Packit Service a721b1
      if (! sub->contents.tables)
Packit Service a721b1
	{
Packit Service a721b1
	  if (sub->default_value == val)
Packit Service a721b1
	    return 0;
Packit Service a721b1
	  make_sub_tables (sub, managedp);
Packit Service a721b1
	}
Packit Service a721b1
      sub = sub->contents.tables + SUB_IDX (i, c);
Packit Service a721b1
    }
Packit Service a721b1
  if (! sub->contents.values)
Packit Service a721b1
    {
Packit Service a721b1
      if (sub->default_value == val)
Packit Service a721b1
	return 0;
Packit Service a721b1
      make_sub_values (sub, managedp);
Packit Service a721b1
    }
Packit Service a721b1
  sub->contents.values[SUB_IDX (3, c)] = val;
Packit Service a721b1
  if (managedp && val)
Packit Service a721b1
    M17N_OBJECT_REF (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 Assign a value to the characters in the specified range.
Packit Service a721b1
Packit Service a721b1
    The mchartable_set_range () function assigns value $VAL to the
Packit Service a721b1
    characters from $FROM to $TO (both inclusive) in chartable $TABLE.
Packit Service a721b1
Packit Service a721b1
    @return
Packit Service a721b1
    If the operation was successful, mchartable_set_range () returns
Packit Service a721b1
    0.  Otherwise it returns -1 and assigns an error code to the
Packit Service a721b1
    external variable #merror_code.  If $FROM is greater than $TO,
Packit Service a721b1
    mchartable_set_range () returns immediately without an error.  */
Packit Service a721b1
Packit Service a721b1
/***ja
Packit Service a721b1
    @brief 指定範囲の文字に値を設定する.
Packit Service a721b1
Packit Service a721b1
    関数 mchartable_set_range () は、文字テーブル $TABLE 中の $FROM 
Packit Service a721b1
    から $TO まで(両端を含む)の文字に、値として $VAL を設定する。
Packit Service a721b1
Packit Service a721b1
    @return
Packit Service a721b1
    処理が成功すれば mchartable_set_range () は 0 を返す。そうでなければ 
Packit Service a721b1
    -1 を返し、外部変数 #merror_code にエラーコードを設定する。$FROM が 
Packit Service a721b1
    $TO より大きいときには、 mchartable_set_range () 
Packit Service a721b1
    は何もせず、エラーも起こさない。  */
Packit Service a721b1
Packit Service a721b1
/***
Packit Service a721b1
    @errors
Packit Service a721b1
    @c MERROR_CHAR
Packit Service a721b1
Packit Service a721b1
    @seealso
Packit Service a721b1
    mchartable_set ()  */
Packit Service a721b1
Packit Service a721b1
int
Packit Service a721b1
mchartable_set_range (MCharTable *table, int from, int to, void *val)
Packit Service a721b1
{
Packit Service a721b1
  int managedp = table->key != Mnil && table->key->managing_key;
Packit Service a721b1
Packit Service a721b1
  M_CHECK_CHAR (from, -1);
Packit Service a721b1
  M_CHECK_CHAR (to, -1);
Packit Service a721b1
Packit Service a721b1
  if (from > to)
Packit Service a721b1
    return 0;
Packit Service a721b1
Packit Service a721b1
  if (table->max_char < 0)
Packit Service a721b1
    table->min_char = from, table->max_char = to;
Packit Service a721b1
  else{
Packit Service a721b1
    if (from < table->min_char)
Packit Service a721b1
      table->min_char = from;
Packit Service a721b1
    if (to > table->max_char)
Packit Service a721b1
      table->max_char = to;
Packit Service a721b1
  }
Packit Service a721b1
  set_chartable_range (&table->subtable, from, to, val, managedp);
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 Search for characters that have non-default value.
Packit Service a721b1
Packit Service a721b1
    The mchartable_range () function searches chartable $TABLE for the
Packit Service a721b1
    first and the last character codes that do not have the default
Packit Service a721b1
    value of $TABLE, and set $FROM and $TO to them, respectively.  If
Packit Service a721b1
    all characters have the default value, both $FROM and $TO are set
Packit Service a721b1
    to -1.  */
Packit Service a721b1
Packit Service a721b1
/***ja
Packit Service a721b1
    @brief 値がデフォルトと異なる文字を探す.
Packit Service a721b1
Packit Service a721b1
    関数 mchartable_range () は文字テーブル $TABLE 中で、$TABLE 
Packit Service a721b1
    のデフォルト値以外の値を持つ最初と最後の文字を探し、それぞれを $FROM 
Packit Service a721b1
    と $TO に設定する。すべての文字が値としてデフォルト値をとっている場合には
Packit Service a721b1
    $FROM と $TO を -1に設定する。  */
Packit Service a721b1
Packit Service a721b1
void
Packit Service a721b1
mchartable_range (MCharTable *table, int *from, int *to)
Packit Service a721b1
{
Packit Service a721b1
  *from = chartab_min_non_default_char (&table->subtable,
Packit Service a721b1
					table->subtable.default_value);
Packit Service a721b1
  if (*from == -1)
Packit Service a721b1
    *to = -1;
Packit Service a721b1
  else
Packit Service a721b1
    *to = chartab_max_non_default_char (&table->subtable,
Packit Service a721b1
					table->subtable.default_value);
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
/*=*/
Packit Service a721b1
Packit Service a721b1
/***en
Packit Service a721b1
    @brief Call a function for characters in a chartable.
Packit Service a721b1
Packit Service a721b1
    The mchartable_map () function calls function $FUNC for characters
Packit Service a721b1
    in chartable $TABLE.  No function call occurs for characters that
Packit Service a721b1
    have value $IGNORE in $TABLE.  Comparison of $IGNORE and character
Packit Service a721b1
    value is done with the operator @c ==.  Be careful when you use
Packit Service a721b1
    string literals or pointers.
Packit Service a721b1
Packit Service a721b1
    Instead of calling $FUNC for each character, mchartable_map ()
Packit Service a721b1
    tries to optimize the number of function calls, i.e. it makes a
Packit Service a721b1
    single function call for a chunk of characters when those
Packit Service a721b1
    consecutive characters have the same value.
Packit Service a721b1
Packit Service a721b1
    No matter how long the character chunk is, $FUNC is called with
Packit Service a721b1
    four arguments; $FROM, $TO, $VAL, and $ARG.  $FROM and $TO (both
Packit Service a721b1
    inclusive) defines the range of characters that have value $VAL.
Packit Service a721b1
    $ARG is the same as $FUNC_ARG.
Packit Service a721b1
Packit Service a721b1
    @return
Packit Service a721b1
    This function always returns 0.  */
Packit Service a721b1
Packit Service a721b1
/***ja
Packit Service a721b1
    @brief 文字テーブル中の文字に対して指定の関数を呼ぶ.
Packit Service a721b1
Packit Service a721b1
    関数 mchartable_map () は、文字テーブル $TABLE 中の文字に対して関数
Packit Service a721b1
    $FUNC を呼ぶ。ただし$TABLE 中でも値が $IGNORE 
Packit Service a721b1
    である文字については関数呼び出しを行なわない。$IGNORE と文字の値の比較は 
Packit Service a721b1
    @c == で行なうので、文字列リテラルやポインタを使う際には注意を要する。
Packit Service a721b1
Packit Service a721b1
    mchartable_map () は、一文字ごとに $FUNC 
Packit Service a721b1
    を呼ぶのではなく、関数呼び出しの回数を最適化しようとする。
Packit Service a721b1
    すなわち、連続した文字が同じ値を持っていた場合には、その文字のまとまり全体について一度の関数呼び出
Packit Service a721b1
    ししか行なわない。
Packit Service a721b1
Packit Service a721b1
    文字のまとまりの大きさにかかわらず、$FUNC は $FROM, $TO, $VAL, $ARG 
Packit Service a721b1
    の4引数で呼ばれる。$FROM と $TO (両端を含む)は $VAL 
Packit Service a721b1
    を値として持つ文字の範囲を示し、$ARG は $FUNC_ARG そのものである。
Packit Service a721b1
Packit Service a721b1
    @return
Packit Service a721b1
    この関数は常に0を返す。  */
Packit Service a721b1
Packit Service a721b1
int
Packit Service a721b1
mchartable_map (MCharTable *table, void *ignore,
Packit Service a721b1
		void (*func) (int, int, void *, void *),
Packit Service a721b1
		void *func_arg)
Packit Service a721b1
{
Packit Service a721b1
  map_chartable (&table->subtable, ignore, 0, func, func_arg);
Packit Service a721b1
  return 0;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
/*=*/
Packit Service a721b1
Packit Service a721b1
/*** @} */
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 chartable.
Packit Service a721b1
Packit Service a721b1
    The mdebug_dump_chartab () function prints a chartable $TABLE 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 $TABLE.  */
Packit Service a721b1
Packit Service a721b1
/***ja
Packit Service a721b1
    @brief 文字テーブルをダンプする.
Packit Service a721b1
Packit Service a721b1
    関数 mdebug_dump_chartab () は文字テーブル $TABLE を標準エラー出力
Packit Service a721b1
    もしくは環境変数 MDEBUG_DUMP_FONT で指定されたファイルに人間に可読
Packit Service a721b1
    な形で印刷する。$INDENT は2行目以降のインデントを指定する。
Packit Service a721b1
Packit Service a721b1
    @return
Packit Service a721b1
    この関数は $TABLE を返す。  */
Packit Service a721b1
Packit Service a721b1
MCharTable *
Packit Service a721b1
mdebug_dump_chartab (MCharTable *table, int indent)
Packit Service a721b1
{
Packit Service a721b1
  fprintf (mdebug__output, "(chartab (U+%04X U+%04X)",
Packit Service a721b1
	   table->min_char, table->max_char);
Packit Service a721b1
  dump_sub_chartab (&table->subtable, table->subtable.default_value,
Packit Service a721b1
		    table->key, indent + 2);
Packit Service a721b1
  fprintf (mdebug__output, ")");
Packit Service a721b1
  return table;
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
*/