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