conmakehash.c 5.8 KB

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