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