Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
conmakehash.c
Go to the documentation of this file.
1 /*
2  * conmakehash.c
3  *
4  * Create arrays for initializing the kernel folded tables (using a hash
5  * table turned out to be to limiting...) Unfortunately we can't simply
6  * preinitialize the tables at compile time since kfree() cannot accept
7  * memory not allocated by kmalloc(), and doing our own memory management
8  * just for this seems like massive overkill.
9  *
10  * Copyright (C) 1995-1997 H. Peter Anvin
11  *
12  * This program is a part of the Linux kernel, and may be freely
13  * copied under the terms of the GNU General Public License (GPL),
14  * version 2, or at your option any later version.
15  */
16 
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <sysexits.h>
20 #include <string.h>
21 #include <ctype.h>
22 
23 #define MAX_FONTLEN 256
24 
25 typedef unsigned short unicode;
26 
27 static void usage(char *argv0)
28 {
29  fprintf(stderr, "Usage: \n"
30  " %s chartable [hashsize] [hashstep] [maxhashlevel]\n", argv0);
31  exit(EX_USAGE);
32 }
33 
34 static int getunicode(char **p0)
35 {
36  char *p = *p0;
37 
38  while (*p == ' ' || *p == '\t')
39  p++;
40  if (*p != 'U' || p[1] != '+' ||
41  !isxdigit(p[2]) || !isxdigit(p[3]) || !isxdigit(p[4]) ||
42  !isxdigit(p[5]) || isxdigit(p[6]))
43  return -1;
44  *p0 = p+6;
45  return strtol(p+2,0,16);
46 }
47 
49  /* Massive overkill, but who cares? */
51 
52 static void addpair(int fp, int un)
53 {
54  int i;
55 
56  if ( un <= 0xfffe )
57  {
58  /* Check it isn't a duplicate */
59 
60  for ( i = 0 ; i < unicount[fp] ; i++ )
61  if ( unitable[fp][i] == un )
62  return;
63 
64  /* Add to list */
65 
66  if ( unicount[fp] > 254 )
67  {
68  fprintf(stderr, "ERROR: Only 255 unicodes/glyph permitted!\n");
69  exit(EX_DATAERR);
70  }
71 
72  unitable[fp][unicount[fp]] = un;
73  unicount[fp]++;
74  }
75 
76  /* otherwise: ignore */
77 }
78 
79 int main(int argc, char *argv[])
80 {
81  FILE *ctbl;
82  char *tblname;
83  char buffer[65536];
84  int fontlen;
85  int i, nuni, nent;
86  int fp0, fp1, un0, un1;
87  char *p, *p1;
88 
89  if ( argc < 2 || argc > 5 )
90  usage(argv[0]);
91 
92  if ( !strcmp(argv[1],"-") )
93  {
94  ctbl = stdin;
95  tblname = "stdin";
96  }
97  else
98  {
99  ctbl = fopen(tblname = argv[1], "r");
100  if ( !ctbl )
101  {
102  perror(tblname);
103  exit(EX_NOINPUT);
104  }
105  }
106 
107  /* For now we assume the default font is always 256 characters. */
108  fontlen = 256;
109 
110  /* Initialize table */
111 
112  for ( i = 0 ; i < fontlen ; i++ )
113  unicount[i] = 0;
114 
115  /* Now we come to the tricky part. Parse the input table. */
116 
117  while ( fgets(buffer, sizeof(buffer), ctbl) != NULL )
118  {
119  if ( (p = strchr(buffer, '\n')) != NULL )
120  *p = '\0';
121  else
122  fprintf(stderr, "%s: Warning: line too long\n", tblname);
123 
124  p = buffer;
125 
126 /*
127  * Syntax accepted:
128  * <fontpos> <unicode> <unicode> ...
129  * <range> idem
130  * <range> <unicode range>
131  *
132  * where <range> ::= <fontpos>-<fontpos>
133  * and <unicode> ::= U+<h><h><h><h>
134  * and <h> ::= <hexadecimal digit>
135  */
136 
137  while (*p == ' ' || *p == '\t')
138  p++;
139  if (!*p || *p == '#')
140  continue; /* skip comment or blank line */
141 
142  fp0 = strtol(p, &p1, 0);
143  if (p1 == p)
144  {
145  fprintf(stderr, "Bad input line: %s\n", buffer);
146  exit(EX_DATAERR);
147  }
148  p = p1;
149 
150  while (*p == ' ' || *p == '\t')
151  p++;
152  if (*p == '-')
153  {
154  p++;
155  fp1 = strtol(p, &p1, 0);
156  if (p1 == p)
157  {
158  fprintf(stderr, "Bad input line: %s\n", buffer);
159  exit(EX_DATAERR);
160  }
161  p = p1;
162  }
163  else
164  fp1 = 0;
165 
166  if ( fp0 < 0 || fp0 >= fontlen )
167  {
168  fprintf(stderr,
169  "%s: Glyph number (0x%x) larger than font length\n",
170  tblname, fp0);
171  exit(EX_DATAERR);
172  }
173  if ( fp1 && (fp1 < fp0 || fp1 >= fontlen) )
174  {
175  fprintf(stderr,
176  "%s: Bad end of range (0x%x)\n",
177  tblname, fp1);
178  exit(EX_DATAERR);
179  }
180 
181  if (fp1)
182  {
183  /* we have a range; expect the word "idem" or a Unicode range of the
184  same length */
185  while (*p == ' ' || *p == '\t')
186  p++;
187  if (!strncmp(p, "idem", 4))
188  {
189  for (i=fp0; i<=fp1; i++)
190  addpair(i,i);
191  p += 4;
192  }
193  else
194  {
195  un0 = getunicode(&p);
196  while (*p == ' ' || *p == '\t')
197  p++;
198  if (*p != '-')
199  {
200  fprintf(stderr,
201 "%s: Corresponding to a range of font positions, there should be a Unicode range\n",
202  tblname);
203  exit(EX_DATAERR);
204  }
205  p++;
206  un1 = getunicode(&p);
207  if (un0 < 0 || un1 < 0)
208  {
209  fprintf(stderr,
210 "%s: Bad Unicode range corresponding to font position range 0x%x-0x%x\n",
211  tblname, fp0, fp1);
212  exit(EX_DATAERR);
213  }
214  if (un1 - un0 != fp1 - fp0)
215  {
216  fprintf(stderr,
217 "%s: Unicode range U+%x-U+%x not of the same length as font position range 0x%x-0x%x\n",
218  tblname, un0, un1, fp0, fp1);
219  exit(EX_DATAERR);
220  }
221  for(i=fp0; i<=fp1; i++)
222  addpair(i,un0-fp0+i);
223  }
224  }
225  else
226  {
227  /* no range; expect a list of unicode values for a single font position */
228 
229  while ( (un0 = getunicode(&p)) >= 0 )
230  addpair(fp0, un0);
231  }
232  while (*p == ' ' || *p == '\t')
233  p++;
234  if (*p && *p != '#')
235  fprintf(stderr, "%s: trailing junk (%s) ignored\n", tblname, p);
236  }
237 
238  /* Okay, we hit EOF, now output hash table */
239 
240  fclose(ctbl);
241 
242 
243  /* Compute total size of Unicode list */
244  nuni = 0;
245  for ( i = 0 ; i < fontlen ; i++ )
246  nuni += unicount[i];
247 
248  printf("\
249 /*\n\
250  * Do not edit this file; it was automatically generated by\n\
251  *\n\
252  * conmakehash %s > [this file]\n\
253  *\n\
254  */\n\
255 \n\
256 #include <linux/types.h>\n\
257 \n\
258 u8 dfont_unicount[%d] = \n\
259 {\n\t", argv[1], fontlen);
260 
261  for ( i = 0 ; i < fontlen ; i++ )
262  {
263  printf("%3d", unicount[i]);
264  if ( i == fontlen-1 )
265  printf("\n};\n");
266  else if ( i % 8 == 7 )
267  printf(",\n\t");
268  else
269  printf(", ");
270  }
271 
272  printf("\nu16 dfont_unitable[%d] = \n{\n\t", nuni);
273 
274  fp0 = 0;
275  nent = 0;
276  for ( i = 0 ; i < nuni ; i++ )
277  {
278  while ( nent >= unicount[fp0] )
279  {
280  fp0++;
281  nent = 0;
282  }
283  printf("0x%04x", unitable[fp0][nent++]);
284  if ( i == nuni-1 )
285  printf("\n};\n");
286  else if ( i % 8 == 7 )
287  printf(",\n\t");
288  else
289  printf(", ");
290  }
291 
292  exit(EX_OK);
293 }