/* Conversion of files between different charsets and surfaces.
   Copyright © 1998, 99 Free Software Foundation, Inc.
   François Pinard <pinard@iro.umontreal.ca>, 1998.

   This program 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 program 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 program; if not, write to the Free Software Foundation, Inc.,
   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */

/*===================================================================\
| This module is merely a sand box for now, and is not operational.  |
\===================================================================*/

#include "common.h"

/* FIXME: From charset.c.  */
/* Hash table size for charset names.  */
#define HASH_TABLE_SIZE 997

/* This file takes care of dynamically loading supplementary tables in source
   form, or later dumping them as compilable C code.  */

void
recode_freeze_tables (RECODE_OUTER outer)
{
#if 0
  /* Produce header block comment.  */

  fputs ("\
/* DO NOT MODIFY THIS FILE!  It was generated by `recode --freeze-tables'.  */\n\
\n\
/* Conversion of files between different charsets and surfaces.\n\
   Copyright © 1998 Free Software Foundation, Inc.\n\
   This file is part of the GNU C Library.\n\
   Contributed by François Pinard <pinard@iro.umontreal.ca>, 1998.\n\
\n\
   The `recode' Library is free software; you can redistribute it and/or\n\
   modify it under the terms of the GNU Library General Public License\n\
   as published by the Free Software Foundation; either version 2 of the\n\
   License, or (at your option) any later version.\n\
\n\
   The `recode' Library is distributed in the hope that it will be\n\
   useful, but WITHOUT ANY WARRANTY; without even the implied warranty\n\
   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n\
   Library General Public License for more details.\n\
\n\
   You should have received a copy of the GNU Library General Public\n\
   License along with the `recode' Library; see the file `COPYING.LIB'.\n\
   If not, write to the Free Software Foundation, Inc., 59 Temple Place -\n\
   Suite 330, Boston, MA 02111-1307, USA.  */\n\
\n\
#include \"common.h\"\n",
	 stdout);
#endif

#if 0
  /* Save the hash table.  */

  {
    struct recode_hash *hash;

    fputs ("\n", stdout);
    printf ("struct recode_hash hash_table[%d] =\n", HASH_TABLE_SIZE);
    fputs ("  {\n", stdout);

    for (hash = outer->hash_table;
	 hash < outer->hash_table + HASH_TABLE_SIZE;
	 hash++)
      {
	fputs ("    {", stdout);
	if (hash->name)
	  printf ("\"%s\"", hash->name);
	else
	  fputs ("NULL", stdout);
	fputs (", CHARSET", stdout);
	fputs (", ", stdout);
	if (hash->next)
	  printf ("NEXT", hash->next);
	else
	  fputs ("NULL", stdout);
	fputs ("},\n", stdout);
      }
    fputs ("  };\n", stdout);
  }
#endif
}

#if 0

/* Hashable structure for relating charset or alias names to charsets.  */

struct recode_hash
  {
    /* Charset or alias name, or NULL.  */
    const char *name;
    /* Associated charset.  */
    RECODE_CHARSET charset;
    /* Next index in table, or NULL.  */
    struct recode_hash *next;
  };

struct recode_outer
{
  struct recode_hash *hash_table;
  unsigned number_of_charsets;

  /* Arrays of strings ready for argmatch.  */
  const char **argmatch_charset_array;
  const char **argmatch_surface_array;

  /* recode.c */
  /* -------- */

  /* Known single steps.  */
  RECODE_STEP step_list;
  unsigned number_of_steps;

  /* Identity recoding table.  */
  const unsigned char *one_to_same;

  /* Universal charset used for surface transformations.  */
  RECODE_CHARSET data_charset;

  /* Specially known UCS-2 charset.  */
  RECODE_CHARSET ucs2_charset;

  /* Preset qualities, to make step initialisation simpler.  */
  struct recode_quality quality_byte_reversible;
  struct recode_quality quality_byte_to_byte;
#if 0
  struct recode_quality quality_one_to_maybe; /* FIXME: unused? */
#endif
  struct recode_quality quality_byte_to_variable;
  struct recode_quality quality_variable_to_byte;
  struct recode_quality quality_variable_to_variable;
};

