(root)/
fribidi-1.0.13/
gen.tab/
gen-joining-type-tab.c
       1  /* FriBidi
       2   * gen-joining-type-tab.c - generate joining-type.tab.i
       3   *
       4   * Author:
       5   *   Behdad Esfahbod, 2004
       6   *
       7   * Copyright (C) 2004 Sharif FarsiWeb, Inc
       8   * Copyright (C) 2004 Behdad Esfahbod
       9   * 
      10   * This library is free software; you can redistribute it and/or
      11   * modify it under the terms of the GNU Lesser General Public
      12   * License as published by the Free Software Foundation; either
      13   * version 2.1 of the License, or (at your option) any later version.
      14   * 
      15   * This library is distributed in the hope that it will be useful,
      16   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      17   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      18   * Lesser General Public License for more details.
      19   * 
      20   * You should have received a copy of the GNU Lesser General Public License
      21   * along with this library, in a file named COPYING; if not, write to the
      22   * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
      23   * Boston, MA 02110-1301, USA
      24   * 
      25   * For licensing issues, contact <fribidi.license@gmail.com>.
      26   */
      27  
      28  #include <common.h>
      29  
      30  #include <fribidi-unicode.h>
      31  
      32  #include <stdio.h>
      33  #ifdef HAVE_CONFIG_H
      34  # include <config.h>
      35  #endif
      36  
      37  #ifdef STDC_HEADERS
      38  # include <stdlib.h>
      39  # include <stddef.h>
      40  #else
      41  # if HAVE_STDLIB_H
      42  #  include <stdlib.h>
      43  # endif
      44  #endif
      45  #ifdef HAVE_STRING_H
      46  # if !STDC_HEADERS && HAVE_MEMORY_H
      47  #  include <memory.h>
      48  # endif
      49  # include <string.h>
      50  #endif
      51  #ifdef HAVE_STRINGS_H
      52  # include <strings.h>
      53  #endif
      54  
      55  #include "packtab.h"
      56  
      57  #define appname "gen-joining-type-tab"
      58  #define outputname "joining-type.tab.i"
      59  
      60  static void
      61  die (
      62    const char *msg
      63  )
      64  {
      65    fprintf (stderr, appname ": %s\n", msg);
      66    exit (1);
      67  }
      68  
      69  static void
      70  die2 (
      71    const char *fmt,
      72    const char *p
      73  )
      74  {
      75    fprintf (stderr, appname ": ");
      76    fprintf (stderr, fmt, p);
      77    fprintf (stderr, "\n");
      78    exit (1);
      79  }
      80  
      81  static void
      82  die3 (
      83    const char *fmt,
      84    const char *p,
      85    const char *q
      86  )
      87  {
      88    fprintf (stderr, appname ": ");
      89    fprintf (stderr, fmt, p, q);
      90    fprintf (stderr, "\n");
      91    exit (1);
      92  }
      93  
      94  static void
      95  die3l (
      96    const char *fmt,
      97    unsigned long l,
      98    const char *p
      99  )
     100  {
     101    fprintf (stderr, appname ": ");
     102    fprintf (stderr, fmt, l, p);
     103    fprintf (stderr, "\n");
     104    exit (1);
     105  }
     106  
     107  enum FriBidiJoiningLinearEnumOffsetOne
     108  {
     109  # define _FRIBIDI_ADD_TYPE(TYPE,SYMBOL) TYPE,
     110  # include <fribidi-joining-types-list.h>
     111  # undef _FRIBIDI_ADD_TYPE
     112    NUM_TYPES
     113  };
     114  
     115  struct
     116  {
     117    const char *name;
     118    int key;
     119  }
     120  type_names[] =
     121  {
     122  # define _FRIBIDI_ADD_TYPE(TYPE,SYMBOL) {STRINGIZE(TYPE), TYPE},
     123  # include <fribidi-joining-types-list.h>
     124  # undef _FRIBIDI_ADD_TYPE
     125  };
     126  
     127  #define type_names_count (sizeof (type_names) / sizeof (type_names[0]))
     128  
     129  static const char *names[type_names_count];
     130  
     131  static char
     132  get_type (
     133    const char *s
     134  )
     135  {
     136    unsigned int i;
     137  
     138    for (i = 0; i < type_names_count; i++)
     139      if (!strcmp (s, type_names[i].name))
     140        return type_names[i].key;
     141    die2 ("joining type name `%s' not found", s);
     142    return -1;
     143  }
     144  
     145  static const char *ignored_bidi_types[] = {
     146    "BN",
     147    "LRE",
     148    "RLE",
     149    "LRO",
     150    "RLO",
     151    "PDF",
     152    "LRI",
     153    "RLI",
     154    "FSI",
     155    "PDI",
     156    NULL
     157  };
     158  
     159  static const char *transparent_general_categories[] = {
     160    "Mn",
     161    "Me",
     162    "Cf",
     163    NULL
     164  };
     165  
     166  static const char *
     167  type_is (
     168    const char *s,
     169    const char *type_list[]
     170  )
     171  {
     172    for (; type_list[0]; type_list++)
     173      if (!strcmp (s, type_list[0]))
     174        return type_list[0];
     175    return NULL;
     176  }
     177  
     178  #define table_name "Joi"
     179  #define macro_name "FRIBIDI_GET_JOINING_TYPE"
     180  
     181  static signed int table[FRIBIDI_UNICODE_CHARS];
     182  static char buf[4000];
     183  static char tp[sizeof (buf)], tp_gen[sizeof (buf)], tp_bidi[sizeof (buf)];
     184  
     185  static void
     186  clear_tab (
     187    void
     188  )
     189  {
     190    register FriBidiChar c;
     191  
     192    for (c = 0; c < FRIBIDI_UNICODE_CHARS; c++)
     193      table[c] = U;
     194  }
     195  
     196  static void
     197  init (
     198    void
     199  )
     200  {
     201    register int i;
     202  
     203    for (i = 0; i < type_names_count; i++)
     204      names[i] = 0;
     205    for (i = type_names_count - 1; i >= 0; i--)
     206      names[type_names[i].key] = type_names[i].name;
     207  
     208    clear_tab ();
     209  }
     210  
     211  static void
     212  read_unicode_data_txt (
     213    FILE *f
     214  )
     215  {
     216    unsigned long c, l;
     217  
     218    l = 0;
     219    while (fgets (buf, sizeof buf, f))
     220      {
     221        int i;
     222        const char *s = buf;
     223  
     224        l++;
     225  
     226        while (*s == ' ')
     227  	s++;
     228  
     229        if (*s == '#' || *s == '\0' || *s == '\n')
     230  	continue;
     231  
     232        i = sscanf (s, "%lx;%*[^;];%[^; ];%*[^;];%[^; ]", &c, tp_gen, tp_bidi);
     233        if (i != 3 || c >= FRIBIDI_UNICODE_CHARS)
     234  	die3l ("UnicodeData.txt: invalid input at line %ld: %s", l, s);
     235  
     236        if (type_is (tp_bidi, ignored_bidi_types))
     237  	table[c] = G;
     238        if (type_is (tp_gen, transparent_general_categories))
     239  	table[c] = T;
     240      }
     241  }
     242  
     243  static void
     244  read_arabic_shaping_txt (
     245    FILE *f
     246  )
     247  {
     248    unsigned long c, c2, l;
     249  
     250    l = 0;
     251    while (fgets (buf, sizeof buf, f))
     252      {
     253        int i;
     254        register char typ;
     255        const char *s = buf;
     256  
     257        l++;
     258  
     259        while (*s == ' ')
     260  	s++;
     261  
     262        if (*s == '#' || *s == '\0' || *s == '\n')
     263  	continue;
     264  
     265        i = sscanf (s, "%lx ; %*[^;]; %[^; ]", &c, tp);
     266        if (i == 2)
     267  	c2 = c;
     268        else
     269  	i = sscanf (s, "%lx..%lx ; %*[^;]; %[^; ]", &c, &c2, tp) - 1;
     270  
     271        if (i != 2 || c > c2 || c2 >= FRIBIDI_UNICODE_CHARS)
     272  	die3l ("ArabicShaping.txt: invalid input at line %ld: %s", l, s);
     273  
     274        typ = get_type (tp);
     275        for (; c <= c2; c++)
     276  	table[c] = typ;
     277      }
     278  }
     279  
     280  static void
     281  read_data (
     282    const char *data_file_type[],
     283    const char *data_file_name[]
     284  )
     285  {
     286    FILE *f;
     287  
     288    for (; data_file_name[0] && data_file_type[0];
     289         data_file_name++, data_file_type++)
     290      {
     291        if (!(f = fopen (data_file_name[0], "rt")))
     292  	die2 ("error: cannot open `%s' for reading", data_file_name[0]);
     293  
     294        if (!strcmp (data_file_type[0], "UnicodeData.txt"))
     295  	read_unicode_data_txt (f);
     296        else if (!strcmp (data_file_type[0], "ArabicShaping.txt"))
     297  	read_arabic_shaping_txt (f);
     298        else
     299  	die2 ("error: unknown data-file type %s", data_file_type[0]);
     300  
     301        fclose (f);
     302      }
     303  
     304  }
     305  
     306  static void
     307  gen_joining_type_tab (
     308    int max_depth,
     309    const char *data_file_type[]
     310  )
     311  {
     312    printf ("/* " outputname "\n * generated by " appname " (" FRIBIDI_NAME " "
     313  	  FRIBIDI_VERSION ")\n" " * from the files %s, %s of Unicode version "
     314  	  FRIBIDI_UNICODE_VERSION ". */\n\n", data_file_type[0],
     315  	  data_file_type[1]);
     316  
     317    printf ("#define PACKTAB_UINT8 uint8_t\n"
     318  	  "#define PACKTAB_UINT16 uint16_t\n"
     319  	  "#define PACKTAB_UINT32 uint32_t\n\n");
     320  
     321    if (!pack_table
     322        (table, FRIBIDI_UNICODE_CHARS, 1, U, max_depth, 1, names,
     323         "unsigned char", table_name, macro_name, stdout))
     324      die ("error: insufficient memory, decrease max_depth");
     325  
     326    printf ("#undef PACKTAB_UINT8\n"
     327  	  "#undef PACKTAB_UINT16\n" "#undef PACKTAB_UINT32\n\n");
     328  
     329    printf ("/* End of generated " outputname " */\n");
     330  }
     331  
     332  int
     333  main (
     334    int argc,
     335    const char **argv
     336  )
     337  {
     338    const char *data_file_type[] =
     339      { "UnicodeData.txt", "ArabicShaping.txt", NULL };
     340  
     341    if (argc < 4)
     342      die3 ("usage:\n  " appname " max-depth /path/to/%s /path/to/%s [junk...]",
     343  	  data_file_type[0], data_file_type[1]);
     344  
     345    {
     346      int max_depth = atoi (argv[1]);
     347      const char *data_file_name[] = { NULL, NULL, NULL };
     348      data_file_name[0] = argv[2];
     349      data_file_name[1] = argv[3];
     350  
     351      if (max_depth < 2)
     352        die ("invalid depth");
     353  
     354      init ();
     355      read_data (data_file_type, data_file_name);
     356      gen_joining_type_tab (max_depth, data_file_type);
     357    }
     358  
     359    return 0;
     360  }