diff options
Diffstat (limited to 'tools/kons2c.c')
| -rw-r--r-- | tools/kons2c.c | 216 |
1 files changed, 13 insertions, 203 deletions
diff --git a/tools/kons2c.c b/tools/kons2c.c index 8cacbc8..2a53520 100644 --- a/tools/kons2c.c +++ b/tools/kons2c.c @@ -25,31 +25,16 @@ /* * usage: kons2c [-n name] [-split rows] <script.kons> <output prefix> - * turns konscript text into C. any converter can write konscript text, this is the one place that writes C from it. - * - * the text goes through the real parser first, so every jump lands on a label that is there, and nothing is written if it - * doesn't parse. what comes out is only constant data: a list of kon_cmd_t, a sorted list of labels and a find function. - * strings are written as literals where everything but plain printable characters is an octal escape, so what is in the - * script can't be anything but text to the compiler. there is no pointer arithmetic, no generated logic and nothing to overrun - * - * writes prefix.h and prefix.c, and with -split also prefix_0.inc, prefix_1.inc and so on that prefix.c includes inside - * the one array, so a big script is several files for the editor and one list for the program + * konscript text to C, for scripts written by hand. the converters write C themselves through konscriptc.h */ -#include "konscript.h" +#define KONSCRIPTC_IMPLEMENTATION +#include "konscriptc.h" -#include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -static const char *const opNames[] = { - "KON_OP_END", "KON_OP_SAY", "KON_OP_MENU", "KON_OP_OPTION", "KON_OP_JUMP", "KON_OP_SWITCH", "KON_OP_VAR", - "KON_OP_IFSWITCH", "KON_OP_IFVAR", "KON_OP_WAIT", "KON_OP_HOST", "KON_OP_CALL", "KON_OP_RETURN" -}; - -/*** reading ***/ - static char *readFile(const char *path, size_t *size) { FILE *f = fopen(path, "rb"); @@ -72,86 +57,14 @@ static char *readFile(const char *path, size_t *size) return text; } -static int compareLabels(const void *a, const void *b) -{ - return strcmp(((const kon_scriptLabel_t *)a)->name, ((const kon_scriptLabel_t *)b)->name); -} - -/*** writing ***/ - -static int putString(FILE *f, const char *s) -{ - size_t i, column = 0; - - if (!s) return fputs("NULL", f) >= 0; - fputc('"', f); - for (i = 0; s[i]; i++) { - unsigned char c = (unsigned char)s[i]; - - if (column >= 100) { - fputs("\"\n\t\t\"", f); - column = 0; - } - if (c == '"' || c == '\\' || c == '?') { - fprintf(f, "\\%c", c); - column += 2; - } else if (c == '\n' || c == '\t') { - fputs(c == '\n' ? "\\n" : "\\t", f); - column += 2; - } else if (c >= 0x20 && c < 0x7F) { - fputc(c, f); - column++; - } else { - fprintf(f, "\\%03o", c); - column += 4; - } - } - fputc('"', f); - return 1; -} - -static void putRow(FILE *f, const kon_cmd_t *c) -{ - fprintf(f, "\t{%s, %d, %d, %d, %d, ", opNames[c->op], c->a, c->b, c->c, c->d); - putString(f, c->text); - fputs("},\n", f); -} - -static void identifier(char *out, size_t size, const char *path) -{ - const char *base = strrchr(path, '/'); - size_t i, n = 0; - - base = base ? base + 1 : path; - for (i = 0; base[i] && base[i] != '.' && n + 1 < size; i++) out[n++] = isalnum((unsigned char)base[i]) ? (char)tolower((unsigned char)base[i]) : '_'; - out[n] = '\0'; - if (!n || isdigit((unsigned char)out[0])) { - memmove(out + 1, out, n + 1 < size ? n + 1 : size - 1); - out[0] = 'k'; - } -} - -static FILE *create(const char *prefix, const char *suffix) -{ - char path[1024]; - FILE *f; - - if (snprintf(path, sizeof path, "%s%s", prefix, suffix) >= (int)sizeof path) return NULL; - f = fopen(path, "wb"); - if (!f) fprintf(stderr, "cannot write %s\n", path); - return f; -} - int main(int argc, char **argv) { - char name[64] = "", upper[64]; + char name[64] = "", error[200]; const char *input = NULL, *prefix = NULL; - int split = 0, i, rows, lines = 1; - size_t size, k; + int split = 0, i; + size_t size; char *source; - kon_scriptBuild_t b; - kon_cmd_t *cmds; - FILE *f; + konsc_result_t result; for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-n") && i + 1 < argc) { @@ -164,125 +77,22 @@ int main(int argc, char **argv) prefix = argv[i]; } } - if (!input || !prefix || split < 0) { + if (!input || !prefix) { fprintf(stderr, "usage: kons2c [-n name] [-split rows] <script.kons> <output prefix>\n"); return 2; } - if (!name[0]) identifier(name, sizeof name, prefix); - for (k = 0; name[k]; k++) { - if (!isalnum((unsigned char)name[k]) && name[k] != '_') { - fprintf(stderr, "the name has to be letters, digits and _\n"); - return 2; - } - upper[k] = (char)toupper((unsigned char)name[k]); - } - upper[k] = '\0'; - if (isdigit((unsigned char)name[0])) { - fprintf(stderr, "the name can't start with a digit\n"); - return 2; - } - + if (!name[0]) konsc_name(name, sizeof name, prefix); source = readFile(input, &size); if (!source) { fprintf(stderr, "cannot read %s\n", input); return 1; } - for (k = 0; k < size; k++) { - if (source[k] == '\n') lines++; - } - - memset(&b, 0, sizeof b); - b.maxCmds = lines + 2; - b.maxLabels = lines + 2; - b.poolSize = (int)(size + 16); - b.hashSize = 16; - while (b.hashSize < 2 * b.maxLabels) b.hashSize *= 2; - cmds = malloc((size_t)b.maxCmds * sizeof *cmds); - b.cmds = cmds; - b.pool = malloc((size_t)b.poolSize); - b.labels = malloc((size_t)b.maxLabels * sizeof *b.labels); - b.hash = malloc((size_t)b.hashSize * sizeof *b.hash); - if (size > 2000000000u || !cmds || !b.pool || !b.labels || !b.hash) { - fprintf(stderr, "out of memory\n"); - return 1; - } - if (!kon_scriptParse(&b, source)) { - fprintf(stderr, "%s:%d: %s\n", input, b.errorLine, b.error); + if (konsc_write(source, size, prefix, name, split, &result, error, sizeof error) != 0) { + fprintf(stderr, "%s: %s\n", input, error); + free(source); return 1; } - - /* a label at the very end would point past the list, so the list gets an end of its own to land on */ - cmds[b.count].op = KON_OP_END; - cmds[b.count].a = cmds[b.count].b = cmds[b.count].c = cmds[b.count].d = 0; - cmds[b.count].text = NULL; - rows = b.count + 1; - qsort(b.labels, (size_t)b.labelCount, sizeof *b.labels, compareLabels); - - if (split) { - int part, first; - - for (part = 0, first = 0; first < rows; part++, first += split) { - char suffix[32]; - int last = first + split < rows ? first + split : rows; - - snprintf(suffix, sizeof suffix, "_%d.inc", part); - f = create(prefix, suffix); - if (!f) return 1; - fprintf(f, "/* part %d of %s, rows %d to %d, included by %s.c */\n", part, name, first, last - 1, name); - for (i = first; i < last; i++) putRow(f, &cmds[i]); - if (fclose(f) != 0) return 1; - } - } - - f = create(prefix, ".c"); - if (!f) return 1; - { - const char *base = strrchr(prefix, '/'); - - fprintf(f, "/* made by kons2c from %s, don't edit */\n\n", strrchr(input, '/') ? strrchr(input, '/') + 1 : input); - fprintf(f, "#include \"%s.h\"\n\n#include <string.h>\n\n", base ? base + 1 : prefix); - } - fprintf(f, "const int %s_count = %d;\n\n", name, rows); - fprintf(f, "const kon_cmd_t %s_cmds[%d] = {\n", name, rows); - if (split) { - const char *base = strrchr(prefix, '/'); - int part, first; - - for (part = 0, first = 0; first < rows; part++, first += split) fprintf(f, "#include \"%s_%d.inc\"\n", base ? base + 1 : prefix, part); - } else { - for (i = 0; i < rows; i++) putRow(f, &cmds[i]); - } - fprintf(f, "};\n\n"); - fprintf(f, "const int %s_labelCount = %d;\n\n", name, b.labelCount); - fprintf(f, "const kon_scriptLabel_t %s_labels[%d] = {\n", name, b.labelCount > 0 ? b.labelCount : 1); - for (i = 0; i < b.labelCount; i++) { - fprintf(f, "\t{"); - putString(f, b.labels[i].name); - fprintf(f, ", %d},\n", b.labels[i].at); - } - if (b.labelCount == 0) fprintf(f, "\t{\"\", 0}\n"); - fprintf(f, "};\n\n"); - fprintf(f, "int %s_find(const char *label)\n{\n\tint low = 0, high = %s_labelCount - 1;\n\n", name, name); - fprintf(f, "\twhile (low <= high) {\n\t\tint mid = low + (high - low) / 2;\n\t\tint order = strcmp(label, %s_labels[mid].name);\n\n", name); - fprintf(f, "\t\tif (order == 0) return %s_labels[mid].at;\n\t\tif (order < 0) high = mid - 1;\n\t\telse low = mid + 1;\n\t}\n\treturn -1;\n}\n", name); - if (fclose(f) != 0) return 1; - - f = create(prefix, ".h"); - if (!f) return 1; - fprintf(f, "/* made by kons2c, don't edit */\n\n#ifndef %s_H\n#define %s_H\n\n#include \"konscript.h\"\n\n", upper, upper); - fprintf(f, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n"); - fprintf(f, "#define %s_COUNT %d\n\n", upper, rows); - fprintf(f, "extern const int %s_count;\nextern const kon_cmd_t %s_cmds[%d];\n", name, name, rows); - fprintf(f, "extern const int %s_labelCount;\nextern const kon_scriptLabel_t %s_labels[%d];\n\n", name, name, b.labelCount > 0 ? b.labelCount : 1); - fprintf(f, "/* where a label is, or -1 */\nint %s_find(const char *label);\n\n", name); - fprintf(f, "#ifdef __cplusplus\n}\n#endif\n#endif\n"); - if (fclose(f) != 0) return 1; - - printf("%s: %d commands, %d labels%s\n", name, rows, b.labelCount, split ? ", split" : ""); + printf("%s: %d commands, %d labels%s\n", name, result.commands, result.labels, split ? ", split" : ""); free(source); - free(cmds); - free(b.pool); - free(b.labels); - free(b.hash); return 0; } |
