From 2646bda3a5584b283190f22f32cf7ff669c925e8 Mon Sep 17 00:00:00 2001 From: Choe Hwanjin Date: Sun, 12 Dec 2010 19:08:30 +0900 Subject: [PATCH] =?utf8?q?=ED=95=9C=EA=B8=80=20=EC=9E=90=ED=8C=90=EC=9D=84?= =?utf8?q?=20=EC=98=81=EB=AC=B8=20=EC=83=81=ED=83=9C=EB=A1=9C=20=EC=B9=9C?= =?utf8?q?=20=EC=8A=A4=ED=8A=B8=EB=A7=81=EC=9D=84=20=ED=95=9C=EA=B8=80?= =?utf8?q?=EB=A1=9C=20=EB=B3=80=ED=99=98=ED=95=B4=EC=A3=BC=EB=8A=94=20?= =?utf8?q?=ED=94=84=EB=A1=9C=EA=B7=B8=EB=9E=A8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 예를 들어 hangul -i dkssudgktpdy 를 실행하면 "안녕하세요"를 출력, echo dkssudgktpdy | hangul 을 실행하면 "안녕하세요"를 출력한다. git-svn-id: http://kldp.net/svn/hangul/libhangul/trunk@228 8f00fcd2-89fc-0310-932e-b01be5b65e01 --- tools/Makefile.am | 8 +- tools/hangul.c | 343 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 347 insertions(+), 4 deletions(-) create mode 100644 tools/hangul.c diff --git a/tools/Makefile.am b/tools/Makefile.am index fd0bc9b..29e4fe9 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -1,6 +1,6 @@ -bin_PROGRAMS = hanjac +bin_PROGRAMS = hangul -hanjac_CFLAGS = -hanjac_SOURCES = hanjac.c -hanjac_LDADD = ../hangul/libhangul.la +hangul_CFLAGS = -I../hangul +hangul_SOURCES = hangul.c +hangul_LDADD = ../hangul/libhangul.la diff --git a/tools/hangul.c b/tools/hangul.c new file mode 100644 index 0000000..a12e882 --- /dev/null +++ b/tools/hangul.c @@ -0,0 +1,343 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#define _(x) (x) + +#ifdef WORDS_BIGENDIAN +#define UCS4 "UCS-4BE" +#else +#define UCS4 "UCS-4LE" +#endif + +static const char* program_name = "hangul"; +static iconv_t cd_ucs4_to_utf8 = (iconv_t)-1; + +static void +print_error(int status, int errnum, const char* format, ...) +{ + va_list ap; + + printf("%s: %s: ", program_name, strerror(errnum)); + + va_start(ap, format); + vprintf(format, ap); + va_end(ap); + + fputc('\n', stdout); +} + +static void +usage(int status) +{ + if (status == EXIT_SUCCESS) { + printf(_("\ +Usage: %s [OPTION]... [FILE]...\n\ +"), program_name); + + fputs(_("\ +Convert string into korean characters according to korean keyboard layout.\n\ +\n\ +Mandatory arguments to long options are mandatory for short options too.\n\ + -k, --keyboard=KEYBOARDID select keyboard layout by KEYBOARDID\n\ + -l, --list list available keyboard and exit\n\ + -i, --input=STRING use STRING as input instead of standard input\n\ + -o, --output=FILE write result to FILE instead of standard output\n\ +"), stdout); + + fputs(_("\ + --help display this help and exit\n\ + --version output version information and exit\n\ +"), stdout); + + fputs(_("\ +\n\ +With no FILE, or when FILE is -, read standard input.\n\ +"), stdout); + + printf(_("\ +\n\ +Examples:\n\ + %s -i gksrmfdlqfur Convert specified string into korean characters.\n\ + %s Convert standard input into korean characters\n\ + and print them to standard output.\n\ +"), + program_name, program_name); + } else { + fprintf(stderr, _("Try `%s --help' for more information.\n"), + program_name); + } + + exit(status); +} + +static void +version() +{ + printf("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION); + exit(EXIT_SUCCESS); +} + +static void +list_keyboards() +{ + unsigned i; + unsigned n; + + n = hangul_ic_get_n_keyboards(); + for (i = 0; i < n; ++i) { + const char* id; + const char* name; + + id = hangul_ic_get_keyboard_id(i); + name = hangul_ic_get_keyboard_name(i); + + printf("%-12s %s\n", id, name); + } + + exit(EXIT_SUCCESS); +} + +size_t ucschar_strlen(const ucschar* str) +{ + const ucschar* p = str; + while (p[0] != 0) { + p++; + } + + return p - str; +} + +static int +fputs_ucschar(const ucschar* str, FILE* stream) +{ + char buf[512]; + char* inbuf; + char* outbuf; + size_t inbytesleft; + size_t outbytesleft; + size_t len; + size_t res; + + len = ucschar_strlen(str); + + inbuf = (char*)str; + outbuf = buf; + inbytesleft = len * 4; + outbytesleft = sizeof(buf) - 1; + + res = iconv(cd_ucs4_to_utf8, &inbuf, &inbytesleft, &outbuf, &outbytesleft); + if (res == -1) { + if (errno == E2BIG) { + } else if (errno == EILSEQ) { + } else if (errno == EINVAL) { + } + } + + *outbuf = '\0'; + + return fputs(buf, stream); +} + +static void +hangul_process_with_string(HangulInputContext* ic, const char* input, FILE* output) +{ + int r; + const ucschar* str; + + while (*input != '\0') { + bool is_processed = hangul_ic_process(ic, *input); + str = hangul_ic_get_commit_string(ic); + if (str[0] != 0) { + r = fputs_ucschar(str, output); + if (r == EOF) + goto on_error; + } + if (!is_processed) { + r = fputc(*input, output); + if (r == EOF) + goto on_error; + } + + input++; + } + + str = hangul_ic_flush(ic); + if (str[0] != 0) { + r = fputs_ucschar(str, output); + if (r == EOF) + goto on_error; + } + + r = fputs("\n", output); + if (r == EOF) + goto on_error; + + return; + +on_error: + print_error(0, errno, _("standard output")); + exit(EXIT_FAILURE); +} + +static void +hangul_process(HangulInputContext* ic, FILE* input, FILE* output) +{ + int r; + int c; + const ucschar* str; + + c = fgetc(input); + while (c != EOF) { + bool res = hangul_ic_process(ic, c); + str = hangul_ic_get_commit_string(ic); + if (str[0] != 0) { + r = fputs_ucschar(str, output); + if (r == EOF) + goto on_error; + } + if (!res) { + r = fputc(c, output); + if (r == EOF) + goto on_error; + } + + c = fgetc(input); + } + + str = hangul_ic_flush(ic); + if (str[0] != 0) { + r = fputs_ucschar(str, output); + if (r == EOF) + goto on_error; + } + + return; + +on_error: + print_error(0, errno, _("standard output")); + exit(EXIT_FAILURE); +} + +int +main(int argc, char *argv[]) +{ + int i; + int res; + const char* input_string; + const char* output_file; + const char* keyboard; + FILE* output; + HangulInputContext* ic; + + setlocale(LC_ALL, ""); + + res = EXIT_SUCCESS; + keyboard = "2"; + input_string = NULL; + output_file = "-"; + while (1) { + int c; + static struct option const long_options[] = { + { "keyboard", required_argument, NULL, 'k' }, + { "list", no_argument, NULL, 'l' }, + { "input", required_argument, NULL, 'i' }, + { "output", required_argument, NULL, 'o' }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'v' }, + { NULL, 0, NULL, 0 } + }; + + c = getopt_long(argc, argv, "k:li:o:", long_options, NULL); + if (c == -1) + break; + + switch (c) { + case 'k': + keyboard = optarg; + break; + case 'l': + list_keyboards(); + break; + case 'i': + input_string = optarg; + break; + case 'o': + output_file = optarg; + break; + case 'h': + usage(EXIT_SUCCESS); + break; + case 'v': + version(); + break; + default: + usage(EXIT_FAILURE); + } + } + + if (strcmp(output_file, "-") == 0) { + output = stdout; + } else { + output = fopen(output_file, "w"); + if (output == NULL) { + print_error(EXIT_FAILURE, errno, "%s", output_file); + exit(EXIT_FAILURE); + } + } + + cd_ucs4_to_utf8 = iconv_open("UTF-8", UCS4); + if (cd_ucs4_to_utf8 == (iconv_t)-1) { + print_error(EXIT_FAILURE, errno, _("conversion from %s to UTF-8"), UCS4); + exit(EXIT_FAILURE); + } + + ic = hangul_ic_new(keyboard); + + if (input_string != NULL) { + hangul_process_with_string(ic, input_string, output); + } + + if (optind < argc) { + for (i = optind; i < argc; i++) { + FILE* input = NULL; + if (strcmp(argv[i], "-") == 0) { + input = stdin; + hangul_process(ic, input, output); + } else { + input = fopen(argv[i], "r"); + if (input == NULL) { + print_error(0, errno, "%s", argv[i]); + } else { + hangul_process(ic, input, output); + fclose(input); + } + } + } + } else if (input_string == NULL) { + hangul_process(ic, stdin, output); + } + + hangul_ic_delete(ic); + + iconv_close(cd_ucs4_to_utf8); + + if (strcmp(output_file, "-") != 0) { + fclose(output); + } + + return res; +} -- 2.7.4