aboutsummaryrefslogtreecommitdiff
path: root/unitbl2c.c
diff options
context:
space:
mode:
Diffstat (limited to 'unitbl2c.c')
-rw-r--r--unitbl2c.c206
1 files changed, 206 insertions, 0 deletions
diff --git a/unitbl2c.c b/unitbl2c.c
new file mode 100644
index 0000000..f2e76cc
--- /dev/null
+++ b/unitbl2c.c
@@ -0,0 +1,206 @@
+/*
+ * VBSF - generate C file with codepage -> unicode tables based on uni*.tbl files
+ * Copyright (C) 2022 Javier S. Pedro
+ *
+ * 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 Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <libgen.h>
+#include <ctype.h>
+#include <string.h>
+
+/** size of codepage -> unicode table */
+#define TBL_SIZE 128 /* in 16bit words */
+/** maximum number of codepages in the same C file */
+#define MAX_CPS 32
+
+static FILE *fout;
+static unsigned all_cps[MAX_CPS] = {0};
+static unsigned num_cps = 0;
+
+static void print_table(const uint16_t *table, unsigned cp)
+{
+ int i;
+ int col = 0;
+
+ fprintf(fout, "static const uint16_t cp%utbl[%u] = {\n ", cp, TBL_SIZE);
+
+ for (i = 0; i < TBL_SIZE; i++)
+ {
+ if (col)
+ {
+ fprintf(fout, ", ");
+ }
+ if (col >= 8)
+ {
+ fprintf(fout, "\n ");
+ col = 0;
+ }
+ fprintf(fout, "0x%04X", table[i]);
+ col++;
+ }
+
+ fprintf(fout, "\n};\n\n");
+}
+
+static int process_table(FILE *fp, const char *base, unsigned cp)
+{
+ char buffer[TBL_SIZE*2];
+ int err;
+
+ // Read "Description of table" (terminated by \r\n)
+ if (!fgets(buffer, sizeof(buffer), fp)) {
+ return -1;
+ }
+
+ fprintf(fout, "// %s", buffer);
+
+ // Read "Table format designator" (currently only format 1 is supported)
+ err = fread(buffer, 1, 1, fp);
+ if (err != 1 || buffer[0] != 1) {
+ return -1;
+ }
+
+ // Now read the actual table (256 bytes in format 1)
+ if ((err = fread(buffer, 1, sizeof(buffer), fp)) != sizeof(buffer)) {
+ return -1;
+ }
+
+ print_table((const uint16_t *)buffer, cp);
+
+ all_cps[num_cps++] = cp;
+
+ return 0;
+}
+
+static int process_file(char *filename)
+{
+ FILE *fp = fopen(filename, "rb");
+ char *base = basename(filename);
+ unsigned cp = 0;
+
+ if (!fp) {
+ fprintf(stderr, "Cannot open file '%s'\n", filename);
+ return -1;
+ }
+
+ if (strnicmp(&base[0], "CP", 2) == 0
+ && isdigit(base[2]) && isdigit(base[3]) && isdigit(base[4])
+ && strnicmp(&base[5], "UNI.TBL", 7) == 0) {
+ cp = atoi(&base[2]);
+ } else if (strnicmp(&base[0], "C", 2) == 0
+ && isdigit(base[1]) && isdigit(base[2]) && isdigit(base[3]) && isdigit(base[4])
+ && strnicmp(&base[5], "UNI.TBL", 7) == 0) {
+ cp = atoi(&base[1]);
+ }
+
+ if (!cp) {
+ fprintf(stderr, "Cannot guess codepage number from filename '%s'\n", base);
+ fclose(fp);
+ return -1;
+ }
+
+ if (process_table(fp, base, cp) != 0) {
+ fprintf(stderr, "Cannot read table format from '%s'\n", base);
+ fclose(fp);
+ return -1;
+ }
+
+ fclose(fp);
+ return 0;
+}
+
+#ifdef __UNIX__
+// no need to process wildcards on UNIX
+static int process_arg(char *arg)
+{
+ return process_file(arg);
+}
+#else
+#include <io.h>
+
+static int process_arg(char *arg)
+{
+ struct _finddata_t fileinfo;
+ intptr_t fh = _findfirst(arg, &fileinfo);
+
+ if (!fh) {
+ fprintf(stderr, "Cannot find '%s'\n", arg);
+ return -1;
+ }
+
+ do {
+ // Name of file in fileinfo will be without path
+ // If so copy the path from the arg
+ char namebuf[_MAX_PATH];
+ char *s;
+
+ if ((s = strrchr(arg, '\\')) || (s = strrchr(arg, '/')) || (s = strrchr(arg, ':'))) {
+ memcpy(namebuf, arg, s-arg+1);
+ strcpy(namebuf + (s-arg) +1, fileinfo.name);
+ } else {
+ strcpy(namebuf, fileinfo.name);
+ }
+
+ if (process_file(namebuf) != 0) {
+ return -1;
+ }
+ } while (_findnext(fh, &fileinfo) == 0);
+
+ return 0;
+}
+#endif
+
+int main(int argc, char **argv)
+{
+ int i;
+
+ if (argc < 3)
+ {
+ fprintf(stderr,
+ "Usage: bin2c <output c file> <unitbl/*.tbl>\n");
+ return 1;
+ }
+
+ fout = fopen(argv[1], "wt");
+ fprintf(fout, "#include <stdint.h>\n");
+
+ for (i = 2; i < argc; i++) {
+ if (process_arg(argv[i])) {
+ return EXIT_FAILURE;
+ }
+ }
+
+ fprintf(fout, "static const uint16_t * get_uni_tbl(unsigned cp) {\n");
+ fprintf(fout, " switch (cp) {\n");
+ for (i = 0; i < num_cps; i++) {
+ unsigned cp = all_cps[i];
+ fprintf(fout, " case %u:\n", cp);
+ fprintf(fout, " return cp%utbl;\n", cp);
+ }
+ fprintf(fout, " default:\n");
+ fprintf(fout, " return 0;\n");
+ fprintf(fout, " }\n");
+ fprintf(fout, "}\n\n");
+
+ fclose(fout);
+
+ printf("Processed %u tables\n", num_cps);
+
+ return EXIT_SUCCESS;
+}