root/drivers/char/conmakehash.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

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

   1 /*
   2  * conmakehash.c
   3  *
   4  * Create a pre-initialized kernel Unicode hash table
   5  *
   6  * Copyright (C) 1995 H. Peter Anvin
   7  *
   8  * This program may be freely copied under the terms of the GNU
   9  * General Public License (GPL), version 2, or at your option
  10  * any later version.
  11  *
  12  */
  13 
  14 #include <stdio.h>
  15 #include <stdlib.h>
  16 #include <sysexits.h>
  17 #include <string.h>
  18 #include <ctype.h>
  19 
  20 typedef unsigned short unicode;
  21 
  22 struct unipair
  23 {
  24   unsigned short glyph;         /* Glyph code */
  25   unicode uc;                   /* Unicode listed */
  26 };
  27 
  28 void usage(char *argv0)
     /* [previous][next][first][last][top][bottom][index][help] */
  29 {
  30   fprintf(stderr, "Usage: \n"
  31          "        %s chartable [hashsize] [hashstep] [maxhashlevel]\n", argv0);
  32   exit(EX_USAGE);
  33 }
  34 
  35 int getunicode(char **p0)
     /* [previous][next][first][last][top][bottom][index][help] */
  36 {
  37   char *p = *p0;
  38 
  39   while (*p == ' ' || *p == '\t')
  40     p++;
  41   if (*p != 'U' || p[1] != '+' ||
  42       !isxdigit(p[2]) || !isxdigit(p[3]) || !isxdigit(p[4]) ||
  43       !isxdigit(p[5]) || isxdigit(p[6]))
  44     return -1;
  45   *p0 = p+6;
  46   return strtol(p+2,0,16);
  47 }
  48 
  49 struct unipair *hashtable;
  50 int hashsize = 641;             /* Size of hash table */
  51 int hashstep = 189;             /* Hash stepping */
  52 int maxhashlevel = 6;           /* Maximum hash depth */
  53 int hashlevel = 0;              /* Actual hash depth */
  54 
  55 void addpair(int fp, int un)
     /* [previous][next][first][last][top][bottom][index][help] */
  56 {
  57   int i, lct;
  58   unicode hu;
  59 
  60   if ( un <= 0xFFFE )
  61     {
  62       /* Add to hash table */
  63 
  64       i = un % hashsize;
  65       lct = 1;
  66       
  67       while ( (hu = hashtable[i].uc) != 0xffff && hu != un )
  68         {
  69           if (lct++ >= maxhashlevel)
  70             {
  71               fprintf(stderr, "ERROR: Hash table overflow\n");
  72               exit(EX_DATAERR);
  73             }
  74           i += hashstep;
  75           if ( i >= hashsize )
  76             i -= hashsize;
  77         }
  78       if ( lct > hashlevel )
  79         hashlevel = lct;
  80 
  81       hashtable[i].uc = un;
  82       hashtable[i].glyph = fp;
  83     }
  84 
  85   /* otherwise: ignore */
  86 }
  87 
  88 int main(int argc, char *argv[])
     /* [previous][next][first][last][top][bottom][index][help] */
  89 {
  90   FILE *ctbl;
  91   char *tblname;
  92   char buffer[65536];
  93   int fontlen;
  94   int i;
  95   int fp0, fp1, un0, un1;
  96   char *p, *p1;
  97 
  98   if ( argc < 2 || argc > 5 )
  99     usage(argv[0]);
 100 
 101   if ( !strcmp(argv[1],"-") )
 102     {
 103       ctbl = stdin;
 104       tblname = "stdin";
 105     }
 106   else
 107     {
 108       ctbl = fopen(tblname = argv[1], "r");
 109       if ( !ctbl )
 110         {
 111           perror(tblname);
 112           exit(EX_NOINPUT);
 113         }
 114     }
 115 
 116   if ( argc > 2 )
 117     {
 118       hashsize = atoi(argv[2]);
 119       if ( hashsize < 256 || hashsize > 2048 )
 120         {
 121           fprintf(stderr, "Illegal hash size\n");
 122           exit(EX_USAGE);
 123         }
 124     }
 125   
 126   if ( argc > 3 )
 127     {
 128       hashstep = atoi(argv[3]) % hashsize;
 129       if ( hashstep < 0 ) hashstep += hashsize;
 130       if ( hashstep < 16 || hashstep >= hashsize-16 )
 131         {
 132           fprintf(stderr, "Bad hash step\n");
 133           exit(EX_USAGE);
 134         }
 135     }
 136 
 137   /* Warn the user in case the hashstep and hashsize are not relatively
 138      prime -- this algorithm could be massively improved */
 139 
 140   for ( i = hashstep ; i > 1 ; i-- )
 141     {
 142       if ( hashstep % i == 0 && hashsize % i == 0 )
 143         break;                  /* Found GCD */
 144     }
 145 
 146   if ( i > 1 )
 147     {
 148       fprintf(stderr,
 149       "WARNING: hashsize and hashstep have common factors (gcd = %d)\n", i);
 150     }
 151 
 152   if ( argc > 4 )
 153     {
 154       maxhashlevel = atoi(argv[4]);
 155       if ( maxhashlevel < 1 || maxhashlevel > hashsize )
 156         {
 157           fprintf(stderr, "Illegal max hash level\n");
 158           exit(EX_USAGE);
 159         }
 160     }
 161 
 162   /* For now we assume the default font is always 256 characters */
 163   fontlen = 256;
 164 
 165   /* Initialize hash table */
 166 
 167   hashtable = malloc(hashsize * sizeof(struct unipair));
 168   if ( !hashtable )
 169     {
 170       fprintf(stderr, "Could not allocate memory for hash table\n");
 171       exit(EX_OSERR);
 172     }
 173 
 174   for ( i = 0 ; i < hashsize ; i++ )
 175     {
 176       hashtable[i].uc = 0xffff;
 177       hashtable[i].glyph = 0;
 178     }
 179 
 180   /* Now we come to the tricky part.  Parse the input table. */
 181 
 182   while ( fgets(buffer, sizeof(buffer), ctbl) != NULL )
 183     {
 184       if ( (p = strchr(buffer, '\n')) != NULL )
 185         *p = '\0';
 186       else
 187         fprintf(stderr, "%s: Warning: line too long\n", tblname);
 188 
 189       p = buffer;
 190 
 191 /*
 192  * Syntax accepted:
 193  *      <fontpos>       <unicode> <unicode> ...
 194  *      <range>         idem
 195  *      <range>         <unicode range>
 196  *
 197  * where <range> ::= <fontpos>-<fontpos>
 198  * and <unicode> ::= U+<h><h><h><h>
 199  * and <h> ::= <hexadecimal digit>
 200  */
 201 
 202       while (*p == ' ' || *p == '\t')
 203         p++;
 204       if (!*p || *p == '#')
 205         continue;       /* skip comment or blank line */
 206 
 207       fp0 = strtol(p, &p1, 0);
 208       if (p1 == p)
 209         {
 210           fprintf(stderr, "Bad input line: %s\n", buffer);
 211           exit(EX_DATAERR);
 212         }
 213       p = p1;
 214 
 215       while (*p == ' ' || *p == '\t')
 216         p++;
 217       if (*p == '-')
 218         {
 219           p++;
 220           fp1 = strtol(p, &p1, 0);
 221           if (p1 == p)
 222             {
 223               fprintf(stderr, "Bad input line: %s\n", buffer);
 224               exit(EX_DATAERR);
 225             }
 226           p = p1;
 227         }
 228       else
 229         fp1 = 0;
 230 
 231       if ( fp0 < 0 || fp0 >= fontlen )
 232         {
 233             fprintf(stderr,
 234                     "%s: Glyph number (0x%x) larger than font length\n",
 235                     tblname, fp0);
 236             exit(EX_DATAERR);
 237         }
 238       if ( fp1 && (fp1 < fp0 || fp1 >= fontlen) )
 239         {
 240             fprintf(stderr,
 241                     "%s: Bad end of range (0x%x)\n",
 242                     tblname, fp1);
 243             exit(EX_DATAERR);
 244         }
 245 
 246       if (fp1)
 247         {
 248           /* we have a range; expect the word "idem" or a Unicode range of the
 249              same length */
 250           while (*p == ' ' || *p == '\t')
 251             p++;
 252           if (!strncmp(p, "idem", 4))
 253             {
 254               for (i=fp0; i<=fp1; i++)
 255                 addpair(i,i);
 256               p += 4;
 257             }
 258           else
 259             {
 260               un0 = getunicode(&p);
 261               while (*p == ' ' || *p == '\t')
 262                 p++;
 263               if (*p != '-')
 264                 {
 265                   fprintf(stderr,
 266 "%s: Corresponding to a range of font positions, there should be a Unicode range\n",
 267                           tblname);
 268                   exit(EX_DATAERR);
 269                 }
 270               p++;
 271               un1 = getunicode(&p);
 272               if (un0 < 0 || un1 < 0)
 273                 {
 274                   fprintf(stderr,
 275 "%s: Bad Unicode range corresponding to font position range 0x%x-0x%x\n",
 276                           tblname, fp0, fp1);
 277                   exit(EX_DATAERR);
 278                 }
 279               if (un1 - un0 != fp1 - fp0)
 280                 {
 281                   fprintf(stderr,
 282 "%s: Unicode range U+%x-U+%x not of the same length as font position range 0x%x-0x%x\n",
 283                           tblname, un0, un1, fp0, fp1);
 284                   exit(EX_DATAERR);
 285                 }
 286               for(i=fp0; i<=fp1; i++)
 287                 addpair(i,un0-fp0+i);
 288             }
 289         }
 290       else
 291         {
 292             /* no range; expect a list of unicode values for a single font position */
 293 
 294             while ( (un0 = getunicode(&p)) >= 0 )
 295               addpair(fp0, un0);
 296         }
 297       while (*p == ' ' || *p == '\t')
 298         p++;
 299       if (*p && *p != '#')
 300         fprintf(stderr, "%s: trailing junk (%s) ignored\n", tblname, p);
 301     }
 302 
 303   /* Okay, we hit EOF, now output hash table */
 304   
 305   fclose(ctbl);
 306   
 307   printf("\
 308 /*\n\
 309  * uni_hash_tbl.h\n\
 310  *\n\
 311  * Do not edit this file; it was automatically generated by\n\
 312  *\n\
 313  * conmakehash %s %d %d %d > uni_hash_tbl.h\n\
 314  *\n\
 315  */\n\
 316 \n\
 317 #include <linux/kd.h>\n\
 318 \n\
 319 #define HASHSIZE      %d\n\
 320 #define HASHSTEP      %d\n\
 321 #define MAXHASHLEVEL  %d\n\
 322 #define DEF_HASHLEVEL %d\n\
 323 \n\
 324 static unsigned int hashsize     = HASHSIZE;\n\
 325 static unsigned int hashstep     = HASHSTEP;\n\
 326 static unsigned int maxhashlevel = MAXHASHLEVEL;\n\
 327 static unsigned int hashlevel    = DEF_HASHLEVEL;\n\
 328 \n\
 329 static struct unipair hashtable[HASHSIZE] =\n\
 330 {\n\t", argv[1], hashsize, hashstep, maxhashlevel,
 331          hashsize, hashstep, maxhashlevel, hashlevel);
 332   
 333   for ( i = 0 ; i < hashsize ; i++ )
 334     {
 335       printf("{0x%04x,0x%02x}", hashtable[i].uc, hashtable[i].glyph);
 336       if ( i == hashsize-1 )
 337         printf("\n};\n");
 338       else if ( i % 4 == 3 )
 339         printf(",\n\t");
 340       else
 341         printf(", ");
 342     }
 343 
 344   printf("\n\
 345 #ifdef NEED_BACKUP_HASHTABLE\n\
 346 \n\
 347 static const struct unipair backup_hashtable[HASHSIZE] = \n{\n\t");
 348  
 349   for ( i = 0 ; i < hashsize ; i++ )
 350     {
 351       printf("{0x%04x,0x%02x}", hashtable[i].uc, hashtable[i].glyph);
 352       if ( i == hashsize-1 )
 353         printf("\n};\n#endif\n");
 354       else if ( i % 4 == 3 )
 355         printf(",\n\t");
 356       else
 357         printf(", ");
 358     }
 359 
 360   exit(EX_OK);
 361 }

/* [previous][next][first][last][top][bottom][index][help] */