w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

fc-lang.c
Go to the documentation of this file.
1 /*
2  * fontconfig/fc-lang/fc-lang.c
3  *
4  * Copyright © 2002 Keith Packard
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 the author(s) not be used in
11  * advertising or publicity pertaining to distribution of the software without
12  * specific, written prior permission. The authors make 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  * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18  * EVENT SHALL THE AUTHOR(S) 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 "fccharset.c"
26 #include "fcstr.c"
27 #include "fcserialize.c"
28 #ifdef WIN32
29 #include <fcntl.h>
30 #include <io.h>
31 extern void kpse_set_program_name(char *a, char *b);
32 #endif
33 
34 /*
35  * fc-lang
36  *
37  * Read a set of language orthographies and build C declarations for
38  * charsets which can then be used to identify which languages are
39  * supported by a given font. Note that this uses some utilities
40  * from the fontconfig library, so the necessary file is simply
41  * included in this compilation. A couple of extra utility
42  * functions are also needed in slightly modified form
43  */
44 
45 FcPrivate void
46 FcCacheObjectReference (void *object)
47 {
48 }
49 
50 FcPrivate void
52 {
53 }
54 
57 {
58  return NULL;
59 }
60 
62 
63 FcChar8 *
65 {
66  return (FcChar8 *) getenv ("HOME");
67 }
68 
69 static void
70 fatal (const char *file, int lineno, const char *msg)
71 {
72  if (lineno)
73  fprintf (stderr, "%s:%d: %s\n", file, lineno, msg);
74  else
75  fprintf (stderr, "%s: %s\n", file, msg);
76  exit (1);
77 }
78 
79 static char *
80 get_line (FILE *f, char *buf, int *lineno)
81 {
82  char *hash;
83  char *line;
84  int end;
85 
86 next:
87  line = buf;
88  if (!fgets (line, 1024, f))
89  return 0;
90  ++(*lineno);
91  hash = strchr (line, '#');
92  if (hash)
93  *hash = '\0';
94 
95  while (line[0] && isspace (line[0]))
96  line++;
97  end = strlen (line);
98  while (end > 0 && isspace (line[end-1]))
99  line[--end] = '\0';
100 
101  if (line[0] == '\0' || line[0] == '\n' || line[0] == '\r')
102  goto next;
103 
104  return line;
105 }
106 
107 static char *dir = 0;
108 
109 static FILE *
110 scanopen (char *file)
111 {
112  FILE *f;
113 
114  f = fopen (file, "r");
115  if (!f && dir)
116  {
117  char path[1024];
118 
119  strcpy (path, dir);
120  strcat (path, "/");
121  strcat (path, file);
122  f = fopen (path, "r");
123  }
124  return f;
125 }
126 
127 /*
128  * build a single charset from a source file
129  *
130  * The file format is quite simple, either
131  * a single hex value or a pair separated with a dash
132  *
133  * Comments begin with '#'
134  */
135 
136 static FcCharSet *
137 scan (FILE *f, char *file, FcCharSetFreezer *freezer)
138 {
139  FcCharSet *c = 0;
140  FcCharSet *n;
141  FcBool del;
142  int start, end, ucs4;
143  char buf[1024];
144  char *line;
145  int lineno = 0;
146 
147  while ((line = get_line (f, buf, &lineno)))
148  {
149  if (!strncmp (line, "include", 7))
150  {
151  FILE *included_f;
152  char *included_file;
153  included_file = strchr (line, ' ');
154  if (!included_file)
155  fatal (file, lineno,
156  "invalid syntax, expected: include filename");
157  while (isspace(*included_file))
158  included_file++;
159  included_f = scanopen (included_file);
160  if (!included_f)
161  fatal (included_file, 0, "can't open");
162  n = scan (included_f, included_file, freezer);
163  fclose (included_f);
164  if (!c)
165  c = FcCharSetCreate ();
166  if (!FcCharSetMerge (c, n, NULL))
167  fatal (file, lineno, "out of memory");
169  continue;
170  }
171  del = FcFalse;
172  if (line[0] == '-')
173  {
174  del = FcTrue;
175  line++;
176  }
177  if (strchr (line, '-'))
178  {
179  if (sscanf (line, "%x-%x", &start, &end) != 2)
180  fatal (file, lineno, "parse error");
181  }
182  else if (strstr (line, ".."))
183  {
184  if (sscanf (line, "%x..%x", &start, &end) != 2)
185  fatal (file, lineno, "parse error");
186  }
187  else
188  {
189  if (sscanf (line, "%x", &start) != 1)
190  fatal (file, lineno, "parse error");
191  end = start;
192  }
193  if (!c)
194  c = FcCharSetCreate ();
195  for (ucs4 = start; ucs4 <= end; ucs4++)
196  {
197  if (!((del ? FcCharSetDelChar : FcCharSetAddChar) (c, ucs4)))
198  fatal (file, lineno, "out of memory");
199  }
200  }
201  n = (FcCharSet *) FcCharSetFreeze (freezer, c);
203  return n;
204 }
205 
206 /*
207  * Convert a file name into a name suitable for C declarations
208  */
209 static char *
210 get_name (char *file)
211 {
212  char *name;
213  char *dot;
214 
215  dot = strchr (file, '.');
216  if (!dot)
217  dot = file + strlen(file);
218  name = malloc (dot - file + 1);
219  strncpy (name, file, dot - file);
220  name[dot-file] = '\0';
221  return name;
222 }
223 
224 /*
225  * Convert a C name into a language name
226  */
227 static char *
228 get_lang (char *name)
229 {
230  char *lang = malloc (strlen (name) + 1);
231  char *l = lang;
232  char c;
233 
234  while ((c = *name++))
235  {
236  if (isupper ((int) (unsigned char) c))
237  c = tolower ((int) (unsigned char) c);
238  if (c == '_')
239  c = '-';
240  if (c == ' ')
241  continue;
242  *l++ = c;
243  }
244  *l++ = '\0';
245  return lang;
246 }
247 
248 typedef struct _Entry {
249  int id;
250  char *file;
252 
253 static int compare (const void *a, const void *b)
254 {
255  const Entry *as = a, *bs = b;
256  return FcStrCmpIgnoreCase ((const FcChar8 *) as->file, (const FcChar8 *) bs->file);
257 }
258 
259 #define MAX_LANG 1024
260 #define MAX_LANG_SET_MAP ((MAX_LANG + 31) / 32)
261 
262 #define BitSet(map, i) ((map)[(entries[i].id)>>5] |= ((FcChar32) 1U << ((entries[i].id) & 0x1f)))
263 
264 int
265 main (int argc, char **argv)
266 {
267  static Entry entries[MAX_LANG + 1];
268  static FcCharSet *sets[MAX_LANG];
269  static int duplicate[MAX_LANG];
270  static int country[MAX_LANG];
271  static char *names[MAX_LANG];
272  static char *langs[MAX_LANG];
273  static int off[MAX_LANG];
274  FILE *f;
275  int ncountry = 0;
276  int i = 0;
277  int nsets = 0;
278  int argi;
279  FcCharLeaf **leaves;
280  int total_leaves = 0;
281  int l, sl, tl, tn;
282  static char line[1024];
283  static FcChar32 map[MAX_LANG_SET_MAP];
284  int num_lang_set_map;
285  int setRangeStart[26];
286  int setRangeEnd[26];
287  FcChar8 setRangeChar;
288  FcCharSetFreezer *freezer;
289 
290 #ifdef WIN32
291  kpse_set_program_name(argv[0], 0);
292  _setmode(_fileno(stdout), _O_BINARY);
293 #endif
294  freezer = FcCharSetFreezerCreate ();
295  if (!freezer)
296  fatal (argv[0], 0, "out of memory");
297  argi = 1;
298  while (argv[argi])
299  {
300  if (!strcmp (argv[argi], "-d"))
301  {
302  argi++;
303  dir = argv[argi++];
304  continue;
305  }
306  if (i == MAX_LANG)
307  fatal (argv[0], 0, "Too many languages");
308  entries[i].id = i;
309  entries[i].file = argv[argi++];
310  i++;
311  }
312  entries[i].file = 0;
313  qsort (entries, i, sizeof (Entry), compare);
314  i = 0;
315  while (entries[i].file)
316  {
317  f = scanopen (entries[i].file);
318  if (!f)
319  fatal (entries[i].file, 0, strerror (errno));
320  sets[i] = scan (f, entries[i].file, freezer);
321  names[i] = get_name (entries[i].file);
322  langs[i] = get_lang(names[i]);
323  if (strchr (langs[i], '-'))
324  country[ncountry++] = i;
325 
326  total_leaves += sets[i]->num;
327  i++;
328  fclose (f);
329  }
330  nsets = i;
331  sets[i] = 0;
332  leaves = malloc (total_leaves * sizeof (FcCharLeaf *));
333  tl = 0;
334  /*
335  * Find unique leaves
336  */
337  for (i = 0; sets[i]; i++)
338  {
339  for (sl = 0; sl < sets[i]->num; sl++)
340  {
341  for (l = 0; l < tl; l++)
342  if (leaves[l] == FcCharSetLeaf(sets[i], sl))
343  break;
344  if (l == tl)
345  leaves[tl++] = FcCharSetLeaf(sets[i], sl);
346  }
347  }
348 
349  /*
350  * Scan the input until the marker is found
351  */
352 
353  while (fgets (line, sizeof (line), stdin))
354  {
355  if (!strncmp (line, "@@@", 3))
356  break;
357  fputs (line, stdout);
358  }
359 
360  printf ("/* total size: %d unique leaves: %d */\n\n",
361  total_leaves, tl);
362 
363  /*
364  * Find duplicate charsets
365  */
366  duplicate[0] = -1;
367  for (i = 1; sets[i]; i++)
368  {
369  int j;
370 
371  duplicate[i] = -1;
372  for (j = 0; j < i; j++)
373  if (sets[j] == sets[i])
374  {
375  duplicate[i] = j;
376  break;
377  }
378  }
379 
380  tn = 0;
381  for (i = 0; sets[i]; i++) {
382  if (duplicate[i] >= 0)
383  continue;
384  off[i] = tn;
385  tn += sets[i]->num;
386  }
387 
388  printf ("#define LEAF0 (%d * sizeof (FcLangCharSet))\n", nsets);
389  printf ("#define OFF0 (LEAF0 + %d * sizeof (FcCharLeaf))\n", tl);
390  printf ("#define NUM0 (OFF0 + %d * sizeof (uintptr_t))\n", tn);
391  printf ("#define SET(n) (n * sizeof (FcLangCharSet) + offsetof (FcLangCharSet, charset))\n");
392  printf ("#define OFF(s,o) (OFF0 + o * sizeof (uintptr_t) - SET(s))\n");
393  printf ("#define NUM(s,n) (NUM0 + n * sizeof (FcChar16) - SET(s))\n");
394  printf ("#define LEAF(o,l) (LEAF0 + l * sizeof (FcCharLeaf) - (OFF0 + o * sizeof (intptr_t)))\n");
395  printf ("#define fcLangCharSets (fcLangData.langCharSets)\n");
396  printf ("#define fcLangCharSetIndices (fcLangData.langIndices)\n");
397  printf ("#define fcLangCharSetIndicesInv (fcLangData.langIndicesInv)\n");
398  printf ("\n");
399 
400  printf ("static const struct {\n"
401  " FcLangCharSet langCharSets[%d];\n"
402  " FcCharLeaf leaves[%d];\n"
403  " uintptr_t leaf_offsets[%d];\n"
404  " FcChar16 numbers[%d];\n"
405  " FcChar%s langIndices[%d];\n"
406  " FcChar%s langIndicesInv[%d];\n"
407  "} fcLangData = {\n",
408  nsets, tl, tn, tn,
409  nsets < 256 ? "8 " : "16", nsets, nsets < 256 ? "8 " : "16", nsets);
410 
411  /*
412  * Dump sets
413  */
414 
415  printf ("{\n");
416  for (i = 0; sets[i]; i++)
417  {
418  int j = duplicate[i];
419 
420  if (j < 0)
421  j = i;
422 
423  printf (" { \"%s\", "
424  " { FC_REF_CONSTANT, %d, OFF(%d,%d), NUM(%d,%d) } }, /* %d */\n",
425  langs[i],
426  sets[j]->num, i, off[j], i, off[j], i);
427  }
428  printf ("},\n");
429 
430  /*
431  * Dump leaves
432  */
433  printf ("{\n");
434  for (l = 0; l < tl; l++)
435  {
436  printf (" { { /* %d */", l);
437  for (i = 0; i < 256/32; i++)
438  {
439  if (i % 4 == 0)
440  printf ("\n ");
441  printf (" 0x%08x,", leaves[l]->map[i]);
442  }
443  printf ("\n } },\n");
444  }
445  printf ("},\n");
446 
447  /*
448  * Dump leaves
449  */
450  printf ("{\n");
451  for (i = 0; sets[i]; i++)
452  {
453  int n;
454 
455  if (duplicate[i] >= 0)
456  continue;
457  printf (" /* %s */\n", names[i]);
458  for (n = 0; n < sets[i]->num; n++)
459  {
460  if (n % 4 == 0)
461  printf (" ");
462  for (l = 0; l < tl; l++)
463  if (leaves[l] == FcCharSetLeaf(sets[i], n))
464  break;
465  if (l == tl)
466  fatal (names[i], 0, "can't find leaf");
467  printf (" LEAF(%3d,%3d),", off[i], l);
468  if (n % 4 == 3)
469  printf ("\n");
470  }
471  if (n % 4 != 0)
472  printf ("\n");
473  }
474  printf ("},\n");
475 
476 
477  printf ("{\n");
478  for (i = 0; sets[i]; i++)
479  {
480  int n;
481 
482  if (duplicate[i] >= 0)
483  continue;
484  printf (" /* %s */\n", names[i]);
485  for (n = 0; n < sets[i]->num; n++)
486  {
487  if (n % 8 == 0)
488  printf (" ");
489  printf (" 0x%04x,", FcCharSetNumbers (sets[i])[n]);
490  if (n % 8 == 7)
491  printf ("\n");
492  }
493  if (n % 8 != 0)
494  printf ("\n");
495  }
496  printf ("},\n");
497 
498  /* langIndices */
499  printf ("{\n");
500  for (i = 0; sets[i]; i++)
501  {
502  printf (" %d, /* %s */\n", entries[i].id, names[i]);
503  }
504  printf ("},\n");
505 
506  /* langIndicesInv */
507  printf ("{\n");
508  {
509  static int entries_inv[MAX_LANG];
510  for (i = 0; sets[i]; i++)
511  entries_inv[entries[i].id] = i;
512  for (i = 0; sets[i]; i++)
513  printf (" %d, /* %s */\n", entries_inv[i], names[entries_inv[i]]);
514  }
515  printf ("}\n");
516 
517  printf ("};\n\n");
518 
519  printf ("#define NUM_LANG_CHAR_SET %d\n", i);
520  num_lang_set_map = (i + 31) / 32;
521  printf ("#define NUM_LANG_SET_MAP %d\n", num_lang_set_map);
522  /*
523  * Dump indices with country codes
524  */
525  if (ncountry)
526  {
527  int c;
528  int ncountry_ent = 0;
529  printf ("\n");
530  printf ("static const FcChar32 fcLangCountrySets[][NUM_LANG_SET_MAP] = {\n");
531  for (c = 0; c < ncountry; c++)
532  {
533  i = country[c];
534  if (i >= 0)
535  {
536  int lang = strchr (langs[i], '-') - langs[i];
537  int d, k;
538 
539  for (k = 0; k < num_lang_set_map; k++)
540  map[k] = 0;
541 
542  BitSet (map, i);
543  for (d = c + 1; d < ncountry; d++)
544  {
545  int j = country[d];
546  if (j >= 0 && !strncmp (langs[j], langs[i], lang + 1))
547  {
548  BitSet(map, j);
549  country[d] = -1;
550  }
551  }
552  printf (" {");
553  for (k = 0; k < num_lang_set_map; k++)
554  printf (" 0x%08x,", map[k]);
555  printf (" }, /* %*.*s */\n",
556  lang, lang, langs[i]);
557  ++ncountry_ent;
558  }
559  }
560  printf ("};\n\n");
561  printf ("#define NUM_COUNTRY_SET %d\n", ncountry_ent);
562  }
563 
564 
565  /*
566  * Find ranges for each letter for faster searching
567  */
568  setRangeChar = 'a';
569  memset(setRangeStart, '\0', sizeof (setRangeStart));
570  memset(setRangeEnd, '\0', sizeof (setRangeEnd));
571  for (i = 0; sets[i]; i++)
572  {
573  char c = names[i][0];
574 
575  while (setRangeChar <= c && c <= 'z')
576  setRangeStart[setRangeChar++ - 'a'] = i;
577  }
578  while (setRangeChar <= 'z') /* no language code starts with these letters */
579  setRangeStart[setRangeChar++ - 'a'] = i;
580 
581  for (setRangeChar = 'a'; setRangeChar < 'z'; setRangeChar++)
582  setRangeEnd[setRangeChar - 'a'] = setRangeStart[setRangeChar+1-'a'] - 1;
583  setRangeEnd[setRangeChar - 'a'] = i - 1;
584 
585  /*
586  * Dump sets start/finish for the fastpath
587  */
588  printf ("\n");
589  printf ("static const FcLangCharSetRange fcLangCharSetRanges[] = {\n");
590  printf ("\n");
591  for (setRangeChar = 'a'; setRangeChar <= 'z' ; setRangeChar++)
592  {
593  printf (" { %d, %d }, /* %c */\n",
594  setRangeStart[setRangeChar - 'a'],
595  setRangeEnd[setRangeChar - 'a'], setRangeChar);
596  }
597  printf ("};\n\n");
598 
599  while (fgets (line, sizeof (line), stdin))
600  fputs (line, stdout);
601 
602  fflush (stdout);
603  exit (ferror (stdout));
604 }
static int lineno
Definition: aftopl.c:19
#define name
#define next(a)
Definition: aptex-macros.h:924
#define hash
Definition: aptex.h:388
#define n
Definition: t4ht.c:1290
#define b
Definition: jpegint.h:372
#define fopen
Definition: xxstdio.h:21
#define fflush
Definition: xxstdio.h:24
#define fgets
Definition: xxstdio.h:29
char * strncpy()
int strcmp()
Definition: coll.cpp:143
int sscanf()
int printf()
char * strcpy()
int main(int argc, char **argv)
Definition: fc-lang.c:265
struct _Entry Entry
static char * get_name(char *file)
Definition: fc-lang.c:210
#define MAX_LANG
Definition: fc-lang.c:259
void FcCacheObjectDereference(void *object)
Definition: fc-lang.c:51
static int compare(const void *a, const void *b)
Definition: fc-lang.c:253
static char * dir
Definition: fc-lang.c:107
static char * get_line(FILE *f, char *buf, int *lineno)
Definition: fc-lang.c:80
static FILE * scanopen(char *file)
Definition: fc-lang.c:110
FcChar8 * FcConfigHome(void)
Definition: fc-lang.c:64
FcChar8 * FcLangNormalize(const FcChar8 *lang)
Definition: fc-lang.c:56
void FcCacheObjectReference(void *object)
Definition: fc-lang.c:46
int FcDebugVal
Definition: fc-lang.c:61
static char * get_lang(char *name)
Definition: fc-lang.c:228
#define BitSet(map, i)
Definition: fc-lang.c:262
#define MAX_LANG_SET_MAP
Definition: fc-lang.c:260
static FcCharSet * scan(FILE *f, char *file, FcCharSetFreezer *freezer)
Definition: fc-lang.c:137
static void fatal(const char *file, int lineno, const char *msg)
Definition: fc-lang.c:70
#define FcCharSetCreate
Definition: fcalias.h:88
#define FcCharSetMerge
Definition: fcalias.h:108
#define FcStrCmpIgnoreCase
Definition: fcalias.h:400
#define FcCharSetDestroy
Definition: fcalias.h:92
#define FcCharSetAddChar
Definition: fcalias.h:94
#define FcCharSetDelChar
Definition: fcalias.h:96
const FcCharSet * FcCharSetFreeze(FcCharSetFreezer *freezer, const FcCharSet *fcs)
Definition: fccharset.c:1217
FcCharSetFreezer * FcCharSetFreezerCreate(void)
Definition: fccharset.c:1254
const FcChar8 lang[6]
Definition: fcfreetype.c:56
#define FcPrivate
Definition: fcftint.h:35
#define FcCharSetNumbers(c)
Definition: fcint.h:381
#define FcCharSetLeaf(c, i)
Definition: fcint.h:378
FcCharLeaf leaves[725]
Definition: fclang.h:40
unsigned char FcChar8
Definition: fontconfig.h:43
#define FcFalse
Definition: fontconfig.h:75
#define FcTrue
Definition: fontconfig.h:76
int FcBool
Definition: fontconfig.h:46
unsigned int FcChar32
Definition: fontconfig.h:45
mpz_t * f
Definition: gen-fib.c:34
#define dot
Definition: globals.h:56
#define c(n)
Definition: gpos-common.c:150
#define a(n)
Definition: gpos-common.c:148
#define d(n)
Definition: gpos-common.c:151
#define strchr
Definition: gsftopk.c:59
#define NULL
Definition: ftobjs.h:61
small capitals from c petite p scientific i
Definition: afcover.h:80
void exit()
char * getenv()
int errno
int num
Definition: disdvi.c:621
#define buf
char * strstr()
#define fclose
Definition: debug.h:100
#define fputs
Definition: mendex.h:67
#define fprintf
Definition: mendex.h:64
static char * strerror(int errnum)
Definition: error.c:56
#define malloc
Definition: alloca.c:91
char * as
Definition: fixwrites.c:8
int strncmp()
#define qsort
Definition: includes.h:72
#define _O_BINARY
Definition: lfs.c:127
tuple num_lang_set_map
Definition: fc-lang.py:350
list names
Definition: fc-lang.py:151
int tn
Definition: fc-lang.py:225
list sets
Definition: fc-lang.py:150
dictionary off
Definition: fc-lang.py:226
list langs
Definition: fc-lang.py:152
list country
Definition: fc-lang.py:153
int total_leaves
Definition: fc-lang.py:155
int k
Definition: otp-parser.c:70
char line[1024]
Definition: process_score.c:29
bstring c int memset(void *s, int c, int length)
#define map
#define tolower(ch)
Definition: utype.h:137
#define isspace(ch)
Definition: utype.h:87
#define isupper(ch)
Definition: utype.h:80
Definition: fc-lang.c:248
char * file
Definition: fc-lang.c:250
int id
Definition: fc-lang.c:249
Definition: filedef.h:30
Definition: bdf.c:133
Definition: texview.c:48
Definition: tpic.c:45
#define FILE
Definition: t1stdio.h:34
#define ferror(f)
Definition: t1stdio.h:110
int j
Definition: t4ht.c:1589
*job_name strlen((char *) job_name) - 4)
char * file
Definition: t4ht.c:931
@ duplicate
Definition: regex.c:435
@ start
Definition: preamble.c:52
#define argv
Definition: xmain.c:270
#define argc
Definition: xmain.c:269
#define end(cp)
Definition: zic.c:71