18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * conmakehash.c
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Create arrays for initializing the kernel folded tables (using a hash
68c2ecf20Sopenharmony_ci * table turned out to be to limiting...)  Unfortunately we can't simply
78c2ecf20Sopenharmony_ci * preinitialize the tables at compile time since kfree() cannot accept
88c2ecf20Sopenharmony_ci * memory not allocated by kmalloc(), and doing our own memory management
98c2ecf20Sopenharmony_ci * just for this seems like massive overkill.
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * Copyright (C) 1995-1997 H. Peter Anvin
128c2ecf20Sopenharmony_ci */
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include <stdio.h>
158c2ecf20Sopenharmony_ci#include <stdlib.h>
168c2ecf20Sopenharmony_ci#include <sysexits.h>
178c2ecf20Sopenharmony_ci#include <string.h>
188c2ecf20Sopenharmony_ci#include <ctype.h>
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#define MAX_FONTLEN 256
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_citypedef unsigned short unicode;
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_cistatic void usage(char *argv0)
258c2ecf20Sopenharmony_ci{
268c2ecf20Sopenharmony_ci  fprintf(stderr, "Usage: \n"
278c2ecf20Sopenharmony_ci         "        %s chartable [hashsize] [hashstep] [maxhashlevel]\n", argv0);
288c2ecf20Sopenharmony_ci  exit(EX_USAGE);
298c2ecf20Sopenharmony_ci}
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_cistatic int getunicode(char **p0)
328c2ecf20Sopenharmony_ci{
338c2ecf20Sopenharmony_ci  char *p = *p0;
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci  while (*p == ' ' || *p == '\t')
368c2ecf20Sopenharmony_ci    p++;
378c2ecf20Sopenharmony_ci  if (*p != 'U' || p[1] != '+' ||
388c2ecf20Sopenharmony_ci      !isxdigit(p[2]) || !isxdigit(p[3]) || !isxdigit(p[4]) ||
398c2ecf20Sopenharmony_ci      !isxdigit(p[5]) || isxdigit(p[6]))
408c2ecf20Sopenharmony_ci    return -1;
418c2ecf20Sopenharmony_ci  *p0 = p+6;
428c2ecf20Sopenharmony_ci  return strtol(p+2,0,16);
438c2ecf20Sopenharmony_ci}
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ciunicode unitable[MAX_FONTLEN][255];
468c2ecf20Sopenharmony_ci				/* Massive overkill, but who cares? */
478c2ecf20Sopenharmony_ciint unicount[MAX_FONTLEN];
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_cistatic void addpair(int fp, int un)
508c2ecf20Sopenharmony_ci{
518c2ecf20Sopenharmony_ci  int i;
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci  if ( un <= 0xfffe )
548c2ecf20Sopenharmony_ci    {
558c2ecf20Sopenharmony_ci      /* Check it isn't a duplicate */
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci      for ( i = 0 ; i < unicount[fp] ; i++ )
588c2ecf20Sopenharmony_ci	if ( unitable[fp][i] == un )
598c2ecf20Sopenharmony_ci	  return;
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci      /* Add to list */
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci      if ( unicount[fp] > 254 )
648c2ecf20Sopenharmony_ci	{
658c2ecf20Sopenharmony_ci	  fprintf(stderr, "ERROR: Only 255 unicodes/glyph permitted!\n");
668c2ecf20Sopenharmony_ci	  exit(EX_DATAERR);
678c2ecf20Sopenharmony_ci	}
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci      unitable[fp][unicount[fp]] = un;
708c2ecf20Sopenharmony_ci      unicount[fp]++;
718c2ecf20Sopenharmony_ci    }
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci  /* otherwise: ignore */
748c2ecf20Sopenharmony_ci}
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ciint main(int argc, char *argv[])
778c2ecf20Sopenharmony_ci{
788c2ecf20Sopenharmony_ci  FILE *ctbl;
798c2ecf20Sopenharmony_ci  char *tblname;
808c2ecf20Sopenharmony_ci  char buffer[65536];
818c2ecf20Sopenharmony_ci  int fontlen;
828c2ecf20Sopenharmony_ci  int i, nuni, nent;
838c2ecf20Sopenharmony_ci  int fp0, fp1, un0, un1;
848c2ecf20Sopenharmony_ci  char *p, *p1;
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci  if ( argc < 2 || argc > 5 )
878c2ecf20Sopenharmony_ci    usage(argv[0]);
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci  if ( !strcmp(argv[1],"-") )
908c2ecf20Sopenharmony_ci    {
918c2ecf20Sopenharmony_ci      ctbl = stdin;
928c2ecf20Sopenharmony_ci      tblname = "stdin";
938c2ecf20Sopenharmony_ci    }
948c2ecf20Sopenharmony_ci  else
958c2ecf20Sopenharmony_ci    {
968c2ecf20Sopenharmony_ci      ctbl = fopen(tblname = argv[1], "r");
978c2ecf20Sopenharmony_ci      if ( !ctbl )
988c2ecf20Sopenharmony_ci	{
998c2ecf20Sopenharmony_ci	  perror(tblname);
1008c2ecf20Sopenharmony_ci	  exit(EX_NOINPUT);
1018c2ecf20Sopenharmony_ci	}
1028c2ecf20Sopenharmony_ci    }
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci  /* For now we assume the default font is always 256 characters. */
1058c2ecf20Sopenharmony_ci  fontlen = 256;
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci  /* Initialize table */
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci  for ( i = 0 ; i < fontlen ; i++ )
1108c2ecf20Sopenharmony_ci    unicount[i] = 0;
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci  /* Now we come to the tricky part.  Parse the input table. */
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci  while ( fgets(buffer, sizeof(buffer), ctbl) != NULL )
1158c2ecf20Sopenharmony_ci    {
1168c2ecf20Sopenharmony_ci      if ( (p = strchr(buffer, '\n')) != NULL )
1178c2ecf20Sopenharmony_ci	*p = '\0';
1188c2ecf20Sopenharmony_ci      else
1198c2ecf20Sopenharmony_ci	fprintf(stderr, "%s: Warning: line too long\n", tblname);
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci      p = buffer;
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci/*
1248c2ecf20Sopenharmony_ci * Syntax accepted:
1258c2ecf20Sopenharmony_ci *	<fontpos>	<unicode> <unicode> ...
1268c2ecf20Sopenharmony_ci *	<range>		idem
1278c2ecf20Sopenharmony_ci *	<range>		<unicode range>
1288c2ecf20Sopenharmony_ci *
1298c2ecf20Sopenharmony_ci * where <range> ::= <fontpos>-<fontpos>
1308c2ecf20Sopenharmony_ci * and <unicode> ::= U+<h><h><h><h>
1318c2ecf20Sopenharmony_ci * and <h> ::= <hexadecimal digit>
1328c2ecf20Sopenharmony_ci */
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci      while (*p == ' ' || *p == '\t')
1358c2ecf20Sopenharmony_ci	p++;
1368c2ecf20Sopenharmony_ci      if (!*p || *p == '#')
1378c2ecf20Sopenharmony_ci	continue;	/* skip comment or blank line */
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci      fp0 = strtol(p, &p1, 0);
1408c2ecf20Sopenharmony_ci      if (p1 == p)
1418c2ecf20Sopenharmony_ci	{
1428c2ecf20Sopenharmony_ci	  fprintf(stderr, "Bad input line: %s\n", buffer);
1438c2ecf20Sopenharmony_ci	  exit(EX_DATAERR);
1448c2ecf20Sopenharmony_ci        }
1458c2ecf20Sopenharmony_ci      p = p1;
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci      while (*p == ' ' || *p == '\t')
1488c2ecf20Sopenharmony_ci	p++;
1498c2ecf20Sopenharmony_ci      if (*p == '-')
1508c2ecf20Sopenharmony_ci	{
1518c2ecf20Sopenharmony_ci	  p++;
1528c2ecf20Sopenharmony_ci	  fp1 = strtol(p, &p1, 0);
1538c2ecf20Sopenharmony_ci	  if (p1 == p)
1548c2ecf20Sopenharmony_ci	    {
1558c2ecf20Sopenharmony_ci	      fprintf(stderr, "Bad input line: %s\n", buffer);
1568c2ecf20Sopenharmony_ci	      exit(EX_DATAERR);
1578c2ecf20Sopenharmony_ci	    }
1588c2ecf20Sopenharmony_ci	  p = p1;
1598c2ecf20Sopenharmony_ci        }
1608c2ecf20Sopenharmony_ci      else
1618c2ecf20Sopenharmony_ci	fp1 = 0;
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci      if ( fp0 < 0 || fp0 >= fontlen )
1648c2ecf20Sopenharmony_ci	{
1658c2ecf20Sopenharmony_ci	    fprintf(stderr,
1668c2ecf20Sopenharmony_ci		    "%s: Glyph number (0x%x) larger than font length\n",
1678c2ecf20Sopenharmony_ci		    tblname, fp0);
1688c2ecf20Sopenharmony_ci	    exit(EX_DATAERR);
1698c2ecf20Sopenharmony_ci	}
1708c2ecf20Sopenharmony_ci      if ( fp1 && (fp1 < fp0 || fp1 >= fontlen) )
1718c2ecf20Sopenharmony_ci	{
1728c2ecf20Sopenharmony_ci	    fprintf(stderr,
1738c2ecf20Sopenharmony_ci		    "%s: Bad end of range (0x%x)\n",
1748c2ecf20Sopenharmony_ci		    tblname, fp1);
1758c2ecf20Sopenharmony_ci	    exit(EX_DATAERR);
1768c2ecf20Sopenharmony_ci	}
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci      if (fp1)
1798c2ecf20Sopenharmony_ci	{
1808c2ecf20Sopenharmony_ci	  /* we have a range; expect the word "idem" or a Unicode range of the
1818c2ecf20Sopenharmony_ci	     same length */
1828c2ecf20Sopenharmony_ci	  while (*p == ' ' || *p == '\t')
1838c2ecf20Sopenharmony_ci	    p++;
1848c2ecf20Sopenharmony_ci	  if (!strncmp(p, "idem", 4))
1858c2ecf20Sopenharmony_ci	    {
1868c2ecf20Sopenharmony_ci	      for (i=fp0; i<=fp1; i++)
1878c2ecf20Sopenharmony_ci		addpair(i,i);
1888c2ecf20Sopenharmony_ci	      p += 4;
1898c2ecf20Sopenharmony_ci	    }
1908c2ecf20Sopenharmony_ci	  else
1918c2ecf20Sopenharmony_ci	    {
1928c2ecf20Sopenharmony_ci	      un0 = getunicode(&p);
1938c2ecf20Sopenharmony_ci	      while (*p == ' ' || *p == '\t')
1948c2ecf20Sopenharmony_ci		p++;
1958c2ecf20Sopenharmony_ci	      if (*p != '-')
1968c2ecf20Sopenharmony_ci		{
1978c2ecf20Sopenharmony_ci		  fprintf(stderr,
1988c2ecf20Sopenharmony_ci"%s: Corresponding to a range of font positions, there should be a Unicode range\n",
1998c2ecf20Sopenharmony_ci			  tblname);
2008c2ecf20Sopenharmony_ci		  exit(EX_DATAERR);
2018c2ecf20Sopenharmony_ci	        }
2028c2ecf20Sopenharmony_ci	      p++;
2038c2ecf20Sopenharmony_ci	      un1 = getunicode(&p);
2048c2ecf20Sopenharmony_ci	      if (un0 < 0 || un1 < 0)
2058c2ecf20Sopenharmony_ci		{
2068c2ecf20Sopenharmony_ci		  fprintf(stderr,
2078c2ecf20Sopenharmony_ci"%s: Bad Unicode range corresponding to font position range 0x%x-0x%x\n",
2088c2ecf20Sopenharmony_ci			  tblname, fp0, fp1);
2098c2ecf20Sopenharmony_ci		  exit(EX_DATAERR);
2108c2ecf20Sopenharmony_ci	        }
2118c2ecf20Sopenharmony_ci	      if (un1 - un0 != fp1 - fp0)
2128c2ecf20Sopenharmony_ci		{
2138c2ecf20Sopenharmony_ci		  fprintf(stderr,
2148c2ecf20Sopenharmony_ci"%s: Unicode range U+%x-U+%x not of the same length as font position range 0x%x-0x%x\n",
2158c2ecf20Sopenharmony_ci			  tblname, un0, un1, fp0, fp1);
2168c2ecf20Sopenharmony_ci		  exit(EX_DATAERR);
2178c2ecf20Sopenharmony_ci	        }
2188c2ecf20Sopenharmony_ci	      for(i=fp0; i<=fp1; i++)
2198c2ecf20Sopenharmony_ci		addpair(i,un0-fp0+i);
2208c2ecf20Sopenharmony_ci	    }
2218c2ecf20Sopenharmony_ci        }
2228c2ecf20Sopenharmony_ci      else
2238c2ecf20Sopenharmony_ci	{
2248c2ecf20Sopenharmony_ci	    /* no range; expect a list of unicode values for a single font position */
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	    while ( (un0 = getunicode(&p)) >= 0 )
2278c2ecf20Sopenharmony_ci	      addpair(fp0, un0);
2288c2ecf20Sopenharmony_ci	}
2298c2ecf20Sopenharmony_ci      while (*p == ' ' || *p == '\t')
2308c2ecf20Sopenharmony_ci	p++;
2318c2ecf20Sopenharmony_ci      if (*p && *p != '#')
2328c2ecf20Sopenharmony_ci	fprintf(stderr, "%s: trailing junk (%s) ignored\n", tblname, p);
2338c2ecf20Sopenharmony_ci    }
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci  /* Okay, we hit EOF, now output hash table */
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci  fclose(ctbl);
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci  /* Compute total size of Unicode list */
2418c2ecf20Sopenharmony_ci  nuni = 0;
2428c2ecf20Sopenharmony_ci  for ( i = 0 ; i < fontlen ; i++ )
2438c2ecf20Sopenharmony_ci    nuni += unicount[i];
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci  printf("\
2468c2ecf20Sopenharmony_ci/*\n\
2478c2ecf20Sopenharmony_ci * Do not edit this file; it was automatically generated by\n\
2488c2ecf20Sopenharmony_ci *\n\
2498c2ecf20Sopenharmony_ci * conmakehash %s > [this file]\n\
2508c2ecf20Sopenharmony_ci *\n\
2518c2ecf20Sopenharmony_ci */\n\
2528c2ecf20Sopenharmony_ci\n\
2538c2ecf20Sopenharmony_ci#include <linux/types.h>\n\
2548c2ecf20Sopenharmony_ci\n\
2558c2ecf20Sopenharmony_ciu8 dfont_unicount[%d] = \n\
2568c2ecf20Sopenharmony_ci{\n\t", argv[1], fontlen);
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci  for ( i = 0 ; i < fontlen ; i++ )
2598c2ecf20Sopenharmony_ci    {
2608c2ecf20Sopenharmony_ci      printf("%3d", unicount[i]);
2618c2ecf20Sopenharmony_ci      if ( i == fontlen-1 )
2628c2ecf20Sopenharmony_ci        printf("\n};\n");
2638c2ecf20Sopenharmony_ci      else if ( i % 8 == 7 )
2648c2ecf20Sopenharmony_ci        printf(",\n\t");
2658c2ecf20Sopenharmony_ci      else
2668c2ecf20Sopenharmony_ci        printf(", ");
2678c2ecf20Sopenharmony_ci    }
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci  printf("\nu16 dfont_unitable[%d] = \n{\n\t", nuni);
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci  fp0 = 0;
2728c2ecf20Sopenharmony_ci  nent = 0;
2738c2ecf20Sopenharmony_ci  for ( i = 0 ; i < nuni ; i++ )
2748c2ecf20Sopenharmony_ci    {
2758c2ecf20Sopenharmony_ci      while ( nent >= unicount[fp0] )
2768c2ecf20Sopenharmony_ci	{
2778c2ecf20Sopenharmony_ci	  fp0++;
2788c2ecf20Sopenharmony_ci	  nent = 0;
2798c2ecf20Sopenharmony_ci	}
2808c2ecf20Sopenharmony_ci      printf("0x%04x", unitable[fp0][nent++]);
2818c2ecf20Sopenharmony_ci      if ( i == nuni-1 )
2828c2ecf20Sopenharmony_ci         printf("\n};\n");
2838c2ecf20Sopenharmony_ci       else if ( i % 8 == 7 )
2848c2ecf20Sopenharmony_ci         printf(",\n\t");
2858c2ecf20Sopenharmony_ci       else
2868c2ecf20Sopenharmony_ci         printf(", ");
2878c2ecf20Sopenharmony_ci    }
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci  exit(EX_OK);
2908c2ecf20Sopenharmony_ci}
291