version up to 1.0.5
[platform/upstream/fribidi.git] / gen.tab / gen-arabic-shaping-tab.c
1 /* FriBidi
2  * gen-arabic-shaping-tab.c - generate arabic-shaping.tab.i
3  *
4  * Author:
5  *   Behdad Esfahbod, 2004, 2005
6  *
7  * Copyright (C) 2004 Sharif FarsiWeb, Inc
8  * Copyright (C) 2004, 2005 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-arabic-shaping-tab"
54 #define outputname "arabic-shaping.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 static const char *arabic_shaping_tags[] = {
104   "isolated",
105   "final",
106   "initial",
107   "medial",
108   NULL
109 };
110
111 static int
112 shape_is (
113   const char *s,
114   const char *type_list[]
115 )
116 {
117   const char **p = type_list;
118   for (; *p; p++)
119     if (!strcmp (s, p[0]))
120       return  p - type_list;
121   return -1;
122 }
123
124 #define table_name "ArShap"
125 #define macro_name "FRIBIDI_GET_ARABIC_SHAPE_PRES"
126
127 #define START_CHAR 0x600
128 #define END_CHAR 0x700
129
130 static FriBidiChar table[FRIBIDI_UNICODE_CHARS][4];
131 static char buf[4000];
132 static char tag[sizeof (buf)], buf2[sizeof (buf)];
133 static FriBidiChar minshaped, maxshaped;
134
135 static void
136 clear_tab (
137   void
138 )
139 {
140   register FriBidiChar c;
141   register int shape;
142
143   for (c = 0; c < FRIBIDI_UNICODE_CHARS; c++)
144     for (shape = 0; shape < 4; shape++)
145       table[c][shape] = c;
146 }
147
148 static void
149 init (
150   void
151 )
152 {
153   minshaped = FRIBIDI_UNICODE_CHARS;
154   maxshaped = 0;
155
156   clear_tab ();
157 }
158
159 static void
160 read_unicode_data_txt (
161   FILE *f
162 )
163 {
164   unsigned long c, unshaped, l;
165
166   l = 0;
167   while (fgets (buf, sizeof buf, f))
168     {
169       int i, shape;
170       const char *s = buf;
171
172       l++;
173
174       while (*s == ' ')
175         s++;
176
177       if (*s == '#' || *s == '\0' || *s == '\n')
178         continue;
179
180       i = sscanf (s, "%lx;%*[^;];%*[^;];%*[^;];%*[^;];<%[^;> ]> %lx %[^; ]", &c, tag, &unshaped, buf2);
181
182       if (i != 3)
183         continue;
184
185       if (i != 3 || c >= FRIBIDI_UNICODE_CHARS || unshaped >= FRIBIDI_UNICODE_CHARS)
186         die3l ("UnicodeData.txt: invalid input at line %ld: %s", l, s);
187
188       shape = shape_is (tag, arabic_shaping_tags);
189       if (shape >= 0)
190         {
191           table[unshaped][shape] = c;
192           if (unshaped < minshaped)
193             minshaped = unshaped;
194           if (unshaped > maxshaped)
195             maxshaped = unshaped;
196         }
197     }
198 }
199
200 static void
201 read_data (
202   const char *data_file_type[],
203   const char *data_file_name[]
204 )
205 {
206   FILE *f;
207
208   for (; data_file_name[0] && data_file_type[0];
209        data_file_name++, data_file_type++)
210     {
211       if (!(f = fopen (data_file_name[0], "rt")))
212         die2 ("error: cannot open `%s' for reading", data_file_name[0]);
213
214       if (!strcmp (data_file_type[0], "UnicodeData.txt"))
215         read_unicode_data_txt (f);
216       else
217         die2 ("error: unknown data-file type %s", data_file_type[0]);
218
219       fclose (f);
220     }
221
222 }
223
224 static void
225 gen_arabic_shaping_tab (
226   int max_depth /* currently unused */,
227   const char *data_file_type[]
228 )
229 {
230   register FriBidiChar c;
231   register int shape;
232  
233   if (maxshaped < minshaped)
234     die ("error: no shaping pair found, something wrong with reading input");
235
236   printf ("/* " outputname "\n * generated by " appname " (" FRIBIDI_NAME " "
237           FRIBIDI_VERSION ")\n" " * from the files %s, %s of Unicode version "
238           FRIBIDI_UNICODE_VERSION ". */\n\n", data_file_type[0],
239           data_file_type[1]);
240
241   printf ("/*\n"
242            "  use %s(key,shape) to access your table\n\n"
243            "  required memory: %ld\n"
244            " */\n\n",
245            macro_name, (long)(maxshaped - minshaped + 1) * 4 * sizeof (FriBidiChar));
246
247   printf ("\n" "/* *IND" "ENT-OFF* */\n\n");
248
249   printf ("static const FriBidiChar %s[%d][%d] = {\n", table_name, maxshaped - minshaped + 1, 4);
250   for (c = minshaped; c <= maxshaped; c++)
251     {
252       printf ("  {");
253       for (shape = 0; shape < 4; shape++)
254         printf ("0x%04lx,", (unsigned long)table[c][shape]);
255       printf ("},\n");
256     }
257       
258
259   printf ("};\n\n");
260
261   printf ("/* *IND" "ENT-ON* */\n\n");
262
263   printf ("#ifndef FRIBIDI_ACCESS_SHAPE_TABLE\n"
264           "# define FRIBIDI_ACCESS_SHAPE_TABLE(table,min,max,x,shape) \\\n"
265           "     (((x)<(min)||(x)>(max))?(x):(table)[(x)-(min)][(shape)])\n"
266           "#endif\n\n");
267   printf ("#define %s(x,shape) "
268           "FRIBIDI_ACCESS_SHAPE_TABLE(%s, 0x%04lx, 0x%04lx, (x), (shape))\n\n",
269           macro_name, table_name, (unsigned long)minshaped, (unsigned long)maxshaped);
270
271   printf ("/* End of generated " outputname " */\n");
272 }
273
274 int
275 main (
276   int argc,
277   const char **argv
278 )
279 {
280   const char *data_file_type[] =
281     { "UnicodeData.txt", NULL };
282
283   if (argc < 3)
284     die3 ("usage:\n  " appname " max-depth /path/to/%s /path/to/%s [junk...]",
285           data_file_type[0], data_file_type[1]);
286
287   {
288     int max_depth = atoi (argv[1]);
289     const char *data_file_name[] = { NULL, NULL };
290     data_file_name[0] = argv[2];
291
292     if (max_depth < 2)
293       die ("invalid depth");
294
295     init ();
296     read_data (data_file_type, data_file_name);
297     gen_arabic_shaping_tab (max_depth, data_file_type);
298   }
299
300   return 0;
301 }