root/scripts/conmakehash.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. usage
  2. getunicode
  3. addpair
  4. main

   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 }

/* [<][>][^][v][top][bottom][index][help] */