diff libcpp/makeucnid.c @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents a06113de4d67
children 84e7813d76e9
line wrap: on
line diff
--- a/libcpp/makeucnid.c	Sun Aug 21 07:07:55 2011 +0900
+++ b/libcpp/makeucnid.c	Fri Oct 27 22:46:09 2017 +0900
@@ -1,5 +1,5 @@
 /* Make ucnid.h from various sources.
-   Copyright (C) 2005, 2009 Free Software Foundation, Inc.
+   Copyright (C) 2005-2017 Free Software Foundation, Inc.
 
 This program is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
@@ -29,15 +29,22 @@
 enum {
   C99 = 1,
   CXX = 2,
-  digit = 4,
-  not_NFC = 8,
-  not_NFKC = 16,
-  maybe_not_NFC = 32
+  N99 = 4,
+  C11 = 8,
+  N11 = 16,
+  all_languages = C99 | CXX | C11,
+  not_NFC = 32,
+  not_NFKC = 64,
+  maybe_not_NFC = 128
 };
 
-static unsigned flags[65536];
-static unsigned short decomp[65536][2];
-static unsigned char combining_value[65536];
+#define NUM_CODE_POINTS 0x110000
+#define MAX_CODE_POINT 0x10ffff
+
+static unsigned flags[NUM_CODE_POINTS];
+static unsigned int all_decomp[NUM_CODE_POINTS][2];
+static unsigned int decomp[NUM_CODE_POINTS][2];
+static unsigned char combining_value[NUM_CODE_POINTS];
 
 /* Die!  */
 
@@ -48,7 +55,7 @@
   exit (1);
 }
 
-/* Read ucnid.tab and set the C99 and CXX flags in header[].  */
+/* Read ucnid.tab and set the flags for language versions in header[].  */
 
 static void
 read_ucnid (const char *fname)
@@ -66,8 +73,14 @@
 	break;
       if (strcmp (line, "[C99]\n") == 0)
 	fl = C99;
+      else if (strcmp (line, "[C99DIG]\n") == 0)
+	fl = C99|N99;
       else if (strcmp (line, "[CXX]\n") == 0)
 	fl = CXX;
+      else if (strcmp (line, "[C11]\n") == 0)
+	fl = C11;
+      else if (strcmp (line, "[C11NOSTART]\n") == 0)
+	fl = C11|N11;
       else if (isxdigit (line[0]))
 	{
 	  char *l = line;
@@ -92,7 +105,7 @@
 		}
 	      while (isspace (*l))
 		l++;
-	      if (end > 0xFFFF)
+	      if (end > MAX_CODE_POINT)
 		fail ("parsing ucnid.tab, end too large");
 	      while (start <= end)
 		flags[start++] |= fl;
@@ -104,10 +117,12 @@
   fclose (f);
 }
 
-/* Read UnicodeData.txt and set the 'digit' flag, and
-   also fill in the 'decomp' table to be the decompositions of
-   characters for which both the character decomposed and all the code
-   points in the decomposition are either C99 or CXX.  */
+/* Read UnicodeData.txt and fill in the 'decomp' table to be the
+   decompositions of characters for which both the character
+   decomposed and all the code points in the decomposition are valid
+   for some supported language version, and the 'all_decomp' table to
+   be the decompositions of all characters without those
+   constraints.  */
 
 static void
 read_table (char *fname)
@@ -121,7 +136,7 @@
       char line[256];
       unsigned long codepoint, this_decomp[4];
       char *l;
-      int i;
+      int i, j;
       int decomp_useful;
 
       if (!fgets (line, sizeof (line), f))
@@ -129,17 +144,13 @@
       codepoint = strtoul (line, &l, 16);
       if (l == line || *l != ';')
 	fail ("parsing UnicodeData.txt, reading code point");
-      if (codepoint > 0xffff || ! (flags[codepoint] & (C99 | CXX)))
-	continue;
+      if (codepoint > MAX_CODE_POINT)
+	fail ("parsing UnicodeData.txt, code point too large");
 
       do {
 	l++;
       } while (*l != ';');
-      /* Category value; things starting with 'N' are numbers of some
-	 kind.  */
-      if (*++l == 'N')
-	flags[codepoint] |= digit;
-
+      /* Category value.  */
       do {
 	l++;
       } while (*l != ';');
@@ -173,7 +184,9 @@
 	}
       if (i > 2)  /* Decomposition too long.  */
 	fail ("parsing UnicodeData.txt, decomposition too long");
-      if (decomp_useful)
+      for (j = 0; j < i; j++)
+	all_decomp[codepoint][j] = this_decomp[j];
+      if ((flags[codepoint] & all_languages) && decomp_useful)
 	while (--i >= 0)
 	  decomp[codepoint][i] = this_decomp[i];
     }
@@ -210,8 +223,8 @@
       start = strtoul (line, &l, 16);
       if (l == line)
 	fail ("parsing DerivedNormalizationProps.txt, reading start");
-      if (start > 0xffff)
-	continue;
+      if (start > MAX_CODE_POINT)
+	fail ("parsing DerivedNormalizationProps.txt, code point too large");
       if (*l == '.' && l[1] == '.')
 	end = strtoul (l + 2, &l, 16);
       else
@@ -239,17 +252,21 @@
   unsigned last_flag = flags[0];
   bool really_safe = decomp[0][0] == 0;
   unsigned char last_combine = combining_value[0];
