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