• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  
usage(char * argv0)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  
getunicode(char ** p0)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  
48  unicode unitable[MAX_FONTLEN][255];
49  				/* Massive overkill, but who cares? */
50  int unicount[MAX_FONTLEN];
51  
addpair(int fp,int un)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  
main(int argc,char * argv[])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  }
294