/*---------------------------.
| Description of a charset.  |
`---------------------------*/

/* Double tables are generated as arrays of indices into a pool of strips,
   each strip holds STRIP_SIZE UCS-2 characters.  Some memory is saved by
   not allowing duplicate strips in the pool.  A smaller strip size yields
   more duplicates and so, a smaller pool, but then, tables get longer
   because more strip indices are needed for each table.  It is difficult to
   predict the optimal strip size.  Tests made on 1997-09-22 showed that a
   strip size of 4 needs 27808 bytes total, 8 needs 22656, 16 needs 23584
   and 32 needs 25568, so we decided to stick to a strip size of 8.  Change
   $STRIP_SIZE in `doc/tables.pl' if you change the value here.  */

/* "Are we speaking slips, strips or bars?" (of gold press'latinum :-) */
#define STRIP_SIZE 8

struct recode_charset
{
  /* Chaining of all known charsets and surfaces.  */
  RECODE_CHARSET next;

  /* Unique ordinal for this charset, counted from zero.  */
  unsigned ordinal;

  /* Main name.  */
  const char *name;

  /* Associated UCS-2 data, if any, or NULL.  */
  const struct strip_data *strip_data;

  /* Step for data..CHARSET transformation, if any, or NULL.  */
  RECODE_STEP resurfacer;

  /* Step for CHARSET..data transformation, if any, or NULL.  */
  RECODE_STEP unsurfacer;

  /* Non zero if this is an acceptable charset (not only a surface).  */
  bool charset_flag : 1;

  /* Non zero if this one should be ignored.  */
  bool ignore : 1;
};

struct recode_surface_list
{
  RECODE_CHARSET surface;
  struct recode_surface_list *next;
};

/* A strip table holds a pointer to a pool of strips, then an array of
   256/STRIP_SIZE offsets for the start of strips into that pool, each strip
   describes STRIP_SIZE UCS-2 characters.  A missing character in a strip is
   indicated by all 16 bits set.  */
struct strip_data
{
  const recode_ucs2 *pool;
  const short offset[256 / STRIP_SIZE];
};
typedef struct strip_data struct strip_data;

/*-------------------------------------------.
| Description of a single step of recoding.  |
`-------------------------------------------*/

struct recode_step
{
  /* Chaining of all known single steps.  */
  RECODE_STEP next;

  /* Charset before conversion.  */
  RECODE_CHARSET before;

  /* Charset after conversion.  */
  RECODE_CHARSET after;

  /* Cost for this single step only.  */
  short conversion_cost;

  /* Recoding quality.  */
  struct recode_quality quality;

  /* Step specific variables.  */
  void *local;

  /* Recoding array of 256 chars, or NULL.  */
  const unsigned char *byte_to_byte;

  /* Recoding array of 256 strings, or NULL.  */
  const char *const *byte_to_variable;

  /* Initialisation handler, to be called before step optimisation.  */
  bool (*init_routine)
    PARAMS ((RECODE_STEP, RECODE_CONST_REQUEST,
	     RECODE_CONST_OPTION_LIST,
	     RECODE_CONST_OPTION_LIST));

  /* Transformation handler, for doing the actual recoding work.  */
  bool (*transform_routine)
    PARAMS ((RECODE_CONST_STEP, RECODE_TASK));
};

struct recode_option_list
{
  const char *option;
  RECODE_OPTION_LIST next;
};

struct recode_quality
{
  enum recode_size in_size : 3;	/* rough byte size of input characters */
  enum recode_size out_size : 3; /* rough byte size of output characters */
  bool reversible : 1;		/* transformation is known to be reversible */
  bool slower : 1;		/* transformation is slower than average */
  bool faster : 1;		/* transformation is faster than average */
};

/* The sole purpose of qualities is for later attributing step costs.  */

enum recode_size
{
  RECODE_1,			/* roughly one byte per character */
  RECODE_2,			/* roughly two bytes per character */
  RECODE_4,			/* roughly four bytes per character */
  RECODE_N			/* variable number of bytes per character */
};
#endif
