From b7c12b1ce02e9ece5824e27b666d7e4fd98c2e6d Mon Sep 17 00:00:00 2001 From: Nunuhara Cabbage Date: Fri, 28 Feb 2020 20:18:28 -0800 Subject: [PATCH] tools: allow changing input/output text encoding Use iconv instead of utfsjis.h so that text encodings other than UTF-8 and SJIS can be used. For three reasons: * to allow using other encodings for dumped files (e.g. UTF-16, SJIS) * to support existing Chinese translations, which use GBK-encoded text * to support theoretical translations to other languages that can't be represented in SJIS --- src/tools/aindump/aindump.c | 86 ++++++++++++++++++-------- src/tools/aindump/aindump.h | 3 + src/tools/aindump/dasm.c | 24 +++----- src/tools/aindump/meson.build | 1 + src/tools/ainedit/ainedit.c | 63 ++++++++++++++----- src/tools/ainedit/ainedit.h | 2 + src/tools/ainedit/asm.c | 23 ++++--- src/tools/ainedit/asm_lexer.yy.c | 52 ++++++++-------- src/tools/ainedit/asm_parser.tab.c | 58 +++++++++--------- src/tools/ainedit/asm_parser.tab.h | 14 ++--- src/tools/ainedit/meson.build | 1 + src/tools/ainedit/text_lexer.l | 4 +- src/tools/ainedit/text_lexer.yy.c | 64 ++++++++++---------- src/tools/ainedit/text_parser.tab.c | 46 +++++++------- src/tools/ainedit/text_parser.tab.h | 14 ++--- src/tools/conv.c | 49 +++++++++++++++ src/tools/ex/dump.c | 48 ++++++--------- src/tools/ex/ex_lexer.l | 7 ++- src/tools/ex/ex_lexer.yy.c | 93 ++++++++++++++--------------- src/tools/ex/exbuild.c | 41 ++++++++++--- src/tools/ex/exdump.c | 46 ++++++++++++-- src/tools/ex/meson.build | 7 ++- 22 files changed, 459 insertions(+), 287 deletions(-) create mode 100644 src/tools/conv.c diff --git a/src/tools/aindump/aindump.c b/src/tools/aindump/aindump.c index 7e59bca..65bfd0b 100644 --- a/src/tools/aindump/aindump.c +++ b/src/tools/aindump/aindump.c @@ -20,13 +20,30 @@ #include #include #include +#include #include "aindump.h" #include "little_endian.h" #include "system4.h" #include "system4/ain.h" #include "system4/instructions.h" #include "system4/string.h" -#include "system4/utfsjis.h" + +iconv_t output_conv; +iconv_t utf8_conv; + +char *convert_text(iconv_t cd, const char *str); + +// encode text in output encoding +char *encode_text_output(const char *str) +{ + return convert_text(output_conv, str); +} + +// encode text as UTF-8 +char *encode_text_utf8(const char *str) +{ + return convert_text(utf8_conv, str); +} int32_t code_reader_get_arg(struct code_reader *r, int n) { @@ -75,34 +92,36 @@ static void usage(void) puts(" Display information from AIN files."); puts(""); puts("Commonly used options:"); - puts(" -h, --help Display this message and exit"); - puts(" -c, --code Dump code section"); - puts(" -j, --json Dump to JSON format"); - puts(" -t, --text Dump strings and messages, sorted by function"); - puts(" -o, --output Set output file path"); + puts(" -h, --help Display this message and exit"); + puts(" -c, --code Dump code section"); + puts(" -j, --json Dump to JSON format"); + puts(" -t, --text Dump strings and messages, sorted by function"); + puts(" -o, --output Set output file path"); puts(""); puts("Less used options:"); - puts(" -C, --raw-code Dump code section (raw)"); - puts(" -f, --functions Dump functions section"); - puts(" -g, --globals Dump globals section"); - puts(" -S, --structures Dump structures section"); - puts(" -m, --messages Dump messages section"); - puts(" -s, --strings Dump strings section"); - puts(" -l, --libraries Dump libraries section"); - puts(" -F, --filenames Dump filenames"); - puts(" --function-types Dump function types section"); - puts(" --delegates Dump delegate types section"); - puts(" --global-group-names Dump global group names section"); - puts(" -e, --enums Dump enums section"); - puts(" -A, --audit Audit AIN file for xsystem4 compatibility"); - puts(" -d, --decrypt Dump decrypted AIN file"); - puts(" --map Dump AIN file map"); - puts(" --inline-strings Dump code in inline-strings mode"); + puts(" -C, --raw-code Dump code section (raw)"); + puts(" -f, --functions Dump functions section"); + puts(" -g, --globals Dump globals section"); + puts(" -S, --structures Dump structures section"); + puts(" -m, --messages Dump messages section"); + puts(" -s, --strings Dump strings section"); + puts(" -l, --libraries Dump libraries section"); + puts(" -F, --filenames Dump filenames"); + puts(" --function-types Dump function types section"); + puts(" --delegates Dump delegate types section"); + puts(" --global-group-names Dump global group names section"); + puts(" -e, --enums Dump enums section"); + puts(" -A, --audit Audit AIN file for xsystem4 compatibility"); + puts(" -d, --decrypt Dump decrypted AIN file"); + puts(" --map Dump AIN file map"); + puts(" --inline-strings Dump code in inline-strings mode"); + puts(" --input-encoding Specify the text encoding of the AIN file (default: SJIS-WIN)"); + puts(" --output-encoding Specify the text encoding of the output file (default: UTF-8)"); } static void print_sjis(FILE *f, const char *s) { - char *u = sjis2utf(s, strlen(s)); + char *u = encode_text_output(s); fprintf(f, "%s", u); free(u); } @@ -221,7 +240,7 @@ static void dump_text_function(struct dump_text_data *data) if (!data->fun) return; - char *u = sjis2utf(data->fun->name, strlen(data->fun->name)); + char *u = encode_text_output(data->fun->name); fprintf(data->out, "\n; %s\n", u); free(u); @@ -486,6 +505,8 @@ enum { LOPT_DECRYPT, LOPT_MAP, LOPT_INLINE_STRINGS, + LOPT_INPUT_ENCODING, + LOPT_OUTPUT_ENCODING }; int main(int argc, char *argv[]) @@ -494,6 +515,8 @@ int main(int argc, char *argv[]) bool decrypt = false; char *output_file = NULL; FILE *output = stdout; + char *input_encoding = "SJIS-WIN"; + char *output_encoding = "UTF-8"; int err = AIN_SUCCESS; unsigned int flags = DASM_NO_STRINGS; struct ain *ain; @@ -525,6 +548,8 @@ int main(int argc, char *argv[]) { "decrypt", no_argument, 0, LOPT_DECRYPT }, { "map", no_argument, 0, LOPT_MAP }, { "inline-strings", no_argument, 0, LOPT_INLINE_STRINGS }, + { "input-encoding", required_argument, 0, LOPT_INPUT_ENCODING }, + { "output-encoding", required_argument, 0, LOPT_OUTPUT_ENCODING }, }; int option_index = 0; int c; @@ -618,6 +643,12 @@ int main(int argc, char *argv[]) case LOPT_INLINE_STRINGS: flags &= ~DASM_NO_STRINGS; break; + case LOPT_INPUT_ENCODING: + input_encoding = optarg; + break; + case LOPT_OUTPUT_ENCODING: + output_encoding = optarg; + break; case '?': ERROR("Unkown command line argument"); } @@ -638,6 +669,13 @@ int main(int argc, char *argv[]) free(output_file); } + if ((output_conv = iconv_open(output_encoding, input_encoding)) == (iconv_t)-1) { + ERROR("iconv_open: %s", strerror(errno)); + } + if ((utf8_conv = iconv_open("utf8", input_encoding)) == (iconv_t)-1) { + ERROR("iconv_open: %s", strerror(errno)); + } + if (decrypt) { dump_decrypted(output, argv[0]); return 0; diff --git a/src/tools/aindump/aindump.h b/src/tools/aindump/aindump.h index c8b5a5f..0532580 100644 --- a/src/tools/aindump/aindump.h +++ b/src/tools/aindump/aindump.h @@ -50,4 +50,7 @@ void for_each_instruction(struct ain *ain, void(*fun)(struct code_reader*, void* // json.c void ain_dump_json(FILE *out, struct ain *ain); +char *encode_text_output(const char *str); +char *encode_text_utf8(const char *str); + #endif /* AINDUMP_H */ diff --git a/src/tools/aindump/dasm.c b/src/tools/aindump/dasm.c index fcca0f7..eea5dd6 100644 --- a/src/tools/aindump/dasm.c +++ b/src/tools/aindump/dasm.c @@ -23,7 +23,6 @@ #include "system4/ain.h" #include "system4/instructions.h" #include "system4/string.h" -#include "system4/utfsjis.h" #define DASM_ERROR(dasm, fmt, ...) ERROR("At 0x%x: " fmt, dasm->addr, ##__VA_ARGS__) @@ -171,7 +170,7 @@ static float arg_to_float(int32_t arg) static void print_sjis(struct dasm_state *dasm, const char *s) { - char *u = sjis2utf(s, strlen(s)); + char *u = encode_text_output(s); fprintf(dasm->out, "%s", u); free(u); } @@ -179,7 +178,7 @@ static void print_sjis(struct dasm_state *dasm, const char *s) static char *_escape_string(const char *str, const char *escape_chars, const char *replace_chars) { int escapes = 0; - char *u = sjis2utf(str, strlen(str)); + char *u = encode_text_output(str); // count number of required escapes for (int i = 0; u[i]; i++) { @@ -235,19 +234,12 @@ static void print_string(struct dasm_state *dasm, const char *str) static void print_identifier(struct dasm_state *dasm, const char *str) { - // if the identifier contains spaces, it must be quoted - for (int i = 0; str[i]; i++) { - if (SJIS_2BYTE(str[i])) { - i++; - continue; - } - if (str[i] == ' ') { - print_string(dasm, str); - return; - } - } - - print_sjis(dasm, str); + char *u = encode_text_utf8(str); + if (strchr(u, ' ')) + print_string(dasm, str); + else + print_sjis(dasm, str); + free(u); } static void print_local_variable(struct dasm_state *dasm, struct ain_function *func, int varno) diff --git a/src/tools/aindump/meson.build b/src/tools/aindump/meson.build index f8e56dc..2c17e25 100644 --- a/src/tools/aindump/meson.build +++ b/src/tools/aindump/meson.build @@ -1,4 +1,5 @@ aindump = ['../../cJSON.c', + '../conv.c', 'aindump.c', 'dasm.c', 'guess_filenames.c', diff --git a/src/tools/ainedit/ainedit.c b/src/tools/ainedit/ainedit.c index 12fb98b..b2d82ef 100644 --- a/src/tools/ainedit/ainedit.c +++ b/src/tools/ainedit/ainedit.c @@ -17,7 +17,10 @@ #include #include #include +#include +#include #include +#include #include "ainedit.h" #include "system4.h" #include "system4/ain.h" @@ -27,13 +30,15 @@ static void usage(void) puts("Usage: ainedit [options...] input-file"); puts(" Edit AIN files."); puts(""); - puts(" -h, --help Display this message and exit"); - puts(" -c, --code Update the CODE section (assemble .jam file)"); - puts(" -j, --json Update AIN file from JSON data"); - puts(" -t, --text Update strings/messages"); - puts(" -o, --output Set output file path"); - puts(" --raw Read code in raw mode"); - puts(" --inline-strings Read code in inline-strings mode"); + puts(" -h, --help Display this message and exit"); + puts(" -c, --code Update the CODE section (assemble .jam file)"); + puts(" -j, --json Update AIN file from JSON data"); + puts(" -t, --text Update strings/messages"); + puts(" -o, --output Set output file path"); + puts(" --raw Read code in raw mode"); + puts(" --inline-strings Read code in inline-strings mode"); + puts(" --input-encoding Specify the text encoding of the input file(s) (default: UTF-8)"); + puts(" --output-encoding Specify the text encoding of the output file (default: SJIS-WIN)"); //puts(" -p,--project Build AIN from project file"); } @@ -47,8 +52,21 @@ enum { LOPT_OUTPUT, LOPT_RAW, LOPT_INLINE_STRINGS, + LOPT_INPUT_ENCODING, + LOPT_OUTPUT_ENCODING, }; +iconv_t ain_conv; +iconv_t print_conv; + +char *convert_text(iconv_t cd, const char *str); + +// encode text for AIN file +char *encode_text(const char *str) +{ + return convert_text(ain_conv, str); +} + int main(int argc, char *argv[]) { initialize_instructions(); @@ -58,16 +76,20 @@ int main(int argc, char *argv[]) const char *decl_file = NULL; const char *text_file = NULL; const char *output_file = NULL; + const char *input_encoding = "UTF-8"; + const char *output_encoding = "SJIS-WIN"; uint32_t flags = ASM_NO_STRINGS; while (1) { static struct option long_options[] = { - { "help", no_argument, 0, LOPT_HELP }, - { "code", required_argument, 0, LOPT_CODE }, - { "json", required_argument, 0, LOPT_JSON }, - { "text", required_argument, 0, LOPT_TEXT }, - { "output", required_argument, 0, LOPT_OUTPUT }, - { "raw", no_argument, 0, LOPT_RAW }, - { "inline-strings", no_argument, 0, LOPT_INLINE_STRINGS }, + { "help", no_argument, 0, LOPT_HELP }, + { "code", required_argument, 0, LOPT_CODE }, + { "json", required_argument, 0, LOPT_JSON }, + { "text", required_argument, 0, LOPT_TEXT }, + { "output", required_argument, 0, LOPT_OUTPUT }, + { "raw", no_argument, 0, LOPT_RAW }, + { "inline-strings", no_argument, 0, LOPT_INLINE_STRINGS }, + { "input-encoding", required_argument, 0, LOPT_INPUT_ENCODING }, + { "output-encoding", required_argument, 0, LOPT_OUTPUT_ENCODING }, }; int option_index = 0; int c; @@ -104,6 +126,12 @@ int main(int argc, char *argv[]) WARNING("Inline strings mode doesn't quite work yet..."); flags &= ~ASM_NO_STRINGS; break; + case LOPT_INPUT_ENCODING: + input_encoding = optarg; + break; + case LOPT_OUTPUT_ENCODING: + output_encoding = optarg; + break; case '?': ERROR("Unknown command line argument"); } @@ -121,6 +149,13 @@ int main(int argc, char *argv[]) ERROR("No output file given"); } + if ((ain_conv = iconv_open(output_encoding, input_encoding)) == (iconv_t)-1) { + ERROR("iconv_open: %s", strerror(errno)); + } + if ((print_conv = iconv_open("utf8", output_encoding)) == (iconv_t)-1) { + ERROR("iconv_open: %s", strerror(errno)); + } + if (!(ain = ain_open(argv[0], &err))) { ERROR("Failed to open ain file: %s", ain_strerror(err)); } diff --git a/src/tools/ainedit/ainedit.h b/src/tools/ainedit/ainedit.h index bcd9bc3..68d7d3b 100644 --- a/src/tools/ainedit/ainedit.h +++ b/src/tools/ainedit/ainedit.h @@ -57,4 +57,6 @@ void ain_write(const char *filename, struct ain *ain); // text.c void read_text(const char *filename, struct ain *ain); +char *encode_text(const char *str); + #endif /* AINEDIT_AINEDIT_H */ diff --git a/src/tools/ainedit/asm.c b/src/tools/ainedit/asm.c index cb66ff2..ba678ac 100644 --- a/src/tools/ainedit/asm.c +++ b/src/tools/ainedit/asm.c @@ -25,7 +25,6 @@ #include "system4/ain.h" #include "system4/instructions.h" #include "system4/string.h" -#include "system4/utfsjis.h" #include "asm_parser.tab.h" extern FILE *yyin; @@ -88,7 +87,7 @@ static int string_table_add(struct string_table *t, const char *s) static int asm_add_message(struct asm_state *state, const char *s) { - char *u = utf2sjis(s, strlen(s)); + char *u = encode_text(s); int i = string_table_add(&state->messages, u); free(u); return i; @@ -97,7 +96,7 @@ static int asm_add_message(struct asm_state *state, const char *s) static int asm_add_string(struct asm_state *state, const char *s) { int ret; - char *u = utf2sjis(s, strlen(s)); + char *u = encode_text(s); khiter_t k = kh_put(string_ht, state->strings_index, u, &ret); if (!ret) { // nothing @@ -269,7 +268,7 @@ static uint32_t asm_resolve_arg(struct asm_state *state, enum opcode opcode, enu return kh_value(label_table, k); } case T_FUNC: { - char *u = utf2sjis(arg, strlen(arg)); + char *u = encode_text(arg); struct ain_function *f = ain_get_function(ain, u); free(u); if (!f) @@ -298,7 +297,7 @@ static uint32_t asm_resolve_arg(struct asm_state *state, enum opcode opcode, enu } case T_LOCAL: { int n, count = 0; - char *u = utf2sjis(arg, strlen(arg)); + char *u = encode_text(arg); u = parse_identifier(state, u, &n); struct ain_function *f = &state->ain->functions[state->func]; for (int i = 0; i < f->nr_vars; i++) { @@ -314,7 +313,7 @@ static uint32_t asm_resolve_arg(struct asm_state *state, enum opcode opcode, enu ASM_ERROR(state, "Unable to resolve local variable: '%s'", arg); } case T_GLOBAL: { - char *u = utf2sjis(arg, strlen(arg)); + char *u = encode_text(arg); for (int i = 0; i < state->ain->nr_globals; i++) { if (!strcmp(u, state->ain->globals[i].name)) { free(u); @@ -324,7 +323,7 @@ static uint32_t asm_resolve_arg(struct asm_state *state, enum opcode opcode, enu ASM_ERROR(state, "Unable to resolve global variable: '%s'", arg); } case T_STRUCT: { - char *u = utf2sjis(arg, strlen(arg)); + char *u = encode_text(arg); struct ain_struct *s = ain_get_struct(state->ain, u); free(u); if (!s) @@ -351,7 +350,7 @@ static uint32_t asm_resolve_arg(struct asm_state *state, enum opcode opcode, enu if (state->lib < 0) ERROR("Tried to resolve library function without active library?"); int n, count = 0; - char *u = utf2sjis(arg, strlen(arg)); + char *u = encode_text(arg); u = parse_identifier(state, u, &n); for (int i = 0; i < state->ain->libraries[state->lib].nr_functions; i++) { if (strcmp(u, state->ain->libraries[state->lib].functions[i].name)) @@ -370,7 +369,7 @@ static uint32_t asm_resolve_arg(struct asm_state *state, enum opcode opcode, enu case T_FILE: { if (!state->ain->nr_filenames) return atoi(arg); - char *u = utf2sjis(arg, strlen(arg)); + char *u = encode_text(arg); for (int i = 0; i < state->ain->nr_filenames; i++) { if (!strcmp(u, state->ain->filenames[i])) { free(u); @@ -380,7 +379,7 @@ static uint32_t asm_resolve_arg(struct asm_state *state, enum opcode opcode, enu ASM_ERROR(state, "Unable to resolve filename: '%s'", arg); } case T_DLG: { - char *u = utf2sjis(arg, strlen(arg)); + char *u = encode_text(arg); for (int i = 0; i < state->ain->nr_delegates; i++) { if (!strcmp(u, state->ain->delegates[i].name)) { free(u); @@ -445,7 +444,7 @@ void handle_pseudo_op(struct asm_state *state, struct parse_instruction *instr) realloc_string_table(state->ain, n_str); if (state->ain->strings[n_str]) free_string(state->ain->strings[n_str]); - char *sjis = utf2sjis(kv_A(*instr->args, 1)->text, 0); + char *sjis = encode_text(kv_A(*instr->args, 1)->text); state->ain->strings[n_str] = make_string(sjis, strlen(sjis)); free(sjis); break; @@ -457,7 +456,7 @@ void handle_pseudo_op(struct asm_state *state, struct parse_instruction *instr) realloc_message_table(state->ain, n_msg); if (state->ain->messages[n_msg]) free_string(state->ain->messages[n_msg]); - char *sjis = utf2sjis(kv_A(*instr->args, 1)->text, 0); + char *sjis = encode_text(kv_A(*instr->args, 1)->text); state->ain->messages[n_msg] = make_string(sjis, strlen(sjis)); free(sjis); break; diff --git a/src/tools/ainedit/asm_lexer.yy.c b/src/tools/ainedit/asm_lexer.yy.c index c200d84..ba7b320 100644 --- a/src/tools/ainedit/asm_lexer.yy.c +++ b/src/tools/ainedit/asm_lexer.yy.c @@ -1,6 +1,6 @@ -#line 2 "src/ainedit/48087cf@@ainedit@exe/asm_lexer.yy.c" +#line 2 "src/tools/ainedit/659eb3d@@ainedit@exe/asm_lexer.yy.c" -#line 4 "src/ainedit/48087cf@@ainedit@exe/asm_lexer.yy.c" +#line 4 "src/tools/ainedit/659eb3d@@ainedit@exe/asm_lexer.yy.c" #define YY_INT_ALIGNED short int @@ -470,7 +470,7 @@ int yy_flex_debug = 0; #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET char *yytext; -#line 1 "../src/ainedit/asm_lexer.l" +#line 1 "../src/tools/ainedit/asm_lexer.l" /* Copyright (C) 2019 Nunuhara Cabbage * * This program is free software; you can redistribute it and/or modify @@ -486,7 +486,7 @@ char *yytext; * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ -#line 18 "../src/ainedit/asm_lexer.l" +#line 18 "../src/tools/ainedit/asm_lexer.l" #pragma GCC diagnostic ignored "-Wunused-function" @@ -500,9 +500,9 @@ char *yytext; char string_buf[65536]; char *string_buf_ptr; -#line 504 "src/ainedit/48087cf@@ainedit@exe/asm_lexer.yy.c" +#line 504 "src/tools/ainedit/659eb3d@@ainedit@exe/asm_lexer.yy.c" -#line 506 "src/ainedit/48087cf@@ainedit@exe/asm_lexer.yy.c" +#line 506 "src/tools/ainedit/659eb3d@@ainedit@exe/asm_lexer.yy.c" #define INITIAL 0 #define str 1 @@ -720,10 +720,10 @@ YY_DECL } { -#line 39 "../src/ainedit/asm_lexer.l" +#line 39 "../src/tools/ainedit/asm_lexer.l" -#line 727 "src/ainedit/48087cf@@ainedit@exe/asm_lexer.yy.c" +#line 727 "src/tools/ainedit/659eb3d@@ainedit@exe/asm_lexer.yy.c" while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { @@ -782,40 +782,40 @@ do_action: /* This label is used only to access EOF actions. */ case 1: YY_RULE_SETUP -#line 41 "../src/ainedit/asm_lexer.l" +#line 41 "../src/tools/ainedit/asm_lexer.l" ; YY_BREAK case 2: /* rule 2 can match eol */ YY_RULE_SETUP -#line 42 "../src/ainedit/asm_lexer.l" +#line 42 "../src/tools/ainedit/asm_lexer.l" return NEWLINE; YY_BREAK case 3: /* rule 3 can match eol */ YY_RULE_SETUP -#line 43 "../src/ainedit/asm_lexer.l" +#line 43 "../src/tools/ainedit/asm_lexer.l" return NEWLINE; YY_BREAK case 4: YY_RULE_SETUP -#line 44 "../src/ainedit/asm_lexer.l" +#line 44 "../src/tools/ainedit/asm_lexer.l" yylval.string = make_string(yytext, yyleng-1); return LABEL; YY_BREAK case 5: YY_RULE_SETUP -#line 45 "../src/ainedit/asm_lexer.l" +#line 45 "../src/tools/ainedit/asm_lexer.l" yylval.string = make_string(yytext, yyleng); return IDENTIFIER; YY_BREAK case 6: YY_RULE_SETUP -#line 48 "../src/ainedit/asm_lexer.l" +#line 48 "../src/tools/ainedit/asm_lexer.l" string_buf_ptr = string_buf; BEGIN(str); YY_BREAK case 7: YY_RULE_SETUP -#line 51 "../src/ainedit/asm_lexer.l" +#line 51 "../src/tools/ainedit/asm_lexer.l" { BEGIN(INITIAL); *string_buf_ptr = '\0'; @@ -826,43 +826,43 @@ YY_RULE_SETUP case 8: /* rule 8 can match eol */ YY_RULE_SETUP -#line 58 "../src/ainedit/asm_lexer.l" +#line 58 "../src/tools/ainedit/asm_lexer.l" ERROR("Unterminated string literal"); YY_BREAK case 9: YY_RULE_SETUP -#line 60 "../src/ainedit/asm_lexer.l" +#line 60 "../src/tools/ainedit/asm_lexer.l" *string_buf_ptr++ = '\n'; YY_BREAK case 10: YY_RULE_SETUP -#line 61 "../src/ainedit/asm_lexer.l" +#line 61 "../src/tools/ainedit/asm_lexer.l" *string_buf_ptr++ = '\t'; YY_BREAK case 11: YY_RULE_SETUP -#line 62 "../src/ainedit/asm_lexer.l" +#line 62 "../src/tools/ainedit/asm_lexer.l" *string_buf_ptr++ = '\r'; YY_BREAK case 12: YY_RULE_SETUP -#line 63 "../src/ainedit/asm_lexer.l" +#line 63 "../src/tools/ainedit/asm_lexer.l" *string_buf_ptr++ = '\b'; YY_BREAK case 13: YY_RULE_SETUP -#line 64 "../src/ainedit/asm_lexer.l" +#line 64 "../src/tools/ainedit/asm_lexer.l" *string_buf_ptr++ = '\f'; YY_BREAK case 14: /* rule 14 can match eol */ YY_RULE_SETUP -#line 66 "../src/ainedit/asm_lexer.l" +#line 66 "../src/tools/ainedit/asm_lexer.l" *string_buf_ptr++ = yytext[1]; YY_BREAK case 15: YY_RULE_SETUP -#line 68 "../src/ainedit/asm_lexer.l" +#line 68 "../src/tools/ainedit/asm_lexer.l" { char *yptr = yytext; while (*yptr) @@ -872,10 +872,10 @@ YY_RULE_SETUP case 16: YY_RULE_SETUP -#line 75 "../src/ainedit/asm_lexer.l" +#line 75 "../src/tools/ainedit/asm_lexer.l" ECHO; YY_BREAK -#line 879 "src/ainedit/48087cf@@ainedit@exe/asm_lexer.yy.c" +#line 879 "src/tools/ainedit/659eb3d@@ainedit@exe/asm_lexer.yy.c" case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(str): yyterminate(); @@ -1881,6 +1881,6 @@ void yyfree (void * ptr ) #define YYTABLES_NAME "yytables" -#line 75 "../src/ainedit/asm_lexer.l" +#line 75 "../src/tools/ainedit/asm_lexer.l" diff --git a/src/tools/ainedit/asm_parser.tab.c b/src/tools/ainedit/asm_parser.tab.c index cbe6153..ae68a3f 100644 --- a/src/tools/ainedit/asm_parser.tab.c +++ b/src/tools/ainedit/asm_parser.tab.c @@ -88,8 +88,8 @@ /* In a future release of Bison, this section will be replaced by #include "asm_parser.tab.h". */ -#ifndef YY_YY_SRC_AINEDIT_48087CF_AINEDIT_EXE_ASM_PARSER_TAB_H_INCLUDED -# define YY_YY_SRC_AINEDIT_48087CF_AINEDIT_EXE_ASM_PARSER_TAB_H_INCLUDED +#ifndef YY_YY_SRC_TOOLS_AINEDIT_659EB3D_AINEDIT_EXE_ASM_PARSER_TAB_H_INCLUDED +# define YY_YY_SRC_TOOLS_AINEDIT_659EB3D_AINEDIT_EXE_ASM_PARSER_TAB_H_INCLUDED /* Debug traces. */ #ifndef YYDEBUG # define YYDEBUG 0 @@ -98,7 +98,7 @@ extern int yydebug; #endif /* "%code requires" blocks. */ -#line 9 "../src/ainedit/asm_parser.y" /* yacc.c:352 */ +#line 9 "../src/tools/ainedit/asm_parser.y" /* yacc.c:352 */ #include #include "khash.h" @@ -118,7 +118,7 @@ extern int yydebug; KHASH_MAP_INIT_STR(label_table, uint32_t); khash_t(label_table) *label_table; -#line 122 "src/ainedit/48087cf@@ainedit@exe/asm_parser.tab.c" /* yacc.c:352 */ +#line 122 "src/tools/ainedit/659eb3d@@ainedit@exe/asm_parser.tab.c" /* yacc.c:352 */ /* Token type. */ #ifndef YYTOKENTYPE @@ -136,7 +136,7 @@ extern int yydebug; union YYSTYPE { -#line 1 "../src/ainedit/asm_parser.y" /* yacc.c:352 */ +#line 1 "../src/tools/ainedit/asm_parser.y" /* yacc.c:352 */ int token; struct string *string; @@ -144,7 +144,7 @@ union YYSTYPE struct parse_instruction *instr; parse_instruction_list *program; -#line 148 "src/ainedit/48087cf@@ainedit@exe/asm_parser.tab.c" /* yacc.c:352 */ +#line 148 "src/tools/ainedit/659eb3d@@ainedit@exe/asm_parser.tab.c" /* yacc.c:352 */ }; typedef union YYSTYPE YYSTYPE; @@ -157,10 +157,10 @@ extern YYSTYPE yylval; int yyparse (void); -#endif /* !YY_YY_SRC_AINEDIT_48087CF_AINEDIT_EXE_ASM_PARSER_TAB_H_INCLUDED */ +#endif /* !YY_YY_SRC_TOOLS_AINEDIT_659EB3D_AINEDIT_EXE_ASM_PARSER_TAB_H_INCLUDED */ /* Second part of user prologue. */ -#line 29 "../src/ainedit/asm_parser.y" /* yacc.c:354 */ +#line 29 "../src/tools/ainedit/asm_parser.y" /* yacc.c:354 */ #include @@ -245,7 +245,7 @@ static void push_label(char *name) } -#line 249 "src/ainedit/48087cf@@ainedit@exe/asm_parser.tab.c" /* yacc.c:354 */ +#line 249 "src/tools/ainedit/659eb3d@@ainedit@exe/asm_parser.tab.c" /* yacc.c:354 */ #ifdef short # undef short @@ -1315,61 +1315,61 @@ yyreduce: switch (yyn) { case 2: -#line 125 "../src/ainedit/asm_parser.y" /* yacc.c:1652 */ +#line 125 "../src/tools/ainedit/asm_parser.y" /* yacc.c:1652 */ { parsed_code = (yyvsp[0].program); } -#line 1321 "src/ainedit/48087cf@@ainedit@exe/asm_parser.tab.c" /* yacc.c:1652 */ +#line 1321 "src/tools/ainedit/659eb3d@@ainedit@exe/asm_parser.tab.c" /* yacc.c:1652 */ break; case 3: -#line 128 "../src/ainedit/asm_parser.y" /* yacc.c:1652 */ +#line 128 "../src/tools/ainedit/asm_parser.y" /* yacc.c:1652 */ { (yyval.program) = make_program(); if ((yyvsp[0].instr)) { push_instruction((yyval.program), (yyvsp[0].instr)); } } -#line 1327 "src/ainedit/48087cf@@ainedit@exe/asm_parser.tab.c" /* yacc.c:1652 */ +#line 1327 "src/tools/ainedit/659eb3d@@ainedit@exe/asm_parser.tab.c" /* yacc.c:1652 */ break; case 4: -#line 129 "../src/ainedit/asm_parser.y" /* yacc.c:1652 */ +#line 129 "../src/tools/ainedit/asm_parser.y" /* yacc.c:1652 */ { if ((yyvsp[0].instr)) { push_instruction((yyvsp[-1].program), (yyvsp[0].instr)); } } -#line 1333 "src/ainedit/48087cf@@ainedit@exe/asm_parser.tab.c" /* yacc.c:1652 */ +#line 1333 "src/tools/ainedit/659eb3d@@ainedit@exe/asm_parser.tab.c" /* yacc.c:1652 */ break; case 5: -#line 132 "../src/ainedit/asm_parser.y" /* yacc.c:1652 */ +#line 132 "../src/tools/ainedit/asm_parser.y" /* yacc.c:1652 */ { (yyval.instr) = NULL; } -#line 1339 "src/ainedit/48087cf@@ainedit@exe/asm_parser.tab.c" /* yacc.c:1652 */ +#line 1339 "src/tools/ainedit/659eb3d@@ainedit@exe/asm_parser.tab.c" /* yacc.c:1652 */ break; case 6: -#line 133 "../src/ainedit/asm_parser.y" /* yacc.c:1652 */ +#line 133 "../src/tools/ainedit/asm_parser.y" /* yacc.c:1652 */ { push_label((yyvsp[0].string)->text); (yyval.instr) = NULL; } -#line 1345 "src/ainedit/48087cf@@ainedit@exe/asm_parser.tab.c" /* yacc.c:1652 */ +#line 1345 "src/tools/ainedit/659eb3d@@ainedit@exe/asm_parser.tab.c" /* yacc.c:1652 */ break; case 7: -#line 134 "../src/ainedit/asm_parser.y" /* yacc.c:1652 */ +#line 134 "../src/tools/ainedit/asm_parser.y" /* yacc.c:1652 */ { (yyval.instr) = make_instruction((yyvsp[-1].string), NULL); } -#line 1351 "src/ainedit/48087cf@@ainedit@exe/asm_parser.tab.c" /* yacc.c:1652 */ +#line 1351 "src/tools/ainedit/659eb3d@@ainedit@exe/asm_parser.tab.c" /* yacc.c:1652 */ break; case 8: -#line 135 "../src/ainedit/asm_parser.y" /* yacc.c:1652 */ +#line 135 "../src/tools/ainedit/asm_parser.y" /* yacc.c:1652 */ { (yyval.instr) = make_instruction((yyvsp[-2].string), (yyvsp[-1].args)); } -#line 1357 "src/ainedit/48087cf@@ainedit@exe/asm_parser.tab.c" /* yacc.c:1652 */ +#line 1357 "src/tools/ainedit/659eb3d@@ainedit@exe/asm_parser.tab.c" /* yacc.c:1652 */ break; case 9: -#line 137 "../src/ainedit/asm_parser.y" /* yacc.c:1652 */ +#line 137 "../src/tools/ainedit/asm_parser.y" /* yacc.c:1652 */ { (yyval.args) = make_arglist(); push_arg((yyval.args), (yyvsp[0].string)); } -#line 1363 "src/ainedit/48087cf@@ainedit@exe/asm_parser.tab.c" /* yacc.c:1652 */ +#line 1363 "src/tools/ainedit/659eb3d@@ainedit@exe/asm_parser.tab.c" /* yacc.c:1652 */ break; case 10: -#line 138 "../src/ainedit/asm_parser.y" /* yacc.c:1652 */ +#line 138 "../src/tools/ainedit/asm_parser.y" /* yacc.c:1652 */ { push_arg((yyvsp[-1].args), (yyvsp[0].string)); } -#line 1369 "src/ainedit/48087cf@@ainedit@exe/asm_parser.tab.c" /* yacc.c:1652 */ +#line 1369 "src/tools/ainedit/659eb3d@@ainedit@exe/asm_parser.tab.c" /* yacc.c:1652 */ break; -#line 1373 "src/ainedit/48087cf@@ainedit@exe/asm_parser.tab.c" /* yacc.c:1652 */ +#line 1373 "src/tools/ainedit/659eb3d@@ainedit@exe/asm_parser.tab.c" /* yacc.c:1652 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -1600,5 +1600,5 @@ yyreturn: #endif return yyresult; } -#line 141 "../src/ainedit/asm_parser.y" /* yacc.c:1918 */ +#line 141 "../src/tools/ainedit/asm_parser.y" /* yacc.c:1918 */ diff --git a/src/tools/ainedit/asm_parser.tab.h b/src/tools/ainedit/asm_parser.tab.h index 1de4021..9998e45 100644 --- a/src/tools/ainedit/asm_parser.tab.h +++ b/src/tools/ainedit/asm_parser.tab.h @@ -34,8 +34,8 @@ /* Undocumented macros, especially those whose name start with YY_, are private implementation details. Do not rely on them. */ -#ifndef YY_YY_SRC_AINEDIT_48087CF_AINEDIT_EXE_ASM_PARSER_TAB_H_INCLUDED -# define YY_YY_SRC_AINEDIT_48087CF_AINEDIT_EXE_ASM_PARSER_TAB_H_INCLUDED +#ifndef YY_YY_SRC_TOOLS_AINEDIT_659EB3D_AINEDIT_EXE_ASM_PARSER_TAB_H_INCLUDED +# define YY_YY_SRC_TOOLS_AINEDIT_659EB3D_AINEDIT_EXE_ASM_PARSER_TAB_H_INCLUDED /* Debug traces. */ #ifndef YYDEBUG # define YYDEBUG 0 @@ -44,7 +44,7 @@ extern int yydebug; #endif /* "%code requires" blocks. */ -#line 9 "../src/ainedit/asm_parser.y" /* yacc.c:1921 */ +#line 9 "../src/tools/ainedit/asm_parser.y" /* yacc.c:1921 */ #include #include "khash.h" @@ -64,7 +64,7 @@ extern int yydebug; KHASH_MAP_INIT_STR(label_table, uint32_t); khash_t(label_table) *label_table; -#line 68 "src/ainedit/48087cf@@ainedit@exe/asm_parser.tab.h" /* yacc.c:1921 */ +#line 68 "src/tools/ainedit/659eb3d@@ainedit@exe/asm_parser.tab.h" /* yacc.c:1921 */ /* Token type. */ #ifndef YYTOKENTYPE @@ -82,7 +82,7 @@ extern int yydebug; union YYSTYPE { -#line 1 "../src/ainedit/asm_parser.y" /* yacc.c:1921 */ +#line 1 "../src/tools/ainedit/asm_parser.y" /* yacc.c:1921 */ int token; struct string *string; @@ -90,7 +90,7 @@ union YYSTYPE struct parse_instruction *instr; parse_instruction_list *program; -#line 94 "src/ainedit/48087cf@@ainedit@exe/asm_parser.tab.h" /* yacc.c:1921 */ +#line 94 "src/tools/ainedit/659eb3d@@ainedit@exe/asm_parser.tab.h" /* yacc.c:1921 */ }; typedef union YYSTYPE YYSTYPE; @@ -103,4 +103,4 @@ extern YYSTYPE yylval; int yyparse (void); -#endif /* !YY_YY_SRC_AINEDIT_48087CF_AINEDIT_EXE_ASM_PARSER_TAB_H_INCLUDED */ +#endif /* !YY_YY_SRC_TOOLS_AINEDIT_659EB3D_AINEDIT_EXE_ASM_PARSER_TAB_H_INCLUDED */ diff --git a/src/tools/ainedit/meson.build b/src/tools/ainedit/meson.build index 4cb22cd..44260dd 100644 --- a/src/tools/ainedit/meson.build +++ b/src/tools/ainedit/meson.build @@ -1,5 +1,6 @@ # sources for ainedit ainedit = ['../../cJSON.c', + '../conv.c', 'ainedit.c', 'asm.c', 'json.c', diff --git a/src/tools/ainedit/text_lexer.l b/src/tools/ainedit/text_lexer.l index 0180bd0..52511c6 100644 --- a/src/tools/ainedit/text_lexer.l +++ b/src/tools/ainedit/text_lexer.l @@ -21,9 +21,9 @@ #include #include #include "text_parser.tab.h" +#include "ainedit.h" #include "system4.h" #include "system4/string.h" -#include "system4/utfsjis.h" char string_buf[65536]; char *string_buf_ptr; @@ -53,7 +53,7 @@ s return STRINGS; \" { BEGIN(INITIAL); *string_buf_ptr = '\0'; - char *sjis = utf2sjis(string_buf, strlen(string_buf)); + char *sjis = encode_text(string_buf); text_lval.string = make_string(sjis, strlen(sjis)); free(sjis); return STRING; diff --git a/src/tools/ainedit/text_lexer.yy.c b/src/tools/ainedit/text_lexer.yy.c index 6d29d39..d466128 100644 --- a/src/tools/ainedit/text_lexer.yy.c +++ b/src/tools/ainedit/text_lexer.yy.c @@ -1,6 +1,6 @@ -#line 2 "src/ainedit/48087cf@@ainedit@exe/text_lexer.yy.c" +#line 2 "src/tools/ainedit/659eb3d@@ainedit@exe/text_lexer.yy.c" -#line 4 "src/ainedit/48087cf@@ainedit@exe/text_lexer.yy.c" +#line 4 "src/tools/ainedit/659eb3d@@ainedit@exe/text_lexer.yy.c" #define YY_INT_ALIGNED short int @@ -721,7 +721,7 @@ int yy_flex_debug = 0; #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET char *yytext; -#line 1 "../src/ainedit/text_lexer.l" +#line 1 "../src/tools/ainedit/text_lexer.l" /* Copyright (C) 2019 Nunuhara Cabbage * * This program is free software; you can redistribute it and/or modify @@ -737,23 +737,23 @@ char *yytext; * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ -#line 18 "../src/ainedit/text_lexer.l" +#line 18 "../src/tools/ainedit/text_lexer.l" #pragma GCC diagnostic ignored "-Wunused-function" #include #include #include "text_parser.tab.h" +#include "ainedit.h" #include "system4.h" #include "system4/string.h" -#include "system4/utfsjis.h" char string_buf[65536]; char *string_buf_ptr; -#line 755 "src/ainedit/48087cf@@ainedit@exe/text_lexer.yy.c" +#line 755 "src/tools/ainedit/659eb3d@@ainedit@exe/text_lexer.yy.c" -#line 757 "src/ainedit/48087cf@@ainedit@exe/text_lexer.yy.c" +#line 757 "src/tools/ainedit/659eb3d@@ainedit@exe/text_lexer.yy.c" #define INITIAL 0 #define str 1 @@ -971,10 +971,10 @@ YY_DECL } { -#line 38 "../src/ainedit/text_lexer.l" +#line 38 "../src/tools/ainedit/text_lexer.l" -#line 978 "src/ainedit/48087cf@@ainedit@exe/text_lexer.yy.c" +#line 978 "src/tools/ainedit/659eb3d@@ainedit@exe/text_lexer.yy.c" while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { @@ -1033,64 +1033,64 @@ do_action: /* This label is used only to access EOF actions. */ case 1: YY_RULE_SETUP -#line 40 "../src/ainedit/text_lexer.l" +#line 40 "../src/tools/ainedit/text_lexer.l" ; YY_BREAK case 2: /* rule 2 can match eol */ YY_RULE_SETUP -#line 41 "../src/ainedit/text_lexer.l" +#line 41 "../src/tools/ainedit/text_lexer.l" return NEWLINE; YY_BREAK case 3: /* rule 3 can match eol */ YY_RULE_SETUP -#line 42 "../src/ainedit/text_lexer.l" +#line 42 "../src/tools/ainedit/text_lexer.l" return NEWLINE; YY_BREAK case 4: YY_RULE_SETUP -#line 43 "../src/ainedit/text_lexer.l" +#line 43 "../src/tools/ainedit/text_lexer.l" return LBRACKET; YY_BREAK case 5: YY_RULE_SETUP -#line 44 "../src/ainedit/text_lexer.l" +#line 44 "../src/tools/ainedit/text_lexer.l" return RBRACKET; YY_BREAK case 6: YY_RULE_SETUP -#line 45 "../src/ainedit/text_lexer.l" +#line 45 "../src/tools/ainedit/text_lexer.l" return EQUAL; YY_BREAK case 7: YY_RULE_SETUP -#line 46 "../src/ainedit/text_lexer.l" +#line 46 "../src/tools/ainedit/text_lexer.l" text_lval.integer = atoi(text_text); return NUMBER; YY_BREAK case 8: YY_RULE_SETUP -#line 47 "../src/ainedit/text_lexer.l" +#line 47 "../src/tools/ainedit/text_lexer.l" return MESSAGES; YY_BREAK case 9: YY_RULE_SETUP -#line 48 "../src/ainedit/text_lexer.l" +#line 48 "../src/tools/ainedit/text_lexer.l" return STRINGS; YY_BREAK case 10: YY_RULE_SETUP -#line 50 "../src/ainedit/text_lexer.l" +#line 50 "../src/tools/ainedit/text_lexer.l" string_buf_ptr = string_buf; BEGIN(str); YY_BREAK case 11: YY_RULE_SETUP -#line 53 "../src/ainedit/text_lexer.l" +#line 53 "../src/tools/ainedit/text_lexer.l" { BEGIN(INITIAL); *string_buf_ptr = '\0'; - char *sjis = utf2sjis(string_buf, strlen(string_buf)); + char *sjis = encode_text(string_buf); text_lval.string = make_string(sjis, strlen(sjis)); free(sjis); return STRING; @@ -1099,43 +1099,43 @@ YY_RULE_SETUP case 12: /* rule 12 can match eol */ YY_RULE_SETUP -#line 62 "../src/ainedit/text_lexer.l" +#line 62 "../src/tools/ainedit/text_lexer.l" ERROR("Unterminated string literal"); YY_BREAK case 13: YY_RULE_SETUP -#line 64 "../src/ainedit/text_lexer.l" +#line 64 "../src/tools/ainedit/text_lexer.l" *string_buf_ptr++ = '\n'; YY_BREAK case 14: YY_RULE_SETUP -#line 65 "../src/ainedit/text_lexer.l" +#line 65 "../src/tools/ainedit/text_lexer.l" *string_buf_ptr++ = '\t'; YY_BREAK case 15: YY_RULE_SETUP -#line 66 "../src/ainedit/text_lexer.l" +#line 66 "../src/tools/ainedit/text_lexer.l" *string_buf_ptr++ = '\r'; YY_BREAK case 16: YY_RULE_SETUP -#line 67 "../src/ainedit/text_lexer.l" +#line 67 "../src/tools/ainedit/text_lexer.l" *string_buf_ptr++ = '\b'; YY_BREAK case 17: YY_RULE_SETUP -#line 68 "../src/ainedit/text_lexer.l" +#line 68 "../src/tools/ainedit/text_lexer.l" *string_buf_ptr++ = '\f'; YY_BREAK case 18: /* rule 18 can match eol */ YY_RULE_SETUP -#line 70 "../src/ainedit/text_lexer.l" +#line 70 "../src/tools/ainedit/text_lexer.l" *string_buf_ptr++ = text_text[1]; YY_BREAK case 19: YY_RULE_SETUP -#line 72 "../src/ainedit/text_lexer.l" +#line 72 "../src/tools/ainedit/text_lexer.l" { char *yptr = text_text; while (*yptr) @@ -1145,10 +1145,10 @@ YY_RULE_SETUP case 20: YY_RULE_SETUP -#line 79 "../src/ainedit/text_lexer.l" +#line 79 "../src/tools/ainedit/text_lexer.l" ECHO; YY_BREAK -#line 1152 "src/ainedit/48087cf@@ainedit@exe/text_lexer.yy.c" +#line 1152 "src/tools/ainedit/659eb3d@@ainedit@exe/text_lexer.yy.c" case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(str): yyterminate(); @@ -2154,6 +2154,6 @@ void yyfree (void * ptr ) #define YYTABLES_NAME "yytables" -#line 79 "../src/ainedit/text_lexer.l" +#line 79 "../src/tools/ainedit/text_lexer.l" diff --git a/src/tools/ainedit/text_parser.tab.c b/src/tools/ainedit/text_parser.tab.c index 8a6c153..aad1920 100644 --- a/src/tools/ainedit/text_parser.tab.c +++ b/src/tools/ainedit/text_parser.tab.c @@ -97,8 +97,8 @@ /* In a future release of Bison, this section will be replaced by #include "text_parser.tab.h". */ -#ifndef YY_TEXT_SRC_AINEDIT_48087CF_AINEDIT_EXE_TEXT_PARSER_TAB_H_INCLUDED -# define YY_TEXT_SRC_AINEDIT_48087CF_AINEDIT_EXE_TEXT_PARSER_TAB_H_INCLUDED +#ifndef YY_TEXT_SRC_TOOLS_AINEDIT_659EB3D_AINEDIT_EXE_TEXT_PARSER_TAB_H_INCLUDED +# define YY_TEXT_SRC_TOOLS_AINEDIT_659EB3D_AINEDIT_EXE_TEXT_PARSER_TAB_H_INCLUDED /* Debug traces. */ #ifndef TEXT_DEBUG # if defined YYDEBUG @@ -115,7 +115,7 @@ extern int text_debug; #endif /* "%code requires" blocks. */ -#line 11 "../src/ainedit/text_parser.y" /* yacc.c:352 */ +#line 11 "../src/tools/ainedit/text_parser.y" /* yacc.c:352 */ #include "kvec.h" @@ -130,7 +130,7 @@ extern int text_debug; assignment_list *statements; -#line 134 "src/ainedit/48087cf@@ainedit@exe/text_parser.tab.c" /* yacc.c:352 */ +#line 134 "src/tools/ainedit/659eb3d@@ainedit@exe/text_parser.tab.c" /* yacc.c:352 */ /* Token type. */ #ifndef TEXT_TOKENTYPE @@ -153,7 +153,7 @@ extern int text_debug; union TEXT_STYPE { -#line 3 "../src/ainedit/text_parser.y" /* yacc.c:352 */ +#line 3 "../src/tools/ainedit/text_parser.y" /* yacc.c:352 */ int token; int integer; @@ -161,7 +161,7 @@ union TEXT_STYPE struct text_assignment *assign; assignment_list *program; -#line 165 "src/ainedit/48087cf@@ainedit@exe/text_parser.tab.c" /* yacc.c:352 */ +#line 165 "src/tools/ainedit/659eb3d@@ainedit@exe/text_parser.tab.c" /* yacc.c:352 */ }; typedef union TEXT_STYPE TEXT_STYPE; @@ -174,10 +174,10 @@ extern TEXT_STYPE text_lval; int text_parse (void); -#endif /* !YY_TEXT_SRC_AINEDIT_48087CF_AINEDIT_EXE_TEXT_PARSER_TAB_H_INCLUDED */ +#endif /* !YY_TEXT_SRC_TOOLS_AINEDIT_659EB3D_AINEDIT_EXE_TEXT_PARSER_TAB_H_INCLUDED */ /* Second part of user prologue. */ -#line 26 "../src/ainedit/text_parser.y" /* yacc.c:354 */ +#line 26 "../src/tools/ainedit/text_parser.y" /* yacc.c:354 */ #include @@ -209,7 +209,7 @@ static struct text_assignment *make_assignment(int type, int index, struct strin } -#line 213 "src/ainedit/48087cf@@ainedit@exe/text_parser.tab.c" /* yacc.c:354 */ +#line 213 "src/tools/ainedit/659eb3d@@ainedit@exe/text_parser.tab.c" /* yacc.c:354 */ #ifdef short # undef short @@ -1283,43 +1283,43 @@ yyreduce: switch (yyn) { case 2: -#line 69 "../src/ainedit/text_parser.y" /* yacc.c:1652 */ +#line 69 "../src/tools/ainedit/text_parser.y" /* yacc.c:1652 */ { statements = (yyvsp[0].program); } -#line 1289 "src/ainedit/48087cf@@ainedit@exe/text_parser.tab.c" /* yacc.c:1652 */ +#line 1289 "src/tools/ainedit/659eb3d@@ainedit@exe/text_parser.tab.c" /* yacc.c:1652 */ break; case 3: -#line 72 "../src/ainedit/text_parser.y" /* yacc.c:1652 */ +#line 72 "../src/tools/ainedit/text_parser.y" /* yacc.c:1652 */ { (yyval.program) = make_program(); if ((yyvsp[0].assign)) { push_statement((yyval.program), (yyvsp[0].assign)); } } -#line 1295 "src/ainedit/48087cf@@ainedit@exe/text_parser.tab.c" /* yacc.c:1652 */ +#line 1295 "src/tools/ainedit/659eb3d@@ainedit@exe/text_parser.tab.c" /* yacc.c:1652 */ break; case 4: -#line 73 "../src/ainedit/text_parser.y" /* yacc.c:1652 */ +#line 73 "../src/tools/ainedit/text_parser.y" /* yacc.c:1652 */ { if ((yyvsp[0].assign)) { push_statement((yyvsp[-1].program), (yyvsp[0].assign)); } } -#line 1301 "src/ainedit/48087cf@@ainedit@exe/text_parser.tab.c" /* yacc.c:1652 */ +#line 1301 "src/tools/ainedit/659eb3d@@ainedit@exe/text_parser.tab.c" /* yacc.c:1652 */ break; case 5: -#line 76 "../src/ainedit/text_parser.y" /* yacc.c:1652 */ +#line 76 "../src/tools/ainedit/text_parser.y" /* yacc.c:1652 */ { (yyval.assign) = NULL; } -#line 1307 "src/ainedit/48087cf@@ainedit@exe/text_parser.tab.c" /* yacc.c:1652 */ +#line 1307 "src/tools/ainedit/659eb3d@@ainedit@exe/text_parser.tab.c" /* yacc.c:1652 */ break; case 6: -#line 77 "../src/ainedit/text_parser.y" /* yacc.c:1652 */ +#line 77 "../src/tools/ainedit/text_parser.y" /* yacc.c:1652 */ { (yyval.assign) = make_assignment(MESSAGES, (yyvsp[-4].integer), (yyvsp[-1].string)); } -#line 1313 "src/ainedit/48087cf@@ainedit@exe/text_parser.tab.c" /* yacc.c:1652 */ +#line 1313 "src/tools/ainedit/659eb3d@@ainedit@exe/text_parser.tab.c" /* yacc.c:1652 */ break; case 7: -#line 78 "../src/ainedit/text_parser.y" /* yacc.c:1652 */ +#line 78 "../src/tools/ainedit/text_parser.y" /* yacc.c:1652 */ { (yyval.assign) = make_assignment(STRINGS, (yyvsp[-4].integer), (yyvsp[-1].string)); } -#line 1319 "src/ainedit/48087cf@@ainedit@exe/text_parser.tab.c" /* yacc.c:1652 */ +#line 1319 "src/tools/ainedit/659eb3d@@ainedit@exe/text_parser.tab.c" /* yacc.c:1652 */ break; -#line 1323 "src/ainedit/48087cf@@ainedit@exe/text_parser.tab.c" /* yacc.c:1652 */ +#line 1323 "src/tools/ainedit/659eb3d@@ainedit@exe/text_parser.tab.c" /* yacc.c:1652 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -1550,5 +1550,5 @@ yyreturn: #endif return yyresult; } -#line 81 "../src/ainedit/text_parser.y" /* yacc.c:1918 */ +#line 81 "../src/tools/ainedit/text_parser.y" /* yacc.c:1918 */ diff --git a/src/tools/ainedit/text_parser.tab.h b/src/tools/ainedit/text_parser.tab.h index da8b102..92b71c8 100644 --- a/src/tools/ainedit/text_parser.tab.h +++ b/src/tools/ainedit/text_parser.tab.h @@ -34,8 +34,8 @@ /* Undocumented macros, especially those whose name start with YY_, are private implementation details. Do not rely on them. */ -#ifndef YY_TEXT_SRC_AINEDIT_48087CF_AINEDIT_EXE_TEXT_PARSER_TAB_H_INCLUDED -# define YY_TEXT_SRC_AINEDIT_48087CF_AINEDIT_EXE_TEXT_PARSER_TAB_H_INCLUDED +#ifndef YY_TEXT_SRC_TOOLS_AINEDIT_659EB3D_AINEDIT_EXE_TEXT_PARSER_TAB_H_INCLUDED +# define YY_TEXT_SRC_TOOLS_AINEDIT_659EB3D_AINEDIT_EXE_TEXT_PARSER_TAB_H_INCLUDED /* Debug traces. */ #ifndef TEXT_DEBUG # if defined YYDEBUG @@ -52,7 +52,7 @@ extern int text_debug; #endif /* "%code requires" blocks. */ -#line 11 "../src/ainedit/text_parser.y" /* yacc.c:1921 */ +#line 11 "../src/tools/ainedit/text_parser.y" /* yacc.c:1921 */ #include "kvec.h" @@ -67,7 +67,7 @@ extern int text_debug; assignment_list *statements; -#line 71 "src/ainedit/48087cf@@ainedit@exe/text_parser.tab.h" /* yacc.c:1921 */ +#line 71 "src/tools/ainedit/659eb3d@@ainedit@exe/text_parser.tab.h" /* yacc.c:1921 */ /* Token type. */ #ifndef TEXT_TOKENTYPE @@ -90,7 +90,7 @@ extern int text_debug; union TEXT_STYPE { -#line 3 "../src/ainedit/text_parser.y" /* yacc.c:1921 */ +#line 3 "../src/tools/ainedit/text_parser.y" /* yacc.c:1921 */ int token; int integer; @@ -98,7 +98,7 @@ union TEXT_STYPE struct text_assignment *assign; assignment_list *program; -#line 102 "src/ainedit/48087cf@@ainedit@exe/text_parser.tab.h" /* yacc.c:1921 */ +#line 102 "src/tools/ainedit/659eb3d@@ainedit@exe/text_parser.tab.h" /* yacc.c:1921 */ }; typedef union TEXT_STYPE TEXT_STYPE; @@ -111,4 +111,4 @@ extern TEXT_STYPE text_lval; int text_parse (void); -#endif /* !YY_TEXT_SRC_AINEDIT_48087CF_AINEDIT_EXE_TEXT_PARSER_TAB_H_INCLUDED */ +#endif /* !YY_TEXT_SRC_TOOLS_AINEDIT_659EB3D_AINEDIT_EXE_TEXT_PARSER_TAB_H_INCLUDED */ diff --git a/src/tools/conv.c b/src/tools/conv.c new file mode 100644 index 0000000..8babdd0 --- /dev/null +++ b/src/tools/conv.c @@ -0,0 +1,49 @@ +/* Copyright (C) 2019 Nunuhara Cabbage + * + * 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, see . + */ + +#include +#include +#include +#include +#include "system4.h" + +char *convert_text(iconv_t cd, const char *str) +{ + size_t inbytesleft = strlen(str); + char *inbuf = (char*)str; + + size_t outbuf_size = inbytesleft; + size_t outbytesleft = outbuf_size; + char *outbuf = xmalloc(outbuf_size+1); + char *outptr = outbuf; + + while (inbytesleft) { + if (iconv(cd, &inbuf, &inbytesleft, &outptr, &outbytesleft) == (size_t)-1 && errno != E2BIG) { + ERROR("iconv: %s", strerror(errno)); + } + // reallocate outbuf + size_t out_index = outbuf_size - outbytesleft; + outbytesleft += outbuf_size; + outbuf_size *= 2; + outbuf = xrealloc(outbuf, outbuf_size+1); + outptr = outbuf + out_index; + } + *outptr = '\0'; + + return outbuf; +} + + diff --git a/src/tools/ex/dump.c b/src/tools/ex/dump.c index 437b58d..0b820f3 100644 --- a/src/tools/ex/dump.c +++ b/src/tools/ex/dump.c @@ -27,7 +27,9 @@ #include "system4.h" #include "system4/ex.h" #include "system4/string.h" -#include "system4/utfsjis.h" + +char *encode_text(const char *str); +char *encode_text_utf8(const char *str); int indent_level = 0; @@ -54,7 +56,7 @@ static const char *ex_strtype(enum ex_value_type type) static char *_escape_string(const char *str, const char *escape_chars, const char *replace_chars) { int escapes = 0; - char *u = sjis2utf(str, strlen(str)); + char *u = encode_text(str); // count number of required escapes for (int i = 0; u[i]; i++) { @@ -115,40 +117,26 @@ static void ex_dump_identifier(FILE *out, struct string *s) fprintf(out, "\"\""); return; } + + char *u = encode_text_utf8(s->text); + // identifier beginning with a digit if (s->text[0] >= '0' && s->text[0] <= '9') { + free(u); ex_dump_string(out, s); return; } - // identifier containing special character - for (int i = 0; i < s->size; i++) { - switch (s->text[i]) { - case ' ': - case '\t': - case '\r': - case '\n': - case '\\': - case '(': - case ')': - case '[': - case ']': - case '{': - case '}': - case '=': - case ',': - case '.': - case ';': - case '"': - case '-': - ex_dump_string(out, s); - return; - } - if (SJIS_2BYTE(s->text[i])) - i++; + + size_t i = strcspn(u, " \t\r\n\\()[]{}=,.;\"-"); + if (u[i]) { + free(u); + ex_dump_string(out, s); + return; } - // safe identifier: print unquoted - char *u = sjis2utf(s->text, s->size); + // FIXME: don't reencode if output format is UTF-8 (the default) + free(u); + u = encode_text(s->text); fprintf(out, "%s", u); free(u); } @@ -321,7 +309,7 @@ void ex_dump_split(FILE *manifest, struct ex *ex, const char *dir) { for (uint32_t i = 0; i < ex->nr_blocks; i++) { char buf[PATH_MAX]; - char *name = sjis2utf(ex->blocks[i].name->text, ex->blocks[i].name->size); + char *name = encode_text(ex->blocks[i].name->text); snprintf(buf, PATH_MAX, "%s/%u_%s.x", dir, i, name); FILE *out = file_open_utf8(buf, "w"); diff --git a/src/tools/ex/ex_lexer.l b/src/tools/ex/ex_lexer.l index e8ba4f2..d195086 100644 --- a/src/tools/ex/ex_lexer.l +++ b/src/tools/ex/ex_lexer.l @@ -25,14 +25,15 @@ #include "ex_parser.tab.h" #include "system4.h" #include "system4/string.h" -#include "system4/utfsjis.h" + +char *encode_text(const char *str); char string_buf[65536]; char *string_buf_ptr; struct string *make_string_from_utf8(const char *str, size_t len) { - char *sjis = utf2sjis(str, len); + char *sjis = encode_text(str); struct string *s = make_string(sjis, strlen(sjis)); free(sjis); return s; @@ -82,7 +83,7 @@ tree return TREE; \" { BEGIN(INITIAL); *string_buf_ptr = '\0'; - char *sjis = utf2sjis(string_buf, strlen(string_buf)); + char *sjis = encode_text(string_buf); yex_lval.s = make_string(sjis, strlen(sjis)); free(sjis); return CONST_STRING; diff --git a/src/tools/ex/ex_lexer.yy.c b/src/tools/ex/ex_lexer.yy.c index 134186d..0979eec 100644 --- a/src/tools/ex/ex_lexer.yy.c +++ b/src/tools/ex/ex_lexer.yy.c @@ -787,14 +787,15 @@ char *yytext; #include "ex_parser.tab.h" #include "system4.h" #include "system4/string.h" -#include "system4/utfsjis.h" + +char *encode_text(const char *str); char string_buf[65536]; char *string_buf_ptr; struct string *make_string_from_utf8(const char *str, size_t len) { - char *sjis = utf2sjis(str, len); + char *sjis = encode_text(str); struct string *s = make_string(sjis, strlen(sjis)); free(sjis); return s; @@ -802,9 +803,9 @@ struct string *make_string_from_utf8(const char *str, size_t len) unsigned long yex_line = 1; -#line 806 "src/tools/ex/cf5f17f@@exbuild@exe/ex_lexer.yy.c" +#line 807 "src/tools/ex/cf5f17f@@exbuild@exe/ex_lexer.yy.c" -#line 808 "src/tools/ex/cf5f17f@@exbuild@exe/ex_lexer.yy.c" +#line 809 "src/tools/ex/cf5f17f@@exbuild@exe/ex_lexer.yy.c" #define INITIAL 0 #define str 1 @@ -1023,10 +1024,10 @@ YY_DECL } { -#line 54 "../src/tools/ex/ex_lexer.l" +#line 55 "../src/tools/ex/ex_lexer.l" -#line 1030 "src/tools/ex/cf5f17f@@exbuild@exe/ex_lexer.yy.c" +#line 1031 "src/tools/ex/cf5f17f@@exbuild@exe/ex_lexer.yy.c" while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { @@ -1085,129 +1086,129 @@ do_action: /* This label is used only to access EOF actions. */ case 1: YY_RULE_SETUP -#line 56 "../src/tools/ex/ex_lexer.l" +#line 57 "../src/tools/ex/ex_lexer.l" ; YY_BREAK case 2: /* rule 2 can match eol */ YY_RULE_SETUP -#line 57 "../src/tools/ex/ex_lexer.l" +#line 58 "../src/tools/ex/ex_lexer.l" yex_line++; YY_BREAK case 3: /* rule 3 can match eol */ YY_RULE_SETUP -#line 58 "../src/tools/ex/ex_lexer.l" +#line 59 "../src/tools/ex/ex_lexer.l" yex_line++; YY_BREAK case 4: YY_RULE_SETUP -#line 59 "../src/tools/ex/ex_lexer.l" +#line 60 "../src/tools/ex/ex_lexer.l" return '('; YY_BREAK case 5: YY_RULE_SETUP -#line 60 "../src/tools/ex/ex_lexer.l" +#line 61 "../src/tools/ex/ex_lexer.l" return ')'; YY_BREAK case 6: YY_RULE_SETUP -#line 61 "../src/tools/ex/ex_lexer.l" +#line 62 "../src/tools/ex/ex_lexer.l" return '{'; YY_BREAK case 7: YY_RULE_SETUP -#line 62 "../src/tools/ex/ex_lexer.l" +#line 63 "../src/tools/ex/ex_lexer.l" return '}'; YY_BREAK case 8: YY_RULE_SETUP -#line 63 "../src/tools/ex/ex_lexer.l" +#line 64 "../src/tools/ex/ex_lexer.l" return '['; YY_BREAK case 9: YY_RULE_SETUP -#line 64 "../src/tools/ex/ex_lexer.l" +#line 65 "../src/tools/ex/ex_lexer.l" return ']'; YY_BREAK case 10: YY_RULE_SETUP -#line 65 "../src/tools/ex/ex_lexer.l" +#line 66 "../src/tools/ex/ex_lexer.l" return '='; YY_BREAK case 11: YY_RULE_SETUP -#line 66 "../src/tools/ex/ex_lexer.l" +#line 67 "../src/tools/ex/ex_lexer.l" return ','; YY_BREAK case 12: YY_RULE_SETUP -#line 67 "../src/tools/ex/ex_lexer.l" +#line 68 "../src/tools/ex/ex_lexer.l" return ';'; YY_BREAK case 13: YY_RULE_SETUP -#line 68 "../src/tools/ex/ex_lexer.l" +#line 69 "../src/tools/ex/ex_lexer.l" return '-'; YY_BREAK case 14: YY_RULE_SETUP -#line 69 "../src/tools/ex/ex_lexer.l" +#line 70 "../src/tools/ex/ex_lexer.l" return INT; YY_BREAK case 15: YY_RULE_SETUP -#line 70 "../src/tools/ex/ex_lexer.l" +#line 71 "../src/tools/ex/ex_lexer.l" return FLOAT; YY_BREAK case 16: YY_RULE_SETUP -#line 71 "../src/tools/ex/ex_lexer.l" +#line 72 "../src/tools/ex/ex_lexer.l" return STRING; YY_BREAK case 17: YY_RULE_SETUP -#line 72 "../src/tools/ex/ex_lexer.l" +#line 73 "../src/tools/ex/ex_lexer.l" return TABLE; YY_BREAK case 18: YY_RULE_SETUP -#line 73 "../src/tools/ex/ex_lexer.l" +#line 74 "../src/tools/ex/ex_lexer.l" return LIST; YY_BREAK case 19: YY_RULE_SETUP -#line 74 "../src/tools/ex/ex_lexer.l" +#line 75 "../src/tools/ex/ex_lexer.l" return TREE; YY_BREAK case 20: YY_RULE_SETUP -#line 75 "../src/tools/ex/ex_lexer.l" +#line 76 "../src/tools/ex/ex_lexer.l" yex_lval.s = make_string_from_utf8(yex_text, yex_leng); return CONST_STRING; YY_BREAK case 21: YY_RULE_SETUP -#line 76 "../src/tools/ex/ex_lexer.l" +#line 77 "../src/tools/ex/ex_lexer.l" yex_lval.f = strtof(yex_text, NULL); return CONST_FLOAT; YY_BREAK case 22: YY_RULE_SETUP -#line 77 "../src/tools/ex/ex_lexer.l" +#line 78 "../src/tools/ex/ex_lexer.l" yex_lval.i = atoi(yex_text); return CONST_INT; YY_BREAK case 23: YY_RULE_SETUP -#line 79 "../src/tools/ex/ex_lexer.l" +#line 80 "../src/tools/ex/ex_lexer.l" string_buf_ptr = string_buf; BEGIN(str); YY_BREAK case 24: YY_RULE_SETUP -#line 82 "../src/tools/ex/ex_lexer.l" +#line 83 "../src/tools/ex/ex_lexer.l" { BEGIN(INITIAL); *string_buf_ptr = '\0'; - char *sjis = utf2sjis(string_buf, strlen(string_buf)); + char *sjis = encode_text(string_buf); yex_lval.s = make_string(sjis, strlen(sjis)); free(sjis); return CONST_STRING; @@ -1216,43 +1217,43 @@ YY_RULE_SETUP case 25: /* rule 25 can match eol */ YY_RULE_SETUP -#line 91 "../src/tools/ex/ex_lexer.l" +#line 92 "../src/tools/ex/ex_lexer.l" ERROR("Unterminated string literal"); YY_BREAK case 26: YY_RULE_SETUP -#line 93 "../src/tools/ex/ex_lexer.l" +#line 94 "../src/tools/ex/ex_lexer.l" *string_buf_ptr++ = '\n'; YY_BREAK case 27: YY_RULE_SETUP -#line 94 "../src/tools/ex/ex_lexer.l" +#line 95 "../src/tools/ex/ex_lexer.l" *string_buf_ptr++ = '\t'; YY_BREAK case 28: YY_RULE_SETUP -#line 95 "../src/tools/ex/ex_lexer.l" +#line 96 "../src/tools/ex/ex_lexer.l" *string_buf_ptr++ = '\r'; YY_BREAK case 29: YY_RULE_SETUP -#line 96 "../src/tools/ex/ex_lexer.l" +#line 97 "../src/tools/ex/ex_lexer.l" *string_buf_ptr++ = '\b'; YY_BREAK case 30: YY_RULE_SETUP -#line 97 "../src/tools/ex/ex_lexer.l" +#line 98 "../src/tools/ex/ex_lexer.l" *string_buf_ptr++ = '\f'; YY_BREAK case 31: /* rule 31 can match eol */ YY_RULE_SETUP -#line 99 "../src/tools/ex/ex_lexer.l" +#line 100 "../src/tools/ex/ex_lexer.l" *string_buf_ptr++ = yex_text[1]; YY_BREAK case 32: YY_RULE_SETUP -#line 101 "../src/tools/ex/ex_lexer.l" +#line 102 "../src/tools/ex/ex_lexer.l" { char *yptr = yex_text; while (*yptr) @@ -1262,20 +1263,19 @@ YY_RULE_SETUP case 33: YY_RULE_SETUP -#line 108 "../src/tools/ex/ex_lexer.l" +#line 109 "../src/tools/ex/ex_lexer.l" BEGIN(incl); YY_BREAK case 34: YY_RULE_SETUP -#line 111 "../src/tools/ex/ex_lexer.l" +#line 112 "../src/tools/ex/ex_lexer.l" ; YY_BREAK case 35: YY_RULE_SETUP -#line 112 "../src/tools/ex/ex_lexer.l" +#line 113 "../src/tools/ex/ex_lexer.l" { - NOTICE("INCLUDING %s", yex_text); yex_text[yex_leng-1] = '\0'; yex_in = fopen(yex_text+1, "r"); if (!yex_in) @@ -1290,7 +1290,6 @@ case YY_STATE_EOF(str): case YY_STATE_EOF(incl): #line 123 "../src/tools/ex/ex_lexer.l" { - NOTICE("GOT EOF"); yex_pop_buffer_state(); if (!YY_CURRENT_BUFFER) { yyterminate(); @@ -1299,10 +1298,10 @@ case YY_STATE_EOF(incl): YY_BREAK case 36: YY_RULE_SETUP -#line 131 "../src/tools/ex/ex_lexer.l" +#line 130 "../src/tools/ex/ex_lexer.l" ECHO; YY_BREAK -#line 1306 "src/tools/ex/cf5f17f@@exbuild@exe/ex_lexer.yy.c" +#line 1305 "src/tools/ex/cf5f17f@@exbuild@exe/ex_lexer.yy.c" case YY_END_OF_BUFFER: { @@ -2305,6 +2304,6 @@ void yyfree (void * ptr ) #define YYTABLES_NAME "yytables" -#line 131 "../src/tools/ex/ex_lexer.l" +#line 130 "../src/tools/ex/ex_lexer.l" diff --git a/src/tools/ex/exbuild.c b/src/tools/ex/exbuild.c index 2057bdf..2d5eb79 100644 --- a/src/tools/ex/exbuild.c +++ b/src/tools/ex/exbuild.c @@ -19,40 +19,57 @@ #include #include #include +#include #include "system4.h" #include "system4/ex.h" #include "system4/string.h" -#include "system4/utfsjis.h" #include "ast.h" void ex_write(FILE *out, struct ex *ex); extern bool columns_first; +iconv_t output_conv; + +char *convert_text(iconv_t cd, const char *str); + +char *encode_text(const char *str) +{ + return convert_text(output_conv, str); +} + static void usage(void) { puts("Usage: exbuild [options...] input-file"); puts(" Build EX files."); puts(""); - puts(" -h, --help Display this message and exit"); - puts(" -o, --output Set the output file path"); - puts(" --old Use this for pre-Evenicle .ex files"); + puts(" -h, --help Display this message and exit"); + puts(" -o, --output Set the output file path"); + puts(" --old Use this for pre-Evenicle .ex files"); + puts(" --input-encoding Specify the encoding of the input file (default: UTF-8)"); + puts(" --output-encoding Specify the encoding of the output file (default: SJIS-WIN)"); } enum { LOPT_HELP = 256, LOPT_OUTPUT, LOPT_OLD, + LOPT_INPUT_ENCODING, + LOPT_OUTPUT_ENCODING, }; int main(int argc, char *argv[]) { const char *output_file = NULL; + const char *input_encoding = "UTF-8"; + const char *output_encoding = "SJIS-WIN"; while (1) { static struct option long_options[] = { - { "help", no_argument, 0, LOPT_HELP }, - { "output", required_argument, 0, LOPT_OUTPUT }, - { "old", no_argument, 0, LOPT_OLD }, + { "help", no_argument, 0, LOPT_HELP }, + { "output", required_argument, 0, LOPT_OUTPUT }, + { "old", no_argument, 0, LOPT_OLD }, + { "input-encoding", required_argument, 0, LOPT_INPUT_ENCODING }, + { "output-encoding", required_argument, 0, LOPT_OUTPUT_ENCODING }, }; int option_index = 0; int c; @@ -73,6 +90,12 @@ int main(int argc, char *argv[]) case LOPT_OLD: columns_first = true; break; + case LOPT_INPUT_ENCODING: + input_encoding = optarg; + break; + case LOPT_OUTPUT_ENCODING: + output_encoding = optarg; + break; case '?': ERROR("Unknown command line argument"); } @@ -100,6 +123,10 @@ int main(int argc, char *argv[]) if (!in) ERROR("fopen failed: %s", strerror(errno)); + if ((output_conv = iconv_open(output_encoding, input_encoding)) == (iconv_t)-1) { + ERROR("iconv_open: %s", strerror(errno)); + } + struct ex *ex = ex_parse(in); ex_write(out, ex); ex_free(ex); diff --git a/src/tools/ex/exdump.c b/src/tools/ex/exdump.c index 4b6cadf..44b2315 100644 --- a/src/tools/ex/exdump.c +++ b/src/tools/ex/exdump.c @@ -22,24 +22,41 @@ #include #include #include +#include #include "little_endian.h" #include "system4.h" #include "system4/ex.h" #include "system4/string.h" -#include "system4/utfsjis.h" int ex_dump(FILE *out, struct ex *ex); int ex_dump_split(FILE *out, struct ex *ex, const char *dir); +iconv_t output_conv; +iconv_t utf8_conv; + +char *convert_text(iconv_t cd, const char *str); + +char *encode_text(const char *str) +{ + return convert_text(output_conv, str); +} + +char *encode_text_utf8(const char *str) +{ + return convert_text(utf8_conv, str); +} + static void usage(void) { puts("Usage: exdump [options...] input-file"); puts(" Dump EX files."); puts(""); - puts(" -h, --help Display this message and exit"); - puts(" -d, --decrypt Decrypt the EX file only"); - puts(" -o, --output Set the output file path"); - puts(" -s, --split Split output into multiple files"); + puts(" -h, --help Display this message and exit"); + puts(" -d, --decrypt Decrypt the EX file only"); + puts(" -o, --output Set the output file path"); + puts(" -s, --split Split output into multiple files"); + puts(" --input-encoding Specify the encoding of the EX file (default: SJIS-WIN)"); + puts(" --output-encoding Specify the encoding of the output file (default UTF-8)"); } enum { @@ -47,6 +64,8 @@ enum { LOPT_DECRYPT, LOPT_OUTPUT, LOPT_SPLIT, + LOPT_INPUT_ENCODING, + LOPT_OUTPUT_ENCODING, }; int main(int argc, char *argv[]) @@ -54,6 +73,8 @@ int main(int argc, char *argv[]) bool decrypt = false; bool split = false; char *output_file = NULL; + char *input_encoding = "SJIS-WIN"; + char *output_encoding = "UTF-8"; while (1) { static struct option long_options[] = { @@ -61,6 +82,8 @@ int main(int argc, char *argv[]) { "decrypt", no_argument, 0, LOPT_DECRYPT }, { "output", required_argument, 0, LOPT_OUTPUT }, { "split", no_argument, 0, LOPT_SPLIT }, + { "input-encoding", required_argument, 0, LOPT_INPUT_ENCODING }, + { "output-encoding", required_argument, 0, LOPT_OUTPUT_ENCODING }, }; int option_index = 0; int c; @@ -86,6 +109,12 @@ int main(int argc, char *argv[]) case LOPT_SPLIT: split = true; break; + case LOPT_INPUT_ENCODING: + input_encoding = optarg; + break; + case LOPT_OUTPUT_ENCODING: + output_encoding = optarg; + break; case '?': ERROR("Unknown command line argument"); } @@ -105,6 +134,13 @@ int main(int argc, char *argv[]) if (!out) ERROR("fopen failed: %s", strerror(errno)); + if ((output_conv = iconv_open(output_encoding, input_encoding)) == (iconv_t)-1) { + ERROR("iconv_open: %s", strerror(errno)); + } + if ((utf8_conv = iconv_open("UTF-8", input_encoding)) == (iconv_t)-1) { + ERROR("iconv_open: %s", strerror(errno)); + } + if (decrypt) { size_t size; uint8_t *buf = ex_decrypt(argv[0], &size, NULL); diff --git a/src/tools/ex/meson.build b/src/tools/ex/meson.build index 46558fb..e1e6e64 100644 --- a/src/tools/ex/meson.build +++ b/src/tools/ex/meson.build @@ -1,12 +1,13 @@ -exdump = ['dump.c', +exdump = ['../conv.c', + 'dump.c', 'exdump.c', ] lfiles = flexgen.process('ex_lexer.l') pfiles = bisongen.process('ex_parser.y') -exbuild = ['ast.c', - 'dump.c', +exbuild = ['../conv.c', + 'ast.c', 'exbuild.c', 'pack.c', ]