xref: /netbsd/external/gpl3/gcc/dist/libcpp/makeucnid.c (revision dd083157)
1c3d31fe1Smrg /* Make ucnid.h from various sources.
2*dd083157Smrg    Copyright (C) 2005-2020 Free Software Foundation, Inc.
3c3d31fe1Smrg 
4c3d31fe1Smrg This program is free software; you can redistribute it and/or modify it
5c3d31fe1Smrg under the terms of the GNU General Public License as published by the
6c3d31fe1Smrg Free Software Foundation; either version 3, or (at your option) any
7c3d31fe1Smrg later version.
8c3d31fe1Smrg 
9c3d31fe1Smrg This program is distributed in the hope that it will be useful,
10c3d31fe1Smrg but WITHOUT ANY WARRANTY; without even the implied warranty of
11c3d31fe1Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12c3d31fe1Smrg GNU General Public License for more details.
13c3d31fe1Smrg 
14c3d31fe1Smrg You should have received a copy of the GNU General Public License
15c3d31fe1Smrg along with this program; see the file COPYING3.  If not see
16c3d31fe1Smrg <http://www.gnu.org/licenses/>.  */
17c3d31fe1Smrg 
18c3d31fe1Smrg /* Run this program as
19c3d31fe1Smrg    ./makeucnid ucnid.tab UnicodeData.txt DerivedNormalizationProps.txt \
20c3d31fe1Smrg        > ucnid.h
21c3d31fe1Smrg */
22c3d31fe1Smrg 
23c3d31fe1Smrg #include <stdio.h>
24c3d31fe1Smrg #include <string.h>
25c3d31fe1Smrg #include <ctype.h>
26c3d31fe1Smrg #include <stdbool.h>
27c3d31fe1Smrg #include <stdlib.h>
28c3d31fe1Smrg 
29c3d31fe1Smrg enum {
30c3d31fe1Smrg   C99 = 1,
31c3d31fe1Smrg   CXX = 2,
325ef59e75Smrg   N99 = 4,
335ef59e75Smrg   C11 = 8,
345ef59e75Smrg   N11 = 16,
355ef59e75Smrg   all_languages = C99 | CXX | C11,
365ef59e75Smrg   not_NFC = 32,
375ef59e75Smrg   not_NFKC = 64,
385ef59e75Smrg   maybe_not_NFC = 128
39c3d31fe1Smrg };
40c3d31fe1Smrg 
415ef59e75Smrg #define NUM_CODE_POINTS 0x110000
425ef59e75Smrg #define MAX_CODE_POINT 0x10ffff
435ef59e75Smrg 
445ef59e75Smrg static unsigned flags[NUM_CODE_POINTS];
455ef59e75Smrg static unsigned int all_decomp[NUM_CODE_POINTS][2];
465ef59e75Smrg static unsigned int decomp[NUM_CODE_POINTS][2];
475ef59e75Smrg static unsigned char combining_value[NUM_CODE_POINTS];
48c3d31fe1Smrg 
49c3d31fe1Smrg /* Die!  */
50c3d31fe1Smrg 
51c3d31fe1Smrg static void
fail(const char * s)52c3d31fe1Smrg fail (const char *s)
53c3d31fe1Smrg {
54c3d31fe1Smrg   fprintf (stderr, "%s\n", s);
55c3d31fe1Smrg   exit (1);
56c3d31fe1Smrg }
57c3d31fe1Smrg 
585ef59e75Smrg /* Read ucnid.tab and set the flags for language versions in header[].  */
59c3d31fe1Smrg 
60c3d31fe1Smrg static void
read_ucnid(const char * fname)61c3d31fe1Smrg read_ucnid (const char *fname)
62c3d31fe1Smrg {
63c3d31fe1Smrg   FILE *f = fopen (fname, "r");
64c3d31fe1Smrg   unsigned fl = 0;
65c3d31fe1Smrg 
66c3d31fe1Smrg   if (!f)
67c3d31fe1Smrg     fail ("opening ucnid.tab");
68c3d31fe1Smrg   for (;;)
69c3d31fe1Smrg     {
70c3d31fe1Smrg       char line[256];
71c3d31fe1Smrg 
72c3d31fe1Smrg       if (!fgets (line, sizeof (line), f))
73c3d31fe1Smrg 	break;
74c3d31fe1Smrg       if (strcmp (line, "[C99]\n") == 0)
75c3d31fe1Smrg 	fl = C99;
765ef59e75Smrg       else if (strcmp (line, "[C99DIG]\n") == 0)
775ef59e75Smrg 	fl = C99|N99;
78c3d31fe1Smrg       else if (strcmp (line, "[CXX]\n") == 0)
79c3d31fe1Smrg 	fl = CXX;
805ef59e75Smrg       else if (strcmp (line, "[C11]\n") == 0)
815ef59e75Smrg 	fl = C11;
825ef59e75Smrg       else if (strcmp (line, "[C11NOSTART]\n") == 0)
835ef59e75Smrg 	fl = C11|N11;
84c3d31fe1Smrg       else if (isxdigit (line[0]))
85c3d31fe1Smrg 	{
86c3d31fe1Smrg 	  char *l = line;
87c3d31fe1Smrg 	  while (*l)
88c3d31fe1Smrg 	    {
89c3d31fe1Smrg 	      unsigned long start, end;
90c3d31fe1Smrg 	      char *endptr;
91c3d31fe1Smrg 	      start = strtoul (l, &endptr, 16);
92c3d31fe1Smrg 	      if (endptr == l || (*endptr != '-' && ! isspace (*endptr)))
93c3d31fe1Smrg 		fail ("parsing ucnid.tab [1]");
94c3d31fe1Smrg 	      l = endptr;
95c3d31fe1Smrg 	      if (*l != '-')
96c3d31fe1Smrg 		end = start;
97c3d31fe1Smrg 	      else
98c3d31fe1Smrg 		{
99c3d31fe1Smrg 		  end = strtoul (l + 1, &endptr, 16);
100c3d31fe1Smrg 		  if (end < start)
101c3d31fe1Smrg 		    fail ("parsing ucnid.tab, end before start");
102c3d31fe1Smrg 		  l = endptr;
103c3d31fe1Smrg 		  if (! isspace (*l))
104c3d31fe1Smrg 		    fail ("parsing ucnid.tab, junk after range");
105c3d31fe1Smrg 		}
106c3d31fe1Smrg 	      while (isspace (*l))
107c3d31fe1Smrg 		l++;
1085ef59e75Smrg 	      if (end > MAX_CODE_POINT)
109c3d31fe1Smrg 		fail ("parsing ucnid.tab, end too large");
110c3d31fe1Smrg 	      while (start <= end)
111c3d31fe1Smrg 		flags[start++] |= fl;
112c3d31fe1Smrg 	    }
113c3d31fe1Smrg 	}
114c3d31fe1Smrg     }
115c3d31fe1Smrg   if (ferror (f))
116c3d31fe1Smrg     fail ("reading ucnid.tab");
117c3d31fe1Smrg   fclose (f);
118c3d31fe1Smrg }
119c3d31fe1Smrg 
1205ef59e75Smrg /* Read UnicodeData.txt and fill in the 'decomp' table to be the
1215ef59e75Smrg    decompositions of characters for which both the character
1225ef59e75Smrg    decomposed and all the code points in the decomposition are valid
1235ef59e75Smrg    for some supported language version, and the 'all_decomp' table to
1245ef59e75Smrg    be the decompositions of all characters without those
1255ef59e75Smrg    constraints.  */
126c3d31fe1Smrg 
127c3d31fe1Smrg static void
read_table(char * fname)128c3d31fe1Smrg read_table (char *fname)
129c3d31fe1Smrg {
130c3d31fe1Smrg   FILE * f = fopen (fname, "r");
131c3d31fe1Smrg 
132c3d31fe1Smrg   if (!f)
133c3d31fe1Smrg     fail ("opening UnicodeData.txt");
134c3d31fe1Smrg   for (;;)
135c3d31fe1Smrg     {
136c3d31fe1Smrg       char line[256];
137c3d31fe1Smrg       unsigned long codepoint, this_decomp[4];
138c3d31fe1Smrg       char *l;
1395ef59e75Smrg       int i, j;
140c3d31fe1Smrg       int decomp_useful;
141c3d31fe1Smrg 
142c3d31fe1Smrg       if (!fgets (line, sizeof (line), f))
143c3d31fe1Smrg 	break;
144c3d31fe1Smrg       codepoint = strtoul (line, &l, 16);
145c3d31fe1Smrg       if (l == line || *l != ';')
146c3d31fe1Smrg 	fail ("parsing UnicodeData.txt, reading code point");
1475ef59e75Smrg       if (codepoint > MAX_CODE_POINT)
1485ef59e75Smrg 	fail ("parsing UnicodeData.txt, code point too large");
149c3d31fe1Smrg 
150c3d31fe1Smrg       do {
151c3d31fe1Smrg 	l++;
152c3d31fe1Smrg       } while (*l != ';');
1535ef59e75Smrg       /* Category value.  */
154c3d31fe1Smrg       do {
155c3d31fe1Smrg 	l++;
156c3d31fe1Smrg       } while (*l != ';');
157c3d31fe1Smrg       /* Canonical combining class; in NFC/NFKC, they must be increasing
158c3d31fe1Smrg 	 (or zero).  */
159c3d31fe1Smrg       if (! isdigit (*++l))
160c3d31fe1Smrg 	fail ("parsing UnicodeData.txt, combining class not number");
161c3d31fe1Smrg       combining_value[codepoint] = strtoul (l, &l, 10);
162c3d31fe1Smrg       if (*l++ != ';')
163c3d31fe1Smrg 	fail ("parsing UnicodeData.txt, junk after combining class");
164c3d31fe1Smrg 
165c3d31fe1Smrg       /* Skip over bidi value.  */
166c3d31fe1Smrg       do {
167c3d31fe1Smrg 	l++;
168c3d31fe1Smrg       } while (*l != ';');
169c3d31fe1Smrg 
170c3d31fe1Smrg       /* Decomposition mapping.  */
171c3d31fe1Smrg       decomp_useful = flags[codepoint];
172c3d31fe1Smrg       if (*++l == '<')  /* Compatibility mapping. */
173c3d31fe1Smrg 	continue;
174c3d31fe1Smrg       for (i = 0; i < 4; i++)
175c3d31fe1Smrg 	{
176c3d31fe1Smrg 	  if (*l == ';')
177c3d31fe1Smrg 	    break;
178c3d31fe1Smrg 	  if (!isxdigit (*l))
179c3d31fe1Smrg 	    fail ("parsing UnicodeData.txt, decomposition format");
180c3d31fe1Smrg 	  this_decomp[i] = strtoul (l, &l, 16);
181c3d31fe1Smrg 	  decomp_useful &= flags[this_decomp[i]];
182c3d31fe1Smrg 	  while (isspace (*l))
183c3d31fe1Smrg 	    l++;
184c3d31fe1Smrg 	}
185c3d31fe1Smrg       if (i > 2)  /* Decomposition too long.  */
186c3d31fe1Smrg 	fail ("parsing UnicodeData.txt, decomposition too long");
1875ef59e75Smrg       for (j = 0; j < i; j++)
1885ef59e75Smrg 	all_decomp[codepoint][j] = this_decomp[j];
1895ef59e75Smrg       if ((flags[codepoint] & all_languages) && decomp_useful)
190c3d31fe1Smrg 	while (--i >= 0)
191c3d31fe1Smrg 	  decomp[codepoint][i] = this_decomp[i];
192c3d31fe1Smrg     }
193c3d31fe1Smrg   if (ferror (f))
194c3d31fe1Smrg     fail ("reading UnicodeData.txt");
195c3d31fe1Smrg   fclose (f);
196c3d31fe1Smrg }
197c3d31fe1Smrg 
198c3d31fe1Smrg /* Read DerivedNormalizationProps.txt and set the flags that say whether
199c3d31fe1Smrg    a character is in NFC, NFKC, or is context-dependent.  */
200c3d31fe1Smrg 
201c3d31fe1Smrg static void
read_derived(const char * fname)202c3d31fe1Smrg read_derived (const char *fname)
203c3d31fe1Smrg {
204c3d31fe1Smrg   FILE * f = fopen (fname, "r");
205c3d31fe1Smrg 
206c3d31fe1Smrg   if (!f)
207c3d31fe1Smrg     fail ("opening DerivedNormalizationProps.txt");
208c3d31fe1Smrg   for (;;)
209c3d31fe1Smrg     {
210c3d31fe1Smrg       char line[256];
211c3d31fe1Smrg       unsigned long start, end;
212c3d31fe1Smrg       char *l;
213c3d31fe1Smrg       bool not_NFC_p, not_NFKC_p, maybe_not_NFC_p;
214c3d31fe1Smrg 
215c3d31fe1Smrg       if (!fgets (line, sizeof (line), f))
216c3d31fe1Smrg 	break;
217c3d31fe1Smrg       not_NFC_p = (strstr (line, "; NFC_QC; N") != NULL);
218c3d31fe1Smrg       not_NFKC_p = (strstr (line, "; NFKC_QC; N") != NULL);
219c3d31fe1Smrg       maybe_not_NFC_p = (strstr (line, "; NFC_QC; M") != NULL);
220c3d31fe1Smrg       if (! not_NFC_p && ! not_NFKC_p && ! maybe_not_NFC_p)
221c3d31fe1Smrg 	continue;
222c3d31fe1Smrg 
223c3d31fe1Smrg       start = strtoul (line, &l, 16);
224c3d31fe1Smrg       if (l == line)
225c3d31fe1Smrg 	fail ("parsing DerivedNormalizationProps.txt, reading start");
2265ef59e75Smrg       if (start > MAX_CODE_POINT)
2275ef59e75Smrg 	fail ("parsing DerivedNormalizationProps.txt, code point too large");
228c3d31fe1Smrg       if (*l == '.' && l[1] == '.')
229c3d31fe1Smrg 	end = strtoul (l + 2, &l, 16);
230c3d31fe1Smrg       else
231c3d31fe1Smrg 	end = start;
232c3d31fe1Smrg 
233c3d31fe1Smrg       while (start <= end)
234c3d31fe1Smrg 	flags[start++] |= ((not_NFC_p ? not_NFC : 0)
235c3d31fe1Smrg 			   | (not_NFKC_p ? not_NFKC : 0)
236c3d31fe1Smrg 			   | (maybe_not_NFC_p ? maybe_not_NFC : 0)
237c3d31fe1Smrg 			   );
238c3d31fe1Smrg     }
239c3d31fe1Smrg   if (ferror (f))
240c3d31fe1Smrg     fail ("reading DerivedNormalizationProps.txt");
241c3d31fe1Smrg   fclose (f);
242c3d31fe1Smrg }
243c3d31fe1Smrg 
244c3d31fe1Smrg /* Write out the table.
245c3d31fe1Smrg    The table consists of two words per entry.  The first word is the flags
246c3d31fe1Smrg    for the unicode code points up to and including the second word.  */
247c3d31fe1Smrg 
248c3d31fe1Smrg static void
write_table(void)249c3d31fe1Smrg write_table (void)
250c3d31fe1Smrg {
251c3d31fe1Smrg   unsigned i;
252c3d31fe1Smrg   unsigned last_flag = flags[0];
253c3d31fe1Smrg   bool really_safe = decomp[0][0] == 0;
254c3d31fe1Smrg   unsigned char last_combine = combining_value[0];
255c3d31fe1Smrg 
2565ef59e75Smrg   printf ("static const struct ucnrange ucnranges[] = {\n");
2575ef59e75Smrg 
2585ef59e75Smrg   for (i = 1; i <= NUM_CODE_POINTS; i++)
2595ef59e75Smrg     if (i == NUM_CODE_POINTS
2605ef59e75Smrg 	|| (flags[i] != last_flag && ((flags[i] | last_flag) & all_languages))
261c3d31fe1Smrg 	|| really_safe != (decomp[i][0] == 0)
262c3d31fe1Smrg 	|| combining_value[i] != last_combine)
263c3d31fe1Smrg       {
2645ef59e75Smrg 	printf ("{ %s|%s|%s|%s|%s|%s|%s|%s|%s, %3d, %#06x },\n",
265c3d31fe1Smrg 		last_flag & C99 ? "C99" : "  0",
2665ef59e75Smrg 		last_flag & N99 ? "N99" : "  0",
267c3d31fe1Smrg 		last_flag & CXX ? "CXX" : "  0",
2685ef59e75Smrg 		last_flag & C11 ? "C11" : "  0",
2695ef59e75Smrg 		last_flag & N11 ? "N11" : "  0",
270c3d31fe1Smrg 		really_safe ? "CID" : "  0",
271c3d31fe1Smrg 		last_flag & not_NFC ? "  0" : "NFC",
272c3d31fe1Smrg 		last_flag & not_NFKC ? "  0" : "NKC",
273c3d31fe1Smrg 		last_flag & maybe_not_NFC ? "CTX" : "  0",
274c3d31fe1Smrg 		combining_value[i - 1],
275c3d31fe1Smrg 		i - 1);
276c3d31fe1Smrg 	last_flag = flags[i];
277c3d31fe1Smrg 	last_combine = combining_value[0];
278c3d31fe1Smrg 	really_safe = decomp[i][0] == 0;
279c3d31fe1Smrg       }
2805ef59e75Smrg 
2815ef59e75Smrg   printf ("};\n");
2825ef59e75Smrg }
2835ef59e75Smrg 
2845ef59e75Smrg /* Return whether a given character is valid in an identifier for some
2855ef59e75Smrg    supported language, either as itself or as a UCN.  */
2865ef59e75Smrg 
2875ef59e75Smrg static bool
char_id_valid(unsigned int c)2885ef59e75Smrg char_id_valid (unsigned int c)
2895ef59e75Smrg {
2905ef59e75Smrg   return ((flags[c] & all_languages)
2915ef59e75Smrg 	  || (c == 0x24)
2925ef59e75Smrg 	  || (c >= 0x30 && c <= 0x39)
2935ef59e75Smrg 	  || (c >= 0x41 && c <= 0x5a)
2945ef59e75Smrg 	  || (c >= 0x61 && c <= 0x7a));
2955ef59e75Smrg }
2965ef59e75Smrg 
2975ef59e75Smrg /* Write out the switch statement over characters for which it is
2985ef59e75Smrg    context-dependent whether they are in NFC.  */
2995ef59e75Smrg 
3005ef59e75Smrg static void
write_context_switch(void)3015ef59e75Smrg write_context_switch (void)
3025ef59e75Smrg {
3035ef59e75Smrg   unsigned i;
3045ef59e75Smrg   printf ("static bool\n"
3055ef59e75Smrg 	  "check_nfc (cpp_reader *pfile, cppchar_t c, cppchar_t p)\n"
3065ef59e75Smrg 	  "{\n"
3075ef59e75Smrg 	  "  switch (c)\n"
3085ef59e75Smrg 	  "    {\n");
3095ef59e75Smrg   for (i = 0; i < NUM_CODE_POINTS; i++)
3105ef59e75Smrg     {
3115ef59e75Smrg       bool found_case = false;
3125ef59e75Smrg       unsigned j;
3135ef59e75Smrg       if (!(flags[i] & all_languages) || !(flags[i] & maybe_not_NFC))
3145ef59e75Smrg 	continue;
3155ef59e75Smrg       if ((i >= 0x1161 && i <= 0x1175) || (i >= 0x11A8 && i <= 0x11C2))
3165ef59e75Smrg 	continue; /* Hangul handled algorithmically.  */
3175ef59e75Smrg       printf ("    case %#06x:\n"
3185ef59e75Smrg 	      "      switch (p)\n"
3195ef59e75Smrg 	      "\t{\n", i);
3205ef59e75Smrg       /* If an NFC starter character decomposes with this character I
3215ef59e75Smrg 	 as the second character and an NFC starter character S as the
3225ef59e75Smrg 	 first character, that latter character as a previous
3235ef59e75Smrg 	 character means this character is not NFC.  Furthermore, any
3245ef59e75Smrg 	 NFC starter character K made by a series of compositions of S
3255ef59e75Smrg 	 with combining characters whose combining class is greater
3265ef59e75Smrg 	 than that of I also means this character is not NFC.  */
3275ef59e75Smrg       for (j = 0; j < NUM_CODE_POINTS; j++)
3285ef59e75Smrg 	{
3295ef59e75Smrg 	  unsigned s, k;
3305ef59e75Smrg 	  if (all_decomp[j][1] != i)
3315ef59e75Smrg 	    continue;
3325ef59e75Smrg 	  s = all_decomp[j][0];
3335ef59e75Smrg 	  if (combining_value[s] != 0 || (flags[s] & not_NFC) != 0)
3345ef59e75Smrg 	    continue;
3355ef59e75Smrg 	  if (char_id_valid (s))
3365ef59e75Smrg 	    {
3375ef59e75Smrg 	      found_case = true;
3385ef59e75Smrg 	      printf ("\tcase %#06x:\n", s);
3395ef59e75Smrg 	    }
3405ef59e75Smrg 	  for (k = 0; k < NUM_CODE_POINTS; k++)
3415ef59e75Smrg 	    {
3425ef59e75Smrg 	      unsigned t = k;
3435ef59e75Smrg 	      if (k == s || !char_id_valid (k))
3445ef59e75Smrg 		continue;
3455ef59e75Smrg 	      while (all_decomp[t][1] != 0
3465ef59e75Smrg 		     && combining_value[all_decomp[t][1]] > combining_value[i])
3475ef59e75Smrg 		{
3485ef59e75Smrg 		  if (combining_value[t] != 0 || (flags[t] & not_NFC) != 0)
3495ef59e75Smrg 		    break;
3505ef59e75Smrg 		  t = all_decomp[t][0];
3515ef59e75Smrg 		}
3525ef59e75Smrg 	      if (t == s)
3535ef59e75Smrg 		{
3545ef59e75Smrg 		  found_case = true;
3555ef59e75Smrg 		  printf ("\tcase %#06x:\n", k);
3565ef59e75Smrg 		}
3575ef59e75Smrg 	    }
3585ef59e75Smrg 	}
3595ef59e75Smrg       if (found_case)
3605ef59e75Smrg 	printf ("\t  return false;\n");
3615ef59e75Smrg       else
3625ef59e75Smrg 	printf ("\t/* Non-NFC cases not applicable to C/C++.  */\n");
3635ef59e75Smrg       printf ("\tdefault:\n"
3645ef59e75Smrg 	      "\t  return true;\n"
3655ef59e75Smrg 	      "\t}\n\n");
3665ef59e75Smrg     }
3675ef59e75Smrg   printf ("    default:\n"
3685ef59e75Smrg 	  "      cpp_error (pfile, CPP_DL_ICE, \"Character %%x might not be NFKC\", c);\n"
3695ef59e75Smrg 	  "      return true;\n"
3705ef59e75Smrg 	  "  }\n"
3715ef59e75Smrg 	  "}\n");
372c3d31fe1Smrg }
373c3d31fe1Smrg 
374c3d31fe1Smrg /* Print out the huge copyright notice.  */
375c3d31fe1Smrg 
376c3d31fe1Smrg static void
write_copyright(void)377c3d31fe1Smrg write_copyright (void)
378c3d31fe1Smrg {
379c3d31fe1Smrg   static const char copyright[] = "\
380c3d31fe1Smrg /* Unicode characters and various properties.\n\
381*dd083157Smrg    Copyright (C) 2003-2020 Free Software Foundation, Inc.\n\
382c3d31fe1Smrg \n\
383c3d31fe1Smrg    This program is free software; you can redistribute it and/or modify it\n\
384c3d31fe1Smrg    under the terms of the GNU General Public License as published by the\n\
385c3d31fe1Smrg    Free Software Foundation; either version 3, or (at your option) any\n\
386c3d31fe1Smrg    later version.\n\
387c3d31fe1Smrg \n\
388c3d31fe1Smrg    This program is distributed in the hope that it will be useful,\n\
389c3d31fe1Smrg    but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
390c3d31fe1Smrg    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\
391c3d31fe1Smrg    GNU General Public License for more details.\n\
392c3d31fe1Smrg \n\
393c3d31fe1Smrg    You should have received a copy of the GNU General Public License\n\
394c3d31fe1Smrg    along with this program; see the file COPYING3.  If not see\n\
395c3d31fe1Smrg    <http://www.gnu.org/licenses/>.\n\
396c3d31fe1Smrg \n\
397c3d31fe1Smrg \n\
398c3d31fe1Smrg    Copyright (C) 1991-2005 Unicode, Inc.  All rights reserved.\n\
399c3d31fe1Smrg    Distributed under the Terms of Use in\n\
400c3d31fe1Smrg    http://www.unicode.org/copyright.html.\n\
401c3d31fe1Smrg \n\
402c3d31fe1Smrg    Permission is hereby granted, free of charge, to any person\n\
403c3d31fe1Smrg    obtaining a copy of the Unicode data files and any associated\n\
404c3d31fe1Smrg    documentation (the \"Data Files\") or Unicode software and any\n\
405c3d31fe1Smrg    associated documentation (the \"Software\") to deal in the Data Files\n\
406c3d31fe1Smrg    or Software without restriction, including without limitation the\n\
407c3d31fe1Smrg    rights to use, copy, modify, merge, publish, distribute, and/or\n\
408c3d31fe1Smrg    sell copies of the Data Files or Software, and to permit persons to\n\
409c3d31fe1Smrg    whom the Data Files or Software are furnished to do so, provided\n\
410c3d31fe1Smrg    that (a) the above copyright notice(s) and this permission notice\n\
411c3d31fe1Smrg    appear with all copies of the Data Files or Software, (b) both the\n\
412c3d31fe1Smrg    above copyright notice(s) and this permission notice appear in\n\
413c3d31fe1Smrg    associated documentation, and (c) there is clear notice in each\n\
414c3d31fe1Smrg    modified Data File or in the Software as well as in the\n\
415c3d31fe1Smrg    documentation associated with the Data File(s) or Software that the\n\
416c3d31fe1Smrg    data or software has been modified.\n\
417c3d31fe1Smrg \n\
418c3d31fe1Smrg    THE DATA FILES AND SOFTWARE ARE PROVIDED \"AS IS\", WITHOUT WARRANTY\n\
419c3d31fe1Smrg    OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n\
420c3d31fe1Smrg    WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n\
421c3d31fe1Smrg    NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE\n\
422c3d31fe1Smrg    COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR\n\
423c3d31fe1Smrg    ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY\n\
424c3d31fe1Smrg    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,\n\
425c3d31fe1Smrg    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS\n\
426c3d31fe1Smrg    ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE\n\
427c3d31fe1Smrg    OF THE DATA FILES OR SOFTWARE.\n\
428c3d31fe1Smrg \n\
429c3d31fe1Smrg    Except as contained in this notice, the name of a copyright holder\n\
430c3d31fe1Smrg    shall not be used in advertising or otherwise to promote the sale,\n\
431c3d31fe1Smrg    use or other dealings in these Data Files or Software without prior\n\
432c3d31fe1Smrg    written authorization of the copyright holder.  */\n";
433c3d31fe1Smrg 
434c3d31fe1Smrg    puts (copyright);
435c3d31fe1Smrg }
436c3d31fe1Smrg 
437c3d31fe1Smrg /* Main program.  */
438c3d31fe1Smrg 
439c3d31fe1Smrg int
main(int argc,char ** argv)440c3d31fe1Smrg main(int argc, char ** argv)
441c3d31fe1Smrg {
442c3d31fe1Smrg   if (argc != 4)
443c3d31fe1Smrg     fail ("too few arguments to makeucn");
444c3d31fe1Smrg   read_ucnid (argv[1]);
445c3d31fe1Smrg   read_table (argv[2]);
446c3d31fe1Smrg   read_derived (argv[3]);
447c3d31fe1Smrg 
448c3d31fe1Smrg   write_copyright ();
449c3d31fe1Smrg   write_table ();
4505ef59e75Smrg   write_context_switch ();
451c3d31fe1Smrg   return 0;
452c3d31fe1Smrg }
453