summaryrefslogtreecommitdiff
path: root/src/tools
diff options
context:
space:
mode:
authorpeter <peter@pmikkelsen.com>2026-09-25 21:05:33 +0000
committerpeter <peter@pmikkelsen.com>2026-09-25 21:05:33 +0000
commitd44806e3ef366124a5be61a6ece1caf6b014b22f (patch)
treee623fb0b13891023e6218e0d9e4d58d51d34c7bb /src/tools
parent1e88f84ab887be0330585fdb7b8eeb22280cc9d6 (diff)
parentbdfbb6fd4bb9be35c9c338e18dc8e9b447cfe8ca (diff)
Merge unicode-props into trunk
FossilOrigin-Name: 95c406d482112373a41982bf36f3a9159fceff5ff95162cab34e97fd0cfaa73c
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/Makefile.am10
-rw-r--r--src/tools/genboot.c19
-rw-r--r--src/tools/genunicode.c259
3 files changed, 286 insertions, 2 deletions
diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am
index b1079e7..b05ab8a 100644
--- a/src/tools/Makefile.am
+++ b/src/tools/Makefile.am
@@ -1,10 +1,16 @@
-noinst_PROGRAMS += genboot
+noinst_PROGRAMS += genboot genunicode
genboot_SOURCES = src/tools/genboot.c
+genunicode_SOURCES = src/tools/genunicode.c
BUILT_SOURCES += $(top_builddir)/generated/boot.h
-CLEANFILES += $(top_builddir)/generated/boot.h
+BUILT_SOURCES += $(top_builddir)/generated/unicode_properties.c
$(top_builddir)/generated/boot.h: genboot src/lib/boot.aplwc
$(MKDIR_P) $(top_builddir)/generated
./genboot $(top_srcdir)/src/lib/boot.aplwc > $@
+
+$(top_builddir)/generated/unicode_properties.c: genunicode src/unicode/DerivedCoreProperties.txt src/unicode/PropList.txt
+ $(MKDIR_P) $(top_builddir)/generated
+ ./genunicode $(top_srcdir)/src/unicode > $@
+
diff --git a/src/tools/genboot.c b/src/tools/genboot.c
index e89b3aa..9d0a7e4 100644
--- a/src/tools/genboot.c
+++ b/src/tools/genboot.c
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2026 Peter Mikkelsen <petermikkelsen10@gmail.com>
+ *
+ * This file is part of aplwc.
+ *
+ * Aplwc is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Aplwc is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with aplwc. If not, see <https://www.gnu.org/licenses/>.
+ */
+
#include <stdio.h>
#include <assert.h>
diff --git a/src/tools/genunicode.c b/src/tools/genunicode.c
new file mode 100644
index 0000000..76f2c60
--- /dev/null
+++ b/src/tools/genunicode.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2026 Peter Mikkelsen <petermikkelsen10@gmail.com>
+ *
+ * This file is part of aplwc.
+ *
+ * Aplwc is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Aplwc is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with aplwc. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <setjmp.h>
+
+static char *files[] = {
+ "DerivedCoreProperties.txt",
+ "PropList.txt"
+};
+
+static char *properties[] = {
+ "ID_Start",
+ "ID_Continue",
+ "Pattern_Syntax"
+};
+
+struct line {
+ int from;
+ int to;
+ int valid;
+ char property[64];
+};
+
+static void emit_line(struct line *, int *);
+static int peek(FILE *);
+static int parse_line(FILE *, struct line *);
+static int parse_int(FILE *);
+static void parse_dots(FILE *);
+static void parse_sep(FILE *);
+
+static jmp_buf env;
+
+int
+main(int argc, char *argv[])
+{
+ FILE *f;
+ char *dir, *buf;
+ size_t dir_size, tmp_size, max_size, i, j, nfiles;
+ struct line line, prev_line;
+ int current, n;
+
+ assert(argc == 2);
+ dir = argv[1];
+ dir_size = strlen(dir);
+
+ if(dir[dir_size-1] == '/')
+ dir_size--;
+
+ nfiles = sizeof(files)/sizeof(files[0]);
+
+ max_size = 0;
+ for(i = 0; i < nfiles; i++){
+ tmp_size = strlen(files[i]);
+ if(tmp_size > max_size)
+ max_size = tmp_size;
+ }
+ max_size += dir_size + 2;
+ buf = malloc(max_size);
+ assert(buf != NULL);
+ memcpy(buf, dir, dir_size);
+ buf[dir_size] = '/';
+ current = -1;
+ n = 0;
+
+ printf("enum unicode_property {");
+ for(i = 0; i < sizeof(properties)/sizeof(properties[0]); i++)
+ printf("%s%s", (i == 0) ? "\n\t" : ",\n\t", properties[i]);
+ printf("\n};\n\n");
+
+ printf("struct unicode_range {\n\tuint32_t from;\n\tuint32_t to;\n};\n\n");
+
+ for(i = 0; i < sizeof(files)/sizeof(files[0]); i++){
+ memcpy(buf+dir_size+1, files[i], strlen(files[i])+1);
+ f = fopen(buf, "r");
+ assert(f != NULL);
+
+ printf("/* %s */\n\n", files[i]);
+
+ memset(&prev_line, 0, sizeof(prev_line));
+ while(parse_line(f, &line)){
+ if(!line.valid)
+ continue;
+
+ if((current == -1) || (strcmp(line.property, properties[current]) != 0)){
+ if(current != -1){
+ emit_line(&prev_line, &n);
+ printf("\n};\n");
+ printf("#define %s_count %d\n\n", properties[current], n);
+ }
+
+ prev_line.valid = 0;
+ current = -1;
+ for(j = 0; j < sizeof(properties)/sizeof(properties[0]); j++){
+ if(strcmp(line.property, properties[j]) == 0){
+ current = j;
+ n = 0;
+ printf("static struct unicode_range %s_ranges[] = {", properties[j]);
+ break;
+ }
+ }
+ }
+
+ if(current != -1){
+ if(prev_line.valid){
+ if(prev_line.to+1 == line.from)
+ line.from = prev_line.from;
+ else
+ emit_line(&prev_line, &n);
+ }
+ prev_line = line;
+ }
+ }
+ fclose(f);
+ }
+
+ printf("static void\n");
+ printf("unicode_get(enum unicode_property p, int *n, struct unicode_range **r)\n{\n");
+ printf("\tswitch(p){\n");
+ for(i = 0; i < sizeof(properties)/sizeof(properties[0]); i++){
+ printf("\tcase %s:\n", properties[i]);
+ printf("\t\t*n = %s_count;\n", properties[i]);
+ printf("\t\t*r = %s_ranges;\n", properties[i]);
+ printf("\t\tbreak;\n");
+ }
+ printf("\t}\n}\n\n");
+
+ free(buf);
+ return 0;
+}
+
+static void
+emit_line(struct line *line, int *n)
+{
+ printf("%s{0x%X, 0x%X}", (*n == 0) ? "\n\t" : ",\n\t", line->from, line->to);
+ (*n)++;
+}
+
+static int
+peek(FILE *f)
+{
+ int c;
+
+ c = fgetc(f);
+ ungetc(c, f);
+ return c;
+}
+
+static int
+parse_line(FILE *f, struct line *l)
+{
+ int c, i;
+
+ if(setjmp(env)){
+ l->valid = 0;
+ do
+ c = fgetc(f);
+ while(c != EOF && c != '\n');
+ return c != EOF;
+ }else{
+ l->valid = 1;
+ }
+
+ l->from = parse_int(f);
+ if(peek(f) == '.'){
+ parse_dots(f);
+ l->to = parse_int(f);
+ }else{
+ l->to = l->from;
+ }
+ parse_sep(f);
+
+ for(i = 0; ; i++){
+ c = fgetc(f);
+ l->property[i] = c;
+ if(c == ' ' || c == EOF){
+ if(i == 0)
+ longjmp(env, 1);
+ break;
+ }
+ }
+ l->property[i] = 0;
+
+ for(;;){
+ c = fgetc(f);
+ if(c == '\n' || c == EOF)
+ break;
+ }
+ return 1;
+}
+
+static int
+parse_int(FILE *f)
+{
+ int n, m, c;
+
+ n = 0;
+
+ for(;;){
+ c = peek(f);
+ if((c >= '0') && (c <= '9'))
+ m = c - '0';
+ else if((c >= 'A') && (c <= 'F'))
+ m = 10 + (c - 'A');
+ else if(c == '.' || c == ' ')
+ return n;
+ else
+ longjmp(env, 1);
+ fgetc(f);
+ n <<= 4;
+ n += m;
+ }
+}
+
+static void
+parse_dots(FILE *f)
+{
+ int i;
+
+ for(i = 0; i < 2; i++){
+ if(peek(f) != '.')
+ longjmp(env, 1);
+ fgetc(f);
+ }
+}
+
+static void
+parse_sep(FILE *f)
+{
+ while(peek(f) == ' ')
+ fgetc(f);
+
+ if(peek(f) == ';')
+ fgetc(f);
+ else
+ longjmp(env, 1);
+
+ while(peek(f) == ' ')
+ fgetc(f);
+}