Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * conmakehash.c
0004  *
0005  * Create arrays for initializing the kernel folded tables (using a hash
0006  * table turned out to be to limiting...)  Unfortunately we can't simply
0007  * preinitialize the tables at compile time since kfree() cannot accept
0008  * memory not allocated by kmalloc(), and doing our own memory management
0009  * just for this seems like massive overkill.
0010  *
0011  * Copyright (C) 1995-1997 H. Peter Anvin
0012  */
0013 
0014 #include <stdio.h>
0015 #include <stdlib.h>
0016 #include <sysexits.h>
0017 #include <string.h>
0018 #include <ctype.h>
0019 
0020 #define MAX_FONTLEN 256
0021 
0022 typedef unsigned short unicode;
0023 
0024 static void usage(char *argv0)
0025 {
0026   fprintf(stderr, "Usage: \n"
0027          "        %s chartable [hashsize] [hashstep] [maxhashlevel]\n", argv0);
0028   exit(EX_USAGE);
0029 }
0030 
0031 static int getunicode(char **p0)
0032 {
0033   char *p = *p0;
0034 
0035   while (*p == ' ' || *p == '\t')
0036     p++;
0037   if (*p != 'U' || p[1] != '+' ||
0038       !isxdigit(p[2]) || !isxdigit(p[3]) || !isxdigit(p[4]) ||
0039       !isxdigit(p[5]) || isxdigit(p[6]))
0040     return -1;
0041   *p0 = p+6;
0042   return strtol(p+2,0,16);
0043 }
0044 
0045 unicode unitable[MAX_FONTLEN][255];
0046                 /* Massive overkill, but who cares? */
0047 int unicount[MAX_FONTLEN];
0048 
0049 static void addpair(int fp, int un)
0050 {
0051   int i;
0052 
0053   if ( un <= 0xfffe )
0054     {
0055       /* Check it isn't a duplicate */
0056 
0057       for ( i = 0 ; i < unicount[fp] ; i++ )
0058     if ( unitable[fp][i] == un )
0059       return;
0060 
0061       /* Add to list */
0062 
0063       if ( unicount[fp] > 254 )
0064     {
0065       fprintf(stderr, "ERROR: Only 255 unicodes/glyph permitted!\n");
0066       exit(EX_DATAERR);
0067     }
0068 
0069       unitable[fp][unicount[fp]] = un;
0070       unicount[fp]++;
0071     }
0072 
0073   /* otherwise: ignore */
0074 }
0075 
0076 int main(int argc, char *argv[])
0077 {
0078   FILE *ctbl;
0079   char *tblname;
0080   char buffer[65536];
0081   int fontlen;
0082   int i, nuni, nent;
0083   int fp0, fp1, un0, un1;
0084   char *p, *p1;
0085 
0086   if ( argc < 2 || argc > 5 )
0087     usage(argv[0]);
0088 
0089   if ( !strcmp(argv[1],"-") )
0090     {
0091       ctbl = stdin;
0092       tblname = "stdin";
0093     }
0094   else
0095     {
0096       ctbl = fopen(tblname = argv[1], "r");
0097       if ( !ctbl )
0098     {
0099       perror(tblname);
0100       exit(EX_NOINPUT);
0101     }
0102     }
0103 
0104   /* For now we assume the default font is always 256 characters. */
0105   fontlen = 256;
0106 
0107   /* Initialize table */
0108 
0109   for ( i = 0 ; i < fontlen ; i++ )
0110     unicount[i] = 0;
0111 
0112   /* Now we come to the tricky part.  Parse the input table. */
0113 
0114   while ( fgets(buffer, sizeof(buffer), ctbl) != NULL )
0115     {
0116       if ( (p = strchr(buffer, '\n')) != NULL )
0117     *p = '\0';
0118       else
0119     fprintf(stderr, "%s: Warning: line too long\n", tblname);
0120 
0121       p = buffer;
0122 
0123 /*
0124  * Syntax accepted:
0125  *  <fontpos>   <unicode> <unicode> ...
0126  *  <range>     idem
0127  *  <range>     <unicode range>
0128  *
0129  * where <range> ::= <fontpos>-<fontpos>
0130  * and <unicode> ::= U+<h><h><h><h>
0131  * and <h> ::= <hexadecimal digit>
0132  */
0133 
0134       while (*p == ' ' || *p == '\t')
0135     p++;
0136       if (!*p || *p == '#')
0137     continue;   /* skip comment or blank line */
0138 
0139       fp0 = strtol(p, &p1, 0);
0140       if (p1 == p)
0141     {
0142       fprintf(stderr, "Bad input line: %s\n", buffer);
0143       exit(EX_DATAERR);
0144         }
0145       p = p1;
0146 
0147       while (*p == ' ' || *p == '\t')
0148     p++;
0149       if (*p == '-')
0150     {
0151       p++;
0152       fp1 = strtol(p, &p1, 0);
0153       if (p1 == p)
0154         {
0155           fprintf(stderr, "Bad input line: %s\n", buffer);
0156           exit(EX_DATAERR);
0157         }
0158       p = p1;
0159         }
0160       else
0161     fp1 = 0;
0162 
0163       if ( fp0 < 0 || fp0 >= fontlen )
0164     {
0165         fprintf(stderr,
0166             "%s: Glyph number (0x%x) larger than font length\n",
0167             tblname, fp0);
0168         exit(EX_DATAERR);
0169     }
0170       if ( fp1 && (fp1 < fp0 || fp1 >= fontlen) )
0171     {
0172         fprintf(stderr,
0173             "%s: Bad end of range (0x%x)\n",
0174             tblname, fp1);
0175         exit(EX_DATAERR);
0176     }
0177 
0178       if (fp1)
0179     {
0180       /* we have a range; expect the word "idem" or a Unicode range of the
0181          same length */
0182       while (*p == ' ' || *p == '\t')
0183         p++;
0184       if (!strncmp(p, "idem", 4))
0185         {
0186           for (i=fp0; i<=fp1; i++)
0187         addpair(i,i);
0188           p += 4;
0189         }
0190       else
0191         {
0192           un0 = getunicode(&p);
0193           while (*p == ' ' || *p == '\t')
0194         p++;
0195           if (*p != '-')
0196         {
0197           fprintf(stderr,
0198 "%s: Corresponding to a range of font positions, there should be a Unicode range\n",
0199               tblname);
0200           exit(EX_DATAERR);
0201             }
0202           p++;
0203           un1 = getunicode(&p);
0204           if (un0 < 0 || un1 < 0)
0205         {
0206           fprintf(stderr,
0207 "%s: Bad Unicode range corresponding to font position range 0x%x-0x%x\n",
0208               tblname, fp0, fp1);
0209           exit(EX_DATAERR);
0210             }
0211           if (un1 - un0 != fp1 - fp0)
0212         {
0213           fprintf(stderr,
0214 "%s: Unicode range U+%x-U+%x not of the same length as font position range 0x%x-0x%x\n",
0215               tblname, un0, un1, fp0, fp1);
0216           exit(EX_DATAERR);
0217             }
0218           for(i=fp0; i<=fp1; i++)
0219         addpair(i,un0-fp0+i);
0220         }
0221         }
0222       else
0223     {
0224         /* no range; expect a list of unicode values for a single font position */
0225 
0226         while ( (un0 = getunicode(&p)) >= 0 )
0227           addpair(fp0, un0);
0228     }
0229       while (*p == ' ' || *p == '\t')
0230     p++;
0231       if (*p && *p != '#')
0232     fprintf(stderr, "%s: trailing junk (%s) ignored\n", tblname, p);
0233     }
0234 
0235   /* Okay, we hit EOF, now output hash table */
0236 
0237   fclose(ctbl);
0238 
0239 
0240   /* Compute total size of Unicode list */
0241   nuni = 0;
0242   for ( i = 0 ; i < fontlen ; i++ )
0243     nuni += unicount[i];
0244 
0245   printf("\
0246 /*\n\
0247  * Do not edit this file; it was automatically generated by\n\
0248  *\n\
0249  * conmakehash %s > [this file]\n\
0250  *\n\
0251  */\n\
0252 \n\
0253 #include <linux/types.h>\n\
0254 \n\
0255 u8 dfont_unicount[%d] = \n\
0256 {\n\t", argv[1], fontlen);
0257 
0258   for ( i = 0 ; i < fontlen ; i++ )
0259     {
0260       printf("%3d", unicount[i]);
0261       if ( i == fontlen-1 )
0262         printf("\n};\n");
0263       else if ( i % 8 == 7 )
0264         printf(",\n\t");
0265       else
0266         printf(", ");
0267     }
0268 
0269   printf("\nu16 dfont_unitable[%d] = \n{\n\t", nuni);
0270 
0271   fp0 = 0;
0272   nent = 0;
0273   for ( i = 0 ; i < nuni ; i++ )
0274     {
0275       while ( nent >= unicount[fp0] )
0276     {
0277       fp0++;
0278       nent = 0;
0279     }
0280       printf("0x%04x", unitable[fp0][nent++]);
0281       if ( i == nuni-1 )
0282          printf("\n};\n");
0283        else if ( i % 8 == 7 )
0284          printf(",\n\t");
0285        else
0286          printf(", ");
0287     }
0288 
0289   exit(EX_OK);
0290 }