07c095307a14d7575a81b549e3a3ea97ca5c727c
[platform/upstream/fribidi.git] / 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 STDC_HEADERS
34 # include <stdlib.h>
35 # include <stddef.h>
36 #else
37 # if HAVE_STDLIB_H
38 #  include <stdlib.h>
39 # endif
40 #endif
41 #ifdef HAVE_STRING_H
42 # if !STDC_HEADERS && HAVE_MEMORY_H
43 #  include <memory.h>
44 # endif
45 # include <string.h>
46 #endif
47 #ifdef HAVE_STRINGS_H
48 # include <strings.h>
49 #endif
50
51 #include "packtab.h"
52
53 #define appname "gen-joining-type-tab"
54 #define outputname "joining-type.tab.i"
55
56 static void
57 die (
58   const char *msg
59 )
60 {
61   fprintf (stderr, appname ": %s\n", msg);
62   exit (1);
63 }
64
65 static void
66 die2 (
67   const char *fmt,
68   const char *p
69 )
70 {
71   fprintf (stderr, appname ": ");
72   fprintf (stderr, fmt, p);
73   fprintf (stderr, "\n");
74   exit (1);
75 }
76
77 static void
78 die3 (
79   const char *fmt,
80   const char *p,
81   const char *q
82 )
83 {
84   fprintf (stderr, appname ": ");
85   fprintf (stderr, fmt, p, q);
86   fprintf (stderr, "\n");
87   exit (1);
88 }
89
90 static void
91 die3l (
92   const char *fmt,
93   unsigned long l,
94   const char *p
95 )
96 {
97   fprintf (stderr, appname ": ");
98   fprintf (stderr, fmt, l, p);
99   fprintf (stderr, "\n");
100   exit (1);
101 }
102
103 enum FriBidiJoiningLinearEnumOffsetOne
104 {
105 # define _FRIBIDI_ADD_TYPE(TYPE,SYMBOL) TYPE,
106 # include <fribidi-joining-types-list.h>
107 # undef _FRIBIDI_ADD_TYPE
108   NUM_TYPES
109 };
110
111 struct
112 {
113   const char *name;
114   int key;
115 }
116 type_names[] =
117 {
118 # define _FRIBIDI_ADD_TYPE(TYPE,SYMBOL) {STRINGIZE(TYPE), TYPE},
119 # include <fribidi-joining-types-list.h>
120 # undef _FRIBIDI_ADD_TYPE
121 };
122
123 #define type_names_count (sizeof (type_names) / sizeof (type_names[0]))
124
125 static const char *names[type_names_count];
126
127 static char
128 get_type (
129   const char *s
130 )
131 {
132   unsigned int i;
133
134   for (i = 0; i < type_names_count; i++)
135     if (!strcmp (s, type_names[i].name))
136       return type_names[i].key;
137   die2 ("joining type name `%s' not found", s);
138   return -1;
139 }
140
141 static const char *ignored_bidi_types[] = {
142   "BN",
143   "LRE",
144   "RLE",
145   "LRO",
146   "RLO",
147   "PDF",
148   "LRI",
149   "RLI",
150   "FSI",
151   "PDI",
152   NULL
153 };
154
155 static const char *transparent_general_categories[] = {
156   "Mn",
157   "Mn",
158   "Cf",
159   NULL
160 };
161
162 static const char *
163 type_is (
164   const char *s,
165   const char *type_list[]
166 )
167 {
168   for (; type_list[0]; type_list++)
169     if (!strcmp (s, type_list[0]))
170       return type_list[0];
171   return NULL;
172 }
173
174 #define table_name "Joi"
175 #define macro_name "FRIBIDI_GET_JOINING_TYPE"
176
177 static signed int table[FRIBIDI_UNICODE_CHARS];
178 static char buf[4000];
179 static char tp[sizeof (buf)], tp_gen[sizeof (buf)], tp_bidi[sizeof (buf)];
180
181 static void
182 clear_tab (
183   void
184 )
185 {
186   register FriBidiChar c;
187
188   for (c = 0; c < FRIBIDI_UNICODE_CHARS; c++)
189     table[c] = U;
190 }
191
192 static void
193 init (
194   void
195 )
196 {
197   register int i;
198
199   for (i = 0; i < type_names_count; i++)
200     names[i] = 0;
201   for (i = type_names_count - 1; i >= 0; i--)
202     names[type_names[i].key] = type_names[i].name;
203
204   clear_tab ();
205 }
206
207 static void
208 read_unicode_data_txt (
209   FILE *f
210 )
211 {
212   unsigned long c, l;
213
214   l = 0;
215   while (fgets (buf, sizeof buf, f))
216     {
217       int i;
218       const char *s = buf;
219
220       l++;
221
222       while (*s == ' ')
223         s++;
224
225       if (*s == '#' || *s == '\0' || *s == '\n')
226         continue;
227
228       i = sscanf (s, "%lx;%*[^;];%[^; ];%*[^;];%[^; ]", &c, tp_gen, tp_bidi);
229       if (i != 3 || c >= FRIBIDI_UNICODE_CHARS)
230         die3l ("UnicodeData.txt: invalid input at line %ld: %s", l, s);
231
232       if (type_is (tp_bidi, ignored_bidi_types))
233         table[c] = G;
234       if (type_is (tp_gen, transparent_general_categories))
235         table[c] = T;
236     }
237 }
238
239 static void
240 read_arabic_shaping_txt (
241   FILE *f
242 )
243 {
244   unsigned long c, c2, l;
245
246   l = 0;
247   while (fgets (buf, sizeof buf, f))
248     {
249       int i;
250       register char typ;
251       const char *s = buf;
252
253       l++;
254
255       while (*s == ' ')
256         s++;
257
258       if (*s == '#' || *s == '\0' || *s == '\n')
259         continue;
260
261       i = sscanf (s, "%lx ; %*[^;]; %[^; ]", &c, tp);
262       if (i == 2)
263         c2 = c;
264       else
265         i = sscanf (s, "%lx..%lx ; %*[^;]; %[^; ]", &c, &c2, tp) - 1;
266
267       if (i != 2 || c > c2 || c2 >= FRIBIDI_UNICODE_CHARS)
268         die3l ("ArabicShaping.txt: invalid input at line %ld: %s", l, s);
269
270       typ = get_type (tp);
271       for (; c <= c2; c++)
272         table[c] = typ;
273     }
274 }
275
276 static void
277 read_data (
278   const char *data_file_type[],
279   const char *data_file_name[]
280 )
281 {
282   FILE *f;
283
284   for (; data_file_name[0] && data_file_type[0];
285        data_file_name++, data_file_type++)
286     {
287       if (!(f = fopen (data_file_name[0], "rt")))
288         die2 ("error: cannot open `%s' for reading", data_file_name[0]);
289
290       if (!strcmp (data_file_type[0], "UnicodeData.txt"))
291         read_unicode_data_txt (f);
292       else if (!strcmp (data_file_type[0], "ArabicShaping.txt"))
293         read_arabic_shaping_txt (f);
294       else
295         die2 ("error: unknown data-file type %s", data_file_type[0]);
296
297       fclose (f);
298     }
299
300 }
301
302 static void
303 gen_joining_type_tab (
304   int max_depth,
305   const char *data_file_type[]
306 )
307 {
308   printf ("/* " outputname "\n * generated by " appname " (" FRIBIDI_NAME " "
309           FRIBIDI_VERSION ")\n" " * from the files %s, %s of Unicode version "
310           FRIBIDI_UNICODE_VERSION ". */\n\n", data_file_type[0],
311           data_file_type[1]);
312
313   printf ("#define PACKTAB_UINT8 uint8_t\n"
314           "#define PACKTAB_UINT16 uint16_t\n"
315           "#define PACKTAB_UINT32 uint32_t\n\n");
316
317   if (!pack_table
318       (table, FRIBIDI_UNICODE_CHARS, 1, U, max_depth, 1, names,
319        "unsigned char", table_name, macro_name, stdout))
320     die ("error: insufficient memory, decrease max_depth");
321
322   printf ("#undef PACKTAB_UINT8\n"
323           "#undef PACKTAB_UINT16\n" "#undef PACKTAB_UINT32\n\n");
324
325   printf ("/* End of generated " outputname " */\n");
326 }
327
328 int
329 main (
330   int argc,
331   const char **argv
332 )
333 {
334   const char *data_file_type[] =
335     { "UnicodeData.txt", "ArabicShaping.txt", NULL };
336
337   if (argc < 4)
338     die3 ("usage:\n  " appname " max-depth /path/to/%s /path/to/%s [junk...]",
339           data_file_type[0], data_file_type[1]);
340
341   {
342     int max_depth = atoi (argv[1]);
343     const char *data_file_name[] = { NULL, NULL, NULL };
344     data_file_name[0] = argv[2];
345     data_file_name[1] = argv[3];
346
347     if (max_depth < 2)
348       die ("invalid depth");
349
350     init ();
351     read_data (data_file_type, data_file_name);
352     gen_joining_type_tab (max_depth, data_file_type);
353   }
354
355   return 0;
356 }