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 <libgen.h> 15 #include <linux/limits.h> 16 #include <stdio.h> 17 #include <stdlib.h> 18 #include <sysexits.h> 19 #include <string.h> 20 #include <ctype.h> 21 22 #define MAX_FONTLEN 256 23 24 typedef unsigned short unicode; 25 26 static void usage(char *argv0) 27 { 28 fprintf(stderr, "Usage: \n" 29 " %s chartable [hashsize] [hashstep] [maxhashlevel]\n", argv0); 30 exit(EX_USAGE); 31 } 32 33 static int getunicode(char **p0) 34 { 35 char *p = *p0; 36 37 while (*p == ' ' || *p == '\t') 38 p++; 39 if (*p != 'U' || p[1] != '+' || 40 !isxdigit(p[2]) || !isxdigit(p[3]) || !isxdigit(p[4]) || 41 !isxdigit(p[5]) || isxdigit(p[6])) 42 return -1; 43 *p0 = p+6; 44 return strtol(p+2,0,16); 45 } 46 47 unicode unitable[MAX_FONTLEN][255]; 48 /* Massive overkill, but who cares? */ 49 int unicount[MAX_FONTLEN]; 50 51 static void addpair(int fp, int un) 52 { 53 int i; 54 55 if ( un <= 0xfffe ) 56 { 57 /* Check it isn't a duplicate */ 58 59 for ( i = 0 ; i < unicount[fp] ; i++ ) 60 if ( unitable[fp][i] == un ) 61 return; 62 63 /* Add to list */ 64 65 if ( unicount[fp] > 254 ) 66 { 67 fprintf(stderr, "ERROR: Only 255 unicodes/glyph permitted!\n"); 68 exit(EX_DATAERR); 69 } 70 71 unitable[fp][unicount[fp]] = un; 72 unicount[fp]++; 73 } 74 75 /* otherwise: ignore */ 76 } 77 78 int main(int argc, char *argv[]) 79 { 80 FILE *ctbl; 81 const char *tblname; 82 char base_tblname[PATH_MAX]; 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 strncpy(base_tblname, tblname, PATH_MAX); 249 base_tblname[PATH_MAX - 1] = 0; 250 printf("\ 251 /*\n\ 252 * Do not edit this file; it was automatically generated by\n\ 253 *\n\ 254 * conmakehash %s > [this file]\n\ 255 *\n\ 256 */\n\ 257 \n\ 258 #include <linux/types.h>\n\ 259 \n\ 260 u8 dfont_unicount[%d] = \n\ 261 {\n\t", basename(base_tblname), fontlen); 262 263 for ( i = 0 ; i < fontlen ; i++ ) 264 { 265 printf("%3d", unicount[i]); 266 if ( i == fontlen-1 ) 267 printf("\n};\n"); 268 else if ( i % 8 == 7 ) 269 printf(",\n\t"); 270 else 271 printf(", "); 272 } 273 274 printf("\nu16 dfont_unitable[%d] = \n{\n\t", nuni); 275 276 fp0 = 0; 277 nent = 0; 278 for ( i = 0 ; i < nuni ; i++ ) 279 { 280 while ( nent >= unicount[fp0] ) 281 { 282 fp0++; 283 nent = 0; 284 } 285 printf("0x%04x", unitable[fp0][nent++]); 286 if ( i == nuni-1 ) 287 printf("\n};\n"); 288 else if ( i % 8 == 7 ) 289 printf(",\n\t"); 290 else 291 printf(", "); 292 } 293 294 exit(EX_OK); 295 } 296