summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChoe Hwanjin <choe.hwanjin@gmail.com>2010-12-12 19:08:30 +0900
committerChoe Hwanjin <choe.hwanjin@gmail.com>2010-12-12 19:08:30 +0900
commit2646bda3a5584b283190f22f32cf7ff669c925e8 (patch)
treeb91458304151838ad583a2af5bfe9e5ede8b5a76
parente87ec32568f7d9194bb8ce00abf9e820a08a07c0 (diff)
downloadlibhangul-2646bda3a5584b283190f22f32cf7ff669c925e8.tar.gz
한글 자판을 영문 상태로 친 스트링을 한글로 변환해주는 프로그램 구현
예를 들어 hangul -i dkssudgktpdy 를 실행하면 "안녕하세요"를 출력, echo dkssudgktpdy | hangul 을 실행하면 "안녕하세요"를 출력한다. git-svn-id: http://kldp.net/svn/hangul/libhangul/trunk@228 8f00fcd2-89fc-0310-932e-b01be5b65e01
-rw-r--r--tools/Makefile.am8
-rw-r--r--tools/hangul.c343
2 files changed, 347 insertions, 4 deletions
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 <config.h>
+#endif
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <locale.h>
+#include <getopt.h>
+#include <errno.h>
+
+#include <iconv.h>
+
+#include <hangul.h>
+
+#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;
+}