]> git.wh0rd.org - fontconfig.git/blob - fc-lang/fc-lang.c
Build fclang.h before building library This required compiling the charset
[fontconfig.git] / fc-lang / fc-lang.c
1 /*
2 * $XFree86: xc/lib/fontconfig/fc-lang/fc-lang.c,v 1.3 2002/08/22 07:36:43 keithp Exp $
3 *
4 * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
5 *
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of Keith Packard not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission. Keith Packard makes no
13 * representations about the suitability of this software for any purpose. It
14 * is provided "as is" without express or implied warranty.
15 *
16 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
23 */
24
25 #include "fcint.h"
26 #include "fccharset.c"
27 #include "fcstr.c"
28
29 /*
30 * fc-lang
31 *
32 * Read a set of language orthographies and build C declarations for
33 * charsets which can then be used to identify which languages are
34 * supported by a given font. Note that this uses some utilities
35 * from the fontconfig library, so the necessary file is simply
36 * included in this compilation. A couple of extra utility
37 * functions are also needed in slightly modified form
38 */
39
40 void
41 FcMemAlloc (int kind, int size)
42 {
43 }
44
45 void
46 FcMemFree (int kind, int size)
47 {
48 }
49
50 static void
51 fatal (char *file, int lineno, char *msg)
52 {
53 fprintf (stderr, "%s:%d: %s\n", file, lineno, msg);
54 exit (1);
55 }
56
57 static char *
58 get_line (FILE *f, char *line, int *lineno)
59 {
60 char *hash;
61 if (!fgets (line, 1024, f))
62 return 0;
63 ++(*lineno);
64 hash = strchr (line, '#');
65 if (hash)
66 *hash = '\0';
67 if (line[0] == '\0' || line[0] == '\n' || line[0] == '\032' || line[0] == '\r')
68 return get_line (f, line, lineno);
69 return line;
70 }
71
72 /*
73 * build a single charset from a source file
74 *
75 * The file format is quite simple, either
76 * a single hex value or a pair separated with a dash
77 *
78 * Comments begin with '#'
79 */
80
81 static FcCharSet *
82 scan (FILE *f, char *file)
83 {
84 FcCharSet *c = 0;
85 FcCharSet *n;
86 int start, end, ucs4;
87 char line[1024];
88 int lineno = 0;
89
90 while (get_line (f, line, &lineno))
91 {
92 if (!strncmp (line, "include", 7))
93 {
94 file = strchr (line, ' ');
95 while (*file == ' ')
96 file++;
97 end = strlen (file);
98 if (file[end-1] == '\n')
99 file[end-1] = '\0';
100 f = fopen (file, "r");
101 if (!f)
102 fatal (file, 0, "can't open");
103 c = scan (f, file);
104 fclose (f);
105 return c;
106 }
107 if (strchr (line, '-'))
108 {
109 if (sscanf (line, "%x-%x", &start, &end) != 2)
110 fatal (file, lineno, "parse error");
111 }
112 else
113 {
114 if (sscanf (line, "%x", &start) != 1)
115 fatal (file, lineno, "parse error");
116 end = start;
117 }
118 if (!c)
119 c = FcCharSetCreate ();
120 for (ucs4 = start; ucs4 <= end; ucs4++)
121 {
122 if (!FcCharSetAddChar (c, ucs4))
123 fatal (file, lineno, "out of memory");
124 }
125 }
126 n = FcCharSetFreeze (c);
127 FcCharSetDestroy (c);
128 return n;
129 }
130
131 /*
132 * Convert a file name into a name suitable for C declarations
133 */
134 static char *
135 get_name (char *file)
136 {
137 char *name;
138 char *dot;
139
140 dot = strchr (file, '.');
141 if (!dot)
142 dot = file + strlen(file);
143 name = malloc (dot - file + 1);
144 strncpy (name, file, dot - file);
145 name[dot-file] = '\0';
146 return name;
147 }
148
149 /*
150 * Convert a C name into a language name
151 */
152 static char *
153 get_lang (char *name)
154 {
155 char *lang = malloc (strlen (name) + 1);
156 char *l = lang;
157 char c;
158
159 while ((c = *name++))
160 {
161 if (isupper (c))
162 c = tolower (c);
163 if (c == '_')
164 c = '-';
165 if (c == ' ')
166 continue;
167 *l++ = c;
168 }
169 *l++ = '\0';
170 return lang;
171 }
172
173 static int compare (const void *a, const void *b)
174 {
175 const FcChar8 *const *as = a, *const *bs = b;
176 return FcStrCmpIgnoreCase (*as, *bs);
177 }
178
179 #define MAX_LANG 1024
180 #define MAX_LANG_SET_MAP ((MAX_LANG + 31) / 32)
181
182 #define BitSet(map, id) ((map)[(id)>>5] |= ((FcChar32) 1 << ((id) & 0x1f)))
183 #define BitGet(map, id) ((map)[(id)>>5] >> ((id) & 0x1f)) & 1)
184
185 int
186 main (int argc, char **argv)
187 {
188 char *files[MAX_LANG];
189 FcCharSet *sets[MAX_LANG];
190 int duplicate[MAX_LANG];
191 int country[MAX_LANG];
192 char *names[MAX_LANG];
193 char *langs[MAX_LANG];
194 FILE *f;
195 int ncountry = 0;
196 int i = 0;
197 FcCharLeaf **leaves, **sleaves;
198 int total_leaves = 0;
199 int l, sl, tl;
200 int c;
201 char line[1024];
202 FcChar32 map[MAX_LANG_SET_MAP];
203 int num_lang_set_map;
204
205 while (*++argv)
206 {
207 if (i == MAX_LANG)
208 fatal (*argv, 0, "Too many languages");
209 files[i++] = *argv;
210 }
211 files[i] = 0;
212 qsort (files, i, sizeof (char *), compare);
213 i = 0;
214 while (files[i])
215 {
216 f = fopen (files[i], "r");
217 if (!f)
218 fatal (files[i], 0, strerror (errno));
219 sets[i] = scan (f, files[i]);
220 names[i] = get_name (files[i]);
221 langs[i] = get_lang(names[i]);
222 if (strchr (langs[i], '-'))
223 country[ncountry++] = i;
224
225 total_leaves += sets[i]->num;
226 i++;
227 fclose (f);
228 }
229 sets[i] = 0;
230 leaves = malloc (total_leaves * sizeof (FcCharLeaf *));
231 tl = 0;
232 /*
233 * Find unique leaves
234 */
235 for (i = 0; sets[i]; i++)
236 {
237 sleaves = sets[i]->leaves;
238 for (sl = 0; sl < sets[i]->num; sl++)
239 {
240 for (l = 0; l < tl; l++)
241 if (leaves[l] == sleaves[sl])
242 break;
243 if (l == tl)
244 leaves[tl++] = sleaves[sl];
245 }
246 }
247
248 /*
249 * Scan the input until the marker is found
250 */
251
252 while (fgets (line, sizeof (line), stdin))
253 {
254 if (!strncmp (line, "@@@", 3))
255 break;
256 fputs (line, stdout);
257 }
258
259 printf ("/* total size: %d unique leaves: %d */\n\n",
260 total_leaves, tl);
261 /*
262 * Dump leaves
263 */
264 printf ("static const FcCharLeaf leaves[%d] = {\n", tl);
265 for (l = 0; l < tl; l++)
266 {
267 printf (" { { /* %d */", l);
268 for (i = 0; i < 256/32; i++)
269 {
270 if (i % 4 == 0)
271 printf ("\n ");
272 printf (" 0x%08x,", leaves[l]->map[i]);
273 }
274 printf ("\n } },\n");
275 }
276 printf ("};\n\n");
277 printf ("#define L(n) ((FcCharLeaf *) &leaves[n])\n\n");
278
279 /*
280 * Find duplicate charsets
281 */
282 duplicate[0] = -1;
283 for (i = 1; sets[i]; i++)
284 {
285 int j;
286
287 duplicate[i] = -1;
288 for (j = 0; j < i; j++)
289 if (sets[j] == sets[i])
290 {
291 duplicate[i] = j;
292 break;
293 }
294 }
295
296 /*
297 * Dump arrays
298 */
299 for (i = 0; sets[i]; i++)
300 {
301 int n;
302
303 if (duplicate[i] >= 0)
304 continue;
305 printf ("static const FcCharLeaf *leaves_%s[%d] = {\n",
306 names[i], sets[i]->num);
307 for (n = 0; n < sets[i]->num; n++)
308 {
309 if (n % 8 == 0)
310 printf (" ");
311 for (l = 0; l < tl; l++)
312 if (leaves[l] == sets[i]->leaves[n])
313 break;
314 if (l == tl)
315 fatal (names[i], 0, "can't find leaf");
316 printf (" L(%3d),", l);
317 if (n % 8 == 7)
318 printf ("\n");
319 }
320 if (n % 8 != 0)
321 printf ("\n");
322 printf ("};\n\n");
323
324
325 printf ("static const FcChar16 numbers_%s[%d] = {\n",
326 names[i], sets[i]->num);
327 for (n = 0; n < sets[i]->num; n++)
328 {
329 if (n % 8 == 0)
330 printf (" ");
331 printf (" 0x%04x,", sets[i]->numbers[n]);
332 if (n % 8 == 7)
333 printf ("\n");
334 }
335 if (n % 8 != 0)
336 printf ("\n");
337 printf ("};\n\n");
338 }
339 printf ("#undef L\n\n");
340 /*
341 * Dump sets
342 */
343 printf ("static const FcLangCharSet fcLangCharSets[] = {\n");
344 for (i = 0; sets[i]; i++)
345 {
346 int j = duplicate[i];
347 if (j < 0)
348 j = i;
349 printf (" { (FcChar8 *) \"%s\",\n"
350 " { FC_REF_CONSTANT, %d, "
351 "(FcCharLeaf **) leaves_%s, "
352 "(FcChar16 *) numbers_%s } },\n",
353 langs[i],
354 sets[j]->num, names[j], names[j]);
355 }
356 printf ("};\n\n");
357 printf ("#define NUM_LANG_CHAR_SET %d\n", i);
358 num_lang_set_map = (i + 31) / 32;
359 printf ("#define NUM_LANG_SET_MAP %d\n", num_lang_set_map);
360 /*
361 * Dump indices with country codes
362 */
363 if (ncountry)
364 {
365 int ncountry_ent = 0;
366 printf ("\n");
367 printf ("static const FcChar32 fcLangCountrySets[][NUM_LANG_SET_MAP] = {\n");
368 for (c = 0; c < ncountry; c++)
369 {
370 i = country[c];
371 if (i >= 0)
372 {
373 int l = strchr (langs[i], '-') - langs[i];
374 int d, k;
375
376 for (k = 0; k < num_lang_set_map; k++)
377 map[k] = 0;
378
379 BitSet (map, i);
380 for (d = c + 1; d < ncountry; d++)
381 {
382 int j = country[d];
383 if (j >= 0 && !strncmp (langs[j], langs[i], l))
384 {
385 BitSet(map, j);
386 country[d] = -1;
387 }
388 }
389 printf (" {");
390 for (k = 0; k < num_lang_set_map; k++)
391 printf (" 0x%08x,", map[k]);
392 printf (" }, /* %*.*s */\n",
393 l, l, langs[i]);
394 ++ncountry_ent;
395 }
396 }
397 printf ("};\n\n");
398 printf ("#define NUM_COUNTRY_SET %d\n", ncountry_ent);
399 }
400
401 while (fgets (line, sizeof (line), stdin))
402 fputs (line, stdout);
403
404 fflush (stdout);
405 exit (ferror (stdout));
406 }