Home | History | Annotate | Line # | Download | only in libcpp
      1  1.1  mrg /* Make ucnid.h from various sources.
      2  1.1  mrg    Copyright (C) 2005-2022 Free Software Foundation, Inc.
      3  1.1  mrg 
      4  1.1  mrg This program is free software; you can redistribute it and/or modify it
      5  1.1  mrg under the terms of the GNU General Public License as published by the
      6  1.1  mrg Free Software Foundation; either version 3, or (at your option) any
      7  1.1  mrg later version.
      8  1.1  mrg 
      9  1.1  mrg This program is distributed in the hope that it will be useful,
     10  1.1  mrg but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  1.1  mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12  1.1  mrg GNU General Public License for more details.
     13  1.1  mrg 
     14  1.1  mrg You should have received a copy of the GNU General Public License
     15  1.1  mrg along with this program; see the file COPYING3.  If not see
     16  1.1  mrg <http://www.gnu.org/licenses/>.  */
     17  1.1  mrg 
     18  1.1  mrg /* Run this program as
     19  1.1  mrg    ./makeucnid ucnid.tab UnicodeData.txt DerivedNormalizationProps.txt \
     20  1.1  mrg       DerivedCoreProperties.txt > ucnid.h
     21  1.1  mrg */
     22  1.1  mrg 
     23  1.1  mrg #include <stdio.h>
     24  1.1  mrg #include <string.h>
     25  1.1  mrg #include <ctype.h>
     26  1.1  mrg #include <stdbool.h>
     27  1.1  mrg #include <stdlib.h>
     28  1.1  mrg 
     29  1.1  mrg enum {
     30  1.1  mrg   C99 = 1,
     31  1.1  mrg   CXX = 2,
     32  1.1  mrg   N99 = 4,
     33  1.1  mrg   C11 = 8,
     34  1.1  mrg   N11 = 16,
     35  1.1  mrg   CXX23 = 32,
     36  1.1  mrg   NXX23 = 64,
     37  1.1  mrg   all_languages = C99 | CXX | C11 | CXX23 | NXX23,
     38  1.1  mrg   not_NFC = 128,
     39  1.1  mrg   not_NFKC = 256,
     40  1.1  mrg   maybe_not_NFC = 512
     41  1.1  mrg };
     42  1.1  mrg 
     43  1.1  mrg #define NUM_CODE_POINTS 0x110000
     44  1.1  mrg #define MAX_CODE_POINT 0x10ffff
     45  1.1  mrg 
     46  1.1  mrg static unsigned flags[NUM_CODE_POINTS];
     47  1.1  mrg static unsigned int all_decomp[NUM_CODE_POINTS][2];
     48  1.1  mrg static unsigned int decomp[NUM_CODE_POINTS][2];
     49  1.1  mrg static unsigned char combining_value[NUM_CODE_POINTS];
     50  1.1  mrg 
     51  1.1  mrg /* Die!  */
     52  1.1  mrg 
     53  1.1  mrg static void
     54  1.1  mrg fail (const char *s)
     55  1.1  mrg {
     56  1.1  mrg   fprintf (stderr, "%s\n", s);
     57  1.1  mrg   exit (1);
     58  1.1  mrg }
     59  1.1  mrg 
     60  1.1  mrg /* Read ucnid.tab and set the flags for language versions in header[].  */
     61  1.1  mrg 
     62  1.1  mrg static void
     63  1.1  mrg read_ucnid (const char *fname)
     64  1.1  mrg {
     65  1.1  mrg   FILE *f = fopen (fname, "r");
     66  1.1  mrg   unsigned fl = 0;
     67  1.1  mrg 
     68  1.1  mrg   if (!f)
     69  1.1  mrg     fail ("opening ucnid.tab");
     70  1.1  mrg   for (;;)
     71  1.1  mrg     {
     72  1.1  mrg       char line[256];
     73  1.1  mrg 
     74  1.1  mrg       if (!fgets (line, sizeof (line), f))
     75  1.1  mrg 	break;
     76  1.1  mrg       if (strcmp (line, "[C99]\n") == 0)
     77  1.1  mrg 	fl = C99;
     78  1.1  mrg       else if (strcmp (line, "[C99DIG]\n") == 0)
     79  1.1  mrg 	fl = C99|N99;
     80  1.1  mrg       else if (strcmp (line, "[CXX]\n") == 0)
     81  1.1  mrg 	fl = CXX;
     82  1.1  mrg       else if (strcmp (line, "[C11]\n") == 0)
     83  1.1  mrg 	fl = C11;
     84  1.1  mrg       else if (strcmp (line, "[C11NOSTART]\n") == 0)
     85  1.1  mrg 	fl = C11|N11;
     86  1.1  mrg       else if (isxdigit (line[0]))
     87  1.1  mrg 	{
     88  1.1  mrg 	  char *l = line;
     89  1.1  mrg 	  while (*l)
     90  1.1  mrg 	    {
     91  1.1  mrg 	      unsigned long start, end;
     92  1.1  mrg 	      char *endptr;
     93  1.1  mrg 	      start = strtoul (l, &endptr, 16);
     94  1.1  mrg 	      if (endptr == l || (*endptr != '-' && ! isspace (*endptr)))
     95  1.1  mrg 		fail ("parsing ucnid.tab [1]");
     96  1.1  mrg 	      l = endptr;
     97  1.1  mrg 	      if (*l != '-')
     98  1.1  mrg 		end = start;
     99  1.1  mrg 	      else
    100  1.1  mrg 		{
    101  1.1  mrg 		  end = strtoul (l + 1, &endptr, 16);
    102  1.1  mrg 		  if (end < start)
    103  1.1  mrg 		    fail ("parsing ucnid.tab, end before start");
    104  1.1  mrg 		  l = endptr;
    105  1.1  mrg 		  if (! isspace (*l))
    106  1.1  mrg 		    fail ("parsing ucnid.tab, junk after range");
    107  1.1  mrg 		}
    108  1.1  mrg 	      while (isspace (*l))
    109  1.1  mrg 		l++;
    110  1.1  mrg 	      if (end > MAX_CODE_POINT)
    111  1.1  mrg 		fail ("parsing ucnid.tab, end too large");
    112  1.1  mrg 	      while (start <= end)
    113  1.1  mrg 		flags[start++] |= fl;
    114  1.1  mrg 	    }
    115  1.1  mrg 	}
    116  1.1  mrg     }
    117  1.1  mrg   if (ferror (f))
    118  1.1  mrg     fail ("reading ucnid.tab");
    119  1.1  mrg   fclose (f);
    120  1.1  mrg }
    121  1.1  mrg 
    122  1.1  mrg /* Read UnicodeData.txt and fill in the 'decomp' table to be the
    123  1.1  mrg    decompositions of characters for which both the character
    124  1.1  mrg    decomposed and all the code points in the decomposition are valid
    125  1.1  mrg    for some supported language version, and the 'all_decomp' table to
    126  1.1  mrg    be the decompositions of all characters without those
    127  1.1  mrg    constraints.  */
    128  1.1  mrg 
    129  1.1  mrg static void
    130  1.1  mrg read_table (char *fname)
    131  1.1  mrg {
    132  1.1  mrg   FILE * f = fopen (fname, "r");
    133  1.1  mrg 
    134  1.1  mrg   if (!f)
    135  1.1  mrg     fail ("opening UnicodeData.txt");
    136  1.1  mrg   for (;;)
    137  1.1  mrg     {
    138  1.1  mrg       char line[256];
    139  1.1  mrg       unsigned long codepoint, this_decomp[4];
    140  1.1  mrg       char *l;
    141  1.1  mrg       int i, j;
    142  1.1  mrg       int decomp_useful;
    143  1.1  mrg 
    144  1.1  mrg       if (!fgets (line, sizeof (line), f))
    145  1.1  mrg 	break;
    146  1.1  mrg       codepoint = strtoul (line, &l, 16);
    147  1.1  mrg       if (l == line || *l != ';')
    148  1.1  mrg 	fail ("parsing UnicodeData.txt, reading code point");
    149  1.1  mrg       if (codepoint > MAX_CODE_POINT)
    150  1.1  mrg 	fail ("parsing UnicodeData.txt, code point too large");
    151  1.1  mrg 
    152  1.1  mrg       do {
    153  1.1  mrg 	l++;
    154  1.1  mrg       } while (*l != ';');
    155  1.1  mrg       /* Category value.  */
    156  1.1  mrg       do {
    157  1.1  mrg 	l++;
    158  1.1  mrg       } while (*l != ';');
    159  1.1  mrg       /* Canonical combining class; in NFC/NFKC, they must be increasing
    160  1.1  mrg 	 (or zero).  */
    161  1.1  mrg       if (! isdigit (*++l))
    162  1.1  mrg 	fail ("parsing UnicodeData.txt, combining class not number");
    163  1.1  mrg       combining_value[codepoint] = strtoul (l, &l, 10);
    164  1.1  mrg       if (*l++ != ';')
    165  1.1  mrg 	fail ("parsing UnicodeData.txt, junk after combining class");
    166  1.1  mrg 
    167  1.1  mrg       /* Skip over bidi value.  */
    168  1.1  mrg       do {
    169  1.1  mrg 	l++;
    170  1.1  mrg       } while (*l != ';');
    171  1.1  mrg 
    172  1.1  mrg       /* Decomposition mapping.  */
    173  1.1  mrg       decomp_useful = flags[codepoint];
    174  1.1  mrg       if (*++l == '<')  /* Compatibility mapping. */
    175  1.1  mrg 	continue;
    176  1.1  mrg       for (i = 0; i < 4; i++)
    177  1.1  mrg 	{
    178  1.1  mrg 	  if (*l == ';')
    179  1.1  mrg 	    break;
    180  1.1  mrg 	  if (!isxdigit (*l))
    181  1.1  mrg 	    fail ("parsing UnicodeData.txt, decomposition format");
    182  1.1  mrg 	  this_decomp[i] = strtoul (l, &l, 16);
    183  1.1  mrg 	  decomp_useful &= flags[this_decomp[i]];
    184  1.1  mrg 	  while (isspace (*l))
    185  1.1  mrg 	    l++;
    186  1.1  mrg 	}
    187  1.1  mrg       if (i > 2)  /* Decomposition too long.  */
    188  1.1  mrg 	fail ("parsing UnicodeData.txt, decomposition too long");
    189  1.1  mrg       for (j = 0; j < i; j++)
    190  1.1  mrg 	all_decomp[codepoint][j] = this_decomp[j];
    191  1.1  mrg       if ((flags[codepoint] & all_languages) && decomp_useful)
    192  1.1  mrg 	while (--i >= 0)
    193  1.1  mrg 	  decomp[codepoint][i] = this_decomp[i];
    194  1.1  mrg     }
    195  1.1  mrg   if (ferror (f))
    196  1.1  mrg     fail ("reading UnicodeData.txt");
    197  1.1  mrg   fclose (f);
    198  1.1  mrg }
    199  1.1  mrg 
    200  1.1  mrg /* Read DerivedNormalizationProps.txt and set the flags that say whether
    201  1.1  mrg    a character is in NFC, NFKC, or is context-dependent.  */
    202  1.1  mrg 
    203  1.1  mrg static void
    204  1.1  mrg read_derived (const char *fname)
    205  1.1  mrg {
    206  1.1  mrg   FILE * f = fopen (fname, "r");
    207  1.1  mrg 
    208  1.1  mrg   if (!f)
    209  1.1  mrg     fail ("opening DerivedNormalizationProps.txt");
    210  1.1  mrg   for (;;)
    211  1.1  mrg     {
    212  1.1  mrg       char line[256];
    213  1.1  mrg       unsigned long start, end;
    214  1.1  mrg       char *l;
    215  1.1  mrg       bool not_NFC_p, not_NFKC_p, maybe_not_NFC_p;
    216  1.1  mrg 
    217  1.1  mrg       if (!fgets (line, sizeof (line), f))
    218  1.1  mrg 	break;
    219  1.1  mrg       not_NFC_p = (strstr (line, "; NFC_QC; N") != NULL);
    220  1.1  mrg       not_NFKC_p = (strstr (line, "; NFKC_QC; N") != NULL);
    221  1.1  mrg       maybe_not_NFC_p = (strstr (line, "; NFC_QC; M") != NULL);
    222  1.1  mrg       if (! not_NFC_p && ! not_NFKC_p && ! maybe_not_NFC_p)
    223  1.1  mrg 	continue;
    224  1.1  mrg 
    225  1.1  mrg       start = strtoul (line, &l, 16);
    226  1.1  mrg       if (l == line)
    227  1.1  mrg 	fail ("parsing DerivedNormalizationProps.txt, reading start");
    228  1.1  mrg       if (start > MAX_CODE_POINT)
    229  1.1  mrg 	fail ("parsing DerivedNormalizationProps.txt, code point too large");
    230  1.1  mrg       if (*l == '.' && l[1] == '.')
    231  1.1  mrg 	end = strtoul (l + 2, &l, 16);
    232  1.1  mrg       else
    233  1.1  mrg 	end = start;
    234  1.1  mrg 
    235  1.1  mrg       while (start <= end)
    236  1.1  mrg 	flags[start++] |= ((not_NFC_p ? not_NFC : 0)
    237  1.1  mrg 			   | (not_NFKC_p ? not_NFKC : 0)
    238  1.1  mrg 			   | (maybe_not_NFC_p ? maybe_not_NFC : 0)
    239  1.1  mrg 			   );
    240  1.1  mrg     }
    241  1.1  mrg   if (ferror (f))
    242  1.1  mrg     fail ("reading DerivedNormalizationProps.txt");
    243  1.1  mrg   fclose (f);
    244  1.1  mrg }
    245  1.1  mrg 
    246  1.1  mrg /* Read DerivedCoreProperties.txt and fill in languages version in
    247  1.1  mrg    flags from the XID_Start and XID_Continue properties.  */
    248  1.1  mrg 
    249  1.1  mrg static void
    250  1.1  mrg read_derivedcore (char *fname)
    251  1.1  mrg {
    252  1.1  mrg   FILE * f = fopen (fname, "r");
    253  1.1  mrg 
    254  1.1  mrg   if (!f)
    255  1.1  mrg     fail ("opening DerivedCoreProperties.txt");
    256  1.1  mrg   for (;;)
    257  1.1  mrg     {
    258  1.1  mrg       char line[256];
    259  1.1  mrg       unsigned long codepoint_start, codepoint_end;
    260  1.1  mrg       char *l;
    261  1.1  mrg       int i, j;
    262  1.1  mrg 
    263  1.1  mrg       if (!fgets (line, sizeof (line), f))
    264  1.1  mrg 	break;
    265  1.1  mrg       if (line[0] == '#' || line[0] == '\n' || line[0] == '\r')
    266  1.1  mrg 	continue;
    267  1.1  mrg       codepoint_start = strtoul (line, &l, 16);
    268  1.1  mrg       if (l == line)
    269  1.1  mrg 	fail ("parsing DerivedCoreProperties.txt, reading code point");
    270  1.1  mrg       if (codepoint_start > MAX_CODE_POINT)
    271  1.1  mrg 	fail ("parsing DerivedCoreProperties.txt, code point too large");
    272  1.1  mrg 
    273  1.1  mrg       if (*l == '.' && l[1] == '.')
    274  1.1  mrg 	{
    275  1.1  mrg 	  char *l2 = l + 2;
    276  1.1  mrg 	  codepoint_end = strtoul (l + 2, &l, 16);
    277  1.1  mrg 	  if (l == l2 || codepoint_end < codepoint_start)
    278  1.1  mrg 	    fail ("parsing DerivedCoreProperties.txt, reading code point");
    279  1.1  mrg 	  if (codepoint_end > MAX_CODE_POINT)
    280  1.1  mrg 	    fail ("parsing DerivedCoreProperties.txt, code point too large");
    281  1.1  mrg 	}
    282  1.1  mrg       else
    283  1.1  mrg 	codepoint_end = codepoint_start;
    284  1.1  mrg 
    285  1.1  mrg       while (*l == ' ')
    286  1.1  mrg 	l++;
    287  1.1  mrg       if (*l++ != ';')
    288  1.1  mrg 	fail ("parsing DerivedCoreProperties.txt, reading code point");
    289  1.1  mrg 
    290  1.1  mrg       while (*l == ' ')
    291  1.1  mrg 	l++;
    292  1.1  mrg 
    293  1.1  mrg       if (codepoint_end < 0x80)
    294  1.1  mrg         continue;
    295  1.1  mrg 
    296  1.1  mrg       if (strncmp (l, "XID_Start ", 10) == 0)
    297  1.1  mrg 	{
    298  1.1  mrg 	  for (; codepoint_start <= codepoint_end; codepoint_start++)
    299  1.1  mrg 	    flags[codepoint_start]
    300  1.1  mrg 	      = (flags[codepoint_start] | CXX23) & ~NXX23;
    301  1.1  mrg 	}
    302  1.1  mrg       else if (strncmp (l, "XID_Continue ", 13) == 0)
    303  1.1  mrg 	{
    304  1.1  mrg 	  for (; codepoint_start <= codepoint_end; codepoint_start++)
    305  1.1  mrg 	    if ((flags[codepoint_start] & CXX23) == 0)
    306  1.1  mrg 	      flags[codepoint_start] |= CXX23 | NXX23;
    307  1.1  mrg 	}
    308  1.1  mrg     }
    309  1.1  mrg   if (ferror (f))
    310  1.1  mrg     fail ("reading DerivedCoreProperties.txt");
    311  1.1  mrg   fclose (f);
    312  1.1  mrg }
    313  1.1  mrg 
    314  1.1  mrg /* Write out the table.
    315  1.1  mrg    The table consists of two words per entry.  The first word is the flags
    316  1.1  mrg    for the unicode code points up to and including the second word.  */
    317  1.1  mrg 
    318  1.1  mrg static void
    319  1.1  mrg write_table (void)
    320  1.1  mrg {
    321  1.1  mrg   unsigned i;
    322  1.1  mrg   unsigned last_flag = flags[0];
    323  1.1  mrg   bool really_safe = decomp[0][0] == 0;
    324  1.1  mrg   unsigned char last_combine = combining_value[0];
    325  1.1  mrg 
    326  1.1  mrg   printf ("static const struct ucnrange ucnranges[] = {\n");
    327  1.1  mrg 
    328  1.1  mrg   for (i = 1; i <= NUM_CODE_POINTS; i++)
    329  1.1  mrg     if (i == NUM_CODE_POINTS
    330  1.1  mrg 	|| (flags[i] != last_flag && ((flags[i] | last_flag) & all_languages))
    331  1.1  mrg 	|| really_safe != (decomp[i][0] == 0)
    332  1.1  mrg 	|| combining_value[i] != last_combine)
    333  1.1  mrg       {
    334  1.1  mrg 	printf ("{ %s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s, %3d, %#06x },\n",
    335  1.1  mrg 		last_flag & C99 ? "C99" : "  0",
    336  1.1  mrg 		last_flag & N99 ? "N99" : "  0",
    337  1.1  mrg 		last_flag & CXX ? "CXX" : "  0",
    338  1.1  mrg 		last_flag & C11 ? "C11" : "  0",
    339  1.1  mrg 		last_flag & N11 ? "N11" : "  0",
    340  1.1  mrg 		last_flag & CXX23 ? "CXX23" : "    0",
    341  1.1  mrg 		last_flag & NXX23 ? "NXX23" : "    0",
    342  1.1  mrg 		really_safe ? "CID" : "  0",
    343  1.1  mrg 		last_flag & not_NFC ? "  0" : "NFC",
    344  1.1  mrg 		last_flag & not_NFKC ? "  0" : "NKC",
    345  1.1  mrg 		last_flag & maybe_not_NFC ? "CTX" : "  0",
    346  1.1  mrg 		combining_value[i - 1],
    347  1.1  mrg 		i - 1);
    348  1.1  mrg 	last_flag = flags[i];
    349  1.1  mrg 	last_combine = combining_value[i];
    350  1.1  mrg 	really_safe = decomp[i][0] == 0;
    351  1.1  mrg       }
    352  1.1  mrg 
    353  1.1  mrg   printf ("};\n");
    354  1.1  mrg }
    355  1.1  mrg 
    356  1.1  mrg /* Return whether a given character is valid in an identifier for some
    357  1.1  mrg    supported language, either as itself or as a UCN.  */
    358  1.1  mrg 
    359  1.1  mrg static bool
    360  1.1  mrg char_id_valid (unsigned int c)
    361  1.1  mrg {
    362  1.1  mrg   return ((flags[c] & all_languages)
    363  1.1  mrg 	  || (c == 0x24)
    364  1.1  mrg 	  || (c >= 0x30 && c <= 0x39)
    365  1.1  mrg 	  || (c >= 0x41 && c <= 0x5a)
    366  1.1  mrg 	  || (c >= 0x61 && c <= 0x7a));
    367  1.1  mrg }
    368  1.1  mrg 
    369  1.1  mrg /* Write out the switch statement over characters for which it is
    370  1.1  mrg    context-dependent whether they are in NFC.  */
    371  1.1  mrg 
    372  1.1  mrg static void
    373  1.1  mrg write_context_switch (void)
    374  1.1  mrg {
    375  1.1  mrg   unsigned i;
    376  1.1  mrg   printf ("static bool\n"
    377  1.1  mrg 	  "check_nfc (cpp_reader *pfile, cppchar_t c, cppchar_t p)\n"
    378  1.1  mrg 	  "{\n"
    379  1.1  mrg 	  "  switch (c)\n"
    380  1.1  mrg 	  "    {\n");
    381  1.1  mrg   for (i = 0; i < NUM_CODE_POINTS; i++)
    382  1.1  mrg     {
    383  1.1  mrg       bool found_case = false;
    384  1.1  mrg       unsigned j;
    385  1.1  mrg       if (!(flags[i] & all_languages) || !(flags[i] & maybe_not_NFC))
    386  1.1  mrg 	continue;
    387  1.1  mrg       if ((i >= 0x1161 && i <= 0x1175) || (i >= 0x11A8 && i <= 0x11C2))
    388  1.1  mrg 	continue; /* Hangul handled algorithmically.  */
    389  1.1  mrg       printf ("    case %#06x:\n"
    390  1.1  mrg 	      "      switch (p)\n"
    391  1.1  mrg 	      "\t{\n", i);
    392  1.1  mrg       /* If an NFC starter character decomposes with this character I
    393  1.1  mrg 	 as the second character and an NFC starter character S as the
    394  1.1  mrg 	 first character, that latter character as a previous
    395  1.1  mrg 	 character means this character is not NFC.  Furthermore, any
    396  1.1  mrg 	 NFC starter character K made by a series of compositions of S
    397  1.1  mrg 	 with combining characters whose combining class is greater
    398  1.1  mrg 	 than that of I also means this character is not NFC.  */
    399  1.1  mrg       for (j = 0; j < NUM_CODE_POINTS; j++)
    400  1.1  mrg 	{
    401  1.1  mrg 	  unsigned s, k;
    402  1.1  mrg 	  if (all_decomp[j][1] != i)
    403  1.1  mrg 	    continue;
    404  1.1  mrg 	  s = all_decomp[j][0];
    405  1.1  mrg 	  if (combining_value[s] != 0 || (flags[s] & not_NFC) != 0)
    406  1.1  mrg 	    continue;
    407  1.1  mrg 	  if (char_id_valid (s))
    408  1.1  mrg 	    {
    409  1.1  mrg 	      found_case = true;
    410  1.1  mrg 	      printf ("\tcase %#06x:\n", s);
    411  1.1  mrg 	    }
    412  1.1  mrg 	  for (k = 0; k < NUM_CODE_POINTS; k++)
    413  1.1  mrg 	    {
    414  1.1  mrg 	      unsigned t = k;
    415  1.1  mrg 	      if (k == s || !char_id_valid (k))
    416  1.1  mrg 		continue;
    417  1.1  mrg 	      while (all_decomp[t][1] != 0
    418  1.1  mrg 		     && combining_value[all_decomp[t][1]] > combining_value[i])
    419  1.1  mrg 		{
    420  1.1  mrg 		  if (combining_value[t] != 0 || (flags[t] & not_NFC) != 0)
    421  1.1  mrg 		    break;
    422  1.1  mrg 		  t = all_decomp[t][0];
    423  1.1  mrg 		}
    424  1.1  mrg 	      if (t == s)
    425  1.1  mrg 		{
    426  1.1  mrg 		  found_case = true;
    427  1.1  mrg 		  printf ("\tcase %#06x:\n", k);
    428  1.1  mrg 		}
    429  1.1  mrg 	    }
    430  1.1  mrg 	}
    431  1.1  mrg       if (found_case)
    432  1.1  mrg 	printf ("\t  return false;\n");
    433  1.1  mrg       else
    434  1.1  mrg 	printf ("\t/* Non-NFC cases not applicable to C/C++.  */\n");
    435  1.1  mrg       printf ("\tdefault:\n"
    436  1.1  mrg 	      "\t  return true;\n"
    437  1.1  mrg 	      "\t}\n\n");
    438  1.1  mrg     }
    439  1.1  mrg   printf ("    default:\n"
    440  1.1  mrg 	  "      cpp_error (pfile, CPP_DL_ICE, \"Character %%x might not be NFKC\", c);\n"
    441  1.1  mrg 	  "      return true;\n"
    442  1.1  mrg 	  "  }\n"
    443  1.1  mrg 	  "}\n");
    444  1.1  mrg }
    445  1.1  mrg 
    446  1.1  mrg /* Print out the huge copyright notice.  */
    447  1.1  mrg 
    448  1.1  mrg static void
    449  1.1  mrg write_copyright (void)
    450  1.1  mrg {
    451  1.1  mrg   static const char copyright[] = "\
    452  1.1  mrg /* Unicode characters and various properties.\n\
    453  1.1  mrg    Copyright (C) 2003-2022 Free Software Foundation, Inc.\n\
    454  1.1  mrg \n\
    455  1.1  mrg    This program is free software; you can redistribute it and/or modify it\n\
    456  1.1  mrg    under the terms of the GNU General Public License as published by the\n\
    457  1.1  mrg    Free Software Foundation; either version 3, or (at your option) any\n\
    458  1.1  mrg    later version.\n\
    459  1.1  mrg \n\
    460  1.1  mrg    This program is distributed in the hope that it will be useful,\n\
    461  1.1  mrg    but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
    462  1.1  mrg    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\
    463  1.1  mrg    GNU General Public License for more details.\n\
    464  1.1  mrg \n\
    465  1.1  mrg    You should have received a copy of the GNU General Public License\n\
    466  1.1  mrg    along with this program; see the file COPYING3.  If not see\n\
    467  1.1  mrg    <http://www.gnu.org/licenses/>.\n\
    468  1.1  mrg \n\
    469  1.1  mrg \n\
    470  1.1  mrg    Copyright (C) 1991-2005 Unicode, Inc.  All rights reserved.\n\
    471  1.1  mrg    Distributed under the Terms of Use in\n\
    472  1.1  mrg    http://www.unicode.org/copyright.html.\n\
    473  1.1  mrg \n\
    474  1.1  mrg    Permission is hereby granted, free of charge, to any person\n\
    475  1.1  mrg    obtaining a copy of the Unicode data files and any associated\n\
    476  1.1  mrg    documentation (the \"Data Files\") or Unicode software and any\n\
    477  1.1  mrg    associated documentation (the \"Software\") to deal in the Data Files\n\
    478  1.1  mrg    or Software without restriction, including without limitation the\n\
    479  1.1  mrg    rights to use, copy, modify, merge, publish, distribute, and/or\n\
    480  1.1  mrg    sell copies of the Data Files or Software, and to permit persons to\n\
    481  1.1  mrg    whom the Data Files or Software are furnished to do so, provided\n\
    482  1.1  mrg    that (a) the above copyright notice(s) and this permission notice\n\
    483  1.1  mrg    appear with all copies of the Data Files or Software, (b) both the\n\
    484  1.1  mrg    above copyright notice(s) and this permission notice appear in\n\
    485  1.1  mrg    associated documentation, and (c) there is clear notice in each\n\
    486  1.1  mrg    modified Data File or in the Software as well as in the\n\
    487  1.1  mrg    documentation associated with the Data File(s) or Software that the\n\
    488  1.1  mrg    data or software has been modified.\n\
    489  1.1  mrg \n\
    490  1.1  mrg    THE DATA FILES AND SOFTWARE ARE PROVIDED \"AS IS\", WITHOUT WARRANTY\n\
    491  1.1  mrg    OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n\
    492  1.1  mrg    WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n\
    493  1.1  mrg    NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE\n\
    494  1.1  mrg    COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR\n\
    495  1.1  mrg    ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY\n\
    496  1.1  mrg    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,\n\
    497  1.1  mrg    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS\n\
    498  1.1  mrg    ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE\n\
    499  1.1  mrg    OF THE DATA FILES OR SOFTWARE.\n\
    500  1.1  mrg \n\
    501  1.1  mrg    Except as contained in this notice, the name of a copyright holder\n\
    502  1.1  mrg    shall not be used in advertising or otherwise to promote the sale,\n\
    503  1.1  mrg    use or other dealings in these Data Files or Software without prior\n\
    504  1.1  mrg    written authorization of the copyright holder.  */\n";
    505  1.1  mrg 
    506  1.1  mrg    puts (copyright);
    507  1.1  mrg }
    508  1.1  mrg 
    509  1.1  mrg /* Main program.  */
    510  1.1  mrg 
    511  1.1  mrg int
    512  1.1  mrg main(int argc, char ** argv)
    513  1.1  mrg {
    514  1.1  mrg   if (argc != 5)
    515  1.1  mrg     fail ("too few arguments to makeucn");
    516  1.1  mrg   read_ucnid (argv[1]);
    517  1.1  mrg   read_table (argv[2]);
    518  1.1  mrg   read_derived (argv[3]);
    519  1.1  mrg   read_derivedcore (argv[4]);
    520  1.1  mrg 
    521  1.1  mrg   write_copyright ();
    522  1.1  mrg   write_table ();
    523  1.1  mrg   write_context_switch ();
    524  1.1  mrg   return 0;
    525  1.1  mrg }
    526