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