diff options
Diffstat (limited to 'unitbl2c.c')
| -rw-r--r-- | unitbl2c.c | 206 |
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; +} |
