makeucnid.cc revision 1.1 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