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 char *tblname; 80 char buffer[65536]; 81 int fontlen; 82 int i, nuni, nent; 83 int fp0, fp1, un0, un1; 84 char *p, *p1; 85 86 if ( argc < 2 || argc > 5 ) 87 usage(argv[0]); 88 89 if ( !strcmp(argv[1],"-") ) 90 { 91 ctbl = stdin; 92 tblname = "stdin"; 93 } 94 else 95 { 96 ctbl = fopen(tblname = argv[1], "r"); 97 if ( !ctbl ) 98 { 99 perror(tblname); 100 exit(EX_NOINPUT); 101 } 102 } 103 104 /* For now we assume the default font is always 256 characters. */ 105 fontlen = 256; 106 107 /* Initialize table */ 108 109 for ( i = 0 ; i < fontlen ; i++ ) 110 unicount[i] = 0; 111 112 /* Now we come to the tricky part. Parse the input table. */ 113 114 while ( fgets(buffer, sizeof(buffer), ctbl) != NULL ) 115 { 116 if ( (p = strchr(buffer, '\n')) != NULL ) 117 *p = '\0'; 118 else 119 fprintf(stderr, "%s: Warning: line too long\n", tblname); 120 121 p = buffer; 122 123 /* 124 * Syntax accepted: 125 * <fontpos> <unicode> <unicode> ... 126 * <range> idem 127 * <range> <unicode range> 128 * 129 * where <range> ::= <fontpos>-<fontpos> 130 * and <unicode> ::= U+<h><h><h><h> 131 * and <h> ::= <hexadecimal digit> 132 */ 133 134 while (*p == ' ' || *p == '\t') 135 p++; 136 if (!*p || *p == '#') 137 continue; /* skip comment or blank line */ 138 139 fp0 = strtol(p, &p1, 0); 140 if (p1 == p) 141 { 142 fprintf(stderr, "Bad input line: %s\n", buffer); 143 exit(EX_DATAERR); 144 } 145 p = p1; 146 147 while (*p == ' ' || *p == '\t') 148 p++; 149 if (*p == '-') 150 { 151 p++; 152 fp1 = strtol(p, &p1, 0); 153 if (p1 == p) 154 { 155 fprintf(stderr, "Bad input line: %s\n", buffer); 156 exit(EX_DATAERR); 157 } 158 p = p1; 159 } 160 else 161 fp1 = 0; 162 163 if ( fp0 < 0 || fp0 >= fontlen ) 164 { 165 fprintf(stderr, 166 "%s: Glyph number (0x%x) larger than font length\n", 167 tblname, fp0); 168 exit(EX_DATAERR); 169 } 170 if ( fp1 && (fp1 < fp0 || fp1 >= fontlen) ) 171 { 172 fprintf(stderr, 173 "%s: Bad end of range (0x%x)\n", 174 tblname, fp1); 175 exit(EX_DATAERR); 176 } 177 178 if (fp1) 179 { 180 /* we have a range; expect the word "idem" or a Unicode range of the 181 same length */ 182 while (*p == ' ' || *p == '\t') 183 p++; 184 if (!strncmp(p, "idem", 4)) 185 { 186 for (i=fp0; i<=fp1; i++) 187 addpair(i,i); 188 p += 4; 189 } 190 else 191 { 192 un0 = getunicode(&p); 193 while (*p == ' ' || *p == '\t') 194 p++; 195 if (*p != '-') 196 { 197 fprintf(stderr, 198 "%s: Corresponding to a range of font positions, there should be a Unicode range\n", 199 tblname); 200 exit(EX_DATAERR); 201 } 202 p++; 203 un1 = getunicode(&p); 204 if (un0 < 0 || un1 < 0) 205 { 206 fprintf(stderr, 207 "%s: Bad Unicode range corresponding to font position range 0x%x-0x%x\n", 208 tblname, fp0, fp1); 209 exit(EX_DATAERR); 210 } 211 if (un1 - un0 != fp1 - fp0) 212 { 213 fprintf(stderr, 214 "%s: Unicode range U+%x-U+%x not of the same length as font position range 0x%x-0x%x\n", 215 tblname, un0, un1, fp0, fp1); 216 exit(EX_DATAERR); 217 } 218 for(i=fp0; i<=fp1; i++) 219 addpair(i,un0-fp0+i); 220 } 221 } 222 else 223 { 224 /* no range; expect a list of unicode values for a single font position */ 225 226 while ( (un0 = getunicode(&p)) >= 0 ) 227 addpair(fp0, un0); 228 } 229 while (*p == ' ' || *p == '\t') 230 p++; 231 if (*p && *p != '#') 232 fprintf(stderr, "%s: trailing junk (%s) ignored\n", tblname, p); 233 } 234 235 /* Okay, we hit EOF, now output hash table */ 236 237 fclose(ctbl); 238 239 240 /* Compute total size of Unicode list */ 241 nuni = 0; 242 for ( i = 0 ; i < fontlen ; i++ ) 243 nuni += unicount[i]; 244 245 printf("\ 246 /*\n\ 247 * Do not edit this file; it was automatically generated by\n\ 248 *\n\ 249 * conmakehash %s > [this file]\n\ 250 *\n\ 251 */\n\ 252 \n\ 253 #include <linux/types.h>\n\ 254 \n\ 255 u8 dfont_unicount[%d] = \n\ 256 {\n\t", argv[1], fontlen); 257 258 for ( i = 0 ; i < fontlen ; i++ ) 259 { 260 printf("%3d", unicount[i]); 261 if ( i == fontlen-1 ) 262 printf("\n};\n"); 263 else if ( i % 8 == 7 ) 264 printf(",\n\t"); 265 else 266 printf(", "); 267 } 268 269 printf("\nu16 dfont_unitable[%d] = \n{\n\t", nuni); 270 271 fp0 = 0; 272 nent = 0; 273 for ( i = 0 ; i < nuni ; i++ ) 274 { 275 while ( nent >= unicount[fp0] ) 276 { 277 fp0++; 278 nent = 0; 279 } 280 printf("0x%04x", unitable[fp0][nent++]); 281 if ( i == nuni-1 ) 282 printf("\n};\n"); 283 else if ( i % 8 == 7 ) 284 printf(",\n\t"); 285 else 286 printf(", "); 287 } 288 289 exit(EX_OK); 290 } 291