Merge branch 'upstream' into tizen
[platform/upstream/fribidi.git] / gen.tab / gen-mirroring-tab.c
1 /* FriBidi
2  * gen-mirroring-tab.c - generate mirroring.tab.i
3  *
4  * Author:
5  *   Behdad Esfahbod, 2001, 2002, 2004
6  *
7  * Copyright (C) 2004 Sharif FarsiWeb, Inc
8  * Copyright (C) 2001,2002,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-mirroring-tab"
54 #define outputname "mirroring.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 die4 (
79   const char *fmt,
80   unsigned long l,
81   unsigned long p,
82   unsigned long q
83 )
84 {
85   fprintf (stderr, appname ": ");
86   fprintf (stderr, fmt, l, p, q);
87   fprintf (stderr, "\n");
88   exit (1);
89 }
90
91 #define table_name "Mir"
92 #define macro_name "FRIBIDI_GET_MIRRORING"
93
94 static signed int table[FRIBIDI_UNICODE_CHARS];
95 static char buf[4000];
96 static signed long max_dist;
97
98 static void
99 init (
100   void
101 )
102 {
103   max_dist = 0;
104 }
105
106 static void
107 clear_tab (
108   void
109 )
110 {
111   register FriBidiChar c;
112
113   for (c = 0; c < FRIBIDI_UNICODE_CHARS; c++)
114     table[c] = 0;
115 }
116
117 static void
118 init_tab_mirroring_txt (
119   void
120 )
121 {
122   clear_tab ();
123 }
124
125 static void
126 read_bidi_mirroring_txt (
127   FILE *f
128 )
129 {
130   unsigned long l;
131
132   init_tab_mirroring_txt ();
133
134   l = 0;
135   while (fgets (buf, sizeof buf, f))
136     {
137       unsigned long i, j;
138       signed long dist;
139       int k;
140       const char *s = buf;
141
142       l++;
143
144       while (*s == ' ')
145         s++;
146
147       if (s[0] == '#' || s[0] == '\0' || s[0] == '\n')
148         continue;
149
150       k = sscanf (s, "%lx; %lx", &i, &j);
151       if (k != 2 || i >= FRIBIDI_UNICODE_CHARS || j >= FRIBIDI_UNICODE_CHARS)
152         die4 ("invalid pair in input at line %ld: %04lX, %04lX", l, i, j);
153       dist = ((signed long) j - (signed long) i);
154       table[i] = dist;
155       if (dist > max_dist)
156         max_dist = dist;
157       else if (-dist > max_dist)
158         max_dist = -dist;
159     }
160 }
161
162 static void
163 read_data (
164   const char *data_file_type,
165   const char *data_file_name
166 )
167 {
168   FILE *f;
169
170   if (!(f = fopen (data_file_name, "rt")))
171     die2 ("error: cannot open `%s' for reading", data_file_name);
172
173   if (!strcmp (data_file_type, "BidiMirroring.txt"))
174     read_bidi_mirroring_txt (f);
175   else
176     die2 ("error: unknown data-file-type %s", data_file_type);
177
178   fclose (f);
179 }
180
181 static void
182 gen_mirroring_tab (
183   int max_depth,
184   const char *data_file_type
185 )
186 {
187   int key_bytes;
188   const char *key_type;
189
190   printf ("/* " outputname "\n * generated by " appname " (" FRIBIDI_NAME " "
191           FRIBIDI_VERSION ")\n" " * from the file %s of Unicode version "
192           FRIBIDI_UNICODE_VERSION ". */\n\n", data_file_type);
193
194   printf ("#define PACKTAB_UINT8 uint8_t\n"
195           "#define PACKTAB_UINT16 uint16_t\n"
196           "#define PACKTAB_UINT32 uint32_t\n\n");
197
198   key_bytes = max_dist <= 0x7f ? 1 : max_dist < 0x7fff ? 2 : 4;
199   key_type = key_bytes == 1 ? "int8_t" : key_bytes == 2 ?
200     "int16_t" : "int32_t";
201
202   if (!pack_table
203       (table, FRIBIDI_UNICODE_CHARS, key_bytes, 0, max_depth, 1, NULL,
204        key_type, table_name, macro_name "_DELTA", stdout))
205     die ("error: insufficient memory, decrease max_depth");
206
207   printf ("#undef PACKTAB_UINT8\n"
208           "#undef PACKTAB_UINT16\n" "#undef PACKTAB_UINT32\n\n");
209
210   printf ("#define " macro_name "(x) ((x) + " macro_name "_DELTA(x))\n\n");
211
212   printf ("/* End of generated " outputname " */\n");
213 }
214
215 int
216 main (
217   int argc,
218   const char **argv
219 )
220 {
221   const char *data_file_type = "BidiMirroring.txt";
222
223   if (argc < 3)
224     die2 ("usage:\n  " appname " max-depth /path/to/%s [junk...]",
225           data_file_type);
226
227   {
228     int max_depth = atoi (argv[1]);
229     const char *data_file_name = argv[2];
230
231     if (max_depth < 2)
232       die ("invalid depth");
233
234     init ();
235     read_data (data_file_type, data_file_name);
236     gen_mirroring_tab (max_depth, data_file_type);
237   }
238
239   return 0;
240 }