+
+  printf ("static const struct ucnrange ucnranges[] = {\n");
   
-  for (i = 1; i <= 65536; i++)
-    if (i == 65536
-	|| (flags[i] != last_flag && ((flags[i] | last_flag) & (C99 | CXX)))
+  for (i = 1; i <= NUM_CODE_POINTS; i++)
+    if (i == NUM_CODE_POINTS
+	|| (flags[i] != last_flag && ((flags[i] | last_flag) & all_languages))
 	|| really_safe != (decomp[i][0] == 0)
 	|| combining_value[i] != last_combine)
       {
-	printf ("{ %s|%s|%s|%s|%s|%s|%s, %3d, %#06x },\n",
+	printf ("{ %s|%s|%s|%s|%s|%s|%s|%s|%s, %3d, %#06x },\n",
 		last_flag & C99 ? "C99" : "  0",
-		last_flag & digit ? "DIG" : "  0",
+		last_flag & N99 ? "N99" : "  0",
 		last_flag & CXX ? "CXX" : "  0",
+		last_flag & C11 ? "C11" : "  0",
+		last_flag & N11 ? "N11" : "  0",
 		really_safe ? "CID" : "  0",
 		last_flag & not_NFC ? "  0" : "NFC",
 		last_flag & not_NFKC ? "  0" : "NKC",
@@ -260,6 +277,98 @@
 	last_combine = combining_value[0];
 	really_safe = decomp[i][0] == 0;
       }
+
+  printf ("};\n");
+}
+
+/* Return whether a given character is valid in an identifier for some
+   supported language, either as itself or as a UCN.  */
+
+static bool
+char_id_valid (unsigned int c)
+{
+  return ((flags[c] & all_languages)
+	  || (c == 0x24)
+	  || (c >= 0x30 && c <= 0x39)
+	  || (c >= 0x41 && c <= 0x5a)
+	  || (c >= 0x61 && c <= 0x7a));
+}
+
+/* Write out the switch statement over characters for which it is
+   context-dependent whether they are in NFC.  */
+
+static void
+write_context_switch (void)
+{
+  unsigned i;
+  printf ("static bool\n"
+	  "check_nfc (cpp_reader *pfile, cppchar_t c, cppchar_t p)\n"
+	  "{\n"
+	  "  switch (c)\n"
+	  "    {\n");
+  for (i = 0; i < NUM_CODE_POINTS; i++)
+    {
+      bool found_case = false;
+      unsigned j;
+      if (!(flags[i] & all_languages) || !(flags[i] & maybe_not_NFC))
+	continue;
+      if ((i >= 0x1161 && i <= 0x1175) || (i >= 0x11A8 && i <= 0x11C2))
+	continue; /* Hangul handled algorithmically.  */
+      printf ("    case %#06x:\n"
+	      "      switch (p)\n"
+	      "\t{\n", i);
+      /* If an NFC starter character decomposes with this character I
+	 as the second character and an NFC starter character S as the
+	 first character, that latter character as a previous
+	 character means this character is not NFC.  Furthermore, any
+	 NFC starter character K made by a series of compositions of S
+	 with combining characters whose combining class is greater
+	 than that of I also means this character is not NFC.  */
+      for (j = 0; j < NUM_CODE_POINTS; j++)
+	{
+	  unsigned s, k;
+	  if (all_decomp[j][1] != i)
+	    continue;
+	  s = all_decomp[j][0];
+	  if (combining_value[s] != 0 || (flags[s] & not_NFC) != 0)
+	    continue;
+	  if (char_id_valid (s))
+	    {
+	      found_case = true;
+	      printf ("\tcase %#06x:\n", s);
+	    }
+	  for (k = 0; k < NUM_CODE_POINTS; k++)
+	    {
+	      unsigned t = k;
+	      if (k == s || !char_id_valid (k))
+		continue;
+	      while (all_decomp[t][1] != 0
+		     && combining_value[all_decomp[t][1]] > combining_value[i])
+		{
+		  if (combining_value[t] != 0 || (flags[t] & not_NFC) != 0)
+		    break;
+		  t = all_decomp[t][0];
+		}
+	      if (t == s)
+		{
+		  found_case = true;
+		  printf ("\tcase %#06x:\n", k);
+		}
+	    }
+	}
+      if (found_case)
+	printf ("\t  return false;\n");
+      else
+	printf ("\t/* Non-NFC cases not applicable to C/C++.  */\n");
+      printf ("\tdefault:\n"
+	      "\t  return true;\n"
+	      "\t}\n\n");
+    }
+  printf ("    default:\n"
+	  "      cpp_error (pfile, CPP_DL_ICE, \"Character %%x might not be NFKC\", c);\n"
+	  "      return true;\n"
+	  "  }\n"
+	  "}\n");
 }
 
 /* Print out the huge copyright notice.  */
@@ -269,7 +378,7 @@
 {
   static const char copyright[] = "\
 /* Unicode characters and various properties.\n\
-   Copyright (C) 2003, 2005 Free Software Foundation, Inc.\n\
+   Copyright (C) 2003-2017 Free Software Foundation, Inc.\n\
 \n\
    This program is free software; you can redistribute it and/or modify it\n\
    under the terms of the GNU General Public License as published by the\n\
@@ -338,5 +447,6 @@
 
   write_copyright ();
   write_table ();
+  write_context_switch ();
   return 0;
 }