linux/scripts/conmakehash.c
<<
>>
Prefs
   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
  22typedef unsigned short unicode;
  23
  24static void usage(char *argv0)
  25{
  26  fprintf(stderr, "Usage: \n"
  27         "        %s chartable [hashsize] [hashstep] [maxhashlevel]\n", argv0);
  28  exit(EX_USAGE);
  29}
  30
  31static 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
  45unicode unitable[MAX_FONTLEN][255];
  46                                /* Massive overkill, but who cares? */
  47int unicount[MAX_FONTLEN];
  48
  49static 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
  76int 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\
 255u8 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