/* * 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 #include #include #include #include #include /** 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 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 \n"); return 1; } fout = fopen(argv[1], "wt"); fprintf(fout, "#include \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